- convert all files to unix line-ending
[openocd.git] / src / target / etm.c
index fe4ac77f6dd7386456b69edc828e17981a14a57d..8475a99fe9ca66a4c652118a3beef989a2253002 100644 (file)
-/***************************************************************************\r
- *   Copyright (C) 2005 by Dominic Rath                                    *\r
- *   Dominic.Rath@gmx.de                                                   *\r
- *                                                                         *\r
- *   This program is free software; you can redistribute it and/or modify  *\r
- *   it under the terms of the GNU General Public License as published by  *\r
- *   the Free Software Foundation; either version 2 of the License, or     *\r
- *   (at your option) any later version.                                   *\r
- *                                                                         *\r
- *   This program is distributed in the hope that it will be useful,       *\r
- *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *\r
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *\r
- *   GNU General Public License for more details.                          *\r
- *                                                                         *\r
- *   You should have received a copy of the GNU General Public License     *\r
- *   along with this program; if not, write to the                         *\r
- *   Free Software Foundation, Inc.,                                       *\r
- *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *\r
- ***************************************************************************/\r
-#ifdef HAVE_CONFIG_H\r
-#include "config.h"\r
-#endif\r
-\r
-#include <string.h>\r
-\r
-#include "etm.h"\r
-#include "etb.h"\r
-\r
-#include "armv4_5.h"\r
-#include "arm7_9_common.h"\r
-#include "arm_disassembler.h"\r
-#include "arm_simulator.h"\r
-\r
-#include "log.h"\r
-#include "arm_jtag.h"\r
-#include "types.h"\r
-#include "binarybuffer.h"\r
-#include "target.h"\r
-#include "register.h"\r
-#include "jtag.h"\r
-#include "fileio.h"\r
-\r
-#include <stdlib.h>\r
-\r
-/* ETM register access functionality \r
- * \r
- */\r
-\r
-bitfield_desc_t etm_comms_ctrl_bitfield_desc[] = \r
-{\r
-       {"R", 1},\r
-       {"W", 1},\r
-       {"reserved", 26},\r
-       {"version", 4}\r
-};\r
-\r
-int etm_reg_arch_info[] =\r
-{\r
-       0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,\r
-       0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,\r
-       0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, \r
-       0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, \r
-       0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,\r
-       0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, \r
-       0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,\r
-       0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,\r
-       0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, \r
-       0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, \r
-       0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,\r
-       0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,\r
-       0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x67, \r
-       0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, \r
-};\r
-\r
-int etm_reg_arch_size_info[] =\r
-{\r
-       32, 32, 17, 8, 3, 9, 32, 16,\r
-       17, 26, 25, 8, 17, 32, 32, 17,\r
-       32, 32, 32, 32, 32, 32, 32, 32, \r
-       32, 32, 32, 32, 32, 32, 32, 32, \r
-       7, 7, 7, 7, 7, 7, 7, 7, \r
-       7, 7, 7, 7, 7, 7, 7, 7, \r
-       32, 32, 32, 32, 32, 32, 32, 32, \r
-       32, 32, 32, 32, 32, 32, 32, 32, \r
-       32, 32, 32, 32, 32, 32, 32, 32, \r
-       32, 32, 32, 32, 32, 32, 32, 32, \r
-       16, 16, 16, 16, 18, 18, 18, 18,\r
-       17, 17, 17, 17, 16, 16, 16, 16,\r
-       17, 17, 17, 17, 17, 17, 2, \r
-       17, 17, 17, 17, 32, 32, 32, 32 \r
-};\r
-\r
-char* etm_reg_list[] =\r
-{\r
-       "ETM_CTRL",\r
-       "ETM_CONFIG",\r
-       "ETM_TRIG_EVENT",\r
-       "ETM_MMD_CTRL",\r
-       "ETM_STATUS",\r
-       "ETM_SYS_CONFIG",\r
-       "ETM_TRACE_RESOURCE_CTRL",\r
-       "ETM_TRACE_EN_CTRL2",\r
-       "ETM_TRACE_EN_EVENT",\r
-       "ETM_TRACE_EN_CTRL1",\r
-       "ETM_FIFOFULL_REGION",\r
-       "ETM_FIFOFULL_LEVEL",\r
-       "ETM_VIEWDATA_EVENT",\r
-       "ETM_VIEWDATA_CTRL1",\r
-       "ETM_VIEWDATA_CTRL2",\r
-       "ETM_VIEWDATA_CTRL3",\r
-       "ETM_ADDR_COMPARATOR_VALUE1",\r
-       "ETM_ADDR_COMPARATOR_VALUE2",\r
-       "ETM_ADDR_COMPARATOR_VALUE3",\r
-       "ETM_ADDR_COMPARATOR_VALUE4",\r
-       "ETM_ADDR_COMPARATOR_VALUE5",\r
-       "ETM_ADDR_COMPARATOR_VALUE6",\r
-       "ETM_ADDR_COMPARATOR_VALUE7",\r
-       "ETM_ADDR_COMPARATOR_VALUE8",\r
-       "ETM_ADDR_COMPARATOR_VALUE9",\r
-       "ETM_ADDR_COMPARATOR_VALUE10",\r
-       "ETM_ADDR_COMPARATOR_VALUE11",\r
-       "ETM_ADDR_COMPARATOR_VALUE12",\r
-       "ETM_ADDR_COMPARATOR_VALUE13",\r
-       "ETM_ADDR_COMPARATOR_VALUE14",\r
-       "ETM_ADDR_COMPARATOR_VALUE15",\r
-       "ETM_ADDR_COMPARATOR_VALUE16",\r
-       "ETM_ADDR_ACCESS_TYPE1",\r
-       "ETM_ADDR_ACCESS_TYPE2",\r
-       "ETM_ADDR_ACCESS_TYPE3",\r
-       "ETM_ADDR_ACCESS_TYPE4",\r
-       "ETM_ADDR_ACCESS_TYPE5",\r
-       "ETM_ADDR_ACCESS_TYPE6",\r
-       "ETM_ADDR_ACCESS_TYPE7",\r
-       "ETM_ADDR_ACCESS_TYPE8",\r
-       "ETM_ADDR_ACCESS_TYPE9",\r
-       "ETM_ADDR_ACCESS_TYPE10",\r
-       "ETM_ADDR_ACCESS_TYPE11",\r
-       "ETM_ADDR_ACCESS_TYPE12",\r
-       "ETM_ADDR_ACCESS_TYPE13",\r
-       "ETM_ADDR_ACCESS_TYPE14",\r
-       "ETM_ADDR_ACCESS_TYPE15",\r
-       "ETM_ADDR_ACCESS_TYPE16",\r
-       "ETM_DATA_COMPARATOR_VALUE1",\r
-       "ETM_DATA_COMPARATOR_VALUE2",\r
-       "ETM_DATA_COMPARATOR_VALUE3",\r
-       "ETM_DATA_COMPARATOR_VALUE4",\r
-       "ETM_DATA_COMPARATOR_VALUE5",\r
-       "ETM_DATA_COMPARATOR_VALUE6",\r
-       "ETM_DATA_COMPARATOR_VALUE7",\r
-       "ETM_DATA_COMPARATOR_VALUE8",\r
-       "ETM_DATA_COMPARATOR_VALUE9",\r
-       "ETM_DATA_COMPARATOR_VALUE10",\r
-       "ETM_DATA_COMPARATOR_VALUE11",\r
-       "ETM_DATA_COMPARATOR_VALUE12",\r
-       "ETM_DATA_COMPARATOR_VALUE13",\r
-       "ETM_DATA_COMPARATOR_VALUE14",\r
-       "ETM_DATA_COMPARATOR_VALUE15",\r
-       "ETM_DATA_COMPARATOR_VALUE16",\r
-       "ETM_DATA_COMPARATOR_MASK1",\r
-       "ETM_DATA_COMPARATOR_MASK2",\r
-       "ETM_DATA_COMPARATOR_MASK3",\r
-       "ETM_DATA_COMPARATOR_MASK4",\r
-       "ETM_DATA_COMPARATOR_MASK5",\r
-       "ETM_DATA_COMPARATOR_MASK6",\r
-       "ETM_DATA_COMPARATOR_MASK7",\r
-       "ETM_DATA_COMPARATOR_MASK8",\r
-       "ETM_DATA_COMPARATOR_MASK9",\r
-       "ETM_DATA_COMPARATOR_MASK10",\r
-       "ETM_DATA_COMPARATOR_MASK11",\r
-       "ETM_DATA_COMPARATOR_MASK12",\r
-       "ETM_DATA_COMPARATOR_MASK13",\r
-       "ETM_DATA_COMPARATOR_MASK14",\r
-       "ETM_DATA_COMPARATOR_MASK15",\r
-       "ETM_DATA_COMPARATOR_MASK16",\r
-       "ETM_COUNTER_INITAL_VALUE1",\r
-       "ETM_COUNTER_INITAL_VALUE2",\r
-       "ETM_COUNTER_INITAL_VALUE3",\r
-       "ETM_COUNTER_INITAL_VALUE4",\r
-       "ETM_COUNTER_ENABLE1",\r
-       "ETM_COUNTER_ENABLE2",\r
-       "ETM_COUNTER_ENABLE3",\r
-       "ETM_COUNTER_ENABLE4",\r
-       "ETM_COUNTER_RELOAD_VALUE1",\r
-       "ETM_COUNTER_RELOAD_VALUE2",\r
-       "ETM_COUNTER_RELOAD_VALUE3",\r
-       "ETM_COUNTER_RELOAD_VALUE4",\r
-       "ETM_COUNTER_VALUE1",\r
-       "ETM_COUNTER_VALUE2",\r
-       "ETM_COUNTER_VALUE3",\r
-       "ETM_COUNTER_VALUE4",\r
-       "ETM_SEQUENCER_CTRL1",\r
-       "ETM_SEQUENCER_CTRL2",\r
-       "ETM_SEQUENCER_CTRL3",\r
-       "ETM_SEQUENCER_CTRL4",\r
-       "ETM_SEQUENCER_CTRL5",\r
-       "ETM_SEQUENCER_CTRL6",\r
-       "ETM_SEQUENCER_STATE",\r
-       "ETM_EXTERNAL_OUTPUT1",\r
-       "ETM_EXTERNAL_OUTPUT2",\r
-       "ETM_EXTERNAL_OUTPUT3",\r
-       "ETM_EXTERNAL_OUTPUT4",\r
-       "ETM_CONTEXTID_COMPARATOR_VALUE1",\r
-       "ETM_CONTEXTID_COMPARATOR_VALUE2",\r
-       "ETM_CONTEXTID_COMPARATOR_VALUE3",\r
-       "ETM_CONTEXTID_COMPARATOR_MASK"\r
-};  \r
-\r
-int etm_reg_arch_type = -1;\r
-\r
-int etm_get_reg(reg_t *reg);\r
-int etm_set_reg(reg_t *reg, u32 value);\r
-int etm_set_reg_w_exec(reg_t *reg, u8 *buf);\r
-\r
-int etm_write_reg(reg_t *reg, u32 value);\r
-int etm_read_reg(reg_t *reg);\r
-\r
-command_t *etm_cmd = NULL;\r
-\r
-reg_cache_t* etm_build_reg_cache(target_t *target, arm_jtag_t *jtag_info, etm_context_t *etm_ctx)\r
-{\r
-       reg_cache_t *reg_cache = malloc(sizeof(reg_cache_t));\r
-       reg_t *reg_list = NULL;\r
-       etm_reg_t *arch_info = NULL;\r
-       int num_regs = sizeof(etm_reg_arch_info)/sizeof(int);\r
-       int i;\r
-       u32 etm_ctrl_value;\r
-       \r
-       /* register a register arch-type for etm registers only once */\r
-       if (etm_reg_arch_type == -1)\r
-               etm_reg_arch_type = register_reg_arch_type(etm_get_reg, etm_set_reg_w_exec);\r
-       \r
-       /* the actual registers are kept in two arrays */\r
-       reg_list = calloc(num_regs, sizeof(reg_t));\r
-       arch_info = calloc(num_regs, sizeof(etm_reg_t));\r
-       \r
-       /* fill in values for the reg cache */\r
-       reg_cache->name = "etm registers";\r
-       reg_cache->next = NULL;\r
-       reg_cache->reg_list = reg_list;\r
-       reg_cache->num_regs = num_regs;\r
-       \r
-       /* set up registers */\r
-       for (i = 0; i < num_regs; i++)\r
-       {\r
-               reg_list[i].name = etm_reg_list[i];\r
-               reg_list[i].size = 32;\r
-               reg_list[i].dirty = 0;\r
-               reg_list[i].valid = 0;\r
-               reg_list[i].bitfield_desc = NULL;\r
-               reg_list[i].num_bitfields = 0;\r
-               reg_list[i].value = calloc(1, 4);\r
-               reg_list[i].arch_info = &arch_info[i];\r
-               reg_list[i].arch_type = etm_reg_arch_type;\r
-               reg_list[i].size = etm_reg_arch_size_info[i];\r
-               arch_info[i].addr = etm_reg_arch_info[i];\r
-               arch_info[i].jtag_info = jtag_info;\r
-       }\r
-\r
-       /* initialize some ETM control register settings */     \r
-       etm_get_reg(&reg_list[ETM_CTRL]);\r
-       etm_ctrl_value = buf_get_u32(reg_list[ETM_CTRL].value, 0, reg_list[ETM_CTRL].size);\r
-       \r
-       /* clear the ETM powerdown bit (0) */\r
-       etm_ctrl_value &= ~0x1;\r
-               \r
-       /* configure port width (6:4), mode (17:16) and clocking (13) */\r
-       etm_ctrl_value = (etm_ctrl_value & \r
-               ~ETM_PORT_WIDTH_MASK & ~ETM_PORT_MODE_MASK & ~ETM_PORT_CLOCK_MASK)\r
-               | etm_ctx->portmode;\r
-       \r
-       buf_set_u32(reg_list[ETM_CTRL].value, 0, reg_list[ETM_CTRL].size, etm_ctrl_value);\r
-       etm_store_reg(&reg_list[ETM_CTRL]);\r
-       \r
-       /* the ETM might have an ETB connected */\r
-       if (strcmp(etm_ctx->capture_driver->name, "etb") == 0)\r
-       {\r
-               etb_t *etb = etm_ctx->capture_driver_priv;\r
-               \r
-               if (!etb)\r
-               {\r
-                       ERROR("etb selected as etm capture driver, but no ETB configured");\r
-                       return ERROR_OK;\r
-               }\r
-               \r
-               reg_cache->next = etb_build_reg_cache(etb);\r
-               \r
-               etb->reg_cache = reg_cache->next;\r
-       }\r
-       \r
-       if (etm_ctx->capture_driver->init(etm_ctx) != ERROR_OK)\r
-       {\r
-               ERROR("ETM capture driver initialization failed");\r
-               exit(-1);\r
-       }\r
-       \r
-       return reg_cache;\r
-}\r
-\r
-int etm_get_reg(reg_t *reg)\r
-{\r
-       if (etm_read_reg(reg) != ERROR_OK)\r
-       {\r
-               ERROR("BUG: error scheduling etm register read");\r
-               exit(-1);\r
-       }\r
-       \r
-       if (jtag_execute_queue() != ERROR_OK)\r
-       {\r
-               ERROR("register read failed");\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int etm_read_reg_w_check(reg_t *reg, u8* check_value, u8* check_mask)\r
-{\r
-       etm_reg_t *etm_reg = reg->arch_info;\r
-       u8 reg_addr = etm_reg->addr & 0x7f;\r
-       scan_field_t fields[3];\r
-       \r
-       DEBUG("%i", etm_reg->addr);\r
-\r
-       jtag_add_end_state(TAP_RTI);\r
-       arm_jtag_scann(etm_reg->jtag_info, 0x6);\r
-       arm_jtag_set_instr(etm_reg->jtag_info, etm_reg->jtag_info->intest_instr, NULL);\r
-       \r
-       fields[0].device = etm_reg->jtag_info->chain_pos;\r
-       fields[0].num_bits = 32;\r
-       fields[0].out_value = reg->value;\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = NULL;\r
-       fields[0].in_check_value = NULL;\r
-       fields[0].in_check_mask = NULL;\r
-       fields[0].in_handler = NULL;\r
-       fields[0].in_handler_priv = NULL;\r
-       \r
-       fields[1].device = etm_reg->jtag_info->chain_pos;\r
-       fields[1].num_bits = 7;\r
-       fields[1].out_value = malloc(1);\r
-       buf_set_u32(fields[1].out_value, 0, 7, reg_addr);\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = NULL;\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-       fields[1].in_handler = NULL;\r
-       fields[1].in_handler_priv = NULL;\r
-\r
-       fields[2].device = etm_reg->jtag_info->chain_pos;\r
-       fields[2].num_bits = 1;\r
-       fields[2].out_value = malloc(1);\r
-       buf_set_u32(fields[2].out_value, 0, 1, 0);\r
-       fields[2].out_mask = NULL;\r
-       fields[2].in_value = NULL;\r
-       fields[2].in_check_value = NULL;\r
-       fields[2].in_check_mask = NULL;\r
-       fields[2].in_handler = NULL;\r
-       fields[2].in_handler_priv = NULL;\r
-       \r
-       jtag_add_dr_scan(3, fields, -1);\r
-       \r
-       fields[0].in_value = reg->value;\r
-       jtag_set_check_value(fields+0, check_value, check_mask, NULL);  \r
-               \r
-       jtag_add_dr_scan(3, fields, -1);\r
-\r
-       free(fields[1].out_value);\r
-       free(fields[2].out_value);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int etm_read_reg(reg_t *reg)\r
-{\r
-       return etm_read_reg_w_check(reg, NULL, NULL);   \r
-}\r
-\r
-int etm_set_reg(reg_t *reg, u32 value)\r
-{\r
-       if (etm_write_reg(reg, value) != ERROR_OK)\r
-       {\r
-               ERROR("BUG: error scheduling etm register write");\r
-               exit(-1);\r
-       }\r
-       \r
-       buf_set_u32(reg->value, 0, reg->size, value);\r
-       reg->valid = 1;\r
-       reg->dirty = 0;\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int etm_set_reg_w_exec(reg_t *reg, u8 *buf)\r
-{\r
-       etm_set_reg(reg, buf_get_u32(buf, 0, reg->size));\r
-       \r
-       if (jtag_execute_queue() != ERROR_OK)\r
-       {\r
-               ERROR("register write failed");\r
-               exit(-1);\r
-       }\r
-       return ERROR_OK;\r
-}\r
-\r
-int etm_write_reg(reg_t *reg, u32 value)\r
-{\r
-       etm_reg_t *etm_reg = reg->arch_info;\r
-       u8 reg_addr = etm_reg->addr & 0x7f;\r
-       scan_field_t fields[3];\r
-       \r
-       DEBUG("%i: 0x%8.8x", etm_reg->addr, value);\r
-       \r
-       jtag_add_end_state(TAP_RTI);\r
-       arm_jtag_scann(etm_reg->jtag_info, 0x6);\r
-       arm_jtag_set_instr(etm_reg->jtag_info, etm_reg->jtag_info->intest_instr, NULL);\r
-       \r
-       fields[0].device = etm_reg->jtag_info->chain_pos;\r
-       fields[0].num_bits = 32;\r
-       fields[0].out_value = malloc(4);\r
-       buf_set_u32(fields[0].out_value, 0, 32, value);\r
-       fields[0].out_mask = NULL;\r
-       fields[0].in_value = NULL;\r
-       fields[0].in_check_value = NULL;\r
-       fields[0].in_check_mask = NULL;\r
-       fields[0].in_handler = NULL;\r
-       fields[0].in_handler_priv = NULL;\r
-       \r
-       fields[1].device = etm_reg->jtag_info->chain_pos;\r
-       fields[1].num_bits = 7;\r
-       fields[1].out_value = malloc(1);\r
-       buf_set_u32(fields[1].out_value, 0, 7, reg_addr);\r
-       fields[1].out_mask = NULL;\r
-       fields[1].in_value = NULL;\r
-       fields[1].in_check_value = NULL;\r
-       fields[1].in_check_mask = NULL;\r
-       fields[1].in_handler = NULL;\r
-       fields[1].in_handler_priv = NULL;\r
-\r
-       fields[2].device = etm_reg->jtag_info->chain_pos;\r
-       fields[2].num_bits = 1;\r
-       fields[2].out_value = malloc(1);\r
-       buf_set_u32(fields[2].out_value, 0, 1, 1);\r
-       fields[2].out_mask = NULL;\r
-       fields[2].in_value = NULL;\r
-       fields[2].in_check_value = NULL;\r
-       fields[2].in_check_mask = NULL;\r
-       fields[2].in_handler = NULL;\r
-       fields[2].in_handler_priv = NULL;\r
-       \r
-       jtag_add_dr_scan(3, fields, -1);\r
-       \r
-       free(fields[0].out_value);\r
-       free(fields[1].out_value);\r
-       free(fields[2].out_value);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int etm_store_reg(reg_t *reg)\r
-{\r
-       return etm_write_reg(reg, buf_get_u32(reg->value, 0, reg->size));\r
-}\r
-\r
-/* ETM trace analysis functionality\r
- * \r
- */\r
-extern etm_capture_driver_t etb_capture_driver;\r
-extern etm_capture_driver_t etm_dummy_capture_driver;\r
-#if BUILD_OOCD_TRACE == 1\r
-extern etm_capture_driver_t oocd_trace_capture_driver;\r
-#endif\r
-\r
-etm_capture_driver_t *etm_capture_drivers[] = \r
-{\r
-       &etb_capture_driver,\r
-       &etm_dummy_capture_driver,\r
-#if BUILD_OOCD_TRACE == 1\r
-       &oocd_trace_capture_driver,\r
-#endif\r
-       NULL\r
-};\r
-\r
-char *etmv1v1_branch_reason_strings[] =\r
-{\r
-       "normal PC change",\r
-       "tracing enabled",\r
-       "trace restarted after overflow",\r
-       "exit from debug",\r
-       "periodic synchronization",\r
-       "reserved",\r
-       "reserved",\r
-       "reserved",\r
-};\r
-\r
-int etm_read_instruction(etm_context_t *ctx, arm_instruction_t *instruction)\r
-{\r
-       int i;\r
-       int section = -1;\r
-       u32 size_read;\r
-       u32 opcode;\r
-       int retval;\r
-       \r
-       if (!ctx->image)\r
-               return ERROR_TRACE_IMAGE_UNAVAILABLE;\r
-       \r
-       /* search for the section the current instruction belongs to */ \r
-       for (i = 0; i < ctx->image->num_sections; i++)\r
-       {\r
-               if ((ctx->image->sections[i].base_address <= ctx->current_pc) &&\r
-                       (ctx->image->sections[i].base_address + ctx->image->sections[i].size > ctx->current_pc))\r
-               {\r
-                       section = i;\r
-                       break;\r
-               }\r
-       }\r
-       \r
-       if (section == -1)\r
-       {\r
-               /* current instruction couldn't be found in the image */\r
-               return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;\r
-       }\r
-       \r
-       if (ctx->core_state == ARMV4_5_STATE_ARM)\r
-       {\r
-               u8 buf[4];\r
-               if ((retval = image_read_section(ctx->image, section, \r
-                       ctx->current_pc - ctx->image->sections[section].base_address,\r
-                       4, buf, &size_read)) != ERROR_OK)\r
-               {\r
-                       ERROR("error while reading instruction: %i", retval);\r
-                       return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;\r
-               }\r
-               opcode = target_buffer_get_u32(ctx->target, buf);\r
-               arm_evaluate_opcode(opcode, ctx->current_pc, instruction);\r
-       }\r
-       else if (ctx->core_state == ARMV4_5_STATE_THUMB)\r
-       {\r
-               u8 buf[2];\r
-               if ((retval = image_read_section(ctx->image, section, \r
-                       ctx->current_pc - ctx->image->sections[section].base_address,\r
-                       2, buf, &size_read)) != ERROR_OK)\r
-               {\r
-                       ERROR("error while reading instruction: %i", retval);\r
-                       return ERROR_TRACE_INSTRUCTION_UNAVAILABLE;\r
-               }\r
-               opcode = target_buffer_get_u16(ctx->target, buf);\r
-               thumb_evaluate_opcode(opcode, ctx->current_pc, instruction);\r
-       }\r
-       else if (ctx->core_state == ARMV4_5_STATE_JAZELLE)\r
-       {\r
-               ERROR("BUG: tracing of jazelle code not supported");\r
-               exit(-1);\r
-       }\r
-       else\r
-       {\r
-               ERROR("BUG: unknown core state encountered");\r
-               exit(-1);\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int etmv1_next_packet(etm_context_t *ctx, u8 *packet, int apo)\r
-{\r
-       while (ctx->data_index < ctx->trace_depth)\r
-       {\r
-               /* if the caller specified an address packet offset, skip until the\r
-                * we reach the n-th cycle marked with tracesync */\r
-               if (apo > 0)\r
-               {\r
-                       if (ctx->trace_data[ctx->data_index].flags & ETMV1_TRACESYNC_CYCLE)\r
-                               apo--;\r
-                       \r
-                       if (apo > 0)\r
-                       {\r
-                               ctx->data_index++;\r
-                               ctx->data_half = 0;\r
-                       }\r
-                       continue;\r
-               }\r
-               \r
-               /* no tracedata output during a TD cycle\r
-                * or in a trigger cycle */\r
-               if ((ctx->trace_data[ctx->data_index].pipestat == STAT_TD)\r
-                       || (ctx->trace_data[ctx->data_index].flags & ETMV1_TRIGGER_CYCLE))\r
-               {\r
-                       ctx->data_index++;\r
-                       ctx->data_half = 0;\r
-                       continue;\r
-               }\r
-               \r
-               if ((ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_16BIT)\r
-               {\r
-                       if (ctx->data_half == 0)\r
-                       {\r
-                               *packet = ctx->trace_data[ctx->data_index].packet & 0xff;\r
-                               ctx->data_half = 1;\r
-                       }\r
-                       else\r
-                       {\r
-                               *packet = (ctx->trace_data[ctx->data_index].packet & 0xff00) >> 8;\r
-                               ctx->data_half = 0;\r
-                               ctx->data_index++;\r
-                       }\r
-               }\r
-               else if ((ctx->portmode & ETM_PORT_WIDTH_MASK) == ETM_PORT_8BIT)\r
-               {\r
-                       *packet = ctx->trace_data[ctx->data_index].packet & 0xff;\r
-                       ctx->data_index++;\r
-               }\r
-               else\r
-               {\r
-                       /* on a 4-bit port, a packet will be output during two consecutive cycles */\r
-                       if (ctx->data_index > (ctx->trace_depth - 2))\r
-                               return -1;\r
-                       \r
-                       *packet = ctx->trace_data[ctx->data_index].packet & 0xf;\r
-                       *packet |= (ctx->trace_data[ctx->data_index + 1].packet & 0xf) << 4;\r
-                       ctx->data_index += 2;\r
-               }\r
-                                       \r
-               return 0;\r
-       }\r
-       \r
-       return -1;\r
-}\r
-\r
-int etmv1_branch_address(etm_context_t *ctx)\r
-{\r
-       int retval;\r
-       u8 packet;\r
-       int shift = 0;\r
-       int apo;\r
-       int i;\r
-       \r
-       /* quit analysis if less than two cycles are left in the trace\r
-        * because we can't extract the APO */\r
-       if (ctx->data_index > (ctx->trace_depth - 2))\r
-               return -1;\r
-               \r
-       /* a BE could be output during an APO cycle, skip the current\r
-        * and continue with the new one */\r
-       if (ctx->trace_data[ctx->pipe_index + 1].pipestat & 0x4)\r
-               return 1;\r
-       if (ctx->trace_data[ctx->pipe_index + 2].pipestat & 0x4)\r
-               return 2;\r
-               \r
-       /* address packet offset encoded in the next two cycles' pipestat bits */\r
-       apo = ctx->trace_data[ctx->pipe_index + 1].pipestat & 0x3;\r
-       apo |= (ctx->trace_data[ctx->pipe_index + 2].pipestat & 0x3) << 2;\r
-       \r
-       /* count number of tracesync cycles between current pipe_index and data_index\r
-        * i.e. the number of tracesyncs that data_index already passed by\r
-        * to subtract them from the APO */\r
-       for (i = ctx->pipe_index; i < ctx->data_index; i++)\r
-       {\r
-               if (ctx->trace_data[ctx->pipe_index + 1].pipestat & ETMV1_TRACESYNC_CYCLE)\r
-                       apo--;\r
-       }\r
-       \r
-       /* extract up to four 7-bit packets */\r
-       do {\r
-               if ((retval = etmv1_next_packet(ctx, &packet, (shift == 0) ? apo + 1 : 0)) != 0)\r
-                       return -1;\r
-               ctx->last_branch &= ~(0x7f << shift);\r
-               ctx->last_branch |= (packet & 0x7f) << shift;\r
-               shift += 7;\r
-       } while ((packet & 0x80) && (shift < 28));\r
-       \r
-       /* one last packet holding 4 bits of the address, plus the branch reason code */\r
-       if ((shift == 28) && (packet & 0x80))\r
-       {\r
-               if ((retval = etmv1_next_packet(ctx, &packet, 0)) != 0)\r
-                       return -1;\r
-               ctx->last_branch &= 0x0fffffff;\r
-               ctx->last_branch |= (packet & 0x0f) << 28;\r
-               ctx->last_branch_reason = (packet & 0x70) >> 4;\r
-               shift += 4;\r
-       }\r
-       else\r
-       {\r
-               ctx->last_branch_reason = 0;\r
-       }\r
-       \r
-       if (shift == 32)\r
-       {\r
-               ctx->pc_ok = 1;\r
-       }\r
-       \r
-       /* if a full address was output, we might have branched into Jazelle state */\r
-       if ((shift == 32) && (packet & 0x80))\r
-       {\r
-               ctx->core_state = ARMV4_5_STATE_JAZELLE;\r
-       }\r
-       else\r
-       {\r
-               /* if we didn't branch into Jazelle state, the current processor state is\r
-                * encoded in bit 0 of the branch target address */\r
-               if (ctx->last_branch & 0x1)\r
-               {\r
-                       ctx->core_state = ARMV4_5_STATE_THUMB;\r
-                       ctx->last_branch &= ~0x1;\r
-               }\r
-               else\r
-               {\r
-                       ctx->core_state = ARMV4_5_STATE_ARM;\r
-                       ctx->last_branch &= ~0x3;\r
-               }\r
-       }\r
-       \r
-       return 0;\r
-}\r
-\r
-int etmv1_data(etm_context_t *ctx, int size, u32 *data)\r
-{\r
-       int j;\r
-       u8 buf[4];\r
-       int retval;\r
-       \r
-       for (j = 0; j < size; j++)\r
-       {\r
-               if ((retval = etmv1_next_packet(ctx, &buf[j], 0)) != 0)\r
-                       return -1;\r
-       }\r
-       \r
-       if (size == 8)\r
-               ERROR("TODO: add support for 64-bit values");\r
-       else if (size == 4)\r
-               *data = target_buffer_get_u32(ctx->target, buf);\r
-       else if (size == 2)\r
-               *data = target_buffer_get_u16(ctx->target, buf);\r
-       else if (size == 1)\r
-               *data = buf[0];\r
-               \r
-       return 0;\r
-}\r
-\r
-int etmv1_analyze_trace(etm_context_t *ctx, struct command_context_s *cmd_ctx)\r
-{\r
-       int retval;\r
-       arm_instruction_t instruction;\r
-       \r
-       /* read the trace data if it wasn't read already */\r
-       if (ctx->trace_depth == 0)\r
-               ctx->capture_driver->read_trace(ctx);\r
-       \r
-       /* start at the beginning of the captured trace */\r
-       ctx->pipe_index = 0;\r
-       ctx->data_index = 0;\r
-       ctx->data_half = 0;\r
-\r
-       /* neither the PC nor the data pointer are valid */     \r
-       ctx->pc_ok = 0;\r
-       ctx->ptr_ok = 0;\r
-       \r
-       while (ctx->pipe_index < ctx->trace_depth)\r
-       {\r
-               u8 pipestat = ctx->trace_data[ctx->pipe_index].pipestat;\r
-               u32 next_pc = ctx->current_pc;\r
-               u32 old_data_index = ctx->data_index;\r
-               u32 old_data_half = ctx->data_half;\r
-               u32 old_index = ctx->pipe_index;\r
-               u32 last_instruction = ctx->last_instruction;\r
-               u32 cycles = 0;\r
-               int current_pc_ok = ctx->pc_ok;\r
-               \r
-               if (ctx->trace_data[ctx->pipe_index].flags & ETMV1_TRIGGER_CYCLE)\r
-               {\r
-                       command_print(cmd_ctx, "--- trigger ---");\r
-               }\r
-\r
-               /* instructions execute in IE/D or BE/D cycles */\r
-               if ((pipestat == STAT_IE) || (pipestat == STAT_ID))\r
-                       ctx->last_instruction = ctx->pipe_index;\r
-               \r
-               /* if we don't have a valid pc skip until we reach an indirect branch */\r
-               if ((!ctx->pc_ok) && (pipestat != STAT_BE))\r
-               {\r
-                       ctx->pipe_index++;\r
-                       continue;\r
-               }\r
-               \r
-               /* any indirect branch could have interrupted instruction flow\r
-                * - the branch reason code could indicate a trace discontinuity\r
-                * - a branch to the exception vectors indicates an exception\r
-                */\r
-               if ((pipestat == STAT_BE) || (pipestat == STAT_BD))\r
-               {\r
-                       /* backup current data index, to be able to consume the branch address\r
-                        * before examining data address and values\r
-                        */\r
-                       old_data_index = ctx->data_index;\r
-                       old_data_half = ctx->data_half;\r
-\r
-                       ctx->last_instruction = ctx->pipe_index;\r
-                       \r
-                       if ((retval = etmv1_branch_address(ctx)) != 0)\r
-                       {\r
-                               /* negative return value from etmv1_branch_address means we ran out of packets,\r
-                                * quit analysing the trace */\r
-                               if (retval < 0)\r
-                                       break;\r
-                               \r
-                               /* a positive return values means the current branch was abandoned,\r
-                                * and a new branch was encountered in cycle ctx->pipe_index + retval;\r
-                                */\r
-                               WARNING("abandoned branch encountered, correctnes of analysis uncertain");\r
-                               ctx->pipe_index += retval;\r
-                               continue;\r
-                       }\r
-                       \r
-                       /* skip over APO cycles */\r
-                       ctx->pipe_index += 2;\r
-                       \r
-                       switch (ctx->last_branch_reason)\r
-                       {\r
-                               case 0x0:       /* normal PC change */\r
-                                       next_pc = ctx->last_branch;\r
-                                       break;\r
-                               case 0x1:       /* tracing enabled */\r
-                                       command_print(cmd_ctx, "--- tracing enabled at 0x%8.8x ---", ctx->last_branch);\r
-                                       ctx->current_pc = ctx->last_branch;\r
-                                       ctx->pipe_index++;\r
-                                       continue;\r
-                                       break;\r
-                               case 0x2:       /* trace restarted after FIFO overflow */\r
-                                       command_print(cmd_ctx, "--- trace restarted after FIFO overflow at 0x%8.8x ---", ctx->last_branch);\r
-                                       ctx->current_pc = ctx->last_branch;\r
-                                       ctx->pipe_index++;\r
-                                       continue;\r
-                                       break;\r
-                               case 0x3:       /* exit from debug state */\r
-                                       command_print(cmd_ctx, "--- exit from debug state at 0x%8.8x ---", ctx->last_branch);\r
-                                       ctx->current_pc = ctx->last_branch;\r
-                                       ctx->pipe_index++;\r
-                                       continue;\r
-                                       break;\r
-                               case 0x4:       /* periodic synchronization point */\r
-                                       next_pc = ctx->last_branch;\r
-                                       /* if we had no valid PC prior to this synchronization point,\r
-                                        * we have to move on with the next trace cycle\r
-                                        */\r
-                                       if (!current_pc_ok)\r
-                                       {\r
-                                               command_print(cmd_ctx, "--- periodic synchronization point at 0x%8.8x ---", next_pc);\r
-                                               ctx->current_pc = next_pc;\r
-                                               ctx->pipe_index++;\r
-                                               continue;\r
-                                       }\r
-                                       break;\r
-                               default:        /* reserved */\r
-                                       ERROR("BUG: branch reason code 0x%x is reserved", ctx->last_branch_reason);             \r
-                                       exit(-1);\r
-                                       break;\r
-                       }\r
-                       \r
-                       /* if we got here the branch was a normal PC change\r
-                        * (or a periodic synchronization point, which means the same for that matter)\r
-                        * if we didn't accquire a complete PC continue with the next cycle\r
-                        */\r
-                       if (!ctx->pc_ok)\r
-                               continue;\r
-                       \r
-                       /* indirect branch to the exception vector means an exception occured */\r
-                       if (((ctx->last_branch >= 0x0) && (ctx->last_branch <= 0x20))\r
-                               || ((ctx->last_branch >= 0xffff0000) && (ctx->last_branch <= 0xffff0020)))\r
-                       {\r
-                               if ((ctx->last_branch & 0xff) == 0x10)\r
-                               {\r
-                                       command_print(cmd_ctx, "data abort");\r
-                               }\r
-                               else\r
-                               {\r
-                                       command_print(cmd_ctx, "exception vector 0x%2.2x", ctx->last_branch);\r
-                                       ctx->current_pc = ctx->last_branch;\r
-                                       ctx->pipe_index++;\r
-                                       continue;\r
-                               }\r
-                       }\r
-               }\r
-               \r
-               /* an instruction was executed (or not, depending on the condition flags)\r
-                * retrieve it from the image for displaying */\r
-               if (ctx->pc_ok && (pipestat != STAT_WT) && (pipestat != STAT_TD) &&\r
-                       !(((pipestat == STAT_BE) || (pipestat == STAT_BD)) &&\r
-                               ((ctx->last_branch_reason != 0x0) && (ctx->last_branch_reason != 0x4))))  \r
-               {\r
-                       if ((retval = etm_read_instruction(ctx, &instruction)) != ERROR_OK)\r
-                       {\r
-                               /* can't continue tracing with no image available */\r
-                               if (retval == ERROR_TRACE_IMAGE_UNAVAILABLE)\r
-                               {\r
-                                       return retval;\r
-                               }\r
-                               else if (retval == ERROR_TRACE_INSTRUCTION_UNAVAILABLE)\r
-                               {\r
-                                       /* TODO: handle incomplete images \r
-                                        * for now we just quit the analsysis*/\r
-                                       return retval;\r
-                               }\r
-                       }\r
-                       \r
-                       cycles = old_index - last_instruction;\r
-               }\r
-               \r
-               if ((pipestat == STAT_ID) || (pipestat == STAT_BD))\r
-               {\r
-                       u32 new_data_index = ctx->data_index;\r
-                       u32 new_data_half = ctx->data_half;\r
-                       \r
-                       /* in case of a branch with data, the branch target address was consumed before\r
-                        * we temporarily go back to the saved data index */\r
-                       if (pipestat == STAT_BD)\r
-                       {\r
-                               ctx->data_index = old_data_index;\r
-                               ctx->data_half = old_data_half;\r
-                       }\r
-                       \r
-                       if (ctx->tracemode & ETMV1_TRACE_ADDR)\r
-                       {                       \r
-                               u8 packet;\r
-                               int shift = 0;\r
-                               \r
-                               do {\r
-                                       if ((retval = etmv1_next_packet(ctx, &packet, 0)) != 0)\r
-                                               return ERROR_ETM_ANALYSIS_FAILED;\r
-                                       ctx->last_ptr &= ~(0x7f << shift);\r
-                                       ctx->last_ptr |= (packet & 0x7f) << shift;\r
-                                       shift += 7;\r
-                               } while ((packet & 0x80) && (shift < 32));\r
-                               \r
-                               if (shift >= 32)\r
-                                       ctx->ptr_ok = 1;\r
-                               \r
-                               if (ctx->ptr_ok)\r
-                               {\r
-                                       command_print(cmd_ctx, "address: 0x%8.8x", ctx->last_ptr);\r
-                               }\r
-                       }\r
-                       \r
-                       if (ctx->tracemode & ETMV1_TRACE_DATA)\r
-                       {\r
-                               if ((instruction.type == ARM_LDM) || (instruction.type == ARM_STM))\r
-                               {\r
-                                       int i;\r
-                                       for (i = 0; i < 16; i++)\r
-                                       {\r
-                                               if (instruction.info.load_store_multiple.register_list & (1 << i))\r
-                                               {\r
-                                                       u32 data;\r
-                                                       if (etmv1_data(ctx, 4, &data) != 0)\r
-                                                               return ERROR_ETM_ANALYSIS_FAILED;\r
-                                                       command_print(cmd_ctx, "data: 0x%8.8x", data);\r
-                                               }\r
-                                       }\r
-                               }\r
-                               else if ((instruction.type >= ARM_LDR) && (instruction.type <= ARM_STRH))\r
-                               {\r
-                                       u32 data;\r
-                                       if (etmv1_data(ctx, arm_access_size(&instruction), &data) != 0)\r
-                                               return ERROR_ETM_ANALYSIS_FAILED;\r
-                                       command_print(cmd_ctx, "data: 0x%8.8x", data);\r
-                               }\r
-                       }\r
-                       \r
-                       /* restore data index after consuming BD address and data */\r
-                       if (pipestat == STAT_BD)\r
-                       {\r
-                               ctx->data_index = new_data_index;\r
-                               ctx->data_half = new_data_half;\r
-                       }\r
-               }\r
-               \r
-               /* adjust PC */\r
-               if ((pipestat == STAT_IE) || (pipestat == STAT_ID))\r
-               {\r
-                       if (((instruction.type == ARM_B) ||\r
-                               (instruction.type == ARM_BL) ||\r
-                               (instruction.type == ARM_BLX)) &&\r
-                               (instruction.info.b_bl_bx_blx.target_address != -1))\r
-                       {\r
-                               next_pc = instruction.info.b_bl_bx_blx.target_address;\r
-                       }\r
-                       else\r
-                       {\r
-                               next_pc += (ctx->core_state == ARMV4_5_STATE_ARM) ? 4 : 2;\r
-                       }\r
-               }\r
-               else if (pipestat == STAT_IN)\r
-               {\r
-                       next_pc += (ctx->core_state == ARMV4_5_STATE_ARM) ? 4 : 2;\r
-               }\r
-\r
-               if ((pipestat != STAT_TD) && (pipestat != STAT_WT))\r
-               {\r
-                       char cycles_text[32] = "";\r
-                       \r
-                       /* if the trace was captured with cycle accurate tracing enabled,\r
-                        * output the number of cycles since the last executed instruction\r
-                        */\r
-                       if (ctx->tracemode & ETMV1_CYCLE_ACCURATE)\r
-                       {\r
-                               snprintf(cycles_text, 32, " (%i %s)",\r
-                                       cycles,\r
-                                       (cycles == 1) ? "cycle" : "cycles");\r
-                       }\r
-                       \r
-                       command_print(cmd_ctx, "%s%s%s",\r
-                               instruction.text,\r
-                               (pipestat == STAT_IN) ? " (not executed)" : "",\r
-                               cycles_text);\r
-\r
-                       ctx->current_pc = next_pc;\r
-                       \r
-                       /* packets for an instruction don't start on or before the preceding\r
-                        * functional pipestat (i.e. other than WT or TD)\r
-                        */\r
-                       if (ctx->data_index <= ctx->pipe_index)\r
-                       {\r
-                               ctx->data_index = ctx->pipe_index + 1;\r
-                               ctx->data_half = 0;\r
-                       }\r
-               }\r
-               \r
-               ctx->pipe_index += 1;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_etm_tracemode_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target;\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       etmv1_tracemode_t tracemode;\r
-       \r
-       target = get_current_target(cmd_ctx);\r
-       \r
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (!arm7_9->etm_ctx)\r
-       {\r
-               command_print(cmd_ctx, "current target doesn't have an ETM configured");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       tracemode = arm7_9->etm_ctx->tracemode;\r
-\r
-       if (argc == 4)\r
-       {\r
-               if (strcmp(args[0], "none") == 0)\r
-               {\r
-                       tracemode = ETMV1_TRACE_NONE;\r
-               }\r
-               else if (strcmp(args[0], "data") == 0)\r
-               {\r
-                       tracemode = ETMV1_TRACE_DATA;\r
-               }\r
-               else if (strcmp(args[0], "address") == 0)\r
-               {\r
-                       tracemode = ETMV1_TRACE_ADDR;\r
-               }\r
-               else if (strcmp(args[0], "all") == 0)\r
-               {\r
-                       tracemode = ETMV1_TRACE_DATA | ETMV1_TRACE_ADDR;\r
-               }\r
-               else\r
-               {\r
-                       command_print(cmd_ctx, "invalid option '%s'", args[0]);\r
-                       return ERROR_OK;\r
-               }\r
-               \r
-               switch (strtol(args[1], NULL, 0))\r
-               {\r
-                       case 0:\r
-                               tracemode |= ETMV1_CONTEXTID_NONE;\r
-                               break;\r
-                       case 8:\r
-                               tracemode |= ETMV1_CONTEXTID_8;\r
-                               break;\r
-                       case 16:\r
-                               tracemode |= ETMV1_CONTEXTID_16;\r
-                               break;\r
-                       case 32:\r
-                               tracemode |= ETMV1_CONTEXTID_32;\r
-                               break;\r
-                       default:\r
-                               command_print(cmd_ctx, "invalid option '%s'", args[1]);\r
-                               return ERROR_OK;\r
-               }\r
-               \r
-               if (strcmp(args[2], "enable") == 0)\r
-               {\r
-                       tracemode |= ETMV1_CYCLE_ACCURATE;\r
-               }\r
-               else if (strcmp(args[2], "disable") == 0)\r
-               {\r
-                       tracemode |= 0;\r
-               }\r
-               else\r
-               {\r
-                       command_print(cmd_ctx, "invalid option '%s'", args[2]);\r
-                       return ERROR_OK;\r
-               }\r
-               \r
-               if (strcmp(args[3], "enable") == 0)\r
-               {\r
-                       tracemode |= ETMV1_BRANCH_OUTPUT;\r
-               }\r
-               else if (strcmp(args[3], "disable") == 0)\r
-               {\r
-                       tracemode |= 0;\r
-               }\r
-               else\r
-               {\r
-                       command_print(cmd_ctx, "invalid option '%s'", args[2]);\r
-                       return ERROR_OK;\r
-               }\r
-       }\r
-       else if (argc != 0)\r
-       {\r
-               command_print(cmd_ctx, "usage: configure trace mode <none|data|address|all> <context id bits> <cycle accurate> <branch output>");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       command_print(cmd_ctx, "current tracemode configuration:");\r
-       \r
-       switch (tracemode & ETMV1_TRACE_MASK)\r
-       {\r
-               case ETMV1_TRACE_NONE:\r
-                       command_print(cmd_ctx, "data tracing: none");\r
-                       break;\r
-               case ETMV1_TRACE_DATA:\r
-                       command_print(cmd_ctx, "data tracing: data only");\r
-                       break;\r
-               case ETMV1_TRACE_ADDR:\r
-                       command_print(cmd_ctx, "data tracing: address only");\r
-                       break;\r
-               case ETMV1_TRACE_DATA | ETMV1_TRACE_ADDR:\r
-                       command_print(cmd_ctx, "data tracing: address and data");\r
-                       break;\r
-       }\r
-       \r
-       switch (tracemode & ETMV1_CONTEXTID_MASK)\r
-       {\r
-               case ETMV1_CONTEXTID_NONE:\r
-                       command_print(cmd_ctx, "contextid tracing: none");\r
-                       break;\r
-               case ETMV1_CONTEXTID_8:\r
-                       command_print(cmd_ctx, "contextid tracing: 8 bit");\r
-                       break;\r
-               case ETMV1_CONTEXTID_16:\r
-                       command_print(cmd_ctx, "contextid tracing: 16 bit");\r
-                       break;\r
-               case ETMV1_CONTEXTID_32:\r
-                       command_print(cmd_ctx, "contextid tracing: 32 bit");\r
-                       break;\r
-       }\r
-       \r
-       if (tracemode & ETMV1_CYCLE_ACCURATE)\r
-       {\r
-               command_print(cmd_ctx, "cycle-accurate tracing enabled");\r
-       }\r
-       else\r
-       {\r
-               command_print(cmd_ctx, "cycle-accurate tracing disabled");\r
-       }\r
-\r
-       if (tracemode & ETMV1_BRANCH_OUTPUT)\r
-       {\r
-               command_print(cmd_ctx, "full branch address output enabled");\r
-       }\r
-       else\r
-       {\r
-               command_print(cmd_ctx, "full branch address output disabled");\r
-       }\r
-       \r
-       /* only update ETM_CTRL register if tracemode changed */\r
-       if (arm7_9->etm_ctx->tracemode != tracemode)\r
-       {\r
-               reg_t *etm_ctrl_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CTRL];\r
-               \r
-               etm_get_reg(etm_ctrl_reg);\r
-               \r
-               buf_set_u32(etm_ctrl_reg->value, 2, 2, tracemode & ETMV1_TRACE_MASK);\r
-               buf_set_u32(etm_ctrl_reg->value, 14, 2, (tracemode & ETMV1_CONTEXTID_MASK) >> 4);\r
-               buf_set_u32(etm_ctrl_reg->value, 12, 1, (tracemode & ETMV1_CYCLE_ACCURATE) >> 8);\r
-               buf_set_u32(etm_ctrl_reg->value, 8, 1, (tracemode & ETMV1_BRANCH_OUTPUT) >> 9);\r
-               etm_store_reg(etm_ctrl_reg);\r
-               \r
-               arm7_9->etm_ctx->tracemode = tracemode;\r
-               \r
-               /* invalidate old trace data */\r
-               arm7_9->etm_ctx->capture_status = TRACE_IDLE;\r
-               if (arm7_9->etm_ctx->trace_depth > 0)\r
-               {\r
-                       free(arm7_9->etm_ctx->trace_data);\r
-                       arm7_9->etm_ctx->trace_data = NULL;\r
-               }\r
-               arm7_9->etm_ctx->trace_depth = 0;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_etm_config_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target;\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       etm_portmode_t portmode = 0x0;\r
-       etm_context_t *etm_ctx = malloc(sizeof(etm_context_t));\r
-       int i;\r
-       \r
-       if (argc != 5)\r
-       {\r
-               ERROR("incomplete 'etm config <target> <port_width> <port_mode> <clocking> <capture_driver>' command");\r
-               exit(-1);\r
-       }\r
-       \r
-       target = get_target_by_num(strtoul(args[0], NULL, 0));\r
-       \r
-       if (!target)\r
-       {\r
-               ERROR("target number '%s' not defined", args[0]);\r
-               exit(-1);\r
-       }\r
-       \r
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       switch (strtoul(args[1], NULL, 0))\r
-       {\r
-               case 4:\r
-                       portmode |= ETM_PORT_4BIT;\r
-                       break;\r
-               case 8:\r
-                       portmode |= ETM_PORT_8BIT;\r
-                       break;\r
-               case 16:\r
-                       portmode |= ETM_PORT_16BIT;\r
-                       break;\r
-               default:\r
-                       command_print(cmd_ctx, "unsupported ETM port width '%s', must be 4, 8 or 16", args[1]);\r
-                       return ERROR_OK;\r
-       }\r
-       \r
-       if (strcmp("normal", args[2]) == 0)\r
-       {\r
-               portmode |= ETM_PORT_NORMAL;\r
-       }\r
-       else if (strcmp("multiplexed", args[2]) == 0)\r
-       {\r
-               portmode |= ETM_PORT_MUXED;\r
-       }\r
-       else if (strcmp("demultiplexed", args[2]) == 0)\r
-       {\r
-               portmode |= ETM_PORT_DEMUXED;\r
-       }\r
-       else\r
-       {\r
-               command_print(cmd_ctx, "unsupported ETM port mode '%s', must be 'normal', 'multiplexed' or 'demultiplexed'", args[2]);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (strcmp("half", args[3]) == 0)\r
-       {\r
-               portmode |= ETM_PORT_HALF_CLOCK;\r
-       }\r
-       else if (strcmp("full", args[3]) == 0)\r
-       {\r
-               portmode |= ETM_PORT_FULL_CLOCK;\r
-       }\r
-       else\r
-       {\r
-               command_print(cmd_ctx, "unsupported ETM port clocking '%s', must be 'full' or 'half'", args[3]);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       for (i=0; etm_capture_drivers[i]; i++)\r
-       {\r
-               if (strcmp(args[4], etm_capture_drivers[i]->name) == 0)\r
-               {\r
-                       if (etm_capture_drivers[i]->register_commands(cmd_ctx) != ERROR_OK)\r
-                       {\r
-                               free(etm_ctx);\r
-                               exit(-1);\r
-                       }\r
-               \r
-                       etm_ctx->capture_driver = etm_capture_drivers[i];\r
-\r
-                       break;\r
-               }\r
-       }\r
-       \r
-       if (!etm_capture_drivers[i])\r
-       {\r
-               /* no supported capture driver found, don't register an ETM */\r
-               free(etm_ctx);\r
-               ERROR("trace capture driver '%s' not found", args[4]);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       etm_ctx->target = target;\r
-       etm_ctx->trigger_percent = 50;\r
-       etm_ctx->trace_data = NULL;\r
-       etm_ctx->trace_depth = 0;\r
-       etm_ctx->portmode = portmode;\r
-       etm_ctx->tracemode = 0x0;\r
-       etm_ctx->core_state = ARMV4_5_STATE_ARM;\r
-       etm_ctx->image = NULL;\r
-       etm_ctx->pipe_index = 0;\r
-       etm_ctx->data_index = 0;\r
-       etm_ctx->current_pc = 0x0;\r
-       etm_ctx->pc_ok = 0;\r
-       etm_ctx->last_branch = 0x0;\r
-       etm_ctx->last_branch_reason = 0x0;\r
-       etm_ctx->last_ptr = 0x0;\r
-       etm_ctx->ptr_ok = 0x0;\r
-       etm_ctx->context_id = 0x0;\r
-       etm_ctx->last_instruction = 0;\r
-       \r
-       arm7_9->etm_ctx = etm_ctx;\r
-       \r
-       etm_register_user_commands(cmd_ctx);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_etm_info_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target;\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       reg_t *etm_config_reg;\r
-       reg_t *etm_sys_config_reg;\r
-       \r
-       int max_port_size;\r
-               \r
-       target = get_current_target(cmd_ctx);\r
-       \r
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (!arm7_9->etm_ctx)\r
-       {\r
-               command_print(cmd_ctx, "current target doesn't have an ETM configured");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       etm_config_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CONFIG];\r
-       etm_sys_config_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_SYS_CONFIG];\r
-       \r
-       etm_get_reg(etm_config_reg);\r
-       command_print(cmd_ctx, "pairs of address comparators: %i", buf_get_u32(etm_config_reg->value, 0, 4));\r
-       command_print(cmd_ctx, "pairs of data comparators: %i", buf_get_u32(etm_config_reg->value, 4, 4));\r
-       command_print(cmd_ctx, "memory map decoders: %i", buf_get_u32(etm_config_reg->value, 8, 5));\r
-       command_print(cmd_ctx, "number of counters: %i", buf_get_u32(etm_config_reg->value, 13, 3));\r
-       command_print(cmd_ctx, "sequencer %spresent",\r
-                       (buf_get_u32(etm_config_reg->value, 16, 1) == 1) ? "" : "not ");\r
-       command_print(cmd_ctx, "number of ext. inputs: %i", buf_get_u32(etm_config_reg->value, 17, 3));\r
-       command_print(cmd_ctx, "number of ext. outputs: %i", buf_get_u32(etm_config_reg->value, 20, 3));\r
-       command_print(cmd_ctx, "FIFO full %spresent",\r
-                       (buf_get_u32(etm_config_reg->value, 23, 1) == 1) ? "" : "not ");\r
-       command_print(cmd_ctx, "protocol version: %i", buf_get_u32(etm_config_reg->value, 28, 3));\r
-       \r
-       etm_get_reg(etm_sys_config_reg);\r
-\r
-       switch (buf_get_u32(etm_sys_config_reg->value, 0, 3))\r
-       {\r
-               case 0:\r
-                       max_port_size = 4;\r
-                       break;\r
-               case 1:\r
-                       max_port_size = 8;\r
-                       break;\r
-               case 2:\r
-                       max_port_size = 16;\r
-                       break;\r
-       }\r
-       command_print(cmd_ctx, "max. port size: %i", max_port_size);\r
-       \r
-       command_print(cmd_ctx, "half-rate clocking %ssupported",\r
-                       (buf_get_u32(etm_sys_config_reg->value, 3, 1) == 1) ? "" : "not ");\r
-       command_print(cmd_ctx, "full-rate clocking %ssupported",\r
-                       (buf_get_u32(etm_sys_config_reg->value, 4, 1) == 1) ? "" : "not ");\r
-       command_print(cmd_ctx, "normal trace format %ssupported",\r
-                       (buf_get_u32(etm_sys_config_reg->value, 5, 1) == 1) ? "" : "not ");\r
-       command_print(cmd_ctx, "multiplex trace format %ssupported",\r
-                       (buf_get_u32(etm_sys_config_reg->value, 6, 1) == 1) ? "" : "not ");\r
-       command_print(cmd_ctx, "demultiplex trace format %ssupported",\r
-                       (buf_get_u32(etm_sys_config_reg->value, 7, 1) == 1) ? "" : "not ");\r
-       command_print(cmd_ctx, "FIFO full %ssupported",\r
-                       (buf_get_u32(etm_sys_config_reg->value, 8, 1) == 1) ? "" : "not ");\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_etm_status_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target;\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       trace_status_t trace_status;\r
-       \r
-       target = get_current_target(cmd_ctx);\r
-       \r
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (!arm7_9->etm_ctx)\r
-       {\r
-               command_print(cmd_ctx, "current target doesn't have an ETM configured");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       trace_status = arm7_9->etm_ctx->capture_driver->status(arm7_9->etm_ctx);\r
-       \r
-       if (trace_status == TRACE_IDLE)\r
-       {\r
-               command_print(cmd_ctx, "tracing is idle");\r
-       }\r
-       else\r
-       {\r
-               static char *completed = " completed";\r
-               static char *running = " is running";\r
-               static char *overflowed = ", trace overflowed";\r
-               static char *triggered = ", trace triggered";\r
-               \r
-               command_print(cmd_ctx, "trace collection%s%s%s", \r
-                       (trace_status & TRACE_RUNNING) ? running : completed,\r
-                       (trace_status & TRACE_OVERFLOWED) ? overflowed : "",\r
-                       (trace_status & TRACE_TRIGGERED) ? triggered : "");\r
-               \r
-               if (arm7_9->etm_ctx->trace_depth > 0)\r
-               {\r
-                       command_print(cmd_ctx, "%i frames of trace data read", arm7_9->etm_ctx->trace_depth);\r
-               }\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_etm_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target;\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       etm_context_t *etm_ctx;\r
-\r
-       if (argc < 1)\r
-       {\r
-               command_print(cmd_ctx, "usage: etm image <file> [base address] [type]");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       target = get_current_target(cmd_ctx);\r
-       \r
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (!(etm_ctx = arm7_9->etm_ctx))\r
-       {\r
-               command_print(cmd_ctx, "current target doesn't have an ETM configured");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (etm_ctx->image)\r
-       {\r
-               image_close(etm_ctx->image);\r
-               free(etm_ctx->image);\r
-               command_print(cmd_ctx, "previously loaded image found and closed");\r
-       }\r
-       \r
-       etm_ctx->image = malloc(sizeof(image_t));\r
-       etm_ctx->image->base_address_set = 0;\r
-       etm_ctx->image->start_address_set = 0;\r
-       \r
-       /* a base address isn't always necessary, default to 0x0 (i.e. don't relocate) */\r
-       if (argc >= 2)\r
-       {\r
-               etm_ctx->image->base_address_set = 1;\r
-               etm_ctx->image->base_address = strtoul(args[1], NULL, 0);\r
-       }\r
-       else\r
-       {\r
-               etm_ctx->image->base_address_set = 0;\r
-       }\r
-               \r
-       if (image_open(etm_ctx->image, args[0], (argc >= 3) ? args[2] : NULL) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "image opening error: %s", etm_ctx->image->error_str);\r
-               free(etm_ctx->image);\r
-               etm_ctx->image = NULL;\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_etm_dump_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       fileio_t file;\r
-       target_t *target;\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       etm_context_t *etm_ctx;\r
-       int i;\r
-       \r
-       if (argc != 1)\r
-       {\r
-               command_print(cmd_ctx, "usage: etm dump <file>");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       target = get_current_target(cmd_ctx);\r
-       \r
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (!(etm_ctx = arm7_9->etm_ctx))\r
-       {\r
-               command_print(cmd_ctx, "current target doesn't have an ETM configured");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (etm_ctx->capture_driver->status == TRACE_IDLE)\r
-       {\r
-               command_print(cmd_ctx, "trace capture wasn't enabled, no trace data captured");\r
-               return ERROR_OK;\r
-       }\r
-\r
-       if (etm_ctx->capture_driver->status(etm_ctx) & TRACE_RUNNING)\r
-       {\r
-               /* TODO: if on-the-fly capture is to be supported, this needs to be changed */\r
-               command_print(cmd_ctx, "trace capture not completed");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       /* read the trace data if it wasn't read already */\r
-       if (etm_ctx->trace_depth == 0)\r
-               etm_ctx->capture_driver->read_trace(etm_ctx);\r
-       \r
-       if (fileio_open(&file, args[0], FILEIO_WRITE, FILEIO_BINARY) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "file open error: %s", file.error_str);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       fileio_write_u32(&file, etm_ctx->capture_status);\r
-       fileio_write_u32(&file, etm_ctx->portmode);\r
-       fileio_write_u32(&file, etm_ctx->tracemode);\r
-       fileio_write_u32(&file, etm_ctx->trace_depth);\r
-       \r
-       for (i = 0; i < etm_ctx->trace_depth; i++)\r
-       {\r
-               fileio_write_u32(&file, etm_ctx->trace_data[i].pipestat);\r
-               fileio_write_u32(&file, etm_ctx->trace_data[i].packet);\r
-               fileio_write_u32(&file, etm_ctx->trace_data[i].flags);\r
-       }\r
-       \r
-       fileio_close(&file);\r
-       \r
-       return ERROR_OK;        \r
-}\r
-\r
-int handle_etm_load_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       fileio_t file;\r
-       target_t *target;\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       etm_context_t *etm_ctx;\r
-       int i;\r
-       \r
-       if (argc != 1)\r
-       {\r
-               command_print(cmd_ctx, "usage: etm load <file>");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       target = get_current_target(cmd_ctx);\r
-       \r
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (!(etm_ctx = arm7_9->etm_ctx))\r
-       {\r
-               command_print(cmd_ctx, "current target doesn't have an ETM configured");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (etm_ctx->capture_driver->status(etm_ctx) & TRACE_RUNNING)\r
-       {\r
-               command_print(cmd_ctx, "trace capture running, stop first");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (fileio_open(&file, args[0], FILEIO_READ, FILEIO_BINARY) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "file open error: %s", file.error_str);\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (file.size % 4)\r
-       {\r
-               command_print(cmd_ctx, "size isn't a multiple of 4, no valid trace data");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (etm_ctx->trace_depth > 0)\r
-       {\r
-               free(etm_ctx->trace_data);\r
-       }\r
-       \r
-       fileio_read_u32(&file, &etm_ctx->capture_status);\r
-       fileio_read_u32(&file, &etm_ctx->portmode);\r
-       fileio_read_u32(&file, &etm_ctx->tracemode);\r
-       fileio_read_u32(&file, &etm_ctx->trace_depth);\r
-       \r
-       etm_ctx->trace_data = malloc(sizeof(etmv1_trace_data_t) * etm_ctx->trace_depth);\r
-       \r
-       for (i = 0; i < etm_ctx->trace_depth; i++)\r
-       {\r
-               u32 pipestat, packet, flags;\r
-               fileio_read_u32(&file, &pipestat);\r
-               fileio_read_u32(&file, &packet);\r
-               fileio_read_u32(&file, &flags);\r
-               etm_ctx->trace_data[i].pipestat = pipestat & 0xff;\r
-               etm_ctx->trace_data[i].packet = packet & 0xffff;\r
-               etm_ctx->trace_data[i].flags = flags;\r
-       }\r
-       \r
-       fileio_close(&file);\r
-       \r
-       return ERROR_OK;        \r
-}\r
-\r
-int handle_etm_trigger_percent_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target;\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       etm_context_t *etm_ctx;\r
-       \r
-       target = get_current_target(cmd_ctx);\r
-       \r
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (!(etm_ctx = arm7_9->etm_ctx))\r
-       {\r
-               command_print(cmd_ctx, "current target doesn't have an ETM configured");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (argc > 0)\r
-       {\r
-               u32 new_value = strtoul(args[0], NULL, 0);\r
-               \r
-               if ((new_value < 2) || (new_value > 100))\r
-               {\r
-                       command_print(cmd_ctx, "valid settings are 2% to 100%");\r
-               }\r
-               else\r
-               {\r
-                       etm_ctx->trigger_percent = new_value;\r
-               }\r
-       }\r
-       \r
-       command_print(cmd_ctx, "%i percent of the tracebuffer reserved for after the trigger", etm_ctx->trigger_percent);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_etm_start_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target;\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       etm_context_t *etm_ctx;\r
-       reg_t *etm_ctrl_reg;\r
-\r
-       target = get_current_target(cmd_ctx);\r
-       \r
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (!(etm_ctx = arm7_9->etm_ctx))\r
-       {\r
-               command_print(cmd_ctx, "current target doesn't have an ETM configured");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       /* invalidate old tracing data */\r
-       arm7_9->etm_ctx->capture_status = TRACE_IDLE;\r
-       if (arm7_9->etm_ctx->trace_depth > 0)\r
-       {\r
-               free(arm7_9->etm_ctx->trace_data);\r
-               arm7_9->etm_ctx->trace_data = NULL;\r
-       }\r
-       arm7_9->etm_ctx->trace_depth = 0;\r
-               \r
-       etm_ctrl_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CTRL];\r
-       etm_get_reg(etm_ctrl_reg);\r
-               \r
-       /* Clear programming bit (10), set port selection bit (11) */\r
-       buf_set_u32(etm_ctrl_reg->value, 10, 2, 0x2);\r
-\r
-       etm_store_reg(etm_ctrl_reg);\r
-       jtag_execute_queue();\r
-\r
-       etm_ctx->capture_driver->start_capture(etm_ctx);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_etm_stop_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target;\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       etm_context_t *etm_ctx;\r
-       reg_t *etm_ctrl_reg;\r
-\r
-       target = get_current_target(cmd_ctx);\r
-       \r
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (!(etm_ctx = arm7_9->etm_ctx))\r
-       {\r
-               command_print(cmd_ctx, "current target doesn't have an ETM configured");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       etm_ctrl_reg = &arm7_9->etm_ctx->reg_cache->reg_list[ETM_CTRL];\r
-       etm_get_reg(etm_ctrl_reg);\r
-               \r
-       /* Set programming bit (10), clear port selection bit (11) */\r
-       buf_set_u32(etm_ctrl_reg->value, 10, 2, 0x1);\r
-\r
-       etm_store_reg(etm_ctrl_reg);    \r
-       jtag_execute_queue();\r
-       \r
-       etm_ctx->capture_driver->stop_capture(etm_ctx);\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int handle_etm_analyze_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)\r
-{\r
-       target_t *target;\r
-       armv4_5_common_t *armv4_5;\r
-       arm7_9_common_t *arm7_9;\r
-       etm_context_t *etm_ctx;\r
-       int retval;\r
-\r
-       target = get_current_target(cmd_ctx);\r
-       \r
-       if (arm7_9_get_arch_pointers(target, &armv4_5, &arm7_9) != ERROR_OK)\r
-       {\r
-               command_print(cmd_ctx, "current target isn't an ARM7/ARM9 target");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if (!(etm_ctx = arm7_9->etm_ctx))\r
-       {\r
-               command_print(cmd_ctx, "current target doesn't have an ETM configured");\r
-               return ERROR_OK;\r
-       }\r
-       \r
-       if ((retval = etmv1_analyze_trace(etm_ctx, cmd_ctx)) != ERROR_OK)\r
-       {\r
-               switch(retval)\r
-               {\r
-                       case ERROR_ETM_ANALYSIS_FAILED:\r
-                               command_print(cmd_ctx, "further analysis failed (corrupted trace data or just end of data");\r
-                               break;\r
-                       case ERROR_TRACE_INSTRUCTION_UNAVAILABLE:\r
-                               command_print(cmd_ctx, "no instruction for current address available, analysis aborted");\r
-                               break;\r
-                       case ERROR_TRACE_IMAGE_UNAVAILABLE:\r
-                               command_print(cmd_ctx, "no image available for trace analysis");\r
-                               break;\r
-                       default:\r
-                               command_print(cmd_ctx, "unknown error: %i", retval);\r
-               }\r
-       }\r
-       \r
-       return ERROR_OK;\r
-}\r
-\r
-int etm_register_commands(struct command_context_s *cmd_ctx)\r
-{\r
-       etm_cmd = register_command(cmd_ctx, NULL, "etm", NULL, COMMAND_ANY, "Embedded Trace Macrocell");\r
-\r
-       register_command(cmd_ctx, etm_cmd, "config", handle_etm_config_command, COMMAND_CONFIG, NULL);\r
-\r
-       return ERROR_OK;\r
-}\r
-\r
-int etm_register_user_commands(struct command_context_s *cmd_ctx)\r
-{\r
-       register_command(cmd_ctx, etm_cmd, "tracemode", handle_etm_tracemode_command,\r
-               COMMAND_EXEC, "configure trace mode <none|data|address|all> <context id bits> <cycle accurate> <branch output");\r
-\r
-       register_command(cmd_ctx, etm_cmd, "info", handle_etm_info_command,\r
-               COMMAND_EXEC, "display info about the current target's ETM");\r
-\r
-       register_command(cmd_ctx, etm_cmd, "trigger_percent <percent>", handle_etm_trigger_percent_command,\r
-               COMMAND_EXEC, "amount (<percent>) of trace buffer to be filled after the trigger occured");\r
-       register_command(cmd_ctx, etm_cmd, "status", handle_etm_status_command,\r
-               COMMAND_EXEC, "display current target's ETM status");\r
-       register_command(cmd_ctx, etm_cmd, "start", handle_etm_start_command,\r
-               COMMAND_EXEC, "start ETM trace collection");\r
-       register_command(cmd_ctx, etm_cmd, "stop", handle_etm_stop_command,\r
-               COMMAND_EXEC, "stop ETM trace collection");\r
-\r
-       register_command(cmd_ctx, etm_cmd, "analyze", handle_etm_analyze_command,\r
-               COMMAND_EXEC, "anaylze collected ETM trace");\r
-\r
-       register_command(cmd_ctx, etm_cmd, "image", handle_etm_image_command,\r
-               COMMAND_EXEC, "load image from <file> [base address]");\r
-\r
-       register_command(cmd_ctx, etm_cmd, "dump", handle_etm_dump_command,\r
-               COMMAND_EXEC, "dump captured trace data <file>");\r
-       register_command(cmd_ctx, etm_cmd, "load", handle_etm_load_command,\r
-               COMMAND_EXEC, "load trace data for analysis <file>");\r
-\r
-       return ERROR_OK;\r
-}\r
+/***************************************************************************
+ *   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;
+}

Linking to existing account procedure

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

SSH host keys fingerprints

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