diff --git a/src/flash/str9xpec.c b/src/flash/str9xpec.c
index 4959df9ff8d99ab39aaba99556bff6d98f5550d6..9df57dd5b1dbedc001acef9fafabceee71b60a0e 100644
--- a/src/flash/str9xpec.c
+++ b/src/flash/str9xpec.c
@@ -1,1348 +1,1348 @@
-/***************************************************************************
- *   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.             *
- ***************************************************************************/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "replacements.h"
-
-#include "str9xpec.h"
-#include "flash.h"
-#include "target.h"
-#include "log.h"
-#include "armv4_5.h"
-#include "arm7_9_common.h"
-#include "jtag.h"
-#include "binarybuffer.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <getopt.h>
-
-str9xpec_mem_layout_t mem_layout_str9pec[] = {
-	{0x00000000, 0x10000, 0},
-	{0x00010000, 0x10000, 1},
-	{0x00020000, 0x10000, 2},
-	{0x00030000, 0x10000, 3},
-	{0x00040000, 0x10000, 4},
-	{0x00050000, 0x10000, 5},
-	{0x00060000, 0x10000, 6},
-	{0x00070000, 0x10000, 7},
-	{0x00080000, 0x02000, 32},
-	{0x00082000, 0x02000, 33},
-	{0x00084000, 0x02000, 34},
-	{0x00086000, 0x02000, 35}
-};
-
-int str9xpec_register_commands(struct command_context_s *cmd_ctx);
-int str9xpec_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
-int str9xpec_erase(struct flash_bank_s *bank, int first, int last);
-int str9xpec_protect(struct flash_bank_s *bank, int set, int first, int last);
-int str9xpec_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
-int str9xpec_probe(struct flash_bank_s *bank);
-int str9xpec_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int str9xpec_protect_check(struct flash_bank_s *bank);
-int str9xpec_erase_check(struct flash_bank_s *bank);
-int str9xpec_info(struct flash_bank_s *bank, char *buf, int buf_size);
-
-int str9xpec_erase_area(struct flash_bank_s *bank, int first, int last);
-int str9xpec_set_address(struct flash_bank_s *bank, u8 sector);
-int str9xpec_write_options(struct flash_bank_s *bank);
-
-int str9xpec_handle_flash_options_cmap_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int str9xpec_handle_flash_options_lvdthd_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int str9xpec_handle_flash_options_lvdsel_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int str9xpec_handle_flash_options_lvdwarn_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int str9xpec_handle_flash_options_read_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int str9xpec_handle_flash_options_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int str9xpec_handle_flash_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int str9xpec_handle_flash_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int str9xpec_handle_flash_enable_turbo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int str9xpec_handle_flash_disable_turbo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-
-flash_driver_t str9xpec_flash =
-{
-	.name = "str9xpec",
-	.register_commands = str9xpec_register_commands,
-	.flash_bank_command = str9xpec_flash_bank_command,
-	.erase = str9xpec_erase,
-	.protect = str9xpec_protect,
-	.write = str9xpec_write,
-	.probe = str9xpec_probe,
-	.auto_probe = str9xpec_probe,
-	.erase_check = str9xpec_erase_check,
-	.protect_check = str9xpec_protect_check,
-	.info = str9xpec_info
-};
-
-int str9xpec_register_commands(struct command_context_s *cmd_ctx)
-{
-	command_t *str9xpec_cmd = register_command(cmd_ctx, NULL, "str9xpec", NULL, COMMAND_ANY, "str9xpec flash specific commands");
-	
-	register_command(cmd_ctx, str9xpec_cmd, "enable_turbo", str9xpec_handle_flash_enable_turbo_command, COMMAND_EXEC,
-					 "enable str9xpec turbo mode");
-	register_command(cmd_ctx, str9xpec_cmd, "disable_turbo", str9xpec_handle_flash_disable_turbo_command, COMMAND_EXEC,
-					 "disable str9xpec turbo mode");
-	register_command(cmd_ctx, str9xpec_cmd, "options_cmap", str9xpec_handle_flash_options_cmap_command, COMMAND_EXEC,
-					 "configure str9xpec boot sector");
-	register_command(cmd_ctx, str9xpec_cmd, "options_lvdthd", str9xpec_handle_flash_options_lvdthd_command, COMMAND_EXEC,
-					 "configure str9xpec lvd threshold");
-	register_command(cmd_ctx, str9xpec_cmd, "options_lvdsel", str9xpec_handle_flash_options_lvdsel_command, COMMAND_EXEC,
-					 "configure str9xpec lvd selection");
-	register_command(cmd_ctx, str9xpec_cmd, "options_lvdwarn", str9xpec_handle_flash_options_lvdwarn_command, COMMAND_EXEC,
-					 "configure str9xpec lvd warning");
-	register_command(cmd_ctx, str9xpec_cmd, "options_read", str9xpec_handle_flash_options_read_command, COMMAND_EXEC,
-					 "read str9xpec options");
-	register_command(cmd_ctx, str9xpec_cmd, "options_write", str9xpec_handle_flash_options_write_command, COMMAND_EXEC,
-					 "write str9xpec options");
-	register_command(cmd_ctx, str9xpec_cmd, "lock", str9xpec_handle_flash_lock_command, COMMAND_EXEC,
-					 "lock str9xpec device");
-	register_command(cmd_ctx, str9xpec_cmd, "unlock", str9xpec_handle_flash_unlock_command, COMMAND_EXEC,
-					 "unlock str9xpec device");
-	register_command(cmd_ctx, str9xpec_cmd, "part_id", str9xpec_handle_part_id_command, COMMAND_EXEC,
-					 "print part id of str9xpec flash bank <num>");
-	
-	return ERROR_OK;
-}
-
-int str9xpec_set_instr(int chain_pos, u32 new_instr, enum tap_state end_state)
-{
-	jtag_device_t *device = jtag_get_device(chain_pos);
-	
-	if (device == NULL)
-	{
-		DEBUG("Invalid Target");
-		return ERROR_TARGET_INVALID;
-	}
-		
-	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 = NULL;
-		field.in_check_mask = NULL;
-		field.in_handler = NULL;
-		field.in_handler_priv = NULL;
-		
-		jtag_add_ir_scan(1, &field, end_state, NULL);
-		
-		free(field.out_value);
-	}
-	
-	return ERROR_OK;
-}
-
-u8 str9xpec_isc_status(int chain_pos)
-{
-	scan_field_t field;
-	u8 status;
-	
-	if (str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI) != ERROR_OK)
-		return ISC_STATUS_ERROR;
-	
-	field.device = chain_pos;
-	field.num_bits = 8;
-	field.out_value = NULL;
-	field.out_mask = NULL;
-	field.in_value = &status;
-	field.in_check_value = NULL;
-	field.in_check_mask = NULL;
-	field.in_handler = NULL;
-	field.in_handler_priv = NULL;
-	
-	jtag_add_dr_scan(1, &field, TAP_RTI, NULL);
-	jtag_execute_queue();
-	
-	DEBUG("status: 0x%2.2x", status);
-	
-	if (status & ISC_STATUS_SECURITY)
-		INFO("Device Security Bit Set");
-	
-	return status;
-}
-
-int str9xpec_isc_enable(struct flash_bank_s *bank)
-{
-	u8 status;
-	u32 chain_pos;
-	str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
-	
-	chain_pos = str9xpec_info->chain_pos;
-	
-	if (str9xpec_info->isc_enable)
-		return ERROR_OK;
-	
-	/* enter isc mode */
-	if (str9xpec_set_instr(chain_pos, ISC_ENABLE, TAP_RTI) != ERROR_OK)
-		return ERROR_TARGET_INVALID;
-	
-	/* check ISC status */
-	status = str9xpec_isc_status(chain_pos);
-	if (status & ISC_STATUS_MODE)
-	{
-		/* we have entered isc mode */
-		str9xpec_info->isc_enable = 1;
-		DEBUG("ISC_MODE Enabled");
-	}
-	
-	return ERROR_OK;
-}
-
-int str9xpec_isc_disable(struct flash_bank_s *bank)
-{
-	u8 status;
-	u32 chain_pos;
-	str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
-	
-	chain_pos = str9xpec_info->chain_pos;
-	
-	if (!str9xpec_info->isc_enable)
-		return ERROR_OK;
-	
-	if (str9xpec_set_instr(chain_pos, ISC_DISABLE, TAP_RTI) != ERROR_OK)
-		return ERROR_TARGET_INVALID;
-	
-	/* delay to handle aborts */
-	jtag_add_sleep(50);
-	
-	/* check ISC status */
-	status = str9xpec_isc_status(chain_pos);
-	if (!(status & ISC_STATUS_MODE))
-	{
-		/* we have left isc mode */
-		str9xpec_info->isc_enable = 0;
-		DEBUG("ISC_MODE Disabled");
-	}
-	
-	return ERROR_OK;
-}
-
-int str9xpec_read_config(struct flash_bank_s *bank)
-{
-	scan_field_t field;
-	u8 status;
-	u32 chain_pos;
-		
-	str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
-	
-	chain_pos = str9xpec_info->chain_pos;
-	
-	DEBUG("ISC_CONFIGURATION");
-	
-	/* execute ISC_CONFIGURATION command */
-	str9xpec_set_instr(chain_pos, ISC_CONFIGURATION, TAP_PI);
-	
-	field.device = chain_pos;
-	field.num_bits = 64;
-	field.out_value = NULL;
-	field.out_mask = NULL;
-	field.in_value = str9xpec_info->options;
-	field.in_check_value = NULL;
-	field.in_check_mask = NULL;
-	field.in_handler = NULL;
-	field.in_handler_priv = NULL;
-	
-	jtag_add_dr_scan(1, &field, TAP_RTI, NULL);
-	jtag_execute_queue();
-	
-	status = str9xpec_isc_status(chain_pos);
-	
-	return status;
-}
-
-int str9xpec_build_block_list(struct flash_bank_s *bank)
-{
-	str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
-	
-	int i;
-	int num_sectors = 0, b0_sectors = 0;
-		
-	switch (bank->size)
-	{
-		case (256 * 1024):
-			b0_sectors = 4;
-			break;
-		case (512 * 1024):
-			b0_sectors = 8;
-			break;
-		default:
-			ERROR("BUG: unknown bank->size encountered");
-			exit(-1);
-	}
-	
-	/* include bank 1 sectors */
-	num_sectors = b0_sectors + 4;
-	bank->size += (32 * 1024);
-	
-	bank->num_sectors = num_sectors;
-	bank->sectors = malloc(sizeof(flash_sector_t) * num_sectors);
-	str9xpec_info->sector_bits = malloc(sizeof(u32) * num_sectors);
-	
-	num_sectors = 0;
-	
-	for (i = 0; i < b0_sectors; i++)
-	{
-		bank->sectors[num_sectors].offset = mem_layout_str9pec[i].sector_start;
-		bank->sectors[num_sectors].size = mem_layout_str9pec[i].sector_size;
-		bank->sectors[num_sectors].is_erased = -1;
-		bank->sectors[num_sectors].is_protected = 1;
-		str9xpec_info->sector_bits[num_sectors++] = mem_layout_str9pec[i].sector_bit;
-	}
-	
-	for (i = 8; i < 12; i++)
-	{
-		bank->sectors[num_sectors].offset = mem_layout_str9pec[i].sector_start;
-		bank->sectors[num_sectors].size = mem_layout_str9pec[i].sector_size;
-		bank->sectors[num_sectors].is_erased = -1;
-		bank->sectors[num_sectors].is_protected = 1;
-		str9xpec_info->sector_bits[num_sectors++] = mem_layout_str9pec[i].sector_bit;
-	}
-	
-	return ERROR_OK;
-}
-
-/* flash bank str9x <base> <size> 0 0 <target#>
- */
-int str9xpec_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
-{
-	str9xpec_flash_controller_t *str9xpec_info;
-	armv4_5_common_t *armv4_5 = NULL;
-	arm7_9_common_t *arm7_9 = NULL;
-	arm_jtag_t *jtag_info = NULL;
-	
-	if (argc < 6)
-	{
-		WARNING("incomplete flash_bank str9x configuration");
-		return ERROR_FLASH_BANK_INVALID;
-	}
-	
-	str9xpec_info = malloc(sizeof(str9xpec_flash_controller_t));
-	bank->driver_priv = str9xpec_info;
-	
-	if (bank->base != 0x00000000)
-	{
-		WARNING("overriding flash base address for STR91x device with 0x00000000");
-		bank->base = 0x00000000;
-	}
-
-	/* find out jtag position of flash controller
-	 * it is always after the arm966 core */
-	
-	armv4_5 = bank->target->arch_info;
-	arm7_9 = armv4_5->arch_info;
-	jtag_info = &arm7_9->jtag_info;
-	
-	str9xpec_info->chain_pos = (jtag_info->chain_pos - 1);
-	str9xpec_info->isc_enable = 0;
-	str9xpec_info->devarm = NULL;
-	
-	str9xpec_build_block_list(bank);
-	
-	/* clear option byte register */
-	buf_set_u32(str9xpec_info->options, 0, 64, 0);
-	
-	return ERROR_OK;
-}
-
-int str9xpec_blank_check(struct flash_bank_s *bank, int first, int last)
-{
-	scan_field_t field;
-	u8 status;
-	u32 chain_pos;
-	int i;
-	u8 *buffer = NULL;
-		
-	str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
-	
-	chain_pos = str9xpec_info->chain_pos;
-	
-	if (!str9xpec_info->isc_enable) {
-		str9xpec_isc_enable( bank );
-	}
-	
-	if (!str9xpec_info->isc_enable) {
-		return ERROR_FLASH_OPERATION_FAILED;
-	}
-	
-	buffer = calloc(CEIL(64, 8), 1);
-
-	DEBUG("blank check: first_bank: %i, last_bank: %i", first, last);
-	
-	for (i = first; i <= last; i++) {
-		buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1);
-	}
-	
-	/* execute ISC_BLANK_CHECK command */
-	str9xpec_set_instr(chain_pos, ISC_BLANK_CHECK, TAP_PI);
-	
-	field.device = chain_pos;
-	field.num_bits = 64;
-	field.out_value = buffer;
-	field.out_mask = NULL;
-	field.in_value = NULL;
-	field.in_check_value = NULL;
-	field.in_check_mask = NULL;
-	field.in_handler = NULL;
-	field.in_handler_priv = NULL;
-	
-	jtag_add_dr_scan(1, &field, TAP_RTI, NULL);
-	jtag_add_sleep(40000);
-	
-	/* read blank check result */
-	field.device = chain_pos;
-	field.num_bits = 64;
-	field.out_value = NULL;
-	field.out_mask = NULL;
-	field.in_value = buffer;
-	field.in_check_value = NULL;
-	field.in_check_mask = NULL;
-	field.in_handler = NULL;
-	field.in_handler_priv = NULL;
-	
-	jtag_add_dr_scan(1, &field, TAP_PI, NULL);
-	jtag_execute_queue();
-	
-	status = str9xpec_isc_status(chain_pos);
-	
-	for (i = first; i <= last; i++)
-	{
-		if (buf_get_u32(buffer, str9xpec_info->sector_bits[i], 1))
-			bank->sectors[i].is_erased = 0;
-		else
-			bank->sectors[i].is_erased = 1;
-	}
-	
-	free(buffer);
-	
-	str9xpec_isc_disable(bank);
-	
-	if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
-		return ERROR_FLASH_OPERATION_FAILED; 
-	return ERROR_OK;
-}
-
-int str9xpec_protect_check(struct flash_bank_s *bank)
-{
-	u8 status;
-	int i;
-		
-	str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
-	
-	status = str9xpec_read_config(bank);
-	
-	for (i = 0; i < bank->num_sectors; i++)
-	{
-		if (buf_get_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1))
-			bank->sectors[i].is_protected = 1;
-		else
-			bank->sectors[i].is_protected = 0;
-	}
-	
-	if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
-		return ERROR_FLASH_OPERATION_FAILED;
-	return ERROR_OK;
-}
-
-int str9xpec_erase_area(struct flash_bank_s *bank, int first, int last)
-{
-	scan_field_t field;
-	u8 status;
-	u32 chain_pos;
-	int i;
-	u8 *buffer = NULL;
-	
-	str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
-	
-	chain_pos = str9xpec_info->chain_pos;
-	
-	if (!str9xpec_info->isc_enable) {
-		str9xpec_isc_enable( bank );
-	}
-	
-	if (!str9xpec_info->isc_enable) {
-		return ISC_STATUS_ERROR;
-	}
-	
-	buffer = calloc(CEIL(64, 8), 1);
-	
-	DEBUG("erase: first_bank: %i, last_bank: %i", first, last);
-	
-	/* last bank: 0xFF signals a full erase (unlock complete device) */
-	/* last bank: 0xFE signals a option byte erase */
-	if (last == 0xFF)
-	{
-		for (i = 0; i < 64; i++) {
-			buf_set_u32(buffer, i, 1, 1);
-		}	
-	}
-	else if (last == 0xFE)
-	{
-		buf_set_u32(buffer, 49, 1, 1);
-	}
-	else
-	{	
-		for (i = first; i <= last; i++) {
-			buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1);
-		}
-	}
-	
-	DEBUG("ISC_ERASE");
-	
-	/* execute ISC_ERASE command */
-	str9xpec_set_instr(chain_pos, ISC_ERASE, TAP_PI);
-	
-	field.device = chain_pos;
-	field.num_bits = 64;
-	field.out_value = buffer;
-	field.out_mask = NULL;
-	field.in_value = NULL;
-	field.in_check_value = NULL;
-	field.in_check_mask = NULL;
-	field.in_handler = NULL;
-	field.in_handler_priv = NULL;
-	
-	jtag_add_dr_scan(1, &field, TAP_RTI, NULL);
-	jtag_execute_queue();
-	
-	jtag_add_sleep(10);
-	
-	/* wait for erase completion */
-	while (!((status = str9xpec_isc_status(chain_pos)) & ISC_STATUS_BUSY)) {
-		usleep(1000);
-	}
-	
-	free(buffer);
-	
-	str9xpec_isc_disable(bank);
-	
-	return status;
-}
-
-int str9xpec_erase(struct flash_bank_s *bank, int first, int last)
-{
-	int status;
-	
-	status = str9xpec_erase_area(bank, first, last);
-	
-	if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
-		return ERROR_FLASH_OPERATION_FAILED;
-	
-	return ERROR_OK;
-}
-
-int str9xpec_lock_device(struct flash_bank_s *bank)
-{
-	scan_field_t field;
-	u8 status;
-	u32 chain_pos;
-	str9xpec_flash_controller_t *str9xpec_info = NULL;
-	
-	str9xpec_info = bank->driver_priv;
-	chain_pos = str9xpec_info->chain_pos;
-	
-	if (!str9xpec_info->isc_enable) {
-		str9xpec_isc_enable( bank );
-	}
-	
-	if (!str9xpec_info->isc_enable) {
-		return ISC_STATUS_ERROR;
-	}
-	
-	/* set security address */
-	str9xpec_set_address(bank, 0x80);
-	
-	/* execute ISC_PROGRAM command */
-	str9xpec_set_instr(chain_pos, ISC_PROGRAM_SECURITY, TAP_RTI);
-	
-	str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI);
-	
-	do {
-		field.device = chain_pos;
-		field.num_bits = 8;
-		field.out_value = NULL;
-		field.out_mask = NULL;
-		field.in_value = &status;
-		field.in_check_value = NULL;
-		field.in_check_mask = NULL;
-		field.in_handler = NULL;
-		field.in_handler_priv = NULL;
-		
-		jtag_add_dr_scan(1, &field, -1, NULL);
-		jtag_execute_queue();
-		
-	} while(!(status & ISC_STATUS_BUSY));
-	
-	str9xpec_isc_disable(bank);
-	
-	return status;
-}
-
-int str9xpec_unlock_device(struct flash_bank_s *bank)
-{
-	u8 status;
-	
-	status = str9xpec_erase_area(bank, 0, 255);
-	
-	return status;
-}
-
-int str9xpec_protect(struct flash_bank_s *bank, int set, int first, int last)
-{
-	u8 status;
-	int i;
-	
-	str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
-	
-	status = str9xpec_read_config(bank);
-	
-	if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
-		return ERROR_FLASH_OPERATION_FAILED;
-
-	DEBUG("protect: first_bank: %i, last_bank: %i", first, last);
-	
-	/* last bank: 0xFF signals a full device protect */
-	if (last == 0xFF)
-	{
-		if( set )
-		{
-			status = str9xpec_lock_device(bank);
-		}
-		else
-		{
-			/* perform full erase to unlock device */
-			status = str9xpec_unlock_device(bank);
-		}
-	}
-	else
-	{	
-		for (i = first; i <= last; i++)
-		{
-			if( set )
-				buf_set_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1, 1);
-			else
-				buf_set_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1, 0);
-		}
-		
-		status = str9xpec_write_options(bank);
-	}
-	
-	if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
-		return ERROR_FLASH_OPERATION_FAILED;
-	
-	return ERROR_OK;
-}
-
-int str9xpec_set_address(struct flash_bank_s *bank, u8 sector)
-{
-	u32 chain_pos;
-	scan_field_t field;
-	str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
-	
-	chain_pos = str9xpec_info->chain_pos;
-	
-	/* set flash controller address */
-	str9xpec_set_instr(chain_pos, ISC_ADDRESS_SHIFT, TAP_PI);
-	
-	field.device = chain_pos;
-	field.num_bits = 8;
-	field.out_value = &sector;
-	field.out_mask = NULL;
-	field.in_value = NULL;
-	field.in_check_value = NULL;
-	field.in_check_mask = NULL;
-	field.in_handler = NULL;
-	field.in_handler_priv = NULL;
-	
-	jtag_add_dr_scan(1, &field, -1, NULL);
-		
-	return ERROR_OK;
-}
-
-int str9xpec_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
-{
-	str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
-	u32 dwords_remaining = (count / 8);
-	u32 bytes_remaining = (count & 0x00000007);
-	u32 bytes_written = 0;
-	u8 status;
-	u32 check_address = offset;
-	u32 chain_pos;
-	scan_field_t field;
-	u8 *scanbuf;
-	int i;
-	u32 first_sector = 0;
-	u32 last_sector = 0;
-	
-	chain_pos = str9xpec_info->chain_pos;
-	
-	if (!str9xpec_info->isc_enable) {
-		str9xpec_isc_enable(bank);
-	}
-	
-	if (!str9xpec_info->isc_enable) {
-		return ERROR_FLASH_OPERATION_FAILED;
-	}
-	
-	if (offset & 0x7)
-	{
-		WARNING("offset 0x%x breaks required 8-byte alignment", offset);
-		return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
-	}
-	
-	for (i = 0; i < bank->num_sectors; i++)
-	{
-		u32 sec_start = bank->sectors[i].offset;
-		u32 sec_end = sec_start + bank->sectors[i].size;
-		
-		/* check if destination falls within the current sector */
-		if ((check_address >= sec_start) && (check_address < sec_end))
-		{
-			/* check if destination ends in the current sector */
-			if (offset + count < sec_end)
-				check_address = offset + count;
-			else
-				check_address = sec_end;
-		}
-		
-		if ((offset >= sec_start) && (offset < sec_end)){
-			first_sector = i;
-		}
-		
-		if ((offset + count >= sec_start) && (offset + count < sec_end)){
-			last_sector = i;
-		}
-	}
-	
-	if (check_address != offset + count)
-		return ERROR_FLASH_DST_OUT_OF_BANK;
-
-	DEBUG("first_sector: %i, last_sector: %i", first_sector, last_sector);
-	
-	scanbuf = calloc(CEIL(64, 8), 1);
-	
-	DEBUG("ISC_PROGRAM");
-	
-	for (i = first_sector; i <= last_sector; i++)
-	{
-		str9xpec_set_address(bank, str9xpec_info->sector_bits[i]);
-		
-		dwords_remaining = dwords_remaining < (bank->sectors[i].size/8) ? dwords_remaining : (bank->sectors[i].size/8);
-
-		while (dwords_remaining > 0)
-		{	
-			str9xpec_set_instr(chain_pos, ISC_PROGRAM, TAP_PI);
-			
-			field.device = chain_pos;
-			field.num_bits = 64;
-			field.out_value = (buffer + bytes_written);
-			field.out_mask = NULL;
-			field.in_value = NULL;
-			field.in_check_value = NULL;
-			field.in_check_mask = NULL;
-			field.in_handler = NULL;
-			field.in_handler_priv = NULL;
-			
-			jtag_add_dr_scan(1, &field, TAP_RTI, NULL);
-			
-			/* small delay before polling */
-			jtag_add_sleep(50);
-			
-			str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI);
-			
-			do {
-				field.device = chain_pos;
-				field.num_bits = 8;
-				field.out_value = NULL;
-				field.out_mask = NULL;
-				field.in_value = scanbuf;
-				field.in_check_value = NULL;
-				field.in_check_mask = NULL;
-				field.in_handler = NULL;
-				field.in_handler_priv = NULL;
-				
-				jtag_add_dr_scan(1, &field, -1, NULL);
-				jtag_execute_queue();
-				
-				status = buf_get_u32(scanbuf, 0, 8);
-				
-			} while(!(status & ISC_STATUS_BUSY));
-			
-			if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
-				return ERROR_FLASH_OPERATION_FAILED;
-			
-			//if ((status & ISC_STATUS_INT_ERROR) != STR9XPEC_ISC_INTFAIL)
-			//	return ERROR_FLASH_OPERATION_FAILED;
-		
-			dwords_remaining--;
-			bytes_written += 8;
-		}
-	}
-	
-	if (bytes_remaining)
-	{
-		u8 last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-		int i = 0;
-				
-		while(bytes_remaining > 0)
-		{
-			last_dword[i++] = *(buffer + bytes_written); 
-			bytes_remaining--;
-			bytes_written++;
-		}
-		
-		str9xpec_set_instr(chain_pos, ISC_PROGRAM, TAP_PI);
-		
-		field.device = chain_pos;
-		field.num_bits = 64;
-		field.out_value = last_dword;
-		field.out_mask = NULL;
-		field.in_value = NULL;
-		field.in_check_value = NULL;
-		field.in_check_mask = NULL;
-		field.in_handler = NULL;
-		field.in_handler_priv = NULL;
-		
-		jtag_add_dr_scan(1, &field, TAP_RTI, NULL);
-		
-		/* small delay before polling */
-		jtag_add_sleep(50);
-		
-		str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI);
-		
-		do {
-			field.device = chain_pos;
-			field.num_bits = 8;
-			field.out_value = NULL;
-			field.out_mask = NULL;
-			field.in_value = scanbuf;
-			field.in_check_value = NULL;
-			field.in_check_mask = NULL;
-			field.in_handler = NULL;
-			field.in_handler_priv = NULL;
-			
-			jtag_add_dr_scan(1, &field, -1, NULL);
-			jtag_execute_queue();
-			
-			status = buf_get_u32(scanbuf, 0, 8);
-			
-		} while(!(status & ISC_STATUS_BUSY));
-		
-		if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
-			return ERROR_FLASH_OPERATION_FAILED;
-		
-		//if ((status & ISC_STATUS_INT_ERROR) != STR9XPEC_ISC_INTFAIL)
-		//	return ERROR_FLASH_OPERATION_FAILED;
-	}
-
-	free(scanbuf);
-
-	str9xpec_isc_disable(bank);
-				
-	return ERROR_OK;
-}
-
-int str9xpec_probe(struct flash_bank_s *bank)
-{
-	return ERROR_OK;
-}
-
-int str9xpec_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	flash_bank_t *bank;
-	scan_field_t field;
-	u8 *buffer = NULL;
-	u32 chain_pos;
-	u32 idcode;
-	str9xpec_flash_controller_t *str9xpec_info = NULL;
-
-	if (argc < 1)
-	{
-		return ERROR_COMMAND_SYNTAX_ERROR;
-	}
-	
-	bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
-	if (!bank)
-	{
-		command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
-		return ERROR_OK;
-	}
-	
-	str9xpec_info = bank->driver_priv;
-	chain_pos = str9xpec_info->chain_pos;
-	
-	buffer = calloc(CEIL(32, 8), 1);
-	
-	str9xpec_set_instr(chain_pos, ISC_IDCODE, TAP_PI);
-	
-	field.device = chain_pos;
-	field.num_bits = 32;
-	field.out_value = NULL;
-	field.out_mask = NULL;
-	field.in_value = buffer;
-	field.in_check_value = NULL;
-	field.in_check_mask = NULL;
-	field.in_handler = NULL;
-	field.in_handler_priv = NULL;
-	
-	jtag_add_dr_scan(1, &field, TAP_RTI, NULL);
-	jtag_execute_queue();
-	
-	idcode = buf_get_u32(buffer, 0, 32);
-	
-	command_print(cmd_ctx, "str9xpec part id: 0x%8.8x", idcode);
-	
-	free(buffer);
-	
-	return ERROR_OK;
-}
-
-int str9xpec_erase_check(struct flash_bank_s *bank)
-{
-	return str9xpec_blank_check(bank, 0, bank->num_sectors - 1);
-}
-
-int str9xpec_info(struct flash_bank_s *bank, char *buf, int buf_size)
-{
-	snprintf(buf, buf_size, "str9xpec flash driver info" );
-	return ERROR_OK;
-}
-
-int str9xpec_handle_flash_options_read_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	flash_bank_t *bank;
-	u8 status;
-	str9xpec_flash_controller_t *str9xpec_info = NULL;
-	
-	if (argc < 1)
-	{
-		command_print(cmd_ctx, "str9xpec options_read <bank>");
-		return ERROR_OK;	
-	}
-	
-	bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
-	if (!bank)
-	{
-		command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
-		return ERROR_OK;
-	}
-	
-	str9xpec_info = bank->driver_priv;
-	
-	status = str9xpec_read_config(bank);
-	
-	if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
-		return ERROR_FLASH_OPERATION_FAILED;
-	
-	/* boot bank */
-	if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1))
-		command_print(cmd_ctx, "CS Map: bank1");
-	else
-		command_print(cmd_ctx, "CS Map: bank0");
-	
-	/* OTP lock */
-	if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_OTPBIT, 1))
-		command_print(cmd_ctx, "OTP Lock: OTP Locked");
-	else
-		command_print(cmd_ctx, "OTP Lock: OTP Unlocked");
-	
-	/* LVD Threshold */
-	if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1))
-		command_print(cmd_ctx, "LVD Threshold: 2.7v");
-	else
-		command_print(cmd_ctx, "LVD Threshold: 2.4v");
-	
-	/* LVD reset warning */
-	if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1))
-		command_print(cmd_ctx, "LVD Reset Warning: VDD or VDDQ Inputs");
-	else
-		command_print(cmd_ctx, "LVD Reset Warning: VDD Input Only");
-	
-	/* LVD reset select */
-	if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1))
-		command_print(cmd_ctx, "LVD Reset Selection: VDD or VDDQ Inputs");
-	else
-		command_print(cmd_ctx, "LVD Reset Selection: VDD Input Only");
-	
-	return ERROR_OK;
-}
-
-int str9xpec_write_options(struct flash_bank_s *bank)
-{
-	scan_field_t field;
-	u8 status;
-	u32 chain_pos;
-	str9xpec_flash_controller_t *str9xpec_info = NULL;
-	
-	str9xpec_info = bank->driver_priv;
-	chain_pos = str9xpec_info->chain_pos;
-	
-	/* erase config options first */
-	status = str9xpec_erase_area( bank, 0xFE, 0xFE );
-	
-	if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
-		return status; 
-	
-	if (!str9xpec_info->isc_enable) {
-		str9xpec_isc_enable( bank );
-	}
-	
-	if (!str9xpec_info->isc_enable) {
-		return ISC_STATUS_ERROR;
-	}
-	
-	/* according to data 64th bit has to be set */
-	buf_set_u32(str9xpec_info->options, 63, 1, 1);
-	
-	/* set option byte address */
-	str9xpec_set_address(bank, 0x50);
-	
-	/* execute ISC_PROGRAM command */
-	str9xpec_set_instr(chain_pos, ISC_PROGRAM, TAP_PI);
-		
-	field.device = chain_pos;
-	field.num_bits = 64;
-	field.out_value = str9xpec_info->options;
-	field.out_mask = NULL;
-	field.in_value = NULL;
-	field.in_check_value = NULL;
-	field.in_check_mask = NULL;
-	field.in_handler = NULL;
-	field.in_handler_priv = NULL;
-	
-	jtag_add_dr_scan(1, &field, TAP_RTI, NULL);
-	
-	/* small delay before polling */
-	jtag_add_sleep(50);
-	
-	str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI);
-	
-	do {
-		field.device = chain_pos;
-		field.num_bits = 8;
-		field.out_value = NULL;
-		field.out_mask = NULL;
-		field.in_value = &status;
-		field.in_check_value = NULL;
-		field.in_check_mask = NULL;
-		field.in_handler = NULL;
-		field.in_handler_priv = NULL;
-		
-		jtag_add_dr_scan(1, &field, -1, NULL);
-		jtag_execute_queue();
-		
-	} while(!(status & ISC_STATUS_BUSY));
-	
-	str9xpec_isc_disable(bank);
-	
-	return status;
-}
-
-int str9xpec_handle_flash_options_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	flash_bank_t *bank;
-	u8 status;
-	
-	if (argc < 1)
-	{
-		command_print(cmd_ctx, "str9xpec options_write <bank>");
-		return ERROR_OK;	
-	}
-	
-	bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
-	if (!bank)
-	{
-		command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
-		return ERROR_OK;
-	}
-	
-	status = str9xpec_write_options(bank);
-	
-	if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
-		return ERROR_FLASH_OPERATION_FAILED;
-	
-	return ERROR_OK;
-}
-
-int str9xpec_handle_flash_options_cmap_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	flash_bank_t *bank;
-	str9xpec_flash_controller_t *str9xpec_info = NULL;
-	
-	if (argc < 2)
-	{
-		command_print(cmd_ctx, "str9xpec options_cmap <bank> <bank0|bank1>");
-		return ERROR_OK;	
-	}
-	
-	bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
-	if (!bank)
-	{
-		command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
-		return ERROR_OK;
-	}
-	
-	str9xpec_info = bank->driver_priv;
-	
-	if (strcmp(args[1], "bank1") == 0)
-	{
-		buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 1);
-	}
-	else
-	{
-		buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 0);
-	}
-	
-	return ERROR_OK;
-}
-
-int str9xpec_handle_flash_options_lvdthd_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	flash_bank_t *bank;
-	str9xpec_flash_controller_t *str9xpec_info = NULL;
-	
-	if (argc < 2)
-	{
-		command_print(cmd_ctx, "str9xpec options_lvdthd <bank> <2.4v|2.7v>");
-		return ERROR_OK;	
-	}
-	
-	bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
-	if (!bank)
-	{
-		command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
-		return ERROR_OK;
-	}
-	
-	str9xpec_info = bank->driver_priv;
-	
-	if (strcmp(args[1], "2.7v") == 0)
-	{
-		buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 1);
-	}
-	else
-	{
-		buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 0);
-	}
-	
-	return ERROR_OK;
-}
-
-int str9xpec_handle_flash_options_lvdsel_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	flash_bank_t *bank;
-	str9xpec_flash_controller_t *str9xpec_info = NULL;
-	
-	if (argc < 2)
-	{
-		command_print(cmd_ctx, "str9xpec options_lvdsel <bank> <vdd|vdd_vddq>");
-		return ERROR_OK;	
-	}
-	
-	bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
-	if (!bank)
-	{
-		command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
-		return ERROR_OK;
-	}
-	
-	str9xpec_info = bank->driver_priv;
-	
-	if (strcmp(args[1], "vdd_vddq") == 0)
-	{
-		buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 1);
-	}
-	else
-	{
-		buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 0);
-	}
-	
-	return ERROR_OK;
-}
-
-int str9xpec_handle_flash_options_lvdwarn_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	flash_bank_t *bank;
-	str9xpec_flash_controller_t *str9xpec_info = NULL;
-	
-	if (argc < 2)
-	{
-		command_print(cmd_ctx, "str9xpec options_lvdwarn <bank> <vdd|vdd_vddq>");
-		return ERROR_OK;	
-	}
-	
-	bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
-	if (!bank)
-	{
-		command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
-		return ERROR_OK;
-	}
-	
-	str9xpec_info = bank->driver_priv;
-	
-	if (strcmp(args[1], "vdd_vddq") == 0)
-	{
-		buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 1);
-	}
-	else
-	{
-		buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 0);
-	}
-	
-	return ERROR_OK;
-}
-
-int str9xpec_handle_flash_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	u8 status;
-	flash_bank_t *bank;
-	
-	if (argc < 1)
-	{
-		command_print(cmd_ctx, "str9xpec lock <bank>");
-		return ERROR_OK;	
-	}
-	
-	bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
-	if (!bank)
-	{
-		command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
-		return ERROR_OK;
-	}
-	
-	status = str9xpec_lock_device(bank);
-	
-	if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
-		return ERROR_FLASH_OPERATION_FAILED;
-	
-	return ERROR_OK;
-}
-
-int str9xpec_handle_flash_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	u8 status;
-	flash_bank_t *bank;
-	
-	if (argc < 1)
-	{
-		command_print(cmd_ctx, "str9xpec unlock <bank>");
-		return ERROR_OK;	
-	}
-	
-	bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
-	if (!bank)
-	{
-		command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
-		return ERROR_OK;
-	}
-	
-	status = str9xpec_unlock_device(bank);
-	
-	if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
-		return ERROR_FLASH_OPERATION_FAILED;
-	
-	return ERROR_OK;
-}
-
-int str9xpec_handle_flash_enable_turbo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	flash_bank_t *bank;
-	u32 chain_pos;
-	jtag_device_t* dev0;
-	jtag_device_t* dev2;
-	str9xpec_flash_controller_t *str9xpec_info = NULL;
-	
-	if (argc < 1)
-	{
-		command_print(cmd_ctx, "str9xpec enable_turbo <bank>");
-		return ERROR_OK;	
-	}
-	
-	bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
-	if (!bank)
-	{
-		command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
-		return ERROR_OK;
-	}
-	
-	str9xpec_info = bank->driver_priv;
-	
-	chain_pos = str9xpec_info->chain_pos;
-	
-	/* remove arm core from chain - enter turbo mode */
-	
-	str9xpec_set_instr(chain_pos+2, 0xD, TAP_RTI);
-	jtag_execute_queue();
-	
-	/* modify scan chain - str9 core has been removed */
-	dev0 = jtag_get_device(chain_pos);
-	str9xpec_info->devarm = jtag_get_device(chain_pos+1);
-	dev2 = jtag_get_device(chain_pos+2);
-	dev0->next = dev2;
-	jtag_num_devices--;
-	
-	return ERROR_OK;
-}
-
-int str9xpec_handle_flash_disable_turbo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	flash_bank_t *bank;
-	u32 chain_pos;
-	jtag_device_t* dev0;
-	str9xpec_flash_controller_t *str9xpec_info = NULL;
-	
-	if (argc < 1)
-	{
-		command_print(cmd_ctx, "str9xpec disable_turbo <bank>");
-		return ERROR_OK;	
-	}
-	
-	bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
-	if (!bank)
-	{
-		command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
-		return ERROR_OK;
-	}
-	
-	str9xpec_info = bank->driver_priv;
-	
-	chain_pos = str9xpec_info->chain_pos;
-	
-	dev0 = jtag_get_device(chain_pos);
-	
-	/* exit turbo mode via TLR */
-	str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_TLR);
-	jtag_execute_queue();
-	
-	/* restore previous scan chain */
-	if( str9xpec_info->devarm ) {
-		dev0->next = str9xpec_info->devarm;
-		jtag_num_devices++;
-		str9xpec_info->devarm = NULL;
-	}
-	
-	return ERROR_OK;
-}
+/***************************************************************************
+ *   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.             *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "replacements.h"
+
+#include "str9xpec.h"
+#include "flash.h"
+#include "target.h"
+#include "log.h"
+#include "armv4_5.h"
+#include "arm7_9_common.h"
+#include "jtag.h"
+#include "binarybuffer.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <getopt.h>
+
+str9xpec_mem_layout_t mem_layout_str9pec[] = {
+	{0x00000000, 0x10000, 0},
+	{0x00010000, 0x10000, 1},
+	{0x00020000, 0x10000, 2},
+	{0x00030000, 0x10000, 3},
+	{0x00040000, 0x10000, 4},
+	{0x00050000, 0x10000, 5},
+	{0x00060000, 0x10000, 6},
+	{0x00070000, 0x10000, 7},
+	{0x00080000, 0x02000, 32},
+	{0x00082000, 0x02000, 33},
+	{0x00084000, 0x02000, 34},
+	{0x00086000, 0x02000, 35}
+};
+
+int str9xpec_register_commands(struct command_context_s *cmd_ctx);
+int str9xpec_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank);
+int str9xpec_erase(struct flash_bank_s *bank, int first, int last);
+int str9xpec_protect(struct flash_bank_s *bank, int set, int first, int last);
+int str9xpec_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
+int str9xpec_probe(struct flash_bank_s *bank);
+int str9xpec_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int str9xpec_protect_check(struct flash_bank_s *bank);
+int str9xpec_erase_check(struct flash_bank_s *bank);
+int str9xpec_info(struct flash_bank_s *bank, char *buf, int buf_size);
+
+int str9xpec_erase_area(struct flash_bank_s *bank, int first, int last);
+int str9xpec_set_address(struct flash_bank_s *bank, u8 sector);
+int str9xpec_write_options(struct flash_bank_s *bank);
+
+int str9xpec_handle_flash_options_cmap_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int str9xpec_handle_flash_options_lvdthd_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int str9xpec_handle_flash_options_lvdsel_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int str9xpec_handle_flash_options_lvdwarn_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int str9xpec_handle_flash_options_read_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int str9xpec_handle_flash_options_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int str9xpec_handle_flash_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int str9xpec_handle_flash_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int str9xpec_handle_flash_enable_turbo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int str9xpec_handle_flash_disable_turbo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+flash_driver_t str9xpec_flash =
+{
+	.name = "str9xpec",
+	.register_commands = str9xpec_register_commands,
+	.flash_bank_command = str9xpec_flash_bank_command,
+	.erase = str9xpec_erase,
+	.protect = str9xpec_protect,
+	.write = str9xpec_write,
+	.probe = str9xpec_probe,
+	.auto_probe = str9xpec_probe,
+	.erase_check = str9xpec_erase_check,
+	.protect_check = str9xpec_protect_check,
+	.info = str9xpec_info
+};
+
+int str9xpec_register_commands(struct command_context_s *cmd_ctx)
+{
+	command_t *str9xpec_cmd = register_command(cmd_ctx, NULL, "str9xpec", NULL, COMMAND_ANY, "str9xpec flash specific commands");
+	
+	register_command(cmd_ctx, str9xpec_cmd, "enable_turbo", str9xpec_handle_flash_enable_turbo_command, COMMAND_EXEC,
+					 "enable str9xpec turbo mode");
+	register_command(cmd_ctx, str9xpec_cmd, "disable_turbo", str9xpec_handle_flash_disable_turbo_command, COMMAND_EXEC,
+					 "disable str9xpec turbo mode");
+	register_command(cmd_ctx, str9xpec_cmd, "options_cmap", str9xpec_handle_flash_options_cmap_command, COMMAND_EXEC,
+					 "configure str9xpec boot sector");
+	register_command(cmd_ctx, str9xpec_cmd, "options_lvdthd", str9xpec_handle_flash_options_lvdthd_command, COMMAND_EXEC,
+					 "configure str9xpec lvd threshold");
+	register_command(cmd_ctx, str9xpec_cmd, "options_lvdsel", str9xpec_handle_flash_options_lvdsel_command, COMMAND_EXEC,
+					 "configure str9xpec lvd selection");
+	register_command(cmd_ctx, str9xpec_cmd, "options_lvdwarn", str9xpec_handle_flash_options_lvdwarn_command, COMMAND_EXEC,
+					 "configure str9xpec lvd warning");
+	register_command(cmd_ctx, str9xpec_cmd, "options_read", str9xpec_handle_flash_options_read_command, COMMAND_EXEC,
+					 "read str9xpec options");
+	register_command(cmd_ctx, str9xpec_cmd, "options_write", str9xpec_handle_flash_options_write_command, COMMAND_EXEC,
+					 "write str9xpec options");
+	register_command(cmd_ctx, str9xpec_cmd, "lock", str9xpec_handle_flash_lock_command, COMMAND_EXEC,
+					 "lock str9xpec device");
+	register_command(cmd_ctx, str9xpec_cmd, "unlock", str9xpec_handle_flash_unlock_command, COMMAND_EXEC,
+					 "unlock str9xpec device");
+	register_command(cmd_ctx, str9xpec_cmd, "part_id", str9xpec_handle_part_id_command, COMMAND_EXEC,
+					 "print part id of str9xpec flash bank <num>");
+	
+	return ERROR_OK;
+}
+
+int str9xpec_set_instr(int chain_pos, u32 new_instr, enum tap_state end_state)
+{
+	jtag_device_t *device = jtag_get_device(chain_pos);
+	
+	if (device == NULL)
+	{
+		DEBUG("Invalid Target");
+		return ERROR_TARGET_INVALID;
+	}
+		
+	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 = NULL;
+		field.in_check_mask = NULL;
+		field.in_handler = NULL;
+		field.in_handler_priv = NULL;
+		
+		jtag_add_ir_scan(1, &field, end_state);
+		
+		free(field.out_value);
+	}
+	
+	return ERROR_OK;
+}
+
+u8 str9xpec_isc_status(int chain_pos)
+{
+	scan_field_t field;
+	u8 status;
+	
+	if (str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI) != ERROR_OK)
+		return ISC_STATUS_ERROR;
+	
+	field.device = chain_pos;
+	field.num_bits = 8;
+	field.out_value = NULL;
+	field.out_mask = NULL;
+	field.in_value = &status;
+	field.in_check_value = NULL;
+	field.in_check_mask = NULL;
+	field.in_handler = NULL;
+	field.in_handler_priv = NULL;
+	
+	jtag_add_dr_scan(1, &field, TAP_RTI);
+	jtag_execute_queue();
+	
+	DEBUG("status: 0x%2.2x", status);
+	
+	if (status & ISC_STATUS_SECURITY)
+		INFO("Device Security Bit Set");
+	
+	return status;
+}
+
+int str9xpec_isc_enable(struct flash_bank_s *bank)
+{
+	u8 status;
+	u32 chain_pos;
+	str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
+	
+	chain_pos = str9xpec_info->chain_pos;
+	
+	if (str9xpec_info->isc_enable)
+		return ERROR_OK;
+	
+	/* enter isc mode */
+	if (str9xpec_set_instr(chain_pos, ISC_ENABLE, TAP_RTI) != ERROR_OK)
+		return ERROR_TARGET_INVALID;
+	
+	/* check ISC status */
+	status = str9xpec_isc_status(chain_pos);
+	if (status & ISC_STATUS_MODE)
+	{
+		/* we have entered isc mode */
+		str9xpec_info->isc_enable = 1;
+		DEBUG("ISC_MODE Enabled");
+	}
+	
+	return ERROR_OK;
+}
+
+int str9xpec_isc_disable(struct flash_bank_s *bank)
+{
+	u8 status;
+	u32 chain_pos;
+	str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
+	
+	chain_pos = str9xpec_info->chain_pos;
+	
+	if (!str9xpec_info->isc_enable)
+		return ERROR_OK;
+	
+	if (str9xpec_set_instr(chain_pos, ISC_DISABLE, TAP_RTI) != ERROR_OK)
+		return ERROR_TARGET_INVALID;
+	
+	/* delay to handle aborts */
+	jtag_add_sleep(50);
+	
+	/* check ISC status */
+	status = str9xpec_isc_status(chain_pos);
+	if (!(status & ISC_STATUS_MODE))
+	{
+		/* we have left isc mode */
+		str9xpec_info->isc_enable = 0;
+		DEBUG("ISC_MODE Disabled");
+	}
+	
+	return ERROR_OK;
+}
+
+int str9xpec_read_config(struct flash_bank_s *bank)
+{
+	scan_field_t field;
+	u8 status;
+	u32 chain_pos;
+		
+	str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
+	
+	chain_pos = str9xpec_info->chain_pos;
+	
+	DEBUG("ISC_CONFIGURATION");
+	
+	/* execute ISC_CONFIGURATION command */
+	str9xpec_set_instr(chain_pos, ISC_CONFIGURATION, TAP_PI);
+	
+	field.device = chain_pos;
+	field.num_bits = 64;
+	field.out_value = NULL;
+	field.out_mask = NULL;
+	field.in_value = str9xpec_info->options;
+	field.in_check_value = NULL;
+	field.in_check_mask = NULL;
+	field.in_handler = NULL;
+	field.in_handler_priv = NULL;
+	
+	jtag_add_dr_scan(1, &field, TAP_RTI);
+	jtag_execute_queue();
+	
+	status = str9xpec_isc_status(chain_pos);
+	
+	return status;
+}
+
+int str9xpec_build_block_list(struct flash_bank_s *bank)
+{
+	str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
+	
+	int i;
+	int num_sectors = 0, b0_sectors = 0;
+		
+	switch (bank->size)
+	{
+		case (256 * 1024):
+			b0_sectors = 4;
+			break;
+		case (512 * 1024):
+			b0_sectors = 8;
+			break;
+		default:
+			ERROR("BUG: unknown bank->size encountered");
+			exit(-1);
+	}
+	
+	/* include bank 1 sectors */
+	num_sectors = b0_sectors + 4;
+	bank->size += (32 * 1024);
+	
+	bank->num_sectors = num_sectors;
+	bank->sectors = malloc(sizeof(flash_sector_t) * num_sectors);
+	str9xpec_info->sector_bits = malloc(sizeof(u32) * num_sectors);
+	
+	num_sectors = 0;
+	
+	for (i = 0; i < b0_sectors; i++)
+	{
+		bank->sectors[num_sectors].offset = mem_layout_str9pec[i].sector_start;
+		bank->sectors[num_sectors].size = mem_layout_str9pec[i].sector_size;
+		bank->sectors[num_sectors].is_erased = -1;
+		bank->sectors[num_sectors].is_protected = 1;
+		str9xpec_info->sector_bits[num_sectors++] = mem_layout_str9pec[i].sector_bit;
+	}
+	
+	for (i = 8; i < 12; i++)
+	{
+		bank->sectors[num_sectors].offset = mem_layout_str9pec[i].sector_start;
+		bank->sectors[num_sectors].size = mem_layout_str9pec[i].sector_size;
+		bank->sectors[num_sectors].is_erased = -1;
+		bank->sectors[num_sectors].is_protected = 1;
+		str9xpec_info->sector_bits[num_sectors++] = mem_layout_str9pec[i].sector_bit;
+	}
+	
+	return ERROR_OK;
+}
+
+/* flash bank str9x <base> <size> 0 0 <target#>
+ */
+int str9xpec_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank)
+{
+	str9xpec_flash_controller_t *str9xpec_info;
+	armv4_5_common_t *armv4_5 = NULL;
+	arm7_9_common_t *arm7_9 = NULL;
+	arm_jtag_t *jtag_info = NULL;
+	
+	if (argc < 6)
+	{
+		WARNING("incomplete flash_bank str9x configuration");
+		return ERROR_FLASH_BANK_INVALID;
+	}
+	
+	str9xpec_info = malloc(sizeof(str9xpec_flash_controller_t));
+	bank->driver_priv = str9xpec_info;
+	
+	if (bank->base != 0x00000000)
+	{
+		WARNING("overriding flash base address for STR91x device with 0x00000000");
+		bank->base = 0x00000000;
+	}
+
+	/* find out jtag position of flash controller
+	 * it is always after the arm966 core */
+	
+	armv4_5 = bank->target->arch_info;
+	arm7_9 = armv4_5->arch_info;
+	jtag_info = &arm7_9->jtag_info;
+	
+	str9xpec_info->chain_pos = (jtag_info->chain_pos - 1);
+	str9xpec_info->isc_enable = 0;
+	str9xpec_info->devarm = NULL;
+	
+	str9xpec_build_block_list(bank);
+	
+	/* clear option byte register */
+	buf_set_u32(str9xpec_info->options, 0, 64, 0);
+	
+	return ERROR_OK;
+}
+
+int str9xpec_blank_check(struct flash_bank_s *bank, int first, int last)
+{
+	scan_field_t field;
+	u8 status;
+	u32 chain_pos;
+	int i;
+	u8 *buffer = NULL;
+		
+	str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
+	
+	chain_pos = str9xpec_info->chain_pos;
+	
+	if (!str9xpec_info->isc_enable) {
+		str9xpec_isc_enable( bank );
+	}
+	
+	if (!str9xpec_info->isc_enable) {
+		return ERROR_FLASH_OPERATION_FAILED;
+	}
+	
+	buffer = calloc(CEIL(64, 8), 1);
+
+	DEBUG("blank check: first_bank: %i, last_bank: %i", first, last);
+	
+	for (i = first; i <= last; i++) {
+		buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1);
+	}
+	
+	/* execute ISC_BLANK_CHECK command */
+	str9xpec_set_instr(chain_pos, ISC_BLANK_CHECK, TAP_PI);
+	
+	field.device = chain_pos;
+	field.num_bits = 64;
+	field.out_value = buffer;
+	field.out_mask = NULL;
+	field.in_value = NULL;
+	field.in_check_value = NULL;
+	field.in_check_mask = NULL;
+	field.in_handler = NULL;
+	field.in_handler_priv = NULL;
+	
+	jtag_add_dr_scan(1, &field, TAP_RTI);
+	jtag_add_sleep(40000);
+	
+	/* read blank check result */
+	field.device = chain_pos;
+	field.num_bits = 64;
+	field.out_value = NULL;
+	field.out_mask = NULL;
+	field.in_value = buffer;
+	field.in_check_value = NULL;
+	field.in_check_mask = NULL;
+	field.in_handler = NULL;
+	field.in_handler_priv = NULL;
+	
+	jtag_add_dr_scan(1, &field, TAP_PI);
+	jtag_execute_queue();
+	
+	status = str9xpec_isc_status(chain_pos);
+	
+	for (i = first; i <= last; i++)
+	{
+		if (buf_get_u32(buffer, str9xpec_info->sector_bits[i], 1))
+			bank->sectors[i].is_erased = 0;
+		else
+			bank->sectors[i].is_erased = 1;
+	}
+	
+	free(buffer);
+	
+	str9xpec_isc_disable(bank);
+	
+	if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
+		return ERROR_FLASH_OPERATION_FAILED; 
+	return ERROR_OK;
+}
+
+int str9xpec_protect_check(struct flash_bank_s *bank)
+{
+	u8 status;
+	int i;
+		
+	str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
+	
+	status = str9xpec_read_config(bank);
+	
+	for (i = 0; i < bank->num_sectors; i++)
+	{
+		if (buf_get_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1))
+			bank->sectors[i].is_protected = 1;
+		else
+			bank->sectors[i].is_protected = 0;
+	}
+	
+	if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
+		return ERROR_FLASH_OPERATION_FAILED;
+	return ERROR_OK;
+}
+
+int str9xpec_erase_area(struct flash_bank_s *bank, int first, int last)
+{
+	scan_field_t field;
+	u8 status;
+	u32 chain_pos;
+	int i;
+	u8 *buffer = NULL;
+	
+	str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
+	
+	chain_pos = str9xpec_info->chain_pos;
+	
+	if (!str9xpec_info->isc_enable) {
+		str9xpec_isc_enable( bank );
+	}
+	
+	if (!str9xpec_info->isc_enable) {
+		return ISC_STATUS_ERROR;
+	}
+	
+	buffer = calloc(CEIL(64, 8), 1);
+	
+	DEBUG("erase: first_bank: %i, last_bank: %i", first, last);
+	
+	/* last bank: 0xFF signals a full erase (unlock complete device) */
+	/* last bank: 0xFE signals a option byte erase */
+	if (last == 0xFF)
+	{
+		for (i = 0; i < 64; i++) {
+			buf_set_u32(buffer, i, 1, 1);
+		}	
+	}
+	else if (last == 0xFE)
+	{
+		buf_set_u32(buffer, 49, 1, 1);
+	}
+	else
+	{	
+		for (i = first; i <= last; i++) {
+			buf_set_u32(buffer, str9xpec_info->sector_bits[i], 1, 1);
+		}
+	}
+	
+	DEBUG("ISC_ERASE");
+	
+	/* execute ISC_ERASE command */
+	str9xpec_set_instr(chain_pos, ISC_ERASE, TAP_PI);
+	
+	field.device = chain_pos;
+	field.num_bits = 64;
+	field.out_value = buffer;
+	field.out_mask = NULL;
+	field.in_value = NULL;
+	field.in_check_value = NULL;
+	field.in_check_mask = NULL;
+	field.in_handler = NULL;
+	field.in_handler_priv = NULL;
+	
+	jtag_add_dr_scan(1, &field, TAP_RTI);
+	jtag_execute_queue();
+	
+	jtag_add_sleep(10);
+	
+	/* wait for erase completion */
+	while (!((status = str9xpec_isc_status(chain_pos)) & ISC_STATUS_BUSY)) {
+		usleep(1000);
+	}
+	
+	free(buffer);
+	
+	str9xpec_isc_disable(bank);
+	
+	return status;
+}
+
+int str9xpec_erase(struct flash_bank_s *bank, int first, int last)
+{
+	int status;
+	
+	status = str9xpec_erase_area(bank, first, last);
+	
+	if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
+		return ERROR_FLASH_OPERATION_FAILED;
+	
+	return ERROR_OK;
+}
+
+int str9xpec_lock_device(struct flash_bank_s *bank)
+{
+	scan_field_t field;
+	u8 status;
+	u32 chain_pos;
+	str9xpec_flash_controller_t *str9xpec_info = NULL;
+	
+	str9xpec_info = bank->driver_priv;
+	chain_pos = str9xpec_info->chain_pos;
+	
+	if (!str9xpec_info->isc_enable) {
+		str9xpec_isc_enable( bank );
+	}
+	
+	if (!str9xpec_info->isc_enable) {
+		return ISC_STATUS_ERROR;
+	}
+	
+	/* set security address */
+	str9xpec_set_address(bank, 0x80);
+	
+	/* execute ISC_PROGRAM command */
+	str9xpec_set_instr(chain_pos, ISC_PROGRAM_SECURITY, TAP_RTI);
+	
+	str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI);
+	
+	do {
+		field.device = chain_pos;
+		field.num_bits = 8;
+		field.out_value = NULL;
+		field.out_mask = NULL;
+		field.in_value = &status;
+		field.in_check_value = NULL;
+		field.in_check_mask = NULL;
+		field.in_handler = NULL;
+		field.in_handler_priv = NULL;
+		
+		jtag_add_dr_scan(1, &field, -1);
+		jtag_execute_queue();
+		
+	} while(!(status & ISC_STATUS_BUSY));
+	
+	str9xpec_isc_disable(bank);
+	
+	return status;
+}
+
+int str9xpec_unlock_device(struct flash_bank_s *bank)
+{
+	u8 status;
+	
+	status = str9xpec_erase_area(bank, 0, 255);
+	
+	return status;
+}
+
+int str9xpec_protect(struct flash_bank_s *bank, int set, int first, int last)
+{
+	u8 status;
+	int i;
+	
+	str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
+	
+	status = str9xpec_read_config(bank);
+	
+	if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
+		return ERROR_FLASH_OPERATION_FAILED;
+
+	DEBUG("protect: first_bank: %i, last_bank: %i", first, last);
+	
+	/* last bank: 0xFF signals a full device protect */
+	if (last == 0xFF)
+	{
+		if( set )
+		{
+			status = str9xpec_lock_device(bank);
+		}
+		else
+		{
+			/* perform full erase to unlock device */
+			status = str9xpec_unlock_device(bank);
+		}
+	}
+	else
+	{	
+		for (i = first; i <= last; i++)
+		{
+			if( set )
+				buf_set_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1, 1);
+			else
+				buf_set_u32(str9xpec_info->options, str9xpec_info->sector_bits[i], 1, 0);
+		}
+		
+		status = str9xpec_write_options(bank);
+	}
+	
+	if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
+		return ERROR_FLASH_OPERATION_FAILED;
+	
+	return ERROR_OK;
+}
+
+int str9xpec_set_address(struct flash_bank_s *bank, u8 sector)
+{
+	u32 chain_pos;
+	scan_field_t field;
+	str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
+	
+	chain_pos = str9xpec_info->chain_pos;
+	
+	/* set flash controller address */
+	str9xpec_set_instr(chain_pos, ISC_ADDRESS_SHIFT, TAP_PI);
+	
+	field.device = chain_pos;
+	field.num_bits = 8;
+	field.out_value = &sector;
+	field.out_mask = NULL;
+	field.in_value = NULL;
+	field.in_check_value = NULL;
+	field.in_check_mask = NULL;
+	field.in_handler = NULL;
+	field.in_handler_priv = NULL;
+	
+	jtag_add_dr_scan(1, &field, -1);
+		
+	return ERROR_OK;
+}
+
+int str9xpec_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count)
+{
+	str9xpec_flash_controller_t *str9xpec_info = bank->driver_priv;
+	u32 dwords_remaining = (count / 8);
+	u32 bytes_remaining = (count & 0x00000007);
+	u32 bytes_written = 0;
+	u8 status;
+	u32 check_address = offset;
+	u32 chain_pos;
+	scan_field_t field;
+	u8 *scanbuf;
+	int i;
+	u32 first_sector = 0;
+	u32 last_sector = 0;
+	
+	chain_pos = str9xpec_info->chain_pos;
+	
+	if (!str9xpec_info->isc_enable) {
+		str9xpec_isc_enable(bank);
+	}
+	
+	if (!str9xpec_info->isc_enable) {
+		return ERROR_FLASH_OPERATION_FAILED;
+	}
+	
+	if (offset & 0x7)
+	{
+		WARNING("offset 0x%x breaks required 8-byte alignment", offset);
+		return ERROR_FLASH_DST_BREAKS_ALIGNMENT;
+	}
+	
+	for (i = 0; i < bank->num_sectors; i++)
+	{
+		u32 sec_start = bank->sectors[i].offset;
+		u32 sec_end = sec_start + bank->sectors[i].size;
+		
+		/* check if destination falls within the current sector */
+		if ((check_address >= sec_start) && (check_address < sec_end))
+		{
+			/* check if destination ends in the current sector */
+			if (offset + count < sec_end)
+				check_address = offset + count;
+			else
+				check_address = sec_end;
+		}
+		
+		if ((offset >= sec_start) && (offset < sec_end)){
+			first_sector = i;
+		}
+		
+		if ((offset + count >= sec_start) && (offset + count < sec_end)){
+			last_sector = i;
+		}
+	}
+	
+	if (check_address != offset + count)
+		return ERROR_FLASH_DST_OUT_OF_BANK;
+
+	DEBUG("first_sector: %i, last_sector: %i", first_sector, last_sector);
+	
+	scanbuf = calloc(CEIL(64, 8), 1);
+	
+	DEBUG("ISC_PROGRAM");
+	
+	for (i = first_sector; i <= last_sector; i++)
+	{
+		str9xpec_set_address(bank, str9xpec_info->sector_bits[i]);
+		
+		dwords_remaining = dwords_remaining < (bank->sectors[i].size/8) ? dwords_remaining : (bank->sectors[i].size/8);
+
+		while (dwords_remaining > 0)
+		{	
+			str9xpec_set_instr(chain_pos, ISC_PROGRAM, TAP_PI);
+			
+			field.device = chain_pos;
+			field.num_bits = 64;
+			field.out_value = (buffer + bytes_written);
+			field.out_mask = NULL;
+			field.in_value = NULL;
+			field.in_check_value = NULL;
+			field.in_check_mask = NULL;
+			field.in_handler = NULL;
+			field.in_handler_priv = NULL;
+			
+			jtag_add_dr_scan(1, &field, TAP_RTI);
+			
+			/* small delay before polling */
+			jtag_add_sleep(50);
+			
+			str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI);
+			
+			do {
+				field.device = chain_pos;
+				field.num_bits = 8;
+				field.out_value = NULL;
+				field.out_mask = NULL;
+				field.in_value = scanbuf;
+				field.in_check_value = NULL;
+				field.in_check_mask = NULL;
+				field.in_handler = NULL;
+				field.in_handler_priv = NULL;
+				
+				jtag_add_dr_scan(1, &field, -1);
+				jtag_execute_queue();
+				
+				status = buf_get_u32(scanbuf, 0, 8);
+				
+			} while(!(status & ISC_STATUS_BUSY));
+			
+			if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
+				return ERROR_FLASH_OPERATION_FAILED;
+			
+			//if ((status & ISC_STATUS_INT_ERROR) != STR9XPEC_ISC_INTFAIL)
+			//	return ERROR_FLASH_OPERATION_FAILED;
+		
+			dwords_remaining--;
+			bytes_written += 8;
+		}
+	}
+	
+	if (bytes_remaining)
+	{
+		u8 last_dword[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+		int i = 0;
+				
+		while(bytes_remaining > 0)
+		{
+			last_dword[i++] = *(buffer + bytes_written); 
+			bytes_remaining--;
+			bytes_written++;
+		}
+		
+		str9xpec_set_instr(chain_pos, ISC_PROGRAM, TAP_PI);
+		
+		field.device = chain_pos;
+		field.num_bits = 64;
+		field.out_value = last_dword;
+		field.out_mask = NULL;
+		field.in_value = NULL;
+		field.in_check_value = NULL;
+		field.in_check_mask = NULL;
+		field.in_handler = NULL;
+		field.in_handler_priv = NULL;
+		
+		jtag_add_dr_scan(1, &field, TAP_RTI);
+		
+		/* small delay before polling */
+		jtag_add_sleep(50);
+		
+		str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI);
+		
+		do {
+			field.device = chain_pos;
+			field.num_bits = 8;
+			field.out_value = NULL;
+			field.out_mask = NULL;
+			field.in_value = scanbuf;
+			field.in_check_value = NULL;
+			field.in_check_mask = NULL;
+			field.in_handler = NULL;
+			field.in_handler_priv = NULL;
+			
+			jtag_add_dr_scan(1, &field, -1);
+			jtag_execute_queue();
+			
+			status = buf_get_u32(scanbuf, 0, 8);
+			
+		} while(!(status & ISC_STATUS_BUSY));
+		
+		if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
+			return ERROR_FLASH_OPERATION_FAILED;
+		
+		//if ((status & ISC_STATUS_INT_ERROR) != STR9XPEC_ISC_INTFAIL)
+		//	return ERROR_FLASH_OPERATION_FAILED;
+	}
+
+	free(scanbuf);
+
+	str9xpec_isc_disable(bank);
+				
+	return ERROR_OK;
+}
+
+int str9xpec_probe(struct flash_bank_s *bank)
+{
+	return ERROR_OK;
+}
+
+int str9xpec_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	flash_bank_t *bank;
+	scan_field_t field;
+	u8 *buffer = NULL;
+	u32 chain_pos;
+	u32 idcode;
+	str9xpec_flash_controller_t *str9xpec_info = NULL;
+
+	if (argc < 1)
+	{
+		return ERROR_COMMAND_SYNTAX_ERROR;
+	}
+	
+	bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
+	if (!bank)
+	{
+		command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
+		return ERROR_OK;
+	}
+	
+	str9xpec_info = bank->driver_priv;
+	chain_pos = str9xpec_info->chain_pos;
+	
+	buffer = calloc(CEIL(32, 8), 1);
+	
+	str9xpec_set_instr(chain_pos, ISC_IDCODE, TAP_PI);
+	
+	field.device = chain_pos;
+	field.num_bits = 32;
+	field.out_value = NULL;
+	field.out_mask = NULL;
+	field.in_value = buffer;
+	field.in_check_value = NULL;
+	field.in_check_mask = NULL;
+	field.in_handler = NULL;
+	field.in_handler_priv = NULL;
+	
+	jtag_add_dr_scan(1, &field, TAP_RTI);
+	jtag_execute_queue();
+	
+	idcode = buf_get_u32(buffer, 0, 32);
+	
+	command_print(cmd_ctx, "str9xpec part id: 0x%8.8x", idcode);
+	
+	free(buffer);
+	
+	return ERROR_OK;
+}
+
+int str9xpec_erase_check(struct flash_bank_s *bank)
+{
+	return str9xpec_blank_check(bank, 0, bank->num_sectors - 1);
+}
+
+int str9xpec_info(struct flash_bank_s *bank, char *buf, int buf_size)
+{
+	snprintf(buf, buf_size, "str9xpec flash driver info" );
+	return ERROR_OK;
+}
+
+int str9xpec_handle_flash_options_read_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	flash_bank_t *bank;
+	u8 status;
+	str9xpec_flash_controller_t *str9xpec_info = NULL;
+	
+	if (argc < 1)
+	{
+		command_print(cmd_ctx, "str9xpec options_read <bank>");
+		return ERROR_OK;	
+	}
+	
+	bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
+	if (!bank)
+	{
+		command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
+		return ERROR_OK;
+	}
+	
+	str9xpec_info = bank->driver_priv;
+	
+	status = str9xpec_read_config(bank);
+	
+	if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
+		return ERROR_FLASH_OPERATION_FAILED;
+	
+	/* boot bank */
+	if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1))
+		command_print(cmd_ctx, "CS Map: bank1");
+	else
+		command_print(cmd_ctx, "CS Map: bank0");
+	
+	/* OTP lock */
+	if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_OTPBIT, 1))
+		command_print(cmd_ctx, "OTP Lock: OTP Locked");
+	else
+		command_print(cmd_ctx, "OTP Lock: OTP Unlocked");
+	
+	/* LVD Threshold */
+	if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1))
+		command_print(cmd_ctx, "LVD Threshold: 2.7v");
+	else
+		command_print(cmd_ctx, "LVD Threshold: 2.4v");
+	
+	/* LVD reset warning */
+	if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1))
+		command_print(cmd_ctx, "LVD Reset Warning: VDD or VDDQ Inputs");
+	else
+		command_print(cmd_ctx, "LVD Reset Warning: VDD Input Only");
+	
+	/* LVD reset select */
+	if (buf_get_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1))
+		command_print(cmd_ctx, "LVD Reset Selection: VDD or VDDQ Inputs");
+	else
+		command_print(cmd_ctx, "LVD Reset Selection: VDD Input Only");
+	
+	return ERROR_OK;
+}
+
+int str9xpec_write_options(struct flash_bank_s *bank)
+{
+	scan_field_t field;
+	u8 status;
+	u32 chain_pos;
+	str9xpec_flash_controller_t *str9xpec_info = NULL;
+	
+	str9xpec_info = bank->driver_priv;
+	chain_pos = str9xpec_info->chain_pos;
+	
+	/* erase config options first */
+	status = str9xpec_erase_area( bank, 0xFE, 0xFE );
+	
+	if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
+		return status; 
+	
+	if (!str9xpec_info->isc_enable) {
+		str9xpec_isc_enable( bank );
+	}
+	
+	if (!str9xpec_info->isc_enable) {
+		return ISC_STATUS_ERROR;
+	}
+	
+	/* according to data 64th bit has to be set */
+	buf_set_u32(str9xpec_info->options, 63, 1, 1);
+	
+	/* set option byte address */
+	str9xpec_set_address(bank, 0x50);
+	
+	/* execute ISC_PROGRAM command */
+	str9xpec_set_instr(chain_pos, ISC_PROGRAM, TAP_PI);
+		
+	field.device = chain_pos;
+	field.num_bits = 64;
+	field.out_value = str9xpec_info->options;
+	field.out_mask = NULL;
+	field.in_value = NULL;
+	field.in_check_value = NULL;
+	field.in_check_mask = NULL;
+	field.in_handler = NULL;
+	field.in_handler_priv = NULL;
+	
+	jtag_add_dr_scan(1, &field, TAP_RTI);
+	
+	/* small delay before polling */
+	jtag_add_sleep(50);
+	
+	str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_PI);
+	
+	do {
+		field.device = chain_pos;
+		field.num_bits = 8;
+		field.out_value = NULL;
+		field.out_mask = NULL;
+		field.in_value = &status;
+		field.in_check_value = NULL;
+		field.in_check_mask = NULL;
+		field.in_handler = NULL;
+		field.in_handler_priv = NULL;
+		
+		jtag_add_dr_scan(1, &field, -1);
+		jtag_execute_queue();
+		
+	} while(!(status & ISC_STATUS_BUSY));
+	
+	str9xpec_isc_disable(bank);
+	
+	return status;
+}
+
+int str9xpec_handle_flash_options_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	flash_bank_t *bank;
+	u8 status;
+	
+	if (argc < 1)
+	{
+		command_print(cmd_ctx, "str9xpec options_write <bank>");
+		return ERROR_OK;	
+	}
+	
+	bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
+	if (!bank)
+	{
+		command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
+		return ERROR_OK;
+	}
+	
+	status = str9xpec_write_options(bank);
+	
+	if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
+		return ERROR_FLASH_OPERATION_FAILED;
+	
+	return ERROR_OK;
+}
+
+int str9xpec_handle_flash_options_cmap_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	flash_bank_t *bank;
+	str9xpec_flash_controller_t *str9xpec_info = NULL;
+	
+	if (argc < 2)
+	{
+		command_print(cmd_ctx, "str9xpec options_cmap <bank> <bank0|bank1>");
+		return ERROR_OK;	
+	}
+	
+	bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
+	if (!bank)
+	{
+		command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
+		return ERROR_OK;
+	}
+	
+	str9xpec_info = bank->driver_priv;
+	
+	if (strcmp(args[1], "bank1") == 0)
+	{
+		buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 1);
+	}
+	else
+	{
+		buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_CSMAPBIT, 1, 0);
+	}
+	
+	return ERROR_OK;
+}
+
+int str9xpec_handle_flash_options_lvdthd_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	flash_bank_t *bank;
+	str9xpec_flash_controller_t *str9xpec_info = NULL;
+	
+	if (argc < 2)
+	{
+		command_print(cmd_ctx, "str9xpec options_lvdthd <bank> <2.4v|2.7v>");
+		return ERROR_OK;	
+	}
+	
+	bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
+	if (!bank)
+	{
+		command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
+		return ERROR_OK;
+	}
+	
+	str9xpec_info = bank->driver_priv;
+	
+	if (strcmp(args[1], "2.7v") == 0)
+	{
+		buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 1);
+	}
+	else
+	{
+		buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDTHRESBIT, 1, 0);
+	}
+	
+	return ERROR_OK;
+}
+
+int str9xpec_handle_flash_options_lvdsel_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	flash_bank_t *bank;
+	str9xpec_flash_controller_t *str9xpec_info = NULL;
+	
+	if (argc < 2)
+	{
+		command_print(cmd_ctx, "str9xpec options_lvdsel <bank> <vdd|vdd_vddq>");
+		return ERROR_OK;	
+	}
+	
+	bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
+	if (!bank)
+	{
+		command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
+		return ERROR_OK;
+	}
+	
+	str9xpec_info = bank->driver_priv;
+	
+	if (strcmp(args[1], "vdd_vddq") == 0)
+	{
+		buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 1);
+	}
+	else
+	{
+		buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDSELBIT, 1, 0);
+	}
+	
+	return ERROR_OK;
+}
+
+int str9xpec_handle_flash_options_lvdwarn_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	flash_bank_t *bank;
+	str9xpec_flash_controller_t *str9xpec_info = NULL;
+	
+	if (argc < 2)
+	{
+		command_print(cmd_ctx, "str9xpec options_lvdwarn <bank> <vdd|vdd_vddq>");
+		return ERROR_OK;	
+	}
+	
+	bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
+	if (!bank)
+	{
+		command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
+		return ERROR_OK;
+	}
+	
+	str9xpec_info = bank->driver_priv;
+	
+	if (strcmp(args[1], "vdd_vddq") == 0)
+	{
+		buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 1);
+	}
+	else
+	{
+		buf_set_u32(str9xpec_info->options, STR9XPEC_OPT_LVDWARNBIT, 1, 0);
+	}
+	
+	return ERROR_OK;
+}
+
+int str9xpec_handle_flash_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	u8 status;
+	flash_bank_t *bank;
+	
+	if (argc < 1)
+	{
+		command_print(cmd_ctx, "str9xpec lock <bank>");
+		return ERROR_OK;	
+	}
+	
+	bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
+	if (!bank)
+	{
+		command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
+		return ERROR_OK;
+	}
+	
+	status = str9xpec_lock_device(bank);
+	
+	if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
+		return ERROR_FLASH_OPERATION_FAILED;
+	
+	return ERROR_OK;
+}
+
+int str9xpec_handle_flash_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	u8 status;
+	flash_bank_t *bank;
+	
+	if (argc < 1)
+	{
+		command_print(cmd_ctx, "str9xpec unlock <bank>");
+		return ERROR_OK;	
+	}
+	
+	bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
+	if (!bank)
+	{
+		command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
+		return ERROR_OK;
+	}
+	
+	status = str9xpec_unlock_device(bank);
+	
+	if ((status & ISC_STATUS_ERROR) != STR9XPEC_ISC_SUCCESS)
+		return ERROR_FLASH_OPERATION_FAILED;
+	
+	return ERROR_OK;
+}
+
+int str9xpec_handle_flash_enable_turbo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	flash_bank_t *bank;
+	u32 chain_pos;
+	jtag_device_t* dev0;
+	jtag_device_t* dev2;
+	str9xpec_flash_controller_t *str9xpec_info = NULL;
+	
+	if (argc < 1)
+	{
+		command_print(cmd_ctx, "str9xpec enable_turbo <bank>");
+		return ERROR_OK;	
+	}
+	
+	bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
+	if (!bank)
+	{
+		command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
+		return ERROR_OK;
+	}
+	
+	str9xpec_info = bank->driver_priv;
+	
+	chain_pos = str9xpec_info->chain_pos;
+	
+	/* remove arm core from chain - enter turbo mode */
+	
+	str9xpec_set_instr(chain_pos+2, 0xD, TAP_RTI);
+	jtag_execute_queue();
+	
+	/* modify scan chain - str9 core has been removed */
+	dev0 = jtag_get_device(chain_pos);
+	str9xpec_info->devarm = jtag_get_device(chain_pos+1);
+	dev2 = jtag_get_device(chain_pos+2);
+	dev0->next = dev2;
+	jtag_num_devices--;
+	
+	return ERROR_OK;
+}
+
+int str9xpec_handle_flash_disable_turbo_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	flash_bank_t *bank;
+	u32 chain_pos;
+	jtag_device_t* dev0;
+	str9xpec_flash_controller_t *str9xpec_info = NULL;
+	
+	if (argc < 1)
+	{
+		command_print(cmd_ctx, "str9xpec disable_turbo <bank>");
+		return ERROR_OK;	
+	}
+	
+	bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
+	if (!bank)
+	{
+		command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]);
+		return ERROR_OK;
+	}
+	
+	str9xpec_info = bank->driver_priv;
+	
+	chain_pos = str9xpec_info->chain_pos;
+	
+	dev0 = jtag_get_device(chain_pos);
+	
+	/* exit turbo mode via TLR */
+	str9xpec_set_instr(chain_pos, ISC_NOOP, TAP_TLR);
+	jtag_execute_queue();
+	
+	/* restore previous scan chain */
+	if( str9xpec_info->devarm ) {
+		dev0->next = str9xpec_info->devarm;
+		jtag_num_devices++;
+		str9xpec_info->devarm = NULL;
+	}
+	
+	return ERROR_OK;
+}
diff --git a/src/jtag/jtag.c b/src/jtag/jtag.c
index c4015118ca96f2543d578b790a56993518eee24e..605c34cf56c90905f3dfe48f7ff2c57550e27415 100644
--- a/src/jtag/jtag.c
+++ b/src/jtag/jtag.c
@@ -1,1836 +1,1837 @@
-/***************************************************************************
- *   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.             *
- ***************************************************************************/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "replacements.h"
-
-#include "jtag.h"
-
-#include "command.h"
-#include "log.h"
-#include "interpreter.h"
-
-#include "stdlib.h"
-#include "string.h"
-#include <unistd.h>
-
-char* tap_state_strings[16] =
-{
-	"tlr", 
-	"sds", "cd", "sd", "e1d", "pd", "e2d", "ud",
-	"rti",
-	"sis", "ci", "si", "e1i", "pi", "e2i", "ui"
-};
-
-typedef struct cmd_queue_page_s
-{
-	void *address;
-	size_t used;
-	struct cmd_queue_page_s *next;
-} cmd_queue_page_t;
-
-#define CMD_QUEUE_PAGE_SIZE (1024 * 1024)
-static cmd_queue_page_t *cmd_queue_pages = NULL;
-
-/* tap_move[i][j]: tap movement command to go from state i to state j
- * 0: Test-Logic-Reset
- * 1: Run-Test/Idle
- * 2: Shift-DR
- * 3: Pause-DR
- * 4: Shift-IR
- * 5: Pause-IR
- * 
- * SD->SD and SI->SI have to be caught in interface specific code
- */
-u8 tap_move[6][6] =
-{
-/*	  TLR   RTI   SD    PD    SI    PI             */
-	{0x7f, 0x00, 0x17, 0x0a, 0x1b, 0x16},	/* TLR */
-	{0x7f, 0x00, 0x25, 0x05, 0x2b, 0x0b},	/* RTI */
-	{0x7f, 0x31, 0x00, 0x01, 0x0f, 0x2f},	/* SD  */
-	{0x7f, 0x30, 0x20, 0x17, 0x1e, 0x2f},	/* PD  */
-	{0x7f, 0x31, 0x07, 0x17, 0x00, 0x01},	/* SI  */
-	{0x7f, 0x30, 0x1c, 0x17, 0x20, 0x2f}	/* PI  */
-};
-
-int tap_move_map[16] = {
-	0, -1, -1,  2, -1,  3, -1, -1,
-	1, -1, -1,  4, -1,  5, -1, -1
-};
-
-tap_transition_t tap_transitions[16] =
-{
-	{TAP_TLR, TAP_RTI},		/* TLR */
-	{TAP_SIS, TAP_CD},		/* SDS */
-	{TAP_E1D, TAP_SD},		/* CD  */
-	{TAP_E1D, TAP_SD},		/* SD  */
-	{TAP_UD,  TAP_PD}, 		/* E1D */
-	{TAP_E2D, TAP_PD},		/* PD  */
-	{TAP_UD,  TAP_SD},		/* E2D */
-	{TAP_SDS, TAP_RTI},		/* UD  */
-	{TAP_SDS, TAP_RTI},		/* RTI */
-	{TAP_TLR, TAP_CI},		/* SIS */
-	{TAP_E1I, TAP_SI},		/* CI  */
-	{TAP_E1I, TAP_SI},		/* SI  */
-	{TAP_UI,  TAP_PI}, 		/* E1I */
-	{TAP_E2I, TAP_PI},		/* PI  */
-	{TAP_UI,  TAP_SI},		/* E2I */
-	{TAP_SDS, TAP_RTI}		/* UI  */
-};
-
-char* jtag_event_strings[] =
-{
-	"SRST asserted",
-	"TRST asserted",
-	"SRST released",
-	"TRST released"
-};
-
-enum tap_state end_state = TAP_TLR;
-enum tap_state cur_state = TAP_TLR;
-int jtag_trst = 0;
-int jtag_srst = 0;
-
-jtag_command_t *jtag_command_queue = NULL;
-jtag_command_t **last_comand_pointer = &jtag_command_queue;
-jtag_device_t *jtag_devices = NULL;
-int jtag_num_devices = 0;
-int jtag_ir_scan_size = 0;
-enum reset_types jtag_reset_config = RESET_NONE;
-enum tap_state cmd_queue_end_state = TAP_TLR;
-enum tap_state cmd_queue_cur_state = TAP_TLR;
-
-int jtag_verify_capture_ir = 1;
-
-/* how long the OpenOCD should wait before attempting JTAG communication after reset lines deasserted (in ms) */
-int jtag_nsrst_delay = 0; /* default to no nSRST delay */
-int jtag_ntrst_delay = 0; /* default to no nTRST delay */ 
-
-/* maximum number of JTAG devices expected in the chain
- */
-#define JTAG_MAX_CHAIN_SIZE 20 
-
-/* callbacks to inform high-level handlers about JTAG state changes */
-jtag_event_callback_t *jtag_event_callbacks;
-
-/* jtag interfaces (parport, FTDI-USB, TI-USB, ...)
- */
-#if BUILD_PARPORT == 1
-	extern jtag_interface_t parport_interface;
-#endif
-
-#if BUILD_FT2232_FTD2XX == 1
-	extern jtag_interface_t ft2232_interface;
-#endif
-
-#if BUILD_FT2232_LIBFTDI == 1
-	extern jtag_interface_t ft2232_interface;
-#endif
-
-#if BUILD_AMTJTAGACCEL == 1
-	extern jtag_interface_t amt_jtagaccel_interface;
-#endif
-
-#if BUILD_EP93XX == 1
-	extern jtag_interface_t ep93xx_interface;
-#endif
-
-#if BUILD_AT91RM9200 == 1
-	extern jtag_interface_t at91rm9200_interface;
-#endif
-
-#if BUILD_GW16012 == 1
-	extern jtag_interface_t gw16012_interface;
-#endif
-
-#if BUILD_PRESTO_LIBFTDI == 1 || BUILD_PRESTO_FTD2XX == 1
-	extern jtag_interface_t presto_interface;
-#endif
-
-#if BUILD_USBPROG == 1
-	extern jtag_interface_t usbprog_interface;
-#endif
-
-jtag_interface_t *jtag_interfaces[] = {
-#if BUILD_PARPORT == 1
-	&parport_interface,
-#endif
-#if BUILD_FT2232_FTD2XX == 1
-	&ft2232_interface,
-#endif
-#if BUILD_FT2232_LIBFTDI == 1
-	&ft2232_interface,
-#endif
-#if BUILD_AMTJTAGACCEL == 1
-	&amt_jtagaccel_interface,
-#endif
-#if BUILD_EP93XX == 1
-	&ep93xx_interface,
-#endif
-#if BUILD_AT91RM9200 == 1
-	&at91rm9200_interface,
-#endif
-#if BUILD_GW16012 == 1
-	&gw16012_interface,
-#endif
-#if BUILD_PRESTO_LIBFTDI == 1 || BUILD_PRESTO_FTD2XX == 1
-	&presto_interface,
-#endif
-#if BUILD_USBPROG == 1
-	&usbprog_interface,
-#endif
-	NULL,
-};
-
-jtag_interface_t *jtag = NULL;
-
-/* configuration */
-char* jtag_interface = NULL;
-int jtag_speed = -1;
-
-
-/* forward declarations */
-int jtag_add_statemove(enum tap_state endstate);
-int jtag_add_pathmove(int num_states, enum tap_state *path);
-int jtag_add_runtest(int num_cycles, enum tap_state endstate);
-int jtag_add_reset(int trst, int srst);
-int jtag_add_end_state(enum tap_state endstate);
-int jtag_add_sleep(u32 us);
-int jtag_execute_queue(void);
-int jtag_cancel_queue(void);
-
-/* jtag commands */
-int handle_interface_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_jtag_speed_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_jtag_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_reset_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_jtag_nsrst_delay_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_jtag_ntrst_delay_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-
-int handle_scan_chain_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-
-int handle_endstate_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_jtag_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_runtest_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_statemove_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_irscan_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_drscan_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-
-int handle_verify_ircapture_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-
-int jtag_register_event_callback(int (*callback)(enum jtag_event event, void *priv), void *priv)
-{
-	jtag_event_callback_t **callbacks_p = &jtag_event_callbacks;
-	
-	if (callback == NULL)
-	{
-		return ERROR_INVALID_ARGUMENTS;
-	}
-	
-	if (*callbacks_p)
-	{
-		while ((*callbacks_p)->next)
-			callbacks_p = &((*callbacks_p)->next);
-		callbacks_p = &((*callbacks_p)->next);
-	}
-	
-	(*callbacks_p) = malloc(sizeof(jtag_event_callback_t));
-	(*callbacks_p)->callback = callback;
-	(*callbacks_p)->priv = priv;
-	(*callbacks_p)->next = NULL;
-	
-	return ERROR_OK;
-}
-
-int jtag_unregister_event_callback(int (*callback)(enum jtag_event event, void *priv))
-{
-	jtag_event_callback_t **callbacks_p = &jtag_event_callbacks;
-	
-	if (callback == NULL)
-	{
-		return ERROR_INVALID_ARGUMENTS;
-	}
-		
-	while (*callbacks_p)
-	{
-		jtag_event_callback_t **next = &((*callbacks_p)->next);
-		if ((*callbacks_p)->callback == callback)
-		{
-			free(*callbacks_p);
-			*callbacks_p = *next;
-		}
-		callbacks_p = next;
-	}
-	
-	return ERROR_OK;
-}
-
-int jtag_call_event_callbacks(enum jtag_event event)
-{
-	jtag_event_callback_t *callback = jtag_event_callbacks;
-	
-	DEBUG("jtag event: %s", jtag_event_strings[event]);
-	
-	while (callback)
-	{
-		callback->callback(event, callback->priv);
-		callback = callback->next;
-	}
-	
-	return ERROR_OK;
-}
-
-/* returns a pointer to the pointer of the last command in queue
- * this may be a pointer to the root pointer (jtag_command_queue)
- * or to the next member of the last but one command
- */
-jtag_command_t** jtag_get_last_command_p(void)
-{
-/*	jtag_command_t *cmd = jtag_command_queue;
-	
-	if (cmd)
-		while (cmd->next)
-			cmd = cmd->next;
-	else
-		return &jtag_command_queue;
-	
-	return &cmd->next;*/
-	
-	return last_comand_pointer;
-}
-
-/* returns a pointer to the n-th device in the scan chain */
-jtag_device_t* jtag_get_device(int num)
-{
-	jtag_device_t *device = jtag_devices;
-	int i = 0;
-
-	while (device)
-	{
-		if (num == i)
-			return device;
-		device = device->next;
-		i++;
-	}
-	
-	ERROR("jtag device number %d not defined", num);
-	exit(-1);
-}
-
-void* cmd_queue_alloc(size_t size)
-{
-	cmd_queue_page_t **p_page = &cmd_queue_pages;
-	int offset;
-
-	if (*p_page)
-	{
-		while ((*p_page)->next)
-			p_page = &((*p_page)->next);
-		if (CMD_QUEUE_PAGE_SIZE - (*p_page)->used < size)
-			p_page = &((*p_page)->next);
-	}
-
-	if (!*p_page)
-	{
-		*p_page = malloc(sizeof(cmd_queue_page_t));
-		(*p_page)->used = 0;
-		(*p_page)->address = malloc(CMD_QUEUE_PAGE_SIZE);
-		(*p_page)->next = NULL;
-	}
-
-	offset = (*p_page)->used;
-	(*p_page)->used += size;
-	
-	u8 *t=(u8 *)((*p_page)->address);
-	return t + offset;
-}
-
-void cmd_queue_free()
-{
-	cmd_queue_page_t *page = cmd_queue_pages;
-
-	while (page)
-	{
-		cmd_queue_page_t *last = page;
-		free(page->address);
-		page = page->next;
-		free(last);
-	}
-
-	cmd_queue_pages = NULL;
-}
-
-int jtag_add_ir_scan(int num_fields, scan_field_t *fields, enum tap_state state, void *dummy_anachronism)
-{
-	jtag_command_t **last_cmd;
-	jtag_device_t *device;
-	int i, j;
-	int scan_size = 0;
-
-	if (jtag_trst == 1)
-	{
-		WARNING("JTAG command queued, while TRST is low (TAP in reset)");
-		return ERROR_JTAG_TRST_ASSERTED;
-	}
-
-	last_cmd = jtag_get_last_command_p();
-	
-	/* allocate memory for a new list member */
-	*last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
-	(*last_cmd)->next = NULL;
-	last_comand_pointer = &((*last_cmd)->next);
-	(*last_cmd)->type = JTAG_SCAN;
-
-	/* allocate memory for ir scan command */
-	(*last_cmd)->cmd.scan = cmd_queue_alloc(sizeof(scan_command_t));
-	(*last_cmd)->cmd.scan->ir_scan = 1;
-	(*last_cmd)->cmd.scan->num_fields = jtag_num_devices;	/* one field per device */
-	(*last_cmd)->cmd.scan->fields = cmd_queue_alloc(jtag_num_devices * sizeof(scan_field_t));
-	(*last_cmd)->cmd.scan->end_state = state;
-		
-	if (state != -1)
-		cmd_queue_end_state = state;
-
-	if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)
-		jtag_call_event_callbacks(JTAG_TRST_RELEASED);
-	
-	if (cmd_queue_end_state == TAP_TLR)
-		jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
-	
-	cmd_queue_cur_state = cmd_queue_end_state;
-		
-	for (i = 0; i < jtag_num_devices; i++)
-	{
-		int found = 0;
-		device = jtag_get_device(i);
-		scan_size = device->ir_length;
-		(*last_cmd)->cmd.scan->fields[i].device = i;
-		(*last_cmd)->cmd.scan->fields[i].num_bits = scan_size;
-		(*last_cmd)->cmd.scan->fields[i].in_value = NULL;
-		(*last_cmd)->cmd.scan->fields[i].in_handler = NULL;	/* disable verification by default */
-
-		/* search the list */
-		for (j = 0; j < num_fields; j++)
-		{
-			if (i == fields[j].device)
-			{
-				found = 1;
-				(*last_cmd)->cmd.scan->fields[i].out_value = buf_cpy(fields[j].out_value, cmd_queue_alloc(CEIL(scan_size, 8)), scan_size);
-				(*last_cmd)->cmd.scan->fields[i].out_mask = buf_cpy(fields[j].out_mask, cmd_queue_alloc(CEIL(scan_size, 8)), scan_size);
-			
-				if (jtag_verify_capture_ir)
-				{
-					if (fields[j].in_handler==NULL)
-					{
-						jtag_set_check_value((*last_cmd)->cmd.scan->fields+i, device->expected, device->expected_mask, NULL);
-					} else
-					{
-						(*last_cmd)->cmd.scan->fields[i].in_handler = fields[j].in_handler;
-						(*last_cmd)->cmd.scan->fields[i].in_handler_priv = fields[j].in_handler_priv;
-						(*last_cmd)->cmd.scan->fields[i].in_check_value = device->expected; 
-						(*last_cmd)->cmd.scan->fields[i].in_check_mask = device->expected_mask;
-					}
-				}
-				
-				device->bypass = 0;
-				break;
-			}
-		}
-	
-		if (!found)
-		{
-			/* if a device isn't listed, set it to BYPASS */
-			(*last_cmd)->cmd.scan->fields[i].out_value = buf_set_ones(cmd_queue_alloc(CEIL(scan_size, 8)), scan_size);
-			(*last_cmd)->cmd.scan->fields[i].out_mask = NULL;
-			device->bypass = 1;
-		
-		}
-		
-		/* update device information */
-		buf_cpy((*last_cmd)->cmd.scan->fields[i].out_value, jtag_get_device(i)->cur_instr, scan_size);
-	}
-	
-	return ERROR_OK;
-}
-
-int jtag_add_plain_ir_scan(int num_fields, scan_field_t *fields, enum tap_state state, void *dummy_anachronism)
-{
-	jtag_command_t **last_cmd;
-	int i;
-
-	if (jtag_trst == 1)
-	{
-		WARNING("JTAG command queued, while TRST is low (TAP in reset)");
-		return ERROR_JTAG_TRST_ASSERTED;
-	}
-
-	last_cmd = jtag_get_last_command_p();
-	
-	/* allocate memory for a new list member */
-	*last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
-	(*last_cmd)->next = NULL;
-	last_comand_pointer = &((*last_cmd)->next);
-	(*last_cmd)->type = JTAG_SCAN;
-
-	/* allocate memory for ir scan command */
-	(*last_cmd)->cmd.scan = cmd_queue_alloc(sizeof(scan_command_t));
-	(*last_cmd)->cmd.scan->ir_scan = 1;
-	(*last_cmd)->cmd.scan->num_fields = num_fields;
-	(*last_cmd)->cmd.scan->fields = cmd_queue_alloc(num_fields * sizeof(scan_field_t));
-	(*last_cmd)->cmd.scan->end_state = state;
-
-	if (state != -1)
-		cmd_queue_end_state = state;
-
-	if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)
-		jtag_call_event_callbacks(JTAG_TRST_RELEASED);
-	
-	if (cmd_queue_end_state == TAP_TLR)
-		jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
-		
-	cmd_queue_cur_state = cmd_queue_end_state;
-	
-	for (i = 0; i < num_fields; i++)
-	{
-		int num_bits = fields[i].num_bits;
-		int num_bytes = CEIL(fields[i].num_bits, 8);
-		(*last_cmd)->cmd.scan->fields[i].device = fields[i].device;
-		(*last_cmd)->cmd.scan->fields[i].num_bits = num_bits;
-		(*last_cmd)->cmd.scan->fields[i].out_value = buf_cpy(fields[i].out_value, cmd_queue_alloc(num_bytes), num_bits);
-		(*last_cmd)->cmd.scan->fields[i].out_mask = buf_cpy(fields[i].out_mask, cmd_queue_alloc(num_bytes), num_bits);
-		(*last_cmd)->cmd.scan->fields[i].in_value = fields[i].in_value;
-		(*last_cmd)->cmd.scan->fields[i].in_check_value = fields[i].in_check_value;
-		(*last_cmd)->cmd.scan->fields[i].in_check_mask = fields[i].in_check_mask;
-		(*last_cmd)->cmd.scan->fields[i].in_handler = NULL;
-		(*last_cmd)->cmd.scan->fields[i].in_handler_priv = NULL;
-	}
-	return ERROR_OK;
-}
-
-int jtag_add_dr_scan(int num_fields, scan_field_t *fields, enum tap_state state, void *dummy_anachronism)
-{
-	int i, j;
-	int bypass_devices = 0;
-	int field_count = 0;
-	jtag_command_t **last_cmd = jtag_get_last_command_p();
-	jtag_device_t *device = jtag_devices;
-	int scan_size;
-
-	if (jtag_trst == 1)
-	{
-		WARNING("JTAG command queued, while TRST is low (TAP in reset)");
-		return ERROR_JTAG_TRST_ASSERTED;
-	}
-
-	/* count devices in bypass */
-	while (device)
-	{
-		if (device->bypass)
-			bypass_devices++;
-		device = device->next;
-	}
-	
-	/* allocate memory for a new list member */
-	*last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
-	last_comand_pointer = &((*last_cmd)->next);
-	(*last_cmd)->next = NULL;
-	(*last_cmd)->type = JTAG_SCAN;
-
-	/* allocate memory for dr scan command */
-	(*last_cmd)->cmd.scan = cmd_queue_alloc(sizeof(scan_command_t));
-	(*last_cmd)->cmd.scan->ir_scan = 0;
-	(*last_cmd)->cmd.scan->num_fields = num_fields + bypass_devices;
-	(*last_cmd)->cmd.scan->fields = cmd_queue_alloc((num_fields + bypass_devices) * sizeof(scan_field_t));
-	(*last_cmd)->cmd.scan->end_state = state;
-	
-	if (state != -1)
-		cmd_queue_end_state = state;
-
-	if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)
-		jtag_call_event_callbacks(JTAG_TRST_RELEASED);
-	
-	if (cmd_queue_end_state == TAP_TLR)
-		jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
-			
-	cmd_queue_cur_state = cmd_queue_end_state;
-	
-	for (i = 0; i < jtag_num_devices; i++)
-	{
-		int found = 0;
-		(*last_cmd)->cmd.scan->fields[field_count].device = i;
-	
-		for (j = 0; j < num_fields; j++)
-		{
-			if (i == fields[j].device)
-			{
-				found = 1;
-				scan_size = fields[j].num_bits;
-				(*last_cmd)->cmd.scan->fields[field_count].num_bits = scan_size;
-				(*last_cmd)->cmd.scan->fields[field_count].out_value = buf_cpy(fields[j].out_value, cmd_queue_alloc(CEIL(scan_size, 8)), scan_size);
-				(*last_cmd)->cmd.scan->fields[field_count].out_mask = buf_cpy(fields[j].out_mask, cmd_queue_alloc(CEIL(scan_size, 8)), scan_size);
-				(*last_cmd)->cmd.scan->fields[field_count].in_value = fields[j].in_value;
-				(*last_cmd)->cmd.scan->fields[field_count].in_check_value = fields[j].in_check_value;
-				(*last_cmd)->cmd.scan->fields[field_count].in_check_mask = fields[j].in_check_mask;
-				(*last_cmd)->cmd.scan->fields[field_count].in_handler = fields[j].in_handler;
-				(*last_cmd)->cmd.scan->fields[field_count++].in_handler_priv = fields[j].in_handler_priv;
-			}
-		}
-		if (!found)
-		{
-			/* if a device isn't listed, the BYPASS register should be selected */
-			if (!jtag_get_device(i)->bypass)
-			{
-				ERROR("BUG: no scan data for a device not in BYPASS");
-				exit(-1);
-			}
-	
-			/* program the scan field to 1 bit length, and ignore it's value */
-			(*last_cmd)->cmd.scan->fields[field_count].num_bits = 1;
-			(*last_cmd)->cmd.scan->fields[field_count].out_value = NULL;
-			(*last_cmd)->cmd.scan->fields[field_count].out_mask = NULL;
-			(*last_cmd)->cmd.scan->fields[field_count].in_value = NULL;
-			(*last_cmd)->cmd.scan->fields[field_count].in_check_value = NULL;
-			(*last_cmd)->cmd.scan->fields[field_count].in_check_mask = NULL;
-			(*last_cmd)->cmd.scan->fields[field_count].in_handler = NULL;
-			(*last_cmd)->cmd.scan->fields[field_count++].in_handler_priv = NULL;
-		}
-		else
-		{
-			/* if a device is listed, the BYPASS register must not be selected */
-			if (jtag_get_device(i)->bypass)
-			{
-				WARNING("scan data for a device in BYPASS");
-			}
-		}
-	}
-	return ERROR_OK;
-}
-
-int jtag_add_plain_dr_scan(int num_fields, scan_field_t *fields, enum tap_state state, void *dummy_anachronism)
-{
-	int i;
-	jtag_command_t **last_cmd = jtag_get_last_command_p();
-	
-	if (jtag_trst == 1)
-	{
-		WARNING("JTAG command queued, while TRST is low (TAP in reset)");
-		return ERROR_JTAG_TRST_ASSERTED;
-	}
-
-	/* allocate memory for a new list member */
-	*last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
-	last_comand_pointer = &((*last_cmd)->next);
-	(*last_cmd)->next = NULL;
-	(*last_cmd)->type = JTAG_SCAN;
-
-	/* allocate memory for scan command */
-	(*last_cmd)->cmd.scan = cmd_queue_alloc(sizeof(scan_command_t));
-	(*last_cmd)->cmd.scan->ir_scan = 0;
-	(*last_cmd)->cmd.scan->num_fields = num_fields;
-	(*last_cmd)->cmd.scan->fields = cmd_queue_alloc(num_fields * sizeof(scan_field_t));
-	(*last_cmd)->cmd.scan->end_state = state;
-		
-	if (state != -1)
-		cmd_queue_end_state = state;
-
-	if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)
-		jtag_call_event_callbacks(JTAG_TRST_RELEASED);
-	
-	if (cmd_queue_end_state == TAP_TLR)
-		jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
-			
-	cmd_queue_cur_state = cmd_queue_end_state;
-	
-	for (i = 0; i < num_fields; i++)
-	{
-		int num_bits = fields[i].num_bits;
-		int num_bytes = CEIL(fields[i].num_bits, 8);
-		(*last_cmd)->cmd.scan->fields[i].device = fields[i].device;
-		(*last_cmd)->cmd.scan->fields[i].num_bits = num_bits;
-		(*last_cmd)->cmd.scan->fields[i].out_value = buf_cpy(fields[i].out_value, cmd_queue_alloc(num_bytes), num_bits);
-		(*last_cmd)->cmd.scan->fields[i].out_mask = buf_cpy(fields[i].out_mask, cmd_queue_alloc(num_bytes), num_bits);
-		(*last_cmd)->cmd.scan->fields[i].in_value = fields[i].in_value;
-		(*last_cmd)->cmd.scan->fields[i].in_check_value = fields[i].in_check_value;
-		(*last_cmd)->cmd.scan->fields[i].in_check_mask = fields[i].in_check_mask;
-		(*last_cmd)->cmd.scan->fields[i].in_handler = fields[i].in_handler;
-		(*last_cmd)->cmd.scan->fields[i].in_handler_priv = fields[i].in_handler_priv;
-	}
-
-	return ERROR_OK;
-}
-int jtag_add_statemove(enum tap_state state)
-{
-	jtag_command_t **last_cmd = jtag_get_last_command_p();
-	
-	if (jtag_trst == 1)
-	{
-		WARNING("JTAG command queued, while TRST is low (TAP in reset)");
-		return ERROR_JTAG_TRST_ASSERTED;
-	}
-
-	/* allocate memory for a new list member */
-	*last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
-	last_comand_pointer = &((*last_cmd)->next);
-	(*last_cmd)->next = NULL;
-	(*last_cmd)->type = JTAG_STATEMOVE;
-
-	(*last_cmd)->cmd.statemove = cmd_queue_alloc(sizeof(statemove_command_t));
-	(*last_cmd)->cmd.statemove->end_state = state;
-	
-	if (state != -1)
-		cmd_queue_end_state = state;
-
-	if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)
-		jtag_call_event_callbacks(JTAG_TRST_RELEASED);
-	
-	if (cmd_queue_end_state == TAP_TLR)
-		jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
-			
-	cmd_queue_cur_state = cmd_queue_end_state;
-	
-	return ERROR_OK;
-}
-
-int jtag_add_pathmove(int num_states, enum tap_state *path)
-{
-	jtag_command_t **last_cmd = jtag_get_last_command_p();
-	int i;
-	
-	if (jtag_trst == 1)
-	{
-		WARNING("JTAG command queued, while TRST is low (TAP in reset)");
-		return ERROR_JTAG_TRST_ASSERTED;
-	}
-	
-	/* the last state has to be a stable state */
-	if (tap_move_map[path[num_states - 1]] == -1)
-	{
-		ERROR("TAP path doesn't finish in a stable state");
-		return ERROR_JTAG_NOT_IMPLEMENTED;
-	}
-	
-	/* allocate memory for a new list member */
-	*last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
-	last_comand_pointer = &((*last_cmd)->next);
-	(*last_cmd)->next = NULL;
-	(*last_cmd)->type = JTAG_PATHMOVE;
-
-	(*last_cmd)->cmd.pathmove = cmd_queue_alloc(sizeof(pathmove_command_t));
-	(*last_cmd)->cmd.pathmove->num_states = num_states;
-	(*last_cmd)->cmd.pathmove->path = cmd_queue_alloc(sizeof(enum tap_state) * num_states);
-	
-	for (i = 0; i < num_states; i++)
-		(*last_cmd)->cmd.pathmove->path[i] = path[i];
-
-	if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)
-		jtag_call_event_callbacks(JTAG_TRST_RELEASED);
-	
-	if (cmd_queue_end_state == TAP_TLR)
-		jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
-	
-	cmd_queue_cur_state = path[num_states - 1];
-	
-	return ERROR_OK;
-}
-
-int jtag_add_runtest(int num_cycles, enum tap_state state)
-{
-	jtag_command_t **last_cmd = jtag_get_last_command_p();
-	
-	if (jtag_trst == 1)
-	{
-		WARNING("JTAG command queued, while TRST is low (TAP in reset)");
-		return ERROR_JTAG_TRST_ASSERTED;
-	}
-
-	/* allocate memory for a new list member */
-	*last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
-	(*last_cmd)->next = NULL;
-	last_comand_pointer = &((*last_cmd)->next);
-	(*last_cmd)->type = JTAG_RUNTEST;
-
-	(*last_cmd)->cmd.runtest = cmd_queue_alloc(sizeof(runtest_command_t));
-	(*last_cmd)->cmd.runtest->num_cycles = num_cycles;
-	(*last_cmd)->cmd.runtest->end_state = state;
-	
-	if (state != -1)
-		cmd_queue_end_state = state;
-
-	if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)
-		jtag_call_event_callbacks(JTAG_TRST_RELEASED);
-	
-	if (cmd_queue_end_state == TAP_TLR)
-		jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
-			
-	cmd_queue_cur_state = cmd_queue_end_state;
-	
-	return ERROR_OK;
-}
-
-int jtag_add_reset(int req_trst, int req_srst)
-{
-	int trst_with_tms = 0;
-	
-	jtag_command_t **last_cmd = jtag_get_last_command_p();
-	
-	if (req_trst == -1)
-		req_trst = jtag_trst;
-	
-	if (req_srst == -1)
-		req_srst = jtag_srst;
-
-	/* Make sure that jtag_reset_config allows the requested reset */
-	/* if SRST pulls TRST, we can't fulfill srst == 1 with trst == 0 */
-	if (((jtag_reset_config & RESET_SRST_PULLS_TRST) && (req_srst == 1)) && (req_trst == 0))
-		return ERROR_JTAG_RESET_WOULD_ASSERT_TRST;
-		
-	/* if TRST pulls SRST, we reset with TAP T-L-R */
-	if (((jtag_reset_config & RESET_TRST_PULLS_SRST) && (req_trst == 1)) && (req_srst == 0))
-	{
-		req_trst = 0;
-		trst_with_tms = 1;
-	}
-	
-	if (req_srst && !(jtag_reset_config & RESET_HAS_SRST))
-	{
-		ERROR("requested nSRST assertion, but the current configuration doesn't support this");
-		return ERROR_JTAG_RESET_CANT_SRST;
-	}
-	
-	if (req_trst && !(jtag_reset_config & RESET_HAS_TRST))
-	{
-		req_trst = 0;
-		trst_with_tms = 1;
-	}
-	
-	/* allocate memory for a new list member */
-	*last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
-	(*last_cmd)->next = NULL;
-	last_comand_pointer = &((*last_cmd)->next);
-	(*last_cmd)->type = JTAG_RESET;
-
-	(*last_cmd)->cmd.reset = cmd_queue_alloc(sizeof(reset_command_t));
-	(*last_cmd)->cmd.reset->trst = req_trst;
-	(*last_cmd)->cmd.reset->srst = req_srst;
-
-	jtag_trst = req_trst;
-	jtag_srst = req_srst;
-
-	if (jtag_srst)
-	{
-		jtag_call_event_callbacks(JTAG_SRST_ASSERTED);
-	}
-	else
-	{
-		jtag_call_event_callbacks(JTAG_SRST_RELEASED);
-		if (jtag_nsrst_delay)
-			jtag_add_sleep(jtag_nsrst_delay * 1000);
-	}
-	
-	if (trst_with_tms)
-	{
-		last_cmd = &((*last_cmd)->next);
-		
-		/* allocate memory for a new list member */
-		*last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
-		(*last_cmd)->next = NULL;
-		last_comand_pointer = &((*last_cmd)->next);
-		(*last_cmd)->type = JTAG_STATEMOVE;
-
-		(*last_cmd)->cmd.statemove = cmd_queue_alloc(sizeof(statemove_command_t));
-		(*last_cmd)->cmd.statemove->end_state = TAP_TLR;
-		
-		jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
-		cmd_queue_cur_state = TAP_TLR;
-		cmd_queue_end_state = TAP_TLR;
-		
-		return ERROR_OK;
-	}
-	else
-	{
-		if (jtag_trst)
-		{
-			/* we just asserted nTRST, so we're now in Test-Logic-Reset,
-			 * and inform possible listeners about this
-			 */
-			cmd_queue_cur_state = TAP_TLR;
-			jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
-		}
-		else
-		{
-			/* the nTRST line got deasserted, so we're still in Test-Logic-Reset,
-			 * but we might want to add a delay to give the TAP time to settle
-			 */
-			if (jtag_ntrst_delay)
-				jtag_add_sleep(jtag_ntrst_delay * 1000);
-		}
-	}
-
-	return ERROR_OK;
-}
-
-int jtag_add_end_state(enum tap_state state)
-{
-	jtag_command_t **last_cmd = jtag_get_last_command_p();
-	
-	/* allocate memory for a new list member */
-	*last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
-	(*last_cmd)->next = NULL;
-	last_comand_pointer = &((*last_cmd)->next);
-	(*last_cmd)->type = JTAG_END_STATE;
-
-	(*last_cmd)->cmd.end_state = cmd_queue_alloc(sizeof(end_state_command_t));
-	(*last_cmd)->cmd.end_state->end_state = state;
-
-	if (state != -1)
-		cmd_queue_end_state = state;
-	
-	return ERROR_OK;
-}
-
-int jtag_add_sleep(u32 us)
-{
-	jtag_command_t **last_cmd = jtag_get_last_command_p();
-	
-	/* allocate memory for a new list member */
-	*last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
-	(*last_cmd)->next = NULL;
-	last_comand_pointer = &((*last_cmd)->next);
-	(*last_cmd)->type = JTAG_SLEEP;
-
-	(*last_cmd)->cmd.sleep = cmd_queue_alloc(sizeof(sleep_command_t));
-	(*last_cmd)->cmd.sleep->us = us;
-	
-	return ERROR_OK;
-}
-
-int jtag_scan_size(scan_command_t *cmd)
-{
-	int bit_count = 0;
-	int i;
-
-	/* count bits in scan command */
-	for (i = 0; i < cmd->num_fields; i++)
-	{
-		bit_count += cmd->fields[i].num_bits;
-	}
-
-	return bit_count;
-}
-
-int jtag_build_buffer(scan_command_t *cmd, u8 **buffer)
-{
-	int bit_count = 0;
-	int i;
-	
-	bit_count = jtag_scan_size(cmd);
-	*buffer = malloc(CEIL(bit_count, 8));
-	
-	bit_count = 0;
-
-	for (i = 0; i < cmd->num_fields; i++)
-	{
-		if (cmd->fields[i].out_value)
-		{
-#ifdef _DEBUG_JTAG_IO_
-			char* char_buf = buf_to_str(cmd->fields[i].out_value, (cmd->fields[i].num_bits > 64) ? 64 : cmd->fields[i].num_bits, 16);
-#endif
-			buf_set_buf(cmd->fields[i].out_value, 0, *buffer, bit_count, cmd->fields[i].num_bits);
-#ifdef _DEBUG_JTAG_IO_
-			DEBUG("fields[%i].out_value: 0x%s", i, char_buf);
-			free(char_buf);
-#endif
-		}
-		
-		bit_count += cmd->fields[i].num_bits;
-	}
-
-	return bit_count;
-
-}
-
-int jtag_read_buffer(u8 *buffer, scan_command_t *cmd)
-{
-	int i;
-	int bit_count = 0;
-	int retval;
-	
-	/* we return ERROR_OK, unless a check fails, or a handler reports a problem */
-	retval = ERROR_OK;
-	
-	for (i = 0; i < cmd->num_fields; i++)
-	{
-		/* if neither in_value nor in_handler
-		 * are specified we don't have to examine this field
-		 */
-		if (cmd->fields[i].in_value || cmd->fields[i].in_handler)
-		{
-			int num_bits = cmd->fields[i].num_bits;
-			u8 *captured = buf_set_buf(buffer, bit_count, malloc(CEIL(num_bits, 8)), 0, num_bits);
-			
-#ifdef _DEBUG_JTAG_IO_
-			char *char_buf;
-
-			char_buf = buf_to_str(captured, (num_bits > 64) ? 64 : num_bits, 16);
-			DEBUG("fields[%i].in_value: 0x%s", i, char_buf);
-			free(char_buf);
-#endif
-			
-			if (cmd->fields[i].in_value)
-			{
-				buf_cpy(captured, cmd->fields[i].in_value, num_bits);
-				
-				if (cmd->fields[i].in_handler)
-				{
-					if (cmd->fields[i].in_handler(cmd->fields[i].in_value, cmd->fields[i].in_handler_priv, cmd->fields+i) != ERROR_OK)
-					{
-						WARNING("in_handler reported a failed check");
-						retval = ERROR_JTAG_QUEUE_FAILED;
-					}
-				}
-			}
-			
-			/* no in_value specified, but a handler takes care of the scanned data */
-			if (cmd->fields[i].in_handler && (!cmd->fields[i].in_value))
-			{
-				if (cmd->fields[i].in_handler(captured, cmd->fields[i].in_handler_priv, cmd->fields+i) != ERROR_OK)
-				{
-					/* We're going to call the error:handler later, but if the in_handler
-					 * reported an error we report this failure upstream
-					 */
-					WARNING("in_handler reported a failed check");
-					retval = ERROR_JTAG_QUEUE_FAILED;
-				}
-			}
-
-			free(captured);
-		}
-		bit_count += cmd->fields[i].num_bits;
-	}
-
-	return retval;
-}
-
-int jtag_check_value(u8 *captured, void *priv, scan_field_t *field)
-{
-	int retval = ERROR_OK;
-	int num_bits = field->num_bits;
-	
-	int compare_failed = 0;
-	
-	if (field->in_check_mask)
-		compare_failed = buf_cmp_mask(captured, field->in_check_value, field->in_check_mask, num_bits);
-	else
-		compare_failed = buf_cmp(captured, field->in_check_value, num_bits);
-	
-	if (compare_failed)
-		{
-		/* An error handler could have caught the failing check
-		 * only report a problem when there wasn't a handler, or if the handler
-		 * acknowledged the error
-		 */ 
-		if (compare_failed)
-		{
-			char *captured_char = buf_to_str(captured, (num_bits > 64) ? 64 : num_bits, 16);
-			char *in_check_value_char = buf_to_str(field->in_check_value, (num_bits > 64) ? 64 : num_bits, 16);
-
-			if (field->in_check_mask)
-			{
-				char *in_check_mask_char;
-				in_check_mask_char = buf_to_str(field->in_check_mask, (num_bits > 64) ? 64 : num_bits, 16);
-				WARNING("value captured during scan didn't pass the requested check: captured: 0x%s check_value: 0x%s check_mask: 0x%s", captured_char, in_check_value_char, in_check_mask_char);
-				free(in_check_mask_char);
-			}
-			else
-			{
-				WARNING("value captured during scan didn't pass the requested check: captured: 0x%s check_value: 0x%s", captured_char, in_check_value_char);
-			}
-
-			free(captured_char);
-			free(in_check_value_char);
-			
-			retval = ERROR_JTAG_QUEUE_FAILED;
-		}
-		
-	}
-	return retval;
-}
-
-/* 
-  set up checking of this field using the in_handler. The values passed in must be valid until
-  after jtag_execute() has completed.
- */
-void jtag_set_check_value(scan_field_t *field, u8 *value, u8 *mask, error_handler_t *in_error_handler)
-{
-	if (value)
-		field->in_handler = jtag_check_value;
-	else
-		field->in_handler = NULL;	/* No check, e.g. embeddedice uses value==NULL to indicate no check */
-	field->in_handler_priv = NULL;	/* this will be filled in at the invocation site to point to the field duplicate */ 
-	field->in_check_value = value;
-	field->in_check_mask = mask;
-}
-
-enum scan_type jtag_scan_type(scan_command_t *cmd)
-{
-	int i;
-	int type = 0;
-	
-	for (i = 0; i < cmd->num_fields; i++)
-	{
-		if (cmd->fields[i].in_value || cmd->fields[i].in_handler)
-			type |= SCAN_IN;
-		if (cmd->fields[i].out_value)
-			type |= SCAN_OUT;
-	}
-
-	return type;
-}
-
-int jtag_execute_queue(void)
-{
-	int retval;
-
-	retval = jtag->execute_queue();
-	
-	cmd_queue_free();
-
-	jtag_command_queue = NULL;
-	last_comand_pointer = &jtag_command_queue;
-
-	return retval;
-}
-
-int jtag_reset_callback(enum jtag_event event, void *priv)
-{
-	jtag_device_t *device = priv;
-
-	DEBUG("-");
-	
-	if (event == JTAG_TRST_ASSERTED)
-	{
-		buf_set_ones(device->cur_instr, device->ir_length);
-		device->bypass = 1;
-	}
-	
-	return ERROR_OK;
-}
-
-void jtag_sleep(u32 us)
-{
-	usleep(us);
-}
-
-/* Try to examine chain layout according to IEEE 1149.1 §12
- */
-int jtag_examine_chain()
-{
-	jtag_device_t *device = jtag_devices;
-	scan_field_t field;
-	u8 idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4];
-	int i;
-	int bit_count;
-	int device_count = 0;
-	u8 zero_check = 0x0;
-	u8 one_check = 0xff;
-	
-	field.device = 0;
-	field.num_bits = sizeof(idcode_buffer) * 8;
-	field.out_value = idcode_buffer;
-	field.out_mask = NULL;
-	field.in_value = idcode_buffer;
-	field.in_check_value = NULL;
-	field.in_check_mask = NULL;
-	field.in_handler = NULL;
-	field.in_handler_priv = NULL;
-	
-	for (i = 0; i < JTAG_MAX_CHAIN_SIZE; i++)
-	{
-		buf_set_u32(idcode_buffer, i * 32, 32, 0x000000FF);
-	}
-	
-	jtag_add_plain_dr_scan(1, &field, TAP_TLR, NULL);
-	jtag_execute_queue();
-	
-	for (i = 0; i < JTAG_MAX_CHAIN_SIZE * 4; i++)
-	{
-		zero_check |= idcode_buffer[i];
-		one_check &= idcode_buffer[i];
-	}
-	
-	/* if there wasn't a single non-zero bit or if all bits were one, the scan isn't valid */
-	if ((zero_check == 0x00) || (one_check == 0xff))
-	{
-		ERROR("JTAG communication failure, check connection, JTAG interface, target power etc.");
-		return ERROR_JTAG_INIT_FAILED;
-	}
-	
-	for (bit_count = 0; bit_count < (JTAG_MAX_CHAIN_SIZE * 32) - 31;)
-	{
-		u32 idcode = buf_get_u32(idcode_buffer, bit_count, 32);
-		if ((idcode & 1) == 0)
-		{
-			/* LSB must not be 0, this indicates a device in bypass */
-			device_count++;
-			
-			bit_count += 1;
-		}
-		else
-		{
-			u32 manufacturer;
-			u32 part;
-			u32 version;
-			
-			if (idcode == 0x000000FF)
-			{
-				/* End of chain (invalid manufacturer ID) */
-				break;
-			}
-			
-			if (device)
-			{
-				device->idcode = idcode;
-				device = device->next;
-			}
-			device_count++;
-			
-			manufacturer = (idcode & 0xffe) >> 1;
-			part = (idcode & 0xffff000) >> 12;
-			version = (idcode & 0xf0000000) >> 28;
-
-			INFO("JTAG device found: 0x%8.8x (Manufacturer: 0x%3.3x, Part: 0x%4.4x, Version: 0x%1.1x)", 
-				idcode, manufacturer, part, version);
-			
-			bit_count += 32;
-		}
-	}
-	
-	/* see if number of discovered devices matches configuration */
-	if (device_count != jtag_num_devices)
-	{
-		ERROR("number of discovered devices in JTAG chain (%i) doesn't match configuration (%i)", 
-			device_count, jtag_num_devices);
-		ERROR("check the config file and ensure proper JTAG communication (connections, speed, ...)");
-		return ERROR_JTAG_INIT_FAILED;
-	}
-	
-	return ERROR_OK;
-}
-
-int jtag_validate_chain()
-{
-	jtag_device_t *device = jtag_devices;
-	int total_ir_length = 0;
-	u8 *ir_test = NULL;
-	scan_field_t field;
-	int chain_pos = 0;
-	
-	while (device)
-	{
-		total_ir_length += device->ir_length;
-		device = device->next;
-	}
-	
-	total_ir_length += 2;
-	ir_test = malloc(CEIL(total_ir_length, 8));
-	buf_set_ones(ir_test, total_ir_length);
-	
-	field.device = 0;
-	field.num_bits = total_ir_length;
-	field.out_value = ir_test;
-	field.out_mask = NULL;
-	field.in_value = ir_test;
-	field.in_check_value = NULL;
-	field.in_check_mask = NULL;
-	field.in_handler = NULL;
-	field.in_handler_priv = NULL;
-	
-	jtag_add_plain_ir_scan(1, &field, TAP_TLR, NULL);
-	jtag_execute_queue();
-	
-	device = jtag_devices;
-	while (device)
-	{
-		if (buf_get_u32(ir_test, chain_pos, 2) != 0x1)
-		{
-			char *cbuf = buf_to_str(ir_test, total_ir_length, 16);
-			ERROR("Error validating JTAG scan chain, IR mismatch, scan returned 0x%s", cbuf);
-			free(cbuf);
-			free(ir_test);
-			return ERROR_JTAG_INIT_FAILED;
-		}
-		chain_pos += device->ir_length;
-		device = device->next;
-	}
-	
-	if (buf_get_u32(ir_test, chain_pos, 2) != 0x3)
-	{
-		char *cbuf = buf_to_str(ir_test, total_ir_length, 16);
-		ERROR("Error validating JTAG scan chain, IR mismatch, scan returned 0x%s", cbuf);
-		free(cbuf);
-		free(ir_test);
-		return ERROR_JTAG_INIT_FAILED;
-	}
-	
-	free(ir_test);
-	
-	return ERROR_OK;
-}
-
-int jtag_register_commands(struct command_context_s *cmd_ctx)
-{
-	register_command(cmd_ctx, NULL, "interface", handle_interface_command,
-		COMMAND_CONFIG, NULL);
-	register_command(cmd_ctx, NULL, "jtag_speed", handle_jtag_speed_command,
-		COMMAND_ANY, "set jtag speed (if supported) <speed>");
-	register_command(cmd_ctx, NULL, "jtag_device", handle_jtag_device_command,
-		COMMAND_CONFIG, "jtag_device <ir_length> <ir_expected> <ir_mask>");
-	register_command(cmd_ctx, NULL, "reset_config", handle_reset_config_command,
-		COMMAND_CONFIG, NULL);
-	register_command(cmd_ctx, NULL, "jtag_nsrst_delay", handle_jtag_nsrst_delay_command,
-		COMMAND_CONFIG, NULL);
-	register_command(cmd_ctx, NULL, "jtag_ntrst_delay", handle_jtag_ntrst_delay_command,
-		COMMAND_CONFIG, NULL);
-		
-	register_command(cmd_ctx, NULL, "scan_chain", handle_scan_chain_command,
-		COMMAND_EXEC, "print current scan chain configuration");
-
-	register_command(cmd_ctx, NULL, "endstate", handle_endstate_command,
-		COMMAND_EXEC, "finish JTAG operations in <tap_state>");
-	register_command(cmd_ctx, NULL, "jtag_reset", handle_jtag_reset_command,
-		COMMAND_EXEC, "toggle reset lines <trst> <srst>");
-	register_command(cmd_ctx, NULL, "runtest", handle_runtest_command,
-		COMMAND_EXEC, "move to Run-Test/Idle, and execute <num_cycles>");
-	register_command(cmd_ctx, NULL, "statemove", handle_statemove_command,
-		COMMAND_EXEC, "move to current endstate or [tap_state]");
-	register_command(cmd_ctx, NULL, "irscan", handle_irscan_command,
-		COMMAND_EXEC, "execute IR scan <device> <instr> [dev2] [instr2] ...");
-	register_command(cmd_ctx, NULL, "drscan", handle_drscan_command,
-		COMMAND_EXEC, "execute DR scan <device> <var> [dev2] [var2] ...");
-
-	register_command(cmd_ctx, NULL, "verify_ircapture", handle_verify_ircapture_command,
-		COMMAND_ANY, "verify value captured during Capture-IR <enable|disable>");
-	return ERROR_OK;
-}
-
-int jtag_init(struct command_context_s *cmd_ctx)
-{
-	int i, validate_tries = 0;
-	
-	DEBUG("-");
-
-	if (jtag_speed == -1)
-		jtag_speed = 0;
-	
-	if (jtag_interface && (jtag_interface[0] != 0))
-		/* configuration var 'jtag_interface' is set, and not empty */
-		for (i = 0; jtag_interfaces[i]; i++)
-		{
-			if (strcmp(jtag_interface, jtag_interfaces[i]->name) == 0)
-			{
-				jtag_device_t *device;
-				device = jtag_devices;
-	
-				if (jtag_interfaces[i]->init() != ERROR_OK)
-					return ERROR_JTAG_INIT_FAILED;
-				jtag = jtag_interfaces[i];
-
-				jtag_ir_scan_size = 0;
-				jtag_num_devices = 0;
-				while (device != NULL)
-				{
-					jtag_ir_scan_size += device->ir_length;
-					jtag_num_devices++;
-					device = device->next;
-				}
-				
-				jtag_add_statemove(TAP_TLR);
-				jtag_execute_queue();
-
-				/* examine chain first, as this could discover the real chain layout */
-				if (jtag_examine_chain() != ERROR_OK)
-				{
-					ERROR("trying to validate configured JTAG chain anyway...");
-				}
-				
-				while (jtag_validate_chain() != ERROR_OK)
-				{
-					validate_tries++;
-					if (validate_tries > 5)
-					{
-						ERROR("Could not validate JTAG chain, exit");
-						jtag = NULL;
-						return ERROR_JTAG_INVALID_INTERFACE;
-					}
-					usleep(10000);
-				}
-
-				return ERROR_OK;
-			}
-		}
-	
-	/* no valid interface was found (i.e. the configuration option,
-	 * didn't match one of the compiled-in interfaces
-	 */
-	ERROR("No valid jtag interface found (%s)", jtag_interface);
-	ERROR("compiled-in jtag interfaces:");
-	for (i = 0; jtag_interfaces[i]; i++)
-	{
-		ERROR("%i: %s", i, jtag_interfaces[i]->name);
-	}
-	
-	jtag = NULL;
-	return ERROR_JTAG_INVALID_INTERFACE;
-}
-
-int handle_interface_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	int i;
-	
-	/* only if the configuration var isn't overwritten from cmdline */
-	if (!jtag_interface)
-	{
-		if (args[0] && (args[0][0] != 0))
-		{
-			for (i=0; jtag_interfaces[i]; i++)
-			{
-				if (strcmp(args[0], jtag_interfaces[i]->name) == 0)
-				{
-					if (jtag_interfaces[i]->register_commands(cmd_ctx) != ERROR_OK)
-						exit(-1);
-				
-					jtag_interface = jtag_interfaces[i]->name;
-		
-					return ERROR_OK;
-				}
-			}
-		}
-		
-		/* remember the requested interface name, so we can complain about it later */
-		jtag_interface = strdup(args[0]);
-		DEBUG("'interface' command didn't specify a valid interface");
-	}
-	
-	return ERROR_OK;
-}
-
-int handle_jtag_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	jtag_device_t **last_device_p = &jtag_devices;
-
-	if (*last_device_p)
-	{
-		while ((*last_device_p)->next)
-			last_device_p = &((*last_device_p)->next);
-		last_device_p = &((*last_device_p)->next);
-	}
-
-	if (argc < 3)
-		return ERROR_OK;
-
-	*last_device_p = malloc(sizeof(jtag_device_t));
-	(*last_device_p)->ir_length = strtoul(args[0], NULL, 0);
-
-	(*last_device_p)->expected = malloc((*last_device_p)->ir_length);
-	buf_set_u32((*last_device_p)->expected, 0, (*last_device_p)->ir_length, strtoul(args[1], NULL, 0));
-	(*last_device_p)->expected_mask = malloc((*last_device_p)->ir_length);
-	buf_set_u32((*last_device_p)->expected_mask, 0, (*last_device_p)->ir_length, strtoul(args[2], NULL, 0));
-
-	(*last_device_p)->cur_instr = malloc((*last_device_p)->ir_length);
-	(*last_device_p)->bypass = 1;
-	buf_set_ones((*last_device_p)->cur_instr, (*last_device_p)->ir_length);
-	
-	(*last_device_p)->next = NULL;
-	
-	jtag_register_event_callback(jtag_reset_callback, (*last_device_p));
-	
-	jtag_num_devices++;
-
-	return ERROR_OK;
-}
-
-int handle_scan_chain_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	jtag_device_t *device = jtag_devices;
-	int device_count = 0;
-	
-	while (device)
-	{
-		u32 expected, expected_mask, cur_instr;
-		expected = buf_get_u32(device->expected, 0, device->ir_length);
-		expected_mask = buf_get_u32(device->expected_mask, 0, device->ir_length);
-		cur_instr = buf_get_u32(device->cur_instr, 0, device->ir_length);
-		command_print(cmd_ctx, "%i: idcode: 0x%8.8x ir length %i, ir capture 0x%x, ir mask 0x%x, current instruction 0x%x", device_count, device->idcode, device->ir_length, expected, expected_mask, cur_instr);
-		device = device->next;
-		device_count++;
-	}
-
-	return ERROR_OK;
-}
-
-int handle_reset_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	if (argc >= 1)
-	{
-		if (strcmp(args[0], "none") == 0)
-			jtag_reset_config = RESET_NONE;
-		else if (strcmp(args[0], "trst_only") == 0)
-			jtag_reset_config = RESET_HAS_TRST;
-		else if (strcmp(args[0], "srst_only") == 0)
-			jtag_reset_config = RESET_HAS_SRST;
-		else if (strcmp(args[0], "trst_and_srst") == 0)
-			jtag_reset_config = RESET_TRST_AND_SRST;
-		else
-		{
-			ERROR("invalid reset_config argument, defaulting to none");
-			jtag_reset_config = RESET_NONE;
-			return ERROR_INVALID_ARGUMENTS;
-		}
-	}
-	
-	if (argc >= 2)
-	{
-		if (strcmp(args[1], "srst_pulls_trst") == 0)
-			jtag_reset_config |= RESET_SRST_PULLS_TRST;
-		else if (strcmp(args[1], "trst_pulls_srst") == 0)
-			jtag_reset_config |= RESET_TRST_PULLS_SRST;
-		else if (strcmp(args[1], "combined") == 0)
-			jtag_reset_config |= RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST;
-		else if (strcmp(args[1], "separate") == 0)
-			jtag_reset_config &= ~(RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST);
-		else
-		{
-			ERROR("invalid reset_config argument, defaulting to none");
-			jtag_reset_config = RESET_NONE;
-			return ERROR_INVALID_ARGUMENTS;
-		}
-	}
-	
-	if (argc >= 3)
-	{
-		if (strcmp(args[2], "trst_open_drain") == 0)
-			jtag_reset_config |= RESET_TRST_OPEN_DRAIN;
-		else if (strcmp(args[2], "trst_push_pull") == 0)
-			jtag_reset_config &= ~RESET_TRST_OPEN_DRAIN;
-		else
-		{
-			ERROR("invalid reset_config argument, defaulting to none");
-			jtag_reset_config = RESET_NONE;
-			return ERROR_INVALID_ARGUMENTS;
-		}
-	}
-
-	if (argc >= 4)
-	{
-		if (strcmp(args[3], "srst_push_pull") == 0)
-			jtag_reset_config |= RESET_SRST_PUSH_PULL;
-		else if (strcmp(args[3], "srst_open_drain") == 0)
-			jtag_reset_config &= ~RESET_SRST_PUSH_PULL;
-		else
-		{
-			ERROR("invalid reset_config argument, defaulting to none");
-			jtag_reset_config = RESET_NONE;
-			return ERROR_INVALID_ARGUMENTS;
-		}
-	}
-	
-	return ERROR_OK;
-}
-
-int handle_jtag_nsrst_delay_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	if (argc < 1)
-	{
-		ERROR("jtag_nsrst_delay <ms> command takes one required argument");
-		exit(-1);
-	}
-	else
-	{
-		jtag_nsrst_delay = strtoul(args[0], NULL, 0);
-	}
-	
-	return ERROR_OK;
-}
-
-int handle_jtag_ntrst_delay_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	if (argc < 1)
-	{
-		ERROR("jtag_ntrst_delay <ms> command takes one required argument");
-		exit(-1);
-	}
-	else
-	{
-		jtag_ntrst_delay = strtoul(args[0], NULL, 0);
-	}
-	
-	return ERROR_OK;
-}
-
-int handle_jtag_speed_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	if (argc == 0)
-		command_print(cmd_ctx, "jtag_speed: %i", jtag_speed);
-
-	if (argc > 0)
-	{
-		/* this command can be called during CONFIG, 
-		 * in which case jtag isn't initialized */
-		if (jtag)
-			jtag->speed(strtoul(args[0], NULL, 0));
-		else
-			jtag_speed = strtoul(args[0], NULL, 0);
-	}
-
-	return ERROR_OK;
-}
-
-int handle_endstate_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	enum tap_state state;
-
-	if (argc < 1)
-	{
+/***************************************************************************
+ *   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.             *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "replacements.h"
+
+#include "jtag.h"
+
+#include "command.h"
+#include "log.h"
+#include "interpreter.h"
+
+#include "stdlib.h"
+#include "string.h"
+#include <unistd.h>
+
+char* tap_state_strings[16] =
+{
+	"tlr", 
+	"sds", "cd", "sd", "e1d", "pd", "e2d", "ud",
+	"rti",
+	"sis", "ci", "si", "e1i", "pi", "e2i", "ui"
+};
+
+typedef struct cmd_queue_page_s
+{
+	void *address;
+	size_t used;
+	struct cmd_queue_page_s *next;
+} cmd_queue_page_t;
+
+#define CMD_QUEUE_PAGE_SIZE (1024 * 1024)
+static cmd_queue_page_t *cmd_queue_pages = NULL;
+
+/* tap_move[i][j]: tap movement command to go from state i to state j
+ * 0: Test-Logic-Reset
+ * 1: Run-Test/Idle
+ * 2: Shift-DR
+ * 3: Pause-DR
+ * 4: Shift-IR
+ * 5: Pause-IR
+ * 
+ * SD->SD and SI->SI have to be caught in interface specific code
+ */
+u8 tap_move[6][6] =
+{
+/*	  TLR   RTI   SD    PD    SI    PI             */
+	{0x7f, 0x00, 0x17, 0x0a, 0x1b, 0x16},	/* TLR */
+	{0x7f, 0x00, 0x25, 0x05, 0x2b, 0x0b},	/* RTI */
+	{0x7f, 0x31, 0x00, 0x01, 0x0f, 0x2f},	/* SD  */
+	{0x7f, 0x30, 0x20, 0x17, 0x1e, 0x2f},	/* PD  */
+	{0x7f, 0x31, 0x07, 0x17, 0x00, 0x01},	/* SI  */
+	{0x7f, 0x30, 0x1c, 0x17, 0x20, 0x2f}	/* PI  */
+};
+
+int tap_move_map[16] = {
+	0, -1, -1,  2, -1,  3, -1, -1,
+	1, -1, -1,  4, -1,  5, -1, -1
+};
+
+tap_transition_t tap_transitions[16] =
+{
+	{TAP_TLR, TAP_RTI},		/* TLR */
+	{TAP_SIS, TAP_CD},		/* SDS */
+	{TAP_E1D, TAP_SD},		/* CD  */
+	{TAP_E1D, TAP_SD},		/* SD  */
+	{TAP_UD,  TAP_PD}, 		/* E1D */
+	{TAP_E2D, TAP_PD},		/* PD  */
+	{TAP_UD,  TAP_SD},		/* E2D */
+	{TAP_SDS, TAP_RTI},		/* UD  */
+	{TAP_SDS, TAP_RTI},		/* RTI */
+	{TAP_TLR, TAP_CI},		/* SIS */
+	{TAP_E1I, TAP_SI},		/* CI  */
+	{TAP_E1I, TAP_SI},		/* SI  */
+	{TAP_UI,  TAP_PI}, 		/* E1I */
+	{TAP_E2I, TAP_PI},		/* PI  */
+	{TAP_UI,  TAP_SI},		/* E2I */
+	{TAP_SDS, TAP_RTI}		/* UI  */
+};
+
+char* jtag_event_strings[] =
+{
+	"SRST asserted",
+	"TRST asserted",
+	"SRST released",
+	"TRST released"
+};
+
+enum tap_state end_state = TAP_TLR;
+enum tap_state cur_state = TAP_TLR;
+int jtag_trst = 0;
+int jtag_srst = 0;
+
+jtag_command_t *jtag_command_queue = NULL;
+jtag_command_t **last_comand_pointer = &jtag_command_queue;
+jtag_device_t *jtag_devices = NULL;
+int jtag_num_devices = 0;
+int jtag_ir_scan_size = 0;
+enum reset_types jtag_reset_config = RESET_NONE;
+enum tap_state cmd_queue_end_state = TAP_TLR;
+enum tap_state cmd_queue_cur_state = TAP_TLR;
+
+int jtag_verify_capture_ir = 1;
+
+/* how long the OpenOCD should wait before attempting JTAG communication after reset lines deasserted (in ms) */
+int jtag_nsrst_delay = 0; /* default to no nSRST delay */
+int jtag_ntrst_delay = 0; /* default to no nTRST delay */ 
+
+/* maximum number of JTAG devices expected in the chain
+ */
+#define JTAG_MAX_CHAIN_SIZE 20 
+
+/* callbacks to inform high-level handlers about JTAG state changes */
+jtag_event_callback_t *jtag_event_callbacks;
+
+/* jtag interfaces (parport, FTDI-USB, TI-USB, ...)
+ */
+#if BUILD_PARPORT == 1
+	extern jtag_interface_t parport_interface;
+#endif
+
+#if BUILD_FT2232_FTD2XX == 1
+	extern jtag_interface_t ft2232_interface;
+#endif
+
+#if BUILD_FT2232_LIBFTDI == 1
+	extern jtag_interface_t ft2232_interface;
+#endif
+
+#if BUILD_AMTJTAGACCEL == 1
+	extern jtag_interface_t amt_jtagaccel_interface;
+#endif
+
+#if BUILD_EP93XX == 1
+	extern jtag_interface_t ep93xx_interface;
+#endif
+
+#if BUILD_AT91RM9200 == 1
+	extern jtag_interface_t at91rm9200_interface;
+#endif
+
+#if BUILD_GW16012 == 1
+	extern jtag_interface_t gw16012_interface;
+#endif
+
+#if BUILD_PRESTO_LIBFTDI == 1 || BUILD_PRESTO_FTD2XX == 1
+	extern jtag_interface_t presto_interface;
+#endif
+
+#if BUILD_USBPROG == 1
+	extern jtag_interface_t usbprog_interface;
+#endif
+
+jtag_interface_t *jtag_interfaces[] = {
+#if BUILD_PARPORT == 1
+	&parport_interface,
+#endif
+#if BUILD_FT2232_FTD2XX == 1
+	&ft2232_interface,
+#endif
+#if BUILD_FT2232_LIBFTDI == 1
+	&ft2232_interface,
+#endif
+#if BUILD_AMTJTAGACCEL == 1
+	&amt_jtagaccel_interface,
+#endif
+#if BUILD_EP93XX == 1
+	&ep93xx_interface,
+#endif
+#if BUILD_AT91RM9200 == 1
+	&at91rm9200_interface,
+#endif
+#if BUILD_GW16012 == 1
+	&gw16012_interface,
+#endif
+#if BUILD_PRESTO_LIBFTDI == 1 || BUILD_PRESTO_FTD2XX == 1
+	&presto_interface,
+#endif
+#if BUILD_USBPROG == 1
+	&usbprog_interface,
+#endif
+	NULL,
+};
+
+jtag_interface_t *jtag = NULL;
+
+/* configuration */
+char* jtag_interface = NULL;
+int jtag_speed = -1;
+
+
+/* forward declarations */
+int jtag_add_statemove(enum tap_state endstate);
+int jtag_add_pathmove(int num_states, enum tap_state *path);
+int jtag_add_runtest(int num_cycles, enum tap_state endstate);
+int jtag_add_reset(int trst, int srst);
+int jtag_add_end_state(enum tap_state endstate);
+int jtag_add_sleep(u32 us);
+int jtag_execute_queue(void);
+int jtag_cancel_queue(void);
+
+/* jtag commands */
+int handle_interface_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_jtag_speed_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_jtag_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_reset_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_jtag_nsrst_delay_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_jtag_ntrst_delay_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+int handle_scan_chain_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+int handle_endstate_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_jtag_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_runtest_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_statemove_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_irscan_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_drscan_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+int handle_verify_ircapture_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+int jtag_register_event_callback(int (*callback)(enum jtag_event event, void *priv), void *priv)
+{
+	jtag_event_callback_t **callbacks_p = &jtag_event_callbacks;
+	
+	if (callback == NULL)
+	{
+		return ERROR_INVALID_ARGUMENTS;
+	}
+	
+	if (*callbacks_p)
+	{
+		while ((*callbacks_p)->next)
+			callbacks_p = &((*callbacks_p)->next);
+		callbacks_p = &((*callbacks_p)->next);
+	}
+	
+	(*callbacks_p) = malloc(sizeof(jtag_event_callback_t));
+	(*callbacks_p)->callback = callback;
+	(*callbacks_p)->priv = priv;
+	(*callbacks_p)->next = NULL;
+	
+	return ERROR_OK;
+}
+
+int jtag_unregister_event_callback(int (*callback)(enum jtag_event event, void *priv))
+{
+	jtag_event_callback_t **callbacks_p = &jtag_event_callbacks;
+	
+	if (callback == NULL)
+	{
+		return ERROR_INVALID_ARGUMENTS;
+	}
+		
+	while (*callbacks_p)
+	{
+		jtag_event_callback_t **next = &((*callbacks_p)->next);
+		if ((*callbacks_p)->callback == callback)
+		{
+			free(*callbacks_p);
+			*callbacks_p = *next;
+		}
+		callbacks_p = next;
+	}
+	
+	return ERROR_OK;
+}
+
+int jtag_call_event_callbacks(enum jtag_event event)
+{
+	jtag_event_callback_t *callback = jtag_event_callbacks;
+	
+	DEBUG("jtag event: %s", jtag_event_strings[event]);
+	
+	while (callback)
+	{
+		callback->callback(event, callback->priv);
+		callback = callback->next;
+	}
+	
+	return ERROR_OK;
+}
+
+/* returns a pointer to the pointer of the last command in queue
+ * this may be a pointer to the root pointer (jtag_command_queue)
+ * or to the next member of the last but one command
+ */
+jtag_command_t** jtag_get_last_command_p(void)
+{
+/*	jtag_command_t *cmd = jtag_command_queue;
+	
+	if (cmd)
+		while (cmd->next)
+			cmd = cmd->next;
+	else
+		return &jtag_command_queue;
+	
+	return &cmd->next;*/
+	
+	return last_comand_pointer;
+}
+
+/* returns a pointer to the n-th device in the scan chain */
+jtag_device_t* jtag_get_device(int num)
+{
+	jtag_device_t *device = jtag_devices;
+	int i = 0;
+
+	while (device)
+	{
+		if (num == i)
+			return device;
+		device = device->next;
+		i++;
+	}
+	
+	ERROR("jtag device number %d not defined", num);
+	exit(-1);
+}
+
+void* cmd_queue_alloc(size_t size)
+{
+	cmd_queue_page_t **p_page = &cmd_queue_pages;
+	int offset;
+
+	if (*p_page)
+	{
+		while ((*p_page)->next)
+			p_page = &((*p_page)->next);
+		if (CMD_QUEUE_PAGE_SIZE - (*p_page)->used < size)
+			p_page = &((*p_page)->next);
+	}
+
+	if (!*p_page)
+	{
+		*p_page = malloc(sizeof(cmd_queue_page_t));
+		(*p_page)->used = 0;
+		(*p_page)->address = malloc(CMD_QUEUE_PAGE_SIZE);
+		(*p_page)->next = NULL;
+	}
+
+	offset = (*p_page)->used;
+	(*p_page)->used += size;
+	
+	u8 *t=(u8 *)((*p_page)->address);
+	return t + offset;
+}
+
+void cmd_queue_free()
+{
+	cmd_queue_page_t *page = cmd_queue_pages;
+
+	while (page)
+	{
+		cmd_queue_page_t *last = page;
+		free(page->address);
+		page = page->next;
+		free(last);
+	}
+
+	cmd_queue_pages = NULL;
+}
+
+int jtag_add_ir_scan(int num_fields, scan_field_t *fields, enum tap_state state)
+{
+	jtag_command_t **last_cmd;
+	jtag_device_t *device;
+	int i, j;
+	int scan_size = 0;
+
+	if (jtag_trst == 1)
+	{
+		WARNING("JTAG command queued, while TRST is low (TAP in reset)");
+		return ERROR_JTAG_TRST_ASSERTED;
+	}
+
+	last_cmd = jtag_get_last_command_p();
+	
+	/* allocate memory for a new list member */
+	*last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
+	(*last_cmd)->next = NULL;
+	last_comand_pointer = &((*last_cmd)->next);
+	(*last_cmd)->type = JTAG_SCAN;
+
+	/* allocate memory for ir scan command */
+	(*last_cmd)->cmd.scan = cmd_queue_alloc(sizeof(scan_command_t));
+	(*last_cmd)->cmd.scan->ir_scan = 1;
+	(*last_cmd)->cmd.scan->num_fields = jtag_num_devices;	/* one field per device */
+	(*last_cmd)->cmd.scan->fields = cmd_queue_alloc(jtag_num_devices * sizeof(scan_field_t));
+	(*last_cmd)->cmd.scan->end_state = state;
+		
+	if (state != -1)
+		cmd_queue_end_state = state;
+
+	if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)
+		jtag_call_event_callbacks(JTAG_TRST_RELEASED);
+	
+	if (cmd_queue_end_state == TAP_TLR)
+		jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
+	
+	cmd_queue_cur_state = cmd_queue_end_state;
+		
+	for (i = 0; i < jtag_num_devices; i++)
+	{
+		int found = 0;
+		device = jtag_get_device(i);
+		scan_size = device->ir_length;
+		(*last_cmd)->cmd.scan->fields[i].device = i;
+		(*last_cmd)->cmd.scan->fields[i].num_bits = scan_size;
+		(*last_cmd)->cmd.scan->fields[i].in_value = NULL;
+		(*last_cmd)->cmd.scan->fields[i].in_handler = NULL;	/* disable verification by default */
+
+		/* search the list */
+		for (j = 0; j < num_fields; j++)
+		{
+			if (i == fields[j].device)
+			{
+				found = 1;
+				(*last_cmd)->cmd.scan->fields[i].out_value = buf_cpy(fields[j].out_value, cmd_queue_alloc(CEIL(scan_size, 8)), scan_size);
+				(*last_cmd)->cmd.scan->fields[i].out_mask = buf_cpy(fields[j].out_mask, cmd_queue_alloc(CEIL(scan_size, 8)), scan_size);
+			
+				if (jtag_verify_capture_ir)
+				{
+					if (fields[j].in_handler==NULL)
+					{
+						jtag_set_check_value((*last_cmd)->cmd.scan->fields+i, device->expected, device->expected_mask, NULL);
+					} else
+					{
+						(*last_cmd)->cmd.scan->fields[i].in_handler = fields[j].in_handler;
+						(*last_cmd)->cmd.scan->fields[i].in_handler_priv = fields[j].in_handler_priv;
+						(*last_cmd)->cmd.scan->fields[i].in_check_value = device->expected; 
+						(*last_cmd)->cmd.scan->fields[i].in_check_mask = device->expected_mask;
+					}
+				}
+				
+				device->bypass = 0;
+				break;
+			}
+		}
+	
+		if (!found)
+		{
+			/* if a device isn't listed, set it to BYPASS */
+			(*last_cmd)->cmd.scan->fields[i].out_value = buf_set_ones(cmd_queue_alloc(CEIL(scan_size, 8)), scan_size);
+			(*last_cmd)->cmd.scan->fields[i].out_mask = NULL;
+			device->bypass = 1;
+		
+		}
+		
+		/* update device information */
+		buf_cpy((*last_cmd)->cmd.scan->fields[i].out_value, jtag_get_device(i)->cur_instr, scan_size);
+	}
+	
+	return ERROR_OK;
+}
+
+int jtag_add_plain_ir_scan(int num_fields, scan_field_t *fields, enum tap_state state)
+{
+	jtag_command_t **last_cmd;
+	int i;
+
+	if (jtag_trst == 1)
+	{
+		WARNING("JTAG command queued, while TRST is low (TAP in reset)");
+		return ERROR_JTAG_TRST_ASSERTED;
+	}
+
+	last_cmd = jtag_get_last_command_p();
+	
+	/* allocate memory for a new list member */
+	*last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
+	(*last_cmd)->next = NULL;
+	last_comand_pointer = &((*last_cmd)->next);
+	(*last_cmd)->type = JTAG_SCAN;
+
+	/* allocate memory for ir scan command */
+	(*last_cmd)->cmd.scan = cmd_queue_alloc(sizeof(scan_command_t));
+	(*last_cmd)->cmd.scan->ir_scan = 1;
+	(*last_cmd)->cmd.scan->num_fields = num_fields;
+	(*last_cmd)->cmd.scan->fields = cmd_queue_alloc(num_fields * sizeof(scan_field_t));
+	(*last_cmd)->cmd.scan->end_state = state;
+
+	if (state != -1)
+		cmd_queue_end_state = state;
+
+	if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)
+		jtag_call_event_callbacks(JTAG_TRST_RELEASED);
+	
+	if (cmd_queue_end_state == TAP_TLR)
+		jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
+		
+	cmd_queue_cur_state = cmd_queue_end_state;
+	
+	for (i = 0; i < num_fields; i++)
+	{
+		int num_bits = fields[i].num_bits;
+		int num_bytes = CEIL(fields[i].num_bits, 8);
+		(*last_cmd)->cmd.scan->fields[i].device = fields[i].device;
+		(*last_cmd)->cmd.scan->fields[i].num_bits = num_bits;
+		(*last_cmd)->cmd.scan->fields[i].out_value = buf_cpy(fields[i].out_value, cmd_queue_alloc(num_bytes), num_bits);
+		(*last_cmd)->cmd.scan->fields[i].out_mask = buf_cpy(fields[i].out_mask, cmd_queue_alloc(num_bytes), num_bits);
+		(*last_cmd)->cmd.scan->fields[i].in_value = fields[i].in_value;
+		(*last_cmd)->cmd.scan->fields[i].in_check_value = fields[i].in_check_value;
+		(*last_cmd)->cmd.scan->fields[i].in_check_mask = fields[i].in_check_mask;
+		(*last_cmd)->cmd.scan->fields[i].in_handler = NULL;
+		(*last_cmd)->cmd.scan->fields[i].in_handler_priv = NULL;
+	}
+	return ERROR_OK;
+}
+
+int jtag_add_dr_scan(int num_fields, scan_field_t *fields, enum tap_state state)
+{
+	int i, j;
+	int bypass_devices = 0;
+	int field_count = 0;
+	jtag_command_t **last_cmd = jtag_get_last_command_p();
+	jtag_device_t *device = jtag_devices;
+	int scan_size;
+
+	if (jtag_trst == 1)
+	{
+		WARNING("JTAG command queued, while TRST is low (TAP in reset)");
+		return ERROR_JTAG_TRST_ASSERTED;
+	}
+
+	/* count devices in bypass */
+	while (device)
+	{
+		if (device->bypass)
+			bypass_devices++;
+		device = device->next;
+	}
+	
+	/* allocate memory for a new list member */
+	*last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
+	last_comand_pointer = &((*last_cmd)->next);
+	(*last_cmd)->next = NULL;
+	(*last_cmd)->type = JTAG_SCAN;
+
+	/* allocate memory for dr scan command */
+	(*last_cmd)->cmd.scan = cmd_queue_alloc(sizeof(scan_command_t));
+	(*last_cmd)->cmd.scan->ir_scan = 0;
+	(*last_cmd)->cmd.scan->num_fields = num_fields + bypass_devices;
+	(*last_cmd)->cmd.scan->fields = cmd_queue_alloc((num_fields + bypass_devices) * sizeof(scan_field_t));
+	(*last_cmd)->cmd.scan->end_state = state;
+	
+	if (state != -1)
+		cmd_queue_end_state = state;
+
+	if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)
+		jtag_call_event_callbacks(JTAG_TRST_RELEASED);
+	
+	if (cmd_queue_end_state == TAP_TLR)
+		jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
+			
+	cmd_queue_cur_state = cmd_queue_end_state;
+	
+	for (i = 0; i < jtag_num_devices; i++)
+	{
+		int found = 0;
+		(*last_cmd)->cmd.scan->fields[field_count].device = i;
+	
+		for (j = 0; j < num_fields; j++)
+		{
+			if (i == fields[j].device)
+			{
+				found = 1;
+				scan_size = fields[j].num_bits;
+				(*last_cmd)->cmd.scan->fields[field_count].num_bits = scan_size;
+				(*last_cmd)->cmd.scan->fields[field_count].out_value = buf_cpy(fields[j].out_value, cmd_queue_alloc(CEIL(scan_size, 8)), scan_size);
+				(*last_cmd)->cmd.scan->fields[field_count].out_mask = buf_cpy(fields[j].out_mask, cmd_queue_alloc(CEIL(scan_size, 8)), scan_size);
+				(*last_cmd)->cmd.scan->fields[field_count].in_value = fields[j].in_value;
+				(*last_cmd)->cmd.scan->fields[field_count].in_check_value = fields[j].in_check_value;
+				(*last_cmd)->cmd.scan->fields[field_count].in_check_mask = fields[j].in_check_mask;
+				(*last_cmd)->cmd.scan->fields[field_count].in_handler = fields[j].in_handler;
+				(*last_cmd)->cmd.scan->fields[field_count++].in_handler_priv = fields[j].in_handler_priv;
+			}
+		}
+		if (!found)
+		{
+			/* if a device isn't listed, the BYPASS register should be selected */
+			if (!jtag_get_device(i)->bypass)
+			{
+				ERROR("BUG: no scan data for a device not in BYPASS");
+				exit(-1);
+			}
+	
+			/* program the scan field to 1 bit length, and ignore it's value */
+			(*last_cmd)->cmd.scan->fields[field_count].num_bits = 1;
+			(*last_cmd)->cmd.scan->fields[field_count].out_value = NULL;
+			(*last_cmd)->cmd.scan->fields[field_count].out_mask = NULL;
+			(*last_cmd)->cmd.scan->fields[field_count].in_value = NULL;
+			(*last_cmd)->cmd.scan->fields[field_count].in_check_value = NULL;
+			(*last_cmd)->cmd.scan->fields[field_count].in_check_mask = NULL;
+			(*last_cmd)->cmd.scan->fields[field_count].in_handler = NULL;
+			(*last_cmd)->cmd.scan->fields[field_count++].in_handler_priv = NULL;
+		}
+		else
+		{
+			/* if a device is listed, the BYPASS register must not be selected */
+			if (jtag_get_device(i)->bypass)
+			{
+				WARNING("scan data for a device in BYPASS");
+			}
+		}
+	}
+	return ERROR_OK;
+}
+
+
+int jtag_add_plain_dr_scan(int num_fields, scan_field_t *fields, enum tap_state state)
+{
+	int i;
+	jtag_command_t **last_cmd = jtag_get_last_command_p();
+	
+	if (jtag_trst == 1)
+	{
+		WARNING("JTAG command queued, while TRST is low (TAP in reset)");
+		return ERROR_JTAG_TRST_ASSERTED;
+	}
+
+	/* allocate memory for a new list member */
+	*last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
+	last_comand_pointer = &((*last_cmd)->next);
+	(*last_cmd)->next = NULL;
+	(*last_cmd)->type = JTAG_SCAN;
+
+	/* allocate memory for scan command */
+	(*last_cmd)->cmd.scan = cmd_queue_alloc(sizeof(scan_command_t));
+	(*last_cmd)->cmd.scan->ir_scan = 0;
+	(*last_cmd)->cmd.scan->num_fields = num_fields;
+	(*last_cmd)->cmd.scan->fields = cmd_queue_alloc(num_fields * sizeof(scan_field_t));
+	(*last_cmd)->cmd.scan->end_state = state;
+		
+	if (state != -1)
+		cmd_queue_end_state = state;
+
+	if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)
+		jtag_call_event_callbacks(JTAG_TRST_RELEASED);
+	
+	if (cmd_queue_end_state == TAP_TLR)
+		jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
+			
+	cmd_queue_cur_state = cmd_queue_end_state;
+	
+	for (i = 0; i < num_fields; i++)
+	{
+		int num_bits = fields[i].num_bits;
+		int num_bytes = CEIL(fields[i].num_bits, 8);
+		(*last_cmd)->cmd.scan->fields[i].device = fields[i].device;
+		(*last_cmd)->cmd.scan->fields[i].num_bits = num_bits;
+		(*last_cmd)->cmd.scan->fields[i].out_value = buf_cpy(fields[i].out_value, cmd_queue_alloc(num_bytes), num_bits);
+		(*last_cmd)->cmd.scan->fields[i].out_mask = buf_cpy(fields[i].out_mask, cmd_queue_alloc(num_bytes), num_bits);
+		(*last_cmd)->cmd.scan->fields[i].in_value = fields[i].in_value;
+		(*last_cmd)->cmd.scan->fields[i].in_check_value = fields[i].in_check_value;
+		(*last_cmd)->cmd.scan->fields[i].in_check_mask = fields[i].in_check_mask;
+		(*last_cmd)->cmd.scan->fields[i].in_handler = fields[i].in_handler;
+		(*last_cmd)->cmd.scan->fields[i].in_handler_priv = fields[i].in_handler_priv;
+	}
+
+	return ERROR_OK;
+}
+int jtag_add_statemove(enum tap_state state)
+{
+	jtag_command_t **last_cmd = jtag_get_last_command_p();
+	
+	if (jtag_trst == 1)
+	{
+		WARNING("JTAG command queued, while TRST is low (TAP in reset)");
+		return ERROR_JTAG_TRST_ASSERTED;
+	}
+
+	/* allocate memory for a new list member */
+	*last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
+	last_comand_pointer = &((*last_cmd)->next);
+	(*last_cmd)->next = NULL;
+	(*last_cmd)->type = JTAG_STATEMOVE;
+
+	(*last_cmd)->cmd.statemove = cmd_queue_alloc(sizeof(statemove_command_t));
+	(*last_cmd)->cmd.statemove->end_state = state;
+	
+	if (state != -1)
+		cmd_queue_end_state = state;
+
+	if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)
+		jtag_call_event_callbacks(JTAG_TRST_RELEASED);
+	
+	if (cmd_queue_end_state == TAP_TLR)
+		jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
+			
+	cmd_queue_cur_state = cmd_queue_end_state;
+	
+	return ERROR_OK;
+}
+
+int jtag_add_pathmove(int num_states, enum tap_state *path)
+{
+	jtag_command_t **last_cmd = jtag_get_last_command_p();
+	int i;
+	
+	if (jtag_trst == 1)
+	{
+		WARNING("JTAG command queued, while TRST is low (TAP in reset)");
+		return ERROR_JTAG_TRST_ASSERTED;
+	}
+	
+	/* the last state has to be a stable state */
+	if (tap_move_map[path[num_states - 1]] == -1)
+	{
+		ERROR("TAP path doesn't finish in a stable state");
+		return ERROR_JTAG_NOT_IMPLEMENTED;
+	}
+	
+	/* allocate memory for a new list member */
+	*last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
+	last_comand_pointer = &((*last_cmd)->next);
+	(*last_cmd)->next = NULL;
+	(*last_cmd)->type = JTAG_PATHMOVE;
+
+	(*last_cmd)->cmd.pathmove = cmd_queue_alloc(sizeof(pathmove_command_t));
+	(*last_cmd)->cmd.pathmove->num_states = num_states;
+	(*last_cmd)->cmd.pathmove->path = cmd_queue_alloc(sizeof(enum tap_state) * num_states);
+	
+	for (i = 0; i < num_states; i++)
+		(*last_cmd)->cmd.pathmove->path[i] = path[i];
+
+	if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)
+		jtag_call_event_callbacks(JTAG_TRST_RELEASED);
+	
+	if (cmd_queue_end_state == TAP_TLR)
+		jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
+	
+	cmd_queue_cur_state = path[num_states - 1];
+	
+	return ERROR_OK;
+}
+
+int jtag_add_runtest(int num_cycles, enum tap_state state)
+{
+	jtag_command_t **last_cmd = jtag_get_last_command_p();
+	
+	if (jtag_trst == 1)
+	{
+		WARNING("JTAG command queued, while TRST is low (TAP in reset)");
+		return ERROR_JTAG_TRST_ASSERTED;
+	}
+
+	/* allocate memory for a new list member */
+	*last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
+	(*last_cmd)->next = NULL;
+	last_comand_pointer = &((*last_cmd)->next);
+	(*last_cmd)->type = JTAG_RUNTEST;
+
+	(*last_cmd)->cmd.runtest = cmd_queue_alloc(sizeof(runtest_command_t));
+	(*last_cmd)->cmd.runtest->num_cycles = num_cycles;
+	(*last_cmd)->cmd.runtest->end_state = state;
+	
+	if (state != -1)
+		cmd_queue_end_state = state;
+
+	if (cmd_queue_cur_state == TAP_TLR && cmd_queue_end_state != TAP_TLR)
+		jtag_call_event_callbacks(JTAG_TRST_RELEASED);
+	
+	if (cmd_queue_end_state == TAP_TLR)
+		jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
+			
+	cmd_queue_cur_state = cmd_queue_end_state;
+	
+	return ERROR_OK;
+}
+
+int jtag_add_reset(int req_trst, int req_srst)
+{
+	int trst_with_tms = 0;
+	
+	jtag_command_t **last_cmd = jtag_get_last_command_p();
+	
+	if (req_trst == -1)
+		req_trst = jtag_trst;
+	
+	if (req_srst == -1)
+		req_srst = jtag_srst;
+
+	/* Make sure that jtag_reset_config allows the requested reset */
+	/* if SRST pulls TRST, we can't fulfill srst == 1 with trst == 0 */
+	if (((jtag_reset_config & RESET_SRST_PULLS_TRST) && (req_srst == 1)) && (req_trst == 0))
+		return ERROR_JTAG_RESET_WOULD_ASSERT_TRST;
+		
+	/* if TRST pulls SRST, we reset with TAP T-L-R */
+	if (((jtag_reset_config & RESET_TRST_PULLS_SRST) && (req_trst == 1)) && (req_srst == 0))
+	{
+		req_trst = 0;
+		trst_with_tms = 1;
+	}
+	
+	if (req_srst && !(jtag_reset_config & RESET_HAS_SRST))
+	{
+		ERROR("requested nSRST assertion, but the current configuration doesn't support this");
+		return ERROR_JTAG_RESET_CANT_SRST;
+	}
+	
+	if (req_trst && !(jtag_reset_config & RESET_HAS_TRST))
+	{
+		req_trst = 0;
+		trst_with_tms = 1;
+	}
+	
+	/* allocate memory for a new list member */
+	*last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
+	(*last_cmd)->next = NULL;
+	last_comand_pointer = &((*last_cmd)->next);
+	(*last_cmd)->type = JTAG_RESET;
+
+	(*last_cmd)->cmd.reset = cmd_queue_alloc(sizeof(reset_command_t));
+	(*last_cmd)->cmd.reset->trst = req_trst;
+	(*last_cmd)->cmd.reset->srst = req_srst;
+
+	jtag_trst = req_trst;
+	jtag_srst = req_srst;
+
+	if (jtag_srst)
+	{
+		jtag_call_event_callbacks(JTAG_SRST_ASSERTED);
+	}
+	else
+	{
+		jtag_call_event_callbacks(JTAG_SRST_RELEASED);
+		if (jtag_nsrst_delay)
+			jtag_add_sleep(jtag_nsrst_delay * 1000);
+	}
+	
+	if (trst_with_tms)
+	{
+		last_cmd = &((*last_cmd)->next);
+		
+		/* allocate memory for a new list member */
+		*last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
+		(*last_cmd)->next = NULL;
+		last_comand_pointer = &((*last_cmd)->next);
+		(*last_cmd)->type = JTAG_STATEMOVE;
+
+		(*last_cmd)->cmd.statemove = cmd_queue_alloc(sizeof(statemove_command_t));
+		(*last_cmd)->cmd.statemove->end_state = TAP_TLR;
+		
+		jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
+		cmd_queue_cur_state = TAP_TLR;
+		cmd_queue_end_state = TAP_TLR;
+		
+		return ERROR_OK;
+	}
+	else
+	{
+		if (jtag_trst)
+		{
+			/* we just asserted nTRST, so we're now in Test-Logic-Reset,
+			 * and inform possible listeners about this
+			 */
+			cmd_queue_cur_state = TAP_TLR;
+			jtag_call_event_callbacks(JTAG_TRST_ASSERTED);
+		}
+		else
+		{
+			/* the nTRST line got deasserted, so we're still in Test-Logic-Reset,
+			 * but we might want to add a delay to give the TAP time to settle
+			 */
+			if (jtag_ntrst_delay)
+				jtag_add_sleep(jtag_ntrst_delay * 1000);
+		}
+	}
+
+	return ERROR_OK;
+}
+
+int jtag_add_end_state(enum tap_state state)
+{
+	jtag_command_t **last_cmd = jtag_get_last_command_p();
+	
+	/* allocate memory for a new list member */
+	*last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
+	(*last_cmd)->next = NULL;
+	last_comand_pointer = &((*last_cmd)->next);
+	(*last_cmd)->type = JTAG_END_STATE;
+
+	(*last_cmd)->cmd.end_state = cmd_queue_alloc(sizeof(end_state_command_t));
+	(*last_cmd)->cmd.end_state->end_state = state;
+
+	if (state != -1)
+		cmd_queue_end_state = state;
+	
+	return ERROR_OK;
+}
+
+int jtag_add_sleep(u32 us)
+{
+	jtag_command_t **last_cmd = jtag_get_last_command_p();
+	
+	/* allocate memory for a new list member */
+	*last_cmd = cmd_queue_alloc(sizeof(jtag_command_t));
+	(*last_cmd)->next = NULL;
+	last_comand_pointer = &((*last_cmd)->next);
+	(*last_cmd)->type = JTAG_SLEEP;
+
+	(*last_cmd)->cmd.sleep = cmd_queue_alloc(sizeof(sleep_command_t));
+	(*last_cmd)->cmd.sleep->us = us;
+	
+	return ERROR_OK;
+}
+
+int jtag_scan_size(scan_command_t *cmd)
+{
+	int bit_count = 0;
+	int i;
+
+	/* count bits in scan command */
+	for (i = 0; i < cmd->num_fields; i++)
+	{
+		bit_count += cmd->fields[i].num_bits;
+	}
+
+	return bit_count;
+}
+
+int jtag_build_buffer(scan_command_t *cmd, u8 **buffer)
+{
+	int bit_count = 0;
+	int i;
+	
+	bit_count = jtag_scan_size(cmd);
+	*buffer = malloc(CEIL(bit_count, 8));
+	
+	bit_count = 0;
+
+	for (i = 0; i < cmd->num_fields; i++)
+	{
+		if (cmd->fields[i].out_value)
+		{
+#ifdef _DEBUG_JTAG_IO_
+			char* char_buf = buf_to_str(cmd->fields[i].out_value, (cmd->fields[i].num_bits > 64) ? 64 : cmd->fields[i].num_bits, 16);
+#endif
+			buf_set_buf(cmd->fields[i].out_value, 0, *buffer, bit_count, cmd->fields[i].num_bits);
+#ifdef _DEBUG_JTAG_IO_
+			DEBUG("fields[%i].out_value: 0x%s", i, char_buf);
+			free(char_buf);
+#endif
+		}
+		
+		bit_count += cmd->fields[i].num_bits;
+	}
+
+	return bit_count;
+
+}
+
+int jtag_read_buffer(u8 *buffer, scan_command_t *cmd)
+{
+	int i;
+	int bit_count = 0;
+	int retval;
+	
+	/* we return ERROR_OK, unless a check fails, or a handler reports a problem */
+	retval = ERROR_OK;
+	
+	for (i = 0; i < cmd->num_fields; i++)
+	{
+		/* if neither in_value nor in_handler
+		 * are specified we don't have to examine this field
+		 */
+		if (cmd->fields[i].in_value || cmd->fields[i].in_handler)
+		{
+			int num_bits = cmd->fields[i].num_bits;
+			u8 *captured = buf_set_buf(buffer, bit_count, malloc(CEIL(num_bits, 8)), 0, num_bits);
+			
+#ifdef _DEBUG_JTAG_IO_
+			char *char_buf;
+
+			char_buf = buf_to_str(captured, (num_bits > 64) ? 64 : num_bits, 16);
+			DEBUG("fields[%i].in_value: 0x%s", i, char_buf);
+			free(char_buf);
+#endif
+			
+			if (cmd->fields[i].in_value)
+			{
+				buf_cpy(captured, cmd->fields[i].in_value, num_bits);
+				
+				if (cmd->fields[i].in_handler)
+				{
+					if (cmd->fields[i].in_handler(cmd->fields[i].in_value, cmd->fields[i].in_handler_priv, cmd->fields+i) != ERROR_OK)
+					{
+						WARNING("in_handler reported a failed check");
+						retval = ERROR_JTAG_QUEUE_FAILED;
+					}
+				}
+			}
+			
+			/* no in_value specified, but a handler takes care of the scanned data */
+			if (cmd->fields[i].in_handler && (!cmd->fields[i].in_value))
+			{
+				if (cmd->fields[i].in_handler(captured, cmd->fields[i].in_handler_priv, cmd->fields+i) != ERROR_OK)
+				{
+					/* We're going to call the error:handler later, but if the in_handler
+					 * reported an error we report this failure upstream
+					 */
+					WARNING("in_handler reported a failed check");
+					retval = ERROR_JTAG_QUEUE_FAILED;
+				}
+			}
+
+			free(captured);
+		}
+		bit_count += cmd->fields[i].num_bits;
+	}
+
+	return retval;
+}
+
+int jtag_check_value(u8 *captured, void *priv, scan_field_t *field)
+{
+	int retval = ERROR_OK;
+	int num_bits = field->num_bits;
+	
+	int compare_failed = 0;
+	
+	if (field->in_check_mask)
+		compare_failed = buf_cmp_mask(captured, field->in_check_value, field->in_check_mask, num_bits);
+	else
+		compare_failed = buf_cmp(captured, field->in_check_value, num_bits);
+	
+	if (compare_failed)
+		{
+		/* An error handler could have caught the failing check
+		 * only report a problem when there wasn't a handler, or if the handler
+		 * acknowledged the error
+		 */ 
+		if (compare_failed)
+		{
+			char *captured_char = buf_to_str(captured, (num_bits > 64) ? 64 : num_bits, 16);
+			char *in_check_value_char = buf_to_str(field->in_check_value, (num_bits > 64) ? 64 : num_bits, 16);
+
+			if (field->in_check_mask)
+			{
+				char *in_check_mask_char;
+				in_check_mask_char = buf_to_str(field->in_check_mask, (num_bits > 64) ? 64 : num_bits, 16);
+				WARNING("value captured during scan didn't pass the requested check: captured: 0x%s check_value: 0x%s check_mask: 0x%s", captured_char, in_check_value_char, in_check_mask_char);
+				free(in_check_mask_char);
+			}
+			else
+			{
+				WARNING("value captured during scan didn't pass the requested check: captured: 0x%s check_value: 0x%s", captured_char, in_check_value_char);
+			}
+
+			free(captured_char);
+			free(in_check_value_char);
+			
+			retval = ERROR_JTAG_QUEUE_FAILED;
+		}
+		
+	}
+	return retval;
+}
+
+/* 
+  set up checking of this field using the in_handler. The values passed in must be valid until
+  after jtag_execute() has completed.
+ */
+void jtag_set_check_value(scan_field_t *field, u8 *value, u8 *mask, error_handler_t *in_error_handler)
+{
+	if (value)
+		field->in_handler = jtag_check_value;
+	else
+		field->in_handler = NULL;	/* No check, e.g. embeddedice uses value==NULL to indicate no check */
+	field->in_handler_priv = NULL;	/* this will be filled in at the invocation site to point to the field duplicate */ 
+	field->in_check_value = value;
+	field->in_check_mask = mask;
+}
+
+enum scan_type jtag_scan_type(scan_command_t *cmd)
+{
+	int i;
+	int type = 0;
+	
+	for (i = 0; i < cmd->num_fields; i++)
+	{
+		if (cmd->fields[i].in_value || cmd->fields[i].in_handler)
+			type |= SCAN_IN;
+		if (cmd->fields[i].out_value)
+			type |= SCAN_OUT;
+	}
+
+	return type;
+}
+
+int jtag_execute_queue(void)
+{
+	int retval;
+
+	retval = jtag->execute_queue();
+	
+	cmd_queue_free();
+
+	jtag_command_queue = NULL;
+	last_comand_pointer = &jtag_command_queue;
+
+	return retval;
+}
+
+int jtag_reset_callback(enum jtag_event event, void *priv)
+{
+	jtag_device_t *device = priv;
+
+	DEBUG("-");
+	
+	if (event == JTAG_TRST_ASSERTED)
+	{
+		buf_set_ones(device->cur_instr, device->ir_length);
+		device->bypass = 1;
+	}
+	
+	return ERROR_OK;
+}
+
+void jtag_sleep(u32 us)
+{
+	usleep(us);
+}
+
+/* Try to examine chain layout according to IEEE 1149.1 §12
+ */
+int jtag_examine_chain()
+{
+	jtag_device_t *device = jtag_devices;
+	scan_field_t field;
+	u8 idcode_buffer[JTAG_MAX_CHAIN_SIZE * 4];
+	int i;
+	int bit_count;
+	int device_count = 0;
+	u8 zero_check = 0x0;
+	u8 one_check = 0xff;
+	
+	field.device = 0;
+	field.num_bits = sizeof(idcode_buffer) * 8;
+	field.out_value = idcode_buffer;
+	field.out_mask = NULL;
+	field.in_value = idcode_buffer;
+	field.in_check_value = NULL;
+	field.in_check_mask = NULL;
+	field.in_handler = NULL;
+	field.in_handler_priv = NULL;
+	
+	for (i = 0; i < JTAG_MAX_CHAIN_SIZE; i++)
+	{
+		buf_set_u32(idcode_buffer, i * 32, 32, 0x000000FF);
+	}
+	
+	jtag_add_plain_dr_scan(1, &field, TAP_TLR);
+	jtag_execute_queue();
+	
+	for (i = 0; i < JTAG_MAX_CHAIN_SIZE * 4; i++)
+	{
+		zero_check |= idcode_buffer[i];
+		one_check &= idcode_buffer[i];
+	}
+	
+	/* if there wasn't a single non-zero bit or if all bits were one, the scan isn't valid */
+	if ((zero_check == 0x00) || (one_check == 0xff))
+	{
+		ERROR("JTAG communication failure, check connection, JTAG interface, target power etc.");
+		return ERROR_JTAG_INIT_FAILED;
+	}
+	
+	for (bit_count = 0; bit_count < (JTAG_MAX_CHAIN_SIZE * 32) - 31;)
+	{
+		u32 idcode = buf_get_u32(idcode_buffer, bit_count, 32);
+		if ((idcode & 1) == 0)
+		{
+			/* LSB must not be 0, this indicates a device in bypass */
+			device_count++;
+			
+			bit_count += 1;
+		}
+		else
+		{
+			u32 manufacturer;
+			u32 part;
+			u32 version;
+			
+			if (idcode == 0x000000FF)
+			{
+				/* End of chain (invalid manufacturer ID) */
+				break;
+			}
+			
+			if (device)
+			{
+				device->idcode = idcode;
+				device = device->next;
+			}
+			device_count++;
+			
+			manufacturer = (idcode & 0xffe) >> 1;
+			part = (idcode & 0xffff000) >> 12;
+			version = (idcode & 0xf0000000) >> 28;
+
+			INFO("JTAG device found: 0x%8.8x (Manufacturer: 0x%3.3x, Part: 0x%4.4x, Version: 0x%1.1x)", 
+				idcode, manufacturer, part, version);
+			
+			bit_count += 32;
+		}
+	}
+	
+	/* see if number of discovered devices matches configuration */
+	if (device_count != jtag_num_devices)
+	{
+		ERROR("number of discovered devices in JTAG chain (%i) doesn't match configuration (%i)", 
+			device_count, jtag_num_devices);
+		ERROR("check the config file and ensure proper JTAG communication (connections, speed, ...)");
+		return ERROR_JTAG_INIT_FAILED;
+	}
+	
+	return ERROR_OK;
+}
+
+int jtag_validate_chain()
+{
+	jtag_device_t *device = jtag_devices;
+	int total_ir_length = 0;
+	u8 *ir_test = NULL;
+	scan_field_t field;
+	int chain_pos = 0;
+	
+	while (device)
+	{
+		total_ir_length += device->ir_length;
+		device = device->next;
+	}
+	
+	total_ir_length += 2;
+	ir_test = malloc(CEIL(total_ir_length, 8));
+	buf_set_ones(ir_test, total_ir_length);
+	
+	field.device = 0;
+	field.num_bits = total_ir_length;
+	field.out_value = ir_test;
+	field.out_mask = NULL;
+	field.in_value = ir_test;
+	field.in_check_value = NULL;
+	field.in_check_mask = NULL;
+	field.in_handler = NULL;
+	field.in_handler_priv = NULL;
+	
+	jtag_add_plain_ir_scan(1, &field, TAP_TLR);
+	jtag_execute_queue();
+	
+	device = jtag_devices;
+	while (device)
+	{
+		if (buf_get_u32(ir_test, chain_pos, 2) != 0x1)
+		{
+			char *cbuf = buf_to_str(ir_test, total_ir_length, 16);
+			ERROR("Error validating JTAG scan chain, IR mismatch, scan returned 0x%s", cbuf);
+			free(cbuf);
+			free(ir_test);
+			return ERROR_JTAG_INIT_FAILED;
+		}
+		chain_pos += device->ir_length;
+		device = device->next;
+	}
+	
+	if (buf_get_u32(ir_test, chain_pos, 2) != 0x3)
+	{
+		char *cbuf = buf_to_str(ir_test, total_ir_length, 16);
+		ERROR("Error validating JTAG scan chain, IR mismatch, scan returned 0x%s", cbuf);
+		free(cbuf);
+		free(ir_test);
+		return ERROR_JTAG_INIT_FAILED;
+	}
+	
+	free(ir_test);
+	
+	return ERROR_OK;
+}
+
+int jtag_register_commands(struct command_context_s *cmd_ctx)
+{
+	register_command(cmd_ctx, NULL, "interface", handle_interface_command,
+		COMMAND_CONFIG, NULL);
+	register_command(cmd_ctx, NULL, "jtag_speed", handle_jtag_speed_command,
+		COMMAND_ANY, "set jtag speed (if supported) <speed>");
+	register_command(cmd_ctx, NULL, "jtag_device", handle_jtag_device_command,
+		COMMAND_CONFIG, "jtag_device <ir_length> <ir_expected> <ir_mask>");
+	register_command(cmd_ctx, NULL, "reset_config", handle_reset_config_command,
+		COMMAND_CONFIG, NULL);
+	register_command(cmd_ctx, NULL, "jtag_nsrst_delay", handle_jtag_nsrst_delay_command,
+		COMMAND_CONFIG, NULL);
+	register_command(cmd_ctx, NULL, "jtag_ntrst_delay", handle_jtag_ntrst_delay_command,
+		COMMAND_CONFIG, NULL);
+		
+	register_command(cmd_ctx, NULL, "scan_chain", handle_scan_chain_command,
+		COMMAND_EXEC, "print current scan chain configuration");
+
+	register_command(cmd_ctx, NULL, "endstate", handle_endstate_command,
+		COMMAND_EXEC, "finish JTAG operations in <tap_state>");
+	register_command(cmd_ctx, NULL, "jtag_reset", handle_jtag_reset_command,
+		COMMAND_EXEC, "toggle reset lines <trst> <srst>");
+	register_command(cmd_ctx, NULL, "runtest", handle_runtest_command,
+		COMMAND_EXEC, "move to Run-Test/Idle, and execute <num_cycles>");
+	register_command(cmd_ctx, NULL, "statemove", handle_statemove_command,
+		COMMAND_EXEC, "move to current endstate or [tap_state]");
+	register_command(cmd_ctx, NULL, "irscan", handle_irscan_command,
+		COMMAND_EXEC, "execute IR scan <device> <instr> [dev2] [instr2] ...");
+	register_command(cmd_ctx, NULL, "drscan", handle_drscan_command,
+		COMMAND_EXEC, "execute DR scan <device> <var> [dev2] [var2] ...");
+
+	register_command(cmd_ctx, NULL, "verify_ircapture", handle_verify_ircapture_command,
+		COMMAND_ANY, "verify value captured during Capture-IR <enable|disable>");
+	return ERROR_OK;
+}
+
+int jtag_init(struct command_context_s *cmd_ctx)
+{
+	int i, validate_tries = 0;
+	
+	DEBUG("-");
+
+	if (jtag_speed == -1)
+		jtag_speed = 0;
+	
+	if (jtag_interface && (jtag_interface[0] != 0))
+		/* configuration var 'jtag_interface' is set, and not empty */
+		for (i = 0; jtag_interfaces[i]; i++)
+		{
+			if (strcmp(jtag_interface, jtag_interfaces[i]->name) == 0)
+			{
+				jtag_device_t *device;
+				device = jtag_devices;
+	
+				if (jtag_interfaces[i]->init() != ERROR_OK)
+					return ERROR_JTAG_INIT_FAILED;
+				jtag = jtag_interfaces[i];
+
+				jtag_ir_scan_size = 0;
+				jtag_num_devices = 0;
+				while (device != NULL)
+				{
+					jtag_ir_scan_size += device->ir_length;
+					jtag_num_devices++;
+					device = device->next;
+				}
+				
+				jtag_add_statemove(TAP_TLR);
+				jtag_execute_queue();
+
+				/* examine chain first, as this could discover the real chain layout */
+				if (jtag_examine_chain() != ERROR_OK)
+				{
+					ERROR("trying to validate configured JTAG chain anyway...");
+				}
+				
+				while (jtag_validate_chain() != ERROR_OK)
+				{
+					validate_tries++;
+					if (validate_tries > 5)
+					{
+						ERROR("Could not validate JTAG chain, exit");
+						jtag = NULL;
+						return ERROR_JTAG_INVALID_INTERFACE;
+					}
+					usleep(10000);
+				}
+
+				return ERROR_OK;
+			}
+		}
+	
+	/* no valid interface was found (i.e. the configuration option,
+	 * didn't match one of the compiled-in interfaces
+	 */
+	ERROR("No valid jtag interface found (%s)", jtag_interface);
+	ERROR("compiled-in jtag interfaces:");
+	for (i = 0; jtag_interfaces[i]; i++)
+	{
+		ERROR("%i: %s", i, jtag_interfaces[i]->name);
+	}
+	
+	jtag = NULL;
+	return ERROR_JTAG_INVALID_INTERFACE;
+}
+
+int handle_interface_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	int i;
+	
+	/* only if the configuration var isn't overwritten from cmdline */
+	if (!jtag_interface)
+	{
+		if (args[0] && (args[0][0] != 0))
+		{
+			for (i=0; jtag_interfaces[i]; i++)
+			{
+				if (strcmp(args[0], jtag_interfaces[i]->name) == 0)
+				{
+					if (jtag_interfaces[i]->register_commands(cmd_ctx) != ERROR_OK)
+						exit(-1);
+				
+					jtag_interface = jtag_interfaces[i]->name;
+		
+					return ERROR_OK;
+				}
+			}
+		}
+		
+		/* remember the requested interface name, so we can complain about it later */
+		jtag_interface = strdup(args[0]);
+		DEBUG("'interface' command didn't specify a valid interface");
+	}
+	
+	return ERROR_OK;
+}
+
+int handle_jtag_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	jtag_device_t **last_device_p = &jtag_devices;
+
+	if (*last_device_p)
+	{
+		while ((*last_device_p)->next)
+			last_device_p = &((*last_device_p)->next);
+		last_device_p = &((*last_device_p)->next);
+	}
+
+	if (argc < 3)
+		return ERROR_OK;
+
+	*last_device_p = malloc(sizeof(jtag_device_t));
+	(*last_device_p)->ir_length = strtoul(args[0], NULL, 0);
+
+	(*last_device_p)->expected = malloc((*last_device_p)->ir_length);
+	buf_set_u32((*last_device_p)->expected, 0, (*last_device_p)->ir_length, strtoul(args[1], NULL, 0));
+	(*last_device_p)->expected_mask = malloc((*last_device_p)->ir_length);
+	buf_set_u32((*last_device_p)->expected_mask, 0, (*last_device_p)->ir_length, strtoul(args[2], NULL, 0));
+
+	(*last_device_p)->cur_instr = malloc((*last_device_p)->ir_length);
+	(*last_device_p)->bypass = 1;
+	buf_set_ones((*last_device_p)->cur_instr, (*last_device_p)->ir_length);
+	
+	(*last_device_p)->next = NULL;
+	
+	jtag_register_event_callback(jtag_reset_callback, (*last_device_p));
+	
+	jtag_num_devices++;
+
+	return ERROR_OK;
+}
+
+int handle_scan_chain_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	jtag_device_t *device = jtag_devices;
+	int device_count = 0;
+	
+	while (device)
+	{
+		u32 expected, expected_mask, cur_instr;
+		expected = buf_get_u32(device->expected, 0, device->ir_length);
+		expected_mask = buf_get_u32(device->expected_mask, 0, device->ir_length);
+		cur_instr = buf_get_u32(device->cur_instr, 0, device->ir_length);
+		command_print(cmd_ctx, "%i: idcode: 0x%8.8x ir length %i, ir capture 0x%x, ir mask 0x%x, current instruction 0x%x", device_count, device->idcode, device->ir_length, expected, expected_mask, cur_instr);
+		device = device->next;
+		device_count++;
+	}
+
+	return ERROR_OK;
+}
+
+int handle_reset_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	if (argc >= 1)
+	{
+		if (strcmp(args[0], "none") == 0)
+			jtag_reset_config = RESET_NONE;
+		else if (strcmp(args[0], "trst_only") == 0)
+			jtag_reset_config = RESET_HAS_TRST;
+		else if (strcmp(args[0], "srst_only") == 0)
+			jtag_reset_config = RESET_HAS_SRST;
+		else if (strcmp(args[0], "trst_and_srst") == 0)
+			jtag_reset_config = RESET_TRST_AND_SRST;
+		else
+		{
+			ERROR("invalid reset_config argument, defaulting to none");
+			jtag_reset_config = RESET_NONE;
+			return ERROR_INVALID_ARGUMENTS;
+		}
+	}
+	
+	if (argc >= 2)
+	{
+		if (strcmp(args[1], "srst_pulls_trst") == 0)
+			jtag_reset_config |= RESET_SRST_PULLS_TRST;
+		else if (strcmp(args[1], "trst_pulls_srst") == 0)
+			jtag_reset_config |= RESET_TRST_PULLS_SRST;
+		else if (strcmp(args[1], "combined") == 0)
+			jtag_reset_config |= RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST;
+		else if (strcmp(args[1], "separate") == 0)
+			jtag_reset_config &= ~(RESET_SRST_PULLS_TRST | RESET_TRST_PULLS_SRST);
+		else
+		{
+			ERROR("invalid reset_config argument, defaulting to none");
+			jtag_reset_config = RESET_NONE;
+			return ERROR_INVALID_ARGUMENTS;
+		}
+	}
+	
+	if (argc >= 3)
+	{
+		if (strcmp(args[2], "trst_open_drain") == 0)
+			jtag_reset_config |= RESET_TRST_OPEN_DRAIN;
+		else if (strcmp(args[2], "trst_push_pull") == 0)
+			jtag_reset_config &= ~RESET_TRST_OPEN_DRAIN;
+		else
+		{
+			ERROR("invalid reset_config argument, defaulting to none");
+			jtag_reset_config = RESET_NONE;
+			return ERROR_INVALID_ARGUMENTS;
+		}
+	}
+
+	if (argc >= 4)
+	{
+		if (strcmp(args[3], "srst_push_pull") == 0)
+			jtag_reset_config |= RESET_SRST_PUSH_PULL;
+		else if (strcmp(args[3], "srst_open_drain") == 0)
+			jtag_reset_config &= ~RESET_SRST_PUSH_PULL;
+		else
+		{
+			ERROR("invalid reset_config argument, defaulting to none");
+			jtag_reset_config = RESET_NONE;
+			return ERROR_INVALID_ARGUMENTS;
+		}
+	}
+	
+	return ERROR_OK;
+}
+
+int handle_jtag_nsrst_delay_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	if (argc < 1)
+	{
+		ERROR("jtag_nsrst_delay <ms> command takes one required argument");
+		exit(-1);
+	}
+	else
+	{
+		jtag_nsrst_delay = strtoul(args[0], NULL, 0);
+	}
+	
+	return ERROR_OK;
+}
+
+int handle_jtag_ntrst_delay_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	if (argc < 1)
+	{
+		ERROR("jtag_ntrst_delay <ms> command takes one required argument");
+		exit(-1);
+	}
+	else
+	{
+		jtag_ntrst_delay = strtoul(args[0], NULL, 0);
+	}
+	
+	return ERROR_OK;
+}
+
+int handle_jtag_speed_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	if (argc == 0)
+		command_print(cmd_ctx, "jtag_speed: %i", jtag_speed);
+
+	if (argc > 0)
+	{
+		/* this command can be called during CONFIG, 
+		 * in which case jtag isn't initialized */
+		if (jtag)
+			jtag->speed(strtoul(args[0], NULL, 0));
+		else
+			jtag_speed = strtoul(args[0], NULL, 0);
+	}
+
+	return ERROR_OK;
+}
+
+int handle_endstate_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	enum tap_state state;
+
+	if (argc < 1)
+	{
 		return ERROR_COMMAND_SYNTAX_ERROR;
-	}
-	else
-	{
-		for (state = 0; state < 16; state++)
-		{
-			if (strcmp(args[0], tap_state_strings[state]) == 0)
-			{
-				jtag_add_end_state(state);
-				jtag_execute_queue();
-			}
-		}
-	}
-	command_print(cmd_ctx, "current endstate: %s", tap_state_strings[end_state]);
-	
-	return ERROR_OK;
-}
-
-int handle_jtag_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	int trst = -1;
-	int srst = -1;
-	int retval;
-	
-	if (argc < 1)
-	{
+	}
+	else
+	{
+		for (state = 0; state < 16; state++)
+		{
+			if (strcmp(args[0], tap_state_strings[state]) == 0)
+			{
+				jtag_add_end_state(state);
+				jtag_execute_queue();
+			}
+		}
+	}
+	command_print(cmd_ctx, "current endstate: %s", tap_state_strings[end_state]);
+	
+	return ERROR_OK;
+}
+
+int handle_jtag_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	int trst = -1;
+	int srst = -1;
+	int retval;
+	
+	if (argc < 1)
+	{
 		return ERROR_COMMAND_SYNTAX_ERROR;
 
-	}
-
-	if (args[0][0] == '1')
-		trst = 1;
-	else if (args[0][0] == '0')
-		trst = 0;
-	else
-	{
+	}
+
+	if (args[0][0] == '1')
+		trst = 1;
+	else if (args[0][0] == '0')
+		trst = 0;
+	else
+	{
 		return ERROR_COMMAND_SYNTAX_ERROR;
-	}
-
-	if (args[1][0] == '1')
-		srst = 1;
-	else if (args[1][0] == '0')
-		srst = 0;
-	else
-	{
+	}
+
+	if (args[1][0] == '1')
+		srst = 1;
+	else if (args[1][0] == '0')
+		srst = 0;
+	else
+	{
 		return ERROR_COMMAND_SYNTAX_ERROR;
-	}
-
-	if ((retval = jtag_add_reset(trst, srst)) != ERROR_OK)
-	{
-		switch (retval)
-		{
-			case ERROR_JTAG_RESET_WOULD_ASSERT_TRST:
-				command_print(cmd_ctx, "requested reset would assert trst\nif this is acceptable, use jtag_reset 1 %c", args[1][0]);
-				break;
-			case ERROR_JTAG_RESET_CANT_SRST:
-				command_print(cmd_ctx, "can't assert srst because the current reset_config doesn't support it");
-				break;
-			default:
-				command_print(cmd_ctx, "unknown error");
-		}
-	}
-	jtag_execute_queue();
-
-	return ERROR_OK;
-}
-
-int handle_runtest_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	if (argc < 1)
-	{
+	}
+
+	if ((retval = jtag_add_reset(trst, srst)) != ERROR_OK)
+	{
+		switch (retval)
+		{
+			case ERROR_JTAG_RESET_WOULD_ASSERT_TRST:
+				command_print(cmd_ctx, "requested reset would assert trst\nif this is acceptable, use jtag_reset 1 %c", args[1][0]);
+				break;
+			case ERROR_JTAG_RESET_CANT_SRST:
+				command_print(cmd_ctx, "can't assert srst because the current reset_config doesn't support it");
+				break;
+			default:
+				command_print(cmd_ctx, "unknown error");
+		}
+	}
+	jtag_execute_queue();
+
+	return ERROR_OK;
+}
+
+int handle_runtest_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	if (argc < 1)
+	{
 		return ERROR_COMMAND_SYNTAX_ERROR;
-	}
-
-	jtag_add_runtest(strtol(args[0], NULL, 0), -1);
-	jtag_execute_queue();
-
-	return ERROR_OK;
-
-}
-
-int handle_statemove_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	enum tap_state state;
-
-	state = -1;
-	if (argc == 1)
-	{
-		for (state = 0; state < 16; state++)
-		{
-			if (strcmp(args[0], tap_state_strings[state]) == 0)
-			{
-				break;
-			}
-		}
-	}
-
-	jtag_add_statemove(state);
-	jtag_execute_queue();
-
-	return ERROR_OK;
-
-}
-
-int handle_irscan_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	int i;
-	scan_field_t *fields;
-	
-	if ((argc < 2) || (argc % 2))
-	{
+	}
+
+	jtag_add_runtest(strtol(args[0], NULL, 0), -1);
+	jtag_execute_queue();
+
+	return ERROR_OK;
+
+}
+
+int handle_statemove_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	enum tap_state state;
+
+	state = -1;
+	if (argc == 1)
+	{
+		for (state = 0; state < 16; state++)
+		{
+			if (strcmp(args[0], tap_state_strings[state]) == 0)
+			{
+				break;
+			}
+		}
+	}
+
+	jtag_add_statemove(state);
+	jtag_execute_queue();
+
+	return ERROR_OK;
+
+}
+
+int handle_irscan_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	int i;
+	scan_field_t *fields;
+	
+	if ((argc < 2) || (argc % 2))
+	{
 		return ERROR_COMMAND_SYNTAX_ERROR;
-	}
-
-	fields = malloc(sizeof(scan_field_t) * argc / 2);
-	
-	for (i = 0; i < argc / 2; i++)
-	{
-		int device = strtoul(args[i*2], NULL, 0);
-		int field_size = jtag_get_device(device)->ir_length;
-		fields[i].device = device;
-		fields[i].out_value = malloc(CEIL(field_size, 8));
-		buf_set_u32(fields[i].out_value, 0, field_size, strtoul(args[i*2+1], NULL, 0));
-		fields[i].out_mask = NULL;
-		fields[i].in_value = NULL;
-		fields[i].in_check_mask = NULL;
-		fields[i].in_handler = NULL;
-		fields[i].in_handler_priv = NULL;
-	}
-
-	jtag_add_ir_scan(argc / 2, fields, -1, NULL);
-	jtag_execute_queue();
-
-	for (i = 0; i < argc / 2; i++)
-		free(fields[i].out_value);
-
-	free (fields);
-
-	return ERROR_OK;
-}
-
-int handle_drscan_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	scan_field_t *fields;
-	int num_fields = 0;
-	int field_count = 0;
-	var_t *var;
-	int i, j;
-	
-	if ((argc < 2) || (argc % 2))
-	{
+	}
+
+	fields = malloc(sizeof(scan_field_t) * argc / 2);
+	
+	for (i = 0; i < argc / 2; i++)
+	{
+		int device = strtoul(args[i*2], NULL, 0);
+		int field_size = jtag_get_device(device)->ir_length;
+		fields[i].device = device;
+		fields[i].out_value = malloc(CEIL(field_size, 8));
+		buf_set_u32(fields[i].out_value, 0, field_size, strtoul(args[i*2+1], NULL, 0));
+		fields[i].out_mask = NULL;
+		fields[i].in_value = NULL;
+		fields[i].in_check_mask = NULL;
+		fields[i].in_handler = NULL;
+		fields[i].in_handler_priv = NULL;
+	}
+
+	jtag_add_ir_scan(argc / 2, fields, -1);
+	jtag_execute_queue();
+
+	for (i = 0; i < argc / 2; i++)
+		free(fields[i].out_value);
+
+	free (fields);
+
+	return ERROR_OK;
+}
+
+int handle_drscan_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	scan_field_t *fields;
+	int num_fields = 0;
+	int field_count = 0;
+	var_t *var;
+	int i, j;
+	
+	if ((argc < 2) || (argc % 2))
+	{
 		return ERROR_COMMAND_SYNTAX_ERROR;
-	}
-
-	for (i = 0; i < argc; i+=2)
-	{
-		var = get_var_by_namenum(args[i+1]);
-		if (var)
-		{
-			num_fields += var->num_fields;
-		}
-		else
-		{
-			command_print(cmd_ctx, "variable %s doesn't exist", args[i+1]);
-			return ERROR_OK;
-		}
-	}
-
-	fields = malloc(sizeof(scan_field_t) * num_fields);
-
-	for (i = 0; i < argc; i+=2)
-	{
-		var = get_var_by_namenum(args[i+1]);
-	
-		for (j = 0; j < var->num_fields; j++)
-		{
-			fields[field_count].device = strtol(args[i], NULL, 0);
-			fields[field_count].num_bits = var->fields[j].num_bits;
-			fields[field_count].out_value = malloc(CEIL(var->fields[j].num_bits, 8));
-			buf_set_u32(fields[field_count].out_value, 0, var->fields[j].num_bits, var->fields[j].value);
-			fields[field_count].out_mask = NULL;
-			fields[field_count].in_value = fields[field_count].out_value;
-			fields[field_count].in_check_mask = NULL;
-			fields[field_count].in_check_value = NULL;
-			fields[field_count].in_handler = field_le_to_host;
-			fields[field_count++].in_handler_priv = &(var->fields[j]);
-		}
-	}
-
-	jtag_add_dr_scan(num_fields, fields, -1, NULL);
-	jtag_execute_queue();
-	
-	for (i = 0; i < argc / 2; i++)
-		free(fields[i].out_value);
-
-	free(fields);
-
-	return ERROR_OK;
-}
-
-int handle_verify_ircapture_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
+	}
+
+	for (i = 0; i < argc; i+=2)
+	{
+		var = get_var_by_namenum(args[i+1]);
+		if (var)
+		{
+			num_fields += var->num_fields;
+		}
+		else
+		{
+			command_print(cmd_ctx, "variable %s doesn't exist", args[i+1]);
+			return ERROR_OK;
+		}
+	}
+
+	fields = malloc(sizeof(scan_field_t) * num_fields);
+
+	for (i = 0; i < argc; i+=2)
+	{
+		var = get_var_by_namenum(args[i+1]);
+	
+		for (j = 0; j < var->num_fields; j++)
+		{
+			fields[field_count].device = strtol(args[i], NULL, 0);
+			fields[field_count].num_bits = var->fields[j].num_bits;
+			fields[field_count].out_value = malloc(CEIL(var->fields[j].num_bits, 8));
+			buf_set_u32(fields[field_count].out_value, 0, var->fields[j].num_bits, var->fields[j].value);
+			fields[field_count].out_mask = NULL;
+			fields[field_count].in_value = fields[field_count].out_value;
+			fields[field_count].in_check_mask = NULL;
+			fields[field_count].in_check_value = NULL;
+			fields[field_count].in_handler = field_le_to_host;
+			fields[field_count++].in_handler_priv = &(var->fields[j]);
+		}
+	}
+
+	jtag_add_dr_scan(num_fields, fields, -1);
+	jtag_execute_queue();
+	
+	for (i = 0; i < argc / 2; i++)
+		free(fields[i].out_value);
+
+	free(fields);
+
+	return ERROR_OK;
+}
+
+int handle_verify_ircapture_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
 	if (argc == 1)
-	{
-		if (strcmp(args[0], "enable") == 0)
-		{
-			jtag_verify_capture_ir = 1;
-		}
-		else if (strcmp(args[0], "disable") == 0)
-		{
-			jtag_verify_capture_ir = 0;
+	{
+		if (strcmp(args[0], "enable") == 0)
+		{
+			jtag_verify_capture_ir = 1;
+		}
+		else if (strcmp(args[0], "disable") == 0)
+		{
+			jtag_verify_capture_ir = 0;
 		} else
 		{
 			return ERROR_COMMAND_SYNTAX_ERROR;
-		}
+		}
 	} else if (argc != 0)
 	{
 		return ERROR_COMMAND_SYNTAX_ERROR;
 	}
 	
 	command_print(cmd_ctx, "verify Capture-IR is %s", (jtag_verify_capture_ir) ? "enabled": "disabled");
-	
-	return ERROR_OK;
-}
+	
+	return ERROR_OK;
+}
diff --git a/src/jtag/jtag.h b/src/jtag/jtag.h
index e5df6619bf67808152c1be17bff5b72f3d0be6e8..0e48a020273781da4b6a0a3d894b2998a69f6b3d 100644
--- a/src/jtag/jtag.h
+++ b/src/jtag/jtag.h
@@ -1,327 +1,327 @@
-/***************************************************************************
- *   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 JTAG_H
-#define JTAG_H
-
-#include "types.h"
-#include "binarybuffer.h"
-
-#include "command.h"
-
-#if 0
-#define _DEBUG_JTAG_IO_
-#endif
-
-/* Tap States
- * TLR - Test-Logic-Reset, RTI - Run-Test/Idle, 
- * SDS - Select-DR-Scan, CD - Capture-DR, SD - Shift-DR, E1D - Exit1-DR,
- * PD - Pause-DR, E2D - Exit2-DR, UD - Update-DR,
- * SIS - Select-IR-Scan, CI - Capture-IR, SI - Shift-IR, E1I - Exit1-IR,
- * PI - Pause-IR, E2I - Exit2-IR, UI - Update-IR 
- */
-enum tap_state
-{
-	TAP_TLR = 0x0, TAP_RTI = 0x8, 
-	TAP_SDS = 0x1, TAP_CD = 0x2, TAP_SD = 0x3, TAP_E1D = 0x4, 
-	TAP_PD = 0x5, TAP_E2D = 0x6, TAP_UD = 0x7,
-	TAP_SIS = 0x9, TAP_CI = 0xa, TAP_SI = 0xb, TAP_E1I = 0xc,
-	TAP_PI = 0xd, TAP_E2I = 0xe, TAP_UI = 0xf
-};
-
-typedef struct tap_transition_s
-{
-	enum tap_state high;
-	enum tap_state low;
-} tap_transition_t;
-
-extern char* tap_state_strings[16];
-extern int tap_move_map[16];	/* map 16 TAP states to 6 stable states */
-extern u8 tap_move[6][6];		/* value scanned to TMS to move from one of six stable states to another */
-extern tap_transition_t tap_transitions[16];	/* describe the TAP state diagram */
-
-extern enum tap_state end_state;		/* finish DR scans in dr_end_state */
-extern enum tap_state cur_state;		/* current TAP state */
-
-extern enum tap_state cmd_queue_end_state;		/* finish DR scans in dr_end_state */
-extern enum tap_state cmd_queue_cur_state;		/* current TAP state */
-
-#define TAP_MOVE(from, to) tap_move[tap_move_map[from]][tap_move_map[to]]
-
-typedef void * error_handler_t; /* Later on we can delete error_handler_t, but keep it for now to make patches more readable */
-
-struct scan_field_s;
-typedef int (*in_handler_t)(u8 *in_value, void *priv, struct scan_field_s *field);
-
-typedef struct scan_field_s
-{
-	int device;			/* ordinal device number this instruction refers to */
-	int num_bits;		/* number of bits this field specifies (up to 32) */
-	u8 *out_value;		/* value to be scanned into the device */
-	u8 *out_mask;		/* only masked bits care */
-	u8 *in_value;		/* pointer to a 32-bit memory location to take data scanned out */
-	/* in_check_value/mask, in_handler_error_handler, in_handler_priv can be used by the in handler, otherwise they contain garbage  */
-	u8 *in_check_value;		/* used to validate scan results */ 
-	u8 *in_check_mask;		/* check specified bits against check_value */
-	in_handler_t in_handler;	    /* process received buffer using this handler */
-	void *in_handler_priv;	/* additional information for the in_handler */
-} scan_field_t;
-
-enum scan_type
-{
-	/* IN: from device to host, OUT: from host to device */
-	SCAN_IN = 1, SCAN_OUT = 2, SCAN_IO = 3
-};
-
-typedef struct scan_command_s
-{
-	int ir_scan;	/* instruction/not data scan */
-	int num_fields;		/* number of fields in *fields array */
-	scan_field_t *fields;	/* pointer to an array of data scan fields */
-	enum tap_state end_state;	/* TAP state in which JTAG commands should finish */
-} scan_command_t;
-
-typedef struct statemove_command_s
-{
-	enum tap_state end_state;	/* TAP state in which JTAG commands should finish */
-} statemove_command_t;
-
-typedef struct pathmove_command_s
-{
-	int num_states;				/* number of states in *path */
-	enum tap_state *path;		/* states that have to be passed */
-} pathmove_command_t;
-
-typedef struct runtest_command_s
-{
-	int num_cycles;		/* number of cycles that should be spent in Run-Test/Idle */
-	enum tap_state end_state;	/* TAP state in which JTAG commands should finish */
-} runtest_command_t;
-
-typedef struct reset_command_s
-{
-	int trst;			/* trst/srst 0: deassert, 1: assert, -1: don't change */
-	int srst;
-} reset_command_t;
-
-typedef struct end_state_command_s
-{
-	enum tap_state end_state;	/* TAP state in which JTAG commands should finish */
-} end_state_command_t;
-
-typedef struct sleep_command_s
-{
-	u32 us;		/* number of microseconds to sleep */
-} sleep_command_t;
-
-typedef union jtag_command_container_u
-{
-	scan_command_t *scan;
-	statemove_command_t *statemove;
-	pathmove_command_t *pathmove;
-	runtest_command_t *runtest;
-	reset_command_t *reset;
-	end_state_command_t *end_state;
-	sleep_command_t *sleep;
-} jtag_command_container_t;
-
-enum jtag_command_type
-{
-	JTAG_SCAN = 1,
-	JTAG_STATEMOVE = 2, JTAG_RUNTEST = 3,
-	JTAG_RESET = 4, JTAG_END_STATE = 5,
-	JTAG_PATHMOVE = 6, JTAG_SLEEP = 7
-};
-
-typedef struct jtag_command_s
-{
-	jtag_command_container_t cmd;
-	enum jtag_command_type type;
-	struct jtag_command_s *next;
-} jtag_command_t;
-
-extern jtag_command_t *jtag_command_queue;
-
-typedef struct jtag_device_s
-{
-	int ir_length;		/* size of instruction register */
-	u8 *expected;		/* Capture-IR expected value */
-	u8 *expected_mask;	/* Capture-IR expected mask */
-	u32 idcode;			/* device identification code */
-	u8 *cur_instr;		/* current instruction */
-	int bypass;			/* bypass register selected */
-	struct jtag_device_s *next;
-} jtag_device_t;
-
-extern jtag_device_t *jtag_devices;
-extern int jtag_num_devices;
-extern int jtag_ir_scan_size;
-
-enum reset_line_mode
-{
-	LINE_OPEN_DRAIN = 0x0,
-	LINE_PUSH_PULL = 0x1,
-};
-
-typedef struct jtag_interface_s
-{
-	char* name;
-	
-	/* queued command execution
-	 */
-	int (*execute_queue)(void);
-	
-	/* interface initalization
-	 */
-	int (*speed)(int speed);
-	int (*register_commands)(struct command_context_s *cmd_ctx);
-	int (*init)(void);
-	int (*quit)(void);
-	
-} jtag_interface_t;
-
-enum jtag_event
-{
-	JTAG_SRST_ASSERTED,
-	JTAG_TRST_ASSERTED,
-	JTAG_SRST_RELEASED,
-	JTAG_TRST_RELEASED,
-};
-
-extern char* jtag_event_strings[];
-
-extern int jtag_trst;
-extern int jtag_srst;
-
-typedef struct jtag_event_callback_s
-{
-	int (*callback)(enum jtag_event event, void *priv);
-	void *priv;
-	struct jtag_event_callback_s *next;
-} jtag_event_callback_t;
-
-extern jtag_event_callback_t *jtag_event_callbacks;
-
-extern jtag_interface_t *jtag;	/* global pointer to configured JTAG interface */
-extern enum tap_state end_state;
-extern enum tap_state cur_state;
-
-extern char* jtag_interface;
-extern int jtag_speed;
-
-enum reset_types
-{
-	RESET_NONE = 0x0, 
-	RESET_HAS_TRST = 0x1, 
-	RESET_HAS_SRST = 0x2, 
-	RESET_TRST_AND_SRST = 0x3, 
-	RESET_SRST_PULLS_TRST = 0x4,
-	RESET_TRST_PULLS_SRST = 0x8,
-	RESET_TRST_OPEN_DRAIN = 0x10,
-	RESET_SRST_PUSH_PULL = 0x20,
-};
-
-extern enum reset_types jtag_reset_config;
-
-/* JTAG subsystem */
-extern int jtag_init(struct command_context_s *cmd_ctx);
-extern int jtag_register_commands(struct command_context_s *cmd_ctx);
-
-/* JTAG interface, can be implemented with a software or hardware fifo */
-extern int jtag_add_ir_scan(int num_fields, scan_field_t *fields, enum tap_state endstate, void *dummy_anachronism);
-extern int jtag_add_dr_scan(int num_fields, scan_field_t *fields, enum tap_state endstate, void *dummy_anachronism);
-extern int jtag_add_plain_ir_scan(int num_fields, scan_field_t *fields, enum tap_state endstate, void *dummy_anachronism);
-extern int jtag_add_plain_dr_scan(int num_fields, scan_field_t *fields, enum tap_state endstate, void *dummy_anachronism);
-/* execute a state transition within the JTAG standard, but the exact path
- * path that is taken is undefined. Many implementations use precisely
- * 7 clocks to perform a transition, but it could be more or less
- * than that.
- *
- * The following assertions are made about certain common state moves:
- *
- * - A state move from Pause-[ID]R to Pause-[ID]R should always go through 
- *   Update-[ID]R and Capture-[ID]R before returning to Pause-[ID]R, otherwise 
- *   there's no way force a register update, if you can't go to Run-Test/Idle for 
- *   some reason.
- *
- *   - A state move from Pause-[ID]R to Shift-[ID]R must not go through 
- *   Update-[ID]R.
- *
- *   - Run-Test/Idle must not be entered unless requested, because R-T/I may have 
- *   side effects.
- */
-extern int jtag_add_statemove(enum tap_state endstate);
-/* A list of unambigious single clock state transitions, not
- * all drivers can support this, but it is required for e.g.
- * XScale and Xilinx support
- */
-extern int jtag_add_pathmove(int num_states, enum tap_state *path);
-/* cycle precisely num_cycles in the TAP_RTI state */
-extern int jtag_add_runtest(int num_cycles, enum tap_state endstate);
-extern int jtag_add_reset(int trst, int srst);
-extern int jtag_add_end_state(enum tap_state endstate);
-extern int jtag_add_sleep(u32 us);
-/*
- * For software FIFO implementations, the queued commands can be executed 
- * during this call or earlier. A sw queue might decide to push out
- * some of the jtag_add_xxx() operations once the queue is "big enough".
- * 
- * This fn will return an error code if any of the prior jtag_add_xxx() 
- * calls caused a failure, e.g. check failure. Note that it does not
- * matter if the operation was executed *before* jtag_execute_queue(),
- * jtag_execute_queue() will still return an error code. 
- * 
- * All jtag_add_xxx() calls that have in_handler!=NULL will have been
- * executed when this fn returns, but if what has been queued only 
- * clocks data out, without reading anything back, then JTAG could 
- * be running *after* jtag_execute_queue() returns. The API does 
- * not define a way to flush a hw FIFO that runs *after* 
- * jtag_execute_queue() returns. 
- * 
- * jtag_add_xxx() commands can either be executed immediately or 
- * at some time between the jtag_add_xxx() fn call and jtag_execute_queue().  
- */
-extern int jtag_execute_queue(void);
-
-/* JTAG support functions */
-extern void jtag_set_check_value(scan_field_t *field, u8 *value,  u8 *mask, error_handler_t *in_error_handler);
-extern enum scan_type jtag_scan_type(scan_command_t *cmd);
-extern int jtag_scan_size(scan_command_t *cmd);
-extern int jtag_read_buffer(u8 *buffer, scan_command_t *cmd);
-extern int jtag_build_buffer(scan_command_t *cmd, u8 **buffer);
-extern jtag_device_t* jtag_get_device(int num);
-extern void jtag_sleep(u32 us);
-extern int jtag_call_event_callbacks(enum jtag_event event);
-extern int jtag_register_event_callback(int (*callback)(enum jtag_event event, void *priv), void *priv);
-
-extern int jtag_verify_capture_ir;
-
-
-/* error codes
- * JTAG subsystem uses codes between -100 and -199 */
-
-#define ERROR_JTAG_INIT_FAILED			(-100)
-#define ERROR_JTAG_INVALID_INTERFACE	(-101)
-#define ERROR_JTAG_NOT_IMPLEMENTED		(-102)
-#define ERROR_JTAG_TRST_ASSERTED		(-103)
-#define ERROR_JTAG_QUEUE_FAILED			(-104)
-#define ERROR_JTAG_RESET_WOULD_ASSERT_TRST		(-105)
-#define ERROR_JTAG_RESET_CANT_SRST				(-106)
-#define ERROR_JTAG_DEVICE_ERROR			(-107)
-#endif /* JTAG_H */
+/***************************************************************************
+ *   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 JTAG_H
+#define JTAG_H
+
+#include "types.h"
+#include "binarybuffer.h"
+
+#include "command.h"
+
+#if 0
+#define _DEBUG_JTAG_IO_
+#endif
+
+/* Tap States
+ * TLR - Test-Logic-Reset, RTI - Run-Test/Idle, 
+ * SDS - Select-DR-Scan, CD - Capture-DR, SD - Shift-DR, E1D - Exit1-DR,
+ * PD - Pause-DR, E2D - Exit2-DR, UD - Update-DR,
+ * SIS - Select-IR-Scan, CI - Capture-IR, SI - Shift-IR, E1I - Exit1-IR,
+ * PI - Pause-IR, E2I - Exit2-IR, UI - Update-IR 
+ */
+enum tap_state
+{
+	TAP_TLR = 0x0, TAP_RTI = 0x8, 
+	TAP_SDS = 0x1, TAP_CD = 0x2, TAP_SD = 0x3, TAP_E1D = 0x4, 
+	TAP_PD = 0x5, TAP_E2D = 0x6, TAP_UD = 0x7,
+	TAP_SIS = 0x9, TAP_CI = 0xa, TAP_SI = 0xb, TAP_E1I = 0xc,
+	TAP_PI = 0xd, TAP_E2I = 0xe, TAP_UI = 0xf
+};
+
+typedef struct tap_transition_s
+{
+	enum tap_state high;
+	enum tap_state low;
+} tap_transition_t;
+
+extern char* tap_state_strings[16];
+extern int tap_move_map[16];	/* map 16 TAP states to 6 stable states */
+extern u8 tap_move[6][6];		/* value scanned to TMS to move from one of six stable states to another */
+extern tap_transition_t tap_transitions[16];	/* describe the TAP state diagram */
+
+extern enum tap_state end_state;		/* finish DR scans in dr_end_state */
+extern enum tap_state cur_state;		/* current TAP state */
+
+extern enum tap_state cmd_queue_end_state;		/* finish DR scans in dr_end_state */
+extern enum tap_state cmd_queue_cur_state;		/* current TAP state */
+
+#define TAP_MOVE(from, to) tap_move[tap_move_map[from]][tap_move_map[to]]
+
+typedef void * error_handler_t; /* Later on we can delete error_handler_t, but keep it for now to make patches more readable */
+
+struct scan_field_s;
+typedef int (*in_handler_t)(u8 *in_value, void *priv, struct scan_field_s *field);
+
+typedef struct scan_field_s
+{
+	int device;			/* ordinal device number this instruction refers to */
+	int num_bits;		/* number of bits this field specifies (up to 32) */
+	u8 *out_value;		/* value to be scanned into the device */
+	u8 *out_mask;		/* only masked bits care */
+	u8 *in_value;		/* pointer to a 32-bit memory location to take data scanned out */
+	/* in_check_value/mask, in_handler_error_handler, in_handler_priv can be used by the in handler, otherwise they contain garbage  */
+	u8 *in_check_value;		/* used to validate scan results */ 
+	u8 *in_check_mask;		/* check specified bits against check_value */
+	in_handler_t in_handler;	    /* process received buffer using this handler */
+	void *in_handler_priv;	/* additional information for the in_handler */
+} scan_field_t;
+
+enum scan_type
+{
+	/* IN: from device to host, OUT: from host to device */
+	SCAN_IN = 1, SCAN_OUT = 2, SCAN_IO = 3
+};
+
+typedef struct scan_command_s
+{
+	int ir_scan;	/* instruction/not data scan */
+	int num_fields;		/* number of fields in *fields array */
+	scan_field_t *fields;	/* pointer to an array of data scan fields */
+	enum tap_state end_state;	/* TAP state in which JTAG commands should finish */
+} scan_command_t;
+
+typedef struct statemove_command_s
+{
+	enum tap_state end_state;	/* TAP state in which JTAG commands should finish */
+} statemove_command_t;
+
+typedef struct pathmove_command_s
+{
+	int num_states;				/* number of states in *path */
+	enum tap_state *path;		/* states that have to be passed */
+} pathmove_command_t;
+
+typedef struct runtest_command_s
+{
+	int num_cycles;		/* number of cycles that should be spent in Run-Test/Idle */
+	enum tap_state end_state;	/* TAP state in which JTAG commands should finish */
+} runtest_command_t;
+
+typedef struct reset_command_s
+{
+	int trst;			/* trst/srst 0: deassert, 1: assert, -1: don't change */
+	int srst;
+} reset_command_t;
+
+typedef struct end_state_command_s
+{
+	enum tap_state end_state;	/* TAP state in which JTAG commands should finish */
+} end_state_command_t;
+
+typedef struct sleep_command_s
+{
+	u32 us;		/* number of microseconds to sleep */
+} sleep_command_t;
+
+typedef union jtag_command_container_u
+{
+	scan_command_t *scan;
+	statemove_command_t *statemove;
+	pathmove_command_t *pathmove;
+	runtest_command_t *runtest;
+	reset_command_t *reset;
+	end_state_command_t *end_state;
+	sleep_command_t *sleep;
+} jtag_command_container_t;
+
+enum jtag_command_type
+{
+	JTAG_SCAN = 1,
+	JTAG_STATEMOVE = 2, JTAG_RUNTEST = 3,
+	JTAG_RESET = 4, JTAG_END_STATE = 5,
+	JTAG_PATHMOVE = 6, JTAG_SLEEP = 7
+};
+
+typedef struct jtag_command_s
+{
+	jtag_command_container_t cmd;
+	enum jtag_command_type type;
+	struct jtag_command_s *next;
+} jtag_command_t;
+
+extern jtag_command_t *jtag_command_queue;
+
+typedef struct jtag_device_s
+{
+	int ir_length;		/* size of instruction register */
+	u8 *expected;		/* Capture-IR expected value */
+	u8 *expected_mask;	/* Capture-IR expected mask */
+	u32 idcode;			/* device identification code */
+	u8 *cur_instr;		/* current instruction */
+	int bypass;			/* bypass register selected */
+	struct jtag_device_s *next;
+} jtag_device_t;
+
+extern jtag_device_t *jtag_devices;
+extern int jtag_num_devices;
+extern int jtag_ir_scan_size;
+
+enum reset_line_mode
+{
+	LINE_OPEN_DRAIN = 0x0,
+	LINE_PUSH_PULL = 0x1,
+};
+
+typedef struct jtag_interface_s
+{
+	char* name;
+	
+	/* queued command execution
+	 */
+	int (*execute_queue)(void);
+	
+	/* interface initalization
+	 */
+	int (*speed)(int speed);
+	int (*register_commands)(struct command_context_s *cmd_ctx);
+	int (*init)(void);
+	int (*quit)(void);
+	
+} jtag_interface_t;
+
+enum jtag_event
+{
+	JTAG_SRST_ASSERTED,
+	JTAG_TRST_ASSERTED,
+	JTAG_SRST_RELEASED,
+	JTAG_TRST_RELEASED,
+};
+
+extern char* jtag_event_strings[];
+
+extern int jtag_trst;
+extern int jtag_srst;
+
+typedef struct jtag_event_callback_s
+{
+	int (*callback)(enum jtag_event event, void *priv);
+	void *priv;
+	struct jtag_event_callback_s *next;
+} jtag_event_callback_t;
+
+extern jtag_event_callback_t *jtag_event_callbacks;
+
+extern jtag_interface_t *jtag;	/* global pointer to configured JTAG interface */
+extern enum tap_state end_state;
+extern enum tap_state cur_state;
+
+extern char* jtag_interface;
+extern int jtag_speed;
+
+enum reset_types
+{
+	RESET_NONE = 0x0, 
+	RESET_HAS_TRST = 0x1, 
+	RESET_HAS_SRST = 0x2, 
+	RESET_TRST_AND_SRST = 0x3, 
+	RESET_SRST_PULLS_TRST = 0x4,
+	RESET_TRST_PULLS_SRST = 0x8,
+	RESET_TRST_OPEN_DRAIN = 0x10,
+	RESET_SRST_PUSH_PULL = 0x20,
+};
+
+extern enum reset_types jtag_reset_config;
+
+/* JTAG subsystem */
+extern int jtag_init(struct command_context_s *cmd_ctx);
+extern int jtag_register_commands(struct command_context_s *cmd_ctx);
+
+/* JTAG interface, can be implemented with a software or hardware fifo */
+extern int jtag_add_ir_scan(int num_fields, scan_field_t *fields, enum tap_state endstate);
+extern int jtag_add_dr_scan(int num_fields, scan_field_t *fields, enum tap_state endstate);
+extern int jtag_add_plain_ir_scan(int num_fields, scan_field_t *fields, enum tap_state endstate);
+extern int jtag_add_plain_dr_scan(int num_fields, scan_field_t *fields, enum tap_state endstate);
+/* execute a state transition within the JTAG standard, but the exact path
+ * path that is taken is undefined. Many implementations use precisely
+ * 7 clocks to perform a transition, but it could be more or less
+ * than that.
+ *
+ * The following assertions are made about certain common state moves:
+ *
+ * - A state move from Pause-[ID]R to Pause-[ID]R should always go through 
+ *   Update-[ID]R and Capture-[ID]R before returning to Pause-[ID]R, otherwise 
+ *   there's no way force a register update, if you can't go to Run-Test/Idle for 
+ *   some reason.
+ *
+ *   - A state move from Pause-[ID]R to Shift-[ID]R must not go through 
+ *   Update-[ID]R.
+ *
+ *   - Run-Test/Idle must not be entered unless requested, because R-T/I may have 
+ *   side effects.
+ */
+extern int jtag_add_statemove(enum tap_state endstate);
+/* A list of unambigious single clock state transitions, not
+ * all drivers can support this, but it is required for e.g.
+ * XScale and Xilinx support
+ */
+extern int jtag_add_pathmove(int num_states, enum tap_state *path);
+/* cycle precisely num_cycles in the TAP_RTI state */
+extern int jtag_add_runtest(int num_cycles, enum tap_state endstate);
+extern int jtag_add_reset(int trst, int srst);
+extern int jtag_add_end_state(enum tap_state endstate);
+extern int jtag_add_sleep(u32 us);
+/*
+ * For software FIFO implementations, the queued commands can be executed 
+ * during this call or earlier. A sw queue might decide to push out
+ * some of the jtag_add_xxx() operations once the queue is "big enough".
+ * 
+ * This fn will return an error code if any of the prior jtag_add_xxx() 
+ * calls caused a failure, e.g. check failure. Note that it does not
+ * matter if the operation was executed *before* jtag_execute_queue(),
+ * jtag_execute_queue() will still return an error code. 
+ * 
+ * All jtag_add_xxx() calls that have in_handler!=NULL will have been
+ * executed when this fn returns, but if what has been queued only 
+ * clocks data out, without reading anything back, then JTAG could 
+ * be running *after* jtag_execute_queue() returns. The API does 
+ * not define a way to flush a hw FIFO that runs *after* 
+ * jtag_execute_queue() returns. 
+ * 
+ * jtag_add_xxx() commands can either be executed immediately or 
+ * at some time between the jtag_add_xxx() fn call and jtag_execute_queue().  
+ */
+extern int jtag_execute_queue(void);
+
+/* JTAG support functions */
+extern void jtag_set_check_value(scan_field_t *field, u8 *value,  u8 *mask, error_handler_t *in_error_handler);
+extern enum scan_type jtag_scan_type(scan_command_t *cmd);
+extern int jtag_scan_size(scan_command_t *cmd);
+extern int jtag_read_buffer(u8 *buffer, scan_command_t *cmd);
+extern int jtag_build_buffer(scan_command_t *cmd, u8 **buffer);
+extern jtag_device_t* jtag_get_device(int num);
+extern void jtag_sleep(u32 us);
+extern int jtag_call_event_callbacks(enum jtag_event event);
+extern int jtag_register_event_callback(int (*callback)(enum jtag_event event, void *priv), void *priv);
+
+extern int jtag_verify_capture_ir;
+
+
+/* error codes
+ * JTAG subsystem uses codes between -100 and -199 */
+
+#define ERROR_JTAG_INIT_FAILED			(-100)
+#define ERROR_JTAG_INVALID_INTERFACE	(-101)
+#define ERROR_JTAG_NOT_IMPLEMENTED		(-102)
+#define ERROR_JTAG_TRST_ASSERTED		(-103)
+#define ERROR_JTAG_QUEUE_FAILED			(-104)
+#define ERROR_JTAG_RESET_WOULD_ASSERT_TRST		(-105)
+#define ERROR_JTAG_RESET_CANT_SRST				(-106)
+#define ERROR_JTAG_DEVICE_ERROR			(-107)
+#endif /* JTAG_H */
diff --git a/src/pld/virtex2.c b/src/pld/virtex2.c
index a31c37d94f1be30545c7c3ba9929f9f29c51fcfe..e0cd1a11aeb7081d5e523f17a190d05554fe0fa7 100644
--- a/src/pld/virtex2.c
+++ b/src/pld/virtex2.c
@@ -1,264 +1,264 @@
-/***************************************************************************
- *   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 "virtex2.h"
-
-#include "pld.h"
-#include "xilinx_bit.h"
-#include "command.h"
-#include "log.h"
-#include "jtag.h"
-
-#include <stdlib.h>
-
-int virtex2_register_commands(struct command_context_s *cmd_ctx);
-int virtex2_pld_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct pld_device_s *pld_device);
-int virtex2_load(struct pld_device_s *pld_device, char *filename);
-
-pld_driver_t virtex2_pld =
-{
-	.name = "virtex2",
-	.register_commands = virtex2_register_commands,
-	.pld_device_command = virtex2_pld_device_command,
-	.load = virtex2_load,
-};
-
-int virtex2_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 = NULL;
-		field.in_check_mask = NULL;
-		field.in_handler = NULL;
-		field.in_handler_priv = NULL;
-		
-		jtag_add_ir_scan(1, &field, TAP_RTI, NULL);
-		
-		free(field.out_value);
-	}
-	
-	return ERROR_OK;
-}
-
-int virtex2_send_32(struct pld_device_s *pld_device, int num_words, u32 *words)
-{
-	virtex2_pld_device_t *virtex2_info = pld_device->driver_priv;
-	scan_field_t scan_field;
-	u8 *values;
-	int i;
-	
-	values = malloc(num_words * 4);
-
-	scan_field.device = virtex2_info->chain_pos;
-	scan_field.num_bits = num_words * 32;
-	scan_field.out_value = values;
-	scan_field.out_mask = NULL;
-	scan_field.in_value = NULL;
-	scan_field.in_check_value = NULL;
-	scan_field.in_check_mask = NULL;
-	scan_field.in_handler = NULL;
-	scan_field.in_handler_priv = NULL;
-	
-	for (i = 0; i < num_words; i++)
-		buf_set_u32(values + 4 * i, 0, 32, flip_u32(*words++, 32));
-	
-	virtex2_set_instr(virtex2_info->chain_pos, 0x5); /* CFG_IN */
-	
-	jtag_add_dr_scan(1, &scan_field, TAP_PD, NULL);
-	
-	free(values);
-	
-	return ERROR_OK;
-}
-
-int virtex2_jtag_buf_to_u32(u8 *in_buf, void *priv, struct scan_field_s *field)
-{
-	u32 *dest = priv;
-	*dest = flip_u32(le_to_h_u32(in_buf), 32);
-	return ERROR_OK;
-}
-
-int virtex2_receive_32(struct pld_device_s *pld_device, int num_words, u32 *words)
-{
-	virtex2_pld_device_t *virtex2_info = pld_device->driver_priv;
-	scan_field_t scan_field;
-	
-	scan_field.device = virtex2_info->chain_pos;
-	scan_field.num_bits = 32;
-	scan_field.out_value = NULL;
-	scan_field.out_mask = NULL;
-	scan_field.in_value = NULL;
-	scan_field.in_check_value = NULL;
-	scan_field.in_check_mask = NULL;
-	scan_field.in_handler = virtex2_jtag_buf_to_u32;
-	
-	virtex2_set_instr(virtex2_info->chain_pos, 0x4); /* CFG_OUT */
-	
-	while (num_words--)
-	{
-		scan_field.in_handler_priv = words++;
-		jtag_add_dr_scan(1, &scan_field, TAP_PD, NULL);
-	}
-	
-	return ERROR_OK;
-}
-
-int virtex2_read_stat(struct pld_device_s *pld_device, u32 *status)
-{
-	u32 data[5];
-	
-	jtag_add_statemove(TAP_TLR);
-	
-	data[0] = 0xaa995566; /* synch word */
-	data[1] = 0x2800E001; /* Type 1, read, address 7, 1 word */
-	data[2] = 0x20000000; /* NOOP (Type 1, read, address 0, 0 words */
-	data[3] = 0x20000000; /* NOOP */
-	data[4] = 0x20000000; /* NOOP */
-	virtex2_send_32(pld_device, 5, data);
-	
-	virtex2_receive_32(pld_device, 1, status);
-	
-	jtag_execute_queue();
-	
-	DEBUG("status: 0x%8.8x", *status);
-	
-	return ERROR_OK;
-}
-
-int virtex2_load(struct pld_device_s *pld_device, char *filename)
-{
-	virtex2_pld_device_t *virtex2_info = pld_device->driver_priv;
-	xilinx_bit_file_t bit_file;
-	int retval;
-	int i;
-
-	scan_field_t field;
-
-	field.device = virtex2_info->chain_pos;
-	field.out_mask = NULL;
-	field.in_value = NULL;
-	field.in_check_value = NULL;
-	field.in_check_mask = NULL;
-	field.in_handler = NULL;
-	field.in_handler_priv = NULL;
-	
-	if ((retval = xilinx_read_bit_file(&bit_file, filename)) != ERROR_OK)
-		return retval;
-	
-	jtag_add_end_state(TAP_RTI);
-	virtex2_set_instr(virtex2_info->chain_pos, 0xb); /* JPROG_B */
-	jtag_execute_queue();
-	jtag_add_sleep(1000);
-	
-	virtex2_set_instr(virtex2_info->chain_pos, 0x5); /* CFG_IN */
-	jtag_execute_queue();
-	
-	for (i = 0; i < bit_file.length; i++)
-		bit_file.data[i] = flip_u32(bit_file.data[i], 8);
-	
-	field.num_bits = bit_file.length * 8;
-	field.out_value = bit_file.data;
-
-	jtag_add_dr_scan(1, &field, TAP_PD, NULL);
-	jtag_execute_queue();
-	
-	jtag_add_statemove(TAP_TLR);
-	
-	jtag_add_end_state(TAP_RTI);
-	virtex2_set_instr(virtex2_info->chain_pos, 0xc); /* JSTART */
-	jtag_add_runtest(13, TAP_RTI);
-	virtex2_set_instr(virtex2_info->chain_pos, 0x3f); /* BYPASS */
-	virtex2_set_instr(virtex2_info->chain_pos, 0x3f); /* BYPASS */
-	virtex2_set_instr(virtex2_info->chain_pos, 0xc); /* JSTART */
-	jtag_add_runtest(13, TAP_RTI);
-	virtex2_set_instr(virtex2_info->chain_pos, 0x3f); /* BYPASS */
-	jtag_execute_queue();
-
-	return ERROR_OK;
-}
-
-int virtex2_handle_read_stat_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	pld_device_t *device;
-	virtex2_pld_device_t *virtex2_info;
-	u32 status;
-	
-	if (argc < 1)
-	{
-		command_print(cmd_ctx, "usage: virtex2 read_stat <num>");
-		return ERROR_OK;
-	}
-	
-	device = get_pld_device_by_num(strtoul(args[0], NULL, 0));
-	if (!device)
-	{
-		command_print(cmd_ctx, "pld device '#%s' is out of bounds", args[0]);
-		return ERROR_OK;
-	}
-
-	virtex2_info = device->driver_priv;
-	
-	virtex2_read_stat(device, &status);
-	
-	command_print(cmd_ctx, "virtex2 status register: 0x%8.8x", status);
-	
-	return ERROR_OK;
-}
-
-int virtex2_register_commands(struct command_context_s *cmd_ctx)
-{
-	command_t *virtex2_cmd = register_command(cmd_ctx, NULL, "virtex2", NULL, COMMAND_ANY, "virtex2 specific commands");
-
-	register_command(cmd_ctx, virtex2_cmd, "read_stat", virtex2_handle_read_stat_command, COMMAND_EXEC,
-					 "read Virtex-II status register");
-
-	return ERROR_OK;
-}
-
-int virtex2_pld_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct pld_device_s *pld_device)
-{
-	virtex2_pld_device_t *virtex2_info;
-	
-	if (argc < 2)
-	{
-		WARNING("incomplete pld device 'virtex2' configuration");
-		return ERROR_PLD_DEVICE_INVALID;
-	}
-	
-	virtex2_info = malloc(sizeof(virtex2_pld_device_t));
-	pld_device->driver_priv = virtex2_info;
-	
-	virtex2_info->chain_pos = strtoul(args[1], NULL, 0);
-	
-	return ERROR_OK;
-}
+/***************************************************************************
+ *   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 "virtex2.h"
+
+#include "pld.h"
+#include "xilinx_bit.h"
+#include "command.h"
+#include "log.h"
+#include "jtag.h"
+
+#include <stdlib.h>
+
+int virtex2_register_commands(struct command_context_s *cmd_ctx);
+int virtex2_pld_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct pld_device_s *pld_device);
+int virtex2_load(struct pld_device_s *pld_device, char *filename);
+
+pld_driver_t virtex2_pld =
+{
+	.name = "virtex2",
+	.register_commands = virtex2_register_commands,
+	.pld_device_command = virtex2_pld_device_command,
+	.load = virtex2_load,
+};
+
+int virtex2_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 = NULL;
+		field.in_check_mask = NULL;
+		field.in_handler = NULL;
+		field.in_handler_priv = NULL;
+		
+		jtag_add_ir_scan(1, &field, TAP_RTI);
+		
+		free(field.out_value);
+	}
+	
+	return ERROR_OK;
+}
+
+int virtex2_send_32(struct pld_device_s *pld_device, int num_words, u32 *words)
+{
+	virtex2_pld_device_t *virtex2_info = pld_device->driver_priv;
+	scan_field_t scan_field;
+	u8 *values;
+	int i;
+	
+	values = malloc(num_words * 4);
+
+	scan_field.device = virtex2_info->chain_pos;
+	scan_field.num_bits = num_words * 32;
+	scan_field.out_value = values;
+	scan_field.out_mask = NULL;
+	scan_field.in_value = NULL;
+	scan_field.in_check_value = NULL;
+	scan_field.in_check_mask = NULL;
+	scan_field.in_handler = NULL;
+	scan_field.in_handler_priv = NULL;
+	
+	for (i = 0; i < num_words; i++)
+		buf_set_u32(values + 4 * i, 0, 32, flip_u32(*words++, 32));
+	
+	virtex2_set_instr(virtex2_info->chain_pos, 0x5); /* CFG_IN */
+	
+	jtag_add_dr_scan(1, &scan_field, TAP_PD);
+	
+	free(values);
+	
+	return ERROR_OK;
+}
+
+int virtex2_jtag_buf_to_u32(u8 *in_buf, void *priv, struct scan_field_s *field)
+{
+	u32 *dest = priv;
+	*dest = flip_u32(le_to_h_u32(in_buf), 32);
+	return ERROR_OK;
+}
+
+int virtex2_receive_32(struct pld_device_s *pld_device, int num_words, u32 *words)
+{
+	virtex2_pld_device_t *virtex2_info = pld_device->driver_priv;
+	scan_field_t scan_field;
+	
+	scan_field.device = virtex2_info->chain_pos;
+	scan_field.num_bits = 32;
+	scan_field.out_value = NULL;
+	scan_field.out_mask = NULL;
+	scan_field.in_value = NULL;
+	scan_field.in_check_value = NULL;
+	scan_field.in_check_mask = NULL;
+	scan_field.in_handler = virtex2_jtag_buf_to_u32;
+	
+	virtex2_set_instr(virtex2_info->chain_pos, 0x4); /* CFG_OUT */
+	
+	while (num_words--)
+	{
+		scan_field.in_handler_priv = words++;
+		jtag_add_dr_scan(1, &scan_field, TAP_PD);
+	}
+	
+	return ERROR_OK;
+}
+
+int virtex2_read_stat(struct pld_device_s *pld_device, u32 *status)
+{
+	u32 data[5];
+	
+	jtag_add_statemove(TAP_TLR);
+	
+	data[0] = 0xaa995566; /* synch word */
+	data[1] = 0x2800E001; /* Type 1, read, address 7, 1 word */
+	data[2] = 0x20000000; /* NOOP (Type 1, read, address 0, 0 words */
+	data[3] = 0x20000000; /* NOOP */
+	data[4] = 0x20000000; /* NOOP */
+	virtex2_send_32(pld_device, 5, data);
+	
+	virtex2_receive_32(pld_device, 1, status);
+	
+	jtag_execute_queue();
+	
+	DEBUG("status: 0x%8.8x", *status);
+	
+	return ERROR_OK;
+}
+
+int virtex2_load(struct pld_device_s *pld_device, char *filename)
+{
+	virtex2_pld_device_t *virtex2_info = pld_device->driver_priv;
+	xilinx_bit_file_t bit_file;
+	int retval;
+	int i;
+
+	scan_field_t field;
+
+	field.device = virtex2_info->chain_pos;
+	field.out_mask = NULL;
+	field.in_value = NULL;
+	field.in_check_value = NULL;
+	field.in_check_mask = NULL;
+	field.in_handler = NULL;
+	field.in_handler_priv = NULL;
+	
+	if ((retval = xilinx_read_bit_file(&bit_file, filename)) != ERROR_OK)
+		return retval;
+	
+	jtag_add_end_state(TAP_RTI);
+	virtex2_set_instr(virtex2_info->chain_pos, 0xb); /* JPROG_B */
+	jtag_execute_queue();
+	jtag_add_sleep(1000);
+	
+	virtex2_set_instr(virtex2_info->chain_pos, 0x5); /* CFG_IN */
+	jtag_execute_queue();
+	
+	for (i = 0; i < bit_file.length; i++)
+		bit_file.data[i] = flip_u32(bit_file.data[i], 8);
+	
+	field.num_bits = bit_file.length * 8;
+	field.out_value = bit_file.data;
+
+	jtag_add_dr_scan(1, &field, TAP_PD);
+	jtag_execute_queue();
+	
+	jtag_add_statemove(TAP_TLR);
+	
+	jtag_add_end_state(TAP_RTI);
+	virtex2_set_instr(virtex2_info->chain_pos, 0xc); /* JSTART */
+	jtag_add_runtest(13, TAP_RTI);
+	virtex2_set_instr(virtex2_info->chain_pos, 0x3f); /* BYPASS */
+	virtex2_set_instr(virtex2_info->chain_pos, 0x3f); /* BYPASS */
+	virtex2_set_instr(virtex2_info->chain_pos, 0xc); /* JSTART */
+	jtag_add_runtest(13, TAP_RTI);
+	virtex2_set_instr(virtex2_info->chain_pos, 0x3f); /* BYPASS */
+	jtag_execute_queue();
+
+	return ERROR_OK;
+}
+
+int virtex2_handle_read_stat_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	pld_device_t *device;
+	virtex2_pld_device_t *virtex2_info;
+	u32 status;
+	
+	if (argc < 1)
+	{
+		command_print(cmd_ctx, "usage: virtex2 read_stat <num>");
+		return ERROR_OK;
+	}
+	
+	device = get_pld_device_by_num(strtoul(args[0], NULL, 0));
+	if (!device)
+	{
+		command_print(cmd_ctx, "pld device '#%s' is out of bounds", args[0]);
+		return ERROR_OK;
+	}
+
+	virtex2_info = device->driver_priv;
+	
+	virtex2_read_stat(device, &status);
+	
+	command_print(cmd_ctx, "virtex2 status register: 0x%8.8x", status);
+	
+	return ERROR_OK;
+}
+
+int virtex2_register_commands(struct command_context_s *cmd_ctx)
+{
+	command_t *virtex2_cmd = register_command(cmd_ctx, NULL, "virtex2", NULL, COMMAND_ANY, "virtex2 specific commands");
+
+	register_command(cmd_ctx, virtex2_cmd, "read_stat", virtex2_handle_read_stat_command, COMMAND_EXEC,
+					 "read Virtex-II status register");
+
+	return ERROR_OK;
+}
+
+int virtex2_pld_device_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct pld_device_s *pld_device)
+{
+	virtex2_pld_device_t *virtex2_info;
+	
+	if (argc < 2)
+	{
+		WARNING("incomplete pld device 'virtex2' configuration");
+		return ERROR_PLD_DEVICE_INVALID;
+	}
+	
+	virtex2_info = malloc(sizeof(virtex2_pld_device_t));
+	pld_device->driver_priv = virtex2_info;
+	
+	virtex2_info->chain_pos = strtoul(args[1], NULL, 0);
+	
+	return ERROR_OK;
+}
diff --git a/src/target/arm11.c b/src/target/arm11.c
new file mode 100644
index 0000000000000000000000000000000000000000..11e376a6e6b935e9107f60c1c1d01721d0da924d
--- /dev/null
+++ b/src/target/arm11.c
@@ -0,0 +1,1358 @@
+/***************************************************************************
+ *   Copyright (C) 2008 digenius technology GmbH.                          *
+ *                                                                         *
+ *   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 "arm11.h"
+#include "jtag.h"
+#include "log.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#if 0
+#define _DEBUG_INSTRUCTION_EXECUTION_
+#endif
+
+
+#if 0
+#define FNC_INFO    DEBUG("-")
+#else
+#define FNC_INFO
+#endif
+
+#if 1
+#define FNC_INFO_NOTIMPLEMENTED    do { DEBUG("NOT IMPLEMENTED"); /*exit(-1);*/ } while (0)
+#else
+#define FNC_INFO_NOTIMPLEMENTED
+#endif
+
+static void arm11_on_enter_debug_state(arm11_common_t * arm11);
+
+
+#define ARM11_HANDLER(x)	\
+    .x				= arm11_##x
+
+target_type_t arm11_target =
+{
+    .name			= "arm11",
+
+    ARM11_HANDLER(poll),
+    ARM11_HANDLER(arch_state),
+
+    ARM11_HANDLER(target_request_data),
+
+    ARM11_HANDLER(halt),
+    ARM11_HANDLER(resume),
+    ARM11_HANDLER(step),
+
+    ARM11_HANDLER(assert_reset),
+    ARM11_HANDLER(deassert_reset),
+    ARM11_HANDLER(soft_reset_halt),
+    ARM11_HANDLER(prepare_reset_halt),
+	
+    ARM11_HANDLER(get_gdb_reg_list),
+	
+    ARM11_HANDLER(read_memory),
+    ARM11_HANDLER(write_memory),
+	
+    ARM11_HANDLER(bulk_write_memory),
+	
+    ARM11_HANDLER(checksum_memory),
+
+    ARM11_HANDLER(add_breakpoint),
+    ARM11_HANDLER(remove_breakpoint),
+    ARM11_HANDLER(add_watchpoint),
+    ARM11_HANDLER(remove_watchpoint),
+
+    ARM11_HANDLER(run_algorithm),
+	
+    ARM11_HANDLER(register_commands),
+    ARM11_HANDLER(target_command),
+    ARM11_HANDLER(init_target),
+    ARM11_HANDLER(quit),
+};
+
+int arm11_regs_arch_type = -1;
+
+
+enum arm11_regtype
+{
+    ARM11_REGISTER_CORE,
+    ARM11_REGISTER_CPSR,
+
+    ARM11_REGISTER_FX,
+    ARM11_REGISTER_FPS,
+
+    ARM11_REGISTER_FIQ,
+    ARM11_REGISTER_SVC,
+    ARM11_REGISTER_ABT,
+    ARM11_REGISTER_IRQ,
+    ARM11_REGISTER_UND,
+    ARM11_REGISTER_MON,
+
+    ARM11_REGISTER_SPSR_FIQ,
+    ARM11_REGISTER_SPSR_SVC,
+    ARM11_REGISTER_SPSR_ABT,
+    ARM11_REGISTER_SPSR_IRQ,
+    ARM11_REGISTER_SPSR_UND,
+    ARM11_REGISTER_SPSR_MON,
+
+    /* debug regs */
+    ARM11_REGISTER_DSCR,
+    ARM11_REGISTER_WDTR,
+    ARM11_REGISTER_RDTR,
+};
+
+
+typedef struct arm11_reg_defs_s
+{
+    char *			name;
+    u32				num;
+    int				gdb_num;
+    enum arm11_regtype		type;
+} arm11_reg_defs_t;
+
+/* update arm11_regcache_ids when changing this */
+static const arm11_reg_defs_t arm11_reg_defs[] =
+{
+    {"r0",	0,	0,	ARM11_REGISTER_CORE},
+    {"r1",	1,	1,	ARM11_REGISTER_CORE},
+    {"r2",	2,	2,	ARM11_REGISTER_CORE},
+    {"r3",	3,	3,	ARM11_REGISTER_CORE},
+    {"r4",	4,	4,	ARM11_REGISTER_CORE},
+    {"r5",	5,	5,	ARM11_REGISTER_CORE},
+    {"r6",	6,	6,	ARM11_REGISTER_CORE},
+    {"r7",	7,	7,	ARM11_REGISTER_CORE},
+    {"r8",	8,	8,	ARM11_REGISTER_CORE},
+    {"r9",	9,	9,	ARM11_REGISTER_CORE},
+    {"r10",	10,	10,	ARM11_REGISTER_CORE},
+    {"r11",	11,	11,	ARM11_REGISTER_CORE},
+    {"r12",	12,	12,	ARM11_REGISTER_CORE},
+    {"sp",	13,	13,	ARM11_REGISTER_CORE},
+    {"lr",	14,	14,	ARM11_REGISTER_CORE},
+    {"pc",	15,	15,	ARM11_REGISTER_CORE},
+
+#if ARM11_REGCACHE_FREGS
+    {"f0",	0,	16,	ARM11_REGISTER_FX},
+    {"f1",	1,	17,	ARM11_REGISTER_FX},
+    {"f2",	2,	18,	ARM11_REGISTER_FX},
+    {"f3",	3,	19,	ARM11_REGISTER_FX},
+    {"f4",	4,	20,	ARM11_REGISTER_FX},
+    {"f5",	5,	21,	ARM11_REGISTER_FX},
+    {"f6",	6,	22,	ARM11_REGISTER_FX},
+    {"f7",	7,	23,	ARM11_REGISTER_FX},
+    {"fps",	0,	24,	ARM11_REGISTER_FPS},
+#endif
+
+    {"cpsr",	0,	25,	ARM11_REGISTER_CPSR},
+
+#if ARM11_REGCACHE_MODEREGS
+    {"r8_fiq",	8,	-1,	ARM11_REGISTER_FIQ},
+    {"r9_fiq",	9,	-1,	ARM11_REGISTER_FIQ},
+    {"r10_fiq",	10,	-1,	ARM11_REGISTER_FIQ},
+    {"r11_fiq",	11,	-1,	ARM11_REGISTER_FIQ},
+    {"r12_fiq",	12,	-1,	ARM11_REGISTER_FIQ},
+    {"r13_fiq",	13,	-1,	ARM11_REGISTER_FIQ},
+    {"r14_fiq",	14,	-1,	ARM11_REGISTER_FIQ},
+    {"spsr_fiq", 0,	-1,	ARM11_REGISTER_SPSR_FIQ},
+
+    {"r13_svc",	13,	-1,	ARM11_REGISTER_SVC},
+    {"r14_svc",	14,	-1,	ARM11_REGISTER_SVC},
+    {"spsr_svc", 0,	-1,	ARM11_REGISTER_SPSR_SVC},
+
+    {"r13_abt",	13,	-1,	ARM11_REGISTER_ABT},
+    {"r14_abt",	14,	-1,	ARM11_REGISTER_ABT},
+    {"spsr_abt", 0,	-1,	ARM11_REGISTER_SPSR_ABT},
+
+    {"r13_irq",	13,	-1,	ARM11_REGISTER_IRQ},
+    {"r14_irq",	14,	-1,	ARM11_REGISTER_IRQ},
+    {"spsr_irq", 0,	-1,	ARM11_REGISTER_SPSR_IRQ},
+
+    {"r13_und",	13,	-1,	ARM11_REGISTER_UND},
+    {"r14_und",	14,	-1,	ARM11_REGISTER_UND},
+    {"spsr_und", 0,	-1,	ARM11_REGISTER_SPSR_UND},
+
+    /* ARM1176 only */
+    {"r13_mon",	13,	-1,	ARM11_REGISTER_MON},
+    {"r14_mon",	14,	-1,	ARM11_REGISTER_MON},
+    {"spsr_mon", 0,	-1,	ARM11_REGISTER_SPSR_MON},
+#endif
+
+    /* Debug Registers */
+    {"dscr",	0,	-1,	ARM11_REGISTER_DSCR},
+    {"wdtr",	0,	-1,	ARM11_REGISTER_WDTR},
+    {"rdtr",	0,	-1,	ARM11_REGISTER_RDTR},
+};
+
+enum arm11_regcache_ids
+{
+    ARM11_RC_R0,
+    ARM11_RC_RX			= ARM11_RC_R0,
+
+    ARM11_RC_R1,
+    ARM11_RC_R2,
+    ARM11_RC_R3,
+    ARM11_RC_R4,
+    ARM11_RC_R5,
+    ARM11_RC_R6,
+    ARM11_RC_R7,
+    ARM11_RC_R8,
+    ARM11_RC_R9,
+    ARM11_RC_R10,
+    ARM11_RC_R11,
+    ARM11_RC_R12,
+    ARM11_RC_R13,
+    ARM11_RC_SP			= ARM11_RC_R13,
+    ARM11_RC_R14,
+    ARM11_RC_LR			= ARM11_RC_R14,
+    ARM11_RC_R15,
+    ARM11_RC_PC			= ARM11_RC_R15,
+
+#if ARM11_REGCACHE_FREGS
+    ARM11_RC_F0,
+    ARM11_RC_FX			= ARM11_RC_F0,
+    ARM11_RC_F1,
+    ARM11_RC_F2,
+    ARM11_RC_F3,
+    ARM11_RC_F4,
+    ARM11_RC_F5,
+    ARM11_RC_F6,
+    ARM11_RC_F7,
+    ARM11_RC_FPS,
+#endif
+
+    ARM11_RC_CPSR,
+
+#if ARM11_REGCACHE_MODEREGS
+    ARM11_RC_R8_FIQ,
+    ARM11_RC_R9_FIQ,
+    ARM11_RC_R10_FIQ,
+    ARM11_RC_R11_FIQ,
+    ARM11_RC_R12_FIQ,
+    ARM11_RC_R13_FIQ,
+    ARM11_RC_R14_FIQ,
+    ARM11_RC_SPSR_FIQ,
+
+    ARM11_RC_R13_SVC,
+    ARM11_RC_R14_SVC,
+    ARM11_RC_SPSR_SVC,
+
+    ARM11_RC_R13_ABT,
+    ARM11_RC_R14_ABT,
+    ARM11_RC_SPSR_ABT,
+
+    ARM11_RC_R13_IRQ,
+    ARM11_RC_R14_IRQ,
+    ARM11_RC_SPSR_IRQ,
+
+    ARM11_RC_R13_UND,
+    ARM11_RC_R14_UND,
+    ARM11_RC_SPSR_UND,
+
+    ARM11_RC_R13_MON,
+    ARM11_RC_R14_MON,
+    ARM11_RC_SPSR_MON,
+#endif
+
+    ARM11_RC_DSCR,
+    ARM11_RC_WDTR,
+    ARM11_RC_RDTR,
+
+
+    ARM11_RC_MAX,
+};
+
+#define ARM11_GDB_REGISTER_COUNT	26
+
+u8 arm11_gdb_dummy_fp_value[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+reg_t arm11_gdb_dummy_fp_reg =
+{
+    "GDB dummy floating-point register", arm11_gdb_dummy_fp_value, 0, 1, 96, NULL, 0, NULL, 0
+};
+
+u8 arm11_gdb_dummy_fps_value[] = {0, 0, 0, 0};
+
+reg_t arm11_gdb_dummy_fps_reg =
+{
+    "GDB dummy floating-point status register", arm11_gdb_dummy_fps_value, 0, 1, 32, NULL, 0, NULL, 0
+};
+
+
+
+/** Check and if necessary take control of the system
+ *
+ * \param arm11		Target state variable.
+ * \param dscr		If the current DSCR content is
+ *		        available a pointer to a word holding the
+ *		        DSCR can be passed. Otherwise use NULL.
+ */
+void arm11_check_init(arm11_common_t * arm11, u32 * dscr)
+{
+    FNC_INFO;
+
+    u32			dscr_local_tmp_copy;
+
+    if (!dscr)
+    {
+	dscr = &dscr_local_tmp_copy;
+	*dscr = arm11_read_DSCR(arm11);
+    }
+
+    if (!(*dscr & ARM11_DSCR_MODE_SELECT))
+    {
+	DEBUG("Bringing target into debug mode");
+
+	*dscr |= ARM11_DSCR_MODE_SELECT;		/* Halt debug-mode */
+	arm11_write_DSCR(arm11, *dscr);
+
+	/* add further reset initialization here */
+
+	if (*dscr & ARM11_DSCR_CORE_HALTED)
+	{
+	    arm11->target->state	= TARGET_HALTED;
+	    arm11->target->debug_reason	= arm11_get_DSCR_debug_reason(*dscr);
+	}
+	else
+	{
+	    arm11->target->state	= TARGET_RUNNING;
+	    arm11->target->debug_reason	= DBG_REASON_NOTHALTED;
+	}
+
+	arm11_sc7_clear_bw(arm11);
+    }
+}
+
+
+
+#define R(x) \
+    (arm11->reg_values[ARM11_RC_##x])
+
+/** Save processor state.
+  *
+  * This is called when the HALT instruction has succeeded
+  * or on other occasions that stop the processor.
+  *
+  */
+static void arm11_on_enter_debug_state(arm11_common_t * arm11)
+{
+    FNC_INFO;
+
+    {size_t i;
+    for(i = 0; i < asizeof(arm11->reg_values); i++)
+    {
+	arm11->reg_list[i].valid	= 1;
+	arm11->reg_list[i].dirty	= 0;
+    }}
+
+    /* Save DSCR */
+
+    R(DSCR) = arm11_read_DSCR(arm11);
+
+    /* Save wDTR */
+
+    if (R(DSCR) & ARM11_DSCR_WDTR_FULL)
+    {
+	arm11_add_debug_SCAN_N(arm11, 0x05, -1);
+
+	arm11_add_IR(arm11, ARM11_INTEST, -1);
+
+	scan_field_t	chain5_fields[3];
+
+	arm11_setup_field(arm11, 32, NULL, &R(WDTR),	chain5_fields + 0);
+	arm11_setup_field(arm11,  1, NULL, NULL,	chain5_fields + 1);
+	arm11_setup_field(arm11,  1, NULL, NULL,	chain5_fields + 2);
+
+	jtag_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, TAP_PD);
+    }
+    else
+    {
+	arm11->reg_list[ARM11_RC_WDTR].valid	= 0;
+    }
+
+
+    /* DSCR: set ARM11_DSCR_EXECUTE_ARM_INSTRUCTION_ENABLE */
+    /* ARM1176 spec says this is needed only for wDTR/rDTR's "ITR mode", but not to issue ITRs
+       ARM1136 seems to require this to issue ITR's as well */
+
+    u32 new_dscr = R(DSCR) | ARM11_DSCR_EXECUTE_ARM_INSTRUCTION_ENABLE;
+
+    /* this executes JTAG queue: */ 
+
+    arm11_write_DSCR(arm11, new_dscr);
+
+//    jtag_execute_queue();
+
+
+
+//    DEBUG("SAVE DSCR %08x", R(DSCR));
+
+//    if (R(DSCR) & ARM11_DSCR_WDTR_FULL)
+//	DEBUG("SAVE wDTR %08x", R(WDTR));
+
+
+    /* From the spec:
+	Before executing any instruction in debug state you have to drain the write buffer.
+        This ensures that no imprecise Data Aborts can return at a later point:*/
+
+    /** \todo TODO: Test drain write buffer. */
+
+#if 0
+    while (1)
+    {
+	/* MRC p14,0,R0,c5,c10,0 */
+//	arm11_run_instr_no_data1(arm11, /*0xee150e1a*/0xe320f000);
+
+	/* mcr     15, 0, r0, cr7, cr10, {4} */
+	arm11_run_instr_no_data1(arm11, 0xee070f9a);
+	        
+	u32 dscr = arm11_read_DSCR(arm11);
+
+	DEBUG("DRAIN, DSCR %08x", dscr);
+
+	if (dscr & ARM11_DSCR_STICKY_IMPRECISE_DATA_ABORT)
+	{
+	    arm11_run_instr_no_data1(arm11, 0xe320f000);
+
+	    dscr = arm11_read_DSCR(arm11);
+
+	    DEBUG("DRAIN, DSCR %08x (DONE)", dscr);
+
+	    break;
+	}
+    }
+#endif
+
+
+    arm11_run_instr_data_prepare(arm11);
+
+    /* save r0 - r14 */
+
+
+    /** \todo TODO: handle other mode registers */
+
+    {size_t i;
+    for (i = 0; i < 15; i++)
+    {
+	/* MCR p14,0,R?,c0,c5,0 */
+	arm11_run_instr_data_from_core(arm11, 0xEE000E15 | (i << 12), &R(RX + i), 1);
+    }}
+
+
+    /* save rDTR */
+
+    /* check rDTRfull in DSCR */
+
+    if (R(DSCR) & ARM11_DSCR_RDTR_FULL)
+    {
+	/* MRC p14,0,R0,c0,c5,0 (move rDTR -> r0 (-> wDTR -> local var)) */
+	arm11_run_instr_data_from_core_via_r0(arm11, 0xEE100E15, &R(RDTR));
+    }
+    else
+    {
+	arm11->reg_list[ARM11_RC_RDTR].valid	= 0;
+    }
+
+    /* save CPSR */
+
+    /* MRS r0,CPSR (move CPSR -> r0 (-> wDTR -> local var)) */
+    arm11_run_instr_data_from_core_via_r0(arm11, 0xE10F0000, &R(CPSR));
+
+    /* save PC */
+
+    /* MOV R0,PC (move PC -> r0 (-> wDTR -> local var)) */
+    arm11_run_instr_data_from_core_via_r0(arm11, 0xE1A0000F, &R(PC));
+
+    /* adjust PC depending on ARM state */
+
+    if (R(CPSR) & ARM11_CPSR_J)	/* Java state */
+    {
+	arm11->reg_values[ARM11_RC_PC] -= 0;
+    }
+    else if (R(CPSR) & ARM11_CPSR_T)	/* Thumb state */
+    {
+	arm11->reg_values[ARM11_RC_PC] -= 4;
+    }
+    else					/* ARM state */
+    {
+	arm11->reg_values[ARM11_RC_PC] -= 8;
+    }
+
+//    DEBUG("SAVE PC   %08x", R(PC));
+
+    arm11_run_instr_data_finish(arm11);
+
+
+    {size_t i;
+    for(i = 0; i < ARM11_REGCACHE_COUNT; i++)
+    {
+	if (!arm11->reg_list[i].valid)
+	{
+	    if (arm11->reg_history[i].valid)
+		INFO("%8s INVALID    (%08x)", arm11_reg_defs[i].name, arm11->reg_history[i].value);
+	}
+	else
+	{
+	    if (arm11->reg_history[i].valid)
+	    {
+		if (arm11->reg_history[i].value != arm11->reg_values[i])
+		    INFO("%8s %08x (%08x)", arm11_reg_defs[i].name, arm11->reg_values[i], arm11->reg_history[i].value);
+	    }
+	    else
+	    {
+		INFO("%8s %08x (INVALID)", arm11_reg_defs[i].name, arm11->reg_values[i]);
+	    }
+	}
+    }}
+}
+
+
+/** Restore processor state
+  *
+  * This is called in preparation for the RESTART function.
+  *
+  */
+void arm11_leave_debug_state(arm11_common_t * arm11)
+{
+    FNC_INFO;
+
+    arm11_run_instr_data_prepare(arm11);
+
+    /** \todo TODO: handle other mode registers */
+
+    /* restore R1 - R14 */
+    {size_t i;
+    for (i = 1; i < 15; i++)
+    {
+	if (!arm11->reg_list[ARM11_RC_RX + i].dirty)
+	    continue;
+
+	/* MRC p14,0,r?,c0,c5,0 */
+	arm11_run_instr_data_to_core1(arm11, 0xee100e15 | (i << 12), R(RX + i));
+
+//	DEBUG("RESTORE R%d %08x", i, R(RX + i));
+    }}
+
+    arm11_run_instr_data_finish(arm11);
+
+
+    /* spec says clear wDTR and rDTR; we assume they are clear as
+       otherwide out programming would be sloppy */
+
+    {
+	u32 DSCR = arm11_read_DSCR(arm11);
+
+	if (DSCR & (ARM11_DSCR_RDTR_FULL | ARM11_DSCR_WDTR_FULL))
+	{
+	    ERROR("wDTR/rDTR inconsistent (DSCR %08x)", DSCR);
+	}
+    }
+
+    arm11_run_instr_data_prepare(arm11);
+
+    /* restore original wDTR */
+
+    if ((R(DSCR) & ARM11_DSCR_WDTR_FULL) || arm11->reg_list[ARM11_RC_WDTR].dirty)
+    {
+	/* MCR p14,0,R0,c0,c5,0 */
+	arm11_run_instr_data_to_core_via_r0(arm11, 0xee000e15, R(WDTR));
+    }
+
+    /* restore CPSR */
+
+    /* MSR CPSR,R0*/
+    arm11_run_instr_data_to_core_via_r0(arm11, 0xe129f000, R(CPSR));
+
+
+    /* restore PC */
+
+    /* MOV PC,R0 */
+    arm11_run_instr_data_to_core_via_r0(arm11, 0xe1a0f000, R(PC));
+
+
+    /* restore R0 */
+
+    /* MRC p14,0,r0,c0,c5,0 */
+    arm11_run_instr_data_to_core1(arm11, 0xee100e15, R(R0));
+
+    arm11_run_instr_data_finish(arm11);
+
+
+    /* restore DSCR */
+
+    arm11_write_DSCR(arm11, R(DSCR));
+
+
+    /* restore rDTR */
+    
+    if (R(DSCR) & ARM11_DSCR_RDTR_FULL || arm11->reg_list[ARM11_RC_RDTR].dirty)
+    {
+	arm11_add_debug_SCAN_N(arm11, 0x05, -1);
+
+	arm11_add_IR(arm11, ARM11_EXTEST, -1);
+
+	scan_field_t	chain5_fields[3];
+
+	u8			Ready	    = 0;	/* ignored */
+	u8			Valid	    = 0;	/* ignored */
+
+	arm11_setup_field(arm11, 32, &R(RDTR),	NULL, chain5_fields + 0);
+	arm11_setup_field(arm11,  1, &Ready,	NULL, chain5_fields + 1);
+	arm11_setup_field(arm11,  1, &Valid,	NULL, chain5_fields + 2);
+
+	jtag_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, TAP_PD);
+    }
+
+
+    {size_t i;
+    for(i = 0; i < ARM11_REGCACHE_COUNT; i++)
+    {
+	arm11->reg_history[i].value	= arm11->reg_values[i];
+	arm11->reg_history[i].valid	= arm11->reg_list[i].valid;
+
+	arm11->reg_list[i].valid	= 0;
+	arm11->reg_list[i].dirty	= 0;
+    }}
+}
+
+
+/* poll current target status */
+int arm11_poll(struct target_s *target)
+{
+    FNC_INFO;
+
+    arm11_common_t * arm11 = target->arch_info;
+
+    if (arm11->trst_active)
+	return ERROR_OK;
+
+    u32	dscr = arm11_read_DSCR(arm11);
+
+    DEBUG("DSCR %08x", dscr);
+
+    arm11_check_init(arm11, &dscr);
+
+    if (dscr & ARM11_DSCR_CORE_HALTED)
+    {
+//	DEBUG("CH %d", target->state);
+
+	if (target->state != TARGET_HALTED)
+	{
+	    DEBUG("enter TARGET_HALTED");
+	    target->state		= TARGET_HALTED;
+	    target->debug_reason	= arm11_get_DSCR_debug_reason(dscr);
+	    arm11_on_enter_debug_state(arm11);
+	}
+    }
+    else
+    {
+//	DEBUG("CR %d", target->state);
+
+	if (target->state != TARGET_RUNNING)
+	{
+	    DEBUG("enter TARGET_RUNNING");
+	    target->state		= TARGET_RUNNING;
+	    target->debug_reason	= DBG_REASON_NOTHALTED;
+	}
+    }
+
+    return ERROR_OK;
+}
+/* architecture specific status reply */
+int arm11_arch_state(struct target_s *target)
+{
+    FNC_INFO_NOTIMPLEMENTED;
+
+    return ERROR_OK;
+}
+
+
+/* target request support */
+int arm11_target_request_data(struct target_s *target, u32 size, u8 *buffer)
+{
+    FNC_INFO_NOTIMPLEMENTED;
+
+    return ERROR_OK;
+}
+
+
+
+/* target execution control */
+int arm11_halt(struct target_s *target)
+{
+    FNC_INFO;
+
+    arm11_common_t * arm11 = target->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;
+    }
+
+    if (arm11->trst_active)
+    {
+	arm11->halt_requested = true;
+	return ERROR_OK;
+    }
+
+    arm11_add_IR(arm11, ARM11_HALT, TAP_RTI);
+
+    jtag_execute_queue();
+
+    u32 dscr;
+
+    while (1)
+    {
+	dscr = arm11_read_DSCR(arm11);
+
+	if (dscr & ARM11_DSCR_CORE_HALTED)
+	    break;
+    }
+
+    arm11_on_enter_debug_state(arm11);
+
+    target->state		= TARGET_HALTED;
+    target->debug_reason	= arm11_get_DSCR_debug_reason(dscr);
+    
+    return ERROR_OK;
+}
+
+
+int arm11_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution)
+{
+    FNC_INFO;
+
+    arm11_common_t * arm11 = target->arch_info;
+
+    DEBUG("target->state: %s", target_state_strings[target->state]);
+
+    if (target->state != TARGET_HALTED)
+    {
+	WARNING("target was not halted");
+	return ERROR_TARGET_NOT_HALTED;
+    }
+
+    if (!current)
+	R(PC) = address;
+
+    target->state		= TARGET_RUNNING;
+    target->debug_reason	= DBG_REASON_NOTHALTED;
+
+    arm11_leave_debug_state(arm11);
+
+    arm11_add_IR(arm11, ARM11_RESTART, TAP_RTI);
+
+    jtag_execute_queue();
+
+    while (1)
+    {
+	u32 dscr = arm11_read_DSCR(arm11);
+
+	DEBUG("DSCR %08x", dscr);
+
+	if (dscr & ARM11_DSCR_CORE_RESTARTED)
+	    break;
+    }
+
+    DEBUG("RES %d", target->state);
+
+    return ERROR_OK;
+}
+
+int arm11_step(struct target_s *target, int current, u32 address, int handle_breakpoints)
+{
+    FNC_INFO;
+
+    DEBUG("target->state: %s", target_state_strings[target->state]);
+
+    if (target->state != TARGET_HALTED)
+    {
+	WARNING("target was not halted");
+	return ERROR_TARGET_NOT_HALTED;
+    }
+
+    arm11_common_t * arm11 = target->arch_info;
+
+    /** \todo TODO: check if break-/watchpoints make any sense at all in combination
+      * with this. */
+
+    /** \todo TODO: check if disabling IRQs might be a good idea here. Alternatively
+        the VCR might be something worth looking into. */
+
+    /* Set up breakpoint for stepping */
+
+    arm11_sc7_action_t	brp[2];
+
+    brp[0].write	= 1;
+    brp[0].address	= ARM11_SC7_BVR0;
+    brp[0].value	= R(PC);
+    brp[1].write	= 1;
+    brp[1].address	= ARM11_SC7_BCR0;
+    brp[1].value	= 0x1 | (3 << 1) | (0x0F << 5) | (0 << 14) | (0 << 16) | (0 << 20) | (2 << 21);
+
+    arm11_sc7_run(arm11, brp, asizeof(brp));
+
+    /* resume */
+
+    arm11_leave_debug_state(arm11);
+
+    arm11_add_IR(arm11, ARM11_RESTART, TAP_RTI);
+
+    jtag_execute_queue();
+
+    /** \todo TODO: add a timeout */
+
+    /* wait for halt */
+
+    while (1)
+    {
+	u32 dscr = arm11_read_DSCR(arm11);
+
+	DEBUG("DSCR %08x", dscr);
+
+        if ((dscr & (ARM11_DSCR_CORE_RESTARTED | ARM11_DSCR_CORE_HALTED)) ==
+	    (ARM11_DSCR_CORE_RESTARTED | ARM11_DSCR_CORE_HALTED))
+	    break;
+    }
+
+
+    /* clear breakpoint */
+
+    arm11_sc7_clear_bw(arm11);
+
+
+    /* save state */
+
+    arm11_on_enter_debug_state(arm11);
+
+//    target->state		= TARGET_HALTED;
+    target->debug_reason	= DBG_REASON_SINGLESTEP;
+
+    return ERROR_OK;
+}
+
+
+/* target reset control */
+int arm11_assert_reset(struct target_s *target)
+{
+    FNC_INFO;
+
+#if 0
+    /* assert reset lines */
+    /* resets only the DBGTAP, not the ARM */
+
+    jtag_add_reset(1, 0);
+    jtag_add_sleep(5000);
+
+    arm11_common_t * arm11 = target->arch_info;
+    arm11->trst_active = true;
+#endif
+
+    return ERROR_OK;
+}
+
+int arm11_deassert_reset(struct target_s *target)
+{
+    FNC_INFO;
+
+#if 0
+    DEBUG("target->state: %s", target_state_strings[target->state]);
+
+    /* deassert reset lines */
+    jtag_add_reset(0, 0);
+
+    arm11_common_t * arm11 = target->arch_info;
+    arm11->trst_active = false;
+
+    if (arm11->halt_requested)
+	return arm11_halt(target);
+#endif
+
+    return ERROR_OK;
+}
+
+int arm11_soft_reset_halt(struct target_s *target)
+{
+    FNC_INFO_NOTIMPLEMENTED;
+
+    return ERROR_OK;
+}
+
+int arm11_prepare_reset_halt(struct target_s *target)
+{
+    FNC_INFO_NOTIMPLEMENTED;
+
+    return ERROR_OK;
+}
+
+
+/* target register access for gdb */
+int arm11_get_gdb_reg_list(struct target_s *target, struct reg_s **reg_list[], int *reg_list_size)
+{
+    FNC_INFO;
+
+    arm11_common_t * arm11 = target->arch_info;
+
+    if (target->state != TARGET_HALTED)
+    {
+	return ERROR_TARGET_NOT_HALTED;
+    }
+	
+    *reg_list_size  = ARM11_GDB_REGISTER_COUNT;
+    *reg_list	    = malloc(sizeof(reg_t*) * ARM11_GDB_REGISTER_COUNT);
+
+    {size_t i;
+    for (i = 16; i < 24; i++)
+    {
+	(*reg_list)[i] = &arm11_gdb_dummy_fp_reg;
+    }}
+
+    (*reg_list)[24] = &arm11_gdb_dummy_fps_reg;
+
+
+    {size_t i;
+    for (i = 0; i < ARM11_REGCACHE_COUNT; i++)
+    {
+	if (arm11_reg_defs[i].gdb_num == -1)
+	    continue;
+
+	(*reg_list)[arm11_reg_defs[i].gdb_num] = arm11->reg_list + i;
+    }}
+
+    return ERROR_OK;
+}
+
+
+/* target memory access 
+* size: 1 = byte (8bit), 2 = half-word (16bit), 4 = word (32bit)
+* count: number of items of <size>
+*/
+int arm11_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
+{
+    /** \todo TODO: check if buffer cast to u32* and u16* might cause alignment problems */
+
+    FNC_INFO;
+
+    DEBUG("ADDR %08x  SIZE %08x  COUNT %08x", address, size, count);
+
+    arm11_common_t * arm11 = target->arch_info;
+
+    arm11_run_instr_data_prepare(arm11);
+
+    /* MRC p14,0,r0,c0,c5,0 */
+    arm11_run_instr_data_to_core1(arm11, 0xee100e15, address);
+
+    switch (size)
+    {
+    case 1:
+	/** \todo TODO: check if dirty is the right choice to force a rewrite on arm11_resume() */
+	arm11->reg_list[ARM11_RC_R1].dirty = 1;
+
+	while (count--)
+	{
+	    /* ldrb    r1, [r0], #1 */
+	    arm11_run_instr_no_data1(arm11, 0xe4d01001);
+
+	    u32 res;
+	    /* MCR p14,0,R1,c0,c5,0 */
+	    arm11_run_instr_data_from_core(arm11, 0xEE001E15, &res, 1);
+
+	    *buffer++ = res;
+	}
+	break;
+
+    case 2:
+    {
+	arm11->reg_list[ARM11_RC_R1].dirty = 1;
+
+	u16 * buf16 = (u16*)buffer;
+
+	while (count--)
+	{
+	    /* ldrh    r1, [r0], #2 */
+	    arm11_run_instr_no_data1(arm11, 0xe0d010b2);
+
+	    u32 res;
+
+	    /* MCR p14,0,R1,c0,c5,0 */
+	    arm11_run_instr_data_from_core(arm11, 0xEE001E15, &res, 1);
+
+	    *buf16++ = res;
+	}
+	break;
+    }
+
+    case 4:
+
+	/* LDC p14,c5,[R0],#4 */
+	arm11_run_instr_data_from_core(arm11, 0xecb05e01, (u32 *)buffer, count);
+	break;
+    }
+
+    arm11_run_instr_data_finish(arm11);
+
+    return ERROR_OK;
+}
+
+int arm11_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
+{
+    FNC_INFO;
+
+    DEBUG("ADDR %08x  SIZE %08x  COUNT %08x", address, size, count);
+
+    arm11_common_t * arm11 = target->arch_info;
+
+    arm11_run_instr_data_prepare(arm11);
+
+    /* MRC p14,0,r0,c0,c5,0 */
+    arm11_run_instr_data_to_core1(arm11, 0xee100e15, address);
+
+    switch (size)
+    {
+    case 1:
+	arm11->reg_list[ARM11_RC_R1].dirty = 1;
+
+	while (count--)
+	{
+	    /* MRC p14,0,r1,c0,c5,0 */
+	    arm11_run_instr_data_to_core1(arm11, 0xee101e15, *buffer++);
+
+	    /* strb    r1, [r0], #1 */
+	    arm11_run_instr_no_data1(arm11, 0xe4c01001);
+	}
+	break;
+
+    case 2:
+    {
+	arm11->reg_list[ARM11_RC_R1].dirty = 1;
+
+	u16 * buf16 = (u16*)buffer;
+
+	while (count--)
+	{
+	    /* MRC p14,0,r1,c0,c5,0 */
+	    arm11_run_instr_data_to_core1(arm11, 0xee101e15, *buf16++);
+
+	    /* strh    r1, [r0], #2 */
+	    arm11_run_instr_no_data1(arm11, 0xe0c010b2);
+	}
+	break;
+    }
+
+    case 4:
+	/** \todo TODO: check if buffer cast to u32* might cause alignment problems */
+
+	/* STC p14,c5,[R0],#4 */
+	arm11_run_instr_data_to_core(arm11, 0xeca05e01, (u32 *)buffer, count);
+	break;
+    }
+
+    arm11_run_instr_data_finish(arm11);
+
+    return ERROR_OK;
+}
+
+
+/* write target memory in multiples of 4 byte, optimized for writing large quantities of data */
+int arm11_bulk_write_memory(struct target_s *target, u32 address, u32 count, u8 *buffer)
+{
+    FNC_INFO;
+
+    return arm11_write_memory(target, address, 4, count, buffer);
+}
+
+
+int arm11_checksum_memory(struct target_s *target, u32 address, u32 count, u32* checksum)
+{
+    FNC_INFO_NOTIMPLEMENTED;
+
+    return ERROR_OK;
+}
+
+
+/* target break-/watchpoint control 
+* rw: 0 = write, 1 = read, 2 = access
+*/
+int arm11_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
+{
+    FNC_INFO_NOTIMPLEMENTED;
+
+    return ERROR_OK;
+}
+
+int arm11_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint)
+{
+    FNC_INFO_NOTIMPLEMENTED;
+
+    return ERROR_OK;
+}
+
+int arm11_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
+{
+    FNC_INFO_NOTIMPLEMENTED;
+
+    return ERROR_OK;
+}
+
+int arm11_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint)
+{
+    FNC_INFO_NOTIMPLEMENTED;
+
+    return ERROR_OK;
+}
+
+
+/* target algorithm support */
+int arm11_run_algorithm(struct target_s *target, int num_mem_params, mem_param_t *mem_params, int num_reg_params, reg_param_t *reg_param, u32 entry_point, u32 exit_point, int timeout_ms, void *arch_info)
+{
+    FNC_INFO_NOTIMPLEMENTED;
+
+    return ERROR_OK;
+}
+
+
+int arm11_register_commands(struct command_context_s *cmd_ctx)
+{
+    FNC_INFO;
+
+    return ERROR_OK;
+}
+
+int arm11_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)
+{
+    FNC_INFO;
+
+    if (argc < 4)
+    {
+	ERROR("'target arm11' 4th argument <jtag chain pos>");
+	exit(-1);
+    }
+
+    int chain_pos = strtoul(args[3], NULL, 0);
+
+    NEW(arm11_common_t, arm11, 1);
+
+    arm11->target = target;
+
+    /* prepare JTAG information for the new target */
+    arm11->jtag_info.chain_pos	= chain_pos;
+    arm11->jtag_info.scann_size	= 5;
+
+    arm_jtag_setup_connection(&arm11->jtag_info);
+
+    jtag_device_t *device = jtag_get_device(chain_pos);
+
+    if (device->ir_length != 5)
+    {
+	ERROR("'target arm11' expects 'jtag_device 5 0x01 0x1F 0x1E'");
+	exit(-1);
+    }
+
+    target->arch_info = arm11;
+
+    return ERROR_OK;
+}
+
+int arm11_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
+{
+    FNC_INFO;
+
+    arm11_common_t * arm11 = target->arch_info;
+
+    /* check IDCODE */
+
+    arm11_add_IR(arm11, ARM11_IDCODE, -1);
+
+    scan_field_t		idcode_field;
+
+    arm11_setup_field(arm11, 32, NULL, &arm11->device_id, &idcode_field);
+
+    jtag_add_dr_scan_vc(1, &idcode_field, TAP_PD);
+
+    /* check DIDR */
+
+    arm11_add_debug_SCAN_N(arm11, 0x00, -1);
+
+    arm11_add_IR(arm11, ARM11_INTEST, -1);
+
+    scan_field_t		chain0_fields[2];
+
+    arm11_setup_field(arm11, 32, NULL,	&arm11->didr,		chain0_fields + 0);
+    arm11_setup_field(arm11,  8, NULL,	&arm11->implementor,	chain0_fields + 1);
+
+    jtag_add_dr_scan_vc(asizeof(chain0_fields), chain0_fields, TAP_RTI);
+
+    jtag_execute_queue();
+
+
+    switch (arm11->device_id & 0x0FFFF000)
+    {
+    case 0x07B36000:	INFO("found ARM1136"); break;
+    case 0x07B56000:	INFO("found ARM1156"); break;
+    case 0x07B76000:	INFO("found ARM1176"); break;
+    default:
+    {
+	ERROR("'target arm11' expects IDCODE 0x*7B*7****");
+	exit(-1);
+    }
+    }
+
+    arm11->brp	= ((arm11->didr >> 24) & 0x0F) + 1;
+    arm11->wrp	= ((arm11->didr >> 28) & 0x0F) + 1;
+
+
+    DEBUG("IDCODE %08x IMPLEMENTOR %02x DIDR %08x",
+	arm11->device_id,
+	arm11->implementor,
+	arm11->didr);
+
+    arm11_build_reg_cache(target);
+
+
+    /* as a side-effect this reads DSCR and thus
+     * clears the ARM11_DSCR_STICKY_PRECISE_DATA_ABORT / Sticky Precise Data Abort Flag
+     * as suggested by the spec.
+     */
+
+    arm11_check_init(arm11, NULL);
+
+    return ERROR_OK;
+}
+
+int arm11_quit(void)
+{
+    FNC_INFO_NOTIMPLEMENTED;
+
+    return ERROR_OK;
+}
+
+/** Load a register that is marked !valid in the register cache */
+int arm11_get_reg(reg_t *reg)
+{
+    FNC_INFO;
+
+    target_t * target = ((arm11_reg_state_t *)reg->arch_info)->target;
+
+    if (target->state != TARGET_HALTED)
+    {
+	return ERROR_TARGET_NOT_HALTED;
+    }
+
+    /** \todo TODO: Check this. We assume that all registers are fetched debug entry. */
+
+#if 0
+    arm11_common_t *arm11 = target->arch_info;
+    const arm11_reg_defs_t * arm11_reg_info = arm11_reg_defs + ((arm11_reg_state_t *)reg->arch_info)->def_index;
+#endif
+
+    return ERROR_OK;
+}
+
+/** Change a value in the register cache */
+int arm11_set_reg(reg_t *reg, u8 *buf)
+{
+    FNC_INFO;
+
+    target_t * target = ((arm11_reg_state_t *)reg->arch_info)->target;
+    arm11_common_t *arm11 = target->arch_info;
+//    const arm11_reg_defs_t * arm11_reg_info = arm11_reg_defs + ((arm11_reg_state_t *)reg->arch_info)->def_index;
+
+    arm11->reg_values[((arm11_reg_state_t *)reg->arch_info)->def_index] = buf_get_u32(buf, 0, 32);
+    reg->valid	= 1;
+    reg->dirty	= 1;
+
+    return ERROR_OK;
+}
+
+
+void arm11_build_reg_cache(target_t *target)
+{
+    arm11_common_t *arm11 = target->arch_info;
+
+    NEW(reg_cache_t,		cache,			1);
+    NEW(reg_t,			reg_list,		ARM11_REGCACHE_COUNT);
+    NEW(arm11_reg_state_t,	arm11_reg_states,	ARM11_REGCACHE_COUNT);
+
+    if (arm11_regs_arch_type == -1)
+	arm11_regs_arch_type = register_reg_arch_type(arm11_get_reg, arm11_set_reg);
+
+    arm11->reg_list	= reg_list;
+
+    /* Build the process context cache */ 
+    cache->name		= "arm11 registers";
+    cache->next		= NULL;
+    cache->reg_list	= reg_list;
+    cache->num_regs	= ARM11_REGCACHE_COUNT;
+
+    reg_cache_t **cache_p = register_get_last_cache_p(&target->reg_cache);
+    (*cache_p) = cache;
+
+//    armv7m->core_cache = cache;
+//    armv7m->process_context = cache;
+
+    size_t i;
+
+    /* Not very elegant assertion */
+    if (ARM11_REGCACHE_COUNT != asizeof(arm11->reg_values) ||
+	ARM11_REGCACHE_COUNT != asizeof(arm11_reg_defs) ||
+	ARM11_REGCACHE_COUNT != ARM11_RC_MAX)
+    {
+	ERROR("arm11->reg_values inconsistent (%d %d %d %d)", ARM11_REGCACHE_COUNT, asizeof(arm11->reg_values), asizeof(arm11_reg_defs), ARM11_RC_MAX);
+	exit(-1);
+    }
+
+    for (i = 0; i < ARM11_REGCACHE_COUNT; i++)
+    {
+	reg_t *				r	= reg_list		+ i;
+	const arm11_reg_defs_t *	rd	= arm11_reg_defs	+ i;
+	arm11_reg_state_t *		rs	= arm11_reg_states	+ i;
+
+	r->name			= rd->name;
+	r->size			= 32;
+	r->value		= (u8 *)(arm11->reg_values + i);
+	r->dirty		= 0;
+	r->valid		= 0;
+	r->bitfield_desc	= NULL;
+	r->num_bitfields	= 0;
+	r->arch_type		= arm11_regs_arch_type;
+	r->arch_info		= rs;
+
+	rs->def_index		= i;
+	rs->target		= target;
+    }
+}
+
+#if 0
+    arm11_run_instr_data_prepare(arm11);
+
+    /* MRC p14,0,r0,c0,c5,0 */
+    arm11_run_instr_data_to_core(arm11, 0xee100e15, 0xCA00003C);
+    /* MRC p14,0,r1,c0,c5,0 */
+    arm11_run_instr_data_to_core(arm11, 0xee101e15, 0xFFFFFFFF);
+
+    arm11_run_instr_data_finish(arm11);
+#endif
+
+
diff --git a/src/target/arm11.h b/src/target/arm11.h
new file mode 100644
index 0000000000000000000000000000000000000000..4e061ae48f40787d46fc6e669fbb51ce2e03b170
--- /dev/null
+++ b/src/target/arm11.h
@@ -0,0 +1,250 @@
+/***************************************************************************
+ *   Copyright (C) 2008 digenius technology GmbH.                          *
+ *                                                                         *
+ *   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 ARM11_H
+#define ARM11_H
+
+#include "target.h"
+#include "register.h"
+#include "embeddedice.h"
+#include "arm_jtag.h"
+
+
+#define bool	int
+#define true	1
+#define false	0
+
+#define asizeof(x)	(sizeof(x) / sizeof((x)[0]))
+
+#define NEW(type, variable, items) \
+    type * variable = malloc(sizeof(type) * items)
+
+
+#define ARM11_REGCACHE_MODEREGS		0
+#define ARM11_REGCACHE_FREGS		0
+
+#define ARM11_REGCACHE_COUNT		(20 +					\
+					 23 * ARM11_REGCACHE_MODEREGS +		\
+					  9 * ARM11_REGCACHE_FREGS)
+
+
+typedef struct arm11_register_history_s
+{
+    u32	    value;
+    u8	    valid;
+}arm11_register_history_t;
+
+
+
+typedef struct arm11_common_s
+{
+    target_t *	target;
+
+    arm_jtag_t	jtag_info;
+
+    /** \name Processor type detection */
+    /*@{*/
+
+    u32		device_id;	    /**< IDCODE readout				*/
+    u32		didr;		    /**< DIDR readout (debug capabilities)	*/
+    u8		implementor;	    /**< DIDR Implementor readout		*/
+
+    size_t	brp;		    /**< Number of Breakpoint Register Pairs	*/
+    size_t	wrp;		    /**< Number of Watchpoint Register Pairs	*/
+
+    /*@}*/
+
+
+    u32		last_dscr;	    /**< Last retrieved DSCR value;
+				     *   Can be used to detect changes		*/
+
+    u8		trst_active;
+    u8		halt_requested;
+
+    /** \name Shadow registers to save processor state */
+    /*@{*/
+
+    reg_t *	reg_list;				/**< target register list */
+    u32		reg_values[ARM11_REGCACHE_COUNT];	/**< data for registers */
+
+    /*@}*/
+
+    arm11_register_history_t
+		reg_history[ARM11_REGCACHE_COUNT];	/**< register state before last resume */
+
+
+} arm11_common_t;
+
+
+/**
+ * ARM11 DBGTAP instructions 
+ * 
+ * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0301f/I1006229.html
+ */
+enum arm11_instructions
+{
+    ARM11_EXTEST    = 0x00,
+    ARM11_SCAN_N    = 0x02,
+    ARM11_RESTART   = 0x04,
+    ARM11_HALT	    = 0x08,
+    ARM11_INTEST    = 0x0C,
+    ARM11_ITRSEL    = 0x1D,
+    ARM11_IDCODE    = 0x1E,
+    ARM11_BYPASS    = 0x1F,
+};
+
+enum arm11_dscr
+{
+    ARM11_DSCR_CORE_HALTED				= 1 << 0,
+    ARM11_DSCR_CORE_RESTARTED				= 1 << 1,
+
+    ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_MASK		= 0x0F << 2,
+    ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_HALT		= 0x00 << 2,
+    ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_BREAKPOINT		= 0x01 << 2,
+    ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_WATCHPOINT		= 0x02 << 2,
+    ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_BKPT_INSTRUCTION	= 0x03 << 2,
+    ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_EDBGRQ		= 0x04 << 2,
+    ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_VECTOR_CATCH	= 0x05 << 2,
+
+    ARM11_DSCR_STICKY_PRECISE_DATA_ABORT		= 1 << 6,
+    ARM11_DSCR_STICKY_IMPRECISE_DATA_ABORT		= 1 << 7,
+    ARM11_DSCR_EXECUTE_ARM_INSTRUCTION_ENABLE		= 1 << 13,
+    ARM11_DSCR_MODE_SELECT				= 1 << 14,
+    ARM11_DSCR_WDTR_FULL				= 1 << 29,
+    ARM11_DSCR_RDTR_FULL				= 1 << 30,
+};
+
+enum arm11_cpsr
+{
+    ARM11_CPSR_T				= 1 << 5,
+    ARM11_CPSR_J				= 1 << 24,
+};
+
+enum arm11_sc7
+{
+    ARM11_SC7_NULL				= 0,
+    ARM11_SC7_VCR				= 7,
+    ARM11_SC7_PC				= 8,
+    ARM11_SC7_BVR0				= 64,
+    ARM11_SC7_BCR0				= 80,
+    ARM11_SC7_WVR0				= 96,
+    ARM11_SC7_WCR0				= 112,
+};
+
+
+
+typedef struct arm11_reg_state_s
+{
+    u32				def_index;
+    target_t *			target;
+} arm11_reg_state_t;
+
+
+
+
+/* poll current target status */
+int arm11_poll(struct target_s *target);
+/* architecture specific status reply */
+int arm11_arch_state(struct target_s *target);
+
+/* target request support */
+int arm11_target_request_data(struct target_s *target, u32 size, u8 *buffer);
+
+/* target execution control */
+int arm11_halt(struct target_s *target);
+int arm11_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution);
+int arm11_step(struct target_s *target, int current, u32 address, int handle_breakpoints);
+
+/* target reset control */
+int arm11_assert_reset(struct target_s *target);
+int arm11_deassert_reset(struct target_s *target);
+int arm11_soft_reset_halt(struct target_s *target);
+int arm11_prepare_reset_halt(struct target_s *target);
+
+/* target register access for gdb */
+int arm11_get_gdb_reg_list(struct target_s *target, struct reg_s **reg_list[], int *reg_list_size);
+
+/* target memory access 
+* size: 1 = byte (8bit), 2 = half-word (16bit), 4 = word (32bit)
+* count: number of items of <size>
+*/
+int arm11_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
+int arm11_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
+
+/* write target memory in multiples of 4 byte, optimized for writing large quantities of data */
+int arm11_bulk_write_memory(struct target_s *target, u32 address, u32 count, u8 *buffer);
+
+int arm11_checksum_memory(struct target_s *target, u32 address, u32 count, u32* checksum);
+
+/* target break-/watchpoint control 
+* rw: 0 = write, 1 = read, 2 = access
+*/
+int arm11_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
+int arm11_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
+int arm11_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint);
+int arm11_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint);
+
+/* target algorithm support */
+int arm11_run_algorithm(struct target_s *target, int num_mem_params, mem_param_t *mem_params, int num_reg_params, reg_param_t *reg_param, u32 entry_point, u32 exit_point, int timeout_ms, void *arch_info);
+
+int arm11_register_commands(struct command_context_s *cmd_ctx);
+int arm11_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
+int arm11_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
+int arm11_quit(void);
+
+
+/* helpers */
+void arm11_build_reg_cache(target_t *target);
+
+
+/* internals */
+
+void arm11_setup_field		(arm11_common_t * arm11, int num_bits, void * in_data, void * out_data, scan_field_t * field);
+void arm11_add_IR		(arm11_common_t * arm11, u8 instr, enum tap_state state);
+void arm11_add_debug_SCAN_N	(arm11_common_t * arm11, u8 chain, enum tap_state state);
+void arm11_add_debug_INST	(arm11_common_t * arm11, u32 inst, u8 * flag, enum tap_state state);
+u32  arm11_read_DSCR		(arm11_common_t * arm11);
+void arm11_write_DSCR		(arm11_common_t * arm11, u32 dscr);
+
+enum target_debug_reason arm11_get_DSCR_debug_reason(u32 dscr);
+
+void arm11_run_instr_data_prepare		(arm11_common_t * arm11);
+void arm11_run_instr_data_finish		(arm11_common_t * arm11);
+void arm11_run_instr_no_data			(arm11_common_t * arm11, u32 * opcode, size_t count);
+void arm11_run_instr_no_data1			(arm11_common_t * arm11, u32 opcode);
+void arm11_run_instr_data_to_core		(arm11_common_t * arm11, u32 opcode, u32 * data, size_t count);
+void arm11_run_instr_data_to_core1		(arm11_common_t * arm11, u32 opcode, u32 data);
+void arm11_run_instr_data_from_core		(arm11_common_t * arm11, u32 opcode, u32 * data, size_t count);
+void arm11_run_instr_data_from_core_via_r0	(arm11_common_t * arm11, u32 opcode, u32 * data);
+void arm11_run_instr_data_to_core_via_r0	(arm11_common_t * arm11, u32 opcode, u32 data);
+
+
+typedef struct arm11_sc7_action_s
+{
+    bool    write;
+    u8	    address;
+    u32	    value;
+} arm11_sc7_action_t;
+
+void arm11_sc7_run(arm11_common_t * arm11, arm11_sc7_action_t * actions, size_t count);
+void arm11_sc7_clear_bw(arm11_common_t * arm11);
+
+
+
+#endif /* ARM11_H */
diff --git a/src/target/arm11_dbgtap.c b/src/target/arm11_dbgtap.c
new file mode 100644
index 0000000000000000000000000000000000000000..13b412c5c62a3b3efa5c662d24259300a4d56fce
--- /dev/null
+++ b/src/target/arm11_dbgtap.c
@@ -0,0 +1,611 @@
+/***************************************************************************
+ *   Copyright (C) 2008 digenius technology GmbH.                          *
+ *                                                                         *
+ *   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 "arm11.h"
+#include "jtag.h"
+#include "log.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#if 0
+#define JTAG_DEBUG(expr ...) \
+	do { \
+	    log_printf (LOG_DEBUG, __FILE__, __LINE__, __FUNCTION__, expr); \
+	} while(0)
+#else
+#define JTAG_DEBUG(expr ...) \
+	do {} while(0)
+#endif
+
+/** Code de-clutter: Construct scan_field_t to write out a value
+ *
+ * \param arm11		Target state variable.
+ * \param num_bits	Length of the data field
+ * \param out_data	pointer to the data that will be sent out
+ *			<em>(data is read when it is added to the JTAG queue)</em>
+ * \param in_data	pointer to the memory that will receive data that was clocked in
+ *			<em>(data is written when the JTAG queue is executed)</em>
+ * \param field target data structure that will be initialized
+ */
+void arm11_setup_field(arm11_common_t * arm11, int num_bits, void * out_data, void * in_data, scan_field_t * field)
+{
+    field->device		= arm11->jtag_info.chain_pos;
+    field->num_bits		= num_bits;
+    field->out_mask		= NULL;
+    field->in_check_mask	= NULL;
+    field->in_check_value	= NULL;
+    field->in_handler		= NULL;
+    field->in_handler_priv	= NULL;
+
+    field->out_value		= out_data;
+    field->in_value		= in_data;
+}
+
+
+/** Write JTAG instruction register
+ *
+ * \param arm11 Target state variable.
+ * \param instr An ARM11 DBGTAP instruction. Use enum #arm11_instructions.
+ * \param state Pass the final TAP state or -1 for the default value (Pause-IR).
+ *
+ * \remarks This adds to the JTAG command queue but does \em not execute it.
+ */
+void arm11_add_IR(arm11_common_t * arm11, u8 instr, enum tap_state state)
+{
+    jtag_device_t *device = jtag_get_device(arm11->jtag_info.chain_pos);
+
+    if (buf_get_u32(device->cur_instr, 0, 5) == instr)
+    {
+	JTAG_DEBUG("IR <= 0x%02x SKIPPED", instr);
+	return;
+    }
+
+    JTAG_DEBUG("IR <= 0x%02x", instr);
+
+    scan_field_t field;
+
+    arm11_setup_field(arm11, 5, &instr, NULL, &field);
+
+    jtag_add_ir_scan_vc(1, &field, state == -1 ? TAP_PI : state);
+}
+
+/** Verify shifted out data from Scan Chain Register (SCREG)
+ *  Used as parameter to scan_field_t::in_handler in
+ *  arm11_add_debug_SCAN_N().
+ *
+ */
+static int arm11_in_handler_SCAN_N(u8 *in_value, void *priv, struct scan_field_s *field)
+{
+    /** \todo TODO: clarify why this isnt properly masked in jtag.c jtag_read_buffer() */
+    u8 v = *in_value & 0x1F;
+
+    if (v != 0x10)
+    {
+        ERROR("'arm11 target' JTAG communication error SCREG SCAN OUT 0x%02x (expected 0x10)", v);
+        exit(-1);
+    }
+
+    JTAG_DEBUG("SCREG SCAN OUT 0x%02x", v);
+    return ERROR_OK;
+}
+
+/** Select and write to Scan Chain Register (SCREG)
+ * 
+ * This function sets the instruction register to SCAN_N and writes
+ * the data register with the selected chain number.
+ *
+ * http://infocenter.arm.com/help/topic/com.arm.doc.ddi0301f/Cacbjhfg.html
+ *
+ * \param arm11	    Target state variable.
+ * \param chain	    Scan chain that will be selected.
+ * \param state	    Pass the final TAP state or -1 for the default
+ *		    value (Pause-DR).
+ *
+ * The chain takes effect when Update-DR is passed (usually when subsequently
+ * the INTEXT/EXTEST instructions are written).
+ *
+ * \warning (Obsolete) Using this twice in a row will \em fail. The first call will end
+ *          in Pause-DR. The second call, due to the IR caching, will not
+ *	    go through Capture-DR when shifting in the new scan chain number.
+ *	    As a result the verification in arm11_in_handler_SCAN_N() must
+ *	    fail.
+ *
+ * \remarks This adds to the JTAG command queue but does \em not execute it.
+ */
+
+void arm11_add_debug_SCAN_N(arm11_common_t * arm11, u8 chain, enum tap_state state)
+{
+    JTAG_DEBUG("SCREG <= 0x%02x", chain);
+
+    arm11_add_IR(arm11, ARM11_SCAN_N, -1);
+
+    scan_field_t		field;
+
+    arm11_setup_field(arm11, 5, &chain, NULL, &field);
+
+    field.in_handler = arm11_in_handler_SCAN_N;
+
+    jtag_add_dr_scan_vc(1, &field, state == -1 ? TAP_PD : state);
+}
+
+/** Write an instruction into the ITR register
+ * 
+ * \param arm11	Target state variable.
+ * \param inst	An ARM11 processor instruction/opcode.
+ * \param flag	Optional parameter to retrieve the InstCompl flag
+ *		(this will be written when the JTAG chain is executed). 
+ * \param state	Pass the final TAP state or -1 for the default
+ *		value (Run-Test/Idle).
+ *
+ * \remarks By default this ends with Run-Test/Idle state
+ * and causes the instruction to be executed. If
+ * a subsequent write to DTR is needed before
+ * executing the instruction then TAP_PD should be
+ * passed to \p state.
+ *
+ * \remarks This adds to the JTAG command queue but does \em not execute it.
+ */
+void arm11_add_debug_INST(arm11_common_t * arm11, u32 inst, u8 * flag, enum tap_state state)
+{
+    JTAG_DEBUG("INST <= 0x%08x", inst);
+
+    scan_field_t		itr[2];
+
+    arm11_setup_field(arm11, 32,    &inst,	NULL, itr + 0);
+    arm11_setup_field(arm11, 1,	    NULL,	flag, itr + 1);
+
+    jtag_add_dr_scan_vc(asizeof(itr), itr, state == -1 ? TAP_RTI : state);
+}
+
+/** Read the Debug Status and Control Register (DSCR)
+ *
+ * same as CP14 c1
+ *
+ * \param arm11 Target state variable.
+ * \return DSCR content
+ * 
+ * \remarks This is a stand-alone function that executes the JTAG command queue.
+ */
+u32 arm11_read_DSCR(arm11_common_t * arm11)
+{
+    arm11_add_debug_SCAN_N(arm11, 0x01, -1);
+
+    arm11_add_IR(arm11, ARM11_INTEST, -1);
+
+    u32			dscr;
+    scan_field_t	chain1_field;
+
+    arm11_setup_field(arm11, 32, NULL, &dscr, &chain1_field);
+
+    jtag_add_dr_scan_vc(1, &chain1_field, TAP_PD);
+
+    jtag_execute_queue();
+
+    if (arm11->last_dscr != dscr)
+        JTAG_DEBUG("DSCR  = %08x (OLD %08x)", dscr, arm11->last_dscr);
+
+    arm11->last_dscr = dscr;
+
+    return dscr;
+}
+
+/** Write the Debug Status and Control Register (DSCR)
+ *
+ * same as CP14 c1
+ *
+ * \param arm11 Target state variable.
+ * \param dscr DSCR content
+ * 
+ * \remarks This is a stand-alone function that executes the JTAG command queue.
+ */
+void arm11_write_DSCR(arm11_common_t * arm11, u32 dscr)
+{
+    arm11_add_debug_SCAN_N(arm11, 0x01, -1);
+
+    arm11_add_IR(arm11, ARM11_EXTEST, -1);
+
+    scan_field_t		    chain1_field;
+
+    arm11_setup_field(arm11, 32, &dscr, NULL, &chain1_field);
+
+    jtag_add_dr_scan_vc(1, &chain1_field, TAP_PD);
+
+    jtag_execute_queue();
+
+    JTAG_DEBUG("DSCR <= %08x (OLD %08x)", dscr, arm11->last_dscr);
+
+    arm11->last_dscr = dscr;
+}
+
+
+
+/** Get the debug reason from Debug Status and Control Register (DSCR)
+ *
+ * \param dscr DSCR value to analyze
+ * \return Debug reason
+ * 
+ */
+enum target_debug_reason arm11_get_DSCR_debug_reason(u32 dscr)
+{
+    switch (dscr & ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_MASK)
+    {
+    case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_HALT:			return DBG_REASON_DBGRQ;
+    case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_BREAKPOINT:		return DBG_REASON_BREAKPOINT;
+    case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_WATCHPOINT:		return DBG_REASON_WATCHPOINT;
+    case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_BKPT_INSTRUCTION:	return DBG_REASON_BREAKPOINT;
+    case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_EDBGRQ:		return DBG_REASON_DBGRQ;
+    case ARM11_DSCR_METHOD_OF_DEBUG_ENTRY_VECTOR_CATCH:		return DBG_REASON_BREAKPOINT;
+
+    default:
+	return DBG_REASON_DBGRQ;
+    }
+};
+
+
+
+/** Prepare the stage for ITR/DTR operations
+ * from the arm11_run_instr... group of functions.
+ *
+ * Put arm11_run_instr_data_prepare() and arm11_run_instr_data_finish()
+ * around a block of arm11_run_instr_... calls.
+ *
+ * Select scan chain 5 to allow quick access to DTR. When scan
+ * chain 4 is needed to put in a register the ITRSel instruction
+ * shortcut is used instead of actually changing the Scan_N
+ * register.
+ *
+ * \param arm11 Target state variable.
+ *
+ */
+void arm11_run_instr_data_prepare(arm11_common_t * arm11)
+{
+    arm11_add_debug_SCAN_N(arm11, 0x05, -1);
+}
+
+/** Cleanup after ITR/DTR operations
+ * from the arm11_run_instr... group of functions
+ *
+ * Put arm11_run_instr_data_prepare() and arm11_run_instr_data_finish()
+ * around a block of arm11_run_instr_... calls.
+ *
+ * Any RTI can lead to an instruction execution when
+ * scan chains 4 or 5 are selected and the IR holds
+ * INTEST or EXTEST. So we must disable that before
+ * any following activities lead to an RTI.
+ *
+ * \param arm11 Target state variable.
+ *
+ */
+void arm11_run_instr_data_finish(arm11_common_t * arm11)
+{
+    arm11_add_debug_SCAN_N(arm11, 0x00, -1);
+}
+
+
+/** Execute one or multiple instructions via ITR
+ *
+ * \pre arm11_run_instr_data_prepare() /  arm11_run_instr_data_finish() block
+ *
+ * \param arm11		Target state variable.
+ * \param opcode	Pointer to sequence of ARM opcodes
+ * \param count		Number of opcodes to execute
+ *
+ */
+void arm11_run_instr_no_data(arm11_common_t * arm11, u32 * opcode, size_t count)
+{
+    arm11_add_IR(arm11, ARM11_ITRSEL, -1);
+
+    while (count--)
+    {
+	arm11_add_debug_INST(arm11, *opcode++, NULL, TAP_RTI);
+
+	while (1)
+	{
+	    u8 flag;
+
+	    arm11_add_debug_INST(arm11, 0, &flag, count ? TAP_RTI : TAP_PD);
+
+	    jtag_execute_queue();
+
+	    if (flag)
+		break;
+	}
+    }
+}
+
+/** Execute one instruction via ITR
+ *
+ * \pre arm11_run_instr_data_prepare() /  arm11_run_instr_data_finish() block
+ *
+ * \param arm11		Target state variable.
+ * \param opcode	ARM opcode
+ *
+ */
+void arm11_run_instr_no_data1(arm11_common_t * arm11, u32 opcode)
+{
+    arm11_run_instr_no_data(arm11, &opcode, 1);
+}
+
+
+/** Execute one instruction via ITR repeatedly while
+ *  passing data to the core via DTR on each execution.
+ *
+ *  The executed instruction \em must read data from DTR.
+ *
+ * \pre arm11_run_instr_data_prepare() /  arm11_run_instr_data_finish() block
+ *
+ * \param arm11		Target state variable.
+ * \param opcode	ARM opcode
+ * \param data		Pointer to the data words to be passed to the core
+ * \param count		Number of data words and instruction repetitions
+ *
+ */
+void arm11_run_instr_data_to_core(arm11_common_t * arm11, u32 opcode, u32 * data, size_t count)
+{
+    arm11_add_IR(arm11, ARM11_ITRSEL, -1);
+
+    arm11_add_debug_INST(arm11, opcode, NULL, TAP_PD);
+
+    arm11_add_IR(arm11, ARM11_EXTEST, -1);
+
+    scan_field_t	chain5_fields[3];
+
+    u32			Data;
+    u8			Ready;
+    u8			nRetry;
+
+    arm11_setup_field(arm11, 32,    &Data,  NULL,	chain5_fields + 0);
+    arm11_setup_field(arm11,  1,    NULL,   &Ready,	chain5_fields + 1);
+    arm11_setup_field(arm11,  1,    NULL,   &nRetry,	chain5_fields + 2);
+
+    while (count--)
+    {
+	do
+	{
+	    Data	    = *data;
+
+	    jtag_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, TAP_RTI);
+	    jtag_execute_queue();
+
+	    JTAG_DEBUG("DTR  Ready %d  nRetry %d", Ready, nRetry);
+	}
+	while (!Ready);
+
+	data++;
+    }
+
+    arm11_add_IR(arm11, ARM11_INTEST, -1);
+
+    do
+    {
+	Data	    = 0;
+
+	jtag_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, TAP_PD);
+	jtag_execute_queue();
+
+	JTAG_DEBUG("DTR  Data %08x  Ready %d  nRetry %d", Data, Ready, nRetry);
+    }
+    while (!Ready);
+
+
+}
+
+/** Execute an instruction via ITR while handing data into the core via DTR.
+ *
+ *  The executed instruction \em must read data from DTR.
+ *
+ * \pre arm11_run_instr_data_prepare() /  arm11_run_instr_data_finish() block
+ *
+ * \param arm11		Target state variable.
+ * \param opcode	ARM opcode
+ * \param data		Data word to be passed to the core via DTR
+ *
+ */
+void arm11_run_instr_data_to_core1(arm11_common_t * arm11, u32 opcode, u32 data)
+{
+    arm11_run_instr_data_to_core(arm11, opcode, &data, 1);
+}
+
+
+/** Execute one instruction via ITR repeatedly while
+ *  reading data from the core via DTR on each execution.
+ *
+ *  The executed instruction \em must write data to DTR.
+ *
+ * \pre arm11_run_instr_data_prepare() /  arm11_run_instr_data_finish() block
+ *
+ * \param arm11		Target state variable.
+ * \param opcode	ARM opcode
+ * \param data		Pointer to an array that receives the data words from the core
+ * \param count		Number of data words and instruction repetitions
+ *
+ */
+void arm11_run_instr_data_from_core(arm11_common_t * arm11, u32 opcode, u32 * data, size_t count)
+{
+    arm11_add_IR(arm11, ARM11_ITRSEL, -1);
+
+    arm11_add_debug_INST(arm11, opcode, NULL, TAP_RTI);
+
+    arm11_add_IR(arm11, ARM11_INTEST, -1);
+
+    scan_field_t	chain5_fields[3];
+
+    u32			Data;
+    u8			Ready;
+    u8			nRetry;
+
+    arm11_setup_field(arm11, 32,    NULL,	&Data,	    chain5_fields + 0);
+    arm11_setup_field(arm11,  1,    NULL,	&Ready,	    chain5_fields + 1);
+    arm11_setup_field(arm11,  1,    NULL,	&nRetry,    chain5_fields + 2);
+
+    while (count--)
+    {
+	do
+	{
+	    jtag_add_dr_scan_vc(asizeof(chain5_fields), chain5_fields, count ? TAP_RTI : TAP_PD);
+	    jtag_execute_queue();
+
+	    JTAG_DEBUG("DTR  Data %08x  Ready %d  nRetry %d", Data, Ready, nRetry);
+	}
+	while (!Ready);
+
+	*data++ = Data;
+    }
+}
+
+/** Execute one instruction via ITR
+ *  then load r0 into DTR and read DTR from core.
+ *
+ *  The first executed instruction (\p opcode) should write data to r0.
+ *
+ * \pre arm11_run_instr_data_prepare() /  arm11_run_instr_data_finish() block
+ *
+ * \param arm11		Target state variable.
+ * \param opcode	ARM opcode to write r0 with the value of interest
+ * \param data		Pointer to a data word that receives the value from r0 after \p opcode was executed.
+ *
+ */
+void arm11_run_instr_data_from_core_via_r0(arm11_common_t * arm11, u32 opcode, u32 * data)
+{
+    arm11_run_instr_no_data1(arm11, opcode);
+
+    /* MCR p14,0,R0,c0,c5,0 (move r0 -> wDTR -> local var) */
+    arm11_run_instr_data_from_core(arm11, 0xEE000E15, data, 1);
+}
+
+/** Load data into core via DTR then move it to r0 then
+ *  execute one instruction via ITR
+ *
+ *  The final executed instruction (\p opcode) should read data from r0.
+ *
+ * \pre arm11_run_instr_data_prepare() /  arm11_run_instr_data_finish() block
+ *
+ * \param arm11		Target state variable.
+ * \param opcode	ARM opcode to read r0 act upon it
+ * \param data		Data word that will be written to r0 before \p opcode is executed
+ *
+ */
+void arm11_run_instr_data_to_core_via_r0(arm11_common_t * arm11, u32 opcode, u32 data)
+{
+    /* MRC p14,0,r0,c0,c5,0 */
+    arm11_run_instr_data_to_core1(arm11, 0xEE100E15, data);
+
+    arm11_run_instr_no_data1(arm11, opcode);
+}
+
+
+void arm11_sc7_run(arm11_common_t * arm11, arm11_sc7_action_t * actions, size_t count)
+{
+    arm11_add_debug_SCAN_N(arm11, 0x07, -1);
+
+    arm11_add_IR(arm11, ARM11_EXTEST, -1);
+
+    scan_field_t	chain7_fields[3];
+
+    u8		nRW;
+    u32		DataOut;
+    u8		AddressOut;
+    u8		Ready;
+    u32		DataIn;
+    u8		AddressIn;
+
+    arm11_setup_field(arm11,  1, &nRW,		&Ready,		chain7_fields + 0);
+    arm11_setup_field(arm11, 32, &DataOut,	&DataIn,	chain7_fields + 1);
+    arm11_setup_field(arm11,  7, &AddressOut,	&AddressIn,	chain7_fields + 2);
+
+    {size_t i;
+    for (i = 0; i < count + 1; i++)
+    {
+	if (i < count)
+	{
+	    nRW		= actions[i].write ? 1 : 0;
+	    DataOut	= actions[i].value;
+	    AddressOut	= actions[i].address;
+	}
+	else
+	{
+	    nRW		= 0;
+	    DataOut	= 0;
+	    AddressOut	= 0;
+	}
+
+        do
+	{
+	    JTAG_DEBUG("SC7 <= Address %02x  Data %08x    nRW %d", AddressOut, DataOut, nRW);
+
+	    jtag_add_dr_scan_vc(asizeof(chain7_fields), chain7_fields, TAP_PD);
+	    jtag_execute_queue();
+
+	    JTAG_DEBUG("SC7 => Address %02x  Data %08x  Ready %d", AddressIn, DataIn, Ready);
+	}
+	while (!Ready); /* 'nRW' is 'Ready' on read out */
+
+	if (i > 0)
+	{
+	    if (actions[i - 1].address != AddressIn)
+	    {
+		WARNING("Scan chain 7 shifted out unexpected address");
+	    }
+
+	    if (!actions[i - 1].write)
+	    {
+		actions[i - 1].value = DataIn;
+	    }
+	    else
+	    {
+		if (actions[i - 1].value != DataIn)
+		{
+		    WARNING("Scan chain 7 shifted out unexpected data");
+		}
+	    }
+	}
+    }}
+
+    {size_t i;
+    for (i = 0; i < count; i++)
+    {
+	JTAG_DEBUG("SC7 %02d: %02x %s %08x", i, actions[i].address, actions[i].write ? "<=" : "=>", actions[i].value);
+    }}
+}
+
+void arm11_sc7_clear_bw(arm11_common_t * arm11)
+{
+    size_t actions = arm11->brp + arm11->wrp;
+
+    arm11_sc7_action_t		clear_bw[actions];
+
+    {size_t i;
+    for (i = 0; i < actions; i++)
+    {
+	clear_bw[i].write	= true;
+	clear_bw[i].value	= 0;
+	clear_bw[i].address	=
+	    i < arm11->brp ?
+		ARM11_SC7_BCR0 + i :
+		ARM11_SC7_WCR0 + i - arm11->brp;
+    }}
+
+    arm11_sc7_run(arm11, clear_bw, actions);
+}
+
diff --git a/src/target/arm720t.c b/src/target/arm720t.c
index 62b70e3b6a657aa5c734d7ec20495d0aad8d439d..87a1afb463074c674d5949ad6f1e12d00d29e984 100644
--- a/src/target/arm720t.c
+++ b/src/target/arm720t.c
@@ -1,626 +1,626 @@
-/***************************************************************************
- *   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.             *
- ***************************************************************************/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "arm720t.h"
-#include "jtag.h"
-#include "log.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#if 0
-#define _DEBUG_INSTRUCTION_EXECUTION_
-#endif
-
-/* cli handling */
-int arm720t_register_commands(struct command_context_s *cmd_ctx);
-
-int arm720t_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int arm720t_handle_virt2phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int arm720t_handle_md_phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int arm720t_handle_mw_phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-
-/* forward declarations */
-int arm720t_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
-int arm720t_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
-int arm720t_quit();
-int arm720t_arch_state(struct target_s *target);
-int arm720t_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
-int arm720t_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
-int arm720t_soft_reset_halt(struct target_s *target);
-
-target_type_t arm720t_target =
-{
-	.name = "arm720t",
-
-	.poll = arm7_9_poll,
-	.arch_state = arm720t_arch_state,
-
-	.halt = arm7_9_halt,
-	.resume = arm7_9_resume,
-	.step = arm7_9_step,
-
-	.assert_reset = arm7_9_assert_reset,
-	.deassert_reset = arm7_9_deassert_reset,
-	.soft_reset_halt = arm720t_soft_reset_halt,
-	.prepare_reset_halt = arm7_9_prepare_reset_halt,
-	
-	.get_gdb_reg_list = armv4_5_get_gdb_reg_list,
-
-	.read_memory = arm720t_read_memory,
-	.write_memory = arm720t_write_memory,
-	.bulk_write_memory = arm7_9_bulk_write_memory,
-	.checksum_memory = arm7_9_checksum_memory,
-	
-	.run_algorithm = armv4_5_run_algorithm,
-
-	.add_breakpoint = arm7_9_add_breakpoint,
-	.remove_breakpoint = arm7_9_remove_breakpoint,
-	.add_watchpoint = arm7_9_add_watchpoint,
-	.remove_watchpoint = arm7_9_remove_watchpoint,
-
-	.register_commands = arm720t_register_commands,
-	.target_command = arm720t_target_command,
-	.init_target = arm720t_init_target,
-	.quit = arm720t_quit
-};
-
-int arm720t_scan_cp15(target_t *target, u32 out, u32 *in, int instruction, int clock)
-{
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-	scan_field_t fields[2];
-	u8 out_buf[4];
-	u8 instruction_buf = instruction;
-	
-	buf_set_u32(out_buf, 0, 32, flip_u32(out, 32));
-	
-	jtag_add_end_state(TAP_PD);
-	arm_jtag_scann(jtag_info, 0xf);
-	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
-		
-	fields[0].device = jtag_info->chain_pos;
-	fields[0].num_bits = 1;
-	fields[0].out_value = &instruction_buf;
-	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 = jtag_info->chain_pos;
-	fields[1].num_bits = 32;
-	fields[1].out_value = out_buf;
-	fields[1].out_mask = NULL;
-	fields[1].in_value = NULL;
-	if (in)
-	{
-		fields[1].in_handler = arm_jtag_buf_to_u32_flip;
-		fields[1].in_handler_priv = in;
-	} else
-	{
-		fields[1].in_handler = NULL;
-		fields[1].in_handler_priv = NULL;
-	}
-	fields[1].in_check_value = NULL;
-	fields[1].in_check_mask = NULL;
-	
-	jtag_add_dr_scan(2, fields, -1, NULL);
-
-	if (clock)
-		jtag_add_runtest(0, -1);
-
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_
-	jtag_execute_queue();
-
-	if (in)
-		DEBUG("out: %8.8x, in: %8.8x, instruction: %i, clock: %i", out, *in, instruction, clock);
-	else
-		DEBUG("out: %8.8x, instruction: %i, clock: %i", out, instruction, clock);
-#else
-		DEBUG("out: %8.8x, instruction: %i, clock: %i", out, instruction, clock);
-#endif
-
-	return ERROR_OK;
-}
-
-int arm720t_read_cp15(target_t *target, u32 opcode, u32 *value)
-{
-	/* fetch CP15 opcode */
-	arm720t_scan_cp15(target, opcode, NULL, 1, 1);
-	/* "DECODE" stage */
-	arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 1);
-	/* "EXECUTE" stage (1) */
-	arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 0);
-	arm720t_scan_cp15(target, 0x0, NULL, 0, 1);
-	/* "EXECUTE" stage (2) */
-	arm720t_scan_cp15(target, 0x0, NULL, 0, 1);
-	/* "EXECUTE" stage (3), CDATA is read */
-	arm720t_scan_cp15(target, ARMV4_5_NOP, value, 1, 1);
-	
-	return ERROR_OK;
-}
-
-int arm720t_write_cp15(target_t *target, u32 opcode, u32 value)
-{
-	/* fetch CP15 opcode */
-	arm720t_scan_cp15(target, opcode, NULL, 1, 1);
-	/* "DECODE" stage */
-	arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 1);
-	/* "EXECUTE" stage (1) */
-	arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 0);
-	arm720t_scan_cp15(target, 0x0, NULL, 0, 1);
-	/* "EXECUTE" stage (2) */
-	arm720t_scan_cp15(target, value, NULL, 0, 1);
-	arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 1);
-
-	return ERROR_OK;
-}
-
-u32 arm720t_get_ttb(target_t *target)
-{
-	u32 ttb = 0x0;
-
-	arm720t_read_cp15(target, 0xee120f10, &ttb);
-	jtag_execute_queue();
-	
-	ttb &= 0xffffc000;
-	
-	return ttb;
-}
-
-void arm720t_disable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_cache)
-{
-	u32 cp15_control;
-
-	/* read cp15 control register */
-	arm720t_read_cp15(target, 0xee110f10, &cp15_control);
-	jtag_execute_queue();
-		
-	if (mmu)
-		cp15_control &= ~0x1U;
-	
-	if (d_u_cache || i_cache)
-		cp15_control &= ~0x4U;
-
-	arm720t_write_cp15(target, 0xee010f10, cp15_control);
-}
-
-void arm720t_enable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_cache)
-{
-	u32 cp15_control;
-
-	/* read cp15 control register */
-	arm720t_read_cp15(target, 0xee110f10, &cp15_control);
-	jtag_execute_queue();
-		
-	if (mmu)
-		cp15_control |= 0x1U;
-	
-	if (d_u_cache || i_cache)
-		cp15_control |= 0x4U;
-	
-	arm720t_write_cp15(target, 0xee010f10, cp15_control);
-}
-
-void arm720t_post_debug_entry(target_t *target)
-{
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm7tdmi_common_t *arm7tdmi = arm7_9->arch_info;
-	arm720t_common_t *arm720t = arm7tdmi->arch_info;
-	
-	/* examine cp15 control reg */
-	arm720t_read_cp15(target, 0xee110f10, &arm720t->cp15_control_reg);
-	jtag_execute_queue();
-	DEBUG("cp15_control_reg: %8.8x", arm720t->cp15_control_reg);
-
-	arm720t->armv4_5_mmu.mmu_enabled = (arm720t->cp15_control_reg & 0x1U) ? 1 : 0;
-	arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = (arm720t->cp15_control_reg & 0x4U) ? 1 : 0;
-	arm720t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;
-
-	/* save i/d fault status and address register */
-	arm720t_read_cp15(target, 0xee150f10, &arm720t->fsr_reg);
-	arm720t_read_cp15(target, 0xee160f10, &arm720t->far_reg);
-	jtag_execute_queue();
-}
-
-void arm720t_pre_restore_context(target_t *target)
-{
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm7tdmi_common_t *arm7tdmi = arm7_9->arch_info;
-	arm720t_common_t *arm720t = arm7tdmi->arch_info;
-	
-	/* restore i/d fault status and address register */
-	arm720t_write_cp15(target, 0xee050f10, arm720t->fsr_reg);
-	arm720t_write_cp15(target, 0xee060f10, arm720t->far_reg);
-}
-
-int arm720t_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, arm7_9_common_t **arm7_9_p, arm7tdmi_common_t **arm7tdmi_p, arm720t_common_t **arm720t_p)
-{
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9;
-	arm7tdmi_common_t *arm7tdmi;
-	arm720t_common_t *arm720t;
-	
-	if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
-	{
-		return -1;
-	}
-	
-	arm7_9 = armv4_5->arch_info;
-	if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC)
-	{
-		return -1;
-	}
-	
-	arm7tdmi = arm7_9->arch_info;
-	if (arm7tdmi->common_magic != ARM7TDMI_COMMON_MAGIC)
-	{
-		return -1;
-	}
-	
-	arm720t = arm7tdmi->arch_info;
-	if (arm720t->common_magic != ARM720T_COMMON_MAGIC)
-	{
-		return -1;
-	}
-	
-	*armv4_5_p = armv4_5;
-	*arm7_9_p = arm7_9;
-	*arm7tdmi_p = arm7tdmi;
-	*arm720t_p = arm720t;
-	
-	return ERROR_OK;
-}
-
-int arm720t_arch_state(struct target_s *target)
-{
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm7tdmi_common_t *arm7tdmi = arm7_9->arch_info;
-	arm720t_common_t *arm720t = arm7tdmi->arch_info;
-	
-	char *state[] = 
-	{
-		"disabled", "enabled"
-	};
-	
-	if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
-	{
-		ERROR("BUG: called for a non-ARMv4/5 target");
-		exit(-1);
-	}
-	
-	USER("target halted in %s state due to %s, current mode: %s\n"
-			"cpsr: 0x%8.8x pc: 0x%8.8x\n"
-			"MMU: %s, Cache: %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[arm720t->armv4_5_mmu.mmu_enabled],
-			 state[arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled]);
-	
-	return ERROR_OK;
-}
-
-int arm720t_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
-{
-	int retval;
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm7tdmi_common_t *arm7tdmi = arm7_9->arch_info;
-	arm720t_common_t *arm720t = arm7tdmi->arch_info;
-	
-	/* disable cache, but leave MMU enabled */
-	if (arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled)
-		arm720t_disable_mmu_caches(target, 0, 1, 0);
-	
-	retval = arm7_9_read_memory(target, address, size, count, buffer);
-	
-	if (arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled)
-		arm720t_enable_mmu_caches(target, 0, 1, 0);
-	
-	return retval;
-}
-
-int arm720t_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
-{
-	int retval;
-	
-	if ((retval = arm7_9_write_memory(target, address, size, count, buffer)) != ERROR_OK)
-		return retval;
-
-	return retval;
-}
-
-int arm720t_soft_reset_halt(struct target_s *target)
-{
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm7tdmi_common_t *arm7tdmi = arm7_9->arch_info;
-	arm720t_common_t *arm720t = arm7tdmi->arch_info;
-	reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
-	
-	if (target->state == TARGET_RUNNING)
-	{
-		target->type->halt(target);
-	}
-	
-	while (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0)
-	{
-		embeddedice_read_reg(dbg_stat);
-		jtag_execute_queue();
-	}
-	
-	target->state = TARGET_HALTED;
-	
-	/* SVC, ARM state, IRQ and FIQ disabled */
-	buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8, 0xd3);
-	armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
-	armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
-	
-	/* start fetching from 0x0 */
-	buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, 0x0);
-	armv4_5->core_cache->reg_list[15].dirty = 1;
-	armv4_5->core_cache->reg_list[15].valid = 1;
-	
-	armv4_5->core_mode = ARMV4_5_MODE_SVC;
-	armv4_5->core_state = ARMV4_5_STATE_ARM;
-	
-	arm720t_disable_mmu_caches(target, 1, 1, 1);
-	arm720t->armv4_5_mmu.mmu_enabled = 0;
-	arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0;
-	arm720t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;
-
-	target_call_event_callbacks(target, TARGET_EVENT_HALTED);
-	
-	return ERROR_OK;
-}
-
-int arm720t_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
-{
-	arm7tdmi_init_target(cmd_ctx, target);
-		
-	return ERROR_OK;
-	
-}
-
-int arm720t_quit()
-{
-	
-	return ERROR_OK;
-}
-
-int arm720t_init_arch_info(target_t *target, arm720t_common_t *arm720t, int chain_pos, char *variant)
-{
-	arm7tdmi_common_t *arm7tdmi = &arm720t->arm7tdmi_common;
-	arm7_9_common_t *arm7_9 = &arm7tdmi->arm7_9_common;
-	
-	arm7tdmi_init_arch_info(target, arm7tdmi, chain_pos, variant);
-
-	arm7tdmi->arch_info = arm720t;
-	arm720t->common_magic = ARM720T_COMMON_MAGIC;
-	
-	arm7_9->post_debug_entry = arm720t_post_debug_entry;
-	arm7_9->pre_restore_context = arm720t_pre_restore_context;
-	
-	arm720t->armv4_5_mmu.armv4_5_cache.ctype = -1;
-	arm720t->armv4_5_mmu.get_ttb = arm720t_get_ttb;
-	arm720t->armv4_5_mmu.read_memory = arm7_9_read_memory;
-	arm720t->armv4_5_mmu.write_memory = arm7_9_write_memory;
-	arm720t->armv4_5_mmu.disable_mmu_caches = arm720t_disable_mmu_caches;
-	arm720t->armv4_5_mmu.enable_mmu_caches = arm720t_enable_mmu_caches;
-	arm720t->armv4_5_mmu.has_tiny_pages = 0;
-	arm720t->armv4_5_mmu.mmu_enabled = 0;
-	
-	return ERROR_OK;
-}
-
-int arm720t_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)
-{
-	int chain_pos;
-	char *variant = NULL;
-	arm720t_common_t *arm720t = malloc(sizeof(arm720t_common_t));
-	
-	if (argc < 4)
-	{
-		ERROR("'target arm720t' requires at least one additional argument");
-		exit(-1);
-	}
-	
-	chain_pos = strtoul(args[3], NULL, 0);
-	
-	if (argc >= 5)
-		variant = args[4];
-	
-	DEBUG("chain_pos: %i, variant: %s", chain_pos, variant);
-	
-	arm720t_init_arch_info(target, arm720t, chain_pos, variant);
-
-	return ERROR_OK;
-}
-
-int arm720t_register_commands(struct command_context_s *cmd_ctx)
-{
-	int retval;
-	command_t *arm720t_cmd;
-	
-		
-	retval = arm7tdmi_register_commands(cmd_ctx);
-	
-	arm720t_cmd = register_command(cmd_ctx, NULL, "arm720t", NULL, COMMAND_ANY, "arm720t specific commands");
-
-	register_command(cmd_ctx, arm720t_cmd, "cp15", arm720t_handle_cp15_command, COMMAND_EXEC, "display/modify cp15 register <opcode> [value]");
-	register_command(cmd_ctx, arm720t_cmd, "virt2phys", arm720t_handle_virt2phys_command, COMMAND_EXEC, "translate va to pa <va>");
-
-	register_command(cmd_ctx, arm720t_cmd, "mdw_phys", arm720t_handle_md_phys_command, COMMAND_EXEC, "display memory words <physical addr> [count]");
-	register_command(cmd_ctx, arm720t_cmd, "mdh_phys", arm720t_handle_md_phys_command, COMMAND_EXEC, "display memory half-words <physical addr> [count]");
-	register_command(cmd_ctx, arm720t_cmd, "mdb_phys", arm720t_handle_md_phys_command, COMMAND_EXEC, "display memory bytes <physical addr> [count]");
-
-	register_command(cmd_ctx, arm720t_cmd, "mww_phys", arm720t_handle_mw_phys_command, COMMAND_EXEC, "write memory word <physical addr> <value>");
-	register_command(cmd_ctx, arm720t_cmd, "mwh_phys", arm720t_handle_mw_phys_command, COMMAND_EXEC, "write memory half-word <physical addr> <value>");
-	register_command(cmd_ctx, arm720t_cmd, "mwb_phys", arm720t_handle_mw_phys_command, COMMAND_EXEC, "write memory byte <physical addr> <value>");
-	
-	return ERROR_OK;
-}
-
-int arm720t_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	int retval;
-	target_t *target = get_current_target(cmd_ctx);
-	armv4_5_common_t *armv4_5;
-	arm7_9_common_t *arm7_9;
-	arm7tdmi_common_t *arm7tdmi;
-	arm720t_common_t *arm720t;
-	arm_jtag_t *jtag_info;
-
-	if (arm720t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm7tdmi, &arm720t) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "current target isn't an ARM720t target");
-		return ERROR_OK;
-	}
-	
-	jtag_info = &arm7_9->jtag_info;
-	
-	if (target->state != TARGET_HALTED)
-	{
-		command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
-		return ERROR_OK;
-	}
-
-	/* one or more argument, access a single register (write if second argument is given */
-	if (argc >= 1)
-	{
-		u32 opcode = strtoul(args[0], NULL, 0);
-
-		if (argc == 1)
-		{
-			u32 value;
-			if ((retval = arm720t_read_cp15(target, opcode, &value)) != ERROR_OK)
-			{
-				command_print(cmd_ctx, "couldn't access cp15 with opcode 0x%8.8x", opcode);
-				return ERROR_OK;
-			}
-			jtag_execute_queue();
-			
-			command_print(cmd_ctx, "0x%8.8x: 0x%8.8x", opcode, value);
-		}
-		else if (argc == 2)
-		{
-			u32 value = strtoul(args[1], NULL, 0);
-			if ((retval = arm720t_write_cp15(target, opcode, value)) != ERROR_OK)
-			{
-				command_print(cmd_ctx, "couldn't access cp15 with opcode 0x%8.8x", opcode);
-				return ERROR_OK;
-			}
-			command_print(cmd_ctx, "0x%8.8x: 0x%8.8x", opcode, value);
-		}
-	}
-
-	return ERROR_OK;
-}
-
-int arm720t_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;
-	arm7_9_common_t *arm7_9;
-	arm7tdmi_common_t *arm7tdmi;
-	arm720t_common_t *arm720t;
-	arm_jtag_t *jtag_info;
-
-	if (arm720t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm7tdmi, &arm720t) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "current target isn't an ARM720t target");
-		return ERROR_OK;
-	}
-	
-	jtag_info = &arm7_9->jtag_info;
-	
-	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, &arm720t->armv4_5_mmu);
-}
-
-int arm720t_handle_md_phys_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;
-	arm7_9_common_t *arm7_9;
-	arm7tdmi_common_t *arm7tdmi;
-	arm720t_common_t *arm720t;
-	arm_jtag_t *jtag_info;
-
-	if (arm720t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm7tdmi, &arm720t) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "current target isn't an ARM720t target");
-		return ERROR_OK;
-	}
-	
-	jtag_info = &arm7_9->jtag_info;
-	
-	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_md_phys_command(cmd_ctx, cmd, args, argc, target, &arm720t->armv4_5_mmu);
-}
-
-int arm720t_handle_mw_phys_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;
-	arm7_9_common_t *arm7_9;
-	arm7tdmi_common_t *arm7tdmi;
-	arm720t_common_t *arm720t;
-	arm_jtag_t *jtag_info;
-
-	if (arm720t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm7tdmi, &arm720t) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "current target isn't an ARM720t target");
-		return ERROR_OK;
-	}
-	
-	jtag_info = &arm7_9->jtag_info;
-	
-	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_mw_phys_command(cmd_ctx, cmd, args, argc, target, &arm720t->armv4_5_mmu);
-}
-
+/***************************************************************************
+ *   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.             *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "arm720t.h"
+#include "jtag.h"
+#include "log.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#if 0
+#define _DEBUG_INSTRUCTION_EXECUTION_
+#endif
+
+/* cli handling */
+int arm720t_register_commands(struct command_context_s *cmd_ctx);
+
+int arm720t_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int arm720t_handle_virt2phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int arm720t_handle_md_phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int arm720t_handle_mw_phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+/* forward declarations */
+int arm720t_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
+int arm720t_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
+int arm720t_quit();
+int arm720t_arch_state(struct target_s *target);
+int arm720t_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
+int arm720t_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
+int arm720t_soft_reset_halt(struct target_s *target);
+
+target_type_t arm720t_target =
+{
+	.name = "arm720t",
+
+	.poll = arm7_9_poll,
+	.arch_state = arm720t_arch_state,
+
+	.halt = arm7_9_halt,
+	.resume = arm7_9_resume,
+	.step = arm7_9_step,
+
+	.assert_reset = arm7_9_assert_reset,
+	.deassert_reset = arm7_9_deassert_reset,
+	.soft_reset_halt = arm720t_soft_reset_halt,
+	.prepare_reset_halt = arm7_9_prepare_reset_halt,
+	
+	.get_gdb_reg_list = armv4_5_get_gdb_reg_list,
+
+	.read_memory = arm720t_read_memory,
+	.write_memory = arm720t_write_memory,
+	.bulk_write_memory = arm7_9_bulk_write_memory,
+	.checksum_memory = arm7_9_checksum_memory,
+	
+	.run_algorithm = armv4_5_run_algorithm,
+
+	.add_breakpoint = arm7_9_add_breakpoint,
+	.remove_breakpoint = arm7_9_remove_breakpoint,
+	.add_watchpoint = arm7_9_add_watchpoint,
+	.remove_watchpoint = arm7_9_remove_watchpoint,
+
+	.register_commands = arm720t_register_commands,
+	.target_command = arm720t_target_command,
+	.init_target = arm720t_init_target,
+	.quit = arm720t_quit
+};
+
+int arm720t_scan_cp15(target_t *target, u32 out, u32 *in, int instruction, int clock)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+	scan_field_t fields[2];
+	u8 out_buf[4];
+	u8 instruction_buf = instruction;
+	
+	buf_set_u32(out_buf, 0, 32, flip_u32(out, 32));
+	
+	jtag_add_end_state(TAP_PD);
+	arm_jtag_scann(jtag_info, 0xf);
+	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+		
+	fields[0].device = jtag_info->chain_pos;
+	fields[0].num_bits = 1;
+	fields[0].out_value = &instruction_buf;
+	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 = jtag_info->chain_pos;
+	fields[1].num_bits = 32;
+	fields[1].out_value = out_buf;
+	fields[1].out_mask = NULL;
+	fields[1].in_value = NULL;
+	if (in)
+	{
+		fields[1].in_handler = arm_jtag_buf_to_u32_flip;
+		fields[1].in_handler_priv = in;
+	} else
+	{
+		fields[1].in_handler = NULL;
+		fields[1].in_handler_priv = NULL;
+	}
+	fields[1].in_check_value = NULL;
+	fields[1].in_check_mask = NULL;
+	
+	jtag_add_dr_scan(2, fields, -1);
+
+	if (clock)
+		jtag_add_runtest(0, -1);
+
+#ifdef _DEBUG_INSTRUCTION_EXECUTION_
+	jtag_execute_queue();
+
+	if (in)
+		DEBUG("out: %8.8x, in: %8.8x, instruction: %i, clock: %i", out, *in, instruction, clock);
+	else
+		DEBUG("out: %8.8x, instruction: %i, clock: %i", out, instruction, clock);
+#else
+		DEBUG("out: %8.8x, instruction: %i, clock: %i", out, instruction, clock);
+#endif
+
+	return ERROR_OK;
+}
+
+int arm720t_read_cp15(target_t *target, u32 opcode, u32 *value)
+{
+	/* fetch CP15 opcode */
+	arm720t_scan_cp15(target, opcode, NULL, 1, 1);
+	/* "DECODE" stage */
+	arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 1);
+	/* "EXECUTE" stage (1) */
+	arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 0);
+	arm720t_scan_cp15(target, 0x0, NULL, 0, 1);
+	/* "EXECUTE" stage (2) */
+	arm720t_scan_cp15(target, 0x0, NULL, 0, 1);
+	/* "EXECUTE" stage (3), CDATA is read */
+	arm720t_scan_cp15(target, ARMV4_5_NOP, value, 1, 1);
+	
+	return ERROR_OK;
+}
+
+int arm720t_write_cp15(target_t *target, u32 opcode, u32 value)
+{
+	/* fetch CP15 opcode */
+	arm720t_scan_cp15(target, opcode, NULL, 1, 1);
+	/* "DECODE" stage */
+	arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 1);
+	/* "EXECUTE" stage (1) */
+	arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 0);
+	arm720t_scan_cp15(target, 0x0, NULL, 0, 1);
+	/* "EXECUTE" stage (2) */
+	arm720t_scan_cp15(target, value, NULL, 0, 1);
+	arm720t_scan_cp15(target, ARMV4_5_NOP, NULL, 1, 1);
+
+	return ERROR_OK;
+}
+
+u32 arm720t_get_ttb(target_t *target)
+{
+	u32 ttb = 0x0;
+
+	arm720t_read_cp15(target, 0xee120f10, &ttb);
+	jtag_execute_queue();
+	
+	ttb &= 0xffffc000;
+	
+	return ttb;
+}
+
+void arm720t_disable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_cache)
+{
+	u32 cp15_control;
+
+	/* read cp15 control register */
+	arm720t_read_cp15(target, 0xee110f10, &cp15_control);
+	jtag_execute_queue();
+		
+	if (mmu)
+		cp15_control &= ~0x1U;
+	
+	if (d_u_cache || i_cache)
+		cp15_control &= ~0x4U;
+
+	arm720t_write_cp15(target, 0xee010f10, cp15_control);
+}
+
+void arm720t_enable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_cache)
+{
+	u32 cp15_control;
+
+	/* read cp15 control register */
+	arm720t_read_cp15(target, 0xee110f10, &cp15_control);
+	jtag_execute_queue();
+		
+	if (mmu)
+		cp15_control |= 0x1U;
+	
+	if (d_u_cache || i_cache)
+		cp15_control |= 0x4U;
+	
+	arm720t_write_cp15(target, 0xee010f10, cp15_control);
+}
+
+void arm720t_post_debug_entry(target_t *target)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm7tdmi_common_t *arm7tdmi = arm7_9->arch_info;
+	arm720t_common_t *arm720t = arm7tdmi->arch_info;
+	
+	/* examine cp15 control reg */
+	arm720t_read_cp15(target, 0xee110f10, &arm720t->cp15_control_reg);
+	jtag_execute_queue();
+	DEBUG("cp15_control_reg: %8.8x", arm720t->cp15_control_reg);
+
+	arm720t->armv4_5_mmu.mmu_enabled = (arm720t->cp15_control_reg & 0x1U) ? 1 : 0;
+	arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = (arm720t->cp15_control_reg & 0x4U) ? 1 : 0;
+	arm720t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;
+
+	/* save i/d fault status and address register */
+	arm720t_read_cp15(target, 0xee150f10, &arm720t->fsr_reg);
+	arm720t_read_cp15(target, 0xee160f10, &arm720t->far_reg);
+	jtag_execute_queue();
+}
+
+void arm720t_pre_restore_context(target_t *target)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm7tdmi_common_t *arm7tdmi = arm7_9->arch_info;
+	arm720t_common_t *arm720t = arm7tdmi->arch_info;
+	
+	/* restore i/d fault status and address register */
+	arm720t_write_cp15(target, 0xee050f10, arm720t->fsr_reg);
+	arm720t_write_cp15(target, 0xee060f10, arm720t->far_reg);
+}
+
+int arm720t_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, arm7_9_common_t **arm7_9_p, arm7tdmi_common_t **arm7tdmi_p, arm720t_common_t **arm720t_p)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9;
+	arm7tdmi_common_t *arm7tdmi;
+	arm720t_common_t *arm720t;
+	
+	if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
+	{
+		return -1;
+	}
+	
+	arm7_9 = armv4_5->arch_info;
+	if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC)
+	{
+		return -1;
+	}
+	
+	arm7tdmi = arm7_9->arch_info;
+	if (arm7tdmi->common_magic != ARM7TDMI_COMMON_MAGIC)
+	{
+		return -1;
+	}
+	
+	arm720t = arm7tdmi->arch_info;
+	if (arm720t->common_magic != ARM720T_COMMON_MAGIC)
+	{
+		return -1;
+	}
+	
+	*armv4_5_p = armv4_5;
+	*arm7_9_p = arm7_9;
+	*arm7tdmi_p = arm7tdmi;
+	*arm720t_p = arm720t;
+	
+	return ERROR_OK;
+}
+
+int arm720t_arch_state(struct target_s *target)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm7tdmi_common_t *arm7tdmi = arm7_9->arch_info;
+	arm720t_common_t *arm720t = arm7tdmi->arch_info;
+	
+	char *state[] = 
+	{
+		"disabled", "enabled"
+	};
+	
+	if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
+	{
+		ERROR("BUG: called for a non-ARMv4/5 target");
+		exit(-1);
+	}
+	
+	USER("target halted in %s state due to %s, current mode: %s\n"
+			"cpsr: 0x%8.8x pc: 0x%8.8x\n"
+			"MMU: %s, Cache: %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[arm720t->armv4_5_mmu.mmu_enabled],
+			 state[arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled]);
+	
+	return ERROR_OK;
+}
+
+int arm720t_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
+{
+	int retval;
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm7tdmi_common_t *arm7tdmi = arm7_9->arch_info;
+	arm720t_common_t *arm720t = arm7tdmi->arch_info;
+	
+	/* disable cache, but leave MMU enabled */
+	if (arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled)
+		arm720t_disable_mmu_caches(target, 0, 1, 0);
+	
+	retval = arm7_9_read_memory(target, address, size, count, buffer);
+	
+	if (arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled)
+		arm720t_enable_mmu_caches(target, 0, 1, 0);
+	
+	return retval;
+}
+
+int arm720t_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
+{
+	int retval;
+	
+	if ((retval = arm7_9_write_memory(target, address, size, count, buffer)) != ERROR_OK)
+		return retval;
+
+	return retval;
+}
+
+int arm720t_soft_reset_halt(struct target_s *target)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm7tdmi_common_t *arm7tdmi = arm7_9->arch_info;
+	arm720t_common_t *arm720t = arm7tdmi->arch_info;
+	reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
+	
+	if (target->state == TARGET_RUNNING)
+	{
+		target->type->halt(target);
+	}
+	
+	while (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0)
+	{
+		embeddedice_read_reg(dbg_stat);
+		jtag_execute_queue();
+	}
+	
+	target->state = TARGET_HALTED;
+	
+	/* SVC, ARM state, IRQ and FIQ disabled */
+	buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8, 0xd3);
+	armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
+	armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
+	
+	/* start fetching from 0x0 */
+	buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, 0x0);
+	armv4_5->core_cache->reg_list[15].dirty = 1;
+	armv4_5->core_cache->reg_list[15].valid = 1;
+	
+	armv4_5->core_mode = ARMV4_5_MODE_SVC;
+	armv4_5->core_state = ARMV4_5_STATE_ARM;
+	
+	arm720t_disable_mmu_caches(target, 1, 1, 1);
+	arm720t->armv4_5_mmu.mmu_enabled = 0;
+	arm720t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0;
+	arm720t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;
+
+	target_call_event_callbacks(target, TARGET_EVENT_HALTED);
+	
+	return ERROR_OK;
+}
+
+int arm720t_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
+{
+	arm7tdmi_init_target(cmd_ctx, target);
+		
+	return ERROR_OK;
+	
+}
+
+int arm720t_quit()
+{
+	
+	return ERROR_OK;
+}
+
+int arm720t_init_arch_info(target_t *target, arm720t_common_t *arm720t, int chain_pos, char *variant)
+{
+	arm7tdmi_common_t *arm7tdmi = &arm720t->arm7tdmi_common;
+	arm7_9_common_t *arm7_9 = &arm7tdmi->arm7_9_common;
+	
+	arm7tdmi_init_arch_info(target, arm7tdmi, chain_pos, variant);
+
+	arm7tdmi->arch_info = arm720t;
+	arm720t->common_magic = ARM720T_COMMON_MAGIC;
+	
+	arm7_9->post_debug_entry = arm720t_post_debug_entry;
+	arm7_9->pre_restore_context = arm720t_pre_restore_context;
+	
+	arm720t->armv4_5_mmu.armv4_5_cache.ctype = -1;
+	arm720t->armv4_5_mmu.get_ttb = arm720t_get_ttb;
+	arm720t->armv4_5_mmu.read_memory = arm7_9_read_memory;
+	arm720t->armv4_5_mmu.write_memory = arm7_9_write_memory;
+	arm720t->armv4_5_mmu.disable_mmu_caches = arm720t_disable_mmu_caches;
+	arm720t->armv4_5_mmu.enable_mmu_caches = arm720t_enable_mmu_caches;
+	arm720t->armv4_5_mmu.has_tiny_pages = 0;
+	arm720t->armv4_5_mmu.mmu_enabled = 0;
+	
+	return ERROR_OK;
+}
+
+int arm720t_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)
+{
+	int chain_pos;
+	char *variant = NULL;
+	arm720t_common_t *arm720t = malloc(sizeof(arm720t_common_t));
+	
+	if (argc < 4)
+	{
+		ERROR("'target arm720t' requires at least one additional argument");
+		exit(-1);
+	}
+	
+	chain_pos = strtoul(args[3], NULL, 0);
+	
+	if (argc >= 5)
+		variant = args[4];
+	
+	DEBUG("chain_pos: %i, variant: %s", chain_pos, variant);
+	
+	arm720t_init_arch_info(target, arm720t, chain_pos, variant);
+
+	return ERROR_OK;
+}
+
+int arm720t_register_commands(struct command_context_s *cmd_ctx)
+{
+	int retval;
+	command_t *arm720t_cmd;
+	
+		
+	retval = arm7tdmi_register_commands(cmd_ctx);
+	
+	arm720t_cmd = register_command(cmd_ctx, NULL, "arm720t", NULL, COMMAND_ANY, "arm720t specific commands");
+
+	register_command(cmd_ctx, arm720t_cmd, "cp15", arm720t_handle_cp15_command, COMMAND_EXEC, "display/modify cp15 register <opcode> [value]");
+	register_command(cmd_ctx, arm720t_cmd, "virt2phys", arm720t_handle_virt2phys_command, COMMAND_EXEC, "translate va to pa <va>");
+
+	register_command(cmd_ctx, arm720t_cmd, "mdw_phys", arm720t_handle_md_phys_command, COMMAND_EXEC, "display memory words <physical addr> [count]");
+	register_command(cmd_ctx, arm720t_cmd, "mdh_phys", arm720t_handle_md_phys_command, COMMAND_EXEC, "display memory half-words <physical addr> [count]");
+	register_command(cmd_ctx, arm720t_cmd, "mdb_phys", arm720t_handle_md_phys_command, COMMAND_EXEC, "display memory bytes <physical addr> [count]");
+
+	register_command(cmd_ctx, arm720t_cmd, "mww_phys", arm720t_handle_mw_phys_command, COMMAND_EXEC, "write memory word <physical addr> <value>");
+	register_command(cmd_ctx, arm720t_cmd, "mwh_phys", arm720t_handle_mw_phys_command, COMMAND_EXEC, "write memory half-word <physical addr> <value>");
+	register_command(cmd_ctx, arm720t_cmd, "mwb_phys", arm720t_handle_mw_phys_command, COMMAND_EXEC, "write memory byte <physical addr> <value>");
+	
+	return ERROR_OK;
+}
+
+int arm720t_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	int retval;
+	target_t *target = get_current_target(cmd_ctx);
+	armv4_5_common_t *armv4_5;
+	arm7_9_common_t *arm7_9;
+	arm7tdmi_common_t *arm7tdmi;
+	arm720t_common_t *arm720t;
+	arm_jtag_t *jtag_info;
+
+	if (arm720t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm7tdmi, &arm720t) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "current target isn't an ARM720t target");
+		return ERROR_OK;
+	}
+	
+	jtag_info = &arm7_9->jtag_info;
+	
+	if (target->state != TARGET_HALTED)
+	{
+		command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+		return ERROR_OK;
+	}
+
+	/* one or more argument, access a single register (write if second argument is given */
+	if (argc >= 1)
+	{
+		u32 opcode = strtoul(args[0], NULL, 0);
+
+		if (argc == 1)
+		{
+			u32 value;
+			if ((retval = arm720t_read_cp15(target, opcode, &value)) != ERROR_OK)
+			{
+				command_print(cmd_ctx, "couldn't access cp15 with opcode 0x%8.8x", opcode);
+				return ERROR_OK;
+			}
+			jtag_execute_queue();
+			
+			command_print(cmd_ctx, "0x%8.8x: 0x%8.8x", opcode, value);
+		}
+		else if (argc == 2)
+		{
+			u32 value = strtoul(args[1], NULL, 0);
+			if ((retval = arm720t_write_cp15(target, opcode, value)) != ERROR_OK)
+			{
+				command_print(cmd_ctx, "couldn't access cp15 with opcode 0x%8.8x", opcode);
+				return ERROR_OK;
+			}
+			command_print(cmd_ctx, "0x%8.8x: 0x%8.8x", opcode, value);
+		}
+	}
+
+	return ERROR_OK;
+}
+
+int arm720t_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;
+	arm7_9_common_t *arm7_9;
+	arm7tdmi_common_t *arm7tdmi;
+	arm720t_common_t *arm720t;
+	arm_jtag_t *jtag_info;
+
+	if (arm720t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm7tdmi, &arm720t) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "current target isn't an ARM720t target");
+		return ERROR_OK;
+	}
+	
+	jtag_info = &arm7_9->jtag_info;
+	
+	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, &arm720t->armv4_5_mmu);
+}
+
+int arm720t_handle_md_phys_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;
+	arm7_9_common_t *arm7_9;
+	arm7tdmi_common_t *arm7tdmi;
+	arm720t_common_t *arm720t;
+	arm_jtag_t *jtag_info;
+
+	if (arm720t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm7tdmi, &arm720t) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "current target isn't an ARM720t target");
+		return ERROR_OK;
+	}
+	
+	jtag_info = &arm7_9->jtag_info;
+	
+	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_md_phys_command(cmd_ctx, cmd, args, argc, target, &arm720t->armv4_5_mmu);
+}
+
+int arm720t_handle_mw_phys_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;
+	arm7_9_common_t *arm7_9;
+	arm7tdmi_common_t *arm7tdmi;
+	arm720t_common_t *arm720t;
+	arm_jtag_t *jtag_info;
+
+	if (arm720t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm7tdmi, &arm720t) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "current target isn't an ARM720t target");
+		return ERROR_OK;
+	}
+	
+	jtag_info = &arm7_9->jtag_info;
+	
+	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_mw_phys_command(cmd_ctx, cmd, args, argc, target, &arm720t->armv4_5_mmu);
+}
+
diff --git a/src/target/arm7tdmi.c b/src/target/arm7tdmi.c
index c308380a6a160960581896e84c5e7a0f99ad2b77..5679bbc6e6d4898c05bb251187b08f5e16618fee 100644
--- a/src/target/arm7tdmi.c
+++ b/src/target/arm7tdmi.c
@@ -1,874 +1,874 @@
-/***************************************************************************
- *   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.             *
- ***************************************************************************/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "arm7tdmi.h"
-
-#include "arm7_9_common.h"
-#include "register.h"
-#include "target.h"
-#include "armv4_5.h"
-#include "embeddedice.h"
-#include "etm.h"
-#include "log.h"
-#include "jtag.h"
-#include "arm_jtag.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#if 0
-#define _DEBUG_INSTRUCTION_EXECUTION_
-#endif
-
-/* cli handling */
-int arm7tdmi_register_commands(struct command_context_s *cmd_ctx);
-
-/* forward declarations */
-int arm7tdmi_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
-int arm7tdmi_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
-int arm7tdmi_quit();
-
-/* target function declarations */
-int arm7tdmi_poll(struct target_s *target);
-int arm7tdmi_halt(target_t *target);
-		
-target_type_t arm7tdmi_target =
-{
-	.name = "arm7tdmi",
-
-	.poll = arm7_9_poll,
-	.arch_state = armv4_5_arch_state,
-
-	.target_request_data = arm7_9_target_request_data,
-
-	.halt = arm7_9_halt,
-	.resume = arm7_9_resume,
-	.step = arm7_9_step,
-
-	.assert_reset = arm7_9_assert_reset,
-	.deassert_reset = arm7_9_deassert_reset,
-	.soft_reset_halt = arm7_9_soft_reset_halt,
-	.prepare_reset_halt = arm7_9_prepare_reset_halt,
-
-	.get_gdb_reg_list = armv4_5_get_gdb_reg_list,
-	
-	.read_memory = arm7_9_read_memory,
-	.write_memory = arm7_9_write_memory,
-	.bulk_write_memory = arm7_9_bulk_write_memory,
-	.checksum_memory = arm7_9_checksum_memory,
-	
-	.run_algorithm = armv4_5_run_algorithm,
-	
-	.add_breakpoint = arm7_9_add_breakpoint,
-	.remove_breakpoint = arm7_9_remove_breakpoint,
-	.add_watchpoint = arm7_9_add_watchpoint,
-	.remove_watchpoint = arm7_9_remove_watchpoint,
-
-	.register_commands = arm7tdmi_register_commands,
-	.target_command = arm7tdmi_target_command,
-	.init_target = arm7tdmi_init_target,
-	.quit = arm7tdmi_quit
-};
-
-int arm7tdmi_examine_debug_reason(target_t *target)
-{
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	
-	/* only check the debug reason if we don't know it already */
-	if ((target->debug_reason != DBG_REASON_DBGRQ)
-			&& (target->debug_reason != DBG_REASON_SINGLESTEP))
-	{
-		scan_field_t fields[2];
-		u8 databus[4];
-		u8 breakpoint;
-		
-		jtag_add_end_state(TAP_PD);
-
-		fields[0].device = arm7_9->jtag_info.chain_pos;
-		fields[0].num_bits = 1;
-		fields[0].out_value = NULL;
-		fields[0].out_mask = NULL;
-		fields[0].in_value = &breakpoint;
-		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 = arm7_9->jtag_info.chain_pos;
-		fields[1].num_bits = 32;
-		fields[1].out_value = NULL;
-		fields[1].out_mask = NULL;
-		fields[1].in_value = databus;
-		fields[1].in_check_value = NULL;
-		fields[1].in_check_mask = NULL;
-		fields[1].in_handler = NULL;
-		fields[1].in_handler_priv = NULL;
-		
-		arm_jtag_scann(&arm7_9->jtag_info, 0x1);
-		arm_jtag_set_instr(&arm7_9->jtag_info, arm7_9->jtag_info.intest_instr, NULL);
-
-		jtag_add_dr_scan(2, fields, TAP_PD, NULL);
-		jtag_execute_queue();
-		
-		fields[0].in_value = NULL;
-		fields[0].out_value = &breakpoint;
-		fields[1].in_value = NULL;
-		fields[1].out_value = databus;
-		
-		jtag_add_dr_scan(2, fields, TAP_PD, NULL);
-
-		if (breakpoint & 1)
-			target->debug_reason = DBG_REASON_WATCHPOINT; 
-		else
-			target->debug_reason = DBG_REASON_BREAKPOINT; 
-	}
-
-	return ERROR_OK;
-}
-
-/* put an instruction in the ARM7TDMI pipeline or write the data bus, and optionally read data */
-int arm7tdmi_clock_out(arm_jtag_t *jtag_info, u32 out, u32 *in, int breakpoint)
-{
-	scan_field_t fields[2];
-	u8 out_buf[4];
-	u8 breakpoint_buf;
-	
-	buf_set_u32(out_buf, 0, 32, flip_u32(out, 32));
-	buf_set_u32(&breakpoint_buf, 0, 1, breakpoint);
-
-	jtag_add_end_state(TAP_PD);
-	arm_jtag_scann(jtag_info, 0x1);
-	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
-	
-	fields[0].device = jtag_info->chain_pos;
-	fields[0].num_bits = 1;
-	fields[0].out_value = &breakpoint_buf;
-	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 = jtag_info->chain_pos;
-	fields[1].num_bits = 32;
-	fields[1].out_value = out_buf;
-	fields[1].out_mask = NULL;
-	fields[1].in_value = NULL;
-	if (in)
-	{
-		fields[1].in_handler = arm_jtag_buf_to_u32_flip;
-		fields[1].in_handler_priv = in;
-	}
-	else
-	{
-		fields[1].in_handler = NULL;
-		fields[1].in_handler_priv = NULL;
-	}
-	fields[1].in_check_value = NULL;
-	fields[1].in_check_mask = NULL;
-
-	jtag_add_dr_scan(2, fields, -1, NULL);
-
-	jtag_add_runtest(0, -1);
-	
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_
-{
-		jtag_execute_queue();
-		
-		if (in)
-		{
-			DEBUG("out: 0x%8.8x, in: 0x%8.8x", out, *in);
-		}
-		else
-			DEBUG("out: 0x%8.8x", out);
-}
-#endif
-
-	return ERROR_OK;
-}
-
-/* clock the target, reading the databus */
-int arm7tdmi_clock_data_in(arm_jtag_t *jtag_info, u32 *in)
-{
-	scan_field_t fields[2];
-
-	jtag_add_end_state(TAP_PD);
-	arm_jtag_scann(jtag_info, 0x1);
-	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
-	
-	fields[0].device = jtag_info->chain_pos;
-	fields[0].num_bits = 1;
-	fields[0].out_value = NULL;
-	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 = 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 = arm_jtag_buf_to_u32_flip;
-	fields[1].in_handler_priv = in;
-	fields[1].in_check_value = NULL;
-	fields[1].in_check_mask = NULL;
-
-	jtag_add_dr_scan(2, fields, -1, NULL);
-
-	jtag_add_runtest(0, -1);
-	
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_
-{
-		jtag_execute_queue();
-			
-		if (in)
-		{
-			DEBUG("in: 0x%8.8x", *in);
-		}
-		else
-		{
-			ERROR("BUG: called with in == NULL");
-		}
-}
-#endif
-
-	return ERROR_OK;
-}
-
-/* clock the target, and read the databus
- * the *in pointer points to a buffer where elements of 'size' bytes
- * are stored in big (be==1) or little (be==0) endianness
- */ 
-int arm7tdmi_clock_data_in_endianness(arm_jtag_t *jtag_info, void *in, int size, int be)
-{
-	scan_field_t fields[2];
-
-	jtag_add_end_state(TAP_PD);
-	arm_jtag_scann(jtag_info, 0x1);
-	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
-	
-	fields[0].device = jtag_info->chain_pos;
-	fields[0].num_bits = 1;
-	fields[0].out_value = NULL;
-	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 = jtag_info->chain_pos;
-	fields[1].num_bits = 32;
-	fields[1].out_value = NULL;
-	fields[1].out_mask = NULL;
-	fields[1].in_value = NULL;
-	switch (size)
-	{
-		case 4:
-			fields[1].in_handler = (be) ? arm_jtag_buf_to_be32_flip : arm_jtag_buf_to_le32_flip;
-			break;
-		case 2:
-			fields[1].in_handler = (be) ? arm_jtag_buf_to_be16_flip : arm_jtag_buf_to_le16_flip;
-			break;
-		case 1:
-			fields[1].in_handler = arm_jtag_buf_to_8_flip;
-			break;
-	}
-	fields[1].in_handler_priv = in;
-	fields[1].in_check_value = NULL;
-	fields[1].in_check_mask = NULL;
-
-	jtag_add_dr_scan(2, fields, -1, NULL);
-
-	jtag_add_runtest(0, -1);
-	
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_
-{
-		jtag_execute_queue();
-			
-		if (in)
-		{
-			DEBUG("in: 0x%8.8x", *in);
-		}
-		else
-		{
-			ERROR("BUG: called with in == NULL");
-		}
-}
-#endif
-
-	return ERROR_OK;
-}
-
-void arm7tdmi_change_to_arm(target_t *target, u32 *r0, u32 *pc)
-{
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-	
-	/* save r0 before using it and put system in ARM state 
-	 * to allow common handling of ARM and THUMB debugging */
-	
-	/* fetch STR r0, [r0] */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), NULL, 0);
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
-	/* nothing fetched, STR r0, [r0] in Execute (2) */
-	arm7tdmi_clock_data_in(jtag_info, r0);
-
-	/* MOV r0, r15 fetched, STR in Decode */	
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_MOV(0, 15), NULL, 0);
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), NULL, 0);
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
-	/* nothing fetched, STR r0, [r0] in Execute (2) */
-	arm7tdmi_clock_data_in(jtag_info, pc);
-
-	/* use pc-relative LDR to clear r0[1:0] (for switch to ARM mode) */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), NULL, 0);
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
-	/* nothing fetched, data for LDR r0, [PC, #0] */
-	arm7tdmi_clock_out(jtag_info, 0x0, NULL, 0);
-	/* nothing fetched, data from previous cycle is written to register */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
-	
-	/* fetch BX */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_BX(0), NULL, 0);
-	/* NOP fetched, BX in Decode, MOV in Execute */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
-	/* NOP fetched, BX in Execute (1) */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
-	
-	jtag_execute_queue();
-	
-	/* fix program counter:
-	 * MOV r0, r15 was the 4th instruction (+6)
-	 * reading PC in Thumb state gives address of instruction + 4
-	 */
-	*pc -= 0xa;
-	
-}
-
-void arm7tdmi_read_core_regs(target_t *target, u32 mask, u32* core_regs[16])
-{
-	int i;
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-		
-	/* STMIA r0-15, [r0] at debug speed
-	 * register values will start to appear on 4th DCLK
-	 */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), NULL, 0);
-
-	/* fetch NOP, STM in DECODE stage */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-	/* fetch NOP, STM in EXECUTE stage (1st cycle) */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-
-	for (i = 0; i <= 15; i++)
-	{
-		if (mask & (1 << i))
-			/* nothing fetched, STM still in EXECUTE (1+i cycle) */
-			arm7tdmi_clock_data_in(jtag_info, core_regs[i]);
-	}
-
-}
-
-void arm7tdmi_read_core_regs_target_buffer(target_t *target, u32 mask, void* buffer, int size)
-{
-	int i;
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-	int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0;
-	u32 *buf_u32 = buffer;
-	u16 *buf_u16 = buffer;
-	u8 *buf_u8 = buffer;
-		
-	/* STMIA r0-15, [r0] at debug speed
-	 * register values will start to appear on 4th DCLK
-	 */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), NULL, 0);
-
-	/* fetch NOP, STM in DECODE stage */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-	/* fetch NOP, STM in EXECUTE stage (1st cycle) */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-
-	for (i = 0; i <= 15; i++)
-	{
-		/* nothing fetched, STM still in EXECUTE (1+i cycle), read databus */
-		if (mask & (1 << i))
-		{
-			switch (size)
-			{
-				case 4:
-					arm7tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
-					break;
-				case 2:
-					arm7tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);
-					break;
-				case 1:
-					arm7tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);
-					break;
-			}
-		}
-	}
-	
-}
-
-void arm7tdmi_read_xpsr(target_t *target, u32 *xpsr, int spsr)
-{
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-		
-	/* MRS r0, cpsr */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), NULL, 0);
-	
-	/* STR r0, [r15] */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_STR(0, 15), NULL, 0);
-	/* fetch NOP, STR in DECODE stage */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-	/* fetch NOP, STR in EXECUTE stage (1st cycle) */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-	/* nothing fetched, STR still in EXECUTE (2nd cycle) */
-	arm7tdmi_clock_data_in(jtag_info, xpsr);
-
-}
-
-void arm7tdmi_write_xpsr(target_t *target, u32 xpsr, int spsr)
-{
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-		
-	DEBUG("xpsr: %8.8x, spsr: %i", xpsr, spsr);
-
-	/* MSR1 fetched */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), NULL, 0);
-	/* MSR2 fetched, MSR1 in DECODE */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), NULL, 0);
-	/* MSR3 fetched, MSR1 in EXECUTE (1), MSR2 in DECODE */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), NULL, 0);
-	/* nothing fetched, MSR1 in EXECUTE (2) */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-	/* MSR4 fetched, MSR2 in EXECUTE (1), MSR3 in DECODE */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), NULL, 0);
-	/* nothing fetched, MSR2 in EXECUTE (2) */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-	/* NOP fetched, MSR3 in EXECUTE (1), MSR4 in DECODE */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-	/* nothing fetched, MSR3 in EXECUTE (2) */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-	/* NOP fetched, MSR4 in EXECUTE (1) */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-	/* nothing fetched, MSR4 in EXECUTE (2) */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-}
-
-void arm7tdmi_write_xpsr_im8(target_t *target, u8 xpsr_im, int rot, int spsr)
-{
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-		
-	DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr);
-	
-	/* MSR fetched */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), NULL, 0);
-	/* NOP fetched, MSR in DECODE */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-	/* NOP fetched, MSR in EXECUTE (1) */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-	/* nothing fetched, MSR in EXECUTE (2) */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-	
-}
-
-void arm7tdmi_write_core_regs(target_t *target, u32 mask, u32 core_regs[16])
-{
-	int i;
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-		
-	/* LDMIA r0-15, [r0] at debug speed
-	* register values will start to appear on 4th DCLK
-	*/
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), NULL, 0);
-
-	/* fetch NOP, LDM in DECODE stage */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-	/* fetch NOP, LDM in EXECUTE stage (1st cycle) */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-
-	for (i = 0; i <= 15; i++)
-	{
-		if (mask & (1 << i))
-			/* nothing fetched, LDM still in EXECUTE (1+i cycle) */
-			arm7tdmi_clock_out(jtag_info, core_regs[i], NULL, 0);
-	}
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-	
-}
-
-void arm7tdmi_load_word_regs(target_t *target, u32 mask)
-{
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-
-	/* put system-speed load-multiple into the pipeline */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 1), NULL, 0);
-
-}
-
-void arm7tdmi_load_hword_reg(target_t *target, int num)
-{
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-	
-	/* put system-speed load half-word into the pipeline */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_LDRH_IP(num, 0), NULL, 0);
-
-}
-
-void arm7tdmi_load_byte_reg(target_t *target, int num)
-{
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-
-	/* put system-speed load byte into the pipeline */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_LDRB_IP(num, 0), NULL, 0);
-
-}
-
-void arm7tdmi_store_word_regs(target_t *target, u32 mask)
-{
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-
-	/* put system-speed store-multiple into the pipeline */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask, 0, 1), NULL, 0);
-	
-}
-
-void arm7tdmi_store_hword_reg(target_t *target, int num)
-{
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-
-	/* put system-speed store half-word into the pipeline */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_STRH_IP(num, 0), NULL, 0);
-
-}
-
-void arm7tdmi_store_byte_reg(target_t *target, int num)
-{
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-
-	/* put system-speed store byte into the pipeline */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_STRB_IP(num, 0), NULL, 0);
-
-}
-
-void arm7tdmi_write_pc(target_t *target, u32 pc)
-{
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-	
-	/* LDMIA r0-15, [r0] at debug speed
-	 * register values will start to appear on 4th DCLK
-	 */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x8000, 0, 0), NULL, 0);
-	/* fetch NOP, LDM in DECODE stage */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-	/* fetch NOP, LDM in EXECUTE stage (1st cycle) */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-	/* nothing fetched, LDM in EXECUTE stage (1st cycle) load register */
-	arm7tdmi_clock_out(jtag_info, pc, NULL, 0);
-	/* nothing fetched, LDM in EXECUTE stage (2nd cycle) load register */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-	/* nothing fetched, LDM in EXECUTE stage (3rd cycle) load register */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-	/* fetch NOP, LDM in EXECUTE stage (4th cycle) */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-	/* fetch NOP, LDM in EXECUTE stage (5th cycle) */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-}
-
-void arm7tdmi_branch_resume(target_t *target)
-{
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-	
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_B(0xfffffa, 0), NULL, 0);
-
-}
-
-void arm7tdmi_branch_resume_thumb(target_t *target)
-{
-	DEBUG("-");
-	
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-	reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
-
-	/* LDMIA r0, [r0] at debug speed
-	 * register values will start to appear on 4th DCLK
-	 */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x1, 0, 0), NULL, 0);
-
-	/* fetch NOP, LDM in DECODE stage */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-	/* fetch NOP, LDM in EXECUTE stage (1st cycle) */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-	/* nothing fetched, LDM in EXECUTE stage (2nd cycle) */
-	arm7tdmi_clock_out(jtag_info, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32) | 1, NULL, 0);
-	/* nothing fetched, LDM in EXECUTE stage (3rd cycle) */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-
-	/* Branch and eXchange */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_BX(0), NULL, 0);
-	
-	embeddedice_read_reg(dbg_stat);
-	
-	/* fetch NOP, BX in DECODE stage */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-	
-	/* target is now in Thumb state */
-	embeddedice_read_reg(dbg_stat);
-	
-	/* fetch NOP, BX in EXECUTE stage (1st cycle) */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
-
-	/* target is now in Thumb state */
-	embeddedice_read_reg(dbg_stat);
-
-	/* load r0 value */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), NULL, 0);
-	/* fetch NOP, LDR in Decode */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
-	/* fetch NOP, LDR in Execute */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
-	/* nothing fetched, LDR in EXECUTE stage (2nd cycle) */
-	arm7tdmi_clock_out(jtag_info, buf_get_u32(armv4_5->core_cache->reg_list[0].value, 0, 32), NULL, 0);
-	/* nothing fetched, LDR in EXECUTE stage (3rd cycle) */
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
-	
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
-
-	embeddedice_read_reg(dbg_stat);
-	
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 1);
-	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_B(0x7f8), NULL, 0);
-
-}
-		
-void arm7tdmi_build_reg_cache(target_t *target)
-{
-	reg_cache_t **cache_p = register_get_last_cache_p(&target->reg_cache);
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-
-	(*cache_p) = armv4_5_build_reg_cache(target, armv4_5);
-	armv4_5->core_cache = (*cache_p);
-	
-	(*cache_p)->next = embeddedice_build_reg_cache(target, arm7_9);
-	arm7_9->eice_cache = (*cache_p)->next;
-	
-	if (arm7_9->etm_ctx)
-	{
-		(*cache_p)->next->next = etm_build_reg_cache(target, jtag_info, arm7_9->etm_ctx);
-		arm7_9->etm_ctx->reg_cache = (*cache_p)->next->next;
-	}
-}
-
-int arm7tdmi_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
-{
-	
-	arm7tdmi_build_reg_cache(target);
-	
-	return ERROR_OK;
-	
-}
-
-int arm7tdmi_quit()
-{
-	
-	return ERROR_OK;
-}
-
-int arm7tdmi_init_arch_info(target_t *target, arm7tdmi_common_t *arm7tdmi, int chain_pos, char *variant)
-{
-	armv4_5_common_t *armv4_5;
-	arm7_9_common_t *arm7_9;
-	
-	arm7_9 = &arm7tdmi->arm7_9_common;
-	armv4_5 = &arm7_9->armv4_5_common;
-	
-	/* prepare JTAG information for the new target */
-	arm7_9->jtag_info.chain_pos = chain_pos;
-	arm7_9->jtag_info.scann_size = 4;
-	
-	/* register arch-specific functions */
-	arm7_9->examine_debug_reason = arm7tdmi_examine_debug_reason;
-	arm7_9->change_to_arm = arm7tdmi_change_to_arm;
-	arm7_9->read_core_regs = arm7tdmi_read_core_regs;
-	arm7_9->read_core_regs_target_buffer = arm7tdmi_read_core_regs_target_buffer;
-	arm7_9->read_xpsr = arm7tdmi_read_xpsr;
-	
-	arm7_9->write_xpsr = arm7tdmi_write_xpsr;
-	arm7_9->write_xpsr_im8 = arm7tdmi_write_xpsr_im8;
-	arm7_9->write_core_regs = arm7tdmi_write_core_regs;
-	
-	arm7_9->load_word_regs = arm7tdmi_load_word_regs;
-	arm7_9->load_hword_reg = arm7tdmi_load_hword_reg;
-	arm7_9->load_byte_reg = arm7tdmi_load_byte_reg;
-	
-	arm7_9->store_word_regs = arm7tdmi_store_word_regs;
-	arm7_9->store_hword_reg = arm7tdmi_store_hword_reg;
-	arm7_9->store_byte_reg = arm7tdmi_store_byte_reg;
-	
-	arm7_9->write_pc = arm7tdmi_write_pc;
-	arm7_9->branch_resume = arm7tdmi_branch_resume;
-	arm7_9->branch_resume_thumb = arm7tdmi_branch_resume_thumb;
-	
-	arm7_9->enable_single_step = arm7_9_enable_eice_step;
-	arm7_9->disable_single_step = arm7_9_disable_eice_step;
-		
-	arm7_9->pre_debug_entry = NULL;
-	arm7_9->post_debug_entry = NULL;
-	
-	arm7_9->pre_restore_context = NULL;
-	arm7_9->post_restore_context = NULL;
-	
-	/* initialize arch-specific breakpoint handling */
-	arm7_9->arm_bkpt = 0xdeeedeee;
-	arm7_9->thumb_bkpt = 0xdeee;
-	
-	arm7_9->sw_bkpts_use_wp = 1;
-	arm7_9->sw_bkpts_enabled = 0;
-	arm7_9->dbgreq_adjust_pc = 2;
-	arm7_9->arch_info = arm7tdmi;
-
-	arm7tdmi->arch_info = NULL;
-	arm7tdmi->common_magic = ARM7TDMI_COMMON_MAGIC;
-	
-	if (variant)
-	{
-		arm7tdmi->variant = strdup(variant);
-	}
-	else
-	{
-		arm7tdmi->variant = strdup("");
-	}
-	
-	arm7_9_init_arch_info(target, arm7_9);
-
-	return ERROR_OK;
-}
-
-/* target arm7tdmi <endianess> <startup_mode> <chain_pos> <variant> */
-int arm7tdmi_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)
-{
-	int chain_pos;
-	char *variant = NULL;
-	arm7tdmi_common_t *arm7tdmi = malloc(sizeof(arm7tdmi_common_t));
-
-	if (argc < 4)
-	{
-		ERROR("'target arm7tdmi' requires at least one additional argument");
-		exit(-1);
-	}
-	
-	chain_pos = strtoul(args[3], NULL, 0);
-	
-	if (argc >= 5)
-		variant = args[4];
-	
-	arm7tdmi_init_arch_info(target, arm7tdmi, chain_pos, variant);
-	
-	return ERROR_OK;
-}
-
-int arm7tdmi_register_commands(struct command_context_s *cmd_ctx)
-{
-	int retval;
-	
-	retval = arm7_9_register_commands(cmd_ctx);
-	
-	return ERROR_OK;
-
-}
-
+/***************************************************************************
+ *   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.             *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "arm7tdmi.h"
+
+#include "arm7_9_common.h"
+#include "register.h"
+#include "target.h"
+#include "armv4_5.h"
+#include "embeddedice.h"
+#include "etm.h"
+#include "log.h"
+#include "jtag.h"
+#include "arm_jtag.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#if 0
+#define _DEBUG_INSTRUCTION_EXECUTION_
+#endif
+
+/* cli handling */
+int arm7tdmi_register_commands(struct command_context_s *cmd_ctx);
+
+/* forward declarations */
+int arm7tdmi_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
+int arm7tdmi_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
+int arm7tdmi_quit();
+
+/* target function declarations */
+int arm7tdmi_poll(struct target_s *target);
+int arm7tdmi_halt(target_t *target);
+		
+target_type_t arm7tdmi_target =
+{
+	.name = "arm7tdmi",
+
+	.poll = arm7_9_poll,
+	.arch_state = armv4_5_arch_state,
+
+	.target_request_data = arm7_9_target_request_data,
+
+	.halt = arm7_9_halt,
+	.resume = arm7_9_resume,
+	.step = arm7_9_step,
+
+	.assert_reset = arm7_9_assert_reset,
+	.deassert_reset = arm7_9_deassert_reset,
+	.soft_reset_halt = arm7_9_soft_reset_halt,
+	.prepare_reset_halt = arm7_9_prepare_reset_halt,
+
+	.get_gdb_reg_list = armv4_5_get_gdb_reg_list,
+	
+	.read_memory = arm7_9_read_memory,
+	.write_memory = arm7_9_write_memory,
+	.bulk_write_memory = arm7_9_bulk_write_memory,
+	.checksum_memory = arm7_9_checksum_memory,
+	
+	.run_algorithm = armv4_5_run_algorithm,
+	
+	.add_breakpoint = arm7_9_add_breakpoint,
+	.remove_breakpoint = arm7_9_remove_breakpoint,
+	.add_watchpoint = arm7_9_add_watchpoint,
+	.remove_watchpoint = arm7_9_remove_watchpoint,
+
+	.register_commands = arm7tdmi_register_commands,
+	.target_command = arm7tdmi_target_command,
+	.init_target = arm7tdmi_init_target,
+	.quit = arm7tdmi_quit
+};
+
+int arm7tdmi_examine_debug_reason(target_t *target)
+{
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	
+	/* only check the debug reason if we don't know it already */
+	if ((target->debug_reason != DBG_REASON_DBGRQ)
+			&& (target->debug_reason != DBG_REASON_SINGLESTEP))
+	{
+		scan_field_t fields[2];
+		u8 databus[4];
+		u8 breakpoint;
+		
+		jtag_add_end_state(TAP_PD);
+
+		fields[0].device = arm7_9->jtag_info.chain_pos;
+		fields[0].num_bits = 1;
+		fields[0].out_value = NULL;
+		fields[0].out_mask = NULL;
+		fields[0].in_value = &breakpoint;
+		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 = arm7_9->jtag_info.chain_pos;
+		fields[1].num_bits = 32;
+		fields[1].out_value = NULL;
+		fields[1].out_mask = NULL;
+		fields[1].in_value = databus;
+		fields[1].in_check_value = NULL;
+		fields[1].in_check_mask = NULL;
+		fields[1].in_handler = NULL;
+		fields[1].in_handler_priv = NULL;
+		
+		arm_jtag_scann(&arm7_9->jtag_info, 0x1);
+		arm_jtag_set_instr(&arm7_9->jtag_info, arm7_9->jtag_info.intest_instr, NULL);
+
+		jtag_add_dr_scan(2, fields, TAP_PD);
+		jtag_execute_queue();
+		
+		fields[0].in_value = NULL;
+		fields[0].out_value = &breakpoint;
+		fields[1].in_value = NULL;
+		fields[1].out_value = databus;
+		
+		jtag_add_dr_scan(2, fields, TAP_PD);
+
+		if (breakpoint & 1)
+			target->debug_reason = DBG_REASON_WATCHPOINT; 
+		else
+			target->debug_reason = DBG_REASON_BREAKPOINT; 
+	}
+
+	return ERROR_OK;
+}
+
+/* put an instruction in the ARM7TDMI pipeline or write the data bus, and optionally read data */
+int arm7tdmi_clock_out(arm_jtag_t *jtag_info, u32 out, u32 *in, int breakpoint)
+{
+	scan_field_t fields[2];
+	u8 out_buf[4];
+	u8 breakpoint_buf;
+	
+	buf_set_u32(out_buf, 0, 32, flip_u32(out, 32));
+	buf_set_u32(&breakpoint_buf, 0, 1, breakpoint);
+
+	jtag_add_end_state(TAP_PD);
+	arm_jtag_scann(jtag_info, 0x1);
+	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+	
+	fields[0].device = jtag_info->chain_pos;
+	fields[0].num_bits = 1;
+	fields[0].out_value = &breakpoint_buf;
+	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 = jtag_info->chain_pos;
+	fields[1].num_bits = 32;
+	fields[1].out_value = out_buf;
+	fields[1].out_mask = NULL;
+	fields[1].in_value = NULL;
+	if (in)
+	{
+		fields[1].in_handler = arm_jtag_buf_to_u32_flip;
+		fields[1].in_handler_priv = in;
+	}
+	else
+	{
+		fields[1].in_handler = NULL;
+		fields[1].in_handler_priv = NULL;
+	}
+	fields[1].in_check_value = NULL;
+	fields[1].in_check_mask = NULL;
+
+	jtag_add_dr_scan(2, fields, -1);
+
+	jtag_add_runtest(0, -1);
+	
+#ifdef _DEBUG_INSTRUCTION_EXECUTION_
+{
+		jtag_execute_queue();
+		
+		if (in)
+		{
+			DEBUG("out: 0x%8.8x, in: 0x%8.8x", out, *in);
+		}
+		else
+			DEBUG("out: 0x%8.8x", out);
+}
+#endif
+
+	return ERROR_OK;
+}
+
+/* clock the target, reading the databus */
+int arm7tdmi_clock_data_in(arm_jtag_t *jtag_info, u32 *in)
+{
+	scan_field_t fields[2];
+
+	jtag_add_end_state(TAP_PD);
+	arm_jtag_scann(jtag_info, 0x1);
+	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+	
+	fields[0].device = jtag_info->chain_pos;
+	fields[0].num_bits = 1;
+	fields[0].out_value = NULL;
+	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 = 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 = arm_jtag_buf_to_u32_flip;
+	fields[1].in_handler_priv = in;
+	fields[1].in_check_value = NULL;
+	fields[1].in_check_mask = NULL;
+
+	jtag_add_dr_scan(2, fields, -1);
+
+	jtag_add_runtest(0, -1);
+	
+#ifdef _DEBUG_INSTRUCTION_EXECUTION_
+{
+		jtag_execute_queue();
+			
+		if (in)
+		{
+			DEBUG("in: 0x%8.8x", *in);
+		}
+		else
+		{
+			ERROR("BUG: called with in == NULL");
+		}
+}
+#endif
+
+	return ERROR_OK;
+}
+
+/* clock the target, and read the databus
+ * the *in pointer points to a buffer where elements of 'size' bytes
+ * are stored in big (be==1) or little (be==0) endianness
+ */ 
+int arm7tdmi_clock_data_in_endianness(arm_jtag_t *jtag_info, void *in, int size, int be)
+{
+	scan_field_t fields[2];
+
+	jtag_add_end_state(TAP_PD);
+	arm_jtag_scann(jtag_info, 0x1);
+	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+	
+	fields[0].device = jtag_info->chain_pos;
+	fields[0].num_bits = 1;
+	fields[0].out_value = NULL;
+	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 = jtag_info->chain_pos;
+	fields[1].num_bits = 32;
+	fields[1].out_value = NULL;
+	fields[1].out_mask = NULL;
+	fields[1].in_value = NULL;
+	switch (size)
+	{
+		case 4:
+			fields[1].in_handler = (be) ? arm_jtag_buf_to_be32_flip : arm_jtag_buf_to_le32_flip;
+			break;
+		case 2:
+			fields[1].in_handler = (be) ? arm_jtag_buf_to_be16_flip : arm_jtag_buf_to_le16_flip;
+			break;
+		case 1:
+			fields[1].in_handler = arm_jtag_buf_to_8_flip;
+			break;
+	}
+	fields[1].in_handler_priv = in;
+	fields[1].in_check_value = NULL;
+	fields[1].in_check_mask = NULL;
+
+	jtag_add_dr_scan(2, fields, -1);
+
+	jtag_add_runtest(0, -1);
+	
+#ifdef _DEBUG_INSTRUCTION_EXECUTION_
+{
+		jtag_execute_queue();
+			
+		if (in)
+		{
+			DEBUG("in: 0x%8.8x", *in);
+		}
+		else
+		{
+			ERROR("BUG: called with in == NULL");
+		}
+}
+#endif
+
+	return ERROR_OK;
+}
+
+void arm7tdmi_change_to_arm(target_t *target, u32 *r0, u32 *pc)
+{
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+	
+	/* save r0 before using it and put system in ARM state 
+	 * to allow common handling of ARM and THUMB debugging */
+	
+	/* fetch STR r0, [r0] */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), NULL, 0);
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
+	/* nothing fetched, STR r0, [r0] in Execute (2) */
+	arm7tdmi_clock_data_in(jtag_info, r0);
+
+	/* MOV r0, r15 fetched, STR in Decode */	
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_MOV(0, 15), NULL, 0);
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), NULL, 0);
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
+	/* nothing fetched, STR r0, [r0] in Execute (2) */
+	arm7tdmi_clock_data_in(jtag_info, pc);
+
+	/* use pc-relative LDR to clear r0[1:0] (for switch to ARM mode) */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), NULL, 0);
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
+	/* nothing fetched, data for LDR r0, [PC, #0] */
+	arm7tdmi_clock_out(jtag_info, 0x0, NULL, 0);
+	/* nothing fetched, data from previous cycle is written to register */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
+	
+	/* fetch BX */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_BX(0), NULL, 0);
+	/* NOP fetched, BX in Decode, MOV in Execute */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
+	/* NOP fetched, BX in Execute (1) */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
+	
+	jtag_execute_queue();
+	
+	/* fix program counter:
+	 * MOV r0, r15 was the 4th instruction (+6)
+	 * reading PC in Thumb state gives address of instruction + 4
+	 */
+	*pc -= 0xa;
+	
+}
+
+void arm7tdmi_read_core_regs(target_t *target, u32 mask, u32* core_regs[16])
+{
+	int i;
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+		
+	/* STMIA r0-15, [r0] at debug speed
+	 * register values will start to appear on 4th DCLK
+	 */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), NULL, 0);
+
+	/* fetch NOP, STM in DECODE stage */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+	/* fetch NOP, STM in EXECUTE stage (1st cycle) */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+
+	for (i = 0; i <= 15; i++)
+	{
+		if (mask & (1 << i))
+			/* nothing fetched, STM still in EXECUTE (1+i cycle) */
+			arm7tdmi_clock_data_in(jtag_info, core_regs[i]);
+	}
+
+}
+
+void arm7tdmi_read_core_regs_target_buffer(target_t *target, u32 mask, void* buffer, int size)
+{
+	int i;
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+	int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0;
+	u32 *buf_u32 = buffer;
+	u16 *buf_u16 = buffer;
+	u8 *buf_u8 = buffer;
+		
+	/* STMIA r0-15, [r0] at debug speed
+	 * register values will start to appear on 4th DCLK
+	 */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), NULL, 0);
+
+	/* fetch NOP, STM in DECODE stage */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+	/* fetch NOP, STM in EXECUTE stage (1st cycle) */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+
+	for (i = 0; i <= 15; i++)
+	{
+		/* nothing fetched, STM still in EXECUTE (1+i cycle), read databus */
+		if (mask & (1 << i))
+		{
+			switch (size)
+			{
+				case 4:
+					arm7tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
+					break;
+				case 2:
+					arm7tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);
+					break;
+				case 1:
+					arm7tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);
+					break;
+			}
+		}
+	}
+	
+}
+
+void arm7tdmi_read_xpsr(target_t *target, u32 *xpsr, int spsr)
+{
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+		
+	/* MRS r0, cpsr */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), NULL, 0);
+	
+	/* STR r0, [r15] */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_STR(0, 15), NULL, 0);
+	/* fetch NOP, STR in DECODE stage */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+	/* fetch NOP, STR in EXECUTE stage (1st cycle) */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+	/* nothing fetched, STR still in EXECUTE (2nd cycle) */
+	arm7tdmi_clock_data_in(jtag_info, xpsr);
+
+}
+
+void arm7tdmi_write_xpsr(target_t *target, u32 xpsr, int spsr)
+{
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+		
+	DEBUG("xpsr: %8.8x, spsr: %i", xpsr, spsr);
+
+	/* MSR1 fetched */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), NULL, 0);
+	/* MSR2 fetched, MSR1 in DECODE */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), NULL, 0);
+	/* MSR3 fetched, MSR1 in EXECUTE (1), MSR2 in DECODE */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), NULL, 0);
+	/* nothing fetched, MSR1 in EXECUTE (2) */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+	/* MSR4 fetched, MSR2 in EXECUTE (1), MSR3 in DECODE */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), NULL, 0);
+	/* nothing fetched, MSR2 in EXECUTE (2) */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+	/* NOP fetched, MSR3 in EXECUTE (1), MSR4 in DECODE */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+	/* nothing fetched, MSR3 in EXECUTE (2) */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+	/* NOP fetched, MSR4 in EXECUTE (1) */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+	/* nothing fetched, MSR4 in EXECUTE (2) */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+}
+
+void arm7tdmi_write_xpsr_im8(target_t *target, u8 xpsr_im, int rot, int spsr)
+{
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+		
+	DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr);
+	
+	/* MSR fetched */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), NULL, 0);
+	/* NOP fetched, MSR in DECODE */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+	/* NOP fetched, MSR in EXECUTE (1) */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+	/* nothing fetched, MSR in EXECUTE (2) */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+	
+}
+
+void arm7tdmi_write_core_regs(target_t *target, u32 mask, u32 core_regs[16])
+{
+	int i;
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+		
+	/* LDMIA r0-15, [r0] at debug speed
+	* register values will start to appear on 4th DCLK
+	*/
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), NULL, 0);
+
+	/* fetch NOP, LDM in DECODE stage */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+	/* fetch NOP, LDM in EXECUTE stage (1st cycle) */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+
+	for (i = 0; i <= 15; i++)
+	{
+		if (mask & (1 << i))
+			/* nothing fetched, LDM still in EXECUTE (1+i cycle) */
+			arm7tdmi_clock_out(jtag_info, core_regs[i], NULL, 0);
+	}
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+	
+}
+
+void arm7tdmi_load_word_regs(target_t *target, u32 mask)
+{
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+
+	/* put system-speed load-multiple into the pipeline */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 1), NULL, 0);
+
+}
+
+void arm7tdmi_load_hword_reg(target_t *target, int num)
+{
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+	
+	/* put system-speed load half-word into the pipeline */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_LDRH_IP(num, 0), NULL, 0);
+
+}
+
+void arm7tdmi_load_byte_reg(target_t *target, int num)
+{
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+
+	/* put system-speed load byte into the pipeline */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_LDRB_IP(num, 0), NULL, 0);
+
+}
+
+void arm7tdmi_store_word_regs(target_t *target, u32 mask)
+{
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+
+	/* put system-speed store-multiple into the pipeline */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask, 0, 1), NULL, 0);
+	
+}
+
+void arm7tdmi_store_hword_reg(target_t *target, int num)
+{
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+
+	/* put system-speed store half-word into the pipeline */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_STRH_IP(num, 0), NULL, 0);
+
+}
+
+void arm7tdmi_store_byte_reg(target_t *target, int num)
+{
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+
+	/* put system-speed store byte into the pipeline */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_STRB_IP(num, 0), NULL, 0);
+
+}
+
+void arm7tdmi_write_pc(target_t *target, u32 pc)
+{
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+	
+	/* LDMIA r0-15, [r0] at debug speed
+	 * register values will start to appear on 4th DCLK
+	 */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x8000, 0, 0), NULL, 0);
+	/* fetch NOP, LDM in DECODE stage */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+	/* fetch NOP, LDM in EXECUTE stage (1st cycle) */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+	/* nothing fetched, LDM in EXECUTE stage (1st cycle) load register */
+	arm7tdmi_clock_out(jtag_info, pc, NULL, 0);
+	/* nothing fetched, LDM in EXECUTE stage (2nd cycle) load register */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+	/* nothing fetched, LDM in EXECUTE stage (3rd cycle) load register */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+	/* fetch NOP, LDM in EXECUTE stage (4th cycle) */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+	/* fetch NOP, LDM in EXECUTE stage (5th cycle) */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+}
+
+void arm7tdmi_branch_resume(target_t *target)
+{
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+	
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 1);
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_B(0xfffffa, 0), NULL, 0);
+
+}
+
+void arm7tdmi_branch_resume_thumb(target_t *target)
+{
+	DEBUG("-");
+	
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+	reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
+
+	/* LDMIA r0, [r0] at debug speed
+	 * register values will start to appear on 4th DCLK
+	 */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x1, 0, 0), NULL, 0);
+
+	/* fetch NOP, LDM in DECODE stage */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+	/* fetch NOP, LDM in EXECUTE stage (1st cycle) */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+	/* nothing fetched, LDM in EXECUTE stage (2nd cycle) */
+	arm7tdmi_clock_out(jtag_info, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32) | 1, NULL, 0);
+	/* nothing fetched, LDM in EXECUTE stage (3rd cycle) */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+
+	/* Branch and eXchange */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_BX(0), NULL, 0);
+	
+	embeddedice_read_reg(dbg_stat);
+	
+	/* fetch NOP, BX in DECODE stage */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+	
+	/* target is now in Thumb state */
+	embeddedice_read_reg(dbg_stat);
+	
+	/* fetch NOP, BX in EXECUTE stage (1st cycle) */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_NOP, NULL, 0);
+
+	/* target is now in Thumb state */
+	embeddedice_read_reg(dbg_stat);
+
+	/* load r0 value */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), NULL, 0);
+	/* fetch NOP, LDR in Decode */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
+	/* fetch NOP, LDR in Execute */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
+	/* nothing fetched, LDR in EXECUTE stage (2nd cycle) */
+	arm7tdmi_clock_out(jtag_info, buf_get_u32(armv4_5->core_cache->reg_list[0].value, 0, 32), NULL, 0);
+	/* nothing fetched, LDR in EXECUTE stage (3rd cycle) */
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
+	
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 0);
+
+	embeddedice_read_reg(dbg_stat);
+	
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, NULL, 1);
+	arm7tdmi_clock_out(jtag_info, ARMV4_5_T_B(0x7f8), NULL, 0);
+
+}
+		
+void arm7tdmi_build_reg_cache(target_t *target)
+{
+	reg_cache_t **cache_p = register_get_last_cache_p(&target->reg_cache);
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+
+	(*cache_p) = armv4_5_build_reg_cache(target, armv4_5);
+	armv4_5->core_cache = (*cache_p);
+	
+	(*cache_p)->next = embeddedice_build_reg_cache(target, arm7_9);
+	arm7_9->eice_cache = (*cache_p)->next;
+	
+	if (arm7_9->etm_ctx)
+	{
+		(*cache_p)->next->next = etm_build_reg_cache(target, jtag_info, arm7_9->etm_ctx);
+		arm7_9->etm_ctx->reg_cache = (*cache_p)->next->next;
+	}
+}
+
+int arm7tdmi_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
+{
+	
+	arm7tdmi_build_reg_cache(target);
+	
+	return ERROR_OK;
+	
+}
+
+int arm7tdmi_quit()
+{
+	
+	return ERROR_OK;
+}
+
+int arm7tdmi_init_arch_info(target_t *target, arm7tdmi_common_t *arm7tdmi, int chain_pos, char *variant)
+{
+	armv4_5_common_t *armv4_5;
+	arm7_9_common_t *arm7_9;
+	
+	arm7_9 = &arm7tdmi->arm7_9_common;
+	armv4_5 = &arm7_9->armv4_5_common;
+	
+	/* prepare JTAG information for the new target */
+	arm7_9->jtag_info.chain_pos = chain_pos;
+	arm7_9->jtag_info.scann_size = 4;
+	
+	/* register arch-specific functions */
+	arm7_9->examine_debug_reason = arm7tdmi_examine_debug_reason;
+	arm7_9->change_to_arm = arm7tdmi_change_to_arm;
+	arm7_9->read_core_regs = arm7tdmi_read_core_regs;
+	arm7_9->read_core_regs_target_buffer = arm7tdmi_read_core_regs_target_buffer;
+	arm7_9->read_xpsr = arm7tdmi_read_xpsr;
+	
+	arm7_9->write_xpsr = arm7tdmi_write_xpsr;
+	arm7_9->write_xpsr_im8 = arm7tdmi_write_xpsr_im8;
+	arm7_9->write_core_regs = arm7tdmi_write_core_regs;
+	
+	arm7_9->load_word_regs = arm7tdmi_load_word_regs;
+	arm7_9->load_hword_reg = arm7tdmi_load_hword_reg;
+	arm7_9->load_byte_reg = arm7tdmi_load_byte_reg;
+	
+	arm7_9->store_word_regs = arm7tdmi_store_word_regs;
+	arm7_9->store_hword_reg = arm7tdmi_store_hword_reg;
+	arm7_9->store_byte_reg = arm7tdmi_store_byte_reg;
+	
+	arm7_9->write_pc = arm7tdmi_write_pc;
+	arm7_9->branch_resume = arm7tdmi_branch_resume;
+	arm7_9->branch_resume_thumb = arm7tdmi_branch_resume_thumb;
+	
+	arm7_9->enable_single_step = arm7_9_enable_eice_step;
+	arm7_9->disable_single_step = arm7_9_disable_eice_step;
+		
+	arm7_9->pre_debug_entry = NULL;
+	arm7_9->post_debug_entry = NULL;
+	
+	arm7_9->pre_restore_context = NULL;
+	arm7_9->post_restore_context = NULL;
+	
+	/* initialize arch-specific breakpoint handling */
+	arm7_9->arm_bkpt = 0xdeeedeee;
+	arm7_9->thumb_bkpt = 0xdeee;
+	
+	arm7_9->sw_bkpts_use_wp = 1;
+	arm7_9->sw_bkpts_enabled = 0;
+	arm7_9->dbgreq_adjust_pc = 2;
+	arm7_9->arch_info = arm7tdmi;
+
+	arm7tdmi->arch_info = NULL;
+	arm7tdmi->common_magic = ARM7TDMI_COMMON_MAGIC;
+	
+	if (variant)
+	{
+		arm7tdmi->variant = strdup(variant);
+	}
+	else
+	{
+		arm7tdmi->variant = strdup("");
+	}
+	
+	arm7_9_init_arch_info(target, arm7_9);
+
+	return ERROR_OK;
+}
+
+/* target arm7tdmi <endianess> <startup_mode> <chain_pos> <variant> */
+int arm7tdmi_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)
+{
+	int chain_pos;
+	char *variant = NULL;
+	arm7tdmi_common_t *arm7tdmi = malloc(sizeof(arm7tdmi_common_t));
+
+	if (argc < 4)
+	{
+		ERROR("'target arm7tdmi' requires at least one additional argument");
+		exit(-1);
+	}
+	
+	chain_pos = strtoul(args[3], NULL, 0);
+	
+	if (argc >= 5)
+		variant = args[4];
+	
+	arm7tdmi_init_arch_info(target, arm7tdmi, chain_pos, variant);
+	
+	return ERROR_OK;
+}
+
+int arm7tdmi_register_commands(struct command_context_s *cmd_ctx)
+{
+	int retval;
+	
+	retval = arm7_9_register_commands(cmd_ctx);
+	
+	return ERROR_OK;
+
+}
+
diff --git a/src/target/arm920t.c b/src/target/arm920t.c
index bf159dbeb388606d488fee6f4a98b32ab41df9a6..17c539736d2ae77040e74385c7b86c0ebea48c48 100644
--- a/src/target/arm920t.c
+++ b/src/target/arm920t.c
@@ -1,1485 +1,1485 @@
-/***************************************************************************
- *   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.             *
- ***************************************************************************/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "arm920t.h"
-#include "jtag.h"
-#include "log.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#if 0
-#define _DEBUG_INSTRUCTION_EXECUTION_
-#endif
-
-/* cli handling */
-int arm920t_register_commands(struct command_context_s *cmd_ctx);
-
-int arm920t_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int arm920t_handle_cp15i_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int arm920t_handle_virt2phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int arm920t_handle_cache_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int arm920t_handle_md_phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int arm920t_handle_mw_phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-
-int arm920t_handle_read_cache_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int arm920t_handle_read_mmu_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-
-/* forward declarations */
-int arm920t_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
-int arm920t_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
-int arm920t_quit();
-int arm920t_arch_state(struct target_s *target);
-int arm920t_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
-int arm920t_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
-int arm920t_soft_reset_halt(struct target_s *target);
-
-#define ARM920T_CP15_PHYS_ADDR(x, y, z) ((x << 5) | (y << 1) << (z))
-
-target_type_t arm920t_target =
-{
-	.name = "arm920t",
-
-	.poll = arm7_9_poll,
-	.arch_state = arm920t_arch_state,
-
-	.target_request_data = arm7_9_target_request_data,
-
-	.halt = arm7_9_halt,
-	.resume = arm7_9_resume,
-	.step = arm7_9_step,
-
-	.assert_reset = arm7_9_assert_reset,
-	.deassert_reset = arm7_9_deassert_reset,
-	.soft_reset_halt = arm920t_soft_reset_halt,
-	.prepare_reset_halt = arm7_9_prepare_reset_halt,
-	
-	.get_gdb_reg_list = armv4_5_get_gdb_reg_list,
-
-	.read_memory = arm920t_read_memory,
-	.write_memory = arm920t_write_memory,
-	.bulk_write_memory = arm7_9_bulk_write_memory,
-	.checksum_memory = arm7_9_checksum_memory,
-	
-	.run_algorithm = armv4_5_run_algorithm,
-
-	.add_breakpoint = arm7_9_add_breakpoint,
-	.remove_breakpoint = arm7_9_remove_breakpoint,
-	.add_watchpoint = arm7_9_add_watchpoint,
-	.remove_watchpoint = arm7_9_remove_watchpoint,
-
-	.register_commands = arm920t_register_commands,
-	.target_command = arm920t_target_command,
-	.init_target = arm920t_init_target,
-	.quit = arm920t_quit
-};
-
-int arm920t_read_cp15_physical(target_t *target, int reg_addr, u32 *value)
-{
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-	scan_field_t fields[4];
-	u8 access_type_buf = 1;
-	u8 reg_addr_buf = reg_addr & 0x3f;
-	u8 nr_w_buf = 0;
-	
-	jtag_add_end_state(TAP_RTI);
-	arm_jtag_scann(jtag_info, 0xf);
-	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
-
-	fields[0].device = jtag_info->chain_pos;
-	fields[0].num_bits = 1;
-	fields[0].out_value = &access_type_buf;
-	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 = 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_check_value = NULL;
-	fields[1].in_check_mask = NULL;
-	fields[1].in_handler = NULL;
-	fields[1].in_handler_priv = NULL;
-
-	fields[2].device = jtag_info->chain_pos;
-	fields[2].num_bits = 6;
-	fields[2].out_value = &reg_addr_buf;
-	fields[2].out_mask = NULL;
-	fields[2].in_value = NULL;
-	fields[2].in_check_value = NULL;
-	fields[2].in_check_mask = NULL;
-	fields[2].in_handler = NULL;
-	fields[2].in_handler_priv = NULL;
-
-	fields[3].device = jtag_info->chain_pos;
-	fields[3].num_bits = 1;
-	fields[3].out_value = &nr_w_buf;
-	fields[3].out_mask = NULL;
-	fields[3].in_value = NULL;
-	fields[3].in_check_value = NULL;
-	fields[3].in_check_mask = NULL;
-	fields[3].in_handler = NULL;
-	fields[3].in_handler_priv = NULL;
-	
-	jtag_add_dr_scan(4, fields, -1, NULL);
-
-	fields[1].in_handler_priv = value;
-	fields[1].in_handler = arm_jtag_buf_to_u32;
-
-	jtag_add_dr_scan(4, fields, -1, NULL);
-
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_
-	jtag_execute_queue();
-	DEBUG("addr: 0x%x value: %8.8x", reg_addr, *value);
-#endif
-
-	return ERROR_OK;
-}
-
-int arm920t_write_cp15_physical(target_t *target, int reg_addr, u32 value)
-{
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-	scan_field_t fields[4];
-	u8 access_type_buf = 1;
-	u8 reg_addr_buf = reg_addr & 0x3f;
-	u8 nr_w_buf = 1;
-	u8 value_buf[4];
-	
-	buf_set_u32(value_buf, 0, 32, value);
-	
-	jtag_add_end_state(TAP_RTI);
-	arm_jtag_scann(jtag_info, 0xf);
-	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
-
-	fields[0].device = jtag_info->chain_pos;
-	fields[0].num_bits = 1;
-	fields[0].out_value = &access_type_buf;
-	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 = jtag_info->chain_pos;
-	fields[1].num_bits = 32;
-	fields[1].out_value = value_buf;
-	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;
-
-	fields[2].device = jtag_info->chain_pos;
-	fields[2].num_bits = 6;
-	fields[2].out_value = &reg_addr_buf;
-	fields[2].out_mask = NULL;
-	fields[2].in_value = NULL;
-	fields[2].in_check_value = NULL;
-	fields[2].in_check_mask = NULL;
-	fields[2].in_handler = NULL;
-	fields[2].in_handler_priv = NULL;
-
-	fields[3].device = jtag_info->chain_pos;
-	fields[3].num_bits = 1;
-	fields[3].out_value = &nr_w_buf;
-	fields[3].out_mask = NULL;
-	fields[3].in_value = NULL;
-	fields[3].in_check_value = NULL;
-	fields[3].in_check_mask = NULL;
-	fields[3].in_handler = NULL;
-	fields[3].in_handler_priv = NULL;
-	
-	jtag_add_dr_scan(4, fields, -1, NULL);
-
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_
-	DEBUG("addr: 0x%x value: %8.8x", reg_addr, value);
-#endif
-
-	return ERROR_OK;
-}
-
-int arm920t_execute_cp15(target_t *target, u32 cp15_opcode, u32 arm_opcode)
-{
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-	scan_field_t fields[4];
-	u8 access_type_buf = 0;		/* interpreted access */
-	u8 reg_addr_buf = 0x0;
-	u8 nr_w_buf = 0;
-	u8 cp15_opcode_buf[4];
-	
-	jtag_add_end_state(TAP_RTI);
-	arm_jtag_scann(jtag_info, 0xf);
-	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
-	
-	buf_set_u32(cp15_opcode_buf, 0, 32, cp15_opcode);
-
-	fields[0].device = jtag_info->chain_pos;
-	fields[0].num_bits = 1;
-	fields[0].out_value = &access_type_buf;
-	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 = jtag_info->chain_pos;
-	fields[1].num_bits = 32;
-	fields[1].out_value = cp15_opcode_buf;
-	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;
-
-	fields[2].device = jtag_info->chain_pos;
-	fields[2].num_bits = 6;
-	fields[2].out_value = &reg_addr_buf;
-	fields[2].out_mask = NULL;
-	fields[2].in_value = NULL;
-	fields[2].in_check_value = NULL;
-	fields[2].in_check_mask = NULL;
-	fields[2].in_handler = NULL;
-	fields[2].in_handler_priv = NULL;
-
-	fields[3].device = jtag_info->chain_pos;
-	fields[3].num_bits = 1;
-	fields[3].out_value = &nr_w_buf;
-	fields[3].out_mask = NULL;
-	fields[3].in_value = NULL;
-	fields[3].in_check_value = NULL;
-	fields[3].in_check_mask = NULL;
-	fields[3].in_handler = NULL;
-	fields[3].in_handler_priv = NULL;
-
-	jtag_add_dr_scan(4, fields, -1, NULL);
-
-	arm9tdmi_clock_out(jtag_info, arm_opcode, 0, NULL, 0);
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
-	arm7_9_execute_sys_speed(target);
-	
-	if (jtag_execute_queue() != ERROR_OK)
-	{
-		ERROR("failed executing JTAG queue, exiting");
-		exit(-1);
-	}
-	
-	return ERROR_OK;
-}
-
-int arm920t_read_cp15_interpreted(target_t *target, u32 cp15_opcode, u32 address, u32 *value)
-{
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	u32* regs_p[1];
-	u32 regs[2];
-	u32 cp15c15 = 0x0;
-
-	/* load address into R1 */
-	regs[1] = address;
-	arm9tdmi_write_core_regs(target, 0x2, regs); 
-	
-	/* read-modify-write CP15 test state register 
-	* to enable interpreted access mode */
-	arm920t_read_cp15_physical(target, 0x1e, &cp15c15);	
-	jtag_execute_queue();
-	cp15c15 |= 1;	/* set interpret mode */
-	arm920t_write_cp15_physical(target, 0x1e, cp15c15);
-
-	/* execute CP15 instruction and ARM load (reading from coprocessor) */
-	arm920t_execute_cp15(target, cp15_opcode, ARMV4_5_LDR(0, 1));
-	
-	/* disable interpreted access mode */
-	cp15c15 &= ~1U;	/* clear interpret mode */
-	arm920t_write_cp15_physical(target, 0x1e, cp15c15);
-
-	/* retrieve value from R0 */
-	regs_p[0] = value;
-	arm9tdmi_read_core_regs(target, 0x1, regs_p);
-	jtag_execute_queue();
-	
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_
-	DEBUG("cp15_opcode: %8.8x, address: %8.8x, value: %8.8x", cp15_opcode, address, *value);
-#endif
-
-	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 0).dirty = 1;
-	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 1).dirty = 1;
-
-	return ERROR_OK;
-}
-
-int arm920t_write_cp15_interpreted(target_t *target, u32 cp15_opcode, u32 value, u32 address)
-{
-	u32 cp15c15 = 0x0;
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	u32 regs[2];
-
-	/* load value, address into R0, R1 */
-	regs[0] = value;
-	regs[1] = address;
-	arm9tdmi_write_core_regs(target, 0x3, regs);
-
-	/* read-modify-write CP15 test state register 
-	* to enable interpreted access mode */
-	arm920t_read_cp15_physical(target, 0x1e, &cp15c15);
-	jtag_execute_queue();
-	cp15c15 |= 1;	/* set interpret mode */
-	arm920t_write_cp15_physical(target, 0x1e, cp15c15);
-
-	/* execute CP15 instruction and ARM store (writing to coprocessor) */
-	arm920t_execute_cp15(target, cp15_opcode, ARMV4_5_STR(0, 1));
-
-	/* disable interpreted access mode */
-	cp15c15 &= ~1U;	/* set interpret mode */
-	arm920t_write_cp15_physical(target, 0x1e, cp15c15);
-
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_
-	DEBUG("cp15_opcode: %8.8x, value: %8.8x, address: %8.8x", cp15_opcode, value, address);
-#endif
-
-	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 0).dirty = 1;
-	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 1).dirty = 1;
-	
-	return ERROR_OK;
-}
-
-u32 arm920t_get_ttb(target_t *target)
-{
-	int retval;
-	u32 ttb = 0x0;
-
-	if ((retval = arm920t_read_cp15_interpreted(target, 0xeebf0f51, 0x0, &ttb)) != ERROR_OK)
-		return retval;
-
-	return ttb;
-}
-
-void arm920t_disable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_cache)
-{
-	u32 cp15_control;
-
-	/* read cp15 control register */
-	arm920t_read_cp15_physical(target, 0x2, &cp15_control);
-	jtag_execute_queue();
-		
-	if (mmu)
-		cp15_control &= ~0x1U;
-	
-	if (d_u_cache)
-		cp15_control &= ~0x4U;
-	
-	if (i_cache)
-		cp15_control &= ~0x1000U;
-
-	arm920t_write_cp15_physical(target, 0x2, cp15_control);
-}
-
-void arm920t_enable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_cache)
-{
-	u32 cp15_control;
-
-	/* read cp15 control register */
-	arm920t_read_cp15_physical(target, 0x2, &cp15_control);
-	jtag_execute_queue();
-		
-	if (mmu)
-		cp15_control |= 0x1U;
-	
-	if (d_u_cache)
-		cp15_control |= 0x4U;
-	
-	if (i_cache)
-		cp15_control |= 0x1000U;
-	
-	arm920t_write_cp15_physical(target, 0x2, cp15_control);
-}
-
-void arm920t_post_debug_entry(target_t *target)
-{
-	u32 cp15c15;
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
-	arm920t_common_t *arm920t = arm9tdmi->arch_info;
-	
-	/* examine cp15 control reg */
-	arm920t_read_cp15_physical(target, 0x2, &arm920t->cp15_control_reg);
-	jtag_execute_queue();
-	DEBUG("cp15_control_reg: %8.8x", arm920t->cp15_control_reg);
-
-	if (arm920t->armv4_5_mmu.armv4_5_cache.ctype == -1)
-	{
-		u32 cache_type_reg;
-		/* identify caches */
-		arm920t_read_cp15_physical(target, 0x1, &cache_type_reg);
-		jtag_execute_queue();
-		armv4_5_identify_cache(cache_type_reg, &arm920t->armv4_5_mmu.armv4_5_cache);
-	}
-
-	arm920t->armv4_5_mmu.mmu_enabled = (arm920t->cp15_control_reg & 0x1U) ? 1 : 0;
-	arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = (arm920t->cp15_control_reg & 0x4U) ? 1 : 0;
-	arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = (arm920t->cp15_control_reg & 0x1000U) ? 1 : 0;
-
-	/* save i/d fault status and address register */
-	arm920t_read_cp15_interpreted(target, 0xee150f10, 0x0, &arm920t->d_fsr);
-	arm920t_read_cp15_interpreted(target, 0xee150f30, 0x0, &arm920t->i_fsr);
-	arm920t_read_cp15_interpreted(target, 0xee160f10, 0x0, &arm920t->d_far);
-	arm920t_read_cp15_interpreted(target, 0xee160f30, 0x0, &arm920t->i_far);
-	
-	DEBUG("D FSR: 0x%8.8x, D FAR: 0x%8.8x, I FSR: 0x%8.8x, I FAR: 0x%8.8x",
-		arm920t->d_fsr, arm920t->d_far, arm920t->i_fsr, arm920t->i_far);  
-
-	if (arm920t->preserve_cache)
-	{
-		/* read-modify-write CP15 test state register 
-		 * to disable I/D-cache linefills */
-		arm920t_read_cp15_physical(target, 0x1e, &cp15c15);
-		jtag_execute_queue();
-		cp15c15 |= 0x600;
-		arm920t_write_cp15_physical(target, 0x1e, cp15c15);
-	}
-}
-
-void arm920t_pre_restore_context(target_t *target)
-{
-	u32 cp15c15;
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
-	arm920t_common_t *arm920t = arm9tdmi->arch_info;
-	
-	/* restore i/d fault status and address register */
-	arm920t_write_cp15_interpreted(target, 0xee050f10, arm920t->d_fsr, 0x0);
-	arm920t_write_cp15_interpreted(target, 0xee050f30, arm920t->i_fsr, 0x0);
-	arm920t_write_cp15_interpreted(target, 0xee060f10, arm920t->d_far, 0x0);
-	arm920t_write_cp15_interpreted(target, 0xee060f30, arm920t->i_far, 0x0);
-	
-	/* read-modify-write CP15 test state register 
-	* to reenable I/D-cache linefills */
-	if (arm920t->preserve_cache)
-	{
-		arm920t_read_cp15_physical(target, 0x1e, &cp15c15);
-		jtag_execute_queue();
-		cp15c15 &= ~0x600U;
-		arm920t_write_cp15_physical(target, 0x1e, cp15c15);
-	}
-}
-
-int arm920t_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, arm7_9_common_t **arm7_9_p, arm9tdmi_common_t **arm9tdmi_p, arm920t_common_t **arm920t_p)
-{
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9;
-	arm9tdmi_common_t *arm9tdmi;
-	arm920t_common_t *arm920t;
-	
-	if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
-	{
-		return -1;
-	}
-	
-	arm7_9 = armv4_5->arch_info;
-	if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC)
-	{
-		return -1;
-	}
-	
-	arm9tdmi = arm7_9->arch_info;
-	if (arm9tdmi->common_magic != ARM9TDMI_COMMON_MAGIC)
-	{
-		return -1;
-	}
-	
-	arm920t = arm9tdmi->arch_info;
-	if (arm920t->common_magic != ARM920T_COMMON_MAGIC)
-	{
-		return -1;
-	}
-	
-	*armv4_5_p = armv4_5;
-	*arm7_9_p = arm7_9;
-	*arm9tdmi_p = arm9tdmi;
-	*arm920t_p = arm920t;
-	
-	return ERROR_OK;
-}
-
-int arm920t_arch_state(struct target_s *target)
-{
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
-	arm920t_common_t *arm920t = arm9tdmi->arch_info;
-	
-	char *state[] = 
-	{
-		"disabled", "enabled"
-	};
-	
-	if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
-	{
-		ERROR("BUG: called for a non-ARMv4/5 target");
-		exit(-1);
-	}
-	
-	USER(	"target halted in %s state due to %s, current mode: %s\n"
-			"cpsr: 0x%8.8x pc: 0x%8.8x\n"
-			"MMU: %s, D-Cache: %s, I-Cache: %s",
-			 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[arm920t->armv4_5_mmu.mmu_enabled],
-			 state[arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled], 
-			 state[arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled]);
-	
-	return ERROR_OK;
-}
-
-int arm920t_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
-{
-	int retval;
-	
-	retval = arm7_9_read_memory(target, address, size, count, buffer);
-	
-	return retval;
-}
-
-int arm920t_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
-{
-	int retval;
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
-	arm920t_common_t *arm920t = arm9tdmi->arch_info;
-	
-	if ((retval = arm7_9_write_memory(target, address, size, count, buffer)) != ERROR_OK)
-		return retval;
-
-	if (((size == 4) || (size == 2)) && (count == 1))
-	{
-		if (arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled)
-		{
-			DEBUG("D-Cache enabled, writing through to main memory");
-			u32 pa, cb, ap;
-			int type, domain;
-
-			pa = armv4_5_mmu_translate_va(target, &arm920t->armv4_5_mmu, address, &type, &cb, &domain, &ap);
-			if (type == -1)
-				return ERROR_OK;
-			/* cacheable & bufferable means write-back region */
-			if (cb == 3)
-				armv4_5_mmu_write_physical(target, &arm920t->armv4_5_mmu, pa, size, count, buffer);
-		}
-		
-		if (arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled)
-		{
-			DEBUG("I-Cache enabled, invalidating affected I-Cache line");
-			arm920t_write_cp15_interpreted(target, 0xee070f35, 0x0, address);
-		}
-	}
-
-	return retval;
-}
-
-int arm920t_soft_reset_halt(struct target_s *target)
-{
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
-	arm920t_common_t *arm920t = arm9tdmi->arch_info;
-	reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
-	
-	if (target->state == TARGET_RUNNING)
-	{
-		target->type->halt(target);
-	}
-	
-	while (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0)
-	{
-		embeddedice_read_reg(dbg_stat);
-		jtag_execute_queue();
-	}
-	
-	target->state = TARGET_HALTED;
-	
-	/* SVC, ARM state, IRQ and FIQ disabled */
-	buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8, 0xd3);
-	armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
-	armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
-	
-	/* start fetching from 0x0 */
-	buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, 0x0);
-	armv4_5->core_cache->reg_list[15].dirty = 1;
-	armv4_5->core_cache->reg_list[15].valid = 1;
-	
-	armv4_5->core_mode = ARMV4_5_MODE_SVC;
-	armv4_5->core_state = ARMV4_5_STATE_ARM;
-	
-	arm920t_disable_mmu_caches(target, 1, 1, 1);
-	arm920t->armv4_5_mmu.mmu_enabled = 0;
-	arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0;
-	arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;
-
-	target_call_event_callbacks(target, TARGET_EVENT_HALTED);
-	
-	return ERROR_OK;
-}
-
-int arm920t_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
-{
-	arm9tdmi_init_target(cmd_ctx, target);
-		
-	return ERROR_OK;
-	
-}
-
-int arm920t_quit()
-{
-	
-	return ERROR_OK;
-}
-
-int arm920t_init_arch_info(target_t *target, arm920t_common_t *arm920t, int chain_pos, char *variant)
-{
-	arm9tdmi_common_t *arm9tdmi = &arm920t->arm9tdmi_common;
-	arm7_9_common_t *arm7_9 = &arm9tdmi->arm7_9_common;
-	
-	/* initialize arm9tdmi specific info (including arm7_9 and armv4_5)
-	 */
-	arm9tdmi_init_arch_info(target, arm9tdmi, chain_pos, variant);
-
-	arm9tdmi->arch_info = arm920t;
-	arm920t->common_magic = ARM920T_COMMON_MAGIC;
-	
-	arm7_9->post_debug_entry = arm920t_post_debug_entry;
-	arm7_9->pre_restore_context = arm920t_pre_restore_context;
-	
-	arm920t->armv4_5_mmu.armv4_5_cache.ctype = -1;
-	arm920t->armv4_5_mmu.get_ttb = arm920t_get_ttb;
-	arm920t->armv4_5_mmu.read_memory = arm7_9_read_memory;
-	arm920t->armv4_5_mmu.write_memory = arm7_9_write_memory;
-	arm920t->armv4_5_mmu.disable_mmu_caches = arm920t_disable_mmu_caches;
-	arm920t->armv4_5_mmu.enable_mmu_caches = arm920t_enable_mmu_caches;
-	arm920t->armv4_5_mmu.has_tiny_pages = 1;
-	arm920t->armv4_5_mmu.mmu_enabled = 0;
-	
-	/* disabling linefills leads to lockups, so keep them enabled for now
-	 * this doesn't affect correctness, but might affect timing issues, if
-	 * important data is evicted from the cache during the debug session
-	 * */
-	arm920t->preserve_cache = 0;
-	
-	/* override hw single-step capability from ARM9TDMI */
-	arm7_9->has_single_step = 1;
-	
-	return ERROR_OK;
-}
-
-int arm920t_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)
-{
-	int chain_pos;
-	char *variant = NULL;
-	arm920t_common_t *arm920t = malloc(sizeof(arm920t_common_t));
-	
-	if (argc < 4)
-	{
-		ERROR("'target arm920t' requires at least one additional argument");
-		exit(-1);
-	}
-	
-	chain_pos = strtoul(args[3], NULL, 0);
-	
-	if (argc >= 5)
-		variant = args[4];
-	
-	DEBUG("chain_pos: %i, variant: %s", chain_pos, variant);
-	
-	arm920t_init_arch_info(target, arm920t, chain_pos, variant);
-
-	return ERROR_OK;
-}
-
-int arm920t_register_commands(struct command_context_s *cmd_ctx)
-{
-	int retval;
-	command_t *arm920t_cmd;
-	
-		
-	retval = arm9tdmi_register_commands(cmd_ctx);
-	
-	arm920t_cmd = register_command(cmd_ctx, NULL, "arm920t", NULL, COMMAND_ANY, "arm920t specific commands");
-
-	register_command(cmd_ctx, arm920t_cmd, "cp15", arm920t_handle_cp15_command, COMMAND_EXEC, "display/modify cp15 register <num> [value]");
-	register_command(cmd_ctx, arm920t_cmd, "cp15i", arm920t_handle_cp15i_command, COMMAND_EXEC, "display/modify cp15 (interpreted access) <opcode> [value] [address]");
-	register_command(cmd_ctx, arm920t_cmd, "cache_info", arm920t_handle_cache_info_command, COMMAND_EXEC, "display information about target caches");
-	register_command(cmd_ctx, arm920t_cmd, "virt2phys", arm920t_handle_virt2phys_command, COMMAND_EXEC, "translate va to pa <va>");
-
-	register_command(cmd_ctx, arm920t_cmd, "mdw_phys", arm920t_handle_md_phys_command, COMMAND_EXEC, "display memory words <physical addr> [count]");
-	register_command(cmd_ctx, arm920t_cmd, "mdh_phys", arm920t_handle_md_phys_command, COMMAND_EXEC, "display memory half-words <physical addr> [count]");
-	register_command(cmd_ctx, arm920t_cmd, "mdb_phys", arm920t_handle_md_phys_command, COMMAND_EXEC, "display memory bytes <physical addr> [count]");
-
-	register_command(cmd_ctx, arm920t_cmd, "mww_phys", arm920t_handle_mw_phys_command, COMMAND_EXEC, "write memory word <physical addr> <value>");
-	register_command(cmd_ctx, arm920t_cmd, "mwh_phys", arm920t_handle_mw_phys_command, COMMAND_EXEC, "write memory half-word <physical addr> <value>");
-	register_command(cmd_ctx, arm920t_cmd, "mwb_phys", arm920t_handle_mw_phys_command, COMMAND_EXEC, "write memory byte <physical addr> <value>");
-
-	register_command(cmd_ctx, arm920t_cmd, "read_cache", arm920t_handle_read_cache_command, COMMAND_EXEC, "display I/D cache content");
-	register_command(cmd_ctx, arm920t_cmd, "read_mmu", arm920t_handle_read_mmu_command, COMMAND_EXEC, "display I/D mmu content");
-
-	return ERROR_OK;
-}
-
-int arm920t_handle_read_cache_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;
-	arm7_9_common_t *arm7_9;
-	arm9tdmi_common_t *arm9tdmi;
-	arm920t_common_t *arm920t;
-	arm_jtag_t *jtag_info;
-	u32 cp15c15;
-	u32 cp15_ctrl, cp15_ctrl_saved;
-	u32 regs[16];
-	u32 *regs_p[16];
-	u32 C15_C_D_Ind, C15_C_I_Ind;
-	int i;
-	FILE *output;
-	arm920t_cache_line_t d_cache[8][64], i_cache[8][64];
-	int segment, index;
-	
-	if (argc != 1)
-	{
-		command_print(cmd_ctx, "usage: arm920t read_cache <filename>");
-		return ERROR_OK;
-	}
-	
-	if ((output = fopen(args[0], "w")) == NULL)
-	{
-		DEBUG("error opening cache content file");
-		return ERROR_OK;
-	}
-	
-	for (i = 0; i < 16; i++)
-		regs_p[i] = &regs[i];
-		
-	if (arm920t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm920t) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "current target isn't an ARM920t target");
-		return ERROR_OK;
-	}
-	
-	jtag_info = &arm7_9->jtag_info;
-	
-	/* disable MMU and Caches */
-	arm920t_read_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0x1, 0), &cp15_ctrl);
-	jtag_execute_queue();
-	cp15_ctrl_saved = cp15_ctrl;
-	cp15_ctrl &= ~(ARMV4_5_MMU_ENABLED | ARMV4_5_D_U_CACHE_ENABLED | ARMV4_5_I_CACHE_ENABLED);
-	arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0x1, 0), cp15_ctrl);
-
-	/* read CP15 test state register */ 
-	arm920t_read_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), &cp15c15);
-	jtag_execute_queue();
-	
-	/* read DCache content */
-	fprintf(output, "DCache:\n");
-	
-	/* go through segments 0 to nsets (8 on ARM920T, 4 on ARM922T) */ 
-	for (segment = 0; segment < arm920t->armv4_5_mmu.armv4_5_cache.d_u_size.nsets; segment++)
-	{
-		fprintf(output, "\nsegment: %i\n----------", segment);
-		
-		/* Ra: r0 = SBZ(31:8):segment(7:5):SBZ(4:0) */
-		regs[0] = 0x0 | (segment << 5);
-		arm9tdmi_write_core_regs(target, 0x1, regs);
-		
-		/* set interpret mode */
-		cp15c15 |= 0x1;
-		arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
-		
-		/* D CAM Read, loads current victim into C15.C.D.Ind */
-		arm920t_execute_cp15(target, ARMV4_5_MCR(15,2,0,15,6,2), ARMV4_5_LDR(1, 0));
-	
-		/* read current victim */
-		arm920t_read_cp15_physical(target, 0x3d, &C15_C_D_Ind);
-
-		/* clear interpret mode */
-		cp15c15 &= ~0x1;
-		arm920t_write_cp15_physical(target, 0x1e, cp15c15);
-
-		for (index = 0; index < 64; index++)
-		{
-			/* Ra: r0 = index(31:26):SBZ(25:8):segment(7:5):SBZ(4:0) */
-			regs[0] = 0x0 | (segment << 5) | (index << 26);
-			arm9tdmi_write_core_regs(target, 0x1, regs);
-
-			/* set interpret mode */
-			cp15c15 |= 0x1;
-			arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
-	
-			/* Write DCache victim */
-			arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,9,1,0), ARMV4_5_LDR(1, 0));
-	
-			/* Read D RAM */
-			arm920t_execute_cp15(target, ARMV4_5_MCR(15,2,0,15,10,2), ARMV4_5_LDMIA(0, 0x1fe, 0, 0));
-			
-			/* Read D CAM */
-			arm920t_execute_cp15(target, ARMV4_5_MCR(15,2,0,15,6,2), ARMV4_5_LDR(9, 0));
-			
-			/* clear interpret mode */
-			cp15c15 &= ~0x1;
-			arm920t_write_cp15_physical(target, 0x1e, cp15c15);
-
-			/* read D RAM and CAM content */
-			arm9tdmi_read_core_regs(target, 0x3fe, regs_p);
-			jtag_execute_queue();
-
-			d_cache[segment][index].cam = regs[9];
-			
-			/* mask LFSR[6] */
-			regs[9] &= 0xfffffffe;
-			fprintf(output, "\nsegment: %i, index: %i, CAM: 0x%8.8x, content (%s):\n", segment, index, regs[9], (regs[9] & 0x10) ? "valid" : "invalid");
-			
-			for (i = 1; i < 9; i++)
-			{
-				 d_cache[segment][index].data[i] = regs[i];
-				 fprintf(output, "%i: 0x%8.8x\n", i-1, regs[i]);
-			}
-	
-		}
-		
-		/* Ra: r0 = index(31:26):SBZ(25:8):segment(7:5):SBZ(4:0) */
-		regs[0] = 0x0 | (segment << 5) | (C15_C_D_Ind << 26);
-		arm9tdmi_write_core_regs(target, 0x1, regs);
-
-		/* set interpret mode */
-		cp15c15 |= 0x1;
-		arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
-	
-		/* Write DCache victim */
-		arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,9,1,0), ARMV4_5_LDR(1, 0));
-	
-		/* clear interpret mode */
-		cp15c15 &= ~0x1;
-		arm920t_write_cp15_physical(target, 0x1e, cp15c15);
-	}
-
-	/* read ICache content */
-	fprintf(output, "ICache:\n");
-	
-	/* go through segments 0 to nsets (8 on ARM920T, 4 on ARM922T) */ 
-	for (segment = 0; segment < arm920t->armv4_5_mmu.armv4_5_cache.d_u_size.nsets; segment++)
-	{
-		fprintf(output, "segment: %i\n----------", segment);
-		
-		/* Ra: r0 = SBZ(31:8):segment(7:5):SBZ(4:0) */
-		regs[0] = 0x0 | (segment << 5);
-		arm9tdmi_write_core_regs(target, 0x1, regs);
-		
-		/* set interpret mode */
-		cp15c15 |= 0x1;
-		arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
-		
-		/* I CAM Read, loads current victim into C15.C.I.Ind */
-		arm920t_execute_cp15(target, ARMV4_5_MCR(15,2,0,15,5,2), ARMV4_5_LDR(1, 0));
-	
-		/* read current victim */
-		arm920t_read_cp15_physical(target, 0x3b, &C15_C_I_Ind);
-
-		/* clear interpret mode */
-		cp15c15 &= ~0x1;
-		arm920t_write_cp15_physical(target, 0x1e, cp15c15);
-
-		for (index = 0; index < 64; index++)
-		{
-			/* Ra: r0 = index(31:26):SBZ(25:8):segment(7:5):SBZ(4:0) */
-			regs[0] = 0x0 | (segment << 5) | (index << 26);
-			arm9tdmi_write_core_regs(target, 0x1, regs);
-
-			/* set interpret mode */
-			cp15c15 |= 0x1;
-			arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
-	
-			/* Write ICache victim */
-			arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,9,1,1), ARMV4_5_LDR(1, 0));
-	
-			/* Read I RAM */
-			arm920t_execute_cp15(target, ARMV4_5_MCR(15,2,0,15,9,2), ARMV4_5_LDMIA(0, 0x1fe, 0, 0));
-			
-			/* Read I CAM */
-			arm920t_execute_cp15(target, ARMV4_5_MCR(15,2,0,15,5,2), ARMV4_5_LDR(9, 0));
-			
-			/* clear interpret mode */
-			cp15c15 &= ~0x1;
-			arm920t_write_cp15_physical(target, 0x1e, cp15c15);
-
-			/* read I RAM and CAM content */
-			arm9tdmi_read_core_regs(target, 0x3fe, regs_p);
-			jtag_execute_queue();
-
-			i_cache[segment][index].cam = regs[9];
-			
-			/* mask LFSR[6] */
-			regs[9] &= 0xfffffffe;
-			fprintf(output, "\nsegment: %i, index: %i, CAM: 0x%8.8x, content (%s):\n", segment, index, regs[9], (regs[9] & 0x10) ? "valid" : "invalid");
-			
-			for (i = 1; i < 9; i++)
-			{
-				 i_cache[segment][index].data[i] = regs[i];
-				 fprintf(output, "%i: 0x%8.8x\n", i-1, regs[i]);
-			}
-	
-		}
-		
-	
-		/* Ra: r0 = index(31:26):SBZ(25:8):segment(7:5):SBZ(4:0) */
-		regs[0] = 0x0 | (segment << 5) | (C15_C_D_Ind << 26);
-		arm9tdmi_write_core_regs(target, 0x1, regs);
-
-		/* set interpret mode */
-		cp15c15 |= 0x1;
-		arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
-	
-		/* Write ICache victim */
-		arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,9,1,1), ARMV4_5_LDR(1, 0));
-	
-		/* clear interpret mode */
-		cp15c15 &= ~0x1;
-		arm920t_write_cp15_physical(target, 0x1e, cp15c15);
-	}
-	
-	/* restore CP15 MMU and Cache settings */
-	arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0x1, 0), cp15_ctrl_saved);
-	
-	command_print(cmd_ctx, "cache content successfully output to %s", args[0]);
-	
-	fclose(output);
-	
-	/* mark registers dirty. */
-	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 0).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 0).valid;
-	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 1).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 1).valid;
-	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 2).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 2).valid;
-	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 3).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 3).valid;
-	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 4).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 4).valid;
-	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 5).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 5).valid;
-	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 6).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 6).valid;
-	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 7).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 7).valid;
-	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 8).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 8).valid;
-	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 9).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 9).valid;
-	
-	return ERROR_OK;
-}
-
-int arm920t_handle_read_mmu_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;
-	arm7_9_common_t *arm7_9;
-	arm9tdmi_common_t *arm9tdmi;
-	arm920t_common_t *arm920t;
-	arm_jtag_t *jtag_info;
-	u32 cp15c15;
-	u32 cp15_ctrl, cp15_ctrl_saved;
-	u32 regs[16];
-	u32 *regs_p[16];
-	int i;
-	FILE *output;
-	u32 Dlockdown, Ilockdown;
-	arm920t_tlb_entry_t d_tlb[64], i_tlb[64];
-	int victim;
-	
-	if (argc != 1)
-	{
-		command_print(cmd_ctx, "usage: arm920t read_mmu <filename>");
-		return ERROR_OK;
-	}
-	
-	if ((output = fopen(args[0], "w")) == NULL)
-	{
-		DEBUG("error opening mmu content file");
-		return ERROR_OK;
-	}
-	
-	for (i = 0; i < 16; i++)
-		regs_p[i] = &regs[i];
-		
-	if (arm920t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm920t) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "current target isn't an ARM920t target");
-		return ERROR_OK;
-	}
-	
-	jtag_info = &arm7_9->jtag_info;
-	
-	/* disable MMU and Caches */
-	arm920t_read_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0x1, 0), &cp15_ctrl);
-	jtag_execute_queue();
-	cp15_ctrl_saved = cp15_ctrl;
-	cp15_ctrl &= ~(ARMV4_5_MMU_ENABLED | ARMV4_5_D_U_CACHE_ENABLED | ARMV4_5_I_CACHE_ENABLED);
-	arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0x1, 0), cp15_ctrl);
-
-	/* read CP15 test state register */ 
-	arm920t_read_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), &cp15c15);
-	jtag_execute_queue();
-
-	/* prepare reading D TLB content 
-	 * */
-	
-	/* set interpret mode */
-	cp15c15 |= 0x1;
-	arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
-	
-	/* Read D TLB lockdown */
-	arm920t_execute_cp15(target, ARMV4_5_MRC(15,0,0,10,0,0), ARMV4_5_LDR(1, 0));
-	
-	/* clear interpret mode */
-	cp15c15 &= ~0x1;
-	arm920t_write_cp15_physical(target, 0x1e, cp15c15);
-	
-	/* read D TLB lockdown stored to r1 */
-	arm9tdmi_read_core_regs(target, 0x2, regs_p);
-	jtag_execute_queue();
-	Dlockdown = regs[1];
-	
-	for (victim = 0; victim < 64; victim += 8)
-	{
-		/* new lockdown value: base[31:26]:victim[25:20]:SBZ[19:1]:p[0] 
-		 * base remains unchanged, victim goes through entries 0 to 63 */
-		regs[1] = (Dlockdown & 0xfc000000) | (victim << 20);
-		arm9tdmi_write_core_regs(target, 0x2, regs);
-		
-		/* set interpret mode */
-		cp15c15 |= 0x1;
-		arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
-		
-		/* Write D TLB lockdown */
-		arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,10,0,0), ARMV4_5_STR(1, 0));
-	
-		/* Read D TLB CAM */
-		arm920t_execute_cp15(target, ARMV4_5_MCR(15,4,0,15,6,4), ARMV4_5_LDMIA(0, 0x3fc, 0, 0));
-		
-		/* clear interpret mode */
-		cp15c15 &= ~0x1;
-		arm920t_write_cp15_physical(target, 0x1e, cp15c15);
-		
-		/* read D TLB CAM content stored to r2-r9 */
-		arm9tdmi_read_core_regs(target, 0x3fc, regs_p);
-		jtag_execute_queue();
-		
-		for (i = 0; i < 8; i++)
-			d_tlb[victim + i].cam = regs[i + 2]; 
-	}
-
-	for (victim = 0; victim < 64; victim++)
-	{
-		/* new lockdown value: base[31:26]:victim[25:20]:SBZ[19:1]:p[0] 
-		 * base remains unchanged, victim goes through entries 0 to 63 */
-		regs[1] = (Dlockdown & 0xfc000000) | (victim << 20);
-		arm9tdmi_write_core_regs(target, 0x2, regs);
-		
-		/* set interpret mode */
-		cp15c15 |= 0x1;
-		arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
-		
-		/* Write D TLB lockdown */
-		arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,10,0,0), ARMV4_5_STR(1, 0));
-	
-		/* Read D TLB RAM1 */
-		arm920t_execute_cp15(target, ARMV4_5_MCR(15,4,0,15,10,4), ARMV4_5_LDR(2,0));
-
-		/* Read D TLB RAM2 */
-		arm920t_execute_cp15(target, ARMV4_5_MCR(15,4,0,15,2,5), ARMV4_5_LDR(3,0));
-		
-		/* clear interpret mode */
-		cp15c15 &= ~0x1;
-		arm920t_write_cp15_physical(target, 0x1e, cp15c15);
-		
-		/* read D TLB RAM content stored to r2 and r3 */
-		arm9tdmi_read_core_regs(target, 0xc, regs_p);
-		jtag_execute_queue();
-
-		d_tlb[victim].ram1 = regs[2]; 
-		d_tlb[victim].ram2 = regs[3]; 
-	}
-		
-	/* restore D TLB lockdown */
-	regs[1] = Dlockdown;
-	arm9tdmi_write_core_regs(target, 0x2, regs);
-	
-	/* Write D TLB lockdown */
-	arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,10,0,0), ARMV4_5_STR(1, 0));
-
-	/* prepare reading I TLB content 
-	 * */
-	
-	/* set interpret mode */
-	cp15c15 |= 0x1;
-	arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
-	
-	/* Read I TLB lockdown */
-	arm920t_execute_cp15(target, ARMV4_5_MRC(15,0,0,10,0,1), ARMV4_5_LDR(1, 0));
-	
-	/* clear interpret mode */
-	cp15c15 &= ~0x1;
-	arm920t_write_cp15_physical(target, 0x1e, cp15c15);
-	
-	/* read I TLB lockdown stored to r1 */
-	arm9tdmi_read_core_regs(target, 0x2, regs_p);
-	jtag_execute_queue();
-	Ilockdown = regs[1];
-	
-	for (victim = 0; victim < 64; victim += 8)
-	{
-		/* new lockdown value: base[31:26]:victim[25:20]:SBZ[19:1]:p[0] 
-		 * base remains unchanged, victim goes through entries 0 to 63 */
-		regs[1] = (Ilockdown & 0xfc000000) | (victim << 20);
-		arm9tdmi_write_core_regs(target, 0x2, regs);
-		
-		/* set interpret mode */
-		cp15c15 |= 0x1;
-		arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
-		
-		/* Write I TLB lockdown */
-		arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,10,0,1), ARMV4_5_STR(1, 0));
-	
-		/* Read I TLB CAM */
-		arm920t_execute_cp15(target, ARMV4_5_MCR(15,4,0,15,5,4), ARMV4_5_LDMIA(0, 0x3fc, 0, 0));
-		
-		/* clear interpret mode */
-		cp15c15 &= ~0x1;
-		arm920t_write_cp15_physical(target, 0x1e, cp15c15);
-		
-		/* read I TLB CAM content stored to r2-r9 */
-		arm9tdmi_read_core_regs(target, 0x3fc, regs_p);
-		jtag_execute_queue();
-		
-		for (i = 0; i < 8; i++)
-			i_tlb[i + victim].cam = regs[i + 2]; 
-	}
-
-	for (victim = 0; victim < 64; victim++)
-	{
-		/* new lockdown value: base[31:26]:victim[25:20]:SBZ[19:1]:p[0] 
-		 * base remains unchanged, victim goes through entries 0 to 63 */
-		regs[1] = (Dlockdown & 0xfc000000) | (victim << 20);
-		arm9tdmi_write_core_regs(target, 0x2, regs);
-		
-		/* set interpret mode */
-		cp15c15 |= 0x1;
-		arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
-		
-		/* Write I TLB lockdown */
-		arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,10,0,1), ARMV4_5_STR(1, 0));
-	
-		/* Read I TLB RAM1 */
-		arm920t_execute_cp15(target, ARMV4_5_MCR(15,4,0,15,9,4), ARMV4_5_LDR(2,0));
-
-		/* Read I TLB RAM2 */
-		arm920t_execute_cp15(target, ARMV4_5_MCR(15,4,0,15,1,5), ARMV4_5_LDR(3,0));
-		
-		/* clear interpret mode */
-		cp15c15 &= ~0x1;
-		arm920t_write_cp15_physical(target, 0x1e, cp15c15);
-		
-		/* read I TLB RAM content stored to r2 and r3 */
-		arm9tdmi_read_core_regs(target, 0xc, regs_p);
-		jtag_execute_queue();
-
-		i_tlb[victim].ram1 = regs[2]; 
-		i_tlb[victim].ram2 = regs[3]; 
-	}
-		
-	/* restore I TLB lockdown */
-	regs[1] = Ilockdown;
-	arm9tdmi_write_core_regs(target, 0x2, regs);
-	
-	/* Write I TLB lockdown */
-	arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,10,0,1), ARMV4_5_STR(1, 0));
-	
-	/* restore CP15 MMU and Cache settings */
-	arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0x1, 0), cp15_ctrl_saved);
-
-	/* output data to file */	
-	fprintf(output, "D TLB content:\n");
-	for (i = 0; i < 64; i++)
-	{
-		fprintf(output, "%i: 0x%8.8x 0x%8.8x 0x%8.8x %s\n", i, d_tlb[i].cam, d_tlb[i].ram1, d_tlb[i].ram2, (d_tlb[i].cam & 0x20) ? "(valid)" : "(invalid)");
-	}
-
-	fprintf(output, "\n\nI TLB content:\n");
-	for (i = 0; i < 64; i++)
-	{
-		fprintf(output, "%i: 0x%8.8x 0x%8.8x 0x%8.8x %s\n", i, i_tlb[i].cam, i_tlb[i].ram1, i_tlb[i].ram2, (i_tlb[i].cam & 0x20) ? "(valid)" : "(invalid)");
-	}
-	
-	command_print(cmd_ctx, "mmu content successfully output to %s", args[0]);
-	
-	fclose(output);
-	
-	/* mark registers dirty */
-	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 0).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 0).valid;
-	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 1).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 1).valid;
-	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 2).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 2).valid;
-	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 3).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 3).valid;
-	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 4).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 4).valid;
-	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 5).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 5).valid;
-	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 6).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 6).valid;
-	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 7).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 7).valid;
-	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 8).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 8).valid;
-	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 9).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 9).valid;
-	
-	return ERROR_OK;
-}
-int arm920t_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	int retval;
-	target_t *target = get_current_target(cmd_ctx);
-	armv4_5_common_t *armv4_5;
-	arm7_9_common_t *arm7_9;
-	arm9tdmi_common_t *arm9tdmi;
-	arm920t_common_t *arm920t;
-	arm_jtag_t *jtag_info;
-
-	if (arm920t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm920t) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "current target isn't an ARM920t target");
-		return ERROR_OK;
-	}
-	
-	jtag_info = &arm7_9->jtag_info;
-	
-	if (target->state != TARGET_HALTED)
-	{
-		command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
-		return ERROR_OK;
-	}
-
-	/* one or more argument, access a single register (write if second argument is given */
-	if (argc >= 1)
-	{
-		int address = strtoul(args[0], NULL, 0);
-
-		if (argc == 1)
-		{
-			u32 value;
-			if ((retval = arm920t_read_cp15_physical(target, address, &value)) != ERROR_OK)
-			{
-				command_print(cmd_ctx, "couldn't access reg %i", address);
-				return ERROR_OK;
-			}
-			jtag_execute_queue();
-			
-			command_print(cmd_ctx, "%i: %8.8x", address, value);
-		}
-		else if (argc == 2)
-		{
-			u32 value = strtoul(args[1], NULL, 0);
-			if ((retval = arm920t_write_cp15_physical(target, address, value)) != ERROR_OK)
-			{
-				command_print(cmd_ctx, "couldn't access reg %i", address);
-				return ERROR_OK;
-			}
-			command_print(cmd_ctx, "%i: %8.8x", address, value);
-		}
-	}
-
-	return ERROR_OK;
-}
-
-int arm920t_handle_cp15i_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	int retval;
-	target_t *target = get_current_target(cmd_ctx);
-	armv4_5_common_t *armv4_5;
-	arm7_9_common_t *arm7_9;
-	arm9tdmi_common_t *arm9tdmi;
-	arm920t_common_t *arm920t;
-	arm_jtag_t *jtag_info;
-
-	if (arm920t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm920t) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "current target isn't an ARM920t target");
-		return ERROR_OK;
-	}
-	
-	jtag_info = &arm7_9->jtag_info;
-	
-	if (target->state != TARGET_HALTED)
-	{
-		command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
-		return ERROR_OK;
-	}
-
-	/* one or more argument, access a single register (write if second argument is given */
-	if (argc >= 1)
-	{
-		u32 opcode = strtoul(args[0], NULL, 0);
-
-		if (argc == 1)
-		{
-			u32 value;
-			if ((retval = arm920t_read_cp15_interpreted(target, opcode, 0x0, &value)) != ERROR_OK)
-			{
-				command_print(cmd_ctx, "couldn't execute %8.8x", opcode);
-				return ERROR_OK;
-			}
-			
-			command_print(cmd_ctx, "%8.8x: %8.8x", opcode, value);
-		}
-		else if (argc == 2)
-		{
-			u32 value = strtoul(args[1], NULL, 0);
-			if ((retval = arm920t_write_cp15_interpreted(target, opcode, value, 0)) != ERROR_OK)
-			{
-				command_print(cmd_ctx, "couldn't execute %8.8x", opcode);
-				return ERROR_OK;
-			}
-			command_print(cmd_ctx, "%8.8x: %8.8x", opcode, value);
-		}
-		else if (argc == 3)
-		{
-			u32 value = strtoul(args[1], NULL, 0);
-			u32 address = strtoul(args[2], NULL, 0);
-			if ((retval = arm920t_write_cp15_interpreted(target, opcode, value, address)) != ERROR_OK)
-			{
-				command_print(cmd_ctx, "couldn't execute %8.8x", opcode);
-				return ERROR_OK;
-			}
-			command_print(cmd_ctx, "%8.8x: %8.8x %8.8x", opcode, value, address);
-		}
-	}
-	else
-	{
-		command_print(cmd_ctx, "usage: arm920t cp15i <opcode> [value] [address]");
-	}
-
-	return ERROR_OK;
-}
-
-int arm920t_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;
-	arm7_9_common_t *arm7_9;
-	arm9tdmi_common_t *arm9tdmi;
-	arm920t_common_t *arm920t;
-	
-	if (arm920t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm920t) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "current target isn't an ARM920t target");
-		return ERROR_OK;
-	}
-	
-	return armv4_5_handle_cache_info_command(cmd_ctx, &arm920t->armv4_5_mmu.armv4_5_cache);
-}
-
-int arm920t_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;
-	arm7_9_common_t *arm7_9;
-	arm9tdmi_common_t *arm9tdmi;
-	arm920t_common_t *arm920t;
-	arm_jtag_t *jtag_info;
-
-	if (arm920t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm920t) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "current target isn't an ARM920t target");
-		return ERROR_OK;
-	}
-	
-	jtag_info = &arm7_9->jtag_info;
-	
-	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, &arm920t->armv4_5_mmu);
-}
-
-int arm920t_handle_md_phys_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;
-	arm7_9_common_t *arm7_9;
-	arm9tdmi_common_t *arm9tdmi;
-	arm920t_common_t *arm920t;
-	arm_jtag_t *jtag_info;
-
-	if (arm920t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm920t) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "current target isn't an ARM920t target");
-		return ERROR_OK;
-	}
-	
-	jtag_info = &arm7_9->jtag_info;
-	
-	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_md_phys_command(cmd_ctx, cmd, args, argc, target, &arm920t->armv4_5_mmu);
-}
-
-int arm920t_handle_mw_phys_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;
-	arm7_9_common_t *arm7_9;
-	arm9tdmi_common_t *arm9tdmi;
-	arm920t_common_t *arm920t;
-	arm_jtag_t *jtag_info;
-
-	if (arm920t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm920t) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "current target isn't an ARM920t target");
-		return ERROR_OK;
-	}
-	
-	jtag_info = &arm7_9->jtag_info;
-	
-	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_mw_phys_command(cmd_ctx, cmd, args, argc, target, &arm920t->armv4_5_mmu);
-}
+/***************************************************************************
+ *   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.             *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "arm920t.h"
+#include "jtag.h"
+#include "log.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#if 0
+#define _DEBUG_INSTRUCTION_EXECUTION_
+#endif
+
+/* cli handling */
+int arm920t_register_commands(struct command_context_s *cmd_ctx);
+
+int arm920t_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int arm920t_handle_cp15i_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int arm920t_handle_virt2phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int arm920t_handle_cache_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int arm920t_handle_md_phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int arm920t_handle_mw_phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+int arm920t_handle_read_cache_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int arm920t_handle_read_mmu_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+/* forward declarations */
+int arm920t_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
+int arm920t_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
+int arm920t_quit();
+int arm920t_arch_state(struct target_s *target);
+int arm920t_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
+int arm920t_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
+int arm920t_soft_reset_halt(struct target_s *target);
+
+#define ARM920T_CP15_PHYS_ADDR(x, y, z) ((x << 5) | (y << 1) << (z))
+
+target_type_t arm920t_target =
+{
+	.name = "arm920t",
+
+	.poll = arm7_9_poll,
+	.arch_state = arm920t_arch_state,
+
+	.target_request_data = arm7_9_target_request_data,
+
+	.halt = arm7_9_halt,
+	.resume = arm7_9_resume,
+	.step = arm7_9_step,
+
+	.assert_reset = arm7_9_assert_reset,
+	.deassert_reset = arm7_9_deassert_reset,
+	.soft_reset_halt = arm920t_soft_reset_halt,
+	.prepare_reset_halt = arm7_9_prepare_reset_halt,
+	
+	.get_gdb_reg_list = armv4_5_get_gdb_reg_list,
+
+	.read_memory = arm920t_read_memory,
+	.write_memory = arm920t_write_memory,
+	.bulk_write_memory = arm7_9_bulk_write_memory,
+	.checksum_memory = arm7_9_checksum_memory,
+	
+	.run_algorithm = armv4_5_run_algorithm,
+
+	.add_breakpoint = arm7_9_add_breakpoint,
+	.remove_breakpoint = arm7_9_remove_breakpoint,
+	.add_watchpoint = arm7_9_add_watchpoint,
+	.remove_watchpoint = arm7_9_remove_watchpoint,
+
+	.register_commands = arm920t_register_commands,
+	.target_command = arm920t_target_command,
+	.init_target = arm920t_init_target,
+	.quit = arm920t_quit
+};
+
+int arm920t_read_cp15_physical(target_t *target, int reg_addr, u32 *value)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+	scan_field_t fields[4];
+	u8 access_type_buf = 1;
+	u8 reg_addr_buf = reg_addr & 0x3f;
+	u8 nr_w_buf = 0;
+	
+	jtag_add_end_state(TAP_RTI);
+	arm_jtag_scann(jtag_info, 0xf);
+	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+
+	fields[0].device = jtag_info->chain_pos;
+	fields[0].num_bits = 1;
+	fields[0].out_value = &access_type_buf;
+	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 = 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_check_value = NULL;
+	fields[1].in_check_mask = NULL;
+	fields[1].in_handler = NULL;
+	fields[1].in_handler_priv = NULL;
+
+	fields[2].device = jtag_info->chain_pos;
+	fields[2].num_bits = 6;
+	fields[2].out_value = &reg_addr_buf;
+	fields[2].out_mask = NULL;
+	fields[2].in_value = NULL;
+	fields[2].in_check_value = NULL;
+	fields[2].in_check_mask = NULL;
+	fields[2].in_handler = NULL;
+	fields[2].in_handler_priv = NULL;
+
+	fields[3].device = jtag_info->chain_pos;
+	fields[3].num_bits = 1;
+	fields[3].out_value = &nr_w_buf;
+	fields[3].out_mask = NULL;
+	fields[3].in_value = NULL;
+	fields[3].in_check_value = NULL;
+	fields[3].in_check_mask = NULL;
+	fields[3].in_handler = NULL;
+	fields[3].in_handler_priv = NULL;
+	
+	jtag_add_dr_scan(4, fields, -1);
+
+	fields[1].in_handler_priv = value;
+	fields[1].in_handler = arm_jtag_buf_to_u32;
+
+	jtag_add_dr_scan(4, fields, -1);
+
+#ifdef _DEBUG_INSTRUCTION_EXECUTION_
+	jtag_execute_queue();
+	DEBUG("addr: 0x%x value: %8.8x", reg_addr, *value);
+#endif
+
+	return ERROR_OK;
+}
+
+int arm920t_write_cp15_physical(target_t *target, int reg_addr, u32 value)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+	scan_field_t fields[4];
+	u8 access_type_buf = 1;
+	u8 reg_addr_buf = reg_addr & 0x3f;
+	u8 nr_w_buf = 1;
+	u8 value_buf[4];
+	
+	buf_set_u32(value_buf, 0, 32, value);
+	
+	jtag_add_end_state(TAP_RTI);
+	arm_jtag_scann(jtag_info, 0xf);
+	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+
+	fields[0].device = jtag_info->chain_pos;
+	fields[0].num_bits = 1;
+	fields[0].out_value = &access_type_buf;
+	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 = jtag_info->chain_pos;
+	fields[1].num_bits = 32;
+	fields[1].out_value = value_buf;
+	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;
+
+	fields[2].device = jtag_info->chain_pos;
+	fields[2].num_bits = 6;
+	fields[2].out_value = &reg_addr_buf;
+	fields[2].out_mask = NULL;
+	fields[2].in_value = NULL;
+	fields[2].in_check_value = NULL;
+	fields[2].in_check_mask = NULL;
+	fields[2].in_handler = NULL;
+	fields[2].in_handler_priv = NULL;
+
+	fields[3].device = jtag_info->chain_pos;
+	fields[3].num_bits = 1;
+	fields[3].out_value = &nr_w_buf;
+	fields[3].out_mask = NULL;
+	fields[3].in_value = NULL;
+	fields[3].in_check_value = NULL;
+	fields[3].in_check_mask = NULL;
+	fields[3].in_handler = NULL;
+	fields[3].in_handler_priv = NULL;
+	
+	jtag_add_dr_scan(4, fields, -1);
+
+#ifdef _DEBUG_INSTRUCTION_EXECUTION_
+	DEBUG("addr: 0x%x value: %8.8x", reg_addr, value);
+#endif
+
+	return ERROR_OK;
+}
+
+int arm920t_execute_cp15(target_t *target, u32 cp15_opcode, u32 arm_opcode)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+	scan_field_t fields[4];
+	u8 access_type_buf = 0;		/* interpreted access */
+	u8 reg_addr_buf = 0x0;
+	u8 nr_w_buf = 0;
+	u8 cp15_opcode_buf[4];
+	
+	jtag_add_end_state(TAP_RTI);
+	arm_jtag_scann(jtag_info, 0xf);
+	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+	
+	buf_set_u32(cp15_opcode_buf, 0, 32, cp15_opcode);
+
+	fields[0].device = jtag_info->chain_pos;
+	fields[0].num_bits = 1;
+	fields[0].out_value = &access_type_buf;
+	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 = jtag_info->chain_pos;
+	fields[1].num_bits = 32;
+	fields[1].out_value = cp15_opcode_buf;
+	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;
+
+	fields[2].device = jtag_info->chain_pos;
+	fields[2].num_bits = 6;
+	fields[2].out_value = &reg_addr_buf;
+	fields[2].out_mask = NULL;
+	fields[2].in_value = NULL;
+	fields[2].in_check_value = NULL;
+	fields[2].in_check_mask = NULL;
+	fields[2].in_handler = NULL;
+	fields[2].in_handler_priv = NULL;
+
+	fields[3].device = jtag_info->chain_pos;
+	fields[3].num_bits = 1;
+	fields[3].out_value = &nr_w_buf;
+	fields[3].out_mask = NULL;
+	fields[3].in_value = NULL;
+	fields[3].in_check_value = NULL;
+	fields[3].in_check_mask = NULL;
+	fields[3].in_handler = NULL;
+	fields[3].in_handler_priv = NULL;
+
+	jtag_add_dr_scan(4, fields, -1);
+
+	arm9tdmi_clock_out(jtag_info, arm_opcode, 0, NULL, 0);
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
+	arm7_9_execute_sys_speed(target);
+	
+	if (jtag_execute_queue() != ERROR_OK)
+	{
+		ERROR("failed executing JTAG queue, exiting");
+		exit(-1);
+	}
+	
+	return ERROR_OK;
+}
+
+int arm920t_read_cp15_interpreted(target_t *target, u32 cp15_opcode, u32 address, u32 *value)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	u32* regs_p[1];
+	u32 regs[2];
+	u32 cp15c15 = 0x0;
+
+	/* load address into R1 */
+	regs[1] = address;
+	arm9tdmi_write_core_regs(target, 0x2, regs); 
+	
+	/* read-modify-write CP15 test state register 
+	* to enable interpreted access mode */
+	arm920t_read_cp15_physical(target, 0x1e, &cp15c15);	
+	jtag_execute_queue();
+	cp15c15 |= 1;	/* set interpret mode */
+	arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+
+	/* execute CP15 instruction and ARM load (reading from coprocessor) */
+	arm920t_execute_cp15(target, cp15_opcode, ARMV4_5_LDR(0, 1));
+	
+	/* disable interpreted access mode */
+	cp15c15 &= ~1U;	/* clear interpret mode */
+	arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+
+	/* retrieve value from R0 */
+	regs_p[0] = value;
+	arm9tdmi_read_core_regs(target, 0x1, regs_p);
+	jtag_execute_queue();
+	
+#ifdef _DEBUG_INSTRUCTION_EXECUTION_
+	DEBUG("cp15_opcode: %8.8x, address: %8.8x, value: %8.8x", cp15_opcode, address, *value);
+#endif
+
+	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 0).dirty = 1;
+	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 1).dirty = 1;
+
+	return ERROR_OK;
+}
+
+int arm920t_write_cp15_interpreted(target_t *target, u32 cp15_opcode, u32 value, u32 address)
+{
+	u32 cp15c15 = 0x0;
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	u32 regs[2];
+
+	/* load value, address into R0, R1 */
+	regs[0] = value;
+	regs[1] = address;
+	arm9tdmi_write_core_regs(target, 0x3, regs);
+
+	/* read-modify-write CP15 test state register 
+	* to enable interpreted access mode */
+	arm920t_read_cp15_physical(target, 0x1e, &cp15c15);
+	jtag_execute_queue();
+	cp15c15 |= 1;	/* set interpret mode */
+	arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+
+	/* execute CP15 instruction and ARM store (writing to coprocessor) */
+	arm920t_execute_cp15(target, cp15_opcode, ARMV4_5_STR(0, 1));
+
+	/* disable interpreted access mode */
+	cp15c15 &= ~1U;	/* set interpret mode */
+	arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+
+#ifdef _DEBUG_INSTRUCTION_EXECUTION_
+	DEBUG("cp15_opcode: %8.8x, value: %8.8x, address: %8.8x", cp15_opcode, value, address);
+#endif
+
+	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 0).dirty = 1;
+	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 1).dirty = 1;
+	
+	return ERROR_OK;
+}
+
+u32 arm920t_get_ttb(target_t *target)
+{
+	int retval;
+	u32 ttb = 0x0;
+
+	if ((retval = arm920t_read_cp15_interpreted(target, 0xeebf0f51, 0x0, &ttb)) != ERROR_OK)
+		return retval;
+
+	return ttb;
+}
+
+void arm920t_disable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_cache)
+{
+	u32 cp15_control;
+
+	/* read cp15 control register */
+	arm920t_read_cp15_physical(target, 0x2, &cp15_control);
+	jtag_execute_queue();
+		
+	if (mmu)
+		cp15_control &= ~0x1U;
+	
+	if (d_u_cache)
+		cp15_control &= ~0x4U;
+	
+	if (i_cache)
+		cp15_control &= ~0x1000U;
+
+	arm920t_write_cp15_physical(target, 0x2, cp15_control);
+}
+
+void arm920t_enable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_cache)
+{
+	u32 cp15_control;
+
+	/* read cp15 control register */
+	arm920t_read_cp15_physical(target, 0x2, &cp15_control);
+	jtag_execute_queue();
+		
+	if (mmu)
+		cp15_control |= 0x1U;
+	
+	if (d_u_cache)
+		cp15_control |= 0x4U;
+	
+	if (i_cache)
+		cp15_control |= 0x1000U;
+	
+	arm920t_write_cp15_physical(target, 0x2, cp15_control);
+}
+
+void arm920t_post_debug_entry(target_t *target)
+{
+	u32 cp15c15;
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
+	arm920t_common_t *arm920t = arm9tdmi->arch_info;
+	
+	/* examine cp15 control reg */
+	arm920t_read_cp15_physical(target, 0x2, &arm920t->cp15_control_reg);
+	jtag_execute_queue();
+	DEBUG("cp15_control_reg: %8.8x", arm920t->cp15_control_reg);
+
+	if (arm920t->armv4_5_mmu.armv4_5_cache.ctype == -1)
+	{
+		u32 cache_type_reg;
+		/* identify caches */
+		arm920t_read_cp15_physical(target, 0x1, &cache_type_reg);
+		jtag_execute_queue();
+		armv4_5_identify_cache(cache_type_reg, &arm920t->armv4_5_mmu.armv4_5_cache);
+	}
+
+	arm920t->armv4_5_mmu.mmu_enabled = (arm920t->cp15_control_reg & 0x1U) ? 1 : 0;
+	arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = (arm920t->cp15_control_reg & 0x4U) ? 1 : 0;
+	arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = (arm920t->cp15_control_reg & 0x1000U) ? 1 : 0;
+
+	/* save i/d fault status and address register */
+	arm920t_read_cp15_interpreted(target, 0xee150f10, 0x0, &arm920t->d_fsr);
+	arm920t_read_cp15_interpreted(target, 0xee150f30, 0x0, &arm920t->i_fsr);
+	arm920t_read_cp15_interpreted(target, 0xee160f10, 0x0, &arm920t->d_far);
+	arm920t_read_cp15_interpreted(target, 0xee160f30, 0x0, &arm920t->i_far);
+	
+	DEBUG("D FSR: 0x%8.8x, D FAR: 0x%8.8x, I FSR: 0x%8.8x, I FAR: 0x%8.8x",
+		arm920t->d_fsr, arm920t->d_far, arm920t->i_fsr, arm920t->i_far);  
+
+	if (arm920t->preserve_cache)
+	{
+		/* read-modify-write CP15 test state register 
+		 * to disable I/D-cache linefills */
+		arm920t_read_cp15_physical(target, 0x1e, &cp15c15);
+		jtag_execute_queue();
+		cp15c15 |= 0x600;
+		arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+	}
+}
+
+void arm920t_pre_restore_context(target_t *target)
+{
+	u32 cp15c15;
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
+	arm920t_common_t *arm920t = arm9tdmi->arch_info;
+	
+	/* restore i/d fault status and address register */
+	arm920t_write_cp15_interpreted(target, 0xee050f10, arm920t->d_fsr, 0x0);
+	arm920t_write_cp15_interpreted(target, 0xee050f30, arm920t->i_fsr, 0x0);
+	arm920t_write_cp15_interpreted(target, 0xee060f10, arm920t->d_far, 0x0);
+	arm920t_write_cp15_interpreted(target, 0xee060f30, arm920t->i_far, 0x0);
+	
+	/* read-modify-write CP15 test state register 
+	* to reenable I/D-cache linefills */
+	if (arm920t->preserve_cache)
+	{
+		arm920t_read_cp15_physical(target, 0x1e, &cp15c15);
+		jtag_execute_queue();
+		cp15c15 &= ~0x600U;
+		arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+	}
+}
+
+int arm920t_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, arm7_9_common_t **arm7_9_p, arm9tdmi_common_t **arm9tdmi_p, arm920t_common_t **arm920t_p)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9;
+	arm9tdmi_common_t *arm9tdmi;
+	arm920t_common_t *arm920t;
+	
+	if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
+	{
+		return -1;
+	}
+	
+	arm7_9 = armv4_5->arch_info;
+	if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC)
+	{
+		return -1;
+	}
+	
+	arm9tdmi = arm7_9->arch_info;
+	if (arm9tdmi->common_magic != ARM9TDMI_COMMON_MAGIC)
+	{
+		return -1;
+	}
+	
+	arm920t = arm9tdmi->arch_info;
+	if (arm920t->common_magic != ARM920T_COMMON_MAGIC)
+	{
+		return -1;
+	}
+	
+	*armv4_5_p = armv4_5;
+	*arm7_9_p = arm7_9;
+	*arm9tdmi_p = arm9tdmi;
+	*arm920t_p = arm920t;
+	
+	return ERROR_OK;
+}
+
+int arm920t_arch_state(struct target_s *target)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
+	arm920t_common_t *arm920t = arm9tdmi->arch_info;
+	
+	char *state[] = 
+	{
+		"disabled", "enabled"
+	};
+	
+	if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
+	{
+		ERROR("BUG: called for a non-ARMv4/5 target");
+		exit(-1);
+	}
+	
+	USER(	"target halted in %s state due to %s, current mode: %s\n"
+			"cpsr: 0x%8.8x pc: 0x%8.8x\n"
+			"MMU: %s, D-Cache: %s, I-Cache: %s",
+			 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[arm920t->armv4_5_mmu.mmu_enabled],
+			 state[arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled], 
+			 state[arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled]);
+	
+	return ERROR_OK;
+}
+
+int arm920t_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
+{
+	int retval;
+	
+	retval = arm7_9_read_memory(target, address, size, count, buffer);
+	
+	return retval;
+}
+
+int arm920t_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
+{
+	int retval;
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
+	arm920t_common_t *arm920t = arm9tdmi->arch_info;
+	
+	if ((retval = arm7_9_write_memory(target, address, size, count, buffer)) != ERROR_OK)
+		return retval;
+
+	if (((size == 4) || (size == 2)) && (count == 1))
+	{
+		if (arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled)
+		{
+			DEBUG("D-Cache enabled, writing through to main memory");
+			u32 pa, cb, ap;
+			int type, domain;
+
+			pa = armv4_5_mmu_translate_va(target, &arm920t->armv4_5_mmu, address, &type, &cb, &domain, &ap);
+			if (type == -1)
+				return ERROR_OK;
+			/* cacheable & bufferable means write-back region */
+			if (cb == 3)
+				armv4_5_mmu_write_physical(target, &arm920t->armv4_5_mmu, pa, size, count, buffer);
+		}
+		
+		if (arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled)
+		{
+			DEBUG("I-Cache enabled, invalidating affected I-Cache line");
+			arm920t_write_cp15_interpreted(target, 0xee070f35, 0x0, address);
+		}
+	}
+
+	return retval;
+}
+
+int arm920t_soft_reset_halt(struct target_s *target)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
+	arm920t_common_t *arm920t = arm9tdmi->arch_info;
+	reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
+	
+	if (target->state == TARGET_RUNNING)
+	{
+		target->type->halt(target);
+	}
+	
+	while (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0)
+	{
+		embeddedice_read_reg(dbg_stat);
+		jtag_execute_queue();
+	}
+	
+	target->state = TARGET_HALTED;
+	
+	/* SVC, ARM state, IRQ and FIQ disabled */
+	buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8, 0xd3);
+	armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
+	armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
+	
+	/* start fetching from 0x0 */
+	buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, 0x0);
+	armv4_5->core_cache->reg_list[15].dirty = 1;
+	armv4_5->core_cache->reg_list[15].valid = 1;
+	
+	armv4_5->core_mode = ARMV4_5_MODE_SVC;
+	armv4_5->core_state = ARMV4_5_STATE_ARM;
+	
+	arm920t_disable_mmu_caches(target, 1, 1, 1);
+	arm920t->armv4_5_mmu.mmu_enabled = 0;
+	arm920t->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0;
+	arm920t->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;
+
+	target_call_event_callbacks(target, TARGET_EVENT_HALTED);
+	
+	return ERROR_OK;
+}
+
+int arm920t_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
+{
+	arm9tdmi_init_target(cmd_ctx, target);
+		
+	return ERROR_OK;
+	
+}
+
+int arm920t_quit()
+{
+	
+	return ERROR_OK;
+}
+
+int arm920t_init_arch_info(target_t *target, arm920t_common_t *arm920t, int chain_pos, char *variant)
+{
+	arm9tdmi_common_t *arm9tdmi = &arm920t->arm9tdmi_common;
+	arm7_9_common_t *arm7_9 = &arm9tdmi->arm7_9_common;
+	
+	/* initialize arm9tdmi specific info (including arm7_9 and armv4_5)
+	 */
+	arm9tdmi_init_arch_info(target, arm9tdmi, chain_pos, variant);
+
+	arm9tdmi->arch_info = arm920t;
+	arm920t->common_magic = ARM920T_COMMON_MAGIC;
+	
+	arm7_9->post_debug_entry = arm920t_post_debug_entry;
+	arm7_9->pre_restore_context = arm920t_pre_restore_context;
+	
+	arm920t->armv4_5_mmu.armv4_5_cache.ctype = -1;
+	arm920t->armv4_5_mmu.get_ttb = arm920t_get_ttb;
+	arm920t->armv4_5_mmu.read_memory = arm7_9_read_memory;
+	arm920t->armv4_5_mmu.write_memory = arm7_9_write_memory;
+	arm920t->armv4_5_mmu.disable_mmu_caches = arm920t_disable_mmu_caches;
+	arm920t->armv4_5_mmu.enable_mmu_caches = arm920t_enable_mmu_caches;
+	arm920t->armv4_5_mmu.has_tiny_pages = 1;
+	arm920t->armv4_5_mmu.mmu_enabled = 0;
+	
+	/* disabling linefills leads to lockups, so keep them enabled for now
+	 * this doesn't affect correctness, but might affect timing issues, if
+	 * important data is evicted from the cache during the debug session
+	 * */
+	arm920t->preserve_cache = 0;
+	
+	/* override hw single-step capability from ARM9TDMI */
+	arm7_9->has_single_step = 1;
+	
+	return ERROR_OK;
+}
+
+int arm920t_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)
+{
+	int chain_pos;
+	char *variant = NULL;
+	arm920t_common_t *arm920t = malloc(sizeof(arm920t_common_t));
+	
+	if (argc < 4)
+	{
+		ERROR("'target arm920t' requires at least one additional argument");
+		exit(-1);
+	}
+	
+	chain_pos = strtoul(args[3], NULL, 0);
+	
+	if (argc >= 5)
+		variant = args[4];
+	
+	DEBUG("chain_pos: %i, variant: %s", chain_pos, variant);
+	
+	arm920t_init_arch_info(target, arm920t, chain_pos, variant);
+
+	return ERROR_OK;
+}
+
+int arm920t_register_commands(struct command_context_s *cmd_ctx)
+{
+	int retval;
+	command_t *arm920t_cmd;
+	
+		
+	retval = arm9tdmi_register_commands(cmd_ctx);
+	
+	arm920t_cmd = register_command(cmd_ctx, NULL, "arm920t", NULL, COMMAND_ANY, "arm920t specific commands");
+
+	register_command(cmd_ctx, arm920t_cmd, "cp15", arm920t_handle_cp15_command, COMMAND_EXEC, "display/modify cp15 register <num> [value]");
+	register_command(cmd_ctx, arm920t_cmd, "cp15i", arm920t_handle_cp15i_command, COMMAND_EXEC, "display/modify cp15 (interpreted access) <opcode> [value] [address]");
+	register_command(cmd_ctx, arm920t_cmd, "cache_info", arm920t_handle_cache_info_command, COMMAND_EXEC, "display information about target caches");
+	register_command(cmd_ctx, arm920t_cmd, "virt2phys", arm920t_handle_virt2phys_command, COMMAND_EXEC, "translate va to pa <va>");
+
+	register_command(cmd_ctx, arm920t_cmd, "mdw_phys", arm920t_handle_md_phys_command, COMMAND_EXEC, "display memory words <physical addr> [count]");
+	register_command(cmd_ctx, arm920t_cmd, "mdh_phys", arm920t_handle_md_phys_command, COMMAND_EXEC, "display memory half-words <physical addr> [count]");
+	register_command(cmd_ctx, arm920t_cmd, "mdb_phys", arm920t_handle_md_phys_command, COMMAND_EXEC, "display memory bytes <physical addr> [count]");
+
+	register_command(cmd_ctx, arm920t_cmd, "mww_phys", arm920t_handle_mw_phys_command, COMMAND_EXEC, "write memory word <physical addr> <value>");
+	register_command(cmd_ctx, arm920t_cmd, "mwh_phys", arm920t_handle_mw_phys_command, COMMAND_EXEC, "write memory half-word <physical addr> <value>");
+	register_command(cmd_ctx, arm920t_cmd, "mwb_phys", arm920t_handle_mw_phys_command, COMMAND_EXEC, "write memory byte <physical addr> <value>");
+
+	register_command(cmd_ctx, arm920t_cmd, "read_cache", arm920t_handle_read_cache_command, COMMAND_EXEC, "display I/D cache content");
+	register_command(cmd_ctx, arm920t_cmd, "read_mmu", arm920t_handle_read_mmu_command, COMMAND_EXEC, "display I/D mmu content");
+
+	return ERROR_OK;
+}
+
+int arm920t_handle_read_cache_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;
+	arm7_9_common_t *arm7_9;
+	arm9tdmi_common_t *arm9tdmi;
+	arm920t_common_t *arm920t;
+	arm_jtag_t *jtag_info;
+	u32 cp15c15;
+	u32 cp15_ctrl, cp15_ctrl_saved;
+	u32 regs[16];
+	u32 *regs_p[16];
+	u32 C15_C_D_Ind, C15_C_I_Ind;
+	int i;
+	FILE *output;
+	arm920t_cache_line_t d_cache[8][64], i_cache[8][64];
+	int segment, index;
+	
+	if (argc != 1)
+	{
+		command_print(cmd_ctx, "usage: arm920t read_cache <filename>");
+		return ERROR_OK;
+	}
+	
+	if ((output = fopen(args[0], "w")) == NULL)
+	{
+		DEBUG("error opening cache content file");
+		return ERROR_OK;
+	}
+	
+	for (i = 0; i < 16; i++)
+		regs_p[i] = &regs[i];
+		
+	if (arm920t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm920t) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "current target isn't an ARM920t target");
+		return ERROR_OK;
+	}
+	
+	jtag_info = &arm7_9->jtag_info;
+	
+	/* disable MMU and Caches */
+	arm920t_read_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0x1, 0), &cp15_ctrl);
+	jtag_execute_queue();
+	cp15_ctrl_saved = cp15_ctrl;
+	cp15_ctrl &= ~(ARMV4_5_MMU_ENABLED | ARMV4_5_D_U_CACHE_ENABLED | ARMV4_5_I_CACHE_ENABLED);
+	arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0x1, 0), cp15_ctrl);
+
+	/* read CP15 test state register */ 
+	arm920t_read_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), &cp15c15);
+	jtag_execute_queue();
+	
+	/* read DCache content */
+	fprintf(output, "DCache:\n");
+	
+	/* go through segments 0 to nsets (8 on ARM920T, 4 on ARM922T) */ 
+	for (segment = 0; segment < arm920t->armv4_5_mmu.armv4_5_cache.d_u_size.nsets; segment++)
+	{
+		fprintf(output, "\nsegment: %i\n----------", segment);
+		
+		/* Ra: r0 = SBZ(31:8):segment(7:5):SBZ(4:0) */
+		regs[0] = 0x0 | (segment << 5);
+		arm9tdmi_write_core_regs(target, 0x1, regs);
+		
+		/* set interpret mode */
+		cp15c15 |= 0x1;
+		arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
+		
+		/* D CAM Read, loads current victim into C15.C.D.Ind */
+		arm920t_execute_cp15(target, ARMV4_5_MCR(15,2,0,15,6,2), ARMV4_5_LDR(1, 0));
+	
+		/* read current victim */
+		arm920t_read_cp15_physical(target, 0x3d, &C15_C_D_Ind);
+
+		/* clear interpret mode */
+		cp15c15 &= ~0x1;
+		arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+
+		for (index = 0; index < 64; index++)
+		{
+			/* Ra: r0 = index(31:26):SBZ(25:8):segment(7:5):SBZ(4:0) */
+			regs[0] = 0x0 | (segment << 5) | (index << 26);
+			arm9tdmi_write_core_regs(target, 0x1, regs);
+
+			/* set interpret mode */
+			cp15c15 |= 0x1;
+			arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
+	
+			/* Write DCache victim */
+			arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,9,1,0), ARMV4_5_LDR(1, 0));
+	
+			/* Read D RAM */
+			arm920t_execute_cp15(target, ARMV4_5_MCR(15,2,0,15,10,2), ARMV4_5_LDMIA(0, 0x1fe, 0, 0));
+			
+			/* Read D CAM */
+			arm920t_execute_cp15(target, ARMV4_5_MCR(15,2,0,15,6,2), ARMV4_5_LDR(9, 0));
+			
+			/* clear interpret mode */
+			cp15c15 &= ~0x1;
+			arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+
+			/* read D RAM and CAM content */
+			arm9tdmi_read_core_regs(target, 0x3fe, regs_p);
+			jtag_execute_queue();
+
+			d_cache[segment][index].cam = regs[9];
+			
+			/* mask LFSR[6] */
+			regs[9] &= 0xfffffffe;
+			fprintf(output, "\nsegment: %i, index: %i, CAM: 0x%8.8x, content (%s):\n", segment, index, regs[9], (regs[9] & 0x10) ? "valid" : "invalid");
+			
+			for (i = 1; i < 9; i++)
+			{
+				 d_cache[segment][index].data[i] = regs[i];
+				 fprintf(output, "%i: 0x%8.8x\n", i-1, regs[i]);
+			}
+	
+		}
+		
+		/* Ra: r0 = index(31:26):SBZ(25:8):segment(7:5):SBZ(4:0) */
+		regs[0] = 0x0 | (segment << 5) | (C15_C_D_Ind << 26);
+		arm9tdmi_write_core_regs(target, 0x1, regs);
+
+		/* set interpret mode */
+		cp15c15 |= 0x1;
+		arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
+	
+		/* Write DCache victim */
+		arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,9,1,0), ARMV4_5_LDR(1, 0));
+	
+		/* clear interpret mode */
+		cp15c15 &= ~0x1;
+		arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+	}
+
+	/* read ICache content */
+	fprintf(output, "ICache:\n");
+	
+	/* go through segments 0 to nsets (8 on ARM920T, 4 on ARM922T) */ 
+	for (segment = 0; segment < arm920t->armv4_5_mmu.armv4_5_cache.d_u_size.nsets; segment++)
+	{
+		fprintf(output, "segment: %i\n----------", segment);
+		
+		/* Ra: r0 = SBZ(31:8):segment(7:5):SBZ(4:0) */
+		regs[0] = 0x0 | (segment << 5);
+		arm9tdmi_write_core_regs(target, 0x1, regs);
+		
+		/* set interpret mode */
+		cp15c15 |= 0x1;
+		arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
+		
+		/* I CAM Read, loads current victim into C15.C.I.Ind */
+		arm920t_execute_cp15(target, ARMV4_5_MCR(15,2,0,15,5,2), ARMV4_5_LDR(1, 0));
+	
+		/* read current victim */
+		arm920t_read_cp15_physical(target, 0x3b, &C15_C_I_Ind);
+
+		/* clear interpret mode */
+		cp15c15 &= ~0x1;
+		arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+
+		for (index = 0; index < 64; index++)
+		{
+			/* Ra: r0 = index(31:26):SBZ(25:8):segment(7:5):SBZ(4:0) */
+			regs[0] = 0x0 | (segment << 5) | (index << 26);
+			arm9tdmi_write_core_regs(target, 0x1, regs);
+
+			/* set interpret mode */
+			cp15c15 |= 0x1;
+			arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
+	
+			/* Write ICache victim */
+			arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,9,1,1), ARMV4_5_LDR(1, 0));
+	
+			/* Read I RAM */
+			arm920t_execute_cp15(target, ARMV4_5_MCR(15,2,0,15,9,2), ARMV4_5_LDMIA(0, 0x1fe, 0, 0));
+			
+			/* Read I CAM */
+			arm920t_execute_cp15(target, ARMV4_5_MCR(15,2,0,15,5,2), ARMV4_5_LDR(9, 0));
+			
+			/* clear interpret mode */
+			cp15c15 &= ~0x1;
+			arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+
+			/* read I RAM and CAM content */
+			arm9tdmi_read_core_regs(target, 0x3fe, regs_p);
+			jtag_execute_queue();
+
+			i_cache[segment][index].cam = regs[9];
+			
+			/* mask LFSR[6] */
+			regs[9] &= 0xfffffffe;
+			fprintf(output, "\nsegment: %i, index: %i, CAM: 0x%8.8x, content (%s):\n", segment, index, regs[9], (regs[9] & 0x10) ? "valid" : "invalid");
+			
+			for (i = 1; i < 9; i++)
+			{
+				 i_cache[segment][index].data[i] = regs[i];
+				 fprintf(output, "%i: 0x%8.8x\n", i-1, regs[i]);
+			}
+	
+		}
+		
+	
+		/* Ra: r0 = index(31:26):SBZ(25:8):segment(7:5):SBZ(4:0) */
+		regs[0] = 0x0 | (segment << 5) | (C15_C_D_Ind << 26);
+		arm9tdmi_write_core_regs(target, 0x1, regs);
+
+		/* set interpret mode */
+		cp15c15 |= 0x1;
+		arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
+	
+		/* Write ICache victim */
+		arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,9,1,1), ARMV4_5_LDR(1, 0));
+	
+		/* clear interpret mode */
+		cp15c15 &= ~0x1;
+		arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+	}
+	
+	/* restore CP15 MMU and Cache settings */
+	arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0x1, 0), cp15_ctrl_saved);
+	
+	command_print(cmd_ctx, "cache content successfully output to %s", args[0]);
+	
+	fclose(output);
+	
+	/* mark registers dirty. */
+	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 0).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 0).valid;
+	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 1).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 1).valid;
+	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 2).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 2).valid;
+	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 3).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 3).valid;
+	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 4).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 4).valid;
+	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 5).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 5).valid;
+	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 6).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 6).valid;
+	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 7).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 7).valid;
+	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 8).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 8).valid;
+	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 9).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 9).valid;
+	
+	return ERROR_OK;
+}
+
+int arm920t_handle_read_mmu_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;
+	arm7_9_common_t *arm7_9;
+	arm9tdmi_common_t *arm9tdmi;
+	arm920t_common_t *arm920t;
+	arm_jtag_t *jtag_info;
+	u32 cp15c15;
+	u32 cp15_ctrl, cp15_ctrl_saved;
+	u32 regs[16];
+	u32 *regs_p[16];
+	int i;
+	FILE *output;
+	u32 Dlockdown, Ilockdown;
+	arm920t_tlb_entry_t d_tlb[64], i_tlb[64];
+	int victim;
+	
+	if (argc != 1)
+	{
+		command_print(cmd_ctx, "usage: arm920t read_mmu <filename>");
+		return ERROR_OK;
+	}
+	
+	if ((output = fopen(args[0], "w")) == NULL)
+	{
+		DEBUG("error opening mmu content file");
+		return ERROR_OK;
+	}
+	
+	for (i = 0; i < 16; i++)
+		regs_p[i] = &regs[i];
+		
+	if (arm920t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm920t) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "current target isn't an ARM920t target");
+		return ERROR_OK;
+	}
+	
+	jtag_info = &arm7_9->jtag_info;
+	
+	/* disable MMU and Caches */
+	arm920t_read_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0x1, 0), &cp15_ctrl);
+	jtag_execute_queue();
+	cp15_ctrl_saved = cp15_ctrl;
+	cp15_ctrl &= ~(ARMV4_5_MMU_ENABLED | ARMV4_5_D_U_CACHE_ENABLED | ARMV4_5_I_CACHE_ENABLED);
+	arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0x1, 0), cp15_ctrl);
+
+	/* read CP15 test state register */ 
+	arm920t_read_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), &cp15c15);
+	jtag_execute_queue();
+
+	/* prepare reading D TLB content 
+	 * */
+	
+	/* set interpret mode */
+	cp15c15 |= 0x1;
+	arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
+	
+	/* Read D TLB lockdown */
+	arm920t_execute_cp15(target, ARMV4_5_MRC(15,0,0,10,0,0), ARMV4_5_LDR(1, 0));
+	
+	/* clear interpret mode */
+	cp15c15 &= ~0x1;
+	arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+	
+	/* read D TLB lockdown stored to r1 */
+	arm9tdmi_read_core_regs(target, 0x2, regs_p);
+	jtag_execute_queue();
+	Dlockdown = regs[1];
+	
+	for (victim = 0; victim < 64; victim += 8)
+	{
+		/* new lockdown value: base[31:26]:victim[25:20]:SBZ[19:1]:p[0] 
+		 * base remains unchanged, victim goes through entries 0 to 63 */
+		regs[1] = (Dlockdown & 0xfc000000) | (victim << 20);
+		arm9tdmi_write_core_regs(target, 0x2, regs);
+		
+		/* set interpret mode */
+		cp15c15 |= 0x1;
+		arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
+		
+		/* Write D TLB lockdown */
+		arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,10,0,0), ARMV4_5_STR(1, 0));
+	
+		/* Read D TLB CAM */
+		arm920t_execute_cp15(target, ARMV4_5_MCR(15,4,0,15,6,4), ARMV4_5_LDMIA(0, 0x3fc, 0, 0));
+		
+		/* clear interpret mode */
+		cp15c15 &= ~0x1;
+		arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+		
+		/* read D TLB CAM content stored to r2-r9 */
+		arm9tdmi_read_core_regs(target, 0x3fc, regs_p);
+		jtag_execute_queue();
+		
+		for (i = 0; i < 8; i++)
+			d_tlb[victim + i].cam = regs[i + 2]; 
+	}
+
+	for (victim = 0; victim < 64; victim++)
+	{
+		/* new lockdown value: base[31:26]:victim[25:20]:SBZ[19:1]:p[0] 
+		 * base remains unchanged, victim goes through entries 0 to 63 */
+		regs[1] = (Dlockdown & 0xfc000000) | (victim << 20);
+		arm9tdmi_write_core_regs(target, 0x2, regs);
+		
+		/* set interpret mode */
+		cp15c15 |= 0x1;
+		arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
+		
+		/* Write D TLB lockdown */
+		arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,10,0,0), ARMV4_5_STR(1, 0));
+	
+		/* Read D TLB RAM1 */
+		arm920t_execute_cp15(target, ARMV4_5_MCR(15,4,0,15,10,4), ARMV4_5_LDR(2,0));
+
+		/* Read D TLB RAM2 */
+		arm920t_execute_cp15(target, ARMV4_5_MCR(15,4,0,15,2,5), ARMV4_5_LDR(3,0));
+		
+		/* clear interpret mode */
+		cp15c15 &= ~0x1;
+		arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+		
+		/* read D TLB RAM content stored to r2 and r3 */
+		arm9tdmi_read_core_regs(target, 0xc, regs_p);
+		jtag_execute_queue();
+
+		d_tlb[victim].ram1 = regs[2]; 
+		d_tlb[victim].ram2 = regs[3]; 
+	}
+		
+	/* restore D TLB lockdown */
+	regs[1] = Dlockdown;
+	arm9tdmi_write_core_regs(target, 0x2, regs);
+	
+	/* Write D TLB lockdown */
+	arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,10,0,0), ARMV4_5_STR(1, 0));
+
+	/* prepare reading I TLB content 
+	 * */
+	
+	/* set interpret mode */
+	cp15c15 |= 0x1;
+	arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
+	
+	/* Read I TLB lockdown */
+	arm920t_execute_cp15(target, ARMV4_5_MRC(15,0,0,10,0,1), ARMV4_5_LDR(1, 0));
+	
+	/* clear interpret mode */
+	cp15c15 &= ~0x1;
+	arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+	
+	/* read I TLB lockdown stored to r1 */
+	arm9tdmi_read_core_regs(target, 0x2, regs_p);
+	jtag_execute_queue();
+	Ilockdown = regs[1];
+	
+	for (victim = 0; victim < 64; victim += 8)
+	{
+		/* new lockdown value: base[31:26]:victim[25:20]:SBZ[19:1]:p[0] 
+		 * base remains unchanged, victim goes through entries 0 to 63 */
+		regs[1] = (Ilockdown & 0xfc000000) | (victim << 20);
+		arm9tdmi_write_core_regs(target, 0x2, regs);
+		
+		/* set interpret mode */
+		cp15c15 |= 0x1;
+		arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
+		
+		/* Write I TLB lockdown */
+		arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,10,0,1), ARMV4_5_STR(1, 0));
+	
+		/* Read I TLB CAM */
+		arm920t_execute_cp15(target, ARMV4_5_MCR(15,4,0,15,5,4), ARMV4_5_LDMIA(0, 0x3fc, 0, 0));
+		
+		/* clear interpret mode */
+		cp15c15 &= ~0x1;
+		arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+		
+		/* read I TLB CAM content stored to r2-r9 */
+		arm9tdmi_read_core_regs(target, 0x3fc, regs_p);
+		jtag_execute_queue();
+		
+		for (i = 0; i < 8; i++)
+			i_tlb[i + victim].cam = regs[i + 2]; 
+	}
+
+	for (victim = 0; victim < 64; victim++)
+	{
+		/* new lockdown value: base[31:26]:victim[25:20]:SBZ[19:1]:p[0] 
+		 * base remains unchanged, victim goes through entries 0 to 63 */
+		regs[1] = (Dlockdown & 0xfc000000) | (victim << 20);
+		arm9tdmi_write_core_regs(target, 0x2, regs);
+		
+		/* set interpret mode */
+		cp15c15 |= 0x1;
+		arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0xf, 0), cp15c15);
+		
+		/* Write I TLB lockdown */
+		arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,10,0,1), ARMV4_5_STR(1, 0));
+	
+		/* Read I TLB RAM1 */
+		arm920t_execute_cp15(target, ARMV4_5_MCR(15,4,0,15,9,4), ARMV4_5_LDR(2,0));
+
+		/* Read I TLB RAM2 */
+		arm920t_execute_cp15(target, ARMV4_5_MCR(15,4,0,15,1,5), ARMV4_5_LDR(3,0));
+		
+		/* clear interpret mode */
+		cp15c15 &= ~0x1;
+		arm920t_write_cp15_physical(target, 0x1e, cp15c15);
+		
+		/* read I TLB RAM content stored to r2 and r3 */
+		arm9tdmi_read_core_regs(target, 0xc, regs_p);
+		jtag_execute_queue();
+
+		i_tlb[victim].ram1 = regs[2]; 
+		i_tlb[victim].ram2 = regs[3]; 
+	}
+		
+	/* restore I TLB lockdown */
+	regs[1] = Ilockdown;
+	arm9tdmi_write_core_regs(target, 0x2, regs);
+	
+	/* Write I TLB lockdown */
+	arm920t_execute_cp15(target, ARMV4_5_MCR(15,0,0,10,0,1), ARMV4_5_STR(1, 0));
+	
+	/* restore CP15 MMU and Cache settings */
+	arm920t_write_cp15_physical(target, ARM920T_CP15_PHYS_ADDR(0, 0x1, 0), cp15_ctrl_saved);
+
+	/* output data to file */	
+	fprintf(output, "D TLB content:\n");
+	for (i = 0; i < 64; i++)
+	{
+		fprintf(output, "%i: 0x%8.8x 0x%8.8x 0x%8.8x %s\n", i, d_tlb[i].cam, d_tlb[i].ram1, d_tlb[i].ram2, (d_tlb[i].cam & 0x20) ? "(valid)" : "(invalid)");
+	}
+
+	fprintf(output, "\n\nI TLB content:\n");
+	for (i = 0; i < 64; i++)
+	{
+		fprintf(output, "%i: 0x%8.8x 0x%8.8x 0x%8.8x %s\n", i, i_tlb[i].cam, i_tlb[i].ram1, i_tlb[i].ram2, (i_tlb[i].cam & 0x20) ? "(valid)" : "(invalid)");
+	}
+	
+	command_print(cmd_ctx, "mmu content successfully output to %s", args[0]);
+	
+	fclose(output);
+	
+	/* mark registers dirty */
+	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 0).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 0).valid;
+	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 1).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 1).valid;
+	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 2).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 2).valid;
+	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 3).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 3).valid;
+	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 4).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 4).valid;
+	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 5).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 5).valid;
+	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 6).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 6).valid;
+	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 7).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 7).valid;
+	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 8).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 8).valid;
+	ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 9).dirty = ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5->core_mode, 9).valid;
+	
+	return ERROR_OK;
+}
+int arm920t_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	int retval;
+	target_t *target = get_current_target(cmd_ctx);
+	armv4_5_common_t *armv4_5;
+	arm7_9_common_t *arm7_9;
+	arm9tdmi_common_t *arm9tdmi;
+	arm920t_common_t *arm920t;
+	arm_jtag_t *jtag_info;
+
+	if (arm920t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm920t) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "current target isn't an ARM920t target");
+		return ERROR_OK;
+	}
+	
+	jtag_info = &arm7_9->jtag_info;
+	
+	if (target->state != TARGET_HALTED)
+	{
+		command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+		return ERROR_OK;
+	}
+
+	/* one or more argument, access a single register (write if second argument is given */
+	if (argc >= 1)
+	{
+		int address = strtoul(args[0], NULL, 0);
+
+		if (argc == 1)
+		{
+			u32 value;
+			if ((retval = arm920t_read_cp15_physical(target, address, &value)) != ERROR_OK)
+			{
+				command_print(cmd_ctx, "couldn't access reg %i", address);
+				return ERROR_OK;
+			}
+			jtag_execute_queue();
+			
+			command_print(cmd_ctx, "%i: %8.8x", address, value);
+		}
+		else if (argc == 2)
+		{
+			u32 value = strtoul(args[1], NULL, 0);
+			if ((retval = arm920t_write_cp15_physical(target, address, value)) != ERROR_OK)
+			{
+				command_print(cmd_ctx, "couldn't access reg %i", address);
+				return ERROR_OK;
+			}
+			command_print(cmd_ctx, "%i: %8.8x", address, value);
+		}
+	}
+
+	return ERROR_OK;
+}
+
+int arm920t_handle_cp15i_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	int retval;
+	target_t *target = get_current_target(cmd_ctx);
+	armv4_5_common_t *armv4_5;
+	arm7_9_common_t *arm7_9;
+	arm9tdmi_common_t *arm9tdmi;
+	arm920t_common_t *arm920t;
+	arm_jtag_t *jtag_info;
+
+	if (arm920t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm920t) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "current target isn't an ARM920t target");
+		return ERROR_OK;
+	}
+	
+	jtag_info = &arm7_9->jtag_info;
+	
+	if (target->state != TARGET_HALTED)
+	{
+		command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+		return ERROR_OK;
+	}
+
+	/* one or more argument, access a single register (write if second argument is given */
+	if (argc >= 1)
+	{
+		u32 opcode = strtoul(args[0], NULL, 0);
+
+		if (argc == 1)
+		{
+			u32 value;
+			if ((retval = arm920t_read_cp15_interpreted(target, opcode, 0x0, &value)) != ERROR_OK)
+			{
+				command_print(cmd_ctx, "couldn't execute %8.8x", opcode);
+				return ERROR_OK;
+			}
+			
+			command_print(cmd_ctx, "%8.8x: %8.8x", opcode, value);
+		}
+		else if (argc == 2)
+		{
+			u32 value = strtoul(args[1], NULL, 0);
+			if ((retval = arm920t_write_cp15_interpreted(target, opcode, value, 0)) != ERROR_OK)
+			{
+				command_print(cmd_ctx, "couldn't execute %8.8x", opcode);
+				return ERROR_OK;
+			}
+			command_print(cmd_ctx, "%8.8x: %8.8x", opcode, value);
+		}
+		else if (argc == 3)
+		{
+			u32 value = strtoul(args[1], NULL, 0);
+			u32 address = strtoul(args[2], NULL, 0);
+			if ((retval = arm920t_write_cp15_interpreted(target, opcode, value, address)) != ERROR_OK)
+			{
+				command_print(cmd_ctx, "couldn't execute %8.8x", opcode);
+				return ERROR_OK;
+			}
+			command_print(cmd_ctx, "%8.8x: %8.8x %8.8x", opcode, value, address);
+		}
+	}
+	else
+	{
+		command_print(cmd_ctx, "usage: arm920t cp15i <opcode> [value] [address]");
+	}
+
+	return ERROR_OK;
+}
+
+int arm920t_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;
+	arm7_9_common_t *arm7_9;
+	arm9tdmi_common_t *arm9tdmi;
+	arm920t_common_t *arm920t;
+	
+	if (arm920t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm920t) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "current target isn't an ARM920t target");
+		return ERROR_OK;
+	}
+	
+	return armv4_5_handle_cache_info_command(cmd_ctx, &arm920t->armv4_5_mmu.armv4_5_cache);
+}
+
+int arm920t_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;
+	arm7_9_common_t *arm7_9;
+	arm9tdmi_common_t *arm9tdmi;
+	arm920t_common_t *arm920t;
+	arm_jtag_t *jtag_info;
+
+	if (arm920t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm920t) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "current target isn't an ARM920t target");
+		return ERROR_OK;
+	}
+	
+	jtag_info = &arm7_9->jtag_info;
+	
+	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, &arm920t->armv4_5_mmu);
+}
+
+int arm920t_handle_md_phys_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;
+	arm7_9_common_t *arm7_9;
+	arm9tdmi_common_t *arm9tdmi;
+	arm920t_common_t *arm920t;
+	arm_jtag_t *jtag_info;
+
+	if (arm920t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm920t) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "current target isn't an ARM920t target");
+		return ERROR_OK;
+	}
+	
+	jtag_info = &arm7_9->jtag_info;
+	
+	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_md_phys_command(cmd_ctx, cmd, args, argc, target, &arm920t->armv4_5_mmu);
+}
+
+int arm920t_handle_mw_phys_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;
+	arm7_9_common_t *arm7_9;
+	arm9tdmi_common_t *arm9tdmi;
+	arm920t_common_t *arm920t;
+	arm_jtag_t *jtag_info;
+
+	if (arm920t_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm920t) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "current target isn't an ARM920t target");
+		return ERROR_OK;
+	}
+	
+	jtag_info = &arm7_9->jtag_info;
+	
+	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_mw_phys_command(cmd_ctx, cmd, args, argc, target, &arm920t->armv4_5_mmu);
+}
diff --git a/src/target/arm926ejs.c b/src/target/arm926ejs.c
index 75d43fd8a798991df45308ee2ff5e955a98f5a8c..a02c27ae79bd3289aac7c4b797c4928ec18685d7 100644
--- a/src/target/arm926ejs.c
+++ b/src/target/arm926ejs.c
@@ -1,944 +1,944 @@
-/***************************************************************************
- *   Copyright (C) 2007 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 "arm926ejs.h"
-#include "jtag.h"
-#include "log.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#if 1
-#define _DEBUG_INSTRUCTION_EXECUTION_
-#endif
-
-/* cli handling */
-int arm926ejs_register_commands(struct command_context_s *cmd_ctx);
-
-int arm926ejs_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int arm926ejs_handle_cp15i_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int arm926ejs_handle_virt2phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int arm926ejs_handle_cache_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int arm926ejs_handle_md_phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int arm926ejs_handle_mw_phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-
-int arm926ejs_handle_read_cache_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int arm926ejs_handle_read_mmu_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-
-/* forward declarations */
-int arm926ejs_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
-int arm926ejs_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
-int arm926ejs_quit();
-int arm926ejs_arch_state(struct target_s *target);
-int arm926ejs_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
-int arm926ejs_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
-int arm926ejs_soft_reset_halt(struct target_s *target);
-static int arm926ejs_virt2phys(struct target_s *target, u32 virtual, u32 *physical);
-static int arm926ejs_mmu(struct target_s *target, int *enabled);
-
-target_type_t arm926ejs_target =
-{
-	.name = "arm926ejs",
-
-	.poll = arm7_9_poll,
-	.arch_state = arm926ejs_arch_state,
-
-	.target_request_data = arm7_9_target_request_data,
-
-	.halt = arm7_9_halt,
-	.resume = arm7_9_resume,
-	.step = arm7_9_step,
-
-	.assert_reset = arm7_9_assert_reset,
-	.deassert_reset = arm7_9_deassert_reset,
-	.soft_reset_halt = arm926ejs_soft_reset_halt,
-	.prepare_reset_halt = arm7_9_prepare_reset_halt,
-	
-	.get_gdb_reg_list = armv4_5_get_gdb_reg_list,
-
-	.read_memory = arm7_9_read_memory,
-	.write_memory = arm926ejs_write_memory,
-	.bulk_write_memory = arm7_9_bulk_write_memory,
-	.checksum_memory = arm7_9_checksum_memory,
-	
-	.run_algorithm = armv4_5_run_algorithm,
-
-	.add_breakpoint = arm7_9_add_breakpoint,
-	.remove_breakpoint = arm7_9_remove_breakpoint,
-	.add_watchpoint = arm7_9_add_watchpoint,
-	.remove_watchpoint = arm7_9_remove_watchpoint,
-
-	.register_commands = arm926ejs_register_commands,
-	.target_command = arm926ejs_target_command,
-	.init_target = arm926ejs_init_target,
-	.quit = arm926ejs_quit,
-	.virt2phys = arm926ejs_virt2phys,
-	.mmu = arm926ejs_mmu
-};
-
-
-int arm926ejs_catch_broken_irscan(u8 *captured, void *priv, scan_field_t *field)
-{
-	/* The ARM926EJ-S' instruction register is 4 bits wide */
-	u8 t = *captured & 0xf;
-	u8 t2 = *field->in_check_value & 0xf;
-	if (t == t2)
-	{
-		return ERROR_OK;
-	}
-	else if ((t == 0x0f) || (t == 0x00))
-	{
-		DEBUG("caught ARM926EJ-S invalid Capture-IR result after CP15 access");
-		return ERROR_OK;
-	}
-	return ERROR_JTAG_QUEUE_FAILED;;
-}
-
-#define ARM926EJS_CP15_ADDR(opcode_1, opcode_2, CRn, CRm) ((opcode_1 << 11) | (opcode_2 << 8) | (CRn << 4) | (CRm << 0))
-
-int arm926ejs_cp15_read(target_t *target, u32 op1, u32 op2, u32 CRn, u32 CRm, u32 *value)
-{
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-	u32 address = ARM926EJS_CP15_ADDR(op1, op2, CRn, CRm);
-	scan_field_t fields[4];
-	u8 address_buf[2];
-	u8 nr_w_buf = 0;
-	u8 access = 1;
-	
-	buf_set_u32(address_buf, 0, 14, address);
-	
-	jtag_add_end_state(TAP_RTI);
-	arm_jtag_scann(jtag_info, 0xf);
-	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
-
-	fields[0].device = jtag_info->chain_pos;
-	fields[0].num_bits = 32;
-	fields[0].out_value = NULL;
-	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 = jtag_info->chain_pos;
-	fields[1].num_bits = 1;
-	fields[1].out_value = &access;
-	fields[1].out_mask = NULL;
-	fields[1].in_value = &access;
-	fields[1].in_check_value = NULL;
-	fields[1].in_check_mask = NULL;
-	fields[1].in_handler = NULL;
-	fields[1].in_handler_priv = NULL;
-
-	fields[2].device = jtag_info->chain_pos;
-	fields[2].num_bits = 14;
-	fields[2].out_value = address_buf;
-	fields[2].out_mask = NULL;
-	fields[2].in_value = NULL;
-	fields[2].in_check_value = NULL;
-	fields[2].in_check_mask = NULL;
-	fields[2].in_handler = NULL;
-	fields[2].in_handler_priv = NULL;
-
-	fields[3].device = jtag_info->chain_pos;
-	fields[3].num_bits = 1;
-	fields[3].out_value = &nr_w_buf;
-	fields[3].out_mask = NULL;
-	fields[3].in_value = NULL;
-	fields[3].in_check_value = NULL;
-	fields[3].in_check_mask = NULL;
-	fields[3].in_handler = NULL;
-	fields[3].in_handler_priv = NULL;
-	
-	jtag_add_dr_scan(4, fields, -1, NULL);
-
-	fields[0].in_handler_priv = value;
-	fields[0].in_handler = arm_jtag_buf_to_u32;
-	
-	do
-	{
-		/* rescan with NOP, to wait for the access to complete */
-		access = 0;
-		nr_w_buf = 0;
-		jtag_add_dr_scan(4, fields, -1, NULL);
-		jtag_execute_queue();
-	} while (buf_get_u32(&access, 0, 1) != 1);
-
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_
-	DEBUG("addr: 0x%x value: %8.8x", address, *value);
-#endif
-	
-	arm_jtag_set_instr(jtag_info, 0xc, &arm926ejs_catch_broken_irscan);
-
-	return ERROR_OK;
-}
-
-int arm926ejs_cp15_write(target_t *target, u32 op1, u32 op2, u32 CRn, u32 CRm, u32 value)
-{
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-	u32 address = ARM926EJS_CP15_ADDR(op1, op2, CRn, CRm);
-	scan_field_t fields[4];
-	u8 value_buf[4];
-	u8 address_buf[2];
-	u8 nr_w_buf = 1;
-	u8 access = 1;
-	
-	buf_set_u32(address_buf, 0, 14, address);
-	buf_set_u32(value_buf, 0, 32, value);
-	
-	jtag_add_end_state(TAP_RTI);
-	arm_jtag_scann(jtag_info, 0xf);
-	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
-
-	fields[0].device = jtag_info->chain_pos;
-	fields[0].num_bits = 32;
-	fields[0].out_value = value_buf;
-	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 = jtag_info->chain_pos;
-	fields[1].num_bits = 1;
-	fields[1].out_value = &access;
-	fields[1].out_mask = NULL;
-	fields[1].in_value = &access;
-	fields[1].in_check_value = NULL;
-	fields[1].in_check_mask = NULL;
-	fields[1].in_handler = NULL;
-	fields[1].in_handler_priv = NULL;
-
-	fields[2].device = jtag_info->chain_pos;
-	fields[2].num_bits = 14;
-	fields[2].out_value = address_buf;
-	fields[2].out_mask = NULL;
-	fields[2].in_value = NULL;
-	fields[2].in_check_value = NULL;
-	fields[2].in_check_mask = NULL;
-	fields[2].in_handler = NULL;
-	fields[2].in_handler_priv = NULL;
-
-	fields[3].device = jtag_info->chain_pos;
-	fields[3].num_bits = 1;
-	fields[3].out_value = &nr_w_buf;
-	fields[3].out_mask = NULL;
-	fields[3].in_value = NULL;
-	fields[3].in_check_value = NULL;
-	fields[3].in_check_mask = NULL;
-	fields[3].in_handler = NULL;
-	fields[3].in_handler_priv = NULL;
-	
-	jtag_add_dr_scan(4, fields, -1, NULL);
-
-	do
-	{
-		/* rescan with NOP, to wait for the access to complete */
-		access = 0;
-		nr_w_buf = 0;
-		jtag_add_dr_scan(4, fields, -1, NULL);
-		jtag_execute_queue();
-	} while (buf_get_u32(&access, 0, 1) != 1);
-
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_
-	DEBUG("addr: 0x%x value: %8.8x", address, value);
-#endif
-
-	arm_jtag_set_instr(jtag_info, 0xf, &arm926ejs_catch_broken_irscan);
-
-	return ERROR_OK;
-}
-
-int arm926ejs_examine_debug_reason(target_t *target)
-{
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
-	int debug_reason;
-	int retval;
-
-	embeddedice_read_reg(dbg_stat);
-	if ((retval = jtag_execute_queue()) != ERROR_OK)
-		return retval;
-	
-	debug_reason = buf_get_u32(dbg_stat->value, 6, 4);
-	
-	switch (debug_reason)
-	{
-		case 1:
-			DEBUG("breakpoint from EICE unit 0");
-			target->debug_reason = DBG_REASON_BREAKPOINT;
-			break;
-		case 2:
-			DEBUG("breakpoint from EICE unit 1");
-			target->debug_reason = DBG_REASON_BREAKPOINT;
-			break;
-		case 3:
-			DEBUG("soft breakpoint (BKPT instruction)");
-			target->debug_reason = DBG_REASON_BREAKPOINT;
-			break;
-		case 4:
-			DEBUG("vector catch breakpoint");
-			target->debug_reason = DBG_REASON_BREAKPOINT;
-			break;
-		case 5:
-			DEBUG("external breakpoint");
-			target->debug_reason = DBG_REASON_BREAKPOINT;
-			break;
-		case 6:
-			DEBUG("watchpoint from EICE unit 0");
-			target->debug_reason = DBG_REASON_WATCHPOINT;
-			break;
-		case 7:
-			DEBUG("watchpoint from EICE unit 1");
-			target->debug_reason = DBG_REASON_WATCHPOINT;
-			break;
-		case 8:
-			DEBUG("external watchpoint");
-			target->debug_reason = DBG_REASON_WATCHPOINT;
-			break;
-		case 9:
-			DEBUG("internal debug request");
-			target->debug_reason = DBG_REASON_DBGRQ;
-			break;
-		case 10:
-			DEBUG("external debug request");
-			target->debug_reason = DBG_REASON_DBGRQ;
-			break;
-		case 11:
-			ERROR("BUG: debug re-entry from system speed access shouldn't be handled here");
-			break;
-		default:
-			ERROR("BUG: unknown debug reason: 0x%x", debug_reason);
-			target->debug_reason = DBG_REASON_DBGRQ;
-	}
-	
-	return ERROR_OK;
-}
-
-u32 arm926ejs_get_ttb(target_t *target)
-{
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
-	arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;
-	int retval;
-	u32 ttb = 0x0;
-
-	if ((retval = arm926ejs->read_cp15(target, 0, 0, 2, 0, &ttb)) != ERROR_OK)
-		return retval;
-
-	return ttb;
-}
-
-void arm926ejs_disable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_cache)
-{
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
-	arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;
-	u32 cp15_control;
-
-	/* read cp15 control register */
-	arm926ejs->read_cp15(target, 0, 0, 1, 0, &cp15_control);
-	jtag_execute_queue();
-	
-	if (mmu)
-	{
-		/* invalidate TLB */
-		arm926ejs->write_cp15(target, 0, 0, 8, 7, 0x0);
-		
-		cp15_control &= ~0x1U;
-	}
-	
-	if (d_u_cache)
-	{
-		u32 debug_override;
-		/* read-modify-write CP15 debug override register 
-		 * to enable "test and clean all" */
-		arm926ejs->read_cp15(target, 0, 0, 15, 0, &debug_override);
-		debug_override |= 0x80000;
-		arm926ejs->write_cp15(target, 0, 0, 15, 0, debug_override);
-		
-		/* clean and invalidate DCache */
-		arm926ejs->write_cp15(target, 0, 0, 7, 5, 0x0);
-
-		/* write CP15 debug override register 
-		 * to disable "test and clean all" */
-		debug_override &= ~0x80000;
-		arm926ejs->write_cp15(target, 0, 0, 15, 0, debug_override);
-		
-		cp15_control &= ~0x4U;
-	}
-	
-	if (i_cache)
-	{
-		/* invalidate ICache */
-		arm926ejs->write_cp15(target, 0, 0, 7, 5, 0x0);
-		
-		cp15_control &= ~0x1000U;
-	}
-	
-	arm926ejs->write_cp15(target, 0, 0, 1, 0, cp15_control);
-}
-
-void arm926ejs_enable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_cache)
-{
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
-	arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;
-	u32 cp15_control;
-
-	/* read cp15 control register */
-	arm926ejs->read_cp15(target, 0, 0, 1, 0, &cp15_control);
-	jtag_execute_queue();
-		
-	if (mmu)
-		cp15_control |= 0x1U;
-	
-	if (d_u_cache)
-		cp15_control |= 0x4U;
-	
-	if (i_cache)
-		cp15_control |= 0x1000U;
-	
-	arm926ejs->write_cp15(target, 0, 0, 1, 0, cp15_control);
-}
-
-void arm926ejs_post_debug_entry(target_t *target)
-{
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
-	arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;
-
-	/* examine cp15 control reg */
-	arm926ejs->read_cp15(target, 0, 0, 1, 0, &arm926ejs->cp15_control_reg);
-	jtag_execute_queue();
-	DEBUG("cp15_control_reg: %8.8x", arm926ejs->cp15_control_reg);
-
-	if (arm926ejs->armv4_5_mmu.armv4_5_cache.ctype == -1)
-	{
-		u32 cache_type_reg;
-		/* identify caches */
-		arm926ejs->read_cp15(target, 0, 1, 0, 0, &cache_type_reg);
-		jtag_execute_queue();
-		armv4_5_identify_cache(cache_type_reg, &arm926ejs->armv4_5_mmu.armv4_5_cache);
-	}
-
-	arm926ejs->armv4_5_mmu.mmu_enabled = (arm926ejs->cp15_control_reg & 0x1U) ? 1 : 0;
-	arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = (arm926ejs->cp15_control_reg & 0x4U) ? 1 : 0;
-	arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled = (arm926ejs->cp15_control_reg & 0x1000U) ? 1 : 0;
-
-	/* save i/d fault status and address register */
-	arm926ejs->read_cp15(target, 0, 0, 5, 0, &arm926ejs->d_fsr);
-	arm926ejs->read_cp15(target, 0, 1, 5, 0, &arm926ejs->i_fsr);
-	arm926ejs->read_cp15(target, 0, 0, 6, 0, &arm926ejs->d_far);
-	
-	DEBUG("D FSR: 0x%8.8x, D FAR: 0x%8.8x, I FSR: 0x%8.8x",
-		arm926ejs->d_fsr, arm926ejs->d_far, arm926ejs->i_fsr);  
-
-
-	u32 cache_dbg_ctrl;
-	
-	/* read-modify-write CP15 cache debug control register 
-	 * to disable I/D-cache linefills and force WT */
-	arm926ejs->read_cp15(target, 7, 0, 15, 0, &cache_dbg_ctrl);
-	cache_dbg_ctrl |= 0x7;
-	arm926ejs->write_cp15(target, 7, 0, 15, 0, cache_dbg_ctrl);
-}
-
-void arm926ejs_pre_restore_context(target_t *target)
-{
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
-	arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;
-
-	/* restore i/d fault status and address register */
-	arm926ejs->write_cp15(target, 0, 0, 5, 0, arm926ejs->d_fsr);
-	arm926ejs->write_cp15(target, 0, 1, 5, 0, arm926ejs->i_fsr);
-	arm926ejs->write_cp15(target, 0, 0, 6, 0, arm926ejs->d_far);
-	
-	u32 cache_dbg_ctrl;
-	
-	/* read-modify-write CP15 cache debug control register 
-	 * to reenable I/D-cache linefills and disable WT */
-	arm926ejs->read_cp15(target, 7, 0, 15, 0, &cache_dbg_ctrl);
-	cache_dbg_ctrl &= ~0x7;
-	arm926ejs->write_cp15(target, 7, 0, 15, 0, cache_dbg_ctrl);
-}
-
-int arm926ejs_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, arm7_9_common_t **arm7_9_p, arm9tdmi_common_t **arm9tdmi_p, arm926ejs_common_t **arm926ejs_p)
-{
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9;
-	arm9tdmi_common_t *arm9tdmi;
-	arm926ejs_common_t *arm926ejs;
-	
-	if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
-	{
-		return -1;
-	}
-	
-	arm7_9 = armv4_5->arch_info;
-	if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC)
-	{
-		return -1;
-	}
-	
-	arm9tdmi = arm7_9->arch_info;
-	if (arm9tdmi->common_magic != ARM9TDMI_COMMON_MAGIC)
-	{
-		return -1;
-	}
-	
-	arm926ejs = arm9tdmi->arch_info;
-	if (arm926ejs->common_magic != ARM926EJS_COMMON_MAGIC)
-	{
-		return -1;
-	}
-	
-	*armv4_5_p = armv4_5;
-	*arm7_9_p = arm7_9;
-	*arm9tdmi_p = arm9tdmi;
-	*arm926ejs_p = arm926ejs;
-	
-	return ERROR_OK;
-}
-
-int arm926ejs_arch_state(struct target_s *target)
-{
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
-	arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;
-	
-	char *state[] = 
-	{
-		"disabled", "enabled"
-	};
-	
-	if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
-	{
-		ERROR("BUG: called for a non-ARMv4/5 target");
-		exit(-1);
-	}
-	
-	USER(
-			"target halted in %s state due to %s, current mode: %s\n"
-			"cpsr: 0x%8.8x pc: 0x%8.8x\n"
-			"MMU: %s, D-Cache: %s, I-Cache: %s",
-			 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[arm926ejs->armv4_5_mmu.mmu_enabled],
-			 state[arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled], 
-			 state[arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled]);
-	
-	return ERROR_OK;
-}
-
-int arm926ejs_soft_reset_halt(struct target_s *target)
-{
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
-	arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;
-	reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
-	
-	if (target->state == TARGET_RUNNING)
-	{
-		target->type->halt(target);
-	}
-	
-	while (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0)
-	{
-		embeddedice_read_reg(dbg_stat);
-		jtag_execute_queue();
-	}
-	
-	target->state = TARGET_HALTED;
-	
-	/* SVC, ARM state, IRQ and FIQ disabled */
-	buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8, 0xd3);
-	armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
-	armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
-	
-	/* start fetching from 0x0 */
-	buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, 0x0);
-	armv4_5->core_cache->reg_list[15].dirty = 1;
-	armv4_5->core_cache->reg_list[15].valid = 1;
-	
-	armv4_5->core_mode = ARMV4_5_MODE_SVC;
-	armv4_5->core_state = ARMV4_5_STATE_ARM;
-	
-	arm926ejs_disable_mmu_caches(target, 1, 1, 1);
-	arm926ejs->armv4_5_mmu.mmu_enabled = 0;
-	arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0;
-	arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;
-
-	target_call_event_callbacks(target, TARGET_EVENT_HALTED);
-	
-	return ERROR_OK;
-}
-
-int arm926ejs_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
-{
-	int retval;
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
-	arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;
-	
-	if ((retval = arm7_9_write_memory(target, address, size, count, buffer)) != ERROR_OK)
-		return retval;
-
-	/* If ICache is enabled, we have to invalidate affected ICache lines
-	 * the DCache is forced to write-through, so we don't have to clean it here
-	 */
-	if (arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled)
-	{
-		if (count <= 1)
-		{
-			/* invalidate ICache single entry with MVA */
-			arm926ejs->write_cp15(target, 0, 1, 7, 5, address);
-		}
-		else
-		{
-			/* invalidate ICache */
-			arm926ejs->write_cp15(target, 0, 0, 7, 5, address);
-		}
-	}
-
-	return retval;
-}
-
-int arm926ejs_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
-{
-	arm9tdmi_init_target(cmd_ctx, target);
-		
-	return ERROR_OK;
-	
-}
-
-int arm926ejs_quit()
-{
-	
-	return ERROR_OK;
-}
-
-int arm926ejs_init_arch_info(target_t *target, arm926ejs_common_t *arm926ejs, int chain_pos, char *variant)
-{
-	arm9tdmi_common_t *arm9tdmi = &arm926ejs->arm9tdmi_common;
-	arm7_9_common_t *arm7_9 = &arm9tdmi->arm7_9_common;
-	
-	/* initialize arm9tdmi specific info (including arm7_9 and armv4_5)
-	 */
-	arm9tdmi_init_arch_info(target, arm9tdmi, chain_pos, variant);
-
-	arm9tdmi->arch_info = arm926ejs;
-	arm926ejs->common_magic = ARM926EJS_COMMON_MAGIC;
-	
-	arm7_9->post_debug_entry = arm926ejs_post_debug_entry;
-	arm7_9->pre_restore_context = arm926ejs_pre_restore_context;
-	
-	arm926ejs->read_cp15 = arm926ejs_cp15_read;
-	arm926ejs->write_cp15 = arm926ejs_cp15_write;
-	arm926ejs->armv4_5_mmu.armv4_5_cache.ctype = -1;
-	arm926ejs->armv4_5_mmu.get_ttb = arm926ejs_get_ttb;
-	arm926ejs->armv4_5_mmu.read_memory = arm7_9_read_memory;
-	arm926ejs->armv4_5_mmu.write_memory = arm7_9_write_memory;
-	arm926ejs->armv4_5_mmu.disable_mmu_caches = arm926ejs_disable_mmu_caches;
-	arm926ejs->armv4_5_mmu.enable_mmu_caches = arm926ejs_enable_mmu_caches;
-	arm926ejs->armv4_5_mmu.has_tiny_pages = 1;
-	arm926ejs->armv4_5_mmu.mmu_enabled = 0;
-	
-	arm7_9->examine_debug_reason = arm926ejs_examine_debug_reason;
-	
-	/* The ARM926EJ-S implements the ARMv5TE architecture which
-	 * has the BKPT instruction, so we don't have to use a watchpoint comparator
-	 */
-	arm7_9->arm_bkpt = ARMV5_BKPT(0x0);
-	arm7_9->thumb_bkpt = ARMV5_T_BKPT(0x0) & 0xffff;
-	
-	arm7_9->sw_bkpts_use_wp = 0;
-	arm7_9->sw_bkpts_enabled = 1;
-	
-	return ERROR_OK;
-}
-
-int arm926ejs_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)
-{
-	int chain_pos;
-	char *variant = NULL;
-	arm926ejs_common_t *arm926ejs = malloc(sizeof(arm926ejs_common_t));
-	
-	if (argc < 4)
-	{
-		ERROR("'target arm926ejs' requires at least one additional argument");
-		exit(-1);
-	}
-	
-	chain_pos = strtoul(args[3], NULL, 0);
-	
-	if (argc >= 5)
-		variant = args[4];
-	
-	DEBUG("chain_pos: %i, variant: %s", chain_pos, variant);
-	
-	arm926ejs_init_arch_info(target, arm926ejs, chain_pos, variant);
-
-	return ERROR_OK;
-}
-
-int arm926ejs_register_commands(struct command_context_s *cmd_ctx)
-{
-	int retval;
-	command_t *arm926ejs_cmd;
-	
-		
-	retval = arm9tdmi_register_commands(cmd_ctx);
-	
-	arm926ejs_cmd = register_command(cmd_ctx, NULL, "arm926ejs", NULL, COMMAND_ANY, "arm926ejs specific commands");
-
-	register_command(cmd_ctx, arm926ejs_cmd, "cp15", arm926ejs_handle_cp15_command, COMMAND_EXEC, "display/modify cp15 register <opcode_1> <opcode_2> <CRn> <CRm> [value]");
-	
-	register_command(cmd_ctx, arm926ejs_cmd, "cache_info", arm926ejs_handle_cache_info_command, COMMAND_EXEC, "display information about target caches");
-	register_command(cmd_ctx, arm926ejs_cmd, "virt2phys", arm926ejs_handle_virt2phys_command, COMMAND_EXEC, "translate va to pa <va>");
-
-	register_command(cmd_ctx, arm926ejs_cmd, "mdw_phys", arm926ejs_handle_md_phys_command, COMMAND_EXEC, "display memory words <physical addr> [count]");
-	register_command(cmd_ctx, arm926ejs_cmd, "mdh_phys", arm926ejs_handle_md_phys_command, COMMAND_EXEC, "display memory half-words <physical addr> [count]");
-	register_command(cmd_ctx, arm926ejs_cmd, "mdb_phys", arm926ejs_handle_md_phys_command, COMMAND_EXEC, "display memory bytes <physical addr> [count]");
-
-	register_command(cmd_ctx, arm926ejs_cmd, "mww_phys", arm926ejs_handle_mw_phys_command, COMMAND_EXEC, "write memory word <physical addr> <value>");
-	register_command(cmd_ctx, arm926ejs_cmd, "mwh_phys", arm926ejs_handle_mw_phys_command, COMMAND_EXEC, "write memory half-word <physical addr> <value>");
-	register_command(cmd_ctx, arm926ejs_cmd, "mwb_phys", arm926ejs_handle_mw_phys_command, COMMAND_EXEC, "write memory byte <physical addr> <value>");
-
-	return ERROR_OK;
-}
-
-int arm926ejs_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	int retval;
-	target_t *target = get_current_target(cmd_ctx);
-	armv4_5_common_t *armv4_5;
-	arm7_9_common_t *arm7_9;
-	arm9tdmi_common_t *arm9tdmi;
-	arm926ejs_common_t *arm926ejs;
-	int opcode_1;
-	int opcode_2;
-	int CRn;
-	int CRm;
-
-	if ((argc < 4) || (argc > 5))
-	{
-		command_print(cmd_ctx, "usage: arm926ejs cp15 <opcode_1> <opcode_2> <CRn> <CRm> [value]");
-		return ERROR_OK;
-	}
-	
-	opcode_1 = strtoul(args[0], NULL, 0);
-	opcode_2 = strtoul(args[1], NULL, 0);
-	CRn = strtoul(args[2], NULL, 0);
-	CRm = strtoul(args[3], NULL, 0);
-
-	if (arm926ejs_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm926ejs) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "current target isn't an ARM926EJ-S 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 == 4)
-	{
-		u32 value;
-		if ((retval = arm926ejs->read_cp15(target, opcode_1, opcode_2, CRn, CRm, &value)) != ERROR_OK)
-		{
-			command_print(cmd_ctx, "couldn't access register");
-			return ERROR_OK;
-		}
-		jtag_execute_queue();
-		
-		command_print(cmd_ctx, "%i %i %i %i: %8.8x", opcode_1, opcode_2, CRn, CRm, value);
-	}
-	else
-	{
-		u32 value = strtoul(args[4], NULL, 0);
-		if ((retval = arm926ejs->write_cp15(target, opcode_1, opcode_2, CRn, CRm, value)) != ERROR_OK)
-		{
-			command_print(cmd_ctx, "couldn't access register");
-			return ERROR_OK;
-		}
-		command_print(cmd_ctx, "%i %i %i %i: %8.8x", opcode_1, opcode_2, CRn, CRm, value);
-	}
-
-	return ERROR_OK;
-}
-
-int arm926ejs_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;
-	arm7_9_common_t *arm7_9;
-	arm9tdmi_common_t *arm9tdmi;
-	arm926ejs_common_t *arm926ejs;
-	
-	if (arm926ejs_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm926ejs) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "current target isn't an ARM926EJ-S target");
-		return ERROR_OK;
-	}
-	
-	return armv4_5_handle_cache_info_command(cmd_ctx, &arm926ejs->armv4_5_mmu.armv4_5_cache);
-}
-
-int arm926ejs_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;
-	arm7_9_common_t *arm7_9;
-	arm9tdmi_common_t *arm9tdmi;
-	arm926ejs_common_t *arm926ejs;
-	arm_jtag_t *jtag_info;
-
-	if (arm926ejs_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm926ejs) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "current target isn't an ARM926EJ-S target");
-		return ERROR_OK;
-	}
-	
-	jtag_info = &arm7_9->jtag_info;
-	
-	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, &arm926ejs->armv4_5_mmu);
-}
-
-int arm926ejs_handle_md_phys_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;
-	arm7_9_common_t *arm7_9;
-	arm9tdmi_common_t *arm9tdmi;
-	arm926ejs_common_t *arm926ejs;
-	arm_jtag_t *jtag_info;
-
-	if (arm926ejs_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm926ejs) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "current target isn't an ARM926EJ-S target");
-		return ERROR_OK;
-	}
-	
-	jtag_info = &arm7_9->jtag_info;
-	
-	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_md_phys_command(cmd_ctx, cmd, args, argc, target, &arm926ejs->armv4_5_mmu);
-}
-
-int arm926ejs_handle_mw_phys_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;
-	arm7_9_common_t *arm7_9;
-	arm9tdmi_common_t *arm9tdmi;
-	arm926ejs_common_t *arm926ejs;
-	arm_jtag_t *jtag_info;
-
-	if (arm926ejs_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm926ejs) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "current target isn't an ARM926EJ-S target");
-		return ERROR_OK;
-	}
-	
-	jtag_info = &arm7_9->jtag_info;
-	
-	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_mw_phys_command(cmd_ctx, cmd, args, argc, target, &arm926ejs->armv4_5_mmu);
-}
-static int arm926ejs_virt2phys(struct target_s *target, u32 virtual, u32 *physical)
-{
-	int retval;
-	int type;
-	u32 cb;
-	int domain;
-	u32 ap;
-	
-	armv4_5_common_t *armv4_5;
-	arm7_9_common_t *arm7_9;
-	arm9tdmi_common_t *arm9tdmi;
-	arm926ejs_common_t *arm926ejs;
-	retval= arm926ejs_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm926ejs);
-	if (retval != ERROR_OK)
-	{
-		return retval;
-	}
-	u32 ret = armv4_5_mmu_translate_va(target, &arm926ejs->armv4_5_mmu, virtual, &type, &cb, &domain, &ap);
-	if (type == -1)
-	{
-		return ret;
-	}
-	*physical = ret;
-	return ERROR_OK;
-}
-
-static int arm926ejs_mmu(struct target_s *target, int *enabled)
-{
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm926ejs_common_t *arm926ejs = armv4_5->arch_info;
-	
-	if (target->state != TARGET_HALTED)
-	{
-		ERROR("Target not halted");
-		return ERROR_TARGET_INVALID;
-	}
-	*enabled = arm926ejs->armv4_5_mmu.mmu_enabled;
-	return ERROR_OK;
-}
+/***************************************************************************
+ *   Copyright (C) 2007 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 "arm926ejs.h"
+#include "jtag.h"
+#include "log.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#if 1
+#define _DEBUG_INSTRUCTION_EXECUTION_
+#endif
+
+/* cli handling */
+int arm926ejs_register_commands(struct command_context_s *cmd_ctx);
+
+int arm926ejs_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int arm926ejs_handle_cp15i_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int arm926ejs_handle_virt2phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int arm926ejs_handle_cache_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int arm926ejs_handle_md_phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int arm926ejs_handle_mw_phys_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+int arm926ejs_handle_read_cache_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int arm926ejs_handle_read_mmu_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+/* forward declarations */
+int arm926ejs_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
+int arm926ejs_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
+int arm926ejs_quit();
+int arm926ejs_arch_state(struct target_s *target);
+int arm926ejs_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
+int arm926ejs_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer);
+int arm926ejs_soft_reset_halt(struct target_s *target);
+static int arm926ejs_virt2phys(struct target_s *target, u32 virtual, u32 *physical);
+static int arm926ejs_mmu(struct target_s *target, int *enabled);
+
+target_type_t arm926ejs_target =
+{
+	.name = "arm926ejs",
+
+	.poll = arm7_9_poll,
+	.arch_state = arm926ejs_arch_state,
+
+	.target_request_data = arm7_9_target_request_data,
+
+	.halt = arm7_9_halt,
+	.resume = arm7_9_resume,
+	.step = arm7_9_step,
+
+	.assert_reset = arm7_9_assert_reset,
+	.deassert_reset = arm7_9_deassert_reset,
+	.soft_reset_halt = arm926ejs_soft_reset_halt,
+	.prepare_reset_halt = arm7_9_prepare_reset_halt,
+	
+	.get_gdb_reg_list = armv4_5_get_gdb_reg_list,
+
+	.read_memory = arm7_9_read_memory,
+	.write_memory = arm926ejs_write_memory,
+	.bulk_write_memory = arm7_9_bulk_write_memory,
+	.checksum_memory = arm7_9_checksum_memory,
+	
+	.run_algorithm = armv4_5_run_algorithm,
+
+	.add_breakpoint = arm7_9_add_breakpoint,
+	.remove_breakpoint = arm7_9_remove_breakpoint,
+	.add_watchpoint = arm7_9_add_watchpoint,
+	.remove_watchpoint = arm7_9_remove_watchpoint,
+
+	.register_commands = arm926ejs_register_commands,
+	.target_command = arm926ejs_target_command,
+	.init_target = arm926ejs_init_target,
+	.quit = arm926ejs_quit,
+	.virt2phys = arm926ejs_virt2phys,
+	.mmu = arm926ejs_mmu
+};
+
+
+int arm926ejs_catch_broken_irscan(u8 *captured, void *priv, scan_field_t *field)
+{
+	/* The ARM926EJ-S' instruction register is 4 bits wide */
+	u8 t = *captured & 0xf;
+	u8 t2 = *field->in_check_value & 0xf;
+	if (t == t2)
+	{
+		return ERROR_OK;
+	}
+	else if ((t == 0x0f) || (t == 0x00))
+	{
+		DEBUG("caught ARM926EJ-S invalid Capture-IR result after CP15 access");
+		return ERROR_OK;
+	}
+	return ERROR_JTAG_QUEUE_FAILED;;
+}
+
+#define ARM926EJS_CP15_ADDR(opcode_1, opcode_2, CRn, CRm) ((opcode_1 << 11) | (opcode_2 << 8) | (CRn << 4) | (CRm << 0))
+
+int arm926ejs_cp15_read(target_t *target, u32 op1, u32 op2, u32 CRn, u32 CRm, u32 *value)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+	u32 address = ARM926EJS_CP15_ADDR(op1, op2, CRn, CRm);
+	scan_field_t fields[4];
+	u8 address_buf[2];
+	u8 nr_w_buf = 0;
+	u8 access = 1;
+	
+	buf_set_u32(address_buf, 0, 14, address);
+	
+	jtag_add_end_state(TAP_RTI);
+	arm_jtag_scann(jtag_info, 0xf);
+	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+
+	fields[0].device = jtag_info->chain_pos;
+	fields[0].num_bits = 32;
+	fields[0].out_value = NULL;
+	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 = jtag_info->chain_pos;
+	fields[1].num_bits = 1;
+	fields[1].out_value = &access;
+	fields[1].out_mask = NULL;
+	fields[1].in_value = &access;
+	fields[1].in_check_value = NULL;
+	fields[1].in_check_mask = NULL;
+	fields[1].in_handler = NULL;
+	fields[1].in_handler_priv = NULL;
+
+	fields[2].device = jtag_info->chain_pos;
+	fields[2].num_bits = 14;
+	fields[2].out_value = address_buf;
+	fields[2].out_mask = NULL;
+	fields[2].in_value = NULL;
+	fields[2].in_check_value = NULL;
+	fields[2].in_check_mask = NULL;
+	fields[2].in_handler = NULL;
+	fields[2].in_handler_priv = NULL;
+
+	fields[3].device = jtag_info->chain_pos;
+	fields[3].num_bits = 1;
+	fields[3].out_value = &nr_w_buf;
+	fields[3].out_mask = NULL;
+	fields[3].in_value = NULL;
+	fields[3].in_check_value = NULL;
+	fields[3].in_check_mask = NULL;
+	fields[3].in_handler = NULL;
+	fields[3].in_handler_priv = NULL;
+	
+	jtag_add_dr_scan(4, fields, -1);
+
+	fields[0].in_handler_priv = value;
+	fields[0].in_handler = arm_jtag_buf_to_u32;
+	
+	do
+	{
+		/* rescan with NOP, to wait for the access to complete */
+		access = 0;
+		nr_w_buf = 0;
+		jtag_add_dr_scan(4, fields, -1);
+		jtag_execute_queue();
+	} while (buf_get_u32(&access, 0, 1) != 1);
+
+#ifdef _DEBUG_INSTRUCTION_EXECUTION_
+	DEBUG("addr: 0x%x value: %8.8x", address, *value);
+#endif
+	
+	arm_jtag_set_instr(jtag_info, 0xc, &arm926ejs_catch_broken_irscan);
+
+	return ERROR_OK;
+}
+
+int arm926ejs_cp15_write(target_t *target, u32 op1, u32 op2, u32 CRn, u32 CRm, u32 value)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+	u32 address = ARM926EJS_CP15_ADDR(op1, op2, CRn, CRm);
+	scan_field_t fields[4];
+	u8 value_buf[4];
+	u8 address_buf[2];
+	u8 nr_w_buf = 1;
+	u8 access = 1;
+	
+	buf_set_u32(address_buf, 0, 14, address);
+	buf_set_u32(value_buf, 0, 32, value);
+	
+	jtag_add_end_state(TAP_RTI);
+	arm_jtag_scann(jtag_info, 0xf);
+	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+
+	fields[0].device = jtag_info->chain_pos;
+	fields[0].num_bits = 32;
+	fields[0].out_value = value_buf;
+	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 = jtag_info->chain_pos;
+	fields[1].num_bits = 1;
+	fields[1].out_value = &access;
+	fields[1].out_mask = NULL;
+	fields[1].in_value = &access;
+	fields[1].in_check_value = NULL;
+	fields[1].in_check_mask = NULL;
+	fields[1].in_handler = NULL;
+	fields[1].in_handler_priv = NULL;
+
+	fields[2].device = jtag_info->chain_pos;
+	fields[2].num_bits = 14;
+	fields[2].out_value = address_buf;
+	fields[2].out_mask = NULL;
+	fields[2].in_value = NULL;
+	fields[2].in_check_value = NULL;
+	fields[2].in_check_mask = NULL;
+	fields[2].in_handler = NULL;
+	fields[2].in_handler_priv = NULL;
+
+	fields[3].device = jtag_info->chain_pos;
+	fields[3].num_bits = 1;
+	fields[3].out_value = &nr_w_buf;
+	fields[3].out_mask = NULL;
+	fields[3].in_value = NULL;
+	fields[3].in_check_value = NULL;
+	fields[3].in_check_mask = NULL;
+	fields[3].in_handler = NULL;
+	fields[3].in_handler_priv = NULL;
+	
+	jtag_add_dr_scan(4, fields, -1);
+
+	do
+	{
+		/* rescan with NOP, to wait for the access to complete */
+		access = 0;
+		nr_w_buf = 0;
+		jtag_add_dr_scan(4, fields, -1);
+		jtag_execute_queue();
+	} while (buf_get_u32(&access, 0, 1) != 1);
+
+#ifdef _DEBUG_INSTRUCTION_EXECUTION_
+	DEBUG("addr: 0x%x value: %8.8x", address, value);
+#endif
+
+	arm_jtag_set_instr(jtag_info, 0xf, &arm926ejs_catch_broken_irscan);
+
+	return ERROR_OK;
+}
+
+int arm926ejs_examine_debug_reason(target_t *target)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
+	int debug_reason;
+	int retval;
+
+	embeddedice_read_reg(dbg_stat);
+	if ((retval = jtag_execute_queue()) != ERROR_OK)
+		return retval;
+	
+	debug_reason = buf_get_u32(dbg_stat->value, 6, 4);
+	
+	switch (debug_reason)
+	{
+		case 1:
+			DEBUG("breakpoint from EICE unit 0");
+			target->debug_reason = DBG_REASON_BREAKPOINT;
+			break;
+		case 2:
+			DEBUG("breakpoint from EICE unit 1");
+			target->debug_reason = DBG_REASON_BREAKPOINT;
+			break;
+		case 3:
+			DEBUG("soft breakpoint (BKPT instruction)");
+			target->debug_reason = DBG_REASON_BREAKPOINT;
+			break;
+		case 4:
+			DEBUG("vector catch breakpoint");
+			target->debug_reason = DBG_REASON_BREAKPOINT;
+			break;
+		case 5:
+			DEBUG("external breakpoint");
+			target->debug_reason = DBG_REASON_BREAKPOINT;
+			break;
+		case 6:
+			DEBUG("watchpoint from EICE unit 0");
+			target->debug_reason = DBG_REASON_WATCHPOINT;
+			break;
+		case 7:
+			DEBUG("watchpoint from EICE unit 1");
+			target->debug_reason = DBG_REASON_WATCHPOINT;
+			break;
+		case 8:
+			DEBUG("external watchpoint");
+			target->debug_reason = DBG_REASON_WATCHPOINT;
+			break;
+		case 9:
+			DEBUG("internal debug request");
+			target->debug_reason = DBG_REASON_DBGRQ;
+			break;
+		case 10:
+			DEBUG("external debug request");
+			target->debug_reason = DBG_REASON_DBGRQ;
+			break;
+		case 11:
+			ERROR("BUG: debug re-entry from system speed access shouldn't be handled here");
+			break;
+		default:
+			ERROR("BUG: unknown debug reason: 0x%x", debug_reason);
+			target->debug_reason = DBG_REASON_DBGRQ;
+	}
+	
+	return ERROR_OK;
+}
+
+u32 arm926ejs_get_ttb(target_t *target)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
+	arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;
+	int retval;
+	u32 ttb = 0x0;
+
+	if ((retval = arm926ejs->read_cp15(target, 0, 0, 2, 0, &ttb)) != ERROR_OK)
+		return retval;
+
+	return ttb;
+}
+
+void arm926ejs_disable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_cache)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
+	arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;
+	u32 cp15_control;
+
+	/* read cp15 control register */
+	arm926ejs->read_cp15(target, 0, 0, 1, 0, &cp15_control);
+	jtag_execute_queue();
+	
+	if (mmu)
+	{
+		/* invalidate TLB */
+		arm926ejs->write_cp15(target, 0, 0, 8, 7, 0x0);
+		
+		cp15_control &= ~0x1U;
+	}
+	
+	if (d_u_cache)
+	{
+		u32 debug_override;
+		/* read-modify-write CP15 debug override register 
+		 * to enable "test and clean all" */
+		arm926ejs->read_cp15(target, 0, 0, 15, 0, &debug_override);
+		debug_override |= 0x80000;
+		arm926ejs->write_cp15(target, 0, 0, 15, 0, debug_override);
+		
+		/* clean and invalidate DCache */
+		arm926ejs->write_cp15(target, 0, 0, 7, 5, 0x0);
+
+		/* write CP15 debug override register 
+		 * to disable "test and clean all" */
+		debug_override &= ~0x80000;
+		arm926ejs->write_cp15(target, 0, 0, 15, 0, debug_override);
+		
+		cp15_control &= ~0x4U;
+	}
+	
+	if (i_cache)
+	{
+		/* invalidate ICache */
+		arm926ejs->write_cp15(target, 0, 0, 7, 5, 0x0);
+		
+		cp15_control &= ~0x1000U;
+	}
+	
+	arm926ejs->write_cp15(target, 0, 0, 1, 0, cp15_control);
+}
+
+void arm926ejs_enable_mmu_caches(target_t *target, int mmu, int d_u_cache, int i_cache)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
+	arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;
+	u32 cp15_control;
+
+	/* read cp15 control register */
+	arm926ejs->read_cp15(target, 0, 0, 1, 0, &cp15_control);
+	jtag_execute_queue();
+		
+	if (mmu)
+		cp15_control |= 0x1U;
+	
+	if (d_u_cache)
+		cp15_control |= 0x4U;
+	
+	if (i_cache)
+		cp15_control |= 0x1000U;
+	
+	arm926ejs->write_cp15(target, 0, 0, 1, 0, cp15_control);
+}
+
+void arm926ejs_post_debug_entry(target_t *target)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
+	arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;
+
+	/* examine cp15 control reg */
+	arm926ejs->read_cp15(target, 0, 0, 1, 0, &arm926ejs->cp15_control_reg);
+	jtag_execute_queue();
+	DEBUG("cp15_control_reg: %8.8x", arm926ejs->cp15_control_reg);
+
+	if (arm926ejs->armv4_5_mmu.armv4_5_cache.ctype == -1)
+	{
+		u32 cache_type_reg;
+		/* identify caches */
+		arm926ejs->read_cp15(target, 0, 1, 0, 0, &cache_type_reg);
+		jtag_execute_queue();
+		armv4_5_identify_cache(cache_type_reg, &arm926ejs->armv4_5_mmu.armv4_5_cache);
+	}
+
+	arm926ejs->armv4_5_mmu.mmu_enabled = (arm926ejs->cp15_control_reg & 0x1U) ? 1 : 0;
+	arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = (arm926ejs->cp15_control_reg & 0x4U) ? 1 : 0;
+	arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled = (arm926ejs->cp15_control_reg & 0x1000U) ? 1 : 0;
+
+	/* save i/d fault status and address register */
+	arm926ejs->read_cp15(target, 0, 0, 5, 0, &arm926ejs->d_fsr);
+	arm926ejs->read_cp15(target, 0, 1, 5, 0, &arm926ejs->i_fsr);
+	arm926ejs->read_cp15(target, 0, 0, 6, 0, &arm926ejs->d_far);
+	
+	DEBUG("D FSR: 0x%8.8x, D FAR: 0x%8.8x, I FSR: 0x%8.8x",
+		arm926ejs->d_fsr, arm926ejs->d_far, arm926ejs->i_fsr);  
+
+
+	u32 cache_dbg_ctrl;
+	
+	/* read-modify-write CP15 cache debug control register 
+	 * to disable I/D-cache linefills and force WT */
+	arm926ejs->read_cp15(target, 7, 0, 15, 0, &cache_dbg_ctrl);
+	cache_dbg_ctrl |= 0x7;
+	arm926ejs->write_cp15(target, 7, 0, 15, 0, cache_dbg_ctrl);
+}
+
+void arm926ejs_pre_restore_context(target_t *target)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
+	arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;
+
+	/* restore i/d fault status and address register */
+	arm926ejs->write_cp15(target, 0, 0, 5, 0, arm926ejs->d_fsr);
+	arm926ejs->write_cp15(target, 0, 1, 5, 0, arm926ejs->i_fsr);
+	arm926ejs->write_cp15(target, 0, 0, 6, 0, arm926ejs->d_far);
+	
+	u32 cache_dbg_ctrl;
+	
+	/* read-modify-write CP15 cache debug control register 
+	 * to reenable I/D-cache linefills and disable WT */
+	arm926ejs->read_cp15(target, 7, 0, 15, 0, &cache_dbg_ctrl);
+	cache_dbg_ctrl &= ~0x7;
+	arm926ejs->write_cp15(target, 7, 0, 15, 0, cache_dbg_ctrl);
+}
+
+int arm926ejs_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, arm7_9_common_t **arm7_9_p, arm9tdmi_common_t **arm9tdmi_p, arm926ejs_common_t **arm926ejs_p)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9;
+	arm9tdmi_common_t *arm9tdmi;
+	arm926ejs_common_t *arm926ejs;
+	
+	if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
+	{
+		return -1;
+	}
+	
+	arm7_9 = armv4_5->arch_info;
+	if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC)
+	{
+		return -1;
+	}
+	
+	arm9tdmi = arm7_9->arch_info;
+	if (arm9tdmi->common_magic != ARM9TDMI_COMMON_MAGIC)
+	{
+		return -1;
+	}
+	
+	arm926ejs = arm9tdmi->arch_info;
+	if (arm926ejs->common_magic != ARM926EJS_COMMON_MAGIC)
+	{
+		return -1;
+	}
+	
+	*armv4_5_p = armv4_5;
+	*arm7_9_p = arm7_9;
+	*arm9tdmi_p = arm9tdmi;
+	*arm926ejs_p = arm926ejs;
+	
+	return ERROR_OK;
+}
+
+int arm926ejs_arch_state(struct target_s *target)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
+	arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;
+	
+	char *state[] = 
+	{
+		"disabled", "enabled"
+	};
+	
+	if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
+	{
+		ERROR("BUG: called for a non-ARMv4/5 target");
+		exit(-1);
+	}
+	
+	USER(
+			"target halted in %s state due to %s, current mode: %s\n"
+			"cpsr: 0x%8.8x pc: 0x%8.8x\n"
+			"MMU: %s, D-Cache: %s, I-Cache: %s",
+			 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[arm926ejs->armv4_5_mmu.mmu_enabled],
+			 state[arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled], 
+			 state[arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled]);
+	
+	return ERROR_OK;
+}
+
+int arm926ejs_soft_reset_halt(struct target_s *target)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
+	arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;
+	reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
+	
+	if (target->state == TARGET_RUNNING)
+	{
+		target->type->halt(target);
+	}
+	
+	while (buf_get_u32(dbg_stat->value, EICE_DBG_STATUS_DBGACK, 1) == 0)
+	{
+		embeddedice_read_reg(dbg_stat);
+		jtag_execute_queue();
+	}
+	
+	target->state = TARGET_HALTED;
+	
+	/* SVC, ARM state, IRQ and FIQ disabled */
+	buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 8, 0xd3);
+	armv4_5->core_cache->reg_list[ARMV4_5_CPSR].dirty = 1;
+	armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1;
+	
+	/* start fetching from 0x0 */
+	buf_set_u32(armv4_5->core_cache->reg_list[15].value, 0, 32, 0x0);
+	armv4_5->core_cache->reg_list[15].dirty = 1;
+	armv4_5->core_cache->reg_list[15].valid = 1;
+	
+	armv4_5->core_mode = ARMV4_5_MODE_SVC;
+	armv4_5->core_state = ARMV4_5_STATE_ARM;
+	
+	arm926ejs_disable_mmu_caches(target, 1, 1, 1);
+	arm926ejs->armv4_5_mmu.mmu_enabled = 0;
+	arm926ejs->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled = 0;
+	arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled = 0;
+
+	target_call_event_callbacks(target, TARGET_EVENT_HALTED);
+	
+	return ERROR_OK;
+}
+
+int arm926ejs_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer)
+{
+	int retval;
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm9tdmi_common_t *arm9tdmi = arm7_9->arch_info;
+	arm926ejs_common_t *arm926ejs = arm9tdmi->arch_info;
+	
+	if ((retval = arm7_9_write_memory(target, address, size, count, buffer)) != ERROR_OK)
+		return retval;
+
+	/* If ICache is enabled, we have to invalidate affected ICache lines
+	 * the DCache is forced to write-through, so we don't have to clean it here
+	 */
+	if (arm926ejs->armv4_5_mmu.armv4_5_cache.i_cache_enabled)
+	{
+		if (count <= 1)
+		{
+			/* invalidate ICache single entry with MVA */
+			arm926ejs->write_cp15(target, 0, 1, 7, 5, address);
+		}
+		else
+		{
+			/* invalidate ICache */
+			arm926ejs->write_cp15(target, 0, 0, 7, 5, address);
+		}
+	}
+
+	return retval;
+}
+
+int arm926ejs_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
+{
+	arm9tdmi_init_target(cmd_ctx, target);
+		
+	return ERROR_OK;
+	
+}
+
+int arm926ejs_quit()
+{
+	
+	return ERROR_OK;
+}
+
+int arm926ejs_init_arch_info(target_t *target, arm926ejs_common_t *arm926ejs, int chain_pos, char *variant)
+{
+	arm9tdmi_common_t *arm9tdmi = &arm926ejs->arm9tdmi_common;
+	arm7_9_common_t *arm7_9 = &arm9tdmi->arm7_9_common;
+	
+	/* initialize arm9tdmi specific info (including arm7_9 and armv4_5)
+	 */
+	arm9tdmi_init_arch_info(target, arm9tdmi, chain_pos, variant);
+
+	arm9tdmi->arch_info = arm926ejs;
+	arm926ejs->common_magic = ARM926EJS_COMMON_MAGIC;
+	
+	arm7_9->post_debug_entry = arm926ejs_post_debug_entry;
+	arm7_9->pre_restore_context = arm926ejs_pre_restore_context;
+	
+	arm926ejs->read_cp15 = arm926ejs_cp15_read;
+	arm926ejs->write_cp15 = arm926ejs_cp15_write;
+	arm926ejs->armv4_5_mmu.armv4_5_cache.ctype = -1;
+	arm926ejs->armv4_5_mmu.get_ttb = arm926ejs_get_ttb;
+	arm926ejs->armv4_5_mmu.read_memory = arm7_9_read_memory;
+	arm926ejs->armv4_5_mmu.write_memory = arm7_9_write_memory;
+	arm926ejs->armv4_5_mmu.disable_mmu_caches = arm926ejs_disable_mmu_caches;
+	arm926ejs->armv4_5_mmu.enable_mmu_caches = arm926ejs_enable_mmu_caches;
+	arm926ejs->armv4_5_mmu.has_tiny_pages = 1;
+	arm926ejs->armv4_5_mmu.mmu_enabled = 0;
+	
+	arm7_9->examine_debug_reason = arm926ejs_examine_debug_reason;
+	
+	/* The ARM926EJ-S implements the ARMv5TE architecture which
+	 * has the BKPT instruction, so we don't have to use a watchpoint comparator
+	 */
+	arm7_9->arm_bkpt = ARMV5_BKPT(0x0);
+	arm7_9->thumb_bkpt = ARMV5_T_BKPT(0x0) & 0xffff;
+	
+	arm7_9->sw_bkpts_use_wp = 0;
+	arm7_9->sw_bkpts_enabled = 1;
+	
+	return ERROR_OK;
+}
+
+int arm926ejs_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)
+{
+	int chain_pos;
+	char *variant = NULL;
+	arm926ejs_common_t *arm926ejs = malloc(sizeof(arm926ejs_common_t));
+	
+	if (argc < 4)
+	{
+		ERROR("'target arm926ejs' requires at least one additional argument");
+		exit(-1);
+	}
+	
+	chain_pos = strtoul(args[3], NULL, 0);
+	
+	if (argc >= 5)
+		variant = args[4];
+	
+	DEBUG("chain_pos: %i, variant: %s", chain_pos, variant);
+	
+	arm926ejs_init_arch_info(target, arm926ejs, chain_pos, variant);
+
+	return ERROR_OK;
+}
+
+int arm926ejs_register_commands(struct command_context_s *cmd_ctx)
+{
+	int retval;
+	command_t *arm926ejs_cmd;
+	
+		
+	retval = arm9tdmi_register_commands(cmd_ctx);
+	
+	arm926ejs_cmd = register_command(cmd_ctx, NULL, "arm926ejs", NULL, COMMAND_ANY, "arm926ejs specific commands");
+
+	register_command(cmd_ctx, arm926ejs_cmd, "cp15", arm926ejs_handle_cp15_command, COMMAND_EXEC, "display/modify cp15 register <opcode_1> <opcode_2> <CRn> <CRm> [value]");
+	
+	register_command(cmd_ctx, arm926ejs_cmd, "cache_info", arm926ejs_handle_cache_info_command, COMMAND_EXEC, "display information about target caches");
+	register_command(cmd_ctx, arm926ejs_cmd, "virt2phys", arm926ejs_handle_virt2phys_command, COMMAND_EXEC, "translate va to pa <va>");
+
+	register_command(cmd_ctx, arm926ejs_cmd, "mdw_phys", arm926ejs_handle_md_phys_command, COMMAND_EXEC, "display memory words <physical addr> [count]");
+	register_command(cmd_ctx, arm926ejs_cmd, "mdh_phys", arm926ejs_handle_md_phys_command, COMMAND_EXEC, "display memory half-words <physical addr> [count]");
+	register_command(cmd_ctx, arm926ejs_cmd, "mdb_phys", arm926ejs_handle_md_phys_command, COMMAND_EXEC, "display memory bytes <physical addr> [count]");
+
+	register_command(cmd_ctx, arm926ejs_cmd, "mww_phys", arm926ejs_handle_mw_phys_command, COMMAND_EXEC, "write memory word <physical addr> <value>");
+	register_command(cmd_ctx, arm926ejs_cmd, "mwh_phys", arm926ejs_handle_mw_phys_command, COMMAND_EXEC, "write memory half-word <physical addr> <value>");
+	register_command(cmd_ctx, arm926ejs_cmd, "mwb_phys", arm926ejs_handle_mw_phys_command, COMMAND_EXEC, "write memory byte <physical addr> <value>");
+
+	return ERROR_OK;
+}
+
+int arm926ejs_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	int retval;
+	target_t *target = get_current_target(cmd_ctx);
+	armv4_5_common_t *armv4_5;
+	arm7_9_common_t *arm7_9;
+	arm9tdmi_common_t *arm9tdmi;
+	arm926ejs_common_t *arm926ejs;
+	int opcode_1;
+	int opcode_2;
+	int CRn;
+	int CRm;
+
+	if ((argc < 4) || (argc > 5))
+	{
+		command_print(cmd_ctx, "usage: arm926ejs cp15 <opcode_1> <opcode_2> <CRn> <CRm> [value]");
+		return ERROR_OK;
+	}
+	
+	opcode_1 = strtoul(args[0], NULL, 0);
+	opcode_2 = strtoul(args[1], NULL, 0);
+	CRn = strtoul(args[2], NULL, 0);
+	CRm = strtoul(args[3], NULL, 0);
+
+	if (arm926ejs_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm926ejs) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "current target isn't an ARM926EJ-S 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 == 4)
+	{
+		u32 value;
+		if ((retval = arm926ejs->read_cp15(target, opcode_1, opcode_2, CRn, CRm, &value)) != ERROR_OK)
+		{
+			command_print(cmd_ctx, "couldn't access register");
+			return ERROR_OK;
+		}
+		jtag_execute_queue();
+		
+		command_print(cmd_ctx, "%i %i %i %i: %8.8x", opcode_1, opcode_2, CRn, CRm, value);
+	}
+	else
+	{
+		u32 value = strtoul(args[4], NULL, 0);
+		if ((retval = arm926ejs->write_cp15(target, opcode_1, opcode_2, CRn, CRm, value)) != ERROR_OK)
+		{
+			command_print(cmd_ctx, "couldn't access register");
+			return ERROR_OK;
+		}
+		command_print(cmd_ctx, "%i %i %i %i: %8.8x", opcode_1, opcode_2, CRn, CRm, value);
+	}
+
+	return ERROR_OK;
+}
+
+int arm926ejs_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;
+	arm7_9_common_t *arm7_9;
+	arm9tdmi_common_t *arm9tdmi;
+	arm926ejs_common_t *arm926ejs;
+	
+	if (arm926ejs_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm926ejs) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "current target isn't an ARM926EJ-S target");
+		return ERROR_OK;
+	}
+	
+	return armv4_5_handle_cache_info_command(cmd_ctx, &arm926ejs->armv4_5_mmu.armv4_5_cache);
+}
+
+int arm926ejs_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;
+	arm7_9_common_t *arm7_9;
+	arm9tdmi_common_t *arm9tdmi;
+	arm926ejs_common_t *arm926ejs;
+	arm_jtag_t *jtag_info;
+
+	if (arm926ejs_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm926ejs) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "current target isn't an ARM926EJ-S target");
+		return ERROR_OK;
+	}
+	
+	jtag_info = &arm7_9->jtag_info;
+	
+	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, &arm926ejs->armv4_5_mmu);
+}
+
+int arm926ejs_handle_md_phys_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;
+	arm7_9_common_t *arm7_9;
+	arm9tdmi_common_t *arm9tdmi;
+	arm926ejs_common_t *arm926ejs;
+	arm_jtag_t *jtag_info;
+
+	if (arm926ejs_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm926ejs) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "current target isn't an ARM926EJ-S target");
+		return ERROR_OK;
+	}
+	
+	jtag_info = &arm7_9->jtag_info;
+	
+	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_md_phys_command(cmd_ctx, cmd, args, argc, target, &arm926ejs->armv4_5_mmu);
+}
+
+int arm926ejs_handle_mw_phys_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;
+	arm7_9_common_t *arm7_9;
+	arm9tdmi_common_t *arm9tdmi;
+	arm926ejs_common_t *arm926ejs;
+	arm_jtag_t *jtag_info;
+
+	if (arm926ejs_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm926ejs) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "current target isn't an ARM926EJ-S target");
+		return ERROR_OK;
+	}
+	
+	jtag_info = &arm7_9->jtag_info;
+	
+	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_mw_phys_command(cmd_ctx, cmd, args, argc, target, &arm926ejs->armv4_5_mmu);
+}
+static int arm926ejs_virt2phys(struct target_s *target, u32 virtual, u32 *physical)
+{
+	int retval;
+	int type;
+	u32 cb;
+	int domain;
+	u32 ap;
+	
+	armv4_5_common_t *armv4_5;
+	arm7_9_common_t *arm7_9;
+	arm9tdmi_common_t *arm9tdmi;
+	arm926ejs_common_t *arm926ejs;
+	retval= arm926ejs_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm926ejs);
+	if (retval != ERROR_OK)
+	{
+		return retval;
+	}
+	u32 ret = armv4_5_mmu_translate_va(target, &arm926ejs->armv4_5_mmu, virtual, &type, &cb, &domain, &ap);
+	if (type == -1)
+	{
+		return ret;
+	}
+	*physical = ret;
+	return ERROR_OK;
+}
+
+static int arm926ejs_mmu(struct target_s *target, int *enabled)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm926ejs_common_t *arm926ejs = armv4_5->arch_info;
+	
+	if (target->state != TARGET_HALTED)
+	{
+		ERROR("Target not halted");
+		return ERROR_TARGET_INVALID;
+	}
+	*enabled = arm926ejs->armv4_5_mmu.mmu_enabled;
+	return ERROR_OK;
+}
diff --git a/src/target/arm966e.c b/src/target/arm966e.c
index 2885e3dfb5d549b9b3303f3ffa2936dd3ba093fc..1ea2ce77cc97ecca94bc6a2939ac228856f3391c 100644
--- a/src/target/arm966e.c
+++ b/src/target/arm966e.c
@@ -1,364 +1,364 @@
-/***************************************************************************
- *   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.             *
- ***************************************************************************/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "arm966e.h"
-
-#include "arm7_9_common.h"
-#include "register.h"
-#include "target.h"
-#include "armv4_5.h"
-#include "embeddedice.h"
-#include "log.h"
-#include "jtag.h"
-#include "arm_jtag.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#if 0
-#define _DEBUG_INSTRUCTION_EXECUTION_
-#endif
-
-/* cli handling */
-int arm966e_register_commands(struct command_context_s *cmd_ctx);
-
-/* forward declarations */
-int arm966e_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
-int arm966e_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
-int arm966e_quit(void);
-
-target_type_t arm966e_target =
-{
-	.name = "arm966e",
-
-	.poll = arm7_9_poll,
-	.arch_state = armv4_5_arch_state,
-
-	.target_request_data = arm7_9_target_request_data,
-
-	.halt = arm7_9_halt,
-	.resume = arm7_9_resume,
-	.step = arm7_9_step,
-
-	.assert_reset = arm7_9_assert_reset,
-	.deassert_reset = arm7_9_deassert_reset,
-	.soft_reset_halt = arm7_9_soft_reset_halt,
-	.prepare_reset_halt = arm7_9_prepare_reset_halt,
-
-	.get_gdb_reg_list = armv4_5_get_gdb_reg_list,
-
-	.read_memory = arm7_9_read_memory,
-	.write_memory = arm7_9_write_memory,
-	.bulk_write_memory = arm7_9_bulk_write_memory,
-	.checksum_memory = arm7_9_checksum_memory,
-	
-	.run_algorithm = armv4_5_run_algorithm,
-	
-	.add_breakpoint = arm7_9_add_breakpoint,
-	.remove_breakpoint = arm7_9_remove_breakpoint,
-	.add_watchpoint = arm7_9_add_watchpoint,
-	.remove_watchpoint = arm7_9_remove_watchpoint,
-
-	.register_commands = arm966e_register_commands,
-	.target_command = arm966e_target_command,
-	.init_target = arm966e_init_target,
-	.quit = arm966e_quit,
-};
-
-int arm966e_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
-{
-	arm9tdmi_init_target(cmd_ctx, target);
-		
-	return ERROR_OK;
-}
-
-int arm966e_quit(void)
-{
-	
-	return ERROR_OK;
-}
-
-int arm966e_init_arch_info(target_t *target, arm966e_common_t *arm966e, int chain_pos, char *variant)
-{
-	arm9tdmi_common_t *arm9tdmi = &arm966e->arm9tdmi_common;
-	arm7_9_common_t *arm7_9 = &arm9tdmi->arm7_9_common;
-	
-	arm9tdmi_init_arch_info(target, arm9tdmi, chain_pos, variant);
-
-	arm9tdmi->arch_info = arm966e;
-	arm966e->common_magic = ARM966E_COMMON_MAGIC;
-	
-	/* The ARM966E-S implements the ARMv5TE architecture which
-	 * has the BKPT instruction, so we don't have to use a watchpoint comparator
-	 */
-	arm7_9->arm_bkpt = ARMV5_BKPT(0x0);
-	arm7_9->thumb_bkpt = ARMV5_T_BKPT(0x0) & 0xffff;
-	
-	arm7_9->sw_bkpts_use_wp = 0;
-	arm7_9->sw_bkpts_enabled = 1;
-	
-	return ERROR_OK;
-}
-
-int arm966e_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)
-{
-	int chain_pos;
-	char *variant = NULL;
-	arm966e_common_t *arm966e = malloc(sizeof(arm966e_common_t));
-	
-	if (argc < 4)
-	{
-		ERROR("'target arm966e' requires at least one additional argument");
-		exit(-1);
-	}
-	
-	chain_pos = strtoul(args[3], NULL, 0);
-	
-	if (argc >= 5)
-		variant = args[4];
-	
-	DEBUG("chain_pos: %i, variant: %s", chain_pos, variant);
-	
-	arm966e_init_arch_info(target, arm966e, chain_pos, variant);
-
-	return ERROR_OK;
-}
-
-int arm966e_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, arm7_9_common_t **arm7_9_p, arm9tdmi_common_t **arm9tdmi_p, arm966e_common_t **arm966e_p)
-{
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9;
-	arm9tdmi_common_t *arm9tdmi;
-	arm966e_common_t *arm966e;
-	
-	if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
-	{
-		return -1;
-	}
-	
-	arm7_9 = armv4_5->arch_info;
-	if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC)
-	{
-		return -1;
-	}
-	
-	arm9tdmi = arm7_9->arch_info;
-	if (arm9tdmi->common_magic != ARM9TDMI_COMMON_MAGIC)
-	{
-		return -1;
-	}
-	
-	arm966e = arm9tdmi->arch_info;
-	if (arm966e->common_magic != ARM966E_COMMON_MAGIC)
-	{
-		return -1;
-	}
-	
-	*armv4_5_p = armv4_5;
-	*arm7_9_p = arm7_9;
-	*arm9tdmi_p = arm9tdmi;
-	*arm966e_p = arm966e;
-	
-	return ERROR_OK;
-}
-
-int arm966e_read_cp15(target_t *target, int reg_addr, u32 *value)
-{
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-	scan_field_t fields[3];
-	u8 reg_addr_buf = reg_addr & 0x3f;
-	u8 nr_w_buf = 0;
-	
-	jtag_add_end_state(TAP_RTI);
-	arm_jtag_scann(jtag_info, 0xf);
-	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
-
-	fields[0].device = jtag_info->chain_pos;
-	fields[0].num_bits = 32;
-	fields[0].out_value = NULL;
-	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 = jtag_info->chain_pos;
-	fields[1].num_bits = 6;
-	fields[1].out_value = &reg_addr_buf;
-	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;
-
-	fields[2].device = jtag_info->chain_pos;
-	fields[2].num_bits = 1;
-	fields[2].out_value = &nr_w_buf;
-	fields[2].out_mask = NULL;
-	fields[2].in_value = NULL;
-	fields[2].in_check_value = NULL;
-	fields[2].in_check_mask = NULL;
-	fields[2].in_handler = NULL;
-	fields[2].in_handler_priv = NULL;
-	
-	jtag_add_dr_scan(3, fields, -1, NULL);
-
-	fields[0].in_handler_priv = value;
-	fields[0].in_handler = arm_jtag_buf_to_u32;
-
-	jtag_add_dr_scan(3, fields, -1, NULL);
-
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_
-	jtag_execute_queue();
-	DEBUG("addr: 0x%x value: %8.8x", reg_addr, *value);
-#endif
-
-	return ERROR_OK;
-}
-
-int arm966e_write_cp15(target_t *target, int reg_addr, u32 value)
-{
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-	scan_field_t fields[3];
-	u8 reg_addr_buf = reg_addr & 0x3f;
-	u8 nr_w_buf = 1;
-	u8 value_buf[4];
-	
-	buf_set_u32(value_buf, 0, 32, value);
-	
-	jtag_add_end_state(TAP_RTI);
-	arm_jtag_scann(jtag_info, 0xf);
-	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
-
-	fields[0].device = jtag_info->chain_pos;
-	fields[0].num_bits = 32;
-	fields[0].out_value = value_buf;
-	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 = jtag_info->chain_pos;
-	fields[1].num_bits = 6;
-	fields[1].out_value = &reg_addr_buf;
-	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;
-
-	fields[2].device = jtag_info->chain_pos;
-	fields[2].num_bits = 1;
-	fields[2].out_value = &nr_w_buf;
-	fields[2].out_mask = NULL;
-	fields[2].in_value = NULL;
-	fields[2].in_check_value = NULL;
-	fields[2].in_check_mask = NULL;
-	fields[2].in_handler = NULL;
-	fields[2].in_handler_priv = NULL;
-	
-	jtag_add_dr_scan(3, fields, -1, NULL);
-
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_
-	DEBUG("addr: 0x%x value: %8.8x", reg_addr, value);
-#endif
-
-	return ERROR_OK;
-}
-
-int arm966e_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	int retval;
-	target_t *target = get_current_target(cmd_ctx);
-	armv4_5_common_t *armv4_5;
-	arm7_9_common_t *arm7_9;
-	arm9tdmi_common_t *arm9tdmi;
-	arm966e_common_t *arm966e;
-	arm_jtag_t *jtag_info;
-
-	if (arm966e_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm966e) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "current target isn't an ARM966e target");
-		return ERROR_OK;
-	}
-	
-	jtag_info = &arm7_9->jtag_info;
-	
-	if (target->state != TARGET_HALTED)
-	{
-		command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
-		return ERROR_OK;
-	}
-
-	/* one or more argument, access a single register (write if second argument is given */
-	if (argc >= 1)
-	{
-		int address = strtoul(args[0], NULL, 0);
-
-		if (argc == 1)
-		{
-			u32 value;
-			if ((retval = arm966e_read_cp15(target, address, &value)) != ERROR_OK)
-			{
-				command_print(cmd_ctx, "couldn't access reg %i", address);
-				return ERROR_OK;
-			}
-			jtag_execute_queue();
-			
-			command_print(cmd_ctx, "%i: %8.8x", address, value);
-		}
-		else if (argc == 2)
-		{
-			u32 value = strtoul(args[1], NULL, 0);
-			if ((retval = arm966e_write_cp15(target, address, value)) != ERROR_OK)
-			{
-				command_print(cmd_ctx, "couldn't access reg %i", address);
-				return ERROR_OK;
-			}
-			command_print(cmd_ctx, "%i: %8.8x", address, value);
-		}
-	}
-
-	return ERROR_OK;
-}
-
-int arm966e_register_commands(struct command_context_s *cmd_ctx)
-{
-	int retval;
-	command_t *arm966e_cmd;
-	
-	retval = arm9tdmi_register_commands(cmd_ctx);
-	arm966e_cmd = register_command(cmd_ctx, NULL, "arm966e", NULL, COMMAND_ANY, "arm966e specific commands");
-	register_command(cmd_ctx, arm966e_cmd, "cp15", arm966e_handle_cp15_command, COMMAND_EXEC, "display/modify cp15 register <num> [value]");
-	
-	return ERROR_OK;
-}
+/***************************************************************************
+ *   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.             *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "arm966e.h"
+
+#include "arm7_9_common.h"
+#include "register.h"
+#include "target.h"
+#include "armv4_5.h"
+#include "embeddedice.h"
+#include "log.h"
+#include "jtag.h"
+#include "arm_jtag.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#if 0
+#define _DEBUG_INSTRUCTION_EXECUTION_
+#endif
+
+/* cli handling */
+int arm966e_register_commands(struct command_context_s *cmd_ctx);
+
+/* forward declarations */
+int arm966e_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
+int arm966e_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
+int arm966e_quit(void);
+
+target_type_t arm966e_target =
+{
+	.name = "arm966e",
+
+	.poll = arm7_9_poll,
+	.arch_state = armv4_5_arch_state,
+
+	.target_request_data = arm7_9_target_request_data,
+
+	.halt = arm7_9_halt,
+	.resume = arm7_9_resume,
+	.step = arm7_9_step,
+
+	.assert_reset = arm7_9_assert_reset,
+	.deassert_reset = arm7_9_deassert_reset,
+	.soft_reset_halt = arm7_9_soft_reset_halt,
+	.prepare_reset_halt = arm7_9_prepare_reset_halt,
+
+	.get_gdb_reg_list = armv4_5_get_gdb_reg_list,
+
+	.read_memory = arm7_9_read_memory,
+	.write_memory = arm7_9_write_memory,
+	.bulk_write_memory = arm7_9_bulk_write_memory,
+	.checksum_memory = arm7_9_checksum_memory,
+	
+	.run_algorithm = armv4_5_run_algorithm,
+	
+	.add_breakpoint = arm7_9_add_breakpoint,
+	.remove_breakpoint = arm7_9_remove_breakpoint,
+	.add_watchpoint = arm7_9_add_watchpoint,
+	.remove_watchpoint = arm7_9_remove_watchpoint,
+
+	.register_commands = arm966e_register_commands,
+	.target_command = arm966e_target_command,
+	.init_target = arm966e_init_target,
+	.quit = arm966e_quit,
+};
+
+int arm966e_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
+{
+	arm9tdmi_init_target(cmd_ctx, target);
+		
+	return ERROR_OK;
+}
+
+int arm966e_quit(void)
+{
+	
+	return ERROR_OK;
+}
+
+int arm966e_init_arch_info(target_t *target, arm966e_common_t *arm966e, int chain_pos, char *variant)
+{
+	arm9tdmi_common_t *arm9tdmi = &arm966e->arm9tdmi_common;
+	arm7_9_common_t *arm7_9 = &arm9tdmi->arm7_9_common;
+	
+	arm9tdmi_init_arch_info(target, arm9tdmi, chain_pos, variant);
+
+	arm9tdmi->arch_info = arm966e;
+	arm966e->common_magic = ARM966E_COMMON_MAGIC;
+	
+	/* The ARM966E-S implements the ARMv5TE architecture which
+	 * has the BKPT instruction, so we don't have to use a watchpoint comparator
+	 */
+	arm7_9->arm_bkpt = ARMV5_BKPT(0x0);
+	arm7_9->thumb_bkpt = ARMV5_T_BKPT(0x0) & 0xffff;
+	
+	arm7_9->sw_bkpts_use_wp = 0;
+	arm7_9->sw_bkpts_enabled = 1;
+	
+	return ERROR_OK;
+}
+
+int arm966e_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)
+{
+	int chain_pos;
+	char *variant = NULL;
+	arm966e_common_t *arm966e = malloc(sizeof(arm966e_common_t));
+	
+	if (argc < 4)
+	{
+		ERROR("'target arm966e' requires at least one additional argument");
+		exit(-1);
+	}
+	
+	chain_pos = strtoul(args[3], NULL, 0);
+	
+	if (argc >= 5)
+		variant = args[4];
+	
+	DEBUG("chain_pos: %i, variant: %s", chain_pos, variant);
+	
+	arm966e_init_arch_info(target, arm966e, chain_pos, variant);
+
+	return ERROR_OK;
+}
+
+int arm966e_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, arm7_9_common_t **arm7_9_p, arm9tdmi_common_t **arm9tdmi_p, arm966e_common_t **arm966e_p)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9;
+	arm9tdmi_common_t *arm9tdmi;
+	arm966e_common_t *arm966e;
+	
+	if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
+	{
+		return -1;
+	}
+	
+	arm7_9 = armv4_5->arch_info;
+	if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC)
+	{
+		return -1;
+	}
+	
+	arm9tdmi = arm7_9->arch_info;
+	if (arm9tdmi->common_magic != ARM9TDMI_COMMON_MAGIC)
+	{
+		return -1;
+	}
+	
+	arm966e = arm9tdmi->arch_info;
+	if (arm966e->common_magic != ARM966E_COMMON_MAGIC)
+	{
+		return -1;
+	}
+	
+	*armv4_5_p = armv4_5;
+	*arm7_9_p = arm7_9;
+	*arm9tdmi_p = arm9tdmi;
+	*arm966e_p = arm966e;
+	
+	return ERROR_OK;
+}
+
+int arm966e_read_cp15(target_t *target, int reg_addr, u32 *value)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+	scan_field_t fields[3];
+	u8 reg_addr_buf = reg_addr & 0x3f;
+	u8 nr_w_buf = 0;
+	
+	jtag_add_end_state(TAP_RTI);
+	arm_jtag_scann(jtag_info, 0xf);
+	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+
+	fields[0].device = jtag_info->chain_pos;
+	fields[0].num_bits = 32;
+	fields[0].out_value = NULL;
+	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 = jtag_info->chain_pos;
+	fields[1].num_bits = 6;
+	fields[1].out_value = &reg_addr_buf;
+	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;
+
+	fields[2].device = jtag_info->chain_pos;
+	fields[2].num_bits = 1;
+	fields[2].out_value = &nr_w_buf;
+	fields[2].out_mask = NULL;
+	fields[2].in_value = NULL;
+	fields[2].in_check_value = NULL;
+	fields[2].in_check_mask = NULL;
+	fields[2].in_handler = NULL;
+	fields[2].in_handler_priv = NULL;
+	
+	jtag_add_dr_scan(3, fields, -1);
+
+	fields[0].in_handler_priv = value;
+	fields[0].in_handler = arm_jtag_buf_to_u32;
+
+	jtag_add_dr_scan(3, fields, -1);
+
+#ifdef _DEBUG_INSTRUCTION_EXECUTION_
+	jtag_execute_queue();
+	DEBUG("addr: 0x%x value: %8.8x", reg_addr, *value);
+#endif
+
+	return ERROR_OK;
+}
+
+int arm966e_write_cp15(target_t *target, int reg_addr, u32 value)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+	scan_field_t fields[3];
+	u8 reg_addr_buf = reg_addr & 0x3f;
+	u8 nr_w_buf = 1;
+	u8 value_buf[4];
+	
+	buf_set_u32(value_buf, 0, 32, value);
+	
+	jtag_add_end_state(TAP_RTI);
+	arm_jtag_scann(jtag_info, 0xf);
+	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+
+	fields[0].device = jtag_info->chain_pos;
+	fields[0].num_bits = 32;
+	fields[0].out_value = value_buf;
+	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 = jtag_info->chain_pos;
+	fields[1].num_bits = 6;
+	fields[1].out_value = &reg_addr_buf;
+	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;
+
+	fields[2].device = jtag_info->chain_pos;
+	fields[2].num_bits = 1;
+	fields[2].out_value = &nr_w_buf;
+	fields[2].out_mask = NULL;
+	fields[2].in_value = NULL;
+	fields[2].in_check_value = NULL;
+	fields[2].in_check_mask = NULL;
+	fields[2].in_handler = NULL;
+	fields[2].in_handler_priv = NULL;
+	
+	jtag_add_dr_scan(3, fields, -1);
+
+#ifdef _DEBUG_INSTRUCTION_EXECUTION_
+	DEBUG("addr: 0x%x value: %8.8x", reg_addr, value);
+#endif
+
+	return ERROR_OK;
+}
+
+int arm966e_handle_cp15_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	int retval;
+	target_t *target = get_current_target(cmd_ctx);
+	armv4_5_common_t *armv4_5;
+	arm7_9_common_t *arm7_9;
+	arm9tdmi_common_t *arm9tdmi;
+	arm966e_common_t *arm966e;
+	arm_jtag_t *jtag_info;
+
+	if (arm966e_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi, &arm966e) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "current target isn't an ARM966e target");
+		return ERROR_OK;
+	}
+	
+	jtag_info = &arm7_9->jtag_info;
+	
+	if (target->state != TARGET_HALTED)
+	{
+		command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+		return ERROR_OK;
+	}
+
+	/* one or more argument, access a single register (write if second argument is given */
+	if (argc >= 1)
+	{
+		int address = strtoul(args[0], NULL, 0);
+
+		if (argc == 1)
+		{
+			u32 value;
+			if ((retval = arm966e_read_cp15(target, address, &value)) != ERROR_OK)
+			{
+				command_print(cmd_ctx, "couldn't access reg %i", address);
+				return ERROR_OK;
+			}
+			jtag_execute_queue();
+			
+			command_print(cmd_ctx, "%i: %8.8x", address, value);
+		}
+		else if (argc == 2)
+		{
+			u32 value = strtoul(args[1], NULL, 0);
+			if ((retval = arm966e_write_cp15(target, address, value)) != ERROR_OK)
+			{
+				command_print(cmd_ctx, "couldn't access reg %i", address);
+				return ERROR_OK;
+			}
+			command_print(cmd_ctx, "%i: %8.8x", address, value);
+		}
+	}
+
+	return ERROR_OK;
+}
+
+int arm966e_register_commands(struct command_context_s *cmd_ctx)
+{
+	int retval;
+	command_t *arm966e_cmd;
+	
+	retval = arm9tdmi_register_commands(cmd_ctx);
+	arm966e_cmd = register_command(cmd_ctx, NULL, "arm966e", NULL, COMMAND_ANY, "arm966e specific commands");
+	register_command(cmd_ctx, arm966e_cmd, "cp15", arm966e_handle_cp15_command, COMMAND_EXEC, "display/modify cp15 register <num> [value]");
+	
+	return ERROR_OK;
+}
diff --git a/src/target/arm9tdmi.c b/src/target/arm9tdmi.c
index 5f808cdbb3f5a4e09121e04f0b3c8789c37fb744..7170693dc4b99eafc24fbb81cd1ebc971abc4e61 100644
--- a/src/target/arm9tdmi.c
+++ b/src/target/arm9tdmi.c
@@ -1,1105 +1,1105 @@
-/***************************************************************************
- *   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.             *
- ***************************************************************************/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "arm9tdmi.h"
-
-#include "arm7_9_common.h"
-#include "register.h"
-#include "target.h"
-#include "armv4_5.h"
-#include "embeddedice.h"
-#include "etm.h"
-#include "etb.h"
-#include "log.h"
-#include "jtag.h"
-#include "arm_jtag.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#if 0
-#define _DEBUG_INSTRUCTION_EXECUTION_
-#endif
-
-/* cli handling */
-int arm9tdmi_register_commands(struct command_context_s *cmd_ctx);
-int handle_arm9tdmi_catch_vectors_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-
-/* forward declarations */
-int arm9tdmi_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
-int arm9tdmi_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
-int arm9tdmi_quit();
-		
-target_type_t arm9tdmi_target =
-{
-	.name = "arm9tdmi",
-
-	.poll = arm7_9_poll,
-	.arch_state = armv4_5_arch_state,
-
-	.target_request_data = arm7_9_target_request_data,
-
-	.halt = arm7_9_halt,
-	.resume = arm7_9_resume,
-	.step = arm7_9_step,
-
-	.assert_reset = arm7_9_assert_reset,
-	.deassert_reset = arm7_9_deassert_reset,
-	.soft_reset_halt = arm7_9_soft_reset_halt,
-	.prepare_reset_halt = arm7_9_prepare_reset_halt,
-
-	.get_gdb_reg_list = armv4_5_get_gdb_reg_list,
-
-	.read_memory = arm7_9_read_memory,
-	.write_memory = arm7_9_write_memory,
-	.bulk_write_memory = arm7_9_bulk_write_memory,
-	.checksum_memory = arm7_9_checksum_memory,
-	
-	.run_algorithm = armv4_5_run_algorithm,
-	
-	.add_breakpoint = arm7_9_add_breakpoint,
-	.remove_breakpoint = arm7_9_remove_breakpoint,
-	.add_watchpoint = arm7_9_add_watchpoint,
-	.remove_watchpoint = arm7_9_remove_watchpoint,
-
-	.register_commands = arm9tdmi_register_commands,
-	.target_command = arm9tdmi_target_command,
-	.init_target = arm9tdmi_init_target,
-	.quit = arm9tdmi_quit
-};
-
-arm9tdmi_vector_t arm9tdmi_vectors[] =
-{
-	{"reset", ARM9TDMI_RESET_VECTOR},
-	{"undef", ARM9TDMI_UNDEF_VECTOR},
-	{"swi", ARM9TDMI_SWI_VECTOR},
-	{"pabt", ARM9TDMI_PABT_VECTOR},
-	{"dabt", ARM9TDMI_DABT_VECTOR},
-	{"reserved", ARM9TDMI_RESERVED_VECTOR},
-	{"irq", ARM9TDMI_IRQ_VECTOR},
-	{"fiq", ARM9TDMI_FIQ_VECTOR},
-	{0, 0},
-};
-
-int arm9tdmi_examine_debug_reason(target_t *target)
-{
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	
-	/* only check the debug reason if we don't know it already */
-	if ((target->debug_reason != DBG_REASON_DBGRQ)
-			&& (target->debug_reason != DBG_REASON_SINGLESTEP))
-	{
-		scan_field_t fields[3];
-		u8 databus[4];
-		u8 instructionbus[4];
-		u8 debug_reason;
-
-		jtag_add_end_state(TAP_PD);
-
-		fields[0].device = arm7_9->jtag_info.chain_pos;
-		fields[0].num_bits = 32;
-		fields[0].out_value = NULL;
-		fields[0].out_mask = NULL;
-		fields[0].in_value = databus;
-		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 = arm7_9->jtag_info.chain_pos;
-		fields[1].num_bits = 3;
-		fields[1].out_value = NULL;
-		fields[1].out_mask = NULL;
-		fields[1].in_value = &debug_reason;
-		fields[1].in_check_value = NULL;
-		fields[1].in_check_mask = NULL;
-		fields[1].in_handler = NULL;
-		fields[1].in_handler_priv = NULL;
-		
-		fields[2].device = arm7_9->jtag_info.chain_pos;
-		fields[2].num_bits = 32;
-		fields[2].out_value = NULL;
-		fields[2].out_mask = NULL;
-		fields[2].in_value = instructionbus;
-		fields[2].in_check_value = NULL;
-		fields[2].in_check_mask = NULL;
-		fields[2].in_handler = NULL;
-		fields[2].in_handler_priv = NULL;
-		
-		arm_jtag_scann(&arm7_9->jtag_info, 0x1);
-		arm_jtag_set_instr(&arm7_9->jtag_info, arm7_9->jtag_info.intest_instr, NULL);
-
-		jtag_add_dr_scan(3, fields, TAP_PD, NULL);
-		jtag_execute_queue();
-		
-		fields[0].in_value = NULL;
-		fields[0].out_value = databus;
-		fields[1].in_value = NULL;
-		fields[1].out_value = &debug_reason;
-		fields[2].in_value = NULL;
-		fields[2].out_value = instructionbus;
-		
-		jtag_add_dr_scan(3, fields, TAP_PD, NULL);
-
-		if (debug_reason & 0x4)
-			if (debug_reason & 0x2)
-				target->debug_reason = DBG_REASON_WPTANDBKPT;
-		else
-			target->debug_reason = DBG_REASON_WATCHPOINT;
-		else
-			target->debug_reason = DBG_REASON_BREAKPOINT;
-	}
-
-	return ERROR_OK;
-}
-
-/* put an instruction in the ARM9TDMI pipeline or write the data bus, and optionally read data */
-int arm9tdmi_clock_out(arm_jtag_t *jtag_info, u32 instr, u32 out, u32 *in, int sysspeed)
-{
-	scan_field_t fields[3];
-	u8 out_buf[4];
-	u8 instr_buf[4];
-	u8 sysspeed_buf = 0x0;
-	
-	/* prepare buffer */
-	buf_set_u32(out_buf, 0, 32, out);
-	
-	buf_set_u32(instr_buf, 0, 32, flip_u32(instr, 32));
-	
-	if (sysspeed)
-		buf_set_u32(&sysspeed_buf, 2, 1, 1);
-	
-	jtag_add_end_state(TAP_PD);
-	arm_jtag_scann(jtag_info, 0x1);
-	
-	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
-		
-	fields[0].device = jtag_info->chain_pos;
-	fields[0].num_bits = 32;
-	fields[0].out_value = out_buf;
-	fields[0].out_mask = NULL;
-	fields[0].in_value = NULL;
-	if (in)
-	{
-		fields[0].in_handler = arm_jtag_buf_to_u32;
-		fields[0].in_handler_priv = in;
-	}
-	else
-	{
-		fields[0].in_handler = NULL;
-		fields[0].in_handler_priv = NULL;
-	}
-	fields[0].in_check_value = NULL;
-	fields[0].in_check_mask = NULL;
-	
-	fields[1].device = jtag_info->chain_pos;
-	fields[1].num_bits = 3;
-	fields[1].out_value = &sysspeed_buf;
-	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;
-		
-	fields[2].device = jtag_info->chain_pos;
-	fields[2].num_bits = 32;
-	fields[2].out_value = instr_buf;
-	fields[2].out_mask = NULL;
-	fields[2].in_value = NULL;
-	fields[2].in_check_value = NULL;
-	fields[2].in_check_mask = NULL;
-	fields[2].in_handler = NULL;
-	fields[2].in_handler_priv = NULL;
-
-	jtag_add_dr_scan(3, fields, -1, NULL);
-
-	jtag_add_runtest(0, -1);
-	
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_
-	{
-		jtag_execute_queue();
-		
-		if (in)
-		{
-			DEBUG("instr: 0x%8.8x, out: 0x%8.8x, in: 0x%8.8x", instr, out, *in);
-		}
-		else
-			DEBUG("instr: 0x%8.8x, out: 0x%8.8x", instr, out);
-	}
-#endif
-
-	return ERROR_OK;
-}
-
-/* just read data (instruction and data-out = don't care) */
-int arm9tdmi_clock_data_in(arm_jtag_t *jtag_info, u32 *in)
-{
-	scan_field_t fields[3];
-
-	jtag_add_end_state(TAP_PD);
-	arm_jtag_scann(jtag_info, 0x1);
-	
-	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
-		
-	fields[0].device = jtag_info->chain_pos;
-	fields[0].num_bits = 32;
-	fields[0].out_value = NULL;
-	fields[0].out_mask = NULL;
-	fields[0].in_value = NULL;
-	fields[0].in_handler = arm_jtag_buf_to_u32;
-	fields[0].in_handler_priv = in;
-	fields[0].in_check_value = NULL;
-	fields[0].in_check_mask = NULL;
-	
-	fields[1].device = jtag_info->chain_pos;
-	fields[1].num_bits = 3;
-	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 = jtag_info->chain_pos;
-	fields[2].num_bits = 32;
-	fields[2].out_value = NULL;
-	fields[2].out_mask = NULL;
-	fields[2].in_value = NULL;
-	fields[2].in_check_value = NULL;
-	fields[2].in_check_mask = NULL;
-	fields[2].in_handler = NULL;
-	fields[2].in_handler_priv = NULL;
-	
-	jtag_add_dr_scan(3, fields, -1, NULL);
-
-	jtag_add_runtest(0, -1);
-	
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_
-	{
-		jtag_execute_queue();
-			
-		if (in)
-		{
-			DEBUG("in: 0x%8.8x", *in);
-		}
-		else
-		{
-			ERROR("BUG: called with in == NULL");
-		}
-	}
-#endif
-
-	return ERROR_OK;
-}
-
-/* clock the target, and read the databus
- * the *in pointer points to a buffer where elements of 'size' bytes
- * are stored in big (be==1) or little (be==0) endianness
- */
-int arm9tdmi_clock_data_in_endianness(arm_jtag_t *jtag_info, void *in, int size, int be)
-{
-	scan_field_t fields[3];
-	
-	jtag_add_end_state(TAP_PD);
-	arm_jtag_scann(jtag_info, 0x1);
-	
-	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
-		
-	fields[0].device = jtag_info->chain_pos;
-	fields[0].num_bits = 32;
-	fields[0].out_value = NULL;
-	fields[0].out_mask = NULL;
-	fields[0].in_value = NULL;
-	switch (size)
-	{
-		case 4:
-			fields[0].in_handler = (be) ? arm_jtag_buf_to_be32 : arm_jtag_buf_to_le32;
-			break;
-		case 2:
-			fields[0].in_handler = (be) ? arm_jtag_buf_to_be16 : arm_jtag_buf_to_le16;
-			break;
-		case 1:
-			fields[0].in_handler = arm_jtag_buf_to_8;
-			break;
-	}
-	fields[0].in_handler_priv = in;
-	fields[0].in_check_value = NULL;
-	fields[0].in_check_mask = NULL;
-	
-	fields[1].device = jtag_info->chain_pos;
-	fields[1].num_bits = 3;
-	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 = jtag_info->chain_pos;
-	fields[2].num_bits = 32;
-	fields[2].out_value = NULL;
-	fields[2].out_mask = NULL;
-	fields[2].in_value = NULL;
-	fields[2].in_check_value = NULL;
-	fields[2].in_check_mask = NULL;
-	fields[2].in_handler = NULL;
-	fields[2].in_handler_priv = NULL;
-	
-	jtag_add_dr_scan(3, fields, -1, NULL);
-
-	jtag_add_runtest(0, -1);
-	
-#ifdef _DEBUG_INSTRUCTION_EXECUTION_
-	{
-		jtag_execute_queue();
-			
-		if (in)
-		{
-			DEBUG("in: 0x%8.8x", *in);
-		}
-		else
-		{
-			ERROR("BUG: called with in == NULL");
-		}
-	}
-#endif
-
-	return ERROR_OK;
-}
-
-void arm9tdmi_change_to_arm(target_t *target, u32 *r0, u32 *pc)
-{
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-	
-	/* save r0 before using it and put system in ARM state 
-	 * to allow common handling of ARM and THUMB debugging */
-	
-	/* fetch STR r0, [r0] */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
-	/* STR r0, [r0] in Memory */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, r0, 0);
-
-	/* MOV r0, r15 fetched, STR in Decode */	
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_MOV(0, 15), 0, NULL, 0);
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
-	/* nothing fetched, STR r0, [r0] in Memory */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, pc, 0);
-
-	/* use pc-relative LDR to clear r0[1:0] (for switch to ARM mode) */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), 0, NULL, 0);
-	/* LDR in Decode */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
-	/* LDR in Execute */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
-	/* LDR in Memory (to account for interlock) */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
-
-	/* fetch BX */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_BX(0), 0, NULL, 0);
-	/* NOP fetched, BX in Decode, MOV in Execute */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
-	/* NOP fetched, BX in Execute (1) */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
-	
-	jtag_execute_queue();
-	
-	/* fix program counter:
-	 * MOV r0, r15 was the 5th instruction (+8)
-	 * reading PC in Thumb state gives address of instruction + 4
-	 */
-	*pc -= 0xc;
-}
-
-void arm9tdmi_read_core_regs(target_t *target, u32 mask, u32* core_regs[16])
-{
-	int i;
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-		
-	/* STMIA r0-15, [r0] at debug speed
-	 * register values will start to appear on 4th DCLK
-	 */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
-
-	/* fetch NOP, STM in DECODE stage */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-	/* fetch NOP, STM in EXECUTE stage (1st cycle) */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-
-	for (i = 0; i <= 15; i++)
-	{
-		if (mask & (1 << i))
-			/* nothing fetched, STM in MEMORY (i'th cycle) */
-			arm9tdmi_clock_data_in(jtag_info, core_regs[i]);
-	}
-
-}
-
-void arm9tdmi_read_core_regs_target_buffer(target_t *target, u32 mask, void* buffer, int size)
-{
-	int i;
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-	int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0;
-	u32 *buf_u32 = buffer;
-	u16 *buf_u16 = buffer;
-	u8 *buf_u8 = buffer;
-	
-	/* STMIA r0-15, [r0] at debug speed
-	 * register values will start to appear on 4th DCLK
-	 */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
-
-	/* fetch NOP, STM in DECODE stage */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-	/* fetch NOP, STM in EXECUTE stage (1st cycle) */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-
-	for (i = 0; i <= 15; i++)
-	{
-		if (mask & (1 << i))
-			/* nothing fetched, STM in MEMORY (i'th cycle) */
-			switch (size)
-			{
-				case 4:
-					arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
-					break;
-				case 2:
-					arm9tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);
-					break;
-				case 1:
-					arm9tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);
-					break;
-			}
-	}
-
-}
-
-void arm9tdmi_read_xpsr(target_t *target, u32 *xpsr, int spsr)
-{
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-		
-	/* MRS r0, cpsr */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), 0, NULL, 0);
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-
-	/* STR r0, [r15] */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_STR(0, 15), 0, NULL, 0);
-	/* fetch NOP, STR in DECODE stage */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-	/* fetch NOP, STR in EXECUTE stage (1st cycle) */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-	/* nothing fetched, STR in MEMORY */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, xpsr, 0);
-
-}
-
-void arm9tdmi_write_xpsr(target_t *target, u32 xpsr, int spsr)
-{
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-		
-	DEBUG("xpsr: %8.8x, spsr: %i", xpsr, spsr);
-
-	/* MSR1 fetched */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), 0, NULL, 0);
-	/* MSR2 fetched, MSR1 in DECODE */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), 0, NULL, 0);
-	/* MSR3 fetched, MSR1 in EXECUTE (1), MSR2 in DECODE */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), 0, NULL, 0);
-	/* nothing fetched, MSR1 in EXECUTE (2) */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-	/* nothing fetched, MSR1 in EXECUTE (3) */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-	/* MSR4 fetched, MSR2 in EXECUTE (1), MSR3 in DECODE */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), 0, NULL, 0);
-	/* nothing fetched, MSR2 in EXECUTE (2) */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-	/* nothing fetched, MSR2 in EXECUTE (3) */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-	/* NOP fetched, MSR3 in EXECUTE (1), MSR4 in DECODE */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-	/* nothing fetched, MSR3 in EXECUTE (2) */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-	/* nothing fetched, MSR3 in EXECUTE (3) */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-	/* NOP fetched, MSR4 in EXECUTE (1) */
-	/* last MSR writes flags, which takes only one cycle */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-}
-
-void arm9tdmi_write_xpsr_im8(target_t *target, u8 xpsr_im, int rot, int spsr)
-{
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-		
-	DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr);
-	
-	/* MSR fetched */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), 0, NULL, 0);
-	/* NOP fetched, MSR in DECODE */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-	/* NOP fetched, MSR in EXECUTE (1) */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-	
-	/* rot == 4 writes flags, which takes only one cycle */
-	if (rot != 4)
-	{
-		/* nothing fetched, MSR in EXECUTE (2) */
-		arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-		/* nothing fetched, MSR in EXECUTE (3) */
-		arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-	}
-}
-
-void arm9tdmi_write_core_regs(target_t *target, u32 mask, u32 core_regs[16])
-{
-	int i;
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-		
-	/* LDMIA r0-15, [r0] at debug speed
-	* register values will start to appear on 4th DCLK
-	*/
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
-
-	/* fetch NOP, LDM in DECODE stage */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-	/* fetch NOP, LDM in EXECUTE stage (1st cycle) */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-
-	for (i = 0; i <= 15; i++)
-	{
-		if (mask & (1 << i))
-			/* nothing fetched, LDM still in EXECUTE (1+i cycle) */
-			arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, core_regs[i], NULL, 0);
-	}
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-	
-}
-
-void arm9tdmi_load_word_regs(target_t *target, u32 mask)
-{
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-
-	/* put system-speed load-multiple into the pipeline */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 1), 0, NULL, 0);
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
-
-}
-
-void arm9tdmi_load_hword_reg(target_t *target, int num)
-{
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-	
-	/* put system-speed load half-word into the pipeline */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_LDRH_IP(num, 0), 0, NULL, 0);
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
-}
-
-void arm9tdmi_load_byte_reg(target_t *target, int num)
-{
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-
-	/* put system-speed load byte into the pipeline */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_LDRB_IP(num, 0), 0, NULL, 0);
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
-
-}
-
-void arm9tdmi_store_word_regs(target_t *target, u32 mask)
-{
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-
-	/* put system-speed store-multiple into the pipeline */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask, 0, 1), 0, NULL, 0);
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
-
-}
-
-void arm9tdmi_store_hword_reg(target_t *target, int num)
-{
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-
-	/* put system-speed store half-word into the pipeline */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_STRH_IP(num, 0), 0, NULL, 0);
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
-
-}
-
-void arm9tdmi_store_byte_reg(target_t *target, int num)
-{
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-
-	/* put system-speed store byte into the pipeline */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_STRB_IP(num, 0), 0, NULL, 0);
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
-
-}
-
-void arm9tdmi_write_pc(target_t *target, u32 pc)
-{
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-	
-	/* LDMIA r0-15, [r0] at debug speed
-	 * register values will start to appear on 4th DCLK
-	 */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x8000, 0, 0), 0, NULL, 0);
-
-	/* fetch NOP, LDM in DECODE stage */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-	/* fetch NOP, LDM in EXECUTE stage (1st cycle) */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-	/* nothing fetched, LDM in EXECUTE stage (2nd cycle) (output data) */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, pc, NULL, 0);
-	/* nothing fetched, LDM in EXECUTE stage (3rd cycle) */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-	/* fetch NOP, LDM in EXECUTE stage (4th cycle) */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-	/* fetch NOP, LDM in EXECUTE stage (5th cycle) */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-
-}
-
-void arm9tdmi_branch_resume(target_t *target)
-{
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-	
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_B(0xfffffc, 0), 0, NULL, 0);
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
-
-}
-
-void arm9tdmi_branch_resume_thumb(target_t *target)
-{
-	DEBUG("-");
-	
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-	reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
-
-	/* LDMIA r0-15, [r0] at debug speed
-	* register values will start to appear on 4th DCLK
-	*/
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x1, 0, 0), 0, NULL, 0);
-
-	/* fetch NOP, LDM in DECODE stage */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-	/* fetch NOP, LDM in EXECUTE stage (1st cycle) */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-	/* nothing fetched, LDM in EXECUTE stage (2nd cycle) */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32) | 1, NULL, 0);
-	/* nothing fetched, LDM in EXECUTE stage (3rd cycle) */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-
-	/* Branch and eXchange */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_BX(0), 0, NULL, 0);
-	
-	embeddedice_read_reg(dbg_stat);
-	
-	/* fetch NOP, BX in DECODE stage */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-	
-	embeddedice_read_reg(dbg_stat);
-	
-	/* fetch NOP, BX in EXECUTE stage (1st cycle) */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
-
-	/* target is now in Thumb state */
-	embeddedice_read_reg(dbg_stat);
-
-	/* load r0 value, MOV_IM in Decode*/
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), 0, NULL, 0);
-	/* fetch NOP, LDR in Decode, MOV_IM in Execute */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
-	/* fetch NOP, LDR in Execute */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
-	/* nothing fetched, LDR in EXECUTE stage (2nd cycle) */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, buf_get_u32(armv4_5->core_cache->reg_list[0].value, 0, 32), NULL, 0);
-	/* nothing fetched, LDR in EXECUTE stage (3rd cycle) */
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
-	
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
-
-	embeddedice_read_reg(dbg_stat);
-	
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_B(0x7f7), 0, NULL, 1);
-	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
-
-}
-
-void arm9tdmi_enable_single_step(target_t *target)
-{
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	
-	if (arm7_9->has_single_step)
-	{
-		buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 3, 1, 1);
-		embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
-	}
-	else
-	{
-		arm7_9_enable_eice_step(target);
-	}
-}
-
-void arm9tdmi_disable_single_step(target_t *target)
-{
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	
-	if (arm7_9->has_single_step)
-	{
-		buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 3, 1, 0);
-		embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
-	}
-	else
-	{
-		arm7_9_disable_eice_step(target);
-	}
-}
-
-void arm9tdmi_build_reg_cache(target_t *target)
-{
-	reg_cache_t **cache_p = register_get_last_cache_p(&target->reg_cache);
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-
-	(*cache_p) = armv4_5_build_reg_cache(target, armv4_5);
-	armv4_5->core_cache = (*cache_p);
-	
-	/* one extra register (vector catch) */
-	(*cache_p)->next = embeddedice_build_reg_cache(target, arm7_9);
-	arm7_9->eice_cache = (*cache_p)->next;
-
-	if (arm7_9->etm_ctx)
-	{
-		(*cache_p)->next->next = etm_build_reg_cache(target, jtag_info, arm7_9->etm_ctx);
-		arm7_9->etm_ctx->reg_cache = (*cache_p)->next->next;
-	}
-}
-
-int arm9tdmi_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
-{
-	
-	arm9tdmi_build_reg_cache(target);
-	
-	return ERROR_OK;
-	
-}
-
-int arm9tdmi_quit()
-{
-	
-	return ERROR_OK;
-}
-
-int arm9tdmi_init_arch_info(target_t *target, arm9tdmi_common_t *arm9tdmi, int chain_pos, char *variant)
-{
-	armv4_5_common_t *armv4_5;
-	arm7_9_common_t *arm7_9;
-	
-	arm7_9 = &arm9tdmi->arm7_9_common;
-	armv4_5 = &arm7_9->armv4_5_common;
-	
-	/* prepare JTAG information for the new target */
-	arm7_9->jtag_info.chain_pos = chain_pos;
-	arm7_9->jtag_info.scann_size = 5;
-	
-	/* register arch-specific functions */
-	arm7_9->examine_debug_reason = arm9tdmi_examine_debug_reason;
-	arm7_9->change_to_arm = arm9tdmi_change_to_arm;
-	arm7_9->read_core_regs = arm9tdmi_read_core_regs;
-	arm7_9->read_core_regs_target_buffer = arm9tdmi_read_core_regs_target_buffer;
-	arm7_9->read_xpsr = arm9tdmi_read_xpsr;
-	
-	arm7_9->write_xpsr = arm9tdmi_write_xpsr;
-	arm7_9->write_xpsr_im8 = arm9tdmi_write_xpsr_im8;
-	arm7_9->write_core_regs = arm9tdmi_write_core_regs;
-	
-	arm7_9->load_word_regs = arm9tdmi_load_word_regs;
-	arm7_9->load_hword_reg = arm9tdmi_load_hword_reg;
-	arm7_9->load_byte_reg = arm9tdmi_load_byte_reg;
-	
-	arm7_9->store_word_regs = arm9tdmi_store_word_regs;
-	arm7_9->store_hword_reg = arm9tdmi_store_hword_reg;
-	arm7_9->store_byte_reg = arm9tdmi_store_byte_reg;
-	
-	arm7_9->write_pc = arm9tdmi_write_pc;
-	arm7_9->branch_resume = arm9tdmi_branch_resume;
-	arm7_9->branch_resume_thumb = arm9tdmi_branch_resume_thumb;
-
-	arm7_9->enable_single_step = arm9tdmi_enable_single_step;
-	arm7_9->disable_single_step = arm9tdmi_disable_single_step;
-	
-	arm7_9->pre_debug_entry = NULL;
-	arm7_9->post_debug_entry = NULL;
-	
-	arm7_9->pre_restore_context = NULL;
-	arm7_9->post_restore_context = NULL;
-
-	/* initialize arch-specific breakpoint handling */
-	arm7_9->arm_bkpt = 0xdeeedeee;
-	arm7_9->thumb_bkpt = 0xdeee;
-	
-	arm7_9->sw_bkpts_use_wp = 1;
-	arm7_9->sw_bkpts_enabled = 0;
-	arm7_9->dbgreq_adjust_pc = 3;
-	arm7_9->arch_info = arm9tdmi;
-	
-	arm9tdmi->common_magic = ARM9TDMI_COMMON_MAGIC;
-	arm9tdmi->arch_info = NULL;
-
-	if (variant)
-	{
-		arm9tdmi->variant = strdup(variant);
-	}
-	else
-	{
-		arm9tdmi->variant = strdup("");
-	}
-	
-	arm7_9_init_arch_info(target, arm7_9);
-
-	/* override use of DBGRQ, this is safe on ARM9TDMI */
-	arm7_9->use_dbgrq = 1;
-
-	/* all ARM9s have the vector catch register */
-	arm7_9->has_vector_catch = 1;
-	
-	return ERROR_OK;
-}
-
-int arm9tdmi_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, arm7_9_common_t **arm7_9_p, arm9tdmi_common_t **arm9tdmi_p)
-{
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	arm7_9_common_t *arm7_9;
-	arm9tdmi_common_t *arm9tdmi;
-	
-	if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
-	{
-		return -1;
-	}
-	
-	arm7_9 = armv4_5->arch_info;
-	if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC)
-	{
-		return -1;
-	}
-	
-	arm9tdmi = arm7_9->arch_info;
-	if (arm9tdmi->common_magic != ARM9TDMI_COMMON_MAGIC)
-	{
-		return -1;
-	}
-	
-	*armv4_5_p = armv4_5;
-	*arm7_9_p = arm7_9;
-	*arm9tdmi_p = arm9tdmi;
-	
-	return ERROR_OK;
-}
-
-
-/* target arm9tdmi <endianess> <startup_mode> <chain_pos> <variant>*/
-int arm9tdmi_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)
-{
-	int chain_pos;
-	char *variant = NULL;
-	arm9tdmi_common_t *arm9tdmi = malloc(sizeof(arm9tdmi_common_t));
-
-	if (argc < 4)
-	{
-		ERROR("'target arm9tdmi' requires at least one additional argument");
-		exit(-1);
-	}
-	
-	chain_pos = strtoul(args[3], NULL, 0);
-	
-	if (argc >= 5)
-		variant = args[4];
-	
-	arm9tdmi_init_arch_info(target, arm9tdmi, chain_pos, variant);
-	
-	return ERROR_OK;
-}
-
-int arm9tdmi_register_commands(struct command_context_s *cmd_ctx)
-{
-	int retval;
-	
-	command_t *arm9tdmi_cmd;
-	
-		
-	retval = arm7_9_register_commands(cmd_ctx);
-	
-	arm9tdmi_cmd = register_command(cmd_ctx, NULL, "arm9tdmi", NULL, COMMAND_ANY, "arm9tdmi specific commands");
-
-	register_command(cmd_ctx, arm9tdmi_cmd, "vector_catch", handle_arm9tdmi_catch_vectors_command, COMMAND_EXEC, "catch arm920t vectors ['all'|'none'|'<vec1 vec2 ...>']");
-	
-	
-	return ERROR_OK;
-
-}
-
-int handle_arm9tdmi_catch_vectors_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;
-	arm7_9_common_t *arm7_9;
-	arm9tdmi_common_t *arm9tdmi;
-	reg_t *vector_catch;
-	u32 vector_catch_value;
-	int i, j;
-	
-	if (arm9tdmi_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "current target isn't an ARM9TDMI based target");
-		return ERROR_OK;
-	}
-	
-	vector_catch = &arm7_9->eice_cache->reg_list[EICE_VEC_CATCH];
-	
-	/* read the vector catch register if necessary */
-	if (!vector_catch->valid)
-		embeddedice_read_reg(vector_catch);
-	
-	/* get the current setting */
-	vector_catch_value = buf_get_u32(vector_catch->value, 0, 32);
-	
-	if (argc > 0)
-	{
-		vector_catch_value = 0x0;
-		if (strcmp(args[0], "all") == 0)
-		{
-			vector_catch_value = 0xdf;
-		}
-		else if (strcmp(args[0], "none") == 0)
-		{
-			/* do nothing */
-		}
-		else
-		{
-			for (i = 0; i < argc; i++)
-			{
-				/* go through list of vectors */
-				for(j = 0; arm9tdmi_vectors[j].name; j++)
-				{
-					if (strcmp(args[i], arm9tdmi_vectors[j].name) == 0)
-					{
-						vector_catch_value |= arm9tdmi_vectors[j].value;
-						break;
-					}
-				}
-				
-				/* complain if vector wasn't found */
-				if (!arm9tdmi_vectors[j].name)
-				{
-					command_print(cmd_ctx, "vector '%s' not found, leaving current setting unchanged", args[i]);
-					
-					/* reread current setting */
-					vector_catch_value = buf_get_u32(vector_catch->value, 0, 32);
-					
-					break;
-				}
-			}
-		}
-		
-		/* store new settings */
-		buf_set_u32(vector_catch->value, 0, 32, vector_catch_value);
-		embeddedice_store_reg(vector_catch);
-	}
-		
-	/* output current settings (skip RESERVED vector) */
-	for (i = 0; i < 8; i++)
-	{
-		if (i != 5)
-		{
-			command_print(cmd_ctx, "%s: %s", arm9tdmi_vectors[i].name,
-				(vector_catch_value & (1 << i)) ? "catch" : "don't catch");
-		}  
-	}
-
-	return ERROR_OK;
-}
+/***************************************************************************
+ *   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.             *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "arm9tdmi.h"
+
+#include "arm7_9_common.h"
+#include "register.h"
+#include "target.h"
+#include "armv4_5.h"
+#include "embeddedice.h"
+#include "etm.h"
+#include "etb.h"
+#include "log.h"
+#include "jtag.h"
+#include "arm_jtag.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#if 0
+#define _DEBUG_INSTRUCTION_EXECUTION_
+#endif
+
+/* cli handling */
+int arm9tdmi_register_commands(struct command_context_s *cmd_ctx);
+int handle_arm9tdmi_catch_vectors_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+/* forward declarations */
+int arm9tdmi_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target);
+int arm9tdmi_init_target(struct command_context_s *cmd_ctx, struct target_s *target);
+int arm9tdmi_quit();
+		
+target_type_t arm9tdmi_target =
+{
+	.name = "arm9tdmi",
+
+	.poll = arm7_9_poll,
+	.arch_state = armv4_5_arch_state,
+
+	.target_request_data = arm7_9_target_request_data,
+
+	.halt = arm7_9_halt,
+	.resume = arm7_9_resume,
+	.step = arm7_9_step,
+
+	.assert_reset = arm7_9_assert_reset,
+	.deassert_reset = arm7_9_deassert_reset,
+	.soft_reset_halt = arm7_9_soft_reset_halt,
+	.prepare_reset_halt = arm7_9_prepare_reset_halt,
+
+	.get_gdb_reg_list = armv4_5_get_gdb_reg_list,
+
+	.read_memory = arm7_9_read_memory,
+	.write_memory = arm7_9_write_memory,
+	.bulk_write_memory = arm7_9_bulk_write_memory,
+	.checksum_memory = arm7_9_checksum_memory,
+	
+	.run_algorithm = armv4_5_run_algorithm,
+	
+	.add_breakpoint = arm7_9_add_breakpoint,
+	.remove_breakpoint = arm7_9_remove_breakpoint,
+	.add_watchpoint = arm7_9_add_watchpoint,
+	.remove_watchpoint = arm7_9_remove_watchpoint,
+
+	.register_commands = arm9tdmi_register_commands,
+	.target_command = arm9tdmi_target_command,
+	.init_target = arm9tdmi_init_target,
+	.quit = arm9tdmi_quit
+};
+
+arm9tdmi_vector_t arm9tdmi_vectors[] =
+{
+	{"reset", ARM9TDMI_RESET_VECTOR},
+	{"undef", ARM9TDMI_UNDEF_VECTOR},
+	{"swi", ARM9TDMI_SWI_VECTOR},
+	{"pabt", ARM9TDMI_PABT_VECTOR},
+	{"dabt", ARM9TDMI_DABT_VECTOR},
+	{"reserved", ARM9TDMI_RESERVED_VECTOR},
+	{"irq", ARM9TDMI_IRQ_VECTOR},
+	{"fiq", ARM9TDMI_FIQ_VECTOR},
+	{0, 0},
+};
+
+int arm9tdmi_examine_debug_reason(target_t *target)
+{
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	
+	/* only check the debug reason if we don't know it already */
+	if ((target->debug_reason != DBG_REASON_DBGRQ)
+			&& (target->debug_reason != DBG_REASON_SINGLESTEP))
+	{
+		scan_field_t fields[3];
+		u8 databus[4];
+		u8 instructionbus[4];
+		u8 debug_reason;
+
+		jtag_add_end_state(TAP_PD);
+
+		fields[0].device = arm7_9->jtag_info.chain_pos;
+		fields[0].num_bits = 32;
+		fields[0].out_value = NULL;
+		fields[0].out_mask = NULL;
+		fields[0].in_value = databus;
+		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 = arm7_9->jtag_info.chain_pos;
+		fields[1].num_bits = 3;
+		fields[1].out_value = NULL;
+		fields[1].out_mask = NULL;
+		fields[1].in_value = &debug_reason;
+		fields[1].in_check_value = NULL;
+		fields[1].in_check_mask = NULL;
+		fields[1].in_handler = NULL;
+		fields[1].in_handler_priv = NULL;
+		
+		fields[2].device = arm7_9->jtag_info.chain_pos;
+		fields[2].num_bits = 32;
+		fields[2].out_value = NULL;
+		fields[2].out_mask = NULL;
+		fields[2].in_value = instructionbus;
+		fields[2].in_check_value = NULL;
+		fields[2].in_check_mask = NULL;
+		fields[2].in_handler = NULL;
+		fields[2].in_handler_priv = NULL;
+		
+		arm_jtag_scann(&arm7_9->jtag_info, 0x1);
+		arm_jtag_set_instr(&arm7_9->jtag_info, arm7_9->jtag_info.intest_instr, NULL);
+
+		jtag_add_dr_scan(3, fields, TAP_PD);
+		jtag_execute_queue();
+		
+		fields[0].in_value = NULL;
+		fields[0].out_value = databus;
+		fields[1].in_value = NULL;
+		fields[1].out_value = &debug_reason;
+		fields[2].in_value = NULL;
+		fields[2].out_value = instructionbus;
+		
+		jtag_add_dr_scan(3, fields, TAP_PD);
+
+		if (debug_reason & 0x4)
+			if (debug_reason & 0x2)
+				target->debug_reason = DBG_REASON_WPTANDBKPT;
+		else
+			target->debug_reason = DBG_REASON_WATCHPOINT;
+		else
+			target->debug_reason = DBG_REASON_BREAKPOINT;
+	}
+
+	return ERROR_OK;
+}
+
+/* put an instruction in the ARM9TDMI pipeline or write the data bus, and optionally read data */
+int arm9tdmi_clock_out(arm_jtag_t *jtag_info, u32 instr, u32 out, u32 *in, int sysspeed)
+{
+	scan_field_t fields[3];
+	u8 out_buf[4];
+	u8 instr_buf[4];
+	u8 sysspeed_buf = 0x0;
+	
+	/* prepare buffer */
+	buf_set_u32(out_buf, 0, 32, out);
+	
+	buf_set_u32(instr_buf, 0, 32, flip_u32(instr, 32));
+	
+	if (sysspeed)
+		buf_set_u32(&sysspeed_buf, 2, 1, 1);
+	
+	jtag_add_end_state(TAP_PD);
+	arm_jtag_scann(jtag_info, 0x1);
+	
+	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+		
+	fields[0].device = jtag_info->chain_pos;
+	fields[0].num_bits = 32;
+	fields[0].out_value = out_buf;
+	fields[0].out_mask = NULL;
+	fields[0].in_value = NULL;
+	if (in)
+	{
+		fields[0].in_handler = arm_jtag_buf_to_u32;
+		fields[0].in_handler_priv = in;
+	}
+	else
+	{
+		fields[0].in_handler = NULL;
+		fields[0].in_handler_priv = NULL;
+	}
+	fields[0].in_check_value = NULL;
+	fields[0].in_check_mask = NULL;
+	
+	fields[1].device = jtag_info->chain_pos;
+	fields[1].num_bits = 3;
+	fields[1].out_value = &sysspeed_buf;
+	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;
+		
+	fields[2].device = jtag_info->chain_pos;
+	fields[2].num_bits = 32;
+	fields[2].out_value = instr_buf;
+	fields[2].out_mask = NULL;
+	fields[2].in_value = NULL;
+	fields[2].in_check_value = NULL;
+	fields[2].in_check_mask = NULL;
+	fields[2].in_handler = NULL;
+	fields[2].in_handler_priv = NULL;
+
+	jtag_add_dr_scan(3, fields, -1);
+
+	jtag_add_runtest(0, -1);
+	
+#ifdef _DEBUG_INSTRUCTION_EXECUTION_
+	{
+		jtag_execute_queue();
+		
+		if (in)
+		{
+			DEBUG("instr: 0x%8.8x, out: 0x%8.8x, in: 0x%8.8x", instr, out, *in);
+		}
+		else
+			DEBUG("instr: 0x%8.8x, out: 0x%8.8x", instr, out);
+	}
+#endif
+
+	return ERROR_OK;
+}
+
+/* just read data (instruction and data-out = don't care) */
+int arm9tdmi_clock_data_in(arm_jtag_t *jtag_info, u32 *in)
+{
+	scan_field_t fields[3];
+
+	jtag_add_end_state(TAP_PD);
+	arm_jtag_scann(jtag_info, 0x1);
+	
+	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+		
+	fields[0].device = jtag_info->chain_pos;
+	fields[0].num_bits = 32;
+	fields[0].out_value = NULL;
+	fields[0].out_mask = NULL;
+	fields[0].in_value = NULL;
+	fields[0].in_handler = arm_jtag_buf_to_u32;
+	fields[0].in_handler_priv = in;
+	fields[0].in_check_value = NULL;
+	fields[0].in_check_mask = NULL;
+	
+	fields[1].device = jtag_info->chain_pos;
+	fields[1].num_bits = 3;
+	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 = jtag_info->chain_pos;
+	fields[2].num_bits = 32;
+	fields[2].out_value = NULL;
+	fields[2].out_mask = NULL;
+	fields[2].in_value = NULL;
+	fields[2].in_check_value = NULL;
+	fields[2].in_check_mask = NULL;
+	fields[2].in_handler = NULL;
+	fields[2].in_handler_priv = NULL;
+	
+	jtag_add_dr_scan(3, fields, -1);
+
+	jtag_add_runtest(0, -1);
+	
+#ifdef _DEBUG_INSTRUCTION_EXECUTION_
+	{
+		jtag_execute_queue();
+			
+		if (in)
+		{
+			DEBUG("in: 0x%8.8x", *in);
+		}
+		else
+		{
+			ERROR("BUG: called with in == NULL");
+		}
+	}
+#endif
+
+	return ERROR_OK;
+}
+
+/* clock the target, and read the databus
+ * the *in pointer points to a buffer where elements of 'size' bytes
+ * are stored in big (be==1) or little (be==0) endianness
+ */
+int arm9tdmi_clock_data_in_endianness(arm_jtag_t *jtag_info, void *in, int size, int be)
+{
+	scan_field_t fields[3];
+	
+	jtag_add_end_state(TAP_PD);
+	arm_jtag_scann(jtag_info, 0x1);
+	
+	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+		
+	fields[0].device = jtag_info->chain_pos;
+	fields[0].num_bits = 32;
+	fields[0].out_value = NULL;
+	fields[0].out_mask = NULL;
+	fields[0].in_value = NULL;
+	switch (size)
+	{
+		case 4:
+			fields[0].in_handler = (be) ? arm_jtag_buf_to_be32 : arm_jtag_buf_to_le32;
+			break;
+		case 2:
+			fields[0].in_handler = (be) ? arm_jtag_buf_to_be16 : arm_jtag_buf_to_le16;
+			break;
+		case 1:
+			fields[0].in_handler = arm_jtag_buf_to_8;
+			break;
+	}
+	fields[0].in_handler_priv = in;
+	fields[0].in_check_value = NULL;
+	fields[0].in_check_mask = NULL;
+	
+	fields[1].device = jtag_info->chain_pos;
+	fields[1].num_bits = 3;
+	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 = jtag_info->chain_pos;
+	fields[2].num_bits = 32;
+	fields[2].out_value = NULL;
+	fields[2].out_mask = NULL;
+	fields[2].in_value = NULL;
+	fields[2].in_check_value = NULL;
+	fields[2].in_check_mask = NULL;
+	fields[2].in_handler = NULL;
+	fields[2].in_handler_priv = NULL;
+	
+	jtag_add_dr_scan(3, fields, -1);
+
+	jtag_add_runtest(0, -1);
+	
+#ifdef _DEBUG_INSTRUCTION_EXECUTION_
+	{
+		jtag_execute_queue();
+			
+		if (in)
+		{
+			DEBUG("in: 0x%8.8x", *in);
+		}
+		else
+		{
+			ERROR("BUG: called with in == NULL");
+		}
+	}
+#endif
+
+	return ERROR_OK;
+}
+
+void arm9tdmi_change_to_arm(target_t *target, u32 *r0, u32 *pc)
+{
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+	
+	/* save r0 before using it and put system in ARM state 
+	 * to allow common handling of ARM and THUMB debugging */
+	
+	/* fetch STR r0, [r0] */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
+	/* STR r0, [r0] in Memory */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, r0, 0);
+
+	/* MOV r0, r15 fetched, STR in Decode */	
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_MOV(0, 15), 0, NULL, 0);
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
+	/* nothing fetched, STR r0, [r0] in Memory */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, pc, 0);
+
+	/* use pc-relative LDR to clear r0[1:0] (for switch to ARM mode) */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), 0, NULL, 0);
+	/* LDR in Decode */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
+	/* LDR in Execute */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
+	/* LDR in Memory (to account for interlock) */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
+
+	/* fetch BX */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_BX(0), 0, NULL, 0);
+	/* NOP fetched, BX in Decode, MOV in Execute */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
+	/* NOP fetched, BX in Execute (1) */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
+	
+	jtag_execute_queue();
+	
+	/* fix program counter:
+	 * MOV r0, r15 was the 5th instruction (+8)
+	 * reading PC in Thumb state gives address of instruction + 4
+	 */
+	*pc -= 0xc;
+}
+
+void arm9tdmi_read_core_regs(target_t *target, u32 mask, u32* core_regs[16])
+{
+	int i;
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+		
+	/* STMIA r0-15, [r0] at debug speed
+	 * register values will start to appear on 4th DCLK
+	 */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
+
+	/* fetch NOP, STM in DECODE stage */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+	/* fetch NOP, STM in EXECUTE stage (1st cycle) */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+
+	for (i = 0; i <= 15; i++)
+	{
+		if (mask & (1 << i))
+			/* nothing fetched, STM in MEMORY (i'th cycle) */
+			arm9tdmi_clock_data_in(jtag_info, core_regs[i]);
+	}
+
+}
+
+void arm9tdmi_read_core_regs_target_buffer(target_t *target, u32 mask, void* buffer, int size)
+{
+	int i;
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+	int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0;
+	u32 *buf_u32 = buffer;
+	u16 *buf_u16 = buffer;
+	u8 *buf_u8 = buffer;
+	
+	/* STMIA r0-15, [r0] at debug speed
+	 * register values will start to appear on 4th DCLK
+	 */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
+
+	/* fetch NOP, STM in DECODE stage */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+	/* fetch NOP, STM in EXECUTE stage (1st cycle) */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+
+	for (i = 0; i <= 15; i++)
+	{
+		if (mask & (1 << i))
+			/* nothing fetched, STM in MEMORY (i'th cycle) */
+			switch (size)
+			{
+				case 4:
+					arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
+					break;
+				case 2:
+					arm9tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);
+					break;
+				case 1:
+					arm9tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);
+					break;
+			}
+	}
+
+}
+
+void arm9tdmi_read_xpsr(target_t *target, u32 *xpsr, int spsr)
+{
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+		
+	/* MRS r0, cpsr */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), 0, NULL, 0);
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+
+	/* STR r0, [r15] */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_STR(0, 15), 0, NULL, 0);
+	/* fetch NOP, STR in DECODE stage */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+	/* fetch NOP, STR in EXECUTE stage (1st cycle) */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+	/* nothing fetched, STR in MEMORY */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, xpsr, 0);
+
+}
+
+void arm9tdmi_write_xpsr(target_t *target, u32 xpsr, int spsr)
+{
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+		
+	DEBUG("xpsr: %8.8x, spsr: %i", xpsr, spsr);
+
+	/* MSR1 fetched */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), 0, NULL, 0);
+	/* MSR2 fetched, MSR1 in DECODE */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), 0, NULL, 0);
+	/* MSR3 fetched, MSR1 in EXECUTE (1), MSR2 in DECODE */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), 0, NULL, 0);
+	/* nothing fetched, MSR1 in EXECUTE (2) */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+	/* nothing fetched, MSR1 in EXECUTE (3) */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+	/* MSR4 fetched, MSR2 in EXECUTE (1), MSR3 in DECODE */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), 0, NULL, 0);
+	/* nothing fetched, MSR2 in EXECUTE (2) */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+	/* nothing fetched, MSR2 in EXECUTE (3) */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+	/* NOP fetched, MSR3 in EXECUTE (1), MSR4 in DECODE */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+	/* nothing fetched, MSR3 in EXECUTE (2) */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+	/* nothing fetched, MSR3 in EXECUTE (3) */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+	/* NOP fetched, MSR4 in EXECUTE (1) */
+	/* last MSR writes flags, which takes only one cycle */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+}
+
+void arm9tdmi_write_xpsr_im8(target_t *target, u8 xpsr_im, int rot, int spsr)
+{
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+		
+	DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr);
+	
+	/* MSR fetched */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), 0, NULL, 0);
+	/* NOP fetched, MSR in DECODE */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+	/* NOP fetched, MSR in EXECUTE (1) */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+	
+	/* rot == 4 writes flags, which takes only one cycle */
+	if (rot != 4)
+	{
+		/* nothing fetched, MSR in EXECUTE (2) */
+		arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+		/* nothing fetched, MSR in EXECUTE (3) */
+		arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+	}
+}
+
+void arm9tdmi_write_core_regs(target_t *target, u32 mask, u32 core_regs[16])
+{
+	int i;
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+		
+	/* LDMIA r0-15, [r0] at debug speed
+	* register values will start to appear on 4th DCLK
+	*/
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
+
+	/* fetch NOP, LDM in DECODE stage */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+	/* fetch NOP, LDM in EXECUTE stage (1st cycle) */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+
+	for (i = 0; i <= 15; i++)
+	{
+		if (mask & (1 << i))
+			/* nothing fetched, LDM still in EXECUTE (1+i cycle) */
+			arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, core_regs[i], NULL, 0);
+	}
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+	
+}
+
+void arm9tdmi_load_word_regs(target_t *target, u32 mask)
+{
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+
+	/* put system-speed load-multiple into the pipeline */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 1), 0, NULL, 0);
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
+
+}
+
+void arm9tdmi_load_hword_reg(target_t *target, int num)
+{
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+	
+	/* put system-speed load half-word into the pipeline */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_LDRH_IP(num, 0), 0, NULL, 0);
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
+}
+
+void arm9tdmi_load_byte_reg(target_t *target, int num)
+{
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+
+	/* put system-speed load byte into the pipeline */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_LDRB_IP(num, 0), 0, NULL, 0);
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
+
+}
+
+void arm9tdmi_store_word_regs(target_t *target, u32 mask)
+{
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+
+	/* put system-speed store-multiple into the pipeline */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask, 0, 1), 0, NULL, 0);
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
+
+}
+
+void arm9tdmi_store_hword_reg(target_t *target, int num)
+{
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+
+	/* put system-speed store half-word into the pipeline */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_STRH_IP(num, 0), 0, NULL, 0);
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
+
+}
+
+void arm9tdmi_store_byte_reg(target_t *target, int num)
+{
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+
+	/* put system-speed store byte into the pipeline */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_STRB_IP(num, 0), 0, NULL, 0);
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
+
+}
+
+void arm9tdmi_write_pc(target_t *target, u32 pc)
+{
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+	
+	/* LDMIA r0-15, [r0] at debug speed
+	 * register values will start to appear on 4th DCLK
+	 */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x8000, 0, 0), 0, NULL, 0);
+
+	/* fetch NOP, LDM in DECODE stage */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+	/* fetch NOP, LDM in EXECUTE stage (1st cycle) */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+	/* nothing fetched, LDM in EXECUTE stage (2nd cycle) (output data) */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, pc, NULL, 0);
+	/* nothing fetched, LDM in EXECUTE stage (3rd cycle) */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+	/* fetch NOP, LDM in EXECUTE stage (4th cycle) */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+	/* fetch NOP, LDM in EXECUTE stage (5th cycle) */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+
+}
+
+void arm9tdmi_branch_resume(target_t *target)
+{
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+	
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_B(0xfffffc, 0), 0, NULL, 0);
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
+
+}
+
+void arm9tdmi_branch_resume_thumb(target_t *target)
+{
+	DEBUG("-");
+	
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+	reg_t *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
+
+	/* LDMIA r0-15, [r0] at debug speed
+	* register values will start to appear on 4th DCLK
+	*/
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x1, 0, 0), 0, NULL, 0);
+
+	/* fetch NOP, LDM in DECODE stage */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+	/* fetch NOP, LDM in EXECUTE stage (1st cycle) */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+	/* nothing fetched, LDM in EXECUTE stage (2nd cycle) */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32) | 1, NULL, 0);
+	/* nothing fetched, LDM in EXECUTE stage (3rd cycle) */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+
+	/* Branch and eXchange */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_BX(0), 0, NULL, 0);
+	
+	embeddedice_read_reg(dbg_stat);
+	
+	/* fetch NOP, BX in DECODE stage */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+	
+	embeddedice_read_reg(dbg_stat);
+	
+	/* fetch NOP, BX in EXECUTE stage (1st cycle) */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
+
+	/* target is now in Thumb state */
+	embeddedice_read_reg(dbg_stat);
+
+	/* load r0 value, MOV_IM in Decode*/
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), 0, NULL, 0);
+	/* fetch NOP, LDR in Decode, MOV_IM in Execute */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
+	/* fetch NOP, LDR in Execute */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
+	/* nothing fetched, LDR in EXECUTE stage (2nd cycle) */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, buf_get_u32(armv4_5->core_cache->reg_list[0].value, 0, 32), NULL, 0);
+	/* nothing fetched, LDR in EXECUTE stage (3rd cycle) */
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
+	
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
+
+	embeddedice_read_reg(dbg_stat);
+	
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_B(0x7f7), 0, NULL, 1);
+	arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
+
+}
+
+void arm9tdmi_enable_single_step(target_t *target)
+{
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	
+	if (arm7_9->has_single_step)
+	{
+		buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 3, 1, 1);
+		embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
+	}
+	else
+	{
+		arm7_9_enable_eice_step(target);
+	}
+}
+
+void arm9tdmi_disable_single_step(target_t *target)
+{
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	
+	if (arm7_9->has_single_step)
+	{
+		buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 3, 1, 0);
+		embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
+	}
+	else
+	{
+		arm7_9_disable_eice_step(target);
+	}
+}
+
+void arm9tdmi_build_reg_cache(target_t *target)
+{
+	reg_cache_t **cache_p = register_get_last_cache_p(&target->reg_cache);
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9 = armv4_5->arch_info;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+
+	(*cache_p) = armv4_5_build_reg_cache(target, armv4_5);
+	armv4_5->core_cache = (*cache_p);
+	
+	/* one extra register (vector catch) */
+	(*cache_p)->next = embeddedice_build_reg_cache(target, arm7_9);
+	arm7_9->eice_cache = (*cache_p)->next;
+
+	if (arm7_9->etm_ctx)
+	{
+		(*cache_p)->next->next = etm_build_reg_cache(target, jtag_info, arm7_9->etm_ctx);
+		arm7_9->etm_ctx->reg_cache = (*cache_p)->next->next;
+	}
+}
+
+int arm9tdmi_init_target(struct command_context_s *cmd_ctx, struct target_s *target)
+{
+	
+	arm9tdmi_build_reg_cache(target);
+	
+	return ERROR_OK;
+	
+}
+
+int arm9tdmi_quit()
+{
+	
+	return ERROR_OK;
+}
+
+int arm9tdmi_init_arch_info(target_t *target, arm9tdmi_common_t *arm9tdmi, int chain_pos, char *variant)
+{
+	armv4_5_common_t *armv4_5;
+	arm7_9_common_t *arm7_9;
+	
+	arm7_9 = &arm9tdmi->arm7_9_common;
+	armv4_5 = &arm7_9->armv4_5_common;
+	
+	/* prepare JTAG information for the new target */
+	arm7_9->jtag_info.chain_pos = chain_pos;
+	arm7_9->jtag_info.scann_size = 5;
+	
+	/* register arch-specific functions */
+	arm7_9->examine_debug_reason = arm9tdmi_examine_debug_reason;
+	arm7_9->change_to_arm = arm9tdmi_change_to_arm;
+	arm7_9->read_core_regs = arm9tdmi_read_core_regs;
+	arm7_9->read_core_regs_target_buffer = arm9tdmi_read_core_regs_target_buffer;
+	arm7_9->read_xpsr = arm9tdmi_read_xpsr;
+	
+	arm7_9->write_xpsr = arm9tdmi_write_xpsr;
+	arm7_9->write_xpsr_im8 = arm9tdmi_write_xpsr_im8;
+	arm7_9->write_core_regs = arm9tdmi_write_core_regs;
+	
+	arm7_9->load_word_regs = arm9tdmi_load_word_regs;
+	arm7_9->load_hword_reg = arm9tdmi_load_hword_reg;
+	arm7_9->load_byte_reg = arm9tdmi_load_byte_reg;
+	
+	arm7_9->store_word_regs = arm9tdmi_store_word_regs;
+	arm7_9->store_hword_reg = arm9tdmi_store_hword_reg;
+	arm7_9->store_byte_reg = arm9tdmi_store_byte_reg;
+	
+	arm7_9->write_pc = arm9tdmi_write_pc;
+	arm7_9->branch_resume = arm9tdmi_branch_resume;
+	arm7_9->branch_resume_thumb = arm9tdmi_branch_resume_thumb;
+
+	arm7_9->enable_single_step = arm9tdmi_enable_single_step;
+	arm7_9->disable_single_step = arm9tdmi_disable_single_step;
+	
+	arm7_9->pre_debug_entry = NULL;
+	arm7_9->post_debug_entry = NULL;
+	
+	arm7_9->pre_restore_context = NULL;
+	arm7_9->post_restore_context = NULL;
+
+	/* initialize arch-specific breakpoint handling */
+	arm7_9->arm_bkpt = 0xdeeedeee;
+	arm7_9->thumb_bkpt = 0xdeee;
+	
+	arm7_9->sw_bkpts_use_wp = 1;
+	arm7_9->sw_bkpts_enabled = 0;
+	arm7_9->dbgreq_adjust_pc = 3;
+	arm7_9->arch_info = arm9tdmi;
+	
+	arm9tdmi->common_magic = ARM9TDMI_COMMON_MAGIC;
+	arm9tdmi->arch_info = NULL;
+
+	if (variant)
+	{
+		arm9tdmi->variant = strdup(variant);
+	}
+	else
+	{
+		arm9tdmi->variant = strdup("");
+	}
+	
+	arm7_9_init_arch_info(target, arm7_9);
+
+	/* override use of DBGRQ, this is safe on ARM9TDMI */
+	arm7_9->use_dbgrq = 1;
+
+	/* all ARM9s have the vector catch register */
+	arm7_9->has_vector_catch = 1;
+	
+	return ERROR_OK;
+}
+
+int arm9tdmi_get_arch_pointers(target_t *target, armv4_5_common_t **armv4_5_p, arm7_9_common_t **arm7_9_p, arm9tdmi_common_t **arm9tdmi_p)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	arm7_9_common_t *arm7_9;
+	arm9tdmi_common_t *arm9tdmi;
+	
+	if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
+	{
+		return -1;
+	}
+	
+	arm7_9 = armv4_5->arch_info;
+	if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC)
+	{
+		return -1;
+	}
+	
+	arm9tdmi = arm7_9->arch_info;
+	if (arm9tdmi->common_magic != ARM9TDMI_COMMON_MAGIC)
+	{
+		return -1;
+	}
+	
+	*armv4_5_p = armv4_5;
+	*arm7_9_p = arm7_9;
+	*arm9tdmi_p = arm9tdmi;
+	
+	return ERROR_OK;
+}
+
+
+/* target arm9tdmi <endianess> <startup_mode> <chain_pos> <variant>*/
+int arm9tdmi_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct target_s *target)
+{
+	int chain_pos;
+	char *variant = NULL;
+	arm9tdmi_common_t *arm9tdmi = malloc(sizeof(arm9tdmi_common_t));
+
+	if (argc < 4)
+	{
+		ERROR("'target arm9tdmi' requires at least one additional argument");
+		exit(-1);
+	}
+	
+	chain_pos = strtoul(args[3], NULL, 0);
+	
+	if (argc >= 5)
+		variant = args[4];
+	
+	arm9tdmi_init_arch_info(target, arm9tdmi, chain_pos, variant);
+	
+	return ERROR_OK;
+}
+
+int arm9tdmi_register_commands(struct command_context_s *cmd_ctx)
+{
+	int retval;
+	
+	command_t *arm9tdmi_cmd;
+	
+		
+	retval = arm7_9_register_commands(cmd_ctx);
+	
+	arm9tdmi_cmd = register_command(cmd_ctx, NULL, "arm9tdmi", NULL, COMMAND_ANY, "arm9tdmi specific commands");
+
+	register_command(cmd_ctx, arm9tdmi_cmd, "vector_catch", handle_arm9tdmi_catch_vectors_command, COMMAND_EXEC, "catch arm920t vectors ['all'|'none'|'<vec1 vec2 ...>']");
+	
+	
+	return ERROR_OK;
+
+}
+
+int handle_arm9tdmi_catch_vectors_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;
+	arm7_9_common_t *arm7_9;
+	arm9tdmi_common_t *arm9tdmi;
+	reg_t *vector_catch;
+	u32 vector_catch_value;
+	int i, j;
+	
+	if (arm9tdmi_get_arch_pointers(target, &armv4_5, &arm7_9, &arm9tdmi) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "current target isn't an ARM9TDMI based target");
+		return ERROR_OK;
+	}
+	
+	vector_catch = &arm7_9->eice_cache->reg_list[EICE_VEC_CATCH];
+	
+	/* read the vector catch register if necessary */
+	if (!vector_catch->valid)
+		embeddedice_read_reg(vector_catch);
+	
+	/* get the current setting */
+	vector_catch_value = buf_get_u32(vector_catch->value, 0, 32);
+	
+	if (argc > 0)
+	{
+		vector_catch_value = 0x0;
+		if (strcmp(args[0], "all") == 0)
+		{
+			vector_catch_value = 0xdf;
+		}
+		else if (strcmp(args[0], "none") == 0)
+		{
+			/* do nothing */
+		}
+		else
+		{
+			for (i = 0; i < argc; i++)
+			{
+				/* go through list of vectors */
+				for(j = 0; arm9tdmi_vectors[j].name; j++)
+				{
+					if (strcmp(args[i], arm9tdmi_vectors[j].name) == 0)
+					{
+						vector_catch_value |= arm9tdmi_vectors[j].value;
+						break;
+					}
+				}
+				
+				/* complain if vector wasn't found */
+				if (!arm9tdmi_vectors[j].name)
+				{
+					command_print(cmd_ctx, "vector '%s' not found, leaving current setting unchanged", args[i]);
+					
+					/* reread current setting */
+					vector_catch_value = buf_get_u32(vector_catch->value, 0, 32);
+					
+					break;
+				}
+			}
+		}
+		
+		/* store new settings */
+		buf_set_u32(vector_catch->value, 0, 32, vector_catch_value);
+		embeddedice_store_reg(vector_catch);
+	}
+		
+	/* output current settings (skip RESERVED vector) */
+	for (i = 0; i < 8; i++)
+	{
+		if (i != 5)
+		{
+			command_print(cmd_ctx, "%s: %s", arm9tdmi_vectors[i].name,
+				(vector_catch_value & (1 << i)) ? "catch" : "don't catch");
+		}  
+	}
+
+	return ERROR_OK;
+}
diff --git a/src/target/arm_jtag.c b/src/target/arm_jtag.c
index 070af2137b4b783a3e4d1398e5d383e1e99b5290..08cf3462dcdaab060db23864ff79de3a4357fdd0 100644
--- a/src/target/arm_jtag.c
+++ b/src/target/arm_jtag.c
@@ -1,207 +1,207 @@
-/***************************************************************************
- *   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.             *
- ***************************************************************************/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "arm_jtag.h"
-
-#include "binarybuffer.h"
-#include "log.h"
-#include "jtag.h"
-
-#include <stdlib.h>
-
-#if 0
-#define _ARM_JTAG_SCAN_N_CHECK_
-#endif
-
-int arm_jtag_set_instr(arm_jtag_t *jtag_info, u32 new_instr,  in_handler_t handler)
-{
-	jtag_device_t *device = jtag_get_device(jtag_info->chain_pos);
-	
-	if (buf_get_u32(device->cur_instr, 0, device->ir_length) != new_instr)
-	{
-		scan_field_t field;
-	
-		field.device = jtag_info->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 = NULL;
-		field.in_check_mask = NULL;
-		field.in_handler = handler;
-		field.in_handler_priv = NULL;
-		jtag_add_ir_scan(1, &field, -1, NULL);
-		
-		
-		free(field.out_value);
-	}
-	
-	return ERROR_OK;
-}
-
-int arm_jtag_scann(arm_jtag_t *jtag_info, u32 new_scan_chain)
-{
-	if(jtag_info->cur_scan_chain != new_scan_chain)
-	{
-#ifdef _ARM_JTAG_SCAN_N_CHECK_
-		u8 scan_n_check_value = 1 << (jtag_info->scann_size - 1);
-#endif
-		scan_field_t field;
-		
-		field.device = jtag_info->chain_pos;
-		field.num_bits = jtag_info->scann_size;
-		field.out_value = calloc(CEIL(field.num_bits, 8), 1);
-		buf_set_u32(field.out_value, 0, field.num_bits, new_scan_chain);
-		field.out_mask = NULL;
-		field.in_value = NULL;
-#ifdef _ARM_JTAG_SCAN_N_CHECK_
-		jtag_set_check_value(&field, &scan_n_check_value, NULL, NULL, NULL);
-#else
-		field.in_handler = NULL;
-		field.in_handler_priv = NULL;
-#endif 
-		
-		
-		arm_jtag_set_instr(jtag_info, jtag_info->scann_instr, NULL);
-		jtag_add_dr_scan(1, &field, -1, NULL);
-		
-		jtag_info->cur_scan_chain = new_scan_chain;
-		
-		free(field.out_value);
-	}
-	
-	return ERROR_OK;
-}
-
-int arm_jtag_reset_callback(enum jtag_event event, void *priv)
-{
-	arm_jtag_t *jtag_info = priv;
-	
-	if (event == JTAG_TRST_ASSERTED)
-	{
-		jtag_info->cur_scan_chain = 0;
-	}
-	
-	return ERROR_OK;
-}
-
-int arm_jtag_setup_connection(arm_jtag_t *jtag_info)
-{
-	jtag_info->scann_instr = 0x2;
-	jtag_info->cur_scan_chain = 0;
-	jtag_info->intest_instr = 0xc;
-
-	jtag_register_event_callback(arm_jtag_reset_callback, jtag_info);
-	
-	return ERROR_OK;
-}
-
-/* read JTAG buffer into host-endian u32, flipping bit-order */
-int arm_jtag_buf_to_u32_flip(u8 *in_buf, void *priv, struct scan_field_s *field)
-{
-	u32 *dest = priv;
-	*dest = flip_u32(le_to_h_u32(in_buf), 32);
-	return ERROR_OK;
-}
-
-/* read JTAG buffer into little-endian u32, flipping bit-order */
-int arm_jtag_buf_to_le32_flip(u8 *in_buf, void *priv, struct scan_field_s *field)
-{
-	h_u32_to_le(((u8*)priv), flip_u32(le_to_h_u32(in_buf), 32));
-	return ERROR_OK;
-}
-
-/* read JTAG buffer into little-endian u16, flipping bit-order */
-int arm_jtag_buf_to_le16_flip(u8 *in_buf, void *priv, struct scan_field_s *field)
-{
-	h_u16_to_le(((u8*)priv), flip_u32(le_to_h_u32(in_buf), 32) & 0xffff);
-	return ERROR_OK;
-}
-
-/* read JTAG buffer into big-endian u32, flipping bit-order */
-int arm_jtag_buf_to_be32_flip(u8 *in_buf, void *priv, struct scan_field_s *field)
-{
-	h_u32_to_be(((u8*)priv), flip_u32(le_to_h_u32(in_buf), 32));
-	return ERROR_OK;
-}
-
-/* read JTAG buffer into big-endian u16, flipping bit-order */
-int arm_jtag_buf_to_be16_flip(u8 *in_buf, void *priv, struct scan_field_s *field)
-{
-	h_u16_to_be(((u8*)priv), flip_u32(le_to_h_u32(in_buf), 32) & 0xffff);
-	return ERROR_OK;
-}
-
-/* read JTAG buffer into u8, flipping bit-order */
-int arm_jtag_buf_to_8_flip(u8 *in_buf, void *priv, struct scan_field_s *field)
-{
-	u8 *dest = priv;
-	*dest = flip_u32(le_to_h_u32(in_buf), 32) & 0xff;
-	return ERROR_OK;
-}
-
-/* not-flipping variants */
-/* read JTAG buffer into host-endian u32 */
-int arm_jtag_buf_to_u32(u8 *in_buf, void *priv, struct scan_field_s *field)
-{
-	u32 *dest = priv;
-	*dest = le_to_h_u32(in_buf);
-	return ERROR_OK;
-}
-
-/* read JTAG buffer into little-endian u32 */
-int arm_jtag_buf_to_le32(u8 *in_buf, void *priv, struct scan_field_s *field)
-{
-	h_u32_to_le(((u8*)priv), le_to_h_u32(in_buf));
-	return ERROR_OK;
-}
-
-/* read JTAG buffer into little-endian u16 */
-int arm_jtag_buf_to_le16(u8 *in_buf, void *priv, struct scan_field_s *field)
-{
-	h_u16_to_le(((u8*)priv), le_to_h_u32(in_buf) & 0xffff);
-	return ERROR_OK;
-}
-
-/* read JTAG buffer into big-endian u32 */
-int arm_jtag_buf_to_be32(u8 *in_buf, void *priv, struct scan_field_s *field)
-{
-	h_u32_to_be(((u8*)priv), le_to_h_u32(in_buf));
-	return ERROR_OK;
-}
-
-/* read JTAG buffer into big-endian u16 */
-int arm_jtag_buf_to_be16(u8 *in_buf, void *priv, struct scan_field_s *field)
-{
-	h_u16_to_be(((u8*)priv), le_to_h_u32(in_buf) & 0xffff);
-	return ERROR_OK;
-}
-
-/* read JTAG buffer into u8 */
-int arm_jtag_buf_to_8(u8 *in_buf, void *priv, struct scan_field_s *field)
-{
-	u8 *dest = priv;
-	*dest = le_to_h_u32(in_buf) & 0xff;
-	return ERROR_OK;
-}
+/***************************************************************************
+ *   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.             *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "arm_jtag.h"
+
+#include "binarybuffer.h"
+#include "log.h"
+#include "jtag.h"
+
+#include <stdlib.h>
+
+#if 0
+#define _ARM_JTAG_SCAN_N_CHECK_
+#endif
+
+int arm_jtag_set_instr(arm_jtag_t *jtag_info, u32 new_instr,  in_handler_t handler)
+{
+	jtag_device_t *device = jtag_get_device(jtag_info->chain_pos);
+	
+	if (buf_get_u32(device->cur_instr, 0, device->ir_length) != new_instr)
+	{
+		scan_field_t field;
+	
+		field.device = jtag_info->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 = NULL;
+		field.in_check_mask = NULL;
+		field.in_handler = handler;
+		field.in_handler_priv = NULL;
+		jtag_add_ir_scan(1, &field, -1);
+		
+		
+		free(field.out_value);
+	}
+	
+	return ERROR_OK;
+}
+
+int arm_jtag_scann(arm_jtag_t *jtag_info, u32 new_scan_chain)
+{
+	if(jtag_info->cur_scan_chain != new_scan_chain)
+	{
+#ifdef _ARM_JTAG_SCAN_N_CHECK_
+		u8 scan_n_check_value = 1 << (jtag_info->scann_size - 1);
+#endif
+		scan_field_t field;
+		
+		field.device = jtag_info->chain_pos;
+		field.num_bits = jtag_info->scann_size;
+		field.out_value = calloc(CEIL(field.num_bits, 8), 1);
+		buf_set_u32(field.out_value, 0, field.num_bits, new_scan_chain);
+		field.out_mask = NULL;
+		field.in_value = NULL;
+#ifdef _ARM_JTAG_SCAN_N_CHECK_
+		jtag_set_check_value(&field, &scan_n_check_value, NULL, NULL, NULL);
+#else
+		field.in_handler = NULL;
+		field.in_handler_priv = NULL;
+#endif 
+		
+		
+		arm_jtag_set_instr(jtag_info, jtag_info->scann_instr, NULL);
+		jtag_add_dr_scan(1, &field, -1);
+		
+		jtag_info->cur_scan_chain = new_scan_chain;
+		
+		free(field.out_value);
+	}
+	
+	return ERROR_OK;
+}
+
+int arm_jtag_reset_callback(enum jtag_event event, void *priv)
+{
+	arm_jtag_t *jtag_info = priv;
+	
+	if (event == JTAG_TRST_ASSERTED)
+	{
+		jtag_info->cur_scan_chain = 0;
+	}
+	
+	return ERROR_OK;
+}
+
+int arm_jtag_setup_connection(arm_jtag_t *jtag_info)
+{
+	jtag_info->scann_instr = 0x2;
+	jtag_info->cur_scan_chain = 0;
+	jtag_info->intest_instr = 0xc;
+
+	jtag_register_event_callback(arm_jtag_reset_callback, jtag_info);
+	
+	return ERROR_OK;
+}
+
+/* read JTAG buffer into host-endian u32, flipping bit-order */
+int arm_jtag_buf_to_u32_flip(u8 *in_buf, void *priv, struct scan_field_s *field)
+{
+	u32 *dest = priv;
+	*dest = flip_u32(le_to_h_u32(in_buf), 32);
+	return ERROR_OK;
+}
+
+/* read JTAG buffer into little-endian u32, flipping bit-order */
+int arm_jtag_buf_to_le32_flip(u8 *in_buf, void *priv, struct scan_field_s *field)
+{
+	h_u32_to_le(((u8*)priv), flip_u32(le_to_h_u32(in_buf), 32));
+	return ERROR_OK;
+}
+
+/* read JTAG buffer into little-endian u16, flipping bit-order */
+int arm_jtag_buf_to_le16_flip(u8 *in_buf, void *priv, struct scan_field_s *field)
+{
+	h_u16_to_le(((u8*)priv), flip_u32(le_to_h_u32(in_buf), 32) & 0xffff);
+	return ERROR_OK;
+}
+
+/* read JTAG buffer into big-endian u32, flipping bit-order */
+int arm_jtag_buf_to_be32_flip(u8 *in_buf, void *priv, struct scan_field_s *field)
+{
+	h_u32_to_be(((u8*)priv), flip_u32(le_to_h_u32(in_buf), 32));
+	return ERROR_OK;
+}
+
+/* read JTAG buffer into big-endian u16, flipping bit-order */
+int arm_jtag_buf_to_be16_flip(u8 *in_buf, void *priv, struct scan_field_s *field)
+{
+	h_u16_to_be(((u8*)priv), flip_u32(le_to_h_u32(in_buf), 32) & 0xffff);
+	return ERROR_OK;
+}
+
+/* read JTAG buffer into u8, flipping bit-order */
+int arm_jtag_buf_to_8_flip(u8 *in_buf, void *priv, struct scan_field_s *field)
+{
+	u8 *dest = priv;
+	*dest = flip_u32(le_to_h_u32(in_buf), 32) & 0xff;
+	return ERROR_OK;
+}
+
+/* not-flipping variants */
+/* read JTAG buffer into host-endian u32 */
+int arm_jtag_buf_to_u32(u8 *in_buf, void *priv, struct scan_field_s *field)
+{
+	u32 *dest = priv;
+	*dest = le_to_h_u32(in_buf);
+	return ERROR_OK;
+}
+
+/* read JTAG buffer into little-endian u32 */
+int arm_jtag_buf_to_le32(u8 *in_buf, void *priv, struct scan_field_s *field)
+{
+	h_u32_to_le(((u8*)priv), le_to_h_u32(in_buf));
+	return ERROR_OK;
+}
+
+/* read JTAG buffer into little-endian u16 */
+int arm_jtag_buf_to_le16(u8 *in_buf, void *priv, struct scan_field_s *field)
+{
+	h_u16_to_le(((u8*)priv), le_to_h_u32(in_buf) & 0xffff);
+	return ERROR_OK;
+}
+
+/* read JTAG buffer into big-endian u32 */
+int arm_jtag_buf_to_be32(u8 *in_buf, void *priv, struct scan_field_s *field)
+{
+	h_u32_to_be(((u8*)priv), le_to_h_u32(in_buf));
+	return ERROR_OK;
+}
+
+/* read JTAG buffer into big-endian u16 */
+int arm_jtag_buf_to_be16(u8 *in_buf, void *priv, struct scan_field_s *field)
+{
+	h_u16_to_be(((u8*)priv), le_to_h_u32(in_buf) & 0xffff);
+	return ERROR_OK;
+}
+
+/* read JTAG buffer into u8 */
+int arm_jtag_buf_to_8(u8 *in_buf, void *priv, struct scan_field_s *field)
+{
+	u8 *dest = priv;
+	*dest = le_to_h_u32(in_buf) & 0xff;
+	return ERROR_OK;
+}
diff --git a/src/target/cortex_swjdp.c b/src/target/cortex_swjdp.c
index 8cefcbfd3930b8725bcb0814cae66d1bdade17cf..88b641e3e35c4219cd1ef71f68750fdbe8f935e0 100644
--- a/src/target/cortex_swjdp.c
+++ b/src/target/cortex_swjdp.c
@@ -1,708 +1,708 @@
-/***************************************************************************
- *   Copyright (C) 2006 by Magnus Lundin                                   *
- *   lundin@mlu.mine.nu                                                    *
- *                                                                         *
- *   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.             *
- ***************************************************************************/
-/***************************************************************************
- *                                                                         *
- * CoreSight (Light?) SerialWireJtagDebugPort                              *
- *                                                                         *
- * CoreSightâ„¢ DAP-Lite TRM, ARM DDI 0316A                                  *
- * Cortex-M3â„¢ TRM, ARM DDI 0337C                                            *
- *                                                                         *
-***************************************************************************/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "replacements.h"
-
-#include "cortex_m3.h"
-#include "cortex_swjdp.h"
-#include "jtag.h"
-#include "log.h"
-#include <stdlib.h>
-
-/*
-
-Transaction Mode:
-swjdp->trans_mode = TRANS_MODE_COMPOSITE;
-Uses Overrun checking mode and does not do actual JTAG send/receive or transaction 
-result checking until swjdp_end_transaction()
-This must be done before using or deallocating any return variables.
-
-swjdp->trans_mode == TRANS_MODE_ATOMIC
-All reads and writes to the AHB bus are checked for valid completion, and return values
-are immediatley available.
-
-*/
-
-/***************************************************************************
- *                                                                         *
- * DPACC and APACC scanchain access through JTAG-DR                        *
- *                                                                         *
-***************************************************************************/
-
-/* Scan out and in from target ordered u8 buffers */
-int swjdp_scan(arm_jtag_t *jtag_info, u8 instr, u8 reg_addr, u8 RnW, u8 *outvalue, u8 *invalue, u8 *ack)
-{
-	scan_field_t fields[2];
-	u8 out_addr_buf;
-	
-	jtag_add_end_state(TAP_RTI);
-	arm_jtag_set_instr(jtag_info, instr, NULL);
-
-	fields[0].device = jtag_info->chain_pos;
-	fields[0].num_bits = 3;
-	buf_set_u32(&out_addr_buf, 0, 3, ((reg_addr >> 1) & 0x6) | (RnW & 0x1));
-	fields[0].out_value = &out_addr_buf;
-	fields[0].out_mask = NULL;
-	fields[0].in_value = ack;
-	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 = jtag_info->chain_pos;
-	fields[1].num_bits = 32;
-	fields[1].out_value = outvalue;
-	fields[1].out_mask = NULL;
-	fields[1].in_value = invalue;
-	fields[1].in_handler = NULL;
-	fields[1].in_handler_priv = NULL;
-	fields[1].in_check_value = NULL;
-	fields[1].in_check_mask = NULL;
-
-	jtag_add_dr_scan(2, fields, -1, NULL);
-
-	return ERROR_OK;
-}
-
-/* Scan out and in from host ordered u32 variables */
-int swjdp_scan_u32(arm_jtag_t *jtag_info, u8 instr, u8 reg_addr, u8 RnW, u32 outvalue, u32 *invalue, u8 *ack)
-{
-	scan_field_t fields[2];
-	u8 out_value_buf[4];
-	u8 out_addr_buf;
-	
-	jtag_add_end_state(TAP_RTI);
-	arm_jtag_set_instr(jtag_info, instr, NULL);
-
-	fields[0].device = jtag_info->chain_pos;
-	fields[0].num_bits = 3;
-	buf_set_u32(&out_addr_buf, 0, 3, ((reg_addr >> 1) & 0x6) | (RnW & 0x1));
-	fields[0].out_value = &out_addr_buf;
-	fields[0].out_mask = NULL;
-	fields[0].in_value = ack;
-	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 = jtag_info->chain_pos;
-	fields[1].num_bits = 32;
-	buf_set_u32(out_value_buf, 0, 32, outvalue);
-	fields[1].out_value = out_value_buf;
-	fields[1].out_mask = NULL;
-	fields[1].in_value = NULL;
-	if (invalue)
-	{
-		fields[1].in_handler = arm_jtag_buf_to_u32;
-		fields[1].in_handler_priv = invalue;
-	}
-	else
-	{
-		fields[1].in_handler = NULL;
-		fields[1].in_handler_priv = NULL;
-	}
-	fields[1].in_check_value = NULL;
-	fields[1].in_check_mask = NULL;
-
-	jtag_add_dr_scan(2, fields, -1, NULL);
-
-	return ERROR_OK;
-}
-
-/* scan_inout_check adds one extra inscan for DPAP_READ commands to read variables */ 
-int scan_inout_check(swjdp_common_t *swjdp, u8 instr, u8 reg_addr, u8 RnW, u8 *outvalue, u8 *invalue)
-{
-	swjdp_scan(swjdp->jtag_info, instr, reg_addr, RnW, outvalue, NULL, NULL);
-	if ((RnW == DPAP_READ) && (invalue != NULL))
-	{
-		swjdp_scan(swjdp->jtag_info, SWJDP_IR_DPACC, 0xC, DPAP_READ, 0, invalue, &swjdp->ack);
-	}
-	
-	/* In TRANS_MODE_ATOMIC all SWJDP_IR_APACC transactions wait for ack=OK/FAULT and the check CTRL_STAT */
-	if ((instr == SWJDP_IR_APACC) && (swjdp->trans_mode == TRANS_MODE_ATOMIC))
-	{
-		return swjdp_transaction_endcheck(swjdp);
-	}
-
-	return ERROR_OK;
-}
-
-int scan_inout_check_u32(swjdp_common_t *swjdp, u8 instr, u8 reg_addr, u8 RnW, u32 outvalue, u32 *invalue)
-{
-
-	swjdp_scan_u32(swjdp->jtag_info, instr, reg_addr, RnW, outvalue, NULL, NULL);
-	if ((RnW==DPAP_READ) && (invalue != NULL))
-	{
-		swjdp_scan_u32(swjdp->jtag_info, SWJDP_IR_DPACC, 0xC, DPAP_READ, 0, invalue, &swjdp->ack);
-	}
-	
-	/* In TRANS_MODE_ATOMIC all SWJDP_IR_APACC transactions wait for ack=OK/FAULT and then check CTRL_STAT */
-	if ((instr == SWJDP_IR_APACC) && (swjdp->trans_mode == TRANS_MODE_ATOMIC))
-	{
-		return swjdp_transaction_endcheck(swjdp);
-	}
-
-	return ERROR_OK;
-}
-
-int swjdp_transaction_endcheck(swjdp_common_t *swjdp)
-{
-	int waitcount = 0;
-	u32 ctrlstat;
-
-	scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
-	scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
-	jtag_execute_queue();
-	
-	swjdp->ack = swjdp->ack & 0x7;
-	
-	while (swjdp->ack != 2)
-	{
-		if (swjdp->ack == 1)
-		{
-			waitcount++;
-			if (waitcount > 100)
-			{
-				WARNING("Timeout waiting for ACK = OK/FAULT in SWJDP transaction");
-
-				return ERROR_JTAG_DEVICE_ERROR;
-			}
-		}
-		else
-		{
-			WARNING("Invalid ACK in SWJDP transaction");
-			return ERROR_JTAG_DEVICE_ERROR;
-		}
-
-		scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
-		jtag_execute_queue();
-		swjdp->ack = swjdp->ack & 0x7;
-	}
-
-	/* Check for STICKYERR and STICKYORUN */
-	if (ctrlstat & (SSTICKYORUN | SSTICKYERR))
-	{
-		DEBUG("swjdp: CTRL/STAT error 0x%x", ctrlstat);
-		/* Check power to debug regions */
-		if ((ctrlstat & 0xf0000000) != 0xf0000000)
-		{
-			 ahbap_debugport_init(swjdp);
-		}
-		else
-		{
-			u32 dcb_dhcsr,nvic_shcsr, nvic_bfar, nvic_cfsr;
-			
-			if (ctrlstat & SSTICKYORUN)
-				ERROR("SWJ-DP OVERRUN - check clock or reduce jtag speed");
-			
-			if (ctrlstat & SSTICKYERR)
-				ERROR("SWJ-DP STICKY ERROR");
-			
-			/* Clear Sticky Error Bits */
-			scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_WRITE, swjdp->dp_ctrl_stat | SSTICKYORUN | SSTICKYERR, NULL);
-			scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
-			jtag_execute_queue();
-
-			DEBUG("swjdp: status 0x%x", ctrlstat);
-			
-			/* Can we find out the reason for the error ?? */			
-			ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &dcb_dhcsr);
-			ahbap_read_system_atomic_u32(swjdp, NVIC_SHCSR, &nvic_shcsr);
-			ahbap_read_system_atomic_u32(swjdp, NVIC_CFSR, &nvic_cfsr);
-			ahbap_read_system_atomic_u32(swjdp, NVIC_BFAR, &nvic_bfar);
-			ERROR("dcb_dhcsr 0x%x, nvic_shcsr 0x%x, nvic_cfsr 0x%x, nvic_bfar 0x%x", dcb_dhcsr, nvic_shcsr, nvic_cfsr, nvic_bfar);
-		}
-		jtag_execute_queue();
-		return ERROR_JTAG_DEVICE_ERROR;
-	}
-
-	return ERROR_OK;
-}
-
-/***************************************************************************
- *                                                                         *
- * DP and AHB-AP  register access  through APACC and DPACC                 *
- *                                                                         *
-***************************************************************************/
-
-int swjdp_write_dpacc(swjdp_common_t *swjdp, u32 value, u8 reg_addr)
-{
-	u8 out_value_buf[4];
-	
-	buf_set_u32(out_value_buf, 0, 32, value);
-	return scan_inout_check(swjdp, SWJDP_IR_DPACC, reg_addr, DPAP_WRITE, out_value_buf, NULL);
-}
-
-int swjdp_read_dpacc(swjdp_common_t *swjdp, u32 *value, u8 reg_addr)
-{
-	scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, reg_addr, DPAP_READ, 0, value);
-
-    return ERROR_OK;
-}
-
-int swjdp_bankselect_apacc(swjdp_common_t *swjdp,u32 reg_addr)
-{
-	u32 select;
-	select = (reg_addr & 0xFF0000F0);
-
-	if (select != swjdp->dp_select_value)
-	{
-		swjdp_write_dpacc(swjdp, select, DP_SELECT);
-		swjdp->dp_select_value = select;
-	}
-
-	return ERROR_OK;
-}
-
-int ahbap_write_reg(swjdp_common_t *swjdp, u32 reg_addr, u8* out_value_buf)
-{
-	swjdp_bankselect_apacc(swjdp, reg_addr);
-	scan_inout_check(swjdp, SWJDP_IR_APACC, reg_addr, DPAP_WRITE, out_value_buf, NULL);
-
-	return ERROR_OK;
-}
-
-int ahbap_read_reg(swjdp_common_t *swjdp, u32 reg_addr, u8 *in_value_buf)
-{
-	swjdp_bankselect_apacc(swjdp, reg_addr);
-	scan_inout_check(swjdp, SWJDP_IR_APACC, reg_addr, DPAP_READ, 0, in_value_buf);
-
-	return ERROR_OK;
-}
-int ahbap_write_reg_u32(swjdp_common_t *swjdp, u32 reg_addr, u32 value)
-{
-	u8 out_value_buf[4];
-	
-	buf_set_u32(out_value_buf, 0, 32, value);
-	swjdp_bankselect_apacc(swjdp, reg_addr);
-	scan_inout_check(swjdp, SWJDP_IR_APACC, reg_addr, DPAP_WRITE, out_value_buf, NULL);
-
-	return ERROR_OK;
-}
-
-int ahbap_read_reg_u32(swjdp_common_t *swjdp, u32 reg_addr, u32 *value)
-{
-	swjdp_bankselect_apacc(swjdp, reg_addr);
-	scan_inout_check_u32(swjdp, SWJDP_IR_APACC, reg_addr, DPAP_READ, 0, value);
-
-	return ERROR_OK;
-}
-
-/***************************************************************************
- *                                                                         *
- * AHB-AP access to memory and system registers on AHB bus                 *
- *                                                                         *
-***************************************************************************/
-
-int ahbap_setup_accessport(swjdp_common_t *swjdp, u32 csw, u32 tar)
-{
-	csw = csw | CSW_DBGSWENABLE | CSW_MASTER_DEBUG | CSW_HPROT;
-	if (csw != swjdp->ap_csw_value)
-	{
-		//DEBUG("swjdp : Set CSW %x",csw);
-		ahbap_write_reg_u32(swjdp, AHBAP_CSW, csw ); 
-		swjdp->ap_csw_value = csw;
-	}
-	if (tar != swjdp->ap_tar_value)
-	{
-		//DEBUG("swjdp : Set TAR %x",tar);
-		ahbap_write_reg_u32(swjdp, AHBAP_TAR, tar );
-		swjdp->ap_tar_value = tar;
-	}
-	if (csw & CSW_ADDRINC_MASK)
-	{ 	
-		/* Do not cache TAR value when autoincrementing */	
-		swjdp->ap_tar_value = -1;
-	}
-	return ERROR_OK;
-}
-
-/*****************************************************************************
-*                                                                            *
-* ahbap_read_system_u32(swjdp_common_t *swjdp, u32 address, u32 *value)      *
-*                                                                            *
-* Read a u32 value from memory or system register                            *
-* Functionally equivalent to target_read_u32(target, address, u32 *value),   *
-* but with less overhead                                                     *
-*****************************************************************************/
-int ahbap_read_system_u32(swjdp_common_t *swjdp, u32 address, u32 *value)
-{
-	swjdp->trans_mode = TRANS_MODE_COMPOSITE;
-
-	ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, address & 0xFFFFFFF0);
-	ahbap_read_reg_u32(swjdp, AHBAP_BD0 | (address & 0xC), value );
-	
-	return ERROR_OK;
-}
-
-int ahbap_read_system_atomic_u32(swjdp_common_t *swjdp, u32 address, u32 *value)
-{
-	ahbap_read_system_u32(swjdp, address, value);
-	
-	return swjdp_transaction_endcheck(swjdp);
-}
-
-/*****************************************************************************
-*                                                                            *
-* ahbap_write_system_u32(swjdp_common_t *swjdp, u32 address, u32 value)      *
-*                                                                            *
-* Write a u32 value to memory or system register                             *
-*                                                                            *
-*****************************************************************************/
-int ahbap_write_system_u32(swjdp_common_t *swjdp, u32 address, u32 value)
-{
-	swjdp->trans_mode = TRANS_MODE_COMPOSITE;
-
-	ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, address & 0xFFFFFFF0);
-	ahbap_write_reg_u32(swjdp, AHBAP_BD0 | (address & 0xC), value );
-
-	return ERROR_OK;
-}
-
-int ahbap_write_system_atomic_u32(swjdp_common_t *swjdp, u32 address, u32 value)
-{
-	ahbap_write_system_u32(swjdp, address, value);
-	
-	return swjdp_transaction_endcheck(swjdp);
-}
-
-/*****************************************************************************
-*                                                                            *
-* ahbap_write_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address) *
-*                                                                            *
-* Write a buffer in target order (little endian)                             *
-*                                                                            *
-*****************************************************************************/
-int ahbap_write_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)
-{
-	u32 outvalue;
-	int wcount, blocksize, writecount, errorcount = 0, retval = ERROR_OK;
-
-	swjdp->trans_mode = TRANS_MODE_COMPOSITE;
-
-	while ((address & 0x3) && (count > 0))
-	{
-		ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address);
-		outvalue = (*buffer++) << 8 * (address & 0x3);
-		ahbap_write_reg_u32(swjdp, AHBAP_DRW, outvalue );
-		swjdp_transaction_endcheck(swjdp);
-		count--;
-		address++;
-	}
-	wcount = count >> 2;
-	count = count - 4 * wcount;
-	while (wcount > 0)
-	{
-		/* Adjust to write blocks within 4K aligned boundaries */
-		blocksize = (0x1000 - (0xFFF & address)) >> 2;
-		if (wcount < blocksize)
-			blocksize = wcount;
-		ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_SINGLE, address);
-		for (writecount=0; writecount<blocksize; writecount++)
-		{
-			ahbap_write_reg(swjdp, AHBAP_DRW, buffer + 4 * writecount );
-		}
-		if (swjdp_transaction_endcheck(swjdp) == ERROR_OK)
-		{
-			wcount = wcount - blocksize;
-			address = address + 4 * blocksize;
-			buffer = buffer + 4 * blocksize;
-		}
-		else
-		{
-			errorcount++;
-		}
-		if (errorcount > 1)
-		{
-			WARNING("Block write error address 0x%x, wcount 0x%x", address, wcount);
-			return ERROR_JTAG_DEVICE_ERROR;
-		}
-	}
-	
-	while (count > 0)
-	{
-		ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address);
-		outvalue = (*buffer++) << 8 * (address & 0x3);
-		ahbap_write_reg_u32(swjdp, AHBAP_DRW, outvalue );
-		retval = swjdp_transaction_endcheck(swjdp);
-		count--;
-		address++;
-	}
-
-	return retval;
-}
-
-int ahbap_write_buf_u16(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)
-{
-	u32 outvalue;
-	int retval = ERROR_OK;
-	
-	swjdp->trans_mode = TRANS_MODE_COMPOSITE;
-	
-	while (count > 0)
-	{
-		ahbap_setup_accessport(swjdp, CSW_16BIT | CSW_ADDRINC_SINGLE, address);
-		outvalue = *((u16*)buffer) << 8 * (address & 0x3);
-		ahbap_write_reg_u32(swjdp, AHBAP_DRW, outvalue );
-		retval = swjdp_transaction_endcheck(swjdp);
-		count -= 2;
-		address += 2;
-		buffer += 2;
-	}
-
-	return retval;
-}
-
-/*****************************************************************************
-*                                                                            *
-* ahbap_read_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)  *
-*                                                                            *
-* Read block fast in target order (little endian) into a buffer       *
-*                                                                            *
-*****************************************************************************/
-int ahbap_read_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)
-{
-	u32 invalue;
-	int wcount, blocksize, readcount, errorcount = 0, retval = ERROR_OK;
-
-	swjdp->trans_mode = TRANS_MODE_COMPOSITE;
-
-	while ((address & 0x3) && (count > 0))
-	{
-		ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address);
-		ahbap_read_reg_u32(swjdp, AHBAP_DRW, &invalue);
-		swjdp_transaction_endcheck(swjdp);
-		*buffer++ = (invalue >> 8 * (address & 0x3)) & 0xFF;
-		count--;
-		address++;
-	}
-	wcount = count >> 2;
-	count = count - 4 * wcount;
-	while (wcount > 0)
-	{
-		/* Adjust to read within 4K block boundaries */
-		blocksize = (0x1000 - (0xFFF & address)) >> 2;
-		if (wcount < blocksize)
-			blocksize = wcount;
-		ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_SINGLE, address);
-		/* Scan out first read */
-		swjdp_scan(swjdp->jtag_info, SWJDP_IR_APACC, AHBAP_DRW, DPAP_READ, 0, NULL, NULL);
-		for (readcount = 0; readcount < blocksize - 1; readcount++)
-		{
-			/* Scan out read instruction and scan in previous value */
-			swjdp_scan(swjdp->jtag_info, SWJDP_IR_APACC, AHBAP_DRW, DPAP_READ, 0, buffer + 4 * readcount, &swjdp->ack);
-		}
-		/* Scan in last value */
-		swjdp_scan(swjdp->jtag_info, SWJDP_IR_DPACC, 0xC, DPAP_READ, 0, buffer + 4 * readcount, &swjdp->ack);
-		if (swjdp_transaction_endcheck(swjdp) == ERROR_OK)
-		{
-			wcount = wcount - blocksize;
-			address += 4 * blocksize;
-			buffer += 4 * blocksize; 
-		}
-		else
-		{
-			errorcount++;
-		}
-		if (errorcount > 1)
-		{
-			WARNING("Block read error address 0x%x, count 0x%x", address, count);
-			return ERROR_JTAG_DEVICE_ERROR;
-		}
-	}
-
-	while (count > 0)
-	{
-		ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address);
-		ahbap_read_reg_u32(swjdp, AHBAP_DRW, &invalue );
-		retval = swjdp_transaction_endcheck(swjdp);
-		*buffer++ = (invalue >> 8 * (address & 0x3)) & 0xFF;
-		count--;
-		address++;
-	}
-
-	return retval;
-}
-
-int ahbap_read_buf_u16(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)
-{
-	u32 invalue;
-	int retval = ERROR_OK;
-	
-	swjdp->trans_mode = TRANS_MODE_COMPOSITE;
-	
-	while (count > 0)
-	{
-		ahbap_setup_accessport(swjdp, CSW_16BIT | CSW_ADDRINC_SINGLE, address);
-		ahbap_read_reg_u32(swjdp, AHBAP_DRW, &invalue );
-		retval = swjdp_transaction_endcheck(swjdp);
-		*((u16*)buffer) = (invalue >> 8 * (address & 0x3));
-		count -= 2;
-		address += 2;
-		buffer += 2;
-	}
-
-	return retval;
-}
-
-int ahbap_block_read_u32(swjdp_common_t *swjdp, u32 *buffer, int count, u32 address)
-{
-	int readcount, errorcount = 0;
-	u32 blocksize;
-	
-	swjdp->trans_mode = TRANS_MODE_COMPOSITE;
-	
-	while (count > 0)
-	{
-		/* Adjust to read within 4K block boundaries */
-		blocksize = (0x1000 - (0xFFF & address)) >> 2;
-		if (count < blocksize)
-			blocksize = count;
-		ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_SINGLE, address);
-		for (readcount = 0; readcount < blocksize; readcount++)
-		{
-			ahbap_read_reg_u32(swjdp, AHBAP_DRW, buffer + readcount );
-		}
-		if (swjdp_transaction_endcheck(swjdp) == ERROR_OK)
-		{
-			count = count - blocksize;
-			address = address + 4 * blocksize;
-			buffer = buffer + blocksize;
-		}
-		else
-		{
-			errorcount++;
-		}
-		if (errorcount > 1)
-		{
-			WARNING("Block read error address 0x%x, count 0x%x", address, count);
-			return ERROR_JTAG_DEVICE_ERROR;
-		}
-	}
-
-	return ERROR_OK;
-}
-
-int ahbap_read_coreregister_u32(swjdp_common_t *swjdp, u32 *value, int regnum)
-{
-	int retval;
-	u32 dcrdr;
-	
-	ahbap_read_system_atomic_u32(swjdp, DCB_DCRDR, &dcrdr);
-	
-	swjdp->trans_mode = TRANS_MODE_COMPOSITE;
-
-	/* ahbap_write_system_u32(swjdp, DCB_DCRSR, regnum); */
-	ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRSR & 0xFFFFFFF0);
-	ahbap_write_reg_u32(swjdp, AHBAP_BD0 | (DCB_DCRSR & 0xC), regnum );
-
-	/* ahbap_read_system_u32(swjdp, DCB_DCRDR, value); */
-	ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRDR & 0xFFFFFFF0);
-	ahbap_read_reg_u32(swjdp, AHBAP_BD0 | (DCB_DCRDR & 0xC), value );
-	
-	retval = swjdp_transaction_endcheck(swjdp);
-	ahbap_write_system_atomic_u32(swjdp, DCB_DCRDR, dcrdr);
-	return retval;
-}
-
-int ahbap_write_coreregister_u32(swjdp_common_t *swjdp, u32 value, int regnum)
-{
-	int retval;
-	u32 dcrdr;
-	
-	ahbap_read_system_atomic_u32(swjdp, DCB_DCRDR, &dcrdr);
-	
-	swjdp->trans_mode = TRANS_MODE_COMPOSITE;
-	
-	/* ahbap_write_system_u32(swjdp, DCB_DCRDR, core_regs[i]); */
-	ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRDR & 0xFFFFFFF0);
-	ahbap_write_reg_u32(swjdp, AHBAP_BD0 | (DCB_DCRDR & 0xC), value );
-
-	/* ahbap_write_system_u32(swjdp, DCB_DCRSR, i | DCRSR_WnR	); */
-	ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRSR & 0xFFFFFFF0);
-	ahbap_write_reg_u32(swjdp, AHBAP_BD0 | (DCB_DCRSR & 0xC), regnum | DCRSR_WnR );
-	
-	retval = swjdp_transaction_endcheck(swjdp);
-	ahbap_write_system_atomic_u32(swjdp, DCB_DCRDR, dcrdr);
-	return retval;
-}
-
-int ahbap_debugport_init(swjdp_common_t *swjdp)
-{
-	u32 idreg, romaddr, dummy;
-	u32 ctrlstat;
-	int cnt = 0;
-	
-	DEBUG(" ");
-	
-	swjdp->ap_csw_value = -1;
-	swjdp->ap_tar_value = -1;
-	swjdp->trans_mode = TRANS_MODE_ATOMIC;
-	swjdp_read_dpacc(swjdp, &dummy, DP_CTRL_STAT);
-	swjdp_write_dpacc(swjdp, SSTICKYERR, DP_CTRL_STAT);
-	swjdp_read_dpacc(swjdp, &dummy, DP_CTRL_STAT);
-	
-	swjdp->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ;
-
-	swjdp_write_dpacc(swjdp, swjdp->dp_ctrl_stat, DP_CTRL_STAT);
-	swjdp_read_dpacc(swjdp, &ctrlstat, DP_CTRL_STAT);
-	jtag_execute_queue();
-
-	/* Check that we have debug power domains activated */
-	while (!(ctrlstat & CDBGPWRUPACK) && (cnt++ < 10))
-	{
-		DEBUG("swjdp: wait CDBGPWRUPACK");
-		swjdp_read_dpacc(swjdp, &ctrlstat, DP_CTRL_STAT);
-		jtag_execute_queue();
-		usleep(10000);
-	}
-
-	while (!(ctrlstat & CSYSPWRUPACK) && (cnt++ < 10))
-	{
-		DEBUG("swjdp: wait CSYSPWRUPACK");
-		swjdp_read_dpacc(swjdp, &ctrlstat, DP_CTRL_STAT);
-		jtag_execute_queue();
-		usleep(10000);
-	}
-
-	swjdp_read_dpacc(swjdp, &dummy, DP_CTRL_STAT);
-	/* With debug power on we can activate OVERRUN checking */
-	swjdp->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ | CORUNDETECT;
-	swjdp_write_dpacc(swjdp, swjdp->dp_ctrl_stat , DP_CTRL_STAT);
-	swjdp_read_dpacc(swjdp, &dummy, DP_CTRL_STAT);
-	
-	ahbap_read_reg_u32(swjdp, 0xFC, &idreg);
-	ahbap_read_reg_u32(swjdp, 0xF8, &romaddr);
-	
-	DEBUG("AHB-AP ID Register 0x%x, Debug ROM Address 0x%x", idreg, romaddr);	
-	
-	return ERROR_OK;
-}
+/***************************************************************************
+ *   Copyright (C) 2006 by Magnus Lundin                                   *
+ *   lundin@mlu.mine.nu                                                    *
+ *                                                                         *
+ *   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.             *
+ ***************************************************************************/
+/***************************************************************************
+ *                                                                         *
+ * CoreSight (Light?) SerialWireJtagDebugPort                              *
+ *                                                                         *
+ * CoreSightâ„¢ DAP-Lite TRM, ARM DDI 0316A                                  *
+ * Cortex-M3â„¢ TRM, ARM DDI 0337C                                            *
+ *                                                                         *
+***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "replacements.h"
+
+#include "cortex_m3.h"
+#include "cortex_swjdp.h"
+#include "jtag.h"
+#include "log.h"
+#include <stdlib.h>
+
+/*
+
+Transaction Mode:
+swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+Uses Overrun checking mode and does not do actual JTAG send/receive or transaction 
+result checking until swjdp_end_transaction()
+This must be done before using or deallocating any return variables.
+
+swjdp->trans_mode == TRANS_MODE_ATOMIC
+All reads and writes to the AHB bus are checked for valid completion, and return values
+are immediatley available.
+
+*/
+
+/***************************************************************************
+ *                                                                         *
+ * DPACC and APACC scanchain access through JTAG-DR                        *
+ *                                                                         *
+***************************************************************************/
+
+/* Scan out and in from target ordered u8 buffers */
+int swjdp_scan(arm_jtag_t *jtag_info, u8 instr, u8 reg_addr, u8 RnW, u8 *outvalue, u8 *invalue, u8 *ack)
+{
+	scan_field_t fields[2];
+	u8 out_addr_buf;
+	
+	jtag_add_end_state(TAP_RTI);
+	arm_jtag_set_instr(jtag_info, instr, NULL);
+
+	fields[0].device = jtag_info->chain_pos;
+	fields[0].num_bits = 3;
+	buf_set_u32(&out_addr_buf, 0, 3, ((reg_addr >> 1) & 0x6) | (RnW & 0x1));
+	fields[0].out_value = &out_addr_buf;
+	fields[0].out_mask = NULL;
+	fields[0].in_value = ack;
+	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 = jtag_info->chain_pos;
+	fields[1].num_bits = 32;
+	fields[1].out_value = outvalue;
+	fields[1].out_mask = NULL;
+	fields[1].in_value = invalue;
+	fields[1].in_handler = NULL;
+	fields[1].in_handler_priv = NULL;
+	fields[1].in_check_value = NULL;
+	fields[1].in_check_mask = NULL;
+
+	jtag_add_dr_scan(2, fields, -1);
+
+	return ERROR_OK;
+}
+
+/* Scan out and in from host ordered u32 variables */
+int swjdp_scan_u32(arm_jtag_t *jtag_info, u8 instr, u8 reg_addr, u8 RnW, u32 outvalue, u32 *invalue, u8 *ack)
+{
+	scan_field_t fields[2];
+	u8 out_value_buf[4];
+	u8 out_addr_buf;
+	
+	jtag_add_end_state(TAP_RTI);
+	arm_jtag_set_instr(jtag_info, instr, NULL);
+
+	fields[0].device = jtag_info->chain_pos;
+	fields[0].num_bits = 3;
+	buf_set_u32(&out_addr_buf, 0, 3, ((reg_addr >> 1) & 0x6) | (RnW & 0x1));
+	fields[0].out_value = &out_addr_buf;
+	fields[0].out_mask = NULL;
+	fields[0].in_value = ack;
+	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 = jtag_info->chain_pos;
+	fields[1].num_bits = 32;
+	buf_set_u32(out_value_buf, 0, 32, outvalue);
+	fields[1].out_value = out_value_buf;
+	fields[1].out_mask = NULL;
+	fields[1].in_value = NULL;
+	if (invalue)
+	{
+		fields[1].in_handler = arm_jtag_buf_to_u32;
+		fields[1].in_handler_priv = invalue;
+	}
+	else
+	{
+		fields[1].in_handler = NULL;
+		fields[1].in_handler_priv = NULL;
+	}
+	fields[1].in_check_value = NULL;
+	fields[1].in_check_mask = NULL;
+
+	jtag_add_dr_scan(2, fields, -1);
+
+	return ERROR_OK;
+}
+
+/* scan_inout_check adds one extra inscan for DPAP_READ commands to read variables */ 
+int scan_inout_check(swjdp_common_t *swjdp, u8 instr, u8 reg_addr, u8 RnW, u8 *outvalue, u8 *invalue)
+{
+	swjdp_scan(swjdp->jtag_info, instr, reg_addr, RnW, outvalue, NULL, NULL);
+	if ((RnW == DPAP_READ) && (invalue != NULL))
+	{
+		swjdp_scan(swjdp->jtag_info, SWJDP_IR_DPACC, 0xC, DPAP_READ, 0, invalue, &swjdp->ack);
+	}
+	
+	/* In TRANS_MODE_ATOMIC all SWJDP_IR_APACC transactions wait for ack=OK/FAULT and the check CTRL_STAT */
+	if ((instr == SWJDP_IR_APACC) && (swjdp->trans_mode == TRANS_MODE_ATOMIC))
+	{
+		return swjdp_transaction_endcheck(swjdp);
+	}
+
+	return ERROR_OK;
+}
+
+int scan_inout_check_u32(swjdp_common_t *swjdp, u8 instr, u8 reg_addr, u8 RnW, u32 outvalue, u32 *invalue)
+{
+
+	swjdp_scan_u32(swjdp->jtag_info, instr, reg_addr, RnW, outvalue, NULL, NULL);
+	if ((RnW==DPAP_READ) && (invalue != NULL))
+	{
+		swjdp_scan_u32(swjdp->jtag_info, SWJDP_IR_DPACC, 0xC, DPAP_READ, 0, invalue, &swjdp->ack);
+	}
+	
+	/* In TRANS_MODE_ATOMIC all SWJDP_IR_APACC transactions wait for ack=OK/FAULT and then check CTRL_STAT */
+	if ((instr == SWJDP_IR_APACC) && (swjdp->trans_mode == TRANS_MODE_ATOMIC))
+	{
+		return swjdp_transaction_endcheck(swjdp);
+	}
+
+	return ERROR_OK;
+}
+
+int swjdp_transaction_endcheck(swjdp_common_t *swjdp)
+{
+	int waitcount = 0;
+	u32 ctrlstat;
+
+	scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
+	scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
+	jtag_execute_queue();
+	
+	swjdp->ack = swjdp->ack & 0x7;
+	
+	while (swjdp->ack != 2)
+	{
+		if (swjdp->ack == 1)
+		{
+			waitcount++;
+			if (waitcount > 100)
+			{
+				WARNING("Timeout waiting for ACK = OK/FAULT in SWJDP transaction");
+
+				return ERROR_JTAG_DEVICE_ERROR;
+			}
+		}
+		else
+		{
+			WARNING("Invalid ACK in SWJDP transaction");
+			return ERROR_JTAG_DEVICE_ERROR;
+		}
+
+		scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
+		jtag_execute_queue();
+		swjdp->ack = swjdp->ack & 0x7;
+	}
+
+	/* Check for STICKYERR and STICKYORUN */
+	if (ctrlstat & (SSTICKYORUN | SSTICKYERR))
+	{
+		DEBUG("swjdp: CTRL/STAT error 0x%x", ctrlstat);
+		/* Check power to debug regions */
+		if ((ctrlstat & 0xf0000000) != 0xf0000000)
+		{
+			 ahbap_debugport_init(swjdp);
+		}
+		else
+		{
+			u32 dcb_dhcsr,nvic_shcsr, nvic_bfar, nvic_cfsr;
+			
+			if (ctrlstat & SSTICKYORUN)
+				ERROR("SWJ-DP OVERRUN - check clock or reduce jtag speed");
+			
+			if (ctrlstat & SSTICKYERR)
+				ERROR("SWJ-DP STICKY ERROR");
+			
+			/* Clear Sticky Error Bits */
+			scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_WRITE, swjdp->dp_ctrl_stat | SSTICKYORUN | SSTICKYERR, NULL);
+			scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat);
+			jtag_execute_queue();
+
+			DEBUG("swjdp: status 0x%x", ctrlstat);
+			
+			/* Can we find out the reason for the error ?? */			
+			ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &dcb_dhcsr);
+			ahbap_read_system_atomic_u32(swjdp, NVIC_SHCSR, &nvic_shcsr);
+			ahbap_read_system_atomic_u32(swjdp, NVIC_CFSR, &nvic_cfsr);
+			ahbap_read_system_atomic_u32(swjdp, NVIC_BFAR, &nvic_bfar);
+			ERROR("dcb_dhcsr 0x%x, nvic_shcsr 0x%x, nvic_cfsr 0x%x, nvic_bfar 0x%x", dcb_dhcsr, nvic_shcsr, nvic_cfsr, nvic_bfar);
+		}
+		jtag_execute_queue();
+		return ERROR_JTAG_DEVICE_ERROR;
+	}
+
+	return ERROR_OK;
+}
+
+/***************************************************************************
+ *                                                                         *
+ * DP and AHB-AP  register access  through APACC and DPACC                 *
+ *                                                                         *
+***************************************************************************/
+
+int swjdp_write_dpacc(swjdp_common_t *swjdp, u32 value, u8 reg_addr)
+{
+	u8 out_value_buf[4];
+	
+	buf_set_u32(out_value_buf, 0, 32, value);
+	return scan_inout_check(swjdp, SWJDP_IR_DPACC, reg_addr, DPAP_WRITE, out_value_buf, NULL);
+}
+
+int swjdp_read_dpacc(swjdp_common_t *swjdp, u32 *value, u8 reg_addr)
+{
+	scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, reg_addr, DPAP_READ, 0, value);
+
+    return ERROR_OK;
+}
+
+int swjdp_bankselect_apacc(swjdp_common_t *swjdp,u32 reg_addr)
+{
+	u32 select;
+	select = (reg_addr & 0xFF0000F0);
+
+	if (select != swjdp->dp_select_value)
+	{
+		swjdp_write_dpacc(swjdp, select, DP_SELECT);
+		swjdp->dp_select_value = select;
+	}
+
+	return ERROR_OK;
+}
+
+int ahbap_write_reg(swjdp_common_t *swjdp, u32 reg_addr, u8* out_value_buf)
+{
+	swjdp_bankselect_apacc(swjdp, reg_addr);
+	scan_inout_check(swjdp, SWJDP_IR_APACC, reg_addr, DPAP_WRITE, out_value_buf, NULL);
+
+	return ERROR_OK;
+}
+
+int ahbap_read_reg(swjdp_common_t *swjdp, u32 reg_addr, u8 *in_value_buf)
+{
+	swjdp_bankselect_apacc(swjdp, reg_addr);
+	scan_inout_check(swjdp, SWJDP_IR_APACC, reg_addr, DPAP_READ, 0, in_value_buf);
+
+	return ERROR_OK;
+}
+int ahbap_write_reg_u32(swjdp_common_t *swjdp, u32 reg_addr, u32 value)
+{
+	u8 out_value_buf[4];
+	
+	buf_set_u32(out_value_buf, 0, 32, value);
+	swjdp_bankselect_apacc(swjdp, reg_addr);
+	scan_inout_check(swjdp, SWJDP_IR_APACC, reg_addr, DPAP_WRITE, out_value_buf, NULL);
+
+	return ERROR_OK;
+}
+
+int ahbap_read_reg_u32(swjdp_common_t *swjdp, u32 reg_addr, u32 *value)
+{
+	swjdp_bankselect_apacc(swjdp, reg_addr);
+	scan_inout_check_u32(swjdp, SWJDP_IR_APACC, reg_addr, DPAP_READ, 0, value);
+
+	return ERROR_OK;
+}
+
+/***************************************************************************
+ *                                                                         *
+ * AHB-AP access to memory and system registers on AHB bus                 *
+ *                                                                         *
+***************************************************************************/
+
+int ahbap_setup_accessport(swjdp_common_t *swjdp, u32 csw, u32 tar)
+{
+	csw = csw | CSW_DBGSWENABLE | CSW_MASTER_DEBUG | CSW_HPROT;
+	if (csw != swjdp->ap_csw_value)
+	{
+		//DEBUG("swjdp : Set CSW %x",csw);
+		ahbap_write_reg_u32(swjdp, AHBAP_CSW, csw ); 
+		swjdp->ap_csw_value = csw;
+	}
+	if (tar != swjdp->ap_tar_value)
+	{
+		//DEBUG("swjdp : Set TAR %x",tar);
+		ahbap_write_reg_u32(swjdp, AHBAP_TAR, tar );
+		swjdp->ap_tar_value = tar;
+	}
+	if (csw & CSW_ADDRINC_MASK)
+	{ 	
+		/* Do not cache TAR value when autoincrementing */	
+		swjdp->ap_tar_value = -1;
+	}
+	return ERROR_OK;
+}
+
+/*****************************************************************************
+*                                                                            *
+* ahbap_read_system_u32(swjdp_common_t *swjdp, u32 address, u32 *value)      *
+*                                                                            *
+* Read a u32 value from memory or system register                            *
+* Functionally equivalent to target_read_u32(target, address, u32 *value),   *
+* but with less overhead                                                     *
+*****************************************************************************/
+int ahbap_read_system_u32(swjdp_common_t *swjdp, u32 address, u32 *value)
+{
+	swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+
+	ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, address & 0xFFFFFFF0);
+	ahbap_read_reg_u32(swjdp, AHBAP_BD0 | (address & 0xC), value );
+	
+	return ERROR_OK;
+}
+
+int ahbap_read_system_atomic_u32(swjdp_common_t *swjdp, u32 address, u32 *value)
+{
+	ahbap_read_system_u32(swjdp, address, value);
+	
+	return swjdp_transaction_endcheck(swjdp);
+}
+
+/*****************************************************************************
+*                                                                            *
+* ahbap_write_system_u32(swjdp_common_t *swjdp, u32 address, u32 value)      *
+*                                                                            *
+* Write a u32 value to memory or system register                             *
+*                                                                            *
+*****************************************************************************/
+int ahbap_write_system_u32(swjdp_common_t *swjdp, u32 address, u32 value)
+{
+	swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+
+	ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, address & 0xFFFFFFF0);
+	ahbap_write_reg_u32(swjdp, AHBAP_BD0 | (address & 0xC), value );
+
+	return ERROR_OK;
+}
+
+int ahbap_write_system_atomic_u32(swjdp_common_t *swjdp, u32 address, u32 value)
+{
+	ahbap_write_system_u32(swjdp, address, value);
+	
+	return swjdp_transaction_endcheck(swjdp);
+}
+
+/*****************************************************************************
+*                                                                            *
+* ahbap_write_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address) *
+*                                                                            *
+* Write a buffer in target order (little endian)                             *
+*                                                                            *
+*****************************************************************************/
+int ahbap_write_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)
+{
+	u32 outvalue;
+	int wcount, blocksize, writecount, errorcount = 0, retval = ERROR_OK;
+
+	swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+
+	while ((address & 0x3) && (count > 0))
+	{
+		ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address);
+		outvalue = (*buffer++) << 8 * (address & 0x3);
+		ahbap_write_reg_u32(swjdp, AHBAP_DRW, outvalue );
+		swjdp_transaction_endcheck(swjdp);
+		count--;
+		address++;
+	}
+	wcount = count >> 2;
+	count = count - 4 * wcount;
+	while (wcount > 0)
+	{
+		/* Adjust to write blocks within 4K aligned boundaries */
+		blocksize = (0x1000 - (0xFFF & address)) >> 2;
+		if (wcount < blocksize)
+			blocksize = wcount;
+		ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_SINGLE, address);
+		for (writecount=0; writecount<blocksize; writecount++)
+		{
+			ahbap_write_reg(swjdp, AHBAP_DRW, buffer + 4 * writecount );
+		}
+		if (swjdp_transaction_endcheck(swjdp) == ERROR_OK)
+		{
+			wcount = wcount - blocksize;
+			address = address + 4 * blocksize;
+			buffer = buffer + 4 * blocksize;
+		}
+		else
+		{
+			errorcount++;
+		}
+		if (errorcount > 1)
+		{
+			WARNING("Block write error address 0x%x, wcount 0x%x", address, wcount);
+			return ERROR_JTAG_DEVICE_ERROR;
+		}
+	}
+	
+	while (count > 0)
+	{
+		ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address);
+		outvalue = (*buffer++) << 8 * (address & 0x3);
+		ahbap_write_reg_u32(swjdp, AHBAP_DRW, outvalue );
+		retval = swjdp_transaction_endcheck(swjdp);
+		count--;
+		address++;
+	}
+
+	return retval;
+}
+
+int ahbap_write_buf_u16(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)
+{
+	u32 outvalue;
+	int retval = ERROR_OK;
+	
+	swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+	
+	while (count > 0)
+	{
+		ahbap_setup_accessport(swjdp, CSW_16BIT | CSW_ADDRINC_SINGLE, address);
+		outvalue = *((u16*)buffer) << 8 * (address & 0x3);
+		ahbap_write_reg_u32(swjdp, AHBAP_DRW, outvalue );
+		retval = swjdp_transaction_endcheck(swjdp);
+		count -= 2;
+		address += 2;
+		buffer += 2;
+	}
+
+	return retval;
+}
+
+/*****************************************************************************
+*                                                                            *
+* ahbap_read_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)  *
+*                                                                            *
+* Read block fast in target order (little endian) into a buffer       *
+*                                                                            *
+*****************************************************************************/
+int ahbap_read_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)
+{
+	u32 invalue;
+	int wcount, blocksize, readcount, errorcount = 0, retval = ERROR_OK;
+
+	swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+
+	while ((address & 0x3) && (count > 0))
+	{
+		ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address);
+		ahbap_read_reg_u32(swjdp, AHBAP_DRW, &invalue);
+		swjdp_transaction_endcheck(swjdp);
+		*buffer++ = (invalue >> 8 * (address & 0x3)) & 0xFF;
+		count--;
+		address++;
+	}
+	wcount = count >> 2;
+	count = count - 4 * wcount;
+	while (wcount > 0)
+	{
+		/* Adjust to read within 4K block boundaries */
+		blocksize = (0x1000 - (0xFFF & address)) >> 2;
+		if (wcount < blocksize)
+			blocksize = wcount;
+		ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_SINGLE, address);
+		/* Scan out first read */
+		swjdp_scan(swjdp->jtag_info, SWJDP_IR_APACC, AHBAP_DRW, DPAP_READ, 0, NULL, NULL);
+		for (readcount = 0; readcount < blocksize - 1; readcount++)
+		{
+			/* Scan out read instruction and scan in previous value */
+			swjdp_scan(swjdp->jtag_info, SWJDP_IR_APACC, AHBAP_DRW, DPAP_READ, 0, buffer + 4 * readcount, &swjdp->ack);
+		}
+		/* Scan in last value */
+		swjdp_scan(swjdp->jtag_info, SWJDP_IR_DPACC, 0xC, DPAP_READ, 0, buffer + 4 * readcount, &swjdp->ack);
+		if (swjdp_transaction_endcheck(swjdp) == ERROR_OK)
+		{
+			wcount = wcount - blocksize;
+			address += 4 * blocksize;
+			buffer += 4 * blocksize; 
+		}
+		else
+		{
+			errorcount++;
+		}
+		if (errorcount > 1)
+		{
+			WARNING("Block read error address 0x%x, count 0x%x", address, count);
+			return ERROR_JTAG_DEVICE_ERROR;
+		}
+	}
+
+	while (count > 0)
+	{
+		ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address);
+		ahbap_read_reg_u32(swjdp, AHBAP_DRW, &invalue );
+		retval = swjdp_transaction_endcheck(swjdp);
+		*buffer++ = (invalue >> 8 * (address & 0x3)) & 0xFF;
+		count--;
+		address++;
+	}
+
+	return retval;
+}
+
+int ahbap_read_buf_u16(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address)
+{
+	u32 invalue;
+	int retval = ERROR_OK;
+	
+	swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+	
+	while (count > 0)
+	{
+		ahbap_setup_accessport(swjdp, CSW_16BIT | CSW_ADDRINC_SINGLE, address);
+		ahbap_read_reg_u32(swjdp, AHBAP_DRW, &invalue );
+		retval = swjdp_transaction_endcheck(swjdp);
+		*((u16*)buffer) = (invalue >> 8 * (address & 0x3));
+		count -= 2;
+		address += 2;
+		buffer += 2;
+	}
+
+	return retval;
+}
+
+int ahbap_block_read_u32(swjdp_common_t *swjdp, u32 *buffer, int count, u32 address)
+{
+	int readcount, errorcount = 0;
+	u32 blocksize;
+	
+	swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+	
+	while (count > 0)
+	{
+		/* Adjust to read within 4K block boundaries */
+		blocksize = (0x1000 - (0xFFF & address)) >> 2;
+		if (count < blocksize)
+			blocksize = count;
+		ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_SINGLE, address);
+		for (readcount = 0; readcount < blocksize; readcount++)
+		{
+			ahbap_read_reg_u32(swjdp, AHBAP_DRW, buffer + readcount );
+		}
+		if (swjdp_transaction_endcheck(swjdp) == ERROR_OK)
+		{
+			count = count - blocksize;
+			address = address + 4 * blocksize;
+			buffer = buffer + blocksize;
+		}
+		else
+		{
+			errorcount++;
+		}
+		if (errorcount > 1)
+		{
+			WARNING("Block read error address 0x%x, count 0x%x", address, count);
+			return ERROR_JTAG_DEVICE_ERROR;
+		}
+	}
+
+	return ERROR_OK;
+}
+
+int ahbap_read_coreregister_u32(swjdp_common_t *swjdp, u32 *value, int regnum)
+{
+	int retval;
+	u32 dcrdr;
+	
+	ahbap_read_system_atomic_u32(swjdp, DCB_DCRDR, &dcrdr);
+	
+	swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+
+	/* ahbap_write_system_u32(swjdp, DCB_DCRSR, regnum); */
+	ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRSR & 0xFFFFFFF0);
+	ahbap_write_reg_u32(swjdp, AHBAP_BD0 | (DCB_DCRSR & 0xC), regnum );
+
+	/* ahbap_read_system_u32(swjdp, DCB_DCRDR, value); */
+	ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRDR & 0xFFFFFFF0);
+	ahbap_read_reg_u32(swjdp, AHBAP_BD0 | (DCB_DCRDR & 0xC), value );
+	
+	retval = swjdp_transaction_endcheck(swjdp);
+	ahbap_write_system_atomic_u32(swjdp, DCB_DCRDR, dcrdr);
+	return retval;
+}
+
+int ahbap_write_coreregister_u32(swjdp_common_t *swjdp, u32 value, int regnum)
+{
+	int retval;
+	u32 dcrdr;
+	
+	ahbap_read_system_atomic_u32(swjdp, DCB_DCRDR, &dcrdr);
+	
+	swjdp->trans_mode = TRANS_MODE_COMPOSITE;
+	
+	/* ahbap_write_system_u32(swjdp, DCB_DCRDR, core_regs[i]); */
+	ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRDR & 0xFFFFFFF0);
+	ahbap_write_reg_u32(swjdp, AHBAP_BD0 | (DCB_DCRDR & 0xC), value );
+
+	/* ahbap_write_system_u32(swjdp, DCB_DCRSR, i | DCRSR_WnR	); */
+	ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRSR & 0xFFFFFFF0);
+	ahbap_write_reg_u32(swjdp, AHBAP_BD0 | (DCB_DCRSR & 0xC), regnum | DCRSR_WnR );
+	
+	retval = swjdp_transaction_endcheck(swjdp);
+	ahbap_write_system_atomic_u32(swjdp, DCB_DCRDR, dcrdr);
+	return retval;
+}
+
+int ahbap_debugport_init(swjdp_common_t *swjdp)
+{
+	u32 idreg, romaddr, dummy;
+	u32 ctrlstat;
+	int cnt = 0;
+	
+	DEBUG(" ");
+	
+	swjdp->ap_csw_value = -1;
+	swjdp->ap_tar_value = -1;
+	swjdp->trans_mode = TRANS_MODE_ATOMIC;
+	swjdp_read_dpacc(swjdp, &dummy, DP_CTRL_STAT);
+	swjdp_write_dpacc(swjdp, SSTICKYERR, DP_CTRL_STAT);
+	swjdp_read_dpacc(swjdp, &dummy, DP_CTRL_STAT);
+	
+	swjdp->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ;
+
+	swjdp_write_dpacc(swjdp, swjdp->dp_ctrl_stat, DP_CTRL_STAT);
+	swjdp_read_dpacc(swjdp, &ctrlstat, DP_CTRL_STAT);
+	jtag_execute_queue();
+
+	/* Check that we have debug power domains activated */
+	while (!(ctrlstat & CDBGPWRUPACK) && (cnt++ < 10))
+	{
+		DEBUG("swjdp: wait CDBGPWRUPACK");
+		swjdp_read_dpacc(swjdp, &ctrlstat, DP_CTRL_STAT);
+		jtag_execute_queue();
+		usleep(10000);
+	}
+
+	while (!(ctrlstat & CSYSPWRUPACK) && (cnt++ < 10))
+	{
+		DEBUG("swjdp: wait CSYSPWRUPACK");
+		swjdp_read_dpacc(swjdp, &ctrlstat, DP_CTRL_STAT);
+		jtag_execute_queue();
+		usleep(10000);
+	}
+
+	swjdp_read_dpacc(swjdp, &dummy, DP_CTRL_STAT);
+	/* With debug power on we can activate OVERRUN checking */
+	swjdp->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ | CORUNDETECT;
+	swjdp_write_dpacc(swjdp, swjdp->dp_ctrl_stat , DP_CTRL_STAT);
+	swjdp_read_dpacc(swjdp, &dummy, DP_CTRL_STAT);
+	
+	ahbap_read_reg_u32(swjdp, 0xFC, &idreg);
+	ahbap_read_reg_u32(swjdp, 0xF8, &romaddr);
+	
+	DEBUG("AHB-AP ID Register 0x%x, Debug ROM Address 0x%x", idreg, romaddr);	
+	
+	return ERROR_OK;
+}
diff --git a/src/target/embeddedice.c b/src/target/embeddedice.c
index 3713fe95261b79815af5dfcde9ec4e2cb7af1209..07b965b07ecfa2d3317955e863030cf00d30207d 100644
--- a/src/target/embeddedice.c
+++ b/src/target/embeddedice.c
@@ -1,565 +1,565 @@
-/***************************************************************************
- *   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.             *
- ***************************************************************************/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "embeddedice.h"
-
-#include "armv4_5.h"
-#include "arm7_9_common.h"
-
-#include "log.h"
-#include "arm_jtag.h"
-#include "types.h"
-#include "binarybuffer.h"
-#include "target.h"
-#include "register.h"
-#include "jtag.h"
-
-#include <stdlib.h>
-
-bitfield_desc_t embeddedice_comms_ctrl_bitfield_desc[] = 
-{
-	{"R", 1},
-	{"W", 1},
-	{"reserved", 26},
-	{"version", 4}
-};
-
-int embeddedice_reg_arch_info[] =
-{
-	0x0, 0x1, 0x4, 0x5,
-	0x8, 0x9, 0xa, 0xb, 0xc, 0xd,
-	0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
-	0x2
-};
-
-char* embeddedice_reg_list[] =
-{
-	"debug_ctrl",
-	"debug_status",
-	
-	"comms_ctrl",
-	"comms_data",
-	
-	"watch 0 addr value",
-	"watch 0 addr mask",
-	"watch 0 data value",
-	"watch 0 data mask",
-	"watch 0 control value",
-	"watch 0 control mask",
-	
-	"watch 1 addr value",
-	"watch 1 addr mask",
-	"watch 1 data value",
-	"watch 1 data mask",
-	"watch 1 control value",
-	"watch 1 control mask",
-	
-	"vector catch"
-};
-
-int embeddedice_reg_arch_type = -1;
-
-int embeddedice_get_reg(reg_t *reg);
-int embeddedice_set_reg(reg_t *reg, u32 value);
-int embeddedice_set_reg_w_exec(reg_t *reg, u8 *buf);
-
-int embeddedice_write_reg(reg_t *reg, u32 value);
-int embeddedice_read_reg(reg_t *reg);
-
-reg_cache_t* embeddedice_build_reg_cache(target_t *target, arm7_9_common_t *arm7_9)
-{
-	reg_cache_t *reg_cache = malloc(sizeof(reg_cache_t));
-	reg_t *reg_list = NULL;
-	embeddedice_reg_t *arch_info = NULL;
-	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
-	int num_regs;
-	int i;
-	int eice_version = 0;
-	
-	/* register a register arch-type for EmbeddedICE registers only once */
-	if (embeddedice_reg_arch_type == -1)
-		embeddedice_reg_arch_type = register_reg_arch_type(embeddedice_get_reg, embeddedice_set_reg_w_exec);
-	
-	if (arm7_9->has_vector_catch)
-		num_regs = 17;
-	else
-		num_regs = 16;
-		
-	/* the actual registers are kept in two arrays */
-	reg_list = calloc(num_regs, sizeof(reg_t));
-	arch_info = calloc(num_regs, sizeof(embeddedice_reg_t));
-	
-	/* fill in values for the reg cache */
-	reg_cache->name = "EmbeddedICE registers";
-	reg_cache->next = NULL;
-	reg_cache->reg_list = reg_list;
-	reg_cache->num_regs = num_regs;
-	
-	/* set up registers */
-	for (i = 0; i < num_regs; i++)
-	{
-		reg_list[i].name = embeddedice_reg_list[i];
-		reg_list[i].size = 32;
-		reg_list[i].dirty = 0;
-		reg_list[i].valid = 0;
-		reg_list[i].bitfield_desc = NULL;
-		reg_list[i].num_bitfields = 0;
-		reg_list[i].value = calloc(1, 4);
-		reg_list[i].arch_info = &arch_info[i];
-		reg_list[i].arch_type = embeddedice_reg_arch_type;
-		arch_info[i].addr = embeddedice_reg_arch_info[i];
-		arch_info[i].jtag_info = jtag_info;
-	}
-	
-	/* identify EmbeddedICE version by reading DCC control register */
-	embeddedice_read_reg(&reg_list[EICE_COMMS_CTRL]);
-	jtag_execute_queue();
-	
-	eice_version = buf_get_u32(reg_list[EICE_COMMS_CTRL].value, 28, 4);
-	
-	switch (eice_version)
-	{
-		case 1:
-			reg_list[EICE_DBG_CTRL].size = 3;
-			reg_list[EICE_DBG_STAT].size = 5;
-			break;
-		case 2:
-			reg_list[EICE_DBG_CTRL].size = 4;
-			reg_list[EICE_DBG_STAT].size = 5;
-			arm7_9->has_single_step = 1;
-			break;
-		case 3:
-			ERROR("EmbeddedICE version 3 detected, EmbeddedICE handling might be broken"); 
-			reg_list[EICE_DBG_CTRL].size = 6;
-			reg_list[EICE_DBG_STAT].size = 5;
-			arm7_9->has_single_step = 1;
-			arm7_9->has_monitor_mode = 1;
-			break;
-		case 4:
-			reg_list[EICE_DBG_CTRL].size = 6;
-			reg_list[EICE_DBG_STAT].size = 5;
-			arm7_9->has_monitor_mode = 1;
-			break;
-		case 5:
-			reg_list[EICE_DBG_CTRL].size = 6;
-			reg_list[EICE_DBG_STAT].size = 5;
-			arm7_9->has_single_step = 1;
-			arm7_9->has_monitor_mode = 1;
-			break;
-		case 6:
-			reg_list[EICE_DBG_CTRL].size = 6;
-			reg_list[EICE_DBG_STAT].size = 10;
-			arm7_9->has_monitor_mode = 1;
-			break;
-		case 7:
-			WARNING("EmbeddedICE version 7 detected, EmbeddedICE handling might be broken");
-			reg_list[EICE_DBG_CTRL].size = 6;
-			reg_list[EICE_DBG_STAT].size = 5;
-			arm7_9->has_monitor_mode = 1;
-			break;
-		default:
-			ERROR("unknown EmbeddedICE version (comms ctrl: 0x%8.8x)", buf_get_u32(reg_list[EICE_COMMS_CTRL].value, 0, 32));
-	}
-	
-	/* explicitly disable monitor mode */
-	if (arm7_9->has_monitor_mode)
-	{
-		embeddedice_read_reg(&reg_list[EICE_DBG_CTRL]);
-		jtag_execute_queue();
-		buf_set_u32(reg_list[EICE_DBG_CTRL].value, 4, 1, 0);
-		embeddedice_set_reg_w_exec(&reg_list[EICE_DBG_CTRL], reg_list[EICE_DBG_CTRL].value);
-	}
-	
-	return reg_cache;
-}
-
-int embeddedice_get_reg(reg_t *reg)
-{
-	if (embeddedice_read_reg(reg) != ERROR_OK)
-	{
-		ERROR("BUG: error scheduling EmbeddedICE register read");
-		exit(-1);
-	}
-	
-	if (jtag_execute_queue() != ERROR_OK)
-	{
-		ERROR("register read failed");
-	}
-	
-	return ERROR_OK;
-}
-
-int embeddedice_read_reg_w_check(reg_t *reg, u8* check_value, u8* check_mask)
-{
-	embeddedice_reg_t *ice_reg = reg->arch_info;
-	u8 reg_addr = ice_reg->addr & 0x1f;
-	scan_field_t fields[3];
-	u8 field1_out[1];
-	u8 field2_out[1];
-
-	DEBUG("%i", ice_reg->addr);
-
-	jtag_add_end_state(TAP_RTI);
-	arm_jtag_scann(ice_reg->jtag_info, 0x2);
-	
-	arm_jtag_set_instr(ice_reg->jtag_info, ice_reg->jtag_info->intest_instr, NULL);
-	
-	fields[0].device = ice_reg->jtag_info->chain_pos;
-	fields[0].num_bits = 32;
-	fields[0].out_value = reg->value;
-	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 = ice_reg->jtag_info->chain_pos;
-	fields[1].num_bits = 5;
-	fields[1].out_value = field1_out;
-	buf_set_u32(fields[1].out_value, 0, 5, reg_addr);
-	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;
-
-	fields[2].device = ice_reg->jtag_info->chain_pos;
-	fields[2].num_bits = 1;
-	fields[2].out_value = field2_out;
-	buf_set_u32(fields[2].out_value, 0, 1, 0);
-	fields[2].out_mask = NULL;
-	fields[2].in_value = NULL;
-	fields[2].in_check_value = NULL;
-	fields[2].in_check_mask = NULL;
-	fields[2].in_handler = NULL;
-	fields[2].in_handler_priv = NULL;
-	
-	jtag_add_dr_scan(3, fields, -1, NULL);
-	
-	fields[0].in_value = reg->value;
-	jtag_set_check_value(fields+0, check_value, check_mask, NULL);
-	
-	/* when reading the DCC data register, leaving the address field set to
-	 * EICE_COMMS_DATA would read the register twice
-	 * reading the control register is safe
-	 */
-	buf_set_u32(fields[1].out_value, 0, 5, embeddedice_reg_arch_info[EICE_COMMS_CTRL]);
-	
-	jtag_add_dr_scan(3, fields, -1, NULL);
-
-	return ERROR_OK;
-}
-
-/* receive <size> words of 32 bit from the DCC
- * we pretend the target is always going to be fast enough
- * (relative to the JTAG clock), so we don't need to handshake
- */
-int embeddedice_receive(arm_jtag_t *jtag_info, u32 *data, u32 size)
-{
-	scan_field_t fields[3];
-	u8 field1_out[1];
-	u8 field2_out[1];
-
-	jtag_add_end_state(TAP_RTI);
-	arm_jtag_scann(jtag_info, 0x2);
-	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
-	
-	fields[0].device = jtag_info->chain_pos;
-	fields[0].num_bits = 32;
-	fields[0].out_value = NULL;
-	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 = jtag_info->chain_pos;
-	fields[1].num_bits = 5;
-	fields[1].out_value = field1_out;
-	buf_set_u32(fields[1].out_value, 0, 5, embeddedice_reg_arch_info[EICE_COMMS_DATA]);
-	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;
-
-	fields[2].device = jtag_info->chain_pos;
-	fields[2].num_bits = 1;
-	fields[2].out_value = field2_out;
-	buf_set_u32(fields[2].out_value, 0, 1, 0);
-	fields[2].out_mask = NULL;
-	fields[2].in_value = NULL;
-	fields[2].in_check_value = NULL;
-	fields[2].in_check_mask = NULL;
-	fields[2].in_handler = NULL;
-	fields[2].in_handler_priv = NULL;
-	
-	jtag_add_dr_scan(3, fields, -1, NULL);
-	
-	while (size > 0)
-	{
-		/* when reading the last item, set the register address to the DCC control reg,
-		 * to avoid reading additional data from the DCC data reg
-		 */
-		if (size == 1)
-			buf_set_u32(fields[1].out_value, 0, 5, embeddedice_reg_arch_info[EICE_COMMS_CTRL]);
-		
-		fields[0].in_handler = arm_jtag_buf_to_u32;
-		fields[0].in_handler_priv = data;
-		jtag_add_dr_scan(3, fields, -1, NULL);
-		
-		data++;
-		size--;
-	}
-	
-	return jtag_execute_queue();
-}
-
-int embeddedice_read_reg(reg_t *reg)
-{
-	return embeddedice_read_reg_w_check(reg, NULL, NULL);	
-}
-
-int embeddedice_set_reg(reg_t *reg, u32 value)
-{
-	if (embeddedice_write_reg(reg, value) != ERROR_OK)
-	{
-		ERROR("BUG: error scheduling EmbeddedICE register write");
-		exit(-1);
-	}
-	
-	buf_set_u32(reg->value, 0, reg->size, value);
-	reg->valid = 1;
-	reg->dirty = 0;
-	
-	return ERROR_OK;
-}
-
-int embeddedice_set_reg_w_exec(reg_t *reg, u8 *buf)
-{
-	embeddedice_set_reg(reg, buf_get_u32(buf, 0, reg->size));
-	
-	if (jtag_execute_queue() != ERROR_OK)
-	{
-		ERROR("register write failed");
-		exit(-1);
-	}
-	return ERROR_OK;
-}
-
-int embeddedice_write_reg(reg_t *reg, u32 value)
-{
-	embeddedice_reg_t *ice_reg = reg->arch_info;
-	u8 reg_addr = ice_reg->addr & 0x1f;
-	scan_field_t fields[3];
-	u8 field0_out[4];
-	u8 field1_out[1];
-	u8 field2_out[1];
-
-	DEBUG("%i: 0x%8.8x", ice_reg->addr, value);
-	
-	jtag_add_end_state(TAP_RTI);
-	arm_jtag_scann(ice_reg->jtag_info, 0x2);
-	
-	arm_jtag_set_instr(ice_reg->jtag_info, ice_reg->jtag_info->intest_instr, NULL);
-	
-	fields[0].device = ice_reg->jtag_info->chain_pos;
-	fields[0].num_bits = 32;
-	fields[0].out_value = field0_out;
-	buf_set_u32(fields[0].out_value, 0, 32, value);
-	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 = ice_reg->jtag_info->chain_pos;
-	fields[1].num_bits = 5;
-	fields[1].out_value = field1_out;
-	buf_set_u32(fields[1].out_value, 0, 5, reg_addr);
-	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;
-
-	fields[2].device = ice_reg->jtag_info->chain_pos;
-	fields[2].num_bits = 1;
-	fields[2].out_value = field2_out;
-	buf_set_u32(fields[2].out_value, 0, 1, 1);
-	fields[2].out_mask = NULL;
-	fields[2].in_value = NULL;
-	fields[2].in_check_value = NULL;
-	fields[2].in_check_mask = NULL;
-	fields[2].in_handler = NULL;
-	fields[2].in_handler_priv = NULL;
-	
-	jtag_add_dr_scan(3, fields, -1, NULL);
-	
-	return ERROR_OK;
-}
-
-int embeddedice_store_reg(reg_t *reg)
-{
-	return embeddedice_write_reg(reg, buf_get_u32(reg->value, 0, reg->size));
-}
-
-/* send <size> words of 32 bit to the DCC
- * we pretend the target is always going to be fast enough
- * (relative to the JTAG clock), so we don't need to handshake
- */
-int embeddedice_send(arm_jtag_t *jtag_info, u32 *data, u32 size)
-{
-	scan_field_t fields[3];
-	u8 field0_out[4];
-	u8 field1_out[1];
-	u8 field2_out[1];
-
-	jtag_add_end_state(TAP_RTI);
-	arm_jtag_scann(jtag_info, 0x2);
-	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
-
-	fields[0].device = jtag_info->chain_pos;
-	fields[0].num_bits = 32;
-	fields[0].out_value = field0_out;
-	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 = jtag_info->chain_pos;
-	fields[1].num_bits = 5;
-	fields[1].out_value = field1_out;
-	buf_set_u32(fields[1].out_value, 0, 5, embeddedice_reg_arch_info[EICE_COMMS_DATA]);
-	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;
-
-	fields[2].device = jtag_info->chain_pos;
-	fields[2].num_bits = 1;
-	fields[2].out_value = field2_out;
-	buf_set_u32(fields[2].out_value, 0, 1, 1);
-	fields[2].out_mask = NULL;
-	fields[2].in_value = NULL;
-	fields[2].in_check_value = NULL;
-	fields[2].in_check_mask = NULL;
-	fields[2].in_handler = NULL;
-	fields[2].in_handler_priv = NULL;
-
-	while (size > 0)
-	{
-		buf_set_u32(fields[0].out_value, 0, 32, *data);
-		jtag_add_dr_scan(3, fields, -1, NULL);
-
-		data++;
-		size--;
-	}
-
-	/* call to jtag_execute_queue() intentionally omitted */
-	return ERROR_OK;
-}
-
-/* wait for DCC control register R/W handshake bit to become active
- */
-int embeddedice_handshake(arm_jtag_t *jtag_info, int hsbit, u32 timeout)
-{
-	scan_field_t fields[3];
-	u8 field0_in[4];
-	u8 field1_out[1];
-	u8 field2_out[1];
-	int retval;
-	int hsact;
-	struct timeval lap;
-	struct timeval now;
-
-	if (hsbit == EICE_COMM_CTRL_WBIT)
-		hsact = 1;
-	else if (hsbit == EICE_COMM_CTRL_RBIT)
-		hsact = 0;
-	else
-		return ERROR_INVALID_ARGUMENTS;
-
-	jtag_add_end_state(TAP_RTI);
-	arm_jtag_scann(jtag_info, 0x2);
-	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
-
-	fields[0].device = jtag_info->chain_pos;
-	fields[0].num_bits = 32;
-	fields[0].out_value = NULL;
-	fields[0].out_mask = NULL;
-	fields[0].in_value = field0_in;
-	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 = jtag_info->chain_pos;
-	fields[1].num_bits = 5;
-	fields[1].out_value = field1_out;
-	buf_set_u32(fields[1].out_value, 0, 5, embeddedice_reg_arch_info[EICE_COMMS_CTRL]);
-	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;
-
-	fields[2].device = jtag_info->chain_pos;
-	fields[2].num_bits = 1;
-	fields[2].out_value = field2_out;
-	buf_set_u32(fields[2].out_value, 0, 1, 0);
-	fields[2].out_mask = NULL;
-	fields[2].in_value = NULL;
-	fields[2].in_check_value = NULL;
-	fields[2].in_check_mask = NULL;
-	fields[2].in_handler = NULL;
-	fields[2].in_handler_priv = NULL;
-
-	jtag_add_dr_scan(3, fields, -1, NULL);
-	gettimeofday(&lap, NULL);
-	do
-	{
-		jtag_add_dr_scan(3, fields, -1, NULL);
-		if ((retval = jtag_execute_queue()) != ERROR_OK)
-			return retval;
-
-		if (buf_get_u32(field0_in, hsbit, 1) == hsact)
-			return ERROR_OK;
-
-		gettimeofday(&now, NULL);
-	}
-	while ((now.tv_sec-lap.tv_sec)*1000 + (now.tv_usec-lap.tv_usec)/1000 <= timeout);
-
-	return ERROR_TARGET_TIMEOUT;
-}
+/***************************************************************************
+ *   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.             *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "embeddedice.h"
+
+#include "armv4_5.h"
+#include "arm7_9_common.h"
+
+#include "log.h"
+#include "arm_jtag.h"
+#include "types.h"
+#include "binarybuffer.h"
+#include "target.h"
+#include "register.h"
+#include "jtag.h"
+
+#include <stdlib.h>
+
+bitfield_desc_t embeddedice_comms_ctrl_bitfield_desc[] = 
+{
+	{"R", 1},
+	{"W", 1},
+	{"reserved", 26},
+	{"version", 4}
+};
+
+int embeddedice_reg_arch_info[] =
+{
+	0x0, 0x1, 0x4, 0x5,
+	0x8, 0x9, 0xa, 0xb, 0xc, 0xd,
+	0x10, 0x11, 0x12, 0x13, 0x14, 0x15,
+	0x2
+};
+
+char* embeddedice_reg_list[] =
+{
+	"debug_ctrl",
+	"debug_status",
+	
+	"comms_ctrl",
+	"comms_data",
+	
+	"watch 0 addr value",
+	"watch 0 addr mask",
+	"watch 0 data value",
+	"watch 0 data mask",
+	"watch 0 control value",
+	"watch 0 control mask",
+	
+	"watch 1 addr value",
+	"watch 1 addr mask",
+	"watch 1 data value",
+	"watch 1 data mask",
+	"watch 1 control value",
+	"watch 1 control mask",
+	
+	"vector catch"
+};
+
+int embeddedice_reg_arch_type = -1;
+
+int embeddedice_get_reg(reg_t *reg);
+int embeddedice_set_reg(reg_t *reg, u32 value);
+int embeddedice_set_reg_w_exec(reg_t *reg, u8 *buf);
+
+int embeddedice_write_reg(reg_t *reg, u32 value);
+int embeddedice_read_reg(reg_t *reg);
+
+reg_cache_t* embeddedice_build_reg_cache(target_t *target, arm7_9_common_t *arm7_9)
+{
+	reg_cache_t *reg_cache = malloc(sizeof(reg_cache_t));
+	reg_t *reg_list = NULL;
+	embeddedice_reg_t *arch_info = NULL;
+	arm_jtag_t *jtag_info = &arm7_9->jtag_info;
+	int num_regs;
+	int i;
+	int eice_version = 0;
+	
+	/* register a register arch-type for EmbeddedICE registers only once */
+	if (embeddedice_reg_arch_type == -1)
+		embeddedice_reg_arch_type = register_reg_arch_type(embeddedice_get_reg, embeddedice_set_reg_w_exec);
+	
+	if (arm7_9->has_vector_catch)
+		num_regs = 17;
+	else
+		num_regs = 16;
+		
+	/* the actual registers are kept in two arrays */
+	reg_list = calloc(num_regs, sizeof(reg_t));
+	arch_info = calloc(num_regs, sizeof(embeddedice_reg_t));
+	
+	/* fill in values for the reg cache */
+	reg_cache->name = "EmbeddedICE registers";
+	reg_cache->next = NULL;
+	reg_cache->reg_list = reg_list;
+	reg_cache->num_regs = num_regs;
+	
+	/* set up registers */
+	for (i = 0; i < num_regs; i++)
+	{
+		reg_list[i].name = embeddedice_reg_list[i];
+		reg_list[i].size = 32;
+		reg_list[i].dirty = 0;
+		reg_list[i].valid = 0;
+		reg_list[i].bitfield_desc = NULL;
+		reg_list[i].num_bitfields = 0;
+		reg_list[i].value = calloc(1, 4);
+		reg_list[i].arch_info = &arch_info[i];
+		reg_list[i].arch_type = embeddedice_reg_arch_type;
+		arch_info[i].addr = embeddedice_reg_arch_info[i];
+		arch_info[i].jtag_info = jtag_info;
+	}
+	
+	/* identify EmbeddedICE version by reading DCC control register */
+	embeddedice_read_reg(&reg_list[EICE_COMMS_CTRL]);
+	jtag_execute_queue();
+	
+	eice_version = buf_get_u32(reg_list[EICE_COMMS_CTRL].value, 28, 4);
+	
+	switch (eice_version)
+	{
+		case 1:
+			reg_list[EICE_DBG_CTRL].size = 3;
+			reg_list[EICE_DBG_STAT].size = 5;
+			break;
+		case 2:
+			reg_list[EICE_DBG_CTRL].size = 4;
+			reg_list[EICE_DBG_STAT].size = 5;
+			arm7_9->has_single_step = 1;
+			break;
+		case 3:
+			ERROR("EmbeddedICE version 3 detected, EmbeddedICE handling might be broken"); 
+			reg_list[EICE_DBG_CTRL].size = 6;
+			reg_list[EICE_DBG_STAT].size = 5;
+			arm7_9->has_single_step = 1;
+			arm7_9->has_monitor_mode = 1;
+			break;
+		case 4:
+			reg_list[EICE_DBG_CTRL].size = 6;
+			reg_list[EICE_DBG_STAT].size = 5;
+			arm7_9->has_monitor_mode = 1;
+			break;
+		case 5:
+			reg_list[EICE_DBG_CTRL].size = 6;
+			reg_list[EICE_DBG_STAT].size = 5;
+			arm7_9->has_single_step = 1;
+			arm7_9->has_monitor_mode = 1;
+			break;
+		case 6:
+			reg_list[EICE_DBG_CTRL].size = 6;
+			reg_list[EICE_DBG_STAT].size = 10;
+			arm7_9->has_monitor_mode = 1;
+			break;
+		case 7:
+			WARNING("EmbeddedICE version 7 detected, EmbeddedICE handling might be broken");
+			reg_list[EICE_DBG_CTRL].size = 6;
+			reg_list[EICE_DBG_STAT].size = 5;
+			arm7_9->has_monitor_mode = 1;
+			break;
+		default:
+			ERROR("unknown EmbeddedICE version (comms ctrl: 0x%8.8x)", buf_get_u32(reg_list[EICE_COMMS_CTRL].value, 0, 32));
+	}
+	
+	/* explicitly disable monitor mode */
+	if (arm7_9->has_monitor_mode)
+	{
+		embeddedice_read_reg(&reg_list[EICE_DBG_CTRL]);
+		jtag_execute_queue();
+		buf_set_u32(reg_list[EICE_DBG_CTRL].value, 4, 1, 0);
+		embeddedice_set_reg_w_exec(&reg_list[EICE_DBG_CTRL], reg_list[EICE_DBG_CTRL].value);
+	}
+	
+	return reg_cache;
+}
+
+int embeddedice_get_reg(reg_t *reg)
+{
+	if (embeddedice_read_reg(reg) != ERROR_OK)
+	{
+		ERROR("BUG: error scheduling EmbeddedICE register read");
+		exit(-1);
+	}
+	
+	if (jtag_execute_queue() != ERROR_OK)
+	{
+		ERROR("register read failed");
+	}
+	
+	return ERROR_OK;
+}
+
+int embeddedice_read_reg_w_check(reg_t *reg, u8* check_value, u8* check_mask)
+{
+	embeddedice_reg_t *ice_reg = reg->arch_info;
+	u8 reg_addr = ice_reg->addr & 0x1f;
+	scan_field_t fields[3];
+	u8 field1_out[1];
+	u8 field2_out[1];
+
+	DEBUG("%i", ice_reg->addr);
+
+	jtag_add_end_state(TAP_RTI);
+	arm_jtag_scann(ice_reg->jtag_info, 0x2);
+	
+	arm_jtag_set_instr(ice_reg->jtag_info, ice_reg->jtag_info->intest_instr, NULL);
+	
+	fields[0].device = ice_reg->jtag_info->chain_pos;
+	fields[0].num_bits = 32;
+	fields[0].out_value = reg->value;
+	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 = ice_reg->jtag_info->chain_pos;
+	fields[1].num_bits = 5;
+	fields[1].out_value = field1_out;
+	buf_set_u32(fields[1].out_value, 0, 5, reg_addr);
+	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;
+
+	fields[2].device = ice_reg->jtag_info->chain_pos;
+	fields[2].num_bits = 1;
+	fields[2].out_value = field2_out;
+	buf_set_u32(fields[2].out_value, 0, 1, 0);
+	fields[2].out_mask = NULL;
+	fields[2].in_value = NULL;
+	fields[2].in_check_value = NULL;
+	fields[2].in_check_mask = NULL;
+	fields[2].in_handler = NULL;
+	fields[2].in_handler_priv = NULL;
+	
+	jtag_add_dr_scan(3, fields, -1);
+	
+	fields[0].in_value = reg->value;
+	jtag_set_check_value(fields+0, check_value, check_mask, NULL);
+	
+	/* when reading the DCC data register, leaving the address field set to
+	 * EICE_COMMS_DATA would read the register twice
+	 * reading the control register is safe
+	 */
+	buf_set_u32(fields[1].out_value, 0, 5, embeddedice_reg_arch_info[EICE_COMMS_CTRL]);
+	
+	jtag_add_dr_scan(3, fields, -1);
+
+	return ERROR_OK;
+}
+
+/* receive <size> words of 32 bit from the DCC
+ * we pretend the target is always going to be fast enough
+ * (relative to the JTAG clock), so we don't need to handshake
+ */
+int embeddedice_receive(arm_jtag_t *jtag_info, u32 *data, u32 size)
+{
+	scan_field_t fields[3];
+	u8 field1_out[1];
+	u8 field2_out[1];
+
+	jtag_add_end_state(TAP_RTI);
+	arm_jtag_scann(jtag_info, 0x2);
+	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+	
+	fields[0].device = jtag_info->chain_pos;
+	fields[0].num_bits = 32;
+	fields[0].out_value = NULL;
+	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 = jtag_info->chain_pos;
+	fields[1].num_bits = 5;
+	fields[1].out_value = field1_out;
+	buf_set_u32(fields[1].out_value, 0, 5, embeddedice_reg_arch_info[EICE_COMMS_DATA]);
+	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;
+
+	fields[2].device = jtag_info->chain_pos;
+	fields[2].num_bits = 1;
+	fields[2].out_value = field2_out;
+	buf_set_u32(fields[2].out_value, 0, 1, 0);
+	fields[2].out_mask = NULL;
+	fields[2].in_value = NULL;
+	fields[2].in_check_value = NULL;
+	fields[2].in_check_mask = NULL;
+	fields[2].in_handler = NULL;
+	fields[2].in_handler_priv = NULL;
+	
+	jtag_add_dr_scan(3, fields, -1);
+	
+	while (size > 0)
+	{
+		/* when reading the last item, set the register address to the DCC control reg,
+		 * to avoid reading additional data from the DCC data reg
+		 */
+		if (size == 1)
+			buf_set_u32(fields[1].out_value, 0, 5, embeddedice_reg_arch_info[EICE_COMMS_CTRL]);
+		
+		fields[0].in_handler = arm_jtag_buf_to_u32;
+		fields[0].in_handler_priv = data;
+		jtag_add_dr_scan(3, fields, -1);
+		
+		data++;
+		size--;
+	}
+	
+	return jtag_execute_queue();
+}
+
+int embeddedice_read_reg(reg_t *reg)
+{
+	return embeddedice_read_reg_w_check(reg, NULL, NULL);	
+}
+
+int embeddedice_set_reg(reg_t *reg, u32 value)
+{
+	if (embeddedice_write_reg(reg, value) != ERROR_OK)
+	{
+		ERROR("BUG: error scheduling EmbeddedICE register write");
+		exit(-1);
+	}
+	
+	buf_set_u32(reg->value, 0, reg->size, value);
+	reg->valid = 1;
+	reg->dirty = 0;
+	
+	return ERROR_OK;
+}
+
+int embeddedice_set_reg_w_exec(reg_t *reg, u8 *buf)
+{
+	embeddedice_set_reg(reg, buf_get_u32(buf, 0, reg->size));
+	
+	if (jtag_execute_queue() != ERROR_OK)
+	{
+		ERROR("register write failed");
+		exit(-1);
+	}
+	return ERROR_OK;
+}
+
+int embeddedice_write_reg(reg_t *reg, u32 value)
+{
+	embeddedice_reg_t *ice_reg = reg->arch_info;
+	u8 reg_addr = ice_reg->addr & 0x1f;
+	scan_field_t fields[3];
+	u8 field0_out[4];
+	u8 field1_out[1];
+	u8 field2_out[1];
+
+	DEBUG("%i: 0x%8.8x", ice_reg->addr, value);
+	
+	jtag_add_end_state(TAP_RTI);
+	arm_jtag_scann(ice_reg->jtag_info, 0x2);
+	
+	arm_jtag_set_instr(ice_reg->jtag_info, ice_reg->jtag_info->intest_instr, NULL);
+	
+	fields[0].device = ice_reg->jtag_info->chain_pos;
+	fields[0].num_bits = 32;
+	fields[0].out_value = field0_out;
+	buf_set_u32(fields[0].out_value, 0, 32, value);
+	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 = ice_reg->jtag_info->chain_pos;
+	fields[1].num_bits = 5;
+	fields[1].out_value = field1_out;
+	buf_set_u32(fields[1].out_value, 0, 5, reg_addr);
+	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;
+
+	fields[2].device = ice_reg->jtag_info->chain_pos;
+	fields[2].num_bits = 1;
+	fields[2].out_value = field2_out;
+	buf_set_u32(fields[2].out_value, 0, 1, 1);
+	fields[2].out_mask = NULL;
+	fields[2].in_value = NULL;
+	fields[2].in_check_value = NULL;
+	fields[2].in_check_mask = NULL;
+	fields[2].in_handler = NULL;
+	fields[2].in_handler_priv = NULL;
+	
+	jtag_add_dr_scan(3, fields, -1);
+	
+	return ERROR_OK;
+}
+
+int embeddedice_store_reg(reg_t *reg)
+{
+	return embeddedice_write_reg(reg, buf_get_u32(reg->value, 0, reg->size));
+}
+
+/* send <size> words of 32 bit to the DCC
+ * we pretend the target is always going to be fast enough
+ * (relative to the JTAG clock), so we don't need to handshake
+ */
+int embeddedice_send(arm_jtag_t *jtag_info, u32 *data, u32 size)
+{
+	scan_field_t fields[3];
+	u8 field0_out[4];
+	u8 field1_out[1];
+	u8 field2_out[1];
+
+	jtag_add_end_state(TAP_RTI);
+	arm_jtag_scann(jtag_info, 0x2);
+	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+
+	fields[0].device = jtag_info->chain_pos;
+	fields[0].num_bits = 32;
+	fields[0].out_value = field0_out;
+	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 = jtag_info->chain_pos;
+	fields[1].num_bits = 5;
+	fields[1].out_value = field1_out;
+	buf_set_u32(fields[1].out_value, 0, 5, embeddedice_reg_arch_info[EICE_COMMS_DATA]);
+	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;
+
+	fields[2].device = jtag_info->chain_pos;
+	fields[2].num_bits = 1;
+	fields[2].out_value = field2_out;
+	buf_set_u32(fields[2].out_value, 0, 1, 1);
+	fields[2].out_mask = NULL;
+	fields[2].in_value = NULL;
+	fields[2].in_check_value = NULL;
+	fields[2].in_check_mask = NULL;
+	fields[2].in_handler = NULL;
+	fields[2].in_handler_priv = NULL;
+
+	while (size > 0)
+	{
+		buf_set_u32(fields[0].out_value, 0, 32, *data);
+		jtag_add_dr_scan(3, fields, -1);
+
+		data++;
+		size--;
+	}
+
+	/* call to jtag_execute_queue() intentionally omitted */
+	return ERROR_OK;
+}
+
+/* wait for DCC control register R/W handshake bit to become active
+ */
+int embeddedice_handshake(arm_jtag_t *jtag_info, int hsbit, u32 timeout)
+{
+	scan_field_t fields[3];
+	u8 field0_in[4];
+	u8 field1_out[1];
+	u8 field2_out[1];
+	int retval;
+	int hsact;
+	struct timeval lap;
+	struct timeval now;
+
+	if (hsbit == EICE_COMM_CTRL_WBIT)
+		hsact = 1;
+	else if (hsbit == EICE_COMM_CTRL_RBIT)
+		hsact = 0;
+	else
+		return ERROR_INVALID_ARGUMENTS;
+
+	jtag_add_end_state(TAP_RTI);
+	arm_jtag_scann(jtag_info, 0x2);
+	arm_jtag_set_instr(jtag_info, jtag_info->intest_instr, NULL);
+
+	fields[0].device = jtag_info->chain_pos;
+	fields[0].num_bits = 32;
+	fields[0].out_value = NULL;
+	fields[0].out_mask = NULL;
+	fields[0].in_value = field0_in;
+	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 = jtag_info->chain_pos;
+	fields[1].num_bits = 5;
+	fields[1].out_value = field1_out;
+	buf_set_u32(fields[1].out_value, 0, 5, embeddedice_reg_arch_info[EICE_COMMS_CTRL]);
+	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;
+
+	fields[2].device = jtag_info->chain_pos;
+	fields[2].num_bits = 1;
+	fields[2].out_value = field2_out;
+	buf_set_u32(fields[2].out_value, 0, 1, 0);
+	fields[2].out_mask = NULL;
+	fields[2].in_value = NULL;
+	fields[2].in_check_value = NULL;
+	fields[2].in_check_mask = NULL;
+	fields[2].in_handler = NULL;
+	fields[2].in_handler_priv = NULL;
+
+	jtag_add_dr_scan(3, fields, -1);
+	gettimeofday(&lap, NULL);
+	do
+	{
+		jtag_add_dr_scan(3, fields, -1);
+		if ((retval = jtag_execute_queue()) != ERROR_OK)
+			return retval;
+
+		if (buf_get_u32(field0_in, hsbit, 1) == hsact)
+			return ERROR_OK;
+
+		gettimeofday(&now, NULL);
+	}
+	while ((now.tv_sec-lap.tv_sec)*1000 + (now.tv_usec-lap.tv_usec)/1000 <= timeout);
+
+	return ERROR_TARGET_TIMEOUT;
+}
diff --git a/src/target/etb.c b/src/target/etb.c
index 0c409fb0ca15cae497de12ee7db6767ffc6cc9b1..6c9d3a0c139f5f5dbb842634ce5b2ec898200cfa 100644
--- a/src/target/etb.c
+++ b/src/target/etb.c
@@ -1,741 +1,741 @@
-/***************************************************************************
- *   Copyright (C) 2007 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 <string.h>
-
-#include "arm7_9_common.h"
-#include "etb.h"
-#include "etm.h"
-
-#include "log.h"
-#include "types.h"
-#include "binarybuffer.h"
-#include "target.h"
-#include "register.h"
-#include "jtag.h"
-
-#include <stdlib.h>
-
-char* etb_reg_list[] =
-{
-	"ETB_identification",
-	"ETB_ram_depth",
-	"ETB_ram_width",
-	"ETB_status",
-	"ETB_ram_data",
-	"ETB_ram_read_pointer",
-	"ETB_ram_write_pointer",
-	"ETB_trigger_counter",
-	"ETB_control",
-};
-
-int etb_reg_arch_type = -1;
-
-int etb_get_reg(reg_t *reg);
-int etb_set_reg(reg_t *reg, u32 value);
-int etb_set_reg_w_exec(reg_t *reg, u8 *buf);
-
-int etb_write_reg(reg_t *reg, u32 value);
-int etb_read_reg(reg_t *reg);
-
-int handle_etb_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-
-int etb_set_instr(etb_t *etb, u32 new_instr)
-{
-	jtag_device_t *device = jtag_get_device(etb->chain_pos);
-	
-	if (buf_get_u32(device->cur_instr, 0, device->ir_length) != new_instr)
-	{
-		scan_field_t field;
-	
-		field.device = etb->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 = NULL;
-		field.in_check_mask = NULL;
-		field.in_handler = NULL;
-		field.in_handler_priv = NULL;
-				
-		jtag_add_ir_scan(1, &field, -1, NULL);
-		
-		free(field.out_value);
-	}
-	
-	return ERROR_OK;
-}
-
-int etb_scann(etb_t *etb, u32 new_scan_chain)
-{
-	if(etb->cur_scan_chain != new_scan_chain)
-	{
-		scan_field_t field;
-		
-		field.device = etb->chain_pos;
-		field.num_bits = 5;
-		field.out_value = calloc(CEIL(field.num_bits, 8), 1);
-		buf_set_u32(field.out_value, 0, field.num_bits, new_scan_chain);
-		field.out_mask = NULL;
-		field.in_value = NULL;
-		field.in_check_value = NULL;
-		field.in_check_mask = NULL;
-		field.in_handler = NULL;
-		field.in_handler_priv = NULL;
-		
-		/* select INTEST instruction */
-		etb_set_instr(etb, 0x2);
-		jtag_add_dr_scan(1, &field, -1, NULL);
-		
-		etb->cur_scan_chain = new_scan_chain;
-		
-		free(field.out_value);
-	}
-
-	return ERROR_OK;
-}
-
-reg_cache_t* etb_build_reg_cache(etb_t *etb)
-{
-	reg_cache_t *reg_cache = malloc(sizeof(reg_cache_t));
-	reg_t *reg_list = NULL;
-	etb_reg_t *arch_info = NULL;
-	int num_regs = 9;
-	int i;
-	
-	/* register a register arch-type for etm registers only once */
-	if (etb_reg_arch_type == -1)
-		etb_reg_arch_type = register_reg_arch_type(etb_get_reg, etb_set_reg_w_exec);
-	
-	/* the actual registers are kept in two arrays */
-	reg_list = calloc(num_regs, sizeof(reg_t));
-	arch_info = calloc(num_regs, sizeof(etb_reg_t));
-	
-	/* fill in values for the reg cache */
-	reg_cache->name = "etb registers";
-	reg_cache->next = NULL;
-	reg_cache->reg_list = reg_list;
-	reg_cache->num_regs = num_regs;
-	
-	/* set up registers */
-	for (i = 0; i < num_regs; i++)
-	{
-		reg_list[i].name = etb_reg_list[i];
-		reg_list[i].size = 32;
-		reg_list[i].dirty = 0;
-		reg_list[i].valid = 0;
-		reg_list[i].bitfield_desc = NULL;
-		reg_list[i].num_bitfields = 0;
-		reg_list[i].value = calloc(1, 4);
-		reg_list[i].arch_info = &arch_info[i];
-		reg_list[i].arch_type = etb_reg_arch_type;
-		reg_list[i].size = 32;
-		arch_info[i].addr = i;
-		arch_info[i].etb = etb;
-	}
-	
-	return reg_cache;
-}
-
-int etb_get_reg(reg_t *reg)
-{
-	if (etb_read_reg(reg) != ERROR_OK)
-	{
-		ERROR("BUG: error scheduling etm register read");
-		exit(-1);
-	}
-	
-	if (jtag_execute_queue() != ERROR_OK)
-	{
-		ERROR("register read failed");
-	}
-	
-	return ERROR_OK;
-}
-
-int etb_read_ram(etb_t *etb, u32 *data, int num_frames)
-{
-	scan_field_t fields[3];
-	int i;
-	
-	jtag_add_end_state(TAP_RTI);
-	etb_scann(etb, 0x0);
-	etb_set_instr(etb, 0xc);
-	
-	fields[0].device = etb->chain_pos;
-	fields[0].num_bits = 32;
-	fields[0].out_value = NULL;
-	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 = etb->chain_pos;
-	fields[1].num_bits = 7;
-	fields[1].out_value = malloc(1);
-	buf_set_u32(fields[1].out_value, 0, 7, 4);
-	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;
-
-	fields[2].device = etb->chain_pos;
-	fields[2].num_bits = 1;
-	fields[2].out_value = malloc(1);
-	buf_set_u32(fields[2].out_value, 0, 1, 0);
-	fields[2].out_mask = NULL;
-	fields[2].in_value = NULL;
-	fields[2].in_check_value = NULL;
-	fields[2].in_check_mask = NULL;
-	fields[2].in_handler = NULL;
-	fields[2].in_handler_priv = NULL;
-	
-	jtag_add_dr_scan(3, fields, -1, NULL);
-
-	fields[0].in_handler = buf_to_u32_handler;
-	
-	for (i = 0; i < num_frames; i++)
-	{
-		/* ensure nR/W reamins set to read */
-		buf_set_u32(fields[2].out_value, 0, 1, 0);
-		
-		/* address remains set to 0x4 (RAM data) until we read the last frame */
-		if (i < num_frames - 1)
-			buf_set_u32(fields[1].out_value, 0, 7, 4);
-		else
-			buf_set_u32(fields[1].out_value, 0, 7, 0);
-		
-		fields[0].in_handler_priv = &data[i];
-		jtag_add_dr_scan(3, fields, -1, NULL);
-	}
-	
-	jtag_execute_queue();
-	
-	free(fields[1].out_value);
-	free(fields[2].out_value);
-	
-	return ERROR_OK;
-}
-
-int etb_read_reg_w_check(reg_t *reg, u8* check_value, u8* check_mask)
-{
-	etb_reg_t *etb_reg = reg->arch_info;
-	u8 reg_addr = etb_reg->addr & 0x7f;
-	scan_field_t fields[3];
-	
-	DEBUG("%i", etb_reg->addr);
-
-	jtag_add_end_state(TAP_RTI);
-	etb_scann(etb_reg->etb, 0x0);
-	etb_set_instr(etb_reg->etb, 0xc);
-	
-	fields[0].device = etb_reg->etb->chain_pos;
-	fields[0].num_bits = 32;
-	fields[0].out_value = reg->value;
-	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 = etb_reg->etb->chain_pos;
-	fields[1].num_bits = 7;
-	fields[1].out_value = malloc(1);
-	buf_set_u32(fields[1].out_value, 0, 7, reg_addr);
-	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;
-
-	fields[2].device = etb_reg->etb->chain_pos;
-	fields[2].num_bits = 1;
-	fields[2].out_value = malloc(1);
-	buf_set_u32(fields[2].out_value, 0, 1, 0);
-	fields[2].out_mask = NULL;
-	fields[2].in_value = NULL;
-	fields[2].in_check_value = NULL;
-	fields[2].in_check_mask = NULL;
-	fields[2].in_handler = NULL;
-	fields[2].in_handler_priv = NULL;
-	
-	jtag_add_dr_scan(3, fields, -1, NULL);
-	
-	/* read the identification register in the second run, to make sure we
-	 * don't read the ETB data register twice, skipping every second entry
-	 */
-	buf_set_u32(fields[1].out_value, 0, 7, 0x0);
-	fields[0].in_value = reg->value;
-	
-	jtag_set_check_value(fields+0, check_value, check_mask, NULL);
-	
-	jtag_add_dr_scan(3, fields, -1, NULL);
-
-	free(fields[1].out_value);
-	free(fields[2].out_value);
-	
-	return ERROR_OK;
-}
-
-int etb_read_reg(reg_t *reg)
-{
-	return etb_read_reg_w_check(reg, NULL, NULL);	
-}
-
-int etb_set_reg(reg_t *reg, u32 value)
-{
-	if (etb_write_reg(reg, value) != ERROR_OK)
-	{
-		ERROR("BUG: error scheduling etm register write");
-		exit(-1);
-	}
-	
-	buf_set_u32(reg->value, 0, reg->size, value);
-	reg->valid = 1;
-	reg->dirty = 0;
-	
-	return ERROR_OK;
-}
-
-int etb_set_reg_w_exec(reg_t *reg, u8 *buf)
-{
-	etb_set_reg(reg, buf_get_u32(buf, 0, reg->size));
-	
-	if (jtag_execute_queue() != ERROR_OK)
-	{
-		ERROR("register write failed");
-		exit(-1);
-	}
-	return ERROR_OK;
-}
-
-int etb_write_reg(reg_t *reg, u32 value)
-{
-	etb_reg_t *etb_reg = reg->arch_info;
-	u8 reg_addr = etb_reg->addr & 0x7f;
-	scan_field_t fields[3];
-	
-	DEBUG("%i: 0x%8.8x", etb_reg->addr, value);
-	
-	jtag_add_end_state(TAP_RTI);
-	etb_scann(etb_reg->etb, 0x0);
-	etb_set_instr(etb_reg->etb, 0xc);
-	
-	fields[0].device = etb_reg->etb->chain_pos;
-	fields[0].num_bits = 32;
-	fields[0].out_value = malloc(4);
-	buf_set_u32(fields[0].out_value, 0, 32, value);
-	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 = etb_reg->etb->chain_pos;
-	fields[1].num_bits = 7;
-	fields[1].out_value = malloc(1);
-	buf_set_u32(fields[1].out_value, 0, 7, reg_addr);
-	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;
-
-	fields[2].device = etb_reg->etb->chain_pos;
-	fields[2].num_bits = 1;
-	fields[2].out_value = malloc(1);
-	buf_set_u32(fields[2].out_value, 0, 1, 1);
-	fields[2].out_mask = NULL;
-	fields[2].in_value = NULL;
-	fields[2].in_check_value = NULL;
-	fields[2].in_check_mask = NULL;
-	fields[2].in_handler = NULL;
-	fields[2].in_handler_priv = NULL;
-	
-	jtag_add_dr_scan(3, fields, -1, NULL);
-	
-	free(fields[0].out_value);
-	free(fields[1].out_value);
-	free(fields[2].out_value);
-	
-	return ERROR_OK;
-}
-
-int etb_store_reg(reg_t *reg)
-{
-	return etb_write_reg(reg, buf_get_u32(reg->value, 0, reg->size));
-}
-
-int etb_register_commands(struct command_context_s *cmd_ctx)
-{
-	command_t *etb_cmd;
-	
-	etb_cmd = register_command(cmd_ctx, NULL, "etb", NULL, COMMAND_ANY, "Embedded Trace Buffer");
-	
-	register_command(cmd_ctx, etb_cmd, "config", handle_etb_config_command, COMMAND_CONFIG, NULL);
-
-	return ERROR_OK;
-}
-
-int handle_etb_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	target_t *target;
-	jtag_device_t *jtag_device;
-	armv4_5_common_t *armv4_5;
-	arm7_9_common_t *arm7_9;
-	
-	if (argc != 2)
-	{
-		ERROR("incomplete 'etb config <target> <chain_pos>' command");
-		exit(-1);
-	}
-	
-	target = get_target_by_num(strtoul(args[0], NULL, 0));
-	
-	if (!target)
-	{
-		ERROR("target number '%s' not defined", args[0]);
-		exit(-1);
-	}
-	
-	if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
-		return ERROR_OK;
-	}
-	
-	jtag_device = jtag_get_device(strtoul(args[1], NULL, 0));
-	
-	if (!jtag_device)
-	{
-		ERROR("jtag device number '%s' not defined", args[1]);
-		exit(-1);
-	}
-	
-	if (arm7_9->etm_ctx)
-	{
-		etb_t *etb = malloc(sizeof(etb_t));
-		
-		arm7_9->etm_ctx->capture_driver_priv = etb;
-		
-		etb->chain_pos = strtoul(args[1], NULL, 0);
-		etb->cur_scan_chain = -1;
-		etb->reg_cache = NULL;
-		etb->ram_width = 0;
-		etb->ram_depth = 0;
-	}
-	else
-	{
-		ERROR("target has no ETM defined, ETB left unconfigured");
-	}
-
-	return ERROR_OK;
-}
-
-int etb_init(etm_context_t *etm_ctx)
-{
-	etb_t *etb = etm_ctx->capture_driver_priv;
-	
-	etb->etm_ctx = etm_ctx;
-	
-	/* identify ETB RAM depth and width */
-	etb_read_reg(&etb->reg_cache->reg_list[ETB_RAM_DEPTH]);
-	etb_read_reg(&etb->reg_cache->reg_list[ETB_RAM_WIDTH]);
-	jtag_execute_queue();
-
-	etb->ram_depth = buf_get_u32(etb->reg_cache->reg_list[ETB_RAM_DEPTH].value, 0, 32);
-	etb->ram_width = buf_get_u32(etb->reg_cache->reg_list[ETB_RAM_WIDTH].value, 0, 32);
-	
-	return ERROR_OK;
-}
-
-trace_status_t etb_status(etm_context_t *etm_ctx)
-{
-	etb_t *etb = etm_ctx->capture_driver_priv;
-	
-	etb->etm_ctx = etm_ctx;
-	
-	/* if tracing is currently idle, return this information */
-	if (etm_ctx->capture_status == TRACE_IDLE)
-	{
-		return etm_ctx->capture_status;
-	}
-	else if (etm_ctx->capture_status & TRACE_RUNNING)
-	{
-		reg_t *etb_status_reg = &etb->reg_cache->reg_list[ETB_STATUS];
-		int etb_timeout = 100;
-		
-		/* trace is running, check the ETB status flags */
-		etb_get_reg(etb_status_reg);
-	
-		/* check Full bit to identify an overflow */
-		if (buf_get_u32(etb_status_reg->value, 0, 1) == 1)
-			etm_ctx->capture_status |= TRACE_OVERFLOWED;
-
-		/* check Triggered bit to identify trigger condition */
-		if (buf_get_u32(etb_status_reg->value, 1, 1) == 1)
-			etm_ctx->capture_status |= TRACE_TRIGGERED;
-
-		/* check AcqComp to identify trace completion */
-		if (buf_get_u32(etb_status_reg->value, 2, 1) == 1)
-		{
-			while (etb_timeout-- && (buf_get_u32(etb_status_reg->value, 3, 1) == 0))
-			{
-				/* wait for data formatter idle */
-				etb_get_reg(etb_status_reg);
-			}
-			
-			if (etb_timeout == 0)
-			{
-				ERROR("AcqComp set but DFEmpty won't go high, ETB status: 0x%x",
-					buf_get_u32(etb_status_reg->value, 0, etb_status_reg->size));
-			}
-			
-			if (!(etm_ctx->capture_status && TRACE_TRIGGERED))
-			{
-				ERROR("trace completed, but no trigger condition detected");
-			}
-			
-			etm_ctx->capture_status &= ~TRACE_RUNNING;
-			etm_ctx->capture_status |= TRACE_COMPLETED;
-		}
-	}
-	
-	return etm_ctx->capture_status;
-}
-
-int etb_read_trace(etm_context_t *etm_ctx)
-{
-	etb_t *etb = etm_ctx->capture_driver_priv;
-	int first_frame = 0;
-	int num_frames = etb->ram_depth;
-	u32 *trace_data = NULL;
-	int i, j;
-	
-	etb_read_reg(&etb->reg_cache->reg_list[ETB_STATUS]);
-	etb_read_reg(&etb->reg_cache->reg_list[ETB_RAM_WRITE_POINTER]);
-	jtag_execute_queue();
-	
-	/* check if we overflowed, and adjust first frame of the trace accordingly
-	 * if we didn't overflow, read only up to the frame that would be written next,
-	 * i.e. don't read invalid entries
-	 */
-	if (buf_get_u32(etb->reg_cache->reg_list[ETB_STATUS].value, 0, 1))
-	{
-		first_frame = buf_get_u32(etb->reg_cache->reg_list[ETB_RAM_WRITE_POINTER].value, 0, 32);
-	}
-	else
-	{
-		num_frames = buf_get_u32(etb->reg_cache->reg_list[ETB_RAM_WRITE_POINTER].value, 0, 32);
-	}
-	
-	etb_write_reg(&etb->reg_cache->reg_list[ETB_RAM_READ_POINTER], first_frame);
-
-	/* read data into temporary array for unpacking */	
-	trace_data = malloc(sizeof(u32) * num_frames);
-	etb_read_ram(etb, trace_data, num_frames);
-
-	if (etm_ctx->trace_depth > 0)
-	{
-		free(etm_ctx->trace_data);
-	}
-	
-	if ((etm_ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_4BIT)
-		etm_ctx->trace_depth = num_frames * 3;
-	else if ((etm_ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_8BIT)
-		etm_ctx->trace_depth = num_frames * 2;
-	else
-		etm_ctx->trace_depth = num_frames;
-
-	etm_ctx->trace_data = malloc(sizeof(etmv1_trace_data_t) * etm_ctx->trace_depth);
-	
-	for (i = 0, j = 0; i < num_frames; i++)
-	{
-		if ((etm_ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_4BIT)
-		{
-			/* trace word j */
-			etm_ctx->trace_data[j].pipestat = trace_data[i] & 0x7;
-			etm_ctx->trace_data[j].packet = (trace_data[i] & 0x78) >> 3;
-			etm_ctx->trace_data[j].flags = 0;
-			if ((trace_data[i] & 0x80) >> 7)
-			{
-				etm_ctx->trace_data[j].flags |= ETMV1_TRACESYNC_CYCLE;
-			}
-			if (etm_ctx->trace_data[j].pipestat == STAT_TR)
-			{
-				etm_ctx->trace_data[j].pipestat = etm_ctx->trace_data[j].packet & 0x7;
-				etm_ctx->trace_data[j].flags |= ETMV1_TRIGGER_CYCLE;
-			}
-			
-			/* trace word j+1 */
-			etm_ctx->trace_data[j+1].pipestat = (trace_data[i] & 0x100) >> 8;
-			etm_ctx->trace_data[j+1].packet = (trace_data[i] & 0x7800) >> 11;
-			etm_ctx->trace_data[j+1].flags = 0;
-			if ((trace_data[i] & 0x8000) >> 15)
-			{
-				etm_ctx->trace_data[j+1].flags |= ETMV1_TRACESYNC_CYCLE;
-			}
-			if (etm_ctx->trace_data[j+1].pipestat == STAT_TR)
-			{
-				etm_ctx->trace_data[j+1].pipestat = etm_ctx->trace_data[j+1].packet & 0x7;
-				etm_ctx->trace_data[j+1].flags |= ETMV1_TRIGGER_CYCLE;
-			}
-			
-			/* trace word j+2 */
-			etm_ctx->trace_data[j+2].pipestat = (trace_data[i] & 0x10000) >> 16;
-			etm_ctx->trace_data[j+2].packet = (trace_data[i] & 0x780000) >> 19;
-			etm_ctx->trace_data[j+2].flags = 0;
-			if ((trace_data[i] & 0x800000) >> 23)
-			{
-				etm_ctx->trace_data[j+2].flags |= ETMV1_TRACESYNC_CYCLE;
-			}
-			if (etm_ctx->trace_data[j+2].pipestat == STAT_TR)
-			{
-				etm_ctx->trace_data[j+2].pipestat = etm_ctx->trace_data[j+2].packet & 0x7;
-				etm_ctx->trace_data[j+2].flags |= ETMV1_TRIGGER_CYCLE;
-			}
-			
-			j += 3;
-		}
-		else if ((etm_ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_8BIT)
-		{
-			/* trace word j */
-			etm_ctx->trace_data[j].pipestat = trace_data[i] & 0x7;
-			etm_ctx->trace_data[j].packet = (trace_data[i] & 0x7f8) >> 3;
-			etm_ctx->trace_data[j].flags = 0;
-			if ((trace_data[i] & 0x800) >> 11)
-			{
-				etm_ctx->trace_data[j].flags |= ETMV1_TRACESYNC_CYCLE;
-			}
-			if (etm_ctx->trace_data[j].pipestat == STAT_TR)
-			{
-				etm_ctx->trace_data[j].pipestat = etm_ctx->trace_data[j].packet & 0x7;
-				etm_ctx->trace_data[j].flags |= ETMV1_TRIGGER_CYCLE;
-			}
-
-			/* trace word j+1 */
-			etm_ctx->trace_data[j+1].pipestat = (trace_data[i] & 0x7000) >> 12;
-			etm_ctx->trace_data[j+1].packet = (trace_data[i] & 0x7f8000) >> 15;
-			etm_ctx->trace_data[j+1].flags = 0;
-			if ((trace_data[i] & 0x800000) >> 23)
-			{
-				etm_ctx->trace_data[j+1].flags |= ETMV1_TRACESYNC_CYCLE;
-			}
-			if (etm_ctx->trace_data[j+1].pipestat == STAT_TR)
-			{
-				etm_ctx->trace_data[j+1].pipestat = etm_ctx->trace_data[j+1].packet & 0x7;
-				etm_ctx->trace_data[j+1].flags |= ETMV1_TRIGGER_CYCLE;
-			}
-			
-			j += 2;
-		}
-		else
-		{
-			/* trace word j */
-			etm_ctx->trace_data[j].pipestat = trace_data[i] & 0x7;
-			etm_ctx->trace_data[j].packet = (trace_data[i] & 0x7fff8) >> 3;
-			etm_ctx->trace_data[j].flags = 0;
-			if ((trace_data[i] & 0x80000) >> 19)
-			{
-				etm_ctx->trace_data[j].flags |= ETMV1_TRACESYNC_CYCLE;
-			}
-			if (etm_ctx->trace_data[j].pipestat == STAT_TR)
-			{
-				etm_ctx->trace_data[j].pipestat = etm_ctx->trace_data[j].packet & 0x7;
-				etm_ctx->trace_data[j].flags |= ETMV1_TRIGGER_CYCLE;
-			}
-			
-			j += 1;
-		}
-	}
-	
-	free(trace_data);
-	
-	return ERROR_OK;
-}
-
-int etb_start_capture(etm_context_t *etm_ctx)
-{
-	etb_t *etb = etm_ctx->capture_driver_priv;
-	u32 etb_ctrl_value = 0x1;
-	u32 trigger_count;
-
-	if ((etm_ctx->portmode & ETM_PORT_MODE_MASK) == ETM_PORT_DEMUXED)
-	{
-		if ((etm_ctx->portmode & ETM_PORT_WIDTH_MASK) != ETM_PORT_8BIT)
-		{
-			ERROR("ETB can't run in demultiplexed mode with a 4 or 16 bit port");
-			return ERROR_ETM_PORTMODE_NOT_SUPPORTED;
-		}
-		etb_ctrl_value |= 0x2;
-	}
-	
-	if ((etm_ctx->portmode & ETM_PORT_MODE_MASK) == ETM_PORT_MUXED)
-		return ERROR_ETM_PORTMODE_NOT_SUPPORTED;
-	
-	trigger_count = (etb->ram_depth * etm_ctx->trigger_percent) / 100;
-	
-	etb_write_reg(&etb->reg_cache->reg_list[ETB_TRIGGER_COUNTER], trigger_count);
-	etb_write_reg(&etb->reg_cache->reg_list[ETB_RAM_WRITE_POINTER], 0x0);
-	etb_write_reg(&etb->reg_cache->reg_list[ETB_CTRL], etb_ctrl_value);
-	jtag_execute_queue();
-	
-	/* we're starting a new trace, initialize capture status */
-	etm_ctx->capture_status = TRACE_RUNNING;
-	
-	return ERROR_OK; 
-}
-
-int etb_stop_capture(etm_context_t *etm_ctx)
-{
-	etb_t *etb = etm_ctx->capture_driver_priv;
-	reg_t *etb_ctrl_reg = &etb->reg_cache->reg_list[ETB_CTRL];
-
-	etb_write_reg(etb_ctrl_reg, 0x0);
-	jtag_execute_queue();
-	
-	/* trace stopped, just clear running flag, but preserve others */ 
-	etm_ctx->capture_status &= ~TRACE_RUNNING;
-	
-	return ERROR_OK;
-}
-
-etm_capture_driver_t etb_capture_driver =
-{
-	.name = "etb",
-	.register_commands = etb_register_commands,
-	.init = etb_init,
-	.status = etb_status,
-	.start_capture = etb_start_capture,
-	.stop_capture = etb_stop_capture,
-	.read_trace = etb_read_trace,
-};
+/***************************************************************************
+ *   Copyright (C) 2007 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 <string.h>
+
+#include "arm7_9_common.h"
+#include "etb.h"
+#include "etm.h"
+
+#include "log.h"
+#include "types.h"
+#include "binarybuffer.h"
+#include "target.h"
+#include "register.h"
+#include "jtag.h"
+
+#include <stdlib.h>
+
+char* etb_reg_list[] =
+{
+	"ETB_identification",
+	"ETB_ram_depth",
+	"ETB_ram_width",
+	"ETB_status",
+	"ETB_ram_data",
+	"ETB_ram_read_pointer",
+	"ETB_ram_write_pointer",
+	"ETB_trigger_counter",
+	"ETB_control",
+};
+
+int etb_reg_arch_type = -1;
+
+int etb_get_reg(reg_t *reg);
+int etb_set_reg(reg_t *reg, u32 value);
+int etb_set_reg_w_exec(reg_t *reg, u8 *buf);
+
+int etb_write_reg(reg_t *reg, u32 value);
+int etb_read_reg(reg_t *reg);
+
+int handle_etb_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+int etb_set_instr(etb_t *etb, u32 new_instr)
+{
+	jtag_device_t *device = jtag_get_device(etb->chain_pos);
+	
+	if (buf_get_u32(device->cur_instr, 0, device->ir_length) != new_instr)
+	{
+		scan_field_t field;
+	
+		field.device = etb->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 = NULL;
+		field.in_check_mask = NULL;
+		field.in_handler = NULL;
+		field.in_handler_priv = NULL;
+				
+		jtag_add_ir_scan(1, &field, -1);
+		
+		free(field.out_value);
+	}
+	
+	return ERROR_OK;
+}
+
+int etb_scann(etb_t *etb, u32 new_scan_chain)
+{
+	if(etb->cur_scan_chain != new_scan_chain)
+	{
+		scan_field_t field;
+		
+		field.device = etb->chain_pos;
+		field.num_bits = 5;
+		field.out_value = calloc(CEIL(field.num_bits, 8), 1);
+		buf_set_u32(field.out_value, 0, field.num_bits, new_scan_chain);
+		field.out_mask = NULL;
+		field.in_value = NULL;
+		field.in_check_value = NULL;
+		field.in_check_mask = NULL;
+		field.in_handler = NULL;
+		field.in_handler_priv = NULL;
+		
+		/* select INTEST instruction */
+		etb_set_instr(etb, 0x2);
+		jtag_add_dr_scan(1, &field, -1);
+		
+		etb->cur_scan_chain = new_scan_chain;
+		
+		free(field.out_value);
+	}
+
+	return ERROR_OK;
+}
+
+reg_cache_t* etb_build_reg_cache(etb_t *etb)
+{
+	reg_cache_t *reg_cache = malloc(sizeof(reg_cache_t));
+	reg_t *reg_list = NULL;
+	etb_reg_t *arch_info = NULL;
+	int num_regs = 9;
+	int i;
+	
+	/* register a register arch-type for etm registers only once */
+	if (etb_reg_arch_type == -1)
+		etb_reg_arch_type = register_reg_arch_type(etb_get_reg, etb_set_reg_w_exec);
+	
+	/* the actual registers are kept in two arrays */
+	reg_list = calloc(num_regs, sizeof(reg_t));
+	arch_info = calloc(num_regs, sizeof(etb_reg_t));
+	
+	/* fill in values for the reg cache */
+	reg_cache->name = "etb registers";
+	reg_cache->next = NULL;
+	reg_cache->reg_list = reg_list;
+	reg_cache->num_regs = num_regs;
+	
+	/* set up registers */
+	for (i = 0; i < num_regs; i++)
+	{
+		reg_list[i].name = etb_reg_list[i];
+		reg_list[i].size = 32;
+		reg_list[i].dirty = 0;
+		reg_list[i].valid = 0;
+		reg_list[i].bitfield_desc = NULL;
+		reg_list[i].num_bitfields = 0;
+		reg_list[i].value = calloc(1, 4);
+		reg_list[i].arch_info = &arch_info[i];
+		reg_list[i].arch_type = etb_reg_arch_type;
+		reg_list[i].size = 32;
+		arch_info[i].addr = i;
+		arch_info[i].etb = etb;
+	}
+	
+	return reg_cache;
+}
+
+int etb_get_reg(reg_t *reg)
+{
+	if (etb_read_reg(reg) != ERROR_OK)
+	{
+		ERROR("BUG: error scheduling etm register read");
+		exit(-1);
+	}
+	
+	if (jtag_execute_queue() != ERROR_OK)
+	{
+		ERROR("register read failed");
+	}
+	
+	return ERROR_OK;
+}
+
+int etb_read_ram(etb_t *etb, u32 *data, int num_frames)
+{
+	scan_field_t fields[3];
+	int i;
+	
+	jtag_add_end_state(TAP_RTI);
+	etb_scann(etb, 0x0);
+	etb_set_instr(etb, 0xc);
+	
+	fields[0].device = etb->chain_pos;
+	fields[0].num_bits = 32;
+	fields[0].out_value = NULL;
+	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 = etb->chain_pos;
+	fields[1].num_bits = 7;
+	fields[1].out_value = malloc(1);
+	buf_set_u32(fields[1].out_value, 0, 7, 4);
+	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;
+
+	fields[2].device = etb->chain_pos;
+	fields[2].num_bits = 1;
+	fields[2].out_value = malloc(1);
+	buf_set_u32(fields[2].out_value, 0, 1, 0);
+	fields[2].out_mask = NULL;
+	fields[2].in_value = NULL;
+	fields[2].in_check_value = NULL;
+	fields[2].in_check_mask = NULL;
+	fields[2].in_handler = NULL;
+	fields[2].in_handler_priv = NULL;
+	
+	jtag_add_dr_scan(3, fields, -1);
+
+	fields[0].in_handler = buf_to_u32_handler;
+	
+	for (i = 0; i < num_frames; i++)
+	{
+		/* ensure nR/W reamins set to read */
+		buf_set_u32(fields[2].out_value, 0, 1, 0);
+		
+		/* address remains set to 0x4 (RAM data) until we read the last frame */
+		if (i < num_frames - 1)
+			buf_set_u32(fields[1].out_value, 0, 7, 4);
+		else
+			buf_set_u32(fields[1].out_value, 0, 7, 0);
+		
+		fields[0].in_handler_priv = &data[i];
+		jtag_add_dr_scan(3, fields, -1);
+	}
+	
+	jtag_execute_queue();
+	
+	free(fields[1].out_value);
+	free(fields[2].out_value);
+	
+	return ERROR_OK;
+}
+
+int etb_read_reg_w_check(reg_t *reg, u8* check_value, u8* check_mask)
+{
+	etb_reg_t *etb_reg = reg->arch_info;
+	u8 reg_addr = etb_reg->addr & 0x7f;
+	scan_field_t fields[3];
+	
+	DEBUG("%i", etb_reg->addr);
+
+	jtag_add_end_state(TAP_RTI);
+	etb_scann(etb_reg->etb, 0x0);
+	etb_set_instr(etb_reg->etb, 0xc);
+	
+	fields[0].device = etb_reg->etb->chain_pos;
+	fields[0].num_bits = 32;
+	fields[0].out_value = reg->value;
+	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 = etb_reg->etb->chain_pos;
+	fields[1].num_bits = 7;
+	fields[1].out_value = malloc(1);
+	buf_set_u32(fields[1].out_value, 0, 7, reg_addr);
+	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;
+
+	fields[2].device = etb_reg->etb->chain_pos;
+	fields[2].num_bits = 1;
+	fields[2].out_value = malloc(1);
+	buf_set_u32(fields[2].out_value, 0, 1, 0);
+	fields[2].out_mask = NULL;
+	fields[2].in_value = NULL;
+	fields[2].in_check_value = NULL;
+	fields[2].in_check_mask = NULL;
+	fields[2].in_handler = NULL;
+	fields[2].in_handler_priv = NULL;
+	
+	jtag_add_dr_scan(3, fields, -1);
+	
+	/* read the identification register in the second run, to make sure we
+	 * don't read the ETB data register twice, skipping every second entry
+	 */
+	buf_set_u32(fields[1].out_value, 0, 7, 0x0);
+	fields[0].in_value = reg->value;
+	
+	jtag_set_check_value(fields+0, check_value, check_mask, NULL);
+	
+	jtag_add_dr_scan(3, fields, -1);
+
+	free(fields[1].out_value);
+	free(fields[2].out_value);
+	
+	return ERROR_OK;
+}
+
+int etb_read_reg(reg_t *reg)
+{
+	return etb_read_reg_w_check(reg, NULL, NULL);	
+}
+
+int etb_set_reg(reg_t *reg, u32 value)
+{
+	if (etb_write_reg(reg, value) != ERROR_OK)
+	{
+		ERROR("BUG: error scheduling etm register write");
+		exit(-1);
+	}
+	
+	buf_set_u32(reg->value, 0, reg->size, value);
+	reg->valid = 1;
+	reg->dirty = 0;
+	
+	return ERROR_OK;
+}
+
+int etb_set_reg_w_exec(reg_t *reg, u8 *buf)
+{
+	etb_set_reg(reg, buf_get_u32(buf, 0, reg->size));
+	
+	if (jtag_execute_queue() != ERROR_OK)
+	{
+		ERROR("register write failed");
+		exit(-1);
+	}
+	return ERROR_OK;
+}
+
+int etb_write_reg(reg_t *reg, u32 value)
+{
+	etb_reg_t *etb_reg = reg->arch_info;
+	u8 reg_addr = etb_reg->addr & 0x7f;
+	scan_field_t fields[3];
+	
+	DEBUG("%i: 0x%8.8x", etb_reg->addr, value);
+	
+	jtag_add_end_state(TAP_RTI);
+	etb_scann(etb_reg->etb, 0x0);
+	etb_set_instr(etb_reg->etb, 0xc);
+	
+	fields[0].device = etb_reg->etb->chain_pos;
+	fields[0].num_bits = 32;
+	fields[0].out_value = malloc(4);
+	buf_set_u32(fields[0].out_value, 0, 32, value);
+	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 = etb_reg->etb->chain_pos;
+	fields[1].num_bits = 7;
+	fields[1].out_value = malloc(1);
+	buf_set_u32(fields[1].out_value, 0, 7, reg_addr);
+	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;
+
+	fields[2].device = etb_reg->etb->chain_pos;
+	fields[2].num_bits = 1;
+	fields[2].out_value = malloc(1);
+	buf_set_u32(fields[2].out_value, 0, 1, 1);
+	fields[2].out_mask = NULL;
+	fields[2].in_value = NULL;
+	fields[2].in_check_value = NULL;
+	fields[2].in_check_mask = NULL;
+	fields[2].in_handler = NULL;
+	fields[2].in_handler_priv = NULL;
+	
+	jtag_add_dr_scan(3, fields, -1);
+	
+	free(fields[0].out_value);
+	free(fields[1].out_value);
+	free(fields[2].out_value);
+	
+	return ERROR_OK;
+}
+
+int etb_store_reg(reg_t *reg)
+{
+	return etb_write_reg(reg, buf_get_u32(reg->value, 0, reg->size));
+}
+
+int etb_register_commands(struct command_context_s *cmd_ctx)
+{
+	command_t *etb_cmd;
+	
+	etb_cmd = register_command(cmd_ctx, NULL, "etb", NULL, COMMAND_ANY, "Embedded Trace Buffer");
+	
+	register_command(cmd_ctx, etb_cmd, "config", handle_etb_config_command, COMMAND_CONFIG, NULL);
+
+	return ERROR_OK;
+}
+
+int handle_etb_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	target_t *target;
+	jtag_device_t *jtag_device;
+	armv4_5_common_t *armv4_5;
+	arm7_9_common_t *arm7_9;
+	
+	if (argc != 2)
+	{
+		ERROR("incomplete 'etb config <target> <chain_pos>' command");
+		exit(-1);
+	}
+	
+	target = get_target_by_num(strtoul(args[0], NULL, 0));
+	
+	if (!target)
+	{
+		ERROR("target number '%s' not defined", args[0]);
+		exit(-1);
+	}
+	
+	if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
+		return ERROR_OK;
+	}
+	
+	jtag_device = jtag_get_device(strtoul(args[1], NULL, 0));
+	
+	if (!jtag_device)
+	{
+		ERROR("jtag device number '%s' not defined", args[1]);
+		exit(-1);
+	}
+	
+	if (arm7_9->etm_ctx)
+	{
+		etb_t *etb = malloc(sizeof(etb_t));
+		
+		arm7_9->etm_ctx->capture_driver_priv = etb;
+		
+		etb->chain_pos = strtoul(args[1], NULL, 0);
+		etb->cur_scan_chain = -1;
+		etb->reg_cache = NULL;
+		etb->ram_width = 0;
+		etb->ram_depth = 0;
+	}
+	else
+	{
+		ERROR("target has no ETM defined, ETB left unconfigured");
+	}
+
+	return ERROR_OK;
+}
+
+int etb_init(etm_context_t *etm_ctx)
+{
+	etb_t *etb = etm_ctx->capture_driver_priv;
+	
+	etb->etm_ctx = etm_ctx;
+	
+	/* identify ETB RAM depth and width */
+	etb_read_reg(&etb->reg_cache->reg_list[ETB_RAM_DEPTH]);
+	etb_read_reg(&etb->reg_cache->reg_list[ETB_RAM_WIDTH]);
+	jtag_execute_queue();
+
+	etb->ram_depth = buf_get_u32(etb->reg_cache->reg_list[ETB_RAM_DEPTH].value, 0, 32);
+	etb->ram_width = buf_get_u32(etb->reg_cache->reg_list[ETB_RAM_WIDTH].value, 0, 32);
+	
+	return ERROR_OK;
+}
+
+trace_status_t etb_status(etm_context_t *etm_ctx)
+{
+	etb_t *etb = etm_ctx->capture_driver_priv;
+	
+	etb->etm_ctx = etm_ctx;
+	
+	/* if tracing is currently idle, return this information */
+	if (etm_ctx->capture_status == TRACE_IDLE)
+	{
+		return etm_ctx->capture_status;
+	}
+	else if (etm_ctx->capture_status & TRACE_RUNNING)
+	{
+		reg_t *etb_status_reg = &etb->reg_cache->reg_list[ETB_STATUS];
+		int etb_timeout = 100;
+		
+		/* trace is running, check the ETB status flags */
+		etb_get_reg(etb_status_reg);
+	
+		/* check Full bit to identify an overflow */
+		if (buf_get_u32(etb_status_reg->value, 0, 1) == 1)
+			etm_ctx->capture_status |= TRACE_OVERFLOWED;
+
+		/* check Triggered bit to identify trigger condition */
+		if (buf_get_u32(etb_status_reg->value, 1, 1) == 1)
+			etm_ctx->capture_status |= TRACE_TRIGGERED;
+
+		/* check AcqComp to identify trace completion */
+		if (buf_get_u32(etb_status_reg->value, 2, 1) == 1)
+		{
+			while (etb_timeout-- && (buf_get_u32(etb_status_reg->value, 3, 1) == 0))
+			{
+				/* wait for data formatter idle */
+				etb_get_reg(etb_status_reg);
+			}
+			
+			if (etb_timeout == 0)
+			{
+				ERROR("AcqComp set but DFEmpty won't go high, ETB status: 0x%x",
+					buf_get_u32(etb_status_reg->value, 0, etb_status_reg->size));
+			}
+			
+			if (!(etm_ctx->capture_status && TRACE_TRIGGERED))
+			{
+				ERROR("trace completed, but no trigger condition detected");
+			}
+			
+			etm_ctx->capture_status &= ~TRACE_RUNNING;
+			etm_ctx->capture_status |= TRACE_COMPLETED;
+		}
+	}
+	
+	return etm_ctx->capture_status;
+}
+
+int etb_read_trace(etm_context_t *etm_ctx)
+{
+	etb_t *etb = etm_ctx->capture_driver_priv;
+	int first_frame = 0;
+	int num_frames = etb->ram_depth;
+	u32 *trace_data = NULL;
+	int i, j;
+	
+	etb_read_reg(&etb->reg_cache->reg_list[ETB_STATUS]);
+	etb_read_reg(&etb->reg_cache->reg_list[ETB_RAM_WRITE_POINTER]);
+	jtag_execute_queue();
+	
+	/* check if we overflowed, and adjust first frame of the trace accordingly
+	 * if we didn't overflow, read only up to the frame that would be written next,
+	 * i.e. don't read invalid entries
+	 */
+	if (buf_get_u32(etb->reg_cache->reg_list[ETB_STATUS].value, 0, 1))
+	{
+		first_frame = buf_get_u32(etb->reg_cache->reg_list[ETB_RAM_WRITE_POINTER].value, 0, 32);
+	}
+	else
+	{
+		num_frames = buf_get_u32(etb->reg_cache->reg_list[ETB_RAM_WRITE_POINTER].value, 0, 32);
+	}
+	
+	etb_write_reg(&etb->reg_cache->reg_list[ETB_RAM_READ_POINTER], first_frame);
+
+	/* read data into temporary array for unpacking */	
+	trace_data = malloc(sizeof(u32) * num_frames);
+	etb_read_ram(etb, trace_data, num_frames);
+
+	if (etm_ctx->trace_depth > 0)
+	{
+		free(etm_ctx->trace_data);
+	}
+	
+	if ((etm_ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_4BIT)
+		etm_ctx->trace_depth = num_frames * 3;
+	else if ((etm_ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_8BIT)
+		etm_ctx->trace_depth = num_frames * 2;
+	else
+		etm_ctx->trace_depth = num_frames;
+
+	etm_ctx->trace_data = malloc(sizeof(etmv1_trace_data_t) * etm_ctx->trace_depth);
+	
+	for (i = 0, j = 0; i < num_frames; i++)
+	{
+		if ((etm_ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_4BIT)
+		{
+			/* trace word j */
+			etm_ctx->trace_data[j].pipestat = trace_data[i] & 0x7;
+			etm_ctx->trace_data[j].packet = (trace_data[i] & 0x78) >> 3;
+			etm_ctx->trace_data[j].flags = 0;
+			if ((trace_data[i] & 0x80) >> 7)
+			{
+				etm_ctx->trace_data[j].flags |= ETMV1_TRACESYNC_CYCLE;
+			}
+			if (etm_ctx->trace_data[j].pipestat == STAT_TR)
+			{
+				etm_ctx->trace_data[j].pipestat = etm_ctx->trace_data[j].packet & 0x7;
+				etm_ctx->trace_data[j].flags |= ETMV1_TRIGGER_CYCLE;
+			}
+			
+			/* trace word j+1 */
+			etm_ctx->trace_data[j+1].pipestat = (trace_data[i] & 0x100) >> 8;
+			etm_ctx->trace_data[j+1].packet = (trace_data[i] & 0x7800) >> 11;
+			etm_ctx->trace_data[j+1].flags = 0;
+			if ((trace_data[i] & 0x8000) >> 15)
+			{
+				etm_ctx->trace_data[j+1].flags |= ETMV1_TRACESYNC_CYCLE;
+			}
+			if (etm_ctx->trace_data[j+1].pipestat == STAT_TR)
+			{
+				etm_ctx->trace_data[j+1].pipestat = etm_ctx->trace_data[j+1].packet & 0x7;
+				etm_ctx->trace_data[j+1].flags |= ETMV1_TRIGGER_CYCLE;
+			}
+			
+			/* trace word j+2 */
+			etm_ctx->trace_data[j+2].pipestat = (trace_data[i] & 0x10000) >> 16;
+			etm_ctx->trace_data[j+2].packet = (trace_data[i] & 0x780000) >> 19;
+			etm_ctx->trace_data[j+2].flags = 0;
+			if ((trace_data[i] & 0x800000) >> 23)
+			{
+				etm_ctx->trace_data[j+2].flags |= ETMV1_TRACESYNC_CYCLE;
+			}
+			if (etm_ctx->trace_data[j+2].pipestat == STAT_TR)
+			{
+				etm_ctx->trace_data[j+2].pipestat = etm_ctx->trace_data[j+2].packet & 0x7;
+				etm_ctx->trace_data[j+2].flags |= ETMV1_TRIGGER_CYCLE;
+			}
+			
+			j += 3;
+		}
+		else if ((etm_ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_8BIT)
+		{
+			/* trace word j */
+			etm_ctx->trace_data[j].pipestat = trace_data[i] & 0x7;
+			etm_ctx->trace_data[j].packet = (trace_data[i] & 0x7f8) >> 3;
+			etm_ctx->trace_data[j].flags = 0;
+			if ((trace_data[i] & 0x800) >> 11)
+			{
+				etm_ctx->trace_data[j].flags |= ETMV1_TRACESYNC_CYCLE;
+			}
+			if (etm_ctx->trace_data[j].pipestat == STAT_TR)
+			{
+				etm_ctx->trace_data[j].pipestat = etm_ctx->trace_data[j].packet & 0x7;
+				etm_ctx->trace_data[j].flags |= ETMV1_TRIGGER_CYCLE;
+			}
+
+			/* trace word j+1 */
+			etm_ctx->trace_data[j+1].pipestat = (trace_data[i] & 0x7000) >> 12;
+			etm_ctx->trace_data[j+1].packet = (trace_data[i] & 0x7f8000) >> 15;
+			etm_ctx->trace_data[j+1].flags = 0;
+			if ((trace_data[i] & 0x800000) >> 23)
+			{
+				etm_ctx->trace_data[j+1].flags |= ETMV1_TRACESYNC_CYCLE;
+			}
+			if (etm_ctx->trace_data[j+1].pipestat == STAT_TR)
+			{
+				etm_ctx->trace_data[j+1].pipestat = etm_ctx->trace_data[j+1].packet & 0x7;
+				etm_ctx->trace_data[j+1].flags |= ETMV1_TRIGGER_CYCLE;
+			}
+			
+			j += 2;
+		}
+		else
+		{
+			/* trace word j */
+			etm_ctx->trace_data[j].pipestat = trace_data[i] & 0x7;
+			etm_ctx->trace_data[j].packet = (trace_data[i] & 0x7fff8) >> 3;
+			etm_ctx->trace_data[j].flags = 0;
+			if ((trace_data[i] & 0x80000) >> 19)
+			{
+				etm_ctx->trace_data[j].flags |= ETMV1_TRACESYNC_CYCLE;
+			}
+			if (etm_ctx->trace_data[j].pipestat == STAT_TR)
+			{
+				etm_ctx->trace_data[j].pipestat = etm_ctx->trace_data[j].packet & 0x7;
+				etm_ctx->trace_data[j].flags |= ETMV1_TRIGGER_CYCLE;
+			}
+			
+			j += 1;
+		}
+	}
+	
+	free(trace_data);
+	
+	return ERROR_OK;
+}
+
+int etb_start_capture(etm_context_t *etm_ctx)
+{
+	etb_t *etb = etm_ctx->capture_driver_priv;
+	u32 etb_ctrl_value = 0x1;
+	u32 trigger_count;
+
+	if ((etm_ctx->portmode & ETM_PORT_MODE_MASK) == ETM_PORT_DEMUXED)
+	{
+		if ((etm_ctx->portmode & ETM_PORT_WIDTH_MASK) != ETM_PORT_8BIT)
+		{
+			ERROR("ETB can't run in demultiplexed mode with a 4 or 16 bit port");
+			return ERROR_ETM_PORTMODE_NOT_SUPPORTED;
+		}
+		etb_ctrl_value |= 0x2;
+	}
+	
+	if ((etm_ctx->portmode & ETM_PORT_MODE_MASK) == ETM_PORT_MUXED)
+		return ERROR_ETM_PORTMODE_NOT_SUPPORTED;
+	
+	trigger_count = (etb->ram_depth * etm_ctx->trigger_percent) / 100;
+	
+	etb_write_reg(&etb->reg_cache->reg_list[ETB_TRIGGER_COUNTER], trigger_count);
+	etb_write_reg(&etb->reg_cache->reg_list[ETB_RAM_WRITE_POINTER], 0x0);
+	etb_write_reg(&etb->reg_cache->reg_list[ETB_CTRL], etb_ctrl_value);
+	jtag_execute_queue();
+	
+	/* we're starting a new trace, initialize capture status */
+	etm_ctx->capture_status = TRACE_RUNNING;
+	
+	return ERROR_OK; 
+}
+
+int etb_stop_capture(etm_context_t *etm_ctx)
+{
+	etb_t *etb = etm_ctx->capture_driver_priv;
+	reg_t *etb_ctrl_reg = &etb->reg_cache->reg_list[ETB_CTRL];
+
+	etb_write_reg(etb_ctrl_reg, 0x0);
+	jtag_execute_queue();
+	
+	/* trace stopped, just clear running flag, but preserve others */ 
+	etm_ctx->capture_status &= ~TRACE_RUNNING;
+	
+	return ERROR_OK;
+}
+
+etm_capture_driver_t etb_capture_driver =
+{
+	.name = "etb",
+	.register_commands = etb_register_commands,
+	.init = etb_init,
+	.status = etb_status,
+	.start_capture = etb_start_capture,
+	.stop_capture = etb_stop_capture,
+	.read_trace = etb_read_trace,
+};
diff --git a/src/target/etm.c b/src/target/etm.c
index 0d20b0d5866060f37bddeef1d9c4b00277960d6d..fe4ac77f6dd7386456b69edc828e17981a14a57d 100644
--- a/src/target/etm.c
+++ b/src/target/etm.c
@@ -1,1863 +1,1863 @@
-/***************************************************************************
- *   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.             *
- ***************************************************************************/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <string.h>
-
-#include "etm.h"
-#include "etb.h"
-
-#include "armv4_5.h"
-#include "arm7_9_common.h"
-#include "arm_disassembler.h"
-#include "arm_simulator.h"
-
-#include "log.h"
-#include "arm_jtag.h"
-#include "types.h"
-#include "binarybuffer.h"
-#include "target.h"
-#include "register.h"
-#include "jtag.h"
-#include "fileio.h"
-
-#include <stdlib.h>
-
-/* ETM register access functionality 
- * 
- */
-
-bitfield_desc_t etm_comms_ctrl_bitfield_desc[] = 
-{
-	{"R", 1},
-	{"W", 1},
-	{"reserved", 26},
-	{"version", 4}
-};
-
-int etm_reg_arch_info[] =
-{
-	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
-	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
-	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 
-	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 
-	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
-	0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 
-	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
-	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
-	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 
-	0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 
-	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
-	0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
-	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x67, 
-	0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 
-};
-
-int etm_reg_arch_size_info[] =
-{
-	32, 32, 17, 8, 3, 9, 32, 16,
-	17, 26, 25, 8, 17, 32, 32, 17,
-	32, 32, 32, 32, 32, 32, 32, 32, 
-	32, 32, 32, 32, 32, 32, 32, 32, 
-	7, 7, 7, 7, 7, 7, 7, 7, 
-	7, 7, 7, 7, 7, 7, 7, 7, 
-	32, 32, 32, 32, 32, 32, 32, 32, 
-	32, 32, 32, 32, 32, 32, 32, 32, 
-	32, 32, 32, 32, 32, 32, 32, 32, 
-	32, 32, 32, 32, 32, 32, 32, 32, 
-	16, 16, 16, 16, 18, 18, 18, 18,
-	17, 17, 17, 17, 16, 16, 16, 16,
-	17, 17, 17, 17, 17, 17, 2, 
-	17, 17, 17, 17, 32, 32, 32, 32 
-};
-
-char* etm_reg_list[] =
-{
-	"ETM_CTRL",
-	"ETM_CONFIG",
-	"ETM_TRIG_EVENT",
-	"ETM_MMD_CTRL",
-	"ETM_STATUS",
-	"ETM_SYS_CONFIG",
-	"ETM_TRACE_RESOURCE_CTRL",
-	"ETM_TRACE_EN_CTRL2",
-	"ETM_TRACE_EN_EVENT",
-	"ETM_TRACE_EN_CTRL1",
-	"ETM_FIFOFULL_REGION",
-	"ETM_FIFOFULL_LEVEL",
-	"ETM_VIEWDATA_EVENT",
-	"ETM_VIEWDATA_CTRL1",
-	"ETM_VIEWDATA_CTRL2",
-	"ETM_VIEWDATA_CTRL3",
-	"ETM_ADDR_COMPARATOR_VALUE1",
-	"ETM_ADDR_COMPARATOR_VALUE2",
-	"ETM_ADDR_COMPARATOR_VALUE3",
-	"ETM_ADDR_COMPARATOR_VALUE4",
-	"ETM_ADDR_COMPARATOR_VALUE5",
-	"ETM_ADDR_COMPARATOR_VALUE6",
-	"ETM_ADDR_COMPARATOR_VALUE7",
-	"ETM_ADDR_COMPARATOR_VALUE8",
-	"ETM_ADDR_COMPARATOR_VALUE9",
-	"ETM_ADDR_COMPARATOR_VALUE10",
-	"ETM_ADDR_COMPARATOR_VALUE11",
-	"ETM_ADDR_COMPARATOR_VALUE12",
-	"ETM_ADDR_COMPARATOR_VALUE13",
-	"ETM_ADDR_COMPARATOR_VALUE14",
-	"ETM_ADDR_COMPARATOR_VALUE15",
-	"ETM_ADDR_COMPARATOR_VALUE16",
-	"ETM_ADDR_ACCESS_TYPE1",
-	"ETM_ADDR_ACCESS_TYPE2",
-	"ETM_ADDR_ACCESS_TYPE3",
-	"ETM_ADDR_ACCESS_TYPE4",
-	"ETM_ADDR_ACCESS_TYPE5",
-	"ETM_ADDR_ACCESS_TYPE6",
-	"ETM_ADDR_ACCESS_TYPE7",
-	"ETM_ADDR_ACCESS_TYPE8",
-	"ETM_ADDR_ACCESS_TYPE9",
-	"ETM_ADDR_ACCESS_TYPE10",
-	"ETM_ADDR_ACCESS_TYPE11",
-	"ETM_ADDR_ACCESS_TYPE12",
-	"ETM_ADDR_ACCESS_TYPE13",
-	"ETM_ADDR_ACCESS_TYPE14",
-	"ETM_ADDR_ACCESS_TYPE15",
-	"ETM_ADDR_ACCESS_TYPE16",
-	"ETM_DATA_COMPARATOR_VALUE1",
-	"ETM_DATA_COMPARATOR_VALUE2",
-	"ETM_DATA_COMPARATOR_VALUE3",
-	"ETM_DATA_COMPARATOR_VALUE4",
-	"ETM_DATA_COMPARATOR_VALUE5",
-	"ETM_DATA_COMPARATOR_VALUE6",
-	"ETM_DATA_COMPARATOR_VALUE7",
-	"ETM_DATA_COMPARATOR_VALUE8",
-	"ETM_DATA_COMPARATOR_VALUE9",
-	"ETM_DATA_COMPARATOR_VALUE10",
-	"ETM_DATA_COMPARATOR_VALUE11",
-	"ETM_DATA_COMPARATOR_VALUE12",
-	"ETM_DATA_COMPARATOR_VALUE13",
-	"ETM_DATA_COMPARATOR_VALUE14",
-	"ETM_DATA_COMPARATOR_VALUE15",
-	"ETM_DATA_COMPARATOR_VALUE16",
-	"ETM_DATA_COMPARATOR_MASK1",
-	"ETM_DATA_COMPARATOR_MASK2",
-	"ETM_DATA_COMPARATOR_MASK3",
-	"ETM_DATA_COMPARATOR_MASK4",
-	"ETM_DATA_COMPARATOR_MASK5",
-	"ETM_DATA_COMPARATOR_MASK6",
-	"ETM_DATA_COMPARATOR_MASK7",
-	"ETM_DATA_COMPARATOR_MASK8",
-	"ETM_DATA_COMPARATOR_MASK9",
-	"ETM_DATA_COMPARATOR_MASK10",
-	"ETM_DATA_COMPARATOR_MASK11",
-	"ETM_DATA_COMPARATOR_MASK12",
-	"ETM_DATA_COMPARATOR_MASK13",
-	"ETM_DATA_COMPARATOR_MASK14",
-	"ETM_DATA_COMPARATOR_MASK15",
-	"ETM_DATA_COMPARATOR_MASK16",
-	"ETM_COUNTER_INITAL_VALUE1",
-	"ETM_COUNTER_INITAL_VALUE2",
-	"ETM_COUNTER_INITAL_VALUE3",
-	"ETM_COUNTER_INITAL_VALUE4",
-	"ETM_COUNTER_ENABLE1",
-	"ETM_COUNTER_ENABLE2",
-	"ETM_COUNTER_ENABLE3",
-	"ETM_COUNTER_ENABLE4",
-	"ETM_COUNTER_RELOAD_VALUE1",
-	"ETM_COUNTER_RELOAD_VALUE2",
-	"ETM_COUNTER_RELOAD_VALUE3",
-	"ETM_COUNTER_RELOAD_VALUE4",
-	"ETM_COUNTER_VALUE1",
-	"ETM_COUNTER_VALUE2",
-	"ETM_COUNTER_VALUE3",
-	"ETM_COUNTER_VALUE4",
-	"ETM_SEQUENCER_CTRL1",
-	"ETM_SEQUENCER_CTRL2",
-	"ETM_SEQUENCER_CTRL3",
-	"ETM_SEQUENCER_CTRL4",
-	"ETM_SEQUENCER_CTRL5",
-	"ETM_SEQUENCER_CTRL6",
-	"ETM_SEQUENCER_STATE",
-	"ETM_EXTERNAL_OUTPUT1",
-	"ETM_EXTERNAL_OUTPUT2",
-	"ETM_EXTERNAL_OUTPUT3",
-	"ETM_EXTERNAL_OUTPUT4",
-	"ETM_CONTEXTID_COMPARATOR_VALUE1",
-	"ETM_CONTEXTID_COMPARATOR_VALUE2",
-	"ETM_CONTEXTID_COMPARATOR_VALUE3",
-	"ETM_CONTEXTID_COMPARATOR_MASK"
-};  
-
-int etm_reg_arch_type = -1;
-
-int etm_get_reg(reg_t *reg);
-int etm_set_reg(reg_t *reg, u32 value);
-int etm_set_reg_w_exec(reg_t *reg, u8 *buf);
-
-int etm_write_reg(reg_t *reg, u32 value);
-int etm_read_reg(reg_t *reg);
-
-command_t *etm_cmd = NULL;
-
-reg_cache_t* etm_build_reg_cache(target_t *target, arm_jtag_t *jtag_info, etm_context_t *etm_ctx)
-{
-	reg_cache_t *reg_cache = malloc(sizeof(reg_cache_t));
-	reg_t *reg_list = NULL;
-	etm_reg_t *arch_info = NULL;
-	int num_regs = sizeof(etm_reg_arch_info)/sizeof(int);
-	int i;
-	u32 etm_ctrl_value;
-	
-	/* register a register arch-type for etm registers only once */
-	if (etm_reg_arch_type == -1)
-		etm_reg_arch_type = register_reg_arch_type(etm_get_reg, etm_set_reg_w_exec);
-	
-	/* the actual registers are kept in two arrays */
-	reg_list = calloc(num_regs, sizeof(reg_t));
-	arch_info = calloc(num_regs, sizeof(etm_reg_t));
-	
-	/* fill in values for the reg cache */
-	reg_cache->name = "etm registers";
-	reg_cache->next = NULL;
-	reg_cache->reg_list = reg_list;
-	reg_cache->num_regs = num_regs;
-	
-	/* set up registers */
-	for (i = 0; i < num_regs; i++)
-	{
-		reg_list[i].name = etm_reg_list[i];
-		reg_list[i].size = 32;
-		reg_list[i].dirty = 0;
-		reg_list[i].valid = 0;
-		reg_list[i].bitfield_desc = NULL;
-		reg_list[i].num_bitfields = 0;
-		reg_list[i].value = calloc(1, 4);
-		reg_list[i].arch_info = &arch_info[i];
-		reg_list[i].arch_type = etm_reg_arch_type;
-		reg_list[i].size = etm_reg_arch_size_info[i];
-		arch_info[i].addr = etm_reg_arch_info[i];
-		arch_info[i].jtag_info = jtag_info;
-	}
-
-	/* initialize some ETM control register settings */	
-	etm_get_reg(&reg_list[ETM_CTRL]);
-	etm_ctrl_value = buf_get_u32(reg_list[ETM_CTRL].value, 0, reg_list[ETM_CTRL].size);
-	
-	/* clear the ETM powerdown bit (0) */
-	etm_ctrl_value &= ~0x1;
-		
-	/* configure port width (6:4), mode (17:16) and clocking (13) */
-	etm_ctrl_value = (etm_ctrl_value & 
-		~ETM_PORT_WIDTH_MASK & ~ETM_PORT_MODE_MASK & ~ETM_PORT_CLOCK_MASK)
-		| etm_ctx->portmode;
-	
-	buf_set_u32(reg_list[ETM_CTRL].value, 0, reg_list[ETM_CTRL].size, etm_ctrl_value);
-	etm_store_reg(&reg_list[ETM_CTRL]);
-	
-	/* the ETM might have an ETB connected */
-	if (strcmp(etm_ctx->capture_driver->name, "etb") == 0)
-	{
-		etb_t *etb = etm_ctx->capture_driver_priv;
-		
-		if (!etb)
-		{
-			ERROR("etb selected as etm capture driver, but no ETB configured");
-			return ERROR_OK;
-		}
-		
-		reg_cache->next = etb_build_reg_cache(etb);
-		
-		etb->reg_cache = reg_cache->next;
-	}
-	
-	if (etm_ctx->capture_driver->init(etm_ctx) != ERROR_OK)
-	{
-		ERROR("ETM capture driver initialization failed");
-		exit(-1);
-	}
-	
-	return reg_cache;
-}
-
-int etm_get_reg(reg_t *reg)
-{
-	if (etm_read_reg(reg) != ERROR_OK)
-	{
-		ERROR("BUG: error scheduling etm register read");
-		exit(-1);
-	}
-	
-	if (jtag_execute_queue() != ERROR_OK)
-	{
-		ERROR("register read failed");
-	}
-	
-	return ERROR_OK;
-}
-
-int etm_read_reg_w_check(reg_t *reg, u8* check_value, u8* check_mask)
-{
-	etm_reg_t *etm_reg = reg->arch_info;
-	u8 reg_addr = etm_reg->addr & 0x7f;
-	scan_field_t fields[3];
-	
-	DEBUG("%i", etm_reg->addr);
-
-	jtag_add_end_state(TAP_RTI);
-	arm_jtag_scann(etm_reg->jtag_info, 0x6);
-	arm_jtag_set_instr(etm_reg->jtag_info, etm_reg->jtag_info->intest_instr, NULL);
-	
-	fields[0].device = etm_reg->jtag_info->chain_pos;
-	fields[0].num_bits = 32;
-	fields[0].out_value = reg->value;
-	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 = etm_reg->jtag_info->chain_pos;
-	fields[1].num_bits = 7;
-	fields[1].out_value = malloc(1);
-	buf_set_u32(fields[1].out_value, 0, 7, reg_addr);
-	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;
-
-	fields[2].device = etm_reg->jtag_info->chain_pos;
-	fields[2].num_bits = 1;
-	fields[2].out_value = malloc(1);
-	buf_set_u32(fields[2].out_value, 0, 1, 0);
-	fields[2].out_mask = NULL;
-	fields[2].in_value = NULL;
-	fields[2].in_check_value = NULL;
-	fields[2].in_check_mask = NULL;
-	fields[2].in_handler = NULL;
-	fields[2].in_handler_priv = NULL;
-	
-	jtag_add_dr_scan(3, fields, -1, NULL);
-	
-	fields[0].in_value = reg->value;
-	jtag_set_check_value(fields+0, check_value, check_mask, NULL);	
-		
-	jtag_add_dr_scan(3, fields, -1, NULL);
-
-	free(fields[1].out_value);
-	free(fields[2].out_value);
-	
-	return ERROR_OK;
-}
-
-int etm_read_reg(reg_t *reg)
-{
-	return etm_read_reg_w_check(reg, NULL, NULL);	
-}
-
-int etm_set_reg(reg_t *reg, u32 value)
-{
-	if (etm_write_reg(reg, value) != ERROR_OK)
-	{
-		ERROR("BUG: error scheduling etm register write");
-		exit(-1);
-	}
-	
-	buf_set_u32(reg->value, 0, reg->size, value);
-	reg->valid = 1;
-	reg->dirty = 0;
-	
-	return ERROR_OK;
-}
-
-int etm_set_reg_w_exec(reg_t *reg, u8 *buf)
-{
-	etm_set_reg(reg, buf_get_u32(buf, 0, reg->size));
-	
-	if (jtag_execute_queue() != ERROR_OK)
-	{
-		ERROR("register write failed");
-		exit(-1);
-	}
-	return ERROR_OK;
-}
-
-int etm_write_reg(reg_t *reg, u32 value)
-{
-	etm_reg_t *etm_reg = reg->arch_info;
-	u8 reg_addr = etm_reg->addr & 0x7f;
-	scan_field_t fields[3];
-	
-	DEBUG("%i: 0x%8.8x", etm_reg->addr, value);
-	
-	jtag_add_end_state(TAP_RTI);
-	arm_jtag_scann(etm_reg->jtag_info, 0x6);
-	arm_jtag_set_instr(etm_reg->jtag_info, etm_reg->jtag_info->intest_instr, NULL);
-	
-	fields[0].device = etm_reg->jtag_info->chain_pos;
-	fields[0].num_bits = 32;
-	fields[0].out_value = malloc(4);
-	buf_set_u32(fields[0].out_value, 0, 32, value);
-	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 = etm_reg->jtag_info->chain_pos;
-	fields[1].num_bits = 7;
-	fields[1].out_value = malloc(1);
-	buf_set_u32(fields[1].out_value, 0, 7, reg_addr);
-	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;
-
-	fields[2].device = etm_reg->jtag_info->chain_pos;
-	fields[2].num_bits = 1;
-	fields[2].out_value = malloc(1);
-	buf_set_u32(fields[2].out_value, 0, 1, 1);
-	fields[2].out_mask = NULL;
-	fields[2].in_value = NULL;
-	fields[2].in_check_value = NULL;
-	fields[2].in_check_mask = NULL;
-	fields[2].in_handler = NULL;
-	fields[2].in_handler_priv = NULL;
-	
-	jtag_add_dr_scan(3, fields, -1, NULL);
-	
-	free(fields[0].out_value);
-	free(fields[1].out_value);
-	free(fields[2].out_value);
-	
-	return ERROR_OK;
-}
-
-int etm_store_reg(reg_t *reg)
-{
-	return etm_write_reg(reg, buf_get_u32(reg->value, 0, reg->size));
-}
-
-/* ETM trace analysis functionality
- * 
- */
-extern etm_capture_driver_t etb_capture_driver;
-extern etm_capture_driver_t etm_dummy_capture_driver;
-#if BUILD_OOCD_TRACE == 1
-extern etm_capture_driver_t oocd_trace_capture_driver;
-#endif
-
-etm_capture_driver_t *etm_capture_drivers[] = 
-{
-	&etb_capture_driver,
-	&etm_dummy_capture_driver,
-#if BUILD_OOCD_TRACE == 1
-	&oocd_trace_capture_driver,
-#endif
-	NULL
-};
-
-char *etmv1v1_branch_reason_strings[] =
-{
-	"normal PC change",
-	"tracing enabled",
-	"trace restarted after overflow",
-	"exit from debug",
-	"periodic synchronization",
-	"reserved",
-	"reserved",
-	"reserved",
-};
-
-int etm_read_instruction(etm_context_t *ctx, arm_instruction_t *instruction)
-{
-	int i;
-	int section = -1;
-	u32 size_read;
-	u32 opcode;
-	int retval;
-	
-	if (!ctx->image)
-		return ERROR_TRACE_IMAGE_UNAVAILABLE;
-	
-	/* search for the section the current instruction belongs to */	
-	for (i = 0; i < ctx->image->num_sections; i++)
-	{
-		if ((ctx->image->sections[i].base_address <= ctx->current_pc) &&
-			(ctx->image->sections[i].base_address + ctx->image->sections[i].size > ctx->current_pc))
-		{
-			section = i;
-			break;
-		}
-	}
-	
-	if (section == -1)
-	{
-		/* current instruction couldn't be found in the image */
-		return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
-	}
-	
-	if (ctx->core_state == ARMV4_5_STATE_ARM)
-	{
-		u8 buf[4];
-		if ((retval = image_read_section(ctx->image, section, 
-			ctx->current_pc - ctx->image->sections[section].base_address,
-			4, buf, &size_read)) != ERROR_OK)
-		{
-			ERROR("error while reading instruction: %i", retval);
-			return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
-		}
-		opcode = target_buffer_get_u32(ctx->target, buf);
-		arm_evaluate_opcode(opcode, ctx->current_pc, instruction);
-	}
-	else if (ctx->core_state == ARMV4_5_STATE_THUMB)
-	{
-		u8 buf[2];
-		if ((retval = image_read_section(ctx->image, section, 
-			ctx->current_pc - ctx->image->sections[section].base_address,
-			2, buf, &size_read)) != ERROR_OK)
-		{
-			ERROR("error while reading instruction: %i", retval);
-			return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
-		}
-		opcode = target_buffer_get_u16(ctx->target, buf);
-		thumb_evaluate_opcode(opcode, ctx->current_pc, instruction);
-	}
-	else if (ctx->core_state == ARMV4_5_STATE_JAZELLE)
-	{
-		ERROR("BUG: tracing of jazelle code not supported");
-		exit(-1);
-	}
-	else
-	{
-		ERROR("BUG: unknown core state encountered");
-		exit(-1);
-	}
-	
-	return ERROR_OK;
-}
-
-int etmv1_next_packet(etm_context_t *ctx, u8 *packet, int apo)
-{
-	while (ctx->data_index < ctx->trace_depth)
-	{
-		/* if the caller specified an address packet offset, skip until the
-		 * we reach the n-th cycle marked with tracesync */
-		if (apo > 0)
-		{
-			if (ctx->trace_data[ctx->data_index].flags & ETMV1_TRACESYNC_CYCLE)
-				apo--;
-			
-			if (apo > 0)
-			{
-				ctx->data_index++;
-				ctx->data_half = 0;
-			}
-			continue;
-		}
-		
-		/* no tracedata output during a TD cycle
-		 * or in a trigger cycle */
-		if ((ctx->trace_data[ctx->data_index].pipestat == STAT_TD)
-			|| (ctx->trace_data[ctx->data_index].flags & ETMV1_TRIGGER_CYCLE))
-		{
-			ctx->data_index++;
-			ctx->data_half = 0;
-			continue;
-		}
-		
-		if ((ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_16BIT)
-		{
-			if (ctx->data_half == 0)
-			{
-				*packet = ctx->trace_data[ctx->data_index].packet & 0xff;
-				ctx->data_half = 1;
-			}
-			else
-			{
-				*packet = (ctx->trace_data[ctx->data_index].packet & 0xff00) >> 8;
-				ctx->data_half = 0;
-				ctx->data_index++;
-			}
-		}
-		else if ((ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_8BIT)
-		{
-			*packet = ctx->trace_data[ctx->data_index].packet & 0xff;
-			ctx->data_index++;
-		}
-		else
-		{
-			/* on a 4-bit port, a packet will be output during two consecutive cycles */
-			if (ctx->data_index > (ctx->trace_depth - 2))
-				return -1;
-			
-			*packet = ctx->trace_data[ctx->data_index].packet & 0xf;
-			*packet |= (ctx->trace_data[ctx->data_index + 1].packet & 0xf) << 4;
-			ctx->data_index += 2;
-		}
-					
-		return 0;
-	}
-	
-	return -1;
-}
-
-int etmv1_branch_address(etm_context_t *ctx)
-{
-	int retval;
-	u8 packet;
-	int shift = 0;
-	int apo;
-	int i;
-	
-	/* quit analysis if less than two cycles are left in the trace
-	 * because we can't extract the APO */
-	if (ctx->data_index > (ctx->trace_depth - 2))
-		return -1;
-		
-	/* a BE could be output during an APO cycle, skip the current
-	 * and continue with the new one */
-	if (ctx->trace_data[ctx->pipe_index + 1].pipestat & 0x4)
-		return 1;
-	if (ctx->trace_data[ctx->pipe_index + 2].pipestat & 0x4)
-		return 2;
-		
-	/* address packet offset encoded in the next two cycles' pipestat bits */
-	apo = ctx->trace_data[ctx->pipe_index + 1].pipestat & 0x3;
-	apo |= (ctx->trace_data[ctx->pipe_index + 2].pipestat & 0x3) << 2;
-	
-	/* count number of tracesync cycles between current pipe_index and data_index
-	 * i.e. the number of tracesyncs that data_index already passed by
-	 * to subtract them from the APO */
-	for (i = ctx->pipe_index; i < ctx->data_index; i++)
-	{
-		if (ctx->trace_data[ctx->pipe_index + 1].pipestat & ETMV1_TRACESYNC_CYCLE)
-			apo--;
-	}
-	
-	/* extract up to four 7-bit packets */
-	do {
-		if ((retval = etmv1_next_packet(ctx, &packet, (shift == 0) ? apo + 1 : 0)) != 0)
-			return -1;
-		ctx->last_branch &= ~(0x7f << shift);
-		ctx->last_branch |= (packet & 0x7f) << shift;
-		shift += 7;
-	} while ((packet & 0x80) && (shift < 28));
-	
-	/* one last packet holding 4 bits of the address, plus the branch reason code */
-	if ((shift == 28) && (packet & 0x80))
-	{
-		if ((retval = etmv1_next_packet(ctx, &packet, 0)) != 0)
-			return -1;
-		ctx->last_branch &= 0x0fffffff;
-		ctx->last_branch |= (packet & 0x0f) << 28;
-		ctx->last_branch_reason = (packet & 0x70) >> 4;
-		shift += 4;
-	}
-	else
-	{
-		ctx->last_branch_reason = 0;
-	}
-	
-	if (shift == 32)
-	{
-		ctx->pc_ok = 1;
-	}
-	
-	/* if a full address was output, we might have branched into Jazelle state */
-	if ((shift == 32) && (packet & 0x80))
-	{
-		ctx->core_state = ARMV4_5_STATE_JAZELLE;
-	}
-	else
-	{
-		/* if we didn't branch into Jazelle state, the current processor state is
-		 * encoded in bit 0 of the branch target address */
-		if (ctx->last_branch & 0x1)
-		{
-			ctx->core_state = ARMV4_5_STATE_THUMB;
-			ctx->last_branch &= ~0x1;
-		}
-		else
-		{
-			ctx->core_state = ARMV4_5_STATE_ARM;
-			ctx->last_branch &= ~0x3;
-		}
-	}
-	
-	return 0;
-}
-
-int etmv1_data(etm_context_t *ctx, int size, u32 *data)
-{
-	int j;
-	u8 buf[4];
-	int retval;
-	
-	for (j = 0; j < size; j++)
-	{
-		if ((retval = etmv1_next_packet(ctx, &buf[j], 0)) != 0)
-			return -1;
-	}
-	
-	if (size == 8)
-		ERROR("TODO: add support for 64-bit values");
-	else if (size == 4)
-		*data = target_buffer_get_u32(ctx->target, buf);
-	else if (size == 2)
-		*data = target_buffer_get_u16(ctx->target, buf);
-	else if (size == 1)
-		*data = buf[0];
-		
-	return 0;
-}
-
-int etmv1_analyze_trace(etm_context_t *ctx, struct command_context_s *cmd_ctx)
-{
-	int retval;
-	arm_instruction_t instruction;
-	
-	/* read the trace data if it wasn't read already */
-	if (ctx->trace_depth == 0)
-		ctx->capture_driver->read_trace(ctx);
-	
-	/* start at the beginning of the captured trace */
-	ctx->pipe_index = 0;
-	ctx->data_index = 0;
-	ctx->data_half = 0;
-
-	/* neither the PC nor the data pointer are valid */	
-	ctx->pc_ok = 0;
-	ctx->ptr_ok = 0;
-	
-	while (ctx->pipe_index < ctx->trace_depth)
-	{
-		u8 pipestat = ctx->trace_data[ctx->pipe_index].pipestat;
-		u32 next_pc = ctx->current_pc;
-		u32 old_data_index = ctx->data_index;
-		u32 old_data_half = ctx->data_half;
-		u32 old_index = ctx->pipe_index;
-		u32 last_instruction = ctx->last_instruction;
-		u32 cycles = 0;
-		int current_pc_ok = ctx->pc_ok;
-		
-		if (ctx->trace_data[ctx->pipe_index].flags & ETMV1_TRIGGER_CYCLE)
-		{
-			command_print(cmd_ctx, "--- trigger ---");
-		}
-
-		/* instructions execute in IE/D or BE/D cycles */
-		if ((pipestat == STAT_IE) || (pipestat == STAT_ID))
-			ctx->last_instruction = ctx->pipe_index;
-		
-		/* if we don't have a valid pc skip until we reach an indirect branch */
-		if ((!ctx->pc_ok) && (pipestat != STAT_BE))
-		{
-			ctx->pipe_index++;
-			continue;
-		}
-		
-		/* any indirect branch could have interrupted instruction flow
-		 * - the branch reason code could indicate a trace discontinuity
-		 * - a branch to the exception vectors indicates an exception
-		 */
-		if ((pipestat == STAT_BE) || (pipestat == STAT_BD))
-		{
-			/* backup current data index, to be able to consume the branch address
-			 * before examining data address and values
-			 */
-			old_data_index = ctx->data_index;
-			old_data_half = ctx->data_half;
-
-			ctx->last_instruction = ctx->pipe_index;
-			
-			if ((retval = etmv1_branch_address(ctx)) != 0)
-			{
-				/* negative return value from etmv1_branch_address means we ran out of packets,
-				 * quit analysing the trace */
-				if (retval < 0)
-					break;
-				
-				/* a positive return values means the current branch was abandoned,
-				 * and a new branch was encountered in cycle ctx->pipe_index + retval;
-				 */
-				WARNING("abandoned branch encountered, correctnes of analysis uncertain");
-				ctx->pipe_index += retval;
-				continue;
-			}
-			
-			/* skip over APO cycles */
-			ctx->pipe_index += 2;
-			
-			switch (ctx->last_branch_reason)
-			{
-				case 0x0:	/* normal PC change */
-					next_pc = ctx->last_branch;
-					break;
-				case 0x1:	/* tracing enabled */
-					command_print(cmd_ctx, "--- tracing enabled at 0x%8.8x ---", ctx->last_branch);
-					ctx->current_pc = ctx->last_branch;
-					ctx->pipe_index++;
-					continue;
-					break;
-				case 0x2:	/* trace restarted after FIFO overflow */
-					command_print(cmd_ctx, "--- trace restarted after FIFO overflow at 0x%8.8x ---", ctx->last_branch);
-					ctx->current_pc = ctx->last_branch;
-					ctx->pipe_index++;
-					continue;
-					break;
-				case 0x3:	/* exit from debug state */
-					command_print(cmd_ctx, "--- exit from debug state at 0x%8.8x ---", ctx->last_branch);
-					ctx->current_pc = ctx->last_branch;
-					ctx->pipe_index++;
-					continue;
-					break;
-				case 0x4:	/* periodic synchronization point */
-					next_pc = ctx->last_branch;
-					/* if we had no valid PC prior to this synchronization point,
-					 * we have to move on with the next trace cycle
-					 */
-					if (!current_pc_ok)
-					{
-						command_print(cmd_ctx, "--- periodic synchronization point at 0x%8.8x ---", next_pc);
-						ctx->current_pc = next_pc;
-						ctx->pipe_index++;
-						continue;
-					}
-					break;
-				default:	/* reserved */
-					ERROR("BUG: branch reason code 0x%x is reserved", ctx->last_branch_reason);		
-					exit(-1);
-					break;
-			}
-			
-			/* if we got here the branch was a normal PC change
-			 * (or a periodic synchronization point, which means the same for that matter)
-			 * if we didn't accquire a complete PC continue with the next cycle
-			 */
-			if (!ctx->pc_ok)
-				continue;
-			
-			/* indirect branch to the exception vector means an exception occured */
-			if (((ctx->last_branch >= 0x0) && (ctx->last_branch <= 0x20))
-				|| ((ctx->last_branch >= 0xffff0000) && (ctx->last_branch <= 0xffff0020)))
-			{
-				if ((ctx->last_branch & 0xff) == 0x10)
-				{
-					command_print(cmd_ctx, "data abort");
-				}
-				else
-				{
-					command_print(cmd_ctx, "exception vector 0x%2.2x", ctx->last_branch);
-					ctx->current_pc = ctx->last_branch;
-					ctx->pipe_index++;
-					continue;
-				}
-			}
-		}
-		
-		/* an instruction was executed (or not, depending on the condition flags)
-		 * retrieve it from the image for displaying */
-		if (ctx->pc_ok && (pipestat != STAT_WT) && (pipestat != STAT_TD) &&
-			!(((pipestat == STAT_BE) || (pipestat == STAT_BD)) &&
-				((ctx->last_branch_reason != 0x0) && (ctx->last_branch_reason != 0x4))))  
-		{
-			if ((retval = etm_read_instruction(ctx, &instruction)) != ERROR_OK)
-			{
-				/* can't continue tracing with no image available */
-				if (retval == ERROR_TRACE_IMAGE_UNAVAILABLE)
-				{
-					return retval;
-				}
-				else if (retval == ERROR_TRACE_INSTRUCTION_UNAVAILABLE)
-				{
-					/* TODO: handle incomplete images 
-					 * for now we just quit the analsysis*/
-					return retval;
-				}
-			}
-			
-			cycles = old_index - last_instruction;
-		}
-		
-		if ((pipestat == STAT_ID) || (pipestat == STAT_BD))
-		{
-			u32 new_data_index = ctx->data_index;
-			u32 new_data_half = ctx->data_half;
-			
-			/* in case of a branch with data, the branch target address was consumed before
-			 * we temporarily go back to the saved data index */
-			if (pipestat == STAT_BD)
-			{
-				ctx->data_index = old_data_index;
-				ctx->data_half = old_data_half;
-			}
-			
-			if (ctx->tracemode & ETMV1_TRACE_ADDR)
-			{			
-				u8 packet;
-				int shift = 0;
-				
-				do {
-					if ((retval = etmv1_next_packet(ctx, &packet, 0)) != 0)
-						return ERROR_ETM_ANALYSIS_FAILED;
-					ctx->last_ptr &= ~(0x7f << shift);
-					ctx->last_ptr |= (packet & 0x7f) << shift;
-					shift += 7;
-				} while ((packet & 0x80) && (shift < 32));
-				
-				if (shift >= 32)
-					ctx->ptr_ok = 1;
-				
-				if (ctx->ptr_ok)
-				{
-					command_print(cmd_ctx, "address: 0x%8.8x", ctx->last_ptr);
-				}
-			}
-			
-			if (ctx->tracemode & ETMV1_TRACE_DATA)
-			{
-				if ((instruction.type == ARM_LDM) || (instruction.type == ARM_STM))
-				{
-					int i;
-					for (i = 0; i < 16; i++)
-					{
-						if (instruction.info.load_store_multiple.register_list & (1 << i))
-						{
-							u32 data;
-							if (etmv1_data(ctx, 4, &data) != 0)
-								return ERROR_ETM_ANALYSIS_FAILED;
-							command_print(cmd_ctx, "data: 0x%8.8x", data);
-						}
-					}
-				}
-				else if ((instruction.type >= ARM_LDR) && (instruction.type <= ARM_STRH))
-				{
-					u32 data;
-					if (etmv1_data(ctx, arm_access_size(&instruction), &data) != 0)
-						return ERROR_ETM_ANALYSIS_FAILED;
-					command_print(cmd_ctx, "data: 0x%8.8x", data);
-				}
-			}
-			
-			/* restore data index after consuming BD address and data */
-			if (pipestat == STAT_BD)
-			{
-				ctx->data_index = new_data_index;
-				ctx->data_half = new_data_half;
-			}
-		}
-		
-		/* adjust PC */
-		if ((pipestat == STAT_IE) || (pipestat == STAT_ID))
-		{
-			if (((instruction.type == ARM_B) ||
-				(instruction.type == ARM_BL) ||
-				(instruction.type == ARM_BLX)) &&
-				(instruction.info.b_bl_bx_blx.target_address != -1))
-			{
-				next_pc = instruction.info.b_bl_bx_blx.target_address;
-			}
-			else
-			{
-				next_pc += (ctx->core_state == ARMV4_5_STATE_ARM) ? 4 : 2;
-			}
-		}
-		else if (pipestat == STAT_IN)
-		{
-			next_pc += (ctx->core_state == ARMV4_5_STATE_ARM) ? 4 : 2;
-		}
-
-		if ((pipestat != STAT_TD) && (pipestat != STAT_WT))
-		{
-			char cycles_text[32] = "";
-			
-			/* if the trace was captured with cycle accurate tracing enabled,
-			 * output the number of cycles since the last executed instruction
-			 */
-			if (ctx->tracemode & ETMV1_CYCLE_ACCURATE)
-			{
-				snprintf(cycles_text, 32, " (%i %s)",
-					cycles,
-					(cycles == 1) ? "cycle" : "cycles");
-			}
-			
-			command_print(cmd_ctx, "%s%s%s",
-				instruction.text,
-				(pipestat == STAT_IN) ? " (not executed)" : "",
-				cycles_text);
-
-			ctx->current_pc = next_pc;
-			
-			/* packets for an instruction don't start on or before the preceding
-			 * functional pipestat (i.e. other than WT or TD)
-			 */
-			if (ctx->data_index <= ctx->pipe_index)
-			{
-				ctx->data_index = ctx->pipe_index + 1;
-				ctx->data_half = 0;
-			}
-		}
-		
-		ctx->pipe_index += 1;
-	}
-	
-	return ERROR_OK;
-}
-
-int handle_etm_tracemode_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	target_t *target;
-	armv4_5_common_t *armv4_5;
-	arm7_9_common_t *arm7_9;
-	etmv1_tracemode_t tracemode;
-	
-	target = get_current_target(cmd_ctx);
-	
-	if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
-		return ERROR_OK;
-	}
-	
-	if (!arm7_9->etm_ctx)
-	{
-		command_print(cmd_ctx, "current target doesn't have an ETM configured");
-		return ERROR_OK;
-	}
-	
-	tracemode = arm7_9->etm_ctx->tracemode;
-
-	if (argc == 4)
-	{
-		if (strcmp(args[0], "none") == 0)
-		{
-			tracemode = ETMV1_TRACE_NONE;
-		}
-		else if (strcmp(args[0], "data") == 0)
-		{
-			tracemode = ETMV1_TRACE_DATA;
-		}
-		else if (strcmp(args[0], "address") == 0)
-		{
-			tracemode = ETMV1_TRACE_ADDR;
-		}
-		else if (strcmp(args[0], "all") == 0)
-		{
-			tracemode = ETMV1_TRACE_DATA | ETMV1_TRACE_ADDR;
-		}
-		else
-		{
-			command_print(cmd_ctx, "invalid option '%s'", args[0]);
-			return ERROR_OK;
-		}
-		
-		switch (strtol(args[1], NULL, 0))
-		{
-			case 0:
-				tracemode |= ETMV1_CONTEXTID_NONE;
-				break;
-			case 8:
-				tracemode |= ETMV1_CONTEXTID_8;
-				break;
-			case 16:
-				tracemode |= ETMV1_CONTEXTID_16;
-				break;
-			case 32:
-				tracemode |= ETMV1_CONTEXTID_32;
-				break;
-			default:
-				command_print(cmd_ctx, "invalid option '%s'", args[1]);
-				return ERROR_OK;
-		}
-		
-		if (strcmp(args[2], "enable") == 0)
-		{
-			tracemode |= ETMV1_CYCLE_ACCURATE;
-		}
-		else if (strcmp(args[2], "disable") == 0)
-		{
-			tracemode |= 0;
-		}
-		else
-		{
-			command_print(cmd_ctx, "invalid option '%s'", args[2]);
-			return ERROR_OK;
-		}
-		
-		if (strcmp(args[3], "enable") == 0)
-		{
-			tracemode |= ETMV1_BRANCH_OUTPUT;
-		}
-		else if (strcmp(args[3], "disable") == 0)
-		{
-			tracemode |= 0;
-		}
-		else
-		{
-			command_print(cmd_ctx, "invalid option '%s'", args[2]);
-			return ERROR_OK;
-		}
-	}
-	else if (argc != 0)
-	{
-		command_print(cmd_ctx, "usage: configure trace mode <none|data|address|all> <context id bits> <cycle accurate> <branch output>");
-		return ERROR_OK;
-	}
-	
-	command_print(cmd_ctx, "current tracemode configuration:");
-	
-	switch (tracemode & ETMV1_TRACE_MASK)
-	{
-		case ETMV1_TRACE_NONE:
-			command_print(cmd_ctx, "data tracing: none");
-			break;
-		case ETMV1_TRACE_DATA:
-			command_print(cmd_ctx, "data tracing: data only");
-			break;
-		case ETMV1_TRACE_ADDR:
-			command_print(cmd_ctx, "data tracing: address only");
-			break;
-		case ETMV1_TRACE_DATA | ETMV1_TRACE_ADDR:
-			command_print(cmd_ctx, "data tracing: address and data");
-			break;
-	}
-	
-	switch (tracemode & ETMV1_CONTEXTID_MASK)
-	{
-		case ETMV1_CONTEXTID_NONE:
-			command_print(cmd_ctx, "contextid tracing: none");
-			break;
-		case ETMV1_CONTEXTID_8:
-			command_print(cmd_ctx, "contextid tracing: 8 bit");
-			break;
-		case ETMV1_CONTEXTID_16:
-			command_print(cmd_ctx, "contextid tracing: 16 bit");
-			break;
-		case ETMV1_CONTEXTID_32:
-			command_print(cmd_ctx, "contextid tracing: 32 bit");
-			break;
-	}
-	
-	if (tracemode & ETMV1_CYCLE_ACCURATE)
-	{
-		command_print(cmd_ctx, "cycle-accurate tracing enabled");
-	}
-	else
-	{
-		command_print(cmd_ctx, "cycle-accurate tracing disabled");
-	}
-
-	if (tracemode & ETMV1_BRANCH_OUTPUT)
-	{
-		command_print(cmd_ctx, "full branch address output enabled");
-	}
-	else
-	{
-		command_print(cmd_ctx, "full branch address output disabled");
-	}
-	
-	/* only update ETM_CTRL register if tracemode changed */
-	if (arm7_9->etm_ctx->tracemode != tracemode)
-	{
-		reg_t *etm_ctrl_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CTRL];
-		
-		etm_get_reg(etm_ctrl_reg);
-		
-		buf_set_u32(etm_ctrl_reg->value, 2, 2, tracemode & ETMV1_TRACE_MASK);
-		buf_set_u32(etm_ctrl_reg->value, 14, 2, (tracemode & ETMV1_CONTEXTID_MASK) >> 4);
-		buf_set_u32(etm_ctrl_reg->value, 12, 1, (tracemode & ETMV1_CYCLE_ACCURATE) >> 8);
-		buf_set_u32(etm_ctrl_reg->value, 8, 1, (tracemode & ETMV1_BRANCH_OUTPUT) >> 9);
-		etm_store_reg(etm_ctrl_reg);
-		
-		arm7_9->etm_ctx->tracemode = tracemode;
-		
-		/* invalidate old trace data */
-		arm7_9->etm_ctx->capture_status = TRACE_IDLE;
-		if (arm7_9->etm_ctx->trace_depth > 0)
-		{
-			free(arm7_9->etm_ctx->trace_data);
-			arm7_9->etm_ctx->trace_data = NULL;
-		}
-		arm7_9->etm_ctx->trace_depth = 0;
-	}
-	
-	return ERROR_OK;
-}
-
-int handle_etm_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	target_t *target;
-	armv4_5_common_t *armv4_5;
-	arm7_9_common_t *arm7_9;
-	etm_portmode_t portmode = 0x0;
-	etm_context_t *etm_ctx = malloc(sizeof(etm_context_t));
-	int i;
-	
-	if (argc != 5)
-	{
-		ERROR("incomplete 'etm config <target> <port_width> <port_mode> <clocking> <capture_driver>' command");
-		exit(-1);
-	}
-	
-	target = get_target_by_num(strtoul(args[0], NULL, 0));
-	
-	if (!target)
-	{
-		ERROR("target number '%s' not defined", args[0]);
-		exit(-1);
-	}
-	
-	if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
-		return ERROR_OK;
-	}
-	
-	switch (strtoul(args[1], NULL, 0))
-	{
-		case 4:
-			portmode |= ETM_PORT_4BIT;
-			break;
-		case 8:
-			portmode |= ETM_PORT_8BIT;
-			break;
-		case 16:
-			portmode |= ETM_PORT_16BIT;
-			break;
-		default:
-			command_print(cmd_ctx, "unsupported ETM port width '%s', must be 4, 8 or 16", args[1]);
-			return ERROR_OK;
-	}
-	
-	if (strcmp("normal", args[2]) == 0)
-	{
-		portmode |= ETM_PORT_NORMAL;
-	}
-	else if (strcmp("multiplexed", args[2]) == 0)
-	{
-		portmode |= ETM_PORT_MUXED;
-	}
-	else if (strcmp("demultiplexed", args[2]) == 0)
-	{
-		portmode |= ETM_PORT_DEMUXED;
-	}
-	else
-	{
-		command_print(cmd_ctx, "unsupported ETM port mode '%s', must be 'normal', 'multiplexed' or 'demultiplexed'", args[2]);
-		return ERROR_OK;
-	}
-	
-	if (strcmp("half", args[3]) == 0)
-	{
-		portmode |= ETM_PORT_HALF_CLOCK;
-	}
-	else if (strcmp("full", args[3]) == 0)
-	{
-		portmode |= ETM_PORT_FULL_CLOCK;
-	}
-	else
-	{
-		command_print(cmd_ctx, "unsupported ETM port clocking '%s', must be 'full' or 'half'", args[3]);
-		return ERROR_OK;
-	}
-	
-	for (i=0; etm_capture_drivers[i]; i++)
-	{
-		if (strcmp(args[4], etm_capture_drivers[i]->name) == 0)
-		{
-			if (etm_capture_drivers[i]->register_commands(cmd_ctx) != ERROR_OK)
-			{
-				free(etm_ctx);
-				exit(-1);
-			}
-		
-			etm_ctx->capture_driver = etm_capture_drivers[i];
-
-			break;
-		}
-	}
-	
-	if (!etm_capture_drivers[i])
-	{
-		/* no supported capture driver found, don't register an ETM */
-		free(etm_ctx);
-		ERROR("trace capture driver '%s' not found", args[4]);
-		return ERROR_OK;
-	}
-	
-	etm_ctx->target = target;
-	etm_ctx->trigger_percent = 50;
-	etm_ctx->trace_data = NULL;
-	etm_ctx->trace_depth = 0;
-	etm_ctx->portmode = portmode;
-	etm_ctx->tracemode = 0x0;
-	etm_ctx->core_state = ARMV4_5_STATE_ARM;
-	etm_ctx->image = NULL;
-	etm_ctx->pipe_index = 0;
-	etm_ctx->data_index = 0;
-	etm_ctx->current_pc = 0x0;
-	etm_ctx->pc_ok = 0;
-	etm_ctx->last_branch = 0x0;
-	etm_ctx->last_branch_reason = 0x0;
-	etm_ctx->last_ptr = 0x0;
-	etm_ctx->ptr_ok = 0x0;
-	etm_ctx->context_id = 0x0;
-	etm_ctx->last_instruction = 0;
-	
-	arm7_9->etm_ctx = etm_ctx;
-	
-	etm_register_user_commands(cmd_ctx);
-	
-	return ERROR_OK;
-}
-
-int handle_etm_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	target_t *target;
-	armv4_5_common_t *armv4_5;
-	arm7_9_common_t *arm7_9;
-	reg_t *etm_config_reg;
-	reg_t *etm_sys_config_reg;
-	
-	int max_port_size;
-		
-	target = get_current_target(cmd_ctx);
-	
-	if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
-		return ERROR_OK;
-	}
-	
-	if (!arm7_9->etm_ctx)
-	{
-		command_print(cmd_ctx, "current target doesn't have an ETM configured");
-		return ERROR_OK;
-	}
-	
-	etm_config_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CONFIG];
-	etm_sys_config_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_SYS_CONFIG];
-	
-	etm_get_reg(etm_config_reg);
-	command_print(cmd_ctx, "pairs of address comparators: %i", buf_get_u32(etm_config_reg->value, 0, 4));
-	command_print(cmd_ctx, "pairs of data comparators: %i", buf_get_u32(etm_config_reg->value, 4, 4));
-	command_print(cmd_ctx, "memory map decoders: %i", buf_get_u32(etm_config_reg->value, 8, 5));
-	command_print(cmd_ctx, "number of counters: %i", buf_get_u32(etm_config_reg->value, 13, 3));
-	command_print(cmd_ctx, "sequencer %spresent",
-			(buf_get_u32(etm_config_reg->value, 16, 1) == 1) ? "" : "not ");
-	command_print(cmd_ctx, "number of ext. inputs: %i", buf_get_u32(etm_config_reg->value, 17, 3));
-	command_print(cmd_ctx, "number of ext. outputs: %i", buf_get_u32(etm_config_reg->value, 20, 3));
-	command_print(cmd_ctx, "FIFO full %spresent",
-			(buf_get_u32(etm_config_reg->value, 23, 1) == 1) ? "" : "not ");
-	command_print(cmd_ctx, "protocol version: %i", buf_get_u32(etm_config_reg->value, 28, 3));
-	
-	etm_get_reg(etm_sys_config_reg);
-
-	switch (buf_get_u32(etm_sys_config_reg->value, 0, 3))
-	{
-		case 0:
-			max_port_size = 4;
-			break;
-		case 1:
-			max_port_size = 8;
-			break;
-		case 2:
-			max_port_size = 16;
-			break;
-	}
-	command_print(cmd_ctx, "max. port size: %i", max_port_size);
-	
-	command_print(cmd_ctx, "half-rate clocking %ssupported",
-			(buf_get_u32(etm_sys_config_reg->value, 3, 1) == 1) ? "" : "not ");
-	command_print(cmd_ctx, "full-rate clocking %ssupported",
-			(buf_get_u32(etm_sys_config_reg->value, 4, 1) == 1) ? "" : "not ");
-	command_print(cmd_ctx, "normal trace format %ssupported",
-			(buf_get_u32(etm_sys_config_reg->value, 5, 1) == 1) ? "" : "not ");
-	command_print(cmd_ctx, "multiplex trace format %ssupported",
-			(buf_get_u32(etm_sys_config_reg->value, 6, 1) == 1) ? "" : "not ");
-	command_print(cmd_ctx, "demultiplex trace format %ssupported",
-			(buf_get_u32(etm_sys_config_reg->value, 7, 1) == 1) ? "" : "not ");
-	command_print(cmd_ctx, "FIFO full %ssupported",
-			(buf_get_u32(etm_sys_config_reg->value, 8, 1) == 1) ? "" : "not ");
-	
-	return ERROR_OK;
-}
-
-int handle_etm_status_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	target_t *target;
-	armv4_5_common_t *armv4_5;
-	arm7_9_common_t *arm7_9;
-	trace_status_t trace_status;
-	
-	target = get_current_target(cmd_ctx);
-	
-	if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
-		return ERROR_OK;
-	}
-	
-	if (!arm7_9->etm_ctx)
-	{
-		command_print(cmd_ctx, "current target doesn't have an ETM configured");
-		return ERROR_OK;
-	}
-	
-	trace_status = arm7_9->etm_ctx->capture_driver->status(arm7_9->etm_ctx);
-	
-	if (trace_status == TRACE_IDLE)
-	{
-		command_print(cmd_ctx, "tracing is idle");
-	}
-	else
-	{
-		static char *completed = " completed";
-		static char *running = " is running";
-		static char *overflowed = ", trace overflowed";
-		static char *triggered = ", trace triggered";
-		
-		command_print(cmd_ctx, "trace collection%s%s%s", 
-			(trace_status & TRACE_RUNNING) ? running : completed,
-			(trace_status & TRACE_OVERFLOWED) ? overflowed : "",
-			(trace_status & TRACE_TRIGGERED) ? triggered : "");
-		
-		if (arm7_9->etm_ctx->trace_depth > 0)
-		{
-			command_print(cmd_ctx, "%i frames of trace data read", arm7_9->etm_ctx->trace_depth);
-		}
-	}
-	
-	return ERROR_OK;
-}
-
-int handle_etm_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	target_t *target;
-	armv4_5_common_t *armv4_5;
-	arm7_9_common_t *arm7_9;
-	etm_context_t *etm_ctx;
-
-	if (argc < 1)
-	{
-		command_print(cmd_ctx, "usage: etm image <file> [base address] [type]");
-		return ERROR_OK;
-	}
-	
-	target = get_current_target(cmd_ctx);
-	
-	if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
-		return ERROR_OK;
-	}
-	
-	if (!(etm_ctx = arm7_9->etm_ctx))
-	{
-		command_print(cmd_ctx, "current target doesn't have an ETM configured");
-		return ERROR_OK;
-	}
-	
-	if (etm_ctx->image)
-	{
-		image_close(etm_ctx->image);
-		free(etm_ctx->image);
-		command_print(cmd_ctx, "previously loaded image found and closed");
-	}
-	
-	etm_ctx->image = malloc(sizeof(image_t));
-	etm_ctx->image->base_address_set = 0;
-	etm_ctx->image->start_address_set = 0;
-	
-	/* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */
-	if (argc >= 2)
-	{
-		etm_ctx->image->base_address_set = 1;
-		etm_ctx->image->base_address = strtoul(args[1], NULL, 0);
-	}
-	else
-	{
-		etm_ctx->image->base_address_set = 0;
-	}
-		
-	if (image_open(etm_ctx->image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "image opening error: %s", etm_ctx->image->error_str);
-		free(etm_ctx->image);
-		etm_ctx->image = NULL;
-		return ERROR_OK;
-	}
-	
-	return ERROR_OK;
-}
-
-int handle_etm_dump_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	fileio_t file;
-	target_t *target;
-	armv4_5_common_t *armv4_5;
-	arm7_9_common_t *arm7_9;
-	etm_context_t *etm_ctx;
-	int i;
-	
-	if (argc != 1)
-	{
-		command_print(cmd_ctx, "usage: etm dump <file>");
-		return ERROR_OK;
-	}
-	
-	target = get_current_target(cmd_ctx);
-	
-	if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
-		return ERROR_OK;
-	}
-	
-	if (!(etm_ctx = arm7_9->etm_ctx))
-	{
-		command_print(cmd_ctx, "current target doesn't have an ETM configured");
-		return ERROR_OK;
-	}
-	
-	if (etm_ctx->capture_driver->status == TRACE_IDLE)
-	{
-		command_print(cmd_ctx, "trace capture wasn't enabled, no trace data captured");
-		return ERROR_OK;
-	}
-
-	if (etm_ctx->capture_driver->status(etm_ctx) & TRACE_RUNNING)
-	{
-		/* TODO: if on-the-fly capture is to be supported, this needs to be changed */
-		command_print(cmd_ctx, "trace capture not completed");
-		return ERROR_OK;
-	}
-	
-	/* read the trace data if it wasn't read already */
-	if (etm_ctx->trace_depth == 0)
-		etm_ctx->capture_driver->read_trace(etm_ctx);
-	
-	if (fileio_open(&file, args[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "file open error: %s", file.error_str);
-		return ERROR_OK;
-	}
-	
-	fileio_write_u32(&file, etm_ctx->capture_status);
-	fileio_write_u32(&file, etm_ctx->portmode);
-	fileio_write_u32(&file, etm_ctx->tracemode);
-	fileio_write_u32(&file, etm_ctx->trace_depth);
-	
-	for (i = 0; i < etm_ctx->trace_depth; i++)
-	{
-		fileio_write_u32(&file, etm_ctx->trace_data[i].pipestat);
-		fileio_write_u32(&file, etm_ctx->trace_data[i].packet);
-		fileio_write_u32(&file, etm_ctx->trace_data[i].flags);
-	}
-	
-	fileio_close(&file);
-	
-	return ERROR_OK;	
-}
-
-int handle_etm_load_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	fileio_t file;
-	target_t *target;
-	armv4_5_common_t *armv4_5;
-	arm7_9_common_t *arm7_9;
-	etm_context_t *etm_ctx;
-	int i;
-	
-	if (argc != 1)
-	{
-		command_print(cmd_ctx, "usage: etm load <file>");
-		return ERROR_OK;
-	}
-	
-	target = get_current_target(cmd_ctx);
-	
-	if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
-		return ERROR_OK;
-	}
-	
-	if (!(etm_ctx = arm7_9->etm_ctx))
-	{
-		command_print(cmd_ctx, "current target doesn't have an ETM configured");
-		return ERROR_OK;
-	}
-	
-	if (etm_ctx->capture_driver->status(etm_ctx) & TRACE_RUNNING)
-	{
-		command_print(cmd_ctx, "trace capture running, stop first");
-		return ERROR_OK;
-	}
-	
-	if (fileio_open(&file, args[0], FILEIO_READ, FILEIO_BINARY) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "file open error: %s", file.error_str);
-		return ERROR_OK;
-	}
-	
-	if (file.size % 4)
-	{
-		command_print(cmd_ctx, "size isn't a multiple of 4, no valid trace data");
-		return ERROR_OK;
-	}
-	
-	if (etm_ctx->trace_depth > 0)
-	{
-		free(etm_ctx->trace_data);
-	}
-	
-	fileio_read_u32(&file, &etm_ctx->capture_status);
-	fileio_read_u32(&file, &etm_ctx->portmode);
-	fileio_read_u32(&file, &etm_ctx->tracemode);
-	fileio_read_u32(&file, &etm_ctx->trace_depth);
-	
-	etm_ctx->trace_data = malloc(sizeof(etmv1_trace_data_t) * etm_ctx->trace_depth);
-	
-	for (i = 0; i < etm_ctx->trace_depth; i++)
-	{
-		u32 pipestat, packet, flags;
-		fileio_read_u32(&file, &pipestat);
-		fileio_read_u32(&file, &packet);
-		fileio_read_u32(&file, &flags);
-		etm_ctx->trace_data[i].pipestat = pipestat & 0xff;
-		etm_ctx->trace_data[i].packet = packet & 0xffff;
-		etm_ctx->trace_data[i].flags = flags;
-	}
-	
-	fileio_close(&file);
-	
-	return ERROR_OK;	
-}
-
-int handle_etm_trigger_percent_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	target_t *target;
-	armv4_5_common_t *armv4_5;
-	arm7_9_common_t *arm7_9;
-	etm_context_t *etm_ctx;
-	
-	target = get_current_target(cmd_ctx);
-	
-	if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
-		return ERROR_OK;
-	}
-	
-	if (!(etm_ctx = arm7_9->etm_ctx))
-	{
-		command_print(cmd_ctx, "current target doesn't have an ETM configured");
-		return ERROR_OK;
-	}
-	
-	if (argc > 0)
-	{
-		u32 new_value = strtoul(args[0], NULL, 0);
-		
-		if ((new_value < 2) || (new_value > 100))
-		{
-			command_print(cmd_ctx, "valid settings are 2% to 100%");
-		}
-		else
-		{
-			etm_ctx->trigger_percent = new_value;
-		}
-	}
-	
-	command_print(cmd_ctx, "%i percent of the tracebuffer reserved for after the trigger", etm_ctx->trigger_percent);
-
-	return ERROR_OK;
-}
-
-int handle_etm_start_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	target_t *target;
-	armv4_5_common_t *armv4_5;
-	arm7_9_common_t *arm7_9;
-	etm_context_t *etm_ctx;
-	reg_t *etm_ctrl_reg;
-
-	target = get_current_target(cmd_ctx);
-	
-	if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
-		return ERROR_OK;
-	}
-	
-	if (!(etm_ctx = arm7_9->etm_ctx))
-	{
-		command_print(cmd_ctx, "current target doesn't have an ETM configured");
-		return ERROR_OK;
-	}
-	
-	/* invalidate old tracing data */
-	arm7_9->etm_ctx->capture_status = TRACE_IDLE;
-	if (arm7_9->etm_ctx->trace_depth > 0)
-	{
-		free(arm7_9->etm_ctx->trace_data);
-		arm7_9->etm_ctx->trace_data = NULL;
-	}
-	arm7_9->etm_ctx->trace_depth = 0;
-		
-	etm_ctrl_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CTRL];
-	etm_get_reg(etm_ctrl_reg);
-		
-	/* Clear programming bit (10), set port selection bit (11) */
-	buf_set_u32(etm_ctrl_reg->value, 10, 2, 0x2);
-
-	etm_store_reg(etm_ctrl_reg);
-	jtag_execute_queue();
-
-	etm_ctx->capture_driver->start_capture(etm_ctx);
-
-	return ERROR_OK;
-}
-
-int handle_etm_stop_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	target_t *target;
-	armv4_5_common_t *armv4_5;
-	arm7_9_common_t *arm7_9;
-	etm_context_t *etm_ctx;
-	reg_t *etm_ctrl_reg;
-
-	target = get_current_target(cmd_ctx);
-	
-	if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
-		return ERROR_OK;
-	}
-	
-	if (!(etm_ctx = arm7_9->etm_ctx))
-	{
-		command_print(cmd_ctx, "current target doesn't have an ETM configured");
-		return ERROR_OK;
-	}
-	
-	etm_ctrl_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CTRL];
-	etm_get_reg(etm_ctrl_reg);
-		
-	/* Set programming bit (10), clear port selection bit (11) */
-	buf_set_u32(etm_ctrl_reg->value, 10, 2, 0x1);
-
-	etm_store_reg(etm_ctrl_reg);	
-	jtag_execute_queue();
-	
-	etm_ctx->capture_driver->stop_capture(etm_ctx);
-	
-	return ERROR_OK;
-}
-
-int handle_etm_analyze_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	target_t *target;
-	armv4_5_common_t *armv4_5;
-	arm7_9_common_t *arm7_9;
-	etm_context_t *etm_ctx;
-	int retval;
-
-	target = get_current_target(cmd_ctx);
-	
-	if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
-		return ERROR_OK;
-	}
-	
-	if (!(etm_ctx = arm7_9->etm_ctx))
-	{
-		command_print(cmd_ctx, "current target doesn't have an ETM configured");
-		return ERROR_OK;
-	}
-	
-	if ((retval = etmv1_analyze_trace(etm_ctx, cmd_ctx)) != ERROR_OK)
-	{
-		switch(retval)
-		{
-			case ERROR_ETM_ANALYSIS_FAILED:
-				command_print(cmd_ctx, "further analysis failed (corrupted trace data or just end of data");
-				break;
-			case ERROR_TRACE_INSTRUCTION_UNAVAILABLE:
-				command_print(cmd_ctx, "no instruction for current address available, analysis aborted");
-				break;
-			case ERROR_TRACE_IMAGE_UNAVAILABLE:
-				command_print(cmd_ctx, "no image available for trace analysis");
-				break;
-			default:
-				command_print(cmd_ctx, "unknown error: %i", retval);
-		}
-	}
-	
-	return ERROR_OK;
-}
-
-int etm_register_commands(struct command_context_s *cmd_ctx)
-{
-	etm_cmd = register_command(cmd_ctx, NULL, "etm", NULL, COMMAND_ANY, "Embedded Trace Macrocell");
-
-	register_command(cmd_ctx, etm_cmd, "config", handle_etm_config_command, COMMAND_CONFIG, NULL);
-
-	return ERROR_OK;
-}
-
-int etm_register_user_commands(struct command_context_s *cmd_ctx)
-{
-	register_command(cmd_ctx, etm_cmd, "tracemode", handle_etm_tracemode_command,
-		COMMAND_EXEC, "configure trace mode <none|data|address|all> <context id bits> <cycle accurate> <branch output");
-
-	register_command(cmd_ctx, etm_cmd, "info", handle_etm_info_command,
-		COMMAND_EXEC, "display info about the current target's ETM");
-
-	register_command(cmd_ctx, etm_cmd, "trigger_percent <percent>", handle_etm_trigger_percent_command,
-		COMMAND_EXEC, "amount (<percent>) of trace buffer to be filled after the trigger occured");
-	register_command(cmd_ctx, etm_cmd, "status", handle_etm_status_command,
-		COMMAND_EXEC, "display current target's ETM status");
-	register_command(cmd_ctx, etm_cmd, "start", handle_etm_start_command,
-		COMMAND_EXEC, "start ETM trace collection");
-	register_command(cmd_ctx, etm_cmd, "stop", handle_etm_stop_command,
-		COMMAND_EXEC, "stop ETM trace collection");
-
-	register_command(cmd_ctx, etm_cmd, "analyze", handle_etm_analyze_command,
-		COMMAND_EXEC, "anaylze collected ETM trace");
-
-	register_command(cmd_ctx, etm_cmd, "image", handle_etm_image_command,
-		COMMAND_EXEC, "load image from <file> [base address]");
-
-	register_command(cmd_ctx, etm_cmd, "dump", handle_etm_dump_command,
-		COMMAND_EXEC, "dump captured trace data <file>");
-	register_command(cmd_ctx, etm_cmd, "load", handle_etm_load_command,
-		COMMAND_EXEC, "load trace data for analysis <file>");
-
-	return ERROR_OK;
-}
+/***************************************************************************
+ *   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.             *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include "etm.h"
+#include "etb.h"
+
+#include "armv4_5.h"
+#include "arm7_9_common.h"
+#include "arm_disassembler.h"
+#include "arm_simulator.h"
+
+#include "log.h"
+#include "arm_jtag.h"
+#include "types.h"
+#include "binarybuffer.h"
+#include "target.h"
+#include "register.h"
+#include "jtag.h"
+#include "fileio.h"
+
+#include <stdlib.h>
+
+/* ETM register access functionality 
+ * 
+ */
+
+bitfield_desc_t etm_comms_ctrl_bitfield_desc[] = 
+{
+	{"R", 1},
+	{"W", 1},
+	{"reserved", 26},
+	{"version", 4}
+};
+
+int etm_reg_arch_info[] =
+{
+	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+	0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 
+	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 
+	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+	0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 
+	0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+	0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+	0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 
+	0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 
+	0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
+	0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+	0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x67, 
+	0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 
+};
+
+int etm_reg_arch_size_info[] =
+{
+	32, 32, 17, 8, 3, 9, 32, 16,
+	17, 26, 25, 8, 17, 32, 32, 17,
+	32, 32, 32, 32, 32, 32, 32, 32, 
+	32, 32, 32, 32, 32, 32, 32, 32, 
+	7, 7, 7, 7, 7, 7, 7, 7, 
+	7, 7, 7, 7, 7, 7, 7, 7, 
+	32, 32, 32, 32, 32, 32, 32, 32, 
+	32, 32, 32, 32, 32, 32, 32, 32, 
+	32, 32, 32, 32, 32, 32, 32, 32, 
+	32, 32, 32, 32, 32, 32, 32, 32, 
+	16, 16, 16, 16, 18, 18, 18, 18,
+	17, 17, 17, 17, 16, 16, 16, 16,
+	17, 17, 17, 17, 17, 17, 2, 
+	17, 17, 17, 17, 32, 32, 32, 32 
+};
+
+char* etm_reg_list[] =
+{
+	"ETM_CTRL",
+	"ETM_CONFIG",
+	"ETM_TRIG_EVENT",
+	"ETM_MMD_CTRL",
+	"ETM_STATUS",
+	"ETM_SYS_CONFIG",
+	"ETM_TRACE_RESOURCE_CTRL",
+	"ETM_TRACE_EN_CTRL2",
+	"ETM_TRACE_EN_EVENT",
+	"ETM_TRACE_EN_CTRL1",
+	"ETM_FIFOFULL_REGION",
+	"ETM_FIFOFULL_LEVEL",
+	"ETM_VIEWDATA_EVENT",
+	"ETM_VIEWDATA_CTRL1",
+	"ETM_VIEWDATA_CTRL2",
+	"ETM_VIEWDATA_CTRL3",
+	"ETM_ADDR_COMPARATOR_VALUE1",
+	"ETM_ADDR_COMPARATOR_VALUE2",
+	"ETM_ADDR_COMPARATOR_VALUE3",
+	"ETM_ADDR_COMPARATOR_VALUE4",
+	"ETM_ADDR_COMPARATOR_VALUE5",
+	"ETM_ADDR_COMPARATOR_VALUE6",
+	"ETM_ADDR_COMPARATOR_VALUE7",
+	"ETM_ADDR_COMPARATOR_VALUE8",
+	"ETM_ADDR_COMPARATOR_VALUE9",
+	"ETM_ADDR_COMPARATOR_VALUE10",
+	"ETM_ADDR_COMPARATOR_VALUE11",
+	"ETM_ADDR_COMPARATOR_VALUE12",
+	"ETM_ADDR_COMPARATOR_VALUE13",
+	"ETM_ADDR_COMPARATOR_VALUE14",
+	"ETM_ADDR_COMPARATOR_VALUE15",
+	"ETM_ADDR_COMPARATOR_VALUE16",
+	"ETM_ADDR_ACCESS_TYPE1",
+	"ETM_ADDR_ACCESS_TYPE2",
+	"ETM_ADDR_ACCESS_TYPE3",
+	"ETM_ADDR_ACCESS_TYPE4",
+	"ETM_ADDR_ACCESS_TYPE5",
+	"ETM_ADDR_ACCESS_TYPE6",
+	"ETM_ADDR_ACCESS_TYPE7",
+	"ETM_ADDR_ACCESS_TYPE8",
+	"ETM_ADDR_ACCESS_TYPE9",
+	"ETM_ADDR_ACCESS_TYPE10",
+	"ETM_ADDR_ACCESS_TYPE11",
+	"ETM_ADDR_ACCESS_TYPE12",
+	"ETM_ADDR_ACCESS_TYPE13",
+	"ETM_ADDR_ACCESS_TYPE14",
+	"ETM_ADDR_ACCESS_TYPE15",
+	"ETM_ADDR_ACCESS_TYPE16",
+	"ETM_DATA_COMPARATOR_VALUE1",
+	"ETM_DATA_COMPARATOR_VALUE2",
+	"ETM_DATA_COMPARATOR_VALUE3",
+	"ETM_DATA_COMPARATOR_VALUE4",
+	"ETM_DATA_COMPARATOR_VALUE5",
+	"ETM_DATA_COMPARATOR_VALUE6",
+	"ETM_DATA_COMPARATOR_VALUE7",
+	"ETM_DATA_COMPARATOR_VALUE8",
+	"ETM_DATA_COMPARATOR_VALUE9",
+	"ETM_DATA_COMPARATOR_VALUE10",
+	"ETM_DATA_COMPARATOR_VALUE11",
+	"ETM_DATA_COMPARATOR_VALUE12",
+	"ETM_DATA_COMPARATOR_VALUE13",
+	"ETM_DATA_COMPARATOR_VALUE14",
+	"ETM_DATA_COMPARATOR_VALUE15",
+	"ETM_DATA_COMPARATOR_VALUE16",
+	"ETM_DATA_COMPARATOR_MASK1",
+	"ETM_DATA_COMPARATOR_MASK2",
+	"ETM_DATA_COMPARATOR_MASK3",
+	"ETM_DATA_COMPARATOR_MASK4",
+	"ETM_DATA_COMPARATOR_MASK5",
+	"ETM_DATA_COMPARATOR_MASK6",
+	"ETM_DATA_COMPARATOR_MASK7",
+	"ETM_DATA_COMPARATOR_MASK8",
+	"ETM_DATA_COMPARATOR_MASK9",
+	"ETM_DATA_COMPARATOR_MASK10",
+	"ETM_DATA_COMPARATOR_MASK11",
+	"ETM_DATA_COMPARATOR_MASK12",
+	"ETM_DATA_COMPARATOR_MASK13",
+	"ETM_DATA_COMPARATOR_MASK14",
+	"ETM_DATA_COMPARATOR_MASK15",
+	"ETM_DATA_COMPARATOR_MASK16",
+	"ETM_COUNTER_INITAL_VALUE1",
+	"ETM_COUNTER_INITAL_VALUE2",
+	"ETM_COUNTER_INITAL_VALUE3",
+	"ETM_COUNTER_INITAL_VALUE4",
+	"ETM_COUNTER_ENABLE1",
+	"ETM_COUNTER_ENABLE2",
+	"ETM_COUNTER_ENABLE3",
+	"ETM_COUNTER_ENABLE4",
+	"ETM_COUNTER_RELOAD_VALUE1",
+	"ETM_COUNTER_RELOAD_VALUE2",
+	"ETM_COUNTER_RELOAD_VALUE3",
+	"ETM_COUNTER_RELOAD_VALUE4",
+	"ETM_COUNTER_VALUE1",
+	"ETM_COUNTER_VALUE2",
+	"ETM_COUNTER_VALUE3",
+	"ETM_COUNTER_VALUE4",
+	"ETM_SEQUENCER_CTRL1",
+	"ETM_SEQUENCER_CTRL2",
+	"ETM_SEQUENCER_CTRL3",
+	"ETM_SEQUENCER_CTRL4",
+	"ETM_SEQUENCER_CTRL5",
+	"ETM_SEQUENCER_CTRL6",
+	"ETM_SEQUENCER_STATE",
+	"ETM_EXTERNAL_OUTPUT1",
+	"ETM_EXTERNAL_OUTPUT2",
+	"ETM_EXTERNAL_OUTPUT3",
+	"ETM_EXTERNAL_OUTPUT4",
+	"ETM_CONTEXTID_COMPARATOR_VALUE1",
+	"ETM_CONTEXTID_COMPARATOR_VALUE2",
+	"ETM_CONTEXTID_COMPARATOR_VALUE3",
+	"ETM_CONTEXTID_COMPARATOR_MASK"
+};  
+
+int etm_reg_arch_type = -1;
+
+int etm_get_reg(reg_t *reg);
+int etm_set_reg(reg_t *reg, u32 value);
+int etm_set_reg_w_exec(reg_t *reg, u8 *buf);
+
+int etm_write_reg(reg_t *reg, u32 value);
+int etm_read_reg(reg_t *reg);
+
+command_t *etm_cmd = NULL;
+
+reg_cache_t* etm_build_reg_cache(target_t *target, arm_jtag_t *jtag_info, etm_context_t *etm_ctx)
+{
+	reg_cache_t *reg_cache = malloc(sizeof(reg_cache_t));
+	reg_t *reg_list = NULL;
+	etm_reg_t *arch_info = NULL;
+	int num_regs = sizeof(etm_reg_arch_info)/sizeof(int);
+	int i;
+	u32 etm_ctrl_value;
+	
+	/* register a register arch-type for etm registers only once */
+	if (etm_reg_arch_type == -1)
+		etm_reg_arch_type = register_reg_arch_type(etm_get_reg, etm_set_reg_w_exec);
+	
+	/* the actual registers are kept in two arrays */
+	reg_list = calloc(num_regs, sizeof(reg_t));
+	arch_info = calloc(num_regs, sizeof(etm_reg_t));
+	
+	/* fill in values for the reg cache */
+	reg_cache->name = "etm registers";
+	reg_cache->next = NULL;
+	reg_cache->reg_list = reg_list;
+	reg_cache->num_regs = num_regs;
+	
+	/* set up registers */
+	for (i = 0; i < num_regs; i++)
+	{
+		reg_list[i].name = etm_reg_list[i];
+		reg_list[i].size = 32;
+		reg_list[i].dirty = 0;
+		reg_list[i].valid = 0;
+		reg_list[i].bitfield_desc = NULL;
+		reg_list[i].num_bitfields = 0;
+		reg_list[i].value = calloc(1, 4);
+		reg_list[i].arch_info = &arch_info[i];
+		reg_list[i].arch_type = etm_reg_arch_type;
+		reg_list[i].size = etm_reg_arch_size_info[i];
+		arch_info[i].addr = etm_reg_arch_info[i];
+		arch_info[i].jtag_info = jtag_info;
+	}
+
+	/* initialize some ETM control register settings */	
+	etm_get_reg(&reg_list[ETM_CTRL]);
+	etm_ctrl_value = buf_get_u32(reg_list[ETM_CTRL].value, 0, reg_list[ETM_CTRL].size);
+	
+	/* clear the ETM powerdown bit (0) */
+	etm_ctrl_value &= ~0x1;
+		
+	/* configure port width (6:4), mode (17:16) and clocking (13) */
+	etm_ctrl_value = (etm_ctrl_value & 
+		~ETM_PORT_WIDTH_MASK & ~ETM_PORT_MODE_MASK & ~ETM_PORT_CLOCK_MASK)
+		| etm_ctx->portmode;
+	
+	buf_set_u32(reg_list[ETM_CTRL].value, 0, reg_list[ETM_CTRL].size, etm_ctrl_value);
+	etm_store_reg(&reg_list[ETM_CTRL]);
+	
+	/* the ETM might have an ETB connected */
+	if (strcmp(etm_ctx->capture_driver->name, "etb") == 0)
+	{
+		etb_t *etb = etm_ctx->capture_driver_priv;
+		
+		if (!etb)
+		{
+			ERROR("etb selected as etm capture driver, but no ETB configured");
+			return ERROR_OK;
+		}
+		
+		reg_cache->next = etb_build_reg_cache(etb);
+		
+		etb->reg_cache = reg_cache->next;
+	}
+	
+	if (etm_ctx->capture_driver->init(etm_ctx) != ERROR_OK)
+	{
+		ERROR("ETM capture driver initialization failed");
+		exit(-1);
+	}
+	
+	return reg_cache;
+}
+
+int etm_get_reg(reg_t *reg)
+{
+	if (etm_read_reg(reg) != ERROR_OK)
+	{
+		ERROR("BUG: error scheduling etm register read");
+		exit(-1);
+	}
+	
+	if (jtag_execute_queue() != ERROR_OK)
+	{
+		ERROR("register read failed");
+	}
+	
+	return ERROR_OK;
+}
+
+int etm_read_reg_w_check(reg_t *reg, u8* check_value, u8* check_mask)
+{
+	etm_reg_t *etm_reg = reg->arch_info;
+	u8 reg_addr = etm_reg->addr & 0x7f;
+	scan_field_t fields[3];
+	
+	DEBUG("%i", etm_reg->addr);
+
+	jtag_add_end_state(TAP_RTI);
+	arm_jtag_scann(etm_reg->jtag_info, 0x6);
+	arm_jtag_set_instr(etm_reg->jtag_info, etm_reg->jtag_info->intest_instr, NULL);
+	
+	fields[0].device = etm_reg->jtag_info->chain_pos;
+	fields[0].num_bits = 32;
+	fields[0].out_value = reg->value;
+	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 = etm_reg->jtag_info->chain_pos;
+	fields[1].num_bits = 7;
+	fields[1].out_value = malloc(1);
+	buf_set_u32(fields[1].out_value, 0, 7, reg_addr);
+	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;
+
+	fields[2].device = etm_reg->jtag_info->chain_pos;
+	fields[2].num_bits = 1;
+	fields[2].out_value = malloc(1);
+	buf_set_u32(fields[2].out_value, 0, 1, 0);
+	fields[2].out_mask = NULL;
+	fields[2].in_value = NULL;
+	fields[2].in_check_value = NULL;
+	fields[2].in_check_mask = NULL;
+	fields[2].in_handler = NULL;
+	fields[2].in_handler_priv = NULL;
+	
+	jtag_add_dr_scan(3, fields, -1);
+	
+	fields[0].in_value = reg->value;
+	jtag_set_check_value(fields+0, check_value, check_mask, NULL);	
+		
+	jtag_add_dr_scan(3, fields, -1);
+
+	free(fields[1].out_value);
+	free(fields[2].out_value);
+	
+	return ERROR_OK;
+}
+
+int etm_read_reg(reg_t *reg)
+{
+	return etm_read_reg_w_check(reg, NULL, NULL);	
+}
+
+int etm_set_reg(reg_t *reg, u32 value)
+{
+	if (etm_write_reg(reg, value) != ERROR_OK)
+	{
+		ERROR("BUG: error scheduling etm register write");
+		exit(-1);
+	}
+	
+	buf_set_u32(reg->value, 0, reg->size, value);
+	reg->valid = 1;
+	reg->dirty = 0;
+	
+	return ERROR_OK;
+}
+
+int etm_set_reg_w_exec(reg_t *reg, u8 *buf)
+{
+	etm_set_reg(reg, buf_get_u32(buf, 0, reg->size));
+	
+	if (jtag_execute_queue() != ERROR_OK)
+	{
+		ERROR("register write failed");
+		exit(-1);
+	}
+	return ERROR_OK;
+}
+
+int etm_write_reg(reg_t *reg, u32 value)
+{
+	etm_reg_t *etm_reg = reg->arch_info;
+	u8 reg_addr = etm_reg->addr & 0x7f;
+	scan_field_t fields[3];
+	
+	DEBUG("%i: 0x%8.8x", etm_reg->addr, value);
+	
+	jtag_add_end_state(TAP_RTI);
+	arm_jtag_scann(etm_reg->jtag_info, 0x6);
+	arm_jtag_set_instr(etm_reg->jtag_info, etm_reg->jtag_info->intest_instr, NULL);
+	
+	fields[0].device = etm_reg->jtag_info->chain_pos;
+	fields[0].num_bits = 32;
+	fields[0].out_value = malloc(4);
+	buf_set_u32(fields[0].out_value, 0, 32, value);
+	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 = etm_reg->jtag_info->chain_pos;
+	fields[1].num_bits = 7;
+	fields[1].out_value = malloc(1);
+	buf_set_u32(fields[1].out_value, 0, 7, reg_addr);
+	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;
+
+	fields[2].device = etm_reg->jtag_info->chain_pos;
+	fields[2].num_bits = 1;
+	fields[2].out_value = malloc(1);
+	buf_set_u32(fields[2].out_value, 0, 1, 1);
+	fields[2].out_mask = NULL;
+	fields[2].in_value = NULL;
+	fields[2].in_check_value = NULL;
+	fields[2].in_check_mask = NULL;
+	fields[2].in_handler = NULL;
+	fields[2].in_handler_priv = NULL;
+	
+	jtag_add_dr_scan(3, fields, -1);
+	
+	free(fields[0].out_value);
+	free(fields[1].out_value);
+	free(fields[2].out_value);
+	
+	return ERROR_OK;
+}
+
+int etm_store_reg(reg_t *reg)
+{
+	return etm_write_reg(reg, buf_get_u32(reg->value, 0, reg->size));
+}
+
+/* ETM trace analysis functionality
+ * 
+ */
+extern etm_capture_driver_t etb_capture_driver;
+extern etm_capture_driver_t etm_dummy_capture_driver;
+#if BUILD_OOCD_TRACE == 1
+extern etm_capture_driver_t oocd_trace_capture_driver;
+#endif
+
+etm_capture_driver_t *etm_capture_drivers[] = 
+{
+	&etb_capture_driver,
+	&etm_dummy_capture_driver,
+#if BUILD_OOCD_TRACE == 1
+	&oocd_trace_capture_driver,
+#endif
+	NULL
+};
+
+char *etmv1v1_branch_reason_strings[] =
+{
+	"normal PC change",
+	"tracing enabled",
+	"trace restarted after overflow",
+	"exit from debug",
+	"periodic synchronization",
+	"reserved",
+	"reserved",
+	"reserved",
+};
+
+int etm_read_instruction(etm_context_t *ctx, arm_instruction_t *instruction)
+{
+	int i;
+	int section = -1;
+	u32 size_read;
+	u32 opcode;
+	int retval;
+	
+	if (!ctx->image)
+		return ERROR_TRACE_IMAGE_UNAVAILABLE;
+	
+	/* search for the section the current instruction belongs to */	
+	for (i = 0; i < ctx->image->num_sections; i++)
+	{
+		if ((ctx->image->sections[i].base_address <= ctx->current_pc) &&
+			(ctx->image->sections[i].base_address + ctx->image->sections[i].size > ctx->current_pc))
+		{
+			section = i;
+			break;
+		}
+	}
+	
+	if (section == -1)
+	{
+		/* current instruction couldn't be found in the image */
+		return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
+	}
+	
+	if (ctx->core_state == ARMV4_5_STATE_ARM)
+	{
+		u8 buf[4];
+		if ((retval = image_read_section(ctx->image, section, 
+			ctx->current_pc - ctx->image->sections[section].base_address,
+			4, buf, &size_read)) != ERROR_OK)
+		{
+			ERROR("error while reading instruction: %i", retval);
+			return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
+		}
+		opcode = target_buffer_get_u32(ctx->target, buf);
+		arm_evaluate_opcode(opcode, ctx->current_pc, instruction);
+	}
+	else if (ctx->core_state == ARMV4_5_STATE_THUMB)
+	{
+		u8 buf[2];
+		if ((retval = image_read_section(ctx->image, section, 
+			ctx->current_pc - ctx->image->sections[section].base_address,
+			2, buf, &size_read)) != ERROR_OK)
+		{
+			ERROR("error while reading instruction: %i", retval);
+			return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
+		}
+		opcode = target_buffer_get_u16(ctx->target, buf);
+		thumb_evaluate_opcode(opcode, ctx->current_pc, instruction);
+	}
+	else if (ctx->core_state == ARMV4_5_STATE_JAZELLE)
+	{
+		ERROR("BUG: tracing of jazelle code not supported");
+		exit(-1);
+	}
+	else
+	{
+		ERROR("BUG: unknown core state encountered");
+		exit(-1);
+	}
+	
+	return ERROR_OK;
+}
+
+int etmv1_next_packet(etm_context_t *ctx, u8 *packet, int apo)
+{
+	while (ctx->data_index < ctx->trace_depth)
+	{
+		/* if the caller specified an address packet offset, skip until the
+		 * we reach the n-th cycle marked with tracesync */
+		if (apo > 0)
+		{
+			if (ctx->trace_data[ctx->data_index].flags & ETMV1_TRACESYNC_CYCLE)
+				apo--;
+			
+			if (apo > 0)
+			{
+				ctx->data_index++;
+				ctx->data_half = 0;
+			}
+			continue;
+		}
+		
+		/* no tracedata output during a TD cycle
+		 * or in a trigger cycle */
+		if ((ctx->trace_data[ctx->data_index].pipestat == STAT_TD)
+			|| (ctx->trace_data[ctx->data_index].flags & ETMV1_TRIGGER_CYCLE))
+		{
+			ctx->data_index++;
+			ctx->data_half = 0;
+			continue;
+		}
+		
+		if ((ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_16BIT)
+		{
+			if (ctx->data_half == 0)
+			{
+				*packet = ctx->trace_data[ctx->data_index].packet & 0xff;
+				ctx->data_half = 1;
+			}
+			else
+			{
+				*packet = (ctx->trace_data[ctx->data_index].packet & 0xff00) >> 8;
+				ctx->data_half = 0;
+				ctx->data_index++;
+			}
+		}
+		else if ((ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_8BIT)
+		{
+			*packet = ctx->trace_data[ctx->data_index].packet & 0xff;
+			ctx->data_index++;
+		}
+		else
+		{
+			/* on a 4-bit port, a packet will be output during two consecutive cycles */
+			if (ctx->data_index > (ctx->trace_depth - 2))
+				return -1;
+			
+			*packet = ctx->trace_data[ctx->data_index].packet & 0xf;
+			*packet |= (ctx->trace_data[ctx->data_index + 1].packet & 0xf) << 4;
+			ctx->data_index += 2;
+		}
+					
+		return 0;
+	}
+	
+	return -1;
+}
+
+int etmv1_branch_address(etm_context_t *ctx)
+{
+	int retval;
+	u8 packet;
+	int shift = 0;
+	int apo;
+	int i;
+	
+	/* quit analysis if less than two cycles are left in the trace
+	 * because we can't extract the APO */
+	if (ctx->data_index > (ctx->trace_depth - 2))
+		return -1;
+		
+	/* a BE could be output during an APO cycle, skip the current
+	 * and continue with the new one */
+	if (ctx->trace_data[ctx->pipe_index + 1].pipestat & 0x4)
+		return 1;
+	if (ctx->trace_data[ctx->pipe_index + 2].pipestat & 0x4)
+		return 2;
+		
+	/* address packet offset encoded in the next two cycles' pipestat bits */
+	apo = ctx->trace_data[ctx->pipe_index + 1].pipestat & 0x3;
+	apo |= (ctx->trace_data[ctx->pipe_index + 2].pipestat & 0x3) << 2;
+	
+	/* count number of tracesync cycles between current pipe_index and data_index
+	 * i.e. the number of tracesyncs that data_index already passed by
+	 * to subtract them from the APO */
+	for (i = ctx->pipe_index; i < ctx->data_index; i++)
+	{
+		if (ctx->trace_data[ctx->pipe_index + 1].pipestat & ETMV1_TRACESYNC_CYCLE)
+			apo--;
+	}
+	
+	/* extract up to four 7-bit packets */
+	do {
+		if ((retval = etmv1_next_packet(ctx, &packet, (shift == 0) ? apo + 1 : 0)) != 0)
+			return -1;
+		ctx->last_branch &= ~(0x7f << shift);
+		ctx->last_branch |= (packet & 0x7f) << shift;
+		shift += 7;
+	} while ((packet & 0x80) && (shift < 28));
+	
+	/* one last packet holding 4 bits of the address, plus the branch reason code */
+	if ((shift == 28) && (packet & 0x80))
+	{
+		if ((retval = etmv1_next_packet(ctx, &packet, 0)) != 0)
+			return -1;
+		ctx->last_branch &= 0x0fffffff;
+		ctx->last_branch |= (packet & 0x0f) << 28;
+		ctx->last_branch_reason = (packet & 0x70) >> 4;
+		shift += 4;
+	}
+	else
+	{
+		ctx->last_branch_reason = 0;
+	}
+	
+	if (shift == 32)
+	{
+		ctx->pc_ok = 1;
+	}
+	
+	/* if a full address was output, we might have branched into Jazelle state */
+	if ((shift == 32) && (packet & 0x80))
+	{
+		ctx->core_state = ARMV4_5_STATE_JAZELLE;
+	}
+	else
+	{
+		/* if we didn't branch into Jazelle state, the current processor state is
+		 * encoded in bit 0 of the branch target address */
+		if (ctx->last_branch & 0x1)
+		{
+			ctx->core_state = ARMV4_5_STATE_THUMB;
+			ctx->last_branch &= ~0x1;
+		}
+		else
+		{
+			ctx->core_state = ARMV4_5_STATE_ARM;
+			ctx->last_branch &= ~0x3;
+		}
+	}
+	
+	return 0;
+}
+
+int etmv1_data(etm_context_t *ctx, int size, u32 *data)
+{
+	int j;
+	u8 buf[4];
+	int retval;
+	
+	for (j = 0; j < size; j++)
+	{
+		if ((retval = etmv1_next_packet(ctx, &buf[j], 0)) != 0)
+			return -1;
+	}
+	
+	if (size == 8)
+		ERROR("TODO: add support for 64-bit values");
+	else if (size == 4)
+		*data = target_buffer_get_u32(ctx->target, buf);
+	else if (size == 2)
+		*data = target_buffer_get_u16(ctx->target, buf);
+	else if (size == 1)
+		*data = buf[0];
+		
+	return 0;
+}
+
+int etmv1_analyze_trace(etm_context_t *ctx, struct command_context_s *cmd_ctx)
+{
+	int retval;
+	arm_instruction_t instruction;
+	
+	/* read the trace data if it wasn't read already */
+	if (ctx->trace_depth == 0)
+		ctx->capture_driver->read_trace(ctx);
+	
+	/* start at the beginning of the captured trace */
+	ctx->pipe_index = 0;
+	ctx->data_index = 0;
+	ctx->data_half = 0;
+
+	/* neither the PC nor the data pointer are valid */	
+	ctx->pc_ok = 0;
+	ctx->ptr_ok = 0;
+	
+	while (ctx->pipe_index < ctx->trace_depth)
+	{
+		u8 pipestat = ctx->trace_data[ctx->pipe_index].pipestat;
+		u32 next_pc = ctx->current_pc;
+		u32 old_data_index = ctx->data_index;
+		u32 old_data_half = ctx->data_half;
+		u32 old_index = ctx->pipe_index;
+		u32 last_instruction = ctx->last_instruction;
+		u32 cycles = 0;
+		int current_pc_ok = ctx->pc_ok;
+		
+		if (ctx->trace_data[ctx->pipe_index].flags & ETMV1_TRIGGER_CYCLE)
+		{
+			command_print(cmd_ctx, "--- trigger ---");
+		}
+
+		/* instructions execute in IE/D or BE/D cycles */
+		if ((pipestat == STAT_IE) || (pipestat == STAT_ID))
+			ctx->last_instruction = ctx->pipe_index;
+		
+		/* if we don't have a valid pc skip until we reach an indirect branch */
+		if ((!ctx->pc_ok) && (pipestat != STAT_BE))
+		{
+			ctx->pipe_index++;
+			continue;
+		}
+		
+		/* any indirect branch could have interrupted instruction flow
+		 * - the branch reason code could indicate a trace discontinuity
+		 * - a branch to the exception vectors indicates an exception
+		 */
+		if ((pipestat == STAT_BE) || (pipestat == STAT_BD))
+		{
+			/* backup current data index, to be able to consume the branch address
+			 * before examining data address and values
+			 */
+			old_data_index = ctx->data_index;
+			old_data_half = ctx->data_half;
+
+			ctx->last_instruction = ctx->pipe_index;
+			
+			if ((retval = etmv1_branch_address(ctx)) != 0)
+			{
+				/* negative return value from etmv1_branch_address means we ran out of packets,
+				 * quit analysing the trace */
+				if (retval < 0)
+					break;
+				
+				/* a positive return values means the current branch was abandoned,
+				 * and a new branch was encountered in cycle ctx->pipe_index + retval;
+				 */
+				WARNING("abandoned branch encountered, correctnes of analysis uncertain");
+				ctx->pipe_index += retval;
+				continue;
+			}
+			
+			/* skip over APO cycles */
+			ctx->pipe_index += 2;
+			
+			switch (ctx->last_branch_reason)
+			{
+				case 0x0:	/* normal PC change */
+					next_pc = ctx->last_branch;
+					break;
+				case 0x1:	/* tracing enabled */
+					command_print(cmd_ctx, "--- tracing enabled at 0x%8.8x ---", ctx->last_branch);
+					ctx->current_pc = ctx->last_branch;
+					ctx->pipe_index++;
+					continue;
+					break;
+				case 0x2:	/* trace restarted after FIFO overflow */
+					command_print(cmd_ctx, "--- trace restarted after FIFO overflow at 0x%8.8x ---", ctx->last_branch);
+					ctx->current_pc = ctx->last_branch;
+					ctx->pipe_index++;
+					continue;
+					break;
+				case 0x3:	/* exit from debug state */
+					command_print(cmd_ctx, "--- exit from debug state at 0x%8.8x ---", ctx->last_branch);
+					ctx->current_pc = ctx->last_branch;
+					ctx->pipe_index++;
+					continue;
+					break;
+				case 0x4:	/* periodic synchronization point */
+					next_pc = ctx->last_branch;
+					/* if we had no valid PC prior to this synchronization point,
+					 * we have to move on with the next trace cycle
+					 */
+					if (!current_pc_ok)
+					{
+						command_print(cmd_ctx, "--- periodic synchronization point at 0x%8.8x ---", next_pc);
+						ctx->current_pc = next_pc;
+						ctx->pipe_index++;
+						continue;
+					}
+					break;
+				default:	/* reserved */
+					ERROR("BUG: branch reason code 0x%x is reserved", ctx->last_branch_reason);		
+					exit(-1);
+					break;
+			}
+			
+			/* if we got here the branch was a normal PC change
+			 * (or a periodic synchronization point, which means the same for that matter)
+			 * if we didn't accquire a complete PC continue with the next cycle
+			 */
+			if (!ctx->pc_ok)
+				continue;
+			
+			/* indirect branch to the exception vector means an exception occured */
+			if (((ctx->last_branch >= 0x0) && (ctx->last_branch <= 0x20))
+				|| ((ctx->last_branch >= 0xffff0000) && (ctx->last_branch <= 0xffff0020)))
+			{
+				if ((ctx->last_branch & 0xff) == 0x10)
+				{
+					command_print(cmd_ctx, "data abort");
+				}
+				else
+				{
+					command_print(cmd_ctx, "exception vector 0x%2.2x", ctx->last_branch);
+					ctx->current_pc = ctx->last_branch;
+					ctx->pipe_index++;
+					continue;
+				}
+			}
+		}
+		
+		/* an instruction was executed (or not, depending on the condition flags)
+		 * retrieve it from the image for displaying */
+		if (ctx->pc_ok && (pipestat != STAT_WT) && (pipestat != STAT_TD) &&
+			!(((pipestat == STAT_BE) || (pipestat == STAT_BD)) &&
+				((ctx->last_branch_reason != 0x0) && (ctx->last_branch_reason != 0x4))))  
+		{
+			if ((retval = etm_read_instruction(ctx, &instruction)) != ERROR_OK)
+			{
+				/* can't continue tracing with no image available */
+				if (retval == ERROR_TRACE_IMAGE_UNAVAILABLE)
+				{
+					return retval;
+				}
+				else if (retval == ERROR_TRACE_INSTRUCTION_UNAVAILABLE)
+				{
+					/* TODO: handle incomplete images 
+					 * for now we just quit the analsysis*/
+					return retval;
+				}
+			}
+			
+			cycles = old_index - last_instruction;
+		}
+		
+		if ((pipestat == STAT_ID) || (pipestat == STAT_BD))
+		{
+			u32 new_data_index = ctx->data_index;
+			u32 new_data_half = ctx->data_half;
+			
+			/* in case of a branch with data, the branch target address was consumed before
+			 * we temporarily go back to the saved data index */
+			if (pipestat == STAT_BD)
+			{
+				ctx->data_index = old_data_index;
+				ctx->data_half = old_data_half;
+			}
+			
+			if (ctx->tracemode & ETMV1_TRACE_ADDR)
+			{			
+				u8 packet;
+				int shift = 0;
+				
+				do {
+					if ((retval = etmv1_next_packet(ctx, &packet, 0)) != 0)
+						return ERROR_ETM_ANALYSIS_FAILED;
+					ctx->last_ptr &= ~(0x7f << shift);
+					ctx->last_ptr |= (packet & 0x7f) << shift;
+					shift += 7;
+				} while ((packet & 0x80) && (shift < 32));
+				
+				if (shift >= 32)
+					ctx->ptr_ok = 1;
+				
+				if (ctx->ptr_ok)
+				{
+					command_print(cmd_ctx, "address: 0x%8.8x", ctx->last_ptr);
+				}
+			}
+			
+			if (ctx->tracemode & ETMV1_TRACE_DATA)
+			{
+				if ((instruction.type == ARM_LDM) || (instruction.type == ARM_STM))
+				{
+					int i;
+					for (i = 0; i < 16; i++)
+					{
+						if (instruction.info.load_store_multiple.register_list & (1 << i))
+						{
+							u32 data;
+							if (etmv1_data(ctx, 4, &data) != 0)
+								return ERROR_ETM_ANALYSIS_FAILED;
+							command_print(cmd_ctx, "data: 0x%8.8x", data);
+						}
+					}
+				}
+				else if ((instruction.type >= ARM_LDR) && (instruction.type <= ARM_STRH))
+				{
+					u32 data;
+					if (etmv1_data(ctx, arm_access_size(&instruction), &data) != 0)
+						return ERROR_ETM_ANALYSIS_FAILED;
+					command_print(cmd_ctx, "data: 0x%8.8x", data);
+				}
+			}
+			
+			/* restore data index after consuming BD address and data */
+			if (pipestat == STAT_BD)
+			{
+				ctx->data_index = new_data_index;
+				ctx->data_half = new_data_half;
+			}
+		}
+		
+		/* adjust PC */
+		if ((pipestat == STAT_IE) || (pipestat == STAT_ID))
+		{
+			if (((instruction.type == ARM_B) ||
+				(instruction.type == ARM_BL) ||
+				(instruction.type == ARM_BLX)) &&
+				(instruction.info.b_bl_bx_blx.target_address != -1))
+			{
+				next_pc = instruction.info.b_bl_bx_blx.target_address;
+			}
+			else
+			{
+				next_pc += (ctx->core_state == ARMV4_5_STATE_ARM) ? 4 : 2;
+			}
+		}
+		else if (pipestat == STAT_IN)
+		{
+			next_pc += (ctx->core_state == ARMV4_5_STATE_ARM) ? 4 : 2;
+		}
+
+		if ((pipestat != STAT_TD) && (pipestat != STAT_WT))
+		{
+			char cycles_text[32] = "";
+			
+			/* if the trace was captured with cycle accurate tracing enabled,
+			 * output the number of cycles since the last executed instruction
+			 */
+			if (ctx->tracemode & ETMV1_CYCLE_ACCURATE)
+			{
+				snprintf(cycles_text, 32, " (%i %s)",
+					cycles,
+					(cycles == 1) ? "cycle" : "cycles");
+			}
+			
+			command_print(cmd_ctx, "%s%s%s",
+				instruction.text,
+				(pipestat == STAT_IN) ? " (not executed)" : "",
+				cycles_text);
+
+			ctx->current_pc = next_pc;
+			
+			/* packets for an instruction don't start on or before the preceding
+			 * functional pipestat (i.e. other than WT or TD)
+			 */
+			if (ctx->data_index <= ctx->pipe_index)
+			{
+				ctx->data_index = ctx->pipe_index + 1;
+				ctx->data_half = 0;
+			}
+		}
+		
+		ctx->pipe_index += 1;
+	}
+	
+	return ERROR_OK;
+}
+
+int handle_etm_tracemode_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	target_t *target;
+	armv4_5_common_t *armv4_5;
+	arm7_9_common_t *arm7_9;
+	etmv1_tracemode_t tracemode;
+	
+	target = get_current_target(cmd_ctx);
+	
+	if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
+		return ERROR_OK;
+	}
+	
+	if (!arm7_9->etm_ctx)
+	{
+		command_print(cmd_ctx, "current target doesn't have an ETM configured");
+		return ERROR_OK;
+	}
+	
+	tracemode = arm7_9->etm_ctx->tracemode;
+
+	if (argc == 4)
+	{
+		if (strcmp(args[0], "none") == 0)
+		{
+			tracemode = ETMV1_TRACE_NONE;
+		}
+		else if (strcmp(args[0], "data") == 0)
+		{
+			tracemode = ETMV1_TRACE_DATA;
+		}
+		else if (strcmp(args[0], "address") == 0)
+		{
+			tracemode = ETMV1_TRACE_ADDR;
+		}
+		else if (strcmp(args[0], "all") == 0)
+		{
+			tracemode = ETMV1_TRACE_DATA | ETMV1_TRACE_ADDR;
+		}
+		else
+		{
+			command_print(cmd_ctx, "invalid option '%s'", args[0]);
+			return ERROR_OK;
+		}
+		
+		switch (strtol(args[1], NULL, 0))
+		{
+			case 0:
+				tracemode |= ETMV1_CONTEXTID_NONE;
+				break;
+			case 8:
+				tracemode |= ETMV1_CONTEXTID_8;
+				break;
+			case 16:
+				tracemode |= ETMV1_CONTEXTID_16;
+				break;
+			case 32:
+				tracemode |= ETMV1_CONTEXTID_32;
+				break;
+			default:
+				command_print(cmd_ctx, "invalid option '%s'", args[1]);
+				return ERROR_OK;
+		}
+		
+		if (strcmp(args[2], "enable") == 0)
+		{
+			tracemode |= ETMV1_CYCLE_ACCURATE;
+		}
+		else if (strcmp(args[2], "disable") == 0)
+		{
+			tracemode |= 0;
+		}
+		else
+		{
+			command_print(cmd_ctx, "invalid option '%s'", args[2]);
+			return ERROR_OK;
+		}
+		
+		if (strcmp(args[3], "enable") == 0)
+		{
+			tracemode |= ETMV1_BRANCH_OUTPUT;
+		}
+		else if (strcmp(args[3], "disable") == 0)
+		{
+			tracemode |= 0;
+		}
+		else
+		{
+			command_print(cmd_ctx, "invalid option '%s'", args[2]);
+			return ERROR_OK;
+		}
+	}
+	else if (argc != 0)
+	{
+		command_print(cmd_ctx, "usage: configure trace mode <none|data|address|all> <context id bits> <cycle accurate> <branch output>");
+		return ERROR_OK;
+	}
+	
+	command_print(cmd_ctx, "current tracemode configuration:");
+	
+	switch (tracemode & ETMV1_TRACE_MASK)
+	{
+		case ETMV1_TRACE_NONE:
+			command_print(cmd_ctx, "data tracing: none");
+			break;
+		case ETMV1_TRACE_DATA:
+			command_print(cmd_ctx, "data tracing: data only");
+			break;
+		case ETMV1_TRACE_ADDR:
+			command_print(cmd_ctx, "data tracing: address only");
+			break;
+		case ETMV1_TRACE_DATA | ETMV1_TRACE_ADDR:
+			command_print(cmd_ctx, "data tracing: address and data");
+			break;
+	}
+	
+	switch (tracemode & ETMV1_CONTEXTID_MASK)
+	{
+		case ETMV1_CONTEXTID_NONE:
+			command_print(cmd_ctx, "contextid tracing: none");
+			break;
+		case ETMV1_CONTEXTID_8:
+			command_print(cmd_ctx, "contextid tracing: 8 bit");
+			break;
+		case ETMV1_CONTEXTID_16:
+			command_print(cmd_ctx, "contextid tracing: 16 bit");
+			break;
+		case ETMV1_CONTEXTID_32:
+			command_print(cmd_ctx, "contextid tracing: 32 bit");
+			break;
+	}
+	
+	if (tracemode & ETMV1_CYCLE_ACCURATE)
+	{
+		command_print(cmd_ctx, "cycle-accurate tracing enabled");
+	}
+	else
+	{
+		command_print(cmd_ctx, "cycle-accurate tracing disabled");
+	}
+
+	if (tracemode & ETMV1_BRANCH_OUTPUT)
+	{
+		command_print(cmd_ctx, "full branch address output enabled");
+	}
+	else
+	{
+		command_print(cmd_ctx, "full branch address output disabled");
+	}
+	
+	/* only update ETM_CTRL register if tracemode changed */
+	if (arm7_9->etm_ctx->tracemode != tracemode)
+	{
+		reg_t *etm_ctrl_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CTRL];
+		
+		etm_get_reg(etm_ctrl_reg);
+		
+		buf_set_u32(etm_ctrl_reg->value, 2, 2, tracemode & ETMV1_TRACE_MASK);
+		buf_set_u32(etm_ctrl_reg->value, 14, 2, (tracemode & ETMV1_CONTEXTID_MASK) >> 4);
+		buf_set_u32(etm_ctrl_reg->value, 12, 1, (tracemode & ETMV1_CYCLE_ACCURATE) >> 8);
+		buf_set_u32(etm_ctrl_reg->value, 8, 1, (tracemode & ETMV1_BRANCH_OUTPUT) >> 9);
+		etm_store_reg(etm_ctrl_reg);
+		
+		arm7_9->etm_ctx->tracemode = tracemode;
+		
+		/* invalidate old trace data */
+		arm7_9->etm_ctx->capture_status = TRACE_IDLE;
+		if (arm7_9->etm_ctx->trace_depth > 0)
+		{
+			free(arm7_9->etm_ctx->trace_data);
+			arm7_9->etm_ctx->trace_data = NULL;
+		}
+		arm7_9->etm_ctx->trace_depth = 0;
+	}
+	
+	return ERROR_OK;
+}
+
+int handle_etm_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	target_t *target;
+	armv4_5_common_t *armv4_5;
+	arm7_9_common_t *arm7_9;
+	etm_portmode_t portmode = 0x0;
+	etm_context_t *etm_ctx = malloc(sizeof(etm_context_t));
+	int i;
+	
+	if (argc != 5)
+	{
+		ERROR("incomplete 'etm config <target> <port_width> <port_mode> <clocking> <capture_driver>' command");
+		exit(-1);
+	}
+	
+	target = get_target_by_num(strtoul(args[0], NULL, 0));
+	
+	if (!target)
+	{
+		ERROR("target number '%s' not defined", args[0]);
+		exit(-1);
+	}
+	
+	if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
+		return ERROR_OK;
+	}
+	
+	switch (strtoul(args[1], NULL, 0))
+	{
+		case 4:
+			portmode |= ETM_PORT_4BIT;
+			break;
+		case 8:
+			portmode |= ETM_PORT_8BIT;
+			break;
+		case 16:
+			portmode |= ETM_PORT_16BIT;
+			break;
+		default:
+			command_print(cmd_ctx, "unsupported ETM port width '%s', must be 4, 8 or 16", args[1]);
+			return ERROR_OK;
+	}
+	
+	if (strcmp("normal", args[2]) == 0)
+	{
+		portmode |= ETM_PORT_NORMAL;
+	}
+	else if (strcmp("multiplexed", args[2]) == 0)
+	{
+		portmode |= ETM_PORT_MUXED;
+	}
+	else if (strcmp("demultiplexed", args[2]) == 0)
+	{
+		portmode |= ETM_PORT_DEMUXED;
+	}
+	else
+	{
+		command_print(cmd_ctx, "unsupported ETM port mode '%s', must be 'normal', 'multiplexed' or 'demultiplexed'", args[2]);
+		return ERROR_OK;
+	}
+	
+	if (strcmp("half", args[3]) == 0)
+	{
+		portmode |= ETM_PORT_HALF_CLOCK;
+	}
+	else if (strcmp("full", args[3]) == 0)
+	{
+		portmode |= ETM_PORT_FULL_CLOCK;
+	}
+	else
+	{
+		command_print(cmd_ctx, "unsupported ETM port clocking '%s', must be 'full' or 'half'", args[3]);
+		return ERROR_OK;
+	}
+	
+	for (i=0; etm_capture_drivers[i]; i++)
+	{
+		if (strcmp(args[4], etm_capture_drivers[i]->name) == 0)
+		{
+			if (etm_capture_drivers[i]->register_commands(cmd_ctx) != ERROR_OK)
+			{
+				free(etm_ctx);
+				exit(-1);
+			}
+		
+			etm_ctx->capture_driver = etm_capture_drivers[i];
+
+			break;
+		}
+	}
+	
+	if (!etm_capture_drivers[i])
+	{
+		/* no supported capture driver found, don't register an ETM */
+		free(etm_ctx);
+		ERROR("trace capture driver '%s' not found", args[4]);
+		return ERROR_OK;
+	}
+	
+	etm_ctx->target = target;
+	etm_ctx->trigger_percent = 50;
+	etm_ctx->trace_data = NULL;
+	etm_ctx->trace_depth = 0;
+	etm_ctx->portmode = portmode;
+	etm_ctx->tracemode = 0x0;
+	etm_ctx->core_state = ARMV4_5_STATE_ARM;
+	etm_ctx->image = NULL;
+	etm_ctx->pipe_index = 0;
+	etm_ctx->data_index = 0;
+	etm_ctx->current_pc = 0x0;
+	etm_ctx->pc_ok = 0;
+	etm_ctx->last_branch = 0x0;
+	etm_ctx->last_branch_reason = 0x0;
+	etm_ctx->last_ptr = 0x0;
+	etm_ctx->ptr_ok = 0x0;
+	etm_ctx->context_id = 0x0;
+	etm_ctx->last_instruction = 0;
+	
+	arm7_9->etm_ctx = etm_ctx;
+	
+	etm_register_user_commands(cmd_ctx);
+	
+	return ERROR_OK;
+}
+
+int handle_etm_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	target_t *target;
+	armv4_5_common_t *armv4_5;
+	arm7_9_common_t *arm7_9;
+	reg_t *etm_config_reg;
+	reg_t *etm_sys_config_reg;
+	
+	int max_port_size;
+		
+	target = get_current_target(cmd_ctx);
+	
+	if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
+		return ERROR_OK;
+	}
+	
+	if (!arm7_9->etm_ctx)
+	{
+		command_print(cmd_ctx, "current target doesn't have an ETM configured");
+		return ERROR_OK;
+	}
+	
+	etm_config_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CONFIG];
+	etm_sys_config_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_SYS_CONFIG];
+	
+	etm_get_reg(etm_config_reg);
+	command_print(cmd_ctx, "pairs of address comparators: %i", buf_get_u32(etm_config_reg->value, 0, 4));
+	command_print(cmd_ctx, "pairs of data comparators: %i", buf_get_u32(etm_config_reg->value, 4, 4));
+	command_print(cmd_ctx, "memory map decoders: %i", buf_get_u32(etm_config_reg->value, 8, 5));
+	command_print(cmd_ctx, "number of counters: %i", buf_get_u32(etm_config_reg->value, 13, 3));
+	command_print(cmd_ctx, "sequencer %spresent",
+			(buf_get_u32(etm_config_reg->value, 16, 1) == 1) ? "" : "not ");
+	command_print(cmd_ctx, "number of ext. inputs: %i", buf_get_u32(etm_config_reg->value, 17, 3));
+	command_print(cmd_ctx, "number of ext. outputs: %i", buf_get_u32(etm_config_reg->value, 20, 3));
+	command_print(cmd_ctx, "FIFO full %spresent",
+			(buf_get_u32(etm_config_reg->value, 23, 1) == 1) ? "" : "not ");
+	command_print(cmd_ctx, "protocol version: %i", buf_get_u32(etm_config_reg->value, 28, 3));
+	
+	etm_get_reg(etm_sys_config_reg);
+
+	switch (buf_get_u32(etm_sys_config_reg->value, 0, 3))
+	{
+		case 0:
+			max_port_size = 4;
+			break;
+		case 1:
+			max_port_size = 8;
+			break;
+		case 2:
+			max_port_size = 16;
+			break;
+	}
+	command_print(cmd_ctx, "max. port size: %i", max_port_size);
+	
+	command_print(cmd_ctx, "half-rate clocking %ssupported",
+			(buf_get_u32(etm_sys_config_reg->value, 3, 1) == 1) ? "" : "not ");
+	command_print(cmd_ctx, "full-rate clocking %ssupported",
+			(buf_get_u32(etm_sys_config_reg->value, 4, 1) == 1) ? "" : "not ");
+	command_print(cmd_ctx, "normal trace format %ssupported",
+			(buf_get_u32(etm_sys_config_reg->value, 5, 1) == 1) ? "" : "not ");
+	command_print(cmd_ctx, "multiplex trace format %ssupported",
+			(buf_get_u32(etm_sys_config_reg->value, 6, 1) == 1) ? "" : "not ");
+	command_print(cmd_ctx, "demultiplex trace format %ssupported",
+			(buf_get_u32(etm_sys_config_reg->value, 7, 1) == 1) ? "" : "not ");
+	command_print(cmd_ctx, "FIFO full %ssupported",
+			(buf_get_u32(etm_sys_config_reg->value, 8, 1) == 1) ? "" : "not ");
+	
+	return ERROR_OK;
+}
+
+int handle_etm_status_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	target_t *target;
+	armv4_5_common_t *armv4_5;
+	arm7_9_common_t *arm7_9;
+	trace_status_t trace_status;
+	
+	target = get_current_target(cmd_ctx);
+	
+	if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
+		return ERROR_OK;
+	}
+	
+	if (!arm7_9->etm_ctx)
+	{
+		command_print(cmd_ctx, "current target doesn't have an ETM configured");
+		return ERROR_OK;
+	}
+	
+	trace_status = arm7_9->etm_ctx->capture_driver->status(arm7_9->etm_ctx);
+	
+	if (trace_status == TRACE_IDLE)
+	{
+		command_print(cmd_ctx, "tracing is idle");
+	}
+	else
+	{
+		static char *completed = " completed";
+		static char *running = " is running";
+		static char *overflowed = ", trace overflowed";
+		static char *triggered = ", trace triggered";
+		
+		command_print(cmd_ctx, "trace collection%s%s%s", 
+			(trace_status & TRACE_RUNNING) ? running : completed,
+			(trace_status & TRACE_OVERFLOWED) ? overflowed : "",
+			(trace_status & TRACE_TRIGGERED) ? triggered : "");
+		
+		if (arm7_9->etm_ctx->trace_depth > 0)
+		{
+			command_print(cmd_ctx, "%i frames of trace data read", arm7_9->etm_ctx->trace_depth);
+		}
+	}
+	
+	return ERROR_OK;
+}
+
+int handle_etm_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	target_t *target;
+	armv4_5_common_t *armv4_5;
+	arm7_9_common_t *arm7_9;
+	etm_context_t *etm_ctx;
+
+	if (argc < 1)
+	{
+		command_print(cmd_ctx, "usage: etm image <file> [base address] [type]");
+		return ERROR_OK;
+	}
+	
+	target = get_current_target(cmd_ctx);
+	
+	if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
+		return ERROR_OK;
+	}
+	
+	if (!(etm_ctx = arm7_9->etm_ctx))
+	{
+		command_print(cmd_ctx, "current target doesn't have an ETM configured");
+		return ERROR_OK;
+	}
+	
+	if (etm_ctx->image)
+	{
+		image_close(etm_ctx->image);
+		free(etm_ctx->image);
+		command_print(cmd_ctx, "previously loaded image found and closed");
+	}
+	
+	etm_ctx->image = malloc(sizeof(image_t));
+	etm_ctx->image->base_address_set = 0;
+	etm_ctx->image->start_address_set = 0;
+	
+	/* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */
+	if (argc >= 2)
+	{
+		etm_ctx->image->base_address_set = 1;
+		etm_ctx->image->base_address = strtoul(args[1], NULL, 0);
+	}
+	else
+	{
+		etm_ctx->image->base_address_set = 0;
+	}
+		
+	if (image_open(etm_ctx->image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "image opening error: %s", etm_ctx->image->error_str);
+		free(etm_ctx->image);
+		etm_ctx->image = NULL;
+		return ERROR_OK;
+	}
+	
+	return ERROR_OK;
+}
+
+int handle_etm_dump_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	fileio_t file;
+	target_t *target;
+	armv4_5_common_t *armv4_5;
+	arm7_9_common_t *arm7_9;
+	etm_context_t *etm_ctx;
+	int i;
+	
+	if (argc != 1)
+	{
+		command_print(cmd_ctx, "usage: etm dump <file>");
+		return ERROR_OK;
+	}
+	
+	target = get_current_target(cmd_ctx);
+	
+	if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
+		return ERROR_OK;
+	}
+	
+	if (!(etm_ctx = arm7_9->etm_ctx))
+	{
+		command_print(cmd_ctx, "current target doesn't have an ETM configured");
+		return ERROR_OK;
+	}
+	
+	if (etm_ctx->capture_driver->status == TRACE_IDLE)
+	{
+		command_print(cmd_ctx, "trace capture wasn't enabled, no trace data captured");
+		return ERROR_OK;
+	}
+
+	if (etm_ctx->capture_driver->status(etm_ctx) & TRACE_RUNNING)
+	{
+		/* TODO: if on-the-fly capture is to be supported, this needs to be changed */
+		command_print(cmd_ctx, "trace capture not completed");
+		return ERROR_OK;
+	}
+	
+	/* read the trace data if it wasn't read already */
+	if (etm_ctx->trace_depth == 0)
+		etm_ctx->capture_driver->read_trace(etm_ctx);
+	
+	if (fileio_open(&file, args[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "file open error: %s", file.error_str);
+		return ERROR_OK;
+	}
+	
+	fileio_write_u32(&file, etm_ctx->capture_status);
+	fileio_write_u32(&file, etm_ctx->portmode);
+	fileio_write_u32(&file, etm_ctx->tracemode);
+	fileio_write_u32(&file, etm_ctx->trace_depth);
+	
+	for (i = 0; i < etm_ctx->trace_depth; i++)
+	{
+		fileio_write_u32(&file, etm_ctx->trace_data[i].pipestat);
+		fileio_write_u32(&file, etm_ctx->trace_data[i].packet);
+		fileio_write_u32(&file, etm_ctx->trace_data[i].flags);
+	}
+	
+	fileio_close(&file);
+	
+	return ERROR_OK;	
+}
+
+int handle_etm_load_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	fileio_t file;
+	target_t *target;
+	armv4_5_common_t *armv4_5;
+	arm7_9_common_t *arm7_9;
+	etm_context_t *etm_ctx;
+	int i;
+	
+	if (argc != 1)
+	{
+		command_print(cmd_ctx, "usage: etm load <file>");
+		return ERROR_OK;
+	}
+	
+	target = get_current_target(cmd_ctx);
+	
+	if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
+		return ERROR_OK;
+	}
+	
+	if (!(etm_ctx = arm7_9->etm_ctx))
+	{
+		command_print(cmd_ctx, "current target doesn't have an ETM configured");
+		return ERROR_OK;
+	}
+	
+	if (etm_ctx->capture_driver->status(etm_ctx) & TRACE_RUNNING)
+	{
+		command_print(cmd_ctx, "trace capture running, stop first");
+		return ERROR_OK;
+	}
+	
+	if (fileio_open(&file, args[0], FILEIO_READ, FILEIO_BINARY) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "file open error: %s", file.error_str);
+		return ERROR_OK;
+	}
+	
+	if (file.size % 4)
+	{
+		command_print(cmd_ctx, "size isn't a multiple of 4, no valid trace data");
+		return ERROR_OK;
+	}
+	
+	if (etm_ctx->trace_depth > 0)
+	{
+		free(etm_ctx->trace_data);
+	}
+	
+	fileio_read_u32(&file, &etm_ctx->capture_status);
+	fileio_read_u32(&file, &etm_ctx->portmode);
+	fileio_read_u32(&file, &etm_ctx->tracemode);
+	fileio_read_u32(&file, &etm_ctx->trace_depth);
+	
+	etm_ctx->trace_data = malloc(sizeof(etmv1_trace_data_t) * etm_ctx->trace_depth);
+	
+	for (i = 0; i < etm_ctx->trace_depth; i++)
+	{
+		u32 pipestat, packet, flags;
+		fileio_read_u32(&file, &pipestat);
+		fileio_read_u32(&file, &packet);
+		fileio_read_u32(&file, &flags);
+		etm_ctx->trace_data[i].pipestat = pipestat & 0xff;
+		etm_ctx->trace_data[i].packet = packet & 0xffff;
+		etm_ctx->trace_data[i].flags = flags;
+	}
+	
+	fileio_close(&file);
+	
+	return ERROR_OK;	
+}
+
+int handle_etm_trigger_percent_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	target_t *target;
+	armv4_5_common_t *armv4_5;
+	arm7_9_common_t *arm7_9;
+	etm_context_t *etm_ctx;
+	
+	target = get_current_target(cmd_ctx);
+	
+	if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
+		return ERROR_OK;
+	}
+	
+	if (!(etm_ctx = arm7_9->etm_ctx))
+	{
+		command_print(cmd_ctx, "current target doesn't have an ETM configured");
+		return ERROR_OK;
+	}
+	
+	if (argc > 0)
+	{
+		u32 new_value = strtoul(args[0], NULL, 0);
+		
+		if ((new_value < 2) || (new_value > 100))
+		{
+			command_print(cmd_ctx, "valid settings are 2% to 100%");
+		}
+		else
+		{
+			etm_ctx->trigger_percent = new_value;
+		}
+	}
+	
+	command_print(cmd_ctx, "%i percent of the tracebuffer reserved for after the trigger", etm_ctx->trigger_percent);
+
+	return ERROR_OK;
+}
+
+int handle_etm_start_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	target_t *target;
+	armv4_5_common_t *armv4_5;
+	arm7_9_common_t *arm7_9;
+	etm_context_t *etm_ctx;
+	reg_t *etm_ctrl_reg;
+
+	target = get_current_target(cmd_ctx);
+	
+	if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
+		return ERROR_OK;
+	}
+	
+	if (!(etm_ctx = arm7_9->etm_ctx))
+	{
+		command_print(cmd_ctx, "current target doesn't have an ETM configured");
+		return ERROR_OK;
+	}
+	
+	/* invalidate old tracing data */
+	arm7_9->etm_ctx->capture_status = TRACE_IDLE;
+	if (arm7_9->etm_ctx->trace_depth > 0)
+	{
+		free(arm7_9->etm_ctx->trace_data);
+		arm7_9->etm_ctx->trace_data = NULL;
+	}
+	arm7_9->etm_ctx->trace_depth = 0;
+		
+	etm_ctrl_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CTRL];
+	etm_get_reg(etm_ctrl_reg);
+		
+	/* Clear programming bit (10), set port selection bit (11) */
+	buf_set_u32(etm_ctrl_reg->value, 10, 2, 0x2);
+
+	etm_store_reg(etm_ctrl_reg);
+	jtag_execute_queue();
+
+	etm_ctx->capture_driver->start_capture(etm_ctx);
+
+	return ERROR_OK;
+}
+
+int handle_etm_stop_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	target_t *target;
+	armv4_5_common_t *armv4_5;
+	arm7_9_common_t *arm7_9;
+	etm_context_t *etm_ctx;
+	reg_t *etm_ctrl_reg;
+
+	target = get_current_target(cmd_ctx);
+	
+	if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
+		return ERROR_OK;
+	}
+	
+	if (!(etm_ctx = arm7_9->etm_ctx))
+	{
+		command_print(cmd_ctx, "current target doesn't have an ETM configured");
+		return ERROR_OK;
+	}
+	
+	etm_ctrl_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CTRL];
+	etm_get_reg(etm_ctrl_reg);
+		
+	/* Set programming bit (10), clear port selection bit (11) */
+	buf_set_u32(etm_ctrl_reg->value, 10, 2, 0x1);
+
+	etm_store_reg(etm_ctrl_reg);	
+	jtag_execute_queue();
+	
+	etm_ctx->capture_driver->stop_capture(etm_ctx);
+	
+	return ERROR_OK;
+}
+
+int handle_etm_analyze_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	target_t *target;
+	armv4_5_common_t *armv4_5;
+	arm7_9_common_t *arm7_9;
+	etm_context_t *etm_ctx;
+	int retval;
+
+	target = get_current_target(cmd_ctx);
+	
+	if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");
+		return ERROR_OK;
+	}
+	
+	if (!(etm_ctx = arm7_9->etm_ctx))
+	{
+		command_print(cmd_ctx, "current target doesn't have an ETM configured");
+		return ERROR_OK;
+	}
+	
+	if ((retval = etmv1_analyze_trace(etm_ctx, cmd_ctx)) != ERROR_OK)
+	{
+		switch(retval)
+		{
+			case ERROR_ETM_ANALYSIS_FAILED:
+				command_print(cmd_ctx, "further analysis failed (corrupted trace data or just end of data");
+				break;
+			case ERROR_TRACE_INSTRUCTION_UNAVAILABLE:
+				command_print(cmd_ctx, "no instruction for current address available, analysis aborted");
+				break;
+			case ERROR_TRACE_IMAGE_UNAVAILABLE:
+				command_print(cmd_ctx, "no image available for trace analysis");
+				break;
+			default:
+				command_print(cmd_ctx, "unknown error: %i", retval);
+		}
+	}
+	
+	return ERROR_OK;
+}
+
+int etm_register_commands(struct command_context_s *cmd_ctx)
+{
+	etm_cmd = register_command(cmd_ctx, NULL, "etm", NULL, COMMAND_ANY, "Embedded Trace Macrocell");
+
+	register_command(cmd_ctx, etm_cmd, "config", handle_etm_config_command, COMMAND_CONFIG, NULL);
+
+	return ERROR_OK;
+}
+
+int etm_register_user_commands(struct command_context_s *cmd_ctx)
+{
+	register_command(cmd_ctx, etm_cmd, "tracemode", handle_etm_tracemode_command,
+		COMMAND_EXEC, "configure trace mode <none|data|address|all> <context id bits> <cycle accurate> <branch output");
+
+	register_command(cmd_ctx, etm_cmd, "info", handle_etm_info_command,
+		COMMAND_EXEC, "display info about the current target's ETM");
+
+	register_command(cmd_ctx, etm_cmd, "trigger_percent <percent>", handle_etm_trigger_percent_command,
+		COMMAND_EXEC, "amount (<percent>) of trace buffer to be filled after the trigger occured");
+	register_command(cmd_ctx, etm_cmd, "status", handle_etm_status_command,
+		COMMAND_EXEC, "display current target's ETM status");
+	register_command(cmd_ctx, etm_cmd, "start", handle_etm_start_command,
+		COMMAND_EXEC, "start ETM trace collection");
+	register_command(cmd_ctx, etm_cmd, "stop", handle_etm_stop_command,
+		COMMAND_EXEC, "stop ETM trace collection");
+
+	register_command(cmd_ctx, etm_cmd, "analyze", handle_etm_analyze_command,
+		COMMAND_EXEC, "anaylze collected ETM trace");
+
+	register_command(cmd_ctx, etm_cmd, "image", handle_etm_image_command,
+		COMMAND_EXEC, "load image from <file> [base address]");
+
+	register_command(cmd_ctx, etm_cmd, "dump", handle_etm_dump_command,
+		COMMAND_EXEC, "dump captured trace data <file>");
+	register_command(cmd_ctx, etm_cmd, "load", handle_etm_load_command,
+		COMMAND_EXEC, "load trace data for analysis <file>");
+
+	return ERROR_OK;
+}
diff --git a/src/target/target.c b/src/target/target.c
index 27df12fc33f42d34466c6f5ea6ad300ce90f822a..a9f7c1034b893b2e9f557b120e0fcb2ee3eed643 100644
--- a/src/target/target.c
+++ b/src/target/target.c
@@ -1,2332 +1,2332 @@
-/***************************************************************************
- *   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.             *
- ***************************************************************************/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "replacements.h"
-#include "target.h"
-#include "target_request.h"
-
-#include "log.h"
-#include "configuration.h"
-#include "binarybuffer.h"
-#include "jtag.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <inttypes.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <errno.h>
-
-#include <sys/time.h>
-#include <time.h>
-
-#include <time_support.h>
-
-#include <fileio.h>
-#include <image.h>
-
-int cli_target_callback_event_handler(struct target_s *target, enum target_event event, void *priv);
-
-
-int handle_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_daemon_startup_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_targets_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-
-int handle_target_script_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_run_and_halt_time_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_working_area_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-
-int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_poll_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_wait_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_soft_reset_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_resume_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_step_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_bp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_rbp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_rwp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
-int handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc);
-
-/* targets
- */
-extern target_type_t arm7tdmi_target;
-extern target_type_t arm720t_target;
-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 feroceon_target;
-extern target_type_t xscale_target;
-extern target_type_t cortexm3_target;
-
-target_type_t *target_types[] =
-{
-	&arm7tdmi_target,
-	&arm9tdmi_target,
-	&arm920t_target,
-	&arm720t_target,
-	&arm966e_target,
-	&arm926ejs_target,
-	&feroceon_target,
-	&xscale_target,
-	&cortexm3_target,
-	NULL,
-};
-
-target_t *targets = NULL;
-target_event_callback_t *target_event_callbacks = NULL;
-target_timer_callback_t *target_timer_callbacks = NULL;
-
-char *target_state_strings[] =
-{
-	"unknown",
-	"running",
-	"halted",
-	"reset",
-	"debug_running",
-};
-
-char *target_debug_reason_strings[] =
-{
-	"debug request", "breakpoint", "watchpoint",
-	"watchpoint and breakpoint", "single step",
-	"target not halted"
-};
-
-char *target_endianess_strings[] =
-{
-	"big endian",
-	"little endian",
-};
-
-enum daemon_startup_mode startup_mode = DAEMON_ATTACH;
-
-static int target_continous_poll = 1;
-
-/* read a u32 from a buffer in target memory endianness */
-u32 target_buffer_get_u32(target_t *target, u8 *buffer)
-{
-	if (target->endianness == TARGET_LITTLE_ENDIAN)
-		return le_to_h_u32(buffer);
-	else
-		return be_to_h_u32(buffer);
-}
-
-/* read a u16 from a buffer in target memory endianness */
-u16 target_buffer_get_u16(target_t *target, u8 *buffer)
-{
-	if (target->endianness == TARGET_LITTLE_ENDIAN)
-		return le_to_h_u16(buffer);
-	else
-		return be_to_h_u16(buffer);
-}
-
-/* write a u32 to a buffer in target memory endianness */
-void target_buffer_set_u32(target_t *target, u8 *buffer, u32 value)
-{
-	if (target->endianness == TARGET_LITTLE_ENDIAN)
-		h_u32_to_le(buffer, value);
-	else
-		h_u32_to_be(buffer, value);
-}
-
-/* write a u16 to a buffer in target memory endianness */
-void target_buffer_set_u16(target_t *target, u8 *buffer, u16 value)
-{
-	if (target->endianness == TARGET_LITTLE_ENDIAN)
-		h_u16_to_le(buffer, value);
-	else
-		h_u16_to_be(buffer, value);
-}
-
-/* returns a pointer to the n-th configured target */
-target_t* get_target_by_num(int num)
-{
-	target_t *target = targets;
-	int i = 0;
-
-	while (target)
-	{
-		if (num == i)
-			return target;
-		target = target->next;
-		i++;
-	}
-
-	return NULL;
-}
-
-int get_num_by_target(target_t *query_target)
-{
-	target_t *target = targets;
-	int i = 0;	
-	
-	while (target)
-	{
-		if (target == query_target)
-			return i;
-		target = target->next;
-		i++;
-	}
-	
-	return -1;
-}
-
-target_t* get_current_target(command_context_t *cmd_ctx)
-{
-	target_t *target = get_target_by_num(cmd_ctx->current_target);
-	
-	if (target == NULL)
-	{
-		ERROR("BUG: current_target out of bounds");
-		exit(-1);
-	}
-	
-	return target;
-}
-
-/* Process target initialization, when target entered debug out of reset
- * the handler is unregistered at the end of this function, so it's only called once
- */
-int target_init_handler(struct target_s *target, enum target_event event, void *priv)
-{
-	FILE *script;
-	struct command_context_s *cmd_ctx = priv;
-	
-	if ((event == TARGET_EVENT_HALTED) && (target->reset_script))
-	{
-		target_unregister_event_callback(target_init_handler, priv);
-
-		script = open_file_from_path(cmd_ctx, target->reset_script, "r");
-		if (!script)
-		{
-			ERROR("couldn't open script file %s", target->reset_script);
-				return ERROR_OK;
-		}
-
-		INFO("executing reset script '%s'", target->reset_script);
-		command_run_file(cmd_ctx, script, COMMAND_EXEC);
-		fclose(script);
-
-		jtag_execute_queue();
-	}
-	
-	return ERROR_OK;
-}
-
-int target_run_and_halt_handler(void *priv)
-{
-	target_t *target = priv;
-	
-	target->type->halt(target);
-	
-	return ERROR_OK;
-}
-
-int target_process_reset(struct command_context_s *cmd_ctx)
-{
-	int retval = ERROR_OK;
-	target_t *target;
-	struct timeval timeout, now;
-	
-	/* prepare reset_halt where necessary */
-	target = targets;
-	while (target)
-	{
-		if (jtag_reset_config & RESET_SRST_PULLS_TRST)
-		{
-			switch (target->reset_mode)
-			{
-				case RESET_HALT:
-					command_print(cmd_ctx, "nSRST pulls nTRST, falling back to RESET_RUN_AND_HALT");
-					target->reset_mode = RESET_RUN_AND_HALT;
-					break;
-				case RESET_INIT:
-					command_print(cmd_ctx, "nSRST pulls nTRST, falling back to RESET_RUN_AND_INIT");
-					target->reset_mode = RESET_RUN_AND_INIT;
-					break;
-				default:
-					break;
-			} 
-		}
-		switch (target->reset_mode)
-		{
-			case RESET_HALT:
-			case RESET_INIT:
-				target->type->prepare_reset_halt(target);
-				break;
-			default:
-				break;
-		}
-		target = target->next;
-	}
-	
-	target = targets;
-	while (target)
-	{
-		target->type->assert_reset(target);
-		target = target->next;
-	}
-	jtag_execute_queue();
-	
-	/* request target halt if necessary, and schedule further action */
-	target = targets;
-	while (target)
-	{
-		switch (target->reset_mode)
-		{
-			case RESET_RUN:
-				/* nothing to do if target just wants to be run */
-				break;
-			case RESET_RUN_AND_HALT:
-				/* schedule halt */
-				target_register_timer_callback(target_run_and_halt_handler, target->run_and_halt_time, 0, target);
-				break;
-			case RESET_RUN_AND_INIT:
-				/* schedule halt */
-				target_register_timer_callback(target_run_and_halt_handler, target->run_and_halt_time, 0, target);
-				target_register_event_callback(target_init_handler, cmd_ctx);
-				break;
-			case RESET_HALT:
-				target->type->halt(target);
-				break;
-			case RESET_INIT:
-				target->type->halt(target);
-				target_register_event_callback(target_init_handler, cmd_ctx);
-				break;
-			default:
-				ERROR("BUG: unknown target->reset_mode");
-		}
-		target = target->next;
-	}
-	
-	target = targets;
-	while (target)
-	{
-		target->type->deassert_reset(target);
-		target = target->next;
-	}
-	jtag_execute_queue();
-
-	/* Wait for reset to complete, maximum 5 seconds. */	
-	gettimeofday(&timeout, NULL);
-	timeval_add_time(&timeout, 5, 0);
-	for(;;)
-	{
-		gettimeofday(&now, NULL);
-		
-		target_call_timer_callbacks();
-		
-		target = targets;
-		while (target)
-		{
-			target->type->poll(target);
-			if ((target->reset_mode == RESET_RUN_AND_INIT) || (target->reset_mode == RESET_RUN_AND_HALT))
-			{
-				if (target->state != TARGET_HALTED)
-				{
-					if ((now.tv_sec > timeout.tv_sec) || ((now.tv_sec == timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec)))
-					{
-						command_print(cmd_ctx, "Timed out waiting for reset");
-						goto done;
-					}
-					usleep(100*1000); /* Do not eat all cpu */
-					goto again;
-				}
-			}
-			target = target->next;
-		}
-		/* All targets we're waiting for are halted */
-		break;
-		
-		again:;
-	}
-	done:
-	
-	
-	/* We want any events to be processed before the prompt */
-	target_call_timer_callbacks();
-	
-	return retval;
-}
-
-static int default_virt2phys(struct target_s *target, u32 virtual, u32 *physical)
-{
-	*physical = virtual;
-	return ERROR_OK;
-}
-
-static int default_mmu(struct target_s *target, int *enabled)
-{
-	*enabled = 0;
-	return ERROR_OK;
-}
-
-int target_init(struct command_context_s *cmd_ctx)
-{
-	target_t *target = targets;
-	
-	while (target)
-	{
-		if (target->type->init_target(cmd_ctx, target) != ERROR_OK)
-		{
-			ERROR("target '%s' init failed", target->type->name);
-			exit(-1);
-		}
-		
-		/* Set up default functions if none are provided by target */
-		if (target->type->virt2phys == NULL)
-		{
-			target->type->virt2phys = default_virt2phys;
-		}
-		if (target->type->mmu == NULL)
-		{
-			target->type->mmu = default_mmu;
-		}
-		target = target->next;
-	}
-	
-	if (targets)
-	{
-		target_register_user_commands(cmd_ctx);
-		target_register_timer_callback(handle_target, 100, 1, NULL);
-	}
-		
-	return ERROR_OK;
-}
-
-int target_init_reset(struct command_context_s *cmd_ctx)
-{
-	if (startup_mode == DAEMON_RESET)
-		target_process_reset(cmd_ctx);
-	
-	return ERROR_OK;
-}
-
-int target_register_event_callback(int (*callback)(struct target_s *target, enum target_event event, void *priv), void *priv)
-{
-	target_event_callback_t **callbacks_p = &target_event_callbacks;
-	
-	if (callback == NULL)
-	{
-		return ERROR_INVALID_ARGUMENTS;
-	}
-	
-	if (*callbacks_p)
-	{
-		while ((*callbacks_p)->next)
-			callbacks_p = &((*callbacks_p)->next);
-		callbacks_p = &((*callbacks_p)->next);
-	}
-	
-	(*callbacks_p) = malloc(sizeof(target_event_callback_t));
-	(*callbacks_p)->callback = callback;
-	(*callbacks_p)->priv = priv;
-	(*callbacks_p)->next = NULL;
-	
-	return ERROR_OK;
-}
-
-int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int periodic, void *priv)
-{
-	target_timer_callback_t **callbacks_p = &target_timer_callbacks;
-	struct timeval now;
-	
-	if (callback == NULL)
-	{
-		return ERROR_INVALID_ARGUMENTS;
-	}
-	
-	if (*callbacks_p)
-	{
-		while ((*callbacks_p)->next)
-			callbacks_p = &((*callbacks_p)->next);
-		callbacks_p = &((*callbacks_p)->next);
-	}
-	
-	(*callbacks_p) = malloc(sizeof(target_timer_callback_t));
-	(*callbacks_p)->callback = callback;
-	(*callbacks_p)->periodic = periodic;
-	(*callbacks_p)->time_ms = time_ms;
-	
-	gettimeofday(&now, NULL);
-	(*callbacks_p)->when.tv_usec = now.tv_usec + (time_ms % 1000) * 1000;
-	time_ms -= (time_ms % 1000);
-	(*callbacks_p)->when.tv_sec = now.tv_sec + (time_ms / 1000);
-	if ((*callbacks_p)->when.tv_usec > 1000000)
-	{
-		(*callbacks_p)->when.tv_usec = (*callbacks_p)->when.tv_usec - 1000000;
-		(*callbacks_p)->when.tv_sec += 1;
-	}
-	
-	(*callbacks_p)->priv = priv;
-	(*callbacks_p)->next = NULL;
-	
-	return ERROR_OK;
-}
-
-int target_unregister_event_callback(int (*callback)(struct target_s *target, enum target_event event, void *priv), void *priv)
-{
-	target_event_callback_t **p = &target_event_callbacks;
-	target_event_callback_t *c = target_event_callbacks;
-	
-	if (callback == NULL)
-	{
-		return ERROR_INVALID_ARGUMENTS;
-	}
-		
-	while (c)
-	{
-		target_event_callback_t *next = c->next;
-		if ((c->callback == callback) && (c->priv == priv))
-		{
-			*p = next;
-			free(c);
-			return ERROR_OK;
-		}
-		else
-			p = &(c->next);
-		c = next;
-	}
-	
-	return ERROR_OK;
-}
-
-int target_unregister_timer_callback(int (*callback)(void *priv), void *priv)
-{
-	target_timer_callback_t **p = &target_timer_callbacks;
-	target_timer_callback_t *c = target_timer_callbacks;
-	
-	if (callback == NULL)
-	{
-		return ERROR_INVALID_ARGUMENTS;
-	}
-		
-	while (c)
-	{
-		target_timer_callback_t *next = c->next;
-		if ((c->callback == callback) && (c->priv == priv))
-		{
-			*p = next;
-			free(c);
-			return ERROR_OK;
-		}
-		else
-			p = &(c->next);
-		c = next;
-	}
-	
-	return ERROR_OK;
-}
-
-int target_call_event_callbacks(target_t *target, enum target_event event)
-{
-	target_event_callback_t *callback = target_event_callbacks;
-	target_event_callback_t *next_callback;
-	
-	DEBUG("target event %i", event);
-	
-	while (callback)
-	{
-		next_callback = callback->next;
-		callback->callback(target, event, callback->priv);
-		callback = next_callback;
-	}
-	
-	return ERROR_OK;
-}
-
-int target_call_timer_callbacks()
-{
-	target_timer_callback_t *callback = target_timer_callbacks;
-	target_timer_callback_t *next_callback;
-	struct timeval now;
-
-	gettimeofday(&now, NULL);
-	
-	while (callback)
-	{
-		next_callback = callback->next;
-		
-		if (((now.tv_sec >= callback->when.tv_sec) && (now.tv_usec >= callback->when.tv_usec))
-			|| (now.tv_sec > callback->when.tv_sec))
-		{
-			callback->callback(callback->priv);
-			if (callback->periodic)
-			{
-				int time_ms = callback->time_ms;
-				callback->when.tv_usec = now.tv_usec + (time_ms % 1000) * 1000;
-				time_ms -= (time_ms % 1000);
-				callback->when.tv_sec = now.tv_sec + time_ms / 1000;
-				if (callback->when.tv_usec > 1000000)
-				{
-					callback->when.tv_usec = callback->when.tv_usec - 1000000;
-					callback->when.tv_sec += 1;
-				}
-			}
-			else
-				target_unregister_timer_callback(callback->callback, callback->priv);
-		}
-			
-		callback = next_callback;
-	}
-	
-	return ERROR_OK;
-}
-
-int target_alloc_working_area(struct target_s *target, u32 size, working_area_t **area)
-{
-	working_area_t *c = target->working_areas;
-	working_area_t *new_wa = NULL;
-	
-	/* Reevaluate working area address based on MMU state*/
-	if (target->working_areas == NULL)
-	{
-		int retval;
-		int enabled;
-		retval = target->type->mmu(target, &enabled);
-		if (retval != ERROR_OK)
-		{
-			return retval;
-		}
-		if (enabled)
-		{
-			target->working_area = target->working_area_virt;
-		}
-		else
-		{
-			target->working_area = target->working_area_phys;
-		}
-	}
-	
-	/* only allocate multiples of 4 byte */
-	if (size % 4)
-	{
-		ERROR("BUG: code tried to allocate unaligned number of bytes, padding");
-		size = CEIL(size, 4);
-	}
-	
-	/* see if there's already a matching working area */
-	while (c)
-	{
-		if ((c->free) && (c->size == size))
-		{
-			new_wa = c;
-			break;
-		}
-		c = c->next;
-	}
-	
-	/* if not, allocate a new one */
-	if (!new_wa)
-	{
-		working_area_t **p = &target->working_areas;
-		u32 first_free = target->working_area;
-		u32 free_size = target->working_area_size;
-		
-		DEBUG("allocating new working area");
-		
-		c = target->working_areas;
-		while (c)
-		{
-			first_free += c->size;
-			free_size -= c->size;
-			p = &c->next;
-			c = c->next;
-		}
-		
-		if (free_size < size)
-		{
-			WARNING("not enough working area available(requested %d, free %d)", size, free_size);
-			return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-		}
-		
-		new_wa = malloc(sizeof(working_area_t));
-		new_wa->next = NULL;
-		new_wa->size = size;
-		new_wa->address = first_free;
-		
-		if (target->backup_working_area)
-		{
-			new_wa->backup = malloc(new_wa->size);
-			target->type->read_memory(target, new_wa->address, 4, new_wa->size / 4, new_wa->backup);
-		}
-		else
-		{
-			new_wa->backup = NULL;
-		}
-		
-		/* put new entry in list */
-		*p = new_wa;
-	}
-	
-	/* mark as used, and return the new (reused) area */
-	new_wa->free = 0;
-	*area = new_wa;
-	
-	/* user pointer */
-	new_wa->user = area;
-	
-	return ERROR_OK;
-}
-
-int target_free_working_area(struct target_s *target, working_area_t *area)
-{
-	if (area->free)
-		return ERROR_OK;
-	
-	if (target->backup_working_area)
-		target->type->write_memory(target, area->address, 4, area->size / 4, area->backup);
-	
-	area->free = 1;
-	
-	/* mark user pointer invalid */
-	*area->user = NULL;
-	area->user = NULL;
-	
-	return ERROR_OK;
-}
-
-int target_free_all_working_areas(struct target_s *target)
-{
-	working_area_t *c = target->working_areas;
-
-	while (c)
-	{
-		working_area_t *next = c->next;
-		target_free_working_area(target, c);
-		
-		if (c->backup)
-			free(c->backup);
-		
-		free(c);
-		
-		c = next;
-	}
-	
-	target->working_areas = NULL;
-	
-	return ERROR_OK;
-}
-
-int target_register_commands(struct command_context_s *cmd_ctx)
-{
-	register_command(cmd_ctx, NULL, "target", handle_target_command, COMMAND_CONFIG, NULL);
-	register_command(cmd_ctx, NULL, "targets", handle_targets_command, COMMAND_EXEC, NULL);
-	register_command(cmd_ctx, NULL, "daemon_startup", handle_daemon_startup_command, COMMAND_CONFIG, NULL);
-	register_command(cmd_ctx, NULL, "target_script", handle_target_script_command, COMMAND_CONFIG, NULL);
-	register_command(cmd_ctx, NULL, "run_and_halt_time", handle_run_and_halt_time_command, COMMAND_CONFIG, NULL);
-	register_command(cmd_ctx, NULL, "working_area", handle_working_area_command, COMMAND_ANY, "working_area <target#> <address> <size> <'backup'|'nobackup'> [virtual address]");
-	register_command(cmd_ctx, NULL, "virt2phys", handle_virt2phys_command, COMMAND_ANY, "virt2phys <virtual address>");
-
-	return ERROR_OK;
-}
-
-int target_arch_state(struct target_s *target)
-{
-	int retval;
-	if (target==NULL)
-	{
-		USER("No target has been configured");
-		return ERROR_OK;
-	}
-	
-	USER("target state: %s", target_state_strings[target->state]);
-	
-	if (target->state!=TARGET_HALTED)
-		return ERROR_OK;
-	
-	retval=target->type->arch_state(target);
-	return retval;
-}
-
-/* Single aligned words are guaranteed to use 16 or 32 bit access 
- * mode respectively, otherwise data is handled as quickly as 
- * possible
- */
-int target_write_buffer(struct target_s *target, u32 address, u32 size, u8 *buffer)
-{
-	int retval;
-	
-	DEBUG("writing buffer of %i byte at 0x%8.8x", size, address);
-	
-	if (((address % 2) == 0) && (size == 2))
-	{
-		return target->type->write_memory(target, address, 2, 1, buffer);
-	}
-	
-	/* handle unaligned head bytes */
-	if (address % 4)
-	{
-		int unaligned = 4 - (address % 4);
-		
-		if (unaligned > size)
-			unaligned = size;
-
-		if ((retval = target->type->write_memory(target, address, 1, unaligned, buffer)) != ERROR_OK)
-			return retval;
-		
-		buffer += unaligned;
-		address += unaligned;
-		size -= unaligned;
-	}
-		
-	/* handle aligned words */
-	if (size >= 4)
-	{
-		int aligned = size - (size % 4);
-	
-		/* use bulk writes above a certain limit. This may have to be changed */
-		if (aligned > 128)
-		{
-			if ((retval = target->type->bulk_write_memory(target, address, aligned / 4, buffer)) != ERROR_OK)
-				return retval;
-		}
-		else
-		{
-			if ((retval = target->type->write_memory(target, address, 4, aligned / 4, buffer)) != ERROR_OK)
-				return retval;
-		}
-		
-		buffer += aligned;
-		address += aligned;
-		size -= aligned;
-	}
-	
-	/* handle tail writes of less than 4 bytes */
-	if (size > 0)
-	{
-		if ((retval = target->type->write_memory(target, address, 1, size, buffer)) != ERROR_OK)
-			return retval;
-	}
-	
-	return ERROR_OK;
-}
-
-
-/* Single aligned words are guaranteed to use 16 or 32 bit access 
- * mode respectively, otherwise data is handled as quickly as 
- * possible
- */
-int target_read_buffer(struct target_s *target, u32 address, u32 size, u8 *buffer)
-{
-	int retval;
-	
-	DEBUG("reading buffer of %i byte at 0x%8.8x", size, address);
-	
-	if (((address % 2) == 0) && (size == 2))
-	{
-		return target->type->read_memory(target, address, 2, 1, buffer);
-	}
-	
-	/* handle unaligned head bytes */
-	if (address % 4)
-	{
-		int unaligned = 4 - (address % 4);
-		
-		if (unaligned > size)
-			unaligned = size;
-
-		if ((retval = target->type->read_memory(target, address, 1, unaligned, buffer)) != ERROR_OK)
-			return retval;
-		
-		buffer += unaligned;
-		address += unaligned;
-		size -= unaligned;
-	}
-		
-	/* handle aligned words */
-	if (size >= 4)
-	{
-		int aligned = size - (size % 4);
-	
-		if ((retval = target->type->read_memory(target, address, 4, aligned / 4, buffer)) != ERROR_OK)
-			return retval;
-		
-		buffer += aligned;
-		address += aligned;
-		size -= aligned;
-	}
-	
-	/* handle tail writes of less than 4 bytes */
-	if (size > 0)
-	{
-		if ((retval = target->type->read_memory(target, address, 1, size, buffer)) != ERROR_OK)
-			return retval;
-	}
-	
-	return ERROR_OK;
-}
-
-int target_checksum_memory(struct target_s *target, u32 address, u32 size, u32* crc)
-{
-	u8 *buffer;
-	int retval;
-	int i;
-	u32 checksum = 0;
-	
-	if ((retval = target->type->checksum_memory(target, address,
-		size, &checksum)) == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
-	{
-		buffer = malloc(size);
-		if (buffer == NULL)
-		{
-			ERROR("error allocating buffer for section (%d bytes)", size);
-			return ERROR_INVALID_ARGUMENTS;
-		}
-		retval = target_read_buffer(target, address, size, buffer);
-		if (retval != ERROR_OK)
-		{
-			free(buffer);
-			return retval;
-		}
-
-		/* convert to target endianess */
-		for (i = 0; i < (size/sizeof(u32)); i++)
-		{
-			u32 target_data;
-			target_data = target_buffer_get_u32(target, &buffer[i*sizeof(u32)]);
-			target_buffer_set_u32(target, &buffer[i*sizeof(u32)], target_data);
-		}
-
-		retval = image_calculate_checksum( buffer, size, &checksum );
-		free(buffer);
-	}
-	
-	*crc = checksum;
-	
-	return retval;
-}
-
-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);
-	
-	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);
-	}
-	
-	return retval;
-}
-
-int target_read_u16(struct target_s *target, u32 address, u16 *value)
-{
-	u8 value_buf[2];
-	
-	int retval = target->type->read_memory(target, address, 2, 1, value_buf);
-	
-	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;
-}
-
-int target_read_u8(struct target_s *target, u32 address, u8 *value)
-{
-	int retval = target->type->read_memory(target, address, 1, 1, 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;
-}
-
-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);	
-	if ((retval = target->type->write_memory(target, address, 4, 1, value_buf)) != ERROR_OK)
-	{
-		DEBUG("failed: %i", retval);
-	}
-	
-	return retval;
-}
-
-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);	
-	if ((retval = target->type->write_memory(target, address, 2, 1, value_buf)) != ERROR_OK)
-	{
-		DEBUG("failed: %i", retval);
-	}
-	
-	return retval;
-}
-
-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);
-
-	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)
-{
-	register_command(cmd_ctx,  NULL, "reg", handle_reg_command, COMMAND_EXEC, NULL);
-	register_command(cmd_ctx,  NULL, "poll", handle_poll_command, COMMAND_EXEC, "poll target state");
-	register_command(cmd_ctx,  NULL, "wait_halt", handle_wait_halt_command, COMMAND_EXEC, "wait for target halt [time (s)]");
-	register_command(cmd_ctx,  NULL, "halt", handle_halt_command, COMMAND_EXEC, "halt target");
-	register_command(cmd_ctx,  NULL, "resume", handle_resume_command, COMMAND_EXEC, "resume target [addr]");
-	register_command(cmd_ctx,  NULL, "step", handle_step_command, COMMAND_EXEC, "step one instruction from current PC or [addr]");
-	register_command(cmd_ctx,  NULL, "reset", handle_reset_command, COMMAND_EXEC, "reset target [run|halt|init|run_and_halt|run_and_init]");
-	register_command(cmd_ctx,  NULL, "soft_reset_halt", handle_soft_reset_halt_command, COMMAND_EXEC, "halt the target and do a soft reset");
-
-	register_command(cmd_ctx,  NULL, "mdw", handle_md_command, COMMAND_EXEC, "display memory words <addr> [count]");
-	register_command(cmd_ctx,  NULL, "mdh", handle_md_command, COMMAND_EXEC, "display memory half-words <addr> [count]");
-	register_command(cmd_ctx,  NULL, "mdb", handle_md_command, COMMAND_EXEC, "display memory bytes <addr> [count]");
-	
-	register_command(cmd_ctx,  NULL, "mww", handle_mw_command, COMMAND_EXEC, "write memory word <addr> <value>");
-	register_command(cmd_ctx,  NULL, "mwh", handle_mw_command, COMMAND_EXEC, "write memory half-word <addr> <value>");
-	register_command(cmd_ctx,  NULL, "mwb", handle_mw_command, COMMAND_EXEC, "write memory byte <addr> <value>");
-	
-	register_command(cmd_ctx,  NULL, "bp", handle_bp_command, COMMAND_EXEC, "set breakpoint <address> <length> [hw]");	
-	register_command(cmd_ctx,  NULL, "rbp", handle_rbp_command, COMMAND_EXEC, "remove breakpoint <adress>");
-	register_command(cmd_ctx,  NULL, "wp", handle_wp_command, COMMAND_EXEC, "set watchpoint <address> <length> <r/w/a> [value] [mask]");	
-	register_command(cmd_ctx,  NULL, "rwp", handle_rwp_command, COMMAND_EXEC, "remove watchpoint <adress>");
-	
-	register_command(cmd_ctx,  NULL, "load_image", handle_load_image_command, COMMAND_EXEC, "load_image <file> <address> ['bin'|'ihex'|'elf'|'s19']");
-	register_command(cmd_ctx,  NULL, "dump_image", handle_dump_image_command, COMMAND_EXEC, "dump_image <file> <address> <size>");
-	register_command(cmd_ctx,  NULL, "verify_image", handle_verify_image_command, COMMAND_EXEC, "verify_image <file> [offset] [type]");
-	register_command(cmd_ctx,  NULL, "load_binary", handle_load_image_command, COMMAND_EXEC, "[DEPRECATED] load_binary <file> <address>");
-	register_command(cmd_ctx,  NULL, "dump_binary", handle_dump_image_command, COMMAND_EXEC, "[DEPRECATED] dump_binary <file> <address> <size>");
-	
-	target_request_register_commands(cmd_ctx);
-	trace_register_commands(cmd_ctx);
-	
-	return ERROR_OK;
-}
-
-int handle_targets_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	target_t *target = targets;
-	int count = 0;
-	
-	if (argc == 1)
-	{
-		int num = strtoul(args[0], NULL, 0);
-		
-		while (target)
-		{
-			count++;
-			target = target->next;
-		}
-		
-		if (num < count)
-			cmd_ctx->current_target = num;
-		else
-			command_print(cmd_ctx, "%i is out of bounds, only %i targets are configured", num, count);
-			
-		return ERROR_OK;
-	}
-		
-	while (target)
-	{
-		command_print(cmd_ctx, "%i: %s (%s), state: %s", count++, target->type->name, target_endianess_strings[target->endianness], target_state_strings[target->state]);
-		target = target->next;
-	}
-	
-	return ERROR_OK;
-}
-
-int handle_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	int i;
-	int found = 0;
-	
-	if (argc < 3)
-	{
-		ERROR("target command requires at least three arguments: <type> <endianess> <reset_mode>");
-		exit(-1);
-	}
-	
-	/* search for the specified target */
-	if (args[0] && (args[0][0] != 0))
-	{
-		for (i = 0; target_types[i]; i++)
-		{
-			if (strcmp(args[0], target_types[i]->name) == 0)
-			{
-				target_t **last_target_p = &targets;
-				
-				/* register target specific commands */
-				if (target_types[i]->register_commands(cmd_ctx) != ERROR_OK)
-				{
-					ERROR("couldn't register '%s' commands", args[0]);
-					exit(-1);
-				}
-
-				if (*last_target_p)
-				{
-					while ((*last_target_p)->next)
-						last_target_p = &((*last_target_p)->next);
-					last_target_p = &((*last_target_p)->next);
-				}
-
-				*last_target_p = malloc(sizeof(target_t));
-				
-				(*last_target_p)->type = target_types[i];
-				
-				if (strcmp(args[1], "big") == 0)
-					(*last_target_p)->endianness = TARGET_BIG_ENDIAN;
-				else if (strcmp(args[1], "little") == 0)
-					(*last_target_p)->endianness = TARGET_LITTLE_ENDIAN;
-				else
-				{
-					ERROR("endianness must be either 'little' or 'big', not '%s'", args[1]);
-					exit(-1);
-				}
-				
-				/* what to do on a target reset */
-				if (strcmp(args[2], "reset_halt") == 0)
-					(*last_target_p)->reset_mode = RESET_HALT;
-				else if (strcmp(args[2], "reset_run") == 0)
-					(*last_target_p)->reset_mode = RESET_RUN;
-				else if (strcmp(args[2], "reset_init") == 0)
-					(*last_target_p)->reset_mode = RESET_INIT;
-				else if (strcmp(args[2], "run_and_halt") == 0)
-					(*last_target_p)->reset_mode = RESET_RUN_AND_HALT;
-				else if (strcmp(args[2], "run_and_init") == 0)
-					(*last_target_p)->reset_mode = RESET_RUN_AND_INIT;
-				else
-				{
-					ERROR("unknown target startup mode %s", args[2]);
-					exit(-1);
-				}
-				(*last_target_p)->run_and_halt_time = 1000; /* default 1s */
-				
-				(*last_target_p)->reset_script = NULL;
-				(*last_target_p)->post_halt_script = NULL;
-				(*last_target_p)->pre_resume_script = NULL;
-				(*last_target_p)->gdb_program_script = NULL;
-				
-				(*last_target_p)->working_area = 0x0;
-				(*last_target_p)->working_area_size = 0x0;
-				(*last_target_p)->working_areas = NULL;
-				(*last_target_p)->backup_working_area = 0;
-				
-				(*last_target_p)->state = TARGET_UNKNOWN;
-				(*last_target_p)->reg_cache = NULL;
-				(*last_target_p)->breakpoints = NULL;
-				(*last_target_p)->watchpoints = NULL;
-				(*last_target_p)->next = NULL;
-				(*last_target_p)->arch_info = NULL;
-				
-				/* initialize trace information */
-				(*last_target_p)->trace_info = malloc(sizeof(trace_t));
-				(*last_target_p)->trace_info->num_trace_points = 0;
-				(*last_target_p)->trace_info->trace_points_size = 0;
-				(*last_target_p)->trace_info->trace_points = NULL;
-				(*last_target_p)->trace_info->trace_history_size = 0;
-				(*last_target_p)->trace_info->trace_history = NULL;
-				(*last_target_p)->trace_info->trace_history_pos = 0;
-				(*last_target_p)->trace_info->trace_history_overflowed = 0;
-				
-				(*last_target_p)->dbgmsg = NULL;
-				(*last_target_p)->dbg_msg_enabled = 0;
-								
-				(*last_target_p)->type->target_command(cmd_ctx, cmd, args, argc, *last_target_p);
-				
-				found = 1;
-				break;
-			}
-		}
-	}
-	
-	/* no matching target found */
-	if (!found)
-	{
-		ERROR("target '%s' not found", args[0]);
-		exit(-1);
-	}
-
-	return ERROR_OK;
-}
-
-/* usage: target_script <target#> <event> <script_file> */
-int handle_target_script_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	target_t *target = NULL;
-	
-	if (argc < 3)
-	{
-		ERROR("incomplete target_script command");
-		exit(-1);
-	}
-	
-	target = get_target_by_num(strtoul(args[0], NULL, 0));
-	
-	if (!target)
-	{
-		ERROR("target number '%s' not defined", args[0]);
-		exit(-1);
-	}
-	
-	if (strcmp(args[1], "reset") == 0)
-	{
-		if (target->reset_script)
-			free(target->reset_script);
-		target->reset_script = strdup(args[2]);
-	}
-	else if (strcmp(args[1], "post_halt") == 0)
-	{
-		if (target->post_halt_script)
-			free(target->post_halt_script);
-		target->post_halt_script = strdup(args[2]);
-	}
-	else if (strcmp(args[1], "pre_resume") == 0)
-	{
-		if (target->pre_resume_script)
-			free(target->pre_resume_script);
-		target->pre_resume_script = strdup(args[2]);
-	}
-	else if (strcmp(args[1], "gdb_program_config") == 0)
-	{
-		if (target->gdb_program_script)
-			free(target->gdb_program_script);
-		target->gdb_program_script = strdup(args[2]);
-	}
-	else
-	{
-		ERROR("unknown event type: '%s", args[1]);
-		exit(-1);	
-	}
-	
-	return ERROR_OK;
-}
-
-int handle_run_and_halt_time_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	target_t *target = NULL;
-	
-	if (argc < 2)
-	{
-		ERROR("incomplete run_and_halt_time command");
-		exit(-1);
-	}
-	
-	target = get_target_by_num(strtoul(args[0], NULL, 0));
-	
-	if (!target)
-	{
-		ERROR("target number '%s' not defined", args[0]);
-		exit(-1);
-	}
-	
-	target->run_and_halt_time = strtoul(args[1], NULL, 0);
-	
-	return ERROR_OK;
-}
-
-int handle_working_area_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	target_t *target = NULL;
-	
-	if ((argc < 4) || (argc > 5))
-	{
-		return ERROR_COMMAND_SYNTAX_ERROR;
-	}
-	
-	target = get_target_by_num(strtoul(args[0], NULL, 0));
-	
-	if (!target)
-	{
-		ERROR("target number '%s' not defined", args[0]);
-		exit(-1);
-	}
-	target_free_all_working_areas(target);
-	
-	target->working_area_phys = target->working_area_virt = strtoul(args[1], NULL, 0);
-	if (argc == 5)
-	{
-		target->working_area_virt = strtoul(args[4], NULL, 0);
-	}
-	target->working_area_size = strtoul(args[2], NULL, 0);
-	
-	if (strcmp(args[3], "backup") == 0)
-	{
-		target->backup_working_area = 1;
-	}
-	else if (strcmp(args[3], "nobackup") == 0)
-	{
-		target->backup_working_area = 0;
-	}
-	else
-	{
-		ERROR("unrecognized <backup|nobackup> argument (%s)", args[3]);
-		return ERROR_COMMAND_SYNTAX_ERROR;
-	}
-	
-	return ERROR_OK;
-}
-
-
-/* process target state changes */
-int handle_target(void *priv)
-{
-	int retval;
-	target_t *target = targets;
-	
-	while (target)
-	{
-		/* only poll if target isn't already halted */
-		if (target->state != TARGET_HALTED)
-		{
-			if (target_continous_poll)
-				if ((retval = target->type->poll(target)) != ERROR_OK)
-				{
-					ERROR("couldn't poll target(%d). It's due for a reset.", retval);
-				}
-		}
-	
-		target = target->next;
-	}
-	
-	return ERROR_OK;
-}
-
-int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	target_t *target;
-	reg_t *reg = NULL;
-	int count = 0;
-	char *value;
-	
-	DEBUG("-");
-	
-	target = get_current_target(cmd_ctx);
-	
-	/* list all available registers for the current target */
-	if (argc == 0)
-	{
-		reg_cache_t *cache = target->reg_cache;
-		
-		count = 0;
-		while(cache)
-		{
-			int i;
-			for (i = 0; i < cache->num_regs; i++)
-			{
-				value = buf_to_str(cache->reg_list[i].value, cache->reg_list[i].size, 16);
-				command_print(cmd_ctx, "(%i) %s (/%i): 0x%s (dirty: %i, valid: %i)", count++, cache->reg_list[i].name, cache->reg_list[i].size, value, cache->reg_list[i].dirty, cache->reg_list[i].valid);
-				free(value);
-			}
-			cache = cache->next;
-		}
-		
-		return ERROR_OK;
-	}
-	
-	/* access a single register by its ordinal number */
-	if ((args[0][0] >= '0') && (args[0][0] <= '9'))
-	{
-		int num = strtoul(args[0], NULL, 0);
-		reg_cache_t *cache = target->reg_cache;
-		
-		count = 0;
-		while(cache)
-		{
-			int i;
-			for (i = 0; i < cache->num_regs; i++)
-			{
-				if (count++ == num)
-				{
-					reg = &cache->reg_list[i];
-					break;
-				}
-			}
-			if (reg)
-				break;
-			cache = cache->next;
-		}
-		
-		if (!reg)
-		{
-			command_print(cmd_ctx, "%i is out of bounds, the current target has only %i registers (0 - %i)", num, count, count - 1);
-			return ERROR_OK;
-		}
-	} else /* access a single register by its name */
-	{
-		reg = register_get_by_name(target->reg_cache, args[0], 1);
-		
-		if (!reg)
-		{
-			command_print(cmd_ctx, "register %s not found in current target", args[0]);
-			return ERROR_OK;
-		}
-	}
-
-	/* display a register */
-	if ((argc == 1) || ((argc == 2) && !((args[1][0] >= '0') && (args[1][0] <= '9'))))
-	{
-		if ((argc == 2) && (strcmp(args[1], "force") == 0))
-			reg->valid = 0;
-		
-		if (reg->valid == 0)
-		{
-			reg_arch_type_t *arch_type = register_get_arch_type(reg->arch_type);
-			if (arch_type == NULL)
-			{
-				ERROR("BUG: encountered unregistered arch type");
-				return ERROR_OK;
-			}
-			arch_type->get(reg);
-		}
-		value = buf_to_str(reg->value, reg->size, 16);
-		command_print(cmd_ctx, "%s (/%i): 0x%s", reg->name, reg->size, value);
-		free(value);
-		return ERROR_OK;
-	}
-	
-	/* set register value */
-	if (argc == 2)
-	{
-		u8 *buf = malloc(CEIL(reg->size, 8));
-		str_to_buf(args[1], strlen(args[1]), buf, reg->size, 0);
-
-		reg_arch_type_t *arch_type = register_get_arch_type(reg->arch_type);
-		if (arch_type == NULL)
-		{
-			ERROR("BUG: encountered unregistered arch type");
-			return ERROR_OK;
-		}
-		
-		arch_type->set(reg, buf);
-		
-		value = buf_to_str(reg->value, reg->size, 16);
-		command_print(cmd_ctx, "%s (/%i): 0x%s", reg->name, reg->size, value);
-		free(value);
-		
-		free(buf);
-		
-		return ERROR_OK;
-	}
-	
-	command_print(cmd_ctx, "usage: reg <#|name> [value]");
-	
-	return ERROR_OK;
-}
-
-static int wait_state(struct command_context_s *cmd_ctx, char *cmd, enum target_state state, int ms);
-
-int handle_poll_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	target_t *target = get_current_target(cmd_ctx);
-
-	if (argc == 0)
-	{
-		target->type->poll(target);
-			target_arch_state(target);
-	}
-	else
-	{
-		if (strcmp(args[0], "on") == 0)
-		{
-			target_continous_poll = 1;
-		}
-		else if (strcmp(args[0], "off") == 0)
-		{
-			target_continous_poll = 0;
-		}
-		else
-		{
-			command_print(cmd_ctx, "arg is \"on\" or \"off\"");
-		}
-	}
-	
-	
-	return ERROR_OK;
-}
-
-int handle_wait_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	int ms = 5000;
-	
-	if (argc > 0)
-	{
-		char *end;
-
-		ms = strtoul(args[0], &end, 0) * 1000;
-		if (*end)
-		{
-			command_print(cmd_ctx, "usage: %s [seconds]", cmd);
-			return ERROR_OK;
-		}
-	}
-
-	return wait_state(cmd_ctx, cmd, TARGET_HALTED, ms); 
-}
-
-static void target_process_events(struct command_context_s *cmd_ctx)
-{
-	target_t *target = get_current_target(cmd_ctx);
-	target->type->poll(target);
-	target_call_timer_callbacks();
-}
-
-static int wait_state(struct command_context_s *cmd_ctx, char *cmd, enum target_state state, int ms)
-{
-	int retval;
-	struct timeval timeout, now;
-	
-	gettimeofday(&timeout, NULL);
-	timeval_add_time(&timeout, 0, ms * 1000);
-	
-	target_t *target = get_current_target(cmd_ctx);
-	for (;;)
-	{
-		if ((retval=target->type->poll(target))!=ERROR_OK)
-			return retval;
-		target_call_timer_callbacks();
-		if (target->state == state)
-		{
-			break;
-		}
-		command_print(cmd_ctx, "waiting for target %s...", target_state_strings[state]);
-		
-		gettimeofday(&now, NULL);
-		if ((now.tv_sec > timeout.tv_sec) || ((now.tv_sec == timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec)))
-		{
-			command_print(cmd_ctx, "timed out while waiting for target %s", target_state_strings[state]);
-			ERROR("timed out while waiting for target %s", target_state_strings[state]);
-			break;
-		}
-	}
-	
-	return ERROR_OK;
-}
-
-int handle_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	int retval;
-	target_t *target = get_current_target(cmd_ctx);
-
-	DEBUG("-");
-	
-	command_print(cmd_ctx, "requesting target halt...");
-
-	if ((retval = target->type->halt(target)) != ERROR_OK)
-	{	
-		switch (retval)
-		{
-			case ERROR_TARGET_ALREADY_HALTED:
-				command_print(cmd_ctx, "target already halted");
-				break;
-			case ERROR_TARGET_TIMEOUT:
-				command_print(cmd_ctx, "target timed out... shutting down");
-				return retval;
-			default:
-				command_print(cmd_ctx, "unknown error... shutting down");
-				return retval;
-		}
-	}
-	
-	return handle_wait_halt_command(cmd_ctx, cmd, args, argc);
-}
-
-/* what to do on daemon startup */
-int handle_daemon_startup_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	if (argc == 1)
-	{
-		if (strcmp(args[0], "attach") == 0)
-		{
-			startup_mode = DAEMON_ATTACH;
-			return ERROR_OK;
-		}
-		else if (strcmp(args[0], "reset") == 0)
-		{
-			startup_mode = DAEMON_RESET;
-			return ERROR_OK;
-		}
-	}
-	
-	WARNING("invalid daemon_startup configuration directive: %s", args[0]);
-	return ERROR_OK;
-
-}
-		
-int handle_soft_reset_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	target_t *target = get_current_target(cmd_ctx);
-	int retval;
-	
-	command_print(cmd_ctx, "requesting target halt and executing a soft reset");
-	
-	if ((retval = target->type->soft_reset_halt(target)) != ERROR_OK)
-	{	
-		switch (retval)
-		{
-			case ERROR_TARGET_TIMEOUT:
-				command_print(cmd_ctx, "target timed out... shutting down");
-				exit(-1);
-			default:
-				command_print(cmd_ctx, "unknown error... shutting down");
-				exit(-1);
-		}
-	}
-	
-	return ERROR_OK;
-}
-
-int handle_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	target_t *target = get_current_target(cmd_ctx);
-	enum target_reset_mode reset_mode = target->reset_mode;
-	enum target_reset_mode save = target->reset_mode;
-	
-	DEBUG("-");
-	
-	if (argc >= 1)
-	{
-		if (strcmp("run", args[0]) == 0)
-			reset_mode = RESET_RUN;
-		else if (strcmp("halt", args[0]) == 0)
-			reset_mode = RESET_HALT;
-		else if (strcmp("init", args[0]) == 0)
-			reset_mode = RESET_INIT;
-		else if (strcmp("run_and_halt", args[0]) == 0)
-		{
-			reset_mode = RESET_RUN_AND_HALT;
-			if (argc >= 2)
-			{
-				target->run_and_halt_time = strtoul(args[1], NULL, 0);
-			}
-		}
-		else if (strcmp("run_and_init", args[0]) == 0)
-		{
-			reset_mode = RESET_RUN_AND_INIT;
-			if (argc >= 2)
-			{
-				target->run_and_halt_time = strtoul(args[1], NULL, 0);
-			}
-		}
-		else
-		{
-			command_print(cmd_ctx, "usage: reset ['run', 'halt', 'init', 'run_and_halt', 'run_and_init]");
-			return ERROR_OK;
-		}
-	}
-	
-	/* temporarily modify mode of current reset target */
-	target->reset_mode = reset_mode;
-
-	/* reset *all* targets */
-	target_process_reset(cmd_ctx);
-	
-	/* Restore default reset mode for this target */
-    target->reset_mode = save;
-	
-	return ERROR_OK;
-}
-
-int handle_resume_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	int retval;
-	target_t *target = get_current_target(cmd_ctx);
-	
-	if (argc == 0)
-		retval = target->type->resume(target, 1, 0, 1, 0); /* current pc, addr = 0, handle breakpoints, not debugging */
-	else if (argc == 1)
-		retval = target->type->resume(target, 0, strtoul(args[0], NULL, 0), 1, 0); /* addr = args[0], handle breakpoints, not debugging */
-	else
-	{
-		return ERROR_COMMAND_SYNTAX_ERROR;
-	}
-
-	target_process_events(cmd_ctx);
-	
-	target_arch_state(target);
-	
-	return retval;
-}
-
-int handle_step_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	target_t *target = get_current_target(cmd_ctx);
-	
-	DEBUG("-");
-	
-	if (argc == 0)
-		target->type->step(target, 1, 0, 1); /* current pc, addr = 0, handle breakpoints */
-
-	if (argc == 1)
-		target->type->step(target, 0, strtoul(args[0], NULL, 0), 1); /* addr = args[0], handle breakpoints */
-	
-	return ERROR_OK;
-}
-
-int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	const int line_bytecnt = 32;
-	int count = 1;
-	int size = 4;
-	u32 address = 0;
-	int line_modulo;
-	int i;
-
-	char output[128];
-	int output_len;
-
-	int retval;
-
-	u8 *buffer;
-	target_t *target = get_current_target(cmd_ctx);
-
-	if (argc < 1)
-		return ERROR_OK;
-
-	if (argc == 2)
-		count = strtoul(args[1], NULL, 0);
-
-	address = strtoul(args[0], NULL, 0);
-	
-
-	switch (cmd[2])
-	{
-		case 'w':
-			size = 4; line_modulo = line_bytecnt / 4;
-			break;
-		case 'h':
-			size = 2; line_modulo = line_bytecnt / 2;
-			break;
-		case 'b':
-			size = 1; line_modulo = line_bytecnt / 1;
-			break;
-		default:
-			return ERROR_OK;
-	}
-
-	buffer = calloc(count, size);
-	retval  = target->type->read_memory(target, address, size, count, buffer);
-	if (retval != ERROR_OK)
-	{
-		switch (retval)
-		{
-			case ERROR_TARGET_UNALIGNED_ACCESS:
-				command_print(cmd_ctx, "error: address not aligned");
-				break;
-			case ERROR_TARGET_NOT_HALTED:
-				command_print(cmd_ctx, "error: target must be halted for memory accesses");
-				break;			
-			case ERROR_TARGET_DATA_ABORT:
-				command_print(cmd_ctx, "error: access caused data abort, system possibly corrupted");
-				break;
-			default:
-				command_print(cmd_ctx, "error: unknown error");
-				break;
-		}
-		return ERROR_OK;
-	}
-
-	output_len = 0;
-
-	for (i = 0; i < count; i++)
-	{
-		if (i%line_modulo == 0)
-			output_len += snprintf(output + output_len, 128 - output_len, "0x%8.8x: ", address + (i*size));
-		
-		switch (size)
-		{
-			case 4:
-				output_len += snprintf(output + output_len, 128 - output_len, "%8.8x ", target_buffer_get_u32(target, &buffer[i*4]));
-				break;
-			case 2:
-				output_len += snprintf(output + output_len, 128 - output_len, "%4.4x ", target_buffer_get_u16(target, &buffer[i*2]));
-				break;
-			case 1:
-				output_len += snprintf(output + output_len, 128 - output_len, "%2.2x ", buffer[i*1]);
-				break;
-		}
-
-		if ((i%line_modulo == line_modulo-1) || (i == count - 1))
-		{
-			command_print(cmd_ctx, output);
-			output_len = 0;
-		}
-	}
-
-	free(buffer);
-	
-	return ERROR_OK;
-}
-
-int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	u32 address = 0;
-	u32 value = 0;
-	int retval;
-	target_t *target = get_current_target(cmd_ctx);
-	u8 value_buf[4];
-
-	if (argc < 2)
-		return ERROR_OK;
-
-	address = strtoul(args[0], NULL, 0);
-	value = strtoul(args[1], NULL, 0);
-
-	switch (cmd[2])
-	{
-		case 'w':
-			target_buffer_set_u32(target, value_buf, value);
-			retval = target->type->write_memory(target, address, 4, 1, value_buf);
-			break;
-		case 'h':
-			target_buffer_set_u16(target, value_buf, value);
-			retval = target->type->write_memory(target, address, 2, 1, value_buf);
-			break;
-		case 'b':
-			value_buf[0] = value;
-			retval = target->type->write_memory(target, address, 1, 1, value_buf);
-			break;
-		default:
-			return ERROR_OK;
-	}
-
-	switch (retval)
-	{
-		case ERROR_TARGET_UNALIGNED_ACCESS:
-			command_print(cmd_ctx, "error: address not aligned");
-			break;
-		case ERROR_TARGET_DATA_ABORT:
-			command_print(cmd_ctx, "error: access caused data abort, system possibly corrupted");
-			break;
-		case ERROR_TARGET_NOT_HALTED:
-			command_print(cmd_ctx, "error: target must be halted for memory accesses");
-			break;
-		case ERROR_OK:
-			break;
-		default:
-			command_print(cmd_ctx, "error: unknown error");
-			break;
-	}
-
-	return ERROR_OK;
-
-}
-
-int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	u8 *buffer;
-	u32 buf_cnt;
-	u32 image_size;
-	int i;
-	int retval;
-
-	image_t image;	
-	
-	duration_t duration;
-	char *duration_text;
-	
-	target_t *target = get_current_target(cmd_ctx);
-
-	if (argc < 1)
-	{
-		command_print(cmd_ctx, "usage: load_image <filename> [address] [type]");
-		return ERROR_OK;
-	}
-	
-	/* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */
-	if (argc >= 2)
-	{
-		image.base_address_set = 1;
-		image.base_address = strtoul(args[1], NULL, 0);
-	}
-	else
-	{
-		image.base_address_set = 0;
-	}
-	
-	image.start_address_set = 0;
-
-	duration_start_measure(&duration);
-	
-	if (image_open(&image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "load_image error: %s", image.error_str);
-		return ERROR_OK;
-	}
-	
-	image_size = 0x0;
-	for (i = 0; i < image.num_sections; i++)
-	{
-		buffer = malloc(image.sections[i].size);
-		if (buffer == NULL)
-		{
-			command_print(cmd_ctx, "error allocating buffer for section (%d bytes)", image.sections[i].size);
-			break;
-		}
-		
-		if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
-		{
-			ERROR("image_read_section failed with error code: %i", retval);
-			command_print(cmd_ctx, "image reading failed, download aborted");
-			free(buffer);
-			image_close(&image);
-			return ERROR_OK;
-		}
-		target_write_buffer(target, image.sections[i].base_address, buf_cnt, buffer);
-		image_size += buf_cnt;
-		command_print(cmd_ctx, "%u byte written at address 0x%8.8x", buf_cnt, image.sections[i].base_address);
-		
-		free(buffer);
-	}
-
-	duration_stop_measure(&duration, &duration_text);
-	command_print(cmd_ctx, "downloaded %u byte in %s", image_size, duration_text);
-	free(duration_text);
-	
-	image_close(&image);
-
-	return ERROR_OK;
-
-}
-
-int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	fileio_t fileio;
-	
-	u32 address;
-	u32 size;
-	u8 buffer[560];
-	int retval;
-	
-	duration_t duration;
-	char *duration_text;
-	
-	target_t *target = get_current_target(cmd_ctx);
-
-	if (argc != 3)
-	{
-		command_print(cmd_ctx, "usage: dump_image <filename> <address> <size>");
-		return ERROR_OK;
-	}
-
-	address = strtoul(args[1], NULL, 0);
-	size = strtoul(args[2], NULL, 0);
-
-	if ((address & 3) || (size & 3))
-	{
-		command_print(cmd_ctx, "only 32-bit aligned address and size are supported");
-		return ERROR_OK;
-	}
-	
-	if (fileio_open(&fileio, args[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "dump_image error: %s", fileio.error_str);
-		return ERROR_OK;
-	}
-	
-	duration_start_measure(&duration);
-	
-	while (size > 0)
-	{
-		u32 size_written;
-		u32 this_run_size = (size > 560) ? 560 : size;
-		
-		retval = target->type->read_memory(target, address, 4, this_run_size / 4, buffer);
-		if (retval != ERROR_OK)
-		{
-			command_print(cmd_ctx, "Reading memory failed %d", retval);
-			break;
-		}
-		
-		fileio_write(&fileio, this_run_size, buffer, &size_written);
-		
-		size -= this_run_size;
-		address += this_run_size;
-	}
-
-	fileio_close(&fileio);
-
-	duration_stop_measure(&duration, &duration_text);
-	command_print(cmd_ctx, "dumped %"PRIi64" byte in %s", fileio.size, duration_text);
-	free(duration_text);
-	
-	return ERROR_OK;
-}
-
-int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	u8 *buffer;
-	u32 buf_cnt;
-	u32 image_size;
-	int i;
-	int retval;
-	u32 checksum = 0;
-	u32 mem_checksum = 0;
-
-	image_t image;	
-	
-	duration_t duration;
-	char *duration_text;
-	
-	target_t *target = get_current_target(cmd_ctx);
-	
-	if (argc < 1)
-	{
-		command_print(cmd_ctx, "usage: verify_image <file> [offset] [type]");
-		return ERROR_OK;
-	}
-	
-	if (!target)
-	{
-		ERROR("no target selected");
-		return ERROR_OK;
-	}
-	
-	duration_start_measure(&duration);
-	
-	if (argc >= 2)
-	{
-		image.base_address_set = 1;
-		image.base_address = strtoul(args[1], NULL, 0);
-	}
-	else
-	{
-		image.base_address_set = 0;
-		image.base_address = 0x0;
-	}
-
-	image.start_address_set = 0;
-
-	if (image_open(&image, args[0], (argc == 3) ? args[2] : NULL) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "verify_image error: %s", image.error_str);
-		return ERROR_OK;
-	}
-	
-	image_size = 0x0;
-	for (i = 0; i < image.num_sections; i++)
-	{
-		buffer = malloc(image.sections[i].size);
-		if (buffer == NULL)
-		{
-			command_print(cmd_ctx, "error allocating buffer for section (%d bytes)", image.sections[i].size);
-			break;
-		}
-		if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
-		{
-			ERROR("image_read_section failed with error code: %i", retval);
-			command_print(cmd_ctx, "image reading failed, verify aborted");
-			free(buffer);
-			image_close(&image);
-			return ERROR_OK;
-		}
-		
-		/* calculate checksum of image */
-		image_calculate_checksum( buffer, buf_cnt, &checksum );
-		
-		retval = target_checksum_memory(target, image.sections[i].base_address, buf_cnt, &mem_checksum);
-		
-		if( retval != ERROR_OK )
-		{
-			command_print(cmd_ctx, "could not calculate checksum, verify aborted");
-			free(buffer);
-			image_close(&image);
-			return ERROR_OK;
-		}
-		
-		if( checksum != mem_checksum )
-		{
-			/* failed crc checksum, fall back to a binary compare */
-			u8 *data;
-			
-			command_print(cmd_ctx, "checksum mismatch - attempting binary compare");
-			
-			data = (u8*)malloc(buf_cnt);
-			
-			/* Can we use 32bit word accesses? */
-			int size = 1;
-			int count = buf_cnt;
-			if ((count % 4) == 0)
-			{
-				size *= 4;
-				count /= 4;
-			}
-			retval = target->type->read_memory(target, image.sections[i].base_address, size, count, data);
-	
-			if (retval == ERROR_OK)
-			{
-				int t;
-				for (t = 0; t < buf_cnt; t++)
-				{
-					if (data[t] != buffer[t])
-					{
-						command_print(cmd_ctx, "Verify operation failed address 0x%08x. Was 0x%02x instead of 0x%02x\n", t + image.sections[i].base_address, data[t], buffer[t]);
-						free(data);
-						free(buffer);
-						image_close(&image);
-						return ERROR_OK;
-					}
-				}
-			}
-			
-			free(data);
-		}
-		
-		free(buffer);
-		image_size += buf_cnt;
-	}
-	
-	duration_stop_measure(&duration, &duration_text);
-	command_print(cmd_ctx, "verified %u bytes in %s", image_size, duration_text);
-	free(duration_text);
-	
-	image_close(&image);
-	
-	return ERROR_OK;
-}
-
-int handle_bp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	int retval;
-	target_t *target = get_current_target(cmd_ctx);
-
-	if (argc == 0)
-	{
-		breakpoint_t *breakpoint = target->breakpoints;
-
-		while (breakpoint)
-		{
-			if (breakpoint->type == BKPT_SOFT)
-			{
-				char* buf = buf_to_str(breakpoint->orig_instr, breakpoint->length, 16);
-				command_print(cmd_ctx, "0x%8.8x, 0x%x, %i, 0x%s", breakpoint->address, breakpoint->length, breakpoint->set, buf);
-				free(buf);
-			}
-			else
-			{
-				command_print(cmd_ctx, "0x%8.8x, 0x%x, %i", breakpoint->address, breakpoint->length, breakpoint->set);
-			}
-			breakpoint = breakpoint->next;
-		}
-	}
-	else if (argc >= 2)
-	{
-		int hw = BKPT_SOFT;
-		u32 length = 0;
-
-		length = strtoul(args[1], NULL, 0);
-		
-		if (argc >= 3)
-			if (strcmp(args[2], "hw") == 0)
-				hw = BKPT_HARD;
-
-		if ((retval = breakpoint_add(target, strtoul(args[0], NULL, 0), length, hw)) != ERROR_OK)
-		{
-			switch (retval)
-			{
-				case ERROR_TARGET_NOT_HALTED:
-					command_print(cmd_ctx, "target must be halted to set breakpoints");
-					break;
-				case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
-					command_print(cmd_ctx, "no more breakpoints available");
-					break;
-				default:
-					command_print(cmd_ctx, "unknown error, breakpoint not set");
-					break;
-			}
-		}
-		else
-		{
-			command_print(cmd_ctx, "breakpoint added at address 0x%8.8x", strtoul(args[0], NULL, 0));
-		}
-	}
-	else
-	{
-		command_print(cmd_ctx, "usage: bp <address> <length> ['hw']");
-	}
-
-	return ERROR_OK;
-}
-
-int handle_rbp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	target_t *target = get_current_target(cmd_ctx);
-
-	if (argc > 0)
-		breakpoint_remove(target, strtoul(args[0], NULL, 0));
-
-	return ERROR_OK;
-}
-
-int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	target_t *target = get_current_target(cmd_ctx);
-	int retval;
-
-	if (argc == 0)
-	{
-		watchpoint_t *watchpoint = target->watchpoints;
-
-		while (watchpoint)
-		{
-			command_print(cmd_ctx, "address: 0x%8.8x, mask: 0x%8.8x, r/w/a: %i, value: 0x%8.8x, mask: 0x%8.8x", watchpoint->address, watchpoint->length, watchpoint->rw, watchpoint->value, watchpoint->mask);
-			watchpoint = watchpoint->next;
-		}
-	} 
-	else if (argc >= 2)
-	{
-		enum watchpoint_rw type = WPT_ACCESS;
-		u32 data_value = 0x0;
-		u32 data_mask = 0xffffffff;
-		
-		if (argc >= 3)
-		{
-			switch(args[2][0])
-			{
-				case 'r':
-					type = WPT_READ;
-					break;
-				case 'w':
-					type = WPT_WRITE;
-					break;
-				case 'a':
-					type = WPT_ACCESS;
-					break;
-				default:
-					command_print(cmd_ctx, "usage: wp <address> <length> [r/w/a] [value] [mask]");
-					return ERROR_OK;
-			}
-		}
-		if (argc >= 4)
-		{
-			data_value = strtoul(args[3], NULL, 0);
-		}
-		if (argc >= 5)
-		{
-			data_mask = strtoul(args[4], NULL, 0);
-		}
-		
-		if ((retval = watchpoint_add(target, strtoul(args[0], NULL, 0),
-				strtoul(args[1], NULL, 0), type, data_value, data_mask)) != ERROR_OK)
-		{
-			switch (retval)
-			{
-				case ERROR_TARGET_NOT_HALTED:
-					command_print(cmd_ctx, "target must be halted to set watchpoints");
-					break;
-				case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
-					command_print(cmd_ctx, "no more watchpoints available");
-					break;
-				default:
-					command_print(cmd_ctx, "unknown error, watchpoint not set");
-					break;
-			}	
-		}
-	}
-	else
-	{
-		command_print(cmd_ctx, "usage: wp <address> <length> [r/w/a] [value] [mask]");
-	}
-		
-	return ERROR_OK;
-}
-
-int handle_rwp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	target_t *target = get_current_target(cmd_ctx);
-
-	if (argc > 0)
-		watchpoint_remove(target, strtoul(args[0], NULL, 0));
-	
-	return ERROR_OK;
-}
-
-int handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)
-{
-	int retval;
-	target_t *target = get_current_target(cmd_ctx);
-	u32 va;
-	u32 pa;
-
-	if (argc != 1)
-	{
-		return ERROR_COMMAND_SYNTAX_ERROR;
-	}
-	va = strtoul(args[0], NULL, 0);
-
-	retval = target->type->virt2phys(target, va, &pa);
-	if (retval == ERROR_OK)
-	{
-		command_print(cmd_ctx, "Physical address 0x%08x", pa);
-	}
-	else
-	{
-		/* lower levels will have logged a detailed error which is 
-		 * forwarded to telnet/GDB session.  
-		 */
-	}
-	return retval;
-}
+/***************************************************************************
+ *   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.             *
+ ***************************************************************************/
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "replacements.h"
+#include "target.h"
+#include "target_request.h"
+
+#include "log.h"
+#include "configuration.h"
+#include "binarybuffer.h"
+#include "jtag.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <inttypes.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <sys/time.h>
+#include <time.h>
+
+#include <time_support.h>
+
+#include <fileio.h>
+#include <image.h>
+
+int cli_target_callback_event_handler(struct target_s *target, enum target_event event, void *priv);
+
+
+int handle_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_daemon_startup_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_targets_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+int handle_target_script_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_run_and_halt_time_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_working_area_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+
+int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_poll_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_wait_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_soft_reset_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_resume_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_step_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_bp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_rbp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_rwp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
+int handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc);
+
+/* targets
+ */
+extern target_type_t arm7tdmi_target;
+extern target_type_t arm720t_target;
+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 feroceon_target;
+extern target_type_t xscale_target;
+extern target_type_t cortexm3_target;
+
+target_type_t *target_types[] =
+{
+	&arm7tdmi_target,
+	&arm9tdmi_target,
+	&arm920t_target,
+	&arm720t_target,
+	&arm966e_target,
+	&arm926ejs_target,
+	&feroceon_target,
+	&xscale_target,
+	&cortexm3_target,
+	NULL,
+};
+
+target_t *targets = NULL;
+target_event_callback_t *target_event_callbacks = NULL;
+target_timer_callback_t *target_timer_callbacks = NULL;
+
+char *target_state_strings[] =
+{
+	"unknown",
+	"running",
+	"halted",
+	"reset",
+	"debug_running",
+};
+
+char *target_debug_reason_strings[] =
+{
+	"debug request", "breakpoint", "watchpoint",
+	"watchpoint and breakpoint", "single step",
+	"target not halted"
+};
+
+char *target_endianess_strings[] =
+{
+	"big endian",
+	"little endian",
+};
+
+enum daemon_startup_mode startup_mode = DAEMON_ATTACH;
+
+static int target_continous_poll = 1;
+
+/* read a u32 from a buffer in target memory endianness */
+u32 target_buffer_get_u32(target_t *target, u8 *buffer)
+{
+	if (target->endianness == TARGET_LITTLE_ENDIAN)
+		return le_to_h_u32(buffer);
+	else
+		return be_to_h_u32(buffer);
+}
+
+/* read a u16 from a buffer in target memory endianness */
+u16 target_buffer_get_u16(target_t *target, u8 *buffer)
+{
+	if (target->endianness == TARGET_LITTLE_ENDIAN)
+		return le_to_h_u16(buffer);
+	else
+		return be_to_h_u16(buffer);
+}
+
+/* write a u32 to a buffer in target memory endianness */
+void target_buffer_set_u32(target_t *target, u8 *buffer, u32 value)
+{
+	if (target->endianness == TARGET_LITTLE_ENDIAN)
+		h_u32_to_le(buffer, value);
+	else
+		h_u32_to_be(buffer, value);
+}
+
+/* write a u16 to a buffer in target memory endianness */
+void target_buffer_set_u16(target_t *target, u8 *buffer, u16 value)
+{
+	if (target->endianness == TARGET_LITTLE_ENDIAN)
+		h_u16_to_le(buffer, value);
+	else
+		h_u16_to_be(buffer, value);
+}
+
+/* returns a pointer to the n-th configured target */
+target_t* get_target_by_num(int num)
+{
+	target_t *target = targets;
+	int i = 0;
+
+	while (target)
+	{
+		if (num == i)
+			return target;
+		target = target->next;
+		i++;
+	}
+
+	return NULL;
+}
+
+int get_num_by_target(target_t *query_target)
+{
+	target_t *target = targets;
+	int i = 0;	
+	
+	while (target)
+	{
+		if (target == query_target)
+			return i;
+		target = target->next;
+		i++;
+	}
+	
+	return -1;
+}
+
+target_t* get_current_target(command_context_t *cmd_ctx)
+{
+	target_t *target = get_target_by_num(cmd_ctx->current_target);
+	
+	if (target == NULL)
+	{
+		ERROR("BUG: current_target out of bounds");
+		exit(-1);
+	}
+	
+	return target;
+}
+
+/* Process target initialization, when target entered debug out of reset
+ * the handler is unregistered at the end of this function, so it's only called once
+ */
+int target_init_handler(struct target_s *target, enum target_event event, void *priv)
+{
+	FILE *script;
+	struct command_context_s *cmd_ctx = priv;
+	
+	if ((event == TARGET_EVENT_HALTED) && (target->reset_script))
+	{
+		target_unregister_event_callback(target_init_handler, priv);
+
+		script = open_file_from_path(cmd_ctx, target->reset_script, "r");
+		if (!script)
+		{
+			ERROR("couldn't open script file %s", target->reset_script);
+				return ERROR_OK;
+		}
+
+		INFO("executing reset script '%s'", target->reset_script);
+		command_run_file(cmd_ctx, script, COMMAND_EXEC);
+		fclose(script);
+
+		jtag_execute_queue();
+	}
+	
+	return ERROR_OK;
+}
+
+int target_run_and_halt_handler(void *priv)
+{
+	target_t *target = priv;
+	
+	target->type->halt(target);
+	
+	return ERROR_OK;
+}
+
+int target_process_reset(struct command_context_s *cmd_ctx)
+{
+	int retval = ERROR_OK;
+	target_t *target;
+	struct timeval timeout, now;
+	
+	/* prepare reset_halt where necessary */
+	target = targets;
+	while (target)
+	{
+		if (jtag_reset_config & RESET_SRST_PULLS_TRST)
+		{
+			switch (target->reset_mode)
+			{
+				case RESET_HALT:
+					command_print(cmd_ctx, "nSRST pulls nTRST, falling back to RESET_RUN_AND_HALT");
+					target->reset_mode = RESET_RUN_AND_HALT;
+					break;
+				case RESET_INIT:
+					command_print(cmd_ctx, "nSRST pulls nTRST, falling back to RESET_RUN_AND_INIT");
+					target->reset_mode = RESET_RUN_AND_INIT;
+					break;
+				default:
+					break;
+			} 
+		}
+		switch (target->reset_mode)
+		{
+			case RESET_HALT:
+			case RESET_INIT:
+				target->type->prepare_reset_halt(target);
+				break;
+			default:
+				break;
+		}
+		target = target->next;
+	}
+	
+	target = targets;
+	while (target)
+	{
+		target->type->assert_reset(target);
+		target = target->next;
+	}
+	jtag_execute_queue();
+	
+	/* request target halt if necessary, and schedule further action */
+	target = targets;
+	while (target)
+	{
+		switch (target->reset_mode)
+		{
+			case RESET_RUN:
+				/* nothing to do if target just wants to be run */
+				break;
+			case RESET_RUN_AND_HALT:
+				/* schedule halt */
+				target_register_timer_callback(target_run_and_halt_handler, target->run_and_halt_time, 0, target);
+				break;
+			case RESET_RUN_AND_INIT:
+				/* schedule halt */
+				target_register_timer_callback(target_run_and_halt_handler, target->run_and_halt_time, 0, target);
+				target_register_event_callback(target_init_handler, cmd_ctx);
+				break;
+			case RESET_HALT:
+				target->type->halt(target);
+				break;
+			case RESET_INIT:
+				target->type->halt(target);
+				target_register_event_callback(target_init_handler, cmd_ctx);
+				break;
+			default:
+				ERROR("BUG: unknown target->reset_mode");
+		}
+		target = target->next;
+	}
+	
+	target = targets;
+	while (target)
+	{
+		target->type->deassert_reset(target);
+		target = target->next;
+	}
+	jtag_execute_queue();
+
+	/* Wait for reset to complete, maximum 5 seconds. */	
+	gettimeofday(&timeout, NULL);
+	timeval_add_time(&timeout, 5, 0);
+	for(;;)
+	{
+		gettimeofday(&now, NULL);
+		
+		target_call_timer_callbacks();
+		
+		target = targets;
+		while (target)
+		{
+			target->type->poll(target);
+			if ((target->reset_mode == RESET_RUN_AND_INIT) || (target->reset_mode == RESET_RUN_AND_HALT))
+			{
+				if (target->state != TARGET_HALTED)
+				{
+					if ((now.tv_sec > timeout.tv_sec) || ((now.tv_sec == timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec)))
+					{
+						command_print(cmd_ctx, "Timed out waiting for reset");
+						goto done;
+					}
+					usleep(100*1000); /* Do not eat all cpu */
+					goto again;
+				}
+			}
+			target = target->next;
+		}
+		/* All targets we're waiting for are halted */
+		break;
+		
+		again:;
+	}
+	done:
+	
+	
+	/* We want any events to be processed before the prompt */
+	target_call_timer_callbacks();
+	
+	return retval;
+}
+
+static int default_virt2phys(struct target_s *target, u32 virtual, u32 *physical)
+{
+	*physical = virtual;
+	return ERROR_OK;
+}
+
+static int default_mmu(struct target_s *target, int *enabled)
+{
+	*enabled = 0;
+	return ERROR_OK;
+}
+
+int target_init(struct command_context_s *cmd_ctx)
+{
+	target_t *target = targets;
+	
+	while (target)
+	{
+		if (target->type->init_target(cmd_ctx, target) != ERROR_OK)
+		{
+			ERROR("target '%s' init failed", target->type->name);
+			exit(-1);
+		}
+		
+		/* Set up default functions if none are provided by target */
+		if (target->type->virt2phys == NULL)
+		{
+			target->type->virt2phys = default_virt2phys;
+		}
+		if (target->type->mmu == NULL)
+		{
+			target->type->mmu = default_mmu;
+		}
+		target = target->next;
+	}
+	
+	if (targets)
+	{
+		target_register_user_commands(cmd_ctx);
+		target_register_timer_callback(handle_target, 100, 1, NULL);
+	}
+		
+	return ERROR_OK;
+}
+
+int target_init_reset(struct command_context_s *cmd_ctx)
+{
+	if (startup_mode == DAEMON_RESET)
+		target_process_reset(cmd_ctx);
+	
+	return ERROR_OK;
+}
+
+int target_register_event_callback(int (*callback)(struct target_s *target, enum target_event event, void *priv), void *priv)
+{
+	target_event_callback_t **callbacks_p = &target_event_callbacks;
+	
+	if (callback == NULL)
+	{
+		return ERROR_INVALID_ARGUMENTS;
+	}
+	
+	if (*callbacks_p)
+	{
+		while ((*callbacks_p)->next)
+			callbacks_p = &((*callbacks_p)->next);
+		callbacks_p = &((*callbacks_p)->next);
+	}
+	
+	(*callbacks_p) = malloc(sizeof(target_event_callback_t));
+	(*callbacks_p)->callback = callback;
+	(*callbacks_p)->priv = priv;
+	(*callbacks_p)->next = NULL;
+	
+	return ERROR_OK;
+}
+
+int target_register_timer_callback(int (*callback)(void *priv), int time_ms, int periodic, void *priv)
+{
+	target_timer_callback_t **callbacks_p = &target_timer_callbacks;
+	struct timeval now;
+	
+	if (callback == NULL)
+	{
+		return ERROR_INVALID_ARGUMENTS;
+	}
+	
+	if (*callbacks_p)
+	{
+		while ((*callbacks_p)->next)
+			callbacks_p = &((*callbacks_p)->next);
+		callbacks_p = &((*callbacks_p)->next);
+	}
+	
+	(*callbacks_p) = malloc(sizeof(target_timer_callback_t));
+	(*callbacks_p)->callback = callback;
+	(*callbacks_p)->periodic = periodic;
+	(*callbacks_p)->time_ms = time_ms;
+	
+	gettimeofday(&now, NULL);
+	(*callbacks_p)->when.tv_usec = now.tv_usec + (time_ms % 1000) * 1000;
+	time_ms -= (time_ms % 1000);
+	(*callbacks_p)->when.tv_sec = now.tv_sec + (time_ms / 1000);
+	if ((*callbacks_p)->when.tv_usec > 1000000)
+	{
+		(*callbacks_p)->when.tv_usec = (*callbacks_p)->when.tv_usec - 1000000;
+		(*callbacks_p)->when.tv_sec += 1;
+	}
+	
+	(*callbacks_p)->priv = priv;
+	(*callbacks_p)->next = NULL;
+	
+	return ERROR_OK;
+}
+
+int target_unregister_event_callback(int (*callback)(struct target_s *target, enum target_event event, void *priv), void *priv)
+{
+	target_event_callback_t **p = &target_event_callbacks;
+	target_event_callback_t *c = target_event_callbacks;
+	
+	if (callback == NULL)
+	{
+		return ERROR_INVALID_ARGUMENTS;
+	}
+		
+	while (c)
+	{
+		target_event_callback_t *next = c->next;
+		if ((c->callback == callback) && (c->priv == priv))
+		{
+			*p = next;
+			free(c);
+			return ERROR_OK;
+		}
+		else
+			p = &(c->next);
+		c = next;
+	}
+	
+	return ERROR_OK;
+}
+
+int target_unregister_timer_callback(int (*callback)(void *priv), void *priv)
+{
+	target_timer_callback_t **p = &target_timer_callbacks;
+	target_timer_callback_t *c = target_timer_callbacks;
+	
+	if (callback == NULL)
+	{
+		return ERROR_INVALID_ARGUMENTS;
+	}
+		
+	while (c)
+	{
+		target_timer_callback_t *next = c->next;
+		if ((c->callback == callback) && (c->priv == priv))
+		{
+			*p = next;
+			free(c);
+			return ERROR_OK;
+		}
+		else
+			p = &(c->next);
+		c = next;
+	}
+	
+	return ERROR_OK;
+}
+
+int target_call_event_callbacks(target_t *target, enum target_event event)
+{
+	target_event_callback_t *callback = target_event_callbacks;
+	target_event_callback_t *next_callback;
+	
+	DEBUG("target event %i", event);
+	
+	while (callback)
+	{
+		next_callback = callback->next;
+		callback->callback(target, event, callback->priv);
+		callback = next_callback;
+	}
+	
+	return ERROR_OK;
+}
+
+int target_call_timer_callbacks()
+{
+	target_timer_callback_t *callback = target_timer_callbacks;
+	target_timer_callback_t *next_callback;
+	struct timeval now;
+
+	gettimeofday(&now, NULL);
+	
+	while (callback)
+	{
+		next_callback = callback->next;
+		
+		if (((now.tv_sec >= callback->when.tv_sec) && (now.tv_usec >= callback->when.tv_usec))
+			|| (now.tv_sec > callback->when.tv_sec))
+		{
+			callback->callback(callback->priv);
+			if (callback->periodic)
+			{
+				int time_ms = callback->time_ms;
+				callback->when.tv_usec = now.tv_usec + (time_ms % 1000) * 1000;
+				time_ms -= (time_ms % 1000);
+				callback->when.tv_sec = now.tv_sec + time_ms / 1000;
+				if (callback->when.tv_usec > 1000000)
+				{
+					callback->when.tv_usec = callback->when.tv_usec - 1000000;
+					callback->when.tv_sec += 1;
+				}
+			}
+			else
+				target_unregister_timer_callback(callback->callback, callback->priv);
+		}
+			
+		callback = next_callback;
+	}
+	
+	return ERROR_OK;
+}
+
+int target_alloc_working_area(struct target_s *target, u32 size, working_area_t **area)
+{
+	working_area_t *c = target->working_areas;
+	working_area_t *new_wa = NULL;
+	
+	/* Reevaluate working area address based on MMU state*/
+	if (target->working_areas == NULL)
+	{
+		int retval;
+		int enabled;
+		retval = target->type->mmu(target, &enabled);
+		if (retval != ERROR_OK)
+		{
+			return retval;
+		}
+		if (enabled)
+		{
+			target->working_area = target->working_area_virt;
+		}
+		else
+		{
+			target->working_area = target->working_area_phys;
+		}
+	}
+	
+	/* only allocate multiples of 4 byte */
+	if (size % 4)
+	{
+		ERROR("BUG: code tried to allocate unaligned number of bytes, padding");
+		size = CEIL(size, 4);
+	}
+	
+	/* see if there's already a matching working area */
+	while (c)
+	{
+		if ((c->free) && (c->size == size))
+		{
+			new_wa = c;
+			break;
+		}
+		c = c->next;
+	}
+	
+	/* if not, allocate a new one */
+	if (!new_wa)
+	{
+		working_area_t **p = &target->working_areas;
+		u32 first_free = target->working_area;
+		u32 free_size = target->working_area_size;
+		
+		DEBUG("allocating new working area");
+		
+		c = target->working_areas;
+		while (c)
+		{
+			first_free += c->size;
+			free_size -= c->size;
+			p = &c->next;
+			c = c->next;
+		}
+		
+		if (free_size < size)
+		{
+			WARNING("not enough working area available(requested %d, free %d)", size, free_size);
+			return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+		}
+		
+		new_wa = malloc(sizeof(working_area_t));
+		new_wa->next = NULL;
+		new_wa->size = size;
+		new_wa->address = first_free;
+		
+		if (target->backup_working_area)
+		{
+			new_wa->backup = malloc(new_wa->size);
+			target->type->read_memory(target, new_wa->address, 4, new_wa->size / 4, new_wa->backup);
+		}
+		else
+		{
+			new_wa->backup = NULL;
+		}
+		
+		/* put new entry in list */
+		*p = new_wa;
+	}
+	
+	/* mark as used, and return the new (reused) area */
+	new_wa->free = 0;
+	*area = new_wa;
+	
+	/* user pointer */
+	new_wa->user = area;
+	
+	return ERROR_OK;
+}
+
+int target_free_working_area(struct target_s *target, working_area_t *area)
+{
+	if (area->free)
+		return ERROR_OK;
+	
+	if (target->backup_working_area)
+		target->type->write_memory(target, area->address, 4, area->size / 4, area->backup);
+	
+	area->free = 1;
+	
+	/* mark user pointer invalid */
+	*area->user = NULL;
+	area->user = NULL;
+	
+	return ERROR_OK;
+}
+
+int target_free_all_working_areas(struct target_s *target)
+{
+	working_area_t *c = target->working_areas;
+
+	while (c)
+	{
+		working_area_t *next = c->next;
+		target_free_working_area(target, c);
+		
+		if (c->backup)
+			free(c->backup);
+		
+		free(c);
+		
+		c = next;
+	}
+	
+	target->working_areas = NULL;
+	
+	return ERROR_OK;
+}
+
+int target_register_commands(struct command_context_s *cmd_ctx)
+{
+	register_command(cmd_ctx, NULL, "target", handle_target_command, COMMAND_CONFIG, NULL);
+	register_command(cmd_ctx, NULL, "targets", handle_targets_command, COMMAND_EXEC, NULL);
+	register_command(cmd_ctx, NULL, "daemon_startup", handle_daemon_startup_command, COMMAND_CONFIG, NULL);
+	register_command(cmd_ctx, NULL, "target_script", handle_target_script_command, COMMAND_CONFIG, NULL);
+	register_command(cmd_ctx, NULL, "run_and_halt_time", handle_run_and_halt_time_command, COMMAND_CONFIG, NULL);
+	register_command(cmd_ctx, NULL, "working_area", handle_working_area_command, COMMAND_ANY, "working_area <target#> <address> <size> <'backup'|'nobackup'> [virtual address]");
+	register_command(cmd_ctx, NULL, "virt2phys", handle_virt2phys_command, COMMAND_ANY, "virt2phys <virtual address>");
+
+	return ERROR_OK;
+}
+
+int target_arch_state(struct target_s *target)
+{
+	int retval;
+	if (target==NULL)
+	{
+		USER("No target has been configured");
+		return ERROR_OK;
+	}
+	
+	USER("target state: %s", target_state_strings[target->state]);
+	
+	if (target->state!=TARGET_HALTED)
+		return ERROR_OK;
+	
+	retval=target->type->arch_state(target);
+	return retval;
+}
+
+/* Single aligned words are guaranteed to use 16 or 32 bit access 
+ * mode respectively, otherwise data is handled as quickly as 
+ * possible
+ */
+int target_write_buffer(struct target_s *target, u32 address, u32 size, u8 *buffer)
+{
+	int retval;
+	
+	DEBUG("writing buffer of %i byte at 0x%8.8x", size, address);
+	
+	if (((address % 2) == 0) && (size == 2))
+	{
+		return target->type->write_memory(target, address, 2, 1, buffer);
+	}
+	
+	/* handle unaligned head bytes */
+	if (address % 4)
+	{
+		int unaligned = 4 - (address % 4);
+		
+		if (unaligned > size)
+			unaligned = size;
+
+		if ((retval = target->type->write_memory(target, address, 1, unaligned, buffer)) != ERROR_OK)
+			return retval;
+		
+		buffer += unaligned;
+		address += unaligned;
+		size -= unaligned;
+	}
+		
+	/* handle aligned words */
+	if (size >= 4)
+	{
+		int aligned = size - (size % 4);
+	
+		/* use bulk writes above a certain limit. This may have to be changed */
+		if (aligned > 128)
+		{
+			if ((retval = target->type->bulk_write_memory(target, address, aligned / 4, buffer)) != ERROR_OK)
+				return retval;
+		}
+		else
+		{
+			if ((retval = target->type->write_memory(target, address, 4, aligned / 4, buffer)) != ERROR_OK)
+				return retval;
+		}
+		
+		buffer += aligned;
+		address += aligned;
+		size -= aligned;
+	}
+	
+	/* handle tail writes of less than 4 bytes */
+	if (size > 0)
+	{
+		if ((retval = target->type->write_memory(target, address, 1, size, buffer)) != ERROR_OK)
+			return retval;
+	}
+	
+	return ERROR_OK;
+}
+
+
+/* Single aligned words are guaranteed to use 16 or 32 bit access 
+ * mode respectively, otherwise data is handled as quickly as 
+ * possible
+ */
+int target_read_buffer(struct target_s *target, u32 address, u32 size, u8 *buffer)
+{
+	int retval;
+	
+	DEBUG("reading buffer of %i byte at 0x%8.8x", size, address);
+	
+	if (((address % 2) == 0) && (size == 2))
+	{
+		return target->type->read_memory(target, address, 2, 1, buffer);
+	}
+	
+	/* handle unaligned head bytes */
+	if (address % 4)
+	{
+		int unaligned = 4 - (address % 4);
+		
+		if (unaligned > size)
+			unaligned = size;
+
+		if ((retval = target->type->read_memory(target, address, 1, unaligned, buffer)) != ERROR_OK)
+			return retval;
+		
+		buffer += unaligned;
+		address += unaligned;
+		size -= unaligned;
+	}
+		
+	/* handle aligned words */
+	if (size >= 4)
+	{
+		int aligned = size - (size % 4);
+	
+		if ((retval = target->type->read_memory(target, address, 4, aligned / 4, buffer)) != ERROR_OK)
+			return retval;
+		
+		buffer += aligned;
+		address += aligned;
+		size -= aligned;
+	}
+	
+	/* handle tail writes of less than 4 bytes */
+	if (size > 0)
+	{
+		if ((retval = target->type->read_memory(target, address, 1, size, buffer)) != ERROR_OK)
+			return retval;
+	}
+	
+	return ERROR_OK;
+}
+
+int target_checksum_memory(struct target_s *target, u32 address, u32 size, u32* crc)
+{
+	u8 *buffer;
+	int retval;
+	int i;
+	u32 checksum = 0;
+	
+	if ((retval = target->type->checksum_memory(target, address,
+		size, &checksum)) == ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
+	{
+		buffer = malloc(size);
+		if (buffer == NULL)
+		{
+			ERROR("error allocating buffer for section (%d bytes)", size);
+			return ERROR_INVALID_ARGUMENTS;
+		}
+		retval = target_read_buffer(target, address, size, buffer);
+		if (retval != ERROR_OK)
+		{
+			free(buffer);
+			return retval;
+		}
+
+		/* convert to target endianess */
+		for (i = 0; i < (size/sizeof(u32)); i++)
+		{
+			u32 target_data;
+			target_data = target_buffer_get_u32(target, &buffer[i*sizeof(u32)]);
+			target_buffer_set_u32(target, &buffer[i*sizeof(u32)], target_data);
+		}
+
+		retval = image_calculate_checksum( buffer, size, &checksum );
+		free(buffer);
+	}
+	
+	*crc = checksum;
+	
+	return retval;
+}
+
+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);
+	
+	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);
+	}
+	
+	return retval;
+}
+
+int target_read_u16(struct target_s *target, u32 address, u16 *value)
+{
+	u8 value_buf[2];
+	
+	int retval = target->type->read_memory(target, address, 2, 1, value_buf);
+	
+	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;
+}
+
+int target_read_u8(struct target_s *target, u32 address, u8 *value)
+{
+	int retval = target->type->read_memory(target, address, 1, 1, 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;
+}
+
+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);	
+	if ((retval = target->type->write_memory(target, address, 4, 1, value_buf)) != ERROR_OK)
+	{
+		DEBUG("failed: %i", retval);
+	}
+	
+	return retval;
+}
+
+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);	
+	if ((retval = target->type->write_memory(target, address, 2, 1, value_buf)) != ERROR_OK)
+	{
+		DEBUG("failed: %i", retval);
+	}
+	
+	return retval;
+}
+
+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);
+
+	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)
+{
+	register_command(cmd_ctx,  NULL, "reg", handle_reg_command, COMMAND_EXEC, NULL);
+	register_command(cmd_ctx,  NULL, "poll", handle_poll_command, COMMAND_EXEC, "poll target state");
+	register_command(cmd_ctx,  NULL, "wait_halt", handle_wait_halt_command, COMMAND_EXEC, "wait for target halt [time (s)]");
+	register_command(cmd_ctx,  NULL, "halt", handle_halt_command, COMMAND_EXEC, "halt target");
+	register_command(cmd_ctx,  NULL, "resume", handle_resume_command, COMMAND_EXEC, "resume target [addr]");
+	register_command(cmd_ctx,  NULL, "step", handle_step_command, COMMAND_EXEC, "step one instruction from current PC or [addr]");
+	register_command(cmd_ctx,  NULL, "reset", handle_reset_command, COMMAND_EXEC, "reset target [run|halt|init|run_and_halt|run_and_init]");
+	register_command(cmd_ctx,  NULL, "soft_reset_halt", handle_soft_reset_halt_command, COMMAND_EXEC, "halt the target and do a soft reset");
+
+	register_command(cmd_ctx,  NULL, "mdw", handle_md_command, COMMAND_EXEC, "display memory words <addr> [count]");
+	register_command(cmd_ctx,  NULL, "mdh", handle_md_command, COMMAND_EXEC, "display memory half-words <addr> [count]");
+	register_command(cmd_ctx,  NULL, "mdb", handle_md_command, COMMAND_EXEC, "display memory bytes <addr> [count]");
+	
+	register_command(cmd_ctx,  NULL, "mww", handle_mw_command, COMMAND_EXEC, "write memory word <addr> <value>");
+	register_command(cmd_ctx,  NULL, "mwh", handle_mw_command, COMMAND_EXEC, "write memory half-word <addr> <value>");
+	register_command(cmd_ctx,  NULL, "mwb", handle_mw_command, COMMAND_EXEC, "write memory byte <addr> <value>");
+	
+	register_command(cmd_ctx,  NULL, "bp", handle_bp_command, COMMAND_EXEC, "set breakpoint <address> <length> [hw]");	
+	register_command(cmd_ctx,  NULL, "rbp", handle_rbp_command, COMMAND_EXEC, "remove breakpoint <adress>");
+	register_command(cmd_ctx,  NULL, "wp", handle_wp_command, COMMAND_EXEC, "set watchpoint <address> <length> <r/w/a> [value] [mask]");	
+	register_command(cmd_ctx,  NULL, "rwp", handle_rwp_command, COMMAND_EXEC, "remove watchpoint <adress>");
+	
+	register_command(cmd_ctx,  NULL, "load_image", handle_load_image_command, COMMAND_EXEC, "load_image <file> <address> ['bin'|'ihex'|'elf'|'s19']");
+	register_command(cmd_ctx,  NULL, "dump_image", handle_dump_image_command, COMMAND_EXEC, "dump_image <file> <address> <size>");
+	register_command(cmd_ctx,  NULL, "verify_image", handle_verify_image_command, COMMAND_EXEC, "verify_image <file> [offset] [type]");
+	register_command(cmd_ctx,  NULL, "load_binary", handle_load_image_command, COMMAND_EXEC, "[DEPRECATED] load_binary <file> <address>");
+	register_command(cmd_ctx,  NULL, "dump_binary", handle_dump_image_command, COMMAND_EXEC, "[DEPRECATED] dump_binary <file> <address> <size>");
+	
+	target_request_register_commands(cmd_ctx);
+	trace_register_commands(cmd_ctx);
+	
+	return ERROR_OK;
+}
+
+int handle_targets_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	target_t *target = targets;
+	int count = 0;
+	
+	if (argc == 1)
+	{
+		int num = strtoul(args[0], NULL, 0);
+		
+		while (target)
+		{
+			count++;
+			target = target->next;
+		}
+		
+		if (num < count)
+			cmd_ctx->current_target = num;
+		else
+			command_print(cmd_ctx, "%i is out of bounds, only %i targets are configured", num, count);
+			
+		return ERROR_OK;
+	}
+		
+	while (target)
+	{
+		command_print(cmd_ctx, "%i: %s (%s), state: %s", count++, target->type->name, target_endianess_strings[target->endianness], target_state_strings[target->state]);
+		target = target->next;
+	}
+	
+	return ERROR_OK;
+}
+
+int handle_target_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	int i;
+	int found = 0;
+	
+	if (argc < 3)
+	{
+		ERROR("target command requires at least three arguments: <type> <endianess> <reset_mode>");
+		exit(-1);
+	}
+	
+	/* search for the specified target */
+	if (args[0] && (args[0][0] != 0))
+	{
+		for (i = 0; target_types[i]; i++)
+		{
+			if (strcmp(args[0], target_types[i]->name) == 0)
+			{
+				target_t **last_target_p = &targets;
+				
+				/* register target specific commands */
+				if (target_types[i]->register_commands(cmd_ctx) != ERROR_OK)
+				{
+					ERROR("couldn't register '%s' commands", args[0]);
+					exit(-1);
+				}
+
+				if (*last_target_p)
+				{
+					while ((*last_target_p)->next)
+						last_target_p = &((*last_target_p)->next);
+					last_target_p = &((*last_target_p)->next);
+				}
+
+				*last_target_p = malloc(sizeof(target_t));
+				
+				(*last_target_p)->type = target_types[i];
+				
+				if (strcmp(args[1], "big") == 0)
+					(*last_target_p)->endianness = TARGET_BIG_ENDIAN;
+				else if (strcmp(args[1], "little") == 0)
+					(*last_target_p)->endianness = TARGET_LITTLE_ENDIAN;
+				else
+				{
+					ERROR("endianness must be either 'little' or 'big', not '%s'", args[1]);
+					exit(-1);
+				}
+				
+				/* what to do on a target reset */
+				if (strcmp(args[2], "reset_halt") == 0)
+					(*last_target_p)->reset_mode = RESET_HALT;
+				else if (strcmp(args[2], "reset_run") == 0)
+					(*last_target_p)->reset_mode = RESET_RUN;
+				else if (strcmp(args[2], "reset_init") == 0)
+					(*last_target_p)->reset_mode = RESET_INIT;
+				else if (strcmp(args[2], "run_and_halt") == 0)
+					(*last_target_p)->reset_mode = RESET_RUN_AND_HALT;
+				else if (strcmp(args[2], "run_and_init") == 0)
+					(*last_target_p)->reset_mode = RESET_RUN_AND_INIT;
+				else
+				{
+					ERROR("unknown target startup mode %s", args[2]);
+					exit(-1);
+				}
+				(*last_target_p)->run_and_halt_time = 1000; /* default 1s */
+				
+				(*last_target_p)->reset_script = NULL;
+				(*last_target_p)->post_halt_script = NULL;
+				(*last_target_p)->pre_resume_script = NULL;
+				(*last_target_p)->gdb_program_script = NULL;
+				
+				(*last_target_p)->working_area = 0x0;
+				(*last_target_p)->working_area_size = 0x0;
+				(*last_target_p)->working_areas = NULL;
+				(*last_target_p)->backup_working_area = 0;
+				
+				(*last_target_p)->state = TARGET_UNKNOWN;
+				(*last_target_p)->reg_cache = NULL;
+				(*last_target_p)->breakpoints = NULL;
+				(*last_target_p)->watchpoints = NULL;
+				(*last_target_p)->next = NULL;
+				(*last_target_p)->arch_info = NULL;
+				
+				/* initialize trace information */
+				(*last_target_p)->trace_info = malloc(sizeof(trace_t));
+				(*last_target_p)->trace_info->num_trace_points = 0;
+				(*last_target_p)->trace_info->trace_points_size = 0;
+				(*last_target_p)->trace_info->trace_points = NULL;
+				(*last_target_p)->trace_info->trace_history_size = 0;
+				(*last_target_p)->trace_info->trace_history = NULL;
+				(*last_target_p)->trace_info->trace_history_pos = 0;
+				(*last_target_p)->trace_info->trace_history_overflowed = 0;
+				
+				(*last_target_p)->dbgmsg = NULL;
+				(*last_target_p)->dbg_msg_enabled = 0;
+								
+				(*last_target_p)->type->target_command(cmd_ctx, cmd, args, argc, *last_target_p);
+				
+				found = 1;
+				break;
+			}
+		}
+	}
+	
+	/* no matching target found */
+	if (!found)
+	{
+		ERROR("target '%s' not found", args[0]);
+		exit(-1);
+	}
+
+	return ERROR_OK;
+}
+
+/* usage: target_script <target#> <event> <script_file> */
+int handle_target_script_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	target_t *target = NULL;
+	
+	if (argc < 3)
+	{
+		ERROR("incomplete target_script command");
+		exit(-1);
+	}
+	
+	target = get_target_by_num(strtoul(args[0], NULL, 0));
+	
+	if (!target)
+	{
+		ERROR("target number '%s' not defined", args[0]);
+		exit(-1);
+	}
+	
+	if (strcmp(args[1], "reset") == 0)
+	{
+		if (target->reset_script)
+			free(target->reset_script);
+		target->reset_script = strdup(args[2]);
+	}
+	else if (strcmp(args[1], "post_halt") == 0)
+	{
+		if (target->post_halt_script)
+			free(target->post_halt_script);
+		target->post_halt_script = strdup(args[2]);
+	}
+	else if (strcmp(args[1], "pre_resume") == 0)
+	{
+		if (target->pre_resume_script)
+			free(target->pre_resume_script);
+		target->pre_resume_script = strdup(args[2]);
+	}
+	else if (strcmp(args[1], "gdb_program_config") == 0)
+	{
+		if (target->gdb_program_script)
+			free(target->gdb_program_script);
+		target->gdb_program_script = strdup(args[2]);
+	}
+	else
+	{
+		ERROR("unknown event type: '%s", args[1]);
+		exit(-1);	
+	}
+	
+	return ERROR_OK;
+}
+
+int handle_run_and_halt_time_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	target_t *target = NULL;
+	
+	if (argc < 2)
+	{
+		ERROR("incomplete run_and_halt_time command");
+		exit(-1);
+	}
+	
+	target = get_target_by_num(strtoul(args[0], NULL, 0));
+	
+	if (!target)
+	{
+		ERROR("target number '%s' not defined", args[0]);
+		exit(-1);
+	}
+	
+	target->run_and_halt_time = strtoul(args[1], NULL, 0);
+	
+	return ERROR_OK;
+}
+
+int handle_working_area_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	target_t *target = NULL;
+	
+	if ((argc < 4) || (argc > 5))
+	{
+		return ERROR_COMMAND_SYNTAX_ERROR;
+	}
+	
+	target = get_target_by_num(strtoul(args[0], NULL, 0));
+	
+	if (!target)
+	{
+		ERROR("target number '%s' not defined", args[0]);
+		exit(-1);
+	}
+	target_free_all_working_areas(target);
+	
+	target->working_area_phys = target->working_area_virt = strtoul(args[1], NULL, 0);
+	if (argc == 5)
+	{
+		target->working_area_virt = strtoul(args[4], NULL, 0);
+	}
+	target->working_area_size = strtoul(args[2], NULL, 0);
+	
+	if (strcmp(args[3], "backup") == 0)
+	{
+		target->backup_working_area = 1;
+	}
+	else if (strcmp(args[3], "nobackup") == 0)
+	{
+		target->backup_working_area = 0;
+	}
+	else
+	{
+		ERROR("unrecognized <backup|nobackup> argument (%s)", args[3]);
+		return ERROR_COMMAND_SYNTAX_ERROR;
+	}
+	
+	return ERROR_OK;
+}
+
+
+/* process target state changes */
+int handle_target(void *priv)
+{
+	int retval;
+	target_t *target = targets;
+	
+	while (target)
+	{
+		/* only poll if target isn't already halted */
+		if (target->state != TARGET_HALTED)
+		{
+			if (target_continous_poll)
+				if ((retval = target->type->poll(target)) != ERROR_OK)
+				{
+					ERROR("couldn't poll target(%d). It's due for a reset.", retval);
+				}
+		}
+	
+		target = target->next;
+	}
+	
+	return ERROR_OK;
+}
+
+int handle_reg_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	target_t *target;
+	reg_t *reg = NULL;
+	int count = 0;
+	char *value;
+	
+	DEBUG("-");
+	
+	target = get_current_target(cmd_ctx);
+	
+	/* list all available registers for the current target */
+	if (argc == 0)
+	{
+		reg_cache_t *cache = target->reg_cache;
+		
+		count = 0;
+		while(cache)
+		{
+			int i;
+			for (i = 0; i < cache->num_regs; i++)
+			{
+				value = buf_to_str(cache->reg_list[i].value, cache->reg_list[i].size, 16);
+				command_print(cmd_ctx, "(%i) %s (/%i): 0x%s (dirty: %i, valid: %i)", count++, cache->reg_list[i].name, cache->reg_list[i].size, value, cache->reg_list[i].dirty, cache->reg_list[i].valid);
+				free(value);
+			}
+			cache = cache->next;
+		}
+		
+		return ERROR_OK;
+	}
+	
+	/* access a single register by its ordinal number */
+	if ((args[0][0] >= '0') && (args[0][0] <= '9'))
+	{
+		int num = strtoul(args[0], NULL, 0);
+		reg_cache_t *cache = target->reg_cache;
+		
+		count = 0;
+		while(cache)
+		{
+			int i;
+			for (i = 0; i < cache->num_regs; i++)
+			{
+				if (count++ == num)
+				{
+					reg = &cache->reg_list[i];
+					break;
+				}
+			}
+			if (reg)
+				break;
+			cache = cache->next;
+		}
+		
+		if (!reg)
+		{
+			command_print(cmd_ctx, "%i is out of bounds, the current target has only %i registers (0 - %i)", num, count, count - 1);
+			return ERROR_OK;
+		}
+	} else /* access a single register by its name */
+	{
+		reg = register_get_by_name(target->reg_cache, args[0], 1);
+		
+		if (!reg)
+		{
+			command_print(cmd_ctx, "register %s not found in current target", args[0]);
+			return ERROR_OK;
+		}
+	}
+
+	/* display a register */
+	if ((argc == 1) || ((argc == 2) && !((args[1][0] >= '0') && (args[1][0] <= '9'))))
+	{
+		if ((argc == 2) && (strcmp(args[1], "force") == 0))
+			reg->valid = 0;
+		
+		if (reg->valid == 0)
+		{
+			reg_arch_type_t *arch_type = register_get_arch_type(reg->arch_type);
+			if (arch_type == NULL)
+			{
+				ERROR("BUG: encountered unregistered arch type");
+				return ERROR_OK;
+			}
+			arch_type->get(reg);
+		}
+		value = buf_to_str(reg->value, reg->size, 16);
+		command_print(cmd_ctx, "%s (/%i): 0x%s", reg->name, reg->size, value);
+		free(value);
+		return ERROR_OK;
+	}
+	
+	/* set register value */
+	if (argc == 2)
+	{
+		u8 *buf = malloc(CEIL(reg->size, 8));
+		str_to_buf(args[1], strlen(args[1]), buf, reg->size, 0);
+
+		reg_arch_type_t *arch_type = register_get_arch_type(reg->arch_type);
+		if (arch_type == NULL)
+		{
+			ERROR("BUG: encountered unregistered arch type");
+			return ERROR_OK;
+		}
+		
+		arch_type->set(reg, buf);
+		
+		value = buf_to_str(reg->value, reg->size, 16);
+		command_print(cmd_ctx, "%s (/%i): 0x%s", reg->name, reg->size, value);
+		free(value);
+		
+		free(buf);
+		
+		return ERROR_OK;
+	}
+	
+	command_print(cmd_ctx, "usage: reg <#|name> [value]");
+	
+	return ERROR_OK;
+}
+
+static int wait_state(struct command_context_s *cmd_ctx, char *cmd, enum target_state state, int ms);
+
+int handle_poll_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	target_t *target = get_current_target(cmd_ctx);
+
+	if (argc == 0)
+	{
+		target->type->poll(target);
+			target_arch_state(target);
+	}
+	else
+	{
+		if (strcmp(args[0], "on") == 0)
+		{
+			target_continous_poll = 1;
+		}
+		else if (strcmp(args[0], "off") == 0)
+		{
+			target_continous_poll = 0;
+		}
+		else
+		{
+			command_print(cmd_ctx, "arg is \"on\" or \"off\"");
+		}
+	}
+	
+	
+	return ERROR_OK;
+}
+
+int handle_wait_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	int ms = 5000;
+	
+	if (argc > 0)
+	{
+		char *end;
+
+		ms = strtoul(args[0], &end, 0) * 1000;
+		if (*end)
+		{
+			command_print(cmd_ctx, "usage: %s [seconds]", cmd);
+			return ERROR_OK;
+		}
+	}
+
+	return wait_state(cmd_ctx, cmd, TARGET_HALTED, ms); 
+}
+
+static void target_process_events(struct command_context_s *cmd_ctx)
+{
+	target_t *target = get_current_target(cmd_ctx);
+	target->type->poll(target);
+	target_call_timer_callbacks();
+}
+
+static int wait_state(struct command_context_s *cmd_ctx, char *cmd, enum target_state state, int ms)
+{
+	int retval;
+	struct timeval timeout, now;
+	
+	gettimeofday(&timeout, NULL);
+	timeval_add_time(&timeout, 0, ms * 1000);
+	
+	target_t *target = get_current_target(cmd_ctx);
+	for (;;)
+	{
+		if ((retval=target->type->poll(target))!=ERROR_OK)
+			return retval;
+		target_call_timer_callbacks();
+		if (target->state == state)
+		{
+			break;
+		}
+		command_print(cmd_ctx, "waiting for target %s...", target_state_strings[state]);
+		
+		gettimeofday(&now, NULL);
+		if ((now.tv_sec > timeout.tv_sec) || ((now.tv_sec == timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec)))
+		{
+			command_print(cmd_ctx, "timed out while waiting for target %s", target_state_strings[state]);
+			ERROR("timed out while waiting for target %s", target_state_strings[state]);
+			break;
+		}
+	}
+	
+	return ERROR_OK;
+}
+
+int handle_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	int retval;
+	target_t *target = get_current_target(cmd_ctx);
+
+	DEBUG("-");
+	
+	command_print(cmd_ctx, "requesting target halt...");
+
+	if ((retval = target->type->halt(target)) != ERROR_OK)
+	{	
+		switch (retval)
+		{
+			case ERROR_TARGET_ALREADY_HALTED:
+				command_print(cmd_ctx, "target already halted");
+				break;
+			case ERROR_TARGET_TIMEOUT:
+				command_print(cmd_ctx, "target timed out... shutting down");
+				return retval;
+			default:
+				command_print(cmd_ctx, "unknown error... shutting down");
+				return retval;
+		}
+	}
+	
+	return handle_wait_halt_command(cmd_ctx, cmd, args, argc);
+}
+
+/* what to do on daemon startup */
+int handle_daemon_startup_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	if (argc == 1)
+	{
+		if (strcmp(args[0], "attach") == 0)
+		{
+			startup_mode = DAEMON_ATTACH;
+			return ERROR_OK;
+		}
+		else if (strcmp(args[0], "reset") == 0)
+		{
+			startup_mode = DAEMON_RESET;
+			return ERROR_OK;
+		}
+	}
+	
+	WARNING("invalid daemon_startup configuration directive: %s", args[0]);
+	return ERROR_OK;
+
+}
+		
+int handle_soft_reset_halt_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	target_t *target = get_current_target(cmd_ctx);
+	int retval;
+	
+	command_print(cmd_ctx, "requesting target halt and executing a soft reset");
+	
+	if ((retval = target->type->soft_reset_halt(target)) != ERROR_OK)
+	{	
+		switch (retval)
+		{
+			case ERROR_TARGET_TIMEOUT:
+				command_print(cmd_ctx, "target timed out... shutting down");
+				exit(-1);
+			default:
+				command_print(cmd_ctx, "unknown error... shutting down");
+				exit(-1);
+		}
+	}
+	
+	return ERROR_OK;
+}
+
+int handle_reset_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	target_t *target = get_current_target(cmd_ctx);
+	enum target_reset_mode reset_mode = target->reset_mode;
+	enum target_reset_mode save = target->reset_mode;
+	
+	DEBUG("-");
+	
+	if (argc >= 1)
+	{
+		if (strcmp("run", args[0]) == 0)
+			reset_mode = RESET_RUN;
+		else if (strcmp("halt", args[0]) == 0)
+			reset_mode = RESET_HALT;
+		else if (strcmp("init", args[0]) == 0)
+			reset_mode = RESET_INIT;
+		else if (strcmp("run_and_halt", args[0]) == 0)
+		{
+			reset_mode = RESET_RUN_AND_HALT;
+			if (argc >= 2)
+			{
+				target->run_and_halt_time = strtoul(args[1], NULL, 0);
+			}
+		}
+		else if (strcmp("run_and_init", args[0]) == 0)
+		{
+			reset_mode = RESET_RUN_AND_INIT;
+			if (argc >= 2)
+			{
+				target->run_and_halt_time = strtoul(args[1], NULL, 0);
+			}
+		}
+		else
+		{
+			command_print(cmd_ctx, "usage: reset ['run', 'halt', 'init', 'run_and_halt', 'run_and_init]");
+			return ERROR_OK;
+		}
+	}
+	
+	/* temporarily modify mode of current reset target */
+	target->reset_mode = reset_mode;
+
+	/* reset *all* targets */
+	target_process_reset(cmd_ctx);
+	
+	/* Restore default reset mode for this target */
+    target->reset_mode = save;
+	
+	return ERROR_OK;
+}
+
+int handle_resume_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	int retval;
+	target_t *target = get_current_target(cmd_ctx);
+	
+	if (argc == 0)
+		retval = target->type->resume(target, 1, 0, 1, 0); /* current pc, addr = 0, handle breakpoints, not debugging */
+	else if (argc == 1)
+		retval = target->type->resume(target, 0, strtoul(args[0], NULL, 0), 1, 0); /* addr = args[0], handle breakpoints, not debugging */
+	else
+	{
+		return ERROR_COMMAND_SYNTAX_ERROR;
+	}
+
+	target_process_events(cmd_ctx);
+	
+	target_arch_state(target);
+	
+	return retval;
+}
+
+int handle_step_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	target_t *target = get_current_target(cmd_ctx);
+	
+	DEBUG("-");
+	
+	if (argc == 0)
+		target->type->step(target, 1, 0, 1); /* current pc, addr = 0, handle breakpoints */
+
+	if (argc == 1)
+		target->type->step(target, 0, strtoul(args[0], NULL, 0), 1); /* addr = args[0], handle breakpoints */
+	
+	return ERROR_OK;
+}
+
+int handle_md_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	const int line_bytecnt = 32;
+	int count = 1;
+	int size = 4;
+	u32 address = 0;
+	int line_modulo;
+	int i;
+
+	char output[128];
+	int output_len;
+
+	int retval;
+
+	u8 *buffer;
+	target_t *target = get_current_target(cmd_ctx);
+
+	if (argc < 1)
+		return ERROR_OK;
+
+	if (argc == 2)
+		count = strtoul(args[1], NULL, 0);
+
+	address = strtoul(args[0], NULL, 0);
+	
+
+	switch (cmd[2])
+	{
+		case 'w':
+			size = 4; line_modulo = line_bytecnt / 4;
+			break;
+		case 'h':
+			size = 2; line_modulo = line_bytecnt / 2;
+			break;
+		case 'b':
+			size = 1; line_modulo = line_bytecnt / 1;
+			break;
+		default:
+			return ERROR_OK;
+	}
+
+	buffer = calloc(count, size);
+	retval  = target->type->read_memory(target, address, size, count, buffer);
+	if (retval != ERROR_OK)
+	{
+		switch (retval)
+		{
+			case ERROR_TARGET_UNALIGNED_ACCESS:
+				command_print(cmd_ctx, "error: address not aligned");
+				break;
+			case ERROR_TARGET_NOT_HALTED:
+				command_print(cmd_ctx, "error: target must be halted for memory accesses");
+				break;			
+			case ERROR_TARGET_DATA_ABORT:
+				command_print(cmd_ctx, "error: access caused data abort, system possibly corrupted");
+				break;
+			default:
+				command_print(cmd_ctx, "error: unknown error");
+				break;
+		}
+		return ERROR_OK;
+	}
+
+	output_len = 0;
+
+	for (i = 0; i < count; i++)
+	{
+		if (i%line_modulo == 0)
+			output_len += snprintf(output + output_len, 128 - output_len, "0x%8.8x: ", address + (i*size));
+		
+		switch (size)
+		{
+			case 4:
+				output_len += snprintf(output + output_len, 128 - output_len, "%8.8x ", target_buffer_get_u32(target, &buffer[i*4]));
+				break;
+			case 2:
+				output_len += snprintf(output + output_len, 128 - output_len, "%4.4x ", target_buffer_get_u16(target, &buffer[i*2]));
+				break;
+			case 1:
+				output_len += snprintf(output + output_len, 128 - output_len, "%2.2x ", buffer[i*1]);
+				break;
+		}
+
+		if ((i%line_modulo == line_modulo-1) || (i == count - 1))
+		{
+			command_print(cmd_ctx, output);
+			output_len = 0;
+		}
+	}
+
+	free(buffer);
+	
+	return ERROR_OK;
+}
+
+int handle_mw_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	u32 address = 0;
+	u32 value = 0;
+	int retval;
+	target_t *target = get_current_target(cmd_ctx);
+	u8 value_buf[4];
+
+	if (argc < 2)
+		return ERROR_OK;
+
+	address = strtoul(args[0], NULL, 0);
+	value = strtoul(args[1], NULL, 0);
+
+	switch (cmd[2])
+	{
+		case 'w':
+			target_buffer_set_u32(target, value_buf, value);
+			retval = target->type->write_memory(target, address, 4, 1, value_buf);
+			break;
+		case 'h':
+			target_buffer_set_u16(target, value_buf, value);
+			retval = target->type->write_memory(target, address, 2, 1, value_buf);
+			break;
+		case 'b':
+			value_buf[0] = value;
+			retval = target->type->write_memory(target, address, 1, 1, value_buf);
+			break;
+		default:
+			return ERROR_OK;
+	}
+
+	switch (retval)
+	{
+		case ERROR_TARGET_UNALIGNED_ACCESS:
+			command_print(cmd_ctx, "error: address not aligned");
+			break;
+		case ERROR_TARGET_DATA_ABORT:
+			command_print(cmd_ctx, "error: access caused data abort, system possibly corrupted");
+			break;
+		case ERROR_TARGET_NOT_HALTED:
+			command_print(cmd_ctx, "error: target must be halted for memory accesses");
+			break;
+		case ERROR_OK:
+			break;
+		default:
+			command_print(cmd_ctx, "error: unknown error");
+			break;
+	}
+
+	return ERROR_OK;
+
+}
+
+int handle_load_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	u8 *buffer;
+	u32 buf_cnt;
+	u32 image_size;
+	int i;
+	int retval;
+
+	image_t image;	
+	
+	duration_t duration;
+	char *duration_text;
+	
+	target_t *target = get_current_target(cmd_ctx);
+
+	if (argc < 1)
+	{
+		command_print(cmd_ctx, "usage: load_image <filename> [address] [type]");
+		return ERROR_OK;
+	}
+	
+	/* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */
+	if (argc >= 2)
+	{
+		image.base_address_set = 1;
+		image.base_address = strtoul(args[1], NULL, 0);
+	}
+	else
+	{
+		image.base_address_set = 0;
+	}
+	
+	image.start_address_set = 0;
+
+	duration_start_measure(&duration);
+	
+	if (image_open(&image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "load_image error: %s", image.error_str);
+		return ERROR_OK;
+	}
+	
+	image_size = 0x0;
+	for (i = 0; i < image.num_sections; i++)
+	{
+		buffer = malloc(image.sections[i].size);
+		if (buffer == NULL)
+		{
+			command_print(cmd_ctx, "error allocating buffer for section (%d bytes)", image.sections[i].size);
+			break;
+		}
+		
+		if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
+		{
+			ERROR("image_read_section failed with error code: %i", retval);
+			command_print(cmd_ctx, "image reading failed, download aborted");
+			free(buffer);
+			image_close(&image);
+			return ERROR_OK;
+		}
+		target_write_buffer(target, image.sections[i].base_address, buf_cnt, buffer);
+		image_size += buf_cnt;
+		command_print(cmd_ctx, "%u byte written at address 0x%8.8x", buf_cnt, image.sections[i].base_address);
+		
+		free(buffer);
+	}
+
+	duration_stop_measure(&duration, &duration_text);
+	command_print(cmd_ctx, "downloaded %u byte in %s", image_size, duration_text);
+	free(duration_text);
+	
+	image_close(&image);
+
+	return ERROR_OK;
+
+}
+
+int handle_dump_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	fileio_t fileio;
+	
+	u32 address;
+	u32 size;
+	u8 buffer[560];
+	int retval;
+	
+	duration_t duration;
+	char *duration_text;
+	
+	target_t *target = get_current_target(cmd_ctx);
+
+	if (argc != 3)
+	{
+		command_print(cmd_ctx, "usage: dump_image <filename> <address> <size>");
+		return ERROR_OK;
+	}
+
+	address = strtoul(args[1], NULL, 0);
+	size = strtoul(args[2], NULL, 0);
+
+	if ((address & 3) || (size & 3))
+	{
+		command_print(cmd_ctx, "only 32-bit aligned address and size are supported");
+		return ERROR_OK;
+	}
+	
+	if (fileio_open(&fileio, args[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "dump_image error: %s", fileio.error_str);
+		return ERROR_OK;
+	}
+	
+	duration_start_measure(&duration);
+	
+	while (size > 0)
+	{
+		u32 size_written;
+		u32 this_run_size = (size > 560) ? 560 : size;
+		
+		retval = target->type->read_memory(target, address, 4, this_run_size / 4, buffer);
+		if (retval != ERROR_OK)
+		{
+			command_print(cmd_ctx, "Reading memory failed %d", retval);
+			break;
+		}
+		
+		fileio_write(&fileio, this_run_size, buffer, &size_written);
+		
+		size -= this_run_size;
+		address += this_run_size;
+	}
+
+	fileio_close(&fileio);
+
+	duration_stop_measure(&duration, &duration_text);
+	command_print(cmd_ctx, "dumped %"PRIi64" byte in %s", fileio.size, duration_text);
+	free(duration_text);
+	
+	return ERROR_OK;
+}
+
+int handle_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	u8 *buffer;
+	u32 buf_cnt;
+	u32 image_size;
+	int i;
+	int retval;
+	u32 checksum = 0;
+	u32 mem_checksum = 0;
+
+	image_t image;	
+	
+	duration_t duration;
+	char *duration_text;
+	
+	target_t *target = get_current_target(cmd_ctx);
+	
+	if (argc < 1)
+	{
+		command_print(cmd_ctx, "usage: verify_image <file> [offset] [type]");
+		return ERROR_OK;
+	}
+	
+	if (!target)
+	{
+		ERROR("no target selected");
+		return ERROR_OK;
+	}
+	
+	duration_start_measure(&duration);
+	
+	if (argc >= 2)
+	{
+		image.base_address_set = 1;
+		image.base_address = strtoul(args[1], NULL, 0);
+	}
+	else
+	{
+		image.base_address_set = 0;
+		image.base_address = 0x0;
+	}
+
+	image.start_address_set = 0;
+
+	if (image_open(&image, args[0], (argc == 3) ? args[2] : NULL) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "verify_image error: %s", image.error_str);
+		return ERROR_OK;
+	}
+	
+	image_size = 0x0;
+	for (i = 0; i < image.num_sections; i++)
+	{
+		buffer = malloc(image.sections[i].size);
+		if (buffer == NULL)
+		{
+			command_print(cmd_ctx, "error allocating buffer for section (%d bytes)", image.sections[i].size);
+			break;
+		}
+		if ((retval = image_read_section(&image, i, 0x0, image.sections[i].size, buffer, &buf_cnt)) != ERROR_OK)
+		{
+			ERROR("image_read_section failed with error code: %i", retval);
+			command_print(cmd_ctx, "image reading failed, verify aborted");
+			free(buffer);
+			image_close(&image);
+			return ERROR_OK;
+		}
+		
+		/* calculate checksum of image */
+		image_calculate_checksum( buffer, buf_cnt, &checksum );
+		
+		retval = target_checksum_memory(target, image.sections[i].base_address, buf_cnt, &mem_checksum);
+		
+		if( retval != ERROR_OK )
+		{
+			command_print(cmd_ctx, "could not calculate checksum, verify aborted");
+			free(buffer);
+			image_close(&image);
+			return ERROR_OK;
+		}
+		
+		if( checksum != mem_checksum )
+		{
+			/* failed crc checksum, fall back to a binary compare */
+			u8 *data;
+			
+			command_print(cmd_ctx, "checksum mismatch - attempting binary compare");
+			
+			data = (u8*)malloc(buf_cnt);
+			
+			/* Can we use 32bit word accesses? */
+			int size = 1;
+			int count = buf_cnt;
+			if ((count % 4) == 0)
+			{
+				size *= 4;
+				count /= 4;
+			}
+			retval = target->type->read_memory(target, image.sections[i].base_address, size, count, data);
+	
+			if (retval == ERROR_OK)
+			{
+				int t;
+				for (t = 0; t < buf_cnt; t++)
+				{
+					if (data[t] != buffer[t])
+					{
+						command_print(cmd_ctx, "Verify operation failed address 0x%08x. Was 0x%02x instead of 0x%02x\n", t + image.sections[i].base_address, data[t], buffer[t]);
+						free(data);
+						free(buffer);
+						image_close(&image);
+						return ERROR_OK;
+					}
+				}
+			}
+			
+			free(data);
+		}
+		
+		free(buffer);
+		image_size += buf_cnt;
+	}
+	
+	duration_stop_measure(&duration, &duration_text);
+	command_print(cmd_ctx, "verified %u bytes in %s", image_size, duration_text);
+	free(duration_text);
+	
+	image_close(&image);
+	
+	return ERROR_OK;
+}
+
+int handle_bp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	int retval;
+	target_t *target = get_current_target(cmd_ctx);
+
+	if (argc == 0)
+	{
+		breakpoint_t *breakpoint = target->breakpoints;
+
+		while (breakpoint)
+		{
+			if (breakpoint->type == BKPT_SOFT)
+			{
+				char* buf = buf_to_str(breakpoint->orig_instr, breakpoint->length, 16);
+				command_print(cmd_ctx, "0x%8.8x, 0x%x, %i, 0x%s", breakpoint->address, breakpoint->length, breakpoint->set, buf);
+				free(buf);
+			}
+			else
+			{
+				command_print(cmd_ctx, "0x%8.8x, 0x%x, %i", breakpoint->address, breakpoint->length, breakpoint->set);
+			}
+			breakpoint = breakpoint->next;
+		}
+	}
+	else if (argc >= 2)
+	{
+		int hw = BKPT_SOFT;
+		u32 length = 0;
+
+		length = strtoul(args[1], NULL, 0);
+		
+		if (argc >= 3)
+			if (strcmp(args[2], "hw") == 0)
+				hw = BKPT_HARD;
+
+		if ((retval = breakpoint_add(target, strtoul(args[0], NULL, 0), length, hw)) != ERROR_OK)
+		{
+			switch (retval)
+			{
+				case ERROR_TARGET_NOT_HALTED:
+					command_print(cmd_ctx, "target must be halted to set breakpoints");
+					break;
+				case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
+					command_print(cmd_ctx, "no more breakpoints available");
+					break;
+				default:
+					command_print(cmd_ctx, "unknown error, breakpoint not set");
+					break;
+			}
+		}
+		else
+		{
+			command_print(cmd_ctx, "breakpoint added at address 0x%8.8x", strtoul(args[0], NULL, 0));
+		}
+	}
+	else
+	{
+		command_print(cmd_ctx, "usage: bp <address> <length> ['hw']");
+	}
+
+	return ERROR_OK;
+}
+
+int handle_rbp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	target_t *target = get_current_target(cmd_ctx);
+
+	if (argc > 0)
+		breakpoint_remove(target, strtoul(args[0], NULL, 0));
+
+	return ERROR_OK;
+}
+
+int handle_wp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	target_t *target = get_current_target(cmd_ctx);
+	int retval;
+
+	if (argc == 0)
+	{
+		watchpoint_t *watchpoint = target->watchpoints;
+
+		while (watchpoint)
+		{
+			command_print(cmd_ctx, "address: 0x%8.8x, mask: 0x%8.8x, r/w/a: %i, value: 0x%8.8x, mask: 0x%8.8x", watchpoint->address, watchpoint->length, watchpoint->rw, watchpoint->value, watchpoint->mask);
+			watchpoint = watchpoint->next;
+		}
+	} 
+	else if (argc >= 2)
+	{
+		enum watchpoint_rw type = WPT_ACCESS;
+		u32 data_value = 0x0;
+		u32 data_mask = 0xffffffff;
+		
+		if (argc >= 3)
+		{
+			switch(args[2][0])
+			{
+				case 'r':
+					type = WPT_READ;
+					break;
+				case 'w':
+					type = WPT_WRITE;
+					break;
+				case 'a':
+					type = WPT_ACCESS;
+					break;
+				default:
+					command_print(cmd_ctx, "usage: wp <address> <length> [r/w/a] [value] [mask]");
+					return ERROR_OK;
+			}
+		}
+		if (argc >= 4)
+		{
+			data_value = strtoul(args[3], NULL, 0);
+		}
+		if (argc >= 5)
+		{
+			data_mask = strtoul(args[4], NULL, 0);
+		}
+		
+		if ((retval = watchpoint_add(target, strtoul(args[0], NULL, 0),
+				strtoul(args[1], NULL, 0), type, data_value, data_mask)) != ERROR_OK)
+		{
+			switch (retval)
+			{
+				case ERROR_TARGET_NOT_HALTED:
+					command_print(cmd_ctx, "target must be halted to set watchpoints");
+					break;
+				case ERROR_TARGET_RESOURCE_NOT_AVAILABLE:
+					command_print(cmd_ctx, "no more watchpoints available");
+					break;
+				default:
+					command_print(cmd_ctx, "unknown error, watchpoint not set");
+					break;
+			}	
+		}
+	}
+	else
+	{
+		command_print(cmd_ctx, "usage: wp <address> <length> [r/w/a] [value] [mask]");
+	}
+		
+	return ERROR_OK;
+}
+
+int handle_rwp_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	target_t *target = get_current_target(cmd_ctx);
+
+	if (argc > 0)
+		watchpoint_remove(target, strtoul(args[0], NULL, 0));
+	
+	return ERROR_OK;
+}
+
+int handle_virt2phys_command(command_context_t *cmd_ctx, char *cmd, char **args, int argc)
+{
+	int retval;
+	target_t *target = get_current_target(cmd_ctx);
+	u32 va;
+	u32 pa;
+
+	if (argc != 1)
+	{
+		return ERROR_COMMAND_SYNTAX_ERROR;
+	}
+	va = strtoul(args[0], NULL, 0);
+
+	retval = target->type->virt2phys(target, va, &pa);
+	if (retval == ERROR_OK)
+	{
+		command_print(cmd_ctx, "Physical address 0x%08x", pa);
+	}
+	else
+	{
+		/* lower levels will have logged a detailed error which is 
+		 * forwarded to telnet/GDB session.  
+		 */
+	}
+	return retval;
+}
diff --git a/src/target/xscale.c b/src/target/xscale.c
index bfa0f9f9f7a5a2652d03895d9c5e9df8448e93d5..11ae5eedf4149679ee104c3d54b0a84b115263fa 100644
--- a/src/target/xscale.c
+++ b/src/target/xscale.c
@@ -1,3799 +1,3799 @@
-/***************************************************************************
- *   Copyright (C) 2006, 2007 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 "replacements.h"
-
-#include "xscale.h"
-
-#include "register.h"
-#include "target.h"
-#include "armv4_5.h"
-#include "arm_simulator.h"
-#include "arm_disassembler.h"
-#include "log.h"
-#include "jtag.h"
-#include "binarybuffer.h"
-#include "time_support.h"
-#include "breakpoints.h"
-#include "fileio.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <sys/types.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);
-int xscale_poll(target_t *target);
-int xscale_halt(target_t *target);
-int xscale_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution);
-int xscale_step(struct target_s *target, int current, u32 address, int handle_breakpoints);
-int xscale_debug_entry(target_t *target);
-int xscale_restore_context(target_t *target);
-
-int xscale_assert_reset(target_t *target);
-int xscale_deassert_reset(target_t *target);
-int xscale_soft_reset_halt(struct target_s *target);
-int xscale_prepare_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_checksum_memory(struct target_s *target, u32 address, u32 count, u32* checksum);
-
-int xscale_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
-int xscale_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
-int xscale_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
-int xscale_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
-int xscale_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint);
-int xscale_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint);
-void xscale_enable_watchpoints(struct target_s *target);
-void xscale_enable_breakpoints(struct target_s *target);
-static int xscale_virt2phys(struct target_s *target, u32 virtual, u32 *physical);
-static int xscale_mmu(struct target_s *target, int *enabled);
-
-int xscale_read_trace(target_t *target);
-
-target_type_t xscale_target =
-{
-	.name = "xscale",
-
-	.poll = xscale_poll,
-	.arch_state = xscale_arch_state,
-
-	.target_request_data = NULL,
-
-	.halt = xscale_halt,
-	.resume = xscale_resume,
-	.step = xscale_step,
-
-	.assert_reset = xscale_assert_reset,
-	.deassert_reset = xscale_deassert_reset,
-	.soft_reset_halt = xscale_soft_reset_halt,
-	.prepare_reset_halt = xscale_prepare_reset_halt,
-
-	.get_gdb_reg_list = armv4_5_get_gdb_reg_list,
-
-	.read_memory = xscale_read_memory,
-	.write_memory = xscale_write_memory,
-	.bulk_write_memory = xscale_bulk_write_memory,
-	.checksum_memory = xscale_checksum_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,
-	
-	.virt2phys = xscale_virt2phys,
-	.mmu = xscale_mmu
-};
-
-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)
-	{
-		ERROR("target isn't an XScale target");
-		return -1;
-	}
-
-	if (xscale->common_magic != XSCALE_COMMON_MAGIC)
-	{
-		ERROR("target isn't an XScale target");
-		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;
-		jtag_set_check_value(&field, device->expected, device->expected_mask, NULL);
-
-		jtag_add_ir_scan(1, &field, -1, NULL);
-
-		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;
-	jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, 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;
-	jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, NULL);
-
-	jtag_add_dr_scan(3, fields, -1, NULL);
-
-	if ((retval = jtag_execute_queue()) != ERROR_OK)
-	{
-		ERROR("JTAG error while reading DCSR");
-		return retval;
-	}
-
-	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, NULL);
-
-	return ERROR_OK;
-}
-
-int xscale_receive(target_t *target, u32 *buffer, int num_words)
-{
-	int retval = ERROR_OK;
-	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;
-
-	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; */
-	jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, 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;
-	jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, 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 */
-	int attempts = 0;
-	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, NULL);
-			words_scheduled++;
-		}
-
-		if ((retval = jtag_execute_queue()) != ERROR_OK)
-		{
-			ERROR("JTAG error while receiving data from debug handler");
-			break;
-		}
-
-		/* 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--;
-			}
-		}
-		if (words_scheduled == 0)
-		{
-			if (attempts++ == 1000)
-			{
-				ERROR("Failed to receiving data from debug handler after 1000 attempts");
-				retval = ERROR_JTAG_QUEUE_FAILED;
-				break;
-			}
-		}
-		
-		words_done += words_scheduled;
-	}
-
-	for (i = 0; i < num_words; i++)
-		*(buffer++) = buf_get_u32((u8*)&field1[i], 0, 32);
-
-	free(field1);
-
-	return retval;
-}
-
-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];
-	enum tap_state noconsume_path[9];
-
-	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;
-
-	noconsume_path[0] = TAP_SDS;
-	noconsume_path[1] = TAP_CD;
-	noconsume_path[2] = TAP_E1D;
-	noconsume_path[3] = TAP_PD;
-	noconsume_path[4] = TAP_E2D;
-	noconsume_path[5] = TAP_UD;
-	noconsume_path[6] = TAP_SDS;
-	noconsume_path[7] = TAP_CD;
-	noconsume_path[8] = 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;
-	jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, 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;
-	jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, 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_pathmove(sizeof(noconsume_path)/sizeof(*noconsume_path), noconsume_path);
-
-		jtag_add_dr_scan(3, fields, TAP_RTI, NULL);
-
-		if ((retval = jtag_execute_queue()) != ERROR_OK)
-		{
-			ERROR("JTAG error while reading TX");
-			return ERROR_TARGET_TIMEOUT;
-		}
-
-		gettimeofday(&now, NULL);
-		if ((now.tv_sec > timeout.tv_sec) || ((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;
-	jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, 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;
-	jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, NULL);
-
-	gettimeofday(&timeout, NULL);
-	timeval_add_time(&timeout, 5, 0);
-
-	/* poll until rx_read is low */
-	DEBUG("polling RX");
-	do
-	{
-		jtag_add_dr_scan(3, fields, TAP_RTI, NULL);
-
-		if ((retval = jtag_execute_queue()) != ERROR_OK)
-		{
-			ERROR("JTAG error while writing RX");
-			return retval;
-		}
-
-		gettimeofday(&now, NULL);
-		if ((now.tv_sec > timeout.tv_sec) || ((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, NULL);
-
-	if ((retval = jtag_execute_queue()) != ERROR_OK)
-	{
-		ERROR("JTAG error while writing RX");
-		return retval;
-	}
-
-	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_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_handler = NULL;
-	if (!xscale->fast_memory_access)
-	{
-		jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, 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_handler = NULL;
-	if (!xscale->fast_memory_access)
-	{
-		jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, NULL);
-	}
-
-	if (size==4)
-	{
-		int endianness = target->endianness;
-		while (done_count++ < count)
-		{
-			if (endianness == TARGET_LITTLE_ENDIAN)
-			{
-				output[0]=buffer[0];
-				output[1]=buffer[1];
-				output[2]=buffer[2];
-				output[3]=buffer[3];
-			} else
-			{
-				output[0]=buffer[3];
-				output[1]=buffer[2];
-				output[2]=buffer[1];
-				output[3]=buffer[0];
-			}
-			jtag_add_dr_scan(3, fields, TAP_RTI, NULL);
-			buffer += size;
-		}
-		
-	} else
-	{
-		while (done_count++ < count)
-		{
-		/* extract sized element from target-endian buffer, and put it
-		 * into little-endian output buffer
-		 */
-		switch (size)
-		{
-			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, NULL);
-		buffer += size;
-	}
-
-	}
-
-	if ((retval = jtag_execute_queue()) != ERROR_OK)
-	{
-		ERROR("JTAG error while sending data to debug handler");
-		return retval;
-	}
-
-	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;
-	jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, 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;
-	jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, NULL);
-
-	jtag_add_dr_scan(3, fields, -1, NULL);
-
-	if ((retval = jtag_execute_queue()) != ERROR_OK)
-	{
-		ERROR("JTAG error while writing DCSR");
-		return retval;
-	}
-
-	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, NULL);
-
-	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, NULL);
-	}
-
-	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, NULL);
-
-	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)
-{
-	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);
-	}
-
-	USER("target halted in %s state due to %s, current mode: %s\n"
-			"cpsr: 0x%8.8x pc: 0x%8.8x\n"
-			"MMU: %s, D-Cache: %s, I-Cache: %s"
-			"%s",
-			 armv4_5_state_strings[armv4_5->core_state],
-			 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;
-}
-
-int xscale_poll(target_t *target)
-{
-	int retval=ERROR_OK;
-	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))
-	{
-		enum target_state previous_state = target->state;
-		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;
-
-			target->state = TARGET_HALTED;
-
-			/* process debug entry, fetching current mode regs */
-			retval = xscale_debug_entry(target);
-		}
-		else if (retval != ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
-		{
-			USER("error while polling TX register, reset CPU");
-			/* here we "lie" so GDB won't get stuck and a reset can be perfomed */
-			target->state = TARGET_HALTED;
-		}
-
-			/* debug_entry could have overwritten target state (i.e. immediate resume)
-			 * don't signal event handlers in that case
-			 */
-		if (target->state != TARGET_HALTED)
-			return ERROR_OK;
-
-		/* if target was running, signal that we halted
-		 * otherwise we reentered from debug execution */
-		if (previous_state == TARGET_RUNNING)
-			target_call_event_callbacks(target, TARGET_EVENT_HALTED);
-		else
-			target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
-	}
-	return retval;
-}
-
-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[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;
-
-	/* tracing enabled, read collected trace data */
-	if (xscale->trace.buffer_enabled)
-	{
-		xscale_read_trace(target);
-		xscale->trace.buffer_fill--;
-
-		/* resume if we're still collecting trace data */
-		if ((xscale->arch_debug_reason == XSCALE_DBG_REASON_TB_FULL)
-			&& (xscale->trace.buffer_fill > 0))
-		{
-			xscale_resume(target, 1, 0x0, 1, 0);
-		}
-		else
-		{
-			xscale->trace.buffer_enabled = 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");
-		return ERROR_TARGET_INVALID;
-	}
-	else if (target->state == TARGET_RESET)
-	{
-		DEBUG("target->state == TARGET_RESET");
-	}
-	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]);
-
-	/* select DCSR instruction (set endstate to R-T-I to ensure we don't
-	 * end up in T-L-R, which would reset JTAG
-	 */
-	jtag_add_end_state(TAP_RTI);
-	xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.dcsr);
-
-	/* 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);
-
-	/* select BYPASS, because having DCSR selected caused problems on the PXA27x */
-	xscale_jtag_set_instr(xscale->jtag_info.chain_pos, 0x7f);
-	jtag_execute_queue();
-
-	/* assert reset */
-	jtag_add_reset(0, 1);
-
-	/* sleep 1ms, to be sure we fulfill any requirements */
-	jtag_add_sleep(1000);
-	jtag_execute_queue();
-
-	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;
-
-	fileio_t debug_handler;
-	u32 address;
-	u32 binary_size;
-
-	u32 buf_cnt;
-	int i;
-	int retval;
-
-	breakpoint_t *breakpoint = target->breakpoints;
-
-	DEBUG("-");
-
-	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 SRST */
-		jtag_add_reset(0, 0);
-
-		/* wait 300ms; 150 and 100ms were not enough */
-		jtag_add_sleep(300*1000);
-
-		jtag_add_runtest(2030, TAP_RTI);
-		jtag_execute_queue();
-
-		/* 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);
-
-		/* Load debug handler */
-		if (fileio_open(&debug_handler, PKGLIBDIR "/xscale/debug_handler.bin", FILEIO_READ, FILEIO_BINARY) != ERROR_OK)
-		{
-			ERROR("file open error: %s", debug_handler.error_str);
-			return ERROR_OK;
-		}
-
-		if ((binary_size = debug_handler.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)
-		{
-			u32 cache_line[8];
-			u8 buffer[32];
-
-			if ((retval = fileio_read(&debug_handler, 32, buffer, &buf_cnt)) != ERROR_OK)
-			{
-				ERROR("reading debug handler failed: %s", debug_handler.error_str);
-			}
-
-			for (i = 0; i < buf_cnt; i += 4)
-			{
-				/* convert LE buffer to host-endian u32 */
-				cache_line[i / 4] = le_to_h_u32(&buffer[i]);
-			}
-
-			for (; buf_cnt < 32; buf_cnt += 4)
-			{
-					cache_line[buf_cnt / 4] = 0xe1a08008;
-			}
-
-			/* only load addresses other than the reset vectors */
-			if ((address % 0x400) != 0x0)
-			{
-				xscale_load_ic(target, 1, address, cache_line);
-			}
-
-			address += buf_cnt;
-			binary_size -= buf_cnt;
-		};
-
-		xscale_load_ic(target, 1, 0x0, xscale->low_vectors);
-		xscale_load_ic(target, 1, 0xffff0000, xscale->high_vectors);
-
-		jtag_add_runtest(30, TAP_RTI);
-
-		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);
-
-		/* clear Hold reset to let the target run (should enter debug handler) */
-		xscale_write_dcsr(target, 0, 1);
-		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;
-
-			/* resume the target */
-			xscale_resume(target, 1, 0x0, 1, 0);
-		}
-
-		fileio_close(&debug_handler);
-	}
-	else
-	{
-		jtag_add_reset(0, 0);
-	}
-
-
-	return ERROR_OK;
-}
-
-int xscale_soft_reset_halt(struct target_s *target)
-{
-
-	return ERROR_OK;
-}
-
-int xscale_prepare_reset_halt(struct target_s *target)
-{
-	/* nothing to be done for reset_halt on XScale targets
-	 * we always halt after a reset to upload the debug handler
-	 */
-	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)
-{
-	return xscale_write_memory(target, address, 4, count, buffer);
-}
-
-int xscale_checksum_memory(struct target_s *target, u32 address, u32 count, u32* checksum)
-{
-	return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
-}
-
-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 = 0;
-	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;
-}
-
-int xscale_read_trace(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;
-	xscale_trace_data_t **trace_data_p;
-
-	/* 258 words from debug handler
-	 * 256 trace buffer entries
-	 * 2 checkpoint addresses
-	 */
-	u32 trace_buffer[258];
-	int is_address[256];
-	int i, j;
-
-	if (target->state != TARGET_HALTED)
-	{
-		WARNING("target must be stopped to read trace data");
-		return ERROR_TARGET_NOT_HALTED;
-	}
-
-	/* send read trace buffer command (command 0x61) */
-	xscale_send_u32(target, 0x61);
-
-	/* receive trace buffer content */
-	xscale_receive(target, trace_buffer, 258);
-
-	/* parse buffer backwards to identify address entries */
-	for (i = 255; i >= 0; i--)
-	{
-		is_address[i] = 0;
-		if (((trace_buffer[i] & 0xf0) == 0x90) ||
-			((trace_buffer[i] & 0xf0) == 0xd0))
-		{
-			if (i >= 3)
-				is_address[--i] = 1;
-			if (i >= 2)
-				is_address[--i] = 1;
-			if (i >= 1)
-				is_address[--i] = 1;
-			if (i >= 0)
-				is_address[--i] = 1;
-		}
-	}
-
-
-	/* search first non-zero entry */
-	for (j = 0; (j < 256) && (trace_buffer[j] == 0) && (!is_address[j]); j++)
-		;
-
-	if (j == 256)
-	{
-		DEBUG("no trace data collected");
-		return ERROR_XSCALE_NO_TRACE_DATA;
-	}
-
-	for (trace_data_p = &xscale->trace.data; *trace_data_p; trace_data_p = &(*trace_data_p)->next)
-		;
-
-	*trace_data_p = malloc(sizeof(xscale_trace_data_t));
-	(*trace_data_p)->next = NULL;
-	(*trace_data_p)->chkpt0 = trace_buffer[256];
-	(*trace_data_p)->chkpt1 = trace_buffer[257];
-	(*trace_data_p)->last_instruction = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
-	(*trace_data_p)->entries = malloc(sizeof(xscale_trace_entry_t) * (256 - j));
-	(*trace_data_p)->depth = 256 - j;
-
-	for (i = j; i < 256; i++)
-	{
-		(*trace_data_p)->entries[i - j].data = trace_buffer[i];
-		if (is_address[i])
-			(*trace_data_p)->entries[i - j].type = XSCALE_TRACE_ADDRESS;
-		else
-			(*trace_data_p)->entries[i - j].type = XSCALE_TRACE_MESSAGE;
-	}
-
-	return ERROR_OK;
-}
-
-int xscale_read_instruction(target_t *target, arm_instruction_t *instruction)
-{
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	xscale_common_t *xscale = armv4_5->arch_info;
-	int i;
-	int section = -1;
-	u32 size_read;
-	u32 opcode;
-	int retval;
-
-	if (!xscale->trace.image)
-		return ERROR_TRACE_IMAGE_UNAVAILABLE;
-
-	/* search for the section the current instruction belongs to */
-	for (i = 0; i < xscale->trace.image->num_sections; i++)
-	{
-		if ((xscale->trace.image->sections[i].base_address <= xscale->trace.current_pc) &&
-			(xscale->trace.image->sections[i].base_address + xscale->trace.image->sections[i].size > xscale->trace.current_pc))
-		{
-			section = i;
-			break;
-		}
-	}
-
-	if (section == -1)
-	{
-		/* current instruction couldn't be found in the image */
-		return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
-	}
-
-	if (xscale->trace.core_state == ARMV4_5_STATE_ARM)
-	{
-		u8 buf[4];
-		if ((retval = image_read_section(xscale->trace.image, section,
-			xscale->trace.current_pc - xscale->trace.image->sections[section].base_address,
-			4, buf, &size_read)) != ERROR_OK)
-		{
-			ERROR("error while reading instruction: %i", retval);
-			return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
-		}
-		opcode = target_buffer_get_u32(target, buf);
-		arm_evaluate_opcode(opcode, xscale->trace.current_pc, instruction);
-	}
-	else if (xscale->trace.core_state == ARMV4_5_STATE_THUMB)
-	{
-		u8 buf[2];
-		if ((retval = image_read_section(xscale->trace.image, section,
-			xscale->trace.current_pc - xscale->trace.image->sections[section].base_address,
-			2, buf, &size_read)) != ERROR_OK)
-		{
-			ERROR("error while reading instruction: %i", retval);
-			return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
-		}
-		opcode = target_buffer_get_u16(target, buf);
-		thumb_evaluate_opcode(opcode, xscale->trace.current_pc, instruction);
-	}
-	else
-	{
-		ERROR("BUG: unknown core state encountered");
-		exit(-1);
-	}
-
-	return ERROR_OK;
-}
-
-int xscale_branch_address(xscale_trace_data_t *trace_data, int i, u32 *target)
-{
-	/* if there are less than four entries prior to the indirect branch message
-	 * we can't extract the address */
-	if (i < 4)
-	{
-		return -1;
-	}
-
-	*target = (trace_data->entries[i-1].data) | (trace_data->entries[i-2].data << 8) |
-				(trace_data->entries[i-3].data << 16) | (trace_data->entries[i-4].data << 24);
-
-	return 0;
-}
-
-int xscale_analyze_trace(target_t *target, command_context_t *cmd_ctx)
-{
-	/* get pointers to arch-specific information */
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	xscale_common_t *xscale = armv4_5->arch_info;
-	int next_pc_ok = 0;
-	u32 next_pc = 0x0;
-	xscale_trace_data_t *trace_data = xscale->trace.data;
-	int retval;
-
-	while (trace_data)
-	{
-		int i, chkpt;
-		int rollover;
-		int branch;
-		int exception;
-		xscale->trace.core_state = ARMV4_5_STATE_ARM;
-
-		chkpt = 0;
-		rollover = 0;
-
-		for (i = 0; i < trace_data->depth; i++)
-		{
-			next_pc_ok = 0;
-			branch = 0;
-			exception = 0;
-
-			if (trace_data->entries[i].type == XSCALE_TRACE_ADDRESS)
-				continue;
-
-			switch ((trace_data->entries[i].data & 0xf0) >> 4)
-			{
-				case 0:		/* Exceptions */
-				case 1:
-				case 2:
-				case 3:
-				case 4:
-				case 5:
-				case 6:
-				case 7:
-					exception = (trace_data->entries[i].data & 0x70) >> 4;
-					next_pc_ok = 1;
-					next_pc = (trace_data->entries[i].data & 0xf0) >> 2;
-					command_print(cmd_ctx, "--- exception %i ---", (trace_data->entries[i].data & 0xf0) >> 4);
-					break;
-				case 8:		/* Direct Branch */
-					branch = 1;
-					break;
-				case 9:		/* Indirect Branch */
-					branch = 1;
-					if (xscale_branch_address(trace_data, i, &next_pc) == 0)
-					{
-						next_pc_ok = 1;
-					}
-					break;
-				case 13:	/* Checkpointed Indirect Branch */
-					if (xscale_branch_address(trace_data, i, &next_pc) == 0)
-					{
-						next_pc_ok = 1;
-						if (((chkpt == 0) && (next_pc != trace_data->chkpt0))
-							|| ((chkpt == 1) && (next_pc != trace_data->chkpt1)))
-							WARNING("checkpointed indirect branch target address doesn't match checkpoint");
-					}
-					/* explicit fall-through */
-				case 12:	/* Checkpointed Direct Branch */
-					branch = 1;
-					if (chkpt == 0)
-					{
-						next_pc_ok = 1;
-						next_pc = trace_data->chkpt0;
-						chkpt++;
-					}
-					else if (chkpt == 1)
-					{
-						next_pc_ok = 1;
-						next_pc = trace_data->chkpt0;
-						chkpt++;
-					}
-					else
-					{
-						WARNING("more than two checkpointed branches encountered");
-					}
-					break;
-				case 15:	/* Roll-over */
-					rollover++;
-					continue;
-				default:	/* Reserved */
-					command_print(cmd_ctx, "--- reserved trace message ---");
-					ERROR("BUG: trace message %i is reserved", (trace_data->entries[i].data & 0xf0) >> 4);
-					return ERROR_OK;
-			}
-
-			if (xscale->trace.pc_ok)
-			{
-				int executed = (trace_data->entries[i].data & 0xf) + rollover * 16;
-				arm_instruction_t instruction;
-
-				if ((exception == 6) || (exception == 7))
-				{
-					/* IRQ or FIQ exception, no instruction executed */
-					executed -= 1;
-				}
-
-				while (executed-- >= 0)
-				{
-					if ((retval = xscale_read_instruction(target, &instruction)) != ERROR_OK)
-					{
-						/* can't continue tracing with no image available */
-						if (retval == ERROR_TRACE_IMAGE_UNAVAILABLE)
-						{
-							return retval;
-						}
-						else if (retval == ERROR_TRACE_INSTRUCTION_UNAVAILABLE)
-						{
-							/* TODO: handle incomplete images */
-						}
-					}
-
-					/* a precise abort on a load to the PC is included in the incremental
-					 * word count, other instructions causing data aborts are not included
-					 */
-					if ((executed == 0) && (exception == 4)
-						&& ((instruction.type >= ARM_LDR) && (instruction.type <= ARM_LDM)))
-					{
-						if ((instruction.type == ARM_LDM)
-							&& ((instruction.info.load_store_multiple.register_list & 0x8000) == 0))
-						{
-							executed--;
-						}
-						else if (((instruction.type >= ARM_LDR) && (instruction.type <= ARM_LDRSH))
-							&& (instruction.info.load_store.Rd != 15))
-						{
-							executed--;
-						}
-					}
-
-					/* only the last instruction executed
-					 * (the one that caused the control flow change)
-					 * could be a taken branch
-					 */
-					if (((executed == -1) && (branch == 1)) &&
-						(((instruction.type == ARM_B) ||
-							(instruction.type == ARM_BL) ||
-							(instruction.type == ARM_BLX)) &&
-							(instruction.info.b_bl_bx_blx.target_address != -1)))
-					{
-						xscale->trace.current_pc = instruction.info.b_bl_bx_blx.target_address;
-					}
-					else
-					{
-						xscale->trace.current_pc += (xscale->trace.core_state == ARMV4_5_STATE_ARM) ? 4 : 2;
-					}
-					command_print(cmd_ctx, "%s", instruction.text);
-				}
-
-				rollover = 0;
-			}
-
-			if (next_pc_ok)
-			{
-				xscale->trace.current_pc = next_pc;
-				xscale->trace.pc_ok = 1;
-			}
-		}
-
-		for (; xscale->trace.current_pc < trace_data->last_instruction; xscale->trace.current_pc += (xscale->trace.core_state == ARMV4_5_STATE_ARM) ? 4 : 2)
-		{
-			arm_instruction_t instruction;
-			if ((retval = xscale_read_instruction(target, &instruction)) != ERROR_OK)
-			{
-				/* can't continue tracing with no image available */
-				if (retval == ERROR_TRACE_IMAGE_UNAVAILABLE)
-				{
-					return retval;
-				}
-				else if (retval == ERROR_TRACE_INSTRUCTION_UNAVAILABLE)
-				{
-					/* TODO: handle incomplete images */
-				}
-			}
-			command_print(cmd_ctx, "%s", instruction.text);
-		}
-
-		trace_data = trace_data->next;
-	}
-
-	return ERROR_OK;
-}
-
-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");
-	}
-
-	/* assert TRST once during startup */
-	jtag_add_reset(1, 0);
-	jtag_add_sleep(5000);
-	jtag_add_reset(0, 0);
-	jtag_execute_queue();
-
-	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.capture_status = TRACE_IDLE;
-	xscale->trace.data = NULL;
-	xscale->trace.image = NULL;
-	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;
-
-	xscale->fast_memory_access = 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>");
-		return ERROR_OK;
-	}
-
-	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)
-	{
-		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)
-	{
-		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)
-	{
-		return ERROR_OK;
-	}
-
-	return armv4_5_handle_cache_info_command(cmd_ctx, &xscale->armv4_5_mmu.armv4_5_cache);
-}
-
-static int xscale_virt2phys(struct target_s *target, u32 virtual, u32 *physical)
-{
-	armv4_5_common_t *armv4_5;
-	xscale_common_t *xscale;
-	int retval;
-	int type;
-	u32 cb;
-	int domain;
-	u32 ap;
-	
-	if ((retval = xscale_get_arch_pointers(target, &armv4_5, &xscale)) != ERROR_OK)
-	{
-		return retval;
-	}
-	u32 ret = armv4_5_mmu_translate_va(target, &xscale->armv4_5_mmu, virtual, &type, &cb, &domain, &ap);
-	if (type == -1)
-	{
-		return ret;
-	}
-	
-	*physical = ret;
-	return ERROR_OK;
-}
-
-static int xscale_mmu(struct target_s *target, int *enabled)
-{
-	armv4_5_common_t *armv4_5 = target->arch_info;
-	xscale_common_t *xscale = armv4_5->arch_info;
-
-	if (target->state != TARGET_HALTED)
-	{
-		ERROR("Target not halted");
-		return ERROR_TARGET_INVALID;
-	}
-	
-	*enabled = xscale->armv4_5_mmu.mmu_enabled;
-	return ERROR_OK;
-}
-
-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)
-	{
-		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)
-	{
-		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)
-	{
-		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)
-	{
-		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)
-	{
-		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_data_t *td, *next_td;
-		xscale->trace.buffer_enabled = 1;
-
-		/* free old trace data */
-		td = xscale->trace.data;
-		while (td)
-		{
-			next_td = td->next;
-
-			if (td->entries)
-				free(td->entries);
-			free(td);
-			td = next_td;
-		}
-		xscale->trace.data = NULL;
-	}
-	else if ((argc >= 1) && (strcmp("disable", args[0]) == 0))
-	{
-		xscale->trace.buffer_enabled = 0;
-	}
-
-	if ((argc >= 2) && (strcmp("fill", args[1]) == 0))
-	{
-		if (argc >= 3)
-			xscale->trace.buffer_fill = strtoul(args[2], NULL, 0);
-		else
-			xscale->trace.buffer_fill = 1;
-	}
-	else if ((argc >= 2) && (strcmp("wrap", args[1]) == 0))
-	{
-		xscale->trace.buffer_fill = -1;
-	}
-
-	if (xscale->trace.buffer_enabled)
-	{
-		/* if we enable the trace buffer in fill-once
-		 * mode we know the address of the first instruction */
-		xscale->trace.pc_ok = 1;
-		xscale->trace.current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
-	}
-	else
-	{
-		/* otherwise the address is unknown, and we have no known good PC */
-		xscale->trace.pc_ok = 0;
-	}
-
-	command_print(cmd_ctx, "trace buffer %s (%s)",
-		(xscale->trace.buffer_enabled) ? "enabled" : "disabled",
-		(xscale->trace.buffer_fill > 0) ? "fill" : "wrap");
-
-	dcsr_value = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 0, 32);
-	if (xscale->trace.buffer_fill >= 0)
-		xscale_write_dcsr_sw(target, (dcsr_value & 0xfffffffc) | 2);
-	else
-		xscale_write_dcsr_sw(target, dcsr_value & 0xfffffffc);
-
-	return ERROR_OK;
-}
-
-int xscale_handle_trace_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
-{
-	target_t *target;
-	armv4_5_common_t *armv4_5;
-	xscale_common_t *xscale;
-
-	if (argc < 1)
-	{
-		command_print(cmd_ctx, "usage: xscale trace_image <file> [base address] [type]");
-		return ERROR_OK;
-	}
-
-	target = get_current_target(cmd_ctx);
-
-	if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
-	{
-		return ERROR_OK;
-	}
-
-	if (xscale->trace.image)
-	{
-		image_close(xscale->trace.image);
-		free(xscale->trace.image);
-		command_print(cmd_ctx, "previously loaded image found and closed");
-	}
-
-	xscale->trace.image = malloc(sizeof(image_t));
-	xscale->trace.image->base_address_set = 0;
-	xscale->trace.image->start_address_set = 0;
-
-	/* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */
-	if (argc >= 2)
-	{
-		xscale->trace.image->base_address_set = 1;
-		xscale->trace.image->base_address = strtoul(args[1], NULL, 0);
-	}
-	else
-	{
-		xscale->trace.image->base_address_set = 0;
-	}
-
-	if (image_open(xscale->trace.image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "image opening error: %s", xscale->trace.image->error_str);
-		free(xscale->trace.image);
-		xscale->trace.image = NULL;
-		return ERROR_OK;
-	}
-
-	return ERROR_OK;
-}
-
-int xscale_handle_dump_trace_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;
-	xscale_trace_data_t *trace_data;
-	fileio_t file;
-
-	if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
-	{
-		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)
-	{
-		command_print(cmd_ctx, "usage: xscale dump_trace <file>");
-		return ERROR_OK;
-	}
-
-	trace_data = xscale->trace.data;
-
-	if (!trace_data)
-	{
-		command_print(cmd_ctx, "no trace data collected");
-		return ERROR_OK;
-	}
-
-	if (fileio_open(&file, args[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK)
-	{
-		command_print(cmd_ctx, "file open error: %s", file.error_str);
-		return ERROR_OK;
-	}
-
-	while (trace_data)
-	{
-		int i;
-
-		fileio_write_u32(&file, trace_data->chkpt0);
-		fileio_write_u32(&file, trace_data->chkpt1);
-		fileio_write_u32(&file, trace_data->last_instruction);
-		fileio_write_u32(&file, trace_data->depth);
-
-		for (i = 0; i < trace_data->depth; i++)
-			fileio_write_u32(&file, trace_data->entries[i].data | ((trace_data->entries[i].type & 0xffff) << 16));
-
-		trace_data = trace_data->next;
-	}
-
-	fileio_close(&file);
-
-	return ERROR_OK;
-}
-
-int xscale_handle_analyze_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;
-
-	if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
-	{
-		return ERROR_OK;
-	}
-
-	xscale_analyze_trace(target, cmd_ctx);
-
-	return ERROR_OK;
-}
-
-int xscale_handle_cp15(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)
-	{
-		return ERROR_OK;
-	}
-	
-	if (target->state != TARGET_HALTED)
-	{
-		command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
-		return ERROR_OK;
-	}
-	u32 reg_no = 0;
-	reg_t *reg = NULL;
-	if(argc > 0)
-	{
-		reg_no = strtoul(args[0], NULL, 0);
-		/*translate from xscale cp15 register no to openocd register*/
-		switch(reg_no)
-		{
-		case 0:
-			reg_no = XSCALE_MAINID;
-			break;
-		case 1:
-			reg_no = XSCALE_CTRL;
-			break;
-		case 2:
-			reg_no = XSCALE_TTB;
-			break; 
-		case 3:
-			reg_no = XSCALE_DAC;
-			break;
-		case 5:
-			reg_no = XSCALE_FSR;
-			break;
-		case 6:
-			reg_no = XSCALE_FAR;
-			break;
-		case 13:
-			reg_no = XSCALE_PID;
-			break;
-		case 15:
-			reg_no = XSCALE_CPACCESS;
-			break;
-		default:
-			command_print(cmd_ctx, "invalid register number");
-			return ERROR_INVALID_ARGUMENTS;
-		}
-		reg = &xscale->reg_cache->reg_list[reg_no];
-		
-	}
-	if(argc == 1)
-	{
-		u32 value;
-		
-		/* read cp15 control register */
-		xscale_get_reg(reg);
-		value = buf_get_u32(reg->value, 0, 32);
-		command_print(cmd_ctx, "%s (/%i): 0x%x", reg->name, reg->size, value);
-	}
-	else if(argc == 2)
-	{   
-
-		u32 value = strtoul(args[1], NULL, 0);
-		
-		/* send CP write request (command 0x41) */
-		xscale_send_u32(target, 0x41);
-		
-		/* send CP register number */
-		xscale_send_u32(target, reg_no);
-		
-		/* send CP register value */
-		xscale_send_u32(target, value);
-		
-		/* execute cpwait to ensure outstanding operations complete */
-		xscale_send_u32(target, 0x53);
-	}
-	else
-	{
-		command_print(cmd_ctx, "usage: cp15 [register]<, [value]>");	
-	}
-	
-	return ERROR_OK;
-}
-
-int handle_xscale_fast_memory_access_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)
-	{
-		return ERROR_OK;
-	}
-	
-	if (argc == 1)
-	{
-		if (strcmp("enable", args[0]) == 0)
-		{
-			xscale->fast_memory_access = 1;
-		}
-		else if (strcmp("disable", args[0]) == 0)
-		{
-			xscale->fast_memory_access = 0;
-		}
-		else
-		{
-			return ERROR_COMMAND_SYNTAX_ERROR;
-		}
-	} else if (argc!=0)
-	{
-		return ERROR_COMMAND_SYNTAX_ERROR;
-	}
-		
-	command_print(cmd_ctx, "fast memory access is %s", (xscale->fast_memory_access) ? "enabled" : "disabled");
-
-	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_ANY, "'xscale debug_handler <target#> <address>' command takes two required operands");
-	register_command(cmd_ctx, xscale_cmd, "cache_clean_address", xscale_handle_cache_clean_address_command, COMMAND_ANY, NULL);
-
-	register_command(cmd_ctx, xscale_cmd, "cache_info", xscale_handle_cache_info_command, COMMAND_EXEC, NULL);
-	register_command(cmd_ctx, xscale_cmd, "mmu", xscale_handle_mmu_command, COMMAND_EXEC, "['enable'|'disable'] the MMU");
-	register_command(cmd_ctx, xscale_cmd, "icache", xscale_handle_idcache_command, COMMAND_EXEC, "['enable'|'disable'] the ICache");
-	register_command(cmd_ctx, xscale_cmd, "dcache", xscale_handle_idcache_command, COMMAND_EXEC, "['enable'|'disable'] the DCache");
-
-	register_command(cmd_ctx, xscale_cmd, "vector_catch", xscale_handle_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' [n]|'wrap']");
-
-	register_command(cmd_ctx, xscale_cmd, "dump_trace", xscale_handle_dump_trace_command, COMMAND_EXEC, "dump content of trace buffer to <file>");
-	register_command(cmd_ctx, xscale_cmd, "analyze_trace", xscale_handle_analyze_trace_buffer_command, COMMAND_EXEC, "analyze content of trace buffer");
-	register_command(cmd_ctx, xscale_cmd, "trace_image", xscale_handle_trace_image_command,
-		COMMAND_EXEC, "load image from <file> [base address]");
-
-	register_command(cmd_ctx, xscale_cmd, "cp15", xscale_handle_cp15, COMMAND_EXEC, "access coproc 15 <register> [value]");
-	register_command(cmd_ctx, xscale_cmd, "fast_memory_access", handle_xscale_fast_memory_access_command,
-		 COMMAND_ANY, "use fast memory accesses instead of slower but potentially unsafe slow accesses <enable|disable>");
-	
-	armv4_5_register_commands(cmd_ctx);
-
-	return ERROR_OK;
-}
+/***************************************************************************
+ *   Copyright (C) 2006, 2007 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 "replacements.h"
+
+#include "xscale.h"
+
+#include "register.h"
+#include "target.h"
+#include "armv4_5.h"
+#include "arm_simulator.h"
+#include "arm_disassembler.h"
+#include "log.h"
+#include "jtag.h"
+#include "binarybuffer.h"
+#include "time_support.h"
+#include "breakpoints.h"
+#include "fileio.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <sys/types.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);
+int xscale_poll(target_t *target);
+int xscale_halt(target_t *target);
+int xscale_resume(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution);
+int xscale_step(struct target_s *target, int current, u32 address, int handle_breakpoints);
+int xscale_debug_entry(target_t *target);
+int xscale_restore_context(target_t *target);
+
+int xscale_assert_reset(target_t *target);
+int xscale_deassert_reset(target_t *target);
+int xscale_soft_reset_halt(struct target_s *target);
+int xscale_prepare_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_checksum_memory(struct target_s *target, u32 address, u32 count, u32* checksum);
+
+int xscale_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
+int xscale_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
+int xscale_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
+int xscale_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint);
+int xscale_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint);
+int xscale_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoint);
+void xscale_enable_watchpoints(struct target_s *target);
+void xscale_enable_breakpoints(struct target_s *target);
+static int xscale_virt2phys(struct target_s *target, u32 virtual, u32 *physical);
+static int xscale_mmu(struct target_s *target, int *enabled);
+
+int xscale_read_trace(target_t *target);
+
+target_type_t xscale_target =
+{
+	.name = "xscale",
+
+	.poll = xscale_poll,
+	.arch_state = xscale_arch_state,
+
+	.target_request_data = NULL,
+
+	.halt = xscale_halt,
+	.resume = xscale_resume,
+	.step = xscale_step,
+
+	.assert_reset = xscale_assert_reset,
+	.deassert_reset = xscale_deassert_reset,
+	.soft_reset_halt = xscale_soft_reset_halt,
+	.prepare_reset_halt = xscale_prepare_reset_halt,
+
+	.get_gdb_reg_list = armv4_5_get_gdb_reg_list,
+
+	.read_memory = xscale_read_memory,
+	.write_memory = xscale_write_memory,
+	.bulk_write_memory = xscale_bulk_write_memory,
+	.checksum_memory = xscale_checksum_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,
+	
+	.virt2phys = xscale_virt2phys,
+	.mmu = xscale_mmu
+};
+
+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)
+	{
+		ERROR("target isn't an XScale target");
+		return -1;
+	}
+
+	if (xscale->common_magic != XSCALE_COMMON_MAGIC)
+	{
+		ERROR("target isn't an XScale target");
+		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;
+		jtag_set_check_value(&field, device->expected, device->expected_mask, 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;
+	jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, 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;
+	jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, NULL);
+
+	jtag_add_dr_scan(3, fields, -1);
+
+	if ((retval = jtag_execute_queue()) != ERROR_OK)
+	{
+		ERROR("JTAG error while reading DCSR");
+		return retval;
+	}
+
+	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)
+{
+	int retval = ERROR_OK;
+	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;
+
+	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; */
+	jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, 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;
+	jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, 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 */
+	int attempts = 0;
+	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");
+			break;
+		}
+
+		/* 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--;
+			}
+		}
+		if (words_scheduled == 0)
+		{
+			if (attempts++ == 1000)
+			{
+				ERROR("Failed to receiving data from debug handler after 1000 attempts");
+				retval = ERROR_JTAG_QUEUE_FAILED;
+				break;
+			}
+		}
+		
+		words_done += words_scheduled;
+	}
+
+	for (i = 0; i < num_words; i++)
+		*(buffer++) = buf_get_u32((u8*)&field1[i], 0, 32);
+
+	free(field1);
+
+	return retval;
+}
+
+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];
+	enum tap_state noconsume_path[9];
+
+	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;
+
+	noconsume_path[0] = TAP_SDS;
+	noconsume_path[1] = TAP_CD;
+	noconsume_path[2] = TAP_E1D;
+	noconsume_path[3] = TAP_PD;
+	noconsume_path[4] = TAP_E2D;
+	noconsume_path[5] = TAP_UD;
+	noconsume_path[6] = TAP_SDS;
+	noconsume_path[7] = TAP_CD;
+	noconsume_path[8] = 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;
+	jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, 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;
+	jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, 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_pathmove(sizeof(noconsume_path)/sizeof(*noconsume_path), noconsume_path);
+
+		jtag_add_dr_scan(3, fields, TAP_RTI);
+
+		if ((retval = jtag_execute_queue()) != ERROR_OK)
+		{
+			ERROR("JTAG error while reading TX");
+			return ERROR_TARGET_TIMEOUT;
+		}
+
+		gettimeofday(&now, NULL);
+		if ((now.tv_sec > timeout.tv_sec) || ((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;
+	jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, 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;
+	jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, NULL);
+
+	gettimeofday(&timeout, NULL);
+	timeval_add_time(&timeout, 5, 0);
+
+	/* poll until rx_read is low */
+	DEBUG("polling RX");
+	do
+	{
+		jtag_add_dr_scan(3, fields, TAP_RTI);
+
+		if ((retval = jtag_execute_queue()) != ERROR_OK)
+		{
+			ERROR("JTAG error while writing RX");
+			return retval;
+		}
+
+		gettimeofday(&now, NULL);
+		if ((now.tv_sec > timeout.tv_sec) || ((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");
+		return retval;
+	}
+
+	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_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_handler = NULL;
+	if (!xscale->fast_memory_access)
+	{
+		jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, 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_handler = NULL;
+	if (!xscale->fast_memory_access)
+	{
+		jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, NULL);
+	}
+
+	if (size==4)
+	{
+		int endianness = target->endianness;
+		while (done_count++ < count)
+		{
+			if (endianness == TARGET_LITTLE_ENDIAN)
+			{
+				output[0]=buffer[0];
+				output[1]=buffer[1];
+				output[2]=buffer[2];
+				output[3]=buffer[3];
+			} else
+			{
+				output[0]=buffer[3];
+				output[1]=buffer[2];
+				output[2]=buffer[1];
+				output[3]=buffer[0];
+			}
+			jtag_add_dr_scan(3, fields, TAP_RTI);
+			buffer += size;
+		}
+		
+	} else
+	{
+		while (done_count++ < count)
+		{
+		/* extract sized element from target-endian buffer, and put it
+		 * into little-endian output buffer
+		 */
+		switch (size)
+		{
+			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");
+		return retval;
+	}
+
+	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;
+	jtag_set_check_value(fields+0, &field0_check_value, &field0_check_mask, 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;
+	jtag_set_check_value(fields+2, &field2_check_value, &field2_check_mask, NULL);
+
+	jtag_add_dr_scan(3, fields, -1);
+
+	if ((retval = jtag_execute_queue()) != ERROR_OK)
+	{
+		ERROR("JTAG error while writing DCSR");
+		return retval;
+	}
+
+	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)
+{
+	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);
+	}
+
+	USER("target halted in %s state due to %s, current mode: %s\n"
+			"cpsr: 0x%8.8x pc: 0x%8.8x\n"
+			"MMU: %s, D-Cache: %s, I-Cache: %s"
+			"%s",
+			 armv4_5_state_strings[armv4_5->core_state],
+			 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;
+}
+
+int xscale_poll(target_t *target)
+{
+	int retval=ERROR_OK;
+	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))
+	{
+		enum target_state previous_state = target->state;
+		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;
+
+			target->state = TARGET_HALTED;
+
+			/* process debug entry, fetching current mode regs */
+			retval = xscale_debug_entry(target);
+		}
+		else if (retval != ERROR_TARGET_RESOURCE_NOT_AVAILABLE)
+		{
+			USER("error while polling TX register, reset CPU");
+			/* here we "lie" so GDB won't get stuck and a reset can be perfomed */
+			target->state = TARGET_HALTED;
+		}
+
+			/* debug_entry could have overwritten target state (i.e. immediate resume)
+			 * don't signal event handlers in that case
+			 */
+		if (target->state != TARGET_HALTED)
+			return ERROR_OK;
+
+		/* if target was running, signal that we halted
+		 * otherwise we reentered from debug execution */
+		if (previous_state == TARGET_RUNNING)
+			target_call_event_callbacks(target, TARGET_EVENT_HALTED);
+		else
+			target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED);
+	}
+	return retval;
+}
+
+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[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;
+
+	/* tracing enabled, read collected trace data */
+	if (xscale->trace.buffer_enabled)
+	{
+		xscale_read_trace(target);
+		xscale->trace.buffer_fill--;
+
+		/* resume if we're still collecting trace data */
+		if ((xscale->arch_debug_reason == XSCALE_DBG_REASON_TB_FULL)
+			&& (xscale->trace.buffer_fill > 0))
+		{
+			xscale_resume(target, 1, 0x0, 1, 0);
+		}
+		else
+		{
+			xscale->trace.buffer_enabled = 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");
+		return ERROR_TARGET_INVALID;
+	}
+	else if (target->state == TARGET_RESET)
+	{
+		DEBUG("target->state == TARGET_RESET");
+	}
+	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]);
+
+	/* select DCSR instruction (set endstate to R-T-I to ensure we don't
+	 * end up in T-L-R, which would reset JTAG
+	 */
+	jtag_add_end_state(TAP_RTI);
+	xscale_jtag_set_instr(xscale->jtag_info.chain_pos, xscale->jtag_info.dcsr);
+
+	/* 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);
+
+	/* select BYPASS, because having DCSR selected caused problems on the PXA27x */
+	xscale_jtag_set_instr(xscale->jtag_info.chain_pos, 0x7f);
+	jtag_execute_queue();
+
+	/* assert reset */
+	jtag_add_reset(0, 1);
+
+	/* sleep 1ms, to be sure we fulfill any requirements */
+	jtag_add_sleep(1000);
+	jtag_execute_queue();
+
+	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;
+
+	fileio_t debug_handler;
+	u32 address;
+	u32 binary_size;
+
+	u32 buf_cnt;
+	int i;
+	int retval;
+
+	breakpoint_t *breakpoint = target->breakpoints;
+
+	DEBUG("-");
+
+	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 SRST */
+		jtag_add_reset(0, 0);
+
+		/* wait 300ms; 150 and 100ms were not enough */
+		jtag_add_sleep(300*1000);
+
+		jtag_add_runtest(2030, TAP_RTI);
+		jtag_execute_queue();
+
+		/* 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);
+
+		/* Load debug handler */
+		if (fileio_open(&debug_handler, PKGLIBDIR "/xscale/debug_handler.bin", FILEIO_READ, FILEIO_BINARY) != ERROR_OK)
+		{
+			ERROR("file open error: %s", debug_handler.error_str);
+			return ERROR_OK;
+		}
+
+		if ((binary_size = debug_handler.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)
+		{
+			u32 cache_line[8];
+			u8 buffer[32];
+
+			if ((retval = fileio_read(&debug_handler, 32, buffer, &buf_cnt)) != ERROR_OK)
+			{
+				ERROR("reading debug handler failed: %s", debug_handler.error_str);
+			}
+
+			for (i = 0; i < buf_cnt; i += 4)
+			{
+				/* convert LE buffer to host-endian u32 */
+				cache_line[i / 4] = le_to_h_u32(&buffer[i]);
+			}
+
+			for (; buf_cnt < 32; buf_cnt += 4)
+			{
+					cache_line[buf_cnt / 4] = 0xe1a08008;
+			}
+
+			/* only load addresses other than the reset vectors */
+			if ((address % 0x400) != 0x0)
+			{
+				xscale_load_ic(target, 1, address, cache_line);
+			}
+
+			address += buf_cnt;
+			binary_size -= buf_cnt;
+		};
+
+		xscale_load_ic(target, 1, 0x0, xscale->low_vectors);
+		xscale_load_ic(target, 1, 0xffff0000, xscale->high_vectors);
+
+		jtag_add_runtest(30, TAP_RTI);
+
+		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);
+
+		/* clear Hold reset to let the target run (should enter debug handler) */
+		xscale_write_dcsr(target, 0, 1);
+		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;
+
+			/* resume the target */
+			xscale_resume(target, 1, 0x0, 1, 0);
+		}
+
+		fileio_close(&debug_handler);
+	}
+	else
+	{
+		jtag_add_reset(0, 0);
+	}
+
+
+	return ERROR_OK;
+}
+
+int xscale_soft_reset_halt(struct target_s *target)
+{
+
+	return ERROR_OK;
+}
+
+int xscale_prepare_reset_halt(struct target_s *target)
+{
+	/* nothing to be done for reset_halt on XScale targets
+	 * we always halt after a reset to upload the debug handler
+	 */
+	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)
+{
+	return xscale_write_memory(target, address, 4, count, buffer);
+}
+
+int xscale_checksum_memory(struct target_s *target, u32 address, u32 count, u32* checksum)
+{
+	return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
+}
+
+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 = 0;
+	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;
+}
+
+int xscale_read_trace(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;
+	xscale_trace_data_t **trace_data_p;
+
+	/* 258 words from debug handler
+	 * 256 trace buffer entries
+	 * 2 checkpoint addresses
+	 */
+	u32 trace_buffer[258];
+	int is_address[256];
+	int i, j;
+
+	if (target->state != TARGET_HALTED)
+	{
+		WARNING("target must be stopped to read trace data");
+		return ERROR_TARGET_NOT_HALTED;
+	}
+
+	/* send read trace buffer command (command 0x61) */
+	xscale_send_u32(target, 0x61);
+
+	/* receive trace buffer content */
+	xscale_receive(target, trace_buffer, 258);
+
+	/* parse buffer backwards to identify address entries */
+	for (i = 255; i >= 0; i--)
+	{
+		is_address[i] = 0;
+		if (((trace_buffer[i] & 0xf0) == 0x90) ||
+			((trace_buffer[i] & 0xf0) == 0xd0))
+		{
+			if (i >= 3)
+				is_address[--i] = 1;
+			if (i >= 2)
+				is_address[--i] = 1;
+			if (i >= 1)
+				is_address[--i] = 1;
+			if (i >= 0)
+				is_address[--i] = 1;
+		}
+	}
+
+
+	/* search first non-zero entry */
+	for (j = 0; (j < 256) && (trace_buffer[j] == 0) && (!is_address[j]); j++)
+		;
+
+	if (j == 256)
+	{
+		DEBUG("no trace data collected");
+		return ERROR_XSCALE_NO_TRACE_DATA;
+	}
+
+	for (trace_data_p = &xscale->trace.data; *trace_data_p; trace_data_p = &(*trace_data_p)->next)
+		;
+
+	*trace_data_p = malloc(sizeof(xscale_trace_data_t));
+	(*trace_data_p)->next = NULL;
+	(*trace_data_p)->chkpt0 = trace_buffer[256];
+	(*trace_data_p)->chkpt1 = trace_buffer[257];
+	(*trace_data_p)->last_instruction = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
+	(*trace_data_p)->entries = malloc(sizeof(xscale_trace_entry_t) * (256 - j));
+	(*trace_data_p)->depth = 256 - j;
+
+	for (i = j; i < 256; i++)
+	{
+		(*trace_data_p)->entries[i - j].data = trace_buffer[i];
+		if (is_address[i])
+			(*trace_data_p)->entries[i - j].type = XSCALE_TRACE_ADDRESS;
+		else
+			(*trace_data_p)->entries[i - j].type = XSCALE_TRACE_MESSAGE;
+	}
+
+	return ERROR_OK;
+}
+
+int xscale_read_instruction(target_t *target, arm_instruction_t *instruction)
+{
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	xscale_common_t *xscale = armv4_5->arch_info;
+	int i;
+	int section = -1;
+	u32 size_read;
+	u32 opcode;
+	int retval;
+
+	if (!xscale->trace.image)
+		return ERROR_TRACE_IMAGE_UNAVAILABLE;
+
+	/* search for the section the current instruction belongs to */
+	for (i = 0; i < xscale->trace.image->num_sections; i++)
+	{
+		if ((xscale->trace.image->sections[i].base_address <= xscale->trace.current_pc) &&
+			(xscale->trace.image->sections[i].base_address + xscale->trace.image->sections[i].size > xscale->trace.current_pc))
+		{
+			section = i;
+			break;
+		}
+	}
+
+	if (section == -1)
+	{
+		/* current instruction couldn't be found in the image */
+		return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
+	}
+
+	if (xscale->trace.core_state == ARMV4_5_STATE_ARM)
+	{
+		u8 buf[4];
+		if ((retval = image_read_section(xscale->trace.image, section,
+			xscale->trace.current_pc - xscale->trace.image->sections[section].base_address,
+			4, buf, &size_read)) != ERROR_OK)
+		{
+			ERROR("error while reading instruction: %i", retval);
+			return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
+		}
+		opcode = target_buffer_get_u32(target, buf);
+		arm_evaluate_opcode(opcode, xscale->trace.current_pc, instruction);
+	}
+	else if (xscale->trace.core_state == ARMV4_5_STATE_THUMB)
+	{
+		u8 buf[2];
+		if ((retval = image_read_section(xscale->trace.image, section,
+			xscale->trace.current_pc - xscale->trace.image->sections[section].base_address,
+			2, buf, &size_read)) != ERROR_OK)
+		{
+			ERROR("error while reading instruction: %i", retval);
+			return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;
+		}
+		opcode = target_buffer_get_u16(target, buf);
+		thumb_evaluate_opcode(opcode, xscale->trace.current_pc, instruction);
+	}
+	else
+	{
+		ERROR("BUG: unknown core state encountered");
+		exit(-1);
+	}
+
+	return ERROR_OK;
+}
+
+int xscale_branch_address(xscale_trace_data_t *trace_data, int i, u32 *target)
+{
+	/* if there are less than four entries prior to the indirect branch message
+	 * we can't extract the address */
+	if (i < 4)
+	{
+		return -1;
+	}
+
+	*target = (trace_data->entries[i-1].data) | (trace_data->entries[i-2].data << 8) |
+				(trace_data->entries[i-3].data << 16) | (trace_data->entries[i-4].data << 24);
+
+	return 0;
+}
+
+int xscale_analyze_trace(target_t *target, command_context_t *cmd_ctx)
+{
+	/* get pointers to arch-specific information */
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	xscale_common_t *xscale = armv4_5->arch_info;
+	int next_pc_ok = 0;
+	u32 next_pc = 0x0;
+	xscale_trace_data_t *trace_data = xscale->trace.data;
+	int retval;
+
+	while (trace_data)
+	{
+		int i, chkpt;
+		int rollover;
+		int branch;
+		int exception;
+		xscale->trace.core_state = ARMV4_5_STATE_ARM;
+
+		chkpt = 0;
+		rollover = 0;
+
+		for (i = 0; i < trace_data->depth; i++)
+		{
+			next_pc_ok = 0;
+			branch = 0;
+			exception = 0;
+
+			if (trace_data->entries[i].type == XSCALE_TRACE_ADDRESS)
+				continue;
+
+			switch ((trace_data->entries[i].data & 0xf0) >> 4)
+			{
+				case 0:		/* Exceptions */
+				case 1:
+				case 2:
+				case 3:
+				case 4:
+				case 5:
+				case 6:
+				case 7:
+					exception = (trace_data->entries[i].data & 0x70) >> 4;
+					next_pc_ok = 1;
+					next_pc = (trace_data->entries[i].data & 0xf0) >> 2;
+					command_print(cmd_ctx, "--- exception %i ---", (trace_data->entries[i].data & 0xf0) >> 4);
+					break;
+				case 8:		/* Direct Branch */
+					branch = 1;
+					break;
+				case 9:		/* Indirect Branch */
+					branch = 1;
+					if (xscale_branch_address(trace_data, i, &next_pc) == 0)
+					{
+						next_pc_ok = 1;
+					}
+					break;
+				case 13:	/* Checkpointed Indirect Branch */
+					if (xscale_branch_address(trace_data, i, &next_pc) == 0)
+					{
+						next_pc_ok = 1;
+						if (((chkpt == 0) && (next_pc != trace_data->chkpt0))
+							|| ((chkpt == 1) && (next_pc != trace_data->chkpt1)))
+							WARNING("checkpointed indirect branch target address doesn't match checkpoint");
+					}
+					/* explicit fall-through */
+				case 12:	/* Checkpointed Direct Branch */
+					branch = 1;
+					if (chkpt == 0)
+					{
+						next_pc_ok = 1;
+						next_pc = trace_data->chkpt0;
+						chkpt++;
+					}
+					else if (chkpt == 1)
+					{
+						next_pc_ok = 1;
+						next_pc = trace_data->chkpt0;
+						chkpt++;
+					}
+					else
+					{
+						WARNING("more than two checkpointed branches encountered");
+					}
+					break;
+				case 15:	/* Roll-over */
+					rollover++;
+					continue;
+				default:	/* Reserved */
+					command_print(cmd_ctx, "--- reserved trace message ---");
+					ERROR("BUG: trace message %i is reserved", (trace_data->entries[i].data & 0xf0) >> 4);
+					return ERROR_OK;
+			}
+
+			if (xscale->trace.pc_ok)
+			{
+				int executed = (trace_data->entries[i].data & 0xf) + rollover * 16;
+				arm_instruction_t instruction;
+
+				if ((exception == 6) || (exception == 7))
+				{
+					/* IRQ or FIQ exception, no instruction executed */
+					executed -= 1;
+				}
+
+				while (executed-- >= 0)
+				{
+					if ((retval = xscale_read_instruction(target, &instruction)) != ERROR_OK)
+					{
+						/* can't continue tracing with no image available */
+						if (retval == ERROR_TRACE_IMAGE_UNAVAILABLE)
+						{
+							return retval;
+						}
+						else if (retval == ERROR_TRACE_INSTRUCTION_UNAVAILABLE)
+						{
+							/* TODO: handle incomplete images */
+						}
+					}
+
+					/* a precise abort on a load to the PC is included in the incremental
+					 * word count, other instructions causing data aborts are not included
+					 */
+					if ((executed == 0) && (exception == 4)
+						&& ((instruction.type >= ARM_LDR) && (instruction.type <= ARM_LDM)))
+					{
+						if ((instruction.type == ARM_LDM)
+							&& ((instruction.info.load_store_multiple.register_list & 0x8000) == 0))
+						{
+							executed--;
+						}
+						else if (((instruction.type >= ARM_LDR) && (instruction.type <= ARM_LDRSH))
+							&& (instruction.info.load_store.Rd != 15))
+						{
+							executed--;
+						}
+					}
+
+					/* only the last instruction executed
+					 * (the one that caused the control flow change)
+					 * could be a taken branch
+					 */
+					if (((executed == -1) && (branch == 1)) &&
+						(((instruction.type == ARM_B) ||
+							(instruction.type == ARM_BL) ||
+							(instruction.type == ARM_BLX)) &&
+							(instruction.info.b_bl_bx_blx.target_address != -1)))
+					{
+						xscale->trace.current_pc = instruction.info.b_bl_bx_blx.target_address;
+					}
+					else
+					{
+						xscale->trace.current_pc += (xscale->trace.core_state == ARMV4_5_STATE_ARM) ? 4 : 2;
+					}
+					command_print(cmd_ctx, "%s", instruction.text);
+				}
+
+				rollover = 0;
+			}
+
+			if (next_pc_ok)
+			{
+				xscale->trace.current_pc = next_pc;
+				xscale->trace.pc_ok = 1;
+			}
+		}
+
+		for (; xscale->trace.current_pc < trace_data->last_instruction; xscale->trace.current_pc += (xscale->trace.core_state == ARMV4_5_STATE_ARM) ? 4 : 2)
+		{
+			arm_instruction_t instruction;
+			if ((retval = xscale_read_instruction(target, &instruction)) != ERROR_OK)
+			{
+				/* can't continue tracing with no image available */
+				if (retval == ERROR_TRACE_IMAGE_UNAVAILABLE)
+				{
+					return retval;
+				}
+				else if (retval == ERROR_TRACE_INSTRUCTION_UNAVAILABLE)
+				{
+					/* TODO: handle incomplete images */
+				}
+			}
+			command_print(cmd_ctx, "%s", instruction.text);
+		}
+
+		trace_data = trace_data->next;
+	}
+
+	return ERROR_OK;
+}
+
+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");
+	}
+
+	/* assert TRST once during startup */
+	jtag_add_reset(1, 0);
+	jtag_add_sleep(5000);
+	jtag_add_reset(0, 0);
+	jtag_execute_queue();
+
+	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.capture_status = TRACE_IDLE;
+	xscale->trace.data = NULL;
+	xscale->trace.image = NULL;
+	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;
+
+	xscale->fast_memory_access = 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>");
+		return ERROR_OK;
+	}
+
+	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)
+	{
+		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)
+	{
+		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)
+	{
+		return ERROR_OK;
+	}
+
+	return armv4_5_handle_cache_info_command(cmd_ctx, &xscale->armv4_5_mmu.armv4_5_cache);
+}
+
+static int xscale_virt2phys(struct target_s *target, u32 virtual, u32 *physical)
+{
+	armv4_5_common_t *armv4_5;
+	xscale_common_t *xscale;
+	int retval;
+	int type;
+	u32 cb;
+	int domain;
+	u32 ap;
+	
+	if ((retval = xscale_get_arch_pointers(target, &armv4_5, &xscale)) != ERROR_OK)
+	{
+		return retval;
+	}
+	u32 ret = armv4_5_mmu_translate_va(target, &xscale->armv4_5_mmu, virtual, &type, &cb, &domain, &ap);
+	if (type == -1)
+	{
+		return ret;
+	}
+	
+	*physical = ret;
+	return ERROR_OK;
+}
+
+static int xscale_mmu(struct target_s *target, int *enabled)
+{
+	armv4_5_common_t *armv4_5 = target->arch_info;
+	xscale_common_t *xscale = armv4_5->arch_info;
+
+	if (target->state != TARGET_HALTED)
+	{
+		ERROR("Target not halted");
+		return ERROR_TARGET_INVALID;
+	}
+	
+	*enabled = xscale->armv4_5_mmu.mmu_enabled;
+	return ERROR_OK;
+}
+
+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)
+	{
+		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)
+	{
+		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)
+	{
+		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)
+	{
+		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)
+	{
+		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_data_t *td, *next_td;
+		xscale->trace.buffer_enabled = 1;
+
+		/* free old trace data */
+		td = xscale->trace.data;
+		while (td)
+		{
+			next_td = td->next;
+
+			if (td->entries)
+				free(td->entries);
+			free(td);
+			td = next_td;
+		}
+		xscale->trace.data = NULL;
+	}
+	else if ((argc >= 1) && (strcmp("disable", args[0]) == 0))
+	{
+		xscale->trace.buffer_enabled = 0;
+	}
+
+	if ((argc >= 2) && (strcmp("fill", args[1]) == 0))
+	{
+		if (argc >= 3)
+			xscale->trace.buffer_fill = strtoul(args[2], NULL, 0);
+		else
+			xscale->trace.buffer_fill = 1;
+	}
+	else if ((argc >= 2) && (strcmp("wrap", args[1]) == 0))
+	{
+		xscale->trace.buffer_fill = -1;
+	}
+
+	if (xscale->trace.buffer_enabled)
+	{
+		/* if we enable the trace buffer in fill-once
+		 * mode we know the address of the first instruction */
+		xscale->trace.pc_ok = 1;
+		xscale->trace.current_pc = buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32);
+	}
+	else
+	{
+		/* otherwise the address is unknown, and we have no known good PC */
+		xscale->trace.pc_ok = 0;
+	}
+
+	command_print(cmd_ctx, "trace buffer %s (%s)",
+		(xscale->trace.buffer_enabled) ? "enabled" : "disabled",
+		(xscale->trace.buffer_fill > 0) ? "fill" : "wrap");
+
+	dcsr_value = buf_get_u32(xscale->reg_cache->reg_list[XSCALE_DCSR].value, 0, 32);
+	if (xscale->trace.buffer_fill >= 0)
+		xscale_write_dcsr_sw(target, (dcsr_value & 0xfffffffc) | 2);
+	else
+		xscale_write_dcsr_sw(target, dcsr_value & 0xfffffffc);
+
+	return ERROR_OK;
+}
+
+int xscale_handle_trace_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
+{
+	target_t *target;
+	armv4_5_common_t *armv4_5;
+	xscale_common_t *xscale;
+
+	if (argc < 1)
+	{
+		command_print(cmd_ctx, "usage: xscale trace_image <file> [base address] [type]");
+		return ERROR_OK;
+	}
+
+	target = get_current_target(cmd_ctx);
+
+	if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
+	{
+		return ERROR_OK;
+	}
+
+	if (xscale->trace.image)
+	{
+		image_close(xscale->trace.image);
+		free(xscale->trace.image);
+		command_print(cmd_ctx, "previously loaded image found and closed");
+	}
+
+	xscale->trace.image = malloc(sizeof(image_t));
+	xscale->trace.image->base_address_set = 0;
+	xscale->trace.image->start_address_set = 0;
+
+	/* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */
+	if (argc >= 2)
+	{
+		xscale->trace.image->base_address_set = 1;
+		xscale->trace.image->base_address = strtoul(args[1], NULL, 0);
+	}
+	else
+	{
+		xscale->trace.image->base_address_set = 0;
+	}
+
+	if (image_open(xscale->trace.image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "image opening error: %s", xscale->trace.image->error_str);
+		free(xscale->trace.image);
+		xscale->trace.image = NULL;
+		return ERROR_OK;
+	}
+
+	return ERROR_OK;
+}
+
+int xscale_handle_dump_trace_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;
+	xscale_trace_data_t *trace_data;
+	fileio_t file;
+
+	if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
+	{
+		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)
+	{
+		command_print(cmd_ctx, "usage: xscale dump_trace <file>");
+		return ERROR_OK;
+	}
+
+	trace_data = xscale->trace.data;
+
+	if (!trace_data)
+	{
+		command_print(cmd_ctx, "no trace data collected");
+		return ERROR_OK;
+	}
+
+	if (fileio_open(&file, args[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK)
+	{
+		command_print(cmd_ctx, "file open error: %s", file.error_str);
+		return ERROR_OK;
+	}
+
+	while (trace_data)
+	{
+		int i;
+
+		fileio_write_u32(&file, trace_data->chkpt0);
+		fileio_write_u32(&file, trace_data->chkpt1);
+		fileio_write_u32(&file, trace_data->last_instruction);
+		fileio_write_u32(&file, trace_data->depth);
+
+		for (i = 0; i < trace_data->depth; i++)
+			fileio_write_u32(&file, trace_data->entries[i].data | ((trace_data->entries[i].type & 0xffff) << 16));
+
+		trace_data = trace_data->next;
+	}
+
+	fileio_close(&file);
+
+	return ERROR_OK;
+}
+
+int xscale_handle_analyze_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;
+
+	if (xscale_get_arch_pointers(target, &armv4_5, &xscale) != ERROR_OK)
+	{
+		return ERROR_OK;
+	}
+
+	xscale_analyze_trace(target, cmd_ctx);
+
+	return ERROR_OK;
+}
+
+int xscale_handle_cp15(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)
+	{
+		return ERROR_OK;
+	}
+	
+	if (target->state != TARGET_HALTED)
+	{
+		command_print(cmd_ctx, "target must be stopped for \"%s\" command", cmd);
+		return ERROR_OK;
+	}
+	u32 reg_no = 0;
+	reg_t *reg = NULL;
+	if(argc > 0)
+	{
+		reg_no = strtoul(args[0], NULL, 0);
+		/*translate from xscale cp15 register no to openocd register*/
+		switch(reg_no)
+		{
+		case 0:
+			reg_no = XSCALE_MAINID;
+			break;
+		case 1:
+			reg_no = XSCALE_CTRL;
+			break;
+		case 2:
+			reg_no = XSCALE_TTB;
+			break; 
+		case 3:
+			reg_no = XSCALE_DAC;
+			break;
+		case 5:
+			reg_no = XSCALE_FSR;
+			break;
+		case 6:
+			reg_no = XSCALE_FAR;
+			break;
+		case 13:
+			reg_no = XSCALE_PID;
+			break;
+		case 15:
+			reg_no = XSCALE_CPACCESS;
+			break;
+		default:
+			command_print(cmd_ctx, "invalid register number");
+			return ERROR_INVALID_ARGUMENTS;
+		}
+		reg = &xscale->reg_cache->reg_list[reg_no];
+		
+	}
+	if(argc == 1)
+	{
+		u32 value;
+		
+		/* read cp15 control register */
+		xscale_get_reg(reg);
+		value = buf_get_u32(reg->value, 0, 32);
+		command_print(cmd_ctx, "%s (/%i): 0x%x", reg->name, reg->size, value);
+	}
+	else if(argc == 2)
+	{   
+
+		u32 value = strtoul(args[1], NULL, 0);
+		
+		/* send CP write request (command 0x41) */
+		xscale_send_u32(target, 0x41);
+		
+		/* send CP register number */
+		xscale_send_u32(target, reg_no);
+		
+		/* send CP register value */
+		xscale_send_u32(target, value);
+		
+		/* execute cpwait to ensure outstanding operations complete */
+		xscale_send_u32(target, 0x53);
+	}
+	else
+	{
+		command_print(cmd_ctx, "usage: cp15 [register]<, [value]>");	
+	}
+	
+	return ERROR_OK;
+}
+
+int handle_xscale_fast_memory_access_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)
+	{
+		return ERROR_OK;
+	}
+	
+	if (argc == 1)
+	{
+		if (strcmp("enable", args[0]) == 0)
+		{
+			xscale->fast_memory_access = 1;
+		}
+		else if (strcmp("disable", args[0]) == 0)
+		{
+			xscale->fast_memory_access = 0;
+		}
+		else
+		{
+			return ERROR_COMMAND_SYNTAX_ERROR;
+		}
+	} else if (argc!=0)
+	{
+		return ERROR_COMMAND_SYNTAX_ERROR;
+	}
+		
+	command_print(cmd_ctx, "fast memory access is %s", (xscale->fast_memory_access) ? "enabled" : "disabled");
+
+	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_ANY, "'xscale debug_handler <target#> <address>' command takes two required operands");
+	register_command(cmd_ctx, xscale_cmd, "cache_clean_address", xscale_handle_cache_clean_address_command, COMMAND_ANY, NULL);
+
+	register_command(cmd_ctx, xscale_cmd, "cache_info", xscale_handle_cache_info_command, COMMAND_EXEC, NULL);
+	register_command(cmd_ctx, xscale_cmd, "mmu", xscale_handle_mmu_command, COMMAND_EXEC, "['enable'|'disable'] the MMU");
+	register_command(cmd_ctx, xscale_cmd, "icache", xscale_handle_idcache_command, COMMAND_EXEC, "['enable'|'disable'] the ICache");
+	register_command(cmd_ctx, xscale_cmd, "dcache", xscale_handle_idcache_command, COMMAND_EXEC, "['enable'|'disable'] the DCache");
+
+	register_command(cmd_ctx, xscale_cmd, "vector_catch", xscale_handle_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' [n]|'wrap']");
+
+	register_command(cmd_ctx, xscale_cmd, "dump_trace", xscale_handle_dump_trace_command, COMMAND_EXEC, "dump content of trace buffer to <file>");
+	register_command(cmd_ctx, xscale_cmd, "analyze_trace", xscale_handle_analyze_trace_buffer_command, COMMAND_EXEC, "analyze content of trace buffer");
+	register_command(cmd_ctx, xscale_cmd, "trace_image", xscale_handle_trace_image_command,
+		COMMAND_EXEC, "load image from <file> [base address]");
+
+	register_command(cmd_ctx, xscale_cmd, "cp15", xscale_handle_cp15, COMMAND_EXEC, "access coproc 15 <register> [value]");
+	register_command(cmd_ctx, xscale_cmd, "fast_memory_access", handle_xscale_fast_memory_access_command,
+		 COMMAND_ANY, "use fast memory accesses instead of slower but potentially unsafe slow accesses <enable|disable>");
+	
+	armv4_5_register_commands(cmd_ctx);
+
+	return ERROR_OK;
+}
diff --git a/src/xsvf/xsvf.c b/src/xsvf/xsvf.c
index 48ca0645484ae6937595ecc3be677403458886eb..298377d9d52c25053388a28f2b91c0053324ad70 100644
--- a/src/xsvf/xsvf.c
+++ b/src/xsvf/xsvf.c
@@ -188,9 +188,9 @@ int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, char **arg
 						field.in_handler = NULL;
 						field.in_handler_priv = NULL;
 						if (device == -1)
-							jtag_add_plain_ir_scan(1, &field, TAP_PI, NULL);
+							jtag_add_plain_ir_scan(1, &field, TAP_PI);
 						else
-							jtag_add_ir_scan(1, &field, TAP_PI, NULL);
+							jtag_add_ir_scan(1, &field, TAP_PI);
 						if (jtag_execute_queue() != ERROR_OK)
 						{
 							tdo_mismatch = 1;
@@ -228,9 +228,9 @@ int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, char **arg
 					field.in_value = NULL;
 					jtag_set_check_value(&field, dr_in_buf, dr_in_mask, NULL);
 					if (device == -1)
-						jtag_add_plain_dr_scan(1, &field, TAP_PD, NULL);
+						jtag_add_plain_dr_scan(1, &field, TAP_PD);
 					else
-						jtag_add_dr_scan(1, &field, TAP_PD, NULL);
+						jtag_add_dr_scan(1, &field, TAP_PD);
 					if (jtag_execute_queue() != ERROR_OK)
 					{
 						tdo_mismatch = 1;
@@ -302,9 +302,9 @@ int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, char **arg
 						field.in_value = NULL;
 						jtag_set_check_value(&field, dr_in_buf, dr_in_mask, NULL);
 						if (device == -1)
-							jtag_add_plain_dr_scan(1, &field, TAP_PD, NULL);
+							jtag_add_plain_dr_scan(1, &field, TAP_PD);
 						else
-							jtag_add_dr_scan(1, &field, TAP_PD, NULL);
+							jtag_add_dr_scan(1, &field, TAP_PD);
 						if (jtag_execute_queue() != ERROR_OK)
 						{
 							tdo_mismatch = 1;
@@ -428,9 +428,9 @@ int handle_xsvf_command(struct command_context_s *cmd_ctx, char *cmd, char **arg
 						field.in_handler = NULL;
 						field.in_handler_priv = NULL;
 						if (device == -1)
-							jtag_add_plain_ir_scan(1, &field, xsvf_to_tap[xendir], NULL);
+							jtag_add_plain_ir_scan(1, &field, xsvf_to_tap[xendir]);
 						else
-							jtag_add_ir_scan(1, &field, xsvf_to_tap[xendir], NULL);
+							jtag_add_ir_scan(1, &field, xsvf_to_tap[xendir]);
 					}
 					free(ir_buf);
 				}