aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvgeniy Didin <didin@synopsys.com>2020-03-18 16:12:04 +0300
committerOleksij Rempel <linux@rempel-privat.de>2020-05-08 05:57:12 +0100
commit0af37282c742dfc3492348f44f66215939148fb0 (patch)
tree91b0255d1edb4727856985a35bb3200ec4c9ec73
parent05eb9a357cd2794a83f8176827cb3a59db375683 (diff)
downloadopenocd-jz4730-0af37282c742dfc3492348f44f66215939148fb0.tar.gz
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>
-rw-r--r--src/target/arc.c103
-rw-r--r--src/target/arc.h7
2 files changed, 108 insertions, 2 deletions
diff --git a/src/target/arc.c b/src/target/arc.c
index 823b9ed70..396bf8a47 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 af4149f97..c02787e33 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 */