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

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)