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"
32 /* FIXME: Eliminate the next two functions when we have the time to
33 change all the callers. */
35 void i387_to_double (char *from
, char *to
);
36 void double_to_i387 (char *from
, char *to
);
39 i387_to_double (char *from
, char *to
)
41 floatformat_to_double (&floatformat_i387_ext
, from
, (double *) to
);
45 double_to_i387 (char *from
, char *to
)
47 floatformat_from_double (&floatformat_i387_ext
, (double *) from
, to
);
51 /* FIXME: The functions on this page are used by the old `info float'
52 implementations that a few of the i386 targets provide. These
53 functions should be removed if all of these have been converted to
54 use the generic implementation based on the new register file
57 static void print_387_control_bits (unsigned int control
);
58 static void print_387_status_bits (unsigned int status
);
61 print_387_control_bits (unsigned int control
)
63 switch ((control
>> 8) & 3)
66 puts_unfiltered (" 24 bit; ");
69 puts_unfiltered (" (bad); ");
72 puts_unfiltered (" 53 bit; ");
75 puts_unfiltered (" 64 bit; ");
78 switch ((control
>> 10) & 3)
81 puts_unfiltered ("NEAR; ");
84 puts_unfiltered ("DOWN; ");
87 puts_unfiltered ("UP; ");
90 puts_unfiltered ("CHOP; ");
95 puts_unfiltered ("mask");
97 puts_unfiltered (" INVAL");
99 puts_unfiltered (" DENOR");
100 if (control
& 0x0004)
101 puts_unfiltered (" DIVZ");
102 if (control
& 0x0008)
103 puts_unfiltered (" OVERF");
104 if (control
& 0x0010)
105 puts_unfiltered (" UNDER");
106 if (control
& 0x0020)
107 puts_unfiltered (" LOS");
108 puts_unfiltered (";");
111 if (control
& 0xe080)
112 warning ("\nreserved bits on: %s",
113 local_hex_string (control
& 0xe080));
117 print_387_control_word (unsigned int control
)
119 printf_filtered ("control %s:", local_hex_string(control
& 0xffff));
120 print_387_control_bits (control
);
121 puts_unfiltered ("\n");
125 print_387_status_bits (unsigned int status
)
127 printf_unfiltered (" flags %d%d%d%d; ",
128 (status
& 0x4000) != 0,
129 (status
& 0x0400) != 0,
130 (status
& 0x0200) != 0,
131 (status
& 0x0100) != 0);
132 printf_unfiltered ("top %d; ", (status
>> 11) & 7);
135 puts_unfiltered ("excep");
136 if (status
& 0x0001) puts_unfiltered (" INVAL");
137 if (status
& 0x0002) puts_unfiltered (" DENOR");
138 if (status
& 0x0004) puts_unfiltered (" DIVZ");
139 if (status
& 0x0008) puts_unfiltered (" OVERF");
140 if (status
& 0x0010) puts_unfiltered (" UNDER");
141 if (status
& 0x0020) puts_unfiltered (" LOS");
142 if (status
& 0x0040) puts_unfiltered (" STACK");
147 print_387_status_word (unsigned int status
)
149 printf_filtered ("status %s:", local_hex_string (status
& 0xffff));
150 print_387_status_bits (status
);
151 puts_unfiltered ("\n");
155 /* Implement the `info float' layout based on the register definitions
158 /* Print the floating point number specified by RAW. */
160 print_i387_value (char *raw
)
164 /* Avoid call to floatformat_to_doublest if possible to preserve as
165 much information as possible. */
167 #ifdef HAVE_LONG_DOUBLE
168 if (sizeof (value
) == sizeof (long double)
169 && HOST_LONG_DOUBLE_FORMAT
== &floatformat_i387_ext
)
171 /* Copy straight over, but take care of the padding. */
172 memcpy (&value
, raw
, FPU_REG_RAW_SIZE
);
173 memset ((char *) &value
+ FPU_REG_RAW_SIZE
, 0,
174 sizeof (value
) - FPU_REG_RAW_SIZE
);
178 floatformat_to_doublest (&floatformat_i387_ext
, raw
, &value
);
180 /* We try to print 19 digits. The last digit may or may not contain
181 garbage, but we'd better print one too many. We need enough room
182 to print the value, 1 position for the sign, 1 for the decimal
183 point, 19 for the digits and 6 for the exponent adds up to 27. */
184 #ifdef PRINTF_HAS_LONG_DOUBLE
185 printf_filtered (" %-+27.19Lg", (long double) value
);
187 printf_filtered (" %-+27.19g", (double) value
);
191 /* Print the classification for the register contents RAW. */
193 print_i387_ext (unsigned char *raw
)
197 unsigned int exponent
;
198 unsigned long fraction
[2];
200 sign
= raw
[9] & 0x80;
201 integer
= raw
[7] & 0x80;
202 exponent
= (((raw
[9] & 0x7f) << 8) | raw
[8]);
203 fraction
[0] = ((raw
[3] << 24) | (raw
[2] << 16) | (raw
[1] << 8) | raw
[0]);
204 fraction
[1] = (((raw
[7] & 0x7f) << 24) | (raw
[6] << 16)
205 | (raw
[5] << 8) | raw
[4]);
207 if (exponent
== 0x7fff && integer
)
209 if (fraction
[0] == 0x00000000 && fraction
[1] == 0x00000000)
211 printf_filtered (" %cInf", (sign
? '-' : '+'));
212 else if (sign
&& fraction
[0] == 0x00000000 && fraction
[1] == 0x40000000)
213 /* Real Indefinite (QNaN). */
214 puts_unfiltered (" Real Indefinite (QNaN)");
215 else if (fraction
[1] & 0x40000000)
217 puts_filtered (" QNaN");
220 puts_filtered (" SNaN");
222 else if (exponent
< 0x7fff && exponent
> 0x0000 && integer
)
224 print_i387_value (raw
);
225 else if (exponent
== 0x0000)
227 /* Denormal or zero. */
228 print_i387_value (raw
);
231 /* Pseudo-denormal. */
232 puts_filtered (" Pseudo-denormal");
233 else if (fraction
[0] || fraction
[1])
235 puts_filtered (" Denormal");
239 puts_filtered (" Unsupported");
242 /* Print the status word STATUS. */
244 print_i387_status_word (unsigned int status
)
246 printf_filtered ("Status Word: %s",
247 local_hex_string_custom (status
, "04"));
249 printf_filtered (" %s", (status
& 0x0001) ? "IE" : " ");
250 printf_filtered (" %s", (status
& 0x0002) ? "DE" : " ");
251 printf_filtered (" %s", (status
& 0x0004) ? "ZE" : " ");
252 printf_filtered (" %s", (status
& 0x0008) ? "OE" : " ");
253 printf_filtered (" %s", (status
& 0x0010) ? "UE" : " ");
254 printf_filtered (" %s", (status
& 0x0020) ? "PE" : " ");
256 printf_filtered (" %s", (status
& 0x0080) ? "ES" : " ");
258 printf_filtered (" %s", (status
& 0x0040) ? "SF" : " ");
260 printf_filtered (" %s", (status
& 0x0100) ? "C0" : " ");
261 printf_filtered (" %s", (status
& 0x0200) ? "C1" : " ");
262 printf_filtered (" %s", (status
& 0x0400) ? "C2" : " ");
263 printf_filtered (" %s", (status
& 0x4000) ? "C3" : " ");
265 puts_filtered ("\n");
267 printf_filtered (" TOP: %d\n", ((status
>> 11) & 7));
270 /* Print the control word CONTROL. */
272 print_i387_control_word (unsigned int control
)
274 printf_filtered ("Control Word: %s",
275 local_hex_string_custom (control
, "04"));
277 printf_filtered (" %s", (control
& 0x0001) ? "IM" : " ");
278 printf_filtered (" %s", (control
& 0x0002) ? "DM" : " ");
279 printf_filtered (" %s", (control
& 0x0004) ? "ZM" : " ");
280 printf_filtered (" %s", (control
& 0x0008) ? "OM" : " ");
281 printf_filtered (" %s", (control
& 0x0010) ? "UM" : " ");
282 printf_filtered (" %s", (control
& 0x0020) ? "PM" : " ");
284 puts_filtered ("\n");
286 puts_filtered (" PC: ");
287 switch ((control
>> 8) & 3)
290 puts_filtered ("Single Precision (24-bits)\n");
293 puts_filtered ("Reserved\n");
296 puts_filtered ("Double Precision (53-bits)\n");
299 puts_filtered ("Extended Precision (64-bits)\n");
303 puts_filtered (" RC: ");
304 switch ((control
>> 10) & 3)
307 puts_filtered ("Round to nearest\n");
310 puts_filtered ("Round down\n");
313 puts_filtered ("Round up\n");
316 puts_filtered ("Round toward zero\n");
321 /* Print out the i387 floating poin state. */
323 i387_float_info (void)
336 fctrl
= read_register (FCTRL_REGNUM
);
337 fstat
= read_register (FSTAT_REGNUM
);
338 ftag
= read_register (FTAG_REGNUM
);
339 fiseg
= read_register (FCS_REGNUM
);
340 fioff
= read_register (FCOFF_REGNUM
);
341 foseg
= read_register (FDS_REGNUM
);
342 fooff
= read_register (FDOFF_REGNUM
);
343 fop
= read_register (FOP_REGNUM
);
345 top
= ((fstat
>> 11) & 7);
347 for (fpreg
= 7; fpreg
>= 0; fpreg
--)
349 unsigned char raw
[FPU_REG_RAW_SIZE
];
350 int tag
= (ftag
>> (fpreg
* 2)) & 3;
353 printf_filtered ("%sR%d: ", fpreg
== top
? "=>" : " ", fpreg
);
358 puts_filtered ("Valid ");
361 puts_filtered ("Zero ");
364 puts_filtered ("Special ");
367 puts_filtered ("Empty ");
371 read_register_gen ((fpreg
+ 8 - top
) % 8 + FP0_REGNUM
, raw
);
373 puts_filtered ("0x");
374 for (i
= 9; i
>= 0; i
--)
375 printf_filtered ("%02x", raw
[i
]);
378 print_i387_ext (raw
);
380 puts_filtered ("\n");
383 puts_filtered ("\n");
385 print_i387_status_word (fstat
);
386 print_i387_control_word (fctrl
);
387 printf_filtered ("Tag Word: %s\n",
388 local_hex_string_custom (ftag
, "04"));
389 printf_filtered ("Instruction Pointer: %s:",
390 local_hex_string_custom (fiseg
, "02"));
391 printf_filtered ("%s\n", local_hex_string_custom (fioff
, "08"));
392 printf_filtered ("Operand Pointer: %s:",
393 local_hex_string_custom (foseg
, "02"));
394 printf_filtered ("%s\n", local_hex_string_custom (fooff
, "08"));
395 printf_filtered ("Opcode: %s\n",
396 local_hex_string_custom (fop
? (fop
| 0xd800) : 0, "04"));
This page took 0.036839 seconds and 4 git commands to generate.