cmd: add missing usage vars
[fw/openocd] / src / target / arm_disassembler.c
index ee087b1215372f044b79db41b003518b2102980e..34d679c113b7a33355842294e914653501383725 100644 (file)
@@ -25,7 +25,7 @@
 
 #include "target.h"
 #include "arm_disassembler.h"
-#include "log.h"
+#include <helper/log.h>
 
 
 /*
@@ -50,6 +50,7 @@
  *       except as coprocessor 10/11 operations
  *     * Most ARM instructions through ARMv6 are decoded, but some
  *       of the post-ARMv4 opcodes may not be handled yet
+ *             CPS, SDIV, UDIV, LDREX*, STREX*, QASX, ...
  *     * NEON instructions are not understood (ARMv7-A)
  *
  *  - Thumb/Thumb2 decoding
@@ -106,8 +107,18 @@ static uint32_t ror(uint32_t value, int places)
        return (value >> places) | (value << (32 - places));
 }
 
+static int evaluate_unknown(uint32_t opcode,
+               uint32_t address, struct arm_instruction *instruction)
+{
+       instruction->type = ARM_UNDEFINED_INSTRUCTION;
+       snprintf(instruction->text, 128,
+                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+                       "\tUNDEFINED INSTRUCTION", address, opcode);
+       return ERROR_OK;
+}
+
 static int evaluate_pld(uint32_t opcode,
-               uint32_t address, arm_instruction_t *instruction)
+               uint32_t address, struct arm_instruction *instruction)
 {
        /* PLD */
        if ((opcode & 0x0d70f000) == 0x0550f000)
@@ -118,18 +129,55 @@ static int evaluate_pld(uint32_t opcode,
 
                return ERROR_OK;
        }
-       else
-       {
-               instruction->type = ARM_UNDEFINED_INSTRUCTION;
-               return ERROR_OK;
+       return evaluate_unknown(opcode, address, instruction);
+}
+
+static int evaluate_srs(uint32_t opcode,
+               uint32_t address, struct arm_instruction *instruction)
+{
+       const char *wback = (opcode & (1 << 21)) ? "!" : "";
+       const char *mode = "";
+
+       switch ((opcode >> 23) & 0x3) {
+       case 0:
+               mode = "DA";
+               break;
+       case 1:
+               /* "IA" is default */
+               break;
+       case 2:
+               mode = "DB";
+               break;
+       case 3:
+               mode = "IB";
+               break;
        }
 
-       LOG_ERROR("should never reach this point");
-       return -1;
+       switch (opcode & 0x0e500000) {
+       case 0x08400000:
+               snprintf(instruction->text, 128, "0x%8.8" PRIx32
+                               "\t0x%8.8" PRIx32
+                               "\tSRS%s\tSP%s, #%d",
+                               address, opcode,
+                               mode, wback,
+                               (unsigned)(opcode & 0x1f));
+               break;
+       case 0x08100000:
+               snprintf(instruction->text, 128, "0x%8.8" PRIx32
+                               "\t0x%8.8" PRIx32
+                               "\tRFE%s\tr%d%s",
+                               address, opcode,
+                               mode,
+                               (unsigned)((opcode >> 16) & 0xf), wback);
+               break;
+       default:
+               return evaluate_unknown(opcode, address, instruction);
+       }
+       return ERROR_OK;
 }
 
 static int evaluate_swi(uint32_t opcode,
-               uint32_t address, arm_instruction_t *instruction)
+               uint32_t address, struct arm_instruction *instruction)
 {
        instruction->type = ARM_SWI;
 
@@ -141,7 +189,7 @@ static int evaluate_swi(uint32_t opcode,
 }
 
 static int evaluate_blx_imm(uint32_t opcode,
-               uint32_t address, arm_instruction_t *instruction)
+               uint32_t address, struct arm_instruction *instruction)
 {
        int offset;
        uint32_t immediate;
@@ -174,7 +222,7 @@ static int evaluate_blx_imm(uint32_t opcode,
 }
 
 static int evaluate_b_bl(uint32_t opcode,
-               uint32_t address, arm_instruction_t *instruction)
+               uint32_t address, struct arm_instruction *instruction)
 {
        uint8_t L;
        uint32_t immediate;
@@ -212,7 +260,7 @@ static int evaluate_b_bl(uint32_t opcode,
 /* Coprocessor load/store and double register transfers */
 /* both normal and extended instruction space (condition field b1111) */
 static int evaluate_ldc_stc_mcrr_mrrc(uint32_t opcode,
-               uint32_t address, arm_instruction_t *instruction)
+               uint32_t address, struct arm_instruction *instruction)
 {
        uint8_t cp_num = (opcode & 0xf00) >> 8;
 
@@ -232,28 +280,33 @@ static int evaluate_ldc_stc_mcrr_mrrc(uint32_t opcode,
                {
                        instruction->type = ARM_MCRR;
                        mnemonic = "MCRR";
-               }
-
-               /* MRRC */
-               if ((opcode & 0x0ff00000) == 0x0c500000)
-               {
+               } else if ((opcode & 0x0ff00000) == 0x0c500000) {
+                       /* MRRC */
                        instruction->type = ARM_MRRC;
                        mnemonic = "MRRC";
+               } else {
+                       LOG_ERROR("Unknown instruction");
+                       return ERROR_FAIL;
                }
 
-               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);
+               snprintf(instruction->text, 128,
+                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+                               "\t%s%s%s p%i, %x, r%i, r%i, c%i",
+                                address, opcode, mnemonic,
+                               ((opcode & 0xf0000000) == 0xf0000000)
+                                               ? "2" : COND(opcode),
+                                COND(opcode), cp_num, cp_opcode, Rd, Rn, CRm);
        }
        else /* LDC or STC */
        {
                uint8_t CRd, Rn, offset;
-               uint8_t U, N;
+               uint8_t U;
                char *mnemonic;
                char addressing_mode[32];
 
                CRd = (opcode & 0xf000) >> 12;
                Rn = (opcode & 0xf0000) >> 16;
-               offset = (opcode & 0xff);
+               offset = (opcode & 0xff) << 2;
 
                /* load/store */
                if (opcode & 0x00100000)
@@ -268,22 +321,29 @@ static int evaluate_ldc_stc_mcrr_mrrc(uint32_t opcode,
                }
 
                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);
-               else if ((opcode & 0x01200000) == 0x01200000) /* immediate pre-indexed */
-                       snprintf(addressing_mode, 32, "[r%i, #%s0x%2.2x*4]!", Rn, (U) ? "" : "-", offset);
-               else if ((opcode & 0x01200000) == 0x00200000) /* immediate post-indexed */
-                       snprintf(addressing_mode, 32, "[r%i], #%s0x%2.2x*4", Rn, (U) ? "" : "-", offset);
+               if ((opcode & 0x01200000) == 0x01000000) /* offset */
+                       snprintf(addressing_mode, 32, "[r%i, #%s%d]",
+                                       Rn, U ? "" : "-", offset);
+               else if ((opcode & 0x01200000) == 0x01200000) /* pre-indexed */
+                       snprintf(addressing_mode, 32, "[r%i, #%s%d]!",
+                                       Rn, U ? "" : "-", offset);
+               else if ((opcode & 0x01200000) == 0x00200000) /* post-indexed */
+                       snprintf(addressing_mode, 32, "[r%i], #%s%d",
+                                       Rn, U ? "" : "-", offset);
                else if ((opcode & 0x01200000) == 0x00000000) /* unindexed */
-                       snprintf(addressing_mode, 32, "[r%i], #0x%2.2x", Rn, offset);
+                       snprintf(addressing_mode, 32, "[r%i], {%d}",
+                                       Rn, offset >> 2);
 
-               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);
+               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)
+                                               ? "2" : COND(opcode),
+                               (opcode & (1 << 22)) ? "L" : "",
+                               cp_num, CRd, addressing_mode);
        }
 
        return ERROR_OK;
@@ -293,7 +353,7 @@ static int evaluate_ldc_stc_mcrr_mrrc(uint32_t opcode,
 /* Coprocessor register transfer instructions */
 /* both normal and extended instruction space (condition field b1111) */
 static int evaluate_cdp_mcr_mrc(uint32_t opcode,
-               uint32_t address, arm_instruction_t *instruction)
+               uint32_t address, struct arm_instruction *instruction)
 {
        const char *cond;
        char* mnemonic;
@@ -343,7 +403,7 @@ static int evaluate_cdp_mcr_mrc(uint32_t opcode,
 
 /* Load/store instructions */
 static int evaluate_load_store(uint32_t opcode,
-               uint32_t address, arm_instruction_t *instruction)
+               uint32_t address, struct arm_instruction *instruction)
 {
        uint8_t I, P, U, B, W, L;
        uint8_t Rn, Rd;
@@ -634,7 +694,7 @@ undef:
 
 /* ARMv6 and later support "media" instructions (includes SIMD) */
 static int evaluate_media(uint32_t opcode, uint32_t address,
-               arm_instruction_t *instruction)
+               struct arm_instruction *instruction)
 {
        char *cp = instruction->text;
        char *mnemonic = NULL;
@@ -829,7 +889,7 @@ undef:
 
 /* Miscellaneous load/store instructions */
 static int evaluate_misc_load_store(uint32_t opcode,
-               uint32_t address, arm_instruction_t *instruction)
+               uint32_t address, struct arm_instruction *instruction)
 {
        uint8_t P, U, I, W, L, S, H;
        uint8_t Rn, Rd;
@@ -957,7 +1017,7 @@ static int evaluate_misc_load_store(uint32_t opcode,
 
 /* Load/store multiples instructions */
 static int evaluate_ldm_stm(uint32_t opcode,
-               uint32_t address, arm_instruction_t *instruction)
+               uint32_t address, struct arm_instruction *instruction)
 {
        uint8_t P, U, S, W, L, Rn;
        uint32_t register_list;
@@ -1037,8 +1097,11 @@ static int evaluate_ldm_stm(uint32_t opcode,
                }
        }
 
-       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,
+       snprintf(instruction->text, 128,
+                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
+                       "\t%s%s%s r%i%s, {%s}%s",
+                        address, opcode,
+                        mnemonic, addressing_mode, COND(opcode),
                         Rn, (W) ? "!" : "", reg_list, (S) ? "^" : "");
 
        return ERROR_OK;
@@ -1046,7 +1109,7 @@ static int evaluate_ldm_stm(uint32_t opcode,
 
 /* Multiplies, extra load/stores */
 static int evaluate_mul_and_extra_ld_st(uint32_t opcode,
-               uint32_t address, arm_instruction_t *instruction)
+               uint32_t address, struct arm_instruction *instruction)
 {
        /* Multiply (accumulate) (long) and Swap/swap byte */
        if ((opcode & 0x000000f0) == 0x00000090)
@@ -1138,7 +1201,7 @@ static int evaluate_mul_and_extra_ld_st(uint32_t opcode,
 }
 
 static int evaluate_mrs_msr(uint32_t opcode,
-               uint32_t address, arm_instruction_t *instruction)
+               uint32_t address, struct arm_instruction *instruction)
 {
        int R = (opcode & 0x00400000) >> 22;
        char *PSR = (R) ? "SPSR" : "CPSR";
@@ -1193,7 +1256,7 @@ static int evaluate_mrs_msr(uint32_t opcode,
 
 /* Miscellaneous instructions */
 static int evaluate_misc_instr(uint32_t opcode,
-               uint32_t address, arm_instruction_t *instruction)
+               uint32_t address, struct arm_instruction *instruction)
 {
        /* MRS/MSR */
        if ((opcode & 0x000000f0) == 0x00000000)
@@ -1384,7 +1447,7 @@ static int evaluate_misc_instr(uint32_t opcode,
 }
 
 static int evaluate_data_proc(uint32_t opcode,
-               uint32_t address, arm_instruction_t *instruction)
+               uint32_t address, struct arm_instruction *instruction)
 {
        uint8_t I, op, S, Rn, Rd;
        char *mnemonic = NULL;
@@ -1591,10 +1654,11 @@ static int evaluate_data_proc(uint32_t opcode,
        return ERROR_OK;
 }
 
-int arm_evaluate_opcode(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
+int arm_evaluate_opcode(uint32_t opcode, uint32_t address,
+               struct arm_instruction *instruction)
 {
        /* clear fields, to avoid confusion */
-       memset(instruction, 0, sizeof(arm_instruction_t));
+       memset(instruction, 0, sizeof(struct arm_instruction));
        instruction->opcode = opcode;
        instruction->instruction_size = 4;
 
@@ -1605,13 +1669,9 @@ int arm_evaluate_opcode(uint32_t opcode, uint32_t address, arm_instruction_t *in
                if ((opcode & 0x08000000) == 0x00000000)
                        return evaluate_pld(opcode, address, instruction);
 
-               /* Undefined instruction */
+               /* Undefined instruction (or ARMv6+ SRS/RFE) */
                if ((opcode & 0x0e000000) == 0x08000000)
-               {
-                       instruction->type = ARM_UNDEFINED_INSTRUCTION;
-                       snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
-                       return ERROR_OK;
-               }
+                       return evaluate_srs(opcode, address, instruction);
 
                /* Branch and branch with link and change to Thumb */
                if ((opcode & 0x0e000000) == 0x0a000000)
@@ -1717,7 +1777,7 @@ int arm_evaluate_opcode(uint32_t opcode, uint32_t address, arm_instruction_t *in
        }
 
        /* catch opcodes with [27:25] = b110 */
-       if ((opcode & 0x0e000000) == 0x0a000000)
+       if ((opcode & 0x0e000000) == 0x0c000000)
        {
                /* Coprocessor load/store and double register transfers */
                return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
@@ -1739,12 +1799,13 @@ int arm_evaluate_opcode(uint32_t opcode, uint32_t address, arm_instruction_t *in
                        return evaluate_cdp_mcr_mrc(opcode, address, instruction);
        }
 
-       LOG_ERROR("should never reach this point");
+       LOG_ERROR("ARM: should never reach this point (opcode=%08x)",
+                       (unsigned) opcode);
        return -1;
 }
 
 static int evaluate_b_bl_blx_thumb(uint16_t opcode,
-               uint32_t address, arm_instruction_t *instruction)
+               uint32_t address, struct arm_instruction *instruction)
 {
        uint32_t offset = opcode & 0x7ff;
        uint32_t opc = (opcode >> 11) & 0x3;
@@ -1784,8 +1845,12 @@ static int evaluate_b_bl_blx_thumb(uint16_t opcode,
        }
 
        /* TODO: deal correctly with dual opcode (prefixed) BL/BLX;
-        * these are effectively 32-bit instructions even in Thumb1.
-        * Might be simplest to always use the Thumb2 decoder.
+        * these are effectively 32-bit instructions even in Thumb1.  For
+        * disassembly, it's simplest to always use the Thumb2 decoder.
+        *
+        * But some cores will evidently handle them as two instructions,
+        * where exceptions may occur between the two.  The ETMv3.2+ ID
+        * register has a bit which exposes this behavior.
         */
 
        snprintf(instruction->text, 128,
@@ -1799,7 +1864,7 @@ static int evaluate_b_bl_blx_thumb(uint16_t opcode,
 }
 
 static int evaluate_add_sub_thumb(uint16_t opcode,
-               uint32_t address, arm_instruction_t *instruction)
+               uint32_t address, struct arm_instruction *instruction)
 {
        uint8_t Rd = (opcode >> 0) & 0x7;
        uint8_t Rn = (opcode >> 3) & 0x7;
@@ -1845,7 +1910,7 @@ static int evaluate_add_sub_thumb(uint16_t opcode,
 }
 
 static int evaluate_shift_imm_thumb(uint16_t opcode,
-               uint32_t address, arm_instruction_t *instruction)
+               uint32_t address, struct arm_instruction *instruction)
 {
        uint8_t Rd = (opcode >> 0) & 0x7;
        uint8_t Rm = (opcode >> 3) & 0x7;
@@ -1891,7 +1956,7 @@ static int evaluate_shift_imm_thumb(uint16_t opcode,
 }
 
 static int evaluate_data_proc_imm_thumb(uint16_t opcode,
-               uint32_t address, arm_instruction_t *instruction)
+               uint32_t address, struct arm_instruction *instruction)
 {
        uint8_t imm = opcode & 0xff;
        uint8_t Rd = (opcode >> 8) & 0x7;
@@ -1934,7 +1999,7 @@ static int evaluate_data_proc_imm_thumb(uint16_t opcode,
 }
 
 static int evaluate_data_proc_thumb(uint16_t opcode,
-               uint32_t address, arm_instruction_t *instruction)
+               uint32_t address, struct arm_instruction *instruction)
 {
        uint8_t high_reg, op, Rm, Rd,H1,H2;
        char *mnemonic = NULL;
@@ -2120,7 +2185,7 @@ static inline uint32_t thumb_alignpc4(uint32_t addr)
 }
 
 static int evaluate_load_literal_thumb(uint16_t opcode,
-               uint32_t address, arm_instruction_t *instruction)
+               uint32_t address, struct arm_instruction *instruction)
 {
        uint32_t immediate;
        uint8_t Rd = (opcode >> 8) & 0x7;
@@ -2145,7 +2210,7 @@ static int evaluate_load_literal_thumb(uint16_t opcode,
 }
 
 static int evaluate_load_store_reg_thumb(uint16_t opcode,
-               uint32_t address, arm_instruction_t *instruction)
+               uint32_t address, struct arm_instruction *instruction)
 {
        uint8_t Rd = (opcode >> 0) & 0x7;
        uint8_t Rn = (opcode >> 3) & 0x7;
@@ -2203,7 +2268,7 @@ static int evaluate_load_store_reg_thumb(uint16_t opcode,
 }
 
 static int evaluate_load_store_imm_thumb(uint16_t opcode,
-               uint32_t address, arm_instruction_t *instruction)
+               uint32_t address, struct arm_instruction *instruction)
 {
        uint32_t offset = (opcode >> 6) & 0x1f;
        uint8_t Rd = (opcode >> 0) & 0x7;
@@ -2250,7 +2315,7 @@ static int evaluate_load_store_imm_thumb(uint16_t opcode,
 }
 
 static int evaluate_load_store_stack_thumb(uint16_t opcode,
-               uint32_t address, arm_instruction_t *instruction)
+               uint32_t address, struct arm_instruction *instruction)
 {
        uint32_t offset = opcode  & 0xff;
        uint8_t Rd = (opcode >> 8) & 0x7;
@@ -2282,13 +2347,13 @@ static int evaluate_load_store_stack_thumb(uint16_t opcode,
 }
 
 static int evaluate_add_sp_pc_thumb(uint16_t opcode,
-               uint32_t address, arm_instruction_t *instruction)
+               uint32_t address, struct arm_instruction *instruction)
 {
        uint32_t imm = opcode  & 0xff;
        uint8_t Rd = (opcode >> 8) & 0x7;
        uint8_t Rn;
        uint32_t SP = opcode & (1 << 11);
-       char *reg_name;
+       const char *reg_name;
 
        instruction->type = ARM_ADD;
 
@@ -2316,7 +2381,7 @@ static int evaluate_add_sp_pc_thumb(uint16_t opcode,
 }
 
 static int evaluate_adjust_stack_thumb(uint16_t opcode,
-               uint32_t address, arm_instruction_t *instruction)
+               uint32_t address, struct arm_instruction *instruction)
 {
        uint32_t imm = opcode  & 0x7f;
        uint8_t opc = opcode & (1 << 7);
@@ -2347,7 +2412,7 @@ static int evaluate_adjust_stack_thumb(uint16_t opcode,
 }
 
 static int evaluate_breakpoint_thumb(uint16_t opcode,
-               uint32_t address, arm_instruction_t *instruction)
+               uint32_t address, struct arm_instruction *instruction)
 {
        uint32_t imm = opcode  & 0xff;
 
@@ -2361,7 +2426,7 @@ static int evaluate_breakpoint_thumb(uint16_t opcode,
 }
 
 static int evaluate_load_store_multiple_thumb(uint16_t opcode,
-               uint32_t address, arm_instruction_t *instruction)
+               uint32_t address, struct arm_instruction *instruction)
 {
        uint32_t reg_list = opcode  & 0xff;
        uint32_t L = opcode & (1 << 11);
@@ -2439,7 +2504,7 @@ static int evaluate_load_store_multiple_thumb(uint16_t opcode,
 }
 
 static int evaluate_cond_branch_thumb(uint16_t opcode,
-               uint32_t address, arm_instruction_t *instruction)
+               uint32_t address, struct arm_instruction *instruction)
 {
        uint32_t offset = opcode  & 0xff;
        uint8_t cond = (opcode >> 8) & 0xf;
@@ -2481,7 +2546,7 @@ static int evaluate_cond_branch_thumb(uint16_t opcode,
 }
 
 static int evaluate_cb_thumb(uint16_t opcode, uint32_t address,
-               arm_instruction_t *instruction)
+               struct arm_instruction *instruction)
 {
        unsigned offset;
 
@@ -2499,7 +2564,7 @@ static int evaluate_cb_thumb(uint16_t opcode, uint32_t address,
 }
 
 static int evaluate_extend_thumb(uint16_t opcode, uint32_t address,
-               arm_instruction_t *instruction)
+               struct arm_instruction *instruction)
 {
        /* added in ARMv6 */
        snprintf(instruction->text, 128,
@@ -2513,7 +2578,7 @@ static int evaluate_extend_thumb(uint16_t opcode, uint32_t address,
 }
 
 static int evaluate_cps_thumb(uint16_t opcode, uint32_t address,
-               arm_instruction_t *instruction)
+               struct arm_instruction *instruction)
 {
        /* added in ARMv6 */
        if ((opcode & 0x0ff0) == 0x0650)
@@ -2534,7 +2599,7 @@ static int evaluate_cps_thumb(uint16_t opcode, uint32_t address,
 }
 
 static int evaluate_byterev_thumb(uint16_t opcode, uint32_t address,
-               arm_instruction_t *instruction)
+               struct arm_instruction *instruction)
 {
        char *suffix;
 
@@ -2559,7 +2624,7 @@ static int evaluate_byterev_thumb(uint16_t opcode, uint32_t address,
 }
 
 static int evaluate_hint_thumb(uint16_t opcode, uint32_t address,
-               arm_instruction_t *instruction)
+               struct arm_instruction *instruction)
 {
        char *hint;
 
@@ -2592,7 +2657,7 @@ static int evaluate_hint_thumb(uint16_t opcode, uint32_t address,
 }
 
 static int evaluate_ifthen_thumb(uint16_t opcode, uint32_t address,
-               arm_instruction_t *instruction)
+               struct arm_instruction *instruction)
 {
        unsigned cond = (opcode >> 4) & 0x0f;
        char *x = "", *y = "", *z = "";
@@ -2616,10 +2681,10 @@ static int evaluate_ifthen_thumb(uint16_t opcode, uint32_t address,
        return ERROR_OK;
 }
 
-int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
+int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
 {
        /* clear fields, to avoid confusion */
-       memset(instruction, 0, sizeof(arm_instruction_t));
+       memset(instruction, 0, sizeof(struct arm_instruction));
        instruction->opcode = opcode;
        instruction->instruction_size = 2;
 
@@ -2749,12 +2814,12 @@ int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, arm_instruction_t *
                }
        }
 
-       LOG_ERROR("should never reach this point (opcode=%04x)",opcode);
+       LOG_ERROR("Thumb: 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)
+               struct arm_instruction *instruction, char *cp)
 {
        unsigned offset;
        unsigned b21 = 1 << 21;
@@ -2795,7 +2860,7 @@ static int t2ev_b_bl(uint32_t opcode, uint32_t address,
 }
 
 static int t2ev_cond_b(uint32_t opcode, uint32_t address,
-               arm_instruction_t *instruction, char *cp)
+               struct arm_instruction *instruction, char *cp)
 {
        unsigned offset;
        unsigned b17 = 1 << 17;
@@ -2884,7 +2949,7 @@ static const char *special_name(int number)
 }
 
 static int t2ev_hint(uint32_t opcode, uint32_t address,
-               arm_instruction_t *instruction, char *cp)
+               struct arm_instruction *instruction, char *cp)
 {
        const char *mnemonic;
 
@@ -2924,7 +2989,7 @@ static int t2ev_hint(uint32_t opcode, uint32_t address,
 }
 
 static int t2ev_misc(uint32_t opcode, uint32_t address,
-               arm_instruction_t *instruction, char *cp)
+               struct arm_instruction *instruction, char *cp)
 {
        const char *mnemonic;
 
@@ -2948,14 +3013,14 @@ static int t2ev_misc(uint32_t opcode, uint32_t address,
                mnemonic = "ISB";
                break;
        default:
-               return ERROR_INVALID_ARGUMENTS;
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
        strcpy(cp, mnemonic);
        return ERROR_OK;
 }
 
 static int t2ev_b_misc(uint32_t opcode, uint32_t address,
-               arm_instruction_t *instruction, char *cp)
+               struct arm_instruction *instruction, char *cp)
 {
        /* permanently undefined */
        if ((opcode & 0x07f07000) == 0x07f02000) {
@@ -2999,11 +3064,11 @@ static int t2ev_b_misc(uint32_t opcode, uint32_t address,
        }
 
 undef:
-       return ERROR_INVALID_ARGUMENTS;
+       return ERROR_COMMAND_SYNTAX_ERROR;
 }
 
 static int t2ev_data_mod_immed(uint32_t opcode, uint32_t address,
-               arm_instruction_t *instruction, char *cp)
+               struct arm_instruction *instruction, char *cp)
 {
        char *mnemonic = NULL;
        int rn = (opcode >> 16) & 0xf;
@@ -3134,7 +3199,7 @@ static int t2ev_data_mod_immed(uint32_t opcode, uint32_t address,
                suffix2 = ".W";
                break;
        default:
-               return ERROR_INVALID_ARGUMENTS;
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
        if (one)
@@ -3149,7 +3214,7 @@ static int t2ev_data_mod_immed(uint32_t opcode, uint32_t address,
 }
 
 static int t2ev_data_immed(uint32_t opcode, uint32_t address,
-               arm_instruction_t *instruction, char *cp)
+               struct arm_instruction *instruction, char *cp)
 {
        char *mnemonic = NULL;
        int rn = (opcode >> 16) & 0xf;
@@ -3182,7 +3247,7 @@ static int t2ev_data_immed(uint32_t opcode, uint32_t address,
        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);
+               sprintf(cp, "MOVT\tr%d, #%d\t; %#4.4x", rd, immed, immed);
                return ERROR_OK;
        case 0x10:
        case 0x12:
@@ -3223,7 +3288,7 @@ static int t2ev_data_immed(uint32_t opcode, uint32_t address,
                                        (int) (opcode & 0x1f) + 1 - immed);
                return ERROR_OK;
        default:
-               return ERROR_INVALID_ARGUMENTS;
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
        sprintf(cp, "%s\tr%d, r%d, #%d\t; %#3.3x", mnemonic,
@@ -3244,7 +3309,7 @@ do_adr:
 }
 
 static int t2ev_store_single(uint32_t opcode, uint32_t address,
-               arm_instruction_t *instruction, char *cp)
+               struct arm_instruction *instruction, char *cp)
 {
        unsigned op = (opcode >> 20) & 0xf;
        char *size = "";
@@ -3256,7 +3321,7 @@ static int t2ev_store_single(uint32_t opcode, uint32_t address,
        unsigned rt = (opcode >> 12) & 0x0f;
 
        if (rn == 0xf)
-               return ERROR_INVALID_ARGUMENTS;
+               return ERROR_COMMAND_SYNTAX_ERROR;
 
        if (opcode & 0x0800)
                op |= 1;
@@ -3293,7 +3358,7 @@ static int t2ev_store_single(uint32_t opcode, uint32_t address,
                break;
        /* error */
        default:
-               return ERROR_INVALID_ARGUMENTS;
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
        sprintf(cp, "STR%s.W\tr%d, [r%d, r%d, LSL #%d]",
@@ -3316,7 +3381,7 @@ imm8:
                break;
        case 0x000:
        case 0x200:
-               return ERROR_INVALID_ARGUMENTS;
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
        /* two indexed modes will write back rn */
@@ -3337,7 +3402,7 @@ imm8:
 }
 
 static int t2ev_mul32(uint32_t opcode, uint32_t address,
-               arm_instruction_t *instruction, char *cp)
+               struct arm_instruction *instruction, char *cp)
 {
        int ra = (opcode >> 12) & 0xf;
 
@@ -3361,13 +3426,13 @@ static int t2ev_mul32(uint32_t opcode, uint32_t address,
                        (int) (opcode >> 0) & 0xf, ra);
                break;
        default:
-               return ERROR_INVALID_ARGUMENTS;
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
        return ERROR_OK;
 }
 
 static int t2ev_mul64_div(uint32_t opcode, uint32_t address,
-               arm_instruction_t *instruction, char *cp)
+               struct arm_instruction *instruction, char *cp)
 {
        int op = (opcode >> 4) & 0xf;
        char *infix = "MUL";
@@ -3397,24 +3462,41 @@ static int t2ev_mul64_div(uint32_t opcode, uint32_t address,
                                (int) (opcode >> 0) & 0xf);
                break;
        default:
-               return ERROR_INVALID_ARGUMENTS;
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
        return ERROR_OK;
 }
 
 static int t2ev_ldm_stm(uint32_t opcode, uint32_t address,
-               arm_instruction_t *instruction, char *cp)
+               struct arm_instruction *instruction, char *cp)
 {
        int rn = (opcode >> 16) & 0xf;
        int op = (opcode >> 22) & 0x6;
        int t = (opcode >> 21) & 1;
        unsigned registers = opcode & 0xffff;
+       char *mode = "";
 
        if (opcode & (1 << 20))
                op |= 1;
 
        switch (op) {
+       case 0:
+               mode = "DB";
+               /* FALL THROUGH */
+       case 6:
+               sprintf(cp, "SRS%s\tsp%s, #%d", mode,
+                               t ? "!" : "",
+                               (unsigned) (opcode & 0x1f));
+               return ERROR_OK;
+       case 1:
+               mode = "DB";
+               /* FALL THROUGH */
+       case 7:
+               sprintf(cp, "RFE%s\tr%d%s", mode,
+                               (unsigned) ((opcode >> 16) & 0xf),
+                               t ? "!" : "");
+               return ERROR_OK;
        case 2:
                sprintf(cp, "STM.W\tr%d%s, ", rn, t ? "!" : "");
                break;
@@ -3434,7 +3516,7 @@ static int t2ev_ldm_stm(uint32_t opcode, uint32_t address,
                sprintf(cp, "LDMDB.W\tr%d%s, ", rn, t ? "!" : "");
                break;
        default:
-               return ERROR_INVALID_ARGUMENTS;
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
        cp = strchr(cp, 0);
@@ -3454,7 +3536,7 @@ static int t2ev_ldm_stm(uint32_t opcode, uint32_t address,
 
 /* load/store dual or exclusive, table branch */
 static int t2ev_ldrex_strex(uint32_t opcode, uint32_t address,
-               arm_instruction_t *instruction, char *cp)
+               struct arm_instruction *instruction, char *cp)
 {
        unsigned op1op2 = (opcode >> 20) & 0x3;
        unsigned op3 = (opcode >> 4) & 0xf;
@@ -3502,7 +3584,7 @@ static int t2ev_ldrex_strex(uint32_t opcode, uint32_t address,
                        mnemonic = "STREXH";
                        break;
                default:
-                       return ERROR_INVALID_ARGUMENTS;
+                       return ERROR_COMMAND_SYNTAX_ERROR;
                }
                rd = opcode & 0xf;
                imm = 0;
@@ -3522,12 +3604,12 @@ static int t2ev_ldrex_strex(uint32_t opcode, uint32_t address,
                        mnemonic = "LDREXH";
                        break;
                default:
-                       return ERROR_INVALID_ARGUMENTS;
+                       return ERROR_COMMAND_SYNTAX_ERROR;
                }
                imm = 0;
                goto ldrex;
        }
-       return ERROR_INVALID_ARGUMENTS;
+       return ERROR_COMMAND_SYNTAX_ERROR;
 
 strex:
        imm <<= 2;
@@ -3580,7 +3662,7 @@ literal:
 }
 
 static int t2ev_data_shift(uint32_t opcode, uint32_t address,
-               arm_instruction_t *instruction, char *cp)
+               struct arm_instruction *instruction, char *cp)
 {
        int op = (opcode >> 21) & 0xf;
        int rd = (opcode >> 8) & 0xf;
@@ -3598,7 +3680,7 @@ static int t2ev_data_shift(uint32_t opcode, uint32_t address,
        case 0:
                if (rd == 0xf) {
                        if (!(opcode & (1 << 20)))
-                               return ERROR_INVALID_ARGUMENTS;
+                               return ERROR_COMMAND_SYNTAX_ERROR;
                        instruction->type = ARM_TST;
                        mnemonic = "TST";
                        suffix = "";
@@ -3660,7 +3742,7 @@ static int t2ev_data_shift(uint32_t opcode, uint32_t address,
        case 4:
                if (rd == 0xf) {
                        if (!(opcode & (1 << 20)))
-                               return ERROR_INVALID_ARGUMENTS;
+                               return ERROR_COMMAND_SYNTAX_ERROR;
                        instruction->type = ARM_TEQ;
                        mnemonic = "TEQ";
                        suffix = "";
@@ -3672,7 +3754,7 @@ static int t2ev_data_shift(uint32_t opcode, uint32_t address,
        case 8:
                if (rd == 0xf) {
                        if (!(opcode & (1 << 20)))
-                               return ERROR_INVALID_ARGUMENTS;
+                               return ERROR_COMMAND_SYNTAX_ERROR;
                        instruction->type = ARM_CMN;
                        mnemonic = "CMN";
                        suffix = "";
@@ -3692,7 +3774,7 @@ static int t2ev_data_shift(uint32_t opcode, uint32_t address,
        case 0xd:
                if (rd == 0xf) {
                        if (!(opcode & (1 << 21)))
-                               return ERROR_INVALID_ARGUMENTS;
+                               return ERROR_COMMAND_SYNTAX_ERROR;
                        instruction->type = ARM_CMP;
                        mnemonic = "CMP";
                        suffix = "";
@@ -3706,7 +3788,7 @@ static int t2ev_data_shift(uint32_t opcode, uint32_t address,
                mnemonic = "RSB";
                break;
        default:
-               return ERROR_INVALID_ARGUMENTS;
+               return ERROR_COMMAND_SYNTAX_ERROR;
        }
 
        sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
@@ -3755,7 +3837,7 @@ immediate:
 }
 
 static int t2ev_data_reg(uint32_t opcode, uint32_t address,
-               arm_instruction_t *instruction, char *cp)
+               struct arm_instruction *instruction, char *cp)
 {
        char *mnemonic;
        char * suffix = "";
@@ -3775,7 +3857,7 @@ static int t2ev_data_reg(uint32_t opcode, uint32_t address,
                        mnemonic = "ROR";
                        break;
                default:
-                       return ERROR_INVALID_ARGUMENTS;
+                       return ERROR_COMMAND_SYNTAX_ERROR;
                }
 
                instruction->type = ARM_MOV;
@@ -3816,11 +3898,11 @@ static int t2ev_data_reg(uint32_t opcode, uint32_t address,
                case 0xa:
                case 0xb:
                        if (opcode & (1 << 6))
-                               return ERROR_INVALID_ARGUMENTS;
+                               return ERROR_COMMAND_SYNTAX_ERROR;
                        if (((opcode >> 12) & 0xf) != 0xf)
-                               return ERROR_INVALID_ARGUMENTS;
+                               return ERROR_COMMAND_SYNTAX_ERROR;
                        if (!(opcode & (1 << 20)))
-                               return ERROR_INVALID_ARGUMENTS;
+                               return ERROR_COMMAND_SYNTAX_ERROR;
 
                        switch (((opcode >> 19) & 0x04)
                                | ((opcode >> 4) & 0x3)) {
@@ -3840,7 +3922,7 @@ static int t2ev_data_reg(uint32_t opcode, uint32_t address,
                                mnemonic = "CLZ";
                                break;
                        default:
-                               return ERROR_INVALID_ARGUMENTS;
+                               return ERROR_COMMAND_SYNTAX_ERROR;
                        }
                        sprintf(cp, "%s\tr%d, r%d",
                                        mnemonic,
@@ -3848,7 +3930,7 @@ static int t2ev_data_reg(uint32_t opcode, uint32_t address,
                                        (int) (opcode >> 0) & 0xf);
                        break;
                default:
-                       return ERROR_INVALID_ARGUMENTS;
+                       return ERROR_COMMAND_SYNTAX_ERROR;
                }
        }
 
@@ -3856,7 +3938,7 @@ static int t2ev_data_reg(uint32_t opcode, uint32_t address,
 }
 
 static int t2ev_load_word(uint32_t opcode, uint32_t address,
-               arm_instruction_t *instruction, char *cp)
+               struct arm_instruction *instruction, char *cp)
 {
        int rn = (opcode >> 16) & 0xf;
        int immed;
@@ -3904,7 +3986,7 @@ static int t2ev_load_word(uint32_t opcode, uint32_t address,
                char *p1 = "]", *p2 = "";
 
                if (!(opcode & 0x0500))
-                       return ERROR_INVALID_ARGUMENTS;
+                       return ERROR_COMMAND_SYNTAX_ERROR;
 
                immed = opcode & 0x00ff;
 
@@ -3926,11 +4008,11 @@ static int t2ev_load_word(uint32_t opcode, uint32_t address,
                return ERROR_OK;
        }
 
-       return ERROR_INVALID_ARGUMENTS;
+       return ERROR_COMMAND_SYNTAX_ERROR;
 }
 
 static int t2ev_load_byte_hints(uint32_t opcode, uint32_t address,
-               arm_instruction_t *instruction, char *cp)
+               struct arm_instruction *instruction, char *cp)
 {
        int rn = (opcode >> 16) & 0xf;
        int rt = (opcode >> 12) & 0xf;
@@ -4105,11 +4187,11 @@ ldrsb_literal:
                goto ldrxb_immediate_t2;
        }
 
-       return ERROR_INVALID_ARGUMENTS;
+       return ERROR_COMMAND_SYNTAX_ERROR;
 }
 
 static int t2ev_load_halfword(uint32_t opcode, uint32_t address,
-               arm_instruction_t *instruction, char *cp)
+               struct arm_instruction *instruction, char *cp)
 {
        int rn = (opcode >> 16) & 0xf;
        int rt = (opcode >> 12) & 0xf;
@@ -4183,7 +4265,7 @@ ldrh_literal:
                return ERROR_OK;
        }
 
-       return ERROR_INVALID_ARGUMENTS;
+       return ERROR_COMMAND_SYNTAX_ERROR;
 }
 
 /*
@@ -4191,7 +4273,7 @@ ldrh_literal:
  * 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 thumb2_opcode(struct target *target, uint32_t address, struct arm_instruction *instruction)
 {
        int retval;
        uint16_t op;
@@ -4202,7 +4284,7 @@ int thumb2_opcode(target_t *target, uint32_t address, arm_instruction_t *instruc
        address &= ~1;
 
        /* clear fields, to avoid confusion */
-       memset(instruction, 0, sizeof(arm_instruction_t));
+       memset(instruction, 0, sizeof(struct arm_instruction));
 
        /* read first halfword, see if this is the only one */
        retval = target_read_u16(target, address, &op);
@@ -4295,7 +4377,7 @@ int thumb2_opcode(target_t *target, uint32_t address, arm_instruction_t *instruc
         * instructions; not yet handled here.
         */
 
-       if (retval == ERROR_INVALID_ARGUMENTS) {
+       if (retval == ERROR_COMMAND_SYNTAX_ERROR) {
                instruction->type = ARM_UNDEFINED_INSTRUCTION;
                strcpy(cp, "UNDEFINED OPCODE");
                return ERROR_OK;
@@ -4308,7 +4390,7 @@ int thumb2_opcode(target_t *target, uint32_t address, arm_instruction_t *instruc
        return ERROR_OK;
 }
 
-int arm_access_size(arm_instruction_t *instruction)
+int arm_access_size(struct arm_instruction *instruction)
 {
        if ((instruction->type == ARM_LDRB)
                || (instruction->type == ARM_LDRBT)