* i387-tdep.c (print_i387_value): Add extra space after final full
[deliverable/binutils-gdb.git] / gdb / i387-tdep.c
1 /* Intel 387 floating point stuff.
2 Copyright 1988, 1989, 1991, 1992, 1993, 1994, 1998, 1999, 2000, 2001
3 Free Software Foundation, Inc.
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
21
22 #include "defs.h"
23 #include "frame.h"
24 #include "inferior.h"
25 #include "language.h"
26 #include "value.h"
27 #include "gdbcore.h"
28 #include "floatformat.h"
29 #include "regcache.h"
30 #include "gdb_assert.h"
31
32
33 /* FIXME: Eliminate the next two functions when we have the time to
34 change all the callers. */
35
36 void i387_to_double (char *from, char *to);
37 void double_to_i387 (char *from, char *to);
38
39 void
40 i387_to_double (char *from, char *to)
41 {
42 floatformat_to_double (&floatformat_i387_ext, from, (double *) to);
43 }
44
45 void
46 double_to_i387 (char *from, char *to)
47 {
48 floatformat_from_double (&floatformat_i387_ext, (double *) from, to);
49 }
50
51 \f
52 /* FIXME: The functions on this page are used by the old `info float'
53 implementations that a few of the i386 targets provide. These
54 functions should be removed if all of these have been converted to
55 use the generic implementation based on the new register file
56 layout. */
57
58 static void print_387_control_bits (unsigned int control);
59 static void print_387_status_bits (unsigned int status);
60
61 static void
62 print_387_control_bits (unsigned int control)
63 {
64 switch ((control >> 8) & 3)
65 {
66 case 0:
67 puts_unfiltered (" 24 bit; ");
68 break;
69 case 1:
70 puts_unfiltered (" (bad); ");
71 break;
72 case 2:
73 puts_unfiltered (" 53 bit; ");
74 break;
75 case 3:
76 puts_unfiltered (" 64 bit; ");
77 break;
78 }
79 switch ((control >> 10) & 3)
80 {
81 case 0:
82 puts_unfiltered ("NEAR; ");
83 break;
84 case 1:
85 puts_unfiltered ("DOWN; ");
86 break;
87 case 2:
88 puts_unfiltered ("UP; ");
89 break;
90 case 3:
91 puts_unfiltered ("CHOP; ");
92 break;
93 }
94 if (control & 0x3f)
95 {
96 puts_unfiltered ("mask");
97 if (control & 0x0001)
98 puts_unfiltered (" INVAL");
99 if (control & 0x0002)
100 puts_unfiltered (" DENOR");
101 if (control & 0x0004)
102 puts_unfiltered (" DIVZ");
103 if (control & 0x0008)
104 puts_unfiltered (" OVERF");
105 if (control & 0x0010)
106 puts_unfiltered (" UNDER");
107 if (control & 0x0020)
108 puts_unfiltered (" LOS");
109 puts_unfiltered (";");
110 }
111
112 if (control & 0xe080)
113 warning ("\nreserved bits on: %s",
114 local_hex_string (control & 0xe080));
115 }
116
117 void
118 print_387_control_word (unsigned int control)
119 {
120 printf_filtered ("control %s:", local_hex_string(control & 0xffff));
121 print_387_control_bits (control);
122 puts_unfiltered ("\n");
123 }
124
125 static void
126 print_387_status_bits (unsigned int status)
127 {
128 printf_unfiltered (" flags %d%d%d%d; ",
129 (status & 0x4000) != 0,
130 (status & 0x0400) != 0,
131 (status & 0x0200) != 0,
132 (status & 0x0100) != 0);
133 printf_unfiltered ("top %d; ", (status >> 11) & 7);
134 if (status & 0xff)
135 {
136 puts_unfiltered ("excep");
137 if (status & 0x0001) puts_unfiltered (" INVAL");
138 if (status & 0x0002) puts_unfiltered (" DENOR");
139 if (status & 0x0004) puts_unfiltered (" DIVZ");
140 if (status & 0x0008) puts_unfiltered (" OVERF");
141 if (status & 0x0010) puts_unfiltered (" UNDER");
142 if (status & 0x0020) puts_unfiltered (" LOS");
143 if (status & 0x0040) puts_unfiltered (" STACK");
144 }
145 }
146
147 void
148 print_387_status_word (unsigned int status)
149 {
150 printf_filtered ("status %s:", local_hex_string (status & 0xffff));
151 print_387_status_bits (status);
152 puts_unfiltered ("\n");
153 }
154
155 \f
156 /* Implement the `info float' layout based on the register definitions
157 in `tm-i386.h'. */
158
159 /* Print the floating point number specified by RAW. */
160 static void
161 print_i387_value (char *raw)
162 {
163 DOUBLEST value;
164 int len = TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT;
165 char *tmp = alloca (len);
166
167 /* This code only works on targets where ... */
168 gdb_assert (TARGET_LONG_DOUBLE_FORMAT == &floatformat_i387_ext);
169
170 /* Take care of the padding. FP reg is 80 bits. The same value in
171 memory is 96 bits. */
172 gdb_assert (FPU_REG_RAW_SIZE < len);
173 memcpy (&tmp, raw, FPU_REG_RAW_SIZE);
174 memset (&tmp + FPU_REG_RAW_SIZE, 0, len - FPU_REG_RAW_SIZE);
175
176 /* Extract the value as a DOUBLEST. */
177 /* Use extract_floating() rather than floatformat_to_doublest().
178 The latter is lossy in nature. Once GDB gets a host/target
179 independent and non-lossy FP it will become possible to bypass
180 extract_floating() and call floatformat*() directly. Note also
181 the assumptions about TARGET_LONG_DOUBLE above. */
182 value = extract_floating (tmp, len);
183
184 /* We try to print 19 digits. The last digit may or may not contain
185 garbage, but we'd better print one too many. We need enough room
186 to print the value, 1 position for the sign, 1 for the decimal
187 point, 19 for the digits and 6 for the exponent adds up to 27. */
188 #ifdef PRINTF_HAS_LONG_DOUBLE
189 printf_filtered (" %-+27.19Lg", (long double) value);
190 #else
191 printf_filtered (" %-+27.19g", (double) value);
192 #endif
193 }
194
195 /* Print the classification for the register contents RAW. */
196 static void
197 print_i387_ext (unsigned char *raw)
198 {
199 int sign;
200 int integer;
201 unsigned int exponent;
202 unsigned long fraction[2];
203
204 sign = raw[9] & 0x80;
205 integer = raw[7] & 0x80;
206 exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
207 fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
208 fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
209 | (raw[5] << 8) | raw[4]);
210
211 if (exponent == 0x7fff && integer)
212 {
213 if (fraction[0] == 0x00000000 && fraction[1] == 0x00000000)
214 /* Infinity. */
215 printf_filtered (" %cInf", (sign ? '-' : '+'));
216 else if (sign && fraction[0] == 0x00000000 && fraction[1] == 0x40000000)
217 /* Real Indefinite (QNaN). */
218 puts_unfiltered (" Real Indefinite (QNaN)");
219 else if (fraction[1] & 0x40000000)
220 /* QNaN. */
221 puts_filtered (" QNaN");
222 else
223 /* SNaN. */
224 puts_filtered (" SNaN");
225 }
226 else if (exponent < 0x7fff && exponent > 0x0000 && integer)
227 /* Normal. */
228 print_i387_value (raw);
229 else if (exponent == 0x0000)
230 {
231 /* Denormal or zero. */
232 print_i387_value (raw);
233
234 if (integer)
235 /* Pseudo-denormal. */
236 puts_filtered (" Pseudo-denormal");
237 else if (fraction[0] || fraction[1])
238 /* Denormal. */
239 puts_filtered (" Denormal");
240 }
241 else
242 /* Unsupported. */
243 puts_filtered (" Unsupported");
244 }
245
246 /* Print the status word STATUS. */
247 static void
248 print_i387_status_word (unsigned int status)
249 {
250 printf_filtered ("Status Word: %s",
251 local_hex_string_custom (status, "04"));
252 puts_filtered (" ");
253 printf_filtered (" %s", (status & 0x0001) ? "IE" : " ");
254 printf_filtered (" %s", (status & 0x0002) ? "DE" : " ");
255 printf_filtered (" %s", (status & 0x0004) ? "ZE" : " ");
256 printf_filtered (" %s", (status & 0x0008) ? "OE" : " ");
257 printf_filtered (" %s", (status & 0x0010) ? "UE" : " ");
258 printf_filtered (" %s", (status & 0x0020) ? "PE" : " ");
259 puts_filtered (" ");
260 printf_filtered (" %s", (status & 0x0080) ? "ES" : " ");
261 puts_filtered (" ");
262 printf_filtered (" %s", (status & 0x0040) ? "SF" : " ");
263 puts_filtered (" ");
264 printf_filtered (" %s", (status & 0x0100) ? "C0" : " ");
265 printf_filtered (" %s", (status & 0x0200) ? "C1" : " ");
266 printf_filtered (" %s", (status & 0x0400) ? "C2" : " ");
267 printf_filtered (" %s", (status & 0x4000) ? "C3" : " ");
268
269 puts_filtered ("\n");
270
271 printf_filtered (" TOP: %d\n", ((status >> 11) & 7));
272 }
273
274 /* Print the control word CONTROL. */
275 static void
276 print_i387_control_word (unsigned int control)
277 {
278 printf_filtered ("Control Word: %s",
279 local_hex_string_custom (control, "04"));
280 puts_filtered (" ");
281 printf_filtered (" %s", (control & 0x0001) ? "IM" : " ");
282 printf_filtered (" %s", (control & 0x0002) ? "DM" : " ");
283 printf_filtered (" %s", (control & 0x0004) ? "ZM" : " ");
284 printf_filtered (" %s", (control & 0x0008) ? "OM" : " ");
285 printf_filtered (" %s", (control & 0x0010) ? "UM" : " ");
286 printf_filtered (" %s", (control & 0x0020) ? "PM" : " ");
287
288 puts_filtered ("\n");
289
290 puts_filtered (" PC: ");
291 switch ((control >> 8) & 3)
292 {
293 case 0:
294 puts_filtered ("Single Precision (24-bits)\n");
295 break;
296 case 1:
297 puts_filtered ("Reserved\n");
298 break;
299 case 2:
300 puts_filtered ("Double Precision (53-bits)\n");
301 break;
302 case 3:
303 puts_filtered ("Extended Precision (64-bits)\n");
304 break;
305 }
306
307 puts_filtered (" RC: ");
308 switch ((control >> 10) & 3)
309 {
310 case 0:
311 puts_filtered ("Round to nearest\n");
312 break;
313 case 1:
314 puts_filtered ("Round down\n");
315 break;
316 case 2:
317 puts_filtered ("Round up\n");
318 break;
319 case 3:
320 puts_filtered ("Round toward zero\n");
321 break;
322 }
323 }
324
325 /* Print out the i387 floating poin state. */
326 void
327 i387_float_info (void)
328 {
329 unsigned int fctrl;
330 unsigned int fstat;
331 unsigned int ftag;
332 unsigned int fiseg;
333 unsigned int fioff;
334 unsigned int foseg;
335 unsigned int fooff;
336 unsigned int fop;
337 int fpreg;
338 int top;
339
340 fctrl = read_register (FCTRL_REGNUM);
341 fstat = read_register (FSTAT_REGNUM);
342 ftag = read_register (FTAG_REGNUM);
343 fiseg = read_register (FCS_REGNUM);
344 fioff = read_register (FCOFF_REGNUM);
345 foseg = read_register (FDS_REGNUM);
346 fooff = read_register (FDOFF_REGNUM);
347 fop = read_register (FOP_REGNUM);
348
349 top = ((fstat >> 11) & 7);
350
351 for (fpreg = 7; fpreg >= 0; fpreg--)
352 {
353 unsigned char raw[FPU_REG_RAW_SIZE];
354 int tag = (ftag >> (fpreg * 2)) & 3;
355 int i;
356
357 printf_filtered ("%sR%d: ", fpreg == top ? "=>" : " ", fpreg);
358
359 switch (tag)
360 {
361 case 0:
362 puts_filtered ("Valid ");
363 break;
364 case 1:
365 puts_filtered ("Zero ");
366 break;
367 case 2:
368 puts_filtered ("Special ");
369 break;
370 case 3:
371 puts_filtered ("Empty ");
372 break;
373 }
374
375 read_register_gen ((fpreg + 8 - top) % 8 + FP0_REGNUM, raw);
376
377 puts_filtered ("0x");
378 for (i = 9; i >= 0; i--)
379 printf_filtered ("%02x", raw[i]);
380
381 if (tag != 3)
382 print_i387_ext (raw);
383
384 puts_filtered ("\n");
385 }
386
387 puts_filtered ("\n");
388
389 print_i387_status_word (fstat);
390 print_i387_control_word (fctrl);
391 printf_filtered ("Tag Word: %s\n",
392 local_hex_string_custom (ftag, "04"));
393 printf_filtered ("Instruction Pointer: %s:",
394 local_hex_string_custom (fiseg, "02"));
395 printf_filtered ("%s\n", local_hex_string_custom (fioff, "08"));
396 printf_filtered ("Operand Pointer: %s:",
397 local_hex_string_custom (foseg, "02"));
398 printf_filtered ("%s\n", local_hex_string_custom (fooff, "08"));
399 printf_filtered ("Opcode: %s\n",
400 local_hex_string_custom (fop ? (fop | 0xd800) : 0, "04"));
401 }
This page took 0.039289 seconds and 5 git commands to generate.