aboutsummaryrefslogtreecommitdiff
path: root/gdb/xtensa-tdep.c
diff options
context:
space:
mode:
authorMaxim Grigoriev <maxim2405@gmail.com>2008-02-11 21:58:41 +0000
committerMaxim Grigoriev <maxim2405@gmail.com>2008-02-11 21:58:41 +0000
commit94a0e877111421d300d26b858bd3a0a27078d1e8 (patch)
treef34169ef9230d5d48df5cfb3979774e416dd99e9 /gdb/xtensa-tdep.c
parent6c7d412cf3470258471ef41332d68e17c0127c26 (diff)
downloadgdb-94a0e877111421d300d26b858bd3a0a27078d1e8.zip
gdb-94a0e877111421d300d26b858bd3a0a27078d1e8.tar.gz
gdb-94a0e877111421d300d26b858bd3a0a27078d1e8.tar.bz2
2008-02-11 Maxim Grigoriev <maxim2405@gmail.com>
* NEWS (New native configurations): Xtensa GNU/Linux. (New targets): Xtensa GNU/Linux. * Makefile.in (ALL_TARGET_OBS): Add xtensa-linux-nat.o and xtensa-linux-tdep.o (ALLDEPFILES): Add xtensa-linux-tdep.c and xtensa-linux-nat.c (xtensa-linux-nat.o, xtensa-linux-tdep.o): New dependencies. * configure.tgt (xtensa*-*-linux*): New entry. * xtensa-config.c (xtensa_tdep): New variable. (xtensa_config_byte_order, xtensa_config_tdep): Removed. (rmap): Change format based on new macro XTREG. (XTENSA_CONFIG_INSTANTIATE): Use new macro defined in xtensa-tdep.h. * xtensa-linux-nat.c: New. * xtensa-linux-tdep.c: New. * xtensa-xtregs.c: New. * xtensa-tdep.h (xtensa_elf_gregset_t): Update. (XTENSA_ELF_NGREG, XTREG, XTREG_END, XTENSA_GDBARCH_TDEP_INSTANTIATE) (XCHAL_NUM_CONTEXTS, XCHAL_HAVE_EXCEPTIONS): New macros. (xtensa_register_t): New field coprocessor. (XTENSA_REGISTER_FLAGS_PRIVILEGED): Name spelling corrected. * xtensa-tdep.c (xtensa_config_tdep, xtensa_config_byte_order): Removed. (xtensa_pseudo_register_read, xtensa_pseudo_register_write): Update to handle privileged registers. (xtensa_supply_gregset) Remove exccause and excvaddr registers. (xtensa_push_dummy_call): Set windowstart register correctly. (call0_analyze_prologue): Initialize xtensa_default_isa. (xtensa_derive_tdep): New. (xtensa_gdbarch_init): Get rid of xtensa_config_byte_order and xtensa_config_tdep, use XCHAL_HAVE_BE and xtensa_tdep instead. Call xtensa_derive_tdep(). * config/xtensa/linux.mh: New. * regformats/reg-xtensa.dat: New.
Diffstat (limited to 'gdb/xtensa-tdep.c')
-rw-r--r--gdb/xtensa-tdep.c151
1 files changed, 126 insertions, 25 deletions
diff --git a/gdb/xtensa-tdep.c b/gdb/xtensa-tdep.c
index d52addf..16434b4 100644
--- a/gdb/xtensa-tdep.c
+++ b/gdb/xtensa-tdep.c
@@ -51,6 +51,7 @@
#include "xtensa-isa.h"
#include "xtensa-tdep.h"
+#include "xtensa-config.h"
static int xtensa_debug_level = 0;
@@ -94,13 +95,9 @@ static int xtensa_debug_level = 0;
== CallAbiCall0Only ? C0_NARGS : (ARGS_NUM_REGS))
#define ARG_1ST(gdbarch) \
(gdbarch_tdep (gdbarch)->call_abi == CallAbiCall0Only \
- ? (gdbarch_tdep (gdbarch)->a0_base + 0) + C0_ARGS \
+ ? (gdbarch_tdep (gdbarch)->a0_base + C0_ARGS) \
: (gdbarch_tdep (gdbarch)->a0_base + 6))
-extern struct gdbarch_tdep *xtensa_config_tdep (struct gdbarch_info *);
-extern int xtensa_config_byte_order (struct gdbarch_info *);
-
-
/* XTENSA_IS_ENTRY tests whether the first byte of an instruction
indicates that the instruction is an ENTRY instruction. */
@@ -508,12 +505,12 @@ xtensa_pseudo_register_read (struct gdbarch *gdbarch,
regnum, xtensa_register_name (gdbarch, regnum));
if (regnum == gdbarch_num_regs (gdbarch)
- + gdbarch_num_pseudo_regs (gdbarch))
+ + gdbarch_num_pseudo_regs (gdbarch) - 1)
regnum = gdbarch_tdep (gdbarch)->a0_base + 1;
/* Read aliases a0..a15, if this is a Windowed ABI. */
if (gdbarch_tdep (gdbarch)->isa_use_windowed_registers
- && (regnum >= gdbarch_tdep (gdbarch)->a0_base + 0)
+ && (regnum >= gdbarch_tdep (gdbarch)->a0_base)
&& (regnum <= gdbarch_tdep (gdbarch)->a0_base + 15))
{
gdb_byte *buf = (gdb_byte *) alloca (MAX_REGISTER_SIZE);
@@ -526,6 +523,17 @@ xtensa_pseudo_register_read (struct gdbarch *gdbarch,
if (regnum >= 0 && regnum < gdbarch_num_regs (gdbarch))
regcache_raw_read (regcache, regnum, buffer);
+
+ /* We have to find out how to deal with priveleged registers.
+ Let's treat them as pseudo-registers, but we cannot read/write them. */
+
+ else if (regnum < gdbarch_tdep (gdbarch)->a0_base)
+ {
+ buffer[0] = (gdb_byte)0;
+ buffer[1] = (gdb_byte)0;
+ buffer[2] = (gdb_byte)0;
+ buffer[3] = (gdb_byte)0;
+ }
/* Pseudo registers. */
else if (regnum >= 0
&& regnum < gdbarch_num_regs (gdbarch)
@@ -592,12 +600,12 @@ xtensa_pseudo_register_write (struct gdbarch *gdbarch,
regnum, xtensa_register_name (gdbarch, regnum));
if (regnum == gdbarch_num_regs (gdbarch)
- + gdbarch_num_pseudo_regs (gdbarch))
+ + gdbarch_num_pseudo_regs (gdbarch) -1)
regnum = gdbarch_tdep (gdbarch)->a0_base + 1;
/* Renumber register, if aliase a0..a15 on Windowed ABI. */
if (gdbarch_tdep (gdbarch)->isa_use_windowed_registers
- && (regnum >= gdbarch_tdep (gdbarch)->a0_base + 0)
+ && (regnum >= gdbarch_tdep (gdbarch)->a0_base)
&& (regnum <= gdbarch_tdep (gdbarch)->a0_base + 15))
{
gdb_byte *buf = (gdb_byte *) alloca (MAX_REGISTER_SIZE);
@@ -613,6 +621,13 @@ xtensa_pseudo_register_write (struct gdbarch *gdbarch,
if (regnum >= 0 && regnum < gdbarch_num_regs (gdbarch))
regcache_raw_write (regcache, regnum, buffer);
+ /* We have to find out how to deal with priveleged registers.
+ Let's treat them as pseudo-registers, but we cannot read/write them. */
+
+ else if (regnum < gdbarch_tdep (gdbarch)->a0_base)
+ {
+ return;
+ }
/* Pseudo registers. */
else if (regnum >= 0
&& regnum < gdbarch_num_regs (gdbarch)
@@ -812,12 +827,6 @@ xtensa_supply_gregset (const struct regset *regset,
if (regnum == gdbarch_tdep (gdbarch)->sar_regnum || regnum == -1)
regcache_raw_supply (rc, gdbarch_tdep (gdbarch)->sar_regnum,
(char *) &regs->sar);
- if (regnum == gdbarch_tdep (gdbarch)->exccause_regnum || regnum == -1)
- regcache_raw_supply (rc, gdbarch_tdep (gdbarch)->exccause_regnum,
- (char *) &regs->exccause);
- if (regnum == gdbarch_tdep (gdbarch)->excvaddr_regnum || regnum == -1)
- regcache_raw_supply (rc, gdbarch_tdep (gdbarch)->excvaddr_regnum,
- (char *) &regs->excvaddr);
if (regnum >=gdbarch_tdep (gdbarch)->ar_base
&& regnum < gdbarch_tdep (gdbarch)->ar_base
+ gdbarch_tdep (gdbarch)->num_aregs)
@@ -1070,7 +1079,7 @@ xtensa_frame_cache (struct frame_info *next_frame, void **this_cache)
{
int callinc = CALLINC (ps);
ra = frame_unwind_register_unsigned
- (next_frame, gdbarch_tdep (gdbarch)->a0_base + 0 + callinc * 4);
+ (next_frame, gdbarch_tdep (gdbarch)->a0_base + callinc * 4);
DEBUGINFO("[xtensa_frame_cache] 'entry' at 0x%08x\n (callinc = %d)",
(int)pc, callinc);
@@ -1085,7 +1094,7 @@ xtensa_frame_cache (struct frame_info *next_frame, void **this_cache)
else
{
ra = frame_unwind_register_unsigned
- (next_frame, gdbarch_tdep (gdbarch)->a0_base + 0);
+ (next_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);
@@ -1115,6 +1124,7 @@ xtensa_frame_cache (struct frame_info *next_frame, void **this_cache)
/* Set A4...A7/A11. */
/* Read an SP of the previous frame. */
sp = (CORE_ADDR) read_memory_integer (sp - 12, 4);
+ sp = (CORE_ADDR) read_memory_integer (sp - 12, 4);
sp -= cache->wd.callsize * 4;
for ( /* i=4 */ ; i < cache->wd.callsize; i++, sp += 4)
@@ -1293,7 +1303,7 @@ xtensa_frame_prev_register (struct frame_info *next_frame,
if (!cache->call0) /* Windowed ABI. */
{
/* Convert A-register numbers to AR-register numbers. */
- if (regnum >= gdbarch_tdep (gdbarch)->a0_base + 0
+ if (regnum >= gdbarch_tdep (gdbarch)->a0_base
&& regnum <= gdbarch_tdep (gdbarch)->a0_base + 15)
regnum = areg_number (gdbarch, regnum, cache->wd.wb);
@@ -1439,7 +1449,7 @@ xtensa_extract_return_value (struct type *type,
else
{
/* No windowing hardware - Call0 ABI. */
- areg = gdbarch_tdep (gdbarch)->a0_base + 0 + C0_ARGS;
+ areg = gdbarch_tdep (gdbarch)->a0_base + C0_ARGS;
}
DEBUGINFO ("[xtensa_extract_return_value] areg %d len %d\n", areg, len);
@@ -1491,7 +1501,7 @@ xtensa_store_return_value (struct type *type,
}
else
{
- areg = gdbarch_tdep (gdbarch)->a0_base + 0 + C0_ARGS;
+ areg = gdbarch_tdep (gdbarch)->a0_base + C0_ARGS;
}
if (len < 4 && gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
@@ -1769,12 +1779,22 @@ xtensa_push_dummy_call (struct gdbarch *gdbarch,
regcache_cooked_write_unsigned (regcache,
gdbarch_ps_regnum (gdbarch),
ps | 0x00010000);
+
+ /* All the registers have been saved. After executing
+ dummy call, they all will be restored. So it's safe
+ to modify WINDOWSTART register to make it look like there
+ is only one register window corresponding to WINDOWEBASE. */
+
+ regcache_raw_read (regcache, gdbarch_tdep (gdbarch)->wb_regnum, buf);
+ regcache_cooked_write_unsigned (regcache,
+ gdbarch_tdep (gdbarch)->ws_regnum,
+ 1 << extract_unsigned_integer (buf, 4));
}
else
{
/* Simulate CALL0: write RA into A0 register. */
regcache_cooked_write_unsigned
- (regcache, gdbarch_tdep (gdbarch)->a0_base + 0, bp_addr);
+ (regcache, gdbarch_tdep (gdbarch)->a0_base, bp_addr);
}
/* Set new stack pointer and return it. */
@@ -2098,6 +2118,8 @@ call0_analyze_prologue (CORE_ADDR start, CORE_ADDR pc,
}
else nregs = 0;
+ if (!xtensa_default_isa)
+ xtensa_default_isa = xtensa_isa_init (0, 0);
isa = xtensa_default_isa;
gdb_assert (BSZ >= xtensa_isa_maxlength (isa));
ins = xtensa_insnbuf_alloc (isa);
@@ -2341,8 +2363,7 @@ call0_frame_cache (struct frame_info *next_frame,
{
ra = frame_unwind_register_unsigned
(next_frame,
- gdbarch_tdep (gdbarch)->a0_base + 0
- + cache->c0.c0_rt[i].fr_reg);
+ gdbarch_tdep (gdbarch)->a0_base + cache->c0.c0_rt[i].fr_reg);
}
else ra = 0;
}
@@ -2481,8 +2502,87 @@ xtensa_verify_config (struct gdbarch *gdbarch)
do_cleanups (cleanups);
}
+
+/* Derive specific register numbers from the array of registers. */
+
+void
+xtensa_derive_tdep (struct gdbarch_tdep *tdep)
+{
+ xtensa_register_t* rmap;
+ int n, max_size = 4;
+
+ tdep->num_regs = 0;
+ tdep->num_nopriv_regs = 0;
+
+/* Special registers 0..255 (core). */
+#define XTENSA_DBREGN_SREG(n) (0x0200+(n))
+
+ for (rmap = tdep->regmap, n = 0; rmap->target_number != -1; n++, rmap++)
+ {
+ if (rmap->target_number == 0x0020)
+ tdep->pc_regnum = n;
+ else if (rmap->target_number == 0x0100)
+ tdep->ar_base = n;
+ else if (rmap->target_number == 0x0000)
+ tdep->a0_base = n;
+ else if (rmap->target_number == XTENSA_DBREGN_SREG(72))
+ tdep->wb_regnum = n;
+ else if (rmap->target_number == XTENSA_DBREGN_SREG(73))
+ tdep->ws_regnum = n;
+ else if (rmap->target_number == XTENSA_DBREGN_SREG(233))
+ tdep->debugcause_regnum = n;
+ else if (rmap->target_number == XTENSA_DBREGN_SREG(232))
+ tdep->exccause_regnum = n;
+ else if (rmap->target_number == XTENSA_DBREGN_SREG(238))
+ tdep->excvaddr_regnum = n;
+ else if (rmap->target_number == XTENSA_DBREGN_SREG(0))
+ tdep->lbeg_regnum = n;
+ else if (rmap->target_number == XTENSA_DBREGN_SREG(1))
+ tdep->lend_regnum = n;
+ else if (rmap->target_number == XTENSA_DBREGN_SREG(2))
+ tdep->lcount_regnum = n;
+ else if (rmap->target_number == XTENSA_DBREGN_SREG(3))
+ tdep->sar_regnum = n;
+ else if (rmap->target_number == XTENSA_DBREGN_SREG(5))
+ tdep->litbase_regnum = n;
+ else if (rmap->target_number == XTENSA_DBREGN_SREG(230))
+ tdep->ps_regnum = n;
+#if 0
+ else if (rmap->target_number == XTENSA_DBREGN_SREG(226))
+ tdep->interrupt_regnum = n;
+ else if (rmap->target_number == XTENSA_DBREGN_SREG(227))
+ tdep->interrupt2_regnum = n;
+ else if (rmap->target_number == XTENSA_DBREGN_SREG(224))
+ tdep->cpenable_regnum = n;
+#endif
+
+ if (rmap->byte_size > max_size)
+ max_size = rmap->byte_size;
+ if (rmap->mask != 0 && tdep->num_regs == 0)
+ tdep->num_regs = n;
+ /* Find out out how to deal with priveleged registers.
+
+ if ((rmap->flags & XTENSA_REGISTER_FLAGS_PRIVILEGED) != 0
+ && tdep->num_nopriv_regs == 0)
+ tdep->num_nopriv_regs = n;
+ */
+ if ((rmap->flags & XTENSA_REGISTER_FLAGS_PRIVILEGED) != 0
+ && tdep->num_regs == 0)
+ tdep->num_regs = n;
+ }
+
+ /* Number of pseudo registers. */
+ tdep->num_pseudo_regs = n - tdep->num_regs;
+
+ /* Empirically determined maximum sizes. */
+ tdep->max_register_raw_size = max_size;
+ tdep->max_register_virtual_size = max_size;
+}
+
/* Module "constructor" function. */
+extern struct gdbarch_tdep xtensa_tdep;
+
static struct gdbarch *
xtensa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
{
@@ -2493,10 +2593,11 @@ xtensa_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
DEBUGTRACE ("gdbarch_init()\n");
/* We have to set the byte order before we call gdbarch_alloc. */
- info.byte_order = xtensa_config_byte_order (&info);
+ info.byte_order = XCHAL_HAVE_BE ? BFD_ENDIAN_BIG : BFD_ENDIAN_LITTLE;
- tdep = xtensa_config_tdep (&info);
+ tdep = &xtensa_tdep;
gdbarch = gdbarch_alloc (&info, tdep);
+ xtensa_derive_tdep (tdep);
/* Verify our configuration. */
xtensa_verify_config (gdbarch);