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

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)