* NEWS: Mention that the i[3456]-*-aix target has been made obsolete.
[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
315/* Print out the i387 floating poin state. */
316void
61113f8b
MK
317i387_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
318 struct frame_info *frame)
de57eccd
JM
319{
320 unsigned int fctrl;
321 unsigned int fstat;
322 unsigned int ftag;
323 unsigned int fiseg;
324 unsigned int fioff;
325 unsigned int foseg;
326 unsigned int fooff;
327 unsigned int fop;
328 int fpreg;
329 int top;
330
331 fctrl = read_register (FCTRL_REGNUM);
332 fstat = read_register (FSTAT_REGNUM);
333 ftag = read_register (FTAG_REGNUM);
334 fiseg = read_register (FCS_REGNUM);
335 fioff = read_register (FCOFF_REGNUM);
336 foseg = read_register (FDS_REGNUM);
337 fooff = read_register (FDOFF_REGNUM);
338 fop = read_register (FOP_REGNUM);
339
340 top = ((fstat >> 11) & 7);
341
342 for (fpreg = 7; fpreg >= 0; fpreg--)
343 {
344 unsigned char raw[FPU_REG_RAW_SIZE];
345 int tag = (ftag >> (fpreg * 2)) & 3;
346 int i;
347
61113f8b 348 fprintf_filtered (file, "%sR%d: ", fpreg == top ? "=>" : " ", fpreg);
de57eccd
JM
349
350 switch (tag)
351 {
352 case 0:
61113f8b 353 fputs_filtered ("Valid ", file);
de57eccd
JM
354 break;
355 case 1:
61113f8b 356 fputs_filtered ("Zero ", file);
de57eccd
JM
357 break;
358 case 2:
61113f8b 359 fputs_filtered ("Special ", file);
de57eccd
JM
360 break;
361 case 3:
61113f8b 362 fputs_filtered ("Empty ", file);
de57eccd
JM
363 break;
364 }
365
366 read_register_gen ((fpreg + 8 - top) % 8 + FP0_REGNUM, raw);
367
61113f8b 368 fputs_filtered ("0x", file);
de57eccd 369 for (i = 9; i >= 0; i--)
61113f8b 370 fprintf_filtered (file, "%02x", raw[i]);
de57eccd
JM
371
372 if (tag != 3)
61113f8b 373 print_i387_ext (raw, file);
de57eccd 374
61113f8b 375 fputs_filtered ("\n", file);
de57eccd
JM
376 }
377
378 puts_filtered ("\n");
379
61113f8b
MK
380 print_i387_status_word (fstat, file);
381 print_i387_control_word (fctrl, file);
382 fprintf_filtered (file, "Tag Word: %s\n",
383 local_hex_string_custom (ftag, "04"));
384 fprintf_filtered (file, "Instruction Pointer: %s:",
385 local_hex_string_custom (fiseg, "02"));
386 fprintf_filtered (file, "%s\n", local_hex_string_custom (fioff, "08"));
387 fprintf_filtered (file, "Operand Pointer: %s:",
388 local_hex_string_custom (foseg, "02"));
389 fprintf_filtered (file, "%s\n", local_hex_string_custom (fooff, "08"));
390 fprintf_filtered (file, "Opcode: %s\n",
391 local_hex_string_custom (fop ? (fop | 0xd800) : 0, "04"));
de57eccd 392}
e750d25e
JT
393
394/* FIXME: kettenis/2000-05-21: Right now more than a few i386 targets
395 define their own routines to manage the floating-point registers in
396 GDB's register array. Most (if not all) of these targets use the
397 format used by the "fsave" instruction in their communication with
398 the OS. They should all be converted to use the routines below. */
399
400/* At fsave_offset[REGNUM] you'll find the offset to the location in
401 the data structure used by the "fsave" instruction where GDB
402 register REGNUM is stored. */
403
404static int fsave_offset[] =
405{
406 28 + 0 * FPU_REG_RAW_SIZE, /* FP0_REGNUM through ... */
407 28 + 1 * FPU_REG_RAW_SIZE,
408 28 + 2 * FPU_REG_RAW_SIZE,
409 28 + 3 * FPU_REG_RAW_SIZE,
410 28 + 4 * FPU_REG_RAW_SIZE,
411 28 + 5 * FPU_REG_RAW_SIZE,
412 28 + 6 * FPU_REG_RAW_SIZE,
413 28 + 7 * FPU_REG_RAW_SIZE, /* ... FP7_REGNUM. */
414 0, /* FCTRL_REGNUM (16 bits). */
415 4, /* FSTAT_REGNUM (16 bits). */
416 8, /* FTAG_REGNUM (16 bits). */
417 16, /* FISEG_REGNUM (16 bits). */
418 12, /* FIOFF_REGNUM. */
419 24, /* FOSEG_REGNUM. */
420 20, /* FOOFF_REGNUM. */
421 18 /* FOP_REGNUM (bottom 11 bits). */
422};
423
424#define FSAVE_ADDR(fsave, regnum) (fsave + fsave_offset[regnum - FP0_REGNUM])
425\f
426
427/* Fill register REGNUM in GDB's register array with the appropriate
428 value from *FSAVE. This function masks off any of the reserved
429 bits in *FSAVE. */
430
431void
432i387_supply_register (int regnum, char *fsave)
433{
434 /* Most of the FPU control registers occupy only 16 bits in
435 the fsave area. Give those a special treatment. */
436 if (regnum >= FPC_REGNUM
437 && regnum != FIOFF_REGNUM && regnum != FOOFF_REGNUM)
438 {
439 unsigned char val[4];
440
441 memcpy (val, FSAVE_ADDR (fsave, regnum), 2);
442 val[2] = val[3] = 0;
443 if (regnum == FOP_REGNUM)
444 val[1] &= ((1 << 3) - 1);
445 supply_register (regnum, val);
446 }
447 else
448 supply_register (regnum, FSAVE_ADDR (fsave, regnum));
449}
450
451/* Fill GDB's register array with the floating-point register values
452 in *FSAVE. This function masks off any of the reserved
453 bits in *FSAVE. */
454
455void
456i387_supply_fsave (char *fsave)
457{
458 int i;
459
460 for (i = FP0_REGNUM; i < XMM0_REGNUM; i++)
461 i387_supply_register (i, fsave);
462}
463
464/* Fill register REGNUM (if it is a floating-point register) in *FSAVE
465 with the value in GDB's register array. If REGNUM is -1, do this
466 for all registers. This function doesn't touch any of the reserved
467 bits in *FSAVE. */
468
469void
470i387_fill_fsave (char *fsave, int regnum)
471{
472 int i;
473
474 for (i = FP0_REGNUM; i < XMM0_REGNUM; i++)
475 if (regnum == -1 || regnum == i)
476 {
477 /* Most of the FPU control registers occupy only 16 bits in
478 the fsave area. Give those a special treatment. */
479 if (i >= FPC_REGNUM
480 && i != FIOFF_REGNUM && i != FOOFF_REGNUM)
481 {
482 unsigned char buf[4];
483
484 regcache_collect (i, buf);
485
486 if (i == FOP_REGNUM)
487 {
488 /* The opcode occupies only 11 bits. Make sure we
489 don't touch the other bits. */
490 buf[1] &= ((1 << 3) - 1);
491 buf[1] |= ((FSAVE_ADDR (fsave, i))[1] & ~((1 << 3) - 1));
492 }
493 memcpy (FSAVE_ADDR (fsave, i), buf, 2);
494 }
495 else
496 regcache_collect (i, FSAVE_ADDR (fsave, i));
497 }
498}
499\f
500
501/* At fxsave_offset[REGNUM] you'll find the offset to the location in
502 the data structure used by the "fxsave" instruction where GDB
503 register REGNUM is stored. */
504
505static int fxsave_offset[] =
506{
507 32, /* FP0_REGNUM through ... */
508 48,
509 64,
510 80,
511 96,
512 112,
513 128,
514 144, /* ... FP7_REGNUM (80 bits each). */
515 0, /* FCTRL_REGNUM (16 bits). */
516 2, /* FSTAT_REGNUM (16 bits). */
517 4, /* FTAG_REGNUM (16 bits). */
518 12, /* FISEG_REGNUM (16 bits). */
519 8, /* FIOFF_REGNUM. */
520 20, /* FOSEG_REGNUM (16 bits). */
521 16, /* FOOFF_REGNUM. */
522 6, /* FOP_REGNUM (bottom 11 bits). */
523 160, /* XMM0_REGNUM through ... */
524 176,
525 192,
526 208,
527 224,
528 240,
529 256,
530 272, /* ... XMM7_REGNUM (128 bits each). */
531 24, /* MXCSR_REGNUM. */
532};
533
534#define FXSAVE_ADDR(fxsave, regnum) \
535 (fxsave + fxsave_offset[regnum - FP0_REGNUM])
536
537static int i387_tag (unsigned char *raw);
538\f
539
540/* Fill GDB's register array with the floating-point and SSE register
541 values in *FXSAVE. This function masks off any of the reserved
542 bits in *FXSAVE. */
543
544void
545i387_supply_fxsave (char *fxsave)
546{
dff95cc7
MK
547 int i, last_regnum = MXCSR_REGNUM;
548
549 if (gdbarch_tdep (current_gdbarch)->num_xmm_regs == 0)
550 last_regnum = FOP_REGNUM;
e750d25e 551
dff95cc7 552 for (i = FP0_REGNUM; i <= last_regnum; i++)
e750d25e
JT
553 {
554 /* Most of the FPU control registers occupy only 16 bits in
555 the fxsave area. Give those a special treatment. */
556 if (i >= FPC_REGNUM && i < XMM0_REGNUM
557 && i != FIOFF_REGNUM && i != FOOFF_REGNUM)
558 {
559 unsigned char val[4];
560
561 memcpy (val, FXSAVE_ADDR (fxsave, i), 2);
562 val[2] = val[3] = 0;
563 if (i == FOP_REGNUM)
564 val[1] &= ((1 << 3) - 1);
565 else if (i== FTAG_REGNUM)
566 {
567 /* The fxsave area contains a simplified version of the
568 tag word. We have to look at the actual 80-bit FP
569 data to recreate the traditional i387 tag word. */
570
571 unsigned long ftag = 0;
572 int fpreg;
573 int top;
574
575 top = (((FXSAVE_ADDR (fxsave, FSTAT_REGNUM))[1] >> 3) & 0x7);
576
577 for (fpreg = 7; fpreg >= 0; fpreg--)
578 {
579 int tag;
580
581 if (val[0] & (1 << fpreg))
582 {
583 int regnum = (fpreg + 8 - top) % 8 + FP0_REGNUM;
584 tag = i387_tag (FXSAVE_ADDR (fxsave, regnum));
585 }
586 else
587 tag = 3; /* Empty */
588
589 ftag |= tag << (2 * fpreg);
590 }
591 val[0] = ftag & 0xff;
592 val[1] = (ftag >> 8) & 0xff;
593 }
594 supply_register (i, val);
595 }
596 else
597 supply_register (i, FXSAVE_ADDR (fxsave, i));
598 }
599}
600
601/* Fill register REGNUM (if it is a floating-point or SSE register) in
602 *FXSAVE with the value in GDB's register array. If REGNUM is -1, do
603 this for all registers. This function doesn't touch any of the
604 reserved bits in *FXSAVE. */
605
606void
607i387_fill_fxsave (char *fxsave, int regnum)
608{
dff95cc7
MK
609 int i, last_regnum = MXCSR_REGNUM;
610
611 if (gdbarch_tdep (current_gdbarch)->num_xmm_regs == 0)
612 last_regnum = FOP_REGNUM;
e750d25e 613
dff95cc7 614 for (i = FP0_REGNUM; i <= last_regnum; i++)
e750d25e
JT
615 if (regnum == -1 || regnum == i)
616 {
617 /* Most of the FPU control registers occupy only 16 bits in
618 the fxsave area. Give those a special treatment. */
619 if (i >= FPC_REGNUM && i < XMM0_REGNUM
620 && i != FIOFF_REGNUM && i != FDOFF_REGNUM)
621 {
622 unsigned char buf[4];
623
624 regcache_collect (i, buf);
625
626 if (i == FOP_REGNUM)
627 {
628 /* The opcode occupies only 11 bits. Make sure we
629 don't touch the other bits. */
630 buf[1] &= ((1 << 3) - 1);
631 buf[1] |= ((FXSAVE_ADDR (fxsave, i))[1] & ~((1 << 3) - 1));
632 }
633 else if (i == FTAG_REGNUM)
634 {
635 /* Converting back is much easier. */
636
637 unsigned short ftag;
638 int fpreg;
639
640 ftag = (buf[1] << 8) | buf[0];
641 buf[0] = 0;
642 buf[1] = 0;
643
644 for (fpreg = 7; fpreg >= 0; fpreg--)
645 {
646 int tag = (ftag >> (fpreg * 2)) & 3;
647
648 if (tag != 3)
649 buf[0] |= (1 << fpreg);
650 }
651 }
652 memcpy (FXSAVE_ADDR (fxsave, i), buf, 2);
653 }
654 else
655 regcache_collect (i, FXSAVE_ADDR (fxsave, i));
656 }
657}
658
659/* Recreate the FTW (tag word) valid bits from the 80-bit FP data in
660 *RAW. */
661
662static int
663i387_tag (unsigned char *raw)
664{
665 int integer;
666 unsigned int exponent;
667 unsigned long fraction[2];
668
669 integer = raw[7] & 0x80;
670 exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
671 fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
672 fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
673 | (raw[5] << 8) | raw[4]);
674
675 if (exponent == 0x7fff)
676 {
677 /* Special. */
678 return (2);
679 }
680 else if (exponent == 0x0000)
681 {
682 if (fraction[0] == 0x0000 && fraction[1] == 0x0000 && !integer)
683 {
684 /* Zero. */
685 return (1);
686 }
687 else
688 {
689 /* Special. */
690 return (2);
691 }
692 }
693 else
694 {
695 if (integer)
696 {
697 /* Valid. */
698 return (0);
699 }
700 else
701 {
702 /* Special. */
703 return (2);
704 }
705 }
706}
This page took 0.268939 seconds and 4 git commands to generate.