warnings: fix alignment warnings
[fw/openocd] / src / target / arm11.c
index 608008620a1e29236d5cbd92693b8781250ba509..9955143adb872c9352c703edc98edbb5556622c3 100644 (file)
@@ -6,6 +6,8 @@
  *                                                                         *
  *   Copyright (C) 2008 Georg Acher <acher@in.tum.de>                      *
  *                                                                         *
+ *   Copyright (C) 2009 David Brownell                                     *
+ *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
  *   it under the terms of the GNU General Public License as published by  *
  *   the Free Software Foundation; either version 2 of the License, or     *
 #include "breakpoints.h"
 #include "arm11_dbgtap.h"
 #include "arm_simulator.h"
-#include "time_support.h"
+#include <helper/time_support.h>
 #include "target_type.h"
 #include "algorithm.h"
 #include "register.h"
+#include "arm_opcodes.h"
 
 
 #if 0
 #define _DEBUG_INSTRUCTION_EXECUTION_
 #endif
 
-static bool arm11_config_memwrite_burst = true;
-static bool arm11_config_memwrite_error_fatal = true;
-static uint32_t arm11_vcr = 0;
-static bool arm11_config_step_irq_enable = false;
-static bool arm11_config_hardware_step = false;
-
-enum arm11_regtype
-{
-       /* debug regs */
-       ARM11_REGISTER_DSCR,
-};
-
-
-struct arm11_reg_defs
-{
-       char *                                  name;
-       uint32_t                                                num;
-       int                                             gdb_num;
-       enum arm11_regtype              type;
-};
-
-/* update arm11_regcache_ids when changing this */
-static const struct arm11_reg_defs arm11_reg_defs[] =
-{
-       /* Debug Registers */
-       {"dscr",        0,      -1,     ARM11_REGISTER_DSCR},
-};
-
-enum arm11_regcache_ids
-{
-       ARM11_RC_DSCR,
-
-       ARM11_RC_MAX,
-};
 
 static int arm11_step(struct target *target, int current,
                uint32_t address, int handle_breakpoints);
-/* helpers */
-static int arm11_build_reg_cache(struct target *target);
-static int arm11_set_reg(struct reg *reg, uint8_t *buf);
-static int arm11_get_reg(struct reg *reg);
 
 
 /** Check and if necessary take control of the system
  *
  * \param arm11                Target state variable.
- * \param dscr         If the current DSCR content is
- *                                     available a pointer to a word holding the
- *                                     DSCR can be passed. Otherwise use NULL.
  */
-static int arm11_check_init(struct arm11_common *arm11, uint32_t *dscr)
+static int arm11_check_init(struct arm11_common *arm11)
 {
-       uint32_t                        dscr_local_tmp_copy;
-
-       if (!dscr)
-       {
-               dscr = &dscr_local_tmp_copy;
-
-               CHECK_RETVAL(arm11_read_DSCR(arm11, dscr));
-       }
+       CHECK_RETVAL(arm11_read_DSCR(arm11));
 
-       if (!(*dscr & ARM11_DSCR_MODE_SELECT))
+       if (!(arm11->dscr & DSCR_HALT_DBG_MODE))
        {
+               LOG_DEBUG("DSCR %08x", (unsigned) arm11->dscr);
                LOG_DEBUG("Bringing target into debug mode");
 
-               *dscr |= ARM11_DSCR_MODE_SELECT;                /* Halt debug-mode */
-               arm11_write_DSCR(arm11, *dscr);
+               arm11->dscr |= DSCR_HALT_DBG_MODE;
+               CHECK_RETVAL(arm11_write_DSCR(arm11, arm11->dscr));
 
                /* add further reset initialization here */
 
                arm11->simulate_reset_on_next_halt = true;
 
-               if (*dscr & ARM11_DSCR_CORE_HALTED)
+               if (arm11->dscr & DSCR_CORE_HALTED)
                {
                        /** \todo TODO: this needs further scrutiny because
                          * arm11_debug_entry() never gets called.  (WHY NOT?)
@@ -121,8 +77,7 @@ static int arm11_check_init(struct arm11_common *arm11, uint32_t *dscr)
                          */
 
                        arm11->arm.target->state = TARGET_HALTED;
-                       arm11->arm.target->debug_reason =
-                                       arm11_get_DSCR_debug_reason(*dscr);
+                       arm_dpm_report_dscr(arm11->arm.dpm, arm11->dscr);
                }
                else
                {
@@ -130,45 +85,31 @@ static int arm11_check_init(struct arm11_common *arm11, uint32_t *dscr)
                        arm11->arm.target->debug_reason = DBG_REASON_NOTHALTED;
                }
 
-               arm11_sc7_clear_vbw(arm11);
+               CHECK_RETVAL(arm11_sc7_clear_vbw(arm11));
        }
 
        return ERROR_OK;
 }
 
-
-
-#define R(x) \
-       (arm11->reg_values[ARM11_RC_##x])
-
 /**
  * Save processor state.  This is called after a HALT instruction
  * succeeds, and on other occasions the processor enters debug mode
- * (breakpoint, watchpoint, etc).
+ * (breakpoint, watchpoint, etc).  Caller has updated arm11->dscr.
  */
-static int arm11_debug_entry(struct arm11_common *arm11, uint32_t dscr)
+static int arm11_debug_entry(struct arm11_common *arm11)
 {
        int retval;
 
        arm11->arm.target->state = TARGET_HALTED;
-       arm11->arm.target->debug_reason = arm11_get_DSCR_debug_reason(dscr);
+       arm_dpm_report_dscr(arm11->arm.dpm, arm11->dscr);
 
        /* REVISIT entire cache should already be invalid !!! */
        register_cache_invalidate(arm11->arm.core_cache);
 
-       for (size_t i = 0; i < ARRAY_SIZE(arm11->reg_values); i++)
-       {
-               arm11->reg_list[i].valid        = 1;
-               arm11->reg_list[i].dirty        = 0;
-       }
-
        /* See e.g. ARM1136 TRM, "14.8.4 Entering Debug state" */
 
-       /* Save DSCR */
-       R(DSCR) = dscr;
-
-       /* Save wDTR */
-       arm11->is_wdtr_saved = !!(dscr & ARM11_DSCR_WDTR_FULL);
+       /* maybe save wDTR (pending DCC write to debug SW, e.g. libdcc) */
+       arm11->is_wdtr_saved = !!(arm11->dscr & DSCR_DTR_TX_FULL);
        if (arm11->is_wdtr_saved)
        {
                arm11_add_debug_SCAN_N(arm11, 0x05, ARM11_TAP_DEFAULT);
@@ -182,20 +123,17 @@ static int arm11_debug_entry(struct arm11_common *arm11, uint32_t dscr)
                arm11_setup_field(arm11,  1, NULL, NULL,                chain5_fields + 1);
                arm11_setup_field(arm11,  1, NULL, NULL,                chain5_fields + 2);
 
-               arm11_add_dr_scan_vc(ARRAY_SIZE(chain5_fields), chain5_fields, TAP_DRPAUSE);
+               arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(chain5_fields), chain5_fields, TAP_DRPAUSE);
+
        }
 
-       /* DSCR: set ARM11_DSCR_EXECUTE_ARM_INSTRUCTION_ENABLE
+       /* DSCR: set the Execute ARM instruction enable bit.
         *
         * 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...
+        * but not to issue ITRs(?).  The ARMv7 arch spec says it's required
+        * for executing instructions via ITR.
         */
-       uint32_t new_dscr = dscr | ARM11_DSCR_EXECUTE_ARM_INSTRUCTION_ENABLE;
-
-       /* this executes JTAG queue: */
-
-       arm11_write_DSCR(arm11, new_dscr);
+       CHECK_RETVAL(arm11_write_DSCR(arm11, DSCR_ITR_EN | arm11->dscr));
 
 
        /* From the spec:
@@ -243,8 +181,8 @@ static int arm11_debug_entry(struct arm11_common *arm11, uint32_t dscr)
        if (retval != ERROR_OK)
                return retval;
 
-       /* maybe save rDTR */
-       arm11->is_rdtr_saved = !!(dscr & ARM11_DSCR_RDTR_FULL);
+       /* maybe save rDTR (pending DCC read from debug SW, e.g. libdcc) */
+       arm11->is_rdtr_saved = !!(arm11->dscr & DSCR_DTR_RX_FULL);
        if (arm11->is_rdtr_saved)
        {
                /* MRC p14,0,R0,c0,c5,0 (move rDTR -> r0 (-> wDTR -> local var)) */
@@ -273,6 +211,19 @@ static int arm11_debug_entry(struct arm11_common *arm11, uint32_t dscr)
 
        }
 
+       if (arm11->arm.target->debug_reason == DBG_REASON_WATCHPOINT) {
+               uint32_t wfar;
+
+               /* MRC p15, 0, <Rd>, c6, c0, 1 ; Read WFAR */
+               retval = arm11_run_instr_data_from_core_via_r0(arm11,
+                               ARMV4_5_MRC(15, 0, 0, 6, 0, 1),
+                               &wfar);
+               if (retval != ERROR_OK)
+                       return retval;
+               arm_dpm_report_wfar(arm11->arm.dpm, wfar);
+       }
+
+
        retval = arm11_run_instr_data_finish(arm11);
        if (retval != ERROR_OK)
                return retval;
@@ -302,11 +253,9 @@ static int arm11_leave_debug_state(struct arm11_common *arm11, bool bpwp)
        /* spec says clear wDTR and rDTR; we assume they are clear as
           otherwise our programming would be sloppy */
        {
-               uint32_t DSCR;
-
-               CHECK_RETVAL(arm11_read_DSCR(arm11, &DSCR));
+               CHECK_RETVAL(arm11_read_DSCR(arm11));
 
-               if (DSCR & (ARM11_DSCR_RDTR_FULL | ARM11_DSCR_WDTR_FULL))
+               if (arm11->dscr & (DSCR_DTR_RX_FULL | DSCR_DTR_TX_FULL))
                {
                        /*
                        The wDTR/rDTR two registers that are used to send/receive data to/from
@@ -315,7 +264,8 @@ static int arm11_leave_debug_state(struct arm11_common *arm11, bool bpwp)
                        registers hold data that was written by one side (CPU or JTAG) and not
                        read out by the other side.
                        */
-                       LOG_ERROR("wDTR/rDTR inconsistent (DSCR %08" PRIx32 ")", DSCR);
+                       LOG_ERROR("wDTR/rDTR inconsistent (DSCR %08x)",
+                                       (unsigned) arm11->dscr);
                        return ERROR_FAIL;
                }
        }
@@ -341,16 +291,16 @@ static int arm11_leave_debug_state(struct arm11_common *arm11, bool bpwp)
        /* restore CPSR, PC, and R0 ... after flushing any modified
         * registers.
         */
-       retval = arm_dpm_write_dirty_registers(&arm11->dpm, bpwp);
+       CHECK_RETVAL(arm_dpm_write_dirty_registers(&arm11->dpm, bpwp));
+
+       CHECK_RETVAL(arm11_bpwp_flush(arm11));
 
        register_cache_invalidate(arm11->arm.core_cache);
 
        /* restore DSCR */
-
-       arm11_write_DSCR(arm11, R(DSCR));
+       CHECK_RETVAL(arm11_write_DSCR(arm11, arm11->dscr));
 
        /* maybe restore rDTR */
-
        if (arm11->is_rdtr_saved)
        {
                arm11_add_debug_SCAN_N(arm11, 0x05, ARM11_TAP_DEFAULT);
@@ -367,7 +317,7 @@ static int arm11_leave_debug_state(struct arm11_common *arm11, bool bpwp)
                arm11_setup_field(arm11,  1, &Ready,    NULL, chain5_fields + 1);
                arm11_setup_field(arm11,  1, &Valid,    NULL, chain5_fields + 2);
 
-               arm11_add_dr_scan_vc(ARRAY_SIZE(chain5_fields), chain5_fields, TAP_DRPAUSE);
+               arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(chain5_fields), chain5_fields, TAP_DRPAUSE);
        }
 
        /* now processor is ready to RESTART */
@@ -380,27 +330,24 @@ static int arm11_poll(struct target *target)
 {
        int retval;
        struct arm11_common *arm11 = target_to_arm11(target);
-       uint32_t        dscr;
-
-       CHECK_RETVAL(arm11_read_DSCR(arm11, &dscr));
-
-       LOG_DEBUG("DSCR %08" PRIx32 "", dscr);
 
-       CHECK_RETVAL(arm11_check_init(arm11, &dscr));
+       CHECK_RETVAL(arm11_check_init(arm11));
 
-       if (dscr & ARM11_DSCR_CORE_HALTED)
+       if (arm11->dscr & DSCR_CORE_HALTED)
        {
                if (target->state != TARGET_HALTED)
                {
                        enum target_state old_state = target->state;
 
                        LOG_DEBUG("enter TARGET_HALTED");
-                       retval = arm11_debug_entry(arm11, dscr);
+                       retval = arm11_debug_entry(arm11);
                        if (retval != ERROR_OK)
                                return retval;
 
                        target_call_event_callbacks(target,
-                               old_state == TARGET_DEBUG_RUNNING ? TARGET_EVENT_DEBUG_HALTED : TARGET_EVENT_HALTED);
+                               (old_state == TARGET_DEBUG_RUNNING)
+                                       ? TARGET_EVENT_DEBUG_HALTED
+                                       : TARGET_EVENT_HALTED);
                }
        }
        else
@@ -418,12 +365,17 @@ static int arm11_poll(struct target *target)
 /* architecture specific status reply */
 static int arm11_arch_state(struct target *target)
 {
+       struct arm11_common *arm11 = target_to_arm11(target);
        int retval;
 
-       retval = armv4_5_arch_state(target);
+       retval = arm_arch_state(target);
 
        /* REVISIT also display ARM11-specific MMU and cache status ... */
 
+       if (target->debug_reason == DBG_REASON_WATCHPOINT)
+               LOG_USER("Watchpoint triggered at PC %#08x",
+                               (unsigned) arm11->dpm.wp_pc);
+
        return retval;
 }
 
@@ -459,14 +411,13 @@ static int arm11_halt(struct target *target)
 
        CHECK_RETVAL(jtag_execute_queue());
 
-       uint32_t dscr;
        int i = 0;
 
        while (1)
        {
-               CHECK_RETVAL(arm11_read_DSCR(arm11, &dscr));
+               CHECK_RETVAL(arm11_read_DSCR(arm11));
 
-               if (dscr & ARM11_DSCR_CORE_HALTED)
+               if (arm11->dscr & DSCR_CORE_HALTED)
                        break;
 
 
@@ -488,7 +439,7 @@ static int arm11_halt(struct target *target)
 
        enum target_state old_state     = target->state;
 
-       arm11_debug_entry(arm11, dscr);
+       CHECK_RETVAL(arm11_debug_entry(arm11));
 
        CHECK_RETVAL(
                target_call_event_callbacks(target,
@@ -500,7 +451,7 @@ static int arm11_halt(struct target *target)
 static uint32_t
 arm11_nextpc(struct arm11_common *arm11, int current, uint32_t address)
 {
-       void *value = arm11->arm.core_cache->reg_list[15].value;
+       void *value = arm11->arm.pc->value;
 
        if (!current)
                buf_set_u32(value, 0, 32, address);
@@ -533,17 +484,14 @@ static int arm11_resume(struct target *target, int current,
        LOG_DEBUG("RESUME PC %08" PRIx32 "%s", address, !current ? "!" : "");
 
        /* clear breakpoints/watchpoints and VCR*/
-       arm11_sc7_clear_vbw(arm11);
+       CHECK_RETVAL(arm11_sc7_clear_vbw(arm11));
 
        if (!debug_execution)
                target_free_all_working_areas(target);
 
-       /* Set up breakpoints */
-       if (handle_breakpoints)
-       {
-               /* check if one matches PC and step over it if necessary */
-
-               struct breakpoint *     bp;
+       /* Should we skip over breakpoints matching the PC? */
+       if (handle_breakpoints) {
+               struct breakpoint *bp;
 
                for (bp = target->breakpoints; bp; bp = bp->next)
                {
@@ -554,9 +502,11 @@ static int arm11_resume(struct target *target, int current,
                                break;
                        }
                }
+       }
 
-               /* set all breakpoints */
-
+       /* activate all breakpoints */
+       if (true) {
+               struct breakpoint *bp;
                unsigned brp_num = 0;
 
                for (bp = target->breakpoints; bp; bp = bp->next)
@@ -570,7 +520,7 @@ static int arm11_resume(struct target *target, int current,
                        brp[1].address  = ARM11_SC7_BCR0 + brp_num;
                        brp[1].value    = 0x1 | (3 << 1) | (0x0F << 5) | (0 << 14) | (0 << 16) | (0 << 20) | (0 << 21);
 
-                       arm11_sc7_run(arm11, brp, ARRAY_SIZE(brp));
+                       CHECK_RETVAL(arm11_sc7_run(arm11, brp, ARRAY_SIZE(brp)));
 
                        LOG_DEBUG("Add BP %d at %08" PRIx32, brp_num,
                                        bp->address);
@@ -578,10 +528,12 @@ static int arm11_resume(struct target *target, int current,
                        brp_num++;
                }
 
-               arm11_sc7_set_vcr(arm11, arm11_vcr);
+               if (arm11->vcr)
+                       CHECK_RETVAL(arm11_sc7_set_vcr(arm11, arm11->vcr));
        }
 
-       arm11_leave_debug_state(arm11, handle_breakpoints);
+       /* activate all watchpoints and breakpoints */
+       CHECK_RETVAL(arm11_leave_debug_state(arm11, true));
 
        arm11_add_IR(arm11, ARM11_RESTART, TAP_IDLE);
 
@@ -590,13 +542,11 @@ static int arm11_resume(struct target *target, int current,
        int i = 0;
        while (1)
        {
-               uint32_t dscr;
+               CHECK_RETVAL(arm11_read_DSCR(arm11));
 
-               CHECK_RETVAL(arm11_read_DSCR(arm11, &dscr));
+               LOG_DEBUG("DSCR %08x", (unsigned) arm11->dscr);
 
-               LOG_DEBUG("DSCR %08" PRIx32 "", dscr);
-
-               if (dscr & ARM11_DSCR_CORE_RESTARTED)
+               if (arm11->dscr & DSCR_CORE_RESTARTED)
                        break;
 
 
@@ -616,20 +566,12 @@ static int arm11_resume(struct target *target, int current,
                i++;
        }
 
+       target->debug_reason = DBG_REASON_NOTHALTED;
        if (!debug_execution)
-       {
-               target->state                   = TARGET_RUNNING;
-               target->debug_reason    = DBG_REASON_NOTHALTED;
-
-               CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_RESUMED));
-       }
+               target->state = TARGET_RUNNING;
        else
-       {
-               target->state                   = TARGET_DEBUG_RUNNING;
-               target->debug_reason    = DBG_REASON_NOTHALTED;
-
-               CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_RESUMED));
-       }
+               target->state = TARGET_DEBUG_RUNNING;
+       CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_RESUMED));
 
        return ERROR_OK;
 }
@@ -695,7 +637,7 @@ static int arm11_step(struct target *target, int current,
                brp[1].write    = 1;
                brp[1].address  = ARM11_SC7_BCR0;
 
-               if (arm11_config_hardware_step)
+               if (arm11->hardware_step)
                {
                        /* Hardware single stepping ("instruction address
                         * mismatch") is used if enabled.  It's not quite
@@ -739,10 +681,11 @@ static int arm11_step(struct target *target, int current,
                /* resume */
 
 
-               if (arm11_config_step_irq_enable)
-                       R(DSCR) &= ~ARM11_DSCR_INTERRUPTS_DISABLE;              /* should be redundant */
+               if (arm11->step_irq_enable)
+                       /* this disable should be redundant ... */
+                       arm11->dscr &= ~DSCR_INT_DIS;
                else
-                       R(DSCR) |= ARM11_DSCR_INTERRUPTS_DISABLE;
+                       arm11->dscr |= DSCR_INT_DIS;
 
 
                CHECK_RETVAL(arm11_leave_debug_state(arm11, handle_breakpoints));
@@ -753,16 +696,16 @@ static int arm11_step(struct target *target, int current,
 
                /* wait for halt */
                int i = 0;
-               uint32_t dscr;
 
                while (1)
                {
-                       CHECK_RETVAL(arm11_read_DSCR(arm11, &dscr));
+                       const uint32_t mask = DSCR_CORE_RESTARTED
+                                       | DSCR_CORE_HALTED;
 
-                       LOG_DEBUG("DSCR %08" PRIx32 "e", dscr);
+                       CHECK_RETVAL(arm11_read_DSCR(arm11));
+                       LOG_DEBUG("DSCR %08x e", (unsigned) arm11->dscr);
 
-                       if ((dscr & (ARM11_DSCR_CORE_RESTARTED | ARM11_DSCR_CORE_HALTED)) ==
-                               (ARM11_DSCR_CORE_RESTARTED | ARM11_DSCR_CORE_HALTED))
+                       if ((arm11->dscr & mask) == mask)
                                break;
 
                        long long then = 0;
@@ -782,17 +725,17 @@ static int arm11_step(struct target *target, int current,
                }
 
                /* clear breakpoint */
-               arm11_sc7_clear_vbw(arm11);
+               CHECK_RETVAL(arm11_sc7_clear_vbw(arm11));
 
                /* save state */
-               CHECK_RETVAL(arm11_debug_entry(arm11, dscr));
+               CHECK_RETVAL(arm11_debug_entry(arm11));
 
-           /* restore default state */
-               R(DSCR) &= ~ARM11_DSCR_INTERRUPTS_DISABLE;
+               /* restore default state */
+               arm11->dscr &= ~DSCR_INT_DIS;
 
        }
 
-       target->debug_reason    = DBG_REASON_SINGLESTEP;
+       target->debug_reason = DBG_REASON_SINGLESTEP;
 
        CHECK_RETVAL(target_call_event_callbacks(target, TARGET_EVENT_HALTED));
 
@@ -801,67 +744,72 @@ static int arm11_step(struct target *target, int current,
 
 static int arm11_assert_reset(struct target *target)
 {
-       int retval;
        struct arm11_common *arm11 = target_to_arm11(target);
 
-       retval = arm11_check_init(arm11, NULL);
-       if (retval != ERROR_OK)
-               return retval;
-
-       target->state = TARGET_UNKNOWN;
+       /* optionally catch reset vector */
+       if (target->reset_halt && !(arm11->vcr & 1))
+               CHECK_RETVAL(arm11_sc7_set_vcr(arm11, arm11->vcr | 1));
 
-       /* we would very much like to reset into the halted, state,
-        * but resetting and halting is second best... */
-       if (target->reset_halt)
-       {
-               CHECK_RETVAL(target_halt(target));
+       /* 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(arm11->arm.core_cache);
 
-       /* srst is funny. We can not do *anything* else while it's asserted
-        * and it has unkonwn side effects. Make sure no other code runs
-        * meanwhile.
-        *
-        * Code below assumes srst:
-        *
-        * - Causes power-on-reset (but of what parts of the system?). Bug
-        * in arm11?
-        *
-        * - Messes us TAP state without asserting trst.
-        *
-        * - There is another bug in the arm11 core. When you generate an access to
-        * external logic (for example ddr controller via AHB bus) and that block
-        * is not configured (perhaps it is still held in reset), that transaction
-        * will never complete. This will hang arm11 core but it will also hang
-        * JTAG controller. Nothing, short of srst assertion will bring it out of
-        * this.
-        *
-        * Mysteries:
-        *
-        * - What should the PC be after an srst reset when starting in the halted
-        * state?
-        */
+       target->state = TARGET_RESET;
 
-       jtag_add_reset(0, 1);
-       jtag_add_reset(0, 0);
+       return ERROR_OK;
+}
 
-       /* How long do we have to wait? */
-       jtag_add_sleep(5000);
+/*
+ * - There is another bug in the arm11 core.  (iMX31 specific again?)
+ *   When you generate an access to external logic (for example DDR
+ *   controller via AHB bus) and that block is not configured (perhaps
+ *   it is still held in reset), that transaction will never complete.
+ *   This will hang arm11 core but it will also hang JTAG controller.
+ *   Nothing short of srst assertion will bring it out of this.
+ */
+
+static int arm11_deassert_reset(struct target *target)
+{
+       struct arm11_common *arm11 = target_to_arm11(target);
+       int retval;
 
-       /* un-mess up TAP state */
+       /* be certain SRST is off */
+       jtag_add_reset(0, 0);
+
+       /* WORKAROUND i.MX31 problems:  SRST goofs the TAP, and resets
+        * at least DSCR.  OMAP24xx doesn't show that problem, though
+        * SRST-only reset seems to be problematic for other reasons.
+        * (Secure boot sequences being one likelihood!)
+        */
        jtag_add_tlr();
 
-       retval = jtag_execute_queue();
-       if (retval != ERROR_OK)
-       {
-               return retval;
+       CHECK_RETVAL(arm11_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;
-}
+       /* maybe restore vector catch config */
+       if (target->reset_halt && !(arm11->vcr & 1))
+               CHECK_RETVAL(arm11_sc7_set_vcr(arm11, arm11->vcr));
 
-static int arm11_deassert_reset(struct target *target)
-{
        return ERROR_OK;
 }
 
@@ -915,12 +863,12 @@ static int arm11_read_memory_inner(struct target *target,
                {
                        /* ldrb    r1, [r0], #1 */
                        /* ldrb    r1, [r0] */
-                       arm11_run_instr_no_data1(arm11,
-                                       !arm11_config_memrw_no_increment ? 0xe4d01001 : 0xe5d01000);
+                       CHECK_RETVAL(arm11_run_instr_no_data1(arm11,
+                                       !arm11_config_memrw_no_increment ? 0xe4d01001 : 0xe5d01000));
 
                        uint32_t res;
                        /* MCR p14,0,R1,c0,c5,0 */
-                       arm11_run_instr_data_from_core(arm11, 0xEE001E15, &res, 1);
+                       CHECK_RETVAL(arm11_run_instr_data_from_core(arm11, 0xEE001E15, &res, 1));
 
                        *buffer++ = res;
                }
@@ -934,13 +882,13 @@ static int arm11_read_memory_inner(struct target *target,
                        for (size_t i = 0; i < count; i++)
                        {
                                /* ldrh    r1, [r0], #2 */
-                               arm11_run_instr_no_data1(arm11,
-                                       !arm11_config_memrw_no_increment ? 0xe0d010b2 : 0xe1d010b0);
+                               CHECK_RETVAL(arm11_run_instr_no_data1(arm11,
+                                       !arm11_config_memrw_no_increment ? 0xe0d010b2 : 0xe1d010b0));
 
                                uint32_t res;
 
                                /* MCR p14,0,R1,c0,c5,0 */
-                               arm11_run_instr_data_from_core(arm11, 0xEE001E15, &res, 1);
+                               CHECK_RETVAL(arm11_run_instr_data_from_core(arm11, 0xEE001E15, &res, 1));
 
                                uint16_t svalue = res;
                                memcpy(buffer + i * sizeof(uint16_t), &svalue, sizeof(uint16_t));
@@ -953,11 +901,11 @@ static int arm11_read_memory_inner(struct target *target,
                {
                uint32_t instr = !arm11_config_memrw_no_increment ? 0xecb05e01 : 0xed905e00;
                /** \todo TODO: buffer cast to uint32_t* causes alignment warnings */
-               uint32_t *words = (uint32_t *)buffer;
+               uint32_t *words = (uint32_t *)(void *)buffer;
 
                /* LDC p14,c5,[R0],#4 */
                /* LDC p14,c5,[R0] */
-               arm11_run_instr_data_from_core(arm11, instr, words, count);
+               CHECK_RETVAL(arm11_run_instr_data_from_core(arm11, instr, words, count));
                break;
                }
        }
@@ -996,6 +944,7 @@ static int arm11_write_memory_inner(struct target *target,
        if (retval != ERROR_OK)
                return retval;
 
+       /* load r0 with buffer address */
        /* MRC p14,0,r0,c0,c5,0 */
        retval = arm11_run_instr_data_to_core1(arm11, 0xee100e15, address);
        if (retval != ERROR_OK)
@@ -1008,7 +957,7 @@ static int arm11_write_memory_inner(struct target *target,
         * now exercise both burst and non-burst code paths with the
         * default settings, increasing code coverage.
         */
-       bool burst = arm11_config_memwrite_burst && (count > 1);
+       bool burst = arm11->memwrite_burst && (count > 1);
 
        switch (size)
        {
@@ -1018,11 +967,13 @@ static int arm11_write_memory_inner(struct target *target,
 
                        for (size_t i = 0; i < count; i++)
                        {
+                               /* load r1 from DCC with byte data */
                                /* MRC p14,0,r1,c0,c5,0 */
                                retval = arm11_run_instr_data_to_core1(arm11, 0xee101e15, *buffer++);
                                if (retval != ERROR_OK)
                                        return retval;
 
+                               /* write r1 to memory */
                                /* strb    r1, [r0], #1 */
                                /* strb    r1, [r0] */
                                retval = arm11_run_instr_no_data1(arm11,
@@ -1045,11 +996,13 @@ static int arm11_write_memory_inner(struct target *target,
                                uint16_t value;
                                memcpy(&value, buffer + i * sizeof(uint16_t), sizeof(uint16_t));
 
+                               /* load r1 from DCC with halfword data */
                                /* MRC p14,0,r1,c0,c5,0 */
                                retval = arm11_run_instr_data_to_core1(arm11, 0xee101e15, value);
                                if (retval != ERROR_OK)
                                        return retval;
 
+                               /* write r1 to memory */
                                /* strh    r1, [r0], #2 */
                                /* strh    r1, [r0] */
                                retval = arm11_run_instr_no_data1(arm11,
@@ -1064,27 +1017,26 @@ static int arm11_write_memory_inner(struct target *target,
                }
 
        case 4: {
+               /* stream word data through DCC directly to memory */
+               /* increment:           STC p14,c5,[R0],#4 */
+               /* no increment:        STC p14,c5,[R0]*/
                uint32_t instr = !no_increment ? 0xeca05e01 : 0xed805e00;
 
                /** \todo TODO: buffer cast to uint32_t* causes alignment warnings */
-               uint32_t *words = (uint32_t*)buffer;
+               uint32_t *words = (uint32_t*)(void *)buffer;
 
+               /* "burst" here just means trusting each instruction executes
+                * fully before we run the next one:  per-word roundtrips, to
+                * check the Ready flag, are not used.
+                */
                if (!burst)
-               {
-                       /* STC p14,c5,[R0],#4 */
-                       /* STC p14,c5,[R0]*/
-                       retval = arm11_run_instr_data_to_core(arm11, instr, words, count);
-                       if (retval != ERROR_OK)
-                               return retval;
-               }
+                       retval = arm11_run_instr_data_to_core(arm11,
+                                       instr, words, count);
                else
-               {
-                       /* STC p14,c5,[R0],#4 */
-                       /* STC p14,c5,[R0]*/
-                       retval = arm11_run_instr_data_to_core_noack(arm11, instr, words, count);
-                       if (retval != ERROR_OK)
-                               return retval;
-               }
+                       retval = arm11_run_instr_data_to_core_noack(arm11,
+                                       instr, words, count);
+               if (retval != ERROR_OK)
+                       return retval;
 
                break;
        }
@@ -1110,7 +1062,7 @@ static int arm11_write_memory_inner(struct target *target,
                        if (burst)
                                LOG_ERROR("use 'arm11 memwrite burst disable' to disable fast burst mode");
 
-                       if (arm11_config_memwrite_error_fatal)
+                       if (arm11->memwrite_error_fatal)
                                return ERROR_FAIL;
                }
        }
@@ -1202,14 +1154,17 @@ static int arm11_target_create(struct target *target, Jim_Interp *interp)
        if (!arm11)
                return ERROR_FAIL;
 
-       armv4_5_init_arch_info(target, &arm11->arm);
+       arm_init_arch_info(target, &arm11->arm);
 
        arm11->jtag_info.tap = target->tap;
        arm11->jtag_info.scann_size = 5;
        arm11->jtag_info.scann_instr = ARM11_SCAN_N;
-       /* cur_scan_chain == 0 */
+       arm11->jtag_info.cur_scan_chain = ~0;   /* invalid/unknown */
        arm11->jtag_info.intest_instr = ARM11_INTEST;
 
+       arm11->memwrite_burst = true;
+       arm11->memwrite_error_fatal = true;
+
        return ERROR_OK;
 }
 
@@ -1217,12 +1172,7 @@ static int arm11_init_target(struct command_context *cmd_ctx,
                struct target *target)
 {
        /* Initialize anything we can set up without talking to the target */
-
-       /* 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);
+       return ERROR_OK;
 }
 
 /* talk to the target and set things up */
@@ -1244,7 +1194,7 @@ static int arm11_examine(struct target *target)
 
        arm11_setup_field(arm11, 32, NULL, &device_id, &idcode_field);
 
-       arm11_add_dr_scan_vc(1, &idcode_field, TAP_DRPAUSE);
+       arm11_add_dr_scan_vc(arm11->arm.target->tap, 1, &idcode_field, TAP_DRPAUSE);
 
        /* check DIDR */
 
@@ -1257,24 +1207,29 @@ static int arm11_examine(struct target *target)
        arm11_setup_field(arm11, 32, NULL, &didr, chain0_fields + 0);
        arm11_setup_field(arm11,  8, NULL, &implementor, chain0_fields + 1);
 
-       arm11_add_dr_scan_vc(ARRAY_SIZE(chain0_fields), chain0_fields, TAP_IDLE);
+       arm11_add_dr_scan_vc(arm11->arm.target->tap, ARRAY_SIZE(chain0_fields), chain0_fields, TAP_IDLE);
 
        CHECK_RETVAL(jtag_execute_queue());
 
-       switch (device_id & 0x0FFFF000)
+       /* assume the manufacturer id is ok; check the part # */
+       switch ((device_id >> 12) & 0xFFFF)
        {
-       case 0x07B36000:
+       case 0x7B36:
                type = "ARM1136";
                break;
-       case 0x07B56000:
+       case 0x7B37:
+               type = "ARM11 MPCore";
+               break;
+       case 0x7B56:
                type = "ARM1156";
                break;
-       case 0x07B76000:
+       case 0x7B76:
                arm11->arm.core_type = ARM_MODE_MON;
+               /* NOTE: could default arm11->hardware_step to true */
                type = "ARM1176";
                break;
        default:
-               LOG_ERROR("'target arm11' expects IDCODE 0x*7B*7****");
+               LOG_ERROR("unexpected ARM11 ID code");
                return ERROR_FAIL;
        }
        LOG_INFO("found %s", type);
@@ -1290,7 +1245,6 @@ static int arm11_examine(struct target *target)
        }
 
        arm11->brp = ((didr >> 24) & 0x0F) + 1;
-       arm11->wrp = ((didr >> 28) & 0x0F) + 1;
 
        /** \todo TODO: reserve one brp slot if we allow breakpoints during step */
        arm11->free_brps = arm11->brp;
@@ -1303,7 +1257,7 @@ static int arm11_examine(struct target *target)
         * as suggested by the spec.
         */
 
-       retval = arm11_check_init(arm11, NULL);
+       retval = arm11_check_init(arm11);
        if (retval != ERROR_OK)
                return retval;
 
@@ -1311,14 +1265,14 @@ static int arm11_examine(struct target *target)
         * want to know if this core supports Secure Monitor mode.
         */
        if (!target_was_examined(target))
-               retval = arm11_dpm_init(arm11, didr);
+               CHECK_RETVAL(arm11_dpm_init(arm11, didr));
 
        /* ETM on ARM11 still uses original scanchain 6 access mode */
        if (arm11->arm.etm && !target_was_examined(target)) {
                *register_get_last_cache_p(&target->reg_cache) =
                        etm_build_reg_cache(target, &arm11->jtag_info,
                                        arm11->arm.etm);
-               retval = etm_setup(target);
+               CHECK_RETVAL(etm_setup(target));
        }
 
        target_set_examined(target);
@@ -1327,166 +1281,61 @@ static int arm11_examine(struct target *target)
 }
 
 
-/** Load a register that is marked !valid in the register cache */
-static int arm11_get_reg(struct reg *reg)
-{
-       struct arm11_reg_state *r = reg->arch_info;
-       struct target *target = r->target;
-
-       if (target->state != TARGET_HALTED)
-       {
-               LOG_WARNING("target was not halted");
-               return ERROR_TARGET_NOT_HALTED;
-       }
-
-       /** \todo TODO: Check this. We assume that all registers are fetched at debug entry. */
-
-#if 0
-       struct arm11_common *arm11 = target_to_arm11(target);
-       const struct arm11_reg_defs *arm11_reg_info = arm11_reg_defs + ((struct arm11_reg_state *)reg->arch_info)->def_index;
-#endif
-
-       return ERROR_OK;
-}
-
-/** Change a value in the register cache */
-static int arm11_set_reg(struct reg *reg, uint8_t *buf)
-{
-       struct arm11_reg_state *r = reg->arch_info;
-       struct target *target = r->target;
-       struct arm11_common *arm11 = target_to_arm11(target);
-//     const struct arm11_reg_defs *arm11_reg_info = arm11_reg_defs + ((struct arm11_reg_state *)reg->arch_info)->def_index;
-
-       arm11->reg_values[((struct arm11_reg_state *)reg->arch_info)->def_index] = buf_get_u32(buf, 0, 32);
-       reg->valid      = 1;
-       reg->dirty      = 1;
-
-       return ERROR_OK;
-}
-
-static const struct reg_arch_type arm11_reg_type = {
-       .get = arm11_get_reg,
-       .set = arm11_set_reg,
-};
-
-static int arm11_build_reg_cache(struct target *target)
-{
-       struct arm11_common *arm11 = target_to_arm11(target);
-       struct reg_cache *cache;
-       struct reg *reg_list;
-       struct arm11_reg_state *arm11_reg_states;
-
-       cache = calloc(1, sizeof *cache);
-       reg_list = calloc(ARM11_REGCACHE_COUNT, sizeof *reg_list);
-       arm11_reg_states = calloc(ARM11_REGCACHE_COUNT,
-                       sizeof *arm11_reg_states);
-       if (!cache || !reg_list || !arm11_reg_states) {
-               free(cache);
-               free(reg_list);
-               free(arm11_reg_states);
-               return ERROR_FAIL;
-       }
-
-       arm11->reg_list = reg_list;
-
-       /* build cache for some of the debug registers */
-       cache->name = "arm11 debug registers";
-       cache->reg_list = reg_list;
-       cache->num_regs = ARM11_REGCACHE_COUNT;
-
-       struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
-       (*cache_p) = cache;
-
-       arm11->core_cache = cache;
-
-       size_t i;
-
-       /* Not very elegant assertion */
-       if (ARM11_REGCACHE_COUNT != ARRAY_SIZE(arm11->reg_values) ||
-               ARM11_REGCACHE_COUNT != ARRAY_SIZE(arm11_reg_defs) ||
-               ARM11_REGCACHE_COUNT != ARM11_RC_MAX)
-       {
-               LOG_ERROR("BUG: arm11->reg_values inconsistent (%d %u %u %d)",
-                               ARM11_REGCACHE_COUNT,
-                               (unsigned) ARRAY_SIZE(arm11->reg_values),
-                               (unsigned) ARRAY_SIZE(arm11_reg_defs),
-                               ARM11_RC_MAX);
-               /* FIXME minimally, use a build_bug_on(X) mechanism;
-                * runtime exit() here is bad!
-                */
-               exit(-1);
-       }
-
-       for (i = 0; i < ARM11_REGCACHE_COUNT; i++)
-       {
-               struct reg *                                            r       = reg_list                      + i;
-               const struct arm11_reg_defs *   rd      = arm11_reg_defs        + i;
-               struct arm11_reg_state *                        rs      = arm11_reg_states      + i;
-
-               r->name                         = rd->name;
-               r->size                         = 32;
-               r->value                        = (uint8_t *)(arm11->reg_values + i);
-               r->dirty                        = 0;
-               r->valid                        = 0;
-               r->type = &arm11_reg_type;
-               r->arch_info            = rs;
-
-               rs->def_index           = i;
-               rs->target                      = target;
-       }
-
-       return ERROR_OK;
-}
-
-/* FIXME all these BOOL_WRAPPER things should be modifying
- * per-instance state, not shared state; ditto the vector
- * catch register support.  Scan chains with multiple cores
- * should be able to say "work with this core like this,
- * that core like that".  Example, ARM11 MPCore ...
- */
-
 #define ARM11_BOOL_WRAPPER(name, print_name)   \
-               COMMAND_HANDLER(arm11_handle_bool_##name) \
-               { \
-                       return CALL_COMMAND_HANDLER(handle_command_parse_bool, \
-                                       &arm11_config_##name, print_name); \
-               }
+       COMMAND_HANDLER(arm11_handle_bool_##name) \
+       { \
+               struct target *target = get_current_target(CMD_CTX); \
+               struct arm11_common *arm11 = target_to_arm11(target); \
+               \
+               return CALL_COMMAND_HANDLER(handle_command_parse_bool, \
+                               &arm11->name, print_name); \
+       }
 
 ARM11_BOOL_WRAPPER(memwrite_burst, "memory write burst mode")
 ARM11_BOOL_WRAPPER(memwrite_error_fatal, "fatal error mode for memory writes")
 ARM11_BOOL_WRAPPER(step_irq_enable, "IRQs while stepping")
 ARM11_BOOL_WRAPPER(hardware_step, "hardware single step")
 
+/* REVISIT handle the VCR bits like other ARMs:  use symbols for
+ * input and output values.
+ */
+
 COMMAND_HANDLER(arm11_handle_vcr)
 {
+       struct target *target = get_current_target(CMD_CTX);
+       struct arm11_common *arm11 = target_to_arm11(target);
+
        switch (CMD_ARGC) {
        case 0:
                break;
        case 1:
-               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], arm11_vcr);
+               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], arm11->vcr);
                break;
        default:
                return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
-       LOG_INFO("VCR 0x%08" PRIx32 "", arm11_vcr);
+       LOG_INFO("VCR 0x%08" PRIx32 "", arm11->vcr);
        return ERROR_OK;
 }
 
 static const struct command_registration arm11_mw_command_handlers[] = {
        {
                .name = "burst",
-               .handler = &arm11_handle_bool_memwrite_burst,
+               .handler = arm11_handle_bool_memwrite_burst,
                .mode = COMMAND_ANY,
-               .help = "Enable/Disable non-standard but fast burst mode"
-                       " (default: enabled)",
+               .help = "Display or modify flag controlling potentially "
+                       "risky fast burst mode (default: enabled)",
+               .usage = "['enable'|'disable']",
        },
        {
                .name = "error_fatal",
-               .handler = &arm11_handle_bool_memwrite_error_fatal,
+               .handler = arm11_handle_bool_memwrite_error_fatal,
                .mode = COMMAND_ANY,
-               .help = "Terminate program if transfer error was found"
+               .help = "Display or modify flag controlling transfer "
+                       "termination on transfer errors"
                        " (default: enabled)",
+               .usage = "['enable'|'disable']",
        },
        COMMAND_REGISTRATION_DONE
 };
@@ -1496,11 +1345,11 @@ static const struct command_registration arm11_any_command_handlers[] = {
                 * simulate + breakpoint implementation is broken.
                 * TEMPORARY! NOT DOCUMENTED! */
                .name = "hardware_step",
-               .handler = &arm11_handle_bool_hardware_step,
+               .handler = arm11_handle_bool_hardware_step,
                .mode = COMMAND_ANY,
                .help = "DEBUG ONLY - Hardware single stepping"
                        " (default: disabled)",
-               .usage = "(enable|disable)",
+               .usage = "['enable'|'disable']",
        },
        {
                .name = "memwrite",
@@ -1510,19 +1359,22 @@ static const struct command_registration arm11_any_command_handlers[] = {
        },
        {
                .name = "step_irq_enable",
-               .handler = &arm11_handle_bool_step_irq_enable,
+               .handler = arm11_handle_bool_step_irq_enable,
                .mode = COMMAND_ANY,
-               .help = "Enable interrupts while stepping"
-                       " (default: disabled)",
+               .help = "Display or modify flag controlling interrupt "
+                       "enable while stepping (default: disabled)",
+               .usage = "['enable'|'disable']",
        },
        {
                .name = "vcr",
-               .handler = &arm11_handle_vcr,
+               .handler = arm11_handle_vcr,
                .mode = COMMAND_ANY,
-               .help = "Control (Interrupt) Vector Catch Register",
+               .help = "Display or modify Vector Catch Register",
+               .usage = "[value]",
        },
        COMMAND_REGISTRATION_DONE
 };
+
 static const struct command_registration arm11_command_handlers[] = {
        {
                .chain = arm_command_handlers,
@@ -1556,7 +1408,7 @@ struct target_type arm11_target = {
        .deassert_reset =       arm11_deassert_reset,
        .soft_reset_halt =      arm11_soft_reset_halt,
 
-       .get_gdb_reg_list =     armv4_5_get_gdb_reg_list,
+       .get_gdb_reg_list =     arm_get_gdb_reg_list,
 
        .read_memory =          arm11_read_memory,
        .write_memory =         arm11_write_memory,