]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/i387-tdep.c
2007-10-24 Nathan Sidwell <nathan@codesourcery.com>
[thirdparty/binutils-gdb.git] / gdb / i387-tdep.c
CommitLineData
c906108c 1/* Intel 387 floating point stuff.
38edeab8 2
6aba47ca
DJ
3 Copyright (C) 1988, 1989, 1991, 1992, 1993, 1994, 1998, 1999, 2000, 2001,
4 2002, 2003, 2004, 2005, 2007 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
288/* Read a value of type TYPE from register REGNUM in frame FRAME, and
289 return its contents in TO. */
290
291void
292i387_register_to_value (struct frame_info *frame, int regnum,
42835c2b 293 struct type *type, gdb_byte *to)
d532c08f 294{
b4ad899f 295 gdb_byte from[I386_MAX_REGISTER_SIZE];
d532c08f
MK
296
297 gdb_assert (i386_fp_regnum_p (regnum));
298
299 /* We only support floating-point values. */
300 if (TYPE_CODE (type) != TYPE_CODE_FLT)
301 {
8a3fe4f8
AC
302 warning (_("Cannot convert floating-point register value "
303 "to non-floating-point type."));
d532c08f
MK
304 return;
305 }
306
307 /* Convert to TYPE. This should be a no-op if TYPE is equivalent to
308 the extended floating-point format used by the FPU. */
192285c6 309 get_frame_register (frame, regnum, from);
d532c08f
MK
310 convert_typed_floating (from, builtin_type_i387_ext, to, type);
311}
312
313/* Write the contents FROM of a value of type TYPE into register
314 REGNUM in frame FRAME. */
315
316void
317i387_value_to_register (struct frame_info *frame, int regnum,
42835c2b 318 struct type *type, const gdb_byte *from)
d532c08f 319{
b4ad899f 320 gdb_byte to[I386_MAX_REGISTER_SIZE];
d532c08f
MK
321
322 gdb_assert (i386_fp_regnum_p (regnum));
323
324 /* We only support floating-point values. */
325 if (TYPE_CODE (type) != TYPE_CODE_FLT)
326 {
8a3fe4f8
AC
327 warning (_("Cannot convert non-floating-point type "
328 "to floating-point register value."));
d532c08f
MK
329 return;
330 }
331
332 /* Convert from TYPE. This should be a no-op if TYPE is equivalent
333 to the extended floating-point format used by the FPU. */
334 convert_typed_floating (from, type, to, builtin_type_i387_ext);
335 put_frame_register (frame, regnum, to);
336}
337\f
e750d25e 338
786a90bb 339/* Handle FSAVE and FXSAVE formats. */
e750d25e
JT
340
341/* At fsave_offset[REGNUM] you'll find the offset to the location in
342 the data structure used by the "fsave" instruction where GDB
343 register REGNUM is stored. */
344
345static int fsave_offset[] =
346{
5716833c
MK
347 28 + 0 * 10, /* %st(0) ... */
348 28 + 1 * 10,
349 28 + 2 * 10,
350 28 + 3 * 10,
351 28 + 4 * 10,
352 28 + 5 * 10,
353 28 + 6 * 10,
354 28 + 7 * 10, /* ... %st(7). */
355 0, /* `fctrl' (16 bits). */
356 4, /* `fstat' (16 bits). */
357 8, /* `ftag' (16 bits). */
358 16, /* `fiseg' (16 bits). */
359 12, /* `fioff'. */
360 24, /* `foseg' (16 bits). */
361 20, /* `fooff'. */
362 18 /* `fop' (bottom 11 bits). */
e750d25e
JT
363};
364
5716833c
MK
365#define FSAVE_ADDR(fsave, regnum) \
366 (fsave + fsave_offset[regnum - I387_ST0_REGNUM])
e750d25e
JT
367\f
368
41d041d6
MK
369/* Fill register REGNUM in REGCACHE with the appropriate value from
370 *FSAVE. This function masks off any of the reserved bits in
371 *FSAVE. */
e750d25e
JT
372
373void
41d041d6 374i387_supply_fsave (struct regcache *regcache, int regnum, const void *fsave)
e750d25e 375{
41d041d6 376 struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
b4ad899f 377 const gdb_byte *regs = fsave;
e750d25e
JT
378 int i;
379
5716833c
MK
380 gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
381
b87bc0d8
MK
382 /* Define I387_ST0_REGNUM and I387_NUM_XMM_REGS such that we use the
383 proper definitions for REGCACHE's architecture. */
384
5716833c 385#define I387_ST0_REGNUM tdep->st0_regnum
b87bc0d8 386#define I387_NUM_XMM_REGS tdep->num_xmm_regs
5716833c
MK
387
388 for (i = I387_ST0_REGNUM; i < I387_XMM0_REGNUM; i++)
ed504bdf
MK
389 if (regnum == -1 || regnum == i)
390 {
391 if (fsave == NULL)
392 {
5716833c
MK
393 regcache_raw_supply (regcache, i, NULL);
394 continue;
ed504bdf
MK
395 }
396
397 /* Most of the FPU control registers occupy only 16 bits in the
398 fsave area. Give those a special treatment. */
5716833c
MK
399 if (i >= I387_FCTRL_REGNUM
400 && i != I387_FIOFF_REGNUM && i != I387_FOOFF_REGNUM)
ed504bdf 401 {
b4ad899f 402 gdb_byte val[4];
ed504bdf 403
5716833c 404 memcpy (val, FSAVE_ADDR (regs, i), 2);
ed504bdf 405 val[2] = val[3] = 0;
5716833c 406 if (i == I387_FOP_REGNUM)
ed504bdf 407 val[1] &= ((1 << 3) - 1);
5716833c 408 regcache_raw_supply (regcache, i, val);
ed504bdf
MK
409 }
410 else
5716833c 411 regcache_raw_supply (regcache, i, FSAVE_ADDR (regs, i));
ed504bdf 412 }
b87bc0d8
MK
413
414 /* Provide dummy values for the SSE registers. */
415 for (i = I387_XMM0_REGNUM; i < I387_MXCSR_REGNUM; i++)
416 if (regnum == -1 || regnum == i)
417 regcache_raw_supply (regcache, i, NULL);
418 if (regnum == -1 || regnum == I387_MXCSR_REGNUM)
419 {
b4ad899f 420 gdb_byte buf[4];
b87bc0d8
MK
421
422 store_unsigned_integer (buf, 4, 0x1f80);
423 regcache_raw_supply (regcache, I387_MXCSR_REGNUM, buf);
424 }
425
5716833c 426#undef I387_ST0_REGNUM
b87bc0d8 427#undef I387_NUM_XMM_REGS
e750d25e
JT
428}
429
430/* Fill register REGNUM (if it is a floating-point register) in *FSAVE
63b6c53f
MK
431 with the value from REGCACHE. If REGNUM is -1, do this for all
432 registers. This function doesn't touch any of the reserved bits in
433 *FSAVE. */
e750d25e
JT
434
435void
63b6c53f 436i387_collect_fsave (const struct regcache *regcache, int regnum, void *fsave)
e750d25e 437{
e071d1f6 438 struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
b4ad899f 439 gdb_byte *regs = fsave;
e750d25e
JT
440 int i;
441
5716833c
MK
442 gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
443
444 /* Define I387_ST0_REGNUM such that we use the proper definitions
445 for REGCACHE's architecture. */
446#define I387_ST0_REGNUM tdep->st0_regnum
447
448 for (i = I387_ST0_REGNUM; i < I387_XMM0_REGNUM; i++)
e750d25e
JT
449 if (regnum == -1 || regnum == i)
450 {
451 /* Most of the FPU control registers occupy only 16 bits in
452 the fsave area. Give those a special treatment. */
5716833c
MK
453 if (i >= I387_FCTRL_REGNUM
454 && i != I387_FIOFF_REGNUM && i != I387_FOOFF_REGNUM)
e750d25e 455 {
b4ad899f 456 gdb_byte buf[4];
e750d25e 457
5716833c 458 regcache_raw_collect (regcache, i, buf);
e750d25e 459
5716833c 460 if (i == I387_FOP_REGNUM)
e750d25e
JT
461 {
462 /* The opcode occupies only 11 bits. Make sure we
463 don't touch the other bits. */
464 buf[1] &= ((1 << 3) - 1);
5716833c 465 buf[1] |= ((FSAVE_ADDR (regs, i))[1] & ~((1 << 3) - 1));
e750d25e 466 }
5716833c 467 memcpy (FSAVE_ADDR (regs, i), buf, 2);
e750d25e
JT
468 }
469 else
5716833c 470 regcache_raw_collect (regcache, i, FSAVE_ADDR (regs, i));
e750d25e 471 }
5716833c 472#undef I387_ST0_REGNUM
e750d25e
JT
473}
474\f
475
476/* At fxsave_offset[REGNUM] you'll find the offset to the location in
477 the data structure used by the "fxsave" instruction where GDB
478 register REGNUM is stored. */
479
480static int fxsave_offset[] =
481{
5716833c 482 32, /* %st(0) through ... */
e750d25e
JT
483 48,
484 64,
485 80,
486 96,
487 112,
488 128,
5716833c
MK
489 144, /* ... %st(7) (80 bits each). */
490 0, /* `fctrl' (16 bits). */
491 2, /* `fstat' (16 bits). */
492 4, /* `ftag' (16 bits). */
493 12, /* `fiseg' (16 bits). */
494 8, /* `fioff'. */
495 20, /* `foseg' (16 bits). */
496 16, /* `fooff'. */
497 6, /* `fop' (bottom 11 bits). */
498 160 + 0 * 16, /* %xmm0 through ... */
04c8243f
MK
499 160 + 1 * 16,
500 160 + 2 * 16,
501 160 + 3 * 16,
502 160 + 4 * 16,
503 160 + 5 * 16,
504 160 + 6 * 16,
505 160 + 7 * 16,
506 160 + 8 * 16,
507 160 + 9 * 16,
508 160 + 10 * 16,
509 160 + 11 * 16,
510 160 + 12 * 16,
511 160 + 13 * 16,
512 160 + 14 * 16,
5716833c 513 160 + 15 * 16, /* ... %xmm15 (128 bits each). */
e750d25e
JT
514};
515
516#define FXSAVE_ADDR(fxsave, regnum) \
5716833c
MK
517 (fxsave + fxsave_offset[regnum - I387_ST0_REGNUM])
518
519/* We made an unfortunate choice in putting %mxcsr after the SSE
520 registers %xmm0-%xmm7 instead of before, since it makes supporting
521 the registers %xmm8-%xmm15 on AMD64 a bit involved. Therefore we
522 don't include the offset for %mxcsr here above. */
523
524#define FXSAVE_MXCSR_ADDR(fxsave) (fxsave + 24)
e750d25e 525
b4ad899f 526static int i387_tag (const gdb_byte *raw);
e750d25e
JT
527\f
528
41d041d6 529/* Fill register REGNUM in REGCACHE with the appropriate
ed504bdf
MK
530 floating-point or SSE register value from *FXSAVE. This function
531 masks off any of the reserved bits in *FXSAVE. */
e750d25e
JT
532
533void
41d041d6 534i387_supply_fxsave (struct regcache *regcache, int regnum, const void *fxsave)
e750d25e 535{
41d041d6 536 struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
b4ad899f 537 const gdb_byte *regs = fxsave;
5716833c
MK
538 int i;
539
540 gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
541 gdb_assert (tdep->num_xmm_regs > 0);
dff95cc7 542
5716833c
MK
543 /* Define I387_ST0_REGNUM and I387_NUM_XMM_REGS such that we use the
544 proper definitions for REGCACHE's architecture. */
e750d25e 545
5716833c
MK
546#define I387_ST0_REGNUM tdep->st0_regnum
547#define I387_NUM_XMM_REGS tdep->num_xmm_regs
548
549 for (i = I387_ST0_REGNUM; i < I387_MXCSR_REGNUM; i++)
ed504bdf
MK
550 if (regnum == -1 || regnum == i)
551 {
5716833c 552 if (regs == NULL)
ed504bdf 553 {
5716833c 554 regcache_raw_supply (regcache, i, NULL);
ed504bdf
MK
555 continue;
556 }
932bb524 557
ed504bdf
MK
558 /* Most of the FPU control registers occupy only 16 bits in
559 the fxsave area. Give those a special treatment. */
5716833c
MK
560 if (i >= I387_FCTRL_REGNUM && i < I387_XMM0_REGNUM
561 && i != I387_FIOFF_REGNUM && i != I387_FOOFF_REGNUM)
ed504bdf 562 {
b4ad899f 563 gdb_byte val[4];
ed504bdf 564
5716833c 565 memcpy (val, FXSAVE_ADDR (regs, i), 2);
ed504bdf 566 val[2] = val[3] = 0;
5716833c 567 if (i == I387_FOP_REGNUM)
ed504bdf 568 val[1] &= ((1 << 3) - 1);
5716833c 569 else if (i== I387_FTAG_REGNUM)
ed504bdf
MK
570 {
571 /* The fxsave area contains a simplified version of
572 the tag word. We have to look at the actual 80-bit
573 FP data to recreate the traditional i387 tag word. */
574
575 unsigned long ftag = 0;
576 int fpreg;
577 int top;
578
5716833c
MK
579 top = ((FXSAVE_ADDR (regs, I387_FSTAT_REGNUM))[1] >> 3);
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 {
5716833c
MK
588 int regnum = (fpreg + 8 - top) % 8 + I387_ST0_REGNUM;
589 tag = i387_tag (FXSAVE_ADDR (regs, regnum));
ed504bdf
MK
590 }
591 else
592 tag = 3; /* Empty */
593
594 ftag |= tag << (2 * fpreg);
595 }
596 val[0] = ftag & 0xff;
597 val[1] = (ftag >> 8) & 0xff;
598 }
5716833c 599 regcache_raw_supply (regcache, i, val);
ed504bdf
MK
600 }
601 else
5716833c 602 regcache_raw_supply (regcache, i, FXSAVE_ADDR (regs, i));
ed504bdf 603 }
5716833c
MK
604
605 if (regnum == I387_MXCSR_REGNUM || regnum == -1)
606 {
607 if (regs == NULL)
608 regcache_raw_supply (regcache, I387_MXCSR_REGNUM, NULL);
609 else
610 regcache_raw_supply (regcache, I387_MXCSR_REGNUM,
611 FXSAVE_MXCSR_ADDR (regs));
612 }
613
614#undef I387_ST0_REGNUM
615#undef I387_NUM_XMM_REGS
e750d25e
JT
616}
617
618/* Fill register REGNUM (if it is a floating-point or SSE register) in
80571bff
MK
619 *FXSAVE with the value from REGCACHE. If REGNUM is -1, do this for
620 all registers. This function doesn't touch any of the reserved
621 bits in *FXSAVE. */
e750d25e
JT
622
623void
80571bff 624i387_collect_fxsave (const struct regcache *regcache, int regnum, void *fxsave)
e750d25e 625{
e071d1f6 626 struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
b4ad899f 627 gdb_byte *regs = fxsave;
5716833c
MK
628 int i;
629
630 gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
631 gdb_assert (tdep->num_xmm_regs > 0);
dff95cc7 632
5716833c
MK
633 /* Define I387_ST0_REGNUM and I387_NUM_XMM_REGS such that we use the
634 proper definitions for REGCACHE's architecture. */
e750d25e 635
5716833c
MK
636#define I387_ST0_REGNUM tdep->st0_regnum
637#define I387_NUM_XMM_REGS tdep->num_xmm_regs
638
639 for (i = I387_ST0_REGNUM; i < I387_MXCSR_REGNUM; i++)
e750d25e
JT
640 if (regnum == -1 || regnum == i)
641 {
642 /* Most of the FPU control registers occupy only 16 bits in
643 the fxsave area. Give those a special treatment. */
5716833c
MK
644 if (i >= I387_FCTRL_REGNUM && i < I387_XMM0_REGNUM
645 && i != I387_FIOFF_REGNUM && i != I387_FOOFF_REGNUM)
e750d25e 646 {
b4ad899f 647 gdb_byte buf[4];
e750d25e 648
5716833c 649 regcache_raw_collect (regcache, i, buf);
e750d25e 650
5716833c 651 if (i == I387_FOP_REGNUM)
e750d25e
JT
652 {
653 /* The opcode occupies only 11 bits. Make sure we
654 don't touch the other bits. */
655 buf[1] &= ((1 << 3) - 1);
5716833c 656 buf[1] |= ((FXSAVE_ADDR (regs, i))[1] & ~((1 << 3) - 1));
e750d25e 657 }
5716833c 658 else if (i == I387_FTAG_REGNUM)
e750d25e
JT
659 {
660 /* Converting back is much easier. */
661
662 unsigned short ftag;
663 int fpreg;
664
665 ftag = (buf[1] << 8) | buf[0];
666 buf[0] = 0;
667 buf[1] = 0;
668
669 for (fpreg = 7; fpreg >= 0; fpreg--)
670 {
671 int tag = (ftag >> (fpreg * 2)) & 3;
672
673 if (tag != 3)
674 buf[0] |= (1 << fpreg);
675 }
676 }
5716833c 677 memcpy (FXSAVE_ADDR (regs, i), buf, 2);
e750d25e
JT
678 }
679 else
5716833c 680 regcache_raw_collect (regcache, i, FXSAVE_ADDR (regs, i));
e750d25e 681 }
5716833c
MK
682
683 if (regnum == I387_MXCSR_REGNUM || regnum == -1)
684 regcache_raw_collect (regcache, I387_MXCSR_REGNUM,
685 FXSAVE_MXCSR_ADDR (regs));
686
687#undef I387_ST0_REGNUM
688#undef I387_NUM_XMM_REGS
e750d25e
JT
689}
690
691/* Recreate the FTW (tag word) valid bits from the 80-bit FP data in
692 *RAW. */
693
694static int
b4ad899f 695i387_tag (const gdb_byte *raw)
e750d25e
JT
696{
697 int integer;
698 unsigned int exponent;
699 unsigned long fraction[2];
700
701 integer = raw[7] & 0x80;
702 exponent = (((raw[9] & 0x7f) << 8) | raw[8]);
703 fraction[0] = ((raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0]);
704 fraction[1] = (((raw[7] & 0x7f) << 24) | (raw[6] << 16)
705 | (raw[5] << 8) | raw[4]);
706
707 if (exponent == 0x7fff)
708 {
709 /* Special. */
710 return (2);
711 }
712 else if (exponent == 0x0000)
713 {
714 if (fraction[0] == 0x0000 && fraction[1] == 0x0000 && !integer)
715 {
716 /* Zero. */
717 return (1);
718 }
719 else
720 {
721 /* Special. */
722 return (2);
723 }
724 }
725 else
726 {
727 if (integer)
728 {
729 /* Valid. */
730 return (0);
731 }
732 else
733 {
734 /* Special. */
735 return (2);
736 }
737 }
738}
efb1c01c
MK
739
740/* Prepare the FPU stack in REGCACHE for a function return. */
741
742void
743i387_return_value (struct gdbarch *gdbarch, struct regcache *regcache)
744{
745 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
746 ULONGEST fstat;
747
748 /* Define I387_ST0_REGNUM such that we use the proper
749 definitions for the architecture. */
750#define I387_ST0_REGNUM tdep->st0_regnum
751
752 /* Set the top of the floating-point register stack to 7. The
753 actual value doesn't really matter, but 7 is what a normal
754 function return would end up with if the program started out with
755 a freshly initialized FPU. */
756 regcache_raw_read_unsigned (regcache, I387_FSTAT_REGNUM, &fstat);
757 fstat |= (7 << 11);
758 regcache_raw_write_unsigned (regcache, I387_FSTAT_REGNUM, fstat);
759
760 /* Mark %st(1) through %st(7) as empty. Since we set the top of the
761 floating-point register stack to 7, the appropriate value for the
762 tag word is 0x3fff. */
763 regcache_raw_write_unsigned (regcache, I387_FTAG_REGNUM, 0x3fff);
764
765#undef I387_ST0_REGNUM
766}