*** empty log message ***
[deliverable/binutils-gdb.git] / gdb / i387-tdep.c
CommitLineData
c906108c 1/* Intel 387 floating point stuff.
38edeab8 2
6aba47ca 3 Copyright (C) 1988, 1989, 1991, 1992, 1993, 1994, 1998, 1999, 2000, 2001,
9b254dd1 4 2002, 2003, 2004, 2005, 2007, 2008 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
a9762ec7 10 the Free Software Foundation; either version 3 of the License, or
c5aa993b 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 18 You should have received a copy of the GNU General Public License
a9762ec7 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
c906108c
SS
20
21#include "defs.h"
786a90bb
MK
22#include "doublest.h"
23#include "floatformat.h"
c906108c 24#include "frame.h"
786a90bb 25#include "gdbcore.h"
c906108c
SS
26#include "inferior.h"
27#include "language.h"
4e052eda 28#include "regcache.h"
786a90bb
MK
29#include "value.h"
30
d0df8472 31#include "gdb_assert.h"
309367d4 32#include "gdb_string.h"
c906108c 33
9a82579f 34#include "i386-tdep.h"
42c466d7 35#include "i387-tdep.h"
c906108c 36
de57eccd 37/* Print the floating point number specified by RAW. */
786a90bb 38
de57eccd 39static void
b4ad899f 40print_i387_value (const gdb_byte *raw, struct ui_file *file)
de57eccd
JM
41{
42 DOUBLEST value;
4583280c
MK
43
44 /* Using extract_typed_floating here might affect the representation
45 of certain numbers such as NaNs, even if GDB is running natively.
46 This is fine since our caller already detects such special
47 numbers and we print the hexadecimal representation anyway. */
48 value = extract_typed_floating (raw, builtin_type_i387_ext);
de57eccd
JM
49
50 /* We try to print 19 digits. The last digit may or may not contain
51 garbage, but we'd better print one too many. We need enough room
52 to print the value, 1 position for the sign, 1 for the decimal
53 point, 19 for the digits and 6 for the exponent adds up to 27. */
54#ifdef PRINTF_HAS_LONG_DOUBLE
61113f8b 55 fprintf_filtered (file, " %-+27.19Lg", (long double) value);
de57eccd 56#else
61113f8b 57 fprintf_filtered (file, " %-+27.19g", (double) value);
de57eccd
JM
58#endif
59}
60
61/* Print the classification for the register contents RAW. */
786a90bb 62
de57eccd 63static void
b4ad899f 64print_i387_ext (const gdb_byte *raw, struct ui_file *file)
de57eccd
JM
65{
66 int sign;
67 int integer;
68 unsigned int exponent;
69 unsigned long fraction[2];
70
71 sign = raw[9] & 0x80;
72 integer = raw[7] & 0x80;
73 exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
74 fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
75 fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
76 | (raw[5] << 8) | raw[4]);
77
78 if (exponent == 0x7fff && integer)
79 {
80 if (fraction[0] == 0x00000000 && fraction[1] == 0x00000000)
81 /* Infinity. */
61113f8b 82 fprintf_filtered (file, " %cInf", (sign ? '-' : '+'));
de57eccd
JM
83 else if (sign && fraction[0] == 0x00000000 && fraction[1] == 0x40000000)
84 /* Real Indefinite (QNaN). */
61113f8b 85 fputs_unfiltered (" Real Indefinite (QNaN)", file);
de57eccd
JM
86 else if (fraction[1] & 0x40000000)
87 /* QNaN. */
61113f8b 88 fputs_filtered (" QNaN", file);
de57eccd
JM
89 else
90 /* SNaN. */
61113f8b 91 fputs_filtered (" SNaN", file);
de57eccd
JM
92 }
93 else if (exponent < 0x7fff && exponent > 0x0000 && integer)
94 /* Normal. */
61113f8b 95 print_i387_value (raw, file);
de57eccd
JM
96 else if (exponent == 0x0000)
97 {
98 /* Denormal or zero. */
61113f8b 99 print_i387_value (raw, file);
de57eccd
JM
100
101 if (integer)
102 /* Pseudo-denormal. */
61113f8b 103 fputs_filtered (" Pseudo-denormal", file);
de57eccd
JM
104 else if (fraction[0] || fraction[1])
105 /* Denormal. */
61113f8b 106 fputs_filtered (" Denormal", file);
de57eccd
JM
107 }
108 else
109 /* Unsupported. */
61113f8b 110 fputs_filtered (" Unsupported", file);
de57eccd
JM
111}
112
113/* Print the status word STATUS. */
786a90bb 114
de57eccd 115static void
61113f8b 116print_i387_status_word (unsigned int status, struct ui_file *file)
de57eccd 117{
61113f8b 118 fprintf_filtered (file, "Status Word: %s",
bb599908 119 hex_string_custom (status, 4));
61113f8b
MK
120 fputs_filtered (" ", file);
121 fprintf_filtered (file, " %s", (status & 0x0001) ? "IE" : " ");
122 fprintf_filtered (file, " %s", (status & 0x0002) ? "DE" : " ");
123 fprintf_filtered (file, " %s", (status & 0x0004) ? "ZE" : " ");
124 fprintf_filtered (file, " %s", (status & 0x0008) ? "OE" : " ");
125 fprintf_filtered (file, " %s", (status & 0x0010) ? "UE" : " ");
126 fprintf_filtered (file, " %s", (status & 0x0020) ? "PE" : " ");
127 fputs_filtered (" ", file);
128 fprintf_filtered (file, " %s", (status & 0x0080) ? "ES" : " ");
129 fputs_filtered (" ", file);
130 fprintf_filtered (file, " %s", (status & 0x0040) ? "SF" : " ");
131 fputs_filtered (" ", file);
132 fprintf_filtered (file, " %s", (status & 0x0100) ? "C0" : " ");
133 fprintf_filtered (file, " %s", (status & 0x0200) ? "C1" : " ");
134 fprintf_filtered (file, " %s", (status & 0x0400) ? "C2" : " ");
135 fprintf_filtered (file, " %s", (status & 0x4000) ? "C3" : " ");
136
137 fputs_filtered ("\n", file);
138
139 fprintf_filtered (file,
140 " TOP: %d\n", ((status >> 11) & 7));
de57eccd
JM
141}
142
143/* Print the control word CONTROL. */
786a90bb 144
de57eccd 145static void
61113f8b 146print_i387_control_word (unsigned int control, struct ui_file *file)
de57eccd 147{
61113f8b 148 fprintf_filtered (file, "Control Word: %s",
bb599908 149 hex_string_custom (control, 4));
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{
5716833c 203 struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (frame));
b4ad899f 204 gdb_byte buf[4];
1d70089a
MK
205 ULONGEST fctrl;
206 ULONGEST fstat;
207 ULONGEST ftag;
208 ULONGEST fiseg;
209 ULONGEST fioff;
210 ULONGEST foseg;
211 ULONGEST fooff;
212 ULONGEST fop;
de57eccd
JM
213 int fpreg;
214 int top;
215
5716833c
MK
216 gdb_assert (gdbarch == get_frame_arch (frame));
217
218 /* Define I387_ST0_REGNUM such that we use the proper definitions
219 for FRAME's architecture. */
220#define I387_ST0_REGNUM tdep->st0_regnum
221
222 fctrl = get_frame_register_unsigned (frame, I387_FCTRL_REGNUM);
223 fstat = get_frame_register_unsigned (frame, I387_FSTAT_REGNUM);
224 ftag = get_frame_register_unsigned (frame, I387_FTAG_REGNUM);
225 fiseg = get_frame_register_unsigned (frame, I387_FISEG_REGNUM);
226 fioff = get_frame_register_unsigned (frame, I387_FIOFF_REGNUM);
227 foseg = get_frame_register_unsigned (frame, I387_FOSEG_REGNUM);
228 fooff = get_frame_register_unsigned (frame, I387_FOOFF_REGNUM);
229 fop = get_frame_register_unsigned (frame, I387_FOP_REGNUM);
1d70089a 230
de57eccd
JM
231 top = ((fstat >> 11) & 7);
232
233 for (fpreg = 7; fpreg >= 0; fpreg--)
234 {
b4ad899f 235 gdb_byte raw[I386_MAX_REGISTER_SIZE];
de57eccd
JM
236 int tag = (ftag >> (fpreg * 2)) & 3;
237 int i;
238
61113f8b 239 fprintf_filtered (file, "%sR%d: ", fpreg == top ? "=>" : " ", fpreg);
de57eccd
JM
240
241 switch (tag)
242 {
243 case 0:
61113f8b 244 fputs_filtered ("Valid ", file);
de57eccd
JM
245 break;
246 case 1:
61113f8b 247 fputs_filtered ("Zero ", file);
de57eccd
JM
248 break;
249 case 2:
61113f8b 250 fputs_filtered ("Special ", file);
de57eccd
JM
251 break;
252 case 3:
61113f8b 253 fputs_filtered ("Empty ", file);
de57eccd
JM
254 break;
255 }
256
5716833c 257 get_frame_register (frame, (fpreg + 8 - top) % 8 + I387_ST0_REGNUM, raw);
de57eccd 258
61113f8b 259 fputs_filtered ("0x", file);
de57eccd 260 for (i = 9; i >= 0; i--)
61113f8b 261 fprintf_filtered (file, "%02x", raw[i]);
de57eccd
JM
262
263 if (tag != 3)
61113f8b 264 print_i387_ext (raw, file);
de57eccd 265
61113f8b 266 fputs_filtered ("\n", file);
de57eccd
JM
267 }
268
f16a25ae 269 fputs_filtered ("\n", file);
de57eccd 270
61113f8b
MK
271 print_i387_status_word (fstat, file);
272 print_i387_control_word (fctrl, file);
273 fprintf_filtered (file, "Tag Word: %s\n",
bb599908 274 hex_string_custom (ftag, 4));
61113f8b 275 fprintf_filtered (file, "Instruction Pointer: %s:",
bb599908
PH
276 hex_string_custom (fiseg, 2));
277 fprintf_filtered (file, "%s\n", hex_string_custom (fioff, 8));
61113f8b 278 fprintf_filtered (file, "Operand Pointer: %s:",
bb599908
PH
279 hex_string_custom (foseg, 2));
280 fprintf_filtered (file, "%s\n", hex_string_custom (fooff, 8));
61113f8b 281 fprintf_filtered (file, "Opcode: %s\n",
bb599908 282 hex_string_custom (fop ? (fop | 0xd800) : 0, 4));
5716833c
MK
283
284#undef I387_ST0_REGNUM
de57eccd 285}
d532c08f
MK
286\f
287
83acabca
DJ
288/* Return nonzero if a value of type TYPE stored in register REGNUM
289 needs any special handling. */
290
291int
0abe36f5 292i387_convert_register_p (struct gdbarch *gdbarch, int regnum, struct type *type)
83acabca
DJ
293{
294 if (i386_fp_regnum_p (regnum))
295 {
296 /* Floating point registers must be converted unless we are
297 accessing them in their hardware type. */
298 if (type == builtin_type_i387_ext)
299 return 0;
300 else
301 return 1;
302 }
303
304 return 0;
305}
306
d532c08f
MK
307/* Read a value of type TYPE from register REGNUM in frame FRAME, and
308 return its contents in TO. */
309
310void
311i387_register_to_value (struct frame_info *frame, int regnum,
42835c2b 312 struct type *type, gdb_byte *to)
d532c08f 313{
b4ad899f 314 gdb_byte from[I386_MAX_REGISTER_SIZE];
d532c08f
MK
315
316 gdb_assert (i386_fp_regnum_p (regnum));
317
318 /* We only support floating-point values. */
319 if (TYPE_CODE (type) != TYPE_CODE_FLT)
320 {
8a3fe4f8
AC
321 warning (_("Cannot convert floating-point register value "
322 "to non-floating-point type."));
d532c08f
MK
323 return;
324 }
325
83acabca 326 /* Convert to TYPE. */
192285c6 327 get_frame_register (frame, regnum, from);
d532c08f
MK
328 convert_typed_floating (from, builtin_type_i387_ext, to, type);
329}
330
331/* Write the contents FROM of a value of type TYPE into register
332 REGNUM in frame FRAME. */
333
334void
335i387_value_to_register (struct frame_info *frame, int regnum,
42835c2b 336 struct type *type, const gdb_byte *from)
d532c08f 337{
b4ad899f 338 gdb_byte to[I386_MAX_REGISTER_SIZE];
d532c08f
MK
339
340 gdb_assert (i386_fp_regnum_p (regnum));
341
342 /* We only support floating-point values. */
343 if (TYPE_CODE (type) != TYPE_CODE_FLT)
344 {
8a3fe4f8
AC
345 warning (_("Cannot convert non-floating-point type "
346 "to floating-point register value."));
d532c08f
MK
347 return;
348 }
349
83acabca 350 /* Convert from TYPE. */
d532c08f
MK
351 convert_typed_floating (from, type, to, builtin_type_i387_ext);
352 put_frame_register (frame, regnum, to);
353}
354\f
e750d25e 355
786a90bb 356/* Handle FSAVE and FXSAVE formats. */
e750d25e
JT
357
358/* At fsave_offset[REGNUM] you'll find the offset to the location in
359 the data structure used by the "fsave" instruction where GDB
360 register REGNUM is stored. */
361
362static int fsave_offset[] =
363{
5716833c
MK
364 28 + 0 * 10, /* %st(0) ... */
365 28 + 1 * 10,
366 28 + 2 * 10,
367 28 + 3 * 10,
368 28 + 4 * 10,
369 28 + 5 * 10,
370 28 + 6 * 10,
371 28 + 7 * 10, /* ... %st(7). */
372 0, /* `fctrl' (16 bits). */
373 4, /* `fstat' (16 bits). */
374 8, /* `ftag' (16 bits). */
375 16, /* `fiseg' (16 bits). */
376 12, /* `fioff'. */
377 24, /* `foseg' (16 bits). */
378 20, /* `fooff'. */
379 18 /* `fop' (bottom 11 bits). */
e750d25e
JT
380};
381
5716833c
MK
382#define FSAVE_ADDR(fsave, regnum) \
383 (fsave + fsave_offset[regnum - I387_ST0_REGNUM])
e750d25e
JT
384\f
385
41d041d6
MK
386/* Fill register REGNUM in REGCACHE with the appropriate value from
387 *FSAVE. This function masks off any of the reserved bits in
388 *FSAVE. */
e750d25e
JT
389
390void
41d041d6 391i387_supply_fsave (struct regcache *regcache, int regnum, const void *fsave)
e750d25e 392{
41d041d6 393 struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
b4ad899f 394 const gdb_byte *regs = fsave;
e750d25e
JT
395 int i;
396
5716833c
MK
397 gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
398
b87bc0d8
MK
399 /* Define I387_ST0_REGNUM and I387_NUM_XMM_REGS such that we use the
400 proper definitions for REGCACHE's architecture. */
401
5716833c 402#define I387_ST0_REGNUM tdep->st0_regnum
b87bc0d8 403#define I387_NUM_XMM_REGS tdep->num_xmm_regs
5716833c
MK
404
405 for (i = I387_ST0_REGNUM; i < I387_XMM0_REGNUM; i++)
ed504bdf
MK
406 if (regnum == -1 || regnum == i)
407 {
408 if (fsave == NULL)
409 {
5716833c
MK
410 regcache_raw_supply (regcache, i, NULL);
411 continue;
ed504bdf
MK
412 }
413
414 /* Most of the FPU control registers occupy only 16 bits in the
415 fsave area. Give those a special treatment. */
5716833c
MK
416 if (i >= I387_FCTRL_REGNUM
417 && i != I387_FIOFF_REGNUM && i != I387_FOOFF_REGNUM)
ed504bdf 418 {
b4ad899f 419 gdb_byte val[4];
ed504bdf 420
5716833c 421 memcpy (val, FSAVE_ADDR (regs, i), 2);
ed504bdf 422 val[2] = val[3] = 0;
5716833c 423 if (i == I387_FOP_REGNUM)
ed504bdf 424 val[1] &= ((1 << 3) - 1);
5716833c 425 regcache_raw_supply (regcache, i, val);
ed504bdf
MK
426 }
427 else
5716833c 428 regcache_raw_supply (regcache, i, FSAVE_ADDR (regs, i));
ed504bdf 429 }
b87bc0d8
MK
430
431 /* Provide dummy values for the SSE registers. */
432 for (i = I387_XMM0_REGNUM; i < I387_MXCSR_REGNUM; i++)
433 if (regnum == -1 || regnum == i)
434 regcache_raw_supply (regcache, i, NULL);
435 if (regnum == -1 || regnum == I387_MXCSR_REGNUM)
436 {
b4ad899f 437 gdb_byte buf[4];
b87bc0d8
MK
438
439 store_unsigned_integer (buf, 4, 0x1f80);
440 regcache_raw_supply (regcache, I387_MXCSR_REGNUM, buf);
441 }
442
5716833c 443#undef I387_ST0_REGNUM
b87bc0d8 444#undef I387_NUM_XMM_REGS
e750d25e
JT
445}
446
447/* Fill register REGNUM (if it is a floating-point register) in *FSAVE
63b6c53f
MK
448 with the value from REGCACHE. If REGNUM is -1, do this for all
449 registers. This function doesn't touch any of the reserved bits in
450 *FSAVE. */
e750d25e
JT
451
452void
63b6c53f 453i387_collect_fsave (const struct regcache *regcache, int regnum, void *fsave)
e750d25e 454{
e071d1f6 455 struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
b4ad899f 456 gdb_byte *regs = fsave;
e750d25e
JT
457 int i;
458
5716833c
MK
459 gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
460
461 /* Define I387_ST0_REGNUM such that we use the proper definitions
462 for REGCACHE's architecture. */
463#define I387_ST0_REGNUM tdep->st0_regnum
464
465 for (i = I387_ST0_REGNUM; i < I387_XMM0_REGNUM; i++)
e750d25e
JT
466 if (regnum == -1 || regnum == i)
467 {
468 /* Most of the FPU control registers occupy only 16 bits in
469 the fsave area. Give those a special treatment. */
5716833c
MK
470 if (i >= I387_FCTRL_REGNUM
471 && i != I387_FIOFF_REGNUM && i != I387_FOOFF_REGNUM)
e750d25e 472 {
b4ad899f 473 gdb_byte buf[4];
e750d25e 474
5716833c 475 regcache_raw_collect (regcache, i, buf);
e750d25e 476
5716833c 477 if (i == I387_FOP_REGNUM)
e750d25e
JT
478 {
479 /* The opcode occupies only 11 bits. Make sure we
480 don't touch the other bits. */
481 buf[1] &= ((1 << 3) - 1);
5716833c 482 buf[1] |= ((FSAVE_ADDR (regs, i))[1] & ~((1 << 3) - 1));
e750d25e 483 }
5716833c 484 memcpy (FSAVE_ADDR (regs, i), buf, 2);
e750d25e
JT
485 }
486 else
5716833c 487 regcache_raw_collect (regcache, i, FSAVE_ADDR (regs, i));
e750d25e 488 }
5716833c 489#undef I387_ST0_REGNUM
e750d25e
JT
490}
491\f
492
493/* At fxsave_offset[REGNUM] you'll find the offset to the location in
494 the data structure used by the "fxsave" instruction where GDB
495 register REGNUM is stored. */
496
497static int fxsave_offset[] =
498{
5716833c 499 32, /* %st(0) through ... */
e750d25e
JT
500 48,
501 64,
502 80,
503 96,
504 112,
505 128,
5716833c
MK
506 144, /* ... %st(7) (80 bits each). */
507 0, /* `fctrl' (16 bits). */
508 2, /* `fstat' (16 bits). */
509 4, /* `ftag' (16 bits). */
510 12, /* `fiseg' (16 bits). */
511 8, /* `fioff'. */
512 20, /* `foseg' (16 bits). */
513 16, /* `fooff'. */
514 6, /* `fop' (bottom 11 bits). */
515 160 + 0 * 16, /* %xmm0 through ... */
04c8243f
MK
516 160 + 1 * 16,
517 160 + 2 * 16,
518 160 + 3 * 16,
519 160 + 4 * 16,
520 160 + 5 * 16,
521 160 + 6 * 16,
522 160 + 7 * 16,
523 160 + 8 * 16,
524 160 + 9 * 16,
525 160 + 10 * 16,
526 160 + 11 * 16,
527 160 + 12 * 16,
528 160 + 13 * 16,
529 160 + 14 * 16,
5716833c 530 160 + 15 * 16, /* ... %xmm15 (128 bits each). */
e750d25e
JT
531};
532
533#define FXSAVE_ADDR(fxsave, regnum) \
5716833c
MK
534 (fxsave + fxsave_offset[regnum - I387_ST0_REGNUM])
535
536/* We made an unfortunate choice in putting %mxcsr after the SSE
537 registers %xmm0-%xmm7 instead of before, since it makes supporting
538 the registers %xmm8-%xmm15 on AMD64 a bit involved. Therefore we
539 don't include the offset for %mxcsr here above. */
540
541#define FXSAVE_MXCSR_ADDR(fxsave) (fxsave + 24)
e750d25e 542
b4ad899f 543static int i387_tag (const gdb_byte *raw);
e750d25e
JT
544\f
545
41d041d6 546/* Fill register REGNUM in REGCACHE with the appropriate
ed504bdf
MK
547 floating-point or SSE register value from *FXSAVE. This function
548 masks off any of the reserved bits in *FXSAVE. */
e750d25e
JT
549
550void
41d041d6 551i387_supply_fxsave (struct regcache *regcache, int regnum, const void *fxsave)
e750d25e 552{
41d041d6 553 struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
b4ad899f 554 const gdb_byte *regs = fxsave;
5716833c
MK
555 int i;
556
557 gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
558 gdb_assert (tdep->num_xmm_regs > 0);
dff95cc7 559
5716833c
MK
560 /* Define I387_ST0_REGNUM and I387_NUM_XMM_REGS such that we use the
561 proper definitions for REGCACHE's architecture. */
e750d25e 562
5716833c
MK
563#define I387_ST0_REGNUM tdep->st0_regnum
564#define I387_NUM_XMM_REGS tdep->num_xmm_regs
565
566 for (i = I387_ST0_REGNUM; i < I387_MXCSR_REGNUM; i++)
ed504bdf
MK
567 if (regnum == -1 || regnum == i)
568 {
5716833c 569 if (regs == NULL)
ed504bdf 570 {
5716833c 571 regcache_raw_supply (regcache, i, NULL);
ed504bdf
MK
572 continue;
573 }
932bb524 574
ed504bdf
MK
575 /* Most of the FPU control registers occupy only 16 bits in
576 the fxsave area. Give those a special treatment. */
5716833c
MK
577 if (i >= I387_FCTRL_REGNUM && i < I387_XMM0_REGNUM
578 && i != I387_FIOFF_REGNUM && i != I387_FOOFF_REGNUM)
ed504bdf 579 {
b4ad899f 580 gdb_byte val[4];
ed504bdf 581
5716833c 582 memcpy (val, FXSAVE_ADDR (regs, i), 2);
ed504bdf 583 val[2] = val[3] = 0;
5716833c 584 if (i == I387_FOP_REGNUM)
ed504bdf 585 val[1] &= ((1 << 3) - 1);
5716833c 586 else if (i== I387_FTAG_REGNUM)
ed504bdf
MK
587 {
588 /* The fxsave area contains a simplified version of
589 the tag word. We have to look at the actual 80-bit
590 FP data to recreate the traditional i387 tag word. */
591
592 unsigned long ftag = 0;
593 int fpreg;
594 int top;
595
5716833c
MK
596 top = ((FXSAVE_ADDR (regs, I387_FSTAT_REGNUM))[1] >> 3);
597 top &= 0x7;
ed504bdf
MK
598
599 for (fpreg = 7; fpreg >= 0; fpreg--)
600 {
601 int tag;
602
603 if (val[0] & (1 << fpreg))
604 {
5716833c
MK
605 int regnum = (fpreg + 8 - top) % 8 + I387_ST0_REGNUM;
606 tag = i387_tag (FXSAVE_ADDR (regs, regnum));
ed504bdf
MK
607 }
608 else
609 tag = 3; /* Empty */
610
611 ftag |= tag << (2 * fpreg);
612 }
613 val[0] = ftag & 0xff;
614 val[1] = (ftag >> 8) & 0xff;
615 }
5716833c 616 regcache_raw_supply (regcache, i, val);
ed504bdf
MK
617 }
618 else
5716833c 619 regcache_raw_supply (regcache, i, FXSAVE_ADDR (regs, i));
ed504bdf 620 }
5716833c
MK
621
622 if (regnum == I387_MXCSR_REGNUM || regnum == -1)
623 {
624 if (regs == NULL)
625 regcache_raw_supply (regcache, I387_MXCSR_REGNUM, NULL);
626 else
627 regcache_raw_supply (regcache, I387_MXCSR_REGNUM,
628 FXSAVE_MXCSR_ADDR (regs));
629 }
630
631#undef I387_ST0_REGNUM
632#undef I387_NUM_XMM_REGS
e750d25e
JT
633}
634
635/* Fill register REGNUM (if it is a floating-point or SSE register) in
80571bff
MK
636 *FXSAVE with the value from REGCACHE. If REGNUM is -1, do this for
637 all registers. This function doesn't touch any of the reserved
638 bits in *FXSAVE. */
e750d25e
JT
639
640void
80571bff 641i387_collect_fxsave (const struct regcache *regcache, int regnum, void *fxsave)
e750d25e 642{
e071d1f6 643 struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
b4ad899f 644 gdb_byte *regs = fxsave;
5716833c
MK
645 int i;
646
647 gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
648 gdb_assert (tdep->num_xmm_regs > 0);
dff95cc7 649
5716833c
MK
650 /* Define I387_ST0_REGNUM and I387_NUM_XMM_REGS such that we use the
651 proper definitions for REGCACHE's architecture. */
e750d25e 652
5716833c
MK
653#define I387_ST0_REGNUM tdep->st0_regnum
654#define I387_NUM_XMM_REGS tdep->num_xmm_regs
655
656 for (i = I387_ST0_REGNUM; i < I387_MXCSR_REGNUM; i++)
e750d25e
JT
657 if (regnum == -1 || regnum == i)
658 {
659 /* Most of the FPU control registers occupy only 16 bits in
660 the fxsave area. Give those a special treatment. */
5716833c
MK
661 if (i >= I387_FCTRL_REGNUM && i < I387_XMM0_REGNUM
662 && i != I387_FIOFF_REGNUM && i != I387_FOOFF_REGNUM)
e750d25e 663 {
b4ad899f 664 gdb_byte buf[4];
e750d25e 665
5716833c 666 regcache_raw_collect (regcache, i, buf);
e750d25e 667
5716833c 668 if (i == I387_FOP_REGNUM)
e750d25e
JT
669 {
670 /* The opcode occupies only 11 bits. Make sure we
671 don't touch the other bits. */
672 buf[1] &= ((1 << 3) - 1);
5716833c 673 buf[1] |= ((FXSAVE_ADDR (regs, i))[1] & ~((1 << 3) - 1));
e750d25e 674 }
5716833c 675 else if (i == I387_FTAG_REGNUM)
e750d25e
JT
676 {
677 /* Converting back is much easier. */
678
679 unsigned short ftag;
680 int fpreg;
681
682 ftag = (buf[1] << 8) | buf[0];
683 buf[0] = 0;
684 buf[1] = 0;
685
686 for (fpreg = 7; fpreg >= 0; fpreg--)
687 {
688 int tag = (ftag >> (fpreg * 2)) & 3;
689
690 if (tag != 3)
691 buf[0] |= (1 << fpreg);
692 }
693 }
5716833c 694 memcpy (FXSAVE_ADDR (regs, i), buf, 2);
e750d25e
JT
695 }
696 else
5716833c 697 regcache_raw_collect (regcache, i, FXSAVE_ADDR (regs, i));
e750d25e 698 }
5716833c
MK
699
700 if (regnum == I387_MXCSR_REGNUM || regnum == -1)
701 regcache_raw_collect (regcache, I387_MXCSR_REGNUM,
702 FXSAVE_MXCSR_ADDR (regs));
703
704#undef I387_ST0_REGNUM
705#undef I387_NUM_XMM_REGS
e750d25e
JT
706}
707
708/* Recreate the FTW (tag word) valid bits from the 80-bit FP data in
709 *RAW. */
710
711static int
b4ad899f 712i387_tag (const gdb_byte *raw)
e750d25e
JT
713{
714 int integer;
715 unsigned int exponent;
716 unsigned long fraction[2];
717
718 integer = raw[7] & 0x80;
719 exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
720 fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
721 fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
722 | (raw[5] << 8) | raw[4]);
723
724 if (exponent == 0x7fff)
725 {
726 /* Special. */
727 return (2);
728 }
729 else if (exponent == 0x0000)
730 {
731 if (fraction[0] == 0x0000 && fraction[1] == 0x0000 && !integer)
732 {
733 /* Zero. */
734 return (1);
735 }
736 else
737 {
738 /* Special. */
739 return (2);
740 }
741 }
742 else
743 {
744 if (integer)
745 {
746 /* Valid. */
747 return (0);
748 }
749 else
750 {
751 /* Special. */
752 return (2);
753 }
754 }
755}
efb1c01c
MK
756
757/* Prepare the FPU stack in REGCACHE for a function return. */
758
759void
760i387_return_value (struct gdbarch *gdbarch, struct regcache *regcache)
761{
762 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
763 ULONGEST fstat;
764
765 /* Define I387_ST0_REGNUM such that we use the proper
766 definitions for the architecture. */
767#define I387_ST0_REGNUM tdep->st0_regnum
768
769 /* Set the top of the floating-point register stack to 7. The
770 actual value doesn't really matter, but 7 is what a normal
771 function return would end up with if the program started out with
772 a freshly initialized FPU. */
773 regcache_raw_read_unsigned (regcache, I387_FSTAT_REGNUM, &fstat);
774 fstat |= (7 << 11);
775 regcache_raw_write_unsigned (regcache, I387_FSTAT_REGNUM, fstat);
776
777 /* Mark %st(1) through %st(7) as empty. Since we set the top of the
778 floating-point register stack to 7, the appropriate value for the
779 tag word is 0x3fff. */
780 regcache_raw_write_unsigned (regcache, I387_FTAG_REGNUM, 0x3fff);
781
782#undef I387_ST0_REGNUM
783}
This page took 0.645626 seconds and 4 git commands to generate.