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

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)