More instruction decoding fixes:
[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 = "RSBS";
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 char *wback = "!";
1948
1949 if (L)
1950 {
1951 instruction->type = ARM_LDM;
1952 mnemonic = "LDM";
1953 if (opcode & (1 << Rn))
1954 wback = "";
1955 }
1956 else
1957 {
1958 instruction->type = ARM_STM;
1959 mnemonic = "STM";
1960 }
1961 snprintf(ptr_name, sizeof ptr_name, "r%i%s, ", Rn, wback);
1962 }
1963 else
1964 { /* push/pop */
1965 Rn = 13; /* SP */
1966 if (L)
1967 {
1968 instruction->type = ARM_LDM;
1969 mnemonic = "POP";
1970 if (R)
1971 reg_list |= (1 << 15) /*PC*/;
1972 }
1973 else
1974 {
1975 instruction->type = ARM_STM;
1976 mnemonic = "PUSH";
1977 addr_mode = 3; /*DB*/
1978 if (R)
1979 reg_list |= (1 << 14) /*LR*/;
1980 }
1981 }
1982
1983 reg_names_p = reg_names;
1984 for (i = 0; i <= 15; i++)
1985 {
1986 if (reg_list & (1 << i))
1987 reg_names_p += snprintf(reg_names_p, (reg_names + 40 - reg_names_p), "r%i, ", i);
1988 }
1989 if (reg_names_p > reg_names)
1990 reg_names_p[-2] = '\0';
1991 else /* invalid op : no registers */
1992 reg_names[0] = '\0';
1993
1994 snprintf(instruction->text, 128,
1995 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%s{%s}",
1996 address, opcode, mnemonic, ptr_name, reg_names);
1997
1998 instruction->info.load_store_multiple.register_list = reg_list;
1999 instruction->info.load_store_multiple.Rn = Rn;
2000 instruction->info.load_store_multiple.addressing_mode = addr_mode;
2001
2002 return ERROR_OK;
2003 }
2004
2005 int evaluate_cond_branch_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
2006 {
2007 uint32_t offset = opcode & 0xff;
2008 uint8_t cond = (opcode >> 8) & 0xf;
2009 uint32_t target_address;
2010
2011 if (cond == 0xf)
2012 {
2013 instruction->type = ARM_SWI;
2014 snprintf(instruction->text, 128,
2015 "0x%8.8" PRIx32 " 0x%4.4x \tSVC\t%#2.2" PRIx32,
2016 address, opcode, offset);
2017 return ERROR_OK;
2018 }
2019 else if (cond == 0xe)
2020 {
2021 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2022 snprintf(instruction->text, 128,
2023 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2024 address, opcode);
2025 return ERROR_OK;
2026 }
2027
2028 /* sign extend 8-bit offset */
2029 if (offset & 0x00000080)
2030 offset = 0xffffff00 | offset;
2031
2032 target_address = address + 4 + (offset << 1);
2033
2034 snprintf(instruction->text, 128,
2035 "0x%8.8" PRIx32 " 0x%4.4x \tB%s\t%#8.8" PRIx32,
2036 address, opcode,
2037 arm_condition_strings[cond], target_address);
2038
2039 instruction->type = ARM_B;
2040 instruction->info.b_bl_bx_blx.reg_operand = -1;
2041 instruction->info.b_bl_bx_blx.target_address = target_address;
2042
2043 return ERROR_OK;
2044 }
2045
2046 static int evaluate_cb_thumb(uint16_t opcode, uint32_t address,
2047 arm_instruction_t *instruction)
2048 {
2049 unsigned offset;
2050
2051 /* added in Thumb2 */
2052 offset = (opcode >> 3) & 0x1f;
2053 offset |= (opcode & 0x0200) >> 4;
2054
2055 snprintf(instruction->text, 128,
2056 "0x%8.8" PRIx32 " 0x%4.4x \tCB%sZ\tr%d, %#8.8" PRIx32,
2057 address, opcode,
2058 (opcode & 0x0800) ? "N" : "",
2059 opcode & 0x7, address + 4 + (offset << 1));
2060
2061 return ERROR_OK;
2062 }
2063
2064 static int evaluate_extend_thumb(uint16_t opcode, uint32_t address,
2065 arm_instruction_t *instruction)
2066 {
2067 /* added in ARMv6 */
2068 snprintf(instruction->text, 128,
2069 "0x%8.8" PRIx32 " 0x%4.4x \t%cXT%c\tr%d, r%d",
2070 address, opcode,
2071 (opcode & 0x0080) ? 'U' : 'S',
2072 (opcode & 0x0040) ? 'B' : 'H',
2073 opcode & 0x7, (opcode >> 3) & 0x7);
2074
2075 return ERROR_OK;
2076 }
2077
2078 static int evaluate_cps_thumb(uint16_t opcode, uint32_t address,
2079 arm_instruction_t *instruction)
2080 {
2081 /* added in ARMv6 */
2082 if ((opcode & 0x0ff0) == 0x0650)
2083 snprintf(instruction->text, 128,
2084 "0x%8.8" PRIx32 " 0x%4.4x \tSETEND %s",
2085 address, opcode,
2086 (opcode & 0x80) ? "BE" : "LE");
2087 else /* ASSUME (opcode & 0x0fe0) == 0x0660 */
2088 snprintf(instruction->text, 128,
2089 "0x%8.8" PRIx32 " 0x%4.4x \tCPSI%c\t%s%s%s",
2090 address, opcode,
2091 (opcode & 0x0010) ? 'D' : 'E',
2092 (opcode & 0x0004) ? "A" : "",
2093 (opcode & 0x0002) ? "I" : "",
2094 (opcode & 0x0001) ? "F" : "");
2095
2096 return ERROR_OK;
2097 }
2098
2099 static int evaluate_byterev_thumb(uint16_t opcode, uint32_t address,
2100 arm_instruction_t *instruction)
2101 {
2102 char *suffix;
2103
2104 /* added in ARMv6 */
2105 switch ((opcode >> 6) & 3) {
2106 case 0:
2107 suffix = "";
2108 break;
2109 case 1:
2110 suffix = "16";
2111 break;
2112 default:
2113 suffix = "SH";
2114 break;
2115 }
2116 snprintf(instruction->text, 128,
2117 "0x%8.8" PRIx32 " 0x%4.4x \tREV%s\tr%d, r%d",
2118 address, opcode, suffix,
2119 opcode & 0x7, (opcode >> 3) & 0x7);
2120
2121 return ERROR_OK;
2122 }
2123
2124 static int evaluate_hint_thumb(uint16_t opcode, uint32_t address,
2125 arm_instruction_t *instruction)
2126 {
2127 char *hint;
2128
2129 switch ((opcode >> 4) & 0x0f) {
2130 case 0:
2131 hint = "NOP";
2132 break;
2133 case 1:
2134 hint = "YIELD";
2135 break;
2136 case 2:
2137 hint = "WFE";
2138 break;
2139 case 3:
2140 hint = "WFI";
2141 break;
2142 case 4:
2143 hint = "SEV";
2144 break;
2145 default:
2146 hint = "HINT (UNRECOGNIZED)";
2147 break;
2148 }
2149
2150 snprintf(instruction->text, 128,
2151 "0x%8.8" PRIx32 " 0x%4.4x \t%s",
2152 address, opcode, hint);
2153
2154 return ERROR_OK;
2155 }
2156
2157 static int evaluate_ifthen_thumb(uint16_t opcode, uint32_t address,
2158 arm_instruction_t *instruction)
2159 {
2160 unsigned cond = (opcode >> 4) & 0x0f;
2161 char *x = "", *y = "", *z = "";
2162
2163 if (opcode & 0x01)
2164 z = (opcode & 0x02) ? "T" : "E";
2165 if (opcode & 0x03)
2166 y = (opcode & 0x04) ? "T" : "E";
2167 if (opcode & 0x07)
2168 x = (opcode & 0x08) ? "T" : "E";
2169
2170 snprintf(instruction->text, 128,
2171 "0x%8.8" PRIx32 " 0x%4.4x \tIT%s%s%s\t%s",
2172 address, opcode,
2173 x, y, z, arm_condition_strings[cond]);
2174
2175 /* NOTE: strictly speaking, the next 1-4 instructions should
2176 * now be displayed with the relevant conditional suffix...
2177 */
2178
2179 return ERROR_OK;
2180 }
2181
2182 int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
2183 {
2184 /* clear fields, to avoid confusion */
2185 memset(instruction, 0, sizeof(arm_instruction_t));
2186 instruction->opcode = opcode;
2187 instruction->instruction_size = 2;
2188
2189 if ((opcode & 0xe000) == 0x0000)
2190 {
2191 /* add/substract register or immediate */
2192 if ((opcode & 0x1800) == 0x1800)
2193 return evaluate_add_sub_thumb(opcode, address, instruction);
2194 /* shift by immediate */
2195 else
2196 return evaluate_shift_imm_thumb(opcode, address, instruction);
2197 }
2198
2199 /* Add/substract/compare/move immediate */
2200 if ((opcode & 0xe000) == 0x2000)
2201 {
2202 return evaluate_data_proc_imm_thumb(opcode, address, instruction);
2203 }
2204
2205 /* Data processing instructions */
2206 if ((opcode & 0xf800) == 0x4000)
2207 {
2208 return evaluate_data_proc_thumb(opcode, address, instruction);
2209 }
2210
2211 /* Load from literal pool */
2212 if ((opcode & 0xf800) == 0x4800)
2213 {
2214 return evaluate_load_literal_thumb(opcode, address, instruction);
2215 }
2216
2217 /* Load/Store register offset */
2218 if ((opcode & 0xf000) == 0x5000)
2219 {
2220 return evaluate_load_store_reg_thumb(opcode, address, instruction);
2221 }
2222
2223 /* Load/Store immediate offset */
2224 if (((opcode & 0xe000) == 0x6000)
2225 ||((opcode & 0xf000) == 0x8000))
2226 {
2227 return evaluate_load_store_imm_thumb(opcode, address, instruction);
2228 }
2229
2230 /* Load/Store from/to stack */
2231 if ((opcode & 0xf000) == 0x9000)
2232 {
2233 return evaluate_load_store_stack_thumb(opcode, address, instruction);
2234 }
2235
2236 /* Add to SP/PC */
2237 if ((opcode & 0xf000) == 0xa000)
2238 {
2239 return evaluate_add_sp_pc_thumb(opcode, address, instruction);
2240 }
2241
2242 /* Misc */
2243 if ((opcode & 0xf000) == 0xb000)
2244 {
2245 switch ((opcode >> 8) & 0x0f) {
2246 case 0x0:
2247 return evaluate_adjust_stack_thumb(opcode, address, instruction);
2248 case 0x1:
2249 case 0x3:
2250 case 0x9:
2251 case 0xb:
2252 return evaluate_cb_thumb(opcode, address, instruction);
2253 case 0x2:
2254 return evaluate_extend_thumb(opcode, address, instruction);
2255 case 0x4:
2256 case 0x5:
2257 case 0xc:
2258 case 0xd:
2259 return evaluate_load_store_multiple_thumb(opcode, address,
2260 instruction);
2261 case 0x6:
2262 return evaluate_cps_thumb(opcode, address, instruction);
2263 case 0xa:
2264 if ((opcode & 0x00c0) == 0x0080)
2265 break;
2266 return evaluate_byterev_thumb(opcode, address, instruction);
2267 case 0xe:
2268 return evaluate_breakpoint_thumb(opcode, address, instruction);
2269 case 0xf:
2270 if (opcode & 0x000f)
2271 return evaluate_ifthen_thumb(opcode, address,
2272 instruction);
2273 else
2274 return evaluate_hint_thumb(opcode, address,
2275 instruction);
2276 }
2277
2278 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2279 snprintf(instruction->text, 128,
2280 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2281 address, opcode);
2282 return ERROR_OK;
2283 }
2284
2285 /* Load/Store multiple */
2286 if ((opcode & 0xf000) == 0xc000)
2287 {
2288 return evaluate_load_store_multiple_thumb(opcode, address, instruction);
2289 }
2290
2291 /* Conditional branch + SWI */
2292 if ((opcode & 0xf000) == 0xd000)
2293 {
2294 return evaluate_cond_branch_thumb(opcode, address, instruction);
2295 }
2296
2297 if ((opcode & 0xe000) == 0xe000)
2298 {
2299 /* Undefined instructions */
2300 if ((opcode & 0xf801) == 0xe801)
2301 {
2302 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2303 snprintf(instruction->text, 128,
2304 "0x%8.8" PRIx32 " 0x%8.8x\t"
2305 "UNDEFINED INSTRUCTION",
2306 address, opcode);
2307 return ERROR_OK;
2308 }
2309 else
2310 { /* Branch to offset */
2311 return evaluate_b_bl_blx_thumb(opcode, address, instruction);
2312 }
2313 }
2314
2315 LOG_ERROR("should never reach this point (opcode=%04x)",opcode);
2316 return -1;
2317 }
2318
2319 static int t2ev_b_bl(uint32_t opcode, uint32_t address,
2320 arm_instruction_t *instruction, char *cp)
2321 {
2322 unsigned offset;
2323 unsigned b21 = 1 << 21;
2324 unsigned b22 = 1 << 22;
2325
2326 /* instead of combining two smaller 16-bit branch instructions,
2327 * Thumb2 uses only one larger 32-bit instruction.
2328 */
2329 offset = opcode & 0x7ff;
2330 offset |= (opcode & 0x03ff0000) >> 5;
2331 if (opcode & (1 << 26)) {
2332 offset |= 0xff << 23;
2333 if ((opcode & (1 << 11)) == 0)
2334 b21 = 0;
2335 if ((opcode & (1 << 13)) == 0)
2336 b22 = 0;
2337 } else {
2338 if (opcode & (1 << 11))
2339 b21 = 0;
2340 if (opcode & (1 << 13))
2341 b22 = 0;
2342 }
2343 offset |= b21;
2344 offset |= b22;
2345
2346
2347 address += 4;
2348 address += offset << 1;
2349
2350 instruction->type = (opcode & (1 << 14)) ? ARM_BL : ARM_B;
2351 instruction->info.b_bl_bx_blx.reg_operand = -1;
2352 instruction->info.b_bl_bx_blx.target_address = address;
2353 sprintf(cp, "%s\t%#8.8" PRIx32,
2354 (opcode & (1 << 14)) ? "BL" : "B.W",
2355 address);
2356
2357 return ERROR_OK;
2358 }
2359
2360 static int t2ev_cond_b(uint32_t opcode, uint32_t address,
2361 arm_instruction_t *instruction, char *cp)
2362 {
2363 unsigned offset;
2364 unsigned b17 = 1 << 17;
2365 unsigned b18 = 1 << 18;
2366 unsigned cond = (opcode >> 22) & 0x0f;
2367
2368 offset = opcode & 0x7ff;
2369 offset |= (opcode & 0x003f0000) >> 5;
2370 if (opcode & (1 << 26)) {
2371 offset |= 0xffff << 19;
2372 if ((opcode & (1 << 11)) == 0)
2373 b17 = 0;
2374 if ((opcode & (1 << 13)) == 0)
2375 b18 = 0;
2376 } else {
2377 if (opcode & (1 << 11))
2378 b17 = 0;
2379 if (opcode & (1 << 13))
2380 b18 = 0;
2381 }
2382 offset |= b17;
2383 offset |= b18;
2384
2385 address += 4;
2386 address += offset << 1;
2387
2388 instruction->type = ARM_B;
2389 instruction->info.b_bl_bx_blx.reg_operand = -1;
2390 instruction->info.b_bl_bx_blx.target_address = address;
2391 sprintf(cp, "B%s.W\t%#8.8" PRIx32,
2392 arm_condition_strings[cond],
2393 address);
2394
2395 return ERROR_OK;
2396 }
2397
2398 static const char *special_name(int number)
2399 {
2400 char *special = "(RESERVED)";
2401
2402 switch (number) {
2403 case 0:
2404 special = "apsr";
2405 break;
2406 case 1:
2407 special = "iapsr";
2408 break;
2409 case 2:
2410 special = "eapsr";
2411 break;
2412 case 3:
2413 special = "xpsr";
2414 break;
2415 case 5:
2416 special = "ipsr";
2417 break;
2418 case 6:
2419 special = "epsr";
2420 break;
2421 case 7:
2422 special = "iepsr";
2423 break;
2424 case 8:
2425 special = "msp";
2426 break;
2427 case 9:
2428 special = "psp";
2429 break;
2430 case 16:
2431 special = "primask";
2432 break;
2433 case 17:
2434 special = "basepri";
2435 break;
2436 case 18:
2437 special = "basepri_max";
2438 break;
2439 case 19:
2440 special = "faultmask";
2441 break;
2442 case 20:
2443 special = "control";
2444 break;
2445 }
2446 return special;
2447 }
2448
2449 static int t2ev_hint(uint32_t opcode, uint32_t address,
2450 arm_instruction_t *instruction, char *cp)
2451 {
2452 const char *mnemonic;
2453
2454 if (opcode & 0x0700) {
2455 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2456 strcpy(cp, "UNDEFINED");
2457 return ERROR_OK;
2458 }
2459
2460 if (opcode & 0x00f0) {
2461 sprintf(cp, "DBG\t#%d", (int) opcode & 0xf);
2462 return ERROR_OK;
2463 }
2464
2465 switch (opcode & 0x0f) {
2466 case 0:
2467 mnemonic = "NOP.W";
2468 break;
2469 case 1:
2470 mnemonic = "YIELD.W";
2471 break;
2472 case 2:
2473 mnemonic = "WFE.W";
2474 break;
2475 case 3:
2476 mnemonic = "WFI.W";
2477 break;
2478 case 4:
2479 mnemonic = "SEV.W";
2480 break;
2481 default:
2482 mnemonic = "HINT.W (UNRECOGNIZED)";
2483 break;
2484 }
2485 strcpy(cp, mnemonic);
2486 return ERROR_OK;
2487 }
2488
2489 static int t2ev_misc(uint32_t opcode, uint32_t address,
2490 arm_instruction_t *instruction, char *cp)
2491 {
2492 const char *mnemonic;
2493
2494 switch ((opcode >> 4) & 0x0f) {
2495 case 2:
2496 mnemonic = "CLREX";
2497 break;
2498 case 4:
2499 mnemonic = "DSB";
2500 break;
2501 case 5:
2502 mnemonic = "DMB";
2503 break;
2504 case 6:
2505 mnemonic = "ISB";
2506 break;
2507 default:
2508 return ERROR_INVALID_ARGUMENTS;
2509 }
2510 strcpy(cp, mnemonic);
2511 return ERROR_OK;
2512 }
2513
2514 static int t2ev_b_misc(uint32_t opcode, uint32_t address,
2515 arm_instruction_t *instruction, char *cp)
2516 {
2517 /* permanently undefined */
2518 if ((opcode & 0x07f07000) == 0x07f02000) {
2519 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2520 strcpy(cp, "UNDEFINED");
2521 return ERROR_OK;
2522 }
2523
2524 switch ((opcode >> 12) & 0x5) {
2525 case 0x1:
2526 case 0x5:
2527 return t2ev_b_bl(opcode, address, instruction, cp);
2528 case 0x4:
2529 goto undef;
2530 case 0:
2531 if (((opcode >> 23) & 0x07) != 0x07)
2532 return t2ev_cond_b(opcode, address, instruction, cp);
2533 if (opcode & (1 << 26))
2534 goto undef;
2535 break;
2536 }
2537
2538 switch ((opcode >> 20) & 0x7f) {
2539 case 0x38:
2540 case 0x39:
2541 sprintf(cp, "MSR\t%s, r%d", special_name(opcode & 0xff),
2542 (int) (opcode >> 16) & 0x0f);
2543 return ERROR_OK;
2544 case 0x3a:
2545 return t2ev_hint(opcode, address, instruction, cp);
2546 case 0x3b:
2547 return t2ev_misc(opcode, address, instruction, cp);
2548 case 0x3e:
2549 case 0x3f:
2550 sprintf(cp, "MRS\tr%d, %s", (int) (opcode >> 8) & 0x0f,
2551 special_name(opcode & 0xff));
2552 return ERROR_OK;
2553 }
2554
2555 undef:
2556 return ERROR_INVALID_ARGUMENTS;
2557 }
2558
2559 static int t2ev_data_mod_immed(uint32_t opcode, uint32_t address,
2560 arm_instruction_t *instruction, char *cp)
2561 {
2562 char *mnemonic = NULL;
2563 int rn = (opcode >> 16) & 0xf;
2564 int rd = (opcode >> 8) & 0xf;
2565 unsigned immed = opcode & 0xff;
2566 unsigned func;
2567 bool one = false;
2568 char *suffix = "";
2569 char *suffix2 = "";
2570
2571 /* ARMv7-M: A5.3.2 Modified immediate constants */
2572 func = (opcode >> 11) & 0x0e;
2573 if (immed & 0x80)
2574 func |= 1;
2575 if (opcode & (1 << 26))
2576 func |= 0x10;
2577
2578 /* "Modified" immediates */
2579 switch (func >> 1) {
2580 case 0:
2581 break;
2582 case 2:
2583 immed <<= 8;
2584 /* FALLTHROUGH */
2585 case 1:
2586 immed += immed << 16;
2587 break;
2588 case 3:
2589 immed += immed << 8;
2590 immed += immed << 16;
2591 break;
2592 default:
2593 immed |= 0x80;
2594 immed = ror(immed, func);
2595 }
2596
2597 if (opcode & (1 << 20))
2598 suffix = "S";
2599
2600 switch ((opcode >> 21) & 0xf) {
2601 case 0:
2602 if (rd == 0xf) {
2603 instruction->type = ARM_TST;
2604 mnemonic = "TST";
2605 one = true;
2606 suffix = "";
2607 rd = rn;
2608 } else {
2609 instruction->type = ARM_AND;
2610 mnemonic = "AND";
2611 }
2612 break;
2613 case 1:
2614 instruction->type = ARM_BIC;
2615 mnemonic = "BIC";
2616 break;
2617 case 2:
2618 if (rn == 0xf) {
2619 instruction->type = ARM_MOV;
2620 mnemonic = "MOV";
2621 one = true;
2622 suffix2 = ".W";
2623 } else {
2624 instruction->type = ARM_ORR;
2625 mnemonic = "ORR";
2626 }
2627 break;
2628 case 3:
2629 if (rn == 0xf) {
2630 instruction->type = ARM_MVN;
2631 mnemonic = "MVN";
2632 one = true;
2633 } else {
2634 // instruction->type = ARM_ORN;
2635 mnemonic = "ORN";
2636 }
2637 break;
2638 case 4:
2639 if (rd == 0xf) {
2640 instruction->type = ARM_TEQ;
2641 mnemonic = "TEQ";
2642 one = true;
2643 suffix = "";
2644 rd = rn;
2645 } else {
2646 instruction->type = ARM_EOR;
2647 mnemonic = "EOR";
2648 }
2649 break;
2650 case 8:
2651 if (rd == 0xf) {
2652 instruction->type = ARM_CMN;
2653 mnemonic = "CMN";
2654 one = true;
2655 suffix = "";
2656 rd = rn;
2657 } else {
2658 instruction->type = ARM_ADD;
2659 mnemonic = "ADD";
2660 suffix2 = ".W";
2661 }
2662 break;
2663 case 10:
2664 instruction->type = ARM_ADC;
2665 mnemonic = "ADC";
2666 suffix2 = ".W";
2667 break;
2668 case 11:
2669 instruction->type = ARM_SBC;
2670 mnemonic = "SBC";
2671 break;
2672 case 13:
2673 if (rd == 0xf) {
2674 instruction->type = ARM_CMP;
2675 mnemonic = "CMP";
2676 one = true;
2677 suffix = "";
2678 rd = rn;
2679 } else {
2680 instruction->type = ARM_SUB;
2681 mnemonic = "SUB";
2682 }
2683 suffix2 = ".W";
2684 break;
2685 case 14:
2686 instruction->type = ARM_RSB;
2687 mnemonic = "RSB";
2688 suffix2 = ".W";
2689 break;
2690 default:
2691 return ERROR_INVALID_ARGUMENTS;
2692 }
2693
2694 if (one)
2695 sprintf(cp, "%s%s\tr%d, #%d\t; %#8.8x",
2696 mnemonic, suffix2 ,rd, immed, immed);
2697 else
2698 sprintf(cp, "%s%s%s\tr%d, r%d, #%d\t; %#8.8x",
2699 mnemonic, suffix, suffix2,
2700 rd, rn, immed, immed);
2701
2702 return ERROR_OK;
2703 }
2704
2705 static int t2ev_data_immed(uint32_t opcode, uint32_t address,
2706 arm_instruction_t *instruction, char *cp)
2707 {
2708 char *mnemonic = NULL;
2709 int rn = (opcode >> 16) & 0xf;
2710 int rd = (opcode >> 8) & 0xf;
2711 unsigned immed;
2712 bool add = false;
2713 bool is_signed = false;
2714
2715 immed = (opcode & 0x0ff) | ((opcode & 0x7000) >> 4);
2716 if (opcode & (1 << 26))
2717 immed |= (1 << 11);
2718
2719 switch ((opcode >> 20) & 0x1f) {
2720 case 0:
2721 if (rn == 0xf) {
2722 add = true;
2723 goto do_adr;
2724 }
2725 mnemonic = "ADDW";
2726 break;
2727 case 4:
2728 immed |= (opcode >> 4) & 0xf000;
2729 sprintf(cp, "MOVW\tr%d, #%d\t; %#3.3x", rd, immed, immed);
2730 return ERROR_OK;
2731 case 0x0a:
2732 if (rn == 0xf)
2733 goto do_adr;
2734 mnemonic = "SUBW";
2735 break;
2736 case 0x0c:
2737 /* move constant to top 16 bits of register */
2738 immed |= (opcode >> 4) & 0xf000;
2739 sprintf(cp, "MOVT\tr%d, #%d\t; %#4.4x", rn, immed, immed);
2740 return ERROR_OK;
2741 case 0x10:
2742 case 0x12:
2743 is_signed = true;
2744 case 0x18:
2745 case 0x1a:
2746 /* signed/unsigned saturated add */
2747 immed = (opcode >> 6) & 0x03;
2748 immed |= (opcode >> 10) & 0x1c;
2749 sprintf(cp, "%sSAT\tr%d, #%d, r%d, %s #%d\t",
2750 is_signed ? "S" : "U",
2751 rd, (int) (opcode & 0x1f) + is_signed, rn,
2752 (opcode & (1 << 21)) ? "ASR" : "LSL",
2753 immed ? immed : 32);
2754 return ERROR_OK;
2755 case 0x14:
2756 is_signed = true;
2757 /* FALLTHROUGH */
2758 case 0x1c:
2759 /* signed/unsigned bitfield extract */
2760 immed = (opcode >> 6) & 0x03;
2761 immed |= (opcode >> 10) & 0x1c;
2762 sprintf(cp, "%sBFX\tr%d, r%d, #%d, #%d\t",
2763 is_signed ? "S" : "U",
2764 rd, rn, immed,
2765 (int) (opcode & 0x1f) + 1);
2766 return ERROR_OK;
2767 case 0x16:
2768 immed = (opcode >> 6) & 0x03;
2769 immed |= (opcode >> 10) & 0x1c;
2770 if (rn == 0xf) /* bitfield clear */
2771 sprintf(cp, "BFC\tr%d, #%d, #%d\t",
2772 rd, immed,
2773 (int) (opcode & 0x1f) + 1 - immed);
2774 else /* bitfield insert */
2775 sprintf(cp, "BFI\tr%d, r%d, #%d, #%d\t",
2776 rd, rn, immed,
2777 (int) (opcode & 0x1f) + 1 - immed);
2778 return ERROR_OK;
2779 default:
2780 return ERROR_INVALID_ARGUMENTS;
2781 }
2782
2783 sprintf(cp, "%s\tr%d, r%d, #%d\t; %#3.3x", mnemonic,
2784 rd, rn, immed, immed);
2785 return ERROR_OK;
2786
2787 do_adr:
2788 address = thumb_alignpc4(address);
2789 if (add)
2790 address += immed;
2791 else
2792 address -= immed;
2793 /* REVISIT "ADD/SUB Rd, PC, #const ; 0x..." might be better;
2794 * not hiding the pc-relative stuff will sometimes be useful.
2795 */
2796 sprintf(cp, "ADR.W\tr%d, %#8.8" PRIx32, rd, address);
2797 return ERROR_OK;
2798 }
2799
2800 static int t2ev_store_single(uint32_t opcode, uint32_t address,
2801 arm_instruction_t *instruction, char *cp)
2802 {
2803 unsigned op = (opcode >> 20) & 0xf;
2804 char *size = "";
2805 char *suffix = "";
2806 char *p1 = "";
2807 char *p2 = "]";
2808 unsigned immed;
2809 unsigned rn = (opcode >> 16) & 0x0f;
2810 unsigned rt = (opcode >> 12) & 0x0f;
2811
2812 if (rn == 0xf)
2813 return ERROR_INVALID_ARGUMENTS;
2814
2815 if (opcode & 0x0800)
2816 op |= 1;
2817 switch (op) {
2818 /* byte */
2819 case 0x8:
2820 case 0x9:
2821 size = "B";
2822 goto imm12;
2823 case 0x1:
2824 size = "B";
2825 goto imm8;
2826 case 0x0:
2827 size = "B";
2828 break;
2829 /* halfword */
2830 case 0xa:
2831 case 0xb:
2832 size = "H";
2833 goto imm12;
2834 case 0x3:
2835 size = "H";
2836 goto imm8;
2837 case 0x2:
2838 size = "H";
2839 break;
2840 /* word */
2841 case 0xc:
2842 case 0xd:
2843 goto imm12;
2844 case 0x5:
2845 goto imm8;
2846 case 0x4:
2847 break;
2848 /* error */
2849 default:
2850 return ERROR_INVALID_ARGUMENTS;
2851 }
2852
2853 sprintf(cp, "STR%s.W\tr%d, [r%d, r%d, LSL #%d]",
2854 size, rt, rn, (int) opcode & 0x0f,
2855 (int) (opcode >> 4) & 0x03);
2856 return ERROR_OK;
2857
2858 imm12:
2859 immed = opcode & 0x0fff;
2860 sprintf(cp, "STR%s.W\tr%d, [r%d, #%u]\t; %#3.3x",
2861 size, rt, rn, immed, immed);
2862 return ERROR_OK;
2863
2864 imm8:
2865 immed = opcode & 0x00ff;
2866
2867 switch (opcode & 0x700) {
2868 case 0x600:
2869 suffix = "T";
2870 break;
2871 case 0x000:
2872 case 0x200:
2873 return ERROR_INVALID_ARGUMENTS;
2874 }
2875
2876 /* two indexed modes will write back rn */
2877 if (opcode & 0x100) {
2878 if (opcode & 0x400) /* pre-indexed */
2879 p2 = "]!";
2880 else { /* post-indexed */
2881 p1 = "]";
2882 p2 = "";
2883 }
2884 }
2885
2886 sprintf(cp, "STR%s%s\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
2887 size, suffix, rt, rn, p1,
2888 (opcode & 0x200) ? "" : "-",
2889 immed, p2, immed);
2890 return ERROR_OK;
2891 }
2892
2893 static int t2ev_mul32(uint32_t opcode, uint32_t address,
2894 arm_instruction_t *instruction, char *cp)
2895 {
2896 int ra = (opcode >> 12) & 0xf;
2897
2898 switch (opcode & 0x007000f0) {
2899 case 0:
2900 if (ra == 0xf)
2901 sprintf(cp, "MUL\tr%d, r%d, r%d",
2902 (int) (opcode >> 8) & 0xf,
2903 (int) (opcode >> 16) & 0xf,
2904 (int) (opcode >> 0) & 0xf);
2905 else
2906 sprintf(cp, "MLA\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 case 0x10:
2912 sprintf(cp, "MLS\tr%d, r%d, r%d, r%d",
2913 (int) (opcode >> 8) & 0xf,
2914 (int) (opcode >> 16) & 0xf,
2915 (int) (opcode >> 0) & 0xf, ra);
2916 break;
2917 default:
2918 return ERROR_INVALID_ARGUMENTS;
2919 }
2920 return ERROR_OK;
2921 }
2922
2923 static int t2ev_mul64_div(uint32_t opcode, uint32_t address,
2924 arm_instruction_t *instruction, char *cp)
2925 {
2926 int op = (opcode >> 4) & 0xf;
2927 char *infix = "MUL";
2928
2929 op += (opcode >> 16) & 0x70;
2930 switch (op) {
2931 case 0x40:
2932 case 0x60:
2933 infix = "MLA";
2934 /* FALLTHROUGH */
2935 case 0:
2936 case 0x20:
2937 sprintf(cp, "%c%sL\tr%d, r%d, r%d, r%d",
2938 (op & 0x20) ? 'U' : 'S',
2939 infix,
2940 (int) (opcode >> 12) & 0xf,
2941 (int) (opcode >> 8) & 0xf,
2942 (int) (opcode >> 16) & 0xf,
2943 (int) (opcode >> 0) & 0xf);
2944 break;
2945 case 0x1f:
2946 case 0x3f:
2947 sprintf(cp, "%cDIV\tr%d, r%d, r%d",
2948 (op & 0x20) ? 'U' : 'S',
2949 (int) (opcode >> 8) & 0xf,
2950 (int) (opcode >> 16) & 0xf,
2951 (int) (opcode >> 0) & 0xf);
2952 break;
2953 default:
2954 return ERROR_INVALID_ARGUMENTS;
2955 }
2956
2957 return ERROR_OK;
2958 }
2959
2960 static int t2ev_ldm_stm(uint32_t opcode, uint32_t address,
2961 arm_instruction_t *instruction, char *cp)
2962 {
2963 int rn = (opcode >> 16) & 0xf;
2964 int op = (opcode >> 22) & 0x6;
2965 int t = (opcode >> 21) & 1;
2966 unsigned registers = opcode & 0xffff;
2967
2968 if (opcode & (1 << 20))
2969 op |= 1;
2970
2971 switch (op) {
2972 case 2:
2973 sprintf(cp, "STM.W\tr%d%s, ", rn, t ? "!" : "");
2974 break;
2975 case 3:
2976 if (rn == 13 && t)
2977 sprintf(cp, "POP.W\t");
2978 else
2979 sprintf(cp, "LDM.W\tr%d%s, ", rn, t ? "!" : "");
2980 break;
2981 case 4:
2982 if (rn == 13 && t)
2983 sprintf(cp, "PUSH.W\t");
2984 else
2985 sprintf(cp, "STMDB\tr%d%s, ", rn, t ? "!" : "");
2986 break;
2987 case 5:
2988 sprintf(cp, "LDMDB.W\tr%d%s, ", rn, t ? "!" : "");
2989 break;
2990 default:
2991 return ERROR_INVALID_ARGUMENTS;
2992 }
2993
2994 cp = strchr(cp, 0);
2995 *cp++ = '{';
2996 for (t = 0; registers; t++, registers >>= 1) {
2997 if ((registers & 1) == 0)
2998 continue;
2999 registers &= ~1;
3000 sprintf(cp, "r%d%s", t, registers ? ", " : "");
3001 cp = strchr(cp, 0);
3002 }
3003 *cp++ = '}';
3004 *cp++ = 0;
3005
3006 return ERROR_OK;
3007 }
3008
3009 static int t2ev_data_shift(uint32_t opcode, uint32_t address,
3010 arm_instruction_t *instruction, char *cp)
3011 {
3012 int op = (opcode >> 21) & 0xf;
3013 int rd = (opcode >> 8) & 0xf;
3014 int rn = (opcode >> 16) & 0xf;
3015 int type = (opcode >> 4) & 0x3;
3016 int immed = (opcode >> 6) & 0x3;
3017 char *mnemonic;
3018 char *suffix = "";
3019
3020 immed |= (opcode >> 10) & 0x7;
3021 if (opcode & (1 << 21))
3022 suffix = "S";
3023
3024 switch (op) {
3025 case 0:
3026 if (rd == 0xf) {
3027 if (!(opcode & (1 << 21)))
3028 return ERROR_INVALID_ARGUMENTS;
3029 instruction->type = ARM_TST;
3030 mnemonic = "TST";
3031 goto two;
3032 }
3033 instruction->type = ARM_AND;
3034 mnemonic = "AND";
3035 break;
3036 case 1:
3037 instruction->type = ARM_BIC;
3038 mnemonic = "BIC";
3039 break;
3040 case 2:
3041 if (rn == 0xf) {
3042 instruction->type = ARM_MOV;
3043 switch (type) {
3044 case 0:
3045 if (immed == 0) {
3046 sprintf(cp, "MOV%s.W\tr%d, r%d",
3047 suffix, rd,
3048 (int) (opcode & 0xf));
3049 return ERROR_OK;
3050 }
3051 mnemonic = "LSL";
3052 break;
3053 case 1:
3054 mnemonic = "LSR";
3055 break;
3056 case 2:
3057 mnemonic = "ASR";
3058 break;
3059 default:
3060 if (immed == 0) {
3061 sprintf(cp, "RRX%s.W\tr%d, r%d",
3062 suffix, rd,
3063 (int) (opcode & 0xf));
3064 return ERROR_OK;
3065 }
3066 mnemonic = "ROR";
3067 break;
3068 }
3069 goto immediate;
3070 } else {
3071 instruction->type = ARM_ORR;
3072 mnemonic = "ORR";
3073 }
3074 break;
3075 case 3:
3076 if (rn == 0xf) {
3077 instruction->type = ARM_MVN;
3078 mnemonic = "MVN";
3079 rn = rd;
3080 goto two;
3081 } else {
3082 // instruction->type = ARM_ORN;
3083 mnemonic = "ORN";
3084 }
3085 break;
3086 case 4:
3087 if (rd == 0xf) {
3088 if (!(opcode & (1 << 21)))
3089 return ERROR_INVALID_ARGUMENTS;
3090 instruction->type = ARM_TEQ;
3091 mnemonic = "TEQ";
3092 goto two;
3093 }
3094 instruction->type = ARM_EOR;
3095 mnemonic = "EOR";
3096 break;
3097 case 8:
3098 if (rd == 0xf) {
3099 if (!(opcode & (1 << 21)))
3100 return ERROR_INVALID_ARGUMENTS;
3101 instruction->type = ARM_CMN;
3102 mnemonic = "CMN";
3103 goto two;
3104 }
3105 instruction->type = ARM_ADD;
3106 mnemonic = "ADD";
3107 break;
3108 case 0xa:
3109 instruction->type = ARM_ADC;
3110 mnemonic = "ADC";
3111 break;
3112 case 0xb:
3113 instruction->type = ARM_SBC;
3114 mnemonic = "SBC";
3115 break;
3116 case 0xd:
3117 if (rd == 0xf) {
3118 if (!(opcode & (1 << 21)))
3119 return ERROR_INVALID_ARGUMENTS;
3120 instruction->type = ARM_CMP;
3121 mnemonic = "CMP";
3122 goto two;
3123 }
3124 instruction->type = ARM_SUB;
3125 mnemonic = "SUB";
3126 break;
3127 case 0xe:
3128 instruction->type = ARM_RSB;
3129 mnemonic = "RSB";
3130 break;
3131 default:
3132 return ERROR_INVALID_ARGUMENTS;
3133 }
3134
3135 sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
3136 mnemonic, suffix, rd, rn, (int) (opcode & 0xf));
3137
3138 shift:
3139 cp = strchr(cp, 0);
3140
3141 switch (type) {
3142 case 0:
3143 if (immed == 0)
3144 return ERROR_OK;
3145 suffix = "LSL";
3146 break;
3147 case 1:
3148 suffix = "LSR";
3149 break;
3150 case 2:
3151 suffix = "ASR";
3152 break;
3153 case 3:
3154 if (immed == 0) {
3155 strcpy(cp, "RRX");
3156 return ERROR_OK;
3157 }
3158 suffix = "ROR";
3159 break;
3160 }
3161 sprintf(cp, ", %s #%d", suffix, immed ? immed : 32);
3162 return ERROR_OK;
3163
3164 two:
3165 sprintf(cp, "%s%s.W\tr%d, r%d",
3166 mnemonic, suffix, rn, (int) (opcode & 0xf));
3167 goto shift;
3168
3169 immediate:
3170 sprintf(cp, "%s%s.W\tr%d, r%d, #%d",
3171 mnemonic, suffix, rd,
3172 (int) (opcode & 0xf), immed ? immed : 32);
3173 return ERROR_OK;
3174 }
3175
3176 static int t2ev_data_reg(uint32_t opcode, uint32_t address,
3177 arm_instruction_t *instruction, char *cp)
3178 {
3179 char *mnemonic;
3180 char * suffix = "";
3181
3182 if (((opcode >> 4) & 0xf) == 0) {
3183 switch ((opcode >> 21) & 0x7) {
3184 case 0:
3185 mnemonic = "LSL";
3186 break;
3187 case 1:
3188 mnemonic = "LSR";
3189 break;
3190 case 2:
3191 mnemonic = "ASR";
3192 break;
3193 case 3:
3194 mnemonic = "ROR";
3195 break;
3196 default:
3197 return ERROR_INVALID_ARGUMENTS;
3198 }
3199
3200 instruction->type = ARM_MOV;
3201 if (opcode & (1 << 20))
3202 suffix = "S";
3203 sprintf(cp, "%s%s.W\tr%d, r%d, r%d",
3204 mnemonic, suffix,
3205 (int) (opcode >> 8) & 0xf,
3206 (int) (opcode >> 16) & 0xf,
3207 (int) (opcode >> 0) & 0xf);
3208
3209 } else if (opcode & (1 << 7)) {
3210 switch ((opcode >> 20) & 0xf) {
3211 case 0:
3212 case 1:
3213 case 4:
3214 case 5:
3215 switch ((opcode >> 4) & 0x3) {
3216 case 1:
3217 suffix = ", ROR #8";
3218 break;
3219 case 2:
3220 suffix = ", ROR #16";
3221 break;
3222 case 3:
3223 suffix = ", ROR #24";
3224 break;
3225 }
3226 sprintf(cp, "%cXT%c.W\tr%d, r%d%s",
3227 (opcode & (1 << 24)) ? 'U' : 'S',
3228 (opcode & (1 << 26)) ? 'B' : 'H',
3229 (int) (opcode >> 8) & 0xf,
3230 (int) (opcode >> 0) & 0xf,
3231 suffix);
3232 break;
3233 case 8:
3234 case 9:
3235 case 0xa:
3236 case 0xb:
3237 if (opcode & (1 << 6))
3238 return ERROR_INVALID_ARGUMENTS;
3239 if (((opcode >> 12) & 0xf) != 0xf)
3240 return ERROR_INVALID_ARGUMENTS;
3241 if (!(opcode & (1 << 20)))
3242 return ERROR_INVALID_ARGUMENTS;
3243
3244 switch (((opcode >> 19) & 0x04)
3245 | ((opcode >> 4) & 0x3)) {
3246 case 0:
3247 mnemonic = "REV.W";
3248 break;
3249 case 1:
3250 mnemonic = "REV16.W";
3251 break;
3252 case 2:
3253 mnemonic = "RBIT";
3254 break;
3255 case 3:
3256 mnemonic = "REVSH.W";
3257 break;
3258 case 4:
3259 mnemonic = "CLZ";
3260 break;
3261 default:
3262 return ERROR_INVALID_ARGUMENTS;
3263 }
3264 sprintf(cp, "%s\tr%d, r%d",
3265 mnemonic,
3266 (int) (opcode >> 8) & 0xf,
3267 (int) (opcode >> 0) & 0xf);
3268 break;
3269 default:
3270 return ERROR_INVALID_ARGUMENTS;
3271 }
3272 }
3273
3274 return ERROR_OK;
3275 }
3276
3277 static int t2ev_load_word(uint32_t opcode, uint32_t address,
3278 arm_instruction_t *instruction, char *cp)
3279 {
3280 int rn = (opcode >> 16) & 0xf;
3281 int immed;
3282
3283 instruction->type = ARM_LDR;
3284
3285 if (rn == 0xf) {
3286 immed = opcode & 0x0fff;
3287 if ((opcode & (1 << 23)) == 0)
3288 immed = -immed;
3289 sprintf(cp, "LDR\tr%d, %#8.8" PRIx32,
3290 (int) (opcode >> 12) & 0xf,
3291 thumb_alignpc4(address) + immed);
3292 return ERROR_OK;
3293 }
3294
3295 if (opcode & (1 << 23)) {
3296 immed = opcode & 0x0fff;
3297 sprintf(cp, "LDR.W\tr%d, [r%d, #%d]\t; %#3.3x",
3298 (int) (opcode >> 12) & 0xf,
3299 rn, immed, immed);
3300 return ERROR_OK;
3301 }
3302
3303 if (!(opcode & (0x3f << 6))) {
3304 sprintf(cp, "LDR.W\tr%d, [r%d, r%d, LSL #%d]",
3305 (int) (opcode >> 12) & 0xf,
3306 rn,
3307 (int) (opcode >> 0) & 0xf,
3308 (int) (opcode >> 4) & 0x3);
3309 return ERROR_OK;
3310 }
3311
3312
3313 if (((opcode >> 8) & 0xf) == 0xe) {
3314 immed = opcode & 0x00ff;
3315
3316 sprintf(cp, "LDRT\tr%d, [r%d, #%d]\t; %#2.2x",
3317 (int) (opcode >> 12) & 0xf,
3318 rn, immed, immed);
3319 return ERROR_OK;
3320 }
3321
3322 if (((opcode >> 8) & 0xf) == 0xc || (opcode & 0x0900) == 0x0900) {
3323 char *p1 = "]", *p2 = "";
3324
3325 if (!(opcode & 0x0500))
3326 return ERROR_INVALID_ARGUMENTS;
3327
3328 immed = opcode & 0x00ff;
3329
3330 /* two indexed modes will write back rn */
3331 if (opcode & 0x100) {
3332 if (opcode & 0x400) /* pre-indexed */
3333 p2 = "]!";
3334 else { /* post-indexed */
3335 p1 = "]";
3336 p2 = "";
3337 }
3338 }
3339
3340 sprintf(cp, "LDR\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
3341 (int) (opcode >> 12) & 0xf,
3342 rn, p1,
3343 (opcode & 0x200) ? "" : "-",
3344 immed, p2, immed);
3345 return ERROR_OK;
3346 }
3347
3348 return ERROR_INVALID_ARGUMENTS;
3349 }
3350
3351 static int t2ev_load_byte_hints(uint32_t opcode, uint32_t address,
3352 arm_instruction_t *instruction, char *cp)
3353 {
3354 int rn = (opcode >> 16) & 0xf;
3355 int rt = (opcode >> 12) & 0xf;
3356 int op2 = (opcode >> 6) & 0x3f;
3357 unsigned immed;
3358 char *p1 = "", *p2 = "]";
3359 char *mnemonic;
3360
3361 switch ((opcode >> 23) & 0x3) {
3362 case 0:
3363 if ((rn & rt) == 0xf) {
3364 pld_literal:
3365 immed = opcode & 0xfff;
3366 address = thumb_alignpc4(address);
3367 if (opcode & (1 << 23))
3368 address += immed;
3369 else
3370 address -= immed;
3371 sprintf(cp, "PLD\tr%d, %#8.8" PRIx32,
3372 rt, address);
3373 return ERROR_OK;
3374 }
3375 if (rn == 0x0f && rt != 0x0f) {
3376 ldrb_literal:
3377 immed = opcode & 0xfff;
3378 address = thumb_alignpc4(address);
3379 if (opcode & (1 << 23))
3380 address += immed;
3381 else
3382 address -= immed;
3383 sprintf(cp, "LDRB\tr%d, %#8.8" PRIx32,
3384 rt, address);
3385 return ERROR_OK;
3386 }
3387 if (rn == 0x0f)
3388 break;
3389 if ((op2 & 0x3c) == 0x38) {
3390 immed = opcode & 0xff;
3391 sprintf(cp, "LDRBT\tr%d, [r%d, #%d]\t; %#2.2x",
3392 rt, rn, immed, immed);
3393 return ERROR_OK;
3394 }
3395 if ((op2 & 0x3c) == 0x30) {
3396 if (rt == 0x0f) {
3397 immed = opcode & 0xff;
3398 immed = -immed;
3399 preload_immediate:
3400 p1 = (opcode & (1 << 21)) ? "W" : "";
3401 sprintf(cp, "PLD%s\t[r%d, #%d]\t; %#6.6x",
3402 p1, rn, immed, immed);
3403 return ERROR_OK;
3404 }
3405 mnemonic = "LDRB";
3406 ldrxb_immediate_t3:
3407 immed = opcode & 0xff;
3408 if (!(opcode & 0x200))
3409 immed = -immed;
3410
3411 /* two indexed modes will write back rn */
3412 if (opcode & 0x100) {
3413 if (opcode & 0x400) /* pre-indexed */
3414 p2 = "]!";
3415 else { /* post-indexed */
3416 p1 = "]";
3417 p2 = "";
3418 }
3419 }
3420 ldrxb_immediate_t2:
3421 sprintf(cp, "%s\tr%d, [r%d%s, #%d%s\t; %#8.8x",
3422 mnemonic, rt, rn, p1,
3423 immed, p2, immed);
3424 return ERROR_OK;
3425 }
3426 if ((op2 & 0x24) == 0x24) {
3427 mnemonic = "LDRB";
3428 goto ldrxb_immediate_t3;
3429 }
3430 if (op2 == 0) {
3431 int rm = opcode & 0xf;
3432
3433 if (rt == 0x0f)
3434 sprintf(cp, "PLD\t");
3435 else
3436 sprintf(cp, "LDRB.W\tr%d, ", rt);
3437 immed = (opcode >> 4) & 0x3;
3438 cp = strchr(cp, 0);
3439 sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed);
3440 return ERROR_OK;
3441 }
3442 break;
3443 case 1:
3444 if ((rn & rt) == 0xf)
3445 goto pld_literal;
3446 if (rt == 0xf) {
3447 immed = opcode & 0xfff;
3448 goto preload_immediate;
3449 }
3450 if (rn == 0x0f)
3451 goto ldrb_literal;
3452 mnemonic = "LDRB.W";
3453 immed = opcode & 0xfff;
3454 goto ldrxb_immediate_t2;
3455 case 2:
3456 if ((rn & rt) == 0xf) {
3457 immed = opcode & 0xfff;
3458 address = thumb_alignpc4(address);
3459 if (opcode & (1 << 23))
3460 address += immed;
3461 else
3462 address -= immed;
3463 sprintf(cp, "PLI\t%#8.8" PRIx32, address);
3464 return ERROR_OK;
3465 }
3466 if (rn == 0xf && rt != 0xf) {
3467 ldrsb_literal:
3468 immed = opcode & 0xfff;
3469 address = thumb_alignpc4(address);
3470 if (opcode & (1 << 23))
3471 address += immed;
3472 else
3473 address -= immed;
3474 sprintf(cp, "LDRSB\t%#8.8" PRIx32, address);
3475 return ERROR_OK;
3476 }
3477 if (rn == 0xf)
3478 break;
3479 if ((op2 & 0x3c) == 0x38) {
3480 immed = opcode & 0xff;
3481 sprintf(cp, "LDRSBT\tr%d, [r%d, #%d]\t; %#2.2x",
3482 rt, rn, immed, immed);
3483 return ERROR_OK;
3484 }
3485 if ((op2 & 0x3c) == 0x30) {
3486 if (rt == 0xf) {
3487 immed = opcode & 0xff;
3488 immed = -immed; // pli
3489 sprintf(cp, "PLI\t[r%d, #%d]\t; -%#2.2x",
3490 rn, immed, -immed);
3491 return ERROR_OK;
3492 }
3493 mnemonic = "LDRSB";
3494 goto ldrxb_immediate_t3;
3495 }
3496 if ((op2 & 0x24) == 0x24) {
3497 mnemonic = "LDRSB";
3498 goto ldrxb_immediate_t3;
3499 }
3500 if (op2 == 0) {
3501 int rm = opcode & 0xf;
3502
3503 if (rt == 0x0f)
3504 sprintf(cp, "PLI\t");
3505 else
3506 sprintf(cp, "LDRSB.W\tr%d, ", rt);
3507 immed = (opcode >> 4) & 0x3;
3508 cp = strchr(cp, 0);
3509 sprintf(cp, "[r%d, r%d, LSL #%d]", rn, rm, immed);
3510 return ERROR_OK;
3511 }
3512 break;
3513 case 3:
3514 if (rt == 0xf) {
3515 immed = opcode & 0xfff;
3516 sprintf(cp, "PLI\t[r%d, #%d]\t; %#3.3" PRIx32,
3517 rn, immed, immed);
3518 return ERROR_OK;
3519 }
3520 if (rn == 0xf)
3521 goto ldrsb_literal;
3522 immed = opcode & 0xfff;
3523 mnemonic = "LDRSB";
3524 goto ldrxb_immediate_t2;
3525 }
3526
3527 return ERROR_INVALID_ARGUMENTS;
3528 }
3529
3530 static int t2ev_load_halfword(uint32_t opcode, uint32_t address,
3531 arm_instruction_t *instruction, char *cp)
3532 {
3533 int rn = (opcode >> 16) & 0xf;
3534 int rt = (opcode >> 12) & 0xf;
3535 int op2 = (opcode >> 6) & 0x3f;
3536 char *sign = "";
3537 unsigned immed;
3538
3539 if (rt == 0xf) {
3540 sprintf(cp, "HINT (UNALLOCATED)");
3541 return ERROR_OK;
3542 }
3543
3544 if (opcode & (1 << 24))
3545 sign = "S";
3546
3547 if ((opcode & (1 << 23)) == 0) {
3548 if (rn == 0xf) {
3549 ldrh_literal:
3550 immed = opcode & 0xfff;
3551 address = thumb_alignpc4(address);
3552 if (opcode & (1 << 23))
3553 address += immed;
3554 else
3555 address -= immed;
3556 sprintf(cp, "LDR%sH\tr%d, %#8.8" PRIx32,
3557 sign, rt, address);
3558 return ERROR_OK;
3559 }
3560 if (op2 == 0) {
3561 int rm = opcode & 0xf;
3562
3563 immed = (opcode >> 4) & 0x3;
3564 sprintf(cp, "LDR%sH.W\tr%d, [r%d, r%d, LSL #%d]",
3565 sign, rt, rn, rm, immed);
3566 return ERROR_OK;
3567 }
3568 if ((op2 & 0x3c) == 0x38) {
3569 immed = opcode & 0xff;
3570 sprintf(cp, "LDR%sHT\tr%d, [r%d, #%d]\t; %#2.2x",
3571 sign, rt, rn, immed, immed);
3572 return ERROR_OK;
3573 }
3574 if ((op2 & 0x3c) == 0x30 || (op2 & 0x24) == 0x24) {
3575 char *p1 = "", *p2 = "]";
3576
3577 immed = opcode & 0xff;
3578 if (!(opcode & 0x200))
3579 immed = -immed;
3580
3581 /* two indexed modes will write back rn */
3582 if (opcode & 0x100) {
3583 if (opcode & 0x400) /* pre-indexed */
3584 p2 = "]!";
3585 else { /* post-indexed */
3586 p1 = "]";
3587 p2 = "";
3588 }
3589 }
3590 sprintf(cp, "LDR%sH\tr%d, [r%d%s, #%d%s\t; %#8.8x",
3591 sign, rt, rn, p1, immed, p2, immed);
3592 return ERROR_OK;
3593 }
3594 } else {
3595 if (rn == 0xf)
3596 goto ldrh_literal;
3597
3598 immed = opcode & 0xfff;
3599 sprintf(cp, "LDR%sH%s\tr%d, [r%d, #%d]\t; %#6.6x",
3600 sign, *sign ? "" : ".W",
3601 rt, rn, immed, immed);
3602 return ERROR_OK;
3603 }
3604
3605 return ERROR_INVALID_ARGUMENTS;
3606 }
3607
3608 /*
3609 * REVISIT for Thumb2 instructions, instruction->type and friends aren't
3610 * always set. That means eventual arm_simulate_step() support for Thumb2
3611 * will need work in this area.
3612 */
3613 int thumb2_opcode(target_t *target, uint32_t address, arm_instruction_t *instruction)
3614 {
3615 int retval;
3616 uint16_t op;
3617 uint32_t opcode;
3618 char *cp;
3619
3620 /* clear low bit ... it's set on function pointers */
3621 address &= ~1;
3622
3623 /* clear fields, to avoid confusion */
3624 memset(instruction, 0, sizeof(arm_instruction_t));
3625
3626 /* read first halfword, see if this is the only one */
3627 retval = target_read_u16(target, address, &op);
3628 if (retval != ERROR_OK)
3629 return retval;
3630
3631 switch (op & 0xf800) {
3632 case 0xf800:
3633 case 0xf000:
3634 case 0xe800:
3635 /* 32-bit instructions */
3636 instruction->instruction_size = 4;
3637 opcode = op << 16;
3638 retval = target_read_u16(target, address + 2, &op);
3639 if (retval != ERROR_OK)
3640 return retval;
3641 opcode |= op;
3642 instruction->opcode = opcode;
3643 break;
3644 default:
3645 /* 16-bit: Thumb1 + IT + CBZ/CBNZ + ... */
3646 return thumb_evaluate_opcode(op, address, instruction);
3647 }
3648
3649 snprintf(instruction->text, 128,
3650 "0x%8.8" PRIx32 " 0x%8.8" PRIx32 "\t",
3651 address, opcode);
3652 cp = strchr(instruction->text, 0);
3653 retval = ERROR_FAIL;
3654
3655 /* ARMv7-M: A5.3.1 Data processing (modified immediate) */
3656 if ((opcode & 0x1a008000) == 0x10000000)
3657 retval = t2ev_data_mod_immed(opcode, address, instruction, cp);
3658
3659 /* ARMv7-M: A5.3.3 Data processing (plain binary immediate) */
3660 else if ((opcode & 0x1a008000) == 0x12000000)
3661 retval = t2ev_data_immed(opcode, address, instruction, cp);
3662
3663 /* ARMv7-M: A5.3.4 Branches and miscellaneous control */
3664 else if ((opcode & 0x18008000) == 0x10008000)
3665 retval = t2ev_b_misc(opcode, address, instruction, cp);
3666
3667 /* ARMv7-M: A5.3.5 Load/store multiple */
3668 else if ((opcode & 0x1e400000) == 0x08000000)
3669 retval = t2ev_ldm_stm(opcode, address, instruction, cp);
3670
3671 /* ARMv7-M: A5.3.7 Load word */
3672 else if ((opcode & 0x1f700000) == 0x18500000)
3673 retval = t2ev_load_word(opcode, address, instruction, cp);
3674
3675 /* ARMv7-M: A5.3.8 Load halfword, unallocated memory hints */
3676 else if ((opcode & 0x1e700000) == 0x18300000)
3677 retval = t2ev_load_halfword(opcode, address, instruction, cp);
3678
3679 /* ARMv7-M: A5.3.9 Load byte, memory hints */
3680 else if ((opcode & 0x1e700000) == 0x18100000)
3681 retval = t2ev_load_byte_hints(opcode, address, instruction, cp);
3682
3683 /* ARMv7-M: A5.3.10 Store single data item */
3684 else if ((opcode & 0x1f100000) == 0x18000000)
3685 retval = t2ev_store_single(opcode, address, instruction, cp);
3686
3687 /* ARMv7-M: A5.3.11 Data processing (shifted register) */
3688 else if ((opcode & 0x1e000000) == 0x0a000000)
3689 retval = t2ev_data_shift(opcode, address, instruction, cp);
3690
3691 /* ARMv7-M: A5.3.12 Data processing (register)
3692 * and A5.3.13 Miscellaneous operations
3693 */
3694 else if ((opcode & 0x1f000000) == 0x1a000000)
3695 retval = t2ev_data_reg(opcode, address, instruction, cp);
3696
3697 /* ARMv7-M: A5.3.14 Multiply, and multiply accumulate */
3698 else if ((opcode & 0x1f800000) == 0x1b000000)
3699 retval = t2ev_mul32(opcode, address, instruction, cp);
3700
3701 /* ARMv7-M: A5.3.15 Long multiply, long multiply accumulate, divide */
3702 else if ((opcode & 0x1f800000) == 0x1b800000)
3703 retval = t2ev_mul64_div(opcode, address, instruction, cp);
3704
3705 /* FIXME decode more 32-bit instructions */
3706
3707 if (retval == ERROR_OK)
3708 return retval;
3709
3710 if (retval == ERROR_INVALID_ARGUMENTS) {
3711 instruction->type = ARM_UNDEFINED_INSTRUCTION;
3712 strcpy(cp, "UNDEFINED OPCODE");
3713 return ERROR_OK;
3714 }
3715
3716 LOG_DEBUG("Can't decode 32-bit Thumb2 yet (opcode=%08" PRIx32 ")",
3717 opcode);
3718
3719 strcpy(cp, "(32-bit Thumb2 ...)");
3720 return ERROR_OK;
3721 }
3722
3723 int arm_access_size(arm_instruction_t *instruction)
3724 {
3725 if ((instruction->type == ARM_LDRB)
3726 || (instruction->type == ARM_LDRBT)
3727 || (instruction->type == ARM_LDRSB)
3728 || (instruction->type == ARM_STRB)
3729 || (instruction->type == ARM_STRBT))
3730 {
3731 return 1;
3732 }
3733 else if ((instruction->type == ARM_LDRH)
3734 || (instruction->type == ARM_LDRSH)
3735 || (instruction->type == ARM_STRH))
3736 {
3737 return 2;
3738 }
3739 else if ((instruction->type == ARM_LDR)
3740 || (instruction->type == ARM_LDRT)
3741 || (instruction->type == ARM_STR)
3742 || (instruction->type == ARM_STRT))
3743 {
3744 return 4;
3745 }
3746 else if ((instruction->type == ARM_LDRD)
3747 || (instruction->type == ARM_STRD))
3748 {
3749 return 8;
3750 }
3751 else
3752 {
3753 LOG_ERROR("BUG: instruction type %i isn't a load/store instruction", instruction->type);
3754 return 0;
3755 }
3756 }

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)