ARM: standard disassembler uses Thumb2 entry
authorDavid Brownell <dbrownell@users.sourceforge.net>
Mon, 16 Nov 2009 23:29:14 +0000 (15:29 -0800)
committerDavid Brownell <dbrownell@users.sourceforge.net>
Mon, 16 Nov 2009 23:29:14 +0000 (15:29 -0800)
Tweak "standard" ARM disassembler diagnostics to fail if the target
is not "an ARM" (vs. not "an ARMV4/5"), so it makes more sense for
cores inheriting this as the "generic" disassembler.

Also, to use the Thumb2 entry instead of the original Thumb entry.
This makes it work better for both newer cores (which support those
added instructions) and for BL and BLX instructions on older cores.
(Those instructions are 32-bits, which requires curious state-aware
code to go through a 16-bit decode interface...)

Plus minor cleanups, notably to have fewer exit paths and to make
sure they all return failure codes.

Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
src/target/arm_disassembler.c
src/target/armv4_5.c

index 35c3520306c04d89aa2e72da79d56263208c4d96..b93df64d10b2f5fd8a8824c06f1909f2e4a0ef2d 100644 (file)
@@ -1784,8 +1784,12 @@ static int evaluate_b_bl_blx_thumb(uint16_t opcode,
        }
 
        /* TODO: deal correctly with dual opcode (prefixed) BL/BLX;
-        * these are effectively 32-bit instructions even in Thumb1.
-        * Might be simplest to always use the Thumb2 decoder.
+        * these are effectively 32-bit instructions even in Thumb1.  For
+        * disassembly, it's simplest to always use the Thumb2 decoder.
+        *
+        * But some cores will evidently handle them as two instructions,
+        * where exceptions may occur between the two.  The ETMv3.2+ ID
+        * register has a bit which exposes this behavior.
         */
 
        snprintf(instruction->text, 128,
index 334f834a9b504e9f5ef6ac6329a21d8e14d349e4..e112e7b11ce5d855665a134fa343a82ed070b9a4 100644 (file)
@@ -439,19 +439,14 @@ COMMAND_HANDLER(handle_armv4_5_disassemble_command)
 {
        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) {
@@ -477,37 +472,38 @@ COMMAND_HANDLER(handle_armv4_5_disassemble_command)
 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;
-                       }
+               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)