David Brownell <david-b@pacbell.net>:
[openocd.git] / src / target / arm_disassembler.c
index 04dcf4bac62d92ee9b20bdc00065cf41398c810b..63166932f0b270d5f8467dcc2c01195b3d992698 100644 (file)
  *   Free Software Foundation, Inc.,                                       *
  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
  ***************************************************************************/
-#include "arm_disassembler.h"
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
 
+#include "target.h"
+#include "arm_disassembler.h"
 #include "log.h"
 
-#include <strings.h>
 
 /* textual represenation of the condition field */
 /* ALways (default) is ommitted (empty string) */
@@ -31,20 +34,20 @@ char *arm_condition_strings[] =
 };
 
 /* make up for C's missing ROR */
-u32 ror(u32 value, int places) 
-{ 
-       return (value >> places) | (value << (32 - places)); 
+uint32_t ror(uint32_t value, int places)
+{
+       return (value >> places) | (value << (32 - places));
 }
 
-int evaluate_pld(u32 opcode, u32 address, arm_instruction_t *instruction)
+int evaluate_pld(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
 {
        /* PLD */
        if ((opcode & 0x0d70f0000) == 0x0550f000)
        {
                instruction->type = ARM_PLD;
-               
-               snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tPLD ...TODO...", address, opcode);
-               
+
+               snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD ...TODO...", address, opcode);
+
                return ERROR_OK;
        }
        else
@@ -52,132 +55,134 @@ int evaluate_pld(u32 opcode, u32 address, arm_instruction_t *instruction)
                instruction->type = ARM_UNDEFINED_INSTRUCTION;
                return ERROR_OK;
        }
-       
-       ERROR("should never reach this point");
+
+       LOG_ERROR("should never reach this point");
        return -1;
 }
 
-int evaluate_swi(u32 opcode, u32 address, arm_instruction_t *instruction)
+int evaluate_swi(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
 {
        instruction->type = ARM_SWI;
-       
-       snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tSWI 0x%6.6x", address, opcode, (opcode & 0xffffff));
-       
+
+       snprintf(instruction->text, 128,
+                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSVC %#6.6" PRIx32,
+                       address, opcode, (opcode & 0xffffff));
+
        return ERROR_OK;
 }
 
-int evaluate_blx_imm(u32 opcode, u32 address, arm_instruction_t *instruction)
+int evaluate_blx_imm(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
 {
        int offset;
-       u32 immediate;
-       u32 target_address;
-       
+       uint32_t immediate;
+       uint32_t target_address;
+
        instruction->type = ARM_BLX;
        immediate = opcode & 0x00ffffff;
-       
+
        /* sign extend 24-bit immediate */
        if (immediate & 0x00800000)
                offset = 0xff000000 | immediate;
        else
                offset = immediate;
-       
+
        /* shift two bits left */
        offset <<= 2;
-       
+
        /* odd/event halfword */
        if (opcode & 0x01000000)
                offset |= 0x2;
-       
+
        target_address = address + 8 + offset;
-       
-       snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tBLX 0x%8.8x", address, opcode, target_address);
-       
+
+       snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX 0x%8.8" PRIx32 "", address, opcode, target_address);
+
        instruction->info.b_bl_bx_blx.reg_operand = -1;
        instruction->info.b_bl_bx_blx.target_address = target_address;
-       
+
        return ERROR_OK;
 }
 
-int evaluate_b_bl(u32 opcode, u32 address, arm_instruction_t *instruction)
+int evaluate_b_bl(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
 {
-       u8 L;
-       u32 immediate;
+       uint8_t L;
+       uint32_t immediate;
        int offset;
-       u32 target_address;
-       
+       uint32_t target_address;
+
        immediate = opcode & 0x00ffffff;
        L = (opcode & 0x01000000) >> 24;
-       
+
        /* sign extend 24-bit immediate */
        if (immediate & 0x00800000)
                offset = 0xff000000 | immediate;
        else
                offset = immediate;
-       
+
        /* shift two bits left */
        offset <<= 2;
-       
+
        target_address = address + 8 + offset;
 
        if (L)
                instruction->type = ARM_BL;
        else
                instruction->type = ARM_B;
-       
-       snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tB%s%s 0x%8.8x", address, opcode,
+
+       snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tB%s%s 0x%8.8" PRIx32 , address, opcode,
                         (L) ? "L" : "", COND(opcode), target_address);
-       
+
        instruction->info.b_bl_bx_blx.reg_operand = -1;
        instruction->info.b_bl_bx_blx.target_address = target_address;
-       
+
        return ERROR_OK;
 }
 
 /* Coprocessor load/store and double register transfers */
 /* both normal and extended instruction space (condition field b1111) */
-int evaluate_ldc_stc_mcrr_mrrc(u32 opcode, u32 address, arm_instruction_t *instruction)
+int evaluate_ldc_stc_mcrr_mrrc(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
 {
-       u8 cp_num = (opcode & 0xf00) >> 8;
-       
+       uint8_t cp_num = (opcode & 0xf00) >> 8;
+
        /* MCRR or MRRC */
        if (((opcode & 0x0ff00000) == 0x0c400000) || ((opcode & 0x0ff00000) == 0x0c400000))
        {
-               u8 cp_opcode, Rd, Rn, CRm;
+               uint8_t cp_opcode, Rd, Rn, CRm;
                char *mnemonic;
-               
+
                cp_opcode = (opcode & 0xf0) >> 4;
                Rd = (opcode & 0xf000) >> 12;
                Rn = (opcode & 0xf0000) >> 16;
                CRm = (opcode & 0xf);
-               
+
                /* MCRR */
                if ((opcode & 0x0ff00000) == 0x0c400000)
                {
                        instruction->type = ARM_MCRR;
                        mnemonic = "MCRR";
                }
-               
+
                /* MRRC */
                if ((opcode & 0x0ff00000) == 0x0c500000)
                {
                        instruction->type = ARM_MRRC;
                        mnemonic = "MRRC";
                }
-               
-               snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s p%i, %x, r%i, r%i, c%i",
+
+               snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, %x, r%i, r%i, c%i",
                                 address, opcode, mnemonic, COND(opcode), cp_num, cp_opcode, Rd, Rn, CRm);
        }
        else /* LDC or STC */
        {
-               u8 CRd, Rn, offset;
-               u8 U, N;
+               uint8_t CRd, Rn, offset;
+               uint8_t U, N;
                char *mnemonic;
                char addressing_mode[32];
-               
+
                CRd = (opcode & 0xf000) >> 12;
                Rn = (opcode & 0xf0000) >> 16;
                offset = (opcode & 0xff);
-               
+
                /* load/store */
                if (opcode & 0x00100000)
                {
@@ -189,10 +194,10 @@ int evaluate_ldc_stc_mcrr_mrrc(u32 opcode, u32 address, arm_instruction_t *instr
                        instruction->type = ARM_STC;
                        mnemonic = "STC";
                }
-               
+
                U = (opcode & 0x00800000) >> 23;
                N = (opcode & 0x00400000) >> 22;
-               
+
                /* addressing modes */
                if ((opcode & 0x01200000) == 0x01000000) /* immediate offset */
                        snprintf(addressing_mode, 32, "[r%i, #%s0x%2.2x*4]", Rn, (U) ? "" : "-", offset);
@@ -203,31 +208,31 @@ int evaluate_ldc_stc_mcrr_mrrc(u32 opcode, u32 address, arm_instruction_t *instr
                else if ((opcode & 0x01200000) == 0x00000000) /* unindexed */
                        snprintf(addressing_mode, 32, "[r%i], #0x%2.2x", Rn, offset);
 
-               snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s p%i, c%i, %s",
+               snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s p%i, c%i, %s",
                                 address, opcode, mnemonic, ((opcode & 0xf0000000) == 0xf0000000) ? COND(opcode) : "2",
                                 (N) ? "L" : "",
                                 cp_num, CRd, addressing_mode);
        }
-       
+
        return ERROR_OK;
 }
 
 /* Coprocessor data processing instructions */
 /* Coprocessor register transfer instructions */
 /* both normal and extended instruction space (condition field b1111) */
-int evaluate_cdp_mcr_mrc(u32 opcode, u32 address, arm_instruction_t *instruction)
+int evaluate_cdp_mcr_mrc(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
 {
        char* cond;
        char* mnemonic;
-       u8 cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2;
-       
+       uint8_t cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2;
+
        cond = ((opcode & 0xf0000000) == 0xf0000000) ? "2" : COND(opcode);
        cp_num = (opcode & 0xf00) >> 8;
        CRd_Rd = (opcode & 0xf000) >> 12;
        CRn = (opcode & 0xf0000) >> 16;
        CRm = (opcode & 0xf);
        opcode_2 = (opcode & 0xe0) >> 5;
-       
+
        /* CDP or MRC/MCR */
        if (opcode & 0x00000010) /* bit 4 set -> MRC/MCR */
        {
@@ -241,10 +246,10 @@ int evaluate_cdp_mcr_mrc(u32 opcode, u32 address, arm_instruction_t *instruction
                        instruction->type = ARM_MCR;
                        mnemonic = "MCR";
                }
-               
+
                opcode_1 = (opcode & 0x00e00000) >> 21;
-               
-               snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s p%i, 0x%2.2x, r%i, c%i, c%i, 0x%2.2x",
+
+               snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, 0x%2.2x, r%i, c%i, c%i, 0x%2.2x",
                                 address, opcode, mnemonic, cond,
                                 cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2);
        }
@@ -252,26 +257,26 @@ int evaluate_cdp_mcr_mrc(u32 opcode, u32 address, arm_instruction_t *instruction
        {
                instruction->type = ARM_CDP;
                mnemonic = "CDP";
-               
+
                opcode_1 = (opcode & 0x00f00000) >> 20;
-               
-               snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s p%i, 0x%2.2x, c%i, c%i, c%i, 0x%2.2x",
+
+               snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, 0x%2.2x, c%i, c%i, c%i, 0x%2.2x",
                                 address, opcode, mnemonic, cond,
                                 cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2);
        }
-       
+
        return ERROR_OK;
 }
 
 /* Load/store instructions */
-int evaluate_load_store(u32 opcode, u32 address, arm_instruction_t *instruction)
+int evaluate_load_store(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
 {
-       u8 I, P, U, B, W, L;
-       u8 Rn, Rd;
+       uint8_t I, P, U, B, W, L;
+       uint8_t Rn, Rd;
        char *operation; /* "LDR" or "STR" */
        char *suffix; /* "", "B", "T", "BT" */
        char offset[32];
-       
+
        /* examine flags */
        I = (opcode & 0x02000000) >> 25;
        P = (opcode & 0x01000000) >> 24;
@@ -279,13 +284,13 @@ int evaluate_load_store(u32 opcode, u32 address, arm_instruction_t *instruction)
        B = (opcode & 0x00400000) >> 22;
        W = (opcode & 0x00200000) >> 21;
        L = (opcode & 0x00100000) >> 20;
-       
+
        /* target register */
        Rd = (opcode & 0xf000) >> 12;
-       
+
        /* base register */
        Rn = (opcode & 0xf0000) >> 16;
-       
+
        instruction->info.load_store.Rd = Rd;
        instruction->info.load_store.Rn = Rn;
        instruction->info.load_store.U = U;
@@ -295,7 +300,7 @@ int evaluate_load_store(u32 opcode, u32 address, arm_instruction_t *instruction)
                operation = "LDR";
        else
                operation = "STR";
-       
+
        /* determine instruction type and suffix */
        if (B)
        {
@@ -335,28 +340,31 @@ int evaluate_load_store(u32 opcode, u32 address, arm_instruction_t *instruction)
                        suffix = "";
                }
        }
-       
+
        if (!I) /* #+-<offset_12> */
        {
-               u32 offset_12 = (opcode & 0xfff);
-               snprintf(offset, 32, "#%s0x%x", (U) ? "" : "-", offset_12);
-               
+               uint32_t offset_12 = (opcode & 0xfff);
+               if (offset_12)
+                       snprintf(offset, 32, ", #%s0x%" PRIx32 "", (U) ? "" : "-", offset_12);
+               else
+                       snprintf(offset, 32, "%s", "");
+
                instruction->info.load_store.offset_mode = 0;
                instruction->info.load_store.offset.offset = offset_12;
        }
        else /* either +-<Rm> or +-<Rm>, <shift>, #<shift_imm> */
        {
-               u8 shift_imm, shift;
-               u8 Rm;
-               
+               uint8_t shift_imm, shift;
+               uint8_t Rm;
+
                shift_imm = (opcode & 0xf80) >> 7;
                shift = (opcode & 0x60) >> 5;
                Rm = (opcode & 0xf);
-               
+
                /* LSR encodes a shift by 32 bit as 0x0 */
                if ((shift == 0x1) && (shift_imm == 0x0))
                        shift_imm = 0x20;
-               
+
                /* ASR encodes a shift by 32 bit as 0x0 */
                if ((shift == 0x2) && (shift_imm == 0x0))
                        shift_imm = 0x20;
@@ -364,7 +372,7 @@ int evaluate_load_store(u32 opcode, u32 address, arm_instruction_t *instruction)
                /* ROR by 32 bit is actually a RRX */
                if ((shift == 0x3) && (shift_imm == 0x0))
                        shift = 0x4;
-               
+
                instruction->info.load_store.offset_mode = 1;
                instruction->info.load_store.offset.reg.Rm = Rm;
                instruction->info.load_store.offset.reg.shift = shift;
@@ -372,71 +380,71 @@ int evaluate_load_store(u32 opcode, u32 address, arm_instruction_t *instruction)
 
                if ((shift_imm == 0x0) && (shift == 0x0)) /* +-<Rm> */
                {
-                       snprintf(offset, 32, "%sr%i", (U) ? "" : "-", Rm);
+                       snprintf(offset, 32, "%sr%i", (U) ? "" : "-", Rm);
                }
                else /* +-<Rm>, <Shift>, #<shift_imm> */
                {
                        switch (shift)
                        {
                                case 0x0: /* LSL */
-                                       snprintf(offset, 32, "%sr%i, LSL #0x%x", (U) ? "" : "-", Rm, shift_imm);
+                                       snprintf(offset, 32, "%sr%i, LSL #0x%x", (U) ? "" : "-", Rm, shift_imm);
                                        break;
                                case 0x1: /* LSR */
-                                       snprintf(offset, 32, "%sr%i, LSR #0x%x", (U) ? "" : "-", Rm, shift_imm);
+                                       snprintf(offset, 32, "%sr%i, LSR #0x%x", (U) ? "" : "-", Rm, shift_imm);
                                        break;
                                case 0x2: /* ASR */
-                                       snprintf(offset, 32, "%sr%i, ASR #0x%x", (U) ? "" : "-", Rm, shift_imm);
+                                       snprintf(offset, 32, "%sr%i, ASR #0x%x", (U) ? "" : "-", Rm, shift_imm);
                                        break;
                                case 0x3: /* ROR */
-                                       snprintf(offset, 32, "%sr%i, ROR #0x%x", (U) ? "" : "-", Rm, shift_imm);
+                                       snprintf(offset, 32, "%sr%i, ROR #0x%x", (U) ? "" : "-", Rm, shift_imm);
                                        break;
                                case 0x4: /* RRX */
-                                       snprintf(offset, 32, "%sr%i, RRX", (U) ? "" : "-", Rm);
+                                       snprintf(offset, 32, "%sr%i, RRX", (U) ? "" : "-", Rm);
                                        break;
                        }
                }
        }
-       
+
        if (P == 1)
        {
                if (W == 0) /* offset */
                {
-                       snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i, %s]",
+                       snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]",
                                         address, opcode, operation, COND(opcode), suffix,
                                         Rd, Rn, offset);
-                       
+
                        instruction->info.load_store.index_mode = 0;
                }
                else /* pre-indexed */
                {
-                       snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i, %s]!",
+                       snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]!",
                                         address, opcode, operation, COND(opcode), suffix,
                                         Rd, Rn, offset);
-                       
+
                        instruction->info.load_store.index_mode = 1;
                }
        }
        else /* post-indexed */
        {
-               snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i], %s",
+               snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i]%s",
                                 address, opcode, operation, COND(opcode), suffix,
                                 Rd, Rn, offset);
-               
+
                instruction->info.load_store.index_mode = 2;
        }
-       
+
        return ERROR_OK;
 }
 
 /* Miscellaneous load/store instructions */
-int evaluate_misc_load_store(u32 opcode, u32 address, arm_instruction_t *instruction)
+int evaluate_misc_load_store(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
 {
-       u8 P, U, I, W, L, S, H;
-       u8 Rn, Rd;
+       uint8_t P, U, I, W, L, S, H;
+       uint8_t Rn, Rd;
        char *operation; /* "LDR" or "STR" */
        char *suffix; /* "H", "SB", "SH", "D" */
        char offset[32];
-       
+
        /* examine flags */
        P = (opcode & 0x01000000) >> 24;
        U = (opcode & 0x00800000) >> 23;
@@ -445,17 +453,17 @@ int evaluate_misc_load_store(u32 opcode, u32 address, arm_instruction_t *instruc
        L = (opcode & 0x00100000) >> 20;
        S = (opcode & 0x00000040) >> 6;
        H = (opcode & 0x00000020) >> 5;
-       
+
        /* target register */
        Rd = (opcode & 0xf000) >> 12;
-       
+
        /* base register */
        Rn = (opcode & 0xf0000) >> 16;
-       
+
        instruction->info.load_store.Rd = Rd;
        instruction->info.load_store.Rn = Rn;
        instruction->info.load_store.U = U;
-       
+
        /* determine instruction type and suffix */
        if (S) /* signed */
        {
@@ -503,70 +511,70 @@ int evaluate_misc_load_store(u32 opcode, u32 address, arm_instruction_t *instruc
                        instruction->type = ARM_STRH;
                }
        }
-       
+
        if (I) /* Immediate offset/index (#+-<offset_8>)*/
        {
-               u32 offset_8 = ((opcode & 0xf00) >> 4) | (opcode & 0xf);
-               snprintf(offset, 32, "#%s0x%x", (U) ? "" : "-", offset_8);
-               
+               uint32_t offset_8 = ((opcode & 0xf00) >> 4) | (opcode & 0xf);
+               snprintf(offset, 32, "#%s0x%" PRIx32 "", (U) ? "" : "-", offset_8);
+
                instruction->info.load_store.offset_mode = 0;
                instruction->info.load_store.offset.offset = offset_8;
        }
        else /* Register offset/index (+-<Rm>) */
        {
-               u8 Rm;
+               uint8_t Rm;
                Rm = (opcode & 0xf);
                snprintf(offset, 32, "%sr%i", (U) ? "" : "-", Rm);
-               
+
                instruction->info.load_store.offset_mode = 1;
                instruction->info.load_store.offset.reg.Rm = Rm;
                instruction->info.load_store.offset.reg.shift = 0x0;
                instruction->info.load_store.offset.reg.shift_imm = 0x0;
        }
-       
+
        if (P == 1)
        {
                if (W == 0) /* offset */
                {
-                       snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i, %s]",
+                       snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]",
                                         address, opcode, operation, COND(opcode), suffix,
                                         Rd, Rn, offset);
-                       
+
                        instruction->info.load_store.index_mode = 0;
                }
                else /* pre-indexed */
                {
-                       snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i, %s]!",
+                       snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]!",
                                         address, opcode, operation, COND(opcode), suffix,
                                         Rd, Rn, offset);
-               
+
                        instruction->info.load_store.index_mode = 1;
                }
        }
        else /* post-indexed */
        {
-               snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i], %s",
+               snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i], %s",
                                 address, opcode, operation, COND(opcode), suffix,
                                 Rd, Rn, offset);
-       
+
                instruction->info.load_store.index_mode = 2;
        }
-       
+
        return ERROR_OK;
 }
 
 /* Load/store multiples instructions */
-int evaluate_ldm_stm(u32 opcode, u32 address, arm_instruction_t *instruction)
+int evaluate_ldm_stm(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
 {
-       u8 P, U, S, W, L, Rn;
-       u32 register_list;
+       uint8_t P, U, S, W, L, Rn;
+       uint32_t register_list;
        char *addressing_mode;
        char *mnemonic;
        char reg_list[69];
        char *reg_list_p;
        int i;
        int first_reg = 1;
-       
+
        P = (opcode & 0x01000000) >> 24;
        U = (opcode & 0x00800000) >> 23;
        S = (opcode & 0x00400000) >> 22;
@@ -574,12 +582,12 @@ int evaluate_ldm_stm(u32 opcode, u32 address, arm_instruction_t *instruction)
        L = (opcode & 0x00100000) >> 20;
        register_list = (opcode & 0xffff);
        Rn = (opcode & 0xf0000) >> 16;
-       
+
        instruction->info.load_store_multiple.Rn = Rn;
        instruction->info.load_store_multiple.register_list = register_list;
        instruction->info.load_store_multiple.S = S;
        instruction->info.load_store_multiple.W = W;
-       
+
        if (L)
        {
                instruction->type = ARM_LDM;
@@ -590,7 +598,7 @@ int evaluate_ldm_stm(u32 opcode, u32 address, arm_instruction_t *instruction)
                instruction->type = ARM_STM;
                mnemonic = "STM";
        }
-       
+
        if (P)
        {
                if (U)
@@ -609,7 +617,8 @@ int evaluate_ldm_stm(u32 opcode, u32 address, arm_instruction_t *instruction)
                if (U)
                {
                        instruction->info.load_store_multiple.addressing_mode = 0;
-                       addressing_mode = "IA";
+                       /* "IA" is the default in UAL syntax */
+                       addressing_mode = "";
                }
                else
                {
@@ -617,7 +626,7 @@ int evaluate_ldm_stm(u32 opcode, u32 address, arm_instruction_t *instruction)
                        addressing_mode = "DA";
                }
        }
-       
+
        reg_list_p = reg_list;
        for (i = 0; i <= 15; i++)
        {
@@ -634,16 +643,16 @@ int evaluate_ldm_stm(u32 opcode, u32 address, arm_instruction_t *instruction)
                        }
                }
        }
-       
-       snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i%s, {%s}%s",
+
+       snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i%s, {%s}%s",
                         address, opcode, mnemonic, COND(opcode), addressing_mode,
                         Rn, (W) ? "!" : "", reg_list, (S) ? "^" : "");
-       
+
        return ERROR_OK;
 }
 
 /* Multiplies, extra load/stores */
-int evaluate_mul_and_extra_ld_st(u32 opcode, u32 address, arm_instruction_t *instruction)
+int evaluate_mul_and_extra_ld_st(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
 {
        /* Multiply (accumulate) (long) and Swap/swap byte */
        if ((opcode & 0x000000f0) == 0x00000090)
@@ -651,41 +660,41 @@ int evaluate_mul_and_extra_ld_st(u32 opcode, u32 address, arm_instruction_t *ins
                /* Multiply (accumulate) */
                if ((opcode & 0x0f800000) == 0x00000000)
                {
-                       u8 Rm, Rs, Rn, Rd, S;
+                       uint8_t Rm, Rs, Rn, Rd, S;
                        Rm = opcode & 0xf;
                        Rs = (opcode & 0xf00) >> 8;
                        Rn = (opcode & 0xf000) >> 12;
                        Rd = (opcode & 0xf0000) >> 16;
                        S = (opcode & 0x00100000) >> 20;
-                       
+
                        /* examine A bit (accumulate) */
                        if (opcode & 0x00200000)
                        {
                                instruction->type = ARM_MLA;
-                               snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tMLA%s%s r%i, r%i, r%i, r%i",
+                               snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMLA%s%s r%i, r%i, r%i, r%i",
                                                address, opcode, COND(opcode), (S) ? "S" : "", Rd, Rm, Rs, Rn);
                        }
                        else
                        {
                                instruction->type = ARM_MUL;
-                               snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tMUL%s%s r%i, r%i, r%i",
+                               snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMUL%s%s r%i, r%i, r%i",
                                                 address, opcode, COND(opcode), (S) ? "S" : "", Rd, Rm, Rs);
                        }
-                       
+
                        return ERROR_OK;
                }
-               
+
                /* Multiply (accumulate) long */
                if ((opcode & 0x0f800000) == 0x00800000)
                {
-                       char* mnemonic;
-                       u8 Rm, Rs, RdHi, RdLow, S;
+                       char* mnemonic = NULL;
+                       uint8_t Rm, Rs, RdHi, RdLow, S;
                        Rm = opcode & 0xf;
                        Rs = (opcode & 0xf00) >> 8;
                        RdHi = (opcode & 0xf000) >> 12;
                        RdLow = (opcode & 0xf0000) >> 16;
                        S = (opcode & 0x00100000) >> 20;
-                       
+
                        switch ((opcode & 0x00600000) >> 21)
                        {
                                case 0x0:
@@ -705,143 +714,146 @@ int evaluate_mul_and_extra_ld_st(u32 opcode, u32 address, arm_instruction_t *ins
                                        mnemonic = "SMLAL";
                                        break;
                        }
-                       
-                       snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, r%i, r%i, r%i",
+
+                       snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, r%i, r%i",
                                                address, opcode, mnemonic, COND(opcode), (S) ? "S" : "",
                                                RdLow, RdHi, Rm, Rs);
-                       
+
                        return ERROR_OK;
                }
-               
+
                /* Swap/swap byte */
                if ((opcode & 0x0f800000) == 0x01000000)
                {
-                       u8 Rm, Rd, Rn;
+                       uint8_t Rm, Rd, Rn;
                        Rm = opcode & 0xf;
                        Rd = (opcode & 0xf000) >> 12;
                        Rn = (opcode & 0xf0000) >> 16;
-                       
+
                        /* examine B flag */
                        instruction->type = (opcode & 0x00400000) ? ARM_SWPB : ARM_SWP;
-                       
-                       snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s r%i, r%i, [r%i]",
+
+                       snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, [r%i]",
                                         address, opcode, (opcode & 0x00400000) ? "SWPB" : "SWP", COND(opcode), Rd, Rm, Rn);
                        return ERROR_OK;
                }
-               
+
        }
-       
+
        return evaluate_misc_load_store(opcode, address, instruction);
 }
 
-int evaluate_mrs_msr(u32 opcode, u32 address, arm_instruction_t *instruction)
+int evaluate_mrs_msr(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
 {
        int R = (opcode & 0x00400000) >> 22;
        char *PSR = (R) ? "SPSR" : "CPSR";
-               
+
        /* Move register to status register (MSR) */
        if (opcode & 0x00200000)
        {
                instruction->type = ARM_MSR;
-                       
+
                /* immediate variant */
                if (opcode & 0x02000000)
                {
-                       u8 immediate = (opcode & 0xff);
-                       u8 rotate = (opcode & 0xf00);
-                       
-                       snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tMSR%s %s_%s%s%s%s, 0x%8.8x",
+                       uint8_t immediate = (opcode & 0xff);
+                       uint8_t rotate = (opcode & 0xf00);
+
+                       snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, 0x%8.8" PRIx32 ,
                                         address, opcode, COND(opcode), PSR,
                                         (opcode & 0x10000) ? "c" : "",
                                         (opcode & 0x20000) ? "x" : "",
                                         (opcode & 0x40000) ? "s" : "",
                                         (opcode & 0x80000) ? "f" : "",
                                         ror(immediate, (rotate * 2))
-                                       );
+);
                }
                else /* register variant */
                {
-                       u8 Rm = opcode & 0xf;
-                       snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tMSR%s %s_%s%s%s%s, r%i",
+                       uint8_t Rm = opcode & 0xf;
+                       snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, r%i",
                                         address, opcode, COND(opcode), PSR,
                                         (opcode & 0x10000) ? "c" : "",
                                         (opcode & 0x20000) ? "x" : "",
                                         (opcode & 0x40000) ? "s" : "",
                                         (opcode & 0x80000) ? "f" : "",
                                         Rm
-                                       );
+);
                }
-               
+
        }
        else /* Move status register to register (MRS) */
        {
-               u8 Rd;
-               
+               uint8_t Rd;
+
                instruction->type = ARM_MRS;
                Rd = (opcode & 0x0000f000) >> 12;
-                       
-               snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tMRS%s r%i, %s",
+
+               snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMRS%s r%i, %s",
                                 address, opcode, COND(opcode), Rd, PSR);
        }
-       
+
        return ERROR_OK;
 }
 
 /* Miscellaneous instructions */
-int evaluate_misc_instr(u32 opcode, u32 address, arm_instruction_t *instruction)
+int evaluate_misc_instr(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
 {
        /* MRS/MSR */
        if ((opcode & 0x000000f0) == 0x00000000)
        {
                evaluate_mrs_msr(opcode, address, instruction);
        }
-       
+
        /* BX */
        if ((opcode & 0x006000f0) == 0x00200010)
        {
-               u8 Rm;
+               uint8_t Rm;
                instruction->type = ARM_BX;
                Rm = opcode & 0xf;
-               
-               snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tBX%s r%i",
+
+               snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBX%s r%i",
                                 address, opcode, COND(opcode), Rm);
-               
+
                instruction->info.b_bl_bx_blx.reg_operand = Rm;
                instruction->info.b_bl_bx_blx.target_address = -1;
        }
-       
+
        /* CLZ */
-       if ((opcode & 0x0060000f0) == 0x00300010)
+       if ((opcode & 0x006000f0) == 0x00600010)
        {
-               u8 Rm, Rd;
+               uint8_t Rm, Rd;
                instruction->type = ARM_CLZ;
                Rm = opcode & 0xf;
                Rd = (opcode & 0xf000) >> 12;
 
-               snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tCLZ%s r%i, r%i",
+               snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCLZ%s r%i, r%i",
                                 address, opcode, COND(opcode), Rd, Rm);
        }
-       
-       /* BLX */
-       if ((opcode & 0x0060000f0) == 0x00200030)
+
+       /* BLX(2) */
+       if ((opcode & 0x006000f0) == 0x00200030)
        {
-               u8 Rm;
+               uint8_t Rm;
                instruction->type = ARM_BLX;
                Rm = opcode & 0xf;
-               
-               snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tBLX%s r%i",
+
+               snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX%s r%i",
                                 address, opcode, COND(opcode), Rm);
+
+               instruction->info.b_bl_bx_blx.reg_operand = Rm;
+               instruction->info.b_bl_bx_blx.target_address = -1;
        }
-       
+
        /* Enhanced DSP add/subtracts */
        if ((opcode & 0x0000000f0) == 0x00000050)
        {
-               u8 Rm, Rd, Rn;
-               char *mnemonic;
+               uint8_t Rm, Rd, Rn;
+               char *mnemonic = NULL;
                Rm = opcode & 0xf;
                Rd = (opcode & 0xf000) >> 12;
                Rn = (opcode & 0xf0000) >> 16;
-               
+
                switch ((opcode & 0x00600000) >> 21)
                {
                        case 0x0:
@@ -861,118 +873,118 @@ int evaluate_misc_instr(u32 opcode, u32 address, arm_instruction_t *instruction)
                                mnemonic = "QDSUB";
                                break;
                }
-               
-               snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s r%i, r%i, r%i",
+
+               snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, r%i",
                                 address, opcode, mnemonic, COND(opcode), Rd, Rm, Rn);
        }
-       
+
        /* Software breakpoints */
        if ((opcode & 0x0000000f0) == 0x00000070)
        {
-               u32 immediate;
+               uint32_t immediate;
                instruction->type = ARM_BKPT;
                immediate = ((opcode & 0x000fff00) >> 4) | (opcode & 0xf);
-               
-               snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tBKPT 0x%4.4x",
-                                address, opcode, immediate);   
+
+               snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBKPT 0x%4.4" PRIx32 "",
+                                address, opcode, immediate);
        }
-       
+
        /* Enhanced DSP multiplies */
        if ((opcode & 0x000000090) == 0x00000080)
        {
                int x = (opcode & 0x20) >> 5;
                int y = (opcode & 0x40) >> 6;
-               
-               /* SMLA<x><y> */
+
+               /* SMLA < x><y> */
                if ((opcode & 0x00600000) == 0x00000000)
                {
-                       u8 Rd, Rm, Rs, Rn;
+                       uint8_t Rd, Rm, Rs, Rn;
                        instruction->type = ARM_SMLAxy;
                        Rd = (opcode & 0xf0000) >> 16;
                        Rm = (opcode & 0xf);
                        Rs = (opcode & 0xf00) >> 8;
                        Rn = (opcode & 0xf000) >> 12;
-                       
-                       snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tSMLA%s%s%s r%i, r%i, r%i, r%i",
+
+                       snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
                                         address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
                                         Rd, Rm, Rs, Rn);
                }
-               
-               /* SMLAL<x><y> */
+
+               /* SMLAL < x><y> */
                if ((opcode & 0x00600000) == 0x00400000)
                {
-                       u8 RdLow, RdHi, Rm, Rs;
+                       uint8_t RdLow, RdHi, Rm, Rs;
                        instruction->type = ARM_SMLAxy;
                        RdHi = (opcode & 0xf0000) >> 16;
                        RdLow = (opcode & 0xf000) >> 12;
                        Rm = (opcode & 0xf);
                        Rs = (opcode & 0xf00) >> 8;
-                       
-                       snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tSMLA%s%s%s r%i, r%i, r%i, r%i",
+
+                       snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
                                         address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
                                         RdLow, RdHi, Rm, Rs);
                }
-               
-               /* SMLAW<y> */
+
+               /* SMLAW < y> */
                if (((opcode & 0x00600000) == 0x00100000) && (x == 0))
                {
-                       u8 Rd, Rm, Rs, Rn;
+                       uint8_t Rd, Rm, Rs, Rn;
                        instruction->type = ARM_SMLAWy;
                        Rd = (opcode & 0xf0000) >> 16;
                        Rm = (opcode & 0xf);
                        Rs = (opcode & 0xf00) >> 8;
                        Rn = (opcode & 0xf000) >> 12;
 
-                       snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tSMLAW%s%s r%i, r%i, r%i, r%i",
+                       snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLAW%s%s r%i, r%i, r%i, r%i",
                                         address, opcode, (y) ? "T" : "B", COND(opcode),
                                         Rd, Rm, Rs, Rn);
                }
-               
-               /* SMUL<x><y> */
+
+               /* SMUL < x><y> */
                if ((opcode & 0x00600000) == 0x00300000)
                {
-                       u8 Rd, Rm, Rs;
+                       uint8_t Rd, Rm, Rs;
                        instruction->type = ARM_SMULxy;
                        Rd = (opcode & 0xf0000) >> 16;
                        Rm = (opcode & 0xf);
                        Rs = (opcode & 0xf00) >> 8;
-                       
-                       snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tSMULW%s%s%s r%i, r%i, r%i",
+
+                       snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s%s r%i, r%i, r%i",
                                         address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
                                         Rd, Rm, Rs);
                }
-               
-               /* SMULW<y> */
+
+               /* SMULW < y> */
                if (((opcode & 0x00600000) == 0x00100000) && (x == 1))
                {
-                       u8 Rd, Rm, Rs;
+                       uint8_t Rd, Rm, Rs;
                        instruction->type = ARM_SMULWy;
                        Rd = (opcode & 0xf0000) >> 16;
                        Rm = (opcode & 0xf);
                        Rs = (opcode & 0xf00) >> 8;
-                       
-                       snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tSMULW%s%s r%i, r%i, r%i",
+
+                       snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s r%i, r%i, r%i",
                                         address, opcode, (y) ? "T" : "B", COND(opcode),
                                         Rd, Rm, Rs);
                }
        }
-       
+
        return ERROR_OK;
 }
 
-int evaluate_data_proc(u32 opcode, u32 address, arm_instruction_t *instruction)
+int evaluate_data_proc(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
 {
-       u8 I, op, S, Rn, Rd;
-       char *mnemonic;
+       uint8_t I, op, S, Rn, Rd;
+       char *mnemonic = NULL;
        char shifter_operand[32];
-       
+
        I = (opcode & 0x02000000) >> 25;
        op = (opcode & 0x01e00000) >> 21;
        S = (opcode & 0x00100000) >> 20;
-       
+
        Rd = (opcode & 0xf000) >> 12;
        Rn = (opcode & 0xf0000) >> 16;
-       
+
        instruction->info.data_proc.Rd = Rd;
        instruction->info.data_proc.Rn = Rn;
        instruction->info.data_proc.S = S;
@@ -1044,36 +1056,48 @@ int evaluate_data_proc(u32 opcode, u32 address, arm_instruction_t *instruction)
                        mnemonic = "MVN";
                        break;
        }
-       
+
        if (I) /* immediate shifter operand (#<immediate>)*/
        {
-               u8 immed_8 = opcode & 0xff;
-               u8 rotate_imm = (opcode & 0xf00) >> 8;
-               u32 immediate;
-               
+               uint8_t immed_8 = opcode & 0xff;
+               uint8_t rotate_imm = (opcode & 0xf00) >> 8;
+               uint32_t immediate;
+
                immediate = ror(immed_8, rotate_imm * 2);
-               
-               snprintf(shifter_operand, 32, "#0x%x", immediate);
-               
+
+               snprintf(shifter_operand, 32, "#0x%" PRIx32 "", immediate);
+
                instruction->info.data_proc.variant = 0;
                instruction->info.data_proc.shifter_operand.immediate.immediate = immediate;
        }
        else /* register-based shifter operand */
        {
-               u8 shift, Rm;
+               uint8_t shift, Rm;
                shift = (opcode & 0x60) >> 5;
                Rm = (opcode & 0xf);
-               
+
                if ((opcode & 0x10) != 0x10) /* Immediate shifts ("<Rm>" or "<Rm>, <shift> #<shift_immediate>") */
                {
-                       u8 shift_imm;
+                       uint8_t shift_imm;
                        shift_imm = (opcode & 0xf80) >> 7;
 
                        instruction->info.data_proc.variant = 1;
                        instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
                        instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = shift_imm;
                        instruction->info.data_proc.shifter_operand.immediate_shift.shift = shift;
-               
+
+                       /* LSR encodes a shift by 32 bit as 0x0 */
+                       if ((shift == 0x1) && (shift_imm == 0x0))
+                               shift_imm = 0x20;
+
+                       /* ASR encodes a shift by 32 bit as 0x0 */
+                       if ((shift == 0x2) && (shift_imm == 0x0))
+                               shift_imm = 0x20;
+
+                       /* ROR by 32 bit is actually a RRX */
+                       if ((shift == 0x3) && (shift_imm == 0x0))
+                               shift = 0x4;
+
                        if ((shift_imm == 0x0) && (shift == 0x0))
                        {
                                snprintf(shifter_operand, 32, "r%i", Rm);
@@ -1086,34 +1110,31 @@ int evaluate_data_proc(u32 opcode, u32 address, arm_instruction_t *instruction)
                                }
                                else if (shift == 0x1) /* LSR */
                                {
-                                       if (shift_imm == 0x0)
-                                               shift_imm = 0x32;
                                        snprintf(shifter_operand, 32, "r%i, LSR #0x%x", Rm, shift_imm);
                                }
                                else if (shift == 0x2) /* ASR */
                                {
-                                       if (shift_imm == 0x0)
-                                               shift_imm = 0x32;
                                        snprintf(shifter_operand, 32, "r%i, ASR #0x%x", Rm, shift_imm);
                                }
-                               else if (shift == 0x3) /* ROR or RRX */
+                               else if (shift == 0x3) /* ROR */
                                {
-                                       if (shift_imm == 0x0) /* RRX */
-                                               snprintf(shifter_operand, 32, "r%i, RRX", Rm);
-                                       else
-                                               snprintf(shifter_operand, 32, "r%i, ROR #0x%x", Rm, shift_imm);
+                                       snprintf(shifter_operand, 32, "r%i, ROR #0x%x", Rm, shift_imm);
+                               }
+                               else if (shift == 0x4) /* RRX */
+                               {
+                                       snprintf(shifter_operand, 32, "r%i, RRX", Rm);
                                }
                        }
                }
                else /* Register shifts ("<Rm>, <shift> <Rs>") */
                {
-                       u8 Rs = (opcode & 0xf00) >> 8;
-                       
+                       uint8_t Rs = (opcode & 0xf00) >> 8;
+
                        instruction->info.data_proc.variant = 2;
                        instruction->info.data_proc.shifter_operand.register_shift.Rm = Rm;
                        instruction->info.data_proc.shifter_operand.register_shift.Rs = Rs;
                        instruction->info.data_proc.shifter_operand.register_shift.shift = shift;
-                       
+
                        if (shift == 0x0) /* LSL */
                        {
                                snprintf(shifter_operand, 32, "r%i, LSL r%i", Rm, Rs);
@@ -1126,96 +1147,100 @@ int evaluate_data_proc(u32 opcode, u32 address, arm_instruction_t *instruction)
                        {
                                snprintf(shifter_operand, 32, "r%i, ASR r%i", Rm, Rs);
                        }
-                       else if (shift == 0x3) /* ROR or RRX */
+                       else if (shift == 0x3) /* ROR */
                        {
                                snprintf(shifter_operand, 32, "r%i, ROR r%i", Rm, Rs);
                        }
                }
        }
-       
+
        if ((op < 0x8) || (op == 0xc) || (op == 0xe)) /* <opcode3>{<cond>}{S} <Rd>, <Rn>, <shifter_operand> */
        {
-               snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, r%i, %s",
+               snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, %s",
                                 address, opcode, mnemonic, COND(opcode),
                                 (S) ? "S" : "", Rd, Rn, shifter_operand);
        }
        else if ((op == 0xd) || (op == 0xf)) /* <opcode1>{<cond>}{S} <Rd>, <shifter_operand> */
        {
-               snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, %s",
+               if (opcode == 0xe1a00000) /* print MOV r0,r0 as NOP */
+                       snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tNOP",address, opcode);
+               else
+                       snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, %s",
                                 address, opcode, mnemonic, COND(opcode),
                                 (S) ? "S" : "", Rd, shifter_operand);
        }
        else /* <opcode2>{<cond>} <Rn>, <shifter_operand> */
        {
-               snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s r%i, %s",
+               snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, %s",
                                 address, opcode, mnemonic, COND(opcode),
                                 Rn, shifter_operand);
        }
-       
+
        return ERROR_OK;
 }
-               
-int evaluate_opcode(u32 opcode, u32 address, arm_instruction_t *instruction)
+
+int arm_evaluate_opcode(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
 {
        /* clear fields, to avoid confusion */
-       bzero(instruction, sizeof(arm_instruction_t));
+       memset(instruction, 0, sizeof(arm_instruction_t));
        instruction->opcode = opcode;
-       
+       instruction->instruction_size = 4;
+
        /* catch opcodes with condition field [31:28] = b1111 */
        if ((opcode & 0xf0000000) == 0xf0000000)
        {
                /* Undefined instruction (or ARMv5E cache preload PLD) */
                if ((opcode & 0x08000000) == 0x00000000)
                        return evaluate_pld(opcode, address, instruction);
-               
+
                /* Undefined instruction */
                if ((opcode & 0x0e000000) == 0x08000000)
                {
                        instruction->type = ARM_UNDEFINED_INSTRUCTION;
-                       snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tUNDEFINED INSTRUCTION", address, opcode);
+                       snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
                        return ERROR_OK;
                }
-               
+
                /* Branch and branch with link and change to Thumb */
                if ((opcode & 0x0e000000) == 0x0a000000)
                        return evaluate_blx_imm(opcode, address, instruction);
-               
-               /* Extended coprocessor opcode space (ARMv5 and higher )*/
+
+               /* Extended coprocessor opcode space (ARMv5 and higher)*/
                /* Coprocessor load/store and double register transfers */
                if ((opcode & 0x0e000000) == 0x0c000000)
                        return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
-               
+
                /* Coprocessor data processing */
                if ((opcode & 0x0f000100) == 0x0c000000)
                        return evaluate_cdp_mcr_mrc(opcode, address, instruction);
-               
+
                /* Coprocessor register transfers */
                if ((opcode & 0x0f000010) == 0x0c000010)
                        return evaluate_cdp_mcr_mrc(opcode, address, instruction);
-               
+
                /* Undefined instruction */
                if ((opcode & 0x0f000000) == 0x0f000000)
                {
                        instruction->type = ARM_UNDEFINED_INSTRUCTION;
-                       snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tUNDEFINED INSTRUCTION", address, opcode);
+                       snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
                        return ERROR_OK;
                }
        }
-       
+
        /* catch opcodes with [27:25] = b000 */
        if ((opcode & 0x0e000000) == 0x00000000)
        {
                /* Multiplies, extra load/stores */
                if ((opcode & 0x00000090) == 0x00000090)
                        return evaluate_mul_and_extra_ld_st(opcode, address, instruction);
-               
+
                /* Miscellaneous instructions */
                if ((opcode & 0x0f900000) == 0x01000000)
                        return evaluate_misc_instr(opcode, address, instruction);
-               
+
                return evaluate_data_proc(opcode, address, instruction);
        }
-       
+
        /* catch opcodes with [27:25] = b001 */
        if ((opcode & 0x0e000000) == 0x02000000)
        {
@@ -1223,78 +1248,1817 @@ int evaluate_opcode(u32 opcode, u32 address, arm_instruction_t *instruction)
                if ((opcode & 0x0fb00000) == 0x03000000)
                {
                        instruction->type = ARM_UNDEFINED_INSTRUCTION;
-                       snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tUNDEFINED INSTRUCTION", address, opcode);
+                       snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
                        return ERROR_OK;
                }
-                               
+
                /* Move immediate to status register */
                if ((opcode & 0x0fb00000) == 0x03200000)
                        return evaluate_mrs_msr(opcode, address, instruction);
-               
+
                return evaluate_data_proc(opcode, address, instruction);
 
        }
-       
+
        /* catch opcodes with [27:25] = b010 */
        if ((opcode & 0x0e000000) == 0x04000000)
        {
                /* Load/store immediate offset */
                return evaluate_load_store(opcode, address, instruction);
        }
-       
+
        /* catch opcodes with [27:25] = b011 */
-       if ((opcode & 0x0e000000) == 0x04000000)
+       if ((opcode & 0x0e000000) == 0x06000000)
        {
                /* Undefined instruction */
                if ((opcode & 0x00000010) == 0x00000010)
                {
                        instruction->type = ARM_UNDEFINED_INSTRUCTION;
-                       snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tUNDEFINED INSTRUCTION", address, opcode);
+                       snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
                        return ERROR_OK;
                }
-               
+
                /* Load/store register offset */
                return evaluate_load_store(opcode, address, instruction);
 
        }
-       
+
        /* catch opcodes with [27:25] = b100 */
        if ((opcode & 0x0e000000) == 0x08000000)
        {
                /* Load/store multiple */
                return evaluate_ldm_stm(opcode, address, instruction);
        }
-       
+
        /* catch opcodes with [27:25] = b101 */
        if ((opcode & 0x0e000000) == 0x0a000000)
        {
                /* Branch and branch with link */
                return evaluate_b_bl(opcode, address, instruction);
        }
-       
+
        /* catch opcodes with [27:25] = b110 */
        if ((opcode & 0x0e000000) == 0x0a000000)
        {
                /* Coprocessor load/store and double register transfers */
                return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
        }
-       
+
        /* catch opcodes with [27:25] = b111 */
        if ((opcode & 0x0e000000) == 0x0e000000)
        {
                /* Software interrupt */
                if ((opcode & 0x0f000000) == 0x0f000000)
                        return evaluate_swi(opcode, address, instruction);
-               
+
                /* Coprocessor data processing */
                if ((opcode & 0x0f000010) == 0x0e000000)
                        return evaluate_cdp_mcr_mrc(opcode, address, instruction);
-               
+
                /* Coprocessor register transfers */
                if ((opcode & 0x0f000010) == 0x0e000010)
                        return evaluate_cdp_mcr_mrc(opcode, address, instruction);
        }
-       
-       ERROR("should never reach this point");
+
+       LOG_ERROR("should never reach this point");
        return -1;
 }
+
+int evaluate_b_bl_blx_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
+{
+       uint32_t offset = opcode & 0x7ff;
+       uint32_t opc = (opcode >> 11) & 0x3;
+       uint32_t target_address;
+       char *mnemonic = NULL;
+
+       /* sign extend 11-bit offset */
+       if (((opc == 0) || (opc == 2)) && (offset & 0x00000400))
+               offset = 0xfffff800 | offset;
+
+       target_address = address + 4 + (offset << 1);
+
+       switch (opc)
+       {
+               /* unconditional branch */
+               case 0:
+                       instruction->type = ARM_B;
+                       mnemonic = "B";
+                       break;
+               /* BLX suffix */
+               case 1:
+                       instruction->type = ARM_BLX;
+                       mnemonic = "BLX";
+                       break;
+               /* BL/BLX prefix */
+               case 2:
+                       instruction->type = ARM_UNKNOWN_INSTUCTION;
+                       mnemonic = "prefix";
+                       target_address = offset << 12;
+                       break;
+               /* BL suffix */
+               case 3:
+                       instruction->type = ARM_BL;
+                       mnemonic = "BL";
+                       break;
+       }
+
+       /* 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.
+        */
+
+       snprintf(instruction->text, 128,
+                       "0x%8.8" PRIx32 "  0x%4.4x    \t%s\t%#8.8" PRIx32,
+                       address, opcode, mnemonic, target_address);
+
+       instruction->info.b_bl_bx_blx.reg_operand = -1;
+       instruction->info.b_bl_bx_blx.target_address = target_address;
+
+       return ERROR_OK;
+}
+
+int evaluate_add_sub_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
+{
+       uint8_t Rd = (opcode >> 0) & 0x7;
+       uint8_t Rn = (opcode >> 3) & 0x7;
+       uint8_t Rm_imm = (opcode >> 6) & 0x7;
+       uint32_t opc = opcode & (1 << 9);
+       uint32_t reg_imm  = opcode & (1 << 10);
+       char *mnemonic;
+
+       if (opc)
+       {
+               instruction->type = ARM_SUB;
+               mnemonic = "SUBS";
+       }
+       else
+       {
+               instruction->type = ARM_ADD;
+               mnemonic = "ADDS";
+       }
+
+       instruction->info.data_proc.Rd = Rd;
+       instruction->info.data_proc.Rn = Rn;
+       instruction->info.data_proc.S = 1;
+
+       if (reg_imm)
+       {
+               instruction->info.data_proc.variant = 0; /*immediate*/
+               instruction->info.data_proc.shifter_operand.immediate.immediate = Rm_imm;
+               snprintf(instruction->text, 128,
+                       "0x%8.8" PRIx32 "  0x%4.4x    \t%s\tr%i, r%i, #%d",
+                       address, opcode, mnemonic, Rd, Rn, Rm_imm);
+       }
+       else
+       {
+               instruction->info.data_proc.variant = 1; /*immediate shift*/
+               instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm_imm;
+               snprintf(instruction->text, 128,
+                       "0x%8.8" PRIx32 "  0x%4.4x    \t%s\tr%i, r%i, r%i",
+                       address, opcode, mnemonic, Rd, Rn, Rm_imm);
+       }
+
+       return ERROR_OK;
+}
+
+int evaluate_shift_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
+{
+       uint8_t Rd = (opcode >> 0) & 0x7;
+       uint8_t Rm = (opcode >> 3) & 0x7;
+       uint8_t imm = (opcode >> 6) & 0x1f;
+       uint8_t opc = (opcode >> 11) & 0x3;
+       char *mnemonic = NULL;
+
+       switch (opc)
+       {
+               case 0:
+                       instruction->type = ARM_MOV;
+                       mnemonic = "LSLS";
+                       instruction->info.data_proc.shifter_operand.immediate_shift.shift = 0;
+                       break;
+               case 1:
+                       instruction->type = ARM_MOV;
+                       mnemonic = "LSRS";
+                       instruction->info.data_proc.shifter_operand.immediate_shift.shift = 1;
+                       break;
+               case 2:
+                       instruction->type = ARM_MOV;
+                       mnemonic = "ASRS";
+                       instruction->info.data_proc.shifter_operand.immediate_shift.shift = 2;
+                       break;
+       }
+
+       if ((imm == 0) && (opc != 0))
+               imm = 32;
+
+       instruction->info.data_proc.Rd = Rd;
+       instruction->info.data_proc.Rn = -1;
+       instruction->info.data_proc.S = 1;
+
+       instruction->info.data_proc.variant = 1; /*immediate_shift*/
+       instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
+       instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = imm;
+
+       snprintf(instruction->text, 128,
+                       "0x%8.8" PRIx32 "  0x%4.4x    \t%s\tr%i, r%i, #%#2.2x" ,
+                       address, opcode, mnemonic, Rd, Rm, imm);
+
+       return ERROR_OK;
+}
+
+int evaluate_data_proc_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
+{
+       uint8_t imm = opcode & 0xff;
+       uint8_t Rd = (opcode >> 8) & 0x7;
+       uint32_t opc = (opcode >> 11) & 0x3;
+       char *mnemonic = NULL;
+
+       instruction->info.data_proc.Rd = Rd;
+       instruction->info.data_proc.Rn = Rd;
+       instruction->info.data_proc.S = 1;
+       instruction->info.data_proc.variant = 0; /*immediate*/
+       instruction->info.data_proc.shifter_operand.immediate.immediate = imm;
+
+       switch (opc)
+       {
+               case 0:
+                       instruction->type = ARM_MOV;
+                       mnemonic = "MOVS";
+                       instruction->info.data_proc.Rn = -1;
+                       break;
+               case 1:
+                       instruction->type = ARM_CMP;
+                       mnemonic = "CMP";
+                       instruction->info.data_proc.Rd = -1;
+                       break;
+               case 2:
+                       instruction->type = ARM_ADD;
+                       mnemonic = "ADDS";
+                       break;
+               case 3:
+                       instruction->type = ARM_SUB;
+                       mnemonic = "SUBS";
+                       break;
+       }
+
+       snprintf(instruction->text, 128,
+                       "0x%8.8" PRIx32 "  0x%4.4x    \t%s\tr%i, #%#2.2x",
+                       address, opcode, mnemonic, Rd, imm);
+
+       return ERROR_OK;
+}
+
+int evaluate_data_proc_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
+{
+       uint8_t high_reg, op, Rm, Rd,H1,H2;
+       char *mnemonic = NULL;
+       bool nop = false;
+
+       high_reg = (opcode & 0x0400) >> 10;
+       op = (opcode & 0x03C0) >> 6;
+
+       Rd = (opcode & 0x0007);
+       Rm = (opcode & 0x0038) >> 3;
+       H1 = (opcode & 0x0080) >> 7;
+       H2 = (opcode & 0x0040) >> 6;
+
+       instruction->info.data_proc.Rd = Rd;
+       instruction->info.data_proc.Rn = Rd;
+       instruction->info.data_proc.S = (!high_reg || (instruction->type == ARM_CMP));
+       instruction->info.data_proc.variant = 1 /*immediate shift*/;
+       instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
+
+       if (high_reg)
+       {
+               Rd |= H1 << 3;
+               Rm |= H2 << 3;
+               op >>= 2;
+
+               switch (op)
+               {
+                       case 0x0:
+                               instruction->type = ARM_ADD;
+                               mnemonic = "ADD";
+                               break;
+                       case 0x1:
+                               instruction->type = ARM_CMP;
+                               mnemonic = "CMP";
+                               break;
+                       case 0x2:
+                               instruction->type = ARM_MOV;
+                               mnemonic = "MOV";
+                               if (Rd == Rm)
+                                       nop = true;
+                               break;
+                       case 0x3:
+                               if ((opcode & 0x7) == 0x0)
+                               {
+                                       instruction->info.b_bl_bx_blx.reg_operand = Rm;
+                                       if (H1)
+                                       {
+                                               instruction->type = ARM_BLX;
+                                               snprintf(instruction->text, 128,
+                                                       "0x%8.8" PRIx32
+                                                       "  0x%4.4x    \tBLX\tr%i",
+                                                       address, opcode, Rm);
+                                       }
+                                       else
+                                       {
+                                               instruction->type = ARM_BX;
+                                               snprintf(instruction->text, 128,
+                                                       "0x%8.8" PRIx32
+                                                       "  0x%4.4x    \tBX\tr%i",
+                                                       address, opcode, Rm);
+                                       }
+                               }
+                               else
+                               {
+                                       instruction->type = ARM_UNDEFINED_INSTRUCTION;
+                                       snprintf(instruction->text, 128,
+                                               "0x%8.8" PRIx32
+                                               "  0x%4.4x    \t"
+                                               "UNDEFINED INSTRUCTION",
+                                               address, opcode);
+                               }
+                               return ERROR_OK;
+                               break;
+               }
+       }
+       else
+       {
+               switch (op)
+               {
+                       case 0x0:
+                               instruction->type = ARM_AND;
+                               mnemonic = "ANDS";
+                               break;
+                       case 0x1:
+                               instruction->type = ARM_EOR;
+                               mnemonic = "EORS";
+                               break;
+                       case 0x2:
+                               instruction->type = ARM_MOV;
+                               mnemonic = "LSLS";
+                               instruction->info.data_proc.variant = 2 /*register shift*/;
+                               instruction->info.data_proc.shifter_operand.register_shift.shift = 0;
+                               instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
+                               instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
+                               break;
+                       case 0x3:
+                               instruction->type = ARM_MOV;
+                               mnemonic = "LSRS";
+                               instruction->info.data_proc.variant = 2 /*register shift*/;
+                               instruction->info.data_proc.shifter_operand.register_shift.shift = 1;
+                               instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
+                               instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
+                               break;
+                       case 0x4:
+                               instruction->type = ARM_MOV;
+                               mnemonic = "ASRS";
+                               instruction->info.data_proc.variant = 2 /*register shift*/;
+                               instruction->info.data_proc.shifter_operand.register_shift.shift = 2;
+                               instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
+                               instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
+                               break;
+                       case 0x5:
+                               instruction->type = ARM_ADC;
+                               mnemonic = "ADCS";
+                               break;
+                       case 0x6:
+                               instruction->type = ARM_SBC;
+                               mnemonic = "SBCS";
+                               break;
+                       case 0x7:
+                               instruction->type = ARM_MOV;
+                               mnemonic = "RORS";
+                               instruction->info.data_proc.variant = 2 /*register shift*/;
+                               instruction->info.data_proc.shifter_operand.register_shift.shift = 3;
+                               instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
+                               instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
+                               break;
+                       case 0x8:
+                               instruction->type = ARM_TST;
+                               mnemonic = "TST";
+                               break;
+                       case 0x9:
+                               instruction->type = ARM_RSB;
+                               mnemonic = "NEGS";
+                               instruction->info.data_proc.variant = 0 /*immediate*/;
+                               instruction->info.data_proc.shifter_operand.immediate.immediate = 0;
+                               instruction->info.data_proc.Rn = Rm;
+                               break;
+                       case 0xA:
+                               instruction->type = ARM_CMP;
+                               mnemonic = "CMP";
+                               break;
+                       case 0xB:
+                               instruction->type = ARM_CMN;
+                               mnemonic = "CMN";
+                               break;
+                       case 0xC:
+                               instruction->type = ARM_ORR;
+                               mnemonic = "ORRS";
+                               break;
+                       case 0xD:
+                               instruction->type = ARM_MUL;
+                               mnemonic = "MULS";
+                               break;
+                       case 0xE:
+                               instruction->type = ARM_BIC;
+                               mnemonic = "BICS";
+                               break;
+                       case 0xF:
+                               instruction->type = ARM_MVN;
+                               mnemonic = "MVNS";
+                               break;
+               }
+       }
+
+       if (nop)
+               snprintf(instruction->text, 128,
+                               "0x%8.8" PRIx32 "  0x%4.4x    \tNOP\t\t\t"
+                               "; (%s r%i, r%i)",
+                                address, opcode, mnemonic, Rd, Rm);
+       else
+               snprintf(instruction->text, 128,
+                               "0x%8.8" PRIx32 "  0x%4.4x    \t%s\tr%i, r%i",
+                                address, opcode, mnemonic, Rd, Rm);
+
+       return ERROR_OK;
+}
+
+/* PC-relative data addressing is word-aligned even with Thumb */
+static inline uint32_t thumb_alignpc4(uint32_t addr)
+{
+       return (addr + 4) & ~3;
+}
+
+int evaluate_load_literal_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
+{
+       uint32_t immediate;
+       uint8_t Rd = (opcode >> 8) & 0x7;
+
+       instruction->type = ARM_LDR;
+       immediate = opcode & 0x000000ff;
+       immediate *= 4;
+
+       instruction->info.load_store.Rd = Rd;
+       instruction->info.load_store.Rn = 15 /*PC*/;
+       instruction->info.load_store.index_mode = 0; /*offset*/
+       instruction->info.load_store.offset_mode = 0; /*immediate*/
+       instruction->info.load_store.offset.offset = immediate;
+
+       snprintf(instruction->text, 128,
+               "0x%8.8" PRIx32 "  0x%4.4x    \t"
+               "LDR\tr%i, [pc, #%#" PRIx32 "]\t; %#8.8x",
+               address, opcode, Rd, immediate,
+               thumb_alignpc4(address) + immediate);
+
+       return ERROR_OK;
+}
+
+int evaluate_load_store_reg_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
+{
+       uint8_t Rd = (opcode >> 0) & 0x7;
+       uint8_t Rn = (opcode >> 3) & 0x7;
+       uint8_t Rm = (opcode >> 6) & 0x7;
+       uint8_t opc = (opcode >> 9) & 0x7;
+       char *mnemonic = NULL;
+
+       switch (opc)
+       {
+               case 0:
+                       instruction->type = ARM_STR;
+                       mnemonic = "STR";
+                       break;
+               case 1:
+                       instruction->type = ARM_STRH;
+                       mnemonic = "STRH";
+                       break;
+               case 2:
+                       instruction->type = ARM_STRB;
+                       mnemonic = "STRB";
+                       break;
+               case 3:
+                       instruction->type = ARM_LDRSB;
+                       mnemonic = "LDRSB";
+                       break;
+               case 4:
+                       instruction->type = ARM_LDR;
+                       mnemonic = "LDR";
+                       break;
+               case 5:
+                       instruction->type = ARM_LDRH;
+                       mnemonic = "LDRH";
+                       break;
+               case 6:
+                       instruction->type = ARM_LDRB;
+                       mnemonic = "LDRB";
+                       break;
+               case 7:
+                       instruction->type = ARM_LDRSH;
+                       mnemonic = "LDRSH";
+                       break;
+       }
+
+       snprintf(instruction->text, 128,
+                       "0x%8.8" PRIx32 "  0x%4.4x    \t%s\tr%i, [r%i, r%i]",
+                       address, opcode, mnemonic, Rd, Rn, Rm);
+
+       instruction->info.load_store.Rd = Rd;
+       instruction->info.load_store.Rn = Rn;
+       instruction->info.load_store.index_mode = 0; /*offset*/
+       instruction->info.load_store.offset_mode = 1; /*register*/
+       instruction->info.load_store.offset.reg.Rm = Rm;
+
+       return ERROR_OK;
+}
+
+int evaluate_load_store_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
+{
+       uint32_t offset = (opcode >> 6) & 0x1f;
+       uint8_t Rd = (opcode >> 0) & 0x7;
+       uint8_t Rn = (opcode >> 3) & 0x7;
+       uint32_t L = opcode & (1 << 11);
+       uint32_t B = opcode & (1 << 12);
+       char *mnemonic;
+       char suffix = ' ';
+       uint32_t shift = 2;
+
+       if (L)
+       {
+               instruction->type = ARM_LDR;
+               mnemonic = "LDR";
+       }
+       else
+       {
+               instruction->type = ARM_STR;
+               mnemonic = "STR";
+       }
+
+       if ((opcode&0xF000) == 0x8000)
+       {
+               suffix = 'H';
+               shift = 1;
+       }
+       else if (B)
+       {
+               suffix = 'B';
+               shift = 0;
+       }
+
+       snprintf(instruction->text, 128,
+               "0x%8.8" PRIx32 "  0x%4.4x    \t%s%c\tr%i, [r%i, #%#" PRIx32 "]",
+               address, opcode, mnemonic, suffix, Rd, Rn, offset << shift);
+
+       instruction->info.load_store.Rd = Rd;
+       instruction->info.load_store.Rn = Rn;
+       instruction->info.load_store.index_mode = 0; /*offset*/
+       instruction->info.load_store.offset_mode = 0; /*immediate*/
+       instruction->info.load_store.offset.offset = offset << shift;
+
+       return ERROR_OK;
+}
+
+int evaluate_load_store_stack_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
+{
+       uint32_t offset = opcode  & 0xff;
+       uint8_t Rd = (opcode >> 8) & 0x7;
+       uint32_t L = opcode & (1 << 11);
+       char *mnemonic;
+
+       if (L)
+       {
+               instruction->type = ARM_LDR;
+               mnemonic = "LDR";
+       }
+       else
+       {
+               instruction->type = ARM_STR;
+               mnemonic = "STR";
+       }
+
+       snprintf(instruction->text, 128,
+               "0x%8.8" PRIx32 "  0x%4.4x    \t%s\tr%i, [SP, #%#" PRIx32 "]",
+               address, opcode, mnemonic, Rd, offset*4);
+
+       instruction->info.load_store.Rd = Rd;
+       instruction->info.load_store.Rn = 13 /*SP*/;
+       instruction->info.load_store.index_mode = 0; /*offset*/
+       instruction->info.load_store.offset_mode = 0; /*immediate*/
+       instruction->info.load_store.offset.offset = offset*4;
+
+       return ERROR_OK;
+}
+
+int evaluate_add_sp_pc_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
+{
+       uint32_t imm = opcode  & 0xff;
+       uint8_t Rd = (opcode >> 8) & 0x7;
+       uint8_t Rn;
+       uint32_t SP = opcode & (1 << 11);
+       char *reg_name;
+
+       instruction->type = ARM_ADD;
+
+       if (SP)
+       {
+               reg_name = "SP";
+               Rn = 13;
+       }
+       else
+       {
+               reg_name = "PC";
+               Rn = 15;
+       }
+
+       snprintf(instruction->text, 128,
+               "0x%8.8" PRIx32 "  0x%4.4x  \tADD\tr%i, %s, #%#" PRIx32,
+               address, opcode, Rd, reg_name, imm * 4);
+
+       instruction->info.data_proc.variant = 0 /* immediate */;
+       instruction->info.data_proc.Rd = Rd;
+       instruction->info.data_proc.Rn = Rn;
+       instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
+
+       return ERROR_OK;
+}
+
+int evaluate_adjust_stack_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
+{
+       uint32_t imm = opcode  & 0x7f;
+       uint8_t opc = opcode & (1 << 7);
+       char *mnemonic;
+
+
+       if (opc)
+       {
+               instruction->type = ARM_SUB;
+               mnemonic = "SUB";
+       }
+       else
+       {
+               instruction->type = ARM_ADD;
+               mnemonic = "ADD";
+       }
+
+       snprintf(instruction->text, 128,
+                       "0x%8.8" PRIx32 "  0x%4.4x    \t%s\tSP, #%#" PRIx32,
+                       address, opcode, mnemonic, imm*4);
+
+       instruction->info.data_proc.variant = 0 /* immediate */;
+       instruction->info.data_proc.Rd = 13 /*SP*/;
+       instruction->info.data_proc.Rn = 13 /*SP*/;
+       instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
+
+       return ERROR_OK;
+}
+
+int evaluate_breakpoint_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
+{
+       uint32_t imm = opcode  & 0xff;
+
+       instruction->type = ARM_BKPT;
+
+       snprintf(instruction->text, 128,
+                       "0x%8.8" PRIx32 "  0x%4.4x  \tBKPT\t%#2.2" PRIx32 "",
+                       address, opcode, imm);
+
+       return ERROR_OK;
+}
+
+int evaluate_load_store_multiple_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
+{
+       uint32_t reg_list = opcode  & 0xff;
+       uint32_t L = opcode & (1 << 11);
+       uint32_t R = opcode & (1 << 8);
+       uint8_t Rn = (opcode >> 8) & 7;
+       uint8_t addr_mode = 0 /* IA */;
+       char reg_names[40];
+       char *reg_names_p;
+       char *mnemonic;
+       char ptr_name[7] = "";
+       int i;
+
+       if ((opcode & 0xf000) == 0xc000)
+       { /* generic load/store multiple */
+               if (L)
+               {
+                       instruction->type = ARM_LDM;
+                       mnemonic = "LDM";
+               }
+               else
+               {
+                       instruction->type = ARM_STM;
+                       mnemonic = "STM";
+               }
+               snprintf(ptr_name,7,"r%i!, ",Rn);
+       }
+       else
+       { /* push/pop */
+               Rn = 13; /* SP */
+               if (L)
+               {
+                       instruction->type = ARM_LDM;
+                       mnemonic = "POP";
+                       if (R)
+                               reg_list |= (1 << 15) /*PC*/;
+               }
+               else
+               {
+                       instruction->type = ARM_STM;
+                       mnemonic = "PUSH";
+                       addr_mode = 3; /*DB*/
+                       if (R)
+                               reg_list |= (1 << 14) /*LR*/;
+               }
+       }
+
+       reg_names_p = reg_names;
+       for (i = 0; i <= 15; i++)
+       {
+               if (reg_list & (1 << i))
+                       reg_names_p += snprintf(reg_names_p, (reg_names + 40 - reg_names_p), "r%i, ", i);
+       }
+       if (reg_names_p > reg_names)
+               reg_names_p[-2] = '\0';
+       else /* invalid op : no registers */
+               reg_names[0] = '\0';
+
+       snprintf(instruction->text, 128,
+                       "0x%8.8" PRIx32 "  0x%4.4x  \t%s\t%s{%s}",
+                       address, opcode, mnemonic, ptr_name, reg_names);
+
+       instruction->info.load_store_multiple.register_list = reg_list;
+       instruction->info.load_store_multiple.Rn = Rn;
+       instruction->info.load_store_multiple.addressing_mode = addr_mode;
+
+       return ERROR_OK;
+}
+
+int evaluate_cond_branch_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
+{
+       uint32_t offset = opcode  & 0xff;
+       uint8_t cond = (opcode >> 8) & 0xf;
+       uint32_t target_address;
+
+       if (cond == 0xf)
+       {
+               instruction->type = ARM_SWI;
+               snprintf(instruction->text, 128,
+                               "0x%8.8" PRIx32 "  0x%4.4x    \tSVC\t%#2.2" PRIx32,
+                               address, opcode, offset);
+               return ERROR_OK;
+       }
+       else if (cond == 0xe)
+       {
+               instruction->type = ARM_UNDEFINED_INSTRUCTION;
+               snprintf(instruction->text, 128,
+                       "0x%8.8" PRIx32 "  0x%4.4x    \tUNDEFINED INSTRUCTION",
+                       address, opcode);
+               return ERROR_OK;
+       }
+
+       /* sign extend 8-bit offset */
+       if (offset & 0x00000080)
+               offset = 0xffffff00 | offset;
+
+       target_address = address + 4 + (offset << 1);
+
+       snprintf(instruction->text, 128,
+                       "0x%8.8" PRIx32 "  0x%4.4x    \tB%s\t%#8.8" PRIx32,
+                       address, opcode,
+                       arm_condition_strings[cond], target_address);
+
+       instruction->type = ARM_B;
+       instruction->info.b_bl_bx_blx.reg_operand = -1;
+       instruction->info.b_bl_bx_blx.target_address = target_address;
+
+       return ERROR_OK;
+}
+
+static int evaluate_cb_thumb(uint16_t opcode, uint32_t address,
+               arm_instruction_t *instruction)
+{
+       unsigned offset;
+
+       /* added in Thumb2 */
+       offset = (opcode >> 3) & 0x1f;
+       offset |= (opcode & 0x0200) >> 4;
+
+       snprintf(instruction->text, 128,
+                       "0x%8.8" PRIx32 "  0x%4.4x    \tCB%sZ\tr%d, %#8.8" PRIx32,
+                       address, opcode,
+                       (opcode & 0x0800) ? "N" : "",
+                       opcode & 0x7, address + 4 + (offset << 1));
+
+       return ERROR_OK;
+}
+
+static int evaluate_extend_thumb(uint16_t opcode, uint32_t address,
+               arm_instruction_t *instruction)
+{
+       /* added in ARMv6 */
+       snprintf(instruction->text, 128,
+                       "0x%8.8" PRIx32 "  0x%4.4x    \t%cXT%c\tr%d, r%d",
+                       address, opcode,
+                       (opcode & 0x0080) ? 'U' : 'S',
+                       (opcode & 0x0040) ? 'B' : 'H',
+                       opcode & 0x7, (opcode >> 3) & 0x7);
+
+       return ERROR_OK;
+}
+
+static int evaluate_cps_thumb(uint16_t opcode, uint32_t address,
+               arm_instruction_t *instruction)
+{
+       /* added in ARMv6 */
+       if ((opcode & 0x0ff0) == 0x0650)
+               snprintf(instruction->text, 128,
+                               "0x%8.8" PRIx32 "  0x%4.4x    \tSETEND %s",
+                               address, opcode,
+                               (opcode & 0x80) ? "BE" : "LE");
+       else /* ASSUME (opcode & 0x0fe0) == 0x0660 */
+               snprintf(instruction->text, 128,
+                               "0x%8.8" PRIx32 "  0x%4.4x    \tCPSI%c %s%s%s",
+                               address, opcode,
+                               (opcode & 0x0010) ? 'D' : 'E',
+                               (opcode & 0x0004) ? "A" : "",
+                               (opcode & 0x0002) ? "I" : "",
+                               (opcode & 0x0001) ? "F" : "");
+
+       return ERROR_OK;
+}
+
+static int evaluate_byterev_thumb(uint16_t opcode, uint32_t address,
+               arm_instruction_t *instruction)
+{
+       char *suffix;
+
+       /* added in ARMv6 */
+       switch (opcode & 0x00c0) {
+       case 0:
+               suffix = "";
+               break;
+       case 1:
+               suffix = "16";
+               break;
+       default:
+               suffix = "SH";
+               break;
+       }
+       snprintf(instruction->text, 128,
+                       "0x%8.8" PRIx32 "  0x%4.4x    \tREV%s\tr%d, r%d",
+                       address, opcode, suffix,
+                       opcode & 0x7, (opcode >> 3) & 0x7);
+
+       return ERROR_OK;
+}
+
+static int evaluate_hint_thumb(uint16_t opcode, uint32_t address,
+               arm_instruction_t *instruction)
+{
+       char *hint;
+
+       switch ((opcode >> 4) & 0x0f) {
+       case 0:
+               hint = "NOP";
+               break;
+       case 1:
+               hint = "YIELD";
+               break;
+       case 2:
+               hint = "WFE";
+               break;
+       case 3:
+               hint = "WFI";
+               break;
+       case 4:
+               hint = "SEV";
+               break;
+       default:
+               hint = "HINT (UNRECOGNIZED)";
+               break;
+       }
+
+       snprintf(instruction->text, 128,
+                       "0x%8.8" PRIx32 "  0x%4.4x    \t%s",
+                       address, opcode, hint);
+
+       return ERROR_OK;
+}
+
+static int evaluate_ifthen_thumb(uint16_t opcode, uint32_t address,
+               arm_instruction_t *instruction)
+{
+       unsigned cond = (opcode >> 4) & 0x0f;
+       char *x = "", *y = "", *z = "";
+
+       if (opcode & 0x01)
+               z = (opcode & 0x02) ? "T" : "E";
+       if (opcode & 0x03)
+               y = (opcode & 0x04) ? "T" : "E";
+       if (opcode & 0x07)
+               x = (opcode & 0x08) ? "T" : "E";
+
+       snprintf(instruction->text, 128,
+                       "0x%8.8" PRIx32 "  0x%4.4x    \tIT%s%s%s\t%s",
+                       address, opcode,
+                       x, y, z, arm_condition_strings[cond]);
+
+       /* NOTE:  strictly speaking, the next 1-4 instructions should
+        * now be displayed with the relevant conditional suffix...
+        */
+
+       return ERROR_OK;
+}
+
+int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
+{
+       /* clear fields, to avoid confusion */
+       memset(instruction, 0, sizeof(arm_instruction_t));
+       instruction->opcode = opcode;
+       instruction->instruction_size = 2;
+
+       if ((opcode & 0xe000) == 0x0000)
+       {
+               /* add/substract register or immediate */
+               if ((opcode & 0x1800) == 0x1800)
+                       return evaluate_add_sub_thumb(opcode, address, instruction);
+               /* shift by immediate */
+               else
+                       return evaluate_shift_imm_thumb(opcode, address, instruction);
+       }
+
+       /* Add/substract/compare/move immediate */
+       if ((opcode & 0xe000) == 0x2000)
+       {
+               return evaluate_data_proc_imm_thumb(opcode, address, instruction);
+       }
+
+       /* Data processing instructions */
+       if ((opcode & 0xf800) == 0x4000)
+       {
+               return evaluate_data_proc_thumb(opcode, address, instruction);
+       }
+
+       /* Load from literal pool */
+       if ((opcode & 0xf800) == 0x4800)
+       {
+               return evaluate_load_literal_thumb(opcode, address, instruction);
+       }
+
+       /* Load/Store register offset */
+       if ((opcode & 0xf000) == 0x5000)
+       {
+               return evaluate_load_store_reg_thumb(opcode, address, instruction);
+       }
+
+       /* Load/Store immediate offset */
+       if (((opcode & 0xe000) == 0x6000)
+               ||((opcode & 0xf000) == 0x8000))
+       {
+               return evaluate_load_store_imm_thumb(opcode, address, instruction);
+       }
+
+       /* Load/Store from/to stack */
+       if ((opcode & 0xf000) == 0x9000)
+       {
+               return evaluate_load_store_stack_thumb(opcode, address, instruction);
+       }
+
+       /* Add to SP/PC */
+       if ((opcode & 0xf000) == 0xa000)
+       {
+               return evaluate_add_sp_pc_thumb(opcode, address, instruction);
+       }
+
+       /* Misc */
+       if ((opcode & 0xf000) == 0xb000)
+       {
+               switch ((opcode >> 8) & 0x0f) {
+               case 0x0:
+                       return evaluate_adjust_stack_thumb(opcode, address, instruction);
+               case 0x1:
+               case 0x3:
+               case 0x9:
+               case 0xb:
+                       return evaluate_cb_thumb(opcode, address, instruction);
+               case 0x2:
+                       return evaluate_extend_thumb(opcode, address, instruction);
+               case 0x4:
+               case 0x5:
+               case 0xc:
+               case 0xd:
+                       return evaluate_load_store_multiple_thumb(opcode, address,
+                                               instruction);
+               case 0x6:
+                       return evaluate_cps_thumb(opcode, address, instruction);
+               case 0xa:
+                       if ((opcode & 0x00c0) == 0x0080)
+                               break;
+                       return evaluate_byterev_thumb(opcode, address, instruction);
+               case 0xe:
+                       return evaluate_breakpoint_thumb(opcode, address, instruction);
+               case 0xf:
+                       if (opcode & 0x000f)
+                               return evaluate_ifthen_thumb(opcode, address,
+                                               instruction);
+                       else
+                               return evaluate_hint_thumb(opcode, address,
+                                               instruction);
+               }
+
+               instruction->type = ARM_UNDEFINED_INSTRUCTION;
+               snprintf(instruction->text, 128,
+                       "0x%8.8" PRIx32 "  0x%4.4x    \tUNDEFINED INSTRUCTION",
+                       address, opcode);
+               return ERROR_OK;
+       }
+
+       /* Load/Store multiple */
+       if ((opcode & 0xf000) == 0xc000)
+       {
+               return evaluate_load_store_multiple_thumb(opcode, address, instruction);
+       }
+
+       /* Conditional branch + SWI */
+       if ((opcode & 0xf000) == 0xd000)
+       {
+               return evaluate_cond_branch_thumb(opcode, address, instruction);
+       }
+
+       if ((opcode & 0xe000) == 0xe000)
+       {
+               /* Undefined instructions */
+               if ((opcode & 0xf801) == 0xe801)
+               {
+                       instruction->type = ARM_UNDEFINED_INSTRUCTION;
+                       snprintf(instruction->text, 128,
+                                       "0x%8.8" PRIx32 "  0x%8.8x\t"
+                                       "UNDEFINED INSTRUCTION",
+                                       address, opcode);
+                       return ERROR_OK;
+               }
+               else
+               { /* Branch to offset */
+                       return evaluate_b_bl_blx_thumb(opcode, address, instruction);
+               }
+       }
+
+       LOG_ERROR("should never reach this point (opcode=%04x)",opcode);
+       return -1;
+}
+
+static int t2ev_b_bl(uint32_t opcode, uint32_t address,
+               arm_instruction_t *instruction, char *cp)
+{
+       unsigned offset;
+       unsigned b21 = 1 << 21;
+       unsigned b22 = 1 << 22;
+
+       /* instead of combining two smaller 16-bit branch instructions,
+        * Thumb2 uses only one larger 32-bit instruction.
+        */
+       offset = opcode & 0x7ff;
+       offset |= (opcode & 0x03ff0000) >> 5;
+       if (opcode & (1 << 26)) {
+               offset |= 0xff << 23;
+               if ((opcode & (1 << 11)) == 0)
+                       b21 = 0;
+               if ((opcode & (1 << 13)) == 0)
+                       b22 = 0;
+       } else {
+               if (opcode & (1 << 11))
+                       b21 = 0;
+               if (opcode & (1 << 13))
+                       b22 = 0;
+       }
+       offset |= b21;
+       offset |= b22;
+
+
+       address += 4;
+       address += offset << 1;
+
+       instruction->type = (opcode & (1 << 14)) ? ARM_BL : ARM_B;
+       instruction->info.b_bl_bx_blx.reg_operand = -1;
+       instruction->info.b_bl_bx_blx.target_address = address;
+       sprintf(cp, "%s\t%#8.8" PRIx32,
+                       (opcode & (1 << 14)) ? "BL" : "B.W",
+                       address);
+
+       return ERROR_OK;
+}
+
+static int t2ev_cond_b(uint32_t opcode, uint32_t address,
+               arm_instruction_t *instruction, char *cp)
+{
+       unsigned offset;
+       unsigned b17 = 1 << 17;
+       unsigned b18 = 1 << 18;
+       unsigned cond = (opcode >> 22) & 0x0f;
+
+       offset = opcode & 0x7ff;
+       offset |= (opcode & 0x003f0000) >> 5;
+       if (opcode & (1 << 26)) {
+               offset |= 0xffff << 19;
+               if ((opcode & (1 << 11)) == 0)
+                       b17 = 0;
+               if ((opcode & (1 << 13)) == 0)
+                       b18 = 0;
+       } else {
+               if (opcode & (1 << 11))
+                       b17 = 0;
+               if (opcode & (1 << 13))
+                       b18 = 0;
+       }
+       offset |= b17;
+       offset |= b18;
+
+       address += 4;
+       address += offset << 1;
+
+       instruction->type = ARM_B;
+       instruction->info.b_bl_bx_blx.reg_operand = -1;
+       instruction->info.b_bl_bx_blx.target_address = address;
+       sprintf(cp, "B%s.W\t%#8.8" PRIx32,
+                       arm_condition_strings[cond],
+                       address);
+
+       return ERROR_OK;
+}
+
+static const char *special_name(int number)
+{
+       char *special = "(RESERVED)";
+
+       switch (number) {
+       case 0:
+               special = "apsr";
+               break;
+       case 1:
+               special = "iapsr";
+               break;
+       case 2:
+               special = "eapsr";
+               break;
+       case 3:
+               special = "xpsr";
+               break;
+       case 5:
+               special = "ipsr";
+               break;
+       case 6:
+               special = "epsr";
+               break;
+       case 7:
+               special = "iepsr";
+               break;
+       case 8:
+               special = "msp";
+               break;
+       case 9:
+               special = "psp";
+               break;
+       case 16:
+               special = "primask";
+               break;
+       case 17:
+               special = "basepri";
+               break;
+       case 18:
+               special = "basepri_max";
+               break;
+       case 19:
+               special = "faultmask";
+               break;
+       case 20:
+               special = "control";
+               break;
+       }
+       return special;
+}
+
+static int t2ev_hint(uint32_t opcode, uint32_t address,
+               arm_instruction_t *instruction, char *cp)
+{
+       const char *mnemonic;
+
+       if (opcode & 0x0700) {
+               instruction->type = ARM_UNDEFINED_INSTRUCTION;
+               strcpy(cp, "UNDEFINED");
+               return ERROR_OK;
+       }
+
+       if (opcode & 0x00f0) {
+               sprintf(cp, "DBG\t#%d", opcode & 0xf);
+               return ERROR_OK;
+       }
+
+       switch (opcode & 0x0f) {
+       case 0:
+               mnemonic = "NOP.W";
+               break;
+       case 1:
+               mnemonic = "YIELD.W";
+               break;
+       case 2:
+               mnemonic = "WFE.W";
+               break;
+       case 3:
+               mnemonic = "WFI.W";
+               break;
+       case 4:
+               mnemonic = "SEV.W";
+               break;
+       default:
+               mnemonic = "HINT.W (UNRECOGNIZED)";
+               break;
+       }
+       strcpy(cp, mnemonic);
+       return ERROR_OK;
+}
+
+static int t2ev_misc(uint32_t opcode, uint32_t address,
+               arm_instruction_t *instruction, char *cp)
+{
+       const char *mnemonic;
+
+       switch ((opcode >> 4) & 0x0f) {
+       case 2:
+               mnemonic = "CLREX";
+               break;
+       case 4:
+               mnemonic = "DSB";
+               break;
+       case 5:
+               mnemonic = "DMB";
+               break;
+       case 6:
+               mnemonic = "ISB";
+               break;
+       default:
+               return ERROR_INVALID_ARGUMENTS;
+       }
+       strcpy(cp, mnemonic);
+       return ERROR_OK;
+}
+
+static int t2ev_b_misc(uint32_t opcode, uint32_t address,
+               arm_instruction_t *instruction, char *cp)
+{
+       /* permanently undefined */
+       if ((opcode & 0x07f07000) == 0x07f02000) {
+               instruction->type = ARM_UNDEFINED_INSTRUCTION;
+               strcpy(cp, "UNDEFINED");
+               return ERROR_OK;
+       }
+
+       switch ((opcode >> 12) & 0x5) {
+       case 0x1:
+       case 0x5:
+               return t2ev_b_bl(opcode, address, instruction, cp);
+       case 0x4:
+               goto undef;
+       case 0:
+               if (((opcode >> 23) & 0x07) == 0x07)
+                       return t2ev_cond_b(opcode, address, instruction, cp);
+               if (opcode & (1 << 26))
+                       goto undef;
+               break;
+       }
+
+       switch ((opcode >> 20) & 0x7f) {
+       case 0x38:
+       case 0x39:
+               sprintf(cp, "MSR\t%s, r%d", special_name(opcode & 0xff),
+                               (opcode >> 16) & 0x0f);
+               return ERROR_OK;
+       case 0x3a:
+               return t2ev_hint(opcode, address, instruction, cp);
+       case 0x3b:
+               return t2ev_misc(opcode, address, instruction, cp);
+       case 0x3e:
+       case 0x3f:
+               sprintf(cp, "MRS\tr%d, %s", (opcode >> 16) & 0x0f,
+                               special_name(opcode & 0xff));
+               return ERROR_OK;
+       }
+
+undef:
+       return ERROR_INVALID_ARGUMENTS;
+}
+
+static int t2ev_data_mod_immed(uint32_t opcode, uint32_t address,
+               arm_instruction_t *instruction, char *cp)
+{
+       char *mnemonic = NULL;
+       int rn = (opcode >> 16) & 0xf;
+       int rd = (opcode >> 8) & 0xf;
+       unsigned immed = opcode & 0xff;
+       unsigned func;
+       bool one = false;
+       char *suffix = "";
+
+       /* ARMv7-M: A5.3.2 Modified immediate constants */
+       func = (opcode >> 11) & 0x0e;
+       if (immed & 0x80)
+               func |= 1;
+       if (opcode & (1 << 26))
+               func |= 0x10;
+
+       /* "Modified" immediates */
+       switch (func >> 1) {
+       case 0:
+               break;
+       case 2:
+               immed <<= 8;
+               /* FALLTHROUGH */
+       case 1:
+               immed += immed << 16;
+               break;
+       case 3:
+               immed += immed << 8;
+               immed += immed << 16;
+               break;
+       default:
+               immed |= 0x80;
+               immed = ror(immed, func);
+       }
+
+       if (opcode & (1 << 20))
+               suffix = "S";
+
+       switch ((opcode >> 21) & 0xf) {
+       case 0:
+               if (rd == 0xf) {
+                       instruction->type = ARM_TST;
+                       mnemonic = "TST";
+                       one = true;
+                       suffix = "";
+                       rd = rn;
+               } else {
+                       instruction->type = ARM_AND;
+                       mnemonic = "AND";
+               }
+               break;
+       case 1:
+               instruction->type = ARM_BIC;
+               mnemonic = "BIC";
+               break;
+       case 2:
+               if (rn == 0xf) {
+                       instruction->type = ARM_MOV;
+                       mnemonic = "MOV";
+                       one = true;
+               } else {
+                       instruction->type = ARM_ORR;
+                       mnemonic = "ORR";
+               }
+               break;
+       case 3:
+               if (rn == 0xf) {
+                       instruction->type = ARM_MVN;
+                       mnemonic = "MVN";
+                       one = true;
+               } else {
+                       // instruction->type = ARM_ORN;
+                       mnemonic = "ORN";
+               }
+               break;
+       case 4:
+               if (rd == 0xf) {
+                       instruction->type = ARM_TEQ;
+                       mnemonic = "TEQ";
+                       one = true;
+                       suffix = "";
+                       rd = rn;
+               } else {
+                       instruction->type = ARM_EOR;
+                       mnemonic = "EOR";
+               }
+               break;
+       case 8:
+               if (rd == 0xf) {
+                       instruction->type = ARM_CMN;
+                       mnemonic = "CMN";
+                       one = true;
+                       suffix = "";
+                       rd = rn;
+               } else {
+                       instruction->type = ARM_ADD;
+                       mnemonic = "ADD";
+               }
+               break;
+       case 10:
+               instruction->type = ARM_ADC;
+               mnemonic = "ADC";
+               break;
+       case 11:
+               instruction->type = ARM_SBC;
+               mnemonic = "SBC";
+               break;
+       case 13:
+               if (rd == 0xf) {
+                       instruction->type = ARM_CMP;
+                       mnemonic = "CMP";
+                       one = true;
+                       suffix = "";
+                       rd = rn;
+               } else {
+                       instruction->type = ARM_SUB;
+                       mnemonic = "SUB";
+               }
+               break;
+       case 14:
+               instruction->type = ARM_RSB;
+               mnemonic = "RSB";
+               break;
+       default:
+               return ERROR_INVALID_ARGUMENTS;
+       }
+
+       if (one)
+               sprintf(cp, "%s\tr%d, #%d\t; %#8.8x",
+                               mnemonic, rd, immed, immed);
+       else
+               sprintf(cp, "%s%s\tr%d, r%d, #%d\t; %#8.8x",
+                               mnemonic, suffix, rd, rn, immed, immed);
+
+       return ERROR_OK;
+}
+
+static int t2ev_data_immed(uint32_t opcode, uint32_t address,
+               arm_instruction_t *instruction, char *cp)
+{
+       char *mnemonic = NULL;
+       int rn = (opcode >> 16) & 0xf;
+       int rd = (opcode >> 8) & 0xf;
+       unsigned immed;
+       bool add = false;
+       bool is_signed = false;
+
+       immed = (opcode & 0x0ff) | ((opcode & 0x7000) >> 12);
+       if (opcode & (1 << 27))
+               immed |= (1 << 11);
+
+       switch ((opcode >> 20) & 0x1f) {
+       case 0:
+               if (rn == 0xf) {
+                       add = true;
+                       goto do_adr;
+               }
+               mnemonic = "ADD.W";
+               break;
+       case 4:
+               mnemonic = "MOV.W";
+               break;
+       case 0x0a:
+               if (rn == 0xf)
+                       goto do_adr;
+               mnemonic = "SUB.W";
+               break;
+       case 0x0c:
+               /* move constant to top 16 bits of register */
+               immed |= (opcode >> 4) & 0xf000;
+               sprintf(cp, "MOVT\tr%d, #%d\t; %#4.4x", rn, immed, immed);
+               return ERROR_OK;
+       case 0x10:
+       case 0x12:
+               is_signed = true;
+       case 0x18:
+       case 0x1a:
+               /* signed/unsigned saturated add */
+               immed = (opcode >> 6) & 0x03;
+               immed |= (opcode >> 10) & 0x1c;
+               sprintf(cp, "%sSAT\tr%d, #%d, r%d, %s #%d\t",
+                               is_signed ? "S" : "U",
+                               rd, (opcode & 0x1f) + 1, rn,
+                               (opcode & (1 << 21)) ? "ASR" : "LSL",
+                               immed ? immed : 32);
+               return ERROR_OK;
+       case 0x14:
+               is_signed = true;
+               /* FALLTHROUGH */
+       case 0x1c:
+               /* signed/unsigned bitfield extract */
+               immed = (opcode >> 6) & 0x03;
+               immed |= (opcode >> 10) & 0x1c;
+               sprintf(cp, "%sBFX\tr%d, r%d, #%d, #%d\t",
+                               is_signed ? "S" : "U",
+                               rd, rn, immed,
+                               (opcode & 0x1f) + 1);
+               return ERROR_OK;
+       case 0x16:
+               immed = (opcode >> 6) & 0x03;
+               immed |= (opcode >> 10) & 0x1c;
+               if (rn == 0xf)          /* bitfield clear */
+                       sprintf(cp, "BFC\tr%d, #%d, #%d\t",
+                                       rd, immed,
+                                       (opcode & 0x1f) + 1 - immed);
+               else                    /* bitfield insert */
+                       sprintf(cp, "BFI\tr%d, r%d, #%d, #%d\t",
+                                       rd, rn, immed,
+                                       (opcode & 0x1f) + 1 - immed);
+               return ERROR_OK;
+       default:
+               return ERROR_INVALID_ARGUMENTS;
+       }
+
+       sprintf(cp, "%s\tr%d, r%d, #%d\t; %#3.3x", mnemonic,
+                       rd, rn, immed, immed);
+       return ERROR_OK;
+
+do_adr:
+       address = thumb_alignpc4(address);
+       if (add)
+               address += immed;
+       else
+               address -= immed;
+       /* REVISIT "ADD/SUB Rd, PC, #const ; 0x..." might be better;
+        * not hiding the pc-relative stuff will sometimes be useful.
+        */
+       sprintf(cp, "ADR.W\tr%d, %#8.8" PRIx32, rd, address);
+       return ERROR_OK;
+}
+
+static int t2ev_store_single(uint32_t opcode, uint32_t address,
+               arm_instruction_t *instruction, char *cp)
+{
+       unsigned op = (opcode >> 20) & 0xf;
+       char *size = "";
+       char *suffix = "";
+       char *p1 = "";
+       char *p2 = "]";
+       unsigned immed;
+       unsigned rn = (opcode >> 16) & 0x0f;
+       unsigned rt = (opcode >> 12) & 0x0f;
+
+       if (rn == 0xf)
+               return ERROR_INVALID_ARGUMENTS;
+
+       if (opcode & 0x0800)
+               op |= 1;
+       switch (op) {
+       /* byte */
+       case 0x8:
+       case 0x9:
+               size = "B";
+               goto imm12;
+       case 0x1:
+               size = "B";
+               goto imm8;
+       case 0x0:
+               size = "B";
+               break;
+       /* halfword */
+       case 0xa:
+       case 0xb:
+               size = "H";
+               goto imm12;
+       case 0x3:
+               size = "H";
+               goto imm8;
+       case 0x2:
+               size = "H";
+               break;
+       /* word */
+       case 0xc:
+       case 0xd:
+               goto imm12;
+       case 0x5:
+               goto imm8;
+       case 0x4:
+               break;
+       /* error */
+       default:
+               return ERROR_INVALID_ARGUMENTS;
+       }
+
+       sprintf(cp, "STR%s.W\tr%d, [r%d, r%d, LSL #%d]",
+                       size, rt, rn, opcode & 0x0f,
+                       (opcode >> 4) & 0x03);
+
+imm12:
+       immed = opcode & 0x0fff;
+       sprintf(cp, "STR%s.W\tr%d, [r%d, #%u]\t; %#3.3x",
+                       size, rt, rn, immed, immed);
+       return ERROR_OK;
+
+imm8:
+       immed = opcode & 0x00ff;
+
+       switch (opcode & 0x700) {
+       case 0x600:
+               suffix = "T";
+               break;
+       case 0x000:
+       case 0x200:
+               return ERROR_INVALID_ARGUMENTS;
+       }
+
+       /* two indexed modes will write back rn */
+       if (opcode & 0x100) {
+               if (opcode & 0x400)     /* pre-indexed */
+                       p2 = "]!";
+               else {                  /* post-indexed */
+                       p1 = "]";
+                       p2 = "";
+               }
+       }
+
+       sprintf(cp, "STR%s%s\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
+                       size, suffix, rt, rn, p1,
+                       (opcode & 0x200) ? "" : "-",
+                       immed, p2, immed);
+       return ERROR_OK;
+}
+
+static int t2ev_mul32(uint32_t opcode, uint32_t address,
+               arm_instruction_t *instruction, char *cp)
+{
+       int ra = (opcode >> 12) & 0xf;
+
+
+       switch (opcode & 0x007000f0) {
+       case 0:
+               if (ra == 0xf)
+                       sprintf(cp, "MUL\tr%d, r%d, r%d",
+                               (opcode >> 8) & 0xf, (opcode >> 16) & 0xf,
+                               (opcode >> 0) & 0xf);
+               else
+                       sprintf(cp, "MLA\tr%d, r%d, r%d, r%d",
+                               (opcode >> 8) & 0xf, (opcode >> 16) & 0xf,
+                               (opcode >> 0) & 0xf, ra);
+               break;
+       case 0x10:
+               sprintf(cp, "MLS\tr%d, r%d, r%d, r%d",
+                       (opcode >> 8) & 0xf, (opcode >> 16) & 0xf,
+                       (opcode >> 0) & 0xf, ra);
+               break;
+       default:
+               return ERROR_INVALID_ARGUMENTS;
+       }
+       return ERROR_OK;
+}
+
+static int t2ev_mul64_div(uint32_t opcode, uint32_t address,
+               arm_instruction_t *instruction, char *cp)
+{
+       int op = (opcode >> 4) & 0xf;
+       char *infix = "MUL";
+
+       op += (opcode >> 16) & 0x70;
+       switch (op) {
+       case 0x40:
+       case 0x60:
+               infix = "MLA";
+               /* FALLTHROUGH */
+       case 0:
+       case 0x20:
+               sprintf(cp, "%c%sL\tr%d, r%d, r%d, r%d",
+                               (op & 0x20) ? 'U' : 'S',
+                               infix,
+                               (opcode >> 12) & 0xf,
+                               (opcode >> 8) & 0xf,
+                               (opcode >> 16) & 0xf,
+                               (opcode >> 0) & 0xf);
+               break;
+       case 0x1f:
+       case 0x3f:
+               sprintf(cp, "%cDIV\tr%d, r%d, r%d",
+                               (op & 0x20) ? 'U' : 'S',
+                               (opcode >> 8) & 0xf,
+                               (opcode >> 16) & 0xf,
+                               (opcode >> 0) & 0xf);
+               break;
+       default:
+               return ERROR_INVALID_ARGUMENTS;
+       }
+
+       return ERROR_OK;
+}
+
+/*
+ * REVISIT for Thumb2 instructions, instruction->type and friends aren't
+ * always set.  That means eventual arm_simulate_step() support for Thumb2
+ * will need work in this area.
+ */
+int thumb2_opcode(target_t *target, uint32_t address, arm_instruction_t *instruction)
+{
+       int retval;
+       uint16_t op;
+       uint32_t opcode;
+       char *cp;
+
+       /* clear low bit ... it's set on function pointers */
+       address &= ~1;
+
+       /* clear fields, to avoid confusion */
+       memset(instruction, 0, sizeof(arm_instruction_t));
+
+       /* read first halfword, see if this is the only one */
+       retval = target_read_u16(target, address, &op);
+       if (retval != ERROR_OK)
+               return retval;
+
+       switch (op & 0xf800) {
+       case 0xf800:
+       case 0xf000:
+       case 0xe800:
+               /* 32-bit instructions */
+               instruction->instruction_size = 4;
+               opcode = op << 16;
+               retval = target_read_u16(target, address + 2, &op);
+               if (retval != ERROR_OK)
+                       return retval;
+               opcode |= op;
+               instruction->opcode = opcode;
+               break;
+       default:
+               /* 16-bit:  Thumb1 + IT + CBZ/CBNZ + ... */
+               return thumb_evaluate_opcode(op, address, instruction);
+       }
+
+       snprintf(instruction->text, 128,
+                       "0x%8.8" PRIx32 "  0x%8.8" PRIx32 "\t",
+                       address, opcode);
+       cp = strchr(instruction->text, 0);
+       retval = ERROR_FAIL;
+
+       /* ARMv7-M: A5.3.1 Data processing (modified immediate) */
+       if ((opcode & 0x1a008000) == 0x10000000)
+               retval = t2ev_data_mod_immed(opcode, address, instruction, cp);
+
+       /* ARMv7-M: A5.3.3 Data processing (plain binary immediate) */
+       else if ((opcode & 0x1a008000) == 0x12000000)
+               retval = t2ev_data_immed(opcode, address, instruction, cp);
+
+       /* ARMv7-M: A5.3.4 Branches and miscellaneous control */
+       else if ((opcode & 0x18008000) == 0x10008000)
+               retval = t2ev_b_misc(opcode, address, instruction, cp);
+
+       /* ARMv7-M: A5.3.10 Store single data item */
+       else if ((opcode & 0x1f100000) == 0x18000000)
+               retval = t2ev_store_single(opcode, address, instruction, cp);
+
+       /* ARMv7-M: A5.3.14 Multiply, and multiply accumulate */
+       else if ((opcode & 0x1f800000) == 0x1b000000)
+               retval = t2ev_mul32(opcode, address, instruction, cp);
+
+       /* ARMv7-M: A5.3.15 Long multiply, long multiply accumulate, divide */
+       else if ((opcode & 0x1f800000) == 0x1b800000)
+               retval = t2ev_mul64_div(opcode, address, instruction, cp);
+
+       /* FIXME decode more 32-bit instructions */
+
+       if (retval == ERROR_OK)
+               return retval;
+
+       if (retval == ERROR_INVALID_ARGUMENTS) {
+               instruction->type = ARM_UNDEFINED_INSTRUCTION;
+               strcpy(cp, "UNDEFINED OPCODE");
+               return ERROR_OK;
+       }
+
+       LOG_DEBUG("Can't decode 32-bit Thumb2 yet (opcode=%08x)", opcode);
+
+       strcpy(cp, "(32-bit Thumb2 ...)");
+       return ERROR_OK;
+}
+
+int arm_access_size(arm_instruction_t *instruction)
+{
+       if ((instruction->type == ARM_LDRB)
+               || (instruction->type == ARM_LDRBT)
+               || (instruction->type == ARM_LDRSB)
+               || (instruction->type == ARM_STRB)
+               || (instruction->type == ARM_STRBT))
+       {
+               return 1;
+       }
+       else if ((instruction->type == ARM_LDRH)
+               || (instruction->type == ARM_LDRSH)
+               || (instruction->type == ARM_STRH))
+       {
+               return 2;
+       }
+       else if ((instruction->type == ARM_LDR)
+               || (instruction->type == ARM_LDRT)
+               || (instruction->type == ARM_STR)
+               || (instruction->type == ARM_STRT))
+       {
+               return 4;
+       }
+       else if ((instruction->type == ARM_LDRD)
+               || (instruction->type == ARM_STRD))
+       {
+               return 8;
+       }
+       else
+       {
+               LOG_ERROR("BUG: instruction type %i isn't a load/store instruction", instruction->type);
+               return 0;
+       }
+}

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)