ARM11: remove old R0..R15/CPSR code
authorDavid Brownell <dbrownell@users.sourceforge.net>
Tue, 24 Nov 2009 09:27:29 +0000 (01:27 -0800)
committerDavid Brownell <dbrownell@users.sourceforge.net>
Tue, 24 Nov 2009 09:27:29 +0000 (01:27 -0800)
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>
src/target/arm11.c
src/target/arm11.h

index 3bdb44437f9980018040968715190a99ca8266c4..a5175af74144377889a696428aa0d17406b1ef42 100644 (file)
@@ -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;
 
index 033ba899cca6ae64d23f50bea3227a594a4b7699..c3f4e8643bfa6fc6aab38551f869734cd6b484d0 100644 (file)
@@ -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 */