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

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)