OpenOCD
arm_disassembler.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /***************************************************************************
4  * Copyright (C) 2006 by Dominic Rath *
5  * Dominic.Rath@gmx.de *
6  * *
7  * Copyright (C) 2009 by David Brownell *
8  ***************************************************************************/
9 
10 #ifdef HAVE_CONFIG_H
11 #include "config.h"
12 #endif
13 
14 #include "target.h"
15 #include "arm_disassembler.h"
16 #include <helper/log.h>
17 
18 /*
19  * This disassembler supports two main functions for OpenOCD:
20  *
21  * - Various "disassemble" commands. OpenOCD can serve as a
22  * machine-language debugger, without help from GDB.
23  *
24  * - Single stepping. Not all ARM cores support hardware single
25  * stepping. To work without that support, the debugger must
26  * be able to decode instructions to find out where to put a
27  * "next instruction" breakpoint.
28  *
29  * In addition, interpretation of ETM trace data needs some of the
30  * decoding mechanisms.
31  *
32  * At this writing (September 2009) neither function is complete.
33  *
34  * - ARM decoding
35  * * Old-style syntax (not UAL) is generally used
36  * * VFP instructions are not understood (ARMv5 and later)
37  * except as coprocessor 10/11 operations
38  * * Most ARM instructions through ARMv6 are decoded, but some
39  * of the post-ARMv4 opcodes may not be handled yet
40  * CPS, SDIV, UDIV, LDREX*, STREX*, QASX, ...
41  * * NEON instructions are not understood (ARMv7-A)
42  *
43  * - Thumb/Thumb2 decoding
44  * * UAL syntax should be consistently used
45  * * Any Thumb2 instructions used in Cortex-M3 (ARMv7-M) should
46  * be handled properly. Accordingly, so should the subset
47  * used in Cortex-M0/M1; and "original" 16-bit Thumb from
48  * ARMv4T and ARMv5T.
49  * * Conditional effects of Thumb2 "IT" (if-then) instructions
50  * are not handled: the affected instructions are not shown
51  * with their now-conditional suffixes.
52  * * Some ARMv6 and ARMv7-M Thumb2 instructions may not be
53  * handled (minimally for coprocessor access).
54  * * SIMD instructions, and some other Thumb2 instructions
55  * from ARMv7-A, are not understood.
56  *
57  * - ThumbEE decoding
58  * * As a Thumb2 variant, the Thumb2 comments (above) apply.
59  * * Opcodes changed by ThumbEE mode are not handled; these
60  * instructions wrongly decode as LDM and STM.
61  *
62  * - Jazelle decoding ... no support whatsoever for Jazelle mode
63  * or decoding. ARM encourages use of the more generic ThumbEE
64  * mode, instead of Jazelle mode, in current chips.
65  *
66  * - Single-step/emulation ... spotty support, which is only weakly
67  * tested. Thumb2 is not supported. (Arguably a full simulator
68  * is not needed to support just single stepping. Recognizing
69  * branch vs non-branch instructions suffices, except when the
70  * instruction faults and triggers a synchronous exception which
71  * can be intercepted using other means.)
72  *
73  * ARM DDI 0406B "ARM Architecture Reference Manual, ARM v7-A and
74  * ARM v7-R edition" gives the most complete coverage of the various
75  * generations of ARM instructions. At this writing it is publicly
76  * accessible to anyone willing to create an account at the ARM
77  * web site; see http://www.arm.com/documentation/ for information.
78  *
79  * ARM DDI 0403C "ARMv7-M Architecture Reference Manual" provides
80  * more details relevant to the Thumb2-only processors (such as
81  * the Cortex-M implementations).
82  */
83 
84 /* textual representation of the condition field
85  * ALways (default) is omitted (empty string) */
86 static const char *arm_condition_strings[] = {
87  "EQ", "NE", "CS", "CC", "MI", "PL", "VS", "VC", "HI", "LS", "GE", "LT", "GT", "LE", "", "NV"
88 };
89 
90 /* make up for C's missing ROR */
91 static uint32_t ror(uint32_t value, int places)
92 {
93  return (value >> places) | (value << (32 - places));
94 }
95 
96 static int evaluate_unknown(uint32_t opcode,
97  uint32_t address, struct arm_instruction *instruction)
98 {
99  instruction->type = ARM_UNDEFINED_INSTRUCTION;
100  snprintf(instruction->text, 128,
101  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
102  "\tUNDEFINED INSTRUCTION", address, opcode);
103  return ERROR_OK;
104 }
105 
106 static int evaluate_pld(uint32_t opcode,
107  uint32_t address, struct arm_instruction *instruction)
108 {
109  /* PLD */
110  if ((opcode & 0x0d30f000) == 0x0510f000) {
111  uint8_t rn;
112  uint8_t u;
113  unsigned int offset;
114 
115  instruction->type = ARM_PLD;
116  rn = (opcode & 0xf0000) >> 16;
117  u = (opcode & 0x00800000) >> 23;
118  if (rn == 0xf) {
119  /* literal */
120  offset = opcode & 0x0fff;
121  snprintf(instruction->text, 128,
122  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD %s%d",
123  address, opcode, u ? "" : "-", offset);
124  } else {
125  uint8_t i, r;
126 
127  i = (opcode & 0x02000000) >> 25;
128  r = (opcode & 0x00400000) >> 22;
129 
130  if (i) {
131  /* register PLD{W} [<Rn>,+/-<Rm>{, <shift>}] */
132  offset = (opcode & 0x0F80) >> 7;
133  uint8_t rm;
134  rm = opcode & 0xf;
135 
136  if (offset == 0) {
137  /* No shift */
138  snprintf(instruction->text, 128,
139  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d]",
140  address, opcode, r ? "" : "W", rn, u ? "" : "-", rm);
141 
142  } else {
143  uint8_t shift;
144  shift = (opcode & 0x60) >> 5;
145 
146  if (shift == 0x0) {
147  /* LSL */
148  snprintf(instruction->text, 128,
149  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d, LSL #0x%x)",
150  address, opcode, r ? "" : "W", rn, u ? "" : "-", rm, offset);
151  } else if (shift == 0x1) {
152  /* LSR */
153  snprintf(instruction->text, 128,
154  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d, LSR #0x%x)",
155  address, opcode, r ? "" : "W", rn, u ? "" : "-", rm, offset);
156  } else if (shift == 0x2) {
157  /* ASR */
158  snprintf(instruction->text, 128,
159  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d, ASR #0x%x)",
160  address, opcode, r ? "" : "W", rn, u ? "" : "-", rm, offset);
161  } else if (shift == 0x3) {
162  /* ROR */
163  snprintf(instruction->text, 128,
164  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, %sr%d, ROR #0x%x)",
165  address, opcode, r ? "" : "W", rn, u ? "" : "-", rm, offset);
166  }
167  }
168  } else {
169  /* immediate PLD{W} [<Rn>, #+/-<imm12>] */
170  offset = opcode & 0x0fff;
171  if (offset == 0) {
172  snprintf(instruction->text, 128,
173  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d]",
174  address, opcode, r ? "" : "W", rn);
175  } else {
176  snprintf(instruction->text, 128,
177  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tPLD%s [r%d, #%s%d]",
178  address, opcode, r ? "" : "W", rn, u ? "" : "-", offset);
179  }
180  }
181  }
182  return ERROR_OK;
183  }
184  /* DSB */
185  if ((opcode & 0x07f000f0) == 0x05700040) {
186  instruction->type = ARM_DSB;
187 
188  char *opt;
189  switch (opcode & 0x0000000f) {
190  case 0xf:
191  opt = "SY";
192  break;
193  case 0xe:
194  opt = "ST";
195  break;
196  case 0xb:
197  opt = "ISH";
198  break;
199  case 0xa:
200  opt = "ISHST";
201  break;
202  case 0x7:
203  opt = "NSH";
204  break;
205  case 0x6:
206  opt = "NSHST";
207  break;
208  case 0x3:
209  opt = "OSH";
210  break;
211  case 0x2:
212  opt = "OSHST";
213  break;
214  default:
215  opt = "UNK";
216  }
217 
218  snprintf(instruction->text,
219  128,
220  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tDSB %s",
221  address, opcode, opt);
222 
223  return ERROR_OK;
224  }
225  /* ISB */
226  if ((opcode & 0x07f000f0) == 0x05700060) {
227  instruction->type = ARM_ISB;
228 
229  snprintf(instruction->text,
230  128,
231  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tISB %s",
232  address, opcode,
233  ((opcode & 0x0000000f) == 0xf) ? "SY" : "UNK");
234 
235  return ERROR_OK;
236  }
237  return evaluate_unknown(opcode, address, instruction);
238 }
239 
240 static int evaluate_srs(uint32_t opcode,
241  uint32_t address, struct arm_instruction *instruction)
242 {
243  const char *wback = (opcode & (1 << 21)) ? "!" : "";
244  const char *mode = "";
245 
246  switch ((opcode >> 23) & 0x3) {
247  case 0:
248  mode = "DA";
249  break;
250  case 1:
251  /* "IA" is default */
252  break;
253  case 2:
254  mode = "DB";
255  break;
256  case 3:
257  mode = "IB";
258  break;
259  }
260 
261  switch (opcode & 0x0e500000) {
262  case 0x08400000:
263  snprintf(instruction->text, 128, "0x%8.8" PRIx32
264  "\t0x%8.8" PRIx32
265  "\tSRS%s\tSP%s, #%" PRIu32,
266  address, opcode,
267  mode, wback,
268  opcode & 0x1f);
269  break;
270  case 0x08100000:
271  snprintf(instruction->text, 128, "0x%8.8" PRIx32
272  "\t0x%8.8" PRIx32
273  "\tRFE%s\tr%" PRIu32 "%s",
274  address, opcode,
275  mode,
276  (opcode >> 16) & 0xf, wback);
277  break;
278  default:
279  return evaluate_unknown(opcode, address, instruction);
280  }
281  return ERROR_OK;
282 }
283 
284 static int evaluate_swi(uint32_t opcode,
285  uint32_t address, struct arm_instruction *instruction)
286 {
287  instruction->type = ARM_SWI;
288 
289  snprintf(instruction->text, 128,
290  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSVC %#6.6" PRIx32,
291  address, opcode, (opcode & 0xffffff));
292 
293  return ERROR_OK;
294 }
295 
296 static int evaluate_blx_imm(uint32_t opcode,
297  uint32_t address, struct arm_instruction *instruction)
298 {
299  int offset;
300  uint32_t immediate;
301  uint32_t target_address;
302 
303  instruction->type = ARM_BLX;
304  immediate = opcode & 0x00ffffff;
305 
306  /* sign extend 24-bit immediate */
307  if (immediate & 0x00800000)
308  offset = 0xff000000 | immediate;
309  else
310  offset = immediate;
311 
312  /* shift two bits left */
313  offset <<= 2;
314 
315  /* odd/event halfword */
316  if (opcode & 0x01000000)
317  offset |= 0x2;
318 
319  target_address = address + 8 + offset;
320 
321  snprintf(instruction->text,
322  128,
323  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX 0x%8.8" PRIx32,
324  address,
325  opcode,
326  target_address);
327 
328  instruction->info.b_bl_bx_blx.reg_operand = -1;
329  instruction->info.b_bl_bx_blx.target_address = target_address;
330 
331  return ERROR_OK;
332 }
333 
334 static int evaluate_b_bl(uint32_t opcode,
335  uint32_t address, struct arm_instruction *instruction)
336 {
337  uint8_t l;
338  uint32_t immediate;
339  int offset;
340  uint32_t target_address;
341 
342  immediate = opcode & 0x00ffffff;
343  l = (opcode & 0x01000000) >> 24;
344 
345  /* sign extend 24-bit immediate */
346  if (immediate & 0x00800000)
347  offset = 0xff000000 | immediate;
348  else
349  offset = immediate;
350 
351  /* shift two bits left */
352  offset <<= 2;
353 
354  target_address = address + 8 + offset;
355 
356  if (l)
357  instruction->type = ARM_BL;
358  else
359  instruction->type = ARM_B;
360 
361  snprintf(instruction->text,
362  128,
363  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tB%s%s 0x%8.8" PRIx32,
364  address,
365  opcode,
366  (l) ? "L" : "",
367  COND(opcode),
368  target_address);
369 
370  instruction->info.b_bl_bx_blx.reg_operand = -1;
371  instruction->info.b_bl_bx_blx.target_address = target_address;
372 
373  return ERROR_OK;
374 }
375 
376 /* Coprocessor load/store and double register transfers
377  * both normal and extended instruction space (condition field b1111) */
378 static int evaluate_ldc_stc_mcrr_mrrc(uint32_t opcode,
379  uint32_t address, struct arm_instruction *instruction)
380 {
381  uint8_t cp_num = (opcode & 0xf00) >> 8;
382 
383  /* MCRR or MRRC */
384  if (((opcode & 0x0ff00000) == 0x0c400000) || ((opcode & 0x0ff00000) == 0x0c500000)) {
385  uint8_t cp_opcode, rd, rn, crm;
386  char *mnemonic;
387 
388  cp_opcode = (opcode & 0xf0) >> 4;
389  rd = (opcode & 0xf000) >> 12;
390  rn = (opcode & 0xf0000) >> 16;
391  crm = (opcode & 0xf);
392 
393  /* MCRR */
394  if ((opcode & 0x0ff00000) == 0x0c400000) {
395  instruction->type = ARM_MCRR;
396  mnemonic = "MCRR";
397  } else if ((opcode & 0x0ff00000) == 0x0c500000) {
398  /* MRRC */
399  instruction->type = ARM_MRRC;
400  mnemonic = "MRRC";
401  } else {
402  LOG_ERROR("Unknown instruction");
403  return ERROR_FAIL;
404  }
405 
406  snprintf(instruction->text, 128,
407  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
408  "\t%s%s%s p%i, %x, r%i, r%i, c%i",
409  address, opcode, mnemonic,
410  ((opcode & 0xf0000000) == 0xf0000000)
411  ? "2" : COND(opcode),
412  COND(opcode), cp_num, cp_opcode, rd, rn, crm);
413  } else {/* LDC or STC */
414  uint8_t crd, rn, offset;
415  uint8_t u;
416  char *mnemonic;
417  char addressing_mode[32];
418 
419  crd = (opcode & 0xf000) >> 12;
420  rn = (opcode & 0xf0000) >> 16;
421  offset = (opcode & 0xff) << 2;
422 
423  /* load/store */
424  if (opcode & 0x00100000) {
425  instruction->type = ARM_LDC;
426  mnemonic = "LDC";
427  } else {
428  instruction->type = ARM_STC;
429  mnemonic = "STC";
430  }
431 
432  u = (opcode & 0x00800000) >> 23;
433 
434  /* addressing modes */
435  if ((opcode & 0x01200000) == 0x01000000)/* offset */
436  snprintf(addressing_mode, 32, "[r%i, #%s%d]",
437  rn, u ? "" : "-", offset);
438  else if ((opcode & 0x01200000) == 0x01200000) /* pre-indexed */
439  snprintf(addressing_mode, 32, "[r%i, #%s%d]!",
440  rn, u ? "" : "-", offset);
441  else if ((opcode & 0x01200000) == 0x00200000) /* post-indexed */
442  snprintf(addressing_mode, 32, "[r%i], #%s%d",
443  rn, u ? "" : "-", offset);
444  else if ((opcode & 0x01200000) == 0x00000000) /* unindexed */
445  snprintf(addressing_mode, 32, "[r%i], {%d}",
446  rn, offset >> 2);
447 
448  snprintf(instruction->text, 128, "0x%8.8" PRIx32
449  "\t0x%8.8" PRIx32
450  "\t%s%s%s p%i, c%i, %s",
451  address, opcode, mnemonic,
452  ((opcode & 0xf0000000) == 0xf0000000)
453  ? "2" : COND(opcode),
454  (opcode & (1 << 22)) ? "L" : "",
455  cp_num, crd, addressing_mode);
456  }
457 
458  return ERROR_OK;
459 }
460 
461 /* Coprocessor data processing instructions
462  * Coprocessor register transfer instructions
463  * both normal and extended instruction space (condition field b1111) */
464 static int evaluate_cdp_mcr_mrc(uint32_t opcode,
465  uint32_t address, struct arm_instruction *instruction)
466 {
467  const char *cond;
468  char *mnemonic;
469  uint8_t cp_num, opcode_1, crd_rd, crn, crm, opcode_2;
470 
471  cond = ((opcode & 0xf0000000) == 0xf0000000) ? "2" : COND(opcode);
472  cp_num = (opcode & 0xf00) >> 8;
473  crd_rd = (opcode & 0xf000) >> 12;
474  crn = (opcode & 0xf0000) >> 16;
475  crm = (opcode & 0xf);
476  opcode_2 = (opcode & 0xe0) >> 5;
477 
478  /* CDP or MRC/MCR */
479  if (opcode & 0x00000010) { /* bit 4 set -> MRC/MCR */
480  if (opcode & 0x00100000) { /* bit 20 set -> MRC */
481  instruction->type = ARM_MRC;
482  mnemonic = "MRC";
483  } else {/* bit 20 not set -> MCR */
484  instruction->type = ARM_MCR;
485  mnemonic = "MCR";
486  }
487 
488  opcode_1 = (opcode & 0x00e00000) >> 21;
489 
490  snprintf(instruction->text,
491  128,
492  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, 0x%2.2x, r%i, c%i, c%i, 0x%2.2x",
493  address,
494  opcode,
495  mnemonic,
496  cond,
497  cp_num,
498  opcode_1,
499  crd_rd,
500  crn,
501  crm,
502  opcode_2);
503  } else {/* bit 4 not set -> CDP */
504  instruction->type = ARM_CDP;
505  mnemonic = "CDP";
506 
507  opcode_1 = (opcode & 0x00f00000) >> 20;
508 
509  snprintf(instruction->text,
510  128,
511  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s p%i, 0x%2.2x, c%i, c%i, c%i, 0x%2.2x",
512  address,
513  opcode,
514  mnemonic,
515  cond,
516  cp_num,
517  opcode_1,
518  crd_rd,
519  crn,
520  crm,
521  opcode_2);
522  }
523 
524  return ERROR_OK;
525 }
526 
527 /* Load/store instructions */
528 static int evaluate_load_store(uint32_t opcode,
529  uint32_t address, struct arm_instruction *instruction)
530 {
531  uint8_t i, p, u, b, w, l;
532  uint8_t rn, rd;
533  char *operation;/* "LDR" or "STR" */
534  char *suffix; /* "", "B", "T", "BT" */
535  char offset[32];
536 
537  /* examine flags */
538  i = (opcode & 0x02000000) >> 25;
539  p = (opcode & 0x01000000) >> 24;
540  u = (opcode & 0x00800000) >> 23;
541  b = (opcode & 0x00400000) >> 22;
542  w = (opcode & 0x00200000) >> 21;
543  l = (opcode & 0x00100000) >> 20;
544 
545  /* target register */
546  rd = (opcode & 0xf000) >> 12;
547 
548  /* base register */
549  rn = (opcode & 0xf0000) >> 16;
550 
551  instruction->info.load_store.rd = rd;
552  instruction->info.load_store.rn = rn;
553  instruction->info.load_store.u = u;
554 
555  /* determine operation */
556  if (l)
557  operation = "LDR";
558  else
559  operation = "STR";
560 
561  /* determine instruction type and suffix */
562  if (b) {
563  if ((p == 0) && (w == 1)) {
564  if (l)
565  instruction->type = ARM_LDRBT;
566  else
567  instruction->type = ARM_STRBT;
568  suffix = "BT";
569  } else {
570  if (l)
571  instruction->type = ARM_LDRB;
572  else
573  instruction->type = ARM_STRB;
574  suffix = "B";
575  }
576  } else {
577  if ((p == 0) && (w == 1)) {
578  if (l)
579  instruction->type = ARM_LDRT;
580  else
581  instruction->type = ARM_STRT;
582  suffix = "T";
583  } else {
584  if (l)
585  instruction->type = ARM_LDR;
586  else
587  instruction->type = ARM_STR;
588  suffix = "";
589  }
590  }
591 
592  if (!i) { /* #+-<offset_12> */
593  uint32_t offset_12 = (opcode & 0xfff);
594  if (offset_12)
595  snprintf(offset, 32, ", #%s0x%" PRIx32, (u) ? "" : "-", offset_12);
596  else
597  snprintf(offset, 32, "%s", "");
598 
599  instruction->info.load_store.offset_mode = 0;
600  instruction->info.load_store.offset.offset = offset_12;
601  } else {/* either +-<Rm> or +-<Rm>, <shift>, #<shift_imm> */
602  uint8_t shift_imm, shift;
603  uint8_t rm;
604 
605  shift_imm = (opcode & 0xf80) >> 7;
606  shift = (opcode & 0x60) >> 5;
607  rm = (opcode & 0xf);
608 
609  /* LSR encodes a shift by 32 bit as 0x0 */
610  if ((shift == 0x1) && (shift_imm == 0x0))
611  shift_imm = 0x20;
612 
613  /* ASR encodes a shift by 32 bit as 0x0 */
614  if ((shift == 0x2) && (shift_imm == 0x0))
615  shift_imm = 0x20;
616 
617  /* ROR by 32 bit is actually a RRX */
618  if ((shift == 0x3) && (shift_imm == 0x0))
619  shift = 0x4;
620 
621  instruction->info.load_store.offset_mode = 1;
622  instruction->info.load_store.offset.reg.rm = rm;
623  instruction->info.load_store.offset.reg.shift = shift;
624  instruction->info.load_store.offset.reg.shift_imm = shift_imm;
625 
626  if ((shift_imm == 0x0) && (shift == 0x0)) /* +-<Rm> */
627  snprintf(offset, 32, ", %sr%i", (u) ? "" : "-", rm);
628  else { /* +-<Rm>, <Shift>, #<shift_imm> */
629  switch (shift) {
630  case 0x0: /* LSL */
631  snprintf(offset, 32, ", %sr%i, LSL #0x%x", (u) ? "" : "-", rm, shift_imm);
632  break;
633  case 0x1: /* LSR */
634  snprintf(offset, 32, ", %sr%i, LSR #0x%x", (u) ? "" : "-", rm, shift_imm);
635  break;
636  case 0x2: /* ASR */
637  snprintf(offset, 32, ", %sr%i, ASR #0x%x", (u) ? "" : "-", rm, shift_imm);
638  break;
639  case 0x3: /* ROR */
640  snprintf(offset, 32, ", %sr%i, ROR #0x%x", (u) ? "" : "-", rm, shift_imm);
641  break;
642  case 0x4: /* RRX */
643  snprintf(offset, 32, ", %sr%i, RRX", (u) ? "" : "-", rm);
644  break;
645  }
646  }
647  }
648 
649  if (p == 1) {
650  if (w == 0) { /* offset */
651  snprintf(instruction->text,
652  128,
653  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]",
654  address,
655  opcode,
656  operation,
657  COND(opcode),
658  suffix,
659  rd,
660  rn,
661  offset);
662 
663  instruction->info.load_store.index_mode = 0;
664  } else {/* pre-indexed */
665  snprintf(instruction->text,
666  128,
667  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i%s]!",
668  address,
669  opcode,
670  operation,
671  COND(opcode),
672  suffix,
673  rd,
674  rn,
675  offset);
676 
677  instruction->info.load_store.index_mode = 1;
678  }
679  } else {/* post-indexed */
680  snprintf(instruction->text,
681  128,
682  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i]%s",
683  address,
684  opcode,
685  operation,
686  COND(opcode),
687  suffix,
688  rd,
689  rn,
690  offset);
691 
692  instruction->info.load_store.index_mode = 2;
693  }
694 
695  return ERROR_OK;
696 }
697 
698 static int evaluate_extend(uint32_t opcode, uint32_t address, char *cp)
699 {
700  unsigned int rm = (opcode >> 0) & 0xf;
701  unsigned int rd = (opcode >> 12) & 0xf;
702  unsigned int rn = (opcode >> 16) & 0xf;
703  char *type, *rot;
704 
705  switch ((opcode >> 24) & 0x3) {
706  case 0:
707  type = "B16";
708  break;
709  case 1:
710  sprintf(cp, "UNDEFINED");
712  case 2:
713  type = "B";
714  break;
715  default:
716  type = "H";
717  break;
718  }
719 
720  switch ((opcode >> 10) & 0x3) {
721  case 0:
722  rot = "";
723  break;
724  case 1:
725  rot = ", ROR #8";
726  break;
727  case 2:
728  rot = ", ROR #16";
729  break;
730  default:
731  rot = ", ROR #24";
732  break;
733  }
734 
735  if (rn == 0xf) {
736  sprintf(cp, "%cXT%s%s\tr%d, r%d%s",
737  (opcode & (1 << 22)) ? 'U' : 'S',
738  type, COND(opcode),
739  rd, rm, rot);
740  return ARM_MOV;
741  } else {
742  sprintf(cp, "%cXTA%s%s\tr%d, r%d, r%d%s",
743  (opcode & (1 << 22)) ? 'U' : 'S',
744  type, COND(opcode),
745  rd, rn, rm, rot);
746  return ARM_ADD;
747  }
748 }
749 
750 static int evaluate_p_add_sub(uint32_t opcode, uint32_t address, char *cp)
751 {
752  char *prefix;
753  char *op;
754  int type;
755 
756  switch ((opcode >> 20) & 0x7) {
757  case 1:
758  prefix = "S";
759  break;
760  case 2:
761  prefix = "Q";
762  break;
763  case 3:
764  prefix = "SH";
765  break;
766  case 5:
767  prefix = "U";
768  break;
769  case 6:
770  prefix = "UQ";
771  break;
772  case 7:
773  prefix = "UH";
774  break;
775  default:
776  goto undef;
777  }
778 
779  switch ((opcode >> 5) & 0x7) {
780  case 0:
781  op = "ADD16";
782  type = ARM_ADD;
783  break;
784  case 1:
785  op = "ADDSUBX";
786  type = ARM_ADD;
787  break;
788  case 2:
789  op = "SUBADDX";
790  type = ARM_SUB;
791  break;
792  case 3:
793  op = "SUB16";
794  type = ARM_SUB;
795  break;
796  case 4:
797  op = "ADD8";
798  type = ARM_ADD;
799  break;
800  case 7:
801  op = "SUB8";
802  type = ARM_SUB;
803  break;
804  default:
805  goto undef;
806  }
807 
808  sprintf(cp, "%s%s%s\tr%d, r%d, r%d", prefix, op, COND(opcode),
809  (int) (opcode >> 12) & 0xf,
810  (int) (opcode >> 16) & 0xf,
811  (int) (opcode >> 0) & 0xf);
812  return type;
813 
814 undef:
815  /* these opcodes might be used someday */
816  sprintf(cp, "UNDEFINED");
818 }
819 
820 /* ARMv6 and later support "media" instructions (includes SIMD) */
821 static int evaluate_media(uint32_t opcode, uint32_t address,
822  struct arm_instruction *instruction)
823 {
824  char *cp = instruction->text;
825  char *mnemonic = NULL;
826 
827  sprintf(cp,
828  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t",
829  address, opcode);
830  cp = strchr(cp, 0);
831 
832  /* parallel add/subtract */
833  if ((opcode & 0x01800000) == 0x00000000) {
834  instruction->type = evaluate_p_add_sub(opcode, address, cp);
835  return ERROR_OK;
836  }
837 
838  /* halfword pack */
839  if ((opcode & 0x01f00020) == 0x00800000) {
840  char *type, *shift;
841  unsigned int imm = (opcode >> 7) & 0x1f;
842 
843  if (opcode & (1 << 6)) {
844  type = "TB";
845  shift = "ASR";
846  if (imm == 0)
847  imm = 32;
848  } else {
849  type = "BT";
850  shift = "LSL";
851  }
852  sprintf(cp, "PKH%s%s\tr%d, r%d, r%d, %s #%d",
853  type, COND(opcode),
854  (int) (opcode >> 12) & 0xf,
855  (int) (opcode >> 16) & 0xf,
856  (int) (opcode >> 0) & 0xf,
857  shift, imm);
858  return ERROR_OK;
859  }
860 
861  /* word saturate */
862  if ((opcode & 0x01a00020) == 0x00a00000) {
863  char *shift;
864  unsigned int imm = (opcode >> 7) & 0x1f;
865 
866  if (opcode & (1 << 6)) {
867  shift = "ASR";
868  if (imm == 0)
869  imm = 32;
870  } else
871  shift = "LSL";
872 
873  sprintf(cp, "%cSAT%s\tr%d, #%d, r%d, %s #%d",
874  (opcode & (1 << 22)) ? 'U' : 'S',
875  COND(opcode),
876  (int) (opcode >> 12) & 0xf,
877  (int) (opcode >> 16) & 0x1f,
878  (int) (opcode >> 0) & 0xf,
879  shift, imm);
880  return ERROR_OK;
881  }
882 
883  /* sign extension */
884  if ((opcode & 0x018000f0) == 0x00800070) {
885  instruction->type = evaluate_extend(opcode, address, cp);
886  return ERROR_OK;
887  }
888 
889  /* multiplies */
890  if ((opcode & 0x01f00080) == 0x01000000) {
891  unsigned int rn = (opcode >> 12) & 0xf;
892 
893  if (rn != 0xf)
894  sprintf(cp, "SML%cD%s%s\tr%d, r%d, r%d, r%d",
895  (opcode & (1 << 6)) ? 'S' : 'A',
896  (opcode & (1 << 5)) ? "X" : "",
897  COND(opcode),
898  (int) (opcode >> 16) & 0xf,
899  (int) (opcode >> 0) & 0xf,
900  (int) (opcode >> 8) & 0xf,
901  rn);
902  else
903  sprintf(cp, "SMU%cD%s%s\tr%d, r%d, r%d",
904  (opcode & (1 << 6)) ? 'S' : 'A',
905  (opcode & (1 << 5)) ? "X" : "",
906  COND(opcode),
907  (int) (opcode >> 16) & 0xf,
908  (int) (opcode >> 0) & 0xf,
909  (int) (opcode >> 8) & 0xf);
910  return ERROR_OK;
911  }
912  if ((opcode & 0x01f00000) == 0x01400000) {
913  sprintf(cp, "SML%cLD%s%s\tr%d, r%d, r%d, r%d",
914  (opcode & (1 << 6)) ? 'S' : 'A',
915  (opcode & (1 << 5)) ? "X" : "",
916  COND(opcode),
917  (int) (opcode >> 12) & 0xf,
918  (int) (opcode >> 16) & 0xf,
919  (int) (opcode >> 0) & 0xf,
920  (int) (opcode >> 8) & 0xf);
921  return ERROR_OK;
922  }
923  if ((opcode & 0x01f00000) == 0x01500000) {
924  unsigned int rn = (opcode >> 12) & 0xf;
925 
926  switch (opcode & 0xc0) {
927  case 3:
928  if (rn == 0xf)
929  goto undef;
930  /* FALL THROUGH */
931  case 0:
932  break;
933  default:
934  goto undef;
935  }
936 
937  if (rn != 0xf)
938  sprintf(cp, "SMML%c%s%s\tr%d, r%d, r%d, r%d",
939  (opcode & (1 << 6)) ? 'S' : 'A',
940  (opcode & (1 << 5)) ? "R" : "",
941  COND(opcode),
942  (int) (opcode >> 16) & 0xf,
943  (int) (opcode >> 0) & 0xf,
944  (int) (opcode >> 8) & 0xf,
945  rn);
946  else
947  sprintf(cp, "SMMUL%s%s\tr%d, r%d, r%d",
948  (opcode & (1 << 5)) ? "R" : "",
949  COND(opcode),
950  (int) (opcode >> 16) & 0xf,
951  (int) (opcode >> 0) & 0xf,
952  (int) (opcode >> 8) & 0xf);
953  return ERROR_OK;
954  }
955 
956  /* simple matches against the remaining decode bits */
957  switch (opcode & 0x01f000f0) {
958  case 0x00a00030:
959  case 0x00e00030:
960  /* parallel halfword saturate */
961  sprintf(cp, "%cSAT16%s\tr%d, #%d, r%d",
962  (opcode & (1 << 22)) ? 'U' : 'S',
963  COND(opcode),
964  (int)(opcode >> 12) & 0xf,
965  (int)(opcode >> 16) & 0xf,
966  (int)(opcode >> 0) & 0xf);
967  return ERROR_OK;
968  case 0x00b00030:
969  mnemonic = "REV";
970  break;
971  case 0x00b000b0:
972  mnemonic = "REV16";
973  break;
974  case 0x00f000b0:
975  mnemonic = "REVSH";
976  break;
977  case 0x008000b0:
978  /* select bytes */
979  sprintf(cp, "SEL%s\tr%d, r%d, r%d", COND(opcode),
980  (int)(opcode >> 12) & 0xf,
981  (int)(opcode >> 16) & 0xf,
982  (int)(opcode >> 0) & 0xf);
983  return ERROR_OK;
984  case 0x01800010:
985  /* unsigned sum of absolute differences */
986  if (((opcode >> 12) & 0xf) == 0xf)
987  sprintf(cp, "USAD8%s\tr%d, r%d, r%d", COND(opcode),
988  (int)(opcode >> 16) & 0xf,
989  (int)(opcode >> 0) & 0xf,
990  (int)(opcode >> 8) & 0xf);
991  else
992  sprintf(cp, "USADA8%s\tr%d, r%d, r%d, r%d", COND(opcode),
993  (int)(opcode >> 16) & 0xf,
994  (int)(opcode >> 0) & 0xf,
995  (int)(opcode >> 8) & 0xf,
996  (int)(opcode >> 12) & 0xf);
997  return ERROR_OK;
998  }
999  if (mnemonic) {
1000  unsigned int rm = (opcode >> 0) & 0xf;
1001  unsigned int rd = (opcode >> 12) & 0xf;
1002 
1003  sprintf(cp, "%s%s\tr%d, r%d", mnemonic, COND(opcode), rm, rd);
1004  return ERROR_OK;
1005  }
1006 
1007 undef:
1008  /* these opcodes might be used someday */
1009  sprintf(cp, "UNDEFINED");
1010  return ERROR_OK;
1011 }
1012 
1013 /* Miscellaneous load/store instructions */
1014 static int evaluate_misc_load_store(uint32_t opcode,
1015  uint32_t address, struct arm_instruction *instruction)
1016 {
1017  uint8_t p, u, i, w, l, s, h;
1018  uint8_t rn, rd;
1019  char *operation;/* "LDR" or "STR" */
1020  char *suffix; /* "H", "SB", "SH", "D" */
1021  char offset[32];
1022 
1023  /* examine flags */
1024  p = (opcode & 0x01000000) >> 24;
1025  u = (opcode & 0x00800000) >> 23;
1026  i = (opcode & 0x00400000) >> 22;
1027  w = (opcode & 0x00200000) >> 21;
1028  l = (opcode & 0x00100000) >> 20;
1029  s = (opcode & 0x00000040) >> 6;
1030  h = (opcode & 0x00000020) >> 5;
1031 
1032  /* target register */
1033  rd = (opcode & 0xf000) >> 12;
1034 
1035  /* base register */
1036  rn = (opcode & 0xf0000) >> 16;
1037 
1038  instruction->info.load_store.rd = rd;
1039  instruction->info.load_store.rn = rn;
1040  instruction->info.load_store.u = u;
1041 
1042  /* determine instruction type and suffix */
1043  if (s) {/* signed */
1044  if (l) {/* load */
1045  if (h) {
1046  operation = "LDR";
1047  instruction->type = ARM_LDRSH;
1048  suffix = "SH";
1049  } else {
1050  operation = "LDR";
1051  instruction->type = ARM_LDRSB;
1052  suffix = "SB";
1053  }
1054  } else {/* there are no signed stores, so this is used to encode double-register
1055  *load/stores */
1056  suffix = "D";
1057  if (h) {
1058  operation = "STR";
1059  instruction->type = ARM_STRD;
1060  } else {
1061  operation = "LDR";
1062  instruction->type = ARM_LDRD;
1063  }
1064  }
1065  } else {/* unsigned */
1066  suffix = "H";
1067  if (l) {/* load */
1068  operation = "LDR";
1069  instruction->type = ARM_LDRH;
1070  } else {/* store */
1071  operation = "STR";
1072  instruction->type = ARM_STRH;
1073  }
1074  }
1075 
1076  if (i) {/* Immediate offset/index (#+-<offset_8>)*/
1077  uint32_t offset_8 = ((opcode & 0xf00) >> 4) | (opcode & 0xf);
1078  snprintf(offset, 32, "#%s0x%" PRIx32, (u) ? "" : "-", offset_8);
1079 
1080  instruction->info.load_store.offset_mode = 0;
1081  instruction->info.load_store.offset.offset = offset_8;
1082  } else {/* Register offset/index (+-<Rm>) */
1083  uint8_t rm;
1084  rm = (opcode & 0xf);
1085  snprintf(offset, 32, "%sr%i", (u) ? "" : "-", rm);
1086 
1087  instruction->info.load_store.offset_mode = 1;
1088  instruction->info.load_store.offset.reg.rm = rm;
1089  instruction->info.load_store.offset.reg.shift = 0x0;
1090  instruction->info.load_store.offset.reg.shift_imm = 0x0;
1091  }
1092 
1093  if (p == 1) {
1094  if (w == 0) { /* offset */
1095  snprintf(instruction->text,
1096  128,
1097  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]",
1098  address,
1099  opcode,
1100  operation,
1101  COND(opcode),
1102  suffix,
1103  rd,
1104  rn,
1105  offset);
1106 
1107  instruction->info.load_store.index_mode = 0;
1108  } else {/* pre-indexed */
1109  snprintf(instruction->text,
1110  128,
1111  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i, %s]!",
1112  address,
1113  opcode,
1114  operation,
1115  COND(opcode),
1116  suffix,
1117  rd,
1118  rn,
1119  offset);
1120 
1121  instruction->info.load_store.index_mode = 1;
1122  }
1123  } else {/* post-indexed */
1124  snprintf(instruction->text,
1125  128,
1126  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, [r%i], %s",
1127  address,
1128  opcode,
1129  operation,
1130  COND(opcode),
1131  suffix,
1132  rd,
1133  rn,
1134  offset);
1135 
1136  instruction->info.load_store.index_mode = 2;
1137  }
1138 
1139  return ERROR_OK;
1140 }
1141 
1142 /* Load/store multiples instructions */
1143 static int evaluate_ldm_stm(uint32_t opcode,
1144  uint32_t address, struct arm_instruction *instruction)
1145 {
1146  uint8_t p, u, s, w, l, rn;
1147  uint32_t register_list;
1148  char *addressing_mode;
1149  char *mnemonic;
1150  char reg_list[69];
1151  char *reg_list_p;
1152  int i;
1153  int first_reg = 1;
1154 
1155  p = (opcode & 0x01000000) >> 24;
1156  u = (opcode & 0x00800000) >> 23;
1157  s = (opcode & 0x00400000) >> 22;
1158  w = (opcode & 0x00200000) >> 21;
1159  l = (opcode & 0x00100000) >> 20;
1160  register_list = (opcode & 0xffff);
1161  rn = (opcode & 0xf0000) >> 16;
1162 
1163  instruction->info.load_store_multiple.rn = rn;
1164  instruction->info.load_store_multiple.register_list = register_list;
1165  instruction->info.load_store_multiple.s = s;
1166  instruction->info.load_store_multiple.w = w;
1167 
1168  if (l) {
1169  instruction->type = ARM_LDM;
1170  mnemonic = "LDM";
1171  } else {
1172  instruction->type = ARM_STM;
1173  mnemonic = "STM";
1174  }
1175 
1176  if (p) {
1177  if (u) {
1178  instruction->info.load_store_multiple.addressing_mode = 1;
1179  addressing_mode = "IB";
1180  } else {
1181  instruction->info.load_store_multiple.addressing_mode = 3;
1182  addressing_mode = "DB";
1183  }
1184  } else {
1185  if (u) {
1186  instruction->info.load_store_multiple.addressing_mode = 0;
1187  /* "IA" is the default in UAL syntax */
1188  addressing_mode = "";
1189  } else {
1190  instruction->info.load_store_multiple.addressing_mode = 2;
1191  addressing_mode = "DA";
1192  }
1193  }
1194 
1195  reg_list_p = reg_list;
1196  for (i = 0; i <= 15; i++) {
1197  if ((register_list >> i) & 1) {
1198  if (first_reg) {
1199  first_reg = 0;
1200  reg_list_p += snprintf(reg_list_p,
1201  (reg_list + 69 - reg_list_p),
1202  "r%i",
1203  i);
1204  } else
1205  reg_list_p += snprintf(reg_list_p,
1206  (reg_list + 69 - reg_list_p),
1207  ", r%i",
1208  i);
1209  }
1210  }
1211 
1212  snprintf(instruction->text, 128,
1213  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32
1214  "\t%s%s%s r%i%s, {%s}%s",
1215  address, opcode,
1216  mnemonic, addressing_mode, COND(opcode),
1217  rn, (w) ? "!" : "", reg_list, (s) ? "^" : "");
1218 
1219  return ERROR_OK;
1220 }
1221 
1222 /* Multiplies, extra load/stores */
1223 static int evaluate_mul_and_extra_ld_st(uint32_t opcode,
1224  uint32_t address, struct arm_instruction *instruction)
1225 {
1226  /* Multiply (accumulate) (long) and Swap/swap byte */
1227  if ((opcode & 0x000000f0) == 0x00000090) {
1228  /* Multiply (accumulate) */
1229  if ((opcode & 0x0f800000) == 0x00000000) {
1230  uint8_t rm, rs, rn, rd, s;
1231  rm = opcode & 0xf;
1232  rs = (opcode & 0xf00) >> 8;
1233  rn = (opcode & 0xf000) >> 12;
1234  rd = (opcode & 0xf0000) >> 16;
1235  s = (opcode & 0x00100000) >> 20;
1236 
1237  /* examine A bit (accumulate) */
1238  if (opcode & 0x00200000) {
1239  instruction->type = ARM_MLA;
1240  snprintf(instruction->text,
1241  128,
1242  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMLA%s%s r%i, r%i, r%i, r%i",
1243  address,
1244  opcode,
1245  COND(opcode),
1246  (s) ? "S" : "",
1247  rd,
1248  rm,
1249  rs,
1250  rn);
1251  } else {
1252  instruction->type = ARM_MUL;
1253  snprintf(instruction->text,
1254  128,
1255  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMUL%s%s r%i, r%i, r%i",
1256  address,
1257  opcode,
1258  COND(opcode),
1259  (s) ? "S" : "",
1260  rd,
1261  rm,
1262  rs);
1263  }
1264 
1265  return ERROR_OK;
1266  }
1267 
1268  /* Multiply (accumulate) long */
1269  if ((opcode & 0x0f800000) == 0x00800000) {
1270  char *mnemonic = NULL;
1271  uint8_t rm, rs, rd_hi, rd_low, s;
1272  rm = opcode & 0xf;
1273  rs = (opcode & 0xf00) >> 8;
1274  rd_hi = (opcode & 0xf000) >> 12;
1275  rd_low = (opcode & 0xf0000) >> 16;
1276  s = (opcode & 0x00100000) >> 20;
1277 
1278  switch ((opcode & 0x00600000) >> 21) {
1279  case 0x0:
1280  instruction->type = ARM_UMULL;
1281  mnemonic = "UMULL";
1282  break;
1283  case 0x1:
1284  instruction->type = ARM_UMLAL;
1285  mnemonic = "UMLAL";
1286  break;
1287  case 0x2:
1288  instruction->type = ARM_SMULL;
1289  mnemonic = "SMULL";
1290  break;
1291  case 0x3:
1292  instruction->type = ARM_SMLAL;
1293  mnemonic = "SMLAL";
1294  break;
1295  }
1296 
1297  snprintf(instruction->text,
1298  128,
1299  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, r%i, r%i",
1300  address,
1301  opcode,
1302  mnemonic,
1303  COND(opcode),
1304  (s) ? "S" : "",
1305  rd_low,
1306  rd_hi,
1307  rm,
1308  rs);
1309 
1310  return ERROR_OK;
1311  }
1312 
1313  /* Swap/swap byte */
1314  if ((opcode & 0x0f800000) == 0x01000000) {
1315  uint8_t rm, rd, rn;
1316  rm = opcode & 0xf;
1317  rd = (opcode & 0xf000) >> 12;
1318  rn = (opcode & 0xf0000) >> 16;
1319 
1320  /* examine B flag */
1321  instruction->type = (opcode & 0x00400000) ? ARM_SWPB : ARM_SWP;
1322 
1323  snprintf(instruction->text,
1324  128,
1325  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, [r%i]",
1326  address,
1327  opcode,
1328  (opcode & 0x00400000) ? "SWPB" : "SWP",
1329  COND(opcode),
1330  rd,
1331  rm,
1332  rn);
1333  return ERROR_OK;
1334  }
1335 
1336  }
1337 
1338  return evaluate_misc_load_store(opcode, address, instruction);
1339 }
1340 
1341 static int evaluate_mrs_msr(uint32_t opcode,
1342  uint32_t address, struct arm_instruction *instruction)
1343 {
1344  int r = (opcode & 0x00400000) >> 22;
1345  char *PSR = (r) ? "SPSR" : "CPSR";
1346 
1347  /* Move register to status register (MSR) */
1348  if (opcode & 0x00200000) {
1349  instruction->type = ARM_MSR;
1350 
1351  /* immediate variant */
1352  if (opcode & 0x02000000) {
1353  uint8_t immediate = (opcode & 0xff);
1354  uint8_t rotate = (opcode & 0xf00);
1355 
1356  snprintf(instruction->text,
1357  128,
1358  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, 0x%8.8" PRIx32,
1359  address,
1360  opcode,
1361  COND(opcode),
1362  PSR,
1363  (opcode & 0x10000) ? "c" : "",
1364  (opcode & 0x20000) ? "x" : "",
1365  (opcode & 0x40000) ? "s" : "",
1366  (opcode & 0x80000) ? "f" : "",
1367  ror(immediate, (rotate * 2))
1368  );
1369  } else {/* register variant */
1370  uint8_t rm = opcode & 0xf;
1371  snprintf(instruction->text,
1372  128,
1373  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMSR%s %s_%s%s%s%s, r%i",
1374  address,
1375  opcode,
1376  COND(opcode),
1377  PSR,
1378  (opcode & 0x10000) ? "c" : "",
1379  (opcode & 0x20000) ? "x" : "",
1380  (opcode & 0x40000) ? "s" : "",
1381  (opcode & 0x80000) ? "f" : "",
1382  rm
1383  );
1384  }
1385 
1386  } else {/* Move status register to register (MRS) */
1387  uint8_t rd;
1388 
1389  instruction->type = ARM_MRS;
1390  rd = (opcode & 0x0000f000) >> 12;
1391 
1392  snprintf(instruction->text,
1393  128,
1394  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMRS%s r%i, %s",
1395  address,
1396  opcode,
1397  COND(opcode),
1398  rd,
1399  PSR);
1400  }
1401 
1402  return ERROR_OK;
1403 }
1404 
1405 /* Miscellaneous instructions */
1406 static int evaluate_misc_instr(uint32_t opcode,
1407  uint32_t address, struct arm_instruction *instruction)
1408 {
1409  /* MRS/MSR */
1410  if ((opcode & 0x000000f0) == 0x00000000)
1411  evaluate_mrs_msr(opcode, address, instruction);
1412 
1413  /* BX */
1414  if ((opcode & 0x006000f0) == 0x00200010) {
1415  uint8_t rm;
1416  instruction->type = ARM_BX;
1417  rm = opcode & 0xf;
1418 
1419  snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBX%s r%i",
1420  address, opcode, COND(opcode), rm);
1421 
1422  instruction->info.b_bl_bx_blx.reg_operand = rm;
1423  instruction->info.b_bl_bx_blx.target_address = -1;
1424  }
1425 
1426  /* BXJ - "Jazelle" support (ARMv5-J) */
1427  if ((opcode & 0x006000f0) == 0x00200020) {
1428  uint8_t rm;
1429  instruction->type = ARM_BX;
1430  rm = opcode & 0xf;
1431 
1432  snprintf(instruction->text, 128,
1433  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBXJ%s r%i",
1434  address, opcode, COND(opcode), rm);
1435 
1436  instruction->info.b_bl_bx_blx.reg_operand = rm;
1437  instruction->info.b_bl_bx_blx.target_address = -1;
1438  }
1439 
1440  /* CLZ */
1441  if ((opcode & 0x006000f0) == 0x00600010) {
1442  uint8_t rm, rd;
1443  instruction->type = ARM_CLZ;
1444  rm = opcode & 0xf;
1445  rd = (opcode & 0xf000) >> 12;
1446 
1447  snprintf(instruction->text,
1448  128,
1449  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tCLZ%s r%i, r%i",
1450  address,
1451  opcode,
1452  COND(opcode),
1453  rd,
1454  rm);
1455  }
1456 
1457  /* BLX(2) */
1458  if ((opcode & 0x006000f0) == 0x00200030) {
1459  uint8_t rm;
1460  instruction->type = ARM_BLX;
1461  rm = opcode & 0xf;
1462 
1463  snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tBLX%s r%i",
1464  address, opcode, COND(opcode), rm);
1465 
1466  instruction->info.b_bl_bx_blx.reg_operand = rm;
1467  instruction->info.b_bl_bx_blx.target_address = -1;
1468  }
1469 
1470  /* Enhanced DSP add/subtracts */
1471  if ((opcode & 0x0000000f0) == 0x00000050) {
1472  uint8_t rm, rd, rn;
1473  char *mnemonic = NULL;
1474  rm = opcode & 0xf;
1475  rd = (opcode & 0xf000) >> 12;
1476  rn = (opcode & 0xf0000) >> 16;
1477 
1478  switch ((opcode & 0x00600000) >> 21) {
1479  case 0x0:
1480  instruction->type = ARM_QADD;
1481  mnemonic = "QADD";
1482  break;
1483  case 0x1:
1484  instruction->type = ARM_QSUB;
1485  mnemonic = "QSUB";
1486  break;
1487  case 0x2:
1488  instruction->type = ARM_QDADD;
1489  mnemonic = "QDADD";
1490  break;
1491  case 0x3:
1492  instruction->type = ARM_QDSUB;
1493  mnemonic = "QDSUB";
1494  break;
1495  }
1496 
1497  snprintf(instruction->text,
1498  128,
1499  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, r%i, r%i",
1500  address,
1501  opcode,
1502  mnemonic,
1503  COND(opcode),
1504  rd,
1505  rm,
1506  rn);
1507  }
1508 
1509  /* exception return */
1510  if ((opcode & 0x0000000f0) == 0x00000060) {
1511  if (((opcode & 0x600000) >> 21) == 3)
1512  instruction->type = ARM_ERET;
1513  snprintf(instruction->text,
1514  128,
1515  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tERET",
1516  address,
1517  opcode);
1518  }
1519 
1520  /* exception generate instructions */
1521  if ((opcode & 0x0000000f0) == 0x00000070) {
1522  uint32_t immediate = 0;
1523  char *mnemonic = NULL;
1524 
1525  switch ((opcode & 0x600000) >> 21) {
1526  case 0x1:
1527  instruction->type = ARM_BKPT;
1528  mnemonic = "BRKT";
1529  immediate = ((opcode & 0x000fff00) >> 4) | (opcode & 0xf);
1530  break;
1531  case 0x2:
1532  instruction->type = ARM_HVC;
1533  mnemonic = "HVC";
1534  immediate = ((opcode & 0x000fff00) >> 4) | (opcode & 0xf);
1535  break;
1536  case 0x3:
1537  instruction->type = ARM_SMC;
1538  mnemonic = "SMC";
1539  immediate = (opcode & 0xf);
1540  break;
1541  }
1542 
1543  snprintf(instruction->text,
1544  128,
1545  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s 0x%4.4" PRIx32,
1546  address,
1547  opcode,
1548  mnemonic,
1549  immediate);
1550  }
1551 
1552  /* Enhanced DSP multiplies */
1553  if ((opcode & 0x000000090) == 0x00000080) {
1554  int x = (opcode & 0x20) >> 5;
1555  int y = (opcode & 0x40) >> 6;
1556 
1557  /* SMLA < x><y> */
1558  if ((opcode & 0x00600000) == 0x00000000) {
1559  uint8_t rd, rm, rs, rn;
1560  instruction->type = ARM_SMLAXY;
1561  rd = (opcode & 0xf0000) >> 16;
1562  rm = (opcode & 0xf);
1563  rs = (opcode & 0xf00) >> 8;
1564  rn = (opcode & 0xf000) >> 12;
1565 
1566  snprintf(instruction->text,
1567  128,
1568  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
1569  address,
1570  opcode,
1571  (x) ? "T" : "B",
1572  (y) ? "T" : "B",
1573  COND(opcode),
1574  rd,
1575  rm,
1576  rs,
1577  rn);
1578  }
1579 
1580  /* SMLAL < x><y> */
1581  if ((opcode & 0x00600000) == 0x00400000) {
1582  uint8_t rd_low, rd_hi, rm, rs;
1583  instruction->type = ARM_SMLAXY;
1584  rd_hi = (opcode & 0xf0000) >> 16;
1585  rd_low = (opcode & 0xf000) >> 12;
1586  rm = (opcode & 0xf);
1587  rs = (opcode & 0xf00) >> 8;
1588 
1589  snprintf(instruction->text,
1590  128,
1591  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLA%s%s%s r%i, r%i, r%i, r%i",
1592  address,
1593  opcode,
1594  (x) ? "T" : "B",
1595  (y) ? "T" : "B",
1596  COND(opcode),
1597  rd_low,
1598  rd_hi,
1599  rm,
1600  rs);
1601  }
1602 
1603  /* SMLAW < y> */
1604  if (((opcode & 0x00600000) == 0x00200000) && (x == 0)) {
1605  uint8_t rd, rm, rs, rn;
1606  instruction->type = ARM_SMLAWY;
1607  rd = (opcode & 0xf0000) >> 16;
1608  rm = (opcode & 0xf);
1609  rs = (opcode & 0xf00) >> 8;
1610  rn = (opcode & 0xf000) >> 12;
1611 
1612  snprintf(instruction->text,
1613  128,
1614  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMLAW%s%s r%i, r%i, r%i, r%i",
1615  address,
1616  opcode,
1617  (y) ? "T" : "B",
1618  COND(opcode),
1619  rd,
1620  rm,
1621  rs,
1622  rn);
1623  }
1624 
1625  /* SMUL < x><y> */
1626  if ((opcode & 0x00600000) == 0x00600000) {
1627  uint8_t rd, rm, rs;
1628  instruction->type = ARM_SMULXY;
1629  rd = (opcode & 0xf0000) >> 16;
1630  rm = (opcode & 0xf);
1631  rs = (opcode & 0xf00) >> 8;
1632 
1633  snprintf(instruction->text,
1634  128,
1635  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s%s r%i, r%i, r%i",
1636  address,
1637  opcode,
1638  (x) ? "T" : "B",
1639  (y) ? "T" : "B",
1640  COND(opcode),
1641  rd,
1642  rm,
1643  rs);
1644  }
1645 
1646  /* SMULW < y> */
1647  if (((opcode & 0x00600000) == 0x00200000) && (x == 1)) {
1648  uint8_t rd, rm, rs;
1649  instruction->type = ARM_SMULWY;
1650  rd = (opcode & 0xf0000) >> 16;
1651  rm = (opcode & 0xf);
1652  rs = (opcode & 0xf00) >> 8;
1653 
1654  snprintf(instruction->text,
1655  128,
1656  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tSMULW%s%s r%i, r%i, r%i",
1657  address,
1658  opcode,
1659  (y) ? "T" : "B",
1660  COND(opcode),
1661  rd,
1662  rm,
1663  rs);
1664  }
1665  }
1666 
1667  return ERROR_OK;
1668 }
1669 
1670 static int evaluate_mov_imm(uint32_t opcode,
1671  uint32_t address, struct arm_instruction *instruction)
1672 {
1673  uint16_t immediate;
1674  uint8_t rd;
1675  bool t;
1676 
1677  rd = (opcode & 0xf000) >> 12;
1678  t = opcode & 0x00400000;
1679  immediate = (opcode & 0xf0000) >> 4 | (opcode & 0xfff);
1680 
1681  instruction->type = ARM_MOV;
1682  instruction->info.data_proc.rd = rd;
1683 
1684  snprintf(instruction->text,
1685  128,
1686  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tMOV%s%s r%i, #0x%" PRIx16,
1687  address,
1688  opcode,
1689  t ? "T" : "W",
1690  COND(opcode),
1691  rd,
1692  immediate);
1693 
1694  return ERROR_OK;
1695 }
1696 
1697 static int evaluate_data_proc(uint32_t opcode,
1698  uint32_t address, struct arm_instruction *instruction)
1699 {
1700  uint8_t i, op, s, rn, rd;
1701  char *mnemonic = NULL;
1702  char shifter_operand[32];
1703 
1704  i = (opcode & 0x02000000) >> 25;
1705  op = (opcode & 0x01e00000) >> 21;
1706  s = (opcode & 0x00100000) >> 20;
1707 
1708  rd = (opcode & 0xf000) >> 12;
1709  rn = (opcode & 0xf0000) >> 16;
1710 
1711  instruction->info.data_proc.rd = rd;
1712  instruction->info.data_proc.rn = rn;
1713  instruction->info.data_proc.s = s;
1714 
1715  switch (op) {
1716  case 0x0:
1717  instruction->type = ARM_AND;
1718  mnemonic = "AND";
1719  break;
1720  case 0x1:
1721  instruction->type = ARM_EOR;
1722  mnemonic = "EOR";
1723  break;
1724  case 0x2:
1725  instruction->type = ARM_SUB;
1726  mnemonic = "SUB";
1727  break;
1728  case 0x3:
1729  instruction->type = ARM_RSB;
1730  mnemonic = "RSB";
1731  break;
1732  case 0x4:
1733  instruction->type = ARM_ADD;
1734  mnemonic = "ADD";
1735  break;
1736  case 0x5:
1737  instruction->type = ARM_ADC;
1738  mnemonic = "ADC";
1739  break;
1740  case 0x6:
1741  instruction->type = ARM_SBC;
1742  mnemonic = "SBC";
1743  break;
1744  case 0x7:
1745  instruction->type = ARM_RSC;
1746  mnemonic = "RSC";
1747  break;
1748  case 0x8:
1749  instruction->type = ARM_TST;
1750  mnemonic = "TST";
1751  break;
1752  case 0x9:
1753  instruction->type = ARM_TEQ;
1754  mnemonic = "TEQ";
1755  break;
1756  case 0xa:
1757  instruction->type = ARM_CMP;
1758  mnemonic = "CMP";
1759  break;
1760  case 0xb:
1761  instruction->type = ARM_CMN;
1762  mnemonic = "CMN";
1763  break;
1764  case 0xc:
1765  instruction->type = ARM_ORR;
1766  mnemonic = "ORR";
1767  break;
1768  case 0xd:
1769  instruction->type = ARM_MOV;
1770  mnemonic = "MOV";
1771  break;
1772  case 0xe:
1773  instruction->type = ARM_BIC;
1774  mnemonic = "BIC";
1775  break;
1776  case 0xf:
1777  instruction->type = ARM_MVN;
1778  mnemonic = "MVN";
1779  break;
1780  }
1781 
1782  if (i) {/* immediate shifter operand (#<immediate>)*/
1783  uint8_t immed_8 = opcode & 0xff;
1784  uint8_t rotate_imm = (opcode & 0xf00) >> 8;
1785  uint32_t immediate;
1786 
1787  immediate = ror(immed_8, rotate_imm * 2);
1788 
1789  snprintf(shifter_operand, 32, "#0x%" PRIx32, immediate);
1790 
1791  instruction->info.data_proc.variant = 0;
1792  instruction->info.data_proc.shifter_operand.immediate.immediate = immediate;
1793  } else {/* register-based shifter operand */
1794  uint8_t shift, rm;
1795  shift = (opcode & 0x60) >> 5;
1796  rm = (opcode & 0xf);
1797 
1798  if ((opcode & 0x10) != 0x10) { /* Immediate shifts ("<Rm>" or "<Rm>, <shift>
1799  *#<shift_immediate>") */
1800  uint8_t shift_imm;
1801  shift_imm = (opcode & 0xf80) >> 7;
1802 
1803  instruction->info.data_proc.variant = 1;
1804  instruction->info.data_proc.shifter_operand.immediate_shift.rm = rm;
1806  shift_imm;
1807  instruction->info.data_proc.shifter_operand.immediate_shift.shift = shift;
1808 
1809  /* LSR encodes a shift by 32 bit as 0x0 */
1810  if ((shift == 0x1) && (shift_imm == 0x0))
1811  shift_imm = 0x20;
1812 
1813  /* ASR encodes a shift by 32 bit as 0x0 */
1814  if ((shift == 0x2) && (shift_imm == 0x0))
1815  shift_imm = 0x20;
1816 
1817  /* ROR by 32 bit is actually a RRX */
1818  if ((shift == 0x3) && (shift_imm == 0x0))
1819  shift = 0x4;
1820 
1821  if ((shift_imm == 0x0) && (shift == 0x0))
1822  snprintf(shifter_operand, 32, "r%i", rm);
1823  else {
1824  if (shift == 0x0) /* LSL */
1825  snprintf(shifter_operand,
1826  32,
1827  "r%i, LSL #0x%x",
1828  rm,
1829  shift_imm);
1830  else if (shift == 0x1) /* LSR */
1831  snprintf(shifter_operand,
1832  32,
1833  "r%i, LSR #0x%x",
1834  rm,
1835  shift_imm);
1836  else if (shift == 0x2) /* ASR */
1837  snprintf(shifter_operand,
1838  32,
1839  "r%i, ASR #0x%x",
1840  rm,
1841  shift_imm);
1842  else if (shift == 0x3) /* ROR */
1843  snprintf(shifter_operand,
1844  32,
1845  "r%i, ROR #0x%x",
1846  rm,
1847  shift_imm);
1848  else if (shift == 0x4) /* RRX */
1849  snprintf(shifter_operand, 32, "r%i, RRX", rm);
1850  }
1851  } else {/* Register shifts ("<Rm>, <shift> <Rs>") */
1852  uint8_t rs = (opcode & 0xf00) >> 8;
1853 
1854  instruction->info.data_proc.variant = 2;
1855  instruction->info.data_proc.shifter_operand.register_shift.rm = rm;
1857  instruction->info.data_proc.shifter_operand.register_shift.shift = shift;
1858 
1859  if (shift == 0x0) /* LSL */
1860  snprintf(shifter_operand, 32, "r%i, LSL r%i", rm, rs);
1861  else if (shift == 0x1) /* LSR */
1862  snprintf(shifter_operand, 32, "r%i, LSR r%i", rm, rs);
1863  else if (shift == 0x2) /* ASR */
1864  snprintf(shifter_operand, 32, "r%i, ASR r%i", rm, rs);
1865  else if (shift == 0x3) /* ROR */
1866  snprintf(shifter_operand, 32, "r%i, ROR r%i", rm, rs);
1867  }
1868  }
1869 
1870  if ((op < 0x8) || (op == 0xc) || (op == 0xe)) { /* <opcode3>{<cond>}{S} <Rd>, <Rn>,
1871  *<shifter_operand> */
1872  snprintf(instruction->text,
1873  128,
1874  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, r%i, %s",
1875  address,
1876  opcode,
1877  mnemonic,
1878  COND(opcode),
1879  (s) ? "S" : "",
1880  rd,
1881  rn,
1882  shifter_operand);
1883  } else if ((op == 0xd) || (op == 0xf)) { /* <opcode1>{<cond>}{S} <Rd>,
1884  *<shifter_operand> */
1885  if (opcode == 0xe1a00000) /* print MOV r0,r0 as NOP */
1886  snprintf(instruction->text,
1887  128,
1888  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tNOP",
1889  address,
1890  opcode);
1891  else
1892  snprintf(instruction->text,
1893  128,
1894  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s%s r%i, %s",
1895  address,
1896  opcode,
1897  mnemonic,
1898  COND(opcode),
1899  (s) ? "S" : "",
1900  rd,
1901  shifter_operand);
1902  } else {/* <opcode2>{<cond>} <Rn>, <shifter_operand> */
1903  snprintf(instruction->text, 128, "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\t%s%s r%i, %s",
1904  address, opcode, mnemonic, COND(opcode),
1905  rn, shifter_operand);
1906  }
1907 
1908  return ERROR_OK;
1909 }
1910 
1911 int arm_evaluate_opcode(uint32_t opcode, uint32_t address,
1912  struct arm_instruction *instruction)
1913 {
1914  /* clear fields, to avoid confusion */
1915  memset(instruction, 0, sizeof(struct arm_instruction));
1916  instruction->opcode = opcode;
1917  instruction->instruction_size = 4;
1918 
1919  /* catch opcodes with condition field [31:28] = b1111 */
1920  if ((opcode & 0xf0000000) == 0xf0000000) {
1921  /* Undefined instruction (or ARMv5E cache preload PLD) */
1922  if ((opcode & 0x08000000) == 0x00000000)
1923  return evaluate_pld(opcode, address, instruction);
1924 
1925  /* Undefined instruction (or ARMv6+ SRS/RFE) */
1926  if ((opcode & 0x0e000000) == 0x08000000)
1927  return evaluate_srs(opcode, address, instruction);
1928 
1929  /* Branch and branch with link and change to Thumb */
1930  if ((opcode & 0x0e000000) == 0x0a000000)
1931  return evaluate_blx_imm(opcode, address, instruction);
1932 
1933  /* Extended coprocessor opcode space (ARMv5 and higher)
1934  * Coprocessor load/store and double register transfers */
1935  if ((opcode & 0x0e000000) == 0x0c000000)
1936  return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
1937 
1938  /* Coprocessor data processing */
1939  if ((opcode & 0x0f000100) == 0x0c000000)
1940  return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1941 
1942  /* Coprocessor register transfers */
1943  if ((opcode & 0x0f000010) == 0x0c000010)
1944  return evaluate_cdp_mcr_mrc(opcode, address, instruction);
1945 
1946  /* Undefined instruction */
1947  if ((opcode & 0x0f000000) == 0x0f000000) {
1948  instruction->type = ARM_UNDEFINED_INSTRUCTION;
1949  snprintf(instruction->text,
1950  128,
1951  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEFINED INSTRUCTION",
1952  address,
1953  opcode);
1954  return ERROR_OK;
1955  }
1956  }
1957 
1958  /* catch opcodes with [27:25] = b000 */
1959  if ((opcode & 0x0e000000) == 0x00000000) {
1960  /* Multiplies, extra load/stores */
1961  if ((opcode & 0x00000090) == 0x00000090)
1962  return evaluate_mul_and_extra_ld_st(opcode, address, instruction);
1963 
1964  /* Miscellaneous instructions */
1965  if ((opcode & 0x0f900000) == 0x01000000)
1966  return evaluate_misc_instr(opcode, address, instruction);
1967 
1968  return evaluate_data_proc(opcode, address, instruction);
1969  }
1970 
1971  /* catch opcodes with [27:25] = b001 */
1972  if ((opcode & 0x0e000000) == 0x02000000) {
1973  /* 16-bit immediate load */
1974  if ((opcode & 0x0fb00000) == 0x03000000)
1975  return evaluate_mov_imm(opcode, address, instruction);
1976 
1977  /* Move immediate to status register */
1978  if ((opcode & 0x0fb00000) == 0x03200000)
1979  return evaluate_mrs_msr(opcode, address, instruction);
1980 
1981  return evaluate_data_proc(opcode, address, instruction);
1982 
1983  }
1984 
1985  /* catch opcodes with [27:25] = b010 */
1986  if ((opcode & 0x0e000000) == 0x04000000) {
1987  /* Load/store immediate offset */
1988  return evaluate_load_store(opcode, address, instruction);
1989  }
1990 
1991  /* catch opcodes with [27:25] = b011 */
1992  if ((opcode & 0x0e000000) == 0x06000000) {
1993  /* Load/store register offset */
1994  if ((opcode & 0x00000010) == 0x00000000)
1995  return evaluate_load_store(opcode, address, instruction);
1996 
1997  /* Architecturally Undefined instruction
1998  * ... don't expect these to ever be used
1999  */
2000  if ((opcode & 0x07f000f0) == 0x07f000f0) {
2001  instruction->type = ARM_UNDEFINED_INSTRUCTION;
2002  snprintf(instruction->text, 128,
2003  "0x%8.8" PRIx32 "\t0x%8.8" PRIx32 "\tUNDEF",
2004  address, opcode);
2005  return ERROR_OK;
2006  }
2007 
2008  /* "media" instructions */
2009  return evaluate_media(opcode, address, instruction);
2010  }
2011 
2012  /* catch opcodes with [27:25] = b100 */
2013  if ((opcode & 0x0e000000) == 0x08000000) {
2014  /* Load/store multiple */
2015  return evaluate_ldm_stm(opcode, address, instruction);
2016  }
2017 
2018  /* catch opcodes with [27:25] = b101 */
2019  if ((opcode & 0x0e000000) == 0x0a000000) {
2020  /* Branch and branch with link */
2021  return evaluate_b_bl(opcode, address, instruction);
2022  }
2023 
2024  /* catch opcodes with [27:25] = b110 */
2025  if ((opcode & 0x0e000000) == 0x0c000000) {
2026  /* Coprocessor load/store and double register transfers */
2027  return evaluate_ldc_stc_mcrr_mrrc(opcode, address, instruction);
2028  }
2029 
2030  /* catch opcodes with [27:25] = b111 */
2031  if ((opcode & 0x0e000000) == 0x0e000000) {
2032  /* Software interrupt */
2033  if ((opcode & 0x0f000000) == 0x0f000000)
2034  return evaluate_swi(opcode, address, instruction);
2035 
2036  /* Coprocessor data processing */
2037  if ((opcode & 0x0f000010) == 0x0e000000)
2038  return evaluate_cdp_mcr_mrc(opcode, address, instruction);
2039 
2040  /* Coprocessor register transfers */
2041  if ((opcode & 0x0f000010) == 0x0e000010)
2042  return evaluate_cdp_mcr_mrc(opcode, address, instruction);
2043  }
2044 
2045  LOG_ERROR("ARM: should never reach this point (opcode=%08" PRIx32 ")", opcode);
2046  return -1;
2047 }
2048 
2049 static int evaluate_b_bl_blx_thumb(uint16_t opcode,
2050  uint32_t address, struct arm_instruction *instruction)
2051 {
2052  uint32_t offset = opcode & 0x7ff;
2053  uint32_t opc = (opcode >> 11) & 0x3;
2054  uint32_t target_address;
2055  char *mnemonic = NULL;
2056 
2057  /* sign extend 11-bit offset */
2058  if (((opc == 0) || (opc == 2)) && (offset & 0x00000400))
2059  offset = 0xfffff800 | offset;
2060 
2061  target_address = address + 4 + (offset << 1);
2062 
2063  switch (opc) {
2064  /* unconditional branch */
2065  case 0:
2066  instruction->type = ARM_B;
2067  mnemonic = "B";
2068  break;
2069  /* BLX suffix */
2070  case 1:
2071  instruction->type = ARM_BLX;
2072  mnemonic = "BLX";
2073  target_address &= 0xfffffffc;
2074  break;
2075  /* BL/BLX prefix */
2076  case 2:
2077  instruction->type = ARM_UNKNOWN_INSTRUCTION;
2078  mnemonic = "prefix";
2079  target_address = offset << 12;
2080  break;
2081  /* BL suffix */
2082  case 3:
2083  instruction->type = ARM_BL;
2084  mnemonic = "BL";
2085  break;
2086  }
2087 
2088  /* TODO: deal correctly with dual opcode (prefixed) BL/BLX;
2089  * these are effectively 32-bit instructions even in Thumb1. For
2090  * disassembly, it's simplest to always use the Thumb2 decoder.
2091  *
2092  * But some cores will evidently handle them as two instructions,
2093  * where exceptions may occur between the two. The ETMv3.2+ ID
2094  * register has a bit which exposes this behavior.
2095  */
2096 
2097  snprintf(instruction->text, 128,
2098  "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%#8.8" PRIx32,
2099  address, opcode, mnemonic, target_address);
2100 
2101  instruction->info.b_bl_bx_blx.reg_operand = -1;
2102  instruction->info.b_bl_bx_blx.target_address = target_address;
2103 
2104  return ERROR_OK;
2105 }
2106 
2107 static int evaluate_add_sub_thumb(uint16_t opcode,
2108  uint32_t address, struct arm_instruction *instruction)
2109 {
2110  uint8_t rd = (opcode >> 0) & 0x7;
2111  uint8_t rn = (opcode >> 3) & 0x7;
2112  uint8_t rm_imm = (opcode >> 6) & 0x7;
2113  uint32_t opc = opcode & (1 << 9);
2114  uint32_t reg_imm = opcode & (1 << 10);
2115  char *mnemonic;
2116 
2117  if (opc) {
2118  instruction->type = ARM_SUB;
2119  mnemonic = "SUBS";
2120  } else {
2121  /* REVISIT: if reg_imm == 0, display as "MOVS" */
2122  instruction->type = ARM_ADD;
2123  mnemonic = "ADDS";
2124  }
2125 
2126  instruction->info.data_proc.rd = rd;
2127  instruction->info.data_proc.rn = rn;
2128  instruction->info.data_proc.s = 1;
2129 
2130  if (reg_imm) {
2131  instruction->info.data_proc.variant = 0;/*immediate*/
2132  instruction->info.data_proc.shifter_operand.immediate.immediate = rm_imm;
2133  snprintf(instruction->text, 128,
2134  "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%d",
2135  address, opcode, mnemonic, rd, rn, rm_imm);
2136  } else {
2137  instruction->info.data_proc.variant = 1;/*immediate shift*/
2138  instruction->info.data_proc.shifter_operand.immediate_shift.rm = rm_imm;
2139  snprintf(instruction->text, 128,
2140  "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, r%i",
2141  address, opcode, mnemonic, rd, rn, rm_imm);
2142  }
2143 
2144  return ERROR_OK;
2145 }
2146 
2147 static int evaluate_shift_imm_thumb(uint16_t opcode,
2148  uint32_t address, struct arm_instruction *instruction)
2149 {
2150  uint8_t rd = (opcode >> 0) & 0x7;
2151  uint8_t rm = (opcode >> 3) & 0x7;
2152  uint8_t imm = (opcode >> 6) & 0x1f;
2153  uint8_t opc = (opcode >> 11) & 0x3;
2154  char *mnemonic = NULL;
2155 
2156  switch (opc) {
2157  case 0:
2158  instruction->type = ARM_MOV;
2159  mnemonic = "LSLS";
2161  break;
2162  case 1:
2163  instruction->type = ARM_MOV;
2164  mnemonic = "LSRS";
2166  break;
2167  case 2:
2168  instruction->type = ARM_MOV;
2169  mnemonic = "ASRS";
2171  break;
2172  }
2173 
2174  if ((imm == 0) && (opc != 0))
2175  imm = 32;
2176 
2177  instruction->info.data_proc.rd = rd;
2178  instruction->info.data_proc.rn = -1;
2179  instruction->info.data_proc.s = 1;
2180 
2181  instruction->info.data_proc.variant = 1;/*immediate_shift*/
2182  instruction->info.data_proc.shifter_operand.immediate_shift.rm = rm;
2184 
2185  snprintf(instruction->text, 128,
2186  "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i, #%#2.2x",
2187  address, opcode, mnemonic, rd, rm, imm);
2188 
2189  return ERROR_OK;
2190 }
2191 
2192 static int evaluate_data_proc_imm_thumb(uint16_t opcode,
2193  uint32_t address, struct arm_instruction *instruction)
2194 {
2195  uint8_t imm = opcode & 0xff;
2196  uint8_t rd = (opcode >> 8) & 0x7;
2197  uint32_t opc = (opcode >> 11) & 0x3;
2198  char *mnemonic = NULL;
2199 
2200  instruction->info.data_proc.rd = rd;
2201  instruction->info.data_proc.rn = rd;
2202  instruction->info.data_proc.s = 1;
2203  instruction->info.data_proc.variant = 0;/*immediate*/
2204  instruction->info.data_proc.shifter_operand.immediate.immediate = imm;
2205 
2206  switch (opc) {
2207  case 0:
2208  instruction->type = ARM_MOV;
2209  mnemonic = "MOVS";
2210  instruction->info.data_proc.rn = -1;
2211  break;
2212  case 1:
2213  instruction->type = ARM_CMP;
2214  mnemonic = "CMP";
2215  instruction->info.data_proc.rd = -1;
2216  break;
2217  case 2:
2218  instruction->type = ARM_ADD;
2219  mnemonic = "ADDS";
2220  break;
2221  case 3:
2222  instruction->type = ARM_SUB;
2223  mnemonic = "SUBS";
2224  break;
2225  }
2226 
2227  snprintf(instruction->text, 128,
2228  "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, #%#2.2x",
2229  address, opcode, mnemonic, rd, imm);
2230 
2231  return ERROR_OK;
2232 }
2233 
2234 static int evaluate_data_proc_thumb(uint16_t opcode,
2235  uint32_t address, struct arm_instruction *instruction)
2236 {
2237  uint8_t high_reg, op, rm, rd, h1, h2;
2238  char *mnemonic = NULL;
2239  bool nop = false;
2240 
2241  high_reg = (opcode & 0x0400) >> 10;
2242  op = (opcode & 0x03C0) >> 6;
2243 
2244  rd = (opcode & 0x0007);
2245  rm = (opcode & 0x0038) >> 3;
2246  h1 = (opcode & 0x0080) >> 7;
2247  h2 = (opcode & 0x0040) >> 6;
2248 
2249  instruction->info.data_proc.rd = rd;
2250  instruction->info.data_proc.rn = rd;
2251  instruction->info.data_proc.s = (!high_reg || (instruction->type == ARM_CMP));
2252  instruction->info.data_proc.variant = 1 /*immediate shift*/;
2253  instruction->info.data_proc.shifter_operand.immediate_shift.rm = rm;
2254 
2255  if (high_reg) {
2256  rd |= h1 << 3;
2257  rm |= h2 << 3;
2258  op >>= 2;
2259 
2260  switch (op) {
2261  case 0x0:
2262  instruction->type = ARM_ADD;
2263  mnemonic = "ADD";
2264  break;
2265  case 0x1:
2266  instruction->type = ARM_CMP;
2267  mnemonic = "CMP";
2268  break;
2269  case 0x2:
2270  instruction->type = ARM_MOV;
2271  mnemonic = "MOV";
2272  if (rd == rm)
2273  nop = true;
2274  break;
2275  case 0x3:
2276  if ((opcode & 0x7) == 0x0) {
2277  instruction->info.b_bl_bx_blx.reg_operand = rm;
2278  if (h1) {
2279  instruction->type = ARM_BLX;
2280  snprintf(instruction->text, 128,
2281  "0x%8.8" PRIx32
2282  " 0x%4.4x \tBLX\tr%i",
2283  address, opcode, rm);
2284  } else {
2285  instruction->type = ARM_BX;
2286  snprintf(instruction->text, 128,
2287  "0x%8.8" PRIx32
2288  " 0x%4.4x \tBX\tr%i",
2289  address, opcode, rm);
2290  }
2291  } else {
2292  instruction->type = ARM_UNDEFINED_INSTRUCTION;
2293  snprintf(instruction->text, 128,
2294  "0x%8.8" PRIx32
2295  " 0x%4.4x \t"
2296  "UNDEFINED INSTRUCTION",
2297  address, opcode);
2298  }
2299  return ERROR_OK;
2300  }
2301  } else {
2302  switch (op) {
2303  case 0x0:
2304  instruction->type = ARM_AND;
2305  mnemonic = "ANDS";
2306  break;
2307  case 0x1:
2308  instruction->type = ARM_EOR;
2309  mnemonic = "EORS";
2310  break;
2311  case 0x2:
2312  instruction->type = ARM_MOV;
2313  mnemonic = "LSLS";
2314  instruction->info.data_proc.variant = 2 /*register shift*/;
2316  instruction->info.data_proc.shifter_operand.register_shift.rm = rd;
2317  instruction->info.data_proc.shifter_operand.register_shift.rs = rm;
2318  break;
2319  case 0x3:
2320  instruction->type = ARM_MOV;
2321  mnemonic = "LSRS";
2322  instruction->info.data_proc.variant = 2 /*register shift*/;
2324  instruction->info.data_proc.shifter_operand.register_shift.rm = rd;
2325  instruction->info.data_proc.shifter_operand.register_shift.rs = rm;
2326  break;
2327  case 0x4:
2328  instruction->type = ARM_MOV;
2329  mnemonic = "ASRS";
2330  instruction->info.data_proc.variant = 2 /*register shift*/;
2332  instruction->info.data_proc.shifter_operand.register_shift.rm = rd;
2333  instruction->info.data_proc.shifter_operand.register_shift.rs = rm;
2334  break;
2335  case 0x5:
2336  instruction->type = ARM_ADC;
2337  mnemonic = "ADCS";
2338  break;
2339  case 0x6:
2340  instruction->type = ARM_SBC;
2341  mnemonic = "SBCS";
2342  break;
2343  case 0x7:
2344  instruction->type = ARM_MOV;
2345  mnemonic = "RORS";
2346  instruction->info.data_proc.variant = 2 /*register shift*/;
2348  instruction->info.data_proc.shifter_operand.register_shift.rm = rd;
2349  instruction->info.data_proc.shifter_operand.register_shift.rs = rm;
2350  break;
2351  case 0x8:
2352  instruction->type = ARM_TST;
2353  mnemonic = "TST";
2354  break;
2355  case 0x9:
2356  instruction->type = ARM_RSB;
2357  mnemonic = "RSBS";
2358  instruction->info.data_proc.variant = 0 /*immediate*/;
2359  instruction->info.data_proc.shifter_operand.immediate.immediate = 0;
2360  instruction->info.data_proc.rn = rm;
2361  break;
2362  case 0xA:
2363  instruction->type = ARM_CMP;
2364  mnemonic = "CMP";
2365  break;
2366  case 0xB:
2367  instruction->type = ARM_CMN;
2368  mnemonic = "CMN";
2369  break;
2370  case 0xC:
2371  instruction->type = ARM_ORR;
2372  mnemonic = "ORRS";
2373  break;
2374  case 0xD:
2375  instruction->type = ARM_MUL;
2376  mnemonic = "MULS";
2377  break;
2378  case 0xE:
2379  instruction->type = ARM_BIC;
2380  mnemonic = "BICS";
2381  break;
2382  case 0xF:
2383  instruction->type = ARM_MVN;
2384  mnemonic = "MVNS";
2385  break;
2386  }
2387  }
2388 
2389  if (nop)
2390  snprintf(instruction->text, 128,
2391  "0x%8.8" PRIx32 " 0x%4.4x \tNOP\t\t\t"
2392  "; (%s r%i, r%i)",
2393  address, opcode, mnemonic, rd, rm);
2394  else
2395  snprintf(instruction->text, 128,
2396  "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, r%i",
2397  address, opcode, mnemonic, rd, rm);
2398 
2399  return ERROR_OK;
2400 }
2401 
2402 /* PC-relative data addressing is word-aligned even with Thumb */
2403 static inline uint32_t thumb_alignpc4(uint32_t addr)
2404 {
2405  return (addr + 4) & ~3;
2406 }
2407 
2408 static int evaluate_load_literal_thumb(uint16_t opcode,
2409  uint32_t address, struct arm_instruction *instruction)
2410 {
2411  uint32_t immediate;
2412  uint8_t rd = (opcode >> 8) & 0x7;
2413 
2414  instruction->type = ARM_LDR;
2415  immediate = opcode & 0x000000ff;
2416  immediate *= 4;
2417 
2418  instruction->info.load_store.rd = rd;
2419  instruction->info.load_store.rn = 15 /*PC*/;
2420  instruction->info.load_store.index_mode = 0; /*offset*/
2421  instruction->info.load_store.offset_mode = 0; /*immediate*/
2422  instruction->info.load_store.offset.offset = immediate;
2423 
2424  snprintf(instruction->text, 128,
2425  "0x%8.8" PRIx32 " 0x%4.4x \t"
2426  "LDR\tr%i, [pc, #%#" PRIx32 "]\t; %#8.8" PRIx32,
2427  address, opcode, rd, immediate,
2428  thumb_alignpc4(address) + immediate);
2429 
2430  return ERROR_OK;
2431 }
2432 
2433 static int evaluate_load_store_reg_thumb(uint16_t opcode,
2434  uint32_t address, struct arm_instruction *instruction)
2435 {
2436  uint8_t rd = (opcode >> 0) & 0x7;
2437  uint8_t rn = (opcode >> 3) & 0x7;
2438  uint8_t rm = (opcode >> 6) & 0x7;
2439  uint8_t opc = (opcode >> 9) & 0x7;
2440  char *mnemonic = NULL;
2441 
2442  switch (opc) {
2443  case 0:
2444  instruction->type = ARM_STR;
2445  mnemonic = "STR";
2446  break;
2447  case 1:
2448  instruction->type = ARM_STRH;
2449  mnemonic = "STRH";
2450  break;
2451  case 2:
2452  instruction->type = ARM_STRB;
2453  mnemonic = "STRB";
2454  break;
2455  case 3:
2456  instruction->type = ARM_LDRSB;
2457  mnemonic = "LDRSB";
2458  break;
2459  case 4:
2460  instruction->type = ARM_LDR;
2461  mnemonic = "LDR";
2462  break;
2463  case 5:
2464  instruction->type = ARM_LDRH;
2465  mnemonic = "LDRH";
2466  break;
2467  case 6:
2468  instruction->type = ARM_LDRB;
2469  mnemonic = "LDRB";
2470  break;
2471  case 7:
2472  instruction->type = ARM_LDRSH;
2473  mnemonic = "LDRSH";
2474  break;
2475  }
2476 
2477  snprintf(instruction->text, 128,
2478  "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [r%i, r%i]",
2479  address, opcode, mnemonic, rd, rn, rm);
2480 
2481  instruction->info.load_store.rd = rd;
2482  instruction->info.load_store.rn = rn;
2483  instruction->info.load_store.index_mode = 0; /*offset*/
2484  instruction->info.load_store.offset_mode = 1; /*register*/
2485  instruction->info.load_store.offset.reg.rm = rm;
2486 
2487  return ERROR_OK;
2488 }
2489 
2490 static int evaluate_load_store_imm_thumb(uint16_t opcode,
2491  uint32_t address, struct arm_instruction *instruction)
2492 {
2493  uint32_t offset = (opcode >> 6) & 0x1f;
2494  uint8_t rd = (opcode >> 0) & 0x7;
2495  uint8_t rn = (opcode >> 3) & 0x7;
2496  uint32_t l = opcode & (1 << 11);
2497  uint32_t b = opcode & (1 << 12);
2498  char *mnemonic;
2499  char suffix = ' ';
2500  uint32_t shift = 2;
2501 
2502  if (l) {
2503  instruction->type = ARM_LDR;
2504  mnemonic = "LDR";
2505  } else {
2506  instruction->type = ARM_STR;
2507  mnemonic = "STR";
2508  }
2509 
2510  if ((opcode&0xF000) == 0x8000) {
2511  suffix = 'H';
2512  shift = 1;
2513  } else if (b) {
2514  suffix = 'B';
2515  shift = 0;
2516  }
2517 
2518  snprintf(instruction->text, 128,
2519  "0x%8.8" PRIx32 " 0x%4.4x \t%s%c\tr%i, [r%i, #%#" PRIx32 "]",
2520  address, opcode, mnemonic, suffix, rd, rn, offset << shift);
2521 
2522  instruction->info.load_store.rd = rd;
2523  instruction->info.load_store.rn = rn;
2524  instruction->info.load_store.index_mode = 0; /*offset*/
2525  instruction->info.load_store.offset_mode = 0; /*immediate*/
2526  instruction->info.load_store.offset.offset = offset << shift;
2527 
2528  return ERROR_OK;
2529 }
2530 
2531 static int evaluate_load_store_stack_thumb(uint16_t opcode,
2532  uint32_t address, struct arm_instruction *instruction)
2533 {
2534  uint32_t offset = opcode & 0xff;
2535  uint8_t rd = (opcode >> 8) & 0x7;
2536  uint32_t l = opcode & (1 << 11);
2537  char *mnemonic;
2538 
2539  if (l) {
2540  instruction->type = ARM_LDR;
2541  mnemonic = "LDR";
2542  } else {
2543  instruction->type = ARM_STR;
2544  mnemonic = "STR";
2545  }
2546 
2547  snprintf(instruction->text, 128,
2548  "0x%8.8" PRIx32 " 0x%4.4x \t%s\tr%i, [SP, #%#" PRIx32 "]",
2549  address, opcode, mnemonic, rd, offset*4);
2550 
2551  instruction->info.load_store.rd = rd;
2552  instruction->info.load_store.rn = 13 /*SP*/;
2553  instruction->info.load_store.index_mode = 0; /*offset*/
2554  instruction->info.load_store.offset_mode = 0; /*immediate*/
2555  instruction->info.load_store.offset.offset = offset*4;
2556 
2557  return ERROR_OK;
2558 }
2559 
2560 static int evaluate_add_sp_pc_thumb(uint16_t opcode,
2561  uint32_t address, struct arm_instruction *instruction)
2562 {
2563  uint32_t imm = opcode & 0xff;
2564  uint8_t rd = (opcode >> 8) & 0x7;
2565  uint8_t rn;
2566  uint32_t sp = opcode & (1 << 11);
2567  const char *reg_name;
2568 
2569  instruction->type = ARM_ADD;
2570 
2571  if (sp) {
2572  reg_name = "SP";
2573  rn = 13;
2574  } else {
2575  reg_name = "PC";
2576  rn = 15;
2577  }
2578 
2579  snprintf(instruction->text, 128,
2580  "0x%8.8" PRIx32 " 0x%4.4x \tADD\tr%i, %s, #%#" PRIx32,
2581  address, opcode, rd, reg_name, imm * 4);
2582 
2583  instruction->info.data_proc.variant = 0 /* immediate */;
2584  instruction->info.data_proc.rd = rd;
2585  instruction->info.data_proc.rn = rn;
2586  instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
2587 
2588  return ERROR_OK;
2589 }
2590 
2591 static int evaluate_adjust_stack_thumb(uint16_t opcode,
2592  uint32_t address, struct arm_instruction *instruction)
2593 {
2594  uint32_t imm = opcode & 0x7f;
2595  uint8_t opc = opcode & (1 << 7);
2596  char *mnemonic;
2597 
2598 
2599  if (opc) {
2600  instruction->type = ARM_SUB;
2601  mnemonic = "SUB";
2602  } else {
2603  instruction->type = ARM_ADD;
2604  mnemonic = "ADD";
2605  }
2606 
2607  snprintf(instruction->text, 128,
2608  "0x%8.8" PRIx32 " 0x%4.4x \t%s\tSP, #%#" PRIx32,
2609  address, opcode, mnemonic, imm*4);
2610 
2611  instruction->info.data_proc.variant = 0 /* immediate */;
2612  instruction->info.data_proc.rd = 13 /*SP*/;
2613  instruction->info.data_proc.rn = 13 /*SP*/;
2614  instruction->info.data_proc.shifter_operand.immediate.immediate = imm*4;
2615 
2616  return ERROR_OK;
2617 }
2618 
2619 static int evaluate_breakpoint_thumb(uint16_t opcode,
2620  uint32_t address, struct arm_instruction *instruction)
2621 {
2622  uint32_t imm = opcode & 0xff;
2623 
2624  instruction->type = ARM_BKPT;
2625 
2626  snprintf(instruction->text, 128,
2627  "0x%8.8" PRIx32 " 0x%4.4x \tBKPT\t%#2.2" PRIx32,
2628  address, opcode, imm);
2629 
2630  return ERROR_OK;
2631 }
2632 
2633 static int evaluate_load_store_multiple_thumb(uint16_t opcode,
2634  uint32_t address, struct arm_instruction *instruction)
2635 {
2636  uint32_t reg_list = opcode & 0xff;
2637  uint32_t l = opcode & (1 << 11);
2638  uint32_t r = opcode & (1 << 8);
2639  uint8_t rn = (opcode >> 8) & 7;
2640  uint8_t addr_mode = 0 /* IA */;
2641  char reg_names[40];
2642  char *reg_names_p;
2643  char *mnemonic;
2644  char ptr_name[7] = "";
2645  int i;
2646 
2647  /* REVISIT: in ThumbEE mode, there are no LDM or STM instructions.
2648  * The STMIA and LDMIA opcodes are used for other instructions.
2649  */
2650 
2651  if ((opcode & 0xf000) == 0xc000) { /* generic load/store multiple */
2652  char *wback = "!";
2653 
2654  if (l) {
2655  instruction->type = ARM_LDM;
2656  mnemonic = "LDM";
2657  if (opcode & (1 << rn))
2658  wback = "";
2659  } else {
2660  instruction->type = ARM_STM;
2661  mnemonic = "STM";
2662  }
2663  snprintf(ptr_name, sizeof(ptr_name), "r%i%s, ", rn, wback);
2664  } else {/* push/pop */
2665  rn = 13;/* SP */
2666  if (l) {
2667  instruction->type = ARM_LDM;
2668  mnemonic = "POP";
2669  if (r)
2670  reg_list |= (1 << 15) /*PC*/;
2671  } else {
2672  instruction->type = ARM_STM;
2673  mnemonic = "PUSH";
2674  addr_mode = 3; /*DB*/
2675  if (r)
2676  reg_list |= (1 << 14) /*LR*/;
2677  }
2678  }
2679 
2680  reg_names_p = reg_names;
2681  for (i = 0; i <= 15; i++) {
2682  if (reg_list & (1 << i))
2683  reg_names_p += snprintf(reg_names_p,
2684  (reg_names + 40 - reg_names_p),
2685  "r%i, ",
2686  i);
2687  }
2688  if (reg_names_p > reg_names)
2689  reg_names_p[-2] = '\0';
2690  else /* invalid op : no registers */
2691  reg_names[0] = '\0';
2692 
2693  snprintf(instruction->text, 128,
2694  "0x%8.8" PRIx32 " 0x%4.4x \t%s\t%s{%s}",
2695  address, opcode, mnemonic, ptr_name, reg_names);
2696 
2697  instruction->info.load_store_multiple.register_list = reg_list;
2698  instruction->info.load_store_multiple.rn = rn;
2699  instruction->info.load_store_multiple.addressing_mode = addr_mode;
2700 
2701  return ERROR_OK;
2702 }
2703 
2704 static int evaluate_cond_branch_thumb(uint16_t opcode,
2705  uint32_t address, struct arm_instruction *instruction)
2706 {
2707  uint32_t offset = opcode & 0xff;
2708  uint8_t cond = (opcode >> 8) & 0xf;
2709  uint32_t target_address;
2710 
2711  if (cond == 0xf) {
2712  instruction->type = ARM_SWI;
2713  snprintf(instruction->text, 128,
2714  "0x%8.8" PRIx32 " 0x%4.4x \tSVC\t%#2.2" PRIx32,
2715  address, opcode, offset);
2716  return ERROR_OK;
2717  } else if (cond == 0xe) {
2718  instruction->type = ARM_UNDEFINED_INSTRUCTION;
2719  snprintf(instruction->text, 128,
2720  "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2721  address, opcode);
2722  return ERROR_OK;
2723  }
2724 
2725  /* sign extend 8-bit offset */
2726  if (offset & 0x00000080)
2727  offset = 0xffffff00 | offset;
2728 
2729  target_address = address + 4 + (offset << 1);
2730 
2731  snprintf(instruction->text, 128,
2732  "0x%8.8" PRIx32 " 0x%4.4x \tB%s\t%#8.8" PRIx32,
2733  address, opcode,
2734  arm_condition_strings[cond], target_address);
2735 
2736  instruction->type = ARM_B;
2737  instruction->info.b_bl_bx_blx.reg_operand = -1;
2738  instruction->info.b_bl_bx_blx.target_address = target_address;
2739 
2740  return ERROR_OK;
2741 }
2742 
2743 static int evaluate_cb_thumb(uint16_t opcode, uint32_t address,
2744  struct arm_instruction *instruction)
2745 {
2746  unsigned int offset;
2747 
2748  /* added in Thumb2 */
2749  offset = (opcode >> 3) & 0x1f;
2750  offset |= (opcode & 0x0200) >> 4;
2751 
2752  snprintf(instruction->text, 128,
2753  "0x%8.8" PRIx32 " 0x%4.4x \tCB%sZ\tr%d, %#8.8" PRIx32,
2754  address, opcode,
2755  (opcode & 0x0800) ? "N" : "",
2756  opcode & 0x7, address + 4 + (offset << 1));
2757 
2758  return ERROR_OK;
2759 }
2760 
2761 static int evaluate_extend_thumb(uint16_t opcode, uint32_t address,
2762  struct arm_instruction *instruction)
2763 {
2764  /* added in ARMv6 */
2765  snprintf(instruction->text, 128,
2766  "0x%8.8" PRIx32 " 0x%4.4x \t%cXT%c\tr%d, r%d",
2767  address, opcode,
2768  (opcode & 0x0080) ? 'U' : 'S',
2769  (opcode & 0x0040) ? 'B' : 'H',
2770  opcode & 0x7, (opcode >> 3) & 0x7);
2771 
2772  return ERROR_OK;
2773 }
2774 
2775 static int evaluate_cps_thumb(uint16_t opcode, uint32_t address,
2776  struct arm_instruction *instruction)
2777 {
2778  /* added in ARMv6 */
2779  if ((opcode & 0x0ff0) == 0x0650)
2780  snprintf(instruction->text, 128,
2781  "0x%8.8" PRIx32 " 0x%4.4x \tSETEND %s",
2782  address, opcode,
2783  (opcode & 0x80) ? "BE" : "LE");
2784  else /* ASSUME (opcode & 0x0fe0) == 0x0660 */
2785  snprintf(instruction->text, 128,
2786  "0x%8.8" PRIx32 " 0x%4.4x \tCPSI%c\t%s%s%s",
2787  address, opcode,
2788  (opcode & 0x0010) ? 'D' : 'E',
2789  (opcode & 0x0004) ? "A" : "",
2790  (opcode & 0x0002) ? "I" : "",
2791  (opcode & 0x0001) ? "F" : "");
2792 
2793  return ERROR_OK;
2794 }
2795 
2796 static int evaluate_byterev_thumb(uint16_t opcode, uint32_t address,
2797  struct arm_instruction *instruction)
2798 {
2799  char *suffix;
2800 
2801  /* added in ARMv6 */
2802  switch ((opcode >> 6) & 3) {
2803  case 0:
2804  suffix = "";
2805  break;
2806  case 1:
2807  suffix = "16";
2808  break;
2809  default:
2810  suffix = "SH";
2811  break;
2812  }
2813  snprintf(instruction->text, 128,
2814  "0x%8.8" PRIx32 " 0x%4.4x \tREV%s\tr%d, r%d",
2815  address, opcode, suffix,
2816  opcode & 0x7, (opcode >> 3) & 0x7);
2817 
2818  return ERROR_OK;
2819 }
2820 
2821 static int evaluate_hint_thumb(uint16_t opcode, uint32_t address,
2822  struct arm_instruction *instruction)
2823 {
2824  char *hint;
2825 
2826  switch ((opcode >> 4) & 0x0f) {
2827  case 0:
2828  hint = "NOP";
2829  break;
2830  case 1:
2831  hint = "YIELD";
2832  break;
2833  case 2:
2834  hint = "WFE";
2835  break;
2836  case 3:
2837  hint = "WFI";
2838  break;
2839  case 4:
2840  hint = "SEV";
2841  break;
2842  default:
2843  hint = "HINT (UNRECOGNIZED)";
2844  break;
2845  }
2846 
2847  snprintf(instruction->text, 128,
2848  "0x%8.8" PRIx32 " 0x%4.4x \t%s",
2849  address, opcode, hint);
2850 
2851  return ERROR_OK;
2852 }
2853 
2854 static int evaluate_ifthen_thumb(uint16_t opcode, uint32_t address,
2855  struct arm_instruction *instruction)
2856 {
2857  unsigned int cond = (opcode >> 4) & 0x0f;
2858  char *x = "", *y = "", *z = "";
2859 
2860  if (opcode & 0x01)
2861  z = (opcode & 0x02) ? "T" : "E";
2862  if (opcode & 0x03)
2863  y = (opcode & 0x04) ? "T" : "E";
2864  if (opcode & 0x07)
2865  x = (opcode & 0x08) ? "T" : "E";
2866 
2867  snprintf(instruction->text, 128,
2868  "0x%8.8" PRIx32 " 0x%4.4x \tIT%s%s%s\t%s",
2869  address, opcode,
2870  x, y, z, arm_condition_strings[cond]);
2871 
2872  /* NOTE: strictly speaking, the next 1-4 instructions should
2873  * now be displayed with the relevant conditional suffix...
2874  */
2875 
2876  return ERROR_OK;
2877 }
2878 
2879 int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
2880 {
2881  /* clear fields, to avoid confusion */
2882  memset(instruction, 0, sizeof(struct arm_instruction));
2883  instruction->opcode = opcode;
2884  instruction->instruction_size = 2;
2885 
2886  if ((opcode & 0xe000) == 0x0000) {
2887  /* add/subtract register or immediate */
2888  if ((opcode & 0x1800) == 0x1800)
2889  return evaluate_add_sub_thumb(opcode, address, instruction);
2890  /* shift by immediate */
2891  else
2892  return evaluate_shift_imm_thumb(opcode, address, instruction);
2893  }
2894 
2895  /* Add/subtract/compare/move immediate */
2896  if ((opcode & 0xe000) == 0x2000)
2897  return evaluate_data_proc_imm_thumb(opcode, address, instruction);
2898 
2899  /* Data processing instructions */
2900  if ((opcode & 0xf800) == 0x4000)
2901  return evaluate_data_proc_thumb(opcode, address, instruction);
2902 
2903  /* Load from literal pool */
2904  if ((opcode & 0xf800) == 0x4800)
2905  return evaluate_load_literal_thumb(opcode, address, instruction);
2906 
2907  /* Load/Store register offset */
2908  if ((opcode & 0xf000) == 0x5000)
2909  return evaluate_load_store_reg_thumb(opcode, address, instruction);
2910 
2911  /* Load/Store immediate offset */
2912  if (((opcode & 0xe000) == 0x6000)
2913  || ((opcode & 0xf000) == 0x8000))
2914  return evaluate_load_store_imm_thumb(opcode, address, instruction);
2915 
2916  /* Load/Store from/to stack */
2917  if ((opcode & 0xf000) == 0x9000)
2918  return evaluate_load_store_stack_thumb(opcode, address, instruction);
2919 
2920  /* Add to SP/PC */
2921  if ((opcode & 0xf000) == 0xa000)
2922  return evaluate_add_sp_pc_thumb(opcode, address, instruction);
2923 
2924  /* Misc */
2925  if ((opcode & 0xf000) == 0xb000) {
2926  switch ((opcode >> 8) & 0x0f) {
2927  case 0x0:
2928  return evaluate_adjust_stack_thumb(opcode, address, instruction);
2929  case 0x1:
2930  case 0x3:
2931  case 0x9:
2932  case 0xb:
2933  return evaluate_cb_thumb(opcode, address, instruction);
2934  case 0x2:
2935  return evaluate_extend_thumb(opcode, address, instruction);
2936  case 0x4:
2937  case 0x5:
2938  case 0xc:
2939  case 0xd:
2941  instruction);
2942  case 0x6:
2943  return evaluate_cps_thumb(opcode, address, instruction);
2944  case 0xa:
2945  if ((opcode & 0x00c0) == 0x0080)
2946  break;
2947  return evaluate_byterev_thumb(opcode, address, instruction);
2948  case 0xe:
2949  return evaluate_breakpoint_thumb(opcode, address, instruction);
2950  case 0xf:
2951  if (opcode & 0x000f)
2952  return evaluate_ifthen_thumb(opcode, address,
2953  instruction);
2954  else
2955  return evaluate_hint_thumb(opcode, address,
2956  instruction);
2957  }
2958 
2959  instruction->type = ARM_UNDEFINED_INSTRUCTION;
2960  snprintf(instruction->text, 128,
2961  "0x%8.8" PRIx32 " 0x%4.4x \tUNDEFINED INSTRUCTION",
2962  address, opcode);
2963  return ERROR_OK;
2964  }
2965 
2966  /* Load/Store multiple */
2967  if ((opcode & 0xf000) == 0xc000)
2968  return evaluate_load_store_multiple_thumb(opcode, address, instruction);
2969 
2970  /* Conditional branch + SWI */
2971  if ((opcode & 0xf000) == 0xd000)
2972  return evaluate_cond_branch_thumb(opcode, address, instruction);
2973 
2974  if ((opcode & 0xe000) == 0xe000) {
2975  /* Undefined instructions */
2976  if ((opcode & 0xf801) == 0xe801) {
2977  instruction->type = ARM_UNDEFINED_INSTRUCTION;
2978  snprintf(instruction->text, 128,
2979  "0x%8.8" PRIx32 " 0x%8.8x\t"
2980  "UNDEFINED INSTRUCTION",
2981  address, opcode);
2982  return ERROR_OK;
2983  } else /* Branch to offset */
2984  return evaluate_b_bl_blx_thumb(opcode, address, instruction);
2985  }
2986 
2987  LOG_ERROR("Thumb: should never reach this point (opcode=%04x)", opcode);
2988  return -1;
2989 }
2990 
2991 int arm_access_size(struct arm_instruction *instruction)
2992 {
2993  if ((instruction->type == ARM_LDRB)
2994  || (instruction->type == ARM_LDRBT)
2995  || (instruction->type == ARM_LDRSB)
2996  || (instruction->type == ARM_STRB)
2997  || (instruction->type == ARM_STRBT))
2998  return 1;
2999  else if ((instruction->type == ARM_LDRH)
3000  || (instruction->type == ARM_LDRSH)
3001  || (instruction->type == ARM_STRH))
3002  return 2;
3003  else if ((instruction->type == ARM_LDR)
3004  || (instruction->type == ARM_LDRT)
3005  || (instruction->type == ARM_STR)
3006  || (instruction->type == ARM_STRT))
3007  return 4;
3008  else if ((instruction->type == ARM_LDRD)
3009  || (instruction->type == ARM_STRD))
3010  return 8;
3011  else {
3012  LOG_ERROR("BUG: instruction type %i isn't a load/store instruction",
3013  instruction->type);
3014  return 0;
3015  }
3016 }
static int evaluate_load_store_reg_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
static int evaluate_load_store(uint32_t opcode, uint32_t address, struct arm_instruction *instruction)
static int evaluate_b_bl(uint32_t opcode, uint32_t address, struct arm_instruction *instruction)
static int evaluate_media(uint32_t opcode, uint32_t address, struct arm_instruction *instruction)
static int evaluate_cb_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
static int evaluate_load_store_imm_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
static int evaluate_cdp_mcr_mrc(uint32_t opcode, uint32_t address, struct arm_instruction *instruction)
static uint32_t ror(uint32_t value, int places)
static int evaluate_cond_branch_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
static int evaluate_mov_imm(uint32_t opcode, uint32_t address, struct arm_instruction *instruction)
int arm_evaluate_opcode(uint32_t opcode, uint32_t address, struct arm_instruction *instruction)
static int evaluate_srs(uint32_t opcode, uint32_t address, struct arm_instruction *instruction)
static int evaluate_p_add_sub(uint32_t opcode, uint32_t address, char *cp)
static int evaluate_pld(uint32_t opcode, uint32_t address, struct arm_instruction *instruction)
int thumb_evaluate_opcode(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
static int evaluate_load_literal_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
static int evaluate_breakpoint_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
static int evaluate_extend_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
static int evaluate_data_proc(uint32_t opcode, uint32_t address, struct arm_instruction *instruction)
static int evaluate_misc_load_store(uint32_t opcode, uint32_t address, struct arm_instruction *instruction)
static int evaluate_load_store_multiple_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
static uint32_t thumb_alignpc4(uint32_t addr)
static int evaluate_ldm_stm(uint32_t opcode, uint32_t address, struct arm_instruction *instruction)
static int evaluate_ldc_stc_mcrr_mrrc(uint32_t opcode, uint32_t address, struct arm_instruction *instruction)
static const char * arm_condition_strings[]
static int evaluate_shift_imm_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
int arm_access_size(struct arm_instruction *instruction)
static int evaluate_swi(uint32_t opcode, uint32_t address, struct arm_instruction *instruction)
static int evaluate_cps_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
static int evaluate_blx_imm(uint32_t opcode, uint32_t address, struct arm_instruction *instruction)
static int evaluate_load_store_stack_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
static int evaluate_mul_and_extra_ld_st(uint32_t opcode, uint32_t address, struct arm_instruction *instruction)
static int evaluate_ifthen_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
static int evaluate_data_proc_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
static int evaluate_misc_instr(uint32_t opcode, uint32_t address, struct arm_instruction *instruction)
static int evaluate_data_proc_imm_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
static int evaluate_mrs_msr(uint32_t opcode, uint32_t address, struct arm_instruction *instruction)
static int evaluate_byterev_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
static int evaluate_b_bl_blx_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
static int evaluate_add_sub_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
static int evaluate_unknown(uint32_t opcode, uint32_t address, struct arm_instruction *instruction)
static int evaluate_adjust_stack_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
static int evaluate_add_sp_pc_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
static int evaluate_hint_thumb(uint16_t opcode, uint32_t address, struct arm_instruction *instruction)
static int evaluate_extend(uint32_t opcode, uint32_t address, char *cp)
#define COND(opcode)
@ ARM_SMULWY
@ ARM_LDRSB
@ ARM_QDADD
@ ARM_RSB
@ ARM_MSR
@ ARM_UMLAL
@ ARM_CDP
@ ARM_BIC
@ ARM_ADD
@ ARM_DSB
@ ARM_SMULL
@ ARM_UNKNOWN_INSTRUCTION
@ ARM_STM
@ ARM_SMLAXY
@ ARM_QDSUB
@ ARM_SBC
@ ARM_SMC
@ ARM_SWP
@ ARM_SMULXY
@ ARM_RSC
@ ARM_BX
@ ARM_BL
@ ARM_MCRR
@ ARM_MRRC
@ ARM_UMULL
@ ARM_B
@ ARM_MOV
@ ARM_ERET
@ ARM_UNDEFINED_INSTRUCTION
@ ARM_STRD
@ ARM_BKPT
@ ARM_MRC
@ ARM_STC
@ ARM_HVC
@ ARM_LDC
@ ARM_CMP
@ ARM_MRS
@ ARM_ISB
@ ARM_STRH
@ ARM_TST
@ ARM_MUL
@ ARM_LDR
@ ARM_STRT
@ ARM_LDRB
@ ARM_AND
@ ARM_STRBT
@ ARM_MCR
@ ARM_BLX
@ ARM_ADC
@ ARM_STR
@ ARM_LDM
@ ARM_EOR
@ ARM_LDRSH
@ ARM_SWI
@ ARM_LDRH
@ ARM_LDRBT
@ ARM_STRB
@ ARM_LDRT
@ ARM_SMLAWY
@ ARM_LDRD
@ ARM_SWPB
@ ARM_MLA
@ ARM_PLD
@ ARM_SUB
@ ARM_MVN
@ ARM_ORR
@ ARM_QADD
@ ARM_CLZ
@ ARM_CMN
@ ARM_QSUB
@ ARM_SMLAL
@ ARM_TEQ
enum arm_mode mode
Definition: armv4_5.c:280
uint32_t address
Starting address. Sector aligned.
Definition: dw-spi-helper.h:0
const char * rs
Definition: ecos.c:480
uint8_t type
Definition: esp_usb_jtag.c:0
uint64_t op
Definition: lakemont.c:68
#define ERROR_FAIL
Definition: log.h:188
#define LOG_ERROR(expr ...)
Definition: log.h:147
#define ERROR_OK
Definition: log.h:182
#define sp
Definition: mips32.c:222
target_addr_t addr
Start address to search for the control block.
Definition: rtt/rtt.c:28
union arm_shifter_operand shifter_operand
union arm_instruction::@73 info
struct arm_load_store_multiple_instr load_store_multiple
unsigned int instruction_size
enum arm_instruction_type type
struct arm_b_bl_bx_blx_instr b_bl_bx_blx
struct arm_load_store_instr load_store
struct arm_data_proc_instr data_proc
struct arm_shifter_operand::@70 register_shift
struct arm_shifter_operand::@69 immediate_shift
#define NULL
Definition: usb.h:16
uint8_t offset[4]
Definition: vdebug.c:9