/* Target-dependent code for the Xtensa port of GDB, the GNU debugger.
- Copyright (C) 2003, 2005, 2006, 2007 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2005, 2006, 2007, 2008, 2009, 2010, 2011
+ Free Software Foundation, Inc.
This file is part of GDB.
#include "defs.h"
#include "frame.h"
+#include "solib-svr4.h"
#include "symtab.h"
#include "symfile.h"
#include "objfiles.h"
#include "regset.h"
#include "dummy-frame.h"
-#include "elf/dwarf2.h"
+#include "dwarf2.h"
#include "dwarf2-frame.h"
#include "dwarf2loc.h"
#include "frame.h"
#include "xtensa-isa.h"
#include "xtensa-tdep.h"
+#include "xtensa-config.h"
static int xtensa_debug_level = 0;
/* On Windowed ABI, we use a6 through a11 for passing arguments
to a function called by GDB because CALL4 is used. */
-#define ARGS_FIRST_REG gdbarch_tdep (current_gdbarch)->a0_base + 6
#define ARGS_NUM_REGS 6
#define REGISTER_SIZE 4
#define CALLINC(ps) (((ps) & PS_CALLINC_MASK) >> PS_CALLINC_SHIFT)
#define WINSIZE(ra) (4 * (( (ra) >> 30) & 0x3))
-
-/* Convert a live Ax register number to the corresponding Areg number. */
-#define AREG_NUMBER(r, wb) \
- ((((r) - (gdbarch_tdep (current_gdbarch)->a0_base + 0) + (((wb) \
- & ((gdbarch_tdep (current_gdbarch)->num_aregs - 1) >> 2)) << WB_SHIFT)) & \
- (gdbarch_tdep (current_gdbarch)->num_aregs - 1)) \
- + gdbarch_tdep (current_gdbarch)->ar_base)
-
/* ABI-independent macros. */
-#define ARG_NOF (gdbarch_tdep (current_gdbarch)->call_abi \
- == CallAbiCall0Only ? C0_NARGS : (ARGS_NUM_REGS))
-#define ARG_1ST (gdbarch_tdep (current_gdbarch)->call_abi \
- == CallAbiCall0Only \
- ? (gdbarch_tdep (current_gdbarch)->a0_base + 0) + C0_ARGS \
- : (ARGS_FIRST_REG))
-
-extern struct gdbarch_tdep *xtensa_config_tdep (struct gdbarch_info *);
-extern int xtensa_config_byte_order (struct gdbarch_info *);
-
+#define ARG_NOF(gdbarch) \
+ (gdbarch_tdep (gdbarch)->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))
/* XTENSA_IS_ENTRY tests whether the first byte of an instruction
indicates that the instruction is an ENTRY instruction. */
-#define XTENSA_IS_ENTRY(op1) \
- ((gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG) \
+#define XTENSA_IS_ENTRY(gdbarch, op1) \
+ ((gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) \
? ((op1) == 0x6c) : ((op1) == 0x36))
#define XTENSA_ENTRY_LENGTH 3
#define PS_WOE (1<<18)
#define PS_EXC (1<<4)
+/* Convert a live A-register number to the corresponding AR-register
+ number. */
+static int
+arreg_number (struct gdbarch *gdbarch, int a_regnum, ULONGEST wb)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ int arreg;
+
+ arreg = a_regnum - tdep->a0_base;
+ arreg += (wb & ((tdep->num_aregs - 1) >> 2)) << WB_SHIFT;
+ arreg &= tdep->num_aregs - 1;
+
+ return arreg + tdep->ar_base;
+}
+
+/* Convert a live AR-register number to the corresponding A-register order
+ number in a range [0..15]. Return -1, if AR_REGNUM is out of WB window. */
+static int
+areg_number (struct gdbarch *gdbarch, int ar_regnum, unsigned int wb)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ int areg;
+
+ areg = ar_regnum - tdep->ar_base;
+ if (areg < 0 || areg >= tdep->num_aregs)
+ return -1;
+ areg = (areg - wb * 4) & (tdep->num_aregs - 1);
+ return (areg > 15) ? -1 : areg;
+}
+
static inline int
windowing_enabled (CORE_ADDR ps)
{
method to call the inferior function. */
static int
-extract_call_winsize (CORE_ADDR pc)
+extract_call_winsize (struct gdbarch *gdbarch, CORE_ADDR pc)
{
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
int winsize = 4;
int insn;
gdb_byte buf[4];
/* Read the previous instruction (should be a call[x]{4|8|12}. */
read_memory (pc-3, buf, 3);
- insn = extract_unsigned_integer (buf, 3);
+ insn = extract_unsigned_integer (buf, 3, byte_order);
/* Decode call instruction:
Little Endian
call{0,4,8,12} 0101 || {00,01,10,11} || OFFSET
callx{0,4,8,12} 0000 || {00,01,10,11} || 11 || OFFSET. */
- if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_LITTLE)
+ if (byte_order == BFD_ENDIAN_LITTLE)
{
if (((insn & 0xf) == 0x5) || ((insn & 0xcf) == 0xc0))
winsize = (insn & 0x30) >> 2; /* 0, 4, 8, 12. */
/* Returns the name of a register. */
static const char *
-xtensa_register_name (int regnum)
+xtensa_register_name (struct gdbarch *gdbarch, int regnum)
{
/* Return the name stored in the register map. */
- if (regnum >= 0 && regnum < gdbarch_num_regs (current_gdbarch)
- + gdbarch_num_pseudo_regs (current_gdbarch))
- return gdbarch_tdep (current_gdbarch)->regmap[regnum].name;
+ if (regnum >= 0 && regnum < gdbarch_num_regs (gdbarch)
+ + gdbarch_num_pseudo_regs (gdbarch))
+ return gdbarch_tdep (gdbarch)->regmap[regnum].name;
internal_error (__FILE__, __LINE__, _("invalid register %d"), regnum);
return 0;
}
-static unsigned long
-xtensa_read_register (int regnum)
-{
- ULONGEST value;
-
- regcache_raw_read_unsigned (get_current_regcache (), regnum, &value);
- return (unsigned long) value;
-}
-
/* Return the type of a register. Create a new type, if necessary. */
-static struct ctype_cache
-{
- struct ctype_cache *next;
- int size;
- struct type *virtual_type;
-} *type_entries = NULL;
-
static struct type *
xtensa_register_type (struct gdbarch *gdbarch, int regnum)
{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
/* Return signed integer for ARx and Ax registers. */
- if ((regnum >= gdbarch_tdep (current_gdbarch)->ar_base
- && regnum < gdbarch_tdep (current_gdbarch)->ar_base
- + gdbarch_tdep (current_gdbarch)->num_aregs)
- || (regnum >= gdbarch_tdep (current_gdbarch)->a0_base
- && regnum < gdbarch_tdep (current_gdbarch)->a0_base + 16))
- return builtin_type_int;
+ if ((regnum >= tdep->ar_base
+ && regnum < tdep->ar_base + tdep->num_aregs)
+ || (regnum >= tdep->a0_base
+ && regnum < tdep->a0_base + 16))
+ return builtin_type (gdbarch)->builtin_int;
- if (regnum == gdbarch_pc_regnum (current_gdbarch)
- || regnum == gdbarch_tdep (current_gdbarch)->a0_base + 1)
- return lookup_pointer_type (builtin_type_void);
+ if (regnum == gdbarch_pc_regnum (gdbarch)
+ || regnum == tdep->a0_base + 1)
+ return builtin_type (gdbarch)->builtin_data_ptr;
/* Return the stored type for all other registers. */
- else if (regnum >= 0 && regnum < gdbarch_num_regs (current_gdbarch)
- + gdbarch_num_pseudo_regs (current_gdbarch))
+ else if (regnum >= 0 && regnum < gdbarch_num_regs (gdbarch)
+ + gdbarch_num_pseudo_regs (gdbarch))
{
- xtensa_register_t* reg = &gdbarch_tdep (current_gdbarch)->regmap[regnum];
+ xtensa_register_t* reg = &tdep->regmap[regnum];
/* Set ctype for this register (only the first time). */
switch (size)
{
case 1:
- reg->ctype = builtin_type_uint8;
+ reg->ctype = builtin_type (gdbarch)->builtin_uint8;
break;
case 2:
- reg->ctype = builtin_type_uint16;
+ reg->ctype = builtin_type (gdbarch)->builtin_uint16;
break;
case 4:
- reg->ctype = builtin_type_uint32;
+ reg->ctype = builtin_type (gdbarch)->builtin_uint32;
break;
case 8:
- reg->ctype = builtin_type_uint64;
+ reg->ctype = builtin_type (gdbarch)->builtin_uint64;
break;
case 16:
- reg->ctype = builtin_type_uint128;
+ reg->ctype = builtin_type (gdbarch)->builtin_uint128;
break;
default:
- for (tp = type_entries; tp != NULL; tp = tp->next)
+ for (tp = tdep->type_entries; tp != NULL; tp = tp->next)
if (tp->size == size)
break;
{
char *name = xmalloc (16);
tp = xmalloc (sizeof (struct ctype_cache));
- tp->next = type_entries;
- type_entries = tp;
+ tp->next = tdep->type_entries;
+ tdep->type_entries = tp;
tp->size = size;
sprintf (name, "int%d", size * 8);
- tp->virtual_type = init_type (TYPE_CODE_INT, size,
- TYPE_FLAG_UNSIGNED, name,
- NULL);
+ tp->virtual_type
+ = arch_integer_type (gdbarch, size * 8, 1, xstrdup (name));
}
reg->ctype = tp->virtual_type;
to n for An. So, we only have to add the base number for A0. */
static int
-xtensa_reg_to_regnum (int regnum)
+xtensa_reg_to_regnum (struct gdbarch *gdbarch, int regnum)
{
int i;
if (regnum >= 0 && regnum < 16)
- return gdbarch_tdep (current_gdbarch)->a0_base + regnum;
+ return gdbarch_tdep (gdbarch)->a0_base + regnum;
for (i = 0;
- i < gdbarch_num_regs (current_gdbarch)
- + gdbarch_num_pseudo_regs (current_gdbarch);
+ i < gdbarch_num_regs (gdbarch) + gdbarch_num_pseudo_regs (gdbarch);
i++)
- if (regnum == gdbarch_tdep (current_gdbarch)->regmap[i].target_number)
+ if (regnum == gdbarch_tdep (gdbarch)->regmap[i].target_number)
return i;
internal_error (__FILE__, __LINE__,
DEBUGTRACE ("xtensa_register_write_masked ()\n");
/* Copy the masked register to host byte-order. */
- if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
+ if (gdbarch_byte_order (get_regcache_arch (regcache)) == BFD_ENDIAN_BIG)
for (i = 0; i < bytesize; i++)
{
mem >>= 8;
ptr = value;
mem = *ptr;
- if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
+ if (gdbarch_byte_order (get_regcache_arch (regcache)) == BFD_ENDIAN_BIG)
for (i = 0; i < bytesize; i++)
{
if ((i & 3) == 0)
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 (regnum));
+ regnum, xtensa_register_name (gdbarch, regnum));
- if (regnum == gdbarch_num_regs (current_gdbarch)
- + gdbarch_num_pseudo_regs (current_gdbarch))
- regnum = gdbarch_tdep (current_gdbarch)->a0_base + 1;
+ if (regnum == gdbarch_num_regs (gdbarch)
+ + gdbarch_num_pseudo_regs (gdbarch) - 1)
+ regnum = gdbarch_tdep (gdbarch)->a0_base + 1;
/* Read aliases a0..a15, if this is a Windowed ABI. */
- if (gdbarch_tdep (current_gdbarch)->isa_use_windowed_registers
- && (regnum >= gdbarch_tdep (current_gdbarch)->a0_base + 0)
- && (regnum <= gdbarch_tdep (current_gdbarch)->a0_base + 15))
+ if (gdbarch_tdep (gdbarch)->isa_use_windowed_registers
+ && (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 (current_gdbarch)->wb_regnum, buf);
- regnum = AREG_NUMBER (regnum, extract_unsigned_integer (buf, 4));
+ regcache_raw_read (regcache, gdbarch_tdep (gdbarch)->wb_regnum, buf);
+ regnum = arreg_number (gdbarch, regnum,
+ extract_unsigned_integer (buf, 4, byte_order));
}
/* We can always read non-pseudo registers. */
- if (regnum >= 0 && regnum < gdbarch_num_regs (current_gdbarch))
+ if (regnum >= 0 && regnum < gdbarch_num_regs (gdbarch))
regcache_raw_read (regcache, 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)
+ {
+ buffer[0] = (gdb_byte)0;
+ buffer[1] = (gdb_byte)0;
+ buffer[2] = (gdb_byte)0;
+ buffer[3] = (gdb_byte)0;
+ }
/* Pseudo registers. */
else if (regnum >= 0
- && regnum < gdbarch_num_regs (current_gdbarch)
- + gdbarch_num_pseudo_regs (current_gdbarch))
+ && regnum < gdbarch_num_regs (gdbarch)
+ + gdbarch_num_pseudo_regs (gdbarch))
{
- xtensa_register_t *reg = &gdbarch_tdep (current_gdbarch)->regmap[regnum];
+ xtensa_register_t *reg = &gdbarch_tdep (gdbarch)->regmap[regnum];
xtensa_register_type_t type = reg->type;
- int flags = gdbarch_tdep (current_gdbarch)->target_flags;
+ int flags = gdbarch_tdep (gdbarch)->target_flags;
/* We cannot read Unknown or Unmapped registers. */
if (type == xtRegisterTypeUnmapped || type == xtRegisterTypeUnknown)
if ((flags & xtTargetFlagsNonVisibleRegs) == 0)
{
warning (_("cannot read register %s"),
- xtensa_register_name (regnum));
+ xtensa_register_name (gdbarch, regnum));
return;
}
}
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 (regnum));
+ regnum, xtensa_register_name (gdbarch, regnum));
- if (regnum == gdbarch_num_regs (current_gdbarch)
- + gdbarch_num_pseudo_regs (current_gdbarch))
- regnum = gdbarch_tdep (current_gdbarch)->a0_base + 1;
+ 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 (current_gdbarch)->isa_use_windowed_registers
- && (regnum >= gdbarch_tdep (current_gdbarch)->a0_base + 0)
- && (regnum <= gdbarch_tdep (current_gdbarch)->a0_base + 15))
+ if (gdbarch_tdep (gdbarch)->isa_use_windowed_registers
+ && (regnum >= gdbarch_tdep (gdbarch)->a0_base)
+ && (regnum <= gdbarch_tdep (gdbarch)->a0_base + 15))
{
gdb_byte *buf = (gdb_byte *) alloca (MAX_REGISTER_SIZE);
unsigned int wb;
regcache_raw_read (regcache,
- gdbarch_tdep (current_gdbarch)->wb_regnum, buf);
- regnum = AREG_NUMBER (regnum, extract_unsigned_integer (buf, 4));
+ gdbarch_tdep (gdbarch)->wb_regnum, buf);
+ regnum = arreg_number (gdbarch, regnum,
+ extract_unsigned_integer (buf, 4, byte_order));
}
/* We can always write 'core' registers.
Note: We might have converted Ax->ARy. */
- if (regnum >= 0 && regnum < gdbarch_num_regs (current_gdbarch))
+ if (regnum >= 0 && regnum < gdbarch_num_regs (gdbarch))
regcache_raw_write (regcache, 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)
+ {
+ return;
+ }
/* Pseudo registers. */
else if (regnum >= 0
- && regnum < gdbarch_num_regs (current_gdbarch)
- + gdbarch_num_pseudo_regs (current_gdbarch))
+ && regnum < gdbarch_num_regs (gdbarch)
+ + gdbarch_num_pseudo_regs (gdbarch))
{
- xtensa_register_t *reg = &gdbarch_tdep (current_gdbarch)->regmap[regnum];
+ xtensa_register_t *reg = &gdbarch_tdep (gdbarch)->regmap[regnum];
xtensa_register_type_t type = reg->type;
- int flags = gdbarch_tdep (current_gdbarch)->target_flags;
+ int flags = gdbarch_tdep (gdbarch)->target_flags;
/* On most targets, we cannot write registers
of type "Unknown" or "Unmapped". */
if ((flags & xtTargetFlagsNonVisibleRegs) == 0)
{
warning (_("cannot write register %s"),
- xtensa_register_name (regnum));
+ xtensa_register_name (gdbarch, regnum));
return;
}
}
int regnum,
struct reggroup *group)
{
- xtensa_register_t* reg = &gdbarch_tdep (current_gdbarch)->regmap[regnum];
+ xtensa_register_t* reg = &gdbarch_tdep (gdbarch)->regmap[regnum];
xtensa_register_type_t type = reg->type;
xtensa_register_group_t rg = reg->group;
int cp_number;
if (group == vector_reggroup || group == xtensa_vectra_reggroup)
return rg & xtRegisterGroupVectra;
if (group == save_reggroup || group == restore_reggroup)
- return (regnum < gdbarch_num_regs (current_gdbarch)
+ return (regnum < gdbarch_num_regs (gdbarch)
&& (reg->flags & SAVE_REST_FLAGS) == SAVE_REST_VALID);
if ((cp_number = xtensa_coprocessor_register_group (group)) >= 0)
return rg & (xtRegisterGroupCP0 << cp_number);
size_t len)
{
const xtensa_elf_gregset_t *regs = gregs;
+ struct gdbarch *gdbarch = get_regcache_arch (rc);
int i;
- DEBUGTRACE ("xtensa_supply_gregset (..., regnum==%d, ...) \n", regnum);
-
- if (regnum == gdbarch_pc_regnum (current_gdbarch) || regnum == -1)
- regcache_raw_supply (rc,
- gdbarch_pc_regnum (current_gdbarch),
- (char *) ®s->pc);
- if (regnum == gdbarch_ps_regnum (current_gdbarch) || regnum == -1)
- regcache_raw_supply (rc, gdbarch_ps_regnum (current_gdbarch),
- (char *) ®s->ps);
- if (regnum == gdbarch_tdep (current_gdbarch)->wb_regnum || regnum == -1)
- regcache_raw_supply (rc, gdbarch_tdep (current_gdbarch)->wb_regnum,
+ 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);
+ 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 (current_gdbarch)->ws_regnum || regnum == -1)
- regcache_raw_supply (rc, gdbarch_tdep (current_gdbarch)->ws_regnum,
+ 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 (current_gdbarch)->lbeg_regnum || regnum == -1)
- regcache_raw_supply (rc, gdbarch_tdep (current_gdbarch)->lbeg_regnum,
+ 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 (current_gdbarch)->lend_regnum || regnum == -1)
- regcache_raw_supply (rc, gdbarch_tdep (current_gdbarch)->lend_regnum,
+ 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 (current_gdbarch)->lcount_regnum || regnum == -1)
- regcache_raw_supply (rc, gdbarch_tdep (current_gdbarch)->lcount_regnum,
+ 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 (current_gdbarch)->sar_regnum || regnum == -1)
- regcache_raw_supply (rc, gdbarch_tdep (current_gdbarch)->sar_regnum,
+ 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 (current_gdbarch)->exccause_regnum
- || regnum == -1)
- regcache_raw_supply (rc, gdbarch_tdep (current_gdbarch)->exccause_regnum,
- (char *) ®s->exccause);
- if (regnum == gdbarch_tdep (current_gdbarch)->excvaddr_regnum || regnum == -1)
- regcache_raw_supply (rc, gdbarch_tdep (current_gdbarch)->excvaddr_regnum,
- (char *) ®s->excvaddr);
- if (regnum >=gdbarch_tdep (current_gdbarch)->ar_base
- && regnum < gdbarch_tdep (current_gdbarch)->ar_base
- + gdbarch_tdep (current_gdbarch)->num_aregs)
+ 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
- (current_gdbarch)->ar_base]);
+ (gdbarch)->ar_base]);
else if (regnum == -1)
{
- for (i = 0; i < gdbarch_tdep (current_gdbarch)->num_aregs; ++i)
- regcache_raw_supply (rc, gdbarch_tdep (current_gdbarch)->ar_base + i,
+ for (i = 0; i < gdbarch_tdep (gdbarch)->num_aregs; ++i)
+ regcache_raw_supply (rc, gdbarch_tdep (gdbarch)->ar_base + i,
(char *) ®s->ar[i]);
}
}
size_t sect_size)
{
DEBUGTRACE ("xtensa_regset_from_core_section "
- "(..., sect_name==\"%s\", sect_size==%x) \n",
- sect_name, sect_size);
+ "(..., sect_name==\"%s\", sect_size==%x)\n",
+ sect_name, (unsigned int) sect_size);
if (strcmp (sect_name, ".reg") == 0
&& sect_size >= sizeof(xtensa_elf_gregset_t))
/* Frame cache part for Windowed ABI. */
typedef struct xtensa_windowed_frame_cache
{
- int wb; /* Base for this frame; -1 if not in regfile. */
- int callsize; /* Call size to next frame. */
- int ws;
+ int wb; /* WINDOWBASE of the previous frame. */
+ int callsize; /* Call size of this frame. */
+ int ws; /* WINDOWSTART of the previous frame. It
+ keeps track of life windows only. If there
+ is no bit set for the window, that means it
+ had been already spilled because of window
+ overflow. */
+
+ /* Spilled A-registers from the previous frame.
+ AREGS[i] == -1, if corresponding AR is alive. */
CORE_ADDR aregs[XTENSA_NUM_SAVED_AREGS];
} xtensa_windowed_frame_cache_t;
/* Call0 ABI Definitions. */
-#define C0_MAXOPDS 3 /* Maximum number of operands for prologue analysis. */
+#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. */
int fr_reg; /* original register from which register content
is derived, or C0_CONST, or C0_INEXP. */
int fr_ofs; /* constant offset from reg, or immediate value. */
- int to_stk; /* offset from original SP to register (4-byte aligned),
- or C0_NOSTK if register has not been saved. */
+ int to_stk; /* offset from original SP to register (4-byte
+ aligned), or C0_NOSTK if register has not
+ been saved. */
} xtensa_c0reg_t;
typedef struct xtensa_call0_frame_cache
{
int c0_frmsz; /* Stack frame size. */
- int c0_hasfp; /* Current frame uses frame pointer. */
+ int c0_hasfp; /* Current frame uses frame
+ pointer. */
int fp_regnum; /* A-register used as FP. */
int c0_fp; /* Actual value of frame pointer. */
xtensa_c0reg_t c0_rt[C0_NREGS]; /* Register tracking information. */
typedef struct xtensa_frame_cache
{
- CORE_ADDR base; /* Stack pointer of the next frame. */
+ CORE_ADDR base; /* Stack pointer of this frame. */
CORE_ADDR pc; /* PC at the entry point to the function. */
- CORE_ADDR ra; /* The raw return address. */
- CORE_ADDR ps; /* The PS register of the frame. */
- CORE_ADDR prev_sp; /* Stack Pointer of the frame. */
+ CORE_ADDR ra; /* The raw return address (without CALLINC). */
+ CORE_ADDR ps; /* The PS register of this frame. */
+ CORE_ADDR prev_sp; /* Stack Pointer of the previous frame. */
int call0; /* It's a call0 framework (else windowed). */
union
{
else
{
cache->wd.wb = 0;
+ cache->wd.ws = 0;
cache->wd.callsize = -1;
for (i = 0; i < XTENSA_NUM_SAVED_AREGS; i++)
xtensa_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
{
gdb_byte buf[8];
+ CORE_ADDR pc;
- DEBUGTRACE ("xtensa_unwind_pc (next_frame = %p)\n", next_frame);
+ DEBUGTRACE ("xtensa_unwind_pc (next_frame = %s)\n",
+ host_address_to_string (next_frame));
- frame_unwind_register (next_frame, gdbarch_pc_regnum (current_gdbarch), buf);
+ frame_unwind_register (next_frame, gdbarch_pc_regnum (gdbarch), buf);
+ pc = extract_typed_address (buf, builtin_type (gdbarch)->builtin_func_ptr);
- DEBUGINFO ("[xtensa_unwind_pc] pc = 0x%08x\n", (unsigned int)
- extract_typed_address (buf, builtin_type_void_func_ptr));
+ DEBUGINFO ("[xtensa_unwind_pc] pc = 0x%08x\n", (unsigned int) pc);
- return extract_typed_address (buf, builtin_type_void_func_ptr);
+ return pc;
}
static struct frame_id
-xtensa_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
+xtensa_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
{
CORE_ADDR pc, fp;
- /* next_frame->prev is a dummy frame. Return a frame ID of that frame. */
+ /* THIS-FRAME is a dummy frame. Return a frame ID of that frame. */
- DEBUGTRACE ("xtensa_unwind_dummy_id ()\n");
-
- pc = frame_pc_unwind (next_frame);
- fp = frame_unwind_register_unsigned
- (next_frame, gdbarch_tdep (current_gdbarch)->a0_base + 1);
+ pc = get_frame_pc (this_frame);
+ fp = get_frame_register_unsigned
+ (this_frame, gdbarch_tdep (gdbarch)->a0_base + 1);
/* Make dummy frame ID unique by adding a constant. */
return frame_id_build (fp + SP_ALIGNMENT, pc);
}
+/* Returns the best guess about which register is a frame pointer
+ for the function containing CURRENT_PC. */
+
+#define XTENSA_ISA_BSZ 32 /* Instruction buffer size. */
+#define XTENSA_ISA_BADPC ((CORE_ADDR)0) /* Bad PC value. */
+
+static unsigned int
+xtensa_scan_prologue (struct gdbarch *gdbarch, CORE_ADDR current_pc)
+{
+#define RETURN_FP goto done
+
+ unsigned int fp_regnum = gdbarch_tdep (gdbarch)->a0_base + 1;
+ CORE_ADDR start_addr;
+ xtensa_isa isa;
+ xtensa_insnbuf ins, slot;
+ char ibuf[XTENSA_ISA_BSZ];
+ CORE_ADDR ia, bt, ba;
+ xtensa_format ifmt;
+ int ilen, islots, is;
+ xtensa_opcode opc;
+ const char *opcname;
+
+ find_pc_partial_function (current_pc, NULL, &start_addr, NULL);
+ 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);
+ slot = xtensa_insnbuf_alloc (isa);
+ ba = 0;
+
+ 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;
+ if (target_read_memory (ba, ibuf, bt - ba) != 0)
+ RETURN_FP;
+ }
+
+ xtensa_insnbuf_from_chars (isa, ins, &ibuf[ia-ba], 0);
+ ifmt = xtensa_format_decode (isa, ins);
+ if (ifmt == XTENSA_UNDEFINED)
+ RETURN_FP;
+ ilen = xtensa_format_length (isa, ifmt);
+ if (ilen == XTENSA_UNDEFINED)
+ RETURN_FP;
+ islots = xtensa_format_num_slots (isa, ifmt);
+ if (islots == XTENSA_UNDEFINED)
+ RETURN_FP;
+
+ for (is = 0; is < islots; ++is)
+ {
+ if (xtensa_format_get_slot (isa, ifmt, is, ins, slot))
+ RETURN_FP;
+
+ opc = xtensa_opcode_decode (isa, ifmt, is, slot);
+ if (opc == XTENSA_UNDEFINED)
+ RETURN_FP;
+
+ opcname = xtensa_opcode_name (isa, opc);
+
+ if (strcasecmp (opcname, "mov.n") == 0
+ || strcasecmp (opcname, "or") == 0)
+ {
+ unsigned int register_operand;
+
+ /* Possible candidate for setting frame pointer
+ from A1. This is what we are looking for. */
+
+ if (xtensa_operand_get_field (isa, opc, 1, ifmt,
+ is, slot, ®ister_operand) != 0)
+ RETURN_FP;
+ if (xtensa_operand_decode (isa, opc, 1, ®ister_operand) != 0)
+ RETURN_FP;
+ if (register_operand == 1) /* Mov{.n} FP A1. */
+ {
+ if (xtensa_operand_get_field (isa, opc, 0, ifmt, is, slot,
+ ®ister_operand) != 0)
+ RETURN_FP;
+ if (xtensa_operand_decode (isa, opc, 0,
+ ®ister_operand) != 0)
+ RETURN_FP;
+
+ fp_regnum
+ = gdbarch_tdep (gdbarch)->a0_base + register_operand;
+ RETURN_FP;
+ }
+ }
+
+ if (
+ /* We have problems decoding the memory. */
+ opcname == NULL
+ || strcasecmp (opcname, "ill") == 0
+ || strcasecmp (opcname, "ill.n") == 0
+ /* Hit planted breakpoint. */
+ || strcasecmp (opcname, "break") == 0
+ || strcasecmp (opcname, "break.n") == 0
+ /* Flow control instructions finish prologue. */
+ || xtensa_opcode_is_branch (isa, opc) > 0
+ || xtensa_opcode_is_jump (isa, opc) > 0
+ || xtensa_opcode_is_loop (isa, opc) > 0
+ || xtensa_opcode_is_call (isa, opc) > 0
+ || strcasecmp (opcname, "simcall") == 0
+ || strcasecmp (opcname, "syscall") == 0)
+ /* Can not continue analysis. */
+ RETURN_FP;
+ }
+ }
+done:
+ xtensa_insnbuf_free(isa, slot);
+ xtensa_insnbuf_free(isa, ins);
+ return fp_regnum;
+}
+
/* The key values to identify the frame using "cache" are
- cache->base = SP of this frame;
+ cache->base = SP (or best guess about FP) of this frame;
cache->pc = entry-PC (entry point of the frame function);
- cache->prev_sp = SP of the previous frame.
-*/
+ cache->prev_sp = SP of the previous frame. */
static void
-call0_frame_cache (struct frame_info *next_frame,
+call0_frame_cache (struct frame_info *this_frame,
xtensa_frame_cache_t *cache,
- CORE_ADDR pc);
+ CORE_ADDR pc, CORE_ADDR litbase);
static struct xtensa_frame_cache *
-xtensa_frame_cache (struct frame_info *next_frame, void **this_cache)
+xtensa_frame_cache (struct frame_info *this_frame, void **this_cache)
{
xtensa_frame_cache_t *cache;
CORE_ADDR ra, wb, ws, pc, sp, ps;
- unsigned int ps_regnum = gdbarch_ps_regnum (current_gdbarch);
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ unsigned int fp_regnum;
char op1;
int windowed;
- DEBUGTRACE ("xtensa_frame_cache (next_frame %p, *this_cache %p)\n",
- next_frame, this_cache ? *this_cache : (void*)0xdeadbeef);
-
if (*this_cache)
return *this_cache;
- windowed = windowing_enabled (xtensa_read_register (ps_regnum));
+ ps = get_frame_register_unsigned (this_frame, gdbarch_ps_regnum (gdbarch));
+ windowed = windowing_enabled (ps);
/* Get pristine xtensa-frame. */
cache = xtensa_alloc_frame_cache (windowed);
*this_cache = cache;
- pc = frame_unwind_register_unsigned (next_frame,
- gdbarch_pc_regnum (current_gdbarch));
+ pc = get_frame_register_unsigned (this_frame, gdbarch_pc_regnum (gdbarch));
if (windowed)
{
/* Get WINDOWBASE, WINDOWSTART, and PS registers. */
- wb = frame_unwind_register_unsigned
- (next_frame, gdbarch_tdep (current_gdbarch)->wb_regnum);
- ws = frame_unwind_register_unsigned
- (next_frame, gdbarch_tdep (current_gdbarch)->ws_regnum);
- ps = frame_unwind_register_unsigned (next_frame, ps_regnum);
-
- op1 = read_memory_integer (pc, 1);
- if (XTENSA_IS_ENTRY (op1))
+ wb = get_frame_register_unsigned (this_frame,
+ gdbarch_tdep (gdbarch)->wb_regnum);
+ ws = get_frame_register_unsigned (this_frame,
+ gdbarch_tdep (gdbarch)->ws_regnum);
+
+ op1 = read_memory_integer (pc, 1, byte_order);
+ if (XTENSA_IS_ENTRY (gdbarch, op1))
{
int callinc = CALLINC (ps);
- ra = frame_unwind_register_unsigned
- (next_frame,
- gdbarch_tdep (current_gdbarch)->a0_base + 0 + callinc * 4);
-
- DEBUGINFO("[xtensa_frame_cache] 'entry' at 0x%08x\n (callinc = %d)",
- (int)pc, callinc);
+ ra = get_frame_register_unsigned
+ (this_frame, gdbarch_tdep (gdbarch)->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 = frame_unwind_register_unsigned
- (next_frame, gdbarch_tdep
- (current_gdbarch)->a0_base + 1);
+ cache->prev_sp = get_frame_register_unsigned
+ (this_frame, gdbarch_tdep (gdbarch)->a0_base + 1);
+
+ /* This only can be the outermost frame since we are
+ just about to execute ENTRY. SP hasn't been set yet.
+ We can assume any frame size, because it does not
+ matter, and, let's fake frame base in cache. */
+ cache->base = cache->prev_sp + 16;
+
+ cache->pc = pc;
+ cache->ra = (cache->pc & 0xc0000000) | (ra & 0x3fffffff);
+ cache->ps = (ps & ~PS_CALLINC_MASK)
+ | ((WINSIZE(ra)/4) << PS_CALLINC_SHIFT);
+
+ return cache;
}
else
{
- ra = frame_unwind_register_unsigned
- (next_frame, gdbarch_tdep (current_gdbarch)->a0_base + 0);
+ fp_regnum = xtensa_scan_prologue (gdbarch, pc);
+ ra = get_frame_register_unsigned (this_frame,
+ gdbarch_tdep (gdbarch)->a0_base);
cache->wd.callsize = WINSIZE (ra);
cache->wd.wb = (wb - cache->wd.callsize / 4)
- & (gdbarch_tdep (current_gdbarch)->num_aregs / 4 - 1);
+ & (gdbarch_tdep (gdbarch)->num_aregs / 4 - 1);
cache->wd.ws = ws & ~(1 << wb);
- }
- cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME);
- cache->ra = (cache->pc & 0xc0000000) | (ra & 0x3fffffff);
- cache->ps = (ps & ~PS_CALLINC_MASK)
- | ((WINSIZE(ra)/4) << PS_CALLINC_SHIFT);
+ cache->pc = get_frame_func (this_frame);
+ cache->ra = (pc & 0xc0000000) | (ra & 0x3fffffff);
+ cache->ps = (ps & ~PS_CALLINC_MASK)
+ | ((WINSIZE(ra)/4) << PS_CALLINC_SHIFT);
+ }
if (cache->wd.ws == 0)
{
int i;
/* Set A0...A3. */
- sp = frame_unwind_register_unsigned
- (next_frame, gdbarch_tdep (current_gdbarch)->a0_base + 1) - 16;
+ sp = get_frame_register_unsigned
+ (this_frame, gdbarch_tdep (gdbarch)->a0_base + 1) - 16;
for (i = 0; i < 4; i++, sp += 4)
{
if (cache->wd.callsize > 4)
{
/* Set A4...A7/A11. */
- /* Read an SP of the previous frame. */
- sp = (CORE_ADDR) read_memory_integer (sp - 12, 4);
+ /* Get the SP of the frame previous to the previous one.
+ 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;
- for ( /* i=4 */ ; i < cache->wd.callsize; i++, sp += 4)
+ for ( i = 4; i < cache->wd.callsize; i++, sp += 4)
{
cache->wd.aregs[i] = sp;
}
}
if ((cache->prev_sp == 0) && ( ra != 0 ))
- /* If RA is equal to 0 this frame is an outermost frame. Leave
- cache->prev_sp unchanged marking the boundary of the frame stack. */
+ /* If RA is equal to 0 this frame is an outermost frame.
+ Leave cache->prev_sp unchanged marking the boundary of the
+ frame stack. */
{
- if (cache->wd.ws == 0)
+ 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. */
- cache->prev_sp =
- read_memory_integer (cache->wd.aregs[1],
- register_size (current_gdbarch,
- gdbarch_tdep (current_gdbarch)->a0_base
- + 1));
+ sp = get_frame_register_unsigned
+ (this_frame, gdbarch_tdep (gdbarch)->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 = AREG_NUMBER
- (gdbarch_tdep (current_gdbarch)->a0_base + 1,
+ int regnum = arreg_number
+ (gdbarch, gdbarch_tdep (gdbarch)->a0_base + 1,
cache->wd.wb);
- cache->prev_sp = xtensa_read_register (regnum);
+ cache->prev_sp = get_frame_register_unsigned (this_frame,
+ regnum);
}
}
}
else /* Call0 framework. */
{
- call0_frame_cache (next_frame, cache, pc);
+ unsigned int litbase_regnum = gdbarch_tdep (gdbarch)->litbase_regnum;
+ CORE_ADDR litbase = (litbase_regnum == -1)
+ ? 0 : get_frame_register_unsigned (this_frame, litbase_regnum);
+
+ call0_frame_cache (this_frame, cache, pc, litbase);
+ fp_regnum = cache->c0.fp_regnum;
}
- cache->base = frame_unwind_register_unsigned
- (next_frame, gdbarch_tdep (current_gdbarch)->a0_base + 1);
+ cache->base = get_frame_register_unsigned (this_frame, fp_regnum);
return cache;
}
static void
-xtensa_frame_this_id (struct frame_info *next_frame,
+xtensa_frame_this_id (struct frame_info *this_frame,
void **this_cache,
struct frame_id *this_id)
{
struct xtensa_frame_cache *cache =
- xtensa_frame_cache (next_frame, this_cache);
- struct frame_id id;
-
- DEBUGTRACE ("xtensa_frame_this_id (next 0x%08x, *this 0x%08x)\n",
- (unsigned int) next_frame, (unsigned int) *this_cache);
+ xtensa_frame_cache (this_frame, this_cache);
if (cache->prev_sp == 0)
return;
- id = frame_id_build (cache->prev_sp, cache->pc);
- if (frame_id_eq (id, get_frame_id(next_frame)))
- {
- warning(_("\
-Frame stack is corrupted. That could happen because of \
-setting register(s) from GDB or stopping execution \
-inside exception handler. Frame backtracing has stopped. \
-It can make some GDB commands work inappropriately.\n"));
- cache->prev_sp = 0;
- return;
- }
- (*this_id) = id;
-}
-
-static int
-call0_frame_get_reg_at_entry (struct frame_info *next_frame,
- struct xtensa_frame_cache *cache,
- int regnum,
- CORE_ADDR *addrp,
- enum lval_type *lval,
- gdb_byte *valuep)
-{
- CORE_ADDR fp, spe;
- int stkofs;
- int reg = (regnum >= gdbarch_tdep (current_gdbarch)->ar_base
- && regnum <= (gdbarch_tdep (current_gdbarch)->ar_base + C0_NREGS))
- ? regnum - gdbarch_tdep (current_gdbarch)->ar_base : regnum;
-
- /* Determine stack pointer on entry to this function, based on FP. */
- spe = cache->c0.c0_fp - cache->c0.c0_rt[cache->c0.fp_regnum].fr_ofs;
-
- /* If register was saved to the stack frame in the prologue, retrieve it. */
- stkofs = cache->c0.c0_rt[reg].to_stk;
- if (stkofs != C0_NOSTK)
- {
- *lval = lval_memory;
- *addrp = spe + stkofs;
-
- if (valuep)
- read_memory (*addrp, valuep, register_size (current_gdbarch, regnum));
-
- return 1;
- }
-
- /* If not callee-saved or if known to have been overwritten, give up. */
- if (reg < C0_CLESV
- || cache->c0.c0_rt[reg].fr_reg != reg
- || cache->c0.c0_rt[reg].fr_ofs != 0)
- return 0;
-
- if (get_frame_type (next_frame) != NORMAL_FRAME)
- /* TODO: Do we need a special case for DUMMY_FRAME here? */
- return 0;
-
- return call0_frame_get_reg_at_entry (get_next_frame(next_frame),
- cache, regnum, addrp, lval, valuep);
+ (*this_id) = frame_id_build (cache->prev_sp, cache->pc);
}
-static void
-xtensa_frame_prev_register (struct frame_info *next_frame,
+static struct value *
+xtensa_frame_prev_register (struct frame_info *this_frame,
void **this_cache,
- int regnum,
- int *optimizedp,
- enum lval_type *lvalp,
- CORE_ADDR *addrp,
- int *realnump,
- gdb_byte *valuep)
+ int regnum)
{
- struct xtensa_frame_cache *cache =
- xtensa_frame_cache (next_frame, this_cache);
- CORE_ADDR saved_reg = 0;
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
+ struct xtensa_frame_cache *cache;
+ ULONGEST saved_reg = 0;
int done = 1;
- DEBUGTRACE ("xtensa_frame_prev_register (next 0x%08x, "
- "*this 0x%08x, regnum %d (%s), ...)\n",
- (unsigned int) next_frame,
- *this_cache ? (unsigned int) *this_cache : 0, regnum,
- xtensa_register_name (regnum));
+ if (*this_cache == NULL)
+ *this_cache = xtensa_frame_cache (this_frame, this_cache);
+ cache = *this_cache;
- if (regnum ==gdbarch_pc_regnum (current_gdbarch))
+ if (regnum ==gdbarch_pc_regnum (gdbarch))
saved_reg = cache->ra;
- else if (regnum == gdbarch_tdep (current_gdbarch)->a0_base + 1)
+ else if (regnum == gdbarch_tdep (gdbarch)->a0_base + 1)
saved_reg = cache->prev_sp;
else if (!cache->call0)
{
- if (regnum == gdbarch_tdep (current_gdbarch)->ws_regnum)
- {
- if (cache->wd.ws != 0)
- saved_reg = cache->wd.ws;
- else
- saved_reg = 1 << cache->wd.wb;
- }
- else if (regnum == gdbarch_tdep (current_gdbarch)->wb_regnum)
+ if (regnum == gdbarch_tdep (gdbarch)->ws_regnum)
+ saved_reg = cache->wd.ws;
+ else if (regnum == gdbarch_tdep (gdbarch)->wb_regnum)
saved_reg = cache->wd.wb;
- else if (regnum == gdbarch_ps_regnum (current_gdbarch))
+ else if (regnum == gdbarch_ps_regnum (gdbarch))
saved_reg = cache->ps;
else
done = 0;
done = 0;
if (done)
- {
- *optimizedp = 0;
- *lvalp = not_lval;
- *addrp = 0;
- *realnump = -1;
- if (valuep)
- store_unsigned_integer (valuep, 4, saved_reg);
-
- return;
- }
+ return frame_unwind_got_constant (this_frame, regnum, saved_reg);
if (!cache->call0) /* Windowed ABI. */
{
- /* Convert A-register numbers to AR-register numbers. */
- if (regnum >= gdbarch_tdep (current_gdbarch)->a0_base + 0
- && regnum <= gdbarch_tdep (current_gdbarch)->a0_base + 15)
- regnum = AREG_NUMBER (regnum, cache->wd.wb);
-
- /* Check if AR-register has been saved to stack. */
- if (regnum >= gdbarch_tdep (current_gdbarch)->ar_base
- && regnum <= (gdbarch_tdep (current_gdbarch)->ar_base
- + gdbarch_tdep (current_gdbarch)->num_aregs))
+ /* 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)
+ 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))
{
- int areg = regnum - gdbarch_tdep (current_gdbarch)->ar_base
- - (cache->wd.wb * 4);
+ int areg = areg_number (gdbarch, regnum, cache->wd.wb);
if (areg >= 0
&& areg < XTENSA_NUM_SAVED_AREGS
&& cache->wd.aregs[areg] != -1)
- {
- *optimizedp = 0;
- *lvalp = lval_memory;
- *addrp = cache->wd.aregs[areg];
- *realnump = -1;
-
- if (valuep)
- read_memory (*addrp, valuep,
- register_size (current_gdbarch, regnum));
-
- DEBUGINFO ("[xtensa_frame_prev_register] register on stack\n");
- return;
- }
+ return frame_unwind_got_memory (this_frame, regnum,
+ cache->wd.aregs[areg]);
}
}
else /* Call0 ABI. */
{
- int reg = (regnum >= gdbarch_tdep (current_gdbarch)->ar_base
- && regnum <= (gdbarch_tdep (current_gdbarch)->ar_base
+ int reg = (regnum >= gdbarch_tdep (gdbarch)->ar_base
+ && regnum <= (gdbarch_tdep (gdbarch)->ar_base
+ C0_NREGS))
- ? regnum - gdbarch_tdep (current_gdbarch)->ar_base : regnum;
+ ? regnum - gdbarch_tdep (gdbarch)->ar_base : regnum;
if (reg < C0_NREGS)
{
/* Determine SP on entry based on FP. */
spe = cache->c0.c0_fp
- cache->c0.c0_rt[cache->c0.fp_regnum].fr_ofs;
- *optimizedp = 0;
- *lvalp = lval_memory;
- *addrp = spe + stkofs;
- *realnump = -1;
-
- if (valuep)
- read_memory (*addrp, valuep,
- register_size (current_gdbarch, regnum));
-
- DEBUGINFO ("[xtensa_frame_prev_register] register on stack\n");
- return;
+
+ return frame_unwind_got_memory (this_frame, regnum,
+ spe + stkofs);
}
}
}
/* All other registers have been either saved to
the stack or are still alive in the processor. */
- *optimizedp = 0;
- *lvalp = lval_register;
- *addrp = 0;
- *realnump = regnum;
- if (valuep)
- frame_unwind_register (next_frame, (*realnump), valuep);
+ return frame_unwind_got_register (this_frame, regnum, regnum);
}
static const struct frame_unwind
-xtensa_frame_unwind =
+xtensa_unwind =
{
NORMAL_FRAME,
xtensa_frame_this_id,
- xtensa_frame_prev_register
+ xtensa_frame_prev_register,
+ NULL,
+ default_frame_sniffer
};
-static const struct frame_unwind *
-xtensa_frame_sniffer (struct frame_info *next_frame)
-{
- return &xtensa_frame_unwind;
-}
-
static CORE_ADDR
-xtensa_frame_base_address (struct frame_info *next_frame, void **this_cache)
+xtensa_frame_base_address (struct frame_info *this_frame, void **this_cache)
{
struct xtensa_frame_cache *cache =
- xtensa_frame_cache (next_frame, this_cache);
+ xtensa_frame_cache (this_frame, this_cache);
return cache->base;
}
static const struct frame_base
xtensa_frame_base =
{
- &xtensa_frame_unwind,
+ &xtensa_unwind,
xtensa_frame_base_address,
xtensa_frame_base_address,
xtensa_frame_base_address
struct regcache *regcache,
void *dst)
{
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
bfd_byte *valbuf = dst;
int len = TYPE_LENGTH (type);
ULONGEST pc, wb;
gdb_assert(len > 0);
- if (gdbarch_tdep (current_gdbarch)->call_abi != CallAbiCall0Only)
+ if (gdbarch_tdep (gdbarch)->call_abi != CallAbiCall0Only)
{
/* First, we have to find the caller window in the register file. */
- regcache_raw_read_unsigned (regcache,
- gdbarch_pc_regnum (current_gdbarch), &pc);
- callsize = extract_call_winsize (pc);
+ regcache_raw_read_unsigned (regcache, gdbarch_pc_regnum (gdbarch), &pc);
+ callsize = extract_call_winsize (gdbarch, pc);
/* On Xtensa, we can return up to 4 words (or 2 for call12). */
if (len > (callsize > 8 ? 8 : 16))
internal_error (__FILE__, __LINE__,
- _("cannot extract return value of %d bytes long"), len);
+ _("cannot extract return value of %d bytes long"),
+ len);
/* Get the register offset of the return
register (A2) in the caller window. */
regcache_raw_read_unsigned
- (regcache, gdbarch_tdep (current_gdbarch)->wb_regnum, &wb);
- areg = AREG_NUMBER(gdbarch_tdep (current_gdbarch)->a0_base + 2 + callsize,
- wb);
+ (regcache, gdbarch_tdep (gdbarch)->wb_regnum, &wb);
+ areg = arreg_number (gdbarch,
+ gdbarch_tdep (gdbarch)->a0_base + 2 + callsize, wb);
}
else
{
/* No windowing hardware - Call0 ABI. */
- areg = gdbarch_tdep (current_gdbarch)->a0_base + 0 + C0_ARGS;
+ areg = gdbarch_tdep (gdbarch)->a0_base + C0_ARGS;
}
DEBUGINFO ("[xtensa_extract_return_value] areg %d len %d\n", areg, len);
- if (len < 4 && gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
+ if (len < 4 && gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
offset = 4 - len;
for (; len > 0; len -= 4, areg++, valbuf += 4)
struct regcache *regcache,
const void *dst)
{
+ struct gdbarch *gdbarch = get_regcache_arch (regcache);
const bfd_byte *valbuf = dst;
unsigned int areg;
ULONGEST pc, wb;
DEBUGTRACE ("xtensa_store_return_value (...)\n");
- if (gdbarch_tdep (current_gdbarch)->call_abi != CallAbiCall0Only)
+ if (gdbarch_tdep (gdbarch)->call_abi != CallAbiCall0Only)
{
- regcache_raw_read_unsigned
- (regcache, gdbarch_tdep (current_gdbarch)->wb_regnum, &wb);
- regcache_raw_read_unsigned (regcache,
- gdbarch_pc_regnum (current_gdbarch), &pc);
- callsize = extract_call_winsize (pc);
+ regcache_raw_read_unsigned
+ (regcache, gdbarch_tdep (gdbarch)->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));
- areg = AREG_NUMBER
- (gdbarch_tdep (current_gdbarch)->a0_base + 2 + callsize, wb);
+ areg = arreg_number (gdbarch,
+ gdbarch_tdep (gdbarch)->a0_base + 2 + callsize, wb);
DEBUGTRACE ("[xtensa_store_return_value] callsize %d wb %d\n",
callsize, (int) wb);
}
else
{
- areg = gdbarch_tdep (current_gdbarch)->a0_base + 0 + C0_ARGS;
+ areg = gdbarch_tdep (gdbarch)->a0_base + C0_ARGS;
}
- if (len < 4 && gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
+ if (len < 4 && gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
offset = 4 - len;
for (; len > 0; len -= 4, areg++, valbuf += 4)
static enum return_value_convention
xtensa_return_value (struct gdbarch *gdbarch,
+ struct type *func_type,
struct type *valtype,
struct regcache *regcache,
gdb_byte *readbuf,
int struct_return,
CORE_ADDR struct_addr)
{
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
int i;
int size, onstack_size;
gdb_byte *buf = (gdb_byte *) alloca (16);
int align; /* alignment */
union
{
- int offset; /* stack offset if on stack */
- int regno; /* regno if in register */
+ int offset; /* stack offset if on stack. */
+ int regno; /* regno if in register. */
} u;
};
{
struct value *arg = args[i];
struct type *arg_type = check_typedef (value_type (arg));
- fprintf_unfiltered (gdb_stdlog, "%2d: 0x%08x %3d ",
- i, (int) arg, TYPE_LENGTH (arg_type));
+ fprintf_unfiltered (gdb_stdlog, "%2d: %s %3d ", i,
+ host_address_to_string (arg),
+ TYPE_LENGTH (arg_type));
switch (TYPE_CODE (arg_type))
{
case TYPE_CODE_INT:
fprintf_unfiltered (gdb_stdlog, "%3d", TYPE_CODE (arg_type));
break;
}
- fprintf_unfiltered (gdb_stdlog, " 0x%08x\n",
- (unsigned int) value_contents (arg));
+ fprintf_unfiltered (gdb_stdlog, " %s\n",
+ host_address_to_string (value_contents (arg)));
}
}
case TYPE_CODE_ENUM:
/* Cast argument to long if necessary as the mask does it too. */
- if (TYPE_LENGTH (arg_type) < TYPE_LENGTH (builtin_type_long))
+ if (TYPE_LENGTH (arg_type)
+ < TYPE_LENGTH (builtin_type (gdbarch)->builtin_long))
{
- arg_type = builtin_type_long;
+ arg_type = builtin_type (gdbarch)->builtin_long;
arg = value_cast (arg_type, arg);
}
/* Aligment is equal to the type length for the basic types. */
case TYPE_CODE_FLT:
/* Align doubles correctly. */
- if (TYPE_LENGTH (arg_type) == TYPE_LENGTH (builtin_type_double))
- info->align = TYPE_LENGTH (builtin_type_double);
+ if (TYPE_LENGTH (arg_type)
+ == TYPE_LENGTH (builtin_type (gdbarch)->builtin_double))
+ info->align = TYPE_LENGTH (builtin_type (gdbarch)->builtin_double);
else
- info->align = TYPE_LENGTH (builtin_type_long);
+ info->align = TYPE_LENGTH (builtin_type (gdbarch)->builtin_long);
break;
case TYPE_CODE_STRUCT:
default:
- info->align = TYPE_LENGTH (builtin_type_long);
+ info->align = TYPE_LENGTH (builtin_type (gdbarch)->builtin_long);
break;
}
info->length = TYPE_LENGTH (arg_type);
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)
+ if (size + info->length > REGISTER_SIZE * ARG_NOF (gdbarch))
{
info->onstack = 1;
info->u.offset = onstack_size;
else
{
info->onstack = 0;
- info->u.regno = ARG_1ST + size / REGISTER_SIZE;
+ info->u.regno = ARG_1ST (gdbarch) + size / REGISTER_SIZE;
}
size += info->length;
}
sp = align_down (sp - onstack_size, SP_ALIGNMENT);
/* Simulate MOVSP, if Windowed ABI. */
- if ((gdbarch_tdep (current_gdbarch)->call_abi != CallAbiCall0Only)
+ if ((gdbarch_tdep (gdbarch)->call_abi != CallAbiCall0Only)
&& (sp != osp))
{
read_memory (osp - 16, buf, 16);
if (struct_return)
{
- store_unsigned_integer (buf, REGISTER_SIZE, struct_addr);
- regcache_cooked_write (regcache, ARG_1ST, buf);
+ store_unsigned_integer (buf, REGISTER_SIZE, byte_order, struct_addr);
+ regcache_cooked_write (regcache, ARG_1ST (gdbarch), buf);
}
for (i = 0; i < nargs; i++)
applies for structures smaller than one word. */
if (n < REGISTER_SIZE
- && gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
+ && gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
offset += (REGISTER_SIZE - n);
write_memory (offset, info->contents, info->length);
than REGISTER_SIZE; for larger odd-sized structures the excess
will be left-aligned in the register on both endiannesses. */
- if (n < REGISTER_SIZE
- && gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
+ if (n < REGISTER_SIZE && byte_order == BFD_ENDIAN_BIG)
{
- ULONGEST v = extract_unsigned_integer (cp, REGISTER_SIZE);
+ ULONGEST v;
+ v = extract_unsigned_integer (cp, REGISTER_SIZE, byte_order);
v = v >> ((REGISTER_SIZE - n) * TARGET_CHAR_BIT);
- store_unsigned_integer (buf, REGISTER_SIZE, v);
+ store_unsigned_integer (buf, REGISTER_SIZE, byte_order, v);
regcache_cooked_write (regcache, r, buf);
cp += REGISTER_SIZE;
The return address for the current function (in A0) is
saved in the dummy frame, so we can savely overwrite A0 here. */
- if (gdbarch_tdep (current_gdbarch)->call_abi != CallAbiCall0Only)
+ if (gdbarch_tdep (gdbarch)->call_abi != CallAbiCall0Only)
{
ra = (bp_addr & 0x3fffffff) | 0x40000000;
- regcache_raw_read (regcache, gdbarch_ps_regnum (current_gdbarch), buf);
- ps = extract_unsigned_integer (buf, 4) & ~0x00030000;
+ regcache_raw_read (regcache, gdbarch_ps_regnum (gdbarch), buf);
+ ps = extract_unsigned_integer (buf, 4, byte_order) & ~0x00030000;
regcache_cooked_write_unsigned
- (regcache, gdbarch_tdep (current_gdbarch)->a0_base + 4, ra);
+ (regcache, gdbarch_tdep (gdbarch)->a0_base + 4, ra);
regcache_cooked_write_unsigned (regcache,
- gdbarch_ps_regnum (current_gdbarch),
+ gdbarch_ps_regnum (gdbarch),
ps | 0x00010000);
+
+ /* All the registers have been saved. After executing
+ dummy call, they all will be restored. So it's safe
+ 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_cooked_write_unsigned
+ (regcache, gdbarch_tdep (gdbarch)->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 (current_gdbarch)->a0_base + 0, bp_addr);
+ (regcache, gdbarch_tdep (gdbarch)->a0_base, bp_addr);
}
/* Set new stack pointer and return it. */
regcache_cooked_write_unsigned (regcache,
- gdbarch_tdep (current_gdbarch)->a0_base + 1,
- sp);
+ gdbarch_tdep (gdbarch)->a0_base + 1, sp);
/* Make dummy frame ID unique by adding a constant. */
return sp + SP_ALIGNMENT;
}
#define DENSITY_LITTLE_BREAKPOINT { 0x2d, 0xf0 }
static const unsigned char *
-xtensa_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
+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;
DEBUGTRACE ("xtensa_breakpoint_from_pc (pc = 0x%08x)\n", (int) *pcptr);
- if (gdbarch_tdep (current_gdbarch)->isa_use_density_instructions)
+ if (gdbarch_tdep (gdbarch)->isa_use_density_instructions)
{
- if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
{
*lenptr = sizeof (density_big_breakpoint);
return density_big_breakpoint;
}
else
{
- if (gdbarch_byte_order (current_gdbarch) == BFD_ENDIAN_BIG)
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
{
*lenptr = sizeof (big_breakpoint);
return big_breakpoint;
c0opc_mov, /* Moving a register to a register. */
c0opc_movi, /* Moving an immediate to a register. */
c0opc_l32r, /* Loading a literal. */
- c0opc_s32i, /* Storing word at fixed offset from a base register. */
+ c0opc_s32i, /* Storing word at fixed offset from a base
+ register. */
c0opc_NrOf /* Number of opcode classifications. */
} xtensa_insn_kind;
the stack frame. */
static void
-call0_track_op (xtensa_c0reg_t dst[], xtensa_c0reg_t src[],
+call0_track_op (struct gdbarch *gdbarch,
+ xtensa_c0reg_t dst[], xtensa_c0reg_t src[],
xtensa_insn_kind opclass, int nods, unsigned odv[],
- CORE_ADDR pc, int spreg)
+ CORE_ADDR pc, CORE_ADDR litbase, int spreg)
{
- unsigned litbase, litaddr, litval;
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+ unsigned litaddr, litval;
switch (opclass)
{
case c0opc_l32r:
/* 2 operands: dst, literal offset. */
gdb_assert (nods == 2);
- /* litbase = xtensa_get_litbase (pc); can be also used. */
- litbase = (gdbarch_tdep (current_gdbarch)->litbase_regnum == -1)
- ? 0 : xtensa_read_register
- (gdbarch_tdep (current_gdbarch)->litbase_regnum);
litaddr = litbase & 1
? (litbase & ~1) + (signed)odv[1]
: (pc + 3 + (signed)odv[1]) & ~3;
- litval = read_memory_integer(litaddr, 4);
+ litval = read_memory_integer (litaddr, 4, byte_order);
dst[odv[0]].fr_reg = C0_CONST;
dst[odv[0]].fr_ofs = litval;
break;
}
break;
default:
- gdb_assert (0);
+ gdb_assert_not_reached ("unexpected instruction kind");
}
}
because they begin with default assumptions that analysis may change. */
static CORE_ADDR
-call0_analyze_prologue (CORE_ADDR start, CORE_ADDR pc,
+call0_analyze_prologue (struct gdbarch *gdbarch,
+ CORE_ADDR start, CORE_ADDR pc, CORE_ADDR litbase,
int nregs, xtensa_c0reg_t rt[], int *call0)
{
CORE_ADDR ia; /* Current insn address in prologue. */
CORE_ADDR ba = 0; /* Current address at base of insn buffer. */
CORE_ADDR bt; /* Current address at top+1 of insn buffer. */
- #define BSZ 32 /* Instruction buffer size. */
- char ibuf[BSZ]; /* Instruction buffer for decoding prologue. */
+ char ibuf[XTENSA_ISA_BSZ];/* Instruction buffer for decoding prologue. */
xtensa_isa isa; /* libisa ISA handle. */
xtensa_insnbuf ins, slot; /* libisa handle to decoded insn, slot. */
xtensa_format ifmt; /* libisa instruction format. */
Assume we may be in the prologue until we hit a flow control instr. */
rtmp = NULL;
- body_pc = INT_MAX;
+ body_pc = UINT_MAX;
end_pc = 0;
/* Find out, if we have an information about the prologue from DWARF. */
}
else nregs = 0;
+ if (!xtensa_default_isa)
+ xtensa_default_isa = xtensa_isa_init (0, 0);
isa = xtensa_default_isa;
- gdb_assert (BSZ >= xtensa_isa_maxlength (isa));
+ gdb_assert (XTENSA_ISA_BSZ >= xtensa_isa_maxlength (isa));
ins = xtensa_insnbuf_alloc (isa);
slot = xtensa_insnbuf_alloc (isa);
if (ia + xtensa_isa_maxlength (isa) > bt)
{
ba = ia;
- bt = (ba + BSZ) < body_pc ? ba + BSZ : body_pc;
+ bt = (ba + XTENSA_ISA_BSZ) < body_pc ? ba + XTENSA_ISA_BSZ : body_pc;
read_memory (ba, ibuf, bt - ba);
+ /* If there is a memory reading error read_memory () will report it
+ and then throw an exception, stopping command execution. */
}
/* Decode format information. */
goto done;
opc = xtensa_opcode_decode (isa, ifmt, is, slot);
- DEBUGVERB ("[call0_analyze_prologue] instr addr = 0x%08x, opc = %d\n",
+ DEBUGVERB ("[call0_analyze_prologue] instr "
+ "addr = 0x%08x, opc = %d\n",
(unsigned)ia, opc);
if (opc == XTENSA_UNDEFINED)
opclass = c0opc_illegal;
}
/* Track register movement and modification for this operation. */
- call0_track_op (rt, rtmp, opclass, nods, odv, ia, 1);
+ call0_track_op (gdbarch, rt, rtmp, opclass,
+ nods, odv, ia, litbase, 1);
}
}
done:
(unsigned)ia, fail ? "failed" : "succeeded");
xtensa_insnbuf_free(isa, slot);
xtensa_insnbuf_free(isa, ins);
- return fail ? 0 : ia;
+ return fail ? XTENSA_ISA_BADPC : ia;
}
-/* Initialize frame cache for the current frame. The "next_frame" is the next
- one relative to current frame. "cache" is the pointer to the data structure
- we have to initialize. "pc" is curretnt PC. */
+/* Initialize frame cache for the current frame in CALL0 ABI. */
static void
-call0_frame_cache (struct frame_info *next_frame,
- xtensa_frame_cache_t *cache, CORE_ADDR pc)
+call0_frame_cache (struct frame_info *this_frame,
+ xtensa_frame_cache_t *cache,
+ CORE_ADDR pc, CORE_ADDR litbase)
{
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
CORE_ADDR start_pc; /* The beginning of the function. */
CORE_ADDR body_pc=UINT_MAX; /* PC, where prologue analysis stopped. */
CORE_ADDR sp, fp, ra;
if (find_pc_partial_function (pc, NULL, &start_pc, NULL))
{
- body_pc = call0_analyze_prologue (start_pc, pc, C0_NREGS,
+ body_pc = call0_analyze_prologue (gdbarch, start_pc, pc, litbase,
+ C0_NREGS,
&cache->c0.c0_rt[0],
&cache->call0);
+
+ if (body_pc == XTENSA_ISA_BADPC)
+ error (_("Xtensa-specific internal error: CALL0 prologue \
+analysis failed in this frame. GDB command execution stopped."));
}
- sp = frame_unwind_register_unsigned
- (next_frame, gdbarch_tdep (current_gdbarch)->a0_base + 1);
+ sp = get_frame_register_unsigned
+ (this_frame, gdbarch_tdep (gdbarch)->a0_base + 1);
fp = sp; /* Assume FP == SP until proven otherwise. */
/* Get the frame information and FP (if used) at the current PC.
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 (current_gdbarch)->a0_base;
+ fp_regnum += gdbarch_tdep (gdbarch)->a0_base;
}
else /* No data from the prologue analysis. */
{
c0_hasfp = 0;
- fp_regnum = gdbarch_tdep (current_gdbarch)->a0_base + C0_SP;
+ fp_regnum = gdbarch_tdep (gdbarch)->a0_base + C0_SP;
c0_frmsz = 0;
start_pc = pc;
}
alloca() and other dynamic allocations. Adjust frame size by FP - SP. */
if (c0_hasfp)
{
- fp = frame_unwind_register_unsigned (next_frame, fp_regnum);
+ fp = get_frame_register_unsigned (this_frame, fp_regnum);
/* Recalculate previous SP. */
prev_sp = fp + c0_frmsz;
to_stk = cache->c0.c0_rt[C0_RA].to_stk;
if (to_stk != C0_NOSTK)
ra = (CORE_ADDR)
- read_memory_integer (sp + c0_frmsz + cache->c0.c0_rt[C0_RA].to_stk, 4);
+ read_memory_integer (sp + c0_frmsz + cache->c0.c0_rt[C0_RA].to_stk,
+ 4, byte_order);
else if (cache->c0.c0_rt[C0_RA].fr_reg == C0_CONST
&& cache->c0.c0_rt[C0_RA].fr_ofs == 0)
{
- /* Special case for terminating backtrace at a function that wants to
- be seen as the outermost. Such a function will clear it's RA (A0)
- register to 0 in the prologue instead of saving its original value. */
+ /* Special case for terminating backtrace at a function that
+ wants to be seen as the outermost. Such a function will
+ clear it's RA (A0) register to 0 in the prologue instead of
+ saving its original value. */
ra = 0;
}
else
{
- /* RA was copied to another register or (before any function call) may
- still be in the original RA register. This is not always reliable:
- even in a leaf function, register tracking stops after prologue, and
- even in prologue, non-prologue instructions (not tracked) may overwrite
- RA or any register it was copied to. If likely in prologue or before
- any call, use retracking info and hope for the best (compiler should
- have saved RA in stack if not in a leaf function). If not in prologue,
- too bad. */
+ /* RA was copied to another register or (before any function
+ call) may still be in the original RA register. This is not
+ always reliable: even in a leaf function, register tracking
+ stops after prologue, and even in prologue, non-prologue
+ instructions (not tracked) may overwrite RA or any register
+ it was copied to. If likely in prologue or before any call,
+ use retracking info and hope for the best (compiler should
+ have saved RA in stack if not in a leaf function). If not in
+ prologue, too bad. */
int i;
for (i = 0;
++i);
if (i >= C0_NREGS && cache->c0.c0_rt[C0_RA].fr_reg == C0_RA)
i = C0_RA;
- if (i < C0_NREGS) /* Read from the next_frame. */
+ if (i < C0_NREGS)
{
- ra = frame_unwind_register_unsigned
- (next_frame,
- gdbarch_tdep (current_gdbarch)->a0_base + 0
- + cache->c0.c0_rt[i].fr_reg);
+ ra = get_frame_register_unsigned
+ (this_frame,
+ gdbarch_tdep (gdbarch)->a0_base + cache->c0.c0_rt[i].fr_reg);
}
else ra = 0;
}
/* #define DONT_SKIP_PROLOGUE */
-CORE_ADDR
-xtensa_skip_prologue (CORE_ADDR start_pc)
+static CORE_ADDR
+xtensa_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
{
struct symtab_and_line prologue_sal;
CORE_ADDR body_pc;
}
/* No debug line info. Analyze prologue for Call0 or simply skip ENTRY. */
- body_pc = call0_analyze_prologue(start_pc, 0, 0, NULL, NULL);
+ body_pc = call0_analyze_prologue (gdbarch, start_pc, 0, 0, 0, NULL, NULL);
return body_pc != 0 ? body_pc : start_pc;
}
struct ui_file *log;
struct cleanup *cleanups;
struct gdbarch_tdep *tdep;
- long dummy;
+ long length;
char *buf;
tdep = gdbarch_tdep (gdbarch);
if (tdep->a0_base == -1)
fprintf_unfiltered (log, _("\n\ta0_base: No Ax registers"));
- buf = ui_file_xstrdup (log, &dummy);
+ buf = ui_file_xstrdup (log, &length);
make_cleanup (xfree, buf);
- if (strlen (buf) > 0)
+ if (length > 0)
internal_error (__FILE__, __LINE__,
_("the following are invalid: %s"), buf);
do_cleanups (cleanups);
}
+
+/* Derive specific register numbers from the array of registers. */
+
+static void
+xtensa_derive_tdep (struct gdbarch_tdep *tdep)
+{
+ xtensa_register_t* rmap;
+ int n, max_size = 4;
+
+ tdep->num_regs = 0;
+ tdep->num_nopriv_regs = 0;
+
+/* Special registers 0..255 (core). */
+#define XTENSA_DBREGN_SREG(n) (0x0200+(n))
+
+ for (rmap = tdep->regmap, n = 0; rmap->target_number != -1; n++, rmap++)
+ {
+ if (rmap->target_number == 0x0020)
+ tdep->pc_regnum = n;
+ else if (rmap->target_number == 0x0100)
+ tdep->ar_base = n;
+ else if (rmap->target_number == 0x0000)
+ tdep->a0_base = n;
+ else if (rmap->target_number == XTENSA_DBREGN_SREG(72))
+ tdep->wb_regnum = n;
+ else if (rmap->target_number == XTENSA_DBREGN_SREG(73))
+ tdep->ws_regnum = n;
+ else if (rmap->target_number == XTENSA_DBREGN_SREG(233))
+ tdep->debugcause_regnum = n;
+ else if (rmap->target_number == XTENSA_DBREGN_SREG(232))
+ tdep->exccause_regnum = n;
+ else if (rmap->target_number == XTENSA_DBREGN_SREG(238))
+ tdep->excvaddr_regnum = n;
+ else if (rmap->target_number == XTENSA_DBREGN_SREG(0))
+ tdep->lbeg_regnum = n;
+ else if (rmap->target_number == XTENSA_DBREGN_SREG(1))
+ tdep->lend_regnum = n;
+ else if (rmap->target_number == XTENSA_DBREGN_SREG(2))
+ tdep->lcount_regnum = n;
+ else if (rmap->target_number == XTENSA_DBREGN_SREG(3))
+ tdep->sar_regnum = n;
+ else if (rmap->target_number == XTENSA_DBREGN_SREG(5))
+ tdep->litbase_regnum = n;
+ else if (rmap->target_number == XTENSA_DBREGN_SREG(230))
+ tdep->ps_regnum = n;
+#if 0
+ else if (rmap->target_number == XTENSA_DBREGN_SREG(226))
+ tdep->interrupt_regnum = n;
+ else if (rmap->target_number == XTENSA_DBREGN_SREG(227))
+ tdep->interrupt2_regnum = n;
+ else if (rmap->target_number == XTENSA_DBREGN_SREG(224))
+ tdep->cpenable_regnum = n;
+#endif
+
+ if (rmap->byte_size > max_size)
+ 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;
+ }
+
+ /* Number of pseudo registers. */
+ tdep->num_pseudo_regs = n - tdep->num_regs;
+
+ /* Empirically determined maximum sizes. */
+ tdep->max_register_raw_size = max_size;
+ tdep->max_register_virtual_size = max_size;
+}
+
/* Module "constructor" function. */
+extern struct gdbarch_tdep xtensa_tdep;
+
static struct gdbarch *
xtensa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
DEBUGTRACE ("gdbarch_init()\n");
/* We have to set the byte order before we call gdbarch_alloc. */
- info.byte_order = xtensa_config_byte_order (&info);
+ info.byte_order = XCHAL_HAVE_BE ? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE;
- tdep = xtensa_config_tdep (&info);
+ tdep = &xtensa_tdep;
gdbarch = gdbarch_alloc (&info, tdep);
+ xtensa_derive_tdep (tdep);
/* Verify our configuration. */
xtensa_verify_config (gdbarch);
set_gdbarch_pc_regnum (gdbarch, tdep->pc_regnum);
set_gdbarch_ps_regnum (gdbarch, tdep->ps_regnum);
- /* Renumber registers for known formats (stab, dwarf, and dwarf2). */
+ /* Renumber registers for known formats (stabs and dwarf2). */
set_gdbarch_stab_reg_to_regnum (gdbarch, xtensa_reg_to_regnum);
- set_gdbarch_dwarf_reg_to_regnum (gdbarch, xtensa_reg_to_regnum);
set_gdbarch_dwarf2_reg_to_regnum (gdbarch, xtensa_reg_to_regnum);
/* We provide our own function to get register information. */
set_gdbarch_register_name (gdbarch, xtensa_register_name);
set_gdbarch_register_type (gdbarch, xtensa_register_type);
- /* To call functions from GDB using dummy frame */
+ /* To call functions from GDB using dummy frame. */
set_gdbarch_push_dummy_call (gdbarch, xtensa_push_dummy_call);
set_gdbarch_believe_pcc_promotion (gdbarch, 1);
set_gdbarch_frame_align (gdbarch, xtensa_frame_align);
- set_gdbarch_unwind_dummy_id (gdbarch, xtensa_unwind_dummy_id);
+ set_gdbarch_dummy_id (gdbarch, xtensa_dummy_id);
/* Frame handling. */
frame_base_set_default (gdbarch, &xtensa_frame_base);
- frame_unwind_append_sniffer (gdbarch, xtensa_frame_sniffer);
+ frame_unwind_append_unwinder (gdbarch, &xtensa_unwind);
+ dwarf2_append_unwinders (gdbarch);
set_gdbarch_print_insn (gdbarch, print_insn_xtensa);
set_gdbarch_regset_from_core_section (gdbarch,
xtensa_regset_from_core_section);
+ set_solib_svr4_fetch_link_map_offsets
+ (gdbarch, svr4_ilp32_fetch_link_map_offsets);
+
return gdbarch;
}
static void
-xtensa_dump_tdep (struct gdbarch *current_gdbarch, struct ui_file *file)
+xtensa_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
{
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)
{
add_setshow_zinteger_cmd ("xtensa",
class_maintenance,
- &xtensa_debug_level, _("\
-Set Xtensa debugging."), _("\
-Show Xtensa debugging."), _("\
+ &xtensa_debug_level,
+ _("Set Xtensa debugging."),
+ _("Show Xtensa debugging."), _("\
When non-zero, Xtensa-specific debugging is enabled. \
Can be 1, 2, 3, or 4 indicating the level of debugging."),
NULL,