* i386-tdep.h: Put opaque declarations in alphabetical
[binutils-gdb.git] / gdb / i387-tdep.c
1 /* Intel 387 floating point stuff.
2
3 Copyright 1988, 1989, 1991, 1992, 1993, 1994, 1998, 1999, 2000,
4 2001, 2002, 2003 Free Software Foundation, Inc.
5
6 This file is part of GDB.
7
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.
12
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.
17
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. */
22
23 #include "defs.h"
24 #include "doublest.h"
25 #include "floatformat.h"
26 #include "frame.h"
27 #include "gdbcore.h"
28 #include "inferior.h"
29 #include "language.h"
30 #include "regcache.h"
31 #include "value.h"
32
33 #include "gdb_assert.h"
34 #include "gdb_string.h"
35
36 #include "i386-tdep.h"
37 #include "i387-tdep.h"
38
39 /* Implement the `info float' layout based on the register definitions
40 in `tm-i386.h'. */
41
42 /* Print the floating point number specified by RAW. */
43
44 static void
45 print_i387_value (char *raw, struct ui_file *file)
46 {
47 DOUBLEST value;
48
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);
54
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);
61 #else
62 fprintf_filtered (file, " %-+27.19g", (double) value);
63 #endif
64 }
65
66 /* Print the classification for the register contents RAW. */
67
68 static void
69 print_i387_ext (unsigned char *raw, struct ui_file *file)
70 {
71 int sign;
72 int integer;
73 unsigned int exponent;
74 unsigned long fraction[2];
75
76 sign = raw[9] & 0x80;
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]);
82
83 if (exponent == 0x7fff && integer)
84 {
85 if (fraction[0] == 0x00000000 && fraction[1] == 0x00000000)
86 /* Infinity. */
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)
92 /* QNaN. */
93 fputs_filtered (" QNaN", file);
94 else
95 /* SNaN. */
96 fputs_filtered (" SNaN", file);
97 }
98 else if (exponent < 0x7fff && exponent > 0x0000 && integer)
99 /* Normal. */
100 print_i387_value (raw, file);
101 else if (exponent == 0x0000)
102 {
103 /* Denormal or zero. */
104 print_i387_value (raw, file);
105
106 if (integer)
107 /* Pseudo-denormal. */
108 fputs_filtered (" Pseudo-denormal", file);
109 else if (fraction[0] || fraction[1])
110 /* Denormal. */
111 fputs_filtered (" Denormal", file);
112 }
113 else
114 /* Unsupported. */
115 fputs_filtered (" Unsupported", file);
116 }
117
118 /* Print the status word STATUS. */
119
120 static void
121 print_i387_status_word (unsigned int status, struct ui_file *file)
122 {
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" : " ");
141
142 fputs_filtered ("\n", file);
143
144 fprintf_filtered (file,
145 " TOP: %d\n", ((status >> 11) & 7));
146 }
147
148 /* Print the control word CONTROL. */
149
150 static void
151 print_i387_control_word (unsigned int control, struct ui_file *file)
152 {
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" : " ");
162
163 fputs_filtered ("\n", file);
164
165 fputs_filtered (" PC: ", file);
166 switch ((control >> 8) & 3)
167 {
168 case 0:
169 fputs_filtered ("Single Precision (24-bits)\n", file);
170 break;
171 case 1:
172 fputs_filtered ("Reserved\n", file);
173 break;
174 case 2:
175 fputs_filtered ("Double Precision (53-bits)\n", file);
176 break;
177 case 3:
178 fputs_filtered ("Extended Precision (64-bits)\n", file);
179 break;
180 }
181
182 fputs_filtered (" RC: ", file);
183 switch ((control >> 10) & 3)
184 {
185 case 0:
186 fputs_filtered ("Round to nearest\n", file);
187 break;
188 case 1:
189 fputs_filtered ("Round down\n", file);
190 break;
191 case 2:
192 fputs_filtered ("Round up\n", file);
193 break;
194 case 3:
195 fputs_filtered ("Round toward zero\n", file);
196 break;
197 }
198 }
199
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. */
203
204 void
205 i387_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
206 struct frame_info *frame, const char *args)
207 {
208 struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (frame));
209 char buf[4];
210 ULONGEST fctrl;
211 ULONGEST fstat;
212 ULONGEST ftag;
213 ULONGEST fiseg;
214 ULONGEST fioff;
215 ULONGEST foseg;
216 ULONGEST fooff;
217 ULONGEST fop;
218 int fpreg;
219 int top;
220
221 gdb_assert (gdbarch == get_frame_arch (frame));
222
223 /* Define I387_ST0_REGNUM such that we use the proper definitions
224 for FRAME's architecture. */
225 #define I387_ST0_REGNUM tdep->st0_regnum
226
227 fctrl = get_frame_register_unsigned (frame, I387_FCTRL_REGNUM);
228 fstat = get_frame_register_unsigned (frame, I387_FSTAT_REGNUM);
229 ftag = get_frame_register_unsigned (frame, I387_FTAG_REGNUM);
230 fiseg = get_frame_register_unsigned (frame, I387_FISEG_REGNUM);
231 fioff = get_frame_register_unsigned (frame, I387_FIOFF_REGNUM);
232 foseg = get_frame_register_unsigned (frame, I387_FOSEG_REGNUM);
233 fooff = get_frame_register_unsigned (frame, I387_FOOFF_REGNUM);
234 fop = get_frame_register_unsigned (frame, I387_FOP_REGNUM);
235
236 top = ((fstat >> 11) & 7);
237
238 for (fpreg = 7; fpreg >= 0; fpreg--)
239 {
240 unsigned char raw[I386_MAX_REGISTER_SIZE];
241 int tag = (ftag >> (fpreg * 2)) & 3;
242 int i;
243
244 fprintf_filtered (file, "%sR%d: ", fpreg == top ? "=>" : " ", fpreg);
245
246 switch (tag)
247 {
248 case 0:
249 fputs_filtered ("Valid ", file);
250 break;
251 case 1:
252 fputs_filtered ("Zero ", file);
253 break;
254 case 2:
255 fputs_filtered ("Special ", file);
256 break;
257 case 3:
258 fputs_filtered ("Empty ", file);
259 break;
260 }
261
262 get_frame_register (frame, (fpreg + 8 - top) % 8 + I387_ST0_REGNUM, raw);
263
264 fputs_filtered ("0x", file);
265 for (i = 9; i >= 0; i--)
266 fprintf_filtered (file, "%02x", raw[i]);
267
268 if (tag != 3)
269 print_i387_ext (raw, file);
270
271 fputs_filtered ("\n", file);
272 }
273
274 fputs_filtered ("\n", file);
275
276 print_i387_status_word (fstat, file);
277 print_i387_control_word (fctrl, file);
278 fprintf_filtered (file, "Tag Word: %s\n",
279 local_hex_string_custom (ftag, "04"));
280 fprintf_filtered (file, "Instruction Pointer: %s:",
281 local_hex_string_custom (fiseg, "02"));
282 fprintf_filtered (file, "%s\n", local_hex_string_custom (fioff, "08"));
283 fprintf_filtered (file, "Operand Pointer: %s:",
284 local_hex_string_custom (foseg, "02"));
285 fprintf_filtered (file, "%s\n", local_hex_string_custom (fooff, "08"));
286 fprintf_filtered (file, "Opcode: %s\n",
287 local_hex_string_custom (fop ? (fop | 0xd800) : 0, "04"));
288
289 #undef I387_ST0_REGNUM
290 }
291 \f
292
293 /* Read a value of type TYPE from register REGNUM in frame FRAME, and
294 return its contents in TO. */
295
296 void
297 i387_register_to_value (struct frame_info *frame, int regnum,
298 struct type *type, void *to)
299 {
300 char from[I386_MAX_REGISTER_SIZE];
301
302 gdb_assert (i386_fp_regnum_p (regnum));
303
304 /* We only support floating-point values. */
305 if (TYPE_CODE (type) != TYPE_CODE_FLT)
306 {
307 warning ("Cannot convert floating-point register value "
308 "to non-floating-point type.");
309 return;
310 }
311
312 /* Convert to TYPE. This should be a no-op if TYPE is equivalent to
313 the extended floating-point format used by the FPU. */
314 get_frame_register (frame, regnum, from);
315 convert_typed_floating (from, builtin_type_i387_ext, to, type);
316 }
317
318 /* Write the contents FROM of a value of type TYPE into register
319 REGNUM in frame FRAME. */
320
321 void
322 i387_value_to_register (struct frame_info *frame, int regnum,
323 struct type *type, const void *from)
324 {
325 char to[I386_MAX_REGISTER_SIZE];
326
327 gdb_assert (i386_fp_regnum_p (regnum));
328
329 /* We only support floating-point values. */
330 if (TYPE_CODE (type) != TYPE_CODE_FLT)
331 {
332 warning ("Cannot convert non-floating-point type "
333 "to floating-point register value.");
334 return;
335 }
336
337 /* Convert from TYPE. This should be a no-op if TYPE is equivalent
338 to the extended floating-point format used by the FPU. */
339 convert_typed_floating (from, type, to, builtin_type_i387_ext);
340 put_frame_register (frame, regnum, to);
341 }
342 \f
343 \f
344
345 /* Handle FSAVE and FXSAVE formats. */
346
347 /* FIXME: kettenis/20030927: The functions below should accept a
348 `regcache' argument, but I don't want to change the function
349 signature just yet. There's some band-aid in the functions below
350 in the form of the `regcache' local variables. This will ease the
351 transition later on. */
352
353 /* At fsave_offset[REGNUM] you'll find the offset to the location in
354 the data structure used by the "fsave" instruction where GDB
355 register REGNUM is stored. */
356
357 static int fsave_offset[] =
358 {
359 28 + 0 * 10, /* %st(0) ... */
360 28 + 1 * 10,
361 28 + 2 * 10,
362 28 + 3 * 10,
363 28 + 4 * 10,
364 28 + 5 * 10,
365 28 + 6 * 10,
366 28 + 7 * 10, /* ... %st(7). */
367 0, /* `fctrl' (16 bits). */
368 4, /* `fstat' (16 bits). */
369 8, /* `ftag' (16 bits). */
370 16, /* `fiseg' (16 bits). */
371 12, /* `fioff'. */
372 24, /* `foseg' (16 bits). */
373 20, /* `fooff'. */
374 18 /* `fop' (bottom 11 bits). */
375 };
376
377 #define FSAVE_ADDR(fsave, regnum) \
378 (fsave + fsave_offset[regnum - I387_ST0_REGNUM])
379 \f
380
381 /* Fill register REGNUM in GDB's register cache with the appropriate
382 value from *FSAVE. This function masks off any of the reserved
383 bits in *FSAVE. */
384
385 void
386 i387_supply_fsave (const void *fsave, int regnum)
387 {
388 struct regcache *regcache = current_regcache;
389 struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
390 const char *regs = fsave;
391 int i;
392
393 gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
394
395 /* Define I387_ST0_REGNUM such that we use the proper definitions
396 for REGCACHE's architecture. */
397 #define I387_ST0_REGNUM tdep->st0_regnum
398
399 for (i = I387_ST0_REGNUM; i < I387_XMM0_REGNUM; i++)
400 if (regnum == -1 || regnum == i)
401 {
402 if (fsave == NULL)
403 {
404 regcache_raw_supply (regcache, i, NULL);
405 continue;
406 }
407
408 /* Most of the FPU control registers occupy only 16 bits in the
409 fsave area. Give those a special treatment. */
410 if (i >= I387_FCTRL_REGNUM
411 && i != I387_FIOFF_REGNUM && i != I387_FOOFF_REGNUM)
412 {
413 unsigned char val[4];
414
415 memcpy (val, FSAVE_ADDR (regs, i), 2);
416 val[2] = val[3] = 0;
417 if (i == I387_FOP_REGNUM)
418 val[1] &= ((1 << 3) - 1);
419 regcache_raw_supply (regcache, i, val);
420 }
421 else
422 regcache_raw_supply (regcache, i, FSAVE_ADDR (regs, i));
423 }
424 #undef I387_ST0_REGNUM
425 }
426
427 /* Fill register REGNUM (if it is a floating-point register) in *FSAVE
428 with the value in GDB's register cache. If REGNUM is -1, do this
429 for all registers. This function doesn't touch any of the reserved
430 bits in *FSAVE. */
431
432 void
433 i387_fill_fsave (void *fsave, int regnum)
434 {
435 struct regcache *regcache = current_regcache;
436 struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
437 char *regs = fsave;
438 int i;
439
440 gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
441
442 /* Define I387_ST0_REGNUM such that we use the proper definitions
443 for REGCACHE's architecture. */
444 #define I387_ST0_REGNUM tdep->st0_regnum
445
446 for (i = I387_ST0_REGNUM; i < I387_XMM0_REGNUM; i++)
447 if (regnum == -1 || regnum == i)
448 {
449 /* Most of the FPU control registers occupy only 16 bits in
450 the fsave area. Give those a special treatment. */
451 if (i >= I387_FCTRL_REGNUM
452 && i != I387_FIOFF_REGNUM && i != I387_FOOFF_REGNUM)
453 {
454 unsigned char buf[4];
455
456 regcache_raw_collect (regcache, i, buf);
457
458 if (i == I387_FOP_REGNUM)
459 {
460 /* The opcode occupies only 11 bits. Make sure we
461 don't touch the other bits. */
462 buf[1] &= ((1 << 3) - 1);
463 buf[1] |= ((FSAVE_ADDR (regs, i))[1] & ~((1 << 3) - 1));
464 }
465 memcpy (FSAVE_ADDR (regs, i), buf, 2);
466 }
467 else
468 regcache_raw_collect (regcache, i, FSAVE_ADDR (regs, i));
469 }
470 #undef I387_ST0_REGNUM
471 }
472 \f
473
474 /* At fxsave_offset[REGNUM] you'll find the offset to the location in
475 the data structure used by the "fxsave" instruction where GDB
476 register REGNUM is stored. */
477
478 static int fxsave_offset[] =
479 {
480 32, /* %st(0) through ... */
481 48,
482 64,
483 80,
484 96,
485 112,
486 128,
487 144, /* ... %st(7) (80 bits each). */
488 0, /* `fctrl' (16 bits). */
489 2, /* `fstat' (16 bits). */
490 4, /* `ftag' (16 bits). */
491 12, /* `fiseg' (16 bits). */
492 8, /* `fioff'. */
493 20, /* `foseg' (16 bits). */
494 16, /* `fooff'. */
495 6, /* `fop' (bottom 11 bits). */
496 160 + 0 * 16, /* %xmm0 through ... */
497 160 + 1 * 16,
498 160 + 2 * 16,
499 160 + 3 * 16,
500 160 + 4 * 16,
501 160 + 5 * 16,
502 160 + 6 * 16,
503 160 + 7 * 16,
504 160 + 8 * 16,
505 160 + 9 * 16,
506 160 + 10 * 16,
507 160 + 11 * 16,
508 160 + 12 * 16,
509 160 + 13 * 16,
510 160 + 14 * 16,
511 160 + 15 * 16, /* ... %xmm15 (128 bits each). */
512 };
513
514 #define FXSAVE_ADDR(fxsave, regnum) \
515 (fxsave + fxsave_offset[regnum - I387_ST0_REGNUM])
516
517 /* We made an unfortunate choice in putting %mxcsr after the SSE
518 registers %xmm0-%xmm7 instead of before, since it makes supporting
519 the registers %xmm8-%xmm15 on AMD64 a bit involved. Therefore we
520 don't include the offset for %mxcsr here above. */
521
522 #define FXSAVE_MXCSR_ADDR(fxsave) (fxsave + 24)
523
524 static int i387_tag (const unsigned char *raw);
525 \f
526
527 /* Fill register REGNUM in GDB's register cache with the appropriate
528 floating-point or SSE register value from *FXSAVE. This function
529 masks off any of the reserved bits in *FXSAVE. */
530
531 void
532 i387_supply_fxsave (const void *fxsave, int regnum)
533 {
534 struct regcache *regcache = current_regcache;
535 struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
536 const char *regs = fxsave;
537 int i;
538
539 gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
540 gdb_assert (tdep->num_xmm_regs > 0);
541
542 /* Define I387_ST0_REGNUM and I387_NUM_XMM_REGS such that we use the
543 proper definitions for REGCACHE's architecture. */
544
545 #define I387_ST0_REGNUM tdep->st0_regnum
546 #define I387_NUM_XMM_REGS tdep->num_xmm_regs
547
548 for (i = I387_ST0_REGNUM; i < I387_MXCSR_REGNUM; i++)
549 if (regnum == -1 || regnum == i)
550 {
551 if (regs == NULL)
552 {
553 regcache_raw_supply (regcache, i, NULL);
554 continue;
555 }
556
557 /* Most of the FPU control registers occupy only 16 bits in
558 the fxsave area. Give those a special treatment. */
559 if (i >= I387_FCTRL_REGNUM && i < I387_XMM0_REGNUM
560 && i != I387_FIOFF_REGNUM && i != I387_FOOFF_REGNUM)
561 {
562 unsigned char val[4];
563
564 memcpy (val, FXSAVE_ADDR (regs, i), 2);
565 val[2] = val[3] = 0;
566 if (i == I387_FOP_REGNUM)
567 val[1] &= ((1 << 3) - 1);
568 else if (i== I387_FTAG_REGNUM)
569 {
570 /* The fxsave area contains a simplified version of
571 the tag word. We have to look at the actual 80-bit
572 FP data to recreate the traditional i387 tag word. */
573
574 unsigned long ftag = 0;
575 int fpreg;
576 int top;
577
578 top = ((FXSAVE_ADDR (regs, I387_FSTAT_REGNUM))[1] >> 3);
579 top &= 0x7;
580
581 for (fpreg = 7; fpreg >= 0; fpreg--)
582 {
583 int tag;
584
585 if (val[0] & (1 << fpreg))
586 {
587 int regnum = (fpreg + 8 - top) % 8 + I387_ST0_REGNUM;
588 tag = i387_tag (FXSAVE_ADDR (regs, regnum));
589 }
590 else
591 tag = 3; /* Empty */
592
593 ftag |= tag << (2 * fpreg);
594 }
595 val[0] = ftag & 0xff;
596 val[1] = (ftag >> 8) & 0xff;
597 }
598 regcache_raw_supply (regcache, i, val);
599 }
600 else
601 regcache_raw_supply (regcache, i, FXSAVE_ADDR (regs, i));
602 }
603
604 if (regnum == I387_MXCSR_REGNUM || regnum == -1)
605 {
606 if (regs == NULL)
607 regcache_raw_supply (regcache, I387_MXCSR_REGNUM, NULL);
608 else
609 regcache_raw_supply (regcache, I387_MXCSR_REGNUM,
610 FXSAVE_MXCSR_ADDR (regs));
611 }
612
613 #undef I387_ST0_REGNUM
614 #undef I387_NUM_XMM_REGS
615 }
616
617 /* Fill register REGNUM (if it is a floating-point or SSE register) in
618 *FXSAVE with the value in GDB's register cache. If REGNUM is -1, do
619 this for all registers. This function doesn't touch any of the
620 reserved bits in *FXSAVE. */
621
622 void
623 i387_fill_fxsave (void *fxsave, int regnum)
624 {
625 struct regcache *regcache = current_regcache;
626 struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
627 char *regs = fxsave;
628 int i;
629
630 gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
631 gdb_assert (tdep->num_xmm_regs > 0);
632
633 /* Define I387_ST0_REGNUM and I387_NUM_XMM_REGS such that we use the
634 proper definitions for REGCACHE's architecture. */
635
636 #define I387_ST0_REGNUM tdep->st0_regnum
637 #define I387_NUM_XMM_REGS tdep->num_xmm_regs
638
639 for (i = I387_ST0_REGNUM; i < I387_MXCSR_REGNUM; i++)
640 if (regnum == -1 || regnum == i)
641 {
642 /* Most of the FPU control registers occupy only 16 bits in
643 the fxsave area. Give those a special treatment. */
644 if (i >= I387_FCTRL_REGNUM && i < I387_XMM0_REGNUM
645 && i != I387_FIOFF_REGNUM && i != I387_FOOFF_REGNUM)
646 {
647 unsigned char buf[4];
648
649 regcache_raw_collect (regcache, i, buf);
650
651 if (i == I387_FOP_REGNUM)
652 {
653 /* The opcode occupies only 11 bits. Make sure we
654 don't touch the other bits. */
655 buf[1] &= ((1 << 3) - 1);
656 buf[1] |= ((FXSAVE_ADDR (regs, i))[1] & ~((1 << 3) - 1));
657 }
658 else if (i == I387_FTAG_REGNUM)
659 {
660 /* Converting back is much easier. */
661
662 unsigned short ftag;
663 int fpreg;
664
665 ftag = (buf[1] << 8) | buf[0];
666 buf[0] = 0;
667 buf[1] = 0;
668
669 for (fpreg = 7; fpreg >= 0; fpreg--)
670 {
671 int tag = (ftag >> (fpreg * 2)) & 3;
672
673 if (tag != 3)
674 buf[0] |= (1 << fpreg);
675 }
676 }
677 memcpy (FXSAVE_ADDR (regs, i), buf, 2);
678 }
679 else
680 regcache_raw_collect (regcache, i, FXSAVE_ADDR (regs, i));
681 }
682
683 if (regnum == I387_MXCSR_REGNUM || regnum == -1)
684 regcache_raw_collect (regcache, I387_MXCSR_REGNUM,
685 FXSAVE_MXCSR_ADDR (regs));
686
687 #undef I387_ST0_REGNUM
688 #undef I387_NUM_XMM_REGS
689 }
690
691 /* Recreate the FTW (tag word) valid bits from the 80-bit FP data in
692 *RAW. */
693
694 static int
695 i387_tag (const unsigned char *raw)
696 {
697 int integer;
698 unsigned int exponent;
699 unsigned long fraction[2];
700
701 integer = raw[7] & 0x80;
702 exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
703 fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
704 fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
705 | (raw[5] << 8) | raw[4]);
706
707 if (exponent == 0x7fff)
708 {
709 /* Special. */
710 return (2);
711 }
712 else if (exponent == 0x0000)
713 {
714 if (fraction[0] == 0x0000 && fraction[1] == 0x0000 && !integer)
715 {
716 /* Zero. */
717 return (1);
718 }
719 else
720 {
721 /* Special. */
722 return (2);
723 }
724 }
725 else
726 {
727 if (integer)
728 {
729 /* Valid. */
730 return (0);
731 }
732 else
733 {
734 /* Special. */
735 return (2);
736 }
737 }
738 }