X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Farmv4_5.c;h=1886d5e1f6a612847402446d7dd40cfe44e2e12a;hp=09cf143e65858be82bb67922dfa6452bbb9ee972;hb=HEAD;hpb=dee7b7d8212dbe94d5afd6bba736de4fcd1a05ac diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index 09cf143e65..1886d5e1f6 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -1,4 +1,4 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ +// SPDX-License-Identifier: GPL-2.0-or-later /*************************************************************************** * Copyright (C) 2005 by Dominic Rath * @@ -535,7 +535,7 @@ static struct reg_feature arm_gdb_dummy_fp_features = { * Modern ARM cores use Vector Floating Point (VFP), if they * have any floating point support. VFP is not FPA-compatible. */ -struct reg arm_gdb_dummy_fp_reg = { +static struct reg arm_gdb_dummy_fp_reg = { .name = "GDB dummy FPA register", .value = (uint8_t *) arm_gdb_dummy_fp_value, .valid = true, @@ -552,7 +552,7 @@ static const uint8_t arm_gdb_dummy_fps_value[4]; * Dummy FPA status registers are required to support GDB on ARM. * Register packets require an obsolete FPA status register. */ -struct reg arm_gdb_dummy_fps_reg = { +static struct reg arm_gdb_dummy_fps_reg = { .name = "GDB dummy FPA status register", .value = (uint8_t *) arm_gdb_dummy_fps_value, .valid = true, @@ -578,7 +578,7 @@ static int armv4_5_get_core_reg(struct reg *reg) struct target *target = reg_arch_info->target; if (target->state != TARGET_HALTED) { - LOG_ERROR("Target not halted"); + LOG_TARGET_ERROR(target, "not halted"); return ERROR_TARGET_NOT_HALTED; } @@ -600,7 +600,7 @@ static int armv4_5_set_core_reg(struct reg *reg, uint8_t *buf) uint32_t value = buf_get_u32(buf, 0, 32); if (target->state != TARGET_HALTED) { - LOG_ERROR("Target not halted"); + LOG_TARGET_ERROR(target, "not halted"); return ERROR_TARGET_NOT_HALTED; } @@ -817,8 +817,8 @@ COMMAND_HANDLER(handle_armv4_5_reg_command) } if (target->state != TARGET_HALTED) { - command_print(CMD, "error: target must be halted for register accesses"); - return ERROR_FAIL; + command_print(CMD, "Error: target must be halted for register accesses"); + return ERROR_TARGET_NOT_HALTED; } if (arm->core_type != ARM_CORE_TYPE_STD) { @@ -833,7 +833,7 @@ COMMAND_HANDLER(handle_armv4_5_reg_command) } if (!arm->full_context) { - command_print(CMD, "error: target doesn't support %s", + command_print(CMD, "Error: target doesn't support %s", CMD_NAME); return ERROR_FAIL; } @@ -989,35 +989,38 @@ COMMAND_HANDLER(handle_arm_disassemble_command) #endif } -static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv) +COMMAND_HANDLER(handle_armv4_5_mcrmrc) { - struct command_context *context; - struct target *target; - struct arm *arm; - int retval; + bool is_mcr = false; + unsigned int arg_cnt = 5; + + if (!strcmp(CMD_NAME, "mcr")) { + is_mcr = true; + arg_cnt = 6; + } - context = current_command_context(interp); - assert(context); + if (arg_cnt != CMD_ARGC) + return ERROR_COMMAND_SYNTAX_ERROR; - target = get_current_target(context); + struct target *target = get_current_target(CMD_CTX); if (!target) { - LOG_ERROR("%s: no current target", __func__); - return JIM_ERR; + command_print(CMD, "no current target"); + return ERROR_FAIL; } if (!target_was_examined(target)) { - LOG_ERROR("%s: not yet examined", target_name(target)); - return JIM_ERR; + command_print(CMD, "%s: not yet examined", target_name(target)); + return ERROR_TARGET_NOT_EXAMINED; } - arm = target_to_arm(target); + + struct arm *arm = target_to_arm(target); if (!is_arm(arm)) { - LOG_ERROR("%s: not an ARM", target_name(target)); - return JIM_ERR; + command_print(CMD, "%s: not an ARM", target_name(target)); + return ERROR_FAIL; } - if ((argc < 6) || (argc > 7)) { - /* FIXME use the command name to verify # params... */ - LOG_ERROR("%s: wrong number of arguments", __func__); - return JIM_ERR; + if (target->state != TARGET_HALTED) { + command_print(CMD, "Error: [%s] not halted", target_name(target)); + return ERROR_TARGET_NOT_HALTED; } int cpnum; @@ -1026,95 +1029,156 @@ static int jim_mcrmrc(Jim_Interp *interp, int argc, Jim_Obj * const *argv) 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; + 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; } - 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; + 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; } - 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; + 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; } - 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; + 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; } - 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; + 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; } - 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; + if (is_mcr) { + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[5], value); /* NOTE: parameters reordered! */ /* ARMV4_5_MCR(cpnum, op1, 0, crn, crm, op2) */ - retval = arm->mcr(target, cpnum, op1, op2, crn, crm, value); + int retval = arm->mcr(target, cpnum, op1, op2, crn, crm, value); if (retval != ERROR_OK) - return JIM_ERR; + return retval; } else { + value = 0; /* NOTE: parameters reordered! */ /* ARMV4_5_MRC(cpnum, op1, 0, crn, crm, op2) */ - retval = arm->mrc(target, cpnum, op1, op2, crn, crm, &value); + int retval = arm->mrc(target, cpnum, op1, op2, crn, crm, &value); + if (retval != ERROR_OK) + return retval; + + command_print(CMD, "0x%" PRIx32, value); + } + + return ERROR_OK; +} + +COMMAND_HANDLER(handle_armv4_5_mcrrmrrc) +{ + bool is_mcrr = false; + unsigned int arg_cnt = 3; + + if (!strcmp(CMD_NAME, "mcrr")) { + is_mcrr = true; + arg_cnt = 4; + } + + if (arg_cnt != CMD_ARGC) + return ERROR_COMMAND_SYNTAX_ERROR; + + struct target *target = get_current_target(CMD_CTX); + if (!target) { + command_print(CMD, "no current target"); + return ERROR_FAIL; + } + if (!target_was_examined(target)) { + command_print(CMD, "%s: not yet examined", target_name(target)); + return ERROR_TARGET_NOT_EXAMINED; + } + + 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) + return ERROR_TARGET_NOT_HALTED; + + int cpnum; + uint32_t op1; + uint32_t crm; + uint64_t value; + + /* NOTE: parameter sequence matches ARM instruction set usage: + * MCRR pNUM, op1, rX1, rX2, CRm ; write CP from rX1 and rX2 + * MREC pNUM, op1, rX1, rX2, CRm ; read CP into rX1 and rX2 + * The "rXn" are necessarily omitted; they use 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 & ~0xf) { + command_print(CMD, "op1 %d out of range", op1); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], crm); + if (crm & ~0xf) { + command_print(CMD, "CRm %d out of range", crm); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + + /* + * 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 "mrrc2" and "mcrr2" opcodes (toggling one bit) + * if that's ever needed. + */ + if (is_mcrr) { + COMMAND_PARSE_NUMBER(u64, CMD_ARGV[3], value); + + /* NOTE: parameters reordered! */ + /* ARMV5_T_MCRR(cpnum, op1, crm) */ + int retval = arm->mcrr(target, cpnum, op1, crm, value); if (retval != ERROR_OK) - return JIM_ERR; + return retval; + } else { + value = 0; + /* NOTE: parameters reordered! */ + /* ARMV5_T_MRRC(cpnum, op1, crm) */ + int retval = arm->mrrc(target, cpnum, op1, crm, &value); + if (retval != ERROR_OK) + return retval; - Jim_SetResult(interp, Jim_NewIntObj(interp, value)); + command_print(CMD, "0x%" PRIx64, value); } - return JIM_OK; + return ERROR_OK; } static const struct command_registration arm_exec_command_handlers[] = { @@ -1125,6 +1189,41 @@ static const struct command_registration arm_exec_command_handlers[] = { .help = "display ARM core registers", .usage = "", }, + { + .name = "mcr", + .mode = COMMAND_EXEC, + .handler = handle_armv4_5_mcrmrc, + .help = "write coprocessor register", + .usage = "cpnum op1 CRn CRm op2 value", + }, + { + .name = "mrc", + .mode = COMMAND_EXEC, + .handler = handle_armv4_5_mcrmrc, + .help = "read coprocessor register", + .usage = "cpnum op1 CRn CRm op2", + }, + { + .name = "mcrr", + .mode = COMMAND_EXEC, + .handler = handle_armv4_5_mcrrmrrc, + .help = "write coprocessor 64-bit register", + .usage = "cpnum op1 CRm value", + }, + { + .name = "mrrc", + .mode = COMMAND_EXEC, + .handler = handle_armv4_5_mcrrmrrc, + .help = "read coprocessor 64-bit register", + .usage = "cpnum op1 CRm", + }, + { + .chain = arm_all_profiles_command_handlers, + }, + COMMAND_REGISTRATION_DONE +}; + +const struct command_registration arm_all_profiles_command_handlers[] = { { .name = "core_state", .handler = handle_arm_core_state_command, @@ -1139,25 +1238,12 @@ 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 CRm op2 value", - }, - { - .name = "mrc", - .mode = COMMAND_EXEC, - .jim_handler = &jim_mcrmrc, - .help = "read coprocessor register", - .usage = "cpnum op1 CRn CRm op2", - }, { .chain = semihosting_common_handlers, }, COMMAND_REGISTRATION_DONE }; + const struct command_registration arm_command_handlers[] = { { .name = "arm", @@ -1178,7 +1264,7 @@ const struct command_registration arm_command_handlers[] = { * same way as a gdb for arm. This can be changed later on. User can still * set the specific architecture variant with the gdb command. */ -const char *arm_get_gdb_arch(struct target *target) +const char *arm_get_gdb_arch(const struct target *target) { return "arm"; } @@ -1270,7 +1356,7 @@ int arm_get_gdb_reg_list(struct target *target, /* wait for execution to complete and check exit point */ static int armv4_5_run_algorithm_completion(struct target *target, uint32_t exit_point, - int timeout_ms, + unsigned int timeout_ms, void *arch_info) { int retval; @@ -1304,9 +1390,9 @@ 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, + unsigned int timeout_ms, void *arch_info, int (*run_it)(struct target *target, uint32_t exit_point, - int timeout_ms, void *arch_info)) + unsigned int timeout_ms, void *arch_info)) { struct arm *arm = target_to_arm(target); struct arm_algorithm *arm_algorithm_info = arch_info; @@ -1325,7 +1411,7 @@ int armv4_5_run_algorithm_inner(struct target *target, } if (target->state != TARGET_HALTED) { - LOG_WARNING("target not halted"); + LOG_TARGET_ERROR(target, "not halted (run target algo)"); return ERROR_TARGET_NOT_HALTED; } @@ -1492,7 +1578,7 @@ int armv4_5_run_algorithm(struct target *target, struct reg_param *reg_params, target_addr_t entry_point, target_addr_t exit_point, - int timeout_ms, + unsigned int timeout_ms, void *arch_info) { return armv4_5_run_algorithm_inner(target, @@ -1553,7 +1639,7 @@ int arm_checksum_memory(struct target *target, buf_set_u32(reg_params[1].value, 0, 32, count); /* 20 second timeout/megabyte */ - int timeout = 20000 * (1 + (count / (1024 * 1024))); + unsigned int timeout = 20000 * (1 + (count / (1024 * 1024))); /* armv4 must exit using a hardware breakpoint */ if (arm->arch == ARM_ARCH_V4) @@ -1685,6 +1771,14 @@ static int arm_default_mrc(struct target *target, int cpnum, return ERROR_FAIL; } +static int arm_default_mrrc(struct target *target, int cpnum, + uint32_t op, uint32_t crm, + uint64_t *value) +{ + LOG_ERROR("%s doesn't implement MRRC", 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, @@ -1694,6 +1788,14 @@ static int arm_default_mcr(struct target *target, int cpnum, return ERROR_FAIL; } +static int arm_default_mcrr(struct target *target, int cpnum, + uint32_t op, uint32_t crm, + uint64_t value) +{ + LOG_ERROR("%s doesn't implement MCRR", target_type_name(target)); + return ERROR_FAIL; +} + int arm_init_arch_info(struct target *target, struct arm *arm) { target->arch_info = arm; @@ -1713,8 +1815,12 @@ int arm_init_arch_info(struct target *target, struct arm *arm) if (!arm->mrc) arm->mrc = arm_default_mrc; + if (!arm->mrrc) + arm->mrrc = arm_default_mrrc; if (!arm->mcr) arm->mcr = arm_default_mcr; + if (!arm->mcrr) + arm->mcrr = arm_default_mcrr; return ERROR_OK; }