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

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)