ARM: disassemble two more v6+ instructions
[openocd.git] / src / target / arm_disassembler.c
blobe76e3859018e12a9d64a1680e40d2d5fac9c3ef5
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 mode = "";
147 break;
148 case 2:
149 mode = "DB";
150 break;
151 case 3:
152 mode = "IB";
153 break;
156 switch (opcode & 0x0e500000) {
157 case 0x08400000:
158 snprintf(instruction->text, 128, "0x%8.8" PRIx32
159 "\t0x%8.8" PRIx32
160 "\tSRS%s\tSP%s, #%d",
161 address, opcode,
162 mode, wback, 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, (opcode >> 16) & 0xf, wback);
170 break;
171 default:
172 return evaluate_unknown(opcode, address, instruction);
174 return ERROR_OK;
177 static int evaluate_swi(uint32_t opcode,
178 uint32_t address, struct arm_instruction *instruction)
180 instruction->type = ARM_SWI;
182 snprintf(instruction->text, 128,
183 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSVC %#6.6" PRIx32,
184 address, opcode, (opcode & 0xffffff));
186 return ERROR_OK;
189 static int evaluate_blx_imm(uint32_t opcode,
190 uint32_t address, struct arm_instruction *instruction)
192 int offset;
193 uint32_t immediate;
194 uint32_t target_address;
196 instruction->type = ARM_BLX;
197 immediate = opcode & 0x00ffffff;
199 /* sign extend 24-bit immediate */
200 if (immediate & 0x00800000)
201 offset = 0xff000000 | immediate;
202 else
203 offset = immediate;
205 /* shift two bits left */
206 offset <<= 2;
208 /* odd/event halfword */
209 if (opcode & 0x01000000)
210 offset |= 0x2;
212 target_address = address + 8 + offset;
214 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX 0x%8.8" PRIx32 "", address, opcode, target_address);
216 instruction->info.b_bl_bx_blx.reg_operand = -1;
217 instruction->info.b_bl_bx_blx.target_address = target_address;
219 return ERROR_OK;
222 static int evaluate_b_bl(uint32_t opcode,
223 uint32_t address, struct arm_instruction *instruction)
225 uint8_t L;
226 uint32_t immediate;
227 int offset;
228 uint32_t target_address;
230 immediate = opcode & 0x00ffffff;
231 L = (opcode & 0x01000000) >> 24;
233 /* sign extend 24-bit immediate */
234 if (immediate & 0x00800000)
235 offset = 0xff000000 | immediate;
236 else
237 offset = immediate;
239 /* shift two bits left */
240 offset <<= 2;
242 target_address = address + 8 + offset;
244 if (L)
245 instruction->type = ARM_BL;
246 else
247 instruction->type = ARM_B;
249 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tB%s%s 0x%8.8" PRIx32 , address, opcode,
250 (L) ? "L" : "", COND(opcode), target_address);
252 instruction->info.b_bl_bx_blx.reg_operand = -1;
253 instruction->info.b_bl_bx_blx.target_address = target_address;
255 return ERROR_OK;
258 /* Coprocessor load/store and double register transfers */
259 /* both normal and extended instruction space (condition field b1111) */
260 static int evaluate_ldc_stc_mcrr_mrrc(uint32_t opcode,
261 uint32_t address, struct arm_instruction *instruction)
263 uint8_t cp_num = (opcode & 0xf00) >> 8;
265 /* MCRR or MRRC */
266 if (((opcode & 0x0ff00000) == 0x0c400000) || ((opcode & 0x0ff00000) == 0x0c400000))
268 uint8_t cp_opcode, Rd, Rn, CRm;
269 char *mnemonic;
271 cp_opcode = (opcode & 0xf0) >> 4;
272 Rd = (opcode & 0xf000) >> 12;
273 Rn = (opcode & 0xf0000) >> 16;
274 CRm = (opcode & 0xf);
276 /* MCRR */
277 if ((opcode & 0x0ff00000) == 0x0c400000)
279 instruction->type = ARM_MCRR;
280 mnemonic = "MCRR";
283 /* MRRC */
284 if ((opcode & 0x0ff00000) == 0x0c500000)
286 instruction->type = ARM_MRRC;
287 mnemonic = "MRRC";
290 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, %x, r%i, r%i, c%i",
291 address, opcode, mnemonic, COND(opcode), cp_num, cp_opcode, Rd, Rn, CRm);
293 else /* LDC or STC */
295 uint8_t CRd, Rn, offset;
296 uint8_t U, N;
297 char *mnemonic;
298 char addressing_mode[32];
300 CRd = (opcode & 0xf000) >> 12;
301 Rn = (opcode & 0xf0000) >> 16;
302 offset = (opcode & 0xff);
304 /* load/store */
305 if (opcode & 0x00100000)
307 instruction->type = ARM_LDC;
308 mnemonic = "LDC";
310 else
312 instruction->type = ARM_STC;
313 mnemonic = "STC";
316 U = (opcode & 0x00800000) >> 23;
317 N = (opcode & 0x00400000) >> 22;
319 /* addressing modes */
320 if ((opcode & 0x01200000) == 0x01000000) /* immediate offset */
321 snprintf(addressing_mode, 32, "[r%i, #%s0x%2.2x*4]", Rn, (U) ? "" : "-", offset);
322 else if ((opcode & 0x01200000) == 0x01200000) /* immediate pre-indexed */
323 snprintf(addressing_mode, 32, "[r%i, #%s0x%2.2x*4]!", Rn, (U) ? "" : "-", offset);
324 else if ((opcode & 0x01200000) == 0x00200000) /* immediate post-indexed */
325 snprintf(addressing_mode, 32, "[r%i], #%s0x%2.2x*4", Rn, (U) ? "" : "-", offset);
326 else if ((opcode & 0x01200000) == 0x00000000) /* unindexed */
327 snprintf(addressing_mode, 32, "[r%i], #0x%2.2x", Rn, offset);
329 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s p%i, c%i, %s",
330 address, opcode, mnemonic, ((opcode & 0xf0000000) == 0xf0000000) ? COND(opcode) : "2",
331 (N) ? "L" : "",
332 cp_num, CRd, addressing_mode);
335 return ERROR_OK;
338 /* Coprocessor data processing instructions */
339 /* Coprocessor register transfer instructions */
340 /* both normal and extended instruction space (condition field b1111) */
341 static int evaluate_cdp_mcr_mrc(uint32_t opcode,
342 uint32_t address, struct arm_instruction *instruction)
344 const char *cond;
345 char* mnemonic;
346 uint8_t cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2;
348 cond = ((opcode & 0xf0000000) == 0xf0000000) ? "2" : COND(opcode);
349 cp_num = (opcode & 0xf00) >> 8;
350 CRd_Rd = (opcode & 0xf000) >> 12;
351 CRn = (opcode & 0xf0000) >> 16;
352 CRm = (opcode & 0xf);
353 opcode_2 = (opcode & 0xe0) >> 5;
355 /* CDP or MRC/MCR */
356 if (opcode & 0x00000010) /* bit 4 set -> MRC/MCR */
358 if (opcode & 0x00100000) /* bit 20 set -> MRC */
360 instruction->type = ARM_MRC;
361 mnemonic = "MRC";
363 else /* bit 20 not set -> MCR */
365 instruction->type = ARM_MCR;
366 mnemonic = "MCR";
369 opcode_1 = (opcode & 0x00e00000) >> 21;
371 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",
372 address, opcode, mnemonic, cond,
373 cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2);
375 else /* bit 4 not set -> CDP */
377 instruction->type = ARM_CDP;
378 mnemonic = "CDP";
380 opcode_1 = (opcode & 0x00f00000) >> 20;
382 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",
383 address, opcode, mnemonic, cond,
384 cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2);
387 return ERROR_OK;
390 /* Load/store instructions */
391 static int evaluate_load_store(uint32_t opcode,
392 uint32_t address, struct arm_instruction *instruction)
394 uint8_t I, P, U, B, W, L;
395 uint8_t Rn, Rd;
396 char *operation; /* "LDR" or "STR" */
397 char *suffix; /* "", "B", "T", "BT" */
398 char offset[32];
400 /* examine flags */
401 I = (opcode & 0x02000000) >> 25;
402 P = (opcode & 0x01000000) >> 24;
403 U = (opcode & 0x00800000) >> 23;
404 B = (opcode & 0x00400000) >> 22;
405 W = (opcode & 0x00200000) >> 21;
406 L = (opcode & 0x00100000) >> 20;
408 /* target register */
409 Rd = (opcode & 0xf000) >> 12;
411 /* base register */
412 Rn = (opcode & 0xf0000) >> 16;
414 instruction->info.load_store.Rd = Rd;
415 instruction->info.load_store.Rn = Rn;
416 instruction->info.load_store.U = U;
418 /* determine operation */
419 if (L)
420 operation = "LDR";
421 else
422 operation = "STR";
424 /* determine instruction type and suffix */
425 if (B)
427 if ((P == 0) && (W == 1))
429 if (L)
430 instruction->type = ARM_LDRBT;
431 else
432 instruction->type = ARM_STRBT;
433 suffix = "BT";
435 else
437 if (L)
438 instruction->type = ARM_LDRB;
439 else
440 instruction->type = ARM_STRB;
441 suffix = "B";
444 else
446 if ((P == 0) && (W == 1))
448 if (L)
449 instruction->type = ARM_LDRT;
450 else
451 instruction->type = ARM_STRT;
452 suffix = "T";
454 else
456 if (L)
457 instruction->type = ARM_LDR;
458 else
459 instruction->type = ARM_STR;
460 suffix = "";
464 if (!I) /* #+-<offset_12> */
466 uint32_t offset_12 = (opcode & 0xfff);
467 if (offset_12)
468 snprintf(offset, 32, ", #%s0x%" PRIx32 "", (U) ? "" : "-", offset_12);
469 else
470 snprintf(offset, 32, "%s", "");
472 instruction->info.load_store.offset_mode = 0;
473 instruction->info.load_store.offset.offset = offset_12;
475 else /* either +-<Rm> or +-<Rm>, <shift>, #<shift_imm> */
477 uint8_t shift_imm, shift;
478 uint8_t Rm;
480 shift_imm = (opcode & 0xf80) >> 7;
481 shift = (opcode & 0x60) >> 5;
482 Rm = (opcode & 0xf);
484 /* LSR encodes a shift by 32 bit as 0x0 */
485 if ((shift == 0x1) && (shift_imm == 0x0))
486 shift_imm = 0x20;
488 /* ASR encodes a shift by 32 bit as 0x0 */
489 if ((shift == 0x2) && (shift_imm == 0x0))
490 shift_imm = 0x20;
492 /* ROR by 32 bit is actually a RRX */
493 if ((shift == 0x3) && (shift_imm == 0x0))
494 shift = 0x4;
496 instruction->info.load_store.offset_mode = 1;
497 instruction->info.load_store.offset.reg.Rm = Rm;
498 instruction->info.load_store.offset.reg.shift = shift;
499 instruction->info.load_store.offset.reg.shift_imm = shift_imm;
501 if ((shift_imm == 0x0) && (shift == 0x0)) /* +-<Rm> */
503 snprintf(offset, 32, ", %sr%i", (U) ? "" : "-", Rm);
505 else /* +-<Rm>, <Shift>, #<shift_imm> */
507 switch (shift)
509 case 0x0: /* LSL */
510 snprintf(offset, 32, ", %sr%i, LSL #0x%x", (U) ? "" : "-", Rm, shift_imm);
511 break;
512 case 0x1: /* LSR */
513 snprintf(offset, 32, ", %sr%i, LSR #0x%x", (U) ? "" : "-", Rm, shift_imm);
514 break;
515 case 0x2: /* ASR */
516 snprintf(offset, 32, ", %sr%i, ASR #0x%x", (U) ? "" : "-", Rm, shift_imm);
517 break;
518 case 0x3: /* ROR */
519 snprintf(offset, 32, ", %sr%i, ROR #0x%x", (U) ? "" : "-", Rm, shift_imm);
520 break;
521 case 0x4: /* RRX */
522 snprintf(offset, 32, ", %sr%i, RRX", (U) ? "" : "-", Rm);
523 break;
528 if (P == 1)
530 if (W == 0) /* offset */
532 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]",
533 address, opcode, operation, COND(opcode), suffix,
534 Rd, Rn, offset);
536 instruction->info.load_store.index_mode = 0;
538 else /* pre-indexed */
540 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]!",
541 address, opcode, operation, COND(opcode), suffix,
542 Rd, Rn, offset);
544 instruction->info.load_store.index_mode = 1;
547 else /* post-indexed */
549 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i]%s",
550 address, opcode, operation, COND(opcode), suffix,
551 Rd, Rn, offset);
553 instruction->info.load_store.index_mode = 2;
556 return ERROR_OK;
559 static int evaluate_extend(uint32_t opcode, uint32_t address, char *cp)
561 unsigned rm = (opcode >> 0) & 0xf;
562 unsigned rd = (opcode >> 12) & 0xf;
563 unsigned rn = (opcode >> 16) & 0xf;
564 char *type, *rot;
566 switch ((opcode >> 24) & 0x3) {
567 case 0:
568 type = "B16";
569 break;
570 case 1:
571 sprintf(cp, "UNDEFINED");
572 return ARM_UNDEFINED_INSTRUCTION;
573 case 2:
574 type = "B";
575 break;
576 default:
577 type = "H";
578 break;
581 switch ((opcode >> 10) & 0x3) {
582 case 0:
583 rot = "";
584 break;
585 case 1:
586 rot = ", ROR #8";
587 break;
588 case 2:
589 rot = ", ROR #16";
590 break;
591 default:
592 rot = ", ROR #24";
593 break;
596 if (rn == 0xf) {
597 sprintf(cp, "%cXT%s%s\tr%d, r%d%s",
598 (opcode & (1 << 22)) ? 'U' : 'S',
599 type, COND(opcode),
600 rd, rm, rot);
601 return ARM_MOV;
602 } else {
603 sprintf(cp, "%cXTA%s%s\tr%d, r%d, r%d%s",
604 (opcode & (1 << 22)) ? 'U' : 'S',
605 type, COND(opcode),
606 rd, rn, rm, rot);
607 return ARM_ADD;
611 static int evaluate_p_add_sub(uint32_t opcode, uint32_t address, char *cp)
613 char *prefix;
614 char *op;
615 int type;
617 switch ((opcode >> 20) & 0x7) {
618 case 1:
619 prefix = "S";
620 break;
621 case 2:
622 prefix = "Q";
623 break;
624 case 3:
625 prefix = "SH";
626 break;
627 case 5:
628 prefix = "U";
629 break;
630 case 6:
631 prefix = "UQ";
632 break;
633 case 7:
634 prefix = "UH";
635 break;
636 default:
637 goto undef;
640 switch ((opcode >> 5) & 0x7) {
641 case 0:
642 op = "ADD16";
643 type = ARM_ADD;
644 break;
645 case 1:
646 op = "ADDSUBX";
647 type = ARM_ADD;
648 break;
649 case 2:
650 op = "SUBADDX";
651 type = ARM_SUB;
652 break;
653 case 3:
654 op = "SUB16";
655 type = ARM_SUB;
656 break;
657 case 4:
658 op = "ADD8";
659 type = ARM_ADD;
660 break;
661 case 7:
662 op = "SUB8";
663 type = ARM_SUB;
664 break;
665 default:
666 goto undef;
669 sprintf(cp, "%s%s%s\tr%d, r%d, r%d", prefix, op, COND(opcode),
670 (int) (opcode >> 12) & 0xf,
671 (int) (opcode >> 16) & 0xf,
672 (int) (opcode >> 0) & 0xf);
673 return type;
675 undef:
676 /* these opcodes might be used someday */
677 sprintf(cp, "UNDEFINED");
678 return ARM_UNDEFINED_INSTRUCTION;
681 /* ARMv6 and later support "media" instructions (includes SIMD) */
682 static int evaluate_media(uint32_t opcode, uint32_t address,
683 struct arm_instruction *instruction)
685 char *cp = instruction->text;
686 char *mnemonic = NULL;
688 sprintf(cp,
689 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t",
690 address, opcode);
691 cp = strchr(cp, 0);
693 /* parallel add/subtract */
694 if ((opcode & 0x01800000) == 0x00000000) {
695 instruction->type = evaluate_p_add_sub(opcode, address, cp);
696 return ERROR_OK;
699 /* halfword pack */
700 if ((opcode & 0x01f00020) == 0x00800000) {
701 char *type, *shift;
702 unsigned imm = (unsigned) (opcode >> 7) & 0x1f;
704 if (opcode & (1 << 6)) {
705 type = "TB";
706 shift = "ASR";
707 if (imm == 0)
708 imm = 32;
709 } else {
710 type = "BT";
711 shift = "LSL";
713 sprintf(cp, "PKH%s%s\tr%d, r%d, r%d, %s #%d",
714 type, COND(opcode),
715 (int) (opcode >> 12) & 0xf,
716 (int) (opcode >> 16) & 0xf,
717 (int) (opcode >> 0) & 0xf,
718 shift, imm);
719 return ERROR_OK;
722 /* word saturate */
723 if ((opcode & 0x01a00020) == 0x00a00000) {
724 char *shift;
725 unsigned imm = (unsigned) (opcode >> 7) & 0x1f;
727 if (opcode & (1 << 6)) {
728 shift = "ASR";
729 if (imm == 0)
730 imm = 32;
731 } else {
732 shift = "LSL";
735 sprintf(cp, "%cSAT%s\tr%d, #%d, r%d, %s #%d",
736 (opcode & (1 << 22)) ? 'U' : 'S',
737 COND(opcode),
738 (int) (opcode >> 12) & 0xf,
739 (int) (opcode >> 16) & 0x1f,
740 (int) (opcode >> 0) & 0xf,
741 shift, imm);
742 return ERROR_OK;
745 /* sign extension */
746 if ((opcode & 0x018000f0) == 0x00800070) {
747 instruction->type = evaluate_extend(opcode, address, cp);
748 return ERROR_OK;
751 /* multiplies */
752 if ((opcode & 0x01f00080) == 0x01000000) {
753 unsigned rn = (opcode >> 12) & 0xf;
755 if (rn != 0xf)
756 sprintf(cp, "SML%cD%s%s\tr%d, r%d, r%d, r%d",
757 (opcode & (1 << 6)) ? 'S' : 'A',
758 (opcode & (1 << 5)) ? "X" : "",
759 COND(opcode),
760 (int) (opcode >> 16) & 0xf,
761 (int) (opcode >> 0) & 0xf,
762 (int) (opcode >> 8) & 0xf,
763 rn);
764 else
765 sprintf(cp, "SMU%cD%s%s\tr%d, r%d, r%d",
766 (opcode & (1 << 6)) ? 'S' : 'A',
767 (opcode & (1 << 5)) ? "X" : "",
768 COND(opcode),
769 (int) (opcode >> 16) & 0xf,
770 (int) (opcode >> 0) & 0xf,
771 (int) (opcode >> 8) & 0xf);
772 return ERROR_OK;
774 if ((opcode & 0x01f00000) == 0x01400000) {
775 sprintf(cp, "SML%cLD%s%s\tr%d, r%d, r%d, r%d",
776 (opcode & (1 << 6)) ? 'S' : 'A',
777 (opcode & (1 << 5)) ? "X" : "",
778 COND(opcode),
779 (int) (opcode >> 12) & 0xf,
780 (int) (opcode >> 16) & 0xf,
781 (int) (opcode >> 0) & 0xf,
782 (int) (opcode >> 8) & 0xf);
783 return ERROR_OK;
785 if ((opcode & 0x01f00000) == 0x01500000) {
786 unsigned rn = (opcode >> 12) & 0xf;
788 switch (opcode & 0xc0) {
789 case 3:
790 if (rn == 0xf)
791 goto undef;
792 /* FALL THROUGH */
793 case 0:
794 break;
795 default:
796 goto undef;
799 if (rn != 0xf)
800 sprintf(cp, "SMML%c%s%s\tr%d, r%d, r%d, r%d",
801 (opcode & (1 << 6)) ? 'S' : 'A',
802 (opcode & (1 << 5)) ? "R" : "",
803 COND(opcode),
804 (int) (opcode >> 16) & 0xf,
805 (int) (opcode >> 0) & 0xf,
806 (int) (opcode >> 8) & 0xf,
807 rn);
808 else
809 sprintf(cp, "SMMUL%s%s\tr%d, r%d, r%d",
810 (opcode & (1 << 5)) ? "R" : "",
811 COND(opcode),
812 (int) (opcode >> 16) & 0xf,
813 (int) (opcode >> 0) & 0xf,
814 (int) (opcode >> 8) & 0xf);
815 return ERROR_OK;
819 /* simple matches against the remaining decode bits */
820 switch (opcode & 0x01f000f0) {
821 case 0x00a00030:
822 case 0x00e00030:
823 /* parallel halfword saturate */
824 sprintf(cp, "%cSAT16%s\tr%d, #%d, r%d",
825 (opcode & (1 << 22)) ? 'U' : 'S',
826 COND(opcode),
827 (int) (opcode >> 12) & 0xf,
828 (int) (opcode >> 16) & 0xf,
829 (int) (opcode >> 0) & 0xf);
830 return ERROR_OK;
831 case 0x00b00030:
832 mnemonic = "REV";
833 break;
834 case 0x00b000b0:
835 mnemonic = "REV16";
836 break;
837 case 0x00f000b0:
838 mnemonic = "REVSH";
839 break;
840 case 0x008000b0:
841 /* select bytes */
842 sprintf(cp, "SEL%s\tr%d, r%d, r%d", COND(opcode),
843 (int) (opcode >> 12) & 0xf,
844 (int) (opcode >> 16) & 0xf,
845 (int) (opcode >> 0) & 0xf);
846 return ERROR_OK;
847 case 0x01800010:
848 /* unsigned sum of absolute differences */
849 if (((opcode >> 12) & 0xf) == 0xf)
850 sprintf(cp, "USAD8%s\tr%d, r%d, r%d", COND(opcode),
851 (int) (opcode >> 16) & 0xf,
852 (int) (opcode >> 0) & 0xf,
853 (int) (opcode >> 8) & 0xf);
854 else
855 sprintf(cp, "USADA8%s\tr%d, r%d, r%d, r%d", COND(opcode),
856 (int) (opcode >> 16) & 0xf,
857 (int) (opcode >> 0) & 0xf,
858 (int) (opcode >> 8) & 0xf,
859 (int) (opcode >> 12) & 0xf);
860 return ERROR_OK;
862 if (mnemonic) {
863 unsigned rm = (opcode >> 0) & 0xf;
864 unsigned rd = (opcode >> 12) & 0xf;
866 sprintf(cp, "%s%s\tr%d, r%d", mnemonic, COND(opcode), rm, rd);
867 return ERROR_OK;
870 undef:
871 /* these opcodes might be used someday */
872 sprintf(cp, "UNDEFINED");
873 return ERROR_OK;
876 /* Miscellaneous load/store instructions */
877 static int evaluate_misc_load_store(uint32_t opcode,
878 uint32_t address, struct arm_instruction *instruction)
880 uint8_t P, U, I, W, L, S, H;
881 uint8_t Rn, Rd;
882 char *operation; /* "LDR" or "STR" */
883 char *suffix; /* "H", "SB", "SH", "D" */
884 char offset[32];
886 /* examine flags */
887 P = (opcode & 0x01000000) >> 24;
888 U = (opcode & 0x00800000) >> 23;
889 I = (opcode & 0x00400000) >> 22;
890 W = (opcode & 0x00200000) >> 21;
891 L = (opcode & 0x00100000) >> 20;
892 S = (opcode & 0x00000040) >> 6;
893 H = (opcode & 0x00000020) >> 5;
895 /* target register */
896 Rd = (opcode & 0xf000) >> 12;
898 /* base register */
899 Rn = (opcode & 0xf0000) >> 16;
901 instruction->info.load_store.Rd = Rd;
902 instruction->info.load_store.Rn = Rn;
903 instruction->info.load_store.U = U;
905 /* determine instruction type and suffix */
906 if (S) /* signed */
908 if (L) /* load */
910 if (H)
912 operation = "LDR";
913 instruction->type = ARM_LDRSH;
914 suffix = "SH";
916 else
918 operation = "LDR";
919 instruction->type = ARM_LDRSB;
920 suffix = "SB";
923 else /* there are no signed stores, so this is used to encode double-register load/stores */
925 suffix = "D";
926 if (H)
928 operation = "STR";
929 instruction->type = ARM_STRD;
931 else
933 operation = "LDR";
934 instruction->type = ARM_LDRD;
938 else /* unsigned */
940 suffix = "H";
941 if (L) /* load */
943 operation = "LDR";
944 instruction->type = ARM_LDRH;
946 else /* store */
948 operation = "STR";
949 instruction->type = ARM_STRH;
953 if (I) /* Immediate offset/index (#+-<offset_8>)*/
955 uint32_t offset_8 = ((opcode & 0xf00) >> 4) | (opcode & 0xf);
956 snprintf(offset, 32, "#%s0x%" PRIx32 "", (U) ? "" : "-", offset_8);
958 instruction->info.load_store.offset_mode = 0;
959 instruction->info.load_store.offset.offset = offset_8;
961 else /* Register offset/index (+-<Rm>) */
963 uint8_t Rm;
964 Rm = (opcode & 0xf);
965 snprintf(offset, 32, "%sr%i", (U) ? "" : "-", Rm);
967 instruction->info.load_store.offset_mode = 1;
968 instruction->info.load_store.offset.reg.Rm = Rm;
969 instruction->info.load_store.offset.reg.shift = 0x0;
970 instruction->info.load_store.offset.reg.shift_imm = 0x0;
973 if (P == 1)
975 if (W == 0) /* offset */
977 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]",
978 address, opcode, operation, COND(opcode), suffix,
979 Rd, Rn, offset);
981 instruction->info.load_store.index_mode = 0;
983 else /* pre-indexed */
985 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]!",
986 address, opcode, operation, COND(opcode), suffix,
987 Rd, Rn, offset);
989 instruction->info.load_store.index_mode = 1;
992 else /* post-indexed */
994 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i], %s",
995 address, opcode, operation, COND(opcode), suffix,
996 Rd, Rn, offset);
998 instruction->info.load_store.index_mode = 2;
1001 return ERROR_OK;
1004 /* Load/store multiples instructions */
1005 static int evaluate_ldm_stm(uint32_t opcode,
1006 uint32_t address, struct arm_instruction *instruction)
1008 uint8_t P, U, S, W, L, Rn;
1009 uint32_t register_list;
1010 char *addressing_mode;
1011 char *mnemonic;
1012 char reg_list[69];
1013 char *reg_list_p;
1014 int i;
1015 int first_reg = 1;
1017 P = (opcode & 0x01000000) >> 24;
1018 U = (opcode & 0x00800000) >> 23;
1019 S = (opcode & 0x00400000) >> 22;
1020 W = (opcode & 0x00200000) >> 21;
1021 L = (opcode & 0x00100000) >> 20;
1022 register_list = (opcode & 0xffff);
1023 Rn = (opcode & 0xf0000) >> 16;
1025 instruction->info.load_store_multiple.Rn = Rn;
1026 instruction->info.load_store_multiple.register_list = register_list;
1027 instruction->info.load_store_multiple.S = S;
1028 instruction->info.load_store_multiple.W = W;
1030 if (L)
1032 instruction->type = ARM_LDM;
1033 mnemonic = "LDM";
1035 else
1037 instruction->type = ARM_STM;
1038 mnemonic = "STM";
1041 if (P)
1043 if (U)
1045 instruction->info.load_store_multiple.addressing_mode = 1;
1046 addressing_mode = "IB";
1048 else
1050 instruction->info.load_store_multiple.addressing_mode = 3;
1051 addressing_mode = "DB";
1054 else
1056 if (U)
1058 instruction->info.load_store_multiple.addressing_mode = 0;
1059 /* "IA" is the default in UAL syntax */
1060 addressing_mode = "";
1062 else
1064 instruction->info.load_store_multiple.addressing_mode = 2;
1065 addressing_mode = "DA";
1069 reg_list_p = reg_list;
1070 for (i = 0; i <= 15; i++)
1072 if ((register_list >> i) & 1)
1074 if (first_reg)
1076 first_reg = 0;
1077 reg_list_p += snprintf(reg_list_p, (reg_list + 69 - reg_list_p), "r%i", i);
1079 else
1081 reg_list_p += snprintf(reg_list_p, (reg_list + 69 - reg_list_p), ", r%i", i);
1086 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i%s, {%s}%s",
1087 address, opcode, mnemonic, COND(opcode), addressing_mode,
1088 Rn, (W) ? "!" : "", reg_list, (S) ? "^" : "");
1090 return ERROR_OK;
1093 /* Multiplies, extra load/stores */
1094 static int evaluate_mul_and_extra_ld_st(uint32_t opcode,
1095 uint32_t address, struct arm_instruction *instruction)
1097 /* Multiply (accumulate) (long) and Swap/swap byte */
1098 if ((opcode & 0x000000f0) == 0x00000090)
1100 /* Multiply (accumulate) */
1101 if ((opcode & 0x0f800000) == 0x00000000)
1103 uint8_t Rm, Rs, Rn, Rd, S;
1104 Rm = opcode & 0xf;
1105 Rs = (opcode & 0xf00) >> 8;
1106 Rn = (opcode & 0xf000) >> 12;
1107 Rd = (opcode & 0xf0000) >> 16;
1108 S = (opcode & 0x00100000) >> 20;
1110 /* examine A bit (accumulate) */
1111 if (opcode & 0x00200000)
1113 instruction->type = ARM_MLA;
1114 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMLA%s%s r%i, r%i, r%i, r%i",
1115 address, opcode, COND(opcode), (S) ? "S" : "", Rd, Rm, Rs, Rn);
1117 else
1119 instruction->type = ARM_MUL;
1120 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMUL%s%s r%i, r%i, r%i",
1121 address, opcode, COND(opcode), (S) ? "S" : "", Rd, Rm, Rs);
1124 return ERROR_OK;
1127 /* Multiply (accumulate) long */
1128 if ((opcode & 0x0f800000) == 0x00800000)
1130 char* mnemonic = NULL;
1131 uint8_t Rm, Rs, RdHi, RdLow, S;
1132 Rm = opcode & 0xf;
1133 Rs = (opcode & 0xf00) >> 8;
1134 RdHi = (opcode & 0xf000) >> 12;
1135 RdLow = (opcode & 0xf0000) >> 16;
1136 S = (opcode & 0x00100000) >> 20;
1138 switch ((opcode & 0x00600000) >> 21)
1140 case 0x0:
1141 instruction->type = ARM_UMULL;
1142 mnemonic = "UMULL";
1143 break;
1144 case 0x1:
1145 instruction->type = ARM_UMLAL;
1146 mnemonic = "UMLAL";
1147 break;
1148 case 0x2:
1149 instruction->type = ARM_SMULL;
1150 mnemonic = "SMULL";
1151 break;
1152 case 0x3:
1153 instruction->type = ARM_SMLAL;
1154 mnemonic = "SMLAL";
1155 break;
1158 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, r%i, r%i",
1159 address, opcode, mnemonic, COND(opcode), (S) ? "S" : "",
1160 RdLow, RdHi, Rm, Rs);
1162 return ERROR_OK;
1165 /* Swap/swap byte */
1166 if ((opcode & 0x0f800000) == 0x01000000)
1168 uint8_t Rm, Rd, Rn;
1169 Rm = opcode & 0xf;
1170 Rd = (opcode & 0xf000) >> 12;
1171 Rn = (opcode & 0xf0000) >> 16;
1173 /* examine B flag */
1174 instruction->type = (opcode & 0x00400000) ? ARM_SWPB : ARM_SWP;
1176 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, [r%i]",
1177 address, opcode, (opcode & 0x00400000) ? "SWPB" : "SWP", COND(opcode), Rd, Rm, Rn);
1178 return ERROR_OK;
1183 return evaluate_misc_load_store(opcode, address, instruction);
1186 static int evaluate_mrs_msr(uint32_t opcode,
1187 uint32_t address, struct arm_instruction *instruction)
1189 int R = (opcode & 0x00400000) >> 22;
1190 char *PSR = (R) ? "SPSR" : "CPSR";
1192 /* Move register to status register (MSR) */
1193 if (opcode & 0x00200000)
1195 instruction->type = ARM_MSR;
1197 /* immediate variant */
1198 if (opcode & 0x02000000)
1200 uint8_t immediate = (opcode & 0xff);
1201 uint8_t rotate = (opcode & 0xf00);
1203 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, 0x%8.8" PRIx32 ,
1204 address, opcode, COND(opcode), PSR,
1205 (opcode & 0x10000) ? "c" : "",
1206 (opcode & 0x20000) ? "x" : "",
1207 (opcode & 0x40000) ? "s" : "",
1208 (opcode & 0x80000) ? "f" : "",
1209 ror(immediate, (rotate * 2))
1212 else /* register variant */
1214 uint8_t Rm = opcode & 0xf;
1215 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, r%i",
1216 address, opcode, COND(opcode), PSR,
1217 (opcode & 0x10000) ? "c" : "",
1218 (opcode & 0x20000) ? "x" : "",
1219 (opcode & 0x40000) ? "s" : "",
1220 (opcode & 0x80000) ? "f" : "",
1226 else /* Move status register to register (MRS) */
1228 uint8_t Rd;
1230 instruction->type = ARM_MRS;
1231 Rd = (opcode & 0x0000f000) >> 12;
1233 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMRS%s r%i, %s",
1234 address, opcode, COND(opcode), Rd, PSR);
1237 return ERROR_OK;
1240 /* Miscellaneous instructions */
1241 static int evaluate_misc_instr(uint32_t opcode,
1242 uint32_t address, struct arm_instruction *instruction)
1244 /* MRS/MSR */
1245 if ((opcode & 0x000000f0) == 0x00000000)
1247 evaluate_mrs_msr(opcode, address, instruction);
1250 /* BX */
1251 if ((opcode & 0x006000f0) == 0x00200010)
1253 uint8_t Rm;
1254 instruction->type = ARM_BX;
1255 Rm = opcode & 0xf;
1257 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBX%s r%i",
1258 address, opcode, COND(opcode), Rm);
1260 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1261 instruction->info.b_bl_bx_blx.target_address = -1;
1264 /* BXJ - "Jazelle" support (ARMv5-J) */
1265 if ((opcode & 0x006000f0) == 0x00200020)
1267 uint8_t Rm;
1268 instruction->type = ARM_BX;
1269 Rm = opcode & 0xf;
1271 snprintf(instruction->text, 128,
1272 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBXJ%s r%i",
1273 address, opcode, COND(opcode), Rm);
1275 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1276 instruction->info.b_bl_bx_blx.target_address = -1;
1279 /* CLZ */
1280 if ((opcode & 0x006000f0) == 0x00600010)
1282 uint8_t Rm, Rd;
1283 instruction->type = ARM_CLZ;
1284 Rm = opcode & 0xf;
1285 Rd = (opcode & 0xf000) >> 12;
1287 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCLZ%s r%i, r%i",
1288 address, opcode, COND(opcode), Rd, Rm);
1291 /* BLX(2) */
1292 if ((opcode & 0x006000f0) == 0x00200030)
1294 uint8_t Rm;
1295 instruction->type = ARM_BLX;
1296 Rm = opcode & 0xf;
1298 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX%s r%i",
1299 address, opcode, COND(opcode), Rm);
1301 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1302 instruction->info.b_bl_bx_blx.target_address = -1;
1305 /* Enhanced DSP add/subtracts */
1306 if ((opcode & 0x0000000f0) == 0x00000050)
1308 uint8_t Rm, Rd, Rn;
1309 char *mnemonic = NULL;
1310 Rm = opcode & 0xf;
1311 Rd = (opcode & 0xf000) >> 12;
1312 Rn = (opcode & 0xf0000) >> 16;
1314 switch ((opcode & 0x00600000) >> 21)
1316 case 0x0:
1317 instruction->type = ARM_QADD;
1318 mnemonic = "QADD";
1319 break;
1320 case 0x1:
1321 instruction->type = ARM_QSUB;
1322 mnemonic = "QSUB";
1323 break;
1324 case 0x2:
1325 instruction->type = ARM_QDADD;
1326 mnemonic = "QDADD";
1327 break;
1328 case 0x3:
1329 instruction->type = ARM_QDSUB;
1330 mnemonic = "QDSUB";
1331 break;
1334 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, r%i",
1335 address, opcode, mnemonic, COND(opcode), Rd, Rm, Rn);
1338 /* Software breakpoints */
1339 if ((opcode & 0x0000000f0) == 0x00000070)
1341 uint32_t immediate;
1342 instruction->type = ARM_BKPT;
1343 immediate = ((opcode & 0x000fff00) >> 4) | (opcode & 0xf);
1345 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBKPT 0x%4.4" PRIx32 "",
1346 address, opcode, immediate);
1349 /* Enhanced DSP multiplies */
1350 if ((opcode & 0x000000090) == 0x00000080)
1352 int x = (opcode & 0x20) >> 5;
1353 int y = (opcode & 0x40) >> 6;
1355 /* SMLA < x><y> */
1356 if ((opcode & 0x00600000) == 0x00000000)
1358 uint8_t Rd, Rm, Rs, Rn;
1359 instruction->type = ARM_SMLAxy;
1360 Rd = (opcode & 0xf0000) >> 16;
1361 Rm = (opcode & 0xf);
1362 Rs = (opcode & 0xf00) >> 8;
1363 Rn = (opcode & 0xf000) >> 12;
1365 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
1366 address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
1367 Rd, Rm, Rs, Rn);
1370 /* SMLAL < x><y> */
1371 if ((opcode & 0x00600000) == 0x00400000)
1373 uint8_t RdLow, RdHi, Rm, Rs;
1374 instruction->type = ARM_SMLAxy;
1375 RdHi = (opcode & 0xf0000) >> 16;
1376 RdLow = (opcode & 0xf000) >> 12;
1377 Rm = (opcode & 0xf);
1378 Rs = (opcode & 0xf00) >> 8;
1380 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
1381 address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
1382 RdLow, RdHi, Rm, Rs);
1385 /* SMLAW < y> */
1386 if (((opcode & 0x00600000) == 0x00100000) && (x == 0))
1388 uint8_t Rd, Rm, Rs, Rn;
1389 instruction->type = ARM_SMLAWy;
1390 Rd = (opcode & 0xf0000) >> 16;
1391 Rm = (opcode & 0xf);
1392 Rs = (opcode & 0xf00) >> 8;
1393 Rn = (opcode & 0xf000) >> 12;
1395 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLAW%s%s r%i, r%i, r%i, r%i",
1396 address, opcode, (y) ? "T" : "B", COND(opcode),
1397 Rd, Rm, Rs, Rn);
1400 /* SMUL < x><y> */
1401 if ((opcode & 0x00600000) == 0x00300000)
1403 uint8_t Rd, Rm, Rs;
1404 instruction->type = ARM_SMULxy;
1405 Rd = (opcode & 0xf0000) >> 16;
1406 Rm = (opcode & 0xf);
1407 Rs = (opcode & 0xf00) >> 8;
1409 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s%s r%i, r%i, r%i",
1410 address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
1411 Rd, Rm, Rs);
1414 /* SMULW < y> */
1415 if (((opcode & 0x00600000) == 0x00100000) && (x == 1))
1417 uint8_t Rd, Rm, Rs;
1418 instruction->type = ARM_SMULWy;
1419 Rd = (opcode & 0xf0000) >> 16;
1420 Rm = (opcode & 0xf);
1421 Rs = (opcode & 0xf00) >> 8;
1423 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s r%i, r%i, r%i",
1424 address, opcode, (y) ? "T" : "B", COND(opcode),
1425 Rd, Rm, Rs);
1429 return ERROR_OK;
1432 static int evaluate_data_proc(uint32_t opcode,
1433 uint32_t address, struct arm_instruction *instruction)
1435 uint8_t I, op, S, Rn, Rd;
1436 char *mnemonic = NULL;
1437 char shifter_operand[32];
1439 I = (opcode & 0x02000000) >> 25;
1440 op = (opcode & 0x01e00000) >> 21;
1441 S = (opcode & 0x00100000) >> 20;
1443 Rd = (opcode & 0xf000) >> 12;
1444 Rn = (opcode & 0xf0000) >> 16;
1446 instruction->info.data_proc.Rd = Rd;
1447 instruction->info.data_proc.Rn = Rn;
1448 instruction->info.data_proc.S = S;
1450 switch (op)
1452 case 0x0:
1453 instruction->type = ARM_AND;
1454 mnemonic = "AND";
1455 break;
1456 case 0x1:
1457 instruction->type = ARM_EOR;
1458 mnemonic = "EOR";
1459 break;
1460 case 0x2:
1461 instruction->type = ARM_SUB;
1462 mnemonic = "SUB";
1463 break;
1464 case 0x3:
1465 instruction->type = ARM_RSB;
1466 mnemonic = "RSB";
1467 break;
1468 case 0x4:
1469 instruction->type = ARM_ADD;
1470 mnemonic = "ADD";
1471 break;
1472 case 0x5:
1473 instruction->type = ARM_ADC;
1474 mnemonic = "ADC";
1475 break;
1476 case 0x6:
1477 instruction->type = ARM_SBC;
1478 mnemonic = "SBC";
1479 break;
1480 case 0x7:
1481 instruction->type = ARM_RSC;
1482 mnemonic = "RSC";
1483 break;
1484 case 0x8:
1485 instruction->type = ARM_TST;
1486 mnemonic = "TST";
1487 break;
1488 case 0x9:
1489 instruction->type = ARM_TEQ;
1490 mnemonic = "TEQ";
1491 break;
1492 case 0xa:
1493 instruction->type = ARM_CMP;
1494 mnemonic = "CMP";
1495 break;
1496 case 0xb:
1497 instruction->type = ARM_CMN;
1498 mnemonic = "CMN";
1499 break;
1500 case 0xc:
1501 instruction->type = ARM_ORR;
1502 mnemonic = "ORR";
1503 break;
1504 case 0xd:
1505 instruction->type = ARM_MOV;
1506 mnemonic = "MOV";
1507 break;
1508 case 0xe:
1509 instruction->type = ARM_BIC;
1510 mnemonic = "BIC";
1511 break;
1512 case 0xf:
1513 instruction->type = ARM_MVN;
1514 mnemonic = "MVN";
1515 break;
1518 if (I) /* immediate shifter operand (#<immediate>)*/
1520 uint8_t immed_8 = opcode & 0xff;
1521 uint8_t rotate_imm = (opcode & 0xf00) >> 8;
1522 uint32_t immediate;
1524 immediate = ror(immed_8, rotate_imm * 2);
1526 snprintf(shifter_operand, 32, "#0x%" PRIx32 "", immediate);
1528 instruction->info.data_proc.variant = 0;
1529 instruction->info.data_proc.shifter_operand.immediate.immediate = immediate;
1531 else /* register-based shifter operand */
1533 uint8_t shift, Rm;
1534 shift = (opcode & 0x60) >> 5;
1535 Rm = (opcode & 0xf);
1537 if ((opcode & 0x10) != 0x10) /* Immediate shifts ("<Rm>" or "<Rm>, <shift> #<shift_immediate>") */
1539 uint8_t shift_imm;
1540 shift_imm = (opcode & 0xf80) >> 7;
1542 instruction->info.data_proc.variant = 1;
1543 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1544 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = shift_imm;
1545 instruction->info.data_proc.shifter_operand.immediate_shift.shift = shift;
1547 /* LSR encodes a shift by 32 bit as 0x0 */
1548 if ((shift == 0x1) && (shift_imm == 0x0))
1549 shift_imm = 0x20;
1551 /* ASR encodes a shift by 32 bit as 0x0 */
1552 if ((shift == 0x2) && (shift_imm == 0x0))
1553 shift_imm = 0x20;
1555 /* ROR by 32 bit is actually a RRX */
1556 if ((shift == 0x3) && (shift_imm == 0x0))
1557 shift = 0x4;
1559 if ((shift_imm == 0x0) && (shift == 0x0))
1561 snprintf(shifter_operand, 32, "r%i", Rm);
1563 else
1565 if (shift == 0x0) /* LSL */
1567 snprintf(shifter_operand, 32, "r%i, LSL #0x%x", Rm, shift_imm);
1569 else if (shift == 0x1) /* LSR */
1571 snprintf(shifter_operand, 32, "r%i, LSR #0x%x", Rm, shift_imm);
1573 else if (shift == 0x2) /* ASR */
1575 snprintf(shifter_operand, 32, "r%i, ASR #0x%x", Rm, shift_imm);
1577 else if (shift == 0x3) /* ROR */
1579 snprintf(shifter_operand, 32, "r%i, ROR #0x%x", Rm, shift_imm);
1581 else if (shift == 0x4) /* RRX */
1583 snprintf(shifter_operand, 32, "r%i, RRX", Rm);
1587 else /* Register shifts ("<Rm>, <shift> <Rs>") */
1589 uint8_t Rs = (opcode & 0xf00) >> 8;
1591 instruction->info.data_proc.variant = 2;
1592 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rm;
1593 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rs;
1594 instruction->info.data_proc.shifter_operand.register_shift.shift = shift;
1596 if (shift == 0x0) /* LSL */
1598 snprintf(shifter_operand, 32, "r%i, LSL r%i", Rm, Rs);
1600 else if (shift == 0x1) /* LSR */
1602 snprintf(shifter_operand, 32, "r%i, LSR r%i", Rm, Rs);
1604 else if (shift == 0x2) /* ASR */
1606 snprintf(shifter_operand, 32, "r%i, ASR r%i", Rm, Rs);
1608 else if (shift == 0x3) /* ROR */
1610 snprintf(shifter_operand, 32, "r%i, ROR r%i", Rm, Rs);
1615 if ((op < 0x8) || (op == 0xc) || (op == 0xe)) /* <opcode3>{<cond>}{S} <Rd>, <Rn>, <shifter_operand> */
1617 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, %s",
1618 address, opcode, mnemonic, COND(opcode),
1619 (S) ? "S" : "", Rd, Rn, shifter_operand);
1621 else if ((op == 0xd) || (op == 0xf)) /* <opcode1>{<cond>}{S} <Rd>, <shifter_operand> */
1623 if (opcode == 0xe1a00000) /* print MOV r0,r0 as NOP */
1624 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tNOP",address, opcode);
1625 else
1626 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, %s",
1627 address, opcode, mnemonic, COND(opcode),
1628 (S) ? "S" : "", Rd, shifter_operand);
1630 else /* <opcode2>{<cond>} <Rn>, <shifter_operand> */
1632 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, %s",
1633 address, opcode, mnemonic, COND(opcode),
1634 Rn, shifter_operand);
1637 return ERROR_OK;
1640 int arm_evaluate_opcode(uint32_t opcode, uint32_t address, struct arm_instruction *instruction)
1642 /* clear fields, to avoid confusion */
1643 memset(instruction, 0, sizeof(struct arm_instruction));
1644 instruction->opcode = opcode;
1645 instruction->instruction_size = 4;
1647 /* catch opcodes with condition field [31:28] = b1111 */
1648 if ((opcode & 0xf0000000) == 0xf0000000)
1650 /* Undefined instruction (or ARMv5E cache preload PLD) */
1651 if ((opcode & 0x08000000) == 0x00000000)
1652 return evaluate_pld(opcode, address, instruction);
1654 /* Undefined instruction (or ARMv6+ SRS/RFE) */
1655 if ((opcode & 0x0e000000) == 0x08000000)
1656 return evaluate_srs(opcode, address, instruction);
1658 /* Branch and branch with link and change to Thumb */
1659 if ((opcode & 0x0e000000) == 0x0a000000)
1660 return evaluate_blx_imm(opcode, address, instruction);
1662 /* Extended coprocessor opcode space (ARMv5 and higher)*/
1663 /* Coprocessor load/store and double register transfers */
1664 if ((opcode & 0x0e000000) == 0x0c000000)
1665 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1667 /* Coprocessor data processing */
1668 if ((opcode & 0x0f000100) == 0x0c000000)
1669 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1671 /* Coprocessor register transfers */
1672 if ((opcode & 0x0f000010) == 0x0c000010)
1673 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1675 /* Undefined instruction */
1676 if ((opcode & 0x0f000000) == 0x0f000000)
1678 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1679 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1680 return ERROR_OK;
1684 /* catch opcodes with [27:25] = b000 */
1685 if ((opcode & 0x0e000000) == 0x00000000)
1687 /* Multiplies, extra load/stores */
1688 if ((opcode & 0x00000090) == 0x00000090)
1689 return evaluate_mul_and_extra_ld_st(opcode, address, instruction);
1691 /* Miscellaneous instructions */
1692 if ((opcode & 0x0f900000) == 0x01000000)
1693 return evaluate_misc_instr(opcode, address, instruction);
1695 return evaluate_data_proc(opcode, address, instruction);
1698 /* catch opcodes with [27:25] = b001 */
1699 if ((opcode & 0x0e000000) == 0x02000000)
1701 /* Undefined instruction */
1702 if ((opcode & 0x0fb00000) == 0x03000000)
1704 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1705 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1706 return ERROR_OK;
1709 /* Move immediate to status register */
1710 if ((opcode & 0x0fb00000) == 0x03200000)
1711 return evaluate_mrs_msr(opcode, address, instruction);
1713 return evaluate_data_proc(opcode, address, instruction);
1717 /* catch opcodes with [27:25] = b010 */
1718 if ((opcode & 0x0e000000) == 0x04000000)
1720 /* Load/store immediate offset */
1721 return evaluate_load_store(opcode, address, instruction);
1724 /* catch opcodes with [27:25] = b011 */
1725 if ((opcode & 0x0e000000) == 0x06000000)
1727 /* Load/store register offset */
1728 if ((opcode & 0x00000010) == 0x00000000)
1729 return evaluate_load_store(opcode, address, instruction);
1731 /* Architecturally Undefined instruction
1732 * ... don't expect these to ever be used
1734 if ((opcode & 0x07f000f0) == 0x07f000f0)
1736 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1737 snprintf(instruction->text, 128,
1738 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEF",
1739 address, opcode);
1740 return ERROR_OK;
1743 /* "media" instructions */
1744 return evaluate_media(opcode, address, instruction);
1747 /* catch opcodes with [27:25] = b100 */
1748 if ((opcode & 0x0e000000) == 0x08000000)
1750 /* Load/store multiple */
1751 return evaluate_ldm_stm(opcode, address, instruction);
1754 /* catch opcodes with [27:25] = b101 */
1755 if ((opcode & 0x0e000000) == 0x0a000000)
1757 /* Branch and branch with link */
1758 return evaluate_b_bl(opcode, address, instruction);
1761 /* catch opcodes with [27:25] = b110 */
1762 if ((opcode & 0x0e000000) == 0x0a000000)
1764 /* Coprocessor load/store and double register transfers */
1765 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1768 /* catch opcodes with [27:25] = b111 */
1769 if ((opcode & 0x0e000000) == 0x0e000000)
1771 /* Software interrupt */
1772 if ((opcode & 0x0f000000) == 0x0f000000)
1773 return evaluate_swi(opcode, address, instruction);
1775 /* Coprocessor data processing */
1776 if ((opcode & 0x0f000010) == 0x0e000000)
1777 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1779 /* Coprocessor register transfers */
1780 if ((opcode & 0x0f000010) == 0x0e000010)
1781 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1784 LOG_ERROR("should never reach this point");
1785 return -1;
1788 static int evaluate_b_bl_blx_thumb(uint16_t opcode,
1789 uint32_t address, struct arm_instruction *instruction)
1791 uint32_t offset = opcode & 0x7ff;
1792 uint32_t opc = (opcode >> 11) & 0x3;
1793 uint32_t target_address;
1794 char *mnemonic = NULL;
1796 /* sign extend 11-bit offset */
1797 if (((opc == 0) || (opc == 2)) && (offset & 0x00000400))
1798 offset = 0xfffff800 | offset;
1800 target_address = address + 4 + (offset << 1);
1802 switch (opc)
1804 /* unconditional branch */
1805 case 0:
1806 instruction->type = ARM_B;
1807 mnemonic = "B";
1808 break;
1809 /* BLX suffix */
1810 case 1:
1811 instruction->type = ARM_BLX;
1812 mnemonic = "BLX";
1813 target_address &= 0xfffffffc;
1814 break;
1815 /* BL/BLX prefix */
1816 case 2:
1817 instruction->type = ARM_UNKNOWN_INSTUCTION;
1818 mnemonic = "prefix";
1819 target_address = offset << 12;
1820 break;
1821 /* BL suffix */
1822 case 3:
1823 instruction->type = ARM_BL;
1824 mnemonic = "BL";
1825 break;
1828 /* TODO: deal correctly with dual opcode (prefixed) BL/BLX;
1829 * these are effectively 32-bit instructions even in Thumb1. For
1830 * disassembly, it's simplest to always use the Thumb2 decoder.
1832 * But some cores will evidently handle them as two instructions,
1833 * where exceptions may occur between the two. The ETMv3.2+ ID
1834 * register has a bit which exposes this behavior.
1837 snprintf(instruction->text, 128,
1838 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%#8.8" PRIx32,
1839 address, opcode, mnemonic, target_address);
1841 instruction->info.b_bl_bx_blx.reg_operand = -1;
1842 instruction->info.b_bl_bx_blx.target_address = target_address;
1844 return ERROR_OK;
1847 static int evaluate_add_sub_thumb(uint16_t opcode,
1848 uint32_t address, struct arm_instruction *instruction)
1850 uint8_t Rd = (opcode >> 0) & 0x7;
1851 uint8_t Rn = (opcode >> 3) & 0x7;
1852 uint8_t Rm_imm = (opcode >> 6) & 0x7;
1853 uint32_t opc = opcode & (1 << 9);
1854 uint32_t reg_imm = opcode & (1 << 10);
1855 char *mnemonic;
1857 if (opc)
1859 instruction->type = ARM_SUB;
1860 mnemonic = "SUBS";
1862 else
1864 /* REVISIT: if reg_imm == 0, display as "MOVS" */
1865 instruction->type = ARM_ADD;
1866 mnemonic = "ADDS";
1869 instruction->info.data_proc.Rd = Rd;
1870 instruction->info.data_proc.Rn = Rn;
1871 instruction->info.data_proc.S = 1;
1873 if (reg_imm)
1875 instruction->info.data_proc.variant = 0; /*immediate*/
1876 instruction->info.data_proc.shifter_operand.immediate.immediate = Rm_imm;
1877 snprintf(instruction->text, 128,
1878 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%d",
1879 address, opcode, mnemonic, Rd, Rn, Rm_imm);
1881 else
1883 instruction->info.data_proc.variant = 1; /*immediate shift*/
1884 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm_imm;
1885 snprintf(instruction->text, 128,
1886 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, r%i",
1887 address, opcode, mnemonic, Rd, Rn, Rm_imm);
1890 return ERROR_OK;
1893 static int evaluate_shift_imm_thumb(uint16_t opcode,
1894 uint32_t address, struct arm_instruction *instruction)
1896 uint8_t Rd = (opcode >> 0) & 0x7;
1897 uint8_t Rm = (opcode >> 3) & 0x7;
1898 uint8_t imm = (opcode >> 6) & 0x1f;
1899 uint8_t opc = (opcode >> 11) & 0x3;
1900 char *mnemonic = NULL;
1902 switch (opc)
1904 case 0:
1905 instruction->type = ARM_MOV;
1906 mnemonic = "LSLS";
1907 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 0;
1908 break;
1909 case 1:
1910 instruction->type = ARM_MOV;
1911 mnemonic = "LSRS";
1912 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 1;
1913 break;
1914 case 2:
1915 instruction->type = ARM_MOV;
1916 mnemonic = "ASRS";
1917 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 2;
1918 break;
1921 if ((imm == 0) && (opc != 0))
1922 imm = 32;
1924 instruction->info.data_proc.Rd = Rd;
1925 instruction->info.data_proc.Rn = -1;
1926 instruction->info.data_proc.S = 1;
1928 instruction->info.data_proc.variant = 1; /*immediate_shift*/
1929 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1930 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = imm;
1932 snprintf(instruction->text, 128,
1933 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%#2.2x" ,
1934 address, opcode, mnemonic, Rd, Rm, imm);
1936 return ERROR_OK;
1939 static int evaluate_data_proc_imm_thumb(uint16_t opcode,
1940 uint32_t address, struct arm_instruction *instruction)
1942 uint8_t imm = opcode & 0xff;
1943 uint8_t Rd = (opcode >> 8) & 0x7;
1944 uint32_t opc = (opcode >> 11) & 0x3;
1945 char *mnemonic = NULL;
1947 instruction->info.data_proc.Rd = Rd;
1948 instruction->info.data_proc.Rn = Rd;
1949 instruction->info.data_proc.S = 1;
1950 instruction->info.data_proc.variant = 0; /*immediate*/
1951 instruction->info.data_proc.shifter_operand.immediate.immediate = imm;
1953 switch (opc)
1955 case 0:
1956 instruction->type = ARM_MOV;
1957 mnemonic = "MOVS";
1958 instruction->info.data_proc.Rn = -1;
1959 break;
1960 case 1:
1961 instruction->type = ARM_CMP;
1962 mnemonic = "CMP";
1963 instruction->info.data_proc.Rd = -1;
1964 break;
1965 case 2:
1966 instruction->type = ARM_ADD;
1967 mnemonic = "ADDS";
1968 break;
1969 case 3:
1970 instruction->type = ARM_SUB;
1971 mnemonic = "SUBS";
1972 break;
1975 snprintf(instruction->text, 128,
1976 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, #%#2.2x",
1977 address, opcode, mnemonic, Rd, imm);
1979 return ERROR_OK;
1982 static int evaluate_data_proc_thumb(uint16_t opcode,
1983 uint32_t address, struct arm_instruction *instruction)
1985 uint8_t high_reg, op, Rm, Rd,H1,H2;
1986 char *mnemonic = NULL;
1987 bool nop = false;
1989 high_reg = (opcode & 0x0400) >> 10;
1990 op = (opcode & 0x03C0) >> 6;
1992 Rd = (opcode & 0x0007);
1993 Rm = (opcode & 0x0038) >> 3;
1994 H1 = (opcode & 0x0080) >> 7;
1995 H2 = (opcode & 0x0040) >> 6;
1997 instruction->info.data_proc.Rd = Rd;
1998 instruction->info.data_proc.Rn = Rd;
1999 instruction->info.data_proc.S = (!high_reg || (instruction->type == ARM_CMP));
2000 instruction->info.data_proc.variant = 1 /*immediate shift*/;
2001 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
2003 if (high_reg)
2005 Rd |= H1 << 3;
2006 Rm |= H2 << 3;
2007 op >>= 2;
2009 switch (op)
2011 case 0x0:
2012 instruction->type = ARM_ADD;
2013 mnemonic = "ADD";
2014 break;
2015 case 0x1:
2016 instruction->type = ARM_CMP;
2017 mnemonic = "CMP";
2018 break;
2019 case 0x2:
2020 instruction->type = ARM_MOV;
2021 mnemonic = "MOV";
2022 if (Rd == Rm)
2023 nop = true;
2024 break;
2025 case 0x3:
2026 if ((opcode & 0x7) == 0x0)
2028 instruction->info.b_bl_bx_blx.reg_operand = Rm;
2029 if (H1)
2031 instruction->type = ARM_BLX;
2032 snprintf(instruction->text, 128,
2033 "0x%8.8" PRIx32
2034 " 0x%4.4x \tBLX\tr%i",
2035 address, opcode, Rm);
2037 else
2039 instruction->type = ARM_BX;
2040 snprintf(instruction->text, 128,
2041 "0x%8.8" PRIx32
2042 " 0x%4.4x \tBX\tr%i",
2043 address, opcode, Rm);
2046 else
2048 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2049 snprintf(instruction->text, 128,
2050 "0x%8.8" PRIx32
2051 " 0x%4.4x \t"
2052 "UNDEFINED INSTRUCTION",
2053 address, opcode);
2055 return ERROR_OK;
2056 break;
2059 else
2061 switch (op)
2063 case 0x0:
2064 instruction->type = ARM_AND;
2065 mnemonic = "ANDS";
2066 break;
2067 case 0x1:
2068 instruction->type = ARM_EOR;
2069 mnemonic = "EORS";
2070 break;
2071 case 0x2:
2072 instruction->type = ARM_MOV;
2073 mnemonic = "LSLS";
2074 instruction->info.data_proc.variant = 2 /*register shift*/;
2075 instruction->info.data_proc.shifter_operand.register_shift.shift = 0;
2076 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
2077 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
2078 break;
2079 case 0x3:
2080 instruction->type = ARM_MOV;
2081 mnemonic = "LSRS";
2082 instruction->info.data_proc.variant = 2 /*register shift*/;
2083 instruction->info.data_proc.shifter_operand.register_shift.shift = 1;
2084 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
2085 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
2086 break;
2087 case 0x4:
2088 instruction->type = ARM_MOV;
2089 mnemonic = "ASRS";
2090 instruction->info.data_proc.variant = 2 /*register shift*/;
2091 instruction->info.data_proc.shifter_operand.register_shift.shift = 2;
2092 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
2093 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
2094 break;
2095 case 0x5:
2096 instruction->type = ARM_ADC;
2097 mnemonic = "ADCS";
2098 break;
2099 case 0x6:
2100 instruction->type = ARM_SBC;
2101 mnemonic = "SBCS";
2102 break;
2103 case 0x7:
2104 instruction->type = ARM_MOV;
2105 mnemonic = "RORS";
2106 instruction->info.data_proc.variant = 2 /*register shift*/;
2107 instruction->info.data_proc.shifter_operand.register_shift.shift = 3;
2108 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
2109 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
2110 break;
2111 case 0x8:
2112 instruction->type = ARM_TST;
2113 mnemonic = "TST";
2114 break;
2115 case 0x9:
2116 instruction->type = ARM_RSB;
2117 mnemonic = "RSBS";
2118 instruction->info.data_proc.variant = 0 /*immediate*/;
2119 instruction->info.data_proc.shifter_operand.immediate.immediate = 0;
2120 instruction->info.data_proc.Rn = Rm;
2121 break;
2122 case 0xA:
2123 instruction->type = ARM_CMP;
2124 mnemonic = "CMP";
2125 break;
2126 case 0xB:
2127 instruction->type = ARM_CMN;
2128 mnemonic = "CMN";
2129 break;
2130 case 0xC:
2131 instruction->type = ARM_ORR;
2132 mnemonic = "ORRS";
2133 break;
2134 case 0xD:
2135 instruction->type = ARM_MUL;
2136 mnemonic = "MULS";
2137 break;
2138 case 0xE:
2139 instruction->type = ARM_BIC;
2140 mnemonic = "BICS";
2141 break;
2142 case 0xF:
2143 instruction->type = ARM_MVN;
2144 mnemonic = "MVNS";
2145 break;
2149 if (nop)
2150 snprintf(instruction->text, 128,
2151 "0x%8.8" PRIx32 " 0x%4.4x \tNOP\t\t\t"
2152 "; (%s r%i, r%i)",
2153 address, opcode, mnemonic, Rd, Rm);
2154 else
2155 snprintf(instruction->text, 128,
2156 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i",
2157 address, opcode, mnemonic, Rd, Rm);
2159 return ERROR_OK;
2162 /* PC-relative data addressing is word-aligned even with Thumb */
2163 static inline uint32_t thumb_alignpc4(uint32_t addr)
2165 return (addr + 4) & ~3;
2168 static int evaluate_load_literal_thumb(uint16_t opcode,
2169 uint32_t address, struct arm_instruction *instruction)
2171 uint32_t immediate;
2172 uint8_t Rd = (opcode >> 8) & 0x7;
2174 instruction->type = ARM_LDR;
2175 immediate = opcode & 0x000000ff;
2176 immediate *= 4;
2178 instruction->info.load_store.Rd = Rd;
2179 instruction->info.load_store.Rn = 15 /*PC*/;
2180 instruction->info.load_store.index_mode = 0; /*offset*/
2181 instruction->info.load_store.offset_mode = 0; /*immediate*/
2182 instruction->info.load_store.offset.offset = immediate;
2184 snprintf(instruction->text, 128,
2185 "0x%8.8" PRIx32 " 0x%4.4x \t"
2186 "LDR\tr%i, [pc, #%#" PRIx32 "]\t; %#8.8" PRIx32,
2187 address, opcode, Rd, immediate,
2188 thumb_alignpc4(address) + immediate);
2190 return ERROR_OK;
2193 static int evaluate_load_store_reg_thumb(uint16_t opcode,
2194 uint32_t address, struct arm_instruction *instruction)
2196 uint8_t Rd = (opcode >> 0) & 0x7;
2197 uint8_t Rn = (opcode >> 3) & 0x7;
2198 uint8_t Rm = (opcode >> 6) & 0x7;
2199 uint8_t opc = (opcode >> 9) & 0x7;
2200 char *mnemonic = NULL;
2202 switch (opc)
2204 case 0:
2205 instruction->type = ARM_STR;
2206 mnemonic = "STR";
2207 break;
2208 case 1:
2209 instruction->type = ARM_STRH;
2210 mnemonic = "STRH";
2211 break;
2212 case 2:
2213 instruction->type = ARM_STRB;
2214 mnemonic = "STRB";
2215 break;
2216 case 3:
2217 instruction->type = ARM_LDRSB;
2218 mnemonic = "LDRSB";
2219 break;
2220 case 4:
2221 instruction->type = ARM_LDR;
2222 mnemonic = "LDR";
2223 break;
2224 case 5:
2225 instruction->type = ARM_LDRH;
2226 mnemonic = "LDRH";
2227 break;
2228 case 6:
2229 instruction->type = ARM_LDRB;
2230 mnemonic = "LDRB";
2231 break;
2232 case 7:
2233 instruction->type = ARM_LDRSH;
2234 mnemonic = "LDRSH";
2235 break;
2238 snprintf(instruction->text, 128,
2239 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [r%i, r%i]",
2240 address, opcode, mnemonic, Rd, Rn, Rm);
2242 instruction->info.load_store.Rd = Rd;
2243 instruction->info.load_store.Rn = Rn;
2244 instruction->info.load_store.index_mode = 0; /*offset*/
2245 instruction->info.load_store.offset_mode = 1; /*register*/
2246 instruction->info.load_store.offset.reg.Rm = Rm;
2248 return ERROR_OK;
2251 static int evaluate_load_store_imm_thumb(uint16_t opcode,
2252 uint32_t address, struct arm_instruction *instruction)
2254 uint32_t offset = (opcode >> 6) & 0x1f;
2255 uint8_t Rd = (opcode >> 0) & 0x7;
2256 uint8_t Rn = (opcode >> 3) & 0x7;
2257 uint32_t L = opcode & (1 << 11);
2258 uint32_t B = opcode & (1 << 12);
2259 char *mnemonic;
2260 char suffix = ' ';
2261 uint32_t shift = 2;
2263 if (L)
2265 instruction->type = ARM_LDR;
2266 mnemonic = "LDR";
2268 else
2270 instruction->type = ARM_STR;
2271 mnemonic = "STR";
2274 if ((opcode&0xF000) == 0x8000)
2276 suffix = 'H';
2277 shift = 1;
2279 else if (B)
2281 suffix = 'B';
2282 shift = 0;
2285 snprintf(instruction->text, 128,
2286 "0x%8.8" PRIx32 " 0x%4.4x \t%s%c\tr%i, [r%i, #%#" PRIx32 "]",
2287 address, opcode, mnemonic, suffix, Rd, Rn, offset << shift);
2289 instruction->info.load_store.Rd = Rd;
2290 instruction->info.load_store.Rn = Rn;
2291 instruction->info.load_store.index_mode = 0; /*offset*/
2292 instruction->info.load_store.offset_mode = 0; /*immediate*/
2293 instruction->info.load_store.offset.offset = offset << shift;
2295 return ERROR_OK;
2298 static int evaluate_load_store_stack_thumb(uint16_t opcode,
2299 uint32_t address, struct arm_instruction *instruction)
2301 uint32_t offset = opcode & 0xff;
2302 uint8_t Rd = (opcode >> 8) & 0x7;
2303 uint32_t L = opcode & (1 << 11);
2304 char *mnemonic;
2306 if (L)
2308 instruction->type = ARM_LDR;
2309 mnemonic = "LDR";
2311 else
2313 instruction->type = ARM_STR;
2314 mnemonic = "STR";
2317 snprintf(instruction->text, 128,
2318 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [SP, #%#" PRIx32 "]",
2319 address, opcode, mnemonic, Rd, offset*4);
2321 instruction->info.load_store.Rd = Rd;
2322 instruction->info.load_store.Rn = 13 /*SP*/;
2323 instruction->info.load_store.index_mode = 0; /*offset*/
2324 instruction->info.load_store.offset_mode = 0; /*immediate*/
2325 instruction->info.load_store.offset.offset = offset*4;
2327 return ERROR_OK;
2330 static int evaluate_add_sp_pc_thumb(uint16_t opcode,
2331 uint32_t address, struct arm_instruction *instruction)
2333 uint32_t imm = opcode & 0xff;
2334 uint8_t Rd = (opcode >> 8) & 0x7;
2335 uint8_t Rn;
2336 uint32_t SP = opcode & (1 << 11);
2337 char *reg_name;
2339 instruction->type = ARM_ADD;
2341 if (SP)
2343 reg_name = "SP";
2344 Rn = 13;
2346 else
2348 reg_name = "PC";
2349 Rn = 15;
2352 snprintf(instruction->text, 128,
2353 "0x%8.8" PRIx32 " 0x%4.4x \tADD\tr%i, %s, #%#" PRIx32,
2354 address, opcode, Rd, reg_name, imm * 4);
2356 instruction->info.data_proc.variant = 0 /* immediate */;
2357 instruction->info.data_proc.Rd = Rd;
2358 instruction->info.data_proc.Rn = Rn;
2359 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
2361 return ERROR_OK;
2364 static int evaluate_adjust_stack_thumb(uint16_t opcode,
2365 uint32_t address, struct arm_instruction *instruction)
2367 uint32_t imm = opcode & 0x7f;
2368 uint8_t opc = opcode & (1 << 7);
2369 char *mnemonic;
2372 if (opc)
2374 instruction->type = ARM_SUB;
2375 mnemonic = "SUB";
2377 else
2379 instruction->type = ARM_ADD;
2380 mnemonic = "ADD";
2383 snprintf(instruction->text, 128,
2384 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tSP, #%#" PRIx32,
2385 address, opcode, mnemonic, imm*4);
2387 instruction->info.data_proc.variant = 0 /* immediate */;
2388 instruction->info.data_proc.Rd = 13 /*SP*/;
2389 instruction->info.data_proc.Rn = 13 /*SP*/;
2390 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
2392 return ERROR_OK;
2395 static int evaluate_breakpoint_thumb(uint16_t opcode,
2396 uint32_t address, struct arm_instruction *instruction)
2398 uint32_t imm = opcode & 0xff;
2400 instruction->type = ARM_BKPT;
2402 snprintf(instruction->text, 128,
2403 "0x%8.8" PRIx32 " 0x%4.4x \tBKPT\t%#2.2" PRIx32 "",
2404 address, opcode, imm);
2406 return ERROR_OK;
2409 static int evaluate_load_store_multiple_thumb(uint16_t opcode,
2410 uint32_t address, struct arm_instruction *instruction)
2412 uint32_t reg_list = opcode & 0xff;
2413 uint32_t L = opcode & (1 << 11);
2414 uint32_t R = opcode & (1 << 8);
2415 uint8_t Rn = (opcode >> 8) & 7;
2416 uint8_t addr_mode = 0 /* IA */;
2417 char reg_names[40];
2418 char *reg_names_p;
2419 char *mnemonic;
2420 char ptr_name[7] = "";
2421 int i;
2423 /* REVISIT: in ThumbEE mode, there are no LDM or STM instructions.
2424 * The STMIA and LDMIA opcodes are used for other instructions.
2427 if ((opcode & 0xf000) == 0xc000)
2428 { /* generic load/store multiple */
2429 char *wback = "!";
2431 if (L)
2433 instruction->type = ARM_LDM;
2434 mnemonic = "LDM";
2435 if (opcode & (1 << Rn))
2436 wback = "";
2438 else
2440 instruction->type = ARM_STM;
2441 mnemonic = "STM";
2443 snprintf(ptr_name, sizeof ptr_name, "r%i%s, ", Rn, wback);
2445 else
2446 { /* push/pop */
2447 Rn = 13; /* SP */
2448 if (L)
2450 instruction->type = ARM_LDM;
2451 mnemonic = "POP";
2452 if (R)
2453 reg_list |= (1 << 15) /*PC*/;
2455 else
2457 instruction->type = ARM_STM;
2458 mnemonic = "PUSH";
2459 addr_mode = 3; /*DB*/
2460 if (R)
2461 reg_list |= (1 << 14) /*LR*/;
2465 reg_names_p = reg_names;
2466 for (i = 0; i <= 15; i++)
2468 if (reg_list & (1 << i))
2469 reg_names_p += snprintf(reg_names_p, (reg_names + 40 - reg_names_p), "r%i, ", i);
2471 if (reg_names_p > reg_names)
2472 reg_names_p[-2] = '\0';
2473 else /* invalid op : no registers */
2474 reg_names[0] = '\0';
2476 snprintf(instruction->text, 128,
2477 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%s{%s}",
2478 address, opcode, mnemonic, ptr_name, reg_names);
2480 instruction->info.load_store_multiple.register_list = reg_list;
2481 instruction->info.load_store_multiple.Rn = Rn;
2482 instruction->info.load_store_multiple.addressing_mode = addr_mode;
2484 return ERROR_OK;
2487 static int evaluate_cond_branch_thumb(uint16_t opcode,
2488 uint32_t address, struct arm_instruction *instruction)
2490 uint32_t offset = opcode & 0xff;
2491 uint8_t cond = (opcode >> 8) & 0xf;
2492 uint32_t target_address;
2494 if (cond == 0xf)
2496 instruction->type = ARM_SWI;
2497 snprintf(instruction->text, 128,
2498 "0x%8.8" PRIx32 " 0x%4.4x \tSVC\t%#2.2" PRIx32,
2499 address, opcode, offset);
2500 return ERROR_OK;
2502 else if (cond == 0xe)
2504 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2505 snprintf(instruction->text, 128,
2506 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2507 address, opcode);
2508 return ERROR_OK;
2511 /* sign extend 8-bit offset */
2512 if (offset & 0x00000080)
2513 offset = 0xffffff00 | offset;
2515 target_address = address + 4 + (offset << 1);
2517 snprintf(instruction->text, 128,
2518 "0x%8.8" PRIx32 " 0x%4.4x \tB%s\t%#8.8" PRIx32,
2519 address, opcode,
2520 arm_condition_strings[cond], target_address);
2522 instruction->type = ARM_B;
2523 instruction->info.b_bl_bx_blx.reg_operand = -1;
2524 instruction->info.b_bl_bx_blx.target_address = target_address;
2526 return ERROR_OK;
2529 static int evaluate_cb_thumb(uint16_t opcode, uint32_t address,
2530 struct arm_instruction *instruction)
2532 unsigned offset;
2534 /* added in Thumb2 */
2535 offset = (opcode >> 3) & 0x1f;
2536 offset |= (opcode & 0x0200) >> 4;
2538 snprintf(instruction->text, 128,
2539 "0x%8.8" PRIx32 " 0x%4.4x \tCB%sZ\tr%d, %#8.8" PRIx32,
2540 address, opcode,
2541 (opcode & 0x0800) ? "N" : "",
2542 opcode & 0x7, address + 4 + (offset << 1));
2544 return ERROR_OK;
2547 static int evaluate_extend_thumb(uint16_t opcode, uint32_t address,
2548 struct arm_instruction *instruction)
2550 /* added in ARMv6 */
2551 snprintf(instruction->text, 128,
2552 "0x%8.8" PRIx32 " 0x%4.4x \t%cXT%c\tr%d, r%d",
2553 address, opcode,
2554 (opcode & 0x0080) ? 'U' : 'S',
2555 (opcode & 0x0040) ? 'B' : 'H',
2556 opcode & 0x7, (opcode >> 3) & 0x7);
2558 return ERROR_OK;
2561 static int evaluate_cps_thumb(uint16_t opcode, uint32_t address,
2562 struct arm_instruction *instruction)
2564 /* added in ARMv6 */
2565 if ((opcode & 0x0ff0) == 0x0650)
2566 snprintf(instruction->text, 128,
2567 "0x%8.8" PRIx32 " 0x%4.4x \tSETEND %s",
2568 address, opcode,
2569 (opcode & 0x80) ? "BE" : "LE");
2570 else /* ASSUME (opcode & 0x0fe0) == 0x0660 */
2571 snprintf(instruction->text, 128,
2572 "0x%8.8" PRIx32 " 0x%4.4x \tCPSI%c\t%s%s%s",
2573 address, opcode,
2574 (opcode & 0x0010) ? 'D' : 'E',
2575 (opcode & 0x0004) ? "A" : "",
2576 (opcode & 0x0002) ? "I" : "",
2577 (opcode & 0x0001) ? "F" : "");
2579 return ERROR_OK;
2582 static int evaluate_byterev_thumb(uint16_t opcode, uint32_t address,
2583 struct arm_instruction *instruction)
2585 char *suffix;
2587 /* added in ARMv6 */
2588 switch ((opcode >> 6) & 3) {
2589 case 0:
2590 suffix = "";
2591 break;
2592 case 1:
2593 suffix = "16";
2594 break;
2595 default:
2596 suffix = "SH";
2597 break;
2599 snprintf(instruction->text, 128,
2600 "0x%8.8" PRIx32 " 0x%4.4x \tREV%s\tr%d, r%d",
2601 address, opcode, suffix,
2602 opcode & 0x7, (opcode >> 3) & 0x7);
2604 return ERROR_OK;
2607 static int evaluate_hint_thumb(uint16_t opcode, uint32_t address,
2608 struct arm_instruction *instruction)
2610 char *hint;
2612 switch ((opcode >> 4) & 0x0f) {
2613 case 0:
2614 hint = "NOP";
2615 break;
2616 case 1:
2617 hint = "YIELD";
2618 break;
2619 case 2:
2620 hint = "WFE";
2621 break;
2622 case 3:
2623 hint = "WFI";
2624 break;
2625 case 4:
2626 hint = "SEV";
2627 break;
2628 default:
2629 hint = "HINT (UNRECOGNIZED)";
2630 break;
2633 snprintf(instruction->text, 128,
2634 "0x%8.8" PRIx32 " 0x%4.4x \t%s",
2635 address, opcode, hint);
2637 return ERROR_OK;
2640 static int evaluate_ifthen_thumb(uint16_t opcode, uint32_t address,
2641 struct arm_instruction *instruction)
2643 unsigned cond = (opcode >> 4) & 0x0f;
2644 char *x = "", *y = "", *z = "";
2646 if (opcode & 0x01)
2647 z = (opcode & 0x02) ? "T" : "E";
2648 if (opcode & 0x03)
2649 y = (opcode & 0x04) ? "T" : "E";
2650 if (opcode & 0x07)
2651 x = (opcode & 0x08) ? "T" : "E";
2653 snprintf(instruction->text, 128,
2654 "0x%8.8" PRIx32 " 0x%4.4x \tIT%s%s%s\t%s",
2655 address, opcode,
2656 x, y, z, arm_condition_strings[cond]);
2658 /* NOTE: strictly speaking, the next 1-4 instructions should
2659 * now be displayed with the relevant conditional suffix...
2662 return ERROR_OK;
2665 int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
2667 /* clear fields, to avoid confusion */
2668 memset(instruction, 0, sizeof(struct arm_instruction));
2669 instruction->opcode = opcode;
2670 instruction->instruction_size = 2;
2672 if ((opcode & 0xe000) == 0x0000)
2674 /* add/substract register or immediate */
2675 if ((opcode & 0x1800) == 0x1800)
2676 return evaluate_add_sub_thumb(opcode, address, instruction);
2677 /* shift by immediate */
2678 else
2679 return evaluate_shift_imm_thumb(opcode, address, instruction);
2682 /* Add/substract/compare/move immediate */
2683 if ((opcode & 0xe000) == 0x2000)
2685 return evaluate_data_proc_imm_thumb(opcode, address, instruction);
2688 /* Data processing instructions */
2689 if ((opcode & 0xf800) == 0x4000)
2691 return evaluate_data_proc_thumb(opcode, address, instruction);
2694 /* Load from literal pool */
2695 if ((opcode & 0xf800) == 0x4800)
2697 return evaluate_load_literal_thumb(opcode, address, instruction);
2700 /* Load/Store register offset */
2701 if ((opcode & 0xf000) == 0x5000)
2703 return evaluate_load_store_reg_thumb(opcode, address, instruction);
2706 /* Load/Store immediate offset */
2707 if (((opcode & 0xe000) == 0x6000)
2708 ||((opcode & 0xf000) == 0x8000))
2710 return evaluate_load_store_imm_thumb(opcode, address, instruction);
2713 /* Load/Store from/to stack */
2714 if ((opcode & 0xf000) == 0x9000)
2716 return evaluate_load_store_stack_thumb(opcode, address, instruction);
2719 /* Add to SP/PC */
2720 if ((opcode & 0xf000) == 0xa000)
2722 return evaluate_add_sp_pc_thumb(opcode, address, instruction);
2725 /* Misc */
2726 if ((opcode & 0xf000) == 0xb000)
2728 switch ((opcode >> 8) & 0x0f) {
2729 case 0x0:
2730 return evaluate_adjust_stack_thumb(opcode, address, instruction);
2731 case 0x1:
2732 case 0x3:
2733 case 0x9:
2734 case 0xb:
2735 return evaluate_cb_thumb(opcode, address, instruction);
2736 case 0x2:
2737 return evaluate_extend_thumb(opcode, address, instruction);
2738 case 0x4:
2739 case 0x5:
2740 case 0xc:
2741 case 0xd:
2742 return evaluate_load_store_multiple_thumb(opcode, address,
2743 instruction);
2744 case 0x6:
2745 return evaluate_cps_thumb(opcode, address, instruction);
2746 case 0xa:
2747 if ((opcode & 0x00c0) == 0x0080)
2748 break;
2749 return evaluate_byterev_thumb(opcode, address, instruction);
2750 case 0xe:
2751 return evaluate_breakpoint_thumb(opcode, address, instruction);
2752 case 0xf:
2753 if (opcode & 0x000f)
2754 return evaluate_ifthen_thumb(opcode, address,
2755 instruction);
2756 else
2757 return evaluate_hint_thumb(opcode, address,
2758 instruction);
2761 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2762 snprintf(instruction->text, 128,
2763 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2764 address, opcode);
2765 return ERROR_OK;
2768 /* Load/Store multiple */
2769 if ((opcode & 0xf000) == 0xc000)
2771 return evaluate_load_store_multiple_thumb(opcode, address, instruction);
2774 /* Conditional branch + SWI */
2775 if ((opcode & 0xf000) == 0xd000)
2777 return evaluate_cond_branch_thumb(opcode, address, instruction);
2780 if ((opcode & 0xe000) == 0xe000)
2782 /* Undefined instructions */
2783 if ((opcode & 0xf801) == 0xe801)
2785 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2786 snprintf(instruction->text, 128,
2787 "0x%8.8" PRIx32 " 0x%8.8x\t"
2788 "UNDEFINED INSTRUCTION",
2789 address, opcode);
2790 return ERROR_OK;
2792 else
2793 { /* Branch to offset */
2794 return evaluate_b_bl_blx_thumb(opcode, address, instruction);
2798 LOG_ERROR("should never reach this point (opcode=%04x)",opcode);
2799 return -1;
2802 static int t2ev_b_bl(uint32_t opcode, uint32_t address,
2803 struct arm_instruction *instruction, char *cp)
2805 unsigned offset;
2806 unsigned b21 = 1 << 21;
2807 unsigned b22 = 1 << 22;
2809 /* instead of combining two smaller 16-bit branch instructions,
2810 * Thumb2 uses only one larger 32-bit instruction.
2812 offset = opcode & 0x7ff;
2813 offset |= (opcode & 0x03ff0000) >> 5;
2814 if (opcode & (1 << 26)) {
2815 offset |= 0xff << 23;
2816 if ((opcode & (1 << 11)) == 0)
2817 b21 = 0;
2818 if ((opcode & (1 << 13)) == 0)
2819 b22 = 0;
2820 } else {
2821 if (opcode & (1 << 11))
2822 b21 = 0;
2823 if (opcode & (1 << 13))
2824 b22 = 0;
2826 offset |= b21;
2827 offset |= b22;
2830 address += 4;
2831 address += offset << 1;
2833 instruction->type = (opcode & (1 << 14)) ? ARM_BL : ARM_B;
2834 instruction->info.b_bl_bx_blx.reg_operand = -1;
2835 instruction->info.b_bl_bx_blx.target_address = address;
2836 sprintf(cp, "%s\t%#8.8" PRIx32,
2837 (opcode & (1 << 14)) ? "BL" : "B.W",
2838 address);
2840 return ERROR_OK;
2843 static int t2ev_cond_b(uint32_t opcode, uint32_t address,
2844 struct arm_instruction *instruction, char *cp)
2846 unsigned offset;
2847 unsigned b17 = 1 << 17;
2848 unsigned b18 = 1 << 18;
2849 unsigned cond = (opcode >> 22) & 0x0f;
2851 offset = opcode & 0x7ff;
2852 offset |= (opcode & 0x003f0000) >> 5;
2853 if (opcode & (1 << 26)) {
2854 offset |= 0xffff << 19;
2855 if ((opcode & (1 << 11)) == 0)
2856 b17 = 0;
2857 if ((opcode & (1 << 13)) == 0)
2858 b18 = 0;
2859 } else {
2860 if (opcode & (1 << 11))
2861 b17 = 0;
2862 if (opcode & (1 << 13))
2863 b18 = 0;
2865 offset |= b17;
2866 offset |= b18;
2868 address += 4;
2869 address += offset << 1;
2871 instruction->type = ARM_B;
2872 instruction->info.b_bl_bx_blx.reg_operand = -1;
2873 instruction->info.b_bl_bx_blx.target_address = address;
2874 sprintf(cp, "B%s.W\t%#8.8" PRIx32,
2875 arm_condition_strings[cond],
2876 address);
2878 return ERROR_OK;
2881 static const char *special_name(int number)
2883 char *special = "(RESERVED)";
2885 switch (number) {
2886 case 0:
2887 special = "apsr";
2888 break;
2889 case 1:
2890 special = "iapsr";
2891 break;
2892 case 2:
2893 special = "eapsr";
2894 break;
2895 case 3:
2896 special = "xpsr";
2897 break;
2898 case 5:
2899 special = "ipsr";
2900 break;
2901 case 6:
2902 special = "epsr";
2903 break;
2904 case 7:
2905 special = "iepsr";
2906 break;
2907 case 8:
2908 special = "msp";
2909 break;
2910 case 9:
2911 special = "psp";
2912 break;
2913 case 16:
2914 special = "primask";
2915 break;
2916 case 17:
2917 special = "basepri";
2918 break;
2919 case 18:
2920 special = "basepri_max";
2921 break;
2922 case 19:
2923 special = "faultmask";
2924 break;
2925 case 20:
2926 special = "control";
2927 break;
2929 return special;
2932 static int t2ev_hint(uint32_t opcode, uint32_t address,
2933 struct arm_instruction *instruction, char *cp)
2935 const char *mnemonic;
2937 if (opcode & 0x0700) {
2938 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2939 strcpy(cp, "UNDEFINED");
2940 return ERROR_OK;
2943 if (opcode & 0x00f0) {
2944 sprintf(cp, "DBG\t#%d", (int) opcode & 0xf);
2945 return ERROR_OK;
2948 switch (opcode & 0x0f) {
2949 case 0:
2950 mnemonic = "NOP.W";
2951 break;
2952 case 1:
2953 mnemonic = "YIELD.W";
2954 break;
2955 case 2:
2956 mnemonic = "WFE.W";
2957 break;
2958 case 3:
2959 mnemonic = "WFI.W";
2960 break;
2961 case 4:
2962 mnemonic = "SEV.W";
2963 break;
2964 default:
2965 mnemonic = "HINT.W (UNRECOGNIZED)";
2966 break;
2968 strcpy(cp, mnemonic);
2969 return ERROR_OK;
2972 static int t2ev_misc(uint32_t opcode, uint32_t address,
2973 struct arm_instruction *instruction, char *cp)
2975 const char *mnemonic;
2977 switch ((opcode >> 4) & 0x0f) {
2978 case 0:
2979 mnemonic = "LEAVEX";
2980 break;
2981 case 1:
2982 mnemonic = "ENTERX";
2983 break;
2984 case 2:
2985 mnemonic = "CLREX";
2986 break;
2987 case 4:
2988 mnemonic = "DSB";
2989 break;
2990 case 5:
2991 mnemonic = "DMB";
2992 break;
2993 case 6:
2994 mnemonic = "ISB";
2995 break;
2996 default:
2997 return ERROR_INVALID_ARGUMENTS;
2999 strcpy(cp, mnemonic);
3000 return ERROR_OK;
3003 static int t2ev_b_misc(uint32_t opcode, uint32_t address,
3004 struct arm_instruction *instruction, char *cp)
3006 /* permanently undefined */
3007 if ((opcode & 0x07f07000) == 0x07f02000) {
3008 instruction->type = ARM_UNDEFINED_INSTRUCTION;
3009 strcpy(cp, "UNDEFINED");
3010 return ERROR_OK;
3013 switch ((opcode >> 12) & 0x5) {
3014 case 0x1:
3015 case 0x5:
3016 return t2ev_b_bl(opcode, address, instruction, cp);
3017 case 0x4:
3018 goto undef;
3019 case 0:
3020 if (((opcode >> 23) & 0x07) != 0x07)
3021 return t2ev_cond_b(opcode, address, instruction, cp);
3022 if (opcode & (1 << 26))
3023 goto undef;
3024 break;
3027 switch ((opcode >> 20) & 0x7f) {
3028 case 0x38:
3029 case 0x39:
3030 sprintf(cp, "MSR\t%s, r%d", special_name(opcode & 0xff),
3031 (int) (opcode >> 16) & 0x0f);
3032 return ERROR_OK;
3033 case 0x3a:
3034 return t2ev_hint(opcode, address, instruction, cp);
3035 case 0x3b:
3036 return t2ev_misc(opcode, address, instruction, cp);
3037 case 0x3c:
3038 sprintf(cp, "BXJ\tr%d", (int) (opcode >> 16) & 0x0f);
3039 return ERROR_OK;
3040 case 0x3e:
3041 case 0x3f:
3042 sprintf(cp, "MRS\tr%d, %s", (int) (opcode >> 8) & 0x0f,
3043 special_name(opcode & 0xff));
3044 return ERROR_OK;
3047 undef:
3048 return ERROR_INVALID_ARGUMENTS;
3051 static int t2ev_data_mod_immed(uint32_t opcode, uint32_t address,
3052 struct arm_instruction *instruction, char *cp)
3054 char *mnemonic = NULL;
3055 int rn = (opcode >> 16) & 0xf;
3056 int rd = (opcode >> 8) & 0xf;
3057 unsigned immed = opcode & 0xff;
3058 unsigned func;
3059 bool one = false;
3060 char *suffix = "";
3061 char *suffix2 = "";
3063 /* ARMv7-M: A5.3.2 Modified immediate constants */
3064 func = (opcode >> 11) & 0x0e;
3065 if (immed & 0x80)
3066 func |= 1;
3067 if (opcode & (1 << 26))
3068 func |= 0x10;
3070 /* "Modified" immediates */
3071 switch (func >> 1) {
3072 case 0:
3073 break;
3074 case 2:
3075 immed <<= 8;
3076 /* FALLTHROUGH */
3077 case 1:
3078 immed += immed << 16;
3079 break;
3080 case 3:
3081 immed += immed << 8;
3082 immed += immed << 16;
3083 break;
3084 default:
3085 immed |= 0x80;
3086 immed = ror(immed, func);
3089 if (opcode & (1 << 20))
3090 suffix = "S";
3092 switch ((opcode >> 21) & 0xf) {
3093 case 0:
3094 if (rd == 0xf) {
3095 instruction->type = ARM_TST;
3096 mnemonic = "TST";
3097 one = true;
3098 suffix = "";
3099 rd = rn;
3100 } else {
3101 instruction->type = ARM_AND;
3102 mnemonic = "AND";
3104 break;
3105 case 1:
3106 instruction->type = ARM_BIC;
3107 mnemonic = "BIC";
3108 break;
3109 case 2:
3110 if (rn == 0xf) {
3111 instruction->type = ARM_MOV;
3112 mnemonic = "MOV";
3113 one = true;
3114 suffix2 = ".W";
3115 } else {
3116 instruction->type = ARM_ORR;
3117 mnemonic = "ORR";
3119 break;
3120 case 3:
3121 if (rn == 0xf) {
3122 instruction->type = ARM_MVN;
3123 mnemonic = "MVN";
3124 one = true;
3125 } else {
3126 // instruction->type = ARM_ORN;
3127 mnemonic = "ORN";
3129 break;
3130 case 4:
3131 if (rd == 0xf) {
3132 instruction->type = ARM_TEQ;
3133 mnemonic = "TEQ";
3134 one = true;
3135 suffix = "";
3136 rd = rn;
3137 } else {
3138 instruction->type = ARM_EOR;
3139 mnemonic = "EOR";
3141 break;
3142 case 8:
3143 if (rd == 0xf) {
3144 instruction->type = ARM_CMN;
3145 mnemonic = "CMN";
3146 one = true;
3147 suffix = "";
3148 rd = rn;
3149 } else {
3150 instruction->type = ARM_ADD;
3151 mnemonic = "ADD";
3152 suffix2 = ".W";
3154 break;
3155 case 10:
3156 instruction->type = ARM_ADC;
3157 mnemonic = "ADC";
3158 suffix2 = ".W";
3159 break;
3160 case 11:
3161 instruction->type = ARM_SBC;
3162 mnemonic = "SBC";
3163 break;
3164 case 13:
3165 if (rd == 0xf) {
3166 instruction->type = ARM_CMP;
3167 mnemonic = "CMP";
3168 one = true;
3169 suffix = "";
3170 rd = rn;
3171 } else {
3172 instruction->type = ARM_SUB;
3173 mnemonic = "SUB";
3175 suffix2 = ".W";
3176 break;
3177 case 14:
3178 instruction->type = ARM_RSB;
3179 mnemonic = "RSB";
3180 suffix2 = ".W";
3181 break;
3182 default:
3183 return ERROR_INVALID_ARGUMENTS;
3186 if (one)
3187 sprintf(cp, "%s%s\tr%d, #%d\t; %#8.8x",
3188 mnemonic, suffix2 ,rd, immed, immed);
3189 else
3190 sprintf(cp, "%s%s%s\tr%d, r%d, #%d\t; %#8.8x",
3191 mnemonic, suffix, suffix2,
3192 rd, rn, immed, immed);
3194 return ERROR_OK;
3197 static int t2ev_data_immed(uint32_t opcode, uint32_t address,
3198 struct arm_instruction *instruction, char *cp)
3200 char *mnemonic = NULL;
3201 int rn = (opcode >> 16) & 0xf;
3202 int rd = (opcode >> 8) & 0xf;
3203 unsigned immed;
3204 bool add = false;
3205 bool is_signed = false;
3207 immed = (opcode & 0x0ff) | ((opcode & 0x7000) >> 4);
3208 if (opcode & (1 << 26))
3209 immed |= (1 << 11);
3211 switch ((opcode >> 20) & 0x1f) {
3212 case 0:
3213 if (rn == 0xf) {
3214 add = true;
3215 goto do_adr;
3217 mnemonic = "ADDW";
3218 break;
3219 case 4:
3220 immed |= (opcode >> 4) & 0xf000;
3221 sprintf(cp, "MOVW\tr%d, #%d\t; %#3.3x", rd, immed, immed);
3222 return ERROR_OK;
3223 case 0x0a:
3224 if (rn == 0xf)
3225 goto do_adr;
3226 mnemonic = "SUBW";
3227 break;
3228 case 0x0c:
3229 /* move constant to top 16 bits of register */
3230 immed |= (opcode >> 4) & 0xf000;
3231 sprintf(cp, "MOVT\tr%d, #%d\t; %#4.4x", rn, immed, immed);
3232 return ERROR_OK;
3233 case 0x10:
3234 case 0x12:
3235 is_signed = true;
3236 case 0x18:
3237 case 0x1a:
3238 /* signed/unsigned saturated add */
3239 immed = (opcode >> 6) & 0x03;
3240 immed |= (opcode >> 10) & 0x1c;
3241 sprintf(cp, "%sSAT\tr%d, #%d, r%d, %s #%d\t",
3242 is_signed ? "S" : "U",
3243 rd, (int) (opcode & 0x1f) + is_signed, rn,
3244 (opcode & (1 << 21)) ? "ASR" : "LSL",
3245 immed ? immed : 32);
3246 return ERROR_OK;
3247 case 0x14:
3248 is_signed = true;
3249 /* FALLTHROUGH */
3250 case 0x1c:
3251 /* signed/unsigned bitfield extract */
3252 immed = (opcode >> 6) & 0x03;
3253 immed |= (opcode >> 10) & 0x1c;
3254 sprintf(cp, "%sBFX\tr%d, r%d, #%d, #%d\t",
3255 is_signed ? "S" : "U",
3256 rd, rn, immed,
3257 (int) (opcode & 0x1f) + 1);
3258 return ERROR_OK;
3259 case 0x16:
3260 immed = (opcode >> 6) & 0x03;
3261 immed |= (opcode >> 10) & 0x1c;
3262 if (rn == 0xf) /* bitfield clear */
3263 sprintf(cp, "BFC\tr%d, #%d, #%d\t",
3264 rd, immed,
3265 (int) (opcode & 0x1f) + 1 - immed);
3266 else /* bitfield insert */
3267 sprintf(cp, "BFI\tr%d, r%d, #%d, #%d\t",
3268 rd, rn, immed,
3269 (int) (opcode & 0x1f) + 1 - immed);
3270 return ERROR_OK;
3271 default:
3272 return ERROR_INVALID_ARGUMENTS;
3275 sprintf(cp, "%s\tr%d, r%d, #%d\t; %#3.3x", mnemonic,
3276 rd, rn, immed, immed);
3277 return ERROR_OK;
3279 do_adr:
3280 address = thumb_alignpc4(address);
3281 if (add)
3282 address += immed;
3283 else
3284 address -= immed;
3285 /* REVISIT "ADD/SUB Rd, PC, #const ; 0x..." might be better;
3286 * not hiding the pc-relative stuff will sometimes be useful.
3288 sprintf(cp, "ADR.W\tr%d, %#8.8" PRIx32, rd, address);
3289 return ERROR_OK;
3292 static int t2ev_store_single(uint32_t opcode, uint32_t address,
3293 struct arm_instruction *instruction, char *cp)
3295 unsigned op = (opcode >> 20) & 0xf;
3296 char *size = "";
3297 char *suffix = "";
3298 char *p1 = "";
3299 char *p2 = "]";
3300 unsigned immed;
3301 unsigned rn = (opcode >> 16) & 0x0f;
3302 unsigned rt = (opcode >> 12) & 0x0f;
3304 if (rn == 0xf)
3305 return ERROR_INVALID_ARGUMENTS;
3307 if (opcode & 0x0800)
3308 op |= 1;
3309 switch (op) {
3310 /* byte */
3311 case 0x8:
3312 case 0x9:
3313 size = "B";
3314 goto imm12;
3315 case 0x1:
3316 size = "B";
3317 goto imm8;
3318 case 0x0:
3319 size = "B";
3320 break;
3321 /* halfword */
3322 case 0xa:
3323 case 0xb:
3324 size = "H";
3325 goto imm12;
3326 case 0x3:
3327 size = "H";
3328 goto imm8;
3329 case 0x2:
3330 size = "H";
3331 break;
3332 /* word */
3333 case 0xc:
3334 case 0xd:
3335 goto imm12;
3336 case 0x5:
3337 goto imm8;
3338 case 0x4:
3339 break;
3340 /* error */
3341 default:
3342 return ERROR_INVALID_ARGUMENTS;
3345 sprintf(cp, "STR%s.W\tr%d, [r%d, r%d, LSL #%d]",
3346 size, rt, rn, (int) opcode & 0x0f,
3347 (int) (opcode >> 4) & 0x03);
3348 return ERROR_OK;
3350 imm12:
3351 immed = opcode & 0x0fff;
3352 sprintf(cp, "STR%s.W\tr%d, [r%d, #%u]\t; %#3.3x",
3353 size, rt, rn, immed, immed);
3354 return ERROR_OK;
3356 imm8:
3357 immed = opcode & 0x00ff;
3359 switch (opcode & 0x700) {
3360 case 0x600:
3361 suffix = "T";
3362 break;
3363 case 0x000:
3364 case 0x200:
3365 return ERROR_INVALID_ARGUMENTS;
3368 /* two indexed modes will write back rn */
3369 if (opcode & 0x100) {
3370 if (opcode & 0x400) /* pre-indexed */
3371 p2 = "]!";
3372 else { /* post-indexed */
3373 p1 = "]";
3374 p2 = "";
3378 sprintf(cp, "STR%s%s\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
3379 size, suffix, rt, rn, p1,
3380 (opcode & 0x200) ? "" : "-",
3381 immed, p2, immed);
3382 return ERROR_OK;
3385 static int t2ev_mul32(uint32_t opcode, uint32_t address,
3386 struct arm_instruction *instruction, char *cp)
3388 int ra = (opcode >> 12) & 0xf;
3390 switch (opcode & 0x007000f0) {
3391 case 0:
3392 if (ra == 0xf)
3393 sprintf(cp, "MUL\tr%d, r%d, r%d",
3394 (int) (opcode >> 8) & 0xf,
3395 (int) (opcode >> 16) & 0xf,
3396 (int) (opcode >> 0) & 0xf);
3397 else
3398 sprintf(cp, "MLA\tr%d, r%d, r%d, r%d",
3399 (int) (opcode >> 8) & 0xf,
3400 (int) (opcode >> 16) & 0xf,
3401 (int) (opcode >> 0) & 0xf, ra);
3402 break;
3403 case 0x10:
3404 sprintf(cp, "MLS\tr%d, r%d, r%d, r%d",
3405 (int) (opcode >> 8) & 0xf,
3406 (int) (opcode >> 16) & 0xf,
3407 (int) (opcode >> 0) & 0xf, ra);
3408 break;
3409 default:
3410 return ERROR_INVALID_ARGUMENTS;
3412 return ERROR_OK;
3415 static int t2ev_mul64_div(uint32_t opcode, uint32_t address,
3416 struct arm_instruction *instruction, char *cp)
3418 int op = (opcode >> 4) & 0xf;
3419 char *infix = "MUL";
3421 op += (opcode >> 16) & 0x70;
3422 switch (op) {
3423 case 0x40:
3424 case 0x60:
3425 infix = "MLA";
3426 /* FALLTHROUGH */
3427 case 0:
3428 case 0x20:
3429 sprintf(cp, "%c%sL\tr%d, r%d, r%d, r%d",
3430 (op & 0x20) ? 'U' : 'S',
3431 infix,
3432 (int) (opcode >> 12) & 0xf,
3433 (int) (opcode >> 8) & 0xf,
3434 (int) (opcode >> 16) & 0xf,
3435 (int) (opcode >> 0) & 0xf);
3436 break;
3437 case 0x1f:
3438 case 0x3f:
3439 sprintf(cp, "%cDIV\tr%d, r%d, r%d",
3440 (op & 0x20) ? 'U' : 'S',
3441 (int) (opcode >> 8) & 0xf,
3442 (int) (opcode >> 16) & 0xf,
3443 (int) (opcode >> 0) & 0xf);
3444 break;
3445 default:
3446 return ERROR_INVALID_ARGUMENTS;
3449 return ERROR_OK;
3452 static int t2ev_ldm_stm(uint32_t opcode, uint32_t address,
3453 struct arm_instruction *instruction, char *cp)
3455 int rn = (opcode >> 16) & 0xf;
3456 int op = (opcode >> 22) & 0x6;
3457 int t = (opcode >> 21) & 1;
3458 unsigned registers = opcode & 0xffff;
3459 char *mode = "";
3461 if (opcode & (1 << 20))
3462 op |= 1;
3464 switch (op) {
3465 case 0:
3466 mode = "DB";
3467 /* FALL THROUGH */
3468 case 6:
3469 sprintf(cp, "SRS%s\tsp%s, #%d", mode,
3470 t ? "!" : "",
3471 opcode & 0x1f);
3472 return ERROR_OK;
3473 case 1:
3474 mode = "DB";
3475 /* FALL THROUGH */
3476 case 7:
3477 sprintf(cp, "RFE%s\tr%d%s", mode,
3478 (opcode >> 16) & 0xf,
3479 t ? "!" : "");
3480 return ERROR_OK;
3481 case 2:
3482 sprintf(cp, "STM.W\tr%d%s, ", rn, t ? "!" : "");
3483 break;
3484 case 3:
3485 if (rn == 13 && t)
3486 sprintf(cp, "POP.W\t");
3487 else
3488 sprintf(cp, "LDM.W\tr%d%s, ", rn, t ? "!" : "");
3489 break;
3490 case 4:
3491 if (rn == 13 && t)
3492 sprintf(cp, "PUSH.W\t");
3493 else
3494 sprintf(cp, "STMDB\tr%d%s, ", rn, t ? "!" : "");
3495 break;
3496 case 5:
3497 sprintf(cp, "LDMDB.W\tr%d%s, ", rn, t ? "!" : "");
3498 break;
3499 default:
3500 return ERROR_INVALID_ARGUMENTS;
3503 cp = strchr(cp, 0);
3504 *cp++ = '{';
3505 for (t = 0; registers; t++, registers >>= 1) {
3506 if ((registers & 1) == 0)
3507 continue;
3508 registers &= ~1;
3509 sprintf(cp, "r%d%s", t, registers ? ", " : "");
3510 cp = strchr(cp, 0);
3512 *cp++ = '}';
3513 *cp++ = 0;
3515 return ERROR_OK;
3518 /* load/store dual or exclusive, table branch */
3519 static int t2ev_ldrex_strex(uint32_t opcode, uint32_t address,
3520 struct arm_instruction *instruction, char *cp)
3522 unsigned op1op2 = (opcode >> 20) & 0x3;
3523 unsigned op3 = (opcode >> 4) & 0xf;
3524 char *mnemonic;
3525 unsigned rn = (opcode >> 16) & 0xf;
3526 unsigned rt = (opcode >> 12) & 0xf;
3527 unsigned rd = (opcode >> 8) & 0xf;
3528 unsigned imm = opcode & 0xff;
3529 char *p1 = "";
3530 char *p2 = "]";
3532 op1op2 |= (opcode >> 21) & 0xc;
3533 switch (op1op2) {
3534 case 0:
3535 mnemonic = "STREX";
3536 goto strex;
3537 case 1:
3538 mnemonic = "LDREX";
3539 goto ldrex;
3540 case 2:
3541 case 6:
3542 case 8:
3543 case 10:
3544 case 12:
3545 case 14:
3546 mnemonic = "STRD";
3547 goto immediate;
3548 case 3:
3549 case 7:
3550 case 9:
3551 case 11:
3552 case 13:
3553 case 15:
3554 mnemonic = "LDRD";
3555 if (rn == 15)
3556 goto literal;
3557 else
3558 goto immediate;
3559 case 4:
3560 switch (op3) {
3561 case 4:
3562 mnemonic = "STREXB";
3563 break;
3564 case 5:
3565 mnemonic = "STREXH";
3566 break;
3567 default:
3568 return ERROR_INVALID_ARGUMENTS;
3570 rd = opcode & 0xf;
3571 imm = 0;
3572 goto strex;
3573 case 5:
3574 switch (op3) {
3575 case 0:
3576 sprintf(cp, "TBB\t[r%u, r%u]", rn, imm & 0xf);
3577 return ERROR_OK;
3578 case 1:
3579 sprintf(cp, "TBH\t[r%u, r%u, LSL #1]", rn, imm & 0xf);
3580 return ERROR_OK;
3581 case 4:
3582 mnemonic = "LDREXB";
3583 break;
3584 case 5:
3585 mnemonic = "LDREXH";
3586 break;
3587 default:
3588 return ERROR_INVALID_ARGUMENTS;
3590 imm = 0;
3591 goto ldrex;
3593 return ERROR_INVALID_ARGUMENTS;
3595 strex:
3596 imm <<= 2;
3597 if (imm)
3598 sprintf(cp, "%s\tr%u, r%u, [r%u, #%u]\t; %#2.2x",
3599 mnemonic, rd, rt, rn, imm, imm);
3600 else
3601 sprintf(cp, "%s\tr%u, r%u, [r%u]",
3602 mnemonic, rd, rt, rn);
3603 return ERROR_OK;
3605 ldrex:
3606 imm <<= 2;
3607 if (imm)
3608 sprintf(cp, "%s\tr%u, [r%u, #%u]\t; %#2.2x",
3609 mnemonic, rt, rn, imm, imm);
3610 else
3611 sprintf(cp, "%s\tr%u, [r%u]",
3612 mnemonic, rt, rn);
3613 return ERROR_OK;
3615 immediate:
3616 /* two indexed modes will write back rn */
3617 if (opcode & (1 << 21)) {
3618 if (opcode & (1 << 24)) /* pre-indexed */
3619 p2 = "]!";
3620 else { /* post-indexed */
3621 p1 = "]";
3622 p2 = "";
3626 imm <<= 2;
3627 sprintf(cp, "%s\tr%u, r%u, [r%u%s, #%s%u%s\t; %#2.2x",
3628 mnemonic, rt, rd, rn, p1,
3629 (opcode & (1 << 23)) ? "" : "-",
3630 imm, p2, imm);
3631 return ERROR_OK;
3633 literal:
3634 address = thumb_alignpc4(address);
3635 imm <<= 2;
3636 if (opcode & (1 << 23))
3637 address += imm;
3638 else
3639 address -= imm;
3640 sprintf(cp, "%s\tr%u, r%u, %#8.8" PRIx32,
3641 mnemonic, rt, rd, address);
3642 return ERROR_OK;
3645 static int t2ev_data_shift(uint32_t opcode, uint32_t address,
3646 struct arm_instruction *instruction, char *cp)
3648 int op = (opcode >> 21) & 0xf;
3649 int rd = (opcode >> 8) & 0xf;
3650 int rn = (opcode >> 16) & 0xf;
3651 int type = (opcode >> 4) & 0x3;
3652 int immed = (opcode >> 6) & 0x3;
3653 char *mnemonic;
3654 char *suffix = "";
3656 immed |= (opcode >> 10) & 0x1c;
3657 if (opcode & (1 << 20))
3658 suffix = "S";
3660 switch (op) {
3661 case 0:
3662 if (rd == 0xf) {
3663 if (!(opcode & (1 << 20)))
3664 return ERROR_INVALID_ARGUMENTS;
3665 instruction->type = ARM_TST;
3666 mnemonic = "TST";
3667 suffix = "";
3668 goto two;
3670 instruction->type = ARM_AND;
3671 mnemonic = "AND";
3672 break;
3673 case 1:
3674 instruction->type = ARM_BIC;
3675 mnemonic = "BIC";
3676 break;
3677 case 2:
3678 if (rn == 0xf) {
3679 instruction->type = ARM_MOV;
3680 switch (type) {
3681 case 0:
3682 if (immed == 0) {
3683 sprintf(cp, "MOV%s.W\tr%d, r%d",
3684 suffix, rd,
3685 (int) (opcode & 0xf));
3686 return ERROR_OK;
3688 mnemonic = "LSL";
3689 break;
3690 case 1:
3691 mnemonic = "LSR";
3692 break;
3693 case 2:
3694 mnemonic = "ASR";
3695 break;
3696 default:
3697 if (immed == 0) {
3698 sprintf(cp, "RRX%s\tr%d, r%d",
3699 suffix, rd,
3700 (int) (opcode & 0xf));
3701 return ERROR_OK;
3703 mnemonic = "ROR";
3704 break;
3706 goto immediate;
3707 } else {
3708 instruction->type = ARM_ORR;
3709 mnemonic = "ORR";
3711 break;
3712 case 3:
3713 if (rn == 0xf) {
3714 instruction->type = ARM_MVN;
3715 mnemonic = "MVN";
3716 rn = rd;
3717 goto two;
3718 } else {
3719 // instruction->type = ARM_ORN;
3720 mnemonic = "ORN";
3722 break;
3723 case 4:
3724 if (rd == 0xf) {
3725 if (!(opcode & (1 << 20)))
3726 return ERROR_INVALID_ARGUMENTS;
3727 instruction->type = ARM_TEQ;
3728 mnemonic = "TEQ";
3729 suffix = "";
3730 goto two;
3732 instruction->type = ARM_EOR;
3733 mnemonic = "EOR";
3734 break;
3735 case 8:
3736 if (rd == 0xf) {
3737 if (!(opcode & (1 << 20)))
3738 return ERROR_INVALID_ARGUMENTS;
3739 instruction->type = ARM_CMN;
3740 mnemonic = "CMN";
3741 suffix = "";
3742 goto two;
3744 instruction->type = ARM_ADD;
3745 mnemonic = "ADD";
3746 break;
3747 case 0xa:
3748 instruction->type = ARM_ADC;
3749 mnemonic = "ADC";
3750 break;
3751 case 0xb:
3752 instruction->type = ARM_SBC;
3753 mnemonic = "SBC";
3754 break;
3755 case 0xd:
3756 if (rd == 0xf) {
3757 if (!(opcode & (1 << 21)))
3758 return ERROR_INVALID_ARGUMENTS;
3759 instruction->type = ARM_CMP;
3760 mnemonic = "CMP";
3761 suffix = "";
3762 goto two;
3764 instruction->type = ARM_SUB;
3765 mnemonic = "SUB";
3766 break;
3767 case 0xe:
3768 instruction->type = ARM_RSB;
3769 mnemonic = "RSB";
3770 break;
3771 default:
3772 return ERROR_INVALID_ARGUMENTS;
3775 sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
3776 mnemonic, suffix, rd, rn, (int) (opcode & 0xf));
3778 shift:
3779 cp = strchr(cp, 0);
3781 switch (type) {
3782 case 0:
3783 if (immed == 0)
3784 return ERROR_OK;
3785 suffix = "LSL";
3786 break;
3787 case 1:
3788 suffix = "LSR";
3789 if (immed == 32)
3790 immed = 0;
3791 break;
3792 case 2:
3793 suffix = "ASR";
3794 if (immed == 32)
3795 immed = 0;
3796 break;
3797 case 3:
3798 if (immed == 0) {
3799 strcpy(cp, ", RRX");
3800 return ERROR_OK;
3802 suffix = "ROR";
3803 break;
3805 sprintf(cp, ", %s #%d", suffix, immed ? immed : 32);
3806 return ERROR_OK;
3808 two:
3809 sprintf(cp, "%s%s.W\tr%d, r%d",
3810 mnemonic, suffix, rn, (int) (opcode & 0xf));
3811 goto shift;
3813 immediate:
3814 sprintf(cp, "%s%s.W\tr%d, r%d, #%d",
3815 mnemonic, suffix, rd,
3816 (int) (opcode & 0xf), immed ? immed : 32);
3817 return ERROR_OK;
3820 static int t2ev_data_reg(uint32_t opcode, uint32_t address,
3821 struct arm_instruction *instruction, char *cp)
3823 char *mnemonic;
3824 char * suffix = "";
3826 if (((opcode >> 4) & 0xf) == 0) {
3827 switch ((opcode >> 21) & 0x7) {
3828 case 0:
3829 mnemonic = "LSL";
3830 break;
3831 case 1:
3832 mnemonic = "LSR";
3833 break;
3834 case 2:
3835 mnemonic = "ASR";
3836 break;
3837 case 3:
3838 mnemonic = "ROR";
3839 break;
3840 default:
3841 return ERROR_INVALID_ARGUMENTS;
3844 instruction->type = ARM_MOV;
3845 if (opcode & (1 << 20))
3846 suffix = "S";
3847 sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
3848 mnemonic, suffix,
3849 (int) (opcode >> 8) & 0xf,
3850 (int) (opcode >> 16) & 0xf,
3851 (int) (opcode >> 0) & 0xf);
3853 } else if (opcode & (1 << 7)) {
3854 switch ((opcode >> 20) & 0xf) {
3855 case 0:
3856 case 1:
3857 case 4:
3858 case 5:
3859 switch ((opcode >> 4) & 0x3) {
3860 case 1:
3861 suffix = ", ROR #8";
3862 break;
3863 case 2:
3864 suffix = ", ROR #16";
3865 break;
3866 case 3:
3867 suffix = ", ROR #24";
3868 break;
3870 sprintf(cp, "%cXT%c.W\tr%d, r%d%s",
3871 (opcode & (1 << 24)) ? 'U' : 'S',
3872 (opcode & (1 << 26)) ? 'B' : 'H',
3873 (int) (opcode >> 8) & 0xf,
3874 (int) (opcode >> 0) & 0xf,
3875 suffix);
3876 break;
3877 case 8:
3878 case 9:
3879 case 0xa:
3880 case 0xb:
3881 if (opcode & (1 << 6))
3882 return ERROR_INVALID_ARGUMENTS;
3883 if (((opcode >> 12) & 0xf) != 0xf)
3884 return ERROR_INVALID_ARGUMENTS;
3885 if (!(opcode & (1 << 20)))
3886 return ERROR_INVALID_ARGUMENTS;
3888 switch (((opcode >> 19) & 0x04)
3889 | ((opcode >> 4) & 0x3)) {
3890 case 0:
3891 mnemonic = "REV.W";
3892 break;
3893 case 1:
3894 mnemonic = "REV16.W";
3895 break;
3896 case 2:
3897 mnemonic = "RBIT";
3898 break;
3899 case 3:
3900 mnemonic = "REVSH.W";
3901 break;
3902 case 4:
3903 mnemonic = "CLZ";
3904 break;
3905 default:
3906 return ERROR_INVALID_ARGUMENTS;
3908 sprintf(cp, "%s\tr%d, r%d",
3909 mnemonic,
3910 (int) (opcode >> 8) & 0xf,
3911 (int) (opcode >> 0) & 0xf);
3912 break;
3913 default:
3914 return ERROR_INVALID_ARGUMENTS;
3918 return ERROR_OK;
3921 static int t2ev_load_word(uint32_t opcode, uint32_t address,
3922 struct arm_instruction *instruction, char *cp)
3924 int rn = (opcode >> 16) & 0xf;
3925 int immed;
3927 instruction->type = ARM_LDR;
3929 if (rn == 0xf) {
3930 immed = opcode & 0x0fff;
3931 if ((opcode & (1 << 23)) == 0)
3932 immed = -immed;
3933 sprintf(cp, "LDR\tr%d, %#8.8" PRIx32,
3934 (int) (opcode >> 12) & 0xf,
3935 thumb_alignpc4(address) + immed);
3936 return ERROR_OK;
3939 if (opcode & (1 << 23)) {
3940 immed = opcode & 0x0fff;
3941 sprintf(cp, "LDR.W\tr%d, [r%d, #%d]\t; %#3.3x",
3942 (int) (opcode >> 12) & 0xf,
3943 rn, immed, immed);
3944 return ERROR_OK;
3947 if (!(opcode & (0x3f << 6))) {
3948 sprintf(cp, "LDR.W\tr%d, [r%d, r%d, LSL #%d]",
3949 (int) (opcode >> 12) & 0xf,
3951 (int) (opcode >> 0) & 0xf,
3952 (int) (opcode >> 4) & 0x3);
3953 return ERROR_OK;
3957 if (((opcode >> 8) & 0xf) == 0xe) {
3958 immed = opcode & 0x00ff;
3960 sprintf(cp, "LDRT\tr%d, [r%d, #%d]\t; %#2.2x",
3961 (int) (opcode >> 12) & 0xf,
3962 rn, immed, immed);
3963 return ERROR_OK;
3966 if (((opcode >> 8) & 0xf) == 0xc || (opcode & 0x0900) == 0x0900) {
3967 char *p1 = "]", *p2 = "";
3969 if (!(opcode & 0x0500))
3970 return ERROR_INVALID_ARGUMENTS;
3972 immed = opcode & 0x00ff;
3974 /* two indexed modes will write back rn */
3975 if (opcode & 0x100) {
3976 if (opcode & 0x400) /* pre-indexed */
3977 p2 = "]!";
3978 else { /* post-indexed */
3979 p1 = "]";
3980 p2 = "";
3984 sprintf(cp, "LDR\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
3985 (int) (opcode >> 12) & 0xf,
3986 rn, p1,
3987 (opcode & 0x200) ? "" : "-",
3988 immed, p2, immed);
3989 return ERROR_OK;
3992 return ERROR_INVALID_ARGUMENTS;
3995 static int t2ev_load_byte_hints(uint32_t opcode, uint32_t address,
3996 struct arm_instruction *instruction, char *cp)
3998 int rn = (opcode >> 16) & 0xf;
3999 int rt = (opcode >> 12) & 0xf;
4000 int op2 = (opcode >> 6) & 0x3f;
4001 unsigned immed;
4002 char *p1 = "", *p2 = "]";
4003 char *mnemonic;
4005 switch ((opcode >> 23) & 0x3) {
4006 case 0:
4007 if ((rn & rt) == 0xf) {
4008 pld_literal:
4009 immed = opcode & 0xfff;
4010 address = thumb_alignpc4(address);
4011 if (opcode & (1 << 23))
4012 address += immed;
4013 else
4014 address -= immed;
4015 sprintf(cp, "PLD\tr%d, %#8.8" PRIx32,
4016 rt, address);
4017 return ERROR_OK;
4019 if (rn == 0x0f && rt != 0x0f) {
4020 ldrb_literal:
4021 immed = opcode & 0xfff;
4022 address = thumb_alignpc4(address);
4023 if (opcode & (1 << 23))
4024 address += immed;
4025 else
4026 address -= immed;
4027 sprintf(cp, "LDRB\tr%d, %#8.8" PRIx32,
4028 rt, address);
4029 return ERROR_OK;
4031 if (rn == 0x0f)
4032 break;
4033 if ((op2 & 0x3c) == 0x38) {
4034 immed = opcode & 0xff;
4035 sprintf(cp, "LDRBT\tr%d, [r%d, #%d]\t; %#2.2x",
4036 rt, rn, immed, immed);
4037 return ERROR_OK;
4039 if ((op2 & 0x3c) == 0x30) {
4040 if (rt == 0x0f) {
4041 immed = opcode & 0xff;
4042 immed = -immed;
4043 preload_immediate:
4044 p1 = (opcode & (1 << 21)) ? "W" : "";
4045 sprintf(cp, "PLD%s\t[r%d, #%d]\t; %#6.6x",
4046 p1, rn, immed, immed);
4047 return ERROR_OK;
4049 mnemonic = "LDRB";
4050 ldrxb_immediate_t3:
4051 immed = opcode & 0xff;
4052 if (!(opcode & 0x200))
4053 immed = -immed;
4055 /* two indexed modes will write back rn */
4056 if (opcode & 0x100) {
4057 if (opcode & 0x400) /* pre-indexed */
4058 p2 = "]!";
4059 else { /* post-indexed */
4060 p1 = "]";
4061 p2 = "";
4064 ldrxb_immediate_t2:
4065 sprintf(cp, "%s\tr%d, [r%d%s, #%d%s\t; %#8.8x",
4066 mnemonic, rt, rn, p1,
4067 immed, p2, immed);
4068 return ERROR_OK;
4070 if ((op2 & 0x24) == 0x24) {
4071 mnemonic = "LDRB";
4072 goto ldrxb_immediate_t3;
4074 if (op2 == 0) {
4075 int rm = opcode & 0xf;
4077 if (rt == 0x0f)
4078 sprintf(cp, "PLD\t");
4079 else
4080 sprintf(cp, "LDRB.W\tr%d, ", rt);
4081 immed = (opcode >> 4) & 0x3;
4082 cp = strchr(cp, 0);
4083 sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed);
4084 return ERROR_OK;
4086 break;
4087 case 1:
4088 if ((rn & rt) == 0xf)
4089 goto pld_literal;
4090 if (rt == 0xf) {
4091 immed = opcode & 0xfff;
4092 goto preload_immediate;
4094 if (rn == 0x0f)
4095 goto ldrb_literal;
4096 mnemonic = "LDRB.W";
4097 immed = opcode & 0xfff;
4098 goto ldrxb_immediate_t2;
4099 case 2:
4100 if ((rn & rt) == 0xf) {
4101 immed = opcode & 0xfff;
4102 address = thumb_alignpc4(address);
4103 if (opcode & (1 << 23))
4104 address += immed;
4105 else
4106 address -= immed;
4107 sprintf(cp, "PLI\t%#8.8" PRIx32, address);
4108 return ERROR_OK;
4110 if (rn == 0xf && rt != 0xf) {
4111 ldrsb_literal:
4112 immed = opcode & 0xfff;
4113 address = thumb_alignpc4(address);
4114 if (opcode & (1 << 23))
4115 address += immed;
4116 else
4117 address -= immed;
4118 sprintf(cp, "LDRSB\t%#8.8" PRIx32, address);
4119 return ERROR_OK;
4121 if (rn == 0xf)
4122 break;
4123 if ((op2 & 0x3c) == 0x38) {
4124 immed = opcode & 0xff;
4125 sprintf(cp, "LDRSBT\tr%d, [r%d, #%d]\t; %#2.2x",
4126 rt, rn, immed, immed);
4127 return ERROR_OK;
4129 if ((op2 & 0x3c) == 0x30) {
4130 if (rt == 0xf) {
4131 immed = opcode & 0xff;
4132 immed = -immed; // pli
4133 sprintf(cp, "PLI\t[r%d, #%d]\t; -%#2.2x",
4134 rn, immed, -immed);
4135 return ERROR_OK;
4137 mnemonic = "LDRSB";
4138 goto ldrxb_immediate_t3;
4140 if ((op2 & 0x24) == 0x24) {
4141 mnemonic = "LDRSB";
4142 goto ldrxb_immediate_t3;
4144 if (op2 == 0) {
4145 int rm = opcode & 0xf;
4147 if (rt == 0x0f)
4148 sprintf(cp, "PLI\t");
4149 else
4150 sprintf(cp, "LDRSB.W\tr%d, ", rt);
4151 immed = (opcode >> 4) & 0x3;
4152 cp = strchr(cp, 0);
4153 sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed);
4154 return ERROR_OK;
4156 break;
4157 case 3:
4158 if (rt == 0xf) {
4159 immed = opcode & 0xfff;
4160 sprintf(cp, "PLI\t[r%d, #%d]\t; %#3.3x",
4161 rn, immed, immed);
4162 return ERROR_OK;
4164 if (rn == 0xf)
4165 goto ldrsb_literal;
4166 immed = opcode & 0xfff;
4167 mnemonic = "LDRSB";
4168 goto ldrxb_immediate_t2;
4171 return ERROR_INVALID_ARGUMENTS;
4174 static int t2ev_load_halfword(uint32_t opcode, uint32_t address,
4175 struct arm_instruction *instruction, char *cp)
4177 int rn = (opcode >> 16) & 0xf;
4178 int rt = (opcode >> 12) & 0xf;
4179 int op2 = (opcode >> 6) & 0x3f;
4180 char *sign = "";
4181 unsigned immed;
4183 if (rt == 0xf) {
4184 sprintf(cp, "HINT (UNALLOCATED)");
4185 return ERROR_OK;
4188 if (opcode & (1 << 24))
4189 sign = "S";
4191 if ((opcode & (1 << 23)) == 0) {
4192 if (rn == 0xf) {
4193 ldrh_literal:
4194 immed = opcode & 0xfff;
4195 address = thumb_alignpc4(address);
4196 if (opcode & (1 << 23))
4197 address += immed;
4198 else
4199 address -= immed;
4200 sprintf(cp, "LDR%sH\tr%d, %#8.8" PRIx32,
4201 sign, rt, address);
4202 return ERROR_OK;
4204 if (op2 == 0) {
4205 int rm = opcode & 0xf;
4207 immed = (opcode >> 4) & 0x3;
4208 sprintf(cp, "LDR%sH.W\tr%d, [r%d, r%d, LSL #%d]",
4209 sign, rt, rn, rm, immed);
4210 return ERROR_OK;
4212 if ((op2 & 0x3c) == 0x38) {
4213 immed = opcode & 0xff;
4214 sprintf(cp, "LDR%sHT\tr%d, [r%d, #%d]\t; %#2.2x",
4215 sign, rt, rn, immed, immed);
4216 return ERROR_OK;
4218 if ((op2 & 0x3c) == 0x30 || (op2 & 0x24) == 0x24) {
4219 char *p1 = "", *p2 = "]";
4221 immed = opcode & 0xff;
4222 if (!(opcode & 0x200))
4223 immed = -immed;
4225 /* two indexed modes will write back rn */
4226 if (opcode & 0x100) {
4227 if (opcode & 0x400) /* pre-indexed */
4228 p2 = "]!";
4229 else { /* post-indexed */
4230 p1 = "]";
4231 p2 = "";
4234 sprintf(cp, "LDR%sH\tr%d, [r%d%s, #%d%s\t; %#8.8x",
4235 sign, rt, rn, p1, immed, p2, immed);
4236 return ERROR_OK;
4238 } else {
4239 if (rn == 0xf)
4240 goto ldrh_literal;
4242 immed = opcode & 0xfff;
4243 sprintf(cp, "LDR%sH%s\tr%d, [r%d, #%d]\t; %#6.6x",
4244 sign, *sign ? "" : ".W",
4245 rt, rn, immed, immed);
4246 return ERROR_OK;
4249 return ERROR_INVALID_ARGUMENTS;
4253 * REVISIT for Thumb2 instructions, instruction->type and friends aren't
4254 * always set. That means eventual arm_simulate_step() support for Thumb2
4255 * will need work in this area.
4257 int thumb2_opcode(struct target *target, uint32_t address, struct arm_instruction *instruction)
4259 int retval;
4260 uint16_t op;
4261 uint32_t opcode;
4262 char *cp;
4264 /* clear low bit ... it's set on function pointers */
4265 address &= ~1;
4267 /* clear fields, to avoid confusion */
4268 memset(instruction, 0, sizeof(struct arm_instruction));
4270 /* read first halfword, see if this is the only one */
4271 retval = target_read_u16(target, address, &op);
4272 if (retval != ERROR_OK)
4273 return retval;
4275 switch (op & 0xf800) {
4276 case 0xf800:
4277 case 0xf000:
4278 case 0xe800:
4279 /* 32-bit instructions */
4280 instruction->instruction_size = 4;
4281 opcode = op << 16;
4282 retval = target_read_u16(target, address + 2, &op);
4283 if (retval != ERROR_OK)
4284 return retval;
4285 opcode |= op;
4286 instruction->opcode = opcode;
4287 break;
4288 default:
4289 /* 16-bit: Thumb1 + IT + CBZ/CBNZ + ... */
4290 return thumb_evaluate_opcode(op, address, instruction);
4293 snprintf(instruction->text, 128,
4294 "0x%8.8" PRIx32 " 0x%8.8" PRIx32 "\t",
4295 address, opcode);
4296 cp = strchr(instruction->text, 0);
4297 retval = ERROR_FAIL;
4299 /* ARMv7-M: A5.3.1 Data processing (modified immediate) */
4300 if ((opcode & 0x1a008000) == 0x10000000)
4301 retval = t2ev_data_mod_immed(opcode, address, instruction, cp);
4303 /* ARMv7-M: A5.3.3 Data processing (plain binary immediate) */
4304 else if ((opcode & 0x1a008000) == 0x12000000)
4305 retval = t2ev_data_immed(opcode, address, instruction, cp);
4307 /* ARMv7-M: A5.3.4 Branches and miscellaneous control */
4308 else if ((opcode & 0x18008000) == 0x10008000)
4309 retval = t2ev_b_misc(opcode, address, instruction, cp);
4311 /* ARMv7-M: A5.3.5 Load/store multiple */
4312 else if ((opcode & 0x1e400000) == 0x08000000)
4313 retval = t2ev_ldm_stm(opcode, address, instruction, cp);
4315 /* ARMv7-M: A5.3.6 Load/store dual or exclusive, table branch */
4316 else if ((opcode & 0x1e400000) == 0x08400000)
4317 retval = t2ev_ldrex_strex(opcode, address, instruction, cp);
4319 /* ARMv7-M: A5.3.7 Load word */
4320 else if ((opcode & 0x1f700000) == 0x18500000)
4321 retval = t2ev_load_word(opcode, address, instruction, cp);
4323 /* ARMv7-M: A5.3.8 Load halfword, unallocated memory hints */
4324 else if ((opcode & 0x1e700000) == 0x18300000)
4325 retval = t2ev_load_halfword(opcode, address, instruction, cp);
4327 /* ARMv7-M: A5.3.9 Load byte, memory hints */
4328 else if ((opcode & 0x1e700000) == 0x18100000)
4329 retval = t2ev_load_byte_hints(opcode, address, instruction, cp);
4331 /* ARMv7-M: A5.3.10 Store single data item */
4332 else if ((opcode & 0x1f100000) == 0x18000000)
4333 retval = t2ev_store_single(opcode, address, instruction, cp);
4335 /* ARMv7-M: A5.3.11 Data processing (shifted register) */
4336 else if ((opcode & 0x1e000000) == 0x0a000000)
4337 retval = t2ev_data_shift(opcode, address, instruction, cp);
4339 /* ARMv7-M: A5.3.12 Data processing (register)
4340 * and A5.3.13 Miscellaneous operations
4342 else if ((opcode & 0x1f000000) == 0x1a000000)
4343 retval = t2ev_data_reg(opcode, address, instruction, cp);
4345 /* ARMv7-M: A5.3.14 Multiply, and multiply accumulate */
4346 else if ((opcode & 0x1f800000) == 0x1b000000)
4347 retval = t2ev_mul32(opcode, address, instruction, cp);
4349 /* ARMv7-M: A5.3.15 Long multiply, long multiply accumulate, divide */
4350 else if ((opcode & 0x1f800000) == 0x1b800000)
4351 retval = t2ev_mul64_div(opcode, address, instruction, cp);
4353 if (retval == ERROR_OK)
4354 return retval;
4357 * Thumb2 also supports coprocessor, ThumbEE, and DSP/Media (SIMD)
4358 * instructions; not yet handled here.
4361 if (retval == ERROR_INVALID_ARGUMENTS) {
4362 instruction->type = ARM_UNDEFINED_INSTRUCTION;
4363 strcpy(cp, "UNDEFINED OPCODE");
4364 return ERROR_OK;
4367 LOG_DEBUG("Can't decode 32-bit Thumb2 yet (opcode=%08" PRIx32 ")",
4368 opcode);
4370 strcpy(cp, "(32-bit Thumb2 ...)");
4371 return ERROR_OK;
4374 int arm_access_size(struct arm_instruction *instruction)
4376 if ((instruction->type == ARM_LDRB)
4377 || (instruction->type == ARM_LDRBT)
4378 || (instruction->type == ARM_LDRSB)
4379 || (instruction->type == ARM_STRB)
4380 || (instruction->type == ARM_STRBT))
4382 return 1;
4384 else if ((instruction->type == ARM_LDRH)
4385 || (instruction->type == ARM_LDRSH)
4386 || (instruction->type == ARM_STRH))
4388 return 2;
4390 else if ((instruction->type == ARM_LDR)
4391 || (instruction->type == ARM_LDRT)
4392 || (instruction->type == ARM_STR)
4393 || (instruction->type == ARM_STRT))
4395 return 4;
4397 else if ((instruction->type == ARM_LDRD)
4398 || (instruction->type == ARM_STRD))
4400 return 8;
4402 else
4404 LOG_ERROR("BUG: instruction type %i isn't a load/store instruction", instruction->type);
4405 return 0;