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

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)