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

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)