summaryrefslogtreecommitdiff
path: root/gdb/xtensa-tdep.c
diff options
context:
space:
mode:
authorMaxim Grigoriev <maxim2405@gmail.com>2011-03-09 00:55:07 +0000
committerMaxim Grigoriev <maxim2405@gmail.com>2011-03-09 00:55:07 +0000
commit74b5d5fa3979c6484694cecc2110ec241362a80d (patch)
tree1d6da097a85226c0b7b44a84abc444c201aef9a0 /gdb/xtensa-tdep.c
parent63fad560276d7cf2d64b9b39d92d91d888f6d9b7 (diff)
downloadgdb-74b5d5fa3979c6484694cecc2110ec241362a80d.tar.gz
2011-03-08 Maxim Grigoriev <maxim2405@gmail.com>
* xtensa-tdep.c (TX_PS): New. (windowing_enabled): Update to count for Call0 ABI. (xtensa_hextochar): New. (xtensa_init_reggroups): Make algorithm generic. (xtensa_frame_cache): Use TX_PS on Tiny Xtensa.
Diffstat (limited to 'gdb/xtensa-tdep.c')
-rw-r--r--gdb/xtensa-tdep.c66
1 files changed, 43 insertions, 23 deletions
diff --git a/gdb/xtensa-tdep.c b/gdb/xtensa-tdep.c
index c3ed28327b4..49ec8fc8cd8 100644
--- a/gdb/xtensa-tdep.c
+++ b/gdb/xtensa-tdep.c
@@ -91,6 +91,11 @@ static int xtensa_debug_level = 0;
#define CALLINC(ps) (((ps) & PS_CALLINC_MASK) >> PS_CALLINC_SHIFT)
#define WINSIZE(ra) (4 * (( (ra) >> 30) & 0x3))
+/* On TX, hardware can be configured without Exception Option.
+ There is no PS register in this case. Inside XT-GDB, let us treat
+ it as a virtual read-only register always holding the same value. */
+#define TX_PS 0x20
+
/* ABI-independent macros. */
#define ARG_NOF(gdbarch) \
(gdbarch_tdep (gdbarch)->call_abi \
@@ -116,6 +121,16 @@ static int xtensa_debug_level = 0;
#define PS_WOE (1<<18)
#define PS_EXC (1<<4)
+static inline int
+windowing_enabled (struct gdbarch *gdbarch, unsigned int ps)
+{
+ /* If we know CALL0 ABI is set explicitly, say it is Call0. */
+ if (gdbarch_tdep (gdbarch)->call_abi == CallAbiCall0Only)
+ return 0;
+
+ return ((ps & PS_EXC) == 0 && (ps & PS_WOE) != 0);
+}
+
/* Convert a live A-register number to the corresponding AR-register
number. */
static int
@@ -146,12 +161,6 @@ areg_number (struct gdbarch *gdbarch, int ar_regnum, unsigned int wb)
return (areg > 15) ? -1 : areg;
}
-static inline int
-windowing_enabled (CORE_ADDR ps)
-{
- return ((ps & PS_EXC) == 0 && (ps & PS_WOE) != 0);
-}
-
/* Return the window size of the previous call to the function from which we
have just returned.
@@ -692,6 +701,13 @@ xtensa_pseudo_register_write (struct gdbarch *gdbarch,
_("invalid register number %d"), regnum);
}
+static inline char xtensa_hextochar (int xdigit)
+{
+ static char hex[]="0123456789abcdef";
+
+ return hex[xdigit & 0x0f];
+}
+
static struct reggroup *xtensa_ar_reggroup;
static struct reggroup *xtensa_user_reggroup;
static struct reggroup *xtensa_vectra_reggroup;
@@ -700,18 +716,18 @@ 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);
- xtensa_cp[0] = reggroup_new ("cp0", USER_REGGROUP);
- xtensa_cp[1] = reggroup_new ("cp1", USER_REGGROUP);
- xtensa_cp[2] = reggroup_new ("cp2", USER_REGGROUP);
- xtensa_cp[3] = reggroup_new ("cp3", USER_REGGROUP);
- xtensa_cp[4] = reggroup_new ("cp4", USER_REGGROUP);
- xtensa_cp[5] = reggroup_new ("cp5", USER_REGGROUP);
- xtensa_cp[6] = reggroup_new ("cp6", USER_REGGROUP);
- xtensa_cp[7] = reggroup_new ("cp7", USER_REGGROUP);
+ for (i = 0; i < XTENSA_MAX_COPROCESSOR; i++)
+ {
+ cpname[2] = xtensa_hextochar (i);
+ xtensa_cp[i] = reggroup_new (cpname, USER_REGGROUP);
+ }
}
static void
@@ -1187,23 +1203,26 @@ xtensa_frame_cache (struct frame_info *this_frame, void **this_cache)
struct gdbarch *gdbarch = get_frame_arch (this_frame);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
unsigned int fp_regnum;
- char op1;
- int windowed;
+ int windowed, ps_regnum;
if (*this_cache)
return *this_cache;
- ps = get_frame_register_unsigned (this_frame, gdbarch_ps_regnum (gdbarch));
- windowed = windowing_enabled (ps);
+ 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);
/* Get pristine xtensa-frame. */
cache = xtensa_alloc_frame_cache (windowed);
*this_cache = cache;
- pc = get_frame_register_unsigned (this_frame, gdbarch_pc_regnum (gdbarch));
-
if (windowed)
{
+ char op1;
+
/* Get WINDOWBASE, WINDOWSTART, and PS registers. */
wb = get_frame_register_unsigned (this_frame,
gdbarch_tdep (gdbarch)->wb_regnum);
@@ -1228,7 +1247,7 @@ xtensa_frame_cache (struct frame_info *this_frame, void **this_cache)
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->base = cache->prev_sp - 16;
cache->pc = pc;
cache->ra = (cache->pc & 0xc0000000) | (ra & 0x3fffffff);
@@ -1820,9 +1839,10 @@ xtensa_push_dummy_call (struct gdbarch *gdbarch,
if (gdbarch_tdep (gdbarch)->call_abi != CallAbiCall0Only)
{
+ ULONGEST val;
ra = (bp_addr & 0x3fffffff) | 0x40000000;
- regcache_raw_read (regcache, gdbarch_ps_regnum (gdbarch), buf);
- ps = extract_unsigned_integer (buf, 4, byte_order) & ~0x00030000;
+ 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,