/* Intel 387 floating point stuff.
- Copyright 1988, 1989, 1991, 1992, 1993, 1994, 1998, 1999, 2000,
- 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright (C) 1988, 1989, 1991, 1992, 1993, 1994, 1998, 1999, 2000,
+ 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GDB.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA. */
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
#include "defs.h"
#include "doublest.h"
#include "i386-tdep.h"
#include "i387-tdep.h"
-/* Implement the `info float' layout based on the register definitions
- in `tm-i386.h'. */
-
/* Print the floating point number specified by RAW. */
static void
-print_i387_value (char *raw, struct ui_file *file)
+print_i387_value (const gdb_byte *raw, struct ui_file *file)
{
DOUBLEST value;
/* Print the classification for the register contents RAW. */
static void
-print_i387_ext (unsigned char *raw, struct ui_file *file)
+print_i387_ext (const gdb_byte *raw, struct ui_file *file)
{
int sign;
int integer;
print_i387_status_word (unsigned int status, struct ui_file *file)
{
fprintf_filtered (file, "Status Word: %s",
- local_hex_string_custom (status, "04"));
+ hex_string_custom (status, 4));
fputs_filtered (" ", file);
fprintf_filtered (file, " %s", (status & 0x0001) ? "IE" : " ");
fprintf_filtered (file, " %s", (status & 0x0002) ? "DE" : " ");
print_i387_control_word (unsigned int control, struct ui_file *file)
{
fprintf_filtered (file, "Control Word: %s",
- local_hex_string_custom (control, "04"));
+ hex_string_custom (control, 4));
fputs_filtered (" ", file);
fprintf_filtered (file, " %s", (control & 0x0001) ? "IM" : " ");
fprintf_filtered (file, " %s", (control & 0x0002) ? "DM" : " ");
i387_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
struct frame_info *frame, const char *args)
{
- char buf[4];
+ struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (frame));
+ gdb_byte buf[4];
ULONGEST fctrl;
ULONGEST fstat;
ULONGEST ftag;
int fpreg;
int top;
- frame_register_read (frame, FCTRL_REGNUM, buf);
- fctrl = extract_unsigned_integer (buf, 4);
- frame_register_read (frame, FSTAT_REGNUM, buf);
- fstat = extract_unsigned_integer (buf, 4);
- frame_register_read (frame, FTAG_REGNUM, buf);
- ftag = extract_unsigned_integer (buf, 4);
- frame_register_read (frame, FISEG_REGNUM, buf);
- fiseg = extract_unsigned_integer (buf, 4);
- frame_register_read (frame, FIOFF_REGNUM, buf);
- fioff = extract_unsigned_integer (buf, 4);
- frame_register_read (frame, FOSEG_REGNUM, buf);
- foseg = extract_unsigned_integer (buf, 4);
- frame_register_read (frame, FOOFF_REGNUM, buf);
- fooff = extract_unsigned_integer (buf, 4);
- frame_register_read (frame, FOP_REGNUM, buf);
- fop = extract_unsigned_integer (buf, 4);
+ gdb_assert (gdbarch == get_frame_arch (frame));
+
+ /* Define I387_ST0_REGNUM such that we use the proper definitions
+ for FRAME's architecture. */
+#define I387_ST0_REGNUM tdep->st0_regnum
+
+ fctrl = get_frame_register_unsigned (frame, I387_FCTRL_REGNUM);
+ fstat = get_frame_register_unsigned (frame, I387_FSTAT_REGNUM);
+ ftag = get_frame_register_unsigned (frame, I387_FTAG_REGNUM);
+ fiseg = get_frame_register_unsigned (frame, I387_FISEG_REGNUM);
+ fioff = get_frame_register_unsigned (frame, I387_FIOFF_REGNUM);
+ foseg = get_frame_register_unsigned (frame, I387_FOSEG_REGNUM);
+ fooff = get_frame_register_unsigned (frame, I387_FOOFF_REGNUM);
+ fop = get_frame_register_unsigned (frame, I387_FOP_REGNUM);
top = ((fstat >> 11) & 7);
for (fpreg = 7; fpreg >= 0; fpreg--)
{
- unsigned char raw[FPU_REG_RAW_SIZE];
+ gdb_byte raw[I386_MAX_REGISTER_SIZE];
int tag = (ftag >> (fpreg * 2)) & 3;
int i;
break;
}
- frame_register_read (frame, (fpreg + 8 - top) % 8 + FP0_REGNUM, raw);
+ get_frame_register (frame, (fpreg + 8 - top) % 8 + I387_ST0_REGNUM, raw);
fputs_filtered ("0x", file);
for (i = 9; i >= 0; i--)
print_i387_status_word (fstat, file);
print_i387_control_word (fctrl, file);
fprintf_filtered (file, "Tag Word: %s\n",
- local_hex_string_custom (ftag, "04"));
+ hex_string_custom (ftag, 4));
fprintf_filtered (file, "Instruction Pointer: %s:",
- local_hex_string_custom (fiseg, "02"));
- fprintf_filtered (file, "%s\n", local_hex_string_custom (fioff, "08"));
+ hex_string_custom (fiseg, 2));
+ fprintf_filtered (file, "%s\n", hex_string_custom (fioff, 8));
fprintf_filtered (file, "Operand Pointer: %s:",
- local_hex_string_custom (foseg, "02"));
- fprintf_filtered (file, "%s\n", local_hex_string_custom (fooff, "08"));
+ hex_string_custom (foseg, 2));
+ fprintf_filtered (file, "%s\n", hex_string_custom (fooff, 8));
fprintf_filtered (file, "Opcode: %s\n",
- local_hex_string_custom (fop ? (fop | 0xd800) : 0, "04"));
+ hex_string_custom (fop ? (fop | 0xd800) : 0, 4));
+
+#undef I387_ST0_REGNUM
}
\f
void
i387_register_to_value (struct frame_info *frame, int regnum,
- struct type *type, void *to)
+ struct type *type, gdb_byte *to)
{
- char from[I386_MAX_REGISTER_SIZE];
+ gdb_byte from[I386_MAX_REGISTER_SIZE];
gdb_assert (i386_fp_regnum_p (regnum));
/* We only support floating-point values. */
if (TYPE_CODE (type) != TYPE_CODE_FLT)
{
- warning ("Cannot convert floating-point register value "
- "to non-floating-point type.");
+ warning (_("Cannot convert floating-point register value "
+ "to non-floating-point type."));
return;
}
/* Convert to TYPE. This should be a no-op if TYPE is equivalent to
the extended floating-point format used by the FPU. */
- frame_read_register (frame, regnum, from);
+ get_frame_register (frame, regnum, from);
convert_typed_floating (from, builtin_type_i387_ext, to, type);
}
void
i387_value_to_register (struct frame_info *frame, int regnum,
- struct type *type, const void *from)
+ struct type *type, const gdb_byte *from)
{
- char to[I386_MAX_REGISTER_SIZE];
+ gdb_byte to[I386_MAX_REGISTER_SIZE];
gdb_assert (i386_fp_regnum_p (regnum));
/* We only support floating-point values. */
if (TYPE_CODE (type) != TYPE_CODE_FLT)
{
- warning ("Cannot convert non-floating-point type "
- "to floating-point register value.");
+ warning (_("Cannot convert non-floating-point type "
+ "to floating-point register value."));
return;
}
static int fsave_offset[] =
{
- 28 + 0 * FPU_REG_RAW_SIZE, /* FP0_REGNUM through ... */
- 28 + 1 * FPU_REG_RAW_SIZE,
- 28 + 2 * FPU_REG_RAW_SIZE,
- 28 + 3 * FPU_REG_RAW_SIZE,
- 28 + 4 * FPU_REG_RAW_SIZE,
- 28 + 5 * FPU_REG_RAW_SIZE,
- 28 + 6 * FPU_REG_RAW_SIZE,
- 28 + 7 * FPU_REG_RAW_SIZE, /* ... FP7_REGNUM. */
- 0, /* FCTRL_REGNUM (16 bits). */
- 4, /* FSTAT_REGNUM (16 bits). */
- 8, /* FTAG_REGNUM (16 bits). */
- 16, /* FISEG_REGNUM (16 bits). */
- 12, /* FIOFF_REGNUM. */
- 24, /* FOSEG_REGNUM. */
- 20, /* FOOFF_REGNUM. */
- 18 /* FOP_REGNUM (bottom 11 bits). */
+ 28 + 0 * 10, /* %st(0) ... */
+ 28 + 1 * 10,
+ 28 + 2 * 10,
+ 28 + 3 * 10,
+ 28 + 4 * 10,
+ 28 + 5 * 10,
+ 28 + 6 * 10,
+ 28 + 7 * 10, /* ... %st(7). */
+ 0, /* `fctrl' (16 bits). */
+ 4, /* `fstat' (16 bits). */
+ 8, /* `ftag' (16 bits). */
+ 16, /* `fiseg' (16 bits). */
+ 12, /* `fioff'. */
+ 24, /* `foseg' (16 bits). */
+ 20, /* `fooff'. */
+ 18 /* `fop' (bottom 11 bits). */
};
-#define FSAVE_ADDR(fsave, regnum) (fsave + fsave_offset[regnum - FP0_REGNUM])
+#define FSAVE_ADDR(fsave, regnum) \
+ (fsave + fsave_offset[regnum - I387_ST0_REGNUM])
\f
-/* Fill register REGNUM in GDB's register array with the appropriate
- value from *FSAVE. This function masks off any of the reserved
- bits in *FSAVE. */
+/* Fill register REGNUM in REGCACHE with the appropriate value from
+ *FSAVE. This function masks off any of the reserved bits in
+ *FSAVE. */
void
-i387_supply_register (int regnum, char *fsave)
+i387_supply_fsave (struct regcache *regcache, int regnum, const void *fsave)
{
- if (fsave == NULL)
- {
- supply_register (regnum, NULL);
- return;
- }
+ struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
+ const gdb_byte *regs = fsave;
+ int i;
- /* Most of the FPU control registers occupy only 16 bits in
- the fsave area. Give those a special treatment. */
- if (regnum >= FPC_REGNUM
- && regnum != FIOFF_REGNUM && regnum != FOOFF_REGNUM)
- {
- unsigned char val[4];
+ gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
- memcpy (val, FSAVE_ADDR (fsave, regnum), 2);
- val[2] = val[3] = 0;
- if (regnum == FOP_REGNUM)
- val[1] &= ((1 << 3) - 1);
- supply_register (regnum, val);
- }
- else
- supply_register (regnum, FSAVE_ADDR (fsave, regnum));
-}
+ /* Define I387_ST0_REGNUM and I387_NUM_XMM_REGS such that we use the
+ proper definitions for REGCACHE's architecture. */
-/* Fill GDB's register array with the floating-point register values
- in *FSAVE. This function masks off any of the reserved
- bits in *FSAVE. */
+#define I387_ST0_REGNUM tdep->st0_regnum
+#define I387_NUM_XMM_REGS tdep->num_xmm_regs
-void
-i387_supply_fsave (char *fsave)
-{
- int i;
+ for (i = I387_ST0_REGNUM; i < I387_XMM0_REGNUM; i++)
+ if (regnum == -1 || regnum == i)
+ {
+ if (fsave == NULL)
+ {
+ regcache_raw_supply (regcache, i, NULL);
+ continue;
+ }
+
+ /* Most of the FPU control registers occupy only 16 bits in the
+ fsave area. Give those a special treatment. */
+ if (i >= I387_FCTRL_REGNUM
+ && i != I387_FIOFF_REGNUM && i != I387_FOOFF_REGNUM)
+ {
+ gdb_byte val[4];
+
+ memcpy (val, FSAVE_ADDR (regs, i), 2);
+ val[2] = val[3] = 0;
+ if (i == I387_FOP_REGNUM)
+ val[1] &= ((1 << 3) - 1);
+ regcache_raw_supply (regcache, i, val);
+ }
+ else
+ regcache_raw_supply (regcache, i, FSAVE_ADDR (regs, i));
+ }
- for (i = FP0_REGNUM; i < XMM0_REGNUM; i++)
- i387_supply_register (i, fsave);
+ /* Provide dummy values for the SSE registers. */
+ for (i = I387_XMM0_REGNUM; i < I387_MXCSR_REGNUM; i++)
+ if (regnum == -1 || regnum == i)
+ regcache_raw_supply (regcache, i, NULL);
+ if (regnum == -1 || regnum == I387_MXCSR_REGNUM)
+ {
+ gdb_byte buf[4];
+
+ store_unsigned_integer (buf, 4, 0x1f80);
+ regcache_raw_supply (regcache, I387_MXCSR_REGNUM, buf);
+ }
+
+#undef I387_ST0_REGNUM
+#undef I387_NUM_XMM_REGS
}
/* Fill register REGNUM (if it is a floating-point register) in *FSAVE
- with the value in GDB's register array. If REGNUM is -1, do this
- for all registers. This function doesn't touch any of the reserved
- bits in *FSAVE. */
+ with the value from REGCACHE. If REGNUM is -1, do this for all
+ registers. This function doesn't touch any of the reserved bits in
+ *FSAVE. */
void
-i387_fill_fsave (char *fsave, int regnum)
+i387_collect_fsave (const struct regcache *regcache, int regnum, void *fsave)
{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ gdb_byte *regs = fsave;
int i;
- for (i = FP0_REGNUM; i < XMM0_REGNUM; i++)
+ gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
+
+ /* Define I387_ST0_REGNUM such that we use the proper definitions
+ for REGCACHE's architecture. */
+#define I387_ST0_REGNUM tdep->st0_regnum
+
+ for (i = I387_ST0_REGNUM; i < I387_XMM0_REGNUM; i++)
if (regnum == -1 || regnum == i)
{
/* Most of the FPU control registers occupy only 16 bits in
the fsave area. Give those a special treatment. */
- if (i >= FPC_REGNUM
- && i != FIOFF_REGNUM && i != FOOFF_REGNUM)
+ if (i >= I387_FCTRL_REGNUM
+ && i != I387_FIOFF_REGNUM && i != I387_FOOFF_REGNUM)
{
- unsigned char buf[4];
+ gdb_byte buf[4];
- regcache_collect (i, buf);
+ regcache_raw_collect (regcache, i, buf);
- if (i == FOP_REGNUM)
+ if (i == I387_FOP_REGNUM)
{
/* The opcode occupies only 11 bits. Make sure we
don't touch the other bits. */
buf[1] &= ((1 << 3) - 1);
- buf[1] |= ((FSAVE_ADDR (fsave, i))[1] & ~((1 << 3) - 1));
+ buf[1] |= ((FSAVE_ADDR (regs, i))[1] & ~((1 << 3) - 1));
}
- memcpy (FSAVE_ADDR (fsave, i), buf, 2);
+ memcpy (FSAVE_ADDR (regs, i), buf, 2);
}
else
- regcache_collect (i, FSAVE_ADDR (fsave, i));
+ regcache_raw_collect (regcache, i, FSAVE_ADDR (regs, i));
}
+#undef I387_ST0_REGNUM
+}
+
+/* Fill register REGNUM (if it is a floating-point register) in *FSAVE
+ with the value in GDB's register cache. If REGNUM is -1, do this
+ for all registers. This function doesn't touch any of the reserved
+ bits in *FSAVE. */
+
+void
+i387_fill_fsave (void *fsave, int regnum)
+{
+ i387_collect_fsave (current_regcache, regnum, fsave);
}
\f
static int fxsave_offset[] =
{
- 32, /* FP0_REGNUM through ... */
+ 32, /* %st(0) through ... */
48,
64,
80,
96,
112,
128,
- 144, /* ... FP7_REGNUM (80 bits each). */
- 0, /* FCTRL_REGNUM (16 bits). */
- 2, /* FSTAT_REGNUM (16 bits). */
- 4, /* FTAG_REGNUM (16 bits). */
- 12, /* FISEG_REGNUM (16 bits). */
- 8, /* FIOFF_REGNUM. */
- 20, /* FOSEG_REGNUM (16 bits). */
- 16, /* FOOFF_REGNUM. */
- 6, /* FOP_REGNUM (bottom 11 bits). */
- 160 + 0 * 16, /* XMM0_REGNUM through ... */
+ 144, /* ... %st(7) (80 bits each). */
+ 0, /* `fctrl' (16 bits). */
+ 2, /* `fstat' (16 bits). */
+ 4, /* `ftag' (16 bits). */
+ 12, /* `fiseg' (16 bits). */
+ 8, /* `fioff'. */
+ 20, /* `foseg' (16 bits). */
+ 16, /* `fooff'. */
+ 6, /* `fop' (bottom 11 bits). */
+ 160 + 0 * 16, /* %xmm0 through ... */
160 + 1 * 16,
160 + 2 * 16,
160 + 3 * 16,
160 + 12 * 16,
160 + 13 * 16,
160 + 14 * 16,
- 160 + 15 * 16, /* ... XMM15_REGNUM (128 bits each). */
- 24 /* MXCSR_REGNUM. */
+ 160 + 15 * 16, /* ... %xmm15 (128 bits each). */
};
-/* FIXME: kettenis/20030430: We made an unfortunate choice in putting
- %mxcsr after the SSE registers %xmm0-%xmm7 instead of before, since
- it makes supporting the registers %xmm8-%xmm15 on x86-64 a bit
- involved. Hack around it by explicitly overriding the offset for
- %mxcsr here. */
-
#define FXSAVE_ADDR(fxsave, regnum) \
- ((regnum == MXCSR_REGNUM) ? (fxsave + 24) : \
- (fxsave + fxsave_offset[regnum - FP0_REGNUM]))
+ (fxsave + fxsave_offset[regnum - I387_ST0_REGNUM])
+
+/* We made an unfortunate choice in putting %mxcsr after the SSE
+ registers %xmm0-%xmm7 instead of before, since it makes supporting
+ the registers %xmm8-%xmm15 on AMD64 a bit involved. Therefore we
+ don't include the offset for %mxcsr here above. */
+
+#define FXSAVE_MXCSR_ADDR(fxsave) (fxsave + 24)
-static int i387_tag (unsigned char *raw);
+static int i387_tag (const gdb_byte *raw);
\f
-/* Fill GDB's register array with the floating-point and SSE register
- values in *FXSAVE. This function masks off any of the reserved
- bits in *FXSAVE. */
+/* Fill register REGNUM in REGCACHE with the appropriate
+ floating-point or SSE register value from *FXSAVE. This function
+ masks off any of the reserved bits in *FXSAVE. */
void
-i387_supply_fxsave (char *fxsave)
+i387_supply_fxsave (struct regcache *regcache, int regnum, const void *fxsave)
{
- int i, last_regnum = MXCSR_REGNUM;
+ struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
+ const gdb_byte *regs = fxsave;
+ int i;
- if (gdbarch_tdep (current_gdbarch)->num_xmm_regs == 0)
- last_regnum = FOP_REGNUM;
+ gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
+ gdb_assert (tdep->num_xmm_regs > 0);
- for (i = FP0_REGNUM; i <= last_regnum; i++)
- {
- if (fxsave == NULL)
- {
- supply_register (i, NULL);
- continue;
- }
+ /* Define I387_ST0_REGNUM and I387_NUM_XMM_REGS such that we use the
+ proper definitions for REGCACHE's architecture. */
- /* Most of the FPU control registers occupy only 16 bits in
- the fxsave area. Give those a special treatment. */
- if (i >= FPC_REGNUM && i < XMM0_REGNUM
- && i != FIOFF_REGNUM && i != FOOFF_REGNUM)
- {
- unsigned char val[4];
-
- memcpy (val, FXSAVE_ADDR (fxsave, i), 2);
- val[2] = val[3] = 0;
- if (i == FOP_REGNUM)
- val[1] &= ((1 << 3) - 1);
- else if (i== FTAG_REGNUM)
- {
- /* The fxsave area contains a simplified version of the
- tag word. We have to look at the actual 80-bit FP
- data to recreate the traditional i387 tag word. */
-
- unsigned long ftag = 0;
- int fpreg;
- int top;
-
- top = (((FXSAVE_ADDR (fxsave, FSTAT_REGNUM))[1] >> 3) & 0x7);
-
- for (fpreg = 7; fpreg >= 0; fpreg--)
- {
- int tag;
-
- if (val[0] & (1 << fpreg))
- {
- int regnum = (fpreg + 8 - top) % 8 + FP0_REGNUM;
- tag = i387_tag (FXSAVE_ADDR (fxsave, regnum));
- }
- else
- tag = 3; /* Empty */
-
- ftag |= tag << (2 * fpreg);
- }
- val[0] = ftag & 0xff;
- val[1] = (ftag >> 8) & 0xff;
- }
- supply_register (i, val);
- }
+#define I387_ST0_REGNUM tdep->st0_regnum
+#define I387_NUM_XMM_REGS tdep->num_xmm_regs
+
+ for (i = I387_ST0_REGNUM; i < I387_MXCSR_REGNUM; i++)
+ if (regnum == -1 || regnum == i)
+ {
+ if (regs == NULL)
+ {
+ regcache_raw_supply (regcache, i, NULL);
+ continue;
+ }
+
+ /* Most of the FPU control registers occupy only 16 bits in
+ the fxsave area. Give those a special treatment. */
+ if (i >= I387_FCTRL_REGNUM && i < I387_XMM0_REGNUM
+ && i != I387_FIOFF_REGNUM && i != I387_FOOFF_REGNUM)
+ {
+ gdb_byte val[4];
+
+ memcpy (val, FXSAVE_ADDR (regs, i), 2);
+ val[2] = val[3] = 0;
+ if (i == I387_FOP_REGNUM)
+ val[1] &= ((1 << 3) - 1);
+ else if (i== I387_FTAG_REGNUM)
+ {
+ /* The fxsave area contains a simplified version of
+ the tag word. We have to look at the actual 80-bit
+ FP data to recreate the traditional i387 tag word. */
+
+ unsigned long ftag = 0;
+ int fpreg;
+ int top;
+
+ top = ((FXSAVE_ADDR (regs, I387_FSTAT_REGNUM))[1] >> 3);
+ top &= 0x7;
+
+ for (fpreg = 7; fpreg >= 0; fpreg--)
+ {
+ int tag;
+
+ if (val[0] & (1 << fpreg))
+ {
+ int regnum = (fpreg + 8 - top) % 8 + I387_ST0_REGNUM;
+ tag = i387_tag (FXSAVE_ADDR (regs, regnum));
+ }
+ else
+ tag = 3; /* Empty */
+
+ ftag |= tag << (2 * fpreg);
+ }
+ val[0] = ftag & 0xff;
+ val[1] = (ftag >> 8) & 0xff;
+ }
+ regcache_raw_supply (regcache, i, val);
+ }
+ else
+ regcache_raw_supply (regcache, i, FXSAVE_ADDR (regs, i));
+ }
+
+ if (regnum == I387_MXCSR_REGNUM || regnum == -1)
+ {
+ if (regs == NULL)
+ regcache_raw_supply (regcache, I387_MXCSR_REGNUM, NULL);
else
- supply_register (i, FXSAVE_ADDR (fxsave, i));
+ regcache_raw_supply (regcache, I387_MXCSR_REGNUM,
+ FXSAVE_MXCSR_ADDR (regs));
}
+
+#undef I387_ST0_REGNUM
+#undef I387_NUM_XMM_REGS
}
/* Fill register REGNUM (if it is a floating-point or SSE register) in
- *FXSAVE with the value in GDB's register array. If REGNUM is -1, do
- this for all registers. This function doesn't touch any of the
- reserved bits in *FXSAVE. */
+ *FXSAVE with the value from REGCACHE. If REGNUM is -1, do this for
+ all registers. This function doesn't touch any of the reserved
+ bits in *FXSAVE. */
void
-i387_fill_fxsave (char *fxsave, int regnum)
+i387_collect_fxsave (const struct regcache *regcache, int regnum, void *fxsave)
{
- int i, last_regnum = MXCSR_REGNUM;
+ struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ gdb_byte *regs = fxsave;
+ int i;
- if (gdbarch_tdep (current_gdbarch)->num_xmm_regs == 0)
- last_regnum = FOP_REGNUM;
+ gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
+ gdb_assert (tdep->num_xmm_regs > 0);
- for (i = FP0_REGNUM; i <= last_regnum; i++)
+ /* Define I387_ST0_REGNUM and I387_NUM_XMM_REGS such that we use the
+ proper definitions for REGCACHE's architecture. */
+
+#define I387_ST0_REGNUM tdep->st0_regnum
+#define I387_NUM_XMM_REGS tdep->num_xmm_regs
+
+ for (i = I387_ST0_REGNUM; i < I387_MXCSR_REGNUM; i++)
if (regnum == -1 || regnum == i)
{
/* Most of the FPU control registers occupy only 16 bits in
the fxsave area. Give those a special treatment. */
- if (i >= FPC_REGNUM && i < XMM0_REGNUM
- && i != FIOFF_REGNUM && i != FOOFF_REGNUM)
+ if (i >= I387_FCTRL_REGNUM && i < I387_XMM0_REGNUM
+ && i != I387_FIOFF_REGNUM && i != I387_FOOFF_REGNUM)
{
- unsigned char buf[4];
+ gdb_byte buf[4];
- regcache_collect (i, buf);
+ regcache_raw_collect (regcache, i, buf);
- if (i == FOP_REGNUM)
+ if (i == I387_FOP_REGNUM)
{
/* The opcode occupies only 11 bits. Make sure we
don't touch the other bits. */
buf[1] &= ((1 << 3) - 1);
- buf[1] |= ((FXSAVE_ADDR (fxsave, i))[1] & ~((1 << 3) - 1));
+ buf[1] |= ((FXSAVE_ADDR (regs, i))[1] & ~((1 << 3) - 1));
}
- else if (i == FTAG_REGNUM)
+ else if (i == I387_FTAG_REGNUM)
{
/* Converting back is much easier. */
buf[0] |= (1 << fpreg);
}
}
- memcpy (FXSAVE_ADDR (fxsave, i), buf, 2);
+ memcpy (FXSAVE_ADDR (regs, i), buf, 2);
}
else
- regcache_collect (i, FXSAVE_ADDR (fxsave, i));
+ regcache_raw_collect (regcache, i, FXSAVE_ADDR (regs, i));
}
+
+ if (regnum == I387_MXCSR_REGNUM || regnum == -1)
+ regcache_raw_collect (regcache, I387_MXCSR_REGNUM,
+ FXSAVE_MXCSR_ADDR (regs));
+
+#undef I387_ST0_REGNUM
+#undef I387_NUM_XMM_REGS
+}
+
+/* Fill register REGNUM (if it is a floating-point or SSE register) in
+ *FXSAVE with the value in GDB's register cache. If REGNUM is -1, do
+ this for all registers. This function doesn't touch any of the
+ reserved bits in *FXSAVE. */
+
+void
+i387_fill_fxsave (void *fxsave, int regnum)
+{
+ i387_collect_fxsave (current_regcache, regnum, fxsave);
}
/* Recreate the FTW (tag word) valid bits from the 80-bit FP data in
*RAW. */
static int
-i387_tag (unsigned char *raw)
+i387_tag (const gdb_byte *raw)
{
int integer;
unsigned int exponent;
}
}
}
+
+/* Prepare the FPU stack in REGCACHE for a function return. */
+
+void
+i387_return_value (struct gdbarch *gdbarch, struct regcache *regcache)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ ULONGEST fstat;
+
+ /* Define I387_ST0_REGNUM such that we use the proper
+ definitions for the architecture. */
+#define I387_ST0_REGNUM tdep->st0_regnum
+
+ /* Set the top of the floating-point register stack to 7. The
+ actual value doesn't really matter, but 7 is what a normal
+ function return would end up with if the program started out with
+ a freshly initialized FPU. */
+ regcache_raw_read_unsigned (regcache, I387_FSTAT_REGNUM, &fstat);
+ fstat |= (7 << 11);
+ regcache_raw_write_unsigned (regcache, I387_FSTAT_REGNUM, fstat);
+
+ /* Mark %st(1) through %st(7) as empty. Since we set the top of the
+ floating-point register stack to 7, the appropriate value for the
+ tag word is 0x3fff. */
+ regcache_raw_write_unsigned (regcache, I387_FTAG_REGNUM, 0x3fff);
+
+#undef I387_ST0_REGNUM
+}