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

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)