/* Target-dependent code for the Xtensa port of GDB, the GNU debugger.
- Copyright (C) 2003, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2005, 2006, 2007, 2008, 2009, 2010
+ Free Software Foundation, Inc.
This file is part of GDB.
#include "regset.h"
#include "dummy-frame.h"
-#include "elf/dwarf2.h"
+#include "dwarf2.h"
#include "dwarf2-frame.h"
#include "dwarf2loc.h"
#include "frame.h"
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];
/* 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 (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. */
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 (gdbarch)->ar_base
- && regnum < gdbarch_tdep (gdbarch)->ar_base
- + gdbarch_tdep (gdbarch)->num_aregs)
- || (regnum >= gdbarch_tdep (gdbarch)->a0_base
- && regnum < gdbarch_tdep (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 (gdbarch)
- || regnum == gdbarch_tdep (gdbarch)->a0_base + 1)
- return lookup_pointer_type (builtin_type_void);
+ || 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 (gdbarch)
+ gdbarch_num_pseudo_regs (gdbarch))
{
- xtensa_register_t* reg = &gdbarch_tdep (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;
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));
regcache_raw_read (regcache, gdbarch_tdep (gdbarch)->wb_regnum, buf);
regnum = arreg_number (gdbarch, regnum,
- extract_unsigned_integer (buf, 4));
+ extract_unsigned_integer (buf, 4, byte_order));
}
/* We can always read non-pseudo registers. */
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));
regcache_raw_read (regcache,
gdbarch_tdep (gdbarch)->wb_regnum, buf);
regnum = arreg_number (gdbarch, regnum,
- extract_unsigned_integer (buf, 4));
+ extract_unsigned_integer (buf, 4, byte_order));
}
/* We can always write 'core' registers.
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 (without CALLINC). */
- CORE_ADDR ps; /* The PS register of the previous frame. */
+ 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
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 (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;
}
/* 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_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)
ba = ia;
bt = (ba + XTENSA_ISA_BSZ) < current_pc
? ba + XTENSA_ISA_BSZ : current_pc;
- read_memory (ba, ibuf, bt - ba);
+ if (target_read_memory (ba, ibuf, bt - ba) != 0)
+ RETURN_FP;
}
xtensa_insnbuf_from_chars (isa, ins, &ibuf[ia-ba], 0);
static void
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 *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);
- unsigned int ps_regnum = gdbarch_ps_regnum (gdbarch);
+ enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
unsigned int fp_regnum;
char op1;
int windowed;
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 = get_frame_register_unsigned (this_frame,
- gdbarch_pc_regnum (gdbarch));
+ pc = get_frame_register_unsigned (this_frame, gdbarch_pc_regnum (gdbarch));
if (windowed)
{
gdbarch_tdep (gdbarch)->wb_regnum);
ws = get_frame_register_unsigned (this_frame,
gdbarch_tdep (gdbarch)->ws_regnum);
- ps = get_frame_register_unsigned (this_frame, ps_regnum);
- op1 = read_memory_integer (pc, 1);
+ op1 = read_memory_integer (pc, 1, byte_order);
if (XTENSA_IS_ENTRY (gdbarch, op1))
{
int callinc = CALLINC (ps);
cache->wd.ws = ws & ~(1 << wb);
cache->pc = get_frame_func (this_frame);
- cache->ra = (cache->pc & 0xc0000000) | (ra & 0x3fffffff);
+ cache->ra = (pc & 0xc0000000) | (ra & 0x3fffffff);
cache->ps = (ps & ~PS_CALLINC_MASK)
| ((WINSIZE(ra)/4) << PS_CALLINC_SHIFT);
}
/* Set A4...A7/A11. */
/* 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);
- sp = (CORE_ADDR) read_memory_integer (sp - 12, 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)
We can read caller's SP from the proper spill loction. */
sp = get_frame_register_unsigned
(this_frame, gdbarch_tdep (gdbarch)->a0_base + 1);
- cache->prev_sp = read_memory_integer (sp - 12, 4);
+ cache->prev_sp = read_memory_integer (sp - 12, 4, byte_order);
}
else
{
(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 (this_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;
}
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);
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);
if (struct_return)
{
- store_unsigned_integer (buf, REGISTER_SIZE, struct_addr);
+ store_unsigned_integer (buf, REGISTER_SIZE, byte_order, struct_addr);
regcache_cooked_write (regcache, ARG_1ST (gdbarch), buf);
}
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 (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;
{
ra = (bp_addr & 0x3fffffff) | 0x40000000;
regcache_raw_read (regcache, gdbarch_ps_regnum (gdbarch), buf);
- ps = extract_unsigned_integer (buf, 4) & ~0x00030000;
+ ps = extract_unsigned_integer (buf, 4, byte_order) & ~0x00030000;
regcache_cooked_write_unsigned
(regcache, gdbarch_tdep (gdbarch)->a0_base + 4, ra);
regcache_cooked_write_unsigned (regcache,
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));
+ regcache_cooked_write_unsigned
+ (regcache, gdbarch_tdep (gdbarch)->ws_regnum,
+ 1 << extract_unsigned_integer (buf, 4, byte_order));
}
else
{
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;
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. */
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. */
}
/* 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 in CALL0 ABI. */
static void
call0_frame_cache (struct frame_info *this_frame,
- xtensa_frame_cache_t *cache, CORE_ADDR pc)
+ 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 = get_frame_register_unsigned
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)
/* #define DONT_SKIP_PROLOGUE */
-CORE_ADDR
+static CORE_ADDR
xtensa_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc)
{
struct symtab_and_line prologue_sal;
}
/* 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. */
-void
+static void
xtensa_derive_tdep (struct gdbarch_tdep *tdep)
{
xtensa_register_t* rmap;
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)
{