2008-02-25 11:48:04 -06:00
|
|
|
/***************************************************************************
|
|
|
|
* Copyright (C) 2005 by Dominic Rath *
|
|
|
|
* Dominic.Rath@gmx.de *
|
|
|
|
* *
|
2008-09-20 05:50:53 -05:00
|
|
|
* Copyright (C) 2008 by Spencer Oliver *
|
|
|
|
* spen@spen-soft.co.uk *
|
|
|
|
* *
|
2008-10-30 02:49:13 -05:00
|
|
|
* Copyright (C) 2008 by Hongtao Zheng *
|
|
|
|
* hontor@126.com *
|
|
|
|
* *
|
2008-02-25 11:48:04 -06:00
|
|
|
* 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 *
|
2016-05-16 15:41:00 -05:00
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
2008-02-25 11:48:04 -06:00
|
|
|
***************************************************************************/
|
2012-02-05 06:03:04 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "arm9tdmi.h"
|
2009-05-31 07:38:28 -05:00
|
|
|
#include "target_type.h"
|
2009-11-16 02:35:14 -06:00
|
|
|
#include "register.h"
|
2009-12-07 16:54:12 -06:00
|
|
|
#include "arm_opcodes.h"
|
2016-07-22 15:43:11 -05:00
|
|
|
#include "arm_semihosting.h"
|
2008-02-25 11:48:04 -06:00
|
|
|
|
2009-09-17 03:02:43 -05:00
|
|
|
/*
|
|
|
|
* NOTE: this holds code that's used with multiple ARM9 processors:
|
|
|
|
* - ARM9TDMI (ARMv4T) ... in ARM920, ARM922, and ARM940 cores
|
|
|
|
* - ARM9E-S (ARMv5TE) ... in ARM946, ARM966, and ARM968 cores
|
|
|
|
* - ARM9EJS (ARMv5TEJ) ... in ARM926 core
|
|
|
|
*
|
|
|
|
* In short, the file name is a misnomer ... it is NOT specific to
|
|
|
|
* that first generation ARM9 processor, or cores using it.
|
|
|
|
*/
|
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
#if 0
|
|
|
|
#define _DEBUG_INSTRUCTION_EXECUTION_
|
|
|
|
#endif
|
|
|
|
|
2012-02-05 06:03:04 -06:00
|
|
|
enum arm9tdmi_vector_bit {
|
2009-11-17 03:09:50 -06:00
|
|
|
ARM9TDMI_RESET_VECTOR = 0x01,
|
|
|
|
ARM9TDMI_UNDEF_VECTOR = 0x02,
|
|
|
|
ARM9TDMI_SWI_VECTOR = 0x04,
|
|
|
|
ARM9TDMI_PABT_VECTOR = 0x08,
|
|
|
|
ARM9TDMI_DABT_VECTOR = 0x10,
|
|
|
|
/* BIT(5) reserved -- must be zero */
|
|
|
|
ARM9TDMI_IRQ_VECTOR = 0x40,
|
|
|
|
ARM9TDMI_FIQ_VECTOR = 0x80,
|
|
|
|
};
|
|
|
|
|
|
|
|
static const struct arm9tdmi_vector {
|
2010-12-29 15:07:21 -06:00
|
|
|
const char *name;
|
2009-11-17 03:09:50 -06:00
|
|
|
uint32_t value;
|
|
|
|
} arm9tdmi_vectors[] = {
|
2008-02-25 11:48:04 -06:00
|
|
|
{"reset", ARM9TDMI_RESET_VECTOR},
|
|
|
|
{"undef", ARM9TDMI_UNDEF_VECTOR},
|
|
|
|
{"swi", ARM9TDMI_SWI_VECTOR},
|
|
|
|
{"pabt", ARM9TDMI_PABT_VECTOR},
|
|
|
|
{"dabt", ARM9TDMI_DABT_VECTOR},
|
|
|
|
{"irq", ARM9TDMI_IRQ_VECTOR},
|
|
|
|
{"fiq", ARM9TDMI_FIQ_VECTOR},
|
|
|
|
{0, 0},
|
|
|
|
};
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
int arm9tdmi_examine_debug_reason(struct target *target)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
2008-10-14 06:06:30 -05:00
|
|
|
int retval = ERROR_OK;
|
2009-11-13 10:40:03 -06:00
|
|
|
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
/* only check the debug reason if we don't know it already */
|
|
|
|
if ((target->debug_reason != DBG_REASON_DBGRQ)
|
2012-02-05 06:03:04 -06:00
|
|
|
&& (target->debug_reason != DBG_REASON_SINGLESTEP)) {
|
2009-11-13 05:28:03 -06:00
|
|
|
struct scan_field fields[3];
|
2009-06-18 02:04:08 -05:00
|
|
|
uint8_t databus[4];
|
|
|
|
uint8_t instructionbus[4];
|
|
|
|
uint8_t debug_reason;
|
2008-02-25 11:48:04 -06:00
|
|
|
|
|
|
|
fields[0].num_bits = 32;
|
|
|
|
fields[0].out_value = NULL;
|
|
|
|
fields[0].in_value = databus;
|
2009-05-07 08:40:11 -05:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
fields[1].num_bits = 3;
|
|
|
|
fields[1].out_value = NULL;
|
|
|
|
fields[1].in_value = &debug_reason;
|
2009-05-07 08:40:11 -05:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
fields[2].num_bits = 32;
|
|
|
|
fields[2].out_value = NULL;
|
|
|
|
fields[2].in_value = instructionbus;
|
2009-05-07 08:40:11 -05:00
|
|
|
|
2012-02-05 06:03:04 -06:00
|
|
|
retval = arm_jtag_scann(&arm7_9->jtag_info, 0x1, TAP_DRPAUSE);
|
|
|
|
if (retval != ERROR_OK)
|
2008-10-14 06:06:30 -05:00
|
|
|
return retval;
|
2015-11-13 17:30:28 -06:00
|
|
|
retval = arm_jtag_set_instr(arm7_9->jtag_info.tap, arm7_9->jtag_info.intest_instr, NULL, TAP_DRPAUSE);
|
2010-07-19 07:37:45 -05:00
|
|
|
if (retval != ERROR_OK)
|
|
|
|
return retval;
|
2008-02-25 11:48:04 -06:00
|
|
|
|
2010-03-16 08:13:03 -05:00
|
|
|
jtag_add_dr_scan(arm7_9->jtag_info.tap, 3, fields, TAP_DRPAUSE);
|
2012-02-05 06:03:04 -06:00
|
|
|
retval = jtag_execute_queue();
|
|
|
|
if (retval != ERROR_OK)
|
2008-10-14 06:06:30 -05:00
|
|
|
return retval;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
fields[0].in_value = NULL;
|
|
|
|
fields[0].out_value = databus;
|
|
|
|
fields[1].in_value = NULL;
|
|
|
|
fields[1].out_value = &debug_reason;
|
|
|
|
fields[2].in_value = NULL;
|
|
|
|
fields[2].out_value = instructionbus;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2010-03-16 08:13:03 -05:00
|
|
|
jtag_add_dr_scan(arm7_9->jtag_info.tap, 3, fields, TAP_DRPAUSE);
|
2008-02-25 11:48:04 -06:00
|
|
|
|
|
|
|
if (debug_reason & 0x4)
|
|
|
|
if (debug_reason & 0x2)
|
|
|
|
target->debug_reason = DBG_REASON_WPTANDBKPT;
|
|
|
|
else
|
|
|
|
target->debug_reason = DBG_REASON_WATCHPOINT;
|
|
|
|
else
|
|
|
|
target->debug_reason = DBG_REASON_BREAKPOINT;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
2009-11-05 22:36:09 -06:00
|
|
|
/* put an instruction in the ARM9TDMI pipeline or write the data bus,
|
|
|
|
* and optionally read data
|
|
|
|
*/
|
2009-11-13 10:41:00 -06:00
|
|
|
int arm9tdmi_clock_out(struct arm_jtag *jtag_info, uint32_t instr,
|
2009-11-05 22:36:09 -06:00
|
|
|
uint32_t out, uint32_t *in, int sysspeed)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
2008-10-14 06:06:30 -05:00
|
|
|
int retval = ERROR_OK;
|
2009-11-13 05:28:03 -06:00
|
|
|
struct scan_field fields[3];
|
2009-06-18 02:04:08 -05:00
|
|
|
uint8_t out_buf[4];
|
|
|
|
uint8_t instr_buf[4];
|
|
|
|
uint8_t sysspeed_buf = 0x0;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
/* prepare buffer */
|
|
|
|
buf_set_u32(out_buf, 0, 32, out);
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
buf_set_u32(instr_buf, 0, 32, flip_u32(instr, 32));
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
if (sysspeed)
|
|
|
|
buf_set_u32(&sysspeed_buf, 2, 1, 1);
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2012-02-05 06:03:04 -06:00
|
|
|
retval = arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE);
|
|
|
|
if (retval != ERROR_OK)
|
2008-10-14 06:06:30 -05:00
|
|
|
return retval;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2015-11-13 17:30:28 -06:00
|
|
|
retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_DRPAUSE);
|
2010-07-19 07:37:45 -05:00
|
|
|
if (retval != ERROR_OK)
|
|
|
|
return retval;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
fields[0].num_bits = 32;
|
|
|
|
fields[0].out_value = out_buf;
|
|
|
|
fields[0].in_value = NULL;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
fields[1].num_bits = 3;
|
|
|
|
fields[1].out_value = &sysspeed_buf;
|
|
|
|
fields[1].in_value = NULL;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
fields[2].num_bits = 32;
|
|
|
|
fields[2].out_value = instr_buf;
|
|
|
|
fields[2].in_value = NULL;
|
|
|
|
|
2012-02-05 06:03:04 -06:00
|
|
|
if (in) {
|
2009-06-23 17:42:54 -05:00
|
|
|
fields[0].in_value = (uint8_t *)in;
|
2010-03-16 08:13:03 -05:00
|
|
|
jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_DRPAUSE);
|
2009-05-07 08:40:11 -05:00
|
|
|
|
2009-06-19 03:18:36 -05:00
|
|
|
jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)in);
|
2012-02-05 06:03:04 -06:00
|
|
|
} else
|
2010-03-16 08:13:03 -05:00
|
|
|
jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_DRPAUSE);
|
2008-02-25 11:48:04 -06:00
|
|
|
|
2010-03-18 12:31:58 -05:00
|
|
|
jtag_add_runtest(0, TAP_DRPAUSE);
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
#ifdef _DEBUG_INSTRUCTION_EXECUTION_
|
|
|
|
{
|
2012-02-05 06:03:04 -06:00
|
|
|
retval = jtag_execute_queue();
|
|
|
|
if (retval != ERROR_OK)
|
2008-10-14 06:06:30 -05:00
|
|
|
return retval;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
if (in)
|
2008-03-25 10:45:17 -05:00
|
|
|
LOG_DEBUG("instr: 0x%8.8x, out: 0x%8.8x, in: 0x%8.8x", instr, out, *in);
|
2008-02-25 11:48:04 -06:00
|
|
|
else
|
2008-03-25 10:45:17 -05:00
|
|
|
LOG_DEBUG("instr: 0x%8.8x, out: 0x%8.8x", instr, out);
|
2008-02-25 11:48:04 -06:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* just read data (instruction and data-out = don't care) */
|
2009-11-13 10:41:00 -06:00
|
|
|
int arm9tdmi_clock_data_in(struct arm_jtag *jtag_info, uint32_t *in)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
2012-02-05 06:03:04 -06:00
|
|
|
int retval = ERROR_OK;
|
2009-11-13 05:28:03 -06:00
|
|
|
struct scan_field fields[3];
|
2008-02-25 11:48:04 -06:00
|
|
|
|
2012-02-05 06:03:04 -06:00
|
|
|
retval = arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE);
|
|
|
|
if (retval != ERROR_OK)
|
2008-10-14 06:06:30 -05:00
|
|
|
return retval;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2015-11-13 17:30:28 -06:00
|
|
|
retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_DRPAUSE);
|
2010-07-19 07:37:45 -05:00
|
|
|
if (retval != ERROR_OK)
|
|
|
|
return retval;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
fields[0].num_bits = 32;
|
|
|
|
fields[0].out_value = NULL;
|
2009-06-18 02:04:08 -05:00
|
|
|
fields[0].in_value = (uint8_t *)in;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
fields[1].num_bits = 3;
|
|
|
|
fields[1].out_value = NULL;
|
|
|
|
fields[1].in_value = NULL;
|
2009-05-07 08:40:11 -05:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
fields[2].num_bits = 32;
|
|
|
|
fields[2].out_value = NULL;
|
|
|
|
fields[2].in_value = NULL;
|
2009-05-07 08:40:11 -05:00
|
|
|
|
2010-03-16 08:13:03 -05:00
|
|
|
jtag_add_dr_scan(jtag_info->tap, 3, fields, TAP_DRPAUSE);
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2009-06-19 03:18:36 -05:00
|
|
|
jtag_add_callback(arm_le_to_h_u32, (jtag_callback_data_t)in);
|
2008-02-25 11:48:04 -06:00
|
|
|
|
2010-03-16 08:13:03 -05:00
|
|
|
jtag_add_runtest(0, TAP_DRPAUSE);
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
#ifdef _DEBUG_INSTRUCTION_EXECUTION_
|
|
|
|
{
|
2012-02-05 06:03:04 -06:00
|
|
|
retval = jtag_execute_queue();
|
|
|
|
if (retval != ERROR_OK)
|
2008-10-14 06:06:30 -05:00
|
|
|
return retval;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
if (in)
|
2008-03-25 10:45:17 -05:00
|
|
|
LOG_DEBUG("in: 0x%8.8x", *in);
|
2008-02-25 11:48:04 -06:00
|
|
|
else
|
2008-03-25 10:45:17 -05:00
|
|
|
LOG_ERROR("BUG: called with in == NULL");
|
2008-02-25 11:48:04 -06:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* clock the target, and read the databus
|
|
|
|
* the *in pointer points to a buffer where elements of 'size' bytes
|
2009-06-23 17:42:03 -05:00
|
|
|
* are stored in big (be == 1) or little (be == 0) endianness
|
2008-02-25 11:48:04 -06:00
|
|
|
*/
|
2009-11-13 10:41:00 -06:00
|
|
|
int arm9tdmi_clock_data_in_endianness(struct arm_jtag *jtag_info,
|
2009-11-05 22:36:09 -06:00
|
|
|
void *in, int size, int be)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
2008-10-14 06:06:30 -05:00
|
|
|
int retval = ERROR_OK;
|
2012-08-22 12:42:02 -05:00
|
|
|
struct scan_field fields[2];
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2012-02-05 06:03:04 -06:00
|
|
|
retval = arm_jtag_scann(jtag_info, 0x1, TAP_DRPAUSE);
|
|
|
|
if (retval != ERROR_OK)
|
2008-10-14 06:06:30 -05:00
|
|
|
return retval;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2015-11-13 17:30:28 -06:00
|
|
|
retval = arm_jtag_set_instr(jtag_info->tap, jtag_info->intest_instr, NULL, TAP_DRPAUSE);
|
2010-07-19 07:37:45 -05:00
|
|
|
if (retval != ERROR_OK)
|
|
|
|
return retval;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2012-08-22 12:42:02 -05:00
|
|
|
if (size == 4) {
|
|
|
|
fields[0].num_bits = 32;
|
|
|
|
fields[0].out_value = NULL;
|
|
|
|
fields[0].in_value = in;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2012-08-22 12:42:02 -05:00
|
|
|
fields[1].num_bits = 3 + 32;
|
|
|
|
fields[1].out_value = NULL;
|
|
|
|
fields[1].in_value = NULL;
|
|
|
|
} else {
|
|
|
|
/* Discard irrelevant bits of the scan, making sure we don't write more
|
|
|
|
* than size bytes to in */
|
|
|
|
fields[0].num_bits = size * 8;
|
|
|
|
fields[0].out_value = NULL;
|
|
|
|
fields[0].in_value = in;
|
2009-05-07 08:40:11 -05:00
|
|
|
|
2012-08-22 12:42:02 -05:00
|
|
|
fields[1].num_bits = 3 + 32 + 32 - size * 8;
|
|
|
|
fields[1].out_value = NULL;
|
|
|
|
fields[1].in_value = NULL;
|
|
|
|
}
|
2009-05-07 08:40:11 -05:00
|
|
|
|
2012-08-22 12:42:02 -05:00
|
|
|
jtag_add_dr_scan(jtag_info->tap, 2, fields, TAP_DRPAUSE);
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2012-08-22 12:42:02 -05:00
|
|
|
jtag_add_callback4(arm7_9_endianness_callback,
|
2011-12-13 16:21:06 -06:00
|
|
|
(jtag_callback_data_t)in,
|
|
|
|
(jtag_callback_data_t)size,
|
|
|
|
(jtag_callback_data_t)be,
|
2012-08-22 12:42:02 -05:00
|
|
|
(jtag_callback_data_t)0);
|
2008-02-25 11:48:04 -06:00
|
|
|
|
2010-03-16 08:13:03 -05:00
|
|
|
jtag_add_runtest(0, TAP_DRPAUSE);
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
#ifdef _DEBUG_INSTRUCTION_EXECUTION_
|
|
|
|
{
|
2012-02-05 06:03:04 -06:00
|
|
|
retval = jtag_execute_queue();
|
|
|
|
if (retval != ERROR_OK)
|
2008-10-14 06:06:30 -05:00
|
|
|
return retval;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
if (in)
|
2012-02-05 06:03:04 -06:00
|
|
|
LOG_DEBUG("in: 0x%8.8x", *(uint32_t *)in);
|
2008-02-25 11:48:04 -06:00
|
|
|
else
|
2008-03-25 10:45:17 -05:00
|
|
|
LOG_ERROR("BUG: called with in == NULL");
|
2008-02-25 11:48:04 -06:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
static void arm9tdmi_change_to_arm(struct target *target,
|
2009-09-27 23:55:23 -05:00
|
|
|
uint32_t *r0, uint32_t *pc)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
2008-10-14 06:06:30 -05:00
|
|
|
int retval = ERROR_OK;
|
2009-11-13 10:40:03 -06:00
|
|
|
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
2009-11-13 10:41:00 -06:00
|
|
|
struct arm_jtag *jtag_info = &arm7_9->jtag_info;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
|
|
|
/* save r0 before using it and put system in ARM state
|
2008-02-25 11:48:04 -06:00
|
|
|
* to allow common handling of ARM and THUMB debugging */
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
/* fetch STR r0, [r0] */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
|
|
|
|
/* STR r0, [r0] in Memory */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, r0, 0);
|
|
|
|
|
2008-12-13 00:25:50 -06:00
|
|
|
/* MOV r0, r15 fetched, STR in Decode */
|
2008-02-25 11:48:04 -06:00
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_T_MOV(0, 15), 0, NULL, 0);
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_T_STR(0, 0), 0, NULL, 0);
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
|
|
|
|
/* nothing fetched, STR r0, [r0] in Memory */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, pc, 0);
|
|
|
|
|
|
|
|
/* use pc-relative LDR to clear r0[1:0] (for switch to ARM mode) */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), 0, NULL, 0);
|
|
|
|
/* LDR in Decode */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
|
|
|
|
/* LDR in Execute */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
|
|
|
|
/* LDR in Memory (to account for interlock) */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
|
|
|
|
|
|
|
|
/* fetch BX */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_T_BX(0), 0, NULL, 0);
|
|
|
|
/* NOP fetched, BX in Decode, MOV in Execute */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
|
|
|
|
/* NOP fetched, BX in Execute (1) */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2012-02-05 06:03:04 -06:00
|
|
|
retval = jtag_execute_queue();
|
|
|
|
if (retval != ERROR_OK)
|
2008-10-14 15:58:28 -05:00
|
|
|
return;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
/* fix program counter:
|
|
|
|
* MOV r0, r15 was the 5th instruction (+8)
|
|
|
|
* reading PC in Thumb state gives address of instruction + 4
|
|
|
|
*/
|
|
|
|
*pc -= 0xc;
|
|
|
|
}
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
void arm9tdmi_read_core_regs(struct target *target,
|
2012-02-05 06:03:04 -06:00
|
|
|
uint32_t mask, uint32_t *core_regs[16])
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
|
|
|
int i;
|
2009-11-13 10:40:03 -06:00
|
|
|
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
2009-11-13 10:41:00 -06:00
|
|
|
struct arm_jtag *jtag_info = &arm7_9->jtag_info;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
/* STMIA r0-15, [r0] at debug speed
|
|
|
|
* register values will start to appear on 4th DCLK
|
|
|
|
*/
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
|
|
|
|
|
|
|
|
/* fetch NOP, STM in DECODE stage */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
|
|
|
/* fetch NOP, STM in EXECUTE stage (1st cycle) */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
|
|
|
|
2012-02-05 06:03:04 -06:00
|
|
|
for (i = 0; i <= 15; i++) {
|
2008-02-25 11:48:04 -06:00
|
|
|
if (mask & (1 << i))
|
|
|
|
/* nothing fetched, STM in MEMORY (i'th cycle) */
|
|
|
|
arm9tdmi_clock_data_in(jtag_info, core_regs[i]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
static void arm9tdmi_read_core_regs_target_buffer(struct target *target,
|
2012-02-05 06:03:04 -06:00
|
|
|
uint32_t mask, void *buffer, int size)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
|
|
|
int i;
|
2009-11-13 10:40:03 -06:00
|
|
|
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
2009-11-13 10:41:00 -06:00
|
|
|
struct arm_jtag *jtag_info = &arm7_9->jtag_info;
|
2008-02-25 11:48:04 -06:00
|
|
|
int be = (target->endianness == TARGET_BIG_ENDIAN) ? 1 : 0;
|
2009-06-18 02:08:52 -05:00
|
|
|
uint32_t *buf_u32 = buffer;
|
2009-06-18 02:07:59 -05:00
|
|
|
uint16_t *buf_u16 = buffer;
|
2009-06-18 02:04:08 -05:00
|
|
|
uint8_t *buf_u8 = buffer;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
/* STMIA r0-15, [r0] at debug speed
|
|
|
|
* register values will start to appear on 4th DCLK
|
|
|
|
*/
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
|
|
|
|
|
|
|
|
/* fetch NOP, STM in DECODE stage */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
|
|
|
/* fetch NOP, STM in EXECUTE stage (1st cycle) */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
|
|
|
|
2012-02-05 06:03:04 -06:00
|
|
|
for (i = 0; i <= 15; i++) {
|
2008-02-25 11:48:04 -06:00
|
|
|
if (mask & (1 << i))
|
|
|
|
/* nothing fetched, STM in MEMORY (i'th cycle) */
|
2012-02-05 06:03:04 -06:00
|
|
|
switch (size) {
|
2008-02-25 11:48:04 -06:00
|
|
|
case 4:
|
|
|
|
arm9tdmi_clock_data_in_endianness(jtag_info, buf_u32++, 4, be);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
arm9tdmi_clock_data_in_endianness(jtag_info, buf_u16++, 2, be);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
arm9tdmi_clock_data_in_endianness(jtag_info, buf_u8++, 1, be);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
static void arm9tdmi_read_xpsr(struct target *target, uint32_t *xpsr, int spsr)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
2009-11-13 10:40:03 -06:00
|
|
|
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
2009-11-13 10:41:00 -06:00
|
|
|
struct arm_jtag *jtag_info = &arm7_9->jtag_info;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
/* MRS r0, cpsr */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_MRS(0, spsr & 1), 0, NULL, 0);
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
|
|
|
|
|
|
|
/* STR r0, [r15] */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_STR(0, 15), 0, NULL, 0);
|
|
|
|
/* fetch NOP, STR in DECODE stage */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
|
|
|
/* fetch NOP, STR in EXECUTE stage (1st cycle) */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
|
|
|
/* nothing fetched, STR in MEMORY */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, xpsr, 0);
|
|
|
|
}
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
static void arm9tdmi_write_xpsr(struct target *target, uint32_t xpsr, int spsr)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
2009-11-13 10:40:03 -06:00
|
|
|
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
2009-11-13 10:41:00 -06:00
|
|
|
struct arm_jtag *jtag_info = &arm7_9->jtag_info;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2009-06-20 22:15:36 -05:00
|
|
|
LOG_DEBUG("xpsr: %8.8" PRIx32 ", spsr: %i", xpsr, spsr);
|
2008-02-25 11:48:04 -06:00
|
|
|
|
|
|
|
/* MSR1 fetched */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr & 0xff, 0, 1, spsr), 0, NULL, 0);
|
|
|
|
/* MSR2 fetched, MSR1 in DECODE */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff00) >> 8, 0xc, 2, spsr), 0, NULL, 0);
|
|
|
|
/* MSR3 fetched, MSR1 in EXECUTE (1), MSR2 in DECODE */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff0000) >> 16, 0x8, 4, spsr), 0, NULL, 0);
|
|
|
|
/* nothing fetched, MSR1 in EXECUTE (2) */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
|
|
|
/* nothing fetched, MSR1 in EXECUTE (3) */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
|
|
|
/* MSR4 fetched, MSR2 in EXECUTE (1), MSR3 in DECODE */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM((xpsr & 0xff000000) >> 24, 0x4, 8, spsr), 0, NULL, 0);
|
|
|
|
/* nothing fetched, MSR2 in EXECUTE (2) */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
|
|
|
/* nothing fetched, MSR2 in EXECUTE (3) */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
|
|
|
/* NOP fetched, MSR3 in EXECUTE (1), MSR4 in DECODE */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
|
|
|
/* nothing fetched, MSR3 in EXECUTE (2) */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
|
|
|
/* nothing fetched, MSR3 in EXECUTE (3) */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
|
|
|
/* NOP fetched, MSR4 in EXECUTE (1) */
|
|
|
|
/* last MSR writes flags, which takes only one cycle */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
|
|
|
}
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
static void arm9tdmi_write_xpsr_im8(struct target *target,
|
2009-09-27 23:55:23 -05:00
|
|
|
uint8_t xpsr_im, int rot, int spsr)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
2009-11-13 10:40:03 -06:00
|
|
|
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
2009-11-13 10:41:00 -06:00
|
|
|
struct arm_jtag *jtag_info = &arm7_9->jtag_info;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-03-25 10:45:17 -05:00
|
|
|
LOG_DEBUG("xpsr_im: %2.2x, rot: %i, spsr: %i", xpsr_im, rot, spsr);
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
/* MSR fetched */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_MSR_IM(xpsr_im, rot, 1, spsr), 0, NULL, 0);
|
|
|
|
/* NOP fetched, MSR in DECODE */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
|
|
|
/* NOP fetched, MSR in EXECUTE (1) */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
/* rot == 4 writes flags, which takes only one cycle */
|
2012-02-05 06:03:04 -06:00
|
|
|
if (rot != 4) {
|
2008-02-25 11:48:04 -06:00
|
|
|
/* nothing fetched, MSR in EXECUTE (2) */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
|
|
|
/* nothing fetched, MSR in EXECUTE (3) */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
void arm9tdmi_write_core_regs(struct target *target,
|
2009-11-05 22:36:09 -06:00
|
|
|
uint32_t mask, uint32_t core_regs[16])
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
|
|
|
int i;
|
2009-11-13 10:40:03 -06:00
|
|
|
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
2009-11-13 10:41:00 -06:00
|
|
|
struct arm_jtag *jtag_info = &arm7_9->jtag_info;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
/* LDMIA r0-15, [r0] at debug speed
|
|
|
|
* register values will start to appear on 4th DCLK
|
|
|
|
*/
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 0), 0, NULL, 0);
|
|
|
|
|
|
|
|
/* fetch NOP, LDM in DECODE stage */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
|
|
|
/* fetch NOP, LDM in EXECUTE stage (1st cycle) */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
|
|
|
|
2012-02-05 06:03:04 -06:00
|
|
|
for (i = 0; i <= 15; i++) {
|
2008-02-25 11:48:04 -06:00
|
|
|
if (mask & (1 << i))
|
2009-06-23 17:44:17 -05:00
|
|
|
/* nothing fetched, LDM still in EXECUTE (1 + i cycle) */
|
2008-02-25 11:48:04 -06:00
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, core_regs[i], NULL, 0);
|
|
|
|
}
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
|
|
|
}
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
void arm9tdmi_load_word_regs(struct target *target, uint32_t mask)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
2009-11-13 10:40:03 -06:00
|
|
|
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
2009-11-13 10:41:00 -06:00
|
|
|
struct arm_jtag *jtag_info = &arm7_9->jtag_info;
|
2008-02-25 11:48:04 -06:00
|
|
|
|
|
|
|
/* put system-speed load-multiple into the pipeline */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, mask & 0xffff, 0, 1), 0, NULL, 0);
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
|
|
|
|
}
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
void arm9tdmi_load_hword_reg(struct target *target, int num)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
2009-11-13 10:40:03 -06:00
|
|
|
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
2009-11-13 10:41:00 -06:00
|
|
|
struct arm_jtag *jtag_info = &arm7_9->jtag_info;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
/* put system-speed load half-word into the pipeline */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_LDRH_IP(num, 0), 0, NULL, 0);
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
|
|
|
|
}
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
void arm9tdmi_load_byte_reg(struct target *target, int num)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
2009-11-13 10:40:03 -06:00
|
|
|
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
2009-11-13 10:41:00 -06:00
|
|
|
struct arm_jtag *jtag_info = &arm7_9->jtag_info;
|
2008-02-25 11:48:04 -06:00
|
|
|
|
|
|
|
/* put system-speed load byte into the pipeline */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_LDRB_IP(num, 0), 0, NULL, 0);
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
|
|
|
|
}
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
void arm9tdmi_store_word_regs(struct target *target, uint32_t mask)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
2009-11-13 10:40:03 -06:00
|
|
|
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
2009-11-13 10:41:00 -06:00
|
|
|
struct arm_jtag *jtag_info = &arm7_9->jtag_info;
|
2008-02-25 11:48:04 -06:00
|
|
|
|
|
|
|
/* put system-speed store-multiple into the pipeline */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_STMIA(0, mask, 0, 1), 0, NULL, 0);
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
|
|
|
|
}
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
void arm9tdmi_store_hword_reg(struct target *target, int num)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
2009-11-13 10:40:03 -06:00
|
|
|
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
2009-11-13 10:41:00 -06:00
|
|
|
struct arm_jtag *jtag_info = &arm7_9->jtag_info;
|
2008-02-25 11:48:04 -06:00
|
|
|
|
|
|
|
/* put system-speed store half-word into the pipeline */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_STRH_IP(num, 0), 0, NULL, 0);
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
|
|
|
|
}
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
void arm9tdmi_store_byte_reg(struct target *target, int num)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
2009-11-13 10:40:03 -06:00
|
|
|
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
2009-11-13 10:41:00 -06:00
|
|
|
struct arm_jtag *jtag_info = &arm7_9->jtag_info;
|
2008-02-25 11:48:04 -06:00
|
|
|
|
|
|
|
/* put system-speed store byte into the pipeline */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_STRB_IP(num, 0), 0, NULL, 0);
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
|
|
|
|
}
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
static void arm9tdmi_write_pc(struct target *target, uint32_t pc)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
2009-11-13 10:40:03 -06:00
|
|
|
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
2009-11-13 10:41:00 -06:00
|
|
|
struct arm_jtag *jtag_info = &arm7_9->jtag_info;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
/* LDMIA r0-15, [r0] at debug speed
|
|
|
|
* register values will start to appear on 4th DCLK
|
|
|
|
*/
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x8000, 0, 0), 0, NULL, 0);
|
|
|
|
|
|
|
|
/* fetch NOP, LDM in DECODE stage */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
|
|
|
/* fetch NOP, LDM in EXECUTE stage (1st cycle) */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
|
|
|
/* nothing fetched, LDM in EXECUTE stage (2nd cycle) (output data) */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, pc, NULL, 0);
|
|
|
|
/* nothing fetched, LDM in EXECUTE stage (3rd cycle) */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
|
|
|
/* fetch NOP, LDM in EXECUTE stage (4th cycle) */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
|
|
|
/* fetch NOP, LDM in EXECUTE stage (5th cycle) */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
|
|
|
}
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
void arm9tdmi_branch_resume(struct target *target)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
2009-11-13 10:40:03 -06:00
|
|
|
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
2009-11-13 10:41:00 -06:00
|
|
|
struct arm_jtag *jtag_info = &arm7_9->jtag_info;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_B(0xfffffc, 0), 0, NULL, 0);
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 1);
|
|
|
|
}
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
static void arm9tdmi_branch_resume_thumb(struct target *target)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
2008-03-25 10:45:17 -05:00
|
|
|
LOG_DEBUG("-");
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2009-11-13 10:40:03 -06:00
|
|
|
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
2012-01-19 04:06:37 -06:00
|
|
|
struct arm *arm = &arm7_9->arm;
|
2009-11-13 10:41:00 -06:00
|
|
|
struct arm_jtag *jtag_info = &arm7_9->jtag_info;
|
2009-11-13 11:55:49 -06:00
|
|
|
struct reg *dbg_stat = &arm7_9->eice_cache->reg_list[EICE_DBG_STAT];
|
2008-02-25 11:48:04 -06:00
|
|
|
|
|
|
|
/* LDMIA r0-15, [r0] at debug speed
|
|
|
|
* register values will start to appear on 4th DCLK
|
|
|
|
*/
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_LDMIA(0, 0x1, 0, 0), 0, NULL, 0);
|
|
|
|
|
|
|
|
/* fetch NOP, LDM in DECODE stage */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
|
|
|
/* fetch NOP, LDM in EXECUTE stage (1st cycle) */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
|
|
|
/* nothing fetched, LDM in EXECUTE stage (2nd cycle) */
|
2010-02-21 16:34:33 -06:00
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP,
|
2012-01-19 04:06:37 -06:00
|
|
|
buf_get_u32(arm->pc->value, 0, 32) | 1, NULL, 0);
|
2008-02-25 11:48:04 -06:00
|
|
|
/* nothing fetched, LDM in EXECUTE stage (3rd cycle) */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
|
|
|
|
|
|
|
/* Branch and eXchange */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_BX(0), 0, NULL, 0);
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
embeddedice_read_reg(dbg_stat);
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
/* fetch NOP, BX in DECODE stage */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
embeddedice_read_reg(dbg_stat);
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
/* fetch NOP, BX in EXECUTE stage (1st cycle) */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_NOP, 0, NULL, 0);
|
|
|
|
|
|
|
|
/* target is now in Thumb state */
|
|
|
|
embeddedice_read_reg(dbg_stat);
|
|
|
|
|
|
|
|
/* load r0 value, MOV_IM in Decode*/
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_T_LDR_PCREL(0), 0, NULL, 0);
|
|
|
|
/* fetch NOP, LDR in Decode, MOV_IM in Execute */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
|
|
|
|
/* fetch NOP, LDR in Execute */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
|
|
|
|
/* nothing fetched, LDR in EXECUTE stage (2nd cycle) */
|
2012-01-19 04:06:37 -06:00
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP,
|
|
|
|
buf_get_u32(arm->core_cache->reg_list[0].value, 0, 32), NULL, 0);
|
2008-02-25 11:48:04 -06:00
|
|
|
/* nothing fetched, LDR in EXECUTE stage (3rd cycle) */
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
|
|
|
|
|
|
|
|
embeddedice_read_reg(dbg_stat);
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_T_B(0x7f7), 0, NULL, 1);
|
|
|
|
arm9tdmi_clock_out(jtag_info, ARMV4_5_T_NOP, 0, NULL, 0);
|
|
|
|
}
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
void arm9tdmi_enable_single_step(struct target *target, uint32_t next_pc)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
2009-11-13 10:40:03 -06:00
|
|
|
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2012-02-05 06:03:04 -06:00
|
|
|
if (arm7_9->has_single_step) {
|
2008-02-25 11:48:04 -06:00
|
|
|
buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 3, 1, 1);
|
|
|
|
embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
|
2012-02-05 06:03:04 -06:00
|
|
|
} else
|
2008-10-30 02:49:13 -05:00
|
|
|
arm7_9_enable_eice_step(target, next_pc);
|
2008-02-25 11:48:04 -06:00
|
|
|
}
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
void arm9tdmi_disable_single_step(struct target *target)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
2009-11-13 10:40:03 -06:00
|
|
|
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2012-02-05 06:03:04 -06:00
|
|
|
if (arm7_9->has_single_step) {
|
2008-02-25 11:48:04 -06:00
|
|
|
buf_set_u32(arm7_9->eice_cache->reg_list[EICE_DBG_CTRL].value, 3, 1, 0);
|
|
|
|
embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_DBG_CTRL]);
|
2012-02-05 06:03:04 -06:00
|
|
|
} else
|
2008-02-25 11:48:04 -06:00
|
|
|
arm7_9_disable_eice_step(target);
|
|
|
|
}
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
static void arm9tdmi_build_reg_cache(struct target *target)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
2009-11-13 10:44:08 -06:00
|
|
|
struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache);
|
2012-01-19 04:06:37 -06:00
|
|
|
struct arm *arm = target_to_arm(target);
|
2008-02-25 11:48:04 -06:00
|
|
|
|
2012-01-19 04:06:37 -06:00
|
|
|
(*cache_p) = arm_build_reg_cache(target, arm);
|
2008-02-25 11:48:04 -06:00
|
|
|
}
|
|
|
|
|
2009-11-13 15:25:47 -06:00
|
|
|
int arm9tdmi_init_target(struct command_context *cmd_ctx,
|
2009-11-13 12:11:13 -06:00
|
|
|
struct target *target)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
|
|
|
arm9tdmi_build_reg_cache(target);
|
2016-07-22 15:43:11 -05:00
|
|
|
arm_semihosting_init(target);
|
2008-02-25 11:48:04 -06:00
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
2009-11-17 03:09:50 -06:00
|
|
|
int arm9tdmi_init_arch_info(struct target *target,
|
|
|
|
struct arm7_9_common *arm7_9, struct jtag_tap *tap)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
|
|
|
/* prepare JTAG information for the new target */
|
2008-11-30 16:25:43 -06:00
|
|
|
arm7_9->jtag_info.tap = tap;
|
2008-02-25 11:48:04 -06:00
|
|
|
arm7_9->jtag_info.scann_size = 5;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
/* register arch-specific functions */
|
|
|
|
arm7_9->examine_debug_reason = arm9tdmi_examine_debug_reason;
|
|
|
|
arm7_9->change_to_arm = arm9tdmi_change_to_arm;
|
|
|
|
arm7_9->read_core_regs = arm9tdmi_read_core_regs;
|
|
|
|
arm7_9->read_core_regs_target_buffer = arm9tdmi_read_core_regs_target_buffer;
|
|
|
|
arm7_9->read_xpsr = arm9tdmi_read_xpsr;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
arm7_9->write_xpsr = arm9tdmi_write_xpsr;
|
|
|
|
arm7_9->write_xpsr_im8 = arm9tdmi_write_xpsr_im8;
|
|
|
|
arm7_9->write_core_regs = arm9tdmi_write_core_regs;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
arm7_9->load_word_regs = arm9tdmi_load_word_regs;
|
|
|
|
arm7_9->load_hword_reg = arm9tdmi_load_hword_reg;
|
|
|
|
arm7_9->load_byte_reg = arm9tdmi_load_byte_reg;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
arm7_9->store_word_regs = arm9tdmi_store_word_regs;
|
|
|
|
arm7_9->store_hword_reg = arm9tdmi_store_hword_reg;
|
|
|
|
arm7_9->store_byte_reg = arm9tdmi_store_byte_reg;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
arm7_9->write_pc = arm9tdmi_write_pc;
|
|
|
|
arm7_9->branch_resume = arm9tdmi_branch_resume;
|
|
|
|
arm7_9->branch_resume_thumb = arm9tdmi_branch_resume_thumb;
|
|
|
|
|
|
|
|
arm7_9->enable_single_step = arm9tdmi_enable_single_step;
|
|
|
|
arm7_9->disable_single_step = arm9tdmi_disable_single_step;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2013-10-04 17:19:08 -05:00
|
|
|
arm7_9->write_memory = arm7_9_write_memory;
|
2013-03-11 16:21:13 -05:00
|
|
|
arm7_9->bulk_write_memory = arm7_9_bulk_write_memory;
|
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
arm7_9->post_debug_entry = NULL;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
arm7_9->pre_restore_context = NULL;
|
|
|
|
|
|
|
|
/* initialize arch-specific breakpoint handling */
|
|
|
|
arm7_9->arm_bkpt = 0xdeeedeee;
|
|
|
|
arm7_9->thumb_bkpt = 0xdeee;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
arm7_9->dbgreq_adjust_pc = 3;
|
|
|
|
|
|
|
|
arm7_9_init_arch_info(target, arm7_9);
|
|
|
|
|
|
|
|
/* override use of DBGRQ, this is safe on ARM9TDMI */
|
|
|
|
arm7_9->use_dbgrq = 1;
|
|
|
|
|
|
|
|
/* all ARM9s have the vector catch register */
|
|
|
|
arm7_9->has_vector_catch = 1;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
2009-11-13 12:11:13 -06:00
|
|
|
static int arm9tdmi_target_create(struct target *target, Jim_Interp *interp)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
2012-02-05 06:03:04 -06:00
|
|
|
struct arm7_9_common *arm7_9 = calloc(1, sizeof(struct arm7_9_common));
|
2008-02-25 11:48:04 -06:00
|
|
|
|
2009-11-17 03:09:50 -06:00
|
|
|
arm9tdmi_init_arch_info(target, arm7_9, target->tap);
|
2012-01-19 04:06:37 -06:00
|
|
|
arm7_9->arm.is_armv4 = true;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
return ERROR_OK;
|
|
|
|
}
|
|
|
|
|
2020-05-25 04:28:22 -05:00
|
|
|
void arm9tdmi_deinit_target(struct target *target)
|
|
|
|
{
|
|
|
|
struct arm *arm = target_to_arm(target);
|
|
|
|
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
|
|
|
|
|
|
|
arm7_9_deinit(target);
|
|
|
|
arm_free_reg_cache(arm);
|
|
|
|
free(arm7_9);
|
|
|
|
}
|
|
|
|
|
2009-11-10 01:56:52 -06:00
|
|
|
COMMAND_HANDLER(handle_arm9tdmi_catch_vectors_command)
|
2008-02-25 11:48:04 -06:00
|
|
|
{
|
2009-11-15 07:57:37 -06:00
|
|
|
struct target *target = get_current_target(CMD_CTX);
|
2009-11-13 10:40:03 -06:00
|
|
|
struct arm7_9_common *arm7_9 = target_to_arm7_9(target);
|
2009-11-13 11:55:49 -06:00
|
|
|
struct reg *vector_catch;
|
2009-06-18 02:08:52 -05:00
|
|
|
uint32_t vector_catch_value;
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2012-02-05 06:03:04 -06:00
|
|
|
if (!target_was_examined(target)) {
|
2009-12-30 12:43:56 -06:00
|
|
|
LOG_ERROR("Target not examined yet");
|
|
|
|
return ERROR_FAIL;
|
|
|
|
}
|
|
|
|
|
2009-11-06 00:03:40 -06:00
|
|
|
/* it's uncommon, but some ARM7 chips can support this */
|
|
|
|
if (arm7_9->common_magic != ARM7_9_COMMON_MAGIC
|
|
|
|
|| !arm7_9->has_vector_catch) {
|
helper/command: change prototype of command_print/command_print_sameline
To prepare for handling TCL return values consistently, all calls
to command_print/command_print_sameline should switch to CMD as
first parameter.
Change prototype of command_print() and command_print_sameline()
to pass CMD instead of CMD_CTX.
Since the first parameter is currently not used, the change can be
done though scripts without manual coding.
This patch is created using the command:
sed -i PATTERN $(find src/ doc/ -type f)
with all the following patters:
's/\(command_print(cmd\)->ctx,/\1,/'
's/\(command_print(CMD\)_CTX,/\1,/'
's/\(command_print(struct command_\)context \*context,/\1invocation *cmd,/'
's/\(command_print_sameline(cmd\)->ctx,/\1,/'
's/\(command_print_sameline(CMD\)_CTX,/\1,/'
's/\(command_print_sameline(struct command_\)context \*context,/\1invocation *cmd,/'
This change is inspired by http://openocd.zylin.com/1815 from Paul
Fertser but is now done through scripting.
Change-Id: I3386d8f96cdc477e7a2308dd18269de3bed04385
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Signed-off-by: Paul Fertser <fercerpav@gmail.com>
Reviewed-on: http://openocd.zylin.com/5081
Tested-by: jenkins
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
2019-04-03 03:37:24 -05:00
|
|
|
command_print(CMD, "target doesn't have EmbeddedICE "
|
2009-11-06 00:03:40 -06:00
|
|
|
"with vector_catch");
|
|
|
|
return ERROR_TARGET_INVALID;
|
2008-02-25 11:48:04 -06:00
|
|
|
}
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
vector_catch = &arm7_9->eice_cache->reg_list[EICE_VEC_CATCH];
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
/* read the vector catch register if necessary */
|
|
|
|
if (!vector_catch->valid)
|
|
|
|
embeddedice_read_reg(vector_catch);
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
/* get the current setting */
|
2009-08-18 05:22:44 -05:00
|
|
|
vector_catch_value = buf_get_u32(vector_catch->value, 0, 8);
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2012-02-05 06:03:04 -06:00
|
|
|
if (CMD_ARGC > 0) {
|
2008-02-25 11:48:04 -06:00
|
|
|
vector_catch_value = 0x0;
|
2009-11-15 10:15:59 -06:00
|
|
|
if (strcmp(CMD_ARGV[0], "all") == 0)
|
2008-02-25 11:48:04 -06:00
|
|
|
vector_catch_value = 0xdf;
|
2012-02-05 06:03:04 -06:00
|
|
|
else if (strcmp(CMD_ARGV[0], "none") == 0) {
|
2008-02-25 11:48:04 -06:00
|
|
|
/* do nothing */
|
2012-02-05 06:03:04 -06:00
|
|
|
} else {
|
|
|
|
for (unsigned i = 0; i < CMD_ARGC; i++) {
|
2008-02-25 11:48:04 -06:00
|
|
|
/* go through list of vectors */
|
2009-11-10 02:02:18 -06:00
|
|
|
unsigned j;
|
2012-02-05 06:03:04 -06:00
|
|
|
for (j = 0; arm9tdmi_vectors[j].name; j++) {
|
|
|
|
if (strcmp(CMD_ARGV[i], arm9tdmi_vectors[j].name) == 0) {
|
2008-02-25 11:48:04 -06:00
|
|
|
vector_catch_value |= arm9tdmi_vectors[j].value;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
/* complain if vector wasn't found */
|
2012-02-05 06:03:04 -06:00
|
|
|
if (!arm9tdmi_vectors[j].name) {
|
helper/command: change prototype of command_print/command_print_sameline
To prepare for handling TCL return values consistently, all calls
to command_print/command_print_sameline should switch to CMD as
first parameter.
Change prototype of command_print() and command_print_sameline()
to pass CMD instead of CMD_CTX.
Since the first parameter is currently not used, the change can be
done though scripts without manual coding.
This patch is created using the command:
sed -i PATTERN $(find src/ doc/ -type f)
with all the following patters:
's/\(command_print(cmd\)->ctx,/\1,/'
's/\(command_print(CMD\)_CTX,/\1,/'
's/\(command_print(struct command_\)context \*context,/\1invocation *cmd,/'
's/\(command_print_sameline(cmd\)->ctx,/\1,/'
's/\(command_print_sameline(CMD\)_CTX,/\1,/'
's/\(command_print_sameline(struct command_\)context \*context,/\1invocation *cmd,/'
This change is inspired by http://openocd.zylin.com/1815 from Paul
Fertser but is now done through scripting.
Change-Id: I3386d8f96cdc477e7a2308dd18269de3bed04385
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Signed-off-by: Paul Fertser <fercerpav@gmail.com>
Reviewed-on: http://openocd.zylin.com/5081
Tested-by: jenkins
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
2019-04-03 03:37:24 -05:00
|
|
|
command_print(CMD, "vector '%s' not found, leaving current setting unchanged", CMD_ARGV[i]);
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
/* reread current setting */
|
2009-08-18 05:22:44 -05:00
|
|
|
vector_catch_value = buf_get_u32(
|
|
|
|
vector_catch->value,
|
|
|
|
0, 8);
|
2008-02-25 11:48:04 -06:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2008-02-25 11:48:04 -06:00
|
|
|
/* store new settings */
|
2009-08-18 05:22:44 -05:00
|
|
|
buf_set_u32(vector_catch->value, 0, 8, vector_catch_value);
|
2008-02-25 11:48:04 -06:00
|
|
|
embeddedice_store_reg(vector_catch);
|
|
|
|
}
|
2008-12-13 00:25:50 -06:00
|
|
|
|
2009-10-31 20:03:54 -05:00
|
|
|
/* output current settings */
|
2009-11-10 02:02:18 -06:00
|
|
|
for (unsigned i = 0; arm9tdmi_vectors[i].name; i++) {
|
helper/command: change prototype of command_print/command_print_sameline
To prepare for handling TCL return values consistently, all calls
to command_print/command_print_sameline should switch to CMD as
first parameter.
Change prototype of command_print() and command_print_sameline()
to pass CMD instead of CMD_CTX.
Since the first parameter is currently not used, the change can be
done though scripts without manual coding.
This patch is created using the command:
sed -i PATTERN $(find src/ doc/ -type f)
with all the following patters:
's/\(command_print(cmd\)->ctx,/\1,/'
's/\(command_print(CMD\)_CTX,/\1,/'
's/\(command_print(struct command_\)context \*context,/\1invocation *cmd,/'
's/\(command_print_sameline(cmd\)->ctx,/\1,/'
's/\(command_print_sameline(CMD\)_CTX,/\1,/'
's/\(command_print_sameline(struct command_\)context \*context,/\1invocation *cmd,/'
This change is inspired by http://openocd.zylin.com/1815 from Paul
Fertser but is now done through scripting.
Change-Id: I3386d8f96cdc477e7a2308dd18269de3bed04385
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Signed-off-by: Paul Fertser <fercerpav@gmail.com>
Reviewed-on: http://openocd.zylin.com/5081
Tested-by: jenkins
Reviewed-by: Tomas Vanek <vanekt@fbl.cz>
2019-04-03 03:37:24 -05:00
|
|
|
command_print(CMD, "%s: %s", arm9tdmi_vectors[i].name,
|
2009-10-31 20:03:54 -05:00
|
|
|
(vector_catch_value & arm9tdmi_vectors[i].value)
|
|
|
|
? "catch" : "don't catch");
|
2008-02-25 11:48:04 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
return ERROR_OK;
|
|
|
|
}
|
2009-09-27 23:55:23 -05:00
|
|
|
|
2009-11-23 09:43:05 -06:00
|
|
|
static const struct command_registration arm9tdmi_exec_command_handlers[] = {
|
|
|
|
{
|
|
|
|
.name = "vector_catch",
|
|
|
|
.handler = handle_arm9tdmi_catch_vectors_command,
|
|
|
|
.mode = COMMAND_EXEC,
|
2010-01-07 18:41:42 -06:00
|
|
|
.help = "Display, after optionally updating, configuration "
|
|
|
|
"of vector catch unit.",
|
|
|
|
.usage = "[all|none|(reset|undef|swi|pabt|dabt|irq|fiq)*]",
|
2009-11-23 09:43:05 -06:00
|
|
|
},
|
|
|
|
COMMAND_REGISTRATION_DONE
|
|
|
|
};
|
2009-11-23 10:17:01 -06:00
|
|
|
const struct command_registration arm9tdmi_command_handlers[] = {
|
|
|
|
{
|
|
|
|
.chain = arm7_9_command_handlers,
|
|
|
|
},
|
2009-11-23 09:43:05 -06:00
|
|
|
{
|
2010-07-12 13:48:45 -05:00
|
|
|
.name = "arm9",
|
2009-11-23 09:43:05 -06:00
|
|
|
.mode = COMMAND_ANY,
|
2010-07-12 13:48:45 -05:00
|
|
|
.help = "arm9 command group",
|
2012-01-16 07:35:23 -06:00
|
|
|
.usage = "",
|
2009-11-23 09:43:05 -06:00
|
|
|
.chain = arm9tdmi_exec_command_handlers,
|
|
|
|
},
|
|
|
|
COMMAND_REGISTRATION_DONE
|
|
|
|
};
|
|
|
|
|
2009-11-05 22:36:09 -06:00
|
|
|
/** Holds methods for ARM9TDMI targets. */
|
2012-02-05 06:03:04 -06:00
|
|
|
struct target_type arm9tdmi_target = {
|
2009-11-05 22:36:09 -06:00
|
|
|
.name = "arm9tdmi",
|
|
|
|
|
|
|
|
.poll = arm7_9_poll,
|
2009-12-07 16:54:13 -06:00
|
|
|
.arch_state = arm_arch_state,
|
2009-11-05 22:36:09 -06:00
|
|
|
|
|
|
|
.target_request_data = arm7_9_target_request_data,
|
|
|
|
|
|
|
|
.halt = arm7_9_halt,
|
|
|
|
.resume = arm7_9_resume,
|
|
|
|
.step = arm7_9_step,
|
|
|
|
|
|
|
|
.assert_reset = arm7_9_assert_reset,
|
|
|
|
.deassert_reset = arm7_9_deassert_reset,
|
|
|
|
.soft_reset_halt = arm7_9_soft_reset_halt,
|
|
|
|
|
target/arm: add support for multi-architecture gdb
GDB can be built for multi-architecture through the command
./configure --enable-targets=all && make
Such multi-architecture GDB requires the target's architecture to
be selected either manually by the user through the GDB command
"set architecture" or automatically by the target description sent
by the remote target (i.e. OpenOCD).
Commit e65acd889c61a424c7bd72fdee5d6a3aee1d8504 ("gdb_server: add
support for architecture element") already provides the required
infrastructure to support multi-architecture gdb.
arm-none-eabi-gdb 8.2 uses "arm" as default architecture, but also
supports the following values: "arm_any", "armv2", "armv2a",
"armv3", "armv3m", "armv4", "armv4t", "armv5", "armv5t", "armv5te",
"armv5tej", "armv6", "armv6k", "armv6kz", "armv6-m", "armv6s-m",
"armv6t2", "armv7", "armv7e-m", "armv8-a", "armv8-m.base",
"armv8-m.main", "armv8-r", "ep9312", "iwmmxt", "iwmmxt2", "xscale".
These values can be displayed on arm gdb prompt by typing
"set architecture " followed by a TAB for autocompletion.
Set the gdb architecture value for all arm targets to "arm".
Change-Id: I176cb89878606e1febd546ce26543b3e7849500a
Signed-off-by: Antonio Borneo <borneo.antonio@gmail.com>
Reviewed-on: http://openocd.zylin.com/4754
Tested-by: jenkins
Reviewed-by: Spencer Oliver <spen@spen-soft.co.uk>
2018-11-01 08:50:27 -05:00
|
|
|
.get_gdb_arch = arm_get_gdb_arch,
|
2009-12-07 16:54:13 -06:00
|
|
|
.get_gdb_reg_list = arm_get_gdb_reg_list,
|
2009-11-05 22:36:09 -06:00
|
|
|
|
|
|
|
.read_memory = arm7_9_read_memory,
|
2013-03-11 16:21:13 -05:00
|
|
|
.write_memory = arm7_9_write_memory_opt,
|
2009-11-15 12:35:34 -06:00
|
|
|
|
|
|
|
.checksum_memory = arm_checksum_memory,
|
|
|
|
.blank_check_memory = arm_blank_check_memory,
|
2009-11-05 22:36:09 -06:00
|
|
|
|
|
|
|
.run_algorithm = armv4_5_run_algorithm,
|
|
|
|
|
|
|
|
.add_breakpoint = arm7_9_add_breakpoint,
|
|
|
|
.remove_breakpoint = arm7_9_remove_breakpoint,
|
|
|
|
.add_watchpoint = arm7_9_add_watchpoint,
|
|
|
|
.remove_watchpoint = arm7_9_remove_watchpoint,
|
|
|
|
|
2009-11-23 10:17:01 -06:00
|
|
|
.commands = arm9tdmi_command_handlers,
|
2009-11-05 22:36:09 -06:00
|
|
|
.target_create = arm9tdmi_target_create,
|
|
|
|
.init_target = arm9tdmi_init_target,
|
2020-05-25 04:28:22 -05:00
|
|
|
.deinit_target = arm9tdmi_deinit_target,
|
2009-11-13 18:26:39 -06:00
|
|
|
.examine = arm7_9_examine,
|
2010-01-11 08:30:22 -06:00
|
|
|
.check_reset = arm7_9_check_reset,
|
2009-11-05 22:36:09 -06:00
|
|
|
};
|