#include "gdbcore.h"
#include "objfiles.h"
#include "regcache.h"
+#include "regset.h"
#include "symfile.h"
#include "gdb_assert.h"
#include "x86-64-tdep.h"
#include "i387-tdep.h"
-/* Register numbers of various important registers. */
-
-#define X86_64_RAX_REGNUM 0 /* %rax */
-#define X86_64_RDX_REGNUM 3 /* %rdx */
-#define X86_64_RDI_REGNUM 5 /* %rdi */
-#define X86_64_RBP_REGNUM 6 /* %rbp */
-#define X86_64_RSP_REGNUM 7 /* %rsp */
-#define X86_64_RIP_REGNUM 16 /* %rip */
-#define X86_64_EFLAGS_REGNUM 17 /* %eflags */
-#define X86_64_ST0_REGNUM 22 /* %st0 */
-#define X86_64_XMM0_REGNUM 38 /* %xmm0 */
-#define X86_64_XMM1_REGNUM 39 /* %xmm1 */
+/* Register information. */
struct x86_64_register_info
{
static int x86_64_dwarf_regmap[] =
{
/* General Purpose Registers RAX, RDX, RCX, RBX, RSI, RDI. */
- X86_64_RAX_REGNUM, X86_64_RDX_REGNUM, 3, 2,
+ X86_64_RAX_REGNUM, X86_64_RDX_REGNUM, 2, 1,
4, X86_64_RDI_REGNUM,
/* Frame Pointer Register RBP. */
X86_64_XMM0_REGNUM + 14, X86_64_XMM0_REGNUM + 15,
/* Floating Point Registers 0-7. */
- X86_64_ST0_REGNUM + 0, X86_64_ST0_REGNUM + 1,
+ X86_64_ST0_REGNUM + 0, X86_64_ST0_REGNUM + 1,
X86_64_ST0_REGNUM + 2, X86_64_ST0_REGNUM + 3,
X86_64_ST0_REGNUM + 4, X86_64_ST0_REGNUM + 5,
X86_64_ST0_REGNUM + 6, X86_64_ST0_REGNUM + 7
int stack_values_count = 0;
int *stack_values;
stack_values = alloca (nargs * sizeof (int));
+
for (i = 0; i < nargs; i++)
{
enum x86_64_reg_class class[MAX_CLASSES];
int len = TYPE_LENGTH (type);
/* First handle long doubles. */
- if (TYPE_CODE_FLT == TYPE_CODE (type) && len == 16)
+ if (TYPE_CODE_FLT == TYPE_CODE (type) && len == 16)
{
ULONGEST fstat;
char buf[FPU_REG_RAW_SIZE];
else if (TYPE_CODE_FLT == TYPE_CODE (type))
{
/* Handle double and float variables. */
- regcache_cooked_write (regcache, X86_64_XMM0_REGNUM, valbuf);
+ regcache_cooked_write_part (regcache, X86_64_XMM0_REGNUM,
+ 0, len, valbuf);
}
/* XXX: What about complex floating point types? */
else
{
- int low_size = REGISTER_RAW_SIZE (0);
- int high_size = REGISTER_RAW_SIZE (1);
+ int low_size = register_size (current_gdbarch, X86_64_RAX_REGNUM);
+ int high_size = register_size (current_gdbarch, X86_64_RDX_REGNUM);
if (len <= low_size)
regcache_cooked_write_part (regcache, 0, 0, len, valbuf);
};
static const struct frame_unwind *
-x86_64_frame_p (CORE_ADDR pc)
+x86_64_frame_sniffer (struct frame_info *next_frame)
{
return &x86_64_frame_unwind;
}
};
static const struct frame_unwind *
-x86_64_sigtramp_frame_p (CORE_ADDR pc)
+x86_64_sigtramp_frame_sniffer (struct frame_info *next_frame)
{
+ CORE_ADDR pc = frame_pc_unwind (next_frame);
char *name;
find_pc_partial_function (pc, &name, NULL, NULL);
return frame_id_build (fp + 16, frame_pc_unwind (next_frame));
}
+/* 16 byte align the SP per frame requirements. */
+
+static CORE_ADDR
+x86_64_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp)
+{
+ return sp & -(CORE_ADDR)16;
+}
+\f
+
+/* Supply register REGNUM from the floating-point register set REGSET
+ to register cache REGCACHE. If REGNUM is -1, do this for all
+ registers in REGSET. */
+
+static void
+x86_64_supply_fpregset (const struct regset *regset, struct regcache *regcache,
+ int regnum, const void *fpregs, size_t len)
+{
+ const struct gdbarch_tdep *tdep = regset->descr;
+
+ gdb_assert (len == tdep->sizeof_fpregset);
+ x86_64_supply_fxsave (regcache, regnum, fpregs);
+}
+
+/* Return the appropriate register set for the core section identified
+ by SECT_NAME and SECT_SIZE. */
+
+static const struct regset *
+x86_64_regset_from_core_section (struct gdbarch *gdbarch,
+ const char *sect_name, size_t sect_size)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ if (strcmp (sect_name, ".reg2") == 0 && sect_size == tdep->sizeof_fpregset)
+ {
+ if (tdep->fpregset == NULL)
+ {
+ tdep->fpregset = XMALLOC (struct regset);
+ tdep->fpregset->descr = tdep;
+ tdep->fpregset->supply_regset = x86_64_supply_fpregset;
+ }
+
+ return tdep->fpregset;
+ }
+
+ return i386_regset_from_core_section (gdbarch, sect_name, sect_size);
+}
+\f
+
void
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 generally uses `fxsave' instead of `fsave' for saving its
+ floating-point registers. */
+ tdep->sizeof_fpregset = I387_SIZEOF_FXSAVE;
+
+ /* 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. */
/* Call dummy code. */
set_gdbarch_push_dummy_call (gdbarch, x86_64_push_dummy_call);
+ set_gdbarch_frame_align (gdbarch, x86_64_frame_align);
+ set_gdbarch_frame_red_zone_size (gdbarch, 128);
set_gdbarch_convert_register_p (gdbarch, x86_64_convert_register_p);
set_gdbarch_register_to_value (gdbarch, i387_register_to_value);
/* 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);
in the future. */
set_gdbarch_in_solib_call_trampoline (gdbarch, in_plt_section);
- frame_unwind_append_predicate (gdbarch, x86_64_sigtramp_frame_p);
- frame_unwind_append_predicate (gdbarch, x86_64_frame_p);
+ frame_unwind_append_sniffer (gdbarch, x86_64_sigtramp_frame_sniffer);
+ frame_unwind_append_sniffer (gdbarch, x86_64_frame_sniffer);
frame_base_set_default (gdbarch, &x86_64_frame_base);
+
+ /* If we have a register mapping, enable the generic core file support. */
+ if (tdep->gregset_reg_offset)
+ set_gdbarch_regset_from_core_section (gdbarch,
+ x86_64_regset_from_core_section);
}
\f
-#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
bits of these pointers (instead of just the 16-bits of the segment
selector). */
-/* 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. If REGNUM is
+ -1, do this for all registers. This function masks off any of the
+ reserved bits in *FXSAVE. */
void
-x86_64_supply_fxsave (char *fxsave)
+x86_64_supply_fxsave (struct regcache *regcache, int regnum,
+ const void *fxsave)
{
- i387_supply_fxsave (fxsave);
+ i387_supply_fxsave (regcache, regnum, fxsave);
if (fxsave)
{
- supply_register (I387_FISEG_REGNUM, fxsave + 12);
- supply_register (I387_FOSEG_REGNUM, fxsave + 20);
+ const char *regs = fxsave;
+
+ if (regnum == -1 || regnum == I387_FISEG_REGNUM)
+ regcache_raw_supply (regcache, I387_FISEG_REGNUM, regs + 12);
+ if (regnum == -1 || regnum == I387_FOSEG_REGNUM)
+ regcache_raw_supply (regcache, I387_FOSEG_REGNUM, regs + 20);
}
}
/* 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
+ *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. */