change #include "binarybuffer.h" to <helper/binarybuffer.h>
[openocd.git] / src / target / armv4_5.c
index 7e5bb0a1716123d703bea9235c2ec80ba358ee72..80c06ef31d355a7c4f5f523b928935a4066ea06c 100644 (file)
@@ -31,7 +31,7 @@
 #include "arm_jtag.h"
 #include "breakpoints.h"
 #include "arm_disassembler.h"
-#include "binarybuffer.h"
+#include <helper/binarybuffer.h>
 #include "algorithm.h"
 #include "register.h"
 
@@ -281,20 +281,20 @@ static const struct {
        { .name = "r11_fiq", .cookie = 11, .mode = ARMV4_5_MODE_FIQ, },
        { .name = "r12_fiq", .cookie = 12, .mode = ARMV4_5_MODE_FIQ, },
 
-       { .name = "lr_fiq", .cookie = 13, .mode = ARMV4_5_MODE_FIQ, },
-       { .name = "sp_fiq", .cookie = 14, .mode = ARMV4_5_MODE_FIQ, },
+       { .name = "sp_fiq", .cookie = 13, .mode = ARMV4_5_MODE_FIQ, },
+       { .name = "lr_fiq", .cookie = 14, .mode = ARMV4_5_MODE_FIQ, },
 
-       { .name = "lr_irq", .cookie = 13, .mode = ARMV4_5_MODE_IRQ, },
-       { .name = "sp_irq", .cookie = 14, .mode = ARMV4_5_MODE_IRQ, },
+       { .name = "sp_irq", .cookie = 13, .mode = ARMV4_5_MODE_IRQ, },
+       { .name = "lr_irq", .cookie = 14, .mode = ARMV4_5_MODE_IRQ, },
 
-       { .name = "lr_svc", .cookie = 13, .mode = ARMV4_5_MODE_SVC, },
-       { .name = "sp_svc", .cookie = 14, .mode = ARMV4_5_MODE_SVC, },
+       { .name = "sp_svc", .cookie = 13, .mode = ARMV4_5_MODE_SVC, },
+       { .name = "lr_svc", .cookie = 14, .mode = ARMV4_5_MODE_SVC, },
 
-       { .name = "lr_abt", .cookie = 13, .mode = ARMV4_5_MODE_ABT, },
-       { .name = "sp_abt", .cookie = 14, .mode = ARMV4_5_MODE_ABT, },
+       { .name = "sp_abt", .cookie = 13, .mode = ARMV4_5_MODE_ABT, },
+       { .name = "lr_abt", .cookie = 14, .mode = ARMV4_5_MODE_ABT, },
 
-       { .name = "lr_und", .cookie = 13, .mode = ARMV4_5_MODE_UND, },
-       { .name = "sp_und", .cookie = 14, .mode = ARMV4_5_MODE_UND, },
+       { .name = "sp_und", .cookie = 13, .mode = ARMV4_5_MODE_UND, },
+       { .name = "lr_und", .cookie = 14, .mode = ARMV4_5_MODE_UND, },
 
        { .name = "cpsr", .cookie = 16, .mode = ARMV4_5_MODE_ANY, },
        { .name = "spsr_fiq", .cookie = 16, .mode = ARMV4_5_MODE_FIQ, },
@@ -303,8 +303,8 @@ static const struct {
        { .name = "spsr_abt", .cookie = 16, .mode = ARMV4_5_MODE_ABT, },
        { .name = "spsr_und", .cookie = 16, .mode = ARMV4_5_MODE_UND, },
 
-       { .name = "lr_mon", .cookie = 13, .mode = ARM_MODE_MON, },
-       { .name = "sp_mon", .cookie = 14, .mode = ARM_MODE_MON, },
+       { .name = "sp_mon", .cookie = 13, .mode = ARM_MODE_MON, },
+       { .name = "lr_mon", .cookie = 14, .mode = ARM_MODE_MON, },
        { .name = "spsr_mon", .cookie = 16, .mode = ARM_MODE_MON, },
 };
 
@@ -390,6 +390,10 @@ void arm_set_cpsr(struct arm *arm, uint32_t cpsr)
                        state = ARMV4_5_STATE_ARM;
        }
        arm->core_state = state;
+
+       LOG_DEBUG("set CPSR %#8.8x: %s mode, %s state", (unsigned) cpsr,
+                       arm_mode_name(mode),
+                       armv4_5_state_strings[arm->core_state]);
 }
 
 /**
@@ -786,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",
@@ -807,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[] = {
@@ -875,7 +1024,13 @@ static int armv4_5_run_algorithm_completion(struct target *target, uint32_t exit
        return ERROR_OK;
 }
 
-int armv4_5_run_algorithm_inner(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info, int (*run_it)(struct target *target, uint32_t exit_point, int timeout_ms, void *arch_info))
+int armv4_5_run_algorithm_inner(struct target *target,
+               int num_mem_params, struct mem_param *mem_params,
+               int num_reg_params, struct reg_param *reg_params,
+               uint32_t entry_point, uint32_t exit_point,
+               int timeout_ms, void *arch_info,
+               int (*run_it)(struct target *target, uint32_t exit_point,
+                               int timeout_ms, void *arch_info))
 {
        struct arm *armv4_5 = target_to_armv4_5(target);
        struct armv4_5_algorithm *armv4_5_algorithm_info = arch_info;
@@ -885,6 +1040,7 @@ int armv4_5_run_algorithm_inner(struct target *target, int num_mem_params, struc
        int exit_breakpoint_size = 0;
        int i;
        int retval = ERROR_OK;
+
        LOG_DEBUG("Running algorithm");
 
        if (armv4_5_algorithm_info->common_magic != ARMV4_5_COMMON_MAGIC)
@@ -1241,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;
@@ -1256,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;
 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)