From cad39b73904dfe8f5270603aa54a628e59f507d3 Mon Sep 17 00:00:00 2001 From: Kamal Dasu Date: Fri, 23 Feb 2018 13:01:53 -0500 Subject: [PATCH] target: aarch64: Adding mcr, mrc 32-bit coprocesor read/write support Adding mrc and mcr support for 32-bit boot mode on aarch64 target. Change-Id: I3879908253ccdf79509dcad752871f422526ec64 Signed-off-by: Kamal Dasu Reviewed-on: http://openocd.zylin.com/4483 Tested-by: jenkins Reviewed-by: Matthias Welwarsky --- src/target/aarch64.c | 153 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index cd835027..df1e49c2 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -2590,6 +2590,143 @@ COMMAND_HANDLER(aarch64_mask_interrupts_command) return ERROR_OK; } +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; + bool is_mcr = false; + int arg_cnt = 0; + + if (Jim_CompareStringImmediate(interp, argv[0], "mcr")) { + is_mcr = true; + arg_cnt = 7; + } else { + arg_cnt = 6; + } + + context = current_command_context(interp); + assert(context != NULL); + + 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 (target->state != TARGET_HALTED) + return ERROR_TARGET_NOT_HALTED; + + if (arm->core_state == ARM_STATE_AARCH64) { + LOG_ERROR("%s: not 32-bit arm target", target_name(target)); + return JIM_ERR; + } + + if (argc != arg_cnt) { + 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; + + if (is_mcr == true) { + 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 aarch64_exec_command_handlers[] = { { .name = "cache_info", @@ -2625,9 +2762,25 @@ static const struct command_registration aarch64_exec_command_handlers[] = { .help = "mask aarch64 interrupts during single-step", .usage = "['on'|'off']", }, + { + .name = "mcr", + .mode = COMMAND_EXEC, + .jim_handler = jim_mcrmrc, + .help = "write coprocessor register", + .usage = "cpnum op1 CRn CRm op2 value", + }, + { + .name = "mrc", + .mode = COMMAND_EXEC, + .jim_handler = jim_mcrmrc, + .help = "read coprocessor register", + .usage = "cpnum op1 CRn CRm op2", + }, + COMMAND_REGISTRATION_DONE }; + static const struct command_registration aarch64_command_handlers[] = { { .chain = armv8_command_handlers, -- 2.39.5