#endif
#include "armv4_5.h"
+#include "arm_jtag.h"
#include "breakpoints.h"
#include "arm_disassembler.h"
#include "binarybuffer.h"
+#include "algorithm.h"
+#include "register.h"
char* armv4_5_core_reg_list[] =
"cpsr", "spsr_fiq", "spsr_irq", "spsr_svc", "spsr_abt", "spsr_und"
};
-char * armv4_5_mode_strings_list[] =
+static const char *armv4_5_mode_strings_list[] =
{
"Illegal mode value", "User", "FIQ", "IRQ", "Supervisor", "Abort", "Undefined", "System"
};
/* Hack! Yuk! allow -1 index, which simplifies codepaths elsewhere in the code */
-char** armv4_5_mode_strings = armv4_5_mode_strings_list + 1;
+const char **armv4_5_mode_strings = armv4_5_mode_strings_list + 1;
+
+/** Map PSR mode bits to linear number */
+int armv4_5_mode_to_number(enum armv4_5_mode mode)
+{
+ switch (mode) {
+ case ARMV4_5_MODE_ANY:
+ /* map MODE_ANY to user mode */
+ case ARMV4_5_MODE_USR:
+ return 0;
+ case ARMV4_5_MODE_FIQ:
+ return 1;
+ case ARMV4_5_MODE_IRQ:
+ return 2;
+ case ARMV4_5_MODE_SVC:
+ return 3;
+ case ARMV4_5_MODE_ABT:
+ return 4;
+ case ARMV4_5_MODE_UND:
+ return 5;
+ case ARMV4_5_MODE_SYS:
+ return 6;
+ default:
+ LOG_ERROR("invalid mode value encountered %d", mode);
+ return -1;
+ }
+}
+
+/** Map linear number to PSR mode bits. */
+enum armv4_5_mode armv4_5_number_to_mode(int number)
+{
+ switch (number) {
+ case 0:
+ return ARMV4_5_MODE_USR;
+ case 1:
+ return ARMV4_5_MODE_FIQ;
+ case 2:
+ return ARMV4_5_MODE_IRQ;
+ case 3:
+ return ARMV4_5_MODE_SVC;
+ case 4:
+ return ARMV4_5_MODE_ABT;
+ case 5:
+ return ARMV4_5_MODE_UND;
+ case 6:
+ return ARMV4_5_MODE_SYS;
+ default:
+ LOG_ERROR("mode index out of bounds %d", number);
+ return ARMV4_5_MODE_ANY;
+ }
+}
char* armv4_5_state_strings[] =
{
struct target *target = get_current_target(cmd_ctx);
struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
- if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
+ if (!is_arm(armv4_5))
{
- command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
- return ERROR_OK;
+ command_print(cmd_ctx, "current target isn't an ARM");
+ return ERROR_FAIL;
}
if (target->state != TARGET_HALTED)
if (armv4_5_mode_to_number(armv4_5->core_mode)==-1)
return ERROR_FAIL;
+ if (!armv4_5->full_context) {
+ command_print(cmd_ctx, "error: target doesn't support %s",
+ CMD_NAME);
+ return ERROR_FAIL;
+ }
+
for (num = 0; num <= 15; num++)
{
output_len = 0;
struct target *target = get_current_target(cmd_ctx);
struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
- if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
+ if (!is_arm(armv4_5))
{
- command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
- return ERROR_OK;
+ command_print(cmd_ctx, "current target isn't an ARM");
+ return ERROR_FAIL;
}
if (argc > 0)
{
int retval = ERROR_OK;
struct target *target = get_current_target(cmd_ctx);
- struct armv4_5_common_s *armv4_5 = target_to_armv4_5(target);
+ struct arm *arm = target ? target_to_arm(target) : NULL;
uint32_t address;
int count = 1;
- int i;
- struct arm_instruction cur_instruction;
- uint32_t opcode;
- uint16_t thumb_opcode;
int thumb = 0;
- if (armv4_5->common_magic != ARMV4_5_COMMON_MAGIC)
- {
- command_print(cmd_ctx, "current target isn't an ARMV4/5 target");
- return ERROR_OK;
+ if (!is_arm(arm)) {
+ command_print(cmd_ctx, "current target isn't an ARM");
+ return ERROR_FAIL;
}
switch (argc) {
default:
usage:
command_print(cmd_ctx,
- "usage: armv4_5 disassemble <address> [<count> ['thumb']]");
- return ERROR_OK;
- }
-
- for (i = 0; i < count; i++)
- {
- if (thumb)
- {
- 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;
- }
- }
- 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;
- }
+ "usage: arm disassemble <address> [<count> ['thumb']]");
+ count = 0;
+ retval = ERROR_FAIL;
+ }
+
+ while (count-- > 0) {
+ struct arm_instruction cur_instruction;
+
+ if (thumb) {
+ /* Always use Thumb2 disassembly for best handling
+ * of 32-bit BL/BLX, and to work with newer cores
+ * (some ARMv6, all ARMv7) that use Thumb2.
+ */
+ retval = thumb2_opcode(target, address,
+ &cur_instruction);
+ if (retval != ERROR_OK)
+ break;
+ } else {
+ uint32_t opcode;
+
+ retval = target_read_u32(target, address, &opcode);
+ if (retval != ERROR_OK)
+ break;
+ retval = arm_evaluate_opcode(opcode, address,
+ &cur_instruction) != ERROR_OK;
+ if (retval != ERROR_OK)
+ break;
}
command_print(cmd_ctx, "%s", cur_instruction.text);
- address += (thumb) ? 2 : 4;
+ address += cur_instruction.instruction_size;
}
- return ERROR_OK;
+ return retval;
}
int armv4_5_register_commands(struct command_context *cmd_ctx)
{
struct command *armv4_5_cmd;
- armv4_5_cmd = register_command(cmd_ctx, NULL, "armv4_5",
+ armv4_5_cmd = register_command(cmd_ctx, NULL, "arm",
NULL, COMMAND_ANY,
- "armv4/5 specific commands");
+ "generic ARM commands");
register_command(cmd_ctx, armv4_5_cmd, "reg",
handle_armv4_5_reg_command, COMMAND_EXEC,
"display/change ARM core state <arm | thumb>");
register_command(cmd_ctx, armv4_5_cmd, "disassemble",
handle_armv4_5_disassemble_command, COMMAND_EXEC,
- "disassemble instructions <address> [<count> ['thumb']]");
+ "disassemble instructions "
+ "<address> [<count> ['thumb']]");
return ERROR_OK;
}
return retval;
/* convert code into a buffer in target endianness */
- for (i = 0; i < DIM(arm_crc_code); i++) {
+ for (i = 0; i < ARRAY_SIZE(arm_crc_code); i++) {
retval = target_write_u32(target,
crc_algorithm->address + i * sizeof(uint32_t),
arm_crc_code[i]);
return retval;
/* convert code into a buffer in target endianness */
- for (i = 0; i < DIM(check_code); i++) {
+ for (i = 0; i < ARRAY_SIZE(check_code); i++) {
retval = target_write_u32(target,
check_algorithm->address
+ i * sizeof(uint32_t),