MIPS: pracc access tweaks
[fw/openocd] / src / target / xscale.c
index e471ac3be7236312c70ecf143ca92e27913bee6d..6efe59c0aa2982c536bd7452298a7cea21aa2943 100644 (file)
 #include "arm_jtag.h"
 #include "arm_simulator.h"
 #include "arm_disassembler.h"
-#include "time_support.h"
+#include <helper/time_support.h>
 #include "register.h"
 #include "image.h"
+#include "arm_opcodes.h"
+#include "armv4_5.h"
 
 
 /*
@@ -62,7 +64,7 @@
 static int xscale_resume(struct target *, int current,
        uint32_t address, int handle_breakpoints, int debug_execution);
 static int xscale_debug_entry(struct target *);
-static int xscale_restore_context(struct target *);
+static int xscale_restore_banked(struct target *);
 static int xscale_get_reg(struct reg *reg);
 static int xscale_set_reg(struct reg *reg, uint8_t *buf);
 static int xscale_set_breakpoint(struct target *, struct breakpoint *);
@@ -191,7 +193,8 @@ static int xscale_read_dcsr(struct target *target)
        uint8_t field2_check_mask = 0x1;
 
        jtag_set_end_state(TAP_DRPAUSE);
-       xscale_jtag_set_instr(target->tap, XSCALE_SELDCSR);
+       xscale_jtag_set_instr(target->tap,
+               XSCALE_SELDCSR << xscale->xscale_variant);
 
        buf_set_u32(&field0, 1, 1, xscale->hold_rst);
        buf_set_u32(&field0, 2, 1, xscale->external_debug_break);
@@ -256,6 +259,7 @@ static int xscale_receive(struct target *target, uint32_t *buffer, int num_words
        if (num_words == 0)
                return ERROR_INVALID_ARGUMENTS;
 
+       struct xscale_common *xscale = target_to_xscale(target);
        int retval = ERROR_OK;
        tap_state_t path[3];
        struct scan_field fields[3];
@@ -289,7 +293,8 @@ static int xscale_receive(struct target *target, uint32_t *buffer, int num_words
        fields[2].check_mask = &field2_check_mask;
 
        jtag_set_end_state(TAP_IDLE);
-       xscale_jtag_set_instr(target->tap, XSCALE_DBGTX);
+       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 */
 
        /* repeat until all words have been collected */
@@ -371,7 +376,8 @@ static int xscale_read_tx(struct target *target, int consume)
 
        jtag_set_end_state(TAP_IDLE);
 
-       xscale_jtag_set_instr(target->tap, XSCALE_DBGTX);
+       xscale_jtag_set_instr(target->tap,
+               XSCALE_DBGTX << xscale->xscale_variant);
 
        path[0] = TAP_DRSELECT;
        path[1] = TAP_DRCAPTURE;
@@ -412,7 +418,7 @@ static int xscale_read_tx(struct target *target, int consume)
                        jtag_add_pathmove(3, path);
                else
                {
-                       jtag_add_pathmove(sizeof(noconsume_path)/sizeof(*noconsume_path), noconsume_path);
+                       jtag_add_pathmove(ARRAY_SIZE(noconsume_path), noconsume_path);
                }
 
                jtag_add_dr_scan(3, fields, jtag_set_end_state(TAP_IDLE));
@@ -469,7 +475,8 @@ static int xscale_write_rx(struct target *target)
 
        jtag_set_end_state(TAP_IDLE);
 
-       xscale_jtag_set_instr(target->tap, XSCALE_DBGRX);
+       xscale_jtag_set_instr(target->tap,
+               XSCALE_DBGRX << xscale->xscale_variant);
 
        memset(&fields, 0, sizeof fields);
 
@@ -541,6 +548,7 @@ static int xscale_write_rx(struct target *target)
 /* send count elements of size byte to the debug handler */
 static int xscale_send(struct target *target, uint8_t *buffer, int count, int size)
 {
+       struct xscale_common *xscale = target_to_xscale(target);
        uint32_t t[3];
        int bits[3];
        int retval;
@@ -548,7 +556,8 @@ static int xscale_send(struct target *target, uint8_t *buffer, int count, int si
 
        jtag_set_end_state(TAP_IDLE);
 
-       xscale_jtag_set_instr(target->tap, XSCALE_DBGRX);
+       xscale_jtag_set_instr(target->tap,
+               XSCALE_DBGRX << xscale->xscale_variant);
 
        bits[0]=3;
        t[0]=0;
@@ -629,7 +638,8 @@ static int xscale_write_dcsr(struct target *target, int hold_rst, int ext_dbg_br
                xscale->external_debug_break = ext_dbg_brk;
 
        jtag_set_end_state(TAP_IDLE);
-       xscale_jtag_set_instr(target->tap, XSCALE_SELDCSR);
+       xscale_jtag_set_instr(target->tap,
+               XSCALE_SELDCSR << xscale->xscale_variant);
 
        buf_set_u32(&field0, 1, 1, xscale->hold_rst);
        buf_set_u32(&field0, 2, 1, xscale->external_debug_break);
@@ -683,6 +693,7 @@ static unsigned int parity (unsigned int v)
 
 static int xscale_load_ic(struct target *target, uint32_t va, uint32_t buffer[8])
 {
+       struct xscale_common *xscale = target_to_xscale(target);
        uint8_t packet[4];
        uint8_t cmd;
        int word;
@@ -692,7 +703,8 @@ static int xscale_load_ic(struct target *target, uint32_t va, uint32_t buffer[8]
 
        /* LDIC into IR */
        jtag_set_end_state(TAP_IDLE);
-       xscale_jtag_set_instr(target->tap, XSCALE_LDIC);
+       xscale_jtag_set_instr(target->tap,
+               XSCALE_LDIC << xscale->xscale_variant);
 
        /* CMD is b011 to load a cacheline into the Mini ICache.
         * Loading into the main ICache is deprecated, and unused.
@@ -738,12 +750,14 @@ static int xscale_load_ic(struct target *target, uint32_t va, uint32_t buffer[8]
 
 static int xscale_invalidate_ic_line(struct target *target, uint32_t va)
 {
+       struct xscale_common *xscale = target_to_xscale(target);
        uint8_t packet[4];
        uint8_t cmd;
        struct scan_field fields[2];
 
        jtag_set_end_state(TAP_IDLE);
-       xscale_jtag_set_instr(target->tap, XSCALE_LDIC);
+       xscale_jtag_set_instr(target->tap,
+               XSCALE_LDIC << xscale->xscale_variant);
 
        /* CMD for invalidate IC line b000, bits [6:4] b000 */
        buf_set_u32(&cmd, 0, 6, 0x0);
@@ -845,21 +859,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],
@@ -961,12 +968,11 @@ static int xscale_debug_entry(struct target *target)
                         arm_mode_name(armv4_5->core_mode));
 
        /* get banked registers, r8 to r14, and spsr if not in USR/SYS mode */
-       if ((armv4_5->core_mode != ARMV4_5_MODE_USR) && (armv4_5->core_mode != ARMV4_5_MODE_SYS))
-       {
+       if (armv4_5->spsr) {
                xscale_receive(target, buffer, 8);
-               buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 16).value, 0, 32, buffer[7]);
-               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 16).dirty = 0;
-               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 16).valid = 1;
+               buf_set_u32(armv4_5->spsr->value, 0, 32, buffer[7]);
+               armv4_5->spsr->dirty = false;
+               armv4_5->spsr->valid = true;
        }
        else
        {
@@ -974,12 +980,14 @@ static int xscale_debug_entry(struct target *target)
                xscale_receive(target, buffer, 7);
        }
 
-       /* move data from buffer to register cache */
+       /* move data from buffer to right banked register in cache */
        for (i = 8; i <= 14; i++)
        {
-               buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).value, 0, 32, buffer[i - 8]);
-               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).dirty = 0;
-               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).valid = 1;
+               struct reg *r = arm_reg_current(armv4_5, i);
+
+               buf_set_u32(r->value, 0, 32, buffer[i - 8]);
+               r->dirty = false;
+               r->valid = true;
        }
 
        /* examine debug reason */
@@ -1238,7 +1246,7 @@ static int xscale_resume(struct target *target, int current,
                        xscale_enable_single_step(target, next_pc);
 
                        /* restore banked registers */
-                       xscale_restore_context(target);
+                       retval = xscale_restore_banked(target);
 
                        /* send resume request (command 0x30 or 0x31)
                         * clean the trace buffer if it is to be enabled (0x62) */
@@ -1283,7 +1291,7 @@ static int xscale_resume(struct target *target, int current,
        xscale_enable_watchpoints(target);
 
        /* restore banked registers */
-       xscale_restore_context(target);
+       retval = xscale_restore_banked(target);
 
        /* send resume request (command 0x30 or 0x31)
         * clean the trace buffer if it is to be enabled (0x62) */
@@ -1358,7 +1366,7 @@ static int xscale_step_inner(struct target *target, int current,
                return retval;
 
        /* restore banked registers */
-       if ((retval = xscale_restore_context(target)) != ERROR_OK)
+       if ((retval = xscale_restore_banked(target)) != ERROR_OK)
                return retval;
 
        /* send resume request (command 0x30 or 0x31)
@@ -1416,7 +1424,7 @@ 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 arm *armv4_5 = target_to_arm(target);
        struct breakpoint *breakpoint = target->breakpoints;
 
        uint32_t current_pc;
@@ -1479,7 +1487,8 @@ static int xscale_assert_reset(struct target *target)
         * 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_jtag_set_instr(target->tap,
+               XSCALE_SELDCSR << xscale->xscale_variant);
 
        /* set Hold reset, Halt mode and Trap Reset */
        buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 30, 1, 0x1);
@@ -1487,7 +1496,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);
        jtag_execute_queue();
 
        /* assert reset */
@@ -1644,7 +1653,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");
@@ -1652,7 +1661,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");
@@ -1661,7 +1670,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;
 
@@ -1683,50 +1692,56 @@ static int xscale_full_context(struct target *target)
         */
        for (i = 1; i < 7; i++)
        {
-               int valid = 1;
+               enum arm_mode mode = armv4_5_number_to_mode(i);
+               bool valid = true;
+               struct reg *r;
+
+               if (mode == ARM_MODE_USR)
+                       continue;
 
                /* check if there are invalid registers in the current mode
                 */
-               for (j = 0; j <= 16; j++)
+               for (j = 0; valid && j <= 16; j++)
                {
-                       if (ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), j).valid == 0)
-                               valid = 0;
+                       if (!ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
+                                       mode, j).valid)
+                               valid = false;
                }
+               if (valid)
+                       continue;
 
-               if (!valid)
-               {
-                       uint32_t tmp_cpsr;
-
-                       /* request banked registers */
-                       xscale_send_u32(target, 0x0);
+               /* request banked registers */
+               xscale_send_u32(target, 0x0);
 
-                       tmp_cpsr = 0x0;
-                       tmp_cpsr |= armv4_5_number_to_mode(i);
-                       tmp_cpsr |= 0xc0; /* I/F bits */
+               /* send CPSR for desired bank mode */
+               xscale_send_u32(target, mode | 0xc0 /* I/F bits */);
 
-                       /* send CPSR for desired mode */
-                       xscale_send_u32(target, tmp_cpsr);
+               /* get banked registers:  r8 to r14; and SPSR
+                * except in USR/SYS mode
+                */
+               if (mode != ARM_MODE_SYS) {
+                       /* SPSR */
+                       r = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
+                                       mode, 16);
+
+                       xscale_receive(target, buffer, 8);
+
+                       buf_set_u32(r->value, 0, 32, buffer[7]);
+                       r->dirty = false;
+                       r->valid = true;
+               } else {
+                       xscale_receive(target, buffer, 7);
+               }
 
-                       /* get banked registers, r8 to r14, and spsr if not in USR/SYS mode */
-                       if ((armv4_5_number_to_mode(i) != ARMV4_5_MODE_USR) && (armv4_5_number_to_mode(i) != ARMV4_5_MODE_SYS))
-                       {
-                               xscale_receive(target, buffer, 8);
-                               buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 16).value, 0, 32, buffer[7]);
-                               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), 16).dirty = 0;
-                               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), 16).valid = 1;
-                       }
-                       else
-                       {
-                               xscale_receive(target, buffer, 7);
-                       }
+               /* move data from buffer to register cache */
+               for (j = 8; j <= 14; j++)
+               {
+                       r = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
+                                       mode, j);
 
-                       /* move data from buffer to register cache */
-                       for (j = 8; j <= 14; j++)
-                       {
-                               buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), j).value, 0, 32, buffer[j - 8]);
-                               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), j).dirty = 0;
-                               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), j).valid = 1;
-                       }
+                       buf_set_u32(r->value, 0, 32, buffer[j - 8]);
+                       r->dirty = false;
+                       r->valid = true;
                }
        }
 
@@ -1735,9 +1750,9 @@ static int xscale_full_context(struct target *target)
        return ERROR_OK;
 }
 
-static int xscale_restore_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;
 
@@ -1748,54 +1763,60 @@ static int xscale_restore_context(struct target *target)
        }
 
        /* iterate through processor modes (FIQ, IRQ, SVC, ABT, UND and SYS)
-       * we can't enter User mode on an XScale (unpredictable),
-       * but User shares registers with SYS
-       */
+        * and check if any banked registers need to be written.  Ignore
+        * USR mode (number 0) in favor of SYS; we can't enter User mode on
+        * an XScale (unpredictable), but they share all registers.
+        */
        for (i = 1; i < 7; i++)
        {
-               int dirty = 0;
+               enum arm_mode mode = armv4_5_number_to_mode(i);
+               struct reg *r;
 
-               /* check if there are invalid registers in the current mode
-               */
+               if (mode == ARM_MODE_USR)
+                       continue;
+
+               /* check if there are dirty registers in this mode */
                for (j = 8; j <= 14; j++)
                {
-                       if (ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), j).dirty == 1)
-                               dirty = 1;
+                       if (ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
+                                       mode, j).dirty)
+                               goto dirty;
                }
 
                /* if not USR/SYS, check if the SPSR needs to be written */
-               if ((armv4_5_number_to_mode(i) != ARMV4_5_MODE_USR) && (armv4_5_number_to_mode(i) != ARMV4_5_MODE_SYS))
+               if (mode != ARM_MODE_SYS)
                {
-                       if (ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), 16).dirty == 1)
-                               dirty = 1;
+                       if (ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
+                                       mode, 16).dirty)
+                               goto dirty;
                }
 
-               if (dirty)
-               {
-                       uint32_t tmp_cpsr;
-
-                       /* send banked registers */
-                       xscale_send_u32(target, 0x1);
+               /* there's nothing to flush for this mode */
+               continue;
 
-                       tmp_cpsr = 0x0;
-                       tmp_cpsr |= armv4_5_number_to_mode(i);
-                       tmp_cpsr |= 0xc0; /* I/F bits */
+dirty:
+               /* command 0x1:  "send banked registers" */
+               xscale_send_u32(target, 0x1);
 
-                       /* send CPSR for desired mode */
-                       xscale_send_u32(target, tmp_cpsr);
+               /* send CPSR for desired mode */
+               xscale_send_u32(target, mode | 0xc0 /* I/F bits */);
 
-                       /* send banked registers, r8 to r14, and spsr if not in USR/SYS mode */
-                       for (j = 8; j <= 14; j++)
-                       {
-                               xscale_send_u32(target, buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, j).value, 0, 32));
-                               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), j).dirty = 0;
-                       }
+               /* send r8 to r14/lr ... only FIQ needs more than r13..r14,
+                * but this protocol doesn't understand that nuance.
+                */
+               for (j = 8; j <= 14; j++) {
+                       r = &ARMV4_5_CORE_REG_MODE(armv4_5->core_cache,
+                                       mode, j);
+                       xscale_send_u32(target, buf_get_u32(r->value, 0, 32));
+                       r->dirty = false;
+               }
 
-                       if ((armv4_5_number_to_mode(i) != ARMV4_5_MODE_USR) && (armv4_5_number_to_mode(i) != ARMV4_5_MODE_SYS))
-                       {
-                               xscale_send_u32(target, buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 16).value, 0, 32));
-                               ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), 16).dirty = 0;
-                       }
+               /* send spsr if not in USR/SYS mode */
+               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));
+                       r->dirty = false;
                }
        }
 
@@ -1881,6 +1902,21 @@ static int xscale_read_memory(struct target *target, uint32_t address,
        return ERROR_OK;
 }
 
+static int xscale_read_phys_memory(struct target *target, uint32_t address,
+               uint32_t size, uint32_t count, uint8_t *buffer)
+{
+       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;
+}
+
 static int xscale_write_memory(struct target *target, uint32_t address,
                uint32_t size, uint32_t count, uint8_t *buffer)
 {
@@ -1959,6 +1995,21 @@ static int xscale_write_memory(struct target *target, uint32_t address,
        return ERROR_OK;
 }
 
+static int xscale_write_phys_memory(struct target *target, uint32_t address,
+               uint32_t size, uint32_t count, uint8_t *buffer)
+{
+       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;
+}
+
 static int xscale_bulk_write_memory(struct target *target, uint32_t address,
                uint32_t count, uint8_t *buffer)
 {
@@ -2119,12 +2170,6 @@ static int xscale_add_breakpoint(struct target *target,
 {
        struct xscale_common *xscale = target_to_xscale(target);
 
-       if (target->state != TARGET_HALTED)
-       {
-               LOG_WARNING("target not halted");
-               return ERROR_TARGET_NOT_HALTED;
-       }
-
        if ((breakpoint->type == BKPT_HARD) && (xscale->ibcr_available < 1))
        {
                LOG_INFO("no breakpoint unit available for hardware breakpoint");
@@ -2282,12 +2327,6 @@ static int xscale_add_watchpoint(struct target *target,
 {
        struct xscale_common *xscale = target_to_xscale(target);
 
-       if (target->state != TARGET_HALTED)
-       {
-               LOG_WARNING("target not halted");
-               return ERROR_TARGET_NOT_HALTED;
-       }
-
        if (xscale->dbr_available < 1)
        {
                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
@@ -2575,7 +2614,7 @@ static int xscale_read_instruction(struct target *target,
                return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
        }
 
-       if (xscale->trace.core_state == ARMV4_5_STATE_ARM)
+       if (xscale->trace.core_state == ARM_STATE_ARM)
        {
                uint8_t buf[4];
                if ((retval = image_read_section(xscale->trace.image, section,
@@ -2588,7 +2627,7 @@ static int xscale_read_instruction(struct target *target,
                opcode = target_buffer_get_u32(target, buf);
                arm_evaluate_opcode(opcode, xscale->trace.current_pc, instruction);
        }
-       else if (xscale->trace.core_state == ARMV4_5_STATE_THUMB)
+       else if (xscale->trace.core_state == ARM_STATE_THUMB)
        {
                uint8_t buf[2];
                if ((retval = image_read_section(xscale->trace.image, section,
@@ -2640,7 +2679,7 @@ static int xscale_analyze_trace(struct target *target, struct command_context *c
                int rollover;
                int branch;
                int exception;
-               xscale->trace.core_state = ARMV4_5_STATE_ARM;
+               xscale->trace.core_state = ARM_STATE_ARM;
 
                chkpt = 0;
                rollover = 0;
@@ -2774,7 +2813,7 @@ static int xscale_analyze_trace(struct target *target, struct command_context *c
                                        }
                                        else
                                        {
-                                               xscale->trace.current_pc += (xscale->trace.core_state == ARMV4_5_STATE_ARM) ? 4 : 2;
+                                               xscale->trace.current_pc += (xscale->trace.core_state == ARM_STATE_ARM) ? 4 : 2;
                                        }
                                        command_print(cmd_ctx, "%s", instruction.text);
                                }
@@ -2789,7 +2828,7 @@ static int xscale_analyze_trace(struct target *target, struct command_context *c
                        }
                }
 
-               for (; xscale->trace.current_pc < trace_data->last_instruction; xscale->trace.current_pc += (xscale->trace.core_state == ARMV4_5_STATE_ARM) ? 4 : 2)
+               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)
@@ -2825,9 +2864,9 @@ static void xscale_build_reg_cache(struct target *target)
        struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
        struct xscale_reg *arch_info = malloc(sizeof(xscale_reg_arch_info));
        int i;
-       int num_regs = sizeof(xscale_reg_arch_info) / sizeof(struct xscale_reg);
+       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;
@@ -2870,10 +2909,10 @@ static int xscale_init_arch_info(struct target *target,
 
        armv4_5 = &xscale->armv4_5_common;
 
-       /* store architecture specfic data (none so far) */
+       /* store architecture specfic data */
        xscale->common_magic = XSCALE_COMMON_MAGIC;
 
-       /* we don't really *need* variant info ... */
+       /* we don't really *need* a variant param ... */
        if (variant) {
                int ir_length = 0;
 
@@ -2886,6 +2925,8 @@ static int xscale_init_arch_info(struct target *target,
                                || strcmp(variant, "ixp45x") == 0
                                || strcmp(variant, "ixp46x") == 0)
                        ir_length = 7;
+               else if (strcmp(variant, "pxa3xx") == 0)
+                       ir_length = 11;
                else
                        LOG_WARNING("%s: unrecognized variant %s",
                                tap->dotted_name, variant);
@@ -2897,6 +2938,12 @@ static int xscale_init_arch_info(struct target *target,
                }
        }
 
+       /* PXA3xx shifts the JTAG instructions */
+       if (tap->ir_length == 11)
+               xscale->xscale_variant = XSCALE_PXA3XX;
+       else
+               xscale->xscale_variant = XSCALE_IXP4XX_PXA2XX;
+
        /* the debug handler isn't installed (and thus not running) at this time */
        xscale->handler_address = 0xfe000800;
 
@@ -2935,6 +2982,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;
 
@@ -2952,7 +3002,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;
@@ -3554,36 +3604,115 @@ COMMAND_HANDLER(xscale_handle_cp15)
        return ERROR_OK;
 }
 
-static int xscale_register_commands(struct command_context *cmd_ctx)
-{
-       struct command *xscale_cmd;
-
-       xscale_cmd = register_command(cmd_ctx, NULL, "xscale", NULL, COMMAND_ANY, "xscale specific commands");
-
-       register_command(cmd_ctx, xscale_cmd, "debug_handler", xscale_handle_debug_handler_command, COMMAND_ANY, "'xscale debug_handler <target#> <address>' command takes two required operands");
-       register_command(cmd_ctx, xscale_cmd, "cache_clean_address", xscale_handle_cache_clean_address_command, COMMAND_ANY, NULL);
-
-       register_command(cmd_ctx, xscale_cmd, "cache_info", xscale_handle_cache_info_command, COMMAND_EXEC, NULL);
-       register_command(cmd_ctx, xscale_cmd, "mmu", xscale_handle_mmu_command, COMMAND_EXEC, "['enable'|'disable'] the MMU");
-       register_command(cmd_ctx, xscale_cmd, "icache", xscale_handle_idcache_command, COMMAND_EXEC, "['enable'|'disable'] the ICache");
-       register_command(cmd_ctx, xscale_cmd, "dcache", xscale_handle_idcache_command, COMMAND_EXEC, "['enable'|'disable'] the DCache");
-
-       register_command(cmd_ctx, xscale_cmd, "vector_catch", xscale_handle_vector_catch_command, COMMAND_EXEC, "<mask> of vectors that should be catched");
-       register_command(cmd_ctx, xscale_cmd, "vector_table", xscale_handle_vector_table_command, COMMAND_EXEC, "<high|low> <index> <code> set static code for exception handler entry");
-
-       register_command(cmd_ctx, xscale_cmd, "trace_buffer", xscale_handle_trace_buffer_command, COMMAND_EXEC, "<enable | disable> ['fill' [n]|'wrap']");
-
-       register_command(cmd_ctx, xscale_cmd, "dump_trace", xscale_handle_dump_trace_command, COMMAND_EXEC, "dump content of trace buffer to <file>");
-       register_command(cmd_ctx, xscale_cmd, "analyze_trace", xscale_handle_analyze_trace_buffer_command, COMMAND_EXEC, "analyze content of trace buffer");
-       register_command(cmd_ctx, xscale_cmd, "trace_image", xscale_handle_trace_image_command,
-               COMMAND_EXEC, "load image from <file> [base address]");
-
-       register_command(cmd_ctx, xscale_cmd, "cp15", xscale_handle_cp15, COMMAND_EXEC, "access coproc 15 <register> [value]");
-
-       armv4_5_register_commands(cmd_ctx);
-
-       return ERROR_OK;
-}
+static const struct command_registration xscale_exec_command_handlers[] = {
+       {
+               .name = "cache_info",
+               .handler = &xscale_handle_cache_info_command,
+               .mode = COMMAND_EXEC, NULL,
+       },
+
+       {
+               .name = "mmu",
+               .handler = &xscale_handle_mmu_command,
+               .mode = COMMAND_EXEC,
+               .usage = "[enable|disable]",
+               .help = "enable or disable the MMU",
+       },
+       {
+               .name = "icache",
+               .handler = &xscale_handle_idcache_command,
+               .mode = COMMAND_EXEC,
+               .usage = "[enable|disable]",
+               .help = "enable or disable the ICache",
+       },
+       {
+               .name = "dcache",
+               .handler = &xscale_handle_idcache_command,
+               .mode = COMMAND_EXEC,
+               .usage = "[enable|disable]",
+               .help = "enable or disable the DCache",
+       },
+
+       {
+               .name = "vector_catch",
+               .handler = &xscale_handle_vector_catch_command,
+               .mode = COMMAND_EXEC,
+               .help = "mask of vectors that should be caught",
+               .usage = "[<mask>]",
+       },
+       {
+               .name = "vector_table",
+               .handler = &xscale_handle_vector_table_command,
+               .mode = COMMAND_EXEC,
+               .usage = "<high|low> <index> <code>",
+               .help = "set static code for exception handler entry",
+       },
+
+       {
+               .name = "trace_buffer",
+               .handler = &xscale_handle_trace_buffer_command,
+               .mode = COMMAND_EXEC,
+               .usage = "<enable | disable> [fill [n]|wrap]",
+       },
+       {
+               .name = "dump_trace",
+               .handler = &xscale_handle_dump_trace_command,
+               .mode = COMMAND_EXEC,
+               .help = "dump content of trace buffer to <file>",
+               .usage = "<file>",
+       },
+       {
+               .name = "analyze_trace",
+               .handler = &xscale_handle_analyze_trace_buffer_command,
+               .mode = COMMAND_EXEC,
+               .help = "analyze content of trace buffer",
+       },
+       {
+               .name = "trace_image",
+               .handler = &xscale_handle_trace_image_command,
+               COMMAND_EXEC,
+               .help = "load image from <file> [base address]",
+               .usage = "<file> [address] [type]",
+       },
+
+       {
+               .name = "cp15",
+               .handler = &xscale_handle_cp15,
+               .mode = COMMAND_EXEC,
+               .help = "access coproc 15",
+               .usage = "<register> [value]",
+       },
+       COMMAND_REGISTRATION_DONE
+};
+static const struct command_registration xscale_any_command_handlers[] = {
+       {
+               .name = "debug_handler",
+               .handler = &xscale_handle_debug_handler_command,
+               .mode = COMMAND_ANY,
+               .usage = "<target#> <address>",
+       },
+       {
+               .name = "cache_clean_address",
+               .handler = &xscale_handle_cache_clean_address_command,
+               .mode = COMMAND_ANY,
+       },
+       {
+               .chain = xscale_exec_command_handlers,
+       },
+       COMMAND_REGISTRATION_DONE
+};
+static const struct command_registration xscale_command_handlers[] = {
+       {
+               .chain = arm_command_handlers,
+       },
+       {
+               .name = "xscale",
+               .mode = COMMAND_ANY,
+               .help = "xscale command group",
+               .chain = xscale_any_command_handlers,
+       },
+       COMMAND_REGISTRATION_DONE
+};
 
 struct target_type xscale_target =
 {
@@ -3602,10 +3731,13 @@ 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,
        .write_memory = xscale_write_memory,
+       .write_phys_memory = xscale_write_phys_memory,
        .bulk_write_memory = xscale_bulk_write_memory,
 
        .checksum_memory = arm_checksum_memory,
@@ -3618,7 +3750,7 @@ struct target_type xscale_target =
        .add_watchpoint = xscale_add_watchpoint,
        .remove_watchpoint = xscale_remove_watchpoint,
 
-       .register_commands = xscale_register_commands,
+       .commands = xscale_command_handlers,
        .target_create = xscale_target_create,
        .init_target = xscale_init_target,