scan_field_t -> struct scan_field
[fw/openocd] / src / target / arm11.c
index 6ced8f42173d7f09465087d925bbb6235fc49b34..23185488dc6bdf8362c1d843932f54f6fdd2a3b3 100644 (file)
@@ -2,7 +2,7 @@
  *   Copyright (C) 2008 digenius technology GmbH.                          *
  *   Michael Bruck                                                         *
  *                                                                         *
- *   Copyright (C) 2008 Oyvind Harboe oyvind.harboe@zylin.com              *
+ *   Copyright (C) 2008,2009 Oyvind Harboe oyvind.harboe@zylin.com         *
  *                                                                         *
  *   Copyright (C) 2008 Georg Acher <acher@in.tum.de>                      *
  *                                                                         *
 #endif
 
 #include "arm11.h"
+#include "arm11_dbgtap.h"
+#include "armv4_5.h"
+#include "arm_simulator.h"
+#include "time_support.h"
 #include "target_type.h"
 
 
 #define FNC_INFO_NOTIMPLEMENTED
 #endif
 
-static int arm11_on_enter_debug_state(arm11_common_t * arm11);
-
-bool   arm11_config_memwrite_burst                             = true;
-bool   arm11_config_memwrite_error_fatal               = true;
-uint32_t               arm11_vcr                                                               = 0;
-bool   arm11_config_memrw_no_increment                 = false;
-bool   arm11_config_step_irq_enable                    = false;
-
-#define ARM11_HANDLER(x)       \
-       .x                              = arm11_##x
-
-target_type_t arm11_target =
-{
-       .name                   = "arm11",
-
-       ARM11_HANDLER(poll),
-       ARM11_HANDLER(arch_state),
-
-       ARM11_HANDLER(target_request_data),
-
-       ARM11_HANDLER(halt),
-       ARM11_HANDLER(resume),
-       ARM11_HANDLER(step),
-
-       ARM11_HANDLER(assert_reset),
-       ARM11_HANDLER(deassert_reset),
-       ARM11_HANDLER(soft_reset_halt),
-
-       ARM11_HANDLER(get_gdb_reg_list),
-
-       ARM11_HANDLER(read_memory),
-       ARM11_HANDLER(write_memory),
-
-       ARM11_HANDLER(bulk_write_memory),
-
-       ARM11_HANDLER(checksum_memory),
-
-       ARM11_HANDLER(add_breakpoint),
-       ARM11_HANDLER(remove_breakpoint),
-       ARM11_HANDLER(add_watchpoint),
-       ARM11_HANDLER(remove_watchpoint),
-
-       ARM11_HANDLER(run_algorithm),
-
-       ARM11_HANDLER(register_commands),
-       ARM11_HANDLER(target_create),
-       ARM11_HANDLER(init_target),
-       ARM11_HANDLER(examine),
-       ARM11_HANDLER(quit),
-};
-
-int arm11_regs_arch_type = -1;
+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;
 
+static int arm11_regs_arch_type = -1;
 
 enum arm11_regtype
 {
@@ -288,21 +246,32 @@ enum arm11_regcache_ids
 
 #define ARM11_GDB_REGISTER_COUNT       26
 
-uint8_t arm11_gdb_dummy_fp_value[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+static uint8_t arm11_gdb_dummy_fp_value[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 
-reg_t arm11_gdb_dummy_fp_reg =
+static reg_t arm11_gdb_dummy_fp_reg =
 {
        "GDB dummy floating-point register", arm11_gdb_dummy_fp_value, 0, 1, 96, NULL, 0, NULL, 0
 };
 
-uint8_t arm11_gdb_dummy_fps_value[] = {0, 0, 0, 0};
+static uint8_t arm11_gdb_dummy_fps_value[] = {0, 0, 0, 0};
 
-reg_t arm11_gdb_dummy_fps_reg =
+static reg_t arm11_gdb_dummy_fps_reg =
 {
        "GDB dummy floating-point status register", arm11_gdb_dummy_fps_value, 0, 1, 32, NULL, 0, NULL, 0
 };
 
 
+static int arm11_on_enter_debug_state(arm11_common_t *arm11);
+static int arm11_step(struct target_s *target, int current,
+               uint32_t address, int handle_breakpoints);
+/* helpers */
+static int arm11_build_reg_cache(target_t *target);
+static int arm11_set_reg(reg_t *reg, uint8_t *buf);
+static int arm11_get_reg(reg_t *reg);
+
+static void arm11_record_register_history(arm11_common_t * arm11);
+static void arm11_dump_reg_changes(arm11_common_t * arm11);
+
 
 /** Check and if necessary take control of the system
  *
@@ -311,7 +280,7 @@ reg_t arm11_gdb_dummy_fps_reg =
  *                                     available a pointer to a word holding the
  *                                     DSCR can be passed. Otherwise use NULL.
  */
-int arm11_check_init(arm11_common_t * arm11, uint32_t * dscr)
+static int arm11_check_init(arm11_common_t *arm11, uint32_t *dscr)
 {
        FNC_INFO;
 
@@ -369,8 +338,9 @@ int arm11_check_init(arm11_common_t * arm11, uint32_t * dscr)
   * or on other occasions that stop the processor.
   *
   */
-static int arm11_on_enter_debug_state(arm11_common_t * arm11)
+static int arm11_on_enter_debug_state(arm11_common_t *arm11)
 {
+       int retval;
        FNC_INFO;
 
        for (size_t i = 0; i < asizeof(arm11->reg_values); i++)
@@ -390,7 +360,7 @@ static int arm11_on_enter_debug_state(arm11_common_t * arm11)
 
                arm11_add_IR(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT);
 
-               scan_field_t    chain5_fields[3];
+               struct scan_field       chain5_fields[3];
 
                arm11_setup_field(arm11, 32, NULL, &R(WDTR),    chain5_fields + 0);
                arm11_setup_field(arm11,  1, NULL, NULL,                chain5_fields + 1);
@@ -447,7 +417,9 @@ static int arm11_on_enter_debug_state(arm11_common_t * arm11)
        }
 #endif
 
-       arm11_run_instr_data_prepare(arm11);
+       retval = arm11_run_instr_data_prepare(arm11);
+       if (retval != ERROR_OK)
+               return retval;
 
        /* save r0 - r14 */
 
@@ -456,7 +428,9 @@ static int arm11_on_enter_debug_state(arm11_common_t * arm11)
        for (size_t i = 0; i < 15; i++)
        {
                /* MCR p14,0,R?,c0,c5,0 */
-               arm11_run_instr_data_from_core(arm11, 0xEE000E15 | (i << 12), &R(RX + i), 1);
+               retval = arm11_run_instr_data_from_core(arm11, 0xEE000E15 | (i << 12), &R(RX + i), 1);
+               if (retval != ERROR_OK)
+                       return retval;
        }
 
        /* save rDTR */
@@ -466,7 +440,9 @@ static int arm11_on_enter_debug_state(arm11_common_t * arm11)
        if (R(DSCR) & ARM11_DSCR_RDTR_FULL)
        {
                /* MRC p14,0,R0,c0,c5,0 (move rDTR -> r0 (-> wDTR -> local var)) */
-               arm11_run_instr_data_from_core_via_r0(arm11, 0xEE100E15, &R(RDTR));
+               retval = arm11_run_instr_data_from_core_via_r0(arm11, 0xEE100E15, &R(RDTR));
+               if (retval != ERROR_OK)
+                       return retval;
        }
        else
        {
@@ -476,12 +452,16 @@ static int arm11_on_enter_debug_state(arm11_common_t * arm11)
        /* save CPSR */
 
        /* MRS r0,CPSR (move CPSR -> r0 (-> wDTR -> local var)) */
-       arm11_run_instr_data_from_core_via_r0(arm11, 0xE10F0000, &R(CPSR));
+       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)) */
-       arm11_run_instr_data_from_core_via_r0(arm11, 0xE1A0000F, &R(PC));
+       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 */
 
@@ -507,11 +487,15 @@ static int arm11_on_enter_debug_state(arm11_common_t * arm11)
                /* Write 0 (reset value) to Control register 0 to disable MMU/Cache etc. */
 
                /* MCR p15,0,R0,c1,c0,0 */
-               arm11_run_instr_data_to_core_via_r0(arm11, 0xee010f10, 0);
+               retval = arm11_run_instr_data_to_core_via_r0(arm11, 0xee010f10, 0);
+               if (retval != ERROR_OK)
+                       return retval;
 
        }
 
-       arm11_run_instr_data_finish(arm11);
+       retval = arm11_run_instr_data_finish(arm11);
+       if (retval != ERROR_OK)
+               return retval;
 
        arm11_dump_reg_changes(arm11);
 
@@ -553,11 +537,14 @@ void arm11_dump_reg_changes(arm11_common_t * arm11)
   * This is called in preparation for the RESTART function.
   *
   */
-int arm11_leave_debug_state(arm11_common_t * arm11)
+static int arm11_leave_debug_state(arm11_common_t *arm11)
 {
        FNC_INFO;
+       int retval;
 
-       arm11_run_instr_data_prepare(arm11);
+       retval = arm11_run_instr_data_prepare(arm11);
+       if (retval != ERROR_OK)
+               return retval;
 
        /** \todo TODO: handle other mode registers */
 
@@ -574,7 +561,9 @@ int arm11_leave_debug_state(arm11_common_t * arm11)
                //      LOG_DEBUG("RESTORE R" ZU " %08x", i, R(RX + i));
        }
 
-       arm11_run_instr_data_finish(arm11);
+       retval = arm11_run_instr_data_finish(arm11);
+       if (retval != ERROR_OK)
+               return retval;
 
        /* spec says clear wDTR and rDTR; we assume they are clear as
           otherwise our programming would be sloppy */
@@ -585,36 +574,56 @@ int arm11_leave_debug_state(arm11_common_t * arm11)
 
                if (DSCR & (ARM11_DSCR_RDTR_FULL | ARM11_DSCR_WDTR_FULL))
                {
+                       /*
+                       The wDTR/rDTR two registers that are used to send/receive data to/from
+                       the core in tandem with corresponding instruction codes that are
+                       written into the core. The RDTR FULL/WDTR FULL flag indicates that the
+                       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);
+                       return ERROR_FAIL;
                }
        }
 
-       arm11_run_instr_data_prepare(arm11);
+       retval = arm11_run_instr_data_prepare(arm11);
+       if (retval != ERROR_OK)
+               return retval;
 
        /* restore original wDTR */
 
        if ((R(DSCR) & ARM11_DSCR_WDTR_FULL) || arm11->reg_list[ARM11_RC_WDTR].dirty)
        {
                /* MCR p14,0,R0,c0,c5,0 */
-               arm11_run_instr_data_to_core_via_r0(arm11, 0xee000e15, R(WDTR));
+               retval = arm11_run_instr_data_to_core_via_r0(arm11, 0xee000e15, R(WDTR));
+               if (retval != ERROR_OK)
+                       return retval;
        }
 
        /* restore CPSR */
 
        /* MSR CPSR,R0*/
-       arm11_run_instr_data_to_core_via_r0(arm11, 0xe129f000, R(CPSR));
+       retval = arm11_run_instr_data_to_core_via_r0(arm11, 0xe129f000, R(CPSR));
+       if (retval != ERROR_OK)
+               return retval;
+
 
        /* restore PC */
 
        /* MOV PC,R0 */
-       arm11_run_instr_data_to_core_via_r0(arm11, 0xe1a0f000, R(PC));
+       retval = arm11_run_instr_data_to_core_via_r0(arm11, 0xe1a0f000, R(PC));
+       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));
 
-       arm11_run_instr_data_finish(arm11);
+       retval = arm11_run_instr_data_finish(arm11);
+       if (retval != ERROR_OK)
+               return retval;
 
        /* restore DSCR */
 
@@ -628,7 +637,7 @@ int arm11_leave_debug_state(arm11_common_t * arm11)
 
                arm11_add_IR(arm11, ARM11_EXTEST, ARM11_TAP_DEFAULT);
 
-               scan_field_t    chain5_fields[3];
+               struct scan_field       chain5_fields[3];
 
                uint8_t                 Ready           = 0;    /* ignored */
                uint8_t                 Valid           = 0;    /* ignored */
@@ -645,7 +654,7 @@ int arm11_leave_debug_state(arm11_common_t * arm11)
        return ERROR_OK;
 }
 
-void arm11_record_register_history(arm11_common_t * arm11)
+static void arm11_record_register_history(arm11_common_t *arm11)
 {
        for (size_t i = 0; i < ARM11_REGCACHE_COUNT; i++)
        {
@@ -659,15 +668,13 @@ void arm11_record_register_history(arm11_common_t * arm11)
 
 
 /* poll current target status */
-int arm11_poll(struct target_s *target)
+static int arm11_poll(struct target_s *target)
 {
        FNC_INFO;
+       int retval;
 
        arm11_common_t * arm11 = target->arch_info;
 
-       if (arm11->trst_active)
-               return ERROR_OK;
-
        uint32_t        dscr;
 
        CHECK_RETVAL(arm11_read_DSCR(arm11, &dscr));
@@ -685,7 +692,9 @@ int arm11_poll(struct target_s *target)
                        LOG_DEBUG("enter TARGET_HALTED");
                        target->state                   = TARGET_HALTED;
                        target->debug_reason    = arm11_get_DSCR_debug_reason(dscr);
-                       arm11_on_enter_debug_state(arm11);
+                       retval = arm11_on_enter_debug_state(arm11);
+                       if (retval != ERROR_OK)
+                               return retval;
 
                        target_call_event_callbacks(target,
                                old_state == TARGET_DEBUG_RUNNING ? TARGET_EVENT_DEBUG_HALTED : TARGET_EVENT_HALTED);
@@ -704,7 +713,7 @@ int arm11_poll(struct target_s *target)
        return ERROR_OK;
 }
 /* architecture specific status reply */
-int arm11_arch_state(struct target_s *target)
+static int arm11_arch_state(struct target_s *target)
 {
        arm11_common_t * arm11 = target->arch_info;
 
@@ -717,7 +726,8 @@ int arm11_arch_state(struct target_s *target)
 }
 
 /* target request support */
-int arm11_target_request_data(struct target_s *target, uint32_t size, uint8_t *buffer)
+static int arm11_target_request_data(struct target_s *target,
+               uint32_t size, uint8_t *buffer)
 {
        FNC_INFO_NOTIMPLEMENTED;
 
@@ -725,7 +735,7 @@ int arm11_target_request_data(struct target_s *target, uint32_t size, uint8_t *b
 }
 
 /* target execution control */
-int arm11_halt(struct target_s *target)
+static int arm11_halt(struct target_s *target)
 {
        FNC_INFO;
 
@@ -745,24 +755,35 @@ int arm11_halt(struct target_s *target)
                return ERROR_OK;
        }
 
-       if (arm11->trst_active)
-       {
-               arm11->halt_requested = true;
-               return ERROR_OK;
-       }
-
        arm11_add_IR(arm11, ARM11_HALT, TAP_IDLE);
 
        CHECK_RETVAL(jtag_execute_queue());
 
        uint32_t dscr;
 
+       int i = 0;
        while (1)
        {
                CHECK_RETVAL(arm11_read_DSCR(arm11, &dscr));
 
                if (dscr & ARM11_DSCR_CORE_HALTED)
                        break;
+
+
+               long long then = 0;
+               if (i == 1000)
+               {
+                       then = timeval_ms();
+               }
+               if (i >= 1000)
+               {
+                       if ((timeval_ms()-then) > 1000)
+                       {
+                               LOG_WARNING("Timeout (1000ms) waiting for instructions to complete");
+                               return ERROR_FAIL;
+                       }
+               }
+               i++;
        }
 
        arm11_on_enter_debug_state(arm11);
@@ -779,7 +800,8 @@ int arm11_halt(struct target_s *target)
        return ERROR_OK;
 }
 
-int arm11_resume(struct target_s *target, int current, uint32_t address, int handle_breakpoints, int debug_execution)
+static int arm11_resume(struct target_s *target, int current,
+               uint32_t address, int handle_breakpoints, int debug_execution)
 {
        FNC_INFO;
 
@@ -854,6 +876,7 @@ int arm11_resume(struct target_s *target, int current, uint32_t address, int han
 
        CHECK_RETVAL(jtag_execute_queue());
 
+       int i = 0;
        while (1)
        {
                uint32_t dscr;
@@ -864,6 +887,22 @@ int arm11_resume(struct target_s *target, int current, uint32_t address, int han
 
                if (dscr & ARM11_DSCR_CORE_RESTARTED)
                        break;
+
+
+               long long then = 0;
+               if (i == 1000)
+               {
+                       then = timeval_ms();
+               }
+               if (i >= 1000)
+               {
+                       if ((timeval_ms()-then) > 1000)
+                       {
+                               LOG_WARNING("Timeout (1000ms) waiting for instructions to complete");
+                               return ERROR_FAIL;
+                       }
+               }
+               i++;
        }
 
        if (!debug_execution)
@@ -884,7 +923,98 @@ int arm11_resume(struct target_s *target, int current, uint32_t address, int han
        return ERROR_OK;
 }
 
-int arm11_step(struct target_s *target, int current, uint32_t address, int handle_breakpoints)
+
+static int armv4_5_to_arm11(int reg)
+{
+       if (reg < 16)
+               return reg;
+       switch (reg)
+       {
+       case ARMV4_5_CPSR:
+               return ARM11_RC_CPSR;
+       case 16:
+               /* FIX!!! handle thumb better! */
+               return ARM11_RC_CPSR;
+       default:
+               LOG_ERROR("BUG: register translation from armv4_5 to arm11 not supported %d", reg);
+               exit(-1);
+       }
+}
+
+
+static uint32_t arm11_sim_get_reg(struct arm_sim_interface *sim, int reg)
+{
+       arm11_common_t * arm11 = (arm11_common_t *)sim->user_data;
+
+       reg=armv4_5_to_arm11(reg);
+
+       return buf_get_u32(arm11->reg_list[reg].value, 0, 32);
+}
+
+static void arm11_sim_set_reg(struct arm_sim_interface *sim,
+               int reg, uint32_t value)
+{
+       arm11_common_t * arm11 = (arm11_common_t *)sim->user_data;
+
+       reg=armv4_5_to_arm11(reg);
+
+       buf_set_u32(arm11->reg_list[reg].value, 0, 32, value);
+}
+
+static uint32_t arm11_sim_get_cpsr(struct arm_sim_interface *sim,
+               int pos, int bits)
+{
+       arm11_common_t * arm11 = (arm11_common_t *)sim->user_data;
+
+       return buf_get_u32(arm11->reg_list[ARM11_RC_CPSR].value, pos, bits);
+}
+
+static enum armv4_5_state arm11_sim_get_state(struct arm_sim_interface *sim)
+{
+//     arm11_common_t * arm11 = (arm11_common_t *)sim->user_data;
+
+       /* FIX!!!! we should implement thumb for arm11 */
+       return ARMV4_5_STATE_ARM;
+}
+
+static void arm11_sim_set_state(struct arm_sim_interface *sim,
+               enum armv4_5_state mode)
+{
+//     arm11_common_t * arm11 = (arm11_common_t *)sim->user_data;
+
+       /* FIX!!!! we should implement thumb for arm11 */
+       LOG_ERROR("Not implemetned!");
+}
+
+
+static enum armv4_5_mode arm11_sim_get_mode(struct arm_sim_interface *sim)
+{
+       //arm11_common_t * arm11 = (arm11_common_t *)sim->user_data;
+
+       /* FIX!!!! we should implement something that returns the current mode here!!! */
+       return ARMV4_5_MODE_USR;
+}
+
+static int arm11_simulate_step(target_t *target, uint32_t *dry_run_pc)
+{
+       struct arm_sim_interface sim;
+
+       sim.user_data=target->arch_info;
+       sim.get_reg=&arm11_sim_get_reg;
+       sim.set_reg=&arm11_sim_set_reg;
+       sim.get_reg_mode=&arm11_sim_get_reg;
+       sim.set_reg_mode=&arm11_sim_set_reg;
+       sim.get_cpsr=&arm11_sim_get_cpsr;
+       sim.get_mode=&arm11_sim_get_mode;
+       sim.get_state=&arm11_sim_get_state;
+       sim.set_state=&arm11_sim_set_state;
+
+       return arm_simulate_step_core(target, dry_run_pc, &sim);
+
+}
+
+static int arm11_step(struct target_s *target, int current,
+               uint32_t address, int handle_breakpoints)
 {
        FNC_INFO;
 
@@ -904,6 +1034,7 @@ int arm11_step(struct target_s *target, int current, uint32_t address, int handl
 
        LOG_DEBUG("STEP PC %08" PRIx32 "%s", R(PC), !current ? "!" : "");
 
+
        /** \todo TODO: Thumb not supported here */
 
        uint32_t        next_instruction;
@@ -947,10 +1078,30 @@ int arm11_step(struct target_s *target, int current, uint32_t address, int handl
 
                brp[0].write    = 1;
                brp[0].address  = ARM11_SC7_BVR0;
-               brp[0].value    = R(PC);
                brp[1].write    = 1;
                brp[1].address  = ARM11_SC7_BCR0;
-               brp[1].value    = 0x1 | (3 << 1) | (0x0F << 5) | (0 << 14) | (0 << 16) | (0 << 20) | (2 << 21);
+
+               if (arm11_config_hardware_step)
+               {
+                       /* hardware single stepping be used if possible or is it better to
+                        * always use the same code path? Hardware single stepping is not supported
+                        * on all hardware
+                        */
+                        brp[0].value   = R(PC);
+                        brp[1].value   = 0x1 | (3 << 1) | (0x0F << 5) | (0 << 14) | (0 << 16) | (0 << 20) | (2 << 21);
+               } else
+               {
+                       /* sets a breakpoint on the next PC(calculated by simulation),
+                        */
+                       uint32_t next_pc;
+                       int retval;
+                       retval = arm11_simulate_step(target, &next_pc);
+                       if (retval != ERROR_OK)
+                               return retval;
+
+                       brp[0].value    = next_pc;
+                       brp[1].value    = 0x1 | (3 << 1) | (0x0F << 5) | (0 << 14) | (0 << 16) | (0 << 20) | (0 << 21);
+               }
 
                CHECK_RETVAL(arm11_sc7_run(arm11, brp, asizeof(brp)));
 
@@ -969,10 +1120,8 @@ int arm11_step(struct target_s *target, int current, uint32_t address, int handl
 
                CHECK_RETVAL(jtag_execute_queue());
 
-               /** \todo TODO: add a timeout */
-
                /* wait for halt */
-
+               int i = 0;
                while (1)
                {
                        uint32_t dscr;
@@ -984,6 +1133,21 @@ int arm11_step(struct target_s *target, int current, uint32_t address, int handl
                        if ((dscr & (ARM11_DSCR_CORE_RESTARTED | ARM11_DSCR_CORE_HALTED)) ==
                                (ARM11_DSCR_CORE_RESTARTED | ARM11_DSCR_CORE_HALTED))
                                break;
+
+                       long long then = 0;
+                       if (i == 1000)
+                       {
+                               then = timeval_ms();
+                       }
+                       if (i >= 1000)
+                       {
+                               if ((timeval_ms()-then) > 1000)
+                               {
+                                       LOG_WARNING("Timeout (1000ms) waiting for instructions to complete");
+                                       return ERROR_FAIL;
+                               }
+                       }
+                       i++;
                }
 
                /* clear breakpoint */
@@ -1005,53 +1169,74 @@ int arm11_step(struct target_s *target, int current, uint32_t address, int handl
        return ERROR_OK;
 }
 
-/* target reset control */
-int arm11_assert_reset(struct target_s *target)
+static int arm11_assert_reset(target_t *target)
 {
        FNC_INFO;
-
-#if 0
-       /* assert reset lines */
-       /* resets only the DBGTAP, not the ARM */
-
-       jtag_add_reset(1, 0);
-       jtag_add_sleep(5000);
+       int retval;
 
        arm11_common_t * arm11 = target->arch_info;
-       arm11->trst_active = true;
-#endif
+       retval = arm11_check_init(arm11, NULL);
+       if (retval != ERROR_OK)
+               return retval;
+
+       target->state = TARGET_UNKNOWN;
 
+       /* 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));
        }
 
-       return ERROR_OK;
-}
 
-int arm11_deassert_reset(struct target_s *target)
-{
-       FNC_INFO;
+       /* 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?
+        */
 
-#if 0
-       LOG_DEBUG("target->state: %s",
-               target_state_name(target));
+       jtag_add_reset(0, 1);
+       jtag_add_reset(0, 0);
 
+       /* How long do we have to wait? */
+       jtag_add_sleep(5000);
 
-       /* deassert reset lines */
-       jtag_add_reset(0, 0);
+       /* un-mess up TAP state */
+       jtag_add_tlr();
 
-       arm11_common_t * arm11 = target->arch_info;
-       arm11->trst_active = false;
+       retval = jtag_execute_queue();
+       if (retval != ERROR_OK)
+       {
+               return retval;
+       }
 
-       if (arm11->halt_requested)
-               return arm11_halt(target);
-#endif
+       return ERROR_OK;
+}
 
+static int arm11_deassert_reset(target_t *target)
+{
        return ERROR_OK;
 }
 
-int arm11_soft_reset_halt(struct target_s *target)
+static int arm11_soft_reset_halt(struct target_s *target)
 {
        FNC_INFO_NOTIMPLEMENTED;
 
@@ -1059,7 +1244,8 @@ int arm11_soft_reset_halt(struct target_s *target)
 }
 
 /* target register access for gdb */
-int arm11_get_gdb_reg_list(struct target_s *target, struct reg_s **reg_list[], int *reg_list_size)
+static int arm11_get_gdb_reg_list(struct target_s *target,
+               struct reg_s **reg_list[], int *reg_list_size)
 {
        FNC_INFO;
 
@@ -1089,10 +1275,17 @@ int arm11_get_gdb_reg_list(struct target_s *target, struct reg_s **reg_list[], i
 /* target memory access
  * size: 1 = byte (8bit), 2 = half-word (16bit), 4 = word (32bit)
  * count: number of items of <size>
+ *
+ * arm11_config_memrw_no_increment - in the future we may want to be able
+ * to read/write a range of data to a "port". a "port" is an action on
+ * read memory address for some peripheral.
  */
-int arm11_read_memory(struct target_s *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
+static int arm11_read_memory_inner(struct target_s *target,
+               uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer,
+               bool arm11_config_memrw_no_increment)
 {
        /** \todo TODO: check if buffer cast to uint32_t* and uint16_t* might cause alignment problems */
+       int retval;
 
        FNC_INFO;
 
@@ -1106,10 +1299,14 @@ int arm11_read_memory(struct target_s *target, uint32_t address, uint32_t size,
 
        arm11_common_t * arm11 = target->arch_info;
 
-       arm11_run_instr_data_prepare(arm11);
+       retval = arm11_run_instr_data_prepare(arm11);
+       if (retval != ERROR_OK)
+               return retval;
 
        /* MRC p14,0,r0,c0,c5,0 */
-       arm11_run_instr_data_to_core1(arm11, 0xee100e15, address);
+       retval = arm11_run_instr_data_to_core1(arm11, 0xee100e15, address);
+       if (retval != ERROR_OK)
+               return retval;
 
        switch (size)
        {
@@ -1168,13 +1365,24 @@ int arm11_read_memory(struct target_s *target, uint32_t address, uint32_t size,
                }
        }
 
-       arm11_run_instr_data_finish(arm11);
+       return arm11_run_instr_data_finish(arm11);
+}
 
-       return ERROR_OK;
+static int arm11_read_memory(struct target_s *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
+{
+       return arm11_read_memory_inner(target, address, size, count, buffer, false);
 }
 
-int arm11_write_memory(struct target_s *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
+/*
+* arm11_config_memrw_no_increment - in the future we may want to be able
+* to read/write a range of data to a "port". a "port" is an action on
+* read memory address for some peripheral.
+*/
+static int arm11_write_memory_inner(struct target_s *target,
+               uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer,
+               bool arm11_config_memrw_no_increment)
 {
+       int retval;
        FNC_INFO;
 
        if (target->state != TARGET_HALTED)
@@ -1187,10 +1395,23 @@ int arm11_write_memory(struct target_s *target, uint32_t address, uint32_t size,
 
        arm11_common_t * arm11 = target->arch_info;
 
-       arm11_run_instr_data_prepare(arm11);
+       retval = arm11_run_instr_data_prepare(arm11);
+       if (retval != ERROR_OK)
+               return retval;
 
        /* MRC p14,0,r0,c0,c5,0 */
-       arm11_run_instr_data_to_core1(arm11, 0xee100e15, address);
+       retval = arm11_run_instr_data_to_core1(arm11, 0xee100e15, address);
+       if (retval != ERROR_OK)
+               return retval;
+
+       /* burst writes are not used for single words as those may well be
+        * reset init script writes.
+        *
+        * The other advantage is that as burst writes are default, we'll
+        * now exercise both burst and non-burst code paths with the
+        * default settings, increasing code coverage.
+        */
+       bool burst = arm11_config_memwrite_burst && (count > 1);
 
        switch (size)
        {
@@ -1201,12 +1422,16 @@ int arm11_write_memory(struct target_s *target, uint32_t address, uint32_t size,
                        for (size_t i = 0; i < count; i++)
                        {
                                /* MRC p14,0,r1,c0,c5,0 */
-                               arm11_run_instr_data_to_core1(arm11, 0xee101e15, *buffer++);
+                               retval = arm11_run_instr_data_to_core1(arm11, 0xee101e15, *buffer++);
+                               if (retval != ERROR_OK)
+                                       return retval;
 
                                /* strb    r1, [r0], #1 */
                                /* strb    r1, [r0] */
-                               arm11_run_instr_no_data1(arm11,
+                               retval = arm11_run_instr_no_data1(arm11,
                                        !arm11_config_memrw_no_increment ? 0xe4c01001 : 0xe5c01000);
+                               if (retval != ERROR_OK)
+                                       return retval;
                        }
 
                        break;
@@ -1222,12 +1447,16 @@ int arm11_write_memory(struct target_s *target, uint32_t address, uint32_t size,
                                memcpy(&value, buffer + i * sizeof(uint16_t), sizeof(uint16_t));
 
                                /* MRC p14,0,r1,c0,c5,0 */
-                               arm11_run_instr_data_to_core1(arm11, 0xee101e15, value);
+                               retval = arm11_run_instr_data_to_core1(arm11, 0xee101e15, value);
+                               if (retval != ERROR_OK)
+                                       return retval;
 
                                /* strh    r1, [r0], #2 */
                                /* strh    r1, [r0] */
-                               arm11_run_instr_no_data1(arm11,
+                               retval = arm11_run_instr_no_data1(arm11,
                                        !arm11_config_memrw_no_increment ? 0xe0c010b2 : 0xe1c010b0);
+                               if (retval != ERROR_OK)
+                                       return retval;
                        }
 
                        break;
@@ -1239,53 +1468,64 @@ int arm11_write_memory(struct target_s *target, uint32_t address, uint32_t size,
                /** \todo TODO: buffer cast to uint32_t* causes alignment warnings */
                uint32_t *words = (uint32_t*)buffer;
 
-               if (!arm11_config_memwrite_burst)
+               if (!burst)
                {
                        /* STC p14,c5,[R0],#4 */
                        /* STC p14,c5,[R0]*/
-                       arm11_run_instr_data_to_core(arm11, instr, words, count);
+                       retval = arm11_run_instr_data_to_core(arm11, instr, words, count);
+                       if (retval != ERROR_OK)
+                               return retval;
                }
                else
                {
                        /* STC p14,c5,[R0],#4 */
                        /* STC p14,c5,[R0]*/
-                       arm11_run_instr_data_to_core_noack(arm11, instr, words, count);
+                       retval = arm11_run_instr_data_to_core_noack(arm11, instr, words, count);
+                       if (retval != ERROR_OK)
+                               return retval;
                }
 
                break;
        }
        }
 
-#if 1
        /* r0 verification */
        if (!arm11_config_memrw_no_increment)
        {
                uint32_t r0;
 
                /* MCR p14,0,R0,c0,c5,0 */
-               arm11_run_instr_data_from_core(arm11, 0xEE000E15, &r0, 1);
+               retval = arm11_run_instr_data_from_core(arm11, 0xEE000E15, &r0, 1);
+               if (retval != ERROR_OK)
+                       return retval;
 
                if (address + size * count != r0)
                {
-                       LOG_ERROR("Data transfer failed. (%d)", (int)((r0 - address) - size * count));
+                       LOG_ERROR("Data transfer failed. Expected end "
+                                       "address 0x%08x, got 0x%08x",
+                                       (unsigned) (address + size * count),
+                                       (unsigned) r0);
 
-                       if (arm11_config_memwrite_burst)
+                       if (burst)
                                LOG_ERROR("use 'arm11 memwrite burst disable' to disable fast burst mode");
 
                        if (arm11_config_memwrite_error_fatal)
                                return ERROR_FAIL;
                }
        }
-#endif
-
-       arm11_run_instr_data_finish(arm11);
 
-       return ERROR_OK;
+       return arm11_run_instr_data_finish(arm11);
 }
 
+static int arm11_write_memory(struct target_s *target,
+               uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer)
+{
+       return arm11_write_memory_inner(target, address, size, count, buffer, false);
+}
 
 /* write target memory in multiples of 4 byte, optimized for writing large quantities of data */
-int arm11_bulk_write_memory(struct target_s *target, uint32_t address, uint32_t count, uint8_t *buffer)
+static int arm11_bulk_write_memory(struct target_s *target,
+               uint32_t address, uint32_t count, uint8_t *buffer)
 {
        FNC_INFO;
 
@@ -1302,7 +1542,8 @@ int arm11_bulk_write_memory(struct target_s *target, uint32_t address, uint32_t
  * fallback code will read data from the target and calculate the CRC on the
  * host.
  */
-int arm11_checksum_memory(struct target_s *target, uint32_t address, uint32_t count, uint32_t* checksum)
+static int arm11_checksum_memory(struct target_s *target,
+               uint32_t address, uint32_t count, uint32_t* checksum)
 {
        return ERROR_FAIL;
 }
@@ -1310,7 +1551,8 @@ int arm11_checksum_memory(struct target_s *target, uint32_t address, uint32_t co
 /* target break-/watchpoint control
 * rw: 0 = write, 1 = read, 2 = access
 */
-int arm11_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
+static int arm11_add_breakpoint(struct target_s *target,
+               breakpoint_t *breakpoint)
 {
        FNC_INFO;
 
@@ -1341,7 +1583,8 @@ int arm11_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
        return ERROR_OK;
 }
 
-int arm11_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
+static int arm11_remove_breakpoint(struct target_s *target,
+               breakpoint_t *breakpoint)
 {
        FNC_INFO;
 
@@ -1352,14 +1595,16 @@ int arm11_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
        return ERROR_OK;
 }
 
-int arm11_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
+static int arm11_add_watchpoint(struct target_s *target,
+               watchpoint_t *watchpoint)
 {
        FNC_INFO_NOTIMPLEMENTED;
 
        return ERROR_OK;
 }
 
-int arm11_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
+static int arm11_remove_watchpoint(struct target_s *target,
+               watchpoint_t *watchpoint)
 {
        FNC_INFO_NOTIMPLEMENTED;
 
@@ -1368,9 +1613,11 @@ int arm11_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
 
 // HACKHACKHACK - FIXME mode/state
 /* target algorithm support */
-int arm11_run_algorithm(struct target_s *target, int num_mem_params, mem_param_t *mem_params,
-                       int num_reg_params, reg_param_t *reg_params, uint32_t entry_point, uint32_t exit_point,
-                       int timeout_ms, void *arch_info)
+static int arm11_run_algorithm(struct target_s *target,
+               int num_mem_params, mem_param_t *mem_params,
+               int num_reg_params, reg_param_t *reg_params,
+               uint32_t entry_point, uint32_t exit_point,
+               int timeout_ms, void *arch_info)
 {
                arm11_common_t *arm11 = target->arch_info;
 //     enum armv4_5_state core_state = arm11->core_state;
@@ -1393,10 +1640,10 @@ int arm11_run_algorithm(struct target_s *target, int num_mem_params, mem_param_t
 //             return ERROR_FAIL;
 
        // Save regs
-       for (size_t i = 0; i < 16; i++)
+       for (unsigned i = 0; i < 16; i++)
        {
                context[i] = buf_get_u32((uint8_t*)(&arm11->reg_values[i]),0,32);
-               LOG_DEBUG("Save %zi: 0x%" PRIx32 "",i,context[i]);
+               LOG_DEBUG("Save %u: 0x%" PRIx32 "", i, context[i]);
        }
 
        cpsr = buf_get_u32((uint8_t*)(arm11->reg_values + ARM11_RC_CPSR),0,32);
@@ -1532,7 +1779,7 @@ restore:
        return retval;
 }
 
-int arm11_target_create(struct target_s *target, Jim_Interp *interp)
+static int arm11_target_create(struct target_s *target, Jim_Interp *interp)
 {
        FNC_INFO;
 
@@ -1554,15 +1801,18 @@ int arm11_target_create(struct target_s *target, Jim_Interp *interp)
        return ERROR_OK;
 }
 
-int arm11_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
+static int arm11_init_target(struct command_context_s *cmd_ctx,
+               struct target_s *target)
 {
        /* Initialize anything we can set up without talking to the target */
        return arm11_build_reg_cache(target);
 }
 
 /* talk to the target and set things up */
-int arm11_examine(struct target_s *target)
+static int arm11_examine(struct target_s *target)
 {
+       int retval;
+
        FNC_INFO;
 
        arm11_common_t * arm11 = target->arch_info;
@@ -1571,7 +1821,7 @@ int arm11_examine(struct target_s *target)
 
        arm11_add_IR(arm11, ARM11_IDCODE, ARM11_TAP_DEFAULT);
 
-       scan_field_t            idcode_field;
+       struct scan_field               idcode_field;
 
        arm11_setup_field(arm11, 32, NULL, &arm11->device_id, &idcode_field);
 
@@ -1583,7 +1833,7 @@ int arm11_examine(struct target_s *target)
 
        arm11_add_IR(arm11, ARM11_INTEST, ARM11_TAP_DEFAULT);
 
-       scan_field_t            chain0_fields[2];
+       struct scan_field               chain0_fields[2];
 
        arm11_setup_field(arm11, 32, NULL,      &arm11->didr,           chain0_fields + 0);
        arm11_setup_field(arm11,  8, NULL,      &arm11->implementor,    chain0_fields + 1);
@@ -1630,22 +1880,18 @@ int arm11_examine(struct target_s *target)
         * as suggested by the spec.
         */
 
-       arm11_check_init(arm11, NULL);
+       retval = arm11_check_init(arm11, NULL);
+       if (retval != ERROR_OK)
+               return retval;
 
        target_set_examined(target);
 
        return ERROR_OK;
 }
 
-int arm11_quit(void)
-{
-       FNC_INFO_NOTIMPLEMENTED;
-
-       return ERROR_OK;
-}
 
 /** Load a register that is marked !valid in the register cache */
-int arm11_get_reg(reg_t *reg)
+static int arm11_get_reg(reg_t *reg)
 {
        FNC_INFO;
 
@@ -1668,7 +1914,7 @@ int arm11_get_reg(reg_t *reg)
 }
 
 /** Change a value in the register cache */
-int arm11_set_reg(reg_t *reg, uint8_t *buf)
+static int arm11_set_reg(reg_t *reg, uint8_t *buf)
 {
        FNC_INFO;
 
@@ -1683,7 +1929,7 @@ int arm11_set_reg(reg_t *reg, uint8_t *buf)
        return ERROR_OK;
 }
 
-int arm11_build_reg_cache(target_t *target)
+static int arm11_build_reg_cache(target_t *target)
 {
        arm11_common_t *arm11 = target->arch_info;
 
@@ -1745,7 +1991,7 @@ int arm11_build_reg_cache(target_t *target)
        return ERROR_OK;
 }
 
-int arm11_handle_bool(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, bool * var, char * name)
+static COMMAND_HELPER(arm11_handle_bool, bool *var, char *name)
 {
        if (argc == 0)
        {
@@ -1781,37 +2027,26 @@ int arm11_handle_bool(struct command_context_s *cmd_ctx, char *cmd, char **args,
 }
 
 #define BOOL_WRAPPER(name, print_name) \
-int arm11_handle_bool_##name(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) \
+COMMAND_HANDLER(arm11_handle_bool_##name) \
 { \
-       return arm11_handle_bool(cmd_ctx, cmd, args, argc, &arm11_config_##name, print_name); \
+       return CALL_COMMAND_HANDLER(arm11_handle_bool, \
+                       &arm11_config_##name, print_name); \
 }
 
-#define RC_TOP(name, descr, more)  \
-{ \
-       command_t * new_cmd = register_command(cmd_ctx, top_cmd, name, NULL, COMMAND_ANY, descr);  \
-       command_t * top_cmd = new_cmd; \
-       more \
-}
-
-#define RC_FINAL(name, descr, handler) \
-       register_command(cmd_ctx, top_cmd, name, handler, COMMAND_ANY, descr);
-
-#define RC_FINAL_BOOL(name, descr, var)  \
-       register_command(cmd_ctx, top_cmd, name, arm11_handle_bool_##var, COMMAND_ANY, descr);
-
 BOOL_WRAPPER(memwrite_burst,                   "memory write burst mode")
 BOOL_WRAPPER(memwrite_error_fatal,             "fatal error mode for memory writes")
-BOOL_WRAPPER(memrw_no_increment,               "\"no increment\" mode for memory transfers")
 BOOL_WRAPPER(step_irq_enable,                  "IRQs while stepping")
+BOOL_WRAPPER(hardware_step,                    "hardware single step")
 
-int arm11_handle_vcr(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+COMMAND_HANDLER(arm11_handle_vcr)
 {
-       if (argc == 1)
-       {
-               arm11_vcr = strtoul(args[0], NULL, 0);
-       }
-       else if (argc != 0)
-       {
+       switch (argc) {
+       case 0:
+               break;
+       case 1:
+               COMMAND_PARSE_NUMBER(u32, args[0], arm11_vcr);
+               break;
+       default:
                return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
@@ -1819,7 +2054,7 @@ int arm11_handle_vcr(struct command_context_s *cmd_ctx, char *cmd, char **args,
        return ERROR_OK;
 }
 
-const uint32_t arm11_coproc_instruction_limits[] =
+static const uint32_t arm11_coproc_instruction_limits[] =
 {
        15,                             /* coprocessor */
        7,                              /* opcode 1 */
@@ -1829,12 +2064,9 @@ const uint32_t arm11_coproc_instruction_limits[] =
        0xFFFFFFFF,             /* value */
 };
 
-const char arm11_mrc_syntax[] = "Syntax: mrc <jtag_target> <coprocessor> <opcode 1> <CRn> <CRm> <opcode 2>. All parameters are numbers only.";
-const char arm11_mcr_syntax[] = "Syntax: mcr <jtag_target> <coprocessor> <opcode 1> <CRn> <CRm> <opcode 2> <32bit value to write>. All parameters are numbers only.";
-
-arm11_common_t * arm11_find_target(const char * arg)
+static arm11_common_t * arm11_find_target(const char * arg)
 {
-       jtag_tap_t *    tap;
+       struct jtag_tap *       tap;
        target_t *              t;
 
        tap = jtag_tap_by_string(arg);
@@ -1855,128 +2087,202 @@ arm11_common_t * arm11_find_target(const char * arg)
        return 0;
 }
 
-int arm11_handle_mrc_mcr(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, bool read)
+static int arm11_mrc_inner(target_t *target, int cpnum,
+               uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm,
+               uint32_t *value, bool read)
 {
-       if (argc != (read ? 6 : 7))
+       int retval;
+       
+       if (target->state != TARGET_HALTED)
        {
-               LOG_ERROR("Invalid number of arguments. %s", read ? arm11_mrc_syntax : arm11_mcr_syntax);
-               return -1;
+               LOG_ERROR("Target not halted");
+               return ERROR_FAIL;
        }
+               
+       arm11_common_t * arm11 = target->arch_info;
 
-       arm11_common_t * arm11 = arm11_find_target(args[0]);
+       uint32_t instr = 0xEE000010     |
+               (cpnum <<  8) |
+               (op1 << 21) |
+               (CRn << 16) |
+               (CRm <<  0) |
+               (op2 <<  5);
 
-       if (!arm11)
-       {
-               LOG_ERROR("Parameter 1 is not a the JTAG chain position of an ARM11 device. %s",
-                       read ? arm11_mrc_syntax : arm11_mcr_syntax);
+       if (read)
+               instr |= 0x00100000;
 
-               return -1;
-       }
+       retval = arm11_run_instr_data_prepare(arm11);
+       if (retval != ERROR_OK)
+               return retval;
 
-       if (arm11->target->state != TARGET_HALTED)
+       if (read)
        {
-               LOG_WARNING("target was not halted");
-               return ERROR_TARGET_NOT_HALTED;
+               retval = arm11_run_instr_data_from_core_via_r0(arm11, instr, value);
+               if (retval != ERROR_OK)
+                       return retval;
+       }
+       else
+       {
+               retval = arm11_run_instr_data_to_core_via_r0(arm11, instr, *value);
+               if (retval != ERROR_OK)
+                       return retval;
        }
 
-       uint32_t        values[6];
+       return arm11_run_instr_data_finish(arm11);
+}
 
-       for (size_t i = 0; i < (read ? 5 : 6); i++)
-       {
-               values[i] = strtoul(args[i + 1], NULL, 0);
+static int arm11_mrc(target_t *target, int cpnum,
+               uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t *value)
+{
+       return arm11_mrc_inner(target, cpnum, op1, op2, CRn, CRm, value, true);
+}
 
-               if (values[i] > arm11_coproc_instruction_limits[i])
-               {
-                       LOG_ERROR("Parameter %ld out of bounds (%" PRId32 " max). %s",
-                                 (long)(i + 2),
-                                 arm11_coproc_instruction_limits[i],
-                               read ? arm11_mrc_syntax : arm11_mcr_syntax);
-                       return -1;
-               }
+static int arm11_mcr(target_t *target, int cpnum,
+               uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, uint32_t value)
+{
+       return arm11_mrc_inner(target, cpnum, op1, op2, CRn, CRm, &value, false);
+}
+
+static COMMAND_HELPER(arm11_handle_etm_read_write, bool read)
+{
+       if (argc != (read ? 2 : 3))
+       {
+               LOG_ERROR("Invalid number of arguments.");
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
-       uint32_t instr = 0xEE000010     |
-               (values[0] <<  8) |
-               (values[1] << 21) |
-               (values[2] << 16) |
-               (values[3] <<  0) |
-               (values[4] <<  5);
+       arm11_common_t * arm11 = arm11_find_target(args[0]);
 
-       if (read)
-               instr |= 0x00100000;
+       if (!arm11)
+       {
+               LOG_ERROR("Parameter 1 is not the target name of an ARM11 device.");
+               return ERROR_COMMAND_SYNTAX_ERROR;
+       }
 
-       arm11_run_instr_data_prepare(arm11);
+       uint32_t address;
+       COMMAND_PARSE_NUMBER(u32, args[1], address);
 
-       if (read)
+       if (!read)
        {
-               uint32_t result;
-               arm11_run_instr_data_from_core_via_r0(arm11, instr, &result);
+               uint32_t value;
+               COMMAND_PARSE_NUMBER(u32, args[2], value);
+
+               LOG_INFO("ETM write register 0x%02" PRIx32 " (%" PRId32 ") = 0x%08" PRIx32 " (%" PRId32 ")",
+                 address, address, value, value);
 
-               LOG_INFO("MRC p%d, %d, R0, c%d, c%d, %d = 0x%08" PRIx32 " (%" PRId32 ")",
-                        (int)(values[0]),
-                        (int)(values[1]),
-                        (int)(values[2]),
-                        (int)(values[3]),
-                        (int)(values[4]), result, result);
+               CHECK_RETVAL(arm11_write_etm(arm11, address, value));
        }
        else
        {
-               arm11_run_instr_data_to_core_via_r0(arm11, instr, values[5]);
+               uint32_t value;
 
-               LOG_INFO("MRC p%d, %d, R0 (#0x%08" PRIx32 "), c%d, c%d, %d",
-                        (int)(values[0]), (int)(values[1]),
-                        values[5],
-                        (int)(values[2]), (int)(values[3]), (int)(values[4]));
-       }
-
-       arm11_run_instr_data_finish(arm11);
+               CHECK_RETVAL(arm11_read_etm(arm11, address, &value));
 
+           LOG_INFO("ETM read register 0x%02" PRIx32 " (%" PRId32 ") = 0x%08" PRIx32 " (%" PRId32 ")",
+                 address, address, value, value);
+       }
 
        return ERROR_OK;
 }
 
-int arm11_handle_mrc(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+COMMAND_HANDLER(arm11_handle_etmr)
 {
-       return arm11_handle_mrc_mcr(cmd_ctx, cmd, args, argc, true);
+       return CALL_COMMAND_HANDLER(arm11_handle_etm_read_write, true);
 }
 
-int arm11_handle_mcr(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+COMMAND_HANDLER(arm11_handle_etmw)
 {
-       return arm11_handle_mrc_mcr(cmd_ctx, cmd, args, argc, false);
+       return CALL_COMMAND_HANDLER(arm11_handle_etm_read_write, false);
 }
 
-int arm11_register_commands(struct command_context_s *cmd_ctx)
-{
-       FNC_INFO;
+#define ARM11_HANDLER(x)       .x = arm11_##x
+
+target_type_t arm11_target = {
+               .name = "arm11",
 
-       command_t * top_cmd = NULL;
+               ARM11_HANDLER(poll),
+               ARM11_HANDLER(arch_state),
 
-       RC_TOP("arm11",                         "arm11 specific commands",
+               ARM11_HANDLER(target_request_data),
 
-       RC_TOP("memwrite",                              "Control memory write transfer mode",
+               ARM11_HANDLER(halt),
+               ARM11_HANDLER(resume),
+               ARM11_HANDLER(step),
 
-               RC_FINAL_BOOL("burst",                          "Enable/Disable non-standard but fast burst mode (default: enabled)",
-                                               memwrite_burst)
+               ARM11_HANDLER(assert_reset),
+               ARM11_HANDLER(deassert_reset),
+               ARM11_HANDLER(soft_reset_halt),
 
-               RC_FINAL_BOOL("error_fatal",                    "Terminate program if transfer error was found (default: enabled)",
-                                               memwrite_error_fatal)
-) /* memwrite */
+               ARM11_HANDLER(get_gdb_reg_list),
 
-       RC_FINAL_BOOL("no_increment",                   "Don't increment address on multi-read/-write (default: disabled)",
-                                               memrw_no_increment)
+               ARM11_HANDLER(read_memory),
+               ARM11_HANDLER(write_memory),
 
-       RC_FINAL_BOOL("step_irq_enable",                "Enable interrupts while stepping (default: disabled)",
-                                               step_irq_enable)
+               ARM11_HANDLER(bulk_write_memory),
 
-       RC_FINAL("vcr",                                 "Control (Interrupt) Vector Catch Register",
-                                               arm11_handle_vcr)
+               ARM11_HANDLER(checksum_memory),
 
-       RC_FINAL("mrc",                                 "Read Coprocessor register",
-                                               arm11_handle_mrc)
+               ARM11_HANDLER(add_breakpoint),
+               ARM11_HANDLER(remove_breakpoint),
+               ARM11_HANDLER(add_watchpoint),
+               ARM11_HANDLER(remove_watchpoint),
 
-       RC_FINAL("mcr",                                 "Write Coprocessor register",
-                                               arm11_handle_mcr)
-) /* arm11 */
+               ARM11_HANDLER(run_algorithm),
+
+               ARM11_HANDLER(register_commands),
+               ARM11_HANDLER(target_create),
+               ARM11_HANDLER(init_target),
+               ARM11_HANDLER(examine),
+
+               ARM11_HANDLER(mrc),
+               ARM11_HANDLER(mcr),
+       };
+
+
+int arm11_register_commands(struct command_context_s *cmd_ctx)
+{
+       FNC_INFO;
+
+       command_t *top_cmd, *mw_cmd;
+
+       top_cmd = register_command(cmd_ctx, NULL, "arm11",
+                       NULL, COMMAND_ANY, NULL);
+
+       register_command(cmd_ctx, top_cmd, "etmr",
+                       arm11_handle_etmr, COMMAND_ANY,
+                       "Read Embedded Trace Macrocell (ETM) register. etmr <jtag_target> <ETM register address>");
+
+       register_command(cmd_ctx, top_cmd, "etmw",
+                       arm11_handle_etmw, COMMAND_ANY,
+                       "Write Embedded Trace Macrocell (ETM) register. etmr <jtag_target> <ETM register address> <value>");
+
+       /* "hardware_step" is only here to check if the default
+        * simulate + breakpoint implementation is broken.
+        * TEMPORARY! NOT DOCUMENTED!
+        */
+       register_command(cmd_ctx, top_cmd, "hardware_step",
+                       arm11_handle_bool_hardware_step, COMMAND_ANY,
+                       "DEBUG ONLY - Hardware single stepping"
+                               " (default: disabled)");
+
+       mw_cmd = register_command(cmd_ctx, top_cmd, "memwrite",
+                       NULL, COMMAND_ANY, NULL);
+       register_command(cmd_ctx, mw_cmd, "burst",
+                       arm11_handle_bool_memwrite_burst, COMMAND_ANY,
+                       "Enable/Disable non-standard but fast burst mode"
+                               " (default: enabled)");
+       register_command(cmd_ctx, mw_cmd, "error_fatal",
+                       arm11_handle_bool_memwrite_error_fatal, COMMAND_ANY,
+                       "Terminate program if transfer error was found"
+                               " (default: enabled)");
+
+       register_command(cmd_ctx, top_cmd, "step_irq_enable",
+                       arm11_handle_bool_step_irq_enable, COMMAND_ANY,
+                       "Enable interrupts while stepping"
+                               " (default: disabled)");
+       register_command(cmd_ctx, top_cmd, "vcr",
+                       arm11_handle_vcr, COMMAND_ANY,
+                       "Control (Interrupt) Vector Catch Register");
 
        return ERROR_OK;
 }