diff options
author | Evgeniy Didin <didin@synopsys.com> | 2020-03-18 16:12:04 +0300 |
---|---|---|
committer | Oleksij Rempel <linux@rempel-privat.de> | 2020-05-08 05:57:12 +0100 |
commit | 0af37282c742dfc3492348f44f66215939148fb0 (patch) | |
tree | 91b0255d1edb4727856985a35bb3200ec4c9ec73 /src | |
parent | 05eb9a357cd2794a83f8176827cb3a59db375683 (diff) | |
download | riscv-openocd-0af37282c742dfc3492348f44f66215939148fb0.zip riscv-openocd-0af37282c742dfc3492348f44f66215939148fb0.tar.gz riscv-openocd-0af37282c742dfc3492348f44f66215939148fb0.tar.bz2 |
target/arc: Add initial stepping functions
Change-Id: I84845f2ec6f1cff975990f0a495165a02de33227
Signed-off-by: Evgeniy Didin <didin@synopsys.com>
Reviewed-on: http://openocd.zylin.com/5643
Tested-by: jenkins
Reviewed-by: Oleksij Rempel <linux@rempel-privat.de>
Diffstat (limited to 'src')
-rw-r--r-- | src/target/arc.c | 103 | ||||
-rw-r--r-- | src/target/arc.h | 7 |
2 files changed, 108 insertions, 2 deletions
diff --git a/src/target/arc.c b/src/target/arc.c index 823b9ed..396bf8a 100644 --- a/src/target/arc.c +++ b/src/target/arc.c @@ -1286,6 +1286,107 @@ static int arc_target_create(struct target *target, Jim_Interp *interp) } +/* Helper function which swiches core to single_step mode by + * doing aux r/w operations. */ +int arc_config_step(struct target *target, int enable_step) +{ + uint32_t value; + + struct arc_common *arc = target_to_arc(target); + + /* enable core debug step mode */ + if (enable_step) { + CHECK_RETVAL(arc_jtag_read_aux_reg_one(&arc->jtag_info, AUX_STATUS32_REG, + &value)); + value &= ~SET_CORE_AE_BIT; /* clear the AE bit */ + CHECK_RETVAL(arc_jtag_write_aux_reg_one(&arc->jtag_info, AUX_STATUS32_REG, + value)); + LOG_DEBUG(" [status32:0x%08" PRIx32 "]", value); + + /* Doing read-modify-write, because DEBUG might contain manually set + * bits like UB or ED, which should be preserved. */ + CHECK_RETVAL(arc_jtag_read_aux_reg_one(&arc->jtag_info, + AUX_DEBUG_REG, &value)); + value |= SET_CORE_SINGLE_INSTR_STEP; /* set the IS bit */ + CHECK_RETVAL(arc_jtag_write_aux_reg_one(&arc->jtag_info, AUX_DEBUG_REG, + value)); + LOG_DEBUG("core debug step mode enabled [debug-reg:0x%08" PRIx32 "]", value); + + } else { /* disable core debug step mode */ + CHECK_RETVAL(arc_jtag_read_aux_reg_one(&arc->jtag_info, AUX_DEBUG_REG, + &value)); + value &= ~SET_CORE_SINGLE_INSTR_STEP; /* clear the IS bit */ + CHECK_RETVAL(arc_jtag_write_aux_reg_one(&arc->jtag_info, AUX_DEBUG_REG, + value)); + LOG_DEBUG("core debug step mode disabled"); + } + + return ERROR_OK; +} + +int arc_step(struct target *target, int current, target_addr_t address, + int handle_breakpoints) +{ + /* get pointers to arch-specific information */ + struct arc_common *arc = target_to_arc(target); + struct breakpoint *breakpoint = NULL; + struct reg *pc = &(arc->core_and_aux_cache->reg_list[arc->pc_index_in_cache]); + + if (target->state != TARGET_HALTED) { + LOG_WARNING("target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + /* current = 1: continue on current pc, otherwise continue at <address> */ + if (!current) { + buf_set_u32(pc->value, 0, 32, address); + pc->dirty = 1; + pc->valid = 1; + } + + LOG_DEBUG("Target steps one instruction from PC=0x%" PRIx32, + buf_get_u32(pc->value, 0, 32)); + + /* the front-end may request us not to handle breakpoints */ + if (handle_breakpoints) { + breakpoint = breakpoint_find(target, buf_get_u32(pc->value, 0, 32)); + if (breakpoint) + CHECK_RETVAL(arc_unset_breakpoint(target, breakpoint)); + } + + /* restore context */ + CHECK_RETVAL(arc_restore_context(target)); + + target->debug_reason = DBG_REASON_SINGLESTEP; + + CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_RESUMED)); + + /* disable interrupts while stepping */ + CHECK_RETVAL(arc_enable_interrupts(target, 0)); + + /* do a single step */ + CHECK_RETVAL(arc_config_step(target, 1)); + + /* make sure we done our step */ + alive_sleep(1); + + /* registers are now invalid */ + register_cache_invalidate(arc->core_and_aux_cache); + + if (breakpoint) + CHECK_RETVAL(arc_set_breakpoint(target, breakpoint)); + + LOG_DEBUG("target stepped "); + + target->state = TARGET_HALTED; + + /* Saving context */ + CHECK_RETVAL(arc_debug_entry(target)); + CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_HALTED)); + + return ERROR_OK; +} + /* ARC v2 target */ struct target_type arcv2_target = { .name = "arcv2", @@ -1300,7 +1401,7 @@ struct target_type arcv2_target = { .halt = arc_halt, .resume = arc_resume, - .step = NULL, + .step = arc_step, .assert_reset = arc_assert_reset, .deassert_reset = arc_deassert_reset, diff --git a/src/target/arc.h b/src/target/arc.h index af4149f..c02787e 100644 --- a/src/target/arc.h +++ b/src/target/arc.h @@ -33,9 +33,14 @@ #define AUX_PC_REG 0x6 #define AUX_STATUS32_REG 0xA + #define SET_CORE_FORCE_HALT BIT(1) #define SET_CORE_HALT_BIT BIT(0) /* STATUS32[0] = H field */ -#define SET_CORE_ENABLE_INTERRUPTS BIT(31) +#define SET_CORE_ENABLE_INTERRUPTS BIT(31) +/* STATUS32[5] or AE bit indicates if the processor is in exception state */ +#define SET_CORE_AE_BIT BIT(5) +/* Single instruction step bit in Debug register */ +#define SET_CORE_SINGLE_INSTR_STEP BIT(11) #define AUX_STATUS32_REG_HALT_BIT BIT(0) #define AUX_STATUS32_REG_IE_BIT BIT(31) /* STATUS32[31] = IE field */ |