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

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)