diff options
author | Maxim Grigoriev <maxim2405@gmail.com> | 2011-03-09 00:55:09 +0000 |
---|---|---|
committer | Maxim Grigoriev <maxim2405@gmail.com> | 2011-03-09 00:55:09 +0000 |
commit | 98689b250438e851b5d33e7806bb35cfbba19ba3 (patch) | |
tree | c71c47cc975f47fa8f292d56baced1014037fae4 /gdb/xtensa-tdep.c | |
parent | 221e394aa4cf869ddc07de76107e8fc0db1dfa4f (diff) | |
download | gdb-98689b250438e851b5d33e7806bb35cfbba19ba3.zip gdb-98689b250438e851b5d33e7806bb35cfbba19ba3.tar.gz gdb-98689b250438e851b5d33e7806bb35cfbba19ba3.tar.bz2 |
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.c | 66 |
1 files changed, 43 insertions, 23 deletions
diff --git a/gdb/xtensa-tdep.c b/gdb/xtensa-tdep.c index c3ed283..49ec8fc 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, |