gdb/xtensa-tdep.c - gdb
Global variables defined
Data types defined
Functions defined
Macros defined
Source code
- #include "defs.h"
- #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 "regcache.h"
- #include "reggroups.h"
- #include "regset.h"
- #include "dummy-frame.h"
- #include "dwarf2.h"
- #include "dwarf2-frame.h"
- #include "dwarf2loc.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"
- static unsigned int xtensa_debug_level = 0;
- #define DEBUGWARN(args...) \
- if (xtensa_debug_level > 0) \
- fprintf_unfiltered (gdb_stdlog, "(warn ) " args)
- #define DEBUGINFO(args...) \
- if (xtensa_debug_level > 1) \
- fprintf_unfiltered (gdb_stdlog, "(info ) " args)
- #define DEBUGTRACE(args...) \
- if (xtensa_debug_level > 2) \
- fprintf_unfiltered (gdb_stdlog, "(trace) " args)
- #define DEBUGVERB(args...) \
- if (xtensa_debug_level > 3) \
- fprintf_unfiltered (gdb_stdlog, "(verb ) " args)
- #define SP_ALIGNMENT 16
- #define ARGS_NUM_REGS 6
- #define REGISTER_SIZE 4
- #define PS_CALLINC_SHIFT 16
- #define PS_CALLINC_MASK 0x00030000
- #define CALLINC(ps) (((ps) & PS_CALLINC_MASK) >> PS_CALLINC_SHIFT)
- #define WINSIZE(ra) (4 * (( (ra) >> 30) & 0x3))
- #define TX_PS 0x20
- #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))
- #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)
- static int
- windowing_enabled (struct gdbarch *gdbarch, unsigned int ps)
- {
-
- if (gdbarch_tdep (gdbarch)->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);
- 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;
- }
- 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 unsigned long
- xtensa_read_register (int regnum)
- {
- ULONGEST value;
- regcache_raw_read_unsigned (get_current_regcache (), regnum, &value);
- return (unsigned long) value;
- }
- static void
- xtensa_write_register (int regnum, ULONGEST value)
- {
- regcache_raw_write_unsigned (get_current_regcache (), regnum, value);
- }
- static int
- 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];
- DEBUGTRACE ("extract_call_winsize (pc = 0x%08x)\n", (int) pc);
-
- read_memory (pc-3, buf, 3);
- insn = extract_unsigned_integer (buf, 3, byte_order);
-
- if (byte_order == BFD_ENDIAN_LITTLE)
- {
- if (((insn & 0xf) == 0x5) || ((insn & 0xcf) == 0xc0))
- winsize = (insn & 0x30) >> 2;
- }
- else
- {
- if (((insn >> 20) == 0x5) || (((insn >> 16) & 0xf3) == 0x03))
- winsize = (insn >> 16) & 0xc;
- }
- return winsize;
- }
- static int
- xtensa_find_register_by_name (struct gdbarch *gdbarch, char *name)
- {
- int i;
- for (i = 0; i < gdbarch_num_regs (gdbarch)
- + gdbarch_num_pseudo_regs (gdbarch);
- i++)
- if (strcasecmp (gdbarch_tdep (gdbarch)->regmap[i].name, name) == 0)
- return i;
- return -1;
- }
- static const char *
- xtensa_register_name (struct gdbarch *gdbarch, int regnum)
- {
-
- 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 struct type *
- xtensa_register_type (struct gdbarch *gdbarch, int regnum)
- {
- struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
-
- 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 (gdbarch)
- || regnum == tdep->a0_base + 1)
- return builtin_type (gdbarch)->builtin_data_ptr;
-
- else if (regnum >= 0 && regnum < gdbarch_num_regs (gdbarch)
- + gdbarch_num_pseudo_regs (gdbarch))
- {
- xtensa_register_t* reg = &tdep->regmap[regnum];
-
- if (reg->ctype == 0)
- {
- struct ctype_cache *tp;
- int size = reg->byte_size;
-
- switch (size)
- {
- case 1:
- reg->ctype = builtin_type (gdbarch)->builtin_uint8;
- break;
- case 2:
- reg->ctype = builtin_type (gdbarch)->builtin_uint16;
- break;
- case 4:
- reg->ctype = builtin_type (gdbarch)->builtin_uint32;
- break;
- case 8:
- reg->ctype = builtin_type (gdbarch)->builtin_uint64;
- break;
- case 16:
- reg->ctype = builtin_type (gdbarch)->builtin_uint128;
- break;
- default:
- for (tp = tdep->type_entries; tp != NULL; tp = tp->next)
- if (tp->size == size)
- break;
- if (tp == NULL)
- {
- char *name = xstrprintf ("int%d", size * 8);
- tp = xmalloc (sizeof (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);
- }
- reg->ctype = tp->virtual_type;
- }
- }
- return reg->ctype;
- }
- internal_error (__FILE__, __LINE__, _("invalid register number %d"), regnum);
- return 0;
- }
- static int
- xtensa_reg_to_regnum (struct gdbarch *gdbarch, int regnum)
- {
- int i;
- if (regnum >= 0 && regnum < 16)
- return gdbarch_tdep (gdbarch)->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)
- return i;
- internal_error (__FILE__, __LINE__,
- _("invalid dwarf/stabs register number %d"), regnum);
- return 0;
- }
- static void
- xtensa_register_write_masked (struct regcache *regcache,
- xtensa_register_t *reg, const gdb_byte *buffer)
- {
- unsigned int value[(MAX_REGISTER_SIZE + 3) / 4];
- const xtensa_mask_t *mask = reg->mask;
- int shift = 0;
- int start, size;
- unsigned int *ptr = value;
- unsigned int regval, m, mem = 0;
- int bytesize = reg->byte_size;
- int bitsize = bytesize * 8;
- int i, r;
- DEBUGTRACE ("xtensa_register_write_masked ()\n");
-
- if (gdbarch_byte_order (get_regcache_arch (regcache)) == BFD_ENDIAN_BIG)
- for (i = 0; i < bytesize; i++)
- {
- mem >>= 8;
- mem |= (buffer[bytesize - i - 1] << 24);
- if ((i & 3) == 3)
- *ptr++ = mem;
- }
- else
- for (i = 0; i < bytesize; i++)
- {
- mem >>= 8;
- mem |= (buffer[i] << 24);
- if ((i & 3) == 3)
- *ptr++ = mem;
- }
-
- *ptr = mem >> (((0 - bytesize) & 3) * 8);
- ptr = value;
- mem = *ptr;
-
- for (i = 0; i < mask->count; i++)
- {
- start = mask->mask[i].bit_start;
- size = mask->mask[i].bit_size;
- regval = mem >> shift;
- if ((shift += size) > bitsize)
- error (_("size of all masks is larger than the register"));
- if (shift >= 32)
- {
- mem = *(++ptr);
- shift -= 32;
- bitsize -= 32;
- if (shift > 0)
- regval |= mem << (size - shift);
- }
-
- r = mask->mask[i].reg_num;
- if (r >= 0 && size > 0)
- {
-
- ULONGEST old_val;
- regcache_cooked_read_unsigned (regcache, r, &old_val);
- m = 0xffffffff >> (32 - size) << start;
- regval <<= start;
- regval = (regval & m) | (old_val & ~m);
- regcache_cooked_write_unsigned (regcache, r, regval);
- }
- }
- }
- static enum register_status
- xtensa_register_read_masked (struct regcache *regcache,
- xtensa_register_t *reg, gdb_byte *buffer)
- {
- unsigned int value[(MAX_REGISTER_SIZE + 3) / 4];
- const xtensa_mask_t *mask = reg->mask;
- int shift = 0;
- int start, size;
- unsigned int *ptr = value;
- unsigned int regval, mem = 0;
- int bytesize = reg->byte_size;
- int bitsize = bytesize * 8;
- int i;
- DEBUGTRACE ("xtensa_register_read_masked (reg \"%s\", ...)\n",
- reg->name == 0 ? "" : reg->name);
-
- for (i = 0; i < mask->count; i++)
- {
- int r = mask->mask[i].reg_num;
- if (r >= 0)
- {
- enum register_status status;
- ULONGEST val;
- status = regcache_cooked_read_unsigned (regcache, r, &val);
- if (status != REG_VALID)
- return status;
- regval = (unsigned int) val;
- }
- else
- regval = 0;
- start = mask->mask[i].bit_start;
- size = mask->mask[i].bit_size;
- regval >>= start;
- if (size < 32)
- regval &= (0xffffffff >> (32 - size));
- mem |= regval << shift;
- if ((shift += size) > bitsize)
- error (_("size of all masks is larger than the register"));
- if (shift >= 32)
- {
- *ptr++ = mem;
- bitsize -= 32;
- shift -= 32;
- if (shift == 0)
- mem = 0;
- else
- mem = regval >> (size - shift);
- }
- }
- if (shift > 0)
- *ptr = mem;
-
- ptr = value;
- mem = *ptr;
- if (gdbarch_byte_order (get_regcache_arch (regcache)) == BFD_ENDIAN_BIG)
- for (i = 0; i < bytesize; i++)
- {
- if ((i & 3) == 0)
- mem = *ptr++;
- buffer[bytesize - i - 1] = mem & 0xff;
- mem >>= 8;
- }
- else
- for (i = 0; i < bytesize; i++)
- {
- if ((i & 3) == 0)
- mem = *ptr++;
- buffer[i] = mem & 0xff;
- mem >>= 8;
- }
- return REG_VALID;
- }
- static enum register_status
- xtensa_pseudo_register_read (struct gdbarch *gdbarch,
- struct 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;
-
- 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);
- enum register_status status;
- status = regcache_raw_read (regcache,
- gdbarch_tdep (gdbarch)->wb_regnum,
- buf);
- if (status != REG_VALID)
- return status;
- regnum = arreg_number (gdbarch, regnum,
- extract_unsigned_integer (buf, 4, byte_order));
- }
-
- if (regnum >= 0 && regnum < gdbarch_num_regs (gdbarch))
- return regcache_raw_read (regcache, regnum, buffer);
-
- 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;
- return REG_VALID;
- }
-
- else if (regnum >= 0
- && regnum < gdbarch_num_regs (gdbarch)
- + gdbarch_num_pseudo_regs (gdbarch))
- {
- xtensa_register_t *reg = &gdbarch_tdep (gdbarch)->regmap[regnum];
- xtensa_register_type_t type = reg->type;
- int flags = gdbarch_tdep (gdbarch)->target_flags;
-
- if (type == xtRegisterTypeUnmapped || type == xtRegisterTypeUnknown)
- {
- if ((flags & xtTargetFlagsNonVisibleRegs) == 0)
- {
- warning (_("cannot read register %s"),
- xtensa_register_name (gdbarch, regnum));
- return REG_VALID;
- }
- }
-
- else if (type == xtRegisterTypeTieRegfile)
- {
-
- if (flags & xtTargetFlagsUseFetchStore)
- {
- warning (_("cannot read register"));
- return REG_VALID;
- }
-
- else if ((flags & xtTargetFlagsNonVisibleRegs) == 0)
- {
- warning (_("cannot read register"));
- return REG_VALID;
- }
- }
-
- else if (type == xtRegisterTypeMapped || type == xtRegisterTypeTieState)
- return xtensa_register_read_masked (regcache, reg, buffer);
-
- return regcache_raw_read (regcache, regnum, buffer);
- }
- else
- internal_error (__FILE__, __LINE__,
- _("invalid register number %d"), regnum);
- }
- static void
- xtensa_pseudo_register_write (struct gdbarch *gdbarch,
- struct regcache *regcache,
- 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));
- if (regnum == gdbarch_num_regs (gdbarch)
- + gdbarch_num_pseudo_regs (gdbarch) -1)
- regnum = gdbarch_tdep (gdbarch)->a0_base + 1;
-
- 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 (gdbarch)->wb_regnum, buf);
- regnum = arreg_number (gdbarch, regnum,
- extract_unsigned_integer (buf, 4, byte_order));
- }
-
- if (regnum >= 0 && regnum < gdbarch_num_regs (gdbarch))
- regcache_raw_write (regcache, regnum, buffer);
-
- else if (regnum < gdbarch_tdep (gdbarch)->a0_base)
- {
- return;
- }
-
- else if (regnum >= 0
- && regnum < gdbarch_num_regs (gdbarch)
- + gdbarch_num_pseudo_regs (gdbarch))
- {
- xtensa_register_t *reg = &gdbarch_tdep (gdbarch)->regmap[regnum];
- xtensa_register_type_t type = reg->type;
- int flags = gdbarch_tdep (gdbarch)->target_flags;
-
- if (type == xtRegisterTypeUnmapped || type == xtRegisterTypeUnknown)
- {
- if ((flags & xtTargetFlagsNonVisibleRegs) == 0)
- {
- warning (_("cannot write register %s"),
- xtensa_register_name (gdbarch, regnum));
- return;
- }
- }
-
- else if (type == xtRegisterTypeTieRegfile)
- {
-
- if (flags & xtTargetFlagsUseFetchStore)
- {
- warning (_("cannot write register"));
- return;
- }
-
- else if ((flags & xtTargetFlagsNonVisibleRegs) == 0)
- {
- warning (_("cannot write register"));
- return;
- }
- }
-
- else if (type == xtRegisterTypeMapped || type == xtRegisterTypeTieState)
- {
- xtensa_register_write_masked (regcache, reg, buffer);
- return;
- }
-
- regcache_raw_write (regcache, 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 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);
- }
- }
- static void
- xtensa_add_reggroups (struct gdbarch *gdbarch)
- {
- int i;
-
- 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);
-
- 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++)
- reggroup_add (gdbarch, xtensa_cp[i]);
- }
- static int
- xtensa_coprocessor_register_group (struct reggroup *group)
- {
- int i;
- for (i = 0; i < XTENSA_MAX_COPROCESSOR; i++)
- if (group == xtensa_cp[i])
- return i;
- return -1;
- }
- #define SAVE_REST_FLAGS (XTENSA_REGISTER_FLAGS_READABLE \
- | XTENSA_REGISTER_FLAGS_WRITABLE \
- | XTENSA_REGISTER_FLAGS_VOLATILE)
- #define SAVE_REST_VALID (XTENSA_REGISTER_FLAGS_READABLE \
- | XTENSA_REGISTER_FLAGS_WRITABLE)
- static int
- xtensa_register_reggroup_p (struct gdbarch *gdbarch,
- int regnum,
- struct reggroup *group)
- {
- 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 == save_reggroup)
-
- return 1;
-
- if (type == xtRegisterTypeUnmapped || type == xtRegisterTypeUnknown)
- return 0;
- if (group == all_reggroup)
- return 1;
- if (group == xtensa_ar_reggroup)
- return rg & xtRegisterGroupAddrReg;
- if (group == xtensa_user_reggroup)
- return rg & xtRegisterGroupUser;
- if (group == float_reggroup)
- return rg & xtRegisterGroupFloat;
- if (group == general_reggroup)
- return rg & xtRegisterGroupGeneral;
- if (group == system_reggroup)
- return rg & xtRegisterGroupState;
- if (group == vector_reggroup || group == xtensa_vectra_reggroup)
- return rg & xtRegisterGroupVectra;
- if (group == restore_reggroup)
- return (regnum < gdbarch_num_regs (gdbarch)
- && (reg->flags & SAVE_REST_FLAGS) == SAVE_REST_VALID);
- cp_number = xtensa_coprocessor_register_group (group);
- if (cp_number >= 0)
- return rg & (xtRegisterGroupCP0 << cp_number);
- else
- return 1;
- }
- static void
- xtensa_supply_gregset (const struct regset *regset,
- struct regcache *rc,
- int regnum,
- const void *gregs,
- 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 (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 (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]);
- 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]);
- }
- }
- static struct regset
- xtensa_gregset =
- {
- NULL,
- xtensa_supply_gregset
- };
- static void
- xtensa_iterate_over_regset_sections (struct gdbarch *gdbarch,
- iterate_over_regset_sections_cb *cb,
- void *cb_data,
- const struct regcache *regcache)
- {
- DEBUGTRACE ("xtensa_iterate_over_regset_sections\n");
- cb (".reg", sizeof (xtensa_elf_gregset_t), &xtensa_gregset,
- NULL, cb_data);
- }
- #define XTENSA_NUM_SAVED_AREGS 12
- typedef struct xtensa_windowed_frame_cache
- {
- int wb;
- int callsize;
- int ws;
-
- CORE_ADDR aregs[XTENSA_NUM_SAVED_AREGS];
- } xtensa_windowed_frame_cache_t;
- #define C0_MAXOPDS 3
- #define C0_NREGS 16
- #define C0_CLESV 12
- #define C0_SP 1
- #define C0_FP 15
- #define C0_RA 0
- #define C0_ARGS 2
- #define C0_NARGS 6
- #define C0_CONST -1
- #define C0_INEXP -2
- #define C0_NOSTK -1
- extern xtensa_isa xtensa_default_isa;
- typedef struct xtensa_c0reg
- {
- int fr_reg;
- int fr_ofs;
- int to_stk;
- } xtensa_c0reg_t;
- typedef struct xtensa_call0_frame_cache
- {
- int c0_frmsz;
- int c0_hasfp;
- int fp_regnum;
- int c0_fp;
- int c0_fpalign;
- int c0_old_sp;
- int c0_sp_ofs;
- xtensa_c0reg_t c0_rt[C0_NREGS];
- } xtensa_call0_frame_cache_t;
- typedef struct xtensa_frame_cache
- {
- CORE_ADDR base;
- CORE_ADDR pc;
- CORE_ADDR ra;
- CORE_ADDR ps;
- CORE_ADDR prev_sp;
- int call0;
- union
- {
- xtensa_windowed_frame_cache_t wd;
- xtensa_call0_frame_cache_t c0;
- };
- } xtensa_frame_cache_t;
- static struct xtensa_frame_cache *
- xtensa_alloc_frame_cache (int windowed)
- {
- xtensa_frame_cache_t *cache;
- int i;
- DEBUGTRACE ("xtensa_alloc_frame_cache ()\n");
- cache = FRAME_OBSTACK_ZALLOC (xtensa_frame_cache_t);
- cache->base = 0;
- cache->pc = 0;
- cache->ra = 0;
- cache->ps = 0;
- cache->prev_sp = 0;
- cache->call0 = !windowed;
- if (cache->call0)
- {
- cache->c0.c0_frmsz = -1;
- cache->c0.c0_hasfp = 0;
- cache->c0.fp_regnum = -1;
- cache->c0.c0_fp = -1;
- cache->c0.c0_fpalign = 0;
- cache->c0.c0_old_sp = C0_INEXP;
- cache->c0.c0_sp_ofs = C0_NOSTK;
- for (i = 0; i < C0_NREGS; i++)
- {
- cache->c0.c0_rt[i].fr_reg = i;
- cache->c0.c0_rt[i].fr_ofs = 0;
- cache->c0.c0_rt[i].to_stk = C0_NOSTK;
- }
- }
- else
- {
- cache->wd.wb = 0;
- cache->wd.ws = 0;
- cache->wd.callsize = -1;
- for (i = 0; i < XTENSA_NUM_SAVED_AREGS; i++)
- cache->wd.aregs[i] = -1;
- }
- return cache;
- }
- static CORE_ADDR
- xtensa_frame_align (struct gdbarch *gdbarch, CORE_ADDR address)
- {
- return address & ~15;
- }
- static CORE_ADDR
- xtensa_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
- {
- gdb_byte buf[8];
- CORE_ADDR pc;
- DEBUGTRACE ("xtensa_unwind_pc (next_frame = %s)\n",
- host_address_to_string (next_frame));
- 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) pc);
- return pc;
- }
- static struct frame_id
- xtensa_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
- {
- CORE_ADDR pc, fp;
-
- pc = get_frame_pc (this_frame);
- fp = get_frame_register_unsigned
- (this_frame, gdbarch_tdep (gdbarch)->a0_base + 1);
-
- return frame_id_build (fp + SP_ALIGNMENT, pc);
- }
- static int
- xtensa_window_interrupt_insn (struct gdbarch *gdbarch, CORE_ADDR pc)
- {
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- unsigned int insn = read_memory_integer (pc, 4, byte_order);
- unsigned int code;
- if (byte_order == BFD_ENDIAN_BIG)
- {
-
- code = insn & 0xf000ff00;
- if ((code == 0x00009000) || (code == 0x00009400))
- return 1;
-
- code = insn & 0xffffff00;
- return ((code == 0x00430000) || (code == 0x00530000));
- }
- else
- {
-
- code = insn & 0x00ff000f;
- if ((code == 0x090000) || (code == 0x490000))
- return 1;
-
- code = insn & 0x00ffffff;
- return ((code == 0x00003400) || (code == 0x00003500));
- }
- }
- #define XTENSA_ISA_BSZ 32
- #define XTENSA_ISA_BADPC ((CORE_ADDR)0)
- 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;
- gdb_byte 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;
-
- 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)
- {
- 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 (
-
- opcname == NULL
- || strcasecmp (opcname, "ill") == 0
- || strcasecmp (opcname, "ill.n") == 0
-
- || strcasecmp (opcname, "break") == 0
- || strcasecmp (opcname, "break.n") == 0
-
- || 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)
-
- RETURN_FP;
- }
- }
- done:
- xtensa_insnbuf_free(isa, slot);
- xtensa_insnbuf_free(isa, ins);
- return fp_regnum;
- }
- static void
- call0_frame_cache (struct frame_info *this_frame,
- xtensa_frame_cache_t *cache, CORE_ADDR pc);
- static void
- xtensa_window_interrupt_frame_cache (struct frame_info *this_frame,
- xtensa_frame_cache_t *cache,
- CORE_ADDR pc);
- static struct xtensa_frame_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;
- struct gdbarch *gdbarch = get_frame_arch (this_frame);
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- unsigned int fp_regnum;
- int windowed, ps_regnum;
- if (*this_cache)
- return *this_cache;
- pc = get_frame_register_unsigned (this_frame, gdbarch_pc_regnum (gdbarch));
- ps_regnum = gdbarch_ps_regnum (gdbarch);
- ps = (ps_regnum >= 0
- ? get_frame_register_unsigned (this_frame, ps_regnum) : TX_PS);
- windowed = windowing_enabled (gdbarch, ps);
-
- cache = xtensa_alloc_frame_cache (windowed);
- *this_cache = cache;
- if (windowed)
- {
- char 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 = get_frame_register_unsigned
- (this_frame, gdbarch_tdep (gdbarch)->a0_base + callinc * 4);
-
- 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);
-
- 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
- {
- 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 (gdbarch)->num_aregs / 4 - 1);
- cache->wd.ws = ws & ~(1 << wb);
- 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;
-
- sp = get_frame_register_unsigned
- (this_frame, gdbarch_tdep (gdbarch)->a0_base + 1) - 16;
- for (i = 0; i < 4; i++, sp += 4)
- {
- cache->wd.aregs[i] = sp;
- }
- if (cache->wd.callsize > 4)
- {
-
-
- 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)
- {
- cache->wd.aregs[i] = sp;
- }
- }
- }
- if ((cache->prev_sp == 0) && ( ra != 0 ))
-
- {
- if ((cache->wd.ws & (1 << cache->wd.wb)) == 0)
- {
-
- 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
- {
-
- int regnum = arreg_number
- (gdbarch, gdbarch_tdep (gdbarch)->a0_base + 1,
- cache->wd.wb);
- cache->prev_sp = xtensa_read_register (regnum);
- }
- }
- }
- else if (xtensa_window_interrupt_insn (gdbarch, pc))
- {
-
- xtensa_window_interrupt_frame_cache (this_frame, cache, pc);
-
- return cache;
- }
- else
- {
- call0_frame_cache (this_frame, cache, pc);
- fp_regnum = cache->c0.fp_regnum;
- }
- cache->base = get_frame_register_unsigned (this_frame, fp_regnum);
- return cache;
- }
- static int xtensa_session_once_reported = 1;
- static void
- warning_once (void)
- {
- if (xtensa_session_once_reported == 0)
- warning (_("\
- \nUnrecognised function prologue. Stack trace cannot be resolved. \
- This message will not be repeated in this session.\n"));
- xtensa_session_once_reported = 1;
- }
- static void
- 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 (this_frame, this_cache);
- if (cache->prev_sp == 0)
- return;
- (*this_id) = frame_id_build (cache->prev_sp, cache->pc);
- }
- static struct value *
- xtensa_frame_prev_register (struct frame_info *this_frame,
- void **this_cache,
- int regnum)
- {
- struct gdbarch *gdbarch = get_frame_arch (this_frame);
- struct xtensa_frame_cache *cache;
- ULONGEST saved_reg = 0;
- int done = 1;
- if (*this_cache == NULL)
- *this_cache = xtensa_frame_cache (this_frame, this_cache);
- cache = *this_cache;
- if (regnum ==gdbarch_pc_regnum (gdbarch))
- saved_reg = cache->ra;
- else if (regnum == gdbarch_tdep (gdbarch)->a0_base + 1)
- saved_reg = cache->prev_sp;
- else if (!cache->call0)
- {
- 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 (gdbarch))
- saved_reg = cache->ps;
- else
- done = 0;
- }
- else
- done = 0;
- if (done)
- return frame_unwind_got_constant (this_frame, regnum, saved_reg);
- if (!cache->call0)
- {
-
- if (regnum >= gdbarch_tdep (gdbarch)->a0_base
- && regnum <= gdbarch_tdep (gdbarch)->a0_base + 15)
- regnum = arreg_number (gdbarch, regnum, cache->wd.wb);
-
- if (regnum >= gdbarch_tdep (gdbarch)->ar_base
- && regnum <= (gdbarch_tdep (gdbarch)->ar_base
- + gdbarch_tdep (gdbarch)->num_aregs))
- {
- int areg = areg_number (gdbarch, regnum, cache->wd.wb);
- if (areg >= 0
- && areg < XTENSA_NUM_SAVED_AREGS
- && cache->wd.aregs[areg] != -1)
- return frame_unwind_got_memory (this_frame, regnum,
- cache->wd.aregs[areg]);
- }
- }
- else
- {
- int reg = (regnum >= gdbarch_tdep (gdbarch)->ar_base
- && regnum <= (gdbarch_tdep (gdbarch)->ar_base
- + C0_NREGS))
- ? regnum - gdbarch_tdep (gdbarch)->ar_base : regnum;
- if (reg < C0_NREGS)
- {
- CORE_ADDR spe;
- int stkofs;
-
- stkofs = cache->c0.c0_rt[reg].to_stk;
- if (stkofs != C0_NOSTK)
- {
-
- spe = cache->c0.c0_fp
- - cache->c0.c0_rt[cache->c0.fp_regnum].fr_ofs;
- return frame_unwind_got_memory (this_frame, regnum,
- spe + stkofs);
- }
- }
- }
-
- return frame_unwind_got_register (this_frame, regnum, regnum);
- }
- static const struct frame_unwind
- xtensa_unwind =
- {
- NORMAL_FRAME,
- default_frame_unwind_stop_reason,
- xtensa_frame_this_id,
- xtensa_frame_prev_register,
- NULL,
- default_frame_sniffer
- };
- static CORE_ADDR
- xtensa_frame_base_address (struct frame_info *this_frame, void **this_cache)
- {
- struct xtensa_frame_cache *cache =
- xtensa_frame_cache (this_frame, this_cache);
- return cache->base;
- }
- static const struct frame_base
- xtensa_frame_base =
- {
- &xtensa_unwind,
- xtensa_frame_base_address,
- xtensa_frame_base_address,
- xtensa_frame_base_address
- };
- static void
- xtensa_extract_return_value (struct type *type,
- struct regcache *regcache,
- void *dst)
- {
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
- bfd_byte *valbuf = dst;
- int len = TYPE_LENGTH (type);
- ULONGEST pc, wb;
- int callsize, areg;
- int offset = 0;
- DEBUGTRACE ("xtensa_extract_return_value (...)\n");
- gdb_assert(len > 0);
- if (gdbarch_tdep (gdbarch)->call_abi != CallAbiCall0Only)
- {
-
- 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__,
- _("cannot extract return value of %d bytes long"),
- len);
-
- regcache_raw_read_unsigned
- (regcache, gdbarch_tdep (gdbarch)->wb_regnum, &wb);
- areg = arreg_number (gdbarch,
- gdbarch_tdep (gdbarch)->a0_base + 2 + callsize, wb);
- }
- else
- {
-
- 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 (gdbarch) == BFD_ENDIAN_BIG)
- offset = 4 - len;
- for (; len > 0; len -= 4, areg++, valbuf += 4)
- {
- if (len < 4)
- regcache_raw_read_part (regcache, areg, offset, len, valbuf);
- else
- regcache_raw_read (regcache, areg, valbuf);
- }
- }
- static void
- xtensa_store_return_value (struct type *type,
- struct regcache *regcache,
- const void *dst)
- {
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
- const bfd_byte *valbuf = dst;
- unsigned int areg;
- ULONGEST pc, wb;
- int callsize;
- int len = TYPE_LENGTH (type);
- int offset = 0;
- DEBUGTRACE ("xtensa_store_return_value (...)\n");
- if (gdbarch_tdep (gdbarch)->call_abi != CallAbiCall0Only)
- {
- 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 = 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 (gdbarch)->a0_base + C0_ARGS;
- }
- if (len < 4 && gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
- offset = 4 - len;
- for (; len > 0; len -= 4, areg++, valbuf += 4)
- {
- if (len < 4)
- regcache_raw_write_part (regcache, areg, offset, len, valbuf);
- else
- regcache_raw_write (regcache, areg, valbuf);
- }
- }
- static enum return_value_convention
- xtensa_return_value (struct gdbarch *gdbarch,
- struct value *function,
- struct type *valtype,
- struct regcache *regcache,
- gdb_byte *readbuf,
- const gdb_byte *writebuf)
- {
-
- int struct_return = ((TYPE_CODE (valtype) == TYPE_CODE_STRUCT
- || TYPE_CODE (valtype) == TYPE_CODE_UNION
- || TYPE_CODE (valtype) == TYPE_CODE_ARRAY)
- && TYPE_LENGTH (valtype) > 16);
- if (struct_return)
- return RETURN_VALUE_STRUCT_CONVENTION;
- DEBUGTRACE ("xtensa_return_value(...)\n");
- if (writebuf != NULL)
- {
- xtensa_store_return_value (valtype, regcache, writebuf);
- }
- if (readbuf != NULL)
- {
- gdb_assert (!struct_return);
- xtensa_extract_return_value (valtype, regcache, readbuf);
- }
- return RETURN_VALUE_REGISTER_CONVENTION;
- }
- static CORE_ADDR
- xtensa_push_dummy_call (struct gdbarch *gdbarch,
- struct value *function,
- struct regcache *regcache,
- CORE_ADDR bp_addr,
- int nargs,
- struct value **args,
- CORE_ADDR sp,
- int struct_return,
- CORE_ADDR struct_addr)
- {
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- int i;
- int size, onstack_size;
- gdb_byte *buf = (gdb_byte *) alloca (16);
- CORE_ADDR ra, ps;
- struct argument_info
- {
- const bfd_byte *contents;
- int length;
- int onstack;
- int align;
- union
- {
- int offset;
- int regno;
- } u;
- };
- struct argument_info *arg_info =
- (struct argument_info *) alloca (nargs * sizeof (struct argument_info));
- CORE_ADDR osp = sp;
- DEBUGTRACE ("xtensa_push_dummy_call (...)\n");
- 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, "
- "struct_addr=0x%x\n",
- (int) sp, (int) struct_return, (int) struct_addr);
- for (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))
- {
- case TYPE_CODE_INT:
- fprintf_unfiltered (gdb_stdlog, "int");
- break;
- case TYPE_CODE_STRUCT:
- fprintf_unfiltered (gdb_stdlog, "struct");
- break;
- default:
- fprintf_unfiltered (gdb_stdlog, "%3d", TYPE_CODE (arg_type));
- break;
- }
- fprintf_unfiltered (gdb_stdlog, " %s\n",
- host_address_to_string (value_contents (arg)));
- }
- }
-
- size = 0;
- onstack_size = 0;
- i = 0;
- if (struct_return)
- size = REGISTER_SIZE;
- for (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))
- {
- case TYPE_CODE_INT:
- case TYPE_CODE_BOOL:
- case TYPE_CODE_CHAR:
- case TYPE_CODE_RANGE:
- case TYPE_CODE_ENUM:
-
- if (TYPE_LENGTH (arg_type)
- < TYPE_LENGTH (builtin_type (gdbarch)->builtin_long))
- {
- arg_type = builtin_type (gdbarch)->builtin_long;
- arg = value_cast (arg_type, arg);
- }
-
- info->align = TYPE_LENGTH (arg_type);
- break;
- case TYPE_CODE_FLT:
-
- 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 (gdbarch)->builtin_long);
- break;
- case TYPE_CODE_STRUCT:
- default:
- info->align = TYPE_LENGTH (builtin_type (gdbarch)->builtin_long);
- break;
- }
- info->length = TYPE_LENGTH (arg_type);
- info->contents = value_contents (arg);
-
- 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))
- {
- info->onstack = 1;
- info->u.offset = onstack_size;
- onstack_size += info->length;
- }
- else
- {
- info->onstack = 0;
- info->u.regno = ARG_1ST (gdbarch) + size / REGISTER_SIZE;
- }
- size += info->length;
- }
-
- sp = align_down (sp - onstack_size, SP_ALIGNMENT);
-
- if ((gdbarch_tdep (gdbarch)->call_abi != CallAbiCall0Only)
- && (sp != osp))
- {
- read_memory (osp - 16, buf, 16);
- write_memory (sp - 16, buf, 16);
- }
-
- if (struct_return)
- {
- store_unsigned_integer (buf, REGISTER_SIZE, byte_order, struct_addr);
- regcache_cooked_write (regcache, ARG_1ST (gdbarch), buf);
- }
- for (i = 0; i < nargs; i++)
- {
- struct argument_info *info = &arg_info[i];
- if (info->onstack)
- {
- int n = info->length;
- CORE_ADDR offset = sp + info->u.offset;
-
- if (n < REGISTER_SIZE
- && gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
- offset += (REGISTER_SIZE - n);
- write_memory (offset, info->contents, info->length);
- }
- else
- {
- int n = info->length;
- const bfd_byte *cp = info->contents;
- int r = info->u.regno;
-
- if (n < REGISTER_SIZE && byte_order == BFD_ENDIAN_BIG)
- {
- 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, byte_order, v);
- regcache_cooked_write (regcache, r, buf);
- cp += REGISTER_SIZE;
- n -= REGISTER_SIZE;
- r++;
- }
- else
- while (n > 0)
- {
- regcache_cooked_write (regcache, r, cp);
- cp += REGISTER_SIZE;
- n -= REGISTER_SIZE;
- r++;
- }
- }
- }
-
- if (gdbarch_tdep (gdbarch)->call_abi != CallAbiCall0Only)
- {
- ULONGEST val;
- ra = (bp_addr & 0x3fffffff) | 0x40000000;
- 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_cooked_write_unsigned (regcache,
- gdbarch_ps_regnum (gdbarch),
- ps | 0x00010000);
-
- 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
- {
-
- regcache_cooked_write_unsigned
- (regcache, gdbarch_tdep (gdbarch)->a0_base, bp_addr);
- }
-
- regcache_cooked_write_unsigned (regcache,
- gdbarch_tdep (gdbarch)->a0_base + 1, sp);
-
- return sp + SP_ALIGNMENT;
- }
- #define BIG_BREAKPOINT { 0x00, 0x04, 0x00 }
- #define LITTLE_BREAKPOINT { 0x00, 0x40, 0x00 }
- #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;
- DEBUGTRACE ("xtensa_breakpoint_from_pc (pc = 0x%08x)\n", (int) *pcptr);
- if (gdbarch_tdep (gdbarch)->isa_use_density_instructions)
- {
- if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
- {
- *lenptr = sizeof (density_big_breakpoint);
- return density_big_breakpoint;
- }
- else
- {
- *lenptr = sizeof (density_little_breakpoint);
- return density_little_breakpoint;
- }
- }
- else
- {
- if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
- {
- *lenptr = sizeof (big_breakpoint);
- return big_breakpoint;
- }
- else
- {
- *lenptr = sizeof (little_breakpoint);
- return little_breakpoint;
- }
- }
- }
- static int
- call0_ret (CORE_ADDR start_pc, CORE_ADDR finish_pc)
- {
- #define RETURN_RET goto done
- xtensa_isa isa;
- xtensa_insnbuf ins, slot;
- gdb_byte ibuf[XTENSA_ISA_BSZ];
- CORE_ADDR ia, bt, ba;
- xtensa_format ifmt;
- int ilen, islots, is;
- xtensa_opcode opc;
- const char *opcname;
- int found_ret = 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_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;
- if (target_read_memory (ba, ibuf, bt - ba) != 0 )
- RETURN_RET;
- }
- xtensa_insnbuf_from_chars (isa, ins, &ibuf[ia-ba], 0);
- ifmt = xtensa_format_decode (isa, ins);
- if (ifmt == XTENSA_UNDEFINED)
- RETURN_RET;
- ilen = xtensa_format_length (isa, ifmt);
- if (ilen == XTENSA_UNDEFINED)
- RETURN_RET;
- islots = xtensa_format_num_slots (isa, ifmt);
- if (islots == XTENSA_UNDEFINED)
- RETURN_RET;
- for (is = 0; is < islots; ++is)
- {
- if (xtensa_format_get_slot (isa, ifmt, is, ins, slot))
- RETURN_RET;
- opc = xtensa_opcode_decode (isa, ifmt, is, slot);
- if (opc == XTENSA_UNDEFINED)
- RETURN_RET;
- opcname = xtensa_opcode_name (isa, opc);
- if ((strcasecmp (opcname, "ret.n") == 0)
- || (strcasecmp (opcname, "ret") == 0))
- {
- found_ret = 1;
- RETURN_RET;
- }
- }
- }
- done:
- xtensa_insnbuf_free(isa, slot);
- xtensa_insnbuf_free(isa, ins);
- return found_ret;
- }
- typedef enum
- {
- c0opc_illegal,
- c0opc_uninteresting,
- c0opc_flow,
- c0opc_entry,
- c0opc_break,
- c0opc_add,
- c0opc_addi,
- c0opc_and,
- c0opc_sub,
- c0opc_mov,
- c0opc_movi,
- c0opc_l32r,
- c0opc_s32i,
- c0opc_rwxsr,
- c0opc_l32e,
- c0opc_s32e,
- c0opc_rfwo,
- c0opc_rfwu,
- c0opc_NrOf
- } xtensa_insn_kind;
- static int
- rwx_special_register (const char *opcname)
- {
- char ch = *opcname++;
- if ((ch != 'r') && (ch != 'w') && (ch != 'x'))
- return 0;
- if (*opcname++ != 's')
- return 0;
- if (*opcname++ != 'r')
- return 0;
- if (*opcname++ != '.')
- return 0;
- return 1;
- }
- static xtensa_insn_kind
- call0_classify_opcode (xtensa_isa isa, xtensa_opcode opc)
- {
- const char *opcname;
- xtensa_insn_kind opclass = c0opc_uninteresting;
- DEBUGTRACE ("call0_classify_opcode (..., opc = %d)\n", opc);
-
- opcname = xtensa_opcode_name (isa, opc);
- if (opcname == NULL
- || strcasecmp (opcname, "ill") == 0
- || strcasecmp (opcname, "ill.n") == 0)
- opclass = c0opc_illegal;
- else if (strcasecmp (opcname, "break") == 0
- || strcasecmp (opcname, "break.n") == 0)
- opclass = c0opc_break;
- else if (strcasecmp (opcname, "entry") == 0)
- opclass = c0opc_entry;
- else if (strcasecmp (opcname, "rfwo") == 0)
- opclass = c0opc_rfwo;
- else if (strcasecmp (opcname, "rfwu") == 0)
- opclass = c0opc_rfwu;
- else if (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)
- opclass = c0opc_flow;
-
- else if (strcasecmp (opcname, "add") == 0
- || strcasecmp (opcname, "add.n") == 0)
- opclass = c0opc_add;
- else if (strcasecmp (opcname, "and") == 0)
- opclass = c0opc_and;
- else if (strcasecmp (opcname, "addi") == 0
- || strcasecmp (opcname, "addi.n") == 0
- || strcasecmp (opcname, "addmi") == 0)
- opclass = c0opc_addi;
- else if (strcasecmp (opcname, "sub") == 0)
- opclass = c0opc_sub;
- else if (strcasecmp (opcname, "mov.n") == 0
- || strcasecmp (opcname, "or") == 0)
- opclass = c0opc_mov;
- else if (strcasecmp (opcname, "movi") == 0
- || strcasecmp (opcname, "movi.n") == 0)
- opclass = c0opc_movi;
- else if (strcasecmp (opcname, "l32r") == 0)
- opclass = c0opc_l32r;
- else if (strcasecmp (opcname, "s32i") == 0
- || strcasecmp (opcname, "s32i.n") == 0)
- opclass = c0opc_s32i;
- else if (strcasecmp (opcname, "l32e") == 0)
- opclass = c0opc_l32e;
- else if (strcasecmp (opcname, "s32e") == 0)
- opclass = c0opc_s32e;
- else if (rwx_special_register (opcname))
- opclass = c0opc_rwxsr;
- return opclass;
- }
- static int
- 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, xtensa_frame_cache_t *cache)
- {
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- unsigned litbase, litaddr, litval;
- switch (opclass)
- {
- case c0opc_addi:
-
- gdb_assert (nods == 3);
- dst[odv[0]].fr_reg = src[odv[1]].fr_reg;
- dst[odv[0]].fr_ofs = src[odv[1]].fr_ofs + odv[2];
- break;
- case c0opc_add:
-
- 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 dst[odv[0]].fr_reg = C0_INEXP;
- break;
- case c0opc_and:
-
- gdb_assert (nods == 3);
- if (cache->c0.c0_fpalign == 0)
- {
-
- if ((src[odv[0]].fr_reg == spreg) && (src[odv[1]].fr_reg == spreg))
- {
- if (src[odv[2]].fr_reg == C0_CONST)
- cache->c0.c0_fpalign = src[odv[2]].fr_ofs;
- break;
- }
- else if ((src[odv[0]].fr_reg == spreg)
- && (src[odv[2]].fr_reg == spreg))
- {
- if (src[odv[1]].fr_reg == C0_CONST)
- cache->c0.c0_fpalign = src[odv[1]].fr_ofs;
- break;
- }
-
- }
- 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 dst[odv[0]].fr_reg = C0_INEXP;
- break;
- case c0opc_sub:
-
- 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;
- }
- else dst[odv[0]].fr_reg = C0_INEXP;
- break;
- case c0opc_mov:
-
- gdb_assert (nods == 2);
-
- if ((odv[1] == spreg) && (cache->c0.c0_old_sp == C0_INEXP))
- cache->c0.c0_old_sp = odv[0];
- dst[odv[0]].fr_reg = src[odv[1]].fr_reg;
- dst[odv[0]].fr_ofs = src[odv[1]].fr_ofs;
- break;
- case c0opc_movi:
-
- gdb_assert (nods == 2);
- dst[odv[0]].fr_reg = C0_CONST;
- dst[odv[0]].fr_ofs = odv[1];
- break;
- case c0opc_l32r:
-
- gdb_assert (nods == 2);
-
- litbase = (gdbarch_tdep (gdbarch)->litbase_regnum == -1)
- ? 0 : xtensa_read_register
- (gdbarch_tdep (gdbarch)->litbase_regnum);
- litaddr = litbase & 1
- ? (litbase & ~1) + (signed)odv[1]
- : (pc + 3 + (signed)odv[1]) & ~3;
- litval = read_memory_integer (litaddr, 4, byte_order);
- dst[odv[0]].fr_reg = C0_CONST;
- dst[odv[0]].fr_ofs = litval;
- break;
- case c0opc_s32i:
-
- gdb_assert (nods == 3 && spreg >= 0 && spreg < C0_NREGS);
-
- if ((cache->c0.c0_fpalign != 0)
- && (odv[1] == spreg)
- && (odv[0] == cache->c0.c0_old_sp))
- cache->c0.c0_sp_ofs = odv[2];
- if (src[odv[1]].fr_reg == spreg
- && (src[odv[1]].fr_ofs & 3) == 0
- && src[odv[0]].fr_reg >= 0
- && src[odv[0]].fr_ofs == 0
- && src[src[odv[0]].fr_reg].to_stk == C0_NOSTK)
- {
-
- gdb_assert ((odv[2] & 3) == 0);
- dst[src[odv[0]].fr_reg].to_stk = src[odv[1]].fr_ofs + odv[2];
- }
- break;
-
- case c0opc_l32e:
- case c0opc_s32e:
- case c0opc_rfwo:
- case c0opc_rfwu:
- return 1;
- default:
- return 1;
- }
- return 0;
- }
- static CORE_ADDR
- call0_analyze_prologue (struct gdbarch *gdbarch,
- CORE_ADDR start, CORE_ADDR pc,
- int nregs, xtensa_frame_cache_t *cache)
- {
- CORE_ADDR ia;
- CORE_ADDR ba = 0;
- CORE_ADDR bt;
- gdb_byte ibuf[XTENSA_ISA_BSZ];
- xtensa_isa isa;
- xtensa_insnbuf ins, slot;
- xtensa_format ifmt;
- int ilen, islots, is;
- xtensa_opcode opc;
- xtensa_insn_kind opclass;
- int nods;
- unsigned odv[C0_MAXOPDS];
- xtensa_c0reg_t *rtmp;
- int j;
- int fail = 0;
- CORE_ADDR body_pc;
- CORE_ADDR end_pc;
- struct symtab_and_line prologue_sal;
- DEBUGTRACE ("call0_analyze_prologue (start = 0x%08x, pc = 0x%08x, ...)\n",
- (int)start, (int)pc);
-
- rtmp = NULL;
- body_pc = UINT_MAX;
- end_pc = 0;
-
- prologue_sal = find_pc_line (start, 0);
- if (prologue_sal.line != 0)
- body_pc = prologue_sal.end;
-
- if (pc == 0)
- {
- find_pc_partial_function (start, 0, NULL, &end_pc);
- body_pc = min (end_pc, body_pc);
- }
- else
- body_pc = 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);
- slot = xtensa_insnbuf_alloc (isa);
- for (ia = start, bt = ia; ia < body_pc ; ia += ilen)
- {
-
- 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 )
- error (_("Unable to read target memory ..."));
- }
-
- xtensa_insnbuf_from_chars (isa, ins, &ibuf[ia-ba], 0);
- ifmt = xtensa_format_decode (isa, ins);
- if (ifmt == XTENSA_UNDEFINED)
- {
- fail = 1;
- goto done;
- }
- ilen = xtensa_format_length (isa, ifmt);
- if (ilen == XTENSA_UNDEFINED)
- {
- fail = 1;
- goto done;
- }
- islots = xtensa_format_num_slots (isa, ifmt);
- if (islots == XTENSA_UNDEFINED)
- {
- fail = 1;
- goto done;
- }
-
- for (j = 0; j < nregs; ++j)
- rtmp[j] = cache->c0.c0_rt[j];
- for (is = 0; is < islots; ++is)
- {
-
- fail = xtensa_format_get_slot (isa, ifmt, is, ins, slot);
- if (fail)
- goto done;
- opc = xtensa_opcode_decode (isa, ifmt, is, slot);
- DEBUGVERB ("[call0_analyze_prologue] instr addr = 0x%08x, opc = %d\n",
- (unsigned)ia, opc);
- if (opc == XTENSA_UNDEFINED)
- opclass = c0opc_illegal;
- else
- opclass = call0_classify_opcode (isa, opc);
-
- switch (opclass)
- {
- case c0opc_illegal:
- case c0opc_break:
- fail = 1;
- goto done;
- case c0opc_uninteresting:
- continue;
- case c0opc_flow:
- case c0opc_rwxsr:
- goto done;
- case c0opc_entry:
- cache->call0 = 0;
- ia += ilen;
- goto done;
- default:
- cache->call0 = 1;
- }
-
-
- nods = xtensa_opcode_num_operands (isa, opc);
- if (nods == XTENSA_UNDEFINED)
- {
- fail = 1;
- goto done;
- }
- for (j = 0; j < nods && j < C0_MAXOPDS; ++j)
- {
- fail = xtensa_operand_get_field (isa, opc, j, ifmt,
- is, slot, &odv[j]);
- if (fail)
- goto done;
- fail = xtensa_operand_decode (isa, opc, j, &odv[j]);
- if (fail)
- goto done;
- }
-
- if (opclass == c0opc_mov && nods == 3)
- {
- if (odv[2] == odv[1])
- {
- nods = 2;
- if ((odv[0] == 1) && (odv[1] != 1))
-
- goto done;
- }
- else
- {
- opclass = c0opc_uninteresting;
- continue;
- }
- }
-
- fail = call0_track_op (gdbarch, cache->c0.c0_rt, rtmp,
- opclass, nods, odv, ia, 1, cache);
- if (fail)
- goto done;
- }
- }
- done:
- DEBUGVERB ("[call0_analyze_prologue] stopped at instr addr 0x%08x, %s\n",
- (unsigned)ia, fail ? "failed" : "succeeded");
- xtensa_insnbuf_free(isa, slot);
- xtensa_insnbuf_free(isa, ins);
- return fail ? XTENSA_ISA_BADPC : ia;
- }
- static void
- call0_frame_cache (struct frame_info *this_frame,
- xtensa_frame_cache_t *cache, CORE_ADDR pc)
- {
- struct gdbarch *gdbarch = get_frame_arch (this_frame);
- enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- CORE_ADDR start_pc;
- CORE_ADDR body_pc=UINT_MAX;
- CORE_ADDR sp, fp, ra;
- int fp_regnum = C0_SP, c0_hasfp = 0, c0_frmsz = 0, prev_sp = 0, to_stk;
- sp = get_frame_register_unsigned
- (this_frame, gdbarch_tdep (gdbarch)->a0_base + 1);
- fp = sp;
-
- if (find_pc_partial_function (pc, NULL, &start_pc, NULL))
- {
- body_pc = call0_analyze_prologue (gdbarch, start_pc, pc, C0_NREGS, cache);
- if (body_pc == XTENSA_ISA_BADPC)
- {
- warning_once ();
- ra = 0;
- goto finish_frame_analysis;
- }
- }
-
- if (body_pc <= pc)
- {
-
- c0_hasfp = cache->c0.c0_rt[C0_FP].fr_reg == C0_SP;
-
- 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;
- }
- else
- {
- c0_hasfp = 0;
- fp_regnum = gdbarch_tdep (gdbarch)->a0_base + C0_SP;
- c0_frmsz = 0;
- start_pc = pc;
- }
- if (cache->c0.c0_fpalign)
- {
-
- CORE_ADDR unaligned_sp;
- if (cache->c0.c0_old_sp == C0_INEXP)
-
- {
- warning_once ();
- ra = 0;
- goto finish_frame_analysis;
- }
- if (cache->c0.c0_sp_ofs == C0_NOSTK)
-
- unaligned_sp = get_frame_register_unsigned
- (this_frame, gdbarch_tdep (gdbarch)->a0_base + cache->c0.c0_old_sp);
- else
-
- unaligned_sp = (CORE_ADDR)
- read_memory_integer (fp + cache->c0.c0_sp_ofs, 4, byte_order);
- prev_sp = unaligned_sp + c0_frmsz;
- }
- else
- prev_sp = fp + c0_frmsz;
-
- if (c0_hasfp)
- {
- fp = get_frame_register_unsigned (this_frame, fp_regnum);
-
- c0_frmsz += fp - sp;
- }
-
- 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, byte_order);
- else if (cache->c0.c0_rt[C0_RA].fr_reg == C0_CONST
- && cache->c0.c0_rt[C0_RA].fr_ofs == 0)
- {
-
- ra = 0;
- }
- else
- {
-
- int i;
- for (i = 0;
- (i < C0_NREGS)
- && (i == C0_RA || cache->c0.c0_rt[i].fr_reg != C0_RA);
- ++i);
- if (i >= C0_NREGS && cache->c0.c0_rt[C0_RA].fr_reg == C0_RA)
- i = C0_RA;
- if (i < C0_NREGS)
- {
- ra = get_frame_register_unsigned
- (this_frame,
- gdbarch_tdep (gdbarch)->a0_base + cache->c0.c0_rt[i].fr_reg);
- }
- else ra = 0;
- }
- finish_frame_analysis:
- cache->pc = start_pc;
- cache->ra = ra;
-
- cache->prev_sp = (ra != 0) ? prev_sp : 0;
- cache->c0.fp_regnum = fp_regnum;
- cache->c0.c0_frmsz = c0_frmsz;
- cache->c0.c0_hasfp = c0_hasfp;
- cache->c0.c0_fp = fp;
- }
- static CORE_ADDR a0_saved;
- static CORE_ADDR a7_saved;
- static CORE_ADDR a11_saved;
- static int a0_was_saved;
- static int a7_was_saved;
- static int a11_was_saved;
- 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);
- CORE_ADDR addr = xtensa_read_register (asreg) + offset;
- unsigned int spilled_value
- = read_memory_unsigned_integer (addr, 4, gdbarch_byte_order (gdbarch));
- if ((at == 0) && !a0_was_saved)
- {
- a0_saved = xtensa_read_register (atreg);
- a0_was_saved = 1;
- }
- else if ((at == 7) && !a7_was_saved)
- {
- a7_saved = xtensa_read_register (atreg);
- a7_was_saved = 1;
- }
- else if ((at == 11) && !a11_was_saved)
- {
- a11_saved = xtensa_read_register (atreg);
- a11_was_saved = 1;
- }
- xtensa_write_register (atreg, spilled_value);
- }
- 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);
- CORE_ADDR addr = xtensa_read_register (asreg) + offset;
- ULONGEST spilled_value = xtensa_read_register (atreg);
- write_memory_unsigned_integer (addr, 4,
- gdbarch_byte_order (gdbarch),
- spilled_value);
- }
- #define XTENSA_MAX_WINDOW_INTERRUPT_HANDLER_LEN 200
- typedef enum
- {
- xtWindowOverflow,
- xtWindowUnderflow,
- xtNoExceptionHandler
- } xtensa_exception_handler_t;
- static xtensa_exception_handler_t
- execute_code (struct gdbarch *gdbarch, CORE_ADDR current_pc, CORE_ADDR wb)
- {
- xtensa_isa isa;
- xtensa_insnbuf ins, slot;
- gdb_byte ibuf[XTENSA_ISA_BSZ];
- CORE_ADDR ia, bt, ba;
- xtensa_format ifmt;
- int ilen, islots, is;
- xtensa_opcode opc;
- int insn_num = 0;
- int fail = 0;
- void (*func) (struct gdbarch *, int, int, int, CORE_ADDR);
- uint32_t at, as, offset;
-
- int WindowUnderflow12 = (current_pc & 0x1ff) >= 0x140;
- 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;
- ia = current_pc;
- bt = ia;
- a0_was_saved = 0;
- a7_was_saved = 0;
- a11_was_saved = 0;
- 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)
- return xtNoExceptionHandler;
- }
- xtensa_insnbuf_from_chars (isa, ins, &ibuf[ia-ba], 0);
- ifmt = xtensa_format_decode (isa, ins);
- if (ifmt == XTENSA_UNDEFINED)
- return xtNoExceptionHandler;
- ilen = xtensa_format_length (isa, ifmt);
- if (ilen == XTENSA_UNDEFINED)
- return xtNoExceptionHandler;
- islots = xtensa_format_num_slots (isa, ifmt);
- if (islots == XTENSA_UNDEFINED)
- return xtNoExceptionHandler;
- for (is = 0; is < islots; ++is)
- {
- if (xtensa_format_get_slot (isa, ifmt, is, ins, slot))
- return xtNoExceptionHandler;
- opc = xtensa_opcode_decode (isa, ifmt, is, slot);
- if (opc == XTENSA_UNDEFINED)
- return xtNoExceptionHandler;
- switch (call0_classify_opcode (isa, opc))
- {
- case c0opc_illegal:
- case c0opc_flow:
- case c0opc_entry:
- case c0opc_break:
-
- return xtNoExceptionHandler;
- case c0opc_l32e:
- func = execute_l32e;
- break;
- case c0opc_s32e:
- func = execute_s32e;
- break;
- case c0opc_rfwo:
-
- if (a0_was_saved)
- {
- int arreg = arreg_number (gdbarch,
- gdbarch_tdep (gdbarch)->a0_base,
- wb);
- xtensa_write_register (arreg, a0_saved);
- }
- return xtWindowOverflow;
- case c0opc_rfwu:
-
- if (WindowUnderflow12)
- {
- if (a11_was_saved)
- {
- int arreg = arreg_number (gdbarch,
- gdbarch_tdep (gdbarch)->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,
- wb);
- xtensa_write_register (arreg, a7_saved);
- }
- return xtWindowUnderflow;
- default:
- continue;
- }
-
- if ( xtensa_opcode_num_operands (isa, opc) != 3 )
- return xtNoExceptionHandler;
- if (xtensa_operand_get_field (isa, opc, 0, ifmt, is, slot, &at))
- return xtNoExceptionHandler;
- if (xtensa_operand_decode (isa, opc, 0, &at))
- return xtNoExceptionHandler;
- if (xtensa_operand_get_field (isa, opc, 1, ifmt, is, slot, &as))
- return xtNoExceptionHandler;
- if (xtensa_operand_decode (isa, opc, 1, &as))
- return xtNoExceptionHandler;
- if (xtensa_operand_get_field (isa, opc, 2, ifmt, is, slot, &offset))
- return xtNoExceptionHandler;
- if (xtensa_operand_decode (isa, opc, 2, &offset))
- return xtNoExceptionHandler;
- (*func) (gdbarch, at, as, offset, wb);
- }
- ia += ilen;
- }
- return xtNoExceptionHandler;
- }
- static void
- xtensa_window_interrupt_frame_cache (struct frame_info *this_frame,
- xtensa_frame_cache_t *cache,
- CORE_ADDR pc)
- {
- struct gdbarch *gdbarch = get_frame_arch (this_frame);
- CORE_ADDR ps, wb, ws, ra;
- int epc1_regnum, i, regnum;
- xtensa_exception_handler_t eh_type;
-
- 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);
-
- eh_type = execute_code (gdbarch, pc, wb);
- if (eh_type == xtNoExceptionHandler)
- error (_("\
- Unable to decode Xtensa Window Interrupt Handler's code."));
- cache->ps = ps ^ PS_EXC;
- cache->call0 = 0;
-
- for (i = 0; i < XTENSA_NUM_SAVED_AREGS; i++)
- cache->wd.aregs[i] = -1;
- if (eh_type == xtWindowOverflow)
- cache->wd.ws = ws ^ (1 << wb);
- else
- cache->wd.ws = ws | (1 << wb);
- cache->wd.wb = (ps & 0xf00) >> 8;
- regnum = arreg_number (gdbarch, gdbarch_tdep (gdbarch)->a0_base,
- cache->wd.wb);
- ra = xtensa_read_register (regnum);
- cache->wd.callsize = WINSIZE (ra);
- cache->prev_sp = xtensa_read_register (regnum + 1);
-
- regnum = xtensa_scan_prologue (gdbarch, pc);
- regnum = arreg_number (gdbarch,
- gdbarch_tdep (gdbarch)->a0_base + regnum,
- cache->wd.wb);
- cache->base = get_frame_register_unsigned (this_frame, regnum);
-
- epc1_regnum = xtensa_find_register_by_name (gdbarch,"epc1");
- if (epc1_regnum < 0)
- error(_("Unable to read Xtensa register EPC1"));
- cache->ra = xtensa_read_register (epc1_regnum);
- cache->pc = get_frame_func (this_frame);
- }
- static CORE_ADDR
- xtensa_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
- {
- struct symtab_and_line prologue_sal;
- CORE_ADDR body_pc;
- DEBUGTRACE ("xtensa_skip_prologue (start_pc = 0x%08x)\n", (int) start_pc);
- #if DONT_SKIP_PROLOGUE
- return start_pc;
- #endif
-
- prologue_sal = find_pc_line (start_pc, 0);
- if (prologue_sal.line != 0)
- {
-
- CORE_ADDR end_func;
- if ((gdbarch_tdep (gdbarch)->call_abi == CallAbiCall0Only)
- && call0_ret (start_pc, prologue_sal.end))
- return start_pc;
- find_pc_partial_function (prologue_sal.end, NULL, &end_func, NULL);
- if (end_func != start_pc)
- return start_pc;
- return prologue_sal.end;
- }
-
- body_pc = call0_analyze_prologue (gdbarch, start_pc, 0, 0,
- xtensa_alloc_frame_cache (0));
- return body_pc != 0 ? body_pc : 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);
-
- if ((tdep->num_aregs & -tdep->num_aregs) != tdep->num_aregs)
- fprintf_unfiltered (log, _("\
- \n\tnum_aregs: Number of AR registers (%d) is not a power of two!"),
- tdep->num_aregs);
-
- if (tdep->pc_regnum == -1)
- fprintf_unfiltered (log, _("\n\tpc_regnum: No PC register"));
- if (tdep->isa_use_exceptions && tdep->ps_regnum == -1)
- fprintf_unfiltered (log, _("\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"));
- if (tdep->ws_regnum == -1)
- fprintf_unfiltered (log, _("\n\tws_regnum: No WS register"));
- if (tdep->ar_base == -1)
- fprintf_unfiltered (log, _("\n\tar_base: No AR registers"));
- }
- if (tdep->a0_base == -1)
- fprintf_unfiltered (log, _("\n\ta0_base: No Ax registers"));
- buf = ui_file_xstrdup (log, &length);
- make_cleanup (xfree, buf);
- if (length > 0)
- internal_error (__FILE__, __LINE__,
- _("the following are invalid: %s"), buf);
- do_cleanups (cleanups);
- }
- 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;
- #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
- #endif
- if (rmap->byte_size > max_size)
- max_size = rmap->byte_size;
- if (rmap->mask != 0 && tdep->num_regs == 0)
- tdep->num_regs = n;
-
- if ((rmap->flags & XTENSA_REGISTER_FLAGS_PRIVILEGED) != 0
- && tdep->num_regs == 0)
- tdep->num_regs = n;
- }
-
- tdep->num_pseudo_regs = n - tdep->num_regs;
-
- tdep->max_register_raw_size = max_size;
- tdep->max_register_virtual_size = max_size;
- }
- extern struct 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");
-
- info.byte_order = XCHAL_HAVE_BE ? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE;
- tdep = &xtensa_tdep;
- gdbarch = gdbarch_alloc (&info, tdep);
- xtensa_derive_tdep (tdep);
-
- xtensa_verify_config (gdbarch);
- xtensa_session_once_reported = 0;
-
- set_gdbarch_pseudo_register_read (gdbarch, xtensa_pseudo_register_read);
- set_gdbarch_pseudo_register_write (gdbarch, xtensa_pseudo_register_write);
-
- set_gdbarch_num_regs (gdbarch, tdep->num_regs);
- set_gdbarch_num_pseudo_regs (gdbarch, tdep->num_pseudo_regs);
- set_gdbarch_sp_regnum (gdbarch, tdep->a0_base + 1);
- set_gdbarch_pc_regnum (gdbarch, tdep->pc_regnum);
- set_gdbarch_ps_regnum (gdbarch, tdep->ps_regnum);
-
- set_gdbarch_stab_reg_to_regnum (gdbarch, xtensa_reg_to_regnum);
- set_gdbarch_dwarf2_reg_to_regnum (gdbarch, xtensa_reg_to_regnum);
-
- set_gdbarch_register_name (gdbarch, xtensa_register_name);
- set_gdbarch_register_type (gdbarch, xtensa_register_type);
-
- set_gdbarch_push_dummy_call (gdbarch, xtensa_push_dummy_call);
- set_gdbarch_believe_pcc_promotion (gdbarch, 1);
- set_gdbarch_return_value (gdbarch, xtensa_return_value);
-
- set_gdbarch_skip_prologue (gdbarch, xtensa_skip_prologue);
-
- set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
-
- set_gdbarch_breakpoint_from_pc (gdbarch, xtensa_breakpoint_from_pc);
-
- set_gdbarch_decr_pc_after_break (gdbarch, 0);
-
- set_gdbarch_frame_args_skip (gdbarch, 0);
- set_gdbarch_unwind_pc (gdbarch, xtensa_unwind_pc);
- set_gdbarch_frame_align (gdbarch, xtensa_frame_align);
- set_gdbarch_dummy_id (gdbarch, xtensa_dummy_id);
-
- frame_base_set_default (gdbarch, &xtensa_frame_base);
- 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_gdbarch_register_reggroup_p (gdbarch, xtensa_register_reggroup_p);
- set_gdbarch_iterate_over_regset_sections
- (gdbarch, xtensa_iterate_over_regset_sections);
- set_solib_svr4_fetch_link_map_offsets
- (gdbarch, svr4_ilp32_fetch_link_map_offsets);
- return gdbarch;
- }
- static void
- xtensa_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
- {
- error (_("xtensa_dump_tdep(): not implemented"));
- }
- extern initialize_file_ftype _initialize_xtensa_tdep;
- void
- _initialize_xtensa_tdep (void)
- {
- struct cmd_list_element *c;
- gdbarch_register (bfd_arch_xtensa, xtensa_gdbarch_init, xtensa_dump_tdep);
- xtensa_init_reggroups ();
- add_setshow_zuinteger_cmd ("xtensa",
- class_maintenance,
- &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,
- NULL,
- &setdebuglist, &showdebuglist);
- }