Use capstone for ARM disassembler
[openocd.git] / src / target / arm_disassembler.c
index 59c0537b7deff3280120fb0ab1915890f5bef4ce..9b8c09e45f73a9f432316a35bebe95e4fbf70892 100644 (file)
 #include "arm_disassembler.h"
 #include <helper/log.h>
 
+#if HAVE_CAPSTONE
+#include <capstone/capstone.h>
+#endif
+
 /*
  * This disassembler supports two main functions for OpenOCD:
  *
@@ -3000,1616 +3004,126 @@ int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, struct arm_instruct
        return -1;
 }
 
-static int t2ev_b_bl(uint32_t opcode, uint32_t address,
-                    struct arm_instruction *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;
-
-       char *inst;
-       switch ((opcode >> 12) & 0x5) {
-       case 0x1:
-               inst = "B.W";
-               instruction->type = ARM_B;
-               break;
-       case 0x4:
-               inst = "BLX";
-               instruction->type = ARM_BLX;
-               address &= 0xfffffffc;
-               break;
-       case 0x5:
-               inst = "BL";
-               instruction->type = ARM_BL;
-               break;
-       default:
-               return ERROR_COMMAND_SYNTAX_ERROR;
-       }
-       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, inst, address);
-
-       return ERROR_OK;
-}
-
-static int t2ev_cond_b(uint32_t opcode, uint32_t address,
-                      struct arm_instruction *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 |= 0x1fff << 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)
+int arm_access_size(struct arm_instruction *instruction)
 {
-       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;
+       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;
        }
-       return special;
 }
 
-static int t2ev_hint(uint32_t opcode, uint32_t address,
-                    struct arm_instruction *instruction, char *cp)
+#if HAVE_CAPSTONE
+static void print_opcode(struct command_invocation *cmd, const cs_insn *insn)
 {
-       const char *mnemonic;
+       uint32_t opcode = 0;
 
-       if (opcode & 0x0700) {
-               instruction->type = ARM_UNDEFINED_INSTRUCTION;
-               strcpy(cp, "UNDEFINED");
-               return ERROR_OK;
-       }
+       memcpy(&opcode, insn->bytes, insn->size);
 
-       if (opcode & 0x00f0) {
-               sprintf(cp, "DBG\t#%d", (int) opcode & 0xf);
-               return ERROR_OK;
-       }
+       if (insn->size == 4) {
+               uint16_t opcode_high = opcode >> 16;
+               opcode = opcode & 0xffff;
 
-       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;
+               command_print(cmd, "0x%08" PRIx64"  %04x %04x\t%s%s%s",
+                       insn->address, opcode, opcode_high, insn->mnemonic,
+                       insn->op_str[0] ? "\t" : "", insn->op_str);
+       } else {
+               command_print(cmd, "0x%08" PRIx64"  %04x\t%s%s%s",
+                       insn->address, opcode, insn->mnemonic,
+                       insn->op_str[0] ? "\t" : "", insn->op_str);
        }
-       strcpy(cp, mnemonic);
-       return ERROR_OK;
 }
 
-static int t2ev_misc(uint32_t opcode, uint32_t address,
-                    struct arm_instruction *instruction, char *cp)
+int arm_disassemble(struct command_invocation *cmd, struct target *target,
+               target_addr_t address, size_t count, bool thumb_mode)
 {
-       const char *mnemonic;
+       csh handle;
+       int ret;
+       cs_insn *insn;
+       cs_mode mode;
 
-       switch ((opcode >> 4) & 0x0f) {
-               case 0:
-                       mnemonic = "LEAVEX";
-                       break;
-               case 1:
-                       mnemonic = "ENTERX";
-                       break;
-               case 2:
-                       mnemonic = "CLREX";
-                       break;
-               case 4:
-                       mnemonic = "DSB";
-                       break;
-               case 5:
-                       mnemonic = "DMB";
-                       break;
-               case 6:
-                       mnemonic = "ISB";
-                       break;
-               default:
-                       return ERROR_COMMAND_SYNTAX_ERROR;
-       }
-       strcpy(cp, mnemonic);
-       return ERROR_OK;
-}
-
-static int t2ev_b_misc(uint32_t opcode, uint32_t address,
-                      struct arm_instruction *instruction, char *cp)
-{
-       /* permanently undefined */
-       if ((opcode & 0x07f07000) == 0x07f02000) {
-               instruction->type = ARM_UNDEFINED_INSTRUCTION;
-               strcpy(cp, "UNDEFINED");
-               return ERROR_OK;
+       if (!cs_support(CS_ARCH_ARM)) {
+               LOG_ERROR("ARM architecture not supported by capstone");
+               return ERROR_FAIL;
        }
 
-       switch ((opcode >> 12) & 0x5) {
-               case 0x1:
-               case 0x4:
-               case 0x5:
-                       return t2ev_b_bl(opcode, address, instruction, cp);
-               case 0:
-                       if (((opcode >> 23) & 0x07) != 0x07)
-                               return t2ev_cond_b(opcode, address, instruction, cp);
-                       if (opcode & (1 << 26))
-                               goto undef;
-                       break;
-       }
+       mode = CS_MODE_LITTLE_ENDIAN;
 
-       switch ((opcode >> 20) & 0x7f) {
-               case 0x38:
-               case 0x39:
-                       sprintf(cp, "MSR\t%s, r%d", special_name(opcode & 0xff),
-                               (int) (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 0x3c:
-                       sprintf(cp, "BXJ\tr%d", (int) (opcode >> 16) & 0x0f);
-                       return ERROR_OK;
-               case 0x3e:
-               case 0x3f:
-                       sprintf(cp, "MRS\tr%d, %s", (int) (opcode >> 8) & 0x0f,
-                               special_name(opcode & 0xff));
-                       return ERROR_OK;
-       }
+       if (thumb_mode)
+               mode |= CS_MODE_THUMB;
 
-undef:
-       return ERROR_COMMAND_SYNTAX_ERROR;
-}
+       ret = cs_open(CS_ARCH_ARM, mode, &handle);
 
-static int t2ev_data_mod_immed(uint32_t opcode, uint32_t address,
-                              struct arm_instruction *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 = "";
-       char *suffix2 = "";
-
-       /* 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 (ret != CS_ERR_OK) {
+               LOG_ERROR("cs_open() failed: %s", cs_strerror(ret));
+               return ERROR_FAIL;
        }
 
-       if (opcode & (1 << 20))
-               suffix = "S";
+       ret = cs_option(handle, CS_OPT_SKIPDATA, CS_OPT_ON);
 
-       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;
-                               suffix2 = ".W";
-                       } 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";
-                               suffix2 = ".W";
-                       }
-                       break;
-               case 10:
-                       instruction->type = ARM_ADC;
-                       mnemonic = "ADC";
-                       suffix2 = ".W";
-                       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";
-                       }
-                       suffix2 = ".W";
-                       break;
-               case 14:
-                       instruction->type = ARM_RSB;
-                       mnemonic = "RSB";
-                       suffix2 = ".W";
-                       break;
-               default:
-                       return ERROR_COMMAND_SYNTAX_ERROR;
+       if (ret != CS_ERR_OK) {
+               LOG_ERROR("cs_option() failed: %s", cs_strerror(ret));
+               cs_close(&handle);
+               return ERROR_FAIL;
        }
 
-       if (one)
-               sprintf(cp, "%s%s\tr%d, #%d\t; %#8.8x",
-                               mnemonic, suffix2, rd, immed, immed);
-       else
-               sprintf(cp, "%s%s%s\tr%d, r%d, #%d\t; %#8.8x",
-                               mnemonic, suffix, suffix2,
-                               rd, rn, immed, immed);
-
-       return ERROR_OK;
-}
-
-static int t2ev_data_immed(uint32_t opcode, uint32_t address,
-                          struct arm_instruction *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) >> 4);
-       if (opcode & (1 << 26))
-               immed |= (1 << 11);
+       insn = cs_malloc(handle);
 
-       switch ((opcode >> 20) & 0x1f) {
-               case 0:
-                       if (rn == 0xf) {
-                               add = true;
-                               goto do_adr;
-                       }
-                       mnemonic = "ADDW";
-                       break;
-               case 4:
-                       immed |= (opcode >> 4) & 0xf000;
-                       sprintf(cp, "MOVW\tr%d, #%d\t; %#3.3x", rd, immed, immed);
-                       return ERROR_OK;
-               case 0x0a:
-                       if (rn == 0xf)
-                               goto do_adr;
-                       mnemonic = "SUBW";
-                       break;
-               case 0x0c:
-                       /* move constant to top 16 bits of register */
-                       immed |= (opcode >> 4) & 0xf000;
-                       sprintf(cp, "MOVT\tr%d, #%d\t; %#4.4x", rd, immed, immed);
-                       return ERROR_OK;
-               case 0x10:
-               case 0x12:
-                       is_signed = true;
-                       /* fallthrough */
-               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, (int) (opcode & 0x1f) + is_signed, 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,
-                               (int) (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,
-                                               (int) (opcode & 0x1f) + 1 - immed);
-                       else            /* bitfield insert */
-                               sprintf(cp, "BFI\tr%d, r%d, #%d, #%d\t",
-                                               rd, rn, immed,
-                                               (int) (opcode & 0x1f) + 1 - immed);
-                       return ERROR_OK;
-               default:
-                       return ERROR_COMMAND_SYNTAX_ERROR;
+       if (!insn) {
+               LOG_ERROR("cs_malloc() failed\n");
+               cs_close(&handle);
+               return ERROR_FAIL;
        }
 
-       sprintf(cp, "%s\tr%d, r%d, #%d\t; %#3.3x", mnemonic,
-                       rd, rn, immed, immed);
-       return ERROR_OK;
+       while (count > 0) {
+           uint8_t buffer[4];
 
-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;
-}
+               ret = target_read_buffer(target, address, sizeof(buffer), buffer);
 
-static int t2ev_store_single(uint32_t opcode, uint32_t address,
-                            struct arm_instruction *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_COMMAND_SYNTAX_ERROR;
-
-       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_COMMAND_SYNTAX_ERROR;
-       }
+               if (ret != ERROR_OK) {
+                       cs_free(insn, 1);
+                       cs_close(&handle);
+                       return ret;
+               }
 
-       sprintf(cp, "STR%s.W\tr%d, [r%d, r%d, LSL #%d]",
-                       size, rt, rn, (int) opcode & 0x0f,
-                       (int) (opcode >> 4) & 0x03);
-       return ERROR_OK;
+               size_t size = sizeof(buffer);
+               const uint8_t *tmp = buffer;
 
-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;
+               ret = cs_disasm_iter(handle, &tmp, &size, &address, insn);
 
-imm8:
-       immed = opcode & 0x00ff;
+               if (!ret) {
+                       LOG_ERROR("cs_disasm_iter() failed: %s",
+                               cs_strerror(cs_errno(handle)));
+                       cs_free(insn, 1);
+                       cs_close(&handle);
+                       return ERROR_FAIL;
+               }
 
-       switch (opcode & 0x700) {
-               case 0x600:
-                       suffix = "T";
-                       break;
-               case 0x000:
-               case 0x200:
-                       return ERROR_COMMAND_SYNTAX_ERROR;
+               print_opcode(cmd, insn);
+               count--;
        }
 
-       /* two indexed modes will write back rn */
-       if (opcode & 0x100) {
-               if (opcode & 0x400)     /* pre-indexed */
-                       p2 = "]!";
-               else {                  /* post-indexed */
-                       p1 = "]";
-                       p2 = "";
-               }
-       }
+       cs_free(insn, 1);
+       cs_close(&handle);
 
-       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,
-                     struct arm_instruction *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",
-                                               (int) (opcode >> 8) & 0xf,
-                                               (int) (opcode >> 16) & 0xf,
-                                               (int) (opcode >> 0) & 0xf);
-                       else
-                               sprintf(cp, "MLA\tr%d, r%d, r%d, r%d",
-                                               (int) (opcode >> 8) & 0xf,
-                                               (int) (opcode >> 16) & 0xf,
-                                               (int) (opcode >> 0) & 0xf, ra);
-                       break;
-               case 0x10:
-                       sprintf(cp, "MLS\tr%d, r%d, r%d, r%d",
-                               (int) (opcode >> 8) & 0xf,
-                               (int) (opcode >> 16) & 0xf,
-                               (int) (opcode >> 0) & 0xf, ra);
-                       break;
-               default:
-                       return ERROR_COMMAND_SYNTAX_ERROR;
-       }
-       return ERROR_OK;
-}
-
-static int t2ev_mul64_div(uint32_t opcode, uint32_t address,
-                         struct arm_instruction *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,
-                               (int) (opcode >> 12) & 0xf,
-                               (int) (opcode >> 8) & 0xf,
-                               (int) (opcode >> 16) & 0xf,
-                               (int) (opcode >> 0) & 0xf);
-                       break;
-               case 0x1f:
-               case 0x3f:
-                       sprintf(cp, "%cDIV\tr%d, r%d, r%d",
-                               (op & 0x20) ? 'U' : 'S',
-                               (int) (opcode >> 8) & 0xf,
-                               (int) (opcode >> 16) & 0xf,
-                               (int) (opcode >> 0) & 0xf);
-                       break;
-               default:
-                       return ERROR_COMMAND_SYNTAX_ERROR;
-       }
-
-       return ERROR_OK;
-}
-
-static int t2ev_ldm_stm(uint32_t opcode, uint32_t address,
-                       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;
-               case 3:
-                       if (rn == 13 && t)
-                               sprintf(cp, "POP.W\t");
-                       else
-                               sprintf(cp, "LDM.W\tr%d%s, ", rn, t ? "!" : "");
-                       break;
-               case 4:
-                       if (rn == 13 && t)
-                               sprintf(cp, "PUSH.W\t");
-                       else
-                               sprintf(cp, "STMDB\tr%d%s, ", rn, t ? "!" : "");
-                       break;
-               case 5:
-                       sprintf(cp, "LDMDB.W\tr%d%s, ", rn, t ? "!" : "");
-                       break;
-               default:
-                       return ERROR_COMMAND_SYNTAX_ERROR;
-       }
-
-       cp = strchr(cp, 0);
-       *cp++ = '{';
-       for (t = 0; registers; t++, registers >>= 1) {
-               if ((registers & 1) == 0)
-                       continue;
-               registers &= ~1;
-               sprintf(cp, "r%d%s", t, registers ? ", " : "");
-               cp = strchr(cp, 0);
-       }
-       *cp++ = '}';
-       *cp++ = 0;
-
-       return ERROR_OK;
-}
-
-/* load/store dual or exclusive, table branch */
-static int t2ev_ldrex_strex(uint32_t opcode, uint32_t address,
-                           struct arm_instruction *instruction, char *cp)
-{
-       unsigned op1op2 = (opcode >> 20) & 0x3;
-       unsigned op3 = (opcode >> 4) & 0xf;
-       char *mnemonic;
-       unsigned rn = (opcode >> 16) & 0xf;
-       unsigned rt = (opcode >> 12) & 0xf;
-       unsigned rd = (opcode >> 8) & 0xf;
-       unsigned imm = opcode & 0xff;
-       char *p1 = "";
-       char *p2 = "]";
-
-       op1op2 |= (opcode >> 21) & 0xc;
-       switch (op1op2) {
-               case 0:
-                       mnemonic = "STREX";
-                       goto strex;
-               case 1:
-                       mnemonic = "LDREX";
-                       goto ldrex;
-               case 2:
-               case 6:
-               case 8:
-               case 10:
-               case 12:
-               case 14:
-                       mnemonic = "STRD";
-                       goto immediate;
-               case 3:
-               case 7:
-               case 9:
-               case 11:
-               case 13:
-               case 15:
-                       mnemonic = "LDRD";
-                       if (rn == 15)
-                               goto literal;
-                       else
-                               goto immediate;
-               case 4:
-                       switch (op3) {
-                               case 4:
-                                       mnemonic = "STREXB";
-                                       break;
-                               case 5:
-                                       mnemonic = "STREXH";
-                                       break;
-                               default:
-                                       return ERROR_COMMAND_SYNTAX_ERROR;
-                       }
-                       rd = opcode & 0xf;
-                       imm = 0;
-                       goto strex;
-               case 5:
-                       switch (op3) {
-                               case 0:
-                                       sprintf(cp, "TBB\t[r%u, r%u]", rn, imm & 0xf);
-                                       return ERROR_OK;
-                               case 1:
-                                       sprintf(cp, "TBH\t[r%u, r%u, LSL #1]", rn, imm & 0xf);
-                                       return ERROR_OK;
-                               case 4:
-                                       mnemonic = "LDREXB";
-                                       break;
-                               case 5:
-                                       mnemonic = "LDREXH";
-                                       break;
-                               default:
-                                       return ERROR_COMMAND_SYNTAX_ERROR;
-                       }
-                       imm = 0;
-                       goto ldrex;
-       }
-       return ERROR_COMMAND_SYNTAX_ERROR;
-
-strex:
-       imm <<= 2;
-       if (imm)
-               sprintf(cp, "%s\tr%u, r%u, [r%u, #%u]\t; %#2.2x",
-                               mnemonic, rd, rt, rn, imm, imm);
-       else
-               sprintf(cp, "%s\tr%u, r%u, [r%u]",
-                               mnemonic, rd, rt, rn);
-       return ERROR_OK;
-
-ldrex:
-       imm <<= 2;
-       if (imm)
-               sprintf(cp, "%s\tr%u, [r%u, #%u]\t; %#2.2x",
-                               mnemonic, rt, rn, imm, imm);
-       else
-               sprintf(cp, "%s\tr%u, [r%u]",
-                               mnemonic, rt, rn);
-       return ERROR_OK;
-
-immediate:
-       /* two indexed modes will write back rn */
-       if (opcode & (1 << 21)) {
-               if (opcode & (1 << 24)) /* pre-indexed */
-                       p2 = "]!";
-               else {                  /* post-indexed */
-                       p1 = "]";
-                       p2 = "";
-               }
-       }
-
-       imm <<= 2;
-       sprintf(cp, "%s\tr%u, r%u, [r%u%s, #%s%u%s\t; %#2.2x",
-                       mnemonic, rt, rd, rn, p1,
-                       (opcode & (1 << 23)) ? "" : "-",
-                       imm, p2, imm);
-       return ERROR_OK;
-
-literal:
-       address = thumb_alignpc4(address);
-       imm <<= 2;
-       if (opcode & (1 << 23))
-               address += imm;
-       else
-               address -= imm;
-       sprintf(cp, "%s\tr%u, r%u, %#8.8" PRIx32,
-                       mnemonic, rt, rd, address);
-       return ERROR_OK;
-}
-
-static int t2ev_data_shift(uint32_t opcode, uint32_t address,
-                          struct arm_instruction *instruction, char *cp)
-{
-       int op = (opcode >> 21) & 0xf;
-       int rd = (opcode >> 8) & 0xf;
-       int rn = (opcode >> 16) & 0xf;
-       int type = (opcode >> 4) & 0x3;
-       int immed = (opcode >> 6) & 0x3;
-       char *mnemonic;
-       char *suffix = "";
-
-       immed |= (opcode >> 10) & 0x1c;
-       if (opcode & (1 << 20))
-               suffix = "S";
-
-       switch (op) {
-               case 0:
-                       if (rd == 0xf) {
-                               if (!(opcode & (1 << 20)))
-                                       return ERROR_COMMAND_SYNTAX_ERROR;
-                               instruction->type = ARM_TST;
-                               mnemonic = "TST";
-                               suffix = "";
-                               goto two;
-                       }
-                       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;
-                               switch (type) {
-                                       case 0:
-                                               if (immed == 0) {
-                                                       sprintf(cp, "MOV%s.W\tr%d, r%d",
-                                                                       suffix, rd,
-                                                                       (int) (opcode & 0xf));
-                                                       return ERROR_OK;
-                                               }
-                                               mnemonic = "LSL";
-                                               break;
-                                       case 1:
-                                               mnemonic = "LSR";
-                                               break;
-                                       case 2:
-                                               mnemonic = "ASR";
-                                               break;
-                                       default:
-                                               if (immed == 0) {
-                                                       sprintf(cp, "RRX%s\tr%d, r%d",
-                                                                       suffix, rd,
-                                                                       (int) (opcode & 0xf));
-                                                       return ERROR_OK;
-                                               }
-                                               mnemonic = "ROR";
-                                               break;
-                               }
-                               goto immediate;
-                       } else {
-                               instruction->type = ARM_ORR;
-                               mnemonic = "ORR";
-                       }
-                       break;
-               case 3:
-                       if (rn == 0xf) {
-                               instruction->type = ARM_MVN;
-                               mnemonic = "MVN";
-                               rn = rd;
-                               goto two;
-                       } else {
-                               /* instruction->type = ARM_ORN; */
-                               mnemonic = "ORN";
-                       }
-                       break;
-               case 4:
-                       if (rd == 0xf) {
-                               if (!(opcode & (1 << 20)))
-                                       return ERROR_COMMAND_SYNTAX_ERROR;
-                               instruction->type = ARM_TEQ;
-                               mnemonic = "TEQ";
-                               suffix = "";
-                               goto two;
-                       }
-                       instruction->type = ARM_EOR;
-                       mnemonic = "EOR";
-                       break;
-               case 8:
-                       if (rd == 0xf) {
-                               if (!(opcode & (1 << 20)))
-                                       return ERROR_COMMAND_SYNTAX_ERROR;
-                               instruction->type = ARM_CMN;
-                               mnemonic = "CMN";
-                               suffix = "";
-                               goto two;
-                       }
-                       instruction->type = ARM_ADD;
-                       mnemonic = "ADD";
-                       break;
-               case 0xa:
-                       instruction->type = ARM_ADC;
-                       mnemonic = "ADC";
-                       break;
-               case 0xb:
-                       instruction->type = ARM_SBC;
-                       mnemonic = "SBC";
-                       break;
-               case 0xd:
-                       if (rd == 0xf) {
-                               if (!(opcode & (1 << 21)))
-                                       return ERROR_COMMAND_SYNTAX_ERROR;
-                               instruction->type = ARM_CMP;
-                               mnemonic = "CMP";
-                               suffix = "";
-                               goto two;
-                       }
-                       instruction->type = ARM_SUB;
-                       mnemonic = "SUB";
-                       break;
-               case 0xe:
-                       instruction->type = ARM_RSB;
-                       mnemonic = "RSB";
-                       break;
-               default:
-                       return ERROR_COMMAND_SYNTAX_ERROR;
-       }
-
-       sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
-                       mnemonic, suffix, rd, rn, (int) (opcode & 0xf));
-
-shift:
-       cp = strchr(cp, 0);
-
-       switch (type) {
-               case 0:
-                       if (immed == 0)
-                               return ERROR_OK;
-                       suffix = "LSL";
-                       break;
-               case 1:
-                       suffix = "LSR";
-                       if (immed == 32)
-                               immed = 0;
-                       break;
-               case 2:
-                       suffix = "ASR";
-                       if (immed == 32)
-                               immed = 0;
-                       break;
-               case 3:
-                       if (immed == 0) {
-                               strcpy(cp, ", RRX");
-                               return ERROR_OK;
-                       }
-                       suffix = "ROR";
-                       break;
-       }
-       sprintf(cp, ", %s #%d", suffix, immed ? immed : 32);
-       return ERROR_OK;
-
-two:
-       sprintf(cp, "%s%s.W\tr%d, r%d",
-                       mnemonic, suffix, rn, (int) (opcode & 0xf));
-       goto shift;
-
-immediate:
-       sprintf(cp, "%s%s.W\tr%d, r%d, #%d",
-                       mnemonic, suffix, rd,
-                       (int) (opcode & 0xf), immed ? immed : 32);
-       return ERROR_OK;
-}
-
-static int t2ev_data_reg(uint32_t opcode, uint32_t address,
-                        struct arm_instruction *instruction, char *cp)
-{
-       char *mnemonic;
-       char *suffix = "";
-
-       if (((opcode >> 4) & 0xf) == 0) {
-               switch ((opcode >> 21) & 0x7) {
-                       case 0:
-                               mnemonic = "LSL";
-                               break;
-                       case 1:
-                               mnemonic = "LSR";
-                               break;
-                       case 2:
-                               mnemonic = "ASR";
-                               break;
-                       case 3:
-                               mnemonic = "ROR";
-                               break;
-                       default:
-                               return ERROR_COMMAND_SYNTAX_ERROR;
-               }
-
-               instruction->type = ARM_MOV;
-               if (opcode & (1 << 20))
-                       suffix = "S";
-               sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
-                               mnemonic, suffix,
-                               (int) (opcode >> 8) & 0xf,
-                               (int) (opcode >> 16) & 0xf,
-                               (int) (opcode >> 0) & 0xf);
-
-       } else if (opcode & (1 << 7)) {
-               switch ((opcode >> 20) & 0xf) {
-                       case 0:
-                       case 1:
-                       case 4:
-                       case 5:
-                               switch ((opcode >> 4) & 0x3) {
-                                       case 1:
-                                               suffix = ", ROR #8";
-                                               break;
-                                       case 2:
-                                               suffix = ", ROR #16";
-                                               break;
-                                       case 3:
-                                               suffix = ", ROR #24";
-                                               break;
-                               }
-                               sprintf(cp, "%cXT%c.W\tr%d, r%d%s",
-                                       (opcode & (1 << 24)) ? 'U' : 'S',
-                                       (opcode & (1 << 26)) ? 'B' : 'H',
-                                       (int) (opcode >> 8) & 0xf,
-                                       (int) (opcode >> 0) & 0xf,
-                                       suffix);
-                               break;
-                       case 8:
-                       case 9:
-                       case 0xa:
-                       case 0xb:
-                               if (opcode & (1 << 6))
-                                       return ERROR_COMMAND_SYNTAX_ERROR;
-                               if (((opcode >> 12) & 0xf) != 0xf)
-                                       return ERROR_COMMAND_SYNTAX_ERROR;
-                               if (!(opcode & (1 << 20)))
-                                       return ERROR_COMMAND_SYNTAX_ERROR;
-
-                               switch (((opcode >> 19) & 0x04)
-                                       | ((opcode >> 4) & 0x3)) {
-                                       case 0:
-                                               mnemonic = "REV.W";
-                                               break;
-                                       case 1:
-                                               mnemonic = "REV16.W";
-                                               break;
-                                       case 2:
-                                               mnemonic = "RBIT";
-                                               break;
-                                       case 3:
-                                               mnemonic = "REVSH.W";
-                                               break;
-                                       case 4:
-                                               mnemonic = "CLZ";
-                                               break;
-                                       default:
-                                               return ERROR_COMMAND_SYNTAX_ERROR;
-                               }
-                               sprintf(cp, "%s\tr%d, r%d",
-                                       mnemonic,
-                                       (int) (opcode >> 8) & 0xf,
-                                       (int) (opcode >> 0) & 0xf);
-                               break;
-                       default:
-                               return ERROR_COMMAND_SYNTAX_ERROR;
-               }
-       }
-
-       return ERROR_OK;
-}
-
-static int t2ev_load_word(uint32_t opcode, uint32_t address,
-                         struct arm_instruction *instruction, char *cp)
-{
-       int rn = (opcode >> 16) & 0xf;
-       int immed;
-
-       instruction->type = ARM_LDR;
-
-       if (rn == 0xf) {
-               immed = opcode & 0x0fff;
-               if ((opcode & (1 << 23)) == 0)
-                       immed = -immed;
-               sprintf(cp, "LDR\tr%d, %#8.8" PRIx32,
-                               (int) (opcode >> 12) & 0xf,
-                               thumb_alignpc4(address) + immed);
-               return ERROR_OK;
-       }
-
-       if (opcode & (1 << 23)) {
-               immed = opcode & 0x0fff;
-               sprintf(cp, "LDR.W\tr%d, [r%d, #%d]\t; %#3.3x",
-                               (int) (opcode >> 12) & 0xf,
-                               rn, immed, immed);
-               return ERROR_OK;
-       }
-
-       if (!(opcode & (0x3f << 6))) {
-               sprintf(cp, "LDR.W\tr%d, [r%d, r%d, LSL #%d]",
-                               (int) (opcode >> 12) & 0xf,
-                               rn,
-                               (int) (opcode >> 0) & 0xf,
-                               (int) (opcode >> 4) & 0x3);
-               return ERROR_OK;
-       }
-
-
-       if (((opcode >> 8) & 0xf) == 0xe) {
-               immed = opcode & 0x00ff;
-
-               sprintf(cp, "LDRT\tr%d, [r%d, #%d]\t; %#2.2x",
-                               (int) (opcode >> 12) & 0xf,
-                               rn, immed, immed);
-               return ERROR_OK;
-       }
-
-       if (((opcode >> 8) & 0xf) == 0xc || (opcode & 0x0900) == 0x0900) {
-               char *p1 = "]", *p2 = "";
-
-               if (!(opcode & 0x0500))
-                       return ERROR_COMMAND_SYNTAX_ERROR;
-
-               immed = opcode & 0x00ff;
-
-               /* two indexed modes will write back rn */
-               if (opcode & 0x100) {
-                       if (opcode & 0x400)     /* pre-indexed */
-                               p2 = "]!";
-                       else {                  /* post-indexed */
-                               p1 = "]";
-                               p2 = "";
-                       }
-               }
-
-               sprintf(cp, "LDR\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
-                               (int) (opcode >> 12) & 0xf,
-                               rn, p1,
-                               (opcode & 0x200) ? "" : "-",
-                               immed, p2, immed);
-               return ERROR_OK;
-       }
-
-       return ERROR_COMMAND_SYNTAX_ERROR;
-}
-
-static int t2ev_load_byte_hints(uint32_t opcode, uint32_t address,
-                               struct arm_instruction *instruction, char *cp)
-{
-       int rn = (opcode >> 16) & 0xf;
-       int rt = (opcode >> 12) & 0xf;
-       int op2 = (opcode >> 6) & 0x3f;
-       unsigned immed;
-       char *p1 = "", *p2 = "]";
-       char *mnemonic;
-
-       switch ((opcode >> 23) & 0x3) {
-               case 0:
-                       if ((rn & rt) == 0xf) {
-pld_literal:
-                               immed = opcode & 0xfff;
-                               address = thumb_alignpc4(address);
-                               if (opcode & (1 << 23))
-                                       address += immed;
-                               else
-                                       address -= immed;
-                               sprintf(cp, "PLD\tr%d, %#8.8" PRIx32,
-                                               rt, address);
-                               return ERROR_OK;
-                       }
-                       if (rn == 0x0f && rt != 0x0f) {
-ldrb_literal:
-                               immed = opcode & 0xfff;
-                               address = thumb_alignpc4(address);
-                               if (opcode & (1 << 23))
-                                       address += immed;
-                               else
-                                       address -= immed;
-                               sprintf(cp, "LDRB\tr%d, %#8.8" PRIx32,
-                                               rt, address);
-                               return ERROR_OK;
-                       }
-                       if (rn == 0x0f)
-                               break;
-                       if ((op2 & 0x3c) == 0x38) {
-                               immed = opcode & 0xff;
-                               sprintf(cp, "LDRBT\tr%d, [r%d, #%d]\t; %#2.2x",
-                                               rt, rn, immed, immed);
-                               return ERROR_OK;
-                       }
-                       if ((op2 & 0x3c) == 0x30) {
-                               if (rt == 0x0f) {
-                                       immed = opcode & 0xff;
-                                       immed = -immed;
-preload_immediate:
-                                       p1 = (opcode & (1 << 21)) ? "W" : "";
-                                       sprintf(cp, "PLD%s\t[r%d, #%d]\t; %#6.6x",
-                                                       p1, rn, immed, immed);
-                                       return ERROR_OK;
-                               }
-                               mnemonic = "LDRB";
-ldrxb_immediate_t3:
-                               immed = opcode & 0xff;
-                               if (!(opcode & 0x200))
-                                       immed = -immed;
-
-                               /* two indexed modes will write back rn */
-                               if (opcode & 0x100) {
-                                       if (opcode & 0x400)     /* pre-indexed */
-                                               p2 = "]!";
-                                       else {          /* post-indexed */
-                                               p1 = "]";
-                                               p2 = "";
-                                       }
-                               }
-ldrxb_immediate_t2:
-                               sprintf(cp, "%s\tr%d, [r%d%s, #%d%s\t; %#8.8x",
-                                               mnemonic, rt, rn, p1,
-                                               immed, p2, immed);
-                               return ERROR_OK;
-                       }
-                       if ((op2 & 0x24) == 0x24) {
-                               mnemonic = "LDRB";
-                               goto ldrxb_immediate_t3;
-                       }
-                       if (op2 == 0) {
-                               int rm = opcode & 0xf;
-
-                               if (rt == 0x0f)
-                                       sprintf(cp, "PLD\t");
-                               else
-                                       sprintf(cp, "LDRB.W\tr%d, ", rt);
-                               immed = (opcode >> 4) & 0x3;
-                               cp = strchr(cp, 0);
-                               sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed);
-                               return ERROR_OK;
-                       }
-                       break;
-               case 1:
-                       if ((rn & rt) == 0xf)
-                               goto pld_literal;
-                       if (rt == 0xf) {
-                               immed = opcode & 0xfff;
-                               goto preload_immediate;
-                       }
-                       if (rn == 0x0f)
-                               goto ldrb_literal;
-                       mnemonic = "LDRB.W";
-                       immed = opcode & 0xfff;
-                       goto ldrxb_immediate_t2;
-               case 2:
-                       if ((rn & rt) == 0xf) {
-                               immed = opcode & 0xfff;
-                               address = thumb_alignpc4(address);
-                               if (opcode & (1 << 23))
-                                       address += immed;
-                               else
-                                       address -= immed;
-                               sprintf(cp, "PLI\t%#8.8" PRIx32, address);
-                               return ERROR_OK;
-                       }
-                       if (rn == 0xf && rt != 0xf) {
-ldrsb_literal:
-                               immed = opcode & 0xfff;
-                               address = thumb_alignpc4(address);
-                               if (opcode & (1 << 23))
-                                       address += immed;
-                               else
-                                       address -= immed;
-                               sprintf(cp, "LDRSB\t%#8.8" PRIx32, address);
-                               return ERROR_OK;
-                       }
-                       if (rn == 0xf)
-                               break;
-                       if ((op2 & 0x3c) == 0x38) {
-                               immed = opcode & 0xff;
-                               sprintf(cp, "LDRSBT\tr%d, [r%d, #%d]\t; %#2.2x",
-                                               rt, rn, immed, immed);
-                               return ERROR_OK;
-                       }
-                       if ((op2 & 0x3c) == 0x30) {
-                               if (rt == 0xf) {
-                                       immed = opcode & 0xff;
-                                       immed = -immed; /* pli */
-                                       sprintf(cp, "PLI\t[r%d, #%d]\t; -%#2.2x",
-                                                       rn, immed, -immed);
-                                       return ERROR_OK;
-                               }
-                               mnemonic = "LDRSB";
-                               goto ldrxb_immediate_t3;
-                       }
-                       if ((op2 & 0x24) == 0x24) {
-                               mnemonic = "LDRSB";
-                               goto ldrxb_immediate_t3;
-                       }
-                       if (op2 == 0) {
-                               int rm = opcode & 0xf;
-
-                               if (rt == 0x0f)
-                                       sprintf(cp, "PLI\t");
-                               else
-                                       sprintf(cp, "LDRSB.W\tr%d, ", rt);
-                               immed = (opcode >> 4) & 0x3;
-                               cp = strchr(cp, 0);
-                               sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed);
-                               return ERROR_OK;
-                       }
-                       break;
-               case 3:
-                       if (rt == 0xf) {
-                               immed = opcode & 0xfff;
-                               sprintf(cp, "PLI\t[r%d, #%d]\t; %#3.3x",
-                                               rn, immed, immed);
-                               return ERROR_OK;
-                       }
-                       if (rn == 0xf)
-                               goto ldrsb_literal;
-                       immed = opcode & 0xfff;
-                       mnemonic = "LDRSB";
-                       goto ldrxb_immediate_t2;
-       }
-
-       return ERROR_COMMAND_SYNTAX_ERROR;
-}
-
-static int t2ev_load_halfword(uint32_t opcode, uint32_t address,
-                             struct arm_instruction *instruction, char *cp)
-{
-       int rn = (opcode >> 16) & 0xf;
-       int rt = (opcode >> 12) & 0xf;
-       int op2 = (opcode >> 6) & 0x3f;
-       char *sign = "";
-       unsigned immed;
-
-       if (rt == 0xf) {
-               sprintf(cp, "HINT (UNALLOCATED)");
-               return ERROR_OK;
-       }
-
-       if (opcode & (1 << 24))
-               sign = "S";
-
-       if ((opcode & (1 << 23)) == 0) {
-               if (rn == 0xf) {
-ldrh_literal:
-                       immed = opcode & 0xfff;
-                       address = thumb_alignpc4(address);
-                       if (opcode & (1 << 23))
-                               address += immed;
-                       else
-                               address -= immed;
-                       sprintf(cp, "LDR%sH\tr%d, %#8.8" PRIx32,
-                                       sign, rt, address);
-                       return ERROR_OK;
-               }
-               if (op2 == 0) {
-                       int rm = opcode & 0xf;
-
-                       immed = (opcode >> 4) & 0x3;
-                       sprintf(cp, "LDR%sH.W\tr%d, [r%d, r%d, LSL #%d]",
-                                       sign, rt, rn, rm, immed);
-                       return ERROR_OK;
-               }
-               if ((op2 & 0x3c) == 0x38) {
-                       immed = opcode & 0xff;
-                       sprintf(cp, "LDR%sHT\tr%d, [r%d, #%d]\t; %#2.2x",
-                                       sign, rt, rn, immed, immed);
-                       return ERROR_OK;
-               }
-               if ((op2 & 0x3c) == 0x30 || (op2 & 0x24) == 0x24) {
-                       char *p1 = "", *p2 = "]";
-
-                       immed = opcode & 0xff;
-                       if (!(opcode & 0x200))
-                               immed = -immed;
-
-                       /* two indexed modes will write back rn */
-                       if (opcode & 0x100) {
-                               if (opcode & 0x400)     /* pre-indexed */
-                                       p2 = "]!";
-                               else {                  /* post-indexed */
-                                       p1 = "]";
-                                       p2 = "";
-                               }
-                       }
-                       sprintf(cp, "LDR%sH\tr%d, [r%d%s, #%d%s\t; %#8.8x",
-                                       sign, rt, rn, p1, immed, p2, immed);
-                       return ERROR_OK;
-               }
-       } else {
-               if (rn == 0xf)
-                       goto ldrh_literal;
-
-               immed = opcode & 0xfff;
-               sprintf(cp, "LDR%sH%s\tr%d, [r%d, #%d]\t; %#6.6x",
-                               sign, *sign ? "" : ".W",
-                               rt, rn, immed, immed);
-               return ERROR_OK;
-       }
-
-       return ERROR_COMMAND_SYNTAX_ERROR;
-}
-
-/*
- * 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(struct target *target, uint32_t address, struct arm_instruction *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(struct arm_instruction));
-
-       /* 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.5 Load/store multiple */
-       else if ((opcode & 0x1e400000) == 0x08000000)
-               retval = t2ev_ldm_stm(opcode, address, instruction, cp);
-
-       /* ARMv7-M: A5.3.6 Load/store dual or exclusive, table branch */
-       else if ((opcode & 0x1e400000) == 0x08400000)
-               retval = t2ev_ldrex_strex(opcode, address, instruction, cp);
-
-       /* ARMv7-M: A5.3.7 Load word */
-       else if ((opcode & 0x1f700000) == 0x18500000)
-               retval = t2ev_load_word(opcode, address, instruction, cp);
-
-       /* ARMv7-M: A5.3.8 Load halfword, unallocated memory hints */
-       else if ((opcode & 0x1e700000) == 0x18300000)
-               retval = t2ev_load_halfword(opcode, address, instruction, cp);
-
-       /* ARMv7-M: A5.3.9 Load byte, memory hints */
-       else if ((opcode & 0x1e700000) == 0x18100000)
-               retval = t2ev_load_byte_hints(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.11 Data processing (shifted register) */
-       else if ((opcode & 0x1e000000) == 0x0a000000)
-               retval = t2ev_data_shift(opcode, address, instruction, cp);
-
-       /* ARMv7-M: A5.3.12 Data processing (register)
-        * and A5.3.13 Miscellaneous operations
-        */
-       else if ((opcode & 0x1f000000) == 0x1a000000)
-               retval = t2ev_data_reg(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);
-
-       if (retval == ERROR_OK)
-               return retval;
-
-       /*
-        * Thumb2 also supports coprocessor, ThumbEE, and DSP/Media (SIMD)
-        * instructions; not yet handled here.
-        */
-
-       if (retval == ERROR_COMMAND_SYNTAX_ERROR) {
-               instruction->type = ARM_UNDEFINED_INSTRUCTION;
-               strcpy(cp, "UNDEFINED OPCODE");
-               return ERROR_OK;
-       }
-
-       LOG_DEBUG("Can't decode 32-bit Thumb2 yet (opcode=%08" PRIx32 ")",
-                       opcode);
-
-       strcpy(cp, "(32-bit Thumb2 ...)");
-       return ERROR_OK;
-}
-
-int arm_access_size(struct arm_instruction *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;
-       }
-}
+#endif /* HAVE_CAPSTONE */

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)