aboutsummaryrefslogtreecommitdiff
path: root/gdb/cris-tdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/cris-tdep.c')
-rw-r--r--gdb/cris-tdep.c726
1 files changed, 374 insertions, 352 deletions
diff --git a/gdb/cris-tdep.c b/gdb/cris-tdep.c
index 64f1e5f..1cb0d52 100644
--- a/gdb/cris-tdep.c
+++ b/gdb/cris-tdep.c
@@ -42,11 +42,12 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* To get entry_point_address. */
#include "objfiles.h"
-#include "solib.h" /* Support for shared libraries. */
+#include "solib.h" /* Support for shared libraries. */
#include "solib-svr4.h" /* For struct link_map_offsets. */
#include "gdb_string.h"
#include "dis-asm.h"
+
enum cris_num_regs
{
/* There are no floating point registers. Used in gdbserver low-linux.c. */
@@ -107,19 +108,32 @@ extern const struct cris_spec_reg cris_spec_regs[];
/* CRIS version, set via the user command 'set cris-version'. Affects
register names and sizes.*/
-static unsigned int usr_cmd_cris_version;
+static int usr_cmd_cris_version;
/* Indicates whether to trust the above variable. */
static int usr_cmd_cris_version_valid = 0;
-/* Whether to make use of Dwarf-2 CFI (default on). */
-static int usr_cmd_cris_dwarf2_cfi = 1;
+/* CRIS mode, set via the user command 'set cris-mode'. Affects availability
+ of some registers. */
+static const char *usr_cmd_cris_mode;
+
+/* Indicates whether to trust the above variable. */
+static int usr_cmd_cris_mode_valid = 0;
+
+static const char CRIS_MODE_USER[] = "CRIS_MODE_USER";
+static const char CRIS_MODE_SUPERVISOR[] = "CRIS_MODE_SUPERVISOR";
+static const char *cris_mode_enums[] =
+{
+ CRIS_MODE_USER,
+ CRIS_MODE_SUPERVISOR,
+ 0
+};
/* CRIS architecture specific information. */
struct gdbarch_tdep
{
- unsigned int cris_version;
- int cris_dwarf2_cfi;
+ int cris_version;
+ const char *cris_mode;
};
/* Functions for accessing target dependent data. */
@@ -130,121 +144,10 @@ cris_version (void)
return (gdbarch_tdep (current_gdbarch)->cris_version);
}
-/* Sigtramp identification code copied from i386-linux-tdep.c. */
-
-#define SIGTRAMP_INSN0 0x9c5f /* movu.w 0xXX, $r9 */
-#define SIGTRAMP_OFFSET0 0
-#define SIGTRAMP_INSN1 0xe93d /* break 13 */
-#define SIGTRAMP_OFFSET1 4
-
-static const unsigned short sigtramp_code[] =
-{
- SIGTRAMP_INSN0, 0x0077, /* movu.w $0x77, $r9 */
- SIGTRAMP_INSN1 /* break 13 */
-};
-
-#define SIGTRAMP_LEN (sizeof sigtramp_code)
-
-/* Note: same length as normal sigtramp code. */
-
-static const unsigned short rt_sigtramp_code[] =
-{
- SIGTRAMP_INSN0, 0x00ad, /* movu.w $0xad, $r9 */
- SIGTRAMP_INSN1 /* break 13 */
-};
-
-/* If PC is in a sigtramp routine, return the address of the start of
- the routine. Otherwise, return 0. */
-
-static CORE_ADDR
-cris_sigtramp_start (struct frame_info *next_frame)
-{
- CORE_ADDR pc = frame_pc_unwind (next_frame);
- unsigned short buf[SIGTRAMP_LEN];
-
- if (!safe_frame_unwind_memory (next_frame, pc, buf, SIGTRAMP_LEN))
- return 0;
-
- if (buf[0] != SIGTRAMP_INSN0)
- {
- if (buf[0] != SIGTRAMP_INSN1)
- return 0;
-
- pc -= SIGTRAMP_OFFSET1;
- if (!safe_frame_unwind_memory (next_frame, pc, buf, SIGTRAMP_LEN))
- return 0;
- }
-
- if (memcmp (buf, sigtramp_code, SIGTRAMP_LEN) != 0)
- return 0;
-
- return pc;
-}
-
-/* If PC is in a RT sigtramp routine, return the address of the start of
- the routine. Otherwise, return 0. */
-
-static CORE_ADDR
-cris_rt_sigtramp_start (struct frame_info *next_frame)
-{
- CORE_ADDR pc = frame_pc_unwind (next_frame);
- unsigned short buf[SIGTRAMP_LEN];
-
- if (!safe_frame_unwind_memory (next_frame, pc, buf, SIGTRAMP_LEN))
- return 0;
-
- if (buf[0] != SIGTRAMP_INSN0)
- {
- if (buf[0] != SIGTRAMP_INSN1)
- return 0;
-
- pc -= SIGTRAMP_OFFSET1;
- if (!safe_frame_unwind_memory (next_frame, pc, buf, SIGTRAMP_LEN))
- return 0;
- }
-
- if (memcmp (buf, rt_sigtramp_code, SIGTRAMP_LEN) != 0)
- return 0;
-
- return pc;
-}
-
-/* Assuming NEXT_FRAME is a frame following a GNU/Linux sigtramp
- routine, return the address of the associated sigcontext structure. */
-
-static CORE_ADDR
-cris_sigcontext_addr (struct frame_info *next_frame)
+static const char *
+cris_mode (void)
{
- CORE_ADDR pc;
- CORE_ADDR sp;
- char buf[4];
-
- frame_unwind_register (next_frame, SP_REGNUM, buf);
- sp = extract_unsigned_integer (buf, 4);
-
- /* Look for normal sigtramp frame first. */
- pc = cris_sigtramp_start (next_frame);
- if (pc)
- {
- /* struct signal_frame (arch/cris/kernel/signal.c) contains
- struct sigcontext as its first member, meaning the SP points to
- it already. */
- return sp;
- }
-
- pc = cris_rt_sigtramp_start (next_frame);
- if (pc)
- {
- /* struct rt_signal_frame (arch/cris/kernel/signal.c) contains
- a struct ucontext, which in turn contains a struct sigcontext.
- Magic digging:
- 4 + 4 + 128 to struct ucontext, then
- 4 + 4 + 12 to struct sigcontext. */
- return (sp + 156);
- }
-
- error ("Couldn't recognize signal trampoline.");
- return 0;
+ return (gdbarch_tdep (current_gdbarch)->cris_mode);
}
struct cris_unwind_cache
@@ -270,111 +173,6 @@ struct cris_unwind_cache
struct trad_frame_saved_reg *saved_regs;
};
-static struct cris_unwind_cache *
-cris_sigtramp_frame_unwind_cache (struct frame_info *next_frame,
- void **this_cache)
-{
- struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
- struct cris_unwind_cache *info;
- CORE_ADDR pc;
- CORE_ADDR sp;
- CORE_ADDR addr;
- char buf[4];
- int i;
-
- if ((*this_cache))
- return (*this_cache);
-
- info = FRAME_OBSTACK_ZALLOC (struct cris_unwind_cache);
- (*this_cache) = info;
- info->saved_regs = trad_frame_alloc_saved_regs (next_frame);
-
- /* Zero all fields. */
- info->prev_sp = 0;
- info->base = 0;
- info->size = 0;
- info->sp_offset = 0;
- info->r8_offset = 0;
- info->uses_frame = 0;
- info->return_pc = 0;
- info->leaf_function = 0;
-
- frame_unwind_register (next_frame, SP_REGNUM, buf);
- info->base = extract_unsigned_integer (buf, 4);
-
- addr = cris_sigcontext_addr (next_frame);
-
- /* Layout of the sigcontext struct:
- struct sigcontext {
- struct pt_regs regs;
- unsigned long oldmask;
- unsigned long usp;
- }; */
-
- /* R0 to R13 are stored in reverse order at offset (2 * 4) in
- struct pt_regs. */
- for (i = 0; i <= 13; i++)
- info->saved_regs[i].addr = addr + ((15 - i) * 4);
-
- info->saved_regs[MOF_REGNUM].addr = addr + (16 * 4);
- info->saved_regs[DCCR_REGNUM].addr = addr + (17 * 4);
- info->saved_regs[SRP_REGNUM].addr = addr + (18 * 4);
- /* Note: IRP is off by 2 at this point. There's no point in correcting it
- though since that will mean that the backtrace will show a PC different
- from what is shown when stopped. */
- info->saved_regs[IRP_REGNUM].addr = addr + (19 * 4);
- info->saved_regs[PC_REGNUM] = info->saved_regs[IRP_REGNUM];
- info->saved_regs[SP_REGNUM].addr = addr + (24 * 4);
-
- return info;
-}
-
-static void
-cris_sigtramp_frame_this_id (struct frame_info *next_frame, void **this_cache,
- struct frame_id *this_id)
-{
- struct cris_unwind_cache *cache =
- cris_sigtramp_frame_unwind_cache (next_frame, this_cache);
- (*this_id) = frame_id_build (cache->base, frame_pc_unwind (next_frame));
-}
-
-/* Forward declaration. */
-
-static void cris_frame_prev_register (struct frame_info *next_frame,
- void **this_prologue_cache,
- int regnum, int *optimizedp,
- enum lval_type *lvalp, CORE_ADDR *addrp,
- int *realnump, void *bufferp);
-static void
-cris_sigtramp_frame_prev_register (struct frame_info *next_frame,
- void **this_cache,
- int regnum, int *optimizedp,
- enum lval_type *lvalp, CORE_ADDR *addrp,
- int *realnump, void *valuep)
-{
- /* Make sure we've initialized the cache. */
- cris_sigtramp_frame_unwind_cache (next_frame, this_cache);
- cris_frame_prev_register (next_frame, this_cache, regnum,
- optimizedp, lvalp, addrp, realnump, valuep);
-}
-
-static const struct frame_unwind cris_sigtramp_frame_unwind =
-{
- SIGTRAMP_FRAME,
- cris_sigtramp_frame_this_id,
- cris_sigtramp_frame_prev_register
-};
-
-static const struct frame_unwind *
-cris_sigtramp_frame_sniffer (struct frame_info *next_frame)
-{
- if (cris_sigtramp_start (next_frame)
- || cris_rt_sigtramp_start (next_frame))
- return &cris_sigtramp_frame_unwind;
-
- return NULL;
-}
-
/* The instruction environment needed to find single-step breakpoints. */
typedef
struct instruction_environment
@@ -547,11 +345,11 @@ static struct gdbarch *cris_gdbarch_init (struct gdbarch_info,
static void cris_dump_tdep (struct gdbarch *, struct ui_file *);
-static void set_cris_version (char *ignore_args, int from_tty,
- struct cmd_list_element *c);
+static void cris_version_update (char *ignore_args, int from_tty,
+ struct cmd_list_element *c);
-static void set_cris_dwarf2_cfi (char *ignore_args, int from_tty,
- struct cmd_list_element *c);
+static void cris_mode_update (char *ignore_args, int from_tty,
+ struct cmd_list_element *c);
static CORE_ADDR cris_scan_prologue (CORE_ADDR pc,
struct frame_info *next_frame,
@@ -564,8 +362,9 @@ static CORE_ADDR cris_unwind_sp (struct gdbarch *gdbarch,
struct frame_info *next_frame);
/* When arguments must be pushed onto the stack, they go on in reverse
- order. The below implements a FILO (stack) to do this.
- Copied from d10v-tdep.c. */
+ order. The below implements a FILO (stack) to do this. */
+
+/* Borrowed from d10v-tdep.c. */
struct stack_item
{
@@ -600,7 +399,7 @@ pop_stack_item (struct stack_item *si)
the saved registers of frame described by FRAME_INFO. This
includes special registers such as pc and fp saved in special ways
in the stack frame. sp is even more special: the address we return
- for it IS the sp for the next frame. */
+ for it IS the sp for the next frame. */
struct cris_unwind_cache *
cris_frame_unwind_cache (struct frame_info *next_frame,
@@ -732,7 +531,7 @@ cris_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
struct stack_item *si = NULL;
- /* Push the return address. */
+ /* Push the return address. */
regcache_cooked_write_unsigned (regcache, SRP_REGNUM, bp_addr);
/* Are we returning a value using a structure return or a normal value
@@ -968,7 +767,7 @@ cris_scan_prologue (CORE_ADDR pc, struct frame_info *next_frame,
limit = next_frame ? frame_pc_unwind (next_frame) : pc + 64;
/* Find the prologue instructions. */
- while (pc > 0 && pc < limit)
+ while (pc < limit)
{
insn = read_memory_unsigned_integer (pc, 2);
pc += 2;
@@ -1370,8 +1169,13 @@ cris_cannot_store_register (int regno)
/* Writing has no effect. */
return 1;
- /* IBR, BAR, BRP and IRP are read-only in user mode. Let the debug
- agent decide whether they are writable. */
+ else if (cris_mode () == CRIS_MODE_USER)
+ {
+ if (regno == IBR_REGNUM || regno == BAR_REGNUM || regno == BRP_REGNUM
+ || regno == IRP_REGNUM)
+ /* Read-only in user mode. */
+ return 1;
+ }
return 0;
}
@@ -1398,7 +1202,7 @@ cris_register_offset (int regno)
}
else
{
- /* Invalid register. */
+ /* Invalid register. */
return -1;
}
}
@@ -1409,21 +1213,33 @@ cris_register_offset (int regno)
static struct type *
cris_register_type (struct gdbarch *gdbarch, int regno)
{
- if (regno == PC_REGNUM)
- return builtin_type_void_func_ptr;
- else if (regno == SP_REGNUM || regno == CRIS_FP_REGNUM)
- return builtin_type_void_data_ptr;
- else if ((regno >= 0 && regno < SP_REGNUM)
- || (regno >= MOF_REGNUM && regno <= USP_REGNUM))
- /* Note: R8 taken care of previous clause. */
- return builtin_type_uint32;
- else if (regno >= P4_REGNUM && regno <= CCR_REGNUM)
- return builtin_type_uint16;
- else if (regno >= P0_REGNUM && regno <= VR_REGNUM)
- return builtin_type_uint8;
+ if (regno == SP_REGNUM || regno == PC_REGNUM
+ || (regno > P8_REGNUM && regno < USP_REGNUM))
+ {
+ /* SP, PC, IBR, IRP, SRP, BAR, DCCR, BRP */
+ return lookup_pointer_type (builtin_type_void);
+ }
+ else if (regno == P8_REGNUM || regno == USP_REGNUM
+ || (regno >= 0 && regno < SP_REGNUM))
+ {
+ /* R0 - R13, P8, P15 */
+ return builtin_type_unsigned_long;
+ }
+ else if (regno > P3_REGNUM && regno < P8_REGNUM)
+ {
+ /* P4, CCR, DCR0, DCR1 */
+ return builtin_type_unsigned_short;
+ }
+ else if (regno > PC_REGNUM && regno < P4_REGNUM)
+ {
+ /* P0, P1, P2, P3 */
+ return builtin_type_unsigned_char;
+ }
else
- /* Invalid (unimplemented) register. */
- return builtin_type_int0;
+ {
+ /* Invalid register. */
+ return builtin_type_void;
+ }
}
/* Stores a function return value of type type, where valbuf is the address
@@ -1501,49 +1317,10 @@ cris_register_name (int regno)
}
}
-/* Convert DWARF register number REG to the appropriate register
- number used by GDB. */
-
static int
-cris_dwarf2_reg_to_regnum (int reg)
+cris_register_bytes_ok (long bytes)
{
- /* We need to re-map a couple of registers (SRP is 16 in Dwarf-2 register
- numbering, MOF is 18).
- Adapted from gcc/config/cris/cris.h. */
- static int cris_dwarf_regmap[] = {
- 0, 1, 2, 3,
- 4, 5, 6, 7,
- 8, 9, 10, 11,
- 12, 13, 14, 15,
- 27, -1, -1, -1,
- -1, -1, -1, 23,
- -1, -1, -1, 27,
- -1, -1, -1, -1
- };
- int regnum = -1;
-
- if (reg >= 0 && reg < ARRAY_SIZE (cris_dwarf_regmap))
- regnum = cris_dwarf_regmap[reg];
-
- if (regnum == -1)
- warning ("Unmapped DWARF Register #%d encountered\n", reg);
-
- return regnum;
-}
-
-/* DWARF-2 frame support. */
-
-static void
-cris_dwarf2_frame_init_reg (struct gdbarch *gdbarch, int regnum,
- struct dwarf2_frame_state_reg *reg)
-{
- /* The return address column. */
- if (regnum == PC_REGNUM)
- reg->how = DWARF2_FRAME_REG_RA;
-
- /* The call frame address. */
- else if (regnum == SP_REGNUM)
- reg->how = DWARF2_FRAME_REG_CFA;
+ return (bytes == deprecated_register_bytes ());
}
/* Extract from an array regbuf containing the raw register state a function
@@ -1819,7 +1596,6 @@ cris_software_single_step (enum target_signal ignore, int insert_breakpoints)
if (status == -1)
{
/* Could not find a target. FIXME: Should do something. */
- warning ("cris_software_single_step: unable to find step target");
}
else
{
@@ -3536,7 +3312,7 @@ cris_delayed_get_disassembler (bfd_vma addr, struct disassemble_info *info)
disassembler, even when there is no BFD. Does something like
"gdb; target remote; disassmeble *0x123" work? */
gdb_assert (exec_bfd != NULL);
- print_insn = cris_get_disassembler (exec_bfd);
+ print_insn = cris_get_disassembler (exec_bfd);
gdb_assert (print_insn != NULL);
return print_insn (addr, info);
}
@@ -3647,38 +3423,230 @@ cris_linux_svr4_fetch_link_map_offsets (void)
return lmp;
}
+static void
+cris_fpless_backtrace (char *noargs, int from_tty)
+{
+ /* Points at the instruction after the jsr (except when in innermost frame
+ where it points at the original pc). */
+ CORE_ADDR pc = 0;
+
+ /* Temporary variable, used for parsing from the start of the function that
+ the pc is in, up to the pc. */
+ CORE_ADDR tmp_pc = 0;
+ CORE_ADDR sp = 0;
+
+ /* Information about current frame. */
+ struct symtab_and_line sal;
+ char* func_name;
+
+ /* Present instruction. */
+ unsigned short insn;
+
+ /* Next instruction, lookahead. */
+ unsigned short insn_next;
+
+ /* This is to store the offset between sp at start of function and until we
+ reach push srp (if any). */
+ int sp_add_later = 0;
+ int push_srp_found = 0;
+
+ int val = 0;
+
+ /* Frame counter. */
+ int frame = 0;
+
+ /* For the innermost frame, we want to look at srp in case it's a leaf
+ function (since there's no push srp in that case). */
+ int innermost_frame = 1;
+
+ deprecated_read_register_gen (PC_REGNUM, (char *) &pc);
+ deprecated_read_register_gen (SP_REGNUM, (char *) &sp);
+
+ /* We make an explicit return when we can't find an outer frame. */
+ while (1)
+ {
+ /* Get file name and line number. */
+ sal = find_pc_line (pc, 0);
+
+ /* Get function name. */
+ find_pc_partial_function (pc, &func_name, (CORE_ADDR *) NULL,
+ (CORE_ADDR *) NULL);
+
+ /* Print information about current frame. */
+ printf_unfiltered ("#%i 0x%08lx in %s", frame++, pc, func_name);
+ if (sal.symtab)
+ {
+ printf_unfiltered (" at %s:%i", sal.symtab->filename, sal.line);
+ }
+ printf_unfiltered ("\n");
+
+ /* Get the start address of this function. */
+ tmp_pc = get_pc_function_start (pc);
+
+ /* Mini parser, only meant to find push sp and sub ...,sp from the start
+ of the function, up to the pc. */
+ while (tmp_pc < pc)
+ {
+ insn = read_memory_unsigned_integer (tmp_pc, sizeof (short));
+ tmp_pc += sizeof (short);
+ if (insn == 0xE1FC)
+ {
+ /* push <reg> 32 bit instruction */
+ insn_next = read_memory_unsigned_integer (tmp_pc,
+ sizeof (short));
+ tmp_pc += sizeof (short);
+
+ /* Recognize srp. */
+ if (insn_next == 0xBE7E)
+ {
+ /* For subsequent (not this one though) push or sub which
+ affects sp, adjust sp immediately. */
+ push_srp_found = 1;
+
+ /* Note: this will break if we ever encounter a
+ push vr (1 byte) or push ccr (2 bytes). */
+ sp_add_later += 4;
+ }
+ else
+ {
+ /* Some other register was pushed. */
+ if (push_srp_found)
+ {
+ sp += 4;
+ }
+ else
+ {
+ sp_add_later += 4;
+ }
+ }
+ }
+ else if (cris_get_operand2 (insn) == SP_REGNUM
+ && cris_get_mode (insn) == 0x0000
+ && cris_get_opcode (insn) == 0x000A)
+ {
+ /* subq <val>,sp */
+ val = cris_get_quick_value (insn);
+
+ if (push_srp_found)
+ {
+ sp += val;
+ }
+ else
+ {
+ sp_add_later += val;
+ }
+
+ }
+ else if (cris_get_operand2 (insn) == SP_REGNUM
+ /* Autoincrement addressing mode. */
+ && cris_get_mode (insn) == 0x0003
+ /* Opcode. */
+ && ((insn) & 0x03E0) >> 5 == 0x0004)
+ {
+ /* subu <val>,sp */
+ val = get_data_from_address (&insn, tmp_pc);
+
+ if (push_srp_found)
+ {
+ sp += val;
+ }
+ else
+ {
+ sp_add_later += val;
+ }
+ }
+ else if (cris_get_operand2 (insn) == SP_REGNUM
+ && ((insn & 0x0F00) >> 8) == 0x0001
+ && (cris_get_signed_offset (insn) < 0))
+ {
+ /* Immediate byte offset addressing prefix word with sp as base
+ register. Used for CRIS v8 i.e. ETRAX 100 and newer if <val>
+ is between 64 and 128.
+ movem r<regsave>,[sp=sp-<val>] */
+ val = -cris_get_signed_offset (insn);
+ insn_next = read_memory_unsigned_integer (tmp_pc,
+ sizeof (short));
+ tmp_pc += sizeof (short);
+
+ if (cris_get_mode (insn_next) == PREFIX_ASSIGN_MODE
+ && cris_get_opcode (insn_next) == 0x000F
+ && cris_get_size (insn_next) == 0x0003
+ && cris_get_operand1 (insn_next) == SP_REGNUM)
+ {
+ if (push_srp_found)
+ {
+ sp += val;
+ }
+ else
+ {
+ sp_add_later += val;
+ }
+ }
+ }
+ }
+
+ if (push_srp_found)
+ {
+ /* Reset flag. */
+ push_srp_found = 0;
+
+ /* sp should now point at where srp is stored on the stack. Update
+ the pc to the srp. */
+ pc = read_memory_unsigned_integer (sp, 4);
+ }
+ else if (innermost_frame)
+ {
+ /* We couldn't find a push srp in the prologue, so this must be
+ a leaf function, and thus we use the srp register directly.
+ This should happen at most once, for the innermost function. */
+ deprecated_read_register_gen (SRP_REGNUM, (char *) &pc);
+ }
+ else
+ {
+ /* Couldn't find an outer frame. */
+ return;
+ }
+
+ /* Reset flag. (In case the innermost frame wasn't a leaf, we don't
+ want to look at the srp register later either). */
+ innermost_frame = 0;
+
+ /* Now, add the offset for everything up to, and including push srp,
+ that was held back during the prologue parsing. */
+ sp += sp_add_later;
+ sp_add_later = 0;
+ }
+}
+
extern initialize_file_ftype _initialize_cris_tdep; /* -Wmissing-prototypes */
void
_initialize_cris_tdep (void)
{
- static struct cmd_list_element *cris_set_cmdlist;
- static struct cmd_list_element *cris_show_cmdlist;
-
struct cmd_list_element *c;
gdbarch_register (bfd_arch_cris, cris_gdbarch_init, cris_dump_tdep);
/* CRIS-specific user-commands. */
- add_setshow_uinteger_cmd ("cris-version", class_support,
- &usr_cmd_cris_version,
- "Set the current CRIS version.",
- "Show the current CRIS version.",
- "Set if autodetection fails.",
- "Current CRIS version is %s.",
- set_cris_version, NULL,
- &setlist, &showlist);
+ c = add_set_cmd ("cris-version", class_support, var_integer,
+ (char *) &usr_cmd_cris_version,
+ "Set the current CRIS version.", &setlist);
+ set_cmd_sfunc (c, cris_version_update);
+ deprecated_add_show_from_set (c, &showlist);
+
+ c = add_set_enum_cmd ("cris-mode", class_support, cris_mode_enums,
+ &usr_cmd_cris_mode,
+ "Set the current CRIS mode.", &setlist);
+ set_cmd_sfunc (c, cris_mode_update);
+ deprecated_add_show_from_set (c, &showlist);
+
+ c = add_cmd ("cris-fpless-backtrace", class_support, cris_fpless_backtrace,
+ "Display call chain using the subroutine return pointer.\n"
+ "Note that this displays the address after the jump to the "
+ "subroutine.", &cmdlist);
- add_setshow_boolean_cmd ("cris-dwarf2-cfi", class_support,
- &usr_cmd_cris_dwarf2_cfi,
- "Set the usage of Dwarf-2 CFI for CRIS.",
- "Show the usage of Dwarf-2 CFI for CRIS.",
- "Set to \"off\" if using gcc-cris < R59.",
- "Usage of Dwarf-2 CFI for CRIS is %d.",
- set_cris_dwarf2_cfi, NULL,
- &setlist, &showlist);
-
deprecated_add_core_fns (&cris_elf_core_fns);
+
}
/* Prints out all target specific values. */
@@ -3691,37 +3659,65 @@ cris_dump_tdep (struct gdbarch *gdbarch, struct ui_file *file)
{
fprintf_unfiltered (file, "cris_dump_tdep: tdep->cris_version = %i\n",
tdep->cris_version);
- fprintf_unfiltered (file, "cris_dump_tdep: tdep->cris_dwarf2_cfi = %i\n",
- tdep->cris_dwarf2_cfi);
+ fprintf_unfiltered (file, "cris_dump_tdep: tdep->cris_mode = %s\n",
+ tdep->cris_mode);
}
}
static void
-set_cris_version (char *ignore_args, int from_tty,
- struct cmd_list_element *c)
+cris_version_update (char *ignore_args, int from_tty,
+ struct cmd_list_element *c)
{
struct gdbarch_info info;
- usr_cmd_cris_version_valid = 1;
+ /* NOTE: cagney/2002-03-17: The deprecated_add_show_from_set()
+ function clones the set command passed as a parameter. The clone
+ operation will include (BUG?) any ``set'' command callback, if
+ present. Commands like ``info set'' call all the ``show''
+ command callbacks. Unfortunately, for ``show'' commands cloned
+ from ``set'', this includes callbacks belonging to ``set''
+ commands. Making this worse, this only occures if
+ deprecated_add_show_from_set() is called after add_cmd_sfunc()
+ (BUG?). */
+
+ /* From here on, trust the user's CRIS version setting. */
+ if (cmd_type (c) == set_cmd)
+ {
+ usr_cmd_cris_version_valid = 1;
- /* Update the current architecture, if needed. */
- gdbarch_info_init (&info);
- if (!gdbarch_update_p (info))
- internal_error (__FILE__, __LINE__,
- "cris_gdbarch_update: failed to update architecture.");
+ /* Update the current architecture, if needed. */
+ gdbarch_info_init (&info);
+ if (!gdbarch_update_p (info))
+ internal_error (__FILE__, __LINE__, "cris_gdbarch_update: failed to update architecture.");
+ }
}
static void
-set_cris_dwarf2_cfi (char *ignore_args, int from_tty,
- struct cmd_list_element *c)
+cris_mode_update (char *ignore_args, int from_tty,
+ struct cmd_list_element *c)
{
struct gdbarch_info info;
-
- /* Update the current architecture, if needed. */
- gdbarch_info_init (&info);
- if (!gdbarch_update_p (info))
- internal_error (__FILE__, __LINE__,
- "cris_gdbarch_update: failed to update architecture.");
+
+ /* NOTE: cagney/2002-03-17: The deprecated_add_show_from_set()
+ function clones the set command passed as a parameter. The clone
+ operation will include (BUG?) any ``set'' command callback, if
+ present. Commands like ``info set'' call all the ``show''
+ command callbacks. Unfortunately, for ``show'' commands cloned
+ from ``set'', this includes callbacks belonging to ``set''
+ commands. Making this worse, this only occures if
+ deprecated_add_show_from_set() is called after add_cmd_sfunc()
+ (BUG?). */
+
+ /* From here on, trust the user's CRIS mode setting. */
+ if (cmd_type (c) == set_cmd)
+ {
+ usr_cmd_cris_mode_valid = 1;
+
+ /* Update the current architecture, if needed. */
+ gdbarch_info_init (&info);
+ if (!gdbarch_update_p (info))
+ internal_error (__FILE__, __LINE__, "cris_gdbarch_update: failed to update architecture.");
+ }
}
static struct gdbarch *
@@ -3730,6 +3726,8 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
struct gdbarch *gdbarch;
struct gdbarch_tdep *tdep;
int cris_version;
+ const char *cris_mode;
+ int register_bytes;
if (usr_cmd_cris_version_valid)
{
@@ -3742,8 +3740,26 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
cris_version = 10;
}
+ if (usr_cmd_cris_mode_valid)
+ {
+ /* Trust the user's CRIS mode setting. */
+ cris_mode = usr_cmd_cris_mode;
+ }
+ else if (cris_version == 10)
+ {
+ /* Assume CRIS version 10 is in user mode. */
+ cris_mode = CRIS_MODE_USER;
+ }
+ else
+ {
+ /* Strictly speaking, older CRIS version don't have a supervisor mode,
+ but we regard its only mode as supervisor mode. */
+ cris_mode = CRIS_MODE_SUPERVISOR;
+ }
+
/* Make the current settings visible to the user. */
usr_cmd_cris_version = cris_version;
+ usr_cmd_cris_mode = cris_mode;
/* Find a candidate among the list of pre-declared architectures. Both
CRIS version and ABI must match. */
@@ -3751,10 +3767,8 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
arches != NULL;
arches = gdbarch_list_lookup_by_info (arches->next, &info))
{
- if ((gdbarch_tdep (arches->gdbarch)->cris_version
- == usr_cmd_cris_version)
- && (gdbarch_tdep (arches->gdbarch)->cris_dwarf2_cfi
- == usr_cmd_cris_dwarf2_cfi))
+ if ((gdbarch_tdep (arches->gdbarch)->cris_version == cris_version)
+ && (gdbarch_tdep (arches->gdbarch)->cris_mode == cris_mode))
return arches->gdbarch;
}
@@ -3762,8 +3776,8 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
tdep = (struct gdbarch_tdep *) xmalloc (sizeof (struct gdbarch_tdep));
gdbarch = gdbarch_alloc (&info, tdep);
- tdep->cris_version = usr_cmd_cris_version;
- tdep->cris_dwarf2_cfi = usr_cmd_cris_dwarf2_cfi;
+ tdep->cris_version = cris_version;
+ tdep->cris_mode = cris_mode;
/* INIT shall ensure that the INFO.BYTE_ORDER is non-zero. */
switch (info.byte_order)
@@ -3790,11 +3804,16 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_sp_regnum (gdbarch, 14);
set_gdbarch_pc_regnum (gdbarch, 15);
set_gdbarch_register_name (gdbarch, cris_register_name);
-
+
+ /* Length of ordinary registers used in push_word and a few other
+ places. register_size() is the real way to know how big a
+ register is. */
+ set_gdbarch_deprecated_register_size (gdbarch, 4);
set_gdbarch_double_bit (gdbarch, 64);
/* The default definition of a long double is 2 * TARGET_DOUBLE_BIT,
which means we have to set this explicitly. */
set_gdbarch_long_double_bit (gdbarch, 64);
+ set_gdbarch_register_bytes_ok (gdbarch, cris_register_bytes_ok);
set_gdbarch_cannot_store_register (gdbarch, cris_cannot_store_register);
set_gdbarch_cannot_fetch_register (gdbarch, cris_cannot_fetch_register);
@@ -3808,23 +3827,33 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
case 1:
case 2:
case 3:
+ /* Support for these may be added later. */
+ internal_error (__FILE__, __LINE__, "cris_gdbarch_init: unsupported CRIS version");
+ break;
+
case 8:
case 9:
- /* Old versions; not supported. */
- internal_error (__FILE__, __LINE__,
- "cris_gdbarch_init: unsupported CRIS version");
+ /* CRIS v8 and v9, a.k.a. ETRAX 100. General registers R0 - R15
+ (32 bits), special registers P0 - P1 (8 bits), P4 - P5 (16 bits),
+ and P8 - P14 (32 bits). */
+ register_bytes = (16 * 4) + (2 * 1) + (2 * 2) + (7 * 4);
break;
case 10:
case 11:
/* CRIS v10 and v11, a.k.a. ETRAX 100LX. In addition to ETRAX 100,
P7 (32 bits), and P15 (32 bits) have been implemented. */
+ register_bytes = (16 * 4) + (2 * 1) + (2 * 2) + (9 * 4);
break;
default:
internal_error (__FILE__, __LINE__, "cris_gdbarch_init: unknown CRIS version");
}
+ /* Returns the register offset for the first byte of register regno's space
+ in the saved register state. */
+ set_gdbarch_deprecated_register_byte (gdbarch, cris_register_offset);
+
set_gdbarch_register_type (gdbarch, cris_register_type);
/* Dummy frame functions. */
@@ -3844,16 +3873,9 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_unwind_sp (gdbarch, cris_unwind_sp);
set_gdbarch_unwind_dummy_id (gdbarch, cris_unwind_dummy_id);
- if (tdep->cris_dwarf2_cfi == 1)
- {
- /* Hook in the Dwarf-2 frame sniffer. */
- set_gdbarch_dwarf2_reg_to_regnum (gdbarch, cris_dwarf2_reg_to_regnum);
- dwarf2_frame_set_init_reg (gdbarch, cris_dwarf2_frame_init_reg);
- frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer);
- }
-
- frame_unwind_append_sniffer (gdbarch, cris_sigtramp_frame_sniffer);
-
+ /* FIXME: Hook in the DWARF CFI frame unwinder.
+ frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer);
+ */
frame_unwind_append_sniffer (gdbarch, cris_frame_sniffer);
frame_base_set_default (gdbarch, &cris_frame_base);