David Brownell <david-b@pacbell.net>:
[openocd.git] / src / target / arm_disassembler.c
1 /***************************************************************************
2 * Copyright (C) 2006 by Dominic Rath *
3 * Dominic.Rath@gmx.de *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
19 ***************************************************************************/
20 #ifdef HAVE_CONFIG_H
21 #include "config.h"
22 #endif
23
24 #include "target.h"
25 #include "arm_disassembler.h"
26 #include "log.h"
27
28
29 /* textual represenation of the condition field */
30 /* ALways (default) is ommitted (empty string) */
31 char *arm_condition_strings[] =
32 {
33 "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", "HI", "LS", "GE", "LT", "GT", "LE", "", "NV"
34 };
35
36 /* make up for C's missing ROR */
37 uint32_t ror(uint32_t value, int places)
38 {
39 return (value >> places) | (value << (32 - places));
40 }
41
42 int evaluate_pld(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
43 {
44 /* PLD */
45 if ((opcode & 0x0d70f0000) == 0x0550f000)
46 {
47 instruction->type = ARM_PLD;
48
49 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD ...TODO...", address, opcode);
50
51 return ERROR_OK;
52 }
53 else
54 {
55 instruction->type = ARM_UNDEFINED_INSTRUCTION;
56 return ERROR_OK;
57 }
58
59 LOG_ERROR("should never reach this point");
60 return -1;
61 }
62
63 int evaluate_swi(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
64 {
65 instruction->type = ARM_SWI;
66
67 snprintf(instruction->text, 128,
68 "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSVC %#6.6" PRIx32,
69 address, opcode, (opcode & 0xffffff));
70
71 return ERROR_OK;
72 }
73
74 int evaluate_blx_imm(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
75 {
76 int offset;
77 uint32_t immediate;
78 uint32_t target_address;
79
80 instruction->type = ARM_BLX;
81 immediate = opcode & 0x00ffffff;
82
83 /* sign extend 24-bit immediate */
84 if (immediate & 0x00800000)
85 offset = 0xff000000 | immediate;
86 else
87 offset = immediate;
88
89 /* shift two bits left */
90 offset <<= 2;
91
92 /* odd/event halfword */
93 if (opcode & 0x01000000)
94 offset |= 0x2;
95
96 target_address = address + 8 + offset;
97
98 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX 0x%8.8" PRIx32 "", address, opcode, target_address);
99
100 instruction->info.b_bl_bx_blx.reg_operand = -1;
101 instruction->info.b_bl_bx_blx.target_address = target_address;
102
103 return ERROR_OK;
104 }
105
106 int evaluate_b_bl(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
107 {
108 uint8_t L;
109 uint32_t immediate;
110 int offset;
111 uint32_t target_address;
112
113 immediate = opcode & 0x00ffffff;
114 L = (opcode & 0x01000000) >> 24;
115
116 /* sign extend 24-bit immediate */
117 if (immediate & 0x00800000)
118 offset = 0xff000000 | immediate;
119 else
120 offset = immediate;
121
122 /* shift two bits left */
123 offset <<= 2;
124
125 target_address = address + 8 + offset;
126
127 if (L)
128 instruction->type = ARM_BL;
129 else
130 instruction->type = ARM_B;
131
132 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tB%s%s 0x%8.8" PRIx32 , address, opcode,
133 (L) ? "L" : "", COND(opcode), target_address);
134
135 instruction->info.b_bl_bx_blx.reg_operand = -1;
136 instruction->info.b_bl_bx_blx.target_address = target_address;
137
138 return ERROR_OK;
139 }
140
141 /* Coprocessor load/store and double register transfers */
142 /* both normal and extended instruction space (condition field b1111) */
143 int evaluate_ldc_stc_mcrr_mrrc(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
144 {
145 uint8_t cp_num = (opcode & 0xf00) >> 8;
146
147 /* MCRR or MRRC */
148 if (((opcode & 0x0ff00000) == 0x0c400000) || ((opcode & 0x0ff00000) == 0x0c400000))
149 {
150 uint8_t cp_opcode, Rd, Rn, CRm;
151 char *mnemonic;
152
153 cp_opcode = (opcode & 0xf0) >> 4;
154 Rd = (opcode & 0xf000) >> 12;
155 Rn = (opcode & 0xf0000) >> 16;
156 CRm = (opcode & 0xf);
157
158 /* MCRR */
159 if ((opcode & 0x0ff00000) == 0x0c400000)
160 {
161 instruction->type = ARM_MCRR;
162 mnemonic = "MCRR";
163 }
164
165 /* MRRC */
166 if ((opcode & 0x0ff00000) == 0x0c500000)
167 {
168 instruction->type = ARM_MRRC;
169 mnemonic = "MRRC";
170 }
171
172 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, %x, r%i, r%i, c%i",
173 address, opcode, mnemonic, COND(opcode), cp_num, cp_opcode, Rd, Rn, CRm);
174 }
175 else /* LDC or STC */
176 {
177 uint8_t CRd, Rn, offset;
178 uint8_t U, N;
179 char *mnemonic;
180 char addressing_mode[32];
181
182 CRd = (opcode & 0xf000) >> 12;
183 Rn = (opcode & 0xf0000) >> 16;
184 offset = (opcode & 0xff);
185
186 /* load/store */
187 if (opcode & 0x00100000)
188 {
189 instruction->type = ARM_LDC;
190 mnemonic = "LDC";
191 }
192 else
193 {
194 instruction->type = ARM_STC;
195 mnemonic = "STC";
196 }
197
198 U = (opcode & 0x00800000) >> 23;
199 N = (opcode & 0x00400000) >> 22;
200
201 /* addressing modes */
202 if ((opcode & 0x01200000) == 0x01000000) /* immediate offset */
203 snprintf(addressing_mode, 32, "[r%i, #%s0x%2.2x*4]", Rn, (U) ? "" : "-", offset);
204 else if ((opcode & 0x01200000) == 0x01200000) /* immediate pre-indexed */
205 snprintf(addressing_mode, 32, "[r%i, #%s0x%2.2x*4]!", Rn, (U) ? "" : "-", offset);
206 else if ((opcode & 0x01200000) == 0x00200000) /* immediate post-indexed */
207 snprintf(addressing_mode, 32, "[r%i], #%s0x%2.2x*4", Rn, (U) ? "" : "-", offset);
208 else if ((opcode & 0x01200000) == 0x00000000) /* unindexed */
209 snprintf(addressing_mode, 32, "[r%i], #0x%2.2x", Rn, offset);
210
211 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s p%i, c%i, %s",
212 address, opcode, mnemonic, ((opcode & 0xf0000000) == 0xf0000000) ? COND(opcode) : "2",
213 (N) ? "L" : "",
214 cp_num, CRd, addressing_mode);
215 }
216
217 return ERROR_OK;
218 }
219
220 /* Coprocessor data processing instructions */
221 /* Coprocessor register transfer instructions */
222 /* both normal and extended instruction space (condition field b1111) */
223 int evaluate_cdp_mcr_mrc(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
224 {
225 char* cond;
226 char* mnemonic;
227 uint8_t cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2;
228
229 cond = ((opcode & 0xf0000000) == 0xf0000000) ? "2" : COND(opcode);
230 cp_num = (opcode & 0xf00) >> 8;
231 CRd_Rd = (opcode & 0xf000) >> 12;
232 CRn = (opcode & 0xf0000) >> 16;
233 CRm = (opcode & 0xf);
234 opcode_2 = (opcode & 0xe0) >> 5;
235
236 /* CDP or MRC/MCR */
237 if (opcode & 0x00000010) /* bit 4 set -> MRC/MCR */
238 {
239 if (opcode & 0x00100000) /* bit 20 set -> MRC */
240 {
241 instruction->type = ARM_MRC;
242 mnemonic = "MRC";
243 }
244 else /* bit 20 not set -> MCR */
245 {
246 instruction->type = ARM_MCR;
247 mnemonic = "MCR";
248 }
249
250 opcode_1 = (opcode & 0x00e00000) >> 21;
251
252 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, 0x%2.2x, r%i, c%i, c%i, 0x%2.2x",
253 address, opcode, mnemonic, cond,
254 cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2);
255 }
256 else /* bit 4 not set -> CDP */
257 {
258 instruction->type = ARM_CDP;
259 mnemonic = "CDP";
260
261 opcode_1 = (opcode & 0x00f00000) >> 20;
262
263 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, 0x%2.2x, c%i, c%i, c%i, 0x%2.2x",
264 address, opcode, mnemonic, cond,
265 cp_num, opcode_1, CRd_Rd, CRn, CRm, opcode_2);
266 }
267
268 return ERROR_OK;
269 }
270
271 /* Load/store instructions */
272 int evaluate_load_store(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
273 {
274 uint8_t I, P, U, B, W, L;
275 uint8_t Rn, Rd;
276 char *operation; /* "LDR" or "STR" */
277 char *suffix; /* "", "B", "T", "BT" */
278 char offset[32];
279
280 /* examine flags */
281 I = (opcode & 0x02000000) >> 25;
282 P = (opcode & 0x01000000) >> 24;
283 U = (opcode & 0x00800000) >> 23;
284 B = (opcode & 0x00400000) >> 22;
285 W = (opcode & 0x00200000) >> 21;
286 L = (opcode & 0x00100000) >> 20;
287
288 /* target register */
289 Rd = (opcode & 0xf000) >> 12;
290
291 /* base register */
292 Rn = (opcode & 0xf0000) >> 16;
293
294 instruction->info.load_store.Rd = Rd;
295 instruction->info.load_store.Rn = Rn;
296 instruction->info.load_store.U = U;
297
298 /* determine operation */
299 if (L)
300 operation = "LDR";
301 else
302 operation = "STR";
303
304 /* determine instruction type and suffix */
305 if (B)
306 {
307 if ((P == 0) && (W == 1))
308 {
309 if (L)
310 instruction->type = ARM_LDRBT;
311 else
312 instruction->type = ARM_STRBT;
313 suffix = "BT";
314 }
315 else
316 {
317 if (L)
318 instruction->type = ARM_LDRB;
319 else
320 instruction->type = ARM_STRB;
321 suffix = "B";
322 }
323 }
324 else
325 {
326 if ((P == 0) && (W == 1))
327 {
328 if (L)
329 instruction->type = ARM_LDRT;
330 else
331 instruction->type = ARM_STRT;
332 suffix = "T";
333 }
334 else
335 {
336 if (L)
337 instruction->type = ARM_LDR;
338 else
339 instruction->type = ARM_STR;
340 suffix = "";
341 }
342 }
343
344 if (!I) /* #+-<offset_12> */
345 {
346 uint32_t offset_12 = (opcode & 0xfff);
347 if (offset_12)
348 snprintf(offset, 32, ", #%s0x%" PRIx32 "", (U) ? "" : "-", offset_12);
349 else
350 snprintf(offset, 32, "%s", "");
351
352 instruction->info.load_store.offset_mode = 0;
353 instruction->info.load_store.offset.offset = offset_12;
354 }
355 else /* either +-<Rm> or +-<Rm>, <shift>, #<shift_imm> */
356 {
357 uint8_t shift_imm, shift;
358 uint8_t Rm;
359
360 shift_imm = (opcode & 0xf80) >> 7;
361 shift = (opcode & 0x60) >> 5;
362 Rm = (opcode & 0xf);
363
364 /* LSR encodes a shift by 32 bit as 0x0 */
365 if ((shift == 0x1) && (shift_imm == 0x0))
366 shift_imm = 0x20;
367
368 /* ASR encodes a shift by 32 bit as 0x0 */
369 if ((shift == 0x2) && (shift_imm == 0x0))
370 shift_imm = 0x20;
371
372 /* ROR by 32 bit is actually a RRX */
373 if ((shift == 0x3) && (shift_imm == 0x0))
374 shift = 0x4;
375
376 instruction->info.load_store.offset_mode = 1;
377 instruction->info.load_store.offset.reg.Rm = Rm;
378 instruction->info.load_store.offset.reg.shift = shift;
379 instruction->info.load_store.offset.reg.shift_imm = shift_imm;
380
381 if ((shift_imm == 0x0) && (shift == 0x0)) /* +-<Rm> */
382 {
383 snprintf(offset, 32, ", %sr%i", (U) ? "" : "-", Rm);
384 }
385 else /* +-<Rm>, <Shift>, #<shift_imm> */
386 {
387 switch (shift)
388 {
389 case 0x0: /* LSL */
390 snprintf(offset, 32, ", %sr%i, LSL #0x%x", (U) ? "" : "-", Rm, shift_imm);
391 break;
392 case 0x1: /* LSR */
393 snprintf(offset, 32, ", %sr%i, LSR #0x%x", (U) ? "" : "-", Rm, shift_imm);
394 break;
395 case 0x2: /* ASR */
396 snprintf(offset, 32, ", %sr%i, ASR #0x%x", (U) ? "" : "-", Rm, shift_imm);
397 break;
398 case 0x3: /* ROR */
399 snprintf(offset, 32, ", %sr%i, ROR #0x%x", (U) ? "" : "-", Rm, shift_imm);
400 break;
401 case 0x4: /* RRX */
402 snprintf(offset, 32, ", %sr%i, RRX", (U) ? "" : "-", Rm);
403 break;
404 }
405 }
406 }
407
408 if (P == 1)
409 {
410 if (W == 0) /* offset */
411 {
412 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]",
413 address, opcode, operation, COND(opcode), suffix,
414 Rd, Rn, offset);
415
416 instruction->info.load_store.index_mode = 0;
417 }
418 else /* pre-indexed */
419 {
420 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]!",
421 address, opcode, operation, COND(opcode), suffix,
422 Rd, Rn, offset);
423
424 instruction->info.load_store.index_mode = 1;
425 }
426 }
427 else /* post-indexed */
428 {
429 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i]%s",
430 address, opcode, operation, COND(opcode), suffix,
431 Rd, Rn, offset);
432
433 instruction->info.load_store.index_mode = 2;
434 }
435
436 return ERROR_OK;
437 }
438
439 /* Miscellaneous load/store instructions */
440 int evaluate_misc_load_store(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
441 {
442 uint8_t P, U, I, W, L, S, H;
443 uint8_t Rn, Rd;
444 char *operation; /* "LDR" or "STR" */
445 char *suffix; /* "H", "SB", "SH", "D" */
446 char offset[32];
447
448 /* examine flags */
449 P = (opcode & 0x01000000) >> 24;
450 U = (opcode & 0x00800000) >> 23;
451 I = (opcode & 0x00400000) >> 22;
452 W = (opcode & 0x00200000) >> 21;
453 L = (opcode & 0x00100000) >> 20;
454 S = (opcode & 0x00000040) >> 6;
455 H = (opcode & 0x00000020) >> 5;
456
457 /* target register */
458 Rd = (opcode & 0xf000) >> 12;
459
460 /* base register */
461 Rn = (opcode & 0xf0000) >> 16;
462
463 instruction->info.load_store.Rd = Rd;
464 instruction->info.load_store.Rn = Rn;
465 instruction->info.load_store.U = U;
466
467 /* determine instruction type and suffix */
468 if (S) /* signed */
469 {
470 if (L) /* load */
471 {
472 if (H)
473 {
474 operation = "LDR";
475 instruction->type = ARM_LDRSH;
476 suffix = "SH";
477 }
478 else
479 {
480 operation = "LDR";
481 instruction->type = ARM_LDRSB;
482 suffix = "SB";
483 }
484 }
485 else /* there are no signed stores, so this is used to encode double-register load/stores */
486 {
487 suffix = "D";
488 if (H)
489 {
490 operation = "STR";
491 instruction->type = ARM_STRD;
492 }
493 else
494 {
495 operation = "LDR";
496 instruction->type = ARM_LDRD;
497 }
498 }
499 }
500 else /* unsigned */
501 {
502 suffix = "H";
503 if (L) /* load */
504 {
505 operation = "LDR";
506 instruction->type = ARM_LDRH;
507 }
508 else /* store */
509 {
510 operation = "STR";
511 instruction->type = ARM_STRH;
512 }
513 }
514
515 if (I) /* Immediate offset/index (#+-<offset_8>)*/
516 {
517 uint32_t offset_8 = ((opcode & 0xf00) >> 4) | (opcode & 0xf);
518 snprintf(offset, 32, "#%s0x%" PRIx32 "", (U) ? "" : "-", offset_8);
519
520 instruction->info.load_store.offset_mode = 0;
521 instruction->info.load_store.offset.offset = offset_8;
522 }
523 else /* Register offset/index (+-<Rm>) */
524 {
525 uint8_t Rm;
526 Rm = (opcode & 0xf);
527 snprintf(offset, 32, "%sr%i", (U) ? "" : "-", Rm);
528
529 instruction->info.load_store.offset_mode = 1;
530 instruction->info.load_store.offset.reg.Rm = Rm;
531 instruction->info.load_store.offset.reg.shift = 0x0;
532 instruction->info.load_store.offset.reg.shift_imm = 0x0;
533 }
534
535 if (P == 1)
536 {
537 if (W == 0) /* offset */
538 {
539 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]",
540 address, opcode, operation, COND(opcode), suffix,
541 Rd, Rn, offset);
542
543 instruction->info.load_store.index_mode = 0;
544 }
545 else /* pre-indexed */
546 {
547 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]!",
548 address, opcode, operation, COND(opcode), suffix,
549 Rd, Rn, offset);
550
551 instruction->info.load_store.index_mode = 1;
552 }
553 }
554 else /* post-indexed */
555 {
556 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i], %s",
557 address, opcode, operation, COND(opcode), suffix,
558 Rd, Rn, offset);
559
560 instruction->info.load_store.index_mode = 2;
561 }
562
563 return ERROR_OK;
564 }
565
566 /* Load/store multiples instructions */
567 int evaluate_ldm_stm(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
568 {
569 uint8_t P, U, S, W, L, Rn;
570 uint32_t register_list;
571 char *addressing_mode;
572 char *mnemonic;
573 char reg_list[69];
574 char *reg_list_p;
575 int i;
576 int first_reg = 1;
577
578 P = (opcode & 0x01000000) >> 24;
579 U = (opcode & 0x00800000) >> 23;
580 S = (opcode & 0x00400000) >> 22;
581 W = (opcode & 0x00200000) >> 21;
582 L = (opcode & 0x00100000) >> 20;
583 register_list = (opcode & 0xffff);
584 Rn = (opcode & 0xf0000) >> 16;
585
586 instruction->info.load_store_multiple.Rn = Rn;
587 instruction->info.load_store_multiple.register_list = register_list;
588 instruction->info.load_store_multiple.S = S;
589 instruction->info.load_store_multiple.W = W;
590
591 if (L)
592 {
593 instruction->type = ARM_LDM;
594 mnemonic = "LDM";
595 }
596 else
597 {
598 instruction->type = ARM_STM;
599 mnemonic = "STM";
600 }
601
602 if (P)
603 {
604 if (U)
605 {
606 instruction->info.load_store_multiple.addressing_mode = 1;
607 addressing_mode = "IB";
608 }
609 else
610 {
611 instruction->info.load_store_multiple.addressing_mode = 3;
612 addressing_mode = "DB";
613 }
614 }
615 else
616 {
617 if (U)
618 {
619 instruction->info.load_store_multiple.addressing_mode = 0;
620 /* "IA" is the default in UAL syntax */
621 addressing_mode = "";
622 }
623 else
624 {
625 instruction->info.load_store_multiple.addressing_mode = 2;
626 addressing_mode = "DA";
627 }
628 }
629
630 reg_list_p = reg_list;
631 for (i = 0; i <= 15; i++)
632 {
633 if ((register_list >> i) & 1)
634 {
635 if (first_reg)
636 {
637 first_reg = 0;
638 reg_list_p += snprintf(reg_list_p, (reg_list + 69 - reg_list_p), "r%i", i);
639 }
640 else
641 {
642 reg_list_p += snprintf(reg_list_p, (reg_list + 69 - reg_list_p), ", r%i", i);
643 }
644 }
645 }
646
647 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i%s, {%s}%s",
648 address, opcode, mnemonic, COND(opcode), addressing_mode,
649 Rn, (W) ? "!" : "", reg_list, (S) ? "^" : "");
650
651 return ERROR_OK;
652 }
653
654 /* Multiplies, extra load/stores */
655 int evaluate_mul_and_extra_ld_st(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
656 {
657 /* Multiply (accumulate) (long) and Swap/swap byte */
658 if ((opcode & 0x000000f0) == 0x00000090)
659 {
660 /* Multiply (accumulate) */
661 if ((opcode & 0x0f800000) == 0x00000000)
662 {
663 uint8_t Rm, Rs, Rn, Rd, S;
664 Rm = opcode & 0xf;
665 Rs = (opcode & 0xf00) >> 8;
666 Rn = (opcode & 0xf000) >> 12;
667 Rd = (opcode & 0xf0000) >> 16;
668 S = (opcode & 0x00100000) >> 20;
669
670 /* examine A bit (accumulate) */
671 if (opcode & 0x00200000)
672 {
673 instruction->type = ARM_MLA;
674 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMLA%s%s r%i, r%i, r%i, r%i",
675 address, opcode, COND(opcode), (S) ? "S" : "", Rd, Rm, Rs, Rn);
676 }
677 else
678 {
679 instruction->type = ARM_MUL;
680 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMUL%s%s r%i, r%i, r%i",
681 address, opcode, COND(opcode), (S) ? "S" : "", Rd, Rm, Rs);
682 }
683
684 return ERROR_OK;
685 }
686
687 /* Multiply (accumulate) long */
688 if ((opcode & 0x0f800000) == 0x00800000)
689 {
690 char* mnemonic = NULL;
691 uint8_t Rm, Rs, RdHi, RdLow, S;
692 Rm = opcode & 0xf;
693 Rs = (opcode & 0xf00) >> 8;
694 RdHi = (opcode & 0xf000) >> 12;
695 RdLow = (opcode & 0xf0000) >> 16;
696 S = (opcode & 0x00100000) >> 20;
697
698 switch ((opcode & 0x00600000) >> 21)
699 {
700 case 0x0:
701 instruction->type = ARM_UMULL;
702 mnemonic = "UMULL";
703 break;
704 case 0x1:
705 instruction->type = ARM_UMLAL;
706 mnemonic = "UMLAL";
707 break;
708 case 0x2:
709 instruction->type = ARM_SMULL;
710 mnemonic = "SMULL";
711 break;
712 case 0x3:
713 instruction->type = ARM_SMLAL;
714 mnemonic = "SMLAL";
715 break;
716 }
717
718 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, r%i, r%i",
719 address, opcode, mnemonic, COND(opcode), (S) ? "S" : "",
720 RdLow, RdHi, Rm, Rs);
721
722 return ERROR_OK;
723 }
724
725 /* Swap/swap byte */
726 if ((opcode & 0x0f800000) == 0x01000000)
727 {
728 uint8_t Rm, Rd, Rn;
729 Rm = opcode & 0xf;
730 Rd = (opcode & 0xf000) >> 12;
731 Rn = (opcode & 0xf0000) >> 16;
732
733 /* examine B flag */
734 instruction->type = (opcode & 0x00400000) ? ARM_SWPB : ARM_SWP;
735
736 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, [r%i]",
737 address, opcode, (opcode & 0x00400000) ? "SWPB" : "SWP", COND(opcode), Rd, Rm, Rn);
738 return ERROR_OK;
739 }
740
741 }
742
743 return evaluate_misc_load_store(opcode, address, instruction);
744 }
745
746 int evaluate_mrs_msr(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
747 {
748 int R = (opcode & 0x00400000) >> 22;
749 char *PSR = (R) ? "SPSR" : "CPSR";
750
751 /* Move register to status register (MSR) */
752 if (opcode & 0x00200000)
753 {
754 instruction->type = ARM_MSR;
755
756 /* immediate variant */
757 if (opcode & 0x02000000)
758 {
759 uint8_t immediate = (opcode & 0xff);
760 uint8_t rotate = (opcode & 0xf00);
761
762 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, 0x%8.8" PRIx32 ,
763 address, opcode, COND(opcode), PSR,
764 (opcode & 0x10000) ? "c" : "",
765 (opcode & 0x20000) ? "x" : "",
766 (opcode & 0x40000) ? "s" : "",
767 (opcode & 0x80000) ? "f" : "",
768 ror(immediate, (rotate * 2))
769 );
770 }
771 else /* register variant */
772 {
773 uint8_t Rm = opcode & 0xf;
774 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, r%i",
775 address, opcode, COND(opcode), PSR,
776 (opcode & 0x10000) ? "c" : "",
777 (opcode & 0x20000) ? "x" : "",
778 (opcode & 0x40000) ? "s" : "",
779 (opcode & 0x80000) ? "f" : "",
780 Rm
781 );
782 }
783
784 }
785 else /* Move status register to register (MRS) */
786 {
787 uint8_t Rd;
788
789 instruction->type = ARM_MRS;
790 Rd = (opcode & 0x0000f000) >> 12;
791
792 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMRS%s r%i, %s",
793 address, opcode, COND(opcode), Rd, PSR);
794 }
795
796 return ERROR_OK;
797 }
798
799 /* Miscellaneous instructions */
800 int evaluate_misc_instr(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
801 {
802 /* MRS/MSR */
803 if ((opcode & 0x000000f0) == 0x00000000)
804 {
805 evaluate_mrs_msr(opcode, address, instruction);
806 }
807
808 /* BX */
809 if ((opcode & 0x006000f0) == 0x00200010)
810 {
811 uint8_t Rm;
812 instruction->type = ARM_BX;
813 Rm = opcode & 0xf;
814
815 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBX%s r%i",
816 address, opcode, COND(opcode), Rm);
817
818 instruction->info.b_bl_bx_blx.reg_operand = Rm;
819 instruction->info.b_bl_bx_blx.target_address = -1;
820 }
821
822 /* CLZ */
823 if ((opcode & 0x006000f0) == 0x00600010)
824 {
825 uint8_t Rm, Rd;
826 instruction->type = ARM_CLZ;
827 Rm = opcode & 0xf;
828 Rd = (opcode & 0xf000) >> 12;
829
830 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCLZ%s r%i, r%i",
831 address, opcode, COND(opcode), Rd, Rm);
832 }
833
834 /* BLX(2) */
835 if ((opcode & 0x006000f0) == 0x00200030)
836 {
837 uint8_t Rm;
838 instruction->type = ARM_BLX;
839 Rm = opcode & 0xf;
840
841 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX%s r%i",
842 address, opcode, COND(opcode), Rm);
843
844 instruction->info.b_bl_bx_blx.reg_operand = Rm;
845 instruction->info.b_bl_bx_blx.target_address = -1;
846 }
847
848 /* Enhanced DSP add/subtracts */
849 if ((opcode & 0x0000000f0) == 0x00000050)
850 {
851 uint8_t Rm, Rd, Rn;
852 char *mnemonic = NULL;
853 Rm = opcode & 0xf;
854 Rd = (opcode & 0xf000) >> 12;
855 Rn = (opcode & 0xf0000) >> 16;
856
857 switch ((opcode & 0x00600000) >> 21)
858 {
859 case 0x0:
860 instruction->type = ARM_QADD;
861 mnemonic = "QADD";
862 break;
863 case 0x1:
864 instruction->type = ARM_QSUB;
865 mnemonic = "QSUB";
866 break;
867 case 0x2:
868 instruction->type = ARM_QDADD;
869 mnemonic = "QDADD";
870 break;
871 case 0x3:
872 instruction->type = ARM_QDSUB;
873 mnemonic = "QDSUB";
874 break;
875 }
876
877 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, r%i",
878 address, opcode, mnemonic, COND(opcode), Rd, Rm, Rn);
879 }
880
881 /* Software breakpoints */
882 if ((opcode & 0x0000000f0) == 0x00000070)
883 {
884 uint32_t immediate;
885 instruction->type = ARM_BKPT;
886 immediate = ((opcode & 0x000fff00) >> 4) | (opcode & 0xf);
887
888 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBKPT 0x%4.4" PRIx32 "",
889 address, opcode, immediate);
890 }
891
892 /* Enhanced DSP multiplies */
893 if ((opcode & 0x000000090) == 0x00000080)
894 {
895 int x = (opcode & 0x20) >> 5;
896 int y = (opcode & 0x40) >> 6;
897
898 /* SMLA < x><y> */
899 if ((opcode & 0x00600000) == 0x00000000)
900 {
901 uint8_t Rd, Rm, Rs, Rn;
902 instruction->type = ARM_SMLAxy;
903 Rd = (opcode & 0xf0000) >> 16;
904 Rm = (opcode & 0xf);
905 Rs = (opcode & 0xf00) >> 8;
906 Rn = (opcode & 0xf000) >> 12;
907
908 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
909 address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
910 Rd, Rm, Rs, Rn);
911 }
912
913 /* SMLAL < x><y> */
914 if ((opcode & 0x00600000) == 0x00400000)
915 {
916 uint8_t RdLow, RdHi, Rm, Rs;
917 instruction->type = ARM_SMLAxy;
918 RdHi = (opcode & 0xf0000) >> 16;
919 RdLow = (opcode & 0xf000) >> 12;
920 Rm = (opcode & 0xf);
921 Rs = (opcode & 0xf00) >> 8;
922
923 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
924 address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
925 RdLow, RdHi, Rm, Rs);
926 }
927
928 /* SMLAW < y> */
929 if (((opcode & 0x00600000) == 0x00100000) && (x == 0))
930 {
931 uint8_t Rd, Rm, Rs, Rn;
932 instruction->type = ARM_SMLAWy;
933 Rd = (opcode & 0xf0000) >> 16;
934 Rm = (opcode & 0xf);
935 Rs = (opcode & 0xf00) >> 8;
936 Rn = (opcode & 0xf000) >> 12;
937
938 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLAW%s%s r%i, r%i, r%i, r%i",
939 address, opcode, (y) ? "T" : "B", COND(opcode),
940 Rd, Rm, Rs, Rn);
941 }
942
943 /* SMUL < x><y> */
944 if ((opcode & 0x00600000) == 0x00300000)
945 {
946 uint8_t Rd, Rm, Rs;
947 instruction->type = ARM_SMULxy;
948 Rd = (opcode & 0xf0000) >> 16;
949 Rm = (opcode & 0xf);
950 Rs = (opcode & 0xf00) >> 8;
951
952 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s%s r%i, r%i, r%i",
953 address, opcode, (x) ? "T" : "B", (y) ? "T" : "B", COND(opcode),
954 Rd, Rm, Rs);
955 }
956
957 /* SMULW < y> */
958 if (((opcode & 0x00600000) == 0x00100000) && (x == 1))
959 {
960 uint8_t Rd, Rm, Rs;
961 instruction->type = ARM_SMULWy;
962 Rd = (opcode & 0xf0000) >> 16;
963 Rm = (opcode & 0xf);
964 Rs = (opcode & 0xf00) >> 8;
965
966 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s r%i, r%i, r%i",
967 address, opcode, (y) ? "T" : "B", COND(opcode),
968 Rd, Rm, Rs);
969 }
970 }
971
972 return ERROR_OK;
973 }
974
975 int evaluate_data_proc(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
976 {
977 uint8_t I, op, S, Rn, Rd;
978 char *mnemonic = NULL;
979 char shifter_operand[32];
980
981 I = (opcode & 0x02000000) >> 25;
982 op = (opcode & 0x01e00000) >> 21;
983 S = (opcode & 0x00100000) >> 20;
984
985 Rd = (opcode & 0xf000) >> 12;
986 Rn = (opcode & 0xf0000) >> 16;
987
988 instruction->info.data_proc.Rd = Rd;
989 instruction->info.data_proc.Rn = Rn;
990 instruction->info.data_proc.S = S;
991
992 switch (op)
993 {
994 case 0x0:
995 instruction->type = ARM_AND;
996 mnemonic = "AND";
997 break;
998 case 0x1:
999 instruction->type = ARM_EOR;
1000 mnemonic = "EOR";
1001 break;
1002 case 0x2:
1003 instruction->type = ARM_SUB;
1004 mnemonic = "SUB";
1005 break;
1006 case 0x3:
1007 instruction->type = ARM_RSB;
1008 mnemonic = "RSB";
1009 break;
1010 case 0x4:
1011 instruction->type = ARM_ADD;
1012 mnemonic = "ADD";
1013 break;
1014 case 0x5:
1015 instruction->type = ARM_ADC;
1016 mnemonic = "ADC";
1017 break;
1018 case 0x6:
1019 instruction->type = ARM_SBC;
1020 mnemonic = "SBC";
1021 break;
1022 case 0x7:
1023 instruction->type = ARM_RSC;
1024 mnemonic = "RSC";
1025 break;
1026 case 0x8:
1027 instruction->type = ARM_TST;
1028 mnemonic = "TST";
1029 break;
1030 case 0x9:
1031 instruction->type = ARM_TEQ;
1032 mnemonic = "TEQ";
1033 break;
1034 case 0xa:
1035 instruction->type = ARM_CMP;
1036 mnemonic = "CMP";
1037 break;
1038 case 0xb:
1039 instruction->type = ARM_CMN;
1040 mnemonic = "CMN";
1041 break;
1042 case 0xc:
1043 instruction->type = ARM_ORR;
1044 mnemonic = "ORR";
1045 break;
1046 case 0xd:
1047 instruction->type = ARM_MOV;
1048 mnemonic = "MOV";
1049 break;
1050 case 0xe:
1051 instruction->type = ARM_BIC;
1052 mnemonic = "BIC";
1053 break;
1054 case 0xf:
1055 instruction->type = ARM_MVN;
1056 mnemonic = "MVN";
1057 break;
1058 }
1059
1060 if (I) /* immediate shifter operand (#<immediate>)*/
1061 {
1062 uint8_t immed_8 = opcode & 0xff;
1063 uint8_t rotate_imm = (opcode & 0xf00) >> 8;
1064 uint32_t immediate;
1065
1066 immediate = ror(immed_8, rotate_imm * 2);
1067
1068 snprintf(shifter_operand, 32, "#0x%" PRIx32 "", immediate);
1069
1070 instruction->info.data_proc.variant = 0;
1071 instruction->info.data_proc.shifter_operand.immediate.immediate = immediate;
1072 }
1073 else /* register-based shifter operand */
1074 {
1075 uint8_t shift, Rm;
1076 shift = (opcode & 0x60) >> 5;
1077 Rm = (opcode & 0xf);
1078
1079 if ((opcode & 0x10) != 0x10) /* Immediate shifts ("<Rm>" or "<Rm>, <shift> #<shift_immediate>") */
1080 {
1081 uint8_t shift_imm;
1082 shift_imm = (opcode & 0xf80) >> 7;
1083
1084 instruction->info.data_proc.variant = 1;
1085 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1086 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = shift_imm;
1087 instruction->info.data_proc.shifter_operand.immediate_shift.shift = shift;
1088
1089 /* LSR encodes a shift by 32 bit as 0x0 */
1090 if ((shift == 0x1) && (shift_imm == 0x0))
1091 shift_imm = 0x20;
1092
1093 /* ASR encodes a shift by 32 bit as 0x0 */
1094 if ((shift == 0x2) && (shift_imm == 0x0))
1095 shift_imm = 0x20;
1096
1097 /* ROR by 32 bit is actually a RRX */
1098 if ((shift == 0x3) && (shift_imm == 0x0))
1099 shift = 0x4;
1100
1101 if ((shift_imm == 0x0) && (shift == 0x0))
1102 {
1103 snprintf(shifter_operand, 32, "r%i", Rm);
1104 }
1105 else
1106 {
1107 if (shift == 0x0) /* LSL */
1108 {
1109 snprintf(shifter_operand, 32, "r%i, LSL #0x%x", Rm, shift_imm);
1110 }
1111 else if (shift == 0x1) /* LSR */
1112 {
1113 snprintf(shifter_operand, 32, "r%i, LSR #0x%x", Rm, shift_imm);
1114 }
1115 else if (shift == 0x2) /* ASR */
1116 {
1117 snprintf(shifter_operand, 32, "r%i, ASR #0x%x", Rm, shift_imm);
1118 }
1119 else if (shift == 0x3) /* ROR */
1120 {
1121 snprintf(shifter_operand, 32, "r%i, ROR #0x%x", Rm, shift_imm);
1122 }
1123 else if (shift == 0x4) /* RRX */
1124 {
1125 snprintf(shifter_operand, 32, "r%i, RRX", Rm);
1126 }
1127 }
1128 }
1129 else /* Register shifts ("<Rm>, <shift> <Rs>") */
1130 {
1131 uint8_t Rs = (opcode & 0xf00) >> 8;
1132
1133 instruction->info.data_proc.variant = 2;
1134 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rm;
1135 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rs;
1136 instruction->info.data_proc.shifter_operand.register_shift.shift = shift;
1137
1138 if (shift == 0x0) /* LSL */
1139 {
1140 snprintf(shifter_operand, 32, "r%i, LSL r%i", Rm, Rs);
1141 }
1142 else if (shift == 0x1) /* LSR */
1143 {
1144 snprintf(shifter_operand, 32, "r%i, LSR r%i", Rm, Rs);
1145 }
1146 else if (shift == 0x2) /* ASR */
1147 {
1148 snprintf(shifter_operand, 32, "r%i, ASR r%i", Rm, Rs);
1149 }
1150 else if (shift == 0x3) /* ROR */
1151 {
1152 snprintf(shifter_operand, 32, "r%i, ROR r%i", Rm, Rs);
1153 }
1154 }
1155 }
1156
1157 if ((op < 0x8) || (op == 0xc) || (op == 0xe)) /* <opcode3>{<cond>}{S} <Rd>, <Rn>, <shifter_operand> */
1158 {
1159 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, %s",
1160 address, opcode, mnemonic, COND(opcode),
1161 (S) ? "S" : "", Rd, Rn, shifter_operand);
1162 }
1163 else if ((op == 0xd) || (op == 0xf)) /* <opcode1>{<cond>}{S} <Rd>, <shifter_operand> */
1164 {
1165 if (opcode == 0xe1a00000) /* print MOV r0,r0 as NOP */
1166 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tNOP",address, opcode);
1167 else
1168 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, %s",
1169 address, opcode, mnemonic, COND(opcode),
1170 (S) ? "S" : "", Rd, shifter_operand);
1171 }
1172 else /* <opcode2>{<cond>} <Rn>, <shifter_operand> */
1173 {
1174 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, %s",
1175 address, opcode, mnemonic, COND(opcode),
1176 Rn, shifter_operand);
1177 }
1178
1179 return ERROR_OK;
1180 }
1181
1182 int arm_evaluate_opcode(uint32_t opcode, uint32_t address, arm_instruction_t *instruction)
1183 {
1184 /* clear fields, to avoid confusion */
1185 memset(instruction, 0, sizeof(arm_instruction_t));
1186 instruction->opcode = opcode;
1187 instruction->instruction_size = 4;
1188
1189 /* catch opcodes with condition field [31:28] = b1111 */
1190 if ((opcode & 0xf0000000) == 0xf0000000)
1191 {
1192 /* Undefined instruction (or ARMv5E cache preload PLD) */
1193 if ((opcode & 0x08000000) == 0x00000000)
1194 return evaluate_pld(opcode, address, instruction);
1195
1196 /* Undefined instruction */
1197 if ((opcode & 0x0e000000) == 0x08000000)
1198 {
1199 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1200 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1201 return ERROR_OK;
1202 }
1203
1204 /* Branch and branch with link and change to Thumb */
1205 if ((opcode & 0x0e000000) == 0x0a000000)
1206 return evaluate_blx_imm(opcode, address, instruction);
1207
1208 /* Extended coprocessor opcode space (ARMv5 and higher)*/
1209 /* Coprocessor load/store and double register transfers */
1210 if ((opcode & 0x0e000000) == 0x0c000000)
1211 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1212
1213 /* Coprocessor data processing */
1214 if ((opcode & 0x0f000100) == 0x0c000000)
1215 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1216
1217 /* Coprocessor register transfers */
1218 if ((opcode & 0x0f000010) == 0x0c000010)
1219 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1220
1221 /* Undefined instruction */
1222 if ((opcode & 0x0f000000) == 0x0f000000)
1223 {
1224 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1225 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1226 return ERROR_OK;
1227 }
1228 }
1229
1230 /* catch opcodes with [27:25] = b000 */
1231 if ((opcode & 0x0e000000) == 0x00000000)
1232 {
1233 /* Multiplies, extra load/stores */
1234 if ((opcode & 0x00000090) == 0x00000090)
1235 return evaluate_mul_and_extra_ld_st(opcode, address, instruction);
1236
1237 /* Miscellaneous instructions */
1238 if ((opcode & 0x0f900000) == 0x01000000)
1239 return evaluate_misc_instr(opcode, address, instruction);
1240
1241 return evaluate_data_proc(opcode, address, instruction);
1242 }
1243
1244 /* catch opcodes with [27:25] = b001 */
1245 if ((opcode & 0x0e000000) == 0x02000000)
1246 {
1247 /* Undefined instruction */
1248 if ((opcode & 0x0fb00000) == 0x03000000)
1249 {
1250 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1251 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1252 return ERROR_OK;
1253 }
1254
1255 /* Move immediate to status register */
1256 if ((opcode & 0x0fb00000) == 0x03200000)
1257 return evaluate_mrs_msr(opcode, address, instruction);
1258
1259 return evaluate_data_proc(opcode, address, instruction);
1260
1261 }
1262
1263 /* catch opcodes with [27:25] = b010 */
1264 if ((opcode & 0x0e000000) == 0x04000000)
1265 {
1266 /* Load/store immediate offset */
1267 return evaluate_load_store(opcode, address, instruction);
1268 }
1269
1270 /* catch opcodes with [27:25] = b011 */
1271 if ((opcode & 0x0e000000) == 0x06000000)
1272 {
1273 /* Undefined instruction */
1274 if ((opcode & 0x00000010) == 0x00000010)
1275 {
1276 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1277 snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION", address, opcode);
1278 return ERROR_OK;
1279 }
1280
1281 /* Load/store register offset */
1282 return evaluate_load_store(opcode, address, instruction);
1283
1284 }
1285
1286 /* catch opcodes with [27:25] = b100 */
1287 if ((opcode & 0x0e000000) == 0x08000000)
1288 {
1289 /* Load/store multiple */
1290 return evaluate_ldm_stm(opcode, address, instruction);
1291 }
1292
1293 /* catch opcodes with [27:25] = b101 */
1294 if ((opcode & 0x0e000000) == 0x0a000000)
1295 {
1296 /* Branch and branch with link */
1297 return evaluate_b_bl(opcode, address, instruction);
1298 }
1299
1300 /* catch opcodes with [27:25] = b110 */
1301 if ((opcode & 0x0e000000) == 0x0a000000)
1302 {
1303 /* Coprocessor load/store and double register transfers */
1304 return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1305 }
1306
1307 /* catch opcodes with [27:25] = b111 */
1308 if ((opcode & 0x0e000000) == 0x0e000000)
1309 {
1310 /* Software interrupt */
1311 if ((opcode & 0x0f000000) == 0x0f000000)
1312 return evaluate_swi(opcode, address, instruction);
1313
1314 /* Coprocessor data processing */
1315 if ((opcode & 0x0f000010) == 0x0e000000)
1316 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1317
1318 /* Coprocessor register transfers */
1319 if ((opcode & 0x0f000010) == 0x0e000010)
1320 return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1321 }
1322
1323 LOG_ERROR("should never reach this point");
1324 return -1;
1325 }
1326
1327 int evaluate_b_bl_blx_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1328 {
1329 uint32_t offset = opcode & 0x7ff;
1330 uint32_t opc = (opcode >> 11) & 0x3;
1331 uint32_t target_address;
1332 char *mnemonic = NULL;
1333
1334 /* sign extend 11-bit offset */
1335 if (((opc == 0) || (opc == 2)) && (offset & 0x00000400))
1336 offset = 0xfffff800 | offset;
1337
1338 target_address = address + 4 + (offset << 1);
1339
1340 switch (opc)
1341 {
1342 /* unconditional branch */
1343 case 0:
1344 instruction->type = ARM_B;
1345 mnemonic = "B";
1346 break;
1347 /* BLX suffix */
1348 case 1:
1349 instruction->type = ARM_BLX;
1350 mnemonic = "BLX";
1351 break;
1352 /* BL/BLX prefix */
1353 case 2:
1354 instruction->type = ARM_UNKNOWN_INSTUCTION;
1355 mnemonic = "prefix";
1356 target_address = offset << 12;
1357 break;
1358 /* BL suffix */
1359 case 3:
1360 instruction->type = ARM_BL;
1361 mnemonic = "BL";
1362 break;
1363 }
1364
1365 /* TODO: deal correctly with dual opcode (prefixed) BL/BLX;
1366 * these are effectively 32-bit instructions even in Thumb1.
1367 * Might be simplest to always use the Thumb2 decoder.
1368 */
1369
1370 snprintf(instruction->text, 128,
1371 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%#8.8" PRIx32,
1372 address, opcode, mnemonic, target_address);
1373
1374 instruction->info.b_bl_bx_blx.reg_operand = -1;
1375 instruction->info.b_bl_bx_blx.target_address = target_address;
1376
1377 return ERROR_OK;
1378 }
1379
1380 int evaluate_add_sub_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1381 {
1382 uint8_t Rd = (opcode >> 0) & 0x7;
1383 uint8_t Rn = (opcode >> 3) & 0x7;
1384 uint8_t Rm_imm = (opcode >> 6) & 0x7;
1385 uint32_t opc = opcode & (1 << 9);
1386 uint32_t reg_imm = opcode & (1 << 10);
1387 char *mnemonic;
1388
1389 if (opc)
1390 {
1391 instruction->type = ARM_SUB;
1392 mnemonic = "SUBS";
1393 }
1394 else
1395 {
1396 instruction->type = ARM_ADD;
1397 mnemonic = "ADDS";
1398 }
1399
1400 instruction->info.data_proc.Rd = Rd;
1401 instruction->info.data_proc.Rn = Rn;
1402 instruction->info.data_proc.S = 1;
1403
1404 if (reg_imm)
1405 {
1406 instruction->info.data_proc.variant = 0; /*immediate*/
1407 instruction->info.data_proc.shifter_operand.immediate.immediate = Rm_imm;
1408 snprintf(instruction->text, 128,
1409 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%d",
1410 address, opcode, mnemonic, Rd, Rn, Rm_imm);
1411 }
1412 else
1413 {
1414 instruction->info.data_proc.variant = 1; /*immediate shift*/
1415 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm_imm;
1416 snprintf(instruction->text, 128,
1417 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, r%i",
1418 address, opcode, mnemonic, Rd, Rn, Rm_imm);
1419 }
1420
1421 return ERROR_OK;
1422 }
1423
1424 int evaluate_shift_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1425 {
1426 uint8_t Rd = (opcode >> 0) & 0x7;
1427 uint8_t Rm = (opcode >> 3) & 0x7;
1428 uint8_t imm = (opcode >> 6) & 0x1f;
1429 uint8_t opc = (opcode >> 11) & 0x3;
1430 char *mnemonic = NULL;
1431
1432 switch (opc)
1433 {
1434 case 0:
1435 instruction->type = ARM_MOV;
1436 mnemonic = "LSLS";
1437 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 0;
1438 break;
1439 case 1:
1440 instruction->type = ARM_MOV;
1441 mnemonic = "LSRS";
1442 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 1;
1443 break;
1444 case 2:
1445 instruction->type = ARM_MOV;
1446 mnemonic = "ASRS";
1447 instruction->info.data_proc.shifter_operand.immediate_shift.shift = 2;
1448 break;
1449 }
1450
1451 if ((imm == 0) && (opc != 0))
1452 imm = 32;
1453
1454 instruction->info.data_proc.Rd = Rd;
1455 instruction->info.data_proc.Rn = -1;
1456 instruction->info.data_proc.S = 1;
1457
1458 instruction->info.data_proc.variant = 1; /*immediate_shift*/
1459 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1460 instruction->info.data_proc.shifter_operand.immediate_shift.shift_imm = imm;
1461
1462 snprintf(instruction->text, 128,
1463 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%#2.2x" ,
1464 address, opcode, mnemonic, Rd, Rm, imm);
1465
1466 return ERROR_OK;
1467 }
1468
1469 int evaluate_data_proc_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1470 {
1471 uint8_t imm = opcode & 0xff;
1472 uint8_t Rd = (opcode >> 8) & 0x7;
1473 uint32_t opc = (opcode >> 11) & 0x3;
1474 char *mnemonic = NULL;
1475
1476 instruction->info.data_proc.Rd = Rd;
1477 instruction->info.data_proc.Rn = Rd;
1478 instruction->info.data_proc.S = 1;
1479 instruction->info.data_proc.variant = 0; /*immediate*/
1480 instruction->info.data_proc.shifter_operand.immediate.immediate = imm;
1481
1482 switch (opc)
1483 {
1484 case 0:
1485 instruction->type = ARM_MOV;
1486 mnemonic = "MOVS";
1487 instruction->info.data_proc.Rn = -1;
1488 break;
1489 case 1:
1490 instruction->type = ARM_CMP;
1491 mnemonic = "CMP";
1492 instruction->info.data_proc.Rd = -1;
1493 break;
1494 case 2:
1495 instruction->type = ARM_ADD;
1496 mnemonic = "ADDS";
1497 break;
1498 case 3:
1499 instruction->type = ARM_SUB;
1500 mnemonic = "SUBS";
1501 break;
1502 }
1503
1504 snprintf(instruction->text, 128,
1505 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, #%#2.2x",
1506 address, opcode, mnemonic, Rd, imm);
1507
1508 return ERROR_OK;
1509 }
1510
1511 int evaluate_data_proc_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1512 {
1513 uint8_t high_reg, op, Rm, Rd,H1,H2;
1514 char *mnemonic = NULL;
1515
1516 high_reg = (opcode & 0x0400) >> 10;
1517 op = (opcode & 0x03C0) >> 6;
1518
1519 Rd = (opcode & 0x0007);
1520 Rm = (opcode & 0x0038) >> 3;
1521 H1 = (opcode & 0x0080) >> 7;
1522 H2 = (opcode & 0x0040) >> 6;
1523
1524 instruction->info.data_proc.Rd = Rd;
1525 instruction->info.data_proc.Rn = Rd;
1526 instruction->info.data_proc.S = (!high_reg || (instruction->type == ARM_CMP));
1527 instruction->info.data_proc.variant = 1 /*immediate shift*/;
1528 instruction->info.data_proc.shifter_operand.immediate_shift.Rm = Rm;
1529
1530 if (high_reg)
1531 {
1532 Rd |= H1 << 3;
1533 Rm |= H2 << 3;
1534 op >>= 2;
1535
1536 switch (op)
1537 {
1538 case 0x0:
1539 instruction->type = ARM_ADD;
1540 mnemonic = "ADD";
1541 break;
1542 case 0x1:
1543 instruction->type = ARM_CMP;
1544 mnemonic = "CMP";
1545 break;
1546 case 0x2:
1547 instruction->type = ARM_MOV;
1548 mnemonic = "MOV";
1549 break;
1550 case 0x3:
1551 if ((opcode & 0x7) == 0x0)
1552 {
1553 instruction->info.b_bl_bx_blx.reg_operand = Rm;
1554 if (H1)
1555 {
1556 instruction->type = ARM_BLX;
1557 snprintf(instruction->text, 128,
1558 "0x%8.8" PRIx32
1559 " 0x%4.4x \tBLX\tr%i",
1560 address, opcode, Rm);
1561 }
1562 else
1563 {
1564 instruction->type = ARM_BX;
1565 snprintf(instruction->text, 128,
1566 "0x%8.8" PRIx32
1567 " 0x%4.4x \tBX\tr%i",
1568 address, opcode, Rm);
1569 }
1570 }
1571 else
1572 {
1573 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1574 snprintf(instruction->text, 128,
1575 "0x%8.8" PRIx32
1576 " 0x%4.4x \t"
1577 "UNDEFINED INSTRUCTION",
1578 address, opcode);
1579 }
1580 return ERROR_OK;
1581 break;
1582 }
1583 }
1584 else
1585 {
1586 switch (op)
1587 {
1588 case 0x0:
1589 instruction->type = ARM_AND;
1590 mnemonic = "ANDS";
1591 break;
1592 case 0x1:
1593 instruction->type = ARM_EOR;
1594 mnemonic = "EORS";
1595 break;
1596 case 0x2:
1597 instruction->type = ARM_MOV;
1598 mnemonic = "LSLS";
1599 instruction->info.data_proc.variant = 2 /*register shift*/;
1600 instruction->info.data_proc.shifter_operand.register_shift.shift = 0;
1601 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1602 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1603 break;
1604 case 0x3:
1605 instruction->type = ARM_MOV;
1606 mnemonic = "LSRS";
1607 instruction->info.data_proc.variant = 2 /*register shift*/;
1608 instruction->info.data_proc.shifter_operand.register_shift.shift = 1;
1609 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1610 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1611 break;
1612 case 0x4:
1613 instruction->type = ARM_MOV;
1614 mnemonic = "ASRS";
1615 instruction->info.data_proc.variant = 2 /*register shift*/;
1616 instruction->info.data_proc.shifter_operand.register_shift.shift = 2;
1617 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1618 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1619 break;
1620 case 0x5:
1621 instruction->type = ARM_ADC;
1622 mnemonic = "ADCS";
1623 break;
1624 case 0x6:
1625 instruction->type = ARM_SBC;
1626 mnemonic = "SBCS";
1627 break;
1628 case 0x7:
1629 instruction->type = ARM_MOV;
1630 mnemonic = "RORS";
1631 instruction->info.data_proc.variant = 2 /*register shift*/;
1632 instruction->info.data_proc.shifter_operand.register_shift.shift = 3;
1633 instruction->info.data_proc.shifter_operand.register_shift.Rm = Rd;
1634 instruction->info.data_proc.shifter_operand.register_shift.Rs = Rm;
1635 break;
1636 case 0x8:
1637 instruction->type = ARM_TST;
1638 mnemonic = "TST";
1639 break;
1640 case 0x9:
1641 instruction->type = ARM_RSB;
1642 mnemonic = "NEGS";
1643 instruction->info.data_proc.variant = 0 /*immediate*/;
1644 instruction->info.data_proc.shifter_operand.immediate.immediate = 0;
1645 instruction->info.data_proc.Rn = Rm;
1646 break;
1647 case 0xA:
1648 instruction->type = ARM_CMP;
1649 mnemonic = "CMP";
1650 break;
1651 case 0xB:
1652 instruction->type = ARM_CMN;
1653 mnemonic = "CMN";
1654 break;
1655 case 0xC:
1656 instruction->type = ARM_ORR;
1657 mnemonic = "ORRS";
1658 break;
1659 case 0xD:
1660 instruction->type = ARM_MUL;
1661 mnemonic = "MULS";
1662 break;
1663 case 0xE:
1664 instruction->type = ARM_BIC;
1665 mnemonic = "BICS";
1666 break;
1667 case 0xF:
1668 instruction->type = ARM_MVN;
1669 mnemonic = "MVNS";
1670 break;
1671 }
1672 }
1673
1674 snprintf(instruction->text, 128,
1675 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i",
1676 address, opcode, mnemonic, Rd, Rm);
1677
1678 return ERROR_OK;
1679 }
1680
1681 int evaluate_load_literal_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1682 {
1683 uint32_t immediate;
1684 uint8_t Rd = (opcode >> 8) & 0x7;
1685
1686 instruction->type = ARM_LDR;
1687 immediate = opcode & 0x000000ff;
1688
1689 snprintf(instruction->text, 128,
1690 "0x%8.8" PRIx32 " 0x%4.4x \tLDR\tr%i, [pc, #%#" PRIx32 "]",
1691 address, opcode, Rd, immediate*4);
1692
1693 instruction->info.load_store.Rd = Rd;
1694 instruction->info.load_store.Rn = 15 /*PC*/;
1695 instruction->info.load_store.index_mode = 0; /*offset*/
1696 instruction->info.load_store.offset_mode = 0; /*immediate*/
1697 instruction->info.load_store.offset.offset = immediate*4;
1698
1699 return ERROR_OK;
1700 }
1701
1702 int evaluate_load_store_reg_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1703 {
1704 uint8_t Rd = (opcode >> 0) & 0x7;
1705 uint8_t Rn = (opcode >> 3) & 0x7;
1706 uint8_t Rm = (opcode >> 6) & 0x7;
1707 uint8_t opc = (opcode >> 9) & 0x7;
1708 char *mnemonic = NULL;
1709
1710 switch (opc)
1711 {
1712 case 0:
1713 instruction->type = ARM_STR;
1714 mnemonic = "STR";
1715 break;
1716 case 1:
1717 instruction->type = ARM_STRH;
1718 mnemonic = "STRH";
1719 break;
1720 case 2:
1721 instruction->type = ARM_STRB;
1722 mnemonic = "STRB";
1723 break;
1724 case 3:
1725 instruction->type = ARM_LDRSB;
1726 mnemonic = "LDRSB";
1727 break;
1728 case 4:
1729 instruction->type = ARM_LDR;
1730 mnemonic = "LDR";
1731 break;
1732 case 5:
1733 instruction->type = ARM_LDRH;
1734 mnemonic = "LDRH";
1735 break;
1736 case 6:
1737 instruction->type = ARM_LDRB;
1738 mnemonic = "LDRB";
1739 break;
1740 case 7:
1741 instruction->type = ARM_LDRSH;
1742 mnemonic = "LDRSH";
1743 break;
1744 }
1745
1746 snprintf(instruction->text, 128,
1747 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [r%i, r%i]",
1748 address, opcode, mnemonic, Rd, Rn, Rm);
1749
1750 instruction->info.load_store.Rd = Rd;
1751 instruction->info.load_store.Rn = Rn;
1752 instruction->info.load_store.index_mode = 0; /*offset*/
1753 instruction->info.load_store.offset_mode = 1; /*register*/
1754 instruction->info.load_store.offset.reg.Rm = Rm;
1755
1756 return ERROR_OK;
1757 }
1758
1759 int evaluate_load_store_imm_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1760 {
1761 uint32_t offset = (opcode >> 6) & 0x1f;
1762 uint8_t Rd = (opcode >> 0) & 0x7;
1763 uint8_t Rn = (opcode >> 3) & 0x7;
1764 uint32_t L = opcode & (1 << 11);
1765 uint32_t B = opcode & (1 << 12);
1766 char *mnemonic;
1767 char suffix = ' ';
1768 uint32_t shift = 2;
1769
1770 if (L)
1771 {
1772 instruction->type = ARM_LDR;
1773 mnemonic = "LDR";
1774 }
1775 else
1776 {
1777 instruction->type = ARM_STR;
1778 mnemonic = "STR";
1779 }
1780
1781 if ((opcode&0xF000) == 0x8000)
1782 {
1783 suffix = 'H';
1784 shift = 1;
1785 }
1786 else if (B)
1787 {
1788 suffix = 'B';
1789 shift = 0;
1790 }
1791
1792 snprintf(instruction->text, 128,
1793 "0x%8.8" PRIx32 " 0x%4.4x \t%s%c\tr%i, [r%i, #%#" PRIx32 "]",
1794 address, opcode, mnemonic, suffix, Rd, Rn, offset << shift);
1795
1796 instruction->info.load_store.Rd = Rd;
1797 instruction->info.load_store.Rn = Rn;
1798 instruction->info.load_store.index_mode = 0; /*offset*/
1799 instruction->info.load_store.offset_mode = 0; /*immediate*/
1800 instruction->info.load_store.offset.offset = offset << shift;
1801
1802 return ERROR_OK;
1803 }
1804
1805 int evaluate_load_store_stack_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1806 {
1807 uint32_t offset = opcode & 0xff;
1808 uint8_t Rd = (opcode >> 8) & 0x7;
1809 uint32_t L = opcode & (1 << 11);
1810 char *mnemonic;
1811
1812 if (L)
1813 {
1814 instruction->type = ARM_LDR;
1815 mnemonic = "LDR";
1816 }
1817 else
1818 {
1819 instruction->type = ARM_STR;
1820 mnemonic = "STR";
1821 }
1822
1823 snprintf(instruction->text, 128,
1824 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [SP, #%#" PRIx32 "]",
1825 address, opcode, mnemonic, Rd, offset*4);
1826
1827 instruction->info.load_store.Rd = Rd;
1828 instruction->info.load_store.Rn = 13 /*SP*/;
1829 instruction->info.load_store.index_mode = 0; /*offset*/
1830 instruction->info.load_store.offset_mode = 0; /*immediate*/
1831 instruction->info.load_store.offset.offset = offset*4;
1832
1833 return ERROR_OK;
1834 }
1835
1836 int evaluate_add_sp_pc_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1837 {
1838 uint32_t imm = opcode & 0xff;
1839 uint8_t Rd = (opcode >> 8) & 0x7;
1840 uint8_t Rn;
1841 uint32_t SP = opcode & (1 << 11);
1842 char *reg_name;
1843
1844 instruction->type = ARM_ADD;
1845
1846 if (SP)
1847 {
1848 reg_name = "SP";
1849 Rn = 13;
1850 }
1851 else
1852 {
1853 reg_name = "PC";
1854 Rn = 15;
1855 }
1856
1857 snprintf(instruction->text, 128,
1858 "0x%8.8" PRIx32 " 0x%4.4x \tADD\tr%i, %s, #%#" PRIx32,
1859 address, opcode, Rd, reg_name, imm * 4);
1860
1861 instruction->info.data_proc.variant = 0 /* immediate */;
1862 instruction->info.data_proc.Rd = Rd;
1863 instruction->info.data_proc.Rn = Rn;
1864 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
1865
1866 return ERROR_OK;
1867 }
1868
1869 int evaluate_adjust_stack_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1870 {
1871 uint32_t imm = opcode & 0x7f;
1872 uint8_t opc = opcode & (1 << 7);
1873 char *mnemonic;
1874
1875
1876 if (opc)
1877 {
1878 instruction->type = ARM_SUB;
1879 mnemonic = "SUB";
1880 }
1881 else
1882 {
1883 instruction->type = ARM_ADD;
1884 mnemonic = "ADD";
1885 }
1886
1887 snprintf(instruction->text, 128,
1888 "0x%8.8" PRIx32 " 0x%4.4x \t%s\tSP, #%#" PRIx32,
1889 address, opcode, mnemonic, imm*4);
1890
1891 instruction->info.data_proc.variant = 0 /* immediate */;
1892 instruction->info.data_proc.Rd = 13 /*SP*/;
1893 instruction->info.data_proc.Rn = 13 /*SP*/;
1894 instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
1895
1896 return ERROR_OK;
1897 }
1898
1899 int evaluate_breakpoint_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1900 {
1901 uint32_t imm = opcode & 0xff;
1902
1903 instruction->type = ARM_BKPT;
1904
1905 snprintf(instruction->text, 128,
1906 "0x%8.8" PRIx32 " 0x%4.4x \tBKPT\t%#2.2" PRIx32 "",
1907 address, opcode, imm);
1908
1909 return ERROR_OK;
1910 }
1911
1912 int evaluate_load_store_multiple_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1913 {
1914 uint32_t reg_list = opcode & 0xff;
1915 uint32_t L = opcode & (1 << 11);
1916 uint32_t R = opcode & (1 << 8);
1917 uint8_t Rn = (opcode >> 8) & 7;
1918 uint8_t addr_mode = 0 /* IA */;
1919 char reg_names[40];
1920 char *reg_names_p;
1921 char *mnemonic;
1922 char ptr_name[7] = "";
1923 int i;
1924
1925 if ((opcode & 0xf000) == 0xc000)
1926 { /* generic load/store multiple */
1927 if (L)
1928 {
1929 instruction->type = ARM_LDM;
1930 mnemonic = "LDM";
1931 }
1932 else
1933 {
1934 instruction->type = ARM_STM;
1935 mnemonic = "STM";
1936 }
1937 snprintf(ptr_name,7,"r%i!, ",Rn);
1938 }
1939 else
1940 { /* push/pop */
1941 Rn = 13; /* SP */
1942 if (L)
1943 {
1944 instruction->type = ARM_LDM;
1945 mnemonic = "POP";
1946 if (R)
1947 reg_list |= (1 << 15) /*PC*/;
1948 }
1949 else
1950 {
1951 instruction->type = ARM_STM;
1952 mnemonic = "PUSH";
1953 addr_mode = 3; /*DB*/
1954 if (R)
1955 reg_list |= (1 << 14) /*LR*/;
1956 }
1957 }
1958
1959 reg_names_p = reg_names;
1960 for (i = 0; i <= 15; i++)
1961 {
1962 if (reg_list & (1 << i))
1963 reg_names_p += snprintf(reg_names_p, (reg_names + 40 - reg_names_p), "r%i, ", i);
1964 }
1965 if (reg_names_p > reg_names)
1966 reg_names_p[-2] = '\0';
1967 else /* invalid op : no registers */
1968 reg_names[0] = '\0';
1969
1970 snprintf(instruction->text, 128,
1971 "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%s{%s}",
1972 address, opcode, mnemonic, ptr_name, reg_names);
1973
1974 instruction->info.load_store_multiple.register_list = reg_list;
1975 instruction->info.load_store_multiple.Rn = Rn;
1976 instruction->info.load_store_multiple.addressing_mode = addr_mode;
1977
1978 return ERROR_OK;
1979 }
1980
1981 int evaluate_cond_branch_thumb(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
1982 {
1983 uint32_t offset = opcode & 0xff;
1984 uint8_t cond = (opcode >> 8) & 0xf;
1985 uint32_t target_address;
1986
1987 if (cond == 0xf)
1988 {
1989 instruction->type = ARM_SWI;
1990 snprintf(instruction->text, 128,
1991 "0x%8.8" PRIx32 " 0x%4.4x \tSVC\t%#2.2" PRIx32,
1992 address, opcode, offset);
1993 return ERROR_OK;
1994 }
1995 else if (cond == 0xe)
1996 {
1997 instruction->type = ARM_UNDEFINED_INSTRUCTION;
1998 snprintf(instruction->text, 128,
1999 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2000 address, opcode);
2001 return ERROR_OK;
2002 }
2003
2004 /* sign extend 8-bit offset */
2005 if (offset & 0x00000080)
2006 offset = 0xffffff00 | offset;
2007
2008 target_address = address + 4 + (offset << 1);
2009
2010 snprintf(instruction->text, 128,
2011 "0x%8.8" PRIx32 " 0x%4.4x \tB%s\t%#8.8" PRIx32,
2012 address, opcode,
2013 arm_condition_strings[cond], target_address);
2014
2015 instruction->type = ARM_B;
2016 instruction->info.b_bl_bx_blx.reg_operand = -1;
2017 instruction->info.b_bl_bx_blx.target_address = target_address;
2018
2019 return ERROR_OK;
2020 }
2021
2022 static int evaluate_cb_thumb(uint16_t opcode, uint32_t address,
2023 arm_instruction_t *instruction)
2024 {
2025 unsigned offset;
2026
2027 /* added in Thumb2 */
2028 offset = (opcode >> 3) & 0x1f;
2029 offset |= (opcode & 0x0200) >> 4;
2030
2031 snprintf(instruction->text, 128,
2032 "0x%8.8" PRIx32 " 0x%4.4x \tCB%sZ\tr%d, %#8.8" PRIx32,
2033 address, opcode,
2034 (opcode & 0x0800) ? "N" : "",
2035 opcode & 0x7, address + 4 + (offset << 1));
2036
2037 return ERROR_OK;
2038 }
2039
2040 static int evaluate_extend_thumb(uint16_t opcode, uint32_t address,
2041 arm_instruction_t *instruction)
2042 {
2043 /* added in ARMv6 */
2044 snprintf(instruction->text, 128,
2045 "0x%8.8" PRIx32 " 0x%4.4x \t%cXT%c\tr%d, r%d",
2046 address, opcode,
2047 (opcode & 0x0080) ? 'U' : 'S',
2048 (opcode & 0x0040) ? 'B' : 'H',
2049 opcode & 0x7, (opcode >> 3) & 0x7);
2050
2051 return ERROR_OK;
2052 }
2053
2054 static int evaluate_cps_thumb(uint16_t opcode, uint32_t address,
2055 arm_instruction_t *instruction)
2056 {
2057 /* added in ARMv6 */
2058 if ((opcode & 0x0ff0) == 0x0650)
2059 snprintf(instruction->text, 128,
2060 "0x%8.8" PRIx32 " 0x%4.4x \tSETEND %s",
2061 address, opcode,
2062 (opcode & 0x80) ? "BE" : "LE");
2063 else /* ASSUME (opcode & 0x0fe0) == 0x0660 */
2064 snprintf(instruction->text, 128,
2065 "0x%8.8" PRIx32 " 0x%4.4x \tCPSI%c %s%s%s",
2066 address, opcode,
2067 (opcode & 0x0010) ? 'D' : 'E',
2068 (opcode & 0x0004) ? "A" : "",
2069 (opcode & 0x0002) ? "I" : "",
2070 (opcode & 0x0001) ? "F" : "");
2071
2072 return ERROR_OK;
2073 }
2074
2075 static int evaluate_byterev_thumb(uint16_t opcode, uint32_t address,
2076 arm_instruction_t *instruction)
2077 {
2078 char *suffix;
2079
2080 /* added in ARMv6 */
2081 switch (opcode & 0x00c0) {
2082 case 0:
2083 suffix = "";
2084 break;
2085 case 1:
2086 suffix = "16";
2087 break;
2088 default:
2089 suffix = "SH";
2090 break;
2091 }
2092 snprintf(instruction->text, 128,
2093 "0x%8.8" PRIx32 " 0x%4.4x \tREV%s\tr%d, r%d",
2094 address, opcode, suffix,
2095 opcode & 0x7, (opcode >> 3) & 0x7);
2096
2097 return ERROR_OK;
2098 }
2099
2100 static int evaluate_hint_thumb(uint16_t opcode, uint32_t address,
2101 arm_instruction_t *instruction)
2102 {
2103 char *hint;
2104
2105 switch ((opcode >> 4) & 0x0f) {
2106 case 0:
2107 hint = "NOP";
2108 break;
2109 case 1:
2110 hint = "YIELD";
2111 break;
2112 case 2:
2113 hint = "WFE";
2114 break;
2115 case 3:
2116 hint = "WFI";
2117 break;
2118 case 4:
2119 hint = "SEV";
2120 break;
2121 default:
2122 hint = "HINT (UNRECOGNIZED)";
2123 break;
2124 }
2125
2126 snprintf(instruction->text, 128,
2127 "0x%8.8" PRIx32 " 0x%4.4x \t%s",
2128 address, opcode, hint);
2129
2130 return ERROR_OK;
2131 }
2132
2133 static int evaluate_ifthen_thumb(uint16_t opcode, uint32_t address,
2134 arm_instruction_t *instruction)
2135 {
2136 unsigned cond = (opcode >> 4) & 0x0f;
2137 char *x = "", *y = "", *z = "";
2138
2139 if (opcode & 0x01)
2140 z = (opcode & 0x02) ? "T" : "E";
2141 if (opcode & 0x03)
2142 y = (opcode & 0x04) ? "T" : "E";
2143 if (opcode & 0x07)
2144 x = (opcode & 0x08) ? "T" : "E";
2145
2146 snprintf(instruction->text, 128,
2147 "0x%8.8" PRIx32 " 0x%4.4x \tIT%s%s%s\t%s",
2148 address, opcode,
2149 x, y, z, arm_condition_strings[cond]);
2150
2151 /* NOTE: strictly speaking, the next 1-4 instructions should
2152 * now be displayed with the relevant conditional suffix...
2153 */
2154
2155 return ERROR_OK;
2156 }
2157
2158 int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, arm_instruction_t *instruction)
2159 {
2160 /* clear fields, to avoid confusion */
2161 memset(instruction, 0, sizeof(arm_instruction_t));
2162 instruction->opcode = opcode;
2163 instruction->instruction_size = 2;
2164
2165 if ((opcode & 0xe000) == 0x0000)
2166 {
2167 /* add/substract register or immediate */
2168 if ((opcode & 0x1800) == 0x1800)
2169 return evaluate_add_sub_thumb(opcode, address, instruction);
2170 /* shift by immediate */
2171 else
2172 return evaluate_shift_imm_thumb(opcode, address, instruction);
2173 }
2174
2175 /* Add/substract/compare/move immediate */
2176 if ((opcode & 0xe000) == 0x2000)
2177 {
2178 return evaluate_data_proc_imm_thumb(opcode, address, instruction);
2179 }
2180
2181 /* Data processing instructions */
2182 if ((opcode & 0xf800) == 0x4000)
2183 {
2184 return evaluate_data_proc_thumb(opcode, address, instruction);
2185 }
2186
2187 /* Load from literal pool */
2188 if ((opcode & 0xf800) == 0x4800)
2189 {
2190 return evaluate_load_literal_thumb(opcode, address, instruction);
2191 }
2192
2193 /* Load/Store register offset */
2194 if ((opcode & 0xf000) == 0x5000)
2195 {
2196 return evaluate_load_store_reg_thumb(opcode, address, instruction);
2197 }
2198
2199 /* Load/Store immediate offset */
2200 if (((opcode & 0xe000) == 0x6000)
2201 ||((opcode & 0xf000) == 0x8000))
2202 {
2203 return evaluate_load_store_imm_thumb(opcode, address, instruction);
2204 }
2205
2206 /* Load/Store from/to stack */
2207 if ((opcode & 0xf000) == 0x9000)
2208 {
2209 return evaluate_load_store_stack_thumb(opcode, address, instruction);
2210 }
2211
2212 /* Add to SP/PC */
2213 if ((opcode & 0xf000) == 0xa000)
2214 {
2215 return evaluate_add_sp_pc_thumb(opcode, address, instruction);
2216 }
2217
2218 /* Misc */
2219 if ((opcode & 0xf000) == 0xb000)
2220 {
2221 switch ((opcode >> 8) & 0x0f) {
2222 case 0x0:
2223 return evaluate_adjust_stack_thumb(opcode, address, instruction);
2224 case 0x1:
2225 case 0x3:
2226 case 0x9:
2227 case 0xb:
2228 return evaluate_cb_thumb(opcode, address, instruction);
2229 case 0x2:
2230 return evaluate_extend_thumb(opcode, address, instruction);
2231 case 0x4:
2232 case 0x5:
2233 case 0xc:
2234 case 0xd:
2235 return evaluate_load_store_multiple_thumb(opcode, address,
2236 instruction);
2237 case 0x6:
2238 return evaluate_cps_thumb(opcode, address, instruction);
2239 case 0xa:
2240 if ((opcode & 0x00c0) == 0x0080)
2241 break;
2242 return evaluate_byterev_thumb(opcode, address, instruction);
2243 case 0xe:
2244 return evaluate_breakpoint_thumb(opcode, address, instruction);
2245 case 0xf:
2246 if (opcode & 0x000f)
2247 return evaluate_ifthen_thumb(opcode, address,
2248 instruction);
2249 else
2250 return evaluate_hint_thumb(opcode, address,
2251 instruction);
2252 }
2253
2254 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2255 snprintf(instruction->text, 128,
2256 "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2257 address, opcode);
2258 return ERROR_OK;
2259 }
2260
2261 /* Load/Store multiple */
2262 if ((opcode & 0xf000) == 0xc000)
2263 {
2264 return evaluate_load_store_multiple_thumb(opcode, address, instruction);
2265 }
2266
2267 /* Conditional branch + SWI */
2268 if ((opcode & 0xf000) == 0xd000)
2269 {
2270 return evaluate_cond_branch_thumb(opcode, address, instruction);
2271 }
2272
2273 if ((opcode & 0xe000) == 0xe000)
2274 {
2275 /* Undefined instructions */
2276 if ((opcode & 0xf801) == 0xe801)
2277 {
2278 instruction->type = ARM_UNDEFINED_INSTRUCTION;
2279 snprintf(instruction->text, 128,
2280 "0x%8.8" PRIx32 " 0x%8.8x\t"
2281 "UNDEFINED INSTRUCTION",
2282 address, opcode);
2283 return ERROR_OK;
2284 }
2285 else
2286 { /* Branch to offset */
2287 return evaluate_b_bl_blx_thumb(opcode, address, instruction);
2288 }
2289 }
2290
2291 LOG_ERROR("should never reach this point (opcode=%04x)",opcode);
2292 return -1;
2293 }
2294
2295 /*
2296 * REVISIT for Thumb2 instructions, instruction->type and friends aren't
2297 * always set. That means eventual arm_simulate_step() support for Thumb2
2298 * will need work in this area.
2299 */
2300 int thumb2_opcode(target_t *target, uint32_t address, arm_instruction_t *instruction)
2301 {
2302 int retval;
2303 uint16_t op;
2304 uint32_t opcode;
2305
2306 /* clear low bit ... it's set on function pointers */
2307 address &= ~1;
2308
2309 /* clear fields, to avoid confusion */
2310 memset(instruction, 0, sizeof(arm_instruction_t));
2311
2312 /* read first halfword, see if this is the only one */
2313 retval = target_read_u16(target, address, &op);
2314 if (retval != ERROR_OK)
2315 return retval;
2316
2317 switch (op & 0xf800) {
2318 case 0xf800:
2319 case 0xf000:
2320 case 0xe800:
2321 /* 32-bit instructions */
2322 instruction->instruction_size = 4;
2323 opcode = op << 16;
2324 retval = target_read_u16(target, address + 2, &op);
2325 if (retval != ERROR_OK)
2326 return retval;
2327 opcode |= op;
2328 instruction->opcode = opcode;
2329 break;
2330 default:
2331 /* 16-bit: Thumb1 + IT + CBZ/CBNZ + ... */
2332 return thumb_evaluate_opcode(op, address, instruction);
2333 }
2334
2335 /* FIXME decode the 32-bit instructions */
2336
2337 LOG_DEBUG("Can't decode 32-bit Thumb2 yet (opcode=%08x)", opcode);
2338
2339 snprintf(instruction->text, 128,
2340 "0x%8.8" PRIx32 " 0x%8.8x\t... 32-bit Thumb2 ...",
2341 address, opcode);
2342 return ERROR_OK;
2343 }
2344
2345 int arm_access_size(arm_instruction_t *instruction)
2346 {
2347 if ((instruction->type == ARM_LDRB)
2348 || (instruction->type == ARM_LDRBT)
2349 || (instruction->type == ARM_LDRSB)
2350 || (instruction->type == ARM_STRB)
2351 || (instruction->type == ARM_STRBT))
2352 {
2353 return 1;
2354 }
2355 else if ((instruction->type == ARM_LDRH)
2356 || (instruction->type == ARM_LDRSH)
2357 || (instruction->type == ARM_STRH))
2358 {
2359 return 2;
2360 }
2361 else if ((instruction->type == ARM_LDR)
2362 || (instruction->type == ARM_LDRT)
2363 || (instruction->type == ARM_STR)
2364 || (instruction->type == ARM_STRT))
2365 {
2366 return 4;
2367 }
2368 else if ((instruction->type == ARM_LDRD)
2369 || (instruction->type == ARM_STRD))
2370 {
2371 return 8;
2372 }
2373 else
2374 {
2375 LOG_ERROR("BUG: instruction type %i isn't a load/store instruction", instruction->type);
2376 return 0;
2377 }
2378 }

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)