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

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)