From 4a5f45e87d593d6911da680cb92ffbc9b43c9486 Mon Sep 17 00:00:00 2001
From: drath <drath@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Date: Wed, 28 Mar 2007 16:31:55 +0000
Subject: [PATCH] - merged XScale branch back into trunk - fixed some compiler
 warnigns in amt_jtagaccel.c, bitbang.c, parport.c - free working area and
 register stuff if str7x block write algorithm failed - check PC after exiting
 a target algorithm in armv4_5.c

git-svn-id: svn://svn.berlios.de/openocd/trunk@135 b42882b7-edfa-0310-969c-e2dbd0fdcd60
---
 src/flash/str7x.c                   |    9 +-
 src/helper/fileio.c                 |   21 +-
 src/jtag/amt_jtagaccel.c            |    2 +-
 src/jtag/bitbang.c                  |    2 +-
 src/jtag/parport.c                  |    2 +-
 src/openocd.c                       |    2 +-
 src/target/Makefile.am              |    4 +-
 src/target/arm_disassembler.c       |   35 +-
 src/target/arm_disassembler.h       |   36 +-
 src/target/arm_simulator.c          |  684 ++++++
 src/target/arm_simulator.h          |   31 +
 src/target/armv4_5.c                |    9 +-
 src/target/armv4_5.h                |   10 +
 src/target/target.c                 |   87 +-
 src/target/target.h                 |   14 +-
 src/target/xscale.c                 | 3175 +++++++++++++++++++++++++++
 src/target/xscale.h                 |  145 ++
 src/target/xscale/build.sh          |    7 +
 src/target/xscale/debug_handler.S   |  718 ++++++
 src/target/xscale/debug_handler.cmd |   49 +
 src/target/xscale/protocol.h        |   70 +
 21 files changed, 5038 insertions(+), 74 deletions(-)
 create mode 100644 src/target/arm_simulator.c
 create mode 100644 src/target/arm_simulator.h
 create mode 100644 src/target/xscale.c
 create mode 100644 src/target/xscale.h
 create mode 100644 src/target/xscale/build.sh
 create mode 100644 src/target/xscale/debug_handler.S
 create mode 100644 src/target/xscale/debug_handler.cmd
 create mode 100644 src/target/xscale/protocol.h

diff --git a/src/flash/str7x.c b/src/flash/str7x.c
index 62acba387..0fa2f6ce9 100644
--- a/src/flash/str7x.c
+++ b/src/flash/str7x.c
@@ -451,7 +451,7 @@ int str7x_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 cou
 	u32 address = bank->base + offset;
 	reg_param_t reg_params[5];
 	armv4_5_algorithm_t armv4_5_info;
-	int retval;
+	int retval = ERROR_OK;
 	
 	u32 str7x_flash_write_code[] = {
 					/* write:				*/
@@ -537,12 +537,13 @@ int str7x_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 cou
 		if ((retval = target->type->run_algorithm(target, 0, NULL, 5, reg_params, str7x_info->write_algorithm->address, str7x_info->write_algorithm->address + (19 * 4), 10000, &armv4_5_info)) != ERROR_OK)
 		{
 			ERROR("error executing str7x flash write algorithm");
-			return ERROR_FLASH_OPERATION_FAILED;
+			break;
 		}
 	
 		if (buf_get_u32(reg_params[4].value, 0, 32) != 0x00)
 		{
-			return ERROR_FLASH_OPERATION_FAILED;
+			retval = ERROR_FLASH_OPERATION_FAILED;
+			break;
 		}
 		
 		buffer += thisrun_count * 8;
@@ -558,7 +559,7 @@ int str7x_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 cou
 	destroy_reg_param(&reg_params[3]);
 	destroy_reg_param(&reg_params[4]);
 	
-	return ERROR_OK;
+	return retval;
 }
 
 int str7x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
diff --git a/src/helper/fileio.c b/src/helper/fileio.c
index 756e0f460..648f18794 100644
--- a/src/helper/fileio.c
+++ b/src/helper/fileio.c
@@ -242,22 +242,23 @@ int fileio_open(fileio_t *fileio, char *url, enum fileio_access access,
 	enum fileio_pri_type pri_type, void *pri_info, enum fileio_sec_type sec_type)
 {
 	int retval = ERROR_OK;
-	
-	if ((!url) || (strlen(url) < 3))
+	char *resource_identifier = NULL;
+
+	/* try to identify file location */
+	if ((resource_identifier = strstr(url, "bootp://")) && (resource_identifier == url))
 	{
-		snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "invalid file url");
-		return ERROR_INVALID_ARGUMENTS;
+		ERROR("bootp resource location isn't supported yet");
+		return ERROR_FILEIO_RESOURCE_TYPE_UNKNOWN;
 	}
-	
-	if ((url[0] == '/') || (isalpha(url[0])) || ((url[1] == ':') && (url[2] == '\\')))
+	else if ((resource_identifier = strstr(url, "tftp://")) && (resource_identifier == url))
 	{
-		fileio->location = FILEIO_LOCAL;
+		ERROR("tftp resource location isn't supported yet");
+		return ERROR_FILEIO_RESOURCE_TYPE_UNKNOWN;
 	}
 	else
 	{
-		ERROR("couldn't identify resource location from URL '%s'", url);
-		snprintf(fileio->error_str, FILEIO_MAX_ERROR_STRING, "couldn't identify resource location from URL '%s'", url);
-		return ERROR_FILEIO_LOCATION_UNKNOWN;
+		/* default to local files */
+		fileio->location = FILEIO_LOCAL;
 	}
 	
 	fileio->access = access;
diff --git a/src/jtag/amt_jtagaccel.c b/src/jtag/amt_jtagaccel.c
index dca5c334a..ac2635207 100644
--- a/src/jtag/amt_jtagaccel.c
+++ b/src/jtag/amt_jtagaccel.c
@@ -385,7 +385,7 @@ int amt_jtagaccel_execute_queue(void)
 				break;
 			case JTAG_SLEEP:
 #ifdef _DEBUG_JTAG_IO_
-				DEBUG("sleep", cmd->cmd.sleep->us);
+				DEBUG("sleep %i", cmd->cmd.sleep->us);
 #endif
 				jtag_sleep(cmd->cmd.sleep->us);
 				break;
diff --git a/src/jtag/bitbang.c b/src/jtag/bitbang.c
index 2065f62ab..612483649 100644
--- a/src/jtag/bitbang.c
+++ b/src/jtag/bitbang.c
@@ -248,7 +248,7 @@ int bitbang_execute_queue(void)
 				break;
 			case JTAG_SLEEP:
 #ifdef _DEBUG_JTAG_IO_
-				DEBUG("sleep", cmd->cmd.sleep->us);
+				DEBUG("sleep %i", cmd->cmd.sleep->us);
 #endif
 				jtag_sleep(cmd->cmd.sleep->us);
 				break;
diff --git a/src/jtag/parport.c b/src/jtag/parport.c
index 6386940e8..a46d611fd 100644
--- a/src/jtag/parport.c
+++ b/src/jtag/parport.c
@@ -375,7 +375,7 @@ int parport_init(void)
 	dataport = parport_port;
 	statusport = parport_port + 1;
 	
-	DEBUG("requesting privileges for parallel port 0x%x...", dataport);
+	DEBUG("requesting privileges for parallel port 0x%lx...", dataport);
 #if PARPORT_USE_GIVEIO == 1
 	if (parport_get_giveio_access() != 0)
 #else /* PARPORT_USE_GIVEIO */
diff --git a/src/openocd.c b/src/openocd.c
index 4fbaf467e..0b6d1bc06 100644
--- a/src/openocd.c
+++ b/src/openocd.c
@@ -18,7 +18,7 @@
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
 
-#define OPENOCD_VERSION "Open On-Chip Debugger (2007-03-15 14:30 CET)"
+#define OPENOCD_VERSION "Open On-Chip Debugger (2007-03-28 18:30 CEST)"
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
diff --git a/src/target/Makefile.am b/src/target/Makefile.am
index 3e2b39d33..cf1955a05 100644
--- a/src/target/Makefile.am
+++ b/src/target/Makefile.am
@@ -3,7 +3,7 @@ METASOURCES = AUTO
 noinst_LIBRARIES = libtarget.a
 libtarget_a_SOURCES = target.c register.c breakpoints.c armv4_5.c embeddedice.c etm.c arm7tdmi.c arm9tdmi.c \
 	arm_jtag.c arm7_9_common.c algorithm.c arm920t.c arm720t.c armv4_5_mmu.c armv4_5_cache.c arm_disassembler.c \
-	arm966e.c arm926ejs.c etb.c
+	arm966e.c arm926ejs.c etb.c xscale.c arm_simulator.c
 noinst_HEADERS = target.h register.h armv4_5.h embeddedice.h etm.h arm7tdmi.h arm9tdmi.h \
 		arm_jtag.h arm7_9_common.h arm920t.h arm720t.h armv4_5_mmu.h armv4_5_cache.h breakpoints.h algorithm.h \
-		arm_disassembler.h arm966e.h arm926ejs.h etb.h
+		arm_disassembler.h arm966e.h arm926ejs.h etb.h xscale.h arm_simulator.h
diff --git a/src/target/arm_disassembler.c b/src/target/arm_disassembler.c
index f9e0227af..dd7792825 100644
--- a/src/target/arm_disassembler.c
+++ b/src/target/arm_disassembler.c
@@ -835,6 +835,9 @@ int evaluate_misc_instr(u32 opcode, u32 address, arm_instruction_t *instruction)
 		
 		snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tBLX%s r%i",
 				 address, opcode, COND(opcode), Rm);
+				 
+		instruction->info.b_bl_bx_blx.reg_operand = Rm;
+		instruction->info.b_bl_bx_blx.target_address = -1;
 	}
 	
 	/* Enhanced DSP add/subtracts */
@@ -1078,6 +1081,18 @@ int evaluate_data_proc(u32 opcode, u32 address, arm_instruction_t *instruction)
 			instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = shift_imm;
 			instruction->info.data_proc.shifter_operand.immediate_shift.shift = shift;
 		
+			/* LSR encodes a shift by 32 bit as 0x0 */
+			if ((shift == 0x1) && (shift_imm == 0x0))
+				shift_imm = 0x20;
+		
+			/* ASR encodes a shift by 32 bit as 0x0 */
+			if ((shift == 0x2) && (shift_imm == 0x0))
+				shift_imm = 0x20;
+
+			/* ROR by 32 bit is actually a RRX */
+			if ((shift == 0x3) && (shift_imm == 0x0))
+				shift = 0x4;
+			
 			if ((shift_imm == 0x0) && (shift == 0x0))
 			{
 				snprintf(shifter_operand, 32, "r%i", Rm);
@@ -1090,22 +1105,19 @@ int evaluate_data_proc(u32 opcode, u32 address, arm_instruction_t *instruction)
 				}
 				else if (shift == 0x1) /* LSR */
 				{
-					if (shift_imm == 0x0)
-						shift_imm = 0x32;
 					snprintf(shifter_operand, 32, "r%i, LSR #0x%x", Rm, shift_imm);
 				}
 				else if (shift == 0x2) /* ASR */
 				{
-					if (shift_imm == 0x0)
-						shift_imm = 0x32;
 					snprintf(shifter_operand, 32, "r%i, ASR #0x%x", Rm, shift_imm);
 				}
-				else if (shift == 0x3) /* ROR or RRX */
+				else if (shift == 0x3) /* ROR */
+				{
+					snprintf(shifter_operand, 32, "r%i, ROR #0x%x", Rm, shift_imm);
+				}
+				else if (shift == 0x4) /* RRX */
 				{
-					if (shift_imm == 0x0) /* RRX */
-						snprintf(shifter_operand, 32, "r%i, RRX", Rm);
-					else
-						snprintf(shifter_operand, 32, "r%i, ROR #0x%x", Rm, shift_imm);
+					snprintf(shifter_operand, 32, "r%i, RRX", Rm);
 				}
 			}
 		}
@@ -1130,7 +1142,7 @@ int evaluate_data_proc(u32 opcode, u32 address, arm_instruction_t *instruction)
 			{
 				snprintf(shifter_operand, 32, "r%i, ASR r%i", Rm, Rs);
 			}
-			else if (shift == 0x3) /* ROR or RRX */
+			else if (shift == 0x3) /* ROR */
 			{
 				snprintf(shifter_operand, 32, "r%i, ROR r%i", Rm, Rs);
 			}
@@ -1159,7 +1171,7 @@ int evaluate_data_proc(u32 opcode, u32 address, arm_instruction_t *instruction)
 	return ERROR_OK;
 }
 		
-int evaluate_opcode(u32 opcode, u32 address, arm_instruction_t *instruction)
+int arm_evaluate_opcode(u32 opcode, u32 address, arm_instruction_t *instruction)
 {
 	/* clear fields, to avoid confusion */
 	memset(instruction, 0, sizeof(arm_instruction_t));
@@ -1302,3 +1314,4 @@ int evaluate_opcode(u32 opcode, u32 address, arm_instruction_t *instruction)
 	ERROR("should never reach this point");
 	return -1;
 }
+
diff --git a/src/target/arm_disassembler.h b/src/target/arm_disassembler.h
index c6dc6967d..b55c88550 100644
--- a/src/target/arm_disassembler.h
+++ b/src/target/arm_disassembler.h
@@ -126,28 +126,30 @@ typedef struct arm_b_bl_bx_blx_instr_s
 	u32 target_address;
 } arm_b_bl_bx_blx_instr_t;
 
+union arm_shifter_operand
+{
+	struct {
+		u32 immediate;
+	} immediate;
+	struct {
+		u8 Rm;
+		u8 shift;
+		u8 shift_imm;
+	} immediate_shift;
+	struct {
+		u8 Rm;
+		u8 shift;
+		u8 Rs;
+	} register_shift;
+};
+
 typedef struct arm_data_proc_instr_s
 {
 	int variant; /* 0: immediate, 1: immediate_shift, 2: register_shift */
 	u8 S;
 	u8 Rn;
 	u8 Rd;
-	union
-	{
-		struct {
-			u8 immediate;
-		} immediate;
-		struct {
-			u8 Rm;
-			u8 shift;
-			u8 shift_imm;
-		} immediate_shift;
-		struct {
-			u8 Rm;
-			u8 shift;
-			u8 Rs;
-		} register_shift;
-	} shifter_operand;
+	union arm_shifter_operand shifter_operand;
 } arm_data_proc_instr_t;
 
 typedef struct arm_load_store_instr_s
@@ -192,7 +194,7 @@ typedef struct arm_instruction_s
 
 } arm_instruction_t;
 
-extern int evaluate_opcode(u32 opcode, u32 address, arm_instruction_t *instruction);
+extern int arm_evaluate_opcode(u32 opcode, u32 address, arm_instruction_t *instruction);
 
 #define COND(opcode) (arm_condition_strings[(opcode & 0xf0000000)>>28])
 
diff --git a/src/target/arm_simulator.c b/src/target/arm_simulator.c
new file mode 100644
index 000000000..fd0b309ce
--- /dev/null
+++ b/src/target/arm_simulator.c
@@ -0,0 +1,684 @@
+/***************************************************************************
+ *   Copyright (C) 2006 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   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     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "target.h"
+#include "armv4_5.h"
+#include "arm_disassembler.h"
+#include "arm_simulator.h"
+#include "log.h"
+#include "binarybuffer.h"
+
+#include <string.h>
+
+u32 arm_shift(u8 shift, u32 Rm, u32 shift_amount, u8 *carry)
+{
+	u32 return_value;
+	shift_amount &= 0xff;
+	
+	if (shift == 0x0) /* LSL */
+	{
+		if ((shift_amount > 0) && (shift_amount <= 32))
+		{
+			return_value = Rm << shift_amount;
+			*carry = Rm >> (32 - shift_amount);
+		}
+		else if (shift_amount > 32)
+		{
+			return_value = 0x0;
+			*carry = 0x0;
+		}
+		else /* (shift_amount == 0) */
+		{
+			return_value = Rm;
+		}
+	}
+	else if (shift == 0x1) /* LSR */
+	{
+		if ((shift_amount > 0) && (shift_amount <= 32))
+		{
+			return_value = Rm >> shift_amount;
+			*carry = (Rm >> (shift_amount - 1)) & 1;
+		}
+		else if (shift_amount > 32)
+		{
+			return_value = 0x0;
+			*carry = 0x0;
+		}
+		else /* (shift_amount == 0) */
+		{
+			return_value = Rm;
+		}
+	}
+	else if (shift == 0x2) /* ASR */
+	{
+		if ((shift_amount > 0) && (shift_amount <= 32))
+		{
+			/* right shifts of unsigned values are guaranteed to be logical (shift in zeroes)
+			 * simulate an arithmetic shift (shift in signed-bit) by adding the signed-bit manually */
+			return_value = Rm >> shift_amount;
+			if (Rm & 0x80000000)
+				return_value |= 0xffffffff << (32 - shift_amount);
+		}
+		else if (shift_amount > 32)
+		{
+			if (Rm & 0x80000000)
+			{
+				return_value = 0xffffffff;
+				*carry = 0x1;
+			}
+			else
+			{
+				return_value = 0x0;
+				*carry = 0x0;
+			}
+		}
+		else /* (shift_amount == 0) */
+		{
+			return_value = Rm;
+		}
+	}
+	else if (shift == 0x3) /* ROR */
+	{
+		if (shift_amount == 0)
+		{
+			return_value = Rm;
+		}
+		else
+		{
+			shift_amount = shift_amount % 32;
+			return_value = (Rm >> shift_amount) | (Rm << (32 - shift_amount));
+			*carry = (return_value >> 31) & 0x1;
+		}
+	}
+	else if (shift == 0x4) /* RRX */
+	{
+		return_value = Rm >> 1;
+		if (*carry)
+			Rm |= 0x80000000;
+		*carry = Rm & 0x1;
+	}
+	
+	return return_value;
+}
+
+u32 arm_shifter_operand(armv4_5_common_t *armv4_5, int variant, union arm_shifter_operand shifter_operand, u8 *shifter_carry_out)
+{
+	u32 return_value;
+	int instruction_size;
+	
+	if (armv4_5->core_state == ARMV4_5_STATE_ARM)
+		instruction_size = 4;
+	else
+		instruction_size = 2;
+	
+	*shifter_carry_out = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 29, 1);
+	
+	if (variant == 0) /* 32-bit immediate */
+	{
+		return_value = shifter_operand.immediate.immediate;
+	}
+	else if (variant == 1) /* immediate shift */
+	{
+		u32 Rm = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, shifter_operand.immediate_shift.Rm).value, 0, 32);
+		
+		/* adjust RM in case the PC is being read */
+		if (shifter_operand.immediate_shift.Rm == 15)
+			Rm += 2 * instruction_size;
+		
+		return_value = arm_shift(shifter_operand.immediate_shift.shift, Rm, shifter_operand.immediate_shift.shift_imm, shifter_carry_out);
+	}
+	else if (variant == 2) /* register shift */
+	{
+		u32 Rm = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, shifter_operand.register_shift.Rm).value, 0, 32);
+		u32 Rs = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, shifter_operand.register_shift.Rs).value, 0, 32);
+		
+		/* adjust RM in case the PC is being read */
+		if (shifter_operand.register_shift.Rm == 15)
+			Rm += 2 * instruction_size;
+			
+		return_value = arm_shift(shifter_operand.immediate_shift.shift, Rm, Rs, shifter_carry_out);
+	}
+	else
+	{
+		ERROR("BUG: shifter_operand.variant not 0, 1 or 2");
+		return_value = 0xffffffff;
+	}
+	
+	return return_value;
+}
+
+int pass_condition(u32 cpsr, u32 opcode)
+{
+	switch ((opcode & 0xf0000000) >> 28)
+	{
+		case 0x0:	/* EQ */
+			if (cpsr & 0x40000000)
+				return 1;
+			else
+				return 0;
+		case 0x1:	/* NE */
+			if (!(cpsr & 0x40000000))
+				return 1;
+			else
+				return 0;
+		case 0x2:	/* CS */
+			if (cpsr & 0x20000000)
+				return 1;
+			else
+				return 0;
+		case 0x3:	/* CC */
+			if (!(cpsr & 0x20000000))
+				return 1;
+			else
+				return 0;
+		case 0x4:	/* MI */
+			if (cpsr & 0x80000000)
+				return 1;
+			else
+				return 0;
+		case 0x5:	/* PL */
+			if (!(cpsr & 0x80000000))
+				return 1;
+			else
+				return 0;
+		case 0x6:	/* VS */
+			if (cpsr & 0x10000000)
+				return 1;
+			else
+				return 0;
+		case 0x7:	/* VC */
+			if (!(cpsr & 0x10000000))
+				return 1;
+			else
+				return 0;
+		case 0x8:	/* HI */
+			if ((cpsr & 0x20000000) && !(cpsr & 0x40000000))
+				return 1;
+			else
+				return 0;
+		case 0x9:	/* LS */
+			if (!(cpsr & 0x20000000) || (cpsr & 0x40000000))
+				return 1;
+			else
+				return 0;
+		case 0xa:	/* GE */
+			if (((cpsr & 0x80000000) && (cpsr & 0x10000000))
+				|| (!(cpsr & 0x80000000) && !(cpsr & 0x10000000)))
+				return 1;
+			else
+				return 0;
+		case 0xb:	/* LT */
+			if (((cpsr & 0x80000000) && !(cpsr & 0x10000000))
+				|| (!(cpsr & 0x80000000) && (cpsr & 0x10000000)))
+				return 1;
+			else
+				return 0;
+		case 0xc:	/* GT */
+			if (!(cpsr & 0x40000000) &&
+				(((cpsr & 0x80000000) && (cpsr & 0x10000000))
+				|| (!(cpsr & 0x80000000) && !(cpsr & 0x10000000))))
+				return 1;
+			else
+				return 0;
+		case 0xd:	/* LE */
+			if ((cpsr & 0x40000000) &&
+				(((cpsr & 0x80000000) && !(cpsr & 0x10000000))
+				|| (!(cpsr & 0x80000000) && (cpsr & 0x10000000))))
+				return 1;
+			else
+				return 0;
+		case 0xe:
+		case 0xf:
+			return 1;
+				
+	}
+	
+	ERROR("BUG: should never get here");
+	return 0;
+}
+
+/* simulate a single step (if possible)
+ * if the dry_run_pc argument is provided, no state is changed,
+ * but the new pc is stored in the variable pointed at by the argument
+ */
+int arm_simulate_step(target_t *target, u32 *dry_run_pc)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	u32 opcode;
+	u32 current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
+	arm_instruction_t instruction;
+	int instruction_size;
+	
+	if (armv4_5->core_state == ARMV4_5_STATE_ARM)
+	{
+		/* get current instruction, and identify it */
+		target_read_u32(target, current_pc, &opcode);
+		arm_evaluate_opcode(opcode, current_pc, &instruction);
+		instruction_size = 4;
+	}
+	else
+	{
+		/* TODO: add support for Thumb instruction set */
+		instruction_size = 2;
+	}
+	
+	/* check condition code */
+	if (!pass_condition(buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32), opcode))
+	{
+		if (dry_run_pc)
+		{
+			*dry_run_pc = current_pc + instruction_size;
+		}
+		else
+		{
+			buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, current_pc + instruction_size);
+		}
+		
+		return ERROR_OK;
+	}
+	
+	/* examine instruction type */
+
+	/* branch instructions */
+	if ((instruction.type >= ARM_B) && (instruction.type <= ARM_BLX))
+	{
+		u32 target;
+		
+		if (instruction.info.b_bl_bx_blx.reg_operand == -1)
+		{
+			target = instruction.info.b_bl_bx_blx.target_address;
+		}
+		else
+		{
+			target = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, instruction.info.b_bl_bx_blx.reg_operand).value, 0, 32); 
+		}
+		
+		if (dry_run_pc)
+		{	
+			*dry_run_pc = target;
+			return ERROR_OK;
+		}
+		else
+		{
+			if (instruction.type == ARM_B)
+			{
+				buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, target);
+			}
+			else if (instruction.type == ARM_BL)
+			{
+				u32 old_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
+				buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 14).value, 0, 32, old_pc + 4);
+				buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, target);
+			}
+			else if (instruction.type == ARM_BX)
+			{
+				if (target & 0x1)
+				{
+					armv4_5->core_state = ARMV4_5_STATE_THUMB;
+				}
+				else
+				{
+					armv4_5->core_state = ARMV4_5_STATE_ARM;
+				}
+				buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, target & 0xfffffffe);
+			}
+			else if (instruction.type == ARM_BLX)
+			{
+				u32 old_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
+				buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 14).value, 0, 32, old_pc + 4);
+
+				if (target & 0x1)
+				{
+					armv4_5->core_state = ARMV4_5_STATE_THUMB;
+				}
+				else
+				{
+					armv4_5->core_state = ARMV4_5_STATE_ARM;
+				}
+				buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, target & 0xfffffffe);
+			}
+			
+			return ERROR_OK;
+		}
+	}
+	/* data processing instructions, except compare instructions (CMP, CMN, TST, TEQ) */
+	else if (((instruction.type >= ARM_AND) && (instruction.type <= ARM_RSC))
+			|| ((instruction.type >= ARM_ORR) && (instruction.type <= ARM_MVN)))
+	{
+		u32 Rd, Rn, shifter_operand;
+		u8 C = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 29, 1);
+		u8 carry_out;
+		
+		Rd = 0x0;
+		Rn = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, instruction.info.data_proc.Rn).value, 0, 32);
+		shifter_operand = arm_shifter_operand(armv4_5, instruction.info.data_proc.variant, instruction.info.data_proc.shifter_operand, &carry_out);
+
+		/* adjust Rn in case the PC is being read */
+		if (instruction.info.data_proc.Rn == 15)
+			Rn += 2 * instruction_size;
+				
+		if (instruction.type == ARM_AND)
+			Rd = Rn & shifter_operand;
+		else if (instruction.type == ARM_EOR)
+			Rd = Rn ^ shifter_operand;
+		else if (instruction.type == ARM_SUB)
+			Rd = Rn - shifter_operand;
+		else if (instruction.type == ARM_RSB)
+			Rd = shifter_operand - Rn;
+		else if (instruction.type == ARM_ADD)
+			Rd = Rn + shifter_operand;
+		else if (instruction.type == ARM_ADC)
+			Rd = Rn + shifter_operand + (C & 1);
+		else if (instruction.type == ARM_SBC)
+			Rd = Rn - shifter_operand - (C & 1) ? 0 : 1;
+		else if (instruction.type == ARM_RSC)
+			Rd = shifter_operand - Rn - (C & 1) ? 0 : 1;
+		else if (instruction.type == ARM_ORR)
+			Rd = Rn | shifter_operand;
+		else if (instruction.type == ARM_BIC)
+			Rd = Rn & ~(shifter_operand);
+		else if (instruction.type == ARM_MOV)
+			Rd = shifter_operand;
+		else if (instruction.type == ARM_MVN)
+			Rd = ~shifter_operand;
+		
+		if (dry_run_pc)
+		{
+			if (instruction.info.data_proc.Rd == 15)
+			{
+				*dry_run_pc = Rd;
+				return ERROR_OK;
+			}
+			else
+			{
+				*dry_run_pc = current_pc + instruction_size;
+			}
+			
+			return ERROR_OK;
+		}
+		else
+		{
+			buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, instruction.info.data_proc.Rd).value, 0, 32, Rd);
+			WARNING("no updating of flags yet");
+
+			if (instruction.info.data_proc.Rd == 15)  
+				return ERROR_OK;
+		}
+	}
+	/* compare instructions (CMP, CMN, TST, TEQ) */
+	else if ((instruction.type >= ARM_TST) && (instruction.type <= ARM_CMN))
+	{
+		if (dry_run_pc)
+		{
+			*dry_run_pc = current_pc + instruction_size;
+			return ERROR_OK;
+		}
+		else
+		{
+			WARNING("no updating of flags yet");
+		}
+	}
+	/* load register instructions */
+	else if ((instruction.type >= ARM_LDR) && (instruction.type <= ARM_LDRSH))
+	{
+		u32 load_address, modified_address, load_value;
+		u32 Rn = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, instruction.info.load_store.Rn).value, 0, 32);
+		
+		/* adjust Rn in case the PC is being read */
+		if (instruction.info.load_store.Rn == 15)
+			Rn += 2 * instruction_size;
+		
+		if (instruction.info.load_store.offset_mode == 0)
+		{
+			if (instruction.info.load_store.U)
+				modified_address = Rn + instruction.info.load_store.offset.offset;
+			else
+				modified_address = Rn - instruction.info.load_store.offset.offset;
+		}
+		else if (instruction.info.load_store.offset_mode == 1)
+		{
+			u32 offset;
+			u32 Rm = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, instruction.info.load_store.offset.reg.Rm).value, 0, 32);
+			u8 shift = instruction.info.load_store.offset.reg.shift;
+			u8 shift_imm = instruction.info.load_store.offset.reg.shift_imm;
+			u8 carry = buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 29, 1);
+			
+			offset = arm_shift(shift, Rm, shift_imm, &carry);
+			
+			if (instruction.info.load_store.U)
+				modified_address = Rn + offset;
+			else
+				modified_address = Rn - offset;
+		}
+		else
+		{
+			ERROR("BUG: offset_mode neither 0 (offset) nor 1 (scaled register)");
+		}
+		
+		if (instruction.info.load_store.index_mode == 0)
+		{
+			/* offset mode
+			 * we load from the modified address, but don't change the base address register */
+			load_address = modified_address;
+			modified_address = Rn;
+		}
+		else if (instruction.info.load_store.index_mode == 1)
+		{
+			/* pre-indexed mode
+			 * we load from the modified address, and write it back to the base address register */
+			load_address = modified_address;
+		}
+		else if (instruction.info.load_store.index_mode == 2)
+		{
+			/* post-indexed mode
+			 * we load from the unmodified address, and write the modified address back */
+			 load_address = Rn;
+		}
+		
+		target_read_u32(target, load_address, &load_value);
+		
+		if (dry_run_pc)
+		{
+			if (instruction.info.load_store.Rd == 15)
+			{
+				*dry_run_pc = load_value;
+				return ERROR_OK;
+			}
+			else
+			{
+				*dry_run_pc = current_pc + instruction_size;
+			}
+			
+			return ERROR_OK;
+		}
+		else
+		{
+			if ((instruction.info.load_store.index_mode == 1) ||
+				(instruction.info.load_store.index_mode == 2))
+			{
+				buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, instruction.info.load_store.Rn).value, 0, 32, modified_address);
+			} 
+			buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, instruction.info.load_store.Rd).value, 0, 32, load_value);
+			
+			if (instruction.info.load_store.Rd == 15)
+				return ERROR_OK;
+		}
+	}
+	/* load multiple instruction */
+	else if (instruction.type == ARM_LDM)
+	{
+		int i;
+		u32 Rn = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, instruction.info.load_store_multiple.Rn).value, 0, 32);
+		u32 load_values[16];
+		int bits_set = 0;
+
+		for (i = 0; i < 16; i++)
+		{
+			if (instruction.info.load_store_multiple.register_list & (1 << i))
+				bits_set++;
+		}
+		
+		switch (instruction.info.load_store_multiple.addressing_mode)
+		{
+			case 0: /* Increment after */
+				Rn = Rn;
+				break;
+			case 1: /* Increment before */
+				Rn = Rn + 4;
+				break;
+			case 2: /* Decrement after */
+				Rn = Rn - (bits_set * 4) + 4; 
+				break;
+			case 3: /* Decrement before */
+				Rn = Rn - (bits_set * 4);
+				break;
+		}
+
+		for (i = 0; i < 16; i++)
+		{
+			if (instruction.info.load_store_multiple.register_list & (1 << i))
+			{
+				target_read_u32(target, Rn, &load_values[i]);
+				Rn += 4;
+			}
+		}
+		
+		if (dry_run_pc)
+		{
+			if (instruction.info.load_store_multiple.register_list & 0x8000)
+			{
+				*dry_run_pc = load_values[15];
+				return ERROR_OK;
+			}
+		}
+		else
+		{
+			enum armv4_5_mode mode = armv4_5->core_mode;
+			int update_cpsr = 0;
+
+			if (instruction.info.load_store_multiple.S)
+			{
+				if (instruction.info.load_store_multiple.register_list & 0x8000)
+					update_cpsr = 1;
+				else
+					mode = ARMV4_5_MODE_USR;
+			}
+
+			for (i = 0; i < 16; i++)
+			{
+				if (instruction.info.load_store_multiple.register_list & (1 << i))
+				{
+					buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, mode, i).value, 0, 32, load_values[i]);
+				}
+			}
+			
+			if (update_cpsr)
+			{
+				u32 spsr = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 16).value, 0, 32);
+				buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32, spsr);
+			}
+			
+			/* base register writeback */
+			if (instruction.info.load_store_multiple.W)
+				buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, instruction.info.load_store_multiple.Rn).value, 0, 32, Rn); 
+			
+			if (instruction.info.load_store_multiple.register_list & 0x8000)
+				return ERROR_OK;
+		}
+	}
+	/* store multiple instruction */
+	else if (instruction.type == ARM_STM)
+	{
+		int i;
+
+		if (dry_run_pc)
+		{
+			/* STM wont affect PC (advance by instruction size */
+		}
+		else
+		{
+			u32 Rn = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, instruction.info.load_store_multiple.Rn).value, 0, 32);
+			int bits_set = 0;
+			enum armv4_5_mode mode = armv4_5->core_mode;
+
+			for (i = 0; i < 16; i++)
+			{
+				if (instruction.info.load_store_multiple.register_list & (1 << i))
+					bits_set++;
+			}
+			
+			if (instruction.info.load_store_multiple.S)
+			{
+				mode = ARMV4_5_MODE_USR;
+			}
+			
+			switch (instruction.info.load_store_multiple.addressing_mode)
+			{
+				case 0: /* Increment after */
+					Rn = Rn;
+					break;
+				case 1: /* Increment before */
+					Rn = Rn + 4;
+					break;
+				case 2: /* Decrement after */
+					Rn = Rn - (bits_set * 4) + 4; 
+					break;
+				case 3: /* Decrement before */
+					Rn = Rn - (bits_set * 4);
+					break;
+			}
+			
+			for (i = 0; i < 16; i++)
+			{
+				if (instruction.info.load_store_multiple.register_list & (1 << i))
+				{
+					target_write_u32(target, Rn, buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, i).value, 0, 32));
+					Rn += 4;
+				}
+			}
+			
+			/* base register writeback */
+			if (instruction.info.load_store_multiple.W)
+				buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, instruction.info.load_store_multiple.Rn).value, 0, 32, Rn); 
+			
+		}
+	}
+	else if (!dry_run_pc)
+	{
+		/* the instruction wasn't handled, but we're supposed to simulate it
+		 */
+		return ERROR_ARM_SIMULATOR_NOT_IMPLEMENTED;
+	}
+	
+	if (dry_run_pc)
+	{
+		*dry_run_pc = current_pc + instruction_size;
+		return ERROR_OK;
+	}
+	else
+	{
+		buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, current_pc + instruction_size);
+		return ERROR_OK;
+	}
+	
+}
diff --git a/src/target/arm_simulator.h b/src/target/arm_simulator.h
new file mode 100644
index 000000000..9c28a086b
--- /dev/null
+++ b/src/target/arm_simulator.h
@@ -0,0 +1,31 @@
+/***************************************************************************
+ *   Copyright (C) 2006 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   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     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#ifndef ARM_SIMULATOR_H
+#define ARM_SIMULATOR_H
+
+#include "target.h"
+#include "types.h"
+
+extern int arm_simulate_step(target_t *target, u32 *dry_run_pc);
+
+
+#define ERROR_ARM_SIMULATOR_NOT_IMPLEMENTED	(-1000)
+
+#endif /* ARM_SIMULATOR_H */
diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c
index 3eab03354..dc42d1c02 100644
--- a/src/target/armv4_5.c
+++ b/src/target/armv4_5.c
@@ -442,7 +442,7 @@ int handle_armv4_5_disassemble_command(struct command_context_s *cmd_ctx, char *
 	for (i = 0; i < count; i++)
 	{
 		target_read_u32(target, address, &opcode);
-		evaluate_opcode(opcode, address, &cur_instruction);
+		arm_evaluate_opcode(opcode, address, &cur_instruction);
 		command_print(cmd_ctx, "%s", cur_instruction.text);
 		address += (thumb) ? 2 : 4;
 	}
@@ -598,6 +598,13 @@ int armv4_5_run_algorithm(struct target_s *target, int num_mem_params, mem_param
 		}
 	}
 	
+	if ((retval != ERROR_TARGET_TIMEOUT) && 
+		(buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32) != exit_point))
+	{
+		WARNING("target reentered debug state, but not at the desired exit point: 0x%4.4x",
+			buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32)); 
+	}
+	
 	breakpoint_remove(target, exit_point);
 	
 	for (i = 0; i < num_mem_params; i++)
diff --git a/src/target/armv4_5.h b/src/target/armv4_5.h
index 47996de4f..0ba94ff7c 100644
--- a/src/target/armv4_5.h
+++ b/src/target/armv4_5.h
@@ -213,6 +213,11 @@ extern int armv4_5_invalidate_core_regs(target_t *target);
  */
 #define ARMV4_5_MCR(CP, op1, Rd, CRn, CRm, op2) (0xee000010 | (CRm) | ((op2) << 5) | ((CP) << 8) | ((Rd) << 12) | ((CRn) << 16) | ((op1) << 21)) 
 
+/* Breakpoint instruction (ARMv5)
+ * Im: 16-bit immediate
+ */
+#define ARMV5_BKPT(Im) (0xe1200070 | ((Im & 0xfff0) << 8) | (Im & 0xf))
+
 
 /* Thumb mode instructions
  */
@@ -266,4 +271,9 @@ extern int armv4_5_invalidate_core_regs(target_t *target);
  */
 #define ARMV4_5_T_B(Imm)	((0xe000 | (Imm)) | ((0xe000 | (Imm)) << 16))
 
+/* Breakpoint instruction (ARMv5) (Thumb state)
+ * Im: 8-bit immediate
+ */
+#define ARMV5_T_BKPT(Im) ((0xbe00 | Im) | ((0xbe00 | Im) << 16))
+
 #endif /* ARMV4_5_H */
diff --git a/src/target/target.c b/src/target/target.c
index 376fc52f5..548ea0c39 100644
--- a/src/target/target.c
+++ b/src/target/target.c
@@ -79,6 +79,7 @@ extern target_type_t arm9tdmi_target;
 extern target_type_t arm920t_target;
 extern target_type_t arm966e_target;
 extern target_type_t arm926ejs_target;
+extern target_type_t xscale_target;
 
 target_type_t *target_types[] =
 {
@@ -88,6 +89,7 @@ target_type_t *target_types[] =
 	&arm720t_target,
 	&arm966e_target,
 	&arm926ejs_target,
+	&xscale_target,
 	NULL,
 };
 
@@ -727,60 +729,107 @@ int target_read_buffer(struct target_s *target, u32 address, u32 size, u8 *buffe
 	return ERROR_OK;
 }
 
-void target_read_u32(struct target_s *target, u32 address, u32 *value)
+int target_read_u32(struct target_s *target, u32 address, u32 *value)
 {
 	u8 value_buf[4];
+
+	int retval = target->type->read_memory(target, address, 4, 1, value_buf);
 	
-	target->type->read_memory(target, address, 4, 1, value_buf);
+	if (retval == ERROR_OK)
+	{
+		*value = target_buffer_get_u32(target, value_buf);
+		DEBUG("address: 0x%8.8x, value: 0x%8.8x", address, *value);
+	}
+	else
+	{
+		*value = 0x0;
+		DEBUG("address: 0x%8.8x failed", address);
+	}
 	
-	*value = target_buffer_get_u32(target, value_buf);
-
-	DEBUG("address: 0x%8.8x, value: 0x%8.8x", address, *value);
+	return retval;
 }
 
-void target_read_u16(struct target_s *target, u32 address, u16 *value)
+int target_read_u16(struct target_s *target, u32 address, u16 *value)
 {
 	u8 value_buf[2];
 	
-	target->type->read_memory(target, address, 2, 1, value_buf);
+	int retval = target->type->read_memory(target, address, 2, 1, value_buf);
 	
-	*value = target_buffer_get_u16(target, value_buf);
-
-	DEBUG("address: 0x%8.8x, value: 0x%4.4x", address, *value);
+	if (retval == ERROR_OK)
+	{
+		*value = target_buffer_get_u16(target, value_buf);
+		DEBUG("address: 0x%8.8x, value: 0x%4.4x", address, *value);
+	}
+	else
+	{
+		*value = 0x0;
+		DEBUG("address: 0x%8.8x failed", address);
+	}
+	
+	return retval;
 }
 
-void target_read_u8(struct target_s *target, u32 address, u8 *value)
+int target_read_u8(struct target_s *target, u32 address, u8 *value)
 {
-	target->type->read_memory(target, address, 1, 1, value);
+	int retval = target->type->read_memory(target, address, 1, 1, value);
 
-	DEBUG("address: 0x%8.8x, value: 0x%2.2x", address, *value);
+	if (retval == ERROR_OK)
+	{
+		DEBUG("address: 0x%8.8x, value: 0x%2.2x", address, *value);
+	}
+	else
+	{
+		*value = 0x0;
+		DEBUG("address: 0x%8.8x failed", address);
+	}
+	
+	return retval;
 }
 
-void target_write_u32(struct target_s *target, u32 address, u32 value)
+int target_write_u32(struct target_s *target, u32 address, u32 value)
 {
+	int retval;
 	u8 value_buf[4];
 
 	DEBUG("address: 0x%8.8x, value: 0x%8.8x", address, value);
 
 	target_buffer_set_u32(target, value_buf, value);	
-	target->type->write_memory(target, address, 4, 1, value_buf);
+	if ((retval = target->type->write_memory(target, address, 4, 1, value_buf)) != ERROR_OK)
+	{
+		DEBUG("failed: %i", retval);
+	}
+	
+	return retval;
 }
 
-void target_write_u16(struct target_s *target, u32 address, u16 value)
+int target_write_u16(struct target_s *target, u32 address, u16 value)
 {
+	int retval;
 	u8 value_buf[2];
 	
 	DEBUG("address: 0x%8.8x, value: 0x%8.8x", address, value);
 
 	target_buffer_set_u16(target, value_buf, value);	
-	target->type->write_memory(target, address, 2, 1, value_buf);
+	if ((retval = target->type->write_memory(target, address, 2, 1, value_buf)) != ERROR_OK)
+	{
+		DEBUG("failed: %i", retval);
+	}
+	
+	return retval;
 }
 
-void target_write_u8(struct target_s *target, u32 address, u8 value)
+int target_write_u8(struct target_s *target, u32 address, u8 value)
 {
+	int retval;
+	
 	DEBUG("address: 0x%8.8x, value: 0x%2.2x", address, value);
 
-	target->type->read_memory(target, address, 1, 1, &value);
+	if ((retval = target->type->read_memory(target, address, 1, 1, &value)) != ERROR_OK)
+	{
+		DEBUG("failed: %i", retval);
+	}
+	
+	return retval;
 }
 
 int target_register_user_commands(struct command_context_s *cmd_ctx)
diff --git a/src/target/target.h b/src/target/target.h
index 04157fde1..d340a7780 100644
--- a/src/target/target.h
+++ b/src/target/target.h
@@ -50,6 +50,8 @@ enum daemon_startup_mode
 	DAEMON_RESET,		/* reset target (behaviour defined by reset_mode */
 };
 
+extern enum daemon_startup_mode startup_mode;
+
 enum target_reset_mode
 {
 	RESET_RUN = 0,		/* reset and let target run */
@@ -222,12 +224,12 @@ extern u16 target_buffer_get_u16(target_t *target, u8 *buffer);
 extern void target_buffer_set_u32(target_t *target, u8 *buffer, u32 value);
 extern void target_buffer_set_u16(target_t *target, u8 *buffer, u16 value);
 
-void target_read_u32(struct target_s *target, u32 address, u32 *value);
-void target_read_u16(struct target_s *target, u32 address, u16 *value);
-void target_read_u8(struct target_s *target, u32 address, u8 *value);
-void target_write_u32(struct target_s *target, u32 address, u32 value);
-void target_write_u16(struct target_s *target, u32 address, u16 value);
-void target_write_u8(struct target_s *target, u32 address, u8 value);
+int target_read_u32(struct target_s *target, u32 address, u32 *value);
+int target_read_u16(struct target_s *target, u32 address, u16 *value);
+int target_read_u8(struct target_s *target, u32 address, u8 *value);
+int target_write_u32(struct target_s *target, u32 address, u32 value);
+int target_write_u16(struct target_s *target, u32 address, u16 value);
+int target_write_u8(struct target_s *target, u32 address, u8 value);
 
 #define ERROR_TARGET_INVALID	(-300)
 #define ERROR_TARGET_INIT_FAILED (-301)
diff --git a/src/target/xscale.c b/src/target/xscale.c
new file mode 100644
index 000000000..d6c9f215c
--- /dev/null
+++ b/src/target/xscale.c
@@ -0,0 +1,3175 @@
+/***************************************************************************
+ *   Copyright (C) 2006 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   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     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#include "config.h"
+
+#include "xscale.h"
+
+#include "register.h"
+#include "target.h"
+#include "armv4_5.h"
+#include "arm_simulator.h"
+#include "log.h"
+#include "jtag.h"
+#include "binarybuffer.h"
+#include "time_support.h"
+#include "breakpoints.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+
+/* cli handling */
+int xscale_register_commands(struct command_context_s *cmd_ctx);
+
+/* forward declarations */
+int xscale_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
+int xscale_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
+int xscale_quit();
+
+int xscale_arch_state(struct target_s *target, char *buf, int buf_size);
+enum target_state 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);
+
+target_type_t xscale_target =
+{
+	.name = "xscale",
+
+	.poll = xscale_poll,
+	.arch_state = xscale_arch_state,
+
+	.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,
+
+	.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_command = xscale_target_command,
+	.init_target = xscale_init_target,
+	.quit = xscale_quit
+};
+
+char* xscale_reg_list[] =
+{
+	"XSCALE_MAINID",		/* 0 */
+	"XSCALE_CACHETYPE",
+	"XSCALE_CTRL",
+	"XSCALE_AUXCTRL",
+	"XSCALE_TTB",
+	"XSCALE_DAC",
+	"XSCALE_FSR",
+	"XSCALE_FAR",
+	"XSCALE_PID",
+	"XSCALE_CPACCESS",
+	"XSCALE_IBCR0",			/* 10 */
+	"XSCALE_IBCR1",
+	"XSCALE_DBR0",
+	"XSCALE_DBR1",
+	"XSCALE_DBCON",
+	"XSCALE_TBREG",
+	"XSCALE_CHKPT0",		
+	"XSCALE_CHKPT1",
+	"XSCALE_DCSR",
+	"XSCALE_TX",
+	"XSCALE_RX",			/* 20 */
+	"XSCALE_TXRXCTRL",
+};
+
+xscale_reg_t xscale_reg_arch_info[] =
+{
+	{XSCALE_MAINID, NULL},
+	{XSCALE_CACHETYPE, NULL},
+	{XSCALE_CTRL, NULL},
+	{XSCALE_AUXCTRL, NULL},
+	{XSCALE_TTB, NULL},
+	{XSCALE_DAC, NULL},
+	{XSCALE_FSR, NULL},
+	{XSCALE_FAR, NULL},
+	{XSCALE_PID, NULL},
+	{XSCALE_CPACCESS, NULL},
+	{XSCALE_IBCR0, NULL},
+	{XSCALE_IBCR1, NULL},
+	{XSCALE_DBR0, NULL},
+	{XSCALE_DBR1, NULL},
+	{XSCALE_DBCON, NULL},
+	{XSCALE_TBREG, NULL},
+	{XSCALE_CHKPT0, NULL},
+	{XSCALE_CHKPT1, NULL},
+	{XSCALE_DCSR, NULL}, /* DCSR accessed via JTAG or SW */
+	{-1, NULL}, /* TX accessed via JTAG */
+	{-1, NULL}, /* RX accessed via JTAG */
+	{-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)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	xscale_common_t *xscale = armv4_5->arch_info;
+	
+	if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
+	{
+		return -1;
+	}
+	
+	if (xscale->common_magic != XSCALE_COMMON_MAGIC)
+	{
+		return -1;
+	}
+	
+	*armv4_5_p = armv4_5;
+	*xscale_p = xscale;
+	
+	return ERROR_OK;
+}
+
+int xscale_jtag_set_instr(int chain_pos, u32 new_instr)
+{
+	jtag_device_t *device = jtag_get_device(chain_pos);
+	
+	if (buf_get_u32(device->cur_instr, 0, device->ir_length) != new_instr)
+	{
+		scan_field_t field;
+	
+		field.device = chain_pos;
+		field.num_bits = device->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;
+		field.in_check_value = device->expected;
+		field.in_check_mask = device->expected_mask;
+		field.in_handler = NULL;
+		field.in_handler_priv = NULL;
+		
+		jtag_add_ir_scan(1, &field, -1);
+		
+		free(field.out_value);
+	}
+	
+	return ERROR_OK;
+}
+
+int xscale_jtag_callback(enum jtag_event event, void *priv)
+{
+	switch (event)
+	{
+		case JTAG_TRST_ASSERTED:
+			break;
+		case JTAG_TRST_RELEASED:
+			break;
+		case JTAG_SRST_ASSERTED:
+			break;
+		case JTAG_SRST_RELEASED:
+			break;
+		default:
+			WARNING("unhandled JTAG event");
+	}
+	
+	return ERROR_OK;
+}
+
+int xscale_read_dcsr(target_t *target)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	xscale_common_t *xscale = armv4_5->arch_info;
+	
+	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_PD);
+	xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.dcsr);
+	
+	buf_set_u32(&field0, 1, 1, xscale->hold_rst);
+	buf_set_u32(&field0, 2, 1, xscale->external_debug_break);
+	
+	fields[0].device = xscale->jtag_info.chain_pos;
+	fields[0].num_bits = 3;
+	fields[0].out_value = &field0;
+	fields[0].out_mask = NULL;
+	fields[0].in_value = NULL;
+	fields[0].in_check_value = &field0_check_value;
+	fields[0].in_check_mask = &field0_check_mask;
+	fields[0].in_handler = NULL;
+	fields[0].in_handler_priv = NULL;
+		
+	fields[1].device = xscale->jtag_info.chain_pos;
+	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].device = xscale->jtag_info.chain_pos;
+	fields[2].num_bits = 1;
+	fields[2].out_value = &field2;
+	fields[2].out_mask = NULL;
+	fields[2].in_value = NULL;
+	fields[2].in_check_value = &field2_check_value;
+	fields[2].in_check_mask = &field2_check_mask;
+	fields[2].in_handler = NULL;
+	fields[2].in_handler_priv = NULL;
+	
+	jtag_add_dr_scan(3, fields, -1);
+
+	if ((retval = jtag_execute_queue()) != ERROR_OK)
+	{
+		ERROR("JTAG error while reading DCSR");
+		exit(-1);
+	}
+	
+	xscale->reg_cache->reg_list[XSCALE_DCSR].dirty = 0;
+	xscale->reg_cache->reg_list[XSCALE_DCSR].valid = 1;
+	
+	/* write the register with the value we just read
+	 * on this second pass, only the first bit of field0 is guaranteed to be 0)
+	 */
+	field0_check_mask = 0x1;
+	fields[1].out_value = xscale->reg_cache->reg_list[XSCALE_DCSR].value;
+	fields[1].in_value = NULL;
+	
+	jtag_add_end_state(TAP_RTI);
+	
+	jtag_add_dr_scan(3, fields, -1);
+	
+	return ERROR_OK;
+}
+
+int xscale_receive(target_t *target, u32 *buffer, int num_words)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	xscale_common_t *xscale = armv4_5->arch_info;
+	
+	enum tap_state 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;
+	int words_done = 0;
+	int words_scheduled = 0;
+	
+	int i;
+	int retval;
+
+	path[0] = TAP_SDS;
+	path[1] = TAP_CD;
+	path[2] = TAP_SD;
+	
+	fields[0].device = xscale->jtag_info.chain_pos;
+	fields[0].num_bits = 3;
+	fields[0].out_value = NULL;
+	fields[0].out_mask = NULL;
+	/* fields[0].in_value = field0; */
+	fields[0].in_check_value = &field0_check_value;
+	fields[0].in_check_mask = &field0_check_mask;
+	fields[0].in_handler = NULL;
+	fields[0].in_handler_priv = NULL;
+		
+	fields[1].device = xscale->jtag_info.chain_pos;
+	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].device = xscale->jtag_info.chain_pos;
+	fields[2].num_bits = 1;
+	fields[2].out_value = NULL;
+	fields[2].out_mask = NULL;
+	fields[2].in_value = NULL;
+	fields[2].in_check_value = &field2_check_value;
+	fields[2].in_check_mask = &field2_check_mask;
+	fields[2].in_handler = NULL;
+	fields[2].in_handler_priv = NULL;
+
+	jtag_add_end_state(TAP_RTI);
+	xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.dbgtx);
+	jtag_add_runtest(1, -1);
+	
+	/* repeat until all words have been collected */
+	while (words_done < num_words)
+	{
+		/* schedule reads */
+		words_scheduled = 0;
+		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_RTI);
+			words_scheduled++;
+		}
+		
+		if ((retval = jtag_execute_queue()) != ERROR_OK)
+		{
+			ERROR("JTAG error while receiving data from debug handler");
+			exit(-1);
+		}
+		
+		/* examine results */
+		for (i = words_done; i < num_words; i++)
+		{
+			if (!(field0[0] & 1))
+			{
+				/* move backwards if necessary */
+				int j;
+				for (j = i; j < num_words - 1; j++)
+				{
+					field0[j] = field0[j+1];
+					field1[j] = field1[j+1];
+				}
+				words_scheduled--;
+			}
+		}
+		words_done += words_scheduled;
+	}
+	
+	for (i = 0; i < num_words; i++)
+		*(buffer++) = buf_get_u32((u8*)&field1[i], 0, 32);
+	
+	free(field1);
+	
+	return ERROR_OK;
+}
+
+int xscale_read_tx(target_t *target, int consume)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	xscale_common_t *xscale = armv4_5->arch_info;
+	enum tap_state path[3];
+	
+	int retval;
+	struct timeval timeout, now;
+	
+	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_RTI);
+	
+	xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.dbgtx);
+	
+	path[0] = TAP_SDS;
+	path[1] = TAP_CD;
+	path[2] = TAP_SD;
+	
+	fields[0].device = xscale->jtag_info.chain_pos;
+	fields[0].num_bits = 3;
+	fields[0].out_value = NULL;
+	fields[0].out_mask = NULL;
+	fields[0].in_value = &field0_in;
+	fields[0].in_check_value = &field0_check_value;
+	fields[0].in_check_mask = &field0_check_mask;
+	fields[0].in_handler = NULL;
+	fields[0].in_handler_priv = NULL;
+		
+	fields[1].device = xscale->jtag_info.chain_pos;
+	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].device = xscale->jtag_info.chain_pos;
+	fields[2].num_bits = 1;
+	fields[2].out_value = NULL;
+	fields[2].out_mask = NULL;
+	fields[2].in_value = NULL;
+	fields[2].in_check_value = &field2_check_value;
+	fields[2].in_check_mask = &field2_check_mask;
+	fields[2].in_handler = NULL;
+	fields[2].in_handler_priv = NULL;
+	
+	gettimeofday(&timeout, NULL);
+	timeval_add_time(&timeout, 5, 0);
+	
+	do
+	{
+		/* if we want to consume the register content (i.e. clear TX_READY),
+		 * we have to go straight from Capture-DR to Shift-DR
+		 * otherwise, we go from Capture-DR to Exit1-DR to Pause-DR
+		*/
+		if (consume)
+			jtag_add_pathmove(3, path);
+		else
+			jtag_add_statemove(TAP_PD);
+		
+		jtag_add_dr_scan(3, fields, TAP_RTI);
+	
+		if ((retval = jtag_execute_queue()) != ERROR_OK)
+		{
+			ERROR("JTAG error while reading TX");
+			exit(-1);
+		}
+		
+		gettimeofday(&now, NULL);
+		if ((now.tv_sec > timeout.tv_sec) && (now.tv_usec > timeout.tv_usec))
+		{
+			ERROR("time out reading TX register");
+			return ERROR_TARGET_TIMEOUT;
+		}
+	} while ((!(field0_in & 1)) && consume);
+	
+	if (!(field0_in & 1))
+		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+		
+	return ERROR_OK;
+}
+
+int xscale_write_rx(target_t *target)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	xscale_common_t *xscale = armv4_5->arch_info;
+	
+	int retval;
+	struct timeval timeout, now;
+	
+	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_RTI);
+	
+	xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.dbgrx);
+	
+	fields[0].device = xscale->jtag_info.chain_pos;
+	fields[0].num_bits = 3;
+	fields[0].out_value = &field0_out;
+	fields[0].out_mask = NULL;
+	fields[0].in_value = &field0_in;
+	fields[0].in_check_value = &field0_check_value;
+	fields[0].in_check_mask = &field0_check_mask;
+	fields[0].in_handler = NULL;
+	fields[0].in_handler_priv = NULL;
+		
+	fields[1].device = xscale->jtag_info.chain_pos;
+	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].device = xscale->jtag_info.chain_pos;
+	fields[2].num_bits = 1;
+	fields[2].out_value = &field2;
+	fields[2].out_mask = NULL;
+	fields[2].in_value = NULL;
+	fields[2].in_check_value = &field2_check_value;
+	fields[2].in_check_mask = &field2_check_mask;
+	fields[2].in_handler = NULL;
+	fields[2].in_handler_priv = NULL;
+	
+	gettimeofday(&timeout, NULL);
+	timeval_add_time(&timeout, 5, 0);
+	
+	/* poll until rx_read is low */
+	do
+	{
+		DEBUG("polling RX");
+		jtag_add_dr_scan(3, fields, TAP_RTI);
+	
+		if ((retval = jtag_execute_queue()) != ERROR_OK)
+		{
+			ERROR("JTAG error while writing RX");
+			exit(-1);
+		}
+		
+		gettimeofday(&now, NULL);
+		if ((now.tv_sec > timeout.tv_sec) && (now.tv_usec > timeout.tv_usec))
+		{
+			ERROR("time out writing RX register");
+			return ERROR_TARGET_TIMEOUT;
+		}
+	} while (field0_in & 1);
+	
+	/* set rx_valid */
+	field2 = 0x1;
+	jtag_add_dr_scan(3, fields, TAP_RTI);
+	
+	if ((retval = jtag_execute_queue()) != ERROR_OK)
+	{
+		ERROR("JTAG error while writing RX");
+		exit(-1);
+	}
+	
+	return ERROR_OK;
+}
+
+/* send count elements of size byte to the debug handler */
+int xscale_send(target_t *target, u8 *buffer, int count, int size)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	xscale_common_t *xscale = armv4_5->arch_info;
+		
+	int retval;
+	
+	int done_count = 0;
+	u8 output[4] = {0, 0, 0, 0};
+	
+	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 = 0x1;
+	u8 field2_check_value = 0x0;
+	u8 field2_check_mask = 0x1;
+	
+	jtag_add_end_state(TAP_RTI);
+	
+	xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.dbgrx);
+	
+	fields[0].device = xscale->jtag_info.chain_pos;
+	fields[0].num_bits = 3;
+	fields[0].out_value = &field0_out;
+	fields[0].out_mask = NULL;
+	fields[0].in_value = &field0_in;
+	fields[0].in_check_value = &field0_check_value;
+	fields[0].in_check_mask = &field0_check_mask;
+	fields[0].in_handler = NULL;
+	fields[0].in_handler_priv = NULL;
+		
+	fields[1].device = xscale->jtag_info.chain_pos;
+	fields[1].num_bits = 32;
+	fields[1].out_value = output;
+	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].device = xscale->jtag_info.chain_pos;
+	fields[2].num_bits = 1;
+	fields[2].out_value = &field2;
+	fields[2].out_mask = NULL;
+	fields[2].in_value = NULL;
+	fields[2].in_check_value = &field2_check_value;
+	fields[2].in_check_mask = &field2_check_mask;
+	fields[2].in_handler = NULL;
+	fields[2].in_handler_priv = NULL;
+	
+	while (done_count++ < count)
+	{
+		/* extract sized element from target-endian buffer, and put it 
+		 * into little-endian output buffer
+		 */
+		switch (size)
+		{
+			case 4:
+				buf_set_u32(output, 0, 32, target_buffer_get_u32(target, buffer));
+				break;
+			case 2:
+				buf_set_u32(output, 0, 32, target_buffer_get_u16(target, buffer));
+				break;
+			case 1:
+				output[0] = *buffer;
+				break;
+			default:
+				ERROR("BUG: size neither 4, 2 nor 1");
+				exit(-1); 
+		}
+
+		jtag_add_dr_scan(3, fields, TAP_RTI);
+		buffer += size;
+	}
+	
+	if ((retval = jtag_execute_queue()) != ERROR_OK)
+	{
+		ERROR("JTAG error while sending data to debug handler");
+		exit(-1);
+	}
+	
+	return ERROR_OK;
+}
+
+int xscale_send_u32(target_t *target, u32 value)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	xscale_common_t *xscale = armv4_5->arch_info;
+	
+	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)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	xscale_common_t *xscale = armv4_5->arch_info;
+	
+	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;
+	
+	if (hold_rst != -1)
+		xscale->hold_rst = hold_rst;
+	
+	if (ext_dbg_brk != -1)
+		xscale->external_debug_break = ext_dbg_brk;
+
+	jtag_add_end_state(TAP_RTI);
+	xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.dcsr);
+	
+	buf_set_u32(&field0, 1, 1, xscale->hold_rst);
+	buf_set_u32(&field0, 2, 1, xscale->external_debug_break);
+	
+	fields[0].device = xscale->jtag_info.chain_pos;
+	fields[0].num_bits = 3;
+	fields[0].out_value = &field0;
+	fields[0].out_mask = NULL;
+	fields[0].in_value = NULL;
+	fields[0].in_check_value = &field0_check_value;
+	fields[0].in_check_mask = &field0_check_mask;
+	fields[0].in_handler = NULL;
+	fields[0].in_handler_priv = NULL;
+		
+	fields[1].device = xscale->jtag_info.chain_pos;
+	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].device = xscale->jtag_info.chain_pos;
+	fields[2].num_bits = 1;
+	fields[2].out_value = &field2;
+	fields[2].out_mask = NULL;
+	fields[2].in_value = NULL;
+	fields[2].in_check_value = &field2_check_value;
+	fields[2].in_check_mask = &field2_check_mask;
+	fields[2].in_handler = NULL;
+	fields[2].in_handler_priv = NULL;
+	
+	jtag_add_dr_scan(3, fields, -1);
+	
+	if ((retval = jtag_execute_queue()) != ERROR_OK)
+	{
+		ERROR("JTAG error while writing DCSR");
+		exit(-1);
+	}
+	
+	xscale->reg_cache->reg_list[XSCALE_DCSR].dirty = 0;
+	xscale->reg_cache->reg_list[XSCALE_DCSR].valid = 1;
+	
+	return ERROR_OK;
+}
+
+/* parity of the number of bits 0 if even; 1 if odd. for 32 bit words */
+unsigned int parity (unsigned int v)
+{
+	unsigned int ov = v;
+	v ^= v >> 16;
+	v ^= v >> 8;
+	v ^= v >> 4;
+	v &= 0xf;
+	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])
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	xscale_common_t *xscale = armv4_5->arch_info;
+	u8 packet[4];
+	u8 cmd;
+	int word;
+	
+	scan_field_t fields[2];
+
+	DEBUG("loading miniIC at 0x%8.8x", va);
+
+	jtag_add_end_state(TAP_RTI);
+	xscale_jtag_set_instr(xscale->jtag_info.chain_pos, 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);
+		
+	/* virtual address of desired cache line */
+	buf_set_u32(packet, 0, 27, va >> 5);
+	
+	fields[0].device = xscale->jtag_info.chain_pos;
+	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].device = xscale->jtag_info.chain_pos;
+	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, -1);
+
+	fields[0].num_bits = 32;
+	fields[0].out_value = packet;
+	
+	fields[1].num_bits = 1;
+	fields[1].out_value = &cmd;
+	
+	for (word = 0; word < 8; word++)
+	{
+		buf_set_u32(packet, 0, 32, buffer[word]);
+		cmd = parity(*((u32*)packet));
+		jtag_add_dr_scan(2, fields, -1);
+	}
+	
+	jtag_execute_queue();
+	
+	return ERROR_OK;
+}
+
+int xscale_invalidate_ic_line(target_t *target, u32 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];
+
+	jtag_add_end_state(TAP_RTI);
+	xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.ldic); /* LDIC */
+	
+	/* CMD for invalidate IC line b000, bits [6:4] b000 */
+	buf_set_u32(&cmd, 0, 6, 0x0);
+	
+	/* virtual address of desired cache line */
+	buf_set_u32(packet, 0, 27, va >> 5);
+	
+	fields[0].device = xscale->jtag_info.chain_pos;
+	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].device = xscale->jtag_info.chain_pos;
+	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, -1);
+	
+	return ERROR_OK;
+}
+
+int xscale_update_vectors(target_t *target)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	xscale_common_t *xscale = armv4_5->arch_info;
+	int i;
+	
+	u32 low_reset_branch, high_reset_branch;
+
+	for (i = 1; i < 8; i++)
+	{
+		/* if there's a static vector specified for this exception, override */
+		if (xscale->static_high_vectors_set & (1 << i))
+		{
+			xscale->high_vectors[i] = xscale->static_high_vectors[i];
+		}
+		else
+		{
+			if (target_read_u32(target, 0xffff0000 + 4*i, &xscale->high_vectors[i]) != ERROR_OK)
+			{
+				xscale->high_vectors[i] = ARMV4_5_B(0xfffffe, 0);
+			}
+		}
+	}
+
+	for (i = 1; i < 8; i++)
+	{
+		if (xscale->static_low_vectors_set & (1 << i))
+		{
+			xscale->low_vectors[i] = xscale->static_low_vectors[i];
+		}
+		else
+		{
+			if (target_read_u32(target, 0x0 + 4*i, &xscale->low_vectors[i]) != ERROR_OK)
+			{
+				xscale->low_vectors[i] = ARMV4_5_B(0xfffffe, 0);
+			}
+		}
+	}
+	
+	/* calculate branches to debug handler */
+	low_reset_branch = (xscale->handler_address + 0x20 - 0x0 - 0x8) >> 2;
+	high_reset_branch = (xscale->handler_address + 0x20 - 0xffff0000 - 0x8) >> 2;
+	
+	xscale->low_vectors[0] = ARMV4_5_B((low_reset_branch & 0xffffff), 0);
+	xscale->high_vectors[0] = ARMV4_5_B((high_reset_branch & 0xffffff), 0);
+	
+	/* invalidate and load exception vectors in mini i-cache */
+	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);
+	
+	return ERROR_OK;
+}
+
+int xscale_arch_state(struct target_s *target, char *buf, int buf_size)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	xscale_common_t *xscale = armv4_5->arch_info;
+	
+	char *state[] = 
+	{
+		"disabled", "enabled"
+	};
+	
+	char *arch_dbg_reason[] =
+	{
+		"", "\n(processor reset)", "\n(trace buffer full)"
+	};
+	
+	if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
+	{
+		ERROR("BUG: called for a non-ARMv4/5 target");
+		exit(-1);
+	}
+	
+	snprintf(buf, buf_size,
+			"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],
+			 target_debug_reason_strings[target->debug_reason],
+			 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),
+			 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],
+			 arch_dbg_reason[xscale->arch_debug_reason]);
+	
+	return ERROR_OK;
+}
+
+enum target_state xscale_poll(target_t *target)
+{
+	int retval;
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	xscale_common_t *xscale = armv4_5->arch_info;
+	
+	if ((target->state == TARGET_RUNNING) || (target->state == TARGET_DEBUG_RUNNING))
+	{
+		if ((retval = xscale_read_tx(target, 0)) == ERROR_OK)
+		{
+			/* there's data to read from the tx register, we entered debug state */
+			xscale->handler_running = 1;
+			
+			/* process debug entry, fetching current mode regs */
+			if ((retval = xscale_debug_entry(target)) != ERROR_OK)
+				return retval;
+			
+			/* if target was running, signal that we halted
+			 * otherwise we reentered from debug execution */
+			if (target->state == TARGET_RUNNING)
+				target_call_event_callbacks(target, TARGET_EVENT_HALTED);
+			else
+				target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
+
+			target->state = TARGET_HALTED;
+		}
+		else if (retval != ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
+		{
+			ERROR("error while polling TX register");
+			exit(-1);
+		}
+	}
+	
+	return target->state;
+}
+
+int xscale_debug_entry(target_t *target)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	xscale_common_t *xscale = armv4_5->arch_info;
+	u32 pc;
+	u32 *buffer = malloc(4 * 10);
+	int i;
+	
+	u32 moe;
+	
+	/* clear external dbg break (will be written on next DCSR read) */
+	xscale->external_debug_break = 0;
+	xscale_read_dcsr(target);
+	
+	/* get r0, pc, r1 to r7 and cpsr */
+	xscale_receive(target, buffer, 10);
+	
+	/* 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;
+	DEBUG("r0: 0x%8.8x", 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;
+	DEBUG("pc: 0x%8.8x", buffer[1]);
+	
+	/* move data from buffer to register cache */
+	for (i = 1; i <= 7; i++)
+	{
+		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;
+		DEBUG("r%i: 0x%8.8x", 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;
+	DEBUG("cpsr: 0x%8.8x", buffer[9]);
+	
+	armv4_5->core_mode = buffer[9] & 0x1f;
+	if (armv4_5_mode_to_number(armv4_5->core_mode) == -1)
+	{
+		target->state = TARGET_UNKNOWN;
+		ERROR("cpsr contains invalid mode value - communication failure");
+		return ERROR_TARGET_FAILURE;
+	}
+	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;
+	
+	/* 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))
+	{
+		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;
+	}
+	else
+	{
+		/* r8 to r14, but no spsr */
+		xscale_receive(target, buffer, 7);
+	}
+	
+	/* move data from buffer to register 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;
+	}
+	
+	/* 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);
+	
+	switch (moe)
+	{
+		case 0x0: /* Processor reset */
+			target->debug_reason = DBG_REASON_DBGRQ;
+			xscale->arch_debug_reason = XSCALE_DBG_REASON_RESET;
+			pc -= 4;
+			break;
+		case 0x1: /* Instruction breakpoint hit */
+			target->debug_reason = DBG_REASON_BREAKPOINT;
+			xscale->arch_debug_reason = XSCALE_DBG_REASON_GENERIC;
+			pc -= 4;
+			break;
+		case 0x2: /* Data breakpoint hit */
+			target->debug_reason = DBG_REASON_WATCHPOINT;
+			xscale->arch_debug_reason = XSCALE_DBG_REASON_GENERIC;
+			pc -= 4;
+			break;
+		case 0x3: /* BKPT instruction executed */
+			target->debug_reason = DBG_REASON_BREAKPOINT;
+			xscale->arch_debug_reason = XSCALE_DBG_REASON_GENERIC;
+			pc -= 4;
+			break;
+		case 0x4: /* Ext. debug event */
+			target->debug_reason = DBG_REASON_DBGRQ;
+			xscale->arch_debug_reason = XSCALE_DBG_REASON_GENERIC;
+			pc -= 4;
+			break;
+		case 0x5: /* Vector trap occured */
+			target->debug_reason = DBG_REASON_BREAKPOINT;
+			xscale->arch_debug_reason = XSCALE_DBG_REASON_GENERIC;
+			pc -= 4;
+			break;
+		case 0x6: /* Trace buffer full break */
+			target->debug_reason = DBG_REASON_DBGRQ;
+			xscale->arch_debug_reason = XSCALE_DBG_REASON_TB_FULL;
+			pc -= 4;
+			break;
+		case 0x7: /* Reserved */
+		default:
+			ERROR("Method of Entry is 'Reserved'");
+			exit(-1);
+			break;
+	}
+	
+	/* apply PC fixup */
+	buf_set_u32(armv4_5->core_cache->reg_list[15].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;
+		
+		/* read cp15 cache type register */
+		xscale_get_reg(&xscale->reg_cache->reg_list[XSCALE_CACHETYPE]);
+		cache_type_reg = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_CACHETYPE].value, 0, 32);
+		
+		armv4_5_identify_cache(cache_type_reg, &xscale->armv4_5_mmu.armv4_5_cache);
+	}
+	
+	/* examine MMU and Cache settings */
+	/* read cp15 control register */
+	xscale_get_reg(&xscale->reg_cache->reg_list[XSCALE_CTRL]);
+	xscale->cp15_control_reg = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_CTRL].value, 0, 32);
+	xscale->armv4_5_mmu.mmu_enabled = (xscale->cp15_control_reg & 0x1U) ? 1 : 0;
+	xscale->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = (xscale->cp15_control_reg & 0x4U) ? 1 : 0;
+	xscale->armv4_5_mmu.armv4_5_cache.i_cache_enabled = (xscale->cp15_control_reg & 0x1000U) ? 1 : 0;
+	
+	return ERROR_OK;
+}
+
+int xscale_halt(target_t *target)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	xscale_common_t *xscale = armv4_5->arch_info;
+	
+	DEBUG("target->state: %s", target_state_strings[target->state]);
+	
+	if (target->state == TARGET_HALTED)
+	{
+		WARNING("target was already halted");
+		return ERROR_TARGET_ALREADY_HALTED;
+	} 
+	else if (target->state == TARGET_UNKNOWN)
+	{
+		/* this must not happen for a xscale target */
+		ERROR("target was in unknown state when halt was requested");
+		exit(-1);
+	}
+	else if (target->state == TARGET_RESET)
+	{
+		DEBUG("target->state == TARGET_RESET");
+		
+		/* clear TRST */
+		jtag_add_reset(0, -1);
+	}
+	else
+	{
+		/* assert external dbg break */
+		xscale->external_debug_break = 1;
+		xscale_read_dcsr(target);
+	
+		target->debug_reason = DBG_REASON_DBGRQ;
+	}
+	
+	return ERROR_OK;
+}
+
+int xscale_enable_single_step(struct target_s *target, u32 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];
+	
+	if (xscale->ibcr0_used)
+	{
+		breakpoint_t *ibcr0_bp = breakpoint_find(target, buf_get_u32(ibcr0->value, 0, 32) & 0xfffffffe);
+		
+		if (ibcr0_bp)
+		{
+			xscale_unset_breakpoint(target, ibcr0_bp);
+		}
+		else
+		{
+			ERROR("BUG: xscale->ibcr0_used is set, but no breakpoint with that address found");
+			exit(-1);
+		}
+	}
+	
+	xscale_set_reg_u32(ibcr0, next_pc | 0x1);
+	
+	return ERROR_OK;
+}
+
+int xscale_disable_single_step(struct target_s *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];
+	
+	xscale_set_reg_u32(ibcr0, 0x0);
+	
+	return ERROR_OK;
+}
+
+int xscale_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	xscale_common_t *xscale= armv4_5->arch_info;
+	breakpoint_t *breakpoint = target->breakpoints;
+	
+	u32 current_pc;
+	
+	int retval;
+	int i;
+	
+	DEBUG("-");
+	
+	if (target->state != TARGET_HALTED)
+	{
+		WARNING("target not halted");
+		return ERROR_TARGET_NOT_HALTED;
+	}
+	
+	if (!debug_execution)
+	{
+		target_free_all_working_areas(target);
+	}
+	
+	/* update vector tables */
+	xscale_update_vectors(target);
+	
+	/* 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);
+
+	current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].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);
+	}
+	
+	/* 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))))
+		{
+			u32 next_pc;
+			
+			/* there's a breakpoint at the current PC, we have to step over it */
+			DEBUG("unset breakpoint at 0x%8.8x", 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;
+				target_read_u32(target, current_pc, &current_opcode);
+				ERROR("BUG: couldn't calculate PC of next instruction, current opcode was 0x%8.8x", current_opcode);
+			}
+			
+			DEBUG("enable single-step");
+			xscale_enable_single_step(target, next_pc);
+			
+			/* restore banked registers */
+			xscale_restore_context(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 CPSR */
+			xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32));
+			DEBUG("writing cpsr with value 0x%8.8x", buf_get_u32(armv4_5->core_cache->reg_list[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));
+				DEBUG("writing r%i with value 0x%8.8x", 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));
+			DEBUG("writing PC with value 0x%8.8x", buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
+			
+			/* wait for and process debug entry */
+			xscale_debug_entry(target);
+			
+			DEBUG("disable single-step");
+			xscale_disable_single_step(target);
+			
+			DEBUG("set breakpoint at 0x%8.8x", breakpoint->address);
+			xscale_set_breakpoint(target, breakpoint);
+		}
+	}
+	
+	/* enable any pending breakpoints and watchpoints */
+	xscale_enable_breakpoints(target);
+	xscale_enable_watchpoints(target);
+	
+	/* restore banked registers */
+	xscale_restore_context(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 CPSR */
+	xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32));
+	DEBUG("writing cpsr with value 0x%8.8x", buf_get_u32(armv4_5->core_cache->reg_list[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));
+		DEBUG("writing r%i with value 0x%8.8x", 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));
+	DEBUG("writing PC with value 0x%8.8x", buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
+		
+	target->debug_reason = DBG_REASON_NOTHALTED;
+		
+	if (!debug_execution)
+	{
+		/* registers are now invalid */
+		armv4_5_invalidate_core_regs(target);
+		target->state = TARGET_RUNNING;
+		target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
+	}
+	else
+	{
+		target->state = TARGET_DEBUG_RUNNING;
+		target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED);
+	}
+	
+	DEBUG("target resumed");
+	
+	xscale->handler_running = 1;
+	
+	return ERROR_OK;
+}
+
+int xscale_step(struct target_s *target, int current, u32 address, int handle_breakpoints)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	xscale_common_t *xscale = armv4_5->arch_info;
+	breakpoint_t *breakpoint = target->breakpoints;
+	
+	u32 current_pc, next_pc;
+	int i;
+	int retval;
+
+	if (target->state != TARGET_HALTED)
+	{
+		WARNING("target not halted");
+		return ERROR_TARGET_NOT_HALTED;
+	}
+	
+	/* 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);
+	
+	current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
+	
+	/* if we're at the reset vector, we have to simulate the step */
+	if (current_pc == 0x0)
+	{
+		arm_simulate_step(target, NULL);
+		current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
+		
+		target->debug_reason = DBG_REASON_SINGLESTEP;
+		target_call_event_callbacks(target, TARGET_EVENT_HALTED);
+		
+		return ERROR_OK;
+	}
+	
+	/* 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))))
+		{
+			xscale_unset_breakpoint(target, breakpoint);
+		}
+	
+	target->debug_reason = DBG_REASON_SINGLESTEP;
+
+	/* calculate PC of next instruction */
+	if ((retval = arm_simulate_step(target, &next_pc)) != ERROR_OK)
+	{
+		u32 current_opcode;
+		target_read_u32(target, current_pc, &current_opcode);
+		ERROR("BUG: couldn't calculate PC of next instruction, current opcode was 0x%8.8x", current_opcode);
+	}
+	
+	DEBUG("enable single-step");
+	xscale_enable_single_step(target, next_pc);
+	
+	/* restore banked registers */
+	xscale_restore_context(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 CPSR */
+	xscale_send_u32(target, buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32));
+	DEBUG("writing cpsr with value 0x%8.8x", buf_get_u32(armv4_5->core_cache->reg_list[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));
+		DEBUG("writing r%i with value 0x%8.8x", 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));
+	DEBUG("writing PC with value 0x%8.8x", buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32));
+
+	target_call_event_callbacks(target, TARGET_EVENT_RESUMED);
+
+	/* registers are now invalid */
+	armv4_5_invalidate_core_regs(target);
+	
+	/* wait for and process debug entry */
+	xscale_debug_entry(target);
+	
+	DEBUG("disable single-step");
+	xscale_disable_single_step(target);
+		
+	target_call_event_callbacks(target, TARGET_EVENT_HALTED);
+
+	if (breakpoint)
+	{
+		xscale_set_breakpoint(target, breakpoint);
+	}
+		
+	DEBUG("target stepped");
+
+	return ERROR_OK;
+
+}
+
+int xscale_assert_reset(target_t *target)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	xscale_common_t *xscale = armv4_5->arch_info;
+	
+	DEBUG("target->state: %s", target_state_strings[target->state]);
+	
+	/* if the handler isn't installed yet, we have to assert TRST, too */
+	if (!xscale->handler_installed)
+	{
+		jtag_add_reset(1, 1);
+	}
+	else
+		jtag_add_reset(-1, 1);
+	
+	/* sleep 1ms, to be sure we fulfill any requirements */
+	jtag_add_sleep(1000);
+	
+	target->state = TARGET_RESET;
+	
+	return ERROR_OK;
+
+}
+
+int xscale_deassert_reset(target_t *target)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	xscale_common_t *xscale = armv4_5->arch_info;
+	
+	FILE *binary;
+	u32 address;
+	struct stat binary_stat;
+	u32 binary_size;
+
+	u32 buffer[8];
+	u32 buf_cnt;
+	int i;
+	
+	breakpoint_t *breakpoint = target->breakpoints;
+	
+	xscale->ibcr_available = 2;
+	xscale->ibcr0_used = 0;
+	xscale->ibcr1_used = 0;
+		
+	xscale->dbr_available = 2;
+	xscale->dbr0_used = 0;
+	xscale->dbr1_used = 0;
+	
+	/* mark all hardware breakpoints as unset */
+	while (breakpoint)
+	{
+		if (breakpoint->type == BKPT_HARD)
+		{
+			breakpoint->set = 0;
+		}
+		breakpoint = breakpoint->next;
+	}
+	
+	if (!xscale->handler_installed)
+	{
+		/* release TRST */
+		jtag_add_reset(0, -1);
+		jtag_add_sleep(100000);
+		
+		/* set Hold reset, Halt mode and Trap Reset */
+		buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 30, 1, 0x1);
+		buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 16, 1, 0x1);
+		xscale_write_dcsr(target, 1, 0);
+		jtag_add_runtest(100, TAP_RTI);
+		jtag_execute_queue();
+		
+		/* release SRST */
+		jtag_add_reset(0, 0);
+		/* wait 150ms; 100ms were not enough */
+		jtag_add_sleep(150000);
+
+		jtag_add_runtest(2030, TAP_RTI);
+		jtag_execute_queue();
+		
+		xscale_write_dcsr(target, 1, 0);
+		jtag_execute_queue();
+		
+		/* TODO: load debug handler */
+		if (stat("target/xscale/debug_handler.bin", &binary_stat) == -1)
+		{
+			ERROR("couldn't stat() target/xscale/debug_handler.bin: %s",  strerror(errno));
+			return ERROR_OK;
+		}
+		
+		if (!(binary = fopen("target/xscale/debug_handler.bin", "r")))
+		{
+			ERROR("couldn't open target/xscale/debug_handler.bin: %s", strerror(errno));
+			return ERROR_OK;
+		}
+		
+		if ((binary_size = binary_stat.st_size) % 4)
+		{
+			ERROR("debug_handler.bin: size not a multiple of 4");
+			exit(-1);
+		}
+			
+		if (binary_size > 0x800)
+		{
+			ERROR("debug_handler.bin: larger than 2kb");
+			exit(-1);
+		}
+		
+		binary_size = CEIL(binary_size, 32) * 32;
+		
+		address = xscale->handler_address;
+		while (binary_size > 0)
+		{
+			buf_cnt = fread(buffer, 4, 8, binary);
+			
+			for (i = 0; i < buf_cnt; i++)
+			{
+				/* convert LE buffer to host-endian u32 */
+				buffer[i] = buf_get_u32((u8*)(&buffer[i]), 0, 32);
+			}
+			
+			if (buf_cnt < 8)
+			{
+				for (; buf_cnt < 8; buf_cnt++)
+				{
+					buffer[buf_cnt] = 0xe1a08008;
+				}
+			}
+			
+			/* only load addresses other than the reset vectors */
+			if ((address % 0x400) != 0x0)
+			{
+				xscale_load_ic(target, 1, address, buffer);
+			}
+			
+			address += buf_cnt * 4;
+			binary_size -= buf_cnt * 4;
+		};
+		
+		xscale_load_ic(target, 1, 0x0, xscale->low_vectors);
+		xscale_load_ic(target, 1, 0xffff0000, xscale->high_vectors);
+	
+		jtag_add_runtest(30, TAP_RTI);
+		
+		/* let the target run (should enter debug handler) */
+		xscale_write_dcsr(target, 0, 0);
+		target->state = TARGET_RUNNING;
+		
+		if ((target->reset_mode != RESET_HALT) && (target->reset_mode != RESET_INIT))
+		{
+			jtag_add_sleep(10000);
+			
+			/* we should have entered debug now */
+			xscale_debug_entry(target);
+			target->state = TARGET_HALTED;
+			
+			/* the PC is now at 0x0 */
+			buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, 0x0);
+		}
+	}
+	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)
+{
+
+	return ERROR_OK;
+}
+
+int xscale_write_core_reg(struct target_s *target, int num, enum armv4_5_mode mode, u32 value)
+{
+	
+	return ERROR_OK;
+}
+
+int xscale_full_context(target_t *target)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	
+	u32 *buffer;
+	
+	int i, j;
+	
+	DEBUG("-");
+	
+	if (target->state != TARGET_HALTED)
+	{
+		WARNING("target not halted");
+		return ERROR_TARGET_NOT_HALTED;
+	}
+	
+	buffer = malloc(4 * 8);
+	
+	/* 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++)
+	{
+		int valid = 1;
+		
+		/* check if there are invalid registers in the current mode 
+		 */
+		for (j = 0; 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 (!valid)
+		{
+			u32 tmp_cpsr;
+			
+			/* 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 mode */
+			xscale_send_u32(target, tmp_cpsr);
+
+			/* 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++)
+			{
+				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;
+			}
+		}
+	}
+	
+	free(buffer);
+	
+	return ERROR_OK;
+}
+
+int xscale_restore_context(target_t *target)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	
+	int i, j;
+	
+	DEBUG("-");
+	
+	if (target->state != TARGET_HALTED)
+	{
+		WARNING("target not halted");
+		return ERROR_TARGET_NOT_HALTED;
+	}
+	
+	/* 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++)
+	{
+		int dirty = 0;
+		
+		/* check if there are invalid registers in the current 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 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 (ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_number_to_mode(i), 16).dirty == 1)
+				dirty = 1;
+		}
+		
+		if (dirty)
+		{
+			u32 tmp_cpsr;
+			
+			/* send banked registers */
+			xscale_send_u32(target, 0x1);
+			
+			tmp_cpsr = 0x0;
+			tmp_cpsr |= armv4_5_number_to_mode(i);
+			tmp_cpsr |= 0xc0; /* I/F bits */
+			
+			/* send CPSR for desired mode */
+			xscale_send_u32(target, tmp_cpsr);
+
+			/* 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;
+			}
+			
+			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;
+			}
+		}
+	}
+	
+	return ERROR_OK;
+}
+
+int xscale_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	xscale_common_t *xscale = armv4_5->arch_info;
+	u32 *buf32;
+	int i;
+	
+	DEBUG("address: 0x%8.8x, size: 0x%8.8x, count: 0x%8.8x", address, size, count);
+
+	if (target->state != TARGET_HALTED)
+	{
+		WARNING("target not halted");
+		return ERROR_TARGET_NOT_HALTED;
+	}
+
+	/* sanitize arguments */
+	if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
+		return ERROR_INVALID_ARGUMENTS;
+
+	if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
+		return ERROR_TARGET_UNALIGNED_ACCESS;
+	
+	/* send memory read request (command 0x1n, n: access size) */
+	xscale_send_u32(target, 0x10 | size);
+	
+	/* send base address for read request */
+	xscale_send_u32(target, address);
+	
+	/* send number of requested data words */
+	xscale_send_u32(target, count);
+	
+	/* receive data from target (count times 32-bit words in host endianness) */
+	buf32 = malloc(4 * count);
+	xscale_receive(target, buf32, count);
+	
+	/* extract data from host-endian buffer into byte stream */
+	for (i = 0; i < count; i++)
+	{
+		switch (size)
+		{
+			case 4:
+				target_buffer_set_u32(target, buffer, buf32[i]);
+				buffer += 4;
+				break;
+			case 2:
+				target_buffer_set_u16(target, buffer, buf32[i] & 0xffff);
+				buffer += 2;
+				break;
+			case 1:
+				*buffer++ = buf32[i] & 0xff;
+				break;
+			default:
+				ERROR("should never get here");
+				exit(-1);
+		}
+	}
+
+	free(buf32);
+	
+	/* examine DCSR, to see if Sticky Abort (SA) got set */ 
+	xscale_read_dcsr(target);
+	if (buf_get_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 5, 1) == 1)
+	{
+		/* clear SA bit */
+		xscale_send_u32(target, 0x60);
+		
+		return ERROR_TARGET_DATA_ABORT;
+	}
+	
+	return ERROR_OK;
+}
+
+int xscale_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	xscale_common_t *xscale = armv4_5->arch_info;
+	
+	DEBUG("address: 0x%8.8x, size: 0x%8.8x, count: 0x%8.8x", address, size, count);
+
+	if (target->state != TARGET_HALTED)
+	{
+		WARNING("target not halted");
+		return ERROR_TARGET_NOT_HALTED;
+	}
+
+	/* sanitize arguments */
+	if (((size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer))
+		return ERROR_INVALID_ARGUMENTS;
+
+	if (((size == 4) && (address & 0x3u)) || ((size == 2) && (address & 0x1u)))
+		return ERROR_TARGET_UNALIGNED_ACCESS;
+	
+	/* send memory write request (command 0x2n, n: access size) */
+	xscale_send_u32(target, 0x20 | size);
+	
+	/* send base address for read request */
+	xscale_send_u32(target, address);
+	
+	/* send number of requested data words to be written*/
+	xscale_send_u32(target, count);
+	
+	/* extract data from host-endian buffer into byte stream */
+#if 0
+	for (i = 0; i < count; i++)
+	{
+		switch (size)
+		{
+			case 4:
+				value = target_buffer_get_u32(target, buffer);
+				xscale_send_u32(target, value);
+				buffer += 4;
+				break;
+			case 2:
+				value = target_buffer_get_u16(target, buffer);
+				xscale_send_u32(target, value);
+				buffer += 2;
+				break;
+			case 1:
+				value = *buffer;
+				xscale_send_u32(target, value);
+				buffer += 1; 
+				break;
+			default:
+				ERROR("should never get here");
+				exit(-1);
+		}
+	}
+#endif
+	xscale_send(target, buffer, count, size);
+	
+	/* examine DCSR, to see if Sticky Abort (SA) got set */ 
+	xscale_read_dcsr(target);
+	if (buf_get_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 5, 1) == 1)
+	{
+		/* clear SA bit */
+		xscale_send_u32(target, 0x60);
+		
+		return ERROR_TARGET_DATA_ABORT;
+	}
+	
+	return ERROR_OK;
+}
+
+int xscale_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffer)
+{
+	xscale_write_memory(target, address, 4, count, buffer);
+	
+	return ERROR_OK;
+}
+
+u32 xscale_get_ttb(target_t *target)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	xscale_common_t *xscale = armv4_5->arch_info;
+	u32 ttb;
+
+	xscale_get_reg(&xscale->reg_cache->reg_list[XSCALE_TTB]);
+	ttb = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_TTB].value, 0, 32);
+
+	return ttb;
+}
+
+void xscale_disable_mmu_caches(target_t *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;
+
+	/* read cp15 control register */
+	xscale_get_reg(&xscale->reg_cache->reg_list[XSCALE_CTRL]);
+	cp15_control = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_CTRL].value, 0, 32);
+	
+	if (mmu)
+		cp15_control &= ~0x1U;
+	
+	if (d_u_cache)
+	{
+		/* clean DCache */
+		xscale_send_u32(target, 0x50);
+		xscale_send_u32(target, xscale->cache_clean_address);
+		
+		/* invalidate DCache */
+		xscale_send_u32(target, 0x51);
+		
+		cp15_control &= ~0x4U;
+	}
+	
+	if (i_cache)
+	{
+		/* invalidate ICache */
+		xscale_send_u32(target, 0x52);
+		cp15_control &= ~0x1000U;
+	}
+
+	/* write new cp15 control register */
+	xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_CTRL], cp15_control);
+	
+	/* execute cpwait to ensure outstanding operations complete */
+	xscale_send_u32(target, 0x53);
+}
+
+void xscale_enable_mmu_caches(target_t *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;
+
+	/* read cp15 control register */
+	xscale_get_reg(&xscale->reg_cache->reg_list[XSCALE_CTRL]);
+	cp15_control = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_CTRL].value, 0, 32);
+			
+	if (mmu)
+		cp15_control |= 0x1U;
+	
+	if (d_u_cache)
+		cp15_control |= 0x4U;
+	
+	if (i_cache)
+		cp15_control |= 0x1000U;
+	
+	/* write new cp15 control register */
+	xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_CTRL], cp15_control);
+	
+	/* execute cpwait to ensure outstanding operations complete */
+	xscale_send_u32(target, 0x53);
+}
+
+int xscale_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	xscale_common_t *xscale = armv4_5->arch_info;
+	
+	if (target->state != TARGET_HALTED)
+	{
+		WARNING("target not halted");
+		return ERROR_TARGET_NOT_HALTED;
+	}
+	
+	if (xscale->force_hw_bkpts)
+		breakpoint->type = BKPT_HARD;
+
+	if (breakpoint->set)
+	{
+		WARNING("breakpoint already set");
+		return ERROR_OK;
+	}
+
+	if (breakpoint->type == BKPT_HARD)
+	{
+		u32 value = breakpoint->address | 1;
+		if (!xscale->ibcr0_used)
+		{
+			xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_IBCR0], value); 
+			xscale->ibcr0_used = 1;
+			breakpoint->set = 1;	/* breakpoint set on first breakpoint register */
+		}
+		else if (!xscale->ibcr1_used)
+		{
+			xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_IBCR1], value); 
+			xscale->ibcr1_used = 1;
+			breakpoint->set = 2;	/* breakpoint set on second breakpoint register */
+		}
+		else
+		{
+			ERROR("BUG: no hardware comparator available");
+			return ERROR_OK;
+		}
+	}
+	else if (breakpoint->type == BKPT_SOFT)
+	{
+		if (breakpoint->length == 4)
+		{
+			/* keep the original instruction in target endianness */
+			target->type->read_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr);
+			/* write the original instruction in target endianness (arm7_9->arm_bkpt is host endian) */
+			target_write_u32(target, breakpoint->address, xscale->arm_bkpt);
+		}
+		else
+		{
+			/* keep the original instruction in target endianness */
+			target->type->read_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr);
+			/* write the original instruction in target endianness (arm7_9->arm_bkpt is host endian) */
+			target_write_u32(target, breakpoint->address, xscale->thumb_bkpt);
+		}
+		breakpoint->set = 1;
+	}
+
+	return ERROR_OK;
+
+}
+
+int xscale_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	xscale_common_t *xscale = armv4_5->arch_info;
+	
+	if (target->state != TARGET_HALTED)
+	{
+		WARNING("target not halted");
+		return ERROR_TARGET_NOT_HALTED;
+	}
+	
+	if (xscale->force_hw_bkpts)
+	{
+		DEBUG("forcing use of hardware breakpoint at address 0x%8.8x", breakpoint->address);
+		breakpoint->type = BKPT_HARD;
+	}
+	
+	if ((breakpoint->type == BKPT_HARD) && (xscale->ibcr_available < 1))
+	{
+		INFO("no breakpoint unit available for hardware breakpoint");
+		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+	}
+	else
+	{
+		xscale->ibcr_available--;
+	}
+	
+	if ((breakpoint->length != 2) && (breakpoint->length != 4))
+	{
+		INFO("only breakpoints of two (Thumb) or four (ARM) bytes length supported");
+		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+	}
+	
+	return ERROR_OK;
+}
+
+int xscale_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	xscale_common_t *xscale = armv4_5->arch_info;
+	
+	if (target->state != TARGET_HALTED)
+	{
+		WARNING("target not halted");
+		return ERROR_TARGET_NOT_HALTED;
+	}
+
+	if (!breakpoint->set)
+	{
+		WARNING("breakpoint not set");
+		return ERROR_OK;
+	}
+	
+	if (breakpoint->type == BKPT_HARD)
+	{
+		if (breakpoint->set == 1)
+		{
+			xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_IBCR0], 0x0); 
+			xscale->ibcr0_used = 0;
+		}
+		else if (breakpoint->set == 2)
+		{
+			xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_IBCR1], 0x0); 
+			xscale->ibcr1_used = 0;
+		}
+		breakpoint->set = 0;
+	}
+	else
+	{
+		/* restore original instruction (kept in target endianness) */
+		if (breakpoint->length == 4)
+		{
+			target->type->write_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr);
+		}
+		else
+		{
+			target->type->write_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr);
+		}
+		breakpoint->set = 0;
+	}
+
+	return ERROR_OK;
+}
+
+int xscale_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	xscale_common_t *xscale = armv4_5->arch_info;
+	
+	if (target->state != TARGET_HALTED)
+	{
+		WARNING("target not halted");
+		return ERROR_TARGET_NOT_HALTED;
+	}
+	
+	if (breakpoint->set)
+	{
+		xscale_unset_breakpoint(target, breakpoint);
+	}
+	
+	if (breakpoint->type == BKPT_HARD)
+		xscale->ibcr_available++;
+	
+	return ERROR_OK;
+}
+
+int xscale_set_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	xscale_common_t *xscale = armv4_5->arch_info;
+	u8 enable;
+	reg_t *dbcon = &xscale->reg_cache->reg_list[XSCALE_DBCON];
+	u32 dbcon_value = buf_get_u32(dbcon->value, 0, 32);
+	
+	if (target->state != TARGET_HALTED)
+	{
+		WARNING("target not halted");
+		return ERROR_TARGET_NOT_HALTED;
+	}
+	
+	xscale_get_reg(dbcon);
+	
+	switch (watchpoint->rw)
+	{
+		case WPT_READ:
+			enable = 0x3;
+			break;
+		case WPT_ACCESS:
+			enable = 0x2;
+			break;
+		case WPT_WRITE:
+			enable = 0x1;
+			break;
+		default:
+			ERROR("BUG: watchpoint->rw neither read, write nor access");	
+	}
+
+	if (!xscale->dbr0_used)
+	{
+		xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_DBR0], watchpoint->address);
+		dbcon_value |= enable;
+		xscale_set_reg_u32(dbcon, dbcon_value);
+		watchpoint->set = 1;
+		xscale->dbr0_used = 1;
+	}
+	else if (!xscale->dbr1_used)
+	{
+		xscale_set_reg_u32(&xscale->reg_cache->reg_list[XSCALE_DBR1], watchpoint->address);
+		dbcon_value |= enable << 2;
+		xscale_set_reg_u32(dbcon, dbcon_value);
+		watchpoint->set = 2;
+		xscale->dbr1_used = 1;
+	}
+	else
+	{
+		ERROR("BUG: no hardware comparator available");
+		return ERROR_OK;
+	}
+	
+	return ERROR_OK;
+}
+
+int xscale_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	xscale_common_t *xscale = armv4_5->arch_info;
+	
+	if (target->state != TARGET_HALTED)
+	{
+		WARNING("target not halted");
+		return ERROR_TARGET_NOT_HALTED;
+	}
+	
+	if (xscale->dbr_available < 1)
+	{
+		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+	}
+	
+	if ((watchpoint->length != 1) && (watchpoint->length != 2) && (watchpoint->length != 4))
+	{
+		return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+	}
+	
+	xscale->dbr_available--;
+		
+	return ERROR_OK;
+}
+
+int xscale_unset_watchpoint(struct target_s *target, watchpoint_t *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);
+	
+	if (target->state != TARGET_HALTED)
+	{
+		WARNING("target not halted");
+		return ERROR_TARGET_NOT_HALTED;
+	}
+	
+	if (!watchpoint->set)
+	{
+		WARNING("breakpoint not set");
+		return ERROR_OK;
+	}
+	
+	if (watchpoint->set == 1)
+	{
+		dbcon_value &= ~0x3;
+		xscale_set_reg_u32(dbcon, dbcon_value);
+		xscale->dbr0_used = 0;
+	}
+	else if (watchpoint->set == 2)
+	{
+		dbcon_value &= ~0xc;
+		xscale_set_reg_u32(dbcon, dbcon_value);
+		xscale->dbr1_used = 0;
+	}
+	watchpoint->set = 0;
+
+	return ERROR_OK;
+}
+
+int xscale_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	xscale_common_t *xscale = armv4_5->arch_info;
+	
+	if (target->state != TARGET_HALTED)
+	{
+		WARNING("target not halted");
+		return ERROR_TARGET_NOT_HALTED;
+	}
+	
+	if (watchpoint->set)
+	{
+		xscale_unset_watchpoint(target, watchpoint);
+	}
+		
+	xscale->dbr_available++;
+	
+	return ERROR_OK;
+}
+
+void xscale_enable_watchpoints(struct target_s *target)
+{
+	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;
+		
+	/* DCSR, TX and RX are accessible via JTAG */
+	if (strcmp(reg->name, "XSCALE_DCSR") == 0)
+	{
+		return xscale_read_dcsr(arch_info->target);
+	}
+	else if (strcmp(reg->name, "XSCALE_TX") == 0)
+	{
+		/* 1 = consume register content */
+		return xscale_read_tx(arch_info->target, 1);
+	}
+	else if (strcmp(reg->name, "XSCALE_RX") == 0)
+	{
+		/* can't read from RX register (host -> debug handler) */
+		return ERROR_OK;
+	}
+	else if (strcmp(reg->name, "XSCALE_TXRXCTRL") == 0)
+	{
+		/* can't (explicitly) read from TXRXCTRL register */
+		return ERROR_OK;
+	}
+	else /* Other DBG registers have to be transfered by the debug handler */
+	{
+		/* send CP read request (command 0x40) */
+		xscale_send_u32(target, 0x40);
+		
+		/* send CP register number */
+		xscale_send_u32(target, arch_info->dbg_handler_number);
+
+		/* read register value */
+		xscale_read_tx(target, 1);
+		buf_cpy(xscale->reg_cache->reg_list[XSCALE_TX].value, reg->value, 32);
+
+		reg->dirty = 0;
+		reg->valid = 1;
+	}
+	
+	return ERROR_OK;
+}
+
+int xscale_set_reg(reg_t *reg, u8* 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);
+	
+	/* DCSR, TX and RX are accessible via JTAG */
+	if (strcmp(reg->name, "XSCALE_DCSR") == 0)
+	{
+		buf_set_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 0, 32, value);
+		return xscale_write_dcsr(arch_info->target, -1, -1);
+	}
+	else if (strcmp(reg->name, "XSCALE_RX") == 0)
+	{
+		buf_set_u32(xscale->reg_cache->reg_list[XSCALE_RX].value, 0, 32, value);
+		return xscale_write_rx(arch_info->target);
+	}
+	else if (strcmp(reg->name, "XSCALE_TX") == 0)
+	{
+		/* can't write to TX register (debug-handler -> host) */
+		return ERROR_OK;
+	}
+	else if (strcmp(reg->name, "XSCALE_TXRXCTRL") == 0)
+	{
+		/* can't (explicitly) write to TXRXCTRL register */
+		return ERROR_OK;
+	}
+	else /* Other DBG registers have to be transfered by the debug handler */
+	{
+		/* send CP write request (command 0x41) */
+		xscale_send_u32(target, 0x41);
+		
+		/* send CP register number */
+		xscale_send_u32(target, arch_info->dbg_handler_number);
+		
+		/* send CP register value */
+		xscale_send_u32(target, value);
+		buf_set_u32(reg->value, 0, 32, value);
+	}
+	
+	return ERROR_OK;
+}
+
+/* convenience wrapper to access XScale specific registers */
+int xscale_set_reg_u32(reg_t *reg, u32 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;
+	
+	/* send CP write request (command 0x41) */
+	xscale_send_u32(target, 0x41);
+		
+	/* send CP register number */
+	xscale_send_u32(target, dcsr_arch_info->dbg_handler_number);
+		
+	/* send CP register value */
+	xscale_send_u32(target, value);
+	buf_set_u32(dcsr->value, 0, 32, value);
+	
+	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;
+
+	reg_cache_t **cache_p = register_get_last_cache_p(&target->reg_cache);
+	xscale_reg_t *arch_info = malloc(sizeof(xscale_reg_arch_info));
+	int i;
+	int num_regs = sizeof(xscale_reg_arch_info) / sizeof(xscale_reg_t);
+	
+	(*cache_p) = armv4_5_build_reg_cache(target, armv4_5);
+	armv4_5->core_cache = (*cache_p);
+	
+	/* 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 = &(*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)->num_regs = num_regs;
+	
+	for (i = 0; i < num_regs; i++)
+	{
+		(*cache_p)->reg_list[i].name = xscale_reg_list[i];
+		(*cache_p)->reg_list[i].value = calloc(4, 1);
+		(*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;
+		arch_info[i] = xscale_reg_arch_info[i];
+		arch_info[i].target = target;
+	}
+	
+	xscale->reg_cache = (*cache_p);
+}
+
+int xscale_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
+{
+	if (startup_mode != DAEMON_RESET)
+	{
+		ERROR("XScale target requires a reset");
+		ERROR("Reset target to enable debug");
+	}
+	
+	return ERROR_OK;
+}
+
+int xscale_quit()
+{
+	
+	return ERROR_OK;
+}
+
+int xscale_init_arch_info(target_t *target, xscale_common_t *xscale, int chain_pos, char *variant)
+{
+	armv4_5_common_t *armv4_5;
+	u32 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;
+	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.chain_pos = chain_pos;
+	jtag_register_event_callback(xscale_jtag_callback, target);
+
+	xscale->jtag_info.dbgrx = 0x02;
+	xscale->jtag_info.dbgtx = 0x10;
+	xscale->jtag_info.dcsr = 0x09;
+	xscale->jtag_info.ldic = 0x07;	
+
+	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;
+	}
+	
+	/* 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 */
+	memset(xscale->low_vectors, 0, sizeof(xscale->low_vectors));
+	memset(xscale->high_vectors, 0, sizeof(xscale->high_vectors));
+
+	/* no user-specified vectors have been configured yet */
+	xscale->static_low_vectors_set = 0x0;
+	xscale->static_high_vectors_set = 0x0;
+
+	/* calculate branches to debug handler */
+	low_reset_branch = (xscale->handler_address + 0x20 - 0x0 - 0x8) >> 2;
+	high_reset_branch = (xscale->handler_address + 0x20 - 0xffff0000 - 0x8) >> 2;
+	
+	xscale->low_vectors[0] = ARMV4_5_B((low_reset_branch & 0xffffff), 0);
+	xscale->high_vectors[0] = ARMV4_5_B((high_reset_branch & 0xffffff), 0);
+	
+	for (i = 1; i <= 7; i++)
+	{
+		xscale->low_vectors[i] = ARMV4_5_B(0xfffffe, 0);
+		xscale->high_vectors[i] = ARMV4_5_B(0xfffffe, 0);
+	}
+	
+	/* 64kB aligned region used for DCache cleaning */ 
+	xscale->cache_clean_address = 0xfffe0000;	
+	
+	xscale->hold_rst = 0;
+	xscale->external_debug_break = 0;
+	
+	xscale->force_hw_bkpts = 1;
+	
+	xscale->ibcr_available = 2;
+	xscale->ibcr0_used = 0;
+	xscale->ibcr1_used = 0;
+		
+	xscale->dbr_available = 2;
+	xscale->dbr0_used = 0;
+	xscale->dbr1_used = 0;
+	
+	xscale->arm_bkpt = ARMV5_BKPT(0x0);
+	xscale->thumb_bkpt = ARMV5_T_BKPT(0x0) & 0xffff;
+	
+	xscale->vector_catch = 0x1;
+	
+	xscale->trace_buffer_enabled = 0;
+	xscale->trace_buffer_fill = 0;
+	
+	/* prepare ARMv4/5 specific information */
+	armv4_5->arch_info = xscale;
+	armv4_5->read_core_reg = xscale_read_core_reg;
+	armv4_5->write_core_reg = xscale_write_core_reg;
+	armv4_5->full_context = xscale_full_context;
+
+	armv4_5_init_arch_info(target, armv4_5);
+
+	xscale->armv4_5_mmu.armv4_5_cache.ctype = -1;
+	xscale->armv4_5_mmu.get_ttb = xscale_get_ttb;
+	xscale->armv4_5_mmu.read_memory = xscale_read_memory;
+	xscale->armv4_5_mmu.write_memory = xscale_write_memory;
+	xscale->armv4_5_mmu.disable_mmu_caches = xscale_disable_mmu_caches;
+	xscale->armv4_5_mmu.enable_mmu_caches = xscale_enable_mmu_caches;
+	xscale->armv4_5_mmu.has_tiny_pages = 1;
+	xscale->armv4_5_mmu.mmu_enabled = 0;
+	
+	return ERROR_OK;
+}
+
+/* target xscale <endianess> <startup_mode> <chain_pos> <variant> */
+int xscale_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)
+{
+	int chain_pos;
+	char *variant = NULL;
+	xscale_common_t *xscale = malloc(sizeof(xscale_common_t));
+
+	if (argc < 5)
+	{
+		ERROR("'target xscale' requires four arguments: <endianess> <startup_mode> <chain_pos> <variant>");
+		exit(-1);
+	}
+	
+	chain_pos = strtoul(args[3], NULL, 0);
+	
+	variant = args[4];
+	
+	xscale_init_arch_info(target, xscale, chain_pos, variant);
+	xscale_build_reg_cache(target);
+	
+	return ERROR_OK;
+}
+
+int xscale_handle_debug_handler_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	target_t *target = NULL;
+	armv4_5_common_t *armv4_5;
+	xscale_common_t *xscale;
+
+	u32 handler_address;
+
+	if (argc < 2)
+	{
+		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)
+	{
+		ERROR("no target '%s' configured", args[0]);
+		return ERROR_OK;
+	}
+	
+	if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "target isn't an ARM920t target");
+		return ERROR_OK;
+	}
+	
+	handler_address = strtoul(args[1], NULL, 0);
+	
+	if (((handler_address >= 0x800) && (handler_address <= 0x1fef800)) ||
+		((handler_address >= 0xfe000800) && (handler_address <= 0xfffff800)))
+	{
+		xscale->handler_address = handler_address;
+	}
+	else
+	{
+		ERROR("xscale debug_handler <address> must be between 0x800 and 0x1fef800 or between 0xfe000800 and 0xfffff800");
+	}
+	
+	return ERROR_OK;
+}
+
+int xscale_handle_cache_clean_address_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	target_t *target = NULL;
+	armv4_5_common_t *armv4_5;
+	xscale_common_t *xscale;
+
+	u32 cache_clean_address;
+	
+	if (argc < 2)
+	{
+		ERROR("'xscale cache_clean_address <target#> <address>' command takes two required operands");
+		return ERROR_OK;
+	}
+	
+	if ((target = get_target_by_num(strtoul(args[0], NULL, 0))) == NULL)
+	{
+		ERROR("no target '%s' configured", args[0]);
+		return ERROR_OK;
+	}
+	
+	if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "target isn't an XScale target");
+		return ERROR_OK;
+	}
+	
+	cache_clean_address = strtoul(args[1], NULL, 0);
+	
+	if (cache_clean_address & 0xffff)
+	{
+		ERROR("xscale cache_clean_address <address> must be 64kb aligned");
+	}
+	else
+	{
+		xscale->cache_clean_address = cache_clean_address;
+	}
+	
+	return ERROR_OK;
+}
+
+int xscale_handle_cache_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	target_t *target = get_current_target(cmd_ctx);
+	armv4_5_common_t *armv4_5;
+	xscale_common_t *xscale;
+	
+	if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "target isn't an XScale target");
+		return ERROR_OK;
+	}
+	
+	return armv4_5_handle_cache_info_command(cmd_ctx, &xscale->armv4_5_mmu.armv4_5_cache);
+}
+
+int xscale_handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)
+{	
+	target_t *target = get_current_target(cmd_ctx);
+	armv4_5_common_t *armv4_5;
+	xscale_common_t *xscale;
+	
+	if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "target isn't an XScale target");
+		return ERROR_OK;
+	}
+	
+	if (target->state != TARGET_HALTED)
+	{
+		command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+		return ERROR_OK;
+	}
+		
+	return armv4_5_mmu_handle_virt2phys_command(cmd_ctx, cmd, args, argc, target, &xscale->armv4_5_mmu);
+}
+
+int xscale_handle_mmu_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)
+{	
+	target_t *target = get_current_target(cmd_ctx);
+	armv4_5_common_t *armv4_5;
+	xscale_common_t *xscale;
+	
+	if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "target isn't an XScale target");
+		return ERROR_OK;
+	}
+	
+	if (target->state != TARGET_HALTED)
+	{
+		command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+		return ERROR_OK;
+	}
+	
+	if (argc >= 1)
+	{
+		if (strcmp("enable", args[0]) == 0)
+		{
+			xscale_enable_mmu_caches(target, 1, 0, 0);
+			xscale->armv4_5_mmu.mmu_enabled = 1;
+		}
+		else if (strcmp("disable", args[0]) == 0)
+		{
+			xscale_disable_mmu_caches(target, 1, 0, 0);
+			xscale->armv4_5_mmu.mmu_enabled = 0;
+		}
+	}
+		
+	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)
+{	
+	target_t *target = get_current_target(cmd_ctx);
+	armv4_5_common_t *armv4_5;
+	xscale_common_t *xscale;
+	int icache = 0, dcache = 0;
+	
+	if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "target isn't an XScale target");
+		return ERROR_OK;
+	}
+	
+	if (target->state != TARGET_HALTED)
+	{
+		command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+		return ERROR_OK;
+	}
+	
+	if (strcmp(cmd, "icache") == 0)
+		icache = 1;
+	else if (strcmp(cmd, "dcache") == 0)
+		dcache = 1;
+	
+	if (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;
+		}
+	}
+	
+	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");
+	 	
+	return ERROR_OK;
+}
+
+int xscale_handle_vector_catch_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)
+{	
+	target_t *target = get_current_target(cmd_ctx);
+	armv4_5_common_t *armv4_5;
+	xscale_common_t *xscale;
+	
+	if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "target isn't an XScale target");
+		return ERROR_OK;
+	}
+	
+	if (argc < 1)
+	{
+		command_print(cmd_ctx, "usage: xscale vector_catch [mask]");
+	}
+	else
+	{
+		xscale->vector_catch = strtoul(args[0], NULL, 0);
+		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);
+	
+	return ERROR_OK;
+}
+
+int xscale_handle_force_hw_bkpts_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	target_t *target = get_current_target(cmd_ctx);
+	armv4_5_common_t *armv4_5;
+	xscale_common_t *xscale;
+	
+	if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "target isn't an XScale target");
+		return ERROR_OK;
+	}
+	
+	if ((argc >= 1) && (strcmp("enable", args[0]) == 0))
+	{
+		xscale->force_hw_bkpts = 1;
+	}
+	else if ((argc >= 1) && (strcmp("disable", args[0]) == 0))
+	{
+		xscale->force_hw_bkpts = 0;
+	}
+	else
+	{
+		command_print(cmd_ctx, "usage: xscale force_hw_bkpts <enable|disable>");
+	}
+		
+	command_print(cmd_ctx, "force hardware breakpoints %s", (xscale->force_hw_bkpts) ? "enabled" : "disabled");
+
+	return ERROR_OK;
+}
+
+int xscale_handle_trace_buffer_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	target_t *target = get_current_target(cmd_ctx);
+	armv4_5_common_t *armv4_5;
+	xscale_common_t *xscale;
+	u32 dcsr_value;
+	
+	if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "target isn't an XScale target");
+		return ERROR_OK;
+	}
+	
+	if (target->state != TARGET_HALTED)
+	{
+		command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+		return ERROR_OK;
+	}
+	
+	if ((argc >= 1) && (strcmp("enable", args[0]) == 0))
+	{
+		xscale->trace_buffer_enabled = 1;
+	}
+	else if ((argc >= 1) && (strcmp("disable", args[0]) == 0))
+	{
+		xscale->trace_buffer_enabled = 0;
+	}
+
+	if ((argc >= 2) && (strcmp("fill", args[1]) == 0))
+	{
+		xscale->trace_buffer_fill = 1;
+	}
+	else if ((argc >= 2) && (strcmp("wrap", args[1]) == 0))
+	{
+		xscale->trace_buffer_fill = 0;
+	}
+	
+	command_print(cmd_ctx, "trace buffer %s (%s)", 
+		(xscale->trace_buffer_enabled) ? "enabled" : "disabled",
+		(xscale->trace_buffer_fill) ? "fill" : "wrap");
+
+	dcsr_value = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 0, 32);
+	if (xscale->trace_buffer_fill)
+		xscale_write_dcsr_sw(target, (dcsr_value & 0xfffffffc) | 2);
+	else
+		xscale_write_dcsr_sw(target, dcsr_value & 0xfffffffc);
+		
+	return ERROR_OK;
+}
+
+int xscale_handle_dump_trace_buffer_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	target_t *target = get_current_target(cmd_ctx);
+	armv4_5_common_t *armv4_5;
+	xscale_common_t *xscale;
+	u32 trace_buffer[258];
+	int is_address[256];
+	int i;
+	
+	if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "target isn't an XScale target");
+		return ERROR_OK;
+	}
+	
+	if (target->state != TARGET_HALTED)
+	{
+		command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+		return ERROR_OK;
+	}
+
+	/* send read trace buffer command (command 0x61) */
+	xscale_send_u32(target, 0x61);
+	
+	/* receive trace buffer content */
+	xscale_receive(target, trace_buffer, 258);
+	
+	for (i = 255; i >= 0; i--)
+	{
+		is_address[i] = 0;
+		if (((trace_buffer[i] & 0xf0) == 0x90) ||
+			((trace_buffer[i] & 0xf0) == 0xd0)) 
+		{
+			if (i >= 4)
+				is_address[--i] = 1;
+			if (i >= 3)
+				is_address[--i] = 1;
+			if (i >= 2)
+				is_address[--i] = 1;
+			if (i >= 1)
+				is_address[--i] = 1;
+		}
+	}
+	
+	for (i = 0; i < 256; i++)
+	{
+#if 0
+		command_print(cmd_ctx, "0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x 0x%2.2x",
+			trace_buffer[i + 0], trace_buffer[i + 1], trace_buffer[i + 2], trace_buffer[i + 3],
+			trace_buffer[i + 4], trace_buffer[i + 5], trace_buffer[i + 6], trace_buffer[i + 6]
+			);
+		i += 8;
+#endif
+		if (is_address[i])
+		{
+			command_print(cmd_ctx, "address: 0x%2.2x%2.2x%2.2x%2.2x", trace_buffer[i], trace_buffer[i+1], trace_buffer[i+2], trace_buffer[i+3]);
+			i += 3; 
+		}
+		else
+		{
+			switch ((trace_buffer[i] & 0xf0) >> 4)
+			{
+				case 0:
+					command_print(cmd_ctx, "0x%2.2x: reset exception", trace_buffer[i]);
+					break;
+				case 1:
+					command_print(cmd_ctx, "0x%2.2x: undef exception", trace_buffer[i]);
+					break;
+				case 2:
+					command_print(cmd_ctx, "0x%2.2x: swi exception", trace_buffer[i]);
+					break;
+				case 3:
+					command_print(cmd_ctx, "0x%2.2x: pabort exception", trace_buffer[i]);
+					break;
+				case 4:
+					command_print(cmd_ctx, "0x%2.2x: dabort exception", trace_buffer[i]);
+					break;
+				case 5:
+					command_print(cmd_ctx, "0x%2.2x: invalid", trace_buffer[i]);
+					break;
+				case 6:
+					command_print(cmd_ctx, "0x%2.2x: irq exception", trace_buffer[i]);
+					break;
+				case 7:
+					command_print(cmd_ctx, "0x%2.2x: fiq exception", trace_buffer[i]);
+					break;
+				case 0x8:
+					command_print(cmd_ctx, "0x%2.2x: direct branch", trace_buffer[i]);
+					break;
+				case 0x9:
+					command_print(cmd_ctx, "0x%2.2x: indirect branch", trace_buffer[i]);
+					break;
+				case 0xa:
+					command_print(cmd_ctx, "0x%2.2x: invalid", trace_buffer[i]);
+					break;
+				case 0xb:
+					command_print(cmd_ctx, "0x%2.2x: invalid", trace_buffer[i]);
+					break;
+				case 0xc:
+					command_print(cmd_ctx, "0x%2.2x: checkpointed direct branch", trace_buffer[i]);
+					break;
+				case 0xd:
+					command_print(cmd_ctx, "0x%2.2x: checkpointed indirect branch", trace_buffer[i]);
+					break;
+				case 0xe:
+					command_print(cmd_ctx, "0x%2.2x: invalid", trace_buffer[i]);
+					break;
+				case 0xf:
+					command_print(cmd_ctx, "0x%2.2x: rollover", trace_buffer[i]);
+					break;
+			} 
+		}
+	}
+	
+	command_print(cmd_ctx, "chkpt0: 0x%8.8x, chkpt1: 0x%8.8x", trace_buffer[256], trace_buffer[257]);
+
+	return ERROR_OK;	
+}
+
+int xscale_register_commands(struct command_context_s *cmd_ctx)
+{
+	command_t *xscale_cmd;
+
+	xscale_cmd = register_command(cmd_ctx, NULL, "xscale", NULL, COMMAND_ANY, "xscale specific commands");
+	
+	register_command(cmd_ctx, xscale_cmd, "debug_handler", xscale_handle_debug_handler_command, COMMAND_CONFIG, NULL);
+	register_command(cmd_ctx, xscale_cmd, "cache_clean_address", xscale_handle_cache_clean_address_command, COMMAND_ANY, NULL);
+
+	register_command(cmd_ctx, xscale_cmd, "cache_info", xscale_handle_cache_info_command, COMMAND_EXEC, NULL);
+	register_command(cmd_ctx, xscale_cmd, "virt2phys", xscale_handle_virt2phys_command, COMMAND_EXEC, NULL);
+	register_command(cmd_ctx, xscale_cmd, "mmu", xscale_handle_mmu_command, COMMAND_EXEC, "['enable'|'disable'] the MMU");
+	register_command(cmd_ctx, xscale_cmd, "icache", xscale_handle_idcache_command, COMMAND_EXEC, "['enable'|'disable'] the ICache");
+	register_command(cmd_ctx, xscale_cmd, "dcache", xscale_handle_idcache_command, COMMAND_EXEC, "['enable'|'disable'] the DCache");
+	
+	register_command(cmd_ctx, xscale_cmd, "vector_catch", xscale_handle_idcache_command, COMMAND_EXEC, "<mask> of vectors that should be catched");
+	
+	register_command(cmd_ctx, xscale_cmd, "trace_buffer", xscale_handle_trace_buffer_command, COMMAND_EXEC, "<enable|disable> ['fill'|'wrap']");
+
+	register_command(cmd_ctx, xscale_cmd, "dump_trace_buffer", xscale_handle_dump_trace_buffer_command, COMMAND_EXEC, "dump content of trace buffer");
+	
+	armv4_5_register_commands(cmd_ctx);
+	
+	return ERROR_OK;
+}
diff --git a/src/target/xscale.h b/src/target/xscale.h
new file mode 100644
index 000000000..9fcb265e4
--- /dev/null
+++ b/src/target/xscale.h
@@ -0,0 +1,145 @@
+/***************************************************************************
+ *   Copyright (C) 2005 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   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     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#ifndef XSCALE_H
+#define XSCALE_H
+
+#include "target.h"
+#include "register.h"
+#include "armv4_5.h"
+#include "armv4_5_mmu.h"
+
+#define	XSCALE_COMMON_MAGIC 0x58534341
+
+typedef struct xscale_jtag_s
+{
+	/* position in JTAG scan chain */
+	int chain_pos;
+
+	/* IR length and instructions */	
+	int ir_length;
+	u32 dbgrx;
+	u32 dbgtx;
+	u32 ldic;
+	u32 dcsr;
+} xscale_jtag_t;
+
+enum xscale_debug_reason
+{
+	XSCALE_DBG_REASON_GENERIC,
+	XSCALE_DBG_REASON_RESET,
+	XSCALE_DBG_REASON_TB_FULL,
+};
+
+typedef struct xscale_common_s
+{
+	int common_magic;
+	
+	/* XScale registers (CP15, DBG) */
+	reg_cache_t *reg_cache;
+
+	/* pxa250, pxa255, pxa27x, ixp42x, ... */
+	char *variant;
+
+	xscale_jtag_t jtag_info;
+	
+	/* current state of the debug handler */
+	int handler_installed;
+	int handler_running;
+	u32 handler_address;
+	
+	/* target-endian buffers with exception vectors */
+	u32 low_vectors[8];
+	u32 high_vectors[8];
+	
+	/* static low vectors */
+	u8 static_low_vectors_set;	/* bit field with static vectors set by the user */
+	u8 static_high_vectors_set; /* bit field with static vectors set by the user */
+	u32 static_low_vectors[8];
+	u32 static_high_vectors[8];
+
+	/* DCache cleaning */	
+	u32 cache_clean_address;
+	
+	/* whether hold_rst and ext_dbg_break should be set */
+	int hold_rst;
+	int external_debug_break;
+	
+	/* breakpoint / watchpoint handling */
+	int force_hw_bkpts;
+	int dbr_available;
+	int dbr0_used;
+	int dbr1_used;
+	int ibcr_available;
+	int ibcr0_used;
+	int	ibcr1_used;
+	u32 arm_bkpt;
+	u16 thumb_bkpt;
+	
+	u8 vector_catch;
+	
+	int trace_buffer_enabled;
+	int trace_buffer_fill;
+	
+	int arch_debug_reason;
+	
+	/* armv4/5 common stuff */
+	armv4_5_common_t armv4_5_common;
+	
+	/* MMU/Caches */
+	armv4_5_mmu_common_t armv4_5_mmu;
+	u32 cp15_control_reg;
+	
+	/* possible future enhancements that go beyond XScale common stuff */
+	void *arch_info;
+} xscale_common_t;
+
+typedef struct xscale_reg_s
+{
+	int dbg_handler_number;
+	target_t *target;
+} xscale_reg_t;
+
+enum
+{
+	XSCALE_MAINID,		/* 0 */
+	XSCALE_CACHETYPE,
+	XSCALE_CTRL,
+	XSCALE_AUXCTRL,
+	XSCALE_TTB,
+	XSCALE_DAC,
+	XSCALE_FSR,
+	XSCALE_FAR,
+	XSCALE_PID,
+	XSCALE_CPACCESS,
+	XSCALE_IBCR0,		/* 10 */
+	XSCALE_IBCR1,
+	XSCALE_DBR0,
+	XSCALE_DBR1,
+	XSCALE_DBCON,
+	XSCALE_TBREG,
+	XSCALE_CHKPT0,
+	XSCALE_CHKPT1,
+	XSCALE_DCSR,
+	XSCALE_TX,
+	XSCALE_RX,			/* 20 */
+	XSCALE_TXRXCTRL,
+};
+
+#endif /* XSCALE_H */
diff --git a/src/target/xscale/build.sh b/src/target/xscale/build.sh
new file mode 100644
index 000000000..fc828b2c2
--- /dev/null
+++ b/src/target/xscale/build.sh
@@ -0,0 +1,7 @@
+arm-none-eabi-gcc -c debug_handler.S -o debug_handler.o
+arm-none-eabi-ld -EL -n -Tdebug_handler.cmd debug_handler.o -o debug_handler.out
+arm-none-eabi-objcopy -O binary debug_handler.out debug_handler.bin
+
+#arm-none-eabi-gcc -mbig-endian -c debug_handler.S -o debug_handler_be.o
+#arm-none-eabi-ld -EB -n -Tdebug_handler.cmd debug_handler_be.o -o debug_handler_be.out
+#arm-none-eabi-objcopy -O binary debug_handler_be.out debug_handler_be.bin
diff --git a/src/target/xscale/debug_handler.S b/src/target/xscale/debug_handler.S
new file mode 100644
index 000000000..6d9b1cd31
--- /dev/null
+++ b/src/target/xscale/debug_handler.S
@@ -0,0 +1,718 @@
+/***************************************************************************
+ *   Copyright (C) 2006 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   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     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+#include "protocol.h"
+
+    .text
+    .align  4
+
+@ Disable thumb mode
+    .code 32
+
+@ send word to debugger
+.macro m_send_to_debugger reg
+1:
+	mrc p14, 0, r15, c14, c0, 0
+	bvs 1b
+	mcr p14, 0, \reg, c8, c0, 0	
+.endm
+
+@ receive word from debugger
+.macro m_receive_from_debugger reg
+1:
+	mrc p14, 0, r15, c14, c0, 0
+	bpl 1b
+	mrc p14, 0, \reg, c9, c0, 0	
+.endm
+
+@ save register on debugger, small
+.macro m_small_save_reg reg
+	mov r0, \reg
+	bl send_to_debugger
+.endm
+
+@ save status register on debugger, small
+.macro m_small_save_psr
+	mrs r0, spsr
+	bl send_to_debugger
+.endm
+
+@ wait for all outstanding coprocessor accesses to complete
+.macro m_cpwait
+	mrc p15, 0, r0, c2, c0, 0
+	mov r0, r0
+	sub pc, pc, #4
+.endm
+
+.global reset_handler
+.global undef_handler
+.global swi_handler
+.global prefetch_abort_handler
+.global data_abort_handler
+.global irq_handler
+.global fiq_handler
+
+.section .part1 , "ax"
+
+reset_handler:
+	@ read DCSR
+	mrc p14, 0, r13, c10, c0
+	@ check if global enable bit (GE) is set
+	ands r13, r13, #0x80000000
+	
+	bne debug_handler
+
+	@ set global enable bit (GE)
+	mov r13, #0xc0000000
+	mcr p14, 0, r13, c10, c0
+
+debug_handler:
+
+	@ save r0 without modifying other registers
+	m_send_to_debugger r0
+
+	@ save lr (program PC) without branching (use macro)
+	m_send_to_debugger r14
+
+	@ save non-banked registers and spsr (program CPSR)
+	m_small_save_reg r1
+	m_small_save_reg r2
+	m_small_save_reg r3
+	m_small_save_reg r4
+	m_small_save_reg r5
+	m_small_save_reg r6
+	m_small_save_reg r7
+	m_small_save_psr
+
+	mrs r0, spsr
+
+	@ prepare program PSR for debug use (clear Thumb, set I/F to disable interrupts)
+	bic r0, r0, #PSR_T
+	orr r0, r0, #(PSR_I | PSR_F)
+
+	@ examine mode bits
+	and r1, r0, #MODE_MASK
+	cmp r1, #MODE_USR
+
+	bne not_user_mode
+	
+	@ replace USR mode with SYS
+	bic r0, r0, #MODE_MASK
+	orr r0, r0, #MODE_SYS
+
+not_user_mode:
+
+	b save_banked_registers
+
+@ command loop
+@ wait for command from debugger, than execute desired function
+get_command:
+	bl receive_from_debugger
+	
+	@ 0x0n - register access
+	cmp r0, #0x0
+	beq get_banked_registers
+
+	cmp r0, #0x1
+	beq set_banked_registers
+
+	@ 0x1n - read memory
+	cmp r0, #0x11
+	beq read_byte
+
+	cmp r0, #0x12
+	beq read_half_word
+
+	cmp r0, #0x14
+	beq read_word
+
+	@ 0x2n - write memory
+	cmp r0, #0x21
+	beq write_byte
+	
+	cmp r0, #0x22
+	beq write_half_word
+	
+	cmp r0, #0x24
+	beq write_word
+
+	@ 0x3n - program execution
+	cmp r0, #0x30
+	beq resume
+
+	cmp r0, #0x31
+	beq resume_w_trace
+
+	@ 0x4n - coprocessor access
+	cmp r0, #0x40
+	beq read_cp_reg
+
+	cmp r0, #0x41
+	beq write_cp_reg
+
+	@ 0x5n - cache and mmu functions
+	cmp r0, #0x50
+	beq clean_d_cache
+
+	cmp r0, #0x51
+	beq invalidate_d_cache
+	
+	cmp r0, #0x52
+	beq invalidate_i_cache
+
+	cmp r0, #0x53
+	beq cpwait
+
+	@ 0x6n - misc functions
+	cmp r0, #0x60
+	beq clear_sa
+
+	cmp r0, #0x61
+	beq read_trace_buffer
+	
+	cmp r0, #0x62
+	beq clean_trace_buffer
+	
+	@ return (back to get_command)
+	b get_command
+
+@ ----
+
+@ resume program execution
+resume:
+	@ restore CPSR (SPSR_dbg)
+	bl receive_from_debugger
+	msr spsr, r0
+
+	@ restore registers (r7 - r0)
+	bl receive_from_debugger @ r7
+	mov r7, r0
+	bl receive_from_debugger @ r6
+	mov r6, r0
+	bl receive_from_debugger @ r5
+	mov r5, r0
+	bl receive_from_debugger @ r4
+	mov r4, r0
+	bl receive_from_debugger @ r3
+	mov r3, r0
+	bl receive_from_debugger @ r2
+	mov r2, r0
+	bl receive_from_debugger @ r1
+	mov r1, r0
+	bl receive_from_debugger @ r0
+
+	@ resume addresss
+	m_receive_from_debugger lr
+
+	@ branch back to application code, restoring CPSR
+	subs pc, lr, #0	
+
+@ get banked registers
+@ receive mode bits from host, then run into save_banked_registers to 
+	
+get_banked_registers:
+	bl receive_from_debugger
+
+@ save banked registers
+@ r0[4:0]: desired mode bits
+save_banked_registers:
+	@ backup CPSR
+	mrs r7, cpsr
+	msr cpsr_c, r0
+	nop
+
+	@ keep current mode bits in r1 for later use
+	and r1, r0, #MODE_MASK
+	
+	@ backup banked registers
+	m_send_to_debugger r8
+	m_send_to_debugger r9
+	m_send_to_debugger r10
+	m_send_to_debugger r11
+	m_send_to_debugger r12
+	m_send_to_debugger r13
+	m_send_to_debugger r14
+
+	@ if not in SYS mode (or USR, which we replaced with SYS before)
+	cmp r1, #MODE_SYS
+	
+	beq no_spsr_to_save
+
+	@ backup SPSR
+	mrs r0, spsr
+	m_send_to_debugger r0
+
+no_spsr_to_save:
+
+	@ restore CPSR for SDS
+	msr cpsr_c, r7
+	nop
+
+   	@ return
+	b get_command
+
+@ ----
+
+
+@ set banked registers
+@ receive mode bits from host, then run into save_banked_registers to 
+	
+set_banked_registers:
+	bl receive_from_debugger
+
+@ restore banked registers
+@ r0[4:0]: desired mode bits
+restore_banked_registers:
+	@ backup CPSR
+	mrs r7, cpsr
+	msr cpsr_c, r0
+	nop
+
+	@ keep current mode bits in r1 for later use
+	and r1, r0, #MODE_MASK
+	
+	@ set banked registers
+	m_receive_from_debugger r8
+	m_receive_from_debugger r9
+	m_receive_from_debugger r10
+	m_receive_from_debugger r11
+	m_receive_from_debugger r12
+	m_receive_from_debugger r13
+	m_receive_from_debugger r14
+
+	@ if not in SYS mode (or USR, which we replaced with SYS before)
+	cmp r1, #MODE_SYS
+	
+	beq no_spsr_to_restore
+
+	@ set SPSR
+	m_receive_from_debugger r0
+	msr spsr, r0
+
+no_spsr_to_restore:
+
+	@ restore CPSR for SDS
+	msr cpsr_c, r7
+	nop
+
+   	@ return
+	b get_command
+
+@ ----
+
+read_byte:
+	@ r2: address
+	bl receive_from_debugger
+	mov r2, r0
+
+	@ r1: count
+	bl receive_from_debugger
+	mov r1, r0
+
+rb_loop:
+	ldrb r0, [r2], #1
+	
+	@ drain write- (and fill-) buffer to work around XScale errata
+	mcr p15, 0, r8, c7, c10, 4
+
+	bl send_to_debugger
+
+	subs r1, r1, #1
+	bne rb_loop
+	
+	@ return
+	b get_command
+
+@ ----
+
+read_half_word:
+	@ r2: address
+	bl receive_from_debugger
+	mov r2, r0
+
+	@ r1: count
+	bl receive_from_debugger
+	mov r1, r0
+
+rh_loop:
+	ldrh r0, [r2], #2
+	
+	@ drain write- (and fill-) buffer to work around XScale errata
+	mcr p15, 0, r8, c7, c10, 4
+
+	bl send_to_debugger
+
+	subs r1, r1, #1
+	bne rh_loop
+	
+	@ return
+	b get_command
+
+@ ----
+
+read_word:
+	@ r2: address
+	bl receive_from_debugger
+	mov r2, r0
+
+	@ r1: count
+	bl receive_from_debugger
+	mov r1, r0
+
+rw_loop:
+	ldr r0, [r2], #4
+	
+	@ drain write- (and fill-) buffer to work around XScale errata
+	mcr p15, 0, r8, c7, c10, 4
+
+	bl send_to_debugger
+
+	subs r1, r1, #1
+	bne rw_loop
+	
+	@ return
+	b get_command
+
+@ ----
+
+write_byte:
+	@ r2: address
+	bl receive_from_debugger
+	mov r2, r0
+
+	@ r1: count
+	bl receive_from_debugger
+	mov r1, r0
+
+wb_loop:
+	bl receive_from_debugger
+	strb r0, [r2], #1
+
+	@ drain write- (and fill-) buffer to work around XScale errata
+	mcr p15, 0, r8, c7, c10, 4
+
+	subs r1, r1, #1
+	bne wb_loop
+	
+	@ return
+	b get_command
+
+@ ----
+
+write_half_word:
+	@ r2: address
+	bl receive_from_debugger
+	mov r2, r0
+
+	@ r1: count
+	bl receive_from_debugger
+	mov r1, r0
+
+wh_loop:
+	bl receive_from_debugger
+	strh r0, [r2], #2
+
+	@ drain write- (and fill-) buffer to work around XScale errata
+	mcr p15, 0, r8, c7, c10, 4
+
+	subs r1, r1, #1
+	bne wh_loop
+	
+	@ return
+	b get_command
+
+@ ----
+
+write_word:
+	@ r2: address
+	bl receive_from_debugger
+	mov r2, r0
+
+	@ r1: count
+	bl receive_from_debugger
+	mov r1, r0
+
+ww_loop:
+	bl receive_from_debugger
+	str r0, [r2], #4
+
+	@ drain write- (and fill-) buffer to work around XScale errata
+	mcr p15, 0, r8, c7, c10, 4
+
+	subs r1, r1, #1
+	bne ww_loop
+	
+	@ return
+	b get_command
+
+@ ----
+
+clear_sa:
+	@ read DCSR
+	mrc p14, 0, r0, c10, c0
+	
+	@ clear SA bit
+	bic r0, r0, #0x20
+
+	@ write DCSR
+	mcr p14, 0, r0, c10, c0
+
+	@ return
+	b get_command
+
+@ ----
+
+clean_d_cache:
+	@ r0: cache clean area
+	bl receive_from_debugger
+	
+	mov r1, #1024
+clean_loop:
+	mcr p15, 0, r0, c7, c2, 5
+	add r0, r0, #32
+	subs r1, r1, #1
+	bne clean_loop
+
+	@ return
+	b get_command
+
+@ ----
+
+invalidate_d_cache:
+	mcr p15, 0, r0, c7, c6, 0
+
+	@ return
+	b get_command
+
+@ ----
+
+invalidate_i_cache:
+	mcr p15, 0, r0, c7, c5, 0
+
+	@ return
+	b get_command
+
+@ ----
+
+cpwait:
+	m_cpwait
+
+	@return
+	b get_command
+
+@ ----
+
+.section .part2 , "ax"
+
+read_cp_reg:
+	@ requested cp register
+	bl receive_from_debugger
+
+	adr r1, read_cp_table
+	add pc, r1, r0, lsl #3
+
+read_cp_table:
+	mrc p15, 0, r0, c0, c0, 0  @ XSCALE_MAINID
+	b read_cp_reg_reply
+	mrc p15, 0, r0, c0, c0, 1  @ XSCALE_CACHETYPE
+	b read_cp_reg_reply
+	mrc p15, 0, r0, c1, c0, 0  @ XSCALE_CTRL
+	b read_cp_reg_reply
+	mrc p15, 0, r0, c1, c0, 1  @ XSCALE_AUXCTRL
+	b read_cp_reg_reply
+	mrc p15, 0, r0, c2, c0, 0  @ XSCALE_TTB
+	b read_cp_reg_reply
+	mrc p15, 0, r0, c3, c0, 0  @ XSCALE_DAC
+	b read_cp_reg_reply
+	mrc p15, 0, r0, c5, c0, 0  @ XSCALE_FSR
+	b read_cp_reg_reply
+	mrc p15, 0, r0, c6, c0, 0  @ XSCALE_FAR
+	b read_cp_reg_reply
+	mrc p15, 0, r0, c13, c0, 0  @ XSCALE_PID
+	b read_cp_reg_reply
+	mrc p15, 0, r0, c15, c0, 0  @ XSCALE_CP_ACCESS
+	b read_cp_reg_reply
+	mrc p15, 0, r0, c14, c8, 0  @ XSCALE_IBCR0
+	b read_cp_reg_reply
+	mrc p15, 0, r0, c14, c9, 0  @ XSCALE_IBCR1
+	b read_cp_reg_reply
+	mrc p15, 0, r0, c14, c0, 0  @ XSCALE_DBR0
+	b read_cp_reg_reply
+	mrc p15, 0, r0, c14, c3, 0  @ XSCALE_DBR1
+	b read_cp_reg_reply
+	mrc p15, 0, r0, c14, c4, 0  @ XSCALE_DBCON
+	b read_cp_reg_reply
+	mrc p14, 0, r0, c11, c0, 0 @ XSCALE_TBREG
+	b read_cp_reg_reply
+	mrc p14, 0, r0, c12, c0, 0 @ XSCALE_CHKPT0
+	b read_cp_reg_reply
+	mrc p14, 0, r0, c13, c0, 0 @ XSCALE_CHKPT1
+	b read_cp_reg_reply
+	mrc p14, 0, r0, c10, c0, 0 @ XSCALE_DCSR
+	b read_cp_reg_reply
+
+read_cp_reg_reply:
+	bl send_to_debugger	
+
+	@ return
+	b get_command
+
+@ ----
+
+write_cp_reg:
+	@ requested cp register
+	bl receive_from_debugger
+	mov r1, r0
+
+	@ value to be written
+	bl receive_from_debugger
+
+	adr r2, write_cp_table
+	add pc, r2, r1, lsl #3
+
+write_cp_table:
+	mcr p15, 0, r0, c0, c0, 0  @ XSCALE_MAINID (0x0)
+	b get_command
+	mcr p15, 0, r0, c0, c0, 1  @ XSCALE_CACHETYPE (0x1)
+	b get_command
+	mcr p15, 0, r0, c1, c0, 0  @ XSCALE_CTRL (0x2)
+	b get_command
+	mcr p15, 0, r0, c1, c0, 1  @ XSCALE_AUXCTRL (0x3)
+	b get_command
+	mcr p15, 0, r0, c2, c0, 0  @ XSCALE_TTB (0x4)
+	b get_command
+	mcr p15, 0, r0, c3, c0, 0  @ XSCALE_DAC (0x5)
+	b get_command
+	mcr p15, 0, r0, c5, c0, 0  @ XSCALE_FSR (0x6)
+	b get_command
+	mcr p15, 0, r0, c6, c0, 0  @ XSCALE_FAR (0x7)
+	b get_command
+	mcr p15, 0, r0, c13, c0, 0  @ XSCALE_PID (0x8)
+	b get_command
+	mcr p15, 0, r0, c15, c0, 0  @ XSCALE_CP_ACCESS (0x9)
+	b get_command
+	mcr p15, 0, r0, c14, c8, 0  @ XSCALE_IBCR0 (0xa)
+	b get_command
+	mcr p15, 0, r0, c14, c9, 0  @ XSCALE_IBCR1 (0xb)
+	b get_command
+	mcr p15, 0, r0, c14, c0, 0  @ XSCALE_DBR0 (0xc)
+	b get_command
+	mcr p15, 0, r0, c14, c3, 0  @ XSCALE_DBR1 (0xd)
+	b get_command
+	mcr p15, 0, r0, c14, c4, 0  @ XSCALE_DBCON (0xe)
+	b get_command
+	mcr p14, 0, r0, c11, c0, 0 @ XSCALE_TBREG (0xf)
+	b get_command
+	mcr p14, 0, r0, c12, c0, 0 @ XSCALE_CHKPT0 (0x10)
+	b get_command
+	mcr p14, 0, r0, c13, c0, 0 @ XSCALE_CHKPT1 (0x11)
+	b get_command
+	mcr p14, 0, r0, c10, c0, 0 @ XSCALE_DCSR (0x12)
+	b get_command
+
+@ ----
+
+read_trace_buffer:
+
+	@ dump 256 entries from trace buffer
+	mov	r1, #256
+read_tb_loop:
+	mrc p14, 0, r0, c11, c0, 0 @ XSCALE_TBREG
+	bl send_to_debugger
+	subs r1, r1, #1
+	bne read_tb_loop
+
+	@ dump checkpoint register 0
+	mrc p14, 0, r0, c12, c0, 0 @ XSCALE_CHKPT0 (0x10)
+	bl send_to_debugger
+	
+	@ dump checkpoint register 1
+	mrc p14, 0, r0, c13, c0, 0 @ XSCALE_CHKPT1 (0x11)
+	bl send_to_debugger
+
+	@ return
+	b get_command
+	
+@ ----
+
+clean_trace_buffer:
+
+	@ clean 256 entries from trace buffer
+	mov	r1, #256
+clean_tb_loop:
+	mrc p14, 0, r0, c11, c0, 0 @ XSCALE_TBREG
+	subs r1, r1, #1
+	bne clean_tb_loop
+
+	@ return
+	b get_command
+	
+@ ----
+
+
+@ resume program execution with trace buffer enabled
+resume_w_trace:
+	@ restore CPSR (SPSR_dbg)
+	bl receive_from_debugger
+	msr spsr, r0
+
+	@ restore registers (r7 - r0)
+	bl receive_from_debugger @ r7
+	mov r7, r0
+	bl receive_from_debugger @ r6
+	mov r6, r0
+	bl receive_from_debugger @ r5
+	mov r5, r0
+	bl receive_from_debugger @ r4
+	mov r4, r0
+	bl receive_from_debugger @ r3
+	mov r3, r0
+	bl receive_from_debugger @ r2
+	mov r2, r0
+	bl receive_from_debugger @ r1
+	mov r1, r0
+	bl receive_from_debugger @ r0
+
+	@ resume addresss
+	m_receive_from_debugger lr
+
+	mrc p14, 0, r13, c10, c0, 0 @ XSCALE_DCSR
+	orr r13, r13, #1
+	mcr p14, 0, r13, c10, c0, 0 @ XSCALE_DCSR
+
+	@ branch back to application code, restoring CPSR
+	subs pc, lr, #0	
+
+undef_handler:
+swi_handler:
+prefetch_abort_handler:
+data_abort_handler:
+irq_handler:
+fiq_handler:
+1:
+	b 1b
+
+send_to_debugger:
+	m_send_to_debugger r0
+	mov pc, lr
+
+receive_from_debugger:
+	m_receive_from_debugger r0
+	mov pc, lr
+
diff --git a/src/target/xscale/debug_handler.cmd b/src/target/xscale/debug_handler.cmd
new file mode 100644
index 000000000..183c20200
--- /dev/null
+++ b/src/target/xscale/debug_handler.cmd
@@ -0,0 +1,49 @@
+/* identify the Entry Point  */
+ENTRY(reset_handler)
+
+/* specify the mini-ICache memory areas  */
+MEMORY 
+{
+	mini_icache_0 (x)  				: ORIGIN = 0x0, LENGTH = 1024	/* first part of mini icache (sets 0-31) */
+	mini_icache_1 (x)  				: ORIGIN = 0x400, LENGTH = 1024	/* second part of mini icache (sets 0-31) */
+}
+
+/* now define the output sections  */
+SECTIONS 
+{
+	.part1 :
+	{
+		LONG(0)
+		LONG(0)
+		LONG(0)
+		LONG(0)
+		LONG(0)
+		LONG(0)
+		LONG(0)
+		LONG(0)
+		*(.part1)
+	} >mini_icache_0
+
+	.part2 :
+	{
+		LONG(0)
+		LONG(0)
+		LONG(0)
+		LONG(0)
+		LONG(0)
+		LONG(0)
+		LONG(0)
+		LONG(0)
+		*(.part2)
+		FILL(0x0)
+	} >mini_icache_1
+
+	/DISCARD/ :
+	{
+		*(.text)
+		*(.glue_7)
+		*(.glue_7t)
+		*(.data)
+		*(.bss)
+	}
+}
diff --git a/src/target/xscale/protocol.h b/src/target/xscale/protocol.h
new file mode 100644
index 000000000..525db31d2
--- /dev/null
+++ b/src/target/xscale/protocol.h
@@ -0,0 +1,70 @@
+/***************************************************************************
+ *   Copyright (C) 2006 by Dominic Rath                                    *
+ *   Dominic.Rath@gmx.de                                                   *
+ *                                                                         *
+ *   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     *
+ *   (at your option) any later version.                                   *
+ *                                                                         *
+ *   This program is distributed in the hope that it will be useful,       *
+ *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
+ *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
+ *   GNU General Public License for more details.                          *
+ *                                                                         *
+ *   You should have received a copy of the GNU General Public License     *
+ *   along with this program; if not, write to the                         *
+ *   Free Software Foundation, Inc.,                                       *
+ *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
+ ***************************************************************************/
+
+#define REG_R0 0
+#define REG_R1 1
+#define REG_R2 2
+#define REG_R3 3
+#define REG_R4 4
+#define REG_R5 5
+#define REG_R6 6
+#define REG_R7 7
+#define REG_R8 8
+#define REG_R9 9
+#define REG_R10 10
+#define REG_R11 11
+#define REG_R12 12
+#define REG_R13 13
+#define REG_R14 14
+#define REG_R15 15
+#define REG_CPSR 16
+#define REG_SPSR 17
+
+#define MODE_USR 0x10 
+#define MODE_FIQ 0x11
+#define MODE_IRQ 0x12 
+#define MODE_SVC 0x13 
+#define MODE_ABT 0x17
+#define MODE_UND 0x1b
+#define MODE_SYS 0x1f
+
+#define MODE_ANY 0x40
+#define MODE_CURRENT 0x80
+
+#define MODE_MASK 0x1f
+#define PSR_I 0x80
+#define PSR_F 0x40
+#define PSR_T 0x20
+
+#define XSCALE_DBG_MAINID 0x0
+#define XSCALE_DBG_CACHETYPE 0x1
+#define XSCALE_DBG_CTRL 0x2
+#define XSCALE_DBG_AUXCTRL 0x3
+#define XSCALE_DBG_TTB 0x4
+#define XSCALE_DBG_DAC 0x5
+#define XSCALE_DBG_FSR 0x6
+#define XSCALE_DBG_FAR 0x7
+#define XSCALE_DBG_PID 0x8
+#define XSCALE_DBG_CPACCESS 0x9
+#define XSCALE_DBG_IBCR0 0xa
+#define XSCALE_DBG_IBCR1 0xb
+#define XSCALE_DBG_DBR0 0xc
+#define XSCALE_DBG_DBR1 0xd
+#define XSCALE_DBG_DBCON 0xe
-- 
GitLab