arm_disassembler: fix typo 'ARM_UNKNOWN_INSTUCTION' to '.._INSTRUCTION'
[fw/openocd] / src / target / arm_disassembler.c
index f0266d023158172bf97a3fd480b221e3bd134ed9..da8aee28b419c74400aa134cf86d3ae2135c02c4 100644 (file)
@@ -118,14 +118,130 @@ static int evaluate_pld(uint32_t opcode,
                        uint32_t address, struct arm_instruction *instruction)
 {
        /* PLD */
-       if ((opcode & 0x0d70f000) == 0x0550f000) {
+       if ((opcode & 0x0d30f000) == 0x0510f000) {
+               uint8_t Rn;
+               uint8_t U;
+               unsigned offset;
+
                instruction->type = ARM_PLD;
+               Rn = (opcode & 0xf0000) >> 16;
+               U = (opcode & 0x00800000) >> 23;
+               if (Rn == 0xf) {
+                       /* literal */
+                       offset = opcode & 0x0fff;
+                       snprintf(instruction->text, 128,
+                                "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD %s%d",
+                                address, opcode, U ? "" : "-", offset);
+               } else {
+                       uint8_t I, R;
+
+                       I = (opcode & 0x02000000) >> 25;
+                       R = (opcode & 0x00400000) >> 22;
+
+                       if (I) {
+                               /* register PLD{W} [<Rn>,+/-<Rm>{, <shift>}] */
+                               offset = (opcode & 0x0F80) >> 7;
+                               uint8_t Rm;
+                               Rm = opcode & 0xf;
+
+                               if (offset == 0) {
+                                       /* No shift */
+                                       snprintf(instruction->text, 128,
+                                                "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d]",
+                                                address, opcode, R ? "" : "W", Rn, U ? "" : "-", Rm);
+
+                               } else {
+                                       uint8_t shift;
+                                       shift = (opcode & 0x60) >> 5;
+
+                                       if (shift == 0x0) {
+                                               /* LSL */
+                                               snprintf(instruction->text, 128,
+                                                        "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d, LSL #0x%x)",
+                                                        address, opcode, R ? "" : "W", Rn, U ? "" : "-", Rm, offset);
+                                       } else if (shift == 0x1) {
+                                               /* LSR */
+                                               snprintf(instruction->text, 128,
+                                                        "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d, LSR #0x%x)",
+                                                        address, opcode, R ? "" : "W", Rn, U ? "" : "-", Rm, offset);
+                                       } else if (shift == 0x2) {
+                                               /* ASR */
+                                               snprintf(instruction->text, 128,
+                                                        "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d, ASR #0x%x)",
+                                                        address, opcode, R ? "" : "W", Rn, U ? "" : "-", Rm, offset);
+                                       } else if (shift == 0x3) {
+                                               /* ROR */
+                                               snprintf(instruction->text, 128,
+                                                        "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d, ROR #0x%x)",
+                                                        address, opcode, R ? "" : "W", Rn, U ? "" : "-", Rm, offset);
+                                       }
+                               }
+                       } else {
+                               /* immediate PLD{W} [<Rn>, #+/-<imm12>] */
+                               offset = opcode & 0x0fff;
+                               if (offset == 0) {
+                                       snprintf(instruction->text, 128,
+                                                "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d]",
+                                                address, opcode, R ? "" : "W", Rn);
+                               } else {
+                                       snprintf(instruction->text, 128,
+                                                "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, #%s%d]",
+                                                address, opcode, R ? "" : "W", Rn, U ? "" : "-", offset);
+                               }
+                       }
+               }
+               return ERROR_OK;
+       }
+       /* DSB */
+       if ((opcode & 0x07f000f0) == 0x05700040) {
+               instruction->type = ARM_DSB;
+
+               char *opt;
+               switch (opcode & 0x0000000f) {
+               case 0xf:
+                       opt = "SY";
+                       break;
+               case 0xe:
+                       opt = "ST";
+                       break;
+               case 0xb:
+                       opt = "ISH";
+                       break;
+               case 0xa:
+                       opt = "ISHST";
+                       break;
+               case 0x7:
+                       opt = "NSH";
+                       break;
+               case 0x6:
+                       opt = "NSHST";
+                       break;
+               case 0x3:
+                       opt = "OSH";
+                       break;
+               case 0x2:
+                       opt = "OSHST";
+                       break;
+               default:
+                       opt = "UNK";
+               }
 
                snprintf(instruction->text,
                                128,
-                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD ...TODO...",
-                               address,
-                               opcode);
+                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tDSB %s",
+                               address, opcode, opt);
+
+               return ERROR_OK;
+       }
+       /* ISB */
+       if ((opcode & 0x07f000f0) == 0x05700060) {
+               instruction->type = ARM_ISB;
+
+               snprintf(instruction->text,
+                               128,
+                               "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tISB %s",
+                               address, opcode,
+                               ((opcode & 0x0000000f) == 0xf) ? "SY" : "UNK");
 
                return ERROR_OK;
        }
@@ -1496,7 +1612,7 @@ static int evaluate_misc_instr(uint32_t opcode,
                }
 
                /* SMLAW < y> */
-               if (((opcode & 0x00600000) == 0x00100000) && (x == 0)) {
+               if (((opcode & 0x00600000) == 0x00200000) && (x == 0)) {
                        uint8_t Rd, Rm, Rs, Rn;
                        instruction->type = ARM_SMLAWy;
                        Rd = (opcode & 0xf0000) >> 16;
@@ -1518,7 +1634,7 @@ static int evaluate_misc_instr(uint32_t opcode,
                }
 
                /* SMUL < x><y> */
-               if ((opcode & 0x00600000) == 0x00300000) {
+               if ((opcode & 0x00600000) == 0x00600000) {
                        uint8_t Rd, Rm, Rs;
                        instruction->type = ARM_SMULxy;
                        Rd = (opcode & 0xf0000) >> 16;
@@ -1539,7 +1655,7 @@ static int evaluate_misc_instr(uint32_t opcode,
                }
 
                /* SMULW < y> */
-               if (((opcode & 0x00600000) == 0x00100000) && (x == 1)) {
+               if (((opcode & 0x00600000) == 0x00200000) && (x == 1)) {
                        uint8_t Rd, Rm, Rs;
                        instruction->type = ARM_SMULWy;
                        Rd = (opcode & 0xf0000) >> 16;
@@ -1562,6 +1678,33 @@ static int evaluate_misc_instr(uint32_t opcode,
        return ERROR_OK;
 }
 
+static int evaluate_mov_imm(uint32_t opcode,
+                             uint32_t address, struct arm_instruction *instruction)
+{
+       uint16_t immediate;
+       uint8_t Rd;
+       bool T;
+
+       Rd = (opcode & 0xf000) >> 12;
+       T = opcode & 0x00400000;
+       immediate = (opcode & 0xf0000) >> 4 | (opcode & 0xfff);
+
+       instruction->type = ARM_MOV;
+       instruction->info.data_proc.Rd = Rd;
+
+       snprintf(instruction->text,
+                128,
+                "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMOV%s%s r%i, #0x%" PRIx16,
+                address,
+                opcode,
+                T ? "T" : "W",
+                COND(opcode),
+                Rd,
+                immediate);
+
+       return ERROR_OK;
+}
+
 static int evaluate_data_proc(uint32_t opcode,
                              uint32_t address, struct arm_instruction *instruction)
 {
@@ -1838,16 +1981,9 @@ int arm_evaluate_opcode(uint32_t opcode, uint32_t address,
 
        /* catch opcodes with [27:25] = b001 */
        if ((opcode & 0x0e000000) == 0x02000000) {
-               /* Undefined instruction */
-               if ((opcode & 0x0fb00000) == 0x03000000) {
-                       instruction->type = ARM_UNDEFINED_INSTRUCTION;
-                       snprintf(instruction->text,
-                                       128,
-                                       "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
-                                       address,
-                                       opcode);
-                       return ERROR_OK;
-               }
+               /* 16-bit immediate load */
+               if ((opcode & 0x0fb00000) == 0x03000000)
+                       return evaluate_mov_imm(opcode, address, instruction);
 
                /* Move immediate to status register */
                if ((opcode & 0x0fb00000) == 0x03200000)
@@ -1950,7 +2086,7 @@ static int evaluate_b_bl_blx_thumb(uint16_t opcode,
                        break;
                /* BL/BLX prefix */
                case 2:
-                       instruction->type = ARM_UNKNOWN_INSTUCTION;
+                       instruction->type = ARM_UNKNOWN_INSTRUCTION;
                        mnemonic = "prefix";
                        target_address = offset << 12;
                        break;
@@ -2173,7 +2309,6 @@ static int evaluate_data_proc_thumb(uint16_t opcode,
                                                        address, opcode);
                                }
                                return ERROR_OK;
-                               break;
                }
        } else {
                switch (op) {
@@ -2537,7 +2672,7 @@ static int evaluate_load_store_multiple_thumb(uint16_t opcode,
                        instruction->type = ARM_STM;
                        mnemonic = "STM";
                }
-               snprintf(ptr_name, sizeof ptr_name, "r%i%s, ", Rn, wback);
+               snprintf(ptr_name, sizeof(ptr_name), "r%i%s, ", Rn, wback);
        } else {/* push/pop */
                Rn = 13;/* SP */
                if (L) {
@@ -2905,6 +3040,7 @@ static int t2ev_b_bl(uint32_t opcode, uint32_t address,
        case 0x4:
                inst = "BLX";
                instruction->type = ARM_BLX;
+               address &= 0xfffffffc;
                break;
        case 0x5:
                inst = "BL";