diff options
Diffstat (limited to 'gdb/cris-tdep.c')
-rw-r--r-- | gdb/cris-tdep.c | 726 |
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); |