ARM: cygwin complile fixes
[openocd.git] / src / target / arm_disassembler.c
blob5c8ad6a00746a8fd4156d12b9f4f106ec730e678
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, write to the *
19 * Free Software Foundation, Inc., *
20 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
21 ***************************************************************************/
22 #ifdef HAVE_CONFIG_H
23 #include "config.h"
24 #endif
26 #include "target.h"
27 #include "arm_disassembler.h"
28 #include <helper/log.h>
32 * This disassembler supports two main functions for OpenOCD:
34 * - Various "disassemble" commands. OpenOCD can serve as a
35 * machine-language debugger, without help from GDB.
37 * - Single stepping. Not all ARM cores support hardware single
38 * stepping. To work without that support, the debugger must
39 * be able to decode instructions to find out where to put a
40 * "next instruction" breakpoint.
42 * In addition, interpretation of ETM trace data needs some of the
43 * decoding mechanisms.
45 * At this writing (September 2009) neither function is complete.
47 * - ARM decoding
48 * * Old-style syntax (not UAL) is generally used
49 * * VFP instructions are not understood (ARMv5 and later)
50 * except as coprocessor 10/11 operations
51 * * Most ARM instructions through ARMv6 are decoded, but some
52 * of the post-ARMv4 opcodes may not be handled yet
53 * * NEON instructions are not understood (ARMv7-A)
55 * - Thumb/Thumb2 decoding
56 * * UAL syntax should be consistently used
57 * * Any Thumb2 instructions used in Cortex-M3 (ARMv7-M) should
58 * be handled properly. Accordingly, so should the subset
59 * used in Cortex-M0/M1; and "original" 16-bit Thumb from
60 * ARMv4T and ARMv5T.
61 * * Conditional effects of Thumb2 "IT" (if-then) instructions
62 * are not handled: the affected instructions are not shown
63 * with their now-conditional suffixes.
64 * * Some ARMv6 and ARMv7-M Thumb2 instructions may not be
65 * handled (minimally for coprocessor access).
66 * * SIMD instructions, and some other Thumb2 instructions
67 * from ARMv7-A, are not understood.
69 * - ThumbEE decoding
70 * * As a Thumb2 variant, the Thumb2 comments (above) apply.
71 * * Opcodes changed by ThumbEE mode are not handled; these
72 * instructions wrongly decode as LDM and STM.
74 * - Jazelle decoding ... no support whatsoever for Jazelle mode
75 * or decoding. ARM encourages use of the more generic ThumbEE
76 * mode, instead of Jazelle mode, in current chips.
78 * - Single-step/emulation ... spotty support, which is only weakly
79 * tested. Thumb2 is not supported. (Arguably a full simulator
80 * is not needed to support just single stepping. Recognizing
81 * branch vs non-branch instructions suffices, except when the
82 * instruction faults and triggers a synchronous exception which
83 * can be intercepted using other means.)
85 * ARM DDI 0406B "ARM Architecture Reference Manual, ARM v7-A and
86 * ARM v7-R edition" gives the most complete coverage of the various
87 * generations of ARM instructions. At this writing it is publicly
88 * accessible to anyone willing to create an account at the ARM
89 * web site; see http://www.arm.com/documentation/ for information.
91 * ARM DDI 0403C "ARMv7-M Architecture Reference Manual" provides
92 * more details relevant to the Thumb2-only processors (such as
93 * the Cortex-M implementations).
96 /* textual represenation of the condition field */
97 /* ALways (default) is ommitted (empty string) */
98 static const char *arm_condition_strings[] =
100 "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", "HI", "LS", "GE", "LT", "GT", "LE", "", "NV"
103 /* make up for C's missing ROR */
104 static uint32_t ror(uint32_t value, int places)
106 return (value >> places) | (value << (32 - places));
109 static int evaluate_unknown(uint32_t opcode,
110 uint32_t address, struct arm_instruction *instruction)
112 instruction->type = ARM_UNDEFINED_INSTRUCTION;
113 snprintf(instruction->text, 128,
114 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
115 "\tUNDEFINED INSTRUCTION", address, opcode);
116 return ERROR_OK;
119 static int evaluate_pld(uint32_t opcode,
120 uint32_t address, struct arm_instruction *instruction)
122 /* PLD */
123 if ((opcode & 0x0d70f000) == 0x0550f000)
125 instruction->type = ARM_PLD;
127 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD ...TODO...", address, opcode);
129 return ERROR_OK;
131 return evaluate_unknown(opcode, address, instruction);
134 static int evaluate_srs(uint32_t opcode,
135 uint32_t address, struct arm_instruction *instruction)
137 const char *wback = (opcode & (1 << 21)) ? "!" : "";
138 const char *mode = "";
140 switch ((opcode >> 23) & 0x3) {
141 case 0:
142 mode = "DA";
143 break;
144 case 1:
145 /* "IA" is default */
146 break;
147 case 2:
148 mode = "DB";
149 break;
150 case 3:
151 mode = "IB";
152 break;
155 switch (opcode & 0x0e500000) {
156 case 0x08400000:
157 snprintf(instruction->text, 128, "0x%8.8" PRIx32
158 "\t0x%8.8" PRIx32
159 "\tSRS%s\tSP%s, #%d",
160 address, opcode,
161 mode, wback,
162 (unsigned)(opcode & 0x1f));
163 break;
164 case 0x08100000:
165 snprintf(instruction->text, 128, "0x%8.8" PRIx32
166 "\t0x%8.8" PRIx32
167 "\tRFE%s\tr%d%s",
168 address, opcode,
169 mode,
170 (unsigned)((opcode >> 16) & 0xf), wback);
171 break;
172 default:
173 return evaluate_unknown(opcode, address, instruction);
175 return ERROR_OK;
178 static int evaluate_swi(uint32_t opcode,
179 uint32_t address, struct arm_instruction *instruction)
181 instruction->type = ARM_SWI;
183 snprintf(instruction->text, 128,
184 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSVC %#6.6" PRIx32,
185 address, opcode, (opcode & 0xffffff));
187 return ERROR_OK;
190 static int evaluate_blx_imm(uint32_t opcode,
191 uint32_t address, struct arm_instruction *instruction)
193 int offset;
194 uint32_t immediate;
195 uint32_t target_address;
197 instruction->type = ARM_BLX;
198 immediate = opcode & 0x00ffffff;
200 /* sign extend 24-bit immediate */
201 if (immediate & 0x00800000)
202 offset = 0xff000000 | immediate;
203 else
204 offset = immediate;
206 /* shift two bits left */
207 offset <<= 2;
209 /* odd/event halfword */
210 if (opcode & 0x01000000)
211 offset |= 0x2;
213 target_address = address + 8 + offset;
215 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX 0x%8.8" PRIx32 "", address, opcode, target_address);
217 instruction->info.b_bl_bx_blx.reg_operand = -1;
218 instruction->info.b_bl_bx_blx.target_address = target_address;
220 return ERROR_OK;
223 static int evaluate_b_bl(uint32_t opcode,
224 uint32_t address, struct arm_instruction *instruction)
226 uint8_t L;
227 uint32_t immediate;
228 int offset;
229 uint32_t target_address;
231 immediate = opcode & 0x00ffffff;
232 L = (opcode & 0x01000000) >> 24;
234 /* sign extend 24-bit immediate */
235 if (immediate & 0x00800000)
236 offset = 0xff000000 | immediate;
237 else
238 offset = immediate;
240 /* shift two bits left */
241 offset <<= 2;
243 target_address = address + 8 + offset;
245 if (L)
246 instruction->type = ARM_BL;
247 else
248 instruction->type = ARM_B;
250 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tB%s%s 0x%8.8" PRIx32 , address, opcode,
251 (L) ? "L" : "", COND(opcode), target_address);
253 instruction->info.b_bl_bx_blx.reg_operand = -1;
254 instruction->info.b_bl_bx_blx.target_address = target_address;
256 return ERROR_OK;
259 /* Coprocessor load/store and double register transfers */
260 /* both normal and extended instruction space (condition field b1111) */
261 static int evaluate_ldc_stc_mcrr_mrrc(uint32_t opcode,
262 uint32_t address, struct arm_instruction *instruction)
264 uint8_t cp_num = (opcode & 0xf00) >> 8;
266 /* MCRR or MRRC */
267 if (((opcode & 0x0ff00000) == 0x0c400000) || ((opcode & 0x0ff00000) == 0x0c400000))
269 uint8_t cp_opcode, Rd, Rn, CRm;
270 char *mnemonic;
272 cp_opcode = (opcode & 0xf0) >> 4;
273 Rd = (opcode & 0xf000) >> 12;
274 Rn = (opcode & 0xf0000) >> 16;
275 CRm = (opcode & 0xf);
277 /* MCRR */
278 if ((opcode & 0x0ff00000) == 0x0c400000)
280 instruction->type = ARM_MCRR;
281 mnemonic = "MCRR";
284 /* MRRC */
285 if ((opcode & 0x0ff00000) == 0x0c500000)
287 instruction->type = ARM_MRRC;
288 mnemonic = "MRRC";
291 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, %x, r%i, r%i, c%i",
292 address, opcode, mnemonic, COND(opcode), cp_num, cp_opcode, Rd, Rn, CRm);
294 else /* LDC or STC */
296 uint8_t CRd, Rn, offset;
297 uint8_t U, N;
298 char *mnemonic;
299 char addressing_mode[32];
301 CRd = (opcode & 0xf000) >> 12;
302 Rn = (opcode & 0xf0000) >> 16;
303 offset = (opcode & 0xff);
305 /* load/store */
306 if (opcode & 0x00100000)
308 instruction->type = ARM_LDC;
309 mnemonic = "LDC";
311 else
313 instruction->type = ARM_STC;
314 mnemonic = "STC";
317 U = (opcode & 0x00800000) >> 23;
318 N = (opcode & 0x00400000) >> 22;
320 /* addressing modes */
321 if ((opcode & 0x01200000) == 0x01000000) /* immediate offset */
322 snprintf(addressing_mode, 32, "[r%i, #%s0x%2.2x*4]", Rn, (U) ? "" : "-", offset);
323 else if ((opcode & 0x01200000) == 0x01200000) /* immediate pre-indexed */
324 snprintf(addressing_mode, 32, "[r%i, #%s0x%2.2x*4]!", Rn, (U) ? "" : "-", offset);
325 else if ((opcode & 0x01200000) == 0x00200000) /* immediate post-indexed */
326 snprintf(addressing_mode, 32, "[r%i], #%s0x%2.2x*4", Rn, (U) ? "" : "-", offset);
327 else if ((opcode & 0x01200000) == 0x00000000) /* unindexed */
328 snprintf(addressing_mode, 32, "[r%i], #0x%2.2x", Rn, offset);
330 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s p%i, c%i, %s",
331 address, opcode, mnemonic, ((opcode & 0xf0000000) == 0xf0000000) ? COND(opcode) : "2",
332 (N) ? "L" : "",
333 cp_num, CRd, addressing_mode);
336 return ERROR_OK;
339 /* Coprocessor data processing instructions */
340 /* Coprocessor register transfer instructions */
341 /* both normal and extended instruction space (condition field b1111) */
342 static int evaluate_cdp_mcr_mrc(uint32_t opcode,
343 uint32_t address, struct arm_instruction *instruction)
345 const char *cond;
346 char* mnemonic;
347 uint8_t cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2;
349 cond = ((opcode & 0xf0000000) == 0xf0000000) ? "2" : COND(opcode);
350 cp_num = (opcode & 0xf00) >> 8;
351 CRd_Rd = (opcode & 0xf000) >> 12;
352 CRn = (opcode & 0xf0000) >> 16;
353 CRm = (opcode & 0xf);
354 opcode_2 = (opcode & 0xe0) >> 5;
356 /* CDP or MRC/MCR */
357 if (opcode & 0x00000010) /* bit 4 set -> MRC/MCR */
359 if (opcode & 0x00100000) /* bit 20 set -> MRC */
361 instruction->type = ARM_MRC;
362 mnemonic = "MRC";
364 else /* bit 20 not set -> MCR */
366 instruction->type = ARM_MCR;
367 mnemonic = "MCR";
370 opcode_1 = (opcode & 0x00e00000) >> 21;
372 snprintf(instruction->text, 128, "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",
373 address, opcode, mnemonic, cond,
374 cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2);
376 else /* bit 4 not set -> CDP */
378 instruction->type = ARM_CDP;
379 mnemonic = "CDP";
381 opcode_1 = (opcode & 0x00f00000) >> 20;
383 snprintf(instruction->text, 128, "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",
384 address, opcode, mnemonic, cond,
385 cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2);
388 return ERROR_OK;
391 /* Load/store instructions */
392 static int evaluate_load_store(uint32_t opcode,
393 uint32_t address, struct arm_instruction *instruction)
395 uint8_t I, P, U, B, W, L;
396 uint8_t Rn, Rd;
397 char *operation; /* "LDR" or "STR" */
398 char *suffix; /* "", "B", "T", "BT" */
399 char offset[32];
401 /* examine flags */
402 I = (opcode & 0x02000000) >> 25;
403 P = (opcode & 0x01000000) >> 24;
404 U = (opcode & 0x00800000) >> 23;
405 B = (opcode & 0x00400000) >> 22;
406 W = (opcode & 0x00200000) >> 21;
407 L = (opcode & 0x00100000) >> 20;
409 /* target register */
410 Rd = (opcode & 0xf000) >> 12;
412 /* base register */
413 Rn = (opcode & 0xf0000) >> 16;
415 instruction->info.load_store.Rd = Rd;
416 instruction->info.load_store.Rn = Rn;
417 instruction->info.load_store.U = U;
419 /* determine operation */
420 if (L)
421 operation = "LDR";
422 else
423 operation = "STR";
425 /* determine instruction type and suffix */
426 if (B)
428 if ((P == 0) && (W == 1))
430 if (L)
431 instruction->type = ARM_LDRBT;
432 else
433 instruction->type = ARM_STRBT;
434 suffix = "BT";
436 else
438 if (L)
439 instruction->type = ARM_LDRB;
440 else
441 instruction->type = ARM_STRB;
442 suffix = "B";
445 else
447 if ((P == 0) && (W == 1))
449 if (L)
450 instruction->type = ARM_LDRT;
451 else
452 instruction->type = ARM_STRT;
453 suffix = "T";
455 else
457 if (L)
458 instruction->type = ARM_LDR;
459 else
460 instruction->type = ARM_STR;
461 suffix = "";
465 if (!I) /* #+-<offset_12> */
467 uint32_t offset_12 = (opcode & 0xfff);
468 if (offset_12)
469 snprintf(offset, 32, ", #%s0x%" PRIx32 "", (U) ? "" : "-", offset_12);
470 else
471 snprintf(offset, 32, "%s", "");
473 instruction->info.load_store.offset_mode = 0;
474 instruction->info.load_store.offset.offset = offset_12;
476 else /* either +-<Rm> or +-<Rm>, <shift>, #<shift_imm> */
478 uint8_t shift_imm, shift;
479 uint8_t Rm;
481 shift_imm = (opcode & 0xf80) >> 7;
482 shift = (opcode & 0x60) >> 5;
483 Rm = (opcode & 0xf);
485 /* LSR encodes a shift by 32 bit as 0x0 */
486 if ((shift == 0x1) && (shift_imm == 0x0))
487 shift_imm = 0x20;
489 /* ASR encodes a shift by 32 bit as 0x0 */
490 if ((shift == 0x2) && (shift_imm == 0x0))
491 shift_imm = 0x20;
493 /* ROR by 32 bit is actually a RRX */
494 if ((shift == 0x3) && (shift_imm == 0x0))
495 shift = 0x4;
497 instruction->info.load_store.offset_mode = 1;
498 instruction->info.load_store.offset.reg.Rm = Rm;
499 instruction->info.load_store.offset.reg.shift = shift;
500 instruction->info.load_store.offset.reg.shift_imm = shift_imm;
502 if ((shift_imm == 0x0) && (shift == 0x0)) /* +-<Rm> */
504 snprintf(offset, 32, ", %sr%i", (U) ? "" : "-", Rm);
506 else /* +-<Rm>, <Shift>, #<shift_imm> */
508 switch (shift)
510 case 0x0: /* LSL */
511 snprintf(offset, 32, ", %sr%i, LSL #0x%x", (U) ? "" : "-", Rm, shift_imm);
512 break;
513 case 0x1: /* LSR */
514 snprintf(offset, 32, ", %sr%i, LSR #0x%x", (U) ? "" : "-", Rm, shift_imm);
515 break;
516 case 0x2: /* ASR */
517 snprintf(offset, 32, ", %sr%i, ASR #0x%x", (U) ? "" : "-", Rm, shift_imm);
518 break;
519 case 0x3: /* ROR */
520 snprintf(offset, 32, ", %sr%i, ROR #0x%x", (U) ? "" : "-", Rm, shift_imm);
521 break;
522 case 0x4: /* RRX */
523 snprintf(offset, 32, ", %sr%i, RRX", (U) ? "" : "-", Rm);
524 break;
529 if (P == 1)
531 if (W == 0) /* offset */
533 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]",
534 address, opcode, operation, COND(opcode), suffix,
535 Rd, Rn, offset);
537 instruction->info.load_store.index_mode = 0;
539 else /* pre-indexed */
541 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]!",
542 address, opcode, operation, COND(opcode), suffix,
543 Rd, Rn, offset);
545 instruction->info.load_store.index_mode = 1;
548 else /* post-indexed */
550 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i]%s",
551 address, opcode, operation, COND(opcode), suffix,
552 Rd, Rn, offset);
554 instruction->info.load_store.index_mode = 2;
557 return ERROR_OK;
560 static int evaluate_extend(uint32_t opcode, uint32_t address, char *cp)
562 unsigned rm = (opcode >> 0) & 0xf;
563 unsigned rd = (opcode >> 12) & 0xf;
564 unsigned rn = (opcode >> 16) & 0xf;
565 char *type, *rot;
567 switch ((opcode >> 24) & 0x3) {
568 case 0:
569 type = "B16";
570 break;
571 case 1:
572 sprintf(cp, "UNDEFINED");
573 return ARM_UNDEFINED_INSTRUCTION;
574 case 2:
575 type = "B";
576 break;
577 default:
578 type = "H";
579 break;
582 switch ((opcode >> 10) & 0x3) {
583 case 0:
584 rot = "";
585 break;
586 case 1:
587 rot = ", ROR #8";
588 break;
589 case 2:
590 rot = ", ROR #16";
591 break;
592 default:
593 rot = ", ROR #24";
594 break;
597 if (rn == 0xf) {
598 sprintf(cp, "%cXT%s%s\tr%d, r%d%s",
599 (opcode & (1 << 22)) ? 'U' : 'S',
600 type, COND(opcode),
601 rd, rm, rot);
602 return ARM_MOV;
603 } else {
604 sprintf(cp, "%cXTA%s%s\tr%d, r%d, r%d%s",
605 (opcode & (1 << 22)) ? 'U' : 'S',
606 type, COND(opcode),
607 rd, rn, rm, rot);
608 return ARM_ADD;
612 static int evaluate_p_add_sub(uint32_t opcode, uint32_t address, char *cp)
614 char *prefix;
615 char *op;
616 int type;
618 switch ((opcode >> 20) & 0x7) {
619 case 1:
620 prefix = "S";
621 break;
622 case 2:
623 prefix = "Q";
624 break;
625 case 3:
626 prefix = "SH";
627 break;
628 case 5:
629 prefix = "U";
630 break;
631 case 6:
632 prefix = "UQ";
633 break;
634 case 7:
635 prefix = "UH";
636 break;
637 default:
638 goto undef;
641 switch ((opcode >> 5) & 0x7) {
642 case 0:
643 op = "ADD16";
644 type = ARM_ADD;
645 break;
646 case 1:
647 op = "ADDSUBX";
648 type = ARM_ADD;
649 break;
650 case 2:
651 op = "SUBADDX";
652 type = ARM_SUB;
653 break;
654 case 3:
655 op = "SUB16";
656 type = ARM_SUB;
657 break;
658 case 4:
659 op = "ADD8";
660 type = ARM_ADD;
661 break;
662 case 7:
663 op = "SUB8";
664 type = ARM_SUB;
665 break;
666 default:
667 goto undef;
670 sprintf(cp, "%s%s%s\tr%d, r%d, r%d", prefix, op, COND(opcode),
671 (int) (opcode >> 12) & 0xf,
672 (int) (opcode >> 16) & 0xf,
673 (int) (opcode >> 0) & 0xf);
674 return type;
676 undef:
677 /* these opcodes might be used someday */
678 sprintf(cp, "UNDEFINED");
679 return ARM_UNDEFINED_INSTRUCTION;
682 /* ARMv6 and later support "media" instructions (includes SIMD) */
683 static int evaluate_media(uint32_t opcode, uint32_t address,
684 struct arm_instruction *instruction)
686 char *cp = instruction->text;
687 char *mnemonic = NULL;
689 sprintf(cp,
690 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t",
691 address, opcode);
692 cp = strchr(cp, 0);
694 /* parallel add/subtract */
695 if ((opcode & 0x01800000) == 0x00000000) {
696 instruction->type = evaluate_p_add_sub(opcode, address, cp);
697 return ERROR_OK;
700 /* halfword pack */
701 if ((opcode & 0x01f00020) == 0x00800000) {
702 char *type, *shift;
703 unsigned imm = (unsigned) (opcode >> 7) & 0x1f;
705 if (opcode & (1 << 6)) {
706 type = "TB";
707 shift = "ASR";
708 if (imm == 0)
709 imm = 32;
710 } else {
711 type = "BT";
712 shift = "LSL";
714 sprintf(cp, "PKH%s%s\tr%d, r%d, r%d, %s #%d",
715 type, COND(opcode),
716 (int) (opcode >> 12) & 0xf,
717 (int) (opcode >> 16) & 0xf,
718 (int) (opcode >> 0) & 0xf,
719 shift, imm);
720 return ERROR_OK;
723 /* word saturate */
724 if ((opcode & 0x01a00020) == 0x00a00000) {
725 char *shift;
726 unsigned imm = (unsigned) (opcode >> 7) & 0x1f;
728 if (opcode & (1 << 6)) {
729 shift = "ASR";
730 if (imm == 0)
731 imm = 32;
732 } else {
733 shift = "LSL";
736 sprintf(cp, "%cSAT%s\tr%d, #%d, r%d, %s #%d",
737 (opcode & (1 << 22)) ? 'U' : 'S',
738 COND(opcode),
739 (int) (opcode >> 12) & 0xf,
740 (int) (opcode >> 16) & 0x1f,
741 (int) (opcode >> 0) & 0xf,
742 shift, imm);
743 return ERROR_OK;
746 /* sign extension */
747 if ((opcode & 0x018000f0) == 0x00800070) {
748 instruction->type = evaluate_extend(opcode, address, cp);
749 return ERROR_OK;
752 /* multiplies */
753 if ((opcode & 0x01f00080) == 0x01000000) {
754 unsigned rn = (opcode >> 12) & 0xf;
756 if (rn != 0xf)
757 sprintf(cp, "SML%cD%s%s\tr%d, r%d, r%d, r%d",
758 (opcode & (1 << 6)) ? 'S' : 'A',
759 (opcode & (1 << 5)) ? "X" : "",
760 COND(opcode),
761 (int) (opcode >> 16) & 0xf,
762 (int) (opcode >> 0) & 0xf,
763 (int) (opcode >> 8) & 0xf,
764 rn);
765 else
766 sprintf(cp, "SMU%cD%s%s\tr%d, r%d, r%d",
767 (opcode & (1 << 6)) ? 'S' : 'A',
768 (opcode & (1 << 5)) ? "X" : "",
769 COND(opcode),
770 (int) (opcode >> 16) & 0xf,
771 (int) (opcode >> 0) & 0xf,
772 (int) (opcode >> 8) & 0xf);
773 return ERROR_OK;
775 if ((opcode & 0x01f00000) == 0x01400000) {
776 sprintf(cp, "SML%cLD%s%s\tr%d, r%d, r%d, r%d",
777 (opcode & (1 << 6)) ? 'S' : 'A',
778 (opcode & (1 << 5)) ? "X" : "",
779 COND(opcode),
780 (int) (opcode >> 12) & 0xf,
781 (int) (opcode >> 16) & 0xf,
782 (int) (opcode >> 0) & 0xf,
783 (int) (opcode >> 8) & 0xf);
784 return ERROR_OK;
786 if ((opcode & 0x01f00000) == 0x01500000) {
787 unsigned rn = (opcode >> 12) & 0xf;
789 switch (opcode & 0xc0) {
790 case 3:
791 if (rn == 0xf)
792 goto undef;
793 /* FALL THROUGH */
794 case 0:
795 break;
796 default:
797 goto undef;
800 if (rn != 0xf)
801 sprintf(cp, "SMML%c%s%s\tr%d, r%d, r%d, r%d",
802 (opcode & (1 << 6)) ? 'S' : 'A',
803 (opcode & (1 << 5)) ? "R" : "",
804 COND(opcode),
805 (int) (opcode >> 16) & 0xf,
806 (int) (opcode >> 0) & 0xf,
807 (int) (opcode >> 8) & 0xf,
808 rn);
809 else
810 sprintf(cp, "SMMUL%s%s\tr%d, r%d, r%d",
811 (opcode & (1 << 5)) ? "R" : "",
812 COND(opcode),
813 (int) (opcode >> 16) & 0xf,
814 (int) (opcode >> 0) & 0xf,
815 (int) (opcode >> 8) & 0xf);
816 return ERROR_OK;
820 /* simple matches against the remaining decode bits */
821 switch (opcode & 0x01f000f0) {
822 case 0x00a00030:
823 case 0x00e00030:
824 /* parallel halfword saturate */
825 sprintf(cp, "%cSAT16%s\tr%d, #%d, r%d",
826 (opcode & (1 << 22)) ? 'U' : 'S',
827 COND(opcode),
828 (int) (opcode >> 12) & 0xf,
829 (int) (opcode >> 16) & 0xf,
830 (int) (opcode >> 0) & 0xf);
831 return ERROR_OK;
832 case 0x00b00030:
833 mnemonic = "REV";
834 break;
835 case 0x00b000b0:
836 mnemonic = "REV16";
837 break;
838 case 0x00f000b0:
839 mnemonic = "REVSH";
840 break;
841 case 0x008000b0:
842 /* select bytes */
843 sprintf(cp, "SEL%s\tr%d, r%d, r%d", COND(opcode),
844 (int) (opcode >> 12) & 0xf,
845 (int) (opcode >> 16) & 0xf,
846 (int) (opcode >> 0) & 0xf);
847 return ERROR_OK;
848 case 0x01800010:
849 /* unsigned sum of absolute differences */
850 if (((opcode >> 12) & 0xf) == 0xf)
851 sprintf(cp, "USAD8%s\tr%d, r%d, r%d", COND(opcode),
852 (int) (opcode >> 16) & 0xf,
853 (int) (opcode >> 0) & 0xf,
854 (int) (opcode >> 8) & 0xf);
855 else
856 sprintf(cp, "USADA8%s\tr%d, r%d, r%d, r%d", COND(opcode),
857 (int) (opcode >> 16) & 0xf,
858 (int) (opcode >> 0) & 0xf,
859 (int) (opcode >> 8) & 0xf,
860 (int) (opcode >> 12) & 0xf);
861 return ERROR_OK;
863 if (mnemonic) {
864 unsigned rm = (opcode >> 0) & 0xf;
865 unsigned rd = (opcode >> 12) & 0xf;
867 sprintf(cp, "%s%s\tr%d, r%d", mnemonic, COND(opcode), rm, rd);
868 return ERROR_OK;
871 undef:
872 /* these opcodes might be used someday */
873 sprintf(cp, "UNDEFINED");
874 return ERROR_OK;
877 /* Miscellaneous load/store instructions */
878 static int evaluate_misc_load_store(uint32_t opcode,
879 uint32_t address, struct arm_instruction *instruction)
881 uint8_t P, U, I, W, L, S, H;
882 uint8_t Rn, Rd;
883 char *operation; /* "LDR" or "STR" */
884 char *suffix; /* "H", "SB", "SH", "D" */
885 char offset[32];
887 /* examine flags */
888 P = (opcode & 0x01000000) >> 24;
889 U = (opcode & 0x00800000) >> 23;
890 I = (opcode & 0x00400000) >> 22;
891 W = (opcode & 0x00200000) >> 21;
892 L = (opcode & 0x00100000) >> 20;
893 S = (opcode & 0x00000040) >> 6;
894 H = (opcode & 0x00000020) >> 5;
896 /* target register */
897 Rd = (opcode & 0xf000) >> 12;
899 /* base register */
900 Rn = (opcode & 0xf0000) >> 16;
902 instruction->info.load_store.Rd = Rd;
903 instruction->info.load_store.Rn = Rn;
904 instruction->info.load_store.U = U;
906 /* determine instruction type and suffix */
907 if (S) /* signed */
909 if (L) /* load */
911 if (H)
913 operation = "LDR";
914 instruction->type = ARM_LDRSH;
915 suffix = "SH";
917 else
919 operation = "LDR";
920 instruction->type = ARM_LDRSB;
921 suffix = "SB";
924 else /* there are no signed stores, so this is used to encode double-register load/stores */
926 suffix = "D";
927 if (H)
929 operation = "STR";
930 instruction->type = ARM_STRD;
932 else
934 operation = "LDR";
935 instruction->type = ARM_LDRD;
939 else /* unsigned */
941 suffix = "H";
942 if (L) /* load */
944 operation = "LDR";
945 instruction->type = ARM_LDRH;
947 else /* store */
949 operation = "STR";
950 instruction->type = ARM_STRH;
954 if (I) /* Immediate offset/index (#+-<offset_8>)*/
956 uint32_t offset_8 = ((opcode & 0xf00) >> 4) | (opcode & 0xf);
957 snprintf(offset, 32, "#%s0x%" PRIx32 "", (U) ? "" : "-", offset_8);
959 instruction->info.load_store.offset_mode = 0;
960 instruction->info.load_store.offset.offset = offset_8;
962 else /* Register offset/index (+-<Rm>) */
964 uint8_t Rm;
965 Rm = (opcode & 0xf);
966 snprintf(offset, 32, "%sr%i", (U) ? "" : "-", Rm);
968 instruction->info.load_store.offset_mode = 1;
969 instruction->info.load_store.offset.reg.Rm = Rm;
970 instruction->info.load_store.offset.reg.shift = 0x0;
971 instruction->info.load_store.offset.reg.shift_imm = 0x0;
974 if (P == 1)
976 if (W == 0) /* offset */
978 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]",
979 address, opcode, operation, COND(opcode), suffix,
980 Rd, Rn, offset);
982 instruction->info.load_store.index_mode = 0;
984 else /* pre-indexed */
986 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]!",
987 address, opcode, operation, COND(opcode), suffix,
988 Rd, Rn, offset);
990 instruction->info.load_store.index_mode = 1;
993 else /* post-indexed */
995 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i], %s",
996 address, opcode, operation, COND(opcode), suffix,
997 Rd, Rn, offset);
999 instruction->info.load_store.index_mode = 2;
1002 return ERROR_OK;
1005 /* Load/store multiples instructions */
1006 static int evaluate_ldm_stm(uint32_t opcode,
1007 uint32_t address, struct arm_instruction *instruction)
1009 uint8_t P, U, S, W, L, Rn;
1010 uint32_t register_list;
1011 char *addressing_mode;
1012 char *mnemonic;
1013 char reg_list[69];
1014 char *reg_list_p;
1015 int i;
1016 int first_reg = 1;
1018 P = (opcode & 0x01000000) >> 24;
1019 U = (opcode & 0x00800000) >> 23;
1020 S = (opcode & 0x00400000) >> 22;
1021 W = (opcode & 0x00200000) >> 21;
1022 L = (opcode & 0x00100000) >> 20;
1023 register_list = (opcode & 0xffff);
1024 Rn = (opcode & 0xf0000) >> 16;
1026 instruction->info.load_store_multiple.Rn = Rn;
1027 instruction->info.load_store_multiple.register_list = register_list;
1028 instruction->info.load_store_multiple.S = S;
1029 instruction->info.load_store_multiple.W = W;
1031 if (L)
1033 instruction->type = ARM_LDM;
1034 mnemonic = "LDM";
1036 else
1038 instruction->type = ARM_STM;
1039 mnemonic = "STM";
1042 if (P)
1044 if (U)
1046 instruction->info.load_store_multiple.addressing_mode = 1;
1047 addressing_mode = "IB";
1049 else
1051 instruction->info.load_store_multiple.addressing_mode = 3;
1052 addressing_mode = "DB";
1055 else
1057 if (U)
1059 instruction->info.load_store_multiple.addressing_mode = 0;
1060 /* "IA" is the default in UAL syntax */
1061 addressing_mode = "";
1063 else
1065 instruction->info.load_store_multiple.addressing_mode = 2;
1066 addressing_mode = "DA";
1070 reg_list_p = reg_list;
1071 for (i = 0; i <= 15; i++)
1073 if ((register_list >> i) & 1)
1075 if (first_reg)
1077 first_reg = 0;
1078 reg_list_p += snprintf(reg_list_p, (reg_list + 69 - reg_list_p), "r%i", i);
1080 else
1082 reg_list_p += snprintf(reg_list_p, (reg_list + 69 - reg_list_p), ", r%i", i);
1087 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i%s, {%s}%s",
1088 address, opcode, mnemonic, COND(opcode), addressing_mode,
1089 Rn, (W) ? "!" : "", reg_list, (S) ? "^" : "");
1091 return ERROR_OK;
1094 /* Multiplies, extra load/stores */
1095 static int evaluate_mul_and_extra_ld_st(uint32_t opcode,
1096 uint32_t address, struct arm_instruction *instruction)
1098 /* Multiply (accumulate) (long) and Swap/swap byte */
1099 if ((opcode & 0x000000f0) == 0x00000090)
1101 /* Multiply (accumulate) */
1102 if ((opcode & 0x0f800000) == 0x00000000)
1104 uint8_t Rm, Rs, Rn, Rd, S;
1105 Rm = opcode & 0xf;
1106 Rs = (opcode & 0xf00) >> 8;
1107 Rn = (opcode & 0xf000) >> 12;
1108 Rd = (opcode & 0xf0000) >> 16;
1109 S = (opcode & 0x00100000) >> 20;
1111 /* examine A bit (accumulate) */
1112 if (opcode & 0x00200000)
1114 instruction->type = ARM_MLA;
1115 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMLA%s%s r%i, r%i, r%i, r%i",
1116 address, opcode, COND(opcode), (S) ? "S" : "", Rd, Rm, Rs, Rn);
1118 else
1120 instruction->type = ARM_MUL;
1121 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMUL%s%s r%i, r%i, r%i",
1122 address, opcode, COND(opcode), (S) ? "S" : "", Rd, Rm, Rs);
1125 return ERROR_OK;
1128 /* Multiply (accumulate) long */
1129 if ((opcode & 0x0f800000) == 0x00800000)
1131 char* mnemonic = NULL;
1132 uint8_t Rm, Rs, RdHi, RdLow, S;
1133 Rm = opcode & 0xf;
1134 Rs = (opcode & 0xf00) >> 8;
1135 RdHi = (opcode & 0xf000) >> 12;
1136 RdLow = (opcode & 0xf0000) >> 16;
1137 S = (opcode & 0x00100000) >> 20;
1139 switch ((opcode & 0x00600000) >> 21)
1141 case 0x0:
1142 instruction->type = ARM_UMULL;
1143 mnemonic = "UMULL";
1144 break;
1145 case 0x1:
1146 instruction->type = ARM_UMLAL;
1147 mnemonic = "UMLAL";
1148 break;
1149 case 0x2:
1150 instruction->type = ARM_SMULL;
1151 mnemonic = "SMULL";
1152 break;
1153 case 0x3:
1154 instruction->type = ARM_SMLAL;
1155 mnemonic = "SMLAL";
1156 break;
1159 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, r%i, r%i",
1160 address, opcode, mnemonic, COND(opcode), (S) ? "S" : "",
1161 RdLow, RdHi, Rm, Rs);
1163 return ERROR_OK;
1166 /* Swap/swap byte */
1167 if ((opcode & 0x0f800000) == 0x01000000)
1169 uint8_t Rm, Rd, Rn;
1170 Rm = opcode & 0xf;
1171 Rd = (opcode & 0xf000) >> 12;
1172 Rn = (opcode & 0xf0000) >> 16;
1174 /* examine B flag */
1175 instruction->type = (opcode & 0x00400000) ? ARM_SWPB : ARM_SWP;
1177 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, [r%i]",
1178 address, opcode, (opcode & 0x00400000) ? "SWPB" : "SWP", COND(opcode), Rd, Rm, Rn);
1179 return ERROR_OK;
1184 return evaluate_misc_load_store(opcode, address, instruction);
1187 static int evaluate_mrs_msr(uint32_t opcode,
1188 uint32_t address, struct arm_instruction *instruction)
1190 int R = (opcode & 0x00400000) >> 22;
1191 char *PSR = (R) ? "SPSR" : "CPSR";
1193 /* Move register to status register (MSR) */
1194 if (opcode & 0x00200000)
1196 instruction->type = ARM_MSR;
1198 /* immediate variant */
1199 if (opcode & 0x02000000)
1201 uint8_t immediate = (opcode & 0xff);
1202 uint8_t rotate = (opcode & 0xf00);
1204 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, 0x%8.8" PRIx32 ,
1205 address, opcode, COND(opcode), PSR,
1206 (opcode & 0x10000) ? "c" : "",
1207 (opcode & 0x20000) ? "x" : "",
1208 (opcode & 0x40000) ? "s" : "",
1209 (opcode & 0x80000) ? "f" : "",
1210 ror(immediate, (rotate * 2))
1213 else /* register variant */
1215 uint8_t Rm = opcode & 0xf;
1216 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, r%i",
1217 address, opcode, COND(opcode), PSR,
1218 (opcode & 0x10000) ? "c" : "",
1219 (opcode & 0x20000) ? "x" : "",
1220 (opcode & 0x40000) ? "s" : "",
1221 (opcode & 0x80000) ? "f" : "",
1227 else /* Move status register to register (MRS) */
1229 uint8_t Rd;
1231 instruction->type = ARM_MRS;
1232 Rd = (opcode & 0x0000f000) >> 12;
1234 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMRS%s r%i, %s",
1235 address, opcode, COND(opcode), Rd, PSR);
1238 return ERROR_OK;
1241 /* Miscellaneous instructions */
1242 static int evaluate_misc_instr(uint32_t opcode,
1243 uint32_t address, struct arm_instruction *instruction)
1245 /* MRS/MSR */
1246 if ((opcode & 0x000000f0) == 0x00000000)
1248 evaluate_mrs_msr(opcode, address, instruction);
1251 /* BX */
1252 if ((opcode & 0x006000f0) == 0x00200010)
1254 uint8_t Rm;
1255 instruction->type = ARM_BX;
1256 Rm = opcode & 0xf;
1258 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBX%s r%i",
1259 address, opcode, COND(opcode), Rm);
1261 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1262 instruction->info.b_bl_bx_blx.target_address = -1;
1265 /* BXJ - "Jazelle" support (ARMv5-J) */
1266 if ((opcode & 0x006000f0) == 0x00200020)
1268 uint8_t Rm;
1269 instruction->type = ARM_BX;
1270 Rm = opcode & 0xf;
1272 snprintf(instruction->text, 128,
1273 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBXJ%s r%i",
1274 address, opcode, COND(opcode), Rm);
1276 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1277 instruction->info.b_bl_bx_blx.target_address = -1;
1280 /* CLZ */
1281 if ((opcode & 0x006000f0) == 0x00600010)
1283 uint8_t Rm, Rd;
1284 instruction->type = ARM_CLZ;
1285 Rm = opcode & 0xf;
1286 Rd = (opcode & 0xf000) >> 12;
1288 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCLZ%s r%i, r%i",
1289 address, opcode, COND(opcode), Rd, Rm);
1292 /* BLX(2) */
1293 if ((opcode & 0x006000f0) == 0x00200030)
1295 uint8_t Rm;
1296 instruction->type = ARM_BLX;
1297 Rm = opcode & 0xf;
1299 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX%s r%i",
1300 address, opcode, COND(opcode), Rm);
1302 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1303 instruction->info.b_bl_bx_blx.target_address = -1;
1306 /* Enhanced DSP add/subtracts */
1307 if ((opcode & 0x0000000f0) == 0x00000050)
1309 uint8_t Rm, Rd, Rn;
1310 char *mnemonic = NULL;
1311 Rm = opcode & 0xf;
1312 Rd = (opcode & 0xf000) >> 12;
1313 Rn = (opcode & 0xf0000) >> 16;
1315 switch ((opcode & 0x00600000) >> 21)
1317 case 0x0:
1318 instruction->type = ARM_QADD;
1319 mnemonic = "QADD";
1320 break;
1321 case 0x1:
1322 instruction->type = ARM_QSUB;
1323 mnemonic = "QSUB";
1324 break;
1325 case 0x2:
1326 instruction->type = ARM_QDADD;
1327 mnemonic = "QDADD";
1328 break;
1329 case 0x3:
1330 instruction->type = ARM_QDSUB;
1331 mnemonic = "QDSUB";
1332 break;
1335 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, r%i",
1336 address, opcode, mnemonic, COND(opcode), Rd, Rm, Rn);
1339 /* Software breakpoints */
1340 if ((opcode & 0x0000000f0) == 0x00000070)
1342 uint32_t immediate;
1343 instruction->type = ARM_BKPT;
1344 immediate = ((opcode & 0x000fff00) >> 4) | (opcode & 0xf);
1346 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBKPT 0x%4.4" PRIx32 "",
1347 address, opcode, immediate);
1350 /* Enhanced DSP multiplies */
1351 if ((opcode & 0x000000090) == 0x00000080)
1353 int x = (opcode & 0x20) >> 5;
1354 int y = (opcode & 0x40) >> 6;
1356 /* SMLA < x><y> */
1357 if ((opcode & 0x00600000) == 0x00000000)
1359 uint8_t Rd, Rm, Rs, Rn;
1360 instruction->type = ARM_SMLAxy;
1361 Rd = (opcode & 0xf0000) >> 16;
1362 Rm = (opcode & 0xf);
1363 Rs = (opcode & 0xf00) >> 8;
1364 Rn = (opcode & 0xf000) >> 12;
1366 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
1367 address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
1368 Rd, Rm, Rs, Rn);
1371 /* SMLAL < x><y> */
1372 if ((opcode & 0x00600000) == 0x00400000)
1374 uint8_t RdLow, RdHi, Rm, Rs;
1375 instruction->type = ARM_SMLAxy;
1376 RdHi = (opcode & 0xf0000) >> 16;
1377 RdLow = (opcode & 0xf000) >> 12;
1378 Rm = (opcode & 0xf);
1379 Rs = (opcode & 0xf00) >> 8;
1381 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
1382 address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
1383 RdLow, RdHi, Rm, Rs);
1386 /* SMLAW < y> */
1387 if (((opcode & 0x00600000) == 0x00100000) && (x == 0))
1389 uint8_t Rd, Rm, Rs, Rn;
1390 instruction->type = ARM_SMLAWy;
1391 Rd = (opcode & 0xf0000) >> 16;
1392 Rm = (opcode & 0xf);
1393 Rs = (opcode & 0xf00) >> 8;
1394 Rn = (opcode & 0xf000) >> 12;
1396 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLAW%s%s r%i, r%i, r%i, r%i",
1397 address, opcode, (y) ? "T" : "B", COND(opcode),
1398 Rd, Rm, Rs, Rn);
1401 /* SMUL < x><y> */
1402 if ((opcode & 0x00600000) == 0x00300000)
1404 uint8_t Rd, Rm, Rs;
1405 instruction->type = ARM_SMULxy;
1406 Rd = (opcode & 0xf0000) >> 16;
1407 Rm = (opcode & 0xf);
1408 Rs = (opcode & 0xf00) >> 8;
1410 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s%s r%i, r%i, r%i",
1411 address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
1412 Rd, Rm, Rs);
1415 /* SMULW < y> */
1416 if (((opcode & 0x00600000) == 0x00100000) && (x == 1))
1418 uint8_t Rd, Rm, Rs;
1419 instruction->type = ARM_SMULWy;
1420 Rd = (opcode & 0xf0000) >> 16;
1421 Rm = (opcode & 0xf);
1422 Rs = (opcode & 0xf00) >> 8;
1424 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s r%i, r%i, r%i",
1425 address, opcode, (y) ? "T" : "B", COND(opcode),
1426 Rd, Rm, Rs);
1430 return ERROR_OK;
1433 static int evaluate_data_proc(uint32_t opcode,
1434 uint32_t address, struct arm_instruction *instruction)
1436 uint8_t I, op, S, Rn, Rd;
1437 char *mnemonic = NULL;
1438 char shifter_operand[32];
1440 I = (opcode & 0x02000000) >> 25;
1441 op = (opcode & 0x01e00000) >> 21;
1442 S = (opcode & 0x00100000) >> 20;
1444 Rd = (opcode & 0xf000) >> 12;
1445 Rn = (opcode & 0xf0000) >> 16;
1447 instruction->info.data_proc.Rd = Rd;
1448 instruction->info.data_proc.Rn = Rn;
1449 instruction->info.data_proc.S = S;
1451 switch (op)
1453 case 0x0:
1454 instruction->type = ARM_AND;
1455 mnemonic = "AND";
1456 break;
1457 case 0x1:
1458 instruction->type = ARM_EOR;
1459 mnemonic = "EOR";
1460 break;
1461 case 0x2:
1462 instruction->type = ARM_SUB;
1463 mnemonic = "SUB";
1464 break;
1465 case 0x3:
1466 instruction->type = ARM_RSB;
1467 mnemonic = "RSB";
1468 break;
1469 case 0x4:
1470 instruction->type = ARM_ADD;
1471 mnemonic = "ADD";
1472 break;
1473 case 0x5:
1474 instruction->type = ARM_ADC;
1475 mnemonic = "ADC";
1476 break;
1477 case 0x6:
1478 instruction->type = ARM_SBC;
1479 mnemonic = "SBC";
1480 break;
1481 case 0x7:
1482 instruction->type = ARM_RSC;
1483 mnemonic = "RSC";
1484 break;
1485 case 0x8:
1486 instruction->type = ARM_TST;
1487 mnemonic = "TST";
1488 break;
1489 case 0x9:
1490 instruction->type = ARM_TEQ;
1491 mnemonic = "TEQ";
1492 break;
1493 case 0xa:
1494 instruction->type = ARM_CMP;
1495 mnemonic = "CMP";
1496 break;
1497 case 0xb:
1498 instruction->type = ARM_CMN;
1499 mnemonic = "CMN";
1500 break;
1501 case 0xc:
1502 instruction->type = ARM_ORR;
1503 mnemonic = "ORR";
1504 break;
1505 case 0xd:
1506 instruction->type = ARM_MOV;
1507 mnemonic = "MOV";
1508 break;
1509 case 0xe:
1510 instruction->type = ARM_BIC;
1511 mnemonic = "BIC";
1512 break;
1513 case 0xf:
1514 instruction->type = ARM_MVN;
1515 mnemonic = "MVN";
1516 break;
1519 if (I) /* immediate shifter operand (#<immediate>)*/
1521 uint8_t immed_8 = opcode & 0xff;
1522 uint8_t rotate_imm = (opcode & 0xf00) >> 8;
1523 uint32_t immediate;
1525 immediate = ror(immed_8, rotate_imm * 2);
1527 snprintf(shifter_operand, 32, "#0x%" PRIx32 "", immediate);
1529 instruction->info.data_proc.variant = 0;
1530 instruction->info.data_proc.shifter_operand.immediate.immediate = immediate;
1532 else /* register-based shifter operand */
1534 uint8_t shift, Rm;
1535 shift = (opcode & 0x60) >> 5;
1536 Rm = (opcode & 0xf);
1538 if ((opcode & 0x10) != 0x10) /* Immediate shifts ("<Rm>" or "<Rm>, <shift> #<shift_immediate>") */
1540 uint8_t shift_imm;
1541 shift_imm = (opcode & 0xf80) >> 7;
1543 instruction->info.data_proc.variant = 1;
1544 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1545 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = shift_imm;
1546 instruction->info.data_proc.shifter_operand.immediate_shift.shift = shift;
1548 /* LSR encodes a shift by 32 bit as 0x0 */
1549 if ((shift == 0x1) && (shift_imm == 0x0))
1550 shift_imm = 0x20;
1552 /* ASR encodes a shift by 32 bit as 0x0 */
1553 if ((shift == 0x2) && (shift_imm == 0x0))
1554 shift_imm = 0x20;
1556 /* ROR by 32 bit is actually a RRX */
1557 if ((shift == 0x3) && (shift_imm == 0x0))
1558 shift = 0x4;
1560 if ((shift_imm == 0x0) && (shift == 0x0))
1562 snprintf(shifter_operand, 32, "r%i", Rm);
1564 else
1566 if (shift == 0x0) /* LSL */
1568 snprintf(shifter_operand, 32, "r%i, LSL #0x%x", Rm, shift_imm);
1570 else if (shift == 0x1) /* LSR */
1572 snprintf(shifter_operand, 32, "r%i, LSR #0x%x", Rm, shift_imm);
1574 else if (shift == 0x2) /* ASR */
1576 snprintf(shifter_operand, 32, "r%i, ASR #0x%x", Rm, shift_imm);
1578 else if (shift == 0x3) /* ROR */
1580 snprintf(shifter_operand, 32, "r%i, ROR #0x%x", Rm, shift_imm);
1582 else if (shift == 0x4) /* RRX */
1584 snprintf(shifter_operand, 32, "r%i, RRX", Rm);
1588 else /* Register shifts ("<Rm>, <shift> <Rs>") */
1590 uint8_t Rs = (opcode & 0xf00) >> 8;
1592 instruction->info.data_proc.variant = 2;
1593 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rm;
1594 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rs;
1595 instruction->info.data_proc.shifter_operand.register_shift.shift = shift;
1597 if (shift == 0x0) /* LSL */
1599 snprintf(shifter_operand, 32, "r%i, LSL r%i", Rm, Rs);
1601 else if (shift == 0x1) /* LSR */
1603 snprintf(shifter_operand, 32, "r%i, LSR r%i", Rm, Rs);
1605 else if (shift == 0x2) /* ASR */
1607 snprintf(shifter_operand, 32, "r%i, ASR r%i", Rm, Rs);
1609 else if (shift == 0x3) /* ROR */
1611 snprintf(shifter_operand, 32, "r%i, ROR r%i", Rm, Rs);
1616 if ((op < 0x8) || (op == 0xc) || (op == 0xe)) /* <opcode3>{<cond>}{S} <Rd>, <Rn>, <shifter_operand> */
1618 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, %s",
1619 address, opcode, mnemonic, COND(opcode),
1620 (S) ? "S" : "", Rd, Rn, shifter_operand);
1622 else if ((op == 0xd) || (op == 0xf)) /* <opcode1>{<cond>}{S} <Rd>, <shifter_operand> */
1624 if (opcode == 0xe1a00000) /* print MOV r0,r0 as NOP */
1625 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tNOP",address, opcode);
1626 else
1627 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, %s",
1628 address, opcode, mnemonic, COND(opcode),
1629 (S) ? "S" : "", Rd, shifter_operand);
1631 else /* <opcode2>{<cond>} <Rn>, <shifter_operand> */
1633 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, %s",
1634 address, opcode, mnemonic, COND(opcode),
1635 Rn, shifter_operand);
1638 return ERROR_OK;
1641 int arm_evaluate_opcode(uint32_t opcode, uint32_t address, struct arm_instruction *instruction)
1643 /* clear fields, to avoid confusion */
1644 memset(instruction, 0, sizeof(struct arm_instruction));
1645 instruction->opcode = opcode;
1646 instruction->instruction_size = 4;
1648 /* catch opcodes with condition field [31:28] = b1111 */
1649 if ((opcode & 0xf0000000) == 0xf0000000)
1651 /* Undefined instruction (or ARMv5E cache preload PLD) */
1652 if ((opcode & 0x08000000) == 0x00000000)
1653 return evaluate_pld(opcode, address, instruction);
1655 /* Undefined instruction (or ARMv6+ SRS/RFE) */
1656 if ((opcode & 0x0e000000) == 0x08000000)
1657 return evaluate_srs(opcode, address, instruction);
1659 /* Branch and branch with link and change to Thumb */
1660 if ((opcode & 0x0e000000) == 0x0a000000)
1661 return evaluate_blx_imm(opcode, address, instruction);
1663 /* Extended coprocessor opcode space (ARMv5 and higher)*/
1664 /* Coprocessor load/store and double register transfers */
1665 if ((opcode & 0x0e000000) == 0x0c000000)
1666 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1668 /* Coprocessor data processing */
1669 if ((opcode & 0x0f000100) == 0x0c000000)
1670 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1672 /* Coprocessor register transfers */
1673 if ((opcode & 0x0f000010) == 0x0c000010)
1674 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1676 /* Undefined instruction */
1677 if ((opcode & 0x0f000000) == 0x0f000000)
1679 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1680 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1681 return ERROR_OK;
1685 /* catch opcodes with [27:25] = b000 */
1686 if ((opcode & 0x0e000000) == 0x00000000)
1688 /* Multiplies, extra load/stores */
1689 if ((opcode & 0x00000090) == 0x00000090)
1690 return evaluate_mul_and_extra_ld_st(opcode, address, instruction);
1692 /* Miscellaneous instructions */
1693 if ((opcode & 0x0f900000) == 0x01000000)
1694 return evaluate_misc_instr(opcode, address, instruction);
1696 return evaluate_data_proc(opcode, address, instruction);
1699 /* catch opcodes with [27:25] = b001 */
1700 if ((opcode & 0x0e000000) == 0x02000000)
1702 /* Undefined instruction */
1703 if ((opcode & 0x0fb00000) == 0x03000000)
1705 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1706 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1707 return ERROR_OK;
1710 /* Move immediate to status register */
1711 if ((opcode & 0x0fb00000) == 0x03200000)
1712 return evaluate_mrs_msr(opcode, address, instruction);
1714 return evaluate_data_proc(opcode, address, instruction);
1718 /* catch opcodes with [27:25] = b010 */
1719 if ((opcode & 0x0e000000) == 0x04000000)
1721 /* Load/store immediate offset */
1722 return evaluate_load_store(opcode, address, instruction);
1725 /* catch opcodes with [27:25] = b011 */
1726 if ((opcode & 0x0e000000) == 0x06000000)
1728 /* Load/store register offset */
1729 if ((opcode & 0x00000010) == 0x00000000)
1730 return evaluate_load_store(opcode, address, instruction);
1732 /* Architecturally Undefined instruction
1733 * ... don't expect these to ever be used
1735 if ((opcode & 0x07f000f0) == 0x07f000f0)
1737 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1738 snprintf(instruction->text, 128,
1739 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEF",
1740 address, opcode);
1741 return ERROR_OK;
1744 /* "media" instructions */
1745 return evaluate_media(opcode, address, instruction);
1748 /* catch opcodes with [27:25] = b100 */
1749 if ((opcode & 0x0e000000) == 0x08000000)
1751 /* Load/store multiple */
1752 return evaluate_ldm_stm(opcode, address, instruction);
1755 /* catch opcodes with [27:25] = b101 */
1756 if ((opcode & 0x0e000000) == 0x0a000000)
1758 /* Branch and branch with link */
1759 return evaluate_b_bl(opcode, address, instruction);
1762 /* catch opcodes with [27:25] = b110 */
1763 if ((opcode & 0x0e000000) == 0x0a000000)
1765 /* Coprocessor load/store and double register transfers */
1766 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1769 /* catch opcodes with [27:25] = b111 */
1770 if ((opcode & 0x0e000000) == 0x0e000000)
1772 /* Software interrupt */
1773 if ((opcode & 0x0f000000) == 0x0f000000)
1774 return evaluate_swi(opcode, address, instruction);
1776 /* Coprocessor data processing */
1777 if ((opcode & 0x0f000010) == 0x0e000000)
1778 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1780 /* Coprocessor register transfers */
1781 if ((opcode & 0x0f000010) == 0x0e000010)
1782 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1785 LOG_ERROR("should never reach this point");
1786 return -1;
1789 static int evaluate_b_bl_blx_thumb(uint16_t opcode,
1790 uint32_t address, struct arm_instruction *instruction)
1792 uint32_t offset = opcode & 0x7ff;
1793 uint32_t opc = (opcode >> 11) & 0x3;
1794 uint32_t target_address;
1795 char *mnemonic = NULL;
1797 /* sign extend 11-bit offset */
1798 if (((opc == 0) || (opc == 2)) && (offset & 0x00000400))
1799 offset = 0xfffff800 | offset;
1801 target_address = address + 4 + (offset << 1);
1803 switch (opc)
1805 /* unconditional branch */
1806 case 0:
1807 instruction->type = ARM_B;
1808 mnemonic = "B";
1809 break;
1810 /* BLX suffix */
1811 case 1:
1812 instruction->type = ARM_BLX;
1813 mnemonic = "BLX";
1814 target_address &= 0xfffffffc;
1815 break;
1816 /* BL/BLX prefix */
1817 case 2:
1818 instruction->type = ARM_UNKNOWN_INSTUCTION;
1819 mnemonic = "prefix";
1820 target_address = offset << 12;
1821 break;
1822 /* BL suffix */
1823 case 3:
1824 instruction->type = ARM_BL;
1825 mnemonic = "BL";
1826 break;
1829 /* TODO: deal correctly with dual opcode (prefixed) BL/BLX;
1830 * these are effectively 32-bit instructions even in Thumb1. For
1831 * disassembly, it's simplest to always use the Thumb2 decoder.
1833 * But some cores will evidently handle them as two instructions,
1834 * where exceptions may occur between the two. The ETMv3.2+ ID
1835 * register has a bit which exposes this behavior.
1838 snprintf(instruction->text, 128,
1839 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%#8.8" PRIx32,
1840 address, opcode, mnemonic, target_address);
1842 instruction->info.b_bl_bx_blx.reg_operand = -1;
1843 instruction->info.b_bl_bx_blx.target_address = target_address;
1845 return ERROR_OK;
1848 static int evaluate_add_sub_thumb(uint16_t opcode,
1849 uint32_t address, struct arm_instruction *instruction)
1851 uint8_t Rd = (opcode >> 0) & 0x7;
1852 uint8_t Rn = (opcode >> 3) & 0x7;
1853 uint8_t Rm_imm = (opcode >> 6) & 0x7;
1854 uint32_t opc = opcode & (1 << 9);
1855 uint32_t reg_imm = opcode & (1 << 10);
1856 char *mnemonic;
1858 if (opc)
1860 instruction->type = ARM_SUB;
1861 mnemonic = "SUBS";
1863 else
1865 /* REVISIT: if reg_imm == 0, display as "MOVS" */
1866 instruction->type = ARM_ADD;
1867 mnemonic = "ADDS";
1870 instruction->info.data_proc.Rd = Rd;
1871 instruction->info.data_proc.Rn = Rn;
1872 instruction->info.data_proc.S = 1;
1874 if (reg_imm)
1876 instruction->info.data_proc.variant = 0; /*immediate*/
1877 instruction->info.data_proc.shifter_operand.immediate.immediate = Rm_imm;
1878 snprintf(instruction->text, 128,
1879 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%d",
1880 address, opcode, mnemonic, Rd, Rn, Rm_imm);
1882 else
1884 instruction->info.data_proc.variant = 1; /*immediate shift*/
1885 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm_imm;
1886 snprintf(instruction->text, 128,
1887 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, r%i",
1888 address, opcode, mnemonic, Rd, Rn, Rm_imm);
1891 return ERROR_OK;
1894 static int evaluate_shift_imm_thumb(uint16_t opcode,
1895 uint32_t address, struct arm_instruction *instruction)
1897 uint8_t Rd = (opcode >> 0) & 0x7;
1898 uint8_t Rm = (opcode >> 3) & 0x7;
1899 uint8_t imm = (opcode >> 6) & 0x1f;
1900 uint8_t opc = (opcode >> 11) & 0x3;
1901 char *mnemonic = NULL;
1903 switch (opc)
1905 case 0:
1906 instruction->type = ARM_MOV;
1907 mnemonic = "LSLS";
1908 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 0;
1909 break;
1910 case 1:
1911 instruction->type = ARM_MOV;
1912 mnemonic = "LSRS";
1913 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 1;
1914 break;
1915 case 2:
1916 instruction->type = ARM_MOV;
1917 mnemonic = "ASRS";
1918 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 2;
1919 break;
1922 if ((imm == 0) && (opc != 0))
1923 imm = 32;
1925 instruction->info.data_proc.Rd = Rd;
1926 instruction->info.data_proc.Rn = -1;
1927 instruction->info.data_proc.S = 1;
1929 instruction->info.data_proc.variant = 1; /*immediate_shift*/
1930 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1931 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = imm;
1933 snprintf(instruction->text, 128,
1934 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%#2.2x" ,
1935 address, opcode, mnemonic, Rd, Rm, imm);
1937 return ERROR_OK;
1940 static int evaluate_data_proc_imm_thumb(uint16_t opcode,
1941 uint32_t address, struct arm_instruction *instruction)
1943 uint8_t imm = opcode & 0xff;
1944 uint8_t Rd = (opcode >> 8) & 0x7;
1945 uint32_t opc = (opcode >> 11) & 0x3;
1946 char *mnemonic = NULL;
1948 instruction->info.data_proc.Rd = Rd;
1949 instruction->info.data_proc.Rn = Rd;
1950 instruction->info.data_proc.S = 1;
1951 instruction->info.data_proc.variant = 0; /*immediate*/
1952 instruction->info.data_proc.shifter_operand.immediate.immediate = imm;
1954 switch (opc)
1956 case 0:
1957 instruction->type = ARM_MOV;
1958 mnemonic = "MOVS";
1959 instruction->info.data_proc.Rn = -1;
1960 break;
1961 case 1:
1962 instruction->type = ARM_CMP;
1963 mnemonic = "CMP";
1964 instruction->info.data_proc.Rd = -1;
1965 break;
1966 case 2:
1967 instruction->type = ARM_ADD;
1968 mnemonic = "ADDS";
1969 break;
1970 case 3:
1971 instruction->type = ARM_SUB;
1972 mnemonic = "SUBS";
1973 break;
1976 snprintf(instruction->text, 128,
1977 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, #%#2.2x",
1978 address, opcode, mnemonic, Rd, imm);
1980 return ERROR_OK;
1983 static int evaluate_data_proc_thumb(uint16_t opcode,
1984 uint32_t address, struct arm_instruction *instruction)
1986 uint8_t high_reg, op, Rm, Rd,H1,H2;
1987 char *mnemonic = NULL;
1988 bool nop = false;
1990 high_reg = (opcode & 0x0400) >> 10;
1991 op = (opcode & 0x03C0) >> 6;
1993 Rd = (opcode & 0x0007);
1994 Rm = (opcode & 0x0038) >> 3;
1995 H1 = (opcode & 0x0080) >> 7;
1996 H2 = (opcode & 0x0040) >> 6;
1998 instruction->info.data_proc.Rd = Rd;
1999 instruction->info.data_proc.Rn = Rd;
2000 instruction->info.data_proc.S = (!high_reg || (instruction->type == ARM_CMP));
2001 instruction->info.data_proc.variant = 1 /*immediate shift*/;
2002 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
2004 if (high_reg)
2006 Rd |= H1 << 3;
2007 Rm |= H2 << 3;
2008 op >>= 2;
2010 switch (op)
2012 case 0x0:
2013 instruction->type = ARM_ADD;
2014 mnemonic = "ADD";
2015 break;
2016 case 0x1:
2017 instruction->type = ARM_CMP;
2018 mnemonic = "CMP";
2019 break;
2020 case 0x2:
2021 instruction->type = ARM_MOV;
2022 mnemonic = "MOV";
2023 if (Rd == Rm)
2024 nop = true;
2025 break;
2026 case 0x3:
2027 if ((opcode & 0x7) == 0x0)
2029 instruction->info.b_bl_bx_blx.reg_operand = Rm;
2030 if (H1)
2032 instruction->type = ARM_BLX;
2033 snprintf(instruction->text, 128,
2034 "0x%8.8" PRIx32
2035 " 0x%4.4x \tBLX\tr%i",
2036 address, opcode, Rm);
2038 else
2040 instruction->type = ARM_BX;
2041 snprintf(instruction->text, 128,
2042 "0x%8.8" PRIx32
2043 " 0x%4.4x \tBX\tr%i",
2044 address, opcode, Rm);
2047 else
2049 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2050 snprintf(instruction->text, 128,
2051 "0x%8.8" PRIx32
2052 " 0x%4.4x \t"
2053 "UNDEFINED INSTRUCTION",
2054 address, opcode);
2056 return ERROR_OK;
2057 break;
2060 else
2062 switch (op)
2064 case 0x0:
2065 instruction->type = ARM_AND;
2066 mnemonic = "ANDS";
2067 break;
2068 case 0x1:
2069 instruction->type = ARM_EOR;
2070 mnemonic = "EORS";
2071 break;
2072 case 0x2:
2073 instruction->type = ARM_MOV;
2074 mnemonic = "LSLS";
2075 instruction->info.data_proc.variant = 2 /*register shift*/;
2076 instruction->info.data_proc.shifter_operand.register_shift.shift = 0;
2077 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
2078 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
2079 break;
2080 case 0x3:
2081 instruction->type = ARM_MOV;
2082 mnemonic = "LSRS";
2083 instruction->info.data_proc.variant = 2 /*register shift*/;
2084 instruction->info.data_proc.shifter_operand.register_shift.shift = 1;
2085 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
2086 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
2087 break;
2088 case 0x4:
2089 instruction->type = ARM_MOV;
2090 mnemonic = "ASRS";
2091 instruction->info.data_proc.variant = 2 /*register shift*/;
2092 instruction->info.data_proc.shifter_operand.register_shift.shift = 2;
2093 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
2094 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
2095 break;
2096 case 0x5:
2097 instruction->type = ARM_ADC;
2098 mnemonic = "ADCS";
2099 break;
2100 case 0x6:
2101 instruction->type = ARM_SBC;
2102 mnemonic = "SBCS";
2103 break;
2104 case 0x7:
2105 instruction->type = ARM_MOV;
2106 mnemonic = "RORS";
2107 instruction->info.data_proc.variant = 2 /*register shift*/;
2108 instruction->info.data_proc.shifter_operand.register_shift.shift = 3;
2109 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
2110 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
2111 break;
2112 case 0x8:
2113 instruction->type = ARM_TST;
2114 mnemonic = "TST";
2115 break;
2116 case 0x9:
2117 instruction->type = ARM_RSB;
2118 mnemonic = "RSBS";
2119 instruction->info.data_proc.variant = 0 /*immediate*/;
2120 instruction->info.data_proc.shifter_operand.immediate.immediate = 0;
2121 instruction->info.data_proc.Rn = Rm;
2122 break;
2123 case 0xA:
2124 instruction->type = ARM_CMP;
2125 mnemonic = "CMP";
2126 break;
2127 case 0xB:
2128 instruction->type = ARM_CMN;
2129 mnemonic = "CMN";
2130 break;
2131 case 0xC:
2132 instruction->type = ARM_ORR;
2133 mnemonic = "ORRS";
2134 break;
2135 case 0xD:
2136 instruction->type = ARM_MUL;
2137 mnemonic = "MULS";
2138 break;
2139 case 0xE:
2140 instruction->type = ARM_BIC;
2141 mnemonic = "BICS";
2142 break;
2143 case 0xF:
2144 instruction->type = ARM_MVN;
2145 mnemonic = "MVNS";
2146 break;
2150 if (nop)
2151 snprintf(instruction->text, 128,
2152 "0x%8.8" PRIx32 " 0x%4.4x \tNOP\t\t\t"
2153 "; (%s r%i, r%i)",
2154 address, opcode, mnemonic, Rd, Rm);
2155 else
2156 snprintf(instruction->text, 128,
2157 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i",
2158 address, opcode, mnemonic, Rd, Rm);
2160 return ERROR_OK;
2163 /* PC-relative data addressing is word-aligned even with Thumb */
2164 static inline uint32_t thumb_alignpc4(uint32_t addr)
2166 return (addr + 4) & ~3;
2169 static int evaluate_load_literal_thumb(uint16_t opcode,
2170 uint32_t address, struct arm_instruction *instruction)
2172 uint32_t immediate;
2173 uint8_t Rd = (opcode >> 8) & 0x7;
2175 instruction->type = ARM_LDR;
2176 immediate = opcode & 0x000000ff;
2177 immediate *= 4;
2179 instruction->info.load_store.Rd = Rd;
2180 instruction->info.load_store.Rn = 15 /*PC*/;
2181 instruction->info.load_store.index_mode = 0; /*offset*/
2182 instruction->info.load_store.offset_mode = 0; /*immediate*/
2183 instruction->info.load_store.offset.offset = immediate;
2185 snprintf(instruction->text, 128,
2186 "0x%8.8" PRIx32 " 0x%4.4x \t"
2187 "LDR\tr%i, [pc, #%#" PRIx32 "]\t; %#8.8" PRIx32,
2188 address, opcode, Rd, immediate,
2189 thumb_alignpc4(address) + immediate);
2191 return ERROR_OK;
2194 static int evaluate_load_store_reg_thumb(uint16_t opcode,
2195 uint32_t address, struct arm_instruction *instruction)
2197 uint8_t Rd = (opcode >> 0) & 0x7;
2198 uint8_t Rn = (opcode >> 3) & 0x7;
2199 uint8_t Rm = (opcode >> 6) & 0x7;
2200 uint8_t opc = (opcode >> 9) & 0x7;
2201 char *mnemonic = NULL;
2203 switch (opc)
2205 case 0:
2206 instruction->type = ARM_STR;
2207 mnemonic = "STR";
2208 break;
2209 case 1:
2210 instruction->type = ARM_STRH;
2211 mnemonic = "STRH";
2212 break;
2213 case 2:
2214 instruction->type = ARM_STRB;
2215 mnemonic = "STRB";
2216 break;
2217 case 3:
2218 instruction->type = ARM_LDRSB;
2219 mnemonic = "LDRSB";
2220 break;
2221 case 4:
2222 instruction->type = ARM_LDR;
2223 mnemonic = "LDR";
2224 break;
2225 case 5:
2226 instruction->type = ARM_LDRH;
2227 mnemonic = "LDRH";
2228 break;
2229 case 6:
2230 instruction->type = ARM_LDRB;
2231 mnemonic = "LDRB";
2232 break;
2233 case 7:
2234 instruction->type = ARM_LDRSH;
2235 mnemonic = "LDRSH";
2236 break;
2239 snprintf(instruction->text, 128,
2240 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [r%i, r%i]",
2241 address, opcode, mnemonic, Rd, Rn, Rm);
2243 instruction->info.load_store.Rd = Rd;
2244 instruction->info.load_store.Rn = Rn;
2245 instruction->info.load_store.index_mode = 0; /*offset*/
2246 instruction->info.load_store.offset_mode = 1; /*register*/
2247 instruction->info.load_store.offset.reg.Rm = Rm;
2249 return ERROR_OK;
2252 static int evaluate_load_store_imm_thumb(uint16_t opcode,
2253 uint32_t address, struct arm_instruction *instruction)
2255 uint32_t offset = (opcode >> 6) & 0x1f;
2256 uint8_t Rd = (opcode >> 0) & 0x7;
2257 uint8_t Rn = (opcode >> 3) & 0x7;
2258 uint32_t L = opcode & (1 << 11);
2259 uint32_t B = opcode & (1 << 12);
2260 char *mnemonic;
2261 char suffix = ' ';
2262 uint32_t shift = 2;
2264 if (L)
2266 instruction->type = ARM_LDR;
2267 mnemonic = "LDR";
2269 else
2271 instruction->type = ARM_STR;
2272 mnemonic = "STR";
2275 if ((opcode&0xF000) == 0x8000)
2277 suffix = 'H';
2278 shift = 1;
2280 else if (B)
2282 suffix = 'B';
2283 shift = 0;
2286 snprintf(instruction->text, 128,
2287 "0x%8.8" PRIx32 " 0x%4.4x \t%s%c\tr%i, [r%i, #%#" PRIx32 "]",
2288 address, opcode, mnemonic, suffix, Rd, Rn, offset << shift);
2290 instruction->info.load_store.Rd = Rd;
2291 instruction->info.load_store.Rn = Rn;
2292 instruction->info.load_store.index_mode = 0; /*offset*/
2293 instruction->info.load_store.offset_mode = 0; /*immediate*/
2294 instruction->info.load_store.offset.offset = offset << shift;
2296 return ERROR_OK;
2299 static int evaluate_load_store_stack_thumb(uint16_t opcode,
2300 uint32_t address, struct arm_instruction *instruction)
2302 uint32_t offset = opcode & 0xff;
2303 uint8_t Rd = (opcode >> 8) & 0x7;
2304 uint32_t L = opcode & (1 << 11);
2305 char *mnemonic;
2307 if (L)
2309 instruction->type = ARM_LDR;
2310 mnemonic = "LDR";
2312 else
2314 instruction->type = ARM_STR;
2315 mnemonic = "STR";
2318 snprintf(instruction->text, 128,
2319 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [SP, #%#" PRIx32 "]",
2320 address, opcode, mnemonic, Rd, offset*4);
2322 instruction->info.load_store.Rd = Rd;
2323 instruction->info.load_store.Rn = 13 /*SP*/;
2324 instruction->info.load_store.index_mode = 0; /*offset*/
2325 instruction->info.load_store.offset_mode = 0; /*immediate*/
2326 instruction->info.load_store.offset.offset = offset*4;
2328 return ERROR_OK;
2331 static int evaluate_add_sp_pc_thumb(uint16_t opcode,
2332 uint32_t address, struct arm_instruction *instruction)
2334 uint32_t imm = opcode & 0xff;
2335 uint8_t Rd = (opcode >> 8) & 0x7;
2336 uint8_t Rn;
2337 uint32_t SP = opcode & (1 << 11);
2338 char *reg_name;
2340 instruction->type = ARM_ADD;
2342 if (SP)
2344 reg_name = "SP";
2345 Rn = 13;
2347 else
2349 reg_name = "PC";
2350 Rn = 15;
2353 snprintf(instruction->text, 128,
2354 "0x%8.8" PRIx32 " 0x%4.4x \tADD\tr%i, %s, #%#" PRIx32,
2355 address, opcode, Rd, reg_name, imm * 4);
2357 instruction->info.data_proc.variant = 0 /* immediate */;
2358 instruction->info.data_proc.Rd = Rd;
2359 instruction->info.data_proc.Rn = Rn;
2360 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
2362 return ERROR_OK;
2365 static int evaluate_adjust_stack_thumb(uint16_t opcode,
2366 uint32_t address, struct arm_instruction *instruction)
2368 uint32_t imm = opcode & 0x7f;
2369 uint8_t opc = opcode & (1 << 7);
2370 char *mnemonic;
2373 if (opc)
2375 instruction->type = ARM_SUB;
2376 mnemonic = "SUB";
2378 else
2380 instruction->type = ARM_ADD;
2381 mnemonic = "ADD";
2384 snprintf(instruction->text, 128,
2385 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tSP, #%#" PRIx32,
2386 address, opcode, mnemonic, imm*4);
2388 instruction->info.data_proc.variant = 0 /* immediate */;
2389 instruction->info.data_proc.Rd = 13 /*SP*/;
2390 instruction->info.data_proc.Rn = 13 /*SP*/;
2391 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
2393 return ERROR_OK;
2396 static int evaluate_breakpoint_thumb(uint16_t opcode,
2397 uint32_t address, struct arm_instruction *instruction)
2399 uint32_t imm = opcode & 0xff;
2401 instruction->type = ARM_BKPT;
2403 snprintf(instruction->text, 128,
2404 "0x%8.8" PRIx32 " 0x%4.4x \tBKPT\t%#2.2" PRIx32 "",
2405 address, opcode, imm);
2407 return ERROR_OK;
2410 static int evaluate_load_store_multiple_thumb(uint16_t opcode,
2411 uint32_t address, struct arm_instruction *instruction)
2413 uint32_t reg_list = opcode & 0xff;
2414 uint32_t L = opcode & (1 << 11);
2415 uint32_t R = opcode & (1 << 8);
2416 uint8_t Rn = (opcode >> 8) & 7;
2417 uint8_t addr_mode = 0 /* IA */;
2418 char reg_names[40];
2419 char *reg_names_p;
2420 char *mnemonic;
2421 char ptr_name[7] = "";
2422 int i;
2424 /* REVISIT: in ThumbEE mode, there are no LDM or STM instructions.
2425 * The STMIA and LDMIA opcodes are used for other instructions.
2428 if ((opcode & 0xf000) == 0xc000)
2429 { /* generic load/store multiple */
2430 char *wback = "!";
2432 if (L)
2434 instruction->type = ARM_LDM;
2435 mnemonic = "LDM";
2436 if (opcode & (1 << Rn))
2437 wback = "";
2439 else
2441 instruction->type = ARM_STM;
2442 mnemonic = "STM";
2444 snprintf(ptr_name, sizeof ptr_name, "r%i%s, ", Rn, wback);
2446 else
2447 { /* push/pop */
2448 Rn = 13; /* SP */
2449 if (L)
2451 instruction->type = ARM_LDM;
2452 mnemonic = "POP";
2453 if (R)
2454 reg_list |= (1 << 15) /*PC*/;
2456 else
2458 instruction->type = ARM_STM;
2459 mnemonic = "PUSH";
2460 addr_mode = 3; /*DB*/
2461 if (R)
2462 reg_list |= (1 << 14) /*LR*/;
2466 reg_names_p = reg_names;
2467 for (i = 0; i <= 15; i++)
2469 if (reg_list & (1 << i))
2470 reg_names_p += snprintf(reg_names_p, (reg_names + 40 - reg_names_p), "r%i, ", i);
2472 if (reg_names_p > reg_names)
2473 reg_names_p[-2] = '\0';
2474 else /* invalid op : no registers */
2475 reg_names[0] = '\0';
2477 snprintf(instruction->text, 128,
2478 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%s{%s}",
2479 address, opcode, mnemonic, ptr_name, reg_names);
2481 instruction->info.load_store_multiple.register_list = reg_list;
2482 instruction->info.load_store_multiple.Rn = Rn;
2483 instruction->info.load_store_multiple.addressing_mode = addr_mode;
2485 return ERROR_OK;
2488 static int evaluate_cond_branch_thumb(uint16_t opcode,
2489 uint32_t address, struct arm_instruction *instruction)
2491 uint32_t offset = opcode & 0xff;
2492 uint8_t cond = (opcode >> 8) & 0xf;
2493 uint32_t target_address;
2495 if (cond == 0xf)
2497 instruction->type = ARM_SWI;
2498 snprintf(instruction->text, 128,
2499 "0x%8.8" PRIx32 " 0x%4.4x \tSVC\t%#2.2" PRIx32,
2500 address, opcode, offset);
2501 return ERROR_OK;
2503 else if (cond == 0xe)
2505 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2506 snprintf(instruction->text, 128,
2507 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2508 address, opcode);
2509 return ERROR_OK;
2512 /* sign extend 8-bit offset */
2513 if (offset & 0x00000080)
2514 offset = 0xffffff00 | offset;
2516 target_address = address + 4 + (offset << 1);
2518 snprintf(instruction->text, 128,
2519 "0x%8.8" PRIx32 " 0x%4.4x \tB%s\t%#8.8" PRIx32,
2520 address, opcode,
2521 arm_condition_strings[cond], target_address);
2523 instruction->type = ARM_B;
2524 instruction->info.b_bl_bx_blx.reg_operand = -1;
2525 instruction->info.b_bl_bx_blx.target_address = target_address;
2527 return ERROR_OK;
2530 static int evaluate_cb_thumb(uint16_t opcode, uint32_t address,
2531 struct arm_instruction *instruction)
2533 unsigned offset;
2535 /* added in Thumb2 */
2536 offset = (opcode >> 3) & 0x1f;
2537 offset |= (opcode & 0x0200) >> 4;
2539 snprintf(instruction->text, 128,
2540 "0x%8.8" PRIx32 " 0x%4.4x \tCB%sZ\tr%d, %#8.8" PRIx32,
2541 address, opcode,
2542 (opcode & 0x0800) ? "N" : "",
2543 opcode & 0x7, address + 4 + (offset << 1));
2545 return ERROR_OK;
2548 static int evaluate_extend_thumb(uint16_t opcode, uint32_t address,
2549 struct arm_instruction *instruction)
2551 /* added in ARMv6 */
2552 snprintf(instruction->text, 128,
2553 "0x%8.8" PRIx32 " 0x%4.4x \t%cXT%c\tr%d, r%d",
2554 address, opcode,
2555 (opcode & 0x0080) ? 'U' : 'S',
2556 (opcode & 0x0040) ? 'B' : 'H',
2557 opcode & 0x7, (opcode >> 3) & 0x7);
2559 return ERROR_OK;
2562 static int evaluate_cps_thumb(uint16_t opcode, uint32_t address,
2563 struct arm_instruction *instruction)
2565 /* added in ARMv6 */
2566 if ((opcode & 0x0ff0) == 0x0650)
2567 snprintf(instruction->text, 128,
2568 "0x%8.8" PRIx32 " 0x%4.4x \tSETEND %s",
2569 address, opcode,
2570 (opcode & 0x80) ? "BE" : "LE");
2571 else /* ASSUME (opcode & 0x0fe0) == 0x0660 */
2572 snprintf(instruction->text, 128,
2573 "0x%8.8" PRIx32 " 0x%4.4x \tCPSI%c\t%s%s%s",
2574 address, opcode,
2575 (opcode & 0x0010) ? 'D' : 'E',
2576 (opcode & 0x0004) ? "A" : "",
2577 (opcode & 0x0002) ? "I" : "",
2578 (opcode & 0x0001) ? "F" : "");
2580 return ERROR_OK;
2583 static int evaluate_byterev_thumb(uint16_t opcode, uint32_t address,
2584 struct arm_instruction *instruction)
2586 char *suffix;
2588 /* added in ARMv6 */
2589 switch ((opcode >> 6) & 3) {
2590 case 0:
2591 suffix = "";
2592 break;
2593 case 1:
2594 suffix = "16";
2595 break;
2596 default:
2597 suffix = "SH";
2598 break;
2600 snprintf(instruction->text, 128,
2601 "0x%8.8" PRIx32 " 0x%4.4x \tREV%s\tr%d, r%d",
2602 address, opcode, suffix,
2603 opcode & 0x7, (opcode >> 3) & 0x7);
2605 return ERROR_OK;
2608 static int evaluate_hint_thumb(uint16_t opcode, uint32_t address,
2609 struct arm_instruction *instruction)
2611 char *hint;
2613 switch ((opcode >> 4) & 0x0f) {
2614 case 0:
2615 hint = "NOP";
2616 break;
2617 case 1:
2618 hint = "YIELD";
2619 break;
2620 case 2:
2621 hint = "WFE";
2622 break;
2623 case 3:
2624 hint = "WFI";
2625 break;
2626 case 4:
2627 hint = "SEV";
2628 break;
2629 default:
2630 hint = "HINT (UNRECOGNIZED)";
2631 break;
2634 snprintf(instruction->text, 128,
2635 "0x%8.8" PRIx32 " 0x%4.4x \t%s",
2636 address, opcode, hint);
2638 return ERROR_OK;
2641 static int evaluate_ifthen_thumb(uint16_t opcode, uint32_t address,
2642 struct arm_instruction *instruction)
2644 unsigned cond = (opcode >> 4) & 0x0f;
2645 char *x = "", *y = "", *z = "";
2647 if (opcode & 0x01)
2648 z = (opcode & 0x02) ? "T" : "E";
2649 if (opcode & 0x03)
2650 y = (opcode & 0x04) ? "T" : "E";
2651 if (opcode & 0x07)
2652 x = (opcode & 0x08) ? "T" : "E";
2654 snprintf(instruction->text, 128,
2655 "0x%8.8" PRIx32 " 0x%4.4x \tIT%s%s%s\t%s",
2656 address, opcode,
2657 x, y, z, arm_condition_strings[cond]);
2659 /* NOTE: strictly speaking, the next 1-4 instructions should
2660 * now be displayed with the relevant conditional suffix...
2663 return ERROR_OK;
2666 int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
2668 /* clear fields, to avoid confusion */
2669 memset(instruction, 0, sizeof(struct arm_instruction));
2670 instruction->opcode = opcode;
2671 instruction->instruction_size = 2;
2673 if ((opcode & 0xe000) == 0x0000)
2675 /* add/substract register or immediate */
2676 if ((opcode & 0x1800) == 0x1800)
2677 return evaluate_add_sub_thumb(opcode, address, instruction);
2678 /* shift by immediate */
2679 else
2680 return evaluate_shift_imm_thumb(opcode, address, instruction);
2683 /* Add/substract/compare/move immediate */
2684 if ((opcode & 0xe000) == 0x2000)
2686 return evaluate_data_proc_imm_thumb(opcode, address, instruction);
2689 /* Data processing instructions */
2690 if ((opcode & 0xf800) == 0x4000)
2692 return evaluate_data_proc_thumb(opcode, address, instruction);
2695 /* Load from literal pool */
2696 if ((opcode & 0xf800) == 0x4800)
2698 return evaluate_load_literal_thumb(opcode, address, instruction);
2701 /* Load/Store register offset */
2702 if ((opcode & 0xf000) == 0x5000)
2704 return evaluate_load_store_reg_thumb(opcode, address, instruction);
2707 /* Load/Store immediate offset */
2708 if (((opcode & 0xe000) == 0x6000)
2709 ||((opcode & 0xf000) == 0x8000))
2711 return evaluate_load_store_imm_thumb(opcode, address, instruction);
2714 /* Load/Store from/to stack */
2715 if ((opcode & 0xf000) == 0x9000)
2717 return evaluate_load_store_stack_thumb(opcode, address, instruction);
2720 /* Add to SP/PC */
2721 if ((opcode & 0xf000) == 0xa000)
2723 return evaluate_add_sp_pc_thumb(opcode, address, instruction);
2726 /* Misc */
2727 if ((opcode & 0xf000) == 0xb000)
2729 switch ((opcode >> 8) & 0x0f) {
2730 case 0x0:
2731 return evaluate_adjust_stack_thumb(opcode, address, instruction);
2732 case 0x1:
2733 case 0x3:
2734 case 0x9:
2735 case 0xb:
2736 return evaluate_cb_thumb(opcode, address, instruction);
2737 case 0x2:
2738 return evaluate_extend_thumb(opcode, address, instruction);
2739 case 0x4:
2740 case 0x5:
2741 case 0xc:
2742 case 0xd:
2743 return evaluate_load_store_multiple_thumb(opcode, address,
2744 instruction);
2745 case 0x6:
2746 return evaluate_cps_thumb(opcode, address, instruction);
2747 case 0xa:
2748 if ((opcode & 0x00c0) == 0x0080)
2749 break;
2750 return evaluate_byterev_thumb(opcode, address, instruction);
2751 case 0xe:
2752 return evaluate_breakpoint_thumb(opcode, address, instruction);
2753 case 0xf:
2754 if (opcode & 0x000f)
2755 return evaluate_ifthen_thumb(opcode, address,
2756 instruction);
2757 else
2758 return evaluate_hint_thumb(opcode, address,
2759 instruction);
2762 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2763 snprintf(instruction->text, 128,
2764 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2765 address, opcode);
2766 return ERROR_OK;
2769 /* Load/Store multiple */
2770 if ((opcode & 0xf000) == 0xc000)
2772 return evaluate_load_store_multiple_thumb(opcode, address, instruction);
2775 /* Conditional branch + SWI */
2776 if ((opcode & 0xf000) == 0xd000)
2778 return evaluate_cond_branch_thumb(opcode, address, instruction);
2781 if ((opcode & 0xe000) == 0xe000)
2783 /* Undefined instructions */
2784 if ((opcode & 0xf801) == 0xe801)
2786 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2787 snprintf(instruction->text, 128,
2788 "0x%8.8" PRIx32 " 0x%8.8x\t"
2789 "UNDEFINED INSTRUCTION",
2790 address, opcode);
2791 return ERROR_OK;
2793 else
2794 { /* Branch to offset */
2795 return evaluate_b_bl_blx_thumb(opcode, address, instruction);
2799 LOG_ERROR("should never reach this point (opcode=%04x)",opcode);
2800 return -1;
2803 static int t2ev_b_bl(uint32_t opcode, uint32_t address,
2804 struct arm_instruction *instruction, char *cp)
2806 unsigned offset;
2807 unsigned b21 = 1 << 21;
2808 unsigned b22 = 1 << 22;
2810 /* instead of combining two smaller 16-bit branch instructions,
2811 * Thumb2 uses only one larger 32-bit instruction.
2813 offset = opcode & 0x7ff;
2814 offset |= (opcode & 0x03ff0000) >> 5;
2815 if (opcode & (1 << 26)) {
2816 offset |= 0xff << 23;
2817 if ((opcode & (1 << 11)) == 0)
2818 b21 = 0;
2819 if ((opcode & (1 << 13)) == 0)
2820 b22 = 0;
2821 } else {
2822 if (opcode & (1 << 11))
2823 b21 = 0;
2824 if (opcode & (1 << 13))
2825 b22 = 0;
2827 offset |= b21;
2828 offset |= b22;
2831 address += 4;
2832 address += offset << 1;
2834 instruction->type = (opcode & (1 << 14)) ? ARM_BL : ARM_B;
2835 instruction->info.b_bl_bx_blx.reg_operand = -1;
2836 instruction->info.b_bl_bx_blx.target_address = address;
2837 sprintf(cp, "%s\t%#8.8" PRIx32,
2838 (opcode & (1 << 14)) ? "BL" : "B.W",
2839 address);
2841 return ERROR_OK;
2844 static int t2ev_cond_b(uint32_t opcode, uint32_t address,
2845 struct arm_instruction *instruction, char *cp)
2847 unsigned offset;
2848 unsigned b17 = 1 << 17;
2849 unsigned b18 = 1 << 18;
2850 unsigned cond = (opcode >> 22) & 0x0f;
2852 offset = opcode & 0x7ff;
2853 offset |= (opcode & 0x003f0000) >> 5;
2854 if (opcode & (1 << 26)) {
2855 offset |= 0xffff << 19;
2856 if ((opcode & (1 << 11)) == 0)
2857 b17 = 0;
2858 if ((opcode & (1 << 13)) == 0)
2859 b18 = 0;
2860 } else {
2861 if (opcode & (1 << 11))
2862 b17 = 0;
2863 if (opcode & (1 << 13))
2864 b18 = 0;
2866 offset |= b17;
2867 offset |= b18;
2869 address += 4;
2870 address += offset << 1;
2872 instruction->type = ARM_B;
2873 instruction->info.b_bl_bx_blx.reg_operand = -1;
2874 instruction->info.b_bl_bx_blx.target_address = address;
2875 sprintf(cp, "B%s.W\t%#8.8" PRIx32,
2876 arm_condition_strings[cond],
2877 address);
2879 return ERROR_OK;
2882 static const char *special_name(int number)
2884 char *special = "(RESERVED)";
2886 switch (number) {
2887 case 0:
2888 special = "apsr";
2889 break;
2890 case 1:
2891 special = "iapsr";
2892 break;
2893 case 2:
2894 special = "eapsr";
2895 break;
2896 case 3:
2897 special = "xpsr";
2898 break;
2899 case 5:
2900 special = "ipsr";
2901 break;
2902 case 6:
2903 special = "epsr";
2904 break;
2905 case 7:
2906 special = "iepsr";
2907 break;
2908 case 8:
2909 special = "msp";
2910 break;
2911 case 9:
2912 special = "psp";
2913 break;
2914 case 16:
2915 special = "primask";
2916 break;
2917 case 17:
2918 special = "basepri";
2919 break;
2920 case 18:
2921 special = "basepri_max";
2922 break;
2923 case 19:
2924 special = "faultmask";
2925 break;
2926 case 20:
2927 special = "control";
2928 break;
2930 return special;
2933 static int t2ev_hint(uint32_t opcode, uint32_t address,
2934 struct arm_instruction *instruction, char *cp)
2936 const char *mnemonic;
2938 if (opcode & 0x0700) {
2939 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2940 strcpy(cp, "UNDEFINED");
2941 return ERROR_OK;
2944 if (opcode & 0x00f0) {
2945 sprintf(cp, "DBG\t#%d", (int) opcode & 0xf);
2946 return ERROR_OK;
2949 switch (opcode & 0x0f) {
2950 case 0:
2951 mnemonic = "NOP.W";
2952 break;
2953 case 1:
2954 mnemonic = "YIELD.W";
2955 break;
2956 case 2:
2957 mnemonic = "WFE.W";
2958 break;
2959 case 3:
2960 mnemonic = "WFI.W";
2961 break;
2962 case 4:
2963 mnemonic = "SEV.W";
2964 break;
2965 default:
2966 mnemonic = "HINT.W (UNRECOGNIZED)";
2967 break;
2969 strcpy(cp, mnemonic);
2970 return ERROR_OK;
2973 static int t2ev_misc(uint32_t opcode, uint32_t address,
2974 struct arm_instruction *instruction, char *cp)
2976 const char *mnemonic;
2978 switch ((opcode >> 4) & 0x0f) {
2979 case 0:
2980 mnemonic = "LEAVEX";
2981 break;
2982 case 1:
2983 mnemonic = "ENTERX";
2984 break;
2985 case 2:
2986 mnemonic = "CLREX";
2987 break;
2988 case 4:
2989 mnemonic = "DSB";
2990 break;
2991 case 5:
2992 mnemonic = "DMB";
2993 break;
2994 case 6:
2995 mnemonic = "ISB";
2996 break;
2997 default:
2998 return ERROR_INVALID_ARGUMENTS;
3000 strcpy(cp, mnemonic);
3001 return ERROR_OK;
3004 static int t2ev_b_misc(uint32_t opcode, uint32_t address,
3005 struct arm_instruction *instruction, char *cp)
3007 /* permanently undefined */
3008 if ((opcode & 0x07f07000) == 0x07f02000) {
3009 instruction->type = ARM_UNDEFINED_INSTRUCTION;
3010 strcpy(cp, "UNDEFINED");
3011 return ERROR_OK;
3014 switch ((opcode >> 12) & 0x5) {
3015 case 0x1:
3016 case 0x5:
3017 return t2ev_b_bl(opcode, address, instruction, cp);
3018 case 0x4:
3019 goto undef;
3020 case 0:
3021 if (((opcode >> 23) & 0x07) != 0x07)
3022 return t2ev_cond_b(opcode, address, instruction, cp);
3023 if (opcode & (1 << 26))
3024 goto undef;
3025 break;
3028 switch ((opcode >> 20) & 0x7f) {
3029 case 0x38:
3030 case 0x39:
3031 sprintf(cp, "MSR\t%s, r%d", special_name(opcode & 0xff),
3032 (int) (opcode >> 16) & 0x0f);
3033 return ERROR_OK;
3034 case 0x3a:
3035 return t2ev_hint(opcode, address, instruction, cp);
3036 case 0x3b:
3037 return t2ev_misc(opcode, address, instruction, cp);
3038 case 0x3c:
3039 sprintf(cp, "BXJ\tr%d", (int) (opcode >> 16) & 0x0f);
3040 return ERROR_OK;
3041 case 0x3e:
3042 case 0x3f:
3043 sprintf(cp, "MRS\tr%d, %s", (int) (opcode >> 8) & 0x0f,
3044 special_name(opcode & 0xff));
3045 return ERROR_OK;
3048 undef:
3049 return ERROR_INVALID_ARGUMENTS;
3052 static int t2ev_data_mod_immed(uint32_t opcode, uint32_t address,
3053 struct arm_instruction *instruction, char *cp)
3055 char *mnemonic = NULL;
3056 int rn = (opcode >> 16) & 0xf;
3057 int rd = (opcode >> 8) & 0xf;
3058 unsigned immed = opcode & 0xff;
3059 unsigned func;
3060 bool one = false;
3061 char *suffix = "";
3062 char *suffix2 = "";
3064 /* ARMv7-M: A5.3.2 Modified immediate constants */
3065 func = (opcode >> 11) & 0x0e;
3066 if (immed & 0x80)
3067 func |= 1;
3068 if (opcode & (1 << 26))
3069 func |= 0x10;
3071 /* "Modified" immediates */
3072 switch (func >> 1) {
3073 case 0:
3074 break;
3075 case 2:
3076 immed <<= 8;
3077 /* FALLTHROUGH */
3078 case 1:
3079 immed += immed << 16;
3080 break;
3081 case 3:
3082 immed += immed << 8;
3083 immed += immed << 16;
3084 break;
3085 default:
3086 immed |= 0x80;
3087 immed = ror(immed, func);
3090 if (opcode & (1 << 20))
3091 suffix = "S";
3093 switch ((opcode >> 21) & 0xf) {
3094 case 0:
3095 if (rd == 0xf) {
3096 instruction->type = ARM_TST;
3097 mnemonic = "TST";
3098 one = true;
3099 suffix = "";
3100 rd = rn;
3101 } else {
3102 instruction->type = ARM_AND;
3103 mnemonic = "AND";
3105 break;
3106 case 1:
3107 instruction->type = ARM_BIC;
3108 mnemonic = "BIC";
3109 break;
3110 case 2:
3111 if (rn == 0xf) {
3112 instruction->type = ARM_MOV;
3113 mnemonic = "MOV";
3114 one = true;
3115 suffix2 = ".W";
3116 } else {
3117 instruction->type = ARM_ORR;
3118 mnemonic = "ORR";
3120 break;
3121 case 3:
3122 if (rn == 0xf) {
3123 instruction->type = ARM_MVN;
3124 mnemonic = "MVN";
3125 one = true;
3126 } else {
3127 // instruction->type = ARM_ORN;
3128 mnemonic = "ORN";
3130 break;
3131 case 4:
3132 if (rd == 0xf) {
3133 instruction->type = ARM_TEQ;
3134 mnemonic = "TEQ";
3135 one = true;
3136 suffix = "";
3137 rd = rn;
3138 } else {
3139 instruction->type = ARM_EOR;
3140 mnemonic = "EOR";
3142 break;
3143 case 8:
3144 if (rd == 0xf) {
3145 instruction->type = ARM_CMN;
3146 mnemonic = "CMN";
3147 one = true;
3148 suffix = "";
3149 rd = rn;
3150 } else {
3151 instruction->type = ARM_ADD;
3152 mnemonic = "ADD";
3153 suffix2 = ".W";
3155 break;
3156 case 10:
3157 instruction->type = ARM_ADC;
3158 mnemonic = "ADC";
3159 suffix2 = ".W";
3160 break;
3161 case 11:
3162 instruction->type = ARM_SBC;
3163 mnemonic = "SBC";
3164 break;
3165 case 13:
3166 if (rd == 0xf) {
3167 instruction->type = ARM_CMP;
3168 mnemonic = "CMP";
3169 one = true;
3170 suffix = "";
3171 rd = rn;
3172 } else {
3173 instruction->type = ARM_SUB;
3174 mnemonic = "SUB";
3176 suffix2 = ".W";
3177 break;
3178 case 14:
3179 instruction->type = ARM_RSB;
3180 mnemonic = "RSB";
3181 suffix2 = ".W";
3182 break;
3183 default:
3184 return ERROR_INVALID_ARGUMENTS;
3187 if (one)
3188 sprintf(cp, "%s%s\tr%d, #%d\t; %#8.8x",
3189 mnemonic, suffix2 ,rd, immed, immed);
3190 else
3191 sprintf(cp, "%s%s%s\tr%d, r%d, #%d\t; %#8.8x",
3192 mnemonic, suffix, suffix2,
3193 rd, rn, immed, immed);
3195 return ERROR_OK;
3198 static int t2ev_data_immed(uint32_t opcode, uint32_t address,
3199 struct arm_instruction *instruction, char *cp)
3201 char *mnemonic = NULL;
3202 int rn = (opcode >> 16) & 0xf;
3203 int rd = (opcode >> 8) & 0xf;
3204 unsigned immed;
3205 bool add = false;
3206 bool is_signed = false;
3208 immed = (opcode & 0x0ff) | ((opcode & 0x7000) >> 4);
3209 if (opcode & (1 << 26))
3210 immed |= (1 << 11);
3212 switch ((opcode >> 20) & 0x1f) {
3213 case 0:
3214 if (rn == 0xf) {
3215 add = true;
3216 goto do_adr;
3218 mnemonic = "ADDW";
3219 break;
3220 case 4:
3221 immed |= (opcode >> 4) & 0xf000;
3222 sprintf(cp, "MOVW\tr%d, #%d\t; %#3.3x", rd, immed, immed);
3223 return ERROR_OK;
3224 case 0x0a:
3225 if (rn == 0xf)
3226 goto do_adr;
3227 mnemonic = "SUBW";
3228 break;
3229 case 0x0c:
3230 /* move constant to top 16 bits of register */
3231 immed |= (opcode >> 4) & 0xf000;
3232 sprintf(cp, "MOVT\tr%d, #%d\t; %#4.4x", rn, immed, immed);
3233 return ERROR_OK;
3234 case 0x10:
3235 case 0x12:
3236 is_signed = true;
3237 case 0x18:
3238 case 0x1a:
3239 /* signed/unsigned saturated add */
3240 immed = (opcode >> 6) & 0x03;
3241 immed |= (opcode >> 10) & 0x1c;
3242 sprintf(cp, "%sSAT\tr%d, #%d, r%d, %s #%d\t",
3243 is_signed ? "S" : "U",
3244 rd, (int) (opcode & 0x1f) + is_signed, rn,
3245 (opcode & (1 << 21)) ? "ASR" : "LSL",
3246 immed ? immed : 32);
3247 return ERROR_OK;
3248 case 0x14:
3249 is_signed = true;
3250 /* FALLTHROUGH */
3251 case 0x1c:
3252 /* signed/unsigned bitfield extract */
3253 immed = (opcode >> 6) & 0x03;
3254 immed |= (opcode >> 10) & 0x1c;
3255 sprintf(cp, "%sBFX\tr%d, r%d, #%d, #%d\t",
3256 is_signed ? "S" : "U",
3257 rd, rn, immed,
3258 (int) (opcode & 0x1f) + 1);
3259 return ERROR_OK;
3260 case 0x16:
3261 immed = (opcode >> 6) & 0x03;
3262 immed |= (opcode >> 10) & 0x1c;
3263 if (rn == 0xf) /* bitfield clear */
3264 sprintf(cp, "BFC\tr%d, #%d, #%d\t",
3265 rd, immed,
3266 (int) (opcode & 0x1f) + 1 - immed);
3267 else /* bitfield insert */
3268 sprintf(cp, "BFI\tr%d, r%d, #%d, #%d\t",
3269 rd, rn, immed,
3270 (int) (opcode & 0x1f) + 1 - immed);
3271 return ERROR_OK;
3272 default:
3273 return ERROR_INVALID_ARGUMENTS;
3276 sprintf(cp, "%s\tr%d, r%d, #%d\t; %#3.3x", mnemonic,
3277 rd, rn, immed, immed);
3278 return ERROR_OK;
3280 do_adr:
3281 address = thumb_alignpc4(address);
3282 if (add)
3283 address += immed;
3284 else
3285 address -= immed;
3286 /* REVISIT "ADD/SUB Rd, PC, #const ; 0x..." might be better;
3287 * not hiding the pc-relative stuff will sometimes be useful.
3289 sprintf(cp, "ADR.W\tr%d, %#8.8" PRIx32, rd, address);
3290 return ERROR_OK;
3293 static int t2ev_store_single(uint32_t opcode, uint32_t address,
3294 struct arm_instruction *instruction, char *cp)
3296 unsigned op = (opcode >> 20) & 0xf;
3297 char *size = "";
3298 char *suffix = "";
3299 char *p1 = "";
3300 char *p2 = "]";
3301 unsigned immed;
3302 unsigned rn = (opcode >> 16) & 0x0f;
3303 unsigned rt = (opcode >> 12) & 0x0f;
3305 if (rn == 0xf)
3306 return ERROR_INVALID_ARGUMENTS;
3308 if (opcode & 0x0800)
3309 op |= 1;
3310 switch (op) {
3311 /* byte */
3312 case 0x8:
3313 case 0x9:
3314 size = "B";
3315 goto imm12;
3316 case 0x1:
3317 size = "B";
3318 goto imm8;
3319 case 0x0:
3320 size = "B";
3321 break;
3322 /* halfword */
3323 case 0xa:
3324 case 0xb:
3325 size = "H";
3326 goto imm12;
3327 case 0x3:
3328 size = "H";
3329 goto imm8;
3330 case 0x2:
3331 size = "H";
3332 break;
3333 /* word */
3334 case 0xc:
3335 case 0xd:
3336 goto imm12;
3337 case 0x5:
3338 goto imm8;
3339 case 0x4:
3340 break;
3341 /* error */
3342 default:
3343 return ERROR_INVALID_ARGUMENTS;
3346 sprintf(cp, "STR%s.W\tr%d, [r%d, r%d, LSL #%d]",
3347 size, rt, rn, (int) opcode & 0x0f,
3348 (int) (opcode >> 4) & 0x03);
3349 return ERROR_OK;
3351 imm12:
3352 immed = opcode & 0x0fff;
3353 sprintf(cp, "STR%s.W\tr%d, [r%d, #%u]\t; %#3.3x",
3354 size, rt, rn, immed, immed);
3355 return ERROR_OK;
3357 imm8:
3358 immed = opcode & 0x00ff;
3360 switch (opcode & 0x700) {
3361 case 0x600:
3362 suffix = "T";
3363 break;
3364 case 0x000:
3365 case 0x200:
3366 return ERROR_INVALID_ARGUMENTS;
3369 /* two indexed modes will write back rn */
3370 if (opcode & 0x100) {
3371 if (opcode & 0x400) /* pre-indexed */
3372 p2 = "]!";
3373 else { /* post-indexed */
3374 p1 = "]";
3375 p2 = "";
3379 sprintf(cp, "STR%s%s\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
3380 size, suffix, rt, rn, p1,
3381 (opcode & 0x200) ? "" : "-",
3382 immed, p2, immed);
3383 return ERROR_OK;
3386 static int t2ev_mul32(uint32_t opcode, uint32_t address,
3387 struct arm_instruction *instruction, char *cp)
3389 int ra = (opcode >> 12) & 0xf;
3391 switch (opcode & 0x007000f0) {
3392 case 0:
3393 if (ra == 0xf)
3394 sprintf(cp, "MUL\tr%d, r%d, r%d",
3395 (int) (opcode >> 8) & 0xf,
3396 (int) (opcode >> 16) & 0xf,
3397 (int) (opcode >> 0) & 0xf);
3398 else
3399 sprintf(cp, "MLA\tr%d, r%d, r%d, r%d",
3400 (int) (opcode >> 8) & 0xf,
3401 (int) (opcode >> 16) & 0xf,
3402 (int) (opcode >> 0) & 0xf, ra);
3403 break;
3404 case 0x10:
3405 sprintf(cp, "MLS\tr%d, r%d, r%d, r%d",
3406 (int) (opcode >> 8) & 0xf,
3407 (int) (opcode >> 16) & 0xf,
3408 (int) (opcode >> 0) & 0xf, ra);
3409 break;
3410 default:
3411 return ERROR_INVALID_ARGUMENTS;
3413 return ERROR_OK;
3416 static int t2ev_mul64_div(uint32_t opcode, uint32_t address,
3417 struct arm_instruction *instruction, char *cp)
3419 int op = (opcode >> 4) & 0xf;
3420 char *infix = "MUL";
3422 op += (opcode >> 16) & 0x70;
3423 switch (op) {
3424 case 0x40:
3425 case 0x60:
3426 infix = "MLA";
3427 /* FALLTHROUGH */
3428 case 0:
3429 case 0x20:
3430 sprintf(cp, "%c%sL\tr%d, r%d, r%d, r%d",
3431 (op & 0x20) ? 'U' : 'S',
3432 infix,
3433 (int) (opcode >> 12) & 0xf,
3434 (int) (opcode >> 8) & 0xf,
3435 (int) (opcode >> 16) & 0xf,
3436 (int) (opcode >> 0) & 0xf);
3437 break;
3438 case 0x1f:
3439 case 0x3f:
3440 sprintf(cp, "%cDIV\tr%d, r%d, r%d",
3441 (op & 0x20) ? 'U' : 'S',
3442 (int) (opcode >> 8) & 0xf,
3443 (int) (opcode >> 16) & 0xf,
3444 (int) (opcode >> 0) & 0xf);
3445 break;
3446 default:
3447 return ERROR_INVALID_ARGUMENTS;
3450 return ERROR_OK;
3453 static int t2ev_ldm_stm(uint32_t opcode, uint32_t address,
3454 struct arm_instruction *instruction, char *cp)
3456 int rn = (opcode >> 16) & 0xf;
3457 int op = (opcode >> 22) & 0x6;
3458 int t = (opcode >> 21) & 1;
3459 unsigned registers = opcode & 0xffff;
3460 char *mode = "";
3462 if (opcode & (1 << 20))
3463 op |= 1;
3465 switch (op) {
3466 case 0:
3467 mode = "DB";
3468 /* FALL THROUGH */
3469 case 6:
3470 sprintf(cp, "SRS%s\tsp%s, #%d", mode,
3471 t ? "!" : "",
3472 (unsigned) (opcode & 0x1f));
3473 return ERROR_OK;
3474 case 1:
3475 mode = "DB";
3476 /* FALL THROUGH */
3477 case 7:
3478 sprintf(cp, "RFE%s\tr%d%s", mode,
3479 (unsigned) ((opcode >> 16) & 0xf),
3480 t ? "!" : "");
3481 return ERROR_OK;
3482 case 2:
3483 sprintf(cp, "STM.W\tr%d%s, ", rn, t ? "!" : "");
3484 break;
3485 case 3:
3486 if (rn == 13 && t)
3487 sprintf(cp, "POP.W\t");
3488 else
3489 sprintf(cp, "LDM.W\tr%d%s, ", rn, t ? "!" : "");
3490 break;
3491 case 4:
3492 if (rn == 13 && t)
3493 sprintf(cp, "PUSH.W\t");
3494 else
3495 sprintf(cp, "STMDB\tr%d%s, ", rn, t ? "!" : "");
3496 break;
3497 case 5:
3498 sprintf(cp, "LDMDB.W\tr%d%s, ", rn, t ? "!" : "");
3499 break;
3500 default:
3501 return ERROR_INVALID_ARGUMENTS;
3504 cp = strchr(cp, 0);
3505 *cp++ = '{';
3506 for (t = 0; registers; t++, registers >>= 1) {
3507 if ((registers & 1) == 0)
3508 continue;
3509 registers &= ~1;
3510 sprintf(cp, "r%d%s", t, registers ? ", " : "");
3511 cp = strchr(cp, 0);
3513 *cp++ = '}';
3514 *cp++ = 0;
3516 return ERROR_OK;
3519 /* load/store dual or exclusive, table branch */
3520 static int t2ev_ldrex_strex(uint32_t opcode, uint32_t address,
3521 struct arm_instruction *instruction, char *cp)
3523 unsigned op1op2 = (opcode >> 20) & 0x3;
3524 unsigned op3 = (opcode >> 4) & 0xf;
3525 char *mnemonic;
3526 unsigned rn = (opcode >> 16) & 0xf;
3527 unsigned rt = (opcode >> 12) & 0xf;
3528 unsigned rd = (opcode >> 8) & 0xf;
3529 unsigned imm = opcode & 0xff;
3530 char *p1 = "";
3531 char *p2 = "]";
3533 op1op2 |= (opcode >> 21) & 0xc;
3534 switch (op1op2) {
3535 case 0:
3536 mnemonic = "STREX";
3537 goto strex;
3538 case 1:
3539 mnemonic = "LDREX";
3540 goto ldrex;
3541 case 2:
3542 case 6:
3543 case 8:
3544 case 10:
3545 case 12:
3546 case 14:
3547 mnemonic = "STRD";
3548 goto immediate;
3549 case 3:
3550 case 7:
3551 case 9:
3552 case 11:
3553 case 13:
3554 case 15:
3555 mnemonic = "LDRD";
3556 if (rn == 15)
3557 goto literal;
3558 else
3559 goto immediate;
3560 case 4:
3561 switch (op3) {
3562 case 4:
3563 mnemonic = "STREXB";
3564 break;
3565 case 5:
3566 mnemonic = "STREXH";
3567 break;
3568 default:
3569 return ERROR_INVALID_ARGUMENTS;
3571 rd = opcode & 0xf;
3572 imm = 0;
3573 goto strex;
3574 case 5:
3575 switch (op3) {
3576 case 0:
3577 sprintf(cp, "TBB\t[r%u, r%u]", rn, imm & 0xf);
3578 return ERROR_OK;
3579 case 1:
3580 sprintf(cp, "TBH\t[r%u, r%u, LSL #1]", rn, imm & 0xf);
3581 return ERROR_OK;
3582 case 4:
3583 mnemonic = "LDREXB";
3584 break;
3585 case 5:
3586 mnemonic = "LDREXH";
3587 break;
3588 default:
3589 return ERROR_INVALID_ARGUMENTS;
3591 imm = 0;
3592 goto ldrex;
3594 return ERROR_INVALID_ARGUMENTS;
3596 strex:
3597 imm <<= 2;
3598 if (imm)
3599 sprintf(cp, "%s\tr%u, r%u, [r%u, #%u]\t; %#2.2x",
3600 mnemonic, rd, rt, rn, imm, imm);
3601 else
3602 sprintf(cp, "%s\tr%u, r%u, [r%u]",
3603 mnemonic, rd, rt, rn);
3604 return ERROR_OK;
3606 ldrex:
3607 imm <<= 2;
3608 if (imm)
3609 sprintf(cp, "%s\tr%u, [r%u, #%u]\t; %#2.2x",
3610 mnemonic, rt, rn, imm, imm);
3611 else
3612 sprintf(cp, "%s\tr%u, [r%u]",
3613 mnemonic, rt, rn);
3614 return ERROR_OK;
3616 immediate:
3617 /* two indexed modes will write back rn */
3618 if (opcode & (1 << 21)) {
3619 if (opcode & (1 << 24)) /* pre-indexed */
3620 p2 = "]!";
3621 else { /* post-indexed */
3622 p1 = "]";
3623 p2 = "";
3627 imm <<= 2;
3628 sprintf(cp, "%s\tr%u, r%u, [r%u%s, #%s%u%s\t; %#2.2x",
3629 mnemonic, rt, rd, rn, p1,
3630 (opcode & (1 << 23)) ? "" : "-",
3631 imm, p2, imm);
3632 return ERROR_OK;
3634 literal:
3635 address = thumb_alignpc4(address);
3636 imm <<= 2;
3637 if (opcode & (1 << 23))
3638 address += imm;
3639 else
3640 address -= imm;
3641 sprintf(cp, "%s\tr%u, r%u, %#8.8" PRIx32,
3642 mnemonic, rt, rd, address);
3643 return ERROR_OK;
3646 static int t2ev_data_shift(uint32_t opcode, uint32_t address,
3647 struct arm_instruction *instruction, char *cp)
3649 int op = (opcode >> 21) & 0xf;
3650 int rd = (opcode >> 8) & 0xf;
3651 int rn = (opcode >> 16) & 0xf;
3652 int type = (opcode >> 4) & 0x3;
3653 int immed = (opcode >> 6) & 0x3;
3654 char *mnemonic;
3655 char *suffix = "";
3657 immed |= (opcode >> 10) & 0x1c;
3658 if (opcode & (1 << 20))
3659 suffix = "S";
3661 switch (op) {
3662 case 0:
3663 if (rd == 0xf) {
3664 if (!(opcode & (1 << 20)))
3665 return ERROR_INVALID_ARGUMENTS;
3666 instruction->type = ARM_TST;
3667 mnemonic = "TST";
3668 suffix = "";
3669 goto two;
3671 instruction->type = ARM_AND;
3672 mnemonic = "AND";
3673 break;
3674 case 1:
3675 instruction->type = ARM_BIC;
3676 mnemonic = "BIC";
3677 break;
3678 case 2:
3679 if (rn == 0xf) {
3680 instruction->type = ARM_MOV;
3681 switch (type) {
3682 case 0:
3683 if (immed == 0) {
3684 sprintf(cp, "MOV%s.W\tr%d, r%d",
3685 suffix, rd,
3686 (int) (opcode & 0xf));
3687 return ERROR_OK;
3689 mnemonic = "LSL";
3690 break;
3691 case 1:
3692 mnemonic = "LSR";
3693 break;
3694 case 2:
3695 mnemonic = "ASR";
3696 break;
3697 default:
3698 if (immed == 0) {
3699 sprintf(cp, "RRX%s\tr%d, r%d",
3700 suffix, rd,
3701 (int) (opcode & 0xf));
3702 return ERROR_OK;
3704 mnemonic = "ROR";
3705 break;
3707 goto immediate;
3708 } else {
3709 instruction->type = ARM_ORR;
3710 mnemonic = "ORR";
3712 break;
3713 case 3:
3714 if (rn == 0xf) {
3715 instruction->type = ARM_MVN;
3716 mnemonic = "MVN";
3717 rn = rd;
3718 goto two;
3719 } else {
3720 // instruction->type = ARM_ORN;
3721 mnemonic = "ORN";
3723 break;
3724 case 4:
3725 if (rd == 0xf) {
3726 if (!(opcode & (1 << 20)))
3727 return ERROR_INVALID_ARGUMENTS;
3728 instruction->type = ARM_TEQ;
3729 mnemonic = "TEQ";
3730 suffix = "";
3731 goto two;
3733 instruction->type = ARM_EOR;
3734 mnemonic = "EOR";
3735 break;
3736 case 8:
3737 if (rd == 0xf) {
3738 if (!(opcode & (1 << 20)))
3739 return ERROR_INVALID_ARGUMENTS;
3740 instruction->type = ARM_CMN;
3741 mnemonic = "CMN";
3742 suffix = "";
3743 goto two;
3745 instruction->type = ARM_ADD;
3746 mnemonic = "ADD";
3747 break;
3748 case 0xa:
3749 instruction->type = ARM_ADC;
3750 mnemonic = "ADC";
3751 break;
3752 case 0xb:
3753 instruction->type = ARM_SBC;
3754 mnemonic = "SBC";
3755 break;
3756 case 0xd:
3757 if (rd == 0xf) {
3758 if (!(opcode & (1 << 21)))
3759 return ERROR_INVALID_ARGUMENTS;
3760 instruction->type = ARM_CMP;
3761 mnemonic = "CMP";
3762 suffix = "";
3763 goto two;
3765 instruction->type = ARM_SUB;
3766 mnemonic = "SUB";
3767 break;
3768 case 0xe:
3769 instruction->type = ARM_RSB;
3770 mnemonic = "RSB";
3771 break;
3772 default:
3773 return ERROR_INVALID_ARGUMENTS;
3776 sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
3777 mnemonic, suffix, rd, rn, (int) (opcode & 0xf));
3779 shift:
3780 cp = strchr(cp, 0);
3782 switch (type) {
3783 case 0:
3784 if (immed == 0)
3785 return ERROR_OK;
3786 suffix = "LSL";
3787 break;
3788 case 1:
3789 suffix = "LSR";
3790 if (immed == 32)
3791 immed = 0;
3792 break;
3793 case 2:
3794 suffix = "ASR";
3795 if (immed == 32)
3796 immed = 0;
3797 break;
3798 case 3:
3799 if (immed == 0) {
3800 strcpy(cp, ", RRX");
3801 return ERROR_OK;
3803 suffix = "ROR";
3804 break;
3806 sprintf(cp, ", %s #%d", suffix, immed ? immed : 32);
3807 return ERROR_OK;
3809 two:
3810 sprintf(cp, "%s%s.W\tr%d, r%d",
3811 mnemonic, suffix, rn, (int) (opcode & 0xf));
3812 goto shift;
3814 immediate:
3815 sprintf(cp, "%s%s.W\tr%d, r%d, #%d",
3816 mnemonic, suffix, rd,
3817 (int) (opcode & 0xf), immed ? immed : 32);
3818 return ERROR_OK;
3821 static int t2ev_data_reg(uint32_t opcode, uint32_t address,
3822 struct arm_instruction *instruction, char *cp)
3824 char *mnemonic;
3825 char * suffix = "";
3827 if (((opcode >> 4) & 0xf) == 0) {
3828 switch ((opcode >> 21) & 0x7) {
3829 case 0:
3830 mnemonic = "LSL";
3831 break;
3832 case 1:
3833 mnemonic = "LSR";
3834 break;
3835 case 2:
3836 mnemonic = "ASR";
3837 break;
3838 case 3:
3839 mnemonic = "ROR";
3840 break;
3841 default:
3842 return ERROR_INVALID_ARGUMENTS;
3845 instruction->type = ARM_MOV;
3846 if (opcode & (1 << 20))
3847 suffix = "S";
3848 sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
3849 mnemonic, suffix,
3850 (int) (opcode >> 8) & 0xf,
3851 (int) (opcode >> 16) & 0xf,
3852 (int) (opcode >> 0) & 0xf);
3854 } else if (opcode & (1 << 7)) {
3855 switch ((opcode >> 20) & 0xf) {
3856 case 0:
3857 case 1:
3858 case 4:
3859 case 5:
3860 switch ((opcode >> 4) & 0x3) {
3861 case 1:
3862 suffix = ", ROR #8";
3863 break;
3864 case 2:
3865 suffix = ", ROR #16";
3866 break;
3867 case 3:
3868 suffix = ", ROR #24";
3869 break;
3871 sprintf(cp, "%cXT%c.W\tr%d, r%d%s",
3872 (opcode & (1 << 24)) ? 'U' : 'S',
3873 (opcode & (1 << 26)) ? 'B' : 'H',
3874 (int) (opcode >> 8) & 0xf,
3875 (int) (opcode >> 0) & 0xf,
3876 suffix);
3877 break;
3878 case 8:
3879 case 9:
3880 case 0xa:
3881 case 0xb:
3882 if (opcode & (1 << 6))
3883 return ERROR_INVALID_ARGUMENTS;
3884 if (((opcode >> 12) & 0xf) != 0xf)
3885 return ERROR_INVALID_ARGUMENTS;
3886 if (!(opcode & (1 << 20)))
3887 return ERROR_INVALID_ARGUMENTS;
3889 switch (((opcode >> 19) & 0x04)
3890 | ((opcode >> 4) & 0x3)) {
3891 case 0:
3892 mnemonic = "REV.W";
3893 break;
3894 case 1:
3895 mnemonic = "REV16.W";
3896 break;
3897 case 2:
3898 mnemonic = "RBIT";
3899 break;
3900 case 3:
3901 mnemonic = "REVSH.W";
3902 break;
3903 case 4:
3904 mnemonic = "CLZ";
3905 break;
3906 default:
3907 return ERROR_INVALID_ARGUMENTS;
3909 sprintf(cp, "%s\tr%d, r%d",
3910 mnemonic,
3911 (int) (opcode >> 8) & 0xf,
3912 (int) (opcode >> 0) & 0xf);
3913 break;
3914 default:
3915 return ERROR_INVALID_ARGUMENTS;
3919 return ERROR_OK;
3922 static int t2ev_load_word(uint32_t opcode, uint32_t address,
3923 struct arm_instruction *instruction, char *cp)
3925 int rn = (opcode >> 16) & 0xf;
3926 int immed;
3928 instruction->type = ARM_LDR;
3930 if (rn == 0xf) {
3931 immed = opcode & 0x0fff;
3932 if ((opcode & (1 << 23)) == 0)
3933 immed = -immed;
3934 sprintf(cp, "LDR\tr%d, %#8.8" PRIx32,
3935 (int) (opcode >> 12) & 0xf,
3936 thumb_alignpc4(address) + immed);
3937 return ERROR_OK;
3940 if (opcode & (1 << 23)) {
3941 immed = opcode & 0x0fff;
3942 sprintf(cp, "LDR.W\tr%d, [r%d, #%d]\t; %#3.3x",
3943 (int) (opcode >> 12) & 0xf,
3944 rn, immed, immed);
3945 return ERROR_OK;
3948 if (!(opcode & (0x3f << 6))) {
3949 sprintf(cp, "LDR.W\tr%d, [r%d, r%d, LSL #%d]",
3950 (int) (opcode >> 12) & 0xf,
3952 (int) (opcode >> 0) & 0xf,
3953 (int) (opcode >> 4) & 0x3);
3954 return ERROR_OK;
3958 if (((opcode >> 8) & 0xf) == 0xe) {
3959 immed = opcode & 0x00ff;
3961 sprintf(cp, "LDRT\tr%d, [r%d, #%d]\t; %#2.2x",
3962 (int) (opcode >> 12) & 0xf,
3963 rn, immed, immed);
3964 return ERROR_OK;
3967 if (((opcode >> 8) & 0xf) == 0xc || (opcode & 0x0900) == 0x0900) {
3968 char *p1 = "]", *p2 = "";
3970 if (!(opcode & 0x0500))
3971 return ERROR_INVALID_ARGUMENTS;
3973 immed = opcode & 0x00ff;
3975 /* two indexed modes will write back rn */
3976 if (opcode & 0x100) {
3977 if (opcode & 0x400) /* pre-indexed */
3978 p2 = "]!";
3979 else { /* post-indexed */
3980 p1 = "]";
3981 p2 = "";
3985 sprintf(cp, "LDR\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
3986 (int) (opcode >> 12) & 0xf,
3987 rn, p1,
3988 (opcode & 0x200) ? "" : "-",
3989 immed, p2, immed);
3990 return ERROR_OK;
3993 return ERROR_INVALID_ARGUMENTS;
3996 static int t2ev_load_byte_hints(uint32_t opcode, uint32_t address,
3997 struct arm_instruction *instruction, char *cp)
3999 int rn = (opcode >> 16) & 0xf;
4000 int rt = (opcode >> 12) & 0xf;
4001 int op2 = (opcode >> 6) & 0x3f;
4002 unsigned immed;
4003 char *p1 = "", *p2 = "]";
4004 char *mnemonic;
4006 switch ((opcode >> 23) & 0x3) {
4007 case 0:
4008 if ((rn & rt) == 0xf) {
4009 pld_literal:
4010 immed = opcode & 0xfff;
4011 address = thumb_alignpc4(address);
4012 if (opcode & (1 << 23))
4013 address += immed;
4014 else
4015 address -= immed;
4016 sprintf(cp, "PLD\tr%d, %#8.8" PRIx32,
4017 rt, address);
4018 return ERROR_OK;
4020 if (rn == 0x0f && rt != 0x0f) {
4021 ldrb_literal:
4022 immed = opcode & 0xfff;
4023 address = thumb_alignpc4(address);
4024 if (opcode & (1 << 23))
4025 address += immed;
4026 else
4027 address -= immed;
4028 sprintf(cp, "LDRB\tr%d, %#8.8" PRIx32,
4029 rt, address);
4030 return ERROR_OK;
4032 if (rn == 0x0f)
4033 break;
4034 if ((op2 & 0x3c) == 0x38) {
4035 immed = opcode & 0xff;
4036 sprintf(cp, "LDRBT\tr%d, [r%d, #%d]\t; %#2.2x",
4037 rt, rn, immed, immed);
4038 return ERROR_OK;
4040 if ((op2 & 0x3c) == 0x30) {
4041 if (rt == 0x0f) {
4042 immed = opcode & 0xff;
4043 immed = -immed;
4044 preload_immediate:
4045 p1 = (opcode & (1 << 21)) ? "W" : "";
4046 sprintf(cp, "PLD%s\t[r%d, #%d]\t; %#6.6x",
4047 p1, rn, immed, immed);
4048 return ERROR_OK;
4050 mnemonic = "LDRB";
4051 ldrxb_immediate_t3:
4052 immed = opcode & 0xff;
4053 if (!(opcode & 0x200))
4054 immed = -immed;
4056 /* two indexed modes will write back rn */
4057 if (opcode & 0x100) {
4058 if (opcode & 0x400) /* pre-indexed */
4059 p2 = "]!";
4060 else { /* post-indexed */
4061 p1 = "]";
4062 p2 = "";
4065 ldrxb_immediate_t2:
4066 sprintf(cp, "%s\tr%d, [r%d%s, #%d%s\t; %#8.8x",
4067 mnemonic, rt, rn, p1,
4068 immed, p2, immed);
4069 return ERROR_OK;
4071 if ((op2 & 0x24) == 0x24) {
4072 mnemonic = "LDRB";
4073 goto ldrxb_immediate_t3;
4075 if (op2 == 0) {
4076 int rm = opcode & 0xf;
4078 if (rt == 0x0f)
4079 sprintf(cp, "PLD\t");
4080 else
4081 sprintf(cp, "LDRB.W\tr%d, ", rt);
4082 immed = (opcode >> 4) & 0x3;
4083 cp = strchr(cp, 0);
4084 sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed);
4085 return ERROR_OK;
4087 break;
4088 case 1:
4089 if ((rn & rt) == 0xf)
4090 goto pld_literal;
4091 if (rt == 0xf) {
4092 immed = opcode & 0xfff;
4093 goto preload_immediate;
4095 if (rn == 0x0f)
4096 goto ldrb_literal;
4097 mnemonic = "LDRB.W";
4098 immed = opcode & 0xfff;
4099 goto ldrxb_immediate_t2;
4100 case 2:
4101 if ((rn & rt) == 0xf) {
4102 immed = opcode & 0xfff;
4103 address = thumb_alignpc4(address);
4104 if (opcode & (1 << 23))
4105 address += immed;
4106 else
4107 address -= immed;
4108 sprintf(cp, "PLI\t%#8.8" PRIx32, address);
4109 return ERROR_OK;
4111 if (rn == 0xf && rt != 0xf) {
4112 ldrsb_literal:
4113 immed = opcode & 0xfff;
4114 address = thumb_alignpc4(address);
4115 if (opcode & (1 << 23))
4116 address += immed;
4117 else
4118 address -= immed;
4119 sprintf(cp, "LDRSB\t%#8.8" PRIx32, address);
4120 return ERROR_OK;
4122 if (rn == 0xf)
4123 break;
4124 if ((op2 & 0x3c) == 0x38) {
4125 immed = opcode & 0xff;
4126 sprintf(cp, "LDRSBT\tr%d, [r%d, #%d]\t; %#2.2x",
4127 rt, rn, immed, immed);
4128 return ERROR_OK;
4130 if ((op2 & 0x3c) == 0x30) {
4131 if (rt == 0xf) {
4132 immed = opcode & 0xff;
4133 immed = -immed; // pli
4134 sprintf(cp, "PLI\t[r%d, #%d]\t; -%#2.2x",
4135 rn, immed, -immed);
4136 return ERROR_OK;
4138 mnemonic = "LDRSB";
4139 goto ldrxb_immediate_t3;
4141 if ((op2 & 0x24) == 0x24) {
4142 mnemonic = "LDRSB";
4143 goto ldrxb_immediate_t3;
4145 if (op2 == 0) {
4146 int rm = opcode & 0xf;
4148 if (rt == 0x0f)
4149 sprintf(cp, "PLI\t");
4150 else
4151 sprintf(cp, "LDRSB.W\tr%d, ", rt);
4152 immed = (opcode >> 4) & 0x3;
4153 cp = strchr(cp, 0);
4154 sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed);
4155 return ERROR_OK;
4157 break;
4158 case 3:
4159 if (rt == 0xf) {
4160 immed = opcode & 0xfff;
4161 sprintf(cp, "PLI\t[r%d, #%d]\t; %#3.3x",
4162 rn, immed, immed);
4163 return ERROR_OK;
4165 if (rn == 0xf)
4166 goto ldrsb_literal;
4167 immed = opcode & 0xfff;
4168 mnemonic = "LDRSB";
4169 goto ldrxb_immediate_t2;
4172 return ERROR_INVALID_ARGUMENTS;
4175 static int t2ev_load_halfword(uint32_t opcode, uint32_t address,
4176 struct arm_instruction *instruction, char *cp)
4178 int rn = (opcode >> 16) & 0xf;
4179 int rt = (opcode >> 12) & 0xf;
4180 int op2 = (opcode >> 6) & 0x3f;
4181 char *sign = "";
4182 unsigned immed;
4184 if (rt == 0xf) {
4185 sprintf(cp, "HINT (UNALLOCATED)");
4186 return ERROR_OK;
4189 if (opcode & (1 << 24))
4190 sign = "S";
4192 if ((opcode & (1 << 23)) == 0) {
4193 if (rn == 0xf) {
4194 ldrh_literal:
4195 immed = opcode & 0xfff;
4196 address = thumb_alignpc4(address);
4197 if (opcode & (1 << 23))
4198 address += immed;
4199 else
4200 address -= immed;
4201 sprintf(cp, "LDR%sH\tr%d, %#8.8" PRIx32,
4202 sign, rt, address);
4203 return ERROR_OK;
4205 if (op2 == 0) {
4206 int rm = opcode & 0xf;
4208 immed = (opcode >> 4) & 0x3;
4209 sprintf(cp, "LDR%sH.W\tr%d, [r%d, r%d, LSL #%d]",
4210 sign, rt, rn, rm, immed);
4211 return ERROR_OK;
4213 if ((op2 & 0x3c) == 0x38) {
4214 immed = opcode & 0xff;
4215 sprintf(cp, "LDR%sHT\tr%d, [r%d, #%d]\t; %#2.2x",
4216 sign, rt, rn, immed, immed);
4217 return ERROR_OK;
4219 if ((op2 & 0x3c) == 0x30 || (op2 & 0x24) == 0x24) {
4220 char *p1 = "", *p2 = "]";
4222 immed = opcode & 0xff;
4223 if (!(opcode & 0x200))
4224 immed = -immed;
4226 /* two indexed modes will write back rn */
4227 if (opcode & 0x100) {
4228 if (opcode & 0x400) /* pre-indexed */
4229 p2 = "]!";
4230 else { /* post-indexed */
4231 p1 = "]";
4232 p2 = "";
4235 sprintf(cp, "LDR%sH\tr%d, [r%d%s, #%d%s\t; %#8.8x",
4236 sign, rt, rn, p1, immed, p2, immed);
4237 return ERROR_OK;
4239 } else {
4240 if (rn == 0xf)
4241 goto ldrh_literal;
4243 immed = opcode & 0xfff;
4244 sprintf(cp, "LDR%sH%s\tr%d, [r%d, #%d]\t; %#6.6x",
4245 sign, *sign ? "" : ".W",
4246 rt, rn, immed, immed);
4247 return ERROR_OK;
4250 return ERROR_INVALID_ARGUMENTS;
4254 * REVISIT for Thumb2 instructions, instruction->type and friends aren't
4255 * always set. That means eventual arm_simulate_step() support for Thumb2
4256 * will need work in this area.
4258 int thumb2_opcode(struct target *target, uint32_t address, struct arm_instruction *instruction)
4260 int retval;
4261 uint16_t op;
4262 uint32_t opcode;
4263 char *cp;
4265 /* clear low bit ... it's set on function pointers */
4266 address &= ~1;
4268 /* clear fields, to avoid confusion */
4269 memset(instruction, 0, sizeof(struct arm_instruction));
4271 /* read first halfword, see if this is the only one */
4272 retval = target_read_u16(target, address, &op);
4273 if (retval != ERROR_OK)
4274 return retval;
4276 switch (op & 0xf800) {
4277 case 0xf800:
4278 case 0xf000:
4279 case 0xe800:
4280 /* 32-bit instructions */
4281 instruction->instruction_size = 4;
4282 opcode = op << 16;
4283 retval = target_read_u16(target, address + 2, &op);
4284 if (retval != ERROR_OK)
4285 return retval;
4286 opcode |= op;
4287 instruction->opcode = opcode;
4288 break;
4289 default:
4290 /* 16-bit: Thumb1 + IT + CBZ/CBNZ + ... */
4291 return thumb_evaluate_opcode(op, address, instruction);
4294 snprintf(instruction->text, 128,
4295 "0x%8.8" PRIx32 " 0x%8.8" PRIx32 "\t",
4296 address, opcode);
4297 cp = strchr(instruction->text, 0);
4298 retval = ERROR_FAIL;
4300 /* ARMv7-M: A5.3.1 Data processing (modified immediate) */
4301 if ((opcode & 0x1a008000) == 0x10000000)
4302 retval = t2ev_data_mod_immed(opcode, address, instruction, cp);
4304 /* ARMv7-M: A5.3.3 Data processing (plain binary immediate) */
4305 else if ((opcode & 0x1a008000) == 0x12000000)
4306 retval = t2ev_data_immed(opcode, address, instruction, cp);
4308 /* ARMv7-M: A5.3.4 Branches and miscellaneous control */
4309 else if ((opcode & 0x18008000) == 0x10008000)
4310 retval = t2ev_b_misc(opcode, address, instruction, cp);
4312 /* ARMv7-M: A5.3.5 Load/store multiple */
4313 else if ((opcode & 0x1e400000) == 0x08000000)
4314 retval = t2ev_ldm_stm(opcode, address, instruction, cp);
4316 /* ARMv7-M: A5.3.6 Load/store dual or exclusive, table branch */
4317 else if ((opcode & 0x1e400000) == 0x08400000)
4318 retval = t2ev_ldrex_strex(opcode, address, instruction, cp);
4320 /* ARMv7-M: A5.3.7 Load word */
4321 else if ((opcode & 0x1f700000) == 0x18500000)
4322 retval = t2ev_load_word(opcode, address, instruction, cp);
4324 /* ARMv7-M: A5.3.8 Load halfword, unallocated memory hints */
4325 else if ((opcode & 0x1e700000) == 0x18300000)
4326 retval = t2ev_load_halfword(opcode, address, instruction, cp);
4328 /* ARMv7-M: A5.3.9 Load byte, memory hints */
4329 else if ((opcode & 0x1e700000) == 0x18100000)
4330 retval = t2ev_load_byte_hints(opcode, address, instruction, cp);
4332 /* ARMv7-M: A5.3.10 Store single data item */
4333 else if ((opcode & 0x1f100000) == 0x18000000)
4334 retval = t2ev_store_single(opcode, address, instruction, cp);
4336 /* ARMv7-M: A5.3.11 Data processing (shifted register) */
4337 else if ((opcode & 0x1e000000) == 0x0a000000)
4338 retval = t2ev_data_shift(opcode, address, instruction, cp);
4340 /* ARMv7-M: A5.3.12 Data processing (register)
4341 * and A5.3.13 Miscellaneous operations
4343 else if ((opcode & 0x1f000000) == 0x1a000000)
4344 retval = t2ev_data_reg(opcode, address, instruction, cp);
4346 /* ARMv7-M: A5.3.14 Multiply, and multiply accumulate */
4347 else if ((opcode & 0x1f800000) == 0x1b000000)
4348 retval = t2ev_mul32(opcode, address, instruction, cp);
4350 /* ARMv7-M: A5.3.15 Long multiply, long multiply accumulate, divide */
4351 else if ((opcode & 0x1f800000) == 0x1b800000)
4352 retval = t2ev_mul64_div(opcode, address, instruction, cp);
4354 if (retval == ERROR_OK)
4355 return retval;
4358 * Thumb2 also supports coprocessor, ThumbEE, and DSP/Media (SIMD)
4359 * instructions; not yet handled here.
4362 if (retval == ERROR_INVALID_ARGUMENTS) {
4363 instruction->type = ARM_UNDEFINED_INSTRUCTION;
4364 strcpy(cp, "UNDEFINED OPCODE");
4365 return ERROR_OK;
4368 LOG_DEBUG("Can't decode 32-bit Thumb2 yet (opcode=%08" PRIx32 ")",
4369 opcode);
4371 strcpy(cp, "(32-bit Thumb2 ...)");
4372 return ERROR_OK;
4375 int arm_access_size(struct arm_instruction *instruction)
4377 if ((instruction->type == ARM_LDRB)
4378 || (instruction->type == ARM_LDRBT)
4379 || (instruction->type == ARM_LDRSB)
4380 || (instruction->type == ARM_STRB)
4381 || (instruction->type == ARM_STRBT))
4383 return 1;
4385 else if ((instruction->type == ARM_LDRH)
4386 || (instruction->type == ARM_LDRSH)
4387 || (instruction->type == ARM_STRH))
4389 return 2;
4391 else if ((instruction->type == ARM_LDR)
4392 || (instruction->type == ARM_LDRT)
4393 || (instruction->type == ARM_STR)
4394 || (instruction->type == ARM_STRT))
4396 return 4;
4398 else if ((instruction->type == ARM_LDRD)
4399 || (instruction->type == ARM_STRD))
4401 return 8;
4403 else
4405 LOG_ERROR("BUG: instruction type %i isn't a load/store instruction", instruction->type);
4406 return 0;