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, "0x%8.8" PRIx32 "\t0x%4.4x\t%s 0x%8.8" PRIx32 , address, opcode,mnemonic, target_address);
1371
1372 instruction->info.b_bl_bx_blx.reg_operand = -1;
1373 instruction->info.b_bl_bx_blx.target_address = target_address;
1374
1375 return ERROR_OK;
1376 }
1377
1378 int evaluate_add_sub_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1379 {
1380 uint8_t Rd = (opcode >> 0) & 0x7;
1381 uint8_t Rn = (opcode >> 3) & 0x7;
1382 uint8_t Rm_imm = (opcode >> 6) & 0x7;
1383 uint32_t opc = opcode & (1 << 9);
1384 uint32_t reg_imm = opcode & (1 << 10);
1385 char *mnemonic;
1386
1387 if (opc)
1388 {
1389 instruction->type = ARM_SUB;
1390 mnemonic = "SUBS";
1391 }
1392 else
1393 {
1394 instruction->type = ARM_ADD;
1395 mnemonic = "ADDS";
1396 }
1397
1398 instruction->info.data_proc.Rd = Rd;
1399 instruction->info.data_proc.Rn = Rn;
1400 instruction->info.data_proc.S = 1;
1401
1402 if (reg_imm)
1403 {
1404 instruction->info.data_proc.variant = 0; /*immediate*/
1405 instruction->info.data_proc.shifter_operand.immediate.immediate = Rm_imm;
1406 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\t%s r%i, r%i, #%d",
1407 address, opcode, mnemonic, Rd, Rn, Rm_imm);
1408 }
1409 else
1410 {
1411 instruction->info.data_proc.variant = 1; /*immediate shift*/
1412 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm_imm;
1413 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\t%s r%i, r%i, r%i",
1414 address, opcode, mnemonic, Rd, Rn, Rm_imm);
1415 }
1416
1417 return ERROR_OK;
1418 }
1419
1420 int evaluate_shift_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1421 {
1422 uint8_t Rd = (opcode >> 0) & 0x7;
1423 uint8_t Rm = (opcode >> 3) & 0x7;
1424 uint8_t imm = (opcode >> 6) & 0x1f;
1425 uint8_t opc = (opcode >> 11) & 0x3;
1426 char *mnemonic = NULL;
1427
1428 switch (opc)
1429 {
1430 case 0:
1431 instruction->type = ARM_MOV;
1432 mnemonic = "LSLS";
1433 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 0;
1434 break;
1435 case 1:
1436 instruction->type = ARM_MOV;
1437 mnemonic = "LSRS";
1438 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 1;
1439 break;
1440 case 2:
1441 instruction->type = ARM_MOV;
1442 mnemonic = "ASRS";
1443 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 2;
1444 break;
1445 }
1446
1447 if ((imm == 0) && (opc != 0))
1448 imm = 32;
1449
1450 instruction->info.data_proc.Rd = Rd;
1451 instruction->info.data_proc.Rn = -1;
1452 instruction->info.data_proc.S = 1;
1453
1454 instruction->info.data_proc.variant = 1; /*immediate_shift*/
1455 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1456 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = imm;
1457
1458 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\t%s r%i, r%i, #0x%02x" ,
1459 address, opcode, mnemonic, Rd, Rm, imm);
1460
1461 return ERROR_OK;
1462 }
1463
1464 int evaluate_data_proc_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1465 {
1466 uint8_t imm = opcode & 0xff;
1467 uint8_t Rd = (opcode >> 8) & 0x7;
1468 uint32_t opc = (opcode >> 11) & 0x3;
1469 char *mnemonic = NULL;
1470
1471 instruction->info.data_proc.Rd = Rd;
1472 instruction->info.data_proc.Rn = Rd;
1473 instruction->info.data_proc.S = 1;
1474 instruction->info.data_proc.variant = 0; /*immediate*/
1475 instruction->info.data_proc.shifter_operand.immediate.immediate = imm;
1476
1477 switch (opc)
1478 {
1479 case 0:
1480 instruction->type = ARM_MOV;
1481 mnemonic = "MOVS";
1482 instruction->info.data_proc.Rn = -1;
1483 break;
1484 case 1:
1485 instruction->type = ARM_CMP;
1486 mnemonic = "CMP";
1487 instruction->info.data_proc.Rd = -1;
1488 break;
1489 case 2:
1490 instruction->type = ARM_ADD;
1491 mnemonic = "ADDS";
1492 break;
1493 case 3:
1494 instruction->type = ARM_SUB;
1495 mnemonic = "SUBS";
1496 break;
1497 }
1498
1499 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\t%s r%i, #0x%02x" ,
1500 address, opcode, mnemonic, Rd, imm);
1501
1502 return ERROR_OK;
1503 }
1504
1505 int evaluate_data_proc_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1506 {
1507 uint8_t high_reg, op, Rm, Rd,H1,H2;
1508 char *mnemonic = NULL;
1509
1510 high_reg = (opcode & 0x0400) >> 10;
1511 op = (opcode & 0x03C0) >> 6;
1512
1513 Rd = (opcode & 0x0007);
1514 Rm = (opcode & 0x0038) >> 3;
1515 H1 = (opcode & 0x0080) >> 7;
1516 H2 = (opcode & 0x0040) >> 6;
1517
1518 instruction->info.data_proc.Rd = Rd;
1519 instruction->info.data_proc.Rn = Rd;
1520 instruction->info.data_proc.S = (!high_reg || (instruction->type == ARM_CMP));
1521 instruction->info.data_proc.variant = 1 /*immediate shift*/;
1522 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1523
1524 if (high_reg)
1525 {
1526 Rd |= H1 << 3;
1527 Rm |= H2 << 3;
1528 op >>= 2;
1529
1530 switch (op)
1531 {
1532 case 0x0:
1533 instruction->type = ARM_ADD;
1534 mnemonic = "ADD";
1535 break;
1536 case 0x1:
1537 instruction->type = ARM_CMP;
1538 mnemonic = "CMP";
1539 break;
1540 case 0x2:
1541 instruction->type = ARM_MOV;
1542 mnemonic = "MOV";
1543 break;
1544 case 0x3:
1545 if ((opcode & 0x7) == 0x0)
1546 {
1547 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1548 if (H1)
1549 {
1550 instruction->type = ARM_BLX;
1551 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\tBLX r%i", address, opcode, Rm);
1552 }
1553 else
1554 {
1555 instruction->type = ARM_BX;
1556 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\tBX r%i", address, opcode, Rm);
1557 }
1558 }
1559 else
1560 {
1561 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1562 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\tUNDEFINED INSTRUCTION", address, opcode);
1563 }
1564 return ERROR_OK;
1565 break;
1566 }
1567 }
1568 else
1569 {
1570 switch (op)
1571 {
1572 case 0x0:
1573 instruction->type = ARM_AND;
1574 mnemonic = "ANDS";
1575 break;
1576 case 0x1:
1577 instruction->type = ARM_EOR;
1578 mnemonic = "EORS";
1579 break;
1580 case 0x2:
1581 instruction->type = ARM_MOV;
1582 mnemonic = "LSLS";
1583 instruction->info.data_proc.variant = 2 /*register shift*/;
1584 instruction->info.data_proc.shifter_operand.register_shift.shift = 0;
1585 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1586 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1587 break;
1588 case 0x3:
1589 instruction->type = ARM_MOV;
1590 mnemonic = "LSRS";
1591 instruction->info.data_proc.variant = 2 /*register shift*/;
1592 instruction->info.data_proc.shifter_operand.register_shift.shift = 1;
1593 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1594 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1595 break;
1596 case 0x4:
1597 instruction->type = ARM_MOV;
1598 mnemonic = "ASRS";
1599 instruction->info.data_proc.variant = 2 /*register shift*/;
1600 instruction->info.data_proc.shifter_operand.register_shift.shift = 2;
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 0x5:
1605 instruction->type = ARM_ADC;
1606 mnemonic = "ADCS";
1607 break;
1608 case 0x6:
1609 instruction->type = ARM_SBC;
1610 mnemonic = "SBCS";
1611 break;
1612 case 0x7:
1613 instruction->type = ARM_MOV;
1614 mnemonic = "RORS";
1615 instruction->info.data_proc.variant = 2 /*register shift*/;
1616 instruction->info.data_proc.shifter_operand.register_shift.shift = 3;
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 0x8:
1621 instruction->type = ARM_TST;
1622 mnemonic = "TST";
1623 break;
1624 case 0x9:
1625 instruction->type = ARM_RSB;
1626 mnemonic = "NEGS";
1627 instruction->info.data_proc.variant = 0 /*immediate*/;
1628 instruction->info.data_proc.shifter_operand.immediate.immediate = 0;
1629 instruction->info.data_proc.Rn = Rm;
1630 break;
1631 case 0xA:
1632 instruction->type = ARM_CMP;
1633 mnemonic = "CMP";
1634 break;
1635 case 0xB:
1636 instruction->type = ARM_CMN;
1637 mnemonic = "CMN";
1638 break;
1639 case 0xC:
1640 instruction->type = ARM_ORR;
1641 mnemonic = "ORRS";
1642 break;
1643 case 0xD:
1644 instruction->type = ARM_MUL;
1645 mnemonic = "MULS";
1646 break;
1647 case 0xE:
1648 instruction->type = ARM_BIC;
1649 mnemonic = "BICS";
1650 break;
1651 case 0xF:
1652 instruction->type = ARM_MVN;
1653 mnemonic = "MVNS";
1654 break;
1655 }
1656 }
1657
1658 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\t%s r%i, r%i",
1659 address, opcode, mnemonic, Rd, Rm);
1660
1661 return ERROR_OK;
1662 }
1663
1664 int evaluate_load_literal_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1665 {
1666 uint32_t immediate;
1667 uint8_t Rd = (opcode >> 8) & 0x7;
1668
1669 instruction->type = ARM_LDR;
1670 immediate = opcode & 0x000000ff;
1671
1672 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\tLDR r%i, [PC, #0x%" PRIx32 "]", address, opcode, Rd, immediate*4);
1673
1674 instruction->info.load_store.Rd = Rd;
1675 instruction->info.load_store.Rn = 15 /*PC*/;
1676 instruction->info.load_store.index_mode = 0; /*offset*/
1677 instruction->info.load_store.offset_mode = 0; /*immediate*/
1678 instruction->info.load_store.offset.offset = immediate*4;
1679
1680 return ERROR_OK;
1681 }
1682
1683 int evaluate_load_store_reg_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1684 {
1685 uint8_t Rd = (opcode >> 0) & 0x7;
1686 uint8_t Rn = (opcode >> 3) & 0x7;
1687 uint8_t Rm = (opcode >> 6) & 0x7;
1688 uint8_t opc = (opcode >> 9) & 0x7;
1689 char *mnemonic = NULL;
1690
1691 switch (opc)
1692 {
1693 case 0:
1694 instruction->type = ARM_STR;
1695 mnemonic = "STR";
1696 break;
1697 case 1:
1698 instruction->type = ARM_STRH;
1699 mnemonic = "STRH";
1700 break;
1701 case 2:
1702 instruction->type = ARM_STRB;
1703 mnemonic = "STRB";
1704 break;
1705 case 3:
1706 instruction->type = ARM_LDRSB;
1707 mnemonic = "LDRSB";
1708 break;
1709 case 4:
1710 instruction->type = ARM_LDR;
1711 mnemonic = "LDR";
1712 break;
1713 case 5:
1714 instruction->type = ARM_LDRH;
1715 mnemonic = "LDRH";
1716 break;
1717 case 6:
1718 instruction->type = ARM_LDRB;
1719 mnemonic = "LDRB";
1720 break;
1721 case 7:
1722 instruction->type = ARM_LDRSH;
1723 mnemonic = "LDRSH";
1724 break;
1725 }
1726
1727 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\t%s r%i, [r%i, r%i]", address, opcode, mnemonic, Rd, Rn, Rm);
1728
1729 instruction->info.load_store.Rd = Rd;
1730 instruction->info.load_store.Rn = Rn;
1731 instruction->info.load_store.index_mode = 0; /*offset*/
1732 instruction->info.load_store.offset_mode = 1; /*register*/
1733 instruction->info.load_store.offset.reg.Rm = Rm;
1734
1735 return ERROR_OK;
1736 }
1737
1738 int evaluate_load_store_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1739 {
1740 uint32_t offset = (opcode >> 6) & 0x1f;
1741 uint8_t Rd = (opcode >> 0) & 0x7;
1742 uint8_t Rn = (opcode >> 3) & 0x7;
1743 uint32_t L = opcode & (1 << 11);
1744 uint32_t B = opcode & (1 << 12);
1745 char *mnemonic;
1746 char suffix = ' ';
1747 uint32_t shift = 2;
1748
1749 if (L)
1750 {
1751 instruction->type = ARM_LDR;
1752 mnemonic = "LDR";
1753 }
1754 else
1755 {
1756 instruction->type = ARM_STR;
1757 mnemonic = "STR";
1758 }
1759
1760 if ((opcode&0xF000) == 0x8000)
1761 {
1762 suffix = 'H';
1763 shift = 1;
1764 }
1765 else if (B)
1766 {
1767 suffix = 'B';
1768 shift = 0;
1769 }
1770
1771 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\t%s%c r%i, [r%i, #0x%" PRIx32 "]", address, opcode, mnemonic, suffix, Rd, Rn, offset << shift);
1772
1773 instruction->info.load_store.Rd = Rd;
1774 instruction->info.load_store.Rn = Rn;
1775 instruction->info.load_store.index_mode = 0; /*offset*/
1776 instruction->info.load_store.offset_mode = 0; /*immediate*/
1777 instruction->info.load_store.offset.offset = offset << shift;
1778
1779 return ERROR_OK;
1780 }
1781
1782 int evaluate_load_store_stack_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1783 {
1784 uint32_t offset = opcode & 0xff;
1785 uint8_t Rd = (opcode >> 8) & 0x7;
1786 uint32_t L = opcode & (1 << 11);
1787 char *mnemonic;
1788
1789 if (L)
1790 {
1791 instruction->type = ARM_LDR;
1792 mnemonic = "LDR";
1793 }
1794 else
1795 {
1796 instruction->type = ARM_STR;
1797 mnemonic = "STR";
1798 }
1799
1800 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\t%s r%i, [SP, #0x%" PRIx32 "]", address, opcode, mnemonic, Rd, offset*4);
1801
1802 instruction->info.load_store.Rd = Rd;
1803 instruction->info.load_store.Rn = 13 /*SP*/;
1804 instruction->info.load_store.index_mode = 0; /*offset*/
1805 instruction->info.load_store.offset_mode = 0; /*immediate*/
1806 instruction->info.load_store.offset.offset = offset*4;
1807
1808 return ERROR_OK;
1809 }
1810
1811 int evaluate_add_sp_pc_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1812 {
1813 uint32_t imm = opcode & 0xff;
1814 uint8_t Rd = (opcode >> 8) & 0x7;
1815 uint8_t Rn;
1816 uint32_t SP = opcode & (1 << 11);
1817 char *reg_name;
1818
1819 instruction->type = ARM_ADD;
1820
1821 if (SP)
1822 {
1823 reg_name = "SP";
1824 Rn = 13;
1825 }
1826 else
1827 {
1828 reg_name = "PC";
1829 Rn = 15;
1830 }
1831
1832 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\tADD r%i, %s, #0x%" PRIx32 "", address, opcode, Rd,reg_name, imm*4);
1833
1834 instruction->info.data_proc.variant = 0 /* immediate */;
1835 instruction->info.data_proc.Rd = Rd;
1836 instruction->info.data_proc.Rn = Rn;
1837 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
1838
1839 return ERROR_OK;
1840 }
1841
1842 int evaluate_adjust_stack_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1843 {
1844 uint32_t imm = opcode & 0x7f;
1845 uint8_t opc = opcode & (1 << 7);
1846 char *mnemonic;
1847
1848
1849 if (opc)
1850 {
1851 instruction->type = ARM_SUB;
1852 mnemonic = "SUB";
1853 }
1854 else
1855 {
1856 instruction->type = ARM_ADD;
1857 mnemonic = "ADD";
1858 }
1859
1860 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\t%s SP, #0x%" PRIx32 "", address, opcode, mnemonic, imm*4);
1861
1862 instruction->info.data_proc.variant = 0 /* immediate */;
1863 instruction->info.data_proc.Rd = 13 /*SP*/;
1864 instruction->info.data_proc.Rn = 13 /*SP*/;
1865 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
1866
1867 return ERROR_OK;
1868 }
1869
1870 int evaluate_breakpoint_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1871 {
1872 uint32_t imm = opcode & 0xff;
1873
1874 instruction->type = ARM_BKPT;
1875
1876 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\tBKPT 0x%02" PRIx32 "", address, opcode, imm);
1877
1878 return ERROR_OK;
1879 }
1880
1881 int evaluate_load_store_multiple_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1882 {
1883 uint32_t reg_list = opcode & 0xff;
1884 uint32_t L = opcode & (1 << 11);
1885 uint32_t R = opcode & (1 << 8);
1886 uint8_t Rn = (opcode >> 8) & 7;
1887 uint8_t addr_mode = 0 /* IA */;
1888 char reg_names[40];
1889 char *reg_names_p;
1890 char *mnemonic;
1891 char ptr_name[7] = "";
1892 int i;
1893
1894 if ((opcode & 0xf000) == 0xc000)
1895 { /* generic load/store multiple */
1896 if (L)
1897 {
1898 instruction->type = ARM_LDM;
1899 mnemonic = "LDM";
1900 }
1901 else
1902 {
1903 instruction->type = ARM_STM;
1904 mnemonic = "STM";
1905 }
1906 snprintf(ptr_name,7,"r%i!, ",Rn);
1907 }
1908 else
1909 { /* push/pop */
1910 Rn = 13; /* SP */
1911 if (L)
1912 {
1913 instruction->type = ARM_LDM;
1914 mnemonic = "POP";
1915 if (R)
1916 reg_list |= (1 << 15) /*PC*/;
1917 }
1918 else
1919 {
1920 instruction->type = ARM_STM;
1921 mnemonic = "PUSH";
1922 addr_mode = 3; /*DB*/
1923 if (R)
1924 reg_list |= (1 << 14) /*LR*/;
1925 }
1926 }
1927
1928 reg_names_p = reg_names;
1929 for (i = 0; i <= 15; i++)
1930 {
1931 if (reg_list & (1 << i))
1932 reg_names_p += snprintf(reg_names_p, (reg_names + 40 - reg_names_p), "r%i, ", i);
1933 }
1934 if (reg_names_p > reg_names)
1935 reg_names_p[-2] = '\0';
1936 else /* invalid op : no registers */
1937 reg_names[0] = '\0';
1938
1939 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\t%s %s{%s}", address, opcode, mnemonic, ptr_name,reg_names);
1940
1941 instruction->info.load_store_multiple.register_list = reg_list;
1942 instruction->info.load_store_multiple.Rn = Rn;
1943 instruction->info.load_store_multiple.addressing_mode = addr_mode;
1944
1945 return ERROR_OK;
1946 }
1947
1948 int evaluate_cond_branch_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1949 {
1950 uint32_t offset = opcode & 0xff;
1951 uint8_t cond = (opcode >> 8) & 0xf;
1952 uint32_t target_address;
1953
1954 if (cond == 0xf)
1955 {
1956 instruction->type = ARM_SWI;
1957 snprintf(instruction->text, 128,
1958 "0x%8.8" PRIx32 "\t0x%4.4x\tSVC 0x%02" PRIx32,
1959 address, opcode, offset);
1960 return ERROR_OK;
1961 }
1962 else if (cond == 0xe)
1963 {
1964 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1965 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\tUNDEFINED INSTRUCTION", address, opcode);
1966 return ERROR_OK;
1967 }
1968
1969 /* sign extend 8-bit offset */
1970 if (offset & 0x00000080)
1971 offset = 0xffffff00 | offset;
1972
1973 target_address = address + 4 + (offset << 1);
1974
1975 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%4.4x\tB%s 0x%8.8" PRIx32 , address, opcode,
1976 arm_condition_strings[cond], target_address);
1977
1978 instruction->type = ARM_B;
1979 instruction->info.b_bl_bx_blx.reg_operand = -1;
1980 instruction->info.b_bl_bx_blx.target_address = target_address;
1981
1982 return ERROR_OK;
1983 }
1984
1985 static int evaluate_cb_thumb(uint16_t opcode, uint32_t address,
1986 arm_instruction_t *instruction)
1987 {
1988 unsigned offset;
1989
1990 /* added in Thumb2 */
1991 offset = (opcode >> 3) & 0x1f;
1992 offset |= (opcode & 0x0200) >> 4;
1993
1994 snprintf(instruction->text, 128,
1995 "0x%8.8" PRIx32 "\t0x%4.4x\tCB%sZ r%d, %#8.8" PRIx32,
1996 address, opcode,
1997 (opcode & 0x0800) ? "N" : "",
1998 opcode & 0x7, address + 4 + (offset << 1));
1999
2000 return ERROR_OK;
2001 }
2002
2003 static int evaluate_extend_thumb(uint16_t opcode, uint32_t address,
2004 arm_instruction_t *instruction)
2005 {
2006 /* added in ARMv6 */
2007 snprintf(instruction->text, 128,
2008 "0x%8.8" PRIx32 "\t0x%4.4x\t%cXT%c r%d, r%d",
2009 address, opcode,
2010 (opcode & 0x0080) ? 'U' : 'S',
2011 (opcode & 0x0040) ? 'B' : 'H',
2012 opcode & 0x7, (opcode >> 3) & 0x7);
2013
2014 return ERROR_OK;
2015 }
2016
2017 static int evaluate_cps_thumb(uint16_t opcode, uint32_t address,
2018 arm_instruction_t *instruction)
2019 {
2020 /* added in ARMv6 */
2021 if ((opcode & 0x0ff0) == 0x0650)
2022 snprintf(instruction->text, 128,
2023 "0x%8.8" PRIx32 "\t0x%4.4x\tSETEND %s",
2024 address, opcode,
2025 (opcode & 0x80) ? "BE" : "LE");
2026 else /* ASSUME (opcode & 0x0fe0) == 0x0660 */
2027 snprintf(instruction->text, 128,
2028 "0x%8.8" PRIx32 "\t0x%4.4x\tCPSI%c %s%s%s",
2029 address, opcode,
2030 (opcode & 0x0010) ? 'D' : 'E',
2031 (opcode & 0x0004) ? "A" : "",
2032 (opcode & 0x0002) ? "I" : "",
2033 (opcode & 0x0001) ? "F" : "");
2034
2035 return ERROR_OK;
2036 }
2037
2038 static int evaluate_byterev_thumb(uint16_t opcode, uint32_t address,
2039 arm_instruction_t *instruction)
2040 {
2041 char *suffix;
2042
2043 /* added in ARMv6 */
2044 switch (opcode & 0x00c0) {
2045 case 0:
2046 suffix = "";
2047 break;
2048 case 1:
2049 suffix = "16";
2050 break;
2051 default:
2052 suffix = "SH";
2053 break;
2054 }
2055 snprintf(instruction->text, 128,
2056 "0x%8.8" PRIx32 "\t0x%4.4x\tREV%s r%d, r%d",
2057 address, opcode, suffix,
2058 opcode & 0x7, (opcode >> 3) & 0x7);
2059
2060 return ERROR_OK;
2061 }
2062
2063 static int evaluate_hint_thumb(uint16_t opcode, uint32_t address,
2064 arm_instruction_t *instruction)
2065 {
2066 char *hint;
2067
2068 switch ((opcode >> 4) & 0x0f) {
2069 case 0:
2070 hint = "NOP";
2071 break;
2072 case 1:
2073 hint = "YIELD";
2074 break;
2075 case 2:
2076 hint = "WFE";
2077 break;
2078 case 3:
2079 hint = "WFI";
2080 break;
2081 case 4:
2082 hint = "SEV";
2083 break;
2084 default:
2085 hint = "HINT (UNRECOGNIZED)";
2086 break;
2087 }
2088
2089 snprintf(instruction->text, 128,
2090 "0x%8.8" PRIx32 "\t0x%4.4x\t%s",
2091 address, opcode, hint);
2092
2093 return ERROR_OK;
2094 }
2095
2096 static int evaluate_ifthen_thumb(uint16_t opcode, uint32_t address,
2097 arm_instruction_t *instruction)
2098 {
2099 unsigned cond = (opcode >> 4) & 0x0f;
2100 char *x = "", *y = "", *z = "";
2101
2102 if (opcode & 0x01)
2103 z = (opcode & 0x02) ? "T" : "E";
2104 if (opcode & 0x03)
2105 y = (opcode & 0x04) ? "T" : "E";
2106 if (opcode & 0x07)
2107 x = (opcode & 0x08) ? "T" : "E";
2108
2109 snprintf(instruction->text, 128,
2110 "0x%8.8" PRIx32 "\t0x%4.4x\tIT%s%s%s %s",
2111 address, opcode,
2112 x, y, z, arm_condition_strings[cond]);
2113
2114 /* NOTE: strictly speaking, the next 1-4 instructions should
2115 * now be displayed with the relevant conditional suffix...
2116 */
2117
2118 return ERROR_OK;
2119 }
2120
2121 int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
2122 {
2123 /* clear fields, to avoid confusion */
2124 memset(instruction, 0, sizeof(arm_instruction_t));
2125 instruction->opcode = opcode;
2126 instruction->instruction_size = 2;
2127
2128 if ((opcode & 0xe000) == 0x0000)
2129 {
2130 /* add/substract register or immediate */
2131 if ((opcode & 0x1800) == 0x1800)
2132 return evaluate_add_sub_thumb(opcode, address, instruction);
2133 /* shift by immediate */
2134 else
2135 return evaluate_shift_imm_thumb(opcode, address, instruction);
2136 }
2137
2138 /* Add/substract/compare/move immediate */
2139 if ((opcode & 0xe000) == 0x2000)
2140 {
2141 return evaluate_data_proc_imm_thumb(opcode, address, instruction);
2142 }
2143
2144 /* Data processing instructions */
2145 if ((opcode & 0xf800) == 0x4000)
2146 {
2147 return evaluate_data_proc_thumb(opcode, address, instruction);
2148 }
2149
2150 /* Load from literal pool */
2151 if ((opcode & 0xf800) == 0x4800)
2152 {
2153 return evaluate_load_literal_thumb(opcode, address, instruction);
2154 }
2155
2156 /* Load/Store register offset */
2157 if ((opcode & 0xf000) == 0x5000)
2158 {
2159 return evaluate_load_store_reg_thumb(opcode, address, instruction);
2160 }
2161
2162 /* Load/Store immediate offset */
2163 if (((opcode & 0xe000) == 0x6000)
2164 ||((opcode & 0xf000) == 0x8000))
2165 {
2166 return evaluate_load_store_imm_thumb(opcode, address, instruction);
2167 }
2168
2169 /* Load/Store from/to stack */
2170 if ((opcode & 0xf000) == 0x9000)
2171 {
2172 return evaluate_load_store_stack_thumb(opcode, address, instruction);
2173 }
2174
2175 /* Add to SP/PC */
2176 if ((opcode & 0xf000) == 0xa000)
2177 {
2178 return evaluate_add_sp_pc_thumb(opcode, address, instruction);
2179 }
2180
2181 /* Misc */
2182 if ((opcode & 0xf000) == 0xb000)
2183 {
2184 switch ((opcode >> 8) & 0x0f) {
2185 case 0x0:
2186 return evaluate_adjust_stack_thumb(opcode, address, instruction);
2187 case 0x1:
2188 case 0x3:
2189 case 0x9:
2190 case 0xb:
2191 return evaluate_cb_thumb(opcode, address, instruction);
2192 case 0x2:
2193 return evaluate_extend_thumb(opcode, address, instruction);
2194 case 0x4:
2195 case 0x5:
2196 case 0xc:
2197 case 0xd:
2198 return evaluate_load_store_multiple_thumb(opcode, address,
2199 instruction);
2200 case 0x6:
2201 return evaluate_cps_thumb(opcode, address, instruction);
2202 case 0xa:
2203 if ((opcode & 0x00c0) == 0x0080)
2204 break;
2205 return evaluate_byterev_thumb(opcode, address, instruction);
2206 case 0xe:
2207 return evaluate_breakpoint_thumb(opcode, address, instruction);
2208 case 0xf:
2209 if (opcode & 0x000f)
2210 return evaluate_ifthen_thumb(opcode, address,
2211 instruction);
2212 else
2213 return evaluate_hint_thumb(opcode, address,
2214 instruction);
2215 }
2216
2217 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2218 snprintf(instruction->text, 128,
2219 "0x%8.8" PRIx32 "\t0x%4.4x\tUNDEFINED INSTRUCTION",
2220 address, opcode);
2221 return ERROR_OK;
2222 }
2223
2224 /* Load/Store multiple */
2225 if ((opcode & 0xf000) == 0xc000)
2226 {
2227 return evaluate_load_store_multiple_thumb(opcode, address, instruction);
2228 }
2229
2230 /* Conditional branch + SWI */
2231 if ((opcode & 0xf000) == 0xd000)
2232 {
2233 return evaluate_cond_branch_thumb(opcode, address, instruction);
2234 }
2235
2236 if ((opcode & 0xe000) == 0xe000)
2237 {
2238 /* Undefined instructions */
2239 if ((opcode & 0xf801) == 0xe801)
2240 {
2241 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2242 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8x\tUNDEFINED INSTRUCTION", address, opcode);
2243 return ERROR_OK;
2244 }
2245 else
2246 { /* Branch to offset */
2247 return evaluate_b_bl_blx_thumb(opcode, address, instruction);
2248 }
2249 }
2250
2251 LOG_ERROR("should never reach this point (opcode=%04x)",opcode);
2252 return -1;
2253 }
2254
2255 /*
2256 * REVISIT for Thumb2 instructions, instruction->type and friends aren't
2257 * always set. That means eventual arm_simulate_step() support for Thumb2
2258 * will need work in this area.
2259 */
2260 int thumb2_opcode(target_t *target, uint32_t address, arm_instruction_t *instruction)
2261 {
2262 int retval;
2263 uint16_t op;
2264 uint32_t opcode;
2265
2266 /* clear low bit ... it's set on function pointers */
2267 address &= ~1;
2268
2269 /* clear fields, to avoid confusion */
2270 memset(instruction, 0, sizeof(arm_instruction_t));
2271
2272 /* read first halfword, see if this is the only one */
2273 retval = target_read_u16(target, address, &op);
2274 if (retval != ERROR_OK)
2275 return retval;
2276
2277 switch (op & 0xf800) {
2278 case 0xf800:
2279 case 0xf000:
2280 case 0xe800:
2281 /* 32-bit instructions */
2282 instruction->instruction_size = 4;
2283 opcode = op << 16;
2284 retval = target_read_u16(target, address + 2, &op);
2285 if (retval != ERROR_OK)
2286 return retval;
2287 opcode |= op;
2288 instruction->opcode = opcode;
2289 break;
2290 default:
2291 /* 16-bit: Thumb1 + IT + CBZ/CBNZ + ... */
2292 return thumb_evaluate_opcode(op, address, instruction);
2293 }
2294
2295 /* FIXME decode the 32-bit instructions */
2296
2297 LOG_DEBUG("Can't decode 32-bit Thumb2 yet (opcode=%08x)", opcode);
2298
2299 snprintf(instruction->text, 128,
2300 "0x%8.8" PRIx32 "\t0x%8.8x\t... 32-bit Thumb2 ...",
2301 address, opcode);
2302 return ERROR_OK;
2303 }
2304
2305 int arm_access_size(arm_instruction_t *instruction)
2306 {
2307 if ((instruction->type == ARM_LDRB)
2308 || (instruction->type == ARM_LDRBT)
2309 || (instruction->type == ARM_LDRSB)
2310 || (instruction->type == ARM_STRB)
2311 || (instruction->type == ARM_STRBT))
2312 {
2313 return 1;
2314 }
2315 else if ((instruction->type == ARM_LDRH)
2316 || (instruction->type == ARM_LDRSH)
2317 || (instruction->type == ARM_STRH))
2318 {
2319 return 2;
2320 }
2321 else if ((instruction->type == ARM_LDR)
2322 || (instruction->type == ARM_LDRT)
2323 || (instruction->type == ARM_STR)
2324 || (instruction->type == ARM_STRT))
2325 {
2326 return 4;
2327 }
2328 else if ((instruction->type == ARM_LDRD)
2329 || (instruction->type == ARM_STRD))
2330 {
2331 return 8;
2332 }
2333 else
2334 {
2335 LOG_ERROR("BUG: instruction type %i isn't a load/store instruction", instruction->type);
2336 return 0;
2337 }
2338 }

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)