X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Farmv7a.c;h=f0679260fc9b7cabe7f9eb59a6aa949ceb077f12;hp=547a33bb1ed4689875547a1300d20ba33a86e277;hb=cfc4d5c6b7b6f8f82dc5bbf3ee661c179814666e;hpb=7a1ac49ac921964f48e0bbd9e1bf0d151d99b17e diff --git a/src/target/armv7a.c b/src/target/armv7a.c index 547a33bb1e..f0679260fc 100644 --- a/src/target/armv7a.c +++ b/src/target/armv7a.c @@ -23,6 +23,7 @@ #include "replacements.h" #include "armv7a.h" +#include "arm_disassembler.h" #include "target.h" #include "register.h" @@ -69,8 +70,8 @@ char* armv7a_core_reg_list[] = char * armv7a_mode_strings_list[] = { - "Illegal mode value", "System and User", "FIQ", "IRQ", - "Supervisor", "Abort", "Undefined", "Monitor" + "Illegal mode value", "User", "FIQ", "IRQ", + "Supervisor", "Abort", "Undefined", "System", "Monitor" }; /* Hack! Yuk! allow -1 index, which simplifies codepaths elsewhere in the code */ @@ -172,6 +173,23 @@ reg_t armv7a_gdb_dummy_fp_reg = 0, 1, 96, NULL, 0, NULL, 0 }; +void armv7a_show_fault_registers(target_t *target) +{ + uint32_t dfsr, ifsr, dfar, ifar; + struct armv7a_common_s *armv7a = target_to_armv7a(target); + + armv7a->read_cp15(target, 0, 0, 5, 0, &dfsr); + armv7a->read_cp15(target, 0, 1, 5, 0, &ifsr); + armv7a->read_cp15(target, 0, 0, 6, 0, &dfar); + armv7a->read_cp15(target, 0, 2, 6, 0, &ifar); + + LOG_USER("Data fault registers DFSR: %8.8" PRIx32 + ", DFAR: %8.8" PRIx32, dfsr, dfar); + LOG_USER("Instruction fault registers IFSR: %8.8" PRIx32 + ", IFAR: %8.8" PRIx32, ifsr, ifar); + +} + int armv7a_arch_state(struct target_s *target) { static const char *state[] = @@ -179,8 +197,8 @@ int armv7a_arch_state(struct target_s *target) "disabled", "enabled" }; - armv4_5_common_t *armv4_5 = target->arch_info; - armv7a_common_t *armv7a = armv4_5->arch_info; + struct armv7a_common_s *armv7a = target_to_armv7a(target); + struct armv4_5_common_s *armv4_5 = &armv7a->armv4_5_common; if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC) { @@ -191,7 +209,7 @@ int armv7a_arch_state(struct target_s *target) LOG_USER("target halted in %s state due to %s, current mode: %s\n" "%s: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "\n" "MMU: %s, D-Cache: %s, I-Cache: %s", - armv7a_state_strings[armv4_5->core_state], + armv7a_state_strings[armv7a->core_state], Jim_Nvp_value2name_simple(nvp_target_debug_reason, target->debug_reason)->name, armv7a_mode_strings[ @@ -205,73 +223,148 @@ int armv7a_arch_state(struct target_s *target) state[armv7a->armv4_5_mmu.armv4_5_cache.d_u_cache_enabled], state[armv7a->armv4_5_mmu.armv4_5_cache.i_cache_enabled]); + if (armv4_5->core_mode == ARMV7A_MODE_ABT) + armv7a_show_fault_registers(target); + return ERROR_OK; } -static int handle_dap_baseaddr_command(struct command_context_s *cmd_ctx, - char *cmd, char **args, int argc) +COMMAND_HANDLER(handle_dap_baseaddr_command) { target_t *target = get_current_target(cmd_ctx); - armv4_5_common_t *armv4_5 = target->arch_info; - armv7a_common_t *armv7a = armv4_5->arch_info; + struct armv7a_common_s *armv7a = target_to_armv7a(target); swjdp_common_t *swjdp = &armv7a->swjdp_info; return dap_baseaddr_command(cmd_ctx, swjdp, args, argc); } -static int handle_dap_memaccess_command(struct command_context_s *cmd_ctx, - char *cmd, char **args, int argc) +COMMAND_HANDLER(handle_dap_memaccess_command) { target_t *target = get_current_target(cmd_ctx); - armv4_5_common_t *armv4_5 = target->arch_info; - armv7a_common_t *armv7a = armv4_5->arch_info; + struct armv7a_common_s *armv7a = target_to_armv7a(target); swjdp_common_t *swjdp = &armv7a->swjdp_info; return dap_memaccess_command(cmd_ctx, swjdp, args, argc); } -static int handle_dap_apsel_command(struct command_context_s *cmd_ctx, - char *cmd, char **args, int argc) +COMMAND_HANDLER(handle_dap_apsel_command) { target_t *target = get_current_target(cmd_ctx); - armv4_5_common_t *armv4_5 = target->arch_info; - armv7a_common_t *armv7a = armv4_5->arch_info; + struct armv7a_common_s *armv7a = target_to_armv7a(target); swjdp_common_t *swjdp = &armv7a->swjdp_info; return dap_apsel_command(cmd_ctx, swjdp, args, argc); } -static int handle_dap_apid_command(struct command_context_s *cmd_ctx, - char *cmd, char **args, int argc) +COMMAND_HANDLER(handle_dap_apid_command) { target_t *target = get_current_target(cmd_ctx); - armv4_5_common_t *armv4_5 = target->arch_info; - armv7a_common_t *armv7a = armv4_5->arch_info; + struct armv7a_common_s *armv7a = target_to_armv7a(target); swjdp_common_t *swjdp = &armv7a->swjdp_info; return dap_apid_command(cmd_ctx, swjdp, args, argc); } -static int handle_dap_info_command(struct command_context_s *cmd_ctx, - char *cmd, char **args, int argc) +COMMAND_HANDLER(handle_dap_info_command) { target_t *target = get_current_target(cmd_ctx); - armv4_5_common_t *armv4_5 = target->arch_info; - armv7a_common_t *armv7a = armv4_5->arch_info; + struct armv7a_common_s *armv7a = target_to_armv7a(target); swjdp_common_t *swjdp = &armv7a->swjdp_info; uint32_t apsel; - apsel = swjdp->apsel; - if (argc > 0) - apsel = strtoul(args[0], NULL, 0); + switch (argc) { + case 0: + apsel = swjdp->apsel; + break; + case 1: + COMMAND_PARSE_NUMBER(u32, args[0], apsel); + break; + default: + return ERROR_COMMAND_SYNTAX_ERROR; + } return dap_info_command(cmd_ctx, swjdp, apsel); } +COMMAND_HANDLER(handle_armv7a_disassemble_command) +{ + target_t *target = get_current_target(cmd_ctx); + struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target); + int thumb = 0; + int count = 1; + uint32_t address; + int i; + + if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC) { + command_print(cmd_ctx, "current target isn't an ARM target"); + return ERROR_OK; + } + + /* REVISIT: eventually support ThumbEE disassembly too; + * some opcodes work differently. + */ + + switch (argc) { + case 3: + if (strcmp(args[2], "thumb") != 0) + goto usage; + thumb = 1; + /* FALL THROUGH */ + case 2: + COMMAND_PARSE_NUMBER(int, args[1], count); + /* FALL THROUGH */ + case 1: + COMMAND_PARSE_NUMBER(u32, args[0], address); + if (address & 0x01) { + if (!thumb) { + command_print(cmd_ctx, "Disassemble as Thumb"); + thumb = 1; + } + address &= ~1; + } + break; + default: +usage: + command_print(cmd_ctx, + "usage: armv7a disassemble
[ ['thumb']]"); + return ERROR_OK; + } + + for (i = 0; i < count; i++) { + arm_instruction_t cur_instruction; + int retval; + + if (thumb) { + retval = thumb2_opcode(target, address, &cur_instruction); + if (retval != ERROR_OK) + return retval; + + address += cur_instruction.instruction_size; + } else { + uint32_t opcode; + + retval = target_read_u32(target, address, &opcode); + if (retval != ERROR_OK) + return retval; + + retval = arm_evaluate_opcode(opcode, address, + &cur_instruction); + if (retval != ERROR_OK) + return retval; + + address += 4; + } + command_print(cmd_ctx, "%s", cur_instruction.text); + } + + return ERROR_OK; +} + int armv7a_register_commands(struct command_context_s *cmd_ctx) { command_t *arm_adi_v5_dap_cmd; + command_t *armv7a_cmd; arm_adi_v5_dap_cmd = register_command(cmd_ctx, NULL, "dap", NULL, COMMAND_ANY, @@ -297,5 +390,13 @@ int armv7a_register_commands(struct command_context_s *cmd_ctx) "set/get number of extra tck for mem-ap memory " "bus access [0-255]"); + armv7a_cmd = register_command(cmd_ctx, NULL, "armv7a", + NULL, COMMAND_ANY, + "ARMv7-A specific commands"); + + register_command(cmd_ctx, armv7a_cmd, "disassemble", + handle_armv7a_disassemble_command, COMMAND_EXEC, + "disassemble instructions
[ ['thumb']]"); + return ERROR_OK; }