aboutsummaryrefslogtreecommitdiff
path: root/src/target
diff options
context:
space:
mode:
Diffstat (limited to 'src/target')
-rw-r--r--src/target/Makefile.am1
-rw-r--r--src/target/aarch64.c137
-rw-r--r--src/target/adi_v5_jtag.c28
-rw-r--r--src/target/adi_v5_swd.c60
-rw-r--r--src/target/arm.h50
-rw-r--r--src/target/arm_adi_v5.c221
-rw-r--r--src/target/arm_adi_v5.h19
-rw-r--r--src/target/arm_cti.c435
-rw-r--r--src/target/arm_cti.h8
-rw-r--r--src/target/arm_dap.c366
-rw-r--r--src/target/arm_disassembler.c1
-rw-r--r--src/target/arm_dpm.c115
-rw-r--r--src/target/arm_opcodes.h24
-rw-r--r--src/target/armv4_5.c93
-rw-r--r--src/target/armv7a.c50
-rw-r--r--src/target/armv7a.h1
-rw-r--r--src/target/armv7a_cache.c7
-rw-r--r--src/target/armv7m.c3
-rw-r--r--src/target/armv8.c594
-rw-r--r--src/target/armv8.h63
-rw-r--r--src/target/armv8_cache.c9
-rw-r--r--src/target/armv8_dpm.c89
-rw-r--r--src/target/armv8_dpm.h2
-rw-r--r--src/target/armv8_opcodes.h8
-rw-r--r--src/target/cortex_a.c75
-rw-r--r--src/target/cortex_m.c49
-rw-r--r--src/target/hla_target.c35
-rw-r--r--src/target/image.c593
-rw-r--r--src/target/openrisc/jsp_server.c4
-rw-r--r--src/target/openrisc/jsp_server.h1
-rw-r--r--src/target/register.h3
-rw-r--r--src/target/riscv/batch.c5
-rw-r--r--src/target/riscv/encoding.h24
-rw-r--r--src/target/riscv/riscv-011.c6
-rw-r--r--src/target/riscv/riscv-013.c326
-rw-r--r--src/target/riscv/riscv.c176
-rw-r--r--src/target/riscv/riscv.h7
-rw-r--r--src/target/startup.tcl1
-rw-r--r--src/target/stm8.c3
-rw-r--r--src/target/target.c150
-rw-r--r--src/target/target.h13
41 files changed, 2911 insertions, 944 deletions
diff --git a/src/target/Makefile.am b/src/target/Makefile.am
index 9576b23..030015a 100644
--- a/src/target/Makefile.am
+++ b/src/target/Makefile.am
@@ -89,6 +89,7 @@ ARM_DEBUG_SRC = \
%D%/arm_simulator.c \
%D%/arm_semihosting.c \
%D%/arm_adi_v5.c \
+ %D%/arm_dap.c \
%D%/armv7a_cache.c \
%D%/armv7a_cache_l2x.c \
%D%/adi_v5_jtag.c \
diff --git a/src/target/aarch64.c b/src/target/aarch64.c
index 14a2da6..4641a3f 100644
--- a/src/target/aarch64.c
+++ b/src/target/aarch64.c
@@ -40,6 +40,11 @@ enum halt_mode {
HALT_SYNC,
};
+struct aarch64_private_config {
+ struct adiv5_private_config adiv5_config;
+ struct arm_cti *cti;
+};
+
static int aarch64_poll(struct target *target);
static int aarch64_debug_entry(struct target *target);
static int aarch64_restore_context(struct target *target, bool bpwp);
@@ -452,7 +457,7 @@ static int update_halt_gdb(struct target *target, enum target_debug_reason debug
struct target *curr;
if (debug_reason == DBG_REASON_NOTHALTED) {
- LOG_INFO("Halting remaining targets in SMP group");
+ LOG_DEBUG("Halting remaining targets in SMP group");
aarch64_halt_smp(target, true);
}
@@ -1086,7 +1091,7 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres
if (retval != ERROR_OK)
return retval;
- if (target->smp && !handle_breakpoints) {
+ if (target->smp && (current == 1)) {
/*
* isolate current target so that it doesn't get resumed
* together with the others
@@ -1861,7 +1866,7 @@ static int aarch64_write_cpu_memory(struct target *target,
if (dscr & (DSCR_ERR | DSCR_SYS_ERROR_PEND)) {
/* Abort occurred - clear it and exit */
LOG_ERROR("abort occurred - dscr = 0x%08" PRIx32, dscr);
- armv8_dpm_handle_exception(dpm);
+ armv8_dpm_handle_exception(dpm, true);
return ERROR_FAIL;
}
@@ -2080,7 +2085,7 @@ static int aarch64_read_cpu_memory(struct target *target,
if (dscr & (DSCR_ERR | DSCR_SYS_ERROR_PEND)) {
/* Abort occurred - clear it and exit */
LOG_ERROR("abort occurred - dscr = 0x%08" PRIx32, dscr);
- armv8_dpm_handle_exception(dpm);
+ armv8_dpm_handle_exception(dpm, true);
return ERROR_FAIL;
}
@@ -2198,7 +2203,7 @@ static int aarch64_examine_first(struct target *target)
struct aarch64_common *aarch64 = target_to_aarch64(target);
struct armv8_common *armv8 = &aarch64->armv8_common;
struct adiv5_dap *swjdp = armv8->arm.dap;
- uint32_t cti_base;
+ struct aarch64_private_config *pc;
int i;
int retval = ERROR_OK;
uint64_t debug, ttypr;
@@ -2206,10 +2211,6 @@ static int aarch64_examine_first(struct target *target)
uint32_t tmp0, tmp1, tmp2, tmp3;
debug = ttypr = cpuid = 0;
- retval = dap_dp_init(swjdp);
- if (retval != ERROR_OK)
- return retval;
-
/* Search for the APB-AB - it is needed for access to debug registers */
retval = dap_find_ap(swjdp, AP_TYPE_APB_AP, &armv8->debug_ap);
if (retval != ERROR_OK) {
@@ -2289,17 +2290,15 @@ static int aarch64_examine_first(struct target *target)
LOG_DEBUG("ttypr = 0x%08" PRIx64, ttypr);
LOG_DEBUG("debug = 0x%08" PRIx64, debug);
- if (target->ctibase == 0) {
- /* assume a v8 rom table layout */
- cti_base = armv8->debug_base + 0x10000;
- LOG_INFO("Target ctibase is not set, assuming 0x%0" PRIx32, cti_base);
- } else
- cti_base = target->ctibase;
+ if (target->private_config == NULL)
+ return ERROR_FAIL;
- armv8->cti = arm_cti_create(armv8->debug_ap, cti_base);
- if (armv8->cti == NULL)
+ pc = (struct aarch64_private_config *)target->private_config;
+ if (pc->cti == NULL)
return ERROR_FAIL;
+ armv8->cti = pc->cti;
+
retval = aarch64_dpm_setup(aarch64, debug);
if (retval != ERROR_OK)
return retval;
@@ -2356,18 +2355,13 @@ static int aarch64_init_target(struct command_context *cmd_ctx,
}
static int aarch64_init_arch_info(struct target *target,
- struct aarch64_common *aarch64, struct jtag_tap *tap)
+ struct aarch64_common *aarch64, struct adiv5_dap *dap)
{
struct armv8_common *armv8 = &aarch64->armv8_common;
/* Setup struct aarch64_common */
aarch64->common_magic = AARCH64_COMMON_MAGIC;
- /* tap has no dap initialized */
- if (!tap->dap) {
- tap->dap = dap_init();
- tap->dap->tap = tap;
- }
- armv8->arm.dap = tap->dap;
+ armv8->arm.dap = dap;
/* register arch-specific functions */
armv8->examine_debug_reason = NULL;
@@ -2383,9 +2377,13 @@ static int aarch64_init_arch_info(struct target *target,
static int aarch64_target_create(struct target *target, Jim_Interp *interp)
{
+ struct aarch64_private_config *pc = target->private_config;
struct aarch64_common *aarch64 = calloc(1, sizeof(struct aarch64_common));
- return aarch64_init_arch_info(target, aarch64, target->tap);
+ if (adiv5_verify_config(&pc->adiv5_config) != ERROR_OK)
+ return ERROR_FAIL;
+
+ return aarch64_init_arch_info(target, aarch64, pc->adiv5_config.dap);
}
static int aarch64_mmu(struct target *target, int *enabled)
@@ -2405,6 +2403,94 @@ static int aarch64_virt2phys(struct target *target, target_addr_t virt,
return armv8_mmu_translate_va_pa(target, virt, phys, 1);
}
+/*
+ * private target configuration items
+ */
+enum aarch64_cfg_param {
+ CFG_CTI,
+};
+
+static const Jim_Nvp nvp_config_opts[] = {
+ { .name = "-cti", .value = CFG_CTI },
+ { .name = NULL, .value = -1 }
+};
+
+static int aarch64_jim_configure(struct target *target, Jim_GetOptInfo *goi)
+{
+ struct aarch64_private_config *pc;
+ Jim_Nvp *n;
+ int e;
+
+ pc = (struct aarch64_private_config *)target->private_config;
+ if (pc == NULL) {
+ pc = calloc(1, sizeof(struct aarch64_private_config));
+ target->private_config = pc;
+ }
+
+ /*
+ * Call adiv5_jim_configure() to parse the common DAP options
+ * It will return JIM_CONTINUE if it didn't find any known
+ * options, JIM_OK if it correctly parsed the topmost option
+ * and JIM_ERR if an error occured during parameter evaluation.
+ * For JIM_CONTINUE, we check our own params.
+ */
+ e = adiv5_jim_configure(target, goi);
+ if (e != JIM_CONTINUE)
+ return e;
+
+ /* parse config or cget options ... */
+ if (goi->argc > 0) {
+ Jim_SetEmptyResult(goi->interp);
+
+ /* check first if topmost item is for us */
+ e = Jim_Nvp_name2value_obj(goi->interp, nvp_config_opts,
+ goi->argv[0], &n);
+ if (e != JIM_OK)
+ return JIM_CONTINUE;
+
+ e = Jim_GetOpt_Obj(goi, NULL);
+ if (e != JIM_OK)
+ return e;
+
+ switch (n->value) {
+ case CFG_CTI: {
+ if (goi->isconfigure) {
+ Jim_Obj *o_cti;
+ struct arm_cti *cti;
+ e = Jim_GetOpt_Obj(goi, &o_cti);
+ if (e != JIM_OK)
+ return e;
+ cti = cti_instance_by_jim_obj(goi->interp, o_cti);
+ if (cti == NULL) {
+ Jim_SetResultString(goi->interp, "CTI name invalid!", -1);
+ return JIM_ERR;
+ }
+ pc->cti = cti;
+ } else {
+ if (goi->argc != 0) {
+ Jim_WrongNumArgs(goi->interp,
+ goi->argc, goi->argv,
+ "NO PARAMS");
+ return JIM_ERR;
+ }
+
+ if (pc == NULL || pc->cti == NULL) {
+ Jim_SetResultString(goi->interp, "CTI not configured", -1);
+ return JIM_ERR;
+ }
+ Jim_SetResultString(goi->interp, arm_cti_name(pc->cti), -1);
+ }
+ break;
+ }
+
+ default:
+ return JIM_CONTINUE;
+ }
+ }
+
+ return JIM_OK;
+}
+
COMMAND_HANDLER(aarch64_handle_cache_info_command)
{
struct target *target = get_current_target(CMD_CTX);
@@ -2570,6 +2656,7 @@ struct target_type aarch64_target = {
.commands = aarch64_command_handlers,
.target_create = aarch64_target_create,
+ .target_jim_configure = aarch64_jim_configure,
.init_target = aarch64_init_target,
.examine = aarch64_examine,
diff --git a/src/target/adi_v5_jtag.c b/src/target/adi_v5_jtag.c
index c7dc4f7..dc02379 100644
--- a/src/target/adi_v5_jtag.c
+++ b/src/target/adi_v5_jtag.c
@@ -574,6 +574,7 @@ static int jtagdp_transaction_endcheck(struct adiv5_dap *dap)
if ((ctrlstat & (CDBGPWRUPREQ | CDBGPWRUPACK | CSYSPWRUPREQ | CSYSPWRUPACK)) !=
(CDBGPWRUPREQ | CDBGPWRUPACK | CSYSPWRUPREQ | CSYSPWRUPACK)) {
LOG_ERROR("Debug regions are unpowered, an unexpected reset might have happened");
+ dap->do_reconnect = true;
}
if (ctrlstat & SSTICKYERR)
@@ -598,6 +599,20 @@ static int jtagdp_transaction_endcheck(struct adiv5_dap *dap)
/*--------------------------------------------------------------------------*/
+static int jtag_connect(struct adiv5_dap *dap)
+{
+ dap->do_reconnect = false;
+ return dap_dp_init(dap);
+}
+
+static int jtag_check_reconnect(struct adiv5_dap *dap)
+{
+ if (dap->do_reconnect)
+ return jtag_connect(dap);
+
+ return ERROR_OK;
+}
+
static int jtag_dp_q_read(struct adiv5_dap *dap, unsigned reg,
uint32_t *data)
{
@@ -633,7 +648,11 @@ static int jtag_ap_q_bankselect(struct adiv5_ap *ap, unsigned reg)
static int jtag_ap_q_read(struct adiv5_ap *ap, unsigned reg,
uint32_t *data)
{
- int retval = jtag_ap_q_bankselect(ap, reg);
+ int retval = jtag_check_reconnect(ap->dap);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = jtag_ap_q_bankselect(ap, reg);
if (retval != ERROR_OK)
return retval;
@@ -647,7 +666,11 @@ static int jtag_ap_q_read(struct adiv5_ap *ap, unsigned reg,
static int jtag_ap_q_write(struct adiv5_ap *ap, unsigned reg,
uint32_t data)
{
- int retval = jtag_ap_q_bankselect(ap, reg);
+ int retval = jtag_check_reconnect(ap->dap);
+ if (retval != ERROR_OK)
+ return retval;
+
+ retval = jtag_ap_q_bankselect(ap, reg);
if (retval != ERROR_OK)
return retval;
@@ -692,6 +715,7 @@ static int jtag_dp_sync(struct adiv5_dap *dap)
* part of DAP setup
*/
const struct dap_ops jtag_dp_ops = {
+ .connect = jtag_connect,
.queue_dp_read = jtag_dp_q_read,
.queue_dp_write = jtag_dp_q_write,
.queue_ap_read = jtag_ap_q_read,
diff --git a/src/target/adi_v5_swd.c b/src/target/adi_v5_swd.c
index c503f09..0de272d 100644
--- a/src/target/adi_v5_swd.c
+++ b/src/target/adi_v5_swd.c
@@ -53,13 +53,11 @@
#include <jtag/swd.h>
-/* YUK! - but this is currently a global.... */
-extern struct jtag_interface *jtag_interface;
static bool do_sync;
static void swd_finish_read(struct adiv5_dap *dap)
{
- const struct swd_driver *swd = jtag_interface->swd;
+ const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
if (dap->last_read != NULL) {
swd->read_reg(swd_cmd(true, false, DP_RDBUFF), dap->last_read, 0);
dap->last_read = NULL;
@@ -73,7 +71,7 @@ static int swd_queue_dp_read(struct adiv5_dap *dap, unsigned reg,
static void swd_clear_sticky_errors(struct adiv5_dap *dap)
{
- const struct swd_driver *swd = jtag_interface->swd;
+ const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
assert(swd);
swd->write_reg(swd_cmd(false, false, DP_ABORT),
@@ -82,7 +80,7 @@ static void swd_clear_sticky_errors(struct adiv5_dap *dap)
static int swd_run_inner(struct adiv5_dap *dap)
{
- const struct swd_driver *swd = jtag_interface->swd;
+ const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
int retval;
retval = swd->run();
@@ -97,6 +95,7 @@ static int swd_run_inner(struct adiv5_dap *dap)
static int swd_connect(struct adiv5_dap *dap)
{
+ const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
uint32_t dpidr;
int status;
@@ -120,7 +119,7 @@ static int swd_connect(struct adiv5_dap *dap)
}
/* Note, debugport_init() does setup too */
- jtag_interface->swd->switch_seq(JTAG_TO_SWD);
+ swd->switch_seq(JTAG_TO_SWD);
/* Clear link state, including the SELECT cache. */
dap->do_reconnect = false;
@@ -136,6 +135,7 @@ static int swd_connect(struct adiv5_dap *dap)
if (status == ERROR_OK) {
LOG_INFO("SWD DPIDR %#8.8" PRIx32, dpidr);
dap->do_reconnect = false;
+ status = dap_dp_init(dap);
} else
dap->do_reconnect = true;
@@ -157,7 +157,7 @@ static int swd_check_reconnect(struct adiv5_dap *dap)
static int swd_queue_ap_abort(struct adiv5_dap *dap, uint8_t *ack)
{
- const struct swd_driver *swd = jtag_interface->swd;
+ const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
assert(swd);
swd->write_reg(swd_cmd(false, false, DP_ABORT),
@@ -187,7 +187,7 @@ static void swd_queue_dp_bankselect(struct adiv5_dap *dap, unsigned reg)
static int swd_queue_dp_read(struct adiv5_dap *dap, unsigned reg,
uint32_t *data)
{
- const struct swd_driver *swd = jtag_interface->swd;
+ const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
assert(swd);
int retval = swd_check_reconnect(dap);
@@ -203,7 +203,7 @@ static int swd_queue_dp_read(struct adiv5_dap *dap, unsigned reg,
static int swd_queue_dp_write(struct adiv5_dap *dap, unsigned reg,
uint32_t data)
{
- const struct swd_driver *swd = jtag_interface->swd;
+ const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
assert(swd);
int retval = swd_check_reconnect(dap);
@@ -236,10 +236,9 @@ static void swd_queue_ap_bankselect(struct adiv5_ap *ap, unsigned reg)
static int swd_queue_ap_read(struct adiv5_ap *ap, unsigned reg,
uint32_t *data)
{
- const struct swd_driver *swd = jtag_interface->swd;
- assert(swd);
-
struct adiv5_dap *dap = ap->dap;
+ const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
+ assert(swd);
int retval = swd_check_reconnect(dap);
if (retval != ERROR_OK)
@@ -255,10 +254,9 @@ static int swd_queue_ap_read(struct adiv5_ap *ap, unsigned reg,
static int swd_queue_ap_write(struct adiv5_ap *ap, unsigned reg,
uint32_t data)
{
- const struct swd_driver *swd = jtag_interface->swd;
- assert(swd);
-
struct adiv5_dap *dap = ap->dap;
+ const struct swd_driver *swd = adiv5_dap_swd_driver(dap);
+ assert(swd);
int retval = swd_check_reconnect(dap);
if (retval != ERROR_OK)
@@ -279,6 +277,7 @@ static int swd_run(struct adiv5_dap *dap)
}
const struct dap_ops swd_dap_ops = {
+ .connect = swd_connect,
.queue_dp_read = swd_queue_dp_read,
.queue_dp_write = swd_queue_dp_write,
.queue_ap_read = swd_queue_ap_read,
@@ -381,15 +380,15 @@ static const struct command_registration swd_handlers[] = {
static int swd_select(struct command_context *ctx)
{
+ /* FIXME: only place where global 'jtag_interface' is still needed */
+ extern struct jtag_interface *jtag_interface;
+ const struct swd_driver *swd = jtag_interface->swd;
int retval;
retval = register_commands(ctx, NULL, swd_handlers);
-
if (retval != ERROR_OK)
return retval;
- const struct swd_driver *swd = jtag_interface->swd;
-
/* be sure driver is in SWD mode; start
* with hardware default TRN (1), it can be changed later
*/
@@ -404,33 +403,14 @@ static int swd_select(struct command_context *ctx)
return retval;
}
- /* force DAP into SWD mode (not JTAG) */
- /*retval = dap_to_swd(target);*/
-
- if (ctx->current_target) {
- /* force DAP into SWD mode (not JTAG) */
- struct target *target = get_current_target(ctx);
- retval = dap_to_swd(target);
- }
-
return retval;
}
static int swd_init(struct command_context *ctx)
{
- struct target *target = get_current_target(ctx);
- struct arm *arm = target_to_arm(target);
- struct adiv5_dap *dap = arm->dap;
- /* Force the DAP's ops vector for SWD mode.
- * messy - is there a better way? */
- arm->dap->ops = &swd_dap_ops;
- /* First connect after init is not reconnecting. */
- dap->do_reconnect = false;
-
- int retval = swd_connect(dap);
- if (retval != ERROR_OK)
- LOG_ERROR("SWD connect failed");
- return retval;
+ /* nothing done here, SWD is initialized
+ * together with the DAP */
+ return ERROR_OK;
}
static struct transport swd_transport = {
diff --git a/src/target/arm.h b/src/target/arm.h
index eb4a51f..62fbb73 100644
--- a/src/target/arm.h
+++ b/src/target/arm.h
@@ -77,6 +77,43 @@ enum arm_mode {
ARM_MODE_ANY = -1
};
+/* VFPv3 internal register numbers mapping to d0:31 */
+enum {
+ ARM_VFP_V3_D0 = 51,
+ ARM_VFP_V3_D1,
+ ARM_VFP_V3_D2,
+ ARM_VFP_V3_D3,
+ ARM_VFP_V3_D4,
+ ARM_VFP_V3_D5,
+ ARM_VFP_V3_D6,
+ ARM_VFP_V3_D7,
+ ARM_VFP_V3_D8,
+ ARM_VFP_V3_D9,
+ ARM_VFP_V3_D10,
+ ARM_VFP_V3_D11,
+ ARM_VFP_V3_D12,
+ ARM_VFP_V3_D13,
+ ARM_VFP_V3_D14,
+ ARM_VFP_V3_D15,
+ ARM_VFP_V3_D16,
+ ARM_VFP_V3_D17,
+ ARM_VFP_V3_D18,
+ ARM_VFP_V3_D19,
+ ARM_VFP_V3_D20,
+ ARM_VFP_V3_D21,
+ ARM_VFP_V3_D22,
+ ARM_VFP_V3_D23,
+ ARM_VFP_V3_D24,
+ ARM_VFP_V3_D25,
+ ARM_VFP_V3_D26,
+ ARM_VFP_V3_D27,
+ ARM_VFP_V3_D28,
+ ARM_VFP_V3_D29,
+ ARM_VFP_V3_D30,
+ ARM_VFP_V3_D31,
+ ARM_VFP_V3_FPSCR,
+};
+
const char *arm_mode_name(unsigned psr_mode);
bool is_arm_mode(unsigned psr_mode);
@@ -89,6 +126,14 @@ enum arm_state {
ARM_STATE_AARCH64,
};
+/** ARM vector floating point enabled, if yes which version. */
+enum arm_vfp_version {
+ ARM_VFP_DISABLED,
+ ARM_VFP_V1,
+ ARM_VFP_V2,
+ ARM_VFP_V3,
+};
+
#define ARM_COMMON_MAGIC 0x0A450A45
/**
@@ -145,6 +190,9 @@ struct arm {
/** Flag reporting whether semihosting fileio operation is active. */
bool semihosting_hit_fileio;
+ /** Floating point or VFP version, 0 if disabled. */
+ int arm_vfp_version;
+
/** Current semihosting operation. */
int semihosting_op;
@@ -225,7 +273,7 @@ struct arm_reg {
enum arm_mode mode;
struct target *target;
struct arm *arm;
- uint8_t value[8];
+ uint8_t value[16];
};
struct reg_cache *arm_build_reg_cache(struct target *target, struct arm *arm);
diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c
index dfbc5ad..2b7d7b2 100644
--- a/src/target/arm_adi_v5.c
+++ b/src/target/arm_adi_v5.c
@@ -76,6 +76,7 @@
#include <helper/jep106.h>
#include <helper/time_support.h>
#include <helper/list.h>
+#include <helper/jim-nvp.h>
/* ARM ADI Specification requires at least 10 bits used for TAR autoincrement */
@@ -614,34 +615,9 @@ int mem_ap_write_buf_noincr(struct adiv5_ap *ap,
#define DAP_POWER_DOMAIN_TIMEOUT (10)
-/* FIXME don't import ... just initialize as
- * part of DAP transport setup
-*/
-extern const struct dap_ops jtag_dp_ops;
-
/*--------------------------------------------------------------------------*/
/**
- * Create a new DAP
- */
-struct adiv5_dap *dap_init(void)
-{
- struct adiv5_dap *dap = calloc(1, sizeof(struct adiv5_dap));
- int i;
- /* Set up with safe defaults */
- for (i = 0; i <= 255; i++) {
- dap->ap[i].dap = dap;
- dap->ap[i].ap_num = i;
- /* memaccess_tck max is 255 */
- dap->ap[i].memaccess_tck = 255;
- /* Number of bits for tar autoincrement, impl. dep. at least 10 */
- dap->ap[i].tar_autoincr_block = (1<<10);
- }
- INIT_LIST_HEAD(&dap->cmd_journal);
- return dap;
-}
-
-/**
* Invalidate cached DP select and cached TAR and CSW of all APs
*/
void dap_invalidate_cache(struct adiv5_dap *dap)
@@ -667,14 +643,7 @@ int dap_dp_init(struct adiv5_dap *dap)
{
int retval;
- LOG_DEBUG(" ");
- /* JTAG-DP or SWJ-DP, in JTAG mode
- * ... for SWD mode this is patched as part
- * of link switchover
- * FIXME: This should already be setup by the respective transport specific DAP creation.
- */
- if (!dap->ops)
- dap->ops = &jtag_dp_ops;
+ LOG_DEBUG("%s", adiv5_dap_name(dap));
dap_invalidate_cache(dap);
@@ -1376,7 +1345,7 @@ static int dap_rom_display(struct command_context *cmd_ctx,
return ERROR_OK;
}
-static int dap_info_command(struct command_context *cmd_ctx,
+int dap_info_command(struct command_context *cmd_ctx,
struct adiv5_ap *ap)
{
int retval;
@@ -1434,46 +1403,131 @@ static int dap_info_command(struct command_context *cmd_ctx,
return ERROR_OK;
}
+enum adiv5_cfg_param {
+ CFG_DAP,
+ CFG_AP_NUM
+};
+
+static const Jim_Nvp nvp_config_opts[] = {
+ { .name = "-dap", .value = CFG_DAP },
+ { .name = "-ap-num", .value = CFG_AP_NUM },
+ { .name = NULL, .value = -1 }
+};
+
int adiv5_jim_configure(struct target *target, Jim_GetOptInfo *goi)
{
struct adiv5_private_config *pc;
- const char *arg;
- jim_wide ap_num;
int e;
- /* check if argv[0] is for us */
- arg = Jim_GetString(goi->argv[0], NULL);
- if (strcmp(arg, "-ap-num"))
- return JIM_CONTINUE;
+ pc = (struct adiv5_private_config *)target->private_config;
+ if (pc == NULL) {
+ pc = calloc(1, sizeof(struct adiv5_private_config));
+ pc->ap_num = -1;
+ target->private_config = pc;
+ }
- e = Jim_GetOpt_String(goi, &arg, NULL);
- if (e != JIM_OK)
- return e;
+ target->has_dap = true;
+
+ if (goi->argc > 0) {
+ Jim_Nvp *n;
+
+ Jim_SetEmptyResult(goi->interp);
+
+ /* check first if topmost item is for us */
+ e = Jim_Nvp_name2value_obj(goi->interp, nvp_config_opts,
+ goi->argv[0], &n);
+ if (e != JIM_OK)
+ return JIM_CONTINUE;
+
+ e = Jim_GetOpt_Obj(goi, NULL);
+ if (e != JIM_OK)
+ return e;
+
+ switch (n->value) {
+ case CFG_DAP:
+ if (goi->isconfigure) {
+ Jim_Obj *o_t;
+ struct adiv5_dap *dap;
+ e = Jim_GetOpt_Obj(goi, &o_t);
+ if (e != JIM_OK)
+ return e;
+ dap = dap_instance_by_jim_obj(goi->interp, o_t);
+ if (dap == NULL) {
+ Jim_SetResultString(goi->interp, "DAP name invalid!", -1);
+ return JIM_ERR;
+ }
+ if (pc->dap != NULL && pc->dap != dap) {
+ Jim_SetResultString(goi->interp,
+ "DAP assignment cannot be changed after target was created!", -1);
+ return JIM_ERR;
+ }
+ if (target->tap_configured) {
+ Jim_SetResultString(goi->interp,
+ "-chain-position and -dap configparams are mutually exclusive!", -1);
+ return JIM_ERR;
+ }
+ pc->dap = dap;
+ target->tap = dap->tap;
+ target->dap_configured = true;
+ } else {
+ if (goi->argc != 0) {
+ Jim_WrongNumArgs(goi->interp,
+ goi->argc, goi->argv,
+ "NO PARAMS");
+ return JIM_ERR;
+ }
+
+ if (pc->dap == NULL) {
+ Jim_SetResultString(goi->interp, "DAP not configured", -1);
+ return JIM_ERR;
+ }
+ Jim_SetResultString(goi->interp, adiv5_dap_name(pc->dap), -1);
+ }
+ break;
- if (goi->argc == 0) {
- Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-ap-num ?ap-number? ...");
- return JIM_ERR;
+ case CFG_AP_NUM:
+ if (goi->isconfigure) {
+ jim_wide ap_num;
+ e = Jim_GetOpt_Wide(goi, &ap_num);
+ if (e != JIM_OK)
+ return e;
+ pc->ap_num = ap_num;
+ } else {
+ if (goi->argc != 0) {
+ Jim_WrongNumArgs(goi->interp,
+ goi->argc, goi->argv,
+ "NO PARAMS");
+ return JIM_ERR;
+ }
+
+ if (pc->ap_num < 0) {
+ Jim_SetResultString(goi->interp, "AP number not configured", -1);
+ return JIM_ERR;
+ }
+ Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, (int)pc->ap_num));
+ }
+ break;
+ }
}
- e = Jim_GetOpt_Wide(goi, &ap_num);
- if (e != JIM_OK)
- return e;
+ return JIM_OK;
+}
- if (target->private_config == NULL) {
- pc = calloc(1, sizeof(struct adiv5_private_config));
- target->private_config = pc;
- pc->ap_num = ap_num;
- }
+int adiv5_verify_config(struct adiv5_private_config *pc)
+{
+ if (pc == NULL)
+ return ERROR_FAIL;
+ if (pc->dap == NULL)
+ return ERROR_FAIL;
- return JIM_OK;
+ return ERROR_OK;
}
+
COMMAND_HANDLER(handle_dap_info_command)
{
- struct target *target = get_current_target(CMD_CTX);
- struct arm *arm = target_to_arm(target);
- struct adiv5_dap *dap = arm->dap;
+ struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA);
uint32_t apsel;
switch (CMD_ARGC) {
@@ -1494,10 +1548,7 @@ COMMAND_HANDLER(handle_dap_info_command)
COMMAND_HANDLER(dap_baseaddr_command)
{
- struct target *target = get_current_target(CMD_CTX);
- struct arm *arm = target_to_arm(target);
- struct adiv5_dap *dap = arm->dap;
-
+ struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA);
uint32_t apsel, baseaddr;
int retval;
@@ -1534,10 +1585,7 @@ COMMAND_HANDLER(dap_baseaddr_command)
COMMAND_HANDLER(dap_memaccess_command)
{
- struct target *target = get_current_target(CMD_CTX);
- struct arm *arm = target_to_arm(target);
- struct adiv5_dap *dap = arm->dap;
-
+ struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA);
uint32_t memaccess_tck;
switch (CMD_ARGC) {
@@ -1560,10 +1608,7 @@ COMMAND_HANDLER(dap_memaccess_command)
COMMAND_HANDLER(dap_apsel_command)
{
- struct target *target = get_current_target(CMD_CTX);
- struct arm *arm = target_to_arm(target);
- struct adiv5_dap *dap = arm->dap;
-
+ struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA);
uint32_t apsel, apid;
int retval;
@@ -1598,11 +1643,9 @@ COMMAND_HANDLER(dap_apsel_command)
COMMAND_HANDLER(dap_apcsw_command)
{
- struct target *target = get_current_target(CMD_CTX);
- struct arm *arm = target_to_arm(target);
- struct adiv5_dap *dap = arm->dap;
-
- uint32_t apcsw = dap->ap[dap->apsel].csw_default, sprot = 0;
+ struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA);
+ uint32_t apcsw = dap->ap[dap->apsel].csw_default;
+ uint32_t sprot = 0;
switch (CMD_ARGC) {
case 0:
@@ -1631,10 +1674,7 @@ COMMAND_HANDLER(dap_apcsw_command)
COMMAND_HANDLER(dap_apid_command)
{
- struct target *target = get_current_target(CMD_CTX);
- struct arm *arm = target_to_arm(target);
- struct adiv5_dap *dap = arm->dap;
-
+ struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA);
uint32_t apsel, apid;
int retval;
@@ -1666,10 +1706,7 @@ COMMAND_HANDLER(dap_apid_command)
COMMAND_HANDLER(dap_apreg_command)
{
- struct target *target = get_current_target(CMD_CTX);
- struct arm *arm = target_to_arm(target);
- struct adiv5_dap *dap = arm->dap;
-
+ struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA);
uint32_t apsel, reg, value;
int retval;
@@ -1705,10 +1742,7 @@ COMMAND_HANDLER(dap_apreg_command)
COMMAND_HANDLER(dap_ti_be_32_quirks_command)
{
- struct target *target = get_current_target(CMD_CTX);
- struct arm *arm = target_to_arm(target);
- struct adiv5_dap *dap = arm->dap;
-
+ struct adiv5_dap *dap = adiv5_get_dap(CMD_DATA);
uint32_t enable = dap->ti_be_32_quirks;
switch (CMD_ARGC) {
@@ -1729,7 +1763,7 @@ COMMAND_HANDLER(dap_ti_be_32_quirks_command)
return 0;
}
-static const struct command_registration dap_commands[] = {
+const struct command_registration dap_instance_commands[] = {
{
.name = "info",
.handler = handle_dap_info_command,
@@ -1795,14 +1829,3 @@ static const struct command_registration dap_commands[] = {
},
COMMAND_REGISTRATION_DONE
};
-
-const struct command_registration dap_command_handlers[] = {
- {
- .name = "dap",
- .mode = COMMAND_EXEC,
- .help = "DAP command group",
- .usage = "",
- .chain = dap_commands,
- },
- COMMAND_REGISTRATION_DONE
-};
diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h
index 657427b..aa5fa42 100644
--- a/src/target/arm_adi_v5.h
+++ b/src/target/arm_adi_v5.h
@@ -254,6 +254,8 @@ struct adiv5_dap {
* available until run().
*/
struct dap_ops {
+ /** connect operation for SWD */
+ int (*connect)(struct adiv5_dap *dap);
/** DP register read. */
int (*queue_dp_read)(struct adiv5_dap *dap, unsigned reg,
uint32_t *data);
@@ -473,9 +475,6 @@ int mem_ap_read_buf_noincr(struct adiv5_ap *ap,
int mem_ap_write_buf_noincr(struct adiv5_ap *ap,
const uint8_t *buffer, uint32_t size, uint32_t count, uint32_t address);
-/* Create DAP struct */
-struct adiv5_dap *dap_init(void);
-
/* Initialisation of the debug system, power domains and registers */
int dap_dp_init(struct adiv5_dap *dap);
int mem_ap_init(struct adiv5_ap *ap);
@@ -509,12 +508,24 @@ int dap_to_swd(struct target *target);
/* Put debug link into JTAG mode */
int dap_to_jtag(struct target *target);
-extern const struct command_registration dap_command_handlers[];
+extern const struct command_registration dap_instance_commands[];
+
+struct arm_dap_object;
+extern struct adiv5_dap *dap_instance_by_jim_obj(Jim_Interp *interp, Jim_Obj *o);
+extern struct adiv5_dap *adiv5_get_dap(struct arm_dap_object *obj);
+extern int dap_info_command(struct command_context *cmd_ctx,
+ struct adiv5_ap *ap);
+extern int dap_register_commands(struct command_context *cmd_ctx);
+extern const char *adiv5_dap_name(struct adiv5_dap *self);
+extern const struct swd_driver *adiv5_dap_swd_driver(struct adiv5_dap *self);
+extern int dap_cleanup_all(void);
struct adiv5_private_config {
int ap_num;
+ struct adiv5_dap *dap;
};
+extern int adiv5_verify_config(struct adiv5_private_config *pc);
extern int adiv5_jim_configure(struct target *target, Jim_GetOptInfo *goi);
#endif /* OPENOCD_TARGET_ARM_ADI_V5_H */
diff --git a/src/target/arm_cti.c b/src/target/arm_cti.c
index 75169b2..547b961 100644
--- a/src/target/arm_cti.c
+++ b/src/target/arm_cti.c
@@ -27,21 +27,47 @@
#include "target/arm_cti.h"
#include "target/target.h"
#include "helper/time_support.h"
+#include "helper/list.h"
+#include "helper/command.h"
struct arm_cti {
- uint32_t base;
+ target_addr_t base;
struct adiv5_ap *ap;
};
-struct arm_cti *arm_cti_create(struct adiv5_ap *ap, uint32_t base)
+struct arm_cti_object {
+ struct list_head lh;
+ struct arm_cti cti;
+ int ap_num;
+ char *name;
+};
+
+static LIST_HEAD(all_cti);
+
+const char *arm_cti_name(struct arm_cti *self)
+{
+ struct arm_cti_object *obj = container_of(self, struct arm_cti_object, cti);
+ return obj->name;
+}
+
+struct arm_cti *cti_instance_by_jim_obj(Jim_Interp *interp, Jim_Obj *o)
{
- struct arm_cti *self = calloc(1, sizeof(struct arm_cti));
- if (!self)
- return NULL;
+ struct arm_cti_object *obj = NULL;
+ const char *name;
+ bool found = false;
- self->base = base;
- self->ap = ap;
- return self;
+ name = Jim_GetString(o, NULL);
+
+ list_for_each_entry(obj, &all_cti, lh) {
+ if (!strcmp(name, obj->name)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (found)
+ return &obj->cti;
+ return NULL;
}
static int arm_cti_mod_reg_bits(struct arm_cti *self, unsigned int reg, uint32_t mask, uint32_t value)
@@ -146,3 +172,396 @@ int arm_cti_clear_channel(struct arm_cti *self, uint32_t channel)
return arm_cti_write_reg(self, CTI_APPCLEAR, CTI_CHNL(channel));
}
+
+static uint32_t cti_regs[26];
+
+static const struct {
+ uint32_t offset;
+ const char *label;
+ uint32_t *p_val;
+} cti_names[] = {
+ { CTI_CTR, "CTR", &cti_regs[0] },
+ { CTI_GATE, "GATE", &cti_regs[1] },
+ { CTI_INEN0, "INEN0", &cti_regs[2] },
+ { CTI_INEN1, "INEN1", &cti_regs[3] },
+ { CTI_INEN2, "INEN2", &cti_regs[4] },
+ { CTI_INEN3, "INEN3", &cti_regs[5] },
+ { CTI_INEN4, "INEN4", &cti_regs[6] },
+ { CTI_INEN5, "INEN5", &cti_regs[7] },
+ { CTI_INEN6, "INEN6", &cti_regs[8] },
+ { CTI_INEN7, "INEN7", &cti_regs[9] },
+ { CTI_INEN8, "INEN8", &cti_regs[10] },
+ { CTI_OUTEN0, "OUTEN0", &cti_regs[11] },
+ { CTI_OUTEN1, "OUTEN1", &cti_regs[12] },
+ { CTI_OUTEN2, "OUTEN2", &cti_regs[13] },
+ { CTI_OUTEN3, "OUTEN3", &cti_regs[14] },
+ { CTI_OUTEN4, "OUTEN4", &cti_regs[15] },
+ { CTI_OUTEN5, "OUTEN5", &cti_regs[16] },
+ { CTI_OUTEN6, "OUTEN6", &cti_regs[17] },
+ { CTI_OUTEN7, "OUTEN7", &cti_regs[18] },
+ { CTI_OUTEN8, "OUTEN8", &cti_regs[19] },
+ { CTI_TRIN_STATUS, "TRIN", &cti_regs[20] },
+ { CTI_TROUT_STATUS, "TROUT", &cti_regs[21] },
+ { CTI_CHIN_STATUS, "CHIN", &cti_regs[22] },
+ { CTI_CHOU_STATUS, "CHOUT", &cti_regs[23] },
+ { CTI_APPSET, "APPSET", &cti_regs[24] },
+ { CTI_APPCLEAR, "APPCLR", &cti_regs[25] },
+};
+
+static int cti_find_reg_offset(const char *name)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(cti_names); i++) {
+ if (!strcmp(name, cti_names[i].label))
+ return cti_names[i].offset;
+ }
+ return -1;
+}
+
+COMMAND_HANDLER(handle_cti_dump)
+{
+ struct arm_cti_object *obj = CMD_DATA;
+ struct arm_cti *cti = &obj->cti;
+ int retval = ERROR_OK;
+
+ for (int i = 0; (retval == ERROR_OK) && (i < (int)ARRAY_SIZE(cti_names)); i++)
+ retval = mem_ap_read_u32(cti->ap,
+ cti->base + cti_names[i].offset, cti_names[i].p_val);
+
+ if (retval == ERROR_OK)
+ retval = dap_run(cti->ap->dap);
+
+ if (retval != ERROR_OK)
+ return JIM_ERR;
+
+ for (int i = 0; i < (int)ARRAY_SIZE(cti_names); i++)
+ command_print(CMD_CTX, "%8.8s (0x%04"PRIx32") 0x%08"PRIx32,
+ cti_names[i].label, cti_names[i].offset, *cti_names[i].p_val);
+
+ return JIM_OK;
+}
+
+COMMAND_HANDLER(handle_cti_enable)
+{
+ struct arm_cti_object *obj = CMD_DATA;
+ Jim_Interp *interp = CMD_CTX->interp;
+ struct arm_cti *cti = &obj->cti;
+ bool on_off;
+
+ if (CMD_ARGC != 1) {
+ Jim_SetResultString(interp, "wrong number of args", -1);
+ return ERROR_FAIL;
+ }
+
+ COMMAND_PARSE_ON_OFF(CMD_ARGV[0], on_off);
+
+ return arm_cti_enable(cti, on_off);
+}
+
+COMMAND_HANDLER(handle_cti_testmode)
+{
+ struct arm_cti_object *obj = CMD_DATA;
+ Jim_Interp *interp = CMD_CTX->interp;
+ struct arm_cti *cti = &obj->cti;
+ bool on_off;
+
+ if (CMD_ARGC != 1) {
+ Jim_SetResultString(interp, "wrong number of args", -1);
+ return ERROR_FAIL;
+ }
+
+ COMMAND_PARSE_ON_OFF(CMD_ARGV[0], on_off);
+
+ return arm_cti_write_reg(cti, 0xf00, on_off ? 0x1 : 0x0);
+}
+
+COMMAND_HANDLER(handle_cti_write)
+{
+ struct arm_cti_object *obj = CMD_DATA;
+ Jim_Interp *interp = CMD_CTX->interp;
+ struct arm_cti *cti = &obj->cti;
+ int offset;
+ uint32_t value;
+
+ if (CMD_ARGC != 2) {
+ Jim_SetResultString(interp, "Wrong numer of args", -1);
+ return ERROR_FAIL;
+ }
+
+ offset = cti_find_reg_offset(CMD_ARGV[0]);
+ if (offset < 0)
+ return ERROR_FAIL;
+
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value);
+
+ return arm_cti_write_reg(cti, offset, value);
+}
+
+COMMAND_HANDLER(handle_cti_read)
+{
+ struct arm_cti_object *obj = CMD_DATA;
+ Jim_Interp *interp = CMD_CTX->interp;
+ struct arm_cti *cti = &obj->cti;
+ int offset;
+ int retval;
+ uint32_t value;
+
+ if (CMD_ARGC != 1) {
+ Jim_SetResultString(interp, "Wrong numer of args", -1);
+ return ERROR_FAIL;
+ }
+
+ offset = cti_find_reg_offset(CMD_ARGV[0]);
+ if (offset < 0)
+ return ERROR_FAIL;
+
+ retval = arm_cti_read_reg(cti, offset, &value);
+ if (retval != ERROR_OK)
+ return retval;
+
+ command_print(CMD_CTX, "0x%08"PRIx32, value);
+
+ return ERROR_OK;
+}
+
+static const struct command_registration cti_instance_command_handlers[] = {
+ {
+ .name = "dump",
+ .mode = COMMAND_EXEC,
+ .handler = handle_cti_dump,
+ .help = "dump CTI registers",
+ .usage = "",
+ },
+ {
+ .name = "enable",
+ .mode = COMMAND_EXEC,
+ .handler = handle_cti_enable,
+ .help = "enable or disable the CTI",
+ .usage = "'on'|'off'",
+ },
+ {
+ .name = "testmode",
+ .mode = COMMAND_EXEC,
+ .handler = handle_cti_testmode,
+ .help = "enable or disable integration test mode",
+ .usage = "'on'|'off'",
+ },
+ {
+ .name = "write",
+ .mode = COMMAND_EXEC,
+ .handler = handle_cti_write,
+ .help = "write to a CTI register",
+ .usage = "register_name value",
+ },
+ {
+ .name = "read",
+ .mode = COMMAND_EXEC,
+ .handler = handle_cti_read,
+ .help = "read a CTI register",
+ .usage = "register_name",
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+enum cti_cfg_param {
+ CFG_DAP,
+ CFG_AP_NUM,
+ CFG_CTIBASE
+};
+
+static const Jim_Nvp nvp_config_opts[] = {
+ { .name = "-dap", .value = CFG_DAP },
+ { .name = "-ctibase", .value = CFG_CTIBASE },
+ { .name = "-ap-num", .value = CFG_AP_NUM },
+ { .name = NULL, .value = -1 }
+};
+
+static int cti_configure(Jim_GetOptInfo *goi, struct arm_cti_object *cti)
+{
+ struct adiv5_dap *dap = NULL;
+ Jim_Nvp *n;
+ jim_wide w;
+ int e;
+
+ /* parse config or cget options ... */
+ while (goi->argc > 0) {
+ Jim_SetEmptyResult(goi->interp);
+
+ e = Jim_GetOpt_Nvp(goi, nvp_config_opts, &n);
+ if (e != JIM_OK) {
+ Jim_GetOpt_NvpUnknown(goi, nvp_config_opts, 0);
+ return e;
+ }
+ switch (n->value) {
+ case CFG_DAP: {
+ Jim_Obj *o_t;
+ e = Jim_GetOpt_Obj(goi, &o_t);
+ if (e != JIM_OK)
+ return e;
+ dap = dap_instance_by_jim_obj(goi->interp, o_t);
+ if (dap == NULL) {
+ Jim_SetResultString(goi->interp, "-dap is invalid", -1);
+ return JIM_ERR;
+ }
+ /* loop for more */
+ break;
+ }
+ case CFG_CTIBASE:
+ e = Jim_GetOpt_Wide(goi, &w);
+ if (e != JIM_OK)
+ return e;
+ cti->cti.base = (uint32_t)w;
+ /* loop for more */
+ break;
+
+ case CFG_AP_NUM:
+ e = Jim_GetOpt_Wide(goi, &w);
+ if (e != JIM_OK)
+ return e;
+ cti->ap_num = (uint32_t)w;
+ }
+ }
+
+ if (dap == NULL) {
+ Jim_SetResultString(goi->interp, "-dap required when creating CTI", -1);
+ return JIM_ERR;
+ }
+
+ cti->cti.ap = dap_ap(dap, cti->ap_num);
+
+ return JIM_OK;
+}
+
+static int cti_create(Jim_GetOptInfo *goi)
+{
+ struct command_context *cmd_ctx;
+ static struct arm_cti_object *cti;
+ Jim_Obj *new_cmd;
+ Jim_Cmd *cmd;
+ const char *cp;
+ int e;
+
+ cmd_ctx = current_command_context(goi->interp);
+ assert(cmd_ctx != NULL);
+
+ if (goi->argc < 3) {
+ Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ..options...");
+ return JIM_ERR;
+ }
+ /* COMMAND */
+ Jim_GetOpt_Obj(goi, &new_cmd);
+ /* does this command exist? */
+ cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_ERRMSG);
+ if (cmd) {
+ cp = Jim_GetString(new_cmd, NULL);
+ Jim_SetResultFormatted(goi->interp, "Command: %s Exists", cp);
+ return JIM_ERR;
+ }
+
+ /* Create it */
+ cti = calloc(1, sizeof(struct arm_cti_object));
+ if (cti == NULL)
+ return JIM_ERR;
+
+ e = cti_configure(goi, cti);
+ if (e != JIM_OK) {
+ free(cti);
+ return e;
+ }
+
+ cp = Jim_GetString(new_cmd, NULL);
+ cti->name = strdup(cp);
+
+ /* now - create the new cti name command */
+ const struct command_registration cti_subcommands[] = {
+ {
+ .chain = cti_instance_command_handlers,
+ },
+ COMMAND_REGISTRATION_DONE
+ };
+ const struct command_registration cti_commands[] = {
+ {
+ .name = cp,
+ .mode = COMMAND_ANY,
+ .help = "cti instance command group",
+ .usage = "",
+ .chain = cti_subcommands,
+ },
+ COMMAND_REGISTRATION_DONE
+ };
+ e = register_commands(cmd_ctx, NULL, cti_commands);
+ if (ERROR_OK != e)
+ return JIM_ERR;
+
+ struct command *c = command_find_in_context(cmd_ctx, cp);
+ assert(c);
+ command_set_handler_data(c, cti);
+
+ list_add_tail(&cti->lh, &all_cti);
+
+ return (ERROR_OK == e) ? JIM_OK : JIM_ERR;
+}
+
+static int jim_cti_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ Jim_GetOptInfo goi;
+ Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
+ if (goi.argc < 2) {
+ Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv,
+ "<name> [<cti_options> ...]");
+ return JIM_ERR;
+ }
+ return cti_create(&goi);
+}
+
+static int jim_cti_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ struct arm_cti_object *obj;
+
+ if (argc != 1) {
+ Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
+ return JIM_ERR;
+ }
+ Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
+ list_for_each_entry(obj, &all_cti, lh) {
+ Jim_ListAppendElement(interp, Jim_GetResult(interp),
+ Jim_NewStringObj(interp, obj->name, -1));
+ }
+ return JIM_OK;
+}
+
+
+static const struct command_registration cti_subcommand_handlers[] = {
+ {
+ .name = "create",
+ .mode = COMMAND_ANY,
+ .jim_handler = jim_cti_create,
+ .usage = "name '-chain-position' name [options ...]",
+ .help = "Creates a new CTI object",
+ },
+ {
+ .name = "names",
+ .mode = COMMAND_ANY,
+ .jim_handler = jim_cti_names,
+ .usage = "",
+ .help = "Lists all registered CTI objects by name",
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+static const struct command_registration cti_command_handlers[] = {
+ {
+ .name = "cti",
+ .mode = COMMAND_CONFIG,
+ .help = "CTI commands",
+ .chain = cti_subcommand_handlers,
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+int cti_register_commands(struct command_context *cmd_ctx)
+{
+ return register_commands(cmd_ctx, NULL, cti_command_handlers);
+}
+
diff --git a/src/target/arm_cti.h b/src/target/arm_cti.h
index 99724c4..181f064 100644
--- a/src/target/arm_cti.h
+++ b/src/target/arm_cti.h
@@ -34,6 +34,7 @@
#define CTI_INEN5 0x34
#define CTI_INEN6 0x38
#define CTI_INEN7 0x3C
+#define CTI_INEN8 0x40
#define CTI_INEN(n) (0x20 + 4 * n)
#define CTI_OUTEN0 0xA0
#define CTI_OUTEN1 0xA4
@@ -43,6 +44,7 @@
#define CTI_OUTEN5 0xB4
#define CTI_OUTEN6 0xB8
#define CTI_OUTEN7 0xBC
+#define CTI_OUTEN8 0xC0
#define CTI_OUTEN(n) (0xA0 + 4 * n)
#define CTI_TRIN_STATUS 0x130
#define CTI_TROUT_STATUS 0x134
@@ -58,8 +60,10 @@
/* forward-declare arm_cti struct */
struct arm_cti;
+struct adiv5_ap;
-extern struct arm_cti *arm_cti_create(struct adiv5_ap *ap, uint32_t base);
+extern const char *arm_cti_name(struct arm_cti *self);
+extern struct arm_cti *cti_instance_by_jim_obj(Jim_Interp *interp, Jim_Obj *o);
extern int arm_cti_enable(struct arm_cti *self, bool enable);
extern int arm_cti_ack_events(struct arm_cti *self, uint32_t event);
extern int arm_cti_gate_channel(struct arm_cti *self, uint32_t channel);
@@ -70,4 +74,6 @@ extern int arm_cti_pulse_channel(struct arm_cti *self, uint32_t channel);
extern int arm_cti_set_channel(struct arm_cti *self, uint32_t channel);
extern int arm_cti_clear_channel(struct arm_cti *self, uint32_t channel);
+extern int cti_register_commands(struct command_context *cmd_ctx);
+
#endif /* OPENOCD_TARGET_ARM_CTI_H */
diff --git a/src/target/arm_dap.c b/src/target/arm_dap.c
new file mode 100644
index 0000000..692feb3
--- /dev/null
+++ b/src/target/arm_dap.c
@@ -0,0 +1,366 @@
+/***************************************************************************
+ * Copyright (C) 2016 by Matthias Welwarsky *
+ * *
+ * 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., *
+ * *
+ ***************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdint.h>
+#include "target/arm_adi_v5.h"
+#include "target/arm.h"
+#include "helper/list.h"
+#include "helper/command.h"
+#include "transport/transport.h"
+#include "jtag/interface.h"
+
+static LIST_HEAD(all_dap);
+
+extern const struct dap_ops swd_dap_ops;
+extern const struct dap_ops jtag_dp_ops;
+extern struct jtag_interface *jtag_interface;
+
+/* DAP command support */
+struct arm_dap_object {
+ struct list_head lh;
+ struct adiv5_dap dap;
+ char *name;
+ const struct swd_driver *swd;
+};
+
+static void dap_instance_init(struct adiv5_dap *dap)
+{
+ int i;
+ /* Set up with safe defaults */
+ for (i = 0; i <= 255; i++) {
+ dap->ap[i].dap = dap;
+ dap->ap[i].ap_num = i;
+ /* memaccess_tck max is 255 */
+ dap->ap[i].memaccess_tck = 255;
+ /* Number of bits for tar autoincrement, impl. dep. at least 10 */
+ dap->ap[i].tar_autoincr_block = (1<<10);
+ }
+ INIT_LIST_HEAD(&dap->cmd_journal);
+}
+
+const char *adiv5_dap_name(struct adiv5_dap *self)
+{
+ struct arm_dap_object *obj = container_of(self, struct arm_dap_object, dap);
+ return obj->name;
+}
+
+const struct swd_driver *adiv5_dap_swd_driver(struct adiv5_dap *self)
+{
+ struct arm_dap_object *obj = container_of(self, struct arm_dap_object, dap);
+ return obj->swd;
+}
+
+struct adiv5_dap *adiv5_get_dap(struct arm_dap_object *obj)
+{
+ return &obj->dap;
+}
+struct adiv5_dap *dap_instance_by_jim_obj(Jim_Interp *interp, Jim_Obj *o)
+{
+ struct arm_dap_object *obj = NULL;
+ const char *name;
+ bool found = false;
+
+ name = Jim_GetString(o, NULL);
+
+ list_for_each_entry(obj, &all_dap, lh) {
+ if (!strcmp(name, obj->name)) {
+ found = true;
+ break;
+ }
+ }
+
+ if (found)
+ return &obj->dap;
+ return NULL;
+}
+
+static int dap_init_all(void)
+{
+ struct arm_dap_object *obj;
+ int retval;
+
+ LOG_DEBUG("Initializing all DAPs ...");
+
+ list_for_each_entry(obj, &all_dap, lh) {
+ struct adiv5_dap *dap = &obj->dap;
+
+ /* with hla, dap is just a dummy */
+ if (transport_is_hla())
+ continue;
+
+ /* skip taps that are disabled */
+ if (!dap->tap->enabled)
+ continue;
+
+ if (transport_is_swd()) {
+ dap->ops = &swd_dap_ops;
+ obj->swd = jtag_interface->swd;
+ } else
+ dap->ops = &jtag_dp_ops;
+
+ retval = dap->ops->connect(dap);
+ if (retval != ERROR_OK)
+ return retval;
+ }
+
+ return ERROR_OK;
+}
+
+int dap_cleanup_all(void)
+{
+ struct arm_dap_object *obj, *tmp;
+
+ list_for_each_entry_safe(obj, tmp, &all_dap, lh) {
+ free(obj->name);
+ free(obj);
+ }
+
+ return ERROR_OK;
+}
+
+enum dap_cfg_param {
+ CFG_CHAIN_POSITION,
+};
+
+static const Jim_Nvp nvp_config_opts[] = {
+ { .name = "-chain-position", .value = CFG_CHAIN_POSITION },
+ { .name = NULL, .value = -1 }
+};
+
+static int dap_configure(Jim_GetOptInfo *goi, struct arm_dap_object *dap)
+{
+ struct jtag_tap *tap = NULL;
+ Jim_Nvp *n;
+ int e;
+
+ /* parse config or cget options ... */
+ while (goi->argc > 0) {
+ Jim_SetEmptyResult(goi->interp);
+
+ e = Jim_GetOpt_Nvp(goi, nvp_config_opts, &n);
+ if (e != JIM_OK) {
+ Jim_GetOpt_NvpUnknown(goi, nvp_config_opts, 0);
+ return e;
+ }
+ switch (n->value) {
+ case CFG_CHAIN_POSITION: {
+ Jim_Obj *o_t;
+ e = Jim_GetOpt_Obj(goi, &o_t);
+ if (e != JIM_OK)
+ return e;
+ tap = jtag_tap_by_jim_obj(goi->interp, o_t);
+ if (tap == NULL) {
+ Jim_SetResultString(goi->interp, "-chain-position is invalid", -1);
+ return JIM_ERR;
+ }
+ /* loop for more */
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ if (tap == NULL) {
+ Jim_SetResultString(goi->interp, "-chain-position required when creating DAP", -1);
+ return JIM_ERR;
+ }
+
+ dap_instance_init(&dap->dap);
+ dap->dap.tap = tap;
+
+ return JIM_OK;
+}
+
+static int dap_create(Jim_GetOptInfo *goi)
+{
+ struct command_context *cmd_ctx;
+ static struct arm_dap_object *dap;
+ Jim_Obj *new_cmd;
+ Jim_Cmd *cmd;
+ const char *cp;
+ int e;
+
+ cmd_ctx = current_command_context(goi->interp);
+ assert(cmd_ctx != NULL);
+
+ if (goi->argc < 3) {
+ Jim_WrongNumArgs(goi->interp, 1, goi->argv, "?name? ..options...");
+ return JIM_ERR;
+ }
+ /* COMMAND */
+ Jim_GetOpt_Obj(goi, &new_cmd);
+ /* does this command exist? */
+ cmd = Jim_GetCommand(goi->interp, new_cmd, JIM_ERRMSG);
+ if (cmd) {
+ cp = Jim_GetString(new_cmd, NULL);
+ Jim_SetResultFormatted(goi->interp, "Command: %s Exists", cp);
+ return JIM_ERR;
+ }
+
+ /* Create it */
+ dap = calloc(1, sizeof(struct arm_dap_object));
+ if (dap == NULL)
+ return JIM_ERR;
+
+ e = dap_configure(goi, dap);
+ if (e != JIM_OK) {
+ free(dap);
+ return e;
+ }
+
+ cp = Jim_GetString(new_cmd, NULL);
+ dap->name = strdup(cp);
+
+ struct command_registration dap_commands[] = {
+ {
+ .name = cp,
+ .mode = COMMAND_ANY,
+ .help = "dap instance command group",
+ .usage = "",
+ .chain = dap_instance_commands,
+ },
+ COMMAND_REGISTRATION_DONE
+ };
+
+ /* don't expose the instance commands when using hla */
+ if (transport_is_hla())
+ dap_commands[0].chain = NULL;
+
+ e = register_commands(cmd_ctx, NULL, dap_commands);
+ if (ERROR_OK != e)
+ return JIM_ERR;
+
+ struct command *c = command_find_in_context(cmd_ctx, cp);
+ assert(c);
+ command_set_handler_data(c, dap);
+
+ list_add_tail(&dap->lh, &all_dap);
+
+ return (ERROR_OK == e) ? JIM_OK : JIM_ERR;
+}
+
+static int jim_dap_create(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ Jim_GetOptInfo goi;
+ Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1);
+ if (goi.argc < 2) {
+ Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv,
+ "<name> [<dap_options> ...]");
+ return JIM_ERR;
+ }
+ return dap_create(&goi);
+}
+
+static int jim_dap_names(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ struct arm_dap_object *obj;
+
+ if (argc != 1) {
+ Jim_WrongNumArgs(interp, 1, argv, "Too many parameters");
+ return JIM_ERR;
+ }
+ Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0));
+ list_for_each_entry(obj, &all_dap, lh) {
+ Jim_ListAppendElement(interp, Jim_GetResult(interp),
+ Jim_NewStringObj(interp, obj->name, -1));
+ }
+ return JIM_OK;
+}
+
+COMMAND_HANDLER(handle_dap_init)
+{
+ return dap_init_all();
+}
+
+COMMAND_HANDLER(handle_dap_info_command)
+{
+ struct target *target = get_current_target(CMD_CTX);
+ struct arm *arm = target_to_arm(target);
+ struct adiv5_dap *dap = arm->dap;
+ uint32_t apsel;
+
+ switch (CMD_ARGC) {
+ case 0:
+ apsel = dap->apsel;
+ break;
+ case 1:
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], apsel);
+ if (apsel >= 256)
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ break;
+ default:
+ return ERROR_COMMAND_SYNTAX_ERROR;
+ }
+
+ return dap_info_command(CMD_CTX, &dap->ap[apsel]);
+}
+
+static const struct command_registration dap_subcommand_handlers[] = {
+ {
+ .name = "create",
+ .mode = COMMAND_ANY,
+ .jim_handler = jim_dap_create,
+ .usage = "name '-chain-position' name",
+ .help = "Creates a new DAP instance",
+ },
+ {
+ .name = "names",
+ .mode = COMMAND_ANY,
+ .jim_handler = jim_dap_names,
+ .usage = "",
+ .help = "Lists all registered DAP instances by name",
+ },
+ {
+ .name = "init",
+ .mode = COMMAND_ANY,
+ .handler = handle_dap_init,
+ .usage = "",
+ .help = "Initialize all registered DAP instances"
+ },
+ {
+ .name = "info",
+ .handler = handle_dap_info_command,
+ .mode = COMMAND_EXEC,
+ .help = "display ROM table for MEM-AP of current target "
+ "(default currently selected AP)",
+ .usage = "[ap_num]",
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+static const struct command_registration dap_commands[] = {
+ {
+ .name = "dap",
+ .mode = COMMAND_CONFIG,
+ .help = "DAP commands",
+ .chain = dap_subcommand_handlers,
+ },
+ COMMAND_REGISTRATION_DONE
+};
+
+int dap_register_commands(struct command_context *cmd_ctx)
+{
+ return register_commands(cmd_ctx, NULL, dap_commands);
+}
diff --git a/src/target/arm_disassembler.c b/src/target/arm_disassembler.c
index ef69a20..8e783d3 100644
--- a/src/target/arm_disassembler.c
+++ b/src/target/arm_disassembler.c
@@ -2978,6 +2978,7 @@ static int t2ev_b_bl(uint32_t opcode, uint32_t address,
case 0x4:
inst = "BLX";
instruction->type = ARM_BLX;
+ address &= 0xfffffffc;
break;
case 0x5:
inst = "BL";
diff --git a/src/target/arm_dpm.c b/src/target/arm_dpm.c
index 3e8180c..6579099 100644
--- a/src/target/arm_dpm.c
+++ b/src/target/arm_dpm.c
@@ -131,6 +131,42 @@ int dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode)
return retval;
}
+/* Read 64bit VFP registers */
+static int dpm_read_reg_u64(struct arm_dpm *dpm, struct reg *r, unsigned regnum)
+{
+ int retval = ERROR_FAIL;
+ uint32_t value_r0, value_r1;
+
+ switch (regnum) {
+ case ARM_VFP_V3_D0 ... ARM_VFP_V3_D31:
+ /* move from double word register to r0:r1: "vmov r0, r1, vm"
+ * then read r0 via dcc
+ */
+ retval = dpm->instr_read_data_r0(dpm,
+ ARMV4_5_VMOV(1, 1, 0, ((regnum - ARM_VFP_V3_D0) >> 4),
+ ((regnum - ARM_VFP_V3_D0) & 0xf)), &value_r0);
+ /* read r1 via dcc */
+ retval = dpm->instr_read_data_dcc(dpm,
+ ARMV4_5_MCR(14, 0, 1, 0, 5, 0),
+ &value_r1);
+ break;
+ default:
+
+ break;
+ }
+
+ if (retval == ERROR_OK) {
+ buf_set_u32(r->value, 0, 32, value_r0);
+ buf_set_u32(r->value + 4, 0, 32, value_r1);
+ r->valid = true;
+ r->dirty = false;
+ LOG_DEBUG("READ: %s, %8.8x, %8.8x", r->name,
+ (unsigned) value_r0, (unsigned) value_r1);
+ }
+
+ return retval;
+}
+
/* just read the register -- rely on the core mode being right */
static int dpm_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum)
{
@@ -171,6 +207,14 @@ static int dpm_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum)
break;
}
break;
+ case ARM_VFP_V3_D0 ... ARM_VFP_V3_D31:
+ return dpm_read_reg_u64(dpm, r, regnum);
+ break;
+ case ARM_VFP_V3_FPSCR:
+ /* "VMRS r0, FPSCR"; then return via DCC */
+ retval = dpm->instr_read_data_r0(dpm,
+ ARMV4_5_VMRS(0), &value);
+ break;
default:
/* 16: "MRS r0, CPSR"; then return via DCC
* 17: "MRS r0, SPSR"; then return via DCC
@@ -191,6 +235,40 @@ static int dpm_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum)
return retval;
}
+/* Write 64bit VFP registers */
+static int dpm_write_reg_u64(struct arm_dpm *dpm, struct reg *r, unsigned regnum)
+{
+ int retval = ERROR_FAIL;
+ uint32_t value_r0 = buf_get_u32(r->value, 0, 32);
+ uint32_t value_r1 = buf_get_u32(r->value + 4, 0, 32);
+
+ switch (regnum) {
+ case ARM_VFP_V3_D0 ... ARM_VFP_V3_D31:
+ /* write value_r1 to r1 via dcc */
+ retval = dpm->instr_write_data_dcc(dpm,
+ ARMV4_5_MRC(14, 0, 1, 0, 5, 0),
+ value_r1);
+ /* write value_r0 to r0 via dcc then,
+ * move to double word register from r0:r1: "vmov vm, r0, r1"
+ */
+ retval = dpm->instr_write_data_r0(dpm,
+ ARMV4_5_VMOV(0, 1, 0, ((regnum - ARM_VFP_V3_D0) >> 4),
+ ((regnum - ARM_VFP_V3_D0) & 0xf)), value_r0);
+ break;
+ default:
+
+ break;
+ }
+
+ if (retval == ERROR_OK) {
+ r->dirty = false;
+ LOG_DEBUG("WRITE: %s, %8.8x, %8.8x", r->name,
+ (unsigned) value_r0, (unsigned) value_r1);
+ }
+
+ return retval;
+}
+
/* just write the register -- rely on the core mode being right */
static int dpm_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum)
{
@@ -208,6 +286,14 @@ static int dpm_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum)
* read r0 from DCC; then "MOV pc, r0" */
retval = dpm->instr_write_data_r0(dpm, 0xe1a0f000, value);
break;
+ case ARM_VFP_V3_D0 ... ARM_VFP_V3_D31:
+ return dpm_write_reg_u64(dpm, r, regnum);
+ break;
+ case ARM_VFP_V3_FPSCR:
+ /* move to r0 from DCC, then "VMSR FPSCR, r0" */
+ retval = dpm->instr_write_data_r0(dpm,
+ ARMV4_5_VMSR(0), value);
+ break;
default:
/* 16: read r0 from DCC, then "MSR r0, CPSR_cxsf"
* 17: read r0 from DCC, then "MSR r0, SPSR_cxsf"
@@ -262,14 +348,16 @@ int arm_dpm_read_current_registers(struct arm_dpm *dpm)
if (retval != ERROR_OK)
return retval;
- /* read R0 first (it's used for scratch), then CPSR */
- r = arm->core_cache->reg_list + 0;
- if (!r->valid) {
- retval = dpm_read_reg(dpm, r, 0);
- if (retval != ERROR_OK)
- goto fail;
+ /* read R0 and R1 first (it's used for scratch), then CPSR */
+ for (unsigned i = 0; i < 2; i++) {
+ r = arm->core_cache->reg_list + i;
+ if (!r->valid) {
+ retval = dpm_read_reg(dpm, r, i);
+ if (retval != ERROR_OK)
+ goto fail;
+ }
+ r->dirty = true;
}
- r->dirty = true;
retval = dpm->instr_read_data_r0(dpm, ARMV4_5_MRS(0, 0), &cpsr);
if (retval != ERROR_OK)
@@ -279,7 +367,7 @@ int arm_dpm_read_current_registers(struct arm_dpm *dpm)
arm_set_cpsr(arm, cpsr);
/* REVISIT we can probably avoid reading R1..R14, saving time... */
- for (unsigned i = 1; i < 16; i++) {
+ for (unsigned i = 2; i < 16; i++) {
r = arm_reg_current(arm, i);
if (r->valid)
continue;
@@ -412,8 +500,8 @@ int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp)
did_write = false;
- /* check everything except our scratch register R0 */
- for (unsigned i = 1; i < cache->num_regs; i++) {
+ /* check everything except our scratch registers R0 and R1 */
+ for (unsigned i = 2; i < cache->num_regs; i++) {
struct arm_reg *r;
unsigned regnum;
@@ -540,6 +628,7 @@ static enum arm_mode dpm_mapmode(struct arm *arm,
/* r13/sp, and r14/lr are always shadowed */
case 13:
case 14:
+ case ARM_VFP_V3_D0 ... ARM_VFP_V3_FPSCR:
return mode;
default:
LOG_WARNING("invalid register #%u", num);
@@ -561,7 +650,8 @@ static int arm_dpm_read_core_reg(struct target *target, struct reg *r,
struct arm_dpm *dpm = target_to_arm(target)->dpm;
int retval;
- if (regnum < 0 || regnum > 16)
+ if (regnum < 0 || (regnum > 16 && regnum < ARM_VFP_V3_D0) ||
+ (regnum > ARM_VFP_V3_FPSCR))
return ERROR_COMMAND_SYNTAX_ERROR;
if (regnum == 16) {
@@ -604,7 +694,8 @@ static int arm_dpm_write_core_reg(struct target *target, struct reg *r,
int retval;
- if (regnum < 0 || regnum > 16)
+ if (regnum < 0 || (regnum > 16 && regnum < ARM_VFP_V3_D0) ||
+ (regnum > ARM_VFP_V3_FPSCR))
return ERROR_COMMAND_SYNTAX_ERROR;
if (regnum == 16) {
diff --git a/src/target/arm_opcodes.h b/src/target/arm_opcodes.h
index a53fee7..482abe6 100644
--- a/src/target/arm_opcodes.h
+++ b/src/target/arm_opcodes.h
@@ -132,6 +132,30 @@
*/
#define ARMV4_5_BX(Rm) (0xe12fff10 | (Rm))
+/* Copies two words from two ARM core registers
+ * into a doubleword extension register, or
+ * from a doubleword extension register to two ARM core registers.
+ * See Armv7-A arch reference manual section A8.8.345
+ * Rt: Arm core register 1
+ * Rt2: Arm core register 2
+ * Vm: The doubleword extension register
+ * M: m = UInt(M:Vm);
+ * op: to_arm_registers = (op == ‘1’);
+ */
+#define ARMV4_5_VMOV(op, Rt2, Rt, M, Vm) \
+ (0xec400b10 | ((op) << 20) | ((Rt2) << 16) | \
+ ((Rt) << 12) | ((M) << 5) | (Vm))
+
+/* Moves the value of the FPSCR to an ARM core register
+ * Rt: Arm core register
+ */
+#define ARMV4_5_VMRS(Rt) (0xeef10a10 | ((Rt) << 12))
+
+/* Moves the value of an ARM core register to the FPSCR.
+ * Rt: Arm core register
+ */
+#define ARMV4_5_VMSR(Rt) (0xeee10a10 | ((Rt) << 12))
+
/* Store data from coprocessor to consecutive memory
* See Armv7-A arch doc section A8.6.187
* P: 1=index mode (offset from Rn)
diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c
index 48050b0..a6fadaa 100644
--- a/src/target/armv4_5.c
+++ b/src/target/armv4_5.c
@@ -340,6 +340,50 @@ static const struct {
};
+static const struct {
+ unsigned int id;
+ const char *name;
+ uint32_t bits;
+ enum arm_mode mode;
+ enum reg_type type;
+ const char *group;
+ const char *feature;
+} arm_vfp_v3_regs[] = {
+ { ARM_VFP_V3_D0, "d0", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D1, "d1", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D2, "d2", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D3, "d3", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D4, "d4", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D5, "d5", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D6, "d6", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D7, "d7", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D8, "d8", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D9, "d9", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D10, "d10", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D11, "d11", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D12, "d12", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D13, "d13", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D14, "d14", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D15, "d15", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D16, "d16", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D17, "d17", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D18, "d18", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D19, "d19", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D20, "d20", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D21, "d21", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D22, "d22", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D23, "d23", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D24, "d24", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D25, "d25", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D26, "d26", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D27, "d27", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D28, "d28", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D29, "d29", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D30, "d30", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_D31, "d31", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARM_VFP_V3_FPSCR, "fpscr", 32, ARM_MODE_ANY, REG_TYPE_INT, "float", "org.gnu.gdb.arm.vfp"},
+};
+
/* map core mode (USR, FIQ, ...) and register number to
* indices into the register cache
*/
@@ -567,6 +611,10 @@ static int armv4_5_set_core_reg(struct reg *reg, uint8_t *buf)
}
} else {
buf_set_u32(reg->value, 0, 32, value);
+ if (reg->size == 64) {
+ value = buf_get_u32(buf + 4, 0, 32);
+ buf_set_u32(reg->value + 4, 0, 32, value);
+ }
reg->valid = 1;
}
reg->dirty = 1;
@@ -582,6 +630,10 @@ static const struct reg_arch_type arm_reg_type = {
struct reg_cache *arm_build_reg_cache(struct target *target, struct arm *arm)
{
int num_regs = ARRAY_SIZE(arm_core_regs);
+ int num_core_regs = num_regs;
+ if (arm->arm_vfp_version == ARM_VFP_V3)
+ num_regs += ARRAY_SIZE(arm_vfp_v3_regs);
+
struct reg_cache *cache = malloc(sizeof(struct reg_cache));
struct reg *reg_list = calloc(num_regs, sizeof(struct reg));
struct arm_reg *reg_arch_info = calloc(num_regs, sizeof(struct arm_reg));
@@ -599,7 +651,7 @@ struct reg_cache *arm_build_reg_cache(struct target *target, struct arm *arm)
cache->reg_list = reg_list;
cache->num_regs = 0;
- for (i = 0; i < num_regs; i++) {
+ for (i = 0; i < num_core_regs; i++) {
/* Skip registers this core doesn't expose */
if (arm_core_regs[i].mode == ARM_MODE_MON
&& arm->core_type != ARM_MODE_MON)
@@ -651,9 +703,38 @@ struct reg_cache *arm_build_reg_cache(struct target *target, struct arm *arm)
cache->num_regs++;
}
+ int j;
+ for (i = num_core_regs, j = 0; i < num_regs; i++, j++) {
+ reg_arch_info[i].num = arm_vfp_v3_regs[j].id;
+ reg_arch_info[i].mode = arm_vfp_v3_regs[j].mode;
+ reg_arch_info[i].target = target;
+ reg_arch_info[i].arm = arm;
+
+ reg_list[i].name = arm_vfp_v3_regs[j].name;
+ reg_list[i].number = arm_vfp_v3_regs[j].id;
+ reg_list[i].size = arm_vfp_v3_regs[j].bits;
+ reg_list[i].value = reg_arch_info[i].value;
+ reg_list[i].type = &arm_reg_type;
+ reg_list[i].arch_info = &reg_arch_info[i];
+ reg_list[i].exist = true;
+
+ reg_list[i].caller_save = false;
+
+ reg_list[i].reg_data_type = malloc(sizeof(struct reg_data_type));
+ reg_list[i].reg_data_type->type = arm_vfp_v3_regs[j].type;
+
+ reg_list[i].feature = malloc(sizeof(struct reg_feature));
+ reg_list[i].feature->name = arm_vfp_v3_regs[j].feature;
+
+ reg_list[i].group = arm_vfp_v3_regs[j].group;
+
+ cache->num_regs++;
+ }
+
arm->pc = reg_list + 15;
arm->cpsr = reg_list + ARMV4_5_CPSR;
arm->core_cache = cache;
+
return cache;
}
@@ -1229,6 +1310,10 @@ int arm_get_gdb_reg_list(struct target *target,
case REG_CLASS_ALL:
*reg_list_size = (arm->core_type != ARM_MODE_MON ? 48 : 51);
+ unsigned int list_size_core = *reg_list_size;
+ if (arm->arm_vfp_version == ARM_VFP_V3)
+ *reg_list_size += 33;
+
*reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
for (i = 0; i < 16; i++)
@@ -1249,6 +1334,12 @@ int arm_get_gdb_reg_list(struct target *target,
(*reg_list)[24] = &arm_gdb_dummy_fps_reg;
(*reg_list)[24]->size = 0;
+ if (arm->arm_vfp_version == ARM_VFP_V3) {
+ unsigned int num_core_regs = ARRAY_SIZE(arm_core_regs);
+ for (i = 0; i < 33; i++)
+ (*reg_list)[list_size_core + i] = &(arm->core_cache->reg_list[num_core_regs + i]);
+ }
+
return ERROR_OK;
break;
diff --git a/src/target/armv7a.c b/src/target/armv7a.c
index db72afd..fab7363 100644
--- a/src/target/armv7a.c
+++ b/src/target/armv7a.c
@@ -129,9 +129,13 @@ static int armv7a_read_ttbcr(struct target *target)
struct armv7a_common *armv7a = target_to_armv7a(target);
struct arm_dpm *dpm = armv7a->arm.dpm;
uint32_t ttbcr, ttbcr_n;
- int retval = dpm->prepare(dpm);
+ int ttbidx;
+ int retval;
+
+ retval = dpm->prepare(dpm);
if (retval != ERROR_OK)
goto done;
+
/* MRC p15,0,<Rt>,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/
retval = dpm->instr_read_data_r0(dpm,
ARMV4_5_MRC(15, 0, 0, 2, 0, 2),
@@ -145,6 +149,15 @@ static int armv7a_read_ttbcr(struct target *target)
armv7a->armv7a_mmu.ttbcr = ttbcr;
armv7a->armv7a_mmu.cached = 1;
+ for (ttbidx = 0; ttbidx < 2; ttbidx++) {
+ /* MRC p15,0,<Rt>,c2,c0,ttbidx */
+ retval = dpm->instr_read_data_r0(dpm,
+ ARMV4_5_MRC(15, 0, 0, 2, 0, ttbidx),
+ &armv7a->armv7a_mmu.ttbr[ttbidx]);
+ if (retval != ERROR_OK)
+ goto done;
+ }
+
/*
* ARM Architecture Reference Manual (ARMv7-A and ARMv7-Redition),
* document # ARM DDI 0406C
@@ -182,42 +195,21 @@ int armv7a_mmu_translate_va(struct target *target, uint32_t va, uint32_t *val)
uint32_t second_lvl_descriptor = 0x0;
int retval;
struct armv7a_common *armv7a = target_to_armv7a(target);
- struct arm_dpm *dpm = armv7a->arm.dpm;
uint32_t ttbidx = 0; /* default to ttbr0 */
uint32_t ttb_mask;
uint32_t va_mask;
- uint32_t ttbcr;
uint32_t ttb;
- retval = dpm->prepare(dpm);
- if (retval != ERROR_OK)
- goto done;
-
- /* MRC p15,0,<Rt>,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/
- retval = dpm->instr_read_data_r0(dpm,
- ARMV4_5_MRC(15, 0, 0, 2, 0, 2),
- &ttbcr);
- if (retval != ERROR_OK)
- goto done;
-
- /* if ttbcr has changed or was not read before, re-read the information */
- if ((armv7a->armv7a_mmu.cached == 0) ||
- (armv7a->armv7a_mmu.ttbcr != ttbcr)) {
- armv7a_read_ttbcr(target);
- }
+ if (target->state != TARGET_HALTED)
+ LOG_INFO("target not halted, using cached values for translation table!");
/* if va is above the range handled by ttbr0, select ttbr1 */
if (va > armv7a->armv7a_mmu.ttbr_range[0]) {
/* select ttb 1 */
ttbidx = 1;
}
- /* MRC p15,0,<Rt>,c2,c0,ttbidx */
- retval = dpm->instr_read_data_r0(dpm,
- ARMV4_5_MRC(15, 0, 0, 2, 0, ttbidx),
- &ttb);
- if (retval != ERROR_OK)
- return retval;
+ ttb = armv7a->armv7a_mmu.ttbr[ttbidx];
ttb_mask = armv7a->armv7a_mmu.ttbr_mask[ttbidx];
va_mask = 0xfff00000 & armv7a->armv7a_mmu.ttbr_range[ttbidx];
@@ -279,9 +271,6 @@ int armv7a_mmu_translate_va(struct target *target, uint32_t va, uint32_t *val)
}
return ERROR_OK;
-
-done:
- return retval;
}
/* V7 method VA TO PA */
@@ -740,6 +729,8 @@ int armv7a_arch_state(struct target *target)
arm_arch_state(target);
+ armv7a_read_ttbcr(target);
+
if (armv7a->is_armv7r) {
LOG_USER("D-Cache: %s, I-Cache: %s",
state[armv7a->armv7a_mmu.armv7a_cache.d_u_cache_enabled],
@@ -786,9 +777,6 @@ const struct command_registration l2x_cache_command_handlers[] = {
const struct command_registration armv7a_command_handlers[] = {
{
- .chain = dap_command_handlers,
- },
- {
.chain = l2x_cache_command_handlers,
},
{
diff --git a/src/target/armv7a.h b/src/target/armv7a.h
index 14112e4..33f6f5d 100644
--- a/src/target/armv7a.h
+++ b/src/target/armv7a.h
@@ -87,6 +87,7 @@ struct armv7a_mmu_common {
/* following field mmu working way */
int32_t cached; /* 0: not initialized, 1: initialized */
uint32_t ttbcr; /* cache for ttbcr register */
+ uint32_t ttbr[2];
uint32_t ttbr_mask[2];
uint32_t ttbr_range[2];
diff --git a/src/target/armv7a_cache.c b/src/target/armv7a_cache.c
index 7af3e6d..3e5f8d6 100644
--- a/src/target/armv7a_cache.c
+++ b/src/target/armv7a_cache.c
@@ -148,10 +148,11 @@ int armv7a_cache_auto_flush_all_data(struct target *target)
} else
retval = armv7a_l1_d_cache_clean_inval_all(target);
- /* do outer cache flushing after inner caches have been flushed */
- retval = arm7a_l2x_flush_all_data(target);
+ if (retval != ERROR_OK)
+ return retval;
- return retval;
+ /* do outer cache flushing after inner caches have been flushed */
+ return arm7a_l2x_flush_all_data(target);
}
diff --git a/src/target/armv7m.c b/src/target/armv7m.c
index e0911c3..a8ddfe8 100644
--- a/src/target/armv7m.c
+++ b/src/target/armv7m.c
@@ -843,8 +843,5 @@ const struct command_registration armv7m_command_handlers[] = {
{
.chain = arm_command_handlers,
},
- {
- .chain = dap_command_handlers,
- },
COMMAND_REGISTRATION_DONE
};
diff --git a/src/target/armv8.c b/src/target/armv8.c
index 1b8e450..3321dd6 100644
--- a/src/target/armv8.c
+++ b/src/target/armv8.c
@@ -135,6 +135,16 @@ static int armv8_read_reg(struct armv8_common *armv8, int regnum, uint64_t *regv
ARMV8_MRS_DSPSR(0), &value);
value_64 = value;
break;
+ case ARMV8_FPSR:
+ retval = dpm->instr_read_data_r0(dpm,
+ ARMV8_MRS_FPSR(0), &value);
+ value_64 = value;
+ break;
+ case ARMV8_FPCR:
+ retval = dpm->instr_read_data_r0(dpm,
+ ARMV8_MRS_FPCR(0), &value);
+ value_64 = value;
+ break;
case ARMV8_ELR_EL1:
retval = dpm->instr_read_data_r0_64(dpm,
ARMV8_MRS(SYSTEM_ELR_EL1, 0), &value_64);
@@ -184,6 +194,31 @@ static int armv8_read_reg(struct armv8_common *armv8, int regnum, uint64_t *regv
if (retval == ERROR_OK && regval != NULL)
*regval = value_64;
+ else
+ retval = ERROR_FAIL;
+
+ return retval;
+}
+
+static int armv8_read_reg_simdfp_aarch64(struct armv8_common *armv8, int regnum, uint64_t *lvalue, uint64_t *hvalue)
+{
+ int retval = ERROR_FAIL;
+ struct arm_dpm *dpm = &armv8->dpm;
+
+ switch (regnum) {
+ case ARMV8_V0 ... ARMV8_V31:
+ retval = dpm->instr_read_data_r0_64(dpm,
+ ARMV8_MOV_GPR_VFP(0, (regnum - ARMV8_V0), 1), hvalue);
+ if (retval != ERROR_OK)
+ return retval;
+ retval = dpm->instr_read_data_r0_64(dpm,
+ ARMV8_MOV_GPR_VFP(0, (regnum - ARMV8_V0), 0), lvalue);
+ break;
+
+ default:
+ retval = ERROR_FAIL;
+ break;
+ }
return retval;
}
@@ -216,6 +251,18 @@ static int armv8_write_reg(struct armv8_common *armv8, int regnum, uint64_t valu
ARMV8_MSR_DSPSR(0),
value);
break;
+ case ARMV8_FPSR:
+ value = value_64;
+ retval = dpm->instr_write_data_r0(dpm,
+ ARMV8_MSR_FPSR(0),
+ value);
+ break;
+ case ARMV8_FPCR:
+ value = value_64;
+ retval = dpm->instr_write_data_r0(dpm,
+ ARMV8_MSR_FPCR(0),
+ value);
+ break;
/* registers clobbered by taking exception in debug state */
case ARMV8_ELR_EL1:
retval = dpm->instr_write_data_r0_64(dpm,
@@ -267,6 +314,29 @@ static int armv8_write_reg(struct armv8_common *armv8, int regnum, uint64_t valu
return retval;
}
+static int armv8_write_reg_simdfp_aarch64(struct armv8_common *armv8, int regnum, uint64_t lvalue, uint64_t hvalue)
+{
+ int retval = ERROR_FAIL;
+ struct arm_dpm *dpm = &armv8->dpm;
+
+ switch (regnum) {
+ case ARMV8_V0 ... ARMV8_V31:
+ retval = dpm->instr_write_data_r0_64(dpm,
+ ARMV8_MOV_VFP_GPR((regnum - ARMV8_V0), 0, 1), hvalue);
+ if (retval != ERROR_OK)
+ return retval;
+ retval = dpm->instr_write_data_r0_64(dpm,
+ ARMV8_MOV_VFP_GPR((regnum - ARMV8_V0), 0, 0), lvalue);
+ break;
+
+ default:
+ retval = ERROR_FAIL;
+ break;
+ }
+
+ return retval;
+}
+
static int armv8_read_reg32(struct armv8_common *armv8, int regnum, uint64_t *regval)
{
struct arm_dpm *dpm = &armv8->dpm;
@@ -338,6 +408,11 @@ static int armv8_read_reg32(struct armv8_common *armv8, int regnum, uint64_t *re
ARMV8_MRS_xPSR_T1(1, 0),
&value);
break;
+ case ARMV8_FPSR:
+ /* "VMRS r0, FPSCR"; then return via DCC */
+ retval = dpm->instr_read_data_r0(dpm,
+ ARMV4_5_VMRS(0), &value);
+ break;
default:
retval = ERROR_FAIL;
break;
@@ -349,6 +424,56 @@ static int armv8_read_reg32(struct armv8_common *armv8, int regnum, uint64_t *re
return retval;
}
+static int armv8_read_reg_simdfp_aarch32(struct armv8_common *armv8, int regnum, uint64_t *lvalue, uint64_t *hvalue)
+{
+ int retval = ERROR_FAIL;
+ struct arm_dpm *dpm = &armv8->dpm;
+ struct reg *reg_r1 = dpm->arm->core_cache->reg_list + ARMV8_R1;
+ uint32_t value_r0 = 0, value_r1 = 0;
+ unsigned num = (regnum - ARMV8_V0) << 1;
+
+ switch (regnum) {
+ case ARMV8_V0 ... ARMV8_V15:
+ /* we are going to write R1, mark it dirty */
+ reg_r1->dirty = true;
+ /* move from double word register to r0:r1: "vmov r0, r1, vm"
+ * then read r0 via dcc
+ */
+ retval = dpm->instr_read_data_r0(dpm,
+ ARMV4_5_VMOV(1, 1, 0, (num >> 4), (num & 0xf)),
+ &value_r0);
+ /* read r1 via dcc */
+ retval = dpm->instr_read_data_dcc(dpm,
+ ARMV4_5_MCR(14, 0, 1, 0, 5, 0),
+ &value_r1);
+ if (retval == ERROR_OK) {
+ *lvalue = value_r1;
+ *lvalue = ((*lvalue) << 32) | value_r0;
+ } else
+ return retval;
+
+ num++;
+ /* repeat above steps for high 64 bits of V register */
+ retval = dpm->instr_read_data_r0(dpm,
+ ARMV4_5_VMOV(1, 1, 0, (num >> 4), (num & 0xf)),
+ &value_r0);
+ retval = dpm->instr_read_data_dcc(dpm,
+ ARMV4_5_MCR(14, 0, 1, 0, 5, 0),
+ &value_r1);
+ if (retval == ERROR_OK) {
+ *hvalue = value_r1;
+ *hvalue = ((*hvalue) << 32) | value_r0;
+ } else
+ return retval;
+ break;
+ default:
+ retval = ERROR_FAIL;
+ break;
+ }
+
+ return retval;
+}
+
static int armv8_write_reg32(struct armv8_common *armv8, int regnum, uint64_t value)
{
struct arm_dpm *dpm = &armv8->dpm;
@@ -417,6 +542,11 @@ static int armv8_write_reg32(struct armv8_common *armv8, int regnum, uint64_t va
ARMV8_MSR_GP_xPSR_T1(1, 0, 15),
value);
break;
+ case ARMV8_FPSR:
+ /* move to r0 from DCC, then "VMSR FPSCR, r0" */
+ retval = dpm->instr_write_data_r0(dpm,
+ ARMV4_5_VMSR(0), value);
+ break;
default:
retval = ERROR_FAIL;
break;
@@ -426,14 +556,63 @@ static int armv8_write_reg32(struct armv8_common *armv8, int regnum, uint64_t va
}
+static int armv8_write_reg_simdfp_aarch32(struct armv8_common *armv8, int regnum, uint64_t lvalue, uint64_t hvalue)
+{
+ int retval = ERROR_FAIL;
+ struct arm_dpm *dpm = &armv8->dpm;
+ struct reg *reg_r1 = dpm->arm->core_cache->reg_list + ARMV8_R1;
+ uint32_t value_r0 = 0, value_r1 = 0;
+ unsigned num = (regnum - ARMV8_V0) << 1;
+
+ switch (regnum) {
+ case ARMV8_V0 ... ARMV8_V15:
+ /* we are going to write R1, mark it dirty */
+ reg_r1->dirty = true;
+ value_r1 = lvalue >> 32;
+ value_r0 = lvalue & 0xFFFFFFFF;
+ /* write value_r1 to r1 via dcc */
+ retval = dpm->instr_write_data_dcc(dpm,
+ ARMV4_5_MRC(14, 0, 1, 0, 5, 0),
+ value_r1);
+ /* write value_r0 to r0 via dcc then,
+ * move to double word register from r0:r1: "vmov vm, r0, r1"
+ */
+ retval = dpm->instr_write_data_r0(dpm,
+ ARMV4_5_VMOV(0, 1, 0, (num >> 4), (num & 0xf)),
+ value_r0);
+
+ num++;
+ /* repeat above steps for high 64 bits of V register */
+ value_r1 = hvalue >> 32;
+ value_r0 = hvalue & 0xFFFFFFFF;
+ retval = dpm->instr_write_data_dcc(dpm,
+ ARMV4_5_MRC(14, 0, 1, 0, 5, 0),
+ value_r1);
+ retval = dpm->instr_write_data_r0(dpm,
+ ARMV4_5_VMOV(0, 1, 0, (num >> 4), (num & 0xf)),
+ value_r0);
+ break;
+ default:
+ retval = ERROR_FAIL;
+ break;
+ }
+
+ return retval;
+}
+
void armv8_select_reg_access(struct armv8_common *armv8, bool is_aarch64)
{
if (is_aarch64) {
armv8->read_reg_u64 = armv8_read_reg;
armv8->write_reg_u64 = armv8_write_reg;
+ armv8->read_reg_u128 = armv8_read_reg_simdfp_aarch64;
+ armv8->write_reg_u128 = armv8_write_reg_simdfp_aarch64;
+
} else {
armv8->read_reg_u64 = armv8_read_reg32;
armv8->write_reg_u64 = armv8_write_reg32;
+ armv8->read_reg_u128 = armv8_read_reg_simdfp_aarch32;
+ armv8->write_reg_u128 = armv8_write_reg_simdfp_aarch32;
}
}
@@ -441,6 +620,7 @@ void armv8_select_reg_access(struct armv8_common *armv8, bool is_aarch64)
int armv8_read_mpidr(struct armv8_common *armv8)
{
int retval = ERROR_FAIL;
+ struct arm *arm = &armv8->arm;
struct arm_dpm *dpm = armv8->arm.dpm;
uint32_t mpidr;
@@ -448,6 +628,13 @@ int armv8_read_mpidr(struct armv8_common *armv8)
if (retval != ERROR_OK)
goto done;
+ /* check if we're in an unprivileged mode */
+ if (armv8_curel_from_core_mode(arm->core_mode) < SYSTEM_CUREL_EL1) {
+ retval = armv8_dpm_modeswitch(dpm, ARMV8_64_EL1H);
+ if (retval != ERROR_OK)
+ return retval;
+ }
+
retval = dpm->instr_read_data_r0(dpm, armv8_opcode(armv8, READ_REG_MPIDR), &mpidr);
if (retval != ERROR_OK)
goto done;
@@ -463,6 +650,7 @@ int armv8_read_mpidr(struct armv8_common *armv8)
LOG_ERROR("mpidr not in multiprocessor format");
done:
+ armv8_dpm_modeswitch(dpm, ARM_MODE_ANY);
dpm->finish(dpm);
return retval;
}
@@ -897,6 +1085,152 @@ int armv8_arch_state(struct target *target)
return ERROR_OK;
}
+static struct reg_data_type aarch64_vector_base_types[] = {
+ {REG_TYPE_IEEE_DOUBLE, "ieee_double", 0, {NULL} },
+ {REG_TYPE_UINT64, "uint64", 0, {NULL} },
+ {REG_TYPE_INT64, "int64", 0, {NULL} },
+ {REG_TYPE_IEEE_SINGLE, "ieee_single", 0, {NULL} },
+ {REG_TYPE_UINT32, "uint32", 0, {NULL} },
+ {REG_TYPE_INT32, "int32", 0, {NULL} },
+ {REG_TYPE_UINT16, "uint16", 0, {NULL} },
+ {REG_TYPE_INT16, "int16", 0, {NULL} },
+ {REG_TYPE_UINT8, "uint8", 0, {NULL} },
+ {REG_TYPE_INT8, "int8", 0, {NULL} },
+ {REG_TYPE_UINT128, "uint128", 0, {NULL} },
+ {REG_TYPE_INT128, "int128", 0, {NULL} }
+};
+
+static struct reg_data_type_vector aarch64_vector_types[] = {
+ {aarch64_vector_base_types + 0, 2},
+ {aarch64_vector_base_types + 1, 2},
+ {aarch64_vector_base_types + 2, 2},
+ {aarch64_vector_base_types + 3, 4},
+ {aarch64_vector_base_types + 4, 4},
+ {aarch64_vector_base_types + 5, 4},
+ {aarch64_vector_base_types + 6, 8},
+ {aarch64_vector_base_types + 7, 8},
+ {aarch64_vector_base_types + 8, 16},
+ {aarch64_vector_base_types + 9, 16},
+ {aarch64_vector_base_types + 10, 01},
+ {aarch64_vector_base_types + 11, 01},
+};
+
+static struct reg_data_type aarch64_fpu_vector[] = {
+ {REG_TYPE_ARCH_DEFINED, "v2d", REG_TYPE_CLASS_VECTOR, {aarch64_vector_types + 0} },
+ {REG_TYPE_ARCH_DEFINED, "v2u", REG_TYPE_CLASS_VECTOR, {aarch64_vector_types + 1} },
+ {REG_TYPE_ARCH_DEFINED, "v2i", REG_TYPE_CLASS_VECTOR, {aarch64_vector_types + 2} },
+ {REG_TYPE_ARCH_DEFINED, "v4f", REG_TYPE_CLASS_VECTOR, {aarch64_vector_types + 3} },
+ {REG_TYPE_ARCH_DEFINED, "v4u", REG_TYPE_CLASS_VECTOR, {aarch64_vector_types + 4} },
+ {REG_TYPE_ARCH_DEFINED, "v4i", REG_TYPE_CLASS_VECTOR, {aarch64_vector_types + 5} },
+ {REG_TYPE_ARCH_DEFINED, "v8u", REG_TYPE_CLASS_VECTOR, {aarch64_vector_types + 6} },
+ {REG_TYPE_ARCH_DEFINED, "v8i", REG_TYPE_CLASS_VECTOR, {aarch64_vector_types + 7} },
+ {REG_TYPE_ARCH_DEFINED, "v16u", REG_TYPE_CLASS_VECTOR, {aarch64_vector_types + 8} },
+ {REG_TYPE_ARCH_DEFINED, "v16i", REG_TYPE_CLASS_VECTOR, {aarch64_vector_types + 9} },
+ {REG_TYPE_ARCH_DEFINED, "v1u", REG_TYPE_CLASS_VECTOR, {aarch64_vector_types + 10} },
+ {REG_TYPE_ARCH_DEFINED, "v1i", REG_TYPE_CLASS_VECTOR, {aarch64_vector_types + 11} },
+};
+
+static struct reg_data_type_union_field aarch64_union_fields_vnd[] = {
+ {"f", aarch64_fpu_vector + 0, aarch64_union_fields_vnd + 1},
+ {"u", aarch64_fpu_vector + 1, aarch64_union_fields_vnd + 2},
+ {"s", aarch64_fpu_vector + 2, NULL},
+};
+
+static struct reg_data_type_union_field aarch64_union_fields_vns[] = {
+ {"f", aarch64_fpu_vector + 3, aarch64_union_fields_vns + 1},
+ {"u", aarch64_fpu_vector + 4, aarch64_union_fields_vns + 2},
+ {"s", aarch64_fpu_vector + 5, NULL},
+};
+
+static struct reg_data_type_union_field aarch64_union_fields_vnh[] = {
+ {"u", aarch64_fpu_vector + 6, aarch64_union_fields_vnh + 1},
+ {"s", aarch64_fpu_vector + 7, NULL},
+};
+
+static struct reg_data_type_union_field aarch64_union_fields_vnb[] = {
+ {"u", aarch64_fpu_vector + 8, aarch64_union_fields_vnb + 1},
+ {"s", aarch64_fpu_vector + 9, NULL},
+};
+
+static struct reg_data_type_union_field aarch64_union_fields_vnq[] = {
+ {"u", aarch64_fpu_vector + 10, aarch64_union_fields_vnq + 1},
+ {"s", aarch64_fpu_vector + 11, NULL},
+};
+
+static struct reg_data_type_union aarch64_union_types[] = {
+ {aarch64_union_fields_vnd},
+ {aarch64_union_fields_vns},
+ {aarch64_union_fields_vnh},
+ {aarch64_union_fields_vnb},
+ {aarch64_union_fields_vnq},
+};
+
+static struct reg_data_type aarch64_fpu_union[] = {
+ {REG_TYPE_ARCH_DEFINED, "vnd", REG_TYPE_CLASS_UNION, {.reg_type_union = aarch64_union_types + 0} },
+ {REG_TYPE_ARCH_DEFINED, "vns", REG_TYPE_CLASS_UNION, {.reg_type_union = aarch64_union_types + 1} },
+ {REG_TYPE_ARCH_DEFINED, "vnh", REG_TYPE_CLASS_UNION, {.reg_type_union = aarch64_union_types + 2} },
+ {REG_TYPE_ARCH_DEFINED, "vnb", REG_TYPE_CLASS_UNION, {.reg_type_union = aarch64_union_types + 3} },
+ {REG_TYPE_ARCH_DEFINED, "vnq", REG_TYPE_CLASS_UNION, {.reg_type_union = aarch64_union_types + 4} },
+};
+
+static struct reg_data_type_union_field aarch64v_union_fields[] = {
+ {"d", aarch64_fpu_union + 0, aarch64v_union_fields + 1},
+ {"s", aarch64_fpu_union + 1, aarch64v_union_fields + 2},
+ {"h", aarch64_fpu_union + 2, aarch64v_union_fields + 3},
+ {"b", aarch64_fpu_union + 3, aarch64v_union_fields + 4},
+ {"q", aarch64_fpu_union + 4, NULL},
+};
+
+static struct reg_data_type_union aarch64v_union[] = {
+ {aarch64v_union_fields}
+};
+
+static struct reg_data_type aarch64v[] = {
+ {REG_TYPE_ARCH_DEFINED, "aarch64v", REG_TYPE_CLASS_UNION,
+ {.reg_type_union = aarch64v_union} },
+};
+
+static struct reg_data_type_bitfield aarch64_cpsr_bits[] = {
+ { 0, 0 , REG_TYPE_UINT8 },
+ { 2, 3, REG_TYPE_UINT8 },
+ { 4, 4 , REG_TYPE_UINT8 },
+ { 6, 6 , REG_TYPE_BOOL },
+ { 7, 7 , REG_TYPE_BOOL },
+ { 8, 8 , REG_TYPE_BOOL },
+ { 9, 9 , REG_TYPE_BOOL },
+ { 20, 20, REG_TYPE_BOOL },
+ { 21, 21, REG_TYPE_BOOL },
+ { 28, 28, REG_TYPE_BOOL },
+ { 29, 29, REG_TYPE_BOOL },
+ { 30, 30, REG_TYPE_BOOL },
+ { 31, 31, REG_TYPE_BOOL },
+};
+
+static struct reg_data_type_flags_field aarch64_cpsr_fields[] = {
+ { "SP", aarch64_cpsr_bits + 0, aarch64_cpsr_fields + 1 },
+ { "EL", aarch64_cpsr_bits + 1, aarch64_cpsr_fields + 2 },
+ { "nRW", aarch64_cpsr_bits + 2, aarch64_cpsr_fields + 3 },
+ { "F" , aarch64_cpsr_bits + 3, aarch64_cpsr_fields + 4 },
+ { "I" , aarch64_cpsr_bits + 4, aarch64_cpsr_fields + 5 },
+ { "A" , aarch64_cpsr_bits + 5, aarch64_cpsr_fields + 6 },
+ { "D" , aarch64_cpsr_bits + 6, aarch64_cpsr_fields + 7 },
+ { "IL" , aarch64_cpsr_bits + 7, aarch64_cpsr_fields + 8 },
+ { "SS" , aarch64_cpsr_bits + 8, aarch64_cpsr_fields + 9 },
+ { "V" , aarch64_cpsr_bits + 9, aarch64_cpsr_fields + 10 },
+ { "C" , aarch64_cpsr_bits + 10, aarch64_cpsr_fields + 11 },
+ { "Z" , aarch64_cpsr_bits + 11, aarch64_cpsr_fields + 12 },
+ { "N" , aarch64_cpsr_bits + 12, NULL }
+};
+
+static struct reg_data_type_flags aarch64_cpsr_flags[] = {
+ { 4, aarch64_cpsr_fields }
+};
+
+static struct reg_data_type aarch64_flags_cpsr[] = {
+ {REG_TYPE_ARCH_DEFINED, "cpsr_flags", REG_TYPE_CLASS_FLAGS,
+ {.reg_type_flags = aarch64_cpsr_flags} },
+};
+
static const struct {
unsigned id;
const char *name;
@@ -905,59 +1239,104 @@ static const struct {
enum reg_type type;
const char *group;
const char *feature;
+ struct reg_data_type *data_type;
} armv8_regs[] = {
- { ARMV8_R0, "x0", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" },
- { ARMV8_R1, "x1", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" },
- { ARMV8_R2, "x2", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" },
- { ARMV8_R3, "x3", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" },
- { ARMV8_R4, "x4", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" },
- { ARMV8_R5, "x5", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" },
- { ARMV8_R6, "x6", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" },
- { ARMV8_R7, "x7", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" },
- { ARMV8_R8, "x8", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" },
- { ARMV8_R9, "x9", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" },
- { ARMV8_R10, "x10", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" },
- { ARMV8_R11, "x11", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" },
- { ARMV8_R12, "x12", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" },
- { ARMV8_R13, "x13", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" },
- { ARMV8_R14, "x14", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" },
- { ARMV8_R15, "x15", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" },
- { ARMV8_R16, "x16", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" },
- { ARMV8_R17, "x17", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" },
- { ARMV8_R18, "x18", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" },
- { ARMV8_R19, "x19", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" },
- { ARMV8_R20, "x20", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" },
- { ARMV8_R21, "x21", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" },
- { ARMV8_R22, "x22", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" },
- { ARMV8_R23, "x23", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" },
- { ARMV8_R24, "x24", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" },
- { ARMV8_R25, "x25", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" },
- { ARMV8_R26, "x26", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" },
- { ARMV8_R27, "x27", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" },
- { ARMV8_R28, "x28", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" },
- { ARMV8_R29, "x29", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" },
- { ARMV8_R30, "x30", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" },
-
- { ARMV8_SP, "sp", 64, ARM_MODE_ANY, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.aarch64.core" },
- { ARMV8_PC, "pc", 64, ARM_MODE_ANY, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.aarch64.core" },
-
- { ARMV8_xPSR, "CPSR", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.aarch64.core" },
-
- { ARMV8_ELR_EL1, "ELR_EL1", 64, ARMV8_64_EL1H, REG_TYPE_CODE_PTR, "banked", "net.sourceforge.openocd.banked" },
- { ARMV8_ESR_EL1, "ESR_EL1", 32, ARMV8_64_EL1H, REG_TYPE_UINT32, "banked", "net.sourceforge.openocd.banked" },
- { ARMV8_SPSR_EL1, "SPSR_EL1", 32, ARMV8_64_EL1H, REG_TYPE_UINT32, "banked", "net.sourceforge.openocd.banked" },
-
- { ARMV8_ELR_EL2, "ELR_EL2", 64, ARMV8_64_EL2H, REG_TYPE_CODE_PTR, "banked", "net.sourceforge.openocd.banked" },
- { ARMV8_ESR_EL2, "ESR_EL2", 32, ARMV8_64_EL2H, REG_TYPE_UINT32, "banked", "net.sourceforge.openocd.banked" },
- { ARMV8_SPSR_EL2, "SPSR_EL2", 32, ARMV8_64_EL2H, REG_TYPE_UINT32, "banked", "net.sourceforge.openocd.banked" },
-
- { ARMV8_ELR_EL3, "ELR_EL3", 64, ARMV8_64_EL3H, REG_TYPE_CODE_PTR, "banked", "net.sourceforge.openocd.banked" },
- { ARMV8_ESR_EL3, "ESR_EL3", 32, ARMV8_64_EL3H, REG_TYPE_UINT32, "banked", "net.sourceforge.openocd.banked" },
- { ARMV8_SPSR_EL3, "SPSR_EL3", 32, ARMV8_64_EL3H, REG_TYPE_UINT32, "banked", "net.sourceforge.openocd.banked" },
+ { ARMV8_R0, "x0", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core", NULL},
+ { ARMV8_R1, "x1", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core", NULL},
+ { ARMV8_R2, "x2", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core", NULL},
+ { ARMV8_R3, "x3", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core", NULL},
+ { ARMV8_R4, "x4", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core", NULL},
+ { ARMV8_R5, "x5", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core", NULL},
+ { ARMV8_R6, "x6", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core", NULL},
+ { ARMV8_R7, "x7", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core", NULL},
+ { ARMV8_R8, "x8", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core", NULL},
+ { ARMV8_R9, "x9", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core", NULL},
+ { ARMV8_R10, "x10", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core", NULL},
+ { ARMV8_R11, "x11", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core", NULL},
+ { ARMV8_R12, "x12", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core", NULL},
+ { ARMV8_R13, "x13", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core", NULL},
+ { ARMV8_R14, "x14", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core", NULL},
+ { ARMV8_R15, "x15", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core", NULL},
+ { ARMV8_R16, "x16", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core", NULL},
+ { ARMV8_R17, "x17", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core", NULL},
+ { ARMV8_R18, "x18", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core", NULL},
+ { ARMV8_R19, "x19", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core", NULL},
+ { ARMV8_R20, "x20", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core", NULL},
+ { ARMV8_R21, "x21", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core", NULL},
+ { ARMV8_R22, "x22", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core", NULL},
+ { ARMV8_R23, "x23", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core", NULL},
+ { ARMV8_R24, "x24", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core", NULL},
+ { ARMV8_R25, "x25", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core", NULL},
+ { ARMV8_R26, "x26", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core", NULL},
+ { ARMV8_R27, "x27", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core", NULL},
+ { ARMV8_R28, "x28", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core", NULL},
+ { ARMV8_R29, "x29", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core", NULL},
+ { ARMV8_R30, "x30", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core", NULL},
+
+ { ARMV8_SP, "sp", 64, ARM_MODE_ANY, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.aarch64.core", NULL},
+ { ARMV8_PC, "pc", 64, ARM_MODE_ANY, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.aarch64.core", NULL},
+ { ARMV8_xPSR, "cpsr", 32, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED,
+ "general", "org.gnu.gdb.aarch64.core", aarch64_flags_cpsr},
+ { ARMV8_V0, "v0", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v},
+ { ARMV8_V1, "v1", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v},
+ { ARMV8_V2, "v2", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v},
+ { ARMV8_V3, "v3", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v},
+ { ARMV8_V4, "v4", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v},
+ { ARMV8_V5, "v5", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v},
+ { ARMV8_V6, "v6", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v},
+ { ARMV8_V7, "v7", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v},
+ { ARMV8_V8, "v8", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v},
+ { ARMV8_V9, "v9", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v},
+ { ARMV8_V10, "v10", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v},
+ { ARMV8_V11, "v11", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v},
+ { ARMV8_V12, "v12", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v},
+ { ARMV8_V13, "v13", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v},
+ { ARMV8_V14, "v14", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v},
+ { ARMV8_V15, "v15", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v},
+ { ARMV8_V16, "v16", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v},
+ { ARMV8_V17, "v17", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v},
+ { ARMV8_V18, "v18", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v},
+ { ARMV8_V19, "v19", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v},
+ { ARMV8_V20, "v20", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v},
+ { ARMV8_V21, "v21", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v},
+ { ARMV8_V22, "v22", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v},
+ { ARMV8_V23, "v23", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v},
+ { ARMV8_V24, "v24", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v},
+ { ARMV8_V25, "v25", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v},
+ { ARMV8_V26, "v26", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v},
+ { ARMV8_V27, "v27", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v},
+ { ARMV8_V28, "v28", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v},
+ { ARMV8_V29, "v29", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v},
+ { ARMV8_V30, "v30", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v},
+ { ARMV8_V31, "v31", 128, ARM_MODE_ANY, REG_TYPE_ARCH_DEFINED, "simdfp", "org.gnu.gdb.aarch64.fpu", aarch64v},
+ { ARMV8_FPSR, "fpsr", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "simdfp", "org.gnu.gdb.aarch64.fpu", NULL},
+ { ARMV8_FPCR, "fpcr", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "simdfp", "org.gnu.gdb.aarch64.fpu", NULL},
+
+ { ARMV8_ELR_EL1, "ELR_EL1", 64, ARMV8_64_EL1H, REG_TYPE_CODE_PTR, "banked", "net.sourceforge.openocd.banked",
+ NULL},
+ { ARMV8_ESR_EL1, "ESR_EL1", 32, ARMV8_64_EL1H, REG_TYPE_UINT32, "banked", "net.sourceforge.openocd.banked",
+ NULL},
+ { ARMV8_SPSR_EL1, "SPSR_EL1", 32, ARMV8_64_EL1H, REG_TYPE_UINT32, "banked", "net.sourceforge.openocd.banked",
+ NULL},
+
+ { ARMV8_ELR_EL2, "ELR_EL2", 64, ARMV8_64_EL2H, REG_TYPE_CODE_PTR, "banked", "net.sourceforge.openocd.banked",
+ NULL},
+ { ARMV8_ESR_EL2, "ESR_EL2", 32, ARMV8_64_EL2H, REG_TYPE_UINT32, "banked", "net.sourceforge.openocd.banked",
+ NULL},
+ { ARMV8_SPSR_EL2, "SPSR_EL2", 32, ARMV8_64_EL2H, REG_TYPE_UINT32, "banked", "net.sourceforge.openocd.banked",
+ NULL},
+
+ { ARMV8_ELR_EL3, "ELR_EL3", 64, ARMV8_64_EL3H, REG_TYPE_CODE_PTR, "banked", "net.sourceforge.openocd.banked",
+ NULL},
+ { ARMV8_ESR_EL3, "ESR_EL3", 32, ARMV8_64_EL3H, REG_TYPE_UINT32, "banked", "net.sourceforge.openocd.banked",
+ NULL},
+ { ARMV8_SPSR_EL3, "SPSR_EL3", 32, ARMV8_64_EL3H, REG_TYPE_UINT32, "banked", "net.sourceforge.openocd.banked",
+ NULL},
};
static const struct {
unsigned id;
+ unsigned mapping;
const char *name;
unsigned bits;
enum arm_mode mode;
@@ -965,23 +1344,56 @@ static const struct {
const char *group;
const char *feature;
} armv8_regs32[] = {
- { ARMV8_R0, "r0", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
- { ARMV8_R1, "r1", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
- { ARMV8_R2, "r2", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
- { ARMV8_R3, "r3", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
- { ARMV8_R4, "r4", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
- { ARMV8_R5, "r5", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
- { ARMV8_R6, "r6", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
- { ARMV8_R7, "r7", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
- { ARMV8_R8, "r8", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
- { ARMV8_R9, "r9", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
- { ARMV8_R10, "r10", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
- { ARMV8_R11, "r11", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
- { ARMV8_R12, "r12", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
- { ARMV8_R13, "sp", 32, ARM_MODE_ANY, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.arm.core" },
- { ARMV8_R14, "lr", 32, ARM_MODE_ANY, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.arm.core" },
- { ARMV8_PC, "pc", 32, ARM_MODE_ANY, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.arm.core" },
- { ARMV8_xPSR, "cpsr", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+ { ARMV8_R0, 0, "r0", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+ { ARMV8_R1, 0, "r1", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+ { ARMV8_R2, 0, "r2", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+ { ARMV8_R3, 0, "r3", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+ { ARMV8_R4, 0, "r4", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+ { ARMV8_R5, 0, "r5", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+ { ARMV8_R6, 0, "r6", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+ { ARMV8_R7, 0, "r7", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+ { ARMV8_R8, 0, "r8", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+ { ARMV8_R9, 0, "r9", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+ { ARMV8_R10, 0, "r10", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+ { ARMV8_R11, 0, "r11", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+ { ARMV8_R12, 0, "r12", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+ { ARMV8_R13, 0, "sp", 32, ARM_MODE_ANY, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.arm.core" },
+ { ARMV8_R14, 0, "lr", 32, ARM_MODE_ANY, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.arm.core" },
+ { ARMV8_PC, 0, "pc", 32, ARM_MODE_ANY, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.arm.core" },
+ { ARMV8_xPSR, 0, "cpsr", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" },
+ { ARMV8_V0, 0, "d0", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARMV8_V0, 8, "d1", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARMV8_V1, 0, "d2", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARMV8_V1, 8, "d3", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARMV8_V2, 0, "d4", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARMV8_V2, 8, "d5", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARMV8_V3, 0, "d6", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARMV8_V3, 8, "d7", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARMV8_V4, 0, "d8", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARMV8_V4, 8, "d9", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARMV8_V5, 0, "d10", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARMV8_V5, 8, "d11", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARMV8_V6, 0, "d12", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARMV8_V6, 8, "d13", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARMV8_V7, 0, "d14", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARMV8_V7, 8, "d15", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARMV8_V8, 0, "d16", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARMV8_V8, 8, "d17", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARMV8_V9, 0, "d18", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARMV8_V9, 8, "d19", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARMV8_V10, 0, "d20", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARMV8_V10, 8, "d21", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARMV8_V11, 0, "d22", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARMV8_V11, 8, "d23", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARMV8_V12, 0, "d24", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARMV8_V12, 8, "d25", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARMV8_V13, 0, "d26", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARMV8_V13, 8, "d27", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARMV8_V14, 0, "d28", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARMV8_V14, 8, "d29", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARMV8_V15, 0, "d30", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARMV8_V15, 8, "d31", 64, ARM_MODE_ANY, REG_TYPE_IEEE_DOUBLE, NULL, "org.gnu.gdb.arm.vfp"},
+ { ARMV8_FPSR, 0, "fpscr", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "float", "org.gnu.gdb.arm.vfp"},
};
#define ARMV8_NUM_REGS ARRAY_SIZE(armv8_regs)
@@ -1004,15 +1416,23 @@ static int armv8_set_core_reg(struct reg *reg, uint8_t *buf)
struct arm_reg *armv8_reg = reg->arch_info;
struct target *target = armv8_reg->target;
struct arm *arm = target_to_arm(target);
- uint64_t value = buf_get_u64(buf, 0, 64);
+ uint64_t value = buf_get_u64(buf, 0, reg->size);
if (target->state != TARGET_HALTED)
return ERROR_TARGET_NOT_HALTED;
- if (reg == arm->cpsr) {
- armv8_set_cpsr(arm, (uint32_t)value);
- } else {
+ if (reg->size <= 64) {
+ if (reg == arm->cpsr)
+ armv8_set_cpsr(arm, (uint32_t)value);
+ else {
+ buf_set_u64(reg->value, 0, reg->size, value);
+ reg->valid = 1;
+ }
+ } else if (reg->size <= 128) {
+ uint64_t hvalue = buf_get_u64(buf + 8, 0, reg->size - 64);
+
buf_set_u64(reg->value, 0, 64, value);
+ buf_set_u64(reg->value + 8, 0, reg->size - 64, hvalue);
reg->valid = 1;
}
@@ -1061,7 +1481,12 @@ static int armv8_set_core_reg32(struct reg *reg, uint8_t *buf)
if (reg64 == arm->cpsr) {
armv8_set_cpsr(arm, value);
} else {
- buf_set_u32(reg->value, 0, 32, value);
+ if (reg->size <= 32)
+ buf_set_u32(reg->value, 0, 32, value);
+ else if (reg->size <= 64) {
+ uint64_t value64 = buf_get_u64(buf, 0, 64);
+ buf_set_u64(reg->value, 0, 64, value64);
+ }
reg->valid = 1;
reg64->valid = 1;
}
@@ -1122,11 +1547,15 @@ struct reg_cache *armv8_build_reg_cache(struct target *target)
} else
LOG_ERROR("unable to allocate feature list");
- reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type));
- if (reg_list[i].reg_data_type)
- reg_list[i].reg_data_type->type = armv8_regs[i].type;
- else
- LOG_ERROR("unable to allocate reg type list");
+ if (armv8_regs[i].data_type == NULL) {
+ reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type));
+ if (reg_list[i].reg_data_type)
+ reg_list[i].reg_data_type->type = armv8_regs[i].type;
+ else
+ LOG_ERROR("unable to allocate reg type list");
+ } else
+ reg_list[i].reg_data_type = armv8_regs[i].data_type;
+
}
arm->cpsr = reg_list + ARMV8_xPSR;
@@ -1142,7 +1571,7 @@ struct reg_cache *armv8_build_reg_cache(struct target *target)
for (i = 0; i < num_regs32; i++) {
reg_list32[i].name = armv8_regs32[i].name;
reg_list32[i].size = armv8_regs32[i].bits;
- reg_list32[i].value = &arch_info[armv8_regs32[i].id].value[0];
+ reg_list32[i].value = &arch_info[armv8_regs32[i].id].value[armv8_regs32[i].mapping];
reg_list32[i].type = &armv8_reg32_type;
reg_list32[i].arch_info = &arch_info[armv8_regs32[i].id];
reg_list32[i].group = armv8_regs32[i].group;
@@ -1180,13 +1609,9 @@ struct reg *armv8_reg_current(struct arm *arm, unsigned regnum)
}
const struct command_registration armv8_command_handlers[] = {
- {
- .chain = dap_command_handlers,
- },
COMMAND_REGISTRATION_DONE
};
-
int armv8_get_gdb_reg_list(struct target *target,
struct reg **reg_list[], int *reg_list_size,
enum target_register_class reg_class)
@@ -1200,7 +1625,7 @@ int armv8_get_gdb_reg_list(struct target *target,
switch (reg_class) {
case REG_CLASS_GENERAL:
- *reg_list_size = ARMV8_ELR_EL1;
+ *reg_list_size = ARMV8_V0;
*reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
for (i = 0; i < *reg_list_size; i++)
@@ -1227,6 +1652,13 @@ int armv8_get_gdb_reg_list(struct target *target,
switch (reg_class) {
case REG_CLASS_GENERAL:
+ *reg_list_size = ARMV8_R14 + 3;
+ *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
+
+ for (i = 0; i < *reg_list_size; i++)
+ (*reg_list)[i] = cache32->reg_list + i;
+
+ return ERROR_OK;
case REG_CLASS_ALL:
*reg_list_size = cache32->num_regs;
*reg_list = malloc(sizeof(struct reg *) * (*reg_list_size));
diff --git a/src/target/armv8.h b/src/target/armv8.h
index 0f3e66f..6525d26 100644
--- a/src/target/armv8.h
+++ b/src/target/armv8.h
@@ -63,17 +63,52 @@ enum {
ARMV8_PC = 32,
ARMV8_xPSR = 33,
- ARMV8_ELR_EL1 = 34,
- ARMV8_ESR_EL1 = 35,
- ARMV8_SPSR_EL1 = 36,
-
- ARMV8_ELR_EL2 = 37,
- ARMV8_ESR_EL2 = 38,
- ARMV8_SPSR_EL2 = 39,
-
- ARMV8_ELR_EL3 = 40,
- ARMV8_ESR_EL3 = 41,
- ARMV8_SPSR_EL3 = 42,
+ ARMV8_V0 = 34,
+ ARMV8_V1,
+ ARMV8_V2,
+ ARMV8_V3,
+ ARMV8_V4,
+ ARMV8_V5,
+ ARMV8_V6,
+ ARMV8_V7,
+ ARMV8_V8,
+ ARMV8_V9,
+ ARMV8_V10,
+ ARMV8_V11,
+ ARMV8_V12,
+ ARMV8_V13,
+ ARMV8_V14,
+ ARMV8_V15,
+ ARMV8_V16,
+ ARMV8_V17,
+ ARMV8_V18,
+ ARMV8_V19,
+ ARMV8_V20,
+ ARMV8_V21,
+ ARMV8_V22,
+ ARMV8_V23,
+ ARMV8_V24,
+ ARMV8_V25,
+ ARMV8_V26,
+ ARMV8_V27,
+ ARMV8_V28,
+ ARMV8_V29,
+ ARMV8_V30,
+ ARMV8_V31,
+ ARMV8_FPSR,
+ ARMV8_FPCR,
+
+ ARMV8_ELR_EL1 = 68,
+ ARMV8_ESR_EL1 = 69,
+ ARMV8_SPSR_EL1 = 70,
+
+ ARMV8_ELR_EL2 = 71,
+ ARMV8_ESR_EL2 = 72,
+ ARMV8_SPSR_EL2 = 73,
+
+ ARMV8_ELR_EL3 = 74,
+ ARMV8_ESR_EL3 = 75,
+ ARMV8_SPSR_EL3 = 76,
ARMV8_LAST_REG,
};
@@ -179,6 +214,12 @@ struct armv8_common {
int (*read_reg_u64)(struct armv8_common *armv8, int num, uint64_t *value);
int (*write_reg_u64)(struct armv8_common *armv8, int num, uint64_t value);
+ /* SIMD/FPU registers read/write interface */
+ int (*read_reg_u128)(struct armv8_common *armv8, int num,
+ uint64_t *lvalue, uint64_t *hvalue);
+ int (*write_reg_u128)(struct armv8_common *armv8, int num,
+ uint64_t lvalue, uint64_t hvalue);
+
int (*examine_debug_reason)(struct target *target);
int (*post_debug_entry)(struct target *target);
diff --git a/src/target/armv8_cache.c b/src/target/armv8_cache.c
index 7f610c9..40965eb 100644
--- a/src/target/armv8_cache.c
+++ b/src/target/armv8_cache.c
@@ -310,6 +310,7 @@ int armv8_identify_cache(struct armv8_common *armv8)
{
/* read cache descriptor */
int retval = ERROR_FAIL;
+ struct arm *arm = &armv8->arm;
struct arm_dpm *dpm = armv8->arm.dpm;
uint32_t csselr, clidr, ctr;
uint32_t cache_reg;
@@ -320,6 +321,13 @@ int armv8_identify_cache(struct armv8_common *armv8)
if (retval != ERROR_OK)
goto done;
+ /* check if we're in an unprivileged mode */
+ if (armv8_curel_from_core_mode(arm->core_mode) < SYSTEM_CUREL_EL1) {
+ retval = armv8_dpm_modeswitch(dpm, ARMV8_64_EL1H);
+ if (retval != ERROR_OK)
+ return retval;
+ }
+
/* retrieve CTR */
retval = dpm->instr_read_data_r0(dpm,
armv8_opcode(armv8, READ_REG_CTR), &ctr);
@@ -417,6 +425,7 @@ int armv8_identify_cache(struct armv8_common *armv8)
}
done:
+ armv8_dpm_modeswitch(dpm, ARM_MODE_ANY);
dpm->finish(dpm);
return retval;
diff --git a/src/target/armv8_dpm.c b/src/target/armv8_dpm.c
index c79b1a0..3c941fa 100644
--- a/src/target/armv8_dpm.c
+++ b/src/target/armv8_dpm.c
@@ -258,7 +258,7 @@ static int dpmv8_exec_opcode(struct arm_dpm *dpm,
if (dscr & DSCR_ERR) {
LOG_ERROR("Opcode 0x%08"PRIx32", DSCR.ERR=1, DSCR.EL=%i", opcode, dpm->last_el);
- armv8_dpm_handle_exception(dpm);
+ armv8_dpm_handle_exception(dpm, true);
retval = ERROR_FAIL;
}
@@ -600,7 +600,7 @@ int armv8_dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode)
armv8_opcode(armv8, ARMV8_OPC_DCPS) | target_el);
/* DCPS clobbers registers just like an exception taken */
- armv8_dpm_handle_exception(dpm);
+ armv8_dpm_handle_exception(dpm, false);
} else {
core_state = armv8_dpm_get_core_state(dpm);
if (core_state != ARM_STATE_AARCH64) {
@@ -650,21 +650,37 @@ int armv8_dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode)
static int dpmv8_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum)
{
struct armv8_common *armv8 = dpm->arm->arch_info;
- uint64_t value_64;
- int retval;
+ int retval = ERROR_FAIL;
+
+ if (r->size <= 64) {
+ uint64_t value_64;
+ retval = armv8->read_reg_u64(armv8, regnum, &value_64);
+
+ if (retval == ERROR_OK) {
+ r->valid = true;
+ r->dirty = false;
+ buf_set_u64(r->value, 0, r->size, value_64);
+ if (r->size == 64)
+ LOG_DEBUG("READ: %s, %16.8llx", r->name, (unsigned long long) value_64);
+ else
+ LOG_DEBUG("READ: %s, %8.8x", r->name, (unsigned int) value_64);
+ }
+ } else if (r->size <= 128) {
+ uint64_t lvalue = 0, hvalue = 0;
+ retval = armv8->read_reg_u128(armv8, regnum, &lvalue, &hvalue);
+
+ if (retval == ERROR_OK) {
+ r->valid = true;
+ r->dirty = false;
- retval = armv8->read_reg_u64(armv8, regnum, &value_64);
+ buf_set_u64(r->value, 0, 64, lvalue);
+ buf_set_u64(r->value + 8, 0, r->size - 64, hvalue);
- if (retval == ERROR_OK) {
- r->valid = true;
- r->dirty = false;
- buf_set_u64(r->value, 0, r->size, value_64);
- if (r->size == 64)
- LOG_DEBUG("READ: %s, %16.8llx", r->name, (unsigned long long) value_64);
- else
- LOG_DEBUG("READ: %s, %8.8x", r->name, (unsigned int) value_64);
+ LOG_DEBUG("READ: %s, lvalue=%16.8llx", r->name, (unsigned long long) lvalue);
+ LOG_DEBUG("READ: %s, hvalue=%16.8llx", r->name, (unsigned long long) hvalue);
+ }
}
- return ERROR_OK;
+ return retval;
}
/*
@@ -674,20 +690,36 @@ static int dpmv8_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum)
{
struct armv8_common *armv8 = dpm->arm->arch_info;
int retval = ERROR_FAIL;
- uint64_t value_64;
- value_64 = buf_get_u64(r->value, 0, r->size);
+ if (r->size <= 64) {
+ uint64_t value_64;
+
+ value_64 = buf_get_u64(r->value, 0, r->size);
+ retval = armv8->write_reg_u64(armv8, regnum, value_64);
- retval = armv8->write_reg_u64(armv8, regnum, value_64);
- if (retval == ERROR_OK) {
- r->dirty = false;
- if (r->size == 64)
- LOG_DEBUG("WRITE: %s, %16.8llx", r->name, (unsigned long long)value_64);
- else
- LOG_DEBUG("WRITE: %s, %8.8x", r->name, (unsigned int)value_64);
+ if (retval == ERROR_OK) {
+ r->dirty = false;
+ if (r->size == 64)
+ LOG_DEBUG("WRITE: %s, %16.8llx", r->name, (unsigned long long)value_64);
+ else
+ LOG_DEBUG("WRITE: %s, %8.8x", r->name, (unsigned int)value_64);
+ }
+ } else if (r->size <= 128) {
+ uint64_t lvalue, hvalue;
+
+ lvalue = buf_get_u64(r->value, 0, 64);
+ hvalue = buf_get_u64(r->value + 8, 0, r->size - 64);
+ retval = armv8->write_reg_u128(armv8, regnum, lvalue, hvalue);
+
+ if (retval == ERROR_OK) {
+ r->dirty = false;
+
+ LOG_DEBUG("WRITE: %s, lvalue=%16.8llx", r->name, (unsigned long long) lvalue);
+ LOG_DEBUG("WRITE: %s, hvalue=%16.8llx", r->name, (unsigned long long) hvalue);
+ }
}
- return ERROR_OK;
+ return retval;
}
/**
@@ -745,6 +777,10 @@ int armv8_dpm_read_current_registers(struct arm_dpm *dpm)
if (r->valid)
continue;
+ /* Skip reading FP-SIMD registers */
+ if (r->number >= ARMV8_V0 && r->number <= ARMV8_FPCR)
+ continue;
+
/*
* Only read registers that are available from the
* current EL (or core mode).
@@ -1262,7 +1298,7 @@ void armv8_dpm_report_wfar(struct arm_dpm *dpm, uint64_t addr)
* This function must not perform any actions that trigger another exception
* or a recursion will happen.
*/
-void armv8_dpm_handle_exception(struct arm_dpm *dpm)
+void armv8_dpm_handle_exception(struct arm_dpm *dpm, bool do_restore)
{
struct armv8_common *armv8 = dpm->arm->arch_info;
struct reg_cache *cache = dpm->arm->core_cache;
@@ -1308,7 +1344,8 @@ void armv8_dpm_handle_exception(struct arm_dpm *dpm)
armv8_select_opcodes(armv8, core_state == ARM_STATE_AARCH64);
armv8_select_reg_access(armv8, core_state == ARM_STATE_AARCH64);
- armv8_dpm_modeswitch(dpm, ARM_MODE_ANY);
+ if (do_restore)
+ armv8_dpm_modeswitch(dpm, ARM_MODE_ANY);
}
/*----------------------------------------------------------------------*/
diff --git a/src/target/armv8_dpm.h b/src/target/armv8_dpm.h
index c039359..f404403 100644
--- a/src/target/armv8_dpm.h
+++ b/src/target/armv8_dpm.h
@@ -116,7 +116,7 @@ void armv8_dpm_report_wfar(struct arm_dpm *, uint64_t wfar);
#define PRCR_COREPURQ (1 << 3)
void armv8_dpm_report_dscr(struct arm_dpm *dpm, uint32_t dcsr);
-void armv8_dpm_handle_exception(struct arm_dpm *dpm);
+void armv8_dpm_handle_exception(struct arm_dpm *dpm, bool do_restore);
enum arm_state armv8_dpm_get_core_state(struct arm_dpm *dpm);
#endif /* OPENOCD_TARGET_ARM_DPM_H */
diff --git a/src/target/armv8_opcodes.h b/src/target/armv8_opcodes.h
index 987198a..3fda296 100644
--- a/src/target/armv8_opcodes.h
+++ b/src/target/armv8_opcodes.h
@@ -167,6 +167,14 @@
#define ARMV8_STRH_IP(Rd, Rn) (0x78002400 | (Rn << 5) | Rd)
#define ARMV8_STRW_IP(Rd, Rn) (0xb8004400 | (Rn << 5) | Rd)
+#define ARMV8_MOV_GPR_VFP(Rd, Rn, Index) (0x4e083c00 | (Index << 20) | (Rn << 5) | Rd)
+#define ARMV8_MOV_VFP_GPR(Rd, Rn, Index) (0x4e081c00 | (Index << 20) | (Rn << 5) | Rd)
+
+#define ARMV8_MRS_FPCR(Rt) (0xd53b4400 | (Rt))
+#define ARMV8_MRS_FPSR(Rt) (0xd53b4420 | (Rt))
+#define ARMV8_MSR_FPCR(Rt) (0xd51b4400 | (Rt))
+#define ARMV8_MSR_FPSR(Rt) (0xd51b4420 | (Rt))
+
#define ARMV8_SYS(System, Rt) (0xD5080000 | ((System) << 5) | Rt)
enum armv8_opcode {
diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c
index 5d90e34..8985051 100644
--- a/src/target/cortex_a.c
+++ b/src/target/cortex_a.c
@@ -54,7 +54,7 @@
#include "target_type.h"
#include "arm_opcodes.h"
#include "arm_semihosting.h"
-#include "jtag/swd.h"
+#include "transport/transport.h"
#include <helper/time_support.h>
static int cortex_a_poll(struct target *target);
@@ -206,23 +206,27 @@ static int cortex_a_init_debug_access(struct target *target)
/* lock memory-mapped access to debug registers to prevent
* software interference */
- retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
+ retval = mem_ap_write_u32(armv7a->debug_ap,
armv7a->debug_base + CPUDBG_LOCKACCESS, 0);
if (retval != ERROR_OK)
return retval;
/* Disable cacheline fills and force cache write-through in debug state */
- retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
+ retval = mem_ap_write_u32(armv7a->debug_ap,
armv7a->debug_base + CPUDBG_DSCCR, 0);
if (retval != ERROR_OK)
return retval;
/* Disable TLB lookup and refill/eviction in debug state */
- retval = mem_ap_write_atomic_u32(armv7a->debug_ap,
+ retval = mem_ap_write_u32(armv7a->debug_ap,
armv7a->debug_base + CPUDBG_DSMCR, 0);
if (retval != ERROR_OK)
return retval;
+ retval = dap_run(armv7a->debug_ap->dap);
+ if (retval != ERROR_OK)
+ return retval;
+
/* Enabling of instruction execution in debug mode is done in debug_entry code */
/* Resync breakpoint registers */
@@ -1496,10 +1500,22 @@ static int cortex_a_set_breakpoint(struct target *target,
brp_list[brp_i].value);
} else if (breakpoint->type == BKPT_SOFT) {
uint8_t code[4];
+ /* length == 2: Thumb breakpoint */
if (breakpoint->length == 2)
buf_set_u32(code, 0, 32, ARMV5_T_BKPT(0x11));
else
+ /* length == 3: Thumb-2 breakpoint, actual encoding is
+ * a regular Thumb BKPT instruction but we replace a
+ * 32bit Thumb-2 instruction, so fix-up the breakpoint
+ * length
+ */
+ if (breakpoint->length == 3) {
+ buf_set_u32(code, 0, 32, ARMV5_T_BKPT(0x11));
+ breakpoint->length = 4;
+ } else
+ /* length == 4, normal ARM breakpoint */
buf_set_u32(code, 0, 32, ARMV5_BKPT(0x11));
+
retval = target_read_memory(target,
breakpoint->address & 0xFFFFFFFE,
breakpoint->length, 1,
@@ -2931,12 +2947,6 @@ static int cortex_a_examine_first(struct target *target)
int retval = ERROR_OK;
uint32_t didr, cpuid, dbg_osreg;
- retval = dap_dp_init(swjdp);
- if (retval != ERROR_OK) {
- LOG_ERROR("Could not initialize the debug port");
- return retval;
- }
-
/* Search for the APB-AP - it is needed for access to debug registers */
retval = dap_find_ap(swjdp, AP_TYPE_APB_AP, &armv7a->debug_ap);
if (retval != ERROR_OK) {
@@ -3118,22 +3128,13 @@ static int cortex_a_init_target(struct command_context *cmd_ctx,
}
static int cortex_a_init_arch_info(struct target *target,
- struct cortex_a_common *cortex_a, struct jtag_tap *tap)
+ struct cortex_a_common *cortex_a, struct adiv5_dap *dap)
{
struct armv7a_common *armv7a = &cortex_a->armv7a_common;
/* Setup struct cortex_a_common */
cortex_a->common_magic = CORTEX_A_COMMON_MAGIC;
-
- /* tap has no dap initialized */
- if (!tap->dap) {
- tap->dap = dap_init();
-
- /* Leave (only) generic DAP stuff for debugport_init() */
- tap->dap->tap = tap;
- }
-
- armv7a->arm.dap = tap->dap;
+ armv7a->arm.dap = dap;
cortex_a->fast_reg_read = 0;
@@ -3159,19 +3160,34 @@ static int cortex_a_init_arch_info(struct target *target,
static int cortex_a_target_create(struct target *target, Jim_Interp *interp)
{
struct cortex_a_common *cortex_a = calloc(1, sizeof(struct cortex_a_common));
+ cortex_a->common_magic = CORTEX_A_COMMON_MAGIC;
+ struct adiv5_private_config *pc;
+
+ if (target->private_config == NULL)
+ return ERROR_FAIL;
+
+ pc = (struct adiv5_private_config *)target->private_config;
cortex_a->armv7a_common.is_armv7r = false;
- return cortex_a_init_arch_info(target, cortex_a, target->tap);
+ cortex_a->armv7a_common.arm.arm_vfp_version = ARM_VFP_V3;
+
+ return cortex_a_init_arch_info(target, cortex_a, pc->dap);
}
static int cortex_r4_target_create(struct target *target, Jim_Interp *interp)
{
struct cortex_a_common *cortex_a = calloc(1, sizeof(struct cortex_a_common));
+ cortex_a->common_magic = CORTEX_A_COMMON_MAGIC;
+ struct adiv5_private_config *pc;
+
+ pc = (struct adiv5_private_config *)target->private_config;
+ if (adiv5_verify_config(pc) != ERROR_OK)
+ return ERROR_FAIL;
cortex_a->armv7a_common.is_armv7r = true;
- return cortex_a_init_arch_info(target, cortex_a, target->tap);
+ return cortex_a_init_arch_info(target, cortex_a, pc->dap);
}
static void cortex_a_deinit_target(struct target *target)
@@ -3182,6 +3198,7 @@ static void cortex_a_deinit_target(struct target *target)
free(cortex_a->brp_list);
free(dpm->dbp);
free(dpm->dwp);
+ free(target->private_config);
free(cortex_a);
}
@@ -3466,6 +3483,7 @@ struct target_type cortexa_target = {
.commands = cortex_a_command_handlers,
.target_create = cortex_a_target_create,
+ .target_jim_configure = adiv5_jim_configure,
.init_target = cortex_a_init_target,
.examine = cortex_a_examine,
.deinit_target = cortex_a_deinit_target,
@@ -3478,13 +3496,6 @@ struct target_type cortexa_target = {
static const struct command_registration cortex_r4_exec_command_handlers[] = {
{
- .name = "cache_info",
- .handler = cortex_a_handle_cache_info_command,
- .mode = COMMAND_EXEC,
- .help = "display information about target caches",
- .usage = "",
- },
- {
.name = "dbginit",
.handler = cortex_a_handle_dbginit_command,
.mode = COMMAND_EXEC,
@@ -3506,9 +3517,6 @@ static const struct command_registration cortex_r4_command_handlers[] = {
.chain = arm_command_handlers,
},
{
- .chain = armv7a_command_handlers,
- },
- {
.name = "cortex_r4",
.mode = COMMAND_ANY,
.help = "Cortex-R4 command group",
@@ -3551,6 +3559,7 @@ struct target_type cortexr4_target = {
.commands = cortex_r4_command_handlers,
.target_create = cortex_r4_target_create,
+ .target_jim_configure = adiv5_jim_configure,
.init_target = cortex_a_init_target,
.examine = cortex_a_examine,
.deinit_target = cortex_a_deinit_target,
diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c
index 79af632..a356350 100644
--- a/src/target/cortex_m.c
+++ b/src/target/cortex_m.c
@@ -1854,6 +1854,18 @@ static struct dwt_reg dwt_comp[] = {
DWT_COMPARATOR(1),
DWT_COMPARATOR(2),
DWT_COMPARATOR(3),
+ DWT_COMPARATOR(4),
+ DWT_COMPARATOR(5),
+ DWT_COMPARATOR(6),
+ DWT_COMPARATOR(7),
+ DWT_COMPARATOR(8),
+ DWT_COMPARATOR(9),
+ DWT_COMPARATOR(10),
+ DWT_COMPARATOR(11),
+ DWT_COMPARATOR(12),
+ DWT_COMPARATOR(13),
+ DWT_COMPARATOR(14),
+ DWT_COMPARATOR(15),
#undef DWT_COMPARATOR
};
@@ -1887,6 +1899,7 @@ void cortex_m_dwt_setup(struct cortex_m_common *cm, struct target *target)
int reg, i;
target_read_u32(target, DWT_CTRL, &dwtcr);
+ LOG_DEBUG("DWT_CTRL: 0x%" PRIx32, dwtcr);
if (!dwtcr) {
LOG_DEBUG("no DWT");
return;
@@ -1992,12 +2005,6 @@ int cortex_m_examine(struct target *target)
/* stlink shares the examine handler but does not support
* all its calls */
if (!armv7m->stlink) {
- retval = dap_dp_init(swjdp);
- if (retval != ERROR_OK) {
- LOG_ERROR("Could not initialize the debug port");
- return retval;
- }
-
if (cortex_m->apsel < 0) {
/* Search for the MEM-AP */
retval = dap_find_ap(swjdp, AP_TYPE_AHB_AP, &armv7m->debug_ap);
@@ -2228,25 +2235,17 @@ static int cortex_m_handle_target_request(void *priv)
}
static int cortex_m_init_arch_info(struct target *target,
- struct cortex_m_common *cortex_m, struct jtag_tap *tap)
+ struct cortex_m_common *cortex_m, struct adiv5_dap *dap)
{
struct armv7m_common *armv7m = &cortex_m->armv7m;
armv7m_init_arch_info(target, armv7m);
- /* tap has no dap initialized */
- if (!tap->dap) {
- tap->dap = dap_init();
-
- /* Leave (only) generic DAP stuff for debugport_init() */
- tap->dap->tap = tap;
- }
-
/* default reset mode is to use srst if fitted
* if not it will use CORTEX_M3_RESET_VECTRESET */
cortex_m->soft_reset_config = CORTEX_M_RESET_VECTRESET;
- armv7m->arm.dap = tap->dap;
+ armv7m->arm.dap = dap;
/* register arch-specific functions */
armv7m->examine_debug_reason = cortex_m_examine_debug_reason;
@@ -2266,16 +2265,16 @@ static int cortex_m_init_arch_info(struct target *target,
static int cortex_m_target_create(struct target *target, Jim_Interp *interp)
{
struct cortex_m_common *cortex_m = calloc(1, sizeof(struct cortex_m_common));
-
cortex_m->common_magic = CORTEX_M_COMMON_MAGIC;
- cortex_m_init_arch_info(target, cortex_m, target->tap);
-
- if (target->private_config != NULL) {
- struct adiv5_private_config *pc =
- (struct adiv5_private_config *)target->private_config;
- cortex_m->apsel = pc->ap_num;
- } else
- cortex_m->apsel = -1;
+ struct adiv5_private_config *pc;
+
+ pc = (struct adiv5_private_config *)target->private_config;
+ if (adiv5_verify_config(pc) != ERROR_OK)
+ return ERROR_FAIL;
+
+ cortex_m->apsel = pc->ap_num;
+
+ cortex_m_init_arch_info(target, cortex_m, pc->dap);
return ERROR_OK;
}
diff --git a/src/target/hla_target.c b/src/target/hla_target.c
index a3e6835..9ebf241 100644
--- a/src/target/hla_target.c
+++ b/src/target/hla_target.c
@@ -271,7 +271,10 @@ static int hl_target_request_data(struct target *target,
uint32_t i;
for (i = 0; i < (size * 4); i++) {
- hl_dcc_read(hl_if, &data, &ctrl);
+ int err = hl_dcc_read(hl_if, &data, &ctrl);
+ if (err != ERROR_OK)
+ return err;
+
buffer[i] = data;
}
@@ -281,6 +284,8 @@ static int hl_target_request_data(struct target *target,
static int hl_handle_target_request(void *priv)
{
struct target *target = priv;
+ int err;
+
if (!target_was_examined(target))
return ERROR_OK;
struct hl_interface_s *hl_if = target_to_adapter(target);
@@ -292,7 +297,9 @@ static int hl_handle_target_request(void *priv)
uint8_t data;
uint8_t ctrl;
- hl_dcc_read(hl_if, &data, &ctrl);
+ err = hl_dcc_read(hl_if, &data, &ctrl);
+ if (err != ERROR_OK)
+ return err;
/* check if we have data */
if (ctrl & (1 << 0)) {
@@ -300,11 +307,20 @@ static int hl_handle_target_request(void *priv)
/* we assume target is quick enough */
request = data;
- hl_dcc_read(hl_if, &data, &ctrl);
+ err = hl_dcc_read(hl_if, &data, &ctrl);
+ if (err != ERROR_OK)
+ return err;
+
request |= (data << 8);
- hl_dcc_read(hl_if, &data, &ctrl);
+ err = hl_dcc_read(hl_if, &data, &ctrl);
+ if (err != ERROR_OK)
+ return err;
+
request |= (data << 16);
- hl_dcc_read(hl_if, &data, &ctrl);
+ err = hl_dcc_read(hl_if, &data, &ctrl);
+ if (err != ERROR_OK)
+ return err;
+
request |= (data << 24);
target_request(target, request);
}
@@ -349,12 +365,16 @@ static int adapter_target_create(struct target *target,
Jim_Interp *interp)
{
LOG_DEBUG("%s", __func__);
-
+ struct adiv5_private_config *pc = target->private_config;
struct cortex_m_common *cortex_m = calloc(1, sizeof(struct cortex_m_common));
-
if (!cortex_m)
return ERROR_COMMAND_SYNTAX_ERROR;
+ if (pc != NULL && pc->ap_num > 0) {
+ LOG_ERROR("hla_target: invalid parameter -ap-num (> 0)");
+ return ERROR_FAIL;
+ }
+
adapter_init_arch_info(target, cortex_m, target->tap);
return ERROR_OK;
@@ -785,6 +805,7 @@ struct target_type hla_target = {
.init_target = adapter_init_target,
.deinit_target = cortex_m_deinit_target,
.target_create = adapter_target_create,
+ .target_jim_configure = adiv5_jim_configure,
.examine = cortex_m_examine,
.commands = adapter_command_handlers,
diff --git a/src/target/image.c b/src/target/image.c
index f97d904..9f56bea 100644
--- a/src/target/image.c
+++ b/src/target/image.c
@@ -121,8 +121,9 @@ static int image_ihex_buffer_complete_inner(struct image *image,
{
struct image_ihex *ihex = image->type_private;
struct fileio *fileio = ihex->fileio;
- uint32_t full_address = 0x0;
+ uint32_t full_address;
uint32_t cooked_bytes;
+ bool end_rec = false;
int i;
/* we can't determine the number of sections that we'll have to create ahead of time,
@@ -137,175 +138,190 @@ static int image_ihex_buffer_complete_inner(struct image *image,
ihex->buffer = malloc(filesize >> 1);
cooked_bytes = 0x0;
image->num_sections = 0;
- section[image->num_sections].private = &ihex->buffer[cooked_bytes];
- section[image->num_sections].base_address = 0x0;
- section[image->num_sections].size = 0x0;
- section[image->num_sections].flags = 0;
-
- while (fileio_fgets(fileio, 1023, lpszLine) == ERROR_OK) {
- uint32_t count;
- uint32_t address;
- uint32_t record_type;
- uint32_t checksum;
- uint8_t cal_checksum = 0;
- size_t bytes_read = 0;
-
- if (lpszLine[0] == '#')
- continue;
-
- if (sscanf(&lpszLine[bytes_read], ":%2" SCNx32 "%4" SCNx32 "%2" SCNx32, &count,
- &address, &record_type) != 3)
- return ERROR_IMAGE_FORMAT_ERROR;
- bytes_read += 9;
-
- cal_checksum += (uint8_t)count;
- cal_checksum += (uint8_t)(address >> 8);
- cal_checksum += (uint8_t)address;
- cal_checksum += (uint8_t)record_type;
-
- if (record_type == 0) { /* Data Record */
- if ((full_address & 0xffff) != address) {
- /* we encountered a nonconsecutive location, create a new section,
- * unless the current section has zero size, in which case this specifies
- * the current section's base address
- */
- if (section[image->num_sections].size != 0) {
- image->num_sections++;
- if (image->num_sections >= IMAGE_MAX_SECTIONS) {
- /* too many sections */
- LOG_ERROR("Too many sections found in IHEX file");
- return ERROR_IMAGE_FORMAT_ERROR;
+
+ while (!fileio_feof(fileio)) {
+ full_address = 0x0;
+ section[image->num_sections].private = &ihex->buffer[cooked_bytes];
+ section[image->num_sections].base_address = 0x0;
+ section[image->num_sections].size = 0x0;
+ section[image->num_sections].flags = 0;
+
+ while (fileio_fgets(fileio, 1023, lpszLine) == ERROR_OK) {
+ uint32_t count;
+ uint32_t address;
+ uint32_t record_type;
+ uint32_t checksum;
+ uint8_t cal_checksum = 0;
+ size_t bytes_read = 0;
+
+ /* skip comments and blank lines */
+ if ((lpszLine[0] == '#') || (strlen(lpszLine + strspn(lpszLine, "\n\t\r ")) == 0))
+ continue;
+
+ if (sscanf(&lpszLine[bytes_read], ":%2" SCNx32 "%4" SCNx32 "%2" SCNx32, &count,
+ &address, &record_type) != 3)
+ return ERROR_IMAGE_FORMAT_ERROR;
+ bytes_read += 9;
+
+ cal_checksum += (uint8_t)count;
+ cal_checksum += (uint8_t)(address >> 8);
+ cal_checksum += (uint8_t)address;
+ cal_checksum += (uint8_t)record_type;
+
+ if (record_type == 0) { /* Data Record */
+ if ((full_address & 0xffff) != address) {
+ /* we encountered a nonconsecutive location, create a new section,
+ * unless the current section has zero size, in which case this specifies
+ * the current section's base address
+ */
+ if (section[image->num_sections].size != 0) {
+ image->num_sections++;
+ if (image->num_sections >= IMAGE_MAX_SECTIONS) {
+ /* too many sections */
+ LOG_ERROR("Too many sections found in IHEX file");
+ return ERROR_IMAGE_FORMAT_ERROR;
+ }
+ section[image->num_sections].size = 0x0;
+ section[image->num_sections].flags = 0;
+ section[image->num_sections].private =
+ &ihex->buffer[cooked_bytes];
}
- section[image->num_sections].size = 0x0;
- section[image->num_sections].flags = 0;
- section[image->num_sections].private =
- &ihex->buffer[cooked_bytes];
+ section[image->num_sections].base_address =
+ (full_address & 0xffff0000) | address;
+ full_address = (full_address & 0xffff0000) | address;
}
- section[image->num_sections].base_address =
- (full_address & 0xffff0000) | address;
- full_address = (full_address & 0xffff0000) | address;
- }
-
- while (count-- > 0) {
- unsigned value;
- sscanf(&lpszLine[bytes_read], "%2x", &value);
- ihex->buffer[cooked_bytes] = (uint8_t)value;
- cal_checksum += (uint8_t)ihex->buffer[cooked_bytes];
- bytes_read += 2;
- cooked_bytes += 1;
- section[image->num_sections].size += 1;
- full_address++;
- }
- } else if (record_type == 1) { /* End of File Record */
- /* finish the current section */
- image->num_sections++;
-
- /* copy section information */
- image->sections = malloc(sizeof(struct imagesection) * image->num_sections);
- for (i = 0; i < image->num_sections; i++) {
- image->sections[i].private = section[i].private;
- image->sections[i].base_address = section[i].base_address;
- image->sections[i].size = section[i].size;
- image->sections[i].flags = section[i].flags;
- }
- return ERROR_OK;
- } else if (record_type == 2) { /* Linear Address Record */
- uint16_t upper_address;
-
- sscanf(&lpszLine[bytes_read], "%4hx", &upper_address);
- cal_checksum += (uint8_t)(upper_address >> 8);
- cal_checksum += (uint8_t)upper_address;
- bytes_read += 4;
+ while (count-- > 0) {
+ unsigned value;
+ sscanf(&lpszLine[bytes_read], "%2x", &value);
+ ihex->buffer[cooked_bytes] = (uint8_t)value;
+ cal_checksum += (uint8_t)ihex->buffer[cooked_bytes];
+ bytes_read += 2;
+ cooked_bytes += 1;
+ section[image->num_sections].size += 1;
+ full_address++;
+ }
+ } else if (record_type == 1) { /* End of File Record */
+ /* finish the current section */
+ image->num_sections++;
+
+ /* copy section information */
+ image->sections = malloc(sizeof(struct imagesection) * image->num_sections);
+ for (i = 0; i < image->num_sections; i++) {
+ image->sections[i].private = section[i].private;
+ image->sections[i].base_address = section[i].base_address;
+ image->sections[i].size = section[i].size;
+ image->sections[i].flags = section[i].flags;
+ }
- if ((full_address >> 4) != upper_address) {
- /* we encountered a nonconsecutive location, create a new section,
- * unless the current section has zero size, in which case this specifies
- * the current section's base address
- */
- if (section[image->num_sections].size != 0) {
- image->num_sections++;
- if (image->num_sections >= IMAGE_MAX_SECTIONS) {
- /* too many sections */
- LOG_ERROR("Too many sections found in IHEX file");
- return ERROR_IMAGE_FORMAT_ERROR;
+ end_rec = true;
+ break;
+ } else if (record_type == 2) { /* Linear Address Record */
+ uint16_t upper_address;
+
+ sscanf(&lpszLine[bytes_read], "%4hx", &upper_address);
+ cal_checksum += (uint8_t)(upper_address >> 8);
+ cal_checksum += (uint8_t)upper_address;
+ bytes_read += 4;
+
+ if ((full_address >> 4) != upper_address) {
+ /* we encountered a nonconsecutive location, create a new section,
+ * unless the current section has zero size, in which case this specifies
+ * the current section's base address
+ */
+ if (section[image->num_sections].size != 0) {
+ image->num_sections++;
+ if (image->num_sections >= IMAGE_MAX_SECTIONS) {
+ /* too many sections */
+ LOG_ERROR("Too many sections found in IHEX file");
+ return ERROR_IMAGE_FORMAT_ERROR;
+ }
+ section[image->num_sections].size = 0x0;
+ section[image->num_sections].flags = 0;
+ section[image->num_sections].private =
+ &ihex->buffer[cooked_bytes];
}
- section[image->num_sections].size = 0x0;
- section[image->num_sections].flags = 0;
- section[image->num_sections].private =
- &ihex->buffer[cooked_bytes];
+ section[image->num_sections].base_address =
+ (full_address & 0xffff) | (upper_address << 4);
+ full_address = (full_address & 0xffff) | (upper_address << 4);
}
- section[image->num_sections].base_address =
- (full_address & 0xffff) | (upper_address << 4);
- full_address = (full_address & 0xffff) | (upper_address << 4);
- }
- } else if (record_type == 3) { /* Start Segment Address Record */
- uint32_t dummy;
-
- /* "Start Segment Address Record" will not be supported
- * but we must consume it, and do not create an error. */
- while (count-- > 0) {
- sscanf(&lpszLine[bytes_read], "%2" SCNx32, &dummy);
- cal_checksum += (uint8_t)dummy;
- bytes_read += 2;
- }
- } else if (record_type == 4) { /* Extended Linear Address Record */
- uint16_t upper_address;
-
- sscanf(&lpszLine[bytes_read], "%4hx", &upper_address);
- cal_checksum += (uint8_t)(upper_address >> 8);
- cal_checksum += (uint8_t)upper_address;
- bytes_read += 4;
-
- if ((full_address >> 16) != upper_address) {
- /* we encountered a nonconsecutive location, create a new section,
- * unless the current section has zero size, in which case this specifies
- * the current section's base address
- */
- if (section[image->num_sections].size != 0) {
- image->num_sections++;
- if (image->num_sections >= IMAGE_MAX_SECTIONS) {
- /* too many sections */
- LOG_ERROR("Too many sections found in IHEX file");
- return ERROR_IMAGE_FORMAT_ERROR;
+ } else if (record_type == 3) { /* Start Segment Address Record */
+ uint32_t dummy;
+
+ /* "Start Segment Address Record" will not be supported
+ * but we must consume it, and do not create an error. */
+ while (count-- > 0) {
+ sscanf(&lpszLine[bytes_read], "%2" SCNx32, &dummy);
+ cal_checksum += (uint8_t)dummy;
+ bytes_read += 2;
+ }
+ } else if (record_type == 4) { /* Extended Linear Address Record */
+ uint16_t upper_address;
+
+ sscanf(&lpszLine[bytes_read], "%4hx", &upper_address);
+ cal_checksum += (uint8_t)(upper_address >> 8);
+ cal_checksum += (uint8_t)upper_address;
+ bytes_read += 4;
+
+ if ((full_address >> 16) != upper_address) {
+ /* we encountered a nonconsecutive location, create a new section,
+ * unless the current section has zero size, in which case this specifies
+ * the current section's base address
+ */
+ if (section[image->num_sections].size != 0) {
+ image->num_sections++;
+ if (image->num_sections >= IMAGE_MAX_SECTIONS) {
+ /* too many sections */
+ LOG_ERROR("Too many sections found in IHEX file");
+ return ERROR_IMAGE_FORMAT_ERROR;
+ }
+ section[image->num_sections].size = 0x0;
+ section[image->num_sections].flags = 0;
+ section[image->num_sections].private =
+ &ihex->buffer[cooked_bytes];
}
- section[image->num_sections].size = 0x0;
- section[image->num_sections].flags = 0;
- section[image->num_sections].private =
- &ihex->buffer[cooked_bytes];
+ section[image->num_sections].base_address =
+ (full_address & 0xffff) | (upper_address << 16);
+ full_address = (full_address & 0xffff) | (upper_address << 16);
}
- section[image->num_sections].base_address =
- (full_address & 0xffff) | (upper_address << 16);
- full_address = (full_address & 0xffff) | (upper_address << 16);
+ } else if (record_type == 5) { /* Start Linear Address Record */
+ uint32_t start_address;
+
+ sscanf(&lpszLine[bytes_read], "%8" SCNx32, &start_address);
+ cal_checksum += (uint8_t)(start_address >> 24);
+ cal_checksum += (uint8_t)(start_address >> 16);
+ cal_checksum += (uint8_t)(start_address >> 8);
+ cal_checksum += (uint8_t)start_address;
+ bytes_read += 8;
+
+ image->start_address_set = 1;
+ image->start_address = be_to_h_u32((uint8_t *)&start_address);
+ } else {
+ LOG_ERROR("unhandled IHEX record type: %i", (int)record_type);
+ return ERROR_IMAGE_FORMAT_ERROR;
}
- } else if (record_type == 5) { /* Start Linear Address Record */
- uint32_t start_address;
-
- sscanf(&lpszLine[bytes_read], "%8" SCNx32, &start_address);
- cal_checksum += (uint8_t)(start_address >> 24);
- cal_checksum += (uint8_t)(start_address >> 16);
- cal_checksum += (uint8_t)(start_address >> 8);
- cal_checksum += (uint8_t)start_address;
- bytes_read += 8;
-
- image->start_address_set = 1;
- image->start_address = be_to_h_u32((uint8_t *)&start_address);
- } else {
- LOG_ERROR("unhandled IHEX record type: %i", (int)record_type);
- return ERROR_IMAGE_FORMAT_ERROR;
- }
- sscanf(&lpszLine[bytes_read], "%2" SCNx32, &checksum);
+ sscanf(&lpszLine[bytes_read], "%2" SCNx32, &checksum);
- if ((uint8_t)checksum != (uint8_t)(~cal_checksum + 1)) {
- /* checksum failed */
- LOG_ERROR("incorrect record checksum found in IHEX file");
- return ERROR_IMAGE_CHECKSUM;
+ if ((uint8_t)checksum != (uint8_t)(~cal_checksum + 1)) {
+ /* checksum failed */
+ LOG_ERROR("incorrect record checksum found in IHEX file");
+ return ERROR_IMAGE_CHECKSUM;
+ }
+
+ if (end_rec) {
+ end_rec = false;
+ LOG_WARNING("continuing after end-of-file record: %.40s", lpszLine);
+ }
}
}
- LOG_ERROR("premature end of IHEX file, no end-of-file record found");
- return ERROR_IMAGE_FORMAT_ERROR;
+ if (end_rec)
+ return ERROR_OK;
+ else {
+ LOG_ERROR("premature end of IHEX file, no matching end-of-file record found");
+ return ERROR_IMAGE_FORMAT_ERROR;
+ }
}
/**
@@ -510,8 +526,9 @@ static int image_mot_buffer_complete_inner(struct image *image,
{
struct image_mot *mot = image->type_private;
struct fileio *fileio = mot->fileio;
- uint32_t full_address = 0x0;
+ uint32_t full_address;
uint32_t cooked_bytes;
+ bool end_rec = false;
int i;
/* we can't determine the number of sections that we'll have to create ahead of time,
@@ -526,140 +543,158 @@ static int image_mot_buffer_complete_inner(struct image *image,
mot->buffer = malloc(filesize >> 1);
cooked_bytes = 0x0;
image->num_sections = 0;
- section[image->num_sections].private = &mot->buffer[cooked_bytes];
- section[image->num_sections].base_address = 0x0;
- section[image->num_sections].size = 0x0;
- section[image->num_sections].flags = 0;
-
- while (fileio_fgets(fileio, 1023, lpszLine) == ERROR_OK) {
- uint32_t count;
- uint32_t address;
- uint32_t record_type;
- uint32_t checksum;
- uint8_t cal_checksum = 0;
- uint32_t bytes_read = 0;
-
- /* get record type and record length */
- if (sscanf(&lpszLine[bytes_read], "S%1" SCNx32 "%2" SCNx32, &record_type,
- &count) != 2)
- return ERROR_IMAGE_FORMAT_ERROR;
-
- bytes_read += 4;
- cal_checksum += (uint8_t)count;
-
- /* skip checksum byte */
- count -= 1;
-
- if (record_type == 0) {
- /* S0 - starting record (optional) */
- int iValue;
-
- while (count-- > 0) {
- sscanf(&lpszLine[bytes_read], "%2x", &iValue);
- cal_checksum += (uint8_t)iValue;
- bytes_read += 2;
- }
- } else if (record_type >= 1 && record_type <= 3) {
- switch (record_type) {
- case 1:
- /* S1 - 16 bit address data record */
- sscanf(&lpszLine[bytes_read], "%4" SCNx32, &address);
- cal_checksum += (uint8_t)(address >> 8);
- cal_checksum += (uint8_t)address;
- bytes_read += 4;
- count -= 2;
- break;
-
- case 2:
- /* S2 - 24 bit address data record */
- sscanf(&lpszLine[bytes_read], "%6" SCNx32, &address);
- cal_checksum += (uint8_t)(address >> 16);
- cal_checksum += (uint8_t)(address >> 8);
- cal_checksum += (uint8_t)address;
- bytes_read += 6;
- count -= 3;
- break;
-
- case 3:
- /* S3 - 32 bit address data record */
- sscanf(&lpszLine[bytes_read], "%8" SCNx32, &address);
- cal_checksum += (uint8_t)(address >> 24);
- cal_checksum += (uint8_t)(address >> 16);
- cal_checksum += (uint8_t)(address >> 8);
- cal_checksum += (uint8_t)address;
- bytes_read += 8;
- count -= 4;
- break;
- }
+ while (!fileio_feof(fileio)) {
+ full_address = 0x0;
+ section[image->num_sections].private = &mot->buffer[cooked_bytes];
+ section[image->num_sections].base_address = 0x0;
+ section[image->num_sections].size = 0x0;
+ section[image->num_sections].flags = 0;
+
+ while (fileio_fgets(fileio, 1023, lpszLine) == ERROR_OK) {
+ uint32_t count;
+ uint32_t address;
+ uint32_t record_type;
+ uint32_t checksum;
+ uint8_t cal_checksum = 0;
+ uint32_t bytes_read = 0;
+
+ /* skip comments and blank lines */
+ if ((lpszLine[0] == '#') || (strlen(lpszLine + strspn(lpszLine, "\n\t\r ")) == 0))
+ continue;
+
+ /* get record type and record length */
+ if (sscanf(&lpszLine[bytes_read], "S%1" SCNx32 "%2" SCNx32, &record_type,
+ &count) != 2)
+ return ERROR_IMAGE_FORMAT_ERROR;
+
+ bytes_read += 4;
+ cal_checksum += (uint8_t)count;
- if (full_address != address) {
- /* we encountered a nonconsecutive location, create a new section,
- * unless the current section has zero size, in which case this specifies
- * the current section's base address
- */
- if (section[image->num_sections].size != 0) {
- image->num_sections++;
- section[image->num_sections].size = 0x0;
- section[image->num_sections].flags = 0;
- section[image->num_sections].private =
- &mot->buffer[cooked_bytes];
+ /* skip checksum byte */
+ count -= 1;
+
+ if (record_type == 0) {
+ /* S0 - starting record (optional) */
+ int iValue;
+
+ while (count-- > 0) {
+ sscanf(&lpszLine[bytes_read], "%2x", &iValue);
+ cal_checksum += (uint8_t)iValue;
+ bytes_read += 2;
}
- section[image->num_sections].base_address = address;
- full_address = address;
- }
+ } else if (record_type >= 1 && record_type <= 3) {
+ switch (record_type) {
+ case 1:
+ /* S1 - 16 bit address data record */
+ sscanf(&lpszLine[bytes_read], "%4" SCNx32, &address);
+ cal_checksum += (uint8_t)(address >> 8);
+ cal_checksum += (uint8_t)address;
+ bytes_read += 4;
+ count -= 2;
+ break;
+
+ case 2:
+ /* S2 - 24 bit address data record */
+ sscanf(&lpszLine[bytes_read], "%6" SCNx32, &address);
+ cal_checksum += (uint8_t)(address >> 16);
+ cal_checksum += (uint8_t)(address >> 8);
+ cal_checksum += (uint8_t)address;
+ bytes_read += 6;
+ count -= 3;
+ break;
+
+ case 3:
+ /* S3 - 32 bit address data record */
+ sscanf(&lpszLine[bytes_read], "%8" SCNx32, &address);
+ cal_checksum += (uint8_t)(address >> 24);
+ cal_checksum += (uint8_t)(address >> 16);
+ cal_checksum += (uint8_t)(address >> 8);
+ cal_checksum += (uint8_t)address;
+ bytes_read += 8;
+ count -= 4;
+ break;
- while (count-- > 0) {
- unsigned value;
- sscanf(&lpszLine[bytes_read], "%2x", &value);
- mot->buffer[cooked_bytes] = (uint8_t)value;
- cal_checksum += (uint8_t)mot->buffer[cooked_bytes];
- bytes_read += 2;
- cooked_bytes += 1;
- section[image->num_sections].size += 1;
- full_address++;
- }
- } else if (record_type == 5) {
- /* S5 is the data count record, we ignore it */
- uint32_t dummy;
-
- while (count-- > 0) {
- sscanf(&lpszLine[bytes_read], "%2" SCNx32, &dummy);
- cal_checksum += (uint8_t)dummy;
- bytes_read += 2;
- }
- } else if (record_type >= 7 && record_type <= 9) {
- /* S7, S8, S9 - ending records for 32, 24 and 16bit */
- image->num_sections++;
+ }
- /* copy section information */
- image->sections = malloc(sizeof(struct imagesection) * image->num_sections);
- for (i = 0; i < image->num_sections; i++) {
- image->sections[i].private = section[i].private;
- image->sections[i].base_address = section[i].base_address;
- image->sections[i].size = section[i].size;
- image->sections[i].flags = section[i].flags;
+ if (full_address != address) {
+ /* we encountered a nonconsecutive location, create a new section,
+ * unless the current section has zero size, in which case this specifies
+ * the current section's base address
+ */
+ if (section[image->num_sections].size != 0) {
+ image->num_sections++;
+ section[image->num_sections].size = 0x0;
+ section[image->num_sections].flags = 0;
+ section[image->num_sections].private =
+ &mot->buffer[cooked_bytes];
+ }
+ section[image->num_sections].base_address = address;
+ full_address = address;
+ }
+
+ while (count-- > 0) {
+ unsigned value;
+ sscanf(&lpszLine[bytes_read], "%2x", &value);
+ mot->buffer[cooked_bytes] = (uint8_t)value;
+ cal_checksum += (uint8_t)mot->buffer[cooked_bytes];
+ bytes_read += 2;
+ cooked_bytes += 1;
+ section[image->num_sections].size += 1;
+ full_address++;
+ }
+ } else if (record_type == 5) {
+ /* S5 is the data count record, we ignore it */
+ uint32_t dummy;
+
+ while (count-- > 0) {
+ sscanf(&lpszLine[bytes_read], "%2" SCNx32, &dummy);
+ cal_checksum += (uint8_t)dummy;
+ bytes_read += 2;
+ }
+ } else if (record_type >= 7 && record_type <= 9) {
+ /* S7, S8, S9 - ending records for 32, 24 and 16bit */
+ image->num_sections++;
+
+ /* copy section information */
+ image->sections = malloc(sizeof(struct imagesection) * image->num_sections);
+ for (i = 0; i < image->num_sections; i++) {
+ image->sections[i].private = section[i].private;
+ image->sections[i].base_address = section[i].base_address;
+ image->sections[i].size = section[i].size;
+ image->sections[i].flags = section[i].flags;
+ }
+
+ end_rec = true;
+ break;
+ } else {
+ LOG_ERROR("unhandled S19 record type: %i", (int)(record_type));
+ return ERROR_IMAGE_FORMAT_ERROR;
}
- return ERROR_OK;
- } else {
- LOG_ERROR("unhandled S19 record type: %i", (int)(record_type));
- return ERROR_IMAGE_FORMAT_ERROR;
- }
+ /* account for checksum, will always be 0xFF */
+ sscanf(&lpszLine[bytes_read], "%2" SCNx32, &checksum);
+ cal_checksum += (uint8_t)checksum;
- /* account for checksum, will always be 0xFF */
- sscanf(&lpszLine[bytes_read], "%2" SCNx32, &checksum);
- cal_checksum += (uint8_t)checksum;
+ if (cal_checksum != 0xFF) {
+ /* checksum failed */
+ LOG_ERROR("incorrect record checksum found in S19 file");
+ return ERROR_IMAGE_CHECKSUM;
+ }
- if (cal_checksum != 0xFF) {
- /* checksum failed */
- LOG_ERROR("incorrect record checksum found in S19 file");
- return ERROR_IMAGE_CHECKSUM;
+ if (end_rec) {
+ end_rec = false;
+ LOG_WARNING("continuing after end-of-file record: %.40s", lpszLine);
+ }
}
}
- LOG_ERROR("premature end of S19 file, no end-of-file record found");
- return ERROR_IMAGE_FORMAT_ERROR;
+ if (end_rec)
+ return ERROR_OK;
+ else {
+ LOG_ERROR("premature end of S19 file, no matching end-of-file record found");
+ return ERROR_IMAGE_FORMAT_ERROR;
+ }
}
/**
diff --git a/src/target/openrisc/jsp_server.c b/src/target/openrisc/jsp_server.c
index 2d90114..6cd53f4 100644
--- a/src/target/openrisc/jsp_server.c
+++ b/src/target/openrisc/jsp_server.c
@@ -242,3 +242,7 @@ int jsp_register_commands(struct command_context *cmd_ctx)
return register_commands(cmd_ctx, NULL, jsp_command_handlers);
}
+void jsp_service_free(void)
+{
+ free(jsp_port);
+}
diff --git a/src/target/openrisc/jsp_server.h b/src/target/openrisc/jsp_server.h
index f8e7121..e5cfaa8 100644
--- a/src/target/openrisc/jsp_server.h
+++ b/src/target/openrisc/jsp_server.h
@@ -13,5 +13,6 @@ struct jsp_service {
int jsp_init(struct or1k_jtag *jtag_info, char *banner);
int jsp_register_commands(struct command_context *cmd_ctx);
+void jsp_service_free(void);
#endif /* OPENOCD_TARGET_OPENRISC_JSP_SERVER_H */
diff --git a/src/target/register.h b/src/target/register.h
index dc18e9a..32c1f39 100644
--- a/src/target/register.h
+++ b/src/target/register.h
@@ -25,12 +25,14 @@
struct target;
enum reg_type {
+ REG_TYPE_BOOL,
REG_TYPE_INT,
REG_TYPE_INT8,
REG_TYPE_INT16,
REG_TYPE_INT32,
REG_TYPE_INT64,
REG_TYPE_INT128,
+ REG_TYPE_UINT,
REG_TYPE_UINT8,
REG_TYPE_UINT16,
REG_TYPE_UINT32,
@@ -66,6 +68,7 @@ struct reg_data_type_union {
struct reg_data_type_bitfield {
uint32_t start;
uint32_t end;
+ enum reg_type type;
};
struct reg_data_type_struct_field {
diff --git a/src/target/riscv/batch.c b/src/target/riscv/batch.c
index 117119d..9327cb3 100644
--- a/src/target/riscv/batch.c
+++ b/src/target/riscv/batch.c
@@ -160,11 +160,10 @@ void dump_field(const struct scan_field *field)
log_printf_lf(LOG_LVL_DEBUG,
__FILE__, __LINE__, __PRETTY_FUNCTION__,
- "%db %s %08x @%02x -> %s %08x @%02x [0x%p -> 0x%p]",
+ "%db %s %08x @%02x -> %s %08x @%02x",
field->num_bits,
op_string[out_op], out_data, out_address,
- status_string[in_op], in_data, in_address,
- field->out_value, field->in_value);
+ status_string[in_op], in_data, in_address);
} else {
log_printf_lf(LOG_LVL_DEBUG,
__FILE__, __LINE__, __PRETTY_FUNCTION__, "%db %s %08x @%02x -> ?",
diff --git a/src/target/riscv/encoding.h b/src/target/riscv/encoding.h
index c109ce1..e214c0c 100644
--- a/src/target/riscv/encoding.h
+++ b/src/target/riscv/encoding.h
@@ -1,4 +1,4 @@
-// See LICENSE for license details.
+/* See LICENSE for license details. */
#ifndef RISCV_CSR_ENCODING_H
#define RISCV_CSR_ENCODING_H
@@ -156,16 +156,16 @@
#define EXT_IO_BASE 0x40000000
#define DRAM_BASE 0x80000000
-// page table entry (PTE) fields
-#define PTE_V 0x001 // Valid
-#define PTE_R 0x002 // Read
-#define PTE_W 0x004 // Write
-#define PTE_X 0x008 // Execute
-#define PTE_U 0x010 // User
-#define PTE_G 0x020 // Global
-#define PTE_A 0x040 // Accessed
-#define PTE_D 0x080 // Dirty
-#define PTE_SOFT 0x300 // Reserved for Software
+/* page table entry (PTE) fields */
+#define PTE_V 0x001 /* Valid */
+#define PTE_R 0x002 /* Read */
+#define PTE_W 0x004 /* Write */
+#define PTE_X 0x008 /* Execute */
+#define PTE_U 0x010 /* User */
+#define PTE_G 0x020 /* Global */
+#define PTE_A 0x040 /* Accessed */
+#define PTE_D 0x080 /* Dirty */
+#define PTE_SOFT 0x300 /* Reserved for Software */
#define PTE_PPN_SHIFT 10
@@ -191,6 +191,7 @@
#ifdef __GNUC__
+/*
#define read_csr(reg) ({ unsigned long __tmp; \
asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \
__tmp; })
@@ -209,6 +210,7 @@
#define clear_csr(reg, bit) ({ unsigned long __tmp; \
asm volatile ("csrrc %0, " #reg ", %1" : "=r"(__tmp) : "rK"(bit)); \
__tmp; })
+ */
#define rdtime() read_csr(time)
#define rdcycle() read_csr(cycle)
diff --git a/src/target/riscv/riscv-011.c b/src/target/riscv/riscv-011.c
index b450d2b..4322f7b 100644
--- a/src/target/riscv/riscv-011.c
+++ b/src/target/riscv/riscv-011.c
@@ -455,12 +455,12 @@ static uint64_t dbus_read(struct target *target, uint16_t address)
uint64_t value;
dbus_status_t status;
uint16_t address_in;
-
+
/* If the previous read/write was to the same address, we will get the read data
* from the previous access.
* While somewhat nonintuitive, this is an efficient way to get the data.
*/
-
+
unsigned i = 0;
do {
status = dbus_scan(target, &address_in, &value, DBUS_OP_READ, address, 0);
@@ -680,7 +680,7 @@ static bits_t read_bits(struct target *target)
}
increase_dbus_busy_delay(target);
} else if (status == DBUS_STATUS_FAILED) {
- // TODO: return an actual error
+ /* TODO: return an actual error */
return err_result;
}
} while (status == DBUS_STATUS_BUSY && i++ < 256);
diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c
index 4d23cd6..1869038 100644
--- a/src/target/riscv/riscv-013.c
+++ b/src/target/riscv/riscv-013.c
@@ -39,7 +39,7 @@ static void riscv013_clear_abstract_error(struct target *target);
static int riscv013_get_register(struct target *target,
riscv_reg_t *value, int hid, int rid);
static int riscv013_set_register(struct target *target, int hartid, int regid, uint64_t value);
-static void riscv013_select_current_hart(struct target *target);
+static int riscv013_select_current_hart(struct target *target);
static int riscv013_halt_current_hart(struct target *target);
static int riscv013_resume_current_hart(struct target *target);
static int riscv013_step_current_hart(struct target *target);
@@ -253,9 +253,8 @@ static dm013_info_t *get_dm(struct target *target)
info->dm = dm;
target_list_t *target_entry;
list_for_each_entry(target_entry, &dm->target_list, list) {
- if (target_entry->target == target) {
+ if (target_entry->target == target)
return dm;
- }
}
target_entry = calloc(1, sizeof(*target_entry));
target_entry->target = target;
@@ -284,8 +283,11 @@ static void decode_dmi(char *text, unsigned address, unsigned data)
{ DMI_DMCONTROL, ((1L<<10)-1) << DMI_DMCONTROL_HARTSEL_OFFSET, "hartsel" },
{ DMI_DMCONTROL, DMI_DMCONTROL_NDMRESET, "ndmreset" },
{ DMI_DMCONTROL, DMI_DMCONTROL_DMACTIVE, "dmactive" },
+ { DMI_DMCONTROL, DMI_DMCONTROL_ACKHAVERESET, "ackhavereset" },
{ DMI_DMSTATUS, DMI_DMSTATUS_IMPEBREAK, "impebreak" },
+ { DMI_DMSTATUS, DMI_DMSTATUS_ALLHAVERESET, "allhavereset" },
+ { DMI_DMSTATUS, DMI_DMSTATUS_ANYHAVERESET, "anyhavereset" },
{ DMI_DMSTATUS, DMI_DMSTATUS_ALLRESUMEACK, "allresumeack" },
{ DMI_DMSTATUS, DMI_DMSTATUS_ANYRESUMEACK, "anyresumeack" },
{ DMI_DMSTATUS, DMI_DMSTATUS_ALLNONEXISTENT, "allnonexistent" },
@@ -483,58 +485,79 @@ static dmi_status_t dmi_scan(struct target *target, uint32_t *address_in,
return buf_get_u32(in, DTM_DMI_OP_OFFSET, DTM_DMI_OP_LENGTH);
}
-static int dmi_read(struct target *target, uint32_t *value, uint32_t address)
+static int dmi_op_timeout(struct target *target, uint32_t *data_in, int dmi_op,
+ uint32_t address, uint32_t data_out, int timeout_sec)
{
select_dmi(target);
dmi_status_t status;
uint32_t address_in;
- unsigned i = 0;
+ const char *op_name;
+ switch (dmi_op) {
+ case DMI_OP_NOP:
+ op_name = "nop";
+ break;
+ case DMI_OP_READ:
+ op_name = "read";
+ break;
+ case DMI_OP_WRITE:
+ op_name = "write";
+ break;
+ default:
+ LOG_ERROR("Invalid DMI operation: %d", dmi_op);
+ return ERROR_FAIL;
+ }
- /* This first loop ensures that the read request was actually sent
- * to the target. Note that if for some reason this stays busy,
- * it is actually due to the previous dmi_read or dmi_write. */
- for (i = 0; i < 256; i++) {
- status = dmi_scan(target, NULL, NULL, DMI_OP_READ, address, 0,
+ time_t start = time(NULL);
+ /* This first loop performs the request. Note that if for some reason this
+ * stays busy, it is actually due to the previous access. */
+ while (1) {
+ status = dmi_scan(target, NULL, NULL, dmi_op, address, data_out,
false);
if (status == DMI_STATUS_BUSY) {
increase_dmi_busy_delay(target);
} else if (status == DMI_STATUS_SUCCESS) {
break;
} else {
- LOG_ERROR("failed read from 0x%x, status=%d", address, status);
+ LOG_ERROR("failed %s at 0x%x, status=%d", op_name, address, status);
return ERROR_FAIL;
}
+ if (time(NULL) - start > timeout_sec)
+ return ERROR_TIMEOUT_REACHED;
}
if (status != DMI_STATUS_SUCCESS) {
- LOG_ERROR("Failed read from 0x%x; status=%d", address, status);
+ LOG_ERROR("Failed %s at 0x%x; status=%d", op_name, address, status);
return ERROR_FAIL;
}
- /* This second loop ensures that we got the read
- * data back. Note that NOP can result in a 'busy' result as well, but
- * that would be noticed on the next DMI access we do. */
- for (i = 0; i < 256; i++) {
- status = dmi_scan(target, &address_in, value, DMI_OP_NOP, address, 0,
+ /* This second loop ensures the request succeeded, and gets back data.
+ * Note that NOP can result in a 'busy' result as well, but that would be
+ * noticed on the next DMI access we do. */
+ while (1) {
+ status = dmi_scan(target, &address_in, data_in, DMI_OP_NOP, address, 0,
false);
if (status == DMI_STATUS_BUSY) {
increase_dmi_busy_delay(target);
} else if (status == DMI_STATUS_SUCCESS) {
break;
} else {
- LOG_ERROR("failed read (NOP) at 0x%x, status=%d", address, status);
+ LOG_ERROR("failed %s (NOP) at 0x%x, status=%d", op_name, address,
+ status);
return ERROR_FAIL;
}
+ if (time(NULL) - start > timeout_sec)
+ return ERROR_TIMEOUT_REACHED;
}
if (status != DMI_STATUS_SUCCESS) {
- if (status == DMI_STATUS_FAILED) {
- LOG_ERROR("Failed read (NOP) from 0x%x; status=%d", address, status);
+ if (status == DMI_STATUS_FAILED || !data_in) {
+ LOG_ERROR("Failed %s (NOP) at 0x%x; status=%d", op_name, address,
+ status);
} else {
- LOG_ERROR("Failed read (NOP) from 0x%x; value=0x%x, status=%d",
- address, *value, status);
+ LOG_ERROR("Failed %s (NOP) at 0x%x; value=0x%x, status=%d",
+ op_name, address, *data_in, status);
}
return ERROR_FAIL;
}
@@ -542,60 +565,38 @@ static int dmi_read(struct target *target, uint32_t *value, uint32_t address)
return ERROR_OK;
}
-static int dmi_write(struct target *target, uint32_t address, uint32_t value)
+static int dmi_op(struct target *target, uint32_t *data_in, int dmi_op,
+ uint32_t address, uint32_t data_out)
{
- select_dmi(target);
- dmi_status_t status = DMI_STATUS_BUSY;
- unsigned i = 0;
-
- /* The first loop ensures that we successfully sent the write request. */
- for (i = 0; i < 256; i++) {
- status = dmi_scan(target, NULL, NULL, DMI_OP_WRITE, address, value,
- address == DMI_COMMAND);
- if (status == DMI_STATUS_BUSY) {
- increase_dmi_busy_delay(target);
- } else if (status == DMI_STATUS_SUCCESS) {
- break;
- } else {
- LOG_ERROR("failed write to 0x%x, status=%d", address, status);
- break;
- }
- }
-
- if (status != DMI_STATUS_SUCCESS) {
- LOG_ERROR("Failed write to 0x%x;, status=%d",
- address, status);
+ int result = dmi_op_timeout(target, data_in, dmi_op, address, data_out,
+ riscv_command_timeout_sec);
+ if (result == ERROR_TIMEOUT_REACHED) {
+ LOG_ERROR("DMI operation didn't complete in %d seconds. The target is "
+ "either really slow or broken. You could increase the "
+ "timeout with riscv set_command_timeout_sec.",
+ riscv_command_timeout_sec);
return ERROR_FAIL;
}
+ return result;
+}
- /* The second loop isn't strictly necessary, but would ensure that the
- * write is complete/ has no non-busy errors before returning from this
- * function. */
- for (i = 0; i < 256; i++) {
- status = dmi_scan(target, NULL, NULL, DMI_OP_NOP, address, 0,
- false);
- if (status == DMI_STATUS_BUSY) {
- increase_dmi_busy_delay(target);
- } else if (status == DMI_STATUS_SUCCESS) {
- break;
- } else {
- LOG_ERROR("failed write (NOP) at 0x%x, status=%d", address, status);
- break;
- }
- }
- if (status != DMI_STATUS_SUCCESS) {
- LOG_ERROR("failed to write (NOP) 0x%x to 0x%x; status=%d", value, address, status);
- return ERROR_FAIL;
- }
+static int dmi_read(struct target *target, uint32_t *value, uint32_t address)
+{
+ return dmi_op(target, value, DMI_OP_READ, address, 0);
+}
- return ERROR_OK;
+static int dmi_write(struct target *target, uint32_t address, uint32_t value)
+{
+ return dmi_op(target, NULL, DMI_OP_WRITE, address, value);
}
-int dmstatus_read(struct target *target, uint32_t *dmstatus,
- bool authenticated)
+int dmstatus_read_timeout(struct target *target, uint32_t *dmstatus,
+ bool authenticated, unsigned timeout_sec)
{
- if (dmi_read(target, dmstatus, DMI_DMSTATUS) != ERROR_OK)
- return ERROR_FAIL;
+ int result = dmi_op_timeout(target, dmstatus, DMI_OP_READ, DMI_DMSTATUS, 0,
+ timeout_sec);
+ if (result != ERROR_OK)
+ return result;
if (authenticated && !get_field(*dmstatus, DMI_DMSTATUS_AUTHENTICATED)) {
LOG_ERROR("Debugger is not authenticated to target Debug Module. "
"(dmstatus=0x%x). Use `riscv authdata_read` and "
@@ -605,6 +606,13 @@ int dmstatus_read(struct target *target, uint32_t *dmstatus,
return ERROR_OK;
}
+int dmstatus_read(struct target *target, uint32_t *dmstatus,
+ bool authenticated)
+{
+ return dmstatus_read_timeout(target, dmstatus, authenticated,
+ riscv_command_timeout_sec);
+}
+
static void increase_ac_busy_delay(struct target *target)
{
riscv013_info_t *info = get_info(target);
@@ -1163,10 +1171,9 @@ static int register_read_direct(struct target *target, uint64_t *value, uint32_t
int result = register_read_abstract(target, value, number,
register_size(target, number));
- if (result != ERROR_OK && info->progbufsize + r->impebreak >= 2 &&
- riscv_is_halted(target)) {
- assert(number != GDB_REGNO_S0);
-
+ if (result != ERROR_OK &&
+ info->progbufsize + r->impebreak >= 2 &&
+ number > GDB_REGNO_XPR31) {
struct riscv_program program;
riscv_program_init(&program, target);
@@ -1392,7 +1399,8 @@ static int examine(struct target *target)
continue;
r->current_hartid = i;
- riscv013_select_current_hart(target);
+ if (riscv013_select_current_hart(target) != ERROR_OK)
+ return ERROR_FAIL;
uint32_t s;
if (dmstatus_read(target, &s, true) != ERROR_OK)
@@ -1401,6 +1409,11 @@ static int examine(struct target *target)
break;
r->hart_count = i + 1;
+ if (get_field(s, DMI_DMSTATUS_ANYHAVERESET))
+ dmi_write(target, DMI_DMCONTROL,
+ set_field(DMI_DMCONTROL_DMACTIVE | DMI_DMCONTROL_ACKHAVERESET,
+ hartsel_mask(target), i));
+
if (!riscv_is_halted(target)) {
if (riscv013_halt_current_hart(target) != ERROR_OK) {
LOG_ERROR("Fatal: Hart %d failed to halt during examine()", i);
@@ -1571,7 +1584,7 @@ static int assert_reset(struct target *target)
/* TODO: Try to use hasel in dmcontrol */
- /* Set haltreq/resumereq for each hart. */
+ /* Set haltreq for each hart. */
uint32_t control = control_base;
for (int i = 0; i < riscv_count_harts(target); ++i) {
if (!riscv_hart_enabled(target, i))
@@ -1592,20 +1605,8 @@ static int assert_reset(struct target *target)
r->current_hartid);
control = set_field(control, DMI_DMCONTROL_HALTREQ,
target->reset_halt ? 1 : 0);
- control = set_field(control, DMI_DMCONTROL_HARTRESET, 1);
+ control = set_field(control, DMI_DMCONTROL_NDMRESET, 1);
dmi_write(target, DMI_DMCONTROL, control);
-
- /* Read back to check if hartreset is supported. */
- uint32_t rb;
- if (dmi_read(target, &rb, DMI_DMCONTROL) != ERROR_OK)
- return ERROR_FAIL;
- if (!get_field(rb, DMI_DMCONTROL_HARTRESET)) {
- /* Use ndmreset instead. That will reset the entire device, but
- * that's probably what OpenOCD wants anyway. */
- control = set_field(control, DMI_DMCONTROL_HARTRESET, 0);
- control = set_field(control, DMI_DMCONTROL_NDMRESET, 1);
- dmi_write(target, DMI_DMCONTROL, control);
- }
}
target->state = TARGET_RESET;
@@ -1619,57 +1620,77 @@ static int deassert_reset(struct target *target)
RISCV013_INFO(info);
select_dmi(target);
- LOG_DEBUG("%d", r->current_hartid);
-
/* Clear the reset, but make sure haltreq is still set */
uint32_t control = 0;
control = set_field(control, DMI_DMCONTROL_HALTREQ, target->reset_halt ? 1 : 0);
- control = set_field(control, hartsel_mask(target), r->current_hartid);
control = set_field(control, DMI_DMCONTROL_DMACTIVE, 1);
- dmi_write(target, DMI_DMCONTROL, control);
+ dmi_write(target, DMI_DMCONTROL,
+ set_field(control, hartsel_mask(target), r->current_hartid));
uint32_t dmstatus;
int dmi_busy_delay = info->dmi_busy_delay;
time_t start = time(NULL);
- if (target->reset_halt) {
- LOG_DEBUG("Waiting for hart to be halted.");
- do {
- if (dmstatus_read(target, &dmstatus, true) != ERROR_OK)
- return ERROR_FAIL;
- if (time(NULL) - start > riscv_reset_timeout_sec) {
- LOG_ERROR("Hart didn't halt coming out of reset in %ds; "
- "dmstatus=0x%x; "
- "Increase the timeout with riscv set_reset_timeout_sec.",
- riscv_reset_timeout_sec, dmstatus);
- return ERROR_FAIL;
- }
- target->state = TARGET_HALTED;
- } while (get_field(dmstatus, DMI_DMSTATUS_ALLHALTED) == 0);
-
- control = set_field(control, DMI_DMCONTROL_HALTREQ, 0);
- dmi_write(target, DMI_DMCONTROL, control);
+ for (int i = 0; i < riscv_count_harts(target); ++i) {
+ int index = i;
+ if (target->rtos) {
+ if (!riscv_hart_enabled(target, index))
+ continue;
+ dmi_write(target, DMI_DMCONTROL,
+ set_field(control, hartsel_mask(target), index));
+ } else {
+ index = r->current_hartid;
+ }
- } else {
- LOG_DEBUG("Waiting for hart to be running.");
- do {
- if (dmstatus_read(target, &dmstatus, true) != ERROR_OK)
- return ERROR_FAIL;
- if (get_field(dmstatus, DMI_DMSTATUS_ANYHALTED) ||
- get_field(dmstatus, DMI_DMSTATUS_ANYUNAVAIL)) {
- LOG_ERROR("Unexpected hart status during reset. dmstatus=0x%x",
- dmstatus);
+ char *operation;
+ uint32_t expected_field;
+ uint32_t unexpected_field;
+ if (target->reset_halt) {
+ operation = "halt";
+ expected_field = DMI_DMSTATUS_ALLHALTED;
+ unexpected_field = DMI_DMSTATUS_ANYRUNNING;
+ } else {
+ operation = "run";
+ expected_field = DMI_DMSTATUS_ALLRUNNING;
+ unexpected_field = DMI_DMSTATUS_ANYHALTED;
+ }
+ LOG_DEBUG("Waiting for hart %d to %s out of reset.", index, operation);
+ while (1) {
+ int result = dmstatus_read_timeout(target, &dmstatus, true,
+ riscv_reset_timeout_sec);
+ if (result == ERROR_TIMEOUT_REACHED)
+ LOG_ERROR("Hart %d didn't complete a DMI read coming out of "
+ "reset in %ds; Increase the timeout with riscv "
+ "set_reset_timeout_sec.",
+ index, riscv_reset_timeout_sec);
+ if (result != ERROR_OK)
+ return result;
+ if (get_field(dmstatus, unexpected_field)) {
+ LOG_ERROR("Unexpected hart %d status during reset. dmstatus=0x%x",
+ index, dmstatus);
return ERROR_FAIL;
}
+ if (get_field(dmstatus, expected_field))
+ break;
if (time(NULL) - start > riscv_reset_timeout_sec) {
- LOG_ERROR("Hart didn't run coming out of reset in %ds; "
+ LOG_ERROR("Hart %d didn't %s coming out of reset in %ds; "
"dmstatus=0x%x; "
"Increase the timeout with riscv set_reset_timeout_sec.",
- riscv_reset_timeout_sec, dmstatus);
+ index, operation, riscv_reset_timeout_sec, dmstatus);
return ERROR_FAIL;
}
- } while (get_field(dmstatus, DMI_DMSTATUS_ALLRUNNING) == 0);
- target->state = TARGET_RUNNING;
+ }
+ target->state = TARGET_HALTED;
+
+ if (get_field(dmstatus, DMI_DMSTATUS_ALLHAVERESET)) {
+ /* Ack reset. */
+ dmi_write(target, DMI_DMCONTROL,
+ set_field(control, hartsel_mask(target), index) |
+ DMI_DMCONTROL_ACKHAVERESET);
+ }
+
+ if (!target->rtos)
+ break;
}
info->dmi_busy_delay = dmi_busy_delay;
return ERROR_OK;
@@ -1798,19 +1819,16 @@ static int sb_write_address(struct target *target, target_addr_t address)
RISCV013_INFO(info);
unsigned sbasize = get_field(info->sbcs, DMI_SBCS_SBASIZE);
/* There currently is no support for >64-bit addresses in OpenOCD. */
- if (sbasize > 96) {
+ if (sbasize > 96)
dmi_write(target, DMI_SBADDRESS3, 0);
- }
- if (sbasize > 64) {
+ if (sbasize > 64)
dmi_write(target, DMI_SBADDRESS2, 0);
- }
- if (sbasize > 32) {
+ if (sbasize > 32)
#if BUILD_TARGET64
dmi_write(target, DMI_SBADDRESS1, address >> 32);
#else
dmi_write(target, DMI_SBADDRESS1, 0);
#endif
- }
return dmi_write(target, DMI_SBADDRESS0, address);
}
@@ -1826,8 +1844,8 @@ static int read_sbcs_nonbusy(struct target *target, uint32_t *sbcs)
LOG_ERROR("Timed out after %ds waiting for sbbusy to go low (sbcs=0x%x). "
"Increase the timeout with riscv set_command_timeout_sec.",
riscv_command_timeout_sec, *sbcs);
+ return ERROR_FAIL;
}
- return ERROR_FAIL;
}
}
@@ -1955,6 +1973,7 @@ static int read_memory_bus_v1(struct target *target, target_addr_t address,
dmi_write(target, DMI_SBCS, DMI_SBCS_SBBUSYERROR);
next_address = sb_read_address(target);
info->bus_master_read_delay += info->bus_master_read_delay / 10 + 1;
+ continue;
}
unsigned error = get_field(sbcs, DMI_SBCS_SBERROR);
@@ -2393,6 +2412,7 @@ static int write_memory_bus_v1(struct target *target, target_addr_t address,
dmi_write(target, DMI_SBCS, DMI_SBCS_SBBUSYERROR);
next_address = sb_read_address(target);
info->bus_master_write_delay += info->bus_master_write_delay / 10 + 1;
+ continue;
}
unsigned error = get_field(sbcs, DMI_SBCS_SBERROR);
@@ -2697,23 +2717,22 @@ static int riscv013_set_register(struct target *target, int hid, int rid, uint64
return ERROR_OK;
}
-static void riscv013_select_current_hart(struct target *target)
+static int riscv013_select_current_hart(struct target *target)
{
RISCV_INFO(r);
dm013_info_t *dm = get_dm(target);
if (r->current_hartid == dm->current_hartid) {
- LOG_DEBUG(">>> nothing to be done");
- return;
+ return ERROR_OK;
}
- LOG_DEBUG(">>> change it");
-
uint32_t dmcontrol;
- dmi_read(target, &dmcontrol, DMI_DMCONTROL);
+ if (dmi_read(target, &dmcontrol, DMI_DMCONTROL) != ERROR_OK)
+ return ERROR_FAIL;
dmcontrol = set_field(dmcontrol, hartsel_mask(target), r->current_hartid);
- dmi_write(target, DMI_DMCONTROL, dmcontrol);
+ int result = dmi_write(target, DMI_DMCONTROL, dmcontrol);
dm->current_hartid = r->current_hartid;
+ return result;
}
static int riscv013_halt_current_hart(struct target *target)
@@ -2783,9 +2802,25 @@ static bool riscv013_is_halted(struct target *target)
if (dmstatus_read(target, &dmstatus, true) != ERROR_OK)
return false;
if (get_field(dmstatus, DMI_DMSTATUS_ANYUNAVAIL))
- LOG_ERROR("hart %d is unavailiable", riscv_current_hartid(target));
+ LOG_ERROR("Hart %d is unavailable.", riscv_current_hartid(target));
if (get_field(dmstatus, DMI_DMSTATUS_ANYNONEXISTENT))
- LOG_ERROR("hart %d doesn't exist", riscv_current_hartid(target));
+ LOG_ERROR("Hart %d doesn't exist.", riscv_current_hartid(target));
+ if (get_field(dmstatus, DMI_DMSTATUS_ANYHAVERESET)) {
+ int hartid = riscv_current_hartid(target);
+ LOG_INFO("Hart %d unexpectedly reset!", hartid);
+ /* TODO: Can we make this more obvious to eg. a gdb user? */
+ uint32_t dmcontrol = DMI_DMCONTROL_DMACTIVE |
+ DMI_DMCONTROL_ACKHAVERESET;
+ dmcontrol = set_field(dmcontrol, hartsel_mask(target), hartid);
+ /* If we had been halted when we reset, request another halt. If we
+ * ended up running out of reset, then the user will (hopefully) get a
+ * message that a reset happened, that the target is running, and then
+ * that it is halted again once the request goes through.
+ */
+ if (target->state == TARGET_HALTED)
+ dmcontrol |= DMI_DMCONTROL_HALTREQ;
+ dmi_write(target, DMI_DMCONTROL, dmcontrol);
+ }
return get_field(dmstatus, DMI_DMSTATUS_ALLHALTED);
}
@@ -2914,11 +2949,9 @@ static int riscv013_step_or_resume_current_hart(struct target *target, bool step
return ERROR_FAIL;
/* Issue the resume command, and then wait for the current hart to resume. */
- uint32_t dmcontrol;
- if (dmi_read(target, &dmcontrol, DMI_DMCONTROL) != ERROR_OK)
- return ERROR_FAIL;
- dmcontrol = set_field(dmcontrol, DMI_DMCONTROL_RESUMEREQ, 1);
- dmi_write(target, DMI_DMCONTROL, dmcontrol);
+ uint32_t dmcontrol = DMI_DMCONTROL_DMACTIVE;
+ dmcontrol = set_field(dmcontrol, hartsel_mask(target), r->current_hartid);
+ dmi_write(target, DMI_DMCONTROL, dmcontrol | DMI_DMCONTROL_RESUMEREQ);
uint32_t dmstatus;
for (size_t i = 0; i < 256; ++i) {
@@ -2930,17 +2963,16 @@ static int riscv013_step_or_resume_current_hart(struct target *target, bool step
if (step && get_field(dmstatus, DMI_DMSTATUS_ALLHALTED) == 0)
continue;
- dmcontrol = set_field(dmcontrol, DMI_DMCONTROL_RESUMEREQ, 0);
dmi_write(target, DMI_DMCONTROL, dmcontrol);
return ERROR_OK;
}
- if (dmstatus_read(target, &dmstatus, true) != ERROR_OK)
- return ERROR_FAIL;
+ LOG_ERROR("unable to resume hart %d", r->current_hartid);
if (dmi_read(target, &dmcontrol, DMI_DMCONTROL) != ERROR_OK)
return ERROR_FAIL;
- LOG_ERROR("unable to resume hart %d", r->current_hartid);
LOG_ERROR(" dmcontrol=0x%08x", dmcontrol);
+ if (dmstatus_read(target, &dmstatus, true) != ERROR_OK)
+ return ERROR_FAIL;
LOG_ERROR(" dmstatus =0x%08x", dmstatus);
if (step) {
@@ -2965,7 +2997,7 @@ void riscv013_clear_abstract_error(struct target *target)
LOG_ERROR("abstractcs.busy is not going low after %d seconds "
"(abstractcs=0x%x). The target is either really slow or "
"broken. You could increase the timeout with riscv "
- "set_reset_timeout_sec.",
+ "set_command_timeout_sec.",
riscv_command_timeout_sec, abstractcs);
break;
}
diff --git a/src/target/riscv/riscv.c b/src/target/riscv/riscv.c
index aea6d7a..bd09ef7 100644
--- a/src/target/riscv/riscv.c
+++ b/src/target/riscv/riscv.c
@@ -741,19 +741,20 @@ static int old_or_new_riscv_resume(
return riscv_openocd_resume(target, current, address, handle_breakpoints, debug_execution);
}
-static void riscv_select_current_hart(struct target *target)
+static int riscv_select_current_hart(struct target *target)
{
RISCV_INFO(r);
if (r->rtos_hartid != -1 && riscv_rtos_enabled(target))
- riscv_set_current_hartid(target, r->rtos_hartid);
+ return riscv_set_current_hartid(target, r->rtos_hartid);
else
- riscv_set_current_hartid(target, target->coreid);
+ return riscv_set_current_hartid(target, target->coreid);
}
static int riscv_read_memory(struct target *target, target_addr_t address,
uint32_t size, uint32_t count, uint8_t *buffer)
{
- riscv_select_current_hart(target);
+ if (riscv_select_current_hart(target) != ERROR_OK)
+ return ERROR_FAIL;
struct target_type *tt = get_target_type(target);
return tt->read_memory(target, address, size, count, buffer);
}
@@ -761,7 +762,8 @@ static int riscv_read_memory(struct target *target, target_addr_t address,
static int riscv_write_memory(struct target *target, target_addr_t address,
uint32_t size, uint32_t count, const uint8_t *buffer)
{
- riscv_select_current_hart(target);
+ if (riscv_select_current_hart(target) != ERROR_OK)
+ return ERROR_FAIL;
struct target_type *tt = get_target_type(target);
return tt->write_memory(target, address, size, count, buffer);
}
@@ -779,7 +781,8 @@ static int riscv_get_gdb_reg_list(struct target *target,
return ERROR_FAIL;
}
- riscv_select_current_hart(target);
+ if (riscv_select_current_hart(target) != ERROR_OK)
+ return ERROR_FAIL;
switch (reg_class) {
case REG_CLASS_GENERAL:
@@ -968,50 +971,61 @@ int riscv_blank_check_memory(struct target *target,
/*** OpenOCD Helper Functions ***/
-/* 0 means nothing happened, 1 means the hart's state changed (and thus the
- * poll should terminate), and -1 means there was an error. */
-static int riscv_poll_hart(struct target *target, int hartid)
+enum riscv_poll_hart {
+ RPH_NO_CHANGE,
+ RPH_DISCOVERED_HALTED,
+ RPH_DISCOVERED_RUNNING,
+ RPH_ERROR
+};
+static enum riscv_poll_hart riscv_poll_hart(struct target *target, int hartid)
{
RISCV_INFO(r);
- riscv_set_current_hartid(target, hartid);
+ if (riscv_set_current_hartid(target, hartid) != ERROR_OK)
+ return RPH_ERROR;
- LOG_DEBUG("polling hart %d, target->state=%d (TARGET_HALTED=%d)", hartid, target->state, TARGET_HALTED);
+ LOG_DEBUG("polling hart %d, target->state=%d", hartid, target->state);
- /* If OpenOCD this we're running but this hart is halted then it's time
+ /* If OpenOCD thinks we're running but this hart is halted then it's time
* to raise an event. */
- if (target->state != TARGET_HALTED && riscv_is_halted(target)) {
+ bool halted = riscv_is_halted(target);
+ if (target->state != TARGET_HALTED && halted) {
LOG_DEBUG(" triggered a halt");
r->on_halt(target);
- return 1;
+ return RPH_DISCOVERED_HALTED;
+ } else if (target->state != TARGET_RUNNING && !halted) {
+ LOG_DEBUG(" triggered running");
+ target->state = TARGET_RUNNING;
+ return RPH_DISCOVERED_RUNNING;
}
- return 0;
+ return RPH_NO_CHANGE;
}
/*** OpenOCD Interface ***/
int riscv_openocd_poll(struct target *target)
{
LOG_DEBUG("polling all harts");
- int triggered_hart = -1;
+ int halted_hart = -1;
if (riscv_rtos_enabled(target)) {
/* Check every hart for an event. */
for (int i = 0; i < riscv_count_harts(target); ++i) {
- int out = riscv_poll_hart(target, i);
+ enum riscv_poll_hart out = riscv_poll_hart(target, i);
switch (out) {
- case 0:
+ case RPH_NO_CHANGE:
+ case RPH_DISCOVERED_RUNNING:
continue;
- case 1:
- triggered_hart = i;
+ case RPH_DISCOVERED_HALTED:
+ halted_hart = i;
break;
- case -1:
+ case RPH_ERROR:
return ERROR_FAIL;
}
}
- if (triggered_hart == -1) {
+ if (halted_hart == -1) {
LOG_DEBUG(" no harts just halted, target->state=%d", target->state);
return ERROR_OK;
}
- LOG_DEBUG(" hart %d halted", triggered_hart);
+ LOG_DEBUG(" hart %d halted", halted_hart);
/* If we're here then at least one hart triggered. That means
* we want to go and halt _every_ hart in the system, as that's
@@ -1022,15 +1036,19 @@ int riscv_openocd_poll(struct target *target)
for (int i = 0; i < riscv_count_harts(target); ++i)
riscv_halt_one_hart(target, i);
} else {
- if (riscv_poll_hart(target, riscv_current_hartid(target)) == 0)
+ enum riscv_poll_hart out = riscv_poll_hart(target,
+ riscv_current_hartid(target));
+ if (out == RPH_NO_CHANGE || out == RPH_DISCOVERED_RUNNING)
return ERROR_OK;
+ else if (out == RPH_ERROR)
+ return ERROR_FAIL;
- triggered_hart = riscv_current_hartid(target);
- LOG_DEBUG(" hart %d halted", triggered_hart);
+ halted_hart = riscv_current_hartid(target);
+ LOG_DEBUG(" hart %d halted", halted_hart);
}
target->state = TARGET_HALTED;
- switch (riscv_halt_reason(target, triggered_hart)) {
+ switch (riscv_halt_reason(target, halted_hart)) {
case RISCV_HALT_BREAKPOINT:
target->debug_reason = DBG_REASON_BREAKPOINT;
break;
@@ -1046,11 +1064,13 @@ int riscv_openocd_poll(struct target *target)
case RISCV_HALT_UNKNOWN:
target->debug_reason = DBG_REASON_UNDEFINED;
break;
+ case RISCV_HALT_ERROR:
+ return ERROR_FAIL;
}
if (riscv_rtos_enabled(target)) {
- target->rtos->current_threadid = triggered_hart + 1;
- target->rtos->current_thread = triggered_hart + 1;
+ target->rtos->current_threadid = halted_hart + 1;
+ target->rtos->current_thread = halted_hart + 1;
}
target->state = TARGET_HALTED;
@@ -1105,16 +1125,14 @@ int riscv_openocd_resume(
while (watchpoint && result == ERROR_OK) {
LOG_DEBUG("watchpoint %d: set=%d", i, watchpoint->set);
trigger_temporarily_cleared[i] = watchpoint->set;
- if (watchpoint->set) {
+ if (watchpoint->set)
result = riscv_remove_watchpoint(target, watchpoint);
- }
watchpoint = watchpoint->next;
i++;
}
- if (result == ERROR_OK) {
+ if (result == ERROR_OK)
result = riscv_step_rtos_hart(target);
- }
watchpoint = target->watchpoints;
i = 0;
@@ -1217,7 +1235,7 @@ COMMAND_HANDLER(riscv_set_scratch_ram)
return ERROR_OK;
}
- // TODO: use COMMAND_PARSE_NUMBER
+ /* TODO: use COMMAND_PARSE_NUMBER */
long long unsigned int address;
int result = sscanf(CMD_ARGV[0], "%llx", &address);
if (result != (int) strlen(CMD_ARGV[0])) {
@@ -1584,7 +1602,8 @@ int riscv_halt_one_hart(struct target *target, int hartid)
{
RISCV_INFO(r);
LOG_DEBUG("halting hart %d", hartid);
- riscv_set_current_hartid(target, hartid);
+ if (riscv_set_current_hartid(target, hartid) != ERROR_OK)
+ return ERROR_FAIL;
if (riscv_is_halted(target)) {
LOG_DEBUG(" hart %d requested halt, but was already halted", hartid);
return ERROR_OK;
@@ -1610,7 +1629,8 @@ int riscv_resume_one_hart(struct target *target, int hartid)
{
RISCV_INFO(r);
LOG_DEBUG("resuming hart %d", hartid);
- riscv_set_current_hartid(target, hartid);
+ if (riscv_set_current_hartid(target, hartid) != ERROR_OK)
+ return ERROR_FAIL;
if (!riscv_is_halted(target)) {
LOG_DEBUG(" hart %d requested resume, but was already resumed", hartid);
return ERROR_OK;
@@ -1631,7 +1651,8 @@ int riscv_step_rtos_hart(struct target *target)
hartid = 0;
}
}
- riscv_set_current_hartid(target, hartid);
+ if (riscv_set_current_hartid(target, hartid) != ERROR_OK)
+ return ERROR_FAIL;
LOG_DEBUG("stepping hart %d", hartid);
if (!riscv_is_halted(target)) {
@@ -1681,33 +1702,35 @@ bool riscv_rtos_enabled(const struct target *target)
return target->rtos != NULL;
}
-void riscv_set_current_hartid(struct target *target, int hartid)
+int riscv_set_current_hartid(struct target *target, int hartid)
{
RISCV_INFO(r);
if (!r->select_current_hart)
- return;
+ return ERROR_FAIL;
int previous_hartid = riscv_current_hartid(target);
r->current_hartid = hartid;
assert(riscv_hart_enabled(target, hartid));
LOG_DEBUG("setting hartid to %d, was %d", hartid, previous_hartid);
- r->select_current_hart(target);
+ if (r->select_current_hart(target) != ERROR_OK)
+ return ERROR_FAIL;
/* This might get called during init, in which case we shouldn't be
* setting up the register cache. */
if (!target_was_examined(target))
- return;
+ return ERROR_OK;
/* Avoid invalidating the register cache all the time. */
if (r->registers_initialized
&& (!riscv_rtos_enabled(target) || (previous_hartid == hartid))
&& target->reg_cache->reg_list[GDB_REGNO_ZERO].size == (unsigned)riscv_xlen(target)
&& (!riscv_rtos_enabled(target) || (r->rtos_hartid != -1))) {
- return;
+ return ERROR_OK;
} else
LOG_DEBUG("Initializing registers: xlen=%d", riscv_xlen(target));
riscv_invalidate_register_cache(target);
+ return ERROR_OK;
}
void riscv_invalidate_register_cache(struct target *target)
@@ -1797,7 +1820,8 @@ bool riscv_is_halted(struct target *target)
enum riscv_halt_reason riscv_halt_reason(struct target *target, int hartid)
{
RISCV_INFO(r);
- riscv_set_current_hartid(target, hartid);
+ if (riscv_set_current_hartid(target, hartid) != ERROR_OK)
+ return RISCV_HALT_ERROR;
if (!riscv_is_halted(target)) {
LOG_ERROR("Hart is not halted!");
return RISCV_HALT_UNKNOWN;
@@ -2357,6 +2381,72 @@ int riscv_init_registers(struct target *target)
r->exist = riscv_supports_extension(target, riscv_current_hartid(target), 'S') ||
riscv_supports_extension(target, riscv_current_hartid(target), 'N');
break;
+
+ case CSR_CYCLEH:
+ case CSR_TIMEH:
+ case CSR_INSTRETH:
+ case CSR_HPMCOUNTER3H:
+ case CSR_HPMCOUNTER4H:
+ case CSR_HPMCOUNTER5H:
+ case CSR_HPMCOUNTER6H:
+ case CSR_HPMCOUNTER7H:
+ case CSR_HPMCOUNTER8H:
+ case CSR_HPMCOUNTER9H:
+ case CSR_HPMCOUNTER10H:
+ case CSR_HPMCOUNTER11H:
+ case CSR_HPMCOUNTER12H:
+ case CSR_HPMCOUNTER13H:
+ case CSR_HPMCOUNTER14H:
+ case CSR_HPMCOUNTER15H:
+ case CSR_HPMCOUNTER16H:
+ case CSR_HPMCOUNTER17H:
+ case CSR_HPMCOUNTER18H:
+ case CSR_HPMCOUNTER19H:
+ case CSR_HPMCOUNTER20H:
+ case CSR_HPMCOUNTER21H:
+ case CSR_HPMCOUNTER22H:
+ case CSR_HPMCOUNTER23H:
+ case CSR_HPMCOUNTER24H:
+ case CSR_HPMCOUNTER25H:
+ case CSR_HPMCOUNTER26H:
+ case CSR_HPMCOUNTER27H:
+ case CSR_HPMCOUNTER28H:
+ case CSR_HPMCOUNTER29H:
+ case CSR_HPMCOUNTER30H:
+ case CSR_HPMCOUNTER31H:
+ case CSR_MCYCLEH:
+ case CSR_MINSTRETH:
+ case CSR_MHPMCOUNTER3H:
+ case CSR_MHPMCOUNTER4H:
+ case CSR_MHPMCOUNTER5H:
+ case CSR_MHPMCOUNTER6H:
+ case CSR_MHPMCOUNTER7H:
+ case CSR_MHPMCOUNTER8H:
+ case CSR_MHPMCOUNTER9H:
+ case CSR_MHPMCOUNTER10H:
+ case CSR_MHPMCOUNTER11H:
+ case CSR_MHPMCOUNTER12H:
+ case CSR_MHPMCOUNTER13H:
+ case CSR_MHPMCOUNTER14H:
+ case CSR_MHPMCOUNTER15H:
+ case CSR_MHPMCOUNTER16H:
+ case CSR_MHPMCOUNTER17H:
+ case CSR_MHPMCOUNTER18H:
+ case CSR_MHPMCOUNTER19H:
+ case CSR_MHPMCOUNTER20H:
+ case CSR_MHPMCOUNTER21H:
+ case CSR_MHPMCOUNTER22H:
+ case CSR_MHPMCOUNTER23H:
+ case CSR_MHPMCOUNTER24H:
+ case CSR_MHPMCOUNTER25H:
+ case CSR_MHPMCOUNTER26H:
+ case CSR_MHPMCOUNTER27H:
+ case CSR_MHPMCOUNTER28H:
+ case CSR_MHPMCOUNTER29H:
+ case CSR_MHPMCOUNTER30H:
+ case CSR_MHPMCOUNTER31H:
+ r->exist = riscv_xlen(target) == 32;
+ break;
}
if (!r->exist && expose_csr) {
diff --git a/src/target/riscv/riscv.h b/src/target/riscv/riscv.h
index 8e06bd5..63a3b79 100644
--- a/src/target/riscv/riscv.h
+++ b/src/target/riscv/riscv.h
@@ -31,7 +31,8 @@ enum riscv_halt_reason {
RISCV_HALT_BREAKPOINT,
RISCV_HALT_SINGLESTEP,
RISCV_HALT_TRIGGER,
- RISCV_HALT_UNKNOWN
+ RISCV_HALT_UNKNOWN,
+ RISCV_HALT_ERROR
};
typedef struct {
@@ -92,7 +93,7 @@ typedef struct {
riscv_reg_t *value, int hid, int rid);
int (*set_register)(struct target *, int hartid, int regid,
uint64_t value);
- void (*select_current_hart)(struct target *);
+ int (*select_current_hart)(struct target *);
bool (*is_halted)(struct target *target);
int (*halt_current_hart)(struct target *);
int (*resume_current_hart)(struct target *target);
@@ -192,7 +193,7 @@ bool riscv_rtos_enabled(const struct target *target);
/* Sets the current hart, which is the hart that will actually be used when
* issuing debug commands. */
-void riscv_set_current_hartid(struct target *target, int hartid);
+int riscv_set_current_hartid(struct target *target, int hartid);
int riscv_current_hartid(const struct target *target);
/*** Support functions for the RISC-V 'RTOS', which provides multihart support
diff --git a/src/target/startup.tcl b/src/target/startup.tcl
index 9bbc6e3..cf844e1 100644
--- a/src/target/startup.tcl
+++ b/src/target/startup.tcl
@@ -203,6 +203,7 @@ proc init_target_events {} {
foreach t $targets {
set_default_target_event $t gdb-flash-erase-start "reset init"
set_default_target_event $t gdb-flash-write-end "reset halt"
+ set_default_target_event $t gdb-attach "halt"
}
}
diff --git a/src/target/stm8.c b/src/target/stm8.c
index 262497b..4556fd9 100644
--- a/src/target/stm8.c
+++ b/src/target/stm8.c
@@ -477,7 +477,8 @@ static int stm8_examine_debug_reason(struct target *target)
uint8_t csr1, csr2;
retval = stm8_read_dm_csrx(target, &csr1, &csr2);
- LOG_DEBUG("csr1 = 0x%02X csr2 = 0x%02X", csr1, csr2);
+ if (retval == ERROR_OK)
+ LOG_DEBUG("csr1 = 0x%02X csr2 = 0x%02X", csr1, csr2);
if ((target->debug_reason != DBG_REASON_DBGRQ)
&& (target->debug_reason != DBG_REASON_SINGLESTEP)) {
diff --git a/src/target/target.c b/src/target/target.c
index ce7782e..482dc74 100644
--- a/src/target/target.c
+++ b/src/target/target.c
@@ -54,6 +54,7 @@
#include "image.h"
#include "rtos/rtos.h"
#include "transport/transport.h"
+#include "arm_cti.h"
/* default halt wait timeout (ms) */
#define DEFAULT_HALT_TIMEOUT 5000
@@ -512,7 +513,9 @@ struct target *get_target_by_num(int num)
struct target *get_current_target(struct command_context *cmd_ctx)
{
- struct target *target = get_target_by_num(cmd_ctx->current_target);
+ struct target *target = cmd_ctx->current_target_override
+ ? cmd_ctx->current_target_override
+ : cmd_ctx->current_target;
if (target == NULL) {
LOG_ERROR("BUG: current_target out of bounds");
@@ -810,8 +813,7 @@ done:
}
/**
- * Downloads a target-specific native code algorithm to the target,
- * executes and leaves it running.
+ * Executes a target-specific native code algorithm and leaves it running.
*
* @param target used to run the algorithm
* @param arch_info target-specific description of the algorithm.
@@ -884,12 +886,45 @@ done:
}
/**
- * Executes a target-specific native code algorithm in the target.
- * It differs from target_run_algorithm in that the algorithm is asynchronous.
- * Because of this it requires an compliant algorithm:
- * see contrib/loaders/flash/stm32f1x.S for example.
+ * Streams data to a circular buffer on target intended for consumption by code
+ * running asynchronously on target.
+ *
+ * This is intended for applications where target-specific native code runs
+ * on the target, receives data from the circular buffer, does something with
+ * it (most likely writing it to a flash memory), and advances the circular
+ * buffer pointer.
+ *
+ * This assumes that the helper algorithm has already been loaded to the target,
+ * but has not been started yet. Given memory and register parameters are passed
+ * to the algorithm.
+ *
+ * The buffer is defined by (buffer_start, buffer_size) arguments and has the
+ * following format:
+ *
+ * [buffer_start + 0, buffer_start + 4):
+ * Write Pointer address (aka head). Written and updated by this
+ * routine when new data is written to the circular buffer.
+ * [buffer_start + 4, buffer_start + 8):
+ * Read Pointer address (aka tail). Updated by code running on the
+ * target after it consumes data.
+ * [buffer_start + 8, buffer_start + buffer_size):
+ * Circular buffer contents.
+ *
+ * See contrib/loaders/flash/stm32f1x.S for an example.
*
* @param target used to run the algorithm
+ * @param buffer address on the host where data to be sent is located
+ * @param count number of blocks to send
+ * @param block_size size in bytes of each block
+ * @param num_mem_params count of memory-based params to pass to algorithm
+ * @param mem_params memory-based params to pass to algorithm
+ * @param num_reg_params count of register-based params to pass to algorithm
+ * @param reg_params memory-based params to pass to algorithm
+ * @param buffer_start address on the target of the circular buffer structure
+ * @param buffer_size size of the circular buffer structure
+ * @param entry_point address on the target to execute to start the algorithm
+ * @param exit_point address at which to set a breakpoint to catch the
+ * end of the algorithm; can be 0 if target triggers a breakpoint itself
*/
int target_run_flash_async_algorithm(struct target *target,
@@ -1860,8 +1895,26 @@ static void target_destroy(struct target *target)
if (target->type->deinit_target)
target->type->deinit_target(target);
+ jtag_unregister_event_callback(jtag_enable_callback, target);
+
+ struct target_event_action *teap = target->event_action;
+ while (teap) {
+ struct target_event_action *next = teap->next;
+ Jim_DecrRefCount(teap->interp, teap->body);
+ free(teap);
+ teap = next;
+ }
+
+ target_free_all_working_areas(target);
+ /* Now we have none or only one working area marked as free */
+ if (target->working_areas) {
+ free(target->working_areas->backup);
+ free(target->working_areas);
+ }
+
free(target->type);
free(target->trace_info);
+ free(target->fileio_info);
free(target->cmd_name);
free(target);
}
@@ -2475,7 +2528,10 @@ static int find_target(struct command_context *cmd_ctx, const char *name)
return ERROR_FAIL;
}
- cmd_ctx->current_target = target->target_number;
+ cmd_ctx->current_target = target;
+ if (cmd_ctx->current_target_override)
+ cmd_ctx->current_target_override = target;
+
return ERROR_OK;
}
@@ -2503,7 +2559,7 @@ COMMAND_HANDLER(handle_targets_command)
else
state = "tap-disabled";
- if (CMD_CTX->current_target == target->target_number)
+ if (CMD_CTX->current_target == target)
marker = '*';
/* keep columns lined up to match the headers above */
@@ -2920,6 +2976,9 @@ COMMAND_HANDLER(handle_halt_command)
LOG_DEBUG("-");
struct target *target = get_current_target(CMD_CTX);
+
+ target->verbose_halt_msg = true;
+
int retval = target_halt(target);
if (ERROR_OK != retval)
return retval;
@@ -4424,17 +4483,28 @@ void target_handle_event(struct target *target, enum target_event e)
for (teap = target->event_action; teap != NULL; teap = teap->next) {
if (teap->event == e) {
- LOG_DEBUG("target: (%d) %s (%s) event: %d (%s) action: %s",
+ LOG_DEBUG("target(%d): %s (%s) event: %d (%s) action: %s",
target->target_number,
target_name(target),
target_type_name(target),
e,
Jim_Nvp_value2name_simple(nvp_target_event, e)->name,
Jim_GetString(teap->body, NULL));
+
+ /* Override current target by the target an event
+ * is issued from (lot of scripts need it).
+ * Return back to previous override as soon
+ * as the handler processing is done */
+ struct command_context *cmd_ctx = current_command_context(teap->interp);
+ struct target *saved_target_override = cmd_ctx->current_target_override;
+ cmd_ctx->current_target_override = target;
+
if (Jim_EvalObj(teap->interp, teap->body) != JIM_OK) {
Jim_MakeErrorMessage(teap->interp);
command_print(NULL, "%s\n", Jim_GetString(Jim_GetResult(teap->interp), NULL));
}
+
+ cmd_ctx->current_target_override = saved_target_override;
}
}
}
@@ -4464,7 +4534,6 @@ enum target_cfg_param {
TCFG_COREID,
TCFG_CHAIN_POSITION,
TCFG_DBGBASE,
- TCFG_CTIBASE,
TCFG_RTOS,
TCFG_DEFER_EXAMINE,
};
@@ -4480,7 +4549,6 @@ static Jim_Nvp nvp_config_opts[] = {
{ .name = "-coreid", .value = TCFG_COREID },
{ .name = "-chain-position", .value = TCFG_CHAIN_POSITION },
{ .name = "-dbgbase", .value = TCFG_DBGBASE },
- { .name = "-ctibase", .value = TCFG_CTIBASE },
{ .name = "-rtos", .value = TCFG_RTOS },
{ .name = "-defer-examine", .value = TCFG_DEFER_EXAMINE },
{ .name = NULL, .value = -1 }
@@ -4717,6 +4785,13 @@ no_params:
if (goi->isconfigure) {
Jim_Obj *o_t;
struct jtag_tap *tap;
+
+ if (target->has_dap) {
+ Jim_SetResultString(goi->interp,
+ "target requires -dap parameter instead of -chain-position!", -1);
+ return JIM_ERR;
+ }
+
target_free_all_working_areas(target);
e = Jim_GetOpt_Obj(goi, &o_t);
if (e != JIM_OK)
@@ -4724,8 +4799,8 @@ no_params:
tap = jtag_tap_by_jim_obj(goi->interp, o_t);
if (tap == NULL)
return JIM_ERR;
- /* make this exactly 1 or 0 */
target->tap = tap;
+ target->tap_configured = true;
} else {
if (goi->argc != 0)
goto no_params;
@@ -4747,20 +4822,6 @@ no_params:
Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->dbgbase));
/* loop for more */
break;
- case TCFG_CTIBASE:
- if (goi->isconfigure) {
- e = Jim_GetOpt_Wide(goi, &w);
- if (e != JIM_OK)
- return e;
- target->ctibase = (uint32_t)w;
- target->ctibase_set = true;
- } else {
- if (goi->argc != 0)
- goto no_params;
- }
- Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->ctibase));
- /* loop for more */
- break;
case TCFG_RTOS:
/* RTOS */
{
@@ -5512,7 +5573,7 @@ static int target_create(Jim_GetOptInfo *goi)
target = calloc(1, sizeof(struct target));
/* set target number */
target->target_number = new_target_number();
- cmd_ctx->current_target = target->target_number;
+ cmd_ctx->current_target = target;
/* allocate memory for each unique target type */
target->type = calloc(1, sizeof(struct target_type));
@@ -5538,7 +5599,7 @@ static int target_create(Jim_GetOptInfo *goi)
target->next = NULL;
target->arch_info = NULL;
- target->display = 1;
+ target->verbose_halt_msg = true;
target->halt_issued = false;
@@ -5557,9 +5618,21 @@ static int target_create(Jim_GetOptInfo *goi)
goi->isconfigure = 1;
e = target_configure(goi, target);
- if (target->tap == NULL) {
- Jim_SetResultString(goi->interp, "-chain-position required when creating target", -1);
- e = JIM_ERR;
+ if (e == JIM_OK) {
+ if (target->has_dap) {
+ if (!target->dap_configured) {
+ Jim_SetResultString(goi->interp, "-dap ?name? required when creating target", -1);
+ e = JIM_ERR;
+ }
+ } else {
+ if (!target->tap_configured) {
+ Jim_SetResultString(goi->interp, "-chain-position ?name? required when creating target", -1);
+ e = JIM_ERR;
+ }
+ }
+ /* tap must be set after target was configured */
+ if (target->tap == NULL)
+ e = JIM_ERR;
}
if (e != JIM_OK) {
@@ -5576,14 +5649,23 @@ static int target_create(Jim_GetOptInfo *goi)
cp = Jim_GetString(new_cmd, NULL);
target->cmd_name = strdup(cp);
+ if (target->type->target_create) {
+ e = (*(target->type->target_create))(target, goi->interp);
+ if (e != ERROR_OK) {
+ LOG_DEBUG("target_create failed");
+ free(target->type);
+ free(target->cmd_name);
+ free(target);
+ return JIM_ERR;
+ }
+ }
+
/* create the target specific commands */
if (target->type->commands) {
e = register_commands(cmd_ctx, NULL, target->type->commands);
if (ERROR_OK != e)
LOG_ERROR("unable to register '%s' commands", cp);
}
- if (target->type->target_create)
- (*(target->type->target_create))(target, goi->interp);
/* append to end of list */
{
diff --git a/src/target/target.h b/src/target/target.h
index 0096cae..7a8a80f 100644
--- a/src/target/target.h
+++ b/src/target/target.h
@@ -153,7 +153,7 @@ struct target {
struct target_event_action *event_action;
int reset_halt; /* attempt resetting the CPU into the halted mode? */
- uint32_t working_area; /* working area (initialised RAM). Evaluated
+ target_addr_t working_area; /* working area (initialised RAM). Evaluated
* upon first allocation from virtual/physical address. */
bool working_area_virt_spec; /* virtual address specified? */
target_addr_t working_area_virt; /* virtual address */
@@ -176,20 +176,21 @@ struct target {
void *private_config; /* pointer to target specific config data (for jim_configure hook) */
struct target *next; /* next target in list */
- int display; /* display async info in telnet session. Do not display
+ bool verbose_halt_msg; /* display async info in telnet session. Do not display
* lots of halted/resumed info when stepping in debugger. */
bool halt_issued; /* did we transition to halted state? */
int64_t halt_issued_time; /* Note time when halt was issued */
+ /* ARM v7/v8 targets with ADIv5 interface */
bool dbgbase_set; /* By default the debug base is not set */
uint32_t dbgbase; /* Really a Cortex-A specific option, but there is no
* system in place to support target specific options
* currently. */
+ bool has_dap; /* set to true if target has ADIv5 support */
+ bool dap_configured; /* set to true if ADIv5 DAP is configured */
+ bool tap_configured; /* set to true if JTAG tap has been configured
+ * through -chain-position */
- bool ctibase_set; /* By default the debug base is not set */
- uint32_t ctibase; /* Really a Cortex-A specific option, but there is no
- * system in place to support target specific options
- * currently. */
struct rtos *rtos; /* Instance of Real Time Operating System support */
bool rtos_auto_detect; /* A flag that indicates that the RTOS has been specified as "auto"
* and must be detected when symbols are offered */