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

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)