* linux-sh-low.c (sh_regmap): Fix FP register offsets, reported by
[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"
786a90bb
MK
24#include "doublest.h"
25#include "floatformat.h"
c906108c 26#include "frame.h"
786a90bb 27#include "gdbcore.h"
c906108c
SS
28#include "inferior.h"
29#include "language.h"
4e052eda 30#include "regcache.h"
786a90bb
MK
31#include "value.h"
32
d0df8472 33#include "gdb_assert.h"
309367d4 34#include "gdb_string.h"
c906108c 35
9a82579f 36#include "i386-tdep.h"
42c466d7 37#include "i387-tdep.h"
c906108c 38
de57eccd
JM
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. */
786a90bb 43
de57eccd 44static void
61113f8b 45print_i387_value (char *raw, struct ui_file *file)
de57eccd
JM
46{
47 DOUBLEST value;
4583280c
MK
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);
de57eccd
JM
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
61113f8b 60 fprintf_filtered (file, " %-+27.19Lg", (long double) value);
de57eccd 61#else
61113f8b 62 fprintf_filtered (file, " %-+27.19g", (double) value);
de57eccd
JM
63#endif
64}
65
66/* Print the classification for the register contents RAW. */
786a90bb 67
de57eccd 68static void
61113f8b 69print_i387_ext (unsigned char *raw, struct ui_file *file)
de57eccd
JM
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. */
61113f8b 87 fprintf_filtered (file, " %cInf", (sign ? '-' : '+'));
de57eccd
JM
88 else if (sign && fraction[0] == 0x00000000 && fraction[1] == 0x40000000)
89 /* Real Indefinite (QNaN). */
61113f8b 90 fputs_unfiltered (" Real Indefinite (QNaN)", file);
de57eccd
JM
91 else if (fraction[1] & 0x40000000)
92 /* QNaN. */
61113f8b 93 fputs_filtered (" QNaN", file);
de57eccd
JM
94 else
95 /* SNaN. */
61113f8b 96 fputs_filtered (" SNaN", file);
de57eccd
JM
97 }
98 else if (exponent < 0x7fff && exponent > 0x0000 && integer)
99 /* Normal. */
61113f8b 100 print_i387_value (raw, file);
de57eccd
JM
101 else if (exponent == 0x0000)
102 {
103 /* Denormal or zero. */
61113f8b 104 print_i387_value (raw, file);
de57eccd
JM
105
106 if (integer)
107 /* Pseudo-denormal. */
61113f8b 108 fputs_filtered (" Pseudo-denormal", file);
de57eccd
JM
109 else if (fraction[0] || fraction[1])
110 /* Denormal. */
61113f8b 111 fputs_filtered (" Denormal", file);
de57eccd
JM
112 }
113 else
114 /* Unsupported. */
61113f8b 115 fputs_filtered (" Unsupported", file);
de57eccd
JM
116}
117
118/* Print the status word STATUS. */
786a90bb 119
de57eccd 120static void
61113f8b 121print_i387_status_word (unsigned int status, struct ui_file *file)
de57eccd 122{
61113f8b 123 fprintf_filtered (file, "Status Word: %s",
de57eccd 124 local_hex_string_custom (status, "04"));
61113f8b
MK
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));
de57eccd
JM
146}
147
148/* Print the control word CONTROL. */
786a90bb 149
de57eccd 150static void
61113f8b 151print_i387_control_word (unsigned int control, struct ui_file *file)
de57eccd 152{
61113f8b 153 fprintf_filtered (file, "Control Word: %s",
de57eccd 154 local_hex_string_custom (control, "04"));
61113f8b
MK
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" : " ");
de57eccd 162
61113f8b 163 fputs_filtered ("\n", file);
de57eccd 164
61113f8b 165 fputs_filtered (" PC: ", file);
de57eccd
JM
166 switch ((control >> 8) & 3)
167 {
168 case 0:
61113f8b 169 fputs_filtered ("Single Precision (24-bits)\n", file);
de57eccd
JM
170 break;
171 case 1:
61113f8b 172 fputs_filtered ("Reserved\n", file);
de57eccd
JM
173 break;
174 case 2:
61113f8b 175 fputs_filtered ("Double Precision (53-bits)\n", file);
de57eccd
JM
176 break;
177 case 3:
61113f8b 178 fputs_filtered ("Extended Precision (64-bits)\n", file);
de57eccd
JM
179 break;
180 }
181
61113f8b 182 fputs_filtered (" RC: ", file);
de57eccd
JM
183 switch ((control >> 10) & 3)
184 {
185 case 0:
61113f8b 186 fputs_filtered ("Round to nearest\n", file);
de57eccd
JM
187 break;
188 case 1:
61113f8b 189 fputs_filtered ("Round down\n", file);
de57eccd
JM
190 break;
191 case 2:
61113f8b 192 fputs_filtered ("Round up\n", file);
de57eccd
JM
193 break;
194 case 3:
61113f8b 195 fputs_filtered ("Round toward zero\n", file);
de57eccd
JM
196 break;
197 }
198}
199
9b949a49 200/* Print out the i387 floating point state. Note that we ignore FRAME
7d8d2918
MK
201 in the code below. That's OK since floating-point registers are
202 never saved on the stack. */
203
de57eccd 204void
61113f8b 205i387_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
8e186fd6 206 struct frame_info *frame, const char *args)
de57eccd 207{
1d70089a
MK
208 char buf[4];
209 ULONGEST fctrl;
210 ULONGEST fstat;
211 ULONGEST ftag;
212 ULONGEST fiseg;
213 ULONGEST fioff;
214 ULONGEST foseg;
215 ULONGEST fooff;
216 ULONGEST fop;
de57eccd
JM
217 int fpreg;
218 int top;
219
1d70089a
MK
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);
236
de57eccd
JM
237 top = ((fstat >> 11) & 7);
238
239 for (fpreg = 7; fpreg >= 0; fpreg--)
240 {
241 unsigned char raw[FPU_REG_RAW_SIZE];
242 int tag = (ftag >> (fpreg * 2)) & 3;
243 int i;
244
61113f8b 245 fprintf_filtered (file, "%sR%d: ", fpreg == top ? "=>" : " ", fpreg);
de57eccd
JM
246
247 switch (tag)
248 {
249 case 0:
61113f8b 250 fputs_filtered ("Valid ", file);
de57eccd
JM
251 break;
252 case 1:
61113f8b 253 fputs_filtered ("Zero ", file);
de57eccd
JM
254 break;
255 case 2:
61113f8b 256 fputs_filtered ("Special ", file);
de57eccd
JM
257 break;
258 case 3:
61113f8b 259 fputs_filtered ("Empty ", file);
de57eccd
JM
260 break;
261 }
262
1d70089a 263 frame_register_read (frame, (fpreg + 8 - top) % 8 + FP0_REGNUM, raw);
de57eccd 264
61113f8b 265 fputs_filtered ("0x", file);
de57eccd 266 for (i = 9; i >= 0; i--)
61113f8b 267 fprintf_filtered (file, "%02x", raw[i]);
de57eccd
JM
268
269 if (tag != 3)
61113f8b 270 print_i387_ext (raw, file);
de57eccd 271
61113f8b 272 fputs_filtered ("\n", file);
de57eccd
JM
273 }
274
f16a25ae 275 fputs_filtered ("\n", file);
de57eccd 276
61113f8b
MK
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"));
de57eccd 289}
d532c08f
MK
290\f
291
292/* Read a value of type TYPE from register REGNUM in frame FRAME, and
293 return its contents in TO. */
294
295void
296i387_register_to_value (struct frame_info *frame, int regnum,
297 struct type *type, void *to)
298{
299 char from[I386_MAX_REGISTER_SIZE];
300
301 gdb_assert (i386_fp_regnum_p (regnum));
302
303 /* We only support floating-point values. */
304 if (TYPE_CODE (type) != TYPE_CODE_FLT)
305 {
306 warning ("Cannot convert floating-point register value "
307 "to non-floating-point type.");
308 return;
309 }
310
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);
315}
316
317/* Write the contents FROM of a value of type TYPE into register
318 REGNUM in frame FRAME. */
319
320void
321i387_value_to_register (struct frame_info *frame, int regnum,
322 struct type *type, const void *from)
323{
324 char to[I386_MAX_REGISTER_SIZE];
325
326 gdb_assert (i386_fp_regnum_p (regnum));
327
328 /* We only support floating-point values. */
329 if (TYPE_CODE (type) != TYPE_CODE_FLT)
330 {
331 warning ("Cannot convert non-floating-point type "
332 "to floating-point register value.");
333 return;
334 }
335
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);
340}
341\f
e750d25e 342
786a90bb 343/* Handle FSAVE and FXSAVE formats. */
e750d25e
JT
344
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. */
348
349static int fsave_offset[] =
350{
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). */
367};
368
369#define FSAVE_ADDR(fsave, regnum) (fsave + fsave_offset[regnum - FP0_REGNUM])
370\f
371
372/* Fill register REGNUM in GDB's register array with the appropriate
373 value from *FSAVE. This function masks off any of the reserved
374 bits in *FSAVE. */
375
376void
377i387_supply_register (int regnum, char *fsave)
378{
932bb524
KD
379 if (fsave == NULL)
380 {
381 supply_register (regnum, NULL);
382 return;
383 }
384
e750d25e
JT
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)
389 {
390 unsigned char val[4];
391
392 memcpy (val, FSAVE_ADDR (fsave, regnum), 2);
393 val[2] = val[3] = 0;
394 if (regnum == FOP_REGNUM)
395 val[1] &= ((1 << 3) - 1);
396 supply_register (regnum, val);
397 }
398 else
399 supply_register (regnum, FSAVE_ADDR (fsave, regnum));
400}
401
402/* Fill GDB's register array with the floating-point register values
403 in *FSAVE. This function masks off any of the reserved
404 bits in *FSAVE. */
405
406void
407i387_supply_fsave (char *fsave)
408{
409 int i;
410
411 for (i = FP0_REGNUM; i < XMM0_REGNUM; i++)
412 i387_supply_register (i, fsave);
413}
414
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
418 bits in *FSAVE. */
419
420void
421i387_fill_fsave (char *fsave, int regnum)
422{
423 int i;
424
425 for (i = FP0_REGNUM; i < XMM0_REGNUM; i++)
426 if (regnum == -1 || regnum == i)
427 {
428 /* Most of the FPU control registers occupy only 16 bits in
429 the fsave area. Give those a special treatment. */
430 if (i >= FPC_REGNUM
431 && i != FIOFF_REGNUM && i != FOOFF_REGNUM)
432 {
433 unsigned char buf[4];
434
435 regcache_collect (i, buf);
436
437 if (i == FOP_REGNUM)
438 {
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));
443 }
444 memcpy (FSAVE_ADDR (fsave, i), buf, 2);
445 }
446 else
447 regcache_collect (i, FSAVE_ADDR (fsave, i));
448 }
449}
450\f
451
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. */
455
456static int fxsave_offset[] =
457{
458 32, /* FP0_REGNUM through ... */
459 48,
460 64,
461 80,
462 96,
463 112,
464 128,
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). */
04c8243f
MK
474 160 + 0 * 16, /* XMM0_REGNUM through ... */
475 160 + 1 * 16,
476 160 + 2 * 16,
477 160 + 3 * 16,
478 160 + 4 * 16,
479 160 + 5 * 16,
480 160 + 6 * 16,
481 160 + 7 * 16,
482 160 + 8 * 16,
483 160 + 9 * 16,
484 160 + 10 * 16,
485 160 + 11 * 16,
486 160 + 12 * 16,
487 160 + 13 * 16,
488 160 + 14 * 16,
489 160 + 15 * 16, /* ... XMM15_REGNUM (128 bits each). */
490 24 /* MXCSR_REGNUM. */
e750d25e
JT
491};
492
04c8243f
MK
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
497 %mxcsr here. */
498
e750d25e 499#define FXSAVE_ADDR(fxsave, regnum) \
04c8243f
MK
500 ((regnum == MXCSR_REGNUM) ? (fxsave + 24) : \
501 (fxsave + fxsave_offset[regnum - FP0_REGNUM]))
e750d25e
JT
502
503static int i387_tag (unsigned char *raw);
504\f
505
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
508 bits in *FXSAVE. */
509
510void
511i387_supply_fxsave (char *fxsave)
512{
dff95cc7
MK
513 int i, last_regnum = MXCSR_REGNUM;
514
515 if (gdbarch_tdep (current_gdbarch)->num_xmm_regs == 0)
516 last_regnum = FOP_REGNUM;
e750d25e 517
dff95cc7 518 for (i = FP0_REGNUM; i <= last_regnum; i++)
e750d25e 519 {
932bb524
KD
520 if (fxsave == NULL)
521 {
522 supply_register (i, NULL);
523 continue;
524 }
525
e750d25e
JT
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)
530 {
531 unsigned char val[4];
532
533 memcpy (val, FXSAVE_ADDR (fxsave, i), 2);
534 val[2] = val[3] = 0;
535 if (i == FOP_REGNUM)
536 val[1] &= ((1 << 3) - 1);
537 else if (i== FTAG_REGNUM)
538 {
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. */
542
543 unsigned long ftag = 0;
544 int fpreg;
545 int top;
546
547 top = (((FXSAVE_ADDR (fxsave, FSTAT_REGNUM))[1] >> 3) & 0x7);
548
549 for (fpreg = 7; fpreg >= 0; fpreg--)
550 {
551 int tag;
552
553 if (val[0] & (1 << fpreg))
554 {
555 int regnum = (fpreg + 8 - top) % 8 + FP0_REGNUM;
556 tag = i387_tag (FXSAVE_ADDR (fxsave, regnum));
557 }
558 else
559 tag = 3; /* Empty */
560
561 ftag |= tag << (2 * fpreg);
562 }
563 val[0] = ftag & 0xff;
564 val[1] = (ftag >> 8) & 0xff;
565 }
566 supply_register (i, val);
567 }
568 else
569 supply_register (i, FXSAVE_ADDR (fxsave, i));
570 }
571}
572
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. */
577
578void
579i387_fill_fxsave (char *fxsave, int regnum)
580{
dff95cc7
MK
581 int i, last_regnum = MXCSR_REGNUM;
582
583 if (gdbarch_tdep (current_gdbarch)->num_xmm_regs == 0)
584 last_regnum = FOP_REGNUM;
e750d25e 585
dff95cc7 586 for (i = FP0_REGNUM; i <= last_regnum; i++)
e750d25e
JT
587 if (regnum == -1 || regnum == i)
588 {
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
19e33363 592 && i != FIOFF_REGNUM && i != FOOFF_REGNUM)
e750d25e
JT
593 {
594 unsigned char buf[4];
595
596 regcache_collect (i, buf);
597
598 if (i == FOP_REGNUM)
599 {
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));
604 }
605 else if (i == FTAG_REGNUM)
606 {
607 /* Converting back is much easier. */
608
609 unsigned short ftag;
610 int fpreg;
611
612 ftag = (buf[1] << 8) | buf[0];
613 buf[0] = 0;
614 buf[1] = 0;
615
616 for (fpreg = 7; fpreg >= 0; fpreg--)
617 {
618 int tag = (ftag >> (fpreg * 2)) & 3;
619
620 if (tag != 3)
621 buf[0] |= (1 << fpreg);
622 }
623 }
624 memcpy (FXSAVE_ADDR (fxsave, i), buf, 2);
625 }
626 else
627 regcache_collect (i, FXSAVE_ADDR (fxsave, i));
628 }
629}
630
631/* Recreate the FTW (tag word) valid bits from the 80-bit FP data in
632 *RAW. */
633
634static int
635i387_tag (unsigned char *raw)
636{
637 int integer;
638 unsigned int exponent;
639 unsigned long fraction[2];
640
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]);
646
647 if (exponent == 0x7fff)
648 {
649 /* Special. */
650 return (2);
651 }
652 else if (exponent == 0x0000)
653 {
654 if (fraction[0] == 0x0000 && fraction[1] == 0x0000 && !integer)
655 {
656 /* Zero. */
657 return (1);
658 }
659 else
660 {
661 /* Special. */
662 return (2);
663 }
664 }
665 else
666 {
667 if (integer)
668 {
669 /* Valid. */
670 return (0);
671 }
672 else
673 {
674 /* Special. */
675 return (2);
676 }
677 }
678}
This page took 0.310903 seconds and 4 git commands to generate.