ef69a203c59a605cce2c71f9b5f067198bbc6b14
[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) == 0x00100000) && (x == 0)) {
1553 uint8_t Rd, Rm, Rs, Rn;
1554 instruction->type = ARM_SMLAWy;
1555 Rd = (opcode & 0xf0000) >> 16;
1556 Rm = (opcode & 0xf);
1557 Rs = (opcode & 0xf00) >> 8;
1558 Rn = (opcode & 0xf000) >> 12;
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) == 0x00300000) {
1575 uint8_t Rd, Rm, Rs;
1576 instruction->type = ARM_SMULxy;
1577 Rd = (opcode & 0xf0000) >> 16;
1578 Rm = (opcode & 0xf);
1579 Rs = (opcode & 0xf00) >> 8;
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) == 0x00100000) && (x == 1)) {
1596 uint8_t Rd, Rm, Rs;
1597 instruction->type = ARM_SMULWy;
1598 Rd = (opcode & 0xf0000) >> 16;
1599 Rm = (opcode & 0xf);
1600 Rs = (opcode & 0xf00) >> 8;
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 break;
2982 case 0x5:
2983 inst = "BL";
2984 instruction->type = ARM_BL;
2985 break;
2986 default:
2987 return ERROR_COMMAND_SYNTAX_ERROR;
2988 }
2989 instruction->info.b_bl_bx_blx.reg_operand = -1;
2990 instruction->info.b_bl_bx_blx.target_address = address;
2991 sprintf(cp, "%s\t%#8.8" PRIx32, inst, address);
2992
2993 return ERROR_OK;
2994 }
2995
2996 static int t2ev_cond_b(uint32_t opcode, uint32_t address,
2997 struct arm_instruction *instruction, char *cp)
2998 {
2999 unsigned offset;
3000 unsigned b17 = 1 << 17;
3001 unsigned b18 = 1 << 18;
3002 unsigned cond = (opcode >> 22) & 0x0f;
3003
3004 offset = opcode & 0x7ff;
3005 offset |= (opcode & 0x003f0000) >> 5;
3006 if (opcode & (1 << 26)) {
3007 offset |= 0x1fff << 19;
3008 if ((opcode & (1 << 11)) == 0)
3009 b17 = 0;
3010 if ((opcode & (1 << 13)) == 0)
3011 b18 = 0;
3012 } else {
3013 if (opcode & (1 << 11))
3014 b17 = 0;
3015 if (opcode & (1 << 13))
3016 b18 = 0;
3017 }
3018 offset |= b17;
3019 offset |= b18;
3020
3021 address += 4;
3022 address += offset << 1;
3023
3024 instruction->type = ARM_B;
3025 instruction->info.b_bl_bx_blx.reg_operand = -1;
3026 instruction->info.b_bl_bx_blx.target_address = address;
3027 sprintf(cp, "B%s.W\t%#8.8" PRIx32,
3028 arm_condition_strings[cond],
3029 address);
3030
3031 return ERROR_OK;
3032 }
3033
3034 static const char *special_name(int number)
3035 {
3036 char *special = "(RESERVED)";
3037
3038 switch (number) {
3039 case 0:
3040 special = "apsr";
3041 break;
3042 case 1:
3043 special = "iapsr";
3044 break;
3045 case 2:
3046 special = "eapsr";
3047 break;
3048 case 3:
3049 special = "xpsr";
3050 break;
3051 case 5:
3052 special = "ipsr";
3053 break;
3054 case 6:
3055 special = "epsr";
3056 break;
3057 case 7:
3058 special = "iepsr";
3059 break;
3060 case 8:
3061 special = "msp";
3062 break;
3063 case 9:
3064 special = "psp";
3065 break;
3066 case 16:
3067 special = "primask";
3068 break;
3069 case 17:
3070 special = "basepri";
3071 break;
3072 case 18:
3073 special = "basepri_max";
3074 break;
3075 case 19:
3076 special = "faultmask";
3077 break;
3078 case 20:
3079 special = "control";
3080 break;
3081 }
3082 return special;
3083 }
3084
3085 static int t2ev_hint(uint32_t opcode, uint32_t address,
3086 struct arm_instruction *instruction, char *cp)
3087 {
3088 const char *mnemonic;
3089
3090 if (opcode & 0x0700) {
3091 instruction->type = ARM_UNDEFINED_INSTRUCTION;
3092 strcpy(cp, "UNDEFINED");
3093 return ERROR_OK;
3094 }
3095
3096 if (opcode & 0x00f0) {
3097 sprintf(cp, "DBG\t#%d", (int) opcode & 0xf);
3098 return ERROR_OK;
3099 }
3100
3101 switch (opcode & 0x0f) {
3102 case 0:
3103 mnemonic = "NOP.W";
3104 break;
3105 case 1:
3106 mnemonic = "YIELD.W";
3107 break;
3108 case 2:
3109 mnemonic = "WFE.W";
3110 break;
3111 case 3:
3112 mnemonic = "WFI.W";
3113 break;
3114 case 4:
3115 mnemonic = "SEV.W";
3116 break;
3117 default:
3118 mnemonic = "HINT.W (UNRECOGNIZED)";
3119 break;
3120 }
3121 strcpy(cp, mnemonic);
3122 return ERROR_OK;
3123 }
3124
3125 static int t2ev_misc(uint32_t opcode, uint32_t address,
3126 struct arm_instruction *instruction, char *cp)
3127 {
3128 const char *mnemonic;
3129
3130 switch ((opcode >> 4) & 0x0f) {
3131 case 0:
3132 mnemonic = "LEAVEX";
3133 break;
3134 case 1:
3135 mnemonic = "ENTERX";
3136 break;
3137 case 2:
3138 mnemonic = "CLREX";
3139 break;
3140 case 4:
3141 mnemonic = "DSB";
3142 break;
3143 case 5:
3144 mnemonic = "DMB";
3145 break;
3146 case 6:
3147 mnemonic = "ISB";
3148 break;
3149 default:
3150 return ERROR_COMMAND_SYNTAX_ERROR;
3151 }
3152 strcpy(cp, mnemonic);
3153 return ERROR_OK;
3154 }
3155
3156 static int t2ev_b_misc(uint32_t opcode, uint32_t address,
3157 struct arm_instruction *instruction, char *cp)
3158 {
3159 /* permanently undefined */
3160 if ((opcode & 0x07f07000) == 0x07f02000) {
3161 instruction->type = ARM_UNDEFINED_INSTRUCTION;
3162 strcpy(cp, "UNDEFINED");
3163 return ERROR_OK;
3164 }
3165
3166 switch ((opcode >> 12) & 0x5) {
3167 case 0x1:
3168 case 0x4:
3169 case 0x5:
3170 return t2ev_b_bl(opcode, address, instruction, cp);
3171 case 0:
3172 if (((opcode >> 23) & 0x07) != 0x07)
3173 return t2ev_cond_b(opcode, address, instruction, cp);
3174 if (opcode & (1 << 26))
3175 goto undef;
3176 break;
3177 }
3178
3179 switch ((opcode >> 20) & 0x7f) {
3180 case 0x38:
3181 case 0x39:
3182 sprintf(cp, "MSR\t%s, r%d", special_name(opcode & 0xff),
3183 (int) (opcode >> 16) & 0x0f);
3184 return ERROR_OK;
3185 case 0x3a:
3186 return t2ev_hint(opcode, address, instruction, cp);
3187 case 0x3b:
3188 return t2ev_misc(opcode, address, instruction, cp);
3189 case 0x3c:
3190 sprintf(cp, "BXJ\tr%d", (int) (opcode >> 16) & 0x0f);
3191 return ERROR_OK;
3192 case 0x3e:
3193 case 0x3f:
3194 sprintf(cp, "MRS\tr%d, %s", (int) (opcode >> 8) & 0x0f,
3195 special_name(opcode & 0xff));
3196 return ERROR_OK;
3197 }
3198
3199 undef:
3200 return ERROR_COMMAND_SYNTAX_ERROR;
3201 }
3202
3203 static int t2ev_data_mod_immed(uint32_t opcode, uint32_t address,
3204 struct arm_instruction *instruction, char *cp)
3205 {
3206 char *mnemonic = NULL;
3207 int rn = (opcode >> 16) & 0xf;
3208 int rd = (opcode >> 8) & 0xf;
3209 unsigned immed = opcode & 0xff;
3210 unsigned func;
3211 bool one = false;
3212 char *suffix = "";
3213 char *suffix2 = "";
3214
3215 /* ARMv7-M: A5.3.2 Modified immediate constants */
3216 func = (opcode >> 11) & 0x0e;
3217 if (immed & 0x80)
3218 func |= 1;
3219 if (opcode & (1 << 26))
3220 func |= 0x10;
3221
3222 /* "Modified" immediates */
3223 switch (func >> 1) {
3224 case 0:
3225 break;
3226 case 2:
3227 immed <<= 8;
3228 /* FALLTHROUGH */
3229 case 1:
3230 immed += immed << 16;
3231 break;
3232 case 3:
3233 immed += immed << 8;
3234 immed += immed << 16;
3235 break;
3236 default:
3237 immed |= 0x80;
3238 immed = ror(immed, func);
3239 }
3240
3241 if (opcode & (1 << 20))
3242 suffix = "S";
3243
3244 switch ((opcode >> 21) & 0xf) {
3245 case 0:
3246 if (rd == 0xf) {
3247 instruction->type = ARM_TST;
3248 mnemonic = "TST";
3249 one = true;
3250 suffix = "";
3251 rd = rn;
3252 } else {
3253 instruction->type = ARM_AND;
3254 mnemonic = "AND";
3255 }
3256 break;
3257 case 1:
3258 instruction->type = ARM_BIC;
3259 mnemonic = "BIC";
3260 break;
3261 case 2:
3262 if (rn == 0xf) {
3263 instruction->type = ARM_MOV;
3264 mnemonic = "MOV";
3265 one = true;
3266 suffix2 = ".W";
3267 } else {
3268 instruction->type = ARM_ORR;
3269 mnemonic = "ORR";
3270 }
3271 break;
3272 case 3:
3273 if (rn == 0xf) {
3274 instruction->type = ARM_MVN;
3275 mnemonic = "MVN";
3276 one = true;
3277 } else {
3278 /* instruction->type = ARM_ORN; */
3279 mnemonic = "ORN";
3280 }
3281 break;
3282 case 4:
3283 if (rd == 0xf) {
3284 instruction->type = ARM_TEQ;
3285 mnemonic = "TEQ";
3286 one = true;
3287 suffix = "";
3288 rd = rn;
3289 } else {
3290 instruction->type = ARM_EOR;
3291 mnemonic = "EOR";
3292 }
3293 break;
3294 case 8:
3295 if (rd == 0xf) {
3296 instruction->type = ARM_CMN;
3297 mnemonic = "CMN";
3298 one = true;
3299 suffix = "";
3300 rd = rn;
3301 } else {
3302 instruction->type = ARM_ADD;
3303 mnemonic = "ADD";
3304 suffix2 = ".W";
3305 }
3306 break;
3307 case 10:
3308 instruction->type = ARM_ADC;
3309 mnemonic = "ADC";
3310 suffix2 = ".W";
3311 break;
3312 case 11:
3313 instruction->type = ARM_SBC;
3314 mnemonic = "SBC";
3315 break;
3316 case 13:
3317 if (rd == 0xf) {
3318 instruction->type = ARM_CMP;
3319 mnemonic = "CMP";
3320 one = true;
3321 suffix = "";
3322 rd = rn;
3323 } else {
3324 instruction->type = ARM_SUB;
3325 mnemonic = "SUB";
3326 }
3327 suffix2 = ".W";
3328 break;
3329 case 14:
3330 instruction->type = ARM_RSB;
3331 mnemonic = "RSB";
3332 suffix2 = ".W";
3333 break;
3334 default:
3335 return ERROR_COMMAND_SYNTAX_ERROR;
3336 }
3337
3338 if (one)
3339 sprintf(cp, "%s%s\tr%d, #%d\t; %#8.8x",
3340 mnemonic, suffix2, rd, immed, immed);
3341 else
3342 sprintf(cp, "%s%s%s\tr%d, r%d, #%d\t; %#8.8x",
3343 mnemonic, suffix, suffix2,
3344 rd, rn, immed, immed);
3345
3346 return ERROR_OK;
3347 }
3348
3349 static int t2ev_data_immed(uint32_t opcode, uint32_t address,
3350 struct arm_instruction *instruction, char *cp)
3351 {
3352 char *mnemonic = NULL;
3353 int rn = (opcode >> 16) & 0xf;
3354 int rd = (opcode >> 8) & 0xf;
3355 unsigned immed;
3356 bool add = false;
3357 bool is_signed = false;
3358
3359 immed = (opcode & 0x0ff) | ((opcode & 0x7000) >> 4);
3360 if (opcode & (1 << 26))
3361 immed |= (1 << 11);
3362
3363 switch ((opcode >> 20) & 0x1f) {
3364 case 0:
3365 if (rn == 0xf) {
3366 add = true;
3367 goto do_adr;
3368 }
3369 mnemonic = "ADDW";
3370 break;
3371 case 4:
3372 immed |= (opcode >> 4) & 0xf000;
3373 sprintf(cp, "MOVW\tr%d, #%d\t; %#3.3x", rd, immed, immed);
3374 return ERROR_OK;
3375 case 0x0a:
3376 if (rn == 0xf)
3377 goto do_adr;
3378 mnemonic = "SUBW";
3379 break;
3380 case 0x0c:
3381 /* move constant to top 16 bits of register */
3382 immed |= (opcode >> 4) & 0xf000;
3383 sprintf(cp, "MOVT\tr%d, #%d\t; %#4.4x", rd, immed, immed);
3384 return ERROR_OK;
3385 case 0x10:
3386 case 0x12:
3387 is_signed = true;
3388 /* fallthrough */
3389 case 0x18:
3390 case 0x1a:
3391 /* signed/unsigned saturated add */
3392 immed = (opcode >> 6) & 0x03;
3393 immed |= (opcode >> 10) & 0x1c;
3394 sprintf(cp, "%sSAT\tr%d, #%d, r%d, %s #%d\t",
3395 is_signed ? "S" : "U",
3396 rd, (int) (opcode & 0x1f) + is_signed, rn,
3397 (opcode & (1 << 21)) ? "ASR" : "LSL",
3398 immed ? immed : 32);
3399 return ERROR_OK;
3400 case 0x14:
3401 is_signed = true;
3402 /* FALLTHROUGH */
3403 case 0x1c:
3404 /* signed/unsigned bitfield extract */
3405 immed = (opcode >> 6) & 0x03;
3406 immed |= (opcode >> 10) & 0x1c;
3407 sprintf(cp, "%sBFX\tr%d, r%d, #%d, #%d\t",
3408 is_signed ? "S" : "U",
3409 rd, rn, immed,
3410 (int) (opcode & 0x1f) + 1);
3411 return ERROR_OK;
3412 case 0x16:
3413 immed = (opcode >> 6) & 0x03;
3414 immed |= (opcode >> 10) & 0x1c;
3415 if (rn == 0xf) /* bitfield clear */
3416 sprintf(cp, "BFC\tr%d, #%d, #%d\t",
3417 rd, immed,
3418 (int) (opcode & 0x1f) + 1 - immed);
3419 else /* bitfield insert */
3420 sprintf(cp, "BFI\tr%d, r%d, #%d, #%d\t",
3421 rd, rn, immed,
3422 (int) (opcode & 0x1f) + 1 - immed);
3423 return ERROR_OK;
3424 default:
3425 return ERROR_COMMAND_SYNTAX_ERROR;
3426 }
3427
3428 sprintf(cp, "%s\tr%d, r%d, #%d\t; %#3.3x", mnemonic,
3429 rd, rn, immed, immed);
3430 return ERROR_OK;
3431
3432 do_adr:
3433 address = thumb_alignpc4(address);
3434 if (add)
3435 address += immed;
3436 else
3437 address -= immed;
3438 /* REVISIT "ADD/SUB Rd, PC, #const ; 0x..." might be better;
3439 * not hiding the pc-relative stuff will sometimes be useful.
3440 */
3441 sprintf(cp, "ADR.W\tr%d, %#8.8" PRIx32, rd, address);
3442 return ERROR_OK;
3443 }
3444
3445 static int t2ev_store_single(uint32_t opcode, uint32_t address,
3446 struct arm_instruction *instruction, char *cp)
3447 {
3448 unsigned op = (opcode >> 20) & 0xf;
3449 char *size = "";
3450 char *suffix = "";
3451 char *p1 = "";
3452 char *p2 = "]";
3453 unsigned immed;
3454 unsigned rn = (opcode >> 16) & 0x0f;
3455 unsigned rt = (opcode >> 12) & 0x0f;
3456
3457 if (rn == 0xf)
3458 return ERROR_COMMAND_SYNTAX_ERROR;
3459
3460 if (opcode & 0x0800)
3461 op |= 1;
3462 switch (op) {
3463 /* byte */
3464 case 0x8:
3465 case 0x9:
3466 size = "B";
3467 goto imm12;
3468 case 0x1:
3469 size = "B";
3470 goto imm8;
3471 case 0x0:
3472 size = "B";
3473 break;
3474 /* halfword */
3475 case 0xa:
3476 case 0xb:
3477 size = "H";
3478 goto imm12;
3479 case 0x3:
3480 size = "H";
3481 goto imm8;
3482 case 0x2:
3483 size = "H";
3484 break;
3485 /* word */
3486 case 0xc:
3487 case 0xd:
3488 goto imm12;
3489 case 0x5:
3490 goto imm8;
3491 case 0x4:
3492 break;
3493 /* error */
3494 default:
3495 return ERROR_COMMAND_SYNTAX_ERROR;
3496 }
3497
3498 sprintf(cp, "STR%s.W\tr%d, [r%d, r%d, LSL #%d]",
3499 size, rt, rn, (int) opcode & 0x0f,
3500 (int) (opcode >> 4) & 0x03);
3501 return ERROR_OK;
3502
3503 imm12:
3504 immed = opcode & 0x0fff;
3505 sprintf(cp, "STR%s.W\tr%d, [r%d, #%u]\t; %#3.3x",
3506 size, rt, rn, immed, immed);
3507 return ERROR_OK;
3508
3509 imm8:
3510 immed = opcode & 0x00ff;
3511
3512 switch (opcode & 0x700) {
3513 case 0x600:
3514 suffix = "T";
3515 break;
3516 case 0x000:
3517 case 0x200:
3518 return ERROR_COMMAND_SYNTAX_ERROR;
3519 }
3520
3521 /* two indexed modes will write back rn */
3522 if (opcode & 0x100) {
3523 if (opcode & 0x400) /* pre-indexed */
3524 p2 = "]!";
3525 else { /* post-indexed */
3526 p1 = "]";
3527 p2 = "";
3528 }
3529 }
3530
3531 sprintf(cp, "STR%s%s\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
3532 size, suffix, rt, rn, p1,
3533 (opcode & 0x200) ? "" : "-",
3534 immed, p2, immed);
3535 return ERROR_OK;
3536 }
3537
3538 static int t2ev_mul32(uint32_t opcode, uint32_t address,
3539 struct arm_instruction *instruction, char *cp)
3540 {
3541 int ra = (opcode >> 12) & 0xf;
3542
3543 switch (opcode & 0x007000f0) {
3544 case 0:
3545 if (ra == 0xf)
3546 sprintf(cp, "MUL\tr%d, r%d, r%d",
3547 (int) (opcode >> 8) & 0xf,
3548 (int) (opcode >> 16) & 0xf,
3549 (int) (opcode >> 0) & 0xf);
3550 else
3551 sprintf(cp, "MLA\tr%d, r%d, r%d, r%d",
3552 (int) (opcode >> 8) & 0xf,
3553 (int) (opcode >> 16) & 0xf,
3554 (int) (opcode >> 0) & 0xf, ra);
3555 break;
3556 case 0x10:
3557 sprintf(cp, "MLS\tr%d, r%d, r%d, r%d",
3558 (int) (opcode >> 8) & 0xf,
3559 (int) (opcode >> 16) & 0xf,
3560 (int) (opcode >> 0) & 0xf, ra);
3561 break;
3562 default:
3563 return ERROR_COMMAND_SYNTAX_ERROR;
3564 }
3565 return ERROR_OK;
3566 }
3567
3568 static int t2ev_mul64_div(uint32_t opcode, uint32_t address,
3569 struct arm_instruction *instruction, char *cp)
3570 {
3571 int op = (opcode >> 4) & 0xf;
3572 char *infix = "MUL";
3573
3574 op += (opcode >> 16) & 0x70;
3575 switch (op) {
3576 case 0x40:
3577 case 0x60:
3578 infix = "MLA";
3579 /* FALLTHROUGH */
3580 case 0:
3581 case 0x20:
3582 sprintf(cp, "%c%sL\tr%d, r%d, r%d, r%d",
3583 (op & 0x20) ? 'U' : 'S',
3584 infix,
3585 (int) (opcode >> 12) & 0xf,
3586 (int) (opcode >> 8) & 0xf,
3587 (int) (opcode >> 16) & 0xf,
3588 (int) (opcode >> 0) & 0xf);
3589 break;
3590 case 0x1f:
3591 case 0x3f:
3592 sprintf(cp, "%cDIV\tr%d, r%d, r%d",
3593 (op & 0x20) ? 'U' : 'S',
3594 (int) (opcode >> 8) & 0xf,
3595 (int) (opcode >> 16) & 0xf,
3596 (int) (opcode >> 0) & 0xf);
3597 break;
3598 default:
3599 return ERROR_COMMAND_SYNTAX_ERROR;
3600 }
3601
3602 return ERROR_OK;
3603 }
3604
3605 static int t2ev_ldm_stm(uint32_t opcode, uint32_t address,
3606 struct arm_instruction *instruction, char *cp)
3607 {
3608 int rn = (opcode >> 16) & 0xf;
3609 int op = (opcode >> 22) & 0x6;
3610 int t = (opcode >> 21) & 1;
3611 unsigned registers = opcode & 0xffff;
3612 char *mode = "";
3613
3614 if (opcode & (1 << 20))
3615 op |= 1;
3616
3617 switch (op) {
3618 case 0:
3619 mode = "DB";
3620 /* FALL THROUGH */
3621 case 6:
3622 sprintf(cp, "SRS%s\tsp%s, #%d", mode,
3623 t ? "!" : "",
3624 (unsigned) (opcode & 0x1f));
3625 return ERROR_OK;
3626 case 1:
3627 mode = "DB";
3628 /* FALL THROUGH */
3629 case 7:
3630 sprintf(cp, "RFE%s\tr%d%s", mode,
3631 (unsigned) ((opcode >> 16) & 0xf),
3632 t ? "!" : "");
3633 return ERROR_OK;
3634 case 2:
3635 sprintf(cp, "STM.W\tr%d%s, ", rn, t ? "!" : "");
3636 break;
3637 case 3:
3638 if (rn == 13 && t)
3639 sprintf(cp, "POP.W\t");
3640 else
3641 sprintf(cp, "LDM.W\tr%d%s, ", rn, t ? "!" : "");
3642 break;
3643 case 4:
3644 if (rn == 13 && t)
3645 sprintf(cp, "PUSH.W\t");
3646 else
3647 sprintf(cp, "STMDB\tr%d%s, ", rn, t ? "!" : "");
3648 break;
3649 case 5:
3650 sprintf(cp, "LDMDB.W\tr%d%s, ", rn, t ? "!" : "");
3651 break;
3652 default:
3653 return ERROR_COMMAND_SYNTAX_ERROR;
3654 }
3655
3656 cp = strchr(cp, 0);
3657 *cp++ = '{';
3658 for (t = 0; registers; t++, registers >>= 1) {
3659 if ((registers & 1) == 0)
3660 continue;
3661 registers &= ~1;
3662 sprintf(cp, "r%d%s", t, registers ? ", " : "");
3663 cp = strchr(cp, 0);
3664 }
3665 *cp++ = '}';
3666 *cp++ = 0;
3667
3668 return ERROR_OK;
3669 }
3670
3671 /* load/store dual or exclusive, table branch */
3672 static int t2ev_ldrex_strex(uint32_t opcode, uint32_t address,
3673 struct arm_instruction *instruction, char *cp)
3674 {
3675 unsigned op1op2 = (opcode >> 20) & 0x3;
3676 unsigned op3 = (opcode >> 4) & 0xf;
3677 char *mnemonic;
3678 unsigned rn = (opcode >> 16) & 0xf;
3679 unsigned rt = (opcode >> 12) & 0xf;
3680 unsigned rd = (opcode >> 8) & 0xf;
3681 unsigned imm = opcode & 0xff;
3682 char *p1 = "";
3683 char *p2 = "]";
3684
3685 op1op2 |= (opcode >> 21) & 0xc;
3686 switch (op1op2) {
3687 case 0:
3688 mnemonic = "STREX";
3689 goto strex;
3690 case 1:
3691 mnemonic = "LDREX";
3692 goto ldrex;
3693 case 2:
3694 case 6:
3695 case 8:
3696 case 10:
3697 case 12:
3698 case 14:
3699 mnemonic = "STRD";
3700 goto immediate;
3701 case 3:
3702 case 7:
3703 case 9:
3704 case 11:
3705 case 13:
3706 case 15:
3707 mnemonic = "LDRD";
3708 if (rn == 15)
3709 goto literal;
3710 else
3711 goto immediate;
3712 case 4:
3713 switch (op3) {
3714 case 4:
3715 mnemonic = "STREXB";
3716 break;
3717 case 5:
3718 mnemonic = "STREXH";
3719 break;
3720 default:
3721 return ERROR_COMMAND_SYNTAX_ERROR;
3722 }
3723 rd = opcode & 0xf;
3724 imm = 0;
3725 goto strex;
3726 case 5:
3727 switch (op3) {
3728 case 0:
3729 sprintf(cp, "TBB\t[r%u, r%u]", rn, imm & 0xf);
3730 return ERROR_OK;
3731 case 1:
3732 sprintf(cp, "TBH\t[r%u, r%u, LSL #1]", rn, imm & 0xf);
3733 return ERROR_OK;
3734 case 4:
3735 mnemonic = "LDREXB";
3736 break;
3737 case 5:
3738 mnemonic = "LDREXH";
3739 break;
3740 default:
3741 return ERROR_COMMAND_SYNTAX_ERROR;
3742 }
3743 imm = 0;
3744 goto ldrex;
3745 }
3746 return ERROR_COMMAND_SYNTAX_ERROR;
3747
3748 strex:
3749 imm <<= 2;
3750 if (imm)
3751 sprintf(cp, "%s\tr%u, r%u, [r%u, #%u]\t; %#2.2x",
3752 mnemonic, rd, rt, rn, imm, imm);
3753 else
3754 sprintf(cp, "%s\tr%u, r%u, [r%u]",
3755 mnemonic, rd, rt, rn);
3756 return ERROR_OK;
3757
3758 ldrex:
3759 imm <<= 2;
3760 if (imm)
3761 sprintf(cp, "%s\tr%u, [r%u, #%u]\t; %#2.2x",
3762 mnemonic, rt, rn, imm, imm);
3763 else
3764 sprintf(cp, "%s\tr%u, [r%u]",
3765 mnemonic, rt, rn);
3766 return ERROR_OK;
3767
3768 immediate:
3769 /* two indexed modes will write back rn */
3770 if (opcode & (1 << 21)) {
3771 if (opcode & (1 << 24)) /* pre-indexed */
3772 p2 = "]!";
3773 else { /* post-indexed */
3774 p1 = "]";
3775 p2 = "";
3776 }
3777 }
3778
3779 imm <<= 2;
3780 sprintf(cp, "%s\tr%u, r%u, [r%u%s, #%s%u%s\t; %#2.2x",
3781 mnemonic, rt, rd, rn, p1,
3782 (opcode & (1 << 23)) ? "" : "-",
3783 imm, p2, imm);
3784 return ERROR_OK;
3785
3786 literal:
3787 address = thumb_alignpc4(address);
3788 imm <<= 2;
3789 if (opcode & (1 << 23))
3790 address += imm;
3791 else
3792 address -= imm;
3793 sprintf(cp, "%s\tr%u, r%u, %#8.8" PRIx32,
3794 mnemonic, rt, rd, address);
3795 return ERROR_OK;
3796 }
3797
3798 static int t2ev_data_shift(uint32_t opcode, uint32_t address,
3799 struct arm_instruction *instruction, char *cp)
3800 {
3801 int op = (opcode >> 21) & 0xf;
3802 int rd = (opcode >> 8) & 0xf;
3803 int rn = (opcode >> 16) & 0xf;
3804 int type = (opcode >> 4) & 0x3;
3805 int immed = (opcode >> 6) & 0x3;
3806 char *mnemonic;
3807 char *suffix = "";
3808
3809 immed |= (opcode >> 10) & 0x1c;
3810 if (opcode & (1 << 20))
3811 suffix = "S";
3812
3813 switch (op) {
3814 case 0:
3815 if (rd == 0xf) {
3816 if (!(opcode & (1 << 20)))
3817 return ERROR_COMMAND_SYNTAX_ERROR;
3818 instruction->type = ARM_TST;
3819 mnemonic = "TST";
3820 suffix = "";
3821 goto two;
3822 }
3823 instruction->type = ARM_AND;
3824 mnemonic = "AND";
3825 break;
3826 case 1:
3827 instruction->type = ARM_BIC;
3828 mnemonic = "BIC";
3829 break;
3830 case 2:
3831 if (rn == 0xf) {
3832 instruction->type = ARM_MOV;
3833 switch (type) {
3834 case 0:
3835 if (immed == 0) {
3836 sprintf(cp, "MOV%s.W\tr%d, r%d",
3837 suffix, rd,
3838 (int) (opcode & 0xf));
3839 return ERROR_OK;
3840 }
3841 mnemonic = "LSL";
3842 break;
3843 case 1:
3844 mnemonic = "LSR";
3845 break;
3846 case 2:
3847 mnemonic = "ASR";
3848 break;
3849 default:
3850 if (immed == 0) {
3851 sprintf(cp, "RRX%s\tr%d, r%d",
3852 suffix, rd,
3853 (int) (opcode & 0xf));
3854 return ERROR_OK;
3855 }
3856 mnemonic = "ROR";
3857 break;
3858 }
3859 goto immediate;
3860 } else {
3861 instruction->type = ARM_ORR;
3862 mnemonic = "ORR";
3863 }
3864 break;
3865 case 3:
3866 if (rn == 0xf) {
3867 instruction->type = ARM_MVN;
3868 mnemonic = "MVN";
3869 rn = rd;
3870 goto two;
3871 } else {
3872 /* instruction->type = ARM_ORN; */
3873 mnemonic = "ORN";
3874 }
3875 break;
3876 case 4:
3877 if (rd == 0xf) {
3878 if (!(opcode & (1 << 20)))
3879 return ERROR_COMMAND_SYNTAX_ERROR;
3880 instruction->type = ARM_TEQ;
3881 mnemonic = "TEQ";
3882 suffix = "";
3883 goto two;
3884 }
3885 instruction->type = ARM_EOR;
3886 mnemonic = "EOR";
3887 break;
3888 case 8:
3889 if (rd == 0xf) {
3890 if (!(opcode & (1 << 20)))
3891 return ERROR_COMMAND_SYNTAX_ERROR;
3892 instruction->type = ARM_CMN;
3893 mnemonic = "CMN";
3894 suffix = "";
3895 goto two;
3896 }
3897 instruction->type = ARM_ADD;
3898 mnemonic = "ADD";
3899 break;
3900 case 0xa:
3901 instruction->type = ARM_ADC;
3902 mnemonic = "ADC";
3903 break;
3904 case 0xb:
3905 instruction->type = ARM_SBC;
3906 mnemonic = "SBC";
3907 break;
3908 case 0xd:
3909 if (rd == 0xf) {
3910 if (!(opcode & (1 << 21)))
3911 return ERROR_COMMAND_SYNTAX_ERROR;
3912 instruction->type = ARM_CMP;
3913 mnemonic = "CMP";
3914 suffix = "";
3915 goto two;
3916 }
3917 instruction->type = ARM_SUB;
3918 mnemonic = "SUB";
3919 break;
3920 case 0xe:
3921 instruction->type = ARM_RSB;
3922 mnemonic = "RSB";
3923 break;
3924 default:
3925 return ERROR_COMMAND_SYNTAX_ERROR;
3926 }
3927
3928 sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
3929 mnemonic, suffix, rd, rn, (int) (opcode & 0xf));
3930
3931 shift:
3932 cp = strchr(cp, 0);
3933
3934 switch (type) {
3935 case 0:
3936 if (immed == 0)
3937 return ERROR_OK;
3938 suffix = "LSL";
3939 break;
3940 case 1:
3941 suffix = "LSR";
3942 if (immed == 32)
3943 immed = 0;
3944 break;
3945 case 2:
3946 suffix = "ASR";
3947 if (immed == 32)
3948 immed = 0;
3949 break;
3950 case 3:
3951 if (immed == 0) {
3952 strcpy(cp, ", RRX");
3953 return ERROR_OK;
3954 }
3955 suffix = "ROR";
3956 break;
3957 }
3958 sprintf(cp, ", %s #%d", suffix, immed ? immed : 32);
3959 return ERROR_OK;
3960
3961 two:
3962 sprintf(cp, "%s%s.W\tr%d, r%d",
3963 mnemonic, suffix, rn, (int) (opcode & 0xf));
3964 goto shift;
3965
3966 immediate:
3967 sprintf(cp, "%s%s.W\tr%d, r%d, #%d",
3968 mnemonic, suffix, rd,
3969 (int) (opcode & 0xf), immed ? immed : 32);
3970 return ERROR_OK;
3971 }
3972
3973 static int t2ev_data_reg(uint32_t opcode, uint32_t address,
3974 struct arm_instruction *instruction, char *cp)
3975 {
3976 char *mnemonic;
3977 char *suffix = "";
3978
3979 if (((opcode >> 4) & 0xf) == 0) {
3980 switch ((opcode >> 21) & 0x7) {
3981 case 0:
3982 mnemonic = "LSL";
3983 break;
3984 case 1:
3985 mnemonic = "LSR";
3986 break;
3987 case 2:
3988 mnemonic = "ASR";
3989 break;
3990 case 3:
3991 mnemonic = "ROR";
3992 break;
3993 default:
3994 return ERROR_COMMAND_SYNTAX_ERROR;
3995 }
3996
3997 instruction->type = ARM_MOV;
3998 if (opcode & (1 << 20))
3999 suffix = "S";
4000 sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
4001 mnemonic, suffix,
4002 (int) (opcode >> 8) & 0xf,
4003 (int) (opcode >> 16) & 0xf,
4004 (int) (opcode >> 0) & 0xf);
4005
4006 } else if (opcode & (1 << 7)) {
4007 switch ((opcode >> 20) & 0xf) {
4008 case 0:
4009 case 1:
4010 case 4:
4011 case 5:
4012 switch ((opcode >> 4) & 0x3) {
4013 case 1:
4014 suffix = ", ROR #8";
4015 break;
4016 case 2:
4017 suffix = ", ROR #16";
4018 break;
4019 case 3:
4020 suffix = ", ROR #24";
4021 break;
4022 }
4023 sprintf(cp, "%cXT%c.W\tr%d, r%d%s",
4024 (opcode & (1 << 24)) ? 'U' : 'S',
4025 (opcode & (1 << 26)) ? 'B' : 'H',
4026 (int) (opcode >> 8) & 0xf,
4027 (int) (opcode >> 0) & 0xf,
4028 suffix);
4029 break;
4030 case 8:
4031 case 9:
4032 case 0xa:
4033 case 0xb:
4034 if (opcode & (1 << 6))
4035 return ERROR_COMMAND_SYNTAX_ERROR;
4036 if (((opcode >> 12) & 0xf) != 0xf)
4037 return ERROR_COMMAND_SYNTAX_ERROR;
4038 if (!(opcode & (1 << 20)))
4039 return ERROR_COMMAND_SYNTAX_ERROR;
4040
4041 switch (((opcode >> 19) & 0x04)
4042 | ((opcode >> 4) & 0x3)) {
4043 case 0:
4044 mnemonic = "REV.W";
4045 break;
4046 case 1:
4047 mnemonic = "REV16.W";
4048 break;
4049 case 2:
4050 mnemonic = "RBIT";
4051 break;
4052 case 3:
4053 mnemonic = "REVSH.W";
4054 break;
4055 case 4:
4056 mnemonic = "CLZ";
4057 break;
4058 default:
4059 return ERROR_COMMAND_SYNTAX_ERROR;
4060 }
4061 sprintf(cp, "%s\tr%d, r%d",
4062 mnemonic,
4063 (int) (opcode >> 8) & 0xf,
4064 (int) (opcode >> 0) & 0xf);
4065 break;
4066 default:
4067 return ERROR_COMMAND_SYNTAX_ERROR;
4068 }
4069 }
4070
4071 return ERROR_OK;
4072 }
4073
4074 static int t2ev_load_word(uint32_t opcode, uint32_t address,
4075 struct arm_instruction *instruction, char *cp)
4076 {
4077 int rn = (opcode >> 16) & 0xf;
4078 int immed;
4079
4080 instruction->type = ARM_LDR;
4081
4082 if (rn == 0xf) {
4083 immed = opcode & 0x0fff;
4084 if ((opcode & (1 << 23)) == 0)
4085 immed = -immed;
4086 sprintf(cp, "LDR\tr%d, %#8.8" PRIx32,
4087 (int) (opcode >> 12) & 0xf,
4088 thumb_alignpc4(address) + immed);
4089 return ERROR_OK;
4090 }
4091
4092 if (opcode & (1 << 23)) {
4093 immed = opcode & 0x0fff;
4094 sprintf(cp, "LDR.W\tr%d, [r%d, #%d]\t; %#3.3x",
4095 (int) (opcode >> 12) & 0xf,
4096 rn, immed, immed);
4097 return ERROR_OK;
4098 }
4099
4100 if (!(opcode & (0x3f << 6))) {
4101 sprintf(cp, "LDR.W\tr%d, [r%d, r%d, LSL #%d]",
4102 (int) (opcode >> 12) & 0xf,
4103 rn,
4104 (int) (opcode >> 0) & 0xf,
4105 (int) (opcode >> 4) & 0x3);
4106 return ERROR_OK;
4107 }
4108
4109
4110 if (((opcode >> 8) & 0xf) == 0xe) {
4111 immed = opcode & 0x00ff;
4112
4113 sprintf(cp, "LDRT\tr%d, [r%d, #%d]\t; %#2.2x",
4114 (int) (opcode >> 12) & 0xf,
4115 rn, immed, immed);
4116 return ERROR_OK;
4117 }
4118
4119 if (((opcode >> 8) & 0xf) == 0xc || (opcode & 0x0900) == 0x0900) {
4120 char *p1 = "]", *p2 = "";
4121
4122 if (!(opcode & 0x0500))
4123 return ERROR_COMMAND_SYNTAX_ERROR;
4124
4125 immed = opcode & 0x00ff;
4126
4127 /* two indexed modes will write back rn */
4128 if (opcode & 0x100) {
4129 if (opcode & 0x400) /* pre-indexed */
4130 p2 = "]!";
4131 else { /* post-indexed */
4132 p1 = "]";
4133 p2 = "";
4134 }
4135 }
4136
4137 sprintf(cp, "LDR\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
4138 (int) (opcode >> 12) & 0xf,
4139 rn, p1,
4140 (opcode & 0x200) ? "" : "-",
4141 immed, p2, immed);
4142 return ERROR_OK;
4143 }
4144
4145 return ERROR_COMMAND_SYNTAX_ERROR;
4146 }
4147
4148 static int t2ev_load_byte_hints(uint32_t opcode, uint32_t address,
4149 struct arm_instruction *instruction, char *cp)
4150 {
4151 int rn = (opcode >> 16) & 0xf;
4152 int rt = (opcode >> 12) & 0xf;
4153 int op2 = (opcode >> 6) & 0x3f;
4154 unsigned immed;
4155 char *p1 = "", *p2 = "]";
4156 char *mnemonic;
4157
4158 switch ((opcode >> 23) & 0x3) {
4159 case 0:
4160 if ((rn & rt) == 0xf) {
4161 pld_literal:
4162 immed = opcode & 0xfff;
4163 address = thumb_alignpc4(address);
4164 if (opcode & (1 << 23))
4165 address += immed;
4166 else
4167 address -= immed;
4168 sprintf(cp, "PLD\tr%d, %#8.8" PRIx32,
4169 rt, address);
4170 return ERROR_OK;
4171 }
4172 if (rn == 0x0f && rt != 0x0f) {
4173 ldrb_literal:
4174 immed = opcode & 0xfff;
4175 address = thumb_alignpc4(address);
4176 if (opcode & (1 << 23))
4177 address += immed;
4178 else
4179 address -= immed;
4180 sprintf(cp, "LDRB\tr%d, %#8.8" PRIx32,
4181 rt, address);
4182 return ERROR_OK;
4183 }
4184 if (rn == 0x0f)
4185 break;
4186 if ((op2 & 0x3c) == 0x38) {
4187 immed = opcode & 0xff;
4188 sprintf(cp, "LDRBT\tr%d, [r%d, #%d]\t; %#2.2x",
4189 rt, rn, immed, immed);
4190 return ERROR_OK;
4191 }
4192 if ((op2 & 0x3c) == 0x30) {
4193 if (rt == 0x0f) {
4194 immed = opcode & 0xff;
4195 immed = -immed;
4196 preload_immediate:
4197 p1 = (opcode & (1 << 21)) ? "W" : "";
4198 sprintf(cp, "PLD%s\t[r%d, #%d]\t; %#6.6x",
4199 p1, rn, immed, immed);
4200 return ERROR_OK;
4201 }
4202 mnemonic = "LDRB";
4203 ldrxb_immediate_t3:
4204 immed = opcode & 0xff;
4205 if (!(opcode & 0x200))
4206 immed = -immed;
4207
4208 /* two indexed modes will write back rn */
4209 if (opcode & 0x100) {
4210 if (opcode & 0x400) /* pre-indexed */
4211 p2 = "]!";
4212 else { /* post-indexed */
4213 p1 = "]";
4214 p2 = "";
4215 }
4216 }
4217 ldrxb_immediate_t2:
4218 sprintf(cp, "%s\tr%d, [r%d%s, #%d%s\t; %#8.8x",
4219 mnemonic, rt, rn, p1,
4220 immed, p2, immed);
4221 return ERROR_OK;
4222 }
4223 if ((op2 & 0x24) == 0x24) {
4224 mnemonic = "LDRB";
4225 goto ldrxb_immediate_t3;
4226 }
4227 if (op2 == 0) {
4228 int rm = opcode & 0xf;
4229
4230 if (rt == 0x0f)
4231 sprintf(cp, "PLD\t");
4232 else
4233 sprintf(cp, "LDRB.W\tr%d, ", rt);
4234 immed = (opcode >> 4) & 0x3;
4235 cp = strchr(cp, 0);
4236 sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed);
4237 return ERROR_OK;
4238 }
4239 break;
4240 case 1:
4241 if ((rn & rt) == 0xf)
4242 goto pld_literal;
4243 if (rt == 0xf) {
4244 immed = opcode & 0xfff;
4245 goto preload_immediate;
4246 }
4247 if (rn == 0x0f)
4248 goto ldrb_literal;
4249 mnemonic = "LDRB.W";
4250 immed = opcode & 0xfff;
4251 goto ldrxb_immediate_t2;
4252 case 2:
4253 if ((rn & rt) == 0xf) {
4254 immed = opcode & 0xfff;
4255 address = thumb_alignpc4(address);
4256 if (opcode & (1 << 23))
4257 address += immed;
4258 else
4259 address -= immed;
4260 sprintf(cp, "PLI\t%#8.8" PRIx32, address);
4261 return ERROR_OK;
4262 }
4263 if (rn == 0xf && rt != 0xf) {
4264 ldrsb_literal:
4265 immed = opcode & 0xfff;
4266 address = thumb_alignpc4(address);
4267 if (opcode & (1 << 23))
4268 address += immed;
4269 else
4270 address -= immed;
4271 sprintf(cp, "LDRSB\t%#8.8" PRIx32, address);
4272 return ERROR_OK;
4273 }
4274 if (rn == 0xf)
4275 break;
4276 if ((op2 & 0x3c) == 0x38) {
4277 immed = opcode & 0xff;
4278 sprintf(cp, "LDRSBT\tr%d, [r%d, #%d]\t; %#2.2x",
4279 rt, rn, immed, immed);
4280 return ERROR_OK;
4281 }
4282 if ((op2 & 0x3c) == 0x30) {
4283 if (rt == 0xf) {
4284 immed = opcode & 0xff;
4285 immed = -immed; /* pli */
4286 sprintf(cp, "PLI\t[r%d, #%d]\t; -%#2.2x",
4287 rn, immed, -immed);
4288 return ERROR_OK;
4289 }
4290 mnemonic = "LDRSB";
4291 goto ldrxb_immediate_t3;
4292 }
4293 if ((op2 & 0x24) == 0x24) {
4294 mnemonic = "LDRSB";
4295 goto ldrxb_immediate_t3;
4296 }
4297 if (op2 == 0) {
4298 int rm = opcode & 0xf;
4299
4300 if (rt == 0x0f)
4301 sprintf(cp, "PLI\t");
4302 else
4303 sprintf(cp, "LDRSB.W\tr%d, ", rt);
4304 immed = (opcode >> 4) & 0x3;
4305 cp = strchr(cp, 0);
4306 sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed);
4307 return ERROR_OK;
4308 }
4309 break;
4310 case 3:
4311 if (rt == 0xf) {
4312 immed = opcode & 0xfff;
4313 sprintf(cp, "PLI\t[r%d, #%d]\t; %#3.3x",
4314 rn, immed, immed);
4315 return ERROR_OK;
4316 }
4317 if (rn == 0xf)
4318 goto ldrsb_literal;
4319 immed = opcode & 0xfff;
4320 mnemonic = "LDRSB";
4321 goto ldrxb_immediate_t2;
4322 }
4323
4324 return ERROR_COMMAND_SYNTAX_ERROR;
4325 }
4326
4327 static int t2ev_load_halfword(uint32_t opcode, uint32_t address,
4328 struct arm_instruction *instruction, char *cp)
4329 {
4330 int rn = (opcode >> 16) & 0xf;
4331 int rt = (opcode >> 12) & 0xf;
4332 int op2 = (opcode >> 6) & 0x3f;
4333 char *sign = "";
4334 unsigned immed;
4335
4336 if (rt == 0xf) {
4337 sprintf(cp, "HINT (UNALLOCATED)");
4338 return ERROR_OK;
4339 }
4340
4341 if (opcode & (1 << 24))
4342 sign = "S";
4343
4344 if ((opcode & (1 << 23)) == 0) {
4345 if (rn == 0xf) {
4346 ldrh_literal:
4347 immed = opcode & 0xfff;
4348 address = thumb_alignpc4(address);
4349 if (opcode & (1 << 23))
4350 address += immed;
4351 else
4352 address -= immed;
4353 sprintf(cp, "LDR%sH\tr%d, %#8.8" PRIx32,
4354 sign, rt, address);
4355 return ERROR_OK;
4356 }
4357 if (op2 == 0) {
4358 int rm = opcode & 0xf;
4359
4360 immed = (opcode >> 4) & 0x3;
4361 sprintf(cp, "LDR%sH.W\tr%d, [r%d, r%d, LSL #%d]",
4362 sign, rt, rn, rm, immed);
4363 return ERROR_OK;
4364 }
4365 if ((op2 & 0x3c) == 0x38) {
4366 immed = opcode & 0xff;
4367 sprintf(cp, "LDR%sHT\tr%d, [r%d, #%d]\t; %#2.2x",
4368 sign, rt, rn, immed, immed);
4369 return ERROR_OK;
4370 }
4371 if ((op2 & 0x3c) == 0x30 || (op2 & 0x24) == 0x24) {
4372 char *p1 = "", *p2 = "]";
4373
4374 immed = opcode & 0xff;
4375 if (!(opcode & 0x200))
4376 immed = -immed;
4377
4378 /* two indexed modes will write back rn */
4379 if (opcode & 0x100) {
4380 if (opcode & 0x400) /* pre-indexed */
4381 p2 = "]!";
4382 else { /* post-indexed */
4383 p1 = "]";
4384 p2 = "";
4385 }
4386 }
4387 sprintf(cp, "LDR%sH\tr%d, [r%d%s, #%d%s\t; %#8.8x",
4388 sign, rt, rn, p1, immed, p2, immed);
4389 return ERROR_OK;
4390 }
4391 } else {
4392 if (rn == 0xf)
4393 goto ldrh_literal;
4394
4395 immed = opcode & 0xfff;
4396 sprintf(cp, "LDR%sH%s\tr%d, [r%d, #%d]\t; %#6.6x",
4397 sign, *sign ? "" : ".W",
4398 rt, rn, immed, immed);
4399 return ERROR_OK;
4400 }
4401
4402 return ERROR_COMMAND_SYNTAX_ERROR;
4403 }
4404
4405 /*
4406 * REVISIT for Thumb2 instructions, instruction->type and friends aren't
4407 * always set. That means eventual arm_simulate_step() support for Thumb2
4408 * will need work in this area.
4409 */
4410 int thumb2_opcode(struct target *target, uint32_t address, struct arm_instruction *instruction)
4411 {
4412 int retval;
4413 uint16_t op;
4414 uint32_t opcode;
4415 char *cp;
4416
4417 /* clear low bit ... it's set on function pointers */
4418 address &= ~1;
4419
4420 /* clear fields, to avoid confusion */
4421 memset(instruction, 0, sizeof(struct arm_instruction));
4422
4423 /* read first halfword, see if this is the only one */
4424 retval = target_read_u16(target, address, &op);
4425 if (retval != ERROR_OK)
4426 return retval;
4427
4428 switch (op & 0xf800) {
4429 case 0xf800:
4430 case 0xf000:
4431 case 0xe800:
4432 /* 32-bit instructions */
4433 instruction->instruction_size = 4;
4434 opcode = op << 16;
4435 retval = target_read_u16(target, address + 2, &op);
4436 if (retval != ERROR_OK)
4437 return retval;
4438 opcode |= op;
4439 instruction->opcode = opcode;
4440 break;
4441 default:
4442 /* 16-bit: Thumb1 + IT + CBZ/CBNZ + ... */
4443 return thumb_evaluate_opcode(op, address, instruction);
4444 }
4445
4446 snprintf(instruction->text, 128,
4447 "0x%8.8" PRIx32 " 0x%8.8" PRIx32 "\t",
4448 address, opcode);
4449 cp = strchr(instruction->text, 0);
4450 retval = ERROR_FAIL;
4451
4452 /* ARMv7-M: A5.3.1 Data processing (modified immediate) */
4453 if ((opcode & 0x1a008000) == 0x10000000)
4454 retval = t2ev_data_mod_immed(opcode, address, instruction, cp);
4455
4456 /* ARMv7-M: A5.3.3 Data processing (plain binary immediate) */
4457 else if ((opcode & 0x1a008000) == 0x12000000)
4458 retval = t2ev_data_immed(opcode, address, instruction, cp);
4459
4460 /* ARMv7-M: A5.3.4 Branches and miscellaneous control */
4461 else if ((opcode & 0x18008000) == 0x10008000)
4462 retval = t2ev_b_misc(opcode, address, instruction, cp);
4463
4464 /* ARMv7-M: A5.3.5 Load/store multiple */
4465 else if ((opcode & 0x1e400000) == 0x08000000)
4466 retval = t2ev_ldm_stm(opcode, address, instruction, cp);
4467
4468 /* ARMv7-M: A5.3.6 Load/store dual or exclusive, table branch */
4469 else if ((opcode & 0x1e400000) == 0x08400000)
4470 retval = t2ev_ldrex_strex(opcode, address, instruction, cp);
4471
4472 /* ARMv7-M: A5.3.7 Load word */
4473 else if ((opcode & 0x1f700000) == 0x18500000)
4474 retval = t2ev_load_word(opcode, address, instruction, cp);
4475
4476 /* ARMv7-M: A5.3.8 Load halfword, unallocated memory hints */
4477 else if ((opcode & 0x1e700000) == 0x18300000)
4478 retval = t2ev_load_halfword(opcode, address, instruction, cp);
4479
4480 /* ARMv7-M: A5.3.9 Load byte, memory hints */
4481 else if ((opcode & 0x1e700000) == 0x18100000)
4482 retval = t2ev_load_byte_hints(opcode, address, instruction, cp);
4483
4484 /* ARMv7-M: A5.3.10 Store single data item */
4485 else if ((opcode & 0x1f100000) == 0x18000000)
4486 retval = t2ev_store_single(opcode, address, instruction, cp);
4487
4488 /* ARMv7-M: A5.3.11 Data processing (shifted register) */
4489 else if ((opcode & 0x1e000000) == 0x0a000000)
4490 retval = t2ev_data_shift(opcode, address, instruction, cp);
4491
4492 /* ARMv7-M: A5.3.12 Data processing (register)
4493 * and A5.3.13 Miscellaneous operations
4494 */
4495 else if ((opcode & 0x1f000000) == 0x1a000000)
4496 retval = t2ev_data_reg(opcode, address, instruction, cp);
4497
4498 /* ARMv7-M: A5.3.14 Multiply, and multiply accumulate */
4499 else if ((opcode & 0x1f800000) == 0x1b000000)
4500 retval = t2ev_mul32(opcode, address, instruction, cp);
4501
4502 /* ARMv7-M: A5.3.15 Long multiply, long multiply accumulate, divide */
4503 else if ((opcode & 0x1f800000) == 0x1b800000)
4504 retval = t2ev_mul64_div(opcode, address, instruction, cp);
4505
4506 if (retval == ERROR_OK)
4507 return retval;
4508
4509 /*
4510 * Thumb2 also supports coprocessor, ThumbEE, and DSP/Media (SIMD)
4511 * instructions; not yet handled here.
4512 */
4513
4514 if (retval == ERROR_COMMAND_SYNTAX_ERROR) {
4515 instruction->type = ARM_UNDEFINED_INSTRUCTION;
4516 strcpy(cp, "UNDEFINED OPCODE");
4517 return ERROR_OK;
4518 }
4519
4520 LOG_DEBUG("Can't decode 32-bit Thumb2 yet (opcode=%08" PRIx32 ")",
4521 opcode);
4522
4523 strcpy(cp, "(32-bit Thumb2 ...)");
4524 return ERROR_OK;
4525 }
4526
4527 int arm_access_size(struct arm_instruction *instruction)
4528 {
4529 if ((instruction->type == ARM_LDRB)
4530 || (instruction->type == ARM_LDRBT)
4531 || (instruction->type == ARM_LDRSB)
4532 || (instruction->type == ARM_STRB)
4533 || (instruction->type == ARM_STRBT))
4534 return 1;
4535 else if ((instruction->type == ARM_LDRH)
4536 || (instruction->type == ARM_LDRSH)
4537 || (instruction->type == ARM_STRH))
4538 return 2;
4539 else if ((instruction->type == ARM_LDR)
4540 || (instruction->type == ARM_LDRT)
4541 || (instruction->type == ARM_STR)
4542 || (instruction->type == ARM_STRT))
4543 return 4;
4544 else if ((instruction->type == ARM_LDRD)
4545 || (instruction->type == ARM_STRD))
4546 return 8;
4547 else {
4548 LOG_ERROR("BUG: instruction type %i isn't a load/store instruction",
4549 instruction->type);
4550 return 0;
4551 }
4552 }

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)