warnings: fix alignment warnings
[fw/openocd] / src / target / xscale.c
index f52965a34fc64d75690f37fcd15bca3283897290..e0ce400b46101a5b480467693deccf0757a64db4 100644 (file)
@@ -36,6 +36,8 @@
 #include <helper/time_support.h>
 #include "register.h"
 #include "image.h"
+#include "arm_opcodes.h"
+#include "armv4_5.h"
 
 
 /*
@@ -156,10 +158,9 @@ static int xscale_verify_pointer(struct command_context *cmd_ctx,
        return ERROR_OK;
 }
 
-static int xscale_jtag_set_instr(struct jtag_tap *tap, uint32_t new_instr)
+static int xscale_jtag_set_instr(struct jtag_tap *tap, uint32_t new_instr, tap_state_t end_state)
 {
-       if (tap == NULL)
-               return ERROR_FAIL;
+       assert (tap != NULL);
 
        if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != new_instr)
        {
@@ -167,12 +168,11 @@ static int xscale_jtag_set_instr(struct jtag_tap *tap, uint32_t new_instr)
                uint8_t scratch[4];
 
                memset(&field, 0, sizeof field);
-               field.tap = tap;
                field.num_bits = tap->ir_length;
                field.out_value = scratch;
-               buf_set_u32(field.out_value, 0, field.num_bits, new_instr);
+               buf_set_u32(scratch, 0, field.num_bits, new_instr);
 
-               jtag_add_ir_scan(1, &field, jtag_get_end_state());
+               jtag_add_ir_scan(tap, &field, end_state);
        }
 
        return ERROR_OK;
@@ -190,32 +190,29 @@ static int xscale_read_dcsr(struct target *target)
        uint8_t field2_check_value = 0x0;
        uint8_t field2_check_mask = 0x1;
 
-       jtag_set_end_state(TAP_DRPAUSE);
        xscale_jtag_set_instr(target->tap,
-               XSCALE_SELDCSR << xscale->xscale_variant);
+               XSCALE_SELDCSR << xscale->xscale_variant,
+               TAP_DRPAUSE);
 
        buf_set_u32(&field0, 1, 1, xscale->hold_rst);
        buf_set_u32(&field0, 2, 1, xscale->external_debug_break);
 
        memset(&fields, 0, sizeof fields);
 
-       fields[0].tap = target->tap;
        fields[0].num_bits = 3;
        fields[0].out_value = &field0;
        uint8_t tmp;
        fields[0].in_value = &tmp;
 
-       fields[1].tap = target->tap;
        fields[1].num_bits = 32;
        fields[1].in_value = xscale->reg_cache->reg_list[XSCALE_DCSR].value;
 
-       fields[2].tap = target->tap;
        fields[2].num_bits = 1;
        fields[2].out_value = &field2;
        uint8_t tmp2;
        fields[2].in_value = &tmp2;
 
-       jtag_add_dr_scan(3, fields, jtag_get_end_state());
+       jtag_add_dr_scan(target->tap, 3, fields, TAP_DRPAUSE);
 
        jtag_check_value_mask(fields + 0, &field0_check_value, &field0_check_mask);
        jtag_check_value_mask(fields + 2, &field2_check_value, &field2_check_mask);
@@ -236,9 +233,7 @@ static int xscale_read_dcsr(struct target *target)
        fields[1].out_value = xscale->reg_cache->reg_list[XSCALE_DCSR].value;
        fields[1].in_value = NULL;
 
-       jtag_set_end_state(TAP_IDLE);
-
-       jtag_add_dr_scan(3, fields, jtag_get_end_state());
+       jtag_add_dr_scan(target->tap, 3, fields, TAP_DRPAUSE);
 
        /* DANGER!!! this must be here. It will make sure that the arguments
         * to jtag_set_check_value() does not go out of scope! */
@@ -249,7 +244,7 @@ static int xscale_read_dcsr(struct target *target)
 static void xscale_getbuf(jtag_callback_data_t arg)
 {
        uint8_t *in = (uint8_t *)arg;
-       *((uint32_t *)in) = buf_get_u32(in, 0, 32);
+       *((uint32_t *)arg) = buf_get_u32(in, 0, 32);
 }
 
 static int xscale_receive(struct target *target, uint32_t *buffer, int num_words)
@@ -277,23 +272,20 @@ static int xscale_receive(struct target *target, uint32_t *buffer, int num_words
 
        memset(&fields, 0, sizeof fields);
 
-       fields[0].tap = target->tap;
        fields[0].num_bits = 3;
        fields[0].check_value = &field0_check_value;
        fields[0].check_mask = &field0_check_mask;
 
-       fields[1].tap = target->tap;
        fields[1].num_bits = 32;
 
-       fields[2].tap = target->tap;
        fields[2].num_bits = 1;
        fields[2].check_value = &field2_check_value;
        fields[2].check_mask = &field2_check_mask;
 
-       jtag_set_end_state(TAP_IDLE);
        xscale_jtag_set_instr(target->tap,
-               XSCALE_DBGTX << xscale->xscale_variant);
-       jtag_add_runtest(1, jtag_get_end_state()); /* ensures that we're in the TAP_IDLE state as the above could be a no-op */
+               XSCALE_DBGTX << xscale->xscale_variant,
+               TAP_IDLE);
+       jtag_add_runtest(1, TAP_IDLE); /* ensures that we're in the TAP_IDLE state as the above could be a no-op */
 
        /* repeat until all words have been collected */
        int attempts = 0;
@@ -309,7 +301,7 @@ static int xscale_receive(struct target *target, uint32_t *buffer, int num_words
 
                        fields[1].in_value = (uint8_t *)(field1 + i);
 
-                       jtag_add_dr_scan_check(3, fields, jtag_set_end_state(TAP_IDLE));
+                       jtag_add_dr_scan_check(target->tap, 3, fields, TAP_IDLE);
 
                        jtag_add_callback(xscale_getbuf, (jtag_callback_data_t)(field1 + i));
 
@@ -372,10 +364,9 @@ static int xscale_read_tx(struct target *target, int consume)
        uint8_t field2_check_value = 0x0;
        uint8_t field2_check_mask = 0x1;
 
-       jtag_set_end_state(TAP_IDLE);
-
        xscale_jtag_set_instr(target->tap,
-               XSCALE_DBGTX << xscale->xscale_variant);
+               XSCALE_DBGTX << xscale->xscale_variant,
+               TAP_IDLE);
 
        path[0] = TAP_DRSELECT;
        path[1] = TAP_DRCAPTURE;
@@ -390,15 +381,12 @@ static int xscale_read_tx(struct target *target, int consume)
 
        memset(&fields, 0, sizeof fields);
 
-       fields[0].tap = target->tap;
        fields[0].num_bits = 3;
        fields[0].in_value = &field0_in;
 
-       fields[1].tap = target->tap;
        fields[1].num_bits = 32;
        fields[1].in_value = xscale->reg_cache->reg_list[XSCALE_TX].value;
 
-       fields[2].tap = target->tap;
        fields[2].num_bits = 1;
        uint8_t tmp;
        fields[2].in_value = &tmp;
@@ -419,7 +407,7 @@ static int xscale_read_tx(struct target *target, int consume)
                        jtag_add_pathmove(ARRAY_SIZE(noconsume_path), noconsume_path);
                }
 
-               jtag_add_dr_scan(3, fields, jtag_set_end_state(TAP_IDLE));
+               jtag_add_dr_scan(target->tap, 3, fields, TAP_IDLE);
 
                jtag_check_value_mask(fields + 0, &field0_check_value, &field0_check_mask);
                jtag_check_value_mask(fields + 2, &field2_check_value, &field2_check_mask);
@@ -471,23 +459,19 @@ static int xscale_write_rx(struct target *target)
        uint8_t field2_check_value = 0x0;
        uint8_t field2_check_mask = 0x1;
 
-       jtag_set_end_state(TAP_IDLE);
-
        xscale_jtag_set_instr(target->tap,
-               XSCALE_DBGRX << xscale->xscale_variant);
+               XSCALE_DBGRX << xscale->xscale_variant,
+               TAP_IDLE);
 
        memset(&fields, 0, sizeof fields);
 
-       fields[0].tap = target->tap;
        fields[0].num_bits = 3;
        fields[0].out_value = &field0_out;
        fields[0].in_value = &field0_in;
 
-       fields[1].tap = target->tap;
        fields[1].num_bits = 32;
        fields[1].out_value = xscale->reg_cache->reg_list[XSCALE_RX].value;
 
-       fields[2].tap = target->tap;
        fields[2].num_bits = 1;
        fields[2].out_value = &field2;
        uint8_t tmp;
@@ -500,7 +484,7 @@ static int xscale_write_rx(struct target *target)
        LOG_DEBUG("polling RX");
        for (;;)
        {
-               jtag_add_dr_scan(3, fields, jtag_set_end_state(TAP_IDLE));
+               jtag_add_dr_scan(target->tap, 3, fields, TAP_IDLE);
 
                jtag_check_value_mask(fields + 0, &field0_check_value, &field0_check_mask);
                jtag_check_value_mask(fields + 2, &field2_check_value, &field2_check_mask);
@@ -532,7 +516,7 @@ static int xscale_write_rx(struct target *target)
 
        /* set rx_valid */
        field2 = 0x1;
-       jtag_add_dr_scan(3, fields, jtag_set_end_state(TAP_IDLE));
+       jtag_add_dr_scan(target->tap, 3, fields, TAP_IDLE);
 
        if ((retval = jtag_execute_queue()) != ERROR_OK)
        {
@@ -552,10 +536,9 @@ static int xscale_send(struct target *target, uint8_t *buffer, int count, int si
        int retval;
        int done_count = 0;
 
-       jtag_set_end_state(TAP_IDLE);
-
        xscale_jtag_set_instr(target->tap,
-               XSCALE_DBGRX << xscale->xscale_variant);
+               XSCALE_DBGRX << xscale->xscale_variant,
+               TAP_IDLE);
 
        bits[0]=3;
        t[0]=0;
@@ -596,7 +579,7 @@ static int xscale_send(struct target *target, uint8_t *buffer, int count, int si
                                3,
                                bits,
                                t,
-                               jtag_set_end_state(TAP_IDLE));
+                               TAP_IDLE);
                buffer += size;
        }
 
@@ -635,32 +618,29 @@ static int xscale_write_dcsr(struct target *target, int hold_rst, int ext_dbg_br
        if (ext_dbg_brk != -1)
                xscale->external_debug_break = ext_dbg_brk;
 
-       jtag_set_end_state(TAP_IDLE);
        xscale_jtag_set_instr(target->tap,
-               XSCALE_SELDCSR << xscale->xscale_variant);
+               XSCALE_SELDCSR << xscale->xscale_variant,
+               TAP_IDLE);
 
        buf_set_u32(&field0, 1, 1, xscale->hold_rst);
        buf_set_u32(&field0, 2, 1, xscale->external_debug_break);
 
        memset(&fields, 0, sizeof fields);
 
-       fields[0].tap = target->tap;
        fields[0].num_bits = 3;
        fields[0].out_value = &field0;
        uint8_t tmp;
        fields[0].in_value = &tmp;
 
-       fields[1].tap = target->tap;
        fields[1].num_bits = 32;
        fields[1].out_value = xscale->reg_cache->reg_list[XSCALE_DCSR].value;
 
-       fields[2].tap = target->tap;
        fields[2].num_bits = 1;
        fields[2].out_value = &field2;
        uint8_t tmp2;
        fields[2].in_value = &tmp2;
 
-       jtag_add_dr_scan(3, fields, jtag_get_end_state());
+       jtag_add_dr_scan(target->tap, 3, fields, TAP_IDLE);
 
        jtag_check_value_mask(fields + 0, &field0_check_value, &field0_check_mask);
        jtag_check_value_mask(fields + 2, &field2_check_value, &field2_check_mask);
@@ -700,9 +680,9 @@ static int xscale_load_ic(struct target *target, uint32_t va, uint32_t buffer[8]
        LOG_DEBUG("loading miniIC at 0x%8.8" PRIx32 "", va);
 
        /* LDIC into IR */
-       jtag_set_end_state(TAP_IDLE);
        xscale_jtag_set_instr(target->tap,
-               XSCALE_LDIC << xscale->xscale_variant);
+               XSCALE_LDIC << xscale->xscale_variant,
+               TAP_IDLE);
 
        /* CMD is b011 to load a cacheline into the Mini ICache.
         * Loading into the main ICache is deprecated, and unused.
@@ -715,15 +695,13 @@ static int xscale_load_ic(struct target *target, uint32_t va, uint32_t buffer[8]
 
        memset(&fields, 0, sizeof fields);
 
-       fields[0].tap = target->tap;
        fields[0].num_bits = 6;
        fields[0].out_value = &cmd;
 
-       fields[1].tap = target->tap;
        fields[1].num_bits = 27;
        fields[1].out_value = packet;
 
-       jtag_add_dr_scan(2, fields, jtag_get_end_state());
+       jtag_add_dr_scan(target->tap, 2, fields, TAP_IDLE);
 
        /* rest of packet is a cacheline: 8 instructions, with parity */
        fields[0].num_bits = 32;
@@ -740,7 +718,7 @@ static int xscale_load_ic(struct target *target, uint32_t va, uint32_t buffer[8]
                memcpy(&value, packet, sizeof(uint32_t));
                cmd = parity(value);
 
-               jtag_add_dr_scan(2, fields, jtag_get_end_state());
+               jtag_add_dr_scan(target->tap, 2, fields, TAP_IDLE);
        }
 
        return jtag_execute_queue();
@@ -753,9 +731,9 @@ static int xscale_invalidate_ic_line(struct target *target, uint32_t va)
        uint8_t cmd;
        struct scan_field fields[2];
 
-       jtag_set_end_state(TAP_IDLE);
        xscale_jtag_set_instr(target->tap,
-               XSCALE_LDIC << xscale->xscale_variant);
+               XSCALE_LDIC << xscale->xscale_variant,
+               TAP_IDLE);
 
        /* CMD for invalidate IC line b000, bits [6:4] b000 */
        buf_set_u32(&cmd, 0, 6, 0x0);
@@ -765,15 +743,13 @@ static int xscale_invalidate_ic_line(struct target *target, uint32_t va)
 
        memset(&fields, 0, sizeof fields);
 
-       fields[0].tap = target->tap;
        fields[0].num_bits = 6;
        fields[0].out_value = &cmd;
 
-       fields[1].tap = target->tap;
        fields[1].num_bits = 27;
        fields[1].out_value = packet;
 
-       jtag_add_dr_scan(2, fields, jtag_get_end_state());
+       jtag_add_dr_scan(target->tap, 2, fields, TAP_IDLE);
 
        return ERROR_OK;
 }
@@ -857,21 +833,14 @@ static int xscale_arch_state(struct target *target)
                "", "\n(processor reset)", "\n(trace buffer full)"
        };
 
-       if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
+       if (armv4_5->common_magic != ARM_COMMON_MAGIC)
        {
                LOG_ERROR("BUG: called for a non-ARMv4/5 target");
                return ERROR_INVALID_ARGUMENTS;
        }
 
-       LOG_USER("target halted in %s state due to %s, current mode: %s\n"
-                       "cpsr: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "\n"
-                       "MMU: %s, D-Cache: %s, I-Cache: %s"
-                       "%s",
-                        armv4_5_state_strings[armv4_5->core_state],
-                        Jim_Nvp_value2name_simple(nvp_target_debug_reason, target->debug_reason)->name ,
-                        arm_mode_name(armv4_5->core_mode),
-                        buf_get_u32(armv4_5->cpsr->value, 0, 32),
-                        buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32),
+       arm_arch_state(target);
+       LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s%s",
                         state[xscale->armv4_5_mmu.mmu_enabled],
                         state[xscale->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled],
                         state[xscale->armv4_5_mmu.armv4_5_cache.i_cache_enabled],
@@ -926,7 +895,7 @@ static int xscale_debug_entry(struct target *target)
        struct arm *armv4_5 = &xscale->armv4_5_common;
        uint32_t pc;
        uint32_t buffer[10];
-       int i;
+       unsigned i;
        int retval;
        uint32_t moe;
 
@@ -946,9 +915,9 @@ static int xscale_debug_entry(struct target *target)
        LOG_DEBUG("r0: 0x%8.8" PRIx32 "", buffer[0]);
 
        /* move pc from buffer to register cache */
-       buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, buffer[1]);
-       armv4_5->core_cache->reg_list[15].dirty = 1;
-       armv4_5->core_cache->reg_list[15].valid = 1;
+       buf_set_u32(armv4_5->pc->value, 0, 32, buffer[1]);
+       armv4_5->pc->dirty = 1;
+       armv4_5->pc->valid = 1;
        LOG_DEBUG("pc: 0x%8.8" PRIx32 "", buffer[1]);
 
        /* move data from buffer to register cache */
@@ -995,12 +964,17 @@ static int xscale_debug_entry(struct target *target)
                r->valid = true;
        }
 
+       /* mark xscale regs invalid to ensure they are retrieved from the
+        * debug handler if requested  */
+       for (i = 0; i < xscale->reg_cache->num_regs; i++)
+          xscale->reg_cache->reg_list[i].valid = 0;
+
        /* examine debug reason */
        xscale_read_dcsr(target);
        moe = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 2, 3);
 
        /* stored PC (for calculating fixup) */
-       pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
+       pc = buf_get_u32(armv4_5->pc->value, 0, 32);
 
        switch (moe)
        {
@@ -1047,7 +1021,7 @@ static int xscale_debug_entry(struct target *target)
        }
 
        /* apply PC fixup */
-       buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, pc);
+       buf_set_u32(armv4_5->pc->value, 0, 32, pc);
 
        /* on the first debug entry, identify cache type */
        if (xscale->armv4_5_mmu.armv4_5_cache.ctype == -1)
@@ -1217,23 +1191,26 @@ static int xscale_resume(struct target *target, int current,
 
        /* current = 1: continue on current pc, otherwise continue at <address> */
        if (!current)
-               buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, address);
+               buf_set_u32(armv4_5->pc->value, 0, 32, address);
 
-       current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
+       current_pc = buf_get_u32(armv4_5->pc->value, 0, 32);
 
        /* if we're at the reset vector, we have to simulate the branch */
        if (current_pc == 0x0)
        {
                arm_simulate_step(target, NULL);
-               current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
+               current_pc = buf_get_u32(armv4_5->pc->value, 0, 32);
        }
 
        /* the front-end may request us not to handle breakpoints */
        if (handle_breakpoints)
        {
-               if ((breakpoint = breakpoint_find(target, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32))))
+               breakpoint = breakpoint_find(target,
+                               buf_get_u32(armv4_5->pc->value, 0, 32));
+               if (breakpoint != NULL)
                {
                        uint32_t next_pc;
+                       int saved_trace_buffer_enabled;
 
                        /* there's a breakpoint at the current PC, we have to step over it */
                        LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 "", breakpoint->address);
@@ -1253,15 +1230,8 @@ static int xscale_resume(struct target *target, int current,
                        /* restore banked registers */
                        retval = xscale_restore_banked(target);
 
-                       /* send resume request (command 0x30 or 0x31)
-                        * clean the trace buffer if it is to be enabled (0x62) */
-                       if (xscale->trace.buffer_enabled)
-                       {
-                               xscale_send_u32(target, 0x62);
-                               xscale_send_u32(target, 0x31);
-                       }
-                       else
-                               xscale_send_u32(target, 0x30);
+                       /* send resume request */
+                       xscale_send_u32(target, 0x30);
 
                        /* send CPSR */
                        xscale_send_u32(target,
@@ -1277,12 +1247,21 @@ static int xscale_resume(struct target *target, int current,
                        }
 
                        /* send PC */
-                       xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
-                       LOG_DEBUG("writing PC with value 0x%8.8" PRIx32 "", buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
+                       xscale_send_u32(target,
+                                       buf_get_u32(armv4_5->pc->value, 0, 32));
+                       LOG_DEBUG("writing PC with value 0x%8.8" PRIx32,
+                                       buf_get_u32(armv4_5->pc->value, 0, 32));
+
+                       /* disable trace data collection in xscale_debug_entry() */
+                       saved_trace_buffer_enabled = xscale->trace.buffer_enabled;
+                       xscale->trace.buffer_enabled = 0;
 
                        /* wait for and process debug entry */
                        xscale_debug_entry(target);
 
+                       /* re-enable trace buffer, if enabled previously */
+                       xscale->trace.buffer_enabled = saved_trace_buffer_enabled;
+
                        LOG_DEBUG("disable single-step");
                        xscale_disable_single_step(target);
 
@@ -1321,8 +1300,9 @@ static int xscale_resume(struct target *target, int current,
        }
 
        /* send PC */
-       xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
-       LOG_DEBUG("writing PC with value 0x%8.8" PRIx32 "", buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
+       xscale_send_u32(target, buf_get_u32(armv4_5->pc->value, 0, 32));
+       LOG_DEBUG("wrote PC with value 0x%8.8" PRIx32,
+                       buf_get_u32(armv4_5->pc->value, 0, 32));
 
        target->debug_reason = DBG_REASON_NOTHALTED;
 
@@ -1359,7 +1339,7 @@ static int xscale_step_inner(struct target *target, int current,
        if ((retval = arm_simulate_step(target, &next_pc)) != ERROR_OK)
        {
                uint32_t current_opcode, current_pc;
-               current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
+               current_pc = buf_get_u32(armv4_5->pc->value, 0, 32);
 
                target_read_u32(target, current_pc, &current_opcode);
                LOG_ERROR("BUG: couldn't calculate PC of next instruction, current opcode was 0x%8.8" PRIx32 "", current_opcode);
@@ -1404,9 +1384,12 @@ static int xscale_step_inner(struct target *target, int current,
        }
 
        /* send PC */
-       if ((retval = xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32))) != ERROR_OK)
+       retval = xscale_send_u32(target,
+                       buf_get_u32(armv4_5->pc->value, 0, 32));
+       if (retval != ERROR_OK)
                return retval;
-       LOG_DEBUG("writing PC with value 0x%8.8" PRIx32, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
+       LOG_DEBUG("wrote PC with value 0x%8.8" PRIx32,
+                       buf_get_u32(armv4_5->pc->value, 0, 32));
 
        target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
 
@@ -1429,8 +1412,8 @@ static int xscale_step_inner(struct target *target, int current,
 static int xscale_step(struct target *target, int current,
                uint32_t address, int handle_breakpoints)
 {
-       struct arm *armv4_5 = target_to_armv4_5(target);
-       struct breakpoint *breakpoint = target->breakpoints;
+       struct arm *armv4_5 = target_to_arm(target);
+       struct breakpoint *breakpoint = NULL;
 
        uint32_t current_pc;
        int retval;
@@ -1443,16 +1426,16 @@ static int xscale_step(struct target *target, int current,
 
        /* current = 1: continue on current pc, otherwise continue at <address> */
        if (!current)
-               buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, address);
+               buf_set_u32(armv4_5->pc->value, 0, 32, address);
 
-       current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
+       current_pc = buf_get_u32(armv4_5->pc->value, 0, 32);
 
        /* if we're at the reset vector, we have to simulate the step */
        if (current_pc == 0x0)
        {
                if ((retval = arm_simulate_step(target, NULL)) != ERROR_OK)
                        return retval;
-               current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
+               current_pc = buf_get_u32(armv4_5->pc->value, 0, 32);
 
                target->debug_reason = DBG_REASON_SINGLESTEP;
                target_call_event_callbacks(target, TARGET_EVENT_HALTED);
@@ -1462,11 +1445,13 @@ static int xscale_step(struct target *target, int current,
 
        /* the front-end may request us not to handle breakpoints */
        if (handle_breakpoints)
-               if ((breakpoint = breakpoint_find(target, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32))))
-               {
-                       if ((retval = xscale_unset_breakpoint(target, breakpoint)) != ERROR_OK)
-                               return retval;
-               }
+               breakpoint = breakpoint_find(target,
+                               buf_get_u32(armv4_5->pc->value, 0, 32));
+       if (breakpoint != NULL) {
+               retval = xscale_unset_breakpoint(target, breakpoint);
+               if (retval != ERROR_OK)
+                       return retval;
+       }
 
        retval = xscale_step_inner(target, current, address, handle_breakpoints);
 
@@ -1491,9 +1476,9 @@ static int xscale_assert_reset(struct target *target)
        /* select DCSR instruction (set endstate to R-T-I to ensure we don't
         * end up in T-L-R, which would reset JTAG
         */
-       jtag_set_end_state(TAP_IDLE);
        xscale_jtag_set_instr(target->tap,
-               XSCALE_SELDCSR << xscale->xscale_variant);
+               XSCALE_SELDCSR << xscale->xscale_variant,
+               TAP_IDLE);
 
        /* set Hold reset, Halt mode and Trap Reset */
        buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 30, 1, 0x1);
@@ -1501,7 +1486,7 @@ static int xscale_assert_reset(struct target *target)
        xscale_write_dcsr(target, 1, 0);
 
        /* select BYPASS, because having DCSR selected caused problems on the PXA27x */
-       xscale_jtag_set_instr(target->tap, 0x7f);
+       xscale_jtag_set_instr(target->tap, ~0, TAP_IDLE);
        jtag_execute_queue();
 
        /* assert reset */
@@ -1571,7 +1556,7 @@ static int xscale_deassert_reset(struct target *target)
                /* wait 300ms; 150 and 100ms were not enough */
                jtag_add_sleep(300*1000);
 
-               jtag_add_runtest(2030, jtag_set_end_state(TAP_IDLE));
+               jtag_add_runtest(2030, TAP_IDLE);
                jtag_execute_queue();
 
                /* set Hold reset, Halt mode and Trap Reset */
@@ -1628,7 +1613,7 @@ static int xscale_deassert_reset(struct target *target)
                if (retval != ERROR_OK)
                        return retval;
 
-               jtag_add_runtest(30, jtag_set_end_state(TAP_IDLE));
+               jtag_add_runtest(30, TAP_IDLE);
 
                jtag_add_sleep(100000);
 
@@ -1658,7 +1643,7 @@ static int xscale_deassert_reset(struct target *target)
 }
 
 static int xscale_read_core_reg(struct target *target, struct reg *r,
-               int num, enum armv4_5_mode mode)
+               int num, enum arm_mode mode)
 {
        /** \todo add debug handler support for core register reads */
        LOG_ERROR("not implemented");
@@ -1666,7 +1651,7 @@ static int xscale_read_core_reg(struct target *target, struct reg *r,
 }
 
 static int xscale_write_core_reg(struct target *target, struct reg *r,
-               int num, enum armv4_5_mode mode, uint32_t value)
+               int num, enum arm_mode mode, uint32_t value)
 {
        /** \todo add debug handler support for core register writes */
        LOG_ERROR("not implemented");
@@ -1675,7 +1660,7 @@ static int xscale_write_core_reg(struct target *target, struct reg *r,
 
 static int xscale_full_context(struct target *target)
 {
-       struct arm *armv4_5 = target_to_armv4_5(target);
+       struct arm *armv4_5 = target_to_arm(target);
 
        uint32_t *buffer;
 
@@ -1697,11 +1682,11 @@ static int xscale_full_context(struct target *target)
         */
        for (i = 1; i < 7; i++)
        {
-               enum armv4_5_mode mode = armv4_5_number_to_mode(i);
+               enum arm_mode mode = armv4_5_number_to_mode(i);
                bool valid = true;
                struct reg *r;
 
-               if (mode == ARMV4_5_MODE_USR)
+               if (mode == ARM_MODE_USR)
                        continue;
 
                /* check if there are invalid registers in the current mode
@@ -1724,7 +1709,7 @@ static int xscale_full_context(struct target *target)
                /* get banked registers:  r8 to r14; and SPSR
                 * except in USR/SYS mode
                 */
-               if (mode != ARMV4_5_MODE_SYS) {
+               if (mode != ARM_MODE_SYS) {
                        /* SPSR */
                        r = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
                                        mode, 16);
@@ -1757,7 +1742,7 @@ static int xscale_full_context(struct target *target)
 
 static int xscale_restore_banked(struct target *target)
 {
-       struct arm *armv4_5 = target_to_armv4_5(target);
+       struct arm *armv4_5 = target_to_arm(target);
 
        int i, j;
 
@@ -1774,10 +1759,10 @@ static int xscale_restore_banked(struct target *target)
         */
        for (i = 1; i < 7; i++)
        {
-               enum armv4_5_mode mode = armv4_5_number_to_mode(i);
+               enum arm_mode mode = armv4_5_number_to_mode(i);
                struct reg *r;
 
-               if (mode == ARMV4_5_MODE_USR)
+               if (mode == ARM_MODE_USR)
                        continue;
 
                /* check if there are dirty registers in this mode */
@@ -1789,7 +1774,7 @@ static int xscale_restore_banked(struct target *target)
                }
 
                /* if not USR/SYS, check if the SPSR needs to be written */
-               if (mode != ARMV4_5_MODE_SYS)
+               if (mode != ARM_MODE_SYS)
                {
                        if (ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
                                        mode, 16).dirty)
@@ -1817,7 +1802,7 @@ dirty:
                }
 
                /* send spsr if not in USR/SYS mode */
-               if (mode != ARMV4_5_MODE_SYS) {
+               if (mode != ARM_MODE_SYS) {
                        r = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
                                        mode, 16);
                        xscale_send_u32(target, buf_get_u32(r->value, 0, 32));
@@ -1910,7 +1895,13 @@ static int xscale_read_memory(struct target *target, uint32_t address,
 static int xscale_read_phys_memory(struct target *target, uint32_t address,
                uint32_t size, uint32_t count, uint8_t *buffer)
 {
-       /** \todo: provide a non-stub implementtion of this routine. */
+       struct xscale_common *xscale = target_to_xscale(target);
+
+       /* with MMU inactive, there are only physical addresses */
+       if (!xscale->armv4_5_mmu.mmu_enabled)
+               return xscale_read_memory(target, address, size, count, buffer);
+
+       /** \todo: provide a non-stub implementation of this routine. */
        LOG_ERROR("%s: %s is not implemented.  Disable MMU?",
                        target_name(target), __func__);
        return ERROR_FAIL;
@@ -1988,6 +1979,7 @@ static int xscale_write_memory(struct target *target, uint32_t address,
                if ((retval = xscale_send_u32(target, 0x60)) != ERROR_OK)
                        return retval;
 
+               LOG_ERROR("data abort writing memory");
                return ERROR_TARGET_DATA_ABORT;
        }
 
@@ -1997,7 +1989,13 @@ static int xscale_write_memory(struct target *target, uint32_t address,
 static int xscale_write_phys_memory(struct target *target, uint32_t address,
                uint32_t size, uint32_t count, uint8_t *buffer)
 {
-       /** \todo: provide a non-stub implementtion of this routine. */
+       struct xscale_common *xscale = target_to_xscale(target);
+
+       /* with MMU inactive, there are only physical addresses */
+       if (!xscale->armv4_5_mmu.mmu_enabled)
+               return xscale_read_memory(target, address, size, count, buffer);
+
+       /** \todo: provide a non-stub implementation of this routine. */
        LOG_ERROR("%s: %s is not implemented.  Disable MMU?",
                        target_name(target), __func__);
        return ERROR_FAIL;
@@ -2009,25 +2007,33 @@ static int xscale_bulk_write_memory(struct target *target, uint32_t address,
        return xscale_write_memory(target, address, 4, count, buffer);
 }
 
-static uint32_t xscale_get_ttb(struct target *target)
+static int xscale_get_ttb(struct target *target, uint32_t *result)
 {
        struct xscale_common *xscale = target_to_xscale(target);
        uint32_t ttb;
+       int retval;
 
-       xscale_get_reg(&xscale->reg_cache->reg_list[XSCALE_TTB]);
+       retval = xscale_get_reg(&xscale->reg_cache->reg_list[XSCALE_TTB]);
+       if (retval != ERROR_OK)
+               return retval;
        ttb = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_TTB].value, 0, 32);
 
-       return ttb;
+       *result = ttb;
+
+       return ERROR_OK;
 }
 
-static void xscale_disable_mmu_caches(struct target *target, int mmu,
+static int xscale_disable_mmu_caches(struct target *target, int mmu,
                int d_u_cache, int i_cache)
 {
        struct xscale_common *xscale = target_to_xscale(target);
        uint32_t cp15_control;
+       int retval;
 
        /* read cp15 control register */
-       xscale_get_reg(&xscale->reg_cache->reg_list[XSCALE_CTRL]);
+       retval = xscale_get_reg(&xscale->reg_cache->reg_list[XSCALE_CTRL]);
+       if (retval !=ERROR_OK)
+               return retval;
        cp15_control = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_CTRL].value, 0, 32);
 
        if (mmu)
@@ -2036,11 +2042,17 @@ static void xscale_disable_mmu_caches(struct target *target, int mmu,
        if (d_u_cache)
        {
                /* clean DCache */
-               xscale_send_u32(target, 0x50);
-               xscale_send_u32(target, xscale->cache_clean_address);
+               retval = xscale_send_u32(target, 0x50);
+               if (retval !=ERROR_OK)
+                       return retval;
+               retval = xscale_send_u32(target, xscale->cache_clean_address);
+               if (retval !=ERROR_OK)
+                       return retval;
 
                /* invalidate DCache */
-               xscale_send_u32(target, 0x51);
+               retval = xscale_send_u32(target, 0x51);
+               if (retval !=ERROR_OK)
+                       return retval;
 
                cp15_control &= ~0x4U;
        }
@@ -2048,25 +2060,33 @@ static void xscale_disable_mmu_caches(struct target *target, int mmu,
        if (i_cache)
        {
                /* invalidate ICache */
-               xscale_send_u32(target, 0x52);
+               retval = xscale_send_u32(target, 0x52);
+               if (retval !=ERROR_OK)
+                       return retval;
                cp15_control &= ~0x1000U;
        }
 
        /* write new cp15 control register */
-       xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_CTRL], cp15_control);
+       retval = xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_CTRL], cp15_control);
+       if (retval !=ERROR_OK)
+               return retval;
 
        /* execute cpwait to ensure outstanding operations complete */
-       xscale_send_u32(target, 0x53);
+       retval = xscale_send_u32(target, 0x53);
+       return retval;
 }
 
-static void xscale_enable_mmu_caches(struct target *target, int mmu,
+static int xscale_enable_mmu_caches(struct target *target, int mmu,
                int d_u_cache, int i_cache)
 {
        struct xscale_common *xscale = target_to_xscale(target);
        uint32_t cp15_control;
+       int retval;
 
        /* read cp15 control register */
-       xscale_get_reg(&xscale->reg_cache->reg_list[XSCALE_CTRL]);
+       retval = xscale_get_reg(&xscale->reg_cache->reg_list[XSCALE_CTRL]);
+       if (retval !=ERROR_OK)
+               return retval;
        cp15_control = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_CTRL].value, 0, 32);
 
        if (mmu)
@@ -2079,10 +2099,13 @@ static void xscale_enable_mmu_caches(struct target *target, int mmu,
                cp15_control |= 0x1000U;
 
        /* write new cp15 control register */
-       xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_CTRL], cp15_control);
+       retval = xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_CTRL], cp15_control);
+       if (retval !=ERROR_OK)
+               return retval;
 
        /* execute cpwait to ensure outstanding operations complete */
-       xscale_send_u32(target, 0x53);
+       retval = xscale_send_u32(target, 0x53);
+       return retval;
 }
 
 static int xscale_set_breakpoint(struct target *target,
@@ -2119,9 +2142,9 @@ static int xscale_set_breakpoint(struct target *target,
                        breakpoint->set = 2;    /* breakpoint set on second breakpoint register */
                }
                else
-               {
+               {       /* bug: availability previously verified in xscale_add_breakpoint() */
                        LOG_ERROR("BUG: no hardware comparator available");
-                       return ERROR_OK;
+                       return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
                }
        }
        else if (breakpoint->type == BKPT_SOFT)
@@ -2133,7 +2156,7 @@ static int xscale_set_breakpoint(struct target *target,
                        {
                                return retval;
                        }
-                       /* write the original instruction in target endianness (arm7_9->arm_bkpt is host endian) */
+                       /* write the bkpt instruction in target endianness (arm7_9->arm_bkpt is host endian) */
                        if ((retval = target_write_u32(target, breakpoint->address, xscale->arm_bkpt)) != ERROR_OK)
                        {
                                return retval;
@@ -2146,13 +2169,18 @@ static int xscale_set_breakpoint(struct target *target,
                        {
                                return retval;
                        }
-                       /* write the original instruction in target endianness (arm7_9->arm_bkpt is host endian) */
-                       if ((retval = target_write_u32(target, breakpoint->address, xscale->thumb_bkpt)) != ERROR_OK)
+                       /* write the bkpt instruction in target endianness (arm7_9->arm_bkpt is host endian) */
+                       if ((retval = target_write_u16(target, breakpoint->address, xscale->thumb_bkpt)) != ERROR_OK)
                        {
                                return retval;
                        }
                }
                breakpoint->set = 1;
+
+               xscale_send_u32(target, 0x50);   /* clean dcache */
+               xscale_send_u32(target, xscale->cache_clean_address);
+               xscale_send_u32(target, 0x51);   /* invalidate dcache */
+               xscale_send_u32(target, 0x52);   /* invalidate icache and flush fetch buffers */
        }
 
        return ERROR_OK;
@@ -2165,13 +2193,13 @@ static int xscale_add_breakpoint(struct target *target,
 
        if ((breakpoint->type == BKPT_HARD) && (xscale->ibcr_available < 1))
        {
-               LOG_INFO("no breakpoint unit available for hardware breakpoint");
+               LOG_ERROR("no breakpoint unit available for hardware breakpoint");
                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
        }
 
        if ((breakpoint->length != 2) && (breakpoint->length != 4))
        {
-               LOG_INFO("only breakpoints of two (Thumb) or four (ARM) bytes length supported");
+               LOG_ERROR("only breakpoints of two (Thumb) or four (ARM) bytes length supported");
                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
        }
 
@@ -2180,7 +2208,7 @@ static int xscale_add_breakpoint(struct target *target,
                xscale->ibcr_available--;
        }
 
-       return ERROR_OK;
+       return xscale_set_breakpoint(target, breakpoint);
 }
 
 static int xscale_unset_breakpoint(struct target *target,
@@ -2233,6 +2261,11 @@ static int xscale_unset_breakpoint(struct target *target,
                        }
                }
                breakpoint->set = 0;
+
+               xscale_send_u32(target, 0x50);   /* clean dcache */
+               xscale_send_u32(target, xscale->cache_clean_address);
+               xscale_send_u32(target, 0x51);   /* invalidate dcache */
+               xscale_send_u32(target, 0x52);   /* invalidate icache and flush fetch buffers */
        }
 
        return ERROR_OK;
@@ -2244,7 +2277,7 @@ static int xscale_remove_breakpoint(struct target *target, struct breakpoint *br
 
        if (target->state != TARGET_HALTED)
        {
-               LOG_WARNING("target not halted");
+               LOG_ERROR("target not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
 
@@ -2263,18 +2296,16 @@ static int xscale_set_watchpoint(struct target *target,
                struct watchpoint *watchpoint)
 {
        struct xscale_common *xscale = target_to_xscale(target);
-       uint8_t enable = 0;
+       uint32_t enable = 0;
        struct reg *dbcon = &xscale->reg_cache->reg_list[XSCALE_DBCON];
        uint32_t dbcon_value = buf_get_u32(dbcon->value, 0, 32);
 
        if (target->state != TARGET_HALTED)
        {
-               LOG_WARNING("target not halted");
+               LOG_ERROR("target not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
 
-       xscale_get_reg(dbcon);
-
        switch (watchpoint->rw)
        {
                case WPT_READ:
@@ -2290,6 +2321,24 @@ static int xscale_set_watchpoint(struct target *target,
                        LOG_ERROR("BUG: watchpoint->rw neither read, write nor access");
        }
 
+       /* For watchpoint across more than one word, both DBR registers must
+          be enlisted, with the second used as a mask. */
+       if (watchpoint->length > 4)
+       {
+          if (xscale->dbr0_used || xscale->dbr1_used) 
+          {
+                 LOG_ERROR("BUG: sufficient hardware comparators unavailable");
+                 return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+          }
+
+          /* Write mask value to DBR1, based on the length argument.
+               * Address bits ignored by the comparator are those set in mask. */
+          xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_DBR1],
+                                                 watchpoint->length - 1);
+          xscale->dbr1_used = 1;
+          enable |= 0x100;                     /* DBCON[M] */
+       }
+
        if (!xscale->dbr0_used)
        {
                xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_DBR0], watchpoint->address);
@@ -2309,7 +2358,7 @@ static int xscale_set_watchpoint(struct target *target,
        else
        {
                LOG_ERROR("BUG: no hardware comparator available");
-               return ERROR_OK;
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
        }
 
        return ERROR_OK;
@@ -2322,16 +2371,44 @@ static int xscale_add_watchpoint(struct target *target,
 
        if (xscale->dbr_available < 1)
        {
-               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+          LOG_ERROR("no more watchpoint registers available");
+          return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
        }
 
-       if ((watchpoint->length != 1) && (watchpoint->length != 2) && (watchpoint->length != 4))
+       if (watchpoint->value)
+          LOG_WARNING("xscale does not support value, mask arguments; ignoring");
+
+       /* check that length is a power of two */
+       for (uint32_t len = watchpoint->length; len != 1; len /= 2)
        {
-               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+          if (len % 2)
+          {
+                 LOG_ERROR("xscale requires that watchpoint length is a power of two");
+                 return ERROR_COMMAND_ARGUMENT_INVALID;
+          }
        }
 
-       xscale->dbr_available--;
+       if (watchpoint->length == 4) /* single word watchpoint */
+       {
+          xscale->dbr_available--; /* one DBR reg used */
+          return ERROR_OK;
+       }
 
+       /* watchpoints across multiple words require both DBR registers */
+       if (xscale->dbr_available < 2)
+       {
+          LOG_ERROR("insufficient watchpoint registers available");
+          return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+       }
+       
+       if (watchpoint->length > watchpoint->address)
+       {
+          LOG_ERROR("xscale does not support watchpoints with length "
+                                "greater than address");
+          return ERROR_COMMAND_ARGUMENT_INVALID;
+       }
+          
+       xscale->dbr_available = 0;
        return ERROR_OK;
 }
 
@@ -2356,7 +2433,14 @@ static int xscale_unset_watchpoint(struct target *target,
 
        if (watchpoint->set == 1)
        {
-               dbcon_value &= ~0x3;
+          if (watchpoint->length > 4)
+          {
+                 dbcon_value &= ~0x103; /* clear DBCON[M] as well */
+                 xscale->dbr1_used = 0; /* DBR1 was used for mask */
+          }
+          else
+                 dbcon_value &= ~0x3;
+
                xscale_set_reg_u32(dbcon, dbcon_value);
                xscale->dbr0_used = 0;
        }
@@ -2377,7 +2461,7 @@ static int xscale_remove_watchpoint(struct target *target, struct watchpoint *wa
 
        if (target->state != TARGET_HALTED)
        {
-               LOG_WARNING("target not halted");
+               LOG_ERROR("target not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
 
@@ -2386,6 +2470,9 @@ static int xscale_remove_watchpoint(struct target *target, struct watchpoint *wa
                xscale_unset_watchpoint(target, watchpoint);
        }
 
+       if (watchpoint->length > 4)
+          xscale->dbr_available++;     /* both DBR regs now available */
+       
        xscale->dbr_available++;
 
        return ERROR_OK;
@@ -2512,6 +2599,7 @@ static int xscale_read_trace(struct target *target)
        uint32_t trace_buffer[258];
        int is_address[256];
        int i, j;
+       unsigned int num_checkpoints = 0;
 
        if (target->state != TARGET_HALTED)
        {
@@ -2528,23 +2616,27 @@ static int xscale_read_trace(struct target *target)
        /* parse buffer backwards to identify address entries */
        for (i = 255; i >= 0; i--)
        {
+               /* also count number of checkpointed entries */
+               if ((trace_buffer[i] & 0xe0) == 0xc0)
+                       num_checkpoints++;
+
                is_address[i] = 0;
                if (((trace_buffer[i] & 0xf0) == 0x90) ||
                        ((trace_buffer[i] & 0xf0) == 0xd0))
                {
-                       if (i >= 3)
+                       if (i > 0)
                                is_address[--i] = 1;
-                       if (i >= 2)
+                       if (i > 0)
                                is_address[--i] = 1;
-                       if (i >= 1)
+                       if (i > 0)
                                is_address[--i] = 1;
-                       if (i >= 0)
+                       if (i > 0)
                                is_address[--i] = 1;
                }
        }
 
 
-       /* search first non-zero entry */
+       /* search first non-zero entry that is not part of an address */
        for (j = 0; (j < 256) && (trace_buffer[j] == 0) && (!is_address[j]); j++)
                ;
 
@@ -2554,6 +2646,22 @@ static int xscale_read_trace(struct target *target)
                return ERROR_XSCALE_NO_TRACE_DATA;
        }
 
+       /* account for possible partial address at buffer start (wrap mode only) */
+       if (is_address[0])
+       {       /* first entry is address; complete set of 4? */
+               i = 1;
+               while (i < 4)
+                       if (!is_address[i++])
+                               break;
+               if (i < 4)
+                       j += i;   /* partial address; can't use it */
+       }
+
+       /* if first valid entry is indirect branch, can't use that either (no address) */
+       if (((trace_buffer[j] & 0xf0) == 0x90) || ((trace_buffer[j] & 0xf0) == 0xd0))
+               j++;
+
+       /* walk linked list to terminating entry */
        for (trace_data_p = &xscale->trace.data; *trace_data_p; trace_data_p = &(*trace_data_p)->next)
                ;
 
@@ -2561,9 +2669,11 @@ static int xscale_read_trace(struct target *target)
        (*trace_data_p)->next = NULL;
        (*trace_data_p)->chkpt0 = trace_buffer[256];
        (*trace_data_p)->chkpt1 = trace_buffer[257];
-       (*trace_data_p)->last_instruction = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
+       (*trace_data_p)->last_instruction =
+                       buf_get_u32(armv4_5->pc->value, 0, 32);
        (*trace_data_p)->entries = malloc(sizeof(struct xscale_trace_entry) * (256 - j));
        (*trace_data_p)->depth = 256 - j;
+       (*trace_data_p)->num_checkpoints = num_checkpoints;
 
        for (i = j; i < 256; i++)
        {
@@ -2577,10 +2687,10 @@ static int xscale_read_trace(struct target *target)
        return ERROR_OK;
 }
 
-static int xscale_read_instruction(struct target *target,
-               struct arm_instruction *instruction)
+static int xscale_read_instruction(struct target *target, uint32_t pc,
+                                                                  struct arm_instruction *instruction)
 {
-       struct xscale_common *xscale = target_to_xscale(target);
+       struct xscale_common *const xscale = target_to_xscale(target);
        int i;
        int section = -1;
        size_t size_read;
@@ -2593,8 +2703,8 @@ static int xscale_read_instruction(struct target *target,
        /* search for the section the current instruction belongs to */
        for (i = 0; i < xscale->trace.image->num_sections; i++)
        {
-               if ((xscale->trace.image->sections[i].base_address <= xscale->trace.current_pc) &&
-                       (xscale->trace.image->sections[i].base_address + xscale->trace.image->sections[i].size > xscale->trace.current_pc))
+               if ((xscale->trace.image->sections[i].base_address <= pc) &&
+                       (xscale->trace.image->sections[i].base_address + xscale->trace.image->sections[i].size > pc))
                {
                        section = i;
                        break;
@@ -2611,27 +2721,27 @@ static int xscale_read_instruction(struct target *target,
        {
                uint8_t buf[4];
                if ((retval = image_read_section(xscale->trace.image, section,
-                       xscale->trace.current_pc - xscale->trace.image->sections[section].base_address,
+                       pc - xscale->trace.image->sections[section].base_address,
                        4, buf, &size_read)) != ERROR_OK)
                {
                        LOG_ERROR("error while reading instruction: %i", retval);
                        return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
                }
                opcode = target_buffer_get_u32(target, buf);
-               arm_evaluate_opcode(opcode, xscale->trace.current_pc, instruction);
+               arm_evaluate_opcode(opcode, pc, instruction);
        }
        else if (xscale->trace.core_state == ARM_STATE_THUMB)
        {
                uint8_t buf[2];
                if ((retval = image_read_section(xscale->trace.image, section,
-                       xscale->trace.current_pc - xscale->trace.image->sections[section].base_address,
+                       pc - xscale->trace.image->sections[section].base_address,
                        2, buf, &size_read)) != ERROR_OK)
                {
                        LOG_ERROR("error while reading instruction: %i", retval);
                        return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
                }
                opcode = target_buffer_get_u16(target, buf);
-               thumb_evaluate_opcode(opcode, xscale->trace.current_pc, instruction);
+               thumb_evaluate_opcode(opcode, pc, instruction);
        }
        else
        {
@@ -2642,207 +2752,234 @@ static int xscale_read_instruction(struct target *target,
        return ERROR_OK;
 }
 
-static int xscale_branch_address(struct xscale_trace_data *trace_data,
-               int i, uint32_t *target)
+/* Extract address encoded into trace data. 
+ * Write result to address referenced by argument 'target', or 0 if incomplete.  */
+static inline void xscale_branch_address(struct xscale_trace_data *trace_data,
+                                        int i, uint32_t *target)
 {
        /* if there are less than four entries prior to the indirect branch message
         * we can't extract the address */
        if (i < 4)
-       {
-               return -1;
-       }
-
-       *target = (trace_data->entries[i-1].data) | (trace_data->entries[i-2].data << 8) |
-                               (trace_data->entries[i-3].data << 16) | (trace_data->entries[i-4].data << 24);
+               *target = 0;
+       else
+               *target = (trace_data->entries[i-1].data) | (trace_data->entries[i-2].data << 8) |
+                       (trace_data->entries[i-3].data << 16) | (trace_data->entries[i-4].data << 24);
+}
 
-       return 0;
+static inline void xscale_display_instruction(struct target *target, uint32_t pc,
+                                                                                         struct arm_instruction *instruction,
+                                                                                         struct command_context *cmd_ctx)
+{
+   int retval = xscale_read_instruction(target, pc, instruction);
+   if (retval == ERROR_OK)
+         command_print(cmd_ctx, "%s", instruction->text);
+   else
+         command_print(cmd_ctx, "0x%8.8" PRIx32 "\t<not found in image>", pc);
 }
 
 static int xscale_analyze_trace(struct target *target, struct command_context *cmd_ctx)
 {
-       struct xscale_common *xscale = target_to_xscale(target);
-       int next_pc_ok = 0;
-       uint32_t next_pc = 0x0;
-       struct xscale_trace_data *trace_data = xscale->trace.data;
-       int retval;
-
-       while (trace_data)
-       {
-               int i, chkpt;
-               int rollover;
-               int branch;
-               int exception;
-               xscale->trace.core_state = ARM_STATE_ARM;
-
-               chkpt = 0;
-               rollover = 0;
+   struct xscale_common *xscale = target_to_xscale(target);
+   struct xscale_trace_data *trace_data = xscale->trace.data;
+   int i, retval;
+   uint32_t breakpoint_pc;
+   struct arm_instruction instruction;
+   uint32_t current_pc = 0;  /* initialized when address determined */
+       
+   if (!xscale->trace.image)
+         LOG_WARNING("No trace image loaded; use 'xscale trace_image'");
+
+   /* loop for each trace buffer that was loaded from target */
+   while (trace_data)
+   {
+         int chkpt = 0;  /* incremented as checkpointed entries found */
+         int j;
+
+         /* FIXME: set this to correct mode when trace buffer is first enabled */
+         xscale->trace.core_state = ARM_STATE_ARM;
+
+         /* loop for each entry in this trace buffer */
+         for (i = 0; i < trace_data->depth; i++)
+         {
+                int exception = 0;
+                uint32_t chkpt_reg = 0x0;
+                uint32_t branch_target = 0;
+                int count;
+
+                /* trace entry type is upper nybble of 'message byte' */
+                int trace_msg_type = (trace_data->entries[i].data & 0xf0) >> 4;
+
+                /* Target addresses of indirect branches are written into buffer
+                 * before the message byte representing the branch. Skip past it */
+                if (trace_data->entries[i].type == XSCALE_TRACE_ADDRESS)
+                       continue;
 
-               for (i = 0; i < trace_data->depth; i++)
-               {
-                       next_pc_ok = 0;
-                       branch = 0;
-                       exception = 0;
+                switch (trace_msg_type)
+                {
+                       case 0:         /* Exceptions */
+                       case 1:
+                       case 2:
+                       case 3:
+                       case 4:
+                       case 5:
+                       case 6:
+                       case 7:
+                          exception = (trace_data->entries[i].data & 0x70) >> 4;
+
+                          /* FIXME: vector table may be at ffff0000 */
+                          branch_target = (trace_data->entries[i].data & 0xf0) >> 2;
+                          break;
+
+                       case 8:         /* Direct Branch */
+                          break;
+
+                       case 9:         /* Indirect Branch */
+                          xscale_branch_address(trace_data, i, &branch_target);
+                          break;
+
+                       case 13:           /* Checkpointed Indirect Branch */
+                          xscale_branch_address(trace_data, i, &branch_target);
+                          if ((trace_data->num_checkpoints == 2) && (chkpt == 0))
+                                 chkpt_reg = trace_data->chkpt1; /* 2 chkpts, this is oldest */
+                          else
+                                 chkpt_reg = trace_data->chkpt0; /* 1 chkpt, or 2 and newest */
+
+                          chkpt++;
+                          break;
+
+                       case 12:           /* Checkpointed Direct Branch */
+                          if ((trace_data->num_checkpoints == 2) && (chkpt == 0))
+                                 chkpt_reg = trace_data->chkpt1; /* 2 chkpts, this is oldest */
+                          else
+                                 chkpt_reg = trace_data->chkpt0; /* 1 chkpt, or 2 and newest */
+
+                          /* if no current_pc, checkpoint will be starting point */
+                          if (current_pc == 0)
+                                 branch_target = chkpt_reg;
+
+                          chkpt++;
+                          break;
+
+                       case 15:        /* Roll-over */
+                          break;
+
+                       default:        /* Reserved */
+                          LOG_WARNING("trace is suspect: invalid trace message byte");
+                          continue;
+
+                }
+
+                /* If we don't have the current_pc yet, but we did get the branch target
+                 * (either from the trace buffer on indirect branch, or from a checkpoint reg),
+                 * then we can start displaying instructions at the next iteration, with
+                 * branch_target as the starting point.
+                 */
+                if (current_pc == 0)
+                {
+                       current_pc = branch_target; /* remains 0 unless branch_target obtained */
+                       continue;
+                }
+
+                /* We have current_pc.  Read and display the instructions from the image.
+                 * First, display count instructions (lower nybble of message byte). */
+                count = trace_data->entries[i].data & 0x0f;
+                for (j = 0; j < count; j++)
+                {
+                       xscale_display_instruction(target, current_pc, &instruction, cmd_ctx);
+                       current_pc += xscale->trace.core_state == ARM_STATE_ARM ? 4 : 2;
+                }
+
+                /* An additional instruction is implicitly added to count for
+                 * rollover and some exceptions: undef, swi, prefetch abort. */
+                if ((trace_msg_type == 15) || (exception > 0 && exception < 4))
+                {
+                       xscale_display_instruction(target, current_pc, &instruction, cmd_ctx);
+                       current_pc += xscale->trace.core_state == ARM_STATE_ARM ? 4 : 2;
+                }
+
+                if (trace_msg_type == 15) /* rollover */
+                       continue;
 
-                       if (trace_data->entries[i].type == XSCALE_TRACE_ADDRESS)
-                               continue;
+                if (exception)
+                {
+                       command_print(cmd_ctx, "--- exception %i ---", exception);
+                       continue;
+                }
+                       
+                /* not exception or rollover; next instruction is a branch and is
+                 * not included in the count */
+                xscale_display_instruction(target, current_pc, &instruction, cmd_ctx);
+
+                /* for direct branches, extract branch destination from instruction */
+                if ((trace_msg_type == 8) || (trace_msg_type == 12))
+                {
+                       retval = xscale_read_instruction(target, current_pc, &instruction);
+                       if (retval == ERROR_OK)
+                          current_pc = instruction.info.b_bl_bx_blx.target_address;
+                       else
+                          current_pc = 0;      /* branch destination unknown */
 
-                       switch ((trace_data->entries[i].data & 0xf0) >> 4)
+                       /* direct branch w/ checkpoint; can also get from checkpoint reg */
+                       if (trace_msg_type == 12)
                        {
-                               case 0:         /* Exceptions */
-                               case 1:
-                               case 2:
-                               case 3:
-                               case 4:
-                               case 5:
-                               case 6:
-                               case 7:
-                                       exception = (trace_data->entries[i].data & 0x70) >> 4;
-                                       next_pc_ok = 1;
-                                       next_pc = (trace_data->entries[i].data & 0xf0) >> 2;
-                                       command_print(cmd_ctx, "--- exception %i ---", (trace_data->entries[i].data & 0xf0) >> 4);
-                                       break;
-                               case 8:         /* Direct Branch */
-                                       branch = 1;
-                                       break;
-                               case 9:         /* Indirect Branch */
-                                       branch = 1;
-                                       if (xscale_branch_address(trace_data, i, &next_pc) == 0)
-                                       {
-                                               next_pc_ok = 1;
-                                       }
-                                       break;
-                               case 13:        /* Checkpointed Indirect Branch */
-                                       if (xscale_branch_address(trace_data, i, &next_pc) == 0)
-                                       {
-                                               next_pc_ok = 1;
-                                               if (((chkpt == 0) && (next_pc != trace_data->chkpt0))
-                                                       || ((chkpt == 1) && (next_pc != trace_data->chkpt1)))
-                                                       LOG_WARNING("checkpointed indirect branch target address doesn't match checkpoint");
-                                       }
-                                       /* explicit fall-through */
-                               case 12:        /* Checkpointed Direct Branch */
-                                       branch = 1;
-                                       if (chkpt == 0)
-                                       {
-                                               next_pc_ok = 1;
-                                               next_pc = trace_data->chkpt0;
-                                               chkpt++;
-                                       }
-                                       else if (chkpt == 1)
-                                       {
-                                               next_pc_ok = 1;
-                                               next_pc = trace_data->chkpt0;
-                                               chkpt++;
-                                       }
-                                       else
-                                       {
-                                               LOG_WARNING("more than two checkpointed branches encountered");
-                                       }
-                                       break;
-                               case 15:        /* Roll-over */
-                                       rollover++;
-                                       continue;
-                               default:        /* Reserved */
-                                       command_print(cmd_ctx, "--- reserved trace message ---");
-                                       LOG_ERROR("BUG: trace message %i is reserved", (trace_data->entries[i].data & 0xf0) >> 4);
-                                       return ERROR_OK;
+                          if (current_pc == 0)
+                                 current_pc = chkpt_reg;
+                          else if (current_pc != chkpt_reg)  /* sanity check */
+                                 LOG_WARNING("trace is suspect: checkpoint register "
+                                                         "inconsistent with adddress from image");
                        }
 
-                       if (xscale->trace.pc_ok)
-                       {
-                               int executed = (trace_data->entries[i].data & 0xf) + rollover * 16;
-                               struct arm_instruction instruction;
+                       if (current_pc == 0)
+                          command_print(cmd_ctx, "address unknown");
 
-                               if ((exception == 6) || (exception == 7))
-                               {
-                                       /* IRQ or FIQ exception, no instruction executed */
-                                       executed -= 1;
-                               }
+                       continue;
+                }
 
-                               while (executed-- >= 0)
-                               {
-                                       if ((retval = xscale_read_instruction(target, &instruction)) != ERROR_OK)
-                                       {
-                                               /* can't continue tracing with no image available */
-                                               if (retval == ERROR_TRACE_IMAGE_UNAVAILABLE)
-                                               {
-                                                       return retval;
-                                               }
-                                               else if (retval == ERROR_TRACE_INSTRUCTION_UNAVAILABLE)
-                                               {
-                                                       /* TODO: handle incomplete images */
-                                               }
-                                       }
-
-                                       /* a precise abort on a load to the PC is included in the incremental
-                                        * word count, other instructions causing data aborts are not included
-                                        */
-                                       if ((executed == 0) && (exception == 4)
-                                               && ((instruction.type >= ARM_LDR) && (instruction.type <= ARM_LDM)))
-                                       {
-                                               if ((instruction.type == ARM_LDM)
-                                                       && ((instruction.info.load_store_multiple.register_list & 0x8000) == 0))
-                                               {
-                                                       executed--;
-                                               }
-                                               else if (((instruction.type >= ARM_LDR) && (instruction.type <= ARM_LDRSH))
-                                                       && (instruction.info.load_store.Rd != 15))
-                                               {
-                                                       executed--;
-                                               }
-                                       }
-
-                                       /* only the last instruction executed
-                                        * (the one that caused the control flow change)
-                                        * could be a taken branch
-                                        */
-                                       if (((executed == -1) && (branch == 1)) &&
-                                               (((instruction.type == ARM_B) ||
-                                                       (instruction.type == ARM_BL) ||
-                                                       (instruction.type == ARM_BLX)) &&
-                                                       (instruction.info.b_bl_bx_blx.target_address != 0xffffffff)))
-                                       {
-                                               xscale->trace.current_pc = instruction.info.b_bl_bx_blx.target_address;
-                                       }
-                                       else
-                                       {
-                                               xscale->trace.current_pc += (xscale->trace.core_state == ARM_STATE_ARM) ? 4 : 2;
-                                       }
-                                       command_print(cmd_ctx, "%s", instruction.text);
-                               }
+                /* indirect branch; the branch destination was read from trace buffer */
+                if ((trace_msg_type == 9) || (trace_msg_type == 13))
+                {
+                       current_pc = branch_target;
 
-                               rollover = 0;
-                       }
+                       /* sanity check (checkpoint reg is redundant) */
+                       if ((trace_msg_type == 13) && (chkpt_reg != branch_target))
+                          LOG_WARNING("trace is suspect: checkpoint register "
+                                                  "inconsistent with address from trace buffer");
+                }
 
-                       if (next_pc_ok)
-                       {
-                               xscale->trace.current_pc = next_pc;
-                               xscale->trace.pc_ok = 1;
-                       }
-               }
+         } /* END: for (i = 0; i < trace_data->depth; i++) */
 
-               for (; xscale->trace.current_pc < trace_data->last_instruction; xscale->trace.current_pc += (xscale->trace.core_state == ARM_STATE_ARM) ? 4 : 2)
-               {
-                       struct arm_instruction instruction;
-                       if ((retval = xscale_read_instruction(target, &instruction)) != ERROR_OK)
-                       {
-                               /* can't continue tracing with no image available */
-                               if (retval == ERROR_TRACE_IMAGE_UNAVAILABLE)
-                               {
-                                       return retval;
-                               }
-                               else if (retval == ERROR_TRACE_INSTRUCTION_UNAVAILABLE)
-                               {
-                                       /* TODO: handle incomplete images */
-                               }
-                       }
-                       command_print(cmd_ctx, "%s", instruction.text);
-               }
+         breakpoint_pc = trace_data->last_instruction; /* used below */
+         trace_data = trace_data->next;
 
-               trace_data = trace_data->next;
-       }
+   } /* END: while (trace_data) */
 
-       return ERROR_OK;
+   /* Finally... display all instructions up to the value of the pc when the
+       * debug break occurred (saved when trace data was collected from target).
+       * This is necessary because the trace only records execution branches and 16
+       * consecutive instructions (rollovers), so last few typically missed.
+       */
+   if (current_pc == 0)
+         return ERROR_OK;   /* current_pc was never found */
+
+   /* how many instructions remaining? */
+   int gap_count = (breakpoint_pc - current_pc) /
+         (xscale->trace.core_state == ARM_STATE_ARM ? 4 : 2);
+
+   /* should never be negative or over 16, but verify */
+   if (gap_count < 0 || gap_count > 16)
+   {
+         LOG_WARNING("trace is suspect: excessive gap at end of trace");
+         return ERROR_OK;  /* bail; large number or negative value no good */
+   }
+
+   /* display remaining instructions */
+   for (i = 0; i < gap_count; i++)
+   {
+         xscale_display_instruction(target, current_pc, &instruction, cmd_ctx);
+         current_pc += xscale->trace.core_state == ARM_STATE_ARM ? 4 : 2;
+   }
+
+   return ERROR_OK;
 }
 
 static const struct reg_arch_type xscale_reg_type = {
@@ -2859,7 +2996,7 @@ static void xscale_build_reg_cache(struct target *target)
        int i;
        int num_regs = ARRAY_SIZE(xscale_reg_arch_info);
 
-       (*cache_p) = armv4_5_build_reg_cache(target, armv4_5);
+       (*cache_p) = arm_build_reg_cache(target, armv4_5);
 
        (*cache_p)->next = malloc(sizeof(struct reg_cache));
        cache_p = &(*cache_p)->next;
@@ -2975,6 +3112,9 @@ static int xscale_init_arch_info(struct target *target,
        xscale->dbr0_used = 0;
        xscale->dbr1_used = 0;
 
+       LOG_INFO("%s: hardware has 2 breakpoints and 2 watchpoints",
+                       target_name(target));
+
        xscale->arm_bkpt = ARMV5_BKPT(0x0);
        xscale->thumb_bkpt = ARMV5_T_BKPT(0x0) & 0xffff;
 
@@ -2992,7 +3132,7 @@ static int xscale_init_arch_info(struct target *target,
        armv4_5->write_core_reg = xscale_write_core_reg;
        armv4_5->full_context = xscale_full_context;
 
-       armv4_5_init_arch_info(target, armv4_5);
+       arm_init_arch_info(target, armv4_5);
 
        xscale->armv4_5_mmu.armv4_5_cache.ctype = -1;
        xscale->armv4_5_mmu.get_ttb = xscale_get_ttb;
@@ -3117,21 +3257,18 @@ static int xscale_virt2phys(struct target *target,
                uint32_t virtual, uint32_t *physical)
 {
        struct xscale_common *xscale = target_to_xscale(target);
-       int type;
        uint32_t cb;
-       int domain;
-       uint32_t ap;
 
        if (xscale->common_magic != XSCALE_COMMON_MAGIC) {
                LOG_ERROR(xscale_not);
                return ERROR_TARGET_INVALID;
        }
 
-       uint32_t ret = armv4_5_mmu_translate_va(target, &xscale->armv4_5_mmu, virtual, &type, &cb, &domain, &ap);
-       if (type == -1)
-       {
-               return ret;
-       }
+       uint32_t ret;
+       int retval = armv4_5_mmu_translate_va(target, &xscale->armv4_5_mmu,
+                       virtual, &cb, &ret);
+       if (retval != ERROR_OK)
+               return retval;
        *physical = ret;
        return ERROR_OK;
 }
@@ -3196,21 +3333,26 @@ COMMAND_HANDLER(xscale_handle_idcache_command)
                return ERROR_OK;
        }
 
-       bool icache;
-       COMMAND_PARSE_BOOL(CMD_NAME, icache, "icache", "dcache");
-
+       bool icache = false;
+       if (strcmp(CMD_NAME, "icache") == 0)
+               icache = true;
        if (CMD_ARGC >= 1)
        {
                bool enable;
                COMMAND_PARSE_ENABLE(CMD_ARGV[0], enable);
-               if (enable)
-                       xscale_enable_mmu_caches(target, 1, 0, 0);
-               else
-                       xscale_disable_mmu_caches(target, 1, 0, 0);
-               if (icache)
+               if (icache) {
                        xscale->armv4_5_mmu.armv4_5_cache.i_cache_enabled = enable;
-               else
+                       if (enable)
+                               xscale_enable_mmu_caches(target, 0, 0, 1);
+                       else
+                               xscale_disable_mmu_caches(target, 0, 0, 1);
+               } else {
                        xscale->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = enable;
+                       if (enable)
+                               xscale_enable_mmu_caches(target, 0, 1, 0);
+                       else
+                               xscale_disable_mmu_caches(target, 0, 1, 0);
+               }
        }
 
        bool enabled = icache ?
@@ -3311,7 +3453,6 @@ COMMAND_HANDLER(xscale_handle_trace_buffer_command)
 {
        struct target *target = get_current_target(CMD_CTX);
        struct xscale_common *xscale = target_to_xscale(target);
-       struct arm *armv4_5 = &xscale->armv4_5_common;
        uint32_t dcsr_value;
        int retval;
 
@@ -3360,19 +3501,6 @@ COMMAND_HANDLER(xscale_handle_trace_buffer_command)
                xscale->trace.buffer_fill = -1;
        }
 
-       if (xscale->trace.buffer_enabled)
-       {
-               /* if we enable the trace buffer in fill-once
-                * mode we know the address of the first instruction */
-               xscale->trace.pc_ok = 1;
-               xscale->trace.current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
-       }
-       else
-       {
-               /* otherwise the address is unknown, and we have no known good PC */
-               xscale->trace.pc_ok = 0;
-       }
-
        command_print(CMD_CTX, "trace buffer %s (%s)",
                (xscale->trace.buffer_enabled) ? "enabled" : "disabled",
                (xscale->trace.buffer_fill > 0) ? "fill" : "wrap");
@@ -3417,7 +3545,7 @@ COMMAND_HANDLER(xscale_handle_trace_image_command)
        if (CMD_ARGC >= 2)
        {
                xscale->trace.image->base_address_set = 1;
-               COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], xscale->trace.image->base_address);
+               COMMAND_PARSE_NUMBER(llong, CMD_ARGV[1], xscale->trace.image->base_address);
        }
        else
        {
@@ -3597,94 +3725,101 @@ COMMAND_HANDLER(xscale_handle_cp15)
 static const struct command_registration xscale_exec_command_handlers[] = {
        {
                .name = "cache_info",
-               .handler = &xscale_handle_cache_info_command,
-               .mode = COMMAND_EXEC, NULL,
+               .handler = xscale_handle_cache_info_command,
+               .mode = COMMAND_EXEC,
+               .help = "display information about CPU caches",
        },
-
        {
                .name = "mmu",
-               .handler = &xscale_handle_mmu_command,
+               .handler = xscale_handle_mmu_command,
                .mode = COMMAND_EXEC,
-               .usage = "[enable|disable]",
                .help = "enable or disable the MMU",
+               .usage = "['enable'|'disable']",
        },
        {
                .name = "icache",
-               .handler = &xscale_handle_idcache_command,
+               .handler = xscale_handle_idcache_command,
                .mode = COMMAND_EXEC,
-               .usage = "[enable|disable]",
-               .help = "enable or disable the ICache",
+               .help = "display ICache state, optionally enabling or "
+                       "disabling it",
+               .usage = "['enable'|'disable']",
        },
        {
                .name = "dcache",
-               .handler = &xscale_handle_idcache_command,
+               .handler = xscale_handle_idcache_command,
                .mode = COMMAND_EXEC,
-               .usage = "[enable|disable]",
-               .help = "enable or disable the DCache",
+               .help = "display DCache state, optionally enabling or "
+                       "disabling it",
+               .usage = "['enable'|'disable']",
        },
-
        {
                .name = "vector_catch",
-               .handler = &xscale_handle_vector_catch_command,
+               .handler = xscale_handle_vector_catch_command,
                .mode = COMMAND_EXEC,
-               .help = "mask of vectors that should be caught",
-               .usage = "[<mask>]",
+               .help = "set or display 8-bit mask of vectors "
+                       "that should trigger debug entry",
+               .usage = "[mask]",
        },
        {
                .name = "vector_table",
-               .handler = &xscale_handle_vector_table_command,
+               .handler = xscale_handle_vector_table_command,
                .mode = COMMAND_EXEC,
-               .usage = "<high|low> <index> <code>",
-               .help = "set static code for exception handler entry",
+               .help = "set vector table entry in mini-ICache, "
+                       "or display current tables",
+               .usage = "[('high'|'low') index code]",
        },
-
        {
                .name = "trace_buffer",
-               .handler = &xscale_handle_trace_buffer_command,
+               .handler = xscale_handle_trace_buffer_command,
                .mode = COMMAND_EXEC,
-               .usage = "<enable | disable> [fill [n]|wrap]",
+               .help = "display trace buffer status, enable or disable "
+                       "tracing, and optionally reconfigure trace mode",
+               .usage = "['enable'|'disable' ['fill' number|'wrap']]",
        },
        {
                .name = "dump_trace",
-               .handler = &xscale_handle_dump_trace_command,
+               .handler = xscale_handle_dump_trace_command,
                .mode = COMMAND_EXEC,
-               .help = "dump content of trace buffer to <file>",
-               .usage = "<file>",
+               .help = "dump content of trace buffer to file",
+               .usage = "filename",
        },
        {
                .name = "analyze_trace",
-               .handler = &xscale_handle_analyze_trace_buffer_command,
+               .handler = xscale_handle_analyze_trace_buffer_command,
                .mode = COMMAND_EXEC,
                .help = "analyze content of trace buffer",
+               .usage = "",
        },
        {
                .name = "trace_image",
-               .handler = &xscale_handle_trace_image_command,
-               COMMAND_EXEC,
-               .help = "load image from <file> [base address]",
-               .usage = "<file> [address] [type]",
+               .handler = xscale_handle_trace_image_command,
+               .mode = COMMAND_EXEC,
+               .help = "load image from file to address (default 0)",
+               .usage = "filename [offset [filetype]]",
        },
-
        {
                .name = "cp15",
-               .handler = &xscale_handle_cp15,
+               .handler = xscale_handle_cp15,
                .mode = COMMAND_EXEC,
-               .help = "access coproc 15",
-               .usage = "<register> [value]",
+               .help = "Read or write coprocessor 15 register.",
+               .usage = "register [value]",
        },
        COMMAND_REGISTRATION_DONE
 };
 static const struct command_registration xscale_any_command_handlers[] = {
        {
                .name = "debug_handler",
-               .handler = &xscale_handle_debug_handler_command,
+               .handler = xscale_handle_debug_handler_command,
                .mode = COMMAND_ANY,
-               .usage = "<target#> <address>",
+               .help = "Change address used for debug handler.",
+               .usage = "target address",
        },
        {
                .name = "cache_clean_address",
-               .handler = &xscale_handle_cache_clean_address_command,
+               .handler = xscale_handle_cache_clean_address_command,
                .mode = COMMAND_ANY,
+               .help = "Change address used for cleaning data cache.",
+               .usage = "address",
        },
        {
                .chain = xscale_exec_command_handlers,
@@ -3721,7 +3856,8 @@ struct target_type xscale_target =
        .deassert_reset = xscale_deassert_reset,
        .soft_reset_halt = NULL,
 
-       .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
+       /* REVISIT on some cores, allow exporting iwmmxt registers ... */
+       .get_gdb_reg_list = arm_get_gdb_reg_list,
 
        .read_memory = xscale_read_memory,
        .read_phys_memory = xscale_read_phys_memory,