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 (char *from
, char *to
);
34 void double_to_i387 (char *from
, char *to
);
37 i387_to_double (char *from
, char *to
)
39 floatformat_to_double (&floatformat_i387_ext
, from
, (double *) to
);
43 double_to_i387 (char *from
, char *to
)
45 floatformat_from_double (&floatformat_i387_ext
, (double *) from
, to
);
49 /* FIXME: The functions on this page are used by the old `info float'
50 implementations that a few of the i386 targets provide. These
51 functions should be removed if all of these have been converted to
52 use the generic implementation based on the new register file
55 static void print_387_control_bits (unsigned int control
);
56 static void print_387_status_bits (unsigned int status
);
59 print_387_control_bits (unsigned int control
)
61 switch ((control
>> 8) & 3)
64 puts_unfiltered (" 24 bit; ");
67 puts_unfiltered (" (bad); ");
70 puts_unfiltered (" 53 bit; ");
73 puts_unfiltered (" 64 bit; ");
76 switch ((control
>> 10) & 3)
79 puts_unfiltered ("NEAR; ");
82 puts_unfiltered ("DOWN; ");
85 puts_unfiltered ("UP; ");
88 puts_unfiltered ("CHOP; ");
93 puts_unfiltered ("mask");
95 puts_unfiltered (" INVAL");
97 puts_unfiltered (" DENOR");
99 puts_unfiltered (" DIVZ");
100 if (control
& 0x0008)
101 puts_unfiltered (" OVERF");
102 if (control
& 0x0010)
103 puts_unfiltered (" UNDER");
104 if (control
& 0x0020)
105 puts_unfiltered (" LOS");
106 puts_unfiltered (";");
109 if (control
& 0xe080)
110 warning ("\nreserved bits on: %s",
111 local_hex_string (control
& 0xe080));
115 print_387_control_word (unsigned int control
)
117 printf_filtered ("control %s:", local_hex_string(control
& 0xffff));
118 print_387_control_bits (control
);
119 puts_unfiltered ("\n");
123 print_387_status_bits (unsigned int status
)
125 printf_unfiltered (" flags %d%d%d%d; ",
126 (status
& 0x4000) != 0,
127 (status
& 0x0400) != 0,
128 (status
& 0x0200) != 0,
129 (status
& 0x0100) != 0);
130 printf_unfiltered ("top %d; ", (status
>> 11) & 7);
133 puts_unfiltered ("excep");
134 if (status
& 0x0001) puts_unfiltered (" INVAL");
135 if (status
& 0x0002) puts_unfiltered (" DENOR");
136 if (status
& 0x0004) puts_unfiltered (" DIVZ");
137 if (status
& 0x0008) puts_unfiltered (" OVERF");
138 if (status
& 0x0010) puts_unfiltered (" UNDER");
139 if (status
& 0x0020) puts_unfiltered (" LOS");
140 if (status
& 0x0040) puts_unfiltered (" STACK");
145 print_387_status_word (unsigned int status
)
147 printf_filtered ("status %s:", local_hex_string (status
& 0xffff));
148 print_387_status_bits (status
);
149 puts_unfiltered ("\n");
153 /* Implement the `info float' layout based on the register definitions
156 /* Print the floating point number specified by RAW. */
158 print_i387_value (char *raw
)
162 /* Avoid call to floatformat_to_doublest if possible to preserve as
163 much information as possible. */
165 #ifdef HAVE_LONG_DOUBLE
166 if (sizeof (value
) == sizeof (long double)
167 && HOST_LONG_DOUBLE_FORMAT
== &floatformat_i387_ext
)
169 /* Copy straight over, but take care of the padding. */
170 memcpy (&value
, raw
, FPU_REG_RAW_SIZE
);
171 memset ((char *) &value
+ FPU_REG_RAW_SIZE
, 0,
172 sizeof (value
) - FPU_REG_RAW_SIZE
);
176 floatformat_to_doublest (&floatformat_i387_ext
, raw
, &value
);
178 /* We try to print 19 digits. The last digit may or may not contain
179 garbage, but we'd better print one too many. We need enough room
180 to print the value, 1 position for the sign, 1 for the decimal
181 point, 19 for the digits and 6 for the exponent adds up to 27. */
182 #ifdef PRINTF_HAS_LONG_DOUBLE
183 printf_filtered (" %-+27.19Lg", (long double) value
);
185 printf_filtered (" %-+27.19g", (double) value
);
189 /* Print the classification for the register contents RAW. */
191 print_i387_ext (unsigned char *raw
)
195 unsigned int exponent
;
196 unsigned long fraction
[2];
198 sign
= raw
[9] & 0x80;
199 integer
= raw
[7] & 0x80;
200 exponent
= (((raw
[9] & 0x7f) << 8) | raw
[8]);
201 fraction
[0] = ((raw
[3] << 24) | (raw
[2] << 16) | (raw
[1] << 8) | raw
[0]);
202 fraction
[1] = (((raw
[7] & 0x7f) << 24) | (raw
[6] << 16)
203 | (raw
[5] << 8) | raw
[4]);
205 if (exponent
== 0x7fff && integer
)
207 if (fraction
[0] == 0x00000000 && fraction
[1] == 0x00000000)
209 printf_filtered (" %cInf", (sign
? '-' : '+'));
210 else if (sign
&& fraction
[0] == 0x00000000 && fraction
[1] == 0x40000000)
211 /* Real Indefinite (QNaN). */
212 puts_unfiltered (" Real Indefinite (QNaN)");
213 else if (fraction
[1] & 0x40000000)
215 puts_filtered (" QNaN");
218 puts_filtered (" SNaN");
220 else if (exponent
< 0x7fff && exponent
> 0x0000 && integer
)
222 print_i387_value (raw
);
223 else if (exponent
== 0x0000)
225 /* Denormal or zero. */
226 print_i387_value (raw
);
229 /* Pseudo-denormal. */
230 puts_filtered (" Pseudo-denormal");
231 else if (fraction
[0] || fraction
[1])
233 puts_filtered (" Denormal");
237 puts_filtered (" Unsupported");
240 /* Print the status word STATUS. */
242 print_i387_status_word (unsigned int status
)
244 printf_filtered ("Status Word: %s",
245 local_hex_string_custom (status
, "04"));
247 printf_filtered (" %s", (status
& 0x0001) ? "IE" : " ");
248 printf_filtered (" %s", (status
& 0x0002) ? "DE" : " ");
249 printf_filtered (" %s", (status
& 0x0004) ? "ZE" : " ");
250 printf_filtered (" %s", (status
& 0x0008) ? "OE" : " ");
251 printf_filtered (" %s", (status
& 0x0010) ? "UE" : " ");
252 printf_filtered (" %s", (status
& 0x0020) ? "PE" : " ");
254 printf_filtered (" %s", (status
& 0x0080) ? "ES" : " ");
256 printf_filtered (" %s", (status
& 0x0080) ? "SF" : " ");
258 printf_filtered (" %s", (status
& 0x0100) ? "C0" : " ");
259 printf_filtered (" %s", (status
& 0x0200) ? "C1" : " ");
260 printf_filtered (" %s", (status
& 0x0400) ? "C2" : " ");
261 printf_filtered (" %s", (status
& 0x4000) ? "C3" : " ");
263 puts_filtered ("\n");
265 printf_filtered (" TOP: %d\n", ((status
>> 11) & 7));
268 /* Print the control word CONTROL. */
270 print_i387_control_word (unsigned int control
)
272 printf_filtered ("Control Word: %s",
273 local_hex_string_custom (control
, "04"));
275 printf_filtered (" %s", (control
& 0x0001) ? "IM" : " ");
276 printf_filtered (" %s", (control
& 0x0002) ? "DM" : " ");
277 printf_filtered (" %s", (control
& 0x0004) ? "ZM" : " ");
278 printf_filtered (" %s", (control
& 0x0008) ? "OM" : " ");
279 printf_filtered (" %s", (control
& 0x0010) ? "UM" : " ");
280 printf_filtered (" %s", (control
& 0x0020) ? "PM" : " ");
282 puts_filtered ("\n");
284 puts_filtered (" PC: ");
285 switch ((control
>> 8) & 3)
288 puts_filtered ("Single Precision (24-bits)\n");
291 puts_filtered ("Reserved\n");
294 puts_filtered ("Double Precision (53-bits)\n");
297 puts_filtered ("Extended Precision (64-bits)\n");
301 puts_filtered (" RC: ");
302 switch ((control
>> 10) & 3)
305 puts_filtered ("Round to nearest\n");
308 puts_filtered ("Round down\n");
311 puts_filtered ("Round up\n");
314 puts_filtered ("Round toward zero\n");
319 /* Print out the i387 floating poin state. */
321 i387_float_info (void)
334 fctrl
= read_register (FCTRL_REGNUM
);
335 fstat
= read_register (FSTAT_REGNUM
);
336 ftag
= read_register (FTAG_REGNUM
);
337 fiseg
= read_register (FCS_REGNUM
);
338 fioff
= read_register (FCOFF_REGNUM
);
339 foseg
= read_register (FDS_REGNUM
);
340 fooff
= read_register (FDOFF_REGNUM
);
341 fop
= read_register (FOP_REGNUM
);
343 top
= ((fstat
>> 11) & 7);
345 for (fpreg
= 7; fpreg
>= 0; fpreg
--)
347 unsigned char raw
[FPU_REG_RAW_SIZE
];
348 int tag
= (ftag
>> (fpreg
* 2)) & 3;
351 printf_filtered ("%sR%d: ", fpreg
== top
? "=>" : " ", fpreg
);
356 puts_filtered ("Valid ");
359 puts_filtered ("Zero ");
362 puts_filtered ("Special ");
365 puts_filtered ("Empty ");
369 read_register_gen ((fpreg
+ 8 - top
) % 8 + FP0_REGNUM
, raw
);
371 puts_filtered ("0x");
372 for (i
= 9; i
>= 0; i
--)
373 printf_filtered ("%02x", raw
[i
]);
376 print_i387_ext (raw
);
378 puts_filtered ("\n");
381 puts_filtered ("\n");
383 print_i387_status_word (fstat
);
384 print_i387_control_word (fctrl
);
385 printf_filtered ("Tag Word: %s\n",
386 local_hex_string_custom (ftag
, "04"));
387 printf_filtered ("Instruction Pointer: %s:",
388 local_hex_string_custom (fiseg
, "02"));
389 printf_filtered ("%s\n", local_hex_string_custom (fioff
, "08"));
390 printf_filtered ("Operand Pointer: %s:",
391 local_hex_string_custom (foseg
, "02"));
392 printf_filtered ("%s\n", local_hex_string_custom (fooff
, "08"));
393 printf_filtered ("Opcode: %s\n",
394 local_hex_string_custom (fop
? (fop
| 0xd800) : 0, "04"));
This page took 0.037307 seconds and 4 git commands to generate.