David Brownell <david-b@pacbell.net> thumb2 disassembly for Load halfword
[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 instruction->type = ARM_ADD;
1399 mnemonic = "ADDS";
1400 }
1401
1402 instruction->info.data_proc.Rd = Rd;
1403 instruction->info.data_proc.Rn = Rn;
1404 instruction->info.data_proc.S = 1;
1405
1406 if (reg_imm)
1407 {
1408 instruction->info.data_proc.variant = 0; /*immediate*/
1409 instruction->info.data_proc.shifter_operand.immediate.immediate = Rm_imm;
1410 snprintf(instruction->text, 128,
1411 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%d",
1412 address, opcode, mnemonic, Rd, Rn, Rm_imm);
1413 }
1414 else
1415 {
1416 instruction->info.data_proc.variant = 1; /*immediate shift*/
1417 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm_imm;
1418 snprintf(instruction->text, 128,
1419 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, r%i",
1420 address, opcode, mnemonic, Rd, Rn, Rm_imm);
1421 }
1422
1423 return ERROR_OK;
1424 }
1425
1426 int evaluate_shift_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1427 {
1428 uint8_t Rd = (opcode >> 0) & 0x7;
1429 uint8_t Rm = (opcode >> 3) & 0x7;
1430 uint8_t imm = (opcode >> 6) & 0x1f;
1431 uint8_t opc = (opcode >> 11) & 0x3;
1432 char *mnemonic = NULL;
1433
1434 switch (opc)
1435 {
1436 case 0:
1437 instruction->type = ARM_MOV;
1438 mnemonic = "LSLS";
1439 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 0;
1440 break;
1441 case 1:
1442 instruction->type = ARM_MOV;
1443 mnemonic = "LSRS";
1444 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 1;
1445 break;
1446 case 2:
1447 instruction->type = ARM_MOV;
1448 mnemonic = "ASRS";
1449 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 2;
1450 break;
1451 }
1452
1453 if ((imm == 0) && (opc != 0))
1454 imm = 32;
1455
1456 instruction->info.data_proc.Rd = Rd;
1457 instruction->info.data_proc.Rn = -1;
1458 instruction->info.data_proc.S = 1;
1459
1460 instruction->info.data_proc.variant = 1; /*immediate_shift*/
1461 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1462 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = imm;
1463
1464 snprintf(instruction->text, 128,
1465 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%#2.2x" ,
1466 address, opcode, mnemonic, Rd, Rm, imm);
1467
1468 return ERROR_OK;
1469 }
1470
1471 int evaluate_data_proc_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1472 {
1473 uint8_t imm = opcode & 0xff;
1474 uint8_t Rd = (opcode >> 8) & 0x7;
1475 uint32_t opc = (opcode >> 11) & 0x3;
1476 char *mnemonic = NULL;
1477
1478 instruction->info.data_proc.Rd = Rd;
1479 instruction->info.data_proc.Rn = Rd;
1480 instruction->info.data_proc.S = 1;
1481 instruction->info.data_proc.variant = 0; /*immediate*/
1482 instruction->info.data_proc.shifter_operand.immediate.immediate = imm;
1483
1484 switch (opc)
1485 {
1486 case 0:
1487 instruction->type = ARM_MOV;
1488 mnemonic = "MOVS";
1489 instruction->info.data_proc.Rn = -1;
1490 break;
1491 case 1:
1492 instruction->type = ARM_CMP;
1493 mnemonic = "CMP";
1494 instruction->info.data_proc.Rd = -1;
1495 break;
1496 case 2:
1497 instruction->type = ARM_ADD;
1498 mnemonic = "ADDS";
1499 break;
1500 case 3:
1501 instruction->type = ARM_SUB;
1502 mnemonic = "SUBS";
1503 break;
1504 }
1505
1506 snprintf(instruction->text, 128,
1507 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, #%#2.2x",
1508 address, opcode, mnemonic, Rd, imm);
1509
1510 return ERROR_OK;
1511 }
1512
1513 int evaluate_data_proc_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1514 {
1515 uint8_t high_reg, op, Rm, Rd,H1,H2;
1516 char *mnemonic = NULL;
1517 bool nop = false;
1518
1519 high_reg = (opcode & 0x0400) >> 10;
1520 op = (opcode & 0x03C0) >> 6;
1521
1522 Rd = (opcode & 0x0007);
1523 Rm = (opcode & 0x0038) >> 3;
1524 H1 = (opcode & 0x0080) >> 7;
1525 H2 = (opcode & 0x0040) >> 6;
1526
1527 instruction->info.data_proc.Rd = Rd;
1528 instruction->info.data_proc.Rn = Rd;
1529 instruction->info.data_proc.S = (!high_reg || (instruction->type == ARM_CMP));
1530 instruction->info.data_proc.variant = 1 /*immediate shift*/;
1531 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1532
1533 if (high_reg)
1534 {
1535 Rd |= H1 << 3;
1536 Rm |= H2 << 3;
1537 op >>= 2;
1538
1539 switch (op)
1540 {
1541 case 0x0:
1542 instruction->type = ARM_ADD;
1543 mnemonic = "ADD";
1544 break;
1545 case 0x1:
1546 instruction->type = ARM_CMP;
1547 mnemonic = "CMP";
1548 break;
1549 case 0x2:
1550 instruction->type = ARM_MOV;
1551 mnemonic = "MOV";
1552 if (Rd == Rm)
1553 nop = true;
1554 break;
1555 case 0x3:
1556 if ((opcode & 0x7) == 0x0)
1557 {
1558 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1559 if (H1)
1560 {
1561 instruction->type = ARM_BLX;
1562 snprintf(instruction->text, 128,
1563 "0x%8.8" PRIx32
1564 " 0x%4.4x \tBLX\tr%i",
1565 address, opcode, Rm);
1566 }
1567 else
1568 {
1569 instruction->type = ARM_BX;
1570 snprintf(instruction->text, 128,
1571 "0x%8.8" PRIx32
1572 " 0x%4.4x \tBX\tr%i",
1573 address, opcode, Rm);
1574 }
1575 }
1576 else
1577 {
1578 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1579 snprintf(instruction->text, 128,
1580 "0x%8.8" PRIx32
1581 " 0x%4.4x \t"
1582 "UNDEFINED INSTRUCTION",
1583 address, opcode);
1584 }
1585 return ERROR_OK;
1586 break;
1587 }
1588 }
1589 else
1590 {
1591 switch (op)
1592 {
1593 case 0x0:
1594 instruction->type = ARM_AND;
1595 mnemonic = "ANDS";
1596 break;
1597 case 0x1:
1598 instruction->type = ARM_EOR;
1599 mnemonic = "EORS";
1600 break;
1601 case 0x2:
1602 instruction->type = ARM_MOV;
1603 mnemonic = "LSLS";
1604 instruction->info.data_proc.variant = 2 /*register shift*/;
1605 instruction->info.data_proc.shifter_operand.register_shift.shift = 0;
1606 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1607 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1608 break;
1609 case 0x3:
1610 instruction->type = ARM_MOV;
1611 mnemonic = "LSRS";
1612 instruction->info.data_proc.variant = 2 /*register shift*/;
1613 instruction->info.data_proc.shifter_operand.register_shift.shift = 1;
1614 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1615 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1616 break;
1617 case 0x4:
1618 instruction->type = ARM_MOV;
1619 mnemonic = "ASRS";
1620 instruction->info.data_proc.variant = 2 /*register shift*/;
1621 instruction->info.data_proc.shifter_operand.register_shift.shift = 2;
1622 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1623 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1624 break;
1625 case 0x5:
1626 instruction->type = ARM_ADC;
1627 mnemonic = "ADCS";
1628 break;
1629 case 0x6:
1630 instruction->type = ARM_SBC;
1631 mnemonic = "SBCS";
1632 break;
1633 case 0x7:
1634 instruction->type = ARM_MOV;
1635 mnemonic = "RORS";
1636 instruction->info.data_proc.variant = 2 /*register shift*/;
1637 instruction->info.data_proc.shifter_operand.register_shift.shift = 3;
1638 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1639 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1640 break;
1641 case 0x8:
1642 instruction->type = ARM_TST;
1643 mnemonic = "TST";
1644 break;
1645 case 0x9:
1646 instruction->type = ARM_RSB;
1647 mnemonic = "NEGS";
1648 instruction->info.data_proc.variant = 0 /*immediate*/;
1649 instruction->info.data_proc.shifter_operand.immediate.immediate = 0;
1650 instruction->info.data_proc.Rn = Rm;
1651 break;
1652 case 0xA:
1653 instruction->type = ARM_CMP;
1654 mnemonic = "CMP";
1655 break;
1656 case 0xB:
1657 instruction->type = ARM_CMN;
1658 mnemonic = "CMN";
1659 break;
1660 case 0xC:
1661 instruction->type = ARM_ORR;
1662 mnemonic = "ORRS";
1663 break;
1664 case 0xD:
1665 instruction->type = ARM_MUL;
1666 mnemonic = "MULS";
1667 break;
1668 case 0xE:
1669 instruction->type = ARM_BIC;
1670 mnemonic = "BICS";
1671 break;
1672 case 0xF:
1673 instruction->type = ARM_MVN;
1674 mnemonic = "MVNS";
1675 break;
1676 }
1677 }
1678
1679 if (nop)
1680 snprintf(instruction->text, 128,
1681 "0x%8.8" PRIx32 " 0x%4.4x \tNOP\t\t\t"
1682 "; (%s r%i, r%i)",
1683 address, opcode, mnemonic, Rd, Rm);
1684 else
1685 snprintf(instruction->text, 128,
1686 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i",
1687 address, opcode, mnemonic, Rd, Rm);
1688
1689 return ERROR_OK;
1690 }
1691
1692 /* PC-relative data addressing is word-aligned even with Thumb */
1693 static inline uint32_t thumb_alignpc4(uint32_t addr)
1694 {
1695 return (addr + 4) & ~3;
1696 }
1697
1698 int evaluate_load_literal_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1699 {
1700 uint32_t immediate;
1701 uint8_t Rd = (opcode >> 8) & 0x7;
1702
1703 instruction->type = ARM_LDR;
1704 immediate = opcode & 0x000000ff;
1705 immediate *= 4;
1706
1707 instruction->info.load_store.Rd = Rd;
1708 instruction->info.load_store.Rn = 15 /*PC*/;
1709 instruction->info.load_store.index_mode = 0; /*offset*/
1710 instruction->info.load_store.offset_mode = 0; /*immediate*/
1711 instruction->info.load_store.offset.offset = immediate;
1712
1713 snprintf(instruction->text, 128,
1714 "0x%8.8" PRIx32 " 0x%4.4x \t"
1715 "LDR\tr%i, [pc, #%#" PRIx32 "]\t; %#8.8" PRIx32,
1716 address, opcode, Rd, immediate,
1717 thumb_alignpc4(address) + immediate);
1718
1719 return ERROR_OK;
1720 }
1721
1722 int evaluate_load_store_reg_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1723 {
1724 uint8_t Rd = (opcode >> 0) & 0x7;
1725 uint8_t Rn = (opcode >> 3) & 0x7;
1726 uint8_t Rm = (opcode >> 6) & 0x7;
1727 uint8_t opc = (opcode >> 9) & 0x7;
1728 char *mnemonic = NULL;
1729
1730 switch (opc)
1731 {
1732 case 0:
1733 instruction->type = ARM_STR;
1734 mnemonic = "STR";
1735 break;
1736 case 1:
1737 instruction->type = ARM_STRH;
1738 mnemonic = "STRH";
1739 break;
1740 case 2:
1741 instruction->type = ARM_STRB;
1742 mnemonic = "STRB";
1743 break;
1744 case 3:
1745 instruction->type = ARM_LDRSB;
1746 mnemonic = "LDRSB";
1747 break;
1748 case 4:
1749 instruction->type = ARM_LDR;
1750 mnemonic = "LDR";
1751 break;
1752 case 5:
1753 instruction->type = ARM_LDRH;
1754 mnemonic = "LDRH";
1755 break;
1756 case 6:
1757 instruction->type = ARM_LDRB;
1758 mnemonic = "LDRB";
1759 break;
1760 case 7:
1761 instruction->type = ARM_LDRSH;
1762 mnemonic = "LDRSH";
1763 break;
1764 }
1765
1766 snprintf(instruction->text, 128,
1767 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [r%i, r%i]",
1768 address, opcode, mnemonic, Rd, Rn, Rm);
1769
1770 instruction->info.load_store.Rd = Rd;
1771 instruction->info.load_store.Rn = Rn;
1772 instruction->info.load_store.index_mode = 0; /*offset*/
1773 instruction->info.load_store.offset_mode = 1; /*register*/
1774 instruction->info.load_store.offset.reg.Rm = Rm;
1775
1776 return ERROR_OK;
1777 }
1778
1779 int evaluate_load_store_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1780 {
1781 uint32_t offset = (opcode >> 6) & 0x1f;
1782 uint8_t Rd = (opcode >> 0) & 0x7;
1783 uint8_t Rn = (opcode >> 3) & 0x7;
1784 uint32_t L = opcode & (1 << 11);
1785 uint32_t B = opcode & (1 << 12);
1786 char *mnemonic;
1787 char suffix = ' ';
1788 uint32_t shift = 2;
1789
1790 if (L)
1791 {
1792 instruction->type = ARM_LDR;
1793 mnemonic = "LDR";
1794 }
1795 else
1796 {
1797 instruction->type = ARM_STR;
1798 mnemonic = "STR";
1799 }
1800
1801 if ((opcode&0xF000) == 0x8000)
1802 {
1803 suffix = 'H';
1804 shift = 1;
1805 }
1806 else if (B)
1807 {
1808 suffix = 'B';
1809 shift = 0;
1810 }
1811
1812 snprintf(instruction->text, 128,
1813 "0x%8.8" PRIx32 " 0x%4.4x \t%s%c\tr%i, [r%i, #%#" PRIx32 "]",
1814 address, opcode, mnemonic, suffix, Rd, Rn, offset << shift);
1815
1816 instruction->info.load_store.Rd = Rd;
1817 instruction->info.load_store.Rn = Rn;
1818 instruction->info.load_store.index_mode = 0; /*offset*/
1819 instruction->info.load_store.offset_mode = 0; /*immediate*/
1820 instruction->info.load_store.offset.offset = offset << shift;
1821
1822 return ERROR_OK;
1823 }
1824
1825 int evaluate_load_store_stack_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1826 {
1827 uint32_t offset = opcode & 0xff;
1828 uint8_t Rd = (opcode >> 8) & 0x7;
1829 uint32_t L = opcode & (1 << 11);
1830 char *mnemonic;
1831
1832 if (L)
1833 {
1834 instruction->type = ARM_LDR;
1835 mnemonic = "LDR";
1836 }
1837 else
1838 {
1839 instruction->type = ARM_STR;
1840 mnemonic = "STR";
1841 }
1842
1843 snprintf(instruction->text, 128,
1844 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [SP, #%#" PRIx32 "]",
1845 address, opcode, mnemonic, Rd, offset*4);
1846
1847 instruction->info.load_store.Rd = Rd;
1848 instruction->info.load_store.Rn = 13 /*SP*/;
1849 instruction->info.load_store.index_mode = 0; /*offset*/
1850 instruction->info.load_store.offset_mode = 0; /*immediate*/
1851 instruction->info.load_store.offset.offset = offset*4;
1852
1853 return ERROR_OK;
1854 }
1855
1856 int evaluate_add_sp_pc_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1857 {
1858 uint32_t imm = opcode & 0xff;
1859 uint8_t Rd = (opcode >> 8) & 0x7;
1860 uint8_t Rn;
1861 uint32_t SP = opcode & (1 << 11);
1862 char *reg_name;
1863
1864 instruction->type = ARM_ADD;
1865
1866 if (SP)
1867 {
1868 reg_name = "SP";
1869 Rn = 13;
1870 }
1871 else
1872 {
1873 reg_name = "PC";
1874 Rn = 15;
1875 }
1876
1877 snprintf(instruction->text, 128,
1878 "0x%8.8" PRIx32 " 0x%4.4x \tADD\tr%i, %s, #%#" PRIx32,
1879 address, opcode, Rd, reg_name, imm * 4);
1880
1881 instruction->info.data_proc.variant = 0 /* immediate */;
1882 instruction->info.data_proc.Rd = Rd;
1883 instruction->info.data_proc.Rn = Rn;
1884 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
1885
1886 return ERROR_OK;
1887 }
1888
1889 int evaluate_adjust_stack_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1890 {
1891 uint32_t imm = opcode & 0x7f;
1892 uint8_t opc = opcode & (1 << 7);
1893 char *mnemonic;
1894
1895
1896 if (opc)
1897 {
1898 instruction->type = ARM_SUB;
1899 mnemonic = "SUB";
1900 }
1901 else
1902 {
1903 instruction->type = ARM_ADD;
1904 mnemonic = "ADD";
1905 }
1906
1907 snprintf(instruction->text, 128,
1908 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tSP, #%#" PRIx32,
1909 address, opcode, mnemonic, imm*4);
1910
1911 instruction->info.data_proc.variant = 0 /* immediate */;
1912 instruction->info.data_proc.Rd = 13 /*SP*/;
1913 instruction->info.data_proc.Rn = 13 /*SP*/;
1914 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
1915
1916 return ERROR_OK;
1917 }
1918
1919 int evaluate_breakpoint_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1920 {
1921 uint32_t imm = opcode & 0xff;
1922
1923 instruction->type = ARM_BKPT;
1924
1925 snprintf(instruction->text, 128,
1926 "0x%8.8" PRIx32 " 0x%4.4x \tBKPT\t%#2.2" PRIx32 "",
1927 address, opcode, imm);
1928
1929 return ERROR_OK;
1930 }
1931
1932 int evaluate_load_store_multiple_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1933 {
1934 uint32_t reg_list = opcode & 0xff;
1935 uint32_t L = opcode & (1 << 11);
1936 uint32_t R = opcode & (1 << 8);
1937 uint8_t Rn = (opcode >> 8) & 7;
1938 uint8_t addr_mode = 0 /* IA */;
1939 char reg_names[40];
1940 char *reg_names_p;
1941 char *mnemonic;
1942 char ptr_name[7] = "";
1943 int i;
1944
1945 if ((opcode & 0xf000) == 0xc000)
1946 { /* generic load/store multiple */
1947 if (L)
1948 {
1949 instruction->type = ARM_LDM;
1950 mnemonic = "LDM";
1951 }
1952 else
1953 {
1954 instruction->type = ARM_STM;
1955 mnemonic = "STM";
1956 }
1957 snprintf(ptr_name,7,"r%i!, ",Rn);
1958 }
1959 else
1960 { /* push/pop */
1961 Rn = 13; /* SP */
1962 if (L)
1963 {
1964 instruction->type = ARM_LDM;
1965 mnemonic = "POP";
1966 if (R)
1967 reg_list |= (1 << 15) /*PC*/;
1968 }
1969 else
1970 {
1971 instruction->type = ARM_STM;
1972 mnemonic = "PUSH";
1973 addr_mode = 3; /*DB*/
1974 if (R)
1975 reg_list |= (1 << 14) /*LR*/;
1976 }
1977 }
1978
1979 reg_names_p = reg_names;
1980 for (i = 0; i <= 15; i++)
1981 {
1982 if (reg_list & (1 << i))
1983 reg_names_p += snprintf(reg_names_p, (reg_names + 40 - reg_names_p), "r%i, ", i);
1984 }
1985 if (reg_names_p > reg_names)
1986 reg_names_p[-2] = '\0';
1987 else /* invalid op : no registers */
1988 reg_names[0] = '\0';
1989
1990 snprintf(instruction->text, 128,
1991 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%s{%s}",
1992 address, opcode, mnemonic, ptr_name, reg_names);
1993
1994 instruction->info.load_store_multiple.register_list = reg_list;
1995 instruction->info.load_store_multiple.Rn = Rn;
1996 instruction->info.load_store_multiple.addressing_mode = addr_mode;
1997
1998 return ERROR_OK;
1999 }
2000
2001 int evaluate_cond_branch_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
2002 {
2003 uint32_t offset = opcode & 0xff;
2004 uint8_t cond = (opcode >> 8) & 0xf;
2005 uint32_t target_address;
2006
2007 if (cond == 0xf)
2008 {
2009 instruction->type = ARM_SWI;
2010 snprintf(instruction->text, 128,
2011 "0x%8.8" PRIx32 " 0x%4.4x \tSVC\t%#2.2" PRIx32,
2012 address, opcode, offset);
2013 return ERROR_OK;
2014 }
2015 else if (cond == 0xe)
2016 {
2017 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2018 snprintf(instruction->text, 128,
2019 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2020 address, opcode);
2021 return ERROR_OK;
2022 }
2023
2024 /* sign extend 8-bit offset */
2025 if (offset & 0x00000080)
2026 offset = 0xffffff00 | offset;
2027
2028 target_address = address + 4 + (offset << 1);
2029
2030 snprintf(instruction->text, 128,
2031 "0x%8.8" PRIx32 " 0x%4.4x \tB%s\t%#8.8" PRIx32,
2032 address, opcode,
2033 arm_condition_strings[cond], target_address);
2034
2035 instruction->type = ARM_B;
2036 instruction->info.b_bl_bx_blx.reg_operand = -1;
2037 instruction->info.b_bl_bx_blx.target_address = target_address;
2038
2039 return ERROR_OK;
2040 }
2041
2042 static int evaluate_cb_thumb(uint16_t opcode, uint32_t address,
2043 arm_instruction_t *instruction)
2044 {
2045 unsigned offset;
2046
2047 /* added in Thumb2 */
2048 offset = (opcode >> 3) & 0x1f;
2049 offset |= (opcode & 0x0200) >> 4;
2050
2051 snprintf(instruction->text, 128,
2052 "0x%8.8" PRIx32 " 0x%4.4x \tCB%sZ\tr%d, %#8.8" PRIx32,
2053 address, opcode,
2054 (opcode & 0x0800) ? "N" : "",
2055 opcode & 0x7, address + 4 + (offset << 1));
2056
2057 return ERROR_OK;
2058 }
2059
2060 static int evaluate_extend_thumb(uint16_t opcode, uint32_t address,
2061 arm_instruction_t *instruction)
2062 {
2063 /* added in ARMv6 */
2064 snprintf(instruction->text, 128,
2065 "0x%8.8" PRIx32 " 0x%4.4x \t%cXT%c\tr%d, r%d",
2066 address, opcode,
2067 (opcode & 0x0080) ? 'U' : 'S',
2068 (opcode & 0x0040) ? 'B' : 'H',
2069 opcode & 0x7, (opcode >> 3) & 0x7);
2070
2071 return ERROR_OK;
2072 }
2073
2074 static int evaluate_cps_thumb(uint16_t opcode, uint32_t address,
2075 arm_instruction_t *instruction)
2076 {
2077 /* added in ARMv6 */
2078 if ((opcode & 0x0ff0) == 0x0650)
2079 snprintf(instruction->text, 128,
2080 "0x%8.8" PRIx32 " 0x%4.4x \tSETEND %s",
2081 address, opcode,
2082 (opcode & 0x80) ? "BE" : "LE");
2083 else /* ASSUME (opcode & 0x0fe0) == 0x0660 */
2084 snprintf(instruction->text, 128,
2085 "0x%8.8" PRIx32 " 0x%4.4x \tCPSI%c\t%s%s%s",
2086 address, opcode,
2087 (opcode & 0x0010) ? 'D' : 'E',
2088 (opcode & 0x0004) ? "A" : "",
2089 (opcode & 0x0002) ? "I" : "",
2090 (opcode & 0x0001) ? "F" : "");
2091
2092 return ERROR_OK;
2093 }
2094
2095 static int evaluate_byterev_thumb(uint16_t opcode, uint32_t address,
2096 arm_instruction_t *instruction)
2097 {
2098 char *suffix;
2099
2100 /* added in ARMv6 */
2101 switch (opcode & 0x00c0) {
2102 case 0:
2103 suffix = "";
2104 break;
2105 case 1:
2106 suffix = "16";
2107 break;
2108 default:
2109 suffix = "SH";
2110 break;
2111 }
2112 snprintf(instruction->text, 128,
2113 "0x%8.8" PRIx32 " 0x%4.4x \tREV%s\tr%d, r%d",
2114 address, opcode, suffix,
2115 opcode & 0x7, (opcode >> 3) & 0x7);
2116
2117 return ERROR_OK;
2118 }
2119
2120 static int evaluate_hint_thumb(uint16_t opcode, uint32_t address,
2121 arm_instruction_t *instruction)
2122 {
2123 char *hint;
2124
2125 switch ((opcode >> 4) & 0x0f) {
2126 case 0:
2127 hint = "NOP";
2128 break;
2129 case 1:
2130 hint = "YIELD";
2131 break;
2132 case 2:
2133 hint = "WFE";
2134 break;
2135 case 3:
2136 hint = "WFI";
2137 break;
2138 case 4:
2139 hint = "SEV";
2140 break;
2141 default:
2142 hint = "HINT (UNRECOGNIZED)";
2143 break;
2144 }
2145
2146 snprintf(instruction->text, 128,
2147 "0x%8.8" PRIx32 " 0x%4.4x \t%s",
2148 address, opcode, hint);
2149
2150 return ERROR_OK;
2151 }
2152
2153 static int evaluate_ifthen_thumb(uint16_t opcode, uint32_t address,
2154 arm_instruction_t *instruction)
2155 {
2156 unsigned cond = (opcode >> 4) & 0x0f;
2157 char *x = "", *y = "", *z = "";
2158
2159 if (opcode & 0x01)
2160 z = (opcode & 0x02) ? "T" : "E";
2161 if (opcode & 0x03)
2162 y = (opcode & 0x04) ? "T" : "E";
2163 if (opcode & 0x07)
2164 x = (opcode & 0x08) ? "T" : "E";
2165
2166 snprintf(instruction->text, 128,
2167 "0x%8.8" PRIx32 " 0x%4.4x \tIT%s%s%s\t%s",
2168 address, opcode,
2169 x, y, z, arm_condition_strings[cond]);
2170
2171 /* NOTE: strictly speaking, the next 1-4 instructions should
2172 * now be displayed with the relevant conditional suffix...
2173 */
2174
2175 return ERROR_OK;
2176 }
2177
2178 int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
2179 {
2180 /* clear fields, to avoid confusion */
2181 memset(instruction, 0, sizeof(arm_instruction_t));
2182 instruction->opcode = opcode;
2183 instruction->instruction_size = 2;
2184
2185 if ((opcode & 0xe000) == 0x0000)
2186 {
2187 /* add/substract register or immediate */
2188 if ((opcode & 0x1800) == 0x1800)
2189 return evaluate_add_sub_thumb(opcode, address, instruction);
2190 /* shift by immediate */
2191 else
2192 return evaluate_shift_imm_thumb(opcode, address, instruction);
2193 }
2194
2195 /* Add/substract/compare/move immediate */
2196 if ((opcode & 0xe000) == 0x2000)
2197 {
2198 return evaluate_data_proc_imm_thumb(opcode, address, instruction);
2199 }
2200
2201 /* Data processing instructions */
2202 if ((opcode & 0xf800) == 0x4000)
2203 {
2204 return evaluate_data_proc_thumb(opcode, address, instruction);
2205 }
2206
2207 /* Load from literal pool */
2208 if ((opcode & 0xf800) == 0x4800)
2209 {
2210 return evaluate_load_literal_thumb(opcode, address, instruction);
2211 }
2212
2213 /* Load/Store register offset */
2214 if ((opcode & 0xf000) == 0x5000)
2215 {
2216 return evaluate_load_store_reg_thumb(opcode, address, instruction);
2217 }
2218
2219 /* Load/Store immediate offset */
2220 if (((opcode & 0xe000) == 0x6000)
2221 ||((opcode & 0xf000) == 0x8000))
2222 {
2223 return evaluate_load_store_imm_thumb(opcode, address, instruction);
2224 }
2225
2226 /* Load/Store from/to stack */
2227 if ((opcode & 0xf000) == 0x9000)
2228 {
2229 return evaluate_load_store_stack_thumb(opcode, address, instruction);
2230 }
2231
2232 /* Add to SP/PC */
2233 if ((opcode & 0xf000) == 0xa000)
2234 {
2235 return evaluate_add_sp_pc_thumb(opcode, address, instruction);
2236 }
2237
2238 /* Misc */
2239 if ((opcode & 0xf000) == 0xb000)
2240 {
2241 switch ((opcode >> 8) & 0x0f) {
2242 case 0x0:
2243 return evaluate_adjust_stack_thumb(opcode, address, instruction);
2244 case 0x1:
2245 case 0x3:
2246 case 0x9:
2247 case 0xb:
2248 return evaluate_cb_thumb(opcode, address, instruction);
2249 case 0x2:
2250 return evaluate_extend_thumb(opcode, address, instruction);
2251 case 0x4:
2252 case 0x5:
2253 case 0xc:
2254 case 0xd:
2255 return evaluate_load_store_multiple_thumb(opcode, address,
2256 instruction);
2257 case 0x6:
2258 return evaluate_cps_thumb(opcode, address, instruction);
2259 case 0xa:
2260 if ((opcode & 0x00c0) == 0x0080)
2261 break;
2262 return evaluate_byterev_thumb(opcode, address, instruction);
2263 case 0xe:
2264 return evaluate_breakpoint_thumb(opcode, address, instruction);
2265 case 0xf:
2266 if (opcode & 0x000f)
2267 return evaluate_ifthen_thumb(opcode, address,
2268 instruction);
2269 else
2270 return evaluate_hint_thumb(opcode, address,
2271 instruction);
2272 }
2273
2274 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2275 snprintf(instruction->text, 128,
2276 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2277 address, opcode);
2278 return ERROR_OK;
2279 }
2280
2281 /* Load/Store multiple */
2282 if ((opcode & 0xf000) == 0xc000)
2283 {
2284 return evaluate_load_store_multiple_thumb(opcode, address, instruction);
2285 }
2286
2287 /* Conditional branch + SWI */
2288 if ((opcode & 0xf000) == 0xd000)
2289 {
2290 return evaluate_cond_branch_thumb(opcode, address, instruction);
2291 }
2292
2293 if ((opcode & 0xe000) == 0xe000)
2294 {
2295 /* Undefined instructions */
2296 if ((opcode & 0xf801) == 0xe801)
2297 {
2298 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2299 snprintf(instruction->text, 128,
2300 "0x%8.8" PRIx32 " 0x%8.8x\t"
2301 "UNDEFINED INSTRUCTION",
2302 address, opcode);
2303 return ERROR_OK;
2304 }
2305 else
2306 { /* Branch to offset */
2307 return evaluate_b_bl_blx_thumb(opcode, address, instruction);
2308 }
2309 }
2310
2311 LOG_ERROR("should never reach this point (opcode=%04x)",opcode);
2312 return -1;
2313 }
2314
2315 static int t2ev_b_bl(uint32_t opcode, uint32_t address,
2316 arm_instruction_t *instruction, char *cp)
2317 {
2318 unsigned offset;
2319 unsigned b21 = 1 << 21;
2320 unsigned b22 = 1 << 22;
2321
2322 /* instead of combining two smaller 16-bit branch instructions,
2323 * Thumb2 uses only one larger 32-bit instruction.
2324 */
2325 offset = opcode & 0x7ff;
2326 offset |= (opcode & 0x03ff0000) >> 5;
2327 if (opcode & (1 << 26)) {
2328 offset |= 0xff << 23;
2329 if ((opcode & (1 << 11)) == 0)
2330 b21 = 0;
2331 if ((opcode & (1 << 13)) == 0)
2332 b22 = 0;
2333 } else {
2334 if (opcode & (1 << 11))
2335 b21 = 0;
2336 if (opcode & (1 << 13))
2337 b22 = 0;
2338 }
2339 offset |= b21;
2340 offset |= b22;
2341
2342
2343 address += 4;
2344 address += offset << 1;
2345
2346 instruction->type = (opcode & (1 << 14)) ? ARM_BL : ARM_B;
2347 instruction->info.b_bl_bx_blx.reg_operand = -1;
2348 instruction->info.b_bl_bx_blx.target_address = address;
2349 sprintf(cp, "%s\t%#8.8" PRIx32,
2350 (opcode & (1 << 14)) ? "BL" : "B.W",
2351 address);
2352
2353 return ERROR_OK;
2354 }
2355
2356 static int t2ev_cond_b(uint32_t opcode, uint32_t address,
2357 arm_instruction_t *instruction, char *cp)
2358 {
2359 unsigned offset;
2360 unsigned b17 = 1 << 17;
2361 unsigned b18 = 1 << 18;
2362 unsigned cond = (opcode >> 22) & 0x0f;
2363
2364 offset = opcode & 0x7ff;
2365 offset |= (opcode & 0x003f0000) >> 5;
2366 if (opcode & (1 << 26)) {
2367 offset |= 0xffff << 19;
2368 if ((opcode & (1 << 11)) == 0)
2369 b17 = 0;
2370 if ((opcode & (1 << 13)) == 0)
2371 b18 = 0;
2372 } else {
2373 if (opcode & (1 << 11))
2374 b17 = 0;
2375 if (opcode & (1 << 13))
2376 b18 = 0;
2377 }
2378 offset |= b17;
2379 offset |= b18;
2380
2381 address += 4;
2382 address += offset << 1;
2383
2384 instruction->type = ARM_B;
2385 instruction->info.b_bl_bx_blx.reg_operand = -1;
2386 instruction->info.b_bl_bx_blx.target_address = address;
2387 sprintf(cp, "B%s.W\t%#8.8" PRIx32,
2388 arm_condition_strings[cond],
2389 address);
2390
2391 return ERROR_OK;
2392 }
2393
2394 static const char *special_name(int number)
2395 {
2396 char *special = "(RESERVED)";
2397
2398 switch (number) {
2399 case 0:
2400 special = "apsr";
2401 break;
2402 case 1:
2403 special = "iapsr";
2404 break;
2405 case 2:
2406 special = "eapsr";
2407 break;
2408 case 3:
2409 special = "xpsr";
2410 break;
2411 case 5:
2412 special = "ipsr";
2413 break;
2414 case 6:
2415 special = "epsr";
2416 break;
2417 case 7:
2418 special = "iepsr";
2419 break;
2420 case 8:
2421 special = "msp";
2422 break;
2423 case 9:
2424 special = "psp";
2425 break;
2426 case 16:
2427 special = "primask";
2428 break;
2429 case 17:
2430 special = "basepri";
2431 break;
2432 case 18:
2433 special = "basepri_max";
2434 break;
2435 case 19:
2436 special = "faultmask";
2437 break;
2438 case 20:
2439 special = "control";
2440 break;
2441 }
2442 return special;
2443 }
2444
2445 static int t2ev_hint(uint32_t opcode, uint32_t address,
2446 arm_instruction_t *instruction, char *cp)
2447 {
2448 const char *mnemonic;
2449
2450 if (opcode & 0x0700) {
2451 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2452 strcpy(cp, "UNDEFINED");
2453 return ERROR_OK;
2454 }
2455
2456 if (opcode & 0x00f0) {
2457 sprintf(cp, "DBG\t#%d", (int) opcode & 0xf);
2458 return ERROR_OK;
2459 }
2460
2461 switch (opcode & 0x0f) {
2462 case 0:
2463 mnemonic = "NOP.W";
2464 break;
2465 case 1:
2466 mnemonic = "YIELD.W";
2467 break;
2468 case 2:
2469 mnemonic = "WFE.W";
2470 break;
2471 case 3:
2472 mnemonic = "WFI.W";
2473 break;
2474 case 4:
2475 mnemonic = "SEV.W";
2476 break;
2477 default:
2478 mnemonic = "HINT.W (UNRECOGNIZED)";
2479 break;
2480 }
2481 strcpy(cp, mnemonic);
2482 return ERROR_OK;
2483 }
2484
2485 static int t2ev_misc(uint32_t opcode, uint32_t address,
2486 arm_instruction_t *instruction, char *cp)
2487 {
2488 const char *mnemonic;
2489
2490 switch ((opcode >> 4) & 0x0f) {
2491 case 2:
2492 mnemonic = "CLREX";
2493 break;
2494 case 4:
2495 mnemonic = "DSB";
2496 break;
2497 case 5:
2498 mnemonic = "DMB";
2499 break;
2500 case 6:
2501 mnemonic = "ISB";
2502 break;
2503 default:
2504 return ERROR_INVALID_ARGUMENTS;
2505 }
2506 strcpy(cp, mnemonic);
2507 return ERROR_OK;
2508 }
2509
2510 static int t2ev_b_misc(uint32_t opcode, uint32_t address,
2511 arm_instruction_t *instruction, char *cp)
2512 {
2513 /* permanently undefined */
2514 if ((opcode & 0x07f07000) == 0x07f02000) {
2515 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2516 strcpy(cp, "UNDEFINED");
2517 return ERROR_OK;
2518 }
2519
2520 switch ((opcode >> 12) & 0x5) {
2521 case 0x1:
2522 case 0x5:
2523 return t2ev_b_bl(opcode, address, instruction, cp);
2524 case 0x4:
2525 goto undef;
2526 case 0:
2527 if (((opcode >> 23) & 0x07) != 0x07)
2528 return t2ev_cond_b(opcode, address, instruction, cp);
2529 if (opcode & (1 << 26))
2530 goto undef;
2531 break;
2532 }
2533
2534 switch ((opcode >> 20) & 0x7f) {
2535 case 0x38:
2536 case 0x39:
2537 sprintf(cp, "MSR\t%s, r%d", special_name(opcode & 0xff),
2538 (int) (opcode >> 16) & 0x0f);
2539 return ERROR_OK;
2540 case 0x3a:
2541 return t2ev_hint(opcode, address, instruction, cp);
2542 case 0x3b:
2543 return t2ev_misc(opcode, address, instruction, cp);
2544 case 0x3e:
2545 case 0x3f:
2546 sprintf(cp, "MRS\tr%d, %s", (int) (opcode >> 8) & 0x0f,
2547 special_name(opcode & 0xff));
2548 return ERROR_OK;
2549 }
2550
2551 undef:
2552 return ERROR_INVALID_ARGUMENTS;
2553 }
2554
2555 static int t2ev_data_mod_immed(uint32_t opcode, uint32_t address,
2556 arm_instruction_t *instruction, char *cp)
2557 {
2558 char *mnemonic = NULL;
2559 int rn = (opcode >> 16) & 0xf;
2560 int rd = (opcode >> 8) & 0xf;
2561 unsigned immed = opcode & 0xff;
2562 unsigned func;
2563 bool one = false;
2564 char *suffix = "";
2565 char *suffix2 = "";
2566
2567 /* ARMv7-M: A5.3.2 Modified immediate constants */
2568 func = (opcode >> 11) & 0x0e;
2569 if (immed & 0x80)
2570 func |= 1;
2571 if (opcode & (1 << 26))
2572 func |= 0x10;
2573
2574 /* "Modified" immediates */
2575 switch (func >> 1) {
2576 case 0:
2577 break;
2578 case 2:
2579 immed <<= 8;
2580 /* FALLTHROUGH */
2581 case 1:
2582 immed += immed << 16;
2583 break;
2584 case 3:
2585 immed += immed << 8;
2586 immed += immed << 16;
2587 break;
2588 default:
2589 immed |= 0x80;
2590 immed = ror(immed, func);
2591 }
2592
2593 if (opcode & (1 << 20))
2594 suffix = "S";
2595
2596 switch ((opcode >> 21) & 0xf) {
2597 case 0:
2598 if (rd == 0xf) {
2599 instruction->type = ARM_TST;
2600 mnemonic = "TST";
2601 one = true;
2602 suffix = "";
2603 suffix2 = ".W";
2604 rd = rn;
2605 } else {
2606 instruction->type = ARM_AND;
2607 mnemonic = "AND";
2608 }
2609 break;
2610 case 1:
2611 instruction->type = ARM_BIC;
2612 mnemonic = "BIC";
2613 break;
2614 case 2:
2615 if (rn == 0xf) {
2616 instruction->type = ARM_MOV;
2617 mnemonic = "MOV";
2618 one = true;
2619 suffix2 = ".W";
2620 } else {
2621 instruction->type = ARM_ORR;
2622 mnemonic = "ORR";
2623 }
2624 break;
2625 case 3:
2626 if (rn == 0xf) {
2627 instruction->type = ARM_MVN;
2628 mnemonic = "MVN";
2629 one = true;
2630 } else {
2631 // instruction->type = ARM_ORN;
2632 mnemonic = "ORN";
2633 }
2634 break;
2635 case 4:
2636 if (rd == 0xf) {
2637 instruction->type = ARM_TEQ;
2638 mnemonic = "TEQ";
2639 one = true;
2640 suffix = "";
2641 rd = rn;
2642 } else {
2643 instruction->type = ARM_EOR;
2644 mnemonic = "EOR";
2645 }
2646 break;
2647 case 8:
2648 if (rd == 0xf) {
2649 instruction->type = ARM_CMN;
2650 mnemonic = "CMN";
2651 one = true;
2652 suffix = "";
2653 rd = rn;
2654 } else {
2655 instruction->type = ARM_ADD;
2656 mnemonic = "ADD";
2657 suffix2 = ".W";
2658 }
2659 break;
2660 case 10:
2661 instruction->type = ARM_ADC;
2662 mnemonic = "ADC";
2663 break;
2664 case 11:
2665 instruction->type = ARM_SBC;
2666 mnemonic = "SBC";
2667 break;
2668 case 13:
2669 if (rd == 0xf) {
2670 instruction->type = ARM_CMP;
2671 mnemonic = "CMP";
2672 one = true;
2673 suffix = "";
2674 rd = rn;
2675 } else {
2676 instruction->type = ARM_SUB;
2677 mnemonic = "SUB";
2678 }
2679 suffix2 = ".W";
2680 break;
2681 case 14:
2682 instruction->type = ARM_RSB;
2683 mnemonic = "RSB";
2684 suffix2 = ".W";
2685 break;
2686 default:
2687 return ERROR_INVALID_ARGUMENTS;
2688 }
2689
2690 if (one)
2691 sprintf(cp, "%s%s\tr%d, #%d\t; %#8.8x",
2692 mnemonic, suffix2 ,rd, immed, immed);
2693 else
2694 sprintf(cp, "%s%s%s\tr%d, r%d, #%d\t; %#8.8x",
2695 mnemonic, suffix, suffix2,
2696 rd, rn, immed, immed);
2697
2698 return ERROR_OK;
2699 }
2700
2701 static int t2ev_data_immed(uint32_t opcode, uint32_t address,
2702 arm_instruction_t *instruction, char *cp)
2703 {
2704 char *mnemonic = NULL;
2705 int rn = (opcode >> 16) & 0xf;
2706 int rd = (opcode >> 8) & 0xf;
2707 unsigned immed;
2708 bool add = false;
2709 bool is_signed = false;
2710
2711 immed = (opcode & 0x0ff) | ((opcode & 0x7000) >> 12);
2712 if (opcode & (1 << 27))
2713 immed |= (1 << 11);
2714
2715 switch ((opcode >> 20) & 0x1f) {
2716 case 0:
2717 if (rn == 0xf) {
2718 add = true;
2719 goto do_adr;
2720 }
2721 mnemonic = "ADD.W";
2722 break;
2723 case 4:
2724 mnemonic = "MOV.W";
2725 break;
2726 case 0x0a:
2727 if (rn == 0xf)
2728 goto do_adr;
2729 mnemonic = "SUB.W";
2730 break;
2731 case 0x0c:
2732 /* move constant to top 16 bits of register */
2733 immed |= (opcode >> 4) & 0xf000;
2734 sprintf(cp, "MOVT\tr%d, #%d\t; %#4.4x", rn, immed, immed);
2735 return ERROR_OK;
2736 case 0x10:
2737 case 0x12:
2738 is_signed = true;
2739 case 0x18:
2740 case 0x1a:
2741 /* signed/unsigned saturated add */
2742 immed = (opcode >> 6) & 0x03;
2743 immed |= (opcode >> 10) & 0x1c;
2744 sprintf(cp, "%sSAT\tr%d, #%d, r%d, %s #%d\t",
2745 is_signed ? "S" : "U",
2746 rd, (int) (opcode & 0x1f) + 1, rn,
2747 (opcode & (1 << 21)) ? "ASR" : "LSL",
2748 immed ? immed : 32);
2749 return ERROR_OK;
2750 case 0x14:
2751 is_signed = true;
2752 /* FALLTHROUGH */
2753 case 0x1c:
2754 /* signed/unsigned bitfield extract */
2755 immed = (opcode >> 6) & 0x03;
2756 immed |= (opcode >> 10) & 0x1c;
2757 sprintf(cp, "%sBFX\tr%d, r%d, #%d, #%d\t",
2758 is_signed ? "S" : "U",
2759 rd, rn, immed,
2760 (int) (opcode & 0x1f) + 1);
2761 return ERROR_OK;
2762 case 0x16:
2763 immed = (opcode >> 6) & 0x03;
2764 immed |= (opcode >> 10) & 0x1c;
2765 if (rn == 0xf) /* bitfield clear */
2766 sprintf(cp, "BFC\tr%d, #%d, #%d\t",
2767 rd, immed,
2768 (int) (opcode & 0x1f) + 1 - immed);
2769 else /* bitfield insert */
2770 sprintf(cp, "BFI\tr%d, r%d, #%d, #%d\t",
2771 rd, rn, immed,
2772 (int) (opcode & 0x1f) + 1 - immed);
2773 return ERROR_OK;
2774 default:
2775 return ERROR_INVALID_ARGUMENTS;
2776 }
2777
2778 sprintf(cp, "%s\tr%d, r%d, #%d\t; %#3.3x", mnemonic,
2779 rd, rn, immed, immed);
2780 return ERROR_OK;
2781
2782 do_adr:
2783 address = thumb_alignpc4(address);
2784 if (add)
2785 address += immed;
2786 else
2787 address -= immed;
2788 /* REVISIT "ADD/SUB Rd, PC, #const ; 0x..." might be better;
2789 * not hiding the pc-relative stuff will sometimes be useful.
2790 */
2791 sprintf(cp, "ADR.W\tr%d, %#8.8" PRIx32, rd, address);
2792 return ERROR_OK;
2793 }
2794
2795 static int t2ev_store_single(uint32_t opcode, uint32_t address,
2796 arm_instruction_t *instruction, char *cp)
2797 {
2798 unsigned op = (opcode >> 20) & 0xf;
2799 char *size = "";
2800 char *suffix = "";
2801 char *p1 = "";
2802 char *p2 = "]";
2803 unsigned immed;
2804 unsigned rn = (opcode >> 16) & 0x0f;
2805 unsigned rt = (opcode >> 12) & 0x0f;
2806
2807 if (rn == 0xf)
2808 return ERROR_INVALID_ARGUMENTS;
2809
2810 if (opcode & 0x0800)
2811 op |= 1;
2812 switch (op) {
2813 /* byte */
2814 case 0x8:
2815 case 0x9:
2816 size = "B";
2817 goto imm12;
2818 case 0x1:
2819 size = "B";
2820 goto imm8;
2821 case 0x0:
2822 size = "B";
2823 break;
2824 /* halfword */
2825 case 0xa:
2826 case 0xb:
2827 size = "H";
2828 goto imm12;
2829 case 0x3:
2830 size = "H";
2831 goto imm8;
2832 case 0x2:
2833 size = "H";
2834 break;
2835 /* word */
2836 case 0xc:
2837 case 0xd:
2838 goto imm12;
2839 case 0x5:
2840 goto imm8;
2841 case 0x4:
2842 break;
2843 /* error */
2844 default:
2845 return ERROR_INVALID_ARGUMENTS;
2846 }
2847
2848 sprintf(cp, "STR%s.W\tr%d, [r%d, r%d, LSL #%d]",
2849 size, rt, rn, (int) opcode & 0x0f,
2850 (int) (opcode >> 4) & 0x03);
2851
2852 imm12:
2853 immed = opcode & 0x0fff;
2854 sprintf(cp, "STR%s.W\tr%d, [r%d, #%u]\t; %#3.3x",
2855 size, rt, rn, immed, immed);
2856 return ERROR_OK;
2857
2858 imm8:
2859 immed = opcode & 0x00ff;
2860
2861 switch (opcode & 0x700) {
2862 case 0x600:
2863 suffix = "T";
2864 break;
2865 case 0x000:
2866 case 0x200:
2867 return ERROR_INVALID_ARGUMENTS;
2868 }
2869
2870 /* two indexed modes will write back rn */
2871 if (opcode & 0x100) {
2872 if (opcode & 0x400) /* pre-indexed */
2873 p2 = "]!";
2874 else { /* post-indexed */
2875 p1 = "]";
2876 p2 = "";
2877 }
2878 }
2879
2880 sprintf(cp, "STR%s%s\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
2881 size, suffix, rt, rn, p1,
2882 (opcode & 0x200) ? "" : "-",
2883 immed, p2, immed);
2884 return ERROR_OK;
2885 }
2886
2887 static int t2ev_mul32(uint32_t opcode, uint32_t address,
2888 arm_instruction_t *instruction, char *cp)
2889 {
2890 int ra = (opcode >> 12) & 0xf;
2891
2892 switch (opcode & 0x007000f0) {
2893 case 0:
2894 if (ra == 0xf)
2895 sprintf(cp, "MUL\tr%d, r%d, r%d",
2896 (int) (opcode >> 8) & 0xf,
2897 (int) (opcode >> 16) & 0xf,
2898 (int) (opcode >> 0) & 0xf);
2899 else
2900 sprintf(cp, "MLA\tr%d, r%d, r%d, r%d",
2901 (int) (opcode >> 8) & 0xf,
2902 (int) (opcode >> 16) & 0xf,
2903 (int) (opcode >> 0) & 0xf, ra);
2904 break;
2905 case 0x10:
2906 sprintf(cp, "MLS\tr%d, r%d, r%d, r%d",
2907 (int) (opcode >> 8) & 0xf,
2908 (int) (opcode >> 16) & 0xf,
2909 (int) (opcode >> 0) & 0xf, ra);
2910 break;
2911 default:
2912 return ERROR_INVALID_ARGUMENTS;
2913 }
2914 return ERROR_OK;
2915 }
2916
2917 static int t2ev_mul64_div(uint32_t opcode, uint32_t address,
2918 arm_instruction_t *instruction, char *cp)
2919 {
2920 int op = (opcode >> 4) & 0xf;
2921 char *infix = "MUL";
2922
2923 op += (opcode >> 16) & 0x70;
2924 switch (op) {
2925 case 0x40:
2926 case 0x60:
2927 infix = "MLA";
2928 /* FALLTHROUGH */
2929 case 0:
2930 case 0x20:
2931 sprintf(cp, "%c%sL\tr%d, r%d, r%d, r%d",
2932 (op & 0x20) ? 'U' : 'S',
2933 infix,
2934 (int) (opcode >> 12) & 0xf,
2935 (int) (opcode >> 8) & 0xf,
2936 (int) (opcode >> 16) & 0xf,
2937 (int) (opcode >> 0) & 0xf);
2938 break;
2939 case 0x1f:
2940 case 0x3f:
2941 sprintf(cp, "%cDIV\tr%d, r%d, r%d",
2942 (op & 0x20) ? 'U' : 'S',
2943 (int) (opcode >> 8) & 0xf,
2944 (int) (opcode >> 16) & 0xf,
2945 (int) (opcode >> 0) & 0xf);
2946 break;
2947 default:
2948 return ERROR_INVALID_ARGUMENTS;
2949 }
2950
2951 return ERROR_OK;
2952 }
2953
2954 static int t2ev_ldm_stm(uint32_t opcode, uint32_t address,
2955 arm_instruction_t *instruction, char *cp)
2956 {
2957 int rn = (opcode >> 16) & 0xf;
2958 int op = (opcode >> 22) & 0x6;
2959 int t = (opcode >> 21) & 1;
2960 unsigned registers = opcode & 0xffff;
2961
2962 if (opcode & (1 << 20))
2963 op |= 1;
2964
2965 switch (op) {
2966 case 2:
2967 sprintf(cp, "STMB\tr%d%s, ", rn, t ? "!" : "");
2968 break;
2969 case 3:
2970 if (rn == 13 && t)
2971 sprintf(cp, "POP\t");
2972 else
2973 sprintf(cp, "LDM.W\tr%d%s, ", rn, t ? "!" : "");
2974 break;
2975 case 4:
2976 if (rn == 13 && t)
2977 sprintf(cp, "PUSH\t");
2978 else
2979 sprintf(cp, "STM.W\tr%d%s, ", rn, t ? "!" : "");
2980 break;
2981 case 5:
2982 sprintf(cp, "LDMB\tr%d%s, ", rn, t ? "!" : "");
2983 break;
2984 default:
2985 return ERROR_INVALID_ARGUMENTS;
2986 }
2987
2988 cp = strchr(cp, 0);
2989 *cp++ = '{';
2990 for (t = 0; registers; t++, registers >>= 1) {
2991 if ((registers & 1) == 0)
2992 continue;
2993 registers &= ~1;
2994 sprintf(cp, "r%d%s", t, registers ? ", " : "");
2995 cp = strchr(cp, 0);
2996 }
2997 *cp++ = '}';
2998 *cp++ = 0;
2999
3000 return ERROR_OK;
3001 }
3002
3003 static int t2ev_data_shift(uint32_t opcode, uint32_t address,
3004 arm_instruction_t *instruction, char *cp)
3005 {
3006 int op = (opcode >> 21) & 0xf;
3007 int rd = (opcode >> 8) & 0xf;
3008 int rn = (opcode >> 16) & 0xf;
3009 int type = (opcode >> 4) & 0x3;
3010 int immed = (opcode >> 6) & 0x3;
3011 char *mnemonic;
3012 char *suffix = "";
3013
3014 immed |= (opcode >> 10) & 0x7;
3015 if (opcode & (1 << 21))
3016 suffix = "S";
3017
3018 switch (op) {
3019 case 0:
3020 if (rd == 0xf) {
3021 if (!(opcode & (1 << 21)))
3022 return ERROR_INVALID_ARGUMENTS;
3023 instruction->type = ARM_TST;
3024 mnemonic = "TST";
3025 goto two;
3026 }
3027 instruction->type = ARM_AND;
3028 mnemonic = "AND";
3029 break;
3030 case 1:
3031 instruction->type = ARM_BIC;
3032 mnemonic = "BIC";
3033 break;
3034 case 2:
3035 if (rn == 0xf) {
3036 instruction->type = ARM_MOV;
3037 switch (type) {
3038 case 0:
3039 if (immed == 0) {
3040 sprintf(cp, "MOV%s.W\tr%d, r%d",
3041 suffix, rd,
3042 (int) (opcode & 0xf));
3043 return ERROR_OK;
3044 }
3045 mnemonic = "LSL";
3046 break;
3047 case 1:
3048 mnemonic = "LSR";
3049 break;
3050 case 2:
3051 mnemonic = "ASR";
3052 break;
3053 default:
3054 if (immed == 0) {
3055 sprintf(cp, "RRX%s.W\tr%d, r%d",
3056 suffix, rd,
3057 (int) (opcode & 0xf));
3058 return ERROR_OK;
3059 }
3060 mnemonic = "ROR";
3061 break;
3062 }
3063 goto immediate;
3064 } else {
3065 instruction->type = ARM_ORR;
3066 mnemonic = "ORR";
3067 }
3068 break;
3069 case 3:
3070 if (rn == 0xf) {
3071 instruction->type = ARM_MVN;
3072 mnemonic = "MVN";
3073 rn = rd;
3074 goto two;
3075 } else {
3076 // instruction->type = ARM_ORN;
3077 mnemonic = "ORN";
3078 }
3079 break;
3080 case 4:
3081 if (rd == 0xf) {
3082 if (!(opcode & (1 << 21)))
3083 return ERROR_INVALID_ARGUMENTS;
3084 instruction->type = ARM_TEQ;
3085 mnemonic = "TEQ";
3086 goto two;
3087 }
3088 instruction->type = ARM_EOR;
3089 mnemonic = "EOR";
3090 break;
3091 case 8:
3092 if (rd == 0xf) {
3093 if (!(opcode & (1 << 21)))
3094 return ERROR_INVALID_ARGUMENTS;
3095 instruction->type = ARM_CMN;
3096 mnemonic = "CMN";
3097 goto two;
3098 }
3099 instruction->type = ARM_ADD;
3100 mnemonic = "ADD";
3101 break;
3102 case 0xa:
3103 instruction->type = ARM_ADC;
3104 mnemonic = "ADC";
3105 break;
3106 case 0xb:
3107 instruction->type = ARM_SBC;
3108 mnemonic = "SBC";
3109 break;
3110 case 0xd:
3111 if (rd == 0xf) {
3112 if (!(opcode & (1 << 21)))
3113 return ERROR_INVALID_ARGUMENTS;
3114 instruction->type = ARM_CMP;
3115 mnemonic = "CMP";
3116 goto two;
3117 }
3118 instruction->type = ARM_SUB;
3119 mnemonic = "SUB";
3120 break;
3121 case 0xe:
3122 instruction->type = ARM_RSB;
3123 mnemonic = "RSB";
3124 break;
3125 default:
3126 return ERROR_INVALID_ARGUMENTS;
3127 }
3128
3129 sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
3130 mnemonic, suffix, rd, rn, (int) (opcode & 0xf));
3131
3132 shift:
3133 cp = strchr(cp, 0);
3134
3135 switch (type) {
3136 case 0:
3137 if (immed == 0)
3138 return ERROR_OK;
3139 suffix = "LSL";
3140 break;
3141 case 1:
3142 suffix = "LSR";
3143 break;
3144 case 2:
3145 suffix = "ASR";
3146 break;
3147 case 3:
3148 if (immed == 0) {
3149 strcpy(cp, "RRX");
3150 return ERROR_OK;
3151 }
3152 suffix = "ROR";
3153 break;
3154 }
3155 sprintf(cp, ", %s #%d", suffix, immed ? immed : 32);
3156 return ERROR_OK;
3157
3158 two:
3159 sprintf(cp, "%s%s.W\tr%d, r%d",
3160 mnemonic, suffix, rn, (int) (opcode & 0xf));
3161 goto shift;
3162
3163 immediate:
3164 sprintf(cp, "%s%s.W\tr%d, r%d, #%d",
3165 mnemonic, suffix, rd,
3166 (int) (opcode & 0xf), immed ? immed : 32);
3167 return ERROR_OK;
3168 }
3169
3170 static int t2ev_data_reg(uint32_t opcode, uint32_t address,
3171 arm_instruction_t *instruction, char *cp)
3172 {
3173 char *mnemonic;
3174 char * suffix = "";
3175
3176 if (((opcode >> 4) & 0xf) == 0) {
3177 switch ((opcode >> 21) & 0x7) {
3178 case 0:
3179 mnemonic = "LSL";
3180 break;
3181 case 1:
3182 mnemonic = "LSR";
3183 break;
3184 case 2:
3185 mnemonic = "ASR";
3186 break;
3187 case 3:
3188 mnemonic = "ROR";
3189 break;
3190 default:
3191 return ERROR_INVALID_ARGUMENTS;
3192 }
3193
3194 instruction->type = ARM_MOV;
3195 if (opcode & (1 << 20))
3196 suffix = "S";
3197 sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
3198 mnemonic, suffix,
3199 (int) (opcode >> 8) & 0xf,
3200 (int) (opcode >> 16) & 0xf,
3201 (int) (opcode >> 0) & 0xf);
3202
3203 } else if (opcode & (1 << 7)) {
3204 switch ((opcode >> 24) & 0xf) {
3205 case 0:
3206 case 1:
3207 case 4:
3208 case 5:
3209 switch ((opcode >> 4) & 0x3) {
3210 case 1:
3211 suffix = ", ROR #8";
3212 break;
3213 case 2:
3214 suffix = ", ROR #16";
3215 break;
3216 case 3:
3217 suffix = ", ROR #24";
3218 break;
3219 }
3220 sprintf(cp, "%cXT%c.W\tr%d, r%d%s",
3221 (opcode & (1 << 24)) ? 'U' : 'S',
3222 (opcode & (1 << 26)) ? 'B' : 'H',
3223 (int) (opcode >> 8) & 0xf,
3224 (int) (opcode >> 16) & 0xf,
3225 suffix);
3226 break;
3227 case 8:
3228 case 9:
3229 case 0xa:
3230 case 0xb:
3231 if (opcode & (1 << 6))
3232 return ERROR_INVALID_ARGUMENTS;
3233 if (~opcode & (0xff << 12))
3234 return ERROR_INVALID_ARGUMENTS;
3235 if (!(opcode & (1 << 20)))
3236 return ERROR_INVALID_ARGUMENTS;
3237
3238 switch (((opcode >> 19) & 0x04)
3239 | ((opcode >> 4) & 0x3)) {
3240 case 0:
3241 mnemonic = "REV.W";
3242 break;
3243 case 1:
3244 mnemonic = "REV16.W";
3245 break;
3246 case 2:
3247 mnemonic = "RBIT";
3248 break;
3249 case 3:
3250 mnemonic = "REVSH.W";
3251 break;
3252 case 4:
3253 mnemonic = "CLZ";
3254 break;
3255 default:
3256 return ERROR_INVALID_ARGUMENTS;
3257 }
3258 sprintf(cp, "%s\tr%d, r%d",
3259 mnemonic,
3260 (int) (opcode >> 8) & 0xf,
3261 (int) (opcode >> 0) & 0xf);
3262 break;
3263 default:
3264 return ERROR_INVALID_ARGUMENTS;
3265 }
3266 }
3267
3268 return ERROR_OK;
3269 }
3270
3271 static int t2ev_load_word(uint32_t opcode, uint32_t address,
3272 arm_instruction_t *instruction, char *cp)
3273 {
3274 int rn = (opcode >> 16) & 0xf;
3275 int immed;
3276
3277 instruction->type = ARM_LDR;
3278
3279 if (rn == 0xf) {
3280 immed = opcode & 0x0fff;
3281 if (opcode & (1 << 23))
3282 immed = -immed;
3283 sprintf(cp, "LDR\tr%d, %#8.8" PRIx32,
3284 (int) (opcode >> 12) & 0xf,
3285 thumb_alignpc4(address) + immed);
3286 return ERROR_OK;
3287 }
3288
3289 if (opcode & (1 << 23)) {
3290 immed = opcode & 0x0fff;
3291 sprintf(cp, "LDR.W\tr%d, [r%d, #%d]\t; %#3.3x",
3292 (int) (opcode >> 12) & 0xf,
3293 rn, immed, immed);
3294 return ERROR_OK;
3295 }
3296
3297 if (!(opcode & (0x3f << 6))) {
3298 sprintf(cp, "LDR.W\tr%d, [r%d, r%d, LSL #%d]",
3299 (int) (opcode >> 12) & 0xf,
3300 rn,
3301 (int) (opcode >> 0) & 0xf,
3302 (int) (opcode >> 4) & 0x3);
3303 return ERROR_OK;
3304 }
3305
3306
3307 if (((opcode >> 8) & 0xf) == 0xe) {
3308 immed = opcode & 0x00ff;
3309
3310 sprintf(cp, "LDRT\tr%d, [r%d, #%d]\t; %#2.2x",
3311 (int) (opcode >> 12) & 0xf,
3312 rn, immed, immed);
3313 return ERROR_OK;
3314 }
3315
3316 if (((opcode >> 8) & 0xf) == 0xc || (opcode & 0x0900) == 0x0900) {
3317 char *p1 = "]", *p2 = "";
3318
3319 if (!(opcode & 0x0600))
3320 return ERROR_INVALID_ARGUMENTS;
3321
3322 immed = opcode & 0x00ff;
3323
3324 /* two indexed modes will write back rn */
3325 if (opcode & 0x100) {
3326 if (opcode & 0x400) /* pre-indexed */
3327 p2 = "]!";
3328 else { /* post-indexed */
3329 p1 = "]";
3330 p2 = "";
3331 }
3332 }
3333
3334 sprintf(cp, "LDR\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
3335 (int) (opcode >> 12) & 0xf,
3336 rn, p1,
3337 (opcode & 0x200) ? "" : "-",
3338 immed, p2, immed);
3339 return ERROR_OK;
3340 }
3341
3342 return ERROR_INVALID_ARGUMENTS;
3343 }
3344
3345 static int t2ev_load_byte_hints(uint32_t opcode, uint32_t address,
3346 arm_instruction_t *instruction, char *cp)
3347 {
3348 int rn = (opcode >> 16) & 0xf;
3349 int rt = (opcode >> 12) & 0xf;
3350 int op2 = (opcode >> 6) & 0x3f;
3351 unsigned immed;
3352 char *p1 = "]", *p2 = "";
3353 char *mnemonic;
3354
3355 switch ((opcode >> 23) & 0x3) {
3356 case 0:
3357 if ((rn & rt) == 0xf) {
3358 preload_immediate_t2:
3359 immed = opcode & 0xfff;
3360 preload_immediate_t1:
3361 p1 = (opcode & (1 << 21)) ? "W" : "";
3362 sprintf(cp, "PLD%s\t[r%d, #%d]\t; %#6.6x",
3363 p1, rn, immed, immed);
3364 return ERROR_OK;
3365 }
3366 if (rn == 0x0f && rt != 0x0f) {
3367 ldrb_literal:
3368 immed = opcode & 0xfff;
3369 address = thumb_alignpc4(address);
3370 if (opcode & (1 << 23))
3371 address += immed;
3372 else
3373 address -= immed;
3374 sprintf(cp, "LDRB\tr%d, %#8.8" PRIx32,
3375 rt, address);
3376 return ERROR_OK;
3377 }
3378 if (rn == 0x0f)
3379 break;
3380 if ((op2 & 0x3c) == 0x38) {
3381 immed = opcode & 0xff;
3382 sprintf(cp, "LDRBT\tr%d, [r%d, #%d]\t; %#2.2x",
3383 rt, rn, immed, immed);
3384 return ERROR_OK;
3385 }
3386 if ((op2 & 0x3c) == 0x30) {
3387 if (rt == 0x0f) {
3388 immed = opcode & 0xff;
3389 goto preload_immediate_t1;
3390 }
3391 mnemonic = "LDRB";
3392 ldrxb_immediate_t3:
3393 immed = opcode & 0xff;
3394 if (opcode & 0x200)
3395 immed = -immed;
3396
3397 /* two indexed modes will write back rn */
3398 if (opcode & 0x100) {
3399 if (opcode & 0x400) /* pre-indexed */
3400 p2 = "]!";
3401 else { /* post-indexed */
3402 p1 = "]";
3403 p2 = "";
3404 }
3405 }
3406 ldrxb_immediate_t2:
3407 sprintf(cp, "%s\tr%d, [r%d%s, #%d%s\t; %#8.8x",
3408 mnemonic, rt, rn, p1,
3409 immed, p2, immed);
3410 return ERROR_OK;
3411 }
3412 if ((op2 & 0x24) == 0x24) {
3413 mnemonic = "LDRB";
3414 goto ldrxb_immediate_t3;
3415 }
3416 if (op2 == 0) {
3417 int rm = opcode & 0xf;
3418
3419 if (rt == 0x0f)
3420 sprintf(cp, "PLD\t");
3421 else
3422 sprintf(cp, "LDRB.W\tr%d, ", rt);
3423 immed = (opcode >> 4) & 0x3;
3424 cp = strchr(cp, 0);
3425 sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed);
3426 return ERROR_OK;
3427 }
3428 break;
3429 case 1:
3430 if (rt == 0xf)
3431 goto preload_immediate_t2;
3432 if (rn == 0x0f)
3433 goto ldrb_literal;
3434 mnemonic = "LDRB.W";
3435 immed = opcode & 0xfff;
3436 goto ldrxb_immediate_t2;
3437 case 2:
3438 if ((rn & rt) == 0xf) {
3439 pli_immediate:
3440 immed = opcode & 0xfff;
3441 address = thumb_alignpc4(address);
3442 if (opcode & (1 << 23))
3443 address += immed;
3444 else
3445 address -= immed;
3446 sprintf(cp, "PLI\t%#8.8" PRIx32, address);
3447 return ERROR_OK;
3448 }
3449 if (rn == 0xf && rt != 0xf) {
3450 ldrsb_literal:
3451 immed = opcode & 0xfff;
3452 address = thumb_alignpc4(address);
3453 if (opcode & (1 << 23))
3454 address += immed;
3455 else
3456 address -= immed;
3457 sprintf(cp, "LDRSB\t%#8.8" PRIx32, address);
3458 return ERROR_OK;
3459 }
3460 if (rn == 0xf)
3461 break;
3462 if ((op2 & 0x3c) == 0x38) {
3463 immed = opcode & 0xff;
3464 sprintf(cp, "LDRSBT\tr%d, [r%d, #%d]\t; %2.2x",
3465 rt, rn, immed, immed);
3466 return ERROR_OK;
3467 }
3468 if ((op2 & 0x3c) == 0x30) {
3469 if (rt == 0xf) {
3470 immed = opcode & 0xff;
3471 immed = -immed; // pli
3472 sprintf(cp, "PLI\t[r%d, #-%d]\t; %2.2x",
3473 rn, immed, immed);
3474 return ERROR_OK;
3475 }
3476 mnemonic = "LDRSB";
3477 goto ldrxb_immediate_t3;
3478 }
3479 if ((op2 & 0x24) == 0x24) {
3480 mnemonic = "LDRSB";
3481 goto ldrxb_immediate_t3;
3482 }
3483 if (op2 == 0) {
3484 int rm = opcode & 0xf;
3485
3486 if (rt == 0x0f)
3487 sprintf(cp, "PLI\t");
3488 else
3489 sprintf(cp, "LDRSB.W\tr%d, ", rt);
3490 immed = (opcode >> 4) & 0x3;
3491 cp = strchr(cp, 0);
3492 sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed);
3493 return ERROR_OK;
3494 }
3495 break;
3496 case 3:
3497 if (rt == 0xf)
3498 goto pli_immediate;
3499 if (rn == 0xf)
3500 goto ldrsb_literal;
3501 immed = opcode & 0xfff;
3502 mnemonic = "LDRSB";
3503 goto ldrxb_immediate_t2;
3504 }
3505
3506 return ERROR_INVALID_ARGUMENTS;
3507 }
3508
3509 static int t2ev_load_halfword(uint32_t opcode, uint32_t address,
3510 arm_instruction_t *instruction, char *cp)
3511 {
3512 int rn = (opcode >> 16) & 0xf;
3513 int rt = (opcode >> 12) & 0xf;
3514 int op2 = (opcode >> 6) & 0x3f;
3515 char *sign = (opcode & (1 < 24)) ? "S" : "";
3516 unsigned immed;
3517
3518 if (rt == 0xf) {
3519 sprintf(cp, "HINT (UNALLOCATED)");
3520 return ERROR_OK;
3521 }
3522
3523 if ((opcode & (1 << 23)) == 0) {
3524 if (rn == 0xf) {
3525 ldrh_literal:
3526 if (rt == 0xf)
3527 return ERROR_INVALID_ARGUMENTS;
3528 immed = opcode & 0xfff;
3529 address = thumb_alignpc4(address);
3530 if (opcode & (1 << 23))
3531 address += immed;
3532 else
3533 address -= immed;
3534 sprintf(cp, "LDR%sH\tr%d, %#8.8" PRIx32,
3535 sign, rt, address);
3536 return ERROR_OK;
3537 }
3538 if (rt == 0xf)
3539 return ERROR_INVALID_ARGUMENTS;
3540 if (op2 == 0) {
3541 int rm = opcode & 0xf;
3542
3543 immed = (opcode >> 4) & 0x3;
3544 sprintf(cp, "LDR%sH.W\tr%d, [r%d, r%d, LSL #%d]",
3545 sign, rt, rn, rm, immed);
3546 return ERROR_OK;
3547 }
3548 if ((op2 & 0x3c) == 0x38) {
3549 immed = (opcode >> 4) & 0x3;
3550 sprintf(cp, "LDR%sHT\tr%d, [r%d, #%d]\t; %#2.2x",
3551 sign, rt, rn, immed, immed);
3552 return ERROR_OK;
3553 }
3554 if ((op2 & 0x3c) == 0x30 || (op2 & 0x24) == 0x24) {
3555 char *p1 = "]", *p2 = "";
3556
3557 immed = opcode & 0xff;
3558 if (opcode & 0x200)
3559 immed = -immed;
3560
3561 /* two indexed modes will write back rn */
3562 if (opcode & 0x100) {
3563 if (opcode & 0x400) /* pre-indexed */
3564 p2 = "]!";
3565 else { /* post-indexed */
3566 p1 = "]";
3567 p2 = "";
3568 }
3569 }
3570 sprintf(cp, "LDR%sH\tr%d, [r%d%s, #%d%s\t; %#8.8x",
3571 sign, rt, rn, p1, immed, p2, immed);
3572 return ERROR_OK;
3573 }
3574 } else {
3575 if (rn == 0xf)
3576 goto ldrh_literal;
3577 if (rt != 0x0f) {
3578 immed = opcode & 0xfff;
3579 sprintf(cp, "LDR%sH.W\tr%d, [r%d, #%d]\t; %#6.6x",
3580 sign, rt, rn, immed, immed);
3581 return ERROR_OK;
3582 }
3583 }
3584
3585 return ERROR_INVALID_ARGUMENTS;
3586 }
3587
3588 /*
3589 * REVISIT for Thumb2 instructions, instruction->type and friends aren't
3590 * always set. That means eventual arm_simulate_step() support for Thumb2
3591 * will need work in this area.
3592 */
3593 int thumb2_opcode(target_t *target, uint32_t address, arm_instruction_t *instruction)
3594 {
3595 int retval;
3596 uint16_t op;
3597 uint32_t opcode;
3598 char *cp;
3599
3600 /* clear low bit ... it's set on function pointers */
3601 address &= ~1;
3602
3603 /* clear fields, to avoid confusion */
3604 memset(instruction, 0, sizeof(arm_instruction_t));
3605
3606 /* read first halfword, see if this is the only one */
3607 retval = target_read_u16(target, address, &op);
3608 if (retval != ERROR_OK)
3609 return retval;
3610
3611 switch (op & 0xf800) {
3612 case 0xf800:
3613 case 0xf000:
3614 case 0xe800:
3615 /* 32-bit instructions */
3616 instruction->instruction_size = 4;
3617 opcode = op << 16;
3618 retval = target_read_u16(target, address + 2, &op);
3619 if (retval != ERROR_OK)
3620 return retval;
3621 opcode |= op;
3622 instruction->opcode = opcode;
3623 break;
3624 default:
3625 /* 16-bit: Thumb1 + IT + CBZ/CBNZ + ... */
3626 return thumb_evaluate_opcode(op, address, instruction);
3627 }
3628
3629 snprintf(instruction->text, 128,
3630 "0x%8.8" PRIx32 " 0x%8.8" PRIx32 "\t",
3631 address, opcode);
3632 cp = strchr(instruction->text, 0);
3633 retval = ERROR_FAIL;
3634
3635 /* ARMv7-M: A5.3.1 Data processing (modified immediate) */
3636 if ((opcode & 0x1a008000) == 0x10000000)
3637 retval = t2ev_data_mod_immed(opcode, address, instruction, cp);
3638
3639 /* ARMv7-M: A5.3.3 Data processing (plain binary immediate) */
3640 else if ((opcode & 0x1a008000) == 0x12000000)
3641 retval = t2ev_data_immed(opcode, address, instruction, cp);
3642
3643 /* ARMv7-M: A5.3.4 Branches and miscellaneous control */
3644 else if ((opcode & 0x18008000) == 0x10008000)
3645 retval = t2ev_b_misc(opcode, address, instruction, cp);
3646
3647 /* ARMv7-M: A5.3.5 Load/store multiple */
3648 else if ((opcode & 0x1e400000) == 0x08000000)
3649 retval = t2ev_ldm_stm(opcode, address, instruction, cp);
3650
3651 /* ARMv7-M: A5.3.7 Load word */
3652 else if ((opcode & 0x1f700000) == 0x18500000)
3653 retval = t2ev_load_word(opcode, address, instruction, cp);
3654
3655 /* ARMv7-M: A5.3.8 Load halfword, unallocated memory hints */
3656 else if ((opcode & 0x1e700000) == 0x18e00000)
3657 retval = t2ev_load_halfword(opcode, address, instruction, cp);
3658
3659 /* ARMv7-M: A5.3.9 Load byte, memory hints */
3660 else if ((opcode & 0x1e700000) == 0x18100000)
3661 retval = t2ev_load_byte_hints(opcode, address, instruction, cp);
3662
3663 /* ARMv7-M: A5.3.10 Store single data item */
3664 else if ((opcode & 0x1f100000) == 0x18000000)
3665 retval = t2ev_store_single(opcode, address, instruction, cp);
3666
3667 /* ARMv7-M: A5.3.11 Data processing (shifted register) */
3668 else if ((opcode & 0x1e000000) == 0x0a000000)
3669 retval = t2ev_data_shift(opcode, address, instruction, cp);
3670
3671 /* ARMv7-M: A5.3.12 Data processing (register)
3672 * and A5.3.13 Miscellaneous operations
3673 */
3674 else if ((opcode & 0x1f000000) == 0x1a000000)
3675 retval = t2ev_data_reg(opcode, address, instruction, cp);
3676
3677 /* ARMv7-M: A5.3.14 Multiply, and multiply accumulate */
3678 else if ((opcode & 0x1f800000) == 0x1b000000)
3679 retval = t2ev_mul32(opcode, address, instruction, cp);
3680
3681 /* ARMv7-M: A5.3.15 Long multiply, long multiply accumulate, divide */
3682 else if ((opcode & 0x1f800000) == 0x1b800000)
3683 retval = t2ev_mul64_div(opcode, address, instruction, cp);
3684
3685 /* FIXME decode more 32-bit instructions */
3686
3687 if (retval == ERROR_OK)
3688 return retval;
3689
3690 if (retval == ERROR_INVALID_ARGUMENTS) {
3691 instruction->type = ARM_UNDEFINED_INSTRUCTION;
3692 strcpy(cp, "UNDEFINED OPCODE");
3693 return ERROR_OK;
3694 }
3695
3696 LOG_DEBUG("Can't decode 32-bit Thumb2 yet (opcode=%08" PRIx32 ")",
3697 opcode);
3698
3699 strcpy(cp, "(32-bit Thumb2 ...)");
3700 return ERROR_OK;
3701 }
3702
3703 int arm_access_size(arm_instruction_t *instruction)
3704 {
3705 if ((instruction->type == ARM_LDRB)
3706 || (instruction->type == ARM_LDRBT)
3707 || (instruction->type == ARM_LDRSB)
3708 || (instruction->type == ARM_STRB)
3709 || (instruction->type == ARM_STRBT))
3710 {
3711 return 1;
3712 }
3713 else if ((instruction->type == ARM_LDRH)
3714 || (instruction->type == ARM_LDRSH)
3715 || (instruction->type == ARM_STRH))
3716 {
3717 return 2;
3718 }
3719 else if ((instruction->type == ARM_LDR)
3720 || (instruction->type == ARM_LDRT)
3721 || (instruction->type == ARM_STR)
3722 || (instruction->type == ARM_STRT))
3723 {
3724 return 4;
3725 }
3726 else if ((instruction->type == ARM_LDRD)
3727 || (instruction->type == ARM_STRD))
3728 {
3729 return 8;
3730 }
3731 else
3732 {
3733 LOG_ERROR("BUG: instruction type %i isn't a load/store instruction", instruction->type);
3734 return 0;
3735 }
3736 }

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)