jtag/core, target: unregister JTAG events
[openocd.git] / src / target / arm_disassembler.c
blob8e783d3425f303b669c70fe178408cd4628f7b39
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>
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.
45 * - ARM decoding
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
59 * ARMv4T and ARMv5T.
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.
68 * - ThumbEE decoding
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);
114 return ERROR_OK;
117 static int evaluate_pld(uint32_t opcode,
118 uint32_t address, struct arm_instruction *instruction)
120 /* PLD */
121 if ((opcode & 0x0d70f000) == 0x0550f000) {
122 instruction->type = ARM_PLD;
124 snprintf(instruction->text,
125 128,
126 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD ...TODO...",
127 address,
128 opcode);
130 return ERROR_OK;
132 /* DSB */
133 if ((opcode & 0x07f000f0) == 0x05700040) {
134 instruction->type = ARM_DSB;
136 char *opt;
137 switch (opcode & 0x0000000f) {
138 case 0xf:
139 opt = "SY";
140 break;
141 case 0xe:
142 opt = "ST";
143 break;
144 case 0xb:
145 opt = "ISH";
146 break;
147 case 0xa:
148 opt = "ISHST";
149 break;
150 case 0x7:
151 opt = "NSH";
152 break;
153 case 0x6:
154 opt = "NSHST";
155 break;
156 case 0x3:
157 opt = "OSH";
158 break;
159 case 0x2:
160 opt = "OSHST";
161 break;
162 default:
163 opt = "UNK";
166 snprintf(instruction->text,
167 128,
168 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tDSB %s",
169 address, opcode, opt);
171 return ERROR_OK;
173 /* ISB */
174 if ((opcode & 0x07f000f0) == 0x05700060) {
175 instruction->type = ARM_ISB;
177 snprintf(instruction->text,
178 128,
179 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tISB %s",
180 address, opcode,
181 ((opcode & 0x0000000f) == 0xf) ? "SY" : "UNK");
183 return ERROR_OK;
185 return evaluate_unknown(opcode, address, instruction);
188 static int evaluate_srs(uint32_t opcode,
189 uint32_t address, struct arm_instruction *instruction)
191 const char *wback = (opcode & (1 << 21)) ? "!" : "";
192 const char *mode = "";
194 switch ((opcode >> 23) & 0x3) {
195 case 0:
196 mode = "DA";
197 break;
198 case 1:
199 /* "IA" is default */
200 break;
201 case 2:
202 mode = "DB";
203 break;
204 case 3:
205 mode = "IB";
206 break;
209 switch (opcode & 0x0e500000) {
210 case 0x08400000:
211 snprintf(instruction->text, 128, "0x%8.8" PRIx32
212 "\t0x%8.8" PRIx32
213 "\tSRS%s\tSP%s, #%d",
214 address, opcode,
215 mode, wback,
216 (unsigned)(opcode & 0x1f));
217 break;
218 case 0x08100000:
219 snprintf(instruction->text, 128, "0x%8.8" PRIx32
220 "\t0x%8.8" PRIx32
221 "\tRFE%s\tr%d%s",
222 address, opcode,
223 mode,
224 (unsigned)((opcode >> 16) & 0xf), wback);
225 break;
226 default:
227 return evaluate_unknown(opcode, address, instruction);
229 return ERROR_OK;
232 static int evaluate_swi(uint32_t opcode,
233 uint32_t address, struct arm_instruction *instruction)
235 instruction->type = ARM_SWI;
237 snprintf(instruction->text, 128,
238 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSVC %#6.6" PRIx32,
239 address, opcode, (opcode & 0xffffff));
241 return ERROR_OK;
244 static int evaluate_blx_imm(uint32_t opcode,
245 uint32_t address, struct arm_instruction *instruction)
247 int offset;
248 uint32_t immediate;
249 uint32_t target_address;
251 instruction->type = ARM_BLX;
252 immediate = opcode & 0x00ffffff;
254 /* sign extend 24-bit immediate */
255 if (immediate & 0x00800000)
256 offset = 0xff000000 | immediate;
257 else
258 offset = immediate;
260 /* shift two bits left */
261 offset <<= 2;
263 /* odd/event halfword */
264 if (opcode & 0x01000000)
265 offset |= 0x2;
267 target_address = address + 8 + offset;
269 snprintf(instruction->text,
270 128,
271 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX 0x%8.8" PRIx32 "",
272 address,
273 opcode,
274 target_address);
276 instruction->info.b_bl_bx_blx.reg_operand = -1;
277 instruction->info.b_bl_bx_blx.target_address = target_address;
279 return ERROR_OK;
282 static int evaluate_b_bl(uint32_t opcode,
283 uint32_t address, struct arm_instruction *instruction)
285 uint8_t L;
286 uint32_t immediate;
287 int offset;
288 uint32_t target_address;
290 immediate = opcode & 0x00ffffff;
291 L = (opcode & 0x01000000) >> 24;
293 /* sign extend 24-bit immediate */
294 if (immediate & 0x00800000)
295 offset = 0xff000000 | immediate;
296 else
297 offset = immediate;
299 /* shift two bits left */
300 offset <<= 2;
302 target_address = address + 8 + offset;
304 if (L)
305 instruction->type = ARM_BL;
306 else
307 instruction->type = ARM_B;
309 snprintf(instruction->text,
310 128,
311 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tB%s%s 0x%8.8" PRIx32,
312 address,
313 opcode,
314 (L) ? "L" : "",
315 COND(opcode),
316 target_address);
318 instruction->info.b_bl_bx_blx.reg_operand = -1;
319 instruction->info.b_bl_bx_blx.target_address = target_address;
321 return ERROR_OK;
324 /* Coprocessor load/store and double register transfers
325 * both normal and extended instruction space (condition field b1111) */
326 static int evaluate_ldc_stc_mcrr_mrrc(uint32_t opcode,
327 uint32_t address, struct arm_instruction *instruction)
329 uint8_t cp_num = (opcode & 0xf00) >> 8;
331 /* MCRR or MRRC */
332 if (((opcode & 0x0ff00000) == 0x0c400000) || ((opcode & 0x0ff00000) == 0x0c500000)) {
333 uint8_t cp_opcode, Rd, Rn, CRm;
334 char *mnemonic;
336 cp_opcode = (opcode & 0xf0) >> 4;
337 Rd = (opcode & 0xf000) >> 12;
338 Rn = (opcode & 0xf0000) >> 16;
339 CRm = (opcode & 0xf);
341 /* MCRR */
342 if ((opcode & 0x0ff00000) == 0x0c400000) {
343 instruction->type = ARM_MCRR;
344 mnemonic = "MCRR";
345 } else if ((opcode & 0x0ff00000) == 0x0c500000) {
346 /* MRRC */
347 instruction->type = ARM_MRRC;
348 mnemonic = "MRRC";
349 } else {
350 LOG_ERROR("Unknown instruction");
351 return ERROR_FAIL;
354 snprintf(instruction->text, 128,
355 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
356 "\t%s%s%s p%i, %x, r%i, r%i, c%i",
357 address, opcode, mnemonic,
358 ((opcode & 0xf0000000) == 0xf0000000)
359 ? "2" : COND(opcode),
360 COND(opcode), cp_num, cp_opcode, Rd, Rn, CRm);
361 } else {/* LDC or STC */
362 uint8_t CRd, Rn, offset;
363 uint8_t U;
364 char *mnemonic;
365 char addressing_mode[32];
367 CRd = (opcode & 0xf000) >> 12;
368 Rn = (opcode & 0xf0000) >> 16;
369 offset = (opcode & 0xff) << 2;
371 /* load/store */
372 if (opcode & 0x00100000) {
373 instruction->type = ARM_LDC;
374 mnemonic = "LDC";
375 } else {
376 instruction->type = ARM_STC;
377 mnemonic = "STC";
380 U = (opcode & 0x00800000) >> 23;
382 /* addressing modes */
383 if ((opcode & 0x01200000) == 0x01000000)/* offset */
384 snprintf(addressing_mode, 32, "[r%i, #%s%d]",
385 Rn, U ? "" : "-", offset);
386 else if ((opcode & 0x01200000) == 0x01200000) /* pre-indexed */
387 snprintf(addressing_mode, 32, "[r%i, #%s%d]!",
388 Rn, U ? "" : "-", offset);
389 else if ((opcode & 0x01200000) == 0x00200000) /* post-indexed */
390 snprintf(addressing_mode, 32, "[r%i], #%s%d",
391 Rn, U ? "" : "-", offset);
392 else if ((opcode & 0x01200000) == 0x00000000) /* unindexed */
393 snprintf(addressing_mode, 32, "[r%i], {%d}",
394 Rn, offset >> 2);
396 snprintf(instruction->text, 128, "0x%8.8" PRIx32
397 "\t0x%8.8" PRIx32
398 "\t%s%s%s p%i, c%i, %s",
399 address, opcode, mnemonic,
400 ((opcode & 0xf0000000) == 0xf0000000)
401 ? "2" : COND(opcode),
402 (opcode & (1 << 22)) ? "L" : "",
403 cp_num, CRd, addressing_mode);
406 return ERROR_OK;
409 /* Coprocessor data processing instructions
410 * Coprocessor register transfer instructions
411 * both normal and extended instruction space (condition field b1111) */
412 static int evaluate_cdp_mcr_mrc(uint32_t opcode,
413 uint32_t address, struct arm_instruction *instruction)
415 const char *cond;
416 char *mnemonic;
417 uint8_t cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2;
419 cond = ((opcode & 0xf0000000) == 0xf0000000) ? "2" : COND(opcode);
420 cp_num = (opcode & 0xf00) >> 8;
421 CRd_Rd = (opcode & 0xf000) >> 12;
422 CRn = (opcode & 0xf0000) >> 16;
423 CRm = (opcode & 0xf);
424 opcode_2 = (opcode & 0xe0) >> 5;
426 /* CDP or MRC/MCR */
427 if (opcode & 0x00000010) { /* bit 4 set -> MRC/MCR */
428 if (opcode & 0x00100000) { /* bit 20 set -> MRC */
429 instruction->type = ARM_MRC;
430 mnemonic = "MRC";
431 } else {/* bit 20 not set -> MCR */
432 instruction->type = ARM_MCR;
433 mnemonic = "MCR";
436 opcode_1 = (opcode & 0x00e00000) >> 21;
438 snprintf(instruction->text,
439 128,
440 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, 0x%2.2x, r%i, c%i, c%i, 0x%2.2x",
441 address,
442 opcode,
443 mnemonic,
444 cond,
445 cp_num,
446 opcode_1,
447 CRd_Rd,
448 CRn,
449 CRm,
450 opcode_2);
451 } else {/* bit 4 not set -> CDP */
452 instruction->type = ARM_CDP;
453 mnemonic = "CDP";
455 opcode_1 = (opcode & 0x00f00000) >> 20;
457 snprintf(instruction->text,
458 128,
459 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, 0x%2.2x, c%i, c%i, c%i, 0x%2.2x",
460 address,
461 opcode,
462 mnemonic,
463 cond,
464 cp_num,
465 opcode_1,
466 CRd_Rd,
467 CRn,
468 CRm,
469 opcode_2);
472 return ERROR_OK;
475 /* Load/store instructions */
476 static int evaluate_load_store(uint32_t opcode,
477 uint32_t address, struct arm_instruction *instruction)
479 uint8_t I, P, U, B, W, L;
480 uint8_t Rn, Rd;
481 char *operation;/* "LDR" or "STR" */
482 char *suffix; /* "", "B", "T", "BT" */
483 char offset[32];
485 /* examine flags */
486 I = (opcode & 0x02000000) >> 25;
487 P = (opcode & 0x01000000) >> 24;
488 U = (opcode & 0x00800000) >> 23;
489 B = (opcode & 0x00400000) >> 22;
490 W = (opcode & 0x00200000) >> 21;
491 L = (opcode & 0x00100000) >> 20;
493 /* target register */
494 Rd = (opcode & 0xf000) >> 12;
496 /* base register */
497 Rn = (opcode & 0xf0000) >> 16;
499 instruction->info.load_store.Rd = Rd;
500 instruction->info.load_store.Rn = Rn;
501 instruction->info.load_store.U = U;
503 /* determine operation */
504 if (L)
505 operation = "LDR";
506 else
507 operation = "STR";
509 /* determine instruction type and suffix */
510 if (B) {
511 if ((P == 0) && (W == 1)) {
512 if (L)
513 instruction->type = ARM_LDRBT;
514 else
515 instruction->type = ARM_STRBT;
516 suffix = "BT";
517 } else {
518 if (L)
519 instruction->type = ARM_LDRB;
520 else
521 instruction->type = ARM_STRB;
522 suffix = "B";
524 } else {
525 if ((P == 0) && (W == 1)) {
526 if (L)
527 instruction->type = ARM_LDRT;
528 else
529 instruction->type = ARM_STRT;
530 suffix = "T";
531 } else {
532 if (L)
533 instruction->type = ARM_LDR;
534 else
535 instruction->type = ARM_STR;
536 suffix = "";
540 if (!I) { /* #+-<offset_12> */
541 uint32_t offset_12 = (opcode & 0xfff);
542 if (offset_12)
543 snprintf(offset, 32, ", #%s0x%" PRIx32 "", (U) ? "" : "-", offset_12);
544 else
545 snprintf(offset, 32, "%s", "");
547 instruction->info.load_store.offset_mode = 0;
548 instruction->info.load_store.offset.offset = offset_12;
549 } else {/* either +-<Rm> or +-<Rm>, <shift>, #<shift_imm> */
550 uint8_t shift_imm, shift;
551 uint8_t Rm;
553 shift_imm = (opcode & 0xf80) >> 7;
554 shift = (opcode & 0x60) >> 5;
555 Rm = (opcode & 0xf);
557 /* LSR encodes a shift by 32 bit as 0x0 */
558 if ((shift == 0x1) && (shift_imm == 0x0))
559 shift_imm = 0x20;
561 /* ASR encodes a shift by 32 bit as 0x0 */
562 if ((shift == 0x2) && (shift_imm == 0x0))
563 shift_imm = 0x20;
565 /* ROR by 32 bit is actually a RRX */
566 if ((shift == 0x3) && (shift_imm == 0x0))
567 shift = 0x4;
569 instruction->info.load_store.offset_mode = 1;
570 instruction->info.load_store.offset.reg.Rm = Rm;
571 instruction->info.load_store.offset.reg.shift = shift;
572 instruction->info.load_store.offset.reg.shift_imm = shift_imm;
574 if ((shift_imm == 0x0) && (shift == 0x0)) /* +-<Rm> */
575 snprintf(offset, 32, ", %sr%i", (U) ? "" : "-", Rm);
576 else { /* +-<Rm>, <Shift>, #<shift_imm> */
577 switch (shift) {
578 case 0x0: /* LSL */
579 snprintf(offset, 32, ", %sr%i, LSL #0x%x", (U) ? "" : "-", Rm, shift_imm);
580 break;
581 case 0x1: /* LSR */
582 snprintf(offset, 32, ", %sr%i, LSR #0x%x", (U) ? "" : "-", Rm, shift_imm);
583 break;
584 case 0x2: /* ASR */
585 snprintf(offset, 32, ", %sr%i, ASR #0x%x", (U) ? "" : "-", Rm, shift_imm);
586 break;
587 case 0x3: /* ROR */
588 snprintf(offset, 32, ", %sr%i, ROR #0x%x", (U) ? "" : "-", Rm, shift_imm);
589 break;
590 case 0x4: /* RRX */
591 snprintf(offset, 32, ", %sr%i, RRX", (U) ? "" : "-", Rm);
592 break;
597 if (P == 1) {
598 if (W == 0) { /* offset */
599 snprintf(instruction->text,
600 128,
601 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]",
602 address,
603 opcode,
604 operation,
605 COND(opcode),
606 suffix,
609 offset);
611 instruction->info.load_store.index_mode = 0;
612 } else {/* pre-indexed */
613 snprintf(instruction->text,
614 128,
615 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]!",
616 address,
617 opcode,
618 operation,
619 COND(opcode),
620 suffix,
623 offset);
625 instruction->info.load_store.index_mode = 1;
627 } else {/* post-indexed */
628 snprintf(instruction->text,
629 128,
630 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i]%s",
631 address,
632 opcode,
633 operation,
634 COND(opcode),
635 suffix,
638 offset);
640 instruction->info.load_store.index_mode = 2;
643 return ERROR_OK;
646 static int evaluate_extend(uint32_t opcode, uint32_t address, char *cp)
648 unsigned rm = (opcode >> 0) & 0xf;
649 unsigned rd = (opcode >> 12) & 0xf;
650 unsigned rn = (opcode >> 16) & 0xf;
651 char *type, *rot;
653 switch ((opcode >> 24) & 0x3) {
654 case 0:
655 type = "B16";
656 break;
657 case 1:
658 sprintf(cp, "UNDEFINED");
659 return ARM_UNDEFINED_INSTRUCTION;
660 case 2:
661 type = "B";
662 break;
663 default:
664 type = "H";
665 break;
668 switch ((opcode >> 10) & 0x3) {
669 case 0:
670 rot = "";
671 break;
672 case 1:
673 rot = ", ROR #8";
674 break;
675 case 2:
676 rot = ", ROR #16";
677 break;
678 default:
679 rot = ", ROR #24";
680 break;
683 if (rn == 0xf) {
684 sprintf(cp, "%cXT%s%s\tr%d, r%d%s",
685 (opcode & (1 << 22)) ? 'U' : 'S',
686 type, COND(opcode),
687 rd, rm, rot);
688 return ARM_MOV;
689 } else {
690 sprintf(cp, "%cXTA%s%s\tr%d, r%d, r%d%s",
691 (opcode & (1 << 22)) ? 'U' : 'S',
692 type, COND(opcode),
693 rd, rn, rm, rot);
694 return ARM_ADD;
698 static int evaluate_p_add_sub(uint32_t opcode, uint32_t address, char *cp)
700 char *prefix;
701 char *op;
702 int type;
704 switch ((opcode >> 20) & 0x7) {
705 case 1:
706 prefix = "S";
707 break;
708 case 2:
709 prefix = "Q";
710 break;
711 case 3:
712 prefix = "SH";
713 break;
714 case 5:
715 prefix = "U";
716 break;
717 case 6:
718 prefix = "UQ";
719 break;
720 case 7:
721 prefix = "UH";
722 break;
723 default:
724 goto undef;
727 switch ((opcode >> 5) & 0x7) {
728 case 0:
729 op = "ADD16";
730 type = ARM_ADD;
731 break;
732 case 1:
733 op = "ADDSUBX";
734 type = ARM_ADD;
735 break;
736 case 2:
737 op = "SUBADDX";
738 type = ARM_SUB;
739 break;
740 case 3:
741 op = "SUB16";
742 type = ARM_SUB;
743 break;
744 case 4:
745 op = "ADD8";
746 type = ARM_ADD;
747 break;
748 case 7:
749 op = "SUB8";
750 type = ARM_SUB;
751 break;
752 default:
753 goto undef;
756 sprintf(cp, "%s%s%s\tr%d, r%d, r%d", prefix, op, COND(opcode),
757 (int) (opcode >> 12) & 0xf,
758 (int) (opcode >> 16) & 0xf,
759 (int) (opcode >> 0) & 0xf);
760 return type;
762 undef:
763 /* these opcodes might be used someday */
764 sprintf(cp, "UNDEFINED");
765 return ARM_UNDEFINED_INSTRUCTION;
768 /* ARMv6 and later support "media" instructions (includes SIMD) */
769 static int evaluate_media(uint32_t opcode, uint32_t address,
770 struct arm_instruction *instruction)
772 char *cp = instruction->text;
773 char *mnemonic = NULL;
775 sprintf(cp,
776 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t",
777 address, opcode);
778 cp = strchr(cp, 0);
780 /* parallel add/subtract */
781 if ((opcode & 0x01800000) == 0x00000000) {
782 instruction->type = evaluate_p_add_sub(opcode, address, cp);
783 return ERROR_OK;
786 /* halfword pack */
787 if ((opcode & 0x01f00020) == 0x00800000) {
788 char *type, *shift;
789 unsigned imm = (unsigned) (opcode >> 7) & 0x1f;
791 if (opcode & (1 << 6)) {
792 type = "TB";
793 shift = "ASR";
794 if (imm == 0)
795 imm = 32;
796 } else {
797 type = "BT";
798 shift = "LSL";
800 sprintf(cp, "PKH%s%s\tr%d, r%d, r%d, %s #%d",
801 type, COND(opcode),
802 (int) (opcode >> 12) & 0xf,
803 (int) (opcode >> 16) & 0xf,
804 (int) (opcode >> 0) & 0xf,
805 shift, imm);
806 return ERROR_OK;
809 /* word saturate */
810 if ((opcode & 0x01a00020) == 0x00a00000) {
811 char *shift;
812 unsigned imm = (unsigned) (opcode >> 7) & 0x1f;
814 if (opcode & (1 << 6)) {
815 shift = "ASR";
816 if (imm == 0)
817 imm = 32;
818 } else
819 shift = "LSL";
821 sprintf(cp, "%cSAT%s\tr%d, #%d, r%d, %s #%d",
822 (opcode & (1 << 22)) ? 'U' : 'S',
823 COND(opcode),
824 (int) (opcode >> 12) & 0xf,
825 (int) (opcode >> 16) & 0x1f,
826 (int) (opcode >> 0) & 0xf,
827 shift, imm);
828 return ERROR_OK;
831 /* sign extension */
832 if ((opcode & 0x018000f0) == 0x00800070) {
833 instruction->type = evaluate_extend(opcode, address, cp);
834 return ERROR_OK;
837 /* multiplies */
838 if ((opcode & 0x01f00080) == 0x01000000) {
839 unsigned rn = (opcode >> 12) & 0xf;
841 if (rn != 0xf)
842 sprintf(cp, "SML%cD%s%s\tr%d, r%d, r%d, r%d",
843 (opcode & (1 << 6)) ? 'S' : 'A',
844 (opcode & (1 << 5)) ? "X" : "",
845 COND(opcode),
846 (int) (opcode >> 16) & 0xf,
847 (int) (opcode >> 0) & 0xf,
848 (int) (opcode >> 8) & 0xf,
849 rn);
850 else
851 sprintf(cp, "SMU%cD%s%s\tr%d, r%d, r%d",
852 (opcode & (1 << 6)) ? 'S' : 'A',
853 (opcode & (1 << 5)) ? "X" : "",
854 COND(opcode),
855 (int) (opcode >> 16) & 0xf,
856 (int) (opcode >> 0) & 0xf,
857 (int) (opcode >> 8) & 0xf);
858 return ERROR_OK;
860 if ((opcode & 0x01f00000) == 0x01400000) {
861 sprintf(cp, "SML%cLD%s%s\tr%d, r%d, r%d, r%d",
862 (opcode & (1 << 6)) ? 'S' : 'A',
863 (opcode & (1 << 5)) ? "X" : "",
864 COND(opcode),
865 (int) (opcode >> 12) & 0xf,
866 (int) (opcode >> 16) & 0xf,
867 (int) (opcode >> 0) & 0xf,
868 (int) (opcode >> 8) & 0xf);
869 return ERROR_OK;
871 if ((opcode & 0x01f00000) == 0x01500000) {
872 unsigned rn = (opcode >> 12) & 0xf;
874 switch (opcode & 0xc0) {
875 case 3:
876 if (rn == 0xf)
877 goto undef;
878 /* FALL THROUGH */
879 case 0:
880 break;
881 default:
882 goto undef;
885 if (rn != 0xf)
886 sprintf(cp, "SMML%c%s%s\tr%d, r%d, r%d, r%d",
887 (opcode & (1 << 6)) ? 'S' : 'A',
888 (opcode & (1 << 5)) ? "R" : "",
889 COND(opcode),
890 (int) (opcode >> 16) & 0xf,
891 (int) (opcode >> 0) & 0xf,
892 (int) (opcode >> 8) & 0xf,
893 rn);
894 else
895 sprintf(cp, "SMMUL%s%s\tr%d, r%d, r%d",
896 (opcode & (1 << 5)) ? "R" : "",
897 COND(opcode),
898 (int) (opcode >> 16) & 0xf,
899 (int) (opcode >> 0) & 0xf,
900 (int) (opcode >> 8) & 0xf);
901 return ERROR_OK;
904 /* simple matches against the remaining decode bits */
905 switch (opcode & 0x01f000f0) {
906 case 0x00a00030:
907 case 0x00e00030:
908 /* parallel halfword saturate */
909 sprintf(cp, "%cSAT16%s\tr%d, #%d, r%d",
910 (opcode & (1 << 22)) ? 'U' : 'S',
911 COND(opcode),
912 (int) (opcode >> 12) & 0xf,
913 (int) (opcode >> 16) & 0xf,
914 (int) (opcode >> 0) & 0xf);
915 return ERROR_OK;
916 case 0x00b00030:
917 mnemonic = "REV";
918 break;
919 case 0x00b000b0:
920 mnemonic = "REV16";
921 break;
922 case 0x00f000b0:
923 mnemonic = "REVSH";
924 break;
925 case 0x008000b0:
926 /* select bytes */
927 sprintf(cp, "SEL%s\tr%d, r%d, r%d", COND(opcode),
928 (int) (opcode >> 12) & 0xf,
929 (int) (opcode >> 16) & 0xf,
930 (int) (opcode >> 0) & 0xf);
931 return ERROR_OK;
932 case 0x01800010:
933 /* unsigned sum of absolute differences */
934 if (((opcode >> 12) & 0xf) == 0xf)
935 sprintf(cp, "USAD8%s\tr%d, r%d, r%d", COND(opcode),
936 (int) (opcode >> 16) & 0xf,
937 (int) (opcode >> 0) & 0xf,
938 (int) (opcode >> 8) & 0xf);
939 else
940 sprintf(cp, "USADA8%s\tr%d, r%d, r%d, r%d", COND(opcode),
941 (int) (opcode >> 16) & 0xf,
942 (int) (opcode >> 0) & 0xf,
943 (int) (opcode >> 8) & 0xf,
944 (int) (opcode >> 12) & 0xf);
945 return ERROR_OK;
947 if (mnemonic) {
948 unsigned rm = (opcode >> 0) & 0xf;
949 unsigned rd = (opcode >> 12) & 0xf;
951 sprintf(cp, "%s%s\tr%d, r%d", mnemonic, COND(opcode), rm, rd);
952 return ERROR_OK;
955 undef:
956 /* these opcodes might be used someday */
957 sprintf(cp, "UNDEFINED");
958 return ERROR_OK;
961 /* Miscellaneous load/store instructions */
962 static int evaluate_misc_load_store(uint32_t opcode,
963 uint32_t address, struct arm_instruction *instruction)
965 uint8_t P, U, I, W, L, S, H;
966 uint8_t Rn, Rd;
967 char *operation;/* "LDR" or "STR" */
968 char *suffix; /* "H", "SB", "SH", "D" */
969 char offset[32];
971 /* examine flags */
972 P = (opcode & 0x01000000) >> 24;
973 U = (opcode & 0x00800000) >> 23;
974 I = (opcode & 0x00400000) >> 22;
975 W = (opcode & 0x00200000) >> 21;
976 L = (opcode & 0x00100000) >> 20;
977 S = (opcode & 0x00000040) >> 6;
978 H = (opcode & 0x00000020) >> 5;
980 /* target register */
981 Rd = (opcode & 0xf000) >> 12;
983 /* base register */
984 Rn = (opcode & 0xf0000) >> 16;
986 instruction->info.load_store.Rd = Rd;
987 instruction->info.load_store.Rn = Rn;
988 instruction->info.load_store.U = U;
990 /* determine instruction type and suffix */
991 if (S) {/* signed */
992 if (L) {/* load */
993 if (H) {
994 operation = "LDR";
995 instruction->type = ARM_LDRSH;
996 suffix = "SH";
997 } else {
998 operation = "LDR";
999 instruction->type = ARM_LDRSB;
1000 suffix = "SB";
1002 } else {/* there are no signed stores, so this is used to encode double-register
1003 *load/stores */
1004 suffix = "D";
1005 if (H) {
1006 operation = "STR";
1007 instruction->type = ARM_STRD;
1008 } else {
1009 operation = "LDR";
1010 instruction->type = ARM_LDRD;
1013 } else {/* unsigned */
1014 suffix = "H";
1015 if (L) {/* load */
1016 operation = "LDR";
1017 instruction->type = ARM_LDRH;
1018 } else {/* store */
1019 operation = "STR";
1020 instruction->type = ARM_STRH;
1024 if (I) {/* Immediate offset/index (#+-<offset_8>)*/
1025 uint32_t offset_8 = ((opcode & 0xf00) >> 4) | (opcode & 0xf);
1026 snprintf(offset, 32, "#%s0x%" PRIx32 "", (U) ? "" : "-", offset_8);
1028 instruction->info.load_store.offset_mode = 0;
1029 instruction->info.load_store.offset.offset = offset_8;
1030 } else {/* Register offset/index (+-<Rm>) */
1031 uint8_t Rm;
1032 Rm = (opcode & 0xf);
1033 snprintf(offset, 32, "%sr%i", (U) ? "" : "-", Rm);
1035 instruction->info.load_store.offset_mode = 1;
1036 instruction->info.load_store.offset.reg.Rm = Rm;
1037 instruction->info.load_store.offset.reg.shift = 0x0;
1038 instruction->info.load_store.offset.reg.shift_imm = 0x0;
1041 if (P == 1) {
1042 if (W == 0) { /* offset */
1043 snprintf(instruction->text,
1044 128,
1045 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]",
1046 address,
1047 opcode,
1048 operation,
1049 COND(opcode),
1050 suffix,
1053 offset);
1055 instruction->info.load_store.index_mode = 0;
1056 } else {/* pre-indexed */
1057 snprintf(instruction->text,
1058 128,
1059 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]!",
1060 address,
1061 opcode,
1062 operation,
1063 COND(opcode),
1064 suffix,
1067 offset);
1069 instruction->info.load_store.index_mode = 1;
1071 } else {/* post-indexed */
1072 snprintf(instruction->text,
1073 128,
1074 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i], %s",
1075 address,
1076 opcode,
1077 operation,
1078 COND(opcode),
1079 suffix,
1082 offset);
1084 instruction->info.load_store.index_mode = 2;
1087 return ERROR_OK;
1090 /* Load/store multiples instructions */
1091 static int evaluate_ldm_stm(uint32_t opcode,
1092 uint32_t address, struct arm_instruction *instruction)
1094 uint8_t P, U, S, W, L, Rn;
1095 uint32_t register_list;
1096 char *addressing_mode;
1097 char *mnemonic;
1098 char reg_list[69];
1099 char *reg_list_p;
1100 int i;
1101 int first_reg = 1;
1103 P = (opcode & 0x01000000) >> 24;
1104 U = (opcode & 0x00800000) >> 23;
1105 S = (opcode & 0x00400000) >> 22;
1106 W = (opcode & 0x00200000) >> 21;
1107 L = (opcode & 0x00100000) >> 20;
1108 register_list = (opcode & 0xffff);
1109 Rn = (opcode & 0xf0000) >> 16;
1111 instruction->info.load_store_multiple.Rn = Rn;
1112 instruction->info.load_store_multiple.register_list = register_list;
1113 instruction->info.load_store_multiple.S = S;
1114 instruction->info.load_store_multiple.W = W;
1116 if (L) {
1117 instruction->type = ARM_LDM;
1118 mnemonic = "LDM";
1119 } else {
1120 instruction->type = ARM_STM;
1121 mnemonic = "STM";
1124 if (P) {
1125 if (U) {
1126 instruction->info.load_store_multiple.addressing_mode = 1;
1127 addressing_mode = "IB";
1128 } else {
1129 instruction->info.load_store_multiple.addressing_mode = 3;
1130 addressing_mode = "DB";
1132 } else {
1133 if (U) {
1134 instruction->info.load_store_multiple.addressing_mode = 0;
1135 /* "IA" is the default in UAL syntax */
1136 addressing_mode = "";
1137 } else {
1138 instruction->info.load_store_multiple.addressing_mode = 2;
1139 addressing_mode = "DA";
1143 reg_list_p = reg_list;
1144 for (i = 0; i <= 15; i++) {
1145 if ((register_list >> i) & 1) {
1146 if (first_reg) {
1147 first_reg = 0;
1148 reg_list_p += snprintf(reg_list_p,
1149 (reg_list + 69 - reg_list_p),
1150 "r%i",
1152 } else
1153 reg_list_p += snprintf(reg_list_p,
1154 (reg_list + 69 - reg_list_p),
1155 ", r%i",
1160 snprintf(instruction->text, 128,
1161 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
1162 "\t%s%s%s r%i%s, {%s}%s",
1163 address, opcode,
1164 mnemonic, addressing_mode, COND(opcode),
1165 Rn, (W) ? "!" : "", reg_list, (S) ? "^" : "");
1167 return ERROR_OK;
1170 /* Multiplies, extra load/stores */
1171 static int evaluate_mul_and_extra_ld_st(uint32_t opcode,
1172 uint32_t address, struct arm_instruction *instruction)
1174 /* Multiply (accumulate) (long) and Swap/swap byte */
1175 if ((opcode & 0x000000f0) == 0x00000090) {
1176 /* Multiply (accumulate) */
1177 if ((opcode & 0x0f800000) == 0x00000000) {
1178 uint8_t Rm, Rs, Rn, Rd, S;
1179 Rm = opcode & 0xf;
1180 Rs = (opcode & 0xf00) >> 8;
1181 Rn = (opcode & 0xf000) >> 12;
1182 Rd = (opcode & 0xf0000) >> 16;
1183 S = (opcode & 0x00100000) >> 20;
1185 /* examine A bit (accumulate) */
1186 if (opcode & 0x00200000) {
1187 instruction->type = ARM_MLA;
1188 snprintf(instruction->text,
1189 128,
1190 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMLA%s%s r%i, r%i, r%i, r%i",
1191 address,
1192 opcode,
1193 COND(opcode),
1194 (S) ? "S" : "",
1198 Rn);
1199 } else {
1200 instruction->type = ARM_MUL;
1201 snprintf(instruction->text,
1202 128,
1203 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMUL%s%s r%i, r%i, r%i",
1204 address,
1205 opcode,
1206 COND(opcode),
1207 (S) ? "S" : "",
1210 Rs);
1213 return ERROR_OK;
1216 /* Multiply (accumulate) long */
1217 if ((opcode & 0x0f800000) == 0x00800000) {
1218 char *mnemonic = NULL;
1219 uint8_t Rm, Rs, RdHi, RdLow, S;
1220 Rm = opcode & 0xf;
1221 Rs = (opcode & 0xf00) >> 8;
1222 RdHi = (opcode & 0xf000) >> 12;
1223 RdLow = (opcode & 0xf0000) >> 16;
1224 S = (opcode & 0x00100000) >> 20;
1226 switch ((opcode & 0x00600000) >> 21) {
1227 case 0x0:
1228 instruction->type = ARM_UMULL;
1229 mnemonic = "UMULL";
1230 break;
1231 case 0x1:
1232 instruction->type = ARM_UMLAL;
1233 mnemonic = "UMLAL";
1234 break;
1235 case 0x2:
1236 instruction->type = ARM_SMULL;
1237 mnemonic = "SMULL";
1238 break;
1239 case 0x3:
1240 instruction->type = ARM_SMLAL;
1241 mnemonic = "SMLAL";
1242 break;
1245 snprintf(instruction->text,
1246 128,
1247 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, r%i, r%i",
1248 address,
1249 opcode,
1250 mnemonic,
1251 COND(opcode),
1252 (S) ? "S" : "",
1253 RdLow,
1254 RdHi,
1256 Rs);
1258 return ERROR_OK;
1261 /* Swap/swap byte */
1262 if ((opcode & 0x0f800000) == 0x01000000) {
1263 uint8_t Rm, Rd, Rn;
1264 Rm = opcode & 0xf;
1265 Rd = (opcode & 0xf000) >> 12;
1266 Rn = (opcode & 0xf0000) >> 16;
1268 /* examine B flag */
1269 instruction->type = (opcode & 0x00400000) ? ARM_SWPB : ARM_SWP;
1271 snprintf(instruction->text,
1272 128,
1273 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, [r%i]",
1274 address,
1275 opcode,
1276 (opcode & 0x00400000) ? "SWPB" : "SWP",
1277 COND(opcode),
1280 Rn);
1281 return ERROR_OK;
1286 return evaluate_misc_load_store(opcode, address, instruction);
1289 static int evaluate_mrs_msr(uint32_t opcode,
1290 uint32_t address, struct arm_instruction *instruction)
1292 int R = (opcode & 0x00400000) >> 22;
1293 char *PSR = (R) ? "SPSR" : "CPSR";
1295 /* Move register to status register (MSR) */
1296 if (opcode & 0x00200000) {
1297 instruction->type = ARM_MSR;
1299 /* immediate variant */
1300 if (opcode & 0x02000000) {
1301 uint8_t immediate = (opcode & 0xff);
1302 uint8_t rotate = (opcode & 0xf00);
1304 snprintf(instruction->text,
1305 128,
1306 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, 0x%8.8" PRIx32,
1307 address,
1308 opcode,
1309 COND(opcode),
1310 PSR,
1311 (opcode & 0x10000) ? "c" : "",
1312 (opcode & 0x20000) ? "x" : "",
1313 (opcode & 0x40000) ? "s" : "",
1314 (opcode & 0x80000) ? "f" : "",
1315 ror(immediate, (rotate * 2))
1317 } else {/* register variant */
1318 uint8_t Rm = opcode & 0xf;
1319 snprintf(instruction->text,
1320 128,
1321 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, r%i",
1322 address,
1323 opcode,
1324 COND(opcode),
1325 PSR,
1326 (opcode & 0x10000) ? "c" : "",
1327 (opcode & 0x20000) ? "x" : "",
1328 (opcode & 0x40000) ? "s" : "",
1329 (opcode & 0x80000) ? "f" : "",
1334 } else {/* Move status register to register (MRS) */
1335 uint8_t Rd;
1337 instruction->type = ARM_MRS;
1338 Rd = (opcode & 0x0000f000) >> 12;
1340 snprintf(instruction->text,
1341 128,
1342 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMRS%s r%i, %s",
1343 address,
1344 opcode,
1345 COND(opcode),
1347 PSR);
1350 return ERROR_OK;
1353 /* Miscellaneous instructions */
1354 static int evaluate_misc_instr(uint32_t opcode,
1355 uint32_t address, struct arm_instruction *instruction)
1357 /* MRS/MSR */
1358 if ((opcode & 0x000000f0) == 0x00000000)
1359 evaluate_mrs_msr(opcode, address, instruction);
1361 /* BX */
1362 if ((opcode & 0x006000f0) == 0x00200010) {
1363 uint8_t Rm;
1364 instruction->type = ARM_BX;
1365 Rm = opcode & 0xf;
1367 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBX%s r%i",
1368 address, opcode, COND(opcode), Rm);
1370 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1371 instruction->info.b_bl_bx_blx.target_address = -1;
1374 /* BXJ - "Jazelle" support (ARMv5-J) */
1375 if ((opcode & 0x006000f0) == 0x00200020) {
1376 uint8_t Rm;
1377 instruction->type = ARM_BX;
1378 Rm = opcode & 0xf;
1380 snprintf(instruction->text, 128,
1381 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBXJ%s r%i",
1382 address, opcode, COND(opcode), Rm);
1384 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1385 instruction->info.b_bl_bx_blx.target_address = -1;
1388 /* CLZ */
1389 if ((opcode & 0x006000f0) == 0x00600010) {
1390 uint8_t Rm, Rd;
1391 instruction->type = ARM_CLZ;
1392 Rm = opcode & 0xf;
1393 Rd = (opcode & 0xf000) >> 12;
1395 snprintf(instruction->text,
1396 128,
1397 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCLZ%s r%i, r%i",
1398 address,
1399 opcode,
1400 COND(opcode),
1402 Rm);
1405 /* BLX(2) */
1406 if ((opcode & 0x006000f0) == 0x00200030) {
1407 uint8_t Rm;
1408 instruction->type = ARM_BLX;
1409 Rm = opcode & 0xf;
1411 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX%s r%i",
1412 address, opcode, COND(opcode), Rm);
1414 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1415 instruction->info.b_bl_bx_blx.target_address = -1;
1418 /* Enhanced DSP add/subtracts */
1419 if ((opcode & 0x0000000f0) == 0x00000050) {
1420 uint8_t Rm, Rd, Rn;
1421 char *mnemonic = NULL;
1422 Rm = opcode & 0xf;
1423 Rd = (opcode & 0xf000) >> 12;
1424 Rn = (opcode & 0xf0000) >> 16;
1426 switch ((opcode & 0x00600000) >> 21) {
1427 case 0x0:
1428 instruction->type = ARM_QADD;
1429 mnemonic = "QADD";
1430 break;
1431 case 0x1:
1432 instruction->type = ARM_QSUB;
1433 mnemonic = "QSUB";
1434 break;
1435 case 0x2:
1436 instruction->type = ARM_QDADD;
1437 mnemonic = "QDADD";
1438 break;
1439 case 0x3:
1440 instruction->type = ARM_QDSUB;
1441 mnemonic = "QDSUB";
1442 break;
1445 snprintf(instruction->text,
1446 128,
1447 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, r%i",
1448 address,
1449 opcode,
1450 mnemonic,
1451 COND(opcode),
1454 Rn);
1457 /* exception return */
1458 if ((opcode & 0x0000000f0) == 0x00000060) {
1459 if (((opcode & 0x600000) >> 21) == 3)
1460 instruction->type = ARM_ERET;
1461 snprintf(instruction->text,
1462 128,
1463 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tERET",
1464 address,
1465 opcode);
1468 /* exception generate instructions */
1469 if ((opcode & 0x0000000f0) == 0x00000070) {
1470 uint32_t immediate = 0;
1471 char *mnemonic = NULL;
1473 switch ((opcode & 0x600000) >> 21) {
1474 case 0x1:
1475 instruction->type = ARM_BKPT;
1476 mnemonic = "BRKT";
1477 immediate = ((opcode & 0x000fff00) >> 4) | (opcode & 0xf);
1478 break;
1479 case 0x2:
1480 instruction->type = ARM_HVC;
1481 mnemonic = "HVC";
1482 immediate = ((opcode & 0x000fff00) >> 4) | (opcode & 0xf);
1483 break;
1484 case 0x3:
1485 instruction->type = ARM_SMC;
1486 mnemonic = "SMC";
1487 immediate = (opcode & 0xf);
1488 break;
1491 snprintf(instruction->text,
1492 128,
1493 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s 0x%4.4" PRIx32 "",
1494 address,
1495 opcode,
1496 mnemonic,
1497 immediate);
1500 /* Enhanced DSP multiplies */
1501 if ((opcode & 0x000000090) == 0x00000080) {
1502 int x = (opcode & 0x20) >> 5;
1503 int y = (opcode & 0x40) >> 6;
1505 /* SMLA < x><y> */
1506 if ((opcode & 0x00600000) == 0x00000000) {
1507 uint8_t Rd, Rm, Rs, Rn;
1508 instruction->type = ARM_SMLAxy;
1509 Rd = (opcode & 0xf0000) >> 16;
1510 Rm = (opcode & 0xf);
1511 Rs = (opcode & 0xf00) >> 8;
1512 Rn = (opcode & 0xf000) >> 12;
1514 snprintf(instruction->text,
1515 128,
1516 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
1517 address,
1518 opcode,
1519 (x) ? "T" : "B",
1520 (y) ? "T" : "B",
1521 COND(opcode),
1525 Rn);
1528 /* SMLAL < x><y> */
1529 if ((opcode & 0x00600000) == 0x00400000) {
1530 uint8_t RdLow, RdHi, Rm, Rs;
1531 instruction->type = ARM_SMLAxy;
1532 RdHi = (opcode & 0xf0000) >> 16;
1533 RdLow = (opcode & 0xf000) >> 12;
1534 Rm = (opcode & 0xf);
1535 Rs = (opcode & 0xf00) >> 8;
1537 snprintf(instruction->text,
1538 128,
1539 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
1540 address,
1541 opcode,
1542 (x) ? "T" : "B",
1543 (y) ? "T" : "B",
1544 COND(opcode),
1545 RdLow,
1546 RdHi,
1548 Rs);
1551 /* SMLAW < y> */
1552 if (((opcode & 0x00600000) == 0x00100000) && (x == 0)) {
1553 uint8_t Rd, Rm, Rs, Rn;
1554 instruction->type = ARM_SMLAWy;
1555 Rd = (opcode & 0xf0000) >> 16;
1556 Rm = (opcode & 0xf);
1557 Rs = (opcode & 0xf00) >> 8;
1558 Rn = (opcode & 0xf000) >> 12;
1560 snprintf(instruction->text,
1561 128,
1562 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLAW%s%s r%i, r%i, r%i, r%i",
1563 address,
1564 opcode,
1565 (y) ? "T" : "B",
1566 COND(opcode),
1570 Rn);
1573 /* SMUL < x><y> */
1574 if ((opcode & 0x00600000) == 0x00300000) {
1575 uint8_t Rd, Rm, Rs;
1576 instruction->type = ARM_SMULxy;
1577 Rd = (opcode & 0xf0000) >> 16;
1578 Rm = (opcode & 0xf);
1579 Rs = (opcode & 0xf00) >> 8;
1581 snprintf(instruction->text,
1582 128,
1583 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s%s r%i, r%i, r%i",
1584 address,
1585 opcode,
1586 (x) ? "T" : "B",
1587 (y) ? "T" : "B",
1588 COND(opcode),
1591 Rs);
1594 /* SMULW < y> */
1595 if (((opcode & 0x00600000) == 0x00100000) && (x == 1)) {
1596 uint8_t Rd, Rm, Rs;
1597 instruction->type = ARM_SMULWy;
1598 Rd = (opcode & 0xf0000) >> 16;
1599 Rm = (opcode & 0xf);
1600 Rs = (opcode & 0xf00) >> 8;
1602 snprintf(instruction->text,
1603 128,
1604 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s r%i, r%i, r%i",
1605 address,
1606 opcode,
1607 (y) ? "T" : "B",
1608 COND(opcode),
1611 Rs);
1615 return ERROR_OK;
1618 static int evaluate_mov_imm(uint32_t opcode,
1619 uint32_t address, struct arm_instruction *instruction)
1621 uint16_t immediate;
1622 uint8_t Rd;
1623 bool T;
1625 Rd = (opcode & 0xf000) >> 12;
1626 T = opcode & 0x00400000;
1627 immediate = (opcode & 0xf0000) >> 4 | (opcode & 0xfff);
1629 instruction->type = ARM_MOV;
1630 instruction->info.data_proc.Rd = Rd;
1632 snprintf(instruction->text,
1633 128,
1634 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMOV%s%s r%i, #0x%" PRIx16,
1635 address,
1636 opcode,
1637 T ? "T" : "W",
1638 COND(opcode),
1640 immediate);
1642 return ERROR_OK;
1645 static int evaluate_data_proc(uint32_t opcode,
1646 uint32_t address, struct arm_instruction *instruction)
1648 uint8_t I, op, S, Rn, Rd;
1649 char *mnemonic = NULL;
1650 char shifter_operand[32];
1652 I = (opcode & 0x02000000) >> 25;
1653 op = (opcode & 0x01e00000) >> 21;
1654 S = (opcode & 0x00100000) >> 20;
1656 Rd = (opcode & 0xf000) >> 12;
1657 Rn = (opcode & 0xf0000) >> 16;
1659 instruction->info.data_proc.Rd = Rd;
1660 instruction->info.data_proc.Rn = Rn;
1661 instruction->info.data_proc.S = S;
1663 switch (op) {
1664 case 0x0:
1665 instruction->type = ARM_AND;
1666 mnemonic = "AND";
1667 break;
1668 case 0x1:
1669 instruction->type = ARM_EOR;
1670 mnemonic = "EOR";
1671 break;
1672 case 0x2:
1673 instruction->type = ARM_SUB;
1674 mnemonic = "SUB";
1675 break;
1676 case 0x3:
1677 instruction->type = ARM_RSB;
1678 mnemonic = "RSB";
1679 break;
1680 case 0x4:
1681 instruction->type = ARM_ADD;
1682 mnemonic = "ADD";
1683 break;
1684 case 0x5:
1685 instruction->type = ARM_ADC;
1686 mnemonic = "ADC";
1687 break;
1688 case 0x6:
1689 instruction->type = ARM_SBC;
1690 mnemonic = "SBC";
1691 break;
1692 case 0x7:
1693 instruction->type = ARM_RSC;
1694 mnemonic = "RSC";
1695 break;
1696 case 0x8:
1697 instruction->type = ARM_TST;
1698 mnemonic = "TST";
1699 break;
1700 case 0x9:
1701 instruction->type = ARM_TEQ;
1702 mnemonic = "TEQ";
1703 break;
1704 case 0xa:
1705 instruction->type = ARM_CMP;
1706 mnemonic = "CMP";
1707 break;
1708 case 0xb:
1709 instruction->type = ARM_CMN;
1710 mnemonic = "CMN";
1711 break;
1712 case 0xc:
1713 instruction->type = ARM_ORR;
1714 mnemonic = "ORR";
1715 break;
1716 case 0xd:
1717 instruction->type = ARM_MOV;
1718 mnemonic = "MOV";
1719 break;
1720 case 0xe:
1721 instruction->type = ARM_BIC;
1722 mnemonic = "BIC";
1723 break;
1724 case 0xf:
1725 instruction->type = ARM_MVN;
1726 mnemonic = "MVN";
1727 break;
1730 if (I) {/* immediate shifter operand (#<immediate>)*/
1731 uint8_t immed_8 = opcode & 0xff;
1732 uint8_t rotate_imm = (opcode & 0xf00) >> 8;
1733 uint32_t immediate;
1735 immediate = ror(immed_8, rotate_imm * 2);
1737 snprintf(shifter_operand, 32, "#0x%" PRIx32 "", immediate);
1739 instruction->info.data_proc.variant = 0;
1740 instruction->info.data_proc.shifter_operand.immediate.immediate = immediate;
1741 } else {/* register-based shifter operand */
1742 uint8_t shift, Rm;
1743 shift = (opcode & 0x60) >> 5;
1744 Rm = (opcode & 0xf);
1746 if ((opcode & 0x10) != 0x10) { /* Immediate shifts ("<Rm>" or "<Rm>, <shift>
1747 *#<shift_immediate>") */
1748 uint8_t shift_imm;
1749 shift_imm = (opcode & 0xf80) >> 7;
1751 instruction->info.data_proc.variant = 1;
1752 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1753 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm =
1754 shift_imm;
1755 instruction->info.data_proc.shifter_operand.immediate_shift.shift = shift;
1757 /* LSR encodes a shift by 32 bit as 0x0 */
1758 if ((shift == 0x1) && (shift_imm == 0x0))
1759 shift_imm = 0x20;
1761 /* ASR encodes a shift by 32 bit as 0x0 */
1762 if ((shift == 0x2) && (shift_imm == 0x0))
1763 shift_imm = 0x20;
1765 /* ROR by 32 bit is actually a RRX */
1766 if ((shift == 0x3) && (shift_imm == 0x0))
1767 shift = 0x4;
1769 if ((shift_imm == 0x0) && (shift == 0x0))
1770 snprintf(shifter_operand, 32, "r%i", Rm);
1771 else {
1772 if (shift == 0x0) /* LSL */
1773 snprintf(shifter_operand,
1775 "r%i, LSL #0x%x",
1777 shift_imm);
1778 else if (shift == 0x1) /* LSR */
1779 snprintf(shifter_operand,
1781 "r%i, LSR #0x%x",
1783 shift_imm);
1784 else if (shift == 0x2) /* ASR */
1785 snprintf(shifter_operand,
1787 "r%i, ASR #0x%x",
1789 shift_imm);
1790 else if (shift == 0x3) /* ROR */
1791 snprintf(shifter_operand,
1793 "r%i, ROR #0x%x",
1795 shift_imm);
1796 else if (shift == 0x4) /* RRX */
1797 snprintf(shifter_operand, 32, "r%i, RRX", Rm);
1799 } else {/* Register shifts ("<Rm>, <shift> <Rs>") */
1800 uint8_t Rs = (opcode & 0xf00) >> 8;
1802 instruction->info.data_proc.variant = 2;
1803 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rm;
1804 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rs;
1805 instruction->info.data_proc.shifter_operand.register_shift.shift = shift;
1807 if (shift == 0x0) /* LSL */
1808 snprintf(shifter_operand, 32, "r%i, LSL r%i", Rm, Rs);
1809 else if (shift == 0x1) /* LSR */
1810 snprintf(shifter_operand, 32, "r%i, LSR r%i", Rm, Rs);
1811 else if (shift == 0x2) /* ASR */
1812 snprintf(shifter_operand, 32, "r%i, ASR r%i", Rm, Rs);
1813 else if (shift == 0x3) /* ROR */
1814 snprintf(shifter_operand, 32, "r%i, ROR r%i", Rm, Rs);
1818 if ((op < 0x8) || (op == 0xc) || (op == 0xe)) { /* <opcode3>{<cond>}{S} <Rd>, <Rn>,
1819 *<shifter_operand> */
1820 snprintf(instruction->text,
1821 128,
1822 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, %s",
1823 address,
1824 opcode,
1825 mnemonic,
1826 COND(opcode),
1827 (S) ? "S" : "",
1830 shifter_operand);
1831 } else if ((op == 0xd) || (op == 0xf)) { /* <opcode1>{<cond>}{S} <Rd>,
1832 *<shifter_operand> */
1833 if (opcode == 0xe1a00000) /* print MOV r0,r0 as NOP */
1834 snprintf(instruction->text,
1835 128,
1836 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tNOP",
1837 address,
1838 opcode);
1839 else
1840 snprintf(instruction->text,
1841 128,
1842 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, %s",
1843 address,
1844 opcode,
1845 mnemonic,
1846 COND(opcode),
1847 (S) ? "S" : "",
1849 shifter_operand);
1850 } else {/* <opcode2>{<cond>} <Rn>, <shifter_operand> */
1851 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, %s",
1852 address, opcode, mnemonic, COND(opcode),
1853 Rn, shifter_operand);
1856 return ERROR_OK;
1859 int arm_evaluate_opcode(uint32_t opcode, uint32_t address,
1860 struct arm_instruction *instruction)
1862 /* clear fields, to avoid confusion */
1863 memset(instruction, 0, sizeof(struct arm_instruction));
1864 instruction->opcode = opcode;
1865 instruction->instruction_size = 4;
1867 /* catch opcodes with condition field [31:28] = b1111 */
1868 if ((opcode & 0xf0000000) == 0xf0000000) {
1869 /* Undefined instruction (or ARMv5E cache preload PLD) */
1870 if ((opcode & 0x08000000) == 0x00000000)
1871 return evaluate_pld(opcode, address, instruction);
1873 /* Undefined instruction (or ARMv6+ SRS/RFE) */
1874 if ((opcode & 0x0e000000) == 0x08000000)
1875 return evaluate_srs(opcode, address, instruction);
1877 /* Branch and branch with link and change to Thumb */
1878 if ((opcode & 0x0e000000) == 0x0a000000)
1879 return evaluate_blx_imm(opcode, address, instruction);
1881 /* Extended coprocessor opcode space (ARMv5 and higher)
1882 * Coprocessor load/store and double register transfers */
1883 if ((opcode & 0x0e000000) == 0x0c000000)
1884 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1886 /* Coprocessor data processing */
1887 if ((opcode & 0x0f000100) == 0x0c000000)
1888 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1890 /* Coprocessor register transfers */
1891 if ((opcode & 0x0f000010) == 0x0c000010)
1892 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1894 /* Undefined instruction */
1895 if ((opcode & 0x0f000000) == 0x0f000000) {
1896 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1897 snprintf(instruction->text,
1898 128,
1899 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
1900 address,
1901 opcode);
1902 return ERROR_OK;
1906 /* catch opcodes with [27:25] = b000 */
1907 if ((opcode & 0x0e000000) == 0x00000000) {
1908 /* Multiplies, extra load/stores */
1909 if ((opcode & 0x00000090) == 0x00000090)
1910 return evaluate_mul_and_extra_ld_st(opcode, address, instruction);
1912 /* Miscellaneous instructions */
1913 if ((opcode & 0x0f900000) == 0x01000000)
1914 return evaluate_misc_instr(opcode, address, instruction);
1916 return evaluate_data_proc(opcode, address, instruction);
1919 /* catch opcodes with [27:25] = b001 */
1920 if ((opcode & 0x0e000000) == 0x02000000) {
1921 /* 16-bit immediate load */
1922 if ((opcode & 0x0fb00000) == 0x03000000)
1923 return evaluate_mov_imm(opcode, address, instruction);
1925 /* Move immediate to status register */
1926 if ((opcode & 0x0fb00000) == 0x03200000)
1927 return evaluate_mrs_msr(opcode, address, instruction);
1929 return evaluate_data_proc(opcode, address, instruction);
1933 /* catch opcodes with [27:25] = b010 */
1934 if ((opcode & 0x0e000000) == 0x04000000) {
1935 /* Load/store immediate offset */
1936 return evaluate_load_store(opcode, address, instruction);
1939 /* catch opcodes with [27:25] = b011 */
1940 if ((opcode & 0x0e000000) == 0x06000000) {
1941 /* Load/store register offset */
1942 if ((opcode & 0x00000010) == 0x00000000)
1943 return evaluate_load_store(opcode, address, instruction);
1945 /* Architecturally Undefined instruction
1946 * ... don't expect these to ever be used
1948 if ((opcode & 0x07f000f0) == 0x07f000f0) {
1949 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1950 snprintf(instruction->text, 128,
1951 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEF",
1952 address, opcode);
1953 return ERROR_OK;
1956 /* "media" instructions */
1957 return evaluate_media(opcode, address, instruction);
1960 /* catch opcodes with [27:25] = b100 */
1961 if ((opcode & 0x0e000000) == 0x08000000) {
1962 /* Load/store multiple */
1963 return evaluate_ldm_stm(opcode, address, instruction);
1966 /* catch opcodes with [27:25] = b101 */
1967 if ((opcode & 0x0e000000) == 0x0a000000) {
1968 /* Branch and branch with link */
1969 return evaluate_b_bl(opcode, address, instruction);
1972 /* catch opcodes with [27:25] = b110 */
1973 if ((opcode & 0x0e000000) == 0x0c000000) {
1974 /* Coprocessor load/store and double register transfers */
1975 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1978 /* catch opcodes with [27:25] = b111 */
1979 if ((opcode & 0x0e000000) == 0x0e000000) {
1980 /* Software interrupt */
1981 if ((opcode & 0x0f000000) == 0x0f000000)
1982 return evaluate_swi(opcode, address, instruction);
1984 /* Coprocessor data processing */
1985 if ((opcode & 0x0f000010) == 0x0e000000)
1986 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1988 /* Coprocessor register transfers */
1989 if ((opcode & 0x0f000010) == 0x0e000010)
1990 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1993 LOG_ERROR("ARM: should never reach this point (opcode=%08x)",
1994 (unsigned) opcode);
1995 return -1;
1998 static int evaluate_b_bl_blx_thumb(uint16_t opcode,
1999 uint32_t address, struct arm_instruction *instruction)
2001 uint32_t offset = opcode & 0x7ff;
2002 uint32_t opc = (opcode >> 11) & 0x3;
2003 uint32_t target_address;
2004 char *mnemonic = NULL;
2006 /* sign extend 11-bit offset */
2007 if (((opc == 0) || (opc == 2)) && (offset & 0x00000400))
2008 offset = 0xfffff800 | offset;
2010 target_address = address + 4 + (offset << 1);
2012 switch (opc) {
2013 /* unconditional branch */
2014 case 0:
2015 instruction->type = ARM_B;
2016 mnemonic = "B";
2017 break;
2018 /* BLX suffix */
2019 case 1:
2020 instruction->type = ARM_BLX;
2021 mnemonic = "BLX";
2022 target_address &= 0xfffffffc;
2023 break;
2024 /* BL/BLX prefix */
2025 case 2:
2026 instruction->type = ARM_UNKNOWN_INSTUCTION;
2027 mnemonic = "prefix";
2028 target_address = offset << 12;
2029 break;
2030 /* BL suffix */
2031 case 3:
2032 instruction->type = ARM_BL;
2033 mnemonic = "BL";
2034 break;
2037 /* TODO: deal correctly with dual opcode (prefixed) BL/BLX;
2038 * these are effectively 32-bit instructions even in Thumb1. For
2039 * disassembly, it's simplest to always use the Thumb2 decoder.
2041 * But some cores will evidently handle them as two instructions,
2042 * where exceptions may occur between the two. The ETMv3.2+ ID
2043 * register has a bit which exposes this behavior.
2046 snprintf(instruction->text, 128,
2047 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%#8.8" PRIx32,
2048 address, opcode, mnemonic, target_address);
2050 instruction->info.b_bl_bx_blx.reg_operand = -1;
2051 instruction->info.b_bl_bx_blx.target_address = target_address;
2053 return ERROR_OK;
2056 static int evaluate_add_sub_thumb(uint16_t opcode,
2057 uint32_t address, struct arm_instruction *instruction)
2059 uint8_t Rd = (opcode >> 0) & 0x7;
2060 uint8_t Rn = (opcode >> 3) & 0x7;
2061 uint8_t Rm_imm = (opcode >> 6) & 0x7;
2062 uint32_t opc = opcode & (1 << 9);
2063 uint32_t reg_imm = opcode & (1 << 10);
2064 char *mnemonic;
2066 if (opc) {
2067 instruction->type = ARM_SUB;
2068 mnemonic = "SUBS";
2069 } else {
2070 /* REVISIT: if reg_imm == 0, display as "MOVS" */
2071 instruction->type = ARM_ADD;
2072 mnemonic = "ADDS";
2075 instruction->info.data_proc.Rd = Rd;
2076 instruction->info.data_proc.Rn = Rn;
2077 instruction->info.data_proc.S = 1;
2079 if (reg_imm) {
2080 instruction->info.data_proc.variant = 0;/*immediate*/
2081 instruction->info.data_proc.shifter_operand.immediate.immediate = Rm_imm;
2082 snprintf(instruction->text, 128,
2083 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%d",
2084 address, opcode, mnemonic, Rd, Rn, Rm_imm);
2085 } else {
2086 instruction->info.data_proc.variant = 1;/*immediate shift*/
2087 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm_imm;
2088 snprintf(instruction->text, 128,
2089 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, r%i",
2090 address, opcode, mnemonic, Rd, Rn, Rm_imm);
2093 return ERROR_OK;
2096 static int evaluate_shift_imm_thumb(uint16_t opcode,
2097 uint32_t address, struct arm_instruction *instruction)
2099 uint8_t Rd = (opcode >> 0) & 0x7;
2100 uint8_t Rm = (opcode >> 3) & 0x7;
2101 uint8_t imm = (opcode >> 6) & 0x1f;
2102 uint8_t opc = (opcode >> 11) & 0x3;
2103 char *mnemonic = NULL;
2105 switch (opc) {
2106 case 0:
2107 instruction->type = ARM_MOV;
2108 mnemonic = "LSLS";
2109 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 0;
2110 break;
2111 case 1:
2112 instruction->type = ARM_MOV;
2113 mnemonic = "LSRS";
2114 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 1;
2115 break;
2116 case 2:
2117 instruction->type = ARM_MOV;
2118 mnemonic = "ASRS";
2119 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 2;
2120 break;
2123 if ((imm == 0) && (opc != 0))
2124 imm = 32;
2126 instruction->info.data_proc.Rd = Rd;
2127 instruction->info.data_proc.Rn = -1;
2128 instruction->info.data_proc.S = 1;
2130 instruction->info.data_proc.variant = 1;/*immediate_shift*/
2131 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
2132 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = imm;
2134 snprintf(instruction->text, 128,
2135 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%#2.2x",
2136 address, opcode, mnemonic, Rd, Rm, imm);
2138 return ERROR_OK;
2141 static int evaluate_data_proc_imm_thumb(uint16_t opcode,
2142 uint32_t address, struct arm_instruction *instruction)
2144 uint8_t imm = opcode & 0xff;
2145 uint8_t Rd = (opcode >> 8) & 0x7;
2146 uint32_t opc = (opcode >> 11) & 0x3;
2147 char *mnemonic = NULL;
2149 instruction->info.data_proc.Rd = Rd;
2150 instruction->info.data_proc.Rn = Rd;
2151 instruction->info.data_proc.S = 1;
2152 instruction->info.data_proc.variant = 0;/*immediate*/
2153 instruction->info.data_proc.shifter_operand.immediate.immediate = imm;
2155 switch (opc) {
2156 case 0:
2157 instruction->type = ARM_MOV;
2158 mnemonic = "MOVS";
2159 instruction->info.data_proc.Rn = -1;
2160 break;
2161 case 1:
2162 instruction->type = ARM_CMP;
2163 mnemonic = "CMP";
2164 instruction->info.data_proc.Rd = -1;
2165 break;
2166 case 2:
2167 instruction->type = ARM_ADD;
2168 mnemonic = "ADDS";
2169 break;
2170 case 3:
2171 instruction->type = ARM_SUB;
2172 mnemonic = "SUBS";
2173 break;
2176 snprintf(instruction->text, 128,
2177 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, #%#2.2x",
2178 address, opcode, mnemonic, Rd, imm);
2180 return ERROR_OK;
2183 static int evaluate_data_proc_thumb(uint16_t opcode,
2184 uint32_t address, struct arm_instruction *instruction)
2186 uint8_t high_reg, op, Rm, Rd, H1, H2;
2187 char *mnemonic = NULL;
2188 bool nop = false;
2190 high_reg = (opcode & 0x0400) >> 10;
2191 op = (opcode & 0x03C0) >> 6;
2193 Rd = (opcode & 0x0007);
2194 Rm = (opcode & 0x0038) >> 3;
2195 H1 = (opcode & 0x0080) >> 7;
2196 H2 = (opcode & 0x0040) >> 6;
2198 instruction->info.data_proc.Rd = Rd;
2199 instruction->info.data_proc.Rn = Rd;
2200 instruction->info.data_proc.S = (!high_reg || (instruction->type == ARM_CMP));
2201 instruction->info.data_proc.variant = 1 /*immediate shift*/;
2202 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
2204 if (high_reg) {
2205 Rd |= H1 << 3;
2206 Rm |= H2 << 3;
2207 op >>= 2;
2209 switch (op) {
2210 case 0x0:
2211 instruction->type = ARM_ADD;
2212 mnemonic = "ADD";
2213 break;
2214 case 0x1:
2215 instruction->type = ARM_CMP;
2216 mnemonic = "CMP";
2217 break;
2218 case 0x2:
2219 instruction->type = ARM_MOV;
2220 mnemonic = "MOV";
2221 if (Rd == Rm)
2222 nop = true;
2223 break;
2224 case 0x3:
2225 if ((opcode & 0x7) == 0x0) {
2226 instruction->info.b_bl_bx_blx.reg_operand = Rm;
2227 if (H1) {
2228 instruction->type = ARM_BLX;
2229 snprintf(instruction->text, 128,
2230 "0x%8.8" PRIx32
2231 " 0x%4.4x \tBLX\tr%i",
2232 address, opcode, Rm);
2233 } else {
2234 instruction->type = ARM_BX;
2235 snprintf(instruction->text, 128,
2236 "0x%8.8" PRIx32
2237 " 0x%4.4x \tBX\tr%i",
2238 address, opcode, Rm);
2240 } else {
2241 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2242 snprintf(instruction->text, 128,
2243 "0x%8.8" PRIx32
2244 " 0x%4.4x \t"
2245 "UNDEFINED INSTRUCTION",
2246 address, opcode);
2248 return ERROR_OK;
2249 break;
2251 } else {
2252 switch (op) {
2253 case 0x0:
2254 instruction->type = ARM_AND;
2255 mnemonic = "ANDS";
2256 break;
2257 case 0x1:
2258 instruction->type = ARM_EOR;
2259 mnemonic = "EORS";
2260 break;
2261 case 0x2:
2262 instruction->type = ARM_MOV;
2263 mnemonic = "LSLS";
2264 instruction->info.data_proc.variant = 2 /*register shift*/;
2265 instruction->info.data_proc.shifter_operand.register_shift.shift = 0;
2266 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
2267 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
2268 break;
2269 case 0x3:
2270 instruction->type = ARM_MOV;
2271 mnemonic = "LSRS";
2272 instruction->info.data_proc.variant = 2 /*register shift*/;
2273 instruction->info.data_proc.shifter_operand.register_shift.shift = 1;
2274 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
2275 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
2276 break;
2277 case 0x4:
2278 instruction->type = ARM_MOV;
2279 mnemonic = "ASRS";
2280 instruction->info.data_proc.variant = 2 /*register shift*/;
2281 instruction->info.data_proc.shifter_operand.register_shift.shift = 2;
2282 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
2283 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
2284 break;
2285 case 0x5:
2286 instruction->type = ARM_ADC;
2287 mnemonic = "ADCS";
2288 break;
2289 case 0x6:
2290 instruction->type = ARM_SBC;
2291 mnemonic = "SBCS";
2292 break;
2293 case 0x7:
2294 instruction->type = ARM_MOV;
2295 mnemonic = "RORS";
2296 instruction->info.data_proc.variant = 2 /*register shift*/;
2297 instruction->info.data_proc.shifter_operand.register_shift.shift = 3;
2298 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
2299 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
2300 break;
2301 case 0x8:
2302 instruction->type = ARM_TST;
2303 mnemonic = "TST";
2304 break;
2305 case 0x9:
2306 instruction->type = ARM_RSB;
2307 mnemonic = "RSBS";
2308 instruction->info.data_proc.variant = 0 /*immediate*/;
2309 instruction->info.data_proc.shifter_operand.immediate.immediate = 0;
2310 instruction->info.data_proc.Rn = Rm;
2311 break;
2312 case 0xA:
2313 instruction->type = ARM_CMP;
2314 mnemonic = "CMP";
2315 break;
2316 case 0xB:
2317 instruction->type = ARM_CMN;
2318 mnemonic = "CMN";
2319 break;
2320 case 0xC:
2321 instruction->type = ARM_ORR;
2322 mnemonic = "ORRS";
2323 break;
2324 case 0xD:
2325 instruction->type = ARM_MUL;
2326 mnemonic = "MULS";
2327 break;
2328 case 0xE:
2329 instruction->type = ARM_BIC;
2330 mnemonic = "BICS";
2331 break;
2332 case 0xF:
2333 instruction->type = ARM_MVN;
2334 mnemonic = "MVNS";
2335 break;
2339 if (nop)
2340 snprintf(instruction->text, 128,
2341 "0x%8.8" PRIx32 " 0x%4.4x \tNOP\t\t\t"
2342 "; (%s r%i, r%i)",
2343 address, opcode, mnemonic, Rd, Rm);
2344 else
2345 snprintf(instruction->text, 128,
2346 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i",
2347 address, opcode, mnemonic, Rd, Rm);
2349 return ERROR_OK;
2352 /* PC-relative data addressing is word-aligned even with Thumb */
2353 static inline uint32_t thumb_alignpc4(uint32_t addr)
2355 return (addr + 4) & ~3;
2358 static int evaluate_load_literal_thumb(uint16_t opcode,
2359 uint32_t address, struct arm_instruction *instruction)
2361 uint32_t immediate;
2362 uint8_t Rd = (opcode >> 8) & 0x7;
2364 instruction->type = ARM_LDR;
2365 immediate = opcode & 0x000000ff;
2366 immediate *= 4;
2368 instruction->info.load_store.Rd = Rd;
2369 instruction->info.load_store.Rn = 15 /*PC*/;
2370 instruction->info.load_store.index_mode = 0; /*offset*/
2371 instruction->info.load_store.offset_mode = 0; /*immediate*/
2372 instruction->info.load_store.offset.offset = immediate;
2374 snprintf(instruction->text, 128,
2375 "0x%8.8" PRIx32 " 0x%4.4x \t"
2376 "LDR\tr%i, [pc, #%#" PRIx32 "]\t; %#8.8" PRIx32,
2377 address, opcode, Rd, immediate,
2378 thumb_alignpc4(address) + immediate);
2380 return ERROR_OK;
2383 static int evaluate_load_store_reg_thumb(uint16_t opcode,
2384 uint32_t address, struct arm_instruction *instruction)
2386 uint8_t Rd = (opcode >> 0) & 0x7;
2387 uint8_t Rn = (opcode >> 3) & 0x7;
2388 uint8_t Rm = (opcode >> 6) & 0x7;
2389 uint8_t opc = (opcode >> 9) & 0x7;
2390 char *mnemonic = NULL;
2392 switch (opc) {
2393 case 0:
2394 instruction->type = ARM_STR;
2395 mnemonic = "STR";
2396 break;
2397 case 1:
2398 instruction->type = ARM_STRH;
2399 mnemonic = "STRH";
2400 break;
2401 case 2:
2402 instruction->type = ARM_STRB;
2403 mnemonic = "STRB";
2404 break;
2405 case 3:
2406 instruction->type = ARM_LDRSB;
2407 mnemonic = "LDRSB";
2408 break;
2409 case 4:
2410 instruction->type = ARM_LDR;
2411 mnemonic = "LDR";
2412 break;
2413 case 5:
2414 instruction->type = ARM_LDRH;
2415 mnemonic = "LDRH";
2416 break;
2417 case 6:
2418 instruction->type = ARM_LDRB;
2419 mnemonic = "LDRB";
2420 break;
2421 case 7:
2422 instruction->type = ARM_LDRSH;
2423 mnemonic = "LDRSH";
2424 break;
2427 snprintf(instruction->text, 128,
2428 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [r%i, r%i]",
2429 address, opcode, mnemonic, Rd, Rn, Rm);
2431 instruction->info.load_store.Rd = Rd;
2432 instruction->info.load_store.Rn = Rn;
2433 instruction->info.load_store.index_mode = 0; /*offset*/
2434 instruction->info.load_store.offset_mode = 1; /*register*/
2435 instruction->info.load_store.offset.reg.Rm = Rm;
2437 return ERROR_OK;
2440 static int evaluate_load_store_imm_thumb(uint16_t opcode,
2441 uint32_t address, struct arm_instruction *instruction)
2443 uint32_t offset = (opcode >> 6) & 0x1f;
2444 uint8_t Rd = (opcode >> 0) & 0x7;
2445 uint8_t Rn = (opcode >> 3) & 0x7;
2446 uint32_t L = opcode & (1 << 11);
2447 uint32_t B = opcode & (1 << 12);
2448 char *mnemonic;
2449 char suffix = ' ';
2450 uint32_t shift = 2;
2452 if (L) {
2453 instruction->type = ARM_LDR;
2454 mnemonic = "LDR";
2455 } else {
2456 instruction->type = ARM_STR;
2457 mnemonic = "STR";
2460 if ((opcode&0xF000) == 0x8000) {
2461 suffix = 'H';
2462 shift = 1;
2463 } else if (B) {
2464 suffix = 'B';
2465 shift = 0;
2468 snprintf(instruction->text, 128,
2469 "0x%8.8" PRIx32 " 0x%4.4x \t%s%c\tr%i, [r%i, #%#" PRIx32 "]",
2470 address, opcode, mnemonic, suffix, Rd, Rn, offset << shift);
2472 instruction->info.load_store.Rd = Rd;
2473 instruction->info.load_store.Rn = Rn;
2474 instruction->info.load_store.index_mode = 0; /*offset*/
2475 instruction->info.load_store.offset_mode = 0; /*immediate*/
2476 instruction->info.load_store.offset.offset = offset << shift;
2478 return ERROR_OK;
2481 static int evaluate_load_store_stack_thumb(uint16_t opcode,
2482 uint32_t address, struct arm_instruction *instruction)
2484 uint32_t offset = opcode & 0xff;
2485 uint8_t Rd = (opcode >> 8) & 0x7;
2486 uint32_t L = opcode & (1 << 11);
2487 char *mnemonic;
2489 if (L) {
2490 instruction->type = ARM_LDR;
2491 mnemonic = "LDR";
2492 } else {
2493 instruction->type = ARM_STR;
2494 mnemonic = "STR";
2497 snprintf(instruction->text, 128,
2498 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [SP, #%#" PRIx32 "]",
2499 address, opcode, mnemonic, Rd, offset*4);
2501 instruction->info.load_store.Rd = Rd;
2502 instruction->info.load_store.Rn = 13 /*SP*/;
2503 instruction->info.load_store.index_mode = 0; /*offset*/
2504 instruction->info.load_store.offset_mode = 0; /*immediate*/
2505 instruction->info.load_store.offset.offset = offset*4;
2507 return ERROR_OK;
2510 static int evaluate_add_sp_pc_thumb(uint16_t opcode,
2511 uint32_t address, struct arm_instruction *instruction)
2513 uint32_t imm = opcode & 0xff;
2514 uint8_t Rd = (opcode >> 8) & 0x7;
2515 uint8_t Rn;
2516 uint32_t SP = opcode & (1 << 11);
2517 const char *reg_name;
2519 instruction->type = ARM_ADD;
2521 if (SP) {
2522 reg_name = "SP";
2523 Rn = 13;
2524 } else {
2525 reg_name = "PC";
2526 Rn = 15;
2529 snprintf(instruction->text, 128,
2530 "0x%8.8" PRIx32 " 0x%4.4x \tADD\tr%i, %s, #%#" PRIx32,
2531 address, opcode, Rd, reg_name, imm * 4);
2533 instruction->info.data_proc.variant = 0 /* immediate */;
2534 instruction->info.data_proc.Rd = Rd;
2535 instruction->info.data_proc.Rn = Rn;
2536 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
2538 return ERROR_OK;
2541 static int evaluate_adjust_stack_thumb(uint16_t opcode,
2542 uint32_t address, struct arm_instruction *instruction)
2544 uint32_t imm = opcode & 0x7f;
2545 uint8_t opc = opcode & (1 << 7);
2546 char *mnemonic;
2549 if (opc) {
2550 instruction->type = ARM_SUB;
2551 mnemonic = "SUB";
2552 } else {
2553 instruction->type = ARM_ADD;
2554 mnemonic = "ADD";
2557 snprintf(instruction->text, 128,
2558 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tSP, #%#" PRIx32,
2559 address, opcode, mnemonic, imm*4);
2561 instruction->info.data_proc.variant = 0 /* immediate */;
2562 instruction->info.data_proc.Rd = 13 /*SP*/;
2563 instruction->info.data_proc.Rn = 13 /*SP*/;
2564 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
2566 return ERROR_OK;
2569 static int evaluate_breakpoint_thumb(uint16_t opcode,
2570 uint32_t address, struct arm_instruction *instruction)
2572 uint32_t imm = opcode & 0xff;
2574 instruction->type = ARM_BKPT;
2576 snprintf(instruction->text, 128,
2577 "0x%8.8" PRIx32 " 0x%4.4x \tBKPT\t%#2.2" PRIx32 "",
2578 address, opcode, imm);
2580 return ERROR_OK;
2583 static int evaluate_load_store_multiple_thumb(uint16_t opcode,
2584 uint32_t address, struct arm_instruction *instruction)
2586 uint32_t reg_list = opcode & 0xff;
2587 uint32_t L = opcode & (1 << 11);
2588 uint32_t R = opcode & (1 << 8);
2589 uint8_t Rn = (opcode >> 8) & 7;
2590 uint8_t addr_mode = 0 /* IA */;
2591 char reg_names[40];
2592 char *reg_names_p;
2593 char *mnemonic;
2594 char ptr_name[7] = "";
2595 int i;
2597 /* REVISIT: in ThumbEE mode, there are no LDM or STM instructions.
2598 * The STMIA and LDMIA opcodes are used for other instructions.
2601 if ((opcode & 0xf000) == 0xc000) { /* generic load/store multiple */
2602 char *wback = "!";
2604 if (L) {
2605 instruction->type = ARM_LDM;
2606 mnemonic = "LDM";
2607 if (opcode & (1 << Rn))
2608 wback = "";
2609 } else {
2610 instruction->type = ARM_STM;
2611 mnemonic = "STM";
2613 snprintf(ptr_name, sizeof ptr_name, "r%i%s, ", Rn, wback);
2614 } else {/* push/pop */
2615 Rn = 13;/* SP */
2616 if (L) {
2617 instruction->type = ARM_LDM;
2618 mnemonic = "POP";
2619 if (R)
2620 reg_list |= (1 << 15) /*PC*/;
2621 } else {
2622 instruction->type = ARM_STM;
2623 mnemonic = "PUSH";
2624 addr_mode = 3; /*DB*/
2625 if (R)
2626 reg_list |= (1 << 14) /*LR*/;
2630 reg_names_p = reg_names;
2631 for (i = 0; i <= 15; i++) {
2632 if (reg_list & (1 << i))
2633 reg_names_p += snprintf(reg_names_p,
2634 (reg_names + 40 - reg_names_p),
2635 "r%i, ",
2638 if (reg_names_p > reg_names)
2639 reg_names_p[-2] = '\0';
2640 else /* invalid op : no registers */
2641 reg_names[0] = '\0';
2643 snprintf(instruction->text, 128,
2644 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%s{%s}",
2645 address, opcode, mnemonic, ptr_name, reg_names);
2647 instruction->info.load_store_multiple.register_list = reg_list;
2648 instruction->info.load_store_multiple.Rn = Rn;
2649 instruction->info.load_store_multiple.addressing_mode = addr_mode;
2651 return ERROR_OK;
2654 static int evaluate_cond_branch_thumb(uint16_t opcode,
2655 uint32_t address, struct arm_instruction *instruction)
2657 uint32_t offset = opcode & 0xff;
2658 uint8_t cond = (opcode >> 8) & 0xf;
2659 uint32_t target_address;
2661 if (cond == 0xf) {
2662 instruction->type = ARM_SWI;
2663 snprintf(instruction->text, 128,
2664 "0x%8.8" PRIx32 " 0x%4.4x \tSVC\t%#2.2" PRIx32,
2665 address, opcode, offset);
2666 return ERROR_OK;
2667 } else if (cond == 0xe) {
2668 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2669 snprintf(instruction->text, 128,
2670 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2671 address, opcode);
2672 return ERROR_OK;
2675 /* sign extend 8-bit offset */
2676 if (offset & 0x00000080)
2677 offset = 0xffffff00 | offset;
2679 target_address = address + 4 + (offset << 1);
2681 snprintf(instruction->text, 128,
2682 "0x%8.8" PRIx32 " 0x%4.4x \tB%s\t%#8.8" PRIx32,
2683 address, opcode,
2684 arm_condition_strings[cond], target_address);
2686 instruction->type = ARM_B;
2687 instruction->info.b_bl_bx_blx.reg_operand = -1;
2688 instruction->info.b_bl_bx_blx.target_address = target_address;
2690 return ERROR_OK;
2693 static int evaluate_cb_thumb(uint16_t opcode, uint32_t address,
2694 struct arm_instruction *instruction)
2696 unsigned offset;
2698 /* added in Thumb2 */
2699 offset = (opcode >> 3) & 0x1f;
2700 offset |= (opcode & 0x0200) >> 4;
2702 snprintf(instruction->text, 128,
2703 "0x%8.8" PRIx32 " 0x%4.4x \tCB%sZ\tr%d, %#8.8" PRIx32,
2704 address, opcode,
2705 (opcode & 0x0800) ? "N" : "",
2706 opcode & 0x7, address + 4 + (offset << 1));
2708 return ERROR_OK;
2711 static int evaluate_extend_thumb(uint16_t opcode, uint32_t address,
2712 struct arm_instruction *instruction)
2714 /* added in ARMv6 */
2715 snprintf(instruction->text, 128,
2716 "0x%8.8" PRIx32 " 0x%4.4x \t%cXT%c\tr%d, r%d",
2717 address, opcode,
2718 (opcode & 0x0080) ? 'U' : 'S',
2719 (opcode & 0x0040) ? 'B' : 'H',
2720 opcode & 0x7, (opcode >> 3) & 0x7);
2722 return ERROR_OK;
2725 static int evaluate_cps_thumb(uint16_t opcode, uint32_t address,
2726 struct arm_instruction *instruction)
2728 /* added in ARMv6 */
2729 if ((opcode & 0x0ff0) == 0x0650)
2730 snprintf(instruction->text, 128,
2731 "0x%8.8" PRIx32 " 0x%4.4x \tSETEND %s",
2732 address, opcode,
2733 (opcode & 0x80) ? "BE" : "LE");
2734 else /* ASSUME (opcode & 0x0fe0) == 0x0660 */
2735 snprintf(instruction->text, 128,
2736 "0x%8.8" PRIx32 " 0x%4.4x \tCPSI%c\t%s%s%s",
2737 address, opcode,
2738 (opcode & 0x0010) ? 'D' : 'E',
2739 (opcode & 0x0004) ? "A" : "",
2740 (opcode & 0x0002) ? "I" : "",
2741 (opcode & 0x0001) ? "F" : "");
2743 return ERROR_OK;
2746 static int evaluate_byterev_thumb(uint16_t opcode, uint32_t address,
2747 struct arm_instruction *instruction)
2749 char *suffix;
2751 /* added in ARMv6 */
2752 switch ((opcode >> 6) & 3) {
2753 case 0:
2754 suffix = "";
2755 break;
2756 case 1:
2757 suffix = "16";
2758 break;
2759 default:
2760 suffix = "SH";
2761 break;
2763 snprintf(instruction->text, 128,
2764 "0x%8.8" PRIx32 " 0x%4.4x \tREV%s\tr%d, r%d",
2765 address, opcode, suffix,
2766 opcode & 0x7, (opcode >> 3) & 0x7);
2768 return ERROR_OK;
2771 static int evaluate_hint_thumb(uint16_t opcode, uint32_t address,
2772 struct arm_instruction *instruction)
2774 char *hint;
2776 switch ((opcode >> 4) & 0x0f) {
2777 case 0:
2778 hint = "NOP";
2779 break;
2780 case 1:
2781 hint = "YIELD";
2782 break;
2783 case 2:
2784 hint = "WFE";
2785 break;
2786 case 3:
2787 hint = "WFI";
2788 break;
2789 case 4:
2790 hint = "SEV";
2791 break;
2792 default:
2793 hint = "HINT (UNRECOGNIZED)";
2794 break;
2797 snprintf(instruction->text, 128,
2798 "0x%8.8" PRIx32 " 0x%4.4x \t%s",
2799 address, opcode, hint);
2801 return ERROR_OK;
2804 static int evaluate_ifthen_thumb(uint16_t opcode, uint32_t address,
2805 struct arm_instruction *instruction)
2807 unsigned cond = (opcode >> 4) & 0x0f;
2808 char *x = "", *y = "", *z = "";
2810 if (opcode & 0x01)
2811 z = (opcode & 0x02) ? "T" : "E";
2812 if (opcode & 0x03)
2813 y = (opcode & 0x04) ? "T" : "E";
2814 if (opcode & 0x07)
2815 x = (opcode & 0x08) ? "T" : "E";
2817 snprintf(instruction->text, 128,
2818 "0x%8.8" PRIx32 " 0x%4.4x \tIT%s%s%s\t%s",
2819 address, opcode,
2820 x, y, z, arm_condition_strings[cond]);
2822 /* NOTE: strictly speaking, the next 1-4 instructions should
2823 * now be displayed with the relevant conditional suffix...
2826 return ERROR_OK;
2829 int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
2831 /* clear fields, to avoid confusion */
2832 memset(instruction, 0, sizeof(struct arm_instruction));
2833 instruction->opcode = opcode;
2834 instruction->instruction_size = 2;
2836 if ((opcode & 0xe000) == 0x0000) {
2837 /* add/substract register or immediate */
2838 if ((opcode & 0x1800) == 0x1800)
2839 return evaluate_add_sub_thumb(opcode, address, instruction);
2840 /* shift by immediate */
2841 else
2842 return evaluate_shift_imm_thumb(opcode, address, instruction);
2845 /* Add/substract/compare/move immediate */
2846 if ((opcode & 0xe000) == 0x2000)
2847 return evaluate_data_proc_imm_thumb(opcode, address, instruction);
2849 /* Data processing instructions */
2850 if ((opcode & 0xf800) == 0x4000)
2851 return evaluate_data_proc_thumb(opcode, address, instruction);
2853 /* Load from literal pool */
2854 if ((opcode & 0xf800) == 0x4800)
2855 return evaluate_load_literal_thumb(opcode, address, instruction);
2857 /* Load/Store register offset */
2858 if ((opcode & 0xf000) == 0x5000)
2859 return evaluate_load_store_reg_thumb(opcode, address, instruction);
2861 /* Load/Store immediate offset */
2862 if (((opcode & 0xe000) == 0x6000)
2863 || ((opcode & 0xf000) == 0x8000))
2864 return evaluate_load_store_imm_thumb(opcode, address, instruction);
2866 /* Load/Store from/to stack */
2867 if ((opcode & 0xf000) == 0x9000)
2868 return evaluate_load_store_stack_thumb(opcode, address, instruction);
2870 /* Add to SP/PC */
2871 if ((opcode & 0xf000) == 0xa000)
2872 return evaluate_add_sp_pc_thumb(opcode, address, instruction);
2874 /* Misc */
2875 if ((opcode & 0xf000) == 0xb000) {
2876 switch ((opcode >> 8) & 0x0f) {
2877 case 0x0:
2878 return evaluate_adjust_stack_thumb(opcode, address, instruction);
2879 case 0x1:
2880 case 0x3:
2881 case 0x9:
2882 case 0xb:
2883 return evaluate_cb_thumb(opcode, address, instruction);
2884 case 0x2:
2885 return evaluate_extend_thumb(opcode, address, instruction);
2886 case 0x4:
2887 case 0x5:
2888 case 0xc:
2889 case 0xd:
2890 return evaluate_load_store_multiple_thumb(opcode, address,
2891 instruction);
2892 case 0x6:
2893 return evaluate_cps_thumb(opcode, address, instruction);
2894 case 0xa:
2895 if ((opcode & 0x00c0) == 0x0080)
2896 break;
2897 return evaluate_byterev_thumb(opcode, address, instruction);
2898 case 0xe:
2899 return evaluate_breakpoint_thumb(opcode, address, instruction);
2900 case 0xf:
2901 if (opcode & 0x000f)
2902 return evaluate_ifthen_thumb(opcode, address,
2903 instruction);
2904 else
2905 return evaluate_hint_thumb(opcode, address,
2906 instruction);
2909 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2910 snprintf(instruction->text, 128,
2911 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2912 address, opcode);
2913 return ERROR_OK;
2916 /* Load/Store multiple */
2917 if ((opcode & 0xf000) == 0xc000)
2918 return evaluate_load_store_multiple_thumb(opcode, address, instruction);
2920 /* Conditional branch + SWI */
2921 if ((opcode & 0xf000) == 0xd000)
2922 return evaluate_cond_branch_thumb(opcode, address, instruction);
2924 if ((opcode & 0xe000) == 0xe000) {
2925 /* Undefined instructions */
2926 if ((opcode & 0xf801) == 0xe801) {
2927 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2928 snprintf(instruction->text, 128,
2929 "0x%8.8" PRIx32 " 0x%8.8x\t"
2930 "UNDEFINED INSTRUCTION",
2931 address, opcode);
2932 return ERROR_OK;
2933 } else /* Branch to offset */
2934 return evaluate_b_bl_blx_thumb(opcode, address, instruction);
2937 LOG_ERROR("Thumb: should never reach this point (opcode=%04x)", opcode);
2938 return -1;
2941 static int t2ev_b_bl(uint32_t opcode, uint32_t address,
2942 struct arm_instruction *instruction, char *cp)
2944 unsigned offset;
2945 unsigned b21 = 1 << 21;
2946 unsigned b22 = 1 << 22;
2948 /* instead of combining two smaller 16-bit branch instructions,
2949 * Thumb2 uses only one larger 32-bit instruction.
2951 offset = opcode & 0x7ff;
2952 offset |= (opcode & 0x03ff0000) >> 5;
2953 if (opcode & (1 << 26)) {
2954 offset |= 0xff << 23;
2955 if ((opcode & (1 << 11)) == 0)
2956 b21 = 0;
2957 if ((opcode & (1 << 13)) == 0)
2958 b22 = 0;
2959 } else {
2960 if (opcode & (1 << 11))
2961 b21 = 0;
2962 if (opcode & (1 << 13))
2963 b22 = 0;
2965 offset |= b21;
2966 offset |= b22;
2969 address += 4;
2970 address += offset << 1;
2972 char *inst;
2973 switch ((opcode >> 12) & 0x5) {
2974 case 0x1:
2975 inst = "B.W";
2976 instruction->type = ARM_B;
2977 break;
2978 case 0x4:
2979 inst = "BLX";
2980 instruction->type = ARM_BLX;
2981 address &= 0xfffffffc;
2982 break;
2983 case 0x5:
2984 inst = "BL";
2985 instruction->type = ARM_BL;
2986 break;
2987 default:
2988 return ERROR_COMMAND_SYNTAX_ERROR;
2990 instruction->info.b_bl_bx_blx.reg_operand = -1;
2991 instruction->info.b_bl_bx_blx.target_address = address;
2992 sprintf(cp, "%s\t%#8.8" PRIx32, inst, address);
2994 return ERROR_OK;
2997 static int t2ev_cond_b(uint32_t opcode, uint32_t address,
2998 struct arm_instruction *instruction, char *cp)
3000 unsigned offset;
3001 unsigned b17 = 1 << 17;
3002 unsigned b18 = 1 << 18;
3003 unsigned cond = (opcode >> 22) & 0x0f;
3005 offset = opcode & 0x7ff;
3006 offset |= (opcode & 0x003f0000) >> 5;
3007 if (opcode & (1 << 26)) {
3008 offset |= 0x1fff << 19;
3009 if ((opcode & (1 << 11)) == 0)
3010 b17 = 0;
3011 if ((opcode & (1 << 13)) == 0)
3012 b18 = 0;
3013 } else {
3014 if (opcode & (1 << 11))
3015 b17 = 0;
3016 if (opcode & (1 << 13))
3017 b18 = 0;
3019 offset |= b17;
3020 offset |= b18;
3022 address += 4;
3023 address += offset << 1;
3025 instruction->type = ARM_B;
3026 instruction->info.b_bl_bx_blx.reg_operand = -1;
3027 instruction->info.b_bl_bx_blx.target_address = address;
3028 sprintf(cp, "B%s.W\t%#8.8" PRIx32,
3029 arm_condition_strings[cond],
3030 address);
3032 return ERROR_OK;
3035 static const char *special_name(int number)
3037 char *special = "(RESERVED)";
3039 switch (number) {
3040 case 0:
3041 special = "apsr";
3042 break;
3043 case 1:
3044 special = "iapsr";
3045 break;
3046 case 2:
3047 special = "eapsr";
3048 break;
3049 case 3:
3050 special = "xpsr";
3051 break;
3052 case 5:
3053 special = "ipsr";
3054 break;
3055 case 6:
3056 special = "epsr";
3057 break;
3058 case 7:
3059 special = "iepsr";
3060 break;
3061 case 8:
3062 special = "msp";
3063 break;
3064 case 9:
3065 special = "psp";
3066 break;
3067 case 16:
3068 special = "primask";
3069 break;
3070 case 17:
3071 special = "basepri";
3072 break;
3073 case 18:
3074 special = "basepri_max";
3075 break;
3076 case 19:
3077 special = "faultmask";
3078 break;
3079 case 20:
3080 special = "control";
3081 break;
3083 return special;
3086 static int t2ev_hint(uint32_t opcode, uint32_t address,
3087 struct arm_instruction *instruction, char *cp)
3089 const char *mnemonic;
3091 if (opcode & 0x0700) {
3092 instruction->type = ARM_UNDEFINED_INSTRUCTION;
3093 strcpy(cp, "UNDEFINED");
3094 return ERROR_OK;
3097 if (opcode & 0x00f0) {
3098 sprintf(cp, "DBG\t#%d", (int) opcode & 0xf);
3099 return ERROR_OK;
3102 switch (opcode & 0x0f) {
3103 case 0:
3104 mnemonic = "NOP.W";
3105 break;
3106 case 1:
3107 mnemonic = "YIELD.W";
3108 break;
3109 case 2:
3110 mnemonic = "WFE.W";
3111 break;
3112 case 3:
3113 mnemonic = "WFI.W";
3114 break;
3115 case 4:
3116 mnemonic = "SEV.W";
3117 break;
3118 default:
3119 mnemonic = "HINT.W (UNRECOGNIZED)";
3120 break;
3122 strcpy(cp, mnemonic);
3123 return ERROR_OK;
3126 static int t2ev_misc(uint32_t opcode, uint32_t address,
3127 struct arm_instruction *instruction, char *cp)
3129 const char *mnemonic;
3131 switch ((opcode >> 4) & 0x0f) {
3132 case 0:
3133 mnemonic = "LEAVEX";
3134 break;
3135 case 1:
3136 mnemonic = "ENTERX";
3137 break;
3138 case 2:
3139 mnemonic = "CLREX";
3140 break;
3141 case 4:
3142 mnemonic = "DSB";
3143 break;
3144 case 5:
3145 mnemonic = "DMB";
3146 break;
3147 case 6:
3148 mnemonic = "ISB";
3149 break;
3150 default:
3151 return ERROR_COMMAND_SYNTAX_ERROR;
3153 strcpy(cp, mnemonic);
3154 return ERROR_OK;
3157 static int t2ev_b_misc(uint32_t opcode, uint32_t address,
3158 struct arm_instruction *instruction, char *cp)
3160 /* permanently undefined */
3161 if ((opcode & 0x07f07000) == 0x07f02000) {
3162 instruction->type = ARM_UNDEFINED_INSTRUCTION;
3163 strcpy(cp, "UNDEFINED");
3164 return ERROR_OK;
3167 switch ((opcode >> 12) & 0x5) {
3168 case 0x1:
3169 case 0x4:
3170 case 0x5:
3171 return t2ev_b_bl(opcode, address, instruction, cp);
3172 case 0:
3173 if (((opcode >> 23) & 0x07) != 0x07)
3174 return t2ev_cond_b(opcode, address, instruction, cp);
3175 if (opcode & (1 << 26))
3176 goto undef;
3177 break;
3180 switch ((opcode >> 20) & 0x7f) {
3181 case 0x38:
3182 case 0x39:
3183 sprintf(cp, "MSR\t%s, r%d", special_name(opcode & 0xff),
3184 (int) (opcode >> 16) & 0x0f);
3185 return ERROR_OK;
3186 case 0x3a:
3187 return t2ev_hint(opcode, address, instruction, cp);
3188 case 0x3b:
3189 return t2ev_misc(opcode, address, instruction, cp);
3190 case 0x3c:
3191 sprintf(cp, "BXJ\tr%d", (int) (opcode >> 16) & 0x0f);
3192 return ERROR_OK;
3193 case 0x3e:
3194 case 0x3f:
3195 sprintf(cp, "MRS\tr%d, %s", (int) (opcode >> 8) & 0x0f,
3196 special_name(opcode & 0xff));
3197 return ERROR_OK;
3200 undef:
3201 return ERROR_COMMAND_SYNTAX_ERROR;
3204 static int t2ev_data_mod_immed(uint32_t opcode, uint32_t address,
3205 struct arm_instruction *instruction, char *cp)
3207 char *mnemonic = NULL;
3208 int rn = (opcode >> 16) & 0xf;
3209 int rd = (opcode >> 8) & 0xf;
3210 unsigned immed = opcode & 0xff;
3211 unsigned func;
3212 bool one = false;
3213 char *suffix = "";
3214 char *suffix2 = "";
3216 /* ARMv7-M: A5.3.2 Modified immediate constants */
3217 func = (opcode >> 11) & 0x0e;
3218 if (immed & 0x80)
3219 func |= 1;
3220 if (opcode & (1 << 26))
3221 func |= 0x10;
3223 /* "Modified" immediates */
3224 switch (func >> 1) {
3225 case 0:
3226 break;
3227 case 2:
3228 immed <<= 8;
3229 /* FALLTHROUGH */
3230 case 1:
3231 immed += immed << 16;
3232 break;
3233 case 3:
3234 immed += immed << 8;
3235 immed += immed << 16;
3236 break;
3237 default:
3238 immed |= 0x80;
3239 immed = ror(immed, func);
3242 if (opcode & (1 << 20))
3243 suffix = "S";
3245 switch ((opcode >> 21) & 0xf) {
3246 case 0:
3247 if (rd == 0xf) {
3248 instruction->type = ARM_TST;
3249 mnemonic = "TST";
3250 one = true;
3251 suffix = "";
3252 rd = rn;
3253 } else {
3254 instruction->type = ARM_AND;
3255 mnemonic = "AND";
3257 break;
3258 case 1:
3259 instruction->type = ARM_BIC;
3260 mnemonic = "BIC";
3261 break;
3262 case 2:
3263 if (rn == 0xf) {
3264 instruction->type = ARM_MOV;
3265 mnemonic = "MOV";
3266 one = true;
3267 suffix2 = ".W";
3268 } else {
3269 instruction->type = ARM_ORR;
3270 mnemonic = "ORR";
3272 break;
3273 case 3:
3274 if (rn == 0xf) {
3275 instruction->type = ARM_MVN;
3276 mnemonic = "MVN";
3277 one = true;
3278 } else {
3279 /* instruction->type = ARM_ORN; */
3280 mnemonic = "ORN";
3282 break;
3283 case 4:
3284 if (rd == 0xf) {
3285 instruction->type = ARM_TEQ;
3286 mnemonic = "TEQ";
3287 one = true;
3288 suffix = "";
3289 rd = rn;
3290 } else {
3291 instruction->type = ARM_EOR;
3292 mnemonic = "EOR";
3294 break;
3295 case 8:
3296 if (rd == 0xf) {
3297 instruction->type = ARM_CMN;
3298 mnemonic = "CMN";
3299 one = true;
3300 suffix = "";
3301 rd = rn;
3302 } else {
3303 instruction->type = ARM_ADD;
3304 mnemonic = "ADD";
3305 suffix2 = ".W";
3307 break;
3308 case 10:
3309 instruction->type = ARM_ADC;
3310 mnemonic = "ADC";
3311 suffix2 = ".W";
3312 break;
3313 case 11:
3314 instruction->type = ARM_SBC;
3315 mnemonic = "SBC";
3316 break;
3317 case 13:
3318 if (rd == 0xf) {
3319 instruction->type = ARM_CMP;
3320 mnemonic = "CMP";
3321 one = true;
3322 suffix = "";
3323 rd = rn;
3324 } else {
3325 instruction->type = ARM_SUB;
3326 mnemonic = "SUB";
3328 suffix2 = ".W";
3329 break;
3330 case 14:
3331 instruction->type = ARM_RSB;
3332 mnemonic = "RSB";
3333 suffix2 = ".W";
3334 break;
3335 default:
3336 return ERROR_COMMAND_SYNTAX_ERROR;
3339 if (one)
3340 sprintf(cp, "%s%s\tr%d, #%d\t; %#8.8x",
3341 mnemonic, suffix2, rd, immed, immed);
3342 else
3343 sprintf(cp, "%s%s%s\tr%d, r%d, #%d\t; %#8.8x",
3344 mnemonic, suffix, suffix2,
3345 rd, rn, immed, immed);
3347 return ERROR_OK;
3350 static int t2ev_data_immed(uint32_t opcode, uint32_t address,
3351 struct arm_instruction *instruction, char *cp)
3353 char *mnemonic = NULL;
3354 int rn = (opcode >> 16) & 0xf;
3355 int rd = (opcode >> 8) & 0xf;
3356 unsigned immed;
3357 bool add = false;
3358 bool is_signed = false;
3360 immed = (opcode & 0x0ff) | ((opcode & 0x7000) >> 4);
3361 if (opcode & (1 << 26))
3362 immed |= (1 << 11);
3364 switch ((opcode >> 20) & 0x1f) {
3365 case 0:
3366 if (rn == 0xf) {
3367 add = true;
3368 goto do_adr;
3370 mnemonic = "ADDW";
3371 break;
3372 case 4:
3373 immed |= (opcode >> 4) & 0xf000;
3374 sprintf(cp, "MOVW\tr%d, #%d\t; %#3.3x", rd, immed, immed);
3375 return ERROR_OK;
3376 case 0x0a:
3377 if (rn == 0xf)
3378 goto do_adr;
3379 mnemonic = "SUBW";
3380 break;
3381 case 0x0c:
3382 /* move constant to top 16 bits of register */
3383 immed |= (opcode >> 4) & 0xf000;
3384 sprintf(cp, "MOVT\tr%d, #%d\t; %#4.4x", rd, immed, immed);
3385 return ERROR_OK;
3386 case 0x10:
3387 case 0x12:
3388 is_signed = true;
3389 /* fallthrough */
3390 case 0x18:
3391 case 0x1a:
3392 /* signed/unsigned saturated add */
3393 immed = (opcode >> 6) & 0x03;
3394 immed |= (opcode >> 10) & 0x1c;
3395 sprintf(cp, "%sSAT\tr%d, #%d, r%d, %s #%d\t",
3396 is_signed ? "S" : "U",
3397 rd, (int) (opcode & 0x1f) + is_signed, rn,
3398 (opcode & (1 << 21)) ? "ASR" : "LSL",
3399 immed ? immed : 32);
3400 return ERROR_OK;
3401 case 0x14:
3402 is_signed = true;
3403 /* FALLTHROUGH */
3404 case 0x1c:
3405 /* signed/unsigned bitfield extract */
3406 immed = (opcode >> 6) & 0x03;
3407 immed |= (opcode >> 10) & 0x1c;
3408 sprintf(cp, "%sBFX\tr%d, r%d, #%d, #%d\t",
3409 is_signed ? "S" : "U",
3410 rd, rn, immed,
3411 (int) (opcode & 0x1f) + 1);
3412 return ERROR_OK;
3413 case 0x16:
3414 immed = (opcode >> 6) & 0x03;
3415 immed |= (opcode >> 10) & 0x1c;
3416 if (rn == 0xf) /* bitfield clear */
3417 sprintf(cp, "BFC\tr%d, #%d, #%d\t",
3418 rd, immed,
3419 (int) (opcode & 0x1f) + 1 - immed);
3420 else /* bitfield insert */
3421 sprintf(cp, "BFI\tr%d, r%d, #%d, #%d\t",
3422 rd, rn, immed,
3423 (int) (opcode & 0x1f) + 1 - immed);
3424 return ERROR_OK;
3425 default:
3426 return ERROR_COMMAND_SYNTAX_ERROR;
3429 sprintf(cp, "%s\tr%d, r%d, #%d\t; %#3.3x", mnemonic,
3430 rd, rn, immed, immed);
3431 return ERROR_OK;
3433 do_adr:
3434 address = thumb_alignpc4(address);
3435 if (add)
3436 address += immed;
3437 else
3438 address -= immed;
3439 /* REVISIT "ADD/SUB Rd, PC, #const ; 0x..." might be better;
3440 * not hiding the pc-relative stuff will sometimes be useful.
3442 sprintf(cp, "ADR.W\tr%d, %#8.8" PRIx32, rd, address);
3443 return ERROR_OK;
3446 static int t2ev_store_single(uint32_t opcode, uint32_t address,
3447 struct arm_instruction *instruction, char *cp)
3449 unsigned op = (opcode >> 20) & 0xf;
3450 char *size = "";
3451 char *suffix = "";
3452 char *p1 = "";
3453 char *p2 = "]";
3454 unsigned immed;
3455 unsigned rn = (opcode >> 16) & 0x0f;
3456 unsigned rt = (opcode >> 12) & 0x0f;
3458 if (rn == 0xf)
3459 return ERROR_COMMAND_SYNTAX_ERROR;
3461 if (opcode & 0x0800)
3462 op |= 1;
3463 switch (op) {
3464 /* byte */
3465 case 0x8:
3466 case 0x9:
3467 size = "B";
3468 goto imm12;
3469 case 0x1:
3470 size = "B";
3471 goto imm8;
3472 case 0x0:
3473 size = "B";
3474 break;
3475 /* halfword */
3476 case 0xa:
3477 case 0xb:
3478 size = "H";
3479 goto imm12;
3480 case 0x3:
3481 size = "H";
3482 goto imm8;
3483 case 0x2:
3484 size = "H";
3485 break;
3486 /* word */
3487 case 0xc:
3488 case 0xd:
3489 goto imm12;
3490 case 0x5:
3491 goto imm8;
3492 case 0x4:
3493 break;
3494 /* error */
3495 default:
3496 return ERROR_COMMAND_SYNTAX_ERROR;
3499 sprintf(cp, "STR%s.W\tr%d, [r%d, r%d, LSL #%d]",
3500 size, rt, rn, (int) opcode & 0x0f,
3501 (int) (opcode >> 4) & 0x03);
3502 return ERROR_OK;
3504 imm12:
3505 immed = opcode & 0x0fff;
3506 sprintf(cp, "STR%s.W\tr%d, [r%d, #%u]\t; %#3.3x",
3507 size, rt, rn, immed, immed);
3508 return ERROR_OK;
3510 imm8:
3511 immed = opcode & 0x00ff;
3513 switch (opcode & 0x700) {
3514 case 0x600:
3515 suffix = "T";
3516 break;
3517 case 0x000:
3518 case 0x200:
3519 return ERROR_COMMAND_SYNTAX_ERROR;
3522 /* two indexed modes will write back rn */
3523 if (opcode & 0x100) {
3524 if (opcode & 0x400) /* pre-indexed */
3525 p2 = "]!";
3526 else { /* post-indexed */
3527 p1 = "]";
3528 p2 = "";
3532 sprintf(cp, "STR%s%s\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
3533 size, suffix, rt, rn, p1,
3534 (opcode & 0x200) ? "" : "-",
3535 immed, p2, immed);
3536 return ERROR_OK;
3539 static int t2ev_mul32(uint32_t opcode, uint32_t address,
3540 struct arm_instruction *instruction, char *cp)
3542 int ra = (opcode >> 12) & 0xf;
3544 switch (opcode & 0x007000f0) {
3545 case 0:
3546 if (ra == 0xf)
3547 sprintf(cp, "MUL\tr%d, r%d, r%d",
3548 (int) (opcode >> 8) & 0xf,
3549 (int) (opcode >> 16) & 0xf,
3550 (int) (opcode >> 0) & 0xf);
3551 else
3552 sprintf(cp, "MLA\tr%d, r%d, r%d, r%d",
3553 (int) (opcode >> 8) & 0xf,
3554 (int) (opcode >> 16) & 0xf,
3555 (int) (opcode >> 0) & 0xf, ra);
3556 break;
3557 case 0x10:
3558 sprintf(cp, "MLS\tr%d, r%d, r%d, r%d",
3559 (int) (opcode >> 8) & 0xf,
3560 (int) (opcode >> 16) & 0xf,
3561 (int) (opcode >> 0) & 0xf, ra);
3562 break;
3563 default:
3564 return ERROR_COMMAND_SYNTAX_ERROR;
3566 return ERROR_OK;
3569 static int t2ev_mul64_div(uint32_t opcode, uint32_t address,
3570 struct arm_instruction *instruction, char *cp)
3572 int op = (opcode >> 4) & 0xf;
3573 char *infix = "MUL";
3575 op += (opcode >> 16) & 0x70;
3576 switch (op) {
3577 case 0x40:
3578 case 0x60:
3579 infix = "MLA";
3580 /* FALLTHROUGH */
3581 case 0:
3582 case 0x20:
3583 sprintf(cp, "%c%sL\tr%d, r%d, r%d, r%d",
3584 (op & 0x20) ? 'U' : 'S',
3585 infix,
3586 (int) (opcode >> 12) & 0xf,
3587 (int) (opcode >> 8) & 0xf,
3588 (int) (opcode >> 16) & 0xf,
3589 (int) (opcode >> 0) & 0xf);
3590 break;
3591 case 0x1f:
3592 case 0x3f:
3593 sprintf(cp, "%cDIV\tr%d, r%d, r%d",
3594 (op & 0x20) ? 'U' : 'S',
3595 (int) (opcode >> 8) & 0xf,
3596 (int) (opcode >> 16) & 0xf,
3597 (int) (opcode >> 0) & 0xf);
3598 break;
3599 default:
3600 return ERROR_COMMAND_SYNTAX_ERROR;
3603 return ERROR_OK;
3606 static int t2ev_ldm_stm(uint32_t opcode, uint32_t address,
3607 struct arm_instruction *instruction, char *cp)
3609 int rn = (opcode >> 16) & 0xf;
3610 int op = (opcode >> 22) & 0x6;
3611 int t = (opcode >> 21) & 1;
3612 unsigned registers = opcode & 0xffff;
3613 char *mode = "";
3615 if (opcode & (1 << 20))
3616 op |= 1;
3618 switch (op) {
3619 case 0:
3620 mode = "DB";
3621 /* FALL THROUGH */
3622 case 6:
3623 sprintf(cp, "SRS%s\tsp%s, #%d", mode,
3624 t ? "!" : "",
3625 (unsigned) (opcode & 0x1f));
3626 return ERROR_OK;
3627 case 1:
3628 mode = "DB";
3629 /* FALL THROUGH */
3630 case 7:
3631 sprintf(cp, "RFE%s\tr%d%s", mode,
3632 (unsigned) ((opcode >> 16) & 0xf),
3633 t ? "!" : "");
3634 return ERROR_OK;
3635 case 2:
3636 sprintf(cp, "STM.W\tr%d%s, ", rn, t ? "!" : "");
3637 break;
3638 case 3:
3639 if (rn == 13 && t)
3640 sprintf(cp, "POP.W\t");
3641 else
3642 sprintf(cp, "LDM.W\tr%d%s, ", rn, t ? "!" : "");
3643 break;
3644 case 4:
3645 if (rn == 13 && t)
3646 sprintf(cp, "PUSH.W\t");
3647 else
3648 sprintf(cp, "STMDB\tr%d%s, ", rn, t ? "!" : "");
3649 break;
3650 case 5:
3651 sprintf(cp, "LDMDB.W\tr%d%s, ", rn, t ? "!" : "");
3652 break;
3653 default:
3654 return ERROR_COMMAND_SYNTAX_ERROR;
3657 cp = strchr(cp, 0);
3658 *cp++ = '{';
3659 for (t = 0; registers; t++, registers >>= 1) {
3660 if ((registers & 1) == 0)
3661 continue;
3662 registers &= ~1;
3663 sprintf(cp, "r%d%s", t, registers ? ", " : "");
3664 cp = strchr(cp, 0);
3666 *cp++ = '}';
3667 *cp++ = 0;
3669 return ERROR_OK;
3672 /* load/store dual or exclusive, table branch */
3673 static int t2ev_ldrex_strex(uint32_t opcode, uint32_t address,
3674 struct arm_instruction *instruction, char *cp)
3676 unsigned op1op2 = (opcode >> 20) & 0x3;
3677 unsigned op3 = (opcode >> 4) & 0xf;
3678 char *mnemonic;
3679 unsigned rn = (opcode >> 16) & 0xf;
3680 unsigned rt = (opcode >> 12) & 0xf;
3681 unsigned rd = (opcode >> 8) & 0xf;
3682 unsigned imm = opcode & 0xff;
3683 char *p1 = "";
3684 char *p2 = "]";
3686 op1op2 |= (opcode >> 21) & 0xc;
3687 switch (op1op2) {
3688 case 0:
3689 mnemonic = "STREX";
3690 goto strex;
3691 case 1:
3692 mnemonic = "LDREX";
3693 goto ldrex;
3694 case 2:
3695 case 6:
3696 case 8:
3697 case 10:
3698 case 12:
3699 case 14:
3700 mnemonic = "STRD";
3701 goto immediate;
3702 case 3:
3703 case 7:
3704 case 9:
3705 case 11:
3706 case 13:
3707 case 15:
3708 mnemonic = "LDRD";
3709 if (rn == 15)
3710 goto literal;
3711 else
3712 goto immediate;
3713 case 4:
3714 switch (op3) {
3715 case 4:
3716 mnemonic = "STREXB";
3717 break;
3718 case 5:
3719 mnemonic = "STREXH";
3720 break;
3721 default:
3722 return ERROR_COMMAND_SYNTAX_ERROR;
3724 rd = opcode & 0xf;
3725 imm = 0;
3726 goto strex;
3727 case 5:
3728 switch (op3) {
3729 case 0:
3730 sprintf(cp, "TBB\t[r%u, r%u]", rn, imm & 0xf);
3731 return ERROR_OK;
3732 case 1:
3733 sprintf(cp, "TBH\t[r%u, r%u, LSL #1]", rn, imm & 0xf);
3734 return ERROR_OK;
3735 case 4:
3736 mnemonic = "LDREXB";
3737 break;
3738 case 5:
3739 mnemonic = "LDREXH";
3740 break;
3741 default:
3742 return ERROR_COMMAND_SYNTAX_ERROR;
3744 imm = 0;
3745 goto ldrex;
3747 return ERROR_COMMAND_SYNTAX_ERROR;
3749 strex:
3750 imm <<= 2;
3751 if (imm)
3752 sprintf(cp, "%s\tr%u, r%u, [r%u, #%u]\t; %#2.2x",
3753 mnemonic, rd, rt, rn, imm, imm);
3754 else
3755 sprintf(cp, "%s\tr%u, r%u, [r%u]",
3756 mnemonic, rd, rt, rn);
3757 return ERROR_OK;
3759 ldrex:
3760 imm <<= 2;
3761 if (imm)
3762 sprintf(cp, "%s\tr%u, [r%u, #%u]\t; %#2.2x",
3763 mnemonic, rt, rn, imm, imm);
3764 else
3765 sprintf(cp, "%s\tr%u, [r%u]",
3766 mnemonic, rt, rn);
3767 return ERROR_OK;
3769 immediate:
3770 /* two indexed modes will write back rn */
3771 if (opcode & (1 << 21)) {
3772 if (opcode & (1 << 24)) /* pre-indexed */
3773 p2 = "]!";
3774 else { /* post-indexed */
3775 p1 = "]";
3776 p2 = "";
3780 imm <<= 2;
3781 sprintf(cp, "%s\tr%u, r%u, [r%u%s, #%s%u%s\t; %#2.2x",
3782 mnemonic, rt, rd, rn, p1,
3783 (opcode & (1 << 23)) ? "" : "-",
3784 imm, p2, imm);
3785 return ERROR_OK;
3787 literal:
3788 address = thumb_alignpc4(address);
3789 imm <<= 2;
3790 if (opcode & (1 << 23))
3791 address += imm;
3792 else
3793 address -= imm;
3794 sprintf(cp, "%s\tr%u, r%u, %#8.8" PRIx32,
3795 mnemonic, rt, rd, address);
3796 return ERROR_OK;
3799 static int t2ev_data_shift(uint32_t opcode, uint32_t address,
3800 struct arm_instruction *instruction, char *cp)
3802 int op = (opcode >> 21) & 0xf;
3803 int rd = (opcode >> 8) & 0xf;
3804 int rn = (opcode >> 16) & 0xf;
3805 int type = (opcode >> 4) & 0x3;
3806 int immed = (opcode >> 6) & 0x3;
3807 char *mnemonic;
3808 char *suffix = "";
3810 immed |= (opcode >> 10) & 0x1c;
3811 if (opcode & (1 << 20))
3812 suffix = "S";
3814 switch (op) {
3815 case 0:
3816 if (rd == 0xf) {
3817 if (!(opcode & (1 << 20)))
3818 return ERROR_COMMAND_SYNTAX_ERROR;
3819 instruction->type = ARM_TST;
3820 mnemonic = "TST";
3821 suffix = "";
3822 goto two;
3824 instruction->type = ARM_AND;
3825 mnemonic = "AND";
3826 break;
3827 case 1:
3828 instruction->type = ARM_BIC;
3829 mnemonic = "BIC";
3830 break;
3831 case 2:
3832 if (rn == 0xf) {
3833 instruction->type = ARM_MOV;
3834 switch (type) {
3835 case 0:
3836 if (immed == 0) {
3837 sprintf(cp, "MOV%s.W\tr%d, r%d",
3838 suffix, rd,
3839 (int) (opcode & 0xf));
3840 return ERROR_OK;
3842 mnemonic = "LSL";
3843 break;
3844 case 1:
3845 mnemonic = "LSR";
3846 break;
3847 case 2:
3848 mnemonic = "ASR";
3849 break;
3850 default:
3851 if (immed == 0) {
3852 sprintf(cp, "RRX%s\tr%d, r%d",
3853 suffix, rd,
3854 (int) (opcode & 0xf));
3855 return ERROR_OK;
3857 mnemonic = "ROR";
3858 break;
3860 goto immediate;
3861 } else {
3862 instruction->type = ARM_ORR;
3863 mnemonic = "ORR";
3865 break;
3866 case 3:
3867 if (rn == 0xf) {
3868 instruction->type = ARM_MVN;
3869 mnemonic = "MVN";
3870 rn = rd;
3871 goto two;
3872 } else {
3873 /* instruction->type = ARM_ORN; */
3874 mnemonic = "ORN";
3876 break;
3877 case 4:
3878 if (rd == 0xf) {
3879 if (!(opcode & (1 << 20)))
3880 return ERROR_COMMAND_SYNTAX_ERROR;
3881 instruction->type = ARM_TEQ;
3882 mnemonic = "TEQ";
3883 suffix = "";
3884 goto two;
3886 instruction->type = ARM_EOR;
3887 mnemonic = "EOR";
3888 break;
3889 case 8:
3890 if (rd == 0xf) {
3891 if (!(opcode & (1 << 20)))
3892 return ERROR_COMMAND_SYNTAX_ERROR;
3893 instruction->type = ARM_CMN;
3894 mnemonic = "CMN";
3895 suffix = "";
3896 goto two;
3898 instruction->type = ARM_ADD;
3899 mnemonic = "ADD";
3900 break;
3901 case 0xa:
3902 instruction->type = ARM_ADC;
3903 mnemonic = "ADC";
3904 break;
3905 case 0xb:
3906 instruction->type = ARM_SBC;
3907 mnemonic = "SBC";
3908 break;
3909 case 0xd:
3910 if (rd == 0xf) {
3911 if (!(opcode & (1 << 21)))
3912 return ERROR_COMMAND_SYNTAX_ERROR;
3913 instruction->type = ARM_CMP;
3914 mnemonic = "CMP";
3915 suffix = "";
3916 goto two;
3918 instruction->type = ARM_SUB;
3919 mnemonic = "SUB";
3920 break;
3921 case 0xe:
3922 instruction->type = ARM_RSB;
3923 mnemonic = "RSB";
3924 break;
3925 default:
3926 return ERROR_COMMAND_SYNTAX_ERROR;
3929 sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
3930 mnemonic, suffix, rd, rn, (int) (opcode & 0xf));
3932 shift:
3933 cp = strchr(cp, 0);
3935 switch (type) {
3936 case 0:
3937 if (immed == 0)
3938 return ERROR_OK;
3939 suffix = "LSL";
3940 break;
3941 case 1:
3942 suffix = "LSR";
3943 if (immed == 32)
3944 immed = 0;
3945 break;
3946 case 2:
3947 suffix = "ASR";
3948 if (immed == 32)
3949 immed = 0;
3950 break;
3951 case 3:
3952 if (immed == 0) {
3953 strcpy(cp, ", RRX");
3954 return ERROR_OK;
3956 suffix = "ROR";
3957 break;
3959 sprintf(cp, ", %s #%d", suffix, immed ? immed : 32);
3960 return ERROR_OK;
3962 two:
3963 sprintf(cp, "%s%s.W\tr%d, r%d",
3964 mnemonic, suffix, rn, (int) (opcode & 0xf));
3965 goto shift;
3967 immediate:
3968 sprintf(cp, "%s%s.W\tr%d, r%d, #%d",
3969 mnemonic, suffix, rd,
3970 (int) (opcode & 0xf), immed ? immed : 32);
3971 return ERROR_OK;
3974 static int t2ev_data_reg(uint32_t opcode, uint32_t address,
3975 struct arm_instruction *instruction, char *cp)
3977 char *mnemonic;
3978 char *suffix = "";
3980 if (((opcode >> 4) & 0xf) == 0) {
3981 switch ((opcode >> 21) & 0x7) {
3982 case 0:
3983 mnemonic = "LSL";
3984 break;
3985 case 1:
3986 mnemonic = "LSR";
3987 break;
3988 case 2:
3989 mnemonic = "ASR";
3990 break;
3991 case 3:
3992 mnemonic = "ROR";
3993 break;
3994 default:
3995 return ERROR_COMMAND_SYNTAX_ERROR;
3998 instruction->type = ARM_MOV;
3999 if (opcode & (1 << 20))
4000 suffix = "S";
4001 sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
4002 mnemonic, suffix,
4003 (int) (opcode >> 8) & 0xf,
4004 (int) (opcode >> 16) & 0xf,
4005 (int) (opcode >> 0) & 0xf);
4007 } else if (opcode & (1 << 7)) {
4008 switch ((opcode >> 20) & 0xf) {
4009 case 0:
4010 case 1:
4011 case 4:
4012 case 5:
4013 switch ((opcode >> 4) & 0x3) {
4014 case 1:
4015 suffix = ", ROR #8";
4016 break;
4017 case 2:
4018 suffix = ", ROR #16";
4019 break;
4020 case 3:
4021 suffix = ", ROR #24";
4022 break;
4024 sprintf(cp, "%cXT%c.W\tr%d, r%d%s",
4025 (opcode & (1 << 24)) ? 'U' : 'S',
4026 (opcode & (1 << 26)) ? 'B' : 'H',
4027 (int) (opcode >> 8) & 0xf,
4028 (int) (opcode >> 0) & 0xf,
4029 suffix);
4030 break;
4031 case 8:
4032 case 9:
4033 case 0xa:
4034 case 0xb:
4035 if (opcode & (1 << 6))
4036 return ERROR_COMMAND_SYNTAX_ERROR;
4037 if (((opcode >> 12) & 0xf) != 0xf)
4038 return ERROR_COMMAND_SYNTAX_ERROR;
4039 if (!(opcode & (1 << 20)))
4040 return ERROR_COMMAND_SYNTAX_ERROR;
4042 switch (((opcode >> 19) & 0x04)
4043 | ((opcode >> 4) & 0x3)) {
4044 case 0:
4045 mnemonic = "REV.W";
4046 break;
4047 case 1:
4048 mnemonic = "REV16.W";
4049 break;
4050 case 2:
4051 mnemonic = "RBIT";
4052 break;
4053 case 3:
4054 mnemonic = "REVSH.W";
4055 break;
4056 case 4:
4057 mnemonic = "CLZ";
4058 break;
4059 default:
4060 return ERROR_COMMAND_SYNTAX_ERROR;
4062 sprintf(cp, "%s\tr%d, r%d",
4063 mnemonic,
4064 (int) (opcode >> 8) & 0xf,
4065 (int) (opcode >> 0) & 0xf);
4066 break;
4067 default:
4068 return ERROR_COMMAND_SYNTAX_ERROR;
4072 return ERROR_OK;
4075 static int t2ev_load_word(uint32_t opcode, uint32_t address,
4076 struct arm_instruction *instruction, char *cp)
4078 int rn = (opcode >> 16) & 0xf;
4079 int immed;
4081 instruction->type = ARM_LDR;
4083 if (rn == 0xf) {
4084 immed = opcode & 0x0fff;
4085 if ((opcode & (1 << 23)) == 0)
4086 immed = -immed;
4087 sprintf(cp, "LDR\tr%d, %#8.8" PRIx32,
4088 (int) (opcode >> 12) & 0xf,
4089 thumb_alignpc4(address) + immed);
4090 return ERROR_OK;
4093 if (opcode & (1 << 23)) {
4094 immed = opcode & 0x0fff;
4095 sprintf(cp, "LDR.W\tr%d, [r%d, #%d]\t; %#3.3x",
4096 (int) (opcode >> 12) & 0xf,
4097 rn, immed, immed);
4098 return ERROR_OK;
4101 if (!(opcode & (0x3f << 6))) {
4102 sprintf(cp, "LDR.W\tr%d, [r%d, r%d, LSL #%d]",
4103 (int) (opcode >> 12) & 0xf,
4105 (int) (opcode >> 0) & 0xf,
4106 (int) (opcode >> 4) & 0x3);
4107 return ERROR_OK;
4111 if (((opcode >> 8) & 0xf) == 0xe) {
4112 immed = opcode & 0x00ff;
4114 sprintf(cp, "LDRT\tr%d, [r%d, #%d]\t; %#2.2x",
4115 (int) (opcode >> 12) & 0xf,
4116 rn, immed, immed);
4117 return ERROR_OK;
4120 if (((opcode >> 8) & 0xf) == 0xc || (opcode & 0x0900) == 0x0900) {
4121 char *p1 = "]", *p2 = "";
4123 if (!(opcode & 0x0500))
4124 return ERROR_COMMAND_SYNTAX_ERROR;
4126 immed = opcode & 0x00ff;
4128 /* two indexed modes will write back rn */
4129 if (opcode & 0x100) {
4130 if (opcode & 0x400) /* pre-indexed */
4131 p2 = "]!";
4132 else { /* post-indexed */
4133 p1 = "]";
4134 p2 = "";
4138 sprintf(cp, "LDR\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
4139 (int) (opcode >> 12) & 0xf,
4140 rn, p1,
4141 (opcode & 0x200) ? "" : "-",
4142 immed, p2, immed);
4143 return ERROR_OK;
4146 return ERROR_COMMAND_SYNTAX_ERROR;
4149 static int t2ev_load_byte_hints(uint32_t opcode, uint32_t address,
4150 struct arm_instruction *instruction, char *cp)
4152 int rn = (opcode >> 16) & 0xf;
4153 int rt = (opcode >> 12) & 0xf;
4154 int op2 = (opcode >> 6) & 0x3f;
4155 unsigned immed;
4156 char *p1 = "", *p2 = "]";
4157 char *mnemonic;
4159 switch ((opcode >> 23) & 0x3) {
4160 case 0:
4161 if ((rn & rt) == 0xf) {
4162 pld_literal:
4163 immed = opcode & 0xfff;
4164 address = thumb_alignpc4(address);
4165 if (opcode & (1 << 23))
4166 address += immed;
4167 else
4168 address -= immed;
4169 sprintf(cp, "PLD\tr%d, %#8.8" PRIx32,
4170 rt, address);
4171 return ERROR_OK;
4173 if (rn == 0x0f && rt != 0x0f) {
4174 ldrb_literal:
4175 immed = opcode & 0xfff;
4176 address = thumb_alignpc4(address);
4177 if (opcode & (1 << 23))
4178 address += immed;
4179 else
4180 address -= immed;
4181 sprintf(cp, "LDRB\tr%d, %#8.8" PRIx32,
4182 rt, address);
4183 return ERROR_OK;
4185 if (rn == 0x0f)
4186 break;
4187 if ((op2 & 0x3c) == 0x38) {
4188 immed = opcode & 0xff;
4189 sprintf(cp, "LDRBT\tr%d, [r%d, #%d]\t; %#2.2x",
4190 rt, rn, immed, immed);
4191 return ERROR_OK;
4193 if ((op2 & 0x3c) == 0x30) {
4194 if (rt == 0x0f) {
4195 immed = opcode & 0xff;
4196 immed = -immed;
4197 preload_immediate:
4198 p1 = (opcode & (1 << 21)) ? "W" : "";
4199 sprintf(cp, "PLD%s\t[r%d, #%d]\t; %#6.6x",
4200 p1, rn, immed, immed);
4201 return ERROR_OK;
4203 mnemonic = "LDRB";
4204 ldrxb_immediate_t3:
4205 immed = opcode & 0xff;
4206 if (!(opcode & 0x200))
4207 immed = -immed;
4209 /* two indexed modes will write back rn */
4210 if (opcode & 0x100) {
4211 if (opcode & 0x400) /* pre-indexed */
4212 p2 = "]!";
4213 else { /* post-indexed */
4214 p1 = "]";
4215 p2 = "";
4218 ldrxb_immediate_t2:
4219 sprintf(cp, "%s\tr%d, [r%d%s, #%d%s\t; %#8.8x",
4220 mnemonic, rt, rn, p1,
4221 immed, p2, immed);
4222 return ERROR_OK;
4224 if ((op2 & 0x24) == 0x24) {
4225 mnemonic = "LDRB";
4226 goto ldrxb_immediate_t3;
4228 if (op2 == 0) {
4229 int rm = opcode & 0xf;
4231 if (rt == 0x0f)
4232 sprintf(cp, "PLD\t");
4233 else
4234 sprintf(cp, "LDRB.W\tr%d, ", rt);
4235 immed = (opcode >> 4) & 0x3;
4236 cp = strchr(cp, 0);
4237 sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed);
4238 return ERROR_OK;
4240 break;
4241 case 1:
4242 if ((rn & rt) == 0xf)
4243 goto pld_literal;
4244 if (rt == 0xf) {
4245 immed = opcode & 0xfff;
4246 goto preload_immediate;
4248 if (rn == 0x0f)
4249 goto ldrb_literal;
4250 mnemonic = "LDRB.W";
4251 immed = opcode & 0xfff;
4252 goto ldrxb_immediate_t2;
4253 case 2:
4254 if ((rn & rt) == 0xf) {
4255 immed = opcode & 0xfff;
4256 address = thumb_alignpc4(address);
4257 if (opcode & (1 << 23))
4258 address += immed;
4259 else
4260 address -= immed;
4261 sprintf(cp, "PLI\t%#8.8" PRIx32, address);
4262 return ERROR_OK;
4264 if (rn == 0xf && rt != 0xf) {
4265 ldrsb_literal:
4266 immed = opcode & 0xfff;
4267 address = thumb_alignpc4(address);
4268 if (opcode & (1 << 23))
4269 address += immed;
4270 else
4271 address -= immed;
4272 sprintf(cp, "LDRSB\t%#8.8" PRIx32, address);
4273 return ERROR_OK;
4275 if (rn == 0xf)
4276 break;
4277 if ((op2 & 0x3c) == 0x38) {
4278 immed = opcode & 0xff;
4279 sprintf(cp, "LDRSBT\tr%d, [r%d, #%d]\t; %#2.2x",
4280 rt, rn, immed, immed);
4281 return ERROR_OK;
4283 if ((op2 & 0x3c) == 0x30) {
4284 if (rt == 0xf) {
4285 immed = opcode & 0xff;
4286 immed = -immed; /* pli */
4287 sprintf(cp, "PLI\t[r%d, #%d]\t; -%#2.2x",
4288 rn, immed, -immed);
4289 return ERROR_OK;
4291 mnemonic = "LDRSB";
4292 goto ldrxb_immediate_t3;
4294 if ((op2 & 0x24) == 0x24) {
4295 mnemonic = "LDRSB";
4296 goto ldrxb_immediate_t3;
4298 if (op2 == 0) {
4299 int rm = opcode & 0xf;
4301 if (rt == 0x0f)
4302 sprintf(cp, "PLI\t");
4303 else
4304 sprintf(cp, "LDRSB.W\tr%d, ", rt);
4305 immed = (opcode >> 4) & 0x3;
4306 cp = strchr(cp, 0);
4307 sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed);
4308 return ERROR_OK;
4310 break;
4311 case 3:
4312 if (rt == 0xf) {
4313 immed = opcode & 0xfff;
4314 sprintf(cp, "PLI\t[r%d, #%d]\t; %#3.3x",
4315 rn, immed, immed);
4316 return ERROR_OK;
4318 if (rn == 0xf)
4319 goto ldrsb_literal;
4320 immed = opcode & 0xfff;
4321 mnemonic = "LDRSB";
4322 goto ldrxb_immediate_t2;
4325 return ERROR_COMMAND_SYNTAX_ERROR;
4328 static int t2ev_load_halfword(uint32_t opcode, uint32_t address,
4329 struct arm_instruction *instruction, char *cp)
4331 int rn = (opcode >> 16) & 0xf;
4332 int rt = (opcode >> 12) & 0xf;
4333 int op2 = (opcode >> 6) & 0x3f;
4334 char *sign = "";
4335 unsigned immed;
4337 if (rt == 0xf) {
4338 sprintf(cp, "HINT (UNALLOCATED)");
4339 return ERROR_OK;
4342 if (opcode & (1 << 24))
4343 sign = "S";
4345 if ((opcode & (1 << 23)) == 0) {
4346 if (rn == 0xf) {
4347 ldrh_literal:
4348 immed = opcode & 0xfff;
4349 address = thumb_alignpc4(address);
4350 if (opcode & (1 << 23))
4351 address += immed;
4352 else
4353 address -= immed;
4354 sprintf(cp, "LDR%sH\tr%d, %#8.8" PRIx32,
4355 sign, rt, address);
4356 return ERROR_OK;
4358 if (op2 == 0) {
4359 int rm = opcode & 0xf;
4361 immed = (opcode >> 4) & 0x3;
4362 sprintf(cp, "LDR%sH.W\tr%d, [r%d, r%d, LSL #%d]",
4363 sign, rt, rn, rm, immed);
4364 return ERROR_OK;
4366 if ((op2 & 0x3c) == 0x38) {
4367 immed = opcode & 0xff;
4368 sprintf(cp, "LDR%sHT\tr%d, [r%d, #%d]\t; %#2.2x",
4369 sign, rt, rn, immed, immed);
4370 return ERROR_OK;
4372 if ((op2 & 0x3c) == 0x30 || (op2 & 0x24) == 0x24) {
4373 char *p1 = "", *p2 = "]";
4375 immed = opcode & 0xff;
4376 if (!(opcode & 0x200))
4377 immed = -immed;
4379 /* two indexed modes will write back rn */
4380 if (opcode & 0x100) {
4381 if (opcode & 0x400) /* pre-indexed */
4382 p2 = "]!";
4383 else { /* post-indexed */
4384 p1 = "]";
4385 p2 = "";
4388 sprintf(cp, "LDR%sH\tr%d, [r%d%s, #%d%s\t; %#8.8x",
4389 sign, rt, rn, p1, immed, p2, immed);
4390 return ERROR_OK;
4392 } else {
4393 if (rn == 0xf)
4394 goto ldrh_literal;
4396 immed = opcode & 0xfff;
4397 sprintf(cp, "LDR%sH%s\tr%d, [r%d, #%d]\t; %#6.6x",
4398 sign, *sign ? "" : ".W",
4399 rt, rn, immed, immed);
4400 return ERROR_OK;
4403 return ERROR_COMMAND_SYNTAX_ERROR;
4407 * REVISIT for Thumb2 instructions, instruction->type and friends aren't
4408 * always set. That means eventual arm_simulate_step() support for Thumb2
4409 * will need work in this area.
4411 int thumb2_opcode(struct target *target, uint32_t address, struct arm_instruction *instruction)
4413 int retval;
4414 uint16_t op;
4415 uint32_t opcode;
4416 char *cp;
4418 /* clear low bit ... it's set on function pointers */
4419 address &= ~1;
4421 /* clear fields, to avoid confusion */
4422 memset(instruction, 0, sizeof(struct arm_instruction));
4424 /* read first halfword, see if this is the only one */
4425 retval = target_read_u16(target, address, &op);
4426 if (retval != ERROR_OK)
4427 return retval;
4429 switch (op & 0xf800) {
4430 case 0xf800:
4431 case 0xf000:
4432 case 0xe800:
4433 /* 32-bit instructions */
4434 instruction->instruction_size = 4;
4435 opcode = op << 16;
4436 retval = target_read_u16(target, address + 2, &op);
4437 if (retval != ERROR_OK)
4438 return retval;
4439 opcode |= op;
4440 instruction->opcode = opcode;
4441 break;
4442 default:
4443 /* 16-bit: Thumb1 + IT + CBZ/CBNZ + ... */
4444 return thumb_evaluate_opcode(op, address, instruction);
4447 snprintf(instruction->text, 128,
4448 "0x%8.8" PRIx32 " 0x%8.8" PRIx32 "\t",
4449 address, opcode);
4450 cp = strchr(instruction->text, 0);
4451 retval = ERROR_FAIL;
4453 /* ARMv7-M: A5.3.1 Data processing (modified immediate) */
4454 if ((opcode & 0x1a008000) == 0x10000000)
4455 retval = t2ev_data_mod_immed(opcode, address, instruction, cp);
4457 /* ARMv7-M: A5.3.3 Data processing (plain binary immediate) */
4458 else if ((opcode & 0x1a008000) == 0x12000000)
4459 retval = t2ev_data_immed(opcode, address, instruction, cp);
4461 /* ARMv7-M: A5.3.4 Branches and miscellaneous control */
4462 else if ((opcode & 0x18008000) == 0x10008000)
4463 retval = t2ev_b_misc(opcode, address, instruction, cp);
4465 /* ARMv7-M: A5.3.5 Load/store multiple */
4466 else if ((opcode & 0x1e400000) == 0x08000000)
4467 retval = t2ev_ldm_stm(opcode, address, instruction, cp);
4469 /* ARMv7-M: A5.3.6 Load/store dual or exclusive, table branch */
4470 else if ((opcode & 0x1e400000) == 0x08400000)
4471 retval = t2ev_ldrex_strex(opcode, address, instruction, cp);
4473 /* ARMv7-M: A5.3.7 Load word */
4474 else if ((opcode & 0x1f700000) == 0x18500000)
4475 retval = t2ev_load_word(opcode, address, instruction, cp);
4477 /* ARMv7-M: A5.3.8 Load halfword, unallocated memory hints */
4478 else if ((opcode & 0x1e700000) == 0x18300000)
4479 retval = t2ev_load_halfword(opcode, address, instruction, cp);
4481 /* ARMv7-M: A5.3.9 Load byte, memory hints */
4482 else if ((opcode & 0x1e700000) == 0x18100000)
4483 retval = t2ev_load_byte_hints(opcode, address, instruction, cp);
4485 /* ARMv7-M: A5.3.10 Store single data item */
4486 else if ((opcode & 0x1f100000) == 0x18000000)
4487 retval = t2ev_store_single(opcode, address, instruction, cp);
4489 /* ARMv7-M: A5.3.11 Data processing (shifted register) */
4490 else if ((opcode & 0x1e000000) == 0x0a000000)
4491 retval = t2ev_data_shift(opcode, address, instruction, cp);
4493 /* ARMv7-M: A5.3.12 Data processing (register)
4494 * and A5.3.13 Miscellaneous operations
4496 else if ((opcode & 0x1f000000) == 0x1a000000)
4497 retval = t2ev_data_reg(opcode, address, instruction, cp);
4499 /* ARMv7-M: A5.3.14 Multiply, and multiply accumulate */
4500 else if ((opcode & 0x1f800000) == 0x1b000000)
4501 retval = t2ev_mul32(opcode, address, instruction, cp);
4503 /* ARMv7-M: A5.3.15 Long multiply, long multiply accumulate, divide */
4504 else if ((opcode & 0x1f800000) == 0x1b800000)
4505 retval = t2ev_mul64_div(opcode, address, instruction, cp);
4507 if (retval == ERROR_OK)
4508 return retval;
4511 * Thumb2 also supports coprocessor, ThumbEE, and DSP/Media (SIMD)
4512 * instructions; not yet handled here.
4515 if (retval == ERROR_COMMAND_SYNTAX_ERROR) {
4516 instruction->type = ARM_UNDEFINED_INSTRUCTION;
4517 strcpy(cp, "UNDEFINED OPCODE");
4518 return ERROR_OK;
4521 LOG_DEBUG("Can't decode 32-bit Thumb2 yet (opcode=%08" PRIx32 ")",
4522 opcode);
4524 strcpy(cp, "(32-bit Thumb2 ...)");
4525 return ERROR_OK;
4528 int arm_access_size(struct arm_instruction *instruction)
4530 if ((instruction->type == ARM_LDRB)
4531 || (instruction->type == ARM_LDRBT)
4532 || (instruction->type == ARM_LDRSB)
4533 || (instruction->type == ARM_STRB)
4534 || (instruction->type == ARM_STRBT))
4535 return 1;
4536 else if ((instruction->type == ARM_LDRH)
4537 || (instruction->type == ARM_LDRSH)
4538 || (instruction->type == ARM_STRH))
4539 return 2;
4540 else if ((instruction->type == ARM_LDR)
4541 || (instruction->type == ARM_LDRT)
4542 || (instruction->type == ARM_STR)
4543 || (instruction->type == ARM_STRT))
4544 return 4;
4545 else if ((instruction->type == ARM_LDRD)
4546 || (instruction->type == ARM_STRD))
4547 return 8;
4548 else {
4549 LOG_ERROR("BUG: instruction type %i isn't a load/store instruction",
4550 instruction->type);
4551 return 0;