f432f57ca42e69408e96586da0ab5e402ed8163c
[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_data_proc(uint32_t opcode,
1619 uint32_t address, struct arm_instruction *instruction)
1620 {
1621 uint8_t I, op, S, Rn, Rd;
1622 char *mnemonic = NULL;
1623 char shifter_operand[32];
1624
1625 I = (opcode & 0x02000000) >> 25;
1626 op = (opcode & 0x01e00000) >> 21;
1627 S = (opcode & 0x00100000) >> 20;
1628
1629 Rd = (opcode & 0xf000) >> 12;
1630 Rn = (opcode & 0xf0000) >> 16;
1631
1632 instruction->info.data_proc.Rd = Rd;
1633 instruction->info.data_proc.Rn = Rn;
1634 instruction->info.data_proc.S = S;
1635
1636 switch (op) {
1637 case 0x0:
1638 instruction->type = ARM_AND;
1639 mnemonic = "AND";
1640 break;
1641 case 0x1:
1642 instruction->type = ARM_EOR;
1643 mnemonic = "EOR";
1644 break;
1645 case 0x2:
1646 instruction->type = ARM_SUB;
1647 mnemonic = "SUB";
1648 break;
1649 case 0x3:
1650 instruction->type = ARM_RSB;
1651 mnemonic = "RSB";
1652 break;
1653 case 0x4:
1654 instruction->type = ARM_ADD;
1655 mnemonic = "ADD";
1656 break;
1657 case 0x5:
1658 instruction->type = ARM_ADC;
1659 mnemonic = "ADC";
1660 break;
1661 case 0x6:
1662 instruction->type = ARM_SBC;
1663 mnemonic = "SBC";
1664 break;
1665 case 0x7:
1666 instruction->type = ARM_RSC;
1667 mnemonic = "RSC";
1668 break;
1669 case 0x8:
1670 instruction->type = ARM_TST;
1671 mnemonic = "TST";
1672 break;
1673 case 0x9:
1674 instruction->type = ARM_TEQ;
1675 mnemonic = "TEQ";
1676 break;
1677 case 0xa:
1678 instruction->type = ARM_CMP;
1679 mnemonic = "CMP";
1680 break;
1681 case 0xb:
1682 instruction->type = ARM_CMN;
1683 mnemonic = "CMN";
1684 break;
1685 case 0xc:
1686 instruction->type = ARM_ORR;
1687 mnemonic = "ORR";
1688 break;
1689 case 0xd:
1690 instruction->type = ARM_MOV;
1691 mnemonic = "MOV";
1692 break;
1693 case 0xe:
1694 instruction->type = ARM_BIC;
1695 mnemonic = "BIC";
1696 break;
1697 case 0xf:
1698 instruction->type = ARM_MVN;
1699 mnemonic = "MVN";
1700 break;
1701 }
1702
1703 if (I) {/* immediate shifter operand (#<immediate>)*/
1704 uint8_t immed_8 = opcode & 0xff;
1705 uint8_t rotate_imm = (opcode & 0xf00) >> 8;
1706 uint32_t immediate;
1707
1708 immediate = ror(immed_8, rotate_imm * 2);
1709
1710 snprintf(shifter_operand, 32, "#0x%" PRIx32 "", immediate);
1711
1712 instruction->info.data_proc.variant = 0;
1713 instruction->info.data_proc.shifter_operand.immediate.immediate = immediate;
1714 } else {/* register-based shifter operand */
1715 uint8_t shift, Rm;
1716 shift = (opcode & 0x60) >> 5;
1717 Rm = (opcode & 0xf);
1718
1719 if ((opcode & 0x10) != 0x10) { /* Immediate shifts ("<Rm>" or "<Rm>, <shift>
1720 *#<shift_immediate>") */
1721 uint8_t shift_imm;
1722 shift_imm = (opcode & 0xf80) >> 7;
1723
1724 instruction->info.data_proc.variant = 1;
1725 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1726 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm =
1727 shift_imm;
1728 instruction->info.data_proc.shifter_operand.immediate_shift.shift = shift;
1729
1730 /* LSR encodes a shift by 32 bit as 0x0 */
1731 if ((shift == 0x1) && (shift_imm == 0x0))
1732 shift_imm = 0x20;
1733
1734 /* ASR encodes a shift by 32 bit as 0x0 */
1735 if ((shift == 0x2) && (shift_imm == 0x0))
1736 shift_imm = 0x20;
1737
1738 /* ROR by 32 bit is actually a RRX */
1739 if ((shift == 0x3) && (shift_imm == 0x0))
1740 shift = 0x4;
1741
1742 if ((shift_imm == 0x0) && (shift == 0x0))
1743 snprintf(shifter_operand, 32, "r%i", Rm);
1744 else {
1745 if (shift == 0x0) /* LSL */
1746 snprintf(shifter_operand,
1747 32,
1748 "r%i, LSL #0x%x",
1749 Rm,
1750 shift_imm);
1751 else if (shift == 0x1) /* LSR */
1752 snprintf(shifter_operand,
1753 32,
1754 "r%i, LSR #0x%x",
1755 Rm,
1756 shift_imm);
1757 else if (shift == 0x2) /* ASR */
1758 snprintf(shifter_operand,
1759 32,
1760 "r%i, ASR #0x%x",
1761 Rm,
1762 shift_imm);
1763 else if (shift == 0x3) /* ROR */
1764 snprintf(shifter_operand,
1765 32,
1766 "r%i, ROR #0x%x",
1767 Rm,
1768 shift_imm);
1769 else if (shift == 0x4) /* RRX */
1770 snprintf(shifter_operand, 32, "r%i, RRX", Rm);
1771 }
1772 } else {/* Register shifts ("<Rm>, <shift> <Rs>") */
1773 uint8_t Rs = (opcode & 0xf00) >> 8;
1774
1775 instruction->info.data_proc.variant = 2;
1776 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rm;
1777 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rs;
1778 instruction->info.data_proc.shifter_operand.register_shift.shift = shift;
1779
1780 if (shift == 0x0) /* LSL */
1781 snprintf(shifter_operand, 32, "r%i, LSL r%i", Rm, Rs);
1782 else if (shift == 0x1) /* LSR */
1783 snprintf(shifter_operand, 32, "r%i, LSR r%i", Rm, Rs);
1784 else if (shift == 0x2) /* ASR */
1785 snprintf(shifter_operand, 32, "r%i, ASR r%i", Rm, Rs);
1786 else if (shift == 0x3) /* ROR */
1787 snprintf(shifter_operand, 32, "r%i, ROR r%i", Rm, Rs);
1788 }
1789 }
1790
1791 if ((op < 0x8) || (op == 0xc) || (op == 0xe)) { /* <opcode3>{<cond>}{S} <Rd>, <Rn>,
1792 *<shifter_operand> */
1793 snprintf(instruction->text,
1794 128,
1795 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, %s",
1796 address,
1797 opcode,
1798 mnemonic,
1799 COND(opcode),
1800 (S) ? "S" : "",
1801 Rd,
1802 Rn,
1803 shifter_operand);
1804 } else if ((op == 0xd) || (op == 0xf)) { /* <opcode1>{<cond>}{S} <Rd>,
1805 *<shifter_operand> */
1806 if (opcode == 0xe1a00000) /* print MOV r0,r0 as NOP */
1807 snprintf(instruction->text,
1808 128,
1809 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tNOP",
1810 address,
1811 opcode);
1812 else
1813 snprintf(instruction->text,
1814 128,
1815 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, %s",
1816 address,
1817 opcode,
1818 mnemonic,
1819 COND(opcode),
1820 (S) ? "S" : "",
1821 Rd,
1822 shifter_operand);
1823 } else {/* <opcode2>{<cond>} <Rn>, <shifter_operand> */
1824 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, %s",
1825 address, opcode, mnemonic, COND(opcode),
1826 Rn, shifter_operand);
1827 }
1828
1829 return ERROR_OK;
1830 }
1831
1832 int arm_evaluate_opcode(uint32_t opcode, uint32_t address,
1833 struct arm_instruction *instruction)
1834 {
1835 /* clear fields, to avoid confusion */
1836 memset(instruction, 0, sizeof(struct arm_instruction));
1837 instruction->opcode = opcode;
1838 instruction->instruction_size = 4;
1839
1840 /* catch opcodes with condition field [31:28] = b1111 */
1841 if ((opcode & 0xf0000000) == 0xf0000000) {
1842 /* Undefined instruction (or ARMv5E cache preload PLD) */
1843 if ((opcode & 0x08000000) == 0x00000000)
1844 return evaluate_pld(opcode, address, instruction);
1845
1846 /* Undefined instruction (or ARMv6+ SRS/RFE) */
1847 if ((opcode & 0x0e000000) == 0x08000000)
1848 return evaluate_srs(opcode, address, instruction);
1849
1850 /* Branch and branch with link and change to Thumb */
1851 if ((opcode & 0x0e000000) == 0x0a000000)
1852 return evaluate_blx_imm(opcode, address, instruction);
1853
1854 /* Extended coprocessor opcode space (ARMv5 and higher)
1855 * Coprocessor load/store and double register transfers */
1856 if ((opcode & 0x0e000000) == 0x0c000000)
1857 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1858
1859 /* Coprocessor data processing */
1860 if ((opcode & 0x0f000100) == 0x0c000000)
1861 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1862
1863 /* Coprocessor register transfers */
1864 if ((opcode & 0x0f000010) == 0x0c000010)
1865 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1866
1867 /* Undefined instruction */
1868 if ((opcode & 0x0f000000) == 0x0f000000) {
1869 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1870 snprintf(instruction->text,
1871 128,
1872 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
1873 address,
1874 opcode);
1875 return ERROR_OK;
1876 }
1877 }
1878
1879 /* catch opcodes with [27:25] = b000 */
1880 if ((opcode & 0x0e000000) == 0x00000000) {
1881 /* Multiplies, extra load/stores */
1882 if ((opcode & 0x00000090) == 0x00000090)
1883 return evaluate_mul_and_extra_ld_st(opcode, address, instruction);
1884
1885 /* Miscellaneous instructions */
1886 if ((opcode & 0x0f900000) == 0x01000000)
1887 return evaluate_misc_instr(opcode, address, instruction);
1888
1889 return evaluate_data_proc(opcode, address, instruction);
1890 }
1891
1892 /* catch opcodes with [27:25] = b001 */
1893 if ((opcode & 0x0e000000) == 0x02000000) {
1894 /* Undefined instruction */
1895 if ((opcode & 0x0fb00000) == 0x03000000) {
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 /* Move immediate to status register */
1906 if ((opcode & 0x0fb00000) == 0x03200000)
1907 return evaluate_mrs_msr(opcode, address, instruction);
1908
1909 return evaluate_data_proc(opcode, address, instruction);
1910
1911 }
1912
1913 /* catch opcodes with [27:25] = b010 */
1914 if ((opcode & 0x0e000000) == 0x04000000) {
1915 /* Load/store immediate offset */
1916 return evaluate_load_store(opcode, address, instruction);
1917 }
1918
1919 /* catch opcodes with [27:25] = b011 */
1920 if ((opcode & 0x0e000000) == 0x06000000) {
1921 /* Load/store register offset */
1922 if ((opcode & 0x00000010) == 0x00000000)
1923 return evaluate_load_store(opcode, address, instruction);
1924
1925 /* Architecturally Undefined instruction
1926 * ... don't expect these to ever be used
1927 */
1928 if ((opcode & 0x07f000f0) == 0x07f000f0) {
1929 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1930 snprintf(instruction->text, 128,
1931 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEF",
1932 address, opcode);
1933 return ERROR_OK;
1934 }
1935
1936 /* "media" instructions */
1937 return evaluate_media(opcode, address, instruction);
1938 }
1939
1940 /* catch opcodes with [27:25] = b100 */
1941 if ((opcode & 0x0e000000) == 0x08000000) {
1942 /* Load/store multiple */
1943 return evaluate_ldm_stm(opcode, address, instruction);
1944 }
1945
1946 /* catch opcodes with [27:25] = b101 */
1947 if ((opcode & 0x0e000000) == 0x0a000000) {
1948 /* Branch and branch with link */
1949 return evaluate_b_bl(opcode, address, instruction);
1950 }
1951
1952 /* catch opcodes with [27:25] = b110 */
1953 if ((opcode & 0x0e000000) == 0x0c000000) {
1954 /* Coprocessor load/store and double register transfers */
1955 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1956 }
1957
1958 /* catch opcodes with [27:25] = b111 */
1959 if ((opcode & 0x0e000000) == 0x0e000000) {
1960 /* Software interrupt */
1961 if ((opcode & 0x0f000000) == 0x0f000000)
1962 return evaluate_swi(opcode, address, instruction);
1963
1964 /* Coprocessor data processing */
1965 if ((opcode & 0x0f000010) == 0x0e000000)
1966 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1967
1968 /* Coprocessor register transfers */
1969 if ((opcode & 0x0f000010) == 0x0e000010)
1970 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1971 }
1972
1973 LOG_ERROR("ARM: should never reach this point (opcode=%08x)",
1974 (unsigned) opcode);
1975 return -1;
1976 }
1977
1978 static int evaluate_b_bl_blx_thumb(uint16_t opcode,
1979 uint32_t address, struct arm_instruction *instruction)
1980 {
1981 uint32_t offset = opcode & 0x7ff;
1982 uint32_t opc = (opcode >> 11) & 0x3;
1983 uint32_t target_address;
1984 char *mnemonic = NULL;
1985
1986 /* sign extend 11-bit offset */
1987 if (((opc == 0) || (opc == 2)) && (offset & 0x00000400))
1988 offset = 0xfffff800 | offset;
1989
1990 target_address = address + 4 + (offset << 1);
1991
1992 switch (opc) {
1993 /* unconditional branch */
1994 case 0:
1995 instruction->type = ARM_B;
1996 mnemonic = "B";
1997 break;
1998 /* BLX suffix */
1999 case 1:
2000 instruction->type = ARM_BLX;
2001 mnemonic = "BLX";
2002 target_address &= 0xfffffffc;
2003 break;
2004 /* BL/BLX prefix */
2005 case 2:
2006 instruction->type = ARM_UNKNOWN_INSTUCTION;
2007 mnemonic = "prefix";
2008 target_address = offset << 12;
2009 break;
2010 /* BL suffix */
2011 case 3:
2012 instruction->type = ARM_BL;
2013 mnemonic = "BL";
2014 break;
2015 }
2016
2017 /* TODO: deal correctly with dual opcode (prefixed) BL/BLX;
2018 * these are effectively 32-bit instructions even in Thumb1. For
2019 * disassembly, it's simplest to always use the Thumb2 decoder.
2020 *
2021 * But some cores will evidently handle them as two instructions,
2022 * where exceptions may occur between the two. The ETMv3.2+ ID
2023 * register has a bit which exposes this behavior.
2024 */
2025
2026 snprintf(instruction->text, 128,
2027 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%#8.8" PRIx32,
2028 address, opcode, mnemonic, target_address);
2029
2030 instruction->info.b_bl_bx_blx.reg_operand = -1;
2031 instruction->info.b_bl_bx_blx.target_address = target_address;
2032
2033 return ERROR_OK;
2034 }
2035
2036 static int evaluate_add_sub_thumb(uint16_t opcode,
2037 uint32_t address, struct arm_instruction *instruction)
2038 {
2039 uint8_t Rd = (opcode >> 0) & 0x7;
2040 uint8_t Rn = (opcode >> 3) & 0x7;
2041 uint8_t Rm_imm = (opcode >> 6) & 0x7;
2042 uint32_t opc = opcode & (1 << 9);
2043 uint32_t reg_imm = opcode & (1 << 10);
2044 char *mnemonic;
2045
2046 if (opc) {
2047 instruction->type = ARM_SUB;
2048 mnemonic = "SUBS";
2049 } else {
2050 /* REVISIT: if reg_imm == 0, display as "MOVS" */
2051 instruction->type = ARM_ADD;
2052 mnemonic = "ADDS";
2053 }
2054
2055 instruction->info.data_proc.Rd = Rd;
2056 instruction->info.data_proc.Rn = Rn;
2057 instruction->info.data_proc.S = 1;
2058
2059 if (reg_imm) {
2060 instruction->info.data_proc.variant = 0;/*immediate*/
2061 instruction->info.data_proc.shifter_operand.immediate.immediate = Rm_imm;
2062 snprintf(instruction->text, 128,
2063 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%d",
2064 address, opcode, mnemonic, Rd, Rn, Rm_imm);
2065 } else {
2066 instruction->info.data_proc.variant = 1;/*immediate shift*/
2067 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm_imm;
2068 snprintf(instruction->text, 128,
2069 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, r%i",
2070 address, opcode, mnemonic, Rd, Rn, Rm_imm);
2071 }
2072
2073 return ERROR_OK;
2074 }
2075
2076 static int evaluate_shift_imm_thumb(uint16_t opcode,
2077 uint32_t address, struct arm_instruction *instruction)
2078 {
2079 uint8_t Rd = (opcode >> 0) & 0x7;
2080 uint8_t Rm = (opcode >> 3) & 0x7;
2081 uint8_t imm = (opcode >> 6) & 0x1f;
2082 uint8_t opc = (opcode >> 11) & 0x3;
2083 char *mnemonic = NULL;
2084
2085 switch (opc) {
2086 case 0:
2087 instruction->type = ARM_MOV;
2088 mnemonic = "LSLS";
2089 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 0;
2090 break;
2091 case 1:
2092 instruction->type = ARM_MOV;
2093 mnemonic = "LSRS";
2094 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 1;
2095 break;
2096 case 2:
2097 instruction->type = ARM_MOV;
2098 mnemonic = "ASRS";
2099 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 2;
2100 break;
2101 }
2102
2103 if ((imm == 0) && (opc != 0))
2104 imm = 32;
2105
2106 instruction->info.data_proc.Rd = Rd;
2107 instruction->info.data_proc.Rn = -1;
2108 instruction->info.data_proc.S = 1;
2109
2110 instruction->info.data_proc.variant = 1;/*immediate_shift*/
2111 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
2112 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = imm;
2113
2114 snprintf(instruction->text, 128,
2115 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%#2.2x",
2116 address, opcode, mnemonic, Rd, Rm, imm);
2117
2118 return ERROR_OK;
2119 }
2120
2121 static int evaluate_data_proc_imm_thumb(uint16_t opcode,
2122 uint32_t address, struct arm_instruction *instruction)
2123 {
2124 uint8_t imm = opcode & 0xff;
2125 uint8_t Rd = (opcode >> 8) & 0x7;
2126 uint32_t opc = (opcode >> 11) & 0x3;
2127 char *mnemonic = NULL;
2128
2129 instruction->info.data_proc.Rd = Rd;
2130 instruction->info.data_proc.Rn = Rd;
2131 instruction->info.data_proc.S = 1;
2132 instruction->info.data_proc.variant = 0;/*immediate*/
2133 instruction->info.data_proc.shifter_operand.immediate.immediate = imm;
2134
2135 switch (opc) {
2136 case 0:
2137 instruction->type = ARM_MOV;
2138 mnemonic = "MOVS";
2139 instruction->info.data_proc.Rn = -1;
2140 break;
2141 case 1:
2142 instruction->type = ARM_CMP;
2143 mnemonic = "CMP";
2144 instruction->info.data_proc.Rd = -1;
2145 break;
2146 case 2:
2147 instruction->type = ARM_ADD;
2148 mnemonic = "ADDS";
2149 break;
2150 case 3:
2151 instruction->type = ARM_SUB;
2152 mnemonic = "SUBS";
2153 break;
2154 }
2155
2156 snprintf(instruction->text, 128,
2157 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, #%#2.2x",
2158 address, opcode, mnemonic, Rd, imm);
2159
2160 return ERROR_OK;
2161 }
2162
2163 static int evaluate_data_proc_thumb(uint16_t opcode,
2164 uint32_t address, struct arm_instruction *instruction)
2165 {
2166 uint8_t high_reg, op, Rm, Rd, H1, H2;
2167 char *mnemonic = NULL;
2168 bool nop = false;
2169
2170 high_reg = (opcode & 0x0400) >> 10;
2171 op = (opcode & 0x03C0) >> 6;
2172
2173 Rd = (opcode & 0x0007);
2174 Rm = (opcode & 0x0038) >> 3;
2175 H1 = (opcode & 0x0080) >> 7;
2176 H2 = (opcode & 0x0040) >> 6;
2177
2178 instruction->info.data_proc.Rd = Rd;
2179 instruction->info.data_proc.Rn = Rd;
2180 instruction->info.data_proc.S = (!high_reg || (instruction->type == ARM_CMP));
2181 instruction->info.data_proc.variant = 1 /*immediate shift*/;
2182 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
2183
2184 if (high_reg) {
2185 Rd |= H1 << 3;
2186 Rm |= H2 << 3;
2187 op >>= 2;
2188
2189 switch (op) {
2190 case 0x0:
2191 instruction->type = ARM_ADD;
2192 mnemonic = "ADD";
2193 break;
2194 case 0x1:
2195 instruction->type = ARM_CMP;
2196 mnemonic = "CMP";
2197 break;
2198 case 0x2:
2199 instruction->type = ARM_MOV;
2200 mnemonic = "MOV";
2201 if (Rd == Rm)
2202 nop = true;
2203 break;
2204 case 0x3:
2205 if ((opcode & 0x7) == 0x0) {
2206 instruction->info.b_bl_bx_blx.reg_operand = Rm;
2207 if (H1) {
2208 instruction->type = ARM_BLX;
2209 snprintf(instruction->text, 128,
2210 "0x%8.8" PRIx32
2211 " 0x%4.4x \tBLX\tr%i",
2212 address, opcode, Rm);
2213 } else {
2214 instruction->type = ARM_BX;
2215 snprintf(instruction->text, 128,
2216 "0x%8.8" PRIx32
2217 " 0x%4.4x \tBX\tr%i",
2218 address, opcode, Rm);
2219 }
2220 } else {
2221 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2222 snprintf(instruction->text, 128,
2223 "0x%8.8" PRIx32
2224 " 0x%4.4x \t"
2225 "UNDEFINED INSTRUCTION",
2226 address, opcode);
2227 }
2228 return ERROR_OK;
2229 break;
2230 }
2231 } else {
2232 switch (op) {
2233 case 0x0:
2234 instruction->type = ARM_AND;
2235 mnemonic = "ANDS";
2236 break;
2237 case 0x1:
2238 instruction->type = ARM_EOR;
2239 mnemonic = "EORS";
2240 break;
2241 case 0x2:
2242 instruction->type = ARM_MOV;
2243 mnemonic = "LSLS";
2244 instruction->info.data_proc.variant = 2 /*register shift*/;
2245 instruction->info.data_proc.shifter_operand.register_shift.shift = 0;
2246 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
2247 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
2248 break;
2249 case 0x3:
2250 instruction->type = ARM_MOV;
2251 mnemonic = "LSRS";
2252 instruction->info.data_proc.variant = 2 /*register shift*/;
2253 instruction->info.data_proc.shifter_operand.register_shift.shift = 1;
2254 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
2255 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
2256 break;
2257 case 0x4:
2258 instruction->type = ARM_MOV;
2259 mnemonic = "ASRS";
2260 instruction->info.data_proc.variant = 2 /*register shift*/;
2261 instruction->info.data_proc.shifter_operand.register_shift.shift = 2;
2262 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
2263 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
2264 break;
2265 case 0x5:
2266 instruction->type = ARM_ADC;
2267 mnemonic = "ADCS";
2268 break;
2269 case 0x6:
2270 instruction->type = ARM_SBC;
2271 mnemonic = "SBCS";
2272 break;
2273 case 0x7:
2274 instruction->type = ARM_MOV;
2275 mnemonic = "RORS";
2276 instruction->info.data_proc.variant = 2 /*register shift*/;
2277 instruction->info.data_proc.shifter_operand.register_shift.shift = 3;
2278 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
2279 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
2280 break;
2281 case 0x8:
2282 instruction->type = ARM_TST;
2283 mnemonic = "TST";
2284 break;
2285 case 0x9:
2286 instruction->type = ARM_RSB;
2287 mnemonic = "RSBS";
2288 instruction->info.data_proc.variant = 0 /*immediate*/;
2289 instruction->info.data_proc.shifter_operand.immediate.immediate = 0;
2290 instruction->info.data_proc.Rn = Rm;
2291 break;
2292 case 0xA:
2293 instruction->type = ARM_CMP;
2294 mnemonic = "CMP";
2295 break;
2296 case 0xB:
2297 instruction->type = ARM_CMN;
2298 mnemonic = "CMN";
2299 break;
2300 case 0xC:
2301 instruction->type = ARM_ORR;
2302 mnemonic = "ORRS";
2303 break;
2304 case 0xD:
2305 instruction->type = ARM_MUL;
2306 mnemonic = "MULS";
2307 break;
2308 case 0xE:
2309 instruction->type = ARM_BIC;
2310 mnemonic = "BICS";
2311 break;
2312 case 0xF:
2313 instruction->type = ARM_MVN;
2314 mnemonic = "MVNS";
2315 break;
2316 }
2317 }
2318
2319 if (nop)
2320 snprintf(instruction->text, 128,
2321 "0x%8.8" PRIx32 " 0x%4.4x \tNOP\t\t\t"
2322 "; (%s r%i, r%i)",
2323 address, opcode, mnemonic, Rd, Rm);
2324 else
2325 snprintf(instruction->text, 128,
2326 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i",
2327 address, opcode, mnemonic, Rd, Rm);
2328
2329 return ERROR_OK;
2330 }
2331
2332 /* PC-relative data addressing is word-aligned even with Thumb */
2333 static inline uint32_t thumb_alignpc4(uint32_t addr)
2334 {
2335 return (addr + 4) & ~3;
2336 }
2337
2338 static int evaluate_load_literal_thumb(uint16_t opcode,
2339 uint32_t address, struct arm_instruction *instruction)
2340 {
2341 uint32_t immediate;
2342 uint8_t Rd = (opcode >> 8) & 0x7;
2343
2344 instruction->type = ARM_LDR;
2345 immediate = opcode & 0x000000ff;
2346 immediate *= 4;
2347
2348 instruction->info.load_store.Rd = Rd;
2349 instruction->info.load_store.Rn = 15 /*PC*/;
2350 instruction->info.load_store.index_mode = 0; /*offset*/
2351 instruction->info.load_store.offset_mode = 0; /*immediate*/
2352 instruction->info.load_store.offset.offset = immediate;
2353
2354 snprintf(instruction->text, 128,
2355 "0x%8.8" PRIx32 " 0x%4.4x \t"
2356 "LDR\tr%i, [pc, #%#" PRIx32 "]\t; %#8.8" PRIx32,
2357 address, opcode, Rd, immediate,
2358 thumb_alignpc4(address) + immediate);
2359
2360 return ERROR_OK;
2361 }
2362
2363 static int evaluate_load_store_reg_thumb(uint16_t opcode,
2364 uint32_t address, struct arm_instruction *instruction)
2365 {
2366 uint8_t Rd = (opcode >> 0) & 0x7;
2367 uint8_t Rn = (opcode >> 3) & 0x7;
2368 uint8_t Rm = (opcode >> 6) & 0x7;
2369 uint8_t opc = (opcode >> 9) & 0x7;
2370 char *mnemonic = NULL;
2371
2372 switch (opc) {
2373 case 0:
2374 instruction->type = ARM_STR;
2375 mnemonic = "STR";
2376 break;
2377 case 1:
2378 instruction->type = ARM_STRH;
2379 mnemonic = "STRH";
2380 break;
2381 case 2:
2382 instruction->type = ARM_STRB;
2383 mnemonic = "STRB";
2384 break;
2385 case 3:
2386 instruction->type = ARM_LDRSB;
2387 mnemonic = "LDRSB";
2388 break;
2389 case 4:
2390 instruction->type = ARM_LDR;
2391 mnemonic = "LDR";
2392 break;
2393 case 5:
2394 instruction->type = ARM_LDRH;
2395 mnemonic = "LDRH";
2396 break;
2397 case 6:
2398 instruction->type = ARM_LDRB;
2399 mnemonic = "LDRB";
2400 break;
2401 case 7:
2402 instruction->type = ARM_LDRSH;
2403 mnemonic = "LDRSH";
2404 break;
2405 }
2406
2407 snprintf(instruction->text, 128,
2408 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [r%i, r%i]",
2409 address, opcode, mnemonic, Rd, Rn, Rm);
2410
2411 instruction->info.load_store.Rd = Rd;
2412 instruction->info.load_store.Rn = Rn;
2413 instruction->info.load_store.index_mode = 0; /*offset*/
2414 instruction->info.load_store.offset_mode = 1; /*register*/
2415 instruction->info.load_store.offset.reg.Rm = Rm;
2416
2417 return ERROR_OK;
2418 }
2419
2420 static int evaluate_load_store_imm_thumb(uint16_t opcode,
2421 uint32_t address, struct arm_instruction *instruction)
2422 {
2423 uint32_t offset = (opcode >> 6) & 0x1f;
2424 uint8_t Rd = (opcode >> 0) & 0x7;
2425 uint8_t Rn = (opcode >> 3) & 0x7;
2426 uint32_t L = opcode & (1 << 11);
2427 uint32_t B = opcode & (1 << 12);
2428 char *mnemonic;
2429 char suffix = ' ';
2430 uint32_t shift = 2;
2431
2432 if (L) {
2433 instruction->type = ARM_LDR;
2434 mnemonic = "LDR";
2435 } else {
2436 instruction->type = ARM_STR;
2437 mnemonic = "STR";
2438 }
2439
2440 if ((opcode&0xF000) == 0x8000) {
2441 suffix = 'H';
2442 shift = 1;
2443 } else if (B) {
2444 suffix = 'B';
2445 shift = 0;
2446 }
2447
2448 snprintf(instruction->text, 128,
2449 "0x%8.8" PRIx32 " 0x%4.4x \t%s%c\tr%i, [r%i, #%#" PRIx32 "]",
2450 address, opcode, mnemonic, suffix, Rd, Rn, offset << shift);
2451
2452 instruction->info.load_store.Rd = Rd;
2453 instruction->info.load_store.Rn = Rn;
2454 instruction->info.load_store.index_mode = 0; /*offset*/
2455 instruction->info.load_store.offset_mode = 0; /*immediate*/
2456 instruction->info.load_store.offset.offset = offset << shift;
2457
2458 return ERROR_OK;
2459 }
2460
2461 static int evaluate_load_store_stack_thumb(uint16_t opcode,
2462 uint32_t address, struct arm_instruction *instruction)
2463 {
2464 uint32_t offset = opcode & 0xff;
2465 uint8_t Rd = (opcode >> 8) & 0x7;
2466 uint32_t L = opcode & (1 << 11);
2467 char *mnemonic;
2468
2469 if (L) {
2470 instruction->type = ARM_LDR;
2471 mnemonic = "LDR";
2472 } else {
2473 instruction->type = ARM_STR;
2474 mnemonic = "STR";
2475 }
2476
2477 snprintf(instruction->text, 128,
2478 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [SP, #%#" PRIx32 "]",
2479 address, opcode, mnemonic, Rd, offset*4);
2480
2481 instruction->info.load_store.Rd = Rd;
2482 instruction->info.load_store.Rn = 13 /*SP*/;
2483 instruction->info.load_store.index_mode = 0; /*offset*/
2484 instruction->info.load_store.offset_mode = 0; /*immediate*/
2485 instruction->info.load_store.offset.offset = offset*4;
2486
2487 return ERROR_OK;
2488 }
2489
2490 static int evaluate_add_sp_pc_thumb(uint16_t opcode,
2491 uint32_t address, struct arm_instruction *instruction)
2492 {
2493 uint32_t imm = opcode & 0xff;
2494 uint8_t Rd = (opcode >> 8) & 0x7;
2495 uint8_t Rn;
2496 uint32_t SP = opcode & (1 << 11);
2497 const char *reg_name;
2498
2499 instruction->type = ARM_ADD;
2500
2501 if (SP) {
2502 reg_name = "SP";
2503 Rn = 13;
2504 } else {
2505 reg_name = "PC";
2506 Rn = 15;
2507 }
2508
2509 snprintf(instruction->text, 128,
2510 "0x%8.8" PRIx32 " 0x%4.4x \tADD\tr%i, %s, #%#" PRIx32,
2511 address, opcode, Rd, reg_name, imm * 4);
2512
2513 instruction->info.data_proc.variant = 0 /* immediate */;
2514 instruction->info.data_proc.Rd = Rd;
2515 instruction->info.data_proc.Rn = Rn;
2516 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
2517
2518 return ERROR_OK;
2519 }
2520
2521 static int evaluate_adjust_stack_thumb(uint16_t opcode,
2522 uint32_t address, struct arm_instruction *instruction)
2523 {
2524 uint32_t imm = opcode & 0x7f;
2525 uint8_t opc = opcode & (1 << 7);
2526 char *mnemonic;
2527
2528
2529 if (opc) {
2530 instruction->type = ARM_SUB;
2531 mnemonic = "SUB";
2532 } else {
2533 instruction->type = ARM_ADD;
2534 mnemonic = "ADD";
2535 }
2536
2537 snprintf(instruction->text, 128,
2538 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tSP, #%#" PRIx32,
2539 address, opcode, mnemonic, imm*4);
2540
2541 instruction->info.data_proc.variant = 0 /* immediate */;
2542 instruction->info.data_proc.Rd = 13 /*SP*/;
2543 instruction->info.data_proc.Rn = 13 /*SP*/;
2544 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
2545
2546 return ERROR_OK;
2547 }
2548
2549 static int evaluate_breakpoint_thumb(uint16_t opcode,
2550 uint32_t address, struct arm_instruction *instruction)
2551 {
2552 uint32_t imm = opcode & 0xff;
2553
2554 instruction->type = ARM_BKPT;
2555
2556 snprintf(instruction->text, 128,
2557 "0x%8.8" PRIx32 " 0x%4.4x \tBKPT\t%#2.2" PRIx32 "",
2558 address, opcode, imm);
2559
2560 return ERROR_OK;
2561 }
2562
2563 static int evaluate_load_store_multiple_thumb(uint16_t opcode,
2564 uint32_t address, struct arm_instruction *instruction)
2565 {
2566 uint32_t reg_list = opcode & 0xff;
2567 uint32_t L = opcode & (1 << 11);
2568 uint32_t R = opcode & (1 << 8);
2569 uint8_t Rn = (opcode >> 8) & 7;
2570 uint8_t addr_mode = 0 /* IA */;
2571 char reg_names[40];
2572 char *reg_names_p;
2573 char *mnemonic;
2574 char ptr_name[7] = "";
2575 int i;
2576
2577 /* REVISIT: in ThumbEE mode, there are no LDM or STM instructions.
2578 * The STMIA and LDMIA opcodes are used for other instructions.
2579 */
2580
2581 if ((opcode & 0xf000) == 0xc000) { /* generic load/store multiple */
2582 char *wback = "!";
2583
2584 if (L) {
2585 instruction->type = ARM_LDM;
2586 mnemonic = "LDM";
2587 if (opcode & (1 << Rn))
2588 wback = "";
2589 } else {
2590 instruction->type = ARM_STM;
2591 mnemonic = "STM";
2592 }
2593 snprintf(ptr_name, sizeof ptr_name, "r%i%s, ", Rn, wback);
2594 } else {/* push/pop */
2595 Rn = 13;/* SP */
2596 if (L) {
2597 instruction->type = ARM_LDM;
2598 mnemonic = "POP";
2599 if (R)
2600 reg_list |= (1 << 15) /*PC*/;
2601 } else {
2602 instruction->type = ARM_STM;
2603 mnemonic = "PUSH";
2604 addr_mode = 3; /*DB*/
2605 if (R)
2606 reg_list |= (1 << 14) /*LR*/;
2607 }
2608 }
2609
2610 reg_names_p = reg_names;
2611 for (i = 0; i <= 15; i++) {
2612 if (reg_list & (1 << i))
2613 reg_names_p += snprintf(reg_names_p,
2614 (reg_names + 40 - reg_names_p),
2615 "r%i, ",
2616 i);
2617 }
2618 if (reg_names_p > reg_names)
2619 reg_names_p[-2] = '\0';
2620 else /* invalid op : no registers */
2621 reg_names[0] = '\0';
2622
2623 snprintf(instruction->text, 128,
2624 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%s{%s}",
2625 address, opcode, mnemonic, ptr_name, reg_names);
2626
2627 instruction->info.load_store_multiple.register_list = reg_list;
2628 instruction->info.load_store_multiple.Rn = Rn;
2629 instruction->info.load_store_multiple.addressing_mode = addr_mode;
2630
2631 return ERROR_OK;
2632 }
2633
2634 static int evaluate_cond_branch_thumb(uint16_t opcode,
2635 uint32_t address, struct arm_instruction *instruction)
2636 {
2637 uint32_t offset = opcode & 0xff;
2638 uint8_t cond = (opcode >> 8) & 0xf;
2639 uint32_t target_address;
2640
2641 if (cond == 0xf) {
2642 instruction->type = ARM_SWI;
2643 snprintf(instruction->text, 128,
2644 "0x%8.8" PRIx32 " 0x%4.4x \tSVC\t%#2.2" PRIx32,
2645 address, opcode, offset);
2646 return ERROR_OK;
2647 } else if (cond == 0xe) {
2648 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2649 snprintf(instruction->text, 128,
2650 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2651 address, opcode);
2652 return ERROR_OK;
2653 }
2654
2655 /* sign extend 8-bit offset */
2656 if (offset & 0x00000080)
2657 offset = 0xffffff00 | offset;
2658
2659 target_address = address + 4 + (offset << 1);
2660
2661 snprintf(instruction->text, 128,
2662 "0x%8.8" PRIx32 " 0x%4.4x \tB%s\t%#8.8" PRIx32,
2663 address, opcode,
2664 arm_condition_strings[cond], target_address);
2665
2666 instruction->type = ARM_B;
2667 instruction->info.b_bl_bx_blx.reg_operand = -1;
2668 instruction->info.b_bl_bx_blx.target_address = target_address;
2669
2670 return ERROR_OK;
2671 }
2672
2673 static int evaluate_cb_thumb(uint16_t opcode, uint32_t address,
2674 struct arm_instruction *instruction)
2675 {
2676 unsigned offset;
2677
2678 /* added in Thumb2 */
2679 offset = (opcode >> 3) & 0x1f;
2680 offset |= (opcode & 0x0200) >> 4;
2681
2682 snprintf(instruction->text, 128,
2683 "0x%8.8" PRIx32 " 0x%4.4x \tCB%sZ\tr%d, %#8.8" PRIx32,
2684 address, opcode,
2685 (opcode & 0x0800) ? "N" : "",
2686 opcode & 0x7, address + 4 + (offset << 1));
2687
2688 return ERROR_OK;
2689 }
2690
2691 static int evaluate_extend_thumb(uint16_t opcode, uint32_t address,
2692 struct arm_instruction *instruction)
2693 {
2694 /* added in ARMv6 */
2695 snprintf(instruction->text, 128,
2696 "0x%8.8" PRIx32 " 0x%4.4x \t%cXT%c\tr%d, r%d",
2697 address, opcode,
2698 (opcode & 0x0080) ? 'U' : 'S',
2699 (opcode & 0x0040) ? 'B' : 'H',
2700 opcode & 0x7, (opcode >> 3) & 0x7);
2701
2702 return ERROR_OK;
2703 }
2704
2705 static int evaluate_cps_thumb(uint16_t opcode, uint32_t address,
2706 struct arm_instruction *instruction)
2707 {
2708 /* added in ARMv6 */
2709 if ((opcode & 0x0ff0) == 0x0650)
2710 snprintf(instruction->text, 128,
2711 "0x%8.8" PRIx32 " 0x%4.4x \tSETEND %s",
2712 address, opcode,
2713 (opcode & 0x80) ? "BE" : "LE");
2714 else /* ASSUME (opcode & 0x0fe0) == 0x0660 */
2715 snprintf(instruction->text, 128,
2716 "0x%8.8" PRIx32 " 0x%4.4x \tCPSI%c\t%s%s%s",
2717 address, opcode,
2718 (opcode & 0x0010) ? 'D' : 'E',
2719 (opcode & 0x0004) ? "A" : "",
2720 (opcode & 0x0002) ? "I" : "",
2721 (opcode & 0x0001) ? "F" : "");
2722
2723 return ERROR_OK;
2724 }
2725
2726 static int evaluate_byterev_thumb(uint16_t opcode, uint32_t address,
2727 struct arm_instruction *instruction)
2728 {
2729 char *suffix;
2730
2731 /* added in ARMv6 */
2732 switch ((opcode >> 6) & 3) {
2733 case 0:
2734 suffix = "";
2735 break;
2736 case 1:
2737 suffix = "16";
2738 break;
2739 default:
2740 suffix = "SH";
2741 break;
2742 }
2743 snprintf(instruction->text, 128,
2744 "0x%8.8" PRIx32 " 0x%4.4x \tREV%s\tr%d, r%d",
2745 address, opcode, suffix,
2746 opcode & 0x7, (opcode >> 3) & 0x7);
2747
2748 return ERROR_OK;
2749 }
2750
2751 static int evaluate_hint_thumb(uint16_t opcode, uint32_t address,
2752 struct arm_instruction *instruction)
2753 {
2754 char *hint;
2755
2756 switch ((opcode >> 4) & 0x0f) {
2757 case 0:
2758 hint = "NOP";
2759 break;
2760 case 1:
2761 hint = "YIELD";
2762 break;
2763 case 2:
2764 hint = "WFE";
2765 break;
2766 case 3:
2767 hint = "WFI";
2768 break;
2769 case 4:
2770 hint = "SEV";
2771 break;
2772 default:
2773 hint = "HINT (UNRECOGNIZED)";
2774 break;
2775 }
2776
2777 snprintf(instruction->text, 128,
2778 "0x%8.8" PRIx32 " 0x%4.4x \t%s",
2779 address, opcode, hint);
2780
2781 return ERROR_OK;
2782 }
2783
2784 static int evaluate_ifthen_thumb(uint16_t opcode, uint32_t address,
2785 struct arm_instruction *instruction)
2786 {
2787 unsigned cond = (opcode >> 4) & 0x0f;
2788 char *x = "", *y = "", *z = "";
2789
2790 if (opcode & 0x01)
2791 z = (opcode & 0x02) ? "T" : "E";
2792 if (opcode & 0x03)
2793 y = (opcode & 0x04) ? "T" : "E";
2794 if (opcode & 0x07)
2795 x = (opcode & 0x08) ? "T" : "E";
2796
2797 snprintf(instruction->text, 128,
2798 "0x%8.8" PRIx32 " 0x%4.4x \tIT%s%s%s\t%s",
2799 address, opcode,
2800 x, y, z, arm_condition_strings[cond]);
2801
2802 /* NOTE: strictly speaking, the next 1-4 instructions should
2803 * now be displayed with the relevant conditional suffix...
2804 */
2805
2806 return ERROR_OK;
2807 }
2808
2809 int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
2810 {
2811 /* clear fields, to avoid confusion */
2812 memset(instruction, 0, sizeof(struct arm_instruction));
2813 instruction->opcode = opcode;
2814 instruction->instruction_size = 2;
2815
2816 if ((opcode & 0xe000) == 0x0000) {
2817 /* add/substract register or immediate */
2818 if ((opcode & 0x1800) == 0x1800)
2819 return evaluate_add_sub_thumb(opcode, address, instruction);
2820 /* shift by immediate */
2821 else
2822 return evaluate_shift_imm_thumb(opcode, address, instruction);
2823 }
2824
2825 /* Add/substract/compare/move immediate */
2826 if ((opcode & 0xe000) == 0x2000)
2827 return evaluate_data_proc_imm_thumb(opcode, address, instruction);
2828
2829 /* Data processing instructions */
2830 if ((opcode & 0xf800) == 0x4000)
2831 return evaluate_data_proc_thumb(opcode, address, instruction);
2832
2833 /* Load from literal pool */
2834 if ((opcode & 0xf800) == 0x4800)
2835 return evaluate_load_literal_thumb(opcode, address, instruction);
2836
2837 /* Load/Store register offset */
2838 if ((opcode & 0xf000) == 0x5000)
2839 return evaluate_load_store_reg_thumb(opcode, address, instruction);
2840
2841 /* Load/Store immediate offset */
2842 if (((opcode & 0xe000) == 0x6000)
2843 || ((opcode & 0xf000) == 0x8000))
2844 return evaluate_load_store_imm_thumb(opcode, address, instruction);
2845
2846 /* Load/Store from/to stack */
2847 if ((opcode & 0xf000) == 0x9000)
2848 return evaluate_load_store_stack_thumb(opcode, address, instruction);
2849
2850 /* Add to SP/PC */
2851 if ((opcode & 0xf000) == 0xa000)
2852 return evaluate_add_sp_pc_thumb(opcode, address, instruction);
2853
2854 /* Misc */
2855 if ((opcode & 0xf000) == 0xb000) {
2856 switch ((opcode >> 8) & 0x0f) {
2857 case 0x0:
2858 return evaluate_adjust_stack_thumb(opcode, address, instruction);
2859 case 0x1:
2860 case 0x3:
2861 case 0x9:
2862 case 0xb:
2863 return evaluate_cb_thumb(opcode, address, instruction);
2864 case 0x2:
2865 return evaluate_extend_thumb(opcode, address, instruction);
2866 case 0x4:
2867 case 0x5:
2868 case 0xc:
2869 case 0xd:
2870 return evaluate_load_store_multiple_thumb(opcode, address,
2871 instruction);
2872 case 0x6:
2873 return evaluate_cps_thumb(opcode, address, instruction);
2874 case 0xa:
2875 if ((opcode & 0x00c0) == 0x0080)
2876 break;
2877 return evaluate_byterev_thumb(opcode, address, instruction);
2878 case 0xe:
2879 return evaluate_breakpoint_thumb(opcode, address, instruction);
2880 case 0xf:
2881 if (opcode & 0x000f)
2882 return evaluate_ifthen_thumb(opcode, address,
2883 instruction);
2884 else
2885 return evaluate_hint_thumb(opcode, address,
2886 instruction);
2887 }
2888
2889 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2890 snprintf(instruction->text, 128,
2891 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2892 address, opcode);
2893 return ERROR_OK;
2894 }
2895
2896 /* Load/Store multiple */
2897 if ((opcode & 0xf000) == 0xc000)
2898 return evaluate_load_store_multiple_thumb(opcode, address, instruction);
2899
2900 /* Conditional branch + SWI */
2901 if ((opcode & 0xf000) == 0xd000)
2902 return evaluate_cond_branch_thumb(opcode, address, instruction);
2903
2904 if ((opcode & 0xe000) == 0xe000) {
2905 /* Undefined instructions */
2906 if ((opcode & 0xf801) == 0xe801) {
2907 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2908 snprintf(instruction->text, 128,
2909 "0x%8.8" PRIx32 " 0x%8.8x\t"
2910 "UNDEFINED INSTRUCTION",
2911 address, opcode);
2912 return ERROR_OK;
2913 } else /* Branch to offset */
2914 return evaluate_b_bl_blx_thumb(opcode, address, instruction);
2915 }
2916
2917 LOG_ERROR("Thumb: should never reach this point (opcode=%04x)", opcode);
2918 return -1;
2919 }
2920
2921 static int t2ev_b_bl(uint32_t opcode, uint32_t address,
2922 struct arm_instruction *instruction, char *cp)
2923 {
2924 unsigned offset;
2925 unsigned b21 = 1 << 21;
2926 unsigned b22 = 1 << 22;
2927
2928 /* instead of combining two smaller 16-bit branch instructions,
2929 * Thumb2 uses only one larger 32-bit instruction.
2930 */
2931 offset = opcode & 0x7ff;
2932 offset |= (opcode & 0x03ff0000) >> 5;
2933 if (opcode & (1 << 26)) {
2934 offset |= 0xff << 23;
2935 if ((opcode & (1 << 11)) == 0)
2936 b21 = 0;
2937 if ((opcode & (1 << 13)) == 0)
2938 b22 = 0;
2939 } else {
2940 if (opcode & (1 << 11))
2941 b21 = 0;
2942 if (opcode & (1 << 13))
2943 b22 = 0;
2944 }
2945 offset |= b21;
2946 offset |= b22;
2947
2948
2949 address += 4;
2950 address += offset << 1;
2951
2952 char *inst;
2953 switch ((opcode >> 12) & 0x5) {
2954 case 0x1:
2955 inst = "B.W";
2956 instruction->type = ARM_B;
2957 break;
2958 case 0x4:
2959 inst = "BLX";
2960 instruction->type = ARM_BLX;
2961 break;
2962 case 0x5:
2963 inst = "BL";
2964 instruction->type = ARM_BL;
2965 break;
2966 default:
2967 return ERROR_COMMAND_SYNTAX_ERROR;
2968 }
2969 instruction->info.b_bl_bx_blx.reg_operand = -1;
2970 instruction->info.b_bl_bx_blx.target_address = address;
2971 sprintf(cp, "%s\t%#8.8" PRIx32, inst, address);
2972
2973 return ERROR_OK;
2974 }
2975
2976 static int t2ev_cond_b(uint32_t opcode, uint32_t address,
2977 struct arm_instruction *instruction, char *cp)
2978 {
2979 unsigned offset;
2980 unsigned b17 = 1 << 17;
2981 unsigned b18 = 1 << 18;
2982 unsigned cond = (opcode >> 22) & 0x0f;
2983
2984 offset = opcode & 0x7ff;
2985 offset |= (opcode & 0x003f0000) >> 5;
2986 if (opcode & (1 << 26)) {
2987 offset |= 0x1fff << 19;
2988 if ((opcode & (1 << 11)) == 0)
2989 b17 = 0;
2990 if ((opcode & (1 << 13)) == 0)
2991 b18 = 0;
2992 } else {
2993 if (opcode & (1 << 11))
2994 b17 = 0;
2995 if (opcode & (1 << 13))
2996 b18 = 0;
2997 }
2998 offset |= b17;
2999 offset |= b18;
3000
3001 address += 4;
3002 address += offset << 1;
3003
3004 instruction->type = ARM_B;
3005 instruction->info.b_bl_bx_blx.reg_operand = -1;
3006 instruction->info.b_bl_bx_blx.target_address = address;
3007 sprintf(cp, "B%s.W\t%#8.8" PRIx32,
3008 arm_condition_strings[cond],
3009 address);
3010
3011 return ERROR_OK;
3012 }
3013
3014 static const char *special_name(int number)
3015 {
3016 char *special = "(RESERVED)";
3017
3018 switch (number) {
3019 case 0:
3020 special = "apsr";
3021 break;
3022 case 1:
3023 special = "iapsr";
3024 break;
3025 case 2:
3026 special = "eapsr";
3027 break;
3028 case 3:
3029 special = "xpsr";
3030 break;
3031 case 5:
3032 special = "ipsr";
3033 break;
3034 case 6:
3035 special = "epsr";
3036 break;
3037 case 7:
3038 special = "iepsr";
3039 break;
3040 case 8:
3041 special = "msp";
3042 break;
3043 case 9:
3044 special = "psp";
3045 break;
3046 case 16:
3047 special = "primask";
3048 break;
3049 case 17:
3050 special = "basepri";
3051 break;
3052 case 18:
3053 special = "basepri_max";
3054 break;
3055 case 19:
3056 special = "faultmask";
3057 break;
3058 case 20:
3059 special = "control";
3060 break;
3061 }
3062 return special;
3063 }
3064
3065 static int t2ev_hint(uint32_t opcode, uint32_t address,
3066 struct arm_instruction *instruction, char *cp)
3067 {
3068 const char *mnemonic;
3069
3070 if (opcode & 0x0700) {
3071 instruction->type = ARM_UNDEFINED_INSTRUCTION;
3072 strcpy(cp, "UNDEFINED");
3073 return ERROR_OK;
3074 }
3075
3076 if (opcode & 0x00f0) {
3077 sprintf(cp, "DBG\t#%d", (int) opcode & 0xf);
3078 return ERROR_OK;
3079 }
3080
3081 switch (opcode & 0x0f) {
3082 case 0:
3083 mnemonic = "NOP.W";
3084 break;
3085 case 1:
3086 mnemonic = "YIELD.W";
3087 break;
3088 case 2:
3089 mnemonic = "WFE.W";
3090 break;
3091 case 3:
3092 mnemonic = "WFI.W";
3093 break;
3094 case 4:
3095 mnemonic = "SEV.W";
3096 break;
3097 default:
3098 mnemonic = "HINT.W (UNRECOGNIZED)";
3099 break;
3100 }
3101 strcpy(cp, mnemonic);
3102 return ERROR_OK;
3103 }
3104
3105 static int t2ev_misc(uint32_t opcode, uint32_t address,
3106 struct arm_instruction *instruction, char *cp)
3107 {
3108 const char *mnemonic;
3109
3110 switch ((opcode >> 4) & 0x0f) {
3111 case 0:
3112 mnemonic = "LEAVEX";
3113 break;
3114 case 1:
3115 mnemonic = "ENTERX";
3116 break;
3117 case 2:
3118 mnemonic = "CLREX";
3119 break;
3120 case 4:
3121 mnemonic = "DSB";
3122 break;
3123 case 5:
3124 mnemonic = "DMB";
3125 break;
3126 case 6:
3127 mnemonic = "ISB";
3128 break;
3129 default:
3130 return ERROR_COMMAND_SYNTAX_ERROR;
3131 }
3132 strcpy(cp, mnemonic);
3133 return ERROR_OK;
3134 }
3135
3136 static int t2ev_b_misc(uint32_t opcode, uint32_t address,
3137 struct arm_instruction *instruction, char *cp)
3138 {
3139 /* permanently undefined */
3140 if ((opcode & 0x07f07000) == 0x07f02000) {
3141 instruction->type = ARM_UNDEFINED_INSTRUCTION;
3142 strcpy(cp, "UNDEFINED");
3143 return ERROR_OK;
3144 }
3145
3146 switch ((opcode >> 12) & 0x5) {
3147 case 0x1:
3148 case 0x4:
3149 case 0x5:
3150 return t2ev_b_bl(opcode, address, instruction, cp);
3151 case 0:
3152 if (((opcode >> 23) & 0x07) != 0x07)
3153 return t2ev_cond_b(opcode, address, instruction, cp);
3154 if (opcode & (1 << 26))
3155 goto undef;
3156 break;
3157 }
3158
3159 switch ((opcode >> 20) & 0x7f) {
3160 case 0x38:
3161 case 0x39:
3162 sprintf(cp, "MSR\t%s, r%d", special_name(opcode & 0xff),
3163 (int) (opcode >> 16) & 0x0f);
3164 return ERROR_OK;
3165 case 0x3a:
3166 return t2ev_hint(opcode, address, instruction, cp);
3167 case 0x3b:
3168 return t2ev_misc(opcode, address, instruction, cp);
3169 case 0x3c:
3170 sprintf(cp, "BXJ\tr%d", (int) (opcode >> 16) & 0x0f);
3171 return ERROR_OK;
3172 case 0x3e:
3173 case 0x3f:
3174 sprintf(cp, "MRS\tr%d, %s", (int) (opcode >> 8) & 0x0f,
3175 special_name(opcode & 0xff));
3176 return ERROR_OK;
3177 }
3178
3179 undef:
3180 return ERROR_COMMAND_SYNTAX_ERROR;
3181 }
3182
3183 static int t2ev_data_mod_immed(uint32_t opcode, uint32_t address,
3184 struct arm_instruction *instruction, char *cp)
3185 {
3186 char *mnemonic = NULL;
3187 int rn = (opcode >> 16) & 0xf;
3188 int rd = (opcode >> 8) & 0xf;
3189 unsigned immed = opcode & 0xff;
3190 unsigned func;
3191 bool one = false;
3192 char *suffix = "";
3193 char *suffix2 = "";
3194
3195 /* ARMv7-M: A5.3.2 Modified immediate constants */
3196 func = (opcode >> 11) & 0x0e;
3197 if (immed & 0x80)
3198 func |= 1;
3199 if (opcode & (1 << 26))
3200 func |= 0x10;
3201
3202 /* "Modified" immediates */
3203 switch (func >> 1) {
3204 case 0:
3205 break;
3206 case 2:
3207 immed <<= 8;
3208 /* FALLTHROUGH */
3209 case 1:
3210 immed += immed << 16;
3211 break;
3212 case 3:
3213 immed += immed << 8;
3214 immed += immed << 16;
3215 break;
3216 default:
3217 immed |= 0x80;
3218 immed = ror(immed, func);
3219 }
3220
3221 if (opcode & (1 << 20))
3222 suffix = "S";
3223
3224 switch ((opcode >> 21) & 0xf) {
3225 case 0:
3226 if (rd == 0xf) {
3227 instruction->type = ARM_TST;
3228 mnemonic = "TST";
3229 one = true;
3230 suffix = "";
3231 rd = rn;
3232 } else {
3233 instruction->type = ARM_AND;
3234 mnemonic = "AND";
3235 }
3236 break;
3237 case 1:
3238 instruction->type = ARM_BIC;
3239 mnemonic = "BIC";
3240 break;
3241 case 2:
3242 if (rn == 0xf) {
3243 instruction->type = ARM_MOV;
3244 mnemonic = "MOV";
3245 one = true;
3246 suffix2 = ".W";
3247 } else {
3248 instruction->type = ARM_ORR;
3249 mnemonic = "ORR";
3250 }
3251 break;
3252 case 3:
3253 if (rn == 0xf) {
3254 instruction->type = ARM_MVN;
3255 mnemonic = "MVN";
3256 one = true;
3257 } else {
3258 /* instruction->type = ARM_ORN; */
3259 mnemonic = "ORN";
3260 }
3261 break;
3262 case 4:
3263 if (rd == 0xf) {
3264 instruction->type = ARM_TEQ;
3265 mnemonic = "TEQ";
3266 one = true;
3267 suffix = "";
3268 rd = rn;
3269 } else {
3270 instruction->type = ARM_EOR;
3271 mnemonic = "EOR";
3272 }
3273 break;
3274 case 8:
3275 if (rd == 0xf) {
3276 instruction->type = ARM_CMN;
3277 mnemonic = "CMN";
3278 one = true;
3279 suffix = "";
3280 rd = rn;
3281 } else {
3282 instruction->type = ARM_ADD;
3283 mnemonic = "ADD";
3284 suffix2 = ".W";
3285 }
3286 break;
3287 case 10:
3288 instruction->type = ARM_ADC;
3289 mnemonic = "ADC";
3290 suffix2 = ".W";
3291 break;
3292 case 11:
3293 instruction->type = ARM_SBC;
3294 mnemonic = "SBC";
3295 break;
3296 case 13:
3297 if (rd == 0xf) {
3298 instruction->type = ARM_CMP;
3299 mnemonic = "CMP";
3300 one = true;
3301 suffix = "";
3302 rd = rn;
3303 } else {
3304 instruction->type = ARM_SUB;
3305 mnemonic = "SUB";
3306 }
3307 suffix2 = ".W";
3308 break;
3309 case 14:
3310 instruction->type = ARM_RSB;
3311 mnemonic = "RSB";
3312 suffix2 = ".W";
3313 break;
3314 default:
3315 return ERROR_COMMAND_SYNTAX_ERROR;
3316 }
3317
3318 if (one)
3319 sprintf(cp, "%s%s\tr%d, #%d\t; %#8.8x",
3320 mnemonic, suffix2, rd, immed, immed);
3321 else
3322 sprintf(cp, "%s%s%s\tr%d, r%d, #%d\t; %#8.8x",
3323 mnemonic, suffix, suffix2,
3324 rd, rn, immed, immed);
3325
3326 return ERROR_OK;
3327 }
3328
3329 static int t2ev_data_immed(uint32_t opcode, uint32_t address,
3330 struct arm_instruction *instruction, char *cp)
3331 {
3332 char *mnemonic = NULL;
3333 int rn = (opcode >> 16) & 0xf;
3334 int rd = (opcode >> 8) & 0xf;
3335 unsigned immed;
3336 bool add = false;
3337 bool is_signed = false;
3338
3339 immed = (opcode & 0x0ff) | ((opcode & 0x7000) >> 4);
3340 if (opcode & (1 << 26))
3341 immed |= (1 << 11);
3342
3343 switch ((opcode >> 20) & 0x1f) {
3344 case 0:
3345 if (rn == 0xf) {
3346 add = true;
3347 goto do_adr;
3348 }
3349 mnemonic = "ADDW";
3350 break;
3351 case 4:
3352 immed |= (opcode >> 4) & 0xf000;
3353 sprintf(cp, "MOVW\tr%d, #%d\t; %#3.3x", rd, immed, immed);
3354 return ERROR_OK;
3355 case 0x0a:
3356 if (rn == 0xf)
3357 goto do_adr;
3358 mnemonic = "SUBW";
3359 break;
3360 case 0x0c:
3361 /* move constant to top 16 bits of register */
3362 immed |= (opcode >> 4) & 0xf000;
3363 sprintf(cp, "MOVT\tr%d, #%d\t; %#4.4x", rd, immed, immed);
3364 return ERROR_OK;
3365 case 0x10:
3366 case 0x12:
3367 is_signed = true;
3368 /* fallthrough */
3369 case 0x18:
3370 case 0x1a:
3371 /* signed/unsigned saturated add */
3372 immed = (opcode >> 6) & 0x03;
3373 immed |= (opcode >> 10) & 0x1c;
3374 sprintf(cp, "%sSAT\tr%d, #%d, r%d, %s #%d\t",
3375 is_signed ? "S" : "U",
3376 rd, (int) (opcode & 0x1f) + is_signed, rn,
3377 (opcode & (1 << 21)) ? "ASR" : "LSL",
3378 immed ? immed : 32);
3379 return ERROR_OK;
3380 case 0x14:
3381 is_signed = true;
3382 /* FALLTHROUGH */
3383 case 0x1c:
3384 /* signed/unsigned bitfield extract */
3385 immed = (opcode >> 6) & 0x03;
3386 immed |= (opcode >> 10) & 0x1c;
3387 sprintf(cp, "%sBFX\tr%d, r%d, #%d, #%d\t",
3388 is_signed ? "S" : "U",
3389 rd, rn, immed,
3390 (int) (opcode & 0x1f) + 1);
3391 return ERROR_OK;
3392 case 0x16:
3393 immed = (opcode >> 6) & 0x03;
3394 immed |= (opcode >> 10) & 0x1c;
3395 if (rn == 0xf) /* bitfield clear */
3396 sprintf(cp, "BFC\tr%d, #%d, #%d\t",
3397 rd, immed,
3398 (int) (opcode & 0x1f) + 1 - immed);
3399 else /* bitfield insert */
3400 sprintf(cp, "BFI\tr%d, r%d, #%d, #%d\t",
3401 rd, rn, immed,
3402 (int) (opcode & 0x1f) + 1 - immed);
3403 return ERROR_OK;
3404 default:
3405 return ERROR_COMMAND_SYNTAX_ERROR;
3406 }
3407
3408 sprintf(cp, "%s\tr%d, r%d, #%d\t; %#3.3x", mnemonic,
3409 rd, rn, immed, immed);
3410 return ERROR_OK;
3411
3412 do_adr:
3413 address = thumb_alignpc4(address);
3414 if (add)
3415 address += immed;
3416 else
3417 address -= immed;
3418 /* REVISIT "ADD/SUB Rd, PC, #const ; 0x..." might be better;
3419 * not hiding the pc-relative stuff will sometimes be useful.
3420 */
3421 sprintf(cp, "ADR.W\tr%d, %#8.8" PRIx32, rd, address);
3422 return ERROR_OK;
3423 }
3424
3425 static int t2ev_store_single(uint32_t opcode, uint32_t address,
3426 struct arm_instruction *instruction, char *cp)
3427 {
3428 unsigned op = (opcode >> 20) & 0xf;
3429 char *size = "";
3430 char *suffix = "";
3431 char *p1 = "";
3432 char *p2 = "]";
3433 unsigned immed;
3434 unsigned rn = (opcode >> 16) & 0x0f;
3435 unsigned rt = (opcode >> 12) & 0x0f;
3436
3437 if (rn == 0xf)
3438 return ERROR_COMMAND_SYNTAX_ERROR;
3439
3440 if (opcode & 0x0800)
3441 op |= 1;
3442 switch (op) {
3443 /* byte */
3444 case 0x8:
3445 case 0x9:
3446 size = "B";
3447 goto imm12;
3448 case 0x1:
3449 size = "B";
3450 goto imm8;
3451 case 0x0:
3452 size = "B";
3453 break;
3454 /* halfword */
3455 case 0xa:
3456 case 0xb:
3457 size = "H";
3458 goto imm12;
3459 case 0x3:
3460 size = "H";
3461 goto imm8;
3462 case 0x2:
3463 size = "H";
3464 break;
3465 /* word */
3466 case 0xc:
3467 case 0xd:
3468 goto imm12;
3469 case 0x5:
3470 goto imm8;
3471 case 0x4:
3472 break;
3473 /* error */
3474 default:
3475 return ERROR_COMMAND_SYNTAX_ERROR;
3476 }
3477
3478 sprintf(cp, "STR%s.W\tr%d, [r%d, r%d, LSL #%d]",
3479 size, rt, rn, (int) opcode & 0x0f,
3480 (int) (opcode >> 4) & 0x03);
3481 return ERROR_OK;
3482
3483 imm12:
3484 immed = opcode & 0x0fff;
3485 sprintf(cp, "STR%s.W\tr%d, [r%d, #%u]\t; %#3.3x",
3486 size, rt, rn, immed, immed);
3487 return ERROR_OK;
3488
3489 imm8:
3490 immed = opcode & 0x00ff;
3491
3492 switch (opcode & 0x700) {
3493 case 0x600:
3494 suffix = "T";
3495 break;
3496 case 0x000:
3497 case 0x200:
3498 return ERROR_COMMAND_SYNTAX_ERROR;
3499 }
3500
3501 /* two indexed modes will write back rn */
3502 if (opcode & 0x100) {
3503 if (opcode & 0x400) /* pre-indexed */
3504 p2 = "]!";
3505 else { /* post-indexed */
3506 p1 = "]";
3507 p2 = "";
3508 }
3509 }
3510
3511 sprintf(cp, "STR%s%s\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
3512 size, suffix, rt, rn, p1,
3513 (opcode & 0x200) ? "" : "-",
3514 immed, p2, immed);
3515 return ERROR_OK;
3516 }
3517
3518 static int t2ev_mul32(uint32_t opcode, uint32_t address,
3519 struct arm_instruction *instruction, char *cp)
3520 {
3521 int ra = (opcode >> 12) & 0xf;
3522
3523 switch (opcode & 0x007000f0) {
3524 case 0:
3525 if (ra == 0xf)
3526 sprintf(cp, "MUL\tr%d, r%d, r%d",
3527 (int) (opcode >> 8) & 0xf,
3528 (int) (opcode >> 16) & 0xf,
3529 (int) (opcode >> 0) & 0xf);
3530 else
3531 sprintf(cp, "MLA\tr%d, r%d, r%d, r%d",
3532 (int) (opcode >> 8) & 0xf,
3533 (int) (opcode >> 16) & 0xf,
3534 (int) (opcode >> 0) & 0xf, ra);
3535 break;
3536 case 0x10:
3537 sprintf(cp, "MLS\tr%d, r%d, r%d, r%d",
3538 (int) (opcode >> 8) & 0xf,
3539 (int) (opcode >> 16) & 0xf,
3540 (int) (opcode >> 0) & 0xf, ra);
3541 break;
3542 default:
3543 return ERROR_COMMAND_SYNTAX_ERROR;
3544 }
3545 return ERROR_OK;
3546 }
3547
3548 static int t2ev_mul64_div(uint32_t opcode, uint32_t address,
3549 struct arm_instruction *instruction, char *cp)
3550 {
3551 int op = (opcode >> 4) & 0xf;
3552 char *infix = "MUL";
3553
3554 op += (opcode >> 16) & 0x70;
3555 switch (op) {
3556 case 0x40:
3557 case 0x60:
3558 infix = "MLA";
3559 /* FALLTHROUGH */
3560 case 0:
3561 case 0x20:
3562 sprintf(cp, "%c%sL\tr%d, r%d, r%d, r%d",
3563 (op & 0x20) ? 'U' : 'S',
3564 infix,
3565 (int) (opcode >> 12) & 0xf,
3566 (int) (opcode >> 8) & 0xf,
3567 (int) (opcode >> 16) & 0xf,
3568 (int) (opcode >> 0) & 0xf);
3569 break;
3570 case 0x1f:
3571 case 0x3f:
3572 sprintf(cp, "%cDIV\tr%d, r%d, r%d",
3573 (op & 0x20) ? 'U' : 'S',
3574 (int) (opcode >> 8) & 0xf,
3575 (int) (opcode >> 16) & 0xf,
3576 (int) (opcode >> 0) & 0xf);
3577 break;
3578 default:
3579 return ERROR_COMMAND_SYNTAX_ERROR;
3580 }
3581
3582 return ERROR_OK;
3583 }
3584
3585 static int t2ev_ldm_stm(uint32_t opcode, uint32_t address,
3586 struct arm_instruction *instruction, char *cp)
3587 {
3588 int rn = (opcode >> 16) & 0xf;
3589 int op = (opcode >> 22) & 0x6;
3590 int t = (opcode >> 21) & 1;
3591 unsigned registers = opcode & 0xffff;
3592 char *mode = "";
3593
3594 if (opcode & (1 << 20))
3595 op |= 1;
3596
3597 switch (op) {
3598 case 0:
3599 mode = "DB";
3600 /* FALL THROUGH */
3601 case 6:
3602 sprintf(cp, "SRS%s\tsp%s, #%d", mode,
3603 t ? "!" : "",
3604 (unsigned) (opcode & 0x1f));
3605 return ERROR_OK;
3606 case 1:
3607 mode = "DB";
3608 /* FALL THROUGH */
3609 case 7:
3610 sprintf(cp, "RFE%s\tr%d%s", mode,
3611 (unsigned) ((opcode >> 16) & 0xf),
3612 t ? "!" : "");
3613 return ERROR_OK;
3614 case 2:
3615 sprintf(cp, "STM.W\tr%d%s, ", rn, t ? "!" : "");
3616 break;
3617 case 3:
3618 if (rn == 13 && t)
3619 sprintf(cp, "POP.W\t");
3620 else
3621 sprintf(cp, "LDM.W\tr%d%s, ", rn, t ? "!" : "");
3622 break;
3623 case 4:
3624 if (rn == 13 && t)
3625 sprintf(cp, "PUSH.W\t");
3626 else
3627 sprintf(cp, "STMDB\tr%d%s, ", rn, t ? "!" : "");
3628 break;
3629 case 5:
3630 sprintf(cp, "LDMDB.W\tr%d%s, ", rn, t ? "!" : "");
3631 break;
3632 default:
3633 return ERROR_COMMAND_SYNTAX_ERROR;
3634 }
3635
3636 cp = strchr(cp, 0);
3637 *cp++ = '{';
3638 for (t = 0; registers; t++, registers >>= 1) {
3639 if ((registers & 1) == 0)
3640 continue;
3641 registers &= ~1;
3642 sprintf(cp, "r%d%s", t, registers ? ", " : "");
3643 cp = strchr(cp, 0);
3644 }
3645 *cp++ = '}';
3646 *cp++ = 0;
3647
3648 return ERROR_OK;
3649 }
3650
3651 /* load/store dual or exclusive, table branch */
3652 static int t2ev_ldrex_strex(uint32_t opcode, uint32_t address,
3653 struct arm_instruction *instruction, char *cp)
3654 {
3655 unsigned op1op2 = (opcode >> 20) & 0x3;
3656 unsigned op3 = (opcode >> 4) & 0xf;
3657 char *mnemonic;
3658 unsigned rn = (opcode >> 16) & 0xf;
3659 unsigned rt = (opcode >> 12) & 0xf;
3660 unsigned rd = (opcode >> 8) & 0xf;
3661 unsigned imm = opcode & 0xff;
3662 char *p1 = "";
3663 char *p2 = "]";
3664
3665 op1op2 |= (opcode >> 21) & 0xc;
3666 switch (op1op2) {
3667 case 0:
3668 mnemonic = "STREX";
3669 goto strex;
3670 case 1:
3671 mnemonic = "LDREX";
3672 goto ldrex;
3673 case 2:
3674 case 6:
3675 case 8:
3676 case 10:
3677 case 12:
3678 case 14:
3679 mnemonic = "STRD";
3680 goto immediate;
3681 case 3:
3682 case 7:
3683 case 9:
3684 case 11:
3685 case 13:
3686 case 15:
3687 mnemonic = "LDRD";
3688 if (rn == 15)
3689 goto literal;
3690 else
3691 goto immediate;
3692 case 4:
3693 switch (op3) {
3694 case 4:
3695 mnemonic = "STREXB";
3696 break;
3697 case 5:
3698 mnemonic = "STREXH";
3699 break;
3700 default:
3701 return ERROR_COMMAND_SYNTAX_ERROR;
3702 }
3703 rd = opcode & 0xf;
3704 imm = 0;
3705 goto strex;
3706 case 5:
3707 switch (op3) {
3708 case 0:
3709 sprintf(cp, "TBB\t[r%u, r%u]", rn, imm & 0xf);
3710 return ERROR_OK;
3711 case 1:
3712 sprintf(cp, "TBH\t[r%u, r%u, LSL #1]", rn, imm & 0xf);
3713 return ERROR_OK;
3714 case 4:
3715 mnemonic = "LDREXB";
3716 break;
3717 case 5:
3718 mnemonic = "LDREXH";
3719 break;
3720 default:
3721 return ERROR_COMMAND_SYNTAX_ERROR;
3722 }
3723 imm = 0;
3724 goto ldrex;
3725 }
3726 return ERROR_COMMAND_SYNTAX_ERROR;
3727
3728 strex:
3729 imm <<= 2;
3730 if (imm)
3731 sprintf(cp, "%s\tr%u, r%u, [r%u, #%u]\t; %#2.2x",
3732 mnemonic, rd, rt, rn, imm, imm);
3733 else
3734 sprintf(cp, "%s\tr%u, r%u, [r%u]",
3735 mnemonic, rd, rt, rn);
3736 return ERROR_OK;
3737
3738 ldrex:
3739 imm <<= 2;
3740 if (imm)
3741 sprintf(cp, "%s\tr%u, [r%u, #%u]\t; %#2.2x",
3742 mnemonic, rt, rn, imm, imm);
3743 else
3744 sprintf(cp, "%s\tr%u, [r%u]",
3745 mnemonic, rt, rn);
3746 return ERROR_OK;
3747
3748 immediate:
3749 /* two indexed modes will write back rn */
3750 if (opcode & (1 << 21)) {
3751 if (opcode & (1 << 24)) /* pre-indexed */
3752 p2 = "]!";
3753 else { /* post-indexed */
3754 p1 = "]";
3755 p2 = "";
3756 }
3757 }
3758
3759 imm <<= 2;
3760 sprintf(cp, "%s\tr%u, r%u, [r%u%s, #%s%u%s\t; %#2.2x",
3761 mnemonic, rt, rd, rn, p1,
3762 (opcode & (1 << 23)) ? "" : "-",
3763 imm, p2, imm);
3764 return ERROR_OK;
3765
3766 literal:
3767 address = thumb_alignpc4(address);
3768 imm <<= 2;
3769 if (opcode & (1 << 23))
3770 address += imm;
3771 else
3772 address -= imm;
3773 sprintf(cp, "%s\tr%u, r%u, %#8.8" PRIx32,
3774 mnemonic, rt, rd, address);
3775 return ERROR_OK;
3776 }
3777
3778 static int t2ev_data_shift(uint32_t opcode, uint32_t address,
3779 struct arm_instruction *instruction, char *cp)
3780 {
3781 int op = (opcode >> 21) & 0xf;
3782 int rd = (opcode >> 8) & 0xf;
3783 int rn = (opcode >> 16) & 0xf;
3784 int type = (opcode >> 4) & 0x3;
3785 int immed = (opcode >> 6) & 0x3;
3786 char *mnemonic;
3787 char *suffix = "";
3788
3789 immed |= (opcode >> 10) & 0x1c;
3790 if (opcode & (1 << 20))
3791 suffix = "S";
3792
3793 switch (op) {
3794 case 0:
3795 if (rd == 0xf) {
3796 if (!(opcode & (1 << 20)))
3797 return ERROR_COMMAND_SYNTAX_ERROR;
3798 instruction->type = ARM_TST;
3799 mnemonic = "TST";
3800 suffix = "";
3801 goto two;
3802 }
3803 instruction->type = ARM_AND;
3804 mnemonic = "AND";
3805 break;
3806 case 1:
3807 instruction->type = ARM_BIC;
3808 mnemonic = "BIC";
3809 break;
3810 case 2:
3811 if (rn == 0xf) {
3812 instruction->type = ARM_MOV;
3813 switch (type) {
3814 case 0:
3815 if (immed == 0) {
3816 sprintf(cp, "MOV%s.W\tr%d, r%d",
3817 suffix, rd,
3818 (int) (opcode & 0xf));
3819 return ERROR_OK;
3820 }
3821 mnemonic = "LSL";
3822 break;
3823 case 1:
3824 mnemonic = "LSR";
3825 break;
3826 case 2:
3827 mnemonic = "ASR";
3828 break;
3829 default:
3830 if (immed == 0) {
3831 sprintf(cp, "RRX%s\tr%d, r%d",
3832 suffix, rd,
3833 (int) (opcode & 0xf));
3834 return ERROR_OK;
3835 }
3836 mnemonic = "ROR";
3837 break;
3838 }
3839 goto immediate;
3840 } else {
3841 instruction->type = ARM_ORR;
3842 mnemonic = "ORR";
3843 }
3844 break;
3845 case 3:
3846 if (rn == 0xf) {
3847 instruction->type = ARM_MVN;
3848 mnemonic = "MVN";
3849 rn = rd;
3850 goto two;
3851 } else {
3852 /* instruction->type = ARM_ORN; */
3853 mnemonic = "ORN";
3854 }
3855 break;
3856 case 4:
3857 if (rd == 0xf) {
3858 if (!(opcode & (1 << 20)))
3859 return ERROR_COMMAND_SYNTAX_ERROR;
3860 instruction->type = ARM_TEQ;
3861 mnemonic = "TEQ";
3862 suffix = "";
3863 goto two;
3864 }
3865 instruction->type = ARM_EOR;
3866 mnemonic = "EOR";
3867 break;
3868 case 8:
3869 if (rd == 0xf) {
3870 if (!(opcode & (1 << 20)))
3871 return ERROR_COMMAND_SYNTAX_ERROR;
3872 instruction->type = ARM_CMN;
3873 mnemonic = "CMN";
3874 suffix = "";
3875 goto two;
3876 }
3877 instruction->type = ARM_ADD;
3878 mnemonic = "ADD";
3879 break;
3880 case 0xa:
3881 instruction->type = ARM_ADC;
3882 mnemonic = "ADC";
3883 break;
3884 case 0xb:
3885 instruction->type = ARM_SBC;
3886 mnemonic = "SBC";
3887 break;
3888 case 0xd:
3889 if (rd == 0xf) {
3890 if (!(opcode & (1 << 21)))
3891 return ERROR_COMMAND_SYNTAX_ERROR;
3892 instruction->type = ARM_CMP;
3893 mnemonic = "CMP";
3894 suffix = "";
3895 goto two;
3896 }
3897 instruction->type = ARM_SUB;
3898 mnemonic = "SUB";
3899 break;
3900 case 0xe:
3901 instruction->type = ARM_RSB;
3902 mnemonic = "RSB";
3903 break;
3904 default:
3905 return ERROR_COMMAND_SYNTAX_ERROR;
3906 }
3907
3908 sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
3909 mnemonic, suffix, rd, rn, (int) (opcode & 0xf));
3910
3911 shift:
3912 cp = strchr(cp, 0);
3913
3914 switch (type) {
3915 case 0:
3916 if (immed == 0)
3917 return ERROR_OK;
3918 suffix = "LSL";
3919 break;
3920 case 1:
3921 suffix = "LSR";
3922 if (immed == 32)
3923 immed = 0;
3924 break;
3925 case 2:
3926 suffix = "ASR";
3927 if (immed == 32)
3928 immed = 0;
3929 break;
3930 case 3:
3931 if (immed == 0) {
3932 strcpy(cp, ", RRX");
3933 return ERROR_OK;
3934 }
3935 suffix = "ROR";
3936 break;
3937 }
3938 sprintf(cp, ", %s #%d", suffix, immed ? immed : 32);
3939 return ERROR_OK;
3940
3941 two:
3942 sprintf(cp, "%s%s.W\tr%d, r%d",
3943 mnemonic, suffix, rn, (int) (opcode & 0xf));
3944 goto shift;
3945
3946 immediate:
3947 sprintf(cp, "%s%s.W\tr%d, r%d, #%d",
3948 mnemonic, suffix, rd,
3949 (int) (opcode & 0xf), immed ? immed : 32);
3950 return ERROR_OK;
3951 }
3952
3953 static int t2ev_data_reg(uint32_t opcode, uint32_t address,
3954 struct arm_instruction *instruction, char *cp)
3955 {
3956 char *mnemonic;
3957 char *suffix = "";
3958
3959 if (((opcode >> 4) & 0xf) == 0) {
3960 switch ((opcode >> 21) & 0x7) {
3961 case 0:
3962 mnemonic = "LSL";
3963 break;
3964 case 1:
3965 mnemonic = "LSR";
3966 break;
3967 case 2:
3968 mnemonic = "ASR";
3969 break;
3970 case 3:
3971 mnemonic = "ROR";
3972 break;
3973 default:
3974 return ERROR_COMMAND_SYNTAX_ERROR;
3975 }
3976
3977 instruction->type = ARM_MOV;
3978 if (opcode & (1 << 20))
3979 suffix = "S";
3980 sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
3981 mnemonic, suffix,
3982 (int) (opcode >> 8) & 0xf,
3983 (int) (opcode >> 16) & 0xf,
3984 (int) (opcode >> 0) & 0xf);
3985
3986 } else if (opcode & (1 << 7)) {
3987 switch ((opcode >> 20) & 0xf) {
3988 case 0:
3989 case 1:
3990 case 4:
3991 case 5:
3992 switch ((opcode >> 4) & 0x3) {
3993 case 1:
3994 suffix = ", ROR #8";
3995 break;
3996 case 2:
3997 suffix = ", ROR #16";
3998 break;
3999 case 3:
4000 suffix = ", ROR #24";
4001 break;
4002 }
4003 sprintf(cp, "%cXT%c.W\tr%d, r%d%s",
4004 (opcode & (1 << 24)) ? 'U' : 'S',
4005 (opcode & (1 << 26)) ? 'B' : 'H',
4006 (int) (opcode >> 8) & 0xf,
4007 (int) (opcode >> 0) & 0xf,
4008 suffix);
4009 break;
4010 case 8:
4011 case 9:
4012 case 0xa:
4013 case 0xb:
4014 if (opcode & (1 << 6))
4015 return ERROR_COMMAND_SYNTAX_ERROR;
4016 if (((opcode >> 12) & 0xf) != 0xf)
4017 return ERROR_COMMAND_SYNTAX_ERROR;
4018 if (!(opcode & (1 << 20)))
4019 return ERROR_COMMAND_SYNTAX_ERROR;
4020
4021 switch (((opcode >> 19) & 0x04)
4022 | ((opcode >> 4) & 0x3)) {
4023 case 0:
4024 mnemonic = "REV.W";
4025 break;
4026 case 1:
4027 mnemonic = "REV16.W";
4028 break;
4029 case 2:
4030 mnemonic = "RBIT";
4031 break;
4032 case 3:
4033 mnemonic = "REVSH.W";
4034 break;
4035 case 4:
4036 mnemonic = "CLZ";
4037 break;
4038 default:
4039 return ERROR_COMMAND_SYNTAX_ERROR;
4040 }
4041 sprintf(cp, "%s\tr%d, r%d",
4042 mnemonic,
4043 (int) (opcode >> 8) & 0xf,
4044 (int) (opcode >> 0) & 0xf);
4045 break;
4046 default:
4047 return ERROR_COMMAND_SYNTAX_ERROR;
4048 }
4049 }
4050
4051 return ERROR_OK;
4052 }
4053
4054 static int t2ev_load_word(uint32_t opcode, uint32_t address,
4055 struct arm_instruction *instruction, char *cp)
4056 {
4057 int rn = (opcode >> 16) & 0xf;
4058 int immed;
4059
4060 instruction->type = ARM_LDR;
4061
4062 if (rn == 0xf) {
4063 immed = opcode & 0x0fff;
4064 if ((opcode & (1 << 23)) == 0)
4065 immed = -immed;
4066 sprintf(cp, "LDR\tr%d, %#8.8" PRIx32,
4067 (int) (opcode >> 12) & 0xf,
4068 thumb_alignpc4(address) + immed);
4069 return ERROR_OK;
4070 }
4071
4072 if (opcode & (1 << 23)) {
4073 immed = opcode & 0x0fff;
4074 sprintf(cp, "LDR.W\tr%d, [r%d, #%d]\t; %#3.3x",
4075 (int) (opcode >> 12) & 0xf,
4076 rn, immed, immed);
4077 return ERROR_OK;
4078 }
4079
4080 if (!(opcode & (0x3f << 6))) {
4081 sprintf(cp, "LDR.W\tr%d, [r%d, r%d, LSL #%d]",
4082 (int) (opcode >> 12) & 0xf,
4083 rn,
4084 (int) (opcode >> 0) & 0xf,
4085 (int) (opcode >> 4) & 0x3);
4086 return ERROR_OK;
4087 }
4088
4089
4090 if (((opcode >> 8) & 0xf) == 0xe) {
4091 immed = opcode & 0x00ff;
4092
4093 sprintf(cp, "LDRT\tr%d, [r%d, #%d]\t; %#2.2x",
4094 (int) (opcode >> 12) & 0xf,
4095 rn, immed, immed);
4096 return ERROR_OK;
4097 }
4098
4099 if (((opcode >> 8) & 0xf) == 0xc || (opcode & 0x0900) == 0x0900) {
4100 char *p1 = "]", *p2 = "";
4101
4102 if (!(opcode & 0x0500))
4103 return ERROR_COMMAND_SYNTAX_ERROR;
4104
4105 immed = opcode & 0x00ff;
4106
4107 /* two indexed modes will write back rn */
4108 if (opcode & 0x100) {
4109 if (opcode & 0x400) /* pre-indexed */
4110 p2 = "]!";
4111 else { /* post-indexed */
4112 p1 = "]";
4113 p2 = "";
4114 }
4115 }
4116
4117 sprintf(cp, "LDR\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
4118 (int) (opcode >> 12) & 0xf,
4119 rn, p1,
4120 (opcode & 0x200) ? "" : "-",
4121 immed, p2, immed);
4122 return ERROR_OK;
4123 }
4124
4125 return ERROR_COMMAND_SYNTAX_ERROR;
4126 }
4127
4128 static int t2ev_load_byte_hints(uint32_t opcode, uint32_t address,
4129 struct arm_instruction *instruction, char *cp)
4130 {
4131 int rn = (opcode >> 16) & 0xf;
4132 int rt = (opcode >> 12) & 0xf;
4133 int op2 = (opcode >> 6) & 0x3f;
4134 unsigned immed;
4135 char *p1 = "", *p2 = "]";
4136 char *mnemonic;
4137
4138 switch ((opcode >> 23) & 0x3) {
4139 case 0:
4140 if ((rn & rt) == 0xf) {
4141 pld_literal:
4142 immed = opcode & 0xfff;
4143 address = thumb_alignpc4(address);
4144 if (opcode & (1 << 23))
4145 address += immed;
4146 else
4147 address -= immed;
4148 sprintf(cp, "PLD\tr%d, %#8.8" PRIx32,
4149 rt, address);
4150 return ERROR_OK;
4151 }
4152 if (rn == 0x0f && rt != 0x0f) {
4153 ldrb_literal:
4154 immed = opcode & 0xfff;
4155 address = thumb_alignpc4(address);
4156 if (opcode & (1 << 23))
4157 address += immed;
4158 else
4159 address -= immed;
4160 sprintf(cp, "LDRB\tr%d, %#8.8" PRIx32,
4161 rt, address);
4162 return ERROR_OK;
4163 }
4164 if (rn == 0x0f)
4165 break;
4166 if ((op2 & 0x3c) == 0x38) {
4167 immed = opcode & 0xff;
4168 sprintf(cp, "LDRBT\tr%d, [r%d, #%d]\t; %#2.2x",
4169 rt, rn, immed, immed);
4170 return ERROR_OK;
4171 }
4172 if ((op2 & 0x3c) == 0x30) {
4173 if (rt == 0x0f) {
4174 immed = opcode & 0xff;
4175 immed = -immed;
4176 preload_immediate:
4177 p1 = (opcode & (1 << 21)) ? "W" : "";
4178 sprintf(cp, "PLD%s\t[r%d, #%d]\t; %#6.6x",
4179 p1, rn, immed, immed);
4180 return ERROR_OK;
4181 }
4182 mnemonic = "LDRB";
4183 ldrxb_immediate_t3:
4184 immed = opcode & 0xff;
4185 if (!(opcode & 0x200))
4186 immed = -immed;
4187
4188 /* two indexed modes will write back rn */
4189 if (opcode & 0x100) {
4190 if (opcode & 0x400) /* pre-indexed */
4191 p2 = "]!";
4192 else { /* post-indexed */
4193 p1 = "]";
4194 p2 = "";
4195 }
4196 }
4197 ldrxb_immediate_t2:
4198 sprintf(cp, "%s\tr%d, [r%d%s, #%d%s\t; %#8.8x",
4199 mnemonic, rt, rn, p1,
4200 immed, p2, immed);
4201 return ERROR_OK;
4202 }
4203 if ((op2 & 0x24) == 0x24) {
4204 mnemonic = "LDRB";
4205 goto ldrxb_immediate_t3;
4206 }
4207 if (op2 == 0) {
4208 int rm = opcode & 0xf;
4209
4210 if (rt == 0x0f)
4211 sprintf(cp, "PLD\t");
4212 else
4213 sprintf(cp, "LDRB.W\tr%d, ", rt);
4214 immed = (opcode >> 4) & 0x3;
4215 cp = strchr(cp, 0);
4216 sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed);
4217 return ERROR_OK;
4218 }
4219 break;
4220 case 1:
4221 if ((rn & rt) == 0xf)
4222 goto pld_literal;
4223 if (rt == 0xf) {
4224 immed = opcode & 0xfff;
4225 goto preload_immediate;
4226 }
4227 if (rn == 0x0f)
4228 goto ldrb_literal;
4229 mnemonic = "LDRB.W";
4230 immed = opcode & 0xfff;
4231 goto ldrxb_immediate_t2;
4232 case 2:
4233 if ((rn & rt) == 0xf) {
4234 immed = opcode & 0xfff;
4235 address = thumb_alignpc4(address);
4236 if (opcode & (1 << 23))
4237 address += immed;
4238 else
4239 address -= immed;
4240 sprintf(cp, "PLI\t%#8.8" PRIx32, address);
4241 return ERROR_OK;
4242 }
4243 if (rn == 0xf && rt != 0xf) {
4244 ldrsb_literal:
4245 immed = opcode & 0xfff;
4246 address = thumb_alignpc4(address);
4247 if (opcode & (1 << 23))
4248 address += immed;
4249 else
4250 address -= immed;
4251 sprintf(cp, "LDRSB\t%#8.8" PRIx32, address);
4252 return ERROR_OK;
4253 }
4254 if (rn == 0xf)
4255 break;
4256 if ((op2 & 0x3c) == 0x38) {
4257 immed = opcode & 0xff;
4258 sprintf(cp, "LDRSBT\tr%d, [r%d, #%d]\t; %#2.2x",
4259 rt, rn, immed, immed);
4260 return ERROR_OK;
4261 }
4262 if ((op2 & 0x3c) == 0x30) {
4263 if (rt == 0xf) {
4264 immed = opcode & 0xff;
4265 immed = -immed; /* pli */
4266 sprintf(cp, "PLI\t[r%d, #%d]\t; -%#2.2x",
4267 rn, immed, -immed);
4268 return ERROR_OK;
4269 }
4270 mnemonic = "LDRSB";
4271 goto ldrxb_immediate_t3;
4272 }
4273 if ((op2 & 0x24) == 0x24) {
4274 mnemonic = "LDRSB";
4275 goto ldrxb_immediate_t3;
4276 }
4277 if (op2 == 0) {
4278 int rm = opcode & 0xf;
4279
4280 if (rt == 0x0f)
4281 sprintf(cp, "PLI\t");
4282 else
4283 sprintf(cp, "LDRSB.W\tr%d, ", rt);
4284 immed = (opcode >> 4) & 0x3;
4285 cp = strchr(cp, 0);
4286 sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed);
4287 return ERROR_OK;
4288 }
4289 break;
4290 case 3:
4291 if (rt == 0xf) {
4292 immed = opcode & 0xfff;
4293 sprintf(cp, "PLI\t[r%d, #%d]\t; %#3.3x",
4294 rn, immed, immed);
4295 return ERROR_OK;
4296 }
4297 if (rn == 0xf)
4298 goto ldrsb_literal;
4299 immed = opcode & 0xfff;
4300 mnemonic = "LDRSB";
4301 goto ldrxb_immediate_t2;
4302 }
4303
4304 return ERROR_COMMAND_SYNTAX_ERROR;
4305 }
4306
4307 static int t2ev_load_halfword(uint32_t opcode, uint32_t address,
4308 struct arm_instruction *instruction, char *cp)
4309 {
4310 int rn = (opcode >> 16) & 0xf;
4311 int rt = (opcode >> 12) & 0xf;
4312 int op2 = (opcode >> 6) & 0x3f;
4313 char *sign = "";
4314 unsigned immed;
4315
4316 if (rt == 0xf) {
4317 sprintf(cp, "HINT (UNALLOCATED)");
4318 return ERROR_OK;
4319 }
4320
4321 if (opcode & (1 << 24))
4322 sign = "S";
4323
4324 if ((opcode & (1 << 23)) == 0) {
4325 if (rn == 0xf) {
4326 ldrh_literal:
4327 immed = opcode & 0xfff;
4328 address = thumb_alignpc4(address);
4329 if (opcode & (1 << 23))
4330 address += immed;
4331 else
4332 address -= immed;
4333 sprintf(cp, "LDR%sH\tr%d, %#8.8" PRIx32,
4334 sign, rt, address);
4335 return ERROR_OK;
4336 }
4337 if (op2 == 0) {
4338 int rm = opcode & 0xf;
4339
4340 immed = (opcode >> 4) & 0x3;
4341 sprintf(cp, "LDR%sH.W\tr%d, [r%d, r%d, LSL #%d]",
4342 sign, rt, rn, rm, immed);
4343 return ERROR_OK;
4344 }
4345 if ((op2 & 0x3c) == 0x38) {
4346 immed = opcode & 0xff;
4347 sprintf(cp, "LDR%sHT\tr%d, [r%d, #%d]\t; %#2.2x",
4348 sign, rt, rn, immed, immed);
4349 return ERROR_OK;
4350 }
4351 if ((op2 & 0x3c) == 0x30 || (op2 & 0x24) == 0x24) {
4352 char *p1 = "", *p2 = "]";
4353
4354 immed = opcode & 0xff;
4355 if (!(opcode & 0x200))
4356 immed = -immed;
4357
4358 /* two indexed modes will write back rn */
4359 if (opcode & 0x100) {
4360 if (opcode & 0x400) /* pre-indexed */
4361 p2 = "]!";
4362 else { /* post-indexed */
4363 p1 = "]";
4364 p2 = "";
4365 }
4366 }
4367 sprintf(cp, "LDR%sH\tr%d, [r%d%s, #%d%s\t; %#8.8x",
4368 sign, rt, rn, p1, immed, p2, immed);
4369 return ERROR_OK;
4370 }
4371 } else {
4372 if (rn == 0xf)
4373 goto ldrh_literal;
4374
4375 immed = opcode & 0xfff;
4376 sprintf(cp, "LDR%sH%s\tr%d, [r%d, #%d]\t; %#6.6x",
4377 sign, *sign ? "" : ".W",
4378 rt, rn, immed, immed);
4379 return ERROR_OK;
4380 }
4381
4382 return ERROR_COMMAND_SYNTAX_ERROR;
4383 }
4384
4385 /*
4386 * REVISIT for Thumb2 instructions, instruction->type and friends aren't
4387 * always set. That means eventual arm_simulate_step() support for Thumb2
4388 * will need work in this area.
4389 */
4390 int thumb2_opcode(struct target *target, uint32_t address, struct arm_instruction *instruction)
4391 {
4392 int retval;
4393 uint16_t op;
4394 uint32_t opcode;
4395 char *cp;
4396
4397 /* clear low bit ... it's set on function pointers */
4398 address &= ~1;
4399
4400 /* clear fields, to avoid confusion */
4401 memset(instruction, 0, sizeof(struct arm_instruction));
4402
4403 /* read first halfword, see if this is the only one */
4404 retval = target_read_u16(target, address, &op);
4405 if (retval != ERROR_OK)
4406 return retval;
4407
4408 switch (op & 0xf800) {
4409 case 0xf800:
4410 case 0xf000:
4411 case 0xe800:
4412 /* 32-bit instructions */
4413 instruction->instruction_size = 4;
4414 opcode = op << 16;
4415 retval = target_read_u16(target, address + 2, &op);
4416 if (retval != ERROR_OK)
4417 return retval;
4418 opcode |= op;
4419 instruction->opcode = opcode;
4420 break;
4421 default:
4422 /* 16-bit: Thumb1 + IT + CBZ/CBNZ + ... */
4423 return thumb_evaluate_opcode(op, address, instruction);
4424 }
4425
4426 snprintf(instruction->text, 128,
4427 "0x%8.8" PRIx32 " 0x%8.8" PRIx32 "\t",
4428 address, opcode);
4429 cp = strchr(instruction->text, 0);
4430 retval = ERROR_FAIL;
4431
4432 /* ARMv7-M: A5.3.1 Data processing (modified immediate) */
4433 if ((opcode & 0x1a008000) == 0x10000000)
4434 retval = t2ev_data_mod_immed(opcode, address, instruction, cp);
4435
4436 /* ARMv7-M: A5.3.3 Data processing (plain binary immediate) */
4437 else if ((opcode & 0x1a008000) == 0x12000000)
4438 retval = t2ev_data_immed(opcode, address, instruction, cp);
4439
4440 /* ARMv7-M: A5.3.4 Branches and miscellaneous control */
4441 else if ((opcode & 0x18008000) == 0x10008000)
4442 retval = t2ev_b_misc(opcode, address, instruction, cp);
4443
4444 /* ARMv7-M: A5.3.5 Load/store multiple */
4445 else if ((opcode & 0x1e400000) == 0x08000000)
4446 retval = t2ev_ldm_stm(opcode, address, instruction, cp);
4447
4448 /* ARMv7-M: A5.3.6 Load/store dual or exclusive, table branch */
4449 else if ((opcode & 0x1e400000) == 0x08400000)
4450 retval = t2ev_ldrex_strex(opcode, address, instruction, cp);
4451
4452 /* ARMv7-M: A5.3.7 Load word */
4453 else if ((opcode & 0x1f700000) == 0x18500000)
4454 retval = t2ev_load_word(opcode, address, instruction, cp);
4455
4456 /* ARMv7-M: A5.3.8 Load halfword, unallocated memory hints */
4457 else if ((opcode & 0x1e700000) == 0x18300000)
4458 retval = t2ev_load_halfword(opcode, address, instruction, cp);
4459
4460 /* ARMv7-M: A5.3.9 Load byte, memory hints */
4461 else if ((opcode & 0x1e700000) == 0x18100000)
4462 retval = t2ev_load_byte_hints(opcode, address, instruction, cp);
4463
4464 /* ARMv7-M: A5.3.10 Store single data item */
4465 else if ((opcode & 0x1f100000) == 0x18000000)
4466 retval = t2ev_store_single(opcode, address, instruction, cp);
4467
4468 /* ARMv7-M: A5.3.11 Data processing (shifted register) */
4469 else if ((opcode & 0x1e000000) == 0x0a000000)
4470 retval = t2ev_data_shift(opcode, address, instruction, cp);
4471
4472 /* ARMv7-M: A5.3.12 Data processing (register)
4473 * and A5.3.13 Miscellaneous operations
4474 */
4475 else if ((opcode & 0x1f000000) == 0x1a000000)
4476 retval = t2ev_data_reg(opcode, address, instruction, cp);
4477
4478 /* ARMv7-M: A5.3.14 Multiply, and multiply accumulate */
4479 else if ((opcode & 0x1f800000) == 0x1b000000)
4480 retval = t2ev_mul32(opcode, address, instruction, cp);
4481
4482 /* ARMv7-M: A5.3.15 Long multiply, long multiply accumulate, divide */
4483 else if ((opcode & 0x1f800000) == 0x1b800000)
4484 retval = t2ev_mul64_div(opcode, address, instruction, cp);
4485
4486 if (retval == ERROR_OK)
4487 return retval;
4488
4489 /*
4490 * Thumb2 also supports coprocessor, ThumbEE, and DSP/Media (SIMD)
4491 * instructions; not yet handled here.
4492 */
4493
4494 if (retval == ERROR_COMMAND_SYNTAX_ERROR) {
4495 instruction->type = ARM_UNDEFINED_INSTRUCTION;
4496 strcpy(cp, "UNDEFINED OPCODE");
4497 return ERROR_OK;
4498 }
4499
4500 LOG_DEBUG("Can't decode 32-bit Thumb2 yet (opcode=%08" PRIx32 ")",
4501 opcode);
4502
4503 strcpy(cp, "(32-bit Thumb2 ...)");
4504 return ERROR_OK;
4505 }
4506
4507 int arm_access_size(struct arm_instruction *instruction)
4508 {
4509 if ((instruction->type == ARM_LDRB)
4510 || (instruction->type == ARM_LDRBT)
4511 || (instruction->type == ARM_LDRSB)
4512 || (instruction->type == ARM_STRB)
4513 || (instruction->type == ARM_STRBT))
4514 return 1;
4515 else if ((instruction->type == ARM_LDRH)
4516 || (instruction->type == ARM_LDRSH)
4517 || (instruction->type == ARM_STRH))
4518 return 2;
4519 else if ((instruction->type == ARM_LDR)
4520 || (instruction->type == ARM_LDRT)
4521 || (instruction->type == ARM_STR)
4522 || (instruction->type == ARM_STRT))
4523 return 4;
4524 else if ((instruction->type == ARM_LDRD)
4525 || (instruction->type == ARM_STRD))
4526 return 8;
4527 else {
4528 LOG_ERROR("BUG: instruction type %i isn't a load/store instruction",
4529 instruction->type);
4530 return 0;
4531 }
4532 }

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)