target/arc: Add initial stepping functions
authorEvgeniy Didin <didin@synopsys.com>
Wed, 18 Mar 2020 13:12:04 +0000 (16:12 +0300)
committerOleksij Rempel <linux@rempel-privat.de>
Fri, 8 May 2020 04:57:12 +0000 (05:57 +0100)
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>
src/target/arc.c
src/target/arc.h

index 823b9ed7084985f4260f3b428e9d8c736f5c17ba..396bf8a4742dcd4eccfe0eaea249426b770fe29e 100644 (file)
@@ -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,
index af4149f978b7d7853f0ac920df7f84512d97a862..c02787e338f4fb6e2359b17d15000fbead433901 100644 (file)
 #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 */