* i386-tdep.c (i386_register_to_value, i386_value_to_register):
[deliverable/binutils-gdb.git] / gdb / i387-tdep.c
CommitLineData
c906108c 1/* Intel 387 floating point stuff.
38edeab8 2
dff95cc7 3 Copyright 1988, 1989, 1991, 1992, 1993, 1994, 1998, 1999, 2000,
38edeab8 4 2001, 2002, 2003 Free Software Foundation, Inc.
c906108c 5
c5aa993b 6 This file is part of GDB.
c906108c 7
c5aa993b
JM
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.
c906108c 12
c5aa993b
JM
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.
c906108c 17
c5aa993b
JM
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. */
c906108c
SS
22
23#include "defs.h"
24#include "frame.h"
25#include "inferior.h"
26#include "language.h"
d4f3574e 27#include "value.h"
c906108c
SS
28#include "gdbcore.h"
29#include "floatformat.h"
4e052eda 30#include "regcache.h"
d0df8472 31#include "gdb_assert.h"
309367d4 32#include "gdb_string.h"
d16aafd8 33#include "doublest.h"
c906108c 34
9a82579f 35#include "i386-tdep.h"
42c466d7 36#include "i387-tdep.h"
c906108c 37
de57eccd
JM
38/* Implement the `info float' layout based on the register definitions
39 in `tm-i386.h'. */
40
41/* Print the floating point number specified by RAW. */
42static void
61113f8b 43print_i387_value (char *raw, struct ui_file *file)
de57eccd
JM
44{
45 DOUBLEST value;
4583280c
MK
46
47 /* Using extract_typed_floating here might affect the representation
48 of certain numbers such as NaNs, even if GDB is running natively.
49 This is fine since our caller already detects such special
50 numbers and we print the hexadecimal representation anyway. */
51 value = extract_typed_floating (raw, builtin_type_i387_ext);
de57eccd
JM
52
53 /* We try to print 19 digits. The last digit may or may not contain
54 garbage, but we'd better print one too many. We need enough room
55 to print the value, 1 position for the sign, 1 for the decimal
56 point, 19 for the digits and 6 for the exponent adds up to 27. */
57#ifdef PRINTF_HAS_LONG_DOUBLE
61113f8b 58 fprintf_filtered (file, " %-+27.19Lg", (long double) value);
de57eccd 59#else
61113f8b 60 fprintf_filtered (file, " %-+27.19g", (double) value);
de57eccd
JM
61#endif
62}
63
64/* Print the classification for the register contents RAW. */
65static void
61113f8b 66print_i387_ext (unsigned char *raw, struct ui_file *file)
de57eccd
JM
67{
68 int sign;
69 int integer;
70 unsigned int exponent;
71 unsigned long fraction[2];
72
73 sign = raw[9] & 0x80;
74 integer = raw[7] & 0x80;
75 exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
76 fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
77 fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
78 | (raw[5] << 8) | raw[4]);
79
80 if (exponent == 0x7fff && integer)
81 {
82 if (fraction[0] == 0x00000000 && fraction[1] == 0x00000000)
83 /* Infinity. */
61113f8b 84 fprintf_filtered (file, " %cInf", (sign ? '-' : '+'));
de57eccd
JM
85 else if (sign && fraction[0] == 0x00000000 && fraction[1] == 0x40000000)
86 /* Real Indefinite (QNaN). */
61113f8b 87 fputs_unfiltered (" Real Indefinite (QNaN)", file);
de57eccd
JM
88 else if (fraction[1] & 0x40000000)
89 /* QNaN. */
61113f8b 90 fputs_filtered (" QNaN", file);
de57eccd
JM
91 else
92 /* SNaN. */
61113f8b 93 fputs_filtered (" SNaN", file);
de57eccd
JM
94 }
95 else if (exponent < 0x7fff && exponent > 0x0000 && integer)
96 /* Normal. */
61113f8b 97 print_i387_value (raw, file);
de57eccd
JM
98 else if (exponent == 0x0000)
99 {
100 /* Denormal or zero. */
61113f8b 101 print_i387_value (raw, file);
de57eccd
JM
102
103 if (integer)
104 /* Pseudo-denormal. */
61113f8b 105 fputs_filtered (" Pseudo-denormal", file);
de57eccd
JM
106 else if (fraction[0] || fraction[1])
107 /* Denormal. */
61113f8b 108 fputs_filtered (" Denormal", file);
de57eccd
JM
109 }
110 else
111 /* Unsupported. */
61113f8b 112 fputs_filtered (" Unsupported", file);
de57eccd
JM
113}
114
115/* Print the status word STATUS. */
116static void
61113f8b 117print_i387_status_word (unsigned int status, struct ui_file *file)
de57eccd 118{
61113f8b 119 fprintf_filtered (file, "Status Word: %s",
de57eccd 120 local_hex_string_custom (status, "04"));
61113f8b
MK
121 fputs_filtered (" ", file);
122 fprintf_filtered (file, " %s", (status & 0x0001) ? "IE" : " ");
123 fprintf_filtered (file, " %s", (status & 0x0002) ? "DE" : " ");
124 fprintf_filtered (file, " %s", (status & 0x0004) ? "ZE" : " ");
125 fprintf_filtered (file, " %s", (status & 0x0008) ? "OE" : " ");
126 fprintf_filtered (file, " %s", (status & 0x0010) ? "UE" : " ");
127 fprintf_filtered (file, " %s", (status & 0x0020) ? "PE" : " ");
128 fputs_filtered (" ", file);
129 fprintf_filtered (file, " %s", (status & 0x0080) ? "ES" : " ");
130 fputs_filtered (" ", file);
131 fprintf_filtered (file, " %s", (status & 0x0040) ? "SF" : " ");
132 fputs_filtered (" ", file);
133 fprintf_filtered (file, " %s", (status & 0x0100) ? "C0" : " ");
134 fprintf_filtered (file, " %s", (status & 0x0200) ? "C1" : " ");
135 fprintf_filtered (file, " %s", (status & 0x0400) ? "C2" : " ");
136 fprintf_filtered (file, " %s", (status & 0x4000) ? "C3" : " ");
137
138 fputs_filtered ("\n", file);
139
140 fprintf_filtered (file,
141 " TOP: %d\n", ((status >> 11) & 7));
de57eccd
JM
142}
143
144/* Print the control word CONTROL. */
145static void
61113f8b 146print_i387_control_word (unsigned int control, struct ui_file *file)
de57eccd 147{
61113f8b 148 fprintf_filtered (file, "Control Word: %s",
de57eccd 149 local_hex_string_custom (control, "04"));
61113f8b
MK
150 fputs_filtered (" ", file);
151 fprintf_filtered (file, " %s", (control & 0x0001) ? "IM" : " ");
152 fprintf_filtered (file, " %s", (control & 0x0002) ? "DM" : " ");
153 fprintf_filtered (file, " %s", (control & 0x0004) ? "ZM" : " ");
154 fprintf_filtered (file, " %s", (control & 0x0008) ? "OM" : " ");
155 fprintf_filtered (file, " %s", (control & 0x0010) ? "UM" : " ");
156 fprintf_filtered (file, " %s", (control & 0x0020) ? "PM" : " ");
de57eccd 157
61113f8b 158 fputs_filtered ("\n", file);
de57eccd 159
61113f8b 160 fputs_filtered (" PC: ", file);
de57eccd
JM
161 switch ((control >> 8) & 3)
162 {
163 case 0:
61113f8b 164 fputs_filtered ("Single Precision (24-bits)\n", file);
de57eccd
JM
165 break;
166 case 1:
61113f8b 167 fputs_filtered ("Reserved\n", file);
de57eccd
JM
168 break;
169 case 2:
61113f8b 170 fputs_filtered ("Double Precision (53-bits)\n", file);
de57eccd
JM
171 break;
172 case 3:
61113f8b 173 fputs_filtered ("Extended Precision (64-bits)\n", file);
de57eccd
JM
174 break;
175 }
176
61113f8b 177 fputs_filtered (" RC: ", file);
de57eccd
JM
178 switch ((control >> 10) & 3)
179 {
180 case 0:
61113f8b 181 fputs_filtered ("Round to nearest\n", file);
de57eccd
JM
182 break;
183 case 1:
61113f8b 184 fputs_filtered ("Round down\n", file);
de57eccd
JM
185 break;
186 case 2:
61113f8b 187 fputs_filtered ("Round up\n", file);
de57eccd
JM
188 break;
189 case 3:
61113f8b 190 fputs_filtered ("Round toward zero\n", file);
de57eccd
JM
191 break;
192 }
193}
194
9b949a49 195/* Print out the i387 floating point state. Note that we ignore FRAME
7d8d2918
MK
196 in the code below. That's OK since floating-point registers are
197 never saved on the stack. */
198
de57eccd 199void
61113f8b 200i387_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
8e186fd6 201 struct frame_info *frame, const char *args)
de57eccd 202{
1d70089a
MK
203 char buf[4];
204 ULONGEST fctrl;
205 ULONGEST fstat;
206 ULONGEST ftag;
207 ULONGEST fiseg;
208 ULONGEST fioff;
209 ULONGEST foseg;
210 ULONGEST fooff;
211 ULONGEST fop;
de57eccd
JM
212 int fpreg;
213 int top;
214
1d70089a
MK
215 frame_register_read (frame, FCTRL_REGNUM, buf);
216 fctrl = extract_unsigned_integer (buf, 4);
217 frame_register_read (frame, FSTAT_REGNUM, buf);
218 fstat = extract_unsigned_integer (buf, 4);
219 frame_register_read (frame, FTAG_REGNUM, buf);
220 ftag = extract_unsigned_integer (buf, 4);
221 frame_register_read (frame, FISEG_REGNUM, buf);
222 fiseg = extract_unsigned_integer (buf, 4);
223 frame_register_read (frame, FIOFF_REGNUM, buf);
224 fioff = extract_unsigned_integer (buf, 4);
225 frame_register_read (frame, FOSEG_REGNUM, buf);
226 foseg = extract_unsigned_integer (buf, 4);
227 frame_register_read (frame, FOOFF_REGNUM, buf);
228 fooff = extract_unsigned_integer (buf, 4);
229 frame_register_read (frame, FOP_REGNUM, buf);
230 fop = extract_unsigned_integer (buf, 4);
231
de57eccd
JM
232 top = ((fstat >> 11) & 7);
233
234 for (fpreg = 7; fpreg >= 0; fpreg--)
235 {
236 unsigned char raw[FPU_REG_RAW_SIZE];
237 int tag = (ftag >> (fpreg * 2)) & 3;
238 int i;
239
61113f8b 240 fprintf_filtered (file, "%sR%d: ", fpreg == top ? "=>" : " ", fpreg);
de57eccd
JM
241
242 switch (tag)
243 {
244 case 0:
61113f8b 245 fputs_filtered ("Valid ", file);
de57eccd
JM
246 break;
247 case 1:
61113f8b 248 fputs_filtered ("Zero ", file);
de57eccd
JM
249 break;
250 case 2:
61113f8b 251 fputs_filtered ("Special ", file);
de57eccd
JM
252 break;
253 case 3:
61113f8b 254 fputs_filtered ("Empty ", file);
de57eccd
JM
255 break;
256 }
257
1d70089a 258 frame_register_read (frame, (fpreg + 8 - top) % 8 + FP0_REGNUM, raw);
de57eccd 259
61113f8b 260 fputs_filtered ("0x", file);
de57eccd 261 for (i = 9; i >= 0; i--)
61113f8b 262 fprintf_filtered (file, "%02x", raw[i]);
de57eccd
JM
263
264 if (tag != 3)
61113f8b 265 print_i387_ext (raw, file);
de57eccd 266
61113f8b 267 fputs_filtered ("\n", file);
de57eccd
JM
268 }
269
f16a25ae 270 fputs_filtered ("\n", file);
de57eccd 271
61113f8b
MK
272 print_i387_status_word (fstat, file);
273 print_i387_control_word (fctrl, file);
274 fprintf_filtered (file, "Tag Word: %s\n",
275 local_hex_string_custom (ftag, "04"));
276 fprintf_filtered (file, "Instruction Pointer: %s:",
277 local_hex_string_custom (fiseg, "02"));
278 fprintf_filtered (file, "%s\n", local_hex_string_custom (fioff, "08"));
279 fprintf_filtered (file, "Operand Pointer: %s:",
280 local_hex_string_custom (foseg, "02"));
281 fprintf_filtered (file, "%s\n", local_hex_string_custom (fooff, "08"));
282 fprintf_filtered (file, "Opcode: %s\n",
283 local_hex_string_custom (fop ? (fop | 0xd800) : 0, "04"));
de57eccd 284}
d532c08f
MK
285\f
286
287/* Read a value of type TYPE from register REGNUM in frame FRAME, and
288 return its contents in TO. */
289
290void
291i387_register_to_value (struct frame_info *frame, int regnum,
292 struct type *type, void *to)
293{
294 char from[I386_MAX_REGISTER_SIZE];
295
296 gdb_assert (i386_fp_regnum_p (regnum));
297
298 /* We only support floating-point values. */
299 if (TYPE_CODE (type) != TYPE_CODE_FLT)
300 {
301 warning ("Cannot convert floating-point register value "
302 "to non-floating-point type.");
303 return;
304 }
305
306 /* Convert to TYPE. This should be a no-op if TYPE is equivalent to
307 the extended floating-point format used by the FPU. */
308 frame_read_register (frame, regnum, from);
309 convert_typed_floating (from, builtin_type_i387_ext, to, type);
310}
311
312/* Write the contents FROM of a value of type TYPE into register
313 REGNUM in frame FRAME. */
314
315void
316i387_value_to_register (struct frame_info *frame, int regnum,
317 struct type *type, const void *from)
318{
319 char to[I386_MAX_REGISTER_SIZE];
320
321 gdb_assert (i386_fp_regnum_p (regnum));
322
323 /* We only support floating-point values. */
324 if (TYPE_CODE (type) != TYPE_CODE_FLT)
325 {
326 warning ("Cannot convert non-floating-point type "
327 "to floating-point register value.");
328 return;
329 }
330
331 /* Convert from TYPE. This should be a no-op if TYPE is equivalent
332 to the extended floating-point format used by the FPU. */
333 convert_typed_floating (from, type, to, builtin_type_i387_ext);
334 put_frame_register (frame, regnum, to);
335}
336\f
e750d25e
JT
337
338/* FIXME: kettenis/2000-05-21: Right now more than a few i386 targets
339 define their own routines to manage the floating-point registers in
340 GDB's register array. Most (if not all) of these targets use the
341 format used by the "fsave" instruction in their communication with
342 the OS. They should all be converted to use the routines below. */
343
344/* At fsave_offset[REGNUM] you'll find the offset to the location in
345 the data structure used by the "fsave" instruction where GDB
346 register REGNUM is stored. */
347
348static int fsave_offset[] =
349{
350 28 + 0 * FPU_REG_RAW_SIZE, /* FP0_REGNUM through ... */
351 28 + 1 * FPU_REG_RAW_SIZE,
352 28 + 2 * FPU_REG_RAW_SIZE,
353 28 + 3 * FPU_REG_RAW_SIZE,
354 28 + 4 * FPU_REG_RAW_SIZE,
355 28 + 5 * FPU_REG_RAW_SIZE,
356 28 + 6 * FPU_REG_RAW_SIZE,
357 28 + 7 * FPU_REG_RAW_SIZE, /* ... FP7_REGNUM. */
358 0, /* FCTRL_REGNUM (16 bits). */
359 4, /* FSTAT_REGNUM (16 bits). */
360 8, /* FTAG_REGNUM (16 bits). */
361 16, /* FISEG_REGNUM (16 bits). */
362 12, /* FIOFF_REGNUM. */
363 24, /* FOSEG_REGNUM. */
364 20, /* FOOFF_REGNUM. */
365 18 /* FOP_REGNUM (bottom 11 bits). */
366};
367
368#define FSAVE_ADDR(fsave, regnum) (fsave + fsave_offset[regnum - FP0_REGNUM])
369\f
370
371/* Fill register REGNUM in GDB's register array with the appropriate
372 value from *FSAVE. This function masks off any of the reserved
373 bits in *FSAVE. */
374
375void
376i387_supply_register (int regnum, char *fsave)
377{
932bb524
KD
378 if (fsave == NULL)
379 {
380 supply_register (regnum, NULL);
381 return;
382 }
383
e750d25e
JT
384 /* Most of the FPU control registers occupy only 16 bits in
385 the fsave area. Give those a special treatment. */
386 if (regnum >= FPC_REGNUM
387 && regnum != FIOFF_REGNUM && regnum != FOOFF_REGNUM)
388 {
389 unsigned char val[4];
390
391 memcpy (val, FSAVE_ADDR (fsave, regnum), 2);
392 val[2] = val[3] = 0;
393 if (regnum == FOP_REGNUM)
394 val[1] &= ((1 << 3) - 1);
395 supply_register (regnum, val);
396 }
397 else
398 supply_register (regnum, FSAVE_ADDR (fsave, regnum));
399}
400
401/* Fill GDB's register array with the floating-point register values
402 in *FSAVE. This function masks off any of the reserved
403 bits in *FSAVE. */
404
405void
406i387_supply_fsave (char *fsave)
407{
408 int i;
409
410 for (i = FP0_REGNUM; i < XMM0_REGNUM; i++)
411 i387_supply_register (i, fsave);
412}
413
414/* Fill register REGNUM (if it is a floating-point register) in *FSAVE
415 with the value in GDB's register array. If REGNUM is -1, do this
416 for all registers. This function doesn't touch any of the reserved
417 bits in *FSAVE. */
418
419void
420i387_fill_fsave (char *fsave, int regnum)
421{
422 int i;
423
424 for (i = FP0_REGNUM; i < XMM0_REGNUM; i++)
425 if (regnum == -1 || regnum == i)
426 {
427 /* Most of the FPU control registers occupy only 16 bits in
428 the fsave area. Give those a special treatment. */
429 if (i >= FPC_REGNUM
430 && i != FIOFF_REGNUM && i != FOOFF_REGNUM)
431 {
432 unsigned char buf[4];
433
434 regcache_collect (i, buf);
435
436 if (i == FOP_REGNUM)
437 {
438 /* The opcode occupies only 11 bits. Make sure we
439 don't touch the other bits. */
440 buf[1] &= ((1 << 3) - 1);
441 buf[1] |= ((FSAVE_ADDR (fsave, i))[1] & ~((1 << 3) - 1));
442 }
443 memcpy (FSAVE_ADDR (fsave, i), buf, 2);
444 }
445 else
446 regcache_collect (i, FSAVE_ADDR (fsave, i));
447 }
448}
449\f
450
451/* At fxsave_offset[REGNUM] you'll find the offset to the location in
452 the data structure used by the "fxsave" instruction where GDB
453 register REGNUM is stored. */
454
455static int fxsave_offset[] =
456{
457 32, /* FP0_REGNUM through ... */
458 48,
459 64,
460 80,
461 96,
462 112,
463 128,
464 144, /* ... FP7_REGNUM (80 bits each). */
465 0, /* FCTRL_REGNUM (16 bits). */
466 2, /* FSTAT_REGNUM (16 bits). */
467 4, /* FTAG_REGNUM (16 bits). */
468 12, /* FISEG_REGNUM (16 bits). */
469 8, /* FIOFF_REGNUM. */
470 20, /* FOSEG_REGNUM (16 bits). */
471 16, /* FOOFF_REGNUM. */
472 6, /* FOP_REGNUM (bottom 11 bits). */
04c8243f
MK
473 160 + 0 * 16, /* XMM0_REGNUM through ... */
474 160 + 1 * 16,
475 160 + 2 * 16,
476 160 + 3 * 16,
477 160 + 4 * 16,
478 160 + 5 * 16,
479 160 + 6 * 16,
480 160 + 7 * 16,
481 160 + 8 * 16,
482 160 + 9 * 16,
483 160 + 10 * 16,
484 160 + 11 * 16,
485 160 + 12 * 16,
486 160 + 13 * 16,
487 160 + 14 * 16,
488 160 + 15 * 16, /* ... XMM15_REGNUM (128 bits each). */
489 24 /* MXCSR_REGNUM. */
e750d25e
JT
490};
491
04c8243f
MK
492/* FIXME: kettenis/20030430: We made an unfortunate choice in putting
493 %mxcsr after the SSE registers %xmm0-%xmm7 instead of before, since
494 it makes supporting the registers %xmm8-%xmm15 on x86-64 a bit
495 involved. Hack around it by explicitly overriding the offset for
496 %mxcsr here. */
497
e750d25e 498#define FXSAVE_ADDR(fxsave, regnum) \
04c8243f
MK
499 ((regnum == MXCSR_REGNUM) ? (fxsave + 24) : \
500 (fxsave + fxsave_offset[regnum - FP0_REGNUM]))
e750d25e
JT
501
502static int i387_tag (unsigned char *raw);
503\f
504
505/* Fill GDB's register array with the floating-point and SSE register
506 values in *FXSAVE. This function masks off any of the reserved
507 bits in *FXSAVE. */
508
509void
510i387_supply_fxsave (char *fxsave)
511{
dff95cc7
MK
512 int i, last_regnum = MXCSR_REGNUM;
513
514 if (gdbarch_tdep (current_gdbarch)->num_xmm_regs == 0)
515 last_regnum = FOP_REGNUM;
e750d25e 516
dff95cc7 517 for (i = FP0_REGNUM; i <= last_regnum; i++)
e750d25e 518 {
932bb524
KD
519 if (fxsave == NULL)
520 {
521 supply_register (i, NULL);
522 continue;
523 }
524
e750d25e
JT
525 /* Most of the FPU control registers occupy only 16 bits in
526 the fxsave area. Give those a special treatment. */
527 if (i >= FPC_REGNUM && i < XMM0_REGNUM
528 && i != FIOFF_REGNUM && i != FOOFF_REGNUM)
529 {
530 unsigned char val[4];
531
532 memcpy (val, FXSAVE_ADDR (fxsave, i), 2);
533 val[2] = val[3] = 0;
534 if (i == FOP_REGNUM)
535 val[1] &= ((1 << 3) - 1);
536 else if (i== FTAG_REGNUM)
537 {
538 /* The fxsave area contains a simplified version of the
539 tag word. We have to look at the actual 80-bit FP
540 data to recreate the traditional i387 tag word. */
541
542 unsigned long ftag = 0;
543 int fpreg;
544 int top;
545
546 top = (((FXSAVE_ADDR (fxsave, FSTAT_REGNUM))[1] >> 3) & 0x7);
547
548 for (fpreg = 7; fpreg >= 0; fpreg--)
549 {
550 int tag;
551
552 if (val[0] & (1 << fpreg))
553 {
554 int regnum = (fpreg + 8 - top) % 8 + FP0_REGNUM;
555 tag = i387_tag (FXSAVE_ADDR (fxsave, regnum));
556 }
557 else
558 tag = 3; /* Empty */
559
560 ftag |= tag << (2 * fpreg);
561 }
562 val[0] = ftag & 0xff;
563 val[1] = (ftag >> 8) & 0xff;
564 }
565 supply_register (i, val);
566 }
567 else
568 supply_register (i, FXSAVE_ADDR (fxsave, i));
569 }
570}
571
572/* Fill register REGNUM (if it is a floating-point or SSE register) in
573 *FXSAVE with the value in GDB's register array. If REGNUM is -1, do
574 this for all registers. This function doesn't touch any of the
575 reserved bits in *FXSAVE. */
576
577void
578i387_fill_fxsave (char *fxsave, int regnum)
579{
dff95cc7
MK
580 int i, last_regnum = MXCSR_REGNUM;
581
582 if (gdbarch_tdep (current_gdbarch)->num_xmm_regs == 0)
583 last_regnum = FOP_REGNUM;
e750d25e 584
dff95cc7 585 for (i = FP0_REGNUM; i <= last_regnum; i++)
e750d25e
JT
586 if (regnum == -1 || regnum == i)
587 {
588 /* Most of the FPU control registers occupy only 16 bits in
589 the fxsave area. Give those a special treatment. */
590 if (i >= FPC_REGNUM && i < XMM0_REGNUM
19e33363 591 && i != FIOFF_REGNUM && i != FOOFF_REGNUM)
e750d25e
JT
592 {
593 unsigned char buf[4];
594
595 regcache_collect (i, buf);
596
597 if (i == FOP_REGNUM)
598 {
599 /* The opcode occupies only 11 bits. Make sure we
600 don't touch the other bits. */
601 buf[1] &= ((1 << 3) - 1);
602 buf[1] |= ((FXSAVE_ADDR (fxsave, i))[1] & ~((1 << 3) - 1));
603 }
604 else if (i == FTAG_REGNUM)
605 {
606 /* Converting back is much easier. */
607
608 unsigned short ftag;
609 int fpreg;
610
611 ftag = (buf[1] << 8) | buf[0];
612 buf[0] = 0;
613 buf[1] = 0;
614
615 for (fpreg = 7; fpreg >= 0; fpreg--)
616 {
617 int tag = (ftag >> (fpreg * 2)) & 3;
618
619 if (tag != 3)
620 buf[0] |= (1 << fpreg);
621 }
622 }
623 memcpy (FXSAVE_ADDR (fxsave, i), buf, 2);
624 }
625 else
626 regcache_collect (i, FXSAVE_ADDR (fxsave, i));
627 }
628}
629
630/* Recreate the FTW (tag word) valid bits from the 80-bit FP data in
631 *RAW. */
632
633static int
634i387_tag (unsigned char *raw)
635{
636 int integer;
637 unsigned int exponent;
638 unsigned long fraction[2];
639
640 integer = raw[7] & 0x80;
641 exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
642 fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
643 fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
644 | (raw[5] << 8) | raw[4]);
645
646 if (exponent == 0x7fff)
647 {
648 /* Special. */
649 return (2);
650 }
651 else if (exponent == 0x0000)
652 {
653 if (fraction[0] == 0x0000 && fraction[1] == 0x0000 && !integer)
654 {
655 /* Zero. */
656 return (1);
657 }
658 else
659 {
660 /* Special. */
661 return (2);
662 }
663 }
664 else
665 {
666 if (integer)
667 {
668 /* Valid. */
669 return (0);
670 }
671 else
672 {
673 /* Special. */
674 return (2);
675 }
676 }
677}
This page took 0.418605 seconds and 4 git commands to generate.