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

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)