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