* i386-tdep.h: Put opaque declarations in alphabetical
order. Remove spurious whitespace. (struct gdbarch_tdep): add st0_regnum and mm0_regnum members. (i386_sse_regnum_p, i386_mxcsr_regnum_p): Remove prototypes. * i386-tdep.c (MM0_REGNUM): Remove define. (i386_mmx_regnum_p): Add gdbarch argument. (i386_sse_regnum_p, i386_mxcsr_regnum_p): Add gdbarch argument. Rewrite using new macro definitions for FPU/SSE registers. (i386_fp_regnum_p, i386_fpc_regnum_p): Rewrite using new macro definitions from i387-tdep.h. (i386_register_name): Update. (i386_stab_reg_to_regnum, i386_dwarf_reg_to_regnum): Update to use new macro definitions for FPU/SSE registers. (i386_extract_return_value): Determine whether floating-point registers are present by examining REGCACHE's architecture. (i386_store_return_value): Likewise. Use I386_MAX_REGISTER_SIZE instead of FPU_REG_RAW_SIZE. Use new macro definitions for FPU/SSE registers. (i386_register_type): Update. (i386_mmx_regnum_to_fp_regnum): Rewrite using new macro definitions for FPU registers. Use REGCACHE's architecture to determine the appropriate register numbers. (i386_pseudo_register_read, i386_pseudo_register_write, i386_register_reggroup_p): Update. (i386_gdbarch_init): Initialize TDEP->st0_regnum and TDEP->mm0_regnum. * i387-tdep.h (I387_FCTRL_REGNUM, I387_FSTAT_REGNUM, I387_FTAG_REGNUM, I387_FISEG_REGNUM, I387_FIOFF_REGNUM, I387_FOSEG_REGNUM, I387_FOOFF_REGNUM, I387_FOP_REGNUM, I387_XMM0_REGNUM, I387_MXCSR_REGNUM): New defines. (i387_supply_fsave, i387_fill_fsave, i387_supply_fxsave, i387_fill_fxsave): Change type of fsave/fxsave argument from `char *' to `void *'. * i387-tdep.c (i387_print_float_info, fsave_offset, FSAVE_ADDR, i387_supply_fsave, i387_fill_fsave, fxsave_offset, FXSAVE_ADDR, i387_supply_fxsave, i387_fill_fxsave): Update to use new macro definitions for FPU/SSE registers. (FXSAVE_MXCSR_ADDR): New define. * x86-64-tdep.c (x86_64_init_abi): Override TDEP->st0_regnum and TDEP->mm0_regnum. (I387_FISEG_REGNUM, I387_FOSEG_REGNUM): Remove defines. (I387_ST0_REGNUM): Define.
This commit is contained in:
parent
41d35cb0fe
commit
5716833cf8
6 changed files with 377 additions and 175 deletions
|
@ -1,5 +1,48 @@
|
|||
2003-09-27 Mark Kettenis <kettenis@gnu.org>
|
||||
|
||||
* i386-tdep.h: Put opaque declarations in alphabetical
|
||||
order. Remove spurious whitespace.
|
||||
(struct gdbarch_tdep): add st0_regnum and mm0_regnum members.
|
||||
(i386_sse_regnum_p, i386_mxcsr_regnum_p): Remove prototypes.
|
||||
* i386-tdep.c (MM0_REGNUM): Remove define.
|
||||
(i386_mmx_regnum_p): Add gdbarch argument.
|
||||
(i386_sse_regnum_p, i386_mxcsr_regnum_p): Add gdbarch argument.
|
||||
Rewrite using new macro definitions for FPU/SSE registers.
|
||||
(i386_fp_regnum_p, i386_fpc_regnum_p): Rewrite using new macro
|
||||
definitions from i387-tdep.h.
|
||||
(i386_register_name): Update.
|
||||
(i386_stab_reg_to_regnum, i386_dwarf_reg_to_regnum): Update to use
|
||||
new macro definitions for FPU/SSE registers.
|
||||
(i386_extract_return_value): Determine whether floating-point
|
||||
registers are present by examining REGCACHE's architecture.
|
||||
(i386_store_return_value): Likewise. Use I386_MAX_REGISTER_SIZE
|
||||
instead of FPU_REG_RAW_SIZE. Use new macro definitions for
|
||||
FPU/SSE registers.
|
||||
(i386_register_type): Update.
|
||||
(i386_mmx_regnum_to_fp_regnum): Rewrite using new macro
|
||||
definitions for FPU registers. Use REGCACHE's architecture to
|
||||
determine the appropriate register numbers.
|
||||
(i386_pseudo_register_read, i386_pseudo_register_write,
|
||||
i386_register_reggroup_p): Update.
|
||||
(i386_gdbarch_init): Initialize TDEP->st0_regnum and
|
||||
TDEP->mm0_regnum.
|
||||
* i387-tdep.h (I387_FCTRL_REGNUM, I387_FSTAT_REGNUM,
|
||||
I387_FTAG_REGNUM, I387_FISEG_REGNUM, I387_FIOFF_REGNUM,
|
||||
I387_FOSEG_REGNUM, I387_FOOFF_REGNUM, I387_FOP_REGNUM,
|
||||
I387_XMM0_REGNUM, I387_MXCSR_REGNUM): New defines.
|
||||
(i387_supply_fsave, i387_fill_fsave, i387_supply_fxsave,
|
||||
i387_fill_fxsave): Change type of fsave/fxsave argument from `char
|
||||
*' to `void *'.
|
||||
* i387-tdep.c (i387_print_float_info, fsave_offset, FSAVE_ADDR,
|
||||
i387_supply_fsave, i387_fill_fsave, fxsave_offset, FXSAVE_ADDR,
|
||||
i387_supply_fxsave, i387_fill_fxsave): Update to use new macro
|
||||
definitions for FPU/SSE registers.
|
||||
(FXSAVE_MXCSR_ADDR): New define.
|
||||
* x86-64-tdep.c (x86_64_init_abi): Override TDEP->st0_regnum and
|
||||
TDEP->mm0_regnum.
|
||||
(I387_FISEG_REGNUM, I387_FOSEG_REGNUM): Remove defines.
|
||||
(I387_ST0_REGNUM): Define.
|
||||
|
||||
* regcache.h (get_regcache_arch): New prototype.
|
||||
* regcache.c (get_regcache_arch): New function.
|
||||
|
||||
|
|
183
gdb/i386-tdep.c
183
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 (struct gdbarch *gdbarch, int regnum)
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
/* SSE register? */
|
||||
|
||||
static int
|
||||
i386_mmx_regnum_p (int regnum)
|
||||
i386_sse_regnum_p (struct gdbarch *gdbarch, int regnum)
|
||||
{
|
||||
return (regnum >= MM0_REGNUM
|
||||
&& regnum < MM0_REGNUM + i386_num_mmx_regs);
|
||||
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
|
||||
}
|
||||
|
||||
static int
|
||||
i386_mxcsr_regnum_p (struct gdbarch *gdbarch, int 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
|
||||
}
|
||||
|
||||
#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_fp_regnum_p (int regnum)
|
||||
{
|
||||
return (regnum < NUM_REGS
|
||||
&& (FP0_REGNUM && FP0_REGNUM <= regnum && regnum < FPC_REGNUM));
|
||||
if (I387_ST0_REGNUM < 0)
|
||||
return 0;
|
||||
|
||||
return (I387_ST0_REGNUM <= regnum && regnum < I387_FCTRL_REGNUM);
|
||||
}
|
||||
|
||||
int
|
||||
i386_fpc_regnum_p (int regnum)
|
||||
{
|
||||
return (regnum < NUM_REGS
|
||||
&& (FPC_REGNUM <= regnum && regnum < XMM0_REGNUM));
|
||||
}
|
||||
if (I387_ST0_REGNUM < 0)
|
||||
return 0;
|
||||
|
||||
/* SSE register? */
|
||||
|
||||
int
|
||||
i386_sse_regnum_p (int regnum)
|
||||
{
|
||||
return (regnum < NUM_REGS
|
||||
&& (XMM0_REGNUM <= regnum && regnum < MXCSR_REGNUM));
|
||||
}
|
||||
|
||||
int
|
||||
i386_mxcsr_regnum_p (int regnum)
|
||||
{
|
||||
return (regnum < NUM_REGS
|
||||
&& regnum == MXCSR_REGNUM);
|
||||
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 (FP0_REGNUM + fpi);
|
||||
return (I387_ST0_REGNUM + fpreg);
|
||||
|
||||
#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.
|
||||
/* 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-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.
|
||||
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. */
|
||||
|
||||
FIXME: kettenis/20020614: They do include the FPU registers for
|
||||
now, which probably is not quite right. */
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
/* Target-dependent code for GDB, the GNU debugger.
|
||||
/* Target-dependent code for the i386.
|
||||
|
||||
Copyright 2001, 2002, 2003
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
|
@ -22,9 +23,9 @@
|
|||
#ifndef I386_TDEP_H
|
||||
#define I386_TDEP_H
|
||||
|
||||
struct reggroup;
|
||||
struct gdbarch;
|
||||
struct frame_info;
|
||||
struct gdbarch;
|
||||
struct reggroup;
|
||||
|
||||
/* GDB's i386 target supports both the 32-bit Intel Architecture
|
||||
(IA-32) and the 64-bit AMD x86-64 architecture. Internally it uses
|
||||
|
@ -55,6 +56,15 @@ enum struct_return
|
|||
/* i386 architecture specific information. */
|
||||
struct gdbarch_tdep
|
||||
{
|
||||
/* Register number for %st(0). The register numbers for the other
|
||||
registers follow from this one. Set this to -1 to indicate the
|
||||
absence of an FPU. */
|
||||
int st0_regnum;
|
||||
|
||||
/* Register number for %mm0. Set this to -1 to indicate the absence
|
||||
of MMX support. */
|
||||
int mm0_regnum;
|
||||
|
||||
/* Number of SSE registers. */
|
||||
int num_xmm_regs;
|
||||
|
||||
|
@ -131,11 +141,6 @@ extern int i386_fpc_regnum_p (int regnum);
|
|||
#define MXCSR_REGNUM \
|
||||
(XMM0_REGNUM + gdbarch_tdep (current_gdbarch)->num_xmm_regs)
|
||||
|
||||
/* Return non-zero if REGNUM matches the SSE register and the SSE
|
||||
register set is active. */
|
||||
extern int i386_sse_regnum_p (int regnum);
|
||||
extern int i386_mxcsr_regnum_p (int regnum);
|
||||
|
||||
/* FIXME: kettenis/2001-11-24: Obsolete macro's. */
|
||||
#define FCS_REGNUM FISEG_REGNUM
|
||||
#define FCOFF_REGNUM FIOFF_REGNUM
|
||||
|
@ -194,4 +199,3 @@ extern int i386obsd_sc_reg_offset[];
|
|||
extern int i386bsd_sc_reg_offset[];
|
||||
|
||||
#endif /* i386-tdep.h */
|
||||
|
||||
|
|
268
gdb/i387-tdep.c
268
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,34 +340,42 @@ 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
|
||||
|
@ -366,35 +383,45 @@ static int fsave_offset[] =
|
|||
bits in *FSAVE. */
|
||||
|
||||
void
|
||||
i387_supply_fsave (const char *fsave, int regnum)
|
||||
i387_supply_fsave (const void *fsave, int regnum)
|
||||
{
|
||||
struct regcache *regcache = current_regcache;
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
|
||||
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 +430,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 +477,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,19 +508,18 @@ 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);
|
||||
|
||||
|
@ -493,34 +529,43 @@ static int i387_tag (const unsigned char *raw);
|
|||
masks off any of the reserved bits in *FXSAVE. */
|
||||
|
||||
void
|
||||
i387_supply_fxsave (const char *fxsave, int regnum)
|
||||
i387_supply_fxsave (const void *fxsave, int regnum)
|
||||
{
|
||||
int i, last_regnum = MXCSR_REGNUM;
|
||||
struct regcache *regcache = current_regcache;
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
|
||||
const char *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)
|
||||
{
|
||||
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 +575,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 +584,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 +595,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 +620,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;
|
||||
|
||||
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];
|
||||
|
||||
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 +674,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
|
||||
|
|
|
@ -27,6 +27,27 @@ struct ui_file;
|
|||
struct frame_info;
|
||||
struct type;
|
||||
|
||||
/* Because the number of general-purpose registers is different for
|
||||
AMD64, the floating-point registers and SSE registers get shifted.
|
||||
The following definitions are intended to help writing code that
|
||||
needs the register numbers of floating-point registers and SSE
|
||||
registers. In order to use these, one should provide a definition
|
||||
for I387_ST0_REGNUM, and possibly I387_NUM_XMM_REGS, preferably by
|
||||
using a local "#define" in the body of the function that uses this.
|
||||
Please "#undef" them before the end of the function. */
|
||||
|
||||
#define I387_FCTRL_REGNUM (I387_ST0_REGNUM + 8)
|
||||
#define I387_FSTAT_REGNUM (I387_FCTRL_REGNUM + 1)
|
||||
#define I387_FTAG_REGNUM (I387_FCTRL_REGNUM + 2)
|
||||
#define I387_FISEG_REGNUM (I387_FCTRL_REGNUM + 3)
|
||||
#define I387_FIOFF_REGNUM (I387_FCTRL_REGNUM + 4)
|
||||
#define I387_FOSEG_REGNUM (I387_FCTRL_REGNUM + 5)
|
||||
#define I387_FOOFF_REGNUM (I387_FCTRL_REGNUM + 6)
|
||||
#define I387_FOP_REGNUM (I387_FCTRL_REGNUM + 7)
|
||||
#define I387_XMM0_REGNUM (I387_ST0_REGNUM + 16)
|
||||
#define I387_MXCSR_REGNUM (I387_XMM0_REGNUM + I387_NUM_XMM_REGS)
|
||||
|
||||
|
||||
/* Print out the i387 floating point state. */
|
||||
|
||||
extern void i387_print_float_info (struct gdbarch *gdbarch,
|
||||
|
@ -56,26 +77,26 @@ extern void i387_value_to_register (struct frame_info *frame, int regnum,
|
|||
value from *FSAVE. This function masks off any of the reserved
|
||||
bits in *FSAVE. */
|
||||
|
||||
extern void i387_supply_fsave (const char *fsave, int regnum);
|
||||
extern void i387_supply_fsave (const void *fsave, int 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. */
|
||||
|
||||
extern void i387_fill_fsave (char *fsave, int regnum);
|
||||
extern void i387_fill_fsave (void *fsave, int regnum);
|
||||
|
||||
/* Fill register REGNUM in GDB's register cache with the appropriate
|
||||
floating-point or SSE register value from *FXSAVE. This function
|
||||
masks off any of the reserved bits in *FXSAVE. */
|
||||
|
||||
extern void i387_supply_fxsave (const char *fxsave, int regnum);
|
||||
extern void i387_supply_fxsave (const void *fxsave, int regnum);
|
||||
|
||||
/* 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. */
|
||||
|
||||
extern void i387_fill_fxsave (char *fxsave, int regnum);
|
||||
extern void i387_fill_fxsave (void *fxsave, int regnum);
|
||||
|
||||
#endif /* i387-tdep.h */
|
||||
|
|
|
@ -1209,7 +1209,8 @@ x86_64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
|
|||
{
|
||||
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||
|
||||
/* The x86-64 has 16 SSE registers. */
|
||||
/* AMD64 has an FPU and 16 SSE registers. */
|
||||
tdep->st0_regnum = X86_64_ST0_REGNUM;
|
||||
tdep->num_xmm_regs = 16;
|
||||
|
||||
/* This is what all the fuss is about. */
|
||||
|
@ -1264,6 +1265,7 @@ x86_64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
|
|||
|
||||
/* Avoid wiring in the MMX registers for now. */
|
||||
set_gdbarch_num_pseudo_regs (gdbarch, 0);
|
||||
tdep->mm0_regnum = -1;
|
||||
|
||||
set_gdbarch_unwind_dummy_id (gdbarch, x86_64_unwind_dummy_id);
|
||||
|
||||
|
@ -1278,8 +1280,7 @@ x86_64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
|
|||
}
|
||||
|
||||
|
||||
#define I387_FISEG_REGNUM FISEG_REGNUM
|
||||
#define I387_FOSEG_REGNUM FOSEG_REGNUM
|
||||
#define I387_ST0_REGNUM X86_64_ST0_REGNUM
|
||||
|
||||
/* The 64-bit FXSAVE format differs from the 32-bit format in the
|
||||
sense that the instruction pointer and data pointer are simply
|
||||
|
|
Loading…
Add table
Reference in a new issue