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

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)