Use capstone for ARM disassembler
[openocd.git] / src / target / arm_disassembler.c
blob9b8c09e45f73a9f432316a35bebe95e4fbf70892
1 /***************************************************************************
2 * Copyright (C) 2006 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) 2009 by David Brownell *
6 * *
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. *
11 * *
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. *
16 * *
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 ***************************************************************************/
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
25 #include "target.h"
26 #include "arm_disassembler.h"
27 #include <helper/log.h>
29 #if HAVE_CAPSTONE
30 #include <capstone/capstone.h>
31 #endif
34 * This disassembler supports two main functions for OpenOCD:
36 * - Various "disassemble" commands. OpenOCD can serve as a
37 * machine-language debugger, without help from GDB.
39 * - Single stepping. Not all ARM cores support hardware single
40 * stepping. To work without that support, the debugger must
41 * be able to decode instructions to find out where to put a
42 * "next instruction" breakpoint.
44 * In addition, interpretation of ETM trace data needs some of the
45 * decoding mechanisms.
47 * At this writing (September 2009) neither function is complete.
49 * - ARM decoding
50 * * Old-style syntax (not UAL) is generally used
51 * * VFP instructions are not understood (ARMv5 and later)
52 * except as coprocessor 10/11 operations
53 * * Most ARM instructions through ARMv6 are decoded, but some
54 * of the post-ARMv4 opcodes may not be handled yet
55 * CPS, SDIV, UDIV, LDREX*, STREX*, QASX, ...
56 * * NEON instructions are not understood (ARMv7-A)
58 * - Thumb/Thumb2 decoding
59 * * UAL syntax should be consistently used
60 * * Any Thumb2 instructions used in Cortex-M3 (ARMv7-M) should
61 * be handled properly. Accordingly, so should the subset
62 * used in Cortex-M0/M1; and "original" 16-bit Thumb from
63 * ARMv4T and ARMv5T.
64 * * Conditional effects of Thumb2 "IT" (if-then) instructions
65 * are not handled: the affected instructions are not shown
66 * with their now-conditional suffixes.
67 * * Some ARMv6 and ARMv7-M Thumb2 instructions may not be
68 * handled (minimally for coprocessor access).
69 * * SIMD instructions, and some other Thumb2 instructions
70 * from ARMv7-A, are not understood.
72 * - ThumbEE decoding
73 * * As a Thumb2 variant, the Thumb2 comments (above) apply.
74 * * Opcodes changed by ThumbEE mode are not handled; these
75 * instructions wrongly decode as LDM and STM.
77 * - Jazelle decoding ... no support whatsoever for Jazelle mode
78 * or decoding. ARM encourages use of the more generic ThumbEE
79 * mode, instead of Jazelle mode, in current chips.
81 * - Single-step/emulation ... spotty support, which is only weakly
82 * tested. Thumb2 is not supported. (Arguably a full simulator
83 * is not needed to support just single stepping. Recognizing
84 * branch vs non-branch instructions suffices, except when the
85 * instruction faults and triggers a synchronous exception which
86 * can be intercepted using other means.)
88 * ARM DDI 0406B "ARM Architecture Reference Manual, ARM v7-A and
89 * ARM v7-R edition" gives the most complete coverage of the various
90 * generations of ARM instructions. At this writing it is publicly
91 * accessible to anyone willing to create an account at the ARM
92 * web site; see http://www.arm.com/documentation/ for information.
94 * ARM DDI 0403C "ARMv7-M Architecture Reference Manual" provides
95 * more details relevant to the Thumb2-only processors (such as
96 * the Cortex-M implementations).
99 /* textual representation of the condition field
100 * ALways (default) is omitted (empty string) */
101 static const char *arm_condition_strings[] = {
102 "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", "HI", "LS", "GE", "LT", "GT", "LE", "", "NV"
105 /* make up for C's missing ROR */
106 static uint32_t ror(uint32_t value, int places)
108 return (value >> places) | (value << (32 - places));
111 static int evaluate_unknown(uint32_t opcode,
112 uint32_t address, struct arm_instruction *instruction)
114 instruction->type = ARM_UNDEFINED_INSTRUCTION;
115 snprintf(instruction->text, 128,
116 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
117 "\tUNDEFINED INSTRUCTION", address, opcode);
118 return ERROR_OK;
121 static int evaluate_pld(uint32_t opcode,
122 uint32_t address, struct arm_instruction *instruction)
124 /* PLD */
125 if ((opcode & 0x0d30f000) == 0x0510f000) {
126 uint8_t Rn;
127 uint8_t U;
128 unsigned offset;
130 instruction->type = ARM_PLD;
131 Rn = (opcode & 0xf0000) >> 16;
132 U = (opcode & 0x00800000) >> 23;
133 if (Rn == 0xf) {
134 /* literal */
135 offset = opcode & 0x0fff;
136 snprintf(instruction->text, 128,
137 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD %s%d",
138 address, opcode, U ? "" : "-", offset);
139 } else {
140 uint8_t I, R;
142 I = (opcode & 0x02000000) >> 25;
143 R = (opcode & 0x00400000) >> 22;
145 if (I) {
146 /* register PLD{W} [<Rn>,+/-<Rm>{, <shift>}] */
147 offset = (opcode & 0x0F80) >> 7;
148 uint8_t Rm;
149 Rm = opcode & 0xf;
151 if (offset == 0) {
152 /* No shift */
153 snprintf(instruction->text, 128,
154 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d]",
155 address, opcode, R ? "" : "W", Rn, U ? "" : "-", Rm);
157 } else {
158 uint8_t shift;
159 shift = (opcode & 0x60) >> 5;
161 if (shift == 0x0) {
162 /* LSL */
163 snprintf(instruction->text, 128,
164 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d, LSL #0x%x)",
165 address, opcode, R ? "" : "W", Rn, U ? "" : "-", Rm, offset);
166 } else if (shift == 0x1) {
167 /* LSR */
168 snprintf(instruction->text, 128,
169 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d, LSR #0x%x)",
170 address, opcode, R ? "" : "W", Rn, U ? "" : "-", Rm, offset);
171 } else if (shift == 0x2) {
172 /* ASR */
173 snprintf(instruction->text, 128,
174 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d, ASR #0x%x)",
175 address, opcode, R ? "" : "W", Rn, U ? "" : "-", Rm, offset);
176 } else if (shift == 0x3) {
177 /* ROR */
178 snprintf(instruction->text, 128,
179 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d, ROR #0x%x)",
180 address, opcode, R ? "" : "W", Rn, U ? "" : "-", Rm, offset);
183 } else {
184 /* immediate PLD{W} [<Rn>, #+/-<imm12>] */
185 offset = opcode & 0x0fff;
186 if (offset == 0) {
187 snprintf(instruction->text, 128,
188 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d]",
189 address, opcode, R ? "" : "W", Rn);
190 } else {
191 snprintf(instruction->text, 128,
192 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, #%s%d]",
193 address, opcode, R ? "" : "W", Rn, U ? "" : "-", offset);
197 return ERROR_OK;
199 /* DSB */
200 if ((opcode & 0x07f000f0) == 0x05700040) {
201 instruction->type = ARM_DSB;
203 char *opt;
204 switch (opcode & 0x0000000f) {
205 case 0xf:
206 opt = "SY";
207 break;
208 case 0xe:
209 opt = "ST";
210 break;
211 case 0xb:
212 opt = "ISH";
213 break;
214 case 0xa:
215 opt = "ISHST";
216 break;
217 case 0x7:
218 opt = "NSH";
219 break;
220 case 0x6:
221 opt = "NSHST";
222 break;
223 case 0x3:
224 opt = "OSH";
225 break;
226 case 0x2:
227 opt = "OSHST";
228 break;
229 default:
230 opt = "UNK";
233 snprintf(instruction->text,
234 128,
235 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tDSB %s",
236 address, opcode, opt);
238 return ERROR_OK;
240 /* ISB */
241 if ((opcode & 0x07f000f0) == 0x05700060) {
242 instruction->type = ARM_ISB;
244 snprintf(instruction->text,
245 128,
246 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tISB %s",
247 address, opcode,
248 ((opcode & 0x0000000f) == 0xf) ? "SY" : "UNK");
250 return ERROR_OK;
252 return evaluate_unknown(opcode, address, instruction);
255 static int evaluate_srs(uint32_t opcode,
256 uint32_t address, struct arm_instruction *instruction)
258 const char *wback = (opcode & (1 << 21)) ? "!" : "";
259 const char *mode = "";
261 switch ((opcode >> 23) & 0x3) {
262 case 0:
263 mode = "DA";
264 break;
265 case 1:
266 /* "IA" is default */
267 break;
268 case 2:
269 mode = "DB";
270 break;
271 case 3:
272 mode = "IB";
273 break;
276 switch (opcode & 0x0e500000) {
277 case 0x08400000:
278 snprintf(instruction->text, 128, "0x%8.8" PRIx32
279 "\t0x%8.8" PRIx32
280 "\tSRS%s\tSP%s, #%d",
281 address, opcode,
282 mode, wback,
283 (unsigned)(opcode & 0x1f));
284 break;
285 case 0x08100000:
286 snprintf(instruction->text, 128, "0x%8.8" PRIx32
287 "\t0x%8.8" PRIx32
288 "\tRFE%s\tr%d%s",
289 address, opcode,
290 mode,
291 (unsigned)((opcode >> 16) & 0xf), wback);
292 break;
293 default:
294 return evaluate_unknown(opcode, address, instruction);
296 return ERROR_OK;
299 static int evaluate_swi(uint32_t opcode,
300 uint32_t address, struct arm_instruction *instruction)
302 instruction->type = ARM_SWI;
304 snprintf(instruction->text, 128,
305 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSVC %#6.6" PRIx32,
306 address, opcode, (opcode & 0xffffff));
308 return ERROR_OK;
311 static int evaluate_blx_imm(uint32_t opcode,
312 uint32_t address, struct arm_instruction *instruction)
314 int offset;
315 uint32_t immediate;
316 uint32_t target_address;
318 instruction->type = ARM_BLX;
319 immediate = opcode & 0x00ffffff;
321 /* sign extend 24-bit immediate */
322 if (immediate & 0x00800000)
323 offset = 0xff000000 | immediate;
324 else
325 offset = immediate;
327 /* shift two bits left */
328 offset <<= 2;
330 /* odd/event halfword */
331 if (opcode & 0x01000000)
332 offset |= 0x2;
334 target_address = address + 8 + offset;
336 snprintf(instruction->text,
337 128,
338 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX 0x%8.8" PRIx32 "",
339 address,
340 opcode,
341 target_address);
343 instruction->info.b_bl_bx_blx.reg_operand = -1;
344 instruction->info.b_bl_bx_blx.target_address = target_address;
346 return ERROR_OK;
349 static int evaluate_b_bl(uint32_t opcode,
350 uint32_t address, struct arm_instruction *instruction)
352 uint8_t L;
353 uint32_t immediate;
354 int offset;
355 uint32_t target_address;
357 immediate = opcode & 0x00ffffff;
358 L = (opcode & 0x01000000) >> 24;
360 /* sign extend 24-bit immediate */
361 if (immediate & 0x00800000)
362 offset = 0xff000000 | immediate;
363 else
364 offset = immediate;
366 /* shift two bits left */
367 offset <<= 2;
369 target_address = address + 8 + offset;
371 if (L)
372 instruction->type = ARM_BL;
373 else
374 instruction->type = ARM_B;
376 snprintf(instruction->text,
377 128,
378 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tB%s%s 0x%8.8" PRIx32,
379 address,
380 opcode,
381 (L) ? "L" : "",
382 COND(opcode),
383 target_address);
385 instruction->info.b_bl_bx_blx.reg_operand = -1;
386 instruction->info.b_bl_bx_blx.target_address = target_address;
388 return ERROR_OK;
391 /* Coprocessor load/store and double register transfers
392 * both normal and extended instruction space (condition field b1111) */
393 static int evaluate_ldc_stc_mcrr_mrrc(uint32_t opcode,
394 uint32_t address, struct arm_instruction *instruction)
396 uint8_t cp_num = (opcode & 0xf00) >> 8;
398 /* MCRR or MRRC */
399 if (((opcode & 0x0ff00000) == 0x0c400000) || ((opcode & 0x0ff00000) == 0x0c500000)) {
400 uint8_t cp_opcode, Rd, Rn, CRm;
401 char *mnemonic;
403 cp_opcode = (opcode & 0xf0) >> 4;
404 Rd = (opcode & 0xf000) >> 12;
405 Rn = (opcode & 0xf0000) >> 16;
406 CRm = (opcode & 0xf);
408 /* MCRR */
409 if ((opcode & 0x0ff00000) == 0x0c400000) {
410 instruction->type = ARM_MCRR;
411 mnemonic = "MCRR";
412 } else if ((opcode & 0x0ff00000) == 0x0c500000) {
413 /* MRRC */
414 instruction->type = ARM_MRRC;
415 mnemonic = "MRRC";
416 } else {
417 LOG_ERROR("Unknown instruction");
418 return ERROR_FAIL;
421 snprintf(instruction->text, 128,
422 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
423 "\t%s%s%s p%i, %x, r%i, r%i, c%i",
424 address, opcode, mnemonic,
425 ((opcode & 0xf0000000) == 0xf0000000)
426 ? "2" : COND(opcode),
427 COND(opcode), cp_num, cp_opcode, Rd, Rn, CRm);
428 } else {/* LDC or STC */
429 uint8_t CRd, Rn, offset;
430 uint8_t U;
431 char *mnemonic;
432 char addressing_mode[32];
434 CRd = (opcode & 0xf000) >> 12;
435 Rn = (opcode & 0xf0000) >> 16;
436 offset = (opcode & 0xff) << 2;
438 /* load/store */
439 if (opcode & 0x00100000) {
440 instruction->type = ARM_LDC;
441 mnemonic = "LDC";
442 } else {
443 instruction->type = ARM_STC;
444 mnemonic = "STC";
447 U = (opcode & 0x00800000) >> 23;
449 /* addressing modes */
450 if ((opcode & 0x01200000) == 0x01000000)/* offset */
451 snprintf(addressing_mode, 32, "[r%i, #%s%d]",
452 Rn, U ? "" : "-", offset);
453 else if ((opcode & 0x01200000) == 0x01200000) /* pre-indexed */
454 snprintf(addressing_mode, 32, "[r%i, #%s%d]!",
455 Rn, U ? "" : "-", offset);
456 else if ((opcode & 0x01200000) == 0x00200000) /* post-indexed */
457 snprintf(addressing_mode, 32, "[r%i], #%s%d",
458 Rn, U ? "" : "-", offset);
459 else if ((opcode & 0x01200000) == 0x00000000) /* unindexed */
460 snprintf(addressing_mode, 32, "[r%i], {%d}",
461 Rn, offset >> 2);
463 snprintf(instruction->text, 128, "0x%8.8" PRIx32
464 "\t0x%8.8" PRIx32
465 "\t%s%s%s p%i, c%i, %s",
466 address, opcode, mnemonic,
467 ((opcode & 0xf0000000) == 0xf0000000)
468 ? "2" : COND(opcode),
469 (opcode & (1 << 22)) ? "L" : "",
470 cp_num, CRd, addressing_mode);
473 return ERROR_OK;
476 /* Coprocessor data processing instructions
477 * Coprocessor register transfer instructions
478 * both normal and extended instruction space (condition field b1111) */
479 static int evaluate_cdp_mcr_mrc(uint32_t opcode,
480 uint32_t address, struct arm_instruction *instruction)
482 const char *cond;
483 char *mnemonic;
484 uint8_t cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2;
486 cond = ((opcode & 0xf0000000) == 0xf0000000) ? "2" : COND(opcode);
487 cp_num = (opcode & 0xf00) >> 8;
488 CRd_Rd = (opcode & 0xf000) >> 12;
489 CRn = (opcode & 0xf0000) >> 16;
490 CRm = (opcode & 0xf);
491 opcode_2 = (opcode & 0xe0) >> 5;
493 /* CDP or MRC/MCR */
494 if (opcode & 0x00000010) { /* bit 4 set -> MRC/MCR */
495 if (opcode & 0x00100000) { /* bit 20 set -> MRC */
496 instruction->type = ARM_MRC;
497 mnemonic = "MRC";
498 } else {/* bit 20 not set -> MCR */
499 instruction->type = ARM_MCR;
500 mnemonic = "MCR";
503 opcode_1 = (opcode & 0x00e00000) >> 21;
505 snprintf(instruction->text,
506 128,
507 "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",
508 address,
509 opcode,
510 mnemonic,
511 cond,
512 cp_num,
513 opcode_1,
514 CRd_Rd,
515 CRn,
516 CRm,
517 opcode_2);
518 } else {/* bit 4 not set -> CDP */
519 instruction->type = ARM_CDP;
520 mnemonic = "CDP";
522 opcode_1 = (opcode & 0x00f00000) >> 20;
524 snprintf(instruction->text,
525 128,
526 "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",
527 address,
528 opcode,
529 mnemonic,
530 cond,
531 cp_num,
532 opcode_1,
533 CRd_Rd,
534 CRn,
535 CRm,
536 opcode_2);
539 return ERROR_OK;
542 /* Load/store instructions */
543 static int evaluate_load_store(uint32_t opcode,
544 uint32_t address, struct arm_instruction *instruction)
546 uint8_t I, P, U, B, W, L;
547 uint8_t Rn, Rd;
548 char *operation;/* "LDR" or "STR" */
549 char *suffix; /* "", "B", "T", "BT" */
550 char offset[32];
552 /* examine flags */
553 I = (opcode & 0x02000000) >> 25;
554 P = (opcode & 0x01000000) >> 24;
555 U = (opcode & 0x00800000) >> 23;
556 B = (opcode & 0x00400000) >> 22;
557 W = (opcode & 0x00200000) >> 21;
558 L = (opcode & 0x00100000) >> 20;
560 /* target register */
561 Rd = (opcode & 0xf000) >> 12;
563 /* base register */
564 Rn = (opcode & 0xf0000) >> 16;
566 instruction->info.load_store.Rd = Rd;
567 instruction->info.load_store.Rn = Rn;
568 instruction->info.load_store.U = U;
570 /* determine operation */
571 if (L)
572 operation = "LDR";
573 else
574 operation = "STR";
576 /* determine instruction type and suffix */
577 if (B) {
578 if ((P == 0) && (W == 1)) {
579 if (L)
580 instruction->type = ARM_LDRBT;
581 else
582 instruction->type = ARM_STRBT;
583 suffix = "BT";
584 } else {
585 if (L)
586 instruction->type = ARM_LDRB;
587 else
588 instruction->type = ARM_STRB;
589 suffix = "B";
591 } else {
592 if ((P == 0) && (W == 1)) {
593 if (L)
594 instruction->type = ARM_LDRT;
595 else
596 instruction->type = ARM_STRT;
597 suffix = "T";
598 } else {
599 if (L)
600 instruction->type = ARM_LDR;
601 else
602 instruction->type = ARM_STR;
603 suffix = "";
607 if (!I) { /* #+-<offset_12> */
608 uint32_t offset_12 = (opcode & 0xfff);
609 if (offset_12)
610 snprintf(offset, 32, ", #%s0x%" PRIx32 "", (U) ? "" : "-", offset_12);
611 else
612 snprintf(offset, 32, "%s", "");
614 instruction->info.load_store.offset_mode = 0;
615 instruction->info.load_store.offset.offset = offset_12;
616 } else {/* either +-<Rm> or +-<Rm>, <shift>, #<shift_imm> */
617 uint8_t shift_imm, shift;
618 uint8_t Rm;
620 shift_imm = (opcode & 0xf80) >> 7;
621 shift = (opcode & 0x60) >> 5;
622 Rm = (opcode & 0xf);
624 /* LSR encodes a shift by 32 bit as 0x0 */
625 if ((shift == 0x1) && (shift_imm == 0x0))
626 shift_imm = 0x20;
628 /* ASR encodes a shift by 32 bit as 0x0 */
629 if ((shift == 0x2) && (shift_imm == 0x0))
630 shift_imm = 0x20;
632 /* ROR by 32 bit is actually a RRX */
633 if ((shift == 0x3) && (shift_imm == 0x0))
634 shift = 0x4;
636 instruction->info.load_store.offset_mode = 1;
637 instruction->info.load_store.offset.reg.Rm = Rm;
638 instruction->info.load_store.offset.reg.shift = shift;
639 instruction->info.load_store.offset.reg.shift_imm = shift_imm;
641 if ((shift_imm == 0x0) && (shift == 0x0)) /* +-<Rm> */
642 snprintf(offset, 32, ", %sr%i", (U) ? "" : "-", Rm);
643 else { /* +-<Rm>, <Shift>, #<shift_imm> */
644 switch (shift) {
645 case 0x0: /* LSL */
646 snprintf(offset, 32, ", %sr%i, LSL #0x%x", (U) ? "" : "-", Rm, shift_imm);
647 break;
648 case 0x1: /* LSR */
649 snprintf(offset, 32, ", %sr%i, LSR #0x%x", (U) ? "" : "-", Rm, shift_imm);
650 break;
651 case 0x2: /* ASR */
652 snprintf(offset, 32, ", %sr%i, ASR #0x%x", (U) ? "" : "-", Rm, shift_imm);
653 break;
654 case 0x3: /* ROR */
655 snprintf(offset, 32, ", %sr%i, ROR #0x%x", (U) ? "" : "-", Rm, shift_imm);
656 break;
657 case 0x4: /* RRX */
658 snprintf(offset, 32, ", %sr%i, RRX", (U) ? "" : "-", Rm);
659 break;
664 if (P == 1) {
665 if (W == 0) { /* offset */
666 snprintf(instruction->text,
667 128,
668 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]",
669 address,
670 opcode,
671 operation,
672 COND(opcode),
673 suffix,
676 offset);
678 instruction->info.load_store.index_mode = 0;
679 } else {/* pre-indexed */
680 snprintf(instruction->text,
681 128,
682 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]!",
683 address,
684 opcode,
685 operation,
686 COND(opcode),
687 suffix,
690 offset);
692 instruction->info.load_store.index_mode = 1;
694 } else {/* post-indexed */
695 snprintf(instruction->text,
696 128,
697 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i]%s",
698 address,
699 opcode,
700 operation,
701 COND(opcode),
702 suffix,
705 offset);
707 instruction->info.load_store.index_mode = 2;
710 return ERROR_OK;
713 static int evaluate_extend(uint32_t opcode, uint32_t address, char *cp)
715 unsigned rm = (opcode >> 0) & 0xf;
716 unsigned rd = (opcode >> 12) & 0xf;
717 unsigned rn = (opcode >> 16) & 0xf;
718 char *type, *rot;
720 switch ((opcode >> 24) & 0x3) {
721 case 0:
722 type = "B16";
723 break;
724 case 1:
725 sprintf(cp, "UNDEFINED");
726 return ARM_UNDEFINED_INSTRUCTION;
727 case 2:
728 type = "B";
729 break;
730 default:
731 type = "H";
732 break;
735 switch ((opcode >> 10) & 0x3) {
736 case 0:
737 rot = "";
738 break;
739 case 1:
740 rot = ", ROR #8";
741 break;
742 case 2:
743 rot = ", ROR #16";
744 break;
745 default:
746 rot = ", ROR #24";
747 break;
750 if (rn == 0xf) {
751 sprintf(cp, "%cXT%s%s\tr%d, r%d%s",
752 (opcode & (1 << 22)) ? 'U' : 'S',
753 type, COND(opcode),
754 rd, rm, rot);
755 return ARM_MOV;
756 } else {
757 sprintf(cp, "%cXTA%s%s\tr%d, r%d, r%d%s",
758 (opcode & (1 << 22)) ? 'U' : 'S',
759 type, COND(opcode),
760 rd, rn, rm, rot);
761 return ARM_ADD;
765 static int evaluate_p_add_sub(uint32_t opcode, uint32_t address, char *cp)
767 char *prefix;
768 char *op;
769 int type;
771 switch ((opcode >> 20) & 0x7) {
772 case 1:
773 prefix = "S";
774 break;
775 case 2:
776 prefix = "Q";
777 break;
778 case 3:
779 prefix = "SH";
780 break;
781 case 5:
782 prefix = "U";
783 break;
784 case 6:
785 prefix = "UQ";
786 break;
787 case 7:
788 prefix = "UH";
789 break;
790 default:
791 goto undef;
794 switch ((opcode >> 5) & 0x7) {
795 case 0:
796 op = "ADD16";
797 type = ARM_ADD;
798 break;
799 case 1:
800 op = "ADDSUBX";
801 type = ARM_ADD;
802 break;
803 case 2:
804 op = "SUBADDX";
805 type = ARM_SUB;
806 break;
807 case 3:
808 op = "SUB16";
809 type = ARM_SUB;
810 break;
811 case 4:
812 op = "ADD8";
813 type = ARM_ADD;
814 break;
815 case 7:
816 op = "SUB8";
817 type = ARM_SUB;
818 break;
819 default:
820 goto undef;
823 sprintf(cp, "%s%s%s\tr%d, r%d, r%d", prefix, op, COND(opcode),
824 (int) (opcode >> 12) & 0xf,
825 (int) (opcode >> 16) & 0xf,
826 (int) (opcode >> 0) & 0xf);
827 return type;
829 undef:
830 /* these opcodes might be used someday */
831 sprintf(cp, "UNDEFINED");
832 return ARM_UNDEFINED_INSTRUCTION;
835 /* ARMv6 and later support "media" instructions (includes SIMD) */
836 static int evaluate_media(uint32_t opcode, uint32_t address,
837 struct arm_instruction *instruction)
839 char *cp = instruction->text;
840 char *mnemonic = NULL;
842 sprintf(cp,
843 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t",
844 address, opcode);
845 cp = strchr(cp, 0);
847 /* parallel add/subtract */
848 if ((opcode & 0x01800000) == 0x00000000) {
849 instruction->type = evaluate_p_add_sub(opcode, address, cp);
850 return ERROR_OK;
853 /* halfword pack */
854 if ((opcode & 0x01f00020) == 0x00800000) {
855 char *type, *shift;
856 unsigned imm = (unsigned) (opcode >> 7) & 0x1f;
858 if (opcode & (1 << 6)) {
859 type = "TB";
860 shift = "ASR";
861 if (imm == 0)
862 imm = 32;
863 } else {
864 type = "BT";
865 shift = "LSL";
867 sprintf(cp, "PKH%s%s\tr%d, r%d, r%d, %s #%d",
868 type, COND(opcode),
869 (int) (opcode >> 12) & 0xf,
870 (int) (opcode >> 16) & 0xf,
871 (int) (opcode >> 0) & 0xf,
872 shift, imm);
873 return ERROR_OK;
876 /* word saturate */
877 if ((opcode & 0x01a00020) == 0x00a00000) {
878 char *shift;
879 unsigned imm = (unsigned) (opcode >> 7) & 0x1f;
881 if (opcode & (1 << 6)) {
882 shift = "ASR";
883 if (imm == 0)
884 imm = 32;
885 } else
886 shift = "LSL";
888 sprintf(cp, "%cSAT%s\tr%d, #%d, r%d, %s #%d",
889 (opcode & (1 << 22)) ? 'U' : 'S',
890 COND(opcode),
891 (int) (opcode >> 12) & 0xf,
892 (int) (opcode >> 16) & 0x1f,
893 (int) (opcode >> 0) & 0xf,
894 shift, imm);
895 return ERROR_OK;
898 /* sign extension */
899 if ((opcode & 0x018000f0) == 0x00800070) {
900 instruction->type = evaluate_extend(opcode, address, cp);
901 return ERROR_OK;
904 /* multiplies */
905 if ((opcode & 0x01f00080) == 0x01000000) {
906 unsigned rn = (opcode >> 12) & 0xf;
908 if (rn != 0xf)
909 sprintf(cp, "SML%cD%s%s\tr%d, r%d, r%d, r%d",
910 (opcode & (1 << 6)) ? 'S' : 'A',
911 (opcode & (1 << 5)) ? "X" : "",
912 COND(opcode),
913 (int) (opcode >> 16) & 0xf,
914 (int) (opcode >> 0) & 0xf,
915 (int) (opcode >> 8) & 0xf,
916 rn);
917 else
918 sprintf(cp, "SMU%cD%s%s\tr%d, r%d, r%d",
919 (opcode & (1 << 6)) ? 'S' : 'A',
920 (opcode & (1 << 5)) ? "X" : "",
921 COND(opcode),
922 (int) (opcode >> 16) & 0xf,
923 (int) (opcode >> 0) & 0xf,
924 (int) (opcode >> 8) & 0xf);
925 return ERROR_OK;
927 if ((opcode & 0x01f00000) == 0x01400000) {
928 sprintf(cp, "SML%cLD%s%s\tr%d, r%d, r%d, r%d",
929 (opcode & (1 << 6)) ? 'S' : 'A',
930 (opcode & (1 << 5)) ? "X" : "",
931 COND(opcode),
932 (int) (opcode >> 12) & 0xf,
933 (int) (opcode >> 16) & 0xf,
934 (int) (opcode >> 0) & 0xf,
935 (int) (opcode >> 8) & 0xf);
936 return ERROR_OK;
938 if ((opcode & 0x01f00000) == 0x01500000) {
939 unsigned rn = (opcode >> 12) & 0xf;
941 switch (opcode & 0xc0) {
942 case 3:
943 if (rn == 0xf)
944 goto undef;
945 /* FALL THROUGH */
946 case 0:
947 break;
948 default:
949 goto undef;
952 if (rn != 0xf)
953 sprintf(cp, "SMML%c%s%s\tr%d, r%d, r%d, r%d",
954 (opcode & (1 << 6)) ? 'S' : 'A',
955 (opcode & (1 << 5)) ? "R" : "",
956 COND(opcode),
957 (int) (opcode >> 16) & 0xf,
958 (int) (opcode >> 0) & 0xf,
959 (int) (opcode >> 8) & 0xf,
960 rn);
961 else
962 sprintf(cp, "SMMUL%s%s\tr%d, r%d, r%d",
963 (opcode & (1 << 5)) ? "R" : "",
964 COND(opcode),
965 (int) (opcode >> 16) & 0xf,
966 (int) (opcode >> 0) & 0xf,
967 (int) (opcode >> 8) & 0xf);
968 return ERROR_OK;
971 /* simple matches against the remaining decode bits */
972 switch (opcode & 0x01f000f0) {
973 case 0x00a00030:
974 case 0x00e00030:
975 /* parallel halfword saturate */
976 sprintf(cp, "%cSAT16%s\tr%d, #%d, r%d",
977 (opcode & (1 << 22)) ? 'U' : 'S',
978 COND(opcode),
979 (int) (opcode >> 12) & 0xf,
980 (int) (opcode >> 16) & 0xf,
981 (int) (opcode >> 0) & 0xf);
982 return ERROR_OK;
983 case 0x00b00030:
984 mnemonic = "REV";
985 break;
986 case 0x00b000b0:
987 mnemonic = "REV16";
988 break;
989 case 0x00f000b0:
990 mnemonic = "REVSH";
991 break;
992 case 0x008000b0:
993 /* select bytes */
994 sprintf(cp, "SEL%s\tr%d, r%d, r%d", COND(opcode),
995 (int) (opcode >> 12) & 0xf,
996 (int) (opcode >> 16) & 0xf,
997 (int) (opcode >> 0) & 0xf);
998 return ERROR_OK;
999 case 0x01800010:
1000 /* unsigned sum of absolute differences */
1001 if (((opcode >> 12) & 0xf) == 0xf)
1002 sprintf(cp, "USAD8%s\tr%d, r%d, r%d", COND(opcode),
1003 (int) (opcode >> 16) & 0xf,
1004 (int) (opcode >> 0) & 0xf,
1005 (int) (opcode >> 8) & 0xf);
1006 else
1007 sprintf(cp, "USADA8%s\tr%d, r%d, r%d, r%d", COND(opcode),
1008 (int) (opcode >> 16) & 0xf,
1009 (int) (opcode >> 0) & 0xf,
1010 (int) (opcode >> 8) & 0xf,
1011 (int) (opcode >> 12) & 0xf);
1012 return ERROR_OK;
1014 if (mnemonic) {
1015 unsigned rm = (opcode >> 0) & 0xf;
1016 unsigned rd = (opcode >> 12) & 0xf;
1018 sprintf(cp, "%s%s\tr%d, r%d", mnemonic, COND(opcode), rm, rd);
1019 return ERROR_OK;
1022 undef:
1023 /* these opcodes might be used someday */
1024 sprintf(cp, "UNDEFINED");
1025 return ERROR_OK;
1028 /* Miscellaneous load/store instructions */
1029 static int evaluate_misc_load_store(uint32_t opcode,
1030 uint32_t address, struct arm_instruction *instruction)
1032 uint8_t P, U, I, W, L, S, H;
1033 uint8_t Rn, Rd;
1034 char *operation;/* "LDR" or "STR" */
1035 char *suffix; /* "H", "SB", "SH", "D" */
1036 char offset[32];
1038 /* examine flags */
1039 P = (opcode & 0x01000000) >> 24;
1040 U = (opcode & 0x00800000) >> 23;
1041 I = (opcode & 0x00400000) >> 22;
1042 W = (opcode & 0x00200000) >> 21;
1043 L = (opcode & 0x00100000) >> 20;
1044 S = (opcode & 0x00000040) >> 6;
1045 H = (opcode & 0x00000020) >> 5;
1047 /* target register */
1048 Rd = (opcode & 0xf000) >> 12;
1050 /* base register */
1051 Rn = (opcode & 0xf0000) >> 16;
1053 instruction->info.load_store.Rd = Rd;
1054 instruction->info.load_store.Rn = Rn;
1055 instruction->info.load_store.U = U;
1057 /* determine instruction type and suffix */
1058 if (S) {/* signed */
1059 if (L) {/* load */
1060 if (H) {
1061 operation = "LDR";
1062 instruction->type = ARM_LDRSH;
1063 suffix = "SH";
1064 } else {
1065 operation = "LDR";
1066 instruction->type = ARM_LDRSB;
1067 suffix = "SB";
1069 } else {/* there are no signed stores, so this is used to encode double-register
1070 *load/stores */
1071 suffix = "D";
1072 if (H) {
1073 operation = "STR";
1074 instruction->type = ARM_STRD;
1075 } else {
1076 operation = "LDR";
1077 instruction->type = ARM_LDRD;
1080 } else {/* unsigned */
1081 suffix = "H";
1082 if (L) {/* load */
1083 operation = "LDR";
1084 instruction->type = ARM_LDRH;
1085 } else {/* store */
1086 operation = "STR";
1087 instruction->type = ARM_STRH;
1091 if (I) {/* Immediate offset/index (#+-<offset_8>)*/
1092 uint32_t offset_8 = ((opcode & 0xf00) >> 4) | (opcode & 0xf);
1093 snprintf(offset, 32, "#%s0x%" PRIx32 "", (U) ? "" : "-", offset_8);
1095 instruction->info.load_store.offset_mode = 0;
1096 instruction->info.load_store.offset.offset = offset_8;
1097 } else {/* Register offset/index (+-<Rm>) */
1098 uint8_t Rm;
1099 Rm = (opcode & 0xf);
1100 snprintf(offset, 32, "%sr%i", (U) ? "" : "-", Rm);
1102 instruction->info.load_store.offset_mode = 1;
1103 instruction->info.load_store.offset.reg.Rm = Rm;
1104 instruction->info.load_store.offset.reg.shift = 0x0;
1105 instruction->info.load_store.offset.reg.shift_imm = 0x0;
1108 if (P == 1) {
1109 if (W == 0) { /* offset */
1110 snprintf(instruction->text,
1111 128,
1112 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]",
1113 address,
1114 opcode,
1115 operation,
1116 COND(opcode),
1117 suffix,
1120 offset);
1122 instruction->info.load_store.index_mode = 0;
1123 } else {/* pre-indexed */
1124 snprintf(instruction->text,
1125 128,
1126 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]!",
1127 address,
1128 opcode,
1129 operation,
1130 COND(opcode),
1131 suffix,
1134 offset);
1136 instruction->info.load_store.index_mode = 1;
1138 } else {/* post-indexed */
1139 snprintf(instruction->text,
1140 128,
1141 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i], %s",
1142 address,
1143 opcode,
1144 operation,
1145 COND(opcode),
1146 suffix,
1149 offset);
1151 instruction->info.load_store.index_mode = 2;
1154 return ERROR_OK;
1157 /* Load/store multiples instructions */
1158 static int evaluate_ldm_stm(uint32_t opcode,
1159 uint32_t address, struct arm_instruction *instruction)
1161 uint8_t P, U, S, W, L, Rn;
1162 uint32_t register_list;
1163 char *addressing_mode;
1164 char *mnemonic;
1165 char reg_list[69];
1166 char *reg_list_p;
1167 int i;
1168 int first_reg = 1;
1170 P = (opcode & 0x01000000) >> 24;
1171 U = (opcode & 0x00800000) >> 23;
1172 S = (opcode & 0x00400000) >> 22;
1173 W = (opcode & 0x00200000) >> 21;
1174 L = (opcode & 0x00100000) >> 20;
1175 register_list = (opcode & 0xffff);
1176 Rn = (opcode & 0xf0000) >> 16;
1178 instruction->info.load_store_multiple.Rn = Rn;
1179 instruction->info.load_store_multiple.register_list = register_list;
1180 instruction->info.load_store_multiple.S = S;
1181 instruction->info.load_store_multiple.W = W;
1183 if (L) {
1184 instruction->type = ARM_LDM;
1185 mnemonic = "LDM";
1186 } else {
1187 instruction->type = ARM_STM;
1188 mnemonic = "STM";
1191 if (P) {
1192 if (U) {
1193 instruction->info.load_store_multiple.addressing_mode = 1;
1194 addressing_mode = "IB";
1195 } else {
1196 instruction->info.load_store_multiple.addressing_mode = 3;
1197 addressing_mode = "DB";
1199 } else {
1200 if (U) {
1201 instruction->info.load_store_multiple.addressing_mode = 0;
1202 /* "IA" is the default in UAL syntax */
1203 addressing_mode = "";
1204 } else {
1205 instruction->info.load_store_multiple.addressing_mode = 2;
1206 addressing_mode = "DA";
1210 reg_list_p = reg_list;
1211 for (i = 0; i <= 15; i++) {
1212 if ((register_list >> i) & 1) {
1213 if (first_reg) {
1214 first_reg = 0;
1215 reg_list_p += snprintf(reg_list_p,
1216 (reg_list + 69 - reg_list_p),
1217 "r%i",
1219 } else
1220 reg_list_p += snprintf(reg_list_p,
1221 (reg_list + 69 - reg_list_p),
1222 ", r%i",
1227 snprintf(instruction->text, 128,
1228 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
1229 "\t%s%s%s r%i%s, {%s}%s",
1230 address, opcode,
1231 mnemonic, addressing_mode, COND(opcode),
1232 Rn, (W) ? "!" : "", reg_list, (S) ? "^" : "");
1234 return ERROR_OK;
1237 /* Multiplies, extra load/stores */
1238 static int evaluate_mul_and_extra_ld_st(uint32_t opcode,
1239 uint32_t address, struct arm_instruction *instruction)
1241 /* Multiply (accumulate) (long) and Swap/swap byte */
1242 if ((opcode & 0x000000f0) == 0x00000090) {
1243 /* Multiply (accumulate) */
1244 if ((opcode & 0x0f800000) == 0x00000000) {
1245 uint8_t Rm, Rs, Rn, Rd, S;
1246 Rm = opcode & 0xf;
1247 Rs = (opcode & 0xf00) >> 8;
1248 Rn = (opcode & 0xf000) >> 12;
1249 Rd = (opcode & 0xf0000) >> 16;
1250 S = (opcode & 0x00100000) >> 20;
1252 /* examine A bit (accumulate) */
1253 if (opcode & 0x00200000) {
1254 instruction->type = ARM_MLA;
1255 snprintf(instruction->text,
1256 128,
1257 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMLA%s%s r%i, r%i, r%i, r%i",
1258 address,
1259 opcode,
1260 COND(opcode),
1261 (S) ? "S" : "",
1265 Rn);
1266 } else {
1267 instruction->type = ARM_MUL;
1268 snprintf(instruction->text,
1269 128,
1270 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMUL%s%s r%i, r%i, r%i",
1271 address,
1272 opcode,
1273 COND(opcode),
1274 (S) ? "S" : "",
1277 Rs);
1280 return ERROR_OK;
1283 /* Multiply (accumulate) long */
1284 if ((opcode & 0x0f800000) == 0x00800000) {
1285 char *mnemonic = NULL;
1286 uint8_t Rm, Rs, RdHi, RdLow, S;
1287 Rm = opcode & 0xf;
1288 Rs = (opcode & 0xf00) >> 8;
1289 RdHi = (opcode & 0xf000) >> 12;
1290 RdLow = (opcode & 0xf0000) >> 16;
1291 S = (opcode & 0x00100000) >> 20;
1293 switch ((opcode & 0x00600000) >> 21) {
1294 case 0x0:
1295 instruction->type = ARM_UMULL;
1296 mnemonic = "UMULL";
1297 break;
1298 case 0x1:
1299 instruction->type = ARM_UMLAL;
1300 mnemonic = "UMLAL";
1301 break;
1302 case 0x2:
1303 instruction->type = ARM_SMULL;
1304 mnemonic = "SMULL";
1305 break;
1306 case 0x3:
1307 instruction->type = ARM_SMLAL;
1308 mnemonic = "SMLAL";
1309 break;
1312 snprintf(instruction->text,
1313 128,
1314 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, r%i, r%i",
1315 address,
1316 opcode,
1317 mnemonic,
1318 COND(opcode),
1319 (S) ? "S" : "",
1320 RdLow,
1321 RdHi,
1323 Rs);
1325 return ERROR_OK;
1328 /* Swap/swap byte */
1329 if ((opcode & 0x0f800000) == 0x01000000) {
1330 uint8_t Rm, Rd, Rn;
1331 Rm = opcode & 0xf;
1332 Rd = (opcode & 0xf000) >> 12;
1333 Rn = (opcode & 0xf0000) >> 16;
1335 /* examine B flag */
1336 instruction->type = (opcode & 0x00400000) ? ARM_SWPB : ARM_SWP;
1338 snprintf(instruction->text,
1339 128,
1340 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, [r%i]",
1341 address,
1342 opcode,
1343 (opcode & 0x00400000) ? "SWPB" : "SWP",
1344 COND(opcode),
1347 Rn);
1348 return ERROR_OK;
1353 return evaluate_misc_load_store(opcode, address, instruction);
1356 static int evaluate_mrs_msr(uint32_t opcode,
1357 uint32_t address, struct arm_instruction *instruction)
1359 int R = (opcode & 0x00400000) >> 22;
1360 char *PSR = (R) ? "SPSR" : "CPSR";
1362 /* Move register to status register (MSR) */
1363 if (opcode & 0x00200000) {
1364 instruction->type = ARM_MSR;
1366 /* immediate variant */
1367 if (opcode & 0x02000000) {
1368 uint8_t immediate = (opcode & 0xff);
1369 uint8_t rotate = (opcode & 0xf00);
1371 snprintf(instruction->text,
1372 128,
1373 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, 0x%8.8" PRIx32,
1374 address,
1375 opcode,
1376 COND(opcode),
1377 PSR,
1378 (opcode & 0x10000) ? "c" : "",
1379 (opcode & 0x20000) ? "x" : "",
1380 (opcode & 0x40000) ? "s" : "",
1381 (opcode & 0x80000) ? "f" : "",
1382 ror(immediate, (rotate * 2))
1384 } else {/* register variant */
1385 uint8_t Rm = opcode & 0xf;
1386 snprintf(instruction->text,
1387 128,
1388 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, r%i",
1389 address,
1390 opcode,
1391 COND(opcode),
1392 PSR,
1393 (opcode & 0x10000) ? "c" : "",
1394 (opcode & 0x20000) ? "x" : "",
1395 (opcode & 0x40000) ? "s" : "",
1396 (opcode & 0x80000) ? "f" : "",
1401 } else {/* Move status register to register (MRS) */
1402 uint8_t Rd;
1404 instruction->type = ARM_MRS;
1405 Rd = (opcode & 0x0000f000) >> 12;
1407 snprintf(instruction->text,
1408 128,
1409 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMRS%s r%i, %s",
1410 address,
1411 opcode,
1412 COND(opcode),
1414 PSR);
1417 return ERROR_OK;
1420 /* Miscellaneous instructions */
1421 static int evaluate_misc_instr(uint32_t opcode,
1422 uint32_t address, struct arm_instruction *instruction)
1424 /* MRS/MSR */
1425 if ((opcode & 0x000000f0) == 0x00000000)
1426 evaluate_mrs_msr(opcode, address, instruction);
1428 /* BX */
1429 if ((opcode & 0x006000f0) == 0x00200010) {
1430 uint8_t Rm;
1431 instruction->type = ARM_BX;
1432 Rm = opcode & 0xf;
1434 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBX%s r%i",
1435 address, opcode, COND(opcode), Rm);
1437 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1438 instruction->info.b_bl_bx_blx.target_address = -1;
1441 /* BXJ - "Jazelle" support (ARMv5-J) */
1442 if ((opcode & 0x006000f0) == 0x00200020) {
1443 uint8_t Rm;
1444 instruction->type = ARM_BX;
1445 Rm = opcode & 0xf;
1447 snprintf(instruction->text, 128,
1448 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBXJ%s r%i",
1449 address, opcode, COND(opcode), Rm);
1451 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1452 instruction->info.b_bl_bx_blx.target_address = -1;
1455 /* CLZ */
1456 if ((opcode & 0x006000f0) == 0x00600010) {
1457 uint8_t Rm, Rd;
1458 instruction->type = ARM_CLZ;
1459 Rm = opcode & 0xf;
1460 Rd = (opcode & 0xf000) >> 12;
1462 snprintf(instruction->text,
1463 128,
1464 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCLZ%s r%i, r%i",
1465 address,
1466 opcode,
1467 COND(opcode),
1469 Rm);
1472 /* BLX(2) */
1473 if ((opcode & 0x006000f0) == 0x00200030) {
1474 uint8_t Rm;
1475 instruction->type = ARM_BLX;
1476 Rm = opcode & 0xf;
1478 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX%s r%i",
1479 address, opcode, COND(opcode), Rm);
1481 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1482 instruction->info.b_bl_bx_blx.target_address = -1;
1485 /* Enhanced DSP add/subtracts */
1486 if ((opcode & 0x0000000f0) == 0x00000050) {
1487 uint8_t Rm, Rd, Rn;
1488 char *mnemonic = NULL;
1489 Rm = opcode & 0xf;
1490 Rd = (opcode & 0xf000) >> 12;
1491 Rn = (opcode & 0xf0000) >> 16;
1493 switch ((opcode & 0x00600000) >> 21) {
1494 case 0x0:
1495 instruction->type = ARM_QADD;
1496 mnemonic = "QADD";
1497 break;
1498 case 0x1:
1499 instruction->type = ARM_QSUB;
1500 mnemonic = "QSUB";
1501 break;
1502 case 0x2:
1503 instruction->type = ARM_QDADD;
1504 mnemonic = "QDADD";
1505 break;
1506 case 0x3:
1507 instruction->type = ARM_QDSUB;
1508 mnemonic = "QDSUB";
1509 break;
1512 snprintf(instruction->text,
1513 128,
1514 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, r%i",
1515 address,
1516 opcode,
1517 mnemonic,
1518 COND(opcode),
1521 Rn);
1524 /* exception return */
1525 if ((opcode & 0x0000000f0) == 0x00000060) {
1526 if (((opcode & 0x600000) >> 21) == 3)
1527 instruction->type = ARM_ERET;
1528 snprintf(instruction->text,
1529 128,
1530 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tERET",
1531 address,
1532 opcode);
1535 /* exception generate instructions */
1536 if ((opcode & 0x0000000f0) == 0x00000070) {
1537 uint32_t immediate = 0;
1538 char *mnemonic = NULL;
1540 switch ((opcode & 0x600000) >> 21) {
1541 case 0x1:
1542 instruction->type = ARM_BKPT;
1543 mnemonic = "BRKT";
1544 immediate = ((opcode & 0x000fff00) >> 4) | (opcode & 0xf);
1545 break;
1546 case 0x2:
1547 instruction->type = ARM_HVC;
1548 mnemonic = "HVC";
1549 immediate = ((opcode & 0x000fff00) >> 4) | (opcode & 0xf);
1550 break;
1551 case 0x3:
1552 instruction->type = ARM_SMC;
1553 mnemonic = "SMC";
1554 immediate = (opcode & 0xf);
1555 break;
1558 snprintf(instruction->text,
1559 128,
1560 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s 0x%4.4" PRIx32 "",
1561 address,
1562 opcode,
1563 mnemonic,
1564 immediate);
1567 /* Enhanced DSP multiplies */
1568 if ((opcode & 0x000000090) == 0x00000080) {
1569 int x = (opcode & 0x20) >> 5;
1570 int y = (opcode & 0x40) >> 6;
1572 /* SMLA < x><y> */
1573 if ((opcode & 0x00600000) == 0x00000000) {
1574 uint8_t Rd, Rm, Rs, Rn;
1575 instruction->type = ARM_SMLAxy;
1576 Rd = (opcode & 0xf0000) >> 16;
1577 Rm = (opcode & 0xf);
1578 Rs = (opcode & 0xf00) >> 8;
1579 Rn = (opcode & 0xf000) >> 12;
1581 snprintf(instruction->text,
1582 128,
1583 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
1584 address,
1585 opcode,
1586 (x) ? "T" : "B",
1587 (y) ? "T" : "B",
1588 COND(opcode),
1592 Rn);
1595 /* SMLAL < x><y> */
1596 if ((opcode & 0x00600000) == 0x00400000) {
1597 uint8_t RdLow, RdHi, Rm, Rs;
1598 instruction->type = ARM_SMLAxy;
1599 RdHi = (opcode & 0xf0000) >> 16;
1600 RdLow = (opcode & 0xf000) >> 12;
1601 Rm = (opcode & 0xf);
1602 Rs = (opcode & 0xf00) >> 8;
1604 snprintf(instruction->text,
1605 128,
1606 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
1607 address,
1608 opcode,
1609 (x) ? "T" : "B",
1610 (y) ? "T" : "B",
1611 COND(opcode),
1612 RdLow,
1613 RdHi,
1615 Rs);
1618 /* SMLAW < y> */
1619 if (((opcode & 0x00600000) == 0x00200000) && (x == 0)) {
1620 uint8_t Rd, Rm, Rs, Rn;
1621 instruction->type = ARM_SMLAWy;
1622 Rd = (opcode & 0xf0000) >> 16;
1623 Rm = (opcode & 0xf);
1624 Rs = (opcode & 0xf00) >> 8;
1625 Rn = (opcode & 0xf000) >> 12;
1627 snprintf(instruction->text,
1628 128,
1629 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLAW%s%s r%i, r%i, r%i, r%i",
1630 address,
1631 opcode,
1632 (y) ? "T" : "B",
1633 COND(opcode),
1637 Rn);
1640 /* SMUL < x><y> */
1641 if ((opcode & 0x00600000) == 0x00600000) {
1642 uint8_t Rd, Rm, Rs;
1643 instruction->type = ARM_SMULxy;
1644 Rd = (opcode & 0xf0000) >> 16;
1645 Rm = (opcode & 0xf);
1646 Rs = (opcode & 0xf00) >> 8;
1648 snprintf(instruction->text,
1649 128,
1650 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s%s r%i, r%i, r%i",
1651 address,
1652 opcode,
1653 (x) ? "T" : "B",
1654 (y) ? "T" : "B",
1655 COND(opcode),
1658 Rs);
1661 /* SMULW < y> */
1662 if (((opcode & 0x00600000) == 0x00200000) && (x == 1)) {
1663 uint8_t Rd, Rm, Rs;
1664 instruction->type = ARM_SMULWy;
1665 Rd = (opcode & 0xf0000) >> 16;
1666 Rm = (opcode & 0xf);
1667 Rs = (opcode & 0xf00) >> 8;
1669 snprintf(instruction->text,
1670 128,
1671 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s r%i, r%i, r%i",
1672 address,
1673 opcode,
1674 (y) ? "T" : "B",
1675 COND(opcode),
1678 Rs);
1682 return ERROR_OK;
1685 static int evaluate_mov_imm(uint32_t opcode,
1686 uint32_t address, struct arm_instruction *instruction)
1688 uint16_t immediate;
1689 uint8_t Rd;
1690 bool T;
1692 Rd = (opcode & 0xf000) >> 12;
1693 T = opcode & 0x00400000;
1694 immediate = (opcode & 0xf0000) >> 4 | (opcode & 0xfff);
1696 instruction->type = ARM_MOV;
1697 instruction->info.data_proc.Rd = Rd;
1699 snprintf(instruction->text,
1700 128,
1701 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMOV%s%s r%i, #0x%" PRIx16,
1702 address,
1703 opcode,
1704 T ? "T" : "W",
1705 COND(opcode),
1707 immediate);
1709 return ERROR_OK;
1712 static int evaluate_data_proc(uint32_t opcode,
1713 uint32_t address, struct arm_instruction *instruction)
1715 uint8_t I, op, S, Rn, Rd;
1716 char *mnemonic = NULL;
1717 char shifter_operand[32];
1719 I = (opcode & 0x02000000) >> 25;
1720 op = (opcode & 0x01e00000) >> 21;
1721 S = (opcode & 0x00100000) >> 20;
1723 Rd = (opcode & 0xf000) >> 12;
1724 Rn = (opcode & 0xf0000) >> 16;
1726 instruction->info.data_proc.Rd = Rd;
1727 instruction->info.data_proc.Rn = Rn;
1728 instruction->info.data_proc.S = S;
1730 switch (op) {
1731 case 0x0:
1732 instruction->type = ARM_AND;
1733 mnemonic = "AND";
1734 break;
1735 case 0x1:
1736 instruction->type = ARM_EOR;
1737 mnemonic = "EOR";
1738 break;
1739 case 0x2:
1740 instruction->type = ARM_SUB;
1741 mnemonic = "SUB";
1742 break;
1743 case 0x3:
1744 instruction->type = ARM_RSB;
1745 mnemonic = "RSB";
1746 break;
1747 case 0x4:
1748 instruction->type = ARM_ADD;
1749 mnemonic = "ADD";
1750 break;
1751 case 0x5:
1752 instruction->type = ARM_ADC;
1753 mnemonic = "ADC";
1754 break;
1755 case 0x6:
1756 instruction->type = ARM_SBC;
1757 mnemonic = "SBC";
1758 break;
1759 case 0x7:
1760 instruction->type = ARM_RSC;
1761 mnemonic = "RSC";
1762 break;
1763 case 0x8:
1764 instruction->type = ARM_TST;
1765 mnemonic = "TST";
1766 break;
1767 case 0x9:
1768 instruction->type = ARM_TEQ;
1769 mnemonic = "TEQ";
1770 break;
1771 case 0xa:
1772 instruction->type = ARM_CMP;
1773 mnemonic = "CMP";
1774 break;
1775 case 0xb:
1776 instruction->type = ARM_CMN;
1777 mnemonic = "CMN";
1778 break;
1779 case 0xc:
1780 instruction->type = ARM_ORR;
1781 mnemonic = "ORR";
1782 break;
1783 case 0xd:
1784 instruction->type = ARM_MOV;
1785 mnemonic = "MOV";
1786 break;
1787 case 0xe:
1788 instruction->type = ARM_BIC;
1789 mnemonic = "BIC";
1790 break;
1791 case 0xf:
1792 instruction->type = ARM_MVN;
1793 mnemonic = "MVN";
1794 break;
1797 if (I) {/* immediate shifter operand (#<immediate>)*/
1798 uint8_t immed_8 = opcode & 0xff;
1799 uint8_t rotate_imm = (opcode & 0xf00) >> 8;
1800 uint32_t immediate;
1802 immediate = ror(immed_8, rotate_imm * 2);
1804 snprintf(shifter_operand, 32, "#0x%" PRIx32 "", immediate);
1806 instruction->info.data_proc.variant = 0;
1807 instruction->info.data_proc.shifter_operand.immediate.immediate = immediate;
1808 } else {/* register-based shifter operand */
1809 uint8_t shift, Rm;
1810 shift = (opcode & 0x60) >> 5;
1811 Rm = (opcode & 0xf);
1813 if ((opcode & 0x10) != 0x10) { /* Immediate shifts ("<Rm>" or "<Rm>, <shift>
1814 *#<shift_immediate>") */
1815 uint8_t shift_imm;
1816 shift_imm = (opcode & 0xf80) >> 7;
1818 instruction->info.data_proc.variant = 1;
1819 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1820 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm =
1821 shift_imm;
1822 instruction->info.data_proc.shifter_operand.immediate_shift.shift = shift;
1824 /* LSR encodes a shift by 32 bit as 0x0 */
1825 if ((shift == 0x1) && (shift_imm == 0x0))
1826 shift_imm = 0x20;
1828 /* ASR encodes a shift by 32 bit as 0x0 */
1829 if ((shift == 0x2) && (shift_imm == 0x0))
1830 shift_imm = 0x20;
1832 /* ROR by 32 bit is actually a RRX */
1833 if ((shift == 0x3) && (shift_imm == 0x0))
1834 shift = 0x4;
1836 if ((shift_imm == 0x0) && (shift == 0x0))
1837 snprintf(shifter_operand, 32, "r%i", Rm);
1838 else {
1839 if (shift == 0x0) /* LSL */
1840 snprintf(shifter_operand,
1842 "r%i, LSL #0x%x",
1844 shift_imm);
1845 else if (shift == 0x1) /* LSR */
1846 snprintf(shifter_operand,
1848 "r%i, LSR #0x%x",
1850 shift_imm);
1851 else if (shift == 0x2) /* ASR */
1852 snprintf(shifter_operand,
1854 "r%i, ASR #0x%x",
1856 shift_imm);
1857 else if (shift == 0x3) /* ROR */
1858 snprintf(shifter_operand,
1860 "r%i, ROR #0x%x",
1862 shift_imm);
1863 else if (shift == 0x4) /* RRX */
1864 snprintf(shifter_operand, 32, "r%i, RRX", Rm);
1866 } else {/* Register shifts ("<Rm>, <shift> <Rs>") */
1867 uint8_t Rs = (opcode & 0xf00) >> 8;
1869 instruction->info.data_proc.variant = 2;
1870 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rm;
1871 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rs;
1872 instruction->info.data_proc.shifter_operand.register_shift.shift = shift;
1874 if (shift == 0x0) /* LSL */
1875 snprintf(shifter_operand, 32, "r%i, LSL r%i", Rm, Rs);
1876 else if (shift == 0x1) /* LSR */
1877 snprintf(shifter_operand, 32, "r%i, LSR r%i", Rm, Rs);
1878 else if (shift == 0x2) /* ASR */
1879 snprintf(shifter_operand, 32, "r%i, ASR r%i", Rm, Rs);
1880 else if (shift == 0x3) /* ROR */
1881 snprintf(shifter_operand, 32, "r%i, ROR r%i", Rm, Rs);
1885 if ((op < 0x8) || (op == 0xc) || (op == 0xe)) { /* <opcode3>{<cond>}{S} <Rd>, <Rn>,
1886 *<shifter_operand> */
1887 snprintf(instruction->text,
1888 128,
1889 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, %s",
1890 address,
1891 opcode,
1892 mnemonic,
1893 COND(opcode),
1894 (S) ? "S" : "",
1897 shifter_operand);
1898 } else if ((op == 0xd) || (op == 0xf)) { /* <opcode1>{<cond>}{S} <Rd>,
1899 *<shifter_operand> */
1900 if (opcode == 0xe1a00000) /* print MOV r0,r0 as NOP */
1901 snprintf(instruction->text,
1902 128,
1903 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tNOP",
1904 address,
1905 opcode);
1906 else
1907 snprintf(instruction->text,
1908 128,
1909 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, %s",
1910 address,
1911 opcode,
1912 mnemonic,
1913 COND(opcode),
1914 (S) ? "S" : "",
1916 shifter_operand);
1917 } else {/* <opcode2>{<cond>} <Rn>, <shifter_operand> */
1918 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, %s",
1919 address, opcode, mnemonic, COND(opcode),
1920 Rn, shifter_operand);
1923 return ERROR_OK;
1926 int arm_evaluate_opcode(uint32_t opcode, uint32_t address,
1927 struct arm_instruction *instruction)
1929 /* clear fields, to avoid confusion */
1930 memset(instruction, 0, sizeof(struct arm_instruction));
1931 instruction->opcode = opcode;
1932 instruction->instruction_size = 4;
1934 /* catch opcodes with condition field [31:28] = b1111 */
1935 if ((opcode & 0xf0000000) == 0xf0000000) {
1936 /* Undefined instruction (or ARMv5E cache preload PLD) */
1937 if ((opcode & 0x08000000) == 0x00000000)
1938 return evaluate_pld(opcode, address, instruction);
1940 /* Undefined instruction (or ARMv6+ SRS/RFE) */
1941 if ((opcode & 0x0e000000) == 0x08000000)
1942 return evaluate_srs(opcode, address, instruction);
1944 /* Branch and branch with link and change to Thumb */
1945 if ((opcode & 0x0e000000) == 0x0a000000)
1946 return evaluate_blx_imm(opcode, address, instruction);
1948 /* Extended coprocessor opcode space (ARMv5 and higher)
1949 * Coprocessor load/store and double register transfers */
1950 if ((opcode & 0x0e000000) == 0x0c000000)
1951 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1953 /* Coprocessor data processing */
1954 if ((opcode & 0x0f000100) == 0x0c000000)
1955 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1957 /* Coprocessor register transfers */
1958 if ((opcode & 0x0f000010) == 0x0c000010)
1959 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1961 /* Undefined instruction */
1962 if ((opcode & 0x0f000000) == 0x0f000000) {
1963 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1964 snprintf(instruction->text,
1965 128,
1966 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
1967 address,
1968 opcode);
1969 return ERROR_OK;
1973 /* catch opcodes with [27:25] = b000 */
1974 if ((opcode & 0x0e000000) == 0x00000000) {
1975 /* Multiplies, extra load/stores */
1976 if ((opcode & 0x00000090) == 0x00000090)
1977 return evaluate_mul_and_extra_ld_st(opcode, address, instruction);
1979 /* Miscellaneous instructions */
1980 if ((opcode & 0x0f900000) == 0x01000000)
1981 return evaluate_misc_instr(opcode, address, instruction);
1983 return evaluate_data_proc(opcode, address, instruction);
1986 /* catch opcodes with [27:25] = b001 */
1987 if ((opcode & 0x0e000000) == 0x02000000) {
1988 /* 16-bit immediate load */
1989 if ((opcode & 0x0fb00000) == 0x03000000)
1990 return evaluate_mov_imm(opcode, address, instruction);
1992 /* Move immediate to status register */
1993 if ((opcode & 0x0fb00000) == 0x03200000)
1994 return evaluate_mrs_msr(opcode, address, instruction);
1996 return evaluate_data_proc(opcode, address, instruction);
2000 /* catch opcodes with [27:25] = b010 */
2001 if ((opcode & 0x0e000000) == 0x04000000) {
2002 /* Load/store immediate offset */
2003 return evaluate_load_store(opcode, address, instruction);
2006 /* catch opcodes with [27:25] = b011 */
2007 if ((opcode & 0x0e000000) == 0x06000000) {
2008 /* Load/store register offset */
2009 if ((opcode & 0x00000010) == 0x00000000)
2010 return evaluate_load_store(opcode, address, instruction);
2012 /* Architecturally Undefined instruction
2013 * ... don't expect these to ever be used
2015 if ((opcode & 0x07f000f0) == 0x07f000f0) {
2016 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2017 snprintf(instruction->text, 128,
2018 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEF",
2019 address, opcode);
2020 return ERROR_OK;
2023 /* "media" instructions */
2024 return evaluate_media(opcode, address, instruction);
2027 /* catch opcodes with [27:25] = b100 */
2028 if ((opcode & 0x0e000000) == 0x08000000) {
2029 /* Load/store multiple */
2030 return evaluate_ldm_stm(opcode, address, instruction);
2033 /* catch opcodes with [27:25] = b101 */
2034 if ((opcode & 0x0e000000) == 0x0a000000) {
2035 /* Branch and branch with link */
2036 return evaluate_b_bl(opcode, address, instruction);
2039 /* catch opcodes with [27:25] = b110 */
2040 if ((opcode & 0x0e000000) == 0x0c000000) {
2041 /* Coprocessor load/store and double register transfers */
2042 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
2045 /* catch opcodes with [27:25] = b111 */
2046 if ((opcode & 0x0e000000) == 0x0e000000) {
2047 /* Software interrupt */
2048 if ((opcode & 0x0f000000) == 0x0f000000)
2049 return evaluate_swi(opcode, address, instruction);
2051 /* Coprocessor data processing */
2052 if ((opcode & 0x0f000010) == 0x0e000000)
2053 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
2055 /* Coprocessor register transfers */
2056 if ((opcode & 0x0f000010) == 0x0e000010)
2057 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
2060 LOG_ERROR("ARM: should never reach this point (opcode=%08x)",
2061 (unsigned) opcode);
2062 return -1;
2065 static int evaluate_b_bl_blx_thumb(uint16_t opcode,
2066 uint32_t address, struct arm_instruction *instruction)
2068 uint32_t offset = opcode & 0x7ff;
2069 uint32_t opc = (opcode >> 11) & 0x3;
2070 uint32_t target_address;
2071 char *mnemonic = NULL;
2073 /* sign extend 11-bit offset */
2074 if (((opc == 0) || (opc == 2)) && (offset & 0x00000400))
2075 offset = 0xfffff800 | offset;
2077 target_address = address + 4 + (offset << 1);
2079 switch (opc) {
2080 /* unconditional branch */
2081 case 0:
2082 instruction->type = ARM_B;
2083 mnemonic = "B";
2084 break;
2085 /* BLX suffix */
2086 case 1:
2087 instruction->type = ARM_BLX;
2088 mnemonic = "BLX";
2089 target_address &= 0xfffffffc;
2090 break;
2091 /* BL/BLX prefix */
2092 case 2:
2093 instruction->type = ARM_UNKNOWN_INSTRUCTION;
2094 mnemonic = "prefix";
2095 target_address = offset << 12;
2096 break;
2097 /* BL suffix */
2098 case 3:
2099 instruction->type = ARM_BL;
2100 mnemonic = "BL";
2101 break;
2104 /* TODO: deal correctly with dual opcode (prefixed) BL/BLX;
2105 * these are effectively 32-bit instructions even in Thumb1. For
2106 * disassembly, it's simplest to always use the Thumb2 decoder.
2108 * But some cores will evidently handle them as two instructions,
2109 * where exceptions may occur between the two. The ETMv3.2+ ID
2110 * register has a bit which exposes this behavior.
2113 snprintf(instruction->text, 128,
2114 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%#8.8" PRIx32,
2115 address, opcode, mnemonic, target_address);
2117 instruction->info.b_bl_bx_blx.reg_operand = -1;
2118 instruction->info.b_bl_bx_blx.target_address = target_address;
2120 return ERROR_OK;
2123 static int evaluate_add_sub_thumb(uint16_t opcode,
2124 uint32_t address, struct arm_instruction *instruction)
2126 uint8_t Rd = (opcode >> 0) & 0x7;
2127 uint8_t Rn = (opcode >> 3) & 0x7;
2128 uint8_t Rm_imm = (opcode >> 6) & 0x7;
2129 uint32_t opc = opcode & (1 << 9);
2130 uint32_t reg_imm = opcode & (1 << 10);
2131 char *mnemonic;
2133 if (opc) {
2134 instruction->type = ARM_SUB;
2135 mnemonic = "SUBS";
2136 } else {
2137 /* REVISIT: if reg_imm == 0, display as "MOVS" */
2138 instruction->type = ARM_ADD;
2139 mnemonic = "ADDS";
2142 instruction->info.data_proc.Rd = Rd;
2143 instruction->info.data_proc.Rn = Rn;
2144 instruction->info.data_proc.S = 1;
2146 if (reg_imm) {
2147 instruction->info.data_proc.variant = 0;/*immediate*/
2148 instruction->info.data_proc.shifter_operand.immediate.immediate = Rm_imm;
2149 snprintf(instruction->text, 128,
2150 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%d",
2151 address, opcode, mnemonic, Rd, Rn, Rm_imm);
2152 } else {
2153 instruction->info.data_proc.variant = 1;/*immediate shift*/
2154 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm_imm;
2155 snprintf(instruction->text, 128,
2156 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, r%i",
2157 address, opcode, mnemonic, Rd, Rn, Rm_imm);
2160 return ERROR_OK;
2163 static int evaluate_shift_imm_thumb(uint16_t opcode,
2164 uint32_t address, struct arm_instruction *instruction)
2166 uint8_t Rd = (opcode >> 0) & 0x7;
2167 uint8_t Rm = (opcode >> 3) & 0x7;
2168 uint8_t imm = (opcode >> 6) & 0x1f;
2169 uint8_t opc = (opcode >> 11) & 0x3;
2170 char *mnemonic = NULL;
2172 switch (opc) {
2173 case 0:
2174 instruction->type = ARM_MOV;
2175 mnemonic = "LSLS";
2176 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 0;
2177 break;
2178 case 1:
2179 instruction->type = ARM_MOV;
2180 mnemonic = "LSRS";
2181 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 1;
2182 break;
2183 case 2:
2184 instruction->type = ARM_MOV;
2185 mnemonic = "ASRS";
2186 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 2;
2187 break;
2190 if ((imm == 0) && (opc != 0))
2191 imm = 32;
2193 instruction->info.data_proc.Rd = Rd;
2194 instruction->info.data_proc.Rn = -1;
2195 instruction->info.data_proc.S = 1;
2197 instruction->info.data_proc.variant = 1;/*immediate_shift*/
2198 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
2199 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = imm;
2201 snprintf(instruction->text, 128,
2202 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%#2.2x",
2203 address, opcode, mnemonic, Rd, Rm, imm);
2205 return ERROR_OK;
2208 static int evaluate_data_proc_imm_thumb(uint16_t opcode,
2209 uint32_t address, struct arm_instruction *instruction)
2211 uint8_t imm = opcode & 0xff;
2212 uint8_t Rd = (opcode >> 8) & 0x7;
2213 uint32_t opc = (opcode >> 11) & 0x3;
2214 char *mnemonic = NULL;
2216 instruction->info.data_proc.Rd = Rd;
2217 instruction->info.data_proc.Rn = Rd;
2218 instruction->info.data_proc.S = 1;
2219 instruction->info.data_proc.variant = 0;/*immediate*/
2220 instruction->info.data_proc.shifter_operand.immediate.immediate = imm;
2222 switch (opc) {
2223 case 0:
2224 instruction->type = ARM_MOV;
2225 mnemonic = "MOVS";
2226 instruction->info.data_proc.Rn = -1;
2227 break;
2228 case 1:
2229 instruction->type = ARM_CMP;
2230 mnemonic = "CMP";
2231 instruction->info.data_proc.Rd = -1;
2232 break;
2233 case 2:
2234 instruction->type = ARM_ADD;
2235 mnemonic = "ADDS";
2236 break;
2237 case 3:
2238 instruction->type = ARM_SUB;
2239 mnemonic = "SUBS";
2240 break;
2243 snprintf(instruction->text, 128,
2244 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, #%#2.2x",
2245 address, opcode, mnemonic, Rd, imm);
2247 return ERROR_OK;
2250 static int evaluate_data_proc_thumb(uint16_t opcode,
2251 uint32_t address, struct arm_instruction *instruction)
2253 uint8_t high_reg, op, Rm, Rd, H1, H2;
2254 char *mnemonic = NULL;
2255 bool nop = false;
2257 high_reg = (opcode & 0x0400) >> 10;
2258 op = (opcode & 0x03C0) >> 6;
2260 Rd = (opcode & 0x0007);
2261 Rm = (opcode & 0x0038) >> 3;
2262 H1 = (opcode & 0x0080) >> 7;
2263 H2 = (opcode & 0x0040) >> 6;
2265 instruction->info.data_proc.Rd = Rd;
2266 instruction->info.data_proc.Rn = Rd;
2267 instruction->info.data_proc.S = (!high_reg || (instruction->type == ARM_CMP));
2268 instruction->info.data_proc.variant = 1 /*immediate shift*/;
2269 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
2271 if (high_reg) {
2272 Rd |= H1 << 3;
2273 Rm |= H2 << 3;
2274 op >>= 2;
2276 switch (op) {
2277 case 0x0:
2278 instruction->type = ARM_ADD;
2279 mnemonic = "ADD";
2280 break;
2281 case 0x1:
2282 instruction->type = ARM_CMP;
2283 mnemonic = "CMP";
2284 break;
2285 case 0x2:
2286 instruction->type = ARM_MOV;
2287 mnemonic = "MOV";
2288 if (Rd == Rm)
2289 nop = true;
2290 break;
2291 case 0x3:
2292 if ((opcode & 0x7) == 0x0) {
2293 instruction->info.b_bl_bx_blx.reg_operand = Rm;
2294 if (H1) {
2295 instruction->type = ARM_BLX;
2296 snprintf(instruction->text, 128,
2297 "0x%8.8" PRIx32
2298 " 0x%4.4x \tBLX\tr%i",
2299 address, opcode, Rm);
2300 } else {
2301 instruction->type = ARM_BX;
2302 snprintf(instruction->text, 128,
2303 "0x%8.8" PRIx32
2304 " 0x%4.4x \tBX\tr%i",
2305 address, opcode, Rm);
2307 } else {
2308 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2309 snprintf(instruction->text, 128,
2310 "0x%8.8" PRIx32
2311 " 0x%4.4x \t"
2312 "UNDEFINED INSTRUCTION",
2313 address, opcode);
2315 return ERROR_OK;
2317 } else {
2318 switch (op) {
2319 case 0x0:
2320 instruction->type = ARM_AND;
2321 mnemonic = "ANDS";
2322 break;
2323 case 0x1:
2324 instruction->type = ARM_EOR;
2325 mnemonic = "EORS";
2326 break;
2327 case 0x2:
2328 instruction->type = ARM_MOV;
2329 mnemonic = "LSLS";
2330 instruction->info.data_proc.variant = 2 /*register shift*/;
2331 instruction->info.data_proc.shifter_operand.register_shift.shift = 0;
2332 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
2333 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
2334 break;
2335 case 0x3:
2336 instruction->type = ARM_MOV;
2337 mnemonic = "LSRS";
2338 instruction->info.data_proc.variant = 2 /*register shift*/;
2339 instruction->info.data_proc.shifter_operand.register_shift.shift = 1;
2340 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
2341 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
2342 break;
2343 case 0x4:
2344 instruction->type = ARM_MOV;
2345 mnemonic = "ASRS";
2346 instruction->info.data_proc.variant = 2 /*register shift*/;
2347 instruction->info.data_proc.shifter_operand.register_shift.shift = 2;
2348 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
2349 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
2350 break;
2351 case 0x5:
2352 instruction->type = ARM_ADC;
2353 mnemonic = "ADCS";
2354 break;
2355 case 0x6:
2356 instruction->type = ARM_SBC;
2357 mnemonic = "SBCS";
2358 break;
2359 case 0x7:
2360 instruction->type = ARM_MOV;
2361 mnemonic = "RORS";
2362 instruction->info.data_proc.variant = 2 /*register shift*/;
2363 instruction->info.data_proc.shifter_operand.register_shift.shift = 3;
2364 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
2365 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
2366 break;
2367 case 0x8:
2368 instruction->type = ARM_TST;
2369 mnemonic = "TST";
2370 break;
2371 case 0x9:
2372 instruction->type = ARM_RSB;
2373 mnemonic = "RSBS";
2374 instruction->info.data_proc.variant = 0 /*immediate*/;
2375 instruction->info.data_proc.shifter_operand.immediate.immediate = 0;
2376 instruction->info.data_proc.Rn = Rm;
2377 break;
2378 case 0xA:
2379 instruction->type = ARM_CMP;
2380 mnemonic = "CMP";
2381 break;
2382 case 0xB:
2383 instruction->type = ARM_CMN;
2384 mnemonic = "CMN";
2385 break;
2386 case 0xC:
2387 instruction->type = ARM_ORR;
2388 mnemonic = "ORRS";
2389 break;
2390 case 0xD:
2391 instruction->type = ARM_MUL;
2392 mnemonic = "MULS";
2393 break;
2394 case 0xE:
2395 instruction->type = ARM_BIC;
2396 mnemonic = "BICS";
2397 break;
2398 case 0xF:
2399 instruction->type = ARM_MVN;
2400 mnemonic = "MVNS";
2401 break;
2405 if (nop)
2406 snprintf(instruction->text, 128,
2407 "0x%8.8" PRIx32 " 0x%4.4x \tNOP\t\t\t"
2408 "; (%s r%i, r%i)",
2409 address, opcode, mnemonic, Rd, Rm);
2410 else
2411 snprintf(instruction->text, 128,
2412 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i",
2413 address, opcode, mnemonic, Rd, Rm);
2415 return ERROR_OK;
2418 /* PC-relative data addressing is word-aligned even with Thumb */
2419 static inline uint32_t thumb_alignpc4(uint32_t addr)
2421 return (addr + 4) & ~3;
2424 static int evaluate_load_literal_thumb(uint16_t opcode,
2425 uint32_t address, struct arm_instruction *instruction)
2427 uint32_t immediate;
2428 uint8_t Rd = (opcode >> 8) & 0x7;
2430 instruction->type = ARM_LDR;
2431 immediate = opcode & 0x000000ff;
2432 immediate *= 4;
2434 instruction->info.load_store.Rd = Rd;
2435 instruction->info.load_store.Rn = 15 /*PC*/;
2436 instruction->info.load_store.index_mode = 0; /*offset*/
2437 instruction->info.load_store.offset_mode = 0; /*immediate*/
2438 instruction->info.load_store.offset.offset = immediate;
2440 snprintf(instruction->text, 128,
2441 "0x%8.8" PRIx32 " 0x%4.4x \t"
2442 "LDR\tr%i, [pc, #%#" PRIx32 "]\t; %#8.8" PRIx32,
2443 address, opcode, Rd, immediate,
2444 thumb_alignpc4(address) + immediate);
2446 return ERROR_OK;
2449 static int evaluate_load_store_reg_thumb(uint16_t opcode,
2450 uint32_t address, struct arm_instruction *instruction)
2452 uint8_t Rd = (opcode >> 0) & 0x7;
2453 uint8_t Rn = (opcode >> 3) & 0x7;
2454 uint8_t Rm = (opcode >> 6) & 0x7;
2455 uint8_t opc = (opcode >> 9) & 0x7;
2456 char *mnemonic = NULL;
2458 switch (opc) {
2459 case 0:
2460 instruction->type = ARM_STR;
2461 mnemonic = "STR";
2462 break;
2463 case 1:
2464 instruction->type = ARM_STRH;
2465 mnemonic = "STRH";
2466 break;
2467 case 2:
2468 instruction->type = ARM_STRB;
2469 mnemonic = "STRB";
2470 break;
2471 case 3:
2472 instruction->type = ARM_LDRSB;
2473 mnemonic = "LDRSB";
2474 break;
2475 case 4:
2476 instruction->type = ARM_LDR;
2477 mnemonic = "LDR";
2478 break;
2479 case 5:
2480 instruction->type = ARM_LDRH;
2481 mnemonic = "LDRH";
2482 break;
2483 case 6:
2484 instruction->type = ARM_LDRB;
2485 mnemonic = "LDRB";
2486 break;
2487 case 7:
2488 instruction->type = ARM_LDRSH;
2489 mnemonic = "LDRSH";
2490 break;
2493 snprintf(instruction->text, 128,
2494 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [r%i, r%i]",
2495 address, opcode, mnemonic, Rd, Rn, Rm);
2497 instruction->info.load_store.Rd = Rd;
2498 instruction->info.load_store.Rn = Rn;
2499 instruction->info.load_store.index_mode = 0; /*offset*/
2500 instruction->info.load_store.offset_mode = 1; /*register*/
2501 instruction->info.load_store.offset.reg.Rm = Rm;
2503 return ERROR_OK;
2506 static int evaluate_load_store_imm_thumb(uint16_t opcode,
2507 uint32_t address, struct arm_instruction *instruction)
2509 uint32_t offset = (opcode >> 6) & 0x1f;
2510 uint8_t Rd = (opcode >> 0) & 0x7;
2511 uint8_t Rn = (opcode >> 3) & 0x7;
2512 uint32_t L = opcode & (1 << 11);
2513 uint32_t B = opcode & (1 << 12);
2514 char *mnemonic;
2515 char suffix = ' ';
2516 uint32_t shift = 2;
2518 if (L) {
2519 instruction->type = ARM_LDR;
2520 mnemonic = "LDR";
2521 } else {
2522 instruction->type = ARM_STR;
2523 mnemonic = "STR";
2526 if ((opcode&0xF000) == 0x8000) {
2527 suffix = 'H';
2528 shift = 1;
2529 } else if (B) {
2530 suffix = 'B';
2531 shift = 0;
2534 snprintf(instruction->text, 128,
2535 "0x%8.8" PRIx32 " 0x%4.4x \t%s%c\tr%i, [r%i, #%#" PRIx32 "]",
2536 address, opcode, mnemonic, suffix, Rd, Rn, offset << shift);
2538 instruction->info.load_store.Rd = Rd;
2539 instruction->info.load_store.Rn = Rn;
2540 instruction->info.load_store.index_mode = 0; /*offset*/
2541 instruction->info.load_store.offset_mode = 0; /*immediate*/
2542 instruction->info.load_store.offset.offset = offset << shift;
2544 return ERROR_OK;
2547 static int evaluate_load_store_stack_thumb(uint16_t opcode,
2548 uint32_t address, struct arm_instruction *instruction)
2550 uint32_t offset = opcode & 0xff;
2551 uint8_t Rd = (opcode >> 8) & 0x7;
2552 uint32_t L = opcode & (1 << 11);
2553 char *mnemonic;
2555 if (L) {
2556 instruction->type = ARM_LDR;
2557 mnemonic = "LDR";
2558 } else {
2559 instruction->type = ARM_STR;
2560 mnemonic = "STR";
2563 snprintf(instruction->text, 128,
2564 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [SP, #%#" PRIx32 "]",
2565 address, opcode, mnemonic, Rd, offset*4);
2567 instruction->info.load_store.Rd = Rd;
2568 instruction->info.load_store.Rn = 13 /*SP*/;
2569 instruction->info.load_store.index_mode = 0; /*offset*/
2570 instruction->info.load_store.offset_mode = 0; /*immediate*/
2571 instruction->info.load_store.offset.offset = offset*4;
2573 return ERROR_OK;
2576 static int evaluate_add_sp_pc_thumb(uint16_t opcode,
2577 uint32_t address, struct arm_instruction *instruction)
2579 uint32_t imm = opcode & 0xff;
2580 uint8_t Rd = (opcode >> 8) & 0x7;
2581 uint8_t Rn;
2582 uint32_t SP = opcode & (1 << 11);
2583 const char *reg_name;
2585 instruction->type = ARM_ADD;
2587 if (SP) {
2588 reg_name = "SP";
2589 Rn = 13;
2590 } else {
2591 reg_name = "PC";
2592 Rn = 15;
2595 snprintf(instruction->text, 128,
2596 "0x%8.8" PRIx32 " 0x%4.4x \tADD\tr%i, %s, #%#" PRIx32,
2597 address, opcode, Rd, reg_name, imm * 4);
2599 instruction->info.data_proc.variant = 0 /* immediate */;
2600 instruction->info.data_proc.Rd = Rd;
2601 instruction->info.data_proc.Rn = Rn;
2602 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
2604 return ERROR_OK;
2607 static int evaluate_adjust_stack_thumb(uint16_t opcode,
2608 uint32_t address, struct arm_instruction *instruction)
2610 uint32_t imm = opcode & 0x7f;
2611 uint8_t opc = opcode & (1 << 7);
2612 char *mnemonic;
2615 if (opc) {
2616 instruction->type = ARM_SUB;
2617 mnemonic = "SUB";
2618 } else {
2619 instruction->type = ARM_ADD;
2620 mnemonic = "ADD";
2623 snprintf(instruction->text, 128,
2624 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tSP, #%#" PRIx32,
2625 address, opcode, mnemonic, imm*4);
2627 instruction->info.data_proc.variant = 0 /* immediate */;
2628 instruction->info.data_proc.Rd = 13 /*SP*/;
2629 instruction->info.data_proc.Rn = 13 /*SP*/;
2630 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
2632 return ERROR_OK;
2635 static int evaluate_breakpoint_thumb(uint16_t opcode,
2636 uint32_t address, struct arm_instruction *instruction)
2638 uint32_t imm = opcode & 0xff;
2640 instruction->type = ARM_BKPT;
2642 snprintf(instruction->text, 128,
2643 "0x%8.8" PRIx32 " 0x%4.4x \tBKPT\t%#2.2" PRIx32 "",
2644 address, opcode, imm);
2646 return ERROR_OK;
2649 static int evaluate_load_store_multiple_thumb(uint16_t opcode,
2650 uint32_t address, struct arm_instruction *instruction)
2652 uint32_t reg_list = opcode & 0xff;
2653 uint32_t L = opcode & (1 << 11);
2654 uint32_t R = opcode & (1 << 8);
2655 uint8_t Rn = (opcode >> 8) & 7;
2656 uint8_t addr_mode = 0 /* IA */;
2657 char reg_names[40];
2658 char *reg_names_p;
2659 char *mnemonic;
2660 char ptr_name[7] = "";
2661 int i;
2663 /* REVISIT: in ThumbEE mode, there are no LDM or STM instructions.
2664 * The STMIA and LDMIA opcodes are used for other instructions.
2667 if ((opcode & 0xf000) == 0xc000) { /* generic load/store multiple */
2668 char *wback = "!";
2670 if (L) {
2671 instruction->type = ARM_LDM;
2672 mnemonic = "LDM";
2673 if (opcode & (1 << Rn))
2674 wback = "";
2675 } else {
2676 instruction->type = ARM_STM;
2677 mnemonic = "STM";
2679 snprintf(ptr_name, sizeof(ptr_name), "r%i%s, ", Rn, wback);
2680 } else {/* push/pop */
2681 Rn = 13;/* SP */
2682 if (L) {
2683 instruction->type = ARM_LDM;
2684 mnemonic = "POP";
2685 if (R)
2686 reg_list |= (1 << 15) /*PC*/;
2687 } else {
2688 instruction->type = ARM_STM;
2689 mnemonic = "PUSH";
2690 addr_mode = 3; /*DB*/
2691 if (R)
2692 reg_list |= (1 << 14) /*LR*/;
2696 reg_names_p = reg_names;
2697 for (i = 0; i <= 15; i++) {
2698 if (reg_list & (1 << i))
2699 reg_names_p += snprintf(reg_names_p,
2700 (reg_names + 40 - reg_names_p),
2701 "r%i, ",
2704 if (reg_names_p > reg_names)
2705 reg_names_p[-2] = '\0';
2706 else /* invalid op : no registers */
2707 reg_names[0] = '\0';
2709 snprintf(instruction->text, 128,
2710 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%s{%s}",
2711 address, opcode, mnemonic, ptr_name, reg_names);
2713 instruction->info.load_store_multiple.register_list = reg_list;
2714 instruction->info.load_store_multiple.Rn = Rn;
2715 instruction->info.load_store_multiple.addressing_mode = addr_mode;
2717 return ERROR_OK;
2720 static int evaluate_cond_branch_thumb(uint16_t opcode,
2721 uint32_t address, struct arm_instruction *instruction)
2723 uint32_t offset = opcode & 0xff;
2724 uint8_t cond = (opcode >> 8) & 0xf;
2725 uint32_t target_address;
2727 if (cond == 0xf) {
2728 instruction->type = ARM_SWI;
2729 snprintf(instruction->text, 128,
2730 "0x%8.8" PRIx32 " 0x%4.4x \tSVC\t%#2.2" PRIx32,
2731 address, opcode, offset);
2732 return ERROR_OK;
2733 } else if (cond == 0xe) {
2734 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2735 snprintf(instruction->text, 128,
2736 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2737 address, opcode);
2738 return ERROR_OK;
2741 /* sign extend 8-bit offset */
2742 if (offset & 0x00000080)
2743 offset = 0xffffff00 | offset;
2745 target_address = address + 4 + (offset << 1);
2747 snprintf(instruction->text, 128,
2748 "0x%8.8" PRIx32 " 0x%4.4x \tB%s\t%#8.8" PRIx32,
2749 address, opcode,
2750 arm_condition_strings[cond], target_address);
2752 instruction->type = ARM_B;
2753 instruction->info.b_bl_bx_blx.reg_operand = -1;
2754 instruction->info.b_bl_bx_blx.target_address = target_address;
2756 return ERROR_OK;
2759 static int evaluate_cb_thumb(uint16_t opcode, uint32_t address,
2760 struct arm_instruction *instruction)
2762 unsigned offset;
2764 /* added in Thumb2 */
2765 offset = (opcode >> 3) & 0x1f;
2766 offset |= (opcode & 0x0200) >> 4;
2768 snprintf(instruction->text, 128,
2769 "0x%8.8" PRIx32 " 0x%4.4x \tCB%sZ\tr%d, %#8.8" PRIx32,
2770 address, opcode,
2771 (opcode & 0x0800) ? "N" : "",
2772 opcode & 0x7, address + 4 + (offset << 1));
2774 return ERROR_OK;
2777 static int evaluate_extend_thumb(uint16_t opcode, uint32_t address,
2778 struct arm_instruction *instruction)
2780 /* added in ARMv6 */
2781 snprintf(instruction->text, 128,
2782 "0x%8.8" PRIx32 " 0x%4.4x \t%cXT%c\tr%d, r%d",
2783 address, opcode,
2784 (opcode & 0x0080) ? 'U' : 'S',
2785 (opcode & 0x0040) ? 'B' : 'H',
2786 opcode & 0x7, (opcode >> 3) & 0x7);
2788 return ERROR_OK;
2791 static int evaluate_cps_thumb(uint16_t opcode, uint32_t address,
2792 struct arm_instruction *instruction)
2794 /* added in ARMv6 */
2795 if ((opcode & 0x0ff0) == 0x0650)
2796 snprintf(instruction->text, 128,
2797 "0x%8.8" PRIx32 " 0x%4.4x \tSETEND %s",
2798 address, opcode,
2799 (opcode & 0x80) ? "BE" : "LE");
2800 else /* ASSUME (opcode & 0x0fe0) == 0x0660 */
2801 snprintf(instruction->text, 128,
2802 "0x%8.8" PRIx32 " 0x%4.4x \tCPSI%c\t%s%s%s",
2803 address, opcode,
2804 (opcode & 0x0010) ? 'D' : 'E',
2805 (opcode & 0x0004) ? "A" : "",
2806 (opcode & 0x0002) ? "I" : "",
2807 (opcode & 0x0001) ? "F" : "");
2809 return ERROR_OK;
2812 static int evaluate_byterev_thumb(uint16_t opcode, uint32_t address,
2813 struct arm_instruction *instruction)
2815 char *suffix;
2817 /* added in ARMv6 */
2818 switch ((opcode >> 6) & 3) {
2819 case 0:
2820 suffix = "";
2821 break;
2822 case 1:
2823 suffix = "16";
2824 break;
2825 default:
2826 suffix = "SH";
2827 break;
2829 snprintf(instruction->text, 128,
2830 "0x%8.8" PRIx32 " 0x%4.4x \tREV%s\tr%d, r%d",
2831 address, opcode, suffix,
2832 opcode & 0x7, (opcode >> 3) & 0x7);
2834 return ERROR_OK;
2837 static int evaluate_hint_thumb(uint16_t opcode, uint32_t address,
2838 struct arm_instruction *instruction)
2840 char *hint;
2842 switch ((opcode >> 4) & 0x0f) {
2843 case 0:
2844 hint = "NOP";
2845 break;
2846 case 1:
2847 hint = "YIELD";
2848 break;
2849 case 2:
2850 hint = "WFE";
2851 break;
2852 case 3:
2853 hint = "WFI";
2854 break;
2855 case 4:
2856 hint = "SEV";
2857 break;
2858 default:
2859 hint = "HINT (UNRECOGNIZED)";
2860 break;
2863 snprintf(instruction->text, 128,
2864 "0x%8.8" PRIx32 " 0x%4.4x \t%s",
2865 address, opcode, hint);
2867 return ERROR_OK;
2870 static int evaluate_ifthen_thumb(uint16_t opcode, uint32_t address,
2871 struct arm_instruction *instruction)
2873 unsigned cond = (opcode >> 4) & 0x0f;
2874 char *x = "", *y = "", *z = "";
2876 if (opcode & 0x01)
2877 z = (opcode & 0x02) ? "T" : "E";
2878 if (opcode & 0x03)
2879 y = (opcode & 0x04) ? "T" : "E";
2880 if (opcode & 0x07)
2881 x = (opcode & 0x08) ? "T" : "E";
2883 snprintf(instruction->text, 128,
2884 "0x%8.8" PRIx32 " 0x%4.4x \tIT%s%s%s\t%s",
2885 address, opcode,
2886 x, y, z, arm_condition_strings[cond]);
2888 /* NOTE: strictly speaking, the next 1-4 instructions should
2889 * now be displayed with the relevant conditional suffix...
2892 return ERROR_OK;
2895 int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
2897 /* clear fields, to avoid confusion */
2898 memset(instruction, 0, sizeof(struct arm_instruction));
2899 instruction->opcode = opcode;
2900 instruction->instruction_size = 2;
2902 if ((opcode & 0xe000) == 0x0000) {
2903 /* add/subtract register or immediate */
2904 if ((opcode & 0x1800) == 0x1800)
2905 return evaluate_add_sub_thumb(opcode, address, instruction);
2906 /* shift by immediate */
2907 else
2908 return evaluate_shift_imm_thumb(opcode, address, instruction);
2911 /* Add/subtract/compare/move immediate */
2912 if ((opcode & 0xe000) == 0x2000)
2913 return evaluate_data_proc_imm_thumb(opcode, address, instruction);
2915 /* Data processing instructions */
2916 if ((opcode & 0xf800) == 0x4000)
2917 return evaluate_data_proc_thumb(opcode, address, instruction);
2919 /* Load from literal pool */
2920 if ((opcode & 0xf800) == 0x4800)
2921 return evaluate_load_literal_thumb(opcode, address, instruction);
2923 /* Load/Store register offset */
2924 if ((opcode & 0xf000) == 0x5000)
2925 return evaluate_load_store_reg_thumb(opcode, address, instruction);
2927 /* Load/Store immediate offset */
2928 if (((opcode & 0xe000) == 0x6000)
2929 || ((opcode & 0xf000) == 0x8000))
2930 return evaluate_load_store_imm_thumb(opcode, address, instruction);
2932 /* Load/Store from/to stack */
2933 if ((opcode & 0xf000) == 0x9000)
2934 return evaluate_load_store_stack_thumb(opcode, address, instruction);
2936 /* Add to SP/PC */
2937 if ((opcode & 0xf000) == 0xa000)
2938 return evaluate_add_sp_pc_thumb(opcode, address, instruction);
2940 /* Misc */
2941 if ((opcode & 0xf000) == 0xb000) {
2942 switch ((opcode >> 8) & 0x0f) {
2943 case 0x0:
2944 return evaluate_adjust_stack_thumb(opcode, address, instruction);
2945 case 0x1:
2946 case 0x3:
2947 case 0x9:
2948 case 0xb:
2949 return evaluate_cb_thumb(opcode, address, instruction);
2950 case 0x2:
2951 return evaluate_extend_thumb(opcode, address, instruction);
2952 case 0x4:
2953 case 0x5:
2954 case 0xc:
2955 case 0xd:
2956 return evaluate_load_store_multiple_thumb(opcode, address,
2957 instruction);
2958 case 0x6:
2959 return evaluate_cps_thumb(opcode, address, instruction);
2960 case 0xa:
2961 if ((opcode & 0x00c0) == 0x0080)
2962 break;
2963 return evaluate_byterev_thumb(opcode, address, instruction);
2964 case 0xe:
2965 return evaluate_breakpoint_thumb(opcode, address, instruction);
2966 case 0xf:
2967 if (opcode & 0x000f)
2968 return evaluate_ifthen_thumb(opcode, address,
2969 instruction);
2970 else
2971 return evaluate_hint_thumb(opcode, address,
2972 instruction);
2975 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2976 snprintf(instruction->text, 128,
2977 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2978 address, opcode);
2979 return ERROR_OK;
2982 /* Load/Store multiple */
2983 if ((opcode & 0xf000) == 0xc000)
2984 return evaluate_load_store_multiple_thumb(opcode, address, instruction);
2986 /* Conditional branch + SWI */
2987 if ((opcode & 0xf000) == 0xd000)
2988 return evaluate_cond_branch_thumb(opcode, address, instruction);
2990 if ((opcode & 0xe000) == 0xe000) {
2991 /* Undefined instructions */
2992 if ((opcode & 0xf801) == 0xe801) {
2993 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2994 snprintf(instruction->text, 128,
2995 "0x%8.8" PRIx32 " 0x%8.8x\t"
2996 "UNDEFINED INSTRUCTION",
2997 address, opcode);
2998 return ERROR_OK;
2999 } else /* Branch to offset */
3000 return evaluate_b_bl_blx_thumb(opcode, address, instruction);
3003 LOG_ERROR("Thumb: should never reach this point (opcode=%04x)", opcode);
3004 return -1;
3007 int arm_access_size(struct arm_instruction *instruction)
3009 if ((instruction->type == ARM_LDRB)
3010 || (instruction->type == ARM_LDRBT)
3011 || (instruction->type == ARM_LDRSB)
3012 || (instruction->type == ARM_STRB)
3013 || (instruction->type == ARM_STRBT))
3014 return 1;
3015 else if ((instruction->type == ARM_LDRH)
3016 || (instruction->type == ARM_LDRSH)
3017 || (instruction->type == ARM_STRH))
3018 return 2;
3019 else if ((instruction->type == ARM_LDR)
3020 || (instruction->type == ARM_LDRT)
3021 || (instruction->type == ARM_STR)
3022 || (instruction->type == ARM_STRT))
3023 return 4;
3024 else if ((instruction->type == ARM_LDRD)
3025 || (instruction->type == ARM_STRD))
3026 return 8;
3027 else {
3028 LOG_ERROR("BUG: instruction type %i isn't a load/store instruction",
3029 instruction->type);
3030 return 0;
3034 #if HAVE_CAPSTONE
3035 static void print_opcode(struct command_invocation *cmd, const cs_insn *insn)
3037 uint32_t opcode = 0;
3039 memcpy(&opcode, insn->bytes, insn->size);
3041 if (insn->size == 4) {
3042 uint16_t opcode_high = opcode >> 16;
3043 opcode = opcode & 0xffff;
3045 command_print(cmd, "0x%08" PRIx64" %04x %04x\t%s%s%s",
3046 insn->address, opcode, opcode_high, insn->mnemonic,
3047 insn->op_str[0] ? "\t" : "", insn->op_str);
3048 } else {
3049 command_print(cmd, "0x%08" PRIx64" %04x\t%s%s%s",
3050 insn->address, opcode, insn->mnemonic,
3051 insn->op_str[0] ? "\t" : "", insn->op_str);
3055 int arm_disassemble(struct command_invocation *cmd, struct target *target,
3056 target_addr_t address, size_t count, bool thumb_mode)
3058 csh handle;
3059 int ret;
3060 cs_insn *insn;
3061 cs_mode mode;
3063 if (!cs_support(CS_ARCH_ARM)) {
3064 LOG_ERROR("ARM architecture not supported by capstone");
3065 return ERROR_FAIL;
3068 mode = CS_MODE_LITTLE_ENDIAN;
3070 if (thumb_mode)
3071 mode |= CS_MODE_THUMB;
3073 ret = cs_open(CS_ARCH_ARM, mode, &handle);
3075 if (ret != CS_ERR_OK) {
3076 LOG_ERROR("cs_open() failed: %s", cs_strerror(ret));
3077 return ERROR_FAIL;
3080 ret = cs_option(handle, CS_OPT_SKIPDATA, CS_OPT_ON);
3082 if (ret != CS_ERR_OK) {
3083 LOG_ERROR("cs_option() failed: %s", cs_strerror(ret));
3084 cs_close(&handle);
3085 return ERROR_FAIL;
3088 insn = cs_malloc(handle);
3090 if (!insn) {
3091 LOG_ERROR("cs_malloc() failed\n");
3092 cs_close(&handle);
3093 return ERROR_FAIL;
3096 while (count > 0) {
3097 uint8_t buffer[4];
3099 ret = target_read_buffer(target, address, sizeof(buffer), buffer);
3101 if (ret != ERROR_OK) {
3102 cs_free(insn, 1);
3103 cs_close(&handle);
3104 return ret;
3107 size_t size = sizeof(buffer);
3108 const uint8_t *tmp = buffer;
3110 ret = cs_disasm_iter(handle, &tmp, &size, &address, insn);
3112 if (!ret) {
3113 LOG_ERROR("cs_disasm_iter() failed: %s",
3114 cs_strerror(cs_errno(handle)));
3115 cs_free(insn, 1);
3116 cs_close(&handle);
3117 return ERROR_FAIL;
3120 print_opcode(cmd, insn);
3121 count--;
3124 cs_free(insn, 1);
3125 cs_close(&handle);
3127 return ERROR_OK;
3129 #endif /* HAVE_CAPSTONE */