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

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)