/* Target-dependent code for AMD64.
- Copyright (C) 2001-2018 Free Software Foundation, Inc.
+ Copyright (C) 2001-2019 Free Software Foundation, Inc.
Contributed by Jiri Smid, SuSE Labs.
#include "disasm.h"
#include "amd64-tdep.h"
#include "i387-tdep.h"
-#include "x86-xstate.h"
+#include "common/x86-xstate.h"
#include <algorithm>
#include "target-descriptions.h"
#include "arch/amd64.h"
readable_regcache *regcache,
int regnum)
{
- gdb_byte *raw_buf = (gdb_byte *) alloca (register_size (gdbarch, regnum));
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
- enum register_status status;
- struct value *result_value;
- gdb_byte *buf;
- result_value = allocate_value (register_type (gdbarch, regnum));
+ value *result_value = allocate_value (register_type (gdbarch, regnum));
VALUE_LVAL (result_value) = lval_register;
VALUE_REGNUM (result_value) = regnum;
- buf = value_contents_raw (result_value);
+ gdb_byte *buf = value_contents_raw (result_value);
if (i386_byte_regnum_p (gdbarch, regnum))
{
/* Extract (always little endian). */
if (gpnum >= AMD64_NUM_LOWER_BYTE_REGS)
{
+ gpnum -= AMD64_NUM_LOWER_BYTE_REGS;
+ gdb_byte raw_buf[register_size (gdbarch, gpnum)];
+
/* Special handling for AH, BH, CH, DH. */
- status = regcache->raw_read (gpnum - AMD64_NUM_LOWER_BYTE_REGS,
- raw_buf);
+ register_status status = regcache->raw_read (gpnum, raw_buf);
if (status == REG_VALID)
memcpy (buf, raw_buf + 1, 1);
else
}
else
{
- status = regcache->raw_read (gpnum, raw_buf);
+ gdb_byte raw_buf[register_size (gdbarch, gpnum)];
+ register_status status = regcache->raw_read (gpnum, raw_buf);
if (status == REG_VALID)
memcpy (buf, raw_buf, 1);
else
else if (i386_dword_regnum_p (gdbarch, regnum))
{
int gpnum = regnum - tdep->eax_regnum;
+ gdb_byte raw_buf[register_size (gdbarch, gpnum)];
/* Extract (always little endian). */
- status = regcache->raw_read (gpnum, raw_buf);
+ register_status status = regcache->raw_read (gpnum, raw_buf);
if (status == REG_VALID)
memcpy (buf, raw_buf, 4);
else
struct regcache *regcache,
int regnum, const gdb_byte *buf)
{
- gdb_byte *raw_buf = (gdb_byte *) alloca (register_size (gdbarch, regnum));
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
if (i386_byte_regnum_p (gdbarch, regnum))
if (gpnum >= AMD64_NUM_LOWER_BYTE_REGS)
{
+ gpnum -= AMD64_NUM_LOWER_BYTE_REGS;
+ gdb_byte raw_buf[register_size (gdbarch, gpnum)];
+
/* Read ... AH, BH, CH, DH. */
- regcache_raw_read (regcache,
- gpnum - AMD64_NUM_LOWER_BYTE_REGS, raw_buf);
+ regcache->raw_read (gpnum, raw_buf);
/* ... Modify ... (always little endian). */
memcpy (raw_buf + 1, buf, 1);
/* ... Write. */
- regcache_raw_write (regcache,
- gpnum - AMD64_NUM_LOWER_BYTE_REGS, raw_buf);
+ regcache->raw_write (gpnum, raw_buf);
}
else
{
+ gdb_byte raw_buf[register_size (gdbarch, gpnum)];
+
/* Read ... */
- regcache_raw_read (regcache, gpnum, raw_buf);
+ regcache->raw_read (gpnum, raw_buf);
/* ... Modify ... (always little endian). */
memcpy (raw_buf, buf, 1);
/* ... Write. */
- regcache_raw_write (regcache, gpnum, raw_buf);
+ regcache->raw_write (gpnum, raw_buf);
}
}
else if (i386_dword_regnum_p (gdbarch, regnum))
{
int gpnum = regnum - tdep->eax_regnum;
+ gdb_byte raw_buf[register_size (gdbarch, gpnum)];
/* Read ... */
- regcache_raw_read (regcache, gpnum, raw_buf);
+ regcache->raw_read (gpnum, raw_buf);
/* ... Modify ... (always little endian). */
memcpy (raw_buf, buf, 4);
/* ... Write. */
- regcache_raw_write (regcache, gpnum, raw_buf);
+ regcache->raw_write (gpnum, raw_buf);
}
else
i386_pseudo_register_write (gdbarch, regcache, regnum, buf);
{
if (readbuf)
{
- regcache_raw_read (regcache, AMD64_ST0_REGNUM, readbuf);
- regcache_raw_read (regcache, AMD64_ST1_REGNUM, readbuf + 16);
+ regcache->raw_read (AMD64_ST0_REGNUM, readbuf);
+ regcache->raw_read (AMD64_ST1_REGNUM, readbuf + 16);
}
if (writebuf)
{
i387_return_value (gdbarch, regcache);
- regcache_raw_write (regcache, AMD64_ST0_REGNUM, writebuf);
- regcache_raw_write (regcache, AMD64_ST1_REGNUM, writebuf + 16);
+ regcache->raw_write (AMD64_ST0_REGNUM, writebuf);
+ regcache->raw_write (AMD64_ST1_REGNUM, writebuf + 16);
/* Fix up the tag word such that both %st(0) and %st(1) are
marked as valid. */
gdb_assert (regnum != -1);
if (readbuf)
- regcache_raw_read_part (regcache, regnum, offset, std::min (len, 8),
- readbuf + i * 8);
+ regcache->raw_read_part (regnum, offset, std::min (len, 8),
+ readbuf + i * 8);
if (writebuf)
- regcache_raw_write_part (regcache, regnum, offset, std::min (len, 8),
- writebuf + i * 8);
+ regcache->raw_write_part (regnum, offset, std::min (len, 8),
+ writebuf + i * 8);
}
return RETURN_VALUE_REGISTER_CONVENTION;
\f
static CORE_ADDR
-amd64_push_arguments (struct regcache *regcache, int nargs,
- struct value **args, CORE_ADDR sp, int struct_return)
+amd64_push_arguments (struct regcache *regcache, int nargs, struct value **args,
+ CORE_ADDR sp, function_call_return_method return_method)
{
static int integer_regnum[] =
{
int i;
/* Reserve a register for the "hidden" argument. */
- if (struct_return)
+if (return_method == return_method_struct)
integer_reg++;
for (i = 0; i < nargs; i++)
gdb_assert (regnum != -1);
memset (buf, 0, sizeof buf);
memcpy (buf, valbuf + j * 8, std::min (len, 8));
- regcache_raw_write_part (regcache, regnum, offset, 8, buf);
+ regcache->raw_write_part (regnum, offset, 8, buf);
}
}
}
amd64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
struct regcache *regcache, CORE_ADDR bp_addr,
int nargs, struct value **args, CORE_ADDR sp,
- int struct_return, CORE_ADDR struct_addr)
+ function_call_return_method return_method,
+ CORE_ADDR struct_addr)
{
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
gdb_byte buf[8];
i387_reset_bnd_regs (gdbarch, regcache);
/* Pass arguments. */
- sp = amd64_push_arguments (regcache, nargs, args, sp, struct_return);
+ sp = amd64_push_arguments (regcache, nargs, args, sp, return_method);
/* Pass "hidden" argument". */
- if (struct_return)
+ if (return_method == return_method_struct)
{
store_unsigned_integer (buf, 8, byte_order, struct_addr);
- regcache_cooked_write (regcache, AMD64_RDI_REGNUM, buf);
+ regcache->cooked_write (AMD64_RDI_REGNUM, buf);
}
/* Store return address. */
/* Finally, update the stack pointer... */
store_unsigned_integer (buf, 8, byte_order, sp);
- regcache_cooked_write (regcache, AMD64_RSP_REGNUM, buf);
+ regcache->cooked_write (AMD64_RSP_REGNUM, buf);
/* ...and fake a frame pointer. */
- regcache_cooked_write (regcache, AMD64_RBP_REGNUM, buf);
+ regcache->cooked_write (AMD64_RBP_REGNUM, buf);
return sp + 16;
}
static void
amd64_none_init_abi (gdbarch_info info, gdbarch *arch)
{
- amd64_init_abi (info, arch, amd64_target_description (X86_XSTATE_SSE_MASK));
+ amd64_init_abi (info, arch, amd64_target_description (X86_XSTATE_SSE_MASK,
+ true));
}
static struct type *
amd64_x32_none_init_abi (gdbarch_info info, gdbarch *arch)
{
amd64_x32_init_abi (info, arch,
- amd64_target_description (X86_XSTATE_SSE_MASK));
+ amd64_target_description (X86_XSTATE_SSE_MASK, true));
}
/* Return the target description for a specified XSAVE feature mask. */
const struct target_desc *
-amd64_target_description (uint64_t xcr0)
+amd64_target_description (uint64_t xcr0, bool segments)
{
static target_desc *amd64_tdescs \
- [2/*AVX*/][2/*MPX*/][2/*AVX512*/][2/*PKRU*/] = {};
+ [2/*AVX*/][2/*MPX*/][2/*AVX512*/][2/*PKRU*/][2/*segments*/] = {};
target_desc **tdesc;
tdesc = &amd64_tdescs[(xcr0 & X86_XSTATE_AVX) ? 1 : 0]
[(xcr0 & X86_XSTATE_MPX) ? 1 : 0]
[(xcr0 & X86_XSTATE_AVX512) ? 1 : 0]
- [(xcr0 & X86_XSTATE_PKRU) ? 1 : 0];
+ [(xcr0 & X86_XSTATE_PKRU) ? 1 : 0]
+ [segments ? 1 : 0];
if (*tdesc == NULL)
- *tdesc = amd64_create_target_description (xcr0, false, false);
+ *tdesc = amd64_create_target_description (xcr0, false, false,
+ segments);
return *tdesc;
}
for (auto &a : xml_masks)
{
- auto tdesc = amd64_target_description (a.mask);
+ auto tdesc = amd64_target_description (a.mask, true);
selftests::record_xml_tdesc (a.xml, tdesc);
}
const gdb_byte *regs = (const gdb_byte *) fxsave;
if (regnum == -1 || regnum == I387_FISEG_REGNUM (tdep))
- regcache_raw_supply (regcache, I387_FISEG_REGNUM (tdep), regs + 12);
+ regcache->raw_supply (I387_FISEG_REGNUM (tdep), regs + 12);
if (regnum == -1 || regnum == I387_FOSEG_REGNUM (tdep))
- regcache_raw_supply (regcache, I387_FOSEG_REGNUM (tdep), regs + 20);
+ regcache->raw_supply (I387_FOSEG_REGNUM (tdep), regs + 20);
}
}
&& gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 64)
{
const gdb_byte *regs = (const gdb_byte *) xsave;
- static const gdb_byte zero[I386_MAX_REGISTER_SIZE] = { 0 };
ULONGEST clear_bv;
clear_bv = i387_xsave_get_clear_bv (gdbarch, xsave);
if (!(clear_bv & X86_XSTATE_X87))
{
if (regnum == -1 || regnum == I387_FISEG_REGNUM (tdep))
- regcache_raw_supply (regcache, I387_FISEG_REGNUM (tdep),
- regs + 12);
+ regcache->raw_supply (I387_FISEG_REGNUM (tdep), regs + 12);
if (regnum == -1 || regnum == I387_FOSEG_REGNUM (tdep))
- regcache_raw_supply (regcache, I387_FOSEG_REGNUM (tdep),
- regs + 20);
+ regcache->raw_supply (I387_FOSEG_REGNUM (tdep), regs + 20);
}
}
}
if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 64)
{
if (regnum == -1 || regnum == I387_FISEG_REGNUM (tdep))
- regcache_raw_collect (regcache, I387_FISEG_REGNUM (tdep), regs + 12);
+ regcache->raw_collect (I387_FISEG_REGNUM (tdep), regs + 12);
if (regnum == -1 || regnum == I387_FOSEG_REGNUM (tdep))
- regcache_raw_collect (regcache, I387_FOSEG_REGNUM (tdep), regs + 20);
+ regcache->raw_collect (I387_FOSEG_REGNUM (tdep), regs + 20);
}
}
if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 64)
{
if (regnum == -1 || regnum == I387_FISEG_REGNUM (tdep))
- regcache_raw_collect (regcache, I387_FISEG_REGNUM (tdep),
+ regcache->raw_collect (I387_FISEG_REGNUM (tdep),
regs + 12);
if (regnum == -1 || regnum == I387_FOSEG_REGNUM (tdep))
- regcache_raw_collect (regcache, I387_FOSEG_REGNUM (tdep),
+ regcache->raw_collect (I387_FOSEG_REGNUM (tdep),
regs + 20);
}
}