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_INSTUCTION
;
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",
2317 instruction
->type
= ARM_AND
;
2321 instruction
->type
= ARM_EOR
;
2325 instruction
->type
= ARM_MOV
;
2327 instruction
->info
.data_proc
.variant
= 2 /*register shift*/;
2328 instruction
->info
.data_proc
.shifter_operand
.register_shift
.shift
= 0;
2329 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rm
= Rd
;
2330 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rs
= Rm
;
2333 instruction
->type
= ARM_MOV
;
2335 instruction
->info
.data_proc
.variant
= 2 /*register shift*/;
2336 instruction
->info
.data_proc
.shifter_operand
.register_shift
.shift
= 1;
2337 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rm
= Rd
;
2338 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rs
= Rm
;
2341 instruction
->type
= ARM_MOV
;
2343 instruction
->info
.data_proc
.variant
= 2 /*register shift*/;
2344 instruction
->info
.data_proc
.shifter_operand
.register_shift
.shift
= 2;
2345 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rm
= Rd
;
2346 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rs
= Rm
;
2349 instruction
->type
= ARM_ADC
;
2353 instruction
->type
= ARM_SBC
;
2357 instruction
->type
= ARM_MOV
;
2359 instruction
->info
.data_proc
.variant
= 2 /*register shift*/;
2360 instruction
->info
.data_proc
.shifter_operand
.register_shift
.shift
= 3;
2361 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rm
= Rd
;
2362 instruction
->info
.data_proc
.shifter_operand
.register_shift
.Rs
= Rm
;
2365 instruction
->type
= ARM_TST
;
2369 instruction
->type
= ARM_RSB
;
2371 instruction
->info
.data_proc
.variant
= 0 /*immediate*/;
2372 instruction
->info
.data_proc
.shifter_operand
.immediate
.immediate
= 0;
2373 instruction
->info
.data_proc
.Rn
= Rm
;
2376 instruction
->type
= ARM_CMP
;
2380 instruction
->type
= ARM_CMN
;
2384 instruction
->type
= ARM_ORR
;
2388 instruction
->type
= ARM_MUL
;
2392 instruction
->type
= ARM_BIC
;
2396 instruction
->type
= ARM_MVN
;
2403 snprintf(instruction
->text
, 128,
2404 "0x%8.8" PRIx32
" 0x%4.4x \tNOP\t\t\t"
2406 address
, opcode
, mnemonic
, Rd
, Rm
);
2408 snprintf(instruction
->text
, 128,
2409 "0x%8.8" PRIx32
" 0x%4.4x \t%s\tr%i, r%i",
2410 address
, opcode
, mnemonic
, Rd
, Rm
);
2415 /* PC-relative data addressing is word-aligned even with Thumb */
2416 static inline uint32_t thumb_alignpc4(uint32_t addr
)
2418 return (addr
+ 4) & ~3;
2421 static int evaluate_load_literal_thumb(uint16_t opcode
,
2422 uint32_t address
, struct arm_instruction
*instruction
)
2425 uint8_t Rd
= (opcode
>> 8) & 0x7;
2427 instruction
->type
= ARM_LDR
;
2428 immediate
= opcode
& 0x000000ff;
2431 instruction
->info
.load_store
.Rd
= Rd
;
2432 instruction
->info
.load_store
.Rn
= 15 /*PC*/;
2433 instruction
->info
.load_store
.index_mode
= 0; /*offset*/
2434 instruction
->info
.load_store
.offset_mode
= 0; /*immediate*/
2435 instruction
->info
.load_store
.offset
.offset
= immediate
;
2437 snprintf(instruction
->text
, 128,
2438 "0x%8.8" PRIx32
" 0x%4.4x \t"
2439 "LDR\tr%i, [pc, #%#" PRIx32
"]\t; %#8.8" PRIx32
,
2440 address
, opcode
, Rd
, immediate
,
2441 thumb_alignpc4(address
) + immediate
);
2446 static int evaluate_load_store_reg_thumb(uint16_t opcode
,
2447 uint32_t address
, struct arm_instruction
*instruction
)
2449 uint8_t Rd
= (opcode
>> 0) & 0x7;
2450 uint8_t Rn
= (opcode
>> 3) & 0x7;
2451 uint8_t Rm
= (opcode
>> 6) & 0x7;
2452 uint8_t opc
= (opcode
>> 9) & 0x7;
2453 char *mnemonic
= NULL
;
2457 instruction
->type
= ARM_STR
;
2461 instruction
->type
= ARM_STRH
;
2465 instruction
->type
= ARM_STRB
;
2469 instruction
->type
= ARM_LDRSB
;
2473 instruction
->type
= ARM_LDR
;
2477 instruction
->type
= ARM_LDRH
;
2481 instruction
->type
= ARM_LDRB
;
2485 instruction
->type
= ARM_LDRSH
;
2490 snprintf(instruction
->text
, 128,
2491 "0x%8.8" PRIx32
" 0x%4.4x \t%s\tr%i, [r%i, r%i]",
2492 address
, opcode
, mnemonic
, Rd
, Rn
, Rm
);
2494 instruction
->info
.load_store
.Rd
= Rd
;
2495 instruction
->info
.load_store
.Rn
= Rn
;
2496 instruction
->info
.load_store
.index_mode
= 0; /*offset*/
2497 instruction
->info
.load_store
.offset_mode
= 1; /*register*/
2498 instruction
->info
.load_store
.offset
.reg
.Rm
= Rm
;
2503 static int evaluate_load_store_imm_thumb(uint16_t opcode
,
2504 uint32_t address
, struct arm_instruction
*instruction
)
2506 uint32_t offset
= (opcode
>> 6) & 0x1f;
2507 uint8_t Rd
= (opcode
>> 0) & 0x7;
2508 uint8_t Rn
= (opcode
>> 3) & 0x7;
2509 uint32_t L
= opcode
& (1 << 11);
2510 uint32_t B
= opcode
& (1 << 12);
2516 instruction
->type
= ARM_LDR
;
2519 instruction
->type
= ARM_STR
;
2523 if ((opcode
&0xF000) == 0x8000) {
2531 snprintf(instruction
->text
, 128,
2532 "0x%8.8" PRIx32
" 0x%4.4x \t%s%c\tr%i, [r%i, #%#" PRIx32
"]",
2533 address
, opcode
, mnemonic
, suffix
, Rd
, Rn
, offset
<< shift
);
2535 instruction
->info
.load_store
.Rd
= Rd
;
2536 instruction
->info
.load_store
.Rn
= Rn
;
2537 instruction
->info
.load_store
.index_mode
= 0; /*offset*/
2538 instruction
->info
.load_store
.offset_mode
= 0; /*immediate*/
2539 instruction
->info
.load_store
.offset
.offset
= offset
<< shift
;
2544 static int evaluate_load_store_stack_thumb(uint16_t opcode
,
2545 uint32_t address
, struct arm_instruction
*instruction
)
2547 uint32_t offset
= opcode
& 0xff;
2548 uint8_t Rd
= (opcode
>> 8) & 0x7;
2549 uint32_t L
= opcode
& (1 << 11);
2553 instruction
->type
= ARM_LDR
;
2556 instruction
->type
= ARM_STR
;
2560 snprintf(instruction
->text
, 128,
2561 "0x%8.8" PRIx32
" 0x%4.4x \t%s\tr%i, [SP, #%#" PRIx32
"]",
2562 address
, opcode
, mnemonic
, Rd
, offset
*4);
2564 instruction
->info
.load_store
.Rd
= Rd
;
2565 instruction
->info
.load_store
.Rn
= 13 /*SP*/;
2566 instruction
->info
.load_store
.index_mode
= 0; /*offset*/
2567 instruction
->info
.load_store
.offset_mode
= 0; /*immediate*/
2568 instruction
->info
.load_store
.offset
.offset
= offset
*4;
2573 static int evaluate_add_sp_pc_thumb(uint16_t opcode
,
2574 uint32_t address
, struct arm_instruction
*instruction
)
2576 uint32_t imm
= opcode
& 0xff;
2577 uint8_t Rd
= (opcode
>> 8) & 0x7;
2579 uint32_t SP
= opcode
& (1 << 11);
2580 const char *reg_name
;
2582 instruction
->type
= ARM_ADD
;
2592 snprintf(instruction
->text
, 128,
2593 "0x%8.8" PRIx32
" 0x%4.4x \tADD\tr%i, %s, #%#" PRIx32
,
2594 address
, opcode
, Rd
, reg_name
, imm
* 4);
2596 instruction
->info
.data_proc
.variant
= 0 /* immediate */;
2597 instruction
->info
.data_proc
.Rd
= Rd
;
2598 instruction
->info
.data_proc
.Rn
= Rn
;
2599 instruction
->info
.data_proc
.shifter_operand
.immediate
.immediate
= imm
*4;
2604 static int evaluate_adjust_stack_thumb(uint16_t opcode
,
2605 uint32_t address
, struct arm_instruction
*instruction
)
2607 uint32_t imm
= opcode
& 0x7f;
2608 uint8_t opc
= opcode
& (1 << 7);
2613 instruction
->type
= ARM_SUB
;
2616 instruction
->type
= ARM_ADD
;
2620 snprintf(instruction
->text
, 128,
2621 "0x%8.8" PRIx32
" 0x%4.4x \t%s\tSP, #%#" PRIx32
,
2622 address
, opcode
, mnemonic
, imm
*4);
2624 instruction
->info
.data_proc
.variant
= 0 /* immediate */;
2625 instruction
->info
.data_proc
.Rd
= 13 /*SP*/;
2626 instruction
->info
.data_proc
.Rn
= 13 /*SP*/;
2627 instruction
->info
.data_proc
.shifter_operand
.immediate
.immediate
= imm
*4;
2632 static int evaluate_breakpoint_thumb(uint16_t opcode
,
2633 uint32_t address
, struct arm_instruction
*instruction
)
2635 uint32_t imm
= opcode
& 0xff;
2637 instruction
->type
= ARM_BKPT
;
2639 snprintf(instruction
->text
, 128,
2640 "0x%8.8" PRIx32
" 0x%4.4x \tBKPT\t%#2.2" PRIx32
"",
2641 address
, opcode
, imm
);
2646 static int evaluate_load_store_multiple_thumb(uint16_t opcode
,
2647 uint32_t address
, struct arm_instruction
*instruction
)
2649 uint32_t reg_list
= opcode
& 0xff;
2650 uint32_t L
= opcode
& (1 << 11);
2651 uint32_t R
= opcode
& (1 << 8);
2652 uint8_t Rn
= (opcode
>> 8) & 7;
2653 uint8_t addr_mode
= 0 /* IA */;
2657 char ptr_name
[7] = "";
2660 /* REVISIT: in ThumbEE mode, there are no LDM or STM instructions.
2661 * The STMIA and LDMIA opcodes are used for other instructions.
2664 if ((opcode
& 0xf000) == 0xc000) { /* generic load/store multiple */
2668 instruction
->type
= ARM_LDM
;
2670 if (opcode
& (1 << Rn
))
2673 instruction
->type
= ARM_STM
;
2676 snprintf(ptr_name
, sizeof ptr_name
, "r%i%s, ", Rn
, wback
);
2677 } else {/* push/pop */
2680 instruction
->type
= ARM_LDM
;
2683 reg_list
|= (1 << 15) /*PC*/;
2685 instruction
->type
= ARM_STM
;
2687 addr_mode
= 3; /*DB*/
2689 reg_list
|= (1 << 14) /*LR*/;
2693 reg_names_p
= reg_names
;
2694 for (i
= 0; i
<= 15; i
++) {
2695 if (reg_list
& (1 << i
))
2696 reg_names_p
+= snprintf(reg_names_p
,
2697 (reg_names
+ 40 - reg_names_p
),
2701 if (reg_names_p
> reg_names
)
2702 reg_names_p
[-2] = '\0';
2703 else /* invalid op : no registers */
2704 reg_names
[0] = '\0';
2706 snprintf(instruction
->text
, 128,
2707 "0x%8.8" PRIx32
" 0x%4.4x \t%s\t%s{%s}",
2708 address
, opcode
, mnemonic
, ptr_name
, reg_names
);
2710 instruction
->info
.load_store_multiple
.register_list
= reg_list
;
2711 instruction
->info
.load_store_multiple
.Rn
= Rn
;
2712 instruction
->info
.load_store_multiple
.addressing_mode
= addr_mode
;
2717 static int evaluate_cond_branch_thumb(uint16_t opcode
,
2718 uint32_t address
, struct arm_instruction
*instruction
)
2720 uint32_t offset
= opcode
& 0xff;
2721 uint8_t cond
= (opcode
>> 8) & 0xf;
2722 uint32_t target_address
;
2725 instruction
->type
= ARM_SWI
;
2726 snprintf(instruction
->text
, 128,
2727 "0x%8.8" PRIx32
" 0x%4.4x \tSVC\t%#2.2" PRIx32
,
2728 address
, opcode
, offset
);
2730 } else if (cond
== 0xe) {
2731 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
2732 snprintf(instruction
->text
, 128,
2733 "0x%8.8" PRIx32
" 0x%4.4x \tUNDEFINED INSTRUCTION",
2738 /* sign extend 8-bit offset */
2739 if (offset
& 0x00000080)
2740 offset
= 0xffffff00 | offset
;
2742 target_address
= address
+ 4 + (offset
<< 1);
2744 snprintf(instruction
->text
, 128,
2745 "0x%8.8" PRIx32
" 0x%4.4x \tB%s\t%#8.8" PRIx32
,
2747 arm_condition_strings
[cond
], target_address
);
2749 instruction
->type
= ARM_B
;
2750 instruction
->info
.b_bl_bx_blx
.reg_operand
= -1;
2751 instruction
->info
.b_bl_bx_blx
.target_address
= target_address
;
2756 static int evaluate_cb_thumb(uint16_t opcode
, uint32_t address
,
2757 struct arm_instruction
*instruction
)
2761 /* added in Thumb2 */
2762 offset
= (opcode
>> 3) & 0x1f;
2763 offset
|= (opcode
& 0x0200) >> 4;
2765 snprintf(instruction
->text
, 128,
2766 "0x%8.8" PRIx32
" 0x%4.4x \tCB%sZ\tr%d, %#8.8" PRIx32
,
2768 (opcode
& 0x0800) ? "N" : "",
2769 opcode
& 0x7, address
+ 4 + (offset
<< 1));
2774 static int evaluate_extend_thumb(uint16_t opcode
, uint32_t address
,
2775 struct arm_instruction
*instruction
)
2777 /* added in ARMv6 */
2778 snprintf(instruction
->text
, 128,
2779 "0x%8.8" PRIx32
" 0x%4.4x \t%cXT%c\tr%d, r%d",
2781 (opcode
& 0x0080) ? 'U' : 'S',
2782 (opcode
& 0x0040) ? 'B' : 'H',
2783 opcode
& 0x7, (opcode
>> 3) & 0x7);
2788 static int evaluate_cps_thumb(uint16_t opcode
, uint32_t address
,
2789 struct arm_instruction
*instruction
)
2791 /* added in ARMv6 */
2792 if ((opcode
& 0x0ff0) == 0x0650)
2793 snprintf(instruction
->text
, 128,
2794 "0x%8.8" PRIx32
" 0x%4.4x \tSETEND %s",
2796 (opcode
& 0x80) ? "BE" : "LE");
2797 else /* ASSUME (opcode & 0x0fe0) == 0x0660 */
2798 snprintf(instruction
->text
, 128,
2799 "0x%8.8" PRIx32
" 0x%4.4x \tCPSI%c\t%s%s%s",
2801 (opcode
& 0x0010) ? 'D' : 'E',
2802 (opcode
& 0x0004) ? "A" : "",
2803 (opcode
& 0x0002) ? "I" : "",
2804 (opcode
& 0x0001) ? "F" : "");
2809 static int evaluate_byterev_thumb(uint16_t opcode
, uint32_t address
,
2810 struct arm_instruction
*instruction
)
2814 /* added in ARMv6 */
2815 switch ((opcode
>> 6) & 3) {
2826 snprintf(instruction
->text
, 128,
2827 "0x%8.8" PRIx32
" 0x%4.4x \tREV%s\tr%d, r%d",
2828 address
, opcode
, suffix
,
2829 opcode
& 0x7, (opcode
>> 3) & 0x7);
2834 static int evaluate_hint_thumb(uint16_t opcode
, uint32_t address
,
2835 struct arm_instruction
*instruction
)
2839 switch ((opcode
>> 4) & 0x0f) {
2856 hint
= "HINT (UNRECOGNIZED)";
2860 snprintf(instruction
->text
, 128,
2861 "0x%8.8" PRIx32
" 0x%4.4x \t%s",
2862 address
, opcode
, hint
);
2867 static int evaluate_ifthen_thumb(uint16_t opcode
, uint32_t address
,
2868 struct arm_instruction
*instruction
)
2870 unsigned cond
= (opcode
>> 4) & 0x0f;
2871 char *x
= "", *y
= "", *z
= "";
2874 z
= (opcode
& 0x02) ? "T" : "E";
2876 y
= (opcode
& 0x04) ? "T" : "E";
2878 x
= (opcode
& 0x08) ? "T" : "E";
2880 snprintf(instruction
->text
, 128,
2881 "0x%8.8" PRIx32
" 0x%4.4x \tIT%s%s%s\t%s",
2883 x
, y
, z
, arm_condition_strings
[cond
]);
2885 /* NOTE: strictly speaking, the next 1-4 instructions should
2886 * now be displayed with the relevant conditional suffix...
2892 int thumb_evaluate_opcode(uint16_t opcode
, uint32_t address
, struct arm_instruction
*instruction
)
2894 /* clear fields, to avoid confusion */
2895 memset(instruction
, 0, sizeof(struct arm_instruction
));
2896 instruction
->opcode
= opcode
;
2897 instruction
->instruction_size
= 2;
2899 if ((opcode
& 0xe000) == 0x0000) {
2900 /* add/substract register or immediate */
2901 if ((opcode
& 0x1800) == 0x1800)
2902 return evaluate_add_sub_thumb(opcode
, address
, instruction
);
2903 /* shift by immediate */
2905 return evaluate_shift_imm_thumb(opcode
, address
, instruction
);
2908 /* Add/substract/compare/move immediate */
2909 if ((opcode
& 0xe000) == 0x2000)
2910 return evaluate_data_proc_imm_thumb(opcode
, address
, instruction
);
2912 /* Data processing instructions */
2913 if ((opcode
& 0xf800) == 0x4000)
2914 return evaluate_data_proc_thumb(opcode
, address
, instruction
);
2916 /* Load from literal pool */
2917 if ((opcode
& 0xf800) == 0x4800)
2918 return evaluate_load_literal_thumb(opcode
, address
, instruction
);
2920 /* Load/Store register offset */
2921 if ((opcode
& 0xf000) == 0x5000)
2922 return evaluate_load_store_reg_thumb(opcode
, address
, instruction
);
2924 /* Load/Store immediate offset */
2925 if (((opcode
& 0xe000) == 0x6000)
2926 || ((opcode
& 0xf000) == 0x8000))
2927 return evaluate_load_store_imm_thumb(opcode
, address
, instruction
);
2929 /* Load/Store from/to stack */
2930 if ((opcode
& 0xf000) == 0x9000)
2931 return evaluate_load_store_stack_thumb(opcode
, address
, instruction
);
2934 if ((opcode
& 0xf000) == 0xa000)
2935 return evaluate_add_sp_pc_thumb(opcode
, address
, instruction
);
2938 if ((opcode
& 0xf000) == 0xb000) {
2939 switch ((opcode
>> 8) & 0x0f) {
2941 return evaluate_adjust_stack_thumb(opcode
, address
, instruction
);
2946 return evaluate_cb_thumb(opcode
, address
, instruction
);
2948 return evaluate_extend_thumb(opcode
, address
, instruction
);
2953 return evaluate_load_store_multiple_thumb(opcode
, address
,
2956 return evaluate_cps_thumb(opcode
, address
, instruction
);
2958 if ((opcode
& 0x00c0) == 0x0080)
2960 return evaluate_byterev_thumb(opcode
, address
, instruction
);
2962 return evaluate_breakpoint_thumb(opcode
, address
, instruction
);
2964 if (opcode
& 0x000f)
2965 return evaluate_ifthen_thumb(opcode
, address
,
2968 return evaluate_hint_thumb(opcode
, address
,
2972 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
2973 snprintf(instruction
->text
, 128,
2974 "0x%8.8" PRIx32
" 0x%4.4x \tUNDEFINED INSTRUCTION",
2979 /* Load/Store multiple */
2980 if ((opcode
& 0xf000) == 0xc000)
2981 return evaluate_load_store_multiple_thumb(opcode
, address
, instruction
);
2983 /* Conditional branch + SWI */
2984 if ((opcode
& 0xf000) == 0xd000)
2985 return evaluate_cond_branch_thumb(opcode
, address
, instruction
);
2987 if ((opcode
& 0xe000) == 0xe000) {
2988 /* Undefined instructions */
2989 if ((opcode
& 0xf801) == 0xe801) {
2990 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
2991 snprintf(instruction
->text
, 128,
2992 "0x%8.8" PRIx32
" 0x%8.8x\t"
2993 "UNDEFINED INSTRUCTION",
2996 } else /* Branch to offset */
2997 return evaluate_b_bl_blx_thumb(opcode
, address
, instruction
);
3000 LOG_ERROR("Thumb: should never reach this point (opcode=%04x)", opcode
);
3004 static int t2ev_b_bl(uint32_t opcode
, uint32_t address
,
3005 struct arm_instruction
*instruction
, char *cp
)
3008 unsigned b21
= 1 << 21;
3009 unsigned b22
= 1 << 22;
3011 /* instead of combining two smaller 16-bit branch instructions,
3012 * Thumb2 uses only one larger 32-bit instruction.
3014 offset
= opcode
& 0x7ff;
3015 offset
|= (opcode
& 0x03ff0000) >> 5;
3016 if (opcode
& (1 << 26)) {
3017 offset
|= 0xff << 23;
3018 if ((opcode
& (1 << 11)) == 0)
3020 if ((opcode
& (1 << 13)) == 0)
3023 if (opcode
& (1 << 11))
3025 if (opcode
& (1 << 13))
3033 address
+= offset
<< 1;
3036 switch ((opcode
>> 12) & 0x5) {
3039 instruction
->type
= ARM_B
;
3043 instruction
->type
= ARM_BLX
;
3044 address
&= 0xfffffffc;
3048 instruction
->type
= ARM_BL
;
3051 return ERROR_COMMAND_SYNTAX_ERROR
;
3053 instruction
->info
.b_bl_bx_blx
.reg_operand
= -1;
3054 instruction
->info
.b_bl_bx_blx
.target_address
= address
;
3055 sprintf(cp
, "%s\t%#8.8" PRIx32
, inst
, address
);
3060 static int t2ev_cond_b(uint32_t opcode
, uint32_t address
,
3061 struct arm_instruction
*instruction
, char *cp
)
3064 unsigned b17
= 1 << 17;
3065 unsigned b18
= 1 << 18;
3066 unsigned cond
= (opcode
>> 22) & 0x0f;
3068 offset
= opcode
& 0x7ff;
3069 offset
|= (opcode
& 0x003f0000) >> 5;
3070 if (opcode
& (1 << 26)) {
3071 offset
|= 0x1fff << 19;
3072 if ((opcode
& (1 << 11)) == 0)
3074 if ((opcode
& (1 << 13)) == 0)
3077 if (opcode
& (1 << 11))
3079 if (opcode
& (1 << 13))
3086 address
+= offset
<< 1;
3088 instruction
->type
= ARM_B
;
3089 instruction
->info
.b_bl_bx_blx
.reg_operand
= -1;
3090 instruction
->info
.b_bl_bx_blx
.target_address
= address
;
3091 sprintf(cp
, "B%s.W\t%#8.8" PRIx32
,
3092 arm_condition_strings
[cond
],
3098 static const char *special_name(int number
)
3100 char *special
= "(RESERVED)";
3131 special
= "primask";
3134 special
= "basepri";
3137 special
= "basepri_max";
3140 special
= "faultmask";
3143 special
= "control";
3149 static int t2ev_hint(uint32_t opcode
, uint32_t address
,
3150 struct arm_instruction
*instruction
, char *cp
)
3152 const char *mnemonic
;
3154 if (opcode
& 0x0700) {
3155 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
3156 strcpy(cp
, "UNDEFINED");
3160 if (opcode
& 0x00f0) {
3161 sprintf(cp
, "DBG\t#%d", (int) opcode
& 0xf);
3165 switch (opcode
& 0x0f) {
3170 mnemonic
= "YIELD.W";
3182 mnemonic
= "HINT.W (UNRECOGNIZED)";
3185 strcpy(cp
, mnemonic
);
3189 static int t2ev_misc(uint32_t opcode
, uint32_t address
,
3190 struct arm_instruction
*instruction
, char *cp
)
3192 const char *mnemonic
;
3194 switch ((opcode
>> 4) & 0x0f) {
3196 mnemonic
= "LEAVEX";
3199 mnemonic
= "ENTERX";
3214 return ERROR_COMMAND_SYNTAX_ERROR
;
3216 strcpy(cp
, mnemonic
);
3220 static int t2ev_b_misc(uint32_t opcode
, uint32_t address
,
3221 struct arm_instruction
*instruction
, char *cp
)
3223 /* permanently undefined */
3224 if ((opcode
& 0x07f07000) == 0x07f02000) {
3225 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
3226 strcpy(cp
, "UNDEFINED");
3230 switch ((opcode
>> 12) & 0x5) {
3234 return t2ev_b_bl(opcode
, address
, instruction
, cp
);
3236 if (((opcode
>> 23) & 0x07) != 0x07)
3237 return t2ev_cond_b(opcode
, address
, instruction
, cp
);
3238 if (opcode
& (1 << 26))
3243 switch ((opcode
>> 20) & 0x7f) {
3246 sprintf(cp
, "MSR\t%s, r%d", special_name(opcode
& 0xff),
3247 (int) (opcode
>> 16) & 0x0f);
3250 return t2ev_hint(opcode
, address
, instruction
, cp
);
3252 return t2ev_misc(opcode
, address
, instruction
, cp
);
3254 sprintf(cp
, "BXJ\tr%d", (int) (opcode
>> 16) & 0x0f);
3258 sprintf(cp
, "MRS\tr%d, %s", (int) (opcode
>> 8) & 0x0f,
3259 special_name(opcode
& 0xff));
3264 return ERROR_COMMAND_SYNTAX_ERROR
;
3267 static int t2ev_data_mod_immed(uint32_t opcode
, uint32_t address
,
3268 struct arm_instruction
*instruction
, char *cp
)
3270 char *mnemonic
= NULL
;
3271 int rn
= (opcode
>> 16) & 0xf;
3272 int rd
= (opcode
>> 8) & 0xf;
3273 unsigned immed
= opcode
& 0xff;
3279 /* ARMv7-M: A5.3.2 Modified immediate constants */
3280 func
= (opcode
>> 11) & 0x0e;
3283 if (opcode
& (1 << 26))
3286 /* "Modified" immediates */
3287 switch (func
>> 1) {
3294 immed
+= immed
<< 16;
3297 immed
+= immed
<< 8;
3298 immed
+= immed
<< 16;
3302 immed
= ror(immed
, func
);
3305 if (opcode
& (1 << 20))
3308 switch ((opcode
>> 21) & 0xf) {
3311 instruction
->type
= ARM_TST
;
3317 instruction
->type
= ARM_AND
;
3322 instruction
->type
= ARM_BIC
;
3327 instruction
->type
= ARM_MOV
;
3332 instruction
->type
= ARM_ORR
;
3338 instruction
->type
= ARM_MVN
;
3342 /* instruction->type = ARM_ORN; */
3348 instruction
->type
= ARM_TEQ
;
3354 instruction
->type
= ARM_EOR
;
3360 instruction
->type
= ARM_CMN
;
3366 instruction
->type
= ARM_ADD
;
3372 instruction
->type
= ARM_ADC
;
3377 instruction
->type
= ARM_SBC
;
3382 instruction
->type
= ARM_CMP
;
3388 instruction
->type
= ARM_SUB
;
3394 instruction
->type
= ARM_RSB
;
3399 return ERROR_COMMAND_SYNTAX_ERROR
;
3403 sprintf(cp
, "%s%s\tr%d, #%d\t; %#8.8x",
3404 mnemonic
, suffix2
, rd
, immed
, immed
);
3406 sprintf(cp
, "%s%s%s\tr%d, r%d, #%d\t; %#8.8x",
3407 mnemonic
, suffix
, suffix2
,
3408 rd
, rn
, immed
, immed
);
3413 static int t2ev_data_immed(uint32_t opcode
, uint32_t address
,
3414 struct arm_instruction
*instruction
, char *cp
)
3416 char *mnemonic
= NULL
;
3417 int rn
= (opcode
>> 16) & 0xf;
3418 int rd
= (opcode
>> 8) & 0xf;
3421 bool is_signed
= false;
3423 immed
= (opcode
& 0x0ff) | ((opcode
& 0x7000) >> 4);
3424 if (opcode
& (1 << 26))
3427 switch ((opcode
>> 20) & 0x1f) {
3436 immed
|= (opcode
>> 4) & 0xf000;
3437 sprintf(cp
, "MOVW\tr%d, #%d\t; %#3.3x", rd
, immed
, immed
);
3445 /* move constant to top 16 bits of register */
3446 immed
|= (opcode
>> 4) & 0xf000;
3447 sprintf(cp
, "MOVT\tr%d, #%d\t; %#4.4x", rd
, immed
, immed
);
3455 /* signed/unsigned saturated add */
3456 immed
= (opcode
>> 6) & 0x03;
3457 immed
|= (opcode
>> 10) & 0x1c;
3458 sprintf(cp
, "%sSAT\tr%d, #%d, r%d, %s #%d\t",
3459 is_signed
? "S" : "U",
3460 rd
, (int) (opcode
& 0x1f) + is_signed
, rn
,
3461 (opcode
& (1 << 21)) ? "ASR" : "LSL",
3462 immed
? immed
: 32);
3468 /* signed/unsigned bitfield extract */
3469 immed
= (opcode
>> 6) & 0x03;
3470 immed
|= (opcode
>> 10) & 0x1c;
3471 sprintf(cp
, "%sBFX\tr%d, r%d, #%d, #%d\t",
3472 is_signed
? "S" : "U",
3474 (int) (opcode
& 0x1f) + 1);
3477 immed
= (opcode
>> 6) & 0x03;
3478 immed
|= (opcode
>> 10) & 0x1c;
3479 if (rn
== 0xf) /* bitfield clear */
3480 sprintf(cp
, "BFC\tr%d, #%d, #%d\t",
3482 (int) (opcode
& 0x1f) + 1 - immed
);
3483 else /* bitfield insert */
3484 sprintf(cp
, "BFI\tr%d, r%d, #%d, #%d\t",
3486 (int) (opcode
& 0x1f) + 1 - immed
);
3489 return ERROR_COMMAND_SYNTAX_ERROR
;
3492 sprintf(cp
, "%s\tr%d, r%d, #%d\t; %#3.3x", mnemonic
,
3493 rd
, rn
, immed
, immed
);
3497 address
= thumb_alignpc4(address
);
3502 /* REVISIT "ADD/SUB Rd, PC, #const ; 0x..." might be better;
3503 * not hiding the pc-relative stuff will sometimes be useful.
3505 sprintf(cp
, "ADR.W\tr%d, %#8.8" PRIx32
, rd
, address
);
3509 static int t2ev_store_single(uint32_t opcode
, uint32_t address
,
3510 struct arm_instruction
*instruction
, char *cp
)
3512 unsigned op
= (opcode
>> 20) & 0xf;
3518 unsigned rn
= (opcode
>> 16) & 0x0f;
3519 unsigned rt
= (opcode
>> 12) & 0x0f;
3522 return ERROR_COMMAND_SYNTAX_ERROR
;
3524 if (opcode
& 0x0800)
3559 return ERROR_COMMAND_SYNTAX_ERROR
;
3562 sprintf(cp
, "STR%s.W\tr%d, [r%d, r%d, LSL #%d]",
3563 size
, rt
, rn
, (int) opcode
& 0x0f,
3564 (int) (opcode
>> 4) & 0x03);
3568 immed
= opcode
& 0x0fff;
3569 sprintf(cp
, "STR%s.W\tr%d, [r%d, #%u]\t; %#3.3x",
3570 size
, rt
, rn
, immed
, immed
);
3574 immed
= opcode
& 0x00ff;
3576 switch (opcode
& 0x700) {
3582 return ERROR_COMMAND_SYNTAX_ERROR
;
3585 /* two indexed modes will write back rn */
3586 if (opcode
& 0x100) {
3587 if (opcode
& 0x400) /* pre-indexed */
3589 else { /* post-indexed */
3595 sprintf(cp
, "STR%s%s\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
3596 size
, suffix
, rt
, rn
, p1
,
3597 (opcode
& 0x200) ? "" : "-",
3602 static int t2ev_mul32(uint32_t opcode
, uint32_t address
,
3603 struct arm_instruction
*instruction
, char *cp
)
3605 int ra
= (opcode
>> 12) & 0xf;
3607 switch (opcode
& 0x007000f0) {
3610 sprintf(cp
, "MUL\tr%d, r%d, r%d",
3611 (int) (opcode
>> 8) & 0xf,
3612 (int) (opcode
>> 16) & 0xf,
3613 (int) (opcode
>> 0) & 0xf);
3615 sprintf(cp
, "MLA\tr%d, r%d, r%d, r%d",
3616 (int) (opcode
>> 8) & 0xf,
3617 (int) (opcode
>> 16) & 0xf,
3618 (int) (opcode
>> 0) & 0xf, ra
);
3621 sprintf(cp
, "MLS\tr%d, r%d, r%d, r%d",
3622 (int) (opcode
>> 8) & 0xf,
3623 (int) (opcode
>> 16) & 0xf,
3624 (int) (opcode
>> 0) & 0xf, ra
);
3627 return ERROR_COMMAND_SYNTAX_ERROR
;
3632 static int t2ev_mul64_div(uint32_t opcode
, uint32_t address
,
3633 struct arm_instruction
*instruction
, char *cp
)
3635 int op
= (opcode
>> 4) & 0xf;
3636 char *infix
= "MUL";
3638 op
+= (opcode
>> 16) & 0x70;
3646 sprintf(cp
, "%c%sL\tr%d, r%d, r%d, r%d",
3647 (op
& 0x20) ? 'U' : 'S',
3649 (int) (opcode
>> 12) & 0xf,
3650 (int) (opcode
>> 8) & 0xf,
3651 (int) (opcode
>> 16) & 0xf,
3652 (int) (opcode
>> 0) & 0xf);
3656 sprintf(cp
, "%cDIV\tr%d, r%d, r%d",
3657 (op
& 0x20) ? 'U' : 'S',
3658 (int) (opcode
>> 8) & 0xf,
3659 (int) (opcode
>> 16) & 0xf,
3660 (int) (opcode
>> 0) & 0xf);
3663 return ERROR_COMMAND_SYNTAX_ERROR
;
3669 static int t2ev_ldm_stm(uint32_t opcode
, uint32_t address
,
3670 struct arm_instruction
*instruction
, char *cp
)
3672 int rn
= (opcode
>> 16) & 0xf;
3673 int op
= (opcode
>> 22) & 0x6;
3674 int t
= (opcode
>> 21) & 1;
3675 unsigned registers
= opcode
& 0xffff;
3678 if (opcode
& (1 << 20))
3686 sprintf(cp
, "SRS%s\tsp%s, #%d", mode
,
3688 (unsigned) (opcode
& 0x1f));
3694 sprintf(cp
, "RFE%s\tr%d%s", mode
,
3695 (unsigned) ((opcode
>> 16) & 0xf),
3699 sprintf(cp
, "STM.W\tr%d%s, ", rn
, t
? "!" : "");
3703 sprintf(cp
, "POP.W\t");
3705 sprintf(cp
, "LDM.W\tr%d%s, ", rn
, t
? "!" : "");
3709 sprintf(cp
, "PUSH.W\t");
3711 sprintf(cp
, "STMDB\tr%d%s, ", rn
, t
? "!" : "");
3714 sprintf(cp
, "LDMDB.W\tr%d%s, ", rn
, t
? "!" : "");
3717 return ERROR_COMMAND_SYNTAX_ERROR
;
3722 for (t
= 0; registers
; t
++, registers
>>= 1) {
3723 if ((registers
& 1) == 0)
3726 sprintf(cp
, "r%d%s", t
, registers
? ", " : "");
3735 /* load/store dual or exclusive, table branch */
3736 static int t2ev_ldrex_strex(uint32_t opcode
, uint32_t address
,
3737 struct arm_instruction
*instruction
, char *cp
)
3739 unsigned op1op2
= (opcode
>> 20) & 0x3;
3740 unsigned op3
= (opcode
>> 4) & 0xf;
3742 unsigned rn
= (opcode
>> 16) & 0xf;
3743 unsigned rt
= (opcode
>> 12) & 0xf;
3744 unsigned rd
= (opcode
>> 8) & 0xf;
3745 unsigned imm
= opcode
& 0xff;
3749 op1op2
|= (opcode
>> 21) & 0xc;
3779 mnemonic
= "STREXB";
3782 mnemonic
= "STREXH";
3785 return ERROR_COMMAND_SYNTAX_ERROR
;
3793 sprintf(cp
, "TBB\t[r%u, r%u]", rn
, imm
& 0xf);
3796 sprintf(cp
, "TBH\t[r%u, r%u, LSL #1]", rn
, imm
& 0xf);
3799 mnemonic
= "LDREXB";
3802 mnemonic
= "LDREXH";
3805 return ERROR_COMMAND_SYNTAX_ERROR
;
3810 return ERROR_COMMAND_SYNTAX_ERROR
;
3815 sprintf(cp
, "%s\tr%u, r%u, [r%u, #%u]\t; %#2.2x",
3816 mnemonic
, rd
, rt
, rn
, imm
, imm
);
3818 sprintf(cp
, "%s\tr%u, r%u, [r%u]",
3819 mnemonic
, rd
, rt
, rn
);
3825 sprintf(cp
, "%s\tr%u, [r%u, #%u]\t; %#2.2x",
3826 mnemonic
, rt
, rn
, imm
, imm
);
3828 sprintf(cp
, "%s\tr%u, [r%u]",
3833 /* two indexed modes will write back rn */
3834 if (opcode
& (1 << 21)) {
3835 if (opcode
& (1 << 24)) /* pre-indexed */
3837 else { /* post-indexed */
3844 sprintf(cp
, "%s\tr%u, r%u, [r%u%s, #%s%u%s\t; %#2.2x",
3845 mnemonic
, rt
, rd
, rn
, p1
,
3846 (opcode
& (1 << 23)) ? "" : "-",
3851 address
= thumb_alignpc4(address
);
3853 if (opcode
& (1 << 23))
3857 sprintf(cp
, "%s\tr%u, r%u, %#8.8" PRIx32
,
3858 mnemonic
, rt
, rd
, address
);
3862 static int t2ev_data_shift(uint32_t opcode
, uint32_t address
,
3863 struct arm_instruction
*instruction
, char *cp
)
3865 int op
= (opcode
>> 21) & 0xf;
3866 int rd
= (opcode
>> 8) & 0xf;
3867 int rn
= (opcode
>> 16) & 0xf;
3868 int type
= (opcode
>> 4) & 0x3;
3869 int immed
= (opcode
>> 6) & 0x3;
3873 immed
|= (opcode
>> 10) & 0x1c;
3874 if (opcode
& (1 << 20))
3880 if (!(opcode
& (1 << 20)))
3881 return ERROR_COMMAND_SYNTAX_ERROR
;
3882 instruction
->type
= ARM_TST
;
3887 instruction
->type
= ARM_AND
;
3891 instruction
->type
= ARM_BIC
;
3896 instruction
->type
= ARM_MOV
;
3900 sprintf(cp
, "MOV%s.W\tr%d, r%d",
3902 (int) (opcode
& 0xf));
3915 sprintf(cp
, "RRX%s\tr%d, r%d",
3917 (int) (opcode
& 0xf));
3925 instruction
->type
= ARM_ORR
;
3931 instruction
->type
= ARM_MVN
;
3936 /* instruction->type = ARM_ORN; */
3942 if (!(opcode
& (1 << 20)))
3943 return ERROR_COMMAND_SYNTAX_ERROR
;
3944 instruction
->type
= ARM_TEQ
;
3949 instruction
->type
= ARM_EOR
;
3954 if (!(opcode
& (1 << 20)))
3955 return ERROR_COMMAND_SYNTAX_ERROR
;
3956 instruction
->type
= ARM_CMN
;
3961 instruction
->type
= ARM_ADD
;
3965 instruction
->type
= ARM_ADC
;
3969 instruction
->type
= ARM_SBC
;
3974 if (!(opcode
& (1 << 21)))
3975 return ERROR_COMMAND_SYNTAX_ERROR
;
3976 instruction
->type
= ARM_CMP
;
3981 instruction
->type
= ARM_SUB
;
3985 instruction
->type
= ARM_RSB
;
3989 return ERROR_COMMAND_SYNTAX_ERROR
;
3992 sprintf(cp
, "%s%s.W\tr%d, r%d, r%d",
3993 mnemonic
, suffix
, rd
, rn
, (int) (opcode
& 0xf));
4016 strcpy(cp
, ", RRX");
4022 sprintf(cp
, ", %s #%d", suffix
, immed
? immed
: 32);
4026 sprintf(cp
, "%s%s.W\tr%d, r%d",
4027 mnemonic
, suffix
, rn
, (int) (opcode
& 0xf));
4031 sprintf(cp
, "%s%s.W\tr%d, r%d, #%d",
4032 mnemonic
, suffix
, rd
,
4033 (int) (opcode
& 0xf), immed
? immed
: 32);
4037 static int t2ev_data_reg(uint32_t opcode
, uint32_t address
,
4038 struct arm_instruction
*instruction
, char *cp
)
4043 if (((opcode
>> 4) & 0xf) == 0) {
4044 switch ((opcode
>> 21) & 0x7) {
4058 return ERROR_COMMAND_SYNTAX_ERROR
;
4061 instruction
->type
= ARM_MOV
;
4062 if (opcode
& (1 << 20))
4064 sprintf(cp
, "%s%s.W\tr%d, r%d, r%d",
4066 (int) (opcode
>> 8) & 0xf,
4067 (int) (opcode
>> 16) & 0xf,
4068 (int) (opcode
>> 0) & 0xf);
4070 } else if (opcode
& (1 << 7)) {
4071 switch ((opcode
>> 20) & 0xf) {
4076 switch ((opcode
>> 4) & 0x3) {
4078 suffix
= ", ROR #8";
4081 suffix
= ", ROR #16";
4084 suffix
= ", ROR #24";
4087 sprintf(cp
, "%cXT%c.W\tr%d, r%d%s",
4088 (opcode
& (1 << 24)) ? 'U' : 'S',
4089 (opcode
& (1 << 26)) ? 'B' : 'H',
4090 (int) (opcode
>> 8) & 0xf,
4091 (int) (opcode
>> 0) & 0xf,
4098 if (opcode
& (1 << 6))
4099 return ERROR_COMMAND_SYNTAX_ERROR
;
4100 if (((opcode
>> 12) & 0xf) != 0xf)
4101 return ERROR_COMMAND_SYNTAX_ERROR
;
4102 if (!(opcode
& (1 << 20)))
4103 return ERROR_COMMAND_SYNTAX_ERROR
;
4105 switch (((opcode
>> 19) & 0x04)
4106 | ((opcode
>> 4) & 0x3)) {
4111 mnemonic
= "REV16.W";
4117 mnemonic
= "REVSH.W";
4123 return ERROR_COMMAND_SYNTAX_ERROR
;
4125 sprintf(cp
, "%s\tr%d, r%d",
4127 (int) (opcode
>> 8) & 0xf,
4128 (int) (opcode
>> 0) & 0xf);
4131 return ERROR_COMMAND_SYNTAX_ERROR
;
4138 static int t2ev_load_word(uint32_t opcode
, uint32_t address
,
4139 struct arm_instruction
*instruction
, char *cp
)
4141 int rn
= (opcode
>> 16) & 0xf;
4144 instruction
->type
= ARM_LDR
;
4147 immed
= opcode
& 0x0fff;
4148 if ((opcode
& (1 << 23)) == 0)
4150 sprintf(cp
, "LDR\tr%d, %#8.8" PRIx32
,
4151 (int) (opcode
>> 12) & 0xf,
4152 thumb_alignpc4(address
) + immed
);
4156 if (opcode
& (1 << 23)) {
4157 immed
= opcode
& 0x0fff;
4158 sprintf(cp
, "LDR.W\tr%d, [r%d, #%d]\t; %#3.3x",
4159 (int) (opcode
>> 12) & 0xf,
4164 if (!(opcode
& (0x3f << 6))) {
4165 sprintf(cp
, "LDR.W\tr%d, [r%d, r%d, LSL #%d]",
4166 (int) (opcode
>> 12) & 0xf,
4168 (int) (opcode
>> 0) & 0xf,
4169 (int) (opcode
>> 4) & 0x3);
4174 if (((opcode
>> 8) & 0xf) == 0xe) {
4175 immed
= opcode
& 0x00ff;
4177 sprintf(cp
, "LDRT\tr%d, [r%d, #%d]\t; %#2.2x",
4178 (int) (opcode
>> 12) & 0xf,
4183 if (((opcode
>> 8) & 0xf) == 0xc || (opcode
& 0x0900) == 0x0900) {
4184 char *p1
= "]", *p2
= "";
4186 if (!(opcode
& 0x0500))
4187 return ERROR_COMMAND_SYNTAX_ERROR
;
4189 immed
= opcode
& 0x00ff;
4191 /* two indexed modes will write back rn */
4192 if (opcode
& 0x100) {
4193 if (opcode
& 0x400) /* pre-indexed */
4195 else { /* post-indexed */
4201 sprintf(cp
, "LDR\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
4202 (int) (opcode
>> 12) & 0xf,
4204 (opcode
& 0x200) ? "" : "-",
4209 return ERROR_COMMAND_SYNTAX_ERROR
;
4212 static int t2ev_load_byte_hints(uint32_t opcode
, uint32_t address
,
4213 struct arm_instruction
*instruction
, char *cp
)
4215 int rn
= (opcode
>> 16) & 0xf;
4216 int rt
= (opcode
>> 12) & 0xf;
4217 int op2
= (opcode
>> 6) & 0x3f;
4219 char *p1
= "", *p2
= "]";
4222 switch ((opcode
>> 23) & 0x3) {
4224 if ((rn
& rt
) == 0xf) {
4226 immed
= opcode
& 0xfff;
4227 address
= thumb_alignpc4(address
);
4228 if (opcode
& (1 << 23))
4232 sprintf(cp
, "PLD\tr%d, %#8.8" PRIx32
,
4236 if (rn
== 0x0f && rt
!= 0x0f) {
4238 immed
= opcode
& 0xfff;
4239 address
= thumb_alignpc4(address
);
4240 if (opcode
& (1 << 23))
4244 sprintf(cp
, "LDRB\tr%d, %#8.8" PRIx32
,
4250 if ((op2
& 0x3c) == 0x38) {
4251 immed
= opcode
& 0xff;
4252 sprintf(cp
, "LDRBT\tr%d, [r%d, #%d]\t; %#2.2x",
4253 rt
, rn
, immed
, immed
);
4256 if ((op2
& 0x3c) == 0x30) {
4258 immed
= opcode
& 0xff;
4261 p1
= (opcode
& (1 << 21)) ? "W" : "";
4262 sprintf(cp
, "PLD%s\t[r%d, #%d]\t; %#6.6x",
4263 p1
, rn
, immed
, immed
);
4268 immed
= opcode
& 0xff;
4269 if (!(opcode
& 0x200))
4272 /* two indexed modes will write back rn */
4273 if (opcode
& 0x100) {
4274 if (opcode
& 0x400) /* pre-indexed */
4276 else { /* post-indexed */
4282 sprintf(cp
, "%s\tr%d, [r%d%s, #%d%s\t; %#8.8x",
4283 mnemonic
, rt
, rn
, p1
,
4287 if ((op2
& 0x24) == 0x24) {
4289 goto ldrxb_immediate_t3
;
4292 int rm
= opcode
& 0xf;
4295 sprintf(cp
, "PLD\t");
4297 sprintf(cp
, "LDRB.W\tr%d, ", rt
);
4298 immed
= (opcode
>> 4) & 0x3;
4300 sprintf(cp
, "[r%d, r%d, LSL #%d]", rn
, rm
, immed
);
4305 if ((rn
& rt
) == 0xf)
4308 immed
= opcode
& 0xfff;
4309 goto preload_immediate
;
4313 mnemonic
= "LDRB.W";
4314 immed
= opcode
& 0xfff;
4315 goto ldrxb_immediate_t2
;
4317 if ((rn
& rt
) == 0xf) {
4318 immed
= opcode
& 0xfff;
4319 address
= thumb_alignpc4(address
);
4320 if (opcode
& (1 << 23))
4324 sprintf(cp
, "PLI\t%#8.8" PRIx32
, address
);
4327 if (rn
== 0xf && rt
!= 0xf) {
4329 immed
= opcode
& 0xfff;
4330 address
= thumb_alignpc4(address
);
4331 if (opcode
& (1 << 23))
4335 sprintf(cp
, "LDRSB\t%#8.8" PRIx32
, address
);
4340 if ((op2
& 0x3c) == 0x38) {
4341 immed
= opcode
& 0xff;
4342 sprintf(cp
, "LDRSBT\tr%d, [r%d, #%d]\t; %#2.2x",
4343 rt
, rn
, immed
, immed
);
4346 if ((op2
& 0x3c) == 0x30) {
4348 immed
= opcode
& 0xff;
4349 immed
= -immed
; /* pli */
4350 sprintf(cp
, "PLI\t[r%d, #%d]\t; -%#2.2x",
4355 goto ldrxb_immediate_t3
;
4357 if ((op2
& 0x24) == 0x24) {
4359 goto ldrxb_immediate_t3
;
4362 int rm
= opcode
& 0xf;
4365 sprintf(cp
, "PLI\t");
4367 sprintf(cp
, "LDRSB.W\tr%d, ", rt
);
4368 immed
= (opcode
>> 4) & 0x3;
4370 sprintf(cp
, "[r%d, r%d, LSL #%d]", rn
, rm
, immed
);
4376 immed
= opcode
& 0xfff;
4377 sprintf(cp
, "PLI\t[r%d, #%d]\t; %#3.3x",
4383 immed
= opcode
& 0xfff;
4385 goto ldrxb_immediate_t2
;
4388 return ERROR_COMMAND_SYNTAX_ERROR
;
4391 static int t2ev_load_halfword(uint32_t opcode
, uint32_t address
,
4392 struct arm_instruction
*instruction
, char *cp
)
4394 int rn
= (opcode
>> 16) & 0xf;
4395 int rt
= (opcode
>> 12) & 0xf;
4396 int op2
= (opcode
>> 6) & 0x3f;
4401 sprintf(cp
, "HINT (UNALLOCATED)");
4405 if (opcode
& (1 << 24))
4408 if ((opcode
& (1 << 23)) == 0) {
4411 immed
= opcode
& 0xfff;
4412 address
= thumb_alignpc4(address
);
4413 if (opcode
& (1 << 23))
4417 sprintf(cp
, "LDR%sH\tr%d, %#8.8" PRIx32
,
4422 int rm
= opcode
& 0xf;
4424 immed
= (opcode
>> 4) & 0x3;
4425 sprintf(cp
, "LDR%sH.W\tr%d, [r%d, r%d, LSL #%d]",
4426 sign
, rt
, rn
, rm
, immed
);
4429 if ((op2
& 0x3c) == 0x38) {
4430 immed
= opcode
& 0xff;
4431 sprintf(cp
, "LDR%sHT\tr%d, [r%d, #%d]\t; %#2.2x",
4432 sign
, rt
, rn
, immed
, immed
);
4435 if ((op2
& 0x3c) == 0x30 || (op2
& 0x24) == 0x24) {
4436 char *p1
= "", *p2
= "]";
4438 immed
= opcode
& 0xff;
4439 if (!(opcode
& 0x200))
4442 /* two indexed modes will write back rn */
4443 if (opcode
& 0x100) {
4444 if (opcode
& 0x400) /* pre-indexed */
4446 else { /* post-indexed */
4451 sprintf(cp
, "LDR%sH\tr%d, [r%d%s, #%d%s\t; %#8.8x",
4452 sign
, rt
, rn
, p1
, immed
, p2
, immed
);
4459 immed
= opcode
& 0xfff;
4460 sprintf(cp
, "LDR%sH%s\tr%d, [r%d, #%d]\t; %#6.6x",
4461 sign
, *sign
? "" : ".W",
4462 rt
, rn
, immed
, immed
);
4466 return ERROR_COMMAND_SYNTAX_ERROR
;
4470 * REVISIT for Thumb2 instructions, instruction->type and friends aren't
4471 * always set. That means eventual arm_simulate_step() support for Thumb2
4472 * will need work in this area.
4474 int thumb2_opcode(struct target
*target
, uint32_t address
, struct arm_instruction
*instruction
)
4481 /* clear low bit ... it's set on function pointers */
4484 /* clear fields, to avoid confusion */
4485 memset(instruction
, 0, sizeof(struct arm_instruction
));
4487 /* read first halfword, see if this is the only one */
4488 retval
= target_read_u16(target
, address
, &op
);
4489 if (retval
!= ERROR_OK
)
4492 switch (op
& 0xf800) {
4496 /* 32-bit instructions */
4497 instruction
->instruction_size
= 4;
4499 retval
= target_read_u16(target
, address
+ 2, &op
);
4500 if (retval
!= ERROR_OK
)
4503 instruction
->opcode
= opcode
;
4506 /* 16-bit: Thumb1 + IT + CBZ/CBNZ + ... */
4507 return thumb_evaluate_opcode(op
, address
, instruction
);
4510 snprintf(instruction
->text
, 128,
4511 "0x%8.8" PRIx32
" 0x%8.8" PRIx32
"\t",
4513 cp
= strchr(instruction
->text
, 0);
4514 retval
= ERROR_FAIL
;
4516 /* ARMv7-M: A5.3.1 Data processing (modified immediate) */
4517 if ((opcode
& 0x1a008000) == 0x10000000)
4518 retval
= t2ev_data_mod_immed(opcode
, address
, instruction
, cp
);
4520 /* ARMv7-M: A5.3.3 Data processing (plain binary immediate) */
4521 else if ((opcode
& 0x1a008000) == 0x12000000)
4522 retval
= t2ev_data_immed(opcode
, address
, instruction
, cp
);
4524 /* ARMv7-M: A5.3.4 Branches and miscellaneous control */
4525 else if ((opcode
& 0x18008000) == 0x10008000)
4526 retval
= t2ev_b_misc(opcode
, address
, instruction
, cp
);
4528 /* ARMv7-M: A5.3.5 Load/store multiple */
4529 else if ((opcode
& 0x1e400000) == 0x08000000)
4530 retval
= t2ev_ldm_stm(opcode
, address
, instruction
, cp
);
4532 /* ARMv7-M: A5.3.6 Load/store dual or exclusive, table branch */
4533 else if ((opcode
& 0x1e400000) == 0x08400000)
4534 retval
= t2ev_ldrex_strex(opcode
, address
, instruction
, cp
);
4536 /* ARMv7-M: A5.3.7 Load word */
4537 else if ((opcode
& 0x1f700000) == 0x18500000)
4538 retval
= t2ev_load_word(opcode
, address
, instruction
, cp
);
4540 /* ARMv7-M: A5.3.8 Load halfword, unallocated memory hints */
4541 else if ((opcode
& 0x1e700000) == 0x18300000)
4542 retval
= t2ev_load_halfword(opcode
, address
, instruction
, cp
);
4544 /* ARMv7-M: A5.3.9 Load byte, memory hints */
4545 else if ((opcode
& 0x1e700000) == 0x18100000)
4546 retval
= t2ev_load_byte_hints(opcode
, address
, instruction
, cp
);
4548 /* ARMv7-M: A5.3.10 Store single data item */
4549 else if ((opcode
& 0x1f100000) == 0x18000000)
4550 retval
= t2ev_store_single(opcode
, address
, instruction
, cp
);
4552 /* ARMv7-M: A5.3.11 Data processing (shifted register) */
4553 else if ((opcode
& 0x1e000000) == 0x0a000000)
4554 retval
= t2ev_data_shift(opcode
, address
, instruction
, cp
);
4556 /* ARMv7-M: A5.3.12 Data processing (register)
4557 * and A5.3.13 Miscellaneous operations
4559 else if ((opcode
& 0x1f000000) == 0x1a000000)
4560 retval
= t2ev_data_reg(opcode
, address
, instruction
, cp
);
4562 /* ARMv7-M: A5.3.14 Multiply, and multiply accumulate */
4563 else if ((opcode
& 0x1f800000) == 0x1b000000)
4564 retval
= t2ev_mul32(opcode
, address
, instruction
, cp
);
4566 /* ARMv7-M: A5.3.15 Long multiply, long multiply accumulate, divide */
4567 else if ((opcode
& 0x1f800000) == 0x1b800000)
4568 retval
= t2ev_mul64_div(opcode
, address
, instruction
, cp
);
4570 if (retval
== ERROR_OK
)
4574 * Thumb2 also supports coprocessor, ThumbEE, and DSP/Media (SIMD)
4575 * instructions; not yet handled here.
4578 if (retval
== ERROR_COMMAND_SYNTAX_ERROR
) {
4579 instruction
->type
= ARM_UNDEFINED_INSTRUCTION
;
4580 strcpy(cp
, "UNDEFINED OPCODE");
4584 LOG_DEBUG("Can't decode 32-bit Thumb2 yet (opcode=%08" PRIx32
")",
4587 strcpy(cp
, "(32-bit Thumb2 ...)");
4591 int arm_access_size(struct arm_instruction
*instruction
)
4593 if ((instruction
->type
== ARM_LDRB
)
4594 || (instruction
->type
== ARM_LDRBT
)
4595 || (instruction
->type
== ARM_LDRSB
)
4596 || (instruction
->type
== ARM_STRB
)
4597 || (instruction
->type
== ARM_STRBT
))
4599 else if ((instruction
->type
== ARM_LDRH
)
4600 || (instruction
->type
== ARM_LDRSH
)
4601 || (instruction
->type
== ARM_STRH
))
4603 else if ((instruction
->type
== ARM_LDR
)
4604 || (instruction
->type
== ARM_LDRT
)
4605 || (instruction
->type
== ARM_STR
)
4606 || (instruction
->type
== ARM_STRT
))
4608 else if ((instruction
->type
== ARM_LDRD
)
4609 || (instruction
->type
== ARM_STRD
))
4612 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)