2008-04-23 Maxim Grigoriev <maxim2405@gmail.com>
* Makefile.in (xtensa-tdep.o): Update dependencies. * configure.tgt (xtensa*): Update dependencies. * xtensa-tdep.c (arreg_number): Renamed from areg_number. Local variable areg renamed to arreg. (areg_number): New function. (xtensa_pseudo_register_read, xtensa_pseudo_register_write) (xtensa_extract_return_value, xtensa_store_return_value): areg_number replaced by arreg_number. (xtensa_windowed_frame_cache, struct xtensa_frame_cache): New comments. (xtensa_alloc_frame_cache): Initialize cache->wd.ws. (xtensa_scan_prologue): New function. (xtensa_frame_cache): New local fp_regnum. Handle separately the case, when ENTRY instraction hasn't been executed yet. Get the frame pointer value based on prologue analysis. Fix the bugs preventing WS and AR4-AR7/A11 registers from getting right values for intermediate frames, whose registers have been already spilled. (xtensa_frame_prev_register): Fix WS register value. Use are_number and arreg_number appropriately. (xtensa_gdbarch_init): Set solib_svr4_fetch_link_map_offsets to svr4_ilp32_fetch_link_map_offsets.
This commit is contained in:
parent
fe4fa32c96
commit
ee967b5f61
4 changed files with 226 additions and 48 deletions
|
@ -1,3 +1,26 @@
|
||||||
|
2008-04-23 Maxim Grigoriev <maxim2405@gmail.com>
|
||||||
|
|
||||||
|
* Makefile.in (xtensa-tdep.o): Update dependencies.
|
||||||
|
* configure.tgt (xtensa*): Update dependencies.
|
||||||
|
* xtensa-tdep.c (arreg_number): Renamed from areg_number.
|
||||||
|
Local variable areg renamed to arreg.
|
||||||
|
(areg_number): New function.
|
||||||
|
(xtensa_pseudo_register_read, xtensa_pseudo_register_write)
|
||||||
|
(xtensa_extract_return_value, xtensa_store_return_value): areg_number
|
||||||
|
replaced by arreg_number.
|
||||||
|
(xtensa_windowed_frame_cache, struct xtensa_frame_cache): New comments.
|
||||||
|
(xtensa_alloc_frame_cache): Initialize cache->wd.ws.
|
||||||
|
(xtensa_scan_prologue): New function.
|
||||||
|
(xtensa_frame_cache): New local fp_regnum. Handle separately the case,
|
||||||
|
when ENTRY instraction hasn't been executed yet. Get the frame pointer
|
||||||
|
value based on prologue analysis. Fix the bugs preventing WS and
|
||||||
|
AR4-AR7/A11 registers from getting right values for intermediate frames,
|
||||||
|
whose registers have been already spilled.
|
||||||
|
(xtensa_frame_prev_register): Fix WS register value. Use are_number
|
||||||
|
and arreg_number appropriately.
|
||||||
|
(xtensa_gdbarch_init): Set solib_svr4_fetch_link_map_offsets to
|
||||||
|
svr4_ilp32_fetch_link_map_offsets.
|
||||||
|
|
||||||
2008-04-23 Andrew Stubbs <andrew.stubbs@st.com>
|
2008-04-23 Andrew Stubbs <andrew.stubbs@st.com>
|
||||||
|
|
||||||
* printcmd.c: Define USE_PRINTF_I64 and PRINTF_HAS_LONG_LONG on MinGW.
|
* printcmd.c: Define USE_PRINTF_I64 and PRINTF_HAS_LONG_LONG on MinGW.
|
||||||
|
|
|
@ -3016,7 +3016,7 @@ xtensa-tdep.o: xtensa-tdep.c $(defs_h) $(doublest_h) $(frame_h) \
|
||||||
$(value_h) $(gdbcmd_h) $(gdbcore_h) $(dis_asm_h) $(symfile_h) \
|
$(value_h) $(gdbcmd_h) $(gdbcore_h) $(dis_asm_h) $(symfile_h) \
|
||||||
$(objfiles_h) $(gdb_string_h) $(linespec_h) $(regcache_h) \
|
$(objfiles_h) $(gdb_string_h) $(linespec_h) $(regcache_h) \
|
||||||
$(reggroups_h) $(arch_utils_h) $(osabi_h) $(block_h) $(gdb_assert_h) \
|
$(reggroups_h) $(arch_utils_h) $(osabi_h) $(block_h) $(gdb_assert_h) \
|
||||||
$(elf_bfd_h) $(xtensa_tdep_h) $(dwarf2_frame_h)
|
$(elf_bfd_h) $(xtensa_tdep_h) $(dwarf2_frame_h) $(solib_svr4_h)
|
||||||
xtensa-config.o: $(defs_h) $(xtensa_tdep_h)
|
xtensa-config.o: $(defs_h) $(xtensa_tdep_h)
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
@ -523,7 +523,7 @@ xtensa*-*-linux*) gdb_target=linux
|
||||||
;;
|
;;
|
||||||
xtensa*)
|
xtensa*)
|
||||||
# Target: Tensilica Xtensa processors
|
# Target: Tensilica Xtensa processors
|
||||||
gdb_target_obs="xtensa-tdep.o xtensa-config.o"
|
gdb_target_obs="xtensa-tdep.o xtensa-config.o solib.o solib-svr4.o"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
esac
|
esac
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include "defs.h"
|
#include "defs.h"
|
||||||
#include "frame.h"
|
#include "frame.h"
|
||||||
|
#include "solib-svr4.h"
|
||||||
#include "symtab.h"
|
#include "symtab.h"
|
||||||
#include "symfile.h"
|
#include "symfile.h"
|
||||||
#include "objfiles.h"
|
#include "objfiles.h"
|
||||||
|
@ -114,18 +115,33 @@ static int xtensa_debug_level = 0;
|
||||||
#define PS_WOE (1<<18)
|
#define PS_WOE (1<<18)
|
||||||
#define PS_EXC (1<<4)
|
#define PS_EXC (1<<4)
|
||||||
|
|
||||||
/* Convert a live Ax register number to the corresponding Areg number. */
|
/* Convert a live A-register number to the corresponding AR-register number. */
|
||||||
static int
|
static int
|
||||||
areg_number (struct gdbarch *gdbarch, int regnum, ULONGEST wb)
|
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);
|
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
||||||
int areg;
|
int areg;
|
||||||
|
|
||||||
areg = regnum - tdep->a0_base;
|
areg = ar_regnum - tdep->ar_base;
|
||||||
areg += (wb & ((tdep->num_aregs - 1) >> 2)) << WB_SHIFT;
|
if (areg < 0 || areg >= tdep->num_aregs)
|
||||||
areg &= tdep->num_aregs - 1;
|
return -1;
|
||||||
|
areg = (areg - wb * 4) & (tdep->num_aregs - 1);
|
||||||
return areg + tdep->ar_base;
|
return (areg > 15) ? -1 : areg;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int
|
static inline int
|
||||||
|
@ -516,7 +532,8 @@ xtensa_pseudo_register_read (struct gdbarch *gdbarch,
|
||||||
gdb_byte *buf = (gdb_byte *) alloca (MAX_REGISTER_SIZE);
|
gdb_byte *buf = (gdb_byte *) alloca (MAX_REGISTER_SIZE);
|
||||||
|
|
||||||
regcache_raw_read (regcache, gdbarch_tdep (gdbarch)->wb_regnum, buf);
|
regcache_raw_read (regcache, gdbarch_tdep (gdbarch)->wb_regnum, buf);
|
||||||
regnum = areg_number (gdbarch, regnum, extract_unsigned_integer (buf, 4));
|
regnum = arreg_number (gdbarch, regnum,
|
||||||
|
extract_unsigned_integer (buf, 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We can always read non-pseudo registers. */
|
/* We can always read non-pseudo registers. */
|
||||||
|
@ -613,7 +630,8 @@ xtensa_pseudo_register_write (struct gdbarch *gdbarch,
|
||||||
|
|
||||||
regcache_raw_read (regcache,
|
regcache_raw_read (regcache,
|
||||||
gdbarch_tdep (gdbarch)->wb_regnum, buf);
|
gdbarch_tdep (gdbarch)->wb_regnum, buf);
|
||||||
regnum = areg_number (gdbarch, regnum, extract_unsigned_integer (buf, 4));
|
regnum = arreg_number (gdbarch, regnum,
|
||||||
|
extract_unsigned_integer (buf, 4));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We can always write 'core' registers.
|
/* We can always write 'core' registers.
|
||||||
|
@ -880,9 +898,15 @@ xtensa_regset_from_core_section (struct gdbarch *core_arch,
|
||||||
/* Frame cache part for Windowed ABI. */
|
/* Frame cache part for Windowed ABI. */
|
||||||
typedef struct xtensa_windowed_frame_cache
|
typedef struct xtensa_windowed_frame_cache
|
||||||
{
|
{
|
||||||
int wb; /* Base for this frame; -1 if not in regfile. */
|
int wb; /* WINDOWBASE of the previous frame. */
|
||||||
int callsize; /* Call size to next frame. */
|
int callsize; /* Call size of this frame. */
|
||||||
int ws;
|
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];
|
CORE_ADDR aregs[XTENSA_NUM_SAVED_AREGS];
|
||||||
} xtensa_windowed_frame_cache_t;
|
} xtensa_windowed_frame_cache_t;
|
||||||
|
|
||||||
|
@ -932,11 +956,11 @@ typedef struct xtensa_call0_frame_cache
|
||||||
|
|
||||||
typedef struct xtensa_frame_cache
|
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 pc; /* PC at the entry point to the function. */
|
||||||
CORE_ADDR ra; /* The raw return address. */
|
CORE_ADDR ra; /* The raw return address (without CALLINC). */
|
||||||
CORE_ADDR ps; /* The PS register of the frame. */
|
CORE_ADDR ps; /* The PS register of the previous frame. */
|
||||||
CORE_ADDR prev_sp; /* Stack Pointer of the frame. */
|
CORE_ADDR prev_sp; /* Stack Pointer of the previous frame. */
|
||||||
int call0; /* It's a call0 framework (else windowed). */
|
int call0; /* It's a call0 framework (else windowed). */
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
|
@ -979,6 +1003,7 @@ xtensa_alloc_frame_cache (int windowed)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
cache->wd.wb = 0;
|
cache->wd.wb = 0;
|
||||||
|
cache->wd.ws = 0;
|
||||||
cache->wd.callsize = -1;
|
cache->wd.callsize = -1;
|
||||||
|
|
||||||
for (i = 0; i < XTENSA_NUM_SAVED_AREGS; i++)
|
for (i = 0; i < XTENSA_NUM_SAVED_AREGS; i++)
|
||||||
|
@ -1028,9 +1053,126 @@ xtensa_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame)
|
||||||
return frame_id_build (fp + SP_ALIGNMENT, pc);
|
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. */
|
||||||
|
|
||||||
|
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;
|
||||||
|
read_memory (ba, ibuf, bt - ba);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
/* 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->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.
|
||||||
*/
|
*/
|
||||||
|
@ -1047,6 +1189,7 @@ xtensa_frame_cache (struct frame_info *next_frame, void **this_cache)
|
||||||
CORE_ADDR ra, wb, ws, pc, sp, ps;
|
CORE_ADDR ra, wb, ws, pc, sp, ps;
|
||||||
struct gdbarch *gdbarch = get_frame_arch (next_frame);
|
struct gdbarch *gdbarch = get_frame_arch (next_frame);
|
||||||
unsigned int ps_regnum = gdbarch_ps_regnum (gdbarch);
|
unsigned int ps_regnum = gdbarch_ps_regnum (gdbarch);
|
||||||
|
unsigned int fp_regnum;
|
||||||
char op1;
|
char op1;
|
||||||
int windowed;
|
int windowed;
|
||||||
|
|
||||||
|
@ -1090,21 +1233,35 @@ xtensa_frame_cache (struct frame_info *next_frame, void **this_cache)
|
||||||
cache->wd.ws = ws;
|
cache->wd.ws = ws;
|
||||||
cache->prev_sp = frame_unwind_register_unsigned
|
cache->prev_sp = frame_unwind_register_unsigned
|
||||||
(next_frame, gdbarch_tdep (gdbarch)->a0_base + 1);
|
(next_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
|
else
|
||||||
{
|
{
|
||||||
|
fp_regnum = xtensa_scan_prologue (gdbarch, pc);
|
||||||
ra = frame_unwind_register_unsigned
|
ra = frame_unwind_register_unsigned
|
||||||
(next_frame, gdbarch_tdep (gdbarch)->a0_base);
|
(next_frame, gdbarch_tdep (gdbarch)->a0_base);
|
||||||
cache->wd.callsize = WINSIZE (ra);
|
cache->wd.callsize = WINSIZE (ra);
|
||||||
cache->wd.wb = (wb - cache->wd.callsize / 4)
|
cache->wd.wb = (wb - cache->wd.callsize / 4)
|
||||||
& (gdbarch_tdep (gdbarch)->num_aregs / 4 - 1);
|
& (gdbarch_tdep (gdbarch)->num_aregs / 4 - 1);
|
||||||
cache->wd.ws = ws & ~(1 << wb);
|
cache->wd.ws = ws & ~(1 << wb);
|
||||||
}
|
|
||||||
|
|
||||||
cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME);
|
cache->pc = frame_func_unwind (next_frame, NORMAL_FRAME);
|
||||||
cache->ra = (cache->pc & 0xc0000000) | (ra & 0x3fffffff);
|
cache->ra = (cache->pc & 0xc0000000) | (ra & 0x3fffffff);
|
||||||
cache->ps = (ps & ~PS_CALLINC_MASK)
|
cache->ps = (ps & ~PS_CALLINC_MASK)
|
||||||
| ((WINSIZE(ra)/4) << PS_CALLINC_SHIFT);
|
| ((WINSIZE(ra)/4) << PS_CALLINC_SHIFT);
|
||||||
|
}
|
||||||
|
|
||||||
if (cache->wd.ws == 0)
|
if (cache->wd.ws == 0)
|
||||||
{
|
{
|
||||||
|
@ -1122,12 +1279,13 @@ xtensa_frame_cache (struct frame_info *next_frame, void **this_cache)
|
||||||
if (cache->wd.callsize > 4)
|
if (cache->wd.callsize > 4)
|
||||||
{
|
{
|
||||||
/* Set A4...A7/A11. */
|
/* Set A4...A7/A11. */
|
||||||
/* Read an SP of the previous frame. */
|
/* 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);
|
sp = (CORE_ADDR) read_memory_integer (sp - 12, 4);
|
||||||
sp -= cache->wd.callsize * 4;
|
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;
|
cache->wd.aregs[i] = sp;
|
||||||
}
|
}
|
||||||
|
@ -1138,19 +1296,18 @@ xtensa_frame_cache (struct frame_info *next_frame, void **this_cache)
|
||||||
/* If RA is equal to 0 this frame is an outermost frame. Leave
|
/* If RA is equal to 0 this frame is an outermost frame. Leave
|
||||||
cache->prev_sp unchanged marking the boundary of the frame stack. */
|
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.
|
/* Register window overflow already happened.
|
||||||
We can read caller's SP from the proper spill loction. */
|
We can read caller's SP from the proper spill loction. */
|
||||||
cache->prev_sp =
|
sp = frame_unwind_register_unsigned (next_frame,
|
||||||
read_memory_integer (cache->wd.aregs[1],
|
gdbarch_tdep (gdbarch)->a0_base + 1);
|
||||||
register_size (gdbarch,
|
cache->prev_sp = read_memory_integer (sp - 12, 4);
|
||||||
gdbarch_tdep (gdbarch)->a0_base + 1));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Read caller's frame SP directly from the previous window. */
|
/* Read caller's frame SP directly from the previous window. */
|
||||||
int regnum = areg_number
|
int regnum = arreg_number
|
||||||
(gdbarch, gdbarch_tdep (gdbarch)->a0_base + 1,
|
(gdbarch, gdbarch_tdep (gdbarch)->a0_base + 1,
|
||||||
cache->wd.wb);
|
cache->wd.wb);
|
||||||
|
|
||||||
|
@ -1161,10 +1318,10 @@ xtensa_frame_cache (struct frame_info *next_frame, void **this_cache)
|
||||||
else /* Call0 framework. */
|
else /* Call0 framework. */
|
||||||
{
|
{
|
||||||
call0_frame_cache (next_frame, cache, pc);
|
call0_frame_cache (next_frame, cache, pc);
|
||||||
|
fp_regnum = cache->c0.fp_regnum;
|
||||||
}
|
}
|
||||||
|
|
||||||
cache->base = frame_unwind_register_unsigned
|
cache->base = frame_unwind_register_unsigned (next_frame, fp_regnum);
|
||||||
(next_frame, gdbarch_tdep (gdbarch)->a0_base + 1);
|
|
||||||
|
|
||||||
return cache;
|
return cache;
|
||||||
}
|
}
|
||||||
|
@ -1272,12 +1429,7 @@ xtensa_frame_prev_register (struct frame_info *next_frame,
|
||||||
else if (!cache->call0)
|
else if (!cache->call0)
|
||||||
{
|
{
|
||||||
if (regnum == gdbarch_tdep (gdbarch)->ws_regnum)
|
if (regnum == gdbarch_tdep (gdbarch)->ws_regnum)
|
||||||
{
|
saved_reg = cache->wd.ws;
|
||||||
if (cache->wd.ws != 0)
|
|
||||||
saved_reg = cache->wd.ws;
|
|
||||||
else
|
|
||||||
saved_reg = 1 << cache->wd.wb;
|
|
||||||
}
|
|
||||||
else if (regnum == gdbarch_tdep (gdbarch)->wb_regnum)
|
else if (regnum == gdbarch_tdep (gdbarch)->wb_regnum)
|
||||||
saved_reg = cache->wd.wb;
|
saved_reg = cache->wd.wb;
|
||||||
else if (regnum == gdbarch_ps_regnum (gdbarch))
|
else if (regnum == gdbarch_ps_regnum (gdbarch))
|
||||||
|
@ -1302,18 +1454,18 @@ xtensa_frame_prev_register (struct frame_info *next_frame,
|
||||||
|
|
||||||
if (!cache->call0) /* Windowed ABI. */
|
if (!cache->call0) /* Windowed ABI. */
|
||||||
{
|
{
|
||||||
/* Convert A-register numbers to AR-register numbers. */
|
/* Convert A-register numbers to AR-register numbers,
|
||||||
|
if we deal with A-register. */
|
||||||
if (regnum >= gdbarch_tdep (gdbarch)->a0_base
|
if (regnum >= gdbarch_tdep (gdbarch)->a0_base
|
||||||
&& regnum <= gdbarch_tdep (gdbarch)->a0_base + 15)
|
&& regnum <= gdbarch_tdep (gdbarch)->a0_base + 15)
|
||||||
regnum = areg_number (gdbarch, regnum, cache->wd.wb);
|
regnum = arreg_number (gdbarch, regnum, cache->wd.wb);
|
||||||
|
|
||||||
/* Check if AR-register has been saved to stack. */
|
/* Check, if we deal with AR-register saved on stack. */
|
||||||
if (regnum >= gdbarch_tdep (gdbarch)->ar_base
|
if (regnum >= gdbarch_tdep (gdbarch)->ar_base
|
||||||
&& regnum <= (gdbarch_tdep (gdbarch)->ar_base
|
&& regnum <= (gdbarch_tdep (gdbarch)->ar_base
|
||||||
+ gdbarch_tdep (gdbarch)->num_aregs))
|
+ gdbarch_tdep (gdbarch)->num_aregs))
|
||||||
{
|
{
|
||||||
int areg = regnum - gdbarch_tdep (gdbarch)->ar_base
|
int areg = areg_number (gdbarch, regnum, cache->wd.wb);
|
||||||
- (cache->wd.wb * 4);
|
|
||||||
|
|
||||||
if (areg >= 0
|
if (areg >= 0
|
||||||
&& areg < XTENSA_NUM_SAVED_AREGS
|
&& areg < XTENSA_NUM_SAVED_AREGS
|
||||||
|
@ -1443,7 +1595,7 @@ xtensa_extract_return_value (struct type *type,
|
||||||
register (A2) in the caller window. */
|
register (A2) in the caller window. */
|
||||||
regcache_raw_read_unsigned
|
regcache_raw_read_unsigned
|
||||||
(regcache, gdbarch_tdep (gdbarch)->wb_regnum, &wb);
|
(regcache, gdbarch_tdep (gdbarch)->wb_regnum, &wb);
|
||||||
areg = areg_number (gdbarch,
|
areg = arreg_number (gdbarch,
|
||||||
gdbarch_tdep (gdbarch)->a0_base + 2 + callsize, wb);
|
gdbarch_tdep (gdbarch)->a0_base + 2 + callsize, wb);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1493,8 +1645,8 @@ xtensa_store_return_value (struct type *type,
|
||||||
internal_error (__FILE__, __LINE__,
|
internal_error (__FILE__, __LINE__,
|
||||||
_("unimplemented for this length: %d"),
|
_("unimplemented for this length: %d"),
|
||||||
TYPE_LENGTH (type));
|
TYPE_LENGTH (type));
|
||||||
areg = areg_number (gdbarch,
|
areg = arreg_number (gdbarch,
|
||||||
gdbarch_tdep (gdbarch)->a0_base + 2 + callsize, wb);
|
gdbarch_tdep (gdbarch)->a0_base + 2 + callsize, wb);
|
||||||
|
|
||||||
DEBUGTRACE ("[xtensa_store_return_value] callsize %d wb %d\n",
|
DEBUGTRACE ("[xtensa_store_return_value] callsize %d wb %d\n",
|
||||||
callsize, (int) wb);
|
callsize, (int) wb);
|
||||||
|
@ -2666,6 +2818,9 @@ xtensa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||||
set_gdbarch_regset_from_core_section (gdbarch,
|
set_gdbarch_regset_from_core_section (gdbarch,
|
||||||
xtensa_regset_from_core_section);
|
xtensa_regset_from_core_section);
|
||||||
|
|
||||||
|
set_solib_svr4_fetch_link_map_offsets
|
||||||
|
(gdbarch, svr4_ilp32_fetch_link_map_offsets);
|
||||||
|
|
||||||
return gdbarch;
|
return gdbarch;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue