1 /* Intel 387 floating point stuff.
2 Copyright (C) 1988, 89, 91, 98, 99, 2000 Free Software Foundation, Inc.
4 This file is part of GDB.
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
27 #include "floatformat.h"
30 /* FIXME: Eliminate the next two functions when we have the time to
31 change all the callers. */
33 void i387_to_double
PARAMS ((char *from
, char *to
));
34 void double_to_i387
PARAMS ((char *from
, char *to
));
37 i387_to_double (from
, to
)
41 floatformat_to_double (&floatformat_i387_ext
, from
, (double *) to
);
45 double_to_i387 (from
, to
)
49 floatformat_from_double (&floatformat_i387_ext
, (double *) from
, to
);
53 /* FIXME: The functions on this page are used by the old `info float'
54 implementations that a few of the i386 targets provide. These
55 functions should be removed if all of these have been converted to
56 use the generic implementation based on the new register file
59 static void print_387_control_bits
PARAMS ((unsigned int control
));
60 static void print_387_status_bits
PARAMS ((unsigned int status
));
63 print_387_control_bits (control
)
66 switch ((control
>> 8) & 3)
69 puts_unfiltered (" 24 bit; ");
72 puts_unfiltered (" (bad); ");
75 puts_unfiltered (" 53 bit; ");
78 puts_unfiltered (" 64 bit; ");
81 switch ((control
>> 10) & 3)
84 puts_unfiltered ("NEAR; ");
87 puts_unfiltered ("DOWN; ");
90 puts_unfiltered ("UP; ");
93 puts_unfiltered ("CHOP; ");
98 puts_unfiltered ("mask");
100 puts_unfiltered (" INVAL");
101 if (control
& 0x0002)
102 puts_unfiltered (" DENOR");
103 if (control
& 0x0004)
104 puts_unfiltered (" DIVZ");
105 if (control
& 0x0008)
106 puts_unfiltered (" OVERF");
107 if (control
& 0x0010)
108 puts_unfiltered (" UNDER");
109 if (control
& 0x0020)
110 puts_unfiltered (" LOS");
111 puts_unfiltered (";");
114 if (control
& 0xe080)
115 warning ("\nreserved bits on: %s",
116 local_hex_string (control
& 0xe080));
120 print_387_control_word (control
)
121 unsigned int control
;
123 printf_filtered ("control %s:", local_hex_string(control
& 0xffff));
124 print_387_control_bits (control
);
125 puts_unfiltered ("\n");
129 print_387_status_bits (status
)
132 printf_unfiltered (" flags %d%d%d%d; ",
133 (status
& 0x4000) != 0,
134 (status
& 0x0400) != 0,
135 (status
& 0x0200) != 0,
136 (status
& 0x0100) != 0);
137 printf_unfiltered ("top %d; ", (status
>> 11) & 7);
140 puts_unfiltered ("excep");
141 if (status
& 0x0001) puts_unfiltered (" INVAL");
142 if (status
& 0x0002) puts_unfiltered (" DENOR");
143 if (status
& 0x0004) puts_unfiltered (" DIVZ");
144 if (status
& 0x0008) puts_unfiltered (" OVERF");
145 if (status
& 0x0010) puts_unfiltered (" UNDER");
146 if (status
& 0x0020) puts_unfiltered (" LOS");
147 if (status
& 0x0040) puts_unfiltered (" STACK");
152 print_387_status_word (status
)
155 printf_filtered ("status %s:", local_hex_string (status
& 0xffff));
156 print_387_status_bits (status
);
157 puts_unfiltered ("\n");
161 /* Implement the `info float' layout based on the register definitions
164 /* Print the floating point number specified by RAW. */
166 print_i387_value (char *raw
)
170 /* Avoid call to floatformat_to_doublest if possible to preserve as
171 much information as possible. */
173 #ifdef HAVE_LONG_DOUBLE
174 if (sizeof (value
) == sizeof (long double)
175 && HOST_LONG_DOUBLE_FORMAT
== &floatformat_i387_ext
)
177 /* Copy straight over, but take care of the padding. */
178 memcpy (&value
, raw
, FPU_REG_RAW_SIZE
);
179 memset (&value
+ FPU_REG_RAW_SIZE
, 0, sizeof (value
) - FPU_REG_RAW_SIZE
);
183 floatformat_to_doublest (&floatformat_i387_ext
, raw
, &value
);
185 /* We try to print 19 digits. The last digit may or may not contain
186 garbage, but we'd better print one too many. We need enough room
187 to print the value, 1 position for the sign, 1 for the decimal
188 point, 19 for the digits and 6 for the exponent adds up to 27. */
189 #ifdef PRINTF_HAS_LONG_DOUBLE
190 printf_filtered (" %-+27.19Lg", (long double) value
);
192 printf_filtered (" %-+27.19g", (double) value
);
196 /* Print the classification for the register contents RAW. */
198 print_i387_ext (unsigned char *raw
)
202 unsigned int exponent
;
203 unsigned long fraction
[2];
205 sign
= raw
[9] & 0x80;
206 integer
= raw
[7] & 0x80;
207 exponent
= (((raw
[9] & 0x7f) << 8) | raw
[8]);
208 fraction
[0] = ((raw
[3] << 24) | (raw
[2] << 16) | (raw
[1] << 8) | raw
[0]);
209 fraction
[1] = (((raw
[7] & 0x7f) << 24) | (raw
[6] << 16)
210 | (raw
[5] << 8) | raw
[4]);
212 if (exponent
== 0x7fff && integer
)
214 if (fraction
[0] == 0x00000000 && fraction
[1] == 0x00000000)
216 printf_filtered (" %cInf", (sign
? '-' : '+'));
217 else if (sign
&& fraction
[0] == 0x00000000 && fraction
[1] == 0x40000000)
218 /* Real Indefinite (QNaN). */
219 puts_unfiltered (" Real Indefinite (QNaN)");
220 else if (fraction
[1] & 0x40000000)
222 puts_filtered (" QNaN");
225 puts_filtered (" SNaN");
227 else if (exponent
< 0x7fff && exponent
> 0x0000 && integer
)
229 print_i387_value (raw
);
230 else if (exponent
== 0x0000)
232 /* Denormal or zero. */
233 print_i387_value (raw
);
236 /* Pseudo-denormal. */
237 puts_filtered (" Pseudo-denormal");
238 else if (fraction
[0] || fraction
[1])
240 puts_filtered (" Denormal");
244 puts_filtered (" Unsupported");
247 /* Print the status word STATUS. */
249 print_i387_status_word (unsigned int status
)
251 printf_filtered ("Status Word: %s",
252 local_hex_string_custom (status
, "04"));
254 printf_filtered (" %s", (status
& 0x0001) ? "IE" : " ");
255 printf_filtered (" %s", (status
& 0x0002) ? "DE" : " ");
256 printf_filtered (" %s", (status
& 0x0004) ? "ZE" : " ");
257 printf_filtered (" %s", (status
& 0x0008) ? "OE" : " ");
258 printf_filtered (" %s", (status
& 0x0010) ? "UE" : " ");
259 printf_filtered (" %s", (status
& 0x0020) ? "PE" : " ");
261 printf_filtered (" %s", (status
& 0x0080) ? "ES" : " ");
263 printf_filtered (" %s", (status
& 0x0080) ? "SF" : " ");
265 printf_filtered (" %s", (status
& 0x0100) ? "C0" : " ");
266 printf_filtered (" %s", (status
& 0x0200) ? "C1" : " ");
267 printf_filtered (" %s", (status
& 0x0400) ? "C2" : " ");
268 printf_filtered (" %s", (status
& 0x4000) ? "C3" : " ");
270 puts_filtered ("\n");
272 printf_filtered (" TOP: %d\n", ((status
>> 11) & 7));
275 /* Print the control word CONTROL. */
277 print_i387_control_word (unsigned int control
)
279 printf_filtered ("Control Word: %s",
280 local_hex_string_custom (control
, "04"));
282 printf_filtered (" %s", (control
& 0x0001) ? "IM" : " ");
283 printf_filtered (" %s", (control
& 0x0002) ? "DM" : " ");
284 printf_filtered (" %s", (control
& 0x0004) ? "ZM" : " ");
285 printf_filtered (" %s", (control
& 0x0008) ? "OM" : " ");
286 printf_filtered (" %s", (control
& 0x0010) ? "UM" : " ");
287 printf_filtered (" %s", (control
& 0x0020) ? "PM" : " ");
289 puts_filtered ("\n");
291 puts_filtered (" PC: ");
292 switch ((control
>> 8) & 3)
295 puts_filtered ("Single Precision (24-bits)\n");
298 puts_filtered ("Reserved\n");
301 puts_filtered ("Double Precision (53-bits)\n");
304 puts_filtered ("Extended Precision (64-bits)\n");
308 puts_filtered (" RC: ");
309 switch ((control
>> 10) & 3)
312 puts_filtered ("Round to nearest\n");
315 puts_filtered ("Round down\n");
318 puts_filtered ("Round up\n");
321 puts_filtered ("Round toward zero\n");
326 /* Print out the i387 floating poin state. */
328 i387_float_info (void)
341 fctrl
= read_register (FCTRL_REGNUM
);
342 fstat
= read_register (FSTAT_REGNUM
);
343 ftag
= read_register (FTAG_REGNUM
);
344 fiseg
= read_register (FCS_REGNUM
);
345 fioff
= read_register (FCOFF_REGNUM
);
346 foseg
= read_register (FDS_REGNUM
);
347 fooff
= read_register (FDOFF_REGNUM
);
348 fop
= read_register (FOP_REGNUM
);
350 top
= ((fstat
>> 11) & 7);
352 for (fpreg
= 7; fpreg
>= 0; fpreg
--)
354 unsigned char raw
[FPU_REG_RAW_SIZE
];
355 int tag
= (ftag
>> (fpreg
* 2)) & 3;
358 printf_filtered ("%sR%d: ", fpreg
== top
? "=>" : " ", fpreg
);
363 puts_filtered ("Valid ");
366 puts_filtered ("Zero ");
369 puts_filtered ("Special ");
372 puts_filtered ("Empty ");
376 read_register_gen ((fpreg
+ 8 - top
) % 8 + FP0_REGNUM
, raw
);
378 puts_filtered ("0x");
379 for (i
= 9; i
>= 0; i
--)
380 printf_filtered ("%02x", raw
[i
]);
383 print_i387_ext (raw
);
385 puts_filtered ("\n");
388 puts_filtered ("\n");
390 print_i387_status_word (fstat
);
391 print_i387_control_word (fctrl
);
392 printf_filtered ("Tag Word: %s\n",
393 local_hex_string_custom (ftag
, "04"));
394 printf_filtered ("Instruction Pointer: %s:",
395 local_hex_string_custom (fiseg
, "02"));
396 printf_filtered ("%s\n", local_hex_string_custom (fioff
, "08"));
397 printf_filtered ("Operand Pointer: %s:",
398 local_hex_string_custom (foseg
, "02"));
399 printf_filtered ("%s\n", local_hex_string_custom (fooff
, "08"));
400 printf_filtered ("Opcode: %s\n",
401 local_hex_string_custom (fop
? (fop
| 0xd800) : 0, "04"));