* gdb.cp/gdb2495.exp: Skip if gdb,nosignals.
[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,
4c38e0a4
JB
4 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010
5 Free Software Foundation, Inc.
c906108c 6
c5aa993b 7 This file is part of GDB.
c906108c 8
c5aa993b
JM
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
a9762ec7 11 the Free Software Foundation; either version 3 of the License, or
c5aa993b 12 (at your option) any later version.
c906108c 13
c5aa993b
JM
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
c906108c 18
c5aa993b 19 You should have received a copy of the GNU General Public License
a9762ec7 20 along with this program. If not, see <http://www.gnu.org/licenses/>. */
c906108c
SS
21
22#include "defs.h"
786a90bb
MK
23#include "doublest.h"
24#include "floatformat.h"
c906108c 25#include "frame.h"
786a90bb 26#include "gdbcore.h"
c906108c
SS
27#include "inferior.h"
28#include "language.h"
4e052eda 29#include "regcache.h"
786a90bb
MK
30#include "value.h"
31
d0df8472 32#include "gdb_assert.h"
309367d4 33#include "gdb_string.h"
c906108c 34
9a82579f 35#include "i386-tdep.h"
42c466d7 36#include "i387-tdep.h"
c906108c 37
de57eccd 38/* Print the floating point number specified by RAW. */
786a90bb 39
de57eccd 40static void
27067745
UW
41print_i387_value (struct gdbarch *gdbarch,
42 const gdb_byte *raw, struct ui_file *file)
de57eccd
JM
43{
44 DOUBLEST value;
4583280c
MK
45
46 /* Using extract_typed_floating here might affect the representation
47 of certain numbers such as NaNs, even if GDB is running natively.
48 This is fine since our caller already detects such special
49 numbers and we print the hexadecimal representation anyway. */
27067745 50 value = extract_typed_floating (raw, i387_ext_type (gdbarch));
de57eccd
JM
51
52 /* We try to print 19 digits. The last digit may or may not contain
53 garbage, but we'd better print one too many. We need enough room
54 to print the value, 1 position for the sign, 1 for the decimal
55 point, 19 for the digits and 6 for the exponent adds up to 27. */
56#ifdef PRINTF_HAS_LONG_DOUBLE
61113f8b 57 fprintf_filtered (file, " %-+27.19Lg", (long double) value);
de57eccd 58#else
61113f8b 59 fprintf_filtered (file, " %-+27.19g", (double) value);
de57eccd
JM
60#endif
61}
62
63/* Print the classification for the register contents RAW. */
786a90bb 64
de57eccd 65static void
27067745
UW
66print_i387_ext (struct gdbarch *gdbarch,
67 const gdb_byte *raw, struct ui_file *file)
de57eccd
JM
68{
69 int sign;
70 int integer;
71 unsigned int exponent;
72 unsigned long fraction[2];
73
74 sign = raw[9] & 0x80;
75 integer = raw[7] & 0x80;
76 exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
77 fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
78 fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
79 | (raw[5] << 8) | raw[4]);
80
81 if (exponent == 0x7fff && integer)
82 {
83 if (fraction[0] == 0x00000000 && fraction[1] == 0x00000000)
84 /* Infinity. */
61113f8b 85 fprintf_filtered (file, " %cInf", (sign ? '-' : '+'));
de57eccd
JM
86 else if (sign && fraction[0] == 0x00000000 && fraction[1] == 0x40000000)
87 /* Real Indefinite (QNaN). */
61113f8b 88 fputs_unfiltered (" Real Indefinite (QNaN)", file);
de57eccd
JM
89 else if (fraction[1] & 0x40000000)
90 /* QNaN. */
61113f8b 91 fputs_filtered (" QNaN", file);
de57eccd
JM
92 else
93 /* SNaN. */
61113f8b 94 fputs_filtered (" SNaN", file);
de57eccd
JM
95 }
96 else if (exponent < 0x7fff && exponent > 0x0000 && integer)
97 /* Normal. */
27067745 98 print_i387_value (gdbarch, raw, file);
de57eccd
JM
99 else if (exponent == 0x0000)
100 {
101 /* Denormal or zero. */
27067745 102 print_i387_value (gdbarch, raw, file);
de57eccd
JM
103
104 if (integer)
105 /* Pseudo-denormal. */
61113f8b 106 fputs_filtered (" Pseudo-denormal", file);
de57eccd
JM
107 else if (fraction[0] || fraction[1])
108 /* Denormal. */
61113f8b 109 fputs_filtered (" Denormal", file);
de57eccd
JM
110 }
111 else
112 /* Unsupported. */
61113f8b 113 fputs_filtered (" Unsupported", file);
de57eccd
JM
114}
115
116/* Print the status word STATUS. */
786a90bb 117
de57eccd 118static void
61113f8b 119print_i387_status_word (unsigned int status, struct ui_file *file)
de57eccd 120{
61113f8b 121 fprintf_filtered (file, "Status Word: %s",
bb599908 122 hex_string_custom (status, 4));
61113f8b
MK
123 fputs_filtered (" ", file);
124 fprintf_filtered (file, " %s", (status & 0x0001) ? "IE" : " ");
125 fprintf_filtered (file, " %s", (status & 0x0002) ? "DE" : " ");
126 fprintf_filtered (file, " %s", (status & 0x0004) ? "ZE" : " ");
127 fprintf_filtered (file, " %s", (status & 0x0008) ? "OE" : " ");
128 fprintf_filtered (file, " %s", (status & 0x0010) ? "UE" : " ");
129 fprintf_filtered (file, " %s", (status & 0x0020) ? "PE" : " ");
130 fputs_filtered (" ", file);
131 fprintf_filtered (file, " %s", (status & 0x0080) ? "ES" : " ");
132 fputs_filtered (" ", file);
133 fprintf_filtered (file, " %s", (status & 0x0040) ? "SF" : " ");
134 fputs_filtered (" ", file);
135 fprintf_filtered (file, " %s", (status & 0x0100) ? "C0" : " ");
136 fprintf_filtered (file, " %s", (status & 0x0200) ? "C1" : " ");
137 fprintf_filtered (file, " %s", (status & 0x0400) ? "C2" : " ");
138 fprintf_filtered (file, " %s", (status & 0x4000) ? "C3" : " ");
139
140 fputs_filtered ("\n", file);
141
142 fprintf_filtered (file,
143 " TOP: %d\n", ((status >> 11) & 7));
de57eccd
JM
144}
145
146/* Print the control word CONTROL. */
786a90bb 147
de57eccd 148static void
61113f8b 149print_i387_control_word (unsigned int control, struct ui_file *file)
de57eccd 150{
61113f8b 151 fprintf_filtered (file, "Control Word: %s",
bb599908 152 hex_string_custom (control, 4));
61113f8b
MK
153 fputs_filtered (" ", file);
154 fprintf_filtered (file, " %s", (control & 0x0001) ? "IM" : " ");
155 fprintf_filtered (file, " %s", (control & 0x0002) ? "DM" : " ");
156 fprintf_filtered (file, " %s", (control & 0x0004) ? "ZM" : " ");
157 fprintf_filtered (file, " %s", (control & 0x0008) ? "OM" : " ");
158 fprintf_filtered (file, " %s", (control & 0x0010) ? "UM" : " ");
159 fprintf_filtered (file, " %s", (control & 0x0020) ? "PM" : " ");
de57eccd 160
61113f8b 161 fputs_filtered ("\n", file);
de57eccd 162
61113f8b 163 fputs_filtered (" PC: ", file);
de57eccd
JM
164 switch ((control >> 8) & 3)
165 {
166 case 0:
61113f8b 167 fputs_filtered ("Single Precision (24-bits)\n", file);
de57eccd
JM
168 break;
169 case 1:
61113f8b 170 fputs_filtered ("Reserved\n", file);
de57eccd
JM
171 break;
172 case 2:
61113f8b 173 fputs_filtered ("Double Precision (53-bits)\n", file);
de57eccd
JM
174 break;
175 case 3:
61113f8b 176 fputs_filtered ("Extended Precision (64-bits)\n", file);
de57eccd
JM
177 break;
178 }
179
61113f8b 180 fputs_filtered (" RC: ", file);
de57eccd
JM
181 switch ((control >> 10) & 3)
182 {
183 case 0:
61113f8b 184 fputs_filtered ("Round to nearest\n", file);
de57eccd
JM
185 break;
186 case 1:
61113f8b 187 fputs_filtered ("Round down\n", file);
de57eccd
JM
188 break;
189 case 2:
61113f8b 190 fputs_filtered ("Round up\n", file);
de57eccd
JM
191 break;
192 case 3:
61113f8b 193 fputs_filtered ("Round toward zero\n", file);
de57eccd
JM
194 break;
195 }
196}
197
9b949a49 198/* Print out the i387 floating point state. Note that we ignore FRAME
7d8d2918
MK
199 in the code below. That's OK since floating-point registers are
200 never saved on the stack. */
201
de57eccd 202void
61113f8b 203i387_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
8e186fd6 204 struct frame_info *frame, const char *args)
de57eccd 205{
5716833c 206 struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (frame));
b4ad899f 207 gdb_byte buf[4];
1d70089a
MK
208 ULONGEST fctrl;
209 ULONGEST fstat;
210 ULONGEST ftag;
211 ULONGEST fiseg;
212 ULONGEST fioff;
213 ULONGEST foseg;
214 ULONGEST fooff;
215 ULONGEST fop;
de57eccd
JM
216 int fpreg;
217 int top;
218
5716833c
MK
219 gdb_assert (gdbarch == get_frame_arch (frame));
220
20a6ec49
MD
221 fctrl = get_frame_register_unsigned (frame, I387_FCTRL_REGNUM (tdep));
222 fstat = get_frame_register_unsigned (frame, I387_FSTAT_REGNUM (tdep));
223 ftag = get_frame_register_unsigned (frame, I387_FTAG_REGNUM (tdep));
224 fiseg = get_frame_register_unsigned (frame, I387_FISEG_REGNUM (tdep));
225 fioff = get_frame_register_unsigned (frame, I387_FIOFF_REGNUM (tdep));
226 foseg = get_frame_register_unsigned (frame, I387_FOSEG_REGNUM (tdep));
227 fooff = get_frame_register_unsigned (frame, I387_FOOFF_REGNUM (tdep));
228 fop = get_frame_register_unsigned (frame, I387_FOP_REGNUM (tdep));
1d70089a 229
de57eccd
JM
230 top = ((fstat >> 11) & 7);
231
232 for (fpreg = 7; fpreg >= 0; fpreg--)
233 {
b4ad899f 234 gdb_byte raw[I386_MAX_REGISTER_SIZE];
de57eccd
JM
235 int tag = (ftag >> (fpreg * 2)) & 3;
236 int i;
237
61113f8b 238 fprintf_filtered (file, "%sR%d: ", fpreg == top ? "=>" : " ", fpreg);
de57eccd
JM
239
240 switch (tag)
241 {
242 case 0:
61113f8b 243 fputs_filtered ("Valid ", file);
de57eccd
JM
244 break;
245 case 1:
61113f8b 246 fputs_filtered ("Zero ", file);
de57eccd
JM
247 break;
248 case 2:
61113f8b 249 fputs_filtered ("Special ", file);
de57eccd
JM
250 break;
251 case 3:
61113f8b 252 fputs_filtered ("Empty ", file);
de57eccd
JM
253 break;
254 }
255
20a6ec49
MD
256 get_frame_register (frame, (fpreg + 8 - top) % 8 + I387_ST0_REGNUM (tdep),
257 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)
27067745 264 print_i387_ext (gdbarch, 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));
de57eccd 283}
d532c08f
MK
284\f
285
83acabca
DJ
286/* Return nonzero if a value of type TYPE stored in register REGNUM
287 needs any special handling. */
288
289int
0abe36f5 290i387_convert_register_p (struct gdbarch *gdbarch, int regnum, struct type *type)
83acabca 291{
20a6ec49 292 if (i386_fp_regnum_p (gdbarch, regnum))
83acabca
DJ
293 {
294 /* Floating point registers must be converted unless we are
295 accessing them in their hardware type. */
27067745 296 if (type == i387_ext_type (gdbarch))
83acabca
DJ
297 return 0;
298 else
299 return 1;
300 }
301
302 return 0;
303}
304
d532c08f
MK
305/* Read a value of type TYPE from register REGNUM in frame FRAME, and
306 return its contents in TO. */
307
308void
309i387_register_to_value (struct frame_info *frame, int regnum,
42835c2b 310 struct type *type, gdb_byte *to)
d532c08f 311{
27067745 312 struct gdbarch *gdbarch = get_frame_arch (frame);
b4ad899f 313 gdb_byte from[I386_MAX_REGISTER_SIZE];
d532c08f 314
27067745 315 gdb_assert (i386_fp_regnum_p (gdbarch, regnum));
d532c08f
MK
316
317 /* We only support floating-point values. */
318 if (TYPE_CODE (type) != TYPE_CODE_FLT)
319 {
8a3fe4f8
AC
320 warning (_("Cannot convert floating-point register value "
321 "to non-floating-point type."));
d532c08f
MK
322 return;
323 }
324
83acabca 325 /* Convert to TYPE. */
192285c6 326 get_frame_register (frame, regnum, from);
27067745 327 convert_typed_floating (from, i387_ext_type (gdbarch), to, type);
d532c08f
MK
328}
329
330/* Write the contents FROM of a value of type TYPE into register
331 REGNUM in frame FRAME. */
332
333void
334i387_value_to_register (struct frame_info *frame, int regnum,
42835c2b 335 struct type *type, const gdb_byte *from)
d532c08f 336{
27067745 337 struct gdbarch *gdbarch = get_frame_arch (frame);
b4ad899f 338 gdb_byte to[I386_MAX_REGISTER_SIZE];
d532c08f 339
27067745 340 gdb_assert (i386_fp_regnum_p (gdbarch, regnum));
d532c08f
MK
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. */
27067745 351 convert_typed_floating (from, type, to, i387_ext_type (gdbarch));
d532c08f
MK
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
20a6ec49
MD
382#define FSAVE_ADDR(tdep, fsave, regnum) \
383 (fsave + fsave_offset[regnum - I387_ST0_REGNUM (tdep)])
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{
e17a4113
UW
393 struct gdbarch *gdbarch = get_regcache_arch (regcache);
394 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
395 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
b4ad899f 396 const gdb_byte *regs = fsave;
e750d25e
JT
397 int i;
398
5716833c
MK
399 gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
400
20a6ec49 401 for (i = I387_ST0_REGNUM (tdep); i < I387_XMM0_REGNUM (tdep); i++)
ed504bdf
MK
402 if (regnum == -1 || regnum == i)
403 {
404 if (fsave == NULL)
405 {
5716833c
MK
406 regcache_raw_supply (regcache, i, NULL);
407 continue;
ed504bdf
MK
408 }
409
410 /* Most of the FPU control registers occupy only 16 bits in the
411 fsave area. Give those a special treatment. */
20a6ec49
MD
412 if (i >= I387_FCTRL_REGNUM (tdep)
413 && i != I387_FIOFF_REGNUM (tdep) && i != I387_FOOFF_REGNUM (tdep))
ed504bdf 414 {
b4ad899f 415 gdb_byte val[4];
ed504bdf 416
20a6ec49 417 memcpy (val, FSAVE_ADDR (tdep, regs, i), 2);
ed504bdf 418 val[2] = val[3] = 0;
20a6ec49 419 if (i == I387_FOP_REGNUM (tdep))
ed504bdf 420 val[1] &= ((1 << 3) - 1);
5716833c 421 regcache_raw_supply (regcache, i, val);
ed504bdf
MK
422 }
423 else
20a6ec49 424 regcache_raw_supply (regcache, i, FSAVE_ADDR (tdep, regs, i));
ed504bdf 425 }
b87bc0d8
MK
426
427 /* Provide dummy values for the SSE registers. */
20a6ec49 428 for (i = I387_XMM0_REGNUM (tdep); i < I387_MXCSR_REGNUM (tdep); i++)
b87bc0d8
MK
429 if (regnum == -1 || regnum == i)
430 regcache_raw_supply (regcache, i, NULL);
20a6ec49 431 if (regnum == -1 || regnum == I387_MXCSR_REGNUM (tdep))
b87bc0d8 432 {
b4ad899f 433 gdb_byte buf[4];
b87bc0d8 434
e17a4113 435 store_unsigned_integer (buf, 4, byte_order, 0x1f80);
20a6ec49 436 regcache_raw_supply (regcache, I387_MXCSR_REGNUM (tdep), buf);
b87bc0d8 437 }
e750d25e
JT
438}
439
440/* Fill register REGNUM (if it is a floating-point register) in *FSAVE
63b6c53f
MK
441 with the value from REGCACHE. If REGNUM is -1, do this for all
442 registers. This function doesn't touch any of the reserved bits in
443 *FSAVE. */
e750d25e
JT
444
445void
63b6c53f 446i387_collect_fsave (const struct regcache *regcache, int regnum, void *fsave)
e750d25e 447{
e071d1f6 448 struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
b4ad899f 449 gdb_byte *regs = fsave;
e750d25e
JT
450 int i;
451
5716833c
MK
452 gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
453
20a6ec49 454 for (i = I387_ST0_REGNUM (tdep); i < I387_XMM0_REGNUM (tdep); i++)
e750d25e
JT
455 if (regnum == -1 || regnum == i)
456 {
457 /* Most of the FPU control registers occupy only 16 bits in
458 the fsave area. Give those a special treatment. */
20a6ec49
MD
459 if (i >= I387_FCTRL_REGNUM (tdep)
460 && i != I387_FIOFF_REGNUM (tdep) && i != I387_FOOFF_REGNUM (tdep))
e750d25e 461 {
b4ad899f 462 gdb_byte buf[4];
e750d25e 463
5716833c 464 regcache_raw_collect (regcache, i, buf);
e750d25e 465
20a6ec49 466 if (i == I387_FOP_REGNUM (tdep))
e750d25e
JT
467 {
468 /* The opcode occupies only 11 bits. Make sure we
469 don't touch the other bits. */
470 buf[1] &= ((1 << 3) - 1);
20a6ec49 471 buf[1] |= ((FSAVE_ADDR (tdep, regs, i))[1] & ~((1 << 3) - 1));
e750d25e 472 }
20a6ec49 473 memcpy (FSAVE_ADDR (tdep, regs, i), buf, 2);
e750d25e
JT
474 }
475 else
20a6ec49 476 regcache_raw_collect (regcache, i, FSAVE_ADDR (tdep, regs, i));
e750d25e
JT
477 }
478}
479\f
480
481/* At fxsave_offset[REGNUM] you'll find the offset to the location in
482 the data structure used by the "fxsave" instruction where GDB
483 register REGNUM is stored. */
484
485static int fxsave_offset[] =
486{
5716833c 487 32, /* %st(0) through ... */
e750d25e
JT
488 48,
489 64,
490 80,
491 96,
492 112,
493 128,
5716833c
MK
494 144, /* ... %st(7) (80 bits each). */
495 0, /* `fctrl' (16 bits). */
496 2, /* `fstat' (16 bits). */
497 4, /* `ftag' (16 bits). */
498 12, /* `fiseg' (16 bits). */
499 8, /* `fioff'. */
500 20, /* `foseg' (16 bits). */
501 16, /* `fooff'. */
502 6, /* `fop' (bottom 11 bits). */
503 160 + 0 * 16, /* %xmm0 through ... */
04c8243f
MK
504 160 + 1 * 16,
505 160 + 2 * 16,
506 160 + 3 * 16,
507 160 + 4 * 16,
508 160 + 5 * 16,
509 160 + 6 * 16,
510 160 + 7 * 16,
511 160 + 8 * 16,
512 160 + 9 * 16,
513 160 + 10 * 16,
514 160 + 11 * 16,
515 160 + 12 * 16,
516 160 + 13 * 16,
517 160 + 14 * 16,
5716833c 518 160 + 15 * 16, /* ... %xmm15 (128 bits each). */
e750d25e
JT
519};
520
20a6ec49
MD
521#define FXSAVE_ADDR(tdep, fxsave, regnum) \
522 (fxsave + fxsave_offset[regnum - I387_ST0_REGNUM (tdep)])
5716833c
MK
523
524/* We made an unfortunate choice in putting %mxcsr after the SSE
525 registers %xmm0-%xmm7 instead of before, since it makes supporting
526 the registers %xmm8-%xmm15 on AMD64 a bit involved. Therefore we
527 don't include the offset for %mxcsr here above. */
528
529#define FXSAVE_MXCSR_ADDR(fxsave) (fxsave + 24)
e750d25e 530
b4ad899f 531static int i387_tag (const gdb_byte *raw);
e750d25e
JT
532\f
533
41d041d6 534/* Fill register REGNUM in REGCACHE with the appropriate
ed504bdf
MK
535 floating-point or SSE register value from *FXSAVE. This function
536 masks off any of the reserved bits in *FXSAVE. */
e750d25e
JT
537
538void
41d041d6 539i387_supply_fxsave (struct regcache *regcache, int regnum, const void *fxsave)
e750d25e 540{
41d041d6 541 struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
b4ad899f 542 const gdb_byte *regs = fxsave;
5716833c
MK
543 int i;
544
545 gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
546 gdb_assert (tdep->num_xmm_regs > 0);
dff95cc7 547
20a6ec49 548 for (i = I387_ST0_REGNUM (tdep); i < I387_MXCSR_REGNUM (tdep); i++)
ed504bdf
MK
549 if (regnum == -1 || regnum == i)
550 {
5716833c 551 if (regs == NULL)
ed504bdf 552 {
5716833c 553 regcache_raw_supply (regcache, i, NULL);
ed504bdf
MK
554 continue;
555 }
932bb524 556
ed504bdf
MK
557 /* Most of the FPU control registers occupy only 16 bits in
558 the fxsave area. Give those a special treatment. */
20a6ec49
MD
559 if (i >= I387_FCTRL_REGNUM (tdep) && i < I387_XMM0_REGNUM (tdep)
560 && i != I387_FIOFF_REGNUM (tdep) && i != I387_FOOFF_REGNUM (tdep))
ed504bdf 561 {
b4ad899f 562 gdb_byte val[4];
ed504bdf 563
20a6ec49 564 memcpy (val, FXSAVE_ADDR (tdep, regs, i), 2);
ed504bdf 565 val[2] = val[3] = 0;
20a6ec49 566 if (i == I387_FOP_REGNUM (tdep))
ed504bdf 567 val[1] &= ((1 << 3) - 1);
20a6ec49 568 else if (i== I387_FTAG_REGNUM (tdep))
ed504bdf
MK
569 {
570 /* The fxsave area contains a simplified version of
571 the tag word. We have to look at the actual 80-bit
572 FP data to recreate the traditional i387 tag word. */
573
574 unsigned long ftag = 0;
575 int fpreg;
576 int top;
577
20a6ec49
MD
578 top = ((FXSAVE_ADDR (tdep, regs,
579 I387_FSTAT_REGNUM (tdep)))[1] >> 3);
5716833c 580 top &= 0x7;
ed504bdf
MK
581
582 for (fpreg = 7; fpreg >= 0; fpreg--)
583 {
584 int tag;
585
586 if (val[0] & (1 << fpreg))
587 {
20a6ec49
MD
588 int regnum = (fpreg + 8 - top) % 8
589 + I387_ST0_REGNUM (tdep);
590 tag = i387_tag (FXSAVE_ADDR (tdep, regs, regnum));
ed504bdf
MK
591 }
592 else
593 tag = 3; /* Empty */
594
595 ftag |= tag << (2 * fpreg);
596 }
597 val[0] = ftag & 0xff;
598 val[1] = (ftag >> 8) & 0xff;
599 }
5716833c 600 regcache_raw_supply (regcache, i, val);
ed504bdf
MK
601 }
602 else
20a6ec49 603 regcache_raw_supply (regcache, i, FXSAVE_ADDR (tdep, regs, i));
ed504bdf 604 }
5716833c 605
20a6ec49 606 if (regnum == I387_MXCSR_REGNUM (tdep) || regnum == -1)
5716833c
MK
607 {
608 if (regs == NULL)
20a6ec49 609 regcache_raw_supply (regcache, I387_MXCSR_REGNUM (tdep), NULL);
5716833c 610 else
20a6ec49 611 regcache_raw_supply (regcache, I387_MXCSR_REGNUM (tdep),
5716833c
MK
612 FXSAVE_MXCSR_ADDR (regs));
613 }
e750d25e
JT
614}
615
616/* Fill register REGNUM (if it is a floating-point or SSE register) in
80571bff
MK
617 *FXSAVE with the value from REGCACHE. If REGNUM is -1, do this for
618 all registers. This function doesn't touch any of the reserved
619 bits in *FXSAVE. */
e750d25e
JT
620
621void
80571bff 622i387_collect_fxsave (const struct regcache *regcache, int regnum, void *fxsave)
e750d25e 623{
e071d1f6 624 struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
b4ad899f 625 gdb_byte *regs = fxsave;
5716833c
MK
626 int i;
627
628 gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
629 gdb_assert (tdep->num_xmm_regs > 0);
dff95cc7 630
20a6ec49 631 for (i = I387_ST0_REGNUM (tdep); i < I387_MXCSR_REGNUM (tdep); i++)
e750d25e
JT
632 if (regnum == -1 || regnum == i)
633 {
634 /* Most of the FPU control registers occupy only 16 bits in
635 the fxsave area. Give those a special treatment. */
20a6ec49
MD
636 if (i >= I387_FCTRL_REGNUM (tdep) && i < I387_XMM0_REGNUM (tdep)
637 && i != I387_FIOFF_REGNUM (tdep) && i != I387_FOOFF_REGNUM (tdep))
e750d25e 638 {
b4ad899f 639 gdb_byte buf[4];
e750d25e 640
5716833c 641 regcache_raw_collect (regcache, i, buf);
e750d25e 642
20a6ec49 643 if (i == I387_FOP_REGNUM (tdep))
e750d25e
JT
644 {
645 /* The opcode occupies only 11 bits. Make sure we
646 don't touch the other bits. */
647 buf[1] &= ((1 << 3) - 1);
20a6ec49 648 buf[1] |= ((FXSAVE_ADDR (tdep, regs, i))[1] & ~((1 << 3) - 1));
e750d25e 649 }
20a6ec49 650 else if (i == I387_FTAG_REGNUM (tdep))
e750d25e
JT
651 {
652 /* Converting back is much easier. */
653
654 unsigned short ftag;
655 int fpreg;
656
657 ftag = (buf[1] << 8) | buf[0];
658 buf[0] = 0;
659 buf[1] = 0;
660
661 for (fpreg = 7; fpreg >= 0; fpreg--)
662 {
663 int tag = (ftag >> (fpreg * 2)) & 3;
664
665 if (tag != 3)
666 buf[0] |= (1 << fpreg);
667 }
668 }
20a6ec49 669 memcpy (FXSAVE_ADDR (tdep, regs, i), buf, 2);
e750d25e
JT
670 }
671 else
20a6ec49 672 regcache_raw_collect (regcache, i, FXSAVE_ADDR (tdep, regs, i));
e750d25e 673 }
5716833c 674
20a6ec49
MD
675 if (regnum == I387_MXCSR_REGNUM (tdep) || regnum == -1)
676 regcache_raw_collect (regcache, I387_MXCSR_REGNUM (tdep),
5716833c 677 FXSAVE_MXCSR_ADDR (regs));
e750d25e
JT
678}
679
680/* Recreate the FTW (tag word) valid bits from the 80-bit FP data in
681 *RAW. */
682
683static int
b4ad899f 684i387_tag (const gdb_byte *raw)
e750d25e
JT
685{
686 int integer;
687 unsigned int exponent;
688 unsigned long fraction[2];
689
690 integer = raw[7] & 0x80;
691 exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
692 fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
693 fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
694 | (raw[5] << 8) | raw[4]);
695
696 if (exponent == 0x7fff)
697 {
698 /* Special. */
699 return (2);
700 }
701 else if (exponent == 0x0000)
702 {
703 if (fraction[0] == 0x0000 && fraction[1] == 0x0000 && !integer)
704 {
705 /* Zero. */
706 return (1);
707 }
708 else
709 {
710 /* Special. */
711 return (2);
712 }
713 }
714 else
715 {
716 if (integer)
717 {
718 /* Valid. */
719 return (0);
720 }
721 else
722 {
723 /* Special. */
724 return (2);
725 }
726 }
727}
efb1c01c
MK
728
729/* Prepare the FPU stack in REGCACHE for a function return. */
730
731void
732i387_return_value (struct gdbarch *gdbarch, struct regcache *regcache)
733{
734 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
735 ULONGEST fstat;
736
efb1c01c
MK
737 /* Set the top of the floating-point register stack to 7. The
738 actual value doesn't really matter, but 7 is what a normal
739 function return would end up with if the program started out with
740 a freshly initialized FPU. */
20a6ec49 741 regcache_raw_read_unsigned (regcache, I387_FSTAT_REGNUM (tdep), &fstat);
efb1c01c 742 fstat |= (7 << 11);
20a6ec49 743 regcache_raw_write_unsigned (regcache, I387_FSTAT_REGNUM (tdep), fstat);
efb1c01c
MK
744
745 /* Mark %st(1) through %st(7) as empty. Since we set the top of the
746 floating-point register stack to 7, the appropriate value for the
747 tag word is 0x3fff. */
20a6ec49 748 regcache_raw_write_unsigned (regcache, I387_FTAG_REGNUM (tdep), 0x3fff);
efb1c01c 749
efb1c01c 750}
This page took 0.910498 seconds and 4 git commands to generate.