types: write memory now uses const
[openocd.git] / src / target / xscale.c
index c3b8d3358822724130cb2109759da7be57c2021f..3b5674581c2b3131c9695b8648986ec77602ea92 100644 (file)
@@ -2,9 +2,12 @@
  *   Copyright (C) 2006, 2007 by Dominic Rath                              *
  *   Dominic.Rath@gmx.de                                                   *
  *                                                                         *
- *   Copyright (C) 2007,2008 Øyvind Harboe                                 *
+ *   Copyright (C) 2007,2008 Øyvind Harboe                                 *
  *   oyvind.harboe@zylin.com                                               *
  *                                                                         *
+ *   Copyright (C) 2009 Michael Schwingen                                  *
+ *   michael@schwingen.org                                                 *
+ *                                                                         *
  *   This program is free software; you can redistribute it and/or modify  *
  *   it under the terms of the GNU General Public License as published by  *
  *   the Free Software Foundation; either version 2 of the License, or     *
 #include "config.h"
 #endif
 
-#include "replacements.h"
-
+#include "breakpoints.h"
 #include "xscale.h"
-
-#include "arm7_9_common.h"
-#include "register.h"
-#include "target.h"
-#include "armv4_5.h"
+#include "target_type.h"
+#include "arm_jtag.h"
 #include "arm_simulator.h"
 #include "arm_disassembler.h"
-#include "log.h"
-#include "jtag.h"
-#include "binarybuffer.h"
-#include "time_support.h"
-#include "breakpoints.h"
-#include "fileio.h"
-
-#include <stdlib.h>
-#include <string.h>
+#include <helper/time_support.h>
+#include "register.h"
+#include "image.h"
+#include "arm_opcodes.h"
+#include "armv4_5.h"
 
-#include <sys/types.h>
-#include <unistd.h>
-#include <errno.h>
 
+/*
+ * Important XScale documents available as of October 2009 include:
+ *
+ *  Intel XScale® Core Developer’s Manual, January 2004
+ *             Order Number: 273473-002
+ *     This has a chapter detailing debug facilities, and punts some
+ *     details to chip-specific microarchitecture documents.
+ *
+ *  Hot-Debug for Intel XScale® Core Debug White Paper, May 2005
+ *             Document Number: 273539-005
+ *     Less detailed than the developer's manual, but summarizes those
+ *     missing details (for most XScales) and gives LOTS of notes about
+ *     debugger/handler interaction issues.  Presents a simpler reset
+ *     and load-handler sequence than the arch doc.  (Note, OpenOCD
+ *     doesn't currently support "Hot-Debug" as defined there.)
+ *
+ * Chip-specific microarchitecture documents may also be useful.
+ */
 
-/* cli handling */
-int xscale_register_commands(struct command_context_s *cmd_ctx);
 
 /* forward declarations */
-int xscale_target_create(struct target_s *target, Jim_Interp *interp);
-int xscale_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
-int xscale_quit(void);
-
-int xscale_arch_state(struct target_s *target);
-int xscale_poll(target_t *target);
-int xscale_halt(target_t *target);
-int xscale_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution);
-int xscale_step(struct target_s *target, int current, u32 address, int handle_breakpoints);
-int xscale_debug_entry(target_t *target);
-int xscale_restore_context(target_t *target);
-
-int xscale_assert_reset(target_t *target);
-int xscale_deassert_reset(target_t *target);
-int xscale_soft_reset_halt(struct target_s *target);
-
-int xscale_set_reg_u32(reg_t *reg, u32 value);
-
-int xscale_read_core_reg(struct target_s *target, int num, enum armv4_5_mode mode);
-int xscale_write_core_reg(struct target_s *target, int num, enum armv4_5_mode mode, u32 value);
-
-int xscale_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
-int xscale_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
-int xscale_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffer);
-
-int xscale_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
-int xscale_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
-int xscale_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
-int xscale_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
-int xscale_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint);
-int xscale_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint);
-void xscale_enable_watchpoints(struct target_s *target);
-void xscale_enable_breakpoints(struct target_s *target);
-static int xscale_virt2phys(struct target_s *target, u32 virtual, u32 *physical);
-static int xscale_mmu(struct target_s *target, int *enabled);
-
-int xscale_read_trace(target_t *target);
-
-target_type_t xscale_target =
-{
-       .name = "xscale",
-
-       .poll = xscale_poll,
-       .arch_state = xscale_arch_state,
-
-       .target_request_data = NULL,
-
-       .halt = xscale_halt,
-       .resume = xscale_resume,
-       .step = xscale_step,
-
-       .assert_reset = xscale_assert_reset,
-       .deassert_reset = xscale_deassert_reset,
-       .soft_reset_halt = xscale_soft_reset_halt,
-
-       .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
-
-       .read_memory = xscale_read_memory,
-       .write_memory = xscale_write_memory,
-       .bulk_write_memory = xscale_bulk_write_memory,
-       .checksum_memory = arm7_9_checksum_memory,
-       .blank_check_memory = arm7_9_blank_check_memory,
-
-       .run_algorithm = armv4_5_run_algorithm,
-
-       .add_breakpoint = xscale_add_breakpoint,
-       .remove_breakpoint = xscale_remove_breakpoint,
-       .add_watchpoint = xscale_add_watchpoint,
-       .remove_watchpoint = xscale_remove_watchpoint,
-
-       .register_commands = xscale_register_commands,
-       .target_create = xscale_target_create,
-       .init_target = xscale_init_target,
-       .quit = xscale_quit,
-
-       .virt2phys = xscale_virt2phys,
-       .mmu = xscale_mmu
-};
-
-char* xscale_reg_list[] =
+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_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 *);
+static int xscale_set_watchpoint(struct target *, struct watchpoint *);
+static int xscale_unset_breakpoint(struct target *, struct breakpoint *);
+static int xscale_read_trace(struct target *);
+
+
+/* This XScale "debug handler" is loaded into the processor's
+ * mini-ICache, which is 2K of code writable only via JTAG.
+ *
+ * FIXME  the OpenOCD "bin2char" utility currently doesn't handle
+ * binary files cleanly.  It's string oriented, and terminates them
+ * with a NUL character.  Better would be to generate the constants
+ * and let other code decide names, scoping, and other housekeeping.
+ */
+static /* unsigned const char xscale_debug_handler[] = ... */
+#include "xscale_debug.h"
+
+static char *const xscale_reg_list[] =
 {
        "XSCALE_MAINID",                /* 0 */
        "XSCALE_CACHETYPE",
@@ -158,7 +110,7 @@ char* xscale_reg_list[] =
        "XSCALE_TXRXCTRL",
 };
 
-xscale_reg_t xscale_reg_arch_info[] =
+static const struct xscale_reg xscale_reg_arch_info[] =
 {
        {XSCALE_MAINID, NULL},
        {XSCALE_CACHETYPE, NULL},
@@ -184,105 +136,86 @@ xscale_reg_t xscale_reg_arch_info[] =
        {-1, NULL}, /* TXRXCTRL implicit access via JTAG */
 };
 
-int xscale_reg_arch_type = -1;
-
-int xscale_get_reg(reg_t *reg);
-int xscale_set_reg(reg_t *reg, u8 *buf);
-
-int xscale_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, xscale_common_t **xscale_p)
+/* convenience wrapper to access XScale specific registers */
+static int xscale_set_reg_u32(struct reg *reg, uint32_t value)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
+       uint8_t buf[4];
 
-       if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
-       {
-               LOG_ERROR("target isn't an XScale target");
-               return -1;
-       }
+       buf_set_u32(buf, 0, 32, value);
 
-       if (xscale->common_magic != XSCALE_COMMON_MAGIC)
-       {
-               LOG_ERROR("target isn't an XScale target");
-               return -1;
-       }
+       return xscale_set_reg(reg, buf);
+}
 
-       *armv4_5_p = armv4_5;
-       *xscale_p = xscale;
+static const char xscale_not[] = "target is not an XScale";
 
+static int xscale_verify_pointer(struct command_context *cmd_ctx,
+               struct xscale_common *xscale)
+{
+       if (xscale->common_magic != XSCALE_COMMON_MAGIC) {
+               command_print(cmd_ctx, xscale_not);
+               return ERROR_TARGET_INVALID;
+       }
        return ERROR_OK;
 }
 
-int xscale_jtag_set_instr(jtag_tap_t *tap, u32 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)
        {
-               scan_field_t field;
+               struct scan_field field;
+               uint8_t scratch[4];
 
-               field.tap = tap;
+               memset(&field, 0, sizeof field);
                field.num_bits = tap->ir_length;
-               field.out_value = calloc(CEIL(field.num_bits, 8), 1);
-               buf_set_u32(field.out_value, 0, field.num_bits, new_instr);
-               field.out_mask = NULL;
-               field.in_value = NULL;
-               jtag_set_check_value(&field, tap->expected, tap->expected_mask, NULL);
+               field.out_value = scratch;
+               buf_set_u32(scratch, 0, field.num_bits, new_instr);
 
-               jtag_add_ir_scan(1, &field, TAP_INVALID);
-
-               free(field.out_value);
+               jtag_add_ir_scan(tap, &field, end_state);
        }
 
        return ERROR_OK;
 }
 
-int xscale_read_dcsr(target_t *target)
+static int xscale_read_dcsr(struct target *target)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
-
+       struct xscale_common *xscale = target_to_xscale(target);
        int retval;
-
-       scan_field_t fields[3];
-       u8 field0 = 0x0;
-       u8 field0_check_value = 0x2;
-       u8 field0_check_mask = 0x7;
-       u8 field2 = 0x0;
-       u8 field2_check_value = 0x0;
-       u8 field2_check_mask = 0x1;
-
-       jtag_add_end_state(TAP_DRPAUSE);
-       xscale_jtag_set_instr(xscale->jtag_info.tap, xscale->jtag_info.dcsr);
+       struct scan_field fields[3];
+       uint8_t field0 = 0x0;
+       uint8_t field0_check_value = 0x2;
+       uint8_t field0_check_mask = 0x7;
+       uint8_t field2 = 0x0;
+       uint8_t field2_check_value = 0x0;
+       uint8_t field2_check_mask = 0x1;
+
+       xscale_jtag_set_instr(target->tap,
+               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);
 
-       fields[0].tap = xscale->jtag_info.tap;
+       memset(&fields, 0, sizeof fields);
+
        fields[0].num_bits = 3;
        fields[0].out_value = &field0;
-       fields[0].out_mask = NULL;
-       fields[0].in_value = NULL;
-       jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, NULL);
+       uint8_t tmp;
+       fields[0].in_value = &tmp;
 
-       fields[1].tap = xscale->jtag_info.tap;
        fields[1].num_bits = 32;
-       fields[1].out_value = NULL;
-       fields[1].out_mask = NULL;
        fields[1].in_value = xscale->reg_cache->reg_list[XSCALE_DCSR].value;
-       fields[1].in_handler = NULL;
-       fields[1].in_handler_priv = NULL;
-       fields[1].in_check_value = NULL;
-       fields[1].in_check_mask = NULL;
 
-       fields[2].tap = xscale->jtag_info.tap;
        fields[2].num_bits = 1;
        fields[2].out_value = &field2;
-       fields[2].out_mask = NULL;
-       fields[2].in_value = NULL;
-       jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, NULL);
+       uint8_t tmp2;
+       fields[2].in_value = &tmp2;
+
+       jtag_add_dr_scan(target->tap, 3, fields, TAP_DRPAUSE);
 
-       jtag_add_dr_scan(3, fields, TAP_INVALID);
+       jtag_check_value_mask(fields + 0, &field0_check_value, &field0_check_mask);
+       jtag_check_value_mask(fields + 2, &field2_check_value, &field2_check_mask);
 
        if ((retval = jtag_execute_queue()) != ERROR_OK)
        {
@@ -300,72 +233,62 @@ int xscale_read_dcsr(target_t *target)
        fields[1].out_value = xscale->reg_cache->reg_list[XSCALE_DCSR].value;
        fields[1].in_value = NULL;
 
-       jtag_add_end_state(TAP_IDLE);
-
-       jtag_add_dr_scan(3, fields, TAP_INVALID);
+       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! */
        return jtag_execute_queue();
 }
 
-int xscale_receive(target_t *target, u32 *buffer, int num_words)
+
+static void xscale_getbuf(jtag_callback_data_t arg)
 {
-       if (num_words==0)
-               return ERROR_INVALID_ARGUMENTS;
+       uint8_t *in = (uint8_t *)arg;
+       *((uint32_t *)arg) = buf_get_u32(in, 0, 32);
+}
 
-       int retval=ERROR_OK;
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
+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];
-       scan_field_t fields[3];
-
-       u8 *field0 = malloc(num_words * 1);
-       u8 field0_check_value = 0x2;
-       u8 field0_check_mask = 0x6;
-       u32 *field1 = malloc(num_words * 4);
-       u8 field2_check_value = 0x0;
-       u8 field2_check_mask = 0x1;
+       struct scan_field fields[3];
+       uint8_t *field0 = malloc(num_words * 1);
+       uint8_t field0_check_value = 0x2;
+       uint8_t field0_check_mask = 0x6;
+       uint32_t *field1 = malloc(num_words * 4);
+       uint8_t field2_check_value = 0x0;
+       uint8_t field2_check_mask = 0x1;
        int words_done = 0;
        int words_scheduled = 0;
-
        int i;
 
        path[0] = TAP_DRSELECT;
        path[1] = TAP_DRCAPTURE;
        path[2] = TAP_DRSHIFT;
 
-       fields[0].tap = xscale->jtag_info.tap;
+       memset(&fields, 0, sizeof fields);
+
        fields[0].num_bits = 3;
-       fields[0].out_value = NULL;
-       fields[0].out_mask = NULL;
-       fields[0].in_value = NULL;
-       jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, NULL);
+       fields[0].check_value = &field0_check_value;
+       fields[0].check_mask = &field0_check_mask;
 
-       fields[1].tap = xscale->jtag_info.tap;
        fields[1].num_bits = 32;
-       fields[1].out_value = NULL;
-       fields[1].out_mask = NULL;
-       fields[1].in_value = NULL;
-       fields[1].in_handler = NULL;
-       fields[1].in_handler_priv = NULL;
-       fields[1].in_check_value = NULL;
-       fields[1].in_check_mask = NULL;
 
-       fields[2].tap = xscale->jtag_info.tap;
        fields[2].num_bits = 1;
-       fields[2].out_value = NULL;
-       fields[2].out_mask = NULL;
-       fields[2].in_value = NULL;
-       jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, NULL);
+       fields[2].check_value = &field2_check_value;
+       fields[2].check_mask = &field2_check_mask;
 
-       jtag_add_end_state(TAP_IDLE);
-       xscale_jtag_set_instr(xscale->jtag_info.tap, xscale->jtag_info.dbgtx);
-       jtag_add_runtest(1, TAP_INVALID); /* ensures that we're in the TAP_IDLE state as the above could be a no-op */
+       xscale_jtag_set_instr(target->tap,
+               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;
+       int attempts = 0;
        while (words_done < num_words)
        {
                /* schedule reads */
@@ -373,11 +296,15 @@ int xscale_receive(target_t *target, u32 *buffer, int num_words)
                for (i = words_done; i < num_words; i++)
                {
                        fields[0].in_value = &field0[i];
-                       fields[1].in_handler = buf_to_u32_handler;
-                       fields[1].in_handler_priv = (u8*)&field1[i];
 
                        jtag_add_pathmove(3, path);
-                       jtag_add_dr_scan(3, fields, TAP_IDLE);
+
+                       fields[1].in_value = (uint8_t *)(field1 + i);
+
+                       jtag_add_dr_scan_check(target->tap, 3, fields, TAP_IDLE);
+
+                       jtag_add_callback(xscale_getbuf, (jtag_callback_data_t)(field1 + i));
+
                        words_scheduled++;
                }
 
@@ -396,18 +323,18 @@ int xscale_receive(target_t *target, u32 *buffer, int num_words)
                                int j;
                                for (j = i; j < num_words - 1; j++)
                                {
-                                       field0[j] = field0[j+1];
-                                       field1[j] = field1[j+1];
+                                       field0[j] = field0[j + 1];
+                                       field1[j] = field1[j + 1];
                                }
                                words_scheduled--;
                        }
                }
-               if (words_scheduled==0)
+               if (words_scheduled == 0)
                {
                        if (attempts++==1000)
                        {
                                LOG_ERROR("Failed to receiving data from debug handler after 1000 attempts");
-                               retval=ERROR_TARGET_TIMEOUT;
+                               retval = ERROR_TARGET_TIMEOUT;
                                break;
                        }
                }
@@ -416,33 +343,30 @@ int xscale_receive(target_t *target, u32 *buffer, int num_words)
        }
 
        for (i = 0; i < num_words; i++)
-               *(buffer++) = buf_get_u32((u8*)&field1[i], 0, 32);
+               *(buffer++) = buf_get_u32((uint8_t*)&field1[i], 0, 32);
 
        free(field1);
 
        return retval;
 }
 
-int xscale_read_tx(target_t *target, int consume)
+static int xscale_read_tx(struct target *target, int consume)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
+       struct xscale_common *xscale = target_to_xscale(target);
        tap_state_t path[3];
        tap_state_t noconsume_path[6];
-
        int retval;
        struct timeval timeout, now;
+       struct scan_field fields[3];
+       uint8_t field0_in = 0x0;
+       uint8_t field0_check_value = 0x2;
+       uint8_t field0_check_mask = 0x6;
+       uint8_t field2_check_value = 0x0;
+       uint8_t field2_check_mask = 0x1;
 
-       scan_field_t fields[3];
-       u8 field0_in = 0x0;
-       u8 field0_check_value = 0x2;
-       u8 field0_check_mask = 0x6;
-       u8 field2_check_value = 0x0;
-       u8 field2_check_mask = 0x1;
-
-       jtag_add_end_state(TAP_IDLE);
-
-       xscale_jtag_set_instr(xscale->jtag_info.tap, xscale->jtag_info.dbgtx);
+       xscale_jtag_set_instr(target->tap,
+               XSCALE_DBGTX << xscale->xscale_variant,
+               TAP_IDLE);
 
        path[0] = TAP_DRSELECT;
        path[1] = TAP_DRCAPTURE;
@@ -455,29 +379,17 @@ int xscale_read_tx(target_t *target, int consume)
        noconsume_path[4] = TAP_DREXIT2;
        noconsume_path[5] = TAP_DRSHIFT;
 
-       fields[0].tap = xscale->jtag_info.tap;
+       memset(&fields, 0, sizeof fields);
+
        fields[0].num_bits = 3;
-       fields[0].out_value = NULL;
-       fields[0].out_mask = NULL;
        fields[0].in_value = &field0_in;
-       jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, NULL);
 
-       fields[1].tap = xscale->jtag_info.tap;
        fields[1].num_bits = 32;
-       fields[1].out_value = NULL;
-       fields[1].out_mask = NULL;
        fields[1].in_value = xscale->reg_cache->reg_list[XSCALE_TX].value;
-       fields[1].in_handler = NULL;
-       fields[1].in_handler_priv = NULL;
-       fields[1].in_check_value = NULL;
-       fields[1].in_check_mask = NULL;
 
-       fields[2].tap = xscale->jtag_info.tap;
        fields[2].num_bits = 1;
-       fields[2].out_value = NULL;
-       fields[2].out_mask = NULL;
-       fields[2].in_value = NULL;
-       jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, NULL);
+       uint8_t tmp;
+       fields[2].in_value = &tmp;
 
        gettimeofday(&timeout, NULL);
        timeval_add_time(&timeout, 1, 0);
@@ -492,10 +404,13 @@ int xscale_read_tx(target_t *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, 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);
 
                if ((retval = jtag_execute_queue()) != ERROR_OK)
                {
@@ -513,7 +428,7 @@ int xscale_read_tx(target_t *target, int consume)
                {
                        goto done;
                }
-               if (debug_level>=3)
+               if (debug_level >= 3)
                {
                        LOG_DEBUG("waiting 100ms");
                        alive_sleep(100); /* avoid flooding the logs */
@@ -530,50 +445,37 @@ int xscale_read_tx(target_t *target, int consume)
        return ERROR_OK;
 }
 
-int xscale_write_rx(target_t *target)
+static int xscale_write_rx(struct target *target)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
-
+       struct xscale_common *xscale = target_to_xscale(target);
        int retval;
        struct timeval timeout, now;
+       struct scan_field fields[3];
+       uint8_t field0_out = 0x0;
+       uint8_t field0_in = 0x0;
+       uint8_t field0_check_value = 0x2;
+       uint8_t field0_check_mask = 0x6;
+       uint8_t field2 = 0x0;
+       uint8_t field2_check_value = 0x0;
+       uint8_t field2_check_mask = 0x1;
 
-       scan_field_t fields[3];
-       u8 field0_out = 0x0;
-       u8 field0_in = 0x0;
-       u8 field0_check_value = 0x2;
-       u8 field0_check_mask = 0x6;
-       u8 field2 = 0x0;
-       u8 field2_check_value = 0x0;
-       u8 field2_check_mask = 0x1;
-
-       jtag_add_end_state(TAP_IDLE);
+       xscale_jtag_set_instr(target->tap,
+               XSCALE_DBGRX << xscale->xscale_variant,
+               TAP_IDLE);
 
-       xscale_jtag_set_instr(xscale->jtag_info.tap, xscale->jtag_info.dbgrx);
+       memset(&fields, 0, sizeof fields);
 
-       fields[0].tap = xscale->jtag_info.tap;
        fields[0].num_bits = 3;
        fields[0].out_value = &field0_out;
-       fields[0].out_mask = NULL;
        fields[0].in_value = &field0_in;
-       jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, NULL);
 
-       fields[1].tap = xscale->jtag_info.tap;
        fields[1].num_bits = 32;
        fields[1].out_value = xscale->reg_cache->reg_list[XSCALE_RX].value;
-       fields[1].out_mask = NULL;
-       fields[1].in_value = NULL;
-       fields[1].in_handler = NULL;
-       fields[1].in_handler_priv = NULL;
-       fields[1].in_check_value = NULL;
-       fields[1].in_check_mask = NULL;
 
-       fields[2].tap = xscale->jtag_info.tap;
        fields[2].num_bits = 1;
        fields[2].out_value = &field2;
-       fields[2].out_mask = NULL;
-       fields[2].in_value = NULL;
-       jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, NULL);
+       uint8_t tmp;
+       fields[2].in_value = &tmp;
 
        gettimeofday(&timeout, NULL);
        timeval_add_time(&timeout, 1, 0);
@@ -582,7 +484,10 @@ int xscale_write_rx(target_t *target)
        LOG_DEBUG("polling RX");
        for (;;)
        {
-               jtag_add_dr_scan(3, fields, 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);
 
                if ((retval = jtag_execute_queue()) != ERROR_OK)
                {
@@ -598,7 +503,7 @@ int xscale_write_rx(target_t *target)
                }
                if (!(field0_in & 1))
                        goto done;
-               if (debug_level>=3)
+               if (debug_level >= 3)
                {
                        LOG_DEBUG("waiting 100ms");
                        alive_sleep(100); /* avoid flooding the logs */
@@ -611,7 +516,7 @@ int xscale_write_rx(target_t *target)
 
        /* set rx_valid */
        field2 = 0x1;
-       jtag_add_dr_scan(3, fields, TAP_IDLE);
+       jtag_add_dr_scan(target->tap, 3, fields, TAP_IDLE);
 
        if ((retval = jtag_execute_queue()) != ERROR_OK)
        {
@@ -623,20 +528,17 @@ int xscale_write_rx(target_t *target)
 }
 
 /* send count elements of size byte to the debug handler */
-int xscale_send(target_t *target, u8 *buffer, int count, int size)
+static int xscale_send(struct target *target, const uint8_t *buffer, int count, int size)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
-       u32 t[3];
+       struct xscale_common *xscale = target_to_xscale(target);
+       uint32_t t[3];
        int bits[3];
-
        int retval;
-
        int done_count = 0;
 
-       jtag_add_end_state(TAP_IDLE);
-
-       xscale_jtag_set_instr(xscale->jtag_info.tap, xscale->jtag_info.dbgrx);
+       xscale_jtag_set_instr(target->tap,
+               XSCALE_DBGRX << xscale->xscale_variant,
+               TAP_IDLE);
 
        bits[0]=3;
        t[0]=0;
@@ -671,9 +573,9 @@ int xscale_send(target_t *target, u8 *buffer, int count, int size)
                        break;
                default:
                        LOG_ERROR("BUG: size neither 4, 2 nor 1");
-                       exit(-1);
+                       return ERROR_INVALID_ARGUMENTS;
                }
-               jtag_add_dr_out(xscale->jtag_info.tap,
+               jtag_add_dr_out(target->tap,
                                3,
                                bits,
                                t,
@@ -690,29 +592,25 @@ int xscale_send(target_t *target, u8 *buffer, int count, int size)
        return ERROR_OK;
 }
 
-int xscale_send_u32(target_t *target, u32 value)
+static int xscale_send_u32(struct target *target, uint32_t value)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
+       struct xscale_common *xscale = target_to_xscale(target);
 
        buf_set_u32(xscale->reg_cache->reg_list[XSCALE_RX].value, 0, 32, value);
        return xscale_write_rx(target);
 }
 
-int xscale_write_dcsr(target_t *target, int hold_rst, int ext_dbg_brk)
+static int xscale_write_dcsr(struct target *target, int hold_rst, int ext_dbg_brk)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
-
+       struct xscale_common *xscale = target_to_xscale(target);
        int retval;
-
-       scan_field_t fields[3];
-       u8 field0 = 0x0;
-       u8 field0_check_value = 0x2;
-       u8 field0_check_mask = 0x7;
-       u8 field2 = 0x0;
-       u8 field2_check_value = 0x0;
-       u8 field2_check_mask = 0x1;
+       struct scan_field fields[3];
+       uint8_t field0 = 0x0;
+       uint8_t field0_check_value = 0x2;
+       uint8_t field0_check_mask = 0x7;
+       uint8_t field2 = 0x0;
+       uint8_t field2_check_value = 0x0;
+       uint8_t field2_check_mask = 0x1;
 
        if (hold_rst != -1)
                xscale->hold_rst = hold_rst;
@@ -720,37 +618,32 @@ int xscale_write_dcsr(target_t *target, int hold_rst, int ext_dbg_brk)
        if (ext_dbg_brk != -1)
                xscale->external_debug_break = ext_dbg_brk;
 
-       jtag_add_end_state(TAP_IDLE);
-       xscale_jtag_set_instr(xscale->jtag_info.tap, xscale->jtag_info.dcsr);
+       xscale_jtag_set_instr(target->tap,
+               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);
 
-       fields[0].tap = xscale->jtag_info.tap;
+       memset(&fields, 0, sizeof fields);
+
        fields[0].num_bits = 3;
        fields[0].out_value = &field0;
-       fields[0].out_mask = NULL;
-       fields[0].in_value = NULL;
-       jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, NULL);
+       uint8_t tmp;
+       fields[0].in_value = &tmp;
 
-       fields[1].tap = xscale->jtag_info.tap;
        fields[1].num_bits = 32;
        fields[1].out_value = xscale->reg_cache->reg_list[XSCALE_DCSR].value;
-       fields[1].out_mask = NULL;
-       fields[1].in_value = NULL;
-       fields[1].in_handler = NULL;
-       fields[1].in_handler_priv = NULL;
-       fields[1].in_check_value = NULL;
-       fields[1].in_check_mask = NULL;
 
-       fields[2].tap = xscale->jtag_info.tap;
        fields[2].num_bits = 1;
        fields[2].out_value = &field2;
-       fields[2].out_mask = NULL;
-       fields[2].in_value = NULL;
-       jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, NULL);
+       uint8_t tmp2;
+       fields[2].in_value = &tmp2;
+
+       jtag_add_dr_scan(target->tap, 3, fields, TAP_IDLE);
 
-       jtag_add_dr_scan(3, fields, TAP_INVALID);
+       jtag_check_value_mask(fields + 0, &field0_check_value, &field0_check_mask);
+       jtag_check_value_mask(fields + 2, &field2_check_value, &field2_check_mask);
 
        if ((retval = jtag_execute_queue()) != ERROR_OK)
        {
@@ -765,65 +658,52 @@ int xscale_write_dcsr(target_t *target, int hold_rst, int ext_dbg_brk)
 }
 
 /* parity of the number of bits 0 if even; 1 if odd. for 32 bit words */
-unsigned int parity (unsigned int v)
+static unsigned int parity (unsigned int v)
 {
-       unsigned int ov = v;
+       // unsigned int ov = v;
        v ^= v >> 16;
        v ^= v >> 8;
        v ^= v >> 4;
        v &= 0xf;
-       LOG_DEBUG("parity of 0x%x is %i", ov, (0x6996 >> v) & 1);
+       // LOG_DEBUG("parity of 0x%x is %i", ov, (0x6996 >> v) & 1);
        return (0x6996 >> v) & 1;
 }
 
-int xscale_load_ic(target_t *target, int mini, u32 va, u32 buffer[8])
+static int xscale_load_ic(struct target *target, uint32_t va, uint32_t buffer[8])
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
-       u8 packet[4];
-       u8 cmd;
+       struct xscale_common *xscale = target_to_xscale(target);
+       uint8_t packet[4];
+       uint8_t cmd;
        int word;
+       struct scan_field fields[2];
 
-       scan_field_t fields[2];
+       LOG_DEBUG("loading miniIC at 0x%8.8" PRIx32 "", va);
 
-       LOG_DEBUG("loading miniIC at 0x%8.8x", va);
+       /* LDIC into IR */
+       xscale_jtag_set_instr(target->tap,
+               XSCALE_LDIC << xscale->xscale_variant,
+               TAP_IDLE);
 
-       jtag_add_end_state(TAP_IDLE);
-       xscale_jtag_set_instr(xscale->jtag_info.tap, xscale->jtag_info.ldic); /* LDIC */
-
-       /* CMD is b010 for Main IC and b011 for Mini IC */
-       if (mini)
-               buf_set_u32(&cmd, 0, 3, 0x3);
-       else
-               buf_set_u32(&cmd, 0, 3, 0x2);
-
-       buf_set_u32(&cmd, 3, 3, 0x0);
+       /* CMD is b011 to load a cacheline into the Mini ICache.
+        * Loading into the main ICache is deprecated, and unused.
+        * It's followed by three zero bits, and 27 address bits.
+        */
+       buf_set_u32(&cmd, 0, 6, 0x3);
 
        /* virtual address of desired cache line */
        buf_set_u32(packet, 0, 27, va >> 5);
 
-       fields[0].tap = xscale->jtag_info.tap;
+       memset(&fields, 0, sizeof fields);
+
        fields[0].num_bits = 6;
        fields[0].out_value = &cmd;
-       fields[0].out_mask = NULL;
-       fields[0].in_value = NULL;
-       fields[0].in_check_value = NULL;
-       fields[0].in_check_mask = NULL;
-       fields[0].in_handler = NULL;
-       fields[0].in_handler_priv = NULL;
-
-       fields[1].tap = xscale->jtag_info.tap;
+
        fields[1].num_bits = 27;
        fields[1].out_value = packet;
-       fields[1].out_mask = NULL;
-       fields[1].in_value = NULL;
-       fields[1].in_check_value = NULL;
-       fields[1].in_check_mask = NULL;
-       fields[1].in_handler = NULL;
-       fields[1].in_handler_priv = NULL;
 
-       jtag_add_dr_scan(2, fields, TAP_INVALID);
+       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;
        fields[0].out_value = packet;
 
@@ -833,26 +713,27 @@ int xscale_load_ic(target_t *target, int mini, u32 va, u32 buffer[8])
        for (word = 0; word < 8; word++)
        {
                buf_set_u32(packet, 0, 32, buffer[word]);
-               cmd = parity(*((u32*)packet));
-               jtag_add_dr_scan(2, fields, TAP_INVALID);
-       }
 
-       jtag_execute_queue();
+               uint32_t value;
+               memcpy(&value, packet, sizeof(uint32_t));
+               cmd = parity(value);
 
-       return ERROR_OK;
+               jtag_add_dr_scan(target->tap, 2, fields, TAP_IDLE);
+       }
+
+       return jtag_execute_queue();
 }
 
-int xscale_invalidate_ic_line(target_t *target, u32 va)
+static int xscale_invalidate_ic_line(struct target *target, uint32_t va)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
-       u8 packet[4];
-       u8 cmd;
-
-       scan_field_t fields[2];
+       struct xscale_common *xscale = target_to_xscale(target);
+       uint8_t packet[4];
+       uint8_t cmd;
+       struct scan_field fields[2];
 
-       jtag_add_end_state(TAP_IDLE);
-       xscale_jtag_set_instr(xscale->jtag_info.tap, xscale->jtag_info.ldic); /* LDIC */
+       xscale_jtag_set_instr(target->tap,
+               XSCALE_LDIC << xscale->xscale_variant,
+               TAP_IDLE);
 
        /* CMD for invalidate IC line b000, bits [6:4] b000 */
        buf_set_u32(&cmd, 0, 6, 0x0);
@@ -860,39 +741,26 @@ int xscale_invalidate_ic_line(target_t *target, u32 va)
        /* virtual address of desired cache line */
        buf_set_u32(packet, 0, 27, va >> 5);
 
-       fields[0].tap = xscale->jtag_info.tap;
+       memset(&fields, 0, sizeof fields);
+
        fields[0].num_bits = 6;
        fields[0].out_value = &cmd;
-       fields[0].out_mask = NULL;
-       fields[0].in_value = NULL;
-       fields[0].in_check_value = NULL;
-       fields[0].in_check_mask = NULL;
-       fields[0].in_handler = NULL;
-       fields[0].in_handler_priv = NULL;
-
-       fields[1].tap = xscale->jtag_info.tap;
+
        fields[1].num_bits = 27;
        fields[1].out_value = packet;
-       fields[1].out_mask = NULL;
-       fields[1].in_value = NULL;
-       fields[1].in_check_value = NULL;
-       fields[1].in_check_mask = NULL;
-       fields[1].in_handler = NULL;
-       fields[1].in_handler_priv = NULL;
 
-       jtag_add_dr_scan(2, fields, TAP_INVALID);
+       jtag_add_dr_scan(target->tap, 2, fields, TAP_IDLE);
 
        return ERROR_OK;
 }
 
-int xscale_update_vectors(target_t *target)
+static int xscale_update_vectors(struct target *target)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
+       struct xscale_common *xscale = target_to_xscale(target);
        int i;
        int retval;
 
-       u32 low_reset_branch, high_reset_branch;
+       uint32_t low_reset_branch, high_reset_branch;
 
        for (i = 1; i < 8; i++)
        {
@@ -903,10 +771,10 @@ int xscale_update_vectors(target_t *target)
                }
                else
                {
-                       retval=target_read_u32(target, 0xffff0000 + 4*i, &xscale->high_vectors[i]);
+                       retval = target_read_u32(target, 0xffff0000 + 4*i, &xscale->high_vectors[i]);
                        if (retval == ERROR_TARGET_TIMEOUT)
                                return retval;
-                       if (retval!=ERROR_OK)
+                       if (retval != ERROR_OK)
                        {
                                /* Some of these reads will fail as part of normal execution */
                                xscale->high_vectors[i] = ARMV4_5_B(0xfffffe, 0);
@@ -922,10 +790,10 @@ int xscale_update_vectors(target_t *target)
                }
                else
                {
-                       retval=target_read_u32(target, 0x0 + 4*i, &xscale->low_vectors[i]);
+                       retval = target_read_u32(target, 0x0 + 4*i, &xscale->low_vectors[i]);
                        if (retval == ERROR_TARGET_TIMEOUT)
                                return retval;
-                       if (retval!=ERROR_OK)
+                       if (retval != ERROR_OK)
                        {
                                /* Some of these reads will fail as part of normal execution */
                                xscale->low_vectors[i] = ARMV4_5_B(0xfffffe, 0);
@@ -944,42 +812,35 @@ int xscale_update_vectors(target_t *target)
        xscale_invalidate_ic_line(target, 0x0);
        xscale_invalidate_ic_line(target, 0xffff0000);
 
-       xscale_load_ic(target, 1, 0x0, xscale->low_vectors);
-       xscale_load_ic(target, 1, 0xffff0000, xscale->high_vectors);
+       xscale_load_ic(target, 0x0, xscale->low_vectors);
+       xscale_load_ic(target, 0xffff0000, xscale->high_vectors);
 
        return ERROR_OK;
 }
 
-int xscale_arch_state(struct target_s *target)
+static int xscale_arch_state(struct target *target)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
+       struct xscale_common *xscale = target_to_xscale(target);
+       struct arm *armv4_5 = &xscale->armv4_5_common;
 
-       char *state[] =
+       static const char *state[] =
        {
                "disabled", "enabled"
        };
 
-       char *arch_dbg_reason[] =
+       static const char *arch_dbg_reason[] =
        {
                "", "\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");
-               exit(-1);
+               return ERROR_INVALID_ARGUMENTS;
        }
 
-       LOG_USER("target halted in %s state due to %s, current mode: %s\n"
-                       "cpsr: 0x%8.8x pc: 0x%8.8x\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 ,
-                        armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)],
-                        buf_get_u32(armv4_5->core_cache->reg_list[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],
@@ -988,11 +849,9 @@ int xscale_arch_state(struct target_s *target)
        return ERROR_OK;
 }
 
-int xscale_poll(target_t *target)
+static int xscale_poll(struct target *target)
 {
-       int retval=ERROR_OK;
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
+       int retval = ERROR_OK;
 
        if ((target->state == TARGET_RUNNING) || (target->state == TARGET_DEBUG_RUNNING))
        {
@@ -1001,8 +860,6 @@ int xscale_poll(target_t *target)
                {
 
                        /* there's data to read from the tx register, we entered debug state */
-                       xscale->handler_running = 1;
-
                        target->state = TARGET_HALTED;
 
                        /* process debug entry, fetching current mode regs */
@@ -1032,37 +889,36 @@ int xscale_poll(target_t *target)
        return retval;
 }
 
-int xscale_debug_entry(target_t *target)
+static int xscale_debug_entry(struct target *target)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
-       u32 pc;
-       u32 buffer[10];
-       int i;
+       struct xscale_common *xscale = target_to_xscale(target);
+       struct arm *armv4_5 = &xscale->armv4_5_common;
+       uint32_t pc;
+       uint32_t buffer[10];
+       unsigned i;
        int retval;
-
-       u32 moe;
+       uint32_t moe;
 
        /* clear external dbg break (will be written on next DCSR read) */
        xscale->external_debug_break = 0;
-       if ((retval=xscale_read_dcsr(target))!=ERROR_OK)
+       if ((retval = xscale_read_dcsr(target)) != ERROR_OK)
                return retval;
 
        /* get r0, pc, r1 to r7 and cpsr */
-       if ((retval=xscale_receive(target, buffer, 10))!=ERROR_OK)
+       if ((retval = xscale_receive(target, buffer, 10)) != ERROR_OK)
                return retval;
 
        /* move r0 from buffer to register cache */
        buf_set_u32(armv4_5->core_cache->reg_list[0].value, 0, 32, buffer[0]);
-       armv4_5->core_cache->reg_list[15].dirty = 1;
-       armv4_5->core_cache->reg_list[15].valid = 1;
-       LOG_DEBUG("r0: 0x%8.8x", buffer[0]);
+       armv4_5->core_cache->reg_list[0].dirty = 1;
+       armv4_5->core_cache->reg_list[0].valid = 1;
+       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;
-       LOG_DEBUG("pc: 0x%8.8x", buffer[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 */
        for (i = 1; i <= 7; i++)
@@ -1070,39 +926,27 @@ int xscale_debug_entry(target_t *target)
                buf_set_u32(armv4_5->core_cache->reg_list[i].value, 0, 32, buffer[1 + i]);
                armv4_5->core_cache->reg_list[i].dirty = 1;
                armv4_5->core_cache->reg_list[i].valid = 1;
-               LOG_DEBUG("r%i: 0x%8.8x", i, buffer[i + 1]);
+               LOG_DEBUG("r%i: 0x%8.8" PRIx32 "", i, buffer[i + 1]);
        }
 
-       buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32, buffer[9]);
-       armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
-       armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
-       LOG_DEBUG("cpsr: 0x%8.8x", buffer[9]);
+       arm_set_cpsr(armv4_5, buffer[9]);
+       LOG_DEBUG("cpsr: 0x%8.8" PRIx32 "", buffer[9]);
 
-       armv4_5->core_mode = buffer[9] & 0x1f;
-       if (armv4_5_mode_to_number(armv4_5->core_mode) == -1)
+       if (!is_arm_mode(armv4_5->core_mode))
        {
                target->state = TARGET_UNKNOWN;
                LOG_ERROR("cpsr contains invalid mode value - communication failure");
                return ERROR_TARGET_FAILURE;
        }
-       LOG_DEBUG("target entered debug state in %s mode", armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)]);
-
-       if (buffer[9] & 0x20)
-               armv4_5->core_state = ARMV4_5_STATE_THUMB;
-       else
-               armv4_5->core_state = ARMV4_5_STATE_ARM;
-
-
-       if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
-               return ERROR_FAIL;
+       LOG_DEBUG("target entered debug state in %s mode",
+                        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
        {
@@ -1110,20 +954,27 @@ int xscale_debug_entry(target_t *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;
        }
 
+       /* 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)
        {
@@ -1162,7 +1013,7 @@ int xscale_debug_entry(target_t *target)
                        xscale->arch_debug_reason = XSCALE_DBG_REASON_TB_FULL;
                        pc -= 4;
                        break;
-               case 0x7: /* Reserved */
+               case 0x7: /* Reserved (may flag Hot-Debug support) */
                default:
                        LOG_ERROR("Method of Entry is 'Reserved'");
                        exit(-1);
@@ -1170,12 +1021,12 @@ int xscale_debug_entry(target_t *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)
        {
-               u32 cache_type_reg;
+               uint32_t cache_type_reg;
 
                /* read cp15 cache type register */
                xscale_get_reg(&xscale->reg_cache->reg_list[XSCALE_CACHETYPE]);
@@ -1193,33 +1044,31 @@ int xscale_debug_entry(target_t *target)
        xscale->armv4_5_mmu.armv4_5_cache.i_cache_enabled = (xscale->cp15_control_reg & 0x1000U) ? 1 : 0;
 
        /* tracing enabled, read collected trace data */
-       if (xscale->trace.buffer_enabled)
+       if (xscale->trace.mode != XSCALE_TRACE_DISABLED)
        {
                xscale_read_trace(target);
-               xscale->trace.buffer_fill--;
 
-               /* resume if we're still collecting trace data */
-               if ((xscale->arch_debug_reason == XSCALE_DBG_REASON_TB_FULL)
-                       && (xscale->trace.buffer_fill > 0))
+               /* Resume if entered debug due to buffer fill and we're still collecting
+                * trace data.  Note that a debug exception due to trace buffer full
+                * can only happen in fill mode. */
+               if (xscale->arch_debug_reason == XSCALE_DBG_REASON_TB_FULL)
                {
+                 if (--xscale->trace.fill_counter > 0)
                        xscale_resume(target, 1, 0x0, 1, 0);
                }
-               else
-               {
-                       xscale->trace.buffer_enabled = 0;
-               }
+               else    /* entered debug for other reason; reset counter */
+                 xscale->trace.fill_counter = 0;
        }
 
        return ERROR_OK;
 }
 
-int xscale_halt(target_t *target)
+static int xscale_halt(struct target *target)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
+       struct xscale_common *xscale = target_to_xscale(target);
 
        LOG_DEBUG("target->state: %s",
-                 Jim_Nvp_value2name_simple( nvp_target_state, target->state )->name);
+                 target_state_name(target));
 
        if (target->state == TARGET_HALTED)
        {
@@ -1248,16 +1097,15 @@ int xscale_halt(target_t *target)
        return ERROR_OK;
 }
 
-int xscale_enable_single_step(struct target_s *target, u32 next_pc)
+static int xscale_enable_single_step(struct target *target, uint32_t next_pc)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale= armv4_5->arch_info;
-       reg_t *ibcr0 = &xscale->reg_cache->reg_list[XSCALE_IBCR0];
+       struct xscale_common *xscale = target_to_xscale(target);
+       struct reg *ibcr0 = &xscale->reg_cache->reg_list[XSCALE_IBCR0];
        int retval;
 
        if (xscale->ibcr0_used)
        {
-               breakpoint_t *ibcr0_bp = breakpoint_find(target, buf_get_u32(ibcr0->value, 0, 32) & 0xfffffffe);
+               struct breakpoint *ibcr0_bp = breakpoint_find(target, buf_get_u32(ibcr0->value, 0, 32) & 0xfffffffe);
 
                if (ibcr0_bp)
                {
@@ -1270,33 +1118,70 @@ int xscale_enable_single_step(struct target_s *target, u32 next_pc)
                }
        }
 
-       if ((retval=xscale_set_reg_u32(ibcr0, next_pc | 0x1))!=ERROR_OK)
+       if ((retval = xscale_set_reg_u32(ibcr0, next_pc | 0x1)) != ERROR_OK)
                return retval;
 
        return ERROR_OK;
 }
 
-int xscale_disable_single_step(struct target_s *target)
+static int xscale_disable_single_step(struct target *target)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale= armv4_5->arch_info;
-       reg_t *ibcr0 = &xscale->reg_cache->reg_list[XSCALE_IBCR0];
+       struct xscale_common *xscale = target_to_xscale(target);
+       struct reg *ibcr0 = &xscale->reg_cache->reg_list[XSCALE_IBCR0];
        int retval;
 
-       if ((retval=xscale_set_reg_u32(ibcr0, 0x0))!=ERROR_OK)
+       if ((retval = xscale_set_reg_u32(ibcr0, 0x0)) != ERROR_OK)
                return retval;
 
        return ERROR_OK;
 }
 
-int xscale_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution)
+static void xscale_enable_watchpoints(struct target *target)
+{
+       struct watchpoint *watchpoint = target->watchpoints;
+
+       while (watchpoint)
+       {
+               if (watchpoint->set == 0)
+                       xscale_set_watchpoint(target, watchpoint);
+               watchpoint = watchpoint->next;
+       }
+}
+
+static void xscale_enable_breakpoints(struct target *target)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale= armv4_5->arch_info;
-       breakpoint_t *breakpoint = target->breakpoints;
+       struct breakpoint *breakpoint = target->breakpoints;
+
+       /* set any pending breakpoints */
+       while (breakpoint)
+       {
+               if (breakpoint->set == 0)
+                       xscale_set_breakpoint(target, breakpoint);
+               breakpoint = breakpoint->next;
+       }
+}
 
-       u32 current_pc;
+static void xscale_free_trace_data(struct xscale_common *xscale)
+{
+   struct xscale_trace_data *td = xscale->trace.data;
+   while (td)
+   {
+         struct xscale_trace_data *next_td = td->next;
+         if (td->entries)
+                free(td->entries);
+         free(td);
+         td = next_td;
+   }
+   xscale->trace.data = NULL;
+}
 
+static int xscale_resume(struct target *target, int current,
+               uint32_t address, int handle_breakpoints, int debug_execution)
+{
+       struct xscale_common *xscale = target_to_xscale(target);
+       struct arm *armv4_5 = &xscale->armv4_5_common;
+       struct breakpoint *breakpoint = target->breakpoints;
+       uint32_t current_pc;
        int retval;
        int i;
 
@@ -1314,79 +1199,86 @@ int xscale_resume(struct target_s *target, int current, u32 address, int handle_
        }
 
        /* update vector tables */
-       if ((retval=xscale_update_vectors(target))!=ERROR_OK)
+       if ((retval = xscale_update_vectors(target)) != ERROR_OK)
                return retval;
 
        /* 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)
                {
-                       u32 next_pc;
+                       uint32_t next_pc;
+                       enum trace_mode saved_trace_mode;
 
                        /* there's a breakpoint at the current PC, we have to step over it */
-                       LOG_DEBUG("unset breakpoint at 0x%8.8x", breakpoint->address);
+                       LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 "", breakpoint->address);
                        xscale_unset_breakpoint(target, breakpoint);
 
                        /* calculate PC of next instruction */
                        if ((retval = arm_simulate_step(target, &next_pc)) != ERROR_OK)
                        {
-                               u32 current_opcode;
+                               uint32_t current_opcode;
                                target_read_u32(target, current_pc, &current_opcode);
-                               LOG_ERROR("BUG: couldn't calculate PC of next instruction, current opcode was 0x%8.8x", current_opcode);
+                               LOG_ERROR("BUG: couldn't calculate PC of next instruction, current opcode was 0x%8.8" PRIx32 "", current_opcode);
                        }
 
                        LOG_DEBUG("enable single-step");
                        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) */
-                       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, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32));
-                       LOG_DEBUG("writing cpsr with value 0x%8.8x", buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32));
+                       xscale_send_u32(target,
+                               buf_get_u32(armv4_5->cpsr->value, 0, 32));
+                       LOG_DEBUG("writing cpsr with value 0x%8.8" PRIx32,
+                               buf_get_u32(armv4_5->cpsr->value, 0, 32));
 
                        for (i = 7; i >= 0; i--)
                        {
                                /* send register */
                                xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[i].value, 0, 32));
-                               LOG_DEBUG("writing r%i with value 0x%8.8x", i, buf_get_u32(armv4_5->core_cache->reg_list[i].value, 0, 32));
+                               LOG_DEBUG("writing r%i with value 0x%8.8" PRIx32 "", i, buf_get_u32(armv4_5->core_cache->reg_list[i].value, 0, 32));
                        }
 
                        /* 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.8x", 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_mode = xscale->trace.mode;
+                       xscale->trace.mode = XSCALE_TRACE_DISABLED;
 
                        /* wait for and process debug entry */
                        xscale_debug_entry(target);
 
+                       /* re-enable trace buffer, if enabled previously */
+                       xscale->trace.mode = saved_trace_mode;
+
                        LOG_DEBUG("disable single-step");
                        xscale_disable_single_step(target);
 
-                       LOG_DEBUG("set breakpoint at 0x%8.8x", breakpoint->address);
+                       LOG_DEBUG("set breakpoint at 0x%8.8" PRIx32 "", breakpoint->address);
                        xscale_set_breakpoint(target, breakpoint);
                }
        }
@@ -1396,12 +1288,25 @@ int xscale_resume(struct target_s *target, int current, u32 address, int handle_
        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) */
-       if (xscale->trace.buffer_enabled)
+       if (xscale->trace.mode != XSCALE_TRACE_DISABLED)
        {
+               if (xscale->trace.mode == XSCALE_TRACE_FILL)
+               {
+                  /* If trace enabled in fill mode and starting collection of new set
+                       * of buffers, initialize buffer counter and free previous buffers */
+                  if (xscale->trace.fill_counter == 0)
+                  {
+                         xscale->trace.fill_counter = xscale->trace.buffer_fill;
+                         xscale_free_trace_data(xscale);
+                  }
+               }
+               else     /* wrap mode; free previous buffer */
+                  xscale_free_trace_data(xscale);
+
                xscale_send_u32(target, 0x62);
                xscale_send_u32(target, 0x31);
        }
@@ -1409,26 +1314,28 @@ int xscale_resume(struct target_s *target, int current, u32 address, int handle_
                xscale_send_u32(target, 0x30);
 
        /* send CPSR */
-       xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32));
-       LOG_DEBUG("writing cpsr with value 0x%8.8x", buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32));
+       xscale_send_u32(target, buf_get_u32(armv4_5->cpsr->value, 0, 32));
+       LOG_DEBUG("writing cpsr with value 0x%8.8" PRIx32,
+                       buf_get_u32(armv4_5->cpsr->value, 0, 32));
 
        for (i = 7; i >= 0; i--)
        {
                /* send register */
                xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[i].value, 0, 32));
-               LOG_DEBUG("writing r%i with value 0x%8.8x", i, buf_get_u32(armv4_5->core_cache->reg_list[i].value, 0, 32));
+               LOG_DEBUG("writing r%i with value 0x%8.8" PRIx32 "", i, buf_get_u32(armv4_5->core_cache->reg_list[i].value, 0, 32));
        }
 
        /* 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.8x", 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;
 
        if (!debug_execution)
        {
                /* registers are now invalid */
-               armv4_5_invalidate_core_regs(target);
+               register_cache_invalidate(armv4_5->core_cache);
                target->state = TARGET_RUNNING;
                target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
        }
@@ -1440,17 +1347,15 @@ int xscale_resume(struct target_s *target, int current, u32 address, int handle_
 
        LOG_DEBUG("target resumed");
 
-       xscale->handler_running = 1;
-
        return ERROR_OK;
 }
 
-static int xscale_step_inner(struct target_s *target, int current, u32 address, int handle_breakpoints)
+static int xscale_step_inner(struct target *target, int current,
+               uint32_t address, int handle_breakpoints)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
-
-       u32 next_pc;
+       struct xscale_common *xscale = target_to_xscale(target);
+       struct arm *armv4_5 = &xscale->armv4_5_common;
+       uint32_t next_pc;
        int retval;
        int i;
 
@@ -1459,65 +1364,70 @@ static int xscale_step_inner(struct target_s *target, int current, u32 address,
        /* calculate PC of next instruction */
        if ((retval = arm_simulate_step(target, &next_pc)) != ERROR_OK)
        {
-               u32 current_opcode, current_pc;
-               current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
+               uint32_t current_opcode, current_pc;
+               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.8x", current_opcode);
+               LOG_ERROR("BUG: couldn't calculate PC of next instruction, current opcode was 0x%8.8" PRIx32 "", current_opcode);
                return retval;
        }
 
        LOG_DEBUG("enable single-step");
-       if ((retval=xscale_enable_single_step(target, next_pc))!=ERROR_OK)
+       if ((retval = xscale_enable_single_step(target, next_pc)) != ERROR_OK)
                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)
         * clean the trace buffer if it is to be enabled (0x62) */
-       if (xscale->trace.buffer_enabled)
+       if (xscale->trace.mode != XSCALE_TRACE_DISABLED)
        {
-               if ((retval=xscale_send_u32(target, 0x62))!=ERROR_OK)
+               if ((retval = xscale_send_u32(target, 0x62)) != ERROR_OK)
                        return retval;
-               if ((retval=xscale_send_u32(target, 0x31))!=ERROR_OK)
+               if ((retval = xscale_send_u32(target, 0x31)) != ERROR_OK)
                        return retval;
        }
        else
-               if ((retval=xscale_send_u32(target, 0x30))!=ERROR_OK)
+               if ((retval = xscale_send_u32(target, 0x30)) != ERROR_OK)
                        return retval;
 
        /* send CPSR */
-       if ((retval=xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32)))!=ERROR_OK)
+       retval = xscale_send_u32(target,
+                       buf_get_u32(armv4_5->cpsr->value, 0, 32));
+       if (retval != ERROR_OK)
                return retval;
-       LOG_DEBUG("writing cpsr with value 0x%8.8x", buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32));
+       LOG_DEBUG("writing cpsr with value 0x%8.8" PRIx32,
+                       buf_get_u32(armv4_5->cpsr->value, 0, 32));
 
        for (i = 7; i >= 0; i--)
        {
                /* send register */
-               if ((retval=xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[i].value, 0, 32)))!=ERROR_OK)
+               if ((retval = xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[i].value, 0, 32))) != ERROR_OK)
                        return retval;
-               LOG_DEBUG("writing r%i with value 0x%8.8x", i, buf_get_u32(armv4_5->core_cache->reg_list[i].value, 0, 32));
+               LOG_DEBUG("writing r%i with value 0x%8.8" PRIx32 "", i, buf_get_u32(armv4_5->core_cache->reg_list[i].value, 0, 32));
        }
 
        /* 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.8x", 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);
 
        /* registers are now invalid */
-       if ((retval=armv4_5_invalidate_core_regs(target))!=ERROR_OK)
-               return retval;
+       register_cache_invalidate(armv4_5->core_cache);
 
        /* wait for and process debug entry */
-       if ((retval=xscale_debug_entry(target))!=ERROR_OK)
+       if ((retval = xscale_debug_entry(target)) != ERROR_OK)
                return retval;
 
        LOG_DEBUG("disable single-step");
-       if ((retval=xscale_disable_single_step(target))!=ERROR_OK)
+       if ((retval = xscale_disable_single_step(target)) != ERROR_OK)
                return retval;
 
        target_call_event_callbacks(target, TARGET_EVENT_HALTED);
@@ -1525,12 +1435,13 @@ static int xscale_step_inner(struct target_s *target, int current, u32 address,
        return ERROR_OK;
 }
 
-int xscale_step(struct target_s *target, int current, u32 address, int handle_breakpoints)
+static int xscale_step(struct target *target, int current,
+               uint32_t address, int handle_breakpoints)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       breakpoint_t *breakpoint = target->breakpoints;
+       struct arm *armv4_5 = target_to_arm(target);
+       struct breakpoint *breakpoint = NULL;
 
-       u32 current_pc;
+       uint32_t current_pc;
        int retval;
 
        if (target->state != TARGET_HALTED)
@@ -1541,16 +1452,16 @@ int xscale_step(struct target_s *target, int current, u32 address, int handle_br
 
        /* 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)
+               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);
@@ -1560,11 +1471,13 @@ int xscale_step(struct target_s *target, int current, u32 address, int handle_br
 
        /* 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);
 
@@ -1579,19 +1492,19 @@ int xscale_step(struct target_s *target, int current, u32 address, int handle_br
 
 }
 
-int xscale_assert_reset(target_t *target)
+static int xscale_assert_reset(struct target *target)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
+       struct xscale_common *xscale = target_to_xscale(target);
 
        LOG_DEBUG("target->state: %s",
-                 Jim_Nvp_value2name_simple( nvp_target_state, target->state )->name);
+                 target_state_name(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_add_end_state(TAP_IDLE);
-       xscale_jtag_set_instr(xscale->jtag_info.tap, xscale->jtag_info.dcsr);
+       xscale_jtag_set_instr(target->tap,
+               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);
@@ -1599,7 +1512,7 @@ int xscale_assert_reset(target_t *target)
        xscale_write_dcsr(target, 1, 0);
 
        /* select BYPASS, because having DCSR selected caused problems on the PXA27x */
-       xscale_jtag_set_instr(xscale->jtag_info.tap, 0x7f);
+       xscale_jtag_set_instr(target->tap, ~0, TAP_IDLE);
        jtag_execute_queue();
 
        /* assert reset */
@@ -1614,27 +1527,17 @@ int xscale_assert_reset(target_t *target)
     if (target->reset_halt)
     {
        int retval;
-               if ((retval = target_halt(target))!=ERROR_OK)
+               if ((retval = target_halt(target)) != ERROR_OK)
                        return retval;
     }
 
        return ERROR_OK;
 }
 
-int xscale_deassert_reset(target_t *target)
+static int xscale_deassert_reset(struct target *target)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
-
-       fileio_t debug_handler;
-       u32 address;
-       u32 binary_size;
-
-       u32 buf_cnt;
-       u32 i;
-       int retval;
-
-       breakpoint_t *breakpoint = target->breakpoints;
+       struct xscale_common *xscale = target_to_xscale(target);
+       struct breakpoint *breakpoint = target->breakpoints;
 
        LOG_DEBUG("-");
 
@@ -1656,8 +1559,26 @@ int xscale_deassert_reset(target_t *target)
                breakpoint = breakpoint->next;
        }
 
-       if (!xscale->handler_installed)
+       xscale->trace.mode = XSCALE_TRACE_DISABLED;
+       xscale_free_trace_data(xscale);
+
+       register_cache_invalidate(xscale->armv4_5_common.core_cache);
+
+       /* FIXME mark hardware watchpoints got unset too.  Also,
+        * at least some of the XScale registers are invalid...
+        */
+
+       /*
+        * REVISIT:  *assumes* we had a SRST+TRST reset so the mini-icache
+        * contents got invalidated.  Safer to force that, so writing new
+        * contents can't ever fail..
+        */
        {
+               uint32_t address;
+               unsigned buf_cnt;
+               const uint8_t *buffer = xscale_debug_handler;
+               int retval;
+
                /* release SRST */
                jtag_add_reset(0, 0);
 
@@ -1672,60 +1593,54 @@ int xscale_deassert_reset(target_t *target)
                buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 16, 1, 0x1);
                xscale_write_dcsr(target, 1, 0);
 
-               /* Load debug handler */
-               if (fileio_open(&debug_handler, "xscale/debug_handler.bin", FILEIO_READ, FILEIO_BINARY) != ERROR_OK)
-               {
-                       return ERROR_OK;
-               }
-
-               if ((binary_size = debug_handler.size) % 4)
-               {
-                       LOG_ERROR("debug_handler.bin: size not a multiple of 4");
-                       exit(-1);
-               }
-
-               if (binary_size > 0x800)
-               {
-                       LOG_ERROR("debug_handler.bin: larger than 2kb");
-                       exit(-1);
-               }
-
-               binary_size = CEIL(binary_size, 32) * 32;
-
+               /* Load the debug handler into the mini-icache.  Since
+                * it's using halt mode (not monitor mode), it runs in
+                * "Special Debug State" for access to registers, memory,
+                * coprocessors, trace data, etc.
+                */
                address = xscale->handler_address;
-               while (binary_size > 0)
+               for (unsigned binary_size = sizeof xscale_debug_handler - 1;
+                               binary_size > 0;
+                               binary_size -= buf_cnt, buffer += buf_cnt)
                {
-                       u32 cache_line[8];
-                       u8 buffer[32];
+                       uint32_t cache_line[8];
+                       unsigned i;
 
-                       if ((retval = fileio_read(&debug_handler, 32, buffer, &buf_cnt)) != ERROR_OK)
-                       {
-
-                       }
+                       buf_cnt = binary_size;
+                       if (buf_cnt > 32)
+                               buf_cnt = 32;
 
                        for (i = 0; i < buf_cnt; i += 4)
                        {
-                               /* convert LE buffer to host-endian u32 */
+                               /* convert LE buffer to host-endian uint32_t */
                                cache_line[i / 4] = le_to_h_u32(&buffer[i]);
                        }
 
-                       for (; buf_cnt < 32; buf_cnt += 4)
+                       for (; i < 32; i += 4)
                        {
-                               cache_line[buf_cnt / 4] = 0xe1a08008;
+                               cache_line[i / 4] = 0xe1a08008;
                        }
 
                        /* only load addresses other than the reset vectors */
                        if ((address % 0x400) != 0x0)
                        {
-                               xscale_load_ic(target, 1, address, cache_line);
+                               retval = xscale_load_ic(target, address,
+                                               cache_line);
+                               if (retval != ERROR_OK)
+                                       return retval;
                        }
 
                        address += buf_cnt;
-                       binary_size -= buf_cnt;
                };
 
-               xscale_load_ic(target, 1, 0x0, xscale->low_vectors);
-               xscale_load_ic(target, 1, 0xffff0000, xscale->high_vectors);
+               retval = xscale_load_ic(target, 0x0,
+                                       xscale->low_vectors);
+               if (retval != ERROR_OK)
+                       return retval;
+               retval = xscale_load_ic(target, 0xffff0000,
+                                       xscale->high_vectors);
+               if (retval != ERROR_OK)
+                       return retval;
 
                jtag_add_runtest(30, TAP_IDLE);
 
@@ -1751,38 +1666,32 @@ int xscale_deassert_reset(target_t *target)
                        /* resume the target */
                        xscale_resume(target, 1, 0x0, 1, 0);
                }
-
-               fileio_close(&debug_handler);
-       }
-       else
-       {
-               jtag_add_reset(0, 0);
        }
 
        return ERROR_OK;
 }
 
-int xscale_soft_reset_halt(struct target_s *target)
-{
-       return ERROR_OK;
-}
-
-int xscale_read_core_reg(struct target_s *target, int num, enum armv4_5_mode mode)
+static int xscale_read_core_reg(struct target *target, struct reg *r,
+               int num, enum arm_mode mode)
 {
+       /** \todo add debug handler support for core register reads */
+       LOG_ERROR("not implemented");
        return ERROR_OK;
 }
 
-int xscale_write_core_reg(struct target_s *target, int num, enum armv4_5_mode mode, u32 value)
+static int xscale_write_core_reg(struct target *target, struct reg *r,
+               int num, enum arm_mode mode, uint32_t value)
 {
-
+       /** \todo add debug handler support for core register writes */
+       LOG_ERROR("not implemented");
        return ERROR_OK;
 }
 
-int xscale_full_context(target_t *target)
+static int xscale_full_context(struct target *target)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
+       struct arm *armv4_5 = target_to_arm(target);
 
-       u32 *buffer;
+       uint32_t *buffer;
 
        int i, j;
 
@@ -1800,52 +1709,58 @@ int xscale_full_context(target_t *target)
         * we can't enter User mode on an XScale (unpredictable),
         * but User shares registers with SYS
         */
-       for(i = 1; i < 7; i++)
+       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)
-               {
-                       u32 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;
                }
        }
 
@@ -1854,14 +1769,12 @@ int xscale_full_context(target_t *target)
        return ERROR_OK;
 }
 
-int xscale_restore_context(target_t *target)
+static int xscale_restore_banked(struct target *target)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
+       struct arm *armv4_5 = target_to_arm(target);
 
        int i, j;
 
-       LOG_DEBUG("-");
-
        if (target->state != TARGET_HALTED)
        {
                LOG_WARNING("target not halted");
@@ -1869,69 +1782,75 @@ int xscale_restore_context(target_t *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
-       */
-       for(i = 1; i < 7; i++)
+        * 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)
-               {
-                       u32 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;
                }
        }
 
        return ERROR_OK;
 }
 
-int xscale_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
+static int xscale_read_memory(struct target *target, uint32_t address,
+               uint32_t size, uint32_t count, uint8_t *buffer)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
-       u32 *buf32;
-       u32 i;
+       struct xscale_common *xscale = target_to_xscale(target);
+       uint32_t *buf32;
+       uint32_t i;
        int retval;
 
-       LOG_DEBUG("address: 0x%8.8x, size: 0x%8.8x, count: 0x%8.8x", address, size, count);
+       LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32, address, size, count);
 
        if (target->state != TARGET_HALTED)
        {
@@ -1947,20 +1866,20 @@ int xscale_read_memory(struct target_s *target, u32 address, u32 size, u32 count
                return ERROR_TARGET_UNALIGNED_ACCESS;
 
        /* send memory read request (command 0x1n, n: access size) */
-       if ((retval=xscale_send_u32(target, 0x10 | size))!=ERROR_OK)
+       if ((retval = xscale_send_u32(target, 0x10 | size)) != ERROR_OK)
                return retval;
 
        /* send base address for read request */
-       if ((retval=xscale_send_u32(target, address))!=ERROR_OK)
+       if ((retval = xscale_send_u32(target, address)) != ERROR_OK)
                return retval;
 
        /* send number of requested data words */
-       if ((retval=xscale_send_u32(target, count))!=ERROR_OK)
+       if ((retval = xscale_send_u32(target, count)) != ERROR_OK)
                return retval;
 
        /* receive data from target (count times 32-bit words in host endianness) */
        buf32 = malloc(4 * count);
-       if ((retval=xscale_receive(target, buf32, count))!=ERROR_OK)
+       if ((retval = xscale_receive(target, buf32, count)) != ERROR_OK)
                return retval;
 
        /* extract data from host-endian buffer into byte stream */
@@ -1980,20 +1899,20 @@ int xscale_read_memory(struct target_s *target, u32 address, u32 size, u32 count
                                *buffer++ = buf32[i] & 0xff;
                                break;
                        default:
-                               LOG_ERROR("should never get here");
-                               exit(-1);
+                               LOG_ERROR("invalid read size");
+                               return ERROR_INVALID_ARGUMENTS;
                }
        }
 
        free(buf32);
 
        /* examine DCSR, to see if Sticky Abort (SA) got set */
-       if ((retval=xscale_read_dcsr(target))!=ERROR_OK)
+       if ((retval = xscale_read_dcsr(target)) != ERROR_OK)
                return retval;
        if (buf_get_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 5, 1) == 1)
        {
                /* clear SA bit */
-               if ((retval=xscale_send_u32(target, 0x60))!=ERROR_OK)
+               if ((retval = xscale_send_u32(target, 0x60)) != ERROR_OK)
                        return retval;
 
                return ERROR_TARGET_DATA_ABORT;
@@ -2002,13 +1921,28 @@ int xscale_read_memory(struct target_s *target, u32 address, u32 size, u32 count
        return ERROR_OK;
 }
 
-int xscale_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
+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, const uint8_t *buffer)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
+       struct xscale_common *xscale = target_to_xscale(target);
        int retval;
 
-       LOG_DEBUG("address: 0x%8.8x, size: 0x%8.8x, count: 0x%8.8x", address, size, count);
+       LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32, address, size, count);
 
        if (target->state != TARGET_HALTED)
        {
@@ -2024,15 +1958,15 @@ int xscale_write_memory(struct target_s *target, u32 address, u32 size, u32 coun
                return ERROR_TARGET_UNALIGNED_ACCESS;
 
        /* send memory write request (command 0x2n, n: access size) */
-       if ((retval=xscale_send_u32(target, 0x20 | size))!=ERROR_OK)
+       if ((retval = xscale_send_u32(target, 0x20 | size)) != ERROR_OK)
                return retval;
 
        /* send base address for read request */
-       if ((retval=xscale_send_u32(target, address))!=ERROR_OK)
+       if ((retval = xscale_send_u32(target, address)) != ERROR_OK)
                return retval;
 
        /* send number of requested data words to be written*/
-       if ((retval=xscale_send_u32(target, count))!=ERROR_OK)
+       if ((retval = xscale_send_u32(target, count)) != ERROR_OK)
                return retval;
 
        /* extract data from host-endian buffer into byte stream */
@@ -2062,49 +1996,73 @@ int xscale_write_memory(struct target_s *target, u32 address, u32 size, u32 coun
                }
        }
 #endif
-       if ((retval=xscale_send(target, buffer, count, size))!=ERROR_OK)
+       if ((retval = xscale_send(target, buffer, count, size)) != ERROR_OK)
                return retval;
 
        /* examine DCSR, to see if Sticky Abort (SA) got set */
-       if ((retval=xscale_read_dcsr(target))!=ERROR_OK)
+       if ((retval = xscale_read_dcsr(target)) != ERROR_OK)
                return retval;
        if (buf_get_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 5, 1) == 1)
        {
                /* clear SA bit */
-               if ((retval=xscale_send_u32(target, 0x60))!=ERROR_OK)
+               if ((retval = xscale_send_u32(target, 0x60)) != ERROR_OK)
                        return retval;
 
+               LOG_ERROR("data abort writing memory");
                return ERROR_TARGET_DATA_ABORT;
        }
 
        return ERROR_OK;
 }
 
-int xscale_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffer)
+static int xscale_write_phys_memory(struct target *target, uint32_t address,
+               uint32_t size, uint32_t count, const 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_write_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, const uint8_t *buffer)
 {
        return xscale_write_memory(target, address, 4, count, buffer);
 }
 
-u32 xscale_get_ttb(target_t *target)
+static int xscale_get_ttb(struct target *target, uint32_t *result)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
-       u32 ttb;
+       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;
 }
 
-void xscale_disable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_cache)
+static int xscale_disable_mmu_caches(struct target *target, int mmu,
+               int d_u_cache, int i_cache)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
-       u32 cp15_control;
+       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)
@@ -2113,11 +2071,17 @@ void xscale_disable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_c
        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;
        }
@@ -2125,25 +2089,33 @@ void xscale_disable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_c
        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;
 }
 
-void xscale_enable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_cache)
+static int xscale_enable_mmu_caches(struct target *target, int mmu,
+               int d_u_cache, int i_cache)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
-       u32 cp15_control;
+       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)
@@ -2156,17 +2128,20 @@ void xscale_enable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_ca
                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;
 }
 
-int xscale_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
+static int xscale_set_breakpoint(struct target *target,
+               struct breakpoint *breakpoint)
 {
        int retval;
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
+       struct xscale_common *xscale = target_to_xscale(target);
 
        if (target->state != TARGET_HALTED)
        {
@@ -2182,7 +2157,7 @@ int xscale_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
 
        if (breakpoint->type == BKPT_HARD)
        {
-               u32 value = breakpoint->address | 1;
+               uint32_t value = breakpoint->address | 1;
                if (!xscale->ibcr0_used)
                {
                        xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_IBCR0], value);
@@ -2196,9 +2171,9 @@ int xscale_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
                        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)
@@ -2206,12 +2181,12 @@ int xscale_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
                if (breakpoint->length == 4)
                {
                        /* keep the original instruction in target endianness */
-                       if((retval = target->type->read_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr)) != ERROR_OK)
+                       if ((retval = target_read_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr)) != ERROR_OK)
                        {
                                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->arm_bkpt)) != ERROR_OK)
+                       /* 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;
                        }
@@ -2219,42 +2194,41 @@ int xscale_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
                else
                {
                        /* keep the original instruction in target endianness */
-                       if((retval = target->type->read_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr)) != ERROR_OK)
+                       if ((retval = target_read_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr)) != ERROR_OK)
                        {
                                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;
 }
 
-int xscale_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
+static int xscale_add_breakpoint(struct target *target,
+               struct breakpoint *breakpoint)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
-
-       if (target->state != TARGET_HALTED)
-       {
-               LOG_WARNING("target not halted");
-               return ERROR_TARGET_NOT_HALTED;
-       }
+       struct xscale_common *xscale = target_to_xscale(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;
        }
 
@@ -2263,14 +2237,14 @@ int xscale_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
                xscale->ibcr_available--;
        }
 
-       return ERROR_OK;
+       return xscale_set_breakpoint(target, breakpoint);
 }
 
-int xscale_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
+static int xscale_unset_breakpoint(struct target *target,
+               struct breakpoint *breakpoint)
 {
        int retval;
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
+       struct xscale_common *xscale = target_to_xscale(target);
 
        if (target->state != TARGET_HALTED)
        {
@@ -2303,32 +2277,36 @@ int xscale_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
                /* restore original instruction (kept in target endianness) */
                if (breakpoint->length == 4)
                {
-                       if((retval = target->type->write_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr)) != ERROR_OK)
+                       if ((retval = target_write_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr)) != ERROR_OK)
                        {
                                return retval;
                        }
                }
                else
                {
-                       if((retval = target->type->write_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr)) != ERROR_OK)
+                       if ((retval = target_write_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr)) != ERROR_OK)
                        {
                                return retval;
                        }
                }
                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;
 }
 
-int xscale_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
+static int xscale_remove_breakpoint(struct target *target, struct breakpoint *breakpoint)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
+       struct xscale_common *xscale = target_to_xscale(target);
 
        if (target->state != TARGET_HALTED)
        {
-               LOG_WARNING("target not halted");
+               LOG_ERROR("target not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
 
@@ -2343,22 +2321,20 @@ int xscale_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
        return ERROR_OK;
 }
 
-int xscale_set_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
+static int xscale_set_watchpoint(struct target *target,
+               struct watchpoint *watchpoint)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
-       u8 enable=0;
-       reg_t *dbcon = &xscale->reg_cache->reg_list[XSCALE_DBCON];
-       u32 dbcon_value = buf_get_u32(dbcon->value, 0, 32);
+       struct xscale_common *xscale = target_to_xscale(target);
+       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:
@@ -2374,6 +2350,24 @@ int xscale_set_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
                        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);
@@ -2393,44 +2387,66 @@ int xscale_set_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
        else
        {
                LOG_ERROR("BUG: no hardware comparator available");
-               return ERROR_OK;
+               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
        }
 
        return ERROR_OK;
 }
 
-int xscale_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
+static int xscale_add_watchpoint(struct target *target,
+               struct watchpoint *watchpoint)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
+       struct xscale_common *xscale = target_to_xscale(target);
 
-       if (target->state != TARGET_HALTED)
+       if (xscale->dbr_available < 1)
        {
-               LOG_WARNING("target not halted");
-               return ERROR_TARGET_NOT_HALTED;
+          LOG_ERROR("no more watchpoint registers available");
+          return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
        }
 
-       if (xscale->dbr_available < 1)
+       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;
+          }
        }
 
-       if ((watchpoint->length != 1) && (watchpoint->length != 2) && (watchpoint->length != 4))
+       if (watchpoint->length == 4) /* single word watchpoint */
        {
-               return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+          xscale->dbr_available--; /* one DBR reg used */
+          return ERROR_OK;
        }
 
-       xscale->dbr_available--;
-
+       /* 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;
 }
 
-int xscale_unset_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
+static int xscale_unset_watchpoint(struct target *target,
+               struct watchpoint *watchpoint)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
-       reg_t *dbcon = &xscale->reg_cache->reg_list[XSCALE_DBCON];
-       u32 dbcon_value = buf_get_u32(dbcon->value, 0, 32);
+       struct xscale_common *xscale = target_to_xscale(target);
+       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)
        {
@@ -2446,7 +2462,14 @@ int xscale_unset_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
 
        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;
        }
@@ -2461,14 +2484,13 @@ int xscale_unset_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
        return ERROR_OK;
 }
 
-int xscale_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
+static int xscale_remove_watchpoint(struct target *target, struct watchpoint *watchpoint)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
+       struct xscale_common *xscale = target_to_xscale(target);
 
        if (target->state != TARGET_HALTED)
        {
-               LOG_WARNING("target not halted");
+               LOG_ERROR("target not halted");
                return ERROR_TARGET_NOT_HALTED;
        }
 
@@ -2477,42 +2499,19 @@ int xscale_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
                xscale_unset_watchpoint(target, watchpoint);
        }
 
+       if (watchpoint->length > 4)
+          xscale->dbr_available++;     /* both DBR regs now available */
+       
        xscale->dbr_available++;
 
        return ERROR_OK;
 }
 
-void xscale_enable_watchpoints(struct target_s *target)
+static int xscale_get_reg(struct reg *reg)
 {
-       watchpoint_t *watchpoint = target->watchpoints;
-
-       while (watchpoint)
-       {
-               if (watchpoint->set == 0)
-                       xscale_set_watchpoint(target, watchpoint);
-               watchpoint = watchpoint->next;
-       }
-}
-
-void xscale_enable_breakpoints(struct target_s *target)
-{
-       breakpoint_t *breakpoint = target->breakpoints;
-
-       /* set any pending breakpoints */
-       while (breakpoint)
-       {
-               if (breakpoint->set == 0)
-                       xscale_set_breakpoint(target, breakpoint);
-               breakpoint = breakpoint->next;
-       }
-}
-
-int xscale_get_reg(reg_t *reg)
-{
-       xscale_reg_t *arch_info = reg->arch_info;
-       target_t *target = arch_info->target;
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
+       struct xscale_reg *arch_info = reg->arch_info;
+       struct target *target = arch_info->target;
+       struct xscale_common *xscale = target_to_xscale(target);
 
        /* DCSR, TX and RX are accessible via JTAG */
        if (strcmp(reg->name, "XSCALE_DCSR") == 0)
@@ -2553,13 +2552,12 @@ int xscale_get_reg(reg_t *reg)
        return ERROR_OK;
 }
 
-int xscale_set_reg(reg_t *reg, u8* buf)
+static int xscale_set_reg(struct reg *reg, uint8_t* buf)
 {
-       xscale_reg_t *arch_info = reg->arch_info;
-       target_t *target = arch_info->target;
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
-       u32 value = buf_get_u32(buf, 0, 32);
+       struct xscale_reg *arch_info = reg->arch_info;
+       struct target *target = arch_info->target;
+       struct xscale_common *xscale = target_to_xscale(target);
+       uint32_t value = buf_get_u32(buf, 0, 32);
 
        /* DCSR, TX and RX are accessible via JTAG */
        if (strcmp(reg->name, "XSCALE_DCSR") == 0)
@@ -2598,23 +2596,11 @@ int xscale_set_reg(reg_t *reg, u8* buf)
        return ERROR_OK;
 }
 
-/* convenience wrapper to access XScale specific registers */
-int xscale_set_reg_u32(reg_t *reg, u32 value)
+static int xscale_write_dcsr_sw(struct target *target, uint32_t value)
 {
-       u8 buf[4];
-
-       buf_set_u32(buf, 0, 32, value);
-
-       return xscale_set_reg(reg, buf);
-}
-
-int xscale_write_dcsr_sw(target_t *target, u32 value)
-{
-       /* get pointers to arch-specific information */
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
-       reg_t *dcsr = &xscale->reg_cache->reg_list[XSCALE_DCSR];
-       xscale_reg_t *dcsr_arch_info = dcsr->arch_info;
+       struct xscale_common *xscale = target_to_xscale(target);
+       struct reg *dcsr = &xscale->reg_cache->reg_list[XSCALE_DCSR];
+       struct xscale_reg *dcsr_arch_info = dcsr->arch_info;
 
        /* send CP write request (command 0x41) */
        xscale_send_u32(target, 0x41);
@@ -2629,20 +2615,20 @@ int xscale_write_dcsr_sw(target_t *target, u32 value)
        return ERROR_OK;
 }
 
-int xscale_read_trace(target_t *target)
+static int xscale_read_trace(struct target *target)
 {
-       /* get pointers to arch-specific information */
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
-       xscale_trace_data_t **trace_data_p;
+       struct xscale_common *xscale = target_to_xscale(target);
+       struct arm *armv4_5 = &xscale->armv4_5_common;
+       struct xscale_trace_data **trace_data_p;
 
        /* 258 words from debug handler
         * 256 trace buffer entries
         * 2 checkpoint addresses
         */
-       u32 trace_buffer[258];
+       uint32_t trace_buffer[258];
        int is_address[256];
        int i, j;
+       unsigned int num_checkpoints = 0;
 
        if (target->state != TARGET_HALTED)
        {
@@ -2659,23 +2645,27 @@ int xscale_read_trace(target_t *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++)
                ;
 
@@ -2685,16 +2675,34 @@ int xscale_read_trace(target_t *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)
                ;
 
-       *trace_data_p = malloc(sizeof(xscale_trace_data_t));
+       *trace_data_p = malloc(sizeof(struct xscale_trace_data));
        (*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)->entries = malloc(sizeof(xscale_trace_entry_t) * (256 - j));
+       (*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++)
        {
@@ -2708,15 +2716,14 @@ int xscale_read_trace(target_t *target)
        return ERROR_OK;
 }
 
-int xscale_read_instruction(target_t *target, arm_instruction_t *instruction)
+static int xscale_read_instruction(struct target *target, uint32_t pc,
+                                                                  struct arm_instruction *instruction)
 {
-       /* get pointers to arch-specific information */
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
+       struct xscale_common *const xscale = target_to_xscale(target);
        int i;
        int section = -1;
-       u32 size_read;
-       u32 opcode;
+       size_t size_read;
+       uint32_t opcode;
        int retval;
 
        if (!xscale->trace.image)
@@ -2725,8 +2732,8 @@ int xscale_read_instruction(target_t *target, arm_instruction_t *instruction)
        /* 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;
@@ -2739,31 +2746,31 @@ int xscale_read_instruction(target_t *target, arm_instruction_t *instruction)
                return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
        }
 
-       if (xscale->trace.core_state == ARMV4_5_STATE_ARM)
+       if (xscale->trace.core_state == ARM_STATE_ARM)
        {
-               u8 buf[4];
+               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);
+                       LOG_ERROR("error while reading instruction");
                        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 == ARMV4_5_STATE_THUMB)
+       else if (xscale->trace.core_state == ARM_STATE_THUMB)
        {
-               u8 buf[2];
+               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);
+                       LOG_ERROR("error while reading instruction");
                        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
        {
@@ -2774,235 +2781,259 @@ int xscale_read_instruction(target_t *target, arm_instruction_t *instruction)
        return ERROR_OK;
 }
 
-int xscale_branch_address(xscale_trace_data_t *trace_data, int i, u32 *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 = 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);
+}
+
+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);
+   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;
+
+                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 (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 */
 
-       *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);
+                       /* direct branch w/ checkpoint; can also get from checkpoint reg */
+                       if (trace_msg_type == 12)
+                       {
+                          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");
+                       }
 
-       return 0;
-}
+                       if (current_pc == 0)
+                          command_print(cmd_ctx, "address unknown");
 
-int xscale_analyze_trace(target_t *target, command_context_t *cmd_ctx)
-{
-       /* get pointers to arch-specific information */
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
-       int next_pc_ok = 0;
-       u32 next_pc = 0x0;
-       xscale_trace_data_t *trace_data = xscale->trace.data;
-       int retval;
+                       continue;
+                }
 
-       while (trace_data)
-       {
-               int i, chkpt;
-               int rollover;
-               int branch;
-               int exception;
-               xscale->trace.core_state = ARMV4_5_STATE_ARM;
+                /* indirect branch; the branch destination was read from trace buffer */
+                if ((trace_msg_type == 9) || (trace_msg_type == 13))
+                {
+                       current_pc = branch_target;
 
-               chkpt = 0;
-               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");
+                }
 
-               for (i = 0; i < trace_data->depth; i++)
-               {
-                       next_pc_ok = 0;
-                       branch = 0;
-                       exception = 0;
+         } /* END: for (i = 0; i < trace_data->depth; i++) */
 
-                       if (trace_data->entries[i].type == XSCALE_TRACE_ADDRESS)
-                               continue;
+         breakpoint_pc = trace_data->last_instruction; /* used below */
+         trace_data = trace_data->next;
 
-                       switch ((trace_data->entries[i].data & 0xf0) >> 4)
-                       {
-                               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;
-                       }
+   } /* END: while (trace_data) */
 
-                       if (xscale->trace.pc_ok)
-                       {
-                               int executed = (trace_data->entries[i].data & 0xf) + rollover * 16;
-                               arm_instruction_t instruction;
+   /* 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 */
 
-                               if ((exception == 6) || (exception == 7))
-                               {
-                                       /* IRQ or FIQ exception, no instruction executed */
-                                       executed -= 1;
-                               }
+   /* how many instructions remaining? */
+   int gap_count = (breakpoint_pc - current_pc) /
+         (xscale->trace.core_state == ARM_STATE_ARM ? 4 : 2);
 
-                               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 != ~0UL)))
-                                       {
-                                               xscale->trace.current_pc = instruction.info.b_bl_bx_blx.target_address;
-                                       }
-                                       else
-                                       {
-                                               xscale->trace.current_pc += (xscale->trace.core_state == ARMV4_5_STATE_ARM) ? 4 : 2;
-                                       }
-                                       command_print(cmd_ctx, "%s", instruction.text);
-                               }
+   /* 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 */
+   }
 
-                               rollover = 0;
-                       }
+   /* 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;
+   }
 
-                       if (next_pc_ok)
-                       {
-                               xscale->trace.current_pc = next_pc;
-                               xscale->trace.pc_ok = 1;
-                       }
-               }
-
-               for (; xscale->trace.current_pc < trace_data->last_instruction; xscale->trace.current_pc += (xscale->trace.core_state == ARMV4_5_STATE_ARM) ? 4 : 2)
-               {
-                       arm_instruction_t 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);
-               }
-
-               trace_data = trace_data->next;
-       }
-
-       return ERROR_OK;
+   return ERROR_OK;
 }
 
-void xscale_build_reg_cache(target_t *target)
-{
-       /* get pointers to arch-specific information */
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
+static const struct reg_arch_type xscale_reg_type = {
+       .get = xscale_get_reg,
+       .set = xscale_set_reg,
+};
 
-       reg_cache_t **cache_p = register_get_last_cache_p(&target->reg_cache);
-       xscale_reg_t *arch_info = malloc(sizeof(xscale_reg_arch_info));
+static void xscale_build_reg_cache(struct target *target)
+{
+       struct xscale_common *xscale = target_to_xscale(target);
+       struct arm *armv4_5 = &xscale->armv4_5_common;
+       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(xscale_reg_t);
+       int num_regs = ARRAY_SIZE(xscale_reg_arch_info);
 
-       (*cache_p) = armv4_5_build_reg_cache(target, armv4_5);
-       armv4_5->core_cache = (*cache_p);
+       (*cache_p) = arm_build_reg_cache(target, armv4_5);
 
-       /* register a register arch-type for XScale dbg registers only once */
-       if (xscale_reg_arch_type == -1)
-               xscale_reg_arch_type = register_reg_arch_type(xscale_get_reg, xscale_set_reg);
-
-       (*cache_p)->next = malloc(sizeof(reg_cache_t));
+       (*cache_p)->next = malloc(sizeof(struct reg_cache));
        cache_p = &(*cache_p)->next;
 
        /* fill in values for the xscale reg cache */
        (*cache_p)->name = "XScale registers";
        (*cache_p)->next = NULL;
-       (*cache_p)->reg_list = malloc(num_regs * sizeof(reg_t));
+       (*cache_p)->reg_list = malloc(num_regs * sizeof(struct reg));
        (*cache_p)->num_regs = num_regs;
 
        for (i = 0; i < num_regs; i++)
@@ -3012,10 +3043,8 @@ void xscale_build_reg_cache(target_t *target)
                (*cache_p)->reg_list[i].dirty = 0;
                (*cache_p)->reg_list[i].valid = 0;
                (*cache_p)->reg_list[i].size = 32;
-               (*cache_p)->reg_list[i].bitfield_desc = NULL;
-               (*cache_p)->reg_list[i].num_bitfields = 0;
                (*cache_p)->reg_list[i].arch_info = &arch_info[i];
-               (*cache_p)->reg_list[i].arch_type = xscale_reg_arch_type;
+               (*cache_p)->reg_list[i].type = &xscale_reg_type;
                arch_info[i] = xscale_reg_arch_info[i];
                arch_info[i].target = target;
        }
@@ -3023,56 +3052,58 @@ void xscale_build_reg_cache(target_t *target)
        xscale->reg_cache = (*cache_p);
 }
 
-int xscale_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
-{
-       return ERROR_OK;
-}
-
-int xscale_quit(void)
+static int xscale_init_target(struct command_context *cmd_ctx,
+               struct target *target)
 {
+       xscale_build_reg_cache(target);
        return ERROR_OK;
 }
 
-int xscale_init_arch_info(target_t *target, xscale_common_t *xscale, jtag_tap_t *tap, const char *variant)
+static int xscale_init_arch_info(struct target *target,
+               struct xscale_common *xscale, struct jtag_tap *tap, const char *variant)
 {
-       armv4_5_common_t *armv4_5;
-       u32 high_reset_branch, low_reset_branch;
+       struct arm *armv4_5;
+       uint32_t high_reset_branch, low_reset_branch;
        int i;
 
        armv4_5 = &xscale->armv4_5_common;
 
-       /* store architecture specfic data (none so far) */
-       xscale->arch_info = NULL;
+       /* store architecture specfic data */
        xscale->common_magic = XSCALE_COMMON_MAGIC;
 
-       /* remember the variant (PXA25x, PXA27x, IXP42x, ...) */
-       xscale->variant = strdup(variant);
-
-       /* prepare JTAG information for the new target */
-       xscale->jtag_info.tap = tap;
-
-       xscale->jtag_info.dbgrx = 0x02;
-       xscale->jtag_info.dbgtx = 0x10;
-       xscale->jtag_info.dcsr = 0x09;
-       xscale->jtag_info.ldic = 0x07;
+       /* we don't really *need* a variant param ... */
+       if (variant) {
+               int ir_length = 0;
+
+               if (strcmp(variant, "pxa250") == 0
+                               || strcmp(variant, "pxa255") == 0
+                               || strcmp(variant, "pxa26x") == 0)
+                       ir_length = 5;
+               else if (strcmp(variant, "pxa27x") == 0
+                               || strcmp(variant, "ixp42x") == 0
+                               || 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);
 
-       if ((strcmp(xscale->variant, "pxa250") == 0) ||
-               (strcmp(xscale->variant, "pxa255") == 0) ||
-               (strcmp(xscale->variant, "pxa26x") == 0))
-       {
-               xscale->jtag_info.ir_length = 5;
-       }
-       else if ((strcmp(xscale->variant, "pxa27x") == 0) ||
-               (strcmp(xscale->variant, "ixp42x") == 0) ||
-               (strcmp(xscale->variant, "ixp45x") == 0) ||
-               (strcmp(xscale->variant, "ixp46x") == 0))
-       {
-               xscale->jtag_info.ir_length = 7;
+               if (ir_length && ir_length != tap->ir_length) {
+                       LOG_WARNING("%s: IR length for %s is %d; fixing",
+                               tap->dotted_name, variant, ir_length);
+                       tap->ir_length = ir_length;
+               }
        }
 
+       /* 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_installed = 0;
-       xscale->handler_running = 0;
        xscale->handler_address = 0xfe000800;
 
        /* clear the vectors we keep locally for reference */
@@ -3110,16 +3141,19 @@ int xscale_init_arch_info(target_t *target, xscale_common_t *xscale, jtag_tap_t
        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;
 
        xscale->vector_catch = 0x1;
 
-       xscale->trace.capture_status = TRACE_IDLE;
        xscale->trace.data = NULL;
        xscale->trace.image = NULL;
-       xscale->trace.buffer_enabled = 0;
+       xscale->trace.mode = XSCALE_TRACE_DISABLED;
        xscale->trace.buffer_fill = 0;
+       xscale->trace.fill_counter = 0;
 
        /* prepare ARMv4/5 specific information */
        armv4_5->arch_info = xscale;
@@ -3127,7 +3161,7 @@ int xscale_init_arch_info(target_t *target, xscale_common_t *xscale, jtag_tap_t
        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;
@@ -3141,43 +3175,48 @@ int xscale_init_arch_info(target_t *target, xscale_common_t *xscale, jtag_tap_t
        return ERROR_OK;
 }
 
-/* target xscale <endianess> <startup_mode> <chain_pos> <variant> */
-int xscale_target_create(struct target_s *target, Jim_Interp *interp)
+static int xscale_target_create(struct target *target, Jim_Interp *interp)
 {
-       xscale_common_t *xscale = calloc(1,sizeof(xscale_common_t));
+       struct xscale_common *xscale;
 
-       xscale_init_arch_info(target, xscale, target->tap, target->variant);
-       xscale_build_reg_cache(target);
+       if (sizeof xscale_debug_handler - 1 > 0x800) {
+               LOG_ERROR("debug_handler.bin: larger than 2kb");
+               return ERROR_FAIL;
+       }
 
-       return ERROR_OK;
+       xscale = calloc(1, sizeof(*xscale));
+       if (!xscale)
+               return ERROR_FAIL;
+
+       return xscale_init_arch_info(target, xscale, target->tap,
+                       target->variant);
 }
 
-int xscale_handle_debug_handler_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+COMMAND_HANDLER(xscale_handle_debug_handler_command)
 {
-       target_t *target = NULL;
-       armv4_5_common_t *armv4_5;
-       xscale_common_t *xscale;
-
-       u32 handler_address;
+       struct target *target = NULL;
+       struct xscale_common *xscale;
+       int retval;
+       uint32_t handler_address;
 
-       if (argc < 2)
+       if (CMD_ARGC < 2)
        {
                LOG_ERROR("'xscale debug_handler <target#> <address>' command takes two required operands");
                return ERROR_OK;
        }
 
-       if ((target = get_target_by_num(strtoul(args[0], NULL, 0))) == NULL)
+       if ((target = get_target(CMD_ARGV[0])) == NULL)
        {
-               LOG_ERROR("no target '%s' configured", args[0]);
+               LOG_ERROR("target '%s' not defined", CMD_ARGV[0]);
                return ERROR_FAIL;
        }
 
-       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
-       {
-               return ERROR_FAIL;
-       }
+       xscale = target_to_xscale(target);
+       retval = xscale_verify_pointer(CMD_CTX, xscale);
+       if (retval != ERROR_OK)
+               return retval;
 
-       handler_address = strtoul(args[1], NULL, 0);
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], handler_address);
 
        if (((handler_address >= 0x800) && (handler_address <= 0x1fef800)) ||
                ((handler_address >= 0xfe000800) && (handler_address <= 0xfffff800)))
@@ -3193,31 +3232,30 @@ int xscale_handle_debug_handler_command(struct command_context_s *cmd_ctx, char
        return ERROR_OK;
 }
 
-int xscale_handle_cache_clean_address_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+COMMAND_HANDLER(xscale_handle_cache_clean_address_command)
 {
-       target_t *target = NULL;
-       armv4_5_common_t *armv4_5;
-       xscale_common_t *xscale;
-
-       u32 cache_clean_address;
+       struct target *target = NULL;
+       struct xscale_common *xscale;
+       int retval;
+       uint32_t cache_clean_address;
 
-       if (argc < 2)
+       if (CMD_ARGC < 2)
        {
                return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
-       if ((target = get_target_by_num(strtoul(args[0], NULL, 0))) == NULL)
-       {
-               LOG_ERROR("no target '%s' configured", args[0]);
-               return ERROR_FAIL;
-       }
-
-       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
+       target = get_target(CMD_ARGV[0]);
+       if (target == NULL)
        {
+               LOG_ERROR("target '%s' not defined", CMD_ARGV[0]);
                return ERROR_FAIL;
        }
+       xscale = target_to_xscale(target);
+       retval = xscale_verify_pointer(CMD_CTX, xscale);
+       if (retval != ERROR_OK)
+               return retval;
 
-       cache_clean_address = strtoul(args[1], NULL, 0);
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], cache_clean_address);
 
        if (cache_clean_address & 0xffff)
        {
@@ -3231,47 +3269,42 @@ int xscale_handle_cache_clean_address_command(struct command_context_s *cmd_ctx,
        return ERROR_OK;
 }
 
-int xscale_handle_cache_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+COMMAND_HANDLER(xscale_handle_cache_info_command)
 {
-       target_t *target = get_current_target(cmd_ctx);
-       armv4_5_common_t *armv4_5;
-       xscale_common_t *xscale;
+       struct target *target = get_current_target(CMD_CTX);
+       struct xscale_common *xscale = target_to_xscale(target);
+       int retval;
 
-       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
-       {
-               return ERROR_OK;
-       }
+       retval = xscale_verify_pointer(CMD_CTX, xscale);
+       if (retval != ERROR_OK)
+               return retval;
 
-       return armv4_5_handle_cache_info_command(cmd_ctx, &xscale->armv4_5_mmu.armv4_5_cache);
+       return armv4_5_handle_cache_info_command(CMD_CTX, &xscale->armv4_5_mmu.armv4_5_cache);
 }
 
-static int xscale_virt2phys(struct target_s *target, u32 virtual, u32 *physical)
+static int xscale_virt2phys(struct target *target,
+               uint32_t virtual, uint32_t *physical)
 {
-       armv4_5_common_t *armv4_5;
-       xscale_common_t *xscale;
-       int retval;
-       int type;
-       u32 cb;
-       int domain;
-       u32 ap;
+       struct xscale_common *xscale = target_to_xscale(target);
+       uint32_t cb;
 
-       if ((retval = xscale_get_arch_pointers(target, &armv4_5, &xscale)) != ERROR_OK)
-       {
-               return retval;
-       }
-       u32 ret = armv4_5_mmu_translate_va(target, &xscale->armv4_5_mmu, virtual, &type, &cb, &domain, &ap);
-       if (type == -1)
-       {
-               return ret;
+       if (xscale->common_magic != XSCALE_COMMON_MAGIC) {
+               LOG_ERROR(xscale_not);
+               return ERROR_TARGET_INVALID;
        }
+
+       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;
 }
 
-static int xscale_mmu(struct target_s *target, int *enabled)
+static int xscale_mmu(struct target *target, int *enabled)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       xscale_common_t *xscale = armv4_5->arch_info;
+       struct xscale_common *xscale = target_to_xscale(target);
 
        if (target->state != TARGET_HALTED)
        {
@@ -3282,196 +3315,234 @@ static int xscale_mmu(struct target_s *target, int *enabled)
        return ERROR_OK;
 }
 
-int xscale_handle_mmu_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)
+COMMAND_HANDLER(xscale_handle_mmu_command)
 {
-       target_t *target = get_current_target(cmd_ctx);
-       armv4_5_common_t *armv4_5;
-       xscale_common_t *xscale;
+       struct target *target = get_current_target(CMD_CTX);
+       struct xscale_common *xscale = target_to_xscale(target);
+       int retval;
 
-       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
-       {
-               return ERROR_OK;
-       }
+       retval = xscale_verify_pointer(CMD_CTX, xscale);
+       if (retval != ERROR_OK)
+               return retval;
 
        if (target->state != TARGET_HALTED)
        {
-               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+               command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
                return ERROR_OK;
        }
 
-       if (argc >= 1)
+       if (CMD_ARGC >= 1)
        {
-               if (strcmp("enable", args[0]) == 0)
-               {
+               bool enable;
+               COMMAND_PARSE_ENABLE(CMD_ARGV[0], enable);
+               if (enable)
                        xscale_enable_mmu_caches(target, 1, 0, 0);
-                       xscale->armv4_5_mmu.mmu_enabled = 1;
-               }
-               else if (strcmp("disable", args[0]) == 0)
-               {
+               else
                        xscale_disable_mmu_caches(target, 1, 0, 0);
-                       xscale->armv4_5_mmu.mmu_enabled = 0;
-               }
+               xscale->armv4_5_mmu.mmu_enabled = enable;
        }
 
-       command_print(cmd_ctx, "mmu %s", (xscale->armv4_5_mmu.mmu_enabled) ? "enabled" : "disabled");
+       command_print(CMD_CTX, "mmu %s", (xscale->armv4_5_mmu.mmu_enabled) ? "enabled" : "disabled");
 
        return ERROR_OK;
 }
 
-int xscale_handle_idcache_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)
+COMMAND_HANDLER(xscale_handle_idcache_command)
 {
-       target_t *target = get_current_target(cmd_ctx);
-       armv4_5_common_t *armv4_5;
-       xscale_common_t *xscale;
-       int icache = 0, dcache = 0;
+       struct target *target = get_current_target(CMD_CTX);
+       struct xscale_common *xscale = target_to_xscale(target);
 
-       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
-       {
-               return ERROR_OK;
-       }
+       int retval = xscale_verify_pointer(CMD_CTX, xscale);
+       if (retval != ERROR_OK)
+               return retval;
 
        if (target->state != TARGET_HALTED)
        {
-               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+               command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
                return ERROR_OK;
        }
 
-       if (strcmp(cmd, "icache") == 0)
-               icache = 1;
-       else if (strcmp(cmd, "dcache") == 0)
-               dcache = 1;
-
-       if (argc >= 1)
+       bool icache = false;
+       if (strcmp(CMD_NAME, "icache") == 0)
+               icache = true;
+       if (CMD_ARGC >= 1)
        {
-               if (strcmp("enable", args[0]) == 0)
-               {
-                       xscale_enable_mmu_caches(target, 0, dcache, icache);
-
-                       if (icache)
-                               xscale->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 1;
-                       else if (dcache)
-                               xscale->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 1;
-               }
-               else if (strcmp("disable", args[0]) == 0)
-               {
-                       xscale_disable_mmu_caches(target, 0, dcache, icache);
-
-                       if (icache)
-                               xscale->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;
-                       else if (dcache)
-                               xscale->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0;
+               bool enable;
+               COMMAND_PARSE_ENABLE(CMD_ARGV[0], enable);
+               if (icache) {
+                       xscale->armv4_5_mmu.armv4_5_cache.i_cache_enabled = enable;
+                       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);
                }
        }
 
-       if (icache)
-               command_print(cmd_ctx, "icache %s", (xscale->armv4_5_mmu.armv4_5_cache.i_cache_enabled) ? "enabled" : "disabled");
-
-       if (dcache)
-               command_print(cmd_ctx, "dcache %s", (xscale->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled) ? "enabled" : "disabled");
+       bool enabled = icache ?
+                                       xscale->armv4_5_mmu.armv4_5_cache.i_cache_enabled :
+                                       xscale->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled;
+       const char *msg = enabled ? "enabled" : "disabled";
+       command_print(CMD_CTX, "%s %s", CMD_NAME, msg);
 
        return ERROR_OK;
 }
 
-int xscale_handle_vector_catch_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)
+COMMAND_HANDLER(xscale_handle_vector_catch_command)
 {
-       target_t *target = get_current_target(cmd_ctx);
-       armv4_5_common_t *armv4_5;
-       xscale_common_t *xscale;
+       struct target *target = get_current_target(CMD_CTX);
+       struct xscale_common *xscale = target_to_xscale(target);
+       int retval;
 
-       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
-       {
-               return ERROR_OK;
-       }
+       retval = xscale_verify_pointer(CMD_CTX, xscale);
+       if (retval != ERROR_OK)
+               return retval;
 
-       if (argc < 1)
+       if (CMD_ARGC < 1)
        {
-               command_print(cmd_ctx, "usage: xscale vector_catch [mask]");
+               command_print(CMD_CTX, "usage: xscale vector_catch [mask]");
        }
        else
        {
-               xscale->vector_catch = strtoul(args[0], NULL, 0);
+               COMMAND_PARSE_NUMBER(u8, CMD_ARGV[0], xscale->vector_catch);
                buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 16, 8, xscale->vector_catch);
                xscale_write_dcsr(target, -1, -1);
        }
 
-       command_print(cmd_ctx, "vector catch mask: 0x%2.2x", xscale->vector_catch);
+       command_print(CMD_CTX, "vector catch mask: 0x%2.2x", xscale->vector_catch);
 
        return ERROR_OK;
 }
 
 
-int xscale_handle_trace_buffer_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+COMMAND_HANDLER(xscale_handle_vector_table_command)
 {
-       target_t *target = get_current_target(cmd_ctx);
-       armv4_5_common_t *armv4_5;
-       xscale_common_t *xscale;
-       u32 dcsr_value;
+       struct target *target = get_current_target(CMD_CTX);
+       struct xscale_common *xscale = target_to_xscale(target);
+       int err = 0;
+       int retval;
 
-       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
-       {
-               return ERROR_OK;
-       }
+       retval = xscale_verify_pointer(CMD_CTX, xscale);
+       if (retval != ERROR_OK)
+               return retval;
 
-       if (target->state != TARGET_HALTED)
+       if (CMD_ARGC == 0) /* print current settings */
        {
-               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+               int idx;
+
+               command_print(CMD_CTX, "active user-set static vectors:");
+               for (idx = 1; idx < 8; idx++)
+                       if (xscale->static_low_vectors_set & (1 << idx))
+                               command_print(CMD_CTX, "low  %d: 0x%" PRIx32, idx, xscale->static_low_vectors[idx]);
+               for (idx = 1; idx < 8; idx++)
+                       if (xscale->static_high_vectors_set & (1 << idx))
+                               command_print(CMD_CTX, "high %d: 0x%" PRIx32, idx, xscale->static_high_vectors[idx]);
                return ERROR_OK;
        }
 
-       if ((argc >= 1) && (strcmp("enable", args[0]) == 0))
+       if (CMD_ARGC != 3)
+               err = 1;
+       else
        {
-               xscale_trace_data_t *td, *next_td;
-               xscale->trace.buffer_enabled = 1;
+               int idx;
+               COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], idx);
+               uint32_t vec;
+               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], vec);
 
-               /* free old trace data */
-               td = xscale->trace.data;
-               while (td)
-               {
-                       next_td = td->next;
+               if (idx < 1 || idx >= 8)
+                       err = 1;
 
-                       if (td->entries)
-                               free(td->entries);
-                       free(td);
-                       td = next_td;
+               if (!err && strcmp(CMD_ARGV[0], "low") == 0)
+               {
+                       xscale->static_low_vectors_set |= (1<<idx);
+                       xscale->static_low_vectors[idx] = vec;
+               }
+               else if (!err && (strcmp(CMD_ARGV[0], "high") == 0))
+               {
+                       xscale->static_high_vectors_set |= (1<<idx);
+                       xscale->static_high_vectors[idx] = vec;
                }
-               xscale->trace.data = NULL;
-       }
-       else if ((argc >= 1) && (strcmp("disable", args[0]) == 0))
-       {
-               xscale->trace.buffer_enabled = 0;
-       }
-
-       if ((argc >= 2) && (strcmp("fill", args[1]) == 0))
-       {
-               if (argc >= 3)
-                       xscale->trace.buffer_fill = strtoul(args[2], NULL, 0);
                else
-                       xscale->trace.buffer_fill = 1;
+                       err = 1;
        }
-       else if ((argc >= 2) && (strcmp("wrap", args[1]) == 0))
+
+       if (err)
+               command_print(CMD_CTX, "usage: xscale vector_table <high|low> <index> <code>");
+
+       return ERROR_OK;
+}
+
+
+COMMAND_HANDLER(xscale_handle_trace_buffer_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       struct xscale_common *xscale = target_to_xscale(target);
+       uint32_t dcsr_value;
+       int retval;
+
+       retval = xscale_verify_pointer(CMD_CTX, xscale);
+       if (retval != ERROR_OK)
+               return retval;
+
+       if (target->state != TARGET_HALTED)
        {
-               xscale->trace.buffer_fill = -1;
+               command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
+               return ERROR_OK;
        }
 
-       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);
+       if (CMD_ARGC >= 1)
+       {
+          if (strcmp("enable", CMD_ARGV[0]) == 0)
+                 xscale->trace.mode = XSCALE_TRACE_WRAP; /* default */
+          else if (strcmp("disable", CMD_ARGV[0]) == 0)
+                 xscale->trace.mode = XSCALE_TRACE_DISABLED;
+          else
+                 return ERROR_INVALID_ARGUMENTS;
+       }
+
+       if (CMD_ARGC >= 2 && xscale->trace.mode != XSCALE_TRACE_DISABLED)
+       {
+          if (strcmp("fill", CMD_ARGV[1]) == 0)
+          {
+                 int buffcount = 1;                    /* default */
+                 if (CMD_ARGC >= 3)
+                        COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], buffcount);
+                 if (buffcount < 1)                    /* invalid */
+                 {
+                        command_print(CMD_CTX, "fill buffer count must be > 0");
+                        xscale->trace.mode = XSCALE_TRACE_DISABLED;
+                        return ERROR_INVALID_ARGUMENTS;
+                 }
+                 xscale->trace.buffer_fill = buffcount;
+                 xscale->trace.mode = XSCALE_TRACE_FILL;
+          }
+          else if (strcmp("wrap", CMD_ARGV[1]) == 0)
+                 xscale->trace.mode = XSCALE_TRACE_WRAP;
+          else
+          {
+                 xscale->trace.mode = XSCALE_TRACE_DISABLED;
+                 return ERROR_INVALID_ARGUMENTS;
+          }
+       }
+       
+       if (xscale->trace.mode != XSCALE_TRACE_DISABLED)
+       {
+          char fill_string[12];
+          sprintf(fill_string, "fill %" PRId32, xscale->trace.buffer_fill); 
+          command_print(CMD_CTX, "trace buffer enabled (%s)",
+                                        (xscale->trace.mode == XSCALE_TRACE_FILL)
+                                        ? fill_string : "wrap");
        }
        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");
-
+          command_print(CMD_CTX, "trace buffer disabled");
+          
        dcsr_value = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 0, 32);
-       if (xscale->trace.buffer_fill >= 0)
+       if (xscale->trace.mode == XSCALE_TRACE_FILL)
                xscale_write_dcsr_sw(target, (dcsr_value & 0xfffffffc) | 2);
        else
                xscale_write_dcsr_sw(target, dcsr_value & 0xfffffffc);
@@ -3479,48 +3550,45 @@ int xscale_handle_trace_buffer_command(struct command_context_s *cmd_ctx, char *
        return ERROR_OK;
 }
 
-int xscale_handle_trace_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+COMMAND_HANDLER(xscale_handle_trace_image_command)
 {
-       target_t *target;
-       armv4_5_common_t *armv4_5;
-       xscale_common_t *xscale;
+       struct target *target = get_current_target(CMD_CTX);
+       struct xscale_common *xscale = target_to_xscale(target);
+       int retval;
 
-       if (argc < 1)
+       if (CMD_ARGC < 1)
        {
-               command_print(cmd_ctx, "usage: xscale trace_image <file> [base address] [type]");
+               command_print(CMD_CTX, "usage: xscale trace_image <file> [base address] [type]");
                return ERROR_OK;
        }
 
-       target = get_current_target(cmd_ctx);
-
-       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
-       {
-               return ERROR_OK;
-       }
+       retval = xscale_verify_pointer(CMD_CTX, xscale);
+       if (retval != ERROR_OK)
+               return retval;
 
        if (xscale->trace.image)
        {
                image_close(xscale->trace.image);
                free(xscale->trace.image);
-               command_print(cmd_ctx, "previously loaded image found and closed");
+               command_print(CMD_CTX, "previously loaded image found and closed");
        }
 
-       xscale->trace.image = malloc(sizeof(image_t));
+       xscale->trace.image = malloc(sizeof(struct image));
        xscale->trace.image->base_address_set = 0;
        xscale->trace.image->start_address_set = 0;
 
        /* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */
-       if (argc >= 2)
+       if (CMD_ARGC >= 2)
        {
                xscale->trace.image->base_address_set = 1;
-               xscale->trace.image->base_address = strtoul(args[1], NULL, 0);
+               COMMAND_PARSE_NUMBER(llong, CMD_ARGV[1], xscale->trace.image->base_address);
        }
        else
        {
                xscale->trace.image->base_address_set = 0;
        }
 
-       if (image_open(xscale->trace.image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)
+       if (image_open(xscale->trace.image, CMD_ARGV[0], (CMD_ARGC >= 3) ? CMD_ARGV[2] : NULL) != ERROR_OK)
        {
                free(xscale->trace.image);
                xscale->trace.image = NULL;
@@ -3530,28 +3598,27 @@ int xscale_handle_trace_image_command(struct command_context_s *cmd_ctx, char *c
        return ERROR_OK;
 }
 
-int xscale_handle_dump_trace_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+COMMAND_HANDLER(xscale_handle_dump_trace_command)
 {
-       target_t *target = get_current_target(cmd_ctx);
-       armv4_5_common_t *armv4_5;
-       xscale_common_t *xscale;
-       xscale_trace_data_t *trace_data;
-       fileio_t file;
+       struct target *target = get_current_target(CMD_CTX);
+       struct xscale_common *xscale = target_to_xscale(target);
+       struct xscale_trace_data *trace_data;
+       struct fileio file;
+       int retval;
 
-       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
-       {
-               return ERROR_OK;
-       }
+       retval = xscale_verify_pointer(CMD_CTX, xscale);
+       if (retval != ERROR_OK)
+               return retval;
 
        if (target->state != TARGET_HALTED)
        {
-               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+               command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
                return ERROR_OK;
        }
 
-       if (argc < 1)
+       if (CMD_ARGC < 1)
        {
-               command_print(cmd_ctx, "usage: xscale dump_trace <file>");
+               command_print(CMD_CTX, "usage: xscale dump_trace <file>");
                return ERROR_OK;
        }
 
@@ -3559,11 +3626,11 @@ int xscale_handle_dump_trace_command(struct command_context_s *cmd_ctx, char *cm
 
        if (!trace_data)
        {
-               command_print(cmd_ctx, "no trace data collected");
+               command_print(CMD_CTX, "no trace data collected");
                return ERROR_OK;
        }
 
-       if (fileio_open(&file, args[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK)
+       if (fileio_open(&file, CMD_ARGV[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK)
        {
                return ERROR_OK;
        }
@@ -3588,45 +3655,43 @@ int xscale_handle_dump_trace_command(struct command_context_s *cmd_ctx, char *cm
        return ERROR_OK;
 }
 
-int xscale_handle_analyze_trace_buffer_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+COMMAND_HANDLER(xscale_handle_analyze_trace_buffer_command)
 {
-       target_t *target = get_current_target(cmd_ctx);
-       armv4_5_common_t *armv4_5;
-       xscale_common_t *xscale;
+       struct target *target = get_current_target(CMD_CTX);
+       struct xscale_common *xscale = target_to_xscale(target);
+       int retval;
 
-       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
-       {
-               return ERROR_OK;
-       }
+       retval = xscale_verify_pointer(CMD_CTX, xscale);
+       if (retval != ERROR_OK)
+               return retval;
 
-       xscale_analyze_trace(target, cmd_ctx);
+       xscale_analyze_trace(target, CMD_CTX);
 
        return ERROR_OK;
 }
 
-int xscale_handle_cp15(command_context_t *cmd_ctx, char *cmd, char **args, int argc)
+COMMAND_HANDLER(xscale_handle_cp15)
 {
-       target_t *target = get_current_target(cmd_ctx);
-       armv4_5_common_t *armv4_5;
-       xscale_common_t *xscale;
+       struct target *target = get_current_target(CMD_CTX);
+       struct xscale_common *xscale = target_to_xscale(target);
+       int retval;
 
-       if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
-       {
-               return ERROR_OK;
-       }
+       retval = xscale_verify_pointer(CMD_CTX, xscale);
+       if (retval != ERROR_OK)
+               return retval;
 
        if (target->state != TARGET_HALTED)
        {
-               command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+               command_print(CMD_CTX, "target must be stopped for \"%s\" command", CMD_NAME);
                return ERROR_OK;
        }
-       u32 reg_no = 0;
-       reg_t *reg = NULL;
-       if(argc > 0)
+       uint32_t reg_no = 0;
+       struct reg *reg = NULL;
+       if (CMD_ARGC > 0)
        {
-               reg_no = strtoul(args[0], NULL, 0);
+               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], reg_no);
                /*translate from xscale cp15 register no to openocd register*/
-               switch(reg_no)
+               switch (reg_no)
                {
                case 0:
                        reg_no = XSCALE_MAINID;
@@ -3653,25 +3718,25 @@ int xscale_handle_cp15(command_context_t *cmd_ctx, char *cmd, char **args, int a
                        reg_no = XSCALE_CPACCESS;
                        break;
                default:
-                       command_print(cmd_ctx, "invalid register number");
+                       command_print(CMD_CTX, "invalid register number");
                        return ERROR_INVALID_ARGUMENTS;
                }
                reg = &xscale->reg_cache->reg_list[reg_no];
 
        }
-       if(argc == 1)
+       if (CMD_ARGC == 1)
        {
-               u32 value;
+               uint32_t value;
 
                /* read cp15 control register */
                xscale_get_reg(reg);
                value = buf_get_u32(reg->value, 0, 32);
-               command_print(cmd_ctx, "%s (/%i): 0x%x", reg->name, reg->size, value);
+               command_print(CMD_CTX, "%s (/%i): 0x%" PRIx32 "", reg->name, (int)(reg->size), value);
        }
-       else if(argc == 2)
+       else if (CMD_ARGC == 2)
        {
-
-               u32 value = strtoul(args[1], NULL, 0);
+               uint32_t value;
+               COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
 
                /* send CP write request (command 0x41) */
                xscale_send_u32(target, 0x41);
@@ -3687,38 +3752,169 @@ int xscale_handle_cp15(command_context_t *cmd_ctx, char *cmd, char **args, int a
        }
        else
        {
-               command_print(cmd_ctx, "usage: cp15 [register]<, [value]>");
+               command_print(CMD_CTX, "usage: cp15 [register]<, [value]>");
        }
 
        return ERROR_OK;
 }
 
-int xscale_register_commands(struct command_context_s *cmd_ctx)
+static const struct command_registration xscale_exec_command_handlers[] = {
+       {
+               .name = "cache_info",
+               .handler = xscale_handle_cache_info_command,
+               .mode = COMMAND_EXEC,
+               .help = "display information about CPU caches",
+       },
+       {
+               .name = "mmu",
+               .handler = xscale_handle_mmu_command,
+               .mode = COMMAND_EXEC,
+               .help = "enable or disable the MMU",
+               .usage = "['enable'|'disable']",
+       },
+       {
+               .name = "icache",
+               .handler = xscale_handle_idcache_command,
+               .mode = COMMAND_EXEC,
+               .help = "display ICache state, optionally enabling or "
+                       "disabling it",
+               .usage = "['enable'|'disable']",
+       },
+       {
+               .name = "dcache",
+               .handler = xscale_handle_idcache_command,
+               .mode = COMMAND_EXEC,
+               .help = "display DCache state, optionally enabling or "
+                       "disabling it",
+               .usage = "['enable'|'disable']",
+       },
+       {
+               .name = "vector_catch",
+               .handler = xscale_handle_vector_catch_command,
+               .mode = COMMAND_EXEC,
+               .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,
+               .mode = COMMAND_EXEC,
+               .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,
+               .mode = COMMAND_EXEC,
+               .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,
+               .mode = COMMAND_EXEC,
+               .help = "dump content of trace buffer to file",
+               .usage = "filename",
+       },
+       {
+               .name = "analyze_trace",
+               .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,
+               .mode = COMMAND_EXEC,
+               .help = "load image from file to address (default 0)",
+               .usage = "filename [offset [filetype]]",
+       },
+       {
+               .name = "cp15",
+               .handler = xscale_handle_cp15,
+               .mode = COMMAND_EXEC,
+               .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,
+               .mode = COMMAND_ANY,
+               .help = "Change address used for debug handler.",
+               .usage = "target address",
+       },
+       {
+               .name = "cache_clean_address",
+               .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,
+       },
+       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 =
 {
-       command_t *xscale_cmd;
+       .name = "xscale",
+
+       .poll = xscale_poll,
+       .arch_state = xscale_arch_state,
 
-       xscale_cmd = register_command(cmd_ctx, NULL, "xscale", NULL, COMMAND_ANY, "xscale specific commands");
+       .target_request_data = NULL,
+
+       .halt = xscale_halt,
+       .resume = xscale_resume,
+       .step = xscale_step,
 
-       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);
+       .assert_reset = xscale_assert_reset,
+       .deassert_reset = xscale_deassert_reset,
+       .soft_reset_halt = 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");
+       /* REVISIT on some cores, allow exporting iwmmxt registers ... */
+       .get_gdb_reg_list = arm_get_gdb_reg_list,
 
-       register_command(cmd_ctx, xscale_cmd, "vector_catch", xscale_handle_vector_catch_command, COMMAND_EXEC, "<mask> of vectors that should be catched");
+       .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,
 
-       register_command(cmd_ctx, xscale_cmd, "trace_buffer", xscale_handle_trace_buffer_command, COMMAND_EXEC, "<enable|disable> ['fill' [n]|'wrap']");
+       .checksum_memory = arm_checksum_memory,
+       .blank_check_memory = arm_blank_check_memory,
 
-       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]");
+       .run_algorithm = armv4_5_run_algorithm,
 
-       register_command(cmd_ctx, xscale_cmd, "cp15", xscale_handle_cp15, COMMAND_EXEC, "access coproc 15 <register> [value]");
+       .add_breakpoint = xscale_add_breakpoint,
+       .remove_breakpoint = xscale_remove_breakpoint,
+       .add_watchpoint = xscale_add_watchpoint,
+       .remove_watchpoint = xscale_remove_watchpoint,
 
-       armv4_5_register_commands(cmd_ctx);
+       .commands = xscale_command_handlers,
+       .target_create = xscale_target_create,
+       .init_target = xscale_init_target,
 
-       return ERROR_OK;
-}
+       .virt2phys = xscale_virt2phys,
+       .mmu = xscale_mmu
+};

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)