1 /***************************************************************************
2 * Copyright (C) 2006 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
5 * Copyright (C) 2009 by David Brownell *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
19 ***************************************************************************/
26 #include "arm_disassembler.h"
27 #include <helper/log.h>
30 * This disassembler supports two main functions for OpenOCD:
32 * - Various "disassemble" commands. OpenOCD can serve as a
33 * machine-language debugger, without help from GDB.
35 * - Single stepping. Not all ARM cores support hardware single
36 * stepping. To work without that support, the debugger must
37 * be able to decode instructions to find out where to put a
38 * "next instruction" breakpoint.
40 * In addition, interpretation of ETM trace data needs some of the
41 * decoding mechanisms.
43 * At this writing (September 2009) neither function is complete.
46 * * Old-style syntax (not UAL) is generally used
47 * * VFP instructions are not understood (ARMv5 and later)
48 * except as coprocessor 10/11 operations
49 * * Most ARM instructions through ARMv6 are decoded, but some
50 * of the post-ARMv4 opcodes may not be handled yet
51 * CPS, SDIV, UDIV, LDREX*, STREX*, QASX, ...
52 * * NEON instructions are not understood (ARMv7-A)
54 * - Thumb/Thumb2 decoding
55 * * UAL syntax should be consistently used
56 * * Any Thumb2 instructions used in Cortex-M3 (ARMv7-M) should
57 * be handled properly. Accordingly, so should the subset
58 * used in Cortex-M0/M1; and "original" 16-bit Thumb from
60 * * Conditional effects of Thumb2 "IT" (if-then) instructions
61 * are not handled: the affected instructions are not shown
62 * with their now-conditional suffixes.
63 * * Some ARMv6 and ARMv7-M Thumb2 instructions may not be
64 * handled (minimally for coprocessor access).
65 * * SIMD instructions, and some other Thumb2 instructions
66 * from ARMv7-A, are not understood.
69 * * As a Thumb2 variant, the Thumb2 comments (above) apply.
70 * * Opcodes changed by ThumbEE mode are not handled; these
71 * instructions wrongly decode as LDM and STM.
73 * - Jazelle decoding ... no support whatsoever for Jazelle mode
74 * or decoding. ARM encourages use of the more generic ThumbEE
75 * mode, instead of Jazelle mode, in current chips.
77 * - Single-step/emulation ... spotty support, which is only weakly
78 * tested. Thumb2 is not supported. (Arguably a full simulator
79 * is not needed to support just single stepping. Recognizing
80 * branch vs non-branch instructions suffices, except when the
81 * instruction faults and triggers a synchronous exception which
82 * can be intercepted using other means.)
84 * ARM DDI 0406B "ARM Architecture Reference Manual, ARM v7-A and
85 * ARM v7-R edition" gives the most complete coverage of the various
86 * generations of ARM instructions. At this writing it is publicly
87 * accessible to anyone willing to create an account at the ARM
88 * web site; see http://www.arm.com/documentation/ for information.
90 * ARM DDI 0403C "ARMv7-M Architecture Reference Manual" provides
91 * more details relevant to the Thumb2-only processors (such as
92 * the Cortex-M implementations).
95 /* textual represenation of the condition field
96 * ALways (default) is ommitted (empty string) */
97 static const char *arm_condition_strings[] = {
98 "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", "HI", "LS", "GE", "LT", "GT", "LE", "", "NV"
101 /* make up for C's missing ROR */
102 static uint32_t ror(uint32_t value, int places)
104 return (value >> places) | (value << (32 - places));
107 static int evaluate_unknown(uint32_t opcode,
108 uint32_t address, struct arm_instruction *instruction)
110 instruction->type = ARM_UNDEFINED_INSTRUCTION;
111 snprintf(instruction->text, 128,
112 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
113 "\tUNDEFINED INSTRUCTION", address, opcode);
117 static int evaluate_pld(uint32_t opcode,
118 uint32_t address, struct arm_instruction *instruction)
121 if ((opcode & 0x0d70f000) == 0x0550f000) {
122 instruction->type = ARM_PLD;
124 snprintf(instruction->text,
126 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD ...TODO...",
133 if ((opcode & 0x07f000f0) == 0x05700040) {
134 instruction->type = ARM_DSB;
137 switch (opcode & 0x0000000f) {
166 snprintf(instruction->text,
168 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tDSB %s",
169 address, opcode, opt);
174 if ((opcode & 0x07f000f0) == 0x05700060) {
175 instruction->type = ARM_ISB;
177 snprintf(instruction->text,
179 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tISB %s",
181 ((opcode & 0x0000000f) == 0xf) ? "SY" : "UNK");
185 return evaluate_unknown(opcode, address, instruction);
188 static int evaluate_srs(uint32_t opcode,
189 uint32_t address, struct arm_instruction *instruction)
191 const char *wback = (opcode & (1 << 21)) ? "!" : "";
192 const char *mode = "";
194 switch ((opcode >> 23) & 0x3) {
199 /* "IA" is default */
209 switch (opcode & 0x0e500000) {
211 snprintf(instruction->text, 128, "0x%8.8" PRIx32
213 "\tSRS%s\tSP%s, #%d",
216 (unsigned)(opcode & 0x1f));
219 snprintf(instruction->text, 128, "0x%8.8" PRIx32
224 (unsigned)((opcode >> 16) & 0xf), wback);
227 return evaluate_unknown(opcode, address, instruction);
232 static int evaluate_swi(uint32_t opcode,
233 uint32_t address, struct arm_instruction *instruction)
235 instruction->type = ARM_SWI;
237 snprintf(instruction->text, 128,
238 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSVC %#6.6" PRIx32,
239 address, opcode, (opcode & 0xffffff));
244 static int evaluate_blx_imm(uint32_t opcode,
245 uint32_t address, struct arm_instruction *instruction)
249 uint32_t target_address;
251 instruction->type = ARM_BLX;
252 immediate = opcode & 0x00ffffff;
254 /* sign extend 24-bit immediate */
255 if (immediate & 0x00800000)
256 offset = 0xff000000 | immediate;
260 /* shift two bits left */
263 /* odd/event halfword */
264 if (opcode & 0x01000000)
267 target_address = address + 8 + offset;
269 snprintf(instruction->text,
271 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX 0x%8.8" PRIx32 "",
276 instruction->info.b_bl_bx_blx.reg_operand = -1;
277 instruction->info.b_bl_bx_blx.target_address = target_address;
282 static int evaluate_b_bl(uint32_t opcode,
283 uint32_t address, struct arm_instruction *instruction)
288 uint32_t target_address;
290 immediate = opcode & 0x00ffffff;
291 L = (opcode & 0x01000000) >> 24;
293 /* sign extend 24-bit immediate */
294 if (immediate & 0x00800000)
295 offset = 0xff000000 | immediate;
299 /* shift two bits left */
302 target_address = address + 8 + offset;
305 instruction->type = ARM_BL;
307 instruction->type = ARM_B;
309 snprintf(instruction->text,
311 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tB%s%s 0x%8.8" PRIx32,
318 instruction->info.b_bl_bx_blx.reg_operand = -1;
319 instruction->info.b_bl_bx_blx.target_address = target_address;
324 /* Coprocessor load/store and double register transfers
325 * both normal and extended instruction space (condition field b1111) */
326 static int evaluate_ldc_stc_mcrr_mrrc(uint32_t opcode,
327 uint32_t address, struct arm_instruction *instruction)
329 uint8_t cp_num = (opcode & 0xf00) >> 8;
332 if (((opcode & 0x0ff00000) == 0x0c400000) || ((opcode & 0x0ff00000) == 0x0c500000)) {
333 uint8_t cp_opcode, Rd, Rn, CRm;
336 cp_opcode = (opcode & 0xf0) >> 4;
337 Rd = (opcode & 0xf000) >> 12;
338 Rn = (opcode & 0xf0000) >> 16;
339 CRm = (opcode & 0xf);
342 if ((opcode & 0x0ff00000) == 0x0c400000) {
343 instruction->type = ARM_MCRR;
345 } else if ((opcode & 0x0ff00000) == 0x0c500000) {
347 instruction->type = ARM_MRRC;
350 LOG_ERROR("Unknown instruction");
354 snprintf(instruction->text, 128,
355 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
356 "\t%s%s%s p%i, %x, r%i, r%i, c%i",
357 address, opcode, mnemonic,
358 ((opcode & 0xf0000000) == 0xf0000000)
359 ? "2" : COND(opcode),
360 COND(opcode), cp_num, cp_opcode, Rd, Rn, CRm);
361 } else {/* LDC or STC */
362 uint8_t CRd, Rn, offset;
365 char addressing_mode[32];
367 CRd = (opcode & 0xf000) >> 12;
368 Rn = (opcode & 0xf0000) >> 16;
369 offset = (opcode & 0xff) << 2;
372 if (opcode & 0x00100000) {
373 instruction->type = ARM_LDC;
376 instruction->type = ARM_STC;
380 U = (opcode & 0x00800000) >> 23;
382 /* addressing modes */
383 if ((opcode & 0x01200000) == 0x01000000)/* offset */
384 snprintf(addressing_mode, 32, "[r%i, #%s%d]",
385 Rn, U ? "" : "-", offset);
386 else if ((opcode & 0x01200000) == 0x01200000) /* pre-indexed */
387 snprintf(addressing_mode, 32, "[r%i, #%s%d]!",
388 Rn, U ? "" : "-", offset);
389 else if ((opcode & 0x01200000) == 0x00200000) /* post-indexed */
390 snprintf(addressing_mode, 32, "[r%i], #%s%d",
391 Rn, U ? "" : "-", offset);
392 else if ((opcode & 0x01200000) == 0x00000000) /* unindexed */
393 snprintf(addressing_mode, 32, "[r%i], {%d}",
396 snprintf(instruction->text, 128, "0x%8.8" PRIx32
398 "\t%s%s%s p%i, c%i, %s",
399 address, opcode, mnemonic,
400 ((opcode & 0xf0000000) == 0xf0000000)
401 ? "2" : COND(opcode),
402 (opcode & (1 << 22)) ? "L" : "",
403 cp_num, CRd, addressing_mode);
409 /* Coprocessor data processing instructions
410 * Coprocessor register transfer instructions
411 * both normal and extended instruction space (condition field b1111) */
412 static int evaluate_cdp_mcr_mrc(uint32_t opcode,
413 uint32_t address, struct arm_instruction *instruction)
417 uint8_t cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2;
419 cond = ((opcode & 0xf0000000) == 0xf0000000) ? "2" : COND(opcode);
420 cp_num = (opcode & 0xf00) >> 8;
421 CRd_Rd = (opcode & 0xf000) >> 12;
422 CRn = (opcode & 0xf0000) >> 16;
423 CRm = (opcode & 0xf);
424 opcode_2 = (opcode & 0xe0) >> 5;
427 if (opcode & 0x00000010) { /* bit 4 set -> MRC/MCR */
428 if (opcode & 0x00100000) { /* bit 20 set -> MRC */
429 instruction->type = ARM_MRC;
431 } else {/* bit 20 not set -> MCR */
432 instruction->type = ARM_MCR;
436 opcode_1 = (opcode & 0x00e00000) >> 21;
438 snprintf(instruction->text,
440 "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",
451 } else {/* bit 4 not set -> CDP */
452 instruction->type = ARM_CDP;
455 opcode_1 = (opcode & 0x00f00000) >> 20;
457 snprintf(instruction->text,
459 "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",
475 /* Load/store instructions */
476 static int evaluate_load_store(uint32_t opcode,
477 uint32_t address, struct arm_instruction *instruction)
479 uint8_t I, P, U, B, W, L;
481 char *operation;/* "LDR" or "STR" */
482 char *suffix; /* "", "B", "T", "BT" */
486 I = (opcode & 0x02000000) >> 25;
487 P = (opcode & 0x01000000) >> 24;
488 U = (opcode & 0x00800000) >> 23;
489 B = (opcode & 0x00400000) >> 22;
490 W = (opcode & 0x00200000) >> 21;
491 L = (opcode & 0x00100000) >> 20;
493 /* target register */
494 Rd = (opcode & 0xf000) >> 12;
497 Rn = (opcode & 0xf0000) >> 16;
499 instruction->info.load_store.Rd = Rd;
500 instruction->info.load_store.Rn = Rn;
501 instruction->info.load_store.U = U;
503 /* determine operation */
509 /* determine instruction type and suffix */
511 if ((P == 0) && (W == 1)) {
513 instruction->type = ARM_LDRBT;
515 instruction->type = ARM_STRBT;
519 instruction->type = ARM_LDRB;
521 instruction->type = ARM_STRB;
525 if ((P == 0) && (W == 1)) {
527 instruction->type = ARM_LDRT;
529 instruction->type = ARM_STRT;
533 instruction->type = ARM_LDR;
535 instruction->type = ARM_STR;
540 if (!I) { /* #+-<offset_12> */
541 uint32_t offset_12 = (opcode & 0xfff);
543 snprintf(offset, 32, ", #%s0x%" PRIx32 "", (U) ? "" : "-", offset_12);
545 snprintf(offset, 32, "%s", "");
547 instruction->info.load_store.offset_mode = 0;
548 instruction->info.load_store.offset.offset = offset_12;
549 } else {/* either +-<Rm> or +-<Rm>, <shift>, #<shift_imm> */
550 uint8_t shift_imm, shift;
553 shift_imm = (opcode & 0xf80) >> 7;
554 shift = (opcode & 0x60) >> 5;
557 /* LSR encodes a shift by 32 bit as 0x0 */
558 if ((shift == 0x1) && (shift_imm == 0x0))
561 /* ASR encodes a shift by 32 bit as 0x0 */
562 if ((shift == 0x2) && (shift_imm == 0x0))
565 /* ROR by 32 bit is actually a RRX */
566 if ((shift == 0x3) && (shift_imm == 0x0))
569 instruction->info.load_store.offset_mode = 1;
570 instruction->info.load_store.offset.reg.Rm = Rm;
571 instruction->info.load_store.offset.reg.shift = shift;
572 instruction->info.load_store.offset.reg.shift_imm = shift_imm;
574 if ((shift_imm == 0x0) && (shift == 0x0)) /* +-<Rm> */
575 snprintf(offset, 32, ", %sr%i", (U) ? "" : "-", Rm);
576 else { /* +-<Rm>, <Shift>, #<shift_imm> */
579 snprintf(offset, 32, ", %sr%i, LSL #0x%x", (U) ? "" : "-", Rm, shift_imm);
582 snprintf(offset, 32, ", %sr%i, LSR #0x%x", (U) ? "" : "-", Rm, shift_imm);
585 snprintf(offset, 32, ", %sr%i, ASR #0x%x", (U) ? "" : "-", Rm, shift_imm);
588 snprintf(offset, 32, ", %sr%i, ROR #0x%x", (U) ? "" : "-", Rm, shift_imm);
591 snprintf(offset, 32, ", %sr%i, RRX", (U) ? "" : "-", Rm);
598 if (W == 0) { /* offset */
599 snprintf(instruction->text,
601 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]",
611 instruction->info.load_store.index_mode = 0;
612 } else {/* pre-indexed */
613 snprintf(instruction->text,
615 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]!",
625 instruction->info.load_store.index_mode = 1;
627 } else {/* post-indexed */
628 snprintf(instruction->text,
630 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i]%s",
640 instruction->info.load_store.index_mode = 2;
646 static int evaluate_extend(uint32_t opcode, uint32_t address, char *cp)
648 unsigned rm = (opcode >> 0) & 0xf;
649 unsigned rd = (opcode >> 12) & 0xf;
650 unsigned rn = (opcode >> 16) & 0xf;
653 switch ((opcode >> 24) & 0x3) {
658 sprintf(cp, "UNDEFINED");
659 return ARM_UNDEFINED_INSTRUCTION;
668 switch ((opcode >> 10) & 0x3) {
684 sprintf(cp, "%cXT%s%s\tr%d, r%d%s",
685 (opcode & (1 << 22)) ? 'U' : 'S',
690 sprintf(cp, "%cXTA%s%s\tr%d, r%d, r%d%s",
691 (opcode & (1 << 22)) ? 'U' : 'S',
698 static int evaluate_p_add_sub(uint32_t opcode, uint32_t address, char *cp)
704 switch ((opcode >> 20) & 0x7) {
727 switch ((opcode >> 5) & 0x7) {
756 sprintf(cp, "%s%s%s\tr%d, r%d, r%d", prefix, op, COND(opcode),
757 (int) (opcode >> 12) & 0xf,
758 (int) (opcode >> 16) & 0xf,
759 (int) (opcode >> 0) & 0xf);
763 /* these opcodes might be used someday */
764 sprintf(cp, "UNDEFINED");
765 return ARM_UNDEFINED_INSTRUCTION;
768 /* ARMv6 and later support "media" instructions (includes SIMD) */
769 static int evaluate_media(uint32_t opcode, uint32_t address,
770 struct arm_instruction *instruction)
772 char *cp = instruction->text;
773 char *mnemonic = NULL;
776 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t",
780 /* parallel add/subtract */
781 if ((opcode & 0x01800000) == 0x00000000) {
782 instruction->type = evaluate_p_add_sub(opcode, address, cp);
787 if ((opcode & 0x01f00020) == 0x00800000) {
789 unsigned imm = (unsigned) (opcode >> 7) & 0x1f;
791 if (opcode & (1 << 6)) {
800 sprintf(cp, "PKH%s%s\tr%d, r%d, r%d, %s #%d",
802 (int) (opcode >> 12) & 0xf,
803 (int) (opcode >> 16) & 0xf,
804 (int) (opcode >> 0) & 0xf,
810 if ((opcode & 0x01a00020) == 0x00a00000) {
812 unsigned imm = (unsigned) (opcode >> 7) & 0x1f;
814 if (opcode & (1 << 6)) {
821 sprintf(cp, "%cSAT%s\tr%d, #%d, r%d, %s #%d",
822 (opcode & (1 << 22)) ? 'U' : 'S',
824 (int) (opcode >> 12) & 0xf,
825 (int) (opcode >> 16) & 0x1f,
826 (int) (opcode >> 0) & 0xf,
832 if ((opcode & 0x018000f0) == 0x00800070) {
833 instruction->type = evaluate_extend(opcode, address, cp);
838 if ((opcode & 0x01f00080) == 0x01000000) {
839 unsigned rn = (opcode >> 12) & 0xf;
842 sprintf(cp, "SML%cD%s%s\tr%d, r%d, r%d, r%d",
843 (opcode & (1 << 6)) ? 'S' : 'A',
844 (opcode & (1 << 5)) ? "X" : "",
846 (int) (opcode >> 16) & 0xf,
847 (int) (opcode >> 0) & 0xf,
848 (int) (opcode >> 8) & 0xf,
851 sprintf(cp, "SMU%cD%s%s\tr%d, r%d, r%d",
852 (opcode & (1 << 6)) ? 'S' : 'A',
853 (opcode & (1 << 5)) ? "X" : "",
855 (int) (opcode >> 16) & 0xf,
856 (int) (opcode >> 0) & 0xf,
857 (int) (opcode >> 8) & 0xf);
860 if ((opcode & 0x01f00000) == 0x01400000) {
861 sprintf(cp, "SML%cLD%s%s\tr%d, r%d, r%d, r%d",
862 (opcode & (1 << 6)) ? 'S' : 'A',
863 (opcode & (1 << 5)) ? "X" : "",
865 (int) (opcode >> 12) & 0xf,
866 (int) (opcode >> 16) & 0xf,
867 (int) (opcode >> 0) & 0xf,
868 (int) (opcode >> 8) & 0xf);
871 if ((opcode & 0x01f00000) == 0x01500000) {
872 unsigned rn = (opcode >> 12) & 0xf;
874 switch (opcode & 0xc0) {
886 sprintf(cp, "SMML%c%s%s\tr%d, r%d, r%d, r%d",
887 (opcode & (1 << 6)) ? 'S' : 'A',
888 (opcode & (1 << 5)) ? "R" : "",
890 (int) (opcode >> 16) & 0xf,
891 (int) (opcode >> 0) & 0xf,
892 (int) (opcode >> 8) & 0xf,
895 sprintf(cp, "SMMUL%s%s\tr%d, r%d, r%d",
896 (opcode & (1 << 5)) ? "R" : "",
898 (int) (opcode >> 16) & 0xf,
899 (int) (opcode >> 0) & 0xf,
900 (int) (opcode >> 8) & 0xf);
904 /* simple matches against the remaining decode bits */
905 switch (opcode & 0x01f000f0) {
908 /* parallel halfword saturate */
909 sprintf(cp, "%cSAT16%s\tr%d, #%d, r%d",
910 (opcode & (1 << 22)) ? 'U' : 'S',
912 (int) (opcode >> 12) & 0xf,
913 (int) (opcode >> 16) & 0xf,
914 (int) (opcode >> 0) & 0xf);
927 sprintf(cp, "SEL%s\tr%d, r%d, r%d", COND(opcode),
928 (int) (opcode >> 12) & 0xf,
929 (int) (opcode >> 16) & 0xf,
930 (int) (opcode >> 0) & 0xf);
933 /* unsigned sum of absolute differences */
934 if (((opcode >> 12) & 0xf) == 0xf)
935 sprintf(cp, "USAD8%s\tr%d, r%d, r%d", COND(opcode),
936 (int) (opcode >> 16) & 0xf,
937 (int) (opcode >> 0) & 0xf,
938 (int) (opcode >> 8) & 0xf);
940 sprintf(cp, "USADA8%s\tr%d, r%d, r%d, r%d", COND(opcode),
941 (int) (opcode >> 16) & 0xf,
942 (int) (opcode >> 0) & 0xf,
943 (int) (opcode >> 8) & 0xf,
944 (int) (opcode >> 12) & 0xf);
948 unsigned rm = (opcode >> 0) & 0xf;
949 unsigned rd = (opcode >> 12) & 0xf;
951 sprintf(cp, "%s%s\tr%d, r%d", mnemonic, COND(opcode), rm, rd);
956 /* these opcodes might be used someday */
957 sprintf(cp, "UNDEFINED");
961 /* Miscellaneous load/store instructions */
962 static int evaluate_misc_load_store(uint32_t opcode,
963 uint32_t address, struct arm_instruction *instruction)
965 uint8_t P, U, I, W, L, S, H;
967 char *operation;/* "LDR" or "STR" */
968 char *suffix; /* "H", "SB", "SH", "D" */
972 P = (opcode & 0x01000000) >> 24;
973 U = (opcode & 0x00800000) >> 23;
974 I = (opcode & 0x00400000) >> 22;
975 W = (opcode & 0x00200000) >> 21;
976 L = (opcode & 0x00100000) >> 20;
977 S = (opcode & 0x00000040) >> 6;
978 H = (opcode & 0x00000020) >> 5;
980 /* target register */
981 Rd = (opcode & 0xf000) >> 12;
984 Rn = (opcode & 0xf0000) >> 16;
986 instruction->info.load_store.Rd = Rd;
987 instruction->info.load_store.Rn = Rn;
988 instruction->info.load_store.U = U;
990 /* determine instruction type and suffix */
995 instruction->type = ARM_LDRSH;
999 instruction->type = ARM_LDRSB;
1002 } else {/* there are no signed stores, so this is used to encode double-register
1007 instruction->type = ARM_STRD;
1010 instruction->type = ARM_LDRD;
1013 } else {/* unsigned */
1017 instruction->type = ARM_LDRH;
1020 instruction->type = ARM_STRH;
1024 if (I) {/* Immediate offset/index (#+-<offset_8>)*/
1025 uint32_t offset_8 = ((opcode & 0xf00) >> 4) | (opcode & 0xf);
1026 snprintf(offset, 32, "#%s0x%" PRIx32 "", (U) ? "" : "-", offset_8);
1028 instruction->info.load_store.offset_mode = 0;
1029 instruction->info.load_store.offset.offset = offset_8;
1030 } else {/* Register offset/index (+-<Rm>) */
1032 Rm = (opcode & 0xf);
1033 snprintf(offset, 32, "%sr%i", (U) ? "" : "-", Rm);
1035 instruction->info.load_store.offset_mode = 1;
1036 instruction->info.load_store.offset.reg.Rm = Rm;
1037 instruction->info.load_store.offset.reg.shift = 0x0;
1038 instruction->info.load_store.offset.reg.shift_imm = 0x0;
1042 if (W == 0) { /* offset */
1043 snprintf(instruction->text,
1045 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]",
1055 instruction->info.load_store.index_mode = 0;
1056 } else {/* pre-indexed */
1057 snprintf(instruction->text,
1059 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]!",
1069 instruction->info.load_store.index_mode = 1;
1071 } else {/* post-indexed */
1072 snprintf(instruction->text,
1074 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i], %s",
1084 instruction->info.load_store.index_mode = 2;
1090 /* Load/store multiples instructions */
1091 static int evaluate_ldm_stm(uint32_t opcode,
1092 uint32_t address, struct arm_instruction *instruction)
1094 uint8_t P, U, S, W, L, Rn;
1095 uint32_t register_list;
1096 char *addressing_mode;
1103 P = (opcode & 0x01000000) >> 24;
1104 U = (opcode & 0x00800000) >> 23;
1105 S = (opcode & 0x00400000) >> 22;
1106 W = (opcode & 0x00200000) >> 21;
1107 L = (opcode & 0x00100000) >> 20;
1108 register_list = (opcode & 0xffff);
1109 Rn = (opcode & 0xf0000) >> 16;
1111 instruction->info.load_store_multiple.Rn = Rn;
1112 instruction->info.load_store_multiple.register_list = register_list;
1113 instruction->info.load_store_multiple.S = S;
1114 instruction->info.load_store_multiple.W = W;
1117 instruction->type = ARM_LDM;
1120 instruction->type = ARM_STM;
1126 instruction->info.load_store_multiple.addressing_mode = 1;
1127 addressing_mode = "IB";
1129 instruction->info.load_store_multiple.addressing_mode = 3;
1130 addressing_mode = "DB";
1134 instruction->info.load_store_multiple.addressing_mode = 0;
1135 /* "IA" is the default in UAL syntax */
1136 addressing_mode = "";
1138 instruction->info.load_store_multiple.addressing_mode = 2;
1139 addressing_mode = "DA";
1143 reg_list_p = reg_list;
1144 for (i = 0; i <= 15; i++) {
1145 if ((register_list >> i) & 1) {
1148 reg_list_p += snprintf(reg_list_p,
1149 (reg_list + 69 - reg_list_p),
1153 reg_list_p += snprintf(reg_list_p,
1154 (reg_list + 69 - reg_list_p),
1160 snprintf(instruction->text, 128,
1161 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
1162 "\t%s%s%s r%i%s, {%s}%s",
1164 mnemonic, addressing_mode, COND(opcode),
1165 Rn, (W) ? "!" : "", reg_list, (S) ? "^" : "");
1170 /* Multiplies, extra load/stores */
1171 static int evaluate_mul_and_extra_ld_st(uint32_t opcode,
1172 uint32_t address, struct arm_instruction *instruction)
1174 /* Multiply (accumulate) (long) and Swap/swap byte */
1175 if ((opcode & 0x000000f0) == 0x00000090) {
1176 /* Multiply (accumulate) */
1177 if ((opcode & 0x0f800000) == 0x00000000) {
1178 uint8_t Rm, Rs, Rn, Rd, S;
1180 Rs = (opcode & 0xf00) >> 8;
1181 Rn = (opcode & 0xf000) >> 12;
1182 Rd = (opcode & 0xf0000) >> 16;
1183 S = (opcode & 0x00100000) >> 20;
1185 /* examine A bit (accumulate) */
1186 if (opcode & 0x00200000) {
1187 instruction->type = ARM_MLA;
1188 snprintf(instruction->text,
1190 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMLA%s%s r%i, r%i, r%i, r%i",
1200 instruction->type = ARM_MUL;
1201 snprintf(instruction->text,
1203 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMUL%s%s r%i, r%i, r%i",
1216 /* Multiply (accumulate) long */
1217 if ((opcode & 0x0f800000) == 0x00800000) {
1218 char *mnemonic = NULL;
1219 uint8_t Rm, Rs, RdHi, RdLow, S;
1221 Rs = (opcode & 0xf00) >> 8;
1222 RdHi = (opcode & 0xf000) >> 12;
1223 RdLow = (opcode & 0xf0000) >> 16;
1224 S = (opcode & 0x00100000) >> 20;
1226 switch ((opcode & 0x00600000) >> 21) {
1228 instruction->type = ARM_UMULL;
1232 instruction->type = ARM_UMLAL;
1236 instruction->type = ARM_SMULL;
1240 instruction->type = ARM_SMLAL;
1245 snprintf(instruction->text,
1247 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, r%i, r%i",
1261 /* Swap/swap byte */
1262 if ((opcode & 0x0f800000) == 0x01000000) {
1265 Rd = (opcode & 0xf000) >> 12;
1266 Rn = (opcode & 0xf0000) >> 16;
1268 /* examine B flag */
1269 instruction->type = (opcode & 0x00400000) ? ARM_SWPB : ARM_SWP;
1271 snprintf(instruction->text,
1273 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, [r%i]",
1276 (opcode & 0x00400000) ? "SWPB" : "SWP",
1286 return evaluate_misc_load_store(opcode, address, instruction);
1289 static int evaluate_mrs_msr(uint32_t opcode,
1290 uint32_t address, struct arm_instruction *instruction)
1292 int R = (opcode & 0x00400000) >> 22;
1293 char *PSR = (R) ? "SPSR" : "CPSR";
1295 /* Move register to status register (MSR) */
1296 if (opcode & 0x00200000) {
1297 instruction->type = ARM_MSR;
1299 /* immediate variant */
1300 if (opcode & 0x02000000) {
1301 uint8_t immediate = (opcode & 0xff);
1302 uint8_t rotate = (opcode & 0xf00);
1304 snprintf(instruction->text,
1306 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, 0x%8.8" PRIx32,
1311 (opcode & 0x10000) ? "c" : "",
1312 (opcode & 0x20000) ? "x" : "",
1313 (opcode & 0x40000) ? "s" : "",
1314 (opcode & 0x80000) ? "f" : "",
1315 ror(immediate, (rotate * 2))
1317 } else {/* register variant */
1318 uint8_t Rm = opcode & 0xf;
1319 snprintf(instruction->text,
1321 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, r%i",
1326 (opcode & 0x10000) ? "c" : "",
1327 (opcode & 0x20000) ? "x" : "",
1328 (opcode & 0x40000) ? "s" : "",
1329 (opcode & 0x80000) ? "f" : "",
1334 } else {/* Move status register to register (MRS) */
1337 instruction->type = ARM_MRS;
1338 Rd = (opcode & 0x0000f000) >> 12;
1340 snprintf(instruction->text,
1342 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMRS%s r%i, %s",
1353 /* Miscellaneous instructions */
1354 static int evaluate_misc_instr(uint32_t opcode,
1355 uint32_t address, struct arm_instruction *instruction)
1358 if ((opcode & 0x000000f0) == 0x00000000)
1359 evaluate_mrs_msr(opcode, address, instruction);
1362 if ((opcode & 0x006000f0) == 0x00200010) {
1364 instruction->type = ARM_BX;
1367 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBX%s r%i",
1368 address, opcode, COND(opcode), Rm);
1370 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1371 instruction->info.b_bl_bx_blx.target_address = -1;
1374 /* BXJ - "Jazelle" support (ARMv5-J) */
1375 if ((opcode & 0x006000f0) == 0x00200020) {
1377 instruction->type = ARM_BX;
1380 snprintf(instruction->text, 128,
1381 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBXJ%s r%i",
1382 address, opcode, COND(opcode), Rm);
1384 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1385 instruction->info.b_bl_bx_blx.target_address = -1;
1389 if ((opcode & 0x006000f0) == 0x00600010) {
1391 instruction->type = ARM_CLZ;
1393 Rd = (opcode & 0xf000) >> 12;
1395 snprintf(instruction->text,
1397 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCLZ%s r%i, r%i",
1406 if ((opcode & 0x006000f0) == 0x00200030) {
1408 instruction->type = ARM_BLX;
1411 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX%s r%i",
1412 address, opcode, COND(opcode), Rm);
1414 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1415 instruction->info.b_bl_bx_blx.target_address = -1;
1418 /* Enhanced DSP add/subtracts */
1419 if ((opcode & 0x0000000f0) == 0x00000050) {
1421 char *mnemonic = NULL;
1423 Rd = (opcode & 0xf000) >> 12;
1424 Rn = (opcode & 0xf0000) >> 16;
1426 switch ((opcode & 0x00600000) >> 21) {
1428 instruction->type = ARM_QADD;
1432 instruction->type = ARM_QSUB;
1436 instruction->type = ARM_QDADD;
1440 instruction->type = ARM_QDSUB;
1445 snprintf(instruction->text,
1447 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, r%i",
1457 /* exception return */
1458 if ((opcode & 0x0000000f0) == 0x00000060) {
1459 if (((opcode & 0x600000) >> 21) == 3)
1460 instruction->type = ARM_ERET;
1461 snprintf(instruction->text,
1463 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tERET",
1468 /* exception generate instructions */
1469 if ((opcode & 0x0000000f0) == 0x00000070) {
1470 uint32_t immediate = 0;
1471 char *mnemonic = NULL;
1473 switch ((opcode & 0x600000) >> 21) {
1475 instruction->type = ARM_BKPT;
1477 immediate = ((opcode & 0x000fff00) >> 4) | (opcode & 0xf);
1480 instruction->type = ARM_HVC;
1482 immediate = ((opcode & 0x000fff00) >> 4) | (opcode & 0xf);
1485 instruction->type = ARM_SMC;
1487 immediate = (opcode & 0xf);
1491 snprintf(instruction->text,
1493 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s 0x%4.4" PRIx32 "",
1500 /* Enhanced DSP multiplies */
1501 if ((opcode & 0x000000090) == 0x00000080) {
1502 int x = (opcode & 0x20) >> 5;
1503 int y = (opcode & 0x40) >> 6;
1506 if ((opcode & 0x00600000) == 0x00000000) {
1507 uint8_t Rd, Rm, Rs, Rn;
1508 instruction->type = ARM_SMLAxy;
1509 Rd = (opcode & 0xf0000) >> 16;
1510 Rm = (opcode & 0xf);
1511 Rs = (opcode & 0xf00) >> 8;
1512 Rn = (opcode & 0xf000) >> 12;
1514 snprintf(instruction->text,
1516 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
1529 if ((opcode & 0x00600000) == 0x00400000) {
1530 uint8_t RdLow, RdHi, Rm, Rs;
1531 instruction->type = ARM_SMLAxy;
1532 RdHi = (opcode & 0xf0000) >> 16;
1533 RdLow = (opcode & 0xf000) >> 12;
1534 Rm = (opcode & 0xf);
1535 Rs = (opcode & 0xf00) >> 8;
1537 snprintf(instruction->text,
1539 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
1552 if (((opcode & 0x00600000) == 0x00100000) && (x == 0)) {
1553 uint8_t Rd, Rm, Rs, Rn;
1554 instruction->type = ARM_SMLAWy;
1555 Rd = (opcode & 0xf0000) >> 16;
1556 Rm = (opcode & 0xf);
1557 Rs = (opcode & 0xf00) >> 8;
1558 Rn = (opcode & 0xf000) >> 12;
1560 snprintf(instruction->text,
1562 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLAW%s%s r%i, r%i, r%i, r%i",
1574 if ((opcode & 0x00600000) == 0x00300000) {
1576 instruction->type = ARM_SMULxy;
1577 Rd = (opcode & 0xf0000) >> 16;
1578 Rm = (opcode & 0xf);
1579 Rs = (opcode & 0xf00) >> 8;
1581 snprintf(instruction->text,
1583 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s%s r%i, r%i, r%i",
1595 if (((opcode & 0x00600000) == 0x00100000) && (x == 1)) {
1597 instruction->type = ARM_SMULWy;
1598 Rd = (opcode & 0xf0000) >> 16;
1599 Rm = (opcode & 0xf);
1600 Rs = (opcode & 0xf00) >> 8;
1602 snprintf(instruction->text,
1604 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s r%i, r%i, r%i",
1618 static int evaluate_data_proc(uint32_t opcode,
1619 uint32_t address, struct arm_instruction *instruction)
1621 uint8_t I, op, S, Rn, Rd;
1622 char *mnemonic = NULL;
1623 char shifter_operand[32];
1625 I = (opcode & 0x02000000) >> 25;
1626 op = (opcode & 0x01e00000) >> 21;
1627 S = (opcode & 0x00100000) >> 20;
1629 Rd = (opcode & 0xf000) >> 12;
1630 Rn = (opcode & 0xf0000) >> 16;
1632 instruction->info.data_proc.Rd = Rd;
1633 instruction->info.data_proc.Rn = Rn;
1634 instruction->info.data_proc.S = S;
1638 instruction->type = ARM_AND;
1642 instruction->type = ARM_EOR;
1646 instruction->type = ARM_SUB;
1650 instruction->type = ARM_RSB;
1654 instruction->type = ARM_ADD;
1658 instruction->type = ARM_ADC;
1662 instruction->type = ARM_SBC;
1666 instruction->type = ARM_RSC;
1670 instruction->type = ARM_TST;
1674 instruction->type = ARM_TEQ;
1678 instruction->type = ARM_CMP;
1682 instruction->type = ARM_CMN;
1686 instruction->type = ARM_ORR;
1690 instruction->type = ARM_MOV;
1694 instruction->type = ARM_BIC;
1698 instruction->type = ARM_MVN;
1703 if (I) {/* immediate shifter operand (#<immediate>)*/
1704 uint8_t immed_8 = opcode & 0xff;
1705 uint8_t rotate_imm = (opcode & 0xf00) >> 8;
1708 immediate = ror(immed_8, rotate_imm * 2);
1710 snprintf(shifter_operand, 32, "#0x%" PRIx32 "", immediate);
1712 instruction->info.data_proc.variant = 0;
1713 instruction->info.data_proc.shifter_operand.immediate.immediate = immediate;
1714 } else {/* register-based shifter operand */
1716 shift = (opcode & 0x60) >> 5;
1717 Rm = (opcode & 0xf);
1719 if ((opcode & 0x10) != 0x10) { /* Immediate shifts ("<Rm>" or "<Rm>, <shift>
1720 *#<shift_immediate>") */
1722 shift_imm = (opcode & 0xf80) >> 7;
1724 instruction->info.data_proc.variant = 1;
1725 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1726 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm =
1728 instruction->info.data_proc.shifter_operand.immediate_shift.shift = shift;
1730 /* LSR encodes a shift by 32 bit as 0x0 */
1731 if ((shift == 0x1) && (shift_imm == 0x0))
1734 /* ASR encodes a shift by 32 bit as 0x0 */
1735 if ((shift == 0x2) && (shift_imm == 0x0))
1738 /* ROR by 32 bit is actually a RRX */
1739 if ((shift == 0x3) && (shift_imm == 0x0))
1742 if ((shift_imm == 0x0) && (shift == 0x0))
1743 snprintf(shifter_operand, 32, "r%i", Rm);
1745 if (shift == 0x0) /* LSL */
1746 snprintf(shifter_operand,
1751 else if (shift == 0x1) /* LSR */
1752 snprintf(shifter_operand,
1757 else if (shift == 0x2) /* ASR */
1758 snprintf(shifter_operand,
1763 else if (shift == 0x3) /* ROR */
1764 snprintf(shifter_operand,
1769 else if (shift == 0x4) /* RRX */
1770 snprintf(shifter_operand, 32, "r%i, RRX", Rm);
1772 } else {/* Register shifts ("<Rm>, <shift> <Rs>") */
1773 uint8_t Rs = (opcode & 0xf00) >> 8;
1775 instruction->info.data_proc.variant = 2;
1776 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rm;
1777 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rs;
1778 instruction->info.data_proc.shifter_operand.register_shift.shift = shift;
1780 if (shift == 0x0) /* LSL */
1781 snprintf(shifter_operand, 32, "r%i, LSL r%i", Rm, Rs);
1782 else if (shift == 0x1) /* LSR */
1783 snprintf(shifter_operand, 32, "r%i, LSR r%i", Rm, Rs);
1784 else if (shift == 0x2) /* ASR */
1785 snprintf(shifter_operand, 32, "r%i, ASR r%i", Rm, Rs);
1786 else if (shift == 0x3) /* ROR */
1787 snprintf(shifter_operand, 32, "r%i, ROR r%i", Rm, Rs);
1791 if ((op < 0x8) || (op == 0xc) || (op == 0xe)) { /* <opcode3>{<cond>}{S} <Rd>, <Rn>,
1792 *<shifter_operand> */
1793 snprintf(instruction->text,
1795 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, %s",
1804 } else if ((op == 0xd) || (op == 0xf)) { /* <opcode1>{<cond>}{S} <Rd>,
1805 *<shifter_operand> */
1806 if (opcode == 0xe1a00000) /* print MOV r0,r0 as NOP */
1807 snprintf(instruction->text,
1809 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tNOP",
1813 snprintf(instruction->text,
1815 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, %s",
1823 } else {/* <opcode2>{<cond>} <Rn>, <shifter_operand> */
1824 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, %s",
1825 address, opcode, mnemonic, COND(opcode),
1826 Rn, shifter_operand);
1832 int arm_evaluate_opcode(uint32_t opcode, uint32_t address,
1833 struct arm_instruction *instruction)
1835 /* clear fields, to avoid confusion */
1836 memset(instruction, 0, sizeof(struct arm_instruction));
1837 instruction->opcode = opcode;
1838 instruction->instruction_size = 4;
1840 /* catch opcodes with condition field [31:28] = b1111 */
1841 if ((opcode & 0xf0000000) == 0xf0000000) {
1842 /* Undefined instruction (or ARMv5E cache preload PLD) */
1843 if ((opcode & 0x08000000) == 0x00000000)
1844 return evaluate_pld(opcode, address, instruction);
1846 /* Undefined instruction (or ARMv6+ SRS/RFE) */
1847 if ((opcode & 0x0e000000) == 0x08000000)
1848 return evaluate_srs(opcode, address, instruction);
1850 /* Branch and branch with link and change to Thumb */
1851 if ((opcode & 0x0e000000) == 0x0a000000)
1852 return evaluate_blx_imm(opcode, address, instruction);
1854 /* Extended coprocessor opcode space (ARMv5 and higher)
1855 * Coprocessor load/store and double register transfers */
1856 if ((opcode & 0x0e000000) == 0x0c000000)
1857 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1859 /* Coprocessor data processing */
1860 if ((opcode & 0x0f000100) == 0x0c000000)
1861 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1863 /* Coprocessor register transfers */
1864 if ((opcode & 0x0f000010) == 0x0c000010)
1865 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1867 /* Undefined instruction */
1868 if ((opcode & 0x0f000000) == 0x0f000000) {
1869 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1870 snprintf(instruction->text,
1872 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
1879 /* catch opcodes with [27:25] = b000 */
1880 if ((opcode & 0x0e000000) == 0x00000000) {
1881 /* Multiplies, extra load/stores */
1882 if ((opcode & 0x00000090) == 0x00000090)
1883 return evaluate_mul_and_extra_ld_st(opcode, address, instruction);
1885 /* Miscellaneous instructions */
1886 if ((opcode & 0x0f900000) == 0x01000000)
1887 return evaluate_misc_instr(opcode, address, instruction);
1889 return evaluate_data_proc(opcode, address, instruction);
1892 /* catch opcodes with [27:25] = b001 */
1893 if ((opcode & 0x0e000000) == 0x02000000) {
1894 /* Undefined instruction */
1895 if ((opcode & 0x0fb00000) == 0x03000000) {
1896 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1897 snprintf(instruction->text,
1899 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
1905 /* Move immediate to status register */
1906 if ((opcode & 0x0fb00000) == 0x03200000)
1907 return evaluate_mrs_msr(opcode, address, instruction);
1909 return evaluate_data_proc(opcode, address, instruction);
1913 /* catch opcodes with [27:25] = b010 */
1914 if ((opcode & 0x0e000000) == 0x04000000) {
1915 /* Load/store immediate offset */
1916 return evaluate_load_store(opcode, address, instruction);
1919 /* catch opcodes with [27:25] = b011 */
1920 if ((opcode & 0x0e000000) == 0x06000000) {
1921 /* Load/store register offset */
1922 if ((opcode & 0x00000010) == 0x00000000)
1923 return evaluate_load_store(opcode, address, instruction);
1925 /* Architecturally Undefined instruction
1926 * ... don't expect these to ever be used
1928 if ((opcode & 0x07f000f0) == 0x07f000f0) {
1929 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1930 snprintf(instruction->text, 128,
1931 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEF",
1936 /* "media" instructions */
1937 return evaluate_media(opcode, address, instruction);
1940 /* catch opcodes with [27:25] = b100 */
1941 if ((opcode & 0x0e000000) == 0x08000000) {
1942 /* Load/store multiple */
1943 return evaluate_ldm_stm(opcode, address, instruction);
1946 /* catch opcodes with [27:25] = b101 */
1947 if ((opcode & 0x0e000000) == 0x0a000000) {
1948 /* Branch and branch with link */
1949 return evaluate_b_bl(opcode, address, instruction);
1952 /* catch opcodes with [27:25] = b110 */
1953 if ((opcode & 0x0e000000) == 0x0c000000) {
1954 /* Coprocessor load/store and double register transfers */
1955 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1958 /* catch opcodes with [27:25] = b111 */
1959 if ((opcode & 0x0e000000) == 0x0e000000) {
1960 /* Software interrupt */
1961 if ((opcode & 0x0f000000) == 0x0f000000)
1962 return evaluate_swi(opcode, address, instruction);
1964 /* Coprocessor data processing */
1965 if ((opcode & 0x0f000010) == 0x0e000000)
1966 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1968 /* Coprocessor register transfers */
1969 if ((opcode & 0x0f000010) == 0x0e000010)
1970 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1973 LOG_ERROR("ARM: should never reach this point (opcode=%08x)",
1978 static int evaluate_b_bl_blx_thumb(uint16_t opcode,
1979 uint32_t address, struct arm_instruction *instruction)
1981 uint32_t offset = opcode & 0x7ff;
1982 uint32_t opc = (opcode >> 11) & 0x3;
1983 uint32_t target_address;
1984 char *mnemonic = NULL;
1986 /* sign extend 11-bit offset */
1987 if (((opc == 0) || (opc == 2)) && (offset & 0x00000400))
1988 offset = 0xfffff800 | offset;
1990 target_address = address + 4 + (offset << 1);
1993 /* unconditional branch */
1995 instruction->type = ARM_B;
2000 instruction->type = ARM_BLX;
2002 target_address &= 0xfffffffc;
2006 instruction->type = ARM_UNKNOWN_INSTUCTION;
2007 mnemonic = "prefix";
2008 target_address = offset << 12;
2012 instruction->type = ARM_BL;
2017 /* TODO: deal correctly with dual opcode (prefixed) BL/BLX;
2018 * these are effectively 32-bit instructions even in Thumb1. For
2019 * disassembly, it's simplest to always use the Thumb2 decoder.
2021 * But some cores will evidently handle them as two instructions,
2022 * where exceptions may occur between the two. The ETMv3.2+ ID
2023 * register has a bit which exposes this behavior.
2026 snprintf(instruction->text, 128,
2027 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%#8.8" PRIx32,
2028 address, opcode, mnemonic, target_address);
2030 instruction->info.b_bl_bx_blx.reg_operand = -1;
2031 instruction->info.b_bl_bx_blx.target_address = target_address;
2036 static int evaluate_add_sub_thumb(uint16_t opcode,
2037 uint32_t address, struct arm_instruction *instruction)
2039 uint8_t Rd = (opcode >> 0) & 0x7;
2040 uint8_t Rn = (opcode >> 3) & 0x7;
2041 uint8_t Rm_imm = (opcode >> 6) & 0x7;
2042 uint32_t opc = opcode & (1 << 9);
2043 uint32_t reg_imm = opcode & (1 << 10);
2047 instruction->type = ARM_SUB;
2050 /* REVISIT: if reg_imm == 0, display as "MOVS" */
2051 instruction->type = ARM_ADD;
2055 instruction->info.data_proc.Rd = Rd;
2056 instruction->info.data_proc.Rn = Rn;
2057 instruction->info.data_proc.S = 1;
2060 instruction->info.data_proc.variant = 0;/*immediate*/
2061 instruction->info.data_proc.shifter_operand.immediate.immediate = Rm_imm;
2062 snprintf(instruction->text, 128,
2063 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%d",
2064 address, opcode, mnemonic, Rd, Rn, Rm_imm);
2066 instruction->info.data_proc.variant = 1;/*immediate shift*/
2067 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm_imm;
2068 snprintf(instruction->text, 128,
2069 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, r%i",
2070 address, opcode, mnemonic, Rd, Rn, Rm_imm);
2076 static int evaluate_shift_imm_thumb(uint16_t opcode,
2077 uint32_t address, struct arm_instruction *instruction)
2079 uint8_t Rd = (opcode >> 0) & 0x7;
2080 uint8_t Rm = (opcode >> 3) & 0x7;
2081 uint8_t imm = (opcode >> 6) & 0x1f;
2082 uint8_t opc = (opcode >> 11) & 0x3;
2083 char *mnemonic = NULL;
2087 instruction->type = ARM_MOV;
2089 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 0;
2092 instruction->type = ARM_MOV;
2094 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 1;
2097 instruction->type = ARM_MOV;
2099 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 2;
2103 if ((imm == 0) && (opc != 0))
2106 instruction->info.data_proc.Rd = Rd;
2107 instruction->info.data_proc.Rn = -1;
2108 instruction->info.data_proc.S = 1;
2110 instruction->info.data_proc.variant = 1;/*immediate_shift*/
2111 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
2112 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = imm;
2114 snprintf(instruction->text, 128,
2115 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%#2.2x",
2116 address, opcode, mnemonic, Rd, Rm, imm);
2121 static int evaluate_data_proc_imm_thumb(uint16_t opcode,
2122 uint32_t address, struct arm_instruction *instruction)
2124 uint8_t imm = opcode & 0xff;
2125 uint8_t Rd = (opcode >> 8) & 0x7;
2126 uint32_t opc = (opcode >> 11) & 0x3;
2127 char *mnemonic = NULL;
2129 instruction->info.data_proc.Rd = Rd;
2130 instruction->info.data_proc.Rn = Rd;
2131 instruction->info.data_proc.S = 1;
2132 instruction->info.data_proc.variant = 0;/*immediate*/
2133 instruction->info.data_proc.shifter_operand.immediate.immediate = imm;
2137 instruction->type = ARM_MOV;
2139 instruction->info.data_proc.Rn = -1;
2142 instruction->type = ARM_CMP;
2144 instruction->info.data_proc.Rd = -1;
2147 instruction->type = ARM_ADD;
2151 instruction->type = ARM_SUB;
2156 snprintf(instruction->text, 128,
2157 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, #%#2.2x",
2158 address, opcode, mnemonic, Rd, imm);
2163 static int evaluate_data_proc_thumb(uint16_t opcode,
2164 uint32_t address, struct arm_instruction *instruction)
2166 uint8_t high_reg, op, Rm, Rd, H1, H2;
2167 char *mnemonic = NULL;
2170 high_reg = (opcode & 0x0400) >> 10;
2171 op = (opcode & 0x03C0) >> 6;
2173 Rd = (opcode & 0x0007);
2174 Rm = (opcode & 0x0038) >> 3;
2175 H1 = (opcode & 0x0080) >> 7;
2176 H2 = (opcode & 0x0040) >> 6;
2178 instruction->info.data_proc.Rd = Rd;
2179 instruction->info.data_proc.Rn = Rd;
2180 instruction->info.data_proc.S = (!high_reg || (instruction->type == ARM_CMP));
2181 instruction->info.data_proc.variant = 1 /*immediate shift*/;
2182 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
2191 instruction->type = ARM_ADD;
2195 instruction->type = ARM_CMP;
2199 instruction->type = ARM_MOV;
2205 if ((opcode & 0x7) == 0x0) {
2206 instruction->info.b_bl_bx_blx.reg_operand = Rm;
2208 instruction->type = ARM_BLX;
2209 snprintf(instruction->text, 128,
2211 " 0x%4.4x \tBLX\tr%i",
2212 address, opcode, Rm);
2214 instruction->type = ARM_BX;
2215 snprintf(instruction->text, 128,
2217 " 0x%4.4x \tBX\tr%i",
2218 address, opcode, Rm);
2221 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2222 snprintf(instruction->text, 128,
2225 "UNDEFINED INSTRUCTION",
2234 instruction->type = ARM_AND;
2238 instruction->type = ARM_EOR;
2242 instruction->type = ARM_MOV;
2244 instruction->info.data_proc.variant = 2 /*register shift*/;
2245 instruction->info.data_proc.shifter_operand.register_shift.shift = 0;
2246 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
2247 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
2250 instruction->type = ARM_MOV;
2252 instruction->info.data_proc.variant = 2 /*register shift*/;
2253 instruction->info.data_proc.shifter_operand.register_shift.shift = 1;
2254 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
2255 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
2258 instruction->type = ARM_MOV;
2260 instruction->info.data_proc.variant = 2 /*register shift*/;
2261 instruction->info.data_proc.shifter_operand.register_shift.shift = 2;
2262 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
2263 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
2266 instruction->type = ARM_ADC;
2270 instruction->type = ARM_SBC;
2274 instruction->type = ARM_MOV;
2276 instruction->info.data_proc.variant = 2 /*register shift*/;
2277 instruction->info.data_proc.shifter_operand.register_shift.shift = 3;
2278 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
2279 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
2282 instruction->type = ARM_TST;
2286 instruction->type = ARM_RSB;
2288 instruction->info.data_proc.variant = 0 /*immediate*/;
2289 instruction->info.data_proc.shifter_operand.immediate.immediate = 0;
2290 instruction->info.data_proc.Rn = Rm;
2293 instruction->type = ARM_CMP;
2297 instruction->type = ARM_CMN;
2301 instruction->type = ARM_ORR;
2305 instruction->type = ARM_MUL;
2309 instruction->type = ARM_BIC;
2313 instruction->type = ARM_MVN;
2320 snprintf(instruction->text, 128,
2321 "0x%8.8" PRIx32 " 0x%4.4x \tNOP\t\t\t"
2323 address, opcode, mnemonic, Rd, Rm);
2325 snprintf(instruction->text, 128,
2326 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i",
2327 address, opcode, mnemonic, Rd, Rm);
2332 /* PC-relative data addressing is word-aligned even with Thumb */
2333 static inline uint32_t thumb_alignpc4(uint32_t addr)
2335 return (addr + 4) & ~3;
2338 static int evaluate_load_literal_thumb(uint16_t opcode,
2339 uint32_t address, struct arm_instruction *instruction)
2342 uint8_t Rd = (opcode >> 8) & 0x7;
2344 instruction->type = ARM_LDR;
2345 immediate = opcode & 0x000000ff;
2348 instruction->info.load_store.Rd = Rd;
2349 instruction->info.load_store.Rn = 15 /*PC*/;
2350 instruction->info.load_store.index_mode = 0; /*offset*/
2351 instruction->info.load_store.offset_mode = 0; /*immediate*/
2352 instruction->info.load_store.offset.offset = immediate;
2354 snprintf(instruction->text, 128,
2355 "0x%8.8" PRIx32 " 0x%4.4x \t"
2356 "LDR\tr%i, [pc, #%#" PRIx32 "]\t; %#8.8" PRIx32,
2357 address, opcode, Rd, immediate,
2358 thumb_alignpc4(address) + immediate);
2363 static int evaluate_load_store_reg_thumb(uint16_t opcode,
2364 uint32_t address, struct arm_instruction *instruction)
2366 uint8_t Rd = (opcode >> 0) & 0x7;
2367 uint8_t Rn = (opcode >> 3) & 0x7;
2368 uint8_t Rm = (opcode >> 6) & 0x7;
2369 uint8_t opc = (opcode >> 9) & 0x7;
2370 char *mnemonic = NULL;
2374 instruction->type = ARM_STR;
2378 instruction->type = ARM_STRH;
2382 instruction->type = ARM_STRB;
2386 instruction->type = ARM_LDRSB;
2390 instruction->type = ARM_LDR;
2394 instruction->type = ARM_LDRH;
2398 instruction->type = ARM_LDRB;
2402 instruction->type = ARM_LDRSH;
2407 snprintf(instruction->text, 128,
2408 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [r%i, r%i]",
2409 address, opcode, mnemonic, Rd, Rn, Rm);
2411 instruction->info.load_store.Rd = Rd;
2412 instruction->info.load_store.Rn = Rn;
2413 instruction->info.load_store.index_mode = 0; /*offset*/
2414 instruction->info.load_store.offset_mode = 1; /*register*/
2415 instruction->info.load_store.offset.reg.Rm = Rm;
2420 static int evaluate_load_store_imm_thumb(uint16_t opcode,
2421 uint32_t address, struct arm_instruction *instruction)
2423 uint32_t offset = (opcode >> 6) & 0x1f;
2424 uint8_t Rd = (opcode >> 0) & 0x7;
2425 uint8_t Rn = (opcode >> 3) & 0x7;
2426 uint32_t L = opcode & (1 << 11);
2427 uint32_t B = opcode & (1 << 12);
2433 instruction->type = ARM_LDR;
2436 instruction->type = ARM_STR;
2440 if ((opcode&0xF000) == 0x8000) {
2448 snprintf(instruction->text, 128,
2449 "0x%8.8" PRIx32 " 0x%4.4x \t%s%c\tr%i, [r%i, #%#" PRIx32 "]",
2450 address, opcode, mnemonic, suffix, Rd, Rn, offset << shift);
2452 instruction->info.load_store.Rd = Rd;
2453 instruction->info.load_store.Rn = Rn;
2454 instruction->info.load_store.index_mode = 0; /*offset*/
2455 instruction->info.load_store.offset_mode = 0; /*immediate*/
2456 instruction->info.load_store.offset.offset = offset << shift;
2461 static int evaluate_load_store_stack_thumb(uint16_t opcode,
2462 uint32_t address, struct arm_instruction *instruction)
2464 uint32_t offset = opcode & 0xff;
2465 uint8_t Rd = (opcode >> 8) & 0x7;
2466 uint32_t L = opcode & (1 << 11);
2470 instruction->type = ARM_LDR;
2473 instruction->type = ARM_STR;
2477 snprintf(instruction->text, 128,
2478 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [SP, #%#" PRIx32 "]",
2479 address, opcode, mnemonic, Rd, offset*4);
2481 instruction->info.load_store.Rd = Rd;
2482 instruction->info.load_store.Rn = 13 /*SP*/;
2483 instruction->info.load_store.index_mode = 0; /*offset*/
2484 instruction->info.load_store.offset_mode = 0; /*immediate*/
2485 instruction->info.load_store.offset.offset = offset*4;
2490 static int evaluate_add_sp_pc_thumb(uint16_t opcode,
2491 uint32_t address, struct arm_instruction *instruction)
2493 uint32_t imm = opcode & 0xff;
2494 uint8_t Rd = (opcode >> 8) & 0x7;
2496 uint32_t SP = opcode & (1 << 11);
2497 const char *reg_name;
2499 instruction->type = ARM_ADD;
2509 snprintf(instruction->text, 128,
2510 "0x%8.8" PRIx32 " 0x%4.4x \tADD\tr%i, %s, #%#" PRIx32,
2511 address, opcode, Rd, reg_name, imm * 4);
2513 instruction->info.data_proc.variant = 0 /* immediate */;
2514 instruction->info.data_proc.Rd = Rd;
2515 instruction->info.data_proc.Rn = Rn;
2516 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
2521 static int evaluate_adjust_stack_thumb(uint16_t opcode,
2522 uint32_t address, struct arm_instruction *instruction)
2524 uint32_t imm = opcode & 0x7f;
2525 uint8_t opc = opcode & (1 << 7);
2530 instruction->type = ARM_SUB;
2533 instruction->type = ARM_ADD;
2537 snprintf(instruction->text, 128,
2538 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tSP, #%#" PRIx32,
2539 address, opcode, mnemonic, imm*4);
2541 instruction->info.data_proc.variant = 0 /* immediate */;
2542 instruction->info.data_proc.Rd = 13 /*SP*/;
2543 instruction->info.data_proc.Rn = 13 /*SP*/;
2544 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
2549 static int evaluate_breakpoint_thumb(uint16_t opcode,
2550 uint32_t address, struct arm_instruction *instruction)
2552 uint32_t imm = opcode & 0xff;
2554 instruction->type = ARM_BKPT;
2556 snprintf(instruction->text, 128,
2557 "0x%8.8" PRIx32 " 0x%4.4x \tBKPT\t%#2.2" PRIx32 "",
2558 address, opcode, imm);
2563 static int evaluate_load_store_multiple_thumb(uint16_t opcode,
2564 uint32_t address, struct arm_instruction *instruction)
2566 uint32_t reg_list = opcode & 0xff;
2567 uint32_t L = opcode & (1 << 11);
2568 uint32_t R = opcode & (1 << 8);
2569 uint8_t Rn = (opcode >> 8) & 7;
2570 uint8_t addr_mode = 0 /* IA */;
2574 char ptr_name[7] = "";
2577 /* REVISIT: in ThumbEE mode, there are no LDM or STM instructions.
2578 * The STMIA and LDMIA opcodes are used for other instructions.
2581 if ((opcode & 0xf000) == 0xc000) { /* generic load/store multiple */
2585 instruction->type = ARM_LDM;
2587 if (opcode & (1 << Rn))
2590 instruction->type = ARM_STM;
2593 snprintf(ptr_name, sizeof ptr_name, "r%i%s, ", Rn, wback);
2594 } else {/* push/pop */
2597 instruction->type = ARM_LDM;
2600 reg_list |= (1 << 15) /*PC*/;
2602 instruction->type = ARM_STM;
2604 addr_mode = 3; /*DB*/
2606 reg_list |= (1 << 14) /*LR*/;
2610 reg_names_p = reg_names;
2611 for (i = 0; i <= 15; i++) {
2612 if (reg_list & (1 << i))
2613 reg_names_p += snprintf(reg_names_p,
2614 (reg_names + 40 - reg_names_p),
2618 if (reg_names_p > reg_names)
2619 reg_names_p[-2] = '\0';
2620 else /* invalid op : no registers */
2621 reg_names[0] = '\0';
2623 snprintf(instruction->text, 128,
2624 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%s{%s}",
2625 address, opcode, mnemonic, ptr_name, reg_names);
2627 instruction->info.load_store_multiple.register_list = reg_list;
2628 instruction->info.load_store_multiple.Rn = Rn;
2629 instruction->info.load_store_multiple.addressing_mode = addr_mode;
2634 static int evaluate_cond_branch_thumb(uint16_t opcode,
2635 uint32_t address, struct arm_instruction *instruction)
2637 uint32_t offset = opcode & 0xff;
2638 uint8_t cond = (opcode >> 8) & 0xf;
2639 uint32_t target_address;
2642 instruction->type = ARM_SWI;
2643 snprintf(instruction->text, 128,
2644 "0x%8.8" PRIx32 " 0x%4.4x \tSVC\t%#2.2" PRIx32,
2645 address, opcode, offset);
2647 } else if (cond == 0xe) {
2648 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2649 snprintf(instruction->text, 128,
2650 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2655 /* sign extend 8-bit offset */
2656 if (offset & 0x00000080)
2657 offset = 0xffffff00 | offset;
2659 target_address = address + 4 + (offset << 1);
2661 snprintf(instruction->text, 128,
2662 "0x%8.8" PRIx32 " 0x%4.4x \tB%s\t%#8.8" PRIx32,
2664 arm_condition_strings[cond], target_address);
2666 instruction->type = ARM_B;
2667 instruction->info.b_bl_bx_blx.reg_operand = -1;
2668 instruction->info.b_bl_bx_blx.target_address = target_address;
2673 static int evaluate_cb_thumb(uint16_t opcode, uint32_t address,
2674 struct arm_instruction *instruction)
2678 /* added in Thumb2 */
2679 offset = (opcode >> 3) & 0x1f;
2680 offset |= (opcode & 0x0200) >> 4;
2682 snprintf(instruction->text, 128,
2683 "0x%8.8" PRIx32 " 0x%4.4x \tCB%sZ\tr%d, %#8.8" PRIx32,
2685 (opcode & 0x0800) ? "N" : "",
2686 opcode & 0x7, address + 4 + (offset << 1));
2691 static int evaluate_extend_thumb(uint16_t opcode, uint32_t address,
2692 struct arm_instruction *instruction)
2694 /* added in ARMv6 */
2695 snprintf(instruction->text, 128,
2696 "0x%8.8" PRIx32 " 0x%4.4x \t%cXT%c\tr%d, r%d",
2698 (opcode & 0x0080) ? 'U' : 'S',
2699 (opcode & 0x0040) ? 'B' : 'H',
2700 opcode & 0x7, (opcode >> 3) & 0x7);
2705 static int evaluate_cps_thumb(uint16_t opcode, uint32_t address,
2706 struct arm_instruction *instruction)
2708 /* added in ARMv6 */
2709 if ((opcode & 0x0ff0) == 0x0650)
2710 snprintf(instruction->text, 128,
2711 "0x%8.8" PRIx32 " 0x%4.4x \tSETEND %s",
2713 (opcode & 0x80) ? "BE" : "LE");
2714 else /* ASSUME (opcode & 0x0fe0) == 0x0660 */
2715 snprintf(instruction->text, 128,
2716 "0x%8.8" PRIx32 " 0x%4.4x \tCPSI%c\t%s%s%s",
2718 (opcode & 0x0010) ? 'D' : 'E',
2719 (opcode & 0x0004) ? "A" : "",
2720 (opcode & 0x0002) ? "I" : "",
2721 (opcode & 0x0001) ? "F" : "");
2726 static int evaluate_byterev_thumb(uint16_t opcode, uint32_t address,
2727 struct arm_instruction *instruction)
2731 /* added in ARMv6 */
2732 switch ((opcode >> 6) & 3) {
2743 snprintf(instruction->text, 128,
2744 "0x%8.8" PRIx32 " 0x%4.4x \tREV%s\tr%d, r%d",
2745 address, opcode, suffix,
2746 opcode & 0x7, (opcode >> 3) & 0x7);
2751 static int evaluate_hint_thumb(uint16_t opcode, uint32_t address,
2752 struct arm_instruction *instruction)
2756 switch ((opcode >> 4) & 0x0f) {
2773 hint = "HINT (UNRECOGNIZED)";
2777 snprintf(instruction->text, 128,
2778 "0x%8.8" PRIx32 " 0x%4.4x \t%s",
2779 address, opcode, hint);
2784 static int evaluate_ifthen_thumb(uint16_t opcode, uint32_t address,
2785 struct arm_instruction *instruction)
2787 unsigned cond = (opcode >> 4) & 0x0f;
2788 char *x = "", *y = "", *z = "";
2791 z = (opcode & 0x02) ? "T" : "E";
2793 y = (opcode & 0x04) ? "T" : "E";
2795 x = (opcode & 0x08) ? "T" : "E";
2797 snprintf(instruction->text, 128,
2798 "0x%8.8" PRIx32 " 0x%4.4x \tIT%s%s%s\t%s",
2800 x, y, z, arm_condition_strings[cond]);
2802 /* NOTE: strictly speaking, the next 1-4 instructions should
2803 * now be displayed with the relevant conditional suffix...
2809 int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
2811 /* clear fields, to avoid confusion */
2812 memset(instruction, 0, sizeof(struct arm_instruction));
2813 instruction->opcode = opcode;
2814 instruction->instruction_size = 2;
2816 if ((opcode & 0xe000) == 0x0000) {
2817 /* add/substract register or immediate */
2818 if ((opcode & 0x1800) == 0x1800)
2819 return evaluate_add_sub_thumb(opcode, address, instruction);
2820 /* shift by immediate */
2822 return evaluate_shift_imm_thumb(opcode, address, instruction);
2825 /* Add/substract/compare/move immediate */
2826 if ((opcode & 0xe000) == 0x2000)
2827 return evaluate_data_proc_imm_thumb(opcode, address, instruction);
2829 /* Data processing instructions */
2830 if ((opcode & 0xf800) == 0x4000)
2831 return evaluate_data_proc_thumb(opcode, address, instruction);
2833 /* Load from literal pool */
2834 if ((opcode & 0xf800) == 0x4800)
2835 return evaluate_load_literal_thumb(opcode, address, instruction);
2837 /* Load/Store register offset */
2838 if ((opcode & 0xf000) == 0x5000)
2839 return evaluate_load_store_reg_thumb(opcode, address, instruction);
2841 /* Load/Store immediate offset */
2842 if (((opcode & 0xe000) == 0x6000)
2843 || ((opcode & 0xf000) == 0x8000))
2844 return evaluate_load_store_imm_thumb(opcode, address, instruction);
2846 /* Load/Store from/to stack */
2847 if ((opcode & 0xf000) == 0x9000)
2848 return evaluate_load_store_stack_thumb(opcode, address, instruction);
2851 if ((opcode & 0xf000) == 0xa000)
2852 return evaluate_add_sp_pc_thumb(opcode, address, instruction);
2855 if ((opcode & 0xf000) == 0xb000) {
2856 switch ((opcode >> 8) & 0x0f) {
2858 return evaluate_adjust_stack_thumb(opcode, address, instruction);
2863 return evaluate_cb_thumb(opcode, address, instruction);
2865 return evaluate_extend_thumb(opcode, address, instruction);
2870 return evaluate_load_store_multiple_thumb(opcode, address,
2873 return evaluate_cps_thumb(opcode, address, instruction);
2875 if ((opcode & 0x00c0) == 0x0080)
2877 return evaluate_byterev_thumb(opcode, address, instruction);
2879 return evaluate_breakpoint_thumb(opcode, address, instruction);
2881 if (opcode & 0x000f)
2882 return evaluate_ifthen_thumb(opcode, address,
2885 return evaluate_hint_thumb(opcode, address,
2889 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2890 snprintf(instruction->text, 128,
2891 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2896 /* Load/Store multiple */
2897 if ((opcode & 0xf000) == 0xc000)
2898 return evaluate_load_store_multiple_thumb(opcode, address, instruction);
2900 /* Conditional branch + SWI */
2901 if ((opcode & 0xf000) == 0xd000)
2902 return evaluate_cond_branch_thumb(opcode, address, instruction);
2904 if ((opcode & 0xe000) == 0xe000) {
2905 /* Undefined instructions */
2906 if ((opcode & 0xf801) == 0xe801) {
2907 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2908 snprintf(instruction->text, 128,
2909 "0x%8.8" PRIx32 " 0x%8.8x\t"
2910 "UNDEFINED INSTRUCTION",
2913 } else /* Branch to offset */
2914 return evaluate_b_bl_blx_thumb(opcode, address, instruction);
2917 LOG_ERROR("Thumb: should never reach this point (opcode=%04x)", opcode);
2921 static int t2ev_b_bl(uint32_t opcode, uint32_t address,
2922 struct arm_instruction *instruction, char *cp)
2925 unsigned b21 = 1 << 21;
2926 unsigned b22 = 1 << 22;
2928 /* instead of combining two smaller 16-bit branch instructions,
2929 * Thumb2 uses only one larger 32-bit instruction.
2931 offset = opcode & 0x7ff;
2932 offset |= (opcode & 0x03ff0000) >> 5;
2933 if (opcode & (1 << 26)) {
2934 offset |= 0xff << 23;
2935 if ((opcode & (1 << 11)) == 0)
2937 if ((opcode & (1 << 13)) == 0)
2940 if (opcode & (1 << 11))
2942 if (opcode & (1 << 13))
2950 address += offset << 1;
2953 switch ((opcode >> 12) & 0x5) {
2956 instruction->type = ARM_B;
2960 instruction->type = ARM_BLX;
2964 instruction->type = ARM_BL;
2967 return ERROR_COMMAND_SYNTAX_ERROR;
2969 instruction->info.b_bl_bx_blx.reg_operand = -1;
2970 instruction->info.b_bl_bx_blx.target_address = address;
2971 sprintf(cp, "%s\t%#8.8" PRIx32, inst, address);
2976 static int t2ev_cond_b(uint32_t opcode, uint32_t address,
2977 struct arm_instruction *instruction, char *cp)
2980 unsigned b17 = 1 << 17;
2981 unsigned b18 = 1 << 18;
2982 unsigned cond = (opcode >> 22) & 0x0f;
2984 offset = opcode & 0x7ff;
2985 offset |= (opcode & 0x003f0000) >> 5;
2986 if (opcode & (1 << 26)) {
2987 offset |= 0x1fff << 19;
2988 if ((opcode & (1 << 11)) == 0)
2990 if ((opcode & (1 << 13)) == 0)
2993 if (opcode & (1 << 11))
2995 if (opcode & (1 << 13))
3002 address += offset << 1;
3004 instruction->type = ARM_B;
3005 instruction->info.b_bl_bx_blx.reg_operand = -1;
3006 instruction->info.b_bl_bx_blx.target_address = address;
3007 sprintf(cp, "B%s.W\t%#8.8" PRIx32,
3008 arm_condition_strings[cond],
3014 static const char *special_name(int number)
3016 char *special = "(RESERVED)";
3047 special = "primask";
3050 special = "basepri";
3053 special = "basepri_max";
3056 special = "faultmask";
3059 special = "control";
3065 static int t2ev_hint(uint32_t opcode, uint32_t address,
3066 struct arm_instruction *instruction, char *cp)
3068 const char *mnemonic;
3070 if (opcode & 0x0700) {
3071 instruction->type = ARM_UNDEFINED_INSTRUCTION;
3072 strcpy(cp, "UNDEFINED");
3076 if (opcode & 0x00f0) {
3077 sprintf(cp, "DBG\t#%d", (int) opcode & 0xf);
3081 switch (opcode & 0x0f) {
3086 mnemonic = "YIELD.W";
3098 mnemonic = "HINT.W (UNRECOGNIZED)";
3101 strcpy(cp, mnemonic);
3105 static int t2ev_misc(uint32_t opcode, uint32_t address,
3106 struct arm_instruction *instruction, char *cp)
3108 const char *mnemonic;
3110 switch ((opcode >> 4) & 0x0f) {
3112 mnemonic = "LEAVEX";
3115 mnemonic = "ENTERX";
3130 return ERROR_COMMAND_SYNTAX_ERROR;
3132 strcpy(cp, mnemonic);
3136 static int t2ev_b_misc(uint32_t opcode, uint32_t address,
3137 struct arm_instruction *instruction, char *cp)
3139 /* permanently undefined */
3140 if ((opcode & 0x07f07000) == 0x07f02000) {
3141 instruction->type = ARM_UNDEFINED_INSTRUCTION;
3142 strcpy(cp, "UNDEFINED");
3146 switch ((opcode >> 12) & 0x5) {
3150 return t2ev_b_bl(opcode, address, instruction, cp);
3152 if (((opcode >> 23) & 0x07) != 0x07)
3153 return t2ev_cond_b(opcode, address, instruction, cp);
3154 if (opcode & (1 << 26))
3159 switch ((opcode >> 20) & 0x7f) {
3162 sprintf(cp, "MSR\t%s, r%d", special_name(opcode & 0xff),
3163 (int) (opcode >> 16) & 0x0f);
3166 return t2ev_hint(opcode, address, instruction, cp);
3168 return t2ev_misc(opcode, address, instruction, cp);
3170 sprintf(cp, "BXJ\tr%d", (int) (opcode >> 16) & 0x0f);
3174 sprintf(cp, "MRS\tr%d, %s", (int) (opcode >> 8) & 0x0f,
3175 special_name(opcode & 0xff));
3180 return ERROR_COMMAND_SYNTAX_ERROR;
3183 static int t2ev_data_mod_immed(uint32_t opcode, uint32_t address,
3184 struct arm_instruction *instruction, char *cp)
3186 char *mnemonic = NULL;
3187 int rn = (opcode >> 16) & 0xf;
3188 int rd = (opcode >> 8) & 0xf;
3189 unsigned immed = opcode & 0xff;
3195 /* ARMv7-M: A5.3.2 Modified immediate constants */
3196 func = (opcode >> 11) & 0x0e;
3199 if (opcode & (1 << 26))
3202 /* "Modified" immediates */
3203 switch (func >> 1) {
3210 immed += immed << 16;
3213 immed += immed << 8;
3214 immed += immed << 16;
3218 immed = ror(immed, func);
3221 if (opcode & (1 << 20))
3224 switch ((opcode >> 21) & 0xf) {
3227 instruction->type = ARM_TST;
3233 instruction->type = ARM_AND;
3238 instruction->type = ARM_BIC;
3243 instruction->type = ARM_MOV;
3248 instruction->type = ARM_ORR;
3254 instruction->type = ARM_MVN;
3258 /* instruction->type = ARM_ORN; */
3264 instruction->type = ARM_TEQ;
3270 instruction->type = ARM_EOR;
3276 instruction->type = ARM_CMN;
3282 instruction->type = ARM_ADD;
3288 instruction->type = ARM_ADC;
3293 instruction->type = ARM_SBC;
3298 instruction->type = ARM_CMP;
3304 instruction->type = ARM_SUB;
3310 instruction->type = ARM_RSB;
3315 return ERROR_COMMAND_SYNTAX_ERROR;
3319 sprintf(cp, "%s%s\tr%d, #%d\t; %#8.8x",
3320 mnemonic, suffix2, rd, immed, immed);
3322 sprintf(cp, "%s%s%s\tr%d, r%d, #%d\t; %#8.8x",
3323 mnemonic, suffix, suffix2,
3324 rd, rn, immed, immed);
3329 static int t2ev_data_immed(uint32_t opcode, uint32_t address,
3330 struct arm_instruction *instruction, char *cp)
3332 char *mnemonic = NULL;
3333 int rn = (opcode >> 16) & 0xf;
3334 int rd = (opcode >> 8) & 0xf;
3337 bool is_signed = false;
3339 immed = (opcode & 0x0ff) | ((opcode & 0x7000) >> 4);
3340 if (opcode & (1 << 26))
3343 switch ((opcode >> 20) & 0x1f) {
3352 immed |= (opcode >> 4) & 0xf000;
3353 sprintf(cp, "MOVW\tr%d, #%d\t; %#3.3x", rd, immed, immed);
3361 /* move constant to top 16 bits of register */
3362 immed |= (opcode >> 4) & 0xf000;
3363 sprintf(cp, "MOVT\tr%d, #%d\t; %#4.4x", rd, immed, immed);
3371 /* signed/unsigned saturated add */
3372 immed = (opcode >> 6) & 0x03;
3373 immed |= (opcode >> 10) & 0x1c;
3374 sprintf(cp, "%sSAT\tr%d, #%d, r%d, %s #%d\t",
3375 is_signed ? "S" : "U",
3376 rd, (int) (opcode & 0x1f) + is_signed, rn,
3377 (opcode & (1 << 21)) ? "ASR" : "LSL",
3378 immed ? immed : 32);
3384 /* signed/unsigned bitfield extract */
3385 immed = (opcode >> 6) & 0x03;
3386 immed |= (opcode >> 10) & 0x1c;
3387 sprintf(cp, "%sBFX\tr%d, r%d, #%d, #%d\t",
3388 is_signed ? "S" : "U",
3390 (int) (opcode & 0x1f) + 1);
3393 immed = (opcode >> 6) & 0x03;
3394 immed |= (opcode >> 10) & 0x1c;
3395 if (rn == 0xf) /* bitfield clear */
3396 sprintf(cp, "BFC\tr%d, #%d, #%d\t",
3398 (int) (opcode & 0x1f) + 1 - immed);
3399 else /* bitfield insert */
3400 sprintf(cp, "BFI\tr%d, r%d, #%d, #%d\t",
3402 (int) (opcode & 0x1f) + 1 - immed);
3405 return ERROR_COMMAND_SYNTAX_ERROR;
3408 sprintf(cp, "%s\tr%d, r%d, #%d\t; %#3.3x", mnemonic,
3409 rd, rn, immed, immed);
3413 address = thumb_alignpc4(address);
3418 /* REVISIT "ADD/SUB Rd, PC, #const ; 0x..." might be better;
3419 * not hiding the pc-relative stuff will sometimes be useful.
3421 sprintf(cp, "ADR.W\tr%d, %#8.8" PRIx32, rd, address);
3425 static int t2ev_store_single(uint32_t opcode, uint32_t address,
3426 struct arm_instruction *instruction, char *cp)
3428 unsigned op = (opcode >> 20) & 0xf;
3434 unsigned rn = (opcode >> 16) & 0x0f;
3435 unsigned rt = (opcode >> 12) & 0x0f;
3438 return ERROR_COMMAND_SYNTAX_ERROR;
3440 if (opcode & 0x0800)
3475 return ERROR_COMMAND_SYNTAX_ERROR;
3478 sprintf(cp, "STR%s.W\tr%d, [r%d, r%d, LSL #%d]",
3479 size, rt, rn, (int) opcode & 0x0f,
3480 (int) (opcode >> 4) & 0x03);
3484 immed = opcode & 0x0fff;
3485 sprintf(cp, "STR%s.W\tr%d, [r%d, #%u]\t; %#3.3x",
3486 size, rt, rn, immed, immed);
3490 immed = opcode & 0x00ff;
3492 switch (opcode & 0x700) {
3498 return ERROR_COMMAND_SYNTAX_ERROR;
3501 /* two indexed modes will write back rn */
3502 if (opcode & 0x100) {
3503 if (opcode & 0x400) /* pre-indexed */
3505 else { /* post-indexed */
3511 sprintf(cp, "STR%s%s\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
3512 size, suffix, rt, rn, p1,
3513 (opcode & 0x200) ? "" : "-",
3518 static int t2ev_mul32(uint32_t opcode, uint32_t address,
3519 struct arm_instruction *instruction, char *cp)
3521 int ra = (opcode >> 12) & 0xf;
3523 switch (opcode & 0x007000f0) {
3526 sprintf(cp, "MUL\tr%d, r%d, r%d",
3527 (int) (opcode >> 8) & 0xf,
3528 (int) (opcode >> 16) & 0xf,
3529 (int) (opcode >> 0) & 0xf);
3531 sprintf(cp, "MLA\tr%d, r%d, r%d, r%d",
3532 (int) (opcode >> 8) & 0xf,
3533 (int) (opcode >> 16) & 0xf,
3534 (int) (opcode >> 0) & 0xf, ra);
3537 sprintf(cp, "MLS\tr%d, r%d, r%d, r%d",
3538 (int) (opcode >> 8) & 0xf,
3539 (int) (opcode >> 16) & 0xf,
3540 (int) (opcode >> 0) & 0xf, ra);
3543 return ERROR_COMMAND_SYNTAX_ERROR;
3548 static int t2ev_mul64_div(uint32_t opcode, uint32_t address,
3549 struct arm_instruction *instruction, char *cp)
3551 int op = (opcode >> 4) & 0xf;
3552 char *infix = "MUL";
3554 op += (opcode >> 16) & 0x70;
3562 sprintf(cp, "%c%sL\tr%d, r%d, r%d, r%d",
3563 (op & 0x20) ? 'U' : 'S',
3565 (int) (opcode >> 12) & 0xf,
3566 (int) (opcode >> 8) & 0xf,
3567 (int) (opcode >> 16) & 0xf,
3568 (int) (opcode >> 0) & 0xf);
3572 sprintf(cp, "%cDIV\tr%d, r%d, r%d",
3573 (op & 0x20) ? 'U' : 'S',
3574 (int) (opcode >> 8) & 0xf,
3575 (int) (opcode >> 16) & 0xf,
3576 (int) (opcode >> 0) & 0xf);
3579 return ERROR_COMMAND_SYNTAX_ERROR;
3585 static int t2ev_ldm_stm(uint32_t opcode, uint32_t address,
3586 struct arm_instruction *instruction, char *cp)
3588 int rn = (opcode >> 16) & 0xf;
3589 int op = (opcode >> 22) & 0x6;
3590 int t = (opcode >> 21) & 1;
3591 unsigned registers = opcode & 0xffff;
3594 if (opcode & (1 << 20))
3602 sprintf(cp, "SRS%s\tsp%s, #%d", mode,
3604 (unsigned) (opcode & 0x1f));
3610 sprintf(cp, "RFE%s\tr%d%s", mode,
3611 (unsigned) ((opcode >> 16) & 0xf),
3615 sprintf(cp, "STM.W\tr%d%s, ", rn, t ? "!" : "");
3619 sprintf(cp, "POP.W\t");
3621 sprintf(cp, "LDM.W\tr%d%s, ", rn, t ? "!" : "");
3625 sprintf(cp, "PUSH.W\t");
3627 sprintf(cp, "STMDB\tr%d%s, ", rn, t ? "!" : "");
3630 sprintf(cp, "LDMDB.W\tr%d%s, ", rn, t ? "!" : "");
3633 return ERROR_COMMAND_SYNTAX_ERROR;
3638 for (t = 0; registers; t++, registers >>= 1) {
3639 if ((registers & 1) == 0)
3642 sprintf(cp, "r%d%s", t, registers ? ", " : "");
3651 /* load/store dual or exclusive, table branch */
3652 static int t2ev_ldrex_strex(uint32_t opcode, uint32_t address,
3653 struct arm_instruction *instruction, char *cp)
3655 unsigned op1op2 = (opcode >> 20) & 0x3;
3656 unsigned op3 = (opcode >> 4) & 0xf;
3658 unsigned rn = (opcode >> 16) & 0xf;
3659 unsigned rt = (opcode >> 12) & 0xf;
3660 unsigned rd = (opcode >> 8) & 0xf;
3661 unsigned imm = opcode & 0xff;
3665 op1op2 |= (opcode >> 21) & 0xc;
3695 mnemonic = "STREXB";
3698 mnemonic = "STREXH";
3701 return ERROR_COMMAND_SYNTAX_ERROR;
3709 sprintf(cp, "TBB\t[r%u, r%u]", rn, imm & 0xf);
3712 sprintf(cp, "TBH\t[r%u, r%u, LSL #1]", rn, imm & 0xf);
3715 mnemonic = "LDREXB";
3718 mnemonic = "LDREXH";
3721 return ERROR_COMMAND_SYNTAX_ERROR;
3726 return ERROR_COMMAND_SYNTAX_ERROR;
3731 sprintf(cp, "%s\tr%u, r%u, [r%u, #%u]\t; %#2.2x",
3732 mnemonic, rd, rt, rn, imm, imm);
3734 sprintf(cp, "%s\tr%u, r%u, [r%u]",
3735 mnemonic, rd, rt, rn);
3741 sprintf(cp, "%s\tr%u, [r%u, #%u]\t; %#2.2x",
3742 mnemonic, rt, rn, imm, imm);
3744 sprintf(cp, "%s\tr%u, [r%u]",
3749 /* two indexed modes will write back rn */
3750 if (opcode & (1 << 21)) {
3751 if (opcode & (1 << 24)) /* pre-indexed */
3753 else { /* post-indexed */
3760 sprintf(cp, "%s\tr%u, r%u, [r%u%s, #%s%u%s\t; %#2.2x",
3761 mnemonic, rt, rd, rn, p1,
3762 (opcode & (1 << 23)) ? "" : "-",
3767 address = thumb_alignpc4(address);
3769 if (opcode & (1 << 23))
3773 sprintf(cp, "%s\tr%u, r%u, %#8.8" PRIx32,
3774 mnemonic, rt, rd, address);
3778 static int t2ev_data_shift(uint32_t opcode, uint32_t address,
3779 struct arm_instruction *instruction, char *cp)
3781 int op = (opcode >> 21) & 0xf;
3782 int rd = (opcode >> 8) & 0xf;
3783 int rn = (opcode >> 16) & 0xf;
3784 int type = (opcode >> 4) & 0x3;
3785 int immed = (opcode >> 6) & 0x3;
3789 immed |= (opcode >> 10) & 0x1c;
3790 if (opcode & (1 << 20))
3796 if (!(opcode & (1 << 20)))
3797 return ERROR_COMMAND_SYNTAX_ERROR;
3798 instruction->type = ARM_TST;
3803 instruction->type = ARM_AND;
3807 instruction->type = ARM_BIC;
3812 instruction->type = ARM_MOV;
3816 sprintf(cp, "MOV%s.W\tr%d, r%d",
3818 (int) (opcode & 0xf));
3831 sprintf(cp, "RRX%s\tr%d, r%d",
3833 (int) (opcode & 0xf));
3841 instruction->type = ARM_ORR;
3847 instruction->type = ARM_MVN;
3852 /* instruction->type = ARM_ORN; */
3858 if (!(opcode & (1 << 20)))
3859 return ERROR_COMMAND_SYNTAX_ERROR;
3860 instruction->type = ARM_TEQ;
3865 instruction->type = ARM_EOR;
3870 if (!(opcode & (1 << 20)))
3871 return ERROR_COMMAND_SYNTAX_ERROR;
3872 instruction->type = ARM_CMN;
3877 instruction->type = ARM_ADD;
3881 instruction->type = ARM_ADC;
3885 instruction->type = ARM_SBC;
3890 if (!(opcode & (1 << 21)))
3891 return ERROR_COMMAND_SYNTAX_ERROR;
3892 instruction->type = ARM_CMP;
3897 instruction->type = ARM_SUB;
3901 instruction->type = ARM_RSB;
3905 return ERROR_COMMAND_SYNTAX_ERROR;
3908 sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
3909 mnemonic, suffix, rd, rn, (int) (opcode & 0xf));
3932 strcpy(cp, ", RRX");
3938 sprintf(cp, ", %s #%d", suffix, immed ? immed : 32);
3942 sprintf(cp, "%s%s.W\tr%d, r%d",
3943 mnemonic, suffix, rn, (int) (opcode & 0xf));
3947 sprintf(cp, "%s%s.W\tr%d, r%d, #%d",
3948 mnemonic, suffix, rd,
3949 (int) (opcode & 0xf), immed ? immed : 32);
3953 static int t2ev_data_reg(uint32_t opcode, uint32_t address,
3954 struct arm_instruction *instruction, char *cp)
3959 if (((opcode >> 4) & 0xf) == 0) {
3960 switch ((opcode >> 21) & 0x7) {
3974 return ERROR_COMMAND_SYNTAX_ERROR;
3977 instruction->type = ARM_MOV;
3978 if (opcode & (1 << 20))
3980 sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
3982 (int) (opcode >> 8) & 0xf,
3983 (int) (opcode >> 16) & 0xf,
3984 (int) (opcode >> 0) & 0xf);
3986 } else if (opcode & (1 << 7)) {
3987 switch ((opcode >> 20) & 0xf) {
3992 switch ((opcode >> 4) & 0x3) {
3994 suffix = ", ROR #8";
3997 suffix = ", ROR #16";
4000 suffix = ", ROR #24";
4003 sprintf(cp, "%cXT%c.W\tr%d, r%d%s",
4004 (opcode & (1 << 24)) ? 'U' : 'S',
4005 (opcode & (1 << 26)) ? 'B' : 'H',
4006 (int) (opcode >> 8) & 0xf,
4007 (int) (opcode >> 0) & 0xf,
4014 if (opcode & (1 << 6))
4015 return ERROR_COMMAND_SYNTAX_ERROR;
4016 if (((opcode >> 12) & 0xf) != 0xf)
4017 return ERROR_COMMAND_SYNTAX_ERROR;
4018 if (!(opcode & (1 << 20)))
4019 return ERROR_COMMAND_SYNTAX_ERROR;
4021 switch (((opcode >> 19) & 0x04)
4022 | ((opcode >> 4) & 0x3)) {
4027 mnemonic = "REV16.W";
4033 mnemonic = "REVSH.W";
4039 return ERROR_COMMAND_SYNTAX_ERROR;
4041 sprintf(cp, "%s\tr%d, r%d",
4043 (int) (opcode >> 8) & 0xf,
4044 (int) (opcode >> 0) & 0xf);
4047 return ERROR_COMMAND_SYNTAX_ERROR;
4054 static int t2ev_load_word(uint32_t opcode, uint32_t address,
4055 struct arm_instruction *instruction, char *cp)
4057 int rn = (opcode >> 16) & 0xf;
4060 instruction->type = ARM_LDR;
4063 immed = opcode & 0x0fff;
4064 if ((opcode & (1 << 23)) == 0)
4066 sprintf(cp, "LDR\tr%d, %#8.8" PRIx32,
4067 (int) (opcode >> 12) & 0xf,
4068 thumb_alignpc4(address) + immed);
4072 if (opcode & (1 << 23)) {
4073 immed = opcode & 0x0fff;
4074 sprintf(cp, "LDR.W\tr%d, [r%d, #%d]\t; %#3.3x",
4075 (int) (opcode >> 12) & 0xf,
4080 if (!(opcode & (0x3f << 6))) {
4081 sprintf(cp, "LDR.W\tr%d, [r%d, r%d, LSL #%d]",
4082 (int) (opcode >> 12) & 0xf,
4084 (int) (opcode >> 0) & 0xf,
4085 (int) (opcode >> 4) & 0x3);
4090 if (((opcode >> 8) & 0xf) == 0xe) {
4091 immed = opcode & 0x00ff;
4093 sprintf(cp, "LDRT\tr%d, [r%d, #%d]\t; %#2.2x",
4094 (int) (opcode >> 12) & 0xf,
4099 if (((opcode >> 8) & 0xf) == 0xc || (opcode & 0x0900) == 0x0900) {
4100 char *p1 = "]", *p2 = "";
4102 if (!(opcode & 0x0500))
4103 return ERROR_COMMAND_SYNTAX_ERROR;
4105 immed = opcode & 0x00ff;
4107 /* two indexed modes will write back rn */
4108 if (opcode & 0x100) {
4109 if (opcode & 0x400) /* pre-indexed */
4111 else { /* post-indexed */
4117 sprintf(cp, "LDR\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
4118 (int) (opcode >> 12) & 0xf,
4120 (opcode & 0x200) ? "" : "-",
4125 return ERROR_COMMAND_SYNTAX_ERROR;
4128 static int t2ev_load_byte_hints(uint32_t opcode, uint32_t address,
4129 struct arm_instruction *instruction, char *cp)
4131 int rn = (opcode >> 16) & 0xf;
4132 int rt = (opcode >> 12) & 0xf;
4133 int op2 = (opcode >> 6) & 0x3f;
4135 char *p1 = "", *p2 = "]";
4138 switch ((opcode >> 23) & 0x3) {
4140 if ((rn & rt) == 0xf) {
4142 immed = opcode & 0xfff;
4143 address = thumb_alignpc4(address);
4144 if (opcode & (1 << 23))
4148 sprintf(cp, "PLD\tr%d, %#8.8" PRIx32,
4152 if (rn == 0x0f && rt != 0x0f) {
4154 immed = opcode & 0xfff;
4155 address = thumb_alignpc4(address);
4156 if (opcode & (1 << 23))
4160 sprintf(cp, "LDRB\tr%d, %#8.8" PRIx32,
4166 if ((op2 & 0x3c) == 0x38) {
4167 immed = opcode & 0xff;
4168 sprintf(cp, "LDRBT\tr%d, [r%d, #%d]\t; %#2.2x",
4169 rt, rn, immed, immed);
4172 if ((op2 & 0x3c) == 0x30) {
4174 immed = opcode & 0xff;
4177 p1 = (opcode & (1 << 21)) ? "W" : "";
4178 sprintf(cp, "PLD%s\t[r%d, #%d]\t; %#6.6x",
4179 p1, rn, immed, immed);
4184 immed = opcode & 0xff;
4185 if (!(opcode & 0x200))
4188 /* two indexed modes will write back rn */
4189 if (opcode & 0x100) {
4190 if (opcode & 0x400) /* pre-indexed */
4192 else { /* post-indexed */
4198 sprintf(cp, "%s\tr%d, [r%d%s, #%d%s\t; %#8.8x",
4199 mnemonic, rt, rn, p1,
4203 if ((op2 & 0x24) == 0x24) {
4205 goto ldrxb_immediate_t3;
4208 int rm = opcode & 0xf;
4211 sprintf(cp, "PLD\t");
4213 sprintf(cp, "LDRB.W\tr%d, ", rt);
4214 immed = (opcode >> 4) & 0x3;
4216 sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed);
4221 if ((rn & rt) == 0xf)
4224 immed = opcode & 0xfff;
4225 goto preload_immediate;
4229 mnemonic = "LDRB.W";
4230 immed = opcode & 0xfff;
4231 goto ldrxb_immediate_t2;
4233 if ((rn & rt) == 0xf) {
4234 immed = opcode & 0xfff;
4235 address = thumb_alignpc4(address);
4236 if (opcode & (1 << 23))
4240 sprintf(cp, "PLI\t%#8.8" PRIx32, address);
4243 if (rn == 0xf && rt != 0xf) {
4245 immed = opcode & 0xfff;
4246 address = thumb_alignpc4(address);
4247 if (opcode & (1 << 23))
4251 sprintf(cp, "LDRSB\t%#8.8" PRIx32, address);
4256 if ((op2 & 0x3c) == 0x38) {
4257 immed = opcode & 0xff;
4258 sprintf(cp, "LDRSBT\tr%d, [r%d, #%d]\t; %#2.2x",
4259 rt, rn, immed, immed);
4262 if ((op2 & 0x3c) == 0x30) {
4264 immed = opcode & 0xff;
4265 immed = -immed; /* pli */
4266 sprintf(cp, "PLI\t[r%d, #%d]\t; -%#2.2x",
4271 goto ldrxb_immediate_t3;
4273 if ((op2 & 0x24) == 0x24) {
4275 goto ldrxb_immediate_t3;
4278 int rm = opcode & 0xf;
4281 sprintf(cp, "PLI\t");
4283 sprintf(cp, "LDRSB.W\tr%d, ", rt);
4284 immed = (opcode >> 4) & 0x3;
4286 sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed);
4292 immed = opcode & 0xfff;
4293 sprintf(cp, "PLI\t[r%d, #%d]\t; %#3.3x",
4299 immed = opcode & 0xfff;
4301 goto ldrxb_immediate_t2;
4304 return ERROR_COMMAND_SYNTAX_ERROR;
4307 static int t2ev_load_halfword(uint32_t opcode, uint32_t address,
4308 struct arm_instruction *instruction, char *cp)
4310 int rn = (opcode >> 16) & 0xf;
4311 int rt = (opcode >> 12) & 0xf;
4312 int op2 = (opcode >> 6) & 0x3f;
4317 sprintf(cp, "HINT (UNALLOCATED)");
4321 if (opcode & (1 << 24))
4324 if ((opcode & (1 << 23)) == 0) {
4327 immed = opcode & 0xfff;
4328 address = thumb_alignpc4(address);
4329 if (opcode & (1 << 23))
4333 sprintf(cp, "LDR%sH\tr%d, %#8.8" PRIx32,
4338 int rm = opcode & 0xf;
4340 immed = (opcode >> 4) & 0x3;
4341 sprintf(cp, "LDR%sH.W\tr%d, [r%d, r%d, LSL #%d]",
4342 sign, rt, rn, rm, immed);
4345 if ((op2 & 0x3c) == 0x38) {
4346 immed = opcode & 0xff;
4347 sprintf(cp, "LDR%sHT\tr%d, [r%d, #%d]\t; %#2.2x",
4348 sign, rt, rn, immed, immed);
4351 if ((op2 & 0x3c) == 0x30 || (op2 & 0x24) == 0x24) {
4352 char *p1 = "", *p2 = "]";
4354 immed = opcode & 0xff;
4355 if (!(opcode & 0x200))
4358 /* two indexed modes will write back rn */
4359 if (opcode & 0x100) {
4360 if (opcode & 0x400) /* pre-indexed */
4362 else { /* post-indexed */
4367 sprintf(cp, "LDR%sH\tr%d, [r%d%s, #%d%s\t; %#8.8x",
4368 sign, rt, rn, p1, immed, p2, immed);
4375 immed = opcode & 0xfff;
4376 sprintf(cp, "LDR%sH%s\tr%d, [r%d, #%d]\t; %#6.6x",
4377 sign, *sign ? "" : ".W",
4378 rt, rn, immed, immed);
4382 return ERROR_COMMAND_SYNTAX_ERROR;
4386 * REVISIT for Thumb2 instructions, instruction->type and friends aren't
4387 * always set. That means eventual arm_simulate_step() support for Thumb2
4388 * will need work in this area.
4390 int thumb2_opcode(struct target *target, uint32_t address, struct arm_instruction *instruction)
4397 /* clear low bit ... it's set on function pointers */
4400 /* clear fields, to avoid confusion */
4401 memset(instruction, 0, sizeof(struct arm_instruction));
4403 /* read first halfword, see if this is the only one */
4404 retval = target_read_u16(target, address, &op);
4405 if (retval != ERROR_OK)
4408 switch (op & 0xf800) {
4412 /* 32-bit instructions */
4413 instruction->instruction_size = 4;
4415 retval = target_read_u16(target, address + 2, &op);
4416 if (retval != ERROR_OK)
4419 instruction->opcode = opcode;
4422 /* 16-bit: Thumb1 + IT + CBZ/CBNZ + ... */
4423 return thumb_evaluate_opcode(op, address, instruction);
4426 snprintf(instruction->text, 128,
4427 "0x%8.8" PRIx32 " 0x%8.8" PRIx32 "\t",
4429 cp = strchr(instruction->text, 0);
4430 retval = ERROR_FAIL;
4432 /* ARMv7-M: A5.3.1 Data processing (modified immediate) */
4433 if ((opcode & 0x1a008000) == 0x10000000)
4434 retval = t2ev_data_mod_immed(opcode, address, instruction, cp);
4436 /* ARMv7-M: A5.3.3 Data processing (plain binary immediate) */
4437 else if ((opcode & 0x1a008000) == 0x12000000)
4438 retval = t2ev_data_immed(opcode, address, instruction, cp);
4440 /* ARMv7-M: A5.3.4 Branches and miscellaneous control */
4441 else if ((opcode & 0x18008000) == 0x10008000)
4442 retval = t2ev_b_misc(opcode, address, instruction, cp);
4444 /* ARMv7-M: A5.3.5 Load/store multiple */
4445 else if ((opcode & 0x1e400000) == 0x08000000)
4446 retval = t2ev_ldm_stm(opcode, address, instruction, cp);
4448 /* ARMv7-M: A5.3.6 Load/store dual or exclusive, table branch */
4449 else if ((opcode & 0x1e400000) == 0x08400000)
4450 retval = t2ev_ldrex_strex(opcode, address, instruction, cp);
4452 /* ARMv7-M: A5.3.7 Load word */
4453 else if ((opcode & 0x1f700000) == 0x18500000)
4454 retval = t2ev_load_word(opcode, address, instruction, cp);
4456 /* ARMv7-M: A5.3.8 Load halfword, unallocated memory hints */
4457 else if ((opcode & 0x1e700000) == 0x18300000)
4458 retval = t2ev_load_halfword(opcode, address, instruction, cp);
4460 /* ARMv7-M: A5.3.9 Load byte, memory hints */
4461 else if ((opcode & 0x1e700000) == 0x18100000)
4462 retval = t2ev_load_byte_hints(opcode, address, instruction, cp);
4464 /* ARMv7-M: A5.3.10 Store single data item */
4465 else if ((opcode & 0x1f100000) == 0x18000000)
4466 retval = t2ev_store_single(opcode, address, instruction, cp);
4468 /* ARMv7-M: A5.3.11 Data processing (shifted register) */
4469 else if ((opcode & 0x1e000000) == 0x0a000000)
4470 retval = t2ev_data_shift(opcode, address, instruction, cp);
4472 /* ARMv7-M: A5.3.12 Data processing (register)
4473 * and A5.3.13 Miscellaneous operations
4475 else if ((opcode & 0x1f000000) == 0x1a000000)
4476 retval = t2ev_data_reg(opcode, address, instruction, cp);
4478 /* ARMv7-M: A5.3.14 Multiply, and multiply accumulate */
4479 else if ((opcode & 0x1f800000) == 0x1b000000)
4480 retval = t2ev_mul32(opcode, address, instruction, cp);
4482 /* ARMv7-M: A5.3.15 Long multiply, long multiply accumulate, divide */
4483 else if ((opcode & 0x1f800000) == 0x1b800000)
4484 retval = t2ev_mul64_div(opcode, address, instruction, cp);
4486 if (retval == ERROR_OK)
4490 * Thumb2 also supports coprocessor, ThumbEE, and DSP/Media (SIMD)
4491 * instructions; not yet handled here.
4494 if (retval == ERROR_COMMAND_SYNTAX_ERROR) {
4495 instruction->type = ARM_UNDEFINED_INSTRUCTION;
4496 strcpy(cp, "UNDEFINED OPCODE");
4500 LOG_DEBUG("Can't decode 32-bit Thumb2 yet (opcode=%08" PRIx32 ")",
4503 strcpy(cp, "(32-bit Thumb2 ...)");
4507 int arm_access_size(struct arm_instruction *instruction)
4509 if ((instruction->type == ARM_LDRB)
4510 || (instruction->type == ARM_LDRBT)
4511 || (instruction->type == ARM_LDRSB)
4512 || (instruction->type == ARM_STRB)
4513 || (instruction->type == ARM_STRBT))
4515 else if ((instruction->type == ARM_LDRH)
4516 || (instruction->type == ARM_LDRSH)
4517 || (instruction->type == ARM_STRH))
4519 else if ((instruction->type == ARM_LDR)
4520 || (instruction->type == ARM_LDRT)
4521 || (instruction->type == ARM_STR)
4522 || (instruction->type == ARM_STRT))
4524 else if ((instruction->type == ARM_LDRD)
4525 || (instruction->type == ARM_STRD))
4528 LOG_ERROR("BUG: instruction type %i isn't a load/store instruction",