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
1516 high_reg = (opcode & 0x0400) >> 10;
1517 op = (opcode & 0x03C0) >> 6;
1518
1519 Rd = (opcode & 0x0007);
1520 Rm = (opcode & 0x0038) >> 3;
1521 H1 = (opcode & 0x0080) >> 7;
1522 H2 = (opcode & 0x0040) >> 6;
1523
1524 instruction->info.data_proc.Rd = Rd;
1525 instruction->info.data_proc.Rn = Rd;
1526 instruction->info.data_proc.S = (!high_reg || (instruction->type == ARM_CMP));
1527 instruction->info.data_proc.variant = 1 /*immediate shift*/;
1528 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1529
1530 if (high_reg)
1531 {
1532 Rd |= H1 << 3;
1533 Rm |= H2 << 3;
1534 op >>= 2;
1535
1536 switch (op)
1537 {
1538 case 0x0:
1539 instruction->type = ARM_ADD;
1540 mnemonic = "ADD";
1541 break;
1542 case 0x1:
1543 instruction->type = ARM_CMP;
1544 mnemonic = "CMP";
1545 break;
1546 case 0x2:
1547 instruction->type = ARM_MOV;
1548 mnemonic = "MOV";
1549 break;
1550 case 0x3:
1551 if ((opcode & 0x7) == 0x0)
1552 {
1553 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1554 if (H1)
1555 {
1556 instruction->type = ARM_BLX;
1557 snprintf(instruction->text, 128,
1558 "0x%8.8" PRIx32
1559 " 0x%4.4x \tBLX\tr%i",
1560 address, opcode, Rm);
1561 }
1562 else
1563 {
1564 instruction->type = ARM_BX;
1565 snprintf(instruction->text, 128,
1566 "0x%8.8" PRIx32
1567 " 0x%4.4x \tBX\tr%i",
1568 address, opcode, Rm);
1569 }
1570 }
1571 else
1572 {
1573 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1574 snprintf(instruction->text, 128,
1575 "0x%8.8" PRIx32
1576 " 0x%4.4x \t"
1577 "UNDEFINED INSTRUCTION",
1578 address, opcode);
1579 }
1580 return ERROR_OK;
1581 break;
1582 }
1583 }
1584 else
1585 {
1586 switch (op)
1587 {
1588 case 0x0:
1589 instruction->type = ARM_AND;
1590 mnemonic = "ANDS";
1591 break;
1592 case 0x1:
1593 instruction->type = ARM_EOR;
1594 mnemonic = "EORS";
1595 break;
1596 case 0x2:
1597 instruction->type = ARM_MOV;
1598 mnemonic = "LSLS";
1599 instruction->info.data_proc.variant = 2 /*register shift*/;
1600 instruction->info.data_proc.shifter_operand.register_shift.shift = 0;
1601 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1602 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1603 break;
1604 case 0x3:
1605 instruction->type = ARM_MOV;
1606 mnemonic = "LSRS";
1607 instruction->info.data_proc.variant = 2 /*register shift*/;
1608 instruction->info.data_proc.shifter_operand.register_shift.shift = 1;
1609 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1610 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1611 break;
1612 case 0x4:
1613 instruction->type = ARM_MOV;
1614 mnemonic = "ASRS";
1615 instruction->info.data_proc.variant = 2 /*register shift*/;
1616 instruction->info.data_proc.shifter_operand.register_shift.shift = 2;
1617 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1618 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1619 break;
1620 case 0x5:
1621 instruction->type = ARM_ADC;
1622 mnemonic = "ADCS";
1623 break;
1624 case 0x6:
1625 instruction->type = ARM_SBC;
1626 mnemonic = "SBCS";
1627 break;
1628 case 0x7:
1629 instruction->type = ARM_MOV;
1630 mnemonic = "RORS";
1631 instruction->info.data_proc.variant = 2 /*register shift*/;
1632 instruction->info.data_proc.shifter_operand.register_shift.shift = 3;
1633 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1634 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1635 break;
1636 case 0x8:
1637 instruction->type = ARM_TST;
1638 mnemonic = "TST";
1639 break;
1640 case 0x9:
1641 instruction->type = ARM_RSB;
1642 mnemonic = "NEGS";
1643 instruction->info.data_proc.variant = 0 /*immediate*/;
1644 instruction->info.data_proc.shifter_operand.immediate.immediate = 0;
1645 instruction->info.data_proc.Rn = Rm;
1646 break;
1647 case 0xA:
1648 instruction->type = ARM_CMP;
1649 mnemonic = "CMP";
1650 break;
1651 case 0xB:
1652 instruction->type = ARM_CMN;
1653 mnemonic = "CMN";
1654 break;
1655 case 0xC:
1656 instruction->type = ARM_ORR;
1657 mnemonic = "ORRS";
1658 break;
1659 case 0xD:
1660 instruction->type = ARM_MUL;
1661 mnemonic = "MULS";
1662 break;
1663 case 0xE:
1664 instruction->type = ARM_BIC;
1665 mnemonic = "BICS";
1666 break;
1667 case 0xF:
1668 instruction->type = ARM_MVN;
1669 mnemonic = "MVNS";
1670 break;
1671 }
1672 }
1673
1674 snprintf(instruction->text, 128,
1675 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i",
1676 address, opcode, mnemonic, Rd, Rm);
1677
1678 return ERROR_OK;
1679 }
1680
1681 /* PC-relative data addressing is word-aligned even with Thumb */
1682 static inline uint32_t thumb_alignpc4(uint32_t addr)
1683 {
1684 return (addr + 4) & ~3;
1685 }
1686
1687 int evaluate_load_literal_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1688 {
1689 uint32_t immediate;
1690 uint8_t Rd = (opcode >> 8) & 0x7;
1691
1692 instruction->type = ARM_LDR;
1693 immediate = opcode & 0x000000ff;
1694 immediate *= 4;
1695
1696 instruction->info.load_store.Rd = Rd;
1697 instruction->info.load_store.Rn = 15 /*PC*/;
1698 instruction->info.load_store.index_mode = 0; /*offset*/
1699 instruction->info.load_store.offset_mode = 0; /*immediate*/
1700 instruction->info.load_store.offset.offset = immediate;
1701
1702 snprintf(instruction->text, 128,
1703 "0x%8.8" PRIx32 " 0x%4.4x \t"
1704 "LDR\tr%i, [pc, #%#" PRIx32 "]\t; %#8.8x",
1705 address, opcode, Rd, immediate,
1706 thumb_alignpc4(address) + immediate);
1707
1708 return ERROR_OK;
1709 }
1710
1711 int evaluate_load_store_reg_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1712 {
1713 uint8_t Rd = (opcode >> 0) & 0x7;
1714 uint8_t Rn = (opcode >> 3) & 0x7;
1715 uint8_t Rm = (opcode >> 6) & 0x7;
1716 uint8_t opc = (opcode >> 9) & 0x7;
1717 char *mnemonic = NULL;
1718
1719 switch (opc)
1720 {
1721 case 0:
1722 instruction->type = ARM_STR;
1723 mnemonic = "STR";
1724 break;
1725 case 1:
1726 instruction->type = ARM_STRH;
1727 mnemonic = "STRH";
1728 break;
1729 case 2:
1730 instruction->type = ARM_STRB;
1731 mnemonic = "STRB";
1732 break;
1733 case 3:
1734 instruction->type = ARM_LDRSB;
1735 mnemonic = "LDRSB";
1736 break;
1737 case 4:
1738 instruction->type = ARM_LDR;
1739 mnemonic = "LDR";
1740 break;
1741 case 5:
1742 instruction->type = ARM_LDRH;
1743 mnemonic = "LDRH";
1744 break;
1745 case 6:
1746 instruction->type = ARM_LDRB;
1747 mnemonic = "LDRB";
1748 break;
1749 case 7:
1750 instruction->type = ARM_LDRSH;
1751 mnemonic = "LDRSH";
1752 break;
1753 }
1754
1755 snprintf(instruction->text, 128,
1756 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [r%i, r%i]",
1757 address, opcode, mnemonic, Rd, Rn, Rm);
1758
1759 instruction->info.load_store.Rd = Rd;
1760 instruction->info.load_store.Rn = Rn;
1761 instruction->info.load_store.index_mode = 0; /*offset*/
1762 instruction->info.load_store.offset_mode = 1; /*register*/
1763 instruction->info.load_store.offset.reg.Rm = Rm;
1764
1765 return ERROR_OK;
1766 }
1767
1768 int evaluate_load_store_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1769 {
1770 uint32_t offset = (opcode >> 6) & 0x1f;
1771 uint8_t Rd = (opcode >> 0) & 0x7;
1772 uint8_t Rn = (opcode >> 3) & 0x7;
1773 uint32_t L = opcode & (1 << 11);
1774 uint32_t B = opcode & (1 << 12);
1775 char *mnemonic;
1776 char suffix = ' ';
1777 uint32_t shift = 2;
1778
1779 if (L)
1780 {
1781 instruction->type = ARM_LDR;
1782 mnemonic = "LDR";
1783 }
1784 else
1785 {
1786 instruction->type = ARM_STR;
1787 mnemonic = "STR";
1788 }
1789
1790 if ((opcode&0xF000) == 0x8000)
1791 {
1792 suffix = 'H';
1793 shift = 1;
1794 }
1795 else if (B)
1796 {
1797 suffix = 'B';
1798 shift = 0;
1799 }
1800
1801 snprintf(instruction->text, 128,
1802 "0x%8.8" PRIx32 " 0x%4.4x \t%s%c\tr%i, [r%i, #%#" PRIx32 "]",
1803 address, opcode, mnemonic, suffix, Rd, Rn, offset << shift);
1804
1805 instruction->info.load_store.Rd = Rd;
1806 instruction->info.load_store.Rn = Rn;
1807 instruction->info.load_store.index_mode = 0; /*offset*/
1808 instruction->info.load_store.offset_mode = 0; /*immediate*/
1809 instruction->info.load_store.offset.offset = offset << shift;
1810
1811 return ERROR_OK;
1812 }
1813
1814 int evaluate_load_store_stack_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1815 {
1816 uint32_t offset = opcode & 0xff;
1817 uint8_t Rd = (opcode >> 8) & 0x7;
1818 uint32_t L = opcode & (1 << 11);
1819 char *mnemonic;
1820
1821 if (L)
1822 {
1823 instruction->type = ARM_LDR;
1824 mnemonic = "LDR";
1825 }
1826 else
1827 {
1828 instruction->type = ARM_STR;
1829 mnemonic = "STR";
1830 }
1831
1832 snprintf(instruction->text, 128,
1833 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [SP, #%#" PRIx32 "]",
1834 address, opcode, mnemonic, Rd, offset*4);
1835
1836 instruction->info.load_store.Rd = Rd;
1837 instruction->info.load_store.Rn = 13 /*SP*/;
1838 instruction->info.load_store.index_mode = 0; /*offset*/
1839 instruction->info.load_store.offset_mode = 0; /*immediate*/
1840 instruction->info.load_store.offset.offset = offset*4;
1841
1842 return ERROR_OK;
1843 }
1844
1845 int evaluate_add_sp_pc_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1846 {
1847 uint32_t imm = opcode & 0xff;
1848 uint8_t Rd = (opcode >> 8) & 0x7;
1849 uint8_t Rn;
1850 uint32_t SP = opcode & (1 << 11);
1851 char *reg_name;
1852
1853 instruction->type = ARM_ADD;
1854
1855 if (SP)
1856 {
1857 reg_name = "SP";
1858 Rn = 13;
1859 }
1860 else
1861 {
1862 reg_name = "PC";
1863 Rn = 15;
1864 }
1865
1866 snprintf(instruction->text, 128,
1867 "0x%8.8" PRIx32 " 0x%4.4x \tADD\tr%i, %s, #%#" PRIx32,
1868 address, opcode, Rd, reg_name, imm * 4);
1869
1870 instruction->info.data_proc.variant = 0 /* immediate */;
1871 instruction->info.data_proc.Rd = Rd;
1872 instruction->info.data_proc.Rn = Rn;
1873 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
1874
1875 return ERROR_OK;
1876 }
1877
1878 int evaluate_adjust_stack_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1879 {
1880 uint32_t imm = opcode & 0x7f;
1881 uint8_t opc = opcode & (1 << 7);
1882 char *mnemonic;
1883
1884
1885 if (opc)
1886 {
1887 instruction->type = ARM_SUB;
1888 mnemonic = "SUB";
1889 }
1890 else
1891 {
1892 instruction->type = ARM_ADD;
1893 mnemonic = "ADD";
1894 }
1895
1896 snprintf(instruction->text, 128,
1897 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tSP, #%#" PRIx32,
1898 address, opcode, mnemonic, imm*4);
1899
1900 instruction->info.data_proc.variant = 0 /* immediate */;
1901 instruction->info.data_proc.Rd = 13 /*SP*/;
1902 instruction->info.data_proc.Rn = 13 /*SP*/;
1903 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
1904
1905 return ERROR_OK;
1906 }
1907
1908 int evaluate_breakpoint_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1909 {
1910 uint32_t imm = opcode & 0xff;
1911
1912 instruction->type = ARM_BKPT;
1913
1914 snprintf(instruction->text, 128,
1915 "0x%8.8" PRIx32 " 0x%4.4x \tBKPT\t%#2.2" PRIx32 "",
1916 address, opcode, imm);
1917
1918 return ERROR_OK;
1919 }
1920
1921 int evaluate_load_store_multiple_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1922 {
1923 uint32_t reg_list = opcode & 0xff;
1924 uint32_t L = opcode & (1 << 11);
1925 uint32_t R = opcode & (1 << 8);
1926 uint8_t Rn = (opcode >> 8) & 7;
1927 uint8_t addr_mode = 0 /* IA */;
1928 char reg_names[40];
1929 char *reg_names_p;
1930 char *mnemonic;
1931 char ptr_name[7] = "";
1932 int i;
1933
1934 if ((opcode & 0xf000) == 0xc000)
1935 { /* generic load/store multiple */
1936 if (L)
1937 {
1938 instruction->type = ARM_LDM;
1939 mnemonic = "LDM";
1940 }
1941 else
1942 {
1943 instruction->type = ARM_STM;
1944 mnemonic = "STM";
1945 }
1946 snprintf(ptr_name,7,"r%i!, ",Rn);
1947 }
1948 else
1949 { /* push/pop */
1950 Rn = 13; /* SP */
1951 if (L)
1952 {
1953 instruction->type = ARM_LDM;
1954 mnemonic = "POP";
1955 if (R)
1956 reg_list |= (1 << 15) /*PC*/;
1957 }
1958 else
1959 {
1960 instruction->type = ARM_STM;
1961 mnemonic = "PUSH";
1962 addr_mode = 3; /*DB*/
1963 if (R)
1964 reg_list |= (1 << 14) /*LR*/;
1965 }
1966 }
1967
1968 reg_names_p = reg_names;
1969 for (i = 0; i <= 15; i++)
1970 {
1971 if (reg_list & (1 << i))
1972 reg_names_p += snprintf(reg_names_p, (reg_names + 40 - reg_names_p), "r%i, ", i);
1973 }
1974 if (reg_names_p > reg_names)
1975 reg_names_p[-2] = '\0';
1976 else /* invalid op : no registers */
1977 reg_names[0] = '\0';
1978
1979 snprintf(instruction->text, 128,
1980 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%s{%s}",
1981 address, opcode, mnemonic, ptr_name, reg_names);
1982
1983 instruction->info.load_store_multiple.register_list = reg_list;
1984 instruction->info.load_store_multiple.Rn = Rn;
1985 instruction->info.load_store_multiple.addressing_mode = addr_mode;
1986
1987 return ERROR_OK;
1988 }
1989
1990 int evaluate_cond_branch_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1991 {
1992 uint32_t offset = opcode & 0xff;
1993 uint8_t cond = (opcode >> 8) & 0xf;
1994 uint32_t target_address;
1995
1996 if (cond == 0xf)
1997 {
1998 instruction->type = ARM_SWI;
1999 snprintf(instruction->text, 128,
2000 "0x%8.8" PRIx32 " 0x%4.4x \tSVC\t%#2.2" PRIx32,
2001 address, opcode, offset);
2002 return ERROR_OK;
2003 }
2004 else if (cond == 0xe)
2005 {
2006 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2007 snprintf(instruction->text, 128,
2008 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2009 address, opcode);
2010 return ERROR_OK;
2011 }
2012
2013 /* sign extend 8-bit offset */
2014 if (offset & 0x00000080)
2015 offset = 0xffffff00 | offset;
2016
2017 target_address = address + 4 + (offset << 1);
2018
2019 snprintf(instruction->text, 128,
2020 "0x%8.8" PRIx32 " 0x%4.4x \tB%s\t%#8.8" PRIx32,
2021 address, opcode,
2022 arm_condition_strings[cond], target_address);
2023
2024 instruction->type = ARM_B;
2025 instruction->info.b_bl_bx_blx.reg_operand = -1;
2026 instruction->info.b_bl_bx_blx.target_address = target_address;
2027
2028 return ERROR_OK;
2029 }
2030
2031 static int evaluate_cb_thumb(uint16_t opcode, uint32_t address,
2032 arm_instruction_t *instruction)
2033 {
2034 unsigned offset;
2035
2036 /* added in Thumb2 */
2037 offset = (opcode >> 3) & 0x1f;
2038 offset |= (opcode & 0x0200) >> 4;
2039
2040 snprintf(instruction->text, 128,
2041 "0x%8.8" PRIx32 " 0x%4.4x \tCB%sZ\tr%d, %#8.8" PRIx32,
2042 address, opcode,
2043 (opcode & 0x0800) ? "N" : "",
2044 opcode & 0x7, address + 4 + (offset << 1));
2045
2046 return ERROR_OK;
2047 }
2048
2049 static int evaluate_extend_thumb(uint16_t opcode, uint32_t address,
2050 arm_instruction_t *instruction)
2051 {
2052 /* added in ARMv6 */
2053 snprintf(instruction->text, 128,
2054 "0x%8.8" PRIx32 " 0x%4.4x \t%cXT%c\tr%d, r%d",
2055 address, opcode,
2056 (opcode & 0x0080) ? 'U' : 'S',
2057 (opcode & 0x0040) ? 'B' : 'H',
2058 opcode & 0x7, (opcode >> 3) & 0x7);
2059
2060 return ERROR_OK;
2061 }
2062
2063 static int evaluate_cps_thumb(uint16_t opcode, uint32_t address,
2064 arm_instruction_t *instruction)
2065 {
2066 /* added in ARMv6 */
2067 if ((opcode & 0x0ff0) == 0x0650)
2068 snprintf(instruction->text, 128,
2069 "0x%8.8" PRIx32 " 0x%4.4x \tSETEND %s",
2070 address, opcode,
2071 (opcode & 0x80) ? "BE" : "LE");
2072 else /* ASSUME (opcode & 0x0fe0) == 0x0660 */
2073 snprintf(instruction->text, 128,
2074 "0x%8.8" PRIx32 " 0x%4.4x \tCPSI%c %s%s%s",
2075 address, opcode,
2076 (opcode & 0x0010) ? 'D' : 'E',
2077 (opcode & 0x0004) ? "A" : "",
2078 (opcode & 0x0002) ? "I" : "",
2079 (opcode & 0x0001) ? "F" : "");
2080
2081 return ERROR_OK;
2082 }
2083
2084 static int evaluate_byterev_thumb(uint16_t opcode, uint32_t address,
2085 arm_instruction_t *instruction)
2086 {
2087 char *suffix;
2088
2089 /* added in ARMv6 */
2090 switch (opcode & 0x00c0) {
2091 case 0:
2092 suffix = "";
2093 break;
2094 case 1:
2095 suffix = "16";
2096 break;
2097 default:
2098 suffix = "SH";
2099 break;
2100 }
2101 snprintf(instruction->text, 128,
2102 "0x%8.8" PRIx32 " 0x%4.4x \tREV%s\tr%d, r%d",
2103 address, opcode, suffix,
2104 opcode & 0x7, (opcode >> 3) & 0x7);
2105
2106 return ERROR_OK;
2107 }
2108
2109 static int evaluate_hint_thumb(uint16_t opcode, uint32_t address,
2110 arm_instruction_t *instruction)
2111 {
2112 char *hint;
2113
2114 switch ((opcode >> 4) & 0x0f) {
2115 case 0:
2116 hint = "NOP";
2117 break;
2118 case 1:
2119 hint = "YIELD";
2120 break;
2121 case 2:
2122 hint = "WFE";
2123 break;
2124 case 3:
2125 hint = "WFI";
2126 break;
2127 case 4:
2128 hint = "SEV";
2129 break;
2130 default:
2131 hint = "HINT (UNRECOGNIZED)";
2132 break;
2133 }
2134
2135 snprintf(instruction->text, 128,
2136 "0x%8.8" PRIx32 " 0x%4.4x \t%s",
2137 address, opcode, hint);
2138
2139 return ERROR_OK;
2140 }
2141
2142 static int evaluate_ifthen_thumb(uint16_t opcode, uint32_t address,
2143 arm_instruction_t *instruction)
2144 {
2145 unsigned cond = (opcode >> 4) & 0x0f;
2146 char *x = "", *y = "", *z = "";
2147
2148 if (opcode & 0x01)
2149 z = (opcode & 0x02) ? "T" : "E";
2150 if (opcode & 0x03)
2151 y = (opcode & 0x04) ? "T" : "E";
2152 if (opcode & 0x07)
2153 x = (opcode & 0x08) ? "T" : "E";
2154
2155 snprintf(instruction->text, 128,
2156 "0x%8.8" PRIx32 " 0x%4.4x \tIT%s%s%s\t%s",
2157 address, opcode,
2158 x, y, z, arm_condition_strings[cond]);
2159
2160 /* NOTE: strictly speaking, the next 1-4 instructions should
2161 * now be displayed with the relevant conditional suffix...
2162 */
2163
2164 return ERROR_OK;
2165 }
2166
2167 int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
2168 {
2169 /* clear fields, to avoid confusion */
2170 memset(instruction, 0, sizeof(arm_instruction_t));
2171 instruction->opcode = opcode;
2172 instruction->instruction_size = 2;
2173
2174 if ((opcode & 0xe000) == 0x0000)
2175 {
2176 /* add/substract register or immediate */
2177 if ((opcode & 0x1800) == 0x1800)
2178 return evaluate_add_sub_thumb(opcode, address, instruction);
2179 /* shift by immediate */
2180 else
2181 return evaluate_shift_imm_thumb(opcode, address, instruction);
2182 }
2183
2184 /* Add/substract/compare/move immediate */
2185 if ((opcode & 0xe000) == 0x2000)
2186 {
2187 return evaluate_data_proc_imm_thumb(opcode, address, instruction);
2188 }
2189
2190 /* Data processing instructions */
2191 if ((opcode & 0xf800) == 0x4000)
2192 {
2193 return evaluate_data_proc_thumb(opcode, address, instruction);
2194 }
2195
2196 /* Load from literal pool */
2197 if ((opcode & 0xf800) == 0x4800)
2198 {
2199 return evaluate_load_literal_thumb(opcode, address, instruction);
2200 }
2201
2202 /* Load/Store register offset */
2203 if ((opcode & 0xf000) == 0x5000)
2204 {
2205 return evaluate_load_store_reg_thumb(opcode, address, instruction);
2206 }
2207
2208 /* Load/Store immediate offset */
2209 if (((opcode & 0xe000) == 0x6000)
2210 ||((opcode & 0xf000) == 0x8000))
2211 {
2212 return evaluate_load_store_imm_thumb(opcode, address, instruction);
2213 }
2214
2215 /* Load/Store from/to stack */
2216 if ((opcode & 0xf000) == 0x9000)
2217 {
2218 return evaluate_load_store_stack_thumb(opcode, address, instruction);
2219 }
2220
2221 /* Add to SP/PC */
2222 if ((opcode & 0xf000) == 0xa000)
2223 {
2224 return evaluate_add_sp_pc_thumb(opcode, address, instruction);
2225 }
2226
2227 /* Misc */
2228 if ((opcode & 0xf000) == 0xb000)
2229 {
2230 switch ((opcode >> 8) & 0x0f) {
2231 case 0x0:
2232 return evaluate_adjust_stack_thumb(opcode, address, instruction);
2233 case 0x1:
2234 case 0x3:
2235 case 0x9:
2236 case 0xb:
2237 return evaluate_cb_thumb(opcode, address, instruction);
2238 case 0x2:
2239 return evaluate_extend_thumb(opcode, address, instruction);
2240 case 0x4:
2241 case 0x5:
2242 case 0xc:
2243 case 0xd:
2244 return evaluate_load_store_multiple_thumb(opcode, address,
2245 instruction);
2246 case 0x6:
2247 return evaluate_cps_thumb(opcode, address, instruction);
2248 case 0xa:
2249 if ((opcode & 0x00c0) == 0x0080)
2250 break;
2251 return evaluate_byterev_thumb(opcode, address, instruction);
2252 case 0xe:
2253 return evaluate_breakpoint_thumb(opcode, address, instruction);
2254 case 0xf:
2255 if (opcode & 0x000f)
2256 return evaluate_ifthen_thumb(opcode, address,
2257 instruction);
2258 else
2259 return evaluate_hint_thumb(opcode, address,
2260 instruction);
2261 }
2262
2263 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2264 snprintf(instruction->text, 128,
2265 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2266 address, opcode);
2267 return ERROR_OK;
2268 }
2269
2270 /* Load/Store multiple */
2271 if ((opcode & 0xf000) == 0xc000)
2272 {
2273 return evaluate_load_store_multiple_thumb(opcode, address, instruction);
2274 }
2275
2276 /* Conditional branch + SWI */
2277 if ((opcode & 0xf000) == 0xd000)
2278 {
2279 return evaluate_cond_branch_thumb(opcode, address, instruction);
2280 }
2281
2282 if ((opcode & 0xe000) == 0xe000)
2283 {
2284 /* Undefined instructions */
2285 if ((opcode & 0xf801) == 0xe801)
2286 {
2287 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2288 snprintf(instruction->text, 128,
2289 "0x%8.8" PRIx32 " 0x%8.8x\t"
2290 "UNDEFINED INSTRUCTION",
2291 address, opcode);
2292 return ERROR_OK;
2293 }
2294 else
2295 { /* Branch to offset */
2296 return evaluate_b_bl_blx_thumb(opcode, address, instruction);
2297 }
2298 }
2299
2300 LOG_ERROR("should never reach this point (opcode=%04x)",opcode);
2301 return -1;
2302 }
2303
2304 static int t2ev_b_bl(uint32_t opcode, uint32_t address,
2305 arm_instruction_t *instruction, char *cp)
2306 {
2307 unsigned offset;
2308 unsigned b21 = 1 << 21;
2309 unsigned b22 = 1 << 22;
2310
2311 /* instead of combining two smaller 16-bit branch instructions,
2312 * Thumb2 uses only one larger 32-bit instruction.
2313 */
2314 offset = opcode & 0x7ff;
2315 offset |= (opcode & 0x03ff0000) >> 5;
2316 if (opcode & (1 << 26)) {
2317 offset |= 0xff << 23;
2318 if ((opcode & (1 << 11)) == 0)
2319 b21 = 0;
2320 if ((opcode & (1 << 13)) == 0)
2321 b22 = 0;
2322 } else {
2323 if (opcode & (1 << 11))
2324 b21 = 0;
2325 if (opcode & (1 << 13))
2326 b22 = 0;
2327 }
2328 offset |= b21;
2329 offset |= b22;
2330
2331
2332 address += 4;
2333 address += offset << 1;
2334
2335 instruction->type = (opcode & (1 << 14)) ? ARM_BL : ARM_B;
2336 instruction->info.b_bl_bx_blx.reg_operand = -1;
2337 instruction->info.b_bl_bx_blx.target_address = address;
2338 sprintf(cp, "%s\t%#8.8" PRIx32,
2339 (opcode & (1 << 14)) ? "BL" : "B.W",
2340 address);
2341
2342 return ERROR_OK;
2343 }
2344
2345 static int t2ev_cond_b(uint32_t opcode, uint32_t address,
2346 arm_instruction_t *instruction, char *cp)
2347 {
2348 unsigned offset;
2349 unsigned b17 = 1 << 17;
2350 unsigned b18 = 1 << 18;
2351 unsigned cond = (opcode >> 22) & 0x0f;
2352
2353 offset = opcode & 0x7ff;
2354 offset |= (opcode & 0x003f0000) >> 5;
2355 if (opcode & (1 << 26)) {
2356 offset |= 0xffff << 19;
2357 if ((opcode & (1 << 11)) == 0)
2358 b17 = 0;
2359 if ((opcode & (1 << 13)) == 0)
2360 b18 = 0;
2361 } else {
2362 if (opcode & (1 << 11))
2363 b17 = 0;
2364 if (opcode & (1 << 13))
2365 b18 = 0;
2366 }
2367 offset |= b17;
2368 offset |= b18;
2369
2370 address += 4;
2371 address += offset << 1;
2372
2373 instruction->type = ARM_B;
2374 instruction->info.b_bl_bx_blx.reg_operand = -1;
2375 instruction->info.b_bl_bx_blx.target_address = address;
2376 sprintf(cp, "B%s.W\t%#8.8" PRIx32,
2377 arm_condition_strings[cond],
2378 address);
2379
2380 return ERROR_OK;
2381 }
2382
2383 static const char *special_name(int number)
2384 {
2385 char *special = "(RESERVED)";
2386
2387 switch (number) {
2388 case 0:
2389 special = "apsr";
2390 break;
2391 case 1:
2392 special = "iapsr";
2393 break;
2394 case 2:
2395 special = "eapsr";
2396 break;
2397 case 3:
2398 special = "xpsr";
2399 break;
2400 case 5:
2401 special = "ipsr";
2402 break;
2403 case 6:
2404 special = "epsr";
2405 break;
2406 case 7:
2407 special = "iepsr";
2408 break;
2409 case 8:
2410 special = "msp";
2411 break;
2412 case 9:
2413 special = "psp";
2414 break;
2415 case 16:
2416 special = "primask";
2417 break;
2418 case 17:
2419 special = "basepri";
2420 break;
2421 case 18:
2422 special = "basepri_max";
2423 break;
2424 case 19:
2425 special = "faultmask";
2426 break;
2427 case 20:
2428 special = "control";
2429 break;
2430 }
2431 return special;
2432 }
2433
2434 static int t2ev_hint(uint32_t opcode, uint32_t address,
2435 arm_instruction_t *instruction, char *cp)
2436 {
2437 const char *mnemonic;
2438
2439 if (opcode & 0x0700) {
2440 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2441 strcpy(cp, "UNDEFINED");
2442 return ERROR_OK;
2443 }
2444
2445 if (opcode & 0x00f0) {
2446 sprintf(cp, "DBG\t#%d", opcode & 0xf);
2447 return ERROR_OK;
2448 }
2449
2450 switch (opcode & 0x0f) {
2451 case 0:
2452 mnemonic = "NOP.W";
2453 break;
2454 case 1:
2455 mnemonic = "YIELD.W";
2456 break;
2457 case 2:
2458 mnemonic = "WFE.W";
2459 break;
2460 case 3:
2461 mnemonic = "WFI.W";
2462 break;
2463 case 4:
2464 mnemonic = "SEV.W";
2465 break;
2466 default:
2467 mnemonic = "HINT.W (UNRECOGNIZED)";
2468 break;
2469 }
2470 strcpy(cp, mnemonic);
2471 return ERROR_OK;
2472 }
2473
2474 static int t2ev_misc(uint32_t opcode, uint32_t address,
2475 arm_instruction_t *instruction, char *cp)
2476 {
2477 const char *mnemonic;
2478
2479 switch ((opcode >> 4) & 0x0f) {
2480 case 2:
2481 mnemonic = "CLREX";
2482 break;
2483 case 4:
2484 mnemonic = "DSB";
2485 break;
2486 case 5:
2487 mnemonic = "DMB";
2488 break;
2489 case 6:
2490 mnemonic = "ISB";
2491 break;
2492 default:
2493 return ERROR_INVALID_ARGUMENTS;
2494 }
2495 strcpy(cp, mnemonic);
2496 return ERROR_OK;
2497 }
2498
2499 static int t2ev_b_misc(uint32_t opcode, uint32_t address,
2500 arm_instruction_t *instruction, char *cp)
2501 {
2502 /* permanently undefined */
2503 if ((opcode & 0x07f07000) == 0x07f02000) {
2504 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2505 strcpy(cp, "UNDEFINED");
2506 return ERROR_OK;
2507 }
2508
2509 switch ((opcode >> 12) & 0x5) {
2510 case 0x1:
2511 case 0x5:
2512 return t2ev_b_bl(opcode, address, instruction, cp);
2513 case 0x4:
2514 goto undef;
2515 case 0:
2516 if (((opcode >> 23) & 0x07) == 0x07)
2517 return t2ev_cond_b(opcode, address, instruction, cp);
2518 if (opcode & (1 << 26))
2519 goto undef;
2520 break;
2521 }
2522
2523 switch ((opcode >> 20) & 0x7f) {
2524 case 0x38:
2525 case 0x39:
2526 sprintf(cp, "MSR\t%s, r%d", special_name(opcode & 0xff),
2527 (opcode >> 16) & 0x0f);
2528 return ERROR_OK;
2529 case 0x3a:
2530 return t2ev_hint(opcode, address, instruction, cp);
2531 case 0x3b:
2532 return t2ev_misc(opcode, address, instruction, cp);
2533 case 0x3e:
2534 case 0x3f:
2535 sprintf(cp, "MRS\tr%d, %s", (opcode >> 16) & 0x0f,
2536 special_name(opcode & 0xff));
2537 return ERROR_OK;
2538 }
2539
2540 undef:
2541 return ERROR_INVALID_ARGUMENTS;
2542 }
2543
2544 static int t2ev_data_mod_immed(uint32_t opcode, uint32_t address,
2545 arm_instruction_t *instruction, char *cp)
2546 {
2547 char *mnemonic = NULL;
2548 int rn = (opcode >> 16) & 0xf;
2549 int rd = (opcode >> 8) & 0xf;
2550 unsigned immed = opcode & 0xff;
2551 unsigned func;
2552 bool one = false;
2553 char *suffix = "";
2554
2555 /* ARMv7-M: A5.3.2 Modified immediate constants */
2556 func = (opcode >> 11) & 0x0e;
2557 if (immed & 0x80)
2558 func |= 1;
2559 if (opcode & (1 << 26))
2560 func |= 0x10;
2561
2562 /* "Modified" immediates */
2563 switch (func >> 1) {
2564 case 0:
2565 break;
2566 case 2:
2567 immed <<= 8;
2568 /* FALLTHROUGH */
2569 case 1:
2570 immed += immed << 16;
2571 break;
2572 case 3:
2573 immed += immed << 8;
2574 immed += immed << 16;
2575 break;
2576 default:
2577 immed |= 0x80;
2578 immed = ror(immed, func);
2579 }
2580
2581 if (opcode & (1 << 20))
2582 suffix = "S";
2583
2584 switch ((opcode >> 21) & 0xf) {
2585 case 0:
2586 if (rd == 0xf) {
2587 instruction->type = ARM_TST;
2588 mnemonic = "TST";
2589 one = true;
2590 suffix = "";
2591 rd = rn;
2592 } else {
2593 instruction->type = ARM_AND;
2594 mnemonic = "AND";
2595 }
2596 break;
2597 case 1:
2598 instruction->type = ARM_BIC;
2599 mnemonic = "BIC";
2600 break;
2601 case 2:
2602 if (rn == 0xf) {
2603 instruction->type = ARM_MOV;
2604 mnemonic = "MOV";
2605 one = true;
2606 } else {
2607 instruction->type = ARM_ORR;
2608 mnemonic = "ORR";
2609 }
2610 break;
2611 case 3:
2612 if (rn == 0xf) {
2613 instruction->type = ARM_MVN;
2614 mnemonic = "MVN";
2615 one = true;
2616 } else {
2617 // instruction->type = ARM_ORN;
2618 mnemonic = "ORN";
2619 }
2620 break;
2621 case 4:
2622 if (rd == 0xf) {
2623 instruction->type = ARM_TEQ;
2624 mnemonic = "TEQ";
2625 one = true;
2626 suffix = "";
2627 rd = rn;
2628 } else {
2629 instruction->type = ARM_EOR;
2630 mnemonic = "EOR";
2631 }
2632 break;
2633 case 8:
2634 if (rd == 0xf) {
2635 instruction->type = ARM_CMN;
2636 mnemonic = "CMN";
2637 one = true;
2638 suffix = "";
2639 rd = rn;
2640 } else {
2641 instruction->type = ARM_ADD;
2642 mnemonic = "ADD";
2643 }
2644 break;
2645 case 10:
2646 instruction->type = ARM_ADC;
2647 mnemonic = "ADC";
2648 break;
2649 case 11:
2650 instruction->type = ARM_SBC;
2651 mnemonic = "SBC";
2652 break;
2653 case 13:
2654 if (rd == 0xf) {
2655 instruction->type = ARM_CMP;
2656 mnemonic = "CMP";
2657 one = true;
2658 suffix = "";
2659 rd = rn;
2660 } else {
2661 instruction->type = ARM_SUB;
2662 mnemonic = "SUB";
2663 }
2664 break;
2665 case 14:
2666 instruction->type = ARM_RSB;
2667 mnemonic = "RSB";
2668 break;
2669 default:
2670 return ERROR_INVALID_ARGUMENTS;
2671 }
2672
2673 if (one)
2674 sprintf(cp, "%s\tr%d, #%d\t; %#8.8x",
2675 mnemonic, rd, immed, immed);
2676 else
2677 sprintf(cp, "%s%s\tr%d, r%d, #%d\t; %#8.8x",
2678 mnemonic, suffix, rd, rn, immed, immed);
2679
2680 return ERROR_OK;
2681 }
2682
2683 static int t2ev_data_immed(uint32_t opcode, uint32_t address,
2684 arm_instruction_t *instruction, char *cp)
2685 {
2686 char *mnemonic = NULL;
2687 int rn = (opcode >> 16) & 0xf;
2688 int rd = (opcode >> 8) & 0xf;
2689 unsigned immed;
2690 bool add = false;
2691 bool is_signed = false;
2692
2693 immed = (opcode & 0x0ff) | ((opcode & 0x7000) >> 12);
2694 if (opcode & (1 << 27))
2695 immed |= (1 << 11);
2696
2697 switch ((opcode >> 20) & 0x1f) {
2698 case 0:
2699 if (rn == 0xf) {
2700 add = true;
2701 goto do_adr;
2702 }
2703 mnemonic = "ADD.W";
2704 break;
2705 case 4:
2706 mnemonic = "MOV.W";
2707 break;
2708 case 0x0a:
2709 if (rn == 0xf)
2710 goto do_adr;
2711 mnemonic = "SUB.W";
2712 break;
2713 case 0x0c:
2714 /* move constant to top 16 bits of register */
2715 immed |= (opcode >> 4) & 0xf000;
2716 sprintf(cp, "MOVT\tr%d, #%d\t; %#4.4x", rn, immed, immed);
2717 return ERROR_OK;
2718 case 0x10:
2719 case 0x12:
2720 is_signed = true;
2721 case 0x18:
2722 case 0x1a:
2723 /* signed/unsigned saturated add */
2724 immed = (opcode >> 6) & 0x03;
2725 immed |= (opcode >> 10) & 0x1c;
2726 sprintf(cp, "%sSAT\tr%d, #%d, r%d, %s #%d\t",
2727 is_signed ? "S" : "U",
2728 rd, (opcode & 0x1f) + 1, rn,
2729 (opcode & (1 << 21)) ? "ASR" : "LSL",
2730 immed ? immed : 32);
2731 return ERROR_OK;
2732 case 0x14:
2733 is_signed = true;
2734 /* FALLTHROUGH */
2735 case 0x1c:
2736 /* signed/unsigned bitfield extract */
2737 immed = (opcode >> 6) & 0x03;
2738 immed |= (opcode >> 10) & 0x1c;
2739 sprintf(cp, "%sBFX\tr%d, r%d, #%d, #%d\t",
2740 is_signed ? "S" : "U",
2741 rd, rn, immed,
2742 (opcode & 0x1f) + 1);
2743 return ERROR_OK;
2744 case 0x16:
2745 immed = (opcode >> 6) & 0x03;
2746 immed |= (opcode >> 10) & 0x1c;
2747 if (rn == 0xf) /* bitfield clear */
2748 sprintf(cp, "BFC\tr%d, #%d, #%d\t",
2749 rd, immed,
2750 (opcode & 0x1f) + 1 - immed);
2751 else /* bitfield insert */
2752 sprintf(cp, "BFI\tr%d, r%d, #%d, #%d\t",
2753 rd, rn, immed,
2754 (opcode & 0x1f) + 1 - immed);
2755 return ERROR_OK;
2756 default:
2757 return ERROR_INVALID_ARGUMENTS;
2758 }
2759
2760 sprintf(cp, "%s\tr%d, r%d, #%d\t; %#3.3x", mnemonic,
2761 rd, rn, immed, immed);
2762 return ERROR_OK;
2763
2764 do_adr:
2765 address = thumb_alignpc4(address);
2766 if (add)
2767 address += immed;
2768 else
2769 address -= immed;
2770 /* REVISIT "ADD/SUB Rd, PC, #const ; 0x..." might be better;
2771 * not hiding the pc-relative stuff will sometimes be useful.
2772 */
2773 sprintf(cp, "ADR.W\tr%d, %#8.8" PRIx32, rd, address);
2774 return ERROR_OK;
2775 }
2776
2777 /*
2778 * REVISIT for Thumb2 instructions, instruction->type and friends aren't
2779 * always set. That means eventual arm_simulate_step() support for Thumb2
2780 * will need work in this area.
2781 */
2782 int thumb2_opcode(target_t *target, uint32_t address, arm_instruction_t *instruction)
2783 {
2784 int retval;
2785 uint16_t op;
2786 uint32_t opcode;
2787 char *cp;
2788
2789 /* clear low bit ... it's set on function pointers */
2790 address &= ~1;
2791
2792 /* clear fields, to avoid confusion */
2793 memset(instruction, 0, sizeof(arm_instruction_t));
2794
2795 /* read first halfword, see if this is the only one */
2796 retval = target_read_u16(target, address, &op);
2797 if (retval != ERROR_OK)
2798 return retval;
2799
2800 switch (op & 0xf800) {
2801 case 0xf800:
2802 case 0xf000:
2803 case 0xe800:
2804 /* 32-bit instructions */
2805 instruction->instruction_size = 4;
2806 opcode = op << 16;
2807 retval = target_read_u16(target, address + 2, &op);
2808 if (retval != ERROR_OK)
2809 return retval;
2810 opcode |= op;
2811 instruction->opcode = opcode;
2812 break;
2813 default:
2814 /* 16-bit: Thumb1 + IT + CBZ/CBNZ + ... */
2815 return thumb_evaluate_opcode(op, address, instruction);
2816 }
2817
2818 snprintf(instruction->text, 128,
2819 "0x%8.8" PRIx32 " 0x%8.8" PRIx32 "\t",
2820 address, opcode);
2821 cp = strchr(instruction->text, 0);
2822 retval = ERROR_FAIL;
2823
2824 /* ARMv7-M: A5.3.1 Data processing (modified immediate) */
2825 if ((opcode & 0x1a008000) == 0x10000000)
2826 retval = t2ev_data_mod_immed(opcode, address, instruction, cp);
2827
2828 /* ARMv7-M: A5.3.3 Data processing (plain binary immediate) */
2829 else if ((opcode & 0x1a008000) == 0x12000000)
2830 retval = t2ev_data_immed(opcode, address, instruction, cp);
2831
2832 /* ARMv7-M: A5.3.4 Branches and miscellaneous control */
2833 else if ((opcode & 0x18008000) == 0x10008000)
2834 retval = t2ev_b_misc(opcode, address, instruction, cp);
2835
2836 /* FIXME decode more 32-bit instructions */
2837
2838 if (retval == ERROR_OK)
2839 return retval;
2840
2841 if (retval == ERROR_INVALID_ARGUMENTS) {
2842 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2843 strcpy(cp, "UNDEFINED OPCODE");
2844 return ERROR_OK;
2845 }
2846
2847 LOG_DEBUG("Can't decode 32-bit Thumb2 yet (opcode=%08x)", opcode);
2848
2849 strcpy(cp, "(32-bit Thumb2 ...)");
2850 return ERROR_OK;
2851 }
2852
2853 int arm_access_size(arm_instruction_t *instruction)
2854 {
2855 if ((instruction->type == ARM_LDRB)
2856 || (instruction->type == ARM_LDRBT)
2857 || (instruction->type == ARM_LDRSB)
2858 || (instruction->type == ARM_STRB)
2859 || (instruction->type == ARM_STRBT))
2860 {
2861 return 1;
2862 }
2863 else if ((instruction->type == ARM_LDRH)
2864 || (instruction->type == ARM_LDRSH)
2865 || (instruction->type == ARM_STRH))
2866 {
2867 return 2;
2868 }
2869 else if ((instruction->type == ARM_LDR)
2870 || (instruction->type == ARM_LDRT)
2871 || (instruction->type == ARM_STR)
2872 || (instruction->type == ARM_STRT))
2873 {
2874 return 4;
2875 }
2876 else if ((instruction->type == ARM_LDRD)
2877 || (instruction->type == ARM_STRD))
2878 {
2879 return 8;
2880 }
2881 else
2882 {
2883 LOG_ERROR("BUG: instruction type %i isn't a load/store instruction", instruction->type);
2884 return 0;
2885 }
2886 }

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)