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 */

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)