diff options
-rw-r--r-- | gdb/ChangeLog | 22 | ||||
-rw-r--r-- | gdb/cris-tdep.c | 446 |
2 files changed, 402 insertions, 66 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 278bcc9..358745c 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,25 @@ +2005-01-26 Orjan Friberg <orjanf@axis.com> + + * cris-tdep.c (enum cris_num_regs, enum cris_regnums) + (cris_sigtramp_frame_unwind_cache, cris_register_size): Update for + CRISv32. + (crisv32_single_step_through_delay, cris_can_use_hardware_watchpoint) + (cris_region_ok_for_watchpoint, cris_stopped_data_address) + (crisv32_cannot_fetch_register, crisv32_cannot_store_register) + (crisv32_register_type, cris_special_register_name) + (crisv32_register_name): New functions. + (cris_spec_reg_applicable): Recognize more versions. + (cris_register_name): Update with call to cris_special_register_name. + (find_cris_op): Filter out CRISv32 instructions. Tweaked comment and + warning when unable to find step target. + (CRISV10_ELF_NGREG, CRISV32_ELF_NGREG, crisv32_elf_gregset_t): Define. + (supply_gregset): Add struct gdbarch_tdep. Set pseudo-PC register for + CRISv32. + (fetch_core_registers): Update for CRISv32. + (cris_gdbarch_init): Set pc_regnum, register_type, num_regs, + register_name, cannot_store_register, cannot_fetch_register, + have_nonsteppable_watchpoint, single_step_through_delay for CRISv32. + 2005-01-26 Nick Roberts <nickrob@snap.net.nz> * interps.c (interpreter_exec_cmd): Use condition, diff --git a/gdb/cris-tdep.c b/gdb/cris-tdep.c index 784f39f..84f9402 100644 --- a/gdb/cris-tdep.c +++ b/gdb/cris-tdep.c @@ -56,7 +56,12 @@ enum cris_num_regs NUM_GENREGS = 16, /* There are 16 special registers. */ - NUM_SPECREGS = 16 + NUM_SPECREGS = 16, + + /* CRISv32 has a pseudo PC register, not noted here. */ + + /* CRISv32 has 16 support registers. */ + NUM_SUPPREGS = 16 }; /* Register numbers of various important registers. @@ -75,8 +80,9 @@ enum cris_num_regs enum cris_regnums { /* Enums with respect to the general registers, valid for all - CRIS versions. */ + CRIS versions. The frame pointer is always in R8. */ CRIS_FP_REGNUM = 8, + /* ABI related registers. */ STR_REGNUM = 9, RET_REGNUM = 10, ARG1_REGNUM = 10, @@ -84,23 +90,56 @@ enum cris_regnums ARG3_REGNUM = 12, ARG4_REGNUM = 13, - /* Enums with respect to the special registers, some of which may not be - applicable to all CRIS versions. */ - P0_REGNUM = 16, + /* Registers which happen to be common. */ VR_REGNUM = 17, - P2_REGNUM = 18, - P3_REGNUM = 19, + MOF_REGNUM = 23, + SRP_REGNUM = 27, + + /* CRISv10 et. al. specific registers. */ + P0_REGNUM = 16, P4_REGNUM = 20, CCR_REGNUM = 21, - MOF_REGNUM = 23, P8_REGNUM = 24, IBR_REGNUM = 25, IRP_REGNUM = 26, - SRP_REGNUM = 27, BAR_REGNUM = 28, DCCR_REGNUM = 29, BRP_REGNUM = 30, - USP_REGNUM = 31 + USP_REGNUM = 31, + + /* CRISv32 specific registers. */ + ACR_REGNUM = 15, + BZ_REGNUM = 16, + PID_REGNUM = 18, + SRS_REGNUM = 19, + WZ_REGNUM = 20, + EXS_REGNUM = 21, + EDA_REGNUM = 22, + DZ_REGNUM = 24, + EBP_REGNUM = 25, + ERP_REGNUM = 26, + NRP_REGNUM = 28, + CCS_REGNUM = 29, + CRISV32USP_REGNUM = 30, /* Shares name but not number with CRISv10. */ + SPC_REGNUM = 31, + CRISV32PC_REGNUM = 32, /* Shares name but not number with CRISv10. */ + + S0_REGNUM = 33, + S1_REGNUM = 34, + S2_REGNUM = 35, + S3_REGNUM = 36, + S4_REGNUM = 37, + S5_REGNUM = 38, + S6_REGNUM = 39, + S7_REGNUM = 40, + S8_REGNUM = 41, + S9_REGNUM = 42, + S10_REGNUM = 43, + S11_REGNUM = 44, + S12_REGNUM = 45, + S13_REGNUM = 46, + S14_REGNUM = 47, + S15_REGNUM = 48, }; extern const struct cris_spec_reg cris_spec_regs[]; @@ -311,20 +350,52 @@ cris_sigtramp_frame_unwind_cache (struct frame_info *next_frame, 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); + if (tdep->cris_version == 10) + { + /* 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); + } + else + { + /* CRISv32. */ + /* R0 to R13 are stored in order at offset (1 * 4) in + struct pt_regs. */ + for (i = 0; i <= 13; i++) + info->saved_regs[i].addr = addr + ((i + 1) * 4); + + info->saved_regs[ACR_REGNUM].addr = addr + (15 * 4); + info->saved_regs[SRS_REGNUM].addr = addr + (16 * 4); + info->saved_regs[MOF_REGNUM].addr = addr + (17 * 4); + info->saved_regs[SPC_REGNUM].addr = addr + (18 * 4); + info->saved_regs[CCS_REGNUM].addr = addr + (19 * 4); + info->saved_regs[SRP_REGNUM].addr = addr + (20 * 4); + info->saved_regs[ERP_REGNUM].addr = addr + (21 * 4); + info->saved_regs[EXS_REGNUM].addr = addr + (22 * 4); + info->saved_regs[EDA_REGNUM].addr = addr + (23 * 4); + + /* FIXME: If ERP is in a delay slot at this point then the PC will + be wrong at this point. This problem manifests itself in the + sigaltstack.exp test case, which occasionally generates FAILs when + the signal is received while in a delay slot. + + This could be solved by a couple of read_memory_unsigned_integer and a + trad_frame_set_value. */ + info->saved_regs[PC_REGNUM] = info->saved_regs[ERP_REGNUM]; + + info->saved_regs[SP_REGNUM].addr = addr + (25 * 4); + } return info; } @@ -375,7 +446,72 @@ cris_sigtramp_frame_sniffer (struct frame_info *next_frame) return NULL; } +int +crisv32_single_step_through_delay (struct gdbarch *gdbarch, + struct frame_info *this_frame) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); + ULONGEST erp; + int ret = 0; + char buf[4]; + + frame_unwind_register (this_frame, ERP_REGNUM, buf); + erp = extract_unsigned_integer (buf, 4); + + if (erp & 0x1) + { + /* In delay slot - check if there's a breakpoint at the preceding + instruction. */ + if (breakpoint_here_p (erp & ~0x1)) + ret = 1; + } + return ret; +} + +/* Hardware watchpoint support. */ + +/* We support 6 hardware data watchpoints, but cannot trigger on execute + (any combination of read/write is fine). */ + +int +cris_can_use_hardware_watchpoint (int type, int count, int other) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); + + /* No bookkeeping is done here; it is handled by the remote debug agent. */ + + if (tdep->cris_version != 32) + return 0; + else + /* CRISv32: Six data watchpoints, one for instructions. */ + return (((type == bp_read_watchpoint || type == bp_access_watchpoint + || type == bp_hardware_watchpoint) && count <= 6) + || (type == bp_hardware_breakpoint && count <= 1)); +} + +/* The CRISv32 hardware data watchpoints work by specifying ranges, + which have no alignment or length restrictions. */ + +int +cris_region_ok_for_watchpoint (CORE_ADDR addr, int len) +{ + return 1; +} + +/* If the inferior has some watchpoint that triggered, return the + address associated with that watchpoint. Otherwise, return + zero. */ + +CORE_ADDR +cris_stopped_data_address (void) +{ + CORE_ADDR eda; + eda = read_register (EDA_REGNUM); + return eda; +} + /* The instruction environment needed to find single-step breakpoints. */ + typedef struct instruction_environment { @@ -1286,8 +1422,18 @@ cris_spec_reg_applicable (struct cris_spec_reg spec_reg) return (version == 8 || version == 9); case cris_ver_v8p: return (version >= 8); + case cris_ver_v0_10: + return (version >= 0 && version <= 10); + case cris_ver_v3_10: + return (version >= 3 && version <= 10); + case cris_ver_v8_10: + return (version >= 8 && version <= 10); + case cris_ver_v10: + return (version == 10); case cris_ver_v10p: return (version >= 10); + case cris_ver_v32p: + return (version >= 32); default: /* Invalid cris version. */ return 0; @@ -1300,6 +1446,7 @@ cris_spec_reg_applicable (struct cris_spec_reg spec_reg) static int cris_register_size (int regno) { + struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); int i; int spec_regno; @@ -1308,15 +1455,13 @@ cris_register_size (int regno) /* General registers (R0 - R15) are 32 bits. */ return 4; } - else if (regno >= NUM_GENREGS && regno < NUM_REGS) + else if (regno >= NUM_GENREGS && regno < (NUM_GENREGS + NUM_SPECREGS)) { /* Special register (R16 - R31). cris_spec_regs is zero-based. Adjust regno accordingly. */ spec_regno = regno - NUM_GENREGS; - /* The entries in cris_spec_regs are stored in register number order, - which means we can shortcut into the array when searching it. */ - for (i = spec_regno; cris_spec_regs[i].name != NULL; i++) + for (i = 0; cris_spec_regs[i].name != NULL; i++) { if (cris_spec_regs[i].number == spec_regno && cris_spec_reg_applicable (cris_spec_regs[i])) @@ -1326,11 +1471,15 @@ cris_register_size (int regno) /* Special register not applicable to this CRIS version. */ return 0; } - else + else if (regno >= PC_REGNUM && regno < NUM_REGS) { - /* Invalid register. */ - return -1; + /* This will apply to CRISv32 only where there are additional registers + after the special registers (pseudo PC and support registers). */ + return 4; } + + + return -1; } /* Nonzero if regno should not be fetched from the target. This is the case @@ -1373,6 +1522,46 @@ cris_cannot_store_register (int regno) return 0; } +/* Nonzero if regno should not be fetched from the target. This is the case + for unimplemented (size 0) and non-existant registers. */ + +static int +crisv32_cannot_fetch_register (int regno) +{ + return ((regno < 0 || regno >= NUM_REGS) + || (cris_register_size (regno) == 0)); +} + +/* Nonzero if regno should not be written to the target, for various + reasons. */ + +static int +crisv32_cannot_store_register (int regno) +{ + /* There are three kinds of registers we refuse to write to. + 1. Those that not implemented. + 2. Those that are read-only (depends on the processor mode). + 3. Those registers to which a write has no effect. + */ + + if (regno < 0 || regno >= NUM_REGS || cris_register_size (regno) == 0) + /* Not implemented. */ + return 1; + + else if (regno == VR_REGNUM) + /* Read-only. */ + return 1; + + else if (regno == BZ_REGNUM || regno == WZ_REGNUM || regno == DZ_REGNUM) + /* Writing has no effect. */ + return 1; + + /* Many special registers are read-only in user mode. Let the debug + agent decide whether they are writable. */ + + return 0; +} + /* Return the GDB type (defined in gdbtypes.c) for the "standard" data type of data in register regno. */ @@ -1396,6 +1585,32 @@ cris_register_type (struct gdbarch *gdbarch, int regno) return builtin_type_int0; } +static struct type * +crisv32_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 <= ACR_REGNUM) + || (regno >= EXS_REGNUM && regno <= SPC_REGNUM) + || (regno == PID_REGNUM) + || (regno >= S0_REGNUM && regno <= S15_REGNUM)) + /* Note: R8 and SP taken care of by previous clause. */ + return builtin_type_uint32; + else if (regno == WZ_REGNUM) + return builtin_type_uint16; + else if (regno == BZ_REGNUM || regno == VR_REGNUM || regno == SRS_REGNUM) + return builtin_type_uint8; + else + { + /* Invalid (unimplemented) register. Should not happen as there are + no unimplemented CRISv32 registers. */ + warning ("crisv32_register_type: unknown regno %d", regno); + return builtin_type_int0; + } +} + /* Stores a function return value of type type, where valbuf is the address of the value to be stored. */ @@ -1430,6 +1645,29 @@ cris_store_return_value (struct type *type, struct regcache *regcache, unimplemented register. */ static const char * +cris_special_register_name (int regno) +{ + int spec_regno; + int i; + + /* Special register (R16 - R31). cris_spec_regs is zero-based. + Adjust regno accordingly. */ + spec_regno = regno - NUM_GENREGS; + + /* Assume nothing about the layout of the cris_spec_regs struct + when searching. */ + for (i = 0; cris_spec_regs[i].name != NULL; i++) + { + if (cris_spec_regs[i].number == spec_regno + && cris_spec_reg_applicable (cris_spec_regs[i])) + /* Go with the first applicable register. */ + return cris_spec_regs[i].name; + } + /* Special register not applicable to this CRIS version. */ + return NULL; +} + +static const char * cris_register_name (int regno) { static char *cris_genreg_names[] = @@ -1438,9 +1676,6 @@ cris_register_name (int regno) "r8", "r9", "r10", "r11", \ "r12", "r13", "sp", "pc" }; - int i; - int spec_regno; - if (regno >= 0 && regno < NUM_GENREGS) { /* General register. */ @@ -1448,22 +1683,49 @@ cris_register_name (int regno) } else if (regno >= NUM_GENREGS && regno < NUM_REGS) { - /* Special register (R16 - R31). cris_spec_regs is zero-based. - Adjust regno accordingly. */ - spec_regno = regno - NUM_GENREGS; - - /* The entries in cris_spec_regs are stored in register number order, - which means we can shortcut into the array when searching it. */ - for (i = spec_regno; cris_spec_regs[i].name != NULL; i++) - { - if (cris_spec_regs[i].number == spec_regno - && cris_spec_reg_applicable (cris_spec_regs[i])) - /* Go with the first applicable register. */ - return cris_spec_regs[i].name; - } - /* Special register not applicable to this CRIS version. */ + return cris_special_register_name (regno); + } + else + { + /* Invalid register. */ return NULL; } +} + +static const char * +crisv32_register_name (int regno) +{ + static char *crisv32_genreg_names[] = + { "r0", "r1", "r2", "r3", \ + "r4", "r5", "r6", "r7", \ + "r8", "r9", "r10", "r11", \ + "r12", "r13", "sp", "acr" + }; + + static char *crisv32_sreg_names[] = + { "s0", "s1", "s2", "s3", \ + "s4", "s5", "s6", "s7", \ + "s8", "s9", "s10", "s11", \ + "s12", "s13", "s14", "s15" + }; + + if (regno >= 0 && regno < NUM_GENREGS) + { + /* General register. */ + return crisv32_genreg_names[regno]; + } + else if (regno >= NUM_GENREGS && regno < (NUM_GENREGS + NUM_SPECREGS)) + { + return cris_special_register_name (regno); + } + else if (regno == PC_REGNUM) + { + return "pc"; + } + else if (regno >= S0_REGNUM && regno <= S15_REGNUM) + { + return crisv32_sreg_names[regno - S0_REGNUM]; + } else { /* Invalid register. */ @@ -1685,7 +1947,9 @@ find_cris_op (unsigned short insn, inst_env_type *inst_env) for (i = 0; cris_opcodes[i].name != NULL; i++) { if (((cris_opcodes[i].match & insn) == cris_opcodes[i].match) - && ((cris_opcodes[i].lose & insn) == 0)) + && ((cris_opcodes[i].lose & insn) == 0) + /* Only CRISv10 instructions, please. */ + && (cris_opcodes[i].applicable_version != cris_ver_v32p)) { level_of_match = constraint (insn, cris_opcodes[i].args, inst_env); if (level_of_match >= 0) @@ -1788,8 +2052,9 @@ cris_software_single_step (enum target_signal ignore, int insert_breakpoints) int status = find_step_target (&inst_env); if (status == -1) { - /* Could not find a target. FIXME: Should do something. */ - warning ("cris_software_single_step: unable to find step target"); + /* Could not find a target. Things are likely to go downhill + from here. */ + warning ("CRIS software single step could not find a step target."); } else { @@ -3515,13 +3780,18 @@ cris_delayed_get_disassembler (bfd_vma addr, struct disassemble_info *info) typedef unsigned long elf_greg_t; /* Same as user_regs_struct struct in <asm/user.h>. */ -typedef elf_greg_t elf_gregset_t[35]; +#define CRISV10_ELF_NGREG 35 +typedef elf_greg_t elf_gregset_t[CRISV10_ELF_NGREG]; + +#define CRISV32_ELF_NGREG 32 +typedef elf_greg_t crisv32_elf_gregset_t[CRISV32_ELF_NGREG]; /* Unpack an elf_gregset_t into GDB's register cache. */ static void supply_gregset (elf_gregset_t *gregsetp) { + struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch); int i; elf_greg_t *regp = *gregsetp; static char zerobuf[4] = {0}; @@ -3532,6 +3802,18 @@ supply_gregset (elf_gregset_t *gregsetp) { regcache_raw_supply (current_regcache, i, (char *)®p[i]); } + + if (tdep->cris_version == 32) + { + /* Needed to set pseudo-register PC for CRISv32. */ + /* FIXME: If ERP is in a delay slot at this point then the PC will + be wrong. Issue a warning to alert the user. */ + regcache_raw_supply (current_regcache, PC_REGNUM, + (char *)®p[ERP_REGNUM]); + + if (*(char *)®p[ERP_REGNUM] & 0x1) + fprintf_unfiltered (gdb_stderr, "Warning: PC in delay slot\n"); + } } /* Use a local version of this function to get the correct types for @@ -3546,7 +3828,8 @@ fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, switch (which) { case 0: - if (core_reg_size != sizeof (gregset)) + if (core_reg_size != sizeof (elf_gregset_t) + && core_reg_size != sizeof (crisv32_elf_gregset_t)) { warning ("wrong size gregset struct in core file"); } @@ -3706,6 +3989,10 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) /* Trust the user's CRIS version setting. */ cris_version = usr_cmd_cris_version; } + else if (info.abfd && bfd_get_mach (info.abfd) == bfd_mach_cris_v32) + { + cris_version = 32; + } else { /* Assume it's CRIS version 10. */ @@ -3755,18 +4042,16 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) cris_reg_struct_has_addr); set_gdbarch_deprecated_use_struct_convention (gdbarch, always_use_struct_convention); - /* There are 32 registers (some of which may not be implemented). */ - set_gdbarch_num_regs (gdbarch, 32); 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_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_cannot_store_register (gdbarch, cris_cannot_store_register); - set_gdbarch_cannot_fetch_register (gdbarch, cris_cannot_fetch_register); + set_gdbarch_long_double_bit (gdbarch, 64); /* The total amount of space needed to store (in an array called registers) GDB's copy of the machine's register state. Note: We can not use @@ -3789,20 +4074,49 @@ cris_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) 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. */ + set_gdbarch_pc_regnum (gdbarch, 15); + set_gdbarch_register_type (gdbarch, cris_register_type); + /* There are 32 registers (some of which may not be implemented). */ + set_gdbarch_num_regs (gdbarch, 32); + set_gdbarch_register_name (gdbarch, cris_register_name); + set_gdbarch_cannot_store_register (gdbarch, cris_cannot_store_register); + set_gdbarch_cannot_fetch_register (gdbarch, cris_cannot_fetch_register); + + set_gdbarch_software_single_step (gdbarch, cris_software_single_step); + break; + + case 32: + /* CRIS v32. General registers R0 - R15 (32 bits), special registers + P0 - P15 (32 bits) except P0, P1, P3 (8 bits) and P4 (16 bits) + and pseudo-register PC (32 bits). */ + set_gdbarch_pc_regnum (gdbarch, 32); + set_gdbarch_register_type (gdbarch, crisv32_register_type); + /* 32 registers + pseudo-register PC + 16 support registers. */ + set_gdbarch_num_regs (gdbarch, 32 + 1 + 16); + set_gdbarch_register_name (gdbarch, crisv32_register_name); + + set_gdbarch_cannot_store_register + (gdbarch, crisv32_cannot_store_register); + set_gdbarch_cannot_fetch_register + (gdbarch, crisv32_cannot_fetch_register); + + set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1); + + set_gdbarch_single_step_through_delay + (gdbarch, crisv32_single_step_through_delay); + break; default: - internal_error (__FILE__, __LINE__, "cris_gdbarch_init: unknown CRIS version"); + internal_error (__FILE__, __LINE__, + "cris_gdbarch_init: unknown CRIS version"); } - set_gdbarch_register_type (gdbarch, cris_register_type); - - /* Dummy frame functions. */ + /* Dummy frame functions (shared between CRISv10 and CRISv32 since they + have the same ABI). */ set_gdbarch_push_dummy_code (gdbarch, cris_push_dummy_code); set_gdbarch_push_dummy_call (gdbarch, cris_push_dummy_call); set_gdbarch_frame_align (gdbarch, cris_frame_align); - - set_gdbarch_software_single_step (gdbarch, cris_software_single_step); set_gdbarch_skip_prologue (gdbarch, cris_skip_prologue); /* The stack grows downward. */ |