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

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)