summaryrefslogtreecommitdiff
path: root/gdb/i386-tdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/i386-tdep.c')
-rw-r--r--gdb/i386-tdep.c183
1 files changed, 121 insertions, 62 deletions
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index f4cbc347c8a..d3e33576cd6 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -79,45 +79,75 @@ static char *i386_mmx_names[] =
static const int i386_num_mmx_regs = ARRAY_SIZE (i386_mmx_names);
-#define MM0_REGNUM NUM_REGS
-
static int
-i386_mmx_regnum_p (int regnum)
+i386_mmx_regnum_p (struct gdbarch *gdbarch, int regnum)
{
- return (regnum >= MM0_REGNUM
- && regnum < MM0_REGNUM + i386_num_mmx_regs);
+ int mm0_regnum = gdbarch_tdep (gdbarch)->mm0_regnum;
+
+ if (mm0_regnum < 0)
+ return 0;
+
+ return (regnum >= mm0_regnum && regnum < mm0_regnum + i386_num_mmx_regs);
}
-/* FP register? */
+/* SSE register? */
-int
-i386_fp_regnum_p (int regnum)
+static int
+i386_sse_regnum_p (struct gdbarch *gdbarch, int regnum)
{
- return (regnum < NUM_REGS
- && (FP0_REGNUM && FP0_REGNUM <= regnum && regnum < FPC_REGNUM));
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+#define I387_ST0_REGNUM tdep->st0_regnum
+#define I387_NUM_XMM_REGS tdep->num_xmm_regs
+
+ if (I387_NUM_XMM_REGS == 0)
+ return 0;
+
+ return (I387_XMM0_REGNUM <= regnum && regnum < I387_MXCSR_REGNUM);
+
+#undef I387_ST0_REGNUM
+#undef I387_NUM_XMM_REGS
}
-int
-i386_fpc_regnum_p (int regnum)
+static int
+i386_mxcsr_regnum_p (struct gdbarch *gdbarch, int regnum)
{
- return (regnum < NUM_REGS
- && (FPC_REGNUM <= regnum && regnum < XMM0_REGNUM));
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+#define I387_ST0_REGNUM tdep->st0_regnum
+#define I387_NUM_XMM_REGS tdep->num_xmm_regs
+
+ if (I387_NUM_XMM_REGS == 0)
+ return 0;
+
+ return (regnum == I387_MXCSR_REGNUM);
+
+#undef I387_ST0_REGNUM
+#undef I387_NUM_XMM_REGS
}
-/* SSE register? */
+#define I387_ST0_REGNUM (gdbarch_tdep (current_gdbarch)->st0_regnum)
+#define I387_MM0_REGNUM (gdbarch_tdep (current_gdbarch)->mm0_regnum)
+#define I387_NUM_XMM_REGS (gdbarch_tdep (current_gdbarch)->num_xmm_regs)
+
+/* FP register? */
int
-i386_sse_regnum_p (int regnum)
+i386_fp_regnum_p (int regnum)
{
- return (regnum < NUM_REGS
- && (XMM0_REGNUM <= regnum && regnum < MXCSR_REGNUM));
+ if (I387_ST0_REGNUM < 0)
+ return 0;
+
+ return (I387_ST0_REGNUM <= regnum && regnum < I387_FCTRL_REGNUM);
}
int
-i386_mxcsr_regnum_p (int regnum)
+i386_fpc_regnum_p (int regnum)
{
- return (regnum < NUM_REGS
- && regnum == MXCSR_REGNUM);
+ if (I387_ST0_REGNUM < 0)
+ return 0;
+
+ return (I387_FCTRL_REGNUM <= regnum && regnum < I387_XMM0_REGNUM);
}
/* Return the name of register REG. */
@@ -125,8 +155,8 @@ i386_mxcsr_regnum_p (int regnum)
const char *
i386_register_name (int reg)
{
- if (i386_mmx_regnum_p (reg))
- return i386_mmx_names[reg - MM0_REGNUM];
+ if (i386_mmx_regnum_p (current_gdbarch, reg))
+ return i386_mmx_names[reg - I387_MM0_REGNUM];
if (reg >= 0 && reg < i386_num_register_names)
return i386_register_names[reg];
@@ -149,17 +179,17 @@ i386_stab_reg_to_regnum (int reg)
else if (reg >= 12 && reg <= 19)
{
/* Floating-point registers. */
- return reg - 12 + FP0_REGNUM;
+ return reg - 12 + I387_ST0_REGNUM;
}
else if (reg >= 21 && reg <= 28)
{
/* SSE registers. */
- return reg - 21 + XMM0_REGNUM;
+ return reg - 21 + I387_XMM0_REGNUM;
}
else if (reg >= 29 && reg <= 36)
{
/* MMX registers. */
- return reg - 29 + MM0_REGNUM;
+ return reg - 29 + I387_MM0_REGNUM;
}
/* This will hopefully provoke a warning. */
@@ -182,7 +212,7 @@ i386_dwarf_reg_to_regnum (int reg)
else if (reg >= 11 && reg <= 18)
{
/* Floating-point registers. */
- return reg - 11 + FP0_REGNUM;
+ return reg - 11 + I387_ST0_REGNUM;
}
else if (reg >= 21)
{
@@ -193,6 +223,10 @@ i386_dwarf_reg_to_regnum (int reg)
/* This will hopefully provoke a warning. */
return NUM_REGS + NUM_PSEUDO_REGS;
}
+
+#undef I387_ST0_REGNUM
+#undef I387_MM0_REGNUM
+#undef I387_NUM_XMM_REGS
/* This is the variable that is set with "set disassembly-flavor", and
@@ -1121,6 +1155,7 @@ static void
i386_extract_return_value (struct type *type, struct regcache *regcache,
void *dst)
{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
bfd_byte *valbuf = dst;
int len = TYPE_LENGTH (type);
char buf[I386_MAX_REGISTER_SIZE];
@@ -1134,7 +1169,7 @@ i386_extract_return_value (struct type *type, struct regcache *regcache,
if (TYPE_CODE (type) == TYPE_CODE_FLT)
{
- if (FP0_REGNUM < 0)
+ if (tdep->st0_regnum < 0)
{
warning ("Cannot find floating-point return value.");
memset (valbuf, 0, len);
@@ -1178,8 +1213,13 @@ static void
i386_store_return_value (struct type *type, struct regcache *regcache,
const void *valbuf)
{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
int len = TYPE_LENGTH (type);
+ /* Define I387_ST0_REGNUM such that we use the proper definitions
+ for the architecture. */
+#define I387_ST0_REGNUM I386_ST0_REGNUM
+
if (TYPE_CODE (type) == TYPE_CODE_STRUCT
&& TYPE_NFIELDS (type) == 1)
{
@@ -1190,9 +1230,9 @@ i386_store_return_value (struct type *type, struct regcache *regcache,
if (TYPE_CODE (type) == TYPE_CODE_FLT)
{
ULONGEST fstat;
- char buf[FPU_REG_RAW_SIZE];
+ char buf[I386_MAX_REGISTER_SIZE];
- if (FP0_REGNUM < 0)
+ if (tdep->st0_regnum < 0)
{
warning ("Cannot set floating-point return value.");
return;
@@ -1213,14 +1253,14 @@ i386_store_return_value (struct type *type, struct regcache *regcache,
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, FSTAT_REGNUM, &fstat);
+ regcache_raw_read_unsigned (regcache, I387_FSTAT_REGNUM, &fstat);
fstat |= (7 << 11);
- regcache_raw_write_unsigned (regcache, FSTAT_REGNUM, fstat);
+ 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, FTAG_REGNUM, 0x3fff);
+ regcache_raw_write_unsigned (regcache, I387_FTAG_REGNUM, 0x3fff);
}
else
{
@@ -1239,6 +1279,8 @@ i386_store_return_value (struct type *type, struct regcache *regcache,
internal_error (__FILE__, __LINE__,
"Cannot store return value of %d bytes long.", len);
}
+
+#undef I387_ST0_REGNUM
}
/* Extract from REGCACHE, which contains the (raw) register state, the
@@ -1300,10 +1342,10 @@ i386_register_type (struct gdbarch *gdbarch, int regnum)
if (i386_fp_regnum_p (regnum))
return builtin_type_i387_ext;
- if (i386_sse_regnum_p (regnum))
+ if (i386_sse_regnum_p (gdbarch, regnum))
return builtin_type_vec128i;
- if (i386_mmx_regnum_p (regnum))
+ if (i386_mmx_regnum_p (gdbarch, regnum))
return builtin_type_vec64i;
return builtin_type_int;
@@ -1315,24 +1357,30 @@ i386_register_type (struct gdbarch *gdbarch, int regnum)
static int
i386_mmx_regnum_to_fp_regnum (struct regcache *regcache, int regnum)
{
- int mmxi;
+ struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
+ int mmxreg, fpreg;
ULONGEST fstat;
int tos;
- int fpi;
- mmxi = regnum - MM0_REGNUM;
- regcache_raw_read_unsigned (regcache, FSTAT_REGNUM, &fstat);
+ /* Define I387_ST0_REGNUM such that we use the proper definitions
+ for REGCACHE's architecture. */
+#define I387_ST0_REGNUM tdep->st0_regnum
+
+ mmxreg = regnum - tdep->mm0_regnum;
+ regcache_raw_read_unsigned (regcache, I387_FSTAT_REGNUM, &fstat);
tos = (fstat >> 11) & 0x7;
- fpi = (mmxi + tos) % 8;
+ fpreg = (mmxreg + tos) % 8;
+
+ return (I387_ST0_REGNUM + fpreg);
- return (FP0_REGNUM + fpi);
+#undef I387_ST0_REGNUM
}
static void
i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache,
int regnum, void *buf)
{
- if (i386_mmx_regnum_p (regnum))
+ if (i386_mmx_regnum_p (gdbarch, regnum))
{
char mmx_buf[MAX_REGISTER_SIZE];
int fpnum = i386_mmx_regnum_to_fp_regnum (regcache, regnum);
@@ -1349,7 +1397,7 @@ static void
i386_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache,
int regnum, const void *buf)
{
- if (i386_mmx_regnum_p (regnum))
+ if (i386_mmx_regnum_p (gdbarch, regnum))
{
char mmx_buf[MAX_REGISTER_SIZE];
int fpnum = i386_mmx_regnum_to_fp_regnum (regcache, regnum);
@@ -1708,11 +1756,11 @@ int
i386_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
struct reggroup *group)
{
- int sse_regnum_p = (i386_sse_regnum_p (regnum)
- || i386_mxcsr_regnum_p (regnum));
+ int sse_regnum_p = (i386_sse_regnum_p (gdbarch, regnum)
+ || i386_mxcsr_regnum_p (gdbarch, regnum));
int fp_regnum_p = (i386_fp_regnum_p (regnum)
|| i386_fpc_regnum_p (regnum));
- int mmx_regnum_p = (i386_mmx_regnum_p (regnum));
+ int mmx_regnum_p = (i386_mmx_regnum_p (gdbarch, regnum));
if (group == i386_mmx_reggroup)
return mmx_regnum_p;
@@ -1755,22 +1803,28 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
tdep = XMALLOC (struct gdbarch_tdep);
gdbarch = gdbarch_alloc (&info, tdep);
- /* The i386 default settings now include the SSE registers.
- I386_NUM_XREGS includes mxcsr, and we don't want to count
- this as one of the xmm regs -- which is why we subtract one.
-
- Note: kevinb/2003-07-14: Whatever Mark's concerns are about the
- FPU registers in the FIXME below apply to the SSE registers as well.
- The only problem that I see is that these registers will show up
- in "info all-registers" even on CPUs where they don't exist. IMO,
- however, if it's a choice between printing them always (even when
- they don't exist) or never showing them to the user (even when they
- do exist), I prefer the former over the latter. Ideally, of course,
- we'd somehow autodetect that we have them (or not) and display them
- when we have them and suppress them when we don't.
-
- FIXME: kettenis/20020614: They do include the FPU registers for
- now, which probably is not quite right. */
+ /* The default settings include the FPU registers, the MMX registers
+ and the SSE registers. This can be overidden for a specific ABI
+ by adjusting the members `st0_regnum', `mm0_regnum' and
+ `num_xmm_regs' of `struct gdbarch_tdep', otherwise the registers
+ will show up in the output of "info all-registers". Ideally we
+ should try to autodetect whether they are available, such that we
+ can prevent "info all-registers" from displaying registers that
+ aren't available.
+
+ NOTE: kevinb/2003-07-13: ... if it's a choice between printing
+ [the SSE registers] always (even when they don't exist) or never
+ showing them to the user (even when they do exist), I prefer the
+ former over the latter. */
+
+ tdep->st0_regnum = I386_ST0_REGNUM;
+
+ /* The MMX registers are implemented as pseudo-registers. Put off
+ caclulating the register number for %mm0 until we know the number
+ of raw registers. */
+ tdep->mm0_regnum = 0;
+
+ /* I386_NUM_XREGS includes %mxcsr, so substract one. */
tdep->num_xmm_regs = I386_NUM_XREGS - 1;
tdep->jb_pc_offset = -1;
@@ -1874,6 +1928,11 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
frame_unwind_append_sniffer (gdbarch, i386_sigtramp_frame_sniffer);
frame_unwind_append_sniffer (gdbarch, i386_frame_sniffer);
+ /* Unless support for MMX has been disabled, make %mm0 the first
+ pseudo-register. */
+ if (tdep->mm0_regnum == 0)
+ tdep->mm0_regnum = gdbarch_num_regs (gdbarch);
+
return gdbarch;
}