aboutsummaryrefslogtreecommitdiff
path: root/gdb/i387-tdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/i387-tdep.c')
-rw-r--r--gdb/i387-tdep.c274
1 files changed, 173 insertions, 101 deletions
diff --git a/gdb/i387-tdep.c b/gdb/i387-tdep.c
index 6feb392..ff369f9 100644
--- a/gdb/i387-tdep.c
+++ b/gdb/i387-tdep.c
@@ -205,6 +205,7 @@ void
i387_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
struct frame_info *frame, const char *args)
{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (get_frame_arch (frame));
char buf[4];
ULONGEST fctrl;
ULONGEST fstat;
@@ -217,20 +218,26 @@ i387_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
int fpreg;
int top;
- fctrl = get_frame_register_unsigned (frame, FCTRL_REGNUM);
- fstat = get_frame_register_unsigned (frame, FSTAT_REGNUM);
- ftag = get_frame_register_unsigned (frame, FTAG_REGNUM);
- fiseg = get_frame_register_unsigned (frame, FISEG_REGNUM);
- fioff = get_frame_register_unsigned (frame, FIOFF_REGNUM);
- foseg = get_frame_register_unsigned (frame, FOSEG_REGNUM);
- fooff = get_frame_register_unsigned (frame, FOOFF_REGNUM);
- fop = get_frame_register_unsigned (frame, FOP_REGNUM);
+ 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];
+ unsigned char raw[I386_MAX_REGISTER_SIZE];
int tag = (ftag >> (fpreg * 2)) & 3;
int i;
@@ -252,7 +259,7 @@ i387_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
break;
}
- get_frame_register (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--)
@@ -278,6 +285,8 @@ i387_print_float_info (struct gdbarch *gdbarch, struct ui_file *file,
fprintf_filtered (file, "%s\n", local_hex_string_custom (fooff, "08"));
fprintf_filtered (file, "Opcode: %s\n",
local_hex_string_custom (fop ? (fop | 0xd800) : 0, "04"));
+
+#undef I387_ST0_REGNUM
}
@@ -331,70 +340,87 @@ i387_value_to_register (struct frame_info *frame, int regnum,
put_frame_register (frame, regnum, to);
}
+
/* Handle FSAVE and FXSAVE formats. */
+/* FIXME: kettenis/20030927: The functions below should accept a
+ `regcache' argument, but I don't want to change the function
+ signature just yet. There's some band-aid in the functions below
+ in the form of the `regcache' local variables. This will ease the
+ transition later on. */
+
/* At fsave_offset[REGNUM] you'll find the offset to the location in
the data structure used by the "fsave" instruction where GDB
register REGNUM is stored. */
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])
-/* Fill register REGNUM in GDB's register cache 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_fsave (const char *fsave, int regnum)
+i387_supply_fsave (struct regcache *regcache, int regnum, const void *fsave)
{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
+ const char *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)
{
if (fsave == NULL)
{
- supply_register (i, NULL);
- return;
+ 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 >= FPC_REGNUM
- && i != FIOFF_REGNUM && i != FOOFF_REGNUM)
+ if (i >= I387_FCTRL_REGNUM
+ && i != I387_FIOFF_REGNUM && i != I387_FOOFF_REGNUM)
{
unsigned char val[4];
- memcpy (val, FSAVE_ADDR (fsave, i), 2);
+ memcpy (val, FSAVE_ADDR (regs, i), 2);
val[2] = val[3] = 0;
- if (i == FOP_REGNUM)
+ if (i == I387_FOP_REGNUM)
val[1] &= ((1 << 3) - 1);
- supply_register (i, val);
+ regcache_raw_supply (regcache, i, val);
}
else
- supply_register (i, FSAVE_ADDR (fsave, i));
+ regcache_raw_supply (regcache, i, FSAVE_ADDR (regs, i));
}
+#undef I387_ST0_REGNUM
}
/* Fill register REGNUM (if it is a floating-point register) in *FSAVE
@@ -403,34 +429,44 @@ i387_supply_fsave (const char *fsave, int regnum)
bits in *FSAVE. */
void
-i387_fill_fsave (char *fsave, int regnum)
+i387_fill_fsave (void *fsave, int regnum)
{
+ struct regcache *regcache = current_regcache;
+ struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ char *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];
- 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
}
@@ -440,23 +476,23 @@ i387_fill_fsave (char *fsave, int regnum)
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,
@@ -471,56 +507,63 @@ static int fxsave_offset[] =
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 (const unsigned char *raw);
-/* Fill register REGNUM in GDB's register cache with the appropriate
+/* 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 (const char *fxsave, int regnum)
+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 char *regs = fxsave;
+ int i;
+
+ gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
+ gdb_assert (tdep->num_xmm_regs > 0);
- if (gdbarch_tdep (current_gdbarch)->num_xmm_regs == 0)
- last_regnum = FOP_REGNUM;
+ /* Define I387_ST0_REGNUM and I387_NUM_XMM_REGS such that we use the
+ proper definitions for REGCACHE's architecture. */
- for (i = FP0_REGNUM; i <= last_regnum; i++)
+#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 (fxsave == NULL)
+ if (regs == NULL)
{
- supply_register (i, 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 >= 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 val[4];
- memcpy (val, FXSAVE_ADDR (fxsave, i), 2);
+ memcpy (val, FXSAVE_ADDR (regs, i), 2);
val[2] = val[3] = 0;
- if (i == FOP_REGNUM)
+ if (i == I387_FOP_REGNUM)
val[1] &= ((1 << 3) - 1);
- else if (i== FTAG_REGNUM)
+ 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
@@ -530,7 +573,8 @@ i387_supply_fxsave (const char *fxsave, int regnum)
int fpreg;
int top;
- top = (((FXSAVE_ADDR (fxsave, FSTAT_REGNUM))[1] >> 3) & 0x7);
+ top = ((FXSAVE_ADDR (regs, I387_FSTAT_REGNUM))[1] >> 3);
+ top &= 0x7;
for (fpreg = 7; fpreg >= 0; fpreg--)
{
@@ -538,8 +582,8 @@ i387_supply_fxsave (const char *fxsave, int regnum)
if (val[0] & (1 << fpreg))
{
- int regnum = (fpreg + 8 - top) % 8 + FP0_REGNUM;
- tag = i387_tag (FXSAVE_ADDR (fxsave, regnum));
+ int regnum = (fpreg + 8 - top) % 8 + I387_ST0_REGNUM;
+ tag = i387_tag (FXSAVE_ADDR (regs, regnum));
}
else
tag = 3; /* Empty */
@@ -549,11 +593,23 @@ i387_supply_fxsave (const char *fxsave, int regnum)
val[0] = ftag & 0xff;
val[1] = (ftag >> 8) & 0xff;
}
- supply_register (i, val);
+ regcache_raw_supply (regcache, i, val);
}
else
- supply_register (i, FXSAVE_ADDR (fxsave, i));
+ 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
+ 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
@@ -562,33 +618,42 @@ i387_supply_fxsave (const char *fxsave, int regnum)
reserved bits in *FXSAVE. */
void
-i387_fill_fxsave (char *fxsave, int regnum)
+i387_fill_fxsave (void *fxsave, int regnum)
{
- int i, last_regnum = MXCSR_REGNUM;
+ struct regcache *regcache = current_regcache;
+ struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ char *regs = fxsave;
+ int i;
+
+ gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM);
+ gdb_assert (tdep->num_xmm_regs > 0);
- if (gdbarch_tdep (current_gdbarch)->num_xmm_regs == 0)
- last_regnum = FOP_REGNUM;
+ /* Define I387_ST0_REGNUM and I387_NUM_XMM_REGS such that we use the
+ proper definitions for REGCACHE's architecture. */
- for (i = FP0_REGNUM; i <= last_regnum; i++)
+#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];
- 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. */
@@ -607,11 +672,18 @@ i387_fill_fxsave (char *fxsave, int regnum)
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
}
/* Recreate the FTW (tag word) valid bits from the 80-bit FP data in