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