David Brownell <david-b@pacbell.net>:
[openocd.git] / src / target / arm_disassembler.c
1 /***************************************************************************
2 * Copyright (C) 2006 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "target.h"
25 #include "arm_disassembler.h"
26 #include "log.h"
27
28
29 /* textual represenation of the condition field */
30 /* ALways (default) is ommitted (empty string) */
31 char *arm_condition_strings[] =
32 {
33 "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", "HI", "LS", "GE", "LT", "GT", "LE", "", "NV"
34 };
35
36 /* make up for C's missing ROR */
37 uint32_t ror(uint32_t value, int places)
38 {
39 return (value >> places) | (value << (32 - places));
40 }
41
42 int evaluate_pld(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
43 {
44 /* PLD */
45 if ((opcode & 0x0d70f0000) == 0x0550f000)
46 {
47 instruction->type = ARM_PLD;
48
49 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD ...TODO...", address, opcode);
50
51 return ERROR_OK;
52 }
53 else
54 {
55 instruction->type = ARM_UNDEFINED_INSTRUCTION;
56 return ERROR_OK;
57 }
58
59 LOG_ERROR("should never reach this point");
60 return -1;
61 }
62
63 int evaluate_swi(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
64 {
65 instruction->type = ARM_SWI;
66
67 snprintf(instruction->text, 128,
68 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSVC %#6.6" PRIx32,
69 address, opcode, (opcode & 0xffffff));
70
71 return ERROR_OK;
72 }
73
74 int evaluate_blx_imm(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
75 {
76 int offset;
77 uint32_t immediate;
78 uint32_t target_address;
79
80 instruction->type = ARM_BLX;
81 immediate = opcode & 0x00ffffff;
82
83 /* sign extend 24-bit immediate */
84 if (immediate & 0x00800000)
85 offset = 0xff000000 | immediate;
86 else
87 offset = immediate;
88
89 /* shift two bits left */
90 offset <<= 2;
91
92 /* odd/event halfword */
93 if (opcode & 0x01000000)
94 offset |= 0x2;
95
96 target_address = address + 8 + offset;
97
98 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX 0x%8.8" PRIx32 "", address, opcode, target_address);
99
100 instruction->info.b_bl_bx_blx.reg_operand = -1;
101 instruction->info.b_bl_bx_blx.target_address = target_address;
102
103 return ERROR_OK;
104 }
105
106 int evaluate_b_bl(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
107 {
108 uint8_t L;
109 uint32_t immediate;
110 int offset;
111 uint32_t target_address;
112
113 immediate = opcode & 0x00ffffff;
114 L = (opcode & 0x01000000) >> 24;
115
116 /* sign extend 24-bit immediate */
117 if (immediate & 0x00800000)
118 offset = 0xff000000 | immediate;
119 else
120 offset = immediate;
121
122 /* shift two bits left */
123 offset <<= 2;
124
125 target_address = address + 8 + offset;
126
127 if (L)
128 instruction->type = ARM_BL;
129 else
130 instruction->type = ARM_B;
131
132 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tB%s%s 0x%8.8" PRIx32 , address, opcode,
133 (L) ? "L" : "", COND(opcode), target_address);
134
135 instruction->info.b_bl_bx_blx.reg_operand = -1;
136 instruction->info.b_bl_bx_blx.target_address = target_address;
137
138 return ERROR_OK;
139 }
140
141 /* Coprocessor load/store and double register transfers */
142 /* both normal and extended instruction space (condition field b1111) */
143 int evaluate_ldc_stc_mcrr_mrrc(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
144 {
145 uint8_t cp_num = (opcode & 0xf00) >> 8;
146
147 /* MCRR or MRRC */
148 if (((opcode & 0x0ff00000) == 0x0c400000) || ((opcode & 0x0ff00000) == 0x0c400000))
149 {
150 uint8_t cp_opcode, Rd, Rn, CRm;
151 char *mnemonic;
152
153 cp_opcode = (opcode & 0xf0) >> 4;
154 Rd = (opcode & 0xf000) >> 12;
155 Rn = (opcode & 0xf0000) >> 16;
156 CRm = (opcode & 0xf);
157
158 /* MCRR */
159 if ((opcode & 0x0ff00000) == 0x0c400000)
160 {
161 instruction->type = ARM_MCRR;
162 mnemonic = "MCRR";
163 }
164
165 /* MRRC */
166 if ((opcode & 0x0ff00000) == 0x0c500000)
167 {
168 instruction->type = ARM_MRRC;
169 mnemonic = "MRRC";
170 }
171
172 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, %x, r%i, r%i, c%i",
173 address, opcode, mnemonic, COND(opcode), cp_num, cp_opcode, Rd, Rn, CRm);
174 }
175 else /* LDC or STC */
176 {
177 uint8_t CRd, Rn, offset;
178 uint8_t U, N;
179 char *mnemonic;
180 char addressing_mode[32];
181
182 CRd = (opcode & 0xf000) >> 12;
183 Rn = (opcode & 0xf0000) >> 16;
184 offset = (opcode & 0xff);
185
186 /* load/store */
187 if (opcode & 0x00100000)
188 {
189 instruction->type = ARM_LDC;
190 mnemonic = "LDC";
191 }
192 else
193 {
194 instruction->type = ARM_STC;
195 mnemonic = "STC";
196 }
197
198 U = (opcode & 0x00800000) >> 23;
199 N = (opcode & 0x00400000) >> 22;
200
201 /* addressing modes */
202 if ((opcode & 0x01200000) == 0x01000000) /* immediate offset */
203 snprintf(addressing_mode, 32, "[r%i, #%s0x%2.2x*4]", Rn, (U) ? "" : "-", offset);
204 else if ((opcode & 0x01200000) == 0x01200000) /* immediate pre-indexed */
205 snprintf(addressing_mode, 32, "[r%i, #%s0x%2.2x*4]!", Rn, (U) ? "" : "-", offset);
206 else if ((opcode & 0x01200000) == 0x00200000) /* immediate post-indexed */
207 snprintf(addressing_mode, 32, "[r%i], #%s0x%2.2x*4", Rn, (U) ? "" : "-", offset);
208 else if ((opcode & 0x01200000) == 0x00000000) /* unindexed */
209 snprintf(addressing_mode, 32, "[r%i], #0x%2.2x", Rn, offset);
210
211 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s p%i, c%i, %s",
212 address, opcode, mnemonic, ((opcode & 0xf0000000) == 0xf0000000) ? COND(opcode) : "2",
213 (N) ? "L" : "",
214 cp_num, CRd, addressing_mode);
215 }
216
217 return ERROR_OK;
218 }
219
220 /* Coprocessor data processing instructions */
221 /* Coprocessor register transfer instructions */
222 /* both normal and extended instruction space (condition field b1111) */
223 int evaluate_cdp_mcr_mrc(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
224 {
225 char* cond;
226 char* mnemonic;
227 uint8_t cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2;
228
229 cond = ((opcode & 0xf0000000) == 0xf0000000) ? "2" : COND(opcode);
230 cp_num = (opcode & 0xf00) >> 8;
231 CRd_Rd = (opcode & 0xf000) >> 12;
232 CRn = (opcode & 0xf0000) >> 16;
233 CRm = (opcode & 0xf);
234 opcode_2 = (opcode & 0xe0) >> 5;
235
236 /* CDP or MRC/MCR */
237 if (opcode & 0x00000010) /* bit 4 set -> MRC/MCR */
238 {
239 if (opcode & 0x00100000) /* bit 20 set -> MRC */
240 {
241 instruction->type = ARM_MRC;
242 mnemonic = "MRC";
243 }
244 else /* bit 20 not set -> MCR */
245 {
246 instruction->type = ARM_MCR;
247 mnemonic = "MCR";
248 }
249
250 opcode_1 = (opcode & 0x00e00000) >> 21;
251
252 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",
253 address, opcode, mnemonic, cond,
254 cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2);
255 }
256 else /* bit 4 not set -> CDP */
257 {
258 instruction->type = ARM_CDP;
259 mnemonic = "CDP";
260
261 opcode_1 = (opcode & 0x00f00000) >> 20;
262
263 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",
264 address, opcode, mnemonic, cond,
265 cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2);
266 }
267
268 return ERROR_OK;
269 }
270
271 /* Load/store instructions */
272 int evaluate_load_store(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
273 {
274 uint8_t I, P, U, B, W, L;
275 uint8_t Rn, Rd;
276 char *operation; /* "LDR" or "STR" */
277 char *suffix; /* "", "B", "T", "BT" */
278 char offset[32];
279
280 /* examine flags */
281 I = (opcode & 0x02000000) >> 25;
282 P = (opcode & 0x01000000) >> 24;
283 U = (opcode & 0x00800000) >> 23;
284 B = (opcode & 0x00400000) >> 22;
285 W = (opcode & 0x00200000) >> 21;
286 L = (opcode & 0x00100000) >> 20;
287
288 /* target register */
289 Rd = (opcode & 0xf000) >> 12;
290
291 /* base register */
292 Rn = (opcode & 0xf0000) >> 16;
293
294 instruction->info.load_store.Rd = Rd;
295 instruction->info.load_store.Rn = Rn;
296 instruction->info.load_store.U = U;
297
298 /* determine operation */
299 if (L)
300 operation = "LDR";
301 else
302 operation = "STR";
303
304 /* determine instruction type and suffix */
305 if (B)
306 {
307 if ((P == 0) && (W == 1))
308 {
309 if (L)
310 instruction->type = ARM_LDRBT;
311 else
312 instruction->type = ARM_STRBT;
313 suffix = "BT";
314 }
315 else
316 {
317 if (L)
318 instruction->type = ARM_LDRB;
319 else
320 instruction->type = ARM_STRB;
321 suffix = "B";
322 }
323 }
324 else
325 {
326 if ((P == 0) && (W == 1))
327 {
328 if (L)
329 instruction->type = ARM_LDRT;
330 else
331 instruction->type = ARM_STRT;
332 suffix = "T";
333 }
334 else
335 {
336 if (L)
337 instruction->type = ARM_LDR;
338 else
339 instruction->type = ARM_STR;
340 suffix = "";
341 }
342 }
343
344 if (!I) /* #+-<offset_12> */
345 {
346 uint32_t offset_12 = (opcode & 0xfff);
347 if (offset_12)
348 snprintf(offset, 32, ", #%s0x%" PRIx32 "", (U) ? "" : "-", offset_12);
349 else
350 snprintf(offset, 32, "%s", "");
351
352 instruction->info.load_store.offset_mode = 0;
353 instruction->info.load_store.offset.offset = offset_12;
354 }
355 else /* either +-<Rm> or +-<Rm>, <shift>, #<shift_imm> */
356 {
357 uint8_t shift_imm, shift;
358 uint8_t Rm;
359
360 shift_imm = (opcode & 0xf80) >> 7;
361 shift = (opcode & 0x60) >> 5;
362 Rm = (opcode & 0xf);
363
364 /* LSR encodes a shift by 32 bit as 0x0 */
365 if ((shift == 0x1) && (shift_imm == 0x0))
366 shift_imm = 0x20;
367
368 /* ASR encodes a shift by 32 bit as 0x0 */
369 if ((shift == 0x2) && (shift_imm == 0x0))
370 shift_imm = 0x20;
371
372 /* ROR by 32 bit is actually a RRX */
373 if ((shift == 0x3) && (shift_imm == 0x0))
374 shift = 0x4;
375
376 instruction->info.load_store.offset_mode = 1;
377 instruction->info.load_store.offset.reg.Rm = Rm;
378 instruction->info.load_store.offset.reg.shift = shift;
379 instruction->info.load_store.offset.reg.shift_imm = shift_imm;
380
381 if ((shift_imm == 0x0) && (shift == 0x0)) /* +-<Rm> */
382 {
383 snprintf(offset, 32, ", %sr%i", (U) ? "" : "-", Rm);
384 }
385 else /* +-<Rm>, <Shift>, #<shift_imm> */
386 {
387 switch (shift)
388 {
389 case 0x0: /* LSL */
390 snprintf(offset, 32, ", %sr%i, LSL #0x%x", (U) ? "" : "-", Rm, shift_imm);
391 break;
392 case 0x1: /* LSR */
393 snprintf(offset, 32, ", %sr%i, LSR #0x%x", (U) ? "" : "-", Rm, shift_imm);
394 break;
395 case 0x2: /* ASR */
396 snprintf(offset, 32, ", %sr%i, ASR #0x%x", (U) ? "" : "-", Rm, shift_imm);
397 break;
398 case 0x3: /* ROR */
399 snprintf(offset, 32, ", %sr%i, ROR #0x%x", (U) ? "" : "-", Rm, shift_imm);
400 break;
401 case 0x4: /* RRX */
402 snprintf(offset, 32, ", %sr%i, RRX", (U) ? "" : "-", Rm);
403 break;
404 }
405 }
406 }
407
408 if (P == 1)
409 {
410 if (W == 0) /* offset */
411 {
412 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]",
413 address, opcode, operation, COND(opcode), suffix,
414 Rd, Rn, offset);
415
416 instruction->info.load_store.index_mode = 0;
417 }
418 else /* pre-indexed */
419 {
420 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]!",
421 address, opcode, operation, COND(opcode), suffix,
422 Rd, Rn, offset);
423
424 instruction->info.load_store.index_mode = 1;
425 }
426 }
427 else /* post-indexed */
428 {
429 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i]%s",
430 address, opcode, operation, COND(opcode), suffix,
431 Rd, Rn, offset);
432
433 instruction->info.load_store.index_mode = 2;
434 }
435
436 return ERROR_OK;
437 }
438
439 /* Miscellaneous load/store instructions */
440 int evaluate_misc_load_store(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
441 {
442 uint8_t P, U, I, W, L, S, H;
443 uint8_t Rn, Rd;
444 char *operation; /* "LDR" or "STR" */
445 char *suffix; /* "H", "SB", "SH", "D" */
446 char offset[32];
447
448 /* examine flags */
449 P = (opcode & 0x01000000) >> 24;
450 U = (opcode & 0x00800000) >> 23;
451 I = (opcode & 0x00400000) >> 22;
452 W = (opcode & 0x00200000) >> 21;
453 L = (opcode & 0x00100000) >> 20;
454 S = (opcode & 0x00000040) >> 6;
455 H = (opcode & 0x00000020) >> 5;
456
457 /* target register */
458 Rd = (opcode & 0xf000) >> 12;
459
460 /* base register */
461 Rn = (opcode & 0xf0000) >> 16;
462
463 instruction->info.load_store.Rd = Rd;
464 instruction->info.load_store.Rn = Rn;
465 instruction->info.load_store.U = U;
466
467 /* determine instruction type and suffix */
468 if (S) /* signed */
469 {
470 if (L) /* load */
471 {
472 if (H)
473 {
474 operation = "LDR";
475 instruction->type = ARM_LDRSH;
476 suffix = "SH";
477 }
478 else
479 {
480 operation = "LDR";
481 instruction->type = ARM_LDRSB;
482 suffix = "SB";
483 }
484 }
485 else /* there are no signed stores, so this is used to encode double-register load/stores */
486 {
487 suffix = "D";
488 if (H)
489 {
490 operation = "STR";
491 instruction->type = ARM_STRD;
492 }
493 else
494 {
495 operation = "LDR";
496 instruction->type = ARM_LDRD;
497 }
498 }
499 }
500 else /* unsigned */
501 {
502 suffix = "H";
503 if (L) /* load */
504 {
505 operation = "LDR";
506 instruction->type = ARM_LDRH;
507 }
508 else /* store */
509 {
510 operation = "STR";
511 instruction->type = ARM_STRH;
512 }
513 }
514
515 if (I) /* Immediate offset/index (#+-<offset_8>)*/
516 {
517 uint32_t offset_8 = ((opcode & 0xf00) >> 4) | (opcode & 0xf);
518 snprintf(offset, 32, "#%s0x%" PRIx32 "", (U) ? "" : "-", offset_8);
519
520 instruction->info.load_store.offset_mode = 0;
521 instruction->info.load_store.offset.offset = offset_8;
522 }
523 else /* Register offset/index (+-<Rm>) */
524 {
525 uint8_t Rm;
526 Rm = (opcode & 0xf);
527 snprintf(offset, 32, "%sr%i", (U) ? "" : "-", Rm);
528
529 instruction->info.load_store.offset_mode = 1;
530 instruction->info.load_store.offset.reg.Rm = Rm;
531 instruction->info.load_store.offset.reg.shift = 0x0;
532 instruction->info.load_store.offset.reg.shift_imm = 0x0;
533 }
534
535 if (P == 1)
536 {
537 if (W == 0) /* offset */
538 {
539 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]",
540 address, opcode, operation, COND(opcode), suffix,
541 Rd, Rn, offset);
542
543 instruction->info.load_store.index_mode = 0;
544 }
545 else /* pre-indexed */
546 {
547 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]!",
548 address, opcode, operation, COND(opcode), suffix,
549 Rd, Rn, offset);
550
551 instruction->info.load_store.index_mode = 1;
552 }
553 }
554 else /* post-indexed */
555 {
556 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i], %s",
557 address, opcode, operation, COND(opcode), suffix,
558 Rd, Rn, offset);
559
560 instruction->info.load_store.index_mode = 2;
561 }
562
563 return ERROR_OK;
564 }
565
566 /* Load/store multiples instructions */
567 int evaluate_ldm_stm(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
568 {
569 uint8_t P, U, S, W, L, Rn;
570 uint32_t register_list;
571 char *addressing_mode;
572 char *mnemonic;
573 char reg_list[69];
574 char *reg_list_p;
575 int i;
576 int first_reg = 1;
577
578 P = (opcode & 0x01000000) >> 24;
579 U = (opcode & 0x00800000) >> 23;
580 S = (opcode & 0x00400000) >> 22;
581 W = (opcode & 0x00200000) >> 21;
582 L = (opcode & 0x00100000) >> 20;
583 register_list = (opcode & 0xffff);
584 Rn = (opcode & 0xf0000) >> 16;
585
586 instruction->info.load_store_multiple.Rn = Rn;
587 instruction->info.load_store_multiple.register_list = register_list;
588 instruction->info.load_store_multiple.S = S;
589 instruction->info.load_store_multiple.W = W;
590
591 if (L)
592 {
593 instruction->type = ARM_LDM;
594 mnemonic = "LDM";
595 }
596 else
597 {
598 instruction->type = ARM_STM;
599 mnemonic = "STM";
600 }
601
602 if (P)
603 {
604 if (U)
605 {
606 instruction->info.load_store_multiple.addressing_mode = 1;
607 addressing_mode = "IB";
608 }
609 else
610 {
611 instruction->info.load_store_multiple.addressing_mode = 3;
612 addressing_mode = "DB";
613 }
614 }
615 else
616 {
617 if (U)
618 {
619 instruction->info.load_store_multiple.addressing_mode = 0;
620 /* "IA" is the default in UAL syntax */
621 addressing_mode = "";
622 }
623 else
624 {
625 instruction->info.load_store_multiple.addressing_mode = 2;
626 addressing_mode = "DA";
627 }
628 }
629
630 reg_list_p = reg_list;
631 for (i = 0; i <= 15; i++)
632 {
633 if ((register_list >> i) & 1)
634 {
635 if (first_reg)
636 {
637 first_reg = 0;
638 reg_list_p += snprintf(reg_list_p, (reg_list + 69 - reg_list_p), "r%i", i);
639 }
640 else
641 {
642 reg_list_p += snprintf(reg_list_p, (reg_list + 69 - reg_list_p), ", r%i", i);
643 }
644 }
645 }
646
647 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i%s, {%s}%s",
648 address, opcode, mnemonic, COND(opcode), addressing_mode,
649 Rn, (W) ? "!" : "", reg_list, (S) ? "^" : "");
650
651 return ERROR_OK;
652 }
653
654 /* Multiplies, extra load/stores */
655 int evaluate_mul_and_extra_ld_st(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
656 {
657 /* Multiply (accumulate) (long) and Swap/swap byte */
658 if ((opcode & 0x000000f0) == 0x00000090)
659 {
660 /* Multiply (accumulate) */
661 if ((opcode & 0x0f800000) == 0x00000000)
662 {
663 uint8_t Rm, Rs, Rn, Rd, S;
664 Rm = opcode & 0xf;
665 Rs = (opcode & 0xf00) >> 8;
666 Rn = (opcode & 0xf000) >> 12;
667 Rd = (opcode & 0xf0000) >> 16;
668 S = (opcode & 0x00100000) >> 20;
669
670 /* examine A bit (accumulate) */
671 if (opcode & 0x00200000)
672 {
673 instruction->type = ARM_MLA;
674 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMLA%s%s r%i, r%i, r%i, r%i",
675 address, opcode, COND(opcode), (S) ? "S" : "", Rd, Rm, Rs, Rn);
676 }
677 else
678 {
679 instruction->type = ARM_MUL;
680 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMUL%s%s r%i, r%i, r%i",
681 address, opcode, COND(opcode), (S) ? "S" : "", Rd, Rm, Rs);
682 }
683
684 return ERROR_OK;
685 }
686
687 /* Multiply (accumulate) long */
688 if ((opcode & 0x0f800000) == 0x00800000)
689 {
690 char* mnemonic = NULL;
691 uint8_t Rm, Rs, RdHi, RdLow, S;
692 Rm = opcode & 0xf;
693 Rs = (opcode & 0xf00) >> 8;
694 RdHi = (opcode & 0xf000) >> 12;
695 RdLow = (opcode & 0xf0000) >> 16;
696 S = (opcode & 0x00100000) >> 20;
697
698 switch ((opcode & 0x00600000) >> 21)
699 {
700 case 0x0:
701 instruction->type = ARM_UMULL;
702 mnemonic = "UMULL";
703 break;
704 case 0x1:
705 instruction->type = ARM_UMLAL;
706 mnemonic = "UMLAL";
707 break;
708 case 0x2:
709 instruction->type = ARM_SMULL;
710 mnemonic = "SMULL";
711 break;
712 case 0x3:
713 instruction->type = ARM_SMLAL;
714 mnemonic = "SMLAL";
715 break;
716 }
717
718 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, r%i, r%i",
719 address, opcode, mnemonic, COND(opcode), (S) ? "S" : "",
720 RdLow, RdHi, Rm, Rs);
721
722 return ERROR_OK;
723 }
724
725 /* Swap/swap byte */
726 if ((opcode & 0x0f800000) == 0x01000000)
727 {
728 uint8_t Rm, Rd, Rn;
729 Rm = opcode & 0xf;
730 Rd = (opcode & 0xf000) >> 12;
731 Rn = (opcode & 0xf0000) >> 16;
732
733 /* examine B flag */
734 instruction->type = (opcode & 0x00400000) ? ARM_SWPB : ARM_SWP;
735
736 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, [r%i]",
737 address, opcode, (opcode & 0x00400000) ? "SWPB" : "SWP", COND(opcode), Rd, Rm, Rn);
738 return ERROR_OK;
739 }
740
741 }
742
743 return evaluate_misc_load_store(opcode, address, instruction);
744 }
745
746 int evaluate_mrs_msr(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
747 {
748 int R = (opcode & 0x00400000) >> 22;
749 char *PSR = (R) ? "SPSR" : "CPSR";
750
751 /* Move register to status register (MSR) */
752 if (opcode & 0x00200000)
753 {
754 instruction->type = ARM_MSR;
755
756 /* immediate variant */
757 if (opcode & 0x02000000)
758 {
759 uint8_t immediate = (opcode & 0xff);
760 uint8_t rotate = (opcode & 0xf00);
761
762 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, 0x%8.8" PRIx32 ,
763 address, opcode, COND(opcode), PSR,
764 (opcode & 0x10000) ? "c" : "",
765 (opcode & 0x20000) ? "x" : "",
766 (opcode & 0x40000) ? "s" : "",
767 (opcode & 0x80000) ? "f" : "",
768 ror(immediate, (rotate * 2))
769 );
770 }
771 else /* register variant */
772 {
773 uint8_t Rm = opcode & 0xf;
774 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, r%i",
775 address, opcode, COND(opcode), PSR,
776 (opcode & 0x10000) ? "c" : "",
777 (opcode & 0x20000) ? "x" : "",
778 (opcode & 0x40000) ? "s" : "",
779 (opcode & 0x80000) ? "f" : "",
780 Rm
781 );
782 }
783
784 }
785 else /* Move status register to register (MRS) */
786 {
787 uint8_t Rd;
788
789 instruction->type = ARM_MRS;
790 Rd = (opcode & 0x0000f000) >> 12;
791
792 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMRS%s r%i, %s",
793 address, opcode, COND(opcode), Rd, PSR);
794 }
795
796 return ERROR_OK;
797 }
798
799 /* Miscellaneous instructions */
800 int evaluate_misc_instr(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
801 {
802 /* MRS/MSR */
803 if ((opcode & 0x000000f0) == 0x00000000)
804 {
805 evaluate_mrs_msr(opcode, address, instruction);
806 }
807
808 /* BX */
809 if ((opcode & 0x006000f0) == 0x00200010)
810 {
811 uint8_t Rm;
812 instruction->type = ARM_BX;
813 Rm = opcode & 0xf;
814
815 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBX%s r%i",
816 address, opcode, COND(opcode), Rm);
817
818 instruction->info.b_bl_bx_blx.reg_operand = Rm;
819 instruction->info.b_bl_bx_blx.target_address = -1;
820 }
821
822 /* CLZ */
823 if ((opcode & 0x006000f0) == 0x00600010)
824 {
825 uint8_t Rm, Rd;
826 instruction->type = ARM_CLZ;
827 Rm = opcode & 0xf;
828 Rd = (opcode & 0xf000) >> 12;
829
830 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCLZ%s r%i, r%i",
831 address, opcode, COND(opcode), Rd, Rm);
832 }
833
834 /* BLX(2) */
835 if ((opcode & 0x006000f0) == 0x00200030)
836 {
837 uint8_t Rm;
838 instruction->type = ARM_BLX;
839 Rm = opcode & 0xf;
840
841 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX%s r%i",
842 address, opcode, COND(opcode), Rm);
843
844 instruction->info.b_bl_bx_blx.reg_operand = Rm;
845 instruction->info.b_bl_bx_blx.target_address = -1;
846 }
847
848 /* Enhanced DSP add/subtracts */
849 if ((opcode & 0x0000000f0) == 0x00000050)
850 {
851 uint8_t Rm, Rd, Rn;
852 char *mnemonic = NULL;
853 Rm = opcode & 0xf;
854 Rd = (opcode & 0xf000) >> 12;
855 Rn = (opcode & 0xf0000) >> 16;
856
857 switch ((opcode & 0x00600000) >> 21)
858 {
859 case 0x0:
860 instruction->type = ARM_QADD;
861 mnemonic = "QADD";
862 break;
863 case 0x1:
864 instruction->type = ARM_QSUB;
865 mnemonic = "QSUB";
866 break;
867 case 0x2:
868 instruction->type = ARM_QDADD;
869 mnemonic = "QDADD";
870 break;
871 case 0x3:
872 instruction->type = ARM_QDSUB;
873 mnemonic = "QDSUB";
874 break;
875 }
876
877 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, r%i",
878 address, opcode, mnemonic, COND(opcode), Rd, Rm, Rn);
879 }
880
881 /* Software breakpoints */
882 if ((opcode & 0x0000000f0) == 0x00000070)
883 {
884 uint32_t immediate;
885 instruction->type = ARM_BKPT;
886 immediate = ((opcode & 0x000fff00) >> 4) | (opcode & 0xf);
887
888 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBKPT 0x%4.4" PRIx32 "",
889 address, opcode, immediate);
890 }
891
892 /* Enhanced DSP multiplies */
893 if ((opcode & 0x000000090) == 0x00000080)
894 {
895 int x = (opcode & 0x20) >> 5;
896 int y = (opcode & 0x40) >> 6;
897
898 /* SMLA < x><y> */
899 if ((opcode & 0x00600000) == 0x00000000)
900 {
901 uint8_t Rd, Rm, Rs, Rn;
902 instruction->type = ARM_SMLAxy;
903 Rd = (opcode & 0xf0000) >> 16;
904 Rm = (opcode & 0xf);
905 Rs = (opcode & 0xf00) >> 8;
906 Rn = (opcode & 0xf000) >> 12;
907
908 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
909 address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
910 Rd, Rm, Rs, Rn);
911 }
912
913 /* SMLAL < x><y> */
914 if ((opcode & 0x00600000) == 0x00400000)
915 {
916 uint8_t RdLow, RdHi, Rm, Rs;
917 instruction->type = ARM_SMLAxy;
918 RdHi = (opcode & 0xf0000) >> 16;
919 RdLow = (opcode & 0xf000) >> 12;
920 Rm = (opcode & 0xf);
921 Rs = (opcode & 0xf00) >> 8;
922
923 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
924 address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
925 RdLow, RdHi, Rm, Rs);
926 }
927
928 /* SMLAW < y> */
929 if (((opcode & 0x00600000) == 0x00100000) && (x == 0))
930 {
931 uint8_t Rd, Rm, Rs, Rn;
932 instruction->type = ARM_SMLAWy;
933 Rd = (opcode & 0xf0000) >> 16;
934 Rm = (opcode & 0xf);
935 Rs = (opcode & 0xf00) >> 8;
936 Rn = (opcode & 0xf000) >> 12;
937
938 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLAW%s%s r%i, r%i, r%i, r%i",
939 address, opcode, (y) ? "T" : "B", COND(opcode),
940 Rd, Rm, Rs, Rn);
941 }
942
943 /* SMUL < x><y> */
944 if ((opcode & 0x00600000) == 0x00300000)
945 {
946 uint8_t Rd, Rm, Rs;
947 instruction->type = ARM_SMULxy;
948 Rd = (opcode & 0xf0000) >> 16;
949 Rm = (opcode & 0xf);
950 Rs = (opcode & 0xf00) >> 8;
951
952 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s%s r%i, r%i, r%i",
953 address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
954 Rd, Rm, Rs);
955 }
956
957 /* SMULW < y> */
958 if (((opcode & 0x00600000) == 0x00100000) && (x == 1))
959 {
960 uint8_t Rd, Rm, Rs;
961 instruction->type = ARM_SMULWy;
962 Rd = (opcode & 0xf0000) >> 16;
963 Rm = (opcode & 0xf);
964 Rs = (opcode & 0xf00) >> 8;
965
966 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s r%i, r%i, r%i",
967 address, opcode, (y) ? "T" : "B", COND(opcode),
968 Rd, Rm, Rs);
969 }
970 }
971
972 return ERROR_OK;
973 }
974
975 int evaluate_data_proc(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
976 {
977 uint8_t I, op, S, Rn, Rd;
978 char *mnemonic = NULL;
979 char shifter_operand[32];
980
981 I = (opcode & 0x02000000) >> 25;
982 op = (opcode & 0x01e00000) >> 21;
983 S = (opcode & 0x00100000) >> 20;
984
985 Rd = (opcode & 0xf000) >> 12;
986 Rn = (opcode & 0xf0000) >> 16;
987
988 instruction->info.data_proc.Rd = Rd;
989 instruction->info.data_proc.Rn = Rn;
990 instruction->info.data_proc.S = S;
991
992 switch (op)
993 {
994 case 0x0:
995 instruction->type = ARM_AND;
996 mnemonic = "AND";
997 break;
998 case 0x1:
999 instruction->type = ARM_EOR;
1000 mnemonic = "EOR";
1001 break;
1002 case 0x2:
1003 instruction->type = ARM_SUB;
1004 mnemonic = "SUB";
1005 break;
1006 case 0x3:
1007 instruction->type = ARM_RSB;
1008 mnemonic = "RSB";
1009 break;
1010 case 0x4:
1011 instruction->type = ARM_ADD;
1012 mnemonic = "ADD";
1013 break;
1014 case 0x5:
1015 instruction->type = ARM_ADC;
1016 mnemonic = "ADC";
1017 break;
1018 case 0x6:
1019 instruction->type = ARM_SBC;
1020 mnemonic = "SBC";
1021 break;
1022 case 0x7:
1023 instruction->type = ARM_RSC;
1024 mnemonic = "RSC";
1025 break;
1026 case 0x8:
1027 instruction->type = ARM_TST;
1028 mnemonic = "TST";
1029 break;
1030 case 0x9:
1031 instruction->type = ARM_TEQ;
1032 mnemonic = "TEQ";
1033 break;
1034 case 0xa:
1035 instruction->type = ARM_CMP;
1036 mnemonic = "CMP";
1037 break;
1038 case 0xb:
1039 instruction->type = ARM_CMN;
1040 mnemonic = "CMN";
1041 break;
1042 case 0xc:
1043 instruction->type = ARM_ORR;
1044 mnemonic = "ORR";
1045 break;
1046 case 0xd:
1047 instruction->type = ARM_MOV;
1048 mnemonic = "MOV";
1049 break;
1050 case 0xe:
1051 instruction->type = ARM_BIC;
1052 mnemonic = "BIC";
1053 break;
1054 case 0xf:
1055 instruction->type = ARM_MVN;
1056 mnemonic = "MVN";
1057 break;
1058 }
1059
1060 if (I) /* immediate shifter operand (#<immediate>)*/
1061 {
1062 uint8_t immed_8 = opcode & 0xff;
1063 uint8_t rotate_imm = (opcode & 0xf00) >> 8;
1064 uint32_t immediate;
1065
1066 immediate = ror(immed_8, rotate_imm * 2);
1067
1068 snprintf(shifter_operand, 32, "#0x%" PRIx32 "", immediate);
1069
1070 instruction->info.data_proc.variant = 0;
1071 instruction->info.data_proc.shifter_operand.immediate.immediate = immediate;
1072 }
1073 else /* register-based shifter operand */
1074 {
1075 uint8_t shift, Rm;
1076 shift = (opcode & 0x60) >> 5;
1077 Rm = (opcode & 0xf);
1078
1079 if ((opcode & 0x10) != 0x10) /* Immediate shifts ("<Rm>" or "<Rm>, <shift> #<shift_immediate>") */
1080 {
1081 uint8_t shift_imm;
1082 shift_imm = (opcode & 0xf80) >> 7;
1083
1084 instruction->info.data_proc.variant = 1;
1085 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1086 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = shift_imm;
1087 instruction->info.data_proc.shifter_operand.immediate_shift.shift = shift;
1088
1089 /* LSR encodes a shift by 32 bit as 0x0 */
1090 if ((shift == 0x1) && (shift_imm == 0x0))
1091 shift_imm = 0x20;
1092
1093 /* ASR encodes a shift by 32 bit as 0x0 */
1094 if ((shift == 0x2) && (shift_imm == 0x0))
1095 shift_imm = 0x20;
1096
1097 /* ROR by 32 bit is actually a RRX */
1098 if ((shift == 0x3) && (shift_imm == 0x0))
1099 shift = 0x4;
1100
1101 if ((shift_imm == 0x0) && (shift == 0x0))
1102 {
1103 snprintf(shifter_operand, 32, "r%i", Rm);
1104 }
1105 else
1106 {
1107 if (shift == 0x0) /* LSL */
1108 {
1109 snprintf(shifter_operand, 32, "r%i, LSL #0x%x", Rm, shift_imm);
1110 }
1111 else if (shift == 0x1) /* LSR */
1112 {
1113 snprintf(shifter_operand, 32, "r%i, LSR #0x%x", Rm, shift_imm);
1114 }
1115 else if (shift == 0x2) /* ASR */
1116 {
1117 snprintf(shifter_operand, 32, "r%i, ASR #0x%x", Rm, shift_imm);
1118 }
1119 else if (shift == 0x3) /* ROR */
1120 {
1121 snprintf(shifter_operand, 32, "r%i, ROR #0x%x", Rm, shift_imm);
1122 }
1123 else if (shift == 0x4) /* RRX */
1124 {
1125 snprintf(shifter_operand, 32, "r%i, RRX", Rm);
1126 }
1127 }
1128 }
1129 else /* Register shifts ("<Rm>, <shift> <Rs>") */
1130 {
1131 uint8_t Rs = (opcode & 0xf00) >> 8;
1132
1133 instruction->info.data_proc.variant = 2;
1134 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rm;
1135 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rs;
1136 instruction->info.data_proc.shifter_operand.register_shift.shift = shift;
1137
1138 if (shift == 0x0) /* LSL */
1139 {
1140 snprintf(shifter_operand, 32, "r%i, LSL r%i", Rm, Rs);
1141 }
1142 else if (shift == 0x1) /* LSR */
1143 {
1144 snprintf(shifter_operand, 32, "r%i, LSR r%i", Rm, Rs);
1145 }
1146 else if (shift == 0x2) /* ASR */
1147 {
1148 snprintf(shifter_operand, 32, "r%i, ASR r%i", Rm, Rs);
1149 }
1150 else if (shift == 0x3) /* ROR */
1151 {
1152 snprintf(shifter_operand, 32, "r%i, ROR r%i", Rm, Rs);
1153 }
1154 }
1155 }
1156
1157 if ((op < 0x8) || (op == 0xc) || (op == 0xe)) /* <opcode3>{<cond>}{S} <Rd>, <Rn>, <shifter_operand> */
1158 {
1159 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, %s",
1160 address, opcode, mnemonic, COND(opcode),
1161 (S) ? "S" : "", Rd, Rn, shifter_operand);
1162 }
1163 else if ((op == 0xd) || (op == 0xf)) /* <opcode1>{<cond>}{S} <Rd>, <shifter_operand> */
1164 {
1165 if (opcode == 0xe1a00000) /* print MOV r0,r0 as NOP */
1166 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tNOP",address, opcode);
1167 else
1168 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, %s",
1169 address, opcode, mnemonic, COND(opcode),
1170 (S) ? "S" : "", Rd, shifter_operand);
1171 }
1172 else /* <opcode2>{<cond>} <Rn>, <shifter_operand> */
1173 {
1174 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, %s",
1175 address, opcode, mnemonic, COND(opcode),
1176 Rn, shifter_operand);
1177 }
1178
1179 return ERROR_OK;
1180 }
1181
1182 int arm_evaluate_opcode(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
1183 {
1184 /* clear fields, to avoid confusion */
1185 memset(instruction, 0, sizeof(arm_instruction_t));
1186 instruction->opcode = opcode;
1187 instruction->instruction_size = 4;
1188
1189 /* catch opcodes with condition field [31:28] = b1111 */
1190 if ((opcode & 0xf0000000) == 0xf0000000)
1191 {
1192 /* Undefined instruction (or ARMv5E cache preload PLD) */
1193 if ((opcode & 0x08000000) == 0x00000000)
1194 return evaluate_pld(opcode, address, instruction);
1195
1196 /* Undefined instruction */
1197 if ((opcode & 0x0e000000) == 0x08000000)
1198 {
1199 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1200 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1201 return ERROR_OK;
1202 }
1203
1204 /* Branch and branch with link and change to Thumb */
1205 if ((opcode & 0x0e000000) == 0x0a000000)
1206 return evaluate_blx_imm(opcode, address, instruction);
1207
1208 /* Extended coprocessor opcode space (ARMv5 and higher)*/
1209 /* Coprocessor load/store and double register transfers */
1210 if ((opcode & 0x0e000000) == 0x0c000000)
1211 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1212
1213 /* Coprocessor data processing */
1214 if ((opcode & 0x0f000100) == 0x0c000000)
1215 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1216
1217 /* Coprocessor register transfers */
1218 if ((opcode & 0x0f000010) == 0x0c000010)
1219 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1220
1221 /* Undefined instruction */
1222 if ((opcode & 0x0f000000) == 0x0f000000)
1223 {
1224 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1225 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1226 return ERROR_OK;
1227 }
1228 }
1229
1230 /* catch opcodes with [27:25] = b000 */
1231 if ((opcode & 0x0e000000) == 0x00000000)
1232 {
1233 /* Multiplies, extra load/stores */
1234 if ((opcode & 0x00000090) == 0x00000090)
1235 return evaluate_mul_and_extra_ld_st(opcode, address, instruction);
1236
1237 /* Miscellaneous instructions */
1238 if ((opcode & 0x0f900000) == 0x01000000)
1239 return evaluate_misc_instr(opcode, address, instruction);
1240
1241 return evaluate_data_proc(opcode, address, instruction);
1242 }
1243
1244 /* catch opcodes with [27:25] = b001 */
1245 if ((opcode & 0x0e000000) == 0x02000000)
1246 {
1247 /* Undefined instruction */
1248 if ((opcode & 0x0fb00000) == 0x03000000)
1249 {
1250 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1251 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1252 return ERROR_OK;
1253 }
1254
1255 /* Move immediate to status register */
1256 if ((opcode & 0x0fb00000) == 0x03200000)
1257 return evaluate_mrs_msr(opcode, address, instruction);
1258
1259 return evaluate_data_proc(opcode, address, instruction);
1260
1261 }
1262
1263 /* catch opcodes with [27:25] = b010 */
1264 if ((opcode & 0x0e000000) == 0x04000000)
1265 {
1266 /* Load/store immediate offset */
1267 return evaluate_load_store(opcode, address, instruction);
1268 }
1269
1270 /* catch opcodes with [27:25] = b011 */
1271 if ((opcode & 0x0e000000) == 0x06000000)
1272 {
1273 /* Undefined instruction */
1274 if ((opcode & 0x00000010) == 0x00000010)
1275 {
1276 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1277 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1278 return ERROR_OK;
1279 }
1280
1281 /* Load/store register offset */
1282 return evaluate_load_store(opcode, address, instruction);
1283
1284 }
1285
1286 /* catch opcodes with [27:25] = b100 */
1287 if ((opcode & 0x0e000000) == 0x08000000)
1288 {
1289 /* Load/store multiple */
1290 return evaluate_ldm_stm(opcode, address, instruction);
1291 }
1292
1293 /* catch opcodes with [27:25] = b101 */
1294 if ((opcode & 0x0e000000) == 0x0a000000)
1295 {
1296 /* Branch and branch with link */
1297 return evaluate_b_bl(opcode, address, instruction);
1298 }
1299
1300 /* catch opcodes with [27:25] = b110 */
1301 if ((opcode & 0x0e000000) == 0x0a000000)
1302 {
1303 /* Coprocessor load/store and double register transfers */
1304 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1305 }
1306
1307 /* catch opcodes with [27:25] = b111 */
1308 if ((opcode & 0x0e000000) == 0x0e000000)
1309 {
1310 /* Software interrupt */
1311 if ((opcode & 0x0f000000) == 0x0f000000)
1312 return evaluate_swi(opcode, address, instruction);
1313
1314 /* Coprocessor data processing */
1315 if ((opcode & 0x0f000010) == 0x0e000000)
1316 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1317
1318 /* Coprocessor register transfers */
1319 if ((opcode & 0x0f000010) == 0x0e000010)
1320 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1321 }
1322
1323 LOG_ERROR("should never reach this point");
1324 return -1;
1325 }
1326
1327 int evaluate_b_bl_blx_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1328 {
1329 uint32_t offset = opcode & 0x7ff;
1330 uint32_t opc = (opcode >> 11) & 0x3;
1331 uint32_t target_address;
1332 char *mnemonic = NULL;
1333
1334 /* sign extend 11-bit offset */
1335 if (((opc == 0) || (opc == 2)) && (offset & 0x00000400))
1336 offset = 0xfffff800 | offset;
1337
1338 target_address = address + 4 + (offset << 1);
1339
1340 switch (opc)
1341 {
1342 /* unconditional branch */
1343 case 0:
1344 instruction->type = ARM_B;
1345 mnemonic = "B";
1346 break;
1347 /* BLX suffix */
1348 case 1:
1349 instruction->type = ARM_BLX;
1350 mnemonic = "BLX";
1351 break;
1352 /* BL/BLX prefix */
1353 case 2:
1354 instruction->type = ARM_UNKNOWN_INSTUCTION;
1355 mnemonic = "prefix";
1356 target_address = offset << 12;
1357 break;
1358 /* BL suffix */
1359 case 3:
1360 instruction->type = ARM_BL;
1361 mnemonic = "BL";
1362 break;
1363 }
1364
1365 /* TODO: deal correctly with dual opcode (prefixed) BL/BLX;
1366 * these are effectively 32-bit instructions even in Thumb1.
1367 * Might be simplest to always use the Thumb2 decoder.
1368 */
1369
1370 snprintf(instruction->text, 128,
1371 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%#8.8" PRIx32,
1372 address, opcode, mnemonic, target_address);
1373
1374 instruction->info.b_bl_bx_blx.reg_operand = -1;
1375 instruction->info.b_bl_bx_blx.target_address = target_address;
1376
1377 return ERROR_OK;
1378 }
1379
1380 int evaluate_add_sub_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1381 {
1382 uint8_t Rd = (opcode >> 0) & 0x7;
1383 uint8_t Rn = (opcode >> 3) & 0x7;
1384 uint8_t Rm_imm = (opcode >> 6) & 0x7;
1385 uint32_t opc = opcode & (1 << 9);
1386 uint32_t reg_imm = opcode & (1 << 10);
1387 char *mnemonic;
1388
1389 if (opc)
1390 {
1391 instruction->type = ARM_SUB;
1392 mnemonic = "SUBS";
1393 }
1394 else
1395 {
1396 instruction->type = ARM_ADD;
1397 mnemonic = "ADDS";
1398 }
1399
1400 instruction->info.data_proc.Rd = Rd;
1401 instruction->info.data_proc.Rn = Rn;
1402 instruction->info.data_proc.S = 1;
1403
1404 if (reg_imm)
1405 {
1406 instruction->info.data_proc.variant = 0; /*immediate*/
1407 instruction->info.data_proc.shifter_operand.immediate.immediate = Rm_imm;
1408 snprintf(instruction->text, 128,
1409 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%d",
1410 address, opcode, mnemonic, Rd, Rn, Rm_imm);
1411 }
1412 else
1413 {
1414 instruction->info.data_proc.variant = 1; /*immediate shift*/
1415 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm_imm;
1416 snprintf(instruction->text, 128,
1417 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, r%i",
1418 address, opcode, mnemonic, Rd, Rn, Rm_imm);
1419 }
1420
1421 return ERROR_OK;
1422 }
1423
1424 int evaluate_shift_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1425 {
1426 uint8_t Rd = (opcode >> 0) & 0x7;
1427 uint8_t Rm = (opcode >> 3) & 0x7;
1428 uint8_t imm = (opcode >> 6) & 0x1f;
1429 uint8_t opc = (opcode >> 11) & 0x3;
1430 char *mnemonic = NULL;
1431
1432 switch (opc)
1433 {
1434 case 0:
1435 instruction->type = ARM_MOV;
1436 mnemonic = "LSLS";
1437 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 0;
1438 break;
1439 case 1:
1440 instruction->type = ARM_MOV;
1441 mnemonic = "LSRS";
1442 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 1;
1443 break;
1444 case 2:
1445 instruction->type = ARM_MOV;
1446 mnemonic = "ASRS";
1447 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 2;
1448 break;
1449 }
1450
1451 if ((imm == 0) && (opc != 0))
1452 imm = 32;
1453
1454 instruction->info.data_proc.Rd = Rd;
1455 instruction->info.data_proc.Rn = -1;
1456 instruction->info.data_proc.S = 1;
1457
1458 instruction->info.data_proc.variant = 1; /*immediate_shift*/
1459 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1460 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = imm;
1461
1462 snprintf(instruction->text, 128,
1463 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%#2.2x" ,
1464 address, opcode, mnemonic, Rd, Rm, imm);
1465
1466 return ERROR_OK;
1467 }
1468
1469 int evaluate_data_proc_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1470 {
1471 uint8_t imm = opcode & 0xff;
1472 uint8_t Rd = (opcode >> 8) & 0x7;
1473 uint32_t opc = (opcode >> 11) & 0x3;
1474 char *mnemonic = NULL;
1475
1476 instruction->info.data_proc.Rd = Rd;
1477 instruction->info.data_proc.Rn = Rd;
1478 instruction->info.data_proc.S = 1;
1479 instruction->info.data_proc.variant = 0; /*immediate*/
1480 instruction->info.data_proc.shifter_operand.immediate.immediate = imm;
1481
1482 switch (opc)
1483 {
1484 case 0:
1485 instruction->type = ARM_MOV;
1486 mnemonic = "MOVS";
1487 instruction->info.data_proc.Rn = -1;
1488 break;
1489 case 1:
1490 instruction->type = ARM_CMP;
1491 mnemonic = "CMP";
1492 instruction->info.data_proc.Rd = -1;
1493 break;
1494 case 2:
1495 instruction->type = ARM_ADD;
1496 mnemonic = "ADDS";
1497 break;
1498 case 3:
1499 instruction->type = ARM_SUB;
1500 mnemonic = "SUBS";
1501 break;
1502 }
1503
1504 snprintf(instruction->text, 128,
1505 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, #%#2.2x",
1506 address, opcode, mnemonic, Rd, imm);
1507
1508 return ERROR_OK;
1509 }
1510
1511 int evaluate_data_proc_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1512 {
1513 uint8_t high_reg, op, Rm, Rd,H1,H2;
1514 char *mnemonic = NULL;
1515 bool nop = false;
1516
1517 high_reg = (opcode & 0x0400) >> 10;
1518 op = (opcode & 0x03C0) >> 6;
1519
1520 Rd = (opcode & 0x0007);
1521 Rm = (opcode & 0x0038) >> 3;
1522 H1 = (opcode & 0x0080) >> 7;
1523 H2 = (opcode & 0x0040) >> 6;
1524
1525 instruction->info.data_proc.Rd = Rd;
1526 instruction->info.data_proc.Rn = Rd;
1527 instruction->info.data_proc.S = (!high_reg || (instruction->type == ARM_CMP));
1528 instruction->info.data_proc.variant = 1 /*immediate shift*/;
1529 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1530
1531 if (high_reg)
1532 {
1533 Rd |= H1 << 3;
1534 Rm |= H2 << 3;
1535 op >>= 2;
1536
1537 switch (op)
1538 {
1539 case 0x0:
1540 instruction->type = ARM_ADD;
1541 mnemonic = "ADD";
1542 break;
1543 case 0x1:
1544 instruction->type = ARM_CMP;
1545 mnemonic = "CMP";
1546 break;
1547 case 0x2:
1548 instruction->type = ARM_MOV;
1549 mnemonic = "MOV";
1550 if (Rd == Rm)
1551 nop = true;
1552 break;
1553 case 0x3:
1554 if ((opcode & 0x7) == 0x0)
1555 {
1556 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1557 if (H1)
1558 {
1559 instruction->type = ARM_BLX;
1560 snprintf(instruction->text, 128,
1561 "0x%8.8" PRIx32
1562 " 0x%4.4x \tBLX\tr%i",
1563 address, opcode, Rm);
1564 }
1565 else
1566 {
1567 instruction->type = ARM_BX;
1568 snprintf(instruction->text, 128,
1569 "0x%8.8" PRIx32
1570 " 0x%4.4x \tBX\tr%i",
1571 address, opcode, Rm);
1572 }
1573 }
1574 else
1575 {
1576 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1577 snprintf(instruction->text, 128,
1578 "0x%8.8" PRIx32
1579 " 0x%4.4x \t"
1580 "UNDEFINED INSTRUCTION",
1581 address, opcode);
1582 }
1583 return ERROR_OK;
1584 break;
1585 }
1586 }
1587 else
1588 {
1589 switch (op)
1590 {
1591 case 0x0:
1592 instruction->type = ARM_AND;
1593 mnemonic = "ANDS";
1594 break;
1595 case 0x1:
1596 instruction->type = ARM_EOR;
1597 mnemonic = "EORS";
1598 break;
1599 case 0x2:
1600 instruction->type = ARM_MOV;
1601 mnemonic = "LSLS";
1602 instruction->info.data_proc.variant = 2 /*register shift*/;
1603 instruction->info.data_proc.shifter_operand.register_shift.shift = 0;
1604 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1605 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1606 break;
1607 case 0x3:
1608 instruction->type = ARM_MOV;
1609 mnemonic = "LSRS";
1610 instruction->info.data_proc.variant = 2 /*register shift*/;
1611 instruction->info.data_proc.shifter_operand.register_shift.shift = 1;
1612 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1613 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1614 break;
1615 case 0x4:
1616 instruction->type = ARM_MOV;
1617 mnemonic = "ASRS";
1618 instruction->info.data_proc.variant = 2 /*register shift*/;
1619 instruction->info.data_proc.shifter_operand.register_shift.shift = 2;
1620 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1621 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1622 break;
1623 case 0x5:
1624 instruction->type = ARM_ADC;
1625 mnemonic = "ADCS";
1626 break;
1627 case 0x6:
1628 instruction->type = ARM_SBC;
1629 mnemonic = "SBCS";
1630 break;
1631 case 0x7:
1632 instruction->type = ARM_MOV;
1633 mnemonic = "RORS";
1634 instruction->info.data_proc.variant = 2 /*register shift*/;
1635 instruction->info.data_proc.shifter_operand.register_shift.shift = 3;
1636 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1637 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1638 break;
1639 case 0x8:
1640 instruction->type = ARM_TST;
1641 mnemonic = "TST";
1642 break;
1643 case 0x9:
1644 instruction->type = ARM_RSB;
1645 mnemonic = "NEGS";
1646 instruction->info.data_proc.variant = 0 /*immediate*/;
1647 instruction->info.data_proc.shifter_operand.immediate.immediate = 0;
1648 instruction->info.data_proc.Rn = Rm;
1649 break;
1650 case 0xA:
1651 instruction->type = ARM_CMP;
1652 mnemonic = "CMP";
1653 break;
1654 case 0xB:
1655 instruction->type = ARM_CMN;
1656 mnemonic = "CMN";
1657 break;
1658 case 0xC:
1659 instruction->type = ARM_ORR;
1660 mnemonic = "ORRS";
1661 break;
1662 case 0xD:
1663 instruction->type = ARM_MUL;
1664 mnemonic = "MULS";
1665 break;
1666 case 0xE:
1667 instruction->type = ARM_BIC;
1668 mnemonic = "BICS";
1669 break;
1670 case 0xF:
1671 instruction->type = ARM_MVN;
1672 mnemonic = "MVNS";
1673 break;
1674 }
1675 }
1676
1677 if (nop)
1678 snprintf(instruction->text, 128,
1679 "0x%8.8" PRIx32 " 0x%4.4x \tNOP\t\t\t"
1680 "; (%s r%i, r%i)",
1681 address, opcode, mnemonic, Rd, Rm);
1682 else
1683 snprintf(instruction->text, 128,
1684 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i",
1685 address, opcode, mnemonic, Rd, Rm);
1686
1687 return ERROR_OK;
1688 }
1689
1690 /* PC-relative data addressing is word-aligned even with Thumb */
1691 static inline uint32_t thumb_alignpc4(uint32_t addr)
1692 {
1693 return (addr + 4) & ~3;
1694 }
1695
1696 int evaluate_load_literal_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1697 {
1698 uint32_t immediate;
1699 uint8_t Rd = (opcode >> 8) & 0x7;
1700
1701 instruction->type = ARM_LDR;
1702 immediate = opcode & 0x000000ff;
1703 immediate *= 4;
1704
1705 instruction->info.load_store.Rd = Rd;
1706 instruction->info.load_store.Rn = 15 /*PC*/;
1707 instruction->info.load_store.index_mode = 0; /*offset*/
1708 instruction->info.load_store.offset_mode = 0; /*immediate*/
1709 instruction->info.load_store.offset.offset = immediate;
1710
1711 snprintf(instruction->text, 128,
1712 "0x%8.8" PRIx32 " 0x%4.4x \t"
1713 "LDR\tr%i, [pc, #%#" PRIx32 "]\t; %#8.8x",
1714 address, opcode, Rd, immediate,
1715 thumb_alignpc4(address) + immediate);
1716
1717 return ERROR_OK;
1718 }
1719
1720 int evaluate_load_store_reg_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1721 {
1722 uint8_t Rd = (opcode >> 0) & 0x7;
1723 uint8_t Rn = (opcode >> 3) & 0x7;
1724 uint8_t Rm = (opcode >> 6) & 0x7;
1725 uint8_t opc = (opcode >> 9) & 0x7;
1726 char *mnemonic = NULL;
1727
1728 switch (opc)
1729 {
1730 case 0:
1731 instruction->type = ARM_STR;
1732 mnemonic = "STR";
1733 break;
1734 case 1:
1735 instruction->type = ARM_STRH;
1736 mnemonic = "STRH";
1737 break;
1738 case 2:
1739 instruction->type = ARM_STRB;
1740 mnemonic = "STRB";
1741 break;
1742 case 3:
1743 instruction->type = ARM_LDRSB;
1744 mnemonic = "LDRSB";
1745 break;
1746 case 4:
1747 instruction->type = ARM_LDR;
1748 mnemonic = "LDR";
1749 break;
1750 case 5:
1751 instruction->type = ARM_LDRH;
1752 mnemonic = "LDRH";
1753 break;
1754 case 6:
1755 instruction->type = ARM_LDRB;
1756 mnemonic = "LDRB";
1757 break;
1758 case 7:
1759 instruction->type = ARM_LDRSH;
1760 mnemonic = "LDRSH";
1761 break;
1762 }
1763
1764 snprintf(instruction->text, 128,
1765 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [r%i, r%i]",
1766 address, opcode, mnemonic, Rd, Rn, Rm);
1767
1768 instruction->info.load_store.Rd = Rd;
1769 instruction->info.load_store.Rn = Rn;
1770 instruction->info.load_store.index_mode = 0; /*offset*/
1771 instruction->info.load_store.offset_mode = 1; /*register*/
1772 instruction->info.load_store.offset.reg.Rm = Rm;
1773
1774 return ERROR_OK;
1775 }
1776
1777 int evaluate_load_store_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1778 {
1779 uint32_t offset = (opcode >> 6) & 0x1f;
1780 uint8_t Rd = (opcode >> 0) & 0x7;
1781 uint8_t Rn = (opcode >> 3) & 0x7;
1782 uint32_t L = opcode & (1 << 11);
1783 uint32_t B = opcode & (1 << 12);
1784 char *mnemonic;
1785 char suffix = ' ';
1786 uint32_t shift = 2;
1787
1788 if (L)
1789 {
1790 instruction->type = ARM_LDR;
1791 mnemonic = "LDR";
1792 }
1793 else
1794 {
1795 instruction->type = ARM_STR;
1796 mnemonic = "STR";
1797 }
1798
1799 if ((opcode&0xF000) == 0x8000)
1800 {
1801 suffix = 'H';
1802 shift = 1;
1803 }
1804 else if (B)
1805 {
1806 suffix = 'B';
1807 shift = 0;
1808 }
1809
1810 snprintf(instruction->text, 128,
1811 "0x%8.8" PRIx32 " 0x%4.4x \t%s%c\tr%i, [r%i, #%#" PRIx32 "]",
1812 address, opcode, mnemonic, suffix, Rd, Rn, offset << shift);
1813
1814 instruction->info.load_store.Rd = Rd;
1815 instruction->info.load_store.Rn = Rn;
1816 instruction->info.load_store.index_mode = 0; /*offset*/
1817 instruction->info.load_store.offset_mode = 0; /*immediate*/
1818 instruction->info.load_store.offset.offset = offset << shift;
1819
1820 return ERROR_OK;
1821 }
1822
1823 int evaluate_load_store_stack_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1824 {
1825 uint32_t offset = opcode & 0xff;
1826 uint8_t Rd = (opcode >> 8) & 0x7;
1827 uint32_t L = opcode & (1 << 11);
1828 char *mnemonic;
1829
1830 if (L)
1831 {
1832 instruction->type = ARM_LDR;
1833 mnemonic = "LDR";
1834 }
1835 else
1836 {
1837 instruction->type = ARM_STR;
1838 mnemonic = "STR";
1839 }
1840
1841 snprintf(instruction->text, 128,
1842 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [SP, #%#" PRIx32 "]",
1843 address, opcode, mnemonic, Rd, offset*4);
1844
1845 instruction->info.load_store.Rd = Rd;
1846 instruction->info.load_store.Rn = 13 /*SP*/;
1847 instruction->info.load_store.index_mode = 0; /*offset*/
1848 instruction->info.load_store.offset_mode = 0; /*immediate*/
1849 instruction->info.load_store.offset.offset = offset*4;
1850
1851 return ERROR_OK;
1852 }
1853
1854 int evaluate_add_sp_pc_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1855 {
1856 uint32_t imm = opcode & 0xff;
1857 uint8_t Rd = (opcode >> 8) & 0x7;
1858 uint8_t Rn;
1859 uint32_t SP = opcode & (1 << 11);
1860 char *reg_name;
1861
1862 instruction->type = ARM_ADD;
1863
1864 if (SP)
1865 {
1866 reg_name = "SP";
1867 Rn = 13;
1868 }
1869 else
1870 {
1871 reg_name = "PC";
1872 Rn = 15;
1873 }
1874
1875 snprintf(instruction->text, 128,
1876 "0x%8.8" PRIx32 " 0x%4.4x \tADD\tr%i, %s, #%#" PRIx32,
1877 address, opcode, Rd, reg_name, imm * 4);
1878
1879 instruction->info.data_proc.variant = 0 /* immediate */;
1880 instruction->info.data_proc.Rd = Rd;
1881 instruction->info.data_proc.Rn = Rn;
1882 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
1883
1884 return ERROR_OK;
1885 }
1886
1887 int evaluate_adjust_stack_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1888 {
1889 uint32_t imm = opcode & 0x7f;
1890 uint8_t opc = opcode & (1 << 7);
1891 char *mnemonic;
1892
1893
1894 if (opc)
1895 {
1896 instruction->type = ARM_SUB;
1897 mnemonic = "SUB";
1898 }
1899 else
1900 {
1901 instruction->type = ARM_ADD;
1902 mnemonic = "ADD";
1903 }
1904
1905 snprintf(instruction->text, 128,
1906 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tSP, #%#" PRIx32,
1907 address, opcode, mnemonic, imm*4);
1908
1909 instruction->info.data_proc.variant = 0 /* immediate */;
1910 instruction->info.data_proc.Rd = 13 /*SP*/;
1911 instruction->info.data_proc.Rn = 13 /*SP*/;
1912 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
1913
1914 return ERROR_OK;
1915 }
1916
1917 int evaluate_breakpoint_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1918 {
1919 uint32_t imm = opcode & 0xff;
1920
1921 instruction->type = ARM_BKPT;
1922
1923 snprintf(instruction->text, 128,
1924 "0x%8.8" PRIx32 " 0x%4.4x \tBKPT\t%#2.2" PRIx32 "",
1925 address, opcode, imm);
1926
1927 return ERROR_OK;
1928 }
1929
1930 int evaluate_load_store_multiple_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1931 {
1932 uint32_t reg_list = opcode & 0xff;
1933 uint32_t L = opcode & (1 << 11);
1934 uint32_t R = opcode & (1 << 8);
1935 uint8_t Rn = (opcode >> 8) & 7;
1936 uint8_t addr_mode = 0 /* IA */;
1937 char reg_names[40];
1938 char *reg_names_p;
1939 char *mnemonic;
1940 char ptr_name[7] = "";
1941 int i;
1942
1943 if ((opcode & 0xf000) == 0xc000)
1944 { /* generic load/store multiple */
1945 if (L)
1946 {
1947 instruction->type = ARM_LDM;
1948 mnemonic = "LDM";
1949 }
1950 else
1951 {
1952 instruction->type = ARM_STM;
1953 mnemonic = "STM";
1954 }
1955 snprintf(ptr_name,7,"r%i!, ",Rn);
1956 }
1957 else
1958 { /* push/pop */
1959 Rn = 13; /* SP */
1960 if (L)
1961 {
1962 instruction->type = ARM_LDM;
1963 mnemonic = "POP";
1964 if (R)
1965 reg_list |= (1 << 15) /*PC*/;
1966 }
1967 else
1968 {
1969 instruction->type = ARM_STM;
1970 mnemonic = "PUSH";
1971 addr_mode = 3; /*DB*/
1972 if (R)
1973 reg_list |= (1 << 14) /*LR*/;
1974 }
1975 }
1976
1977 reg_names_p = reg_names;
1978 for (i = 0; i <= 15; i++)
1979 {
1980 if (reg_list & (1 << i))
1981 reg_names_p += snprintf(reg_names_p, (reg_names + 40 - reg_names_p), "r%i, ", i);
1982 }
1983 if (reg_names_p > reg_names)
1984 reg_names_p[-2] = '\0';
1985 else /* invalid op : no registers */
1986 reg_names[0] = '\0';
1987
1988 snprintf(instruction->text, 128,
1989 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%s{%s}",
1990 address, opcode, mnemonic, ptr_name, reg_names);
1991
1992 instruction->info.load_store_multiple.register_list = reg_list;
1993 instruction->info.load_store_multiple.Rn = Rn;
1994 instruction->info.load_store_multiple.addressing_mode = addr_mode;
1995
1996 return ERROR_OK;
1997 }
1998
1999 int evaluate_cond_branch_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
2000 {
2001 uint32_t offset = opcode & 0xff;
2002 uint8_t cond = (opcode >> 8) & 0xf;
2003 uint32_t target_address;
2004
2005 if (cond == 0xf)
2006 {
2007 instruction->type = ARM_SWI;
2008 snprintf(instruction->text, 128,
2009 "0x%8.8" PRIx32 " 0x%4.4x \tSVC\t%#2.2" PRIx32,
2010 address, opcode, offset);
2011 return ERROR_OK;
2012 }
2013 else if (cond == 0xe)
2014 {
2015 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2016 snprintf(instruction->text, 128,
2017 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2018 address, opcode);
2019 return ERROR_OK;
2020 }
2021
2022 /* sign extend 8-bit offset */
2023 if (offset & 0x00000080)
2024 offset = 0xffffff00 | offset;
2025
2026 target_address = address + 4 + (offset << 1);
2027
2028 snprintf(instruction->text, 128,
2029 "0x%8.8" PRIx32 " 0x%4.4x \tB%s\t%#8.8" PRIx32,
2030 address, opcode,
2031 arm_condition_strings[cond], target_address);
2032
2033 instruction->type = ARM_B;
2034 instruction->info.b_bl_bx_blx.reg_operand = -1;
2035 instruction->info.b_bl_bx_blx.target_address = target_address;
2036
2037 return ERROR_OK;
2038 }
2039
2040 static int evaluate_cb_thumb(uint16_t opcode, uint32_t address,
2041 arm_instruction_t *instruction)
2042 {
2043 unsigned offset;
2044
2045 /* added in Thumb2 */
2046 offset = (opcode >> 3) & 0x1f;
2047 offset |= (opcode & 0x0200) >> 4;
2048
2049 snprintf(instruction->text, 128,
2050 "0x%8.8" PRIx32 " 0x%4.4x \tCB%sZ\tr%d, %#8.8" PRIx32,
2051 address, opcode,
2052 (opcode & 0x0800) ? "N" : "",
2053 opcode & 0x7, address + 4 + (offset << 1));
2054
2055 return ERROR_OK;
2056 }
2057
2058 static int evaluate_extend_thumb(uint16_t opcode, uint32_t address,
2059 arm_instruction_t *instruction)
2060 {
2061 /* added in ARMv6 */
2062 snprintf(instruction->text, 128,
2063 "0x%8.8" PRIx32 " 0x%4.4x \t%cXT%c\tr%d, r%d",
2064 address, opcode,
2065 (opcode & 0x0080) ? 'U' : 'S',
2066 (opcode & 0x0040) ? 'B' : 'H',
2067 opcode & 0x7, (opcode >> 3) & 0x7);
2068
2069 return ERROR_OK;
2070 }
2071
2072 static int evaluate_cps_thumb(uint16_t opcode, uint32_t address,
2073 arm_instruction_t *instruction)
2074 {
2075 /* added in ARMv6 */
2076 if ((opcode & 0x0ff0) == 0x0650)
2077 snprintf(instruction->text, 128,
2078 "0x%8.8" PRIx32 " 0x%4.4x \tSETEND %s",
2079 address, opcode,
2080 (opcode & 0x80) ? "BE" : "LE");
2081 else /* ASSUME (opcode & 0x0fe0) == 0x0660 */
2082 snprintf(instruction->text, 128,
2083 "0x%8.8" PRIx32 " 0x%4.4x \tCPSI%c %s%s%s",
2084 address, opcode,
2085 (opcode & 0x0010) ? 'D' : 'E',
2086 (opcode & 0x0004) ? "A" : "",
2087 (opcode & 0x0002) ? "I" : "",
2088 (opcode & 0x0001) ? "F" : "");
2089
2090 return ERROR_OK;
2091 }
2092
2093 static int evaluate_byterev_thumb(uint16_t opcode, uint32_t address,
2094 arm_instruction_t *instruction)
2095 {
2096 char *suffix;
2097
2098 /* added in ARMv6 */
2099 switch (opcode & 0x00c0) {
2100 case 0:
2101 suffix = "";
2102 break;
2103 case 1:
2104 suffix = "16";
2105 break;
2106 default:
2107 suffix = "SH";
2108 break;
2109 }
2110 snprintf(instruction->text, 128,
2111 "0x%8.8" PRIx32 " 0x%4.4x \tREV%s\tr%d, r%d",
2112 address, opcode, suffix,
2113 opcode & 0x7, (opcode >> 3) & 0x7);
2114
2115 return ERROR_OK;
2116 }
2117
2118 static int evaluate_hint_thumb(uint16_t opcode, uint32_t address,
2119 arm_instruction_t *instruction)
2120 {
2121 char *hint;
2122
2123 switch ((opcode >> 4) & 0x0f) {
2124 case 0:
2125 hint = "NOP";
2126 break;
2127 case 1:
2128 hint = "YIELD";
2129 break;
2130 case 2:
2131 hint = "WFE";
2132 break;
2133 case 3:
2134 hint = "WFI";
2135 break;
2136 case 4:
2137 hint = "SEV";
2138 break;
2139 default:
2140 hint = "HINT (UNRECOGNIZED)";
2141 break;
2142 }
2143
2144 snprintf(instruction->text, 128,
2145 "0x%8.8" PRIx32 " 0x%4.4x \t%s",
2146 address, opcode, hint);
2147
2148 return ERROR_OK;
2149 }
2150
2151 static int evaluate_ifthen_thumb(uint16_t opcode, uint32_t address,
2152 arm_instruction_t *instruction)
2153 {
2154 unsigned cond = (opcode >> 4) & 0x0f;
2155 char *x = "", *y = "", *z = "";
2156
2157 if (opcode & 0x01)
2158 z = (opcode & 0x02) ? "T" : "E";
2159 if (opcode & 0x03)
2160 y = (opcode & 0x04) ? "T" : "E";
2161 if (opcode & 0x07)
2162 x = (opcode & 0x08) ? "T" : "E";
2163
2164 snprintf(instruction->text, 128,
2165 "0x%8.8" PRIx32 " 0x%4.4x \tIT%s%s%s\t%s",
2166 address, opcode,
2167 x, y, z, arm_condition_strings[cond]);
2168
2169 /* NOTE: strictly speaking, the next 1-4 instructions should
2170 * now be displayed with the relevant conditional suffix...
2171 */
2172
2173 return ERROR_OK;
2174 }
2175
2176 int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
2177 {
2178 /* clear fields, to avoid confusion */
2179 memset(instruction, 0, sizeof(arm_instruction_t));
2180 instruction->opcode = opcode;
2181 instruction->instruction_size = 2;
2182
2183 if ((opcode & 0xe000) == 0x0000)
2184 {
2185 /* add/substract register or immediate */
2186 if ((opcode & 0x1800) == 0x1800)
2187 return evaluate_add_sub_thumb(opcode, address, instruction);
2188 /* shift by immediate */
2189 else
2190 return evaluate_shift_imm_thumb(opcode, address, instruction);
2191 }
2192
2193 /* Add/substract/compare/move immediate */
2194 if ((opcode & 0xe000) == 0x2000)
2195 {
2196 return evaluate_data_proc_imm_thumb(opcode, address, instruction);
2197 }
2198
2199 /* Data processing instructions */
2200 if ((opcode & 0xf800) == 0x4000)
2201 {
2202 return evaluate_data_proc_thumb(opcode, address, instruction);
2203 }
2204
2205 /* Load from literal pool */
2206 if ((opcode & 0xf800) == 0x4800)
2207 {
2208 return evaluate_load_literal_thumb(opcode, address, instruction);
2209 }
2210
2211 /* Load/Store register offset */
2212 if ((opcode & 0xf000) == 0x5000)
2213 {
2214 return evaluate_load_store_reg_thumb(opcode, address, instruction);
2215 }
2216
2217 /* Load/Store immediate offset */
2218 if (((opcode & 0xe000) == 0x6000)
2219 ||((opcode & 0xf000) == 0x8000))
2220 {
2221 return evaluate_load_store_imm_thumb(opcode, address, instruction);
2222 }
2223
2224 /* Load/Store from/to stack */
2225 if ((opcode & 0xf000) == 0x9000)
2226 {
2227 return evaluate_load_store_stack_thumb(opcode, address, instruction);
2228 }
2229
2230 /* Add to SP/PC */
2231 if ((opcode & 0xf000) == 0xa000)
2232 {
2233 return evaluate_add_sp_pc_thumb(opcode, address, instruction);
2234 }
2235
2236 /* Misc */
2237 if ((opcode & 0xf000) == 0xb000)
2238 {
2239 switch ((opcode >> 8) & 0x0f) {
2240 case 0x0:
2241 return evaluate_adjust_stack_thumb(opcode, address, instruction);
2242 case 0x1:
2243 case 0x3:
2244 case 0x9:
2245 case 0xb:
2246 return evaluate_cb_thumb(opcode, address, instruction);
2247 case 0x2:
2248 return evaluate_extend_thumb(opcode, address, instruction);
2249 case 0x4:
2250 case 0x5:
2251 case 0xc:
2252 case 0xd:
2253 return evaluate_load_store_multiple_thumb(opcode, address,
2254 instruction);
2255 case 0x6:
2256 return evaluate_cps_thumb(opcode, address, instruction);
2257 case 0xa:
2258 if ((opcode & 0x00c0) == 0x0080)
2259 break;
2260 return evaluate_byterev_thumb(opcode, address, instruction);
2261 case 0xe:
2262 return evaluate_breakpoint_thumb(opcode, address, instruction);
2263 case 0xf:
2264 if (opcode & 0x000f)
2265 return evaluate_ifthen_thumb(opcode, address,
2266 instruction);
2267 else
2268 return evaluate_hint_thumb(opcode, address,
2269 instruction);
2270 }
2271
2272 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2273 snprintf(instruction->text, 128,
2274 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2275 address, opcode);
2276 return ERROR_OK;
2277 }
2278
2279 /* Load/Store multiple */
2280 if ((opcode & 0xf000) == 0xc000)
2281 {
2282 return evaluate_load_store_multiple_thumb(opcode, address, instruction);
2283 }
2284
2285 /* Conditional branch + SWI */
2286 if ((opcode & 0xf000) == 0xd000)
2287 {
2288 return evaluate_cond_branch_thumb(opcode, address, instruction);
2289 }
2290
2291 if ((opcode & 0xe000) == 0xe000)
2292 {
2293 /* Undefined instructions */
2294 if ((opcode & 0xf801) == 0xe801)
2295 {
2296 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2297 snprintf(instruction->text, 128,
2298 "0x%8.8" PRIx32 " 0x%8.8x\t"
2299 "UNDEFINED INSTRUCTION",
2300 address, opcode);
2301 return ERROR_OK;
2302 }
2303 else
2304 { /* Branch to offset */
2305 return evaluate_b_bl_blx_thumb(opcode, address, instruction);
2306 }
2307 }
2308
2309 LOG_ERROR("should never reach this point (opcode=%04x)",opcode);
2310 return -1;
2311 }
2312
2313 static int t2ev_b_bl(uint32_t opcode, uint32_t address,
2314 arm_instruction_t *instruction, char *cp)
2315 {
2316 unsigned offset;
2317 unsigned b21 = 1 << 21;
2318 unsigned b22 = 1 << 22;
2319
2320 /* instead of combining two smaller 16-bit branch instructions,
2321 * Thumb2 uses only one larger 32-bit instruction.
2322 */
2323 offset = opcode & 0x7ff;
2324 offset |= (opcode & 0x03ff0000) >> 5;
2325 if (opcode & (1 << 26)) {
2326 offset |= 0xff << 23;
2327 if ((opcode & (1 << 11)) == 0)
2328 b21 = 0;
2329 if ((opcode & (1 << 13)) == 0)
2330 b22 = 0;
2331 } else {
2332 if (opcode & (1 << 11))
2333 b21 = 0;
2334 if (opcode & (1 << 13))
2335 b22 = 0;
2336 }
2337 offset |= b21;
2338 offset |= b22;
2339
2340
2341 address += 4;
2342 address += offset << 1;
2343
2344 instruction->type = (opcode & (1 << 14)) ? ARM_BL : ARM_B;
2345 instruction->info.b_bl_bx_blx.reg_operand = -1;
2346 instruction->info.b_bl_bx_blx.target_address = address;
2347 sprintf(cp, "%s\t%#8.8" PRIx32,
2348 (opcode & (1 << 14)) ? "BL" : "B.W",
2349 address);
2350
2351 return ERROR_OK;
2352 }
2353
2354 static int t2ev_cond_b(uint32_t opcode, uint32_t address,
2355 arm_instruction_t *instruction, char *cp)
2356 {
2357 unsigned offset;
2358 unsigned b17 = 1 << 17;
2359 unsigned b18 = 1 << 18;
2360 unsigned cond = (opcode >> 22) & 0x0f;
2361
2362 offset = opcode & 0x7ff;
2363 offset |= (opcode & 0x003f0000) >> 5;
2364 if (opcode & (1 << 26)) {
2365 offset |= 0xffff << 19;
2366 if ((opcode & (1 << 11)) == 0)
2367 b17 = 0;
2368 if ((opcode & (1 << 13)) == 0)
2369 b18 = 0;
2370 } else {
2371 if (opcode & (1 << 11))
2372 b17 = 0;
2373 if (opcode & (1 << 13))
2374 b18 = 0;
2375 }
2376 offset |= b17;
2377 offset |= b18;
2378
2379 address += 4;
2380 address += offset << 1;
2381
2382 instruction->type = ARM_B;
2383 instruction->info.b_bl_bx_blx.reg_operand = -1;
2384 instruction->info.b_bl_bx_blx.target_address = address;
2385 sprintf(cp, "B%s.W\t%#8.8" PRIx32,
2386 arm_condition_strings[cond],
2387 address);
2388
2389 return ERROR_OK;
2390 }
2391
2392 static const char *special_name(int number)
2393 {
2394 char *special = "(RESERVED)";
2395
2396 switch (number) {
2397 case 0:
2398 special = "apsr";
2399 break;
2400 case 1:
2401 special = "iapsr";
2402 break;
2403 case 2:
2404 special = "eapsr";
2405 break;
2406 case 3:
2407 special = "xpsr";
2408 break;
2409 case 5:
2410 special = "ipsr";
2411 break;
2412 case 6:
2413 special = "epsr";
2414 break;
2415 case 7:
2416 special = "iepsr";
2417 break;
2418 case 8:
2419 special = "msp";
2420 break;
2421 case 9:
2422 special = "psp";
2423 break;
2424 case 16:
2425 special = "primask";
2426 break;
2427 case 17:
2428 special = "basepri";
2429 break;
2430 case 18:
2431 special = "basepri_max";
2432 break;
2433 case 19:
2434 special = "faultmask";
2435 break;
2436 case 20:
2437 special = "control";
2438 break;
2439 }
2440 return special;
2441 }
2442
2443 static int t2ev_hint(uint32_t opcode, uint32_t address,
2444 arm_instruction_t *instruction, char *cp)
2445 {
2446 const char *mnemonic;
2447
2448 if (opcode & 0x0700) {
2449 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2450 strcpy(cp, "UNDEFINED");
2451 return ERROR_OK;
2452 }
2453
2454 if (opcode & 0x00f0) {
2455 sprintf(cp, "DBG\t#%d", opcode & 0xf);
2456 return ERROR_OK;
2457 }
2458
2459 switch (opcode & 0x0f) {
2460 case 0:
2461 mnemonic = "NOP.W";
2462 break;
2463 case 1:
2464 mnemonic = "YIELD.W";
2465 break;
2466 case 2:
2467 mnemonic = "WFE.W";
2468 break;
2469 case 3:
2470 mnemonic = "WFI.W";
2471 break;
2472 case 4:
2473 mnemonic = "SEV.W";
2474 break;
2475 default:
2476 mnemonic = "HINT.W (UNRECOGNIZED)";
2477 break;
2478 }
2479 strcpy(cp, mnemonic);
2480 return ERROR_OK;
2481 }
2482
2483 static int t2ev_misc(uint32_t opcode, uint32_t address,
2484 arm_instruction_t *instruction, char *cp)
2485 {
2486 const char *mnemonic;
2487
2488 switch ((opcode >> 4) & 0x0f) {
2489 case 2:
2490 mnemonic = "CLREX";
2491 break;
2492 case 4:
2493 mnemonic = "DSB";
2494 break;
2495 case 5:
2496 mnemonic = "DMB";
2497 break;
2498 case 6:
2499 mnemonic = "ISB";
2500 break;
2501 default:
2502 return ERROR_INVALID_ARGUMENTS;
2503 }
2504 strcpy(cp, mnemonic);
2505 return ERROR_OK;
2506 }
2507
2508 static int t2ev_b_misc(uint32_t opcode, uint32_t address,
2509 arm_instruction_t *instruction, char *cp)
2510 {
2511 /* permanently undefined */
2512 if ((opcode & 0x07f07000) == 0x07f02000) {
2513 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2514 strcpy(cp, "UNDEFINED");
2515 return ERROR_OK;
2516 }
2517
2518 switch ((opcode >> 12) & 0x5) {
2519 case 0x1:
2520 case 0x5:
2521 return t2ev_b_bl(opcode, address, instruction, cp);
2522 case 0x4:
2523 goto undef;
2524 case 0:
2525 if (((opcode >> 23) & 0x07) == 0x07)
2526 return t2ev_cond_b(opcode, address, instruction, cp);
2527 if (opcode & (1 << 26))
2528 goto undef;
2529 break;
2530 }
2531
2532 switch ((opcode >> 20) & 0x7f) {
2533 case 0x38:
2534 case 0x39:
2535 sprintf(cp, "MSR\t%s, r%d", special_name(opcode & 0xff),
2536 (opcode >> 16) & 0x0f);
2537 return ERROR_OK;
2538 case 0x3a:
2539 return t2ev_hint(opcode, address, instruction, cp);
2540 case 0x3b:
2541 return t2ev_misc(opcode, address, instruction, cp);
2542 case 0x3e:
2543 case 0x3f:
2544 sprintf(cp, "MRS\tr%d, %s", (opcode >> 16) & 0x0f,
2545 special_name(opcode & 0xff));
2546 return ERROR_OK;
2547 }
2548
2549 undef:
2550 return ERROR_INVALID_ARGUMENTS;
2551 }
2552
2553 static int t2ev_data_mod_immed(uint32_t opcode, uint32_t address,
2554 arm_instruction_t *instruction, char *cp)
2555 {
2556 char *mnemonic = NULL;
2557 int rn = (opcode >> 16) & 0xf;
2558 int rd = (opcode >> 8) & 0xf;
2559 unsigned immed = opcode & 0xff;
2560 unsigned func;
2561 bool one = false;
2562 char *suffix = "";
2563
2564 /* ARMv7-M: A5.3.2 Modified immediate constants */
2565 func = (opcode >> 11) & 0x0e;
2566 if (immed & 0x80)
2567 func |= 1;
2568 if (opcode & (1 << 26))
2569 func |= 0x10;
2570
2571 /* "Modified" immediates */
2572 switch (func >> 1) {
2573 case 0:
2574 break;
2575 case 2:
2576 immed <<= 8;
2577 /* FALLTHROUGH */
2578 case 1:
2579 immed += immed << 16;
2580 break;
2581 case 3:
2582 immed += immed << 8;
2583 immed += immed << 16;
2584 break;
2585 default:
2586 immed |= 0x80;
2587 immed = ror(immed, func);
2588 }
2589
2590 if (opcode & (1 << 20))
2591 suffix = "S";
2592
2593 switch ((opcode >> 21) & 0xf) {
2594 case 0:
2595 if (rd == 0xf) {
2596 instruction->type = ARM_TST;
2597 mnemonic = "TST";
2598 one = true;
2599 suffix = "";
2600 rd = rn;
2601 } else {
2602 instruction->type = ARM_AND;
2603 mnemonic = "AND";
2604 }
2605 break;
2606 case 1:
2607 instruction->type = ARM_BIC;
2608 mnemonic = "BIC";
2609 break;
2610 case 2:
2611 if (rn == 0xf) {
2612 instruction->type = ARM_MOV;
2613 mnemonic = "MOV";
2614 one = true;
2615 } else {
2616 instruction->type = ARM_ORR;
2617 mnemonic = "ORR";
2618 }
2619 break;
2620 case 3:
2621 if (rn == 0xf) {
2622 instruction->type = ARM_MVN;
2623 mnemonic = "MVN";
2624 one = true;
2625 } else {
2626 // instruction->type = ARM_ORN;
2627 mnemonic = "ORN";
2628 }
2629 break;
2630 case 4:
2631 if (rd == 0xf) {
2632 instruction->type = ARM_TEQ;
2633 mnemonic = "TEQ";
2634 one = true;
2635 suffix = "";
2636 rd = rn;
2637 } else {
2638 instruction->type = ARM_EOR;
2639 mnemonic = "EOR";
2640 }
2641 break;
2642 case 8:
2643 if (rd == 0xf) {
2644 instruction->type = ARM_CMN;
2645 mnemonic = "CMN";
2646 one = true;
2647 suffix = "";
2648 rd = rn;
2649 } else {
2650 instruction->type = ARM_ADD;
2651 mnemonic = "ADD";
2652 }
2653 break;
2654 case 10:
2655 instruction->type = ARM_ADC;
2656 mnemonic = "ADC";
2657 break;
2658 case 11:
2659 instruction->type = ARM_SBC;
2660 mnemonic = "SBC";
2661 break;
2662 case 13:
2663 if (rd == 0xf) {
2664 instruction->type = ARM_CMP;
2665 mnemonic = "CMP";
2666 one = true;
2667 suffix = "";
2668 rd = rn;
2669 } else {
2670 instruction->type = ARM_SUB;
2671 mnemonic = "SUB";
2672 }
2673 break;
2674 case 14:
2675 instruction->type = ARM_RSB;
2676 mnemonic = "RSB";
2677 break;
2678 default:
2679 return ERROR_INVALID_ARGUMENTS;
2680 }
2681
2682 if (one)
2683 sprintf(cp, "%s\tr%d, #%d\t; %#8.8x",
2684 mnemonic, rd, immed, immed);
2685 else
2686 sprintf(cp, "%s%s\tr%d, r%d, #%d\t; %#8.8x",
2687 mnemonic, suffix, rd, rn, immed, immed);
2688
2689 return ERROR_OK;
2690 }
2691
2692 static int t2ev_data_immed(uint32_t opcode, uint32_t address,
2693 arm_instruction_t *instruction, char *cp)
2694 {
2695 char *mnemonic = NULL;
2696 int rn = (opcode >> 16) & 0xf;
2697 int rd = (opcode >> 8) & 0xf;
2698 unsigned immed;
2699 bool add = false;
2700 bool is_signed = false;
2701
2702 immed = (opcode & 0x0ff) | ((opcode & 0x7000) >> 12);
2703 if (opcode & (1 << 27))
2704 immed |= (1 << 11);
2705
2706 switch ((opcode >> 20) & 0x1f) {
2707 case 0:
2708 if (rn == 0xf) {
2709 add = true;
2710 goto do_adr;
2711 }
2712 mnemonic = "ADD.W";
2713 break;
2714 case 4:
2715 mnemonic = "MOV.W";
2716 break;
2717 case 0x0a:
2718 if (rn == 0xf)
2719 goto do_adr;
2720 mnemonic = "SUB.W";
2721 break;
2722 case 0x0c:
2723 /* move constant to top 16 bits of register */
2724 immed |= (opcode >> 4) & 0xf000;
2725 sprintf(cp, "MOVT\tr%d, #%d\t; %#4.4x", rn, immed, immed);
2726 return ERROR_OK;
2727 case 0x10:
2728 case 0x12:
2729 is_signed = true;
2730 case 0x18:
2731 case 0x1a:
2732 /* signed/unsigned saturated add */
2733 immed = (opcode >> 6) & 0x03;
2734 immed |= (opcode >> 10) & 0x1c;
2735 sprintf(cp, "%sSAT\tr%d, #%d, r%d, %s #%d\t",
2736 is_signed ? "S" : "U",
2737 rd, (opcode & 0x1f) + 1, rn,
2738 (opcode & (1 << 21)) ? "ASR" : "LSL",
2739 immed ? immed : 32);
2740 return ERROR_OK;
2741 case 0x14:
2742 is_signed = true;
2743 /* FALLTHROUGH */
2744 case 0x1c:
2745 /* signed/unsigned bitfield extract */
2746 immed = (opcode >> 6) & 0x03;
2747 immed |= (opcode >> 10) & 0x1c;
2748 sprintf(cp, "%sBFX\tr%d, r%d, #%d, #%d\t",
2749 is_signed ? "S" : "U",
2750 rd, rn, immed,
2751 (opcode & 0x1f) + 1);
2752 return ERROR_OK;
2753 case 0x16:
2754 immed = (opcode >> 6) & 0x03;
2755 immed |= (opcode >> 10) & 0x1c;
2756 if (rn == 0xf) /* bitfield clear */
2757 sprintf(cp, "BFC\tr%d, #%d, #%d\t",
2758 rd, immed,
2759 (opcode & 0x1f) + 1 - immed);
2760 else /* bitfield insert */
2761 sprintf(cp, "BFI\tr%d, r%d, #%d, #%d\t",
2762 rd, rn, immed,
2763 (opcode & 0x1f) + 1 - immed);
2764 return ERROR_OK;
2765 default:
2766 return ERROR_INVALID_ARGUMENTS;
2767 }
2768
2769 sprintf(cp, "%s\tr%d, r%d, #%d\t; %#3.3x", mnemonic,
2770 rd, rn, immed, immed);
2771 return ERROR_OK;
2772
2773 do_adr:
2774 address = thumb_alignpc4(address);
2775 if (add)
2776 address += immed;
2777 else
2778 address -= immed;
2779 /* REVISIT "ADD/SUB Rd, PC, #const ; 0x..." might be better;
2780 * not hiding the pc-relative stuff will sometimes be useful.
2781 */
2782 sprintf(cp, "ADR.W\tr%d, %#8.8" PRIx32, rd, address);
2783 return ERROR_OK;
2784 }
2785
2786 static int t2ev_store_single(uint32_t opcode, uint32_t address,
2787 arm_instruction_t *instruction, char *cp)
2788 {
2789 unsigned op = (opcode >> 20) & 0xf;
2790 char *size = "";
2791 char *suffix = "";
2792 char *p1 = "";
2793 char *p2 = "]";
2794 unsigned immed;
2795 unsigned rn = (opcode >> 16) & 0x0f;
2796 unsigned rt = (opcode >> 12) & 0x0f;
2797
2798 if (rn == 0xf)
2799 return ERROR_INVALID_ARGUMENTS;
2800
2801 if (opcode & 0x0800)
2802 op |= 1;
2803 switch (op) {
2804 /* byte */
2805 case 0x8:
2806 case 0x9:
2807 size = "B";
2808 goto imm12;
2809 case 0x1:
2810 size = "B";
2811 goto imm8;
2812 case 0x0:
2813 size = "B";
2814 break;
2815 /* halfword */
2816 case 0xa:
2817 case 0xb:
2818 size = "H";
2819 goto imm12;
2820 case 0x3:
2821 size = "H";
2822 goto imm8;
2823 case 0x2:
2824 size = "H";
2825 break;
2826 /* word */
2827 case 0xc:
2828 case 0xd:
2829 goto imm12;
2830 case 0x5:
2831 goto imm8;
2832 case 0x4:
2833 break;
2834 /* error */
2835 default:
2836 return ERROR_INVALID_ARGUMENTS;
2837 }
2838
2839 sprintf(cp, "STR%s.W\tr%d, [r%d, r%d, LSL #%d]",
2840 size, rt, rn, opcode & 0x0f,
2841 (opcode >> 4) & 0x03);
2842
2843 imm12:
2844 immed = opcode & 0x0fff;
2845 sprintf(cp, "STR%s.W\tr%d, [r%d, #%u]\t; %#3.3x",
2846 size, rt, rn, immed, immed);
2847 return ERROR_OK;
2848
2849 imm8:
2850 immed = opcode & 0x00ff;
2851
2852 switch (opcode & 0x700) {
2853 case 0x600:
2854 suffix = "T";
2855 break;
2856 case 0x000:
2857 case 0x200:
2858 return ERROR_INVALID_ARGUMENTS;
2859 }
2860
2861 /* two indexed modes will write back rn */
2862 if (opcode & 0x100) {
2863 if (opcode & 0x400) /* pre-indexed */
2864 p2 = "]!";
2865 else { /* post-indexed */
2866 p1 = "]";
2867 p2 = "";
2868 }
2869 }
2870
2871 sprintf(cp, "STR%s%s\tr%d, [r%d%s, #%s%u%s\t; %#2.2x",
2872 size, suffix, rt, rn, p1,
2873 (opcode & 0x200) ? "" : "-",
2874 immed, p2, immed);
2875 return ERROR_OK;
2876 }
2877
2878 static int t2ev_mul32(uint32_t opcode, uint32_t address,
2879 arm_instruction_t *instruction, char *cp)
2880 {
2881 int ra = (opcode >> 12) & 0xf;
2882
2883
2884 switch (opcode & 0x007000f0) {
2885 case 0:
2886 if (ra == 0xf)
2887 sprintf(cp, "MUL\tr%d, r%d, r%d",
2888 (opcode >> 8) & 0xf, (opcode >> 16) & 0xf,
2889 (opcode >> 0) & 0xf);
2890 else
2891 sprintf(cp, "MLA\tr%d, r%d, r%d, r%d",
2892 (opcode >> 8) & 0xf, (opcode >> 16) & 0xf,
2893 (opcode >> 0) & 0xf, ra);
2894 break;
2895 case 0x10:
2896 sprintf(cp, "MLS\tr%d, r%d, r%d, r%d",
2897 (opcode >> 8) & 0xf, (opcode >> 16) & 0xf,
2898 (opcode >> 0) & 0xf, ra);
2899 break;
2900 default:
2901 return ERROR_INVALID_ARGUMENTS;
2902 }
2903 return ERROR_OK;
2904 }
2905
2906 static int t2ev_mul64_div(uint32_t opcode, uint32_t address,
2907 arm_instruction_t *instruction, char *cp)
2908 {
2909 int op = (opcode >> 4) & 0xf;
2910 char *infix = "MUL";
2911
2912 op += (opcode >> 16) & 0x70;
2913 switch (op) {
2914 case 0x40:
2915 case 0x60:
2916 infix = "MLA";
2917 /* FALLTHROUGH */
2918 case 0:
2919 case 0x20:
2920 sprintf(cp, "%c%sL\tr%d, r%d, r%d, r%d",
2921 (op & 0x20) ? 'U' : 'S',
2922 infix,
2923 (opcode >> 12) & 0xf,
2924 (opcode >> 8) & 0xf,
2925 (opcode >> 16) & 0xf,
2926 (opcode >> 0) & 0xf);
2927 break;
2928 case 0x1f:
2929 case 0x3f:
2930 sprintf(cp, "%cDIV\tr%d, r%d, r%d",
2931 (op & 0x20) ? 'U' : 'S',
2932 (opcode >> 8) & 0xf,
2933 (opcode >> 16) & 0xf,
2934 (opcode >> 0) & 0xf);
2935 break;
2936 default:
2937 return ERROR_INVALID_ARGUMENTS;
2938 }
2939
2940 return ERROR_OK;
2941 }
2942
2943 static int t2ev_ldm_stm(uint32_t opcode, uint32_t address,
2944 arm_instruction_t *instruction, char *cp)
2945 {
2946 int rn = (opcode >> 16) & 0xf;
2947 int op = (opcode >> 22) & 0x6;
2948 int t = (opcode >> 21) & 1;
2949 unsigned registers = opcode & 0xffff;
2950
2951 if (opcode & (1 << 20))
2952 op |= 1;
2953
2954 switch (op) {
2955 case 2:
2956 sprintf(cp, "STMB\tr%d%s, ", rn, t ? "!" : "");
2957 break;
2958 case 3:
2959 if (rn == 13 && t)
2960 sprintf(cp, "POP\t");
2961 else
2962 sprintf(cp, "LDM\tr%d%s, ", rn, t ? "!" : "");
2963 break;
2964 case 4:
2965 if (rn == 13 && t)
2966 sprintf(cp, "PUSH\t");
2967 else
2968 sprintf(cp, "STM\tr%d%s, ", rn, t ? "!" : "");
2969 break;
2970 case 5:
2971 sprintf(cp, "LDMB\tr%d%s, ", rn, t ? "!" : "");
2972 break;
2973 default:
2974 return ERROR_INVALID_ARGUMENTS;
2975 }
2976
2977 cp = strchr(cp, 0);
2978 *cp++ = '{';
2979 for (t = 0; registers; t++, registers >>= 1) {
2980 if ((registers & 1) == 0)
2981 continue;
2982 registers &= ~1;
2983 sprintf(cp, "r%d%s", t, registers ? "," : "");
2984 cp = strchr(cp, 0);
2985 }
2986 *cp++ = '}';
2987 *cp++ = 0;
2988
2989 return ERROR_OK;
2990 }
2991
2992 /*
2993 * REVISIT for Thumb2 instructions, instruction->type and friends aren't
2994 * always set. That means eventual arm_simulate_step() support for Thumb2
2995 * will need work in this area.
2996 */
2997 int thumb2_opcode(target_t *target, uint32_t address, arm_instruction_t *instruction)
2998 {
2999 int retval;
3000 uint16_t op;
3001 uint32_t opcode;
3002 char *cp;
3003
3004 /* clear low bit ... it's set on function pointers */
3005 address &= ~1;
3006
3007 /* clear fields, to avoid confusion */
3008 memset(instruction, 0, sizeof(arm_instruction_t));
3009
3010 /* read first halfword, see if this is the only one */
3011 retval = target_read_u16(target, address, &op);
3012 if (retval != ERROR_OK)
3013 return retval;
3014
3015 switch (op & 0xf800) {
3016 case 0xf800:
3017 case 0xf000:
3018 case 0xe800:
3019 /* 32-bit instructions */
3020 instruction->instruction_size = 4;
3021 opcode = op << 16;
3022 retval = target_read_u16(target, address + 2, &op);
3023 if (retval != ERROR_OK)
3024 return retval;
3025 opcode |= op;
3026 instruction->opcode = opcode;
3027 break;
3028 default:
3029 /* 16-bit: Thumb1 + IT + CBZ/CBNZ + ... */
3030 return thumb_evaluate_opcode(op, address, instruction);
3031 }
3032
3033 snprintf(instruction->text, 128,
3034 "0x%8.8" PRIx32 " 0x%8.8" PRIx32 "\t",
3035 address, opcode);
3036 cp = strchr(instruction->text, 0);
3037 retval = ERROR_FAIL;
3038
3039 /* ARMv7-M: A5.3.1 Data processing (modified immediate) */
3040 if ((opcode & 0x1a008000) == 0x10000000)
3041 retval = t2ev_data_mod_immed(opcode, address, instruction, cp);
3042
3043 /* ARMv7-M: A5.3.3 Data processing (plain binary immediate) */
3044 else if ((opcode & 0x1a008000) == 0x12000000)
3045 retval = t2ev_data_immed(opcode, address, instruction, cp);
3046
3047 /* ARMv7-M: A5.3.4 Branches and miscellaneous control */
3048 else if ((opcode & 0x18008000) == 0x10008000)
3049 retval = t2ev_b_misc(opcode, address, instruction, cp);
3050
3051 /* ARMv7-M: A5.3.5 Load/store multiple */
3052 else if ((opcode & 0x1e400000) == 0x08000000)
3053 retval = t2ev_ldm_stm(opcode, address, instruction, cp);
3054
3055 /* ARMv7-M: A5.3.10 Store single data item */
3056 else if ((opcode & 0x1f100000) == 0x18000000)
3057 retval = t2ev_store_single(opcode, address, instruction, cp);
3058
3059 /* ARMv7-M: A5.3.14 Multiply, and multiply accumulate */
3060 else if ((opcode & 0x1f800000) == 0x1b000000)
3061 retval = t2ev_mul32(opcode, address, instruction, cp);
3062
3063 /* ARMv7-M: A5.3.15 Long multiply, long multiply accumulate, divide */
3064 else if ((opcode & 0x1f800000) == 0x1b800000)
3065 retval = t2ev_mul64_div(opcode, address, instruction, cp);
3066
3067 /* FIXME decode more 32-bit instructions */
3068
3069 if (retval == ERROR_OK)
3070 return retval;
3071
3072 if (retval == ERROR_INVALID_ARGUMENTS) {
3073 instruction->type = ARM_UNDEFINED_INSTRUCTION;
3074 strcpy(cp, "UNDEFINED OPCODE");
3075 return ERROR_OK;
3076 }
3077
3078 LOG_DEBUG("Can't decode 32-bit Thumb2 yet (opcode=%08x)", opcode);
3079
3080 strcpy(cp, "(32-bit Thumb2 ...)");
3081 return ERROR_OK;
3082 }
3083
3084 int arm_access_size(arm_instruction_t *instruction)
3085 {
3086 if ((instruction->type == ARM_LDRB)
3087 || (instruction->type == ARM_LDRBT)
3088 || (instruction->type == ARM_LDRSB)
3089 || (instruction->type == ARM_STRB)
3090 || (instruction->type == ARM_STRBT))
3091 {
3092 return 1;
3093 }
3094 else if ((instruction->type == ARM_LDRH)
3095 || (instruction->type == ARM_LDRSH)
3096 || (instruction->type == ARM_STRH))
3097 {
3098 return 2;
3099 }
3100 else if ((instruction->type == ARM_LDR)
3101 || (instruction->type == ARM_LDRT)
3102 || (instruction->type == ARM_STR)
3103 || (instruction->type == ARM_STRT))
3104 {
3105 return 4;
3106 }
3107 else if ((instruction->type == ARM_LDRD)
3108 || (instruction->type == ARM_STRD))
3109 {
3110 return 8;
3111 }
3112 else
3113 {
3114 LOG_ERROR("BUG: instruction type %i isn't a load/store instruction", instruction->type);
3115 return 0;
3116 }
3117 }

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)