/* Target-dependent code for the Xtensa port of GDB, the GNU debugger.
- Copyright (C) 2003-2017 Free Software Foundation, Inc.
+ Copyright (C) 2003-2018 Free Software Foundation, Inc.
This file is part of GDB.
#include "dis-asm.h"
#include "inferior.h"
#include "osabi.h"
-#include "floatformat.h"
#include "regcache.h"
#include "reggroups.h"
#include "regset.h"
#define PS_WOE (1<<18)
#define PS_EXC (1<<4)
+/* Big enough to hold the size of the largest register in bytes. */
+#define XTENSA_MAX_REGISTER_SIZE 64
+
static int
windowing_enabled (struct gdbarch *gdbarch, unsigned int ps)
{
/* Find register by name. */
static int
-xtensa_find_register_by_name (struct gdbarch *gdbarch, char *name)
+xtensa_find_register_by_name (struct gdbarch *gdbarch, const char *name)
{
int i;
xtensa_register_write_masked (struct regcache *regcache,
xtensa_register_t *reg, const gdb_byte *buffer)
{
- unsigned int value[(MAX_REGISTER_SIZE + 3) / 4];
+ unsigned int value[(XTENSA_MAX_REGISTER_SIZE + 3) / 4];
const xtensa_mask_t *mask = reg->mask;
int shift = 0; /* Shift for next mask (mod 32). */
DEBUGTRACE ("xtensa_register_write_masked ()\n");
/* Copy the masked register to host byte-order. */
- if (gdbarch_byte_order (get_regcache_arch (regcache)) == BFD_ENDIAN_BIG)
+ if (gdbarch_byte_order (regcache->arch ()) == BFD_ENDIAN_BIG)
for (i = 0; i < bytesize; i++)
{
mem >>= 8;
of the registers and assemble them into a single value. */
static enum register_status
-xtensa_register_read_masked (struct regcache *regcache,
+xtensa_register_read_masked (readable_regcache *regcache,
xtensa_register_t *reg, gdb_byte *buffer)
{
- unsigned int value[(MAX_REGISTER_SIZE + 3) / 4];
+ unsigned int value[(XTENSA_MAX_REGISTER_SIZE + 3) / 4];
const xtensa_mask_t *mask = reg->mask;
int shift = 0;
enum register_status status;
ULONGEST val;
- status = regcache_cooked_read_unsigned (regcache, r, &val);
+ status = regcache->cooked_read (r, &val);
if (status != REG_VALID)
return status;
regval = (unsigned int) val;
ptr = value;
mem = *ptr;
- if (gdbarch_byte_order (get_regcache_arch (regcache)) == BFD_ENDIAN_BIG)
+ if (gdbarch_byte_order (regcache->arch ()) == BFD_ENDIAN_BIG)
for (i = 0; i < bytesize; i++)
{
if ((i & 3) == 0)
static enum register_status
xtensa_pseudo_register_read (struct gdbarch *gdbarch,
- struct regcache *regcache,
+ readable_regcache *regcache,
int regnum,
gdb_byte *buffer)
{
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-
DEBUGTRACE ("xtensa_pseudo_register_read (... regnum = %d (%s) ...)\n",
regnum, xtensa_register_name (gdbarch, regnum));
&& (regnum >= gdbarch_tdep (gdbarch)->a0_base)
&& (regnum <= gdbarch_tdep (gdbarch)->a0_base + 15))
{
- gdb_byte *buf = (gdb_byte *) alloca (MAX_REGISTER_SIZE);
+ ULONGEST value;
enum register_status status;
- status = regcache_raw_read (regcache,
- gdbarch_tdep (gdbarch)->wb_regnum,
- buf);
+ status = regcache->raw_read (gdbarch_tdep (gdbarch)->wb_regnum,
+ &value);
if (status != REG_VALID)
return status;
- regnum = arreg_number (gdbarch, regnum,
- extract_unsigned_integer (buf, 4, byte_order));
+ regnum = arreg_number (gdbarch, regnum, value);
}
/* We can always read non-pseudo registers. */
if (regnum >= 0 && regnum < gdbarch_num_regs (gdbarch))
- return regcache_raw_read (regcache, regnum, buffer);
+ return regcache->raw_read (regnum, buffer);
/* We have to find out how to deal with priveleged registers.
Let's treat them as pseudo-registers, but we cannot read/write them. */
- else if (regnum < gdbarch_tdep (gdbarch)->a0_base)
+ else if (gdbarch_tdep (gdbarch)->call_abi == CallAbiCall0Only
+ || regnum < gdbarch_tdep (gdbarch)->a0_base)
{
buffer[0] = (gdb_byte)0;
buffer[1] = (gdb_byte)0;
return xtensa_register_read_masked (regcache, reg, buffer);
/* Assume that we can read the register. */
- return regcache_raw_read (regcache, regnum, buffer);
+ return regcache->raw_read (regnum, buffer);
}
else
internal_error (__FILE__, __LINE__,
int regnum,
const gdb_byte *buffer)
{
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
-
DEBUGTRACE ("xtensa_pseudo_register_write (... regnum = %d (%s) ...)\n",
regnum, xtensa_register_name (gdbarch, regnum));
&& (regnum >= gdbarch_tdep (gdbarch)->a0_base)
&& (regnum <= gdbarch_tdep (gdbarch)->a0_base + 15))
{
- gdb_byte *buf = (gdb_byte *) alloca (MAX_REGISTER_SIZE);
-
- regcache_raw_read (regcache,
- gdbarch_tdep (gdbarch)->wb_regnum, buf);
- regnum = arreg_number (gdbarch, regnum,
- extract_unsigned_integer (buf, 4, byte_order));
+ ULONGEST value;
+ regcache_raw_read_unsigned (regcache,
+ gdbarch_tdep (gdbarch)->wb_regnum, &value);
+ regnum = arreg_number (gdbarch, regnum, value);
}
/* We can always write 'core' registers.
Note: We might have converted Ax->ARy. */
if (regnum >= 0 && regnum < gdbarch_num_regs (gdbarch))
- regcache_raw_write (regcache, regnum, buffer);
+ regcache->raw_write (regnum, buffer);
/* We have to find out how to deal with priveleged registers.
Let's treat them as pseudo-registers, but we cannot read/write them. */
}
/* Assume that we can write the register. */
- regcache_raw_write (regcache, regnum, buffer);
+ regcache->raw_write (regnum, buffer);
}
else
internal_error (__FILE__, __LINE__,
xtensa_init_reggroups (void)
{
int i;
- char cpname[] = "cp0";
xtensa_ar_reggroup = reggroup_new ("ar", USER_REGGROUP);
xtensa_user_reggroup = reggroup_new ("user", USER_REGGROUP);
xtensa_vectra_reggroup = reggroup_new ("vectra", USER_REGGROUP);
for (i = 0; i < XTENSA_MAX_COPROCESSOR; i++)
- {
- cpname[2] = '0' + i;
- xtensa_cp[i] = reggroup_new (cpname, USER_REGGROUP);
- }
+ xtensa_cp[i] = reggroup_new (xstrprintf ("cp%d", i), USER_REGGROUP);
}
static void
size_t len)
{
const xtensa_elf_gregset_t *regs = (const xtensa_elf_gregset_t *) gregs;
- struct gdbarch *gdbarch = get_regcache_arch (rc);
+ struct gdbarch *gdbarch = rc->arch ();
int i;
DEBUGTRACE ("xtensa_supply_gregset (..., regnum==%d, ...)\n", regnum);
if (regnum == gdbarch_pc_regnum (gdbarch) || regnum == -1)
- regcache_raw_supply (rc, gdbarch_pc_regnum (gdbarch), (char *) ®s->pc);
+ rc->raw_supply (gdbarch_pc_regnum (gdbarch), (char *) ®s->pc);
if (regnum == gdbarch_ps_regnum (gdbarch) || regnum == -1)
- regcache_raw_supply (rc, gdbarch_ps_regnum (gdbarch), (char *) ®s->ps);
+ rc->raw_supply (gdbarch_ps_regnum (gdbarch), (char *) ®s->ps);
if (regnum == gdbarch_tdep (gdbarch)->wb_regnum || regnum == -1)
- regcache_raw_supply (rc, gdbarch_tdep (gdbarch)->wb_regnum,
- (char *) ®s->windowbase);
+ rc->raw_supply (gdbarch_tdep (gdbarch)->wb_regnum,
+ (char *) ®s->windowbase);
if (regnum == gdbarch_tdep (gdbarch)->ws_regnum || regnum == -1)
- regcache_raw_supply (rc, gdbarch_tdep (gdbarch)->ws_regnum,
- (char *) ®s->windowstart);
+ rc->raw_supply (gdbarch_tdep (gdbarch)->ws_regnum,
+ (char *) ®s->windowstart);
if (regnum == gdbarch_tdep (gdbarch)->lbeg_regnum || regnum == -1)
- regcache_raw_supply (rc, gdbarch_tdep (gdbarch)->lbeg_regnum,
- (char *) ®s->lbeg);
+ rc->raw_supply (gdbarch_tdep (gdbarch)->lbeg_regnum,
+ (char *) ®s->lbeg);
if (regnum == gdbarch_tdep (gdbarch)->lend_regnum || regnum == -1)
- regcache_raw_supply (rc, gdbarch_tdep (gdbarch)->lend_regnum,
- (char *) ®s->lend);
+ rc->raw_supply (gdbarch_tdep (gdbarch)->lend_regnum,
+ (char *) ®s->lend);
if (regnum == gdbarch_tdep (gdbarch)->lcount_regnum || regnum == -1)
- regcache_raw_supply (rc, gdbarch_tdep (gdbarch)->lcount_regnum,
- (char *) ®s->lcount);
+ rc->raw_supply (gdbarch_tdep (gdbarch)->lcount_regnum,
+ (char *) ®s->lcount);
if (regnum == gdbarch_tdep (gdbarch)->sar_regnum || regnum == -1)
- regcache_raw_supply (rc, gdbarch_tdep (gdbarch)->sar_regnum,
- (char *) ®s->sar);
+ rc->raw_supply (gdbarch_tdep (gdbarch)->sar_regnum,
+ (char *) ®s->sar);
if (regnum >=gdbarch_tdep (gdbarch)->ar_base
&& regnum < gdbarch_tdep (gdbarch)->ar_base
+ gdbarch_tdep (gdbarch)->num_aregs)
- regcache_raw_supply (rc, regnum,
- (char *) ®s->ar[regnum - gdbarch_tdep
- (gdbarch)->ar_base]);
+ rc->raw_supply
+ (regnum, (char *) ®s->ar[regnum - gdbarch_tdep (gdbarch)->ar_base]);
else if (regnum == -1)
{
for (i = 0; i < gdbarch_tdep (gdbarch)->num_aregs; ++i)
- regcache_raw_supply (rc, gdbarch_tdep (gdbarch)->ar_base + i,
- (char *) ®s->ar[i]);
+ rc->raw_supply (gdbarch_tdep (gdbarch)->ar_base + i,
+ (char *) ®s->ar[i]);
}
}
#define C0_MAXOPDS 3 /* Maximum number of operands for prologue
analysis. */
-#define C0_NREGS 16 /* Number of A-registers to track. */
#define C0_CLESV 12 /* Callee-saved registers are here and up. */
#define C0_SP 1 /* Register used as SP. */
#define C0_FP 15 /* Register used as FP. */
if (start_addr == 0)
return fp_regnum;
- if (!xtensa_default_isa)
- xtensa_default_isa = xtensa_isa_init (0, 0);
isa = xtensa_default_isa;
gdb_assert (XTENSA_ISA_BSZ >= xtensa_isa_maxlength (isa));
ins = xtensa_insnbuf_alloc (isa);
struct regcache *regcache,
void *dst)
{
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch *gdbarch = regcache->arch ();
bfd_byte *valbuf = (bfd_byte *) dst;
int len = TYPE_LENGTH (type);
ULONGEST pc, wb;
for (; len > 0; len -= 4, areg++, valbuf += 4)
{
if (len < 4)
- regcache_raw_read_part (regcache, areg, offset, len, valbuf);
+ regcache->raw_read_part (areg, offset, len, valbuf);
else
- regcache_raw_read (regcache, areg, valbuf);
+ regcache->raw_read (areg, valbuf);
}
}
struct regcache *regcache,
const void *dst)
{
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
+ struct gdbarch *gdbarch = regcache->arch ();
const bfd_byte *valbuf = (const bfd_byte *) dst;
unsigned int areg;
ULONGEST pc, wb;
for (; len > 0; len -= 4, areg++, valbuf += 4)
{
if (len < 4)
- regcache_raw_write_part (regcache, areg, offset, len, valbuf);
+ regcache->raw_write_part (areg, offset, len, valbuf);
else
- regcache_raw_write (regcache, areg, valbuf);
+ regcache->raw_write (areg, valbuf);
}
}
if (struct_return)
{
store_unsigned_integer (buf, REGISTER_SIZE, byte_order, struct_addr);
- regcache_cooked_write (regcache, ARG_1ST (gdbarch), buf);
+ regcache->cooked_write (ARG_1ST (gdbarch), buf);
}
for (i = 0; i < nargs; i++)
v = v >> ((REGISTER_SIZE - n) * TARGET_CHAR_BIT);
store_unsigned_integer (buf, REGISTER_SIZE, byte_order, v);
- regcache_cooked_write (regcache, r, buf);
+ regcache->cooked_write (r, buf);
cp += REGISTER_SIZE;
n -= REGISTER_SIZE;
else
while (n > 0)
{
- regcache_cooked_write (regcache, r, cp);
+ regcache->cooked_write (r, cp);
cp += REGISTER_SIZE;
n -= REGISTER_SIZE;
to modify WINDOWSTART register to make it look like there
is only one register window corresponding to WINDOWEBASE. */
- regcache_raw_read (regcache, gdbarch_tdep (gdbarch)->wb_regnum, buf);
+ regcache->raw_read (gdbarch_tdep (gdbarch)->wb_regnum, buf);
regcache_cooked_write_unsigned
(regcache, gdbarch_tdep (gdbarch)->ws_regnum,
1 << extract_unsigned_integer (buf, 4, byte_order));
cache->call0 = 1;
rtmp = (xtensa_c0reg_t*) alloca(nregs * sizeof(xtensa_c0reg_t));
- if (!xtensa_default_isa)
- xtensa_default_isa = xtensa_isa_init (0, 0);
isa = xtensa_default_isa;
gdb_assert (XTENSA_ISA_BSZ >= xtensa_isa_maxlength (isa));
ins = xtensa_insnbuf_alloc (isa);
/* Special registers 0..255 (core). */
#define XTENSA_DBREGN_SREG(n) (0x0200+(n))
+/* User registers 0..255. */
+#define XTENSA_DBREGN_UREG(n) (0x0300+(n))
for (rmap = tdep->regmap, n = 0; rmap->target_number != -1; n++, rmap++)
{
tdep->litbase_regnum = n;
else if (rmap->target_number == XTENSA_DBREGN_SREG(230))
tdep->ps_regnum = n;
+ else if (rmap->target_number == XTENSA_DBREGN_UREG(231))
+ tdep->threadptr_regnum = n;
#if 0
else if (rmap->target_number == XTENSA_DBREGN_SREG(226))
tdep->interrupt_regnum = n;
max_size = rmap->byte_size;
if (rmap->mask != 0 && tdep->num_regs == 0)
tdep->num_regs = n;
- /* Find out out how to deal with priveleged registers.
-
- if ((rmap->flags & XTENSA_REGISTER_FLAGS_PRIVILEGED) != 0
- && tdep->num_nopriv_regs == 0)
- tdep->num_nopriv_regs = n;
- */
if ((rmap->flags & XTENSA_REGISTER_FLAGS_PRIVILEGED) != 0
- && tdep->num_regs == 0)
- tdep->num_regs = n;
+ && tdep->num_nopriv_regs == 0)
+ tdep->num_nopriv_regs = n;
}
+ if (tdep->num_regs == 0)
+ tdep->num_regs = tdep->num_nopriv_regs;
/* Number of pseudo registers. */
tdep->num_pseudo_regs = n - tdep->num_regs;
DEBUGTRACE ("gdbarch_init()\n");
+ if (!xtensa_default_isa)
+ xtensa_default_isa = xtensa_isa_init (0, 0);
+
/* We have to set the byte order before we call gdbarch_alloc. */
info.byte_order = XCHAL_HAVE_BE ? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE;
xtensa_verify_config (gdbarch);
xtensa_session_once_reported = 0;
+ set_gdbarch_wchar_bit (gdbarch, 2 * TARGET_CHAR_BIT);
+ set_gdbarch_wchar_signed (gdbarch, 0);
+
/* Pseudo-Register read/write. */
set_gdbarch_pseudo_register_read (gdbarch, xtensa_pseudo_register_read);
set_gdbarch_pseudo_register_write (gdbarch, xtensa_pseudo_register_write);
frame_unwind_append_unwinder (gdbarch, &xtensa_unwind);
dwarf2_append_unwinders (gdbarch);
- set_gdbarch_print_insn (gdbarch, print_insn_xtensa);
-
set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
xtensa_add_reggroups (gdbarch);
error (_("xtensa_dump_tdep(): not implemented"));
}
-/* Provide a prototype to silence -Wmissing-prototypes. */
-extern initialize_file_ftype _initialize_xtensa_tdep;
-
void
_initialize_xtensa_tdep (void)
{