1 /* Intel 387 floating point stuff.
2 Copyright 1988, 1989, 1991, 1992, 1993, 1994, 1998, 1999, 2000, 2001
3 Free Software Foundation, Inc.
5 This file is part of GDB.
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.
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.
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. */
28 #include "floatformat.h"
30 #include "gdb_assert.h"
33 /* FIXME: Eliminate the next two functions when we have the time to
34 change all the callers. */
36 void i387_to_double (char *from
, char *to
);
37 void double_to_i387 (char *from
, char *to
);
40 i387_to_double (char *from
, char *to
)
42 floatformat_to_double (&floatformat_i387_ext
, from
, (double *) to
);
46 double_to_i387 (char *from
, char *to
)
48 floatformat_from_double (&floatformat_i387_ext
, (double *) from
, to
);
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
58 static void print_387_control_bits (unsigned int control
);
59 static void print_387_status_bits (unsigned int status
);
62 print_387_control_bits (unsigned int control
)
64 switch ((control
>> 8) & 3)
67 puts_unfiltered (" 24 bit; ");
70 puts_unfiltered (" (bad); ");
73 puts_unfiltered (" 53 bit; ");
76 puts_unfiltered (" 64 bit; ");
79 switch ((control
>> 10) & 3)
82 puts_unfiltered ("NEAR; ");
85 puts_unfiltered ("DOWN; ");
88 puts_unfiltered ("UP; ");
91 puts_unfiltered ("CHOP; ");
96 puts_unfiltered ("mask");
98 puts_unfiltered (" INVAL");
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 (";");
112 if (control
& 0xe080)
113 warning ("\nreserved bits on: %s",
114 local_hex_string (control
& 0xe080));
118 print_387_control_word (unsigned int control
)
120 printf_filtered ("control %s:", local_hex_string(control
& 0xffff));
121 print_387_control_bits (control
);
122 puts_unfiltered ("\n");
126 print_387_status_bits (unsigned int status
)
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);
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");
148 print_387_status_word (unsigned int status
)
150 printf_filtered ("status %s:", local_hex_string (status
& 0xffff));
151 print_387_status_bits (status
);
152 puts_unfiltered ("\n");
156 /* Implement the `info float' layout based on the register definitions
159 /* Print the floating point number specified by RAW. */
161 print_i387_value (char *raw
)
164 int len
= TARGET_LONG_DOUBLE_BIT
/ TARGET_CHAR_BIT
;
165 char *tmp
= alloca (len
);
167 /* This code only works on targets where ... */
168 gdb_assert (TARGET_LONG_DOUBLE_FORMAT
== &floatformat_i387_ext
);
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
);
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
);
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
);
191 printf_filtered (" %-+27.19g", (double) value
);
195 /* Print the classification for the register contents RAW. */
197 print_i387_ext (unsigned char *raw
)
201 unsigned int exponent
;
202 unsigned long fraction
[2];
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]);
211 if (exponent
== 0x7fff && integer
)
213 if (fraction
[0] == 0x00000000 && fraction
[1] == 0x00000000)
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)
221 puts_filtered (" QNaN");
224 puts_filtered (" SNaN");
226 else if (exponent
< 0x7fff && exponent
> 0x0000 && integer
)
228 print_i387_value (raw
);
229 else if (exponent
== 0x0000)
231 /* Denormal or zero. */
232 print_i387_value (raw
);
235 /* Pseudo-denormal. */
236 puts_filtered (" Pseudo-denormal");
237 else if (fraction
[0] || fraction
[1])
239 puts_filtered (" Denormal");
243 puts_filtered (" Unsupported");
246 /* Print the status word STATUS. */
248 print_i387_status_word (unsigned int status
)
250 printf_filtered ("Status Word: %s",
251 local_hex_string_custom (status
, "04"));
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" : " ");
260 printf_filtered (" %s", (status
& 0x0080) ? "ES" : " ");
262 printf_filtered (" %s", (status
& 0x0040) ? "SF" : " ");
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" : " ");
269 puts_filtered ("\n");
271 printf_filtered (" TOP: %d\n", ((status
>> 11) & 7));
274 /* Print the control word CONTROL. */
276 print_i387_control_word (unsigned int control
)
278 printf_filtered ("Control Word: %s",
279 local_hex_string_custom (control
, "04"));
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" : " ");
288 puts_filtered ("\n");
290 puts_filtered (" PC: ");
291 switch ((control
>> 8) & 3)
294 puts_filtered ("Single Precision (24-bits)\n");
297 puts_filtered ("Reserved\n");
300 puts_filtered ("Double Precision (53-bits)\n");
303 puts_filtered ("Extended Precision (64-bits)\n");
307 puts_filtered (" RC: ");
308 switch ((control
>> 10) & 3)
311 puts_filtered ("Round to nearest\n");
314 puts_filtered ("Round down\n");
317 puts_filtered ("Round up\n");
320 puts_filtered ("Round toward zero\n");
325 /* Print out the i387 floating poin state. */
327 i387_float_info (void)
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
);
349 top
= ((fstat
>> 11) & 7);
351 for (fpreg
= 7; fpreg
>= 0; fpreg
--)
353 unsigned char raw
[FPU_REG_RAW_SIZE
];
354 int tag
= (ftag
>> (fpreg
* 2)) & 3;
357 printf_filtered ("%sR%d: ", fpreg
== top
? "=>" : " ", fpreg
);
362 puts_filtered ("Valid ");
365 puts_filtered ("Zero ");
368 puts_filtered ("Special ");
371 puts_filtered ("Empty ");
375 read_register_gen ((fpreg
+ 8 - top
) % 8 + FP0_REGNUM
, raw
);
377 puts_filtered ("0x");
378 for (i
= 9; i
>= 0; i
--)
379 printf_filtered ("%02x", raw
[i
]);
382 print_i387_ext (raw
);
384 puts_filtered ("\n");
387 puts_filtered ("\n");
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"));