1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2006 by Dominic Rath *
5 * Dominic.Rath@gmx.de *
7 * Copyright (C) 2009 by David Brownell *
8 ***************************************************************************/
15 #include "arm_disassembler.h"
16 #include <helper/log.h>
23 * This disassembler supports two main functions for OpenOCD:
25 * - Various "disassemble" commands. OpenOCD can serve as a
26 * machine-language debugger, without help from GDB.
28 * - Single stepping. Not all ARM cores support hardware single
29 * stepping. To work without that support, the debugger must
30 * be able to decode instructions to find out where to put a
31 * "next instruction" breakpoint.
33 * In addition, interpretation of ETM trace data needs some of the
34 * decoding mechanisms.
36 * At this writing (September 2009) neither function is complete.
39 * * Old-style syntax (not UAL) is generally used
40 * * VFP instructions are not understood (ARMv5 and later)
41 * except as coprocessor 10/11 operations
42 * * Most ARM instructions through ARMv6 are decoded, but some
43 * of the post-ARMv4 opcodes may not be handled yet
44 * CPS, SDIV, UDIV, LDREX*, STREX*, QASX, ...
45 * * NEON instructions are not understood (ARMv7-A)
47 * - Thumb/Thumb2 decoding
48 * * UAL syntax should be consistently used
49 * * Any Thumb2 instructions used in Cortex-M3 (ARMv7-M) should
50 * be handled properly. Accordingly, so should the subset
51 * used in Cortex-M0/M1; and "original" 16-bit Thumb from
53 * * Conditional effects of Thumb2 "IT" (if-then) instructions
54 * are not handled: the affected instructions are not shown
55 * with their now-conditional suffixes.
56 * * Some ARMv6 and ARMv7-M Thumb2 instructions may not be
57 * handled (minimally for coprocessor access).
58 * * SIMD instructions, and some other Thumb2 instructions
59 * from ARMv7-A, are not understood.
62 * * As a Thumb2 variant, the Thumb2 comments (above) apply.
63 * * Opcodes changed by ThumbEE mode are not handled; these
64 * instructions wrongly decode as LDM and STM.
66 * - Jazelle decoding ... no support whatsoever for Jazelle mode
67 * or decoding. ARM encourages use of the more generic ThumbEE
68 * mode, instead of Jazelle mode, in current chips.
70 * - Single-step/emulation ... spotty support, which is only weakly
71 * tested. Thumb2 is not supported. (Arguably a full simulator
72 * is not needed to support just single stepping. Recognizing
73 * branch vs non-branch instructions suffices, except when the
74 * instruction faults and triggers a synchronous exception which
75 * can be intercepted using other means.)
77 * ARM DDI 0406B "ARM Architecture Reference Manual, ARM v7-A and
78 * ARM v7-R edition" gives the most complete coverage of the various
79 * generations of ARM instructions. At this writing it is publicly
80 * accessible to anyone willing to create an account at the ARM
81 * web site; see http://www.arm.com/documentation/ for information.
83 * ARM DDI 0403C "ARMv7-M Architecture Reference Manual" provides
84 * more details relevant to the Thumb2-only processors (such as
85 * the Cortex-M implementations).
88 /* textual representation of the condition field
89 * ALways (default) is omitted (empty string) */
90 static const char *arm_condition_strings[] = {
91 "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", "HI", "LS", "GE", "LT", "GT", "LE", "", "NV"
94 /* make up for C's missing ROR */
95 static uint32_t ror(uint32_t value, int places)
97 return (value >> places) | (value << (32 - places));
100 static int evaluate_unknown(uint32_t opcode,
101 uint32_t address, struct arm_instruction *instruction)
103 instruction->type = ARM_UNDEFINED_INSTRUCTION;
104 snprintf(instruction->text, 128,
105 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
106 "\tUNDEFINED INSTRUCTION", address, opcode);
110 static int evaluate_pld(uint32_t opcode,
111 uint32_t address, struct arm_instruction *instruction)
114 if ((opcode & 0x0d30f000) == 0x0510f000) {
119 instruction->type = ARM_PLD;
120 rn = (opcode & 0xf0000) >> 16;
121 u = (opcode & 0x00800000) >> 23;
124 offset = opcode & 0x0fff;
125 snprintf(instruction->text, 128,
126 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD %s%d",
127 address, opcode, u ? "" : "-", offset);
131 i = (opcode & 0x02000000) >> 25;
132 r = (opcode & 0x00400000) >> 22;
135 /* register PLD{W} [<Rn>,+/-<Rm>{, <shift>}] */
136 offset = (opcode & 0x0F80) >> 7;
142 snprintf(instruction->text, 128,
143 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d]",
144 address, opcode, r ? "" : "W", rn, u ? "" : "-", rm);
148 shift = (opcode & 0x60) >> 5;
152 snprintf(instruction->text, 128,
153 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d, LSL #0x%x)",
154 address, opcode, r ? "" : "W", rn, u ? "" : "-", rm, offset);
155 } else if (shift == 0x1) {
157 snprintf(instruction->text, 128,
158 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d, LSR #0x%x)",
159 address, opcode, r ? "" : "W", rn, u ? "" : "-", rm, offset);
160 } else if (shift == 0x2) {
162 snprintf(instruction->text, 128,
163 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d, ASR #0x%x)",
164 address, opcode, r ? "" : "W", rn, u ? "" : "-", rm, offset);
165 } else if (shift == 0x3) {
167 snprintf(instruction->text, 128,
168 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d, ROR #0x%x)",
169 address, opcode, r ? "" : "W", rn, u ? "" : "-", rm, offset);
173 /* immediate PLD{W} [<Rn>, #+/-<imm12>] */
174 offset = opcode & 0x0fff;
176 snprintf(instruction->text, 128,
177 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d]",
178 address, opcode, r ? "" : "W", rn);
180 snprintf(instruction->text, 128,
181 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, #%s%d]",
182 address, opcode, r ? "" : "W", rn, u ? "" : "-", offset);
189 if ((opcode & 0x07f000f0) == 0x05700040) {
190 instruction->type = ARM_DSB;
193 switch (opcode & 0x0000000f) {
222 snprintf(instruction->text,
224 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tDSB %s",
225 address, opcode, opt);
230 if ((opcode & 0x07f000f0) == 0x05700060) {
231 instruction->type = ARM_ISB;
233 snprintf(instruction->text,
235 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tISB %s",
237 ((opcode & 0x0000000f) == 0xf) ? "SY" : "UNK");
241 return evaluate_unknown(opcode, address, instruction);
244 static int evaluate_srs(uint32_t opcode,
245 uint32_t address, struct arm_instruction *instruction)
247 const char *wback = (opcode & (1 << 21)) ? "!" : "";
248 const char *mode = "";
250 switch ((opcode >> 23) & 0x3) {
255 /* "IA" is default */
265 switch (opcode & 0x0e500000) {
267 snprintf(instruction->text, 128, "0x%8.8" PRIx32
269 "\tSRS%s\tSP%s, #%d",
272 (unsigned)(opcode & 0x1f));
275 snprintf(instruction->text, 128, "0x%8.8" PRIx32
280 (unsigned)((opcode >> 16) & 0xf), wback);
283 return evaluate_unknown(opcode, address, instruction);
288 static int evaluate_swi(uint32_t opcode,
289 uint32_t address, struct arm_instruction *instruction)
291 instruction->type = ARM_SWI;
293 snprintf(instruction->text, 128,
294 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSVC %#6.6" PRIx32,
295 address, opcode, (opcode & 0xffffff));
300 static int evaluate_blx_imm(uint32_t opcode,
301 uint32_t address, struct arm_instruction *instruction)
305 uint32_t target_address;
307 instruction->type = ARM_BLX;
308 immediate = opcode & 0x00ffffff;
310 /* sign extend 24-bit immediate */
311 if (immediate & 0x00800000)
312 offset = 0xff000000 | immediate;
316 /* shift two bits left */
319 /* odd/event halfword */
320 if (opcode & 0x01000000)
323 target_address = address + 8 + offset;
325 snprintf(instruction->text,
327 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX 0x%8.8" PRIx32 "",
332 instruction->info.b_bl_bx_blx.reg_operand = -1;
333 instruction->info.b_bl_bx_blx.target_address = target_address;
338 static int evaluate_b_bl(uint32_t opcode,
339 uint32_t address, struct arm_instruction *instruction)
344 uint32_t target_address;
346 immediate = opcode & 0x00ffffff;
347 l = (opcode & 0x01000000) >> 24;
349 /* sign extend 24-bit immediate */
350 if (immediate & 0x00800000)
351 offset = 0xff000000 | immediate;
355 /* shift two bits left */
358 target_address = address + 8 + offset;
361 instruction->type = ARM_BL;
363 instruction->type = ARM_B;
365 snprintf(instruction->text,
367 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tB%s%s 0x%8.8" PRIx32,
374 instruction->info.b_bl_bx_blx.reg_operand = -1;
375 instruction->info.b_bl_bx_blx.target_address = target_address;
380 /* Coprocessor load/store and double register transfers
381 * both normal and extended instruction space (condition field b1111) */
382 static int evaluate_ldc_stc_mcrr_mrrc(uint32_t opcode,
383 uint32_t address, struct arm_instruction *instruction)
385 uint8_t cp_num = (opcode & 0xf00) >> 8;
388 if (((opcode & 0x0ff00000) == 0x0c400000) || ((opcode & 0x0ff00000) == 0x0c500000)) {
389 uint8_t cp_opcode, rd, rn, crm;
392 cp_opcode = (opcode & 0xf0) >> 4;
393 rd = (opcode & 0xf000) >> 12;
394 rn = (opcode & 0xf0000) >> 16;
395 crm = (opcode & 0xf);
398 if ((opcode & 0x0ff00000) == 0x0c400000) {
399 instruction->type = ARM_MCRR;
401 } else if ((opcode & 0x0ff00000) == 0x0c500000) {
403 instruction->type = ARM_MRRC;
406 LOG_ERROR("Unknown instruction");
410 snprintf(instruction->text, 128,
411 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
412 "\t%s%s%s p%i, %x, r%i, r%i, c%i",
413 address, opcode, mnemonic,
414 ((opcode & 0xf0000000) == 0xf0000000)
415 ? "2" : COND(opcode),
416 COND(opcode), cp_num, cp_opcode, rd, rn, crm);
417 } else {/* LDC or STC */
418 uint8_t crd, rn, offset;
421 char addressing_mode[32];
423 crd = (opcode & 0xf000) >> 12;
424 rn = (opcode & 0xf0000) >> 16;
425 offset = (opcode & 0xff) << 2;
428 if (opcode & 0x00100000) {
429 instruction->type = ARM_LDC;
432 instruction->type = ARM_STC;
436 u = (opcode & 0x00800000) >> 23;
438 /* addressing modes */
439 if ((opcode & 0x01200000) == 0x01000000)/* offset */
440 snprintf(addressing_mode, 32, "[r%i, #%s%d]",
441 rn, u ? "" : "-", offset);
442 else if ((opcode & 0x01200000) == 0x01200000) /* pre-indexed */
443 snprintf(addressing_mode, 32, "[r%i, #%s%d]!",
444 rn, u ? "" : "-", offset);
445 else if ((opcode & 0x01200000) == 0x00200000) /* post-indexed */
446 snprintf(addressing_mode, 32, "[r%i], #%s%d",
447 rn, u ? "" : "-", offset);
448 else if ((opcode & 0x01200000) == 0x00000000) /* unindexed */
449 snprintf(addressing_mode, 32, "[r%i], {%d}",
452 snprintf(instruction->text, 128, "0x%8.8" PRIx32
454 "\t%s%s%s p%i, c%i, %s",
455 address, opcode, mnemonic,
456 ((opcode & 0xf0000000) == 0xf0000000)
457 ? "2" : COND(opcode),
458 (opcode & (1 << 22)) ? "L" : "",
459 cp_num, crd, addressing_mode);
465 /* Coprocessor data processing instructions
466 * Coprocessor register transfer instructions
467 * both normal and extended instruction space (condition field b1111) */
468 static int evaluate_cdp_mcr_mrc(uint32_t opcode,
469 uint32_t address, struct arm_instruction *instruction)
473 uint8_t cp_num, opcode_1, crd_rd, crn, crm, opcode_2;
475 cond = ((opcode & 0xf0000000) == 0xf0000000) ? "2" : COND(opcode);
476 cp_num = (opcode & 0xf00) >> 8;
477 crd_rd = (opcode & 0xf000) >> 12;
478 crn = (opcode & 0xf0000) >> 16;
479 crm = (opcode & 0xf);
480 opcode_2 = (opcode & 0xe0) >> 5;
483 if (opcode & 0x00000010) { /* bit 4 set -> MRC/MCR */
484 if (opcode & 0x00100000) { /* bit 20 set -> MRC */
485 instruction->type = ARM_MRC;
487 } else {/* bit 20 not set -> MCR */
488 instruction->type = ARM_MCR;
492 opcode_1 = (opcode & 0x00e00000) >> 21;
494 snprintf(instruction->text,
496 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, 0x%2.2x, r%i, c%i, c%i, 0x%2.2x",
507 } else {/* bit 4 not set -> CDP */
508 instruction->type = ARM_CDP;
511 opcode_1 = (opcode & 0x00f00000) >> 20;
513 snprintf(instruction->text,
515 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, 0x%2.2x, c%i, c%i, c%i, 0x%2.2x",
531 /* Load/store instructions */
532 static int evaluate_load_store(uint32_t opcode,
533 uint32_t address, struct arm_instruction *instruction)
535 uint8_t i, p, u, b, w, l;
537 char *operation;/* "LDR" or "STR" */
538 char *suffix; /* "", "B", "T", "BT" */
542 i = (opcode & 0x02000000) >> 25;
543 p = (opcode & 0x01000000) >> 24;
544 u = (opcode & 0x00800000) >> 23;
545 b = (opcode & 0x00400000) >> 22;
546 w = (opcode & 0x00200000) >> 21;
547 l = (opcode & 0x00100000) >> 20;
549 /* target register */
550 rd = (opcode & 0xf000) >> 12;
553 rn = (opcode & 0xf0000) >> 16;
555 instruction->info.load_store.rd = rd;
556 instruction->info.load_store.rn = rn;
557 instruction->info.load_store.u = u;
559 /* determine operation */
565 /* determine instruction type and suffix */
567 if ((p == 0) && (w == 1)) {
569 instruction->type = ARM_LDRBT;
571 instruction->type = ARM_STRBT;
575 instruction->type = ARM_LDRB;
577 instruction->type = ARM_STRB;
581 if ((p == 0) && (w == 1)) {
583 instruction->type = ARM_LDRT;
585 instruction->type = ARM_STRT;
589 instruction->type = ARM_LDR;
591 instruction->type = ARM_STR;
596 if (!i) { /* #+-<offset_12> */
597 uint32_t offset_12 = (opcode & 0xfff);
599 snprintf(offset, 32, ", #%s0x%" PRIx32 "", (u) ? "" : "-", offset_12);
601 snprintf(offset, 32, "%s", "");
603 instruction->info.load_store.offset_mode = 0;
604 instruction->info.load_store.offset.offset = offset_12;
605 } else {/* either +-<Rm> or +-<Rm>, <shift>, #<shift_imm> */
606 uint8_t shift_imm, shift;
609 shift_imm = (opcode & 0xf80) >> 7;
610 shift = (opcode & 0x60) >> 5;
613 /* LSR encodes a shift by 32 bit as 0x0 */
614 if ((shift == 0x1) && (shift_imm == 0x0))
617 /* ASR encodes a shift by 32 bit as 0x0 */
618 if ((shift == 0x2) && (shift_imm == 0x0))
621 /* ROR by 32 bit is actually a RRX */
622 if ((shift == 0x3) && (shift_imm == 0x0))
625 instruction->info.load_store.offset_mode = 1;
626 instruction->info.load_store.offset.reg.rm = rm;
627 instruction->info.load_store.offset.reg.shift = shift;
628 instruction->info.load_store.offset.reg.shift_imm = shift_imm;
630 if ((shift_imm == 0x0) && (shift == 0x0)) /* +-<Rm> */
631 snprintf(offset, 32, ", %sr%i", (u) ? "" : "-", rm);
632 else { /* +-<Rm>, <Shift>, #<shift_imm> */
635 snprintf(offset, 32, ", %sr%i, LSL #0x%x", (u) ? "" : "-", rm, shift_imm);
638 snprintf(offset, 32, ", %sr%i, LSR #0x%x", (u) ? "" : "-", rm, shift_imm);
641 snprintf(offset, 32, ", %sr%i, ASR #0x%x", (u) ? "" : "-", rm, shift_imm);
644 snprintf(offset, 32, ", %sr%i, ROR #0x%x", (u) ? "" : "-", rm, shift_imm);
647 snprintf(offset, 32, ", %sr%i, RRX", (u) ? "" : "-", rm);
654 if (w == 0) { /* offset */
655 snprintf(instruction->text,
657 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]",
667 instruction->info.load_store.index_mode = 0;
668 } else {/* pre-indexed */
669 snprintf(instruction->text,
671 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]!",
681 instruction->info.load_store.index_mode = 1;
683 } else {/* post-indexed */
684 snprintf(instruction->text,
686 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i]%s",
696 instruction->info.load_store.index_mode = 2;
702 static int evaluate_extend(uint32_t opcode, uint32_t address, char *cp)
704 unsigned rm = (opcode >> 0) & 0xf;
705 unsigned rd = (opcode >> 12) & 0xf;
706 unsigned rn = (opcode >> 16) & 0xf;
709 switch ((opcode >> 24) & 0x3) {
714 sprintf(cp, "UNDEFINED");
715 return ARM_UNDEFINED_INSTRUCTION;
724 switch ((opcode >> 10) & 0x3) {
740 sprintf(cp, "%cXT%s%s\tr%d, r%d%s",
741 (opcode & (1 << 22)) ? 'U' : 'S',
746 sprintf(cp, "%cXTA%s%s\tr%d, r%d, r%d%s",
747 (opcode & (1 << 22)) ? 'U' : 'S',
754 static int evaluate_p_add_sub(uint32_t opcode, uint32_t address, char *cp)
760 switch ((opcode >> 20) & 0x7) {
783 switch ((opcode >> 5) & 0x7) {
812 sprintf(cp, "%s%s%s\tr%d, r%d, r%d", prefix, op, COND(opcode),
813 (int) (opcode >> 12) & 0xf,
814 (int) (opcode >> 16) & 0xf,
815 (int) (opcode >> 0) & 0xf);
819 /* these opcodes might be used someday */
820 sprintf(cp, "UNDEFINED");
821 return ARM_UNDEFINED_INSTRUCTION;
824 /* ARMv6 and later support "media" instructions (includes SIMD) */
825 static int evaluate_media(uint32_t opcode, uint32_t address,
826 struct arm_instruction *instruction)
828 char *cp = instruction->text;
829 char *mnemonic = NULL;
832 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t",
836 /* parallel add/subtract */
837 if ((opcode & 0x01800000) == 0x00000000) {
838 instruction->type = evaluate_p_add_sub(opcode, address, cp);
843 if ((opcode & 0x01f00020) == 0x00800000) {
845 unsigned imm = (unsigned) (opcode >> 7) & 0x1f;
847 if (opcode & (1 << 6)) {
856 sprintf(cp, "PKH%s%s\tr%d, r%d, r%d, %s #%d",
858 (int) (opcode >> 12) & 0xf,
859 (int) (opcode >> 16) & 0xf,
860 (int) (opcode >> 0) & 0xf,
866 if ((opcode & 0x01a00020) == 0x00a00000) {
868 unsigned imm = (unsigned) (opcode >> 7) & 0x1f;
870 if (opcode & (1 << 6)) {
877 sprintf(cp, "%cSAT%s\tr%d, #%d, r%d, %s #%d",
878 (opcode & (1 << 22)) ? 'U' : 'S',
880 (int) (opcode >> 12) & 0xf,
881 (int) (opcode >> 16) & 0x1f,
882 (int) (opcode >> 0) & 0xf,
888 if ((opcode & 0x018000f0) == 0x00800070) {
889 instruction->type = evaluate_extend(opcode, address, cp);
894 if ((opcode & 0x01f00080) == 0x01000000) {
895 unsigned rn = (opcode >> 12) & 0xf;
898 sprintf(cp, "SML%cD%s%s\tr%d, r%d, r%d, r%d",
899 (opcode & (1 << 6)) ? 'S' : 'A',
900 (opcode & (1 << 5)) ? "X" : "",
902 (int) (opcode >> 16) & 0xf,
903 (int) (opcode >> 0) & 0xf,
904 (int) (opcode >> 8) & 0xf,
907 sprintf(cp, "SMU%cD%s%s\tr%d, r%d, r%d",
908 (opcode & (1 << 6)) ? 'S' : 'A',
909 (opcode & (1 << 5)) ? "X" : "",
911 (int) (opcode >> 16) & 0xf,
912 (int) (opcode >> 0) & 0xf,
913 (int) (opcode >> 8) & 0xf);
916 if ((opcode & 0x01f00000) == 0x01400000) {
917 sprintf(cp, "SML%cLD%s%s\tr%d, r%d, r%d, r%d",
918 (opcode & (1 << 6)) ? 'S' : 'A',
919 (opcode & (1 << 5)) ? "X" : "",
921 (int) (opcode >> 12) & 0xf,
922 (int) (opcode >> 16) & 0xf,
923 (int) (opcode >> 0) & 0xf,
924 (int) (opcode >> 8) & 0xf);
927 if ((opcode & 0x01f00000) == 0x01500000) {
928 unsigned rn = (opcode >> 12) & 0xf;
930 switch (opcode & 0xc0) {
942 sprintf(cp, "SMML%c%s%s\tr%d, r%d, r%d, r%d",
943 (opcode & (1 << 6)) ? 'S' : 'A',
944 (opcode & (1 << 5)) ? "R" : "",
946 (int) (opcode >> 16) & 0xf,
947 (int) (opcode >> 0) & 0xf,
948 (int) (opcode >> 8) & 0xf,
951 sprintf(cp, "SMMUL%s%s\tr%d, r%d, r%d",
952 (opcode & (1 << 5)) ? "R" : "",
954 (int) (opcode >> 16) & 0xf,
955 (int) (opcode >> 0) & 0xf,
956 (int) (opcode >> 8) & 0xf);
960 /* simple matches against the remaining decode bits */
961 switch (opcode & 0x01f000f0) {
964 /* parallel halfword saturate */
965 sprintf(cp, "%cSAT16%s\tr%d, #%d, r%d",
966 (opcode & (1 << 22)) ? 'U' : 'S',
968 (int) (opcode >> 12) & 0xf,
969 (int) (opcode >> 16) & 0xf,
970 (int) (opcode >> 0) & 0xf);
983 sprintf(cp, "SEL%s\tr%d, r%d, r%d", COND(opcode),
984 (int) (opcode >> 12) & 0xf,
985 (int) (opcode >> 16) & 0xf,
986 (int) (opcode >> 0) & 0xf);
989 /* unsigned sum of absolute differences */
990 if (((opcode >> 12) & 0xf) == 0xf)
991 sprintf(cp, "USAD8%s\tr%d, r%d, r%d", COND(opcode),
992 (int) (opcode >> 16) & 0xf,
993 (int) (opcode >> 0) & 0xf,
994 (int) (opcode >> 8) & 0xf);
996 sprintf(cp, "USADA8%s\tr%d, r%d, r%d, r%d", COND(opcode),
997 (int) (opcode >> 16) & 0xf,
998 (int) (opcode >> 0) & 0xf,
999 (int) (opcode >> 8) & 0xf,
1000 (int) (opcode >> 12) & 0xf);
1004 unsigned rm = (opcode >> 0) & 0xf;
1005 unsigned rd = (opcode >> 12) & 0xf;
1007 sprintf(cp, "%s%s\tr%d, r%d", mnemonic, COND(opcode), rm, rd);
1012 /* these opcodes might be used someday */
1013 sprintf(cp, "UNDEFINED");
1017 /* Miscellaneous load/store instructions */
1018 static int evaluate_misc_load_store(uint32_t opcode,
1019 uint32_t address, struct arm_instruction *instruction)
1021 uint8_t p, u, i, w, l, s, h;
1023 char *operation;/* "LDR" or "STR" */
1024 char *suffix; /* "H", "SB", "SH", "D" */
1028 p = (opcode & 0x01000000) >> 24;
1029 u = (opcode & 0x00800000) >> 23;
1030 i = (opcode & 0x00400000) >> 22;
1031 w = (opcode & 0x00200000) >> 21;
1032 l = (opcode & 0x00100000) >> 20;
1033 s = (opcode & 0x00000040) >> 6;
1034 h = (opcode & 0x00000020) >> 5;
1036 /* target register */
1037 rd = (opcode & 0xf000) >> 12;
1040 rn = (opcode & 0xf0000) >> 16;
1042 instruction->info.load_store.rd = rd;
1043 instruction->info.load_store.rn = rn;
1044 instruction->info.load_store.u = u;
1046 /* determine instruction type and suffix */
1047 if (s) {/* signed */
1051 instruction->type = ARM_LDRSH;
1055 instruction->type = ARM_LDRSB;
1058 } else {/* there are no signed stores, so this is used to encode double-register
1063 instruction->type = ARM_STRD;
1066 instruction->type = ARM_LDRD;
1069 } else {/* unsigned */
1073 instruction->type = ARM_LDRH;
1076 instruction->type = ARM_STRH;
1080 if (i) {/* Immediate offset/index (#+-<offset_8>)*/
1081 uint32_t offset_8 = ((opcode & 0xf00) >> 4) | (opcode & 0xf);
1082 snprintf(offset, 32, "#%s0x%" PRIx32 "", (u) ? "" : "-", offset_8);
1084 instruction->info.load_store.offset_mode = 0;
1085 instruction->info.load_store.offset.offset = offset_8;
1086 } else {/* Register offset/index (+-<Rm>) */
1088 rm = (opcode & 0xf);
1089 snprintf(offset, 32, "%sr%i", (u) ? "" : "-", rm);
1091 instruction->info.load_store.offset_mode = 1;
1092 instruction->info.load_store.offset.reg.rm = rm;
1093 instruction->info.load_store.offset.reg.shift = 0x0;
1094 instruction->info.load_store.offset.reg.shift_imm = 0x0;
1098 if (w == 0) { /* offset */
1099 snprintf(instruction->text,
1101 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]",
1111 instruction->info.load_store.index_mode = 0;
1112 } else {/* pre-indexed */
1113 snprintf(instruction->text,
1115 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]!",
1125 instruction->info.load_store.index_mode = 1;
1127 } else {/* post-indexed */
1128 snprintf(instruction->text,
1130 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i], %s",
1140 instruction->info.load_store.index_mode = 2;
1146 /* Load/store multiples instructions */
1147 static int evaluate_ldm_stm(uint32_t opcode,
1148 uint32_t address, struct arm_instruction *instruction)
1150 uint8_t p, u, s, w, l, rn;
1151 uint32_t register_list;
1152 char *addressing_mode;
1159 p = (opcode & 0x01000000) >> 24;
1160 u = (opcode & 0x00800000) >> 23;
1161 s = (opcode & 0x00400000) >> 22;
1162 w = (opcode & 0x00200000) >> 21;
1163 l = (opcode & 0x00100000) >> 20;
1164 register_list = (opcode & 0xffff);
1165 rn = (opcode & 0xf0000) >> 16;
1167 instruction->info.load_store_multiple.rn = rn;
1168 instruction->info.load_store_multiple.register_list = register_list;
1169 instruction->info.load_store_multiple.s = s;
1170 instruction->info.load_store_multiple.w = w;
1173 instruction->type = ARM_LDM;
1176 instruction->type = ARM_STM;
1182 instruction->info.load_store_multiple.addressing_mode = 1;
1183 addressing_mode = "IB";
1185 instruction->info.load_store_multiple.addressing_mode = 3;
1186 addressing_mode = "DB";
1190 instruction->info.load_store_multiple.addressing_mode = 0;
1191 /* "IA" is the default in UAL syntax */
1192 addressing_mode = "";
1194 instruction->info.load_store_multiple.addressing_mode = 2;
1195 addressing_mode = "DA";
1199 reg_list_p = reg_list;
1200 for (i = 0; i <= 15; i++) {
1201 if ((register_list >> i) & 1) {
1204 reg_list_p += snprintf(reg_list_p,
1205 (reg_list + 69 - reg_list_p),
1209 reg_list_p += snprintf(reg_list_p,
1210 (reg_list + 69 - reg_list_p),
1216 snprintf(instruction->text, 128,
1217 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
1218 "\t%s%s%s r%i%s, {%s}%s",
1220 mnemonic, addressing_mode, COND(opcode),
1221 rn, (w) ? "!" : "", reg_list, (s) ? "^" : "");
1226 /* Multiplies, extra load/stores */
1227 static int evaluate_mul_and_extra_ld_st(uint32_t opcode,
1228 uint32_t address, struct arm_instruction *instruction)
1230 /* Multiply (accumulate) (long) and Swap/swap byte */
1231 if ((opcode & 0x000000f0) == 0x00000090) {
1232 /* Multiply (accumulate) */
1233 if ((opcode & 0x0f800000) == 0x00000000) {
1234 uint8_t rm, rs, rn, rd, s;
1236 rs = (opcode & 0xf00) >> 8;
1237 rn = (opcode & 0xf000) >> 12;
1238 rd = (opcode & 0xf0000) >> 16;
1239 s = (opcode & 0x00100000) >> 20;
1241 /* examine A bit (accumulate) */
1242 if (opcode & 0x00200000) {
1243 instruction->type = ARM_MLA;
1244 snprintf(instruction->text,
1246 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMLA%s%s r%i, r%i, r%i, r%i",
1256 instruction->type = ARM_MUL;
1257 snprintf(instruction->text,
1259 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMUL%s%s r%i, r%i, r%i",
1272 /* Multiply (accumulate) long */
1273 if ((opcode & 0x0f800000) == 0x00800000) {
1274 char *mnemonic = NULL;
1275 uint8_t rm, rs, rd_hi, rd_low, s;
1277 rs = (opcode & 0xf00) >> 8;
1278 rd_hi = (opcode & 0xf000) >> 12;
1279 rd_low = (opcode & 0xf0000) >> 16;
1280 s = (opcode & 0x00100000) >> 20;
1282 switch ((opcode & 0x00600000) >> 21) {
1284 instruction->type = ARM_UMULL;
1288 instruction->type = ARM_UMLAL;
1292 instruction->type = ARM_SMULL;
1296 instruction->type = ARM_SMLAL;
1301 snprintf(instruction->text,
1303 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, r%i, r%i",
1317 /* Swap/swap byte */
1318 if ((opcode & 0x0f800000) == 0x01000000) {
1321 rd = (opcode & 0xf000) >> 12;
1322 rn = (opcode & 0xf0000) >> 16;
1324 /* examine B flag */
1325 instruction->type = (opcode & 0x00400000) ? ARM_SWPB : ARM_SWP;
1327 snprintf(instruction->text,
1329 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, [r%i]",
1332 (opcode & 0x00400000) ? "SWPB" : "SWP",
1342 return evaluate_misc_load_store(opcode, address, instruction);
1345 static int evaluate_mrs_msr(uint32_t opcode,
1346 uint32_t address, struct arm_instruction *instruction)
1348 int r = (opcode & 0x00400000) >> 22;
1349 char *PSR = (r) ? "SPSR" : "CPSR";
1351 /* Move register to status register (MSR) */
1352 if (opcode & 0x00200000) {
1353 instruction->type = ARM_MSR;
1355 /* immediate variant */
1356 if (opcode & 0x02000000) {
1357 uint8_t immediate = (opcode & 0xff);
1358 uint8_t rotate = (opcode & 0xf00);
1360 snprintf(instruction->text,
1362 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, 0x%8.8" PRIx32,
1367 (opcode & 0x10000) ? "c" : "",
1368 (opcode & 0x20000) ? "x" : "",
1369 (opcode & 0x40000) ? "s" : "",
1370 (opcode & 0x80000) ? "f" : "",
1371 ror(immediate, (rotate * 2))
1373 } else {/* register variant */
1374 uint8_t rm = opcode & 0xf;
1375 snprintf(instruction->text,
1377 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, r%i",
1382 (opcode & 0x10000) ? "c" : "",
1383 (opcode & 0x20000) ? "x" : "",
1384 (opcode & 0x40000) ? "s" : "",
1385 (opcode & 0x80000) ? "f" : "",
1390 } else {/* Move status register to register (MRS) */
1393 instruction->type = ARM_MRS;
1394 rd = (opcode & 0x0000f000) >> 12;
1396 snprintf(instruction->text,
1398 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMRS%s r%i, %s",
1409 /* Miscellaneous instructions */
1410 static int evaluate_misc_instr(uint32_t opcode,
1411 uint32_t address, struct arm_instruction *instruction)
1414 if ((opcode & 0x000000f0) == 0x00000000)
1415 evaluate_mrs_msr(opcode, address, instruction);
1418 if ((opcode & 0x006000f0) == 0x00200010) {
1420 instruction->type = ARM_BX;
1423 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBX%s r%i",
1424 address, opcode, COND(opcode), rm);
1426 instruction->info.b_bl_bx_blx.reg_operand = rm;
1427 instruction->info.b_bl_bx_blx.target_address = -1;
1430 /* BXJ - "Jazelle" support (ARMv5-J) */
1431 if ((opcode & 0x006000f0) == 0x00200020) {
1433 instruction->type = ARM_BX;
1436 snprintf(instruction->text, 128,
1437 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBXJ%s r%i",
1438 address, opcode, COND(opcode), rm);
1440 instruction->info.b_bl_bx_blx.reg_operand = rm;
1441 instruction->info.b_bl_bx_blx.target_address = -1;
1445 if ((opcode & 0x006000f0) == 0x00600010) {
1447 instruction->type = ARM_CLZ;
1449 rd = (opcode & 0xf000) >> 12;
1451 snprintf(instruction->text,
1453 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCLZ%s r%i, r%i",
1462 if ((opcode & 0x006000f0) == 0x00200030) {
1464 instruction->type = ARM_BLX;
1467 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX%s r%i",
1468 address, opcode, COND(opcode), rm);
1470 instruction->info.b_bl_bx_blx.reg_operand = rm;
1471 instruction->info.b_bl_bx_blx.target_address = -1;
1474 /* Enhanced DSP add/subtracts */
1475 if ((opcode & 0x0000000f0) == 0x00000050) {
1477 char *mnemonic = NULL;
1479 rd = (opcode & 0xf000) >> 12;
1480 rn = (opcode & 0xf0000) >> 16;
1482 switch ((opcode & 0x00600000) >> 21) {
1484 instruction->type = ARM_QADD;
1488 instruction->type = ARM_QSUB;
1492 instruction->type = ARM_QDADD;
1496 instruction->type = ARM_QDSUB;
1501 snprintf(instruction->text,
1503 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, r%i",
1513 /* exception return */
1514 if ((opcode & 0x0000000f0) == 0x00000060) {
1515 if (((opcode & 0x600000) >> 21) == 3)
1516 instruction->type = ARM_ERET;
1517 snprintf(instruction->text,
1519 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tERET",
1524 /* exception generate instructions */
1525 if ((opcode & 0x0000000f0) == 0x00000070) {
1526 uint32_t immediate = 0;
1527 char *mnemonic = NULL;
1529 switch ((opcode & 0x600000) >> 21) {
1531 instruction->type = ARM_BKPT;
1533 immediate = ((opcode & 0x000fff00) >> 4) | (opcode & 0xf);
1536 instruction->type = ARM_HVC;
1538 immediate = ((opcode & 0x000fff00) >> 4) | (opcode & 0xf);
1541 instruction->type = ARM_SMC;
1543 immediate = (opcode & 0xf);
1547 snprintf(instruction->text,
1549 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s 0x%4.4" PRIx32 "",
1556 /* Enhanced DSP multiplies */
1557 if ((opcode & 0x000000090) == 0x00000080) {
1558 int x = (opcode & 0x20) >> 5;
1559 int y = (opcode & 0x40) >> 6;
1562 if ((opcode & 0x00600000) == 0x00000000) {
1563 uint8_t rd, rm, rs, rn;
1564 instruction->type = ARM_SMLAXY;
1565 rd = (opcode & 0xf0000) >> 16;
1566 rm = (opcode & 0xf);
1567 rs = (opcode & 0xf00) >> 8;
1568 rn = (opcode & 0xf000) >> 12;
1570 snprintf(instruction->text,
1572 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
1585 if ((opcode & 0x00600000) == 0x00400000) {
1586 uint8_t rd_low, rd_hi, rm, rs;
1587 instruction->type = ARM_SMLAXY;
1588 rd_hi = (opcode & 0xf0000) >> 16;
1589 rd_low = (opcode & 0xf000) >> 12;
1590 rm = (opcode & 0xf);
1591 rs = (opcode & 0xf00) >> 8;
1593 snprintf(instruction->text,
1595 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
1608 if (((opcode & 0x00600000) == 0x00200000) && (x == 0)) {
1609 uint8_t rd, rm, rs, rn;
1610 instruction->type = ARM_SMLAWY;
1611 rd = (opcode & 0xf0000) >> 16;
1612 rm = (opcode & 0xf);
1613 rs = (opcode & 0xf00) >> 8;
1614 rn = (opcode & 0xf000) >> 12;
1616 snprintf(instruction->text,
1618 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLAW%s%s r%i, r%i, r%i, r%i",
1630 if ((opcode & 0x00600000) == 0x00600000) {
1632 instruction->type = ARM_SMULXY;
1633 rd = (opcode & 0xf0000) >> 16;
1634 rm = (opcode & 0xf);
1635 rs = (opcode & 0xf00) >> 8;
1637 snprintf(instruction->text,
1639 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s%s r%i, r%i, r%i",
1651 if (((opcode & 0x00600000) == 0x00200000) && (x == 1)) {
1653 instruction->type = ARM_SMULWY;
1654 rd = (opcode & 0xf0000) >> 16;
1655 rm = (opcode & 0xf);
1656 rs = (opcode & 0xf00) >> 8;
1658 snprintf(instruction->text,
1660 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s r%i, r%i, r%i",
1674 static int evaluate_mov_imm(uint32_t opcode,
1675 uint32_t address, struct arm_instruction *instruction)
1681 rd = (opcode & 0xf000) >> 12;
1682 t = opcode & 0x00400000;
1683 immediate = (opcode & 0xf0000) >> 4 | (opcode & 0xfff);
1685 instruction->type = ARM_MOV;
1686 instruction->info.data_proc.rd = rd;
1688 snprintf(instruction->text,
1690 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMOV%s%s r%i, #0x%" PRIx16,
1701 static int evaluate_data_proc(uint32_t opcode,
1702 uint32_t address, struct arm_instruction *instruction)
1704 uint8_t i, op, s, rn, rd;
1705 char *mnemonic = NULL;
1706 char shifter_operand[32];
1708 i = (opcode & 0x02000000) >> 25;
1709 op = (opcode & 0x01e00000) >> 21;
1710 s = (opcode & 0x00100000) >> 20;
1712 rd = (opcode & 0xf000) >> 12;
1713 rn = (opcode & 0xf0000) >> 16;
1715 instruction->info.data_proc.rd = rd;
1716 instruction->info.data_proc.rn = rn;
1717 instruction->info.data_proc.s = s;
1721 instruction->type = ARM_AND;
1725 instruction->type = ARM_EOR;
1729 instruction->type = ARM_SUB;
1733 instruction->type = ARM_RSB;
1737 instruction->type = ARM_ADD;
1741 instruction->type = ARM_ADC;
1745 instruction->type = ARM_SBC;
1749 instruction->type = ARM_RSC;
1753 instruction->type = ARM_TST;
1757 instruction->type = ARM_TEQ;
1761 instruction->type = ARM_CMP;
1765 instruction->type = ARM_CMN;
1769 instruction->type = ARM_ORR;
1773 instruction->type = ARM_MOV;
1777 instruction->type = ARM_BIC;
1781 instruction->type = ARM_MVN;
1786 if (i) {/* immediate shifter operand (#<immediate>)*/
1787 uint8_t immed_8 = opcode & 0xff;
1788 uint8_t rotate_imm = (opcode & 0xf00) >> 8;
1791 immediate = ror(immed_8, rotate_imm * 2);
1793 snprintf(shifter_operand, 32, "#0x%" PRIx32 "", immediate);
1795 instruction->info.data_proc.variant = 0;
1796 instruction->info.data_proc.shifter_operand.immediate.immediate = immediate;
1797 } else {/* register-based shifter operand */
1799 shift = (opcode & 0x60) >> 5;
1800 rm = (opcode & 0xf);
1802 if ((opcode & 0x10) != 0x10) { /* Immediate shifts ("<Rm>" or "<Rm>, <shift>
1803 *#<shift_immediate>") */
1805 shift_imm = (opcode & 0xf80) >> 7;
1807 instruction->info.data_proc.variant = 1;
1808 instruction->info.data_proc.shifter_operand.immediate_shift.rm = rm;
1809 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm =
1811 instruction->info.data_proc.shifter_operand.immediate_shift.shift = shift;
1813 /* LSR encodes a shift by 32 bit as 0x0 */
1814 if ((shift == 0x1) && (shift_imm == 0x0))
1817 /* ASR encodes a shift by 32 bit as 0x0 */
1818 if ((shift == 0x2) && (shift_imm == 0x0))
1821 /* ROR by 32 bit is actually a RRX */
1822 if ((shift == 0x3) && (shift_imm == 0x0))
1825 if ((shift_imm == 0x0) && (shift == 0x0))
1826 snprintf(shifter_operand, 32, "r%i", rm);
1828 if (shift == 0x0) /* LSL */
1829 snprintf(shifter_operand,
1834 else if (shift == 0x1) /* LSR */
1835 snprintf(shifter_operand,
1840 else if (shift == 0x2) /* ASR */
1841 snprintf(shifter_operand,
1846 else if (shift == 0x3) /* ROR */
1847 snprintf(shifter_operand,
1852 else if (shift == 0x4) /* RRX */
1853 snprintf(shifter_operand, 32, "r%i, RRX", rm);
1855 } else {/* Register shifts ("<Rm>, <shift> <Rs>") */
1856 uint8_t rs = (opcode & 0xf00) >> 8;
1858 instruction->info.data_proc.variant = 2;
1859 instruction->info.data_proc.shifter_operand.register_shift.rm = rm;
1860 instruction->info.data_proc.shifter_operand.register_shift.rs = rs;
1861 instruction->info.data_proc.shifter_operand.register_shift.shift = shift;
1863 if (shift == 0x0) /* LSL */
1864 snprintf(shifter_operand, 32, "r%i, LSL r%i", rm, rs);
1865 else if (shift == 0x1) /* LSR */
1866 snprintf(shifter_operand, 32, "r%i, LSR r%i", rm, rs);
1867 else if (shift == 0x2) /* ASR */
1868 snprintf(shifter_operand, 32, "r%i, ASR r%i", rm, rs);
1869 else if (shift == 0x3) /* ROR */
1870 snprintf(shifter_operand, 32, "r%i, ROR r%i", rm, rs);
1874 if ((op < 0x8) || (op == 0xc) || (op == 0xe)) { /* <opcode3>{<cond>}{S} <Rd>, <Rn>,
1875 *<shifter_operand> */
1876 snprintf(instruction->text,
1878 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, %s",
1887 } else if ((op == 0xd) || (op == 0xf)) { /* <opcode1>{<cond>}{S} <Rd>,
1888 *<shifter_operand> */
1889 if (opcode == 0xe1a00000) /* print MOV r0,r0 as NOP */
1890 snprintf(instruction->text,
1892 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tNOP",
1896 snprintf(instruction->text,
1898 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, %s",
1906 } else {/* <opcode2>{<cond>} <Rn>, <shifter_operand> */
1907 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, %s",
1908 address, opcode, mnemonic, COND(opcode),
1909 rn, shifter_operand);
1915 int arm_evaluate_opcode(uint32_t opcode, uint32_t address,
1916 struct arm_instruction *instruction)
1918 /* clear fields, to avoid confusion */
1919 memset(instruction, 0, sizeof(struct arm_instruction));
1920 instruction->opcode = opcode;
1921 instruction->instruction_size = 4;
1923 /* catch opcodes with condition field [31:28] = b1111 */
1924 if ((opcode & 0xf0000000) == 0xf0000000) {
1925 /* Undefined instruction (or ARMv5E cache preload PLD) */
1926 if ((opcode & 0x08000000) == 0x00000000)
1927 return evaluate_pld(opcode, address, instruction);
1929 /* Undefined instruction (or ARMv6+ SRS/RFE) */
1930 if ((opcode & 0x0e000000) == 0x08000000)
1931 return evaluate_srs(opcode, address, instruction);
1933 /* Branch and branch with link and change to Thumb */
1934 if ((opcode & 0x0e000000) == 0x0a000000)
1935 return evaluate_blx_imm(opcode, address, instruction);
1937 /* Extended coprocessor opcode space (ARMv5 and higher)
1938 * Coprocessor load/store and double register transfers */
1939 if ((opcode & 0x0e000000) == 0x0c000000)
1940 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1942 /* Coprocessor data processing */
1943 if ((opcode & 0x0f000100) == 0x0c000000)
1944 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1946 /* Coprocessor register transfers */
1947 if ((opcode & 0x0f000010) == 0x0c000010)
1948 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1950 /* Undefined instruction */
1951 if ((opcode & 0x0f000000) == 0x0f000000) {
1952 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1953 snprintf(instruction->text,
1955 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
1962 /* catch opcodes with [27:25] = b000 */
1963 if ((opcode & 0x0e000000) == 0x00000000) {
1964 /* Multiplies, extra load/stores */
1965 if ((opcode & 0x00000090) == 0x00000090)
1966 return evaluate_mul_and_extra_ld_st(opcode, address, instruction);
1968 /* Miscellaneous instructions */
1969 if ((opcode & 0x0f900000) == 0x01000000)
1970 return evaluate_misc_instr(opcode, address, instruction);
1972 return evaluate_data_proc(opcode, address, instruction);
1975 /* catch opcodes with [27:25] = b001 */
1976 if ((opcode & 0x0e000000) == 0x02000000) {
1977 /* 16-bit immediate load */
1978 if ((opcode & 0x0fb00000) == 0x03000000)
1979 return evaluate_mov_imm(opcode, address, instruction);
1981 /* Move immediate to status register */
1982 if ((opcode & 0x0fb00000) == 0x03200000)
1983 return evaluate_mrs_msr(opcode, address, instruction);
1985 return evaluate_data_proc(opcode, address, instruction);
1989 /* catch opcodes with [27:25] = b010 */
1990 if ((opcode & 0x0e000000) == 0x04000000) {
1991 /* Load/store immediate offset */
1992 return evaluate_load_store(opcode, address, instruction);
1995 /* catch opcodes with [27:25] = b011 */
1996 if ((opcode & 0x0e000000) == 0x06000000) {
1997 /* Load/store register offset */
1998 if ((opcode & 0x00000010) == 0x00000000)
1999 return evaluate_load_store(opcode, address, instruction);
2001 /* Architecturally Undefined instruction
2002 * ... don't expect these to ever be used
2004 if ((opcode & 0x07f000f0) == 0x07f000f0) {
2005 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2006 snprintf(instruction->text, 128,
2007 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEF",
2012 /* "media" instructions */
2013 return evaluate_media(opcode, address, instruction);
2016 /* catch opcodes with [27:25] = b100 */
2017 if ((opcode & 0x0e000000) == 0x08000000) {
2018 /* Load/store multiple */
2019 return evaluate_ldm_stm(opcode, address, instruction);
2022 /* catch opcodes with [27:25] = b101 */
2023 if ((opcode & 0x0e000000) == 0x0a000000) {
2024 /* Branch and branch with link */
2025 return evaluate_b_bl(opcode, address, instruction);
2028 /* catch opcodes with [27:25] = b110 */
2029 if ((opcode & 0x0e000000) == 0x0c000000) {
2030 /* Coprocessor load/store and double register transfers */
2031 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
2034 /* catch opcodes with [27:25] = b111 */
2035 if ((opcode & 0x0e000000) == 0x0e000000) {
2036 /* Software interrupt */
2037 if ((opcode & 0x0f000000) == 0x0f000000)
2038 return evaluate_swi(opcode, address, instruction);
2040 /* Coprocessor data processing */
2041 if ((opcode & 0x0f000010) == 0x0e000000)
2042 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
2044 /* Coprocessor register transfers */
2045 if ((opcode & 0x0f000010) == 0x0e000010)
2046 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
2049 LOG_ERROR("ARM: should never reach this point (opcode=%08x)",
2054 static int evaluate_b_bl_blx_thumb(uint16_t opcode,
2055 uint32_t address, struct arm_instruction *instruction)
2057 uint32_t offset = opcode & 0x7ff;
2058 uint32_t opc = (opcode >> 11) & 0x3;
2059 uint32_t target_address;
2060 char *mnemonic = NULL;
2062 /* sign extend 11-bit offset */
2063 if (((opc == 0) || (opc == 2)) && (offset & 0x00000400))
2064 offset = 0xfffff800 | offset;
2066 target_address = address + 4 + (offset << 1);
2069 /* unconditional branch */
2071 instruction->type = ARM_B;
2076 instruction->type = ARM_BLX;
2078 target_address &= 0xfffffffc;
2082 instruction->type = ARM_UNKNOWN_INSTRUCTION;
2083 mnemonic = "prefix";
2084 target_address = offset << 12;
2088 instruction->type = ARM_BL;
2093 /* TODO: deal correctly with dual opcode (prefixed) BL/BLX;
2094 * these are effectively 32-bit instructions even in Thumb1. For
2095 * disassembly, it's simplest to always use the Thumb2 decoder.
2097 * But some cores will evidently handle them as two instructions,
2098 * where exceptions may occur between the two. The ETMv3.2+ ID
2099 * register has a bit which exposes this behavior.
2102 snprintf(instruction->text, 128,
2103 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%#8.8" PRIx32,
2104 address, opcode, mnemonic, target_address);
2106 instruction->info.b_bl_bx_blx.reg_operand = -1;
2107 instruction->info.b_bl_bx_blx.target_address = target_address;
2112 static int evaluate_add_sub_thumb(uint16_t opcode,
2113 uint32_t address, struct arm_instruction *instruction)
2115 uint8_t rd = (opcode >> 0) & 0x7;
2116 uint8_t rn = (opcode >> 3) & 0x7;
2117 uint8_t rm_imm = (opcode >> 6) & 0x7;
2118 uint32_t opc = opcode & (1 << 9);
2119 uint32_t reg_imm = opcode & (1 << 10);
2123 instruction->type = ARM_SUB;
2126 /* REVISIT: if reg_imm == 0, display as "MOVS" */
2127 instruction->type = ARM_ADD;
2131 instruction->info.data_proc.rd = rd;
2132 instruction->info.data_proc.rn = rn;
2133 instruction->info.data_proc.s = 1;
2136 instruction->info.data_proc.variant = 0;/*immediate*/
2137 instruction->info.data_proc.shifter_operand.immediate.immediate = rm_imm;
2138 snprintf(instruction->text, 128,
2139 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%d",
2140 address, opcode, mnemonic, rd, rn, rm_imm);
2142 instruction->info.data_proc.variant = 1;/*immediate shift*/
2143 instruction->info.data_proc.shifter_operand.immediate_shift.rm = rm_imm;
2144 snprintf(instruction->text, 128,
2145 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, r%i",
2146 address, opcode, mnemonic, rd, rn, rm_imm);
2152 static int evaluate_shift_imm_thumb(uint16_t opcode,
2153 uint32_t address, struct arm_instruction *instruction)
2155 uint8_t rd = (opcode >> 0) & 0x7;
2156 uint8_t rm = (opcode >> 3) & 0x7;
2157 uint8_t imm = (opcode >> 6) & 0x1f;
2158 uint8_t opc = (opcode >> 11) & 0x3;
2159 char *mnemonic = NULL;
2163 instruction->type = ARM_MOV;
2165 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 0;
2168 instruction->type = ARM_MOV;
2170 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 1;
2173 instruction->type = ARM_MOV;
2175 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 2;
2179 if ((imm == 0) && (opc != 0))
2182 instruction->info.data_proc.rd = rd;
2183 instruction->info.data_proc.rn = -1;
2184 instruction->info.data_proc.s = 1;
2186 instruction->info.data_proc.variant = 1;/*immediate_shift*/
2187 instruction->info.data_proc.shifter_operand.immediate_shift.rm = rm;
2188 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = imm;
2190 snprintf(instruction->text, 128,
2191 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%#2.2x",
2192 address, opcode, mnemonic, rd, rm, imm);
2197 static int evaluate_data_proc_imm_thumb(uint16_t opcode,
2198 uint32_t address, struct arm_instruction *instruction)
2200 uint8_t imm = opcode & 0xff;
2201 uint8_t rd = (opcode >> 8) & 0x7;
2202 uint32_t opc = (opcode >> 11) & 0x3;
2203 char *mnemonic = NULL;
2205 instruction->info.data_proc.rd = rd;
2206 instruction->info.data_proc.rn = rd;
2207 instruction->info.data_proc.s = 1;
2208 instruction->info.data_proc.variant = 0;/*immediate*/
2209 instruction->info.data_proc.shifter_operand.immediate.immediate = imm;
2213 instruction->type = ARM_MOV;
2215 instruction->info.data_proc.rn = -1;
2218 instruction->type = ARM_CMP;
2220 instruction->info.data_proc.rd = -1;
2223 instruction->type = ARM_ADD;
2227 instruction->type = ARM_SUB;
2232 snprintf(instruction->text, 128,
2233 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, #%#2.2x",
2234 address, opcode, mnemonic, rd, imm);
2239 static int evaluate_data_proc_thumb(uint16_t opcode,
2240 uint32_t address, struct arm_instruction *instruction)
2242 uint8_t high_reg, op, rm, rd, h1, h2;
2243 char *mnemonic = NULL;
2246 high_reg = (opcode & 0x0400) >> 10;
2247 op = (opcode & 0x03C0) >> 6;
2249 rd = (opcode & 0x0007);
2250 rm = (opcode & 0x0038) >> 3;
2251 h1 = (opcode & 0x0080) >> 7;
2252 h2 = (opcode & 0x0040) >> 6;
2254 instruction->info.data_proc.rd = rd;
2255 instruction->info.data_proc.rn = rd;
2256 instruction->info.data_proc.s = (!high_reg || (instruction->type == ARM_CMP));
2257 instruction->info.data_proc.variant = 1 /*immediate shift*/;
2258 instruction->info.data_proc.shifter_operand.immediate_shift.rm = rm;
2267 instruction->type = ARM_ADD;
2271 instruction->type = ARM_CMP;
2275 instruction->type = ARM_MOV;
2281 if ((opcode & 0x7) == 0x0) {
2282 instruction->info.b_bl_bx_blx.reg_operand = rm;
2284 instruction->type = ARM_BLX;
2285 snprintf(instruction->text, 128,
2287 " 0x%4.4x \tBLX\tr%i",
2288 address, opcode, rm);
2290 instruction->type = ARM_BX;
2291 snprintf(instruction->text, 128,
2293 " 0x%4.4x \tBX\tr%i",
2294 address, opcode, rm);
2297 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2298 snprintf(instruction->text, 128,
2301 "UNDEFINED INSTRUCTION",
2309 instruction->type = ARM_AND;
2313 instruction->type = ARM_EOR;
2317 instruction->type = ARM_MOV;
2319 instruction->info.data_proc.variant = 2 /*register shift*/;
2320 instruction->info.data_proc.shifter_operand.register_shift.shift = 0;
2321 instruction->info.data_proc.shifter_operand.register_shift.rm = rd;
2322 instruction->info.data_proc.shifter_operand.register_shift.rs = rm;
2325 instruction->type = ARM_MOV;
2327 instruction->info.data_proc.variant = 2 /*register shift*/;
2328 instruction->info.data_proc.shifter_operand.register_shift.shift = 1;
2329 instruction->info.data_proc.shifter_operand.register_shift.rm = rd;
2330 instruction->info.data_proc.shifter_operand.register_shift.rs = rm;
2333 instruction->type = ARM_MOV;
2335 instruction->info.data_proc.variant = 2 /*register shift*/;
2336 instruction->info.data_proc.shifter_operand.register_shift.shift = 2;
2337 instruction->info.data_proc.shifter_operand.register_shift.rm = rd;
2338 instruction->info.data_proc.shifter_operand.register_shift.rs = rm;
2341 instruction->type = ARM_ADC;
2345 instruction->type = ARM_SBC;
2349 instruction->type = ARM_MOV;
2351 instruction->info.data_proc.variant = 2 /*register shift*/;
2352 instruction->info.data_proc.shifter_operand.register_shift.shift = 3;
2353 instruction->info.data_proc.shifter_operand.register_shift.rm = rd;
2354 instruction->info.data_proc.shifter_operand.register_shift.rs = rm;
2357 instruction->type = ARM_TST;
2361 instruction->type = ARM_RSB;
2363 instruction->info.data_proc.variant = 0 /*immediate*/;
2364 instruction->info.data_proc.shifter_operand.immediate.immediate = 0;
2365 instruction->info.data_proc.rn = rm;
2368 instruction->type = ARM_CMP;
2372 instruction->type = ARM_CMN;
2376 instruction->type = ARM_ORR;
2380 instruction->type = ARM_MUL;
2384 instruction->type = ARM_BIC;
2388 instruction->type = ARM_MVN;
2395 snprintf(instruction->text, 128,
2396 "0x%8.8" PRIx32 " 0x%4.4x \tNOP\t\t\t"
2398 address, opcode, mnemonic, rd, rm);
2400 snprintf(instruction->text, 128,
2401 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i",
2402 address, opcode, mnemonic, rd, rm);
2407 /* PC-relative data addressing is word-aligned even with Thumb */
2408 static inline uint32_t thumb_alignpc4(uint32_t addr)
2410 return (addr + 4) & ~3;
2413 static int evaluate_load_literal_thumb(uint16_t opcode,
2414 uint32_t address, struct arm_instruction *instruction)
2417 uint8_t rd = (opcode >> 8) & 0x7;
2419 instruction->type = ARM_LDR;
2420 immediate = opcode & 0x000000ff;
2423 instruction->info.load_store.rd = rd;
2424 instruction->info.load_store.rn = 15 /*PC*/;
2425 instruction->info.load_store.index_mode = 0; /*offset*/
2426 instruction->info.load_store.offset_mode = 0; /*immediate*/
2427 instruction->info.load_store.offset.offset = immediate;
2429 snprintf(instruction->text, 128,
2430 "0x%8.8" PRIx32 " 0x%4.4x \t"
2431 "LDR\tr%i, [pc, #%#" PRIx32 "]\t; %#8.8" PRIx32,
2432 address, opcode, rd, immediate,
2433 thumb_alignpc4(address) + immediate);
2438 static int evaluate_load_store_reg_thumb(uint16_t opcode,
2439 uint32_t address, struct arm_instruction *instruction)
2441 uint8_t rd = (opcode >> 0) & 0x7;
2442 uint8_t rn = (opcode >> 3) & 0x7;
2443 uint8_t rm = (opcode >> 6) & 0x7;
2444 uint8_t opc = (opcode >> 9) & 0x7;
2445 char *mnemonic = NULL;
2449 instruction->type = ARM_STR;
2453 instruction->type = ARM_STRH;
2457 instruction->type = ARM_STRB;
2461 instruction->type = ARM_LDRSB;
2465 instruction->type = ARM_LDR;
2469 instruction->type = ARM_LDRH;
2473 instruction->type = ARM_LDRB;
2477 instruction->type = ARM_LDRSH;
2482 snprintf(instruction->text, 128,
2483 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [r%i, r%i]",
2484 address, opcode, mnemonic, rd, rn, rm);
2486 instruction->info.load_store.rd = rd;
2487 instruction->info.load_store.rn = rn;
2488 instruction->info.load_store.index_mode = 0; /*offset*/
2489 instruction->info.load_store.offset_mode = 1; /*register*/
2490 instruction->info.load_store.offset.reg.rm = rm;
2495 static int evaluate_load_store_imm_thumb(uint16_t opcode,
2496 uint32_t address, struct arm_instruction *instruction)
2498 uint32_t offset = (opcode >> 6) & 0x1f;
2499 uint8_t rd = (opcode >> 0) & 0x7;
2500 uint8_t rn = (opcode >> 3) & 0x7;
2501 uint32_t l = opcode & (1 << 11);
2502 uint32_t b = opcode & (1 << 12);
2508 instruction->type = ARM_LDR;
2511 instruction->type = ARM_STR;
2515 if ((opcode&0xF000) == 0x8000) {
2523 snprintf(instruction->text, 128,
2524 "0x%8.8" PRIx32 " 0x%4.4x \t%s%c\tr%i, [r%i, #%#" PRIx32 "]",
2525 address, opcode, mnemonic, suffix, rd, rn, offset << shift);
2527 instruction->info.load_store.rd = rd;
2528 instruction->info.load_store.rn = rn;
2529 instruction->info.load_store.index_mode = 0; /*offset*/
2530 instruction->info.load_store.offset_mode = 0; /*immediate*/
2531 instruction->info.load_store.offset.offset = offset << shift;
2536 static int evaluate_load_store_stack_thumb(uint16_t opcode,
2537 uint32_t address, struct arm_instruction *instruction)
2539 uint32_t offset = opcode & 0xff;
2540 uint8_t rd = (opcode >> 8) & 0x7;
2541 uint32_t l = opcode & (1 << 11);
2545 instruction->type = ARM_LDR;
2548 instruction->type = ARM_STR;
2552 snprintf(instruction->text, 128,
2553 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [SP, #%#" PRIx32 "]",
2554 address, opcode, mnemonic, rd, offset*4);
2556 instruction->info.load_store.rd = rd;
2557 instruction->info.load_store.rn = 13 /*SP*/;
2558 instruction->info.load_store.index_mode = 0; /*offset*/
2559 instruction->info.load_store.offset_mode = 0; /*immediate*/
2560 instruction->info.load_store.offset.offset = offset*4;
2565 static int evaluate_add_sp_pc_thumb(uint16_t opcode,
2566 uint32_t address, struct arm_instruction *instruction)
2568 uint32_t imm = opcode & 0xff;
2569 uint8_t rd = (opcode >> 8) & 0x7;
2571 uint32_t sp = opcode & (1 << 11);
2572 const char *reg_name;
2574 instruction->type = ARM_ADD;
2584 snprintf(instruction->text, 128,
2585 "0x%8.8" PRIx32 " 0x%4.4x \tADD\tr%i, %s, #%#" PRIx32,
2586 address, opcode, rd, reg_name, imm * 4);
2588 instruction->info.data_proc.variant = 0 /* immediate */;
2589 instruction->info.data_proc.rd = rd;
2590 instruction->info.data_proc.rn = rn;
2591 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
2596 static int evaluate_adjust_stack_thumb(uint16_t opcode,
2597 uint32_t address, struct arm_instruction *instruction)
2599 uint32_t imm = opcode & 0x7f;
2600 uint8_t opc = opcode & (1 << 7);
2605 instruction->type = ARM_SUB;
2608 instruction->type = ARM_ADD;
2612 snprintf(instruction->text, 128,
2613 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tSP, #%#" PRIx32,
2614 address, opcode, mnemonic, imm*4);
2616 instruction->info.data_proc.variant = 0 /* immediate */;
2617 instruction->info.data_proc.rd = 13 /*SP*/;
2618 instruction->info.data_proc.rn = 13 /*SP*/;
2619 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
2624 static int evaluate_breakpoint_thumb(uint16_t opcode,
2625 uint32_t address, struct arm_instruction *instruction)
2627 uint32_t imm = opcode & 0xff;
2629 instruction->type = ARM_BKPT;
2631 snprintf(instruction->text, 128,
2632 "0x%8.8" PRIx32 " 0x%4.4x \tBKPT\t%#2.2" PRIx32 "",
2633 address, opcode, imm);
2638 static int evaluate_load_store_multiple_thumb(uint16_t opcode,
2639 uint32_t address, struct arm_instruction *instruction)
2641 uint32_t reg_list = opcode & 0xff;
2642 uint32_t l = opcode & (1 << 11);
2643 uint32_t r = opcode & (1 << 8);
2644 uint8_t rn = (opcode >> 8) & 7;
2645 uint8_t addr_mode = 0 /* IA */;
2649 char ptr_name[7] = "";
2652 /* REVISIT: in ThumbEE mode, there are no LDM or STM instructions.
2653 * The STMIA and LDMIA opcodes are used for other instructions.
2656 if ((opcode & 0xf000) == 0xc000) { /* generic load/store multiple */
2660 instruction->type = ARM_LDM;
2662 if (opcode & (1 << rn))
2665 instruction->type = ARM_STM;
2668 snprintf(ptr_name, sizeof(ptr_name), "r%i%s, ", rn, wback);
2669 } else {/* push/pop */
2672 instruction->type = ARM_LDM;
2675 reg_list |= (1 << 15) /*PC*/;
2677 instruction->type = ARM_STM;
2679 addr_mode = 3; /*DB*/
2681 reg_list |= (1 << 14) /*LR*/;
2685 reg_names_p = reg_names;
2686 for (i = 0; i <= 15; i++) {
2687 if (reg_list & (1 << i))
2688 reg_names_p += snprintf(reg_names_p,
2689 (reg_names + 40 - reg_names_p),
2693 if (reg_names_p > reg_names)
2694 reg_names_p[-2] = '\0';
2695 else /* invalid op : no registers */
2696 reg_names[0] = '\0';
2698 snprintf(instruction->text, 128,
2699 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%s{%s}",
2700 address, opcode, mnemonic, ptr_name, reg_names);
2702 instruction->info.load_store_multiple.register_list = reg_list;
2703 instruction->info.load_store_multiple.rn = rn;
2704 instruction->info.load_store_multiple.addressing_mode = addr_mode;
2709 static int evaluate_cond_branch_thumb(uint16_t opcode,
2710 uint32_t address, struct arm_instruction *instruction)
2712 uint32_t offset = opcode & 0xff;
2713 uint8_t cond = (opcode >> 8) & 0xf;
2714 uint32_t target_address;
2717 instruction->type = ARM_SWI;
2718 snprintf(instruction->text, 128,
2719 "0x%8.8" PRIx32 " 0x%4.4x \tSVC\t%#2.2" PRIx32,
2720 address, opcode, offset);
2722 } else if (cond == 0xe) {
2723 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2724 snprintf(instruction->text, 128,
2725 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2730 /* sign extend 8-bit offset */
2731 if (offset & 0x00000080)
2732 offset = 0xffffff00 | offset;
2734 target_address = address + 4 + (offset << 1);
2736 snprintf(instruction->text, 128,
2737 "0x%8.8" PRIx32 " 0x%4.4x \tB%s\t%#8.8" PRIx32,
2739 arm_condition_strings[cond], target_address);
2741 instruction->type = ARM_B;
2742 instruction->info.b_bl_bx_blx.reg_operand = -1;
2743 instruction->info.b_bl_bx_blx.target_address = target_address;
2748 static int evaluate_cb_thumb(uint16_t opcode, uint32_t address,
2749 struct arm_instruction *instruction)
2753 /* added in Thumb2 */
2754 offset = (opcode >> 3) & 0x1f;
2755 offset |= (opcode & 0x0200) >> 4;
2757 snprintf(instruction->text, 128,
2758 "0x%8.8" PRIx32 " 0x%4.4x \tCB%sZ\tr%d, %#8.8" PRIx32,
2760 (opcode & 0x0800) ? "N" : "",
2761 opcode & 0x7, address + 4 + (offset << 1));
2766 static int evaluate_extend_thumb(uint16_t opcode, uint32_t address,
2767 struct arm_instruction *instruction)
2769 /* added in ARMv6 */
2770 snprintf(instruction->text, 128,
2771 "0x%8.8" PRIx32 " 0x%4.4x \t%cXT%c\tr%d, r%d",
2773 (opcode & 0x0080) ? 'U' : 'S',
2774 (opcode & 0x0040) ? 'B' : 'H',
2775 opcode & 0x7, (opcode >> 3) & 0x7);
2780 static int evaluate_cps_thumb(uint16_t opcode, uint32_t address,
2781 struct arm_instruction *instruction)
2783 /* added in ARMv6 */
2784 if ((opcode & 0x0ff0) == 0x0650)
2785 snprintf(instruction->text, 128,
2786 "0x%8.8" PRIx32 " 0x%4.4x \tSETEND %s",
2788 (opcode & 0x80) ? "BE" : "LE");
2789 else /* ASSUME (opcode & 0x0fe0) == 0x0660 */
2790 snprintf(instruction->text, 128,
2791 "0x%8.8" PRIx32 " 0x%4.4x \tCPSI%c\t%s%s%s",
2793 (opcode & 0x0010) ? 'D' : 'E',
2794 (opcode & 0x0004) ? "A" : "",
2795 (opcode & 0x0002) ? "I" : "",
2796 (opcode & 0x0001) ? "F" : "");
2801 static int evaluate_byterev_thumb(uint16_t opcode, uint32_t address,
2802 struct arm_instruction *instruction)
2806 /* added in ARMv6 */
2807 switch ((opcode >> 6) & 3) {
2818 snprintf(instruction->text, 128,
2819 "0x%8.8" PRIx32 " 0x%4.4x \tREV%s\tr%d, r%d",
2820 address, opcode, suffix,
2821 opcode & 0x7, (opcode >> 3) & 0x7);
2826 static int evaluate_hint_thumb(uint16_t opcode, uint32_t address,
2827 struct arm_instruction *instruction)
2831 switch ((opcode >> 4) & 0x0f) {
2848 hint = "HINT (UNRECOGNIZED)";
2852 snprintf(instruction->text, 128,
2853 "0x%8.8" PRIx32 " 0x%4.4x \t%s",
2854 address, opcode, hint);
2859 static int evaluate_ifthen_thumb(uint16_t opcode, uint32_t address,
2860 struct arm_instruction *instruction)
2862 unsigned cond = (opcode >> 4) & 0x0f;
2863 char *x = "", *y = "", *z = "";
2866 z = (opcode & 0x02) ? "T" : "E";
2868 y = (opcode & 0x04) ? "T" : "E";
2870 x = (opcode & 0x08) ? "T" : "E";
2872 snprintf(instruction->text, 128,
2873 "0x%8.8" PRIx32 " 0x%4.4x \tIT%s%s%s\t%s",
2875 x, y, z, arm_condition_strings[cond]);
2877 /* NOTE: strictly speaking, the next 1-4 instructions should
2878 * now be displayed with the relevant conditional suffix...
2884 int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
2886 /* clear fields, to avoid confusion */
2887 memset(instruction, 0, sizeof(struct arm_instruction));
2888 instruction->opcode = opcode;
2889 instruction->instruction_size = 2;
2891 if ((opcode & 0xe000) == 0x0000) {
2892 /* add/subtract register or immediate */
2893 if ((opcode & 0x1800) == 0x1800)
2894 return evaluate_add_sub_thumb(opcode, address, instruction);
2895 /* shift by immediate */
2897 return evaluate_shift_imm_thumb(opcode, address, instruction);
2900 /* Add/subtract/compare/move immediate */
2901 if ((opcode & 0xe000) == 0x2000)
2902 return evaluate_data_proc_imm_thumb(opcode, address, instruction);
2904 /* Data processing instructions */
2905 if ((opcode & 0xf800) == 0x4000)
2906 return evaluate_data_proc_thumb(opcode, address, instruction);
2908 /* Load from literal pool */
2909 if ((opcode & 0xf800) == 0x4800)
2910 return evaluate_load_literal_thumb(opcode, address, instruction);
2912 /* Load/Store register offset */
2913 if ((opcode & 0xf000) == 0x5000)
2914 return evaluate_load_store_reg_thumb(opcode, address, instruction);
2916 /* Load/Store immediate offset */
2917 if (((opcode & 0xe000) == 0x6000)
2918 || ((opcode & 0xf000) == 0x8000))
2919 return evaluate_load_store_imm_thumb(opcode, address, instruction);
2921 /* Load/Store from/to stack */
2922 if ((opcode & 0xf000) == 0x9000)
2923 return evaluate_load_store_stack_thumb(opcode, address, instruction);
2926 if ((opcode & 0xf000) == 0xa000)
2927 return evaluate_add_sp_pc_thumb(opcode, address, instruction);
2930 if ((opcode & 0xf000) == 0xb000) {
2931 switch ((opcode >> 8) & 0x0f) {
2933 return evaluate_adjust_stack_thumb(opcode, address, instruction);
2938 return evaluate_cb_thumb(opcode, address, instruction);
2940 return evaluate_extend_thumb(opcode, address, instruction);
2945 return evaluate_load_store_multiple_thumb(opcode, address,
2948 return evaluate_cps_thumb(opcode, address, instruction);
2950 if ((opcode & 0x00c0) == 0x0080)
2952 return evaluate_byterev_thumb(opcode, address, instruction);
2954 return evaluate_breakpoint_thumb(opcode, address, instruction);
2956 if (opcode & 0x000f)
2957 return evaluate_ifthen_thumb(opcode, address,
2960 return evaluate_hint_thumb(opcode, address,
2964 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2965 snprintf(instruction->text, 128,
2966 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2971 /* Load/Store multiple */
2972 if ((opcode & 0xf000) == 0xc000)
2973 return evaluate_load_store_multiple_thumb(opcode, address, instruction);
2975 /* Conditional branch + SWI */
2976 if ((opcode & 0xf000) == 0xd000)
2977 return evaluate_cond_branch_thumb(opcode, address, instruction);
2979 if ((opcode & 0xe000) == 0xe000) {
2980 /* Undefined instructions */
2981 if ((opcode & 0xf801) == 0xe801) {
2982 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2983 snprintf(instruction->text, 128,
2984 "0x%8.8" PRIx32 " 0x%8.8x\t"
2985 "UNDEFINED INSTRUCTION",
2988 } else /* Branch to offset */
2989 return evaluate_b_bl_blx_thumb(opcode, address, instruction);
2992 LOG_ERROR("Thumb: should never reach this point (opcode=%04x)", opcode);
2996 int arm_access_size(struct arm_instruction *instruction)
2998 if ((instruction->type == ARM_LDRB)
2999 || (instruction->type == ARM_LDRBT)
3000 || (instruction->type == ARM_LDRSB)
3001 || (instruction->type == ARM_STRB)
3002 || (instruction->type == ARM_STRBT))
3004 else if ((instruction->type == ARM_LDRH)
3005 || (instruction->type == ARM_LDRSH)
3006 || (instruction->type == ARM_STRH))
3008 else if ((instruction->type == ARM_LDR)
3009 || (instruction->type == ARM_LDRT)
3010 || (instruction->type == ARM_STR)
3011 || (instruction->type == ARM_STRT))
3013 else if ((instruction->type == ARM_LDRD)
3014 || (instruction->type == ARM_STRD))
3017 LOG_ERROR("BUG: instruction type %i isn't a load/store instruction",
3024 static void print_opcode(struct command_invocation *cmd, const cs_insn *insn)
3026 uint32_t opcode = 0;
3028 memcpy(&opcode, insn->bytes, insn->size);
3030 if (insn->size == 4) {
3031 uint16_t opcode_high = opcode >> 16;
3032 opcode = opcode & 0xffff;
3034 command_print(cmd, "0x%08" PRIx64" %04x %04x\t%s%s%s",
3035 insn->address, opcode, opcode_high, insn->mnemonic,
3036 insn->op_str[0] ? "\t" : "", insn->op_str);
3038 command_print(cmd, "0x%08" PRIx64" %04x\t%s%s%s",
3039 insn->address, opcode, insn->mnemonic,
3040 insn->op_str[0] ? "\t" : "", insn->op_str);
3044 int arm_disassemble(struct command_invocation *cmd, struct target *target,
3045 target_addr_t address, size_t count, bool thumb_mode)
3052 if (!cs_support(CS_ARCH_ARM)) {
3053 LOG_ERROR("ARM architecture not supported by capstone");
3057 mode = CS_MODE_LITTLE_ENDIAN;
3060 mode |= CS_MODE_THUMB;
3062 ret = cs_open(CS_ARCH_ARM, mode, &handle);
3064 if (ret != CS_ERR_OK) {
3065 LOG_ERROR("cs_open() failed: %s", cs_strerror(ret));
3069 ret = cs_option(handle, CS_OPT_SKIPDATA, CS_OPT_ON);
3071 if (ret != CS_ERR_OK) {
3072 LOG_ERROR("cs_option() failed: %s", cs_strerror(ret));
3077 insn = cs_malloc(handle);
3080 LOG_ERROR("cs_malloc() failed\n");
3088 ret = target_read_buffer(target, address, sizeof(buffer), buffer);
3090 if (ret != ERROR_OK) {
3096 size_t size = sizeof(buffer);
3097 const uint8_t *tmp = buffer;
3099 ret = cs_disasm_iter(handle, &tmp, &size, &address, insn);
3102 LOG_ERROR("cs_disasm_iter() failed: %s",
3103 cs_strerror(cs_errno(handle)));
3109 print_opcode(cmd, insn);
3118 #endif /* HAVE_CAPSTONE */