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

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)