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 frame_register_read (frame
, FCTRL_REGNUM
, buf
);
221 fctrl
= extract_unsigned_integer (buf
, 4);
222 frame_register_read (frame
, FSTAT_REGNUM
, buf
);
223 fstat
= extract_unsigned_integer (buf
, 4);
224 frame_register_read (frame
, FTAG_REGNUM
, buf
);
225 ftag
= extract_unsigned_integer (buf
, 4);
226 frame_register_read (frame
, FISEG_REGNUM
, buf
);
227 fiseg
= extract_unsigned_integer (buf
, 4);
228 frame_register_read (frame
, FIOFF_REGNUM
, buf
);
229 fioff
= extract_unsigned_integer (buf
, 4);
230 frame_register_read (frame
, FOSEG_REGNUM
, buf
);
231 foseg
= extract_unsigned_integer (buf
, 4);
232 frame_register_read (frame
, FOOFF_REGNUM
, buf
);
233 fooff
= extract_unsigned_integer (buf
, 4);
234 frame_register_read (frame
, FOP_REGNUM
, buf
);
235 fop
= extract_unsigned_integer (buf
, 4);
237 top
= ((fstat
>> 11) & 7);
239 for (fpreg
= 7; fpreg
>= 0; fpreg
--)
241 unsigned char raw
[FPU_REG_RAW_SIZE
];
242 int tag
= (ftag
>> (fpreg
* 2)) & 3;
245 fprintf_filtered (file
, "%sR%d: ", fpreg
== top
? "=>" : " ", fpreg
);
250 fputs_filtered ("Valid ", file
);
253 fputs_filtered ("Zero ", file
);
256 fputs_filtered ("Special ", file
);
259 fputs_filtered ("Empty ", file
);
263 frame_register_read (frame
, (fpreg
+ 8 - top
) % 8 + FP0_REGNUM
, raw
);
265 fputs_filtered ("0x", file
);
266 for (i
= 9; i
>= 0; i
--)
267 fprintf_filtered (file
, "%02x", raw
[i
]);
270 print_i387_ext (raw
, file
);
272 fputs_filtered ("\n", file
);
275 fputs_filtered ("\n", file
);
277 print_i387_status_word (fstat
, file
);
278 print_i387_control_word (fctrl
, file
);
279 fprintf_filtered (file
, "Tag Word: %s\n",
280 local_hex_string_custom (ftag
, "04"));
281 fprintf_filtered (file
, "Instruction Pointer: %s:",
282 local_hex_string_custom (fiseg
, "02"));
283 fprintf_filtered (file
, "%s\n", local_hex_string_custom (fioff
, "08"));
284 fprintf_filtered (file
, "Operand Pointer: %s:",
285 local_hex_string_custom (foseg
, "02"));
286 fprintf_filtered (file
, "%s\n", local_hex_string_custom (fooff
, "08"));
287 fprintf_filtered (file
, "Opcode: %s\n",
288 local_hex_string_custom (fop
? (fop
| 0xd800) : 0, "04"));
292 /* Read a value of type TYPE from register REGNUM in frame FRAME, and
293 return its contents in TO. */
296 i387_register_to_value (struct frame_info
*frame
, int regnum
,
297 struct type
*type
, void *to
)
299 char from
[I386_MAX_REGISTER_SIZE
];
301 gdb_assert (i386_fp_regnum_p (regnum
));
303 /* We only support floating-point values. */
304 if (TYPE_CODE (type
) != TYPE_CODE_FLT
)
306 warning ("Cannot convert floating-point register value "
307 "to non-floating-point type.");
311 /* Convert to TYPE. This should be a no-op if TYPE is equivalent to
312 the extended floating-point format used by the FPU. */
313 frame_read_register (frame
, regnum
, from
);
314 convert_typed_floating (from
, builtin_type_i387_ext
, to
, type
);
317 /* Write the contents FROM of a value of type TYPE into register
318 REGNUM in frame FRAME. */
321 i387_value_to_register (struct frame_info
*frame
, int regnum
,
322 struct type
*type
, const void *from
)
324 char to
[I386_MAX_REGISTER_SIZE
];
326 gdb_assert (i386_fp_regnum_p (regnum
));
328 /* We only support floating-point values. */
329 if (TYPE_CODE (type
) != TYPE_CODE_FLT
)
331 warning ("Cannot convert non-floating-point type "
332 "to floating-point register value.");
336 /* Convert from TYPE. This should be a no-op if TYPE is equivalent
337 to the extended floating-point format used by the FPU. */
338 convert_typed_floating (from
, type
, to
, builtin_type_i387_ext
);
339 put_frame_register (frame
, regnum
, to
);
343 /* Handle FSAVE and FXSAVE formats. */
345 /* At fsave_offset[REGNUM] you'll find the offset to the location in
346 the data structure used by the "fsave" instruction where GDB
347 register REGNUM is stored. */
349 static int fsave_offset
[] =
351 28 + 0 * FPU_REG_RAW_SIZE
, /* FP0_REGNUM through ... */
352 28 + 1 * FPU_REG_RAW_SIZE
,
353 28 + 2 * FPU_REG_RAW_SIZE
,
354 28 + 3 * FPU_REG_RAW_SIZE
,
355 28 + 4 * FPU_REG_RAW_SIZE
,
356 28 + 5 * FPU_REG_RAW_SIZE
,
357 28 + 6 * FPU_REG_RAW_SIZE
,
358 28 + 7 * FPU_REG_RAW_SIZE
, /* ... FP7_REGNUM. */
359 0, /* FCTRL_REGNUM (16 bits). */
360 4, /* FSTAT_REGNUM (16 bits). */
361 8, /* FTAG_REGNUM (16 bits). */
362 16, /* FISEG_REGNUM (16 bits). */
363 12, /* FIOFF_REGNUM. */
364 24, /* FOSEG_REGNUM. */
365 20, /* FOOFF_REGNUM. */
366 18 /* FOP_REGNUM (bottom 11 bits). */
369 #define FSAVE_ADDR(fsave, regnum) (fsave + fsave_offset[regnum - FP0_REGNUM])
372 /* Fill register REGNUM in GDB's register array with the appropriate
373 value from *FSAVE. This function masks off any of the reserved
377 i387_supply_register (int regnum
, char *fsave
)
381 supply_register (regnum
, NULL
);
385 /* Most of the FPU control registers occupy only 16 bits in
386 the fsave area. Give those a special treatment. */
387 if (regnum
>= FPC_REGNUM
388 && regnum
!= FIOFF_REGNUM
&& regnum
!= FOOFF_REGNUM
)
390 unsigned char val
[4];
392 memcpy (val
, FSAVE_ADDR (fsave
, regnum
), 2);
394 if (regnum
== FOP_REGNUM
)
395 val
[1] &= ((1 << 3) - 1);
396 supply_register (regnum
, val
);
399 supply_register (regnum
, FSAVE_ADDR (fsave
, regnum
));
402 /* Fill GDB's register array with the floating-point register values
403 in *FSAVE. This function masks off any of the reserved
407 i387_supply_fsave (char *fsave
)
411 for (i
= FP0_REGNUM
; i
< XMM0_REGNUM
; i
++)
412 i387_supply_register (i
, fsave
);
415 /* Fill register REGNUM (if it is a floating-point register) in *FSAVE
416 with the value in GDB's register array. If REGNUM is -1, do this
417 for all registers. This function doesn't touch any of the reserved
421 i387_fill_fsave (char *fsave
, int regnum
)
425 for (i
= FP0_REGNUM
; i
< XMM0_REGNUM
; i
++)
426 if (regnum
== -1 || regnum
== i
)
428 /* Most of the FPU control registers occupy only 16 bits in
429 the fsave area. Give those a special treatment. */
431 && i
!= FIOFF_REGNUM
&& i
!= FOOFF_REGNUM
)
433 unsigned char buf
[4];
435 regcache_collect (i
, buf
);
439 /* The opcode occupies only 11 bits. Make sure we
440 don't touch the other bits. */
441 buf
[1] &= ((1 << 3) - 1);
442 buf
[1] |= ((FSAVE_ADDR (fsave
, i
))[1] & ~((1 << 3) - 1));
444 memcpy (FSAVE_ADDR (fsave
, i
), buf
, 2);
447 regcache_collect (i
, FSAVE_ADDR (fsave
, i
));
452 /* At fxsave_offset[REGNUM] you'll find the offset to the location in
453 the data structure used by the "fxsave" instruction where GDB
454 register REGNUM is stored. */
456 static int fxsave_offset
[] =
458 32, /* FP0_REGNUM through ... */
465 144, /* ... FP7_REGNUM (80 bits each). */
466 0, /* FCTRL_REGNUM (16 bits). */
467 2, /* FSTAT_REGNUM (16 bits). */
468 4, /* FTAG_REGNUM (16 bits). */
469 12, /* FISEG_REGNUM (16 bits). */
470 8, /* FIOFF_REGNUM. */
471 20, /* FOSEG_REGNUM (16 bits). */
472 16, /* FOOFF_REGNUM. */
473 6, /* FOP_REGNUM (bottom 11 bits). */
474 160 + 0 * 16, /* XMM0_REGNUM through ... */
489 160 + 15 * 16, /* ... XMM15_REGNUM (128 bits each). */
490 24 /* MXCSR_REGNUM. */
493 /* FIXME: kettenis/20030430: We made an unfortunate choice in putting
494 %mxcsr after the SSE registers %xmm0-%xmm7 instead of before, since
495 it makes supporting the registers %xmm8-%xmm15 on x86-64 a bit
496 involved. Hack around it by explicitly overriding the offset for
499 #define FXSAVE_ADDR(fxsave, regnum) \
500 ((regnum == MXCSR_REGNUM) ? (fxsave + 24) : \
501 (fxsave + fxsave_offset[regnum - FP0_REGNUM]))
503 static int i387_tag (unsigned char *raw
);
506 /* Fill GDB's register array with the floating-point and SSE register
507 values in *FXSAVE. This function masks off any of the reserved
511 i387_supply_fxsave (char *fxsave
)
513 int i
, last_regnum
= MXCSR_REGNUM
;
515 if (gdbarch_tdep (current_gdbarch
)->num_xmm_regs
== 0)
516 last_regnum
= FOP_REGNUM
;
518 for (i
= FP0_REGNUM
; i
<= last_regnum
; i
++)
522 supply_register (i
, NULL
);
526 /* Most of the FPU control registers occupy only 16 bits in
527 the fxsave area. Give those a special treatment. */
528 if (i
>= FPC_REGNUM
&& i
< XMM0_REGNUM
529 && i
!= FIOFF_REGNUM
&& i
!= FOOFF_REGNUM
)
531 unsigned char val
[4];
533 memcpy (val
, FXSAVE_ADDR (fxsave
, i
), 2);
536 val
[1] &= ((1 << 3) - 1);
537 else if (i
== FTAG_REGNUM
)
539 /* The fxsave area contains a simplified version of the
540 tag word. We have to look at the actual 80-bit FP
541 data to recreate the traditional i387 tag word. */
543 unsigned long ftag
= 0;
547 top
= (((FXSAVE_ADDR (fxsave
, FSTAT_REGNUM
))[1] >> 3) & 0x7);
549 for (fpreg
= 7; fpreg
>= 0; fpreg
--)
553 if (val
[0] & (1 << fpreg
))
555 int regnum
= (fpreg
+ 8 - top
) % 8 + FP0_REGNUM
;
556 tag
= i387_tag (FXSAVE_ADDR (fxsave
, regnum
));
561 ftag
|= tag
<< (2 * fpreg
);
563 val
[0] = ftag
& 0xff;
564 val
[1] = (ftag
>> 8) & 0xff;
566 supply_register (i
, val
);
569 supply_register (i
, FXSAVE_ADDR (fxsave
, i
));
573 /* Fill register REGNUM (if it is a floating-point or SSE register) in
574 *FXSAVE with the value in GDB's register array. If REGNUM is -1, do
575 this for all registers. This function doesn't touch any of the
576 reserved bits in *FXSAVE. */
579 i387_fill_fxsave (char *fxsave
, int regnum
)
581 int i
, last_regnum
= MXCSR_REGNUM
;
583 if (gdbarch_tdep (current_gdbarch
)->num_xmm_regs
== 0)
584 last_regnum
= FOP_REGNUM
;
586 for (i
= FP0_REGNUM
; i
<= last_regnum
; i
++)
587 if (regnum
== -1 || regnum
== i
)
589 /* Most of the FPU control registers occupy only 16 bits in
590 the fxsave area. Give those a special treatment. */
591 if (i
>= FPC_REGNUM
&& i
< XMM0_REGNUM
592 && i
!= FIOFF_REGNUM
&& i
!= FOOFF_REGNUM
)
594 unsigned char buf
[4];
596 regcache_collect (i
, buf
);
600 /* The opcode occupies only 11 bits. Make sure we
601 don't touch the other bits. */
602 buf
[1] &= ((1 << 3) - 1);
603 buf
[1] |= ((FXSAVE_ADDR (fxsave
, i
))[1] & ~((1 << 3) - 1));
605 else if (i
== FTAG_REGNUM
)
607 /* Converting back is much easier. */
612 ftag
= (buf
[1] << 8) | buf
[0];
616 for (fpreg
= 7; fpreg
>= 0; fpreg
--)
618 int tag
= (ftag
>> (fpreg
* 2)) & 3;
621 buf
[0] |= (1 << fpreg
);
624 memcpy (FXSAVE_ADDR (fxsave
, i
), buf
, 2);
627 regcache_collect (i
, FXSAVE_ADDR (fxsave
, i
));
631 /* Recreate the FTW (tag word) valid bits from the 80-bit FP data in
635 i387_tag (unsigned char *raw
)
638 unsigned int exponent
;
639 unsigned long fraction
[2];
641 integer
= raw
[7] & 0x80;
642 exponent
= (((raw
[9] & 0x7f) << 8) | raw
[8]);
643 fraction
[0] = ((raw
[3] << 24) | (raw
[2] << 16) | (raw
[1] << 8) | raw
[0]);
644 fraction
[1] = (((raw
[7] & 0x7f) << 24) | (raw
[6] << 16)
645 | (raw
[5] << 8) | raw
[4]);
647 if (exponent
== 0x7fff)
652 else if (exponent
== 0x0000)
654 if (fraction
[0] == 0x0000 && fraction
[1] == 0x0000 && !integer
)
This page took 0.060965 seconds and 4 git commands to generate.