1 /* Intel 387 floating point stuff.
2 Copyright (C) 1988, 1989, 1991, 1998, 1999 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 floatformat_to_doublest (&floatformat_i387_ext, raw, &value);
172 /* We try to print 19 digits. The last digit may or may not contain
173 garbage, but we'd better print one too many. We need enough room
174 to print the value, 1 position for the sign, 1 for the decimal
175 point, 19 for the digits and 6 for the exponent adds up to 27. */
176 #ifdef PRINTF_HAS_LONG_DOUBLE
177 printf_filtered (" %-+27.19Lg", (long double) value);
179 printf_filtered (" %-+27.19g", (double) value);
183 /* Print the classification for the register contents RAW. */
185 print_i387_ext (unsigned char *raw)
189 unsigned int exponent;
190 unsigned long fraction[2];
192 sign = raw[9] & 0x80;
193 integer = raw[7] & 0x80;
194 exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
195 fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
196 fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
197 | (raw[5] << 8) | raw[4]);
199 if (exponent == 0x7fff && integer)
201 if (fraction[0] == 0x00000000 && fraction[1] == 0x00000000)
203 printf_filtered (" %cInf", (sign ? '-' : '+'));
204 else if (sign && fraction[0] == 0x00000000 && fraction[1] == 0x40000000)
205 /* Real Indefinite (QNaN). */
206 puts_unfiltered (" Real Indefinite (QNaN)");
207 else if (fraction[1] & 0x40000000)
209 puts_filtered (" QNaN");
212 puts_filtered (" SNaN");
214 else if (exponent < 0x7fff && exponent > 0x0000 && integer)
216 print_i387_value (raw);
217 else if (exponent == 0x0000)
219 /* Denormal or zero. */
220 print_i387_value (raw);
223 /* Pseudo-denormal. */
224 puts_filtered (" Pseudo-denormal");
225 else if (fraction[0] || fraction[1])
227 puts_filtered (" Denormal");
231 puts_filtered (" Unsupported");
234 /* Print the status word STATUS. */
236 print_i387_status_word (unsigned int status)
238 printf_filtered ("Status Word: %s",
239 local_hex_string_custom (status, "04"));
241 printf_filtered (" %s", (status & 0x0001) ? "IE" : " ");
242 printf_filtered (" %s", (status & 0x0002) ? "DE" : " ");
243 printf_filtered (" %s", (status & 0x0004) ? "ZE" : " ");
244 printf_filtered (" %s", (status & 0x0008) ? "OE" : " ");
245 printf_filtered (" %s", (status & 0x0010) ? "UE" : " ");
246 printf_filtered (" %s", (status & 0x0020) ? "PE" : " ");
248 printf_filtered (" %s", (status & 0x0080) ? "ES" : " ");
250 printf_filtered (" %s", (status & 0x0080) ? "SF" : " ");
252 printf_filtered (" %s", (status & 0x0100) ? "C0" : " ");
253 printf_filtered (" %s", (status & 0x0200) ? "C1" : " ");
254 printf_filtered (" %s", (status & 0x0400) ? "C2" : " ");
255 printf_filtered (" %s", (status & 0x4000) ? "C3" : " ");
257 puts_filtered ("\n");
259 printf_filtered (" TOP: %d\n", ((status >> 11) & 7));
262 /* Print the control word CONTROL. */
264 print_i387_control_word (unsigned int control)
266 printf_filtered ("Control Word: %s",
267 local_hex_string_custom (control, "04"));
269 printf_filtered (" %s", (control & 0x0001) ? "IM" : " ");
270 printf_filtered (" %s", (control & 0x0002) ? "DM" : " ");
271 printf_filtered (" %s", (control & 0x0004) ? "ZM" : " ");
272 printf_filtered (" %s", (control & 0x0008) ? "OM" : " ");
273 printf_filtered (" %s", (control & 0x0010) ? "UM" : " ");
274 printf_filtered (" %s", (control & 0x0020) ? "PM" : " ");
276 puts_filtered ("\n");
278 puts_filtered (" PC: ");
279 switch ((control >> 8) & 3)
282 puts_filtered ("Single Precision (24-bits)\n");
285 puts_filtered ("Reserved\n");
288 puts_filtered ("Double Precision (53-bits)\n");
291 puts_filtered ("Extended Precision (64-bits)\n");
295 puts_filtered (" RC: ");
296 switch ((control >> 10) & 3)
299 puts_filtered ("Round to nearest\n");
302 puts_filtered ("Round down\n");
305 puts_filtered ("Round up\n");
308 puts_filtered ("Round toward zero\n");
313 /* Print out the i387 floating poin state. */
315 i387_float_info (void)
328 fctrl = read_register (FCTRL_REGNUM);
329 fstat = read_register (FSTAT_REGNUM);
330 ftag = read_register (FTAG_REGNUM);
331 fiseg = read_register (FCS_REGNUM);
332 fioff = read_register (FCOFF_REGNUM);
333 foseg = read_register (FDS_REGNUM);
334 fooff = read_register (FDOFF_REGNUM);
335 fop = read_register (FOP_REGNUM);
337 top = ((fstat >> 11) & 7);
339 for (fpreg = 7; fpreg >= 0; fpreg--)
341 unsigned char raw[FPU_REG_RAW_SIZE];
342 int tag = (ftag >> (fpreg * 2)) & 3;
345 printf_filtered ("%sR%d: ", fpreg == top ? "=>" : " ", fpreg);
350 puts_filtered ("Valid ");
353 puts_filtered ("Zero ");
356 puts_filtered ("Special ");
359 puts_filtered ("Empty ");
363 read_register_gen ((fpreg + 8 - top) % 8 + FP0_REGNUM, raw);
365 puts_filtered ("0x");
366 for (i = 9; i >= 0; i--)
367 printf_filtered ("%02x", raw[i]);
370 print_i387_ext (raw);
372 puts_filtered ("\n");
375 puts_filtered ("\n");
377 print_i387_status_word (fstat);
378 print_i387_control_word (fctrl);
379 printf_filtered ("Tag Word: %s\n",
380 local_hex_string_custom (ftag, "04"));
381 printf_filtered ("Instruction Pointer: %s:",
382 local_hex_string_custom (fiseg, "02"));
383 printf_filtered ("%s\n", local_hex_string_custom (fioff, "08"));
384 printf_filtered ("Operand Pointer: %s:",
385 local_hex_string_custom (foseg, "02"));
386 printf_filtered ("%s\n", local_hex_string_custom (fooff, "08"));
387 printf_filtered ("Opcode: %s\n",
388 local_hex_string_custom (fop ? (fop | 0xd800) : 0, "04"));
392 /* FIXME: The functions on this page are used to provide `long double'
393 support for Linux. However, the approach does not seem to be the
394 right one, and we are planning to solve this in a way that should
395 work for all i386 targets. These functions will disappear in the
396 near future, so please don't use them. */
399 i387_extract_floating (PTR addr, int len, DOUBLEST *dretptr)
401 if (len == TARGET_LONG_DOUBLE_BIT / 8)
403 if (HOST_LONG_DOUBLE_FORMAT == TARGET_LONG_DOUBLE_FORMAT)
407 memcpy (dretptr, addr, sizeof (retval));
410 floatformat_to_doublest (TARGET_LONG_DOUBLE_FORMAT, addr, dretptr);
419 i387_store_floating (PTR addr, int len, DOUBLEST val)
421 if (len == TARGET_LONG_DOUBLE_BIT / 8)
423 /* This `if' may be totally stupid. I just put it in here to be
424 absolutely sure I'm preserving the semantics of the code I'm
425 frobbing, while I try to maintain portability boundaries; I
426 don't actually know exactly what it's doing. -JimB, May 1999 */
427 if (HOST_LONG_DOUBLE_FORMAT == TARGET_LONG_DOUBLE_FORMAT)
428 memcpy (addr, &val, sizeof (val));
430 floatformat_from_doublest (TARGET_LONG_DOUBLE_FORMAT, &val, addr);