X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Farmv4_5.c;h=eedbc702d6750792f7cb252e900252ee1524238a;hp=c4637aee4006084cc4e7c82ca30aa3ee90e766ac;hb=aa46b1537792688510717cbbc215da160c2cb665;hpb=257d238e618ead82009058efad7e7a7e7102825a diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index c4637aee40..eedbc702d6 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -27,21 +27,10 @@ #include "config.h" #endif -#include "replacements.h" - -#include "arm_disassembler.h" - #include "armv4_5.h" - -#include "target.h" -#include "register.h" -#include "log.h" +#include "arm_disassembler.h" #include "binarybuffer.h" -#include "command.h" -#include -#include -#include bitfield_desc_t armv4_5_psr_bitfield_desc[] = { @@ -82,7 +71,7 @@ char * armv4_5_mode_strings_list[] = }; /* Hack! Yuk! allow -1 index, which simplifies codepaths elsewhere in the code */ -char** armv4_5_mode_strings = armv4_5_mode_strings_list+1; +char** armv4_5_mode_strings = armv4_5_mode_strings_list + 1; char* armv4_5_state_strings[] = { @@ -164,21 +153,20 @@ int armv4_5_core_reg_map[7][17] = } }; -u8 armv4_5_gdb_dummy_fp_value[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +uint8_t armv4_5_gdb_dummy_fp_value[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; reg_t armv4_5_gdb_dummy_fp_reg = { "GDB dummy floating-point register", armv4_5_gdb_dummy_fp_value, 0, 1, 96, NULL, 0, NULL, 0 }; -u8 armv4_5_gdb_dummy_fps_value[] = {0, 0, 0, 0}; +uint8_t armv4_5_gdb_dummy_fps_value[] = {0, 0, 0, 0}; reg_t armv4_5_gdb_dummy_fps_reg = { "GDB dummy floating-point status register", armv4_5_gdb_dummy_fps_value, 0, 1, 32, NULL, 0, NULL, 0 }; - int armv4_5_get_core_reg(reg_t *reg) { int retval; @@ -197,12 +185,12 @@ int armv4_5_get_core_reg(reg_t *reg) return retval; } -int armv4_5_set_core_reg(reg_t *reg, u8 *buf) +int armv4_5_set_core_reg(reg_t *reg, uint8_t *buf) { armv4_5_core_reg_t *armv4_5 = reg->arch_info; target_t *target = armv4_5->target; armv4_5_common_t *armv4_5_target = target->arch_info; - u32 value = buf_get_u32(buf, 0, 32); + uint32_t value = buf_get_u32(buf, 0, 32); if (target->state != TARGET_HALTED) { @@ -232,7 +220,7 @@ int armv4_5_set_core_reg(reg_t *reg, u8 *buf) } } - if (armv4_5_target->core_mode != (value & 0x1f)) + if (armv4_5_target->core_mode != (enum armv4_5_mode)(value & 0x1f)) { LOG_DEBUG("changing ARM core mode to '%s'", armv4_5_mode_strings[armv4_5_mode_to_number(value & 0x1f)]); armv4_5_target->core_mode = value & 0x1f; @@ -309,9 +297,9 @@ int armv4_5_arch_state(struct target_s *target) exit(-1); } - LOG_USER("target halted in %s state due to %s, current mode: %s\ncpsr: 0x%8.8x pc: 0x%8.8x", + LOG_USER("target halted in %s state due to %s, current mode: %s\ncpsr: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "", armv4_5_state_strings[armv4_5->core_state], - Jim_Nvp_value2name_simple( nvp_target_debug_reason, target->debug_reason )->name, + Jim_Nvp_value2name_simple(nvp_target_debug_reason, target->debug_reason)->name, armv4_5_mode_strings[armv4_5_mode_to_number(armv4_5->core_mode)], buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32), buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32)); @@ -351,12 +339,16 @@ int handle_armv4_5_reg_command(struct command_context_s *cmd_ctx, char *cmd, cha { armv4_5->full_context(target); } - output_len += snprintf(output + output_len, 128 - output_len, "%8s: %8.8x ", ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).name, - buf_get_u32(ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).value, 0, 32)); + output_len += snprintf(output + output_len, + 128 - output_len, + "%8s: %8.8" PRIx32 " ", + ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).name, + buf_get_u32(ARMV4_5_CORE_REG_MODENUM(armv4_5->core_cache, mode, num).value, 0, 32)); } - command_print(cmd_ctx, output); + command_print(cmd_ctx, "%s", output); } - command_print(cmd_ctx, " cpsr: %8.8x spsr_fiq: %8.8x spsr_irq: %8.8x spsr_svc: %8.8x spsr_abt: %8.8x spsr_und: %8.8x", + command_print(cmd_ctx, + " cpsr: %8.8" PRIx32 " spsr_fiq: %8.8" PRIx32 " spsr_irq: %8.8" PRIx32 " spsr_svc: %8.8" PRIx32 " spsr_abt: %8.8" PRIx32 " spsr_und: %8.8" PRIx32 "", buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32), buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_FIQ].value, 0, 32), buf_get_u32(armv4_5->core_cache->reg_list[ARMV4_5_SPSR_IRQ].value, 0, 32), @@ -395,16 +387,19 @@ int handle_armv4_5_core_state_command(struct command_context_s *cmd_ctx, char *c return ERROR_OK; } -int handle_armv4_5_disassemble_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +static int +handle_armv4_5_disassemble_command(struct command_context_s *cmd_ctx, + char *cmd, char **args, int argc) { int retval = ERROR_OK; target_t *target = get_current_target(cmd_ctx); armv4_5_common_t *armv4_5 = target->arch_info; - u32 address; - int count; + uint32_t address; + int count = 1; int i; arm_instruction_t cur_instruction; - u32 opcode; + uint32_t opcode; + uint16_t thumb_opcode; int thumb = 0; if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC) @@ -413,28 +408,54 @@ int handle_armv4_5_disassemble_command(struct command_context_s *cmd_ctx, char * return ERROR_OK; } - if (argc < 2) - { - command_print(cmd_ctx, "usage: armv4_5 disassemble
['thumb']"); + switch (argc) { + case 3: + if (strcmp(args[2], "thumb") != 0) + goto usage; + thumb = 1; + /* FALL THROUGH */ + case 2: + count = strtoul(args[1], NULL, 0); + /* FALL THROUGH */ + case 1: + address = strtoul(args[0], NULL, 0); + if (address & 0x01) { + if (!thumb) { + command_print(cmd_ctx, "Disassemble as Thumb"); + thumb = 1; + } + address &= ~1; + } + break; + default: +usage: + command_print(cmd_ctx, + "usage: armv4_5 disassemble
[ ['thumb']]"); return ERROR_OK; } - address = strtoul(args[0], NULL, 0); - count = strtoul(args[1], NULL, 0); - - if (argc >= 3) - if (strcmp(args[2], "thumb") == 0) - thumb = 1; - for (i = 0; i < count; i++) { - if((retval = target_read_u32(target, address, &opcode)) != ERROR_OK) + if (thumb) { - return retval; + if ((retval = target_read_u16(target, address, &thumb_opcode)) != ERROR_OK) + { + return retval; + } + if ((retval = thumb_evaluate_opcode(thumb_opcode, address, &cur_instruction)) != ERROR_OK) + { + return retval; + } } - if((retval = arm_evaluate_opcode(opcode, address, &cur_instruction)) != ERROR_OK) - { - return retval; + else { + if ((retval = target_read_u32(target, address, &opcode)) != ERROR_OK) + { + return retval; + } + if ((retval = arm_evaluate_opcode(opcode, address, &cur_instruction)) != ERROR_OK) + { + return retval; + } } command_print(cmd_ctx, "%s", cur_instruction.text); address += (thumb) ? 2 : 4; @@ -447,12 +468,20 @@ int armv4_5_register_commands(struct command_context_s *cmd_ctx) { command_t *armv4_5_cmd; - armv4_5_cmd = register_command(cmd_ctx, NULL, "armv4_5", NULL, COMMAND_ANY, "armv4/5 specific commands"); + armv4_5_cmd = register_command(cmd_ctx, NULL, "armv4_5", + NULL, COMMAND_ANY, + "armv4/5 specific commands"); - register_command(cmd_ctx, armv4_5_cmd, "reg", handle_armv4_5_reg_command, COMMAND_EXEC, "display ARM core registers"); - register_command(cmd_ctx, armv4_5_cmd, "core_state", handle_armv4_5_core_state_command, COMMAND_EXEC, "display/change ARM core state "); + register_command(cmd_ctx, armv4_5_cmd, "reg", + handle_armv4_5_reg_command, COMMAND_EXEC, + "display ARM core registers"); + register_command(cmd_ctx, armv4_5_cmd, "core_state", + handle_armv4_5_core_state_command, COMMAND_EXEC, + "display/change ARM core state "); + register_command(cmd_ctx, armv4_5_cmd, "disassemble", + handle_armv4_5_disassemble_command, COMMAND_EXEC, + "disassemble instructions
[ ['thumb']]"); - register_command(cmd_ctx, armv4_5_cmd, "disassemble", handle_armv4_5_disassemble_command, COMMAND_EXEC, "disassemble instructions
['thumb']"); return ERROR_OK; } @@ -484,28 +513,31 @@ int armv4_5_get_gdb_reg_list(target_t *target, reg_t **reg_list[], int *reg_list } /* wait for execution to complete and check exit point */ -static int armv4_5_run_algorithm_completion(struct target_s *target, u32 exit_point, int timeout_ms, void *arch_info) +static int armv4_5_run_algorithm_completion(struct target_s *target, uint32_t exit_point, int timeout_ms, void *arch_info) { int retval; armv4_5_common_t *armv4_5 = target->arch_info; - if((retval = target_wait_state(target, TARGET_HALTED, timeout_ms)) != ERROR_OK) + if ((retval = target_wait_state(target, TARGET_HALTED, timeout_ms)) != ERROR_OK) { return retval; } if (target->state != TARGET_HALTED) { - if ((retval=target_halt(target))!=ERROR_OK) + if ((retval = target_halt(target)) != ERROR_OK) return retval; - if ((retval=target_wait_state(target, TARGET_HALTED, 500))!=ERROR_OK) + if ((retval = target_wait_state(target, TARGET_HALTED, 500)) != ERROR_OK) { return retval; } return ERROR_TARGET_TIMEOUT; } - if (buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32) != exit_point) + + /* fast exit: ARMv5+ code can use BKPT */ + if (exit_point && buf_get_u32(armv4_5->core_cache->reg_list[15].value, + 0, 32) != exit_point) { - LOG_WARNING("target reentered debug state, but not at the desired exit point: 0x%4.4x", + LOG_WARNING("target reentered debug state, but not at the desired exit point: 0x%4.4" PRIx32 "", buf_get_u32(armv4_5->core_cache->reg_list[15].value, 0, 32)); return ERROR_TARGET_TIMEOUT; } @@ -513,14 +545,14 @@ static int armv4_5_run_algorithm_completion(struct target_s *target, u32 exit_po return ERROR_OK; } -int armv4_5_run_algorithm_inner(struct target_s *target, int num_mem_params, mem_param_t *mem_params, int num_reg_params, reg_param_t *reg_params, u32 entry_point, u32 exit_point, int timeout_ms, void *arch_info, int (*run_it)(struct target_s *target, u32 exit_point, int timeout_ms, void *arch_info)) +int armv4_5_run_algorithm_inner(struct target_s *target, int num_mem_params, mem_param_t *mem_params, int num_reg_params, reg_param_t *reg_params, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info, int (*run_it)(struct target_s *target, uint32_t exit_point, int timeout_ms, void *arch_info)) { armv4_5_common_t *armv4_5 = target->arch_info; armv4_5_algorithm_t *armv4_5_algorithm_info = arch_info; enum armv4_5_state core_state = armv4_5->core_state; enum armv4_5_mode core_mode = armv4_5->core_mode; - u32 context[17]; - u32 cpsr; + uint32_t context[17]; + uint32_t cpsr; int exit_breakpoint_size = 0; int i; int retval = ERROR_OK; @@ -541,6 +573,13 @@ int armv4_5_run_algorithm_inner(struct target_s *target, int num_mem_params, mem if (armv4_5_mode_to_number(armv4_5->core_mode)==-1) return ERROR_FAIL; + /* armv5 and later can terminate with BKPT instruction; less overhead */ + if (!exit_point && armv4_5->is_armv4) + { + LOG_ERROR("ARMv4 target needs HW breakpoint location"); + return ERROR_FAIL; + } + for (i = 0; i <= 16; i++) { if (!ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid) @@ -551,7 +590,7 @@ int armv4_5_run_algorithm_inner(struct target_s *target, int num_mem_params, mem for (i = 0; i < num_mem_params; i++) { - if((retval = target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK) + if ((retval = target_write_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK) { return retval; } @@ -572,7 +611,7 @@ int armv4_5_run_algorithm_inner(struct target_s *target, int num_mem_params, mem exit(-1); } - if((retval = armv4_5_set_core_reg(reg, reg_params[i].value)) != ERROR_OK) + if ((retval = armv4_5_set_core_reg(reg, reg_params[i].value)) != ERROR_OK) { return retval; } @@ -597,25 +636,31 @@ int armv4_5_run_algorithm_inner(struct target_s *target, int num_mem_params, mem armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1; } - if ((retval = breakpoint_add(target, exit_point, exit_breakpoint_size, BKPT_HARD)) != ERROR_OK) + /* terminate using a hardware or (ARMv5+) software breakpoint */ + if (exit_point && (retval = breakpoint_add(target, exit_point, + exit_breakpoint_size, BKPT_HARD)) != ERROR_OK) { - LOG_ERROR("can't add breakpoint to finish algorithm execution"); + LOG_ERROR("can't add HW breakpoint to terminate algorithm"); return ERROR_TARGET_FAILURE; } - if((retval = target_resume(target, 0, entry_point, 1, 1)) != ERROR_OK) + if ((retval = target_resume(target, 0, entry_point, 1, 1)) != ERROR_OK) { return retval; } int retvaltemp; - retval=run_it(target, exit_point, timeout_ms, arch_info); + retval = run_it(target, exit_point, timeout_ms, arch_info); + + if (exit_point) + breakpoint_remove(target, exit_point); - breakpoint_remove(target, exit_point); + if (retval != ERROR_OK) + return retval; for (i = 0; i < num_mem_params; i++) { if (mem_params[i].direction != PARAM_OUT) - if((retvaltemp = target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK) + if ((retvaltemp = target_read_buffer(target, mem_params[i].address, mem_params[i].size, mem_params[i].value)) != ERROR_OK) { retval = retvaltemp; } @@ -645,10 +690,15 @@ int armv4_5_run_algorithm_inner(struct target_s *target, int num_mem_params, mem for (i = 0; i <= 16; i++) { - LOG_DEBUG("restoring register %s with value 0x%8.8x", ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).name, context[i]); - buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32, context[i]); - ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid = 1; - ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).dirty = 1; + uint32_t regvalue; + regvalue = buf_get_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32); + if (regvalue != context[i]) + { + LOG_DEBUG("restoring register %s with value 0x%8.8" PRIx32 "", ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).name, context[i]); + buf_set_u32(ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).value, 0, 32, context[i]); + ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).valid = 1; + ARMV4_5_CORE_REG_MODE(armv4_5->core_cache, armv4_5_algorithm_info->core_mode, i).dirty = 1; + } } buf_set_u32(armv4_5->core_cache->reg_list[ARMV4_5_CPSR].value, 0, 32, cpsr); armv4_5->core_cache->reg_list[ARMV4_5_CPSR].valid = 1; @@ -660,8 +710,7 @@ int armv4_5_run_algorithm_inner(struct target_s *target, int num_mem_params, mem return retval; } - -int armv4_5_run_algorithm(struct target_s *target, int num_mem_params, mem_param_t *mem_params, int num_reg_params, reg_param_t *reg_params, u32 entry_point, u32 exit_point, int timeout_ms, void *arch_info) +int armv4_5_run_algorithm(struct target_s *target, int num_mem_params, mem_param_t *mem_params, int num_reg_params, reg_param_t *reg_params, uint32_t entry_point, uint32_t exit_point, int timeout_ms, void *arch_info) { return armv4_5_run_algorithm_inner(target, num_mem_params, mem_params, num_reg_params, reg_params, entry_point, exit_point, timeout_ms, arch_info, armv4_5_run_algorithm_completion); }