6e76cf394cc549855808c61e0773e7d34fcd82d0
[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 #include "arm_disassembler.h"
21
22 #include "log.h"
23
24 #include <strings.h>
25
26 /* textual represenation of the condition field */
27 /* ALways (default) is ommitted (empty string) */
28 char *arm_condition_strings[] =
29 {
30 "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", "HI", "LS", "GE", "LT", "GT", "LE", "", "NV"
31 };
32
33 /* make up for C's missing ROR */
34 u32 ror(u32 value, int places)
35 {
36 return (value >> places) | (value << (32 - places));
37 }
38
39 int evaluate_pld(u32 opcode, u32 address, arm_instruction_t *instruction)
40 {
41 /* PLD */
42 if ((opcode & 0x0d70f0000) == 0x0550f000)
43 {
44 instruction->type = ARM_PLD;
45
46 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tPLD ...TODO...", address, opcode);
47
48 return ERROR_OK;
49 }
50 else
51 {
52 instruction->type = ARM_UNDEFINED_INSTRUCTION;
53 return ERROR_OK;
54 }
55
56 ERROR("should never reach this point");
57 return -1;
58 }
59
60 int evaluate_swi(u32 opcode, u32 address, arm_instruction_t *instruction)
61 {
62 instruction->type = ARM_SWI;
63
64 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tSWI 0x%6.6x", address, opcode, (opcode & 0xffffff));
65
66 return ERROR_OK;
67 }
68
69 int evaluate_blx_imm(u32 opcode, u32 address, arm_instruction_t *instruction)
70 {
71 int offset;
72 u32 immediate;
73
74 instruction->type = ARM_BLX;
75 immediate = opcode & 0x00ffffff;
76
77 /* sign extend 24-bit immediate */
78 if (immediate & 0x00800000)
79 offset = 0xff000000 | immediate;
80 else
81 offset = immediate;
82
83 /* shift two bits left */
84 offset <<= 2;
85
86 /* odd/event halfword */
87 if (opcode & 0x01000000)
88 offset |= 0x2;
89
90 instruction->target_address = address + 8 + offset;
91
92 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tBLX 0x%8.8x", address, opcode, instruction->target_address);
93
94 return ERROR_OK;
95 }
96
97 int evaluate_b_bl(u32 opcode, u32 address, arm_instruction_t *instruction)
98 {
99 u8 L;
100 u32 immediate;
101 int offset;
102
103 immediate = opcode & 0x00ffffff;
104 L = (opcode & 0x01000000) >> 24;
105
106 /* sign extend 24-bit immediate */
107 if (immediate & 0x00800000)
108 offset = 0xff000000 | immediate;
109 else
110 offset = immediate;
111
112 /* shift two bits left */
113 offset <<= 2;
114
115 instruction->target_address = address + 8 + offset;
116
117 if (L)
118 instruction->type = ARM_BL;
119 else
120 instruction->type = ARM_B;
121
122 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tB%s%s 0x%8.8x", address, opcode,
123 (L) ? "L" : "", COND(opcode), instruction->target_address);
124
125 return ERROR_OK;
126 }
127
128 /* Coprocessor load/store and double register transfers */
129 /* both normal and extended instruction space (condition field b1111) */
130 int evaluate_ldc_stc_mcrr_mrrc(u32 opcode, u32 address, arm_instruction_t *instruction)
131 {
132 u8 cp_num = (opcode & 0xf00) >> 8;
133
134 /* MCRR or MRRC */
135 if (((opcode & 0x0ff00000) == 0x0c400000) || ((opcode & 0x0ff00000) == 0x0c400000))
136 {
137 u8 cp_opcode, Rd, Rn, CRm;
138 char *mnemonic;
139
140 cp_opcode = (opcode & 0xf0) >> 4;
141 Rd = (opcode & 0xf000) >> 12;
142 Rn = (opcode & 0xf0000) >> 16;
143 CRm = (opcode & 0xf);
144
145 /* MCRR */
146 if ((opcode & 0x0ff00000) == 0x0c400000)
147 {
148 instruction->type = ARM_MCRR;
149 mnemonic = "MCRR";
150 }
151
152 /* MRRC */
153 if ((opcode & 0x0ff00000) == 0x0c500000)
154 {
155 instruction->type = ARM_MRRC;
156 mnemonic = "MRRC";
157 }
158
159 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s p%i, %x, r%i, r%i, c%i",
160 address, opcode, mnemonic, COND(opcode), cp_num, cp_opcode, Rd, Rn, CRm);
161 }
162 else /* LDC or STC */
163 {
164 u8 CRd, Rn, offset;
165 u8 U, N;
166 char *mnemonic;
167 char addressing_mode[32];
168
169 CRd = (opcode & 0xf000) >> 12;
170 Rn = (opcode & 0xf0000) >> 16;
171 offset = (opcode & 0xff);
172
173 /* load/store */
174 if (opcode & 0x00100000)
175 {
176 instruction->type = ARM_LDC;
177 mnemonic = "LDC";
178 }
179 else
180 {
181 instruction->type = ARM_STC;
182 mnemonic = "STC";
183 }
184
185 U = (opcode & 0x00800000) >> 23;
186 N = (opcode & 0x00400000) >> 22;
187
188 /* addressing modes */
189 if ((opcode & 0x01200000) == 0x01000000) /* immediate offset */
190 snprintf(addressing_mode, 32, "[r%i, #%s0x%2.2x*4]", Rn, (U) ? "" : "-", offset);
191 else if ((opcode & 0x01200000) == 0x01200000) /* immediate pre-indexed */
192 snprintf(addressing_mode, 32, "[r%i, #%s0x%2.2x*4]!", Rn, (U) ? "" : "-", offset);
193 else if ((opcode & 0x01200000) == 0x00200000) /* immediate post-indexed */
194 snprintf(addressing_mode, 32, "[r%i], #%s0x%2.2x*4", Rn, (U) ? "" : "-", offset);
195 else if ((opcode & 0x01200000) == 0x00000000) /* unindexed */
196 snprintf(addressing_mode, 32, "[r%i], #0x%2.2x", Rn, offset);
197
198 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s p%i, c%i, %s",
199 address, opcode, mnemonic, ((opcode & 0xf0000000) == 0xf0000000) ? COND(opcode) : "2",
200 (N) ? "L" : "",
201 cp_num, CRd, addressing_mode);
202 }
203
204 return ERROR_OK;
205 }
206
207 /* Coprocessor data processing instructions */
208 /* Coprocessor register transfer instructions */
209 /* both normal and extended instruction space (condition field b1111) */
210 int evaluate_cdp_mcr_mrc(u32 opcode, u32 address, arm_instruction_t *instruction)
211 {
212 char* cond;
213 char* mnemonic;
214 u8 cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2;
215
216 cond = ((opcode & 0xf0000000) == 0xf0000000) ? "2" : COND(opcode);
217 cp_num = (opcode & 0xf00) >> 8;
218 CRd_Rd = (opcode & 0xf000) >> 12;
219 CRn = (opcode & 0xf0000) >> 16;
220 CRm = (opcode & 0xf);
221 opcode_2 = (opcode & 0xe0) >> 5;
222
223 /* CDP or MRC/MCR */
224 if (opcode & 0x00000010) /* bit 4 set -> MRC/MCR */
225 {
226 if (opcode & 0x00100000) /* bit 20 set -> MRC */
227 {
228 instruction->type = ARM_MRC;
229 mnemonic = "MRC";
230 }
231 else /* bit 20 not set -> MCR */
232 {
233 instruction->type = ARM_MCR;
234 mnemonic = "MCR";
235 }
236
237 opcode_1 = (opcode & 0x00e00000) >> 21;
238
239 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s p%i, 0x%2.2x, r%i, c%i, c%i, 0x%2.2x",
240 address, opcode, mnemonic, cond,
241 cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2);
242 }
243 else /* bit 4 not set -> CDP */
244 {
245 instruction->type = ARM_CDP;
246 mnemonic = "CDP";
247
248 opcode_1 = (opcode & 0x00f00000) >> 20;
249
250 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s p%i, 0x%2.2x, c%i, c%i, c%i, 0x%2.2x",
251 address, opcode, mnemonic, cond,
252 cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2);
253 }
254
255 return ERROR_OK;
256 }
257
258 /* Load/store instructions */
259 int evaluate_load_store(u32 opcode, u32 address, arm_instruction_t *instruction)
260 {
261 u8 I, P, U, B, W, L;
262 u8 Rn, Rd;
263 char *operation; /* "LDR" or "STR" */
264 char *suffix; /* "", "B", "T", "BT" */
265 char offset[32];
266
267 /* examine flags */
268 I = (opcode & 0x02000000) >> 25;
269 P = (opcode & 0x01000000) >> 24;
270 U = (opcode & 0x00800000) >> 23;
271 B = (opcode & 0x00400000) >> 22;
272 W = (opcode & 0x00200000) >> 21;
273 L = (opcode & 0x00100000) >> 20;
274
275 /* target register */
276 Rd = (opcode & 0xf000) >> 12;
277
278 /* base register */
279 Rn = (opcode & 0xf0000) >> 16;
280
281 /* determine operation */
282 if (L)
283 operation = "LDR";
284 else
285 operation = "STR";
286
287 /* determine instruction type and suffix */
288 if (B)
289 {
290 if ((P == 0) && (W == 1))
291 {
292 if (L)
293 instruction->type = ARM_LDRBT;
294 else
295 instruction->type = ARM_STRBT;
296 suffix = "BT";
297 }
298 else
299 {
300 if (L)
301 instruction->type = ARM_LDRB;
302 else
303 instruction->type = ARM_STRB;
304 suffix = "B";
305 }
306 }
307 else
308 {
309 if ((P == 0) && (W == 1))
310 {
311 if (L)
312 instruction->type = ARM_LDRT;
313 else
314 instruction->type = ARM_STRT;
315 suffix = "T";
316 }
317 else
318 {
319 if (L)
320 instruction->type = ARM_LDR;
321 else
322 instruction->type = ARM_STR;
323 suffix = "";
324 }
325 }
326
327 if (!I) /* #+-<offset_12> */
328 {
329 u32 offset_12 = (opcode & 0xfff);
330 snprintf(offset, 32, "#%s0x%x", (U) ? "" : "-", offset_12);
331 }
332 else /* either +-<Rm> or +-<Rm>, <shift>, #<shift_imm> */
333 {
334 u8 shift_imm, shift;
335 u8 Rm;
336
337 shift_imm = (opcode & 0xf80) >> 7;
338 shift = (opcode & 0x60) >> 5;
339 Rm = (opcode & 0xf);
340
341 if ((shift_imm == 0x0) && (shift == 0x0)) /* +-<Rm> */
342 {
343 snprintf(offset, 32, "%sr%i", (U) ? "" : "-", Rm);
344 }
345 else /* +-<Rm>, <Shift>, #<shift_imm> */
346 {
347 if (shift == 0x0) /* LSL */
348 {
349 snprintf(offset, 32, "%sr%i, LSL #0x%x", (U) ? "" : "-", Rm, shift_imm);
350 }
351 else if (shift == 0x1) /* LSR */
352 {
353 snprintf(offset, 32, "%sr%i, LSR #0x%x", (U) ? "" : "-", Rm, shift_imm);
354 }
355 else if (shift == 0x2) /* ASR */
356 {
357 snprintf(offset, 32, "%sr%i, ASR #0x%x", (U) ? "" : "-", Rm, shift_imm);
358 }
359 else if (shift == 0x3) /* ROR or RRX */
360 {
361 if (shift_imm == 0x0) /* RRX */
362 snprintf(offset, 32, "%sr%i, RRX", (U) ? "" : "-", Rm);
363 else
364 snprintf(offset, 32, "%sr%i, ROR #0x%x", (U) ? "" : "-", Rm, shift_imm);
365 }
366 }
367 }
368
369 if (P == 1)
370 {
371 if (W == 0) /* offset */
372 {
373 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i, %s]",
374 address, opcode, operation, COND(opcode), suffix,
375 Rd, Rn, offset);
376 }
377 else /* pre-indexed */
378 {
379 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i, %s]!",
380 address, opcode, operation, COND(opcode), suffix,
381 Rd, Rn, offset);
382 }
383 }
384 else /* post-indexed */
385 {
386 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i], %s",
387 address, opcode, operation, COND(opcode), suffix,
388 Rd, Rn, offset);
389 }
390
391 return ERROR_OK;
392 }
393
394 /* Miscellaneous load/store instructions */
395 int evaluate_misc_load_store(u32 opcode, u32 address, arm_instruction_t *instruction)
396 {
397 u8 P, U, I, W, L, S, H;
398 u8 Rn, Rd;
399 char *operation; /* "LDR" or "STR" */
400 char *suffix; /* "H", "SB", "SH", "D" */
401 char offset[32];
402
403 /* examine flags */
404 P = (opcode & 0x01000000) >> 24;
405 U = (opcode & 0x00800000) >> 23;
406 I = (opcode & 0x00400000) >> 22;
407 W = (opcode & 0x00200000) >> 21;
408 L = (opcode & 0x00100000) >> 20;
409 S = (opcode & 0x00000040) >> 6;
410 H = (opcode & 0x00000020) >> 5;
411
412 /* target register */
413 Rd = (opcode & 0xf000) >> 12;
414
415 /* base register */
416 Rn = (opcode & 0xf0000) >> 16;
417
418 /* determine instruction type and suffix */
419 if (S) /* signed */
420 {
421 if (L) /* load */
422 {
423 if (H)
424 {
425 operation = "LDR";
426 instruction->type = ARM_LDRSH;
427 suffix = "SH";
428 }
429 else
430 {
431 operation = "LDR";
432 instruction->type = ARM_LDRSB;
433 suffix = "SB";
434 }
435 }
436 else /* there are no signed stores, so this is used to encode double-register load/stores */
437 {
438 suffix = "D";
439 if (H)
440 {
441 operation = "STR";
442 instruction->type = ARM_STRD;
443 }
444 else
445 {
446 operation = "LDR";
447 instruction->type = ARM_LDRD;
448 }
449 }
450 }
451 else /* unsigned */
452 {
453 suffix = "H";
454 if (L) /* load */
455 {
456 operation = "LDR";
457 instruction->type = ARM_LDRH;
458 }
459 else /* store */
460 {
461 operation = "STR";
462 instruction->type = ARM_STRH;
463 }
464 }
465
466 if (I) /* Immediate offset/index (#+-<offset_8>)*/
467 {
468 u32 offset_8 = ((opcode & 0xf00) >> 4) | (opcode & 0xf);
469 snprintf(offset, 32, "#%s0x%x", (U) ? "" : "-", offset_8);
470 }
471 else /* Register offset/index (+-<Rm>) */
472 {
473 u8 Rm;
474 Rm = (opcode & 0xf);
475 snprintf(offset, 32, "%sr%i", (U) ? "" : "-", Rm);
476 }
477
478 if (P == 1)
479 {
480 if (W == 0) /* offset */
481 {
482 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i, %s]",
483 address, opcode, operation, COND(opcode), suffix,
484 Rd, Rn, offset);
485 }
486 else /* pre-indexed */
487 {
488 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i, %s]!",
489 address, opcode, operation, COND(opcode), suffix,
490 Rd, Rn, offset);
491 }
492 }
493 else /* post-indexed */
494 {
495 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, [r%i], %s",
496 address, opcode, operation, COND(opcode), suffix,
497 Rd, Rn, offset);
498 }
499
500 return ERROR_OK;
501 }
502
503 /* Load/store multiples instructions */
504 int evaluate_ldm_stm(u32 opcode, u32 address, arm_instruction_t *instruction)
505 {
506 u8 P, U, S, W, L, Rn;
507 u32 register_list;
508 char *addressing_mode;
509 char *mnemonic;
510 char reg_list[69];
511 char *reg_list_p;
512 int i;
513 int first_reg = 1;
514
515 P = (opcode & 0x01000000) >> 24;
516 U = (opcode & 0x00800000) >> 23;
517 S = (opcode & 0x00400000) >> 22;
518 W = (opcode & 0x00200000) >> 21;
519 L = (opcode & 0x00100000) >> 20;
520 register_list = (opcode & 0xffff);
521 Rn = (opcode & 0xf0000) >> 16;
522
523 if (L)
524 {
525 instruction->type = ARM_LDM;
526 mnemonic = "LDM";
527 }
528 else
529 {
530 instruction->type = ARM_STM;
531 mnemonic = "STM";
532 }
533
534 if (P)
535 {
536 if (U)
537 addressing_mode = "IB";
538 else
539 addressing_mode = "DB";
540 }
541 else
542 {
543 if (U)
544 addressing_mode = "IA";
545 else
546 addressing_mode = "DA";
547 }
548
549 reg_list_p = reg_list;
550 for (i = 0; i <= 15; i++)
551 {
552 if ((register_list >> i) & 1)
553 {
554 if (first_reg)
555 {
556 first_reg = 0;
557 reg_list_p += snprintf(reg_list_p, (reg_list + 69 - reg_list_p), "r%i", i);
558 }
559 else
560 {
561 reg_list_p += snprintf(reg_list_p, (reg_list + 69 - reg_list_p), ", r%i", i);
562 }
563 }
564 }
565
566 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i%s, {%s}%s",
567 address, opcode, mnemonic, COND(opcode), addressing_mode,
568 Rn, (W) ? "!" : "", reg_list, (S) ? "^" : "");
569
570 return ERROR_OK;
571 }
572
573 /* Multiplies, extra load/stores */
574 int evaluate_mul_and_extra_ld_st(u32 opcode, u32 address, arm_instruction_t *instruction)
575 {
576 /* Multiply (accumulate) (long) and Swap/swap byte */
577 if ((opcode & 0x000000f0) == 0x00000090)
578 {
579 /* Multiply (accumulate) */
580 if ((opcode & 0x0f800000) == 0x00000000)
581 {
582 u8 Rm, Rs, Rn, Rd, S;
583 Rm = opcode & 0xf;
584 Rs = (opcode & 0xf00) >> 8;
585 Rn = (opcode & 0xf000) >> 12;
586 Rd = (opcode & 0xf0000) >> 16;
587 S = (opcode & 0x00100000) >> 20;
588
589 /* examine A bit (accumulate) */
590 if (opcode & 0x00200000)
591 {
592 instruction->type = ARM_MLA;
593 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tMLA%s%s r%i, r%i, r%i, r%i",
594 address, opcode, COND(opcode), (S) ? "S" : "", Rd, Rm, Rs, Rn);
595 }
596 else
597 {
598 instruction->type = ARM_MUL;
599 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tMUL%s%s r%i, r%i, r%i",
600 address, opcode, COND(opcode), (S) ? "S" : "", Rd, Rm, Rs);
601 }
602
603 return ERROR_OK;
604 }
605
606 /* Multiply (accumulate) long */
607 if ((opcode & 0x0f800000) == 0x00800000)
608 {
609 char* mnemonic;
610 u8 Rm, Rs, RdHi, RdLow, S;
611 Rm = opcode & 0xf;
612 Rs = (opcode & 0xf00) >> 8;
613 RdHi = (opcode & 0xf000) >> 12;
614 RdLow = (opcode & 0xf0000) >> 16;
615 S = (opcode & 0x00100000) >> 20;
616
617 switch ((opcode & 0x00600000) >> 21)
618 {
619 case 0x0:
620 instruction->type = ARM_UMULL;
621 mnemonic = "UMULL";
622 break;
623 case 0x1:
624 instruction->type = ARM_UMLAL;
625 mnemonic = "UMLAL";
626 break;
627 case 0x2:
628 instruction->type = ARM_SMULL;
629 mnemonic = "SMULL";
630 break;
631 case 0x3:
632 instruction->type = ARM_SMLAL;
633 mnemonic = "SMLAL";
634 break;
635 }
636
637 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, r%i, r%i, r%i",
638 address, opcode, mnemonic, COND(opcode), (S) ? "S" : "",
639 RdLow, RdHi, Rm, Rs);
640
641 return ERROR_OK;
642 }
643
644 /* Swap/swap byte */
645 if ((opcode & 0x0f800000) == 0x01000000)
646 {
647 u8 Rm, Rd, Rn;
648 Rm = opcode & 0xf;
649 Rd = (opcode & 0xf000) >> 12;
650 Rn = (opcode & 0xf0000) >> 16;
651
652 /* examine B flag */
653 instruction->type = (opcode & 0x00400000) ? ARM_SWPB : ARM_SWP;
654
655 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s r%i, r%i, [r%i]",
656 address, opcode, (opcode & 0x00400000) ? "SWPB" : "SWP", COND(opcode), Rd, Rm, Rn);
657 return ERROR_OK;
658 }
659
660 }
661
662 return evaluate_misc_load_store(opcode, address, instruction);
663 }
664
665 int evaluate_mrs_msr(u32 opcode, u32 address, arm_instruction_t *instruction)
666 {
667 int R = (opcode & 0x00400000) >> 22;
668 char *PSR = (R) ? "SPSR" : "CPSR";
669
670 /* Move register to status register (MSR) */
671 if (opcode & 0x00200000)
672 {
673 instruction->type = ARM_MSR;
674
675 /* immediate variant */
676 if (opcode & 0x02000000)
677 {
678 u8 immediate = (opcode & 0xff);
679 u8 rotate = (opcode & 0xf00);
680
681 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tMSR%s %s_%s%s%s%s, 0x%8.8x",
682 address, opcode, COND(opcode), PSR,
683 (opcode & 0x10000) ? "c" : "",
684 (opcode & 0x20000) ? "x" : "",
685 (opcode & 0x40000) ? "s" : "",
686 (opcode & 0x80000) ? "f" : "",
687 ror(immediate, (rotate * 2))
688 );
689 }
690 else /* register variant */
691 {
692 u8 Rm = opcode & 0xf;
693 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tMSR%s %s_%s%s%s%s, r%i",
694 address, opcode, COND(opcode), PSR,
695 (opcode & 0x10000) ? "c" : "",
696 (opcode & 0x20000) ? "x" : "",
697 (opcode & 0x40000) ? "s" : "",
698 (opcode & 0x80000) ? "f" : "",
699 Rm
700 );
701 }
702
703 }
704 else /* Move status register to register (MRS) */
705 {
706 u8 Rd;
707
708 instruction->type = ARM_MRS;
709 Rd = (opcode & 0x0000f000) >> 12;
710
711 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tMRS%s r%i, %s",
712 address, opcode, COND(opcode), Rd, PSR);
713 }
714
715 return ERROR_OK;
716 }
717
718 /* Miscellaneous instructions */
719 int evaluate_misc_instr(u32 opcode, u32 address, arm_instruction_t *instruction)
720 {
721 /* MRS/MSR */
722 if ((opcode & 0x000000f0) == 0x00000000)
723 {
724 evaluate_mrs_msr(opcode, address, instruction);
725 }
726
727 /* BX */
728 if ((opcode & 0x006000f0) == 0x00200010)
729 {
730 u8 Rm;
731 instruction->type = ARM_BX;
732 Rm = opcode & 0xf;
733
734 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tBX%s r%i",
735 address, opcode, COND(opcode), Rm);
736 }
737
738 /* CLZ */
739 if ((opcode & 0x0060000f0) == 0x00300010)
740 {
741 u8 Rm, Rd;
742 instruction->type = ARM_CLZ;
743 Rm = opcode & 0xf;
744 Rd = (opcode & 0xf000) >> 12;
745
746 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tCLZ%s r%i, r%i",
747 address, opcode, COND(opcode), Rd, Rm);
748 }
749
750 /* BLX */
751 if ((opcode & 0x0060000f0) == 0x00200030)
752 {
753 u8 Rm;
754 instruction->type = ARM_BLX;
755 Rm = opcode & 0xf;
756
757 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tBLX%s r%i",
758 address, opcode, COND(opcode), Rm);
759 }
760
761 /* Enhanced DSP add/subtracts */
762 if ((opcode & 0x0000000f0) == 0x00000050)
763 {
764 u8 Rm, Rd, Rn;
765 char *mnemonic;
766 Rm = opcode & 0xf;
767 Rd = (opcode & 0xf000) >> 12;
768 Rn = (opcode & 0xf0000) >> 16;
769
770 switch ((opcode & 0x00600000) >> 21)
771 {
772 case 0x0:
773 instruction->type = ARM_QADD;
774 mnemonic = "QADD";
775 break;
776 case 0x1:
777 instruction->type = ARM_QSUB;
778 mnemonic = "QSUB";
779 break;
780 case 0x2:
781 instruction->type = ARM_QDADD;
782 mnemonic = "QDADD";
783 break;
784 case 0x3:
785 instruction->type = ARM_QDSUB;
786 mnemonic = "QDSUB";
787 break;
788 }
789
790 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s r%i, r%i, r%i",
791 address, opcode, mnemonic, COND(opcode), Rd, Rm, Rn);
792 }
793
794 /* Software breakpoints */
795 if ((opcode & 0x0000000f0) == 0x00000070)
796 {
797 u32 immediate;
798 instruction->type = ARM_BKPT;
799 immediate = ((opcode & 0x000fff00) >> 4) | (opcode & 0xf);
800
801 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tBKPT 0x%4.4x",
802 address, opcode, immediate);
803 }
804
805 /* Enhanced DSP multiplies */
806 if ((opcode & 0x000000090) == 0x00000080)
807 {
808 int x = (opcode & 0x20) >> 5;
809 int y = (opcode & 0x40) >> 6;
810
811 /* SMLA<x><y> */
812 if ((opcode & 0x00600000) == 0x00000000)
813 {
814 u8 Rd, Rm, Rs, Rn;
815 instruction->type = ARM_SMLAxy;
816 Rd = (opcode & 0xf0000) >> 16;
817 Rm = (opcode & 0xf);
818 Rs = (opcode & 0xf00) >> 8;
819 Rn = (opcode & 0xf000) >> 12;
820
821 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tSMLA%s%s%s r%i, r%i, r%i, r%i",
822 address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
823 Rd, Rm, Rs, Rn);
824 }
825
826 /* SMLAL<x><y> */
827 if ((opcode & 0x00600000) == 0x00400000)
828 {
829 u8 RdLow, RdHi, Rm, Rs;
830 instruction->type = ARM_SMLAxy;
831 RdHi = (opcode & 0xf0000) >> 16;
832 RdLow = (opcode & 0xf000) >> 12;
833 Rm = (opcode & 0xf);
834 Rs = (opcode & 0xf00) >> 8;
835
836 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tSMLA%s%s%s r%i, r%i, r%i, r%i",
837 address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
838 RdLow, RdHi, Rm, Rs);
839 }
840
841 /* SMLAW<y> */
842 if (((opcode & 0x00600000) == 0x00100000) && (x == 0))
843 {
844 u8 Rd, Rm, Rs, Rn;
845 instruction->type = ARM_SMLAWy;
846 Rd = (opcode & 0xf0000) >> 16;
847 Rm = (opcode & 0xf);
848 Rs = (opcode & 0xf00) >> 8;
849 Rn = (opcode & 0xf000) >> 12;
850
851 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tSMLAW%s%s r%i, r%i, r%i, r%i",
852 address, opcode, (y) ? "T" : "B", COND(opcode),
853 Rd, Rm, Rs, Rn);
854 }
855
856 /* SMUL<x><y> */
857 if ((opcode & 0x00600000) == 0x00300000)
858 {
859 u8 Rd, Rm, Rs;
860 instruction->type = ARM_SMULxy;
861 Rd = (opcode & 0xf0000) >> 16;
862 Rm = (opcode & 0xf);
863 Rs = (opcode & 0xf00) >> 8;
864
865 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tSMULW%s%s%s r%i, r%i, r%i",
866 address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
867 Rd, Rm, Rs);
868 }
869
870 /* SMULW<y> */
871 if (((opcode & 0x00600000) == 0x00100000) && (x == 1))
872 {
873 u8 Rd, Rm, Rs;
874 instruction->type = ARM_SMULWy;
875 Rd = (opcode & 0xf0000) >> 16;
876 Rm = (opcode & 0xf);
877 Rs = (opcode & 0xf00) >> 8;
878
879 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tSMULW%s%s r%i, r%i, r%i",
880 address, opcode, (y) ? "T" : "B", COND(opcode),
881 Rd, Rm, Rs);
882 }
883 }
884
885 return ERROR_OK;
886 }
887
888 int evaluate_data_proc(u32 opcode, u32 address, arm_instruction_t *instruction)
889 {
890 u8 I, op, S, Rn, Rd;
891 char *mnemonic;
892 char shifter_operand[32];
893
894 I = (opcode & 0x02000000) >> 25;
895 op = (opcode & 0x01e00000) >> 21;
896 S = (opcode & 0x00100000) >> 20;
897
898 Rd = (opcode & 0xf000) >> 12;
899 Rn = (opcode & 0xf0000) >> 16;
900
901 switch (op)
902 {
903 case 0x0:
904 instruction->type = ARM_AND;
905 mnemonic = "AND";
906 break;
907 case 0x1:
908 instruction->type = ARM_EOR;
909 mnemonic = "EOR";
910 break;
911 case 0x2:
912 instruction->type = ARM_SUB;
913 mnemonic = "SUB";
914 break;
915 case 0x3:
916 instruction->type = ARM_RSB;
917 mnemonic = "RSB";
918 break;
919 case 0x4:
920 instruction->type = ARM_ADD;
921 mnemonic = "ADD";
922 break;
923 case 0x5:
924 instruction->type = ARM_ADC;
925 mnemonic = "ADC";
926 break;
927 case 0x6:
928 instruction->type = ARM_SBC;
929 mnemonic = "SBC";
930 break;
931 case 0x7:
932 instruction->type = ARM_RSC;
933 mnemonic = "RSC";
934 break;
935 case 0x8:
936 instruction->type = ARM_TST;
937 mnemonic = "TST";
938 break;
939 case 0x9:
940 instruction->type = ARM_TEQ;
941 mnemonic = "TEQ";
942 break;
943 case 0xa:
944 instruction->type = ARM_CMP;
945 mnemonic = "CMP";
946 break;
947 case 0xb:
948 instruction->type = ARM_CMN;
949 mnemonic = "CMN";
950 break;
951 case 0xc:
952 instruction->type = ARM_ORR;
953 mnemonic = "ORR";
954 break;
955 case 0xd:
956 instruction->type = ARM_MOV;
957 mnemonic = "MOV";
958 break;
959 case 0xe:
960 instruction->type = ARM_BIC;
961 mnemonic = "BIC";
962 break;
963 case 0xf:
964 instruction->type = ARM_MVN;
965 mnemonic = "MVN";
966 break;
967 }
968
969 if (I) /* immediate shifter operand (#<immediate>)*/
970 {
971 u8 immed_8 = opcode & 0xff;
972 u8 rotate_imm = (opcode & 0xf00) >> 8;
973 u32 immediate;
974
975 immediate = ror(immed_8, rotate_imm * 2);
976
977 snprintf(shifter_operand, 32, "#0x%x", immediate);
978 }
979 else /* register-based shifter operand */
980 {
981 u8 shift, Rm;
982 shift = (opcode & 0x60) >> 5;
983 Rm = (opcode & 0xf);
984
985 if ((opcode & 0x10) != 0x10) /* Immediate shifts ("<Rm>" or "<Rm>, <shift> #<shift_immediate>") */
986 {
987 u8 shift_imm;
988 shift_imm = (opcode & 0xf80) >> 7;
989
990
991 if ((shift_imm == 0x0) && (shift == 0x0))
992 {
993 snprintf(shifter_operand, 32, "r%i", Rm);
994 }
995 else
996 {
997 if (shift == 0x0) /* LSL */
998 {
999 snprintf(shifter_operand, 32, "r%i, LSL #0x%x", Rm, shift_imm);
1000 }
1001 else if (shift == 0x1) /* LSR */
1002 {
1003 if (shift_imm == 0x0)
1004 shift_imm = 0x32;
1005 snprintf(shifter_operand, 32, "r%i, LSR #0x%x", Rm, shift_imm);
1006 }
1007 else if (shift == 0x2) /* ASR */
1008 {
1009 if (shift_imm == 0x0)
1010 shift_imm = 0x32;
1011 snprintf(shifter_operand, 32, "r%i, ASR #0x%x", Rm, shift_imm);
1012 }
1013 else if (shift == 0x3) /* ROR or RRX */
1014 {
1015 if (shift_imm == 0x0) /* RRX */
1016 snprintf(shifter_operand, 32, "r%i, RRX", Rm);
1017 else
1018 snprintf(shifter_operand, 32, "r%i, ROR #0x%x", Rm, shift_imm);
1019 }
1020 }
1021 }
1022 else /* Register shifts ("<Rm>, <shift> <Rs>") */
1023 {
1024 u8 Rs = (opcode & 0xf00) >> 8;
1025
1026 if (shift == 0x0) /* LSL */
1027 {
1028 snprintf(shifter_operand, 32, "r%i, LSL r%i", Rm, Rs);
1029 }
1030 else if (shift == 0x1) /* LSR */
1031 {
1032 snprintf(shifter_operand, 32, "r%i, LSR r%i", Rm, Rs);
1033 }
1034 else if (shift == 0x2) /* ASR */
1035 {
1036 snprintf(shifter_operand, 32, "r%i, ASR r%i", Rm, Rs);
1037 }
1038 else if (shift == 0x3) /* ROR or RRX */
1039 {
1040 snprintf(shifter_operand, 32, "r%i, ROR r%i", Rm, Rs);
1041 }
1042 }
1043 }
1044
1045 if ((op < 0x8) || (op == 0xc) || (op == 0xe)) /* <opcode3>{<cond>}{S} <Rd>, <Rn>, <shifter_operand> */
1046 {
1047 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, r%i, %s",
1048 address, opcode, mnemonic, COND(opcode),
1049 (S) ? "S" : "", Rd, Rn, shifter_operand);
1050 }
1051 else if ((op == 0xd) || (op == 0xf)) /* <opcode1>{<cond>}{S} <Rd>, <shifter_operand> */
1052 {
1053 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s%s r%i, %s",
1054 address, opcode, mnemonic, COND(opcode),
1055 (S) ? "S" : "", Rd, shifter_operand);
1056 }
1057 else /* <opcode2>{<cond>} <Rn>, <shifter_operand> */
1058 {
1059 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\t%s%s r%i, %s",
1060 address, opcode, mnemonic, COND(opcode),
1061 Rn, shifter_operand);
1062 }
1063
1064 return ERROR_OK;
1065 }
1066
1067 int evaluate_opcode(u32 opcode, u32 address, arm_instruction_t *instruction)
1068 {
1069 /* clear fields, to avoid confusion */
1070 bzero(instruction, sizeof(arm_instruction_t));
1071 instruction->opcode = opcode;
1072
1073 /* catch opcodes with condition field [31:28] = b1111 */
1074 if ((opcode & 0xf0000000) == 0xf0000000)
1075 {
1076 /* Undefined instruction (or ARMv5E cache preload PLD) */
1077 if ((opcode & 0x08000000) == 0x00000000)
1078 return evaluate_pld(opcode, address, instruction);
1079
1080 /* Undefined instruction */
1081 if ((opcode & 0x0e000000) == 0x08000000)
1082 {
1083 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1084 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tUNDEFINED INSTRUCTION", address, opcode);
1085 return ERROR_OK;
1086 }
1087
1088 /* Branch and branch with link and change to Thumb */
1089 if ((opcode & 0x0e000000) == 0x0a000000)
1090 return evaluate_blx_imm(opcode, address, instruction);
1091
1092 /* Extended coprocessor opcode space (ARMv5 and higher )*/
1093 /* Coprocessor load/store and double register transfers */
1094 if ((opcode & 0x0e000000) == 0x0c000000)
1095 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1096
1097 /* Coprocessor data processing */
1098 if ((opcode & 0x0f000100) == 0x0c000000)
1099 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1100
1101 /* Coprocessor register transfers */
1102 if ((opcode & 0x0f000010) == 0x0c000010)
1103 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1104
1105 /* Undefined instruction */
1106 if ((opcode & 0x0f000000) == 0x0f000000)
1107 {
1108 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1109 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tUNDEFINED INSTRUCTION", address, opcode);
1110 return ERROR_OK;
1111 }
1112 }
1113
1114 /* catch opcodes with [27:25] = b000 */
1115 if ((opcode & 0x0e000000) == 0x00000000)
1116 {
1117 /* Multiplies, extra load/stores */
1118 if ((opcode & 0x00000090) == 0x00000090)
1119 return evaluate_mul_and_extra_ld_st(opcode, address, instruction);
1120
1121 /* Miscellaneous instructions */
1122 if ((opcode & 0x0f900000) == 0x01000000)
1123 return evaluate_misc_instr(opcode, address, instruction);
1124
1125 return evaluate_data_proc(opcode, address, instruction);
1126 }
1127
1128 /* catch opcodes with [27:25] = b001 */
1129 if ((opcode & 0x0e000000) == 0x02000000)
1130 {
1131 /* Undefined instruction */
1132 if ((opcode & 0x0fb00000) == 0x03000000)
1133 {
1134 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1135 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tUNDEFINED INSTRUCTION", address, opcode);
1136 return ERROR_OK;
1137 }
1138
1139 /* Move immediate to status register */
1140 if ((opcode & 0x0fb00000) == 0x03200000)
1141 return evaluate_mrs_msr(opcode, address, instruction);
1142
1143 return evaluate_data_proc(opcode, address, instruction);
1144
1145 }
1146
1147 /* catch opcodes with [27:25] = b010 */
1148 if ((opcode & 0x0e000000) == 0x04000000)
1149 {
1150 /* Load/store immediate offset */
1151 return evaluate_load_store(opcode, address, instruction);
1152 }
1153
1154 /* catch opcodes with [27:25] = b011 */
1155 if ((opcode & 0x0e000000) == 0x04000000)
1156 {
1157 /* Undefined instruction */
1158 if ((opcode & 0x00000010) == 0x00000010)
1159 {
1160 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1161 snprintf(instruction->text, 128, "0x%8.8x\t0x%8.8x\tUNDEFINED INSTRUCTION", address, opcode);
1162 return ERROR_OK;
1163 }
1164
1165 /* Load/store register offset */
1166 return evaluate_load_store(opcode, address, instruction);
1167
1168 }
1169
1170 /* catch opcodes with [27:25] = b100 */
1171 if ((opcode & 0x0e000000) == 0x08000000)
1172 {
1173 /* Load/store multiple */
1174 return evaluate_ldm_stm(opcode, address, instruction);
1175 }
1176
1177 /* catch opcodes with [27:25] = b101 */
1178 if ((opcode & 0x0e000000) == 0x0a000000)
1179 {
1180 /* Branch and branch with link */
1181 return evaluate_b_bl(opcode, address, instruction);
1182 }
1183
1184 /* catch opcodes with [27:25] = b110 */
1185 if ((opcode & 0x0e000000) == 0x0a000000)
1186 {
1187 /* Coprocessor load/store and double register transfers */
1188 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1189 }
1190
1191 /* catch opcodes with [27:25] = b111 */
1192 if ((opcode & 0x0e000000) == 0x0e000000)
1193 {
1194 /* Software interrupt */
1195 if ((opcode & 0x0f000000) == 0x0f000000)
1196 return evaluate_swi(opcode, address, instruction);
1197
1198 /* Coprocessor data processing */
1199 if ((opcode & 0x0f000010) == 0x0e000000)
1200 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1201
1202 /* Coprocessor register transfers */
1203 if ((opcode & 0x0f000010) == 0x0e000010)
1204 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1205 }
1206
1207 ERROR("should never reach this point");
1208 return -1;
1209 }

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)