target: avoid using interp global variable
[fw/openocd] / src / target / cortex_a8.c
index b006e81a64df7f91547fce2a4020b70d2042c083..8402081dfc947a2b20caa2e18b7ad6c0e407a38e 100644 (file)
@@ -89,15 +89,25 @@ static int cortex_a8_init_debug_access(struct target *target)
        return retval;
 }
 
-int cortex_a8_exec_opcode(struct target *target, uint32_t opcode)
+/* To reduce needless round-trips, pass in a pointer to the current
+ * DSCR value.  Initialize it to zero if you just need to know the
+ * value on return from this function; or (1 << DSCR_INSTR_COMP) if
+ * you happen to know that no instruction is pending.
+ */
+static int cortex_a8_exec_opcode(struct target *target,
+               uint32_t opcode, uint32_t *dscr_p)
 {
        uint32_t dscr;
        int retval;
        struct armv7a_common *armv7a = target_to_armv7a(target);
        struct swjdp_common *swjdp = &armv7a->swjdp_info;
 
+       dscr = dscr_p ? *dscr_p : 0;
+
        LOG_DEBUG("exec opcode 0x%08" PRIx32, opcode);
-       do
+
+       /* Wait for InstrCompl bit to be set */
+       while ((dscr & (1 << DSCR_INSTR_COMP)) == 0)
        {
                retval = mem_ap_read_atomic_u32(swjdp,
                                armv7a->debug_base + CPUDBG_DSCR, &dscr);
@@ -107,7 +117,6 @@ int cortex_a8_exec_opcode(struct target *target, uint32_t opcode)
                        return retval;
                }
        }
-       while ((dscr & (1 << DSCR_INSTR_COMP)) == 0); /* Wait for InstrCompl bit to be set */
 
        mem_ap_write_u32(swjdp, armv7a->debug_base + CPUDBG_ITR, opcode);
 
@@ -123,6 +132,9 @@ int cortex_a8_exec_opcode(struct target *target, uint32_t opcode)
        }
        while ((dscr & (1 << DSCR_INSTR_COMP)) == 0); /* Wait for InstrCompl bit to be set */
 
+       if (dscr_p)
+               *dscr_p = dscr;
+
        return retval;
 }
 
@@ -139,7 +151,7 @@ static int cortex_a8_read_regs_through_mem(struct target *target, uint32_t addre
 
        cortex_a8_dap_read_coreregister_u32(target, regfile, 0);
        cortex_a8_dap_write_coreregister_u32(target, address, 0);
-       cortex_a8_exec_opcode(target, ARMV4_5_STMIA(0, 0xFFFE, 0, 0));
+       cortex_a8_exec_opcode(target, ARMV4_5_STMIA(0, 0xFFFE, 0, 0), NULL);
        dap_ap_select(swjdp, swjdp_memoryap);
        mem_ap_read_buf_u32(swjdp, (uint8_t *)(&regfile[1]), 4*15, address);
        dap_ap_select(swjdp, swjdp_debugap);
@@ -153,10 +165,15 @@ static int cortex_a8_read_cp(struct target *target, uint32_t *value, uint8_t CP,
        int retval;
        struct armv7a_common *armv7a = target_to_armv7a(target);
        struct swjdp_common *swjdp = &armv7a->swjdp_info;
+       uint32_t dscr = 0;
+
+       /* MRC(...) to read coprocessor register into r0 */
+       cortex_a8_exec_opcode(target, ARMV4_5_MRC(CP, op1, 0, CRn, CRm, op2),
+                       &dscr);
 
-       cortex_a8_exec_opcode(target, ARMV4_5_MRC(CP, op1, 0, CRn, CRm, op2));
        /* Move R0 to DTRTX */
-       cortex_a8_exec_opcode(target, ARMV4_5_MCR(14, 0, 0, 0, 5, 0));
+       cortex_a8_exec_opcode(target, ARMV4_5_MCR(14, 0, 0, 0, 5, 0),
+                       &dscr);
 
        /* Read DCCTX */
        retval = mem_ap_read_atomic_u32(swjdp,
@@ -182,16 +199,21 @@ static int cortex_a8_write_cp(struct target *target, uint32_t value,
        {
                LOG_ERROR("DSCR_DTR_RX_FULL, dscr 0x%08" PRIx32, dscr);
                /* Clear DCCRX with MCR(p14, 0, Rd, c0, c5, 0), opcode  0xEE000E15 */
-               cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0));
+               cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
+                               &dscr);
        }
 
+       /* Write DTRRX ... sets DSCR.DTRRXfull but exec_opcode() won't care */
        retval = mem_ap_write_u32(swjdp,
                        armv7a->debug_base + CPUDBG_DTRRX, value);
+
        /* Move DTRRX to r0 */
-       cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0));
+       cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0), &dscr);
 
-       cortex_a8_exec_opcode(target, ARMV4_5_MCR(CP, op1, 0, CRn, CRm, op2));
-       return retval;
+       /* MCR(...) to write r0 to coprocessor */
+       return cortex_a8_exec_opcode(target,
+                       ARMV4_5_MCR(CP, op1, 0, CRn, CRm, op2),
+                       &dscr);
 }
 
 static int cortex_a8_read_cp15(struct target *target, uint32_t op1, uint32_t op2,
@@ -233,7 +255,7 @@ static int cortex_a8_dap_read_coreregister_u32(struct target *target,
 {
        int retval = ERROR_OK;
        uint8_t reg = regnum&0xFF;
-       uint32_t dscr;
+       uint32_t dscr = 0;
        struct armv7a_common *armv7a = target_to_armv7a(target);
        struct swjdp_common *swjdp = &armv7a->swjdp_info;
 
@@ -243,30 +265,35 @@ static int cortex_a8_dap_read_coreregister_u32(struct target *target,
        if (reg < 15)
        {
                /* Rn to DCCTX, "MCR p14, 0, Rn, c0, c5, 0"  0xEE00nE15 */
-               cortex_a8_exec_opcode(target, ARMV4_5_MCR(14, 0, reg, 0, 5, 0));
+               cortex_a8_exec_opcode(target,
+                               ARMV4_5_MCR(14, 0, reg, 0, 5, 0),
+                               &dscr);
        }
        else if (reg == 15)
        {
                /* "MOV r0, r15"; then move r0 to DCCTX */
-               cortex_a8_exec_opcode(target, 0xE1A0000F);
-               cortex_a8_exec_opcode(target, ARMV4_5_MCR(14, 0, 0, 0, 5, 0));
+               cortex_a8_exec_opcode(target, 0xE1A0000F, &dscr);
+               cortex_a8_exec_opcode(target,
+                               ARMV4_5_MCR(14, 0, 0, 0, 5, 0),
+                               &dscr);
        }
        else
        {
                /* "MRS r0, CPSR" or "MRS r0, SPSR"
                 * then move r0 to DCCTX
                 */
-               cortex_a8_exec_opcode(target, ARMV4_5_MRS(0, reg & 1));
-               cortex_a8_exec_opcode(target, ARMV4_5_MCR(14, 0, 0, 0, 5, 0));
+               cortex_a8_exec_opcode(target, ARMV4_5_MRS(0, reg & 1), &dscr);
+               cortex_a8_exec_opcode(target,
+                               ARMV4_5_MCR(14, 0, 0, 0, 5, 0),
+                               &dscr);
        }
 
-       /* Read DTRRTX */
-       do
+       /* Wait for DTRRXfull then read DTRRTX */
+       while ((dscr & (1 << DSCR_DTR_TX_FULL)) == 0)
        {
                retval = mem_ap_read_atomic_u32(swjdp,
                                armv7a->debug_base + CPUDBG_DSCR, &dscr);
        }
-       while ((dscr & (1 << DSCR_DTR_TX_FULL)) == 0); /* Wait for DTRRXfull */
 
        retval = mem_ap_read_atomic_u32(swjdp,
                        armv7a->debug_base + CPUDBG_DTRTX, value);
@@ -293,13 +320,14 @@ static int cortex_a8_dap_write_coreregister_u32(struct target *target,
        {
                LOG_ERROR("DSCR_DTR_RX_FULL, dscr 0x%08" PRIx32, dscr);
                /* Clear DCCRX with MCR(p14, 0, Rd, c0, c5, 0), opcode  0xEE000E15 */
-               cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0));
+               cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
+                               &dscr);
        }
 
        if (Rd > 17)
                return retval;
 
-       /* Write to DCCRX */
+       /* Write DTRRX ... sets DSCR.DTRRXfull but exec_opcode() won't care */
        LOG_DEBUG("write DCC 0x%08" PRIx32, value);
        retval = mem_ap_write_u32(swjdp,
                        armv7a->debug_base + CPUDBG_DTRRX, value);
@@ -307,28 +335,33 @@ static int cortex_a8_dap_write_coreregister_u32(struct target *target,
        if (Rd < 15)
        {
                /* DCCRX to Rn, "MCR p14, 0, Rn, c0, c5, 0", 0xEE00nE15 */
-               cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, Rd, 0, 5, 0));
+               cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, Rd, 0, 5, 0),
+                               &dscr);
        }
        else if (Rd == 15)
        {
                /* DCCRX to R0, "MCR p14, 0, R0, c0, c5, 0", 0xEE000E15
                 * then "mov r15, r0"
                 */
-               cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0));
-               cortex_a8_exec_opcode(target, 0xE1A0F000);
+               cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
+                               &dscr);
+               cortex_a8_exec_opcode(target, 0xE1A0F000, &dscr);
        }
        else
        {
                /* DCCRX to R0, "MCR p14, 0, R0, c0, c5, 0", 0xEE000E15
                 * then "MSR CPSR_cxsf, r0" or "MSR SPSR_cxsf, r0" (all fields)
                 */
-               cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0));
-               cortex_a8_exec_opcode(target, ARMV4_5_MSR_GP(0, 0xF, Rd & 1));
+               cortex_a8_exec_opcode(target, ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
+                               &dscr);
+               cortex_a8_exec_opcode(target, ARMV4_5_MSR_GP(0, 0xF, Rd & 1),
+                               &dscr);
 
                /* "Prefetch flush" after modifying execution status in CPSR */
                if (Rd == 16)
                        cortex_a8_exec_opcode(target,
-                                       ARMV4_5_MCR(15, 0, 0, 7, 5, 4));
+                                       ARMV4_5_MCR(15, 0, 0, 7, 5, 4),
+                                       &dscr);
        }
 
        return retval;
@@ -346,6 +379,199 @@ static int cortex_a8_dap_write_memap_register_u32(struct target *target, uint32_
        return retval;
 }
 
+/*
+ * Cortex-A8 implementation of Debug Programmer's Model
+ *
+ * NOTE the invariant:  these routines return with DSCR_INSTR_COMP set,
+ * so there's no need to poll for it before executing an instruction.
+ *
+ * NOTE that in several of these cases the "stall" mode might be useful.
+ * It'd let us queue a few operations together... prepare/finish might
+ * be the places to enable/disable that mode.
+ */
+
+static inline struct cortex_a8_common *dpm_to_a8(struct arm_dpm *dpm)
+{
+       return container_of(dpm, struct cortex_a8_common, armv7a_common.dpm);
+}
+
+static int cortex_a8_write_dcc(struct cortex_a8_common *a8, uint32_t data)
+{
+       LOG_DEBUG("write DCC 0x%08" PRIx32, data);
+       return mem_ap_write_u32(&a8->armv7a_common.swjdp_info,
+                       a8->armv7a_common.debug_base + CPUDBG_DTRRX, data);
+}
+
+static int cortex_a8_read_dcc(struct cortex_a8_common *a8, uint32_t *data,
+               uint32_t *dscr_p)
+{
+       struct swjdp_common *swjdp = &a8->armv7a_common.swjdp_info;
+       uint32_t dscr = 1 << DSCR_INSTR_COMP;
+       int retval;
+
+       if (dscr_p)
+               dscr = *dscr_p;
+
+       /* Wait for DTRRXfull */
+       while ((dscr & (1 << DSCR_DTR_TX_FULL)) == 0) {
+               retval = mem_ap_read_atomic_u32(swjdp,
+                               a8->armv7a_common.debug_base + CPUDBG_DSCR,
+                               &dscr);
+       }
+
+       retval = mem_ap_read_atomic_u32(swjdp,
+                       a8->armv7a_common.debug_base + CPUDBG_DTRTX, data);
+       LOG_DEBUG("read DCC 0x%08" PRIx32, *data);
+
+       if (dscr_p)
+               *dscr_p = dscr;
+
+       return retval;
+}
+
+static int cortex_a8_dpm_prepare(struct arm_dpm *dpm)
+{
+       struct cortex_a8_common *a8 = dpm_to_a8(dpm);
+       struct swjdp_common *swjdp = &a8->armv7a_common.swjdp_info;
+       uint32_t dscr;
+       int retval;
+
+       /* set up invariant:  INSTR_COMP is set after ever DPM operation */
+       do {
+               retval = mem_ap_read_atomic_u32(swjdp,
+                               a8->armv7a_common.debug_base + CPUDBG_DSCR,
+                               &dscr);
+       } while ((dscr & (1 << DSCR_INSTR_COMP)) == 0);
+
+       /* this "should never happen" ... */
+       if (dscr & (1 << DSCR_DTR_RX_FULL)) {
+               LOG_ERROR("DSCR_DTR_RX_FULL, dscr 0x%08" PRIx32, dscr);
+               /* Clear DCCRX */
+               retval = cortex_a8_exec_opcode(
+                               a8->armv7a_common.armv4_5_common.target,
+                               ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
+                               &dscr);
+       }
+
+       return retval;
+}
+
+static int cortex_a8_dpm_finish(struct arm_dpm *dpm)
+{
+       /* REVISIT what could be done here? */
+       return ERROR_OK;
+}
+
+static int cortex_a8_instr_write_data_dcc(struct arm_dpm *dpm,
+               uint32_t opcode, uint32_t data)
+{
+       struct cortex_a8_common *a8 = dpm_to_a8(dpm);
+       int retval;
+       uint32_t dscr = 1 << DSCR_INSTR_COMP;
+
+       retval = cortex_a8_write_dcc(a8, data);
+
+       return cortex_a8_exec_opcode(
+                       a8->armv7a_common.armv4_5_common.target,
+                       opcode,
+                       &dscr);
+}
+
+static int cortex_a8_instr_write_data_r0(struct arm_dpm *dpm,
+               uint32_t opcode, uint32_t data)
+{
+       struct cortex_a8_common *a8 = dpm_to_a8(dpm);
+       uint32_t dscr = 1 << DSCR_INSTR_COMP;
+       int retval;
+
+       retval = cortex_a8_write_dcc(a8, data);
+
+       /* DCCRX to R0, "MCR p14, 0, R0, c0, c5, 0", 0xEE000E15 */
+       retval = cortex_a8_exec_opcode(
+                       a8->armv7a_common.armv4_5_common.target,
+                       ARMV4_5_MRC(14, 0, 0, 0, 5, 0),
+                       &dscr);
+
+       /* then the opcode, taking data from R0 */
+       retval = cortex_a8_exec_opcode(
+                       a8->armv7a_common.armv4_5_common.target,
+                       opcode,
+                       &dscr);
+
+       return retval;
+}
+
+static int cortex_a8_instr_cpsr_sync(struct arm_dpm *dpm)
+{
+       struct target *target = dpm->arm->target;
+       uint32_t dscr = 1 << DSCR_INSTR_COMP;
+
+       /* "Prefetch flush" after modifying execution status in CPSR */
+       return cortex_a8_exec_opcode(target,
+                       ARMV4_5_MCR(15, 0, 0, 7, 5, 4),
+                       &dscr);
+}
+
+static int cortex_a8_instr_read_data_dcc(struct arm_dpm *dpm,
+               uint32_t opcode, uint32_t *data)
+{
+       struct cortex_a8_common *a8 = dpm_to_a8(dpm);
+       int retval;
+       uint32_t dscr = 1 << DSCR_INSTR_COMP;
+
+       /* the opcode, writing data to DCC */
+       retval = cortex_a8_exec_opcode(
+                       a8->armv7a_common.armv4_5_common.target,
+                       opcode,
+                       &dscr);
+
+       return cortex_a8_read_dcc(a8, data, &dscr);
+}
+
+
+static int cortex_a8_instr_read_data_r0(struct arm_dpm *dpm,
+               uint32_t opcode, uint32_t *data)
+{
+       struct cortex_a8_common *a8 = dpm_to_a8(dpm);
+       uint32_t dscr = 1 << DSCR_INSTR_COMP;
+       int retval;
+
+       /* the opcode, writing data to R0 */
+       retval = cortex_a8_exec_opcode(
+                       a8->armv7a_common.armv4_5_common.target,
+                       opcode,
+                       &dscr);
+
+       /* write R0 to DCC */
+       retval = cortex_a8_exec_opcode(
+                       a8->armv7a_common.armv4_5_common.target,
+                       ARMV4_5_MCR(14, 0, 0, 0, 5, 0),
+                       &dscr);
+
+       return cortex_a8_read_dcc(a8, data, &dscr);
+}
+
+static int cortex_a8_dpm_setup(struct cortex_a8_common *a8, uint32_t didr)
+{
+       struct arm_dpm *dpm = &a8->armv7a_common.dpm;
+
+       dpm->arm = &a8->armv7a_common.armv4_5_common;
+       dpm->didr = didr;
+
+       dpm->prepare = cortex_a8_dpm_prepare;
+       dpm->finish = cortex_a8_dpm_finish;
+
+       dpm->instr_write_data_dcc = cortex_a8_instr_write_data_dcc;
+       dpm->instr_write_data_r0 = cortex_a8_instr_write_data_r0;
+       dpm->instr_cpsr_sync = cortex_a8_instr_cpsr_sync;
+
+       dpm->instr_read_data_dcc = cortex_a8_instr_read_data_dcc;
+       dpm->instr_read_data_r0 = cortex_a8_instr_read_data_r0;
+
+       return arm_dpm_setup(dpm);
+}
+
+
 /*
  * Cortex-A8 Run control
  */
@@ -592,6 +818,12 @@ static int cortex_a8_debug_entry(struct target *target)
        /* Enable the ITR execution once we are in debug mode */
        mem_ap_read_atomic_u32(swjdp,
                                armv7a->debug_base + CPUDBG_DSCR, &dscr);
+
+       /* REVISIT see A8 TRM 12.11.4 steps 2..3 -- make sure that any
+        * imprecise data aborts get discarded by issuing a Data
+        * Synchronization Barrier:  ARMV4_5_MCR(15, 0, 0, 7, 10, 4).
+        */
+
        dscr |= (1 << DSCR_EXT_INT_EN);
        retval = mem_ap_write_atomic_u32(swjdp,
                        armv7a->debug_base + CPUDBG_DSCR, dscr);
@@ -599,22 +831,28 @@ static int cortex_a8_debug_entry(struct target *target)
        /* Examine debug reason */
        switch ((cortex_a8->cpudbg_dscr >> 2)&0xF)
        {
-               case 0:
-               case 4:
+               case 0:         /* DRCR[0] write */
+               case 4:         /* EDBGRQ */
                        target->debug_reason = DBG_REASON_DBGRQ;
                        break;
-               case 1:
-               case 3:
+               case 1:         /* HW breakpoint */
+               case 3:         /* SW BKPT */
+               case 5:         /* vector catch */
                        target->debug_reason = DBG_REASON_BREAKPOINT;
                        break;
-               case 10:
+               case 10:        /* precise watchpoint */
                        target->debug_reason = DBG_REASON_WATCHPOINT;
+                       /* REVISIT could collect WFAR later, to see just
+                        * which instruction triggered the watchpoint.
+                        */
                        break;
                default:
                        target->debug_reason = DBG_REASON_UNDEFINED;
                        break;
        }
 
+       /* REVISIT fast_reg_read is never set ... */
+
        /* Examine target state and mode */
        if (cortex_a8->fast_reg_read)
                target_alloc_working_area(target, 64, &regfile_working_area);
@@ -622,12 +860,7 @@ static int cortex_a8_debug_entry(struct target *target)
        /* First load register acessible through core debug port*/
        if (!regfile_working_area)
        {
-               /* FIXME we don't actually need all these registers;
-                * reading them slows us down.  Just R0, PC, CPSR...
-                */
-               for (i = 0; i <= 15; i++)
-                       cortex_a8_dap_read_coreregister_u32(target,
-                                       &regfile[i], i);
+               retval = arm_dpm_read_current_registers(&armv7a->dpm);
        }
        else
        {
@@ -636,44 +869,41 @@ static int cortex_a8_debug_entry(struct target *target)
                                regfile_working_area->address, regfile);
                dap_ap_select(swjdp, swjdp_memoryap);
                target_free_working_area(target, regfile_working_area);
-       }
 
-       /* read Current PSR */
-       cortex_a8_dap_read_coreregister_u32(target, &cpsr, 16);
-       pc = regfile[15];
-       dap_ap_select(swjdp, swjdp_debugap);
-       LOG_DEBUG("cpsr: %8.8" PRIx32, cpsr);
+               /* read Current PSR */
+               cortex_a8_dap_read_coreregister_u32(target, &cpsr, 16);
+               pc = regfile[15];
+               dap_ap_select(swjdp, swjdp_debugap);
+               LOG_DEBUG("cpsr: %8.8" PRIx32, cpsr);
 
-       arm_set_cpsr(armv4_5, cpsr);
+               arm_set_cpsr(armv4_5, cpsr);
 
-       /* update cache */
-       for (i = 0; i <= ARM_PC; i++)
-       {
-               reg = arm_reg_current(armv4_5, i);
+               /* update cache */
+               for (i = 0; i <= ARM_PC; i++)
+               {
+                       reg = arm_reg_current(armv4_5, i);
 
-               buf_set_u32(reg->value, 0, 32, regfile[i]);
-               reg->valid = 1;
-               reg->dirty = 0;
-       }
+                       buf_set_u32(reg->value, 0, 32, regfile[i]);
+                       reg->valid = 1;
+                       reg->dirty = 0;
+               }
 
-       /* Fixup PC Resume Address */
-       if (cpsr & (1 << 5))
-       {
-               // T bit set for Thumb or ThumbEE state
-               regfile[ARM_PC] -= 4;
-       }
-       else
-       {
-               // ARM state
-               regfile[ARM_PC] -= 8;
-       }
+               /* Fixup PC Resume Address */
+               if (cpsr & (1 << 5))
+               {
+                       // T bit set for Thumb or ThumbEE state
+                       regfile[ARM_PC] -= 4;
+               }
+               else
+               {
+                       // ARM state
+                       regfile[ARM_PC] -= 8;
+               }
 
-       reg = armv4_5->core_cache->reg_list + 15;
-       buf_set_u32(reg->value, 0, 32, regfile[ARM_PC]);
-       reg->dirty = reg->valid;
-       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 15)
-               .dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
-                               armv4_5->core_mode, 15).valid;
+               reg = armv4_5->core_cache->reg_list + 15;
+               buf_set_u32(reg->value, 0, 32, regfile[ARM_PC]);
+               reg->dirty = reg->valid;
+       }
 
 #if 0
 /* TODO, Move this */
@@ -738,6 +968,7 @@ static int cortex_a8_step(struct target *target, int current, uint32_t address,
        struct arm *armv4_5 = &armv7a->armv4_5_common;
        struct breakpoint *breakpoint = NULL;
        struct breakpoint stepbreakpoint;
+       struct reg *r;
 
        int timeout = 100;
 
@@ -748,17 +979,14 @@ static int cortex_a8_step(struct target *target, int current, uint32_t address,
        }
 
        /* current = 1: continue on current pc, otherwise continue at <address> */
+       r = armv4_5->core_cache->reg_list + 15;
        if (!current)
        {
-               buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
-                                       armv4_5->core_mode, ARM_PC).value,
-                               0, 32, address);
+               buf_set_u32(r->value, 0, 32, address);
        }
        else
        {
-               address = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
-                                       armv4_5->core_mode, ARM_PC).value,
-                               0, 32);
+               address = buf_get_u32(r->value, 0, 32);
        }
 
        /* The front-end may request us not to handle breakpoints.
@@ -767,11 +995,7 @@ static int cortex_a8_step(struct target *target, int current, uint32_t address,
         */
        handle_breakpoints = 1;
        if (handle_breakpoints) {
-               breakpoint = breakpoint_find(target,
-                               buf_get_u32(ARMV4_5_CORE_REG_MODE(
-                                       armv4_5->core_cache,
-                                       armv4_5->core_mode, 15).value,
-                       0, 32));
+               breakpoint = breakpoint_find(target, address);
                if (breakpoint)
                        cortex_a8_unset_breakpoint(target, breakpoint);
        }
@@ -814,83 +1038,14 @@ static int cortex_a8_step(struct target *target, int current, uint32_t address,
 
 static int cortex_a8_restore_context(struct target *target)
 {
-       uint32_t value;
        struct armv7a_common *armv7a = target_to_armv7a(target);
-       struct reg_cache *cache = armv7a->armv4_5_common.core_cache;
-       unsigned max = cache->num_regs;
-       struct reg *r;
-       bool flushed, flush_cpsr = false;
 
        LOG_DEBUG(" ");
 
        if (armv7a->pre_restore_context)
                armv7a->pre_restore_context(target);
 
-       /* Flush all dirty registers from the cache, one mode at a time so
-        * that we write CPSR as little as possible.  Save CPSR and R0 for
-        * last; they're used to change modes and write other registers.
-        *
-        * REVISIT be smarter:  save eventual mode for last loop, don't
-        * need to write CPSR an extra time.
-        */
-       do {
-               enum armv4_5_mode mode = ARMV4_5_MODE_ANY;
-               unsigned i;
-
-               flushed = false;
-
-               /* write dirty non-{R0,CPSR} registers sharing the same mode */
-               for (i = max - 1, r = cache->reg_list + 1; i > 0; i--, r++) {
-                       struct arm_reg *reg;
-
-                       if (!r->dirty || r == armv7a->armv4_5_common.cpsr)
-                               continue;
-                       reg = r->arch_info;
-
-                       /* TODO Check return values */
-
-                       /* Pick a mode and update CPSR; else ignore this
-                        * register if it's for a different mode than what
-                        * we're handling on this pass.
-                        *
-                        * REVISIT don't distinguish SYS and USR modes.
-                        *
-                        * FIXME if we restore from FIQ mode, R8..R12 will
-                        * get wrongly flushed onto FIQ shadows...
-                        */
-                       if (mode == ARMV4_5_MODE_ANY) {
-                               mode = reg->mode;
-                               if (mode != ARMV4_5_MODE_ANY) {
-                                       cortex_a8_dap_write_coreregister_u32(
-                                                       target, mode, 16);
-                                       flush_cpsr = true;
-                               }
-                       } else if (mode != reg->mode)
-                               continue;
-
-                       /* Write this register */
-                       value = buf_get_u32(r->value, 0, 32);
-                       cortex_a8_dap_write_coreregister_u32(target, value,
-                                       (reg->num == 16) ? 17 : reg->num);
-                       r->dirty = false;
-                       flushed = true;
-               }
-
-       } while (flushed);
-
-       /* now flush CPSR if needed ... */
-       r = armv7a->armv4_5_common.cpsr;
-       if (flush_cpsr || r->dirty) {
-               value = buf_get_u32(r->value, 0, 32);
-               cortex_a8_dap_write_coreregister_u32(target, value, 16);
-               r->dirty = false;
-       }
-
-       /* ... and R0 always (it was dirtied when we saved context) */
-       r = cache->reg_list + 0;
-       value = buf_get_u32(r->value, 0, 32);
-       cortex_a8_dap_write_coreregister_u32(target, value, 0);
-       r->dirty = false;
+       arm_dpm_write_dirty_registers(&armv7a->dpm);
 
        if (armv7a->post_restore_context)
                armv7a->post_restore_context(target);
@@ -899,204 +1054,6 @@ static int cortex_a8_restore_context(struct target *target)
 }
 
 
-#if 0
-/*
- * Cortex-A8 Core register functions
- */
-static int cortex_a8_load_core_reg_u32(struct target *target, int num,
-               armv4_5_mode_t mode, uint32_t * value)
-{
-       int retval;
-       struct arm *armv4_5 = target_to_armv4_5(target);
-
-       if ((num <= ARM_CPSR))
-       {
-               /* read a normal core register */
-               retval = cortex_a8_dap_read_coreregister_u32(target, value, num);
-
-               if (retval != ERROR_OK)
-               {
-                       LOG_ERROR("JTAG failure %i", retval);
-                       return ERROR_JTAG_DEVICE_ERROR;
-               }
-               LOG_DEBUG("load from core reg %i value 0x%" PRIx32, num, *value);
-       }
-       else
-       {
-               return ERROR_INVALID_ARGUMENTS;
-       }
-
-       /* Register other than r0 - r14 uses r0 for access */
-       if (num > 14)
-               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
-                               armv4_5->core_mode, 0).dirty =
-                       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
-                               armv4_5->core_mode, 0).valid;
-       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
-                               armv4_5->core_mode, 15).dirty =
-                       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
-                               armv4_5->core_mode, 15).valid;
-
-       return ERROR_OK;
-}
-
-static int cortex_a8_store_core_reg_u32(struct target *target, int num,
-               armv4_5_mode_t mode, uint32_t value)
-{
-       int retval;
-//     uint32_t reg;
-       struct arm *armv4_5 = target_to_armv4_5(target);
-
-#ifdef ARMV7_GDB_HACKS
-       /* If the LR register is being modified, make sure it will put us
-        * in "thumb" mode, or an INVSTATE exception will occur. This is a
-        * hack to deal with the fact that gdb will sometimes "forge"
-        * return addresses, and doesn't set the LSB correctly (i.e., when
-        * printing expressions containing function calls, it sets LR=0.) */
-
-       if (num == 14)
-               value |= 0x01;
-#endif
-
-       if ((num <= ARM_CPSR))
-       {
-               retval = cortex_a8_dap_write_coreregister_u32(target, value, num);
-               if (retval != ERROR_OK)
-               {
-                       LOG_ERROR("JTAG failure %i", retval);
-                       ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
-                                       armv4_5->core_mode, num).dirty =
-                               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
-                                       armv4_5->core_mode, num).valid;
-                       return ERROR_JTAG_DEVICE_ERROR;
-               }
-               LOG_DEBUG("write core reg %i value 0x%" PRIx32, num, value);
-       }
-       else
-       {
-               return ERROR_INVALID_ARGUMENTS;
-       }
-
-       return ERROR_OK;
-}
-#endif
-
-
-static int cortex_a8_write_core_reg(struct target *target, struct reg *r,
-               int num, enum armv4_5_mode mode, uint32_t value);
-
-static int cortex_a8_read_core_reg(struct target *target, struct reg *r,
-               int num, enum armv4_5_mode mode)
-{
-       uint32_t value;
-       int retval;
-       struct arm *armv4_5 = target_to_armv4_5(target);
-       struct reg *cpsr_r = NULL;
-       uint32_t cpsr = 0;
-       unsigned cookie = num;
-
-       /* avoid some needless mode changes
-        * FIXME move some of these to shared ARM code...
-        */
-       if (mode != armv4_5->core_mode) {
-               if ((armv4_5->core_mode == ARMV4_5_MODE_SYS)
-                               && (mode == ARMV4_5_MODE_USR))
-                       mode = ARMV4_5_MODE_ANY;
-               else if ((mode != ARMV4_5_MODE_FIQ) && (num <= 12))
-                       mode = ARMV4_5_MODE_ANY;
-
-               if (mode != ARMV4_5_MODE_ANY) {
-                       cpsr_r = armv4_5->cpsr;
-                       cpsr = buf_get_u32(cpsr_r->value, 0, 32);
-                       cortex_a8_write_core_reg(target, cpsr_r,
-                                       16, ARMV4_5_MODE_ANY, mode);
-               }
-       }
-
-       if (num == 16) {
-               switch (mode) {
-               case ARMV4_5_MODE_USR:
-               case ARMV4_5_MODE_SYS:
-               case ARMV4_5_MODE_ANY:
-                       /* CPSR */
-                       break;
-               default:
-                       /* SPSR */
-                       cookie++;
-                       break;
-               }
-       }
-
-       cortex_a8_dap_read_coreregister_u32(target, &value, cookie);
-       retval = jtag_execute_queue();
-       if (retval == ERROR_OK) {
-               r->valid = 1;
-               r->dirty = 0;
-               buf_set_u32(r->value, 0, 32, value);
-       }
-
-       if (cpsr_r)
-               cortex_a8_write_core_reg(target, cpsr_r,
-                               16, ARMV4_5_MODE_ANY, cpsr);
-       return retval;
-}
-
-static int cortex_a8_write_core_reg(struct target *target, struct reg *r,
-               int num, enum armv4_5_mode mode, uint32_t value)
-{
-       int retval;
-       struct arm *armv4_5 = target_to_armv4_5(target);
-       struct reg *cpsr_r = NULL;
-       uint32_t cpsr = 0;
-       unsigned cookie = num;
-
-       /* avoid some needless mode changes
-        * FIXME move some of these to shared ARM code...
-        */
-       if (mode != armv4_5->core_mode) {
-               if ((armv4_5->core_mode == ARMV4_5_MODE_SYS)
-                               && (mode == ARMV4_5_MODE_USR))
-                       mode = ARMV4_5_MODE_ANY;
-               else if ((mode != ARMV4_5_MODE_FIQ) && (num <= 12))
-                       mode = ARMV4_5_MODE_ANY;
-
-               if (mode != ARMV4_5_MODE_ANY) {
-                       cpsr_r = armv4_5->cpsr;
-                       cpsr = buf_get_u32(cpsr_r->value, 0, 32);
-                       cortex_a8_write_core_reg(target, cpsr_r,
-                                       16, ARMV4_5_MODE_ANY, mode);
-               }
-       }
-
-
-       if (num == 16) {
-               switch (mode) {
-               case ARMV4_5_MODE_USR:
-               case ARMV4_5_MODE_SYS:
-               case ARMV4_5_MODE_ANY:
-                       /* CPSR */
-                       break;
-               default:
-                       /* SPSR */
-                       cookie++;
-                       break;
-               }
-       }
-
-       cortex_a8_dap_write_coreregister_u32(target, value, cookie);
-       if ((retval = jtag_execute_queue()) == ERROR_OK) {
-               buf_set_u32(r->value, 0, 32, value);
-               r->valid = 1;
-               r->dirty = 0;
-       }
-
-       if (cpsr_r)
-               cortex_a8_write_core_reg(target, cpsr_r,
-                               16, ARMV4_5_MODE_ANY, cpsr);
-       return retval;
-}
-
-
 /*
  * Cortex-A8 Breakpoint and watchpoint fuctions
  */
@@ -1235,7 +1192,8 @@ static int cortex_a8_unset_breakpoint(struct target *target, struct breakpoint *
        return ERROR_OK;
 }
 
-int cortex_a8_add_breakpoint(struct target *target, struct breakpoint *breakpoint)
+static int cortex_a8_add_breakpoint(struct target *target,
+               struct breakpoint *breakpoint)
 {
        struct cortex_a8_common *cortex_a8 = target_to_cortex_a8(target);
 
@@ -1288,6 +1246,21 @@ static int cortex_a8_assert_reset(struct target *target)
 
        LOG_DEBUG(" ");
 
+       /* FIXME when halt is requested, make it work somehow... */
+
+       /* Issue some kind of warm reset. */
+       if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT)) {
+               target_handle_event(target, TARGET_EVENT_RESET_ASSERT);
+       } else if (jtag_get_reset_config() & RESET_HAS_SRST) {
+               /* REVISIT handle "pulls" cases, if there's
+                * hardware that needs them to work.
+                */
+               jtag_add_reset(0, 1);
+       } else {
+               LOG_ERROR("%s: how to reset?", target_name(target));
+               return ERROR_FAIL;
+       }
+
        /* registers are now invalid */
        register_cache_invalidate(armv7a->armv4_5_common.core_cache);
 
@@ -1298,14 +1271,22 @@ static int cortex_a8_assert_reset(struct target *target)
 
 static int cortex_a8_deassert_reset(struct target *target)
 {
+       int retval;
 
        LOG_DEBUG(" ");
 
-       if (target->reset_halt)
-       {
-               int retval;
-               if ((retval = target_halt(target)) != ERROR_OK)
-                       return retval;
+       /* be certain SRST is off */
+       jtag_add_reset(0, 0);
+
+       retval = cortex_a8_poll(target);
+
+       if (target->reset_halt) {
+               if (target->state != TARGET_HALTED) {
+                       LOG_WARNING("%s: ran after reset and before halt ...",
+                                       target_name(target));
+                       if ((retval = target_halt(target)) != ERROR_OK)
+                               return retval;
+               }
        }
 
        return ERROR_OK;
@@ -1346,7 +1327,7 @@ static int cortex_a8_read_memory(struct target *target, uint32_t address,
        return retval;
 }
 
-int cortex_a8_write_memory(struct target *target, uint32_t address,
+static int cortex_a8_write_memory(struct target *target, uint32_t address,
                uint32_t size, uint32_t count, uint8_t *buffer)
 {
        struct armv7a_common *armv7a = target_to_armv7a(target);
@@ -1517,6 +1498,8 @@ static int cortex_a8_examine_first(struct target *target)
        LOG_DEBUG("ttypr = 0x%08" PRIx32, ttypr);
        LOG_DEBUG("didr = 0x%08" PRIx32, didr);
 
+       cortex_a8_dpm_setup(cortex_a8, didr);
+
        /* Setup Breakpoint Register Pairs */
        cortex_a8->brp_num = ((didr >> 24) & 0x0F) + 1;
        cortex_a8->brp_num_context = ((didr >> 20) & 0x0F) + 1;
@@ -1573,25 +1556,14 @@ static int cortex_a8_examine(struct target *target)
  *     Cortex-A8 target creation and initialization
  */
 
-static void cortex_a8_build_reg_cache(struct target *target)
-{
-       struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
-       struct arm *armv4_5 = target_to_armv4_5(target);
-
-       armv4_5->core_type = ARM_MODE_MON;
-
-       (*cache_p) = armv4_5_build_reg_cache(target, armv4_5);
-}
-
-
 static int cortex_a8_init_target(struct command_context *cmd_ctx,
                struct target *target)
 {
-       cortex_a8_build_reg_cache(target);
+       /* examine_first() does a bunch of this */
        return ERROR_OK;
 }
 
-int cortex_a8_init_arch_info(struct target *target,
+static int cortex_a8_init_arch_info(struct target *target,
                struct cortex_a8_common *cortex_a8, struct jtag_tap *tap)
 {
        struct armv7a_common *armv7a = &cortex_a8->armv7a_common;
@@ -1605,7 +1577,7 @@ int cortex_a8_init_arch_info(struct target *target,
        /* prepare JTAG information for the new target */
        cortex_a8->jtag_info.tap = tap;
        cortex_a8->jtag_info.scann_size = 4;
-LOG_DEBUG(" ");
+
        swjdp->dp_select_value = -1;
        swjdp->ap_csw_value = -1;
        swjdp->ap_tar_value = -1;
@@ -1639,9 +1611,6 @@ LOG_DEBUG(" ");
 
 //     arm7_9->handle_target_request = cortex_a8_handle_target_request;
 
-       armv4_5->read_core_reg = cortex_a8_read_core_reg;
-       armv4_5->write_core_reg = cortex_a8_write_core_reg;
-
        /* REVISIT v7a setup should be in a v7a-specific routine */
        armv4_5_init_arch_info(target, armv4_5);
        armv7a->common_magic = ARMV7_COMMON_MAGIC;
@@ -1679,29 +1648,36 @@ COMMAND_HANDLER(cortex_a8_handle_dbginit_command)
        return ERROR_OK;
 }
 
-
-static int cortex_a8_register_commands(struct command_context *cmd_ctx)
-{
-       struct command *cortex_a8_cmd;
-       int retval = ERROR_OK;
-
-       armv4_5_register_commands(cmd_ctx);
-       armv7a_register_commands(cmd_ctx);
-
-       cortex_a8_cmd = register_command(cmd_ctx, NULL, "cortex_a8",
-                       NULL, COMMAND_ANY,
-                       "cortex_a8 specific commands");
-
-       register_command(cmd_ctx, cortex_a8_cmd, "cache_info",
-                       cortex_a8_handle_cache_info_command, COMMAND_EXEC,
-                       "display information about target caches");
-
-       register_command(cmd_ctx, cortex_a8_cmd, "dbginit",
-                       cortex_a8_handle_dbginit_command, COMMAND_EXEC,
-                       "Initialize core debug");
-
-       return retval;
-}
+static const struct command_registration cortex_a8_exec_command_handlers[] = {
+       {
+               .name = "cache_info",
+               .handler = &cortex_a8_handle_cache_info_command,
+               .mode = COMMAND_EXEC,
+               .help = "display information about target caches",
+       },
+       {
+               .name = "dbginit",
+               .handler = &cortex_a8_handle_dbginit_command,
+               .mode = COMMAND_EXEC,
+               .help = "Initialize core debug",
+       },
+       COMMAND_REGISTRATION_DONE
+};
+static const struct command_registration cortex_a8_command_handlers[] = {
+       {
+               .chain = arm_command_handlers,
+       },
+       {
+               .chain = armv7a_command_handlers,
+       },
+       {
+               .name = "cortex_a8",
+               .mode = COMMAND_ANY,
+               .help = "Cortex-A8 command group",
+               .chain = cortex_a8_exec_command_handlers,
+       },
+       COMMAND_REGISTRATION_DONE
+};
 
 struct target_type cortexa8_target = {
        .name = "cortex_a8",
@@ -1735,7 +1711,7 @@ struct target_type cortexa8_target = {
        .add_watchpoint = NULL,
        .remove_watchpoint = NULL,
 
-       .register_commands = cortex_a8_register_commands,
+       .commands = cortex_a8_command_handlers,
        .target_create = cortex_a8_target_create,
        .init_target = cortex_a8_init_target,
        .examine = cortex_a8_examine,