+ struct arm *arm = target_to_arm(target);
+ if (!is_arm(arm)) {
+ command_print(CMD, "%s: not an ARM", target_name(target));
+ return ERROR_FAIL;
+ }
+
+ if (target->state != TARGET_HALTED) {
+ command_print(CMD, "Error: [%s] not halted", target_name(target));
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+ if (arm->core_state == ARM_STATE_AARCH64) {
+ command_print(CMD, "%s: not 32-bit arm target", target_name(target));
+ return ERROR_FAIL;
+ }
+
+ int cpnum;
+ uint32_t op1;
+ uint32_t op2;
+ uint32_t crn;
+ uint32_t crm;
+ uint32_t value;
+
+ /* 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.
+ */
+ COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], cpnum);
+ if (cpnum & ~0xf) {
+ command_print(CMD, "coprocessor %d out of range", cpnum);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], op1);
+ if (op1 & ~0x7) {
+ command_print(CMD, "op1 %d out of range", op1);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], crn);
+ if (crn & ~0xf) {
+ command_print(CMD, "CRn %d out of range", crn);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], crm);
+ if (crm & ~0xf) {
+ command_print(CMD, "CRm %d out of range", crm);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[4], op2);
+ if (op2 & ~0x7) {
+ command_print(CMD, "op2 %d out of range", op2);
+ return ERROR_COMMAND_ARGUMENT_INVALID;
+ }
+
+ if (is_mcr) {
+ COMMAND_PARSE_NUMBER(u32, CMD_ARGV[5], value);
+
+ /* NOTE: parameters reordered! */
+ /* ARMV4_5_MCR(cpnum, op1, 0, crn, crm, op2) */
+ int retval = arm->mcr(target, cpnum, op1, op2, crn, crm, value);
+ if (retval != ERROR_OK)
+ return retval;
+ } else {
+ value = 0;
+ /* NOTE: parameters reordered! */
+ /* ARMV4_5_MRC(cpnum, op1, 0, crn, crm, op2) */
+ int retval = arm->mrc(target, cpnum, op1, op2, crn, crm, &value);
+ if (retval != ERROR_OK)
+ return retval;
+
+ command_print(CMD, "0x%" PRIx32, value);