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

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)