diff --git a/src/target/arm11.c b/src/target/arm11.c
index daba3b847..30dbedb93 100644
--- a/src/target/arm11.c
+++ b/src/target/arm11.c
@@ -1219,6 +1219,13 @@ static int arm11_remove_watchpoint(struct target *target,
return ERROR_FAIL;
}
+static int arm11_mrc(struct target *target, int cpnum,
+ uint32_t op1, uint32_t op2,
+ uint32_t CRn, uint32_t CRm, uint32_t *value);
+static int arm11_mcr(struct target *target, int cpnum,
+ uint32_t op1, uint32_t op2, uint32_t CRn,
+ uint32_t CRm, uint32_t value);
+
static int arm11_target_create(struct target *target, Jim_Interp *interp)
{
struct arm11_common *arm11;
@@ -1238,6 +1245,9 @@ static int arm11_target_create(struct target *target, Jim_Interp *interp)
armv4_5_init_arch_info(target, &arm11->arm);
+ arm11->arm.mrc = arm11_mrc;
+ arm11->arm.mcr = arm11_mcr;
+
arm11->target = target;
arm11->jtag_info.tap = target->tap;
@@ -1679,7 +1689,4 @@ struct target_type arm11_target = {
.target_create = arm11_target_create,
.init_target = arm11_init_target,
.examine = arm11_examine,
-
- .mrc = arm11_mrc,
- .mcr = arm11_mcr,
};
diff --git a/src/target/arm720t.c b/src/target/arm720t.c
index bae2561ae..d900d8ae2 100644
--- a/src/target/arm720t.c
+++ b/src/target/arm720t.c
@@ -378,11 +378,24 @@ static int arm720t_init_target(struct command_context *cmd_ctx, struct target *t
return arm7tdmi_init_target(cmd_ctx, target);
}
+/* FIXME remove forward decls */
+static int arm720t_mrc(struct target *target, int cpnum,
+ uint32_t op1, uint32_t op2,
+ uint32_t CRn, uint32_t CRm,
+ uint32_t *value);
+static int arm720t_mcr(struct target *target, int cpnum,
+ uint32_t op1, uint32_t op2,
+ uint32_t CRn, uint32_t CRm,
+ uint32_t value);
+
static int arm720t_init_arch_info(struct target *target,
struct arm720t_common *arm720t, struct jtag_tap *tap)
{
struct arm7_9_common *arm7_9 = &arm720t->arm7_9_common;
+ arm7_9->armv4_5_common.mrc = arm720t_mrc;
+ arm7_9->armv4_5_common.mcr = arm720t_mcr;
+
arm7tdmi_init_arch_info(target, arm7_9, tap);
arm720t->common_magic = ARM720T_COMMON_MAGIC;
@@ -556,6 +569,4 @@ struct target_type arm720t_target =
.target_create = arm720t_target_create,
.init_target = arm720t_init_target,
.examine = arm7_9_examine,
- .mrc = arm720t_mrc,
- .mcr = arm720t_mcr,
};
diff --git a/src/target/arm920t.c b/src/target/arm920t.c
index e6c2eed82..17e7a55ae 100644
--- a/src/target/arm920t.c
+++ b/src/target/arm920t.c
@@ -624,10 +624,23 @@ int arm920t_soft_reset_halt(struct target *target)
return ERROR_OK;
}
+/* FIXME remove forward decls */
+static int arm920t_mrc(struct target *target, int cpnum,
+ uint32_t op1, uint32_t op2,
+ uint32_t CRn, uint32_t CRm,
+ uint32_t *value);
+static int arm920t_mcr(struct target *target, int cpnum,
+ uint32_t op1, uint32_t op2,
+ uint32_t CRn, uint32_t CRm,
+ uint32_t value);
+
int arm920t_init_arch_info(struct target *target, struct arm920t_common *arm920t, struct jtag_tap *tap)
{
struct arm7_9_common *arm7_9 = &arm920t->arm7_9_common;
+ arm7_9->armv4_5_common.mrc = arm920t_mrc;
+ arm7_9->armv4_5_common.mcr = arm920t_mcr;
+
/* initialize arm7/arm9 specific info (including armv4_5) */
arm9tdmi_init_arch_info(target, arm7_9, tap);
@@ -1452,6 +1465,4 @@ struct target_type arm920t_target =
.target_create = arm920t_target_create,
.init_target = arm9tdmi_init_target,
.examine = arm7_9_examine,
- .mrc = arm920t_mrc,
- .mcr = arm920t_mcr,
};
diff --git a/src/target/arm926ejs.c b/src/target/arm926ejs.c
index 408ede9de..ca420aa69 100644
--- a/src/target/arm926ejs.c
+++ b/src/target/arm926ejs.c
@@ -673,6 +673,9 @@ int arm926ejs_init_arch_info(struct target *target, struct arm926ejs_common *arm
{
struct arm7_9_common *arm7_9 = &arm926ejs->arm7_9_common;
+ arm7_9->armv4_5_common.mrc = arm926ejs_mrc;
+ arm7_9->armv4_5_common.mcr = arm926ejs_mcr;
+
/* initialize arm7/arm9 specific info (including armv4_5) */
arm9tdmi_init_arch_info(target, arm7_9, tap);
@@ -822,6 +825,4 @@ struct target_type arm926ejs_target =
.read_phys_memory = arm926ejs_read_phys_memory,
.write_phys_memory = arm926ejs_write_phys_memory,
- .mrc = arm926ejs_mrc,
- .mcr = arm926ejs_mcr,
};
diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c
index b5e33ff54..d047b1b6f 100644
--- a/src/target/armv4_5.c
+++ b/src/target/armv4_5.c
@@ -790,6 +790,137 @@ usage:
return retval;
}
+static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ struct command_context *context;
+ struct target *target;
+ struct arm *arm;
+ int retval;
+
+ context = Jim_GetAssocData(interp, "context");
+ if (context == NULL) {
+ LOG_ERROR("%s: no command context", __func__);
+ return JIM_ERR;
+ }
+ target = get_current_target(context);
+ if (target == NULL) {
+ LOG_ERROR("%s: no current target", __func__);
+ return JIM_ERR;
+ }
+ if (!target_was_examined(target)) {
+ LOG_ERROR("%s: not yet examined", target_name(target));
+ return JIM_ERR;
+ }
+ arm = target_to_arm(target);
+ if (!is_arm(arm)) {
+ LOG_ERROR("%s: not an ARM", target_name(target));
+ return JIM_ERR;
+ }
+
+ if ((argc < 6) || (argc > 7)) {
+ /* FIXME use the command name to verify # params... */
+ LOG_ERROR("%s: wrong number of arguments", __func__);
+ return JIM_ERR;
+ }
+
+ int cpnum;
+ uint32_t op1;
+ uint32_t op2;
+ uint32_t CRn;
+ uint32_t CRm;
+ uint32_t value;
+ long l;
+
+ /* NOTE: parameter sequence matches ARM instruction set usage:
+ * MCR pNUM, op1, rX, CRn, CRm, op2 ; write CP from rX
+ * MRC pNUM, op1, rX, CRn, CRm, op2 ; read CP into rX
+ * The "rX" is necessarily omitted; it uses Tcl mechanisms.
+ */
+ retval = Jim_GetLong(interp, argv[1], &l);
+ if (retval != JIM_OK)
+ return retval;
+ if (l & ~0xf) {
+ LOG_ERROR("%s: %s %d out of range", __func__,
+ "coprocessor", (int) l);
+ return JIM_ERR;
+ }
+ cpnum = l;
+
+ retval = Jim_GetLong(interp, argv[2], &l);
+ if (retval != JIM_OK)
+ return retval;
+ if (l & ~0x7) {
+ LOG_ERROR("%s: %s %d out of range", __func__,
+ "op1", (int) l);
+ return JIM_ERR;
+ }
+ op1 = l;
+
+ retval = Jim_GetLong(interp, argv[3], &l);
+ if (retval != JIM_OK)
+ return retval;
+ if (l & ~0xf) {
+ LOG_ERROR("%s: %s %d out of range", __func__,
+ "CRn", (int) l);
+ return JIM_ERR;
+ }
+ CRn = l;
+
+ retval = Jim_GetLong(interp, argv[4], &l);
+ if (retval != JIM_OK)
+ return retval;
+ if (l & ~0xf) {
+ LOG_ERROR("%s: %s %d out of range", __func__,
+ "CRm", (int) l);
+ return JIM_ERR;
+ }
+ CRm = l;
+
+ retval = Jim_GetLong(interp, argv[5], &l);
+ if (retval != JIM_OK)
+ return retval;
+ if (l & ~0x7) {
+ LOG_ERROR("%s: %s %d out of range", __func__,
+ "op2", (int) l);
+ return JIM_ERR;
+ }
+ op2 = l;
+
+ value = 0;
+
+ /* FIXME don't assume "mrc" vs "mcr" from the number of params;
+ * that could easily be a typo! Check both...
+ *
+ * FIXME change the call syntax here ... simplest to just pass
+ * the MRC() or MCR() instruction to be executed. That will also
+ * let us support the "mrc2" and "mcr2" opcodes (toggling one bit)
+ * if that's ever needed.
+ */
+ if (argc == 7) {
+ retval = Jim_GetLong(interp, argv[6], &l);
+ if (retval != JIM_OK) {
+ return retval;
+ }
+ value = l;
+
+ /* NOTE: parameters reordered! */
+ // ARMV4_5_MCR(cpnum, op1, 0, CRn, CRm, op2)
+ retval = arm->mcr(target, cpnum, op1, op2, CRn, CRm, value);
+ if (retval != ERROR_OK)
+ return JIM_ERR;
+ } else {
+ /* NOTE: parameters reordered! */
+ // ARMV4_5_MRC(cpnum, op1, 0, CRn, CRm, op2)
+ retval = arm->mrc(target, cpnum, op1, op2, CRn, CRm, &value);
+ if (retval != ERROR_OK)
+ return JIM_ERR;
+
+ Jim_SetResult(interp, Jim_NewIntObj(interp, value));
+ }
+
+ return JIM_OK;
+}
+
static const struct command_registration arm_exec_command_handlers[] = {
{
.name = "reg",
@@ -811,6 +942,20 @@ static const struct command_registration arm_exec_command_handlers[] = {
.usage = "
[ ['thumb']]",
.help = "disassemble instructions ",
},
+ {
+ .name = "mcr",
+ .mode = COMMAND_EXEC,
+ .jim_handler = &jim_mcrmrc,
+ .help = "write coprocessor register",
+ .usage = "cpnum op1 CRn op2 CRm value",
+ },
+ {
+ .name = "mrc",
+ .jim_handler = &jim_mcrmrc,
+ .help = "read coprocessor register",
+ .usage = "cpnum op1 CRn op2 CRm",
+ },
+
COMMAND_REGISTRATION_DONE
};
const struct command_registration arm_command_handlers[] = {
@@ -1252,6 +1397,24 @@ static int arm_full_context(struct target *target)
return retval;
}
+static int arm_default_mrc(struct target *target, int cpnum,
+ uint32_t op1, uint32_t op2,
+ uint32_t CRn, uint32_t CRm,
+ uint32_t *value)
+{
+ LOG_ERROR("%s doesn't implement MRC", target_type_name(target));
+ return ERROR_FAIL;
+}
+
+static int arm_default_mcr(struct target *target, int cpnum,
+ uint32_t op1, uint32_t op2,
+ uint32_t CRn, uint32_t CRm,
+ uint32_t value)
+{
+ LOG_ERROR("%s doesn't implement MCR", target_type_name(target));
+ return ERROR_FAIL;
+}
+
int armv4_5_init_arch_info(struct target *target, struct arm *armv4_5)
{
target->arch_info = armv4_5;
@@ -1267,5 +1430,10 @@ int armv4_5_init_arch_info(struct target *target, struct arm *armv4_5)
if (!armv4_5->full_context && armv4_5->read_core_reg)
armv4_5->full_context = arm_full_context;
+ if (!armv4_5->mrc)
+ armv4_5->mrc = arm_default_mrc;
+ if (!armv4_5->mcr)
+ armv4_5->mcr = arm_default_mcr;
+
return ERROR_OK;
}
diff --git a/src/target/armv4_5.h b/src/target/armv4_5.h
index 822d14393..7229a6c0b 100644
--- a/src/target/armv4_5.h
+++ b/src/target/armv4_5.h
@@ -112,11 +112,26 @@ struct arm
/** Handle for the Embedded Trace Module, if one is present. */
struct etm_context *etm;
+ /* FIXME all these methods should take "struct arm *" not target */
+
int (*full_context)(struct target *target);
int (*read_core_reg)(struct target *target, struct reg *reg,
int num, enum armv4_5_mode mode);
int (*write_core_reg)(struct target *target, struct reg *reg,
int num, enum armv4_5_mode mode, uint32_t value);
+
+ /** Read coprocessor register. */
+ int (*mrc)(struct target *target, int cpnum,
+ uint32_t op1, uint32_t op2,
+ uint32_t CRn, uint32_t CRm,
+ uint32_t *value);
+
+ /* Write coprocessor register. */
+ int (*mcr)(struct target *target, int cpnum,
+ uint32_t op1, uint32_t op2,
+ uint32_t CRn, uint32_t CRm,
+ uint32_t value);
+
void *arch_info;
};
diff --git a/src/target/cortex_a8.c b/src/target/cortex_a8.c
index 652efa935..9ce6b2bad 100644
--- a/src/target/cortex_a8.c
+++ b/src/target/cortex_a8.c
@@ -936,7 +936,7 @@ static void cortex_a8_post_debug_entry(struct target *target)
int retval;
/* MRC p15,0,