target: arm: disassembler: decode v6T2 ARM DSB instruction
[openocd.git] / src / target / arm_disassembler.c
1 /***************************************************************************
2 * Copyright (C) 2006 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * Copyright (C) 2009 by David Brownell *
6 * *
7 * This program is free software; you can redistribute it and/or modify *
8 * it under the terms of the GNU General Public License as published by *
9 * the Free Software Foundation; either version 2 of the License, or *
10 * (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License *
18 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
19 ***************************************************************************/
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include "target.h"
26 #include "arm_disassembler.h"
27 #include <helper/log.h>
28
29 /*
30 * This disassembler supports two main functions for OpenOCD:
31 *
32 * - Various "disassemble" commands. OpenOCD can serve as a
33 * machine-language debugger, without help from GDB.
34 *
35 * - Single stepping. Not all ARM cores support hardware single
36 * stepping. To work without that support, the debugger must
37 * be able to decode instructions to find out where to put a
38 * "next instruction" breakpoint.
39 *
40 * In addition, interpretation of ETM trace data needs some of the
41 * decoding mechanisms.
42 *
43 * At this writing (September 2009) neither function is complete.
44 *
45 * - ARM decoding
46 * * Old-style syntax (not UAL) is generally used
47 * * VFP instructions are not understood (ARMv5 and later)
48 * except as coprocessor 10/11 operations
49 * * Most ARM instructions through ARMv6 are decoded, but some
50 * of the post-ARMv4 opcodes may not be handled yet
51 * CPS, SDIV, UDIV, LDREX*, STREX*, QASX, ...
52 * * NEON instructions are not understood (ARMv7-A)
53 *
54 * - Thumb/Thumb2 decoding
55 * * UAL syntax should be consistently used
56 * * Any Thumb2 instructions used in Cortex-M3 (ARMv7-M) should
57 * be handled properly. Accordingly, so should the subset
58 * used in Cortex-M0/M1; and "original" 16-bit Thumb from
59 * ARMv4T and ARMv5T.
60 * * Conditional effects of Thumb2 "IT" (if-then) instructions
61 * are not handled: the affected instructions are not shown
62 * with their now-conditional suffixes.
63 * * Some ARMv6 and ARMv7-M Thumb2 instructions may not be
64 * handled (minimally for coprocessor access).
65 * * SIMD instructions, and some other Thumb2 instructions
66 * from ARMv7-A, are not understood.
67 *
68 * - ThumbEE decoding
69 * * As a Thumb2 variant, the Thumb2 comments (above) apply.
70 * * Opcodes changed by ThumbEE mode are not handled; these
71 * instructions wrongly decode as LDM and STM.
72 *
73 * - Jazelle decoding ... no support whatsoever for Jazelle mode
74 * or decoding. ARM encourages use of the more generic ThumbEE
75 * mode, instead of Jazelle mode, in current chips.
76 *
77 * - Single-step/emulation ... spotty support, which is only weakly
78 * tested. Thumb2 is not supported. (Arguably a full simulator
79 * is not needed to support just single stepping. Recognizing
80 * branch vs non-branch instructions suffices, except when the
81 * instruction faults and triggers a synchronous exception which
82 * can be intercepted using other means.)
83 *
84 * ARM DDI 0406B "ARM Architecture Reference Manual, ARM v7-A and
85 * ARM v7-R edition" gives the most complete coverage of the various
86 * generations of ARM instructions. At this writing it is publicly
87 * accessible to anyone willing to create an account at the ARM
88 * web site; see http://www.arm.com/documentation/ for information.
89 *
90 * ARM DDI 0403C "ARMv7-M Architecture Reference Manual" provides
91 * more details relevant to the Thumb2-only processors (such as
92 * the Cortex-M implementations).
93 */
94
95 /* textual represenation of the condition field
96 * ALways (default) is ommitted (empty string) */
97 static const char *arm_condition_strings[] = {
98 "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", "HI", "LS", "GE", "LT", "GT", "LE", "", "NV"
99 };
100
101 /* make up for C's missing ROR */
102 static uint32_t ror(uint32_t value, int places)
103 {
104 return (value >> places) | (value << (32 - places));
105 }
106
107 static int evaluate_unknown(uint32_t opcode,
108 uint32_t address, struct arm_instruction *instruction)
109 {
110 instruction->type = ARM_UNDEFINED_INSTRUCTION;
111 snprintf(instruction->text, 128,
112 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
113 "\tUNDEFINED INSTRUCTION", address, opcode);
114 return ERROR_OK;
115 }
116
117 static int evaluate_pld(uint32_t opcode,
118 uint32_t address, struct arm_instruction *instruction)
119 {
120 /* PLD */
121 if ((opcode & 0x0d70f000) == 0x0550f000) {
122 instruction->type = ARM_PLD;
123
124 snprintf(instruction->text,
125 128,
126 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD ...TODO...",
127 address,
128 opcode);
129
130 return ERROR_OK;
131 }
132 /* DSB */
133 if ((opcode & 0x07f000f0) == 0x05700040) {
134 instruction->type = ARM_DSB;
135
136 char *opt;
137 switch (opcode & 0x0000000f) {
138 case 0xf:
139 opt = "SY";
140 break;
141 case 0xe:
142 opt = "ST";
143 break;
144 case 0xb:
145 opt = "ISH";
146 break;
147 case 0xa:
148 opt = "ISHST";
149 break;
150 case 0x7:
151 opt = "NSH";
152 break;
153 case 0x6:
154 opt = "NSHST";
155 break;
156 case 0x3:
157 opt = "OSH";
158 break;
159 case 0x2:
160 opt = "OSHST";
161 break;
162 default:
163 opt = "UNK";
164 }
165
166 snprintf(instruction->text,
167 128,
168 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tDSB %s",
169 address, opcode, opt);
170
171 return ERROR_OK;
172 }
173 return evaluate_unknown(opcode, address, instruction);
174 }
175
176 static int evaluate_srs(uint32_t opcode,
177 uint32_t address, struct arm_instruction *instruction)
178 {
179 const char *wback = (opcode & (1 << 21)) ? "!" : "";
180 const char *mode = "";
181
182 switch ((opcode >> 23) & 0x3) {
183 case 0:
184 mode = "DA";
185 break;
186 case 1:
187 /* "IA" is default */
188 break;
189 case 2:
190 mode = "DB";
191 break;
192 case 3:
193 mode = "IB";
194 break;
195 }
196
197 switch (opcode & 0x0e500000) {
198 case 0x08400000:
199 snprintf(instruction->text, 128, "0x%8.8" PRIx32
200 "\t0x%8.8" PRIx32
201 "\tSRS%s\tSP%s, #%d",
202 address, opcode,
203 mode, wback,
204 (unsigned)(opcode & 0x1f));
205 break;
206 case 0x08100000:
207 snprintf(instruction->text, 128, "0x%8.8" PRIx32
208 "\t0x%8.8" PRIx32
209 "\tRFE%s\tr%d%s",
210 address, opcode,
211 mode,
212 (unsigned)((opcode >> 16) & 0xf), wback);
213 break;
214 default:
215 return evaluate_unknown(opcode, address, instruction);
216 }
217 return ERROR_OK;
218 }
219
220 static int evaluate_swi(uint32_t opcode,
221 uint32_t address, struct arm_instruction *instruction)
222 {
223 instruction->type = ARM_SWI;
224
225 snprintf(instruction->text, 128,
226 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSVC %#6.6" PRIx32,
227 address, opcode, (opcode & 0xffffff));
228
229 return ERROR_OK;
230 }
231
232 static int evaluate_blx_imm(uint32_t opcode,
233 uint32_t address, struct arm_instruction *instruction)
234 {
235 int offset;
236 uint32_t immediate;
237 uint32_t target_address;
238
239 instruction->type = ARM_BLX;
240 immediate = opcode & 0x00ffffff;
241
242 /* sign extend 24-bit immediate */
243 if (immediate & 0x00800000)
244 offset = 0xff000000 | immediate;
245 else
246 offset = immediate;
247
248 /* shift two bits left */
249 offset <<= 2;
250
251 /* odd/event halfword */
252 if (opcode & 0x01000000)
253 offset |= 0x2;
254
255 target_address = address + 8 + offset;
256
257 snprintf(instruction->text,
258 128,
259 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX 0x%8.8" PRIx32 "",
260 address,
261 opcode,
262 target_address);
263
264 instruction->info.b_bl_bx_blx.reg_operand = -1;
265 instruction->info.b_bl_bx_blx.target_address = target_address;
266
267 return ERROR_OK;
268 }
269
270 static int evaluate_b_bl(uint32_t opcode,
271 uint32_t address, struct arm_instruction *instruction)
272 {
273 uint8_t L;
274 uint32_t immediate;
275 int offset;
276 uint32_t target_address;
277
278 immediate = opcode & 0x00ffffff;
279 L = (opcode & 0x01000000) >> 24;
280
281 /* sign extend 24-bit immediate */
282 if (immediate & 0x00800000)
283 offset = 0xff000000 | immediate;
284 else
285 offset = immediate;
286
287 /* shift two bits left */
288 offset <<= 2;
289
290 target_address = address + 8 + offset;
291
292 if (L)
293 instruction->type = ARM_BL;
294 else
295 instruction->type = ARM_B;
296
297 snprintf(instruction->text,
298 128,
299 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tB%s%s 0x%8.8" PRIx32,
300 address,
301 opcode,
302 (L) ? "L" : "",
303 COND(opcode),
304 target_address);
305
306 instruction->info.b_bl_bx_blx.reg_operand = -1;
307 instruction->info.b_bl_bx_blx.target_address = target_address;
308
309 return ERROR_OK;
310 }
311
312 /* Coprocessor load/store and double register transfers
313 * both normal and extended instruction space (condition field b1111) */
314 static int evaluate_ldc_stc_mcrr_mrrc(uint32_t opcode,
315 uint32_t address, struct arm_instruction *instruction)
316 {
317 uint8_t cp_num = (opcode & 0xf00) >> 8;
318
319 /* MCRR or MRRC */
320 if (((opcode & 0x0ff00000) == 0x0c400000) || ((opcode & 0x0ff00000) == 0x0c500000)) {
321 uint8_t cp_opcode, Rd, Rn, CRm;
322 char *mnemonic;
323
324 cp_opcode = (opcode & 0xf0) >> 4;
325 Rd = (opcode & 0xf000) >> 12;
326 Rn = (opcode & 0xf0000) >> 16;
327 CRm = (opcode & 0xf);
328
329 /* MCRR */
330 if ((opcode & 0x0ff00000) == 0x0c400000) {
331 instruction->type = ARM_MCRR;
332 mnemonic = "MCRR";
333 } else if ((opcode & 0x0ff00000) == 0x0c500000) {
334 /* MRRC */
335 instruction->type = ARM_MRRC;
336 mnemonic = "MRRC";
337 } else {
338 LOG_ERROR("Unknown instruction");
339 return ERROR_FAIL;
340 }
341
342 snprintf(instruction->text, 128,
343 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
344 "\t%s%s%s p%i, %x, r%i, r%i, c%i",
345 address, opcode, mnemonic,
346 ((opcode & 0xf0000000) == 0xf0000000)
347 ? "2" : COND(opcode),
348 COND(opcode), cp_num, cp_opcode, Rd, Rn, CRm);
349 } else {/* LDC or STC */
350 uint8_t CRd, Rn, offset;
351 uint8_t U;
352 char *mnemonic;
353 char addressing_mode[32];
354
355 CRd = (opcode & 0xf000) >> 12;
356 Rn = (opcode & 0xf0000) >> 16;
357 offset = (opcode & 0xff) << 2;
358
359 /* load/store */
360 if (opcode & 0x00100000) {
361 instruction->type = ARM_LDC;
362 mnemonic = "LDC";
363 } else {
364 instruction->type = ARM_STC;
365 mnemonic = "STC";
366 }
367
368 U = (opcode & 0x00800000) >> 23;
369
370 /* addressing modes */
371 if ((opcode & 0x01200000) == 0x01000000)/* offset */
372 snprintf(addressing_mode, 32, "[r%i, #%s%d]",
373 Rn, U ? "" : "-", offset);
374 else if ((opcode & 0x01200000) == 0x01200000) /* pre-indexed */
375 snprintf(addressing_mode, 32, "[r%i, #%s%d]!",
376 Rn, U ? "" : "-", offset);
377 else if ((opcode & 0x01200000) == 0x00200000) /* post-indexed */
378 snprintf(addressing_mode, 32, "[r%i], #%s%d",
379 Rn, U ? "" : "-", offset);
380 else if ((opcode & 0x01200000) == 0x00000000) /* unindexed */
381 snprintf(addressing_mode, 32, "[r%i], {%d}",
382 Rn, offset >> 2);
383
384 snprintf(instruction->text, 128, "0x%8.8" PRIx32
385 "\t0x%8.8" PRIx32
386 "\t%s%s%s p%i, c%i, %s",
387 address, opcode, mnemonic,
388 ((opcode & 0xf0000000) == 0xf0000000)
389 ? "2" : COND(opcode),
390 (opcode & (1 << 22)) ? "L" : "",
391 cp_num, CRd, addressing_mode);
392 }
393
394 return ERROR_OK;
395 }
396
397 /* Coprocessor data processing instructions
398 * Coprocessor register transfer instructions
399 * both normal and extended instruction space (condition field b1111) */
400 static int evaluate_cdp_mcr_mrc(uint32_t opcode,
401 uint32_t address, struct arm_instruction *instruction)
402 {
403 const char *cond;
404 char *mnemonic;
405 uint8_t cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2;
406
407 cond = ((opcode & 0xf0000000) == 0xf0000000) ? "2" : COND(opcode);
408 cp_num = (opcode & 0xf00) >> 8;
409 CRd_Rd = (opcode & 0xf000) >> 12;
410 CRn = (opcode & 0xf0000) >> 16;
411 CRm = (opcode & 0xf);
412 opcode_2 = (opcode & 0xe0) >> 5;
413
414 /* CDP or MRC/MCR */
415 if (opcode & 0x00000010) { /* bit 4 set -> MRC/MCR */
416 if (opcode & 0x00100000) { /* bit 20 set -> MRC */
417 instruction->type = ARM_MRC;
418 mnemonic = "MRC";
419 } else {/* bit 20 not set -> MCR */
420 instruction->type = ARM_MCR;
421 mnemonic = "MCR";
422 }
423
424 opcode_1 = (opcode & 0x00e00000) >> 21;
425
426 snprintf(instruction->text,
427 128,
428 "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",
429 address,
430 opcode,
431 mnemonic,
432 cond,
433 cp_num,
434 opcode_1,
435 CRd_Rd,
436 CRn,
437 CRm,
438 opcode_2);
439 } else {/* bit 4 not set -> CDP */
440 instruction->type = ARM_CDP;
441 mnemonic = "CDP";
442
443 opcode_1 = (opcode & 0x00f00000) >> 20;
444
445 snprintf(instruction->text,
446 128,
447 "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",
448 address,
449 opcode,
450 mnemonic,
451 cond,
452 cp_num,
453 opcode_1,
454 CRd_Rd,
455 CRn,
456 CRm,
457 opcode_2);
458 }
459
460 return ERROR_OK;
461 }
462
463 /* Load/store instructions */
464 static int evaluate_load_store(uint32_t opcode,
465 uint32_t address, struct arm_instruction *instruction)
466 {
467 uint8_t I, P, U, B, W, L;
468 uint8_t Rn, Rd;
469 char *operation;/* "LDR" or "STR" */
470 char *suffix; /* "", "B", "T", "BT" */
471 char offset[32];
472
473 /* examine flags */
474 I = (opcode & 0x02000000) >> 25;
475 P = (opcode & 0x01000000) >> 24;
476 U = (opcode & 0x00800000) >> 23;
477 B = (opcode & 0x00400000) >> 22;
478 W = (opcode & 0x00200000) >> 21;
479 L = (opcode & 0x00100000) >> 20;
480
481 /* target register */
482 Rd = (opcode & 0xf000) >> 12;
483
484 /* base register */
485 Rn = (opcode & 0xf0000) >> 16;
486
487 instruction->info.load_store.Rd = Rd;
488 instruction->info.load_store.Rn = Rn;
489 instruction->info.load_store.U = U;
490
491 /* determine operation */
492 if (L)
493 operation = "LDR";
494 else
495 operation = "STR";
496
497 /* determine instruction type and suffix */
498 if (B) {
499 if ((P == 0) && (W == 1)) {
500 if (L)
501 instruction->type = ARM_LDRBT;
502 else
503 instruction->type = ARM_STRBT;
504 suffix = "BT";
505 } else {
506 if (L)
507 instruction->type = ARM_LDRB;
508 else
509 instruction->type = ARM_STRB;
510 suffix = "B";
511 }
512 } else {
513 if ((P == 0) && (W == 1)) {
514 if (L)
515 instruction->type = ARM_LDRT;
516 else
517 instruction->type = ARM_STRT;
518 suffix = "T";
519 } else {
520 if (L)
521 instruction->type = ARM_LDR;
522 else
523 instruction->type = ARM_STR;
524 suffix = "";
525 }
526 }
527
528 if (!I) { /* #+-<offset_12> */
529 uint32_t offset_12 = (opcode & 0xfff);
530 if (offset_12)
531 snprintf(offset, 32, ", #%s0x%" PRIx32 "", (U) ? "" : "-", offset_12);
532 else
533 snprintf(offset, 32, "%s", "");
534
535 instruction->info.load_store.offset_mode = 0;
536 instruction->info.load_store.offset.offset = offset_12;
537 } else {/* either +-<Rm> or +-<Rm>, <shift>, #<shift_imm> */
538 uint8_t shift_imm, shift;
539 uint8_t Rm;
540
541 shift_imm = (opcode & 0xf80) >> 7;
542 shift = (opcode & 0x60) >> 5;
543 Rm = (opcode & 0xf);
544
545 /* LSR encodes a shift by 32 bit as 0x0 */
546 if ((shift == 0x1) && (shift_imm == 0x0))
547 shift_imm = 0x20;
548
549 /* ASR encodes a shift by 32 bit as 0x0 */
550 if ((shift == 0x2) && (shift_imm == 0x0))
551 shift_imm = 0x20;
552
553 /* ROR by 32 bit is actually a RRX */
554 if ((shift == 0x3) && (shift_imm == 0x0))
555 shift = 0x4;
556
557 instruction->info.load_store.offset_mode = 1;
558 instruction->info.load_store.offset.reg.Rm = Rm;
559 instruction->info.load_store.offset.reg.shift = shift;
560 instruction->info.load_store.offset.reg.shift_imm = shift_imm;
561
562 if ((shift_imm == 0x0) && (shift == 0x0)) /* +-<Rm> */
563 snprintf(offset, 32, ", %sr%i", (U) ? "" : "-", Rm);
564 else { /* +-<Rm>, <Shift>, #<shift_imm> */
565 switch (shift) {
566 case 0x0: /* LSL */
567 snprintf(offset, 32, ", %sr%i, LSL #0x%x", (U) ? "" : "-", Rm, shift_imm);
568 break;
569 case 0x1: /* LSR */
570 snprintf(offset, 32, ", %sr%i, LSR #0x%x", (U) ? "" : "-", Rm, shift_imm);
571 break;
572 case 0x2: /* ASR */
573 snprintf(offset, 32, ", %sr%i, ASR #0x%x", (U) ? "" : "-", Rm, shift_imm);
574 break;
575 case 0x3: /* ROR */
576 snprintf(offset, 32, ", %sr%i, ROR #0x%x", (U) ? "" : "-", Rm, shift_imm);
577 break;
578 case 0x4: /* RRX */
579 snprintf(offset, 32, ", %sr%i, RRX", (U) ? "" : "-", Rm);
580 break;
581 }
582 }
583 }
584
585 if (P == 1) {
586 if (W == 0) { /* offset */
587 snprintf(instruction->text,
588 128,
589 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]",
590 address,
591 opcode,
592 operation,
593 COND(opcode),
594 suffix,
595 Rd,
596 Rn,
597 offset);
598
599 instruction->info.load_store.index_mode = 0;
600 } else {/* pre-indexed */
601 snprintf(instruction->text,
602 128,
603 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]!",
604 address,
605 opcode,
606 operation,
607 COND(opcode),
608 suffix,
609 Rd,
610 Rn,
611 offset);
612
613 instruction->info.load_store.index_mode = 1;
614 }
615 } else {/* post-indexed */
616 snprintf(instruction->text,
617 128,
618 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i]%s",
619 address,
620 opcode,
621 operation,
622 COND(opcode),
623 suffix,
624 Rd,
625 Rn,
626 offset);
627
628 instruction->info.load_store.index_mode = 2;
629 }
630
631 return ERROR_OK;
632 }
633
634 static int evaluate_extend(uint32_t opcode, uint32_t address, char *cp)
635 {
636 unsigned rm = (opcode >> 0) & 0xf;
637 unsigned rd = (opcode >> 12) & 0xf;
638 unsigned rn = (opcode >> 16) & 0xf;
639 char *type, *rot;
640
641 switch ((opcode >> 24) & 0x3) {
642 case 0:
643 type = "B16";
644 break;
645 case 1:
646 sprintf(cp, "UNDEFINED");
647 return ARM_UNDEFINED_INSTRUCTION;
648 case 2:
649 type = "B";
650 break;
651 default:
652 type = "H";
653 break;
654 }
655
656 switch ((opcode >> 10) & 0x3) {
657 case 0:
658 rot = "";
659 break;
660 case 1:
661 rot = ", ROR #8";
662 break;
663 case 2:
664 rot = ", ROR #16";
665 break;
666 default:
667 rot = ", ROR #24";
668 break;
669 }
670
671 if (rn == 0xf) {
672 sprintf(cp, "%cXT%s%s\tr%d, r%d%s",
673 (opcode & (1 << 22)) ? 'U' : 'S',
674 type, COND(opcode),
675 rd, rm, rot);
676 return ARM_MOV;
677 } else {
678 sprintf(cp, "%cXTA%s%s\tr%d, r%d, r%d%s",
679 (opcode & (1 << 22)) ? 'U' : 'S',
680 type, COND(opcode),
681 rd, rn, rm, rot);
682 return ARM_ADD;
683 }
684 }
685
686 static int evaluate_p_add_sub(uint32_t opcode, uint32_t address, char *cp)
687 {
688 char *prefix;
689 char *op;
690 int type;
691
692 switch ((opcode >> 20) & 0x7) {
693 case 1:
694 prefix = "S";
695 break;
696 case 2:
697 prefix = "Q";
698 break;
699 case 3:
700 prefix = "SH";
701 break;
702 case 5:
703 prefix = "U";
704 break;
705 case 6:
706 prefix = "UQ";
707 break;
708 case 7:
709 prefix = "UH";
710 break;
711 default:
712 goto undef;
713 }
714
715 switch ((opcode >> 5) & 0x7) {
716 case 0:
717 op = "ADD16";
718 type = ARM_ADD;
719 break;
720 case 1:
721 op = "ADDSUBX";
722 type = ARM_ADD;
723 break;
724 case 2:
725 op = "SUBADDX";
726 type = ARM_SUB;
727 break;
728 case 3:
729 op = "SUB16";
730 type = ARM_SUB;
731 break;
732 case 4:
733 op = "ADD8";
734 type = ARM_ADD;
735 break;
736 case 7:
737 op = "SUB8";
738 type = ARM_SUB;
739 break;
740 default:
741 goto undef;
742 }
743
744 sprintf(cp, "%s%s%s\tr%d, r%d, r%d", prefix, op, COND(opcode),
745 (int) (opcode >> 12) & 0xf,
746 (int) (opcode >> 16) & 0xf,
747 (int) (opcode >> 0) & 0xf);
748 return type;
749
750 undef:
751 /* these opcodes might be used someday */
752 sprintf(cp, "UNDEFINED");
753 return ARM_UNDEFINED_INSTRUCTION;
754 }
755
756 /* ARMv6 and later support "media" instructions (includes SIMD) */
757 static int evaluate_media(uint32_t opcode, uint32_t address,
758 struct arm_instruction *instruction)
759 {
760 char *cp = instruction->text;
761 char *mnemonic = NULL;
762
763 sprintf(cp,
764 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t",
765 address, opcode);
766 cp = strchr(cp, 0);
767
768 /* parallel add/subtract */
769 if ((opcode & 0x01800000) == 0x00000000) {
770 instruction->type = evaluate_p_add_sub(opcode, address, cp);
771 return ERROR_OK;
772 }
773
774 /* halfword pack */
775 if ((opcode & 0x01f00020) == 0x00800000) {
776 char *type, *shift;
777 unsigned imm = (unsigned) (opcode >> 7) & 0x1f;
778
779 if (opcode & (1 << 6)) {
780 type = "TB";
781 shift = "ASR";
782 if (imm == 0)
783 imm = 32;
784 } else {
785 type = "BT";
786 shift = "LSL";
787 }
788 sprintf(cp, "PKH%s%s\tr%d, r%d, r%d, %s #%d",
789 type, COND(opcode),
790 (int) (opcode >> 12) & 0xf,
791 (int) (opcode >> 16) & 0xf,
792 (int) (opcode >> 0) & 0xf,
793 shift, imm);
794 return ERROR_OK;
795 }
796
797 /* word saturate */
798 if ((opcode & 0x01a00020) == 0x00a00000) {
799 char *shift;
800 unsigned imm = (unsigned) (opcode >> 7) & 0x1f;
801
802 if (opcode & (1 << 6)) {
803 shift = "ASR";
804 if (imm == 0)
805 imm = 32;
806 } else
807 shift = "LSL";
808
809 sprintf(cp, "%cSAT%s\tr%d, #%d, r%d, %s #%d",
810 (opcode & (1 << 22)) ? 'U' : 'S',
811 COND(opcode),
812 (int) (opcode >> 12) & 0xf,
813 (int) (opcode >> 16) & 0x1f,
814 (int) (opcode >> 0) & 0xf,
815 shift, imm);
816 return ERROR_OK;
817 }
818
819 /* sign extension */
820 if ((opcode & 0x018000f0) == 0x00800070) {
821 instruction->type = evaluate_extend(opcode, address, cp);
822 return ERROR_OK;
823 }
824
825 /* multiplies */
826 if ((opcode & 0x01f00080) == 0x01000000) {
827 unsigned rn = (opcode >> 12) & 0xf;
828
829 if (rn != 0xf)
830 sprintf(cp, "SML%cD%s%s\tr%d, r%d, r%d, r%d",
831 (opcode & (1 << 6)) ? 'S' : 'A',
832 (opcode & (1 << 5)) ? "X" : "",
833 COND(opcode),
834 (int) (opcode >> 16) & 0xf,
835 (int) (opcode >> 0) & 0xf,
836 (int) (opcode >> 8) & 0xf,
837 rn);
838 else
839 sprintf(cp, "SMU%cD%s%s\tr%d, r%d, r%d",
840 (opcode & (1 << 6)) ? 'S' : 'A',
841 (opcode & (1 << 5)) ? "X" : "",
842 COND(opcode),
843 (int) (opcode >> 16) & 0xf,
844 (int) (opcode >> 0) & 0xf,
845 (int) (opcode >> 8) & 0xf);
846 return ERROR_OK;
847 }
848 if ((opcode & 0x01f00000) == 0x01400000) {
849 sprintf(cp, "SML%cLD%s%s\tr%d, r%d, r%d, r%d",
850 (opcode & (1 << 6)) ? 'S' : 'A',
851 (opcode & (1 << 5)) ? "X" : "",
852 COND(opcode),
853 (int) (opcode >> 12) & 0xf,
854 (int) (opcode >> 16) & 0xf,
855 (int) (opcode >> 0) & 0xf,
856 (int) (opcode >> 8) & 0xf);
857 return ERROR_OK;
858 }
859 if ((opcode & 0x01f00000) == 0x01500000) {
860 unsigned rn = (opcode >> 12) & 0xf;
861
862 switch (opcode & 0xc0) {
863 case 3:
864 if (rn == 0xf)
865 goto undef;
866 /* FALL THROUGH */
867 case 0:
868 break;
869 default:
870 goto undef;
871 }
872
873 if (rn != 0xf)
874 sprintf(cp, "SMML%c%s%s\tr%d, r%d, r%d, r%d",
875 (opcode & (1 << 6)) ? 'S' : 'A',
876 (opcode & (1 << 5)) ? "R" : "",
877 COND(opcode),
878 (int) (opcode >> 16) & 0xf,
879 (int) (opcode >> 0) & 0xf,
880 (int) (opcode >> 8) & 0xf,
881 rn);
882 else
883 sprintf(cp, "SMMUL%s%s\tr%d, r%d, r%d",
884 (opcode & (1 << 5)) ? "R" : "",
885 COND(opcode),
886 (int) (opcode >> 16) & 0xf,
887 (int) (opcode >> 0) & 0xf,
888 (int) (opcode >> 8) & 0xf);
889 return ERROR_OK;
890 }
891
892 /* simple matches against the remaining decode bits */
893 switch (opcode & 0x01f000f0) {
894 case 0x00a00030:
895 case 0x00e00030:
896 /* parallel halfword saturate */
897 sprintf(cp, "%cSAT16%s\tr%d, #%d, r%d",
898 (opcode & (1 << 22)) ? 'U' : 'S',
899 COND(opcode),
900 (int) (opcode >> 12) & 0xf,
901 (int) (opcode >> 16) & 0xf,
902 (int) (opcode >> 0) & 0xf);
903 return ERROR_OK;
904 case 0x00b00030:
905 mnemonic = "REV";
906 break;
907 case 0x00b000b0:
908 mnemonic = "REV16";
909 break;
910 case 0x00f000b0:
911 mnemonic = "REVSH";
912 break;
913 case 0x008000b0:
914 /* select bytes */
915 sprintf(cp, "SEL%s\tr%d, r%d, r%d", COND(opcode),
916 (int) (opcode >> 12) & 0xf,
917 (int) (opcode >> 16) & 0xf,
918 (int) (opcode >> 0) & 0xf);
919 return ERROR_OK;
920 case 0x01800010:
921 /* unsigned sum of absolute differences */
922 if (((opcode >> 12) & 0xf) == 0xf)
923 sprintf(cp, "USAD8%s\tr%d, r%d, r%d", COND(opcode),
924 (int) (opcode >> 16) & 0xf,
925 (int) (opcode >> 0) & 0xf,
926 (int) (opcode >> 8) & 0xf);
927 else
928 sprintf(cp, "USADA8%s\tr%d, r%d, r%d, r%d", COND(opcode),
929 (int) (opcode >> 16) & 0xf,
930 (int) (opcode >> 0) & 0xf,
931 (int) (opcode >> 8) & 0xf,
932 (int) (opcode >> 12) & 0xf);
933 return ERROR_OK;
934 }
935 if (mnemonic) {
936 unsigned rm = (opcode >> 0) & 0xf;
937 unsigned rd = (opcode >> 12) & 0xf;
938
939 sprintf(cp, "%s%s\tr%d, r%d", mnemonic, COND(opcode), rm, rd);
940 return ERROR_OK;
941 }
942
943 undef:
944 /* these opcodes might be used someday */
945 sprintf(cp, "UNDEFINED");
946 return ERROR_OK;
947 }
948
949 /* Miscellaneous load/store instructions */
950 static int evaluate_misc_load_store(uint32_t opcode,
951 uint32_t address, struct arm_instruction *instruction)
952 {
953 uint8_t P, U, I, W, L, S, H;
954 uint8_t Rn, Rd;
955 char *operation;/* "LDR" or "STR" */
956 char *suffix; /* "H", "SB", "SH", "D" */
957 char offset[32];
958
959 /* examine flags */
960 P = (opcode & 0x01000000) >> 24;
961 U = (opcode & 0x00800000) >> 23;
962 I = (opcode & 0x00400000) >> 22;
963 W = (opcode & 0x00200000) >> 21;
964 L = (opcode & 0x00100000) >> 20;
965 S = (opcode & 0x00000040) >> 6;
966 H = (opcode & 0x00000020) >> 5;
967
968 /* target register */
969 Rd = (opcode & 0xf000) >> 12;
970
971 /* base register */
972 Rn = (opcode & 0xf0000) >> 16;
973
974 instruction->info.load_store.Rd = Rd;
975 instruction->info.load_store.Rn = Rn;
976 instruction->info.load_store.U = U;
977
978 /* determine instruction type and suffix */
979 if (S) {/* signed */
980 if (L) {/* load */
981 if (H) {
982 operation = "LDR";
983 instruction->type = ARM_LDRSH;
984 suffix = "SH";
985 } else {
986 operation = "LDR";
987 instruction->type = ARM_LDRSB;
988 suffix = "SB";
989 }
990 } else {/* there are no signed stores, so this is used to encode double-register
991 *load/stores */
992 suffix = "D";
993 if (H) {
994 operation = "STR";
995 instruction->type = ARM_STRD;
996 } else {
997 operation = "LDR";
998 instruction->type = ARM_LDRD;
999 }
1000 }
1001 } else {/* unsigned */
1002 suffix = "H";
1003 if (L) {/* load */
1004 operation = "LDR";
1005 instruction->type = ARM_LDRH;
1006 } else {/* store */
1007 operation = "STR";
1008 instruction->type = ARM_STRH;
1009 }
1010 }
1011
1012 if (I) {/* Immediate offset/index (#+-<offset_8>)*/
1013 uint32_t offset_8 = ((opcode & 0xf00) >> 4) | (opcode & 0xf);
1014 snprintf(offset, 32, "#%s0x%" PRIx32 "", (U) ? "" : "-", offset_8);
1015
1016 instruction->info.load_store.offset_mode = 0;
1017 instruction->info.load_store.offset.offset = offset_8;
1018 } else {/* Register offset/index (+-<Rm>) */
1019 uint8_t Rm;
1020 Rm = (opcode & 0xf);
1021 snprintf(offset, 32, "%sr%i", (U) ? "" : "-", Rm);
1022
1023 instruction->info.load_store.offset_mode = 1;
1024 instruction->info.load_store.offset.reg.Rm = Rm;
1025 instruction->info.load_store.offset.reg.shift = 0x0;
1026 instruction->info.load_store.offset.reg.shift_imm = 0x0;
1027 }
1028
1029 if (P == 1) {
1030 if (W == 0) { /* offset */
1031 snprintf(instruction->text,
1032 128,
1033 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]",
1034 address,
1035 opcode,
1036 operation,
1037 COND(opcode),
1038 suffix,
1039 Rd,
1040 Rn,
1041 offset);
1042
1043 instruction->info.load_store.index_mode = 0;
1044 } else {/* pre-indexed */
1045 snprintf(instruction->text,
1046 128,
1047 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]!",
1048 address,
1049 opcode,
1050 operation,
1051 COND(opcode),
1052 suffix,
1053 Rd,
1054 Rn,
1055 offset);
1056
1057 instruction->info.load_store.index_mode = 1;
1058 }
1059 } else {/* post-indexed */
1060 snprintf(instruction->text,
1061 128,
1062 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i], %s",
1063 address,
1064 opcode,
1065 operation,
1066 COND(opcode),
1067 suffix,
1068 Rd,
1069 Rn,
1070 offset);
1071
1072 instruction->info.load_store.index_mode = 2;
1073 }
1074
1075 return ERROR_OK;
1076 }
1077
1078 /* Load/store multiples instructions */
1079 static int evaluate_ldm_stm(uint32_t opcode,
1080 uint32_t address, struct arm_instruction *instruction)
1081 {
1082 uint8_t P, U, S, W, L, Rn;
1083 uint32_t register_list;
1084 char *addressing_mode;
1085 char *mnemonic;
1086 char reg_list[69];
1087 char *reg_list_p;
1088 int i;
1089 int first_reg = 1;
1090
1091 P = (opcode & 0x01000000) >> 24;
1092 U = (opcode & 0x00800000) >> 23;
1093 S = (opcode & 0x00400000) >> 22;
1094 W = (opcode & 0x00200000) >> 21;
1095 L = (opcode & 0x00100000) >> 20;
1096 register_list = (opcode & 0xffff);
1097 Rn = (opcode & 0xf0000) >> 16;
1098
1099 instruction->info.load_store_multiple.Rn = Rn;
1100 instruction->info.load_store_multiple.register_list = register_list;
1101 instruction->info.load_store_multiple.S = S;
1102 instruction->info.load_store_multiple.W = W;
1103
1104 if (L) {
1105 instruction->type = ARM_LDM;
1106 mnemonic = "LDM";
1107 } else {
1108 instruction->type = ARM_STM;
1109 mnemonic = "STM";
1110 }
1111
1112 if (P) {
1113 if (U) {
1114 instruction->info.load_store_multiple.addressing_mode = 1;
1115 addressing_mode = "IB";
1116 } else {
1117 instruction->info.load_store_multiple.addressing_mode = 3;
1118 addressing_mode = "DB";
1119 }
1120 } else {
1121 if (U) {
1122 instruction->info.load_store_multiple.addressing_mode = 0;
1123 /* "IA" is the default in UAL syntax */
1124 addressing_mode = "";
1125 } else {
1126 instruction->info.load_store_multiple.addressing_mode = 2;
1127 addressing_mode = "DA";
1128 }
1129 }
1130
1131 reg_list_p = reg_list;
1132 for (i = 0; i <= 15; i++) {
1133 if ((register_list >> i) & 1) {
1134 if (first_reg) {
1135 first_reg = 0;
1136 reg_list_p += snprintf(reg_list_p,
1137 (reg_list + 69 - reg_list_p),
1138 "r%i",
1139 i);
1140 } else
1141 reg_list_p += snprintf(reg_list_p,
1142 (reg_list + 69 - reg_list_p),
1143 ", r%i",
1144 i);
1145 }
1146 }
1147
1148 snprintf(instruction->text, 128,
1149 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
1150 "\t%s%s%s r%i%s, {%s}%s",
1151 address, opcode,
1152 mnemonic, addressing_mode, COND(opcode),
1153 Rn, (W) ? "!" : "", reg_list, (S) ? "^" : "");
1154
1155 return ERROR_OK;
1156 }
1157
1158 /* Multiplies, extra load/stores */
1159 static int evaluate_mul_and_extra_ld_st(uint32_t opcode,
1160 uint32_t address, struct arm_instruction *instruction)
1161 {
1162 /* Multiply (accumulate) (long) and Swap/swap byte */
1163 if ((opcode & 0x000000f0) == 0x00000090) {
1164 /* Multiply (accumulate) */
1165 if ((opcode & 0x0f800000) == 0x00000000) {
1166 uint8_t Rm, Rs, Rn, Rd, S;
1167 Rm = opcode & 0xf;
1168 Rs = (opcode & 0xf00) >> 8;
1169 Rn = (opcode & 0xf000) >> 12;
1170 Rd = (opcode & 0xf0000) >> 16;
1171 S = (opcode & 0x00100000) >> 20;
1172
1173 /* examine A bit (accumulate) */
1174 if (opcode & 0x00200000) {
1175 instruction->type = ARM_MLA;
1176 snprintf(instruction->text,
1177 128,
1178 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMLA%s%s r%i, r%i, r%i, r%i",
1179 address,
1180 opcode,
1181 COND(opcode),
1182 (S) ? "S" : "",
1183 Rd,
1184 Rm,
1185 Rs,
1186 Rn);
1187 } else {
1188 instruction->type = ARM_MUL;
1189 snprintf(instruction->text,
1190 128,
1191 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMUL%s%s r%i, r%i, r%i",
1192 address,
1193 opcode,
1194 COND(opcode),
1195 (S) ? "S" : "",
1196 Rd,
1197 Rm,
1198 Rs);
1199 }
1200
1201 return ERROR_OK;
1202 }
1203
1204 /* Multiply (accumulate) long */
1205 if ((opcode & 0x0f800000) == 0x00800000) {
1206 char *mnemonic = NULL;
1207 uint8_t Rm, Rs, RdHi, RdLow, S;
1208 Rm = opcode & 0xf;
1209 Rs = (opcode & 0xf00) >> 8;
1210 RdHi = (opcode & 0xf000) >> 12;
1211 RdLow = (opcode & 0xf0000) >> 16;
1212 S = (opcode & 0x00100000) >> 20;
1213
1214 switch ((opcode & 0x00600000) >> 21) {
1215 case 0x0:
1216 instruction->type = ARM_UMULL;
1217 mnemonic = "UMULL";
1218 break;
1219 case 0x1:
1220 instruction->type = ARM_UMLAL;
1221 mnemonic = "UMLAL";
1222 break;
1223 case 0x2:
1224 instruction->type = ARM_SMULL;
1225 mnemonic = "SMULL";
1226 break;
1227 case 0x3:
1228 instruction->type = ARM_SMLAL;
1229 mnemonic = "SMLAL";
1230 break;
1231 }
1232
1233 snprintf(instruction->text,
1234 128,
1235 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, r%i, r%i",
1236 address,
1237 opcode,
1238 mnemonic,
1239 COND(opcode),
1240 (S) ? "S" : "",
1241 RdLow,
1242 RdHi,
1243 Rm,
1244 Rs);
1245
1246 return ERROR_OK;
1247 }
1248
1249 /* Swap/swap byte */
1250 if ((opcode & 0x0f800000) == 0x01000000) {
1251 uint8_t Rm, Rd, Rn;
1252 Rm = opcode & 0xf;
1253 Rd = (opcode & 0xf000) >> 12;
1254 Rn = (opcode & 0xf0000) >> 16;
1255
1256 /* examine B flag */
1257 instruction->type = (opcode & 0x00400000) ? ARM_SWPB : ARM_SWP;
1258
1259 snprintf(instruction->text,
1260 128,
1261 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, [r%i]",
1262 address,
1263 opcode,
1264 (opcode & 0x00400000) ? "SWPB" : "SWP",
1265 COND(opcode),
1266 Rd,
1267 Rm,
1268 Rn);
1269 return ERROR_OK;
1270 }
1271
1272 }
1273
1274 return evaluate_misc_load_store(opcode, address, instruction);
1275 }
1276
1277 static int evaluate_mrs_msr(uint32_t opcode,
1278 uint32_t address, struct arm_instruction *instruction)
1279 {
1280 int R = (opcode & 0x00400000) >> 22;
1281 char *PSR = (R) ? "SPSR" : "CPSR";
1282
1283 /* Move register to status register (MSR) */
1284 if (opcode & 0x00200000) {
1285 instruction->type = ARM_MSR;
1286
1287 /* immediate variant */
1288 if (opcode & 0x02000000) {
1289 uint8_t immediate = (opcode & 0xff);
1290 uint8_t rotate = (opcode & 0xf00);
1291
1292 snprintf(instruction->text,
1293 128,
1294 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, 0x%8.8" PRIx32,
1295 address,
1296 opcode,
1297 COND(opcode),
1298 PSR,
1299 (opcode & 0x10000) ? "c" : "",
1300 (opcode & 0x20000) ? "x" : "",
1301 (opcode & 0x40000) ? "s" : "",
1302 (opcode & 0x80000) ? "f" : "",
1303 ror(immediate, (rotate * 2))
1304 );
1305 } else {/* register variant */
1306 uint8_t Rm = opcode & 0xf;
1307 snprintf(instruction->text,
1308 128,
1309 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, r%i",
1310 address,
1311 opcode,
1312 COND(opcode),
1313 PSR,
1314 (opcode & 0x10000) ? "c" : "",
1315 (opcode & 0x20000) ? "x" : "",
1316 (opcode & 0x40000) ? "s" : "",
1317 (opcode & 0x80000) ? "f" : "",
1318 Rm
1319 );
1320 }
1321
1322 } else {/* Move status register to register (MRS) */
1323 uint8_t Rd;
1324
1325 instruction->type = ARM_MRS;
1326 Rd = (opcode & 0x0000f000) >> 12;
1327
1328 snprintf(instruction->text,
1329 128,
1330 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMRS%s r%i, %s",
1331 address,
1332 opcode,
1333 COND(opcode),
1334 Rd,
1335 PSR);
1336 }
1337
1338 return ERROR_OK;
1339 }
1340
1341 /* Miscellaneous instructions */
1342 static int evaluate_misc_instr(uint32_t opcode,
1343 uint32_t address, struct arm_instruction *instruction)
1344 {
1345 /* MRS/MSR */
1346 if ((opcode & 0x000000f0) == 0x00000000)
1347 evaluate_mrs_msr(opcode, address, instruction);
1348
1349 /* BX */
1350 if ((opcode & 0x006000f0) == 0x00200010) {
1351 uint8_t Rm;
1352 instruction->type = ARM_BX;
1353 Rm = opcode & 0xf;
1354
1355 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBX%s r%i",
1356 address, opcode, COND(opcode), Rm);
1357
1358 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1359 instruction->info.b_bl_bx_blx.target_address = -1;
1360 }
1361
1362 /* BXJ - "Jazelle" support (ARMv5-J) */
1363 if ((opcode & 0x006000f0) == 0x00200020) {
1364 uint8_t Rm;
1365 instruction->type = ARM_BX;
1366 Rm = opcode & 0xf;
1367
1368 snprintf(instruction->text, 128,
1369 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBXJ%s r%i",
1370 address, opcode, COND(opcode), Rm);
1371
1372 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1373 instruction->info.b_bl_bx_blx.target_address = -1;
1374 }
1375
1376 /* CLZ */
1377 if ((opcode & 0x006000f0) == 0x00600010) {
1378 uint8_t Rm, Rd;
1379 instruction->type = ARM_CLZ;
1380 Rm = opcode & 0xf;
1381 Rd = (opcode & 0xf000) >> 12;
1382
1383 snprintf(instruction->text,
1384 128,
1385 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCLZ%s r%i, r%i",
1386 address,
1387 opcode,
1388 COND(opcode),
1389 Rd,
1390 Rm);
1391 }
1392
1393 /* BLX(2) */
1394 if ((opcode & 0x006000f0) == 0x00200030) {
1395 uint8_t Rm;
1396 instruction->type = ARM_BLX;
1397 Rm = opcode & 0xf;
1398
1399 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX%s r%i",
1400 address, opcode, COND(opcode), Rm);
1401
1402 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1403 instruction->info.b_bl_bx_blx.target_address = -1;
1404 }
1405
1406 /* Enhanced DSP add/subtracts */
1407 if ((opcode & 0x0000000f0) == 0x00000050) {
1408 uint8_t Rm, Rd, Rn;
1409 char *mnemonic = NULL;
1410 Rm = opcode & 0xf;
1411 Rd = (opcode & 0xf000) >> 12;
1412 Rn = (opcode & 0xf0000) >> 16;
1413
1414 switch ((opcode & 0x00600000) >> 21) {
1415 case 0x0:
1416 instruction->type = ARM_QADD;
1417 mnemonic = "QADD";
1418 break;
1419 case 0x1:
1420 instruction->type = ARM_QSUB;
1421 mnemonic = "QSUB";
1422 break;
1423 case 0x2:
1424 instruction->type = ARM_QDADD;
1425 mnemonic = "QDADD";
1426 break;
1427 case 0x3:
1428 instruction->type = ARM_QDSUB;
1429 mnemonic = "QDSUB";
1430 break;
1431 }
1432
1433 snprintf(instruction->text,
1434 128,
1435 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, r%i",
1436 address,
1437 opcode,
1438 mnemonic,
1439 COND(opcode),
1440 Rd,
1441 Rm,
1442 Rn);
1443 }
1444
1445 /* exception return */
1446 if ((opcode & 0x0000000f0) == 0x00000060) {
1447 if (((opcode & 0x600000) >> 21) == 3)
1448 instruction->type = ARM_ERET;
1449 snprintf(instruction->text,
1450 128,
1451 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tERET",
1452 address,
1453 opcode);
1454 }
1455
1456 /* exception generate instructions */
1457 if ((opcode & 0x0000000f0) == 0x00000070) {
1458 uint32_t immediate = 0;
1459 char *mnemonic = NULL;
1460
1461 switch ((opcode & 0x600000) >> 21) {
1462 case 0x1:
1463 instruction->type = ARM_BKPT;
1464 mnemonic = "BRKT";
1465 immediate = ((opcode & 0x000fff00) >> 4) | (opcode & 0xf);
1466 break;
1467 case 0x2:
1468 instruction->type = ARM_HVC;
1469 mnemonic = "HVC";
1470 immediate = ((opcode & 0x000fff00) >> 4) | (opcode & 0xf);
1471 break;
1472 case 0x3:
1473 instruction->type = ARM_SMC;
1474 mnemonic = "SMC";
1475 immediate = (opcode & 0xf);
1476 break;
1477 }
1478
1479 snprintf(instruction->text,
1480 128,
1481 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s 0x%4.4" PRIx32 "",
1482 address,
1483 opcode,
1484 mnemonic,
1485 immediate);
1486 }
1487
1488 /* Enhanced DSP multiplies */
1489 if ((opcode & 0x000000090) == 0x00000080) {
1490 int x = (opcode & 0x20) >> 5;
1491 int y = (opcode & 0x40) >> 6;
1492
1493 /* SMLA < x><y> */
1494 if ((opcode & 0x00600000) == 0x00000000) {
1495 uint8_t Rd, Rm, Rs, Rn;
1496 instruction->type = ARM_SMLAxy;
1497 Rd = (opcode & 0xf0000) >> 16;
1498 Rm = (opcode & 0xf);
1499 Rs = (opcode & 0xf00) >> 8;
1500 Rn = (opcode & 0xf000) >> 12;
1501
1502 snprintf(instruction->text,
1503 128,
1504 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
1505 address,
1506 opcode,
1507 (x) ? "T" : "B",
1508 (y) ? "T" : "B",
1509 COND(opcode),
1510 Rd,
1511 Rm,
1512 Rs,
1513 Rn);
1514 }
1515
1516 /* SMLAL < x><y> */
1517 if ((opcode & 0x00600000) == 0x00400000) {
1518 uint8_t RdLow, RdHi, Rm, Rs;
1519 instruction->type = ARM_SMLAxy;
1520 RdHi = (opcode & 0xf0000) >> 16;
1521 RdLow = (opcode & 0xf000) >> 12;
1522 Rm = (opcode & 0xf);
1523 Rs = (opcode & 0xf00) >> 8;
1524
1525 snprintf(instruction->text,
1526 128,
1527 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
1528 address,
1529 opcode,
1530 (x) ? "T" : "B",
1531 (y) ? "T" : "B",
1532 COND(opcode),
1533 RdLow,
1534 RdHi,
1535 Rm,
1536 Rs);
1537 }
1538
1539 /* SMLAW < y> */
1540 if (((opcode & 0x00600000) == 0x00100000) && (x == 0)) {
1541 uint8_t Rd, Rm, Rs, Rn;
1542 instruction->type = ARM_SMLAWy;
1543 Rd = (opcode & 0xf0000) >> 16;
1544 Rm = (opcode & 0xf);
1545 Rs = (opcode & 0xf00) >> 8;
1546 Rn = (opcode & 0xf000) >> 12;
1547
1548 snprintf(instruction->text,
1549 128,
1550 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLAW%s%s r%i, r%i, r%i, r%i",
1551 address,
1552 opcode,
1553 (y) ? "T" : "B",
1554 COND(opcode),
1555 Rd,
1556 Rm,
1557 Rs,
1558 Rn);
1559 }
1560
1561 /* SMUL < x><y> */
1562 if ((opcode & 0x00600000) == 0x00300000) {
1563 uint8_t Rd, Rm, Rs;
1564 instruction->type = ARM_SMULxy;
1565 Rd = (opcode & 0xf0000) >> 16;
1566 Rm = (opcode & 0xf);
1567 Rs = (opcode & 0xf00) >> 8;
1568
1569 snprintf(instruction->text,
1570 128,
1571 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s%s r%i, r%i, r%i",
1572 address,
1573 opcode,
1574 (x) ? "T" : "B",
1575 (y) ? "T" : "B",
1576 COND(opcode),
1577 Rd,
1578 Rm,
1579 Rs);
1580 }
1581
1582 /* SMULW < y> */
1583 if (((opcode & 0x00600000) == 0x00100000) && (x == 1)) {
1584 uint8_t Rd, Rm, Rs;
1585 instruction->type = ARM_SMULWy;
1586 Rd = (opcode & 0xf0000) >> 16;
1587 Rm = (opcode & 0xf);
1588 Rs = (opcode & 0xf00) >> 8;
1589
1590 snprintf(instruction->text,
1591 128,
1592 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s r%i, r%i, r%i",
1593 address,
1594 opcode,
1595 (y) ? "T" : "B",
1596 COND(opcode),
1597 Rd,
1598 Rm,
1599 Rs);
1600 }
1601 }
1602
1603 return ERROR_OK;
1604 }
1605
1606 static int evaluate_data_proc(uint32_t opcode,
1607 uint32_t address, struct arm_instruction *instruction)
1608 {
1609 uint8_t I, op, S, Rn, Rd;
1610 char *mnemonic = NULL;
1611 char shifter_operand[32];
1612
1613 I = (opcode & 0x02000000) >> 25;
1614 op = (opcode & 0x01e00000) >> 21;
1615 S = (opcode & 0x00100000) >> 20;
1616
1617 Rd = (opcode & 0xf000) >> 12;
1618 Rn = (opcode & 0xf0000) >> 16;
1619
1620 instruction->info.data_proc.Rd = Rd;
1621 instruction->info.data_proc.Rn = Rn;
1622 instruction->info.data_proc.S = S;
1623
1624 switch (op) {
1625 case 0x0:
1626 instruction->type = ARM_AND;
1627 mnemonic = "AND";
1628 break;
1629 case 0x1:
1630 instruction->type = ARM_EOR;
1631 mnemonic = "EOR";
1632 break;
1633 case 0x2:
1634 instruction->type = ARM_SUB;
1635 mnemonic = "SUB";
1636 break;
1637 case 0x3:
1638 instruction->type = ARM_RSB;
1639 mnemonic = "RSB";
1640 break;
1641 case 0x4:
1642 instruction->type = ARM_ADD;
1643 mnemonic = "ADD";
1644 break;
1645 case 0x5:
1646 instruction->type = ARM_ADC;
1647 mnemonic = "ADC";
1648 break;
1649 case 0x6:
1650 instruction->type = ARM_SBC;
1651 mnemonic = "SBC";
1652 break;
1653 case 0x7:
1654 instruction->type = ARM_RSC;
1655 mnemonic = "RSC";
1656 break;
1657 case 0x8:
1658 instruction->type = ARM_TST;
1659 mnemonic = "TST";
1660 break;
1661 case 0x9:
1662 instruction->type = ARM_TEQ;
1663 mnemonic = "TEQ";
1664 break;
1665 case 0xa:
1666 instruction->type = ARM_CMP;
1667 mnemonic = "CMP";
1668 break;
1669 case 0xb:
1670 instruction->type = ARM_CMN;
1671 mnemonic = "CMN";
1672 break;
1673 case 0xc:
1674 instruction->type = ARM_ORR;
1675 mnemonic = "ORR";
1676 break;
1677 case 0xd:
1678 instruction->type = ARM_MOV;
1679 mnemonic = "MOV";
1680 break;
1681 case 0xe:
1682 instruction->type = ARM_BIC;
1683 mnemonic = "BIC";
1684 break;
1685 case 0xf:
1686 instruction->type = ARM_MVN;
1687 mnemonic = "MVN";
1688 break;
1689 }
1690
1691 if (I) {/* immediate shifter operand (#<immediate>)*/
1692 uint8_t immed_8 = opcode & 0xff;
1693 uint8_t rotate_imm = (opcode & 0xf00) >> 8;
1694 uint32_t immediate;
1695
1696 immediate = ror(immed_8, rotate_imm * 2);
1697
1698 snprintf(shifter_operand, 32, "#0x%" PRIx32 "", immediate);
1699
1700 instruction->info.data_proc.variant = 0;
1701 instruction->info.data_proc.shifter_operand.immediate.immediate = immediate;
1702 } else {/* register-based shifter operand */
1703 uint8_t shift, Rm;
1704 shift = (opcode & 0x60) >> 5;
1705 Rm = (opcode & 0xf);
1706
1707 if ((opcode & 0x10) != 0x10) { /* Immediate shifts ("<Rm>" or "<Rm>, <shift>
1708 *#<shift_immediate>") */
1709 uint8_t shift_imm;
1710 shift_imm = (opcode & 0xf80) >> 7;
1711
1712 instruction->info.data_proc.variant = 1;
1713 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1714 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm =
1715 shift_imm;
1716 instruction->info.data_proc.shifter_operand.immediate_shift.shift = shift;
1717
1718 /* LSR encodes a shift by 32 bit as 0x0 */
1719 if ((shift == 0x1) && (shift_imm == 0x0))
1720 shift_imm = 0x20;
1721
1722 /* ASR encodes a shift by 32 bit as 0x0 */
1723 if ((shift == 0x2) && (shift_imm == 0x0))
1724 shift_imm = 0x20;
1725
1726 /* ROR by 32 bit is actually a RRX */
1727 if ((shift == 0x3) && (shift_imm == 0x0))
1728 shift = 0x4;
1729
1730 if ((shift_imm == 0x0) && (shift == 0x0))
1731 snprintf(shifter_operand, 32, "r%i", Rm);
1732 else {
1733 if (shift == 0x0) /* LSL */
1734 snprintf(shifter_operand,
1735 32,
1736 "r%i, LSL #0x%x",
1737 Rm,
1738 shift_imm);
1739 else if (shift == 0x1) /* LSR */
1740 snprintf(shifter_operand,
1741 32,
1742 "r%i, LSR #0x%x",
1743 Rm,
1744 shift_imm);
1745 else if (shift == 0x2) /* ASR */
1746 snprintf(shifter_operand,
1747 32,
1748 "r%i, ASR #0x%x",
1749 Rm,
1750 shift_imm);
1751 else if (shift == 0x3) /* ROR */
1752 snprintf(shifter_operand,
1753 32,
1754 "r%i, ROR #0x%x",
1755 Rm,
1756 shift_imm);
1757 else if (shift == 0x4) /* RRX */
1758 snprintf(shifter_operand, 32, "r%i, RRX", Rm);
1759 }
1760 } else {/* Register shifts ("<Rm>, <shift> <Rs>") */
1761 uint8_t Rs = (opcode & 0xf00) >> 8;
1762
1763 instruction->info.data_proc.variant = 2;
1764 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rm;
1765 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rs;
1766 instruction->info.data_proc.shifter_operand.register_shift.shift = shift;
1767
1768 if (shift == 0x0) /* LSL */
1769 snprintf(shifter_operand, 32, "r%i, LSL r%i", Rm, Rs);
1770 else if (shift == 0x1) /* LSR */
1771 snprintf(shifter_operand, 32, "r%i, LSR r%i", Rm, Rs);
1772 else if (shift == 0x2) /* ASR */
1773 snprintf(shifter_operand, 32, "r%i, ASR r%i", Rm, Rs);
1774 else if (shift == 0x3) /* ROR */
1775 snprintf(shifter_operand, 32, "r%i, ROR r%i", Rm, Rs);
1776 }
1777 }
1778
1779 if ((op < 0x8) || (op == 0xc) || (op == 0xe)) { /* <opcode3>{<cond>}{S} <Rd>, <Rn>,
1780 *<shifter_operand> */
1781 snprintf(instruction->text,
1782 128,
1783 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, %s",
1784 address,
1785 opcode,
1786 mnemonic,
1787 COND(opcode),
1788 (S) ? "S" : "",
1789 Rd,
1790 Rn,
1791 shifter_operand);
1792 } else if ((op == 0xd) || (op == 0xf)) { /* <opcode1>{<cond>}{S} <Rd>,
1793 *<shifter_operand> */
1794 if (opcode == 0xe1a00000) /* print MOV r0,r0 as NOP */
1795 snprintf(instruction->text,
1796 128,
1797 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tNOP",
1798 address,
1799 opcode);
1800 else
1801 snprintf(instruction->text,
1802 128,
1803 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, %s",
1804 address,
1805 opcode,
1806 mnemonic,
1807 COND(opcode),
1808 (S) ? "S" : "",
1809 Rd,
1810 shifter_operand);
1811 } else {/* <opcode2>{<cond>} <Rn>, <shifter_operand> */
1812 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, %s",
1813 address, opcode, mnemonic, COND(opcode),
1814 Rn, shifter_operand);
1815 }
1816
1817 return ERROR_OK;
1818 }
1819
1820 int arm_evaluate_opcode(uint32_t opcode, uint32_t address,
1821 struct arm_instruction *instruction)
1822 {
1823 /* clear fields, to avoid confusion */
1824 memset(instruction, 0, sizeof(struct arm_instruction));
1825 instruction->opcode = opcode;
1826 instruction->instruction_size = 4;
1827
1828 /* catch opcodes with condition field [31:28] = b1111 */
1829 if ((opcode & 0xf0000000) == 0xf0000000) {
1830 /* Undefined instruction (or ARMv5E cache preload PLD) */
1831 if ((opcode & 0x08000000) == 0x00000000)
1832 return evaluate_pld(opcode, address, instruction);
1833
1834 /* Undefined instruction (or ARMv6+ SRS/RFE) */
1835 if ((opcode & 0x0e000000) == 0x08000000)
1836 return evaluate_srs(opcode, address, instruction);
1837
1838 /* Branch and branch with link and change to Thumb */
1839 if ((opcode & 0x0e000000) == 0x0a000000)
1840 return evaluate_blx_imm(opcode, address, instruction);
1841
1842 /* Extended coprocessor opcode space (ARMv5 and higher)
1843 * Coprocessor load/store and double register transfers */
1844 if ((opcode & 0x0e000000) == 0x0c000000)
1845 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1846
1847 /* Coprocessor data processing */
1848 if ((opcode & 0x0f000100) == 0x0c000000)
1849 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1850
1851 /* Coprocessor register transfers */
1852 if ((opcode & 0x0f000010) == 0x0c000010)
1853 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1854
1855 /* Undefined instruction */
1856 if ((opcode & 0x0f000000) == 0x0f000000) {
1857 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1858 snprintf(instruction->text,
1859 128,
1860 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
1861 address,
1862 opcode);
1863 return ERROR_OK;
1864 }
1865 }
1866
1867 /* catch opcodes with [27:25] = b000 */
1868 if ((opcode & 0x0e000000) == 0x00000000) {
1869 /* Multiplies, extra load/stores */
1870 if ((opcode & 0x00000090) == 0x00000090)
1871 return evaluate_mul_and_extra_ld_st(opcode, address, instruction);
1872
1873 /* Miscellaneous instructions */
1874 if ((opcode & 0x0f900000) == 0x01000000)
1875 return evaluate_misc_instr(opcode, address, instruction);
1876
1877 return evaluate_data_proc(opcode, address, instruction);
1878 }
1879
1880 /* catch opcodes with [27:25] = b001 */
1881 if ((opcode & 0x0e000000) == 0x02000000) {
1882 /* Undefined instruction */
1883 if ((opcode & 0x0fb00000) == 0x03000000) {
1884 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1885 snprintf(instruction->text,
1886 128,
1887 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
1888 address,
1889 opcode);
1890 return ERROR_OK;
1891 }
1892
1893 /* Move immediate to status register */
1894 if ((opcode & 0x0fb00000) == 0x03200000)
1895 return evaluate_mrs_msr(opcode, address, instruction);
1896
1897 return evaluate_data_proc(opcode, address, instruction);
1898
1899 }
1900
1901 /* catch opcodes with [27:25] = b010 */
1902 if ((opcode & 0x0e000000) == 0x04000000) {
1903 /* Load/store immediate offset */
1904 return evaluate_load_store(opcode, address, instruction);
1905 }
1906
1907 /* catch opcodes with [27:25] = b011 */
1908 if ((opcode & 0x0e000000) == 0x06000000) {
1909 /* Load/store register offset */
1910 if ((opcode & 0x00000010) == 0x00000000)
1911 return evaluate_load_store(opcode, address, instruction);
1912
1913 /* Architecturally Undefined instruction
1914 * ... don't expect these to ever be used
1915 */
1916 if ((opcode & 0x07f000f0) == 0x07f000f0) {
1917 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1918 snprintf(instruction->text, 128,
1919 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEF",
1920 address, opcode);
1921 return ERROR_OK;
1922 }
1923
1924 /* "media" instructions */
1925 return evaluate_media(opcode, address, instruction);
1926 }
1927
1928 /* catch opcodes with [27:25] = b100 */
1929 if ((opcode & 0x0e000000) == 0x08000000) {
1930 /* Load/store multiple */
1931 return evaluate_ldm_stm(opcode, address, instruction);
1932 }
1933
1934 /* catch opcodes with [27:25] = b101 */
1935 if ((opcode & 0x0e000000) == 0x0a000000) {
1936 /* Branch and branch with link */
1937 return evaluate_b_bl(opcode, address, instruction);
1938 }
1939
1940 /* catch opcodes with [27:25] = b110 */
1941 if ((opcode & 0x0e000000) == 0x0c000000) {
1942 /* Coprocessor load/store and double register transfers */
1943 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1944 }
1945
1946 /* catch opcodes with [27:25] = b111 */
1947 if ((opcode & 0x0e000000) == 0x0e000000) {
1948 /* Software interrupt */
1949 if ((opcode & 0x0f000000) == 0x0f000000)
1950 return evaluate_swi(opcode, address, instruction);
1951
1952 /* Coprocessor data processing */
1953 if ((opcode & 0x0f000010) == 0x0e000000)
1954 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1955
1956 /* Coprocessor register transfers */
1957 if ((opcode & 0x0f000010) == 0x0e000010)
1958 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1959 }
1960
1961 LOG_ERROR("ARM: should never reach this point (opcode=%08x)",
1962 (unsigned) opcode);
1963 return -1;
1964 }
1965
1966 static int evaluate_b_bl_blx_thumb(uint16_t opcode,
1967 uint32_t address, struct arm_instruction *instruction)
1968 {
1969 uint32_t offset = opcode & 0x7ff;
1970 uint32_t opc = (opcode >> 11) & 0x3;
1971 uint32_t target_address;
1972 char *mnemonic = NULL;
1973
1974 /* sign extend 11-bit offset */
1975 if (((opc == 0) || (opc == 2)) && (offset & 0x00000400))
1976 offset = 0xfffff800 | offset;
1977
1978 target_address = address + 4 + (offset << 1);
1979
1980 switch (opc) {
1981 /* unconditional branch */
1982 case 0:
1983 instruction->type = ARM_B;
1984 mnemonic = "B";
1985 break;
1986 /* BLX suffix */
1987 case 1:
1988 instruction->type = ARM_BLX;
1989 mnemonic = "BLX";
1990 target_address &= 0xfffffffc;
1991 break;
1992 /* BL/BLX prefix */
1993 case 2:
1994 instruction->type = ARM_UNKNOWN_INSTUCTION;
1995 mnemonic = "prefix";
1996 target_address = offset << 12;
1997 break;
1998 /* BL suffix */
1999 case 3:
2000 instruction->type = ARM_BL;
2001 mnemonic = "BL";
2002 break;
2003 }
2004
2005 /* TODO: deal correctly with dual opcode (prefixed) BL/BLX;
2006 * these are effectively 32-bit instructions even in Thumb1. For
2007 * disassembly, it's simplest to always use the Thumb2 decoder.
2008 *
2009 * But some cores will evidently handle them as two instructions,
2010 * where exceptions may occur between the two. The ETMv3.2+ ID
2011 * register has a bit which exposes this behavior.
2012 */
2013
2014 snprintf(instruction->text, 128,
2015 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%#8.8" PRIx32,
2016 address, opcode, mnemonic, target_address);
2017
2018 instruction->info.b_bl_bx_blx.reg_operand = -1;
2019 instruction->info.b_bl_bx_blx.target_address = target_address;
2020
2021 return ERROR_OK;
2022 }
2023
2024 static int evaluate_add_sub_thumb(uint16_t opcode,
2025 uint32_t address, struct arm_instruction *instruction)
2026 {
2027 uint8_t Rd = (opcode >> 0) & 0x7;
2028 uint8_t Rn = (opcode >> 3) & 0x7;
2029 uint8_t Rm_imm = (opcode >> 6) & 0x7;
2030 uint32_t opc = opcode & (1 << 9);
2031 uint32_t reg_imm = opcode & (1 << 10);
2032 char *mnemonic;
2033
2034 if (opc) {
2035 instruction->type = ARM_SUB;
2036 mnemonic = "SUBS";
2037 } else {
2038 /* REVISIT: if reg_imm == 0, display as "MOVS" */
2039 instruction->type = ARM_ADD;
2040 mnemonic = "ADDS";
2041 }
2042
2043 instruction->info.data_proc.Rd = Rd;
2044 instruction->info.data_proc.Rn = Rn;
2045 instruction->info.data_proc.S = 1;
2046
2047 if (reg_imm) {
2048 instruction->info.data_proc.variant = 0;/*immediate*/
2049 instruction->info.data_proc.shifter_operand.immediate.immediate = Rm_imm;
2050 snprintf(instruction->text, 128,
2051 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%d",
2052 address, opcode, mnemonic, Rd, Rn, Rm_imm);
2053 } else {
2054 instruction->info.data_proc.variant = 1;/*immediate shift*/
2055 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm_imm;
2056 snprintf(instruction->text, 128,
2057 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, r%i",
2058 address, opcode, mnemonic, Rd, Rn, Rm_imm);
2059 }
2060
2061 return ERROR_OK;
2062 }
2063
2064 static int evaluate_shift_imm_thumb(uint16_t opcode,
2065 uint32_t address, struct arm_instruction *instruction)
2066 {
2067 uint8_t Rd = (opcode >> 0) & 0x7;
2068 uint8_t Rm = (opcode >> 3) & 0x7;
2069 uint8_t imm = (opcode >> 6) & 0x1f;
2070 uint8_t opc = (opcode >> 11) & 0x3;
2071 char *mnemonic = NULL;
2072
2073 switch (opc) {
2074 case 0:
2075 instruction->type = ARM_MOV;
2076 mnemonic = "LSLS";
2077 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 0;
2078 break;
2079 case 1:
2080 instruction->type = ARM_MOV;
2081 mnemonic = "LSRS";
2082 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 1;
2083 break;
2084 case 2:
2085 instruction->type = ARM_MOV;
2086 mnemonic = "ASRS";
2087 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 2;
2088 break;
2089 }
2090
2091 if ((imm == 0) && (opc != 0))
2092 imm = 32;
2093
2094 instruction->info.data_proc.Rd = Rd;
2095 instruction->info.data_proc.Rn = -1;
2096 instruction->info.data_proc.S = 1;
2097
2098 instruction->info.data_proc.variant = 1;/*immediate_shift*/
2099 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
2100 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = imm;
2101
2102 snprintf(instruction->text, 128,
2103 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%#2.2x",
2104 address, opcode, mnemonic, Rd, Rm, imm);
2105
2106 return ERROR_OK;
2107 }
2108
2109 static int evaluate_data_proc_imm_thumb(uint16_t opcode,
2110 uint32_t address, struct arm_instruction *instruction)
2111 {
2112 uint8_t imm = opcode & 0xff;
2113 uint8_t Rd = (opcode >> 8) & 0x7;
2114 uint32_t opc = (opcode >> 11) & 0x3;
2115 char *mnemonic = NULL;
2116
2117 instruction->info.data_proc.Rd = Rd;
2118 instruction->info.data_proc.Rn = Rd;
2119 instruction->info.data_proc.S = 1;
2120 instruction->info.data_proc.variant = 0;/*immediate*/
2121 instruction->info.data_proc.shifter_operand.immediate.immediate = imm;
2122
2123 switch (opc) {
2124 case 0:
2125 instruction->type = ARM_MOV;
2126 mnemonic = "MOVS";
2127 instruction->info.data_proc.Rn = -1;
2128 break;
2129 case 1:
2130 instruction->type = ARM_CMP;
2131 mnemonic = "CMP";
2132 instruction->info.data_proc.Rd = -1;
2133 break;
2134 case 2:
2135 instruction->type = ARM_ADD;
2136 mnemonic = "ADDS";
2137 break;
2138 case 3:
2139 instruction->type = ARM_SUB;
2140 mnemonic = "SUBS";
2141 break;
2142 }
2143
2144 snprintf(instruction->text, 128,
2145 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, #%#2.2x",
2146 address, opcode, mnemonic, Rd, imm);
2147
2148 return ERROR_OK;
2149 }
2150
2151 static int evaluate_data_proc_thumb(uint16_t opcode,
2152 uint32_t address, struct arm_instruction *instruction)
2153 {
2154 uint8_t high_reg, op, Rm, Rd, H1, H2;
2155 char *mnemonic = NULL;
2156 bool nop = false;
2157
2158 high_reg = (opcode & 0x0400) >> 10;
2159 op = (opcode & 0x03C0) >> 6;
2160
2161 Rd = (opcode & 0x0007);
2162 Rm = (opcode & 0x0038) >> 3;
2163 H1 = (opcode & 0x0080) >> 7;
2164 H2 = (opcode & 0x0040) >> 6;
2165
2166 instruction->info.data_proc.Rd = Rd;
2167 instruction->info.data_proc.Rn = Rd;
2168 instruction->info.data_proc.S = (!high_reg || (instruction->type == ARM_CMP));
2169 instruction->info.data_proc.variant = 1 /*immediate shift*/;
2170 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
2171
2172 if (high_reg) {
2173 Rd |= H1 << 3;
2174 Rm |= H2 << 3;
2175 op >>= 2;
2176
2177 switch (op) {
2178 case 0x0:
2179 instruction->type = ARM_ADD;
2180 mnemonic = "ADD";
2181 break;
2182 case 0x1:
2183 instruction->type = ARM_CMP;
2184 mnemonic = "CMP";
2185 break;
2186 case 0x2:
2187 instruction->type = ARM_MOV;
2188 mnemonic = "MOV";
2189 if (Rd == Rm)
2190 nop = true;
2191 break;
2192 case 0x3:
2193 if ((opcode & 0x7) == 0x0) {
2194 instruction->info.b_bl_bx_blx.reg_operand = Rm;
2195 if (H1) {
2196 instruction->type = ARM_BLX;
2197 snprintf(instruction->text, 128,
2198 "0x%8.8" PRIx32
2199 " 0x%4.4x \tBLX\tr%i",
2200 address, opcode, Rm);
2201 } else {
2202 instruction->type = ARM_BX;
2203 snprintf(instruction->text, 128,
2204 "0x%8.8" PRIx32
2205 " 0x%4.4x \tBX\tr%i",
2206 address, opcode, Rm);
2207 }
2208 } else {
2209 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2210 snprintf(instruction->text, 128,
2211 "0x%8.8" PRIx32
2212 " 0x%4.4x \t"
2213 "UNDEFINED INSTRUCTION",
2214 address, opcode);
2215 }
2216 return ERROR_OK;
2217 break;
2218 }
2219 } else {
2220 switch (op) {
2221 case 0x0:
2222 instruction->type = ARM_AND;
2223 mnemonic = "ANDS";
2224 break;
2225 case 0x1:
2226 instruction->type = ARM_EOR;
2227 mnemonic = "EORS";
2228 break;
2229 case 0x2:
2230 instruction->type = ARM_MOV;
2231 mnemonic = "LSLS";
2232 instruction->info.data_proc.variant = 2 /*register shift*/;
2233 instruction->info.data_proc.shifter_operand.register_shift.shift = 0;
2234 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
2235 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
2236 break;
2237 case 0x3:
2238 instruction->type = ARM_MOV;
2239 mnemonic = "LSRS";
2240 instruction->info.data_proc.variant = 2 /*register shift*/;
2241 instruction->info.data_proc.shifter_operand.register_shift.shift = 1;
2242 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
2243 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
2244 break;
2245 case 0x4:
2246 instruction->type = ARM_MOV;
2247 mnemonic = "ASRS";
2248 instruction->info.data_proc.variant = 2 /*register shift*/;
2249 instruction->info.data_proc.shifter_operand.register_shift.shift = 2;
2250 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
2251 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
2252 break;
2253 case 0x5:
2254 instruction->type = ARM_ADC;
2255 mnemonic = "ADCS";
2256 break;
2257 case 0x6:
2258 instruction->type = ARM_SBC;
2259 mnemonic = "SBCS";
2260 break;
2261 case 0x7:
2262 instruction->type = ARM_MOV;
2263 mnemonic = "RORS";
2264 instruction->info.data_proc.variant = 2 /*register shift*/;
2265 instruction->info.data_proc.shifter_operand.register_shift.shift = 3;
2266 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
2267 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
2268 break;
2269 case 0x8:
2270 instruction->type = ARM_TST;
2271 mnemonic = "TST";
2272 break;
2273 case 0x9:
2274 instruction->type = ARM_RSB;
2275 mnemonic = "RSBS";
2276 instruction->info.data_proc.variant = 0 /*immediate*/;
2277 instruction->info.data_proc.shifter_operand.immediate.immediate = 0;
2278 instruction->info.data_proc.Rn = Rm;
2279 break;
2280 case 0xA:
2281 instruction->type = ARM_CMP;
2282 mnemonic = "CMP";
2283 break;
2284 case 0xB:
2285 instruction->type = ARM_CMN;
2286 mnemonic = "CMN";
2287 break;
2288 case 0xC:
2289 instruction->type = ARM_ORR;
2290 mnemonic = "ORRS";
2291 break;
2292 case 0xD:
2293 instruction->type = ARM_MUL;
2294 mnemonic = "MULS";
2295 break;
2296 case 0xE:
2297 instruction->type = ARM_BIC;
2298 mnemonic = "BICS";
2299 break;
2300 case 0xF:
2301 instruction->type = ARM_MVN;
2302 mnemonic = "MVNS";
2303 break;
2304 }
2305 }
2306
2307 if (nop)
2308 snprintf(instruction->text, 128,
2309 "0x%8.8" PRIx32 " 0x%4.4x \tNOP\t\t\t"
2310 "; (%s r%i, r%i)",
2311 address, opcode, mnemonic, Rd, Rm);
2312 else
2313 snprintf(instruction->text, 128,
2314 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i",
2315 address, opcode, mnemonic, Rd, Rm);
2316
2317 return ERROR_OK;
2318 }
2319
2320 /* PC-relative data addressing is word-aligned even with Thumb */
2321 static inline uint32_t thumb_alignpc4(uint32_t addr)
2322 {
2323 return (addr + 4) & ~3;
2324 }
2325
2326 static int evaluate_load_literal_thumb(uint16_t opcode,
2327 uint32_t address, struct arm_instruction *instruction)
2328 {
2329 uint32_t immediate;
2330 uint8_t Rd = (opcode >> 8) & 0x7;
2331
2332 instruction->type = ARM_LDR;
2333 immediate = opcode & 0x000000ff;
2334 immediate *= 4;
2335
2336 instruction->info.load_store.Rd = Rd;
2337 instruction->info.load_store.Rn = 15 /*PC*/;
2338 instruction->info.load_store.index_mode = 0; /*offset*/
2339 instruction->info.load_store.offset_mode = 0; /*immediate*/
2340 instruction->info.load_store.offset.offset = immediate;
2341
2342 snprintf(instruction->text, 128,
2343 "0x%8.8" PRIx32 " 0x%4.4x \t"
2344 "LDR\tr%i, [pc, #%#" PRIx32 "]\t; %#8.8" PRIx32,
2345 address, opcode, Rd, immediate,
2346 thumb_alignpc4(address) + immediate);
2347
2348 return ERROR_OK;
2349 }
2350
2351 static int evaluate_load_store_reg_thumb(uint16_t opcode,
2352 uint32_t address, struct arm_instruction *instruction)
2353 {
2354 uint8_t Rd = (opcode >> 0) & 0x7;
2355 uint8_t Rn = (opcode >> 3) & 0x7;
2356 uint8_t Rm = (opcode >> 6) & 0x7;
2357 uint8_t opc = (opcode >> 9) & 0x7;
2358 char *mnemonic = NULL;
2359
2360 switch (opc) {
2361 case 0:
2362 instruction->type = ARM_STR;
2363 mnemonic = "STR";
2364 break;
2365 case 1:
2366 instruction->type = ARM_STRH;
2367 mnemonic = "STRH";
2368 break;
2369 case 2:
2370 instruction->type = ARM_STRB;
2371 mnemonic = "STRB";
2372 break;
2373 case 3:
2374 instruction->type = ARM_LDRSB;
2375 mnemonic = "LDRSB";
2376 break;
2377 case 4:
2378 instruction->type = ARM_LDR;
2379 mnemonic = "LDR";
2380 break;
2381 case 5:
2382 instruction->type = ARM_LDRH;
2383 mnemonic = "LDRH";
2384 break;
2385 case 6:
2386 instruction->type = ARM_LDRB;
2387 mnemonic = "LDRB";
2388 break;
2389 case 7:
2390 instruction->type = ARM_LDRSH;
2391 mnemonic = "LDRSH";
2392 break;
2393 }
2394
2395 snprintf(instruction->text, 128,
2396 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [r%i, r%i]",
2397 address, opcode, mnemonic, Rd, Rn, Rm);
2398
2399 instruction->info.load_store.Rd = Rd;
2400 instruction->info.load_store.Rn = Rn;
2401 instruction->info.load_store.index_mode = 0; /*offset*/
2402 instruction->info.load_store.offset_mode = 1; /*register*/
2403 instruction->info.load_store.offset.reg.Rm = Rm;
2404
2405 return ERROR_OK;
2406 }
2407
2408 static int evaluate_load_store_imm_thumb(uint16_t opcode,
2409 uint32_t address, struct arm_instruction *instruction)
2410 {
2411 uint32_t offset = (opcode >> 6) & 0x1f;
2412 uint8_t Rd = (opcode >> 0) & 0x7;
2413 uint8_t Rn = (opcode >> 3) & 0x7;
2414 uint32_t L = opcode & (1 << 11);
2415 uint32_t B = opcode & (1 << 12);
2416 char *mnemonic;
2417 char suffix = ' ';
2418 uint32_t shift = 2;
2419
2420 if (L) {
2421 instruction->type = ARM_LDR;
2422 mnemonic = "LDR";
2423 } else {
2424 instruction->type = ARM_STR;
2425 mnemonic = "STR";
2426 }
2427
2428 if ((opcode&0xF000) == 0x8000) {
2429 suffix = 'H';
2430 shift = 1;
2431 } else if (B) {
2432 suffix = 'B';
2433 shift = 0;
2434 }
2435
2436 snprintf(instruction->text, 128,
2437 "0x%8.8" PRIx32 " 0x%4.4x \t%s%c\tr%i, [r%i, #%#" PRIx32 "]",
2438 address, opcode, mnemonic, suffix, Rd, Rn, offset << shift);
2439
2440 instruction->info.load_store.Rd = Rd;
2441 instruction->info.load_store.Rn = Rn;
2442 instruction->info.load_store.index_mode = 0; /*offset*/
2443 instruction->info.load_store.offset_mode = 0; /*immediate*/
2444 instruction->info.load_store.offset.offset = offset << shift;
2445
2446 return ERROR_OK;
2447 }
2448
2449 static int evaluate_load_store_stack_thumb(uint16_t opcode,
2450 uint32_t address, struct arm_instruction *instruction)
2451 {
2452 uint32_t offset = opcode & 0xff;
2453 uint8_t Rd = (opcode >> 8) & 0x7;
2454 uint32_t L = opcode & (1 << 11);
2455 char *mnemonic;
2456
2457 if (L) {
2458 instruction->type = ARM_LDR;
2459 mnemonic = "LDR";
2460 } else {
2461 instruction->type = ARM_STR;
2462 mnemonic = "STR";
2463 }
2464
2465 snprintf(instruction->text, 128,
2466 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [SP, #%#" PRIx32 "]",
2467 address, opcode, mnemonic, Rd, offset*4);
2468
2469 instruction->info.load_store.Rd = Rd;
2470 instruction->info.load_store.Rn = 13 /*SP*/;
2471 instruction->info.load_store.index_mode = 0; /*offset*/
2472 instruction->info.load_store.offset_mode = 0; /*immediate*/
2473 instruction->info.load_store.offset.offset = offset*4;
2474
2475 return ERROR_OK;
2476 }
2477
2478 static int evaluate_add_sp_pc_thumb(uint16_t opcode,
2479 uint32_t address, struct arm_instruction *instruction)
2480 {
2481 uint32_t imm = opcode & 0xff;
2482 uint8_t Rd = (opcode >> 8) & 0x7;
2483 uint8_t Rn;
2484 uint32_t SP = opcode & (1 << 11);
2485 const char *reg_name;
2486
2487 instruction->type = ARM_ADD;
2488
2489 if (SP) {
2490 reg_name = "SP";
2491 Rn = 13;
2492 } else {
2493 reg_name = "PC";
2494 Rn = 15;
2495 }
2496
2497 snprintf(instruction->text, 128,
2498 "0x%8.8" PRIx32 " 0x%4.4x \tADD\tr%i, %s, #%#" PRIx32,
2499 address, opcode, Rd, reg_name, imm * 4);
2500
2501 instruction->info.data_proc.variant = 0 /* immediate */;
2502 instruction->info.data_proc.Rd = Rd;
2503 instruction->info.data_proc.Rn = Rn;
2504 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
2505
2506 return ERROR_OK;
2507 }
2508
2509 static int evaluate_adjust_stack_thumb(uint16_t opcode,
2510 uint32_t address, struct arm_instruction *instruction)
2511 {
2512 uint32_t imm = opcode & 0x7f;
2513 uint8_t opc = opcode & (1 << 7);
2514 char *mnemonic;
2515
2516
2517 if (opc) {
2518 instruction->type = ARM_SUB;
2519 mnemonic = "SUB";
2520 } else {
2521 instruction->type = ARM_ADD;
2522 mnemonic = "ADD";
2523 }
2524
2525 snprintf(instruction->text, 128,
2526 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tSP, #%#" PRIx32,
2527 address, opcode, mnemonic, imm*4);
2528
2529 instruction->info.data_proc.variant = 0 /* immediate */;
2530 instruction->info.data_proc.Rd = 13 /*SP*/;
2531 instruction->info.data_proc.Rn = 13 /*SP*/;
2532 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
2533
2534 return ERROR_OK;
2535 }
2536
2537 static int evaluate_breakpoint_thumb(uint16_t opcode,
2538 uint32_t address, struct arm_instruction *instruction)
2539 {
2540 uint32_t imm = opcode & 0xff;
2541
2542 instruction->type = ARM_BKPT;
2543
2544 snprintf(instruction->text, 128,
2545 "0x%8.8" PRIx32 " 0x%4.4x \tBKPT\t%#2.2" PRIx32 "",
2546 address, opcode, imm);
2547
2548 return ERROR_OK;
2549 }
2550
2551 static int evaluate_load_store_multiple_thumb(uint16_t opcode,
2552 uint32_t address, struct arm_instruction *instruction)
2553 {
2554 uint32_t reg_list = opcode & 0xff;
2555 uint32_t L = opcode & (1 << 11);
2556 uint32_t R = opcode & (1 << 8);
2557 uint8_t Rn = (opcode >> 8) & 7;
2558 uint8_t addr_mode = 0 /* IA */;
2559 char reg_names[40];
2560 char *reg_names_p;
2561 char *mnemonic;
2562 char ptr_name[7] = "";
2563 int i;
2564
2565 /* REVISIT: in ThumbEE mode, there are no LDM or STM instructions.
2566 * The STMIA and LDMIA opcodes are used for other instructions.
2567 */
2568
2569 if ((opcode & 0xf000) == 0xc000) { /* generic load/store multiple */
2570 char *wback = "!";
2571
2572 if (L) {
2573 instruction->type = ARM_LDM;
2574 mnemonic = "LDM";
2575 if (opcode & (1 << Rn))
2576 wback = "";
2577 } else {
2578 instruction->type = ARM_STM;
2579 mnemonic = "STM";
2580 }
2581 snprintf(ptr_name, sizeof ptr_name, "r%i%s, ", Rn, wback);
2582 } else {/* push/pop */
2583 Rn = 13;/* SP */
2584 if (L) {
2585 instruction->type = ARM_LDM;
2586 mnemonic = "POP";
2587 if (R)
2588 reg_list |= (1 << 15) /*PC*/;
2589 } else {
2590 instruction->type = ARM_STM;
2591 mnemonic = "PUSH";
2592 addr_mode = 3; /*DB*/
2593 if (R)
2594 reg_list |= (1 << 14) /*LR*/;
2595 }
2596 }
2597
2598 reg_names_p = reg_names;
2599 for (i = 0; i <= 15; i++) {
2600 if (reg_list & (1 << i))
2601 reg_names_p += snprintf(reg_names_p,
2602 (reg_names + 40 - reg_names_p),
2603 "r%i, ",
2604 i);
2605 }
2606 if (reg_names_p > reg_names)
2607 reg_names_p[-2] = '\0';
2608 else /* invalid op : no registers */
2609 reg_names[0] = '\0';
2610
2611 snprintf(instruction->text, 128,
2612 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%s{%s}",
2613 address, opcode, mnemonic, ptr_name, reg_names);
2614
2615 instruction->info.load_store_multiple.register_list = reg_list;
2616 instruction->info.load_store_multiple.Rn = Rn;
2617 instruction->info.load_store_multiple.addressing_mode = addr_mode;
2618
2619 return ERROR_OK;
2620 }
2621
2622 static int evaluate_cond_branch_thumb(uint16_t opcode,
2623 uint32_t address, struct arm_instruction *instruction)
2624 {
2625 uint32_t offset = opcode & 0xff;
2626 uint8_t cond = (opcode >> 8) & 0xf;
2627 uint32_t target_address;
2628
2629 if (cond == 0xf) {
2630 instruction->type = ARM_SWI;
2631 snprintf(instruction->text, 128,
2632 "0x%8.8" PRIx32 " 0x%4.4x \tSVC\t%#2.2" PRIx32,
2633 address, opcode, offset);
2634 return ERROR_OK;
2635 } else if (cond == 0xe) {
2636 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2637 snprintf(instruction->text, 128,
2638 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2639 address, opcode);
2640 return ERROR_OK;
2641 }
2642
2643 /* sign extend 8-bit offset */
2644 if (offset & 0x00000080)
2645 offset = 0xffffff00 | offset;
2646
2647 target_address = address + 4 + (offset << 1);
2648
2649 snprintf(instruction->text, 128,
2650 "0x%8.8" PRIx32 " 0x%4.4x \tB%s\t%#8.8" PRIx32,
2651 address, opcode,
2652 arm_condition_strings[cond], target_address);
2653
2654 instruction->type = ARM_B;
2655 instruction->info.b_bl_bx_blx.reg_operand = -1;
2656 instruction->info.b_bl_bx_blx.target_address = target_address;
2657
2658 return ERROR_OK;
2659 }
2660
2661 static int evaluate_cb_thumb(uint16_t opcode, uint32_t address,
2662 struct arm_instruction *instruction)
2663 {
2664 unsigned offset;
2665
2666 /* added in Thumb2 */
2667 offset = (opcode >> 3) & 0x1f;
2668 offset |= (opcode & 0x0200) >> 4;
2669
2670 snprintf(instruction->text, 128,
2671 "0x%8.8" PRIx32 " 0x%4.4x \tCB%sZ\tr%d, %#8.8" PRIx32,
2672 address, opcode,
2673 (opcode & 0x0800) ? "N" : "",
2674 opcode & 0x7, address + 4 + (offset << 1));
2675
2676 return ERROR_OK;
2677 }
2678
2679 static int evaluate_extend_thumb(uint16_t opcode, uint32_t address,
2680 struct arm_instruction *instruction)
2681 {
2682 /* added in ARMv6 */
2683 snprintf(instruction->text, 128,
2684 "0x%8.8" PRIx32 " 0x%4.4x \t%cXT%c\tr%d, r%d",
2685 address, opcode,
2686 (opcode & 0x0080) ? 'U' : 'S',
2687 (opcode & 0x0040) ? 'B' : 'H',
2688 opcode & 0x7, (opcode >> 3) & 0x7);
2689
2690 return ERROR_OK;
2691 }
2692
2693 static int evaluate_cps_thumb(uint16_t opcode, uint32_t address,
2694 struct arm_instruction *instruction)
2695 {
2696 /* added in ARMv6 */
2697 if ((opcode & 0x0ff0) == 0x0650)
2698 snprintf(instruction->text, 128,
2699 "0x%8.8" PRIx32 " 0x%4.4x \tSETEND %s",
2700 address, opcode,
2701 (opcode & 0x80) ? "BE" : "LE");
2702 else /* ASSUME (opcode & 0x0fe0) == 0x0660 */
2703 snprintf(instruction->text, 128,
2704 "0x%8.8" PRIx32 " 0x%4.4x \tCPSI%c\t%s%s%s",
2705 address, opcode,
2706 (opcode & 0x0010) ? 'D' : 'E',
2707 (opcode & 0x0004) ? "A" : "",
2708 (opcode & 0x0002) ? "I" : "",
2709 (opcode & 0x0001) ? "F" : "");
2710
2711 return ERROR_OK;
2712 }
2713
2714 static int evaluate_byterev_thumb(uint16_t opcode, uint32_t address,
2715 struct arm_instruction *instruction)
2716 {
2717 char *suffix;
2718
2719 /* added in ARMv6 */
2720 switch ((opcode >> 6) & 3) {
2721 case 0:
2722 suffix = "";
2723 break;
2724 case 1:
2725 suffix = "16";
2726 break;
2727 default:
2728 suffix = "SH";
2729 break;
2730 }
2731 snprintf(instruction->text, 128,
2732 "0x%8.8" PRIx32 " 0x%4.4x \tREV%s\tr%d, r%d",
2733 address, opcode, suffix,
2734 opcode & 0x7, (opcode >> 3) & 0x7);
2735
2736 return ERROR_OK;
2737 }
2738
2739 static int evaluate_hint_thumb(uint16_t opcode, uint32_t address,
2740 struct arm_instruction *instruction)
2741 {
2742 char *hint;
2743
2744 switch ((opcode >> 4) & 0x0f) {
2745 case 0:
2746 hint = "NOP";
2747 break;
2748 case 1:
2749 hint = "YIELD";
2750 break;
2751 case 2:
2752 hint = "WFE";
2753 break;
2754 case 3:
2755 hint = "WFI";
2756 break;
2757 case 4:
2758 hint = "SEV";
2759 break;
2760 default:
2761 hint = "HINT (UNRECOGNIZED)";
2762 break;
2763 }
2764
2765 snprintf(instruction->text, 128,
2766 "0x%8.8" PRIx32 " 0x%4.4x \t%s",
2767 address, opcode, hint);
2768
2769 return ERROR_OK;
2770 }
2771
2772 static int evaluate_ifthen_thumb(uint16_t opcode, uint32_t address,
2773 struct arm_instruction *instruction)
2774 {
2775 unsigned cond = (opcode >> 4) & 0x0f;
2776 char *x = "", *y = "", *z = "";
2777
2778 if (opcode & 0x01)
2779 z = (opcode & 0x02) ? "T" : "E";
2780 if (opcode & 0x03)
2781 y = (opcode & 0x04) ? "T" : "E";
2782 if (opcode & 0x07)
2783 x = (opcode & 0x08) ? "T" : "E";
2784
2785 snprintf(instruction->text, 128,
2786 "0x%8.8" PRIx32 " 0x%4.4x \tIT%s%s%s\t%s",
2787 address, opcode,
2788 x, y, z, arm_condition_strings[cond]);
2789
2790 /* NOTE: strictly speaking, the next 1-4 instructions should
2791 * now be displayed with the relevant conditional suffix...
2792 */
2793
2794 return ERROR_OK;
2795 }
2796
2797 int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
2798 {
2799 /* clear fields, to avoid confusion */
2800 memset(instruction, 0, sizeof(struct arm_instruction));
2801 instruction->opcode = opcode;
2802 instruction->instruction_size = 2;
2803
2804 if ((opcode & 0xe000) == 0x0000) {
2805 /* add/substract register or immediate */
2806 if ((opcode & 0x1800) == 0x1800)
2807 return evaluate_add_sub_thumb(opcode, address, instruction);
2808 /* shift by immediate */
2809 else
2810 return evaluate_shift_imm_thumb(opcode, address, instruction);
2811 }
2812
2813 /* Add/substract/compare/move immediate */
2814 if ((opcode & 0xe000) == 0x2000)
2815 return evaluate_data_proc_imm_thumb(opcode, address, instruction);
2816
2817 /* Data processing instructions */
2818 if ((opcode & 0xf800) == 0x4000)
2819 return evaluate_data_proc_thumb(opcode, address, instruction);
2820
2821 /* Load from literal pool */
2822 if ((opcode & 0xf800) == 0x4800)
2823 return evaluate_load_literal_thumb(opcode, address, instruction);
2824
2825 /* Load/Store register offset */
2826 if ((opcode & 0xf000) == 0x5000)
2827 return evaluate_load_store_reg_thumb(opcode, address, instruction);
2828
2829 /* Load/Store immediate offset */
2830 if (((opcode & 0xe000) == 0x6000)
2831 || ((opcode & 0xf000) == 0x8000))
2832 return evaluate_load_store_imm_thumb(opcode, address, instruction);
2833
2834 /* Load/Store from/to stack */
2835 if ((opcode & 0xf000) == 0x9000)
2836 return evaluate_load_store_stack_thumb(opcode, address, instruction);
2837
2838 /* Add to SP/PC */
2839 if ((opcode & 0xf000) == 0xa000)
2840 return evaluate_add_sp_pc_thumb(opcode, address, instruction);
2841
2842 /* Misc */
2843 if ((opcode & 0xf000) == 0xb000) {
2844 switch ((opcode >> 8) & 0x0f) {
2845 case 0x0:
2846 return evaluate_adjust_stack_thumb(opcode, address, instruction);
2847 case 0x1:
2848 case 0x3:
2849 case 0x9:
2850 case 0xb:
2851 return evaluate_cb_thumb(opcode, address, instruction);
2852 case 0x2:
2853 return evaluate_extend_thumb(opcode, address, instruction);
2854 case 0x4:
2855 case 0x5:
2856 case 0xc:
2857 case 0xd:
2858 return evaluate_load_store_multiple_thumb(opcode, address,
2859 instruction);
2860 case 0x6:
2861 return evaluate_cps_thumb(opcode, address, instruction);
2862 case 0xa:
2863 if ((opcode & 0x00c0) == 0x0080)
2864 break;
2865 return evaluate_byterev_thumb(opcode, address, instruction);
2866 case 0xe:
2867 return evaluate_breakpoint_thumb(opcode, address, instruction);
2868 case 0xf:
2869 if (opcode & 0x000f)
2870 return evaluate_ifthen_thumb(opcode, address,
2871 instruction);
2872 else
2873 return evaluate_hint_thumb(opcode, address,
2874 instruction);
2875 }
2876
2877 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2878 snprintf(instruction->text, 128,
2879 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2880 address, opcode);
2881 return ERROR_OK;
2882 }
2883
2884 /* Load/Store multiple */
2885 if ((opcode & 0xf000) == 0xc000)
2886 return evaluate_load_store_multiple_thumb(opcode, address, instruction);
2887
2888 /* Conditional branch + SWI */
2889 if ((opcode & 0xf000) == 0xd000)
2890 return evaluate_cond_branch_thumb(opcode, address, instruction);
2891
2892 if ((opcode & 0xe000) == 0xe000) {
2893 /* Undefined instructions */
2894 if ((opcode & 0xf801) == 0xe801) {
2895 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2896 snprintf(instruction->text, 128,
2897 "0x%8.8" PRIx32 " 0x%8.8x\t"
2898 "UNDEFINED INSTRUCTION",
2899 address, opcode);
2900 return ERROR_OK;
2901 } else /* Branch to offset */
2902 return evaluate_b_bl_blx_thumb(opcode, address, instruction);
2903 }
2904
2905 LOG_ERROR("Thumb: should never reach this point (opcode=%04x)", opcode);
2906 return -1;
2907 }
2908
2909 static int t2ev_b_bl(uint32_t opcode, uint32_t address,
2910 struct arm_instruction *instruction, char *cp)
2911 {
2912 unsigned offset;
2913 unsigned b21 = 1 << 21;
2914 unsigned b22 = 1 << 22;
2915
2916 /* instead of combining two smaller 16-bit branch instructions,
2917 * Thumb2 uses only one larger 32-bit instruction.
2918 */
2919 offset = opcode & 0x7ff;
2920 offset |= (opcode & 0x03ff0000) >> 5;
2921 if (opcode & (1 << 26)) {
2922 offset |= 0xff << 23;
2923 if ((opcode & (1 << 11)) == 0)
2924 b21 = 0;
2925 if ((opcode & (1 << 13)) == 0)
2926 b22 = 0;
2927 } else {
2928 if (opcode & (1 << 11))
2929 b21 = 0;
2930 if (opcode & (1 << 13))
2931 b22 = 0;
2932 }
2933 offset |= b21;
2934 offset |= b22;
2935
2936
2937 address += 4;
2938 address += offset << 1;
2939
2940 char *inst;
2941 switch ((opcode >> 12) & 0x5) {
2942 case 0x1:
2943 inst = "B.W";
2944 instruction->type = ARM_B;
2945 break;
2946 case 0x4:
2947 inst = "BLX";
2948 instruction->type = ARM_BLX;
2949 break;
2950 case 0x5:
2951 inst = "BL";
2952 instruction->type = ARM_BL;
2953 break;
2954 default:
2955 return ERROR_COMMAND_SYNTAX_ERROR;
2956 }
2957 instruction->info.b_bl_bx_blx.reg_operand = -1;
2958 instruction->info.b_bl_bx_blx.target_address = address;
2959 sprintf(cp, "%s\t%#8.8" PRIx32, inst, address);
2960
2961 return ERROR_OK;
2962 }
2963
2964 static int t2ev_cond_b(uint32_t opcode, uint32_t address,
2965 struct arm_instruction *instruction, char *cp)
2966 {
2967 unsigned offset;
2968 unsigned b17 = 1 << 17;
2969 unsigned b18 = 1 << 18;
2970 unsigned cond = (opcode >> 22) & 0x0f;
2971
2972 offset = opcode & 0x7ff;
2973 offset |= (opcode & 0x003f0000) >> 5;
2974 if (opcode & (1 << 26)) {
2975 offset |= 0x1fff << 19;
2976 if ((opcode & (1 << 11)) == 0)
2977 b17 = 0;
2978 if ((opcode & (1 << 13)) == 0)
2979 b18 = 0;
2980 } else {
2981 if (opcode & (1 << 11))
2982 b17 = 0;
2983 if (opcode & (1 << 13))
2984 b18 = 0;
2985 }
2986 offset |= b17;
2987 offset |= b18;
2988
2989 address += 4;
2990 address += offset << 1;
2991
2992 instruction->type = ARM_B;
2993 instruction->info.b_bl_bx_blx.reg_operand = -1;
2994 instruction->info.b_bl_bx_blx.target_address = address;
2995 sprintf(cp, "B%s.W\t%#8.8" PRIx32,
2996 arm_condition_strings[cond],
2997 address);
2998
2999 return ERROR_OK;
3000 }
3001
3002 static const char *special_name(int number)
3003 {
3004 char *special = "(RESERVED)";
3005
3006 switch (number) {
3007 case 0:
3008 special = "apsr";
3009 break;
3010 case 1:
3011 special = "iapsr";
3012 break;
3013 case 2:
3014 special = "eapsr";
3015 break;
3016 case 3:
3017 special = "xpsr";
3018 break;
3019 case 5:
3020 special = "ipsr";
3021 break;
3022 case 6:
3023 special = "epsr";
3024 break;
3025 case 7:
3026 special = "iepsr";
3027 break;
3028 case 8:
3029 special = "msp";
3030 break;
3031 case 9:
3032 special = "psp";
3033 break;
3034 case 16:
3035 special = "primask";
3036 break;
3037 case 17:
3038 special = "basepri";
3039 break;
3040 case 18:
3041 special = "basepri_max";
3042 break;
3043 case 19:
3044 special = "faultmask";
3045 break;
3046 case 20:
3047 special = "control";
3048 break;
3049 }
3050 return special;
3051 }
3052
3053 static int t2ev_hint(uint32_t opcode, uint32_t address,
3054 struct arm_instruction *instruction, char *cp)
3055 {
3056 const char *mnemonic;
3057
3058 if (opcode & 0x0700) {
3059 instruction->type = ARM_UNDEFINED_INSTRUCTION;
3060 strcpy(cp, "UNDEFINED");
3061 return ERROR_OK;
3062 }
3063
3064 if (opcode & 0x00f0) {
3065 sprintf(cp, "DBG\t#%d", (int) opcode & 0xf);
3066 return ERROR_OK;
3067 }
3068
3069 switch (opcode & 0x0f) {
3070 case 0:
3071 mnemonic = "NOP.W";
3072 break;
3073 case 1:
3074 mnemonic = "YIELD.W";
3075 break;
3076 case 2:
3077 mnemonic = "WFE.W";
3078 break;
3079 case 3:
3080 mnemonic = "WFI.W";
3081 break;
3082 case 4:
3083 mnemonic = "SEV.W";
3084 break;
3085 default:
3086 mnemonic = "HINT.W (UNRECOGNIZED)";
3087 break;
3088 }
3089 strcpy(cp, mnemonic);
3090 return ERROR_OK;
3091 }
3092
3093 static int t2ev_misc(uint32_t opcode, uint32_t address,
3094 struct arm_instruction *instruction, char *cp)
3095 {
3096 const char *mnemonic;
3097
3098 switch ((opcode >> 4) & 0x0f) {
3099 case 0:
3100 mnemonic = "LEAVEX";
3101 break;
3102 case 1:
3103 mnemonic = "ENTERX";
3104 break;
3105 case 2:
3106 mnemonic = "CLREX";
3107 break;
3108 case 4:
3109 mnemonic = "DSB";
3110 break;
3111 case 5:
3112 mnemonic = "DMB";
3113 break;
3114 case 6:
3115 mnemonic = "ISB";
3116 break;
3117 default:
3118 return ERROR_COMMAND_SYNTAX_ERROR;
3119 }
3120 strcpy(cp, mnemonic);
3121 return ERROR_OK;
3122 }
3123
3124 static int t2ev_b_misc(uint32_t opcode, uint32_t address,
3125 struct arm_instruction *instruction, char *cp)
3126 {
3127 /* permanently undefined */
3128 if ((opcode & 0x07f07000) == 0x07f02000) {
3129 instruction->type = ARM_UNDEFINED_INSTRUCTION;
3130 strcpy(cp, "UNDEFINED");
3131 return ERROR_OK;
3132 }
3133
3134 switch ((opcode >> 12) & 0x5) {
3135 case 0x1:
3136 case 0x4:
3137 case 0x5:
3138 return t2ev_b_bl(opcode, address, instruction, cp);
3139 case 0:
3140 if (((opcode >> 23) & 0x07) != 0x07)
3141 return t2ev_cond_b(opcode, address, instruction, cp);
3142 if (opcode & (1 << 26))
3143 goto undef;
3144 break;
3145 }
3146
3147 switch ((opcode >> 20) & 0x7f) {
3148 case 0x38:
3149 case 0x39:
3150 sprintf(cp, "MSR\t%s, r%d", special_name(opcode & 0xff),
3151 (int) (opcode >> 16) & 0x0f);
3152 return ERROR_OK;
3153 case 0x3a:
3154 return t2ev_hint(opcode, address, instruction, cp);
3155 case 0x3b:
3156 return t2ev_misc(opcode, address, instruction, cp);
3157 case 0x3c:
3158 sprintf(cp, "BXJ\tr%d", (int) (opcode >> 16) & 0x0f);
3159 return ERROR_OK;
3160 case 0x3e:
3161 case 0x3f:
3162 sprintf(cp, "MRS\tr%d, %s", (int) (opcode >> 8) & 0x0f,
3163 special_name(opcode & 0xff));
3164 return ERROR_OK;
3165 }
3166
3167 undef:
3168 return ERROR_COMMAND_SYNTAX_ERROR;
3169 }
3170
3171 static int t2ev_data_mod_immed(uint32_t opcode, uint32_t address,
3172 struct arm_instruction *instruction, char *cp)
3173 {
3174 char *mnemonic = NULL;
3175 int rn = (opcode >> 16) & 0xf;
3176 int rd = (opcode >> 8) & 0xf;
3177 unsigned immed = opcode & 0xff;
3178 unsigned func;
3179 bool one = false;
3180 char *suffix = "";
3181 char *suffix2 = "";
3182
3183 /* ARMv7-M: A5.3.2 Modified immediate constants */
3184 func = (opcode >> 11) & 0x0e;
3185 if (immed & 0x80)
3186 func |= 1;
3187 if (opcode & (1 << 26))
3188 func |= 0x10;
3189
3190 /* "Modified" immediates */
3191 switch (func >> 1) {
3192 case 0:
3193 break;
3194 case 2:
3195 immed <<= 8;
3196 /* FALLTHROUGH */
3197 case 1:
3198 immed += immed << 16;
3199 break;
3200 case 3:
3201 immed += immed << 8;
3202 immed += immed << 16;
3203 break;
3204 default:
3205 immed |= 0x80;
3206 immed = ror(immed, func);
3207 }
3208
3209 if (opcode & (1 << 20))
3210 suffix = "S";
3211
3212 switch ((opcode >> 21) & 0xf) {
3213 case 0:
3214 if (rd == 0xf) {
3215 instruction->type = ARM_TST;
3216 mnemonic = "TST";
3217 one = true;
3218 suffix = "";
3219 rd = rn;
3220 } else {
3221 instruction->type = ARM_AND;
3222 mnemonic = "AND";
3223 }
3224 break;
3225 case 1:
3226 instruction->type = ARM_BIC;
3227 mnemonic = "BIC";
3228 break;
3229 case 2:
3230 if (rn == 0xf) {
3231 instruction->type = ARM_MOV;
3232 mnemonic = "MOV";
3233 one = true;
3234 suffix2 = ".W";
3235 } else {
3236 instruction->type = ARM_ORR;
3237 mnemonic = "ORR";
3238 }
3239 break;
3240 case 3:
3241 if (rn == 0xf) {
3242 instruction->type = ARM_MVN;
3243 mnemonic = "MVN";
3244 one = true;
3245 } else {
3246 /* instruction->type = ARM_ORN; */
3247 mnemonic = "ORN";
3248 }
3249 break;
3250 case 4:
3251 if (rd == 0xf) {
3252 instruction->type = ARM_TEQ;
3253 mnemonic = "TEQ";
3254 one = true;
3255 suffix = "";
3256 rd = rn;
3257 } else {
3258 instruction->type = ARM_EOR;
3259 mnemonic = "EOR";
3260 }
3261 break;
3262 case 8:
3263 if (rd == 0xf) {
3264 instruction->type = ARM_CMN;
3265 mnemonic = "CMN";
3266 one = true;
3267 suffix = "";
3268 rd = rn;
3269 } else {
3270 instruction->type = ARM_ADD;
3271 mnemonic = "ADD";
3272 suffix2 = ".W";
3273 }
3274 break;
3275 case 10:
3276 instruction->type = ARM_ADC;
3277 mnemonic = "ADC";
3278 suffix2 = ".W";
3279 break;
3280 case 11:
3281 instruction->type = ARM_SBC;
3282 mnemonic = "SBC";
3283 break;
3284 case 13:
3285 if (rd == 0xf) {
3286 instruction->type = ARM_CMP;
3287 mnemonic = "CMP";
3288 one = true;
3289 suffix = "";
3290 rd = rn;
3291 } else {
3292 instruction->type = ARM_SUB;
3293 mnemonic = "SUB";
3294 }
3295 suffix2 = ".W";
3296 break;
3297 case 14:
3298 instruction->type = ARM_RSB;
3299 mnemonic = "RSB";
3300 suffix2 = ".W";
3301 break;
3302 default:
3303 return ERROR_COMMAND_SYNTAX_ERROR;
3304 }
3305
3306 if (one)
3307 sprintf(cp, "%s%s\tr%d, #%d\t; %#8.8x",
3308 mnemonic, suffix2, rd, immed, immed);
3309 else
3310 sprintf(cp, "%s%s%s\tr%d, r%d, #%d\t; %#8.8x",
3311 mnemonic, suffix, suffix2,
3312 rd, rn, immed, immed);
3313
3314 return ERROR_OK;
3315 }
3316
3317 static int t2ev_data_immed(uint32_t opcode, uint32_t address,
3318 struct arm_instruction *instruction, char *cp)
3319 {
3320 char *mnemonic = NULL;
3321 int rn = (opcode >> 16) & 0xf;
3322 int rd = (opcode >> 8) & 0xf;
3323 unsigned immed;
3324 bool add = false;
3325 bool is_signed = false;
3326
3327 immed = (opcode & 0x0ff) | ((opcode & 0x7000) >> 4);
3328 if (opcode & (1 << 26))
3329 immed |= (1 << 11);
3330
3331 switch ((opcode >> 20) & 0x1f) {
3332 case 0:
3333 if (rn == 0xf) {
3334 add = true;
3335 goto do_adr;
3336 }
3337 mnemonic = "ADDW";
3338 break;
3339 case 4:
3340 immed |= (opcode >> 4) & 0xf000;
3341 sprintf(cp, "MOVW\tr%d, #%d\t; %#3.3x", rd, immed, immed);
3342 return ERROR_OK;
3343 case 0x0a:
3344 if (rn == 0xf)
3345 goto do_adr;
3346 mnemonic = "SUBW";
3347 break;
3348 case 0x0c:
3349 /* move constant to top 16 bits of register */
3350 immed |= (opcode >> 4) & 0xf000;
3351 sprintf(cp, "MOVT\tr%d, #%d\t; %#4.4x", rd, immed, immed);
3352 return ERROR_OK;
3353 case 0x10:
3354 case 0x12:
3355 is_signed = true;
3356 /* fallthrough */
3357 case 0x18:
3358 case 0x1a:
3359 /* signed/unsigned saturated add */
3360 immed = (opcode >> 6) & 0x03;
3361 immed |= (opcode >> 10) & 0x1c;
3362 sprintf(cp, "%sSAT\tr%d, #%d, r%d, %s #%d\t",
3363 is_signed ? "S" : "U",
3364 rd, (int) (opcode & 0x1f) + is_signed, rn,
3365 (opcode & (1 << 21)) ? "ASR" : "LSL",
3366 immed ? immed : 32);
3367 return ERROR_OK;
3368 case 0x14:
3369 is_signed = true;
3370 /* FALLTHROUGH */
3371 case 0x1c:
3372 /* signed/unsigned bitfield extract */
3373 immed = (opcode >> 6) & 0x03;
3374 immed |= (opcode >> 10) & 0x1c;
3375 sprintf(cp, "%sBFX\tr%d, r%d, #%d, #%d\t",
3376 is_signed ? "S" : "U",
3377 rd, rn, immed,
3378 (int) (opcode & 0x1f) + 1);
3379 return ERROR_OK;
3380 case 0x16:
3381 immed = (opcode >> 6) & 0x03;
3382 immed |= (opcode >> 10) & 0x1c;
3383 if (rn == 0xf) /* bitfield clear */
3384 sprintf(cp, "BFC\tr%d, #%d, #%d\t",
3385 rd, immed,
3386 (int) (opcode & 0x1f) + 1 - immed);
3387 else /* bitfield insert */
3388 sprintf(cp, "BFI\tr%d, r%d, #%d, #%d\t",
3389 rd, rn, immed,
3390 (int) (opcode & 0x1f) + 1 - immed);
3391 return ERROR_OK;
3392 default:
3393 return ERROR_COMMAND_SYNTAX_ERROR;
3394 }
3395
3396 sprintf(cp, "%s\tr%d, r%d, #%d\t; %#3.3x", mnemonic,
3397 rd, rn, immed, immed);
3398 return ERROR_OK;
3399
3400 do_adr:
3401 address = thumb_alignpc4(address);
3402 if (add)
3403 address += immed;
3404 else
3405 address -= immed;
3406 /* REVISIT "ADD/SUB Rd, PC, #const ; 0x..." might be better;
3407 * not hiding the pc-relative stuff will sometimes be useful.
3408 */
3409 sprintf(cp, "ADR.W\tr%d, %#8.8" PRIx32, rd, address);
3410 return ERROR_OK;
3411 }
3412
3413 static int t2ev_store_single(uint32_t opcode, uint32_t address,
3414 struct arm_instruction *instruction, char *cp)
3415 {
3416 unsigned op = (opcode >> 20) & 0xf;
3417 char *size = "";
3418 char *suffix = "";
3419 char *p1 = "";
3420 char *p2 = "]";
3421 unsigned immed;
3422 unsigned rn = (opcode >> 16) & 0x0f;
3423 unsigned rt = (opcode >> 12) & 0x0f;
3424
3425 if (rn == 0xf)
3426 return ERROR_COMMAND_SYNTAX_ERROR;
3427
3428 if (opcode & 0x0800)
3429 op |= 1;
3430 switch (op) {
3431 /* byte */
3432 case 0x8:
3433 case 0x9:
3434 size = "B";
3435 goto imm12;
3436 case 0x1:
3437 size = "B";
3438 goto imm8;
3439 case 0x0:
3440 size = "B";
3441 break;
3442 /* halfword */
3443 case 0xa:
3444 case 0xb:
3445 size = "H";
3446 goto imm12;
3447 case 0x3:
3448 size = "H";
3449 goto imm8;
3450 case 0x2:
3451 size = "H";
3452 break;
3453 /* word */
3454 case 0xc:
3455 case 0xd:
3456 goto imm12;
3457 case 0x5:
3458 goto imm8;
3459 case 0x4:
3460 break;
3461 /* error */
3462 default:
3463 return ERROR_COMMAND_SYNTAX_ERROR;
3464 }
3465
3466 sprintf(cp, "STR%s.W\tr%d, [r%d, r%d, LSL #%d]",
3467 size, rt, rn, (int) opcode & 0x0f,
3468 (int) (opcode >> 4) & 0x03);
3469 return ERROR_OK;
3470
3471 imm12:
3472 immed = opcode & 0x0fff;
3473 sprintf(cp, "STR%s.W\tr%d, [r%d, #%u]\t; %#3.3x",
3474 size, rt, rn, immed, immed);
3475 return ERROR_OK;
3476
3477 imm8:
3478 immed = opcode & 0x00ff;
3479
3480 switch (opcode & 0x700) {
3481 case 0x600:
3482 suffix = "T";
3483 break;
3484 case 0x000:
3485 case 0x200:
3486 return ERROR_COMMAND_SYNTAX_ERROR;
3487 }
3488
3489 /* two indexed modes will write back rn */
3490 if (opcode & 0x100) {
3491 if (opcode & 0x400) /* pre-indexed */
3492 p2 = "]!";
3493 else { /* post-indexed */
3494 p1 = "]";
3495 p2 = "";
3496 }
3497 }
3498
3499 sprintf(cp, "STR%s%s\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
3500 size, suffix, rt, rn, p1,
3501 (opcode & 0x200) ? "" : "-",
3502 immed, p2, immed);
3503 return ERROR_OK;
3504 }
3505
3506 static int t2ev_mul32(uint32_t opcode, uint32_t address,
3507 struct arm_instruction *instruction, char *cp)
3508 {
3509 int ra = (opcode >> 12) & 0xf;
3510
3511 switch (opcode & 0x007000f0) {
3512 case 0:
3513 if (ra == 0xf)
3514 sprintf(cp, "MUL\tr%d, r%d, r%d",
3515 (int) (opcode >> 8) & 0xf,
3516 (int) (opcode >> 16) & 0xf,
3517 (int) (opcode >> 0) & 0xf);
3518 else
3519 sprintf(cp, "MLA\tr%d, r%d, r%d, r%d",
3520 (int) (opcode >> 8) & 0xf,
3521 (int) (opcode >> 16) & 0xf,
3522 (int) (opcode >> 0) & 0xf, ra);
3523 break;
3524 case 0x10:
3525 sprintf(cp, "MLS\tr%d, r%d, r%d, r%d",
3526 (int) (opcode >> 8) & 0xf,
3527 (int) (opcode >> 16) & 0xf,
3528 (int) (opcode >> 0) & 0xf, ra);
3529 break;
3530 default:
3531 return ERROR_COMMAND_SYNTAX_ERROR;
3532 }
3533 return ERROR_OK;
3534 }
3535
3536 static int t2ev_mul64_div(uint32_t opcode, uint32_t address,
3537 struct arm_instruction *instruction, char *cp)
3538 {
3539 int op = (opcode >> 4) & 0xf;
3540 char *infix = "MUL";
3541
3542 op += (opcode >> 16) & 0x70;
3543 switch (op) {
3544 case 0x40:
3545 case 0x60:
3546 infix = "MLA";
3547 /* FALLTHROUGH */
3548 case 0:
3549 case 0x20:
3550 sprintf(cp, "%c%sL\tr%d, r%d, r%d, r%d",
3551 (op & 0x20) ? 'U' : 'S',
3552 infix,
3553 (int) (opcode >> 12) & 0xf,
3554 (int) (opcode >> 8) & 0xf,
3555 (int) (opcode >> 16) & 0xf,
3556 (int) (opcode >> 0) & 0xf);
3557 break;
3558 case 0x1f:
3559 case 0x3f:
3560 sprintf(cp, "%cDIV\tr%d, r%d, r%d",
3561 (op & 0x20) ? 'U' : 'S',
3562 (int) (opcode >> 8) & 0xf,
3563 (int) (opcode >> 16) & 0xf,
3564 (int) (opcode >> 0) & 0xf);
3565 break;
3566 default:
3567 return ERROR_COMMAND_SYNTAX_ERROR;
3568 }
3569
3570 return ERROR_OK;
3571 }
3572
3573 static int t2ev_ldm_stm(uint32_t opcode, uint32_t address,
3574 struct arm_instruction *instruction, char *cp)
3575 {
3576 int rn = (opcode >> 16) & 0xf;
3577 int op = (opcode >> 22) & 0x6;
3578 int t = (opcode >> 21) & 1;
3579 unsigned registers = opcode & 0xffff;
3580 char *mode = "";
3581
3582 if (opcode & (1 << 20))
3583 op |= 1;
3584
3585 switch (op) {
3586 case 0:
3587 mode = "DB";
3588 /* FALL THROUGH */
3589 case 6:
3590 sprintf(cp, "SRS%s\tsp%s, #%d", mode,
3591 t ? "!" : "",
3592 (unsigned) (opcode & 0x1f));
3593 return ERROR_OK;
3594 case 1:
3595 mode = "DB";
3596 /* FALL THROUGH */
3597 case 7:
3598 sprintf(cp, "RFE%s\tr%d%s", mode,
3599 (unsigned) ((opcode >> 16) & 0xf),
3600 t ? "!" : "");
3601 return ERROR_OK;
3602 case 2:
3603 sprintf(cp, "STM.W\tr%d%s, ", rn, t ? "!" : "");
3604 break;
3605 case 3:
3606 if (rn == 13 && t)
3607 sprintf(cp, "POP.W\t");
3608 else
3609 sprintf(cp, "LDM.W\tr%d%s, ", rn, t ? "!" : "");
3610 break;
3611 case 4:
3612 if (rn == 13 && t)
3613 sprintf(cp, "PUSH.W\t");
3614 else
3615 sprintf(cp, "STMDB\tr%d%s, ", rn, t ? "!" : "");
3616 break;
3617 case 5:
3618 sprintf(cp, "LDMDB.W\tr%d%s, ", rn, t ? "!" : "");
3619 break;
3620 default:
3621 return ERROR_COMMAND_SYNTAX_ERROR;
3622 }
3623
3624 cp = strchr(cp, 0);
3625 *cp++ = '{';
3626 for (t = 0; registers; t++, registers >>= 1) {
3627 if ((registers & 1) == 0)
3628 continue;
3629 registers &= ~1;
3630 sprintf(cp, "r%d%s", t, registers ? ", " : "");
3631 cp = strchr(cp, 0);
3632 }
3633 *cp++ = '}';
3634 *cp++ = 0;
3635
3636 return ERROR_OK;
3637 }
3638
3639 /* load/store dual or exclusive, table branch */
3640 static int t2ev_ldrex_strex(uint32_t opcode, uint32_t address,
3641 struct arm_instruction *instruction, char *cp)
3642 {
3643 unsigned op1op2 = (opcode >> 20) & 0x3;
3644 unsigned op3 = (opcode >> 4) & 0xf;
3645 char *mnemonic;
3646 unsigned rn = (opcode >> 16) & 0xf;
3647 unsigned rt = (opcode >> 12) & 0xf;
3648 unsigned rd = (opcode >> 8) & 0xf;
3649 unsigned imm = opcode & 0xff;
3650 char *p1 = "";
3651 char *p2 = "]";
3652
3653 op1op2 |= (opcode >> 21) & 0xc;
3654 switch (op1op2) {
3655 case 0:
3656 mnemonic = "STREX";
3657 goto strex;
3658 case 1:
3659 mnemonic = "LDREX";
3660 goto ldrex;
3661 case 2:
3662 case 6:
3663 case 8:
3664 case 10:
3665 case 12:
3666 case 14:
3667 mnemonic = "STRD";
3668 goto immediate;
3669 case 3:
3670 case 7:
3671 case 9:
3672 case 11:
3673 case 13:
3674 case 15:
3675 mnemonic = "LDRD";
3676 if (rn == 15)
3677 goto literal;
3678 else
3679 goto immediate;
3680 case 4:
3681 switch (op3) {
3682 case 4:
3683 mnemonic = "STREXB";
3684 break;
3685 case 5:
3686 mnemonic = "STREXH";
3687 break;
3688 default:
3689 return ERROR_COMMAND_SYNTAX_ERROR;
3690 }
3691 rd = opcode & 0xf;
3692 imm = 0;
3693 goto strex;
3694 case 5:
3695 switch (op3) {
3696 case 0:
3697 sprintf(cp, "TBB\t[r%u, r%u]", rn, imm & 0xf);
3698 return ERROR_OK;
3699 case 1:
3700 sprintf(cp, "TBH\t[r%u, r%u, LSL #1]", rn, imm & 0xf);
3701 return ERROR_OK;
3702 case 4:
3703 mnemonic = "LDREXB";
3704 break;
3705 case 5:
3706 mnemonic = "LDREXH";
3707 break;
3708 default:
3709 return ERROR_COMMAND_SYNTAX_ERROR;
3710 }
3711 imm = 0;
3712 goto ldrex;
3713 }
3714 return ERROR_COMMAND_SYNTAX_ERROR;
3715
3716 strex:
3717 imm <<= 2;
3718 if (imm)
3719 sprintf(cp, "%s\tr%u, r%u, [r%u, #%u]\t; %#2.2x",
3720 mnemonic, rd, rt, rn, imm, imm);
3721 else
3722 sprintf(cp, "%s\tr%u, r%u, [r%u]",
3723 mnemonic, rd, rt, rn);
3724 return ERROR_OK;
3725
3726 ldrex:
3727 imm <<= 2;
3728 if (imm)
3729 sprintf(cp, "%s\tr%u, [r%u, #%u]\t; %#2.2x",
3730 mnemonic, rt, rn, imm, imm);
3731 else
3732 sprintf(cp, "%s\tr%u, [r%u]",
3733 mnemonic, rt, rn);
3734 return ERROR_OK;
3735
3736 immediate:
3737 /* two indexed modes will write back rn */
3738 if (opcode & (1 << 21)) {
3739 if (opcode & (1 << 24)) /* pre-indexed */
3740 p2 = "]!";
3741 else { /* post-indexed */
3742 p1 = "]";
3743 p2 = "";
3744 }
3745 }
3746
3747 imm <<= 2;
3748 sprintf(cp, "%s\tr%u, r%u, [r%u%s, #%s%u%s\t; %#2.2x",
3749 mnemonic, rt, rd, rn, p1,
3750 (opcode & (1 << 23)) ? "" : "-",
3751 imm, p2, imm);
3752 return ERROR_OK;
3753
3754 literal:
3755 address = thumb_alignpc4(address);
3756 imm <<= 2;
3757 if (opcode & (1 << 23))
3758 address += imm;
3759 else
3760 address -= imm;
3761 sprintf(cp, "%s\tr%u, r%u, %#8.8" PRIx32,
3762 mnemonic, rt, rd, address);
3763 return ERROR_OK;
3764 }
3765
3766 static int t2ev_data_shift(uint32_t opcode, uint32_t address,
3767 struct arm_instruction *instruction, char *cp)
3768 {
3769 int op = (opcode >> 21) & 0xf;
3770 int rd = (opcode >> 8) & 0xf;
3771 int rn = (opcode >> 16) & 0xf;
3772 int type = (opcode >> 4) & 0x3;
3773 int immed = (opcode >> 6) & 0x3;
3774 char *mnemonic;
3775 char *suffix = "";
3776
3777 immed |= (opcode >> 10) & 0x1c;
3778 if (opcode & (1 << 20))
3779 suffix = "S";
3780
3781 switch (op) {
3782 case 0:
3783 if (rd == 0xf) {
3784 if (!(opcode & (1 << 20)))
3785 return ERROR_COMMAND_SYNTAX_ERROR;
3786 instruction->type = ARM_TST;
3787 mnemonic = "TST";
3788 suffix = "";
3789 goto two;
3790 }
3791 instruction->type = ARM_AND;
3792 mnemonic = "AND";
3793 break;
3794 case 1:
3795 instruction->type = ARM_BIC;
3796 mnemonic = "BIC";
3797 break;
3798 case 2:
3799 if (rn == 0xf) {
3800 instruction->type = ARM_MOV;
3801 switch (type) {
3802 case 0:
3803 if (immed == 0) {
3804 sprintf(cp, "MOV%s.W\tr%d, r%d",
3805 suffix, rd,
3806 (int) (opcode & 0xf));
3807 return ERROR_OK;
3808 }
3809 mnemonic = "LSL";
3810 break;
3811 case 1:
3812 mnemonic = "LSR";
3813 break;
3814 case 2:
3815 mnemonic = "ASR";
3816 break;
3817 default:
3818 if (immed == 0) {
3819 sprintf(cp, "RRX%s\tr%d, r%d",
3820 suffix, rd,
3821 (int) (opcode & 0xf));
3822 return ERROR_OK;
3823 }
3824 mnemonic = "ROR";
3825 break;
3826 }
3827 goto immediate;
3828 } else {
3829 instruction->type = ARM_ORR;
3830 mnemonic = "ORR";
3831 }
3832 break;
3833 case 3:
3834 if (rn == 0xf) {
3835 instruction->type = ARM_MVN;
3836 mnemonic = "MVN";
3837 rn = rd;
3838 goto two;
3839 } else {
3840 /* instruction->type = ARM_ORN; */
3841 mnemonic = "ORN";
3842 }
3843 break;
3844 case 4:
3845 if (rd == 0xf) {
3846 if (!(opcode & (1 << 20)))
3847 return ERROR_COMMAND_SYNTAX_ERROR;
3848 instruction->type = ARM_TEQ;
3849 mnemonic = "TEQ";
3850 suffix = "";
3851 goto two;
3852 }
3853 instruction->type = ARM_EOR;
3854 mnemonic = "EOR";
3855 break;
3856 case 8:
3857 if (rd == 0xf) {
3858 if (!(opcode & (1 << 20)))
3859 return ERROR_COMMAND_SYNTAX_ERROR;
3860 instruction->type = ARM_CMN;
3861 mnemonic = "CMN";
3862 suffix = "";
3863 goto two;
3864 }
3865 instruction->type = ARM_ADD;
3866 mnemonic = "ADD";
3867 break;
3868 case 0xa:
3869 instruction->type = ARM_ADC;
3870 mnemonic = "ADC";
3871 break;
3872 case 0xb:
3873 instruction->type = ARM_SBC;
3874 mnemonic = "SBC";
3875 break;
3876 case 0xd:
3877 if (rd == 0xf) {
3878 if (!(opcode & (1 << 21)))
3879 return ERROR_COMMAND_SYNTAX_ERROR;
3880 instruction->type = ARM_CMP;
3881 mnemonic = "CMP";
3882 suffix = "";
3883 goto two;
3884 }
3885 instruction->type = ARM_SUB;
3886 mnemonic = "SUB";
3887 break;
3888 case 0xe:
3889 instruction->type = ARM_RSB;
3890 mnemonic = "RSB";
3891 break;
3892 default:
3893 return ERROR_COMMAND_SYNTAX_ERROR;
3894 }
3895
3896 sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
3897 mnemonic, suffix, rd, rn, (int) (opcode & 0xf));
3898
3899 shift:
3900 cp = strchr(cp, 0);
3901
3902 switch (type) {
3903 case 0:
3904 if (immed == 0)
3905 return ERROR_OK;
3906 suffix = "LSL";
3907 break;
3908 case 1:
3909 suffix = "LSR";
3910 if (immed == 32)
3911 immed = 0;
3912 break;
3913 case 2:
3914 suffix = "ASR";
3915 if (immed == 32)
3916 immed = 0;
3917 break;
3918 case 3:
3919 if (immed == 0) {
3920 strcpy(cp, ", RRX");
3921 return ERROR_OK;
3922 }
3923 suffix = "ROR";
3924 break;
3925 }
3926 sprintf(cp, ", %s #%d", suffix, immed ? immed : 32);
3927 return ERROR_OK;
3928
3929 two:
3930 sprintf(cp, "%s%s.W\tr%d, r%d",
3931 mnemonic, suffix, rn, (int) (opcode & 0xf));
3932 goto shift;
3933
3934 immediate:
3935 sprintf(cp, "%s%s.W\tr%d, r%d, #%d",
3936 mnemonic, suffix, rd,
3937 (int) (opcode & 0xf), immed ? immed : 32);
3938 return ERROR_OK;
3939 }
3940
3941 static int t2ev_data_reg(uint32_t opcode, uint32_t address,
3942 struct arm_instruction *instruction, char *cp)
3943 {
3944 char *mnemonic;
3945 char *suffix = "";
3946
3947 if (((opcode >> 4) & 0xf) == 0) {
3948 switch ((opcode >> 21) & 0x7) {
3949 case 0:
3950 mnemonic = "LSL";
3951 break;
3952 case 1:
3953 mnemonic = "LSR";
3954 break;
3955 case 2:
3956 mnemonic = "ASR";
3957 break;
3958 case 3:
3959 mnemonic = "ROR";
3960 break;
3961 default:
3962 return ERROR_COMMAND_SYNTAX_ERROR;
3963 }
3964
3965 instruction->type = ARM_MOV;
3966 if (opcode & (1 << 20))
3967 suffix = "S";
3968 sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
3969 mnemonic, suffix,
3970 (int) (opcode >> 8) & 0xf,
3971 (int) (opcode >> 16) & 0xf,
3972 (int) (opcode >> 0) & 0xf);
3973
3974 } else if (opcode & (1 << 7)) {
3975 switch ((opcode >> 20) & 0xf) {
3976 case 0:
3977 case 1:
3978 case 4:
3979 case 5:
3980 switch ((opcode >> 4) & 0x3) {
3981 case 1:
3982 suffix = ", ROR #8";
3983 break;
3984 case 2:
3985 suffix = ", ROR #16";
3986 break;
3987 case 3:
3988 suffix = ", ROR #24";
3989 break;
3990 }
3991 sprintf(cp, "%cXT%c.W\tr%d, r%d%s",
3992 (opcode & (1 << 24)) ? 'U' : 'S',
3993 (opcode & (1 << 26)) ? 'B' : 'H',
3994 (int) (opcode >> 8) & 0xf,
3995 (int) (opcode >> 0) & 0xf,
3996 suffix);
3997 break;
3998 case 8:
3999 case 9:
4000 case 0xa:
4001 case 0xb:
4002 if (opcode & (1 << 6))
4003 return ERROR_COMMAND_SYNTAX_ERROR;
4004 if (((opcode >> 12) & 0xf) != 0xf)
4005 return ERROR_COMMAND_SYNTAX_ERROR;
4006 if (!(opcode & (1 << 20)))
4007 return ERROR_COMMAND_SYNTAX_ERROR;
4008
4009 switch (((opcode >> 19) & 0x04)
4010 | ((opcode >> 4) & 0x3)) {
4011 case 0:
4012 mnemonic = "REV.W";
4013 break;
4014 case 1:
4015 mnemonic = "REV16.W";
4016 break;
4017 case 2:
4018 mnemonic = "RBIT";
4019 break;
4020 case 3:
4021 mnemonic = "REVSH.W";
4022 break;
4023 case 4:
4024 mnemonic = "CLZ";
4025 break;
4026 default:
4027 return ERROR_COMMAND_SYNTAX_ERROR;
4028 }
4029 sprintf(cp, "%s\tr%d, r%d",
4030 mnemonic,
4031 (int) (opcode >> 8) & 0xf,
4032 (int) (opcode >> 0) & 0xf);
4033 break;
4034 default:
4035 return ERROR_COMMAND_SYNTAX_ERROR;
4036 }
4037 }
4038
4039 return ERROR_OK;
4040 }
4041
4042 static int t2ev_load_word(uint32_t opcode, uint32_t address,
4043 struct arm_instruction *instruction, char *cp)
4044 {
4045 int rn = (opcode >> 16) & 0xf;
4046 int immed;
4047
4048 instruction->type = ARM_LDR;
4049
4050 if (rn == 0xf) {
4051 immed = opcode & 0x0fff;
4052 if ((opcode & (1 << 23)) == 0)
4053 immed = -immed;
4054 sprintf(cp, "LDR\tr%d, %#8.8" PRIx32,
4055 (int) (opcode >> 12) & 0xf,
4056 thumb_alignpc4(address) + immed);
4057 return ERROR_OK;
4058 }
4059
4060 if (opcode & (1 << 23)) {
4061 immed = opcode & 0x0fff;
4062 sprintf(cp, "LDR.W\tr%d, [r%d, #%d]\t; %#3.3x",
4063 (int) (opcode >> 12) & 0xf,
4064 rn, immed, immed);
4065 return ERROR_OK;
4066 }
4067
4068 if (!(opcode & (0x3f << 6))) {
4069 sprintf(cp, "LDR.W\tr%d, [r%d, r%d, LSL #%d]",
4070 (int) (opcode >> 12) & 0xf,
4071 rn,
4072 (int) (opcode >> 0) & 0xf,
4073 (int) (opcode >> 4) & 0x3);
4074 return ERROR_OK;
4075 }
4076
4077
4078 if (((opcode >> 8) & 0xf) == 0xe) {
4079 immed = opcode & 0x00ff;
4080
4081 sprintf(cp, "LDRT\tr%d, [r%d, #%d]\t; %#2.2x",
4082 (int) (opcode >> 12) & 0xf,
4083 rn, immed, immed);
4084 return ERROR_OK;
4085 }
4086
4087 if (((opcode >> 8) & 0xf) == 0xc || (opcode & 0x0900) == 0x0900) {
4088 char *p1 = "]", *p2 = "";
4089
4090 if (!(opcode & 0x0500))
4091 return ERROR_COMMAND_SYNTAX_ERROR;
4092
4093 immed = opcode & 0x00ff;
4094
4095 /* two indexed modes will write back rn */
4096 if (opcode & 0x100) {
4097 if (opcode & 0x400) /* pre-indexed */
4098 p2 = "]!";
4099 else { /* post-indexed */
4100 p1 = "]";
4101 p2 = "";
4102 }
4103 }
4104
4105 sprintf(cp, "LDR\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
4106 (int) (opcode >> 12) & 0xf,
4107 rn, p1,
4108 (opcode & 0x200) ? "" : "-",
4109 immed, p2, immed);
4110 return ERROR_OK;
4111 }
4112
4113 return ERROR_COMMAND_SYNTAX_ERROR;
4114 }
4115
4116 static int t2ev_load_byte_hints(uint32_t opcode, uint32_t address,
4117 struct arm_instruction *instruction, char *cp)
4118 {
4119 int rn = (opcode >> 16) & 0xf;
4120 int rt = (opcode >> 12) & 0xf;
4121 int op2 = (opcode >> 6) & 0x3f;
4122 unsigned immed;
4123 char *p1 = "", *p2 = "]";
4124 char *mnemonic;
4125
4126 switch ((opcode >> 23) & 0x3) {
4127 case 0:
4128 if ((rn & rt) == 0xf) {
4129 pld_literal:
4130 immed = opcode & 0xfff;
4131 address = thumb_alignpc4(address);
4132 if (opcode & (1 << 23))
4133 address += immed;
4134 else
4135 address -= immed;
4136 sprintf(cp, "PLD\tr%d, %#8.8" PRIx32,
4137 rt, address);
4138 return ERROR_OK;
4139 }
4140 if (rn == 0x0f && rt != 0x0f) {
4141 ldrb_literal:
4142 immed = opcode & 0xfff;
4143 address = thumb_alignpc4(address);
4144 if (opcode & (1 << 23))
4145 address += immed;
4146 else
4147 address -= immed;
4148 sprintf(cp, "LDRB\tr%d, %#8.8" PRIx32,
4149 rt, address);
4150 return ERROR_OK;
4151 }
4152 if (rn == 0x0f)
4153 break;
4154 if ((op2 & 0x3c) == 0x38) {
4155 immed = opcode & 0xff;
4156 sprintf(cp, "LDRBT\tr%d, [r%d, #%d]\t; %#2.2x",
4157 rt, rn, immed, immed);
4158 return ERROR_OK;
4159 }
4160 if ((op2 & 0x3c) == 0x30) {
4161 if (rt == 0x0f) {
4162 immed = opcode & 0xff;
4163 immed = -immed;
4164 preload_immediate:
4165 p1 = (opcode & (1 << 21)) ? "W" : "";
4166 sprintf(cp, "PLD%s\t[r%d, #%d]\t; %#6.6x",
4167 p1, rn, immed, immed);
4168 return ERROR_OK;
4169 }
4170 mnemonic = "LDRB";
4171 ldrxb_immediate_t3:
4172 immed = opcode & 0xff;
4173 if (!(opcode & 0x200))
4174 immed = -immed;
4175
4176 /* two indexed modes will write back rn */
4177 if (opcode & 0x100) {
4178 if (opcode & 0x400) /* pre-indexed */
4179 p2 = "]!";
4180 else { /* post-indexed */
4181 p1 = "]";
4182 p2 = "";
4183 }
4184 }
4185 ldrxb_immediate_t2:
4186 sprintf(cp, "%s\tr%d, [r%d%s, #%d%s\t; %#8.8x",
4187 mnemonic, rt, rn, p1,
4188 immed, p2, immed);
4189 return ERROR_OK;
4190 }
4191 if ((op2 & 0x24) == 0x24) {
4192 mnemonic = "LDRB";
4193 goto ldrxb_immediate_t3;
4194 }
4195 if (op2 == 0) {
4196 int rm = opcode & 0xf;
4197
4198 if (rt == 0x0f)
4199 sprintf(cp, "PLD\t");
4200 else
4201 sprintf(cp, "LDRB.W\tr%d, ", rt);
4202 immed = (opcode >> 4) & 0x3;
4203 cp = strchr(cp, 0);
4204 sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed);
4205 return ERROR_OK;
4206 }
4207 break;
4208 case 1:
4209 if ((rn & rt) == 0xf)
4210 goto pld_literal;
4211 if (rt == 0xf) {
4212 immed = opcode & 0xfff;
4213 goto preload_immediate;
4214 }
4215 if (rn == 0x0f)
4216 goto ldrb_literal;
4217 mnemonic = "LDRB.W";
4218 immed = opcode & 0xfff;
4219 goto ldrxb_immediate_t2;
4220 case 2:
4221 if ((rn & rt) == 0xf) {
4222 immed = opcode & 0xfff;
4223 address = thumb_alignpc4(address);
4224 if (opcode & (1 << 23))
4225 address += immed;
4226 else
4227 address -= immed;
4228 sprintf(cp, "PLI\t%#8.8" PRIx32, address);
4229 return ERROR_OK;
4230 }
4231 if (rn == 0xf && rt != 0xf) {
4232 ldrsb_literal:
4233 immed = opcode & 0xfff;
4234 address = thumb_alignpc4(address);
4235 if (opcode & (1 << 23))
4236 address += immed;
4237 else
4238 address -= immed;
4239 sprintf(cp, "LDRSB\t%#8.8" PRIx32, address);
4240 return ERROR_OK;
4241 }
4242 if (rn == 0xf)
4243 break;
4244 if ((op2 & 0x3c) == 0x38) {
4245 immed = opcode & 0xff;
4246 sprintf(cp, "LDRSBT\tr%d, [r%d, #%d]\t; %#2.2x",
4247 rt, rn, immed, immed);
4248 return ERROR_OK;
4249 }
4250 if ((op2 & 0x3c) == 0x30) {
4251 if (rt == 0xf) {
4252 immed = opcode & 0xff;
4253 immed = -immed; /* pli */
4254 sprintf(cp, "PLI\t[r%d, #%d]\t; -%#2.2x",
4255 rn, immed, -immed);
4256 return ERROR_OK;
4257 }
4258 mnemonic = "LDRSB";
4259 goto ldrxb_immediate_t3;
4260 }
4261 if ((op2 & 0x24) == 0x24) {
4262 mnemonic = "LDRSB";
4263 goto ldrxb_immediate_t3;
4264 }
4265 if (op2 == 0) {
4266 int rm = opcode & 0xf;
4267
4268 if (rt == 0x0f)
4269 sprintf(cp, "PLI\t");
4270 else
4271 sprintf(cp, "LDRSB.W\tr%d, ", rt);
4272 immed = (opcode >> 4) & 0x3;
4273 cp = strchr(cp, 0);
4274 sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed);
4275 return ERROR_OK;
4276 }
4277 break;
4278 case 3:
4279 if (rt == 0xf) {
4280 immed = opcode & 0xfff;
4281 sprintf(cp, "PLI\t[r%d, #%d]\t; %#3.3x",
4282 rn, immed, immed);
4283 return ERROR_OK;
4284 }
4285 if (rn == 0xf)
4286 goto ldrsb_literal;
4287 immed = opcode & 0xfff;
4288 mnemonic = "LDRSB";
4289 goto ldrxb_immediate_t2;
4290 }
4291
4292 return ERROR_COMMAND_SYNTAX_ERROR;
4293 }
4294
4295 static int t2ev_load_halfword(uint32_t opcode, uint32_t address,
4296 struct arm_instruction *instruction, char *cp)
4297 {
4298 int rn = (opcode >> 16) & 0xf;
4299 int rt = (opcode >> 12) & 0xf;
4300 int op2 = (opcode >> 6) & 0x3f;
4301 char *sign = "";
4302 unsigned immed;
4303
4304 if (rt == 0xf) {
4305 sprintf(cp, "HINT (UNALLOCATED)");
4306 return ERROR_OK;
4307 }
4308
4309 if (opcode & (1 << 24))
4310 sign = "S";
4311
4312 if ((opcode & (1 << 23)) == 0) {
4313 if (rn == 0xf) {
4314 ldrh_literal:
4315 immed = opcode & 0xfff;
4316 address = thumb_alignpc4(address);
4317 if (opcode & (1 << 23))
4318 address += immed;
4319 else
4320 address -= immed;
4321 sprintf(cp, "LDR%sH\tr%d, %#8.8" PRIx32,
4322 sign, rt, address);
4323 return ERROR_OK;
4324 }
4325 if (op2 == 0) {
4326 int rm = opcode & 0xf;
4327
4328 immed = (opcode >> 4) & 0x3;
4329 sprintf(cp, "LDR%sH.W\tr%d, [r%d, r%d, LSL #%d]",
4330 sign, rt, rn, rm, immed);
4331 return ERROR_OK;
4332 }
4333 if ((op2 & 0x3c) == 0x38) {
4334 immed = opcode & 0xff;
4335 sprintf(cp, "LDR%sHT\tr%d, [r%d, #%d]\t; %#2.2x",
4336 sign, rt, rn, immed, immed);
4337 return ERROR_OK;
4338 }
4339 if ((op2 & 0x3c) == 0x30 || (op2 & 0x24) == 0x24) {
4340 char *p1 = "", *p2 = "]";
4341
4342 immed = opcode & 0xff;
4343 if (!(opcode & 0x200))
4344 immed = -immed;
4345
4346 /* two indexed modes will write back rn */
4347 if (opcode & 0x100) {
4348 if (opcode & 0x400) /* pre-indexed */
4349 p2 = "]!";
4350 else { /* post-indexed */
4351 p1 = "]";
4352 p2 = "";
4353 }
4354 }
4355 sprintf(cp, "LDR%sH\tr%d, [r%d%s, #%d%s\t; %#8.8x",
4356 sign, rt, rn, p1, immed, p2, immed);
4357 return ERROR_OK;
4358 }
4359 } else {
4360 if (rn == 0xf)
4361 goto ldrh_literal;
4362
4363 immed = opcode & 0xfff;
4364 sprintf(cp, "LDR%sH%s\tr%d, [r%d, #%d]\t; %#6.6x",
4365 sign, *sign ? "" : ".W",
4366 rt, rn, immed, immed);
4367 return ERROR_OK;
4368 }
4369
4370 return ERROR_COMMAND_SYNTAX_ERROR;
4371 }
4372
4373 /*
4374 * REVISIT for Thumb2 instructions, instruction->type and friends aren't
4375 * always set. That means eventual arm_simulate_step() support for Thumb2
4376 * will need work in this area.
4377 */
4378 int thumb2_opcode(struct target *target, uint32_t address, struct arm_instruction *instruction)
4379 {
4380 int retval;
4381 uint16_t op;
4382 uint32_t opcode;
4383 char *cp;
4384
4385 /* clear low bit ... it's set on function pointers */
4386 address &= ~1;
4387
4388 /* clear fields, to avoid confusion */
4389 memset(instruction, 0, sizeof(struct arm_instruction));
4390
4391 /* read first halfword, see if this is the only one */
4392 retval = target_read_u16(target, address, &op);
4393 if (retval != ERROR_OK)
4394 return retval;
4395
4396 switch (op & 0xf800) {
4397 case 0xf800:
4398 case 0xf000:
4399 case 0xe800:
4400 /* 32-bit instructions */
4401 instruction->instruction_size = 4;
4402 opcode = op << 16;
4403 retval = target_read_u16(target, address + 2, &op);
4404 if (retval != ERROR_OK)
4405 return retval;
4406 opcode |= op;
4407 instruction->opcode = opcode;
4408 break;
4409 default:
4410 /* 16-bit: Thumb1 + IT + CBZ/CBNZ + ... */
4411 return thumb_evaluate_opcode(op, address, instruction);
4412 }
4413
4414 snprintf(instruction->text, 128,
4415 "0x%8.8" PRIx32 " 0x%8.8" PRIx32 "\t",
4416 address, opcode);
4417 cp = strchr(instruction->text, 0);
4418 retval = ERROR_FAIL;
4419
4420 /* ARMv7-M: A5.3.1 Data processing (modified immediate) */
4421 if ((opcode & 0x1a008000) == 0x10000000)
4422 retval = t2ev_data_mod_immed(opcode, address, instruction, cp);
4423
4424 /* ARMv7-M: A5.3.3 Data processing (plain binary immediate) */
4425 else if ((opcode & 0x1a008000) == 0x12000000)
4426 retval = t2ev_data_immed(opcode, address, instruction, cp);
4427
4428 /* ARMv7-M: A5.3.4 Branches and miscellaneous control */
4429 else if ((opcode & 0x18008000) == 0x10008000)
4430 retval = t2ev_b_misc(opcode, address, instruction, cp);
4431
4432 /* ARMv7-M: A5.3.5 Load/store multiple */
4433 else if ((opcode & 0x1e400000) == 0x08000000)
4434 retval = t2ev_ldm_stm(opcode, address, instruction, cp);
4435
4436 /* ARMv7-M: A5.3.6 Load/store dual or exclusive, table branch */
4437 else if ((opcode & 0x1e400000) == 0x08400000)
4438 retval = t2ev_ldrex_strex(opcode, address, instruction, cp);
4439
4440 /* ARMv7-M: A5.3.7 Load word */
4441 else if ((opcode & 0x1f700000) == 0x18500000)
4442 retval = t2ev_load_word(opcode, address, instruction, cp);
4443
4444 /* ARMv7-M: A5.3.8 Load halfword, unallocated memory hints */
4445 else if ((opcode & 0x1e700000) == 0x18300000)
4446 retval = t2ev_load_halfword(opcode, address, instruction, cp);
4447
4448 /* ARMv7-M: A5.3.9 Load byte, memory hints */
4449 else if ((opcode & 0x1e700000) == 0x18100000)
4450 retval = t2ev_load_byte_hints(opcode, address, instruction, cp);
4451
4452 /* ARMv7-M: A5.3.10 Store single data item */
4453 else if ((opcode & 0x1f100000) == 0x18000000)
4454 retval = t2ev_store_single(opcode, address, instruction, cp);
4455
4456 /* ARMv7-M: A5.3.11 Data processing (shifted register) */
4457 else if ((opcode & 0x1e000000) == 0x0a000000)
4458 retval = t2ev_data_shift(opcode, address, instruction, cp);
4459
4460 /* ARMv7-M: A5.3.12 Data processing (register)
4461 * and A5.3.13 Miscellaneous operations
4462 */
4463 else if ((opcode & 0x1f000000) == 0x1a000000)
4464 retval = t2ev_data_reg(opcode, address, instruction, cp);
4465
4466 /* ARMv7-M: A5.3.14 Multiply, and multiply accumulate */
4467 else if ((opcode & 0x1f800000) == 0x1b000000)
4468 retval = t2ev_mul32(opcode, address, instruction, cp);
4469
4470 /* ARMv7-M: A5.3.15 Long multiply, long multiply accumulate, divide */
4471 else if ((opcode & 0x1f800000) == 0x1b800000)
4472 retval = t2ev_mul64_div(opcode, address, instruction, cp);
4473
4474 if (retval == ERROR_OK)
4475 return retval;
4476
4477 /*
4478 * Thumb2 also supports coprocessor, ThumbEE, and DSP/Media (SIMD)
4479 * instructions; not yet handled here.
4480 */
4481
4482 if (retval == ERROR_COMMAND_SYNTAX_ERROR) {
4483 instruction->type = ARM_UNDEFINED_INSTRUCTION;
4484 strcpy(cp, "UNDEFINED OPCODE");
4485 return ERROR_OK;
4486 }
4487
4488 LOG_DEBUG("Can't decode 32-bit Thumb2 yet (opcode=%08" PRIx32 ")",
4489 opcode);
4490
4491 strcpy(cp, "(32-bit Thumb2 ...)");
4492 return ERROR_OK;
4493 }
4494
4495 int arm_access_size(struct arm_instruction *instruction)
4496 {
4497 if ((instruction->type == ARM_LDRB)
4498 || (instruction->type == ARM_LDRBT)
4499 || (instruction->type == ARM_LDRSB)
4500 || (instruction->type == ARM_STRB)
4501 || (instruction->type == ARM_STRBT))
4502 return 1;
4503 else if ((instruction->type == ARM_LDRH)
4504 || (instruction->type == ARM_LDRSH)
4505 || (instruction->type == ARM_STRH))
4506 return 2;
4507 else if ((instruction->type == ARM_LDR)
4508 || (instruction->type == ARM_LDRT)
4509 || (instruction->type == ARM_STR)
4510 || (instruction->type == ARM_STRT))
4511 return 4;
4512 else if ((instruction->type == ARM_LDRD)
4513 || (instruction->type == ARM_STRD))
4514 return 8;
4515 else {
4516 LOG_ERROR("BUG: instruction type %i isn't a load/store instruction",
4517 instruction->type);
4518 return 0;
4519 }
4520 }

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)