diff options
author | David Brownell <dbrownell@users.sourceforge.net> | 2009-11-24 01:27:29 -0800 |
---|---|---|
committer | David Brownell <dbrownell@users.sourceforge.net> | 2009-11-24 01:27:29 -0800 |
commit | 3efc99b34a934cb4d657ec27a164769c46c10f28 (patch) | |
tree | c08b985f274dc428f4c769f20e471b8ca81879c7 /src | |
parent | ec64acf536942168b4e038c6720c83687d3a0d08 (diff) | |
download | openocd+libswd-3efc99b34a934cb4d657ec27a164769c46c10f28.tar.gz openocd+libswd-3efc99b34a934cb4d657ec27a164769c46c10f28.tar.bz2 openocd+libswd-3efc99b34a934cb4d657ec27a164769c46c10f28.tar.xz openocd+libswd-3efc99b34a934cb4d657ec27a164769c46c10f28.zip |
ARM11: remove old R0..R15/CPSR code
This finishes the basic switchover to the new register code,
for everything except the debug registers. (And maybe we
shouldn't have a cache for *those* which works this way...)
The context save/restore code now uses the new code, but
it's in a slightly different sequence. That should be fine
since the R0/PC/CPSR stuff is all that really matters (and
if we can update those, we can update the rest).
Now there's no longer a way any code can be confused about
which copy of "r1" (etc) to use.
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Diffstat (limited to 'src')
-rw-r--r-- | src/target/arm11.c | 265 | ||||
-rw-r--r-- | src/target/arm11.h | 5 |
2 files changed, 74 insertions, 196 deletions
diff --git a/src/target/arm11.c b/src/target/arm11.c index 3bdb4443..a5175af7 100644 --- a/src/target/arm11.c +++ b/src/target/arm11.c @@ -48,26 +48,6 @@ static bool arm11_config_hardware_step = false; enum arm11_regtype { - ARM11_REGISTER_CORE, - ARM11_REGISTER_CPSR, - - ARM11_REGISTER_FX, - ARM11_REGISTER_FPS, - - ARM11_REGISTER_FIQ, - ARM11_REGISTER_SVC, - ARM11_REGISTER_ABT, - ARM11_REGISTER_IRQ, - ARM11_REGISTER_UND, - ARM11_REGISTER_MON, - - ARM11_REGISTER_SPSR_FIQ, - ARM11_REGISTER_SPSR_SVC, - ARM11_REGISTER_SPSR_ABT, - ARM11_REGISTER_SPSR_IRQ, - ARM11_REGISTER_SPSR_UND, - ARM11_REGISTER_SPSR_MON, - /* debug regs */ ARM11_REGISTER_DSCR, ARM11_REGISTER_WDTR, @@ -86,25 +66,6 @@ struct arm11_reg_defs /* update arm11_regcache_ids when changing this */ static const struct arm11_reg_defs arm11_reg_defs[] = { - {"r0", 0, 0, ARM11_REGISTER_CORE}, - {"r1", 1, 1, ARM11_REGISTER_CORE}, - {"r2", 2, 2, ARM11_REGISTER_CORE}, - {"r3", 3, 3, ARM11_REGISTER_CORE}, - {"r4", 4, 4, ARM11_REGISTER_CORE}, - {"r5", 5, 5, ARM11_REGISTER_CORE}, - {"r6", 6, 6, ARM11_REGISTER_CORE}, - {"r7", 7, 7, ARM11_REGISTER_CORE}, - {"r8", 8, 8, ARM11_REGISTER_CORE}, - {"r9", 9, 9, ARM11_REGISTER_CORE}, - {"r10", 10, 10, ARM11_REGISTER_CORE}, - {"r11", 11, 11, ARM11_REGISTER_CORE}, - {"r12", 12, 12, ARM11_REGISTER_CORE}, - {"sp", 13, 13, ARM11_REGISTER_CORE}, - {"lr", 14, 14, ARM11_REGISTER_CORE}, - {"pc", 15, 15, ARM11_REGISTER_CORE}, - - {"cpsr", 0, 25, ARM11_REGISTER_CPSR}, - /* Debug Registers */ {"dscr", 0, -1, ARM11_REGISTER_DSCR}, {"wdtr", 0, -1, ARM11_REGISTER_WDTR}, @@ -113,30 +74,6 @@ static const struct arm11_reg_defs arm11_reg_defs[] = enum arm11_regcache_ids { - ARM11_RC_R0, - ARM11_RC_RX = ARM11_RC_R0, - - ARM11_RC_R1, - ARM11_RC_R2, - ARM11_RC_R3, - ARM11_RC_R4, - ARM11_RC_R5, - ARM11_RC_R6, - ARM11_RC_R7, - ARM11_RC_R8, - ARM11_RC_R9, - ARM11_RC_R10, - ARM11_RC_R11, - ARM11_RC_R12, - ARM11_RC_R13, - ARM11_RC_SP = ARM11_RC_R13, - ARM11_RC_R14, - ARM11_RC_LR = ARM11_RC_R14, - ARM11_RC_R15, - ARM11_RC_PC = ARM11_RC_R15, - - ARM11_RC_CPSR, - ARM11_RC_DSCR, ARM11_RC_WDTR, ARM11_RC_RDTR, @@ -229,6 +166,8 @@ static int arm11_on_enter_debug_state(struct arm11_common *arm11) arm11->reg_list[i].dirty = 0; } + /* See e.g. ARM1136 TRM, "14.8.4 Entering Debug state" */ + /* Save DSCR */ CHECK_RETVAL(arm11_read_DSCR(arm11, &R(DSCR))); @@ -254,10 +193,12 @@ static int arm11_on_enter_debug_state(struct arm11_common *arm11) } - /* DSCR: set ARM11_DSCR_EXECUTE_ARM_INSTRUCTION_ENABLE */ - /* ARM1176 spec says this is needed only for wDTR/rDTR's "ITR mode", but not to issue ITRs - ARM1136 seems to require this to issue ITR's as well */ - + /* DSCR: set ARM11_DSCR_EXECUTE_ARM_INSTRUCTION_ENABLE + * + * ARM1176 spec says this is needed only for wDTR/rDTR's "ITR mode", + * but not to issue ITRs. ARM1136 seems to require this to issue + * ITR's as well... + */ uint32_t new_dscr = R(DSCR) | ARM11_DSCR_EXECUTE_ARM_INSTRUCTION_ENABLE; /* this executes JTAG queue: */ @@ -297,6 +238,11 @@ static int arm11_on_enter_debug_state(struct arm11_common *arm11) } #endif + /* Save registers. + * + * NOTE: ARM1136 TRM suggests saving just R0 here now, then + * CPSR and PC after the rDTR stuff. We do it all at once. + */ retval = arm_dpm_read_current_registers(&arm11->dpm); if (retval != ERROR_OK) LOG_ERROR("DPM REG READ -- fail %d", retval); @@ -305,19 +251,7 @@ static int arm11_on_enter_debug_state(struct arm11_common *arm11) if (retval != ERROR_OK) return retval; - /* save r0 - r14 */ - - /** \todo TODO: handle other mode registers */ - - for (size_t i = 0; i < 15; i++) - { - /* MCR p14,0,R?,c0,c5,0 */ - retval = arm11_run_instr_data_from_core(arm11, 0xEE000E15 | (i << 12), &R(RX + i), 1); - if (retval != ERROR_OK) - return retval; - } - - /* save rDTR */ + /* maybe save rDTR */ /* check rDTRfull in DSCR */ @@ -333,34 +267,9 @@ static int arm11_on_enter_debug_state(struct arm11_common *arm11) arm11->reg_list[ARM11_RC_RDTR].valid = 0; } - /* save CPSR */ - - /* MRS r0,CPSR (move CPSR -> r0 (-> wDTR -> local var)) */ - retval = arm11_run_instr_data_from_core_via_r0(arm11, 0xE10F0000, &R(CPSR)); - if (retval != ERROR_OK) - return retval; - - /* save PC */ - - /* MOV R0,PC (move PC -> r0 (-> wDTR -> local var)) */ - retval = arm11_run_instr_data_from_core_via_r0(arm11, 0xE1A0000F, &R(PC)); - if (retval != ERROR_OK) - return retval; - - /* adjust PC depending on ARM state */ - - if (R(CPSR) & ARM11_CPSR_J) /* Java state */ - { - arm11->reg_values[ARM11_RC_PC] -= 0; - } - else if (R(CPSR) & ARM11_CPSR_T) /* Thumb state */ - { - arm11->reg_values[ARM11_RC_PC] -= 4; - } - else /* ARM state */ - { - arm11->reg_values[ARM11_RC_PC] -= 8; - } + /* REVISIT Now that we've saved core state, there's may also + * be MMU and cache state to care about ... + */ if (arm11->simulate_reset_on_next_halt) { @@ -393,29 +302,16 @@ static int arm11_leave_debug_state(struct arm11_common *arm11) { int retval; - retval = arm11_run_instr_data_prepare(arm11); - if (retval != ERROR_OK) - return retval; - - /** \todo TODO: handle other mode registers */ - - /* restore R1 - R14 */ - - for (unsigned i = 1; i < 15; i++) - { - if (!arm11->reg_list[ARM11_RC_RX + i].dirty) - continue; - - /* MRC p14,0,r?,c0,c5,0 */ - arm11_run_instr_data_to_core1(arm11, - 0xee100e15 | (i << 12), R(RX + i)); + /* See e.g. ARM1136 TRM, "14.8.5 Leaving Debug state" */ - // LOG_DEBUG("RESTORE R%u %08x", i, R(RX + i)); - } + /* NOTE: the ARM1136 TRM suggests restoring all registers + * except R0/PC/CPSR right now. Instead, we do them all + * at once, just a bit later on. + */ - retval = arm11_run_instr_data_finish(arm11); - if (retval != ERROR_OK) - return retval; + /* REVISIT once we start caring about MMU and cache state, + * address it here ... + */ /* spec says clear wDTR and rDTR; we assume they are clear as otherwise our programming would be sloppy */ @@ -438,50 +334,27 @@ static int arm11_leave_debug_state(struct arm11_common *arm11) } } -/* DEBUG for now, trust "new" code only for shadowed registers */ -retval = arm_dpm_write_dirty_registers(&arm11->dpm); - - retval = arm11_run_instr_data_prepare(arm11); - if (retval != ERROR_OK) - return retval; - - /* restore original wDTR */ - + /* maybe restore original wDTR */ if ((R(DSCR) & ARM11_DSCR_WDTR_FULL) || arm11->reg_list[ARM11_RC_WDTR].dirty) { + retval = arm11_run_instr_data_prepare(arm11); + if (retval != ERROR_OK) + return retval; + /* MCR p14,0,R0,c0,c5,0 */ retval = arm11_run_instr_data_to_core_via_r0(arm11, 0xee000e15, R(WDTR)); if (retval != ERROR_OK) return retval; - } - - /* restore CPSR */ - - /* MSR CPSR,R0*/ - retval = arm11_run_instr_data_to_core_via_r0(arm11, 0xe129f000, R(CPSR)); - if (retval != ERROR_OK) - return retval; - - - /* restore PC */ - - /* MOV PC,R0 */ - retval = arm11_run_instr_data_to_core_via_r0(arm11, 0xe1a0f000, R(PC)); - if (retval != ERROR_OK) - return retval; + retval = arm11_run_instr_data_finish(arm11); + if (retval != ERROR_OK) + return retval; + } - /* restore R0 */ - - /* MRC p14,0,r0,c0,c5,0 */ - arm11_run_instr_data_to_core1(arm11, 0xee100e15, R(R0)); - - retval = arm11_run_instr_data_finish(arm11); - if (retval != ERROR_OK) - return retval; - -/* DEBUG use this when "new" code is really managing core registers */ -// retval = arm_dpm_write_dirty_registers(&arm11->dpm); + /* restore CPSR, PC, and R0 ... after flushing any modified + * registers. + */ + retval = arm_dpm_write_dirty_registers(&arm11->dpm); register_cache_invalidate(arm11->arm.core_cache); @@ -489,7 +362,7 @@ retval = arm_dpm_write_dirty_registers(&arm11->dpm); arm11_write_DSCR(arm11, R(DSCR)); - /* restore rDTR */ + /* maybe restore rDTR */ if (R(DSCR) & ARM11_DSCR_RDTR_FULL || arm11->reg_list[ARM11_RC_RDTR].dirty) { @@ -509,6 +382,8 @@ retval = arm_dpm_write_dirty_registers(&arm11->dpm); arm11_add_dr_scan_vc(ARRAY_SIZE(chain5_fields), chain5_fields, TAP_DRPAUSE); } + /* now processor is ready to RESTART */ + return ERROR_OK; } @@ -639,6 +514,19 @@ static int arm11_halt(struct target *target) return ERROR_OK; } +static uint32_t +arm11_nextpc(struct arm11_common *arm11, int current, uint32_t address) +{ + void *value = arm11->arm.core_cache->reg_list[15].value; + + if (!current) + buf_set_u32(value, 0, 32, address); + else + address = buf_get_u32(value, 0, 32); + + return address; +} + static int arm11_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution) { @@ -657,10 +545,9 @@ static int arm11_resume(struct target *target, int current, return ERROR_TARGET_NOT_HALTED; } - if (!current) - R(PC) = address; + address = arm11_nextpc(arm11, current, address); - LOG_DEBUG("RESUME PC %08" PRIx32 "%s", R(PC), !current ? "!" : ""); + LOG_DEBUG("RESUME PC %08" PRIx32 "%s", address, !current ? "!" : ""); /* clear breakpoints/watchpoints and VCR*/ arm11_sc7_clear_vbw(arm11); @@ -677,7 +564,7 @@ static int arm11_resume(struct target *target, int current, for (bp = target->breakpoints; bp; bp = bp->next) { - if (bp->address == R(PC)) + if (bp->address == address) { LOG_DEBUG("must step over %08" PRIx32 "", bp->address); arm11_step(target, 1, 0, 0); @@ -778,33 +665,28 @@ static int arm11_step(struct target *target, int current, struct arm11_common *arm11 = target_to_arm11(target); - if (!current) - R(PC) = address; + address = arm11_nextpc(arm11, current, address); - LOG_DEBUG("STEP PC %08" PRIx32 "%s", R(PC), !current ? "!" : ""); + LOG_DEBUG("STEP PC %08" PRIx32 "%s", address, !current ? "!" : ""); /** \todo TODO: Thumb not supported here */ uint32_t next_instruction; - CHECK_RETVAL(arm11_read_memory_word(arm11, R(PC), &next_instruction)); + CHECK_RETVAL(arm11_read_memory_word(arm11, address, &next_instruction)); /* skip over BKPT */ if ((next_instruction & 0xFFF00070) == 0xe1200070) { - R(PC) += 4; - arm11->reg_list[ARM11_RC_PC].valid = 1; - arm11->reg_list[ARM11_RC_PC].dirty = 0; + address = arm11_nextpc(arm11, 0, address + 4); LOG_DEBUG("Skipping BKPT"); } /* skip over Wait for interrupt / Standby */ /* mcr 15, 0, r?, cr7, cr0, {4} */ else if ((next_instruction & 0xFFFF0FFF) == 0xee070f90) { - R(PC) += 4; - arm11->reg_list[ARM11_RC_PC].valid = 1; - arm11->reg_list[ARM11_RC_PC].dirty = 0; + address = arm11_nextpc(arm11, 0, address + 4); LOG_DEBUG("Skipping WFI"); } /* ignore B to self */ @@ -844,7 +726,7 @@ static int arm11_step(struct target *target, int current, * FIXME Thumb stepping likely needs to use 0x03 * or 0xc0 byte masks, not 0x0f. */ - brp[0].value = R(PC); + brp[0].value = address; brp[1].value = 0x1 | (3 << 1) | (0x0F << 5) | (0 << 14) | (0 << 16) | (0 << 20) | (2 << 21); @@ -1045,8 +927,7 @@ static int arm11_read_memory_inner(struct target *target, switch (size) { case 1: - /** \todo TODO: check if dirty is the right choice to force a rewrite on arm11_resume() */ - arm11->reg_list[ARM11_RC_R1].dirty = 1; + arm11->arm.core_cache->reg_list[1].dirty = true; for (size_t i = 0; i < count; i++) { @@ -1066,7 +947,7 @@ static int arm11_read_memory_inner(struct target *target, case 2: { - arm11->reg_list[ARM11_RC_R1].dirty = 1; + arm11->arm.core_cache->reg_list[1].dirty = true; for (size_t i = 0; i < count; i++) { @@ -1150,7 +1031,7 @@ static int arm11_write_memory_inner(struct target *target, { case 1: { - arm11->reg_list[ARM11_RC_R1].dirty = 1; + arm11->arm.core_cache->reg_list[1].dirty = true; for (size_t i = 0; i < count; i++) { @@ -1172,7 +1053,7 @@ static int arm11_write_memory_inner(struct target *target, case 2: { - arm11->reg_list[ARM11_RC_R1].dirty = 1; + arm11->arm.core_cache->reg_list[1].dirty = true; for (size_t i = 0; i < count; i++) { @@ -1363,9 +1244,9 @@ static int arm11_init_target(struct command_context *cmd_ctx, { /* Initialize anything we can set up without talking to the target */ - /* FIXME Switch to use the standard build_reg_cache() not custom - * code. Do it from examine(), after we check whether we're - * an arm1176 and thus support the Secure Monitor mode. + /* REVISIT do we really want such a debug-registers-only cache? + * If we do, it should probably be handled purely by the DPM code, + * so it works identically on the v7a/v7r cores. */ return arm11_build_reg_cache(target); } @@ -1535,9 +1416,8 @@ static int arm11_build_reg_cache(struct target *target) arm11->reg_list = reg_list; - /* Build the process context cache */ - cache->name = "arm11 registers"; - cache->next = NULL; + /* build cache for some of the debug registers */ + cache->name = "arm11 debug registers"; cache->reg_list = reg_list; cache->num_regs = ARM11_REGCACHE_COUNT; @@ -1545,7 +1425,6 @@ static int arm11_build_reg_cache(struct target *target) (*cache_p) = cache; arm11->core_cache = cache; -// armv7m->process_context = cache; size_t i; diff --git a/src/target/arm11.h b/src/target/arm11.h index 033ba899..c3f4e864 100644 --- a/src/target/arm11.h +++ b/src/target/arm11.h @@ -26,8 +26,7 @@ #include "armv4_5.h" #include "arm_dpm.h" -/* TEMPORARY -- till we switch to the shared infrastructure */ -#define ARM11_REGCACHE_COUNT 20 +#define ARM11_REGCACHE_COUNT 3 #define ARM11_TAP_DEFAULT TAP_INVALID @@ -70,7 +69,7 @@ struct arm11_common bool simulate_reset_on_next_halt; /**< Perform cleanups of the ARM state on next halt */ - /** \name Shadow registers to save processor state */ + /** \name Shadow registers to save debug state */ /*@{*/ struct reg * reg_list; /**< target register list */ |