summaryrefslogtreecommitdiff
path: root/src/target/armv4_5.c
diff options
context:
space:
mode:
authorDavid Brownell <dbrownell@users.sourceforge.net>2009-12-01 00:48:53 -0800
committerDavid Brownell <dbrownell@users.sourceforge.net>2009-12-01 00:48:53 -0800
commit177bbd8891ae737ea7f8c0791a6236f72cedee40 (patch)
treeceeef8ae2d729eb5c3d539249f13f019fa300d7c /src/target/armv4_5.c
parent209a0197f0c79442a2314199170a957c36c0ddb6 (diff)
downloadopenocd+libswd-177bbd8891ae737ea7f8c0791a6236f72cedee40.tar.gz
openocd+libswd-177bbd8891ae737ea7f8c0791a6236f72cedee40.tar.bz2
openocd+libswd-177bbd8891ae737ea7f8c0791a6236f72cedee40.tar.xz
openocd+libswd-177bbd8891ae737ea7f8c0791a6236f72cedee40.zip
target: "mcr" and "mrc" are ARM-specific
Switch "mrc" and "mcr" commands to be toplevel ARM operations, as they should initially have been. Correct the usage message for both commands: it matches ARM documentation (as one wants!) instead of reordering them to match the funky mrc() and mcr() method usage (sigh). For Cortex-A8: restore a line that got accidentally dropped, so the secure monitor mode shadow registers will show again. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Diffstat (limited to 'src/target/armv4_5.c')
-rw-r--r--src/target/armv4_5.c168
1 files changed, 168 insertions, 0 deletions
diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c
index b5e33ff5..d047b1b6 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 = "<address> [<count> ['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;
}