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

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)