/* Target-dependent code for the Xtensa port of GDB, the GNU debugger.
- Copyright (C) 2003-2014 Free Software Foundation, Inc.
+ Copyright (C) 2003-2022 Free Software Foundation, Inc.
This file is part of GDB.
#include "frame.h"
#include "solib-svr4.h"
#include "symtab.h"
-#include "symfile.h"
-#include "objfiles.h"
#include "gdbtypes.h"
#include "gdbcore.h"
#include "value.h"
-#include "dis-asm.h"
-#include "inferior.h"
-#include "floatformat.h"
+#include "osabi.h"
#include "regcache.h"
#include "reggroups.h"
#include "regset.h"
-#include "dummy-frame.h"
-#include "dwarf2.h"
-#include "dwarf2-frame.h"
-#include "dwarf2loc.h"
+#include "dwarf2/frame.h"
#include "frame-base.h"
#include "frame-unwind.h"
#include "arch-utils.h"
#include "gdbarch.h"
-#include "remote.h"
-#include "serial.h"
#include "command.h"
#include "gdbcmd.h"
#include "xtensa-isa.h"
#include "xtensa-tdep.h"
#include "xtensa-config.h"
+#include <algorithm>
static unsigned int xtensa_debug_level = 0;
#define DEBUGWARN(args...) \
if (xtensa_debug_level > 0) \
- fprintf_unfiltered (gdb_stdlog, "(warn ) " args)
+ gdb_printf (gdb_stdlog, "(warn ) " args)
#define DEBUGINFO(args...) \
if (xtensa_debug_level > 1) \
- fprintf_unfiltered (gdb_stdlog, "(info ) " args)
+ gdb_printf (gdb_stdlog, "(info ) " args)
#define DEBUGTRACE(args...) \
if (xtensa_debug_level > 2) \
- fprintf_unfiltered (gdb_stdlog, "(trace) " args)
+ gdb_printf (gdb_stdlog, "(trace) " args)
#define DEBUGVERB(args...) \
if (xtensa_debug_level > 3) \
- fprintf_unfiltered (gdb_stdlog, "(verb ) " args)
+ gdb_printf (gdb_stdlog, "(verb ) " args)
/* According to the ABI, the SP must be aligned to 16-byte boundaries. */
#define TX_PS 0x20
/* ABI-independent macros. */
-#define ARG_NOF(gdbarch) \
- (gdbarch_tdep (gdbarch)->call_abi \
+#define ARG_NOF(tdep) \
+ (tdep->call_abi \
== CallAbiCall0Only ? C0_NARGS : (ARGS_NUM_REGS))
-#define ARG_1ST(gdbarch) \
- (gdbarch_tdep (gdbarch)->call_abi == CallAbiCall0Only \
- ? (gdbarch_tdep (gdbarch)->a0_base + C0_ARGS) \
- : (gdbarch_tdep (gdbarch)->a0_base + 6))
+#define ARG_1ST(tdep) \
+ (tdep->call_abi == CallAbiCall0Only \
+ ? (tdep->a0_base + C0_ARGS) \
+ : (tdep->a0_base + 6))
/* XTENSA_IS_ENTRY tests whether the first byte of an instruction
indicates that the instruction is an ENTRY instruction. */
#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)
{
+ xtensa_gdbarch_tdep *tdep = (xtensa_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+
/* If we know CALL0 ABI is set explicitly, say it is Call0. */
- if (gdbarch_tdep (gdbarch)->call_abi == CallAbiCall0Only)
+ if (tdep->call_abi == CallAbiCall0Only)
return 0;
return ((ps & PS_EXC) == 0 && (ps & PS_WOE) != 0);
static int
arreg_number (struct gdbarch *gdbarch, int a_regnum, ULONGEST wb)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ xtensa_gdbarch_tdep *tdep = (xtensa_gdbarch_tdep *) gdbarch_tdep (gdbarch);
int arreg;
arreg = a_regnum - tdep->a0_base;
static int
areg_number (struct gdbarch *gdbarch, int ar_regnum, unsigned int wb)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ xtensa_gdbarch_tdep *tdep = (xtensa_gdbarch_tdep *) gdbarch_tdep (gdbarch);
int areg;
areg = ar_regnum - tdep->ar_base;
/* 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_gdbarch_tdep *tdep = (xtensa_gdbarch_tdep *) gdbarch_tdep (gdbarch);
- for (i = 0; i < gdbarch_num_regs (gdbarch)
- + gdbarch_num_pseudo_regs (gdbarch);
- i++)
-
- if (strcasecmp (gdbarch_tdep (gdbarch)->regmap[i].name, name) == 0)
+ for (i = 0; i < gdbarch_num_cooked_regs (gdbarch); i++)
+ if (strcasecmp (tdep->regmap[i].name, name) == 0)
return i;
return -1;
static const char *
xtensa_register_name (struct gdbarch *gdbarch, int regnum)
{
+ xtensa_gdbarch_tdep *tdep = (xtensa_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+
/* Return the name stored in the register map. */
- if (regnum >= 0 && regnum < gdbarch_num_regs (gdbarch)
- + gdbarch_num_pseudo_regs (gdbarch))
- return gdbarch_tdep (gdbarch)->regmap[regnum].name;
+ if (regnum >= 0 && regnum < gdbarch_num_cooked_regs (gdbarch))
+ return tdep->regmap[regnum].name;
internal_error (__FILE__, __LINE__, _("invalid register %d"), regnum);
return 0;
static struct type *
xtensa_register_type (struct gdbarch *gdbarch, int regnum)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ xtensa_gdbarch_tdep *tdep = (xtensa_gdbarch_tdep *) gdbarch_tdep (gdbarch);
/* Return signed integer for ARx and Ax registers. */
if ((regnum >= tdep->ar_base
return builtin_type (gdbarch)->builtin_data_ptr;
/* Return the stored type for all other registers. */
- else if (regnum >= 0 && regnum < gdbarch_num_regs (gdbarch)
- + gdbarch_num_pseudo_regs (gdbarch))
+ else if (regnum >= 0 && regnum < gdbarch_num_cooked_regs (gdbarch))
{
xtensa_register_t* reg = &tdep->regmap[regnum];
if (tp == NULL)
{
- char *name = xstrprintf ("int%d", size * 8);
- tp = xmalloc (sizeof (struct ctype_cache));
+ std::string name = string_printf ("int%d", size * 8);
+
+ tp = XNEW (struct ctype_cache);
tp->next = tdep->type_entries;
tdep->type_entries = tp;
tp->size = size;
tp->virtual_type
- = arch_integer_type (gdbarch, size * 8, 1, name);
- xfree (name);
+ = arch_integer_type (gdbarch, size * 8, 1, name.c_str ());
}
reg->ctype = tp->virtual_type;
xtensa_reg_to_regnum (struct gdbarch *gdbarch, int regnum)
{
int i;
+ xtensa_gdbarch_tdep *tdep = (xtensa_gdbarch_tdep *) gdbarch_tdep (gdbarch);
if (regnum >= 0 && regnum < 16)
- return gdbarch_tdep (gdbarch)->a0_base + regnum;
+ return tdep->a0_base + regnum;
- for (i = 0;
- i < gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch);
- i++)
- if (regnum == gdbarch_tdep (gdbarch)->regmap[i].target_number)
+ for (i = 0; i < gdbarch_num_cooked_regs (gdbarch); i++)
+ if (regnum == tdep->regmap[i].target_number)
return i;
- internal_error (__FILE__, __LINE__,
- _("invalid dwarf/stabs register number %d"), regnum);
- return 0;
+ return -1;
}
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));
-
- if (regnum == gdbarch_num_regs (gdbarch)
- + gdbarch_num_pseudo_regs (gdbarch) - 1)
- regnum = gdbarch_tdep (gdbarch)->a0_base + 1;
+ xtensa_gdbarch_tdep *tdep = (xtensa_gdbarch_tdep *) gdbarch_tdep (gdbarch);
/* Read aliases a0..a15, if this is a Windowed ABI. */
- if (gdbarch_tdep (gdbarch)->isa_use_windowed_registers
- && (regnum >= gdbarch_tdep (gdbarch)->a0_base)
- && (regnum <= gdbarch_tdep (gdbarch)->a0_base + 15))
+ if (tdep->isa_use_windowed_registers
+ && (regnum >= tdep->a0_base)
+ && (regnum <= tdep->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 (tdep->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 (tdep->call_abi == CallAbiCall0Only
+ || regnum < tdep->a0_base)
{
buffer[0] = (gdb_byte)0;
buffer[1] = (gdb_byte)0;
return REG_VALID;
}
/* Pseudo registers. */
- else if (regnum >= 0
- && regnum < gdbarch_num_regs (gdbarch)
- + gdbarch_num_pseudo_regs (gdbarch))
+ else if (regnum >= 0 && regnum < gdbarch_num_cooked_regs (gdbarch))
{
- xtensa_register_t *reg = &gdbarch_tdep (gdbarch)->regmap[regnum];
+ xtensa_register_t *reg = &tdep->regmap[regnum];
xtensa_register_type_t type = reg->type;
- int flags = gdbarch_tdep (gdbarch)->target_flags;
+ int flags = tdep->target_flags;
/* We cannot read Unknown or Unmapped registers. */
if (type == xtRegisterTypeUnmapped || type == xtRegisterTypeUnknown)
/* Some targets cannot read TIE register files. */
else if (type == xtRegisterTypeTieRegfile)
- {
+ {
/* Use 'fetch' to get register? */
if (flags & xtTargetFlagsUseFetchStore)
{
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));
+ xtensa_gdbarch_tdep *tdep = (xtensa_gdbarch_tdep *) gdbarch_tdep (gdbarch);
- if (regnum == gdbarch_num_regs (gdbarch)
- + gdbarch_num_pseudo_regs (gdbarch) -1)
- regnum = gdbarch_tdep (gdbarch)->a0_base + 1;
-
- /* Renumber register, if aliase a0..a15 on Windowed ABI. */
- if (gdbarch_tdep (gdbarch)->isa_use_windowed_registers
- && (regnum >= gdbarch_tdep (gdbarch)->a0_base)
- && (regnum <= gdbarch_tdep (gdbarch)->a0_base + 15))
+ /* Renumber register, if aliases a0..a15 on Windowed ABI. */
+ if (tdep->isa_use_windowed_registers
+ && (regnum >= tdep->a0_base)
+ && (regnum <= tdep->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,
+ tdep->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. */
- else if (regnum < gdbarch_tdep (gdbarch)->a0_base)
+ else if (regnum < tdep->a0_base)
{
return;
}
/* Pseudo registers. */
- else if (regnum >= 0
- && regnum < gdbarch_num_regs (gdbarch)
- + gdbarch_num_pseudo_regs (gdbarch))
+ else if (regnum >= 0 && regnum < gdbarch_num_cooked_regs (gdbarch))
{
- xtensa_register_t *reg = &gdbarch_tdep (gdbarch)->regmap[regnum];
+ xtensa_register_t *reg = &tdep->regmap[regnum];
xtensa_register_type_t type = reg->type;
- int flags = gdbarch_tdep (gdbarch)->target_flags;
+ int flags = tdep->target_flags;
/* On most targets, we cannot write registers
of type "Unknown" or "Unmapped". */
if (type == xtRegisterTypeUnmapped || type == xtRegisterTypeUnknown)
- {
+ {
if ((flags & xtTargetFlagsNonVisibleRegs) == 0)
{
warning (_("cannot write register %s"),
/* Some targets cannot read TIE register files. */
else if (type == xtRegisterTypeTieRegfile)
- {
+ {
/* Use 'store' to get register? */
if (flags & xtTargetFlagsUseFetchStore)
{
/* We can always write mapped registers. */
else if (type == xtRegisterTypeMapped || type == xtRegisterTypeTieState)
- {
+ {
xtensa_register_write_masked (regcache, reg, buffer);
return;
}
/* Assume that we can write the register. */
- regcache_raw_write (regcache, regnum, buffer);
+ regcache->raw_write (regnum, buffer);
}
else
internal_error (__FILE__, __LINE__,
_("invalid register number %d"), regnum);
}
-static struct reggroup *xtensa_ar_reggroup;
-static struct reggroup *xtensa_user_reggroup;
-static struct reggroup *xtensa_vectra_reggroup;
-static struct reggroup *xtensa_cp[XTENSA_MAX_COPROCESSOR];
+static const reggroup *xtensa_ar_reggroup;
+static const reggroup *xtensa_user_reggroup;
+static const reggroup *xtensa_vectra_reggroup;
+static const reggroup *xtensa_cp[XTENSA_MAX_COPROCESSOR];
static void
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).release (),
+ USER_REGGROUP);
}
static void
xtensa_add_reggroups (struct gdbarch *gdbarch)
{
- int i;
-
- /* Predefined groups. */
- reggroup_add (gdbarch, all_reggroup);
- reggroup_add (gdbarch, save_reggroup);
- reggroup_add (gdbarch, restore_reggroup);
- reggroup_add (gdbarch, system_reggroup);
- reggroup_add (gdbarch, vector_reggroup);
- reggroup_add (gdbarch, general_reggroup);
- reggroup_add (gdbarch, float_reggroup);
-
/* Xtensa-specific groups. */
reggroup_add (gdbarch, xtensa_ar_reggroup);
reggroup_add (gdbarch, xtensa_user_reggroup);
reggroup_add (gdbarch, xtensa_vectra_reggroup);
- for (i = 0; i < XTENSA_MAX_COPROCESSOR; i++)
+ for (int i = 0; i < XTENSA_MAX_COPROCESSOR; i++)
reggroup_add (gdbarch, xtensa_cp[i]);
}
static int
-xtensa_coprocessor_register_group (struct reggroup *group)
+xtensa_coprocessor_register_group (const struct reggroup *group)
{
int i;
static int
xtensa_register_reggroup_p (struct gdbarch *gdbarch,
int regnum,
- struct reggroup *group)
+ const struct reggroup *group)
{
- xtensa_register_t* reg = &gdbarch_tdep (gdbarch)->regmap[regnum];
+ xtensa_gdbarch_tdep *tdep = (xtensa_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+ xtensa_register_t* reg = &tdep->regmap[regnum];
xtensa_register_type_t type = reg->type;
xtensa_register_group_t rg = reg->group;
int cp_number;
const void *gregs,
size_t len)
{
- const xtensa_elf_gregset_t *regs = gregs;
- struct gdbarch *gdbarch = get_regcache_arch (rc);
+ const xtensa_elf_gregset_t *regs = (const xtensa_elf_gregset_t *) gregs;
+ struct gdbarch *gdbarch = rc->arch ();
+ xtensa_gdbarch_tdep *tdep = (xtensa_gdbarch_tdep *) gdbarch_tdep (gdbarch);
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);
- if (regnum == gdbarch_tdep (gdbarch)->wb_regnum || regnum == -1)
- regcache_raw_supply (rc, 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);
- if (regnum == gdbarch_tdep (gdbarch)->lbeg_regnum || regnum == -1)
- regcache_raw_supply (rc, 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);
- if (regnum == gdbarch_tdep (gdbarch)->lcount_regnum || regnum == -1)
- regcache_raw_supply (rc, 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);
- 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 (gdbarch_ps_regnum (gdbarch), (char *) ®s->ps);
+ if (regnum == tdep->wb_regnum || regnum == -1)
+ rc->raw_supply (tdep->wb_regnum,
+ (char *) ®s->windowbase);
+ if (regnum == tdep->ws_regnum || regnum == -1)
+ rc->raw_supply (tdep->ws_regnum,
+ (char *) ®s->windowstart);
+ if (regnum == tdep->lbeg_regnum || regnum == -1)
+ rc->raw_supply (tdep->lbeg_regnum,
+ (char *) ®s->lbeg);
+ if (regnum == tdep->lend_regnum || regnum == -1)
+ rc->raw_supply (tdep->lend_regnum,
+ (char *) ®s->lend);
+ if (regnum == tdep->lcount_regnum || regnum == -1)
+ rc->raw_supply (tdep->lcount_regnum,
+ (char *) ®s->lcount);
+ if (regnum == tdep->sar_regnum || regnum == -1)
+ rc->raw_supply (tdep->sar_regnum,
+ (char *) ®s->sar);
+ if (regnum >=tdep->ar_base
+ && regnum < tdep->ar_base
+ + tdep->num_aregs)
+ rc->raw_supply
+ (regnum, (char *) ®s->ar[regnum - tdep->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]);
+ for (i = 0; i < tdep->num_aregs; ++i)
+ rc->raw_supply (tdep->ar_base + i,
+ (char *) ®s->ar[i]);
}
}
{
DEBUGTRACE ("xtensa_iterate_over_regset_sections\n");
- cb (".reg", sizeof (xtensa_elf_gregset_t), &xtensa_gregset,
- NULL, cb_data);
+ cb (".reg", sizeof (xtensa_elf_gregset_t), sizeof (xtensa_elf_gregset_t),
+ &xtensa_gregset, NULL, cb_data);
}
#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. */
/* Each element of xtensa_call0_frame_cache.c0_rt[] describes for each
A-register where the current content of the reg came from (in terms
of an original reg and a constant). Negative values of c0_rt[n].fp_reg
- mean that the orignal content of the register was saved to the stack.
+ mean that the original content of the register was saved to the stack.
c0_rt[n].fr.ofs is NOT the offset from the frame base because we don't
know where SP will end up until the entire prologue has been analyzed. */
int c0_hasfp; /* Current frame uses frame pointer. */
int fp_regnum; /* A-register used as FP. */
int c0_fp; /* Actual value of frame pointer. */
- int c0_fpalign; /* Dinamic adjustment for the stack
+ int c0_fpalign; /* Dynamic adjustment for the stack
pointer. It's an AND mask. Zero,
if alignment was not adjusted. */
int c0_old_sp; /* In case of dynamic adjustment, it is
xtensa_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
{
CORE_ADDR pc, fp;
+ xtensa_gdbarch_tdep *tdep = (xtensa_gdbarch_tdep *) gdbarch_tdep (gdbarch);
/* THIS-FRAME is a dummy frame. Return a frame ID of that frame. */
pc = get_frame_pc (this_frame);
fp = get_frame_register_unsigned
- (this_frame, gdbarch_tdep (gdbarch)->a0_base + 1);
+ (this_frame, tdep->a0_base + 1);
/* Make dummy frame ID unique by adding a constant. */
return frame_id_build (fp + SP_ALIGNMENT, pc);
{
#define RETURN_FP goto done
- unsigned int fp_regnum = gdbarch_tdep (gdbarch)->a0_base + 1;
+ xtensa_gdbarch_tdep *tdep = (xtensa_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+ unsigned int fp_regnum = tdep->a0_base + 1;
CORE_ADDR start_addr;
xtensa_isa isa;
xtensa_insnbuf ins, slot;
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);
for (ia = start_addr, bt = ia; ia < current_pc ; ia += ilen)
{
if (ia + xtensa_isa_maxlength (isa) > bt)
- {
+ {
ba = ia;
bt = (ba + XTENSA_ISA_BSZ) < current_pc
? ba + XTENSA_ISA_BSZ : current_pc;
RETURN_FP;
fp_regnum
- = gdbarch_tdep (gdbarch)->a0_base + register_operand;
+ = tdep->a0_base + register_operand;
RETURN_FP;
}
}
int windowed, ps_regnum;
if (*this_cache)
- return *this_cache;
+ return (struct xtensa_frame_cache *) *this_cache;
pc = get_frame_register_unsigned (this_frame, gdbarch_pc_regnum (gdbarch));
ps_regnum = gdbarch_ps_regnum (gdbarch);
if (windowed)
{
- char op1;
+ LONGEST op1;
+ xtensa_gdbarch_tdep *tdep = (xtensa_gdbarch_tdep *) gdbarch_tdep (gdbarch);
/* Get WINDOWBASE, WINDOWSTART, and PS registers. */
wb = get_frame_register_unsigned (this_frame,
- gdbarch_tdep (gdbarch)->wb_regnum);
+ tdep->wb_regnum);
ws = get_frame_register_unsigned (this_frame,
- gdbarch_tdep (gdbarch)->ws_regnum);
+ tdep->ws_regnum);
- op1 = read_memory_integer (pc, 1, byte_order);
- if (XTENSA_IS_ENTRY (gdbarch, op1))
+ if (safe_read_memory_integer (pc, 1, byte_order, &op1)
+ && XTENSA_IS_ENTRY (gdbarch, op1))
{
int callinc = CALLINC (ps);
ra = get_frame_register_unsigned
- (this_frame, gdbarch_tdep (gdbarch)->a0_base + callinc * 4);
+ (this_frame, tdep->a0_base + callinc * 4);
/* ENTRY hasn't been executed yet, therefore callsize is still 0. */
cache->wd.callsize = 0;
cache->wd.wb = wb;
cache->wd.ws = ws;
cache->prev_sp = get_frame_register_unsigned
- (this_frame, gdbarch_tdep (gdbarch)->a0_base + 1);
+ (this_frame, tdep->a0_base + 1);
/* This only can be the outermost frame since we are
just about to execute ENTRY. SP hasn't been set yet.
{
fp_regnum = xtensa_scan_prologue (gdbarch, pc);
ra = get_frame_register_unsigned (this_frame,
- gdbarch_tdep (gdbarch)->a0_base);
+ tdep->a0_base);
cache->wd.callsize = WINSIZE (ra);
cache->wd.wb = (wb - cache->wd.callsize / 4)
- & (gdbarch_tdep (gdbarch)->num_aregs / 4 - 1);
+ & (tdep->num_aregs / 4 - 1);
cache->wd.ws = ws & ~(1 << wb);
cache->pc = get_frame_func (this_frame);
/* Set A0...A3. */
sp = get_frame_register_unsigned
- (this_frame, gdbarch_tdep (gdbarch)->a0_base + 1) - 16;
+ (this_frame, tdep->a0_base + 1) - 16;
for (i = 0; i < 4; i++, sp += 4)
{
{
/* Set A4...A7/A11. */
/* Get the SP of the frame previous to the previous one.
- To achieve this, we have to dereference SP twice. */
+ To achieve this, we have to dereference SP twice. */
sp = (CORE_ADDR) read_memory_integer (sp - 12, 4, byte_order);
sp = (CORE_ADDR) read_memory_integer (sp - 12, 4, byte_order);
sp -= cache->wd.callsize * 4;
if ((cache->wd.ws & (1 << cache->wd.wb)) == 0)
{
/* Register window overflow already happened.
- We can read caller's SP from the proper spill loction. */
+ We can read caller's SP from the proper spill location. */
sp = get_frame_register_unsigned
- (this_frame, gdbarch_tdep (gdbarch)->a0_base + 1);
+ (this_frame, tdep->a0_base + 1);
cache->prev_sp = read_memory_integer (sp - 12, 4, byte_order);
}
else
{
/* Read caller's frame SP directly from the previous window. */
int regnum = arreg_number
- (gdbarch, gdbarch_tdep (gdbarch)->a0_base + 1,
+ (gdbarch, tdep->a0_base + 1,
cache->wd.wb);
cache->prev_sp = xtensa_read_register (regnum);
static int xtensa_session_once_reported = 1;
/* Report a problem with prologue analysis while doing backtracing.
- But, do it only once to avoid annoyng repeated messages. */
+ But, do it only once to avoid annoying repeated messages. */
static void
warning_once (void)
struct xtensa_frame_cache *cache;
ULONGEST saved_reg = 0;
int done = 1;
+ xtensa_gdbarch_tdep *tdep = (xtensa_gdbarch_tdep *) gdbarch_tdep (gdbarch);
if (*this_cache == NULL)
*this_cache = xtensa_frame_cache (this_frame, this_cache);
- cache = *this_cache;
+ cache = (struct xtensa_frame_cache *) *this_cache;
if (regnum ==gdbarch_pc_regnum (gdbarch))
saved_reg = cache->ra;
- else if (regnum == gdbarch_tdep (gdbarch)->a0_base + 1)
+ else if (regnum == tdep->a0_base + 1)
saved_reg = cache->prev_sp;
else if (!cache->call0)
{
- if (regnum == gdbarch_tdep (gdbarch)->ws_regnum)
+ if (regnum == tdep->ws_regnum)
saved_reg = cache->wd.ws;
- else if (regnum == gdbarch_tdep (gdbarch)->wb_regnum)
+ else if (regnum == tdep->wb_regnum)
saved_reg = cache->wd.wb;
else if (regnum == gdbarch_ps_regnum (gdbarch))
saved_reg = cache->ps;
{
/* Convert A-register numbers to AR-register numbers,
if we deal with A-register. */
- if (regnum >= gdbarch_tdep (gdbarch)->a0_base
- && regnum <= gdbarch_tdep (gdbarch)->a0_base + 15)
+ if (regnum >= tdep->a0_base
+ && regnum <= tdep->a0_base + 15)
regnum = arreg_number (gdbarch, regnum, cache->wd.wb);
/* Check, if we deal with AR-register saved on stack. */
- if (regnum >= gdbarch_tdep (gdbarch)->ar_base
- && regnum <= (gdbarch_tdep (gdbarch)->ar_base
- + gdbarch_tdep (gdbarch)->num_aregs))
+ if (regnum >= tdep->ar_base
+ && regnum <= (tdep->ar_base
+ + tdep->num_aregs))
{
int areg = areg_number (gdbarch, regnum, cache->wd.wb);
}
else /* Call0 ABI. */
{
- int reg = (regnum >= gdbarch_tdep (gdbarch)->ar_base
- && regnum <= (gdbarch_tdep (gdbarch)->ar_base
+ int reg = (regnum >= tdep->ar_base
+ && regnum <= (tdep->ar_base
+ C0_NREGS))
- ? regnum - gdbarch_tdep (gdbarch)->ar_base : regnum;
+ ? regnum - tdep->ar_base : regnum;
if (reg < C0_NREGS)
{
static const struct frame_unwind
xtensa_unwind =
{
+ "xtensa prologue",
NORMAL_FRAME,
default_frame_unwind_stop_reason,
xtensa_frame_this_id,
struct regcache *regcache,
void *dst)
{
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
- bfd_byte *valbuf = dst;
+ struct gdbarch *gdbarch = regcache->arch ();
+ bfd_byte *valbuf = (bfd_byte *) dst;
int len = TYPE_LENGTH (type);
ULONGEST pc, wb;
int callsize, areg;
gdb_assert(len > 0);
- if (gdbarch_tdep (gdbarch)->call_abi != CallAbiCall0Only)
+ xtensa_gdbarch_tdep *tdep = (xtensa_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+ if (tdep->call_abi != CallAbiCall0Only)
{
/* First, we have to find the caller window in the register file. */
regcache_raw_read_unsigned (regcache, gdbarch_pc_regnum (gdbarch), &pc);
/* Get the register offset of the return
register (A2) in the caller window. */
regcache_raw_read_unsigned
- (regcache, gdbarch_tdep (gdbarch)->wb_regnum, &wb);
+ (regcache, tdep->wb_regnum, &wb);
areg = arreg_number (gdbarch,
- gdbarch_tdep (gdbarch)->a0_base + 2 + callsize, wb);
+ tdep->a0_base + 2 + callsize, wb);
}
else
{
/* No windowing hardware - Call0 ABI. */
- areg = gdbarch_tdep (gdbarch)->a0_base + C0_ARGS;
+ areg = tdep->a0_base + C0_ARGS;
}
DEBUGINFO ("[xtensa_extract_return_value] areg %d len %d\n", areg, len);
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);
- const bfd_byte *valbuf = dst;
+ struct gdbarch *gdbarch = regcache->arch ();
+ const bfd_byte *valbuf = (const bfd_byte *) dst;
unsigned int areg;
ULONGEST pc, wb;
int callsize;
DEBUGTRACE ("xtensa_store_return_value (...)\n");
- if (gdbarch_tdep (gdbarch)->call_abi != CallAbiCall0Only)
+ xtensa_gdbarch_tdep *tdep = (xtensa_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+ if (tdep->call_abi != CallAbiCall0Only)
{
regcache_raw_read_unsigned
- (regcache, gdbarch_tdep (gdbarch)->wb_regnum, &wb);
+ (regcache, tdep->wb_regnum, &wb);
regcache_raw_read_unsigned (regcache, gdbarch_pc_regnum (gdbarch), &pc);
callsize = extract_call_winsize (gdbarch, pc);
if (len > (callsize > 8 ? 8 : 16))
internal_error (__FILE__, __LINE__,
- _("unimplemented for this length: %d"),
- TYPE_LENGTH (type));
+ _("unimplemented for this length: %s"),
+ pulongest (TYPE_LENGTH (type)));
areg = arreg_number (gdbarch,
- gdbarch_tdep (gdbarch)->a0_base + 2 + callsize, wb);
+ tdep->a0_base + 2 + callsize, wb);
DEBUGTRACE ("[xtensa_store_return_value] callsize %d wb %d\n",
- callsize, (int) wb);
+ callsize, (int) wb);
}
else
{
- areg = gdbarch_tdep (gdbarch)->a0_base + C0_ARGS;
+ areg = tdep->a0_base + C0_ARGS;
}
if (len < 4 && gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
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);
}
}
{
/* Structures up to 16 bytes are returned in registers. */
- int struct_return = ((TYPE_CODE (valtype) == TYPE_CODE_STRUCT
- || TYPE_CODE (valtype) == TYPE_CODE_UNION
- || TYPE_CODE (valtype) == TYPE_CODE_ARRAY)
+ int struct_return = ((valtype->code () == TYPE_CODE_STRUCT
+ || valtype->code () == TYPE_CODE_UNION
+ || valtype->code () == TYPE_CODE_ARRAY)
&& TYPE_LENGTH (valtype) > 16);
if (struct_return)
int nargs,
struct value **args,
CORE_ADDR sp,
- int struct_return,
+ function_call_return_method return_method,
CORE_ADDR struct_addr)
{
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- int i;
+ xtensa_gdbarch_tdep *tdep = (xtensa_gdbarch_tdep *) gdbarch_tdep (gdbarch);
int size, onstack_size;
gdb_byte *buf = (gdb_byte *) alloca (16);
CORE_ADDR ra, ps;
if (xtensa_debug_level > 3)
{
- int i;
DEBUGINFO ("[xtensa_push_dummy_call] nargs = %d\n", nargs);
- DEBUGINFO ("[xtensa_push_dummy_call] sp=0x%x, struct_return=%d, "
+ DEBUGINFO ("[xtensa_push_dummy_call] sp=0x%x, return_method=%d, "
"struct_addr=0x%x\n",
- (int) sp, (int) struct_return, (int) struct_addr);
+ (int) sp, (int) return_method, (int) struct_addr);
- for (i = 0; i < nargs; i++)
- {
+ for (int i = 0; i < nargs; i++)
+ {
struct value *arg = args[i];
struct type *arg_type = check_typedef (value_type (arg));
- fprintf_unfiltered (gdb_stdlog, "%2d: %s %3d ", i,
- host_address_to_string (arg),
- TYPE_LENGTH (arg_type));
- switch (TYPE_CODE (arg_type))
+ gdb_printf (gdb_stdlog, "%2d: %s %3s ", i,
+ host_address_to_string (arg),
+ pulongest (TYPE_LENGTH (arg_type)));
+ switch (arg_type->code ())
{
case TYPE_CODE_INT:
- fprintf_unfiltered (gdb_stdlog, "int");
+ gdb_printf (gdb_stdlog, "int");
break;
case TYPE_CODE_STRUCT:
- fprintf_unfiltered (gdb_stdlog, "struct");
+ gdb_printf (gdb_stdlog, "struct");
break;
default:
- fprintf_unfiltered (gdb_stdlog, "%3d", TYPE_CODE (arg_type));
+ gdb_printf (gdb_stdlog, "%3d", arg_type->code ());
break;
}
- fprintf_unfiltered (gdb_stdlog, " %s\n",
- host_address_to_string (value_contents (arg)));
+ gdb_printf (gdb_stdlog, " %s\n",
+ host_address_to_string (value_contents (arg).data ()));
}
}
size = 0;
onstack_size = 0;
- i = 0;
- if (struct_return)
+ if (return_method == return_method_struct)
size = REGISTER_SIZE;
- for (i = 0; i < nargs; i++)
+ for (int i = 0; i < nargs; i++)
{
struct argument_info *info = &arg_info[i];
struct value *arg = args[i];
struct type *arg_type = check_typedef (value_type (arg));
- switch (TYPE_CODE (arg_type))
+ switch (arg_type->code ())
{
case TYPE_CODE_INT:
case TYPE_CODE_BOOL:
break;
}
info->length = TYPE_LENGTH (arg_type);
- info->contents = value_contents (arg);
+ info->contents = value_contents (arg).data ();
/* Align size and onstack_size. */
size = (size + info->align - 1) & ~(info->align - 1);
onstack_size = (onstack_size + info->align - 1) & ~(info->align - 1);
- if (size + info->length > REGISTER_SIZE * ARG_NOF (gdbarch))
+ if (size + info->length > REGISTER_SIZE * ARG_NOF (tdep))
{
info->onstack = 1;
info->u.offset = onstack_size;
else
{
info->onstack = 0;
- info->u.regno = ARG_1ST (gdbarch) + size / REGISTER_SIZE;
+ info->u.regno = ARG_1ST (tdep) + size / REGISTER_SIZE;
}
size += info->length;
}
sp = align_down (sp - onstack_size, SP_ALIGNMENT);
/* Simulate MOVSP, if Windowed ABI. */
- if ((gdbarch_tdep (gdbarch)->call_abi != CallAbiCall0Only)
+ if ((tdep->call_abi != CallAbiCall0Only)
&& (sp != osp))
{
read_memory (osp - 16, buf, 16);
/* Second Loop: Load arguments. */
- if (struct_return)
+ if (return_method == return_method_struct)
{
store_unsigned_integer (buf, REGISTER_SIZE, byte_order, struct_addr);
- regcache_cooked_write (regcache, ARG_1ST (gdbarch), buf);
+ regcache->cooked_write (ARG_1ST (tdep), buf);
}
- for (i = 0; i < nargs; i++)
+ for (int i = 0; i < nargs; i++)
{
struct argument_info *info = &arg_info[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;
/* Set the return address of dummy frame to the dummy address.
The return address for the current function (in A0) is
- saved in the dummy frame, so we can savely overwrite A0 here. */
+ saved in the dummy frame, so we can safely overwrite A0 here. */
- if (gdbarch_tdep (gdbarch)->call_abi != CallAbiCall0Only)
+ if (tdep->call_abi != CallAbiCall0Only)
{
ULONGEST val;
regcache_raw_read_unsigned (regcache, gdbarch_ps_regnum (gdbarch), &val);
ps = (unsigned long) val & ~0x00030000;
regcache_cooked_write_unsigned
- (regcache, gdbarch_tdep (gdbarch)->a0_base + 4, ra);
+ (regcache, tdep->a0_base + 4, ra);
regcache_cooked_write_unsigned (regcache,
gdbarch_ps_regnum (gdbarch),
ps | 0x00010000);
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 (tdep->wb_regnum, buf);
regcache_cooked_write_unsigned
- (regcache, gdbarch_tdep (gdbarch)->ws_regnum,
+ (regcache, tdep->ws_regnum,
1 << extract_unsigned_integer (buf, 4, byte_order));
}
else
{
/* Simulate CALL0: write RA into A0 register. */
regcache_cooked_write_unsigned
- (regcache, gdbarch_tdep (gdbarch)->a0_base, bp_addr);
+ (regcache, tdep->a0_base, bp_addr);
}
/* Set new stack pointer and return it. */
regcache_cooked_write_unsigned (regcache,
- gdbarch_tdep (gdbarch)->a0_base + 1, sp);
+ tdep->a0_base + 1, sp);
/* Make dummy frame ID unique by adding a constant. */
return sp + SP_ALIGNMENT;
}
+/* Implement the breakpoint_kind_from_pc gdbarch method. */
+
+static int
+xtensa_breakpoint_kind_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr)
+{
+ xtensa_gdbarch_tdep *tdep = (xtensa_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+
+ if (tdep->isa_use_density_instructions)
+ return 2;
+ else
+ return 4;
+}
/* Return a breakpoint for the current location of PC. We always use
the density version if we have density instructions (regardless of the
#define DENSITY_BIG_BREAKPOINT { 0xd2, 0x0f }
#define DENSITY_LITTLE_BREAKPOINT { 0x2d, 0xf0 }
-static const unsigned char *
-xtensa_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *pcptr,
- int *lenptr)
-{
- static unsigned char big_breakpoint[] = BIG_BREAKPOINT;
- static unsigned char little_breakpoint[] = LITTLE_BREAKPOINT;
- static unsigned char density_big_breakpoint[] = DENSITY_BIG_BREAKPOINT;
- static unsigned char density_little_breakpoint[] = DENSITY_LITTLE_BREAKPOINT;
+/* Implement the sw_breakpoint_from_kind gdbarch method. */
- DEBUGTRACE ("xtensa_breakpoint_from_pc (pc = 0x%08x)\n", (int) *pcptr);
+static const gdb_byte *
+xtensa_sw_breakpoint_from_kind (struct gdbarch *gdbarch, int kind, int *size)
+{
+ *size = kind;
- if (gdbarch_tdep (gdbarch)->isa_use_density_instructions)
+ if (kind == 4)
{
+ static unsigned char big_breakpoint[] = BIG_BREAKPOINT;
+ static unsigned char little_breakpoint[] = LITTLE_BREAKPOINT;
+
if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
- {
- *lenptr = sizeof (density_big_breakpoint);
- return density_big_breakpoint;
- }
+ return big_breakpoint;
else
- {
- *lenptr = sizeof (density_little_breakpoint);
- return density_little_breakpoint;
- }
+ return little_breakpoint;
}
else
{
+ static unsigned char density_big_breakpoint[] = DENSITY_BIG_BREAKPOINT;
+ static unsigned char density_little_breakpoint[]
+ = DENSITY_LITTLE_BREAKPOINT;
+
if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
- {
- *lenptr = sizeof (big_breakpoint);
- return big_breakpoint;
- }
+ return density_big_breakpoint;
else
- {
- *lenptr = sizeof (little_breakpoint);
- return little_breakpoint;
- }
+ return density_little_breakpoint;
}
}
for (ia = start_pc, bt = ia; ia < finish_pc ; ia += ilen)
{
if (ia + xtensa_isa_maxlength (isa) > bt)
- {
+ {
ba = ia;
bt = (ba + XTENSA_ISA_BSZ) < finish_pc
? ba + XTENSA_ISA_BSZ : finish_pc;
The purpose of this is to simplify prologue analysis by separating
instruction decoding (libisa) from the semantics of prologue analysis. */
-typedef enum
+enum xtensa_insn_kind
{
c0opc_illegal, /* Unknown to libisa (invalid) or 'ill' opcode. */
c0opc_uninteresting, /* Not interesting for Call0 prologue analysis. */
c0opc_rfwo, /* RFWO instruction. */
c0opc_rfwu, /* RFWU instruction. */
c0opc_NrOf /* Number of opcode classifications. */
-} xtensa_insn_kind;
+};
/* Return true, if OPCNAME is RSR, WRS, or XSR instruction. */
be within a bundle. Updates the destination register tracking info
accordingly. The pc is needed only for pc-relative load instructions
(eg. l32r). The SP register number is needed to identify stores to
- the stack frame. Returns 0, if analysis was succesfull, non-zero
+ the stack frame. Returns 0, if analysis was successful, non-zero
otherwise. */
static int
{
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
unsigned litbase, litaddr, litval;
+ xtensa_gdbarch_tdep *tdep = (xtensa_gdbarch_tdep *) gdbarch_tdep (gdbarch);
switch (opclass)
{
/* 3 operands: dst, src1, src2. */
gdb_assert (nods == 3);
if (src[odv[1]].fr_reg == C0_CONST)
- {
+ {
dst[odv[0]].fr_reg = src[odv[2]].fr_reg;
dst[odv[0]].fr_ofs = src[odv[2]].fr_ofs + src[odv[1]].fr_ofs;
}
else if (src[odv[2]].fr_reg == C0_CONST)
- {
+ {
dst[odv[0]].fr_reg = src[odv[1]].fr_reg;
dst[odv[0]].fr_ofs = src[odv[1]].fr_ofs + src[odv[2]].fr_ofs;
}
/* else fall through. */
}
if (src[odv[1]].fr_reg == C0_CONST)
- {
+ {
dst[odv[0]].fr_reg = src[odv[2]].fr_reg;
dst[odv[0]].fr_ofs = src[odv[2]].fr_ofs & src[odv[1]].fr_ofs;
}
else if (src[odv[2]].fr_reg == C0_CONST)
- {
+ {
dst[odv[0]].fr_reg = src[odv[1]].fr_reg;
dst[odv[0]].fr_ofs = src[odv[1]].fr_ofs & src[odv[2]].fr_ofs;
}
/* 3 operands: dst, src1, src2. */
gdb_assert (nods == 3);
if (src[odv[2]].fr_reg == C0_CONST)
- {
+ {
dst[odv[0]].fr_reg = src[odv[1]].fr_reg;
dst[odv[0]].fr_ofs = src[odv[1]].fr_ofs - src[odv[2]].fr_ofs;
}
/* 2 operands: dst, literal offset. */
gdb_assert (nods == 2);
/* litbase = xtensa_get_litbase (pc); can be also used. */
- litbase = (gdbarch_tdep (gdbarch)->litbase_regnum == -1)
+ litbase = (tdep->litbase_regnum == -1)
? 0 : xtensa_read_register
- (gdbarch_tdep (gdbarch)->litbase_regnum);
+ (tdep->litbase_regnum);
litaddr = litbase & 1
? (litbase & ~1) + (signed)odv[1]
: (pc + 3 + (signed)odv[1]) & ~3;
&& src[odv[0]].fr_reg >= 0 /* Value is from a register. */
&& src[odv[0]].fr_ofs == 0 /* Value hasn't been modified. */
&& src[src[odv[0]].fr_reg].to_stk == C0_NOSTK) /* First time. */
- {
+ {
/* ISA encoding guarantees alignment. But, check it anyway. */
gdb_assert ((odv[2] & 3) == 0);
dst[src[odv[0]].fr_reg].to_stk = src[odv[1]].fr_ofs + odv[2];
arg was not supplied to avoid probing beyond the end of valid memory.
If memory is full of garbage that classifies as c0opc_uninteresting.
If this fails (eg. if no symbols) pc ends up 0 as it was.
- Intialize the Call0 frame and register tracking info.
+ Initialize the Call0 frame and register tracking info.
Assume it's Call0 until an 'entry' instruction is encountered.
Assume we may be in the prologue until we hit a flow control instr. */
body_pc = prologue_sal.end;
/* If we are going to analyze the prologue in general without knowing about
- the current PC, make the best assumtion for the end of the prologue. */
+ the current PC, make the best assumption for the end of the prologue. */
if (pc == 0)
{
find_pc_partial_function (start, 0, NULL, &end_pc);
- body_pc = min (end_pc, body_pc);
+ body_pc = std::min (end_pc, body_pc);
}
else
- body_pc = min (pc, body_pc);
+ body_pc = std::min (pc, body_pc);
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);
for (ia = start, bt = ia; ia < body_pc ; ia += ilen)
{
/* (Re)fill instruction buffer from memory if necessary, but do not
- read memory beyond PC to be sure we stay within text section
+ read memory beyond PC to be sure we stay within text section
(this protection only works if a non-zero pc is supplied). */
if (ia + xtensa_isa_maxlength (isa) > bt)
- {
+ {
ba = ia;
bt = (ba + XTENSA_ISA_BSZ) < body_pc ? ba + XTENSA_ISA_BSZ : body_pc;
if (target_read_memory (ba, ibuf, bt - ba) != 0 )
}
/* Analyze a bundle or a single instruction, using a snapshot of
- the register tracking info as input for the entire bundle so that
+ the register tracking info as input for the entire bundle so that
register changes do not take effect within this bundle. */
for (j = 0; j < nregs; ++j)
rtmp[j] = cache->c0.c0_rt[j];
for (is = 0; is < islots; ++is)
- {
+ {
/* Decode a slot and classify the opcode. */
fail = xtensa_format_get_slot (isa, ifmt, is, ins, slot);
CORE_ADDR body_pc=UINT_MAX; /* PC, where prologue analysis stopped. */
CORE_ADDR sp, fp, ra;
int fp_regnum = C0_SP, c0_hasfp = 0, c0_frmsz = 0, prev_sp = 0, to_stk;
+ xtensa_gdbarch_tdep *tdep = (xtensa_gdbarch_tdep *) gdbarch_tdep (gdbarch);
sp = get_frame_register_unsigned
- (this_frame, gdbarch_tdep (gdbarch)->a0_base + 1);
+ (this_frame, tdep->a0_base + 1);
fp = sp; /* Assume FP == SP until proven otherwise. */
/* Find the beginning of the prologue of the function containing the PC
if (body_pc <= pc)
{
/* Prologue analysis was successful up to the PC.
- It includes the cases when PC == START_PC. */
+ It includes the cases when PC == START_PC. */
c0_hasfp = cache->c0.c0_rt[C0_FP].fr_reg == C0_SP;
/* c0_hasfp == true means there is a frame pointer because
we analyzed the prologue and found that cache->c0.c0_rt[C0_FP]
was derived from SP. Otherwise, it would be C0_FP. */
fp_regnum = c0_hasfp ? C0_FP : C0_SP;
c0_frmsz = - cache->c0.c0_rt[fp_regnum].fr_ofs;
- fp_regnum += gdbarch_tdep (gdbarch)->a0_base;
+ fp_regnum += tdep->a0_base;
}
else /* No data from the prologue analysis. */
{
c0_hasfp = 0;
- fp_regnum = gdbarch_tdep (gdbarch)->a0_base + C0_SP;
+ fp_regnum = tdep->a0_base + C0_SP;
c0_frmsz = 0;
start_pc = pc;
}
if (cache->c0.c0_sp_ofs == C0_NOSTK)
/* Saved unaligned value of SP is kept in a register. */
unaligned_sp = get_frame_register_unsigned
- (this_frame, gdbarch_tdep (gdbarch)->a0_base + cache->c0.c0_old_sp);
+ (this_frame, tdep->a0_base + cache->c0.c0_old_sp);
else
/* Get the value from stack. */
unaligned_sp = (CORE_ADDR)
{
ra = get_frame_register_unsigned
(this_frame,
- gdbarch_tdep (gdbarch)->a0_base + cache->c0.c0_rt[i].fr_reg);
+ tdep->a0_base + cache->c0.c0_rt[i].fr_reg);
}
else ra = 0;
}
static void
execute_l32e (struct gdbarch *gdbarch, int at, int as, int offset, CORE_ADDR wb)
{
- int atreg = arreg_number (gdbarch, gdbarch_tdep (gdbarch)->a0_base + at, wb);
- int asreg = arreg_number (gdbarch, gdbarch_tdep (gdbarch)->a0_base + as, wb);
+ xtensa_gdbarch_tdep *tdep = (xtensa_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+ int atreg = arreg_number (gdbarch, tdep->a0_base + at, wb);
+ int asreg = arreg_number (gdbarch, tdep->a0_base + as, wb);
CORE_ADDR addr = xtensa_read_register (asreg) + offset;
unsigned int spilled_value
= read_memory_unsigned_integer (addr, 4, gdbarch_byte_order (gdbarch));
static void
execute_s32e (struct gdbarch *gdbarch, int at, int as, int offset, CORE_ADDR wb)
{
- int atreg = arreg_number (gdbarch, gdbarch_tdep (gdbarch)->a0_base + at, wb);
- int asreg = arreg_number (gdbarch, gdbarch_tdep (gdbarch)->a0_base + as, wb);
+ xtensa_gdbarch_tdep *tdep = (xtensa_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+ int atreg = arreg_number (gdbarch, tdep->a0_base + at, wb);
+ int asreg = arreg_number (gdbarch, tdep->a0_base + as, wb);
CORE_ADDR addr = xtensa_read_register (asreg) + offset;
ULONGEST spilled_value = xtensa_read_register (atreg);
#define XTENSA_MAX_WINDOW_INTERRUPT_HANDLER_LEN 200
-typedef enum
+enum xtensa_exception_handler_t
{
xtWindowOverflow,
xtWindowUnderflow,
xtNoExceptionHandler
-} xtensa_exception_handler_t;
+};
/* Execute instruction stream from current PC until hitting RFWU or RFWO.
Return type of Xtensa Window Interrupt Handler on success. */
int ilen, islots, is;
xtensa_opcode opc;
int insn_num = 0;
- int fail = 0;
void (*func) (struct gdbarch *, int, int, int, CORE_ADDR);
+ xtensa_gdbarch_tdep *tdep = (xtensa_gdbarch_tdep *) gdbarch_tdep (gdbarch);
uint32_t at, as, offset;
while (insn_num++ < XTENSA_MAX_WINDOW_INTERRUPT_HANDLER_LEN)
{
if (ia + xtensa_isa_maxlength (isa) > bt)
- {
+ {
ba = ia;
bt = (ba + XTENSA_ISA_BSZ);
if (target_read_memory (ba, ibuf, bt - ba) != 0)
if (a0_was_saved)
{
int arreg = arreg_number (gdbarch,
- gdbarch_tdep (gdbarch)->a0_base,
+ tdep->a0_base,
wb);
xtensa_write_register (arreg, a0_saved);
}
if (a11_was_saved)
{
int arreg = arreg_number (gdbarch,
- gdbarch_tdep (gdbarch)->a0_base + 11,
+ tdep->a0_base + 11,
wb);
xtensa_write_register (arreg, a11_saved);
}
else if (a7_was_saved)
{
int arreg = arreg_number (gdbarch,
- gdbarch_tdep (gdbarch)->a0_base + 7,
+ tdep->a0_base + 7,
wb);
xtensa_write_register (arreg, a7_saved);
}
return xtWindowUnderflow;
- default: /* Simply skip this insns. */
+ default: /* Simply skip this insns. */
continue;
}
CORE_ADDR ps, wb, ws, ra;
int epc1_regnum, i, regnum;
xtensa_exception_handler_t eh_type;
+ xtensa_gdbarch_tdep *tdep = (xtensa_gdbarch_tdep *) gdbarch_tdep (gdbarch);
/* Read PS, WB, and WS from the hardware. Note that PS register
must be present, if Windowed ABI is supported. */
ps = xtensa_read_register (gdbarch_ps_regnum (gdbarch));
- wb = xtensa_read_register (gdbarch_tdep (gdbarch)->wb_regnum);
- ws = xtensa_read_register (gdbarch_tdep (gdbarch)->ws_regnum);
+ wb = xtensa_read_register (tdep->wb_regnum);
+ ws = xtensa_read_register (tdep->ws_regnum);
/* Execute all the remaining instructions from Window Interrupt Handler
by simulating them on the remote protocol level. On return, set the
cache->wd.ws = ws | (1 << wb);
cache->wd.wb = (ps & 0xf00) >> 8; /* Set WB to OWB. */
- regnum = arreg_number (gdbarch, gdbarch_tdep (gdbarch)->a0_base,
+ regnum = arreg_number (gdbarch, tdep->a0_base,
cache->wd.wb);
ra = xtensa_read_register (regnum);
cache->wd.callsize = WINSIZE (ra);
/* Set regnum to a frame pointer of the frame being cached. */
regnum = xtensa_scan_prologue (gdbarch, pc);
regnum = arreg_number (gdbarch,
- gdbarch_tdep (gdbarch)->a0_base + regnum,
+ tdep->a0_base + regnum,
cache->wd.wb);
cache->base = get_frame_register_unsigned (this_frame, regnum);
int main()
{ int local_var = 1;
- ....
+ ....
}
because, for this source code, both Xtensa compilers will generate two
CORE_ADDR end_func;
- if ((gdbarch_tdep (gdbarch)->call_abi == CallAbiCall0Only)
+ xtensa_gdbarch_tdep *tdep = (xtensa_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+ if ((tdep->call_abi == CallAbiCall0Only)
&& call0_ret (start_pc, prologue_sal.end))
return start_pc;
static void
xtensa_verify_config (struct gdbarch *gdbarch)
{
- struct ui_file *log;
- struct cleanup *cleanups;
- struct gdbarch_tdep *tdep;
- long length;
- char *buf;
-
- tdep = gdbarch_tdep (gdbarch);
- log = mem_fileopen ();
- cleanups = make_cleanup_ui_file_delete (log);
+ xtensa_gdbarch_tdep *tdep = (xtensa_gdbarch_tdep *) gdbarch_tdep (gdbarch);
+ string_file log;
/* Verify that we got a reasonable number of AREGS. */
if ((tdep->num_aregs & -tdep->num_aregs) != tdep->num_aregs)
- fprintf_unfiltered (log, _("\
+ log.printf (_("\
\n\tnum_aregs: Number of AR registers (%d) is not a power of two!"),
- tdep->num_aregs);
+ tdep->num_aregs);
/* Verify that certain registers exist. */
if (tdep->pc_regnum == -1)
- fprintf_unfiltered (log, _("\n\tpc_regnum: No PC register"));
+ log.printf (_("\n\tpc_regnum: No PC register"));
if (tdep->isa_use_exceptions && tdep->ps_regnum == -1)
- fprintf_unfiltered (log, _("\n\tps_regnum: No PS register"));
+ log.printf (_("\n\tps_regnum: No PS register"));
if (tdep->isa_use_windowed_registers)
{
if (tdep->wb_regnum == -1)
- fprintf_unfiltered (log, _("\n\twb_regnum: No WB register"));
+ log.printf (_("\n\twb_regnum: No WB register"));
if (tdep->ws_regnum == -1)
- fprintf_unfiltered (log, _("\n\tws_regnum: No WS register"));
+ log.printf (_("\n\tws_regnum: No WS register"));
if (tdep->ar_base == -1)
- fprintf_unfiltered (log, _("\n\tar_base: No AR registers"));
+ log.printf (_("\n\tar_base: No AR registers"));
}
if (tdep->a0_base == -1)
- fprintf_unfiltered (log, _("\n\ta0_base: No Ax registers"));
+ log.printf (_("\n\ta0_base: No Ax registers"));
- buf = ui_file_xstrdup (log, &length);
- make_cleanup (xfree, buf);
- if (length > 0)
+ if (!log.empty ())
internal_error (__FILE__, __LINE__,
- _("the following are invalid: %s"), buf);
- do_cleanups (cleanups);
+ _("the following are invalid: %s"), log.c_str ());
}
/* Derive specific register numbers from the array of registers. */
static void
-xtensa_derive_tdep (struct gdbarch_tdep *tdep)
+xtensa_derive_tdep (xtensa_gdbarch_tdep *tdep)
{
xtensa_register_t* rmap;
int n, max_size = 4;
/* 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;
/* Module "constructor" function. */
-extern struct gdbarch_tdep xtensa_tdep;
+extern xtensa_gdbarch_tdep xtensa_tdep;
static struct gdbarch *
xtensa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
- struct gdbarch_tdep *tdep;
struct gdbarch *gdbarch;
- struct xtensa_abi_handler *abi_handler;
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;
- tdep = &xtensa_tdep;
+ xtensa_gdbarch_tdep *tdep = &xtensa_tdep;
gdbarch = gdbarch_alloc (&info, tdep);
xtensa_derive_tdep (tdep);
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);
set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
/* Set breakpoints. */
- set_gdbarch_breakpoint_from_pc (gdbarch, xtensa_breakpoint_from_pc);
+ set_gdbarch_breakpoint_kind_from_pc (gdbarch,
+ xtensa_breakpoint_kind_from_pc);
+ set_gdbarch_sw_breakpoint_from_kind (gdbarch,
+ xtensa_sw_breakpoint_from_kind);
/* After breakpoint instruction or illegal instruction, pc still
points at break instruction, so don't decrement. */
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);
set_solib_svr4_fetch_link_map_offsets
(gdbarch, svr4_ilp32_fetch_link_map_offsets);
+ /* Hook in the ABI-specific overrides, if they have been registered. */
+ gdbarch_init_osabi (info, gdbarch);
+
return 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
-_initialize_xtensa_tdep (void)
+_initialize_xtensa_tdep ()
{
- struct cmd_list_element *c;
-
gdbarch_register (bfd_arch_xtensa, xtensa_gdbarch_init, xtensa_dump_tdep);
xtensa_init_reggroups ();