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
& 0x0d30f000) == 0x0510f000) {
126 instruction
->type
= ARM_PLD
;
127 Rn
= (opcode
& 0xf0000) >> 16;
128 U
= (opcode
& 0x00800000) >> 23;
131 offset
= opcode
& 0x0fff;
132 snprintf(instruction
->text
, 128,
133 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tPLD %s%d",
134 address
, opcode
, U
? "" : "-", offset
);
138 I
= (opcode
& 0x02000000) >> 25;
139 R
= (opcode
& 0x00400000) >> 22;
142 /* register PLD{W} [<Rn>,+/-<Rm>{, <shift>}] */
143 offset
= (opcode
& 0x0F80) >> 7;
149 snprintf(instruction
->text
, 128,
150 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tPLD%s [r%d, %sr%d]",
151 address
, opcode
, R
? "" : "W", Rn
, U
? "" : "-", Rm
);
155 shift
= (opcode
& 0x60) >> 5;
159 snprintf(instruction
->text
, 128,
160 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tPLD%s [r%d, %sr%d, LSL #0x%x)",
161 address
, opcode
, R
? "" : "W", Rn
, U
? "" : "-", Rm
, offset
);
162 } else if (shift
== 0x1) {
164 snprintf(instruction
->text
, 128,
165 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tPLD%s [r%d, %sr%d, LSR #0x%x)",
166 address
, opcode
, R
? "" : "W", Rn
, U
? "" : "-", Rm
, offset
);
167 } else if (shift
== 0x2) {
169 snprintf(instruction
->text
, 128,
170 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tPLD%s [r%d, %sr%d, ASR #0x%x)",
171 address
, opcode
, R
? "" : "W", Rn
, U
? "" : "-", Rm
, offset
);
172 } else if (shift
== 0x3) {
174 snprintf(instruction
->text
, 128,
175 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tPLD%s [r%d, %sr%d, ROR #0x%x)",
176 address
, opcode
, R
? "" : "W", Rn
, U
? "" : "-", Rm
, offset
);
180 /* immediate PLD{W} [<Rn>, #+/-<imm12>] */
181 offset
= opcode
& 0x0fff;
183 snprintf(instruction
->text
, 128,
184 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tPLD%s [r%d]",
185 address
, opcode
, R
? "" : "W", Rn
);
187 snprintf(instruction
->text
, 128,
188 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tPLD%s [r%d, #%s%d]",
189 address
, opcode
, R
? "" : "W", Rn
, U
? "" : "-", offset
);
196 if ((opcode
& 0x07f000f0) == 0x05700040) {
197 instruction
->type
= ARM_DSB
;
200 switch (opcode
& 0x0000000f) {
229 snprintf(instruction
->text
,
231 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tDSB %s",
232 address
, opcode
, opt
);
237 if ((opcode
& 0x07f000f0) == 0x05700060) {
238 instruction
->type
= ARM_ISB
;
240 snprintf(instruction
->text
,
242 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tISB %s",
244 ((opcode
& 0x0000000f) == 0xf) ? "SY" : "UNK");
248 return evaluate_unknown(opcode
, address
, instruction
);
251 static int evaluate_srs(uint32_t opcode
,
252 uint32_t address
, struct arm_instruction
*instruction
)
254 const char *wback
= (opcode
& (1 << 21)) ? "!" : "";
255 const char *mode
= "";
257 switch ((opcode
>> 23) & 0x3) {
262 /* "IA" is default */
272 switch (opcode
& 0x0e500000) {
274 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
276 "\tSRS%s\tSP%s, #%d",
279 (unsigned)(opcode
& 0x1f));
282 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
287 (unsigned)((opcode
>> 16) & 0xf), wback
);
290 return evaluate_unknown(opcode
, address
, instruction
);
295 static int evaluate_swi(uint32_t opcode
,
296 uint32_t address
, struct arm_instruction
*instruction
)
298 instruction
->type
= ARM_SWI
;
300 snprintf(instruction
->text
, 128,
301 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tSVC %#6.6" PRIx32
,
302 address
, opcode
, (opcode
& 0xffffff));
307 static int evaluate_blx_imm(uint32_t opcode
,
308 uint32_t address
, struct arm_instruction
*instruction
)
312 uint32_t target_address
;
314 instruction
->type
= ARM_BLX
;
315 immediate
= opcode
& 0x00ffffff;
317 /* sign extend 24-bit immediate */
318 if (immediate
& 0x00800000)
319 offset
= 0xff000000 | immediate
;
323 /* shift two bits left */
326 /* odd/event halfword */
327 if (opcode
& 0x01000000)
330 target_address
= address
+ 8 + offset
;
332 snprintf(instruction
->text
,
334 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tBLX 0x%8.8" PRIx32
"",
339 instruction
->info
.b_bl_bx_blx
.reg_operand
= -1;
340 instruction
->info
.b_bl_bx_blx
.target_address
= target_address
;
345 static int evaluate_b_bl(uint32_t opcode
,
346 uint32_t address
, struct arm_instruction
*instruction
)
351 uint32_t target_address
;
353 immediate
= opcode
& 0x00ffffff;
354 L
= (opcode
& 0x01000000) >> 24;
356 /* sign extend 24-bit immediate */
357 if (immediate
& 0x00800000)
358 offset
= 0xff000000 | immediate
;
362 /* shift two bits left */
365 target_address
= address
+ 8 + offset
;
368 instruction
->type
= ARM_BL
;
370 instruction
->type
= ARM_B
;
372 snprintf(instruction
->text
,
374 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tB%s%s 0x%8.8" PRIx32
,
381 instruction
->info
.b_bl_bx_blx
.reg_operand
= -1;
382 instruction
->info
.b_bl_bx_blx
.target_address
= target_address
;
387 /* Coprocessor load/store and double register transfers
388 * both normal and extended instruction space (condition field b1111) */
389 static int evaluate_ldc_stc_mcrr_mrrc(uint32_t opcode
,
390 uint32_t address
, struct arm_instruction
*instruction
)
392 uint8_t cp_num
= (opcode
& 0xf00) >> 8;
395 if (((opcode
& 0x0ff00000) == 0x0c400000) || ((opcode
& 0x0ff00000) == 0x0c500000)) {
396 uint8_t cp_opcode
, Rd
, Rn
, CRm
;
399 cp_opcode
= (opcode
& 0xf0) >> 4;
400 Rd
= (opcode
& 0xf000) >> 12;
401 Rn
= (opcode
& 0xf0000) >> 16;
402 CRm
= (opcode
& 0xf);
405 if ((opcode
& 0x0ff00000) == 0x0c400000) {
406 instruction
->type
= ARM_MCRR
;
408 } else if ((opcode
& 0x0ff00000) == 0x0c500000) {
410 instruction
->type
= ARM_MRRC
;
413 LOG_ERROR("Unknown instruction");
417 snprintf(instruction
->text
, 128,
418 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
419 "\t%s%s%s p%i, %x, r%i, r%i, c%i",
420 address
, opcode
, mnemonic
,
421 ((opcode
& 0xf0000000) == 0xf0000000)
422 ? "2" : COND(opcode
),
423 COND(opcode
), cp_num
, cp_opcode
, Rd
, Rn
, CRm
);
424 } else {/* LDC or STC */
425 uint8_t CRd
, Rn
, offset
;
428 char addressing_mode
[32];
430 CRd
= (opcode
& 0xf000) >> 12;
431 Rn
= (opcode
& 0xf0000) >> 16;
432 offset
= (opcode
& 0xff) << 2;
435 if (opcode
& 0x00100000) {
436 instruction
->type
= ARM_LDC
;
439 instruction
->type
= ARM_STC
;
443 U
= (opcode
& 0x00800000) >> 23;
445 /* addressing modes */
446 if ((opcode
& 0x01200000) == 0x01000000)/* offset */
447 snprintf(addressing_mode
, 32, "[r%i, #%s%d]",
448 Rn
, U
? "" : "-", offset
);
449 else if ((opcode
& 0x01200000) == 0x01200000) /* pre-indexed */
450 snprintf(addressing_mode
, 32, "[r%i, #%s%d]!",
451 Rn
, U
? "" : "-", offset
);
452 else if ((opcode
& 0x01200000) == 0x00200000) /* post-indexed */
453 snprintf(addressing_mode
, 32, "[r%i], #%s%d",
454 Rn
, U
? "" : "-", offset
);
455 else if ((opcode
& 0x01200000) == 0x00000000) /* unindexed */
456 snprintf(addressing_mode
, 32, "[r%i], {%d}",
459 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
461 "\t%s%s%s p%i, c%i, %s",
462 address
, opcode
, mnemonic
,
463 ((opcode
& 0xf0000000) == 0xf0000000)
464 ? "2" : COND(opcode
),
465 (opcode
& (1 << 22)) ? "L" : "",
466 cp_num
, CRd
, addressing_mode
);
472 /* Coprocessor data processing instructions
473 * Coprocessor register transfer instructions
474 * both normal and extended instruction space (condition field b1111) */
475 static int evaluate_cdp_mcr_mrc(uint32_t opcode
,
476 uint32_t address
, struct arm_instruction
*instruction
)
480 uint8_t cp_num
, opcode_1
, CRd_Rd
, CRn
, CRm
, opcode_2
;
482 cond
= ((opcode
& 0xf0000000) == 0xf0000000) ? "2" : COND(opcode
);
483 cp_num
= (opcode
& 0xf00) >> 8;
484 CRd_Rd
= (opcode
& 0xf000) >> 12;
485 CRn
= (opcode
& 0xf0000) >> 16;
486 CRm
= (opcode
& 0xf);
487 opcode_2
= (opcode
& 0xe0) >> 5;
490 if (opcode
& 0x00000010) { /* bit 4 set -> MRC/MCR */
491 if (opcode
& 0x00100000) { /* bit 20 set -> MRC */
492 instruction
->type
= ARM_MRC
;
494 } else {/* bit 20 not set -> MCR */
495 instruction
->type
= ARM_MCR
;
499 opcode_1
= (opcode
& 0x00e00000) >> 21;
501 snprintf(instruction
->text
,
503 "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",
514 } else {/* bit 4 not set -> CDP */
515 instruction
->type
= ARM_CDP
;
518 opcode_1
= (opcode
& 0x00f00000) >> 20;
520 snprintf(instruction
->text
,
522 "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",
538 /* Load/store instructions */
539 static int evaluate_load_store(uint32_t opcode
,
540 uint32_t address
, struct arm_instruction
*instruction
)
542 uint8_t I
, P
, U
, B
, W
, L
;
544 char *operation
;/* "LDR" or "STR" */
545 char *suffix
; /* "", "B", "T", "BT" */
549 I
= (opcode
& 0x02000000) >> 25;
550 P
= (opcode
& 0x01000000) >> 24;
551 U
= (opcode
& 0x00800000) >> 23;
552 B
= (opcode
& 0x00400000) >> 22;
553 W
= (opcode
& 0x00200000) >> 21;
554 L
= (opcode
& 0x00100000) >> 20;
556 /* target register */
557 Rd
= (opcode
& 0xf000) >> 12;
560 Rn
= (opcode
& 0xf0000) >> 16;
562 instruction
->info
.load_store
.Rd
= Rd
;
563 instruction
->info
.load_store
.Rn
= Rn
;
564 instruction
->info
.load_store
.U
= U
;
566 /* determine operation */
572 /* determine instruction type and suffix */
574 if ((P
== 0) && (W
== 1)) {
576 instruction
->type
= ARM_LDRBT
;
578 instruction
->type
= ARM_STRBT
;
582 instruction
->type
= ARM_LDRB
;
584 instruction
->type
= ARM_STRB
;
588 if ((P
== 0) && (W
== 1)) {
590 instruction
->type
= ARM_LDRT
;
592 instruction
->type
= ARM_STRT
;
596 instruction
->type
= ARM_LDR
;
598 instruction
->type
= ARM_STR
;
603 if (!I
) { /* #+-<offset_12> */
604 uint32_t offset_12
= (opcode
& 0xfff);
606 snprintf(offset
, 32, ", #%s0x%" PRIx32
"", (U
) ? "" : "-", offset_12
);
608 snprintf(offset
, 32, "%s", "");
610 instruction
->info
.load_store
.offset_mode
= 0;
611 instruction
->info
.load_store
.offset
.offset
= offset_12
;
612 } else {/* either +-<Rm> or +-<Rm>, <shift>, #<shift_imm> */
613 uint8_t shift_imm
, shift
;
616 shift_imm
= (opcode
& 0xf80) >> 7;
617 shift
= (opcode
& 0x60) >> 5;
620 /* LSR encodes a shift by 32 bit as 0x0 */
621 if ((shift
== 0x1) && (shift_imm
== 0x0))
624 /* ASR encodes a shift by 32 bit as 0x0 */
625 if ((shift
== 0x2) && (shift_imm
== 0x0))
628 /* ROR by 32 bit is actually a RRX */
629 if ((shift
== 0x3) && (shift_imm
== 0x0))
632 instruction
->info
.load_store
.offset_mode
= 1;
633 instruction
->info
.load_store
.offset
.reg
.Rm
= Rm
;
634 instruction
->info
.load_store
.offset
.reg
.shift
= shift
;
635 instruction
->info
.load_store
.offset
.reg
.shift_imm
= shift_imm
;
637 if ((shift_imm
== 0x0) && (shift
== 0x0)) /* +-<Rm> */
638 snprintf(offset
, 32, ", %sr%i", (U
) ? "" : "-", Rm
);
639 else { /* +-<Rm>, <Shift>, #<shift_imm> */
642 snprintf(offset
, 32, ", %sr%i, LSL #0x%x", (U
) ? "" : "-", Rm
, shift_imm
);
645 snprintf(offset
, 32, ", %sr%i, LSR #0x%x", (U
) ? "" : "-", Rm
, shift_imm
);
648 snprintf(offset
, 32, ", %sr%i, ASR #0x%x", (U
) ? "" : "-", Rm
, shift_imm
);
651 snprintf(offset
, 32, ", %sr%i, ROR #0x%x", (U
) ? "" : "-", Rm
, shift_imm
);
654 snprintf(offset
, 32, ", %sr%i, RRX", (U
) ? "" : "-", Rm
);
661 if (W
== 0) { /* offset */
662 snprintf(instruction
->text
,
664 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\t%s%s%s r%i, [r%i%s]",
674 instruction
->info
.load_store
.index_mode
= 0;
675 } else {/* pre-indexed */
676 snprintf(instruction
->text
,
678 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\t%s%s%s r%i, [r%i%s]!",
688 instruction
->info
.load_store
.index_mode
= 1;
690 } else {/* post-indexed */
691 snprintf(instruction
->text
,
693 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\t%s%s%s r%i, [r%i]%s",
703 instruction
->info
.load_store
.index_mode
= 2;
709 static int evaluate_extend(uint32_t opcode
, uint32_t address
, char *cp
)
711 unsigned rm
= (opcode
>> 0) & 0xf;
712 unsigned rd
= (opcode
>> 12) & 0xf;
713 unsigned rn
= (opcode
>> 16) & 0xf;
716 switch ((opcode
>> 24) & 0x3) {
721 sprintf(cp
, "UNDEFINED");
722 return ARM_UNDEFINED_INSTRUCTION
;
731 switch ((opcode
>> 10) & 0x3) {
747 sprintf(cp
, "%cXT%s%s\tr%d, r%d%s",
748 (opcode
& (1 << 22)) ? 'U' : 'S',
753 sprintf(cp
, "%cXTA%s%s\tr%d, r%d, r%d%s",
754 (opcode
& (1 << 22)) ? 'U' : 'S',
761 static int evaluate_p_add_sub(uint32_t opcode
, uint32_t address
, char *cp
)
767 switch ((opcode
>> 20) & 0x7) {
790 switch ((opcode
>> 5) & 0x7) {
819 sprintf(cp
, "%s%s%s\tr%d, r%d, r%d", prefix
, op
, COND(opcode
),
820 (int) (opcode
>> 12) & 0xf,
821 (int) (opcode
>> 16) & 0xf,
822 (int) (opcode
>> 0) & 0xf);
826 /* these opcodes might be used someday */
827 sprintf(cp
, "UNDEFINED");
828 return ARM_UNDEFINED_INSTRUCTION
;
831 /* ARMv6 and later support "media" instructions (includes SIMD) */
832 static int evaluate_media(uint32_t opcode
, uint32_t address
,
833 struct arm_instruction
*instruction
)
835 char *cp
= instruction
->text
;
836 char *mnemonic
= NULL
;
839 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\t",
843 /* parallel add/subtract */
844 if ((opcode
& 0x01800000) == 0x00000000) {
845 instruction
->type
= evaluate_p_add_sub(opcode
, address
, cp
);
850 if ((opcode
& 0x01f00020) == 0x00800000) {
852 unsigned imm
= (unsigned) (opcode
>> 7) & 0x1f;
854 if (opcode
& (1 << 6)) {
863 sprintf(cp
, "PKH%s%s\tr%d, r%d, r%d, %s #%d",
865 (int) (opcode
>> 12) & 0xf,
866 (int) (opcode
>> 16) & 0xf,
867 (int) (opcode
>> 0) & 0xf,
873 if ((opcode
& 0x01a00020) == 0x00a00000) {
875 unsigned imm
= (unsigned) (opcode
>> 7) & 0x1f;
877 if (opcode
& (1 << 6)) {
884 sprintf(cp
, "%cSAT%s\tr%d, #%d, r%d, %s #%d",
885 (opcode
& (1 << 22)) ? 'U' : 'S',
887 (int) (opcode
>> 12) & 0xf,
888 (int) (opcode
>> 16) & 0x1f,
889 (int) (opcode
>> 0) & 0xf,
895 if ((opcode
& 0x018000f0) == 0x00800070) {
896 instruction
->type
= evaluate_extend(opcode
, address
, cp
);
901 if ((opcode
& 0x01f00080) == 0x01000000) {
902 unsigned rn
= (opcode
>> 12) & 0xf;
905 sprintf(cp
, "SML%cD%s%s\tr%d, r%d, r%d, r%d",
906 (opcode
& (1 << 6)) ? 'S' : 'A',
907 (opcode
& (1 << 5)) ? "X" : "",
909 (int) (opcode
>> 16) & 0xf,
910 (int) (opcode
>> 0) & 0xf,
911 (int) (opcode
>> 8) & 0xf,
914 sprintf(cp
, "SMU%cD%s%s\tr%d, r%d, r%d",
915 (opcode
& (1 << 6)) ? 'S' : 'A',
916 (opcode
& (1 << 5)) ? "X" : "",
918 (int) (opcode
>> 16) & 0xf,
919 (int) (opcode
>> 0) & 0xf,
920 (int) (opcode
>> 8) & 0xf);
923 if ((opcode
& 0x01f00000) == 0x01400000) {
924 sprintf(cp
, "SML%cLD%s%s\tr%d, r%d, r%d, r%d",
925 (opcode
& (1 << 6)) ? 'S' : 'A',
926 (opcode
& (1 << 5)) ? "X" : "",
928 (int) (opcode
>> 12) & 0xf,
929 (int) (opcode
>> 16) & 0xf,
930 (int) (opcode
>> 0) & 0xf,
931 (int) (opcode
>> 8) & 0xf);
934 if ((opcode
& 0x01f00000) == 0x01500000) {
935 unsigned rn
= (opcode
>> 12) & 0xf;
937 switch (opcode
& 0xc0) {
949 sprintf(cp
, "SMML%c%s%s\tr%d, r%d, r%d, r%d",
950 (opcode
& (1 << 6)) ? 'S' : 'A',
951 (opcode
& (1 << 5)) ? "R" : "",
953 (int) (opcode
>> 16) & 0xf,
954 (int) (opcode
>> 0) & 0xf,
955 (int) (opcode
>> 8) & 0xf,
958 sprintf(cp
, "SMMUL%s%s\tr%d, r%d, r%d",
959 (opcode
& (1 << 5)) ? "R" : "",
961 (int) (opcode
>> 16) & 0xf,
962 (int) (opcode
>> 0) & 0xf,
963 (int) (opcode
>> 8) & 0xf);
967 /* simple matches against the remaining decode bits */
968 switch (opcode
& 0x01f000f0) {
971 /* parallel halfword saturate */
972 sprintf(cp
, "%cSAT16%s\tr%d, #%d, r%d",
973 (opcode
& (1 << 22)) ? 'U' : 'S',
975 (int) (opcode
>> 12) & 0xf,
976 (int) (opcode
>> 16) & 0xf,
977 (int) (opcode
>> 0) & 0xf);
990 sprintf(cp
, "SEL%s\tr%d, r%d, r%d", COND(opcode
),
991 (int) (opcode
>> 12) & 0xf,
992 (int) (opcode
>> 16) & 0xf,
993 (int) (opcode
>> 0) & 0xf);
996 /* unsigned sum of absolute differences */
997 if (((opcode
>> 12) & 0xf) == 0xf)
998 sprintf(cp
, "USAD8%s\tr%d, r%d, r%d", COND(opcode
),
999 (int) (opcode
>> 16) & 0xf,
1000 (int) (opcode
>> 0) & 0xf,
1001 (int) (opcode
>> 8) & 0xf);
1003 sprintf(cp
, "USADA8%s\tr%d, r%d, r%d, r%d", COND(opcode
),
1004 (int) (opcode
>> 16) & 0xf,
1005 (int) (opcode
>> 0) & 0xf,
1006 (int) (opcode
>> 8) & 0xf,
1007 (int) (opcode
>> 12) & 0xf);
1011 unsigned rm
= (opcode
>> 0) & 0xf;
1012 unsigned rd
= (opcode
>> 12) & 0xf;
1014 sprintf(cp
, "%s%s\tr%d, r%d", mnemonic
, COND(opcode
), rm
, rd
);
1019 /* these opcodes might be used someday */
1020 sprintf(cp
, "UNDEFINED");
1024 /* Miscellaneous load/store instructions */
1025 static int evaluate_misc_load_store(uint32_t opcode
,
1026 uint32_t address
, struct arm_instruction
*instruction
)
1028 uint8_t P
, U
, I
, W
, L
, S
, H
;
1030 char *operation
;/* "LDR" or "STR" */
1031 char *suffix
; /* "H", "SB", "SH", "D" */
1035 P
= (opcode
& 0x01000000) >> 24;
1036 U
= (opcode
& 0x00800000) >> 23;
1037 I
= (opcode
& 0x00400000) >> 22;
1038 W
= (opcode
& 0x00200000) >> 21;
1039 L
= (opcode
& 0x00100000) >> 20;
1040 S
= (opcode
& 0x00000040) >> 6;
1041 H
= (opcode
& 0x00000020) >> 5;
1043 /* target register */
1044 Rd
= (opcode
& 0xf000) >> 12;
1047 Rn
= (opcode
& 0xf0000) >> 16;
1049 instruction
->info
.load_store
.Rd
= Rd
;
1050 instruction
->info
.load_store
.Rn
= Rn
;
1051 instruction
->info
.load_store
.U
= U
;
1053 /* determine instruction type and suffix */
1054 if (S
) {/* signed */
1058 instruction
->type
= ARM_LDRSH
;
1062 instruction
->type
= ARM_LDRSB
;
1065 } else {/* there are no signed stores, so this is used to encode double-register
1070 instruction
->type
= ARM_STRD
;
1073 instruction
->type
= ARM_LDRD
;
1076 } else {/* unsigned */
1080 instruction
->type
= ARM_LDRH
;
1083 instruction
->type
= ARM_STRH
;
1087 if (I
) {/* Immediate offset/index (#+-<offset_8>)*/
1088 uint32_t offset_8
= ((opcode
& 0xf00) >> 4) | (opcode
& 0xf);
1089 snprintf(offset
, 32, "#%s0x%" PRIx32
"", (U
) ? "" : "-", offset_8
);
1091 instruction
->info
.load_store
.offset_mode
= 0;
1092 instruction
->info
.load_store
.offset
.offset
= offset_8
;
1093 } else {/* Register offset/index (+-<Rm>) */
1095 Rm
= (opcode
& 0xf);
1096 snprintf(offset
, 32, "%sr%i", (U
) ? "" : "-", Rm
);
1098 instruction
->info
.load_store
.offset_mode
= 1;
1099 instruction
->info
.load_store
.offset
.reg
.Rm
= Rm
;
1100 instruction
->info
.load_store
.offset
.reg
.shift
= 0x0;
1101 instruction
->info
.load_store
.offset
.reg
.shift_imm
= 0x0;
1105 if (W
== 0) { /* offset */
1106 snprintf(instruction
->text
,
1108 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\t%s%s%s r%i, [r%i, %s]",
1118 instruction
->info
.load_store
.index_mode
= 0;
1119 } else {/* pre-indexed */
1120 snprintf(instruction
->text
,
1122 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\t%s%s%s r%i, [r%i, %s]!",
1132 instruction
->info
.load_store
.index_mode
= 1;
1134 } else {/* post-indexed */
1135 snprintf(instruction
->text
,
1137 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\t%s%s%s r%i, [r%i], %s",
1147 instruction
->info
.load_store
.index_mode
= 2;
1153 /* Load/store multiples instructions */
1154 static int evaluate_ldm_stm(uint32_t opcode
,
1155 uint32_t address
, struct arm_instruction
*instruction
)
1157 uint8_t P
, U
, S
, W
, L
, Rn
;
1158 uint32_t register_list
;
1159 char *addressing_mode
;
1166 P
= (opcode
& 0x01000000) >> 24;
1167 U
= (opcode
& 0x00800000) >> 23;
1168 S
= (opcode
& 0x00400000) >> 22;
1169 W
= (opcode
& 0x00200000) >> 21;
1170 L
= (opcode
& 0x00100000) >> 20;
1171 register_list
= (opcode
& 0xffff);
1172 Rn
= (opcode
& 0xf0000) >> 16;
1174 instruction
->info
.load_store_multiple
.Rn
= Rn
;
1175 instruction
->info
.load_store_multiple
.register_list
= register_list
;
1176 instruction
->info
.load_store_multiple
.S
= S
;
1177 instruction
->info
.load_store_multiple
.W
= W
;
1180 instruction
->type
= ARM_LDM
;
1183 instruction
->type
= ARM_STM
;
1189 instruction
->info
.load_store_multiple
.addressing_mode
= 1;
1190 addressing_mode
= "IB";
1192 instruction
->info
.load_store_multiple
.addressing_mode
= 3;
1193 addressing_mode
= "DB";
1197 instruction
->info
.load_store_multiple
.addressing_mode
= 0;
1198 /* "IA" is the default in UAL syntax */
1199 addressing_mode
= "";
1201 instruction
->info
.load_store_multiple
.addressing_mode
= 2;
1202 addressing_mode
= "DA";
1206 reg_list_p
= reg_list
;
1207 for (i
= 0; i
<= 15; i
++) {
1208 if ((register_list
>> i
) & 1) {
1211 reg_list_p
+= snprintf(reg_list_p
,
1212 (reg_list
+ 69 - reg_list_p
),
1216 reg_list_p
+= snprintf(reg_list_p
,
1217 (reg_list
+ 69 - reg_list_p
),
1223 snprintf(instruction
->text
, 128,
1224 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
1225 "\t%s%s%s r%i%s, {%s}%s",
1227 mnemonic
, addressing_mode
, COND(opcode
),
1228 Rn
, (W
) ? "!" : "", reg_list
, (S
) ? "^" : "");
1233 /* Multiplies, extra load/stores */
1234 static int evaluate_mul_and_extra_ld_st(uint32_t opcode
,
1235 uint32_t address
, struct arm_instruction
*instruction
)
1237 /* Multiply (accumulate) (long) and Swap/swap byte */
1238 if ((opcode
& 0x000000f0) == 0x00000090) {
1239 /* Multiply (accumulate) */
1240 if ((opcode
& 0x0f800000) == 0x00000000) {
1241 uint8_t Rm
, Rs
, Rn
, Rd
, S
;
1243 Rs
= (opcode
& 0xf00) >> 8;
1244 Rn
= (opcode
& 0xf000) >> 12;
1245 Rd
= (opcode
& 0xf0000) >> 16;
1246 S
= (opcode
& 0x00100000) >> 20;
1248 /* examine A bit (accumulate) */
1249 if (opcode
& 0x00200000) {
1250 instruction
->type
= ARM_MLA
;
1251 snprintf(instruction
->text
,
1253 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tMLA%s%s r%i, r%i, r%i, r%i",
1263 instruction
->type
= ARM_MUL
;
1264 snprintf(instruction
->text
,
1266 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tMUL%s%s r%i, r%i, r%i",
1279 /* Multiply (accumulate) long */
1280 if ((opcode
& 0x0f800000) == 0x00800000) {
1281 char *mnemonic
= NULL
;
1282 uint8_t Rm
, Rs
, RdHi
, RdLow
, S
;
1284 Rs
= (opcode
& 0xf00) >> 8;
1285 RdHi
= (opcode
& 0xf000) >> 12;
1286 RdLow
= (opcode
& 0xf0000) >> 16;
1287 S
= (opcode
& 0x00100000) >> 20;
1289 switch ((opcode
& 0x00600000) >> 21) {
1291 instruction
->type
= ARM_UMULL
;
1295 instruction
->type
= ARM_UMLAL
;
1299 instruction
->type
= ARM_SMULL
;
1303 instruction
->type
= ARM_SMLAL
;
1308 snprintf(instruction
->text
,
1310 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\t%s%s%s r%i, r%i, r%i, r%i",
1324 /* Swap/swap byte */
1325 if ((opcode
& 0x0f800000) == 0x01000000) {
1328 Rd
= (opcode
& 0xf000) >> 12;
1329 Rn
= (opcode
& 0xf0000) >> 16;
1331 /* examine B flag */
1332 instruction
->type
= (opcode
& 0x00400000) ? ARM_SWPB
: ARM_SWP
;
1334 snprintf(instruction
->text
,
1336 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\t%s%s r%i, r%i, [r%i]",
1339 (opcode
& 0x00400000) ? "SWPB" : "SWP",
1349 return evaluate_misc_load_store(opcode
, address
, instruction
);
1352 static int evaluate_mrs_msr(uint32_t opcode
,
1353 uint32_t address
, struct arm_instruction
*instruction
)
1355 int R
= (opcode
& 0x00400000) >> 22;
1356 char *PSR
= (R
) ? "SPSR" : "CPSR";
1358 /* Move register to status register (MSR) */
1359 if (opcode
& 0x00200000) {
1360 instruction
->type
= ARM_MSR
;
1362 /* immediate variant */
1363 if (opcode
& 0x02000000) {
1364 uint8_t immediate
= (opcode
& 0xff);
1365 uint8_t rotate
= (opcode
& 0xf00);
1367 snprintf(instruction
->text
,
1369 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tMSR%s %s_%s%s%s%s, 0x%8.8" PRIx32
,
1374 (opcode
& 0x10000) ? "c" : "",
1375 (opcode
& 0x20000) ? "x" : "",
1376 (opcode
& 0x40000) ? "s" : "",
1377 (opcode
& 0x80000) ? "f" : "",
1378 ror(immediate
, (rotate
* 2))
1380 } else {/* register variant */
1381 uint8_t Rm
= opcode
& 0xf;
1382 snprintf(instruction
->text
,
1384 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tMSR%s %s_%s%s%s%s, r%i",
1389 (opcode
& 0x10000) ? "c" : "",
1390 (opcode
& 0x20000) ? "x" : "",
1391 (opcode
& 0x40000) ? "s" : "",
1392 (opcode
& 0x80000) ? "f" : "",
1397 } else {/* Move status register to register (MRS) */
1400 instruction
->type
= ARM_MRS
;
1401 Rd
= (opcode
& 0x0000f000) >> 12;
1403 snprintf(instruction
->text
,
1405 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tMRS%s r%i, %s",
1416 /* Miscellaneous instructions */
1417 static int evaluate_misc_instr(uint32_t opcode
,
1418 uint32_t address
, struct arm_instruction
*instruction
)
1421 if ((opcode
& 0x000000f0) == 0x00000000)
1422 evaluate_mrs_msr(opcode
, address
, instruction
);
1425 if ((opcode
& 0x006000f0) == 0x00200010) {
1427 instruction
->type
= ARM_BX
;
1430 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tBX%s r%i",
1431 address
, opcode
, COND(opcode
), Rm
);
1433 instruction
->info
.b_bl_bx_blx
.reg_operand
= Rm
;
1434 instruction
->info
.b_bl_bx_blx
.target_address
= -1;
1437 /* BXJ - "Jazelle" support (ARMv5-J) */
1438 if ((opcode
& 0x006000f0) == 0x00200020) {
1440 instruction
->type
= ARM_BX
;
1443 snprintf(instruction
->text
, 128,
1444 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tBXJ%s r%i",
1445 address
, opcode
, COND(opcode
), Rm
);
1447 instruction
->info
.b_bl_bx_blx
.reg_operand
= Rm
;
1448 instruction
->info
.b_bl_bx_blx
.target_address
= -1;
1452 if ((opcode
& 0x006000f0) == 0x00600010) {
1454 instruction
->type
= ARM_CLZ
;
1456 Rd
= (opcode
& 0xf000) >> 12;
1458 snprintf(instruction
->text
,
1460 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tCLZ%s r%i, r%i",
1469 if ((opcode
& 0x006000f0) == 0x00200030) {
1471 instruction
->type
= ARM_BLX
;
1474 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tBLX%s r%i",
1475 address
, opcode
, COND(opcode
), Rm
);
1477 instruction
->info
.b_bl_bx_blx
.reg_operand
= Rm
;
1478 instruction
->info
.b_bl_bx_blx
.target_address
= -1;
1481 /* Enhanced DSP add/subtracts */
1482 if ((opcode
& 0x0000000f0) == 0x00000050) {
1484 char *mnemonic
= NULL
;
1486 Rd
= (opcode
& 0xf000) >> 12;
1487 Rn
= (opcode
& 0xf0000) >> 16;
1489 switch ((opcode
& 0x00600000) >> 21) {
1491 instruction
->type
= ARM_QADD
;
1495 instruction
->type
= ARM_QSUB
;
1499 instruction
->type
= ARM_QDADD
;
1503 instruction
->type
= ARM_QDSUB
;
1508 snprintf(instruction
->text
,
1510 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\t%s%s r%i, r%i, r%i",
1520 /* exception return */
1521 if ((opcode
& 0x0000000f0) == 0x00000060) {
1522 if (((opcode
& 0x600000) >> 21) == 3)
1523 instruction
->type
= ARM_ERET
;
1524 snprintf(instruction
->text
,
1526 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tERET",
1531 /* exception generate instructions */
1532 if ((opcode
& 0x0000000f0) == 0x00000070) {
1533 uint32_t immediate
= 0;
1534 char *mnemonic
= NULL
;
1536 switch ((opcode
& 0x600000) >> 21) {
1538 instruction
->type
= ARM_BKPT
;
1540 immediate
= ((opcode
& 0x000fff00) >> 4) | (opcode
& 0xf);
1543 instruction
->type
= ARM_HVC
;
1545 immediate
= ((opcode
& 0x000fff00) >> 4) | (opcode
& 0xf);
1548 instruction
->type
= ARM_SMC
;
1550 immediate
= (opcode
& 0xf);
1554 snprintf(instruction
->text
,
1556 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\t%s 0x%4.4" PRIx32
"",
1563 /* Enhanced DSP multiplies */
1564 if ((opcode
& 0x000000090) == 0x00000080) {
1565 int x
= (opcode
& 0x20) >> 5;
1566 int y
= (opcode
& 0x40) >> 6;
1569 if ((opcode
& 0x00600000) == 0x00000000) {
1570 uint8_t Rd
, Rm
, Rs
, Rn
;
1571 instruction
->type
= ARM_SMLAxy
;
1572 Rd
= (opcode
& 0xf0000) >> 16;
1573 Rm
= (opcode
& 0xf);
1574 Rs
= (opcode
& 0xf00) >> 8;
1575 Rn
= (opcode
& 0xf000) >> 12;
1577 snprintf(instruction
->text
,
1579 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tSMLA%s%s%s r%i, r%i, r%i, r%i",
1592 if ((opcode
& 0x00600000) == 0x00400000) {
1593 uint8_t RdLow
, RdHi
, Rm
, Rs
;
1594 instruction
->type
= ARM_SMLAxy
;
1595 RdHi
= (opcode
& 0xf0000) >> 16;
1596 RdLow
= (opcode
& 0xf000) >> 12;
1597 Rm
= (opcode
& 0xf);
1598 Rs
= (opcode
& 0xf00) >> 8;
1600 snprintf(instruction
->text
,
1602 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tSMLA%s%s%s r%i, r%i, r%i, r%i",
1615 if (((opcode
& 0x00600000) == 0x00200000) && (x
== 0)) {
1616 uint8_t Rd
, Rm
, Rs
, Rn
;
1617 instruction
->type
= ARM_SMLAWy
;
1618 Rd
= (opcode
& 0xf0000) >> 16;
1619 Rm
= (opcode
& 0xf);
1620 Rs
= (opcode
& 0xf00) >> 8;
1621 Rn
= (opcode
& 0xf000) >> 12;
1623 snprintf(instruction
->text
,
1625 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tSMLAW%s%s r%i, r%i, r%i, r%i",
1637 if ((opcode
& 0x00600000) == 0x00600000) {
1639 instruction
->type
= ARM_SMULxy
;
1640 Rd
= (opcode
& 0xf0000) >> 16;
1641 Rm
= (opcode
& 0xf);
1642 Rs
= (opcode
& 0xf00) >> 8;
1644 snprintf(instruction
->text
,
1646 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tSMULW%s%s%s r%i, r%i, r%i",
1658 if (((opcode
& 0x00600000) == 0x00200000) && (x
== 1)) {
1660 instruction
->type
= ARM_SMULWy
;
1661 Rd
= (opcode
& 0xf0000) >> 16;
1662 Rm
= (opcode
& 0xf);
1663 Rs
= (opcode
& 0xf00) >> 8;
1665 snprintf(instruction
->text
,
1667 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tSMULW%s%s r%i, r%i, r%i",
1681 static int evaluate_mov_imm(uint32_t opcode
,
1682 uint32_t address
, struct arm_instruction
*instruction
)
1688 Rd
= (opcode
& 0xf000) >> 12;
1689 T
= opcode
& 0x00400000;
1690 immediate
= (opcode
& 0xf0000) >> 4 | (opcode
& 0xfff);
1692 instruction
->type
= ARM_MOV
;
1693 instruction
->info
.data_proc
.Rd
= Rd
;
1695 snprintf(instruction
->text
,
1697 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tMOV%s%s r%i, #0x%" PRIx16
,
1708 static int evaluate_data_proc(uint32_t opcode
,
1709 uint32_t address
, struct arm_instruction
*instruction
)
1711 uint8_t I
, op
, S
, Rn
, Rd
;
1712 char *mnemonic
= NULL
;
1713 char shifter_operand
[32];
1715 I
= (opcode
& 0x02000000) >> 25;
1716 op
= (opcode
& 0x01e00000) >> 21;
1717 S
= (opcode
& 0x00100000) >> 20;
1719 Rd
= (opcode
& 0xf000) >> 12;
1720 Rn
= (opcode
& 0xf0000) >> 16;
1722 instruction
->info
.data_proc
.Rd
= Rd
;
1723 instruction
->info
.data_proc
.Rn
= Rn
;
1724 instruction
->info
.data_proc
.S
= S
;
1728 instruction
->type
= ARM_AND
;
1732 instruction
->type
= ARM_EOR
;
1736 instruction
->type
= ARM_SUB
;
1740 instruction
->type
= ARM_RSB
;
1744 instruction
->type
= ARM_ADD
;
1748 instruction
->type
= ARM_ADC
;
1752 instruction
->type
= ARM_SBC
;
1756 instruction
->type
= ARM_RSC
;
1760 instruction
->type
= ARM_TST
;
1764 instruction
->type
= ARM_TEQ
;
1768 instruction
->type
= ARM_CMP
;
1772 instruction
->type
= ARM_CMN
;
1776 instruction
->type
= ARM_ORR
;
1780 instruction
->type
= ARM_MOV
;
1784 instruction
->type
= ARM_BIC
;
1788 instruction
->type
= ARM_MVN
;
1793 if (I
) {/* immediate shifter operand (#<immediate>)*/
1794 uint8_t immed_8
= opcode
& 0xff;
1795 uint8_t rotate_imm
= (opcode
& 0xf00) >> 8;
1798 immediate
= ror(immed_8
, rotate_imm
* 2);
1800 snprintf(shifter_operand
, 32, "#0x%" PRIx32
"", immediate
);
1802 instruction
->info
.data_proc
.variant
= 0;
1803 instruction
->info
.data_proc
.shifter_operand
.immediate
.immediate
= immediate
;
1804 } else {/* register-based shifter operand */
1806 shift
= (opcode
& 0x60) >> 5;
1807 Rm
= (opcode
& 0xf);
1809 if ((opcode
& 0x10) != 0x10) { /* Immediate shifts ("<Rm>" or "<Rm>, <shift>
1810 *#<shift_immediate>") */
1812 shift_imm
= (opcode
& 0xf80) >> 7;
1814 instruction
->info
.data_proc
.variant
= 1;
1815 instruction
->info
.data_proc
.shifter_operand
.immediate_shift
.Rm
= Rm
;
1816 instruction
->info
.data_proc
.shifter_operand
.immediate_shift
.shift_imm
=
1818 instruction
->info
.data_proc
.shifter_operand
.immediate_shift
.shift
= shift
;
1820 /* LSR encodes a shift by 32 bit as 0x0 */
1821 if ((shift
== 0x1) && (shift_imm
== 0x0))
1824 /* ASR encodes a shift by 32 bit as 0x0 */
1825 if ((shift
== 0x2) && (shift_imm
== 0x0))
1828 /* ROR by 32 bit is actually a RRX */
1829 if ((shift
== 0x3) && (shift_imm
== 0x0))
1832 if ((shift_imm
== 0x0) && (shift
== 0x0))
1833 snprintf(shifter_operand
, 32, "r%i", Rm
);
1835 if (shift
== 0x0) /* LSL */
1836 snprintf(shifter_operand
,
1841 else if (shift
== 0x1) /* LSR */
1842 snprintf(shifter_operand
,
1847 else if (shift
== 0x2) /* ASR */
1848 snprintf(shifter_operand
,
1853 else if (shift
== 0x3) /* ROR */
1854 snprintf(shifter_operand
,
1859 else if (shift
== 0x4) /* RRX */
1860 snprintf(shifter_operand
, 32, "r%i, RRX", Rm
);
1862 } else {/* Register shifts ("<Rm>, <shift> <Rs>") */
1863 uint8_t Rs
= (opcode
& 0xf00) >> 8;
1865 instruction
->info
.data_proc
.variant
= 2;
1866 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rm
= Rm
;
1867 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rs
= Rs
;
1868 instruction
->info
.data_proc
.shifter_operand
.register_shift
.shift
= shift
;
1870 if (shift
== 0x0) /* LSL */
1871 snprintf(shifter_operand
, 32, "r%i, LSL r%i", Rm
, Rs
);
1872 else if (shift
== 0x1) /* LSR */
1873 snprintf(shifter_operand
, 32, "r%i, LSR r%i", Rm
, Rs
);
1874 else if (shift
== 0x2) /* ASR */
1875 snprintf(shifter_operand
, 32, "r%i, ASR r%i", Rm
, Rs
);
1876 else if (shift
== 0x3) /* ROR */
1877 snprintf(shifter_operand
, 32, "r%i, ROR r%i", Rm
, Rs
);
1881 if ((op
< 0x8) || (op
== 0xc) || (op
== 0xe)) { /* <opcode3>{<cond>}{S} <Rd>, <Rn>,
1882 *<shifter_operand> */
1883 snprintf(instruction
->text
,
1885 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\t%s%s%s r%i, r%i, %s",
1894 } else if ((op
== 0xd) || (op
== 0xf)) { /* <opcode1>{<cond>}{S} <Rd>,
1895 *<shifter_operand> */
1896 if (opcode
== 0xe1a00000) /* print MOV r0,r0 as NOP */
1897 snprintf(instruction
->text
,
1899 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tNOP",
1903 snprintf(instruction
->text
,
1905 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\t%s%s%s r%i, %s",
1913 } else {/* <opcode2>{<cond>} <Rn>, <shifter_operand> */
1914 snprintf(instruction
->text
, 128, "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\t%s%s r%i, %s",
1915 address
, opcode
, mnemonic
, COND(opcode
),
1916 Rn
, shifter_operand
);
1922 int arm_evaluate_opcode(uint32_t opcode
, uint32_t address
,
1923 struct arm_instruction
*instruction
)
1925 /* clear fields, to avoid confusion */
1926 memset(instruction
, 0, sizeof(struct arm_instruction
));
1927 instruction
->opcode
= opcode
;
1928 instruction
->instruction_size
= 4;
1930 /* catch opcodes with condition field [31:28] = b1111 */
1931 if ((opcode
& 0xf0000000) == 0xf0000000) {
1932 /* Undefined instruction (or ARMv5E cache preload PLD) */
1933 if ((opcode
& 0x08000000) == 0x00000000)
1934 return evaluate_pld(opcode
, address
, instruction
);
1936 /* Undefined instruction (or ARMv6+ SRS/RFE) */
1937 if ((opcode
& 0x0e000000) == 0x08000000)
1938 return evaluate_srs(opcode
, address
, instruction
);
1940 /* Branch and branch with link and change to Thumb */
1941 if ((opcode
& 0x0e000000) == 0x0a000000)
1942 return evaluate_blx_imm(opcode
, address
, instruction
);
1944 /* Extended coprocessor opcode space (ARMv5 and higher)
1945 * Coprocessor load/store and double register transfers */
1946 if ((opcode
& 0x0e000000) == 0x0c000000)
1947 return evaluate_ldc_stc_mcrr_mrrc(opcode
, address
, instruction
);
1949 /* Coprocessor data processing */
1950 if ((opcode
& 0x0f000100) == 0x0c000000)
1951 return evaluate_cdp_mcr_mrc(opcode
, address
, instruction
);
1953 /* Coprocessor register transfers */
1954 if ((opcode
& 0x0f000010) == 0x0c000010)
1955 return evaluate_cdp_mcr_mrc(opcode
, address
, instruction
);
1957 /* Undefined instruction */
1958 if ((opcode
& 0x0f000000) == 0x0f000000) {
1959 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
1960 snprintf(instruction
->text
,
1962 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tUNDEFINED INSTRUCTION",
1969 /* catch opcodes with [27:25] = b000 */
1970 if ((opcode
& 0x0e000000) == 0x00000000) {
1971 /* Multiplies, extra load/stores */
1972 if ((opcode
& 0x00000090) == 0x00000090)
1973 return evaluate_mul_and_extra_ld_st(opcode
, address
, instruction
);
1975 /* Miscellaneous instructions */
1976 if ((opcode
& 0x0f900000) == 0x01000000)
1977 return evaluate_misc_instr(opcode
, address
, instruction
);
1979 return evaluate_data_proc(opcode
, address
, instruction
);
1982 /* catch opcodes with [27:25] = b001 */
1983 if ((opcode
& 0x0e000000) == 0x02000000) {
1984 /* 16-bit immediate load */
1985 if ((opcode
& 0x0fb00000) == 0x03000000)
1986 return evaluate_mov_imm(opcode
, address
, instruction
);
1988 /* Move immediate to status register */
1989 if ((opcode
& 0x0fb00000) == 0x03200000)
1990 return evaluate_mrs_msr(opcode
, address
, instruction
);
1992 return evaluate_data_proc(opcode
, address
, instruction
);
1996 /* catch opcodes with [27:25] = b010 */
1997 if ((opcode
& 0x0e000000) == 0x04000000) {
1998 /* Load/store immediate offset */
1999 return evaluate_load_store(opcode
, address
, instruction
);
2002 /* catch opcodes with [27:25] = b011 */
2003 if ((opcode
& 0x0e000000) == 0x06000000) {
2004 /* Load/store register offset */
2005 if ((opcode
& 0x00000010) == 0x00000000)
2006 return evaluate_load_store(opcode
, address
, instruction
);
2008 /* Architecturally Undefined instruction
2009 * ... don't expect these to ever be used
2011 if ((opcode
& 0x07f000f0) == 0x07f000f0) {
2012 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
2013 snprintf(instruction
->text
, 128,
2014 "0x%8.8" PRIx32
"\t0x%8.8" PRIx32
"\tUNDEF",
2019 /* "media" instructions */
2020 return evaluate_media(opcode
, address
, instruction
);
2023 /* catch opcodes with [27:25] = b100 */
2024 if ((opcode
& 0x0e000000) == 0x08000000) {
2025 /* Load/store multiple */
2026 return evaluate_ldm_stm(opcode
, address
, instruction
);
2029 /* catch opcodes with [27:25] = b101 */
2030 if ((opcode
& 0x0e000000) == 0x0a000000) {
2031 /* Branch and branch with link */
2032 return evaluate_b_bl(opcode
, address
, instruction
);
2035 /* catch opcodes with [27:25] = b110 */
2036 if ((opcode
& 0x0e000000) == 0x0c000000) {
2037 /* Coprocessor load/store and double register transfers */
2038 return evaluate_ldc_stc_mcrr_mrrc(opcode
, address
, instruction
);
2041 /* catch opcodes with [27:25] = b111 */
2042 if ((opcode
& 0x0e000000) == 0x0e000000) {
2043 /* Software interrupt */
2044 if ((opcode
& 0x0f000000) == 0x0f000000)
2045 return evaluate_swi(opcode
, address
, instruction
);
2047 /* Coprocessor data processing */
2048 if ((opcode
& 0x0f000010) == 0x0e000000)
2049 return evaluate_cdp_mcr_mrc(opcode
, address
, instruction
);
2051 /* Coprocessor register transfers */
2052 if ((opcode
& 0x0f000010) == 0x0e000010)
2053 return evaluate_cdp_mcr_mrc(opcode
, address
, instruction
);
2056 LOG_ERROR("ARM: should never reach this point (opcode=%08x)",
2061 static int evaluate_b_bl_blx_thumb(uint16_t opcode
,
2062 uint32_t address
, struct arm_instruction
*instruction
)
2064 uint32_t offset
= opcode
& 0x7ff;
2065 uint32_t opc
= (opcode
>> 11) & 0x3;
2066 uint32_t target_address
;
2067 char *mnemonic
= NULL
;
2069 /* sign extend 11-bit offset */
2070 if (((opc
== 0) || (opc
== 2)) && (offset
& 0x00000400))
2071 offset
= 0xfffff800 | offset
;
2073 target_address
= address
+ 4 + (offset
<< 1);
2076 /* unconditional branch */
2078 instruction
->type
= ARM_B
;
2083 instruction
->type
= ARM_BLX
;
2085 target_address
&= 0xfffffffc;
2089 instruction
->type
= ARM_UNKNOWN_INSTRUCTION
;
2090 mnemonic
= "prefix";
2091 target_address
= offset
<< 12;
2095 instruction
->type
= ARM_BL
;
2100 /* TODO: deal correctly with dual opcode (prefixed) BL/BLX;
2101 * these are effectively 32-bit instructions even in Thumb1. For
2102 * disassembly, it's simplest to always use the Thumb2 decoder.
2104 * But some cores will evidently handle them as two instructions,
2105 * where exceptions may occur between the two. The ETMv3.2+ ID
2106 * register has a bit which exposes this behavior.
2109 snprintf(instruction
->text
, 128,
2110 "0x%8.8" PRIx32
" 0x%4.4x \t%s\t%#8.8" PRIx32
,
2111 address
, opcode
, mnemonic
, target_address
);
2113 instruction
->info
.b_bl_bx_blx
.reg_operand
= -1;
2114 instruction
->info
.b_bl_bx_blx
.target_address
= target_address
;
2119 static int evaluate_add_sub_thumb(uint16_t opcode
,
2120 uint32_t address
, struct arm_instruction
*instruction
)
2122 uint8_t Rd
= (opcode
>> 0) & 0x7;
2123 uint8_t Rn
= (opcode
>> 3) & 0x7;
2124 uint8_t Rm_imm
= (opcode
>> 6) & 0x7;
2125 uint32_t opc
= opcode
& (1 << 9);
2126 uint32_t reg_imm
= opcode
& (1 << 10);
2130 instruction
->type
= ARM_SUB
;
2133 /* REVISIT: if reg_imm == 0, display as "MOVS" */
2134 instruction
->type
= ARM_ADD
;
2138 instruction
->info
.data_proc
.Rd
= Rd
;
2139 instruction
->info
.data_proc
.Rn
= Rn
;
2140 instruction
->info
.data_proc
.S
= 1;
2143 instruction
->info
.data_proc
.variant
= 0;/*immediate*/
2144 instruction
->info
.data_proc
.shifter_operand
.immediate
.immediate
= Rm_imm
;
2145 snprintf(instruction
->text
, 128,
2146 "0x%8.8" PRIx32
" 0x%4.4x \t%s\tr%i, r%i, #%d",
2147 address
, opcode
, mnemonic
, Rd
, Rn
, Rm_imm
);
2149 instruction
->info
.data_proc
.variant
= 1;/*immediate shift*/
2150 instruction
->info
.data_proc
.shifter_operand
.immediate_shift
.Rm
= Rm_imm
;
2151 snprintf(instruction
->text
, 128,
2152 "0x%8.8" PRIx32
" 0x%4.4x \t%s\tr%i, r%i, r%i",
2153 address
, opcode
, mnemonic
, Rd
, Rn
, Rm_imm
);
2159 static int evaluate_shift_imm_thumb(uint16_t opcode
,
2160 uint32_t address
, struct arm_instruction
*instruction
)
2162 uint8_t Rd
= (opcode
>> 0) & 0x7;
2163 uint8_t Rm
= (opcode
>> 3) & 0x7;
2164 uint8_t imm
= (opcode
>> 6) & 0x1f;
2165 uint8_t opc
= (opcode
>> 11) & 0x3;
2166 char *mnemonic
= NULL
;
2170 instruction
->type
= ARM_MOV
;
2172 instruction
->info
.data_proc
.shifter_operand
.immediate_shift
.shift
= 0;
2175 instruction
->type
= ARM_MOV
;
2177 instruction
->info
.data_proc
.shifter_operand
.immediate_shift
.shift
= 1;
2180 instruction
->type
= ARM_MOV
;
2182 instruction
->info
.data_proc
.shifter_operand
.immediate_shift
.shift
= 2;
2186 if ((imm
== 0) && (opc
!= 0))
2189 instruction
->info
.data_proc
.Rd
= Rd
;
2190 instruction
->info
.data_proc
.Rn
= -1;
2191 instruction
->info
.data_proc
.S
= 1;
2193 instruction
->info
.data_proc
.variant
= 1;/*immediate_shift*/
2194 instruction
->info
.data_proc
.shifter_operand
.immediate_shift
.Rm
= Rm
;
2195 instruction
->info
.data_proc
.shifter_operand
.immediate_shift
.shift_imm
= imm
;
2197 snprintf(instruction
->text
, 128,
2198 "0x%8.8" PRIx32
" 0x%4.4x \t%s\tr%i, r%i, #%#2.2x",
2199 address
, opcode
, mnemonic
, Rd
, Rm
, imm
);
2204 static int evaluate_data_proc_imm_thumb(uint16_t opcode
,
2205 uint32_t address
, struct arm_instruction
*instruction
)
2207 uint8_t imm
= opcode
& 0xff;
2208 uint8_t Rd
= (opcode
>> 8) & 0x7;
2209 uint32_t opc
= (opcode
>> 11) & 0x3;
2210 char *mnemonic
= NULL
;
2212 instruction
->info
.data_proc
.Rd
= Rd
;
2213 instruction
->info
.data_proc
.Rn
= Rd
;
2214 instruction
->info
.data_proc
.S
= 1;
2215 instruction
->info
.data_proc
.variant
= 0;/*immediate*/
2216 instruction
->info
.data_proc
.shifter_operand
.immediate
.immediate
= imm
;
2220 instruction
->type
= ARM_MOV
;
2222 instruction
->info
.data_proc
.Rn
= -1;
2225 instruction
->type
= ARM_CMP
;
2227 instruction
->info
.data_proc
.Rd
= -1;
2230 instruction
->type
= ARM_ADD
;
2234 instruction
->type
= ARM_SUB
;
2239 snprintf(instruction
->text
, 128,
2240 "0x%8.8" PRIx32
" 0x%4.4x \t%s\tr%i, #%#2.2x",
2241 address
, opcode
, mnemonic
, Rd
, imm
);
2246 static int evaluate_data_proc_thumb(uint16_t opcode
,
2247 uint32_t address
, struct arm_instruction
*instruction
)
2249 uint8_t high_reg
, op
, Rm
, Rd
, H1
, H2
;
2250 char *mnemonic
= NULL
;
2253 high_reg
= (opcode
& 0x0400) >> 10;
2254 op
= (opcode
& 0x03C0) >> 6;
2256 Rd
= (opcode
& 0x0007);
2257 Rm
= (opcode
& 0x0038) >> 3;
2258 H1
= (opcode
& 0x0080) >> 7;
2259 H2
= (opcode
& 0x0040) >> 6;
2261 instruction
->info
.data_proc
.Rd
= Rd
;
2262 instruction
->info
.data_proc
.Rn
= Rd
;
2263 instruction
->info
.data_proc
.S
= (!high_reg
|| (instruction
->type
== ARM_CMP
));
2264 instruction
->info
.data_proc
.variant
= 1 /*immediate shift*/;
2265 instruction
->info
.data_proc
.shifter_operand
.immediate_shift
.Rm
= Rm
;
2274 instruction
->type
= ARM_ADD
;
2278 instruction
->type
= ARM_CMP
;
2282 instruction
->type
= ARM_MOV
;
2288 if ((opcode
& 0x7) == 0x0) {
2289 instruction
->info
.b_bl_bx_blx
.reg_operand
= Rm
;
2291 instruction
->type
= ARM_BLX
;
2292 snprintf(instruction
->text
, 128,
2294 " 0x%4.4x \tBLX\tr%i",
2295 address
, opcode
, Rm
);
2297 instruction
->type
= ARM_BX
;
2298 snprintf(instruction
->text
, 128,
2300 " 0x%4.4x \tBX\tr%i",
2301 address
, opcode
, Rm
);
2304 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
2305 snprintf(instruction
->text
, 128,
2308 "UNDEFINED INSTRUCTION",
2316 instruction
->type
= ARM_AND
;
2320 instruction
->type
= ARM_EOR
;
2324 instruction
->type
= ARM_MOV
;
2326 instruction
->info
.data_proc
.variant
= 2 /*register shift*/;
2327 instruction
->info
.data_proc
.shifter_operand
.register_shift
.shift
= 0;
2328 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rm
= Rd
;
2329 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rs
= Rm
;
2332 instruction
->type
= ARM_MOV
;
2334 instruction
->info
.data_proc
.variant
= 2 /*register shift*/;
2335 instruction
->info
.data_proc
.shifter_operand
.register_shift
.shift
= 1;
2336 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rm
= Rd
;
2337 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rs
= Rm
;
2340 instruction
->type
= ARM_MOV
;
2342 instruction
->info
.data_proc
.variant
= 2 /*register shift*/;
2343 instruction
->info
.data_proc
.shifter_operand
.register_shift
.shift
= 2;
2344 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rm
= Rd
;
2345 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rs
= Rm
;
2348 instruction
->type
= ARM_ADC
;
2352 instruction
->type
= ARM_SBC
;
2356 instruction
->type
= ARM_MOV
;
2358 instruction
->info
.data_proc
.variant
= 2 /*register shift*/;
2359 instruction
->info
.data_proc
.shifter_operand
.register_shift
.shift
= 3;
2360 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rm
= Rd
;
2361 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rs
= Rm
;
2364 instruction
->type
= ARM_TST
;
2368 instruction
->type
= ARM_RSB
;
2370 instruction
->info
.data_proc
.variant
= 0 /*immediate*/;
2371 instruction
->info
.data_proc
.shifter_operand
.immediate
.immediate
= 0;
2372 instruction
->info
.data_proc
.Rn
= Rm
;
2375 instruction
->type
= ARM_CMP
;
2379 instruction
->type
= ARM_CMN
;
2383 instruction
->type
= ARM_ORR
;
2387 instruction
->type
= ARM_MUL
;
2391 instruction
->type
= ARM_BIC
;
2395 instruction
->type
= ARM_MVN
;
2402 snprintf(instruction
->text
, 128,
2403 "0x%8.8" PRIx32
" 0x%4.4x \tNOP\t\t\t"
2405 address
, opcode
, mnemonic
, Rd
, Rm
);
2407 snprintf(instruction
->text
, 128,
2408 "0x%8.8" PRIx32
" 0x%4.4x \t%s\tr%i, r%i",
2409 address
, opcode
, mnemonic
, Rd
, Rm
);
2414 /* PC-relative data addressing is word-aligned even with Thumb */
2415 static inline uint32_t thumb_alignpc4(uint32_t addr
)
2417 return (addr
+ 4) & ~3;
2420 static int evaluate_load_literal_thumb(uint16_t opcode
,
2421 uint32_t address
, struct arm_instruction
*instruction
)
2424 uint8_t Rd
= (opcode
>> 8) & 0x7;
2426 instruction
->type
= ARM_LDR
;
2427 immediate
= opcode
& 0x000000ff;
2430 instruction
->info
.load_store
.Rd
= Rd
;
2431 instruction
->info
.load_store
.Rn
= 15 /*PC*/;
2432 instruction
->info
.load_store
.index_mode
= 0; /*offset*/
2433 instruction
->info
.load_store
.offset_mode
= 0; /*immediate*/
2434 instruction
->info
.load_store
.offset
.offset
= immediate
;
2436 snprintf(instruction
->text
, 128,
2437 "0x%8.8" PRIx32
" 0x%4.4x \t"
2438 "LDR\tr%i, [pc, #%#" PRIx32
"]\t; %#8.8" PRIx32
,
2439 address
, opcode
, Rd
, immediate
,
2440 thumb_alignpc4(address
) + immediate
);
2445 static int evaluate_load_store_reg_thumb(uint16_t opcode
,
2446 uint32_t address
, struct arm_instruction
*instruction
)
2448 uint8_t Rd
= (opcode
>> 0) & 0x7;
2449 uint8_t Rn
= (opcode
>> 3) & 0x7;
2450 uint8_t Rm
= (opcode
>> 6) & 0x7;
2451 uint8_t opc
= (opcode
>> 9) & 0x7;
2452 char *mnemonic
= NULL
;
2456 instruction
->type
= ARM_STR
;
2460 instruction
->type
= ARM_STRH
;
2464 instruction
->type
= ARM_STRB
;
2468 instruction
->type
= ARM_LDRSB
;
2472 instruction
->type
= ARM_LDR
;
2476 instruction
->type
= ARM_LDRH
;
2480 instruction
->type
= ARM_LDRB
;
2484 instruction
->type
= ARM_LDRSH
;
2489 snprintf(instruction
->text
, 128,
2490 "0x%8.8" PRIx32
" 0x%4.4x \t%s\tr%i, [r%i, r%i]",
2491 address
, opcode
, mnemonic
, Rd
, Rn
, Rm
);
2493 instruction
->info
.load_store
.Rd
= Rd
;
2494 instruction
->info
.load_store
.Rn
= Rn
;
2495 instruction
->info
.load_store
.index_mode
= 0; /*offset*/
2496 instruction
->info
.load_store
.offset_mode
= 1; /*register*/
2497 instruction
->info
.load_store
.offset
.reg
.Rm
= Rm
;
2502 static int evaluate_load_store_imm_thumb(uint16_t opcode
,
2503 uint32_t address
, struct arm_instruction
*instruction
)
2505 uint32_t offset
= (opcode
>> 6) & 0x1f;
2506 uint8_t Rd
= (opcode
>> 0) & 0x7;
2507 uint8_t Rn
= (opcode
>> 3) & 0x7;
2508 uint32_t L
= opcode
& (1 << 11);
2509 uint32_t B
= opcode
& (1 << 12);
2515 instruction
->type
= ARM_LDR
;
2518 instruction
->type
= ARM_STR
;
2522 if ((opcode
&0xF000) == 0x8000) {
2530 snprintf(instruction
->text
, 128,
2531 "0x%8.8" PRIx32
" 0x%4.4x \t%s%c\tr%i, [r%i, #%#" PRIx32
"]",
2532 address
, opcode
, mnemonic
, suffix
, Rd
, Rn
, offset
<< shift
);
2534 instruction
->info
.load_store
.Rd
= Rd
;
2535 instruction
->info
.load_store
.Rn
= Rn
;
2536 instruction
->info
.load_store
.index_mode
= 0; /*offset*/
2537 instruction
->info
.load_store
.offset_mode
= 0; /*immediate*/
2538 instruction
->info
.load_store
.offset
.offset
= offset
<< shift
;
2543 static int evaluate_load_store_stack_thumb(uint16_t opcode
,
2544 uint32_t address
, struct arm_instruction
*instruction
)
2546 uint32_t offset
= opcode
& 0xff;
2547 uint8_t Rd
= (opcode
>> 8) & 0x7;
2548 uint32_t L
= opcode
& (1 << 11);
2552 instruction
->type
= ARM_LDR
;
2555 instruction
->type
= ARM_STR
;
2559 snprintf(instruction
->text
, 128,
2560 "0x%8.8" PRIx32
" 0x%4.4x \t%s\tr%i, [SP, #%#" PRIx32
"]",
2561 address
, opcode
, mnemonic
, Rd
, offset
*4);
2563 instruction
->info
.load_store
.Rd
= Rd
;
2564 instruction
->info
.load_store
.Rn
= 13 /*SP*/;
2565 instruction
->info
.load_store
.index_mode
= 0; /*offset*/
2566 instruction
->info
.load_store
.offset_mode
= 0; /*immediate*/
2567 instruction
->info
.load_store
.offset
.offset
= offset
*4;
2572 static int evaluate_add_sp_pc_thumb(uint16_t opcode
,
2573 uint32_t address
, struct arm_instruction
*instruction
)
2575 uint32_t imm
= opcode
& 0xff;
2576 uint8_t Rd
= (opcode
>> 8) & 0x7;
2578 uint32_t SP
= opcode
& (1 << 11);
2579 const char *reg_name
;
2581 instruction
->type
= ARM_ADD
;
2591 snprintf(instruction
->text
, 128,
2592 "0x%8.8" PRIx32
" 0x%4.4x \tADD\tr%i, %s, #%#" PRIx32
,
2593 address
, opcode
, Rd
, reg_name
, imm
* 4);
2595 instruction
->info
.data_proc
.variant
= 0 /* immediate */;
2596 instruction
->info
.data_proc
.Rd
= Rd
;
2597 instruction
->info
.data_proc
.Rn
= Rn
;
2598 instruction
->info
.data_proc
.shifter_operand
.immediate
.immediate
= imm
*4;
2603 static int evaluate_adjust_stack_thumb(uint16_t opcode
,
2604 uint32_t address
, struct arm_instruction
*instruction
)
2606 uint32_t imm
= opcode
& 0x7f;
2607 uint8_t opc
= opcode
& (1 << 7);
2612 instruction
->type
= ARM_SUB
;
2615 instruction
->type
= ARM_ADD
;
2619 snprintf(instruction
->text
, 128,
2620 "0x%8.8" PRIx32
" 0x%4.4x \t%s\tSP, #%#" PRIx32
,
2621 address
, opcode
, mnemonic
, imm
*4);
2623 instruction
->info
.data_proc
.variant
= 0 /* immediate */;
2624 instruction
->info
.data_proc
.Rd
= 13 /*SP*/;
2625 instruction
->info
.data_proc
.Rn
= 13 /*SP*/;
2626 instruction
->info
.data_proc
.shifter_operand
.immediate
.immediate
= imm
*4;
2631 static int evaluate_breakpoint_thumb(uint16_t opcode
,
2632 uint32_t address
, struct arm_instruction
*instruction
)
2634 uint32_t imm
= opcode
& 0xff;
2636 instruction
->type
= ARM_BKPT
;
2638 snprintf(instruction
->text
, 128,
2639 "0x%8.8" PRIx32
" 0x%4.4x \tBKPT\t%#2.2" PRIx32
"",
2640 address
, opcode
, imm
);
2645 static int evaluate_load_store_multiple_thumb(uint16_t opcode
,
2646 uint32_t address
, struct arm_instruction
*instruction
)
2648 uint32_t reg_list
= opcode
& 0xff;
2649 uint32_t L
= opcode
& (1 << 11);
2650 uint32_t R
= opcode
& (1 << 8);
2651 uint8_t Rn
= (opcode
>> 8) & 7;
2652 uint8_t addr_mode
= 0 /* IA */;
2656 char ptr_name
[7] = "";
2659 /* REVISIT: in ThumbEE mode, there are no LDM or STM instructions.
2660 * The STMIA and LDMIA opcodes are used for other instructions.
2663 if ((opcode
& 0xf000) == 0xc000) { /* generic load/store multiple */
2667 instruction
->type
= ARM_LDM
;
2669 if (opcode
& (1 << Rn
))
2672 instruction
->type
= ARM_STM
;
2675 snprintf(ptr_name
, sizeof(ptr_name
), "r%i%s, ", Rn
, wback
);
2676 } else {/* push/pop */
2679 instruction
->type
= ARM_LDM
;
2682 reg_list
|= (1 << 15) /*PC*/;
2684 instruction
->type
= ARM_STM
;
2686 addr_mode
= 3; /*DB*/
2688 reg_list
|= (1 << 14) /*LR*/;
2692 reg_names_p
= reg_names
;
2693 for (i
= 0; i
<= 15; i
++) {
2694 if (reg_list
& (1 << i
))
2695 reg_names_p
+= snprintf(reg_names_p
,
2696 (reg_names
+ 40 - reg_names_p
),
2700 if (reg_names_p
> reg_names
)
2701 reg_names_p
[-2] = '\0';
2702 else /* invalid op : no registers */
2703 reg_names
[0] = '\0';
2705 snprintf(instruction
->text
, 128,
2706 "0x%8.8" PRIx32
" 0x%4.4x \t%s\t%s{%s}",
2707 address
, opcode
, mnemonic
, ptr_name
, reg_names
);
2709 instruction
->info
.load_store_multiple
.register_list
= reg_list
;
2710 instruction
->info
.load_store_multiple
.Rn
= Rn
;
2711 instruction
->info
.load_store_multiple
.addressing_mode
= addr_mode
;
2716 static int evaluate_cond_branch_thumb(uint16_t opcode
,
2717 uint32_t address
, struct arm_instruction
*instruction
)
2719 uint32_t offset
= opcode
& 0xff;
2720 uint8_t cond
= (opcode
>> 8) & 0xf;
2721 uint32_t target_address
;
2724 instruction
->type
= ARM_SWI
;
2725 snprintf(instruction
->text
, 128,
2726 "0x%8.8" PRIx32
" 0x%4.4x \tSVC\t%#2.2" PRIx32
,
2727 address
, opcode
, offset
);
2729 } else if (cond
== 0xe) {
2730 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
2731 snprintf(instruction
->text
, 128,
2732 "0x%8.8" PRIx32
" 0x%4.4x \tUNDEFINED INSTRUCTION",
2737 /* sign extend 8-bit offset */
2738 if (offset
& 0x00000080)
2739 offset
= 0xffffff00 | offset
;
2741 target_address
= address
+ 4 + (offset
<< 1);
2743 snprintf(instruction
->text
, 128,
2744 "0x%8.8" PRIx32
" 0x%4.4x \tB%s\t%#8.8" PRIx32
,
2746 arm_condition_strings
[cond
], target_address
);
2748 instruction
->type
= ARM_B
;
2749 instruction
->info
.b_bl_bx_blx
.reg_operand
= -1;
2750 instruction
->info
.b_bl_bx_blx
.target_address
= target_address
;
2755 static int evaluate_cb_thumb(uint16_t opcode
, uint32_t address
,
2756 struct arm_instruction
*instruction
)
2760 /* added in Thumb2 */
2761 offset
= (opcode
>> 3) & 0x1f;
2762 offset
|= (opcode
& 0x0200) >> 4;
2764 snprintf(instruction
->text
, 128,
2765 "0x%8.8" PRIx32
" 0x%4.4x \tCB%sZ\tr%d, %#8.8" PRIx32
,
2767 (opcode
& 0x0800) ? "N" : "",
2768 opcode
& 0x7, address
+ 4 + (offset
<< 1));
2773 static int evaluate_extend_thumb(uint16_t opcode
, uint32_t address
,
2774 struct arm_instruction
*instruction
)
2776 /* added in ARMv6 */
2777 snprintf(instruction
->text
, 128,
2778 "0x%8.8" PRIx32
" 0x%4.4x \t%cXT%c\tr%d, r%d",
2780 (opcode
& 0x0080) ? 'U' : 'S',
2781 (opcode
& 0x0040) ? 'B' : 'H',
2782 opcode
& 0x7, (opcode
>> 3) & 0x7);
2787 static int evaluate_cps_thumb(uint16_t opcode
, uint32_t address
,
2788 struct arm_instruction
*instruction
)
2790 /* added in ARMv6 */
2791 if ((opcode
& 0x0ff0) == 0x0650)
2792 snprintf(instruction
->text
, 128,
2793 "0x%8.8" PRIx32
" 0x%4.4x \tSETEND %s",
2795 (opcode
& 0x80) ? "BE" : "LE");
2796 else /* ASSUME (opcode & 0x0fe0) == 0x0660 */
2797 snprintf(instruction
->text
, 128,
2798 "0x%8.8" PRIx32
" 0x%4.4x \tCPSI%c\t%s%s%s",
2800 (opcode
& 0x0010) ? 'D' : 'E',
2801 (opcode
& 0x0004) ? "A" : "",
2802 (opcode
& 0x0002) ? "I" : "",
2803 (opcode
& 0x0001) ? "F" : "");
2808 static int evaluate_byterev_thumb(uint16_t opcode
, uint32_t address
,
2809 struct arm_instruction
*instruction
)
2813 /* added in ARMv6 */
2814 switch ((opcode
>> 6) & 3) {
2825 snprintf(instruction
->text
, 128,
2826 "0x%8.8" PRIx32
" 0x%4.4x \tREV%s\tr%d, r%d",
2827 address
, opcode
, suffix
,
2828 opcode
& 0x7, (opcode
>> 3) & 0x7);
2833 static int evaluate_hint_thumb(uint16_t opcode
, uint32_t address
,
2834 struct arm_instruction
*instruction
)
2838 switch ((opcode
>> 4) & 0x0f) {
2855 hint
= "HINT (UNRECOGNIZED)";
2859 snprintf(instruction
->text
, 128,
2860 "0x%8.8" PRIx32
" 0x%4.4x \t%s",
2861 address
, opcode
, hint
);
2866 static int evaluate_ifthen_thumb(uint16_t opcode
, uint32_t address
,
2867 struct arm_instruction
*instruction
)
2869 unsigned cond
= (opcode
>> 4) & 0x0f;
2870 char *x
= "", *y
= "", *z
= "";
2873 z
= (opcode
& 0x02) ? "T" : "E";
2875 y
= (opcode
& 0x04) ? "T" : "E";
2877 x
= (opcode
& 0x08) ? "T" : "E";
2879 snprintf(instruction
->text
, 128,
2880 "0x%8.8" PRIx32
" 0x%4.4x \tIT%s%s%s\t%s",
2882 x
, y
, z
, arm_condition_strings
[cond
]);
2884 /* NOTE: strictly speaking, the next 1-4 instructions should
2885 * now be displayed with the relevant conditional suffix...
2891 int thumb_evaluate_opcode(uint16_t opcode
, uint32_t address
, struct arm_instruction
*instruction
)
2893 /* clear fields, to avoid confusion */
2894 memset(instruction
, 0, sizeof(struct arm_instruction
));
2895 instruction
->opcode
= opcode
;
2896 instruction
->instruction_size
= 2;
2898 if ((opcode
& 0xe000) == 0x0000) {
2899 /* add/substract register or immediate */
2900 if ((opcode
& 0x1800) == 0x1800)
2901 return evaluate_add_sub_thumb(opcode
, address
, instruction
);
2902 /* shift by immediate */
2904 return evaluate_shift_imm_thumb(opcode
, address
, instruction
);
2907 /* Add/substract/compare/move immediate */
2908 if ((opcode
& 0xe000) == 0x2000)
2909 return evaluate_data_proc_imm_thumb(opcode
, address
, instruction
);
2911 /* Data processing instructions */
2912 if ((opcode
& 0xf800) == 0x4000)
2913 return evaluate_data_proc_thumb(opcode
, address
, instruction
);
2915 /* Load from literal pool */
2916 if ((opcode
& 0xf800) == 0x4800)
2917 return evaluate_load_literal_thumb(opcode
, address
, instruction
);
2919 /* Load/Store register offset */
2920 if ((opcode
& 0xf000) == 0x5000)
2921 return evaluate_load_store_reg_thumb(opcode
, address
, instruction
);
2923 /* Load/Store immediate offset */
2924 if (((opcode
& 0xe000) == 0x6000)
2925 || ((opcode
& 0xf000) == 0x8000))
2926 return evaluate_load_store_imm_thumb(opcode
, address
, instruction
);
2928 /* Load/Store from/to stack */
2929 if ((opcode
& 0xf000) == 0x9000)
2930 return evaluate_load_store_stack_thumb(opcode
, address
, instruction
);
2933 if ((opcode
& 0xf000) == 0xa000)
2934 return evaluate_add_sp_pc_thumb(opcode
, address
, instruction
);
2937 if ((opcode
& 0xf000) == 0xb000) {
2938 switch ((opcode
>> 8) & 0x0f) {
2940 return evaluate_adjust_stack_thumb(opcode
, address
, instruction
);
2945 return evaluate_cb_thumb(opcode
, address
, instruction
);
2947 return evaluate_extend_thumb(opcode
, address
, instruction
);
2952 return evaluate_load_store_multiple_thumb(opcode
, address
,
2955 return evaluate_cps_thumb(opcode
, address
, instruction
);
2957 if ((opcode
& 0x00c0) == 0x0080)
2959 return evaluate_byterev_thumb(opcode
, address
, instruction
);
2961 return evaluate_breakpoint_thumb(opcode
, address
, instruction
);
2963 if (opcode
& 0x000f)
2964 return evaluate_ifthen_thumb(opcode
, address
,
2967 return evaluate_hint_thumb(opcode
, address
,
2971 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
2972 snprintf(instruction
->text
, 128,
2973 "0x%8.8" PRIx32
" 0x%4.4x \tUNDEFINED INSTRUCTION",
2978 /* Load/Store multiple */
2979 if ((opcode
& 0xf000) == 0xc000)
2980 return evaluate_load_store_multiple_thumb(opcode
, address
, instruction
);
2982 /* Conditional branch + SWI */
2983 if ((opcode
& 0xf000) == 0xd000)
2984 return evaluate_cond_branch_thumb(opcode
, address
, instruction
);
2986 if ((opcode
& 0xe000) == 0xe000) {
2987 /* Undefined instructions */
2988 if ((opcode
& 0xf801) == 0xe801) {
2989 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
2990 snprintf(instruction
->text
, 128,
2991 "0x%8.8" PRIx32
" 0x%8.8x\t"
2992 "UNDEFINED INSTRUCTION",
2995 } else /* Branch to offset */
2996 return evaluate_b_bl_blx_thumb(opcode
, address
, instruction
);
2999 LOG_ERROR("Thumb: should never reach this point (opcode=%04x)", opcode
);
3003 static int t2ev_b_bl(uint32_t opcode
, uint32_t address
,
3004 struct arm_instruction
*instruction
, char *cp
)
3007 unsigned b21
= 1 << 21;
3008 unsigned b22
= 1 << 22;
3010 /* instead of combining two smaller 16-bit branch instructions,
3011 * Thumb2 uses only one larger 32-bit instruction.
3013 offset
= opcode
& 0x7ff;
3014 offset
|= (opcode
& 0x03ff0000) >> 5;
3015 if (opcode
& (1 << 26)) {
3016 offset
|= 0xff << 23;
3017 if ((opcode
& (1 << 11)) == 0)
3019 if ((opcode
& (1 << 13)) == 0)
3022 if (opcode
& (1 << 11))
3024 if (opcode
& (1 << 13))
3032 address
+= offset
<< 1;
3035 switch ((opcode
>> 12) & 0x5) {
3038 instruction
->type
= ARM_B
;
3042 instruction
->type
= ARM_BLX
;
3043 address
&= 0xfffffffc;
3047 instruction
->type
= ARM_BL
;
3050 return ERROR_COMMAND_SYNTAX_ERROR
;
3052 instruction
->info
.b_bl_bx_blx
.reg_operand
= -1;
3053 instruction
->info
.b_bl_bx_blx
.target_address
= address
;
3054 sprintf(cp
, "%s\t%#8.8" PRIx32
, inst
, address
);
3059 static int t2ev_cond_b(uint32_t opcode
, uint32_t address
,
3060 struct arm_instruction
*instruction
, char *cp
)
3063 unsigned b17
= 1 << 17;
3064 unsigned b18
= 1 << 18;
3065 unsigned cond
= (opcode
>> 22) & 0x0f;
3067 offset
= opcode
& 0x7ff;
3068 offset
|= (opcode
& 0x003f0000) >> 5;
3069 if (opcode
& (1 << 26)) {
3070 offset
|= 0x1fff << 19;
3071 if ((opcode
& (1 << 11)) == 0)
3073 if ((opcode
& (1 << 13)) == 0)
3076 if (opcode
& (1 << 11))
3078 if (opcode
& (1 << 13))
3085 address
+= offset
<< 1;
3087 instruction
->type
= ARM_B
;
3088 instruction
->info
.b_bl_bx_blx
.reg_operand
= -1;
3089 instruction
->info
.b_bl_bx_blx
.target_address
= address
;
3090 sprintf(cp
, "B%s.W\t%#8.8" PRIx32
,
3091 arm_condition_strings
[cond
],
3097 static const char *special_name(int number
)
3099 char *special
= "(RESERVED)";
3130 special
= "primask";
3133 special
= "basepri";
3136 special
= "basepri_max";
3139 special
= "faultmask";
3142 special
= "control";
3148 static int t2ev_hint(uint32_t opcode
, uint32_t address
,
3149 struct arm_instruction
*instruction
, char *cp
)
3151 const char *mnemonic
;
3153 if (opcode
& 0x0700) {
3154 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
3155 strcpy(cp
, "UNDEFINED");
3159 if (opcode
& 0x00f0) {
3160 sprintf(cp
, "DBG\t#%d", (int) opcode
& 0xf);
3164 switch (opcode
& 0x0f) {
3169 mnemonic
= "YIELD.W";
3181 mnemonic
= "HINT.W (UNRECOGNIZED)";
3184 strcpy(cp
, mnemonic
);
3188 static int t2ev_misc(uint32_t opcode
, uint32_t address
,
3189 struct arm_instruction
*instruction
, char *cp
)
3191 const char *mnemonic
;
3193 switch ((opcode
>> 4) & 0x0f) {
3195 mnemonic
= "LEAVEX";
3198 mnemonic
= "ENTERX";
3213 return ERROR_COMMAND_SYNTAX_ERROR
;
3215 strcpy(cp
, mnemonic
);
3219 static int t2ev_b_misc(uint32_t opcode
, uint32_t address
,
3220 struct arm_instruction
*instruction
, char *cp
)
3222 /* permanently undefined */
3223 if ((opcode
& 0x07f07000) == 0x07f02000) {
3224 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
3225 strcpy(cp
, "UNDEFINED");
3229 switch ((opcode
>> 12) & 0x5) {
3233 return t2ev_b_bl(opcode
, address
, instruction
, cp
);
3235 if (((opcode
>> 23) & 0x07) != 0x07)
3236 return t2ev_cond_b(opcode
, address
, instruction
, cp
);
3237 if (opcode
& (1 << 26))
3242 switch ((opcode
>> 20) & 0x7f) {
3245 sprintf(cp
, "MSR\t%s, r%d", special_name(opcode
& 0xff),
3246 (int) (opcode
>> 16) & 0x0f);
3249 return t2ev_hint(opcode
, address
, instruction
, cp
);
3251 return t2ev_misc(opcode
, address
, instruction
, cp
);
3253 sprintf(cp
, "BXJ\tr%d", (int) (opcode
>> 16) & 0x0f);
3257 sprintf(cp
, "MRS\tr%d, %s", (int) (opcode
>> 8) & 0x0f,
3258 special_name(opcode
& 0xff));
3263 return ERROR_COMMAND_SYNTAX_ERROR
;
3266 static int t2ev_data_mod_immed(uint32_t opcode
, uint32_t address
,
3267 struct arm_instruction
*instruction
, char *cp
)
3269 char *mnemonic
= NULL
;
3270 int rn
= (opcode
>> 16) & 0xf;
3271 int rd
= (opcode
>> 8) & 0xf;
3272 unsigned immed
= opcode
& 0xff;
3278 /* ARMv7-M: A5.3.2 Modified immediate constants */
3279 func
= (opcode
>> 11) & 0x0e;
3282 if (opcode
& (1 << 26))
3285 /* "Modified" immediates */
3286 switch (func
>> 1) {
3293 immed
+= immed
<< 16;
3296 immed
+= immed
<< 8;
3297 immed
+= immed
<< 16;
3301 immed
= ror(immed
, func
);
3304 if (opcode
& (1 << 20))
3307 switch ((opcode
>> 21) & 0xf) {
3310 instruction
->type
= ARM_TST
;
3316 instruction
->type
= ARM_AND
;
3321 instruction
->type
= ARM_BIC
;
3326 instruction
->type
= ARM_MOV
;
3331 instruction
->type
= ARM_ORR
;
3337 instruction
->type
= ARM_MVN
;
3341 /* instruction->type = ARM_ORN; */
3347 instruction
->type
= ARM_TEQ
;
3353 instruction
->type
= ARM_EOR
;
3359 instruction
->type
= ARM_CMN
;
3365 instruction
->type
= ARM_ADD
;
3371 instruction
->type
= ARM_ADC
;
3376 instruction
->type
= ARM_SBC
;
3381 instruction
->type
= ARM_CMP
;
3387 instruction
->type
= ARM_SUB
;
3393 instruction
->type
= ARM_RSB
;
3398 return ERROR_COMMAND_SYNTAX_ERROR
;
3402 sprintf(cp
, "%s%s\tr%d, #%d\t; %#8.8x",
3403 mnemonic
, suffix2
, rd
, immed
, immed
);
3405 sprintf(cp
, "%s%s%s\tr%d, r%d, #%d\t; %#8.8x",
3406 mnemonic
, suffix
, suffix2
,
3407 rd
, rn
, immed
, immed
);
3412 static int t2ev_data_immed(uint32_t opcode
, uint32_t address
,
3413 struct arm_instruction
*instruction
, char *cp
)
3415 char *mnemonic
= NULL
;
3416 int rn
= (opcode
>> 16) & 0xf;
3417 int rd
= (opcode
>> 8) & 0xf;
3420 bool is_signed
= false;
3422 immed
= (opcode
& 0x0ff) | ((opcode
& 0x7000) >> 4);
3423 if (opcode
& (1 << 26))
3426 switch ((opcode
>> 20) & 0x1f) {
3435 immed
|= (opcode
>> 4) & 0xf000;
3436 sprintf(cp
, "MOVW\tr%d, #%d\t; %#3.3x", rd
, immed
, immed
);
3444 /* move constant to top 16 bits of register */
3445 immed
|= (opcode
>> 4) & 0xf000;
3446 sprintf(cp
, "MOVT\tr%d, #%d\t; %#4.4x", rd
, immed
, immed
);
3454 /* signed/unsigned saturated add */
3455 immed
= (opcode
>> 6) & 0x03;
3456 immed
|= (opcode
>> 10) & 0x1c;
3457 sprintf(cp
, "%sSAT\tr%d, #%d, r%d, %s #%d\t",
3458 is_signed
? "S" : "U",
3459 rd
, (int) (opcode
& 0x1f) + is_signed
, rn
,
3460 (opcode
& (1 << 21)) ? "ASR" : "LSL",
3461 immed
? immed
: 32);
3467 /* signed/unsigned bitfield extract */
3468 immed
= (opcode
>> 6) & 0x03;
3469 immed
|= (opcode
>> 10) & 0x1c;
3470 sprintf(cp
, "%sBFX\tr%d, r%d, #%d, #%d\t",
3471 is_signed
? "S" : "U",
3473 (int) (opcode
& 0x1f) + 1);
3476 immed
= (opcode
>> 6) & 0x03;
3477 immed
|= (opcode
>> 10) & 0x1c;
3478 if (rn
== 0xf) /* bitfield clear */
3479 sprintf(cp
, "BFC\tr%d, #%d, #%d\t",
3481 (int) (opcode
& 0x1f) + 1 - immed
);
3482 else /* bitfield insert */
3483 sprintf(cp
, "BFI\tr%d, r%d, #%d, #%d\t",
3485 (int) (opcode
& 0x1f) + 1 - immed
);
3488 return ERROR_COMMAND_SYNTAX_ERROR
;
3491 sprintf(cp
, "%s\tr%d, r%d, #%d\t; %#3.3x", mnemonic
,
3492 rd
, rn
, immed
, immed
);
3496 address
= thumb_alignpc4(address
);
3501 /* REVISIT "ADD/SUB Rd, PC, #const ; 0x..." might be better;
3502 * not hiding the pc-relative stuff will sometimes be useful.
3504 sprintf(cp
, "ADR.W\tr%d, %#8.8" PRIx32
, rd
, address
);
3508 static int t2ev_store_single(uint32_t opcode
, uint32_t address
,
3509 struct arm_instruction
*instruction
, char *cp
)
3511 unsigned op
= (opcode
>> 20) & 0xf;
3517 unsigned rn
= (opcode
>> 16) & 0x0f;
3518 unsigned rt
= (opcode
>> 12) & 0x0f;
3521 return ERROR_COMMAND_SYNTAX_ERROR
;
3523 if (opcode
& 0x0800)
3558 return ERROR_COMMAND_SYNTAX_ERROR
;
3561 sprintf(cp
, "STR%s.W\tr%d, [r%d, r%d, LSL #%d]",
3562 size
, rt
, rn
, (int) opcode
& 0x0f,
3563 (int) (opcode
>> 4) & 0x03);
3567 immed
= opcode
& 0x0fff;
3568 sprintf(cp
, "STR%s.W\tr%d, [r%d, #%u]\t; %#3.3x",
3569 size
, rt
, rn
, immed
, immed
);
3573 immed
= opcode
& 0x00ff;
3575 switch (opcode
& 0x700) {
3581 return ERROR_COMMAND_SYNTAX_ERROR
;
3584 /* two indexed modes will write back rn */
3585 if (opcode
& 0x100) {
3586 if (opcode
& 0x400) /* pre-indexed */
3588 else { /* post-indexed */
3594 sprintf(cp
, "STR%s%s\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
3595 size
, suffix
, rt
, rn
, p1
,
3596 (opcode
& 0x200) ? "" : "-",
3601 static int t2ev_mul32(uint32_t opcode
, uint32_t address
,
3602 struct arm_instruction
*instruction
, char *cp
)
3604 int ra
= (opcode
>> 12) & 0xf;
3606 switch (opcode
& 0x007000f0) {
3609 sprintf(cp
, "MUL\tr%d, r%d, r%d",
3610 (int) (opcode
>> 8) & 0xf,
3611 (int) (opcode
>> 16) & 0xf,
3612 (int) (opcode
>> 0) & 0xf);
3614 sprintf(cp
, "MLA\tr%d, r%d, r%d, r%d",
3615 (int) (opcode
>> 8) & 0xf,
3616 (int) (opcode
>> 16) & 0xf,
3617 (int) (opcode
>> 0) & 0xf, ra
);
3620 sprintf(cp
, "MLS\tr%d, r%d, r%d, r%d",
3621 (int) (opcode
>> 8) & 0xf,
3622 (int) (opcode
>> 16) & 0xf,
3623 (int) (opcode
>> 0) & 0xf, ra
);
3626 return ERROR_COMMAND_SYNTAX_ERROR
;
3631 static int t2ev_mul64_div(uint32_t opcode
, uint32_t address
,
3632 struct arm_instruction
*instruction
, char *cp
)
3634 int op
= (opcode
>> 4) & 0xf;
3635 char *infix
= "MUL";
3637 op
+= (opcode
>> 16) & 0x70;
3645 sprintf(cp
, "%c%sL\tr%d, r%d, r%d, r%d",
3646 (op
& 0x20) ? 'U' : 'S',
3648 (int) (opcode
>> 12) & 0xf,
3649 (int) (opcode
>> 8) & 0xf,
3650 (int) (opcode
>> 16) & 0xf,
3651 (int) (opcode
>> 0) & 0xf);
3655 sprintf(cp
, "%cDIV\tr%d, r%d, r%d",
3656 (op
& 0x20) ? 'U' : 'S',
3657 (int) (opcode
>> 8) & 0xf,
3658 (int) (opcode
>> 16) & 0xf,
3659 (int) (opcode
>> 0) & 0xf);
3662 return ERROR_COMMAND_SYNTAX_ERROR
;
3668 static int t2ev_ldm_stm(uint32_t opcode
, uint32_t address
,
3669 struct arm_instruction
*instruction
, char *cp
)
3671 int rn
= (opcode
>> 16) & 0xf;
3672 int op
= (opcode
>> 22) & 0x6;
3673 int t
= (opcode
>> 21) & 1;
3674 unsigned registers
= opcode
& 0xffff;
3677 if (opcode
& (1 << 20))
3685 sprintf(cp
, "SRS%s\tsp%s, #%d", mode
,
3687 (unsigned) (opcode
& 0x1f));
3693 sprintf(cp
, "RFE%s\tr%d%s", mode
,
3694 (unsigned) ((opcode
>> 16) & 0xf),
3698 sprintf(cp
, "STM.W\tr%d%s, ", rn
, t
? "!" : "");
3702 sprintf(cp
, "POP.W\t");
3704 sprintf(cp
, "LDM.W\tr%d%s, ", rn
, t
? "!" : "");
3708 sprintf(cp
, "PUSH.W\t");
3710 sprintf(cp
, "STMDB\tr%d%s, ", rn
, t
? "!" : "");
3713 sprintf(cp
, "LDMDB.W\tr%d%s, ", rn
, t
? "!" : "");
3716 return ERROR_COMMAND_SYNTAX_ERROR
;
3721 for (t
= 0; registers
; t
++, registers
>>= 1) {
3722 if ((registers
& 1) == 0)
3725 sprintf(cp
, "r%d%s", t
, registers
? ", " : "");
3734 /* load/store dual or exclusive, table branch */
3735 static int t2ev_ldrex_strex(uint32_t opcode
, uint32_t address
,
3736 struct arm_instruction
*instruction
, char *cp
)
3738 unsigned op1op2
= (opcode
>> 20) & 0x3;
3739 unsigned op3
= (opcode
>> 4) & 0xf;
3741 unsigned rn
= (opcode
>> 16) & 0xf;
3742 unsigned rt
= (opcode
>> 12) & 0xf;
3743 unsigned rd
= (opcode
>> 8) & 0xf;
3744 unsigned imm
= opcode
& 0xff;
3748 op1op2
|= (opcode
>> 21) & 0xc;
3778 mnemonic
= "STREXB";
3781 mnemonic
= "STREXH";
3784 return ERROR_COMMAND_SYNTAX_ERROR
;
3792 sprintf(cp
, "TBB\t[r%u, r%u]", rn
, imm
& 0xf);
3795 sprintf(cp
, "TBH\t[r%u, r%u, LSL #1]", rn
, imm
& 0xf);
3798 mnemonic
= "LDREXB";
3801 mnemonic
= "LDREXH";
3804 return ERROR_COMMAND_SYNTAX_ERROR
;
3809 return ERROR_COMMAND_SYNTAX_ERROR
;
3814 sprintf(cp
, "%s\tr%u, r%u, [r%u, #%u]\t; %#2.2x",
3815 mnemonic
, rd
, rt
, rn
, imm
, imm
);
3817 sprintf(cp
, "%s\tr%u, r%u, [r%u]",
3818 mnemonic
, rd
, rt
, rn
);
3824 sprintf(cp
, "%s\tr%u, [r%u, #%u]\t; %#2.2x",
3825 mnemonic
, rt
, rn
, imm
, imm
);
3827 sprintf(cp
, "%s\tr%u, [r%u]",
3832 /* two indexed modes will write back rn */
3833 if (opcode
& (1 << 21)) {
3834 if (opcode
& (1 << 24)) /* pre-indexed */
3836 else { /* post-indexed */
3843 sprintf(cp
, "%s\tr%u, r%u, [r%u%s, #%s%u%s\t; %#2.2x",
3844 mnemonic
, rt
, rd
, rn
, p1
,
3845 (opcode
& (1 << 23)) ? "" : "-",
3850 address
= thumb_alignpc4(address
);
3852 if (opcode
& (1 << 23))
3856 sprintf(cp
, "%s\tr%u, r%u, %#8.8" PRIx32
,
3857 mnemonic
, rt
, rd
, address
);
3861 static int t2ev_data_shift(uint32_t opcode
, uint32_t address
,
3862 struct arm_instruction
*instruction
, char *cp
)
3864 int op
= (opcode
>> 21) & 0xf;
3865 int rd
= (opcode
>> 8) & 0xf;
3866 int rn
= (opcode
>> 16) & 0xf;
3867 int type
= (opcode
>> 4) & 0x3;
3868 int immed
= (opcode
>> 6) & 0x3;
3872 immed
|= (opcode
>> 10) & 0x1c;
3873 if (opcode
& (1 << 20))
3879 if (!(opcode
& (1 << 20)))
3880 return ERROR_COMMAND_SYNTAX_ERROR
;
3881 instruction
->type
= ARM_TST
;
3886 instruction
->type
= ARM_AND
;
3890 instruction
->type
= ARM_BIC
;
3895 instruction
->type
= ARM_MOV
;
3899 sprintf(cp
, "MOV%s.W\tr%d, r%d",
3901 (int) (opcode
& 0xf));
3914 sprintf(cp
, "RRX%s\tr%d, r%d",
3916 (int) (opcode
& 0xf));
3924 instruction
->type
= ARM_ORR
;
3930 instruction
->type
= ARM_MVN
;
3935 /* instruction->type = ARM_ORN; */
3941 if (!(opcode
& (1 << 20)))
3942 return ERROR_COMMAND_SYNTAX_ERROR
;
3943 instruction
->type
= ARM_TEQ
;
3948 instruction
->type
= ARM_EOR
;
3953 if (!(opcode
& (1 << 20)))
3954 return ERROR_COMMAND_SYNTAX_ERROR
;
3955 instruction
->type
= ARM_CMN
;
3960 instruction
->type
= ARM_ADD
;
3964 instruction
->type
= ARM_ADC
;
3968 instruction
->type
= ARM_SBC
;
3973 if (!(opcode
& (1 << 21)))
3974 return ERROR_COMMAND_SYNTAX_ERROR
;
3975 instruction
->type
= ARM_CMP
;
3980 instruction
->type
= ARM_SUB
;
3984 instruction
->type
= ARM_RSB
;
3988 return ERROR_COMMAND_SYNTAX_ERROR
;
3991 sprintf(cp
, "%s%s.W\tr%d, r%d, r%d",
3992 mnemonic
, suffix
, rd
, rn
, (int) (opcode
& 0xf));
4015 strcpy(cp
, ", RRX");
4021 sprintf(cp
, ", %s #%d", suffix
, immed
? immed
: 32);
4025 sprintf(cp
, "%s%s.W\tr%d, r%d",
4026 mnemonic
, suffix
, rn
, (int) (opcode
& 0xf));
4030 sprintf(cp
, "%s%s.W\tr%d, r%d, #%d",
4031 mnemonic
, suffix
, rd
,
4032 (int) (opcode
& 0xf), immed
? immed
: 32);
4036 static int t2ev_data_reg(uint32_t opcode
, uint32_t address
,
4037 struct arm_instruction
*instruction
, char *cp
)
4042 if (((opcode
>> 4) & 0xf) == 0) {
4043 switch ((opcode
>> 21) & 0x7) {
4057 return ERROR_COMMAND_SYNTAX_ERROR
;
4060 instruction
->type
= ARM_MOV
;
4061 if (opcode
& (1 << 20))
4063 sprintf(cp
, "%s%s.W\tr%d, r%d, r%d",
4065 (int) (opcode
>> 8) & 0xf,
4066 (int) (opcode
>> 16) & 0xf,
4067 (int) (opcode
>> 0) & 0xf);
4069 } else if (opcode
& (1 << 7)) {
4070 switch ((opcode
>> 20) & 0xf) {
4075 switch ((opcode
>> 4) & 0x3) {
4077 suffix
= ", ROR #8";
4080 suffix
= ", ROR #16";
4083 suffix
= ", ROR #24";
4086 sprintf(cp
, "%cXT%c.W\tr%d, r%d%s",
4087 (opcode
& (1 << 24)) ? 'U' : 'S',
4088 (opcode
& (1 << 26)) ? 'B' : 'H',
4089 (int) (opcode
>> 8) & 0xf,
4090 (int) (opcode
>> 0) & 0xf,
4097 if (opcode
& (1 << 6))
4098 return ERROR_COMMAND_SYNTAX_ERROR
;
4099 if (((opcode
>> 12) & 0xf) != 0xf)
4100 return ERROR_COMMAND_SYNTAX_ERROR
;
4101 if (!(opcode
& (1 << 20)))
4102 return ERROR_COMMAND_SYNTAX_ERROR
;
4104 switch (((opcode
>> 19) & 0x04)
4105 | ((opcode
>> 4) & 0x3)) {
4110 mnemonic
= "REV16.W";
4116 mnemonic
= "REVSH.W";
4122 return ERROR_COMMAND_SYNTAX_ERROR
;
4124 sprintf(cp
, "%s\tr%d, r%d",
4126 (int) (opcode
>> 8) & 0xf,
4127 (int) (opcode
>> 0) & 0xf);
4130 return ERROR_COMMAND_SYNTAX_ERROR
;
4137 static int t2ev_load_word(uint32_t opcode
, uint32_t address
,
4138 struct arm_instruction
*instruction
, char *cp
)
4140 int rn
= (opcode
>> 16) & 0xf;
4143 instruction
->type
= ARM_LDR
;
4146 immed
= opcode
& 0x0fff;
4147 if ((opcode
& (1 << 23)) == 0)
4149 sprintf(cp
, "LDR\tr%d, %#8.8" PRIx32
,
4150 (int) (opcode
>> 12) & 0xf,
4151 thumb_alignpc4(address
) + immed
);
4155 if (opcode
& (1 << 23)) {
4156 immed
= opcode
& 0x0fff;
4157 sprintf(cp
, "LDR.W\tr%d, [r%d, #%d]\t; %#3.3x",
4158 (int) (opcode
>> 12) & 0xf,
4163 if (!(opcode
& (0x3f << 6))) {
4164 sprintf(cp
, "LDR.W\tr%d, [r%d, r%d, LSL #%d]",
4165 (int) (opcode
>> 12) & 0xf,
4167 (int) (opcode
>> 0) & 0xf,
4168 (int) (opcode
>> 4) & 0x3);
4173 if (((opcode
>> 8) & 0xf) == 0xe) {
4174 immed
= opcode
& 0x00ff;
4176 sprintf(cp
, "LDRT\tr%d, [r%d, #%d]\t; %#2.2x",
4177 (int) (opcode
>> 12) & 0xf,
4182 if (((opcode
>> 8) & 0xf) == 0xc || (opcode
& 0x0900) == 0x0900) {
4183 char *p1
= "]", *p2
= "";
4185 if (!(opcode
& 0x0500))
4186 return ERROR_COMMAND_SYNTAX_ERROR
;
4188 immed
= opcode
& 0x00ff;
4190 /* two indexed modes will write back rn */
4191 if (opcode
& 0x100) {
4192 if (opcode
& 0x400) /* pre-indexed */
4194 else { /* post-indexed */
4200 sprintf(cp
, "LDR\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
4201 (int) (opcode
>> 12) & 0xf,
4203 (opcode
& 0x200) ? "" : "-",
4208 return ERROR_COMMAND_SYNTAX_ERROR
;
4211 static int t2ev_load_byte_hints(uint32_t opcode
, uint32_t address
,
4212 struct arm_instruction
*instruction
, char *cp
)
4214 int rn
= (opcode
>> 16) & 0xf;
4215 int rt
= (opcode
>> 12) & 0xf;
4216 int op2
= (opcode
>> 6) & 0x3f;
4218 char *p1
= "", *p2
= "]";
4221 switch ((opcode
>> 23) & 0x3) {
4223 if ((rn
& rt
) == 0xf) {
4225 immed
= opcode
& 0xfff;
4226 address
= thumb_alignpc4(address
);
4227 if (opcode
& (1 << 23))
4231 sprintf(cp
, "PLD\tr%d, %#8.8" PRIx32
,
4235 if (rn
== 0x0f && rt
!= 0x0f) {
4237 immed
= opcode
& 0xfff;
4238 address
= thumb_alignpc4(address
);
4239 if (opcode
& (1 << 23))
4243 sprintf(cp
, "LDRB\tr%d, %#8.8" PRIx32
,
4249 if ((op2
& 0x3c) == 0x38) {
4250 immed
= opcode
& 0xff;
4251 sprintf(cp
, "LDRBT\tr%d, [r%d, #%d]\t; %#2.2x",
4252 rt
, rn
, immed
, immed
);
4255 if ((op2
& 0x3c) == 0x30) {
4257 immed
= opcode
& 0xff;
4260 p1
= (opcode
& (1 << 21)) ? "W" : "";
4261 sprintf(cp
, "PLD%s\t[r%d, #%d]\t; %#6.6x",
4262 p1
, rn
, immed
, immed
);
4267 immed
= opcode
& 0xff;
4268 if (!(opcode
& 0x200))
4271 /* two indexed modes will write back rn */
4272 if (opcode
& 0x100) {
4273 if (opcode
& 0x400) /* pre-indexed */
4275 else { /* post-indexed */
4281 sprintf(cp
, "%s\tr%d, [r%d%s, #%d%s\t; %#8.8x",
4282 mnemonic
, rt
, rn
, p1
,
4286 if ((op2
& 0x24) == 0x24) {
4288 goto ldrxb_immediate_t3
;
4291 int rm
= opcode
& 0xf;
4294 sprintf(cp
, "PLD\t");
4296 sprintf(cp
, "LDRB.W\tr%d, ", rt
);
4297 immed
= (opcode
>> 4) & 0x3;
4299 sprintf(cp
, "[r%d, r%d, LSL #%d]", rn
, rm
, immed
);
4304 if ((rn
& rt
) == 0xf)
4307 immed
= opcode
& 0xfff;
4308 goto preload_immediate
;
4312 mnemonic
= "LDRB.W";
4313 immed
= opcode
& 0xfff;
4314 goto ldrxb_immediate_t2
;
4316 if ((rn
& rt
) == 0xf) {
4317 immed
= opcode
& 0xfff;
4318 address
= thumb_alignpc4(address
);
4319 if (opcode
& (1 << 23))
4323 sprintf(cp
, "PLI\t%#8.8" PRIx32
, address
);
4326 if (rn
== 0xf && rt
!= 0xf) {
4328 immed
= opcode
& 0xfff;
4329 address
= thumb_alignpc4(address
);
4330 if (opcode
& (1 << 23))
4334 sprintf(cp
, "LDRSB\t%#8.8" PRIx32
, address
);
4339 if ((op2
& 0x3c) == 0x38) {
4340 immed
= opcode
& 0xff;
4341 sprintf(cp
, "LDRSBT\tr%d, [r%d, #%d]\t; %#2.2x",
4342 rt
, rn
, immed
, immed
);
4345 if ((op2
& 0x3c) == 0x30) {
4347 immed
= opcode
& 0xff;
4348 immed
= -immed
; /* pli */
4349 sprintf(cp
, "PLI\t[r%d, #%d]\t; -%#2.2x",
4354 goto ldrxb_immediate_t3
;
4356 if ((op2
& 0x24) == 0x24) {
4358 goto ldrxb_immediate_t3
;
4361 int rm
= opcode
& 0xf;
4364 sprintf(cp
, "PLI\t");
4366 sprintf(cp
, "LDRSB.W\tr%d, ", rt
);
4367 immed
= (opcode
>> 4) & 0x3;
4369 sprintf(cp
, "[r%d, r%d, LSL #%d]", rn
, rm
, immed
);
4375 immed
= opcode
& 0xfff;
4376 sprintf(cp
, "PLI\t[r%d, #%d]\t; %#3.3x",
4382 immed
= opcode
& 0xfff;
4384 goto ldrxb_immediate_t2
;
4387 return ERROR_COMMAND_SYNTAX_ERROR
;
4390 static int t2ev_load_halfword(uint32_t opcode
, uint32_t address
,
4391 struct arm_instruction
*instruction
, char *cp
)
4393 int rn
= (opcode
>> 16) & 0xf;
4394 int rt
= (opcode
>> 12) & 0xf;
4395 int op2
= (opcode
>> 6) & 0x3f;
4400 sprintf(cp
, "HINT (UNALLOCATED)");
4404 if (opcode
& (1 << 24))
4407 if ((opcode
& (1 << 23)) == 0) {
4410 immed
= opcode
& 0xfff;
4411 address
= thumb_alignpc4(address
);
4412 if (opcode
& (1 << 23))
4416 sprintf(cp
, "LDR%sH\tr%d, %#8.8" PRIx32
,
4421 int rm
= opcode
& 0xf;
4423 immed
= (opcode
>> 4) & 0x3;
4424 sprintf(cp
, "LDR%sH.W\tr%d, [r%d, r%d, LSL #%d]",
4425 sign
, rt
, rn
, rm
, immed
);
4428 if ((op2
& 0x3c) == 0x38) {
4429 immed
= opcode
& 0xff;
4430 sprintf(cp
, "LDR%sHT\tr%d, [r%d, #%d]\t; %#2.2x",
4431 sign
, rt
, rn
, immed
, immed
);
4434 if ((op2
& 0x3c) == 0x30 || (op2
& 0x24) == 0x24) {
4435 char *p1
= "", *p2
= "]";
4437 immed
= opcode
& 0xff;
4438 if (!(opcode
& 0x200))
4441 /* two indexed modes will write back rn */
4442 if (opcode
& 0x100) {
4443 if (opcode
& 0x400) /* pre-indexed */
4445 else { /* post-indexed */
4450 sprintf(cp
, "LDR%sH\tr%d, [r%d%s, #%d%s\t; %#8.8x",
4451 sign
, rt
, rn
, p1
, immed
, p2
, immed
);
4458 immed
= opcode
& 0xfff;
4459 sprintf(cp
, "LDR%sH%s\tr%d, [r%d, #%d]\t; %#6.6x",
4460 sign
, *sign
? "" : ".W",
4461 rt
, rn
, immed
, immed
);
4465 return ERROR_COMMAND_SYNTAX_ERROR
;
4469 * REVISIT for Thumb2 instructions, instruction->type and friends aren't
4470 * always set. That means eventual arm_simulate_step() support for Thumb2
4471 * will need work in this area.
4473 int thumb2_opcode(struct target
*target
, uint32_t address
, struct arm_instruction
*instruction
)
4480 /* clear low bit ... it's set on function pointers */
4483 /* clear fields, to avoid confusion */
4484 memset(instruction
, 0, sizeof(struct arm_instruction
));
4486 /* read first halfword, see if this is the only one */
4487 retval
= target_read_u16(target
, address
, &op
);
4488 if (retval
!= ERROR_OK
)
4491 switch (op
& 0xf800) {
4495 /* 32-bit instructions */
4496 instruction
->instruction_size
= 4;
4498 retval
= target_read_u16(target
, address
+ 2, &op
);
4499 if (retval
!= ERROR_OK
)
4502 instruction
->opcode
= opcode
;
4505 /* 16-bit: Thumb1 + IT + CBZ/CBNZ + ... */
4506 return thumb_evaluate_opcode(op
, address
, instruction
);
4509 snprintf(instruction
->text
, 128,
4510 "0x%8.8" PRIx32
" 0x%8.8" PRIx32
"\t",
4512 cp
= strchr(instruction
->text
, 0);
4513 retval
= ERROR_FAIL
;
4515 /* ARMv7-M: A5.3.1 Data processing (modified immediate) */
4516 if ((opcode
& 0x1a008000) == 0x10000000)
4517 retval
= t2ev_data_mod_immed(opcode
, address
, instruction
, cp
);
4519 /* ARMv7-M: A5.3.3 Data processing (plain binary immediate) */
4520 else if ((opcode
& 0x1a008000) == 0x12000000)
4521 retval
= t2ev_data_immed(opcode
, address
, instruction
, cp
);
4523 /* ARMv7-M: A5.3.4 Branches and miscellaneous control */
4524 else if ((opcode
& 0x18008000) == 0x10008000)
4525 retval
= t2ev_b_misc(opcode
, address
, instruction
, cp
);
4527 /* ARMv7-M: A5.3.5 Load/store multiple */
4528 else if ((opcode
& 0x1e400000) == 0x08000000)
4529 retval
= t2ev_ldm_stm(opcode
, address
, instruction
, cp
);
4531 /* ARMv7-M: A5.3.6 Load/store dual or exclusive, table branch */
4532 else if ((opcode
& 0x1e400000) == 0x08400000)
4533 retval
= t2ev_ldrex_strex(opcode
, address
, instruction
, cp
);
4535 /* ARMv7-M: A5.3.7 Load word */
4536 else if ((opcode
& 0x1f700000) == 0x18500000)
4537 retval
= t2ev_load_word(opcode
, address
, instruction
, cp
);
4539 /* ARMv7-M: A5.3.8 Load halfword, unallocated memory hints */
4540 else if ((opcode
& 0x1e700000) == 0x18300000)
4541 retval
= t2ev_load_halfword(opcode
, address
, instruction
, cp
);
4543 /* ARMv7-M: A5.3.9 Load byte, memory hints */
4544 else if ((opcode
& 0x1e700000) == 0x18100000)
4545 retval
= t2ev_load_byte_hints(opcode
, address
, instruction
, cp
);
4547 /* ARMv7-M: A5.3.10 Store single data item */
4548 else if ((opcode
& 0x1f100000) == 0x18000000)
4549 retval
= t2ev_store_single(opcode
, address
, instruction
, cp
);
4551 /* ARMv7-M: A5.3.11 Data processing (shifted register) */
4552 else if ((opcode
& 0x1e000000) == 0x0a000000)
4553 retval
= t2ev_data_shift(opcode
, address
, instruction
, cp
);
4555 /* ARMv7-M: A5.3.12 Data processing (register)
4556 * and A5.3.13 Miscellaneous operations
4558 else if ((opcode
& 0x1f000000) == 0x1a000000)
4559 retval
= t2ev_data_reg(opcode
, address
, instruction
, cp
);
4561 /* ARMv7-M: A5.3.14 Multiply, and multiply accumulate */
4562 else if ((opcode
& 0x1f800000) == 0x1b000000)
4563 retval
= t2ev_mul32(opcode
, address
, instruction
, cp
);
4565 /* ARMv7-M: A5.3.15 Long multiply, long multiply accumulate, divide */
4566 else if ((opcode
& 0x1f800000) == 0x1b800000)
4567 retval
= t2ev_mul64_div(opcode
, address
, instruction
, cp
);
4569 if (retval
== ERROR_OK
)
4573 * Thumb2 also supports coprocessor, ThumbEE, and DSP/Media (SIMD)
4574 * instructions; not yet handled here.
4577 if (retval
== ERROR_COMMAND_SYNTAX_ERROR
) {
4578 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
4579 strcpy(cp
, "UNDEFINED OPCODE");
4583 LOG_DEBUG("Can't decode 32-bit Thumb2 yet (opcode=%08" PRIx32
")",
4586 strcpy(cp
, "(32-bit Thumb2 ...)");
4590 int arm_access_size(struct arm_instruction
*instruction
)
4592 if ((instruction
->type
== ARM_LDRB
)
4593 || (instruction
->type
== ARM_LDRBT
)
4594 || (instruction
->type
== ARM_LDRSB
)
4595 || (instruction
->type
== ARM_STRB
)
4596 || (instruction
->type
== ARM_STRBT
))
4598 else if ((instruction
->type
== ARM_LDRH
)
4599 || (instruction
->type
== ARM_LDRSH
)
4600 || (instruction
->type
== ARM_STRH
))
4602 else if ((instruction
->type
== ARM_LDR
)
4603 || (instruction
->type
== ARM_LDRT
)
4604 || (instruction
->type
== ARM_STR
)
4605 || (instruction
->type
== ARM_STRT
))
4607 else if ((instruction
->type
== ARM_LDRD
)
4608 || (instruction
->type
== ARM_STRD
))
4611 LOG_ERROR("BUG: instruction type %i isn't a load/store instruction",
Linking to existing account procedure
If you already have an account and want to add another login method
you
MUST first sign in with your existing account and
then change URL to read
https://review.openocd.org/login/?link
to get to this page again but this time it'll work for linking. Thank you.
SSH host keys fingerprints
1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=.. |
|+o.. . |
|*.o . . |
|+B . . . |
|Bo. = o S |
|Oo.+ + = |
|oB=.* = . o |
| =+=.+ + E |
|. .=o . o |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)