1 /* Intel 387 floating point stuff.
3 Copyright 1988, 1989, 1991, 1992, 1993, 1994, 1998, 1999, 2000,
4 2001, 2002, 2003 Free Software Foundation, Inc.
6 This file is part of GDB.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330,
21 Boston, MA 02111-1307, USA. */
25 #include "floatformat.h"
33 #include "gdb_assert.h"
34 #include "gdb_string.h"
36 #include "i386-tdep.h"
37 #include "i387-tdep.h"
39 /* Implement the `info float' layout based on the register definitions
42 /* Print the floating point number specified by RAW. */
45 print_i387_value (char *raw
, struct ui_file
*file
)
49 /* Using extract_typed_floating here might affect the representation
50 of certain numbers such as NaNs, even if GDB is running natively.
51 This is fine since our caller already detects such special
52 numbers and we print the hexadecimal representation anyway. */
53 value
= extract_typed_floating (raw
, builtin_type_i387_ext
);
55 /* We try to print 19 digits. The last digit may or may not contain
56 garbage, but we'd better print one too many. We need enough room
57 to print the value, 1 position for the sign, 1 for the decimal
58 point, 19 for the digits and 6 for the exponent adds up to 27. */
59 #ifdef PRINTF_HAS_LONG_DOUBLE
60 fprintf_filtered (file
, " %-+27.19Lg", (long double) value
);
62 fprintf_filtered (file
, " %-+27.19g", (double) value
);
66 /* Print the classification for the register contents RAW. */
69 print_i387_ext (unsigned char *raw
, struct ui_file
*file
)
73 unsigned int exponent
;
74 unsigned long fraction
[2];
77 integer
= raw
[7] & 0x80;
78 exponent
= (((raw
[9] & 0x7f) << 8) | raw
[8]);
79 fraction
[0] = ((raw
[3] << 24) | (raw
[2] << 16) | (raw
[1] << 8) | raw
[0]);
80 fraction
[1] = (((raw
[7] & 0x7f) << 24) | (raw
[6] << 16)
81 | (raw
[5] << 8) | raw
[4]);
83 if (exponent
== 0x7fff && integer
)
85 if (fraction
[0] == 0x00000000 && fraction
[1] == 0x00000000)
87 fprintf_filtered (file
, " %cInf", (sign
? '-' : '+'));
88 else if (sign
&& fraction
[0] == 0x00000000 && fraction
[1] == 0x40000000)
89 /* Real Indefinite (QNaN). */
90 fputs_unfiltered (" Real Indefinite (QNaN)", file
);
91 else if (fraction
[1] & 0x40000000)
93 fputs_filtered (" QNaN", file
);
96 fputs_filtered (" SNaN", file
);
98 else if (exponent
< 0x7fff && exponent
> 0x0000 && integer
)
100 print_i387_value (raw
, file
);
101 else if (exponent
== 0x0000)
103 /* Denormal or zero. */
104 print_i387_value (raw
, file
);
107 /* Pseudo-denormal. */
108 fputs_filtered (" Pseudo-denormal", file
);
109 else if (fraction
[0] || fraction
[1])
111 fputs_filtered (" Denormal", file
);
115 fputs_filtered (" Unsupported", file
);
118 /* Print the status word STATUS. */
121 print_i387_status_word (unsigned int status
, struct ui_file
*file
)
123 fprintf_filtered (file
, "Status Word: %s",
124 local_hex_string_custom (status
, "04"));
125 fputs_filtered (" ", file
);
126 fprintf_filtered (file
, " %s", (status
& 0x0001) ? "IE" : " ");
127 fprintf_filtered (file
, " %s", (status
& 0x0002) ? "DE" : " ");
128 fprintf_filtered (file
, " %s", (status
& 0x0004) ? "ZE" : " ");
129 fprintf_filtered (file
, " %s", (status
& 0x0008) ? "OE" : " ");
130 fprintf_filtered (file
, " %s", (status
& 0x0010) ? "UE" : " ");
131 fprintf_filtered (file
, " %s", (status
& 0x0020) ? "PE" : " ");
132 fputs_filtered (" ", file
);
133 fprintf_filtered (file
, " %s", (status
& 0x0080) ? "ES" : " ");
134 fputs_filtered (" ", file
);
135 fprintf_filtered (file
, " %s", (status
& 0x0040) ? "SF" : " ");
136 fputs_filtered (" ", file
);
137 fprintf_filtered (file
, " %s", (status
& 0x0100) ? "C0" : " ");
138 fprintf_filtered (file
, " %s", (status
& 0x0200) ? "C1" : " ");
139 fprintf_filtered (file
, " %s", (status
& 0x0400) ? "C2" : " ");
140 fprintf_filtered (file
, " %s", (status
& 0x4000) ? "C3" : " ");
142 fputs_filtered ("\n", file
);
144 fprintf_filtered (file
,
145 " TOP: %d\n", ((status
>> 11) & 7));
148 /* Print the control word CONTROL. */
151 print_i387_control_word (unsigned int control
, struct ui_file
*file
)
153 fprintf_filtered (file
, "Control Word: %s",
154 local_hex_string_custom (control
, "04"));
155 fputs_filtered (" ", file
);
156 fprintf_filtered (file
, " %s", (control
& 0x0001) ? "IM" : " ");
157 fprintf_filtered (file
, " %s", (control
& 0x0002) ? "DM" : " ");
158 fprintf_filtered (file
, " %s", (control
& 0x0004) ? "ZM" : " ");
159 fprintf_filtered (file
, " %s", (control
& 0x0008) ? "OM" : " ");
160 fprintf_filtered (file
, " %s", (control
& 0x0010) ? "UM" : " ");
161 fprintf_filtered (file
, " %s", (control
& 0x0020) ? "PM" : " ");
163 fputs_filtered ("\n", file
);
165 fputs_filtered (" PC: ", file
);
166 switch ((control
>> 8) & 3)
169 fputs_filtered ("Single Precision (24-bits)\n", file
);
172 fputs_filtered ("Reserved\n", file
);
175 fputs_filtered ("Double Precision (53-bits)\n", file
);
178 fputs_filtered ("Extended Precision (64-bits)\n", file
);
182 fputs_filtered (" RC: ", file
);
183 switch ((control
>> 10) & 3)
186 fputs_filtered ("Round to nearest\n", file
);
189 fputs_filtered ("Round down\n", file
);
192 fputs_filtered ("Round up\n", file
);
195 fputs_filtered ("Round toward zero\n", file
);
200 /* Print out the i387 floating point state. Note that we ignore FRAME
201 in the code below. That's OK since floating-point registers are
202 never saved on the stack. */
205 i387_print_float_info (struct gdbarch
*gdbarch
, struct ui_file
*file
,
206 struct frame_info
*frame
, const char *args
)
220 fctrl
= get_frame_register_unsigned (frame
, FCTRL_REGNUM
);
221 fstat
= get_frame_register_unsigned (frame
, FSTAT_REGNUM
);
222 ftag
= get_frame_register_unsigned (frame
, FTAG_REGNUM
);
223 fiseg
= get_frame_register_unsigned (frame
, FISEG_REGNUM
);
224 fioff
= get_frame_register_unsigned (frame
, FIOFF_REGNUM
);
225 foseg
= get_frame_register_unsigned (frame
, FOSEG_REGNUM
);
226 fooff
= get_frame_register_unsigned (frame
, FOOFF_REGNUM
);
227 fop
= get_frame_register_unsigned (frame
, FOP_REGNUM
);
229 top
= ((fstat
>> 11) & 7);
231 for (fpreg
= 7; fpreg
>= 0; fpreg
--)
233 unsigned char raw
[FPU_REG_RAW_SIZE
];
234 int tag
= (ftag
>> (fpreg
* 2)) & 3;
237 fprintf_filtered (file
, "%sR%d: ", fpreg
== top
? "=>" : " ", fpreg
);
242 fputs_filtered ("Valid ", file
);
245 fputs_filtered ("Zero ", file
);
248 fputs_filtered ("Special ", file
);
251 fputs_filtered ("Empty ", file
);
255 get_frame_register (frame
, (fpreg
+ 8 - top
) % 8 + FP0_REGNUM
, raw
);
257 fputs_filtered ("0x", file
);
258 for (i
= 9; i
>= 0; i
--)
259 fprintf_filtered (file
, "%02x", raw
[i
]);
262 print_i387_ext (raw
, file
);
264 fputs_filtered ("\n", file
);
267 fputs_filtered ("\n", file
);
269 print_i387_status_word (fstat
, file
);
270 print_i387_control_word (fctrl
, file
);
271 fprintf_filtered (file
, "Tag Word: %s\n",
272 local_hex_string_custom (ftag
, "04"));
273 fprintf_filtered (file
, "Instruction Pointer: %s:",
274 local_hex_string_custom (fiseg
, "02"));
275 fprintf_filtered (file
, "%s\n", local_hex_string_custom (fioff
, "08"));
276 fprintf_filtered (file
, "Operand Pointer: %s:",
277 local_hex_string_custom (foseg
, "02"));
278 fprintf_filtered (file
, "%s\n", local_hex_string_custom (fooff
, "08"));
279 fprintf_filtered (file
, "Opcode: %s\n",
280 local_hex_string_custom (fop
? (fop
| 0xd800) : 0, "04"));
284 /* Read a value of type TYPE from register REGNUM in frame FRAME, and
285 return its contents in TO. */
288 i387_register_to_value (struct frame_info
*frame
, int regnum
,
289 struct type
*type
, void *to
)
291 char from
[I386_MAX_REGISTER_SIZE
];
293 gdb_assert (i386_fp_regnum_p (regnum
));
295 /* We only support floating-point values. */
296 if (TYPE_CODE (type
) != TYPE_CODE_FLT
)
298 warning ("Cannot convert floating-point register value "
299 "to non-floating-point type.");
303 /* Convert to TYPE. This should be a no-op if TYPE is equivalent to
304 the extended floating-point format used by the FPU. */
305 get_frame_register (frame
, regnum
, from
);
306 convert_typed_floating (from
, builtin_type_i387_ext
, to
, type
);
309 /* Write the contents FROM of a value of type TYPE into register
310 REGNUM in frame FRAME. */
313 i387_value_to_register (struct frame_info
*frame
, int regnum
,
314 struct type
*type
, const void *from
)
316 char to
[I386_MAX_REGISTER_SIZE
];
318 gdb_assert (i386_fp_regnum_p (regnum
));
320 /* We only support floating-point values. */
321 if (TYPE_CODE (type
) != TYPE_CODE_FLT
)
323 warning ("Cannot convert non-floating-point type "
324 "to floating-point register value.");
328 /* Convert from TYPE. This should be a no-op if TYPE is equivalent
329 to the extended floating-point format used by the FPU. */
330 convert_typed_floating (from
, type
, to
, builtin_type_i387_ext
);
331 put_frame_register (frame
, regnum
, to
);
335 /* Handle FSAVE and FXSAVE formats. */
337 /* At fsave_offset[REGNUM] you'll find the offset to the location in
338 the data structure used by the "fsave" instruction where GDB
339 register REGNUM is stored. */
341 static int fsave_offset
[] =
343 28 + 0 * FPU_REG_RAW_SIZE
, /* FP0_REGNUM through ... */
344 28 + 1 * FPU_REG_RAW_SIZE
,
345 28 + 2 * FPU_REG_RAW_SIZE
,
346 28 + 3 * FPU_REG_RAW_SIZE
,
347 28 + 4 * FPU_REG_RAW_SIZE
,
348 28 + 5 * FPU_REG_RAW_SIZE
,
349 28 + 6 * FPU_REG_RAW_SIZE
,
350 28 + 7 * FPU_REG_RAW_SIZE
, /* ... FP7_REGNUM. */
351 0, /* FCTRL_REGNUM (16 bits). */
352 4, /* FSTAT_REGNUM (16 bits). */
353 8, /* FTAG_REGNUM (16 bits). */
354 16, /* FISEG_REGNUM (16 bits). */
355 12, /* FIOFF_REGNUM. */
356 24, /* FOSEG_REGNUM. */
357 20, /* FOOFF_REGNUM. */
358 18 /* FOP_REGNUM (bottom 11 bits). */
361 #define FSAVE_ADDR(fsave, regnum) (fsave + fsave_offset[regnum - FP0_REGNUM])
364 /* Fill register REGNUM in GDB's register cache with the appropriate
365 value from *FSAVE. This function masks off any of the reserved
369 i387_supply_fsave (const char *fsave
, int regnum
)
373 for (i
= FP0_REGNUM
; i
< XMM0_REGNUM
; i
++)
374 if (regnum
== -1 || regnum
== i
)
378 supply_register (i
, NULL
);
382 /* Most of the FPU control registers occupy only 16 bits in the
383 fsave area. Give those a special treatment. */
385 && i
!= FIOFF_REGNUM
&& i
!= FOOFF_REGNUM
)
387 unsigned char val
[4];
389 memcpy (val
, FSAVE_ADDR (fsave
, i
), 2);
392 val
[1] &= ((1 << 3) - 1);
393 supply_register (i
, val
);
396 supply_register (i
, FSAVE_ADDR (fsave
, i
));
400 /* Fill register REGNUM (if it is a floating-point register) in *FSAVE
401 with the value in GDB's register cache. If REGNUM is -1, do this
402 for all registers. This function doesn't touch any of the reserved
406 i387_fill_fsave (char *fsave
, int regnum
)
410 for (i
= FP0_REGNUM
; i
< XMM0_REGNUM
; i
++)
411 if (regnum
== -1 || regnum
== i
)
413 /* Most of the FPU control registers occupy only 16 bits in
414 the fsave area. Give those a special treatment. */
416 && i
!= FIOFF_REGNUM
&& i
!= FOOFF_REGNUM
)
418 unsigned char buf
[4];
420 regcache_collect (i
, buf
);
424 /* The opcode occupies only 11 bits. Make sure we
425 don't touch the other bits. */
426 buf
[1] &= ((1 << 3) - 1);
427 buf
[1] |= ((FSAVE_ADDR (fsave
, i
))[1] & ~((1 << 3) - 1));
429 memcpy (FSAVE_ADDR (fsave
, i
), buf
, 2);
432 regcache_collect (i
, FSAVE_ADDR (fsave
, i
));
437 /* At fxsave_offset[REGNUM] you'll find the offset to the location in
438 the data structure used by the "fxsave" instruction where GDB
439 register REGNUM is stored. */
441 static int fxsave_offset
[] =
443 32, /* FP0_REGNUM through ... */
450 144, /* ... FP7_REGNUM (80 bits each). */
451 0, /* FCTRL_REGNUM (16 bits). */
452 2, /* FSTAT_REGNUM (16 bits). */
453 4, /* FTAG_REGNUM (16 bits). */
454 12, /* FISEG_REGNUM (16 bits). */
455 8, /* FIOFF_REGNUM. */
456 20, /* FOSEG_REGNUM (16 bits). */
457 16, /* FOOFF_REGNUM. */
458 6, /* FOP_REGNUM (bottom 11 bits). */
459 160 + 0 * 16, /* XMM0_REGNUM through ... */
474 160 + 15 * 16, /* ... XMM15_REGNUM (128 bits each). */
475 24 /* MXCSR_REGNUM. */
478 /* FIXME: kettenis/20030430: We made an unfortunate choice in putting
479 %mxcsr after the SSE registers %xmm0-%xmm7 instead of before, since
480 it makes supporting the registers %xmm8-%xmm15 on x86-64 a bit
481 involved. Hack around it by explicitly overriding the offset for
484 #define FXSAVE_ADDR(fxsave, regnum) \
485 ((regnum == MXCSR_REGNUM) ? (fxsave + 24) : \
486 (fxsave + fxsave_offset[regnum - FP0_REGNUM]))
488 static int i387_tag (const unsigned char *raw
);
491 /* Fill register REGNUM in GDB's register cache with the appropriate
492 floating-point or SSE register value from *FXSAVE. This function
493 masks off any of the reserved bits in *FXSAVE. */
496 i387_supply_fxsave (const char *fxsave
, int regnum
)
498 int i
, last_regnum
= MXCSR_REGNUM
;
500 if (gdbarch_tdep (current_gdbarch
)->num_xmm_regs
== 0)
501 last_regnum
= FOP_REGNUM
;
503 for (i
= FP0_REGNUM
; i
<= last_regnum
; i
++)
504 if (regnum
== -1 || regnum
== i
)
508 supply_register (i
, NULL
);
512 /* Most of the FPU control registers occupy only 16 bits in
513 the fxsave area. Give those a special treatment. */
514 if (i
>= FPC_REGNUM
&& i
< XMM0_REGNUM
515 && i
!= FIOFF_REGNUM
&& i
!= FOOFF_REGNUM
)
517 unsigned char val
[4];
519 memcpy (val
, FXSAVE_ADDR (fxsave
, i
), 2);
522 val
[1] &= ((1 << 3) - 1);
523 else if (i
== FTAG_REGNUM
)
525 /* The fxsave area contains a simplified version of
526 the tag word. We have to look at the actual 80-bit
527 FP data to recreate the traditional i387 tag word. */
529 unsigned long ftag
= 0;
533 top
= (((FXSAVE_ADDR (fxsave
, FSTAT_REGNUM
))[1] >> 3) & 0x7);
535 for (fpreg
= 7; fpreg
>= 0; fpreg
--)
539 if (val
[0] & (1 << fpreg
))
541 int regnum
= (fpreg
+ 8 - top
) % 8 + FP0_REGNUM
;
542 tag
= i387_tag (FXSAVE_ADDR (fxsave
, regnum
));
547 ftag
|= tag
<< (2 * fpreg
);
549 val
[0] = ftag
& 0xff;
550 val
[1] = (ftag
>> 8) & 0xff;
552 supply_register (i
, val
);
555 supply_register (i
, FXSAVE_ADDR (fxsave
, i
));
559 /* Fill register REGNUM (if it is a floating-point or SSE register) in
560 *FXSAVE with the value in GDB's register cache. If REGNUM is -1, do
561 this for all registers. This function doesn't touch any of the
562 reserved bits in *FXSAVE. */
565 i387_fill_fxsave (char *fxsave
, int regnum
)
567 int i
, last_regnum
= MXCSR_REGNUM
;
569 if (gdbarch_tdep (current_gdbarch
)->num_xmm_regs
== 0)
570 last_regnum
= FOP_REGNUM
;
572 for (i
= FP0_REGNUM
; i
<= last_regnum
; i
++)
573 if (regnum
== -1 || regnum
== i
)
575 /* Most of the FPU control registers occupy only 16 bits in
576 the fxsave area. Give those a special treatment. */
577 if (i
>= FPC_REGNUM
&& i
< XMM0_REGNUM
578 && i
!= FIOFF_REGNUM
&& i
!= FOOFF_REGNUM
)
580 unsigned char buf
[4];
582 regcache_collect (i
, buf
);
586 /* The opcode occupies only 11 bits. Make sure we
587 don't touch the other bits. */
588 buf
[1] &= ((1 << 3) - 1);
589 buf
[1] |= ((FXSAVE_ADDR (fxsave
, i
))[1] & ~((1 << 3) - 1));
591 else if (i
== FTAG_REGNUM
)
593 /* Converting back is much easier. */
598 ftag
= (buf
[1] << 8) | buf
[0];
602 for (fpreg
= 7; fpreg
>= 0; fpreg
--)
604 int tag
= (ftag
>> (fpreg
* 2)) & 3;
607 buf
[0] |= (1 << fpreg
);
610 memcpy (FXSAVE_ADDR (fxsave
, i
), buf
, 2);
613 regcache_collect (i
, FXSAVE_ADDR (fxsave
, i
));
617 /* Recreate the FTW (tag word) valid bits from the 80-bit FP data in
621 i387_tag (const unsigned char *raw
)
624 unsigned int exponent
;
625 unsigned long fraction
[2];
627 integer
= raw
[7] & 0x80;
628 exponent
= (((raw
[9] & 0x7f) << 8) | raw
[8]);
629 fraction
[0] = ((raw
[3] << 24) | (raw
[2] << 16) | (raw
[1] << 8) | raw
[0]);
630 fraction
[1] = (((raw
[7] & 0x7f) << 24) | (raw
[6] << 16)
631 | (raw
[5] << 8) | raw
[4]);
633 if (exponent
== 0x7fff)
638 else if (exponent
== 0x0000)
640 if (fraction
[0] == 0x0000 && fraction
[1] == 0x0000 && !integer
)
This page took 0.04382 seconds and 4 git commands to generate.