Rizin
unix-like reverse engineering framework and cli tools
ARMInstPrinter.c
Go to the documentation of this file.
1 //===-- ARMInstPrinter.cpp - Convert ARM MCInst to assembly syntax --------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This class prints an ARM MCInst to a .s file.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 /* Capstone Disassembly Engine */
15 /* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2015 */
16 
17 #ifdef CAPSTONE_HAS_ARM
18 
19 #include <stdio.h> // DEBUG
20 #include <stdlib.h>
21 #include <string.h>
22 #include <capstone/platform.h>
23 
24 #include "ARMInstPrinter.h"
25 #include "ARMAddressingModes.h"
26 #include "ARMBaseInfo.h"
27 #include "ARMDisassembler.h"
28 #include "../../MCInst.h"
29 #include "../../SStream.h"
30 #include "../../MCRegisterInfo.h"
31 #include "../../utils.h"
32 #include "ARMMapping.h"
33 
34 #define GET_SUBTARGETINFO_ENUM
35 #include "ARMGenSubtargetInfo.inc"
36 
37 
38 static void printRegName(cs_struct *h, SStream *OS, unsigned RegNo);
39 
40 // Autogenerated by tblgen.
41 static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI);
42 static void printOperand(MCInst *MI, unsigned OpNo, SStream *O);
43 static void printSORegRegOperand(MCInst *MI, unsigned OpNum, SStream *O);
44 static void printSORegImmOperand(MCInst *MI, unsigned OpNum, SStream *O);
45 
46 static void printAddrModeTBB(MCInst *MI, unsigned OpNum, SStream *O);
47 static void printAddrModeTBH(MCInst *MI, unsigned OpNum, SStream *O);
48 static void printAddrMode2Operand(MCInst *MI, unsigned OpNum, SStream *O);
49 static void printAM2PreOrOffsetIndexOp(MCInst *MI, unsigned OpNum, SStream *O);
50 static void printAddrMode2OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O);
51 static void printAddrMode3Operand(MCInst *MI, unsigned OpNum, SStream *O, bool AlwaysPrintImm0);
52 static void printAddrMode3OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O);
53 static void printAM3PreOrOffsetIndexOp(MCInst *MI, unsigned Op, SStream *O, bool AlwaysPrintImm0);
54 static void printPostIdxImm8Operand(MCInst *MI, unsigned OpNum, SStream *O);
55 static void printPostIdxRegOperand(MCInst *MI, unsigned OpNum, SStream *O);
56 static void printPostIdxImm8s4Operand(MCInst *MI, unsigned OpNum, SStream *O);
57 static void printAddrMode5Operand(MCInst *MI, unsigned OpNum, SStream *O, bool AlwaysPrintImm0);
58 static void printAddrMode6Operand(MCInst *MI, unsigned OpNum, SStream *O);
59 static void printAddrMode7Operand(MCInst *MI, unsigned OpNum, SStream *O);
60 static void printAddrMode6OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O);
61 
62 static void printBitfieldInvMaskImmOperand(MCInst *MI, unsigned OpNum, SStream *O);
63 static void printMemBOption(MCInst *MI, unsigned OpNum, SStream *O);
64 static void printShiftImmOperand(MCInst *MI, unsigned OpNum, SStream *O);
65 static void printPKHLSLShiftImm(MCInst *MI, unsigned OpNum, SStream *O);
66 static void printPKHASRShiftImm(MCInst *MI, unsigned OpNum, SStream *O);
67 static void printAdrLabelOperand(MCInst *MI, unsigned OpNum, SStream *O, unsigned);
68 static void printThumbS4ImmOperand(MCInst *MI, unsigned OpNum, SStream *O);
69 static void printThumbSRImm(MCInst *MI, unsigned OpNum, SStream *O);
70 static void printThumbITMask(MCInst *MI, unsigned OpNum, SStream *O);
71 static void printThumbAddrModeRROperand(MCInst *MI, unsigned OpNum, SStream *O);
72 static void printThumbAddrModeImm5SOperand(MCInst *MI, unsigned OpNum, SStream *O, unsigned Scale);
73 static void printThumbAddrModeImm5S1Operand(MCInst *MI, unsigned OpNum, SStream *O);
74 static void printThumbAddrModeImm5S2Operand(MCInst *MI, unsigned OpNum, SStream *O);
75 static void printThumbAddrModeImm5S4Operand(MCInst *MI, unsigned OpNum, SStream *O);
76 static void printThumbAddrModeSPOperand(MCInst *MI, unsigned OpNum, SStream *O);
77 static void printT2SOOperand(MCInst *MI, unsigned OpNum, SStream *O);
78 static void printAddrModeImm12Operand(MCInst *MI, unsigned OpNum, SStream *O, bool AlwaysPrintImm0);
79 static void printT2AddrModeImm8Operand(MCInst *MI, unsigned OpNum, SStream *O, bool);
80 static void printT2AddrModeImm8s4Operand(MCInst *MI, unsigned OpNum, SStream *O, bool);
81 static void printT2AddrModeImm0_1020s4Operand(MCInst *MI, unsigned OpNum, SStream *O);
82 static void printT2AddrModeImm8OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O);
83 static void printT2AddrModeImm8s4OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O);
84 static void printT2AddrModeSoRegOperand(MCInst *MI, unsigned OpNum, SStream *O);
85 static void printSetendOperand(MCInst *MI, unsigned OpNum, SStream *O);
86 static void printCPSIMod(MCInst *MI, unsigned OpNum, SStream *O);
87 static void printCPSIFlag(MCInst *MI, unsigned OpNum, SStream *O);
88 static void printMSRMaskOperand(MCInst *MI, unsigned OpNum, SStream *O);
89 static void printPredicateOperand(MCInst *MI, unsigned OpNum, SStream *O);
90 static void printMandatoryPredicateOperand(MCInst *MI, unsigned OpNum, SStream *O);
91 static void printSBitModifierOperand(MCInst *MI, unsigned OpNum, SStream *O);
92 static void printRegisterList(MCInst *MI, unsigned OpNum, SStream *O);
93 static void printNoHashImmediate(MCInst *MI, unsigned OpNum, SStream *O);
94 static void printPImmediate(MCInst *MI, unsigned OpNum, SStream *O);
95 static void printCImmediate(MCInst *MI, unsigned OpNum, SStream *O);
96 static void printCoprocOptionImm(MCInst *MI, unsigned OpNum, SStream *O);
97 static void printFPImmOperand(MCInst *MI, unsigned OpNum, SStream *O);
98 static void printNEONModImmOperand(MCInst *MI, unsigned OpNum, SStream *O);
99 static void printImmPlusOneOperand(MCInst *MI, unsigned OpNum, SStream *O);
100 static void printRotImmOperand(MCInst *MI, unsigned OpNum, SStream *O);
101 static void printGPRPairOperand(MCInst *MI, unsigned OpNum, SStream *O, MCRegisterInfo *MRI);
102 static void printThumbLdrLabelOperand(MCInst *MI, unsigned OpNum, SStream *O);
103 static void printFBits16(MCInst *MI, unsigned OpNum, SStream *O);
104 static void printFBits32(MCInst *MI, unsigned OpNum, SStream *O);
105 static void printVectorIndex(MCInst *MI, unsigned OpNum, SStream *O);
106 static void printVectorListOne(MCInst *MI, unsigned OpNum, SStream *O);
107 static void printVectorListTwo(MCInst *MI, unsigned OpNum, SStream *O, MCRegisterInfo *MRI);
108 static void printVectorListTwoSpaced(MCInst *MI, unsigned OpNum, SStream *O, MCRegisterInfo *RI);
109 static void printVectorListThree(MCInst *MI, unsigned OpNum, SStream *O);
110 static void printVectorListFour(MCInst *MI, unsigned OpNum, SStream *O);
111 static void printVectorListOneAllLanes(MCInst *MI, unsigned OpNum, SStream *O);
112 static void printVectorListTwoAllLanes(MCInst *MI, unsigned OpNum, SStream *O, MCRegisterInfo *RI);
113 static void printVectorListThreeAllLanes(MCInst *MI, unsigned OpNum, SStream *O);
114 static void printVectorListFourAllLanes(MCInst *MI, unsigned OpNum, SStream *O);
115 static void printVectorListTwoSpacedAllLanes(MCInst *MI, unsigned OpNum, SStream *O, MCRegisterInfo *MRI);
116 static void printVectorListThreeSpacedAllLanes(MCInst *MI, unsigned OpNum, SStream *O);
117 static void printVectorListFourSpacedAllLanes(MCInst *MI, unsigned OpNum, SStream *O);
118 static void printVectorListThreeSpaced(MCInst *MI, unsigned OpNum, SStream *O);
119 static void printVectorListFourSpaced(MCInst *MI, unsigned OpNum, SStream *O);
120 static void printBankedRegOperand(MCInst *MI, unsigned OpNum, SStream *O);
121 static void printModImmOperand(MCInst *MI, unsigned OpNum, SStream *O);
122 
123 static void printInstSyncBOption(MCInst *MI, unsigned OpNum, SStream *O);
124 
125 #ifndef CAPSTONE_DIET
126 // copy & normalize access info
127 static uint8_t get_op_access(cs_struct *h, unsigned int id, unsigned int index)
128 {
129  uint8_t *arr = ARM_get_op_access(h, id);
130 
131  if (arr[index] == CS_AC_IGNORE)
132  return 0;
133 
134  return arr[index];
135 }
136 #endif
137 
138 static void set_mem_access(MCInst *MI, bool status)
139 {
140  if (MI->csh->detail != CS_OPT_ON)
141  return;
142 
143  MI->csh->doing_mem = status;
144  if (status) {
145 #ifndef CAPSTONE_DIET
146  uint8_t access;
147 #endif
148 
149  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_MEM;
150  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = ARM_REG_INVALID;
151  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = ARM_REG_INVALID;
152  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.scale = 1;
153  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = 0;
154 
155 #ifndef CAPSTONE_DIET
156  access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
157  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
158  MI->ac_idx++;
159 #endif
160  } else {
161  // done, create the next operand slot
162  MI->flat_insn->detail->arm.op_count++;
163  }
164 }
165 
166 static void op_addImm(MCInst *MI, int v)
167 {
168  if (MI->csh->detail) {
169  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
170  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = v;
171  MI->flat_insn->detail->arm.op_count++;
172  }
173 }
174 
175 #define GET_INSTRINFO_ENUM
176 #include "ARMGenInstrInfo.inc"
177 
178 //#define PRINT_ALIAS_INSTR
179 #include "ARMGenAsmWriter.inc"
180 
182 {
184  handle->get_regname = getRegisterName2;
185  handle->reg_name = ARM_reg_name2;;
186  } else {
187  handle->get_regname = getRegisterName;
188  handle->reg_name = ARM_reg_name;;
189  }
190 }
191 
195 static unsigned translateShiftImm(unsigned imm)
196 {
197  // lsr #32 and asr #32 exist, but should be encoded as a 0.
198  //assert((imm & ~0x1f) == 0 && "Invalid shift encoding");
199  if (imm == 0)
200  return 32;
201  return imm;
202 }
203 
205 static void printRegImmShift(MCInst *MI, SStream *O, ARM_AM_ShiftOpc ShOpc, unsigned ShImm)
206 {
207  if (ShOpc == ARM_AM_no_shift || (ShOpc == ARM_AM_lsl && !ShImm))
208  return;
209  SStream_concat0(O, ", ");
210 
211  //assert (!(ShOpc == ARM_AM_ror && !ShImm) && "Cannot have ror #0");
213  if (MI->csh->detail) {
214  if (MI->csh->doing_mem)
215  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.type = (arm_shifter)ShOpc;
216  else
217  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.type = (arm_shifter)ShOpc;
218  }
219 
220  if (ShOpc != ARM_AM_rrx) {
221  SStream_concat0(O, " ");
222  SStream_concat(O, "#%u", translateShiftImm(ShImm));
223  if (MI->csh->detail) {
224  if (MI->csh->doing_mem)
225  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.value = translateShiftImm(ShImm);
226  else
227  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.value = translateShiftImm(ShImm);
228  }
229  }
230 }
231 
232 static void printRegName(cs_struct *h, SStream *OS, unsigned RegNo)
233 {
234 #ifndef CAPSTONE_DIET
235  SStream_concat0(OS, h->get_regname(RegNo));
236 #endif
237 }
238 
239 static const name_map insn_update_flgs[] = {
240  { ARM_INS_CMN, "cmn" },
241  { ARM_INS_CMP, "cmp" },
242  { ARM_INS_TEQ, "teq" },
243  { ARM_INS_TST, "tst" },
244 
245  { ARM_INS_ADC, "adcs" },
246  { ARM_INS_ADD, "adds" },
247  { ARM_INS_AND, "ands" },
248  { ARM_INS_ASR, "asrs" },
249  { ARM_INS_BIC, "bics" },
250  { ARM_INS_EOR, "eors" },
251  { ARM_INS_LSL, "lsls" },
252  { ARM_INS_LSR, "lsrs" },
253  { ARM_INS_MLA, "mlas" },
254  { ARM_INS_MOV, "movs" },
255  { ARM_INS_MUL, "muls" },
256  { ARM_INS_MVN, "mvns" },
257  { ARM_INS_ORN, "orns" },
258  { ARM_INS_ORR, "orrs" },
259  { ARM_INS_ROR, "rors" },
260  { ARM_INS_RRX, "rrxs" },
261  { ARM_INS_RSB, "rsbs" },
262  { ARM_INS_RSC, "rscs" },
263  { ARM_INS_SBC, "sbcs" },
264  { ARM_INS_SMLAL, "smlals" },
265  { ARM_INS_SMULL, "smulls" },
266  { ARM_INS_SUB, "subs" },
267  { ARM_INS_UMLAL, "umlals" },
268  { ARM_INS_UMULL, "umulls" },
269 
270  { ARM_INS_UADD8, "uadd8" },
271 };
272 
273 void ARM_post_printer(csh ud, cs_insn *insn, char *insn_asm, MCInst *mci)
274 {
275  if (((cs_struct *)ud)->detail != CS_OPT_ON)
276  return;
277 
278  // check if this insn requests write-back
279  if (mci->writeback || (strrchr(insn_asm, '!')) != NULL) {
280  insn->detail->arm.writeback = true;
281  } else if (mci->csh->mode & CS_MODE_THUMB) {
282  // handle some special instructions with writeback
283  //printf(">> Opcode = %u\n", mci->Opcode);
284  switch(mci->Opcode) {
285  default:
286  break;
287  case ARM_t2LDC2L_PRE:
288  case ARM_t2LDC2_PRE:
289  case ARM_t2LDCL_PRE:
290  case ARM_t2LDC_PRE:
291 
292  case ARM_t2LDRB_PRE:
293  case ARM_t2LDRD_PRE:
294  case ARM_t2LDRH_PRE:
295  case ARM_t2LDRSB_PRE:
296  case ARM_t2LDRSH_PRE:
297  case ARM_t2LDR_PRE:
298 
299  case ARM_t2STC2L_PRE:
300  case ARM_t2STC2_PRE:
301  case ARM_t2STCL_PRE:
302  case ARM_t2STC_PRE:
303 
304  case ARM_t2STRB_PRE:
305  case ARM_t2STRD_PRE:
306  case ARM_t2STRH_PRE:
307  case ARM_t2STR_PRE:
308 
309  case ARM_t2LDC2L_POST:
310  case ARM_t2LDC2_POST:
311  case ARM_t2LDCL_POST:
312  case ARM_t2LDC_POST:
313 
314  case ARM_t2LDRB_POST:
315  case ARM_t2LDRD_POST:
316  case ARM_t2LDRH_POST:
317  case ARM_t2LDRSB_POST:
318  case ARM_t2LDRSH_POST:
319  case ARM_t2LDR_POST:
320 
321  case ARM_t2STC2L_POST:
322  case ARM_t2STC2_POST:
323  case ARM_t2STCL_POST:
324  case ARM_t2STC_POST:
325 
326  case ARM_t2STRB_POST:
327  case ARM_t2STRD_POST:
328  case ARM_t2STRH_POST:
329  case ARM_t2STR_POST:
330  insn->detail->arm.writeback = true;
331  break;
332  }
333  } else { // ARM mode
334  // handle some special instructions with writeback
335  //printf(">> Opcode = %u\n", mci->Opcode);
336  switch(mci->Opcode) {
337  default:
338  break;
339  case ARM_LDC2L_PRE:
340  case ARM_LDC2_PRE:
341  case ARM_LDCL_PRE:
342  case ARM_LDC_PRE:
343 
344  case ARM_LDRD_PRE:
345  case ARM_LDRH_PRE:
346  case ARM_LDRSB_PRE:
347  case ARM_LDRSH_PRE:
348 
349  case ARM_STC2L_PRE:
350  case ARM_STC2_PRE:
351  case ARM_STCL_PRE:
352  case ARM_STC_PRE:
353 
354  case ARM_STRD_PRE:
355  case ARM_STRH_PRE:
356 
357  case ARM_LDC2L_POST:
358  case ARM_LDC2_POST:
359  case ARM_LDCL_POST:
360  case ARM_LDC_POST:
361 
362  case ARM_LDRBT_POST:
363  case ARM_LDRD_POST:
364  case ARM_LDRH_POST:
365  case ARM_LDRSB_POST:
366  case ARM_LDRSH_POST:
367 
368  case ARM_STC2L_POST:
369  case ARM_STC2_POST:
370  case ARM_STCL_POST:
371  case ARM_STC_POST:
372 
373  case ARM_STRBT_POST:
374  case ARM_STRD_POST:
375  case ARM_STRH_POST:
376 
377  case ARM_LDRB_POST_IMM:
378  case ARM_LDR_POST_IMM:
379  case ARM_LDR_POST_REG:
380  case ARM_STRB_POST_IMM:
381 
382  case ARM_STR_POST_IMM:
383  case ARM_STR_POST_REG:
384 
385  insn->detail->arm.writeback = true;
386  break;
387  }
388  }
389 
390  // check if this insn requests update flags
391  if (insn->detail->arm.update_flags == false) {
392  // some insn still update flags, regardless of tabgen info
393  unsigned int i, j;
394 
395  for (i = 0; i < ARR_SIZE(insn_update_flgs); i++) {
396  if (insn->id == insn_update_flgs[i].id &&
397  !strncmp(insn_asm, insn_update_flgs[i].name,
398  strlen(insn_update_flgs[i].name))) {
399  insn->detail->arm.update_flags = true;
400  // we have to update regs_write array as well
401  for (j = 0; j < ARR_SIZE(insn->detail->regs_write); j++) {
402  if (insn->detail->regs_write[j] == 0) {
403  insn->detail->regs_write[j] = ARM_REG_CPSR;
404  break;
405  }
406  }
407  break;
408  }
409  }
410  }
411 
412  // instruction should not have invalid CC
413  if (insn->detail->arm.cc == ARM_CC_INVALID) {
414  insn->detail->arm.cc = ARM_CC_AL;
415  }
416 
417  // manual fix for some special instructions
418  // printf(">>> id: %u, mcid: %u\n", insn->id, mci->Opcode);
419  switch(mci->Opcode) {
420  default:
421  break;
422  case ARM_MOVPCLR:
423  insn->detail->arm.operands[0].type = ARM_OP_REG;
424  insn->detail->arm.operands[0].reg = ARM_REG_PC;
425  insn->detail->arm.operands[0].access = CS_AC_WRITE;
426  insn->detail->arm.operands[1].type = ARM_OP_REG;
427  insn->detail->arm.operands[1].reg = ARM_REG_LR;
428  insn->detail->arm.operands[1].access = CS_AC_READ;
429  insn->detail->arm.op_count = 2;
430  break;
431  }
432 }
433 
434 void ARM_printInst(MCInst *MI, SStream *O, void *Info)
435 {
436  MCRegisterInfo *MRI = (MCRegisterInfo *)Info;
437  unsigned Opcode = MCInst_getOpcode(MI), tmp, i, pubOpcode;
438 
439 
440  // printf(">>> Opcode 0: %u\n", MCInst_getOpcode(MI));
441  switch(Opcode) {
442  // Check for HINT instructions w/ canonical names.
443  case ARM_HINT:
444  case ARM_tHINT:
445  case ARM_t2HINT:
446  switch (MCOperand_getImm(MCInst_getOperand(MI, 0))) {
447  case 0: SStream_concat0(O, "nop"); pubOpcode = ARM_INS_NOP; break;
448  case 1: SStream_concat0(O, "yield"); pubOpcode = ARM_INS_YIELD; break;
449  case 2: SStream_concat0(O, "wfe"); pubOpcode = ARM_INS_WFE; break;
450  case 3: SStream_concat0(O, "wfi"); pubOpcode = ARM_INS_WFI; break;
451  case 4: SStream_concat0(O, "sev"); pubOpcode = ARM_INS_SEV; break;
452  case 5:
453  if ((ARM_getFeatureBits(MI->csh->mode) & ARM_HasV8Ops)) {
454  SStream_concat0(O, "sevl");
455  pubOpcode = ARM_INS_SEVL;
456  break;
457  }
458  // Fallthrough for non-v8
459  default:
460  // Anything else should just print normally.
461  printInstruction(MI, O, MRI);
462  return;
463  }
464  printPredicateOperand(MI, 1, O);
465  if (Opcode == ARM_t2HINT)
466  SStream_concat0(O, ".w");
467 
468  MCInst_setOpcodePub(MI, pubOpcode);
469 
470  return;
471 
472  // Check for MOVs and print canonical forms, instead.
473  case ARM_MOVsr: {
474  // FIXME: Thumb variants?
475  unsigned int opc;
476  MCOperand *Dst = MCInst_getOperand(MI, 0);
477  MCOperand *MO1 = MCInst_getOperand(MI, 1);
478  MCOperand *MO2 = MCInst_getOperand(MI, 2);
479  MCOperand *MO3 = MCInst_getOperand(MI, 3);
480 
481  opc = ARM_AM_getSORegShOp((unsigned int)MCOperand_getImm(MO3));
483  switch(opc) {
484  default:
485  break;
486  case ARM_AM_asr:
488  break;
489  case ARM_AM_lsl:
491  break;
492  case ARM_AM_lsr:
494  break;
495  case ARM_AM_ror:
497  break;
498  case ARM_AM_rrx:
500  break;
501  }
502  printSBitModifierOperand(MI, 6, O);
503  printPredicateOperand(MI, 4, O);
504 
505  SStream_concat0(O, "\t");
506  printRegName(MI->csh, O, MCOperand_getReg(Dst));
507  if (MI->csh->detail) {
508  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
509  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(Dst);
510  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_WRITE;
511  MI->flat_insn->detail->arm.op_count++;
512  }
513 
514  SStream_concat0(O, ", ");
515  printRegName(MI->csh, O, MCOperand_getReg(MO1));
516 
517  if (MI->csh->detail) {
518  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
519  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO1);
520  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;
521  MI->flat_insn->detail->arm.op_count++;
522  }
523 
524  SStream_concat0(O, ", ");
525  printRegName(MI->csh, O, MCOperand_getReg(MO2));
526  if (MI->csh->detail) {
527  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
528  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO2);
529  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;
530  MI->flat_insn->detail->arm.op_count++;
531  }
532  //assert(ARM_AM_getSORegOffset(MO3.getImm()) == 0);
533  return;
534  }
535 
536  case ARM_MOVsi: {
537  // FIXME: Thumb variants?
538  unsigned int opc;
539  MCOperand *Dst = MCInst_getOperand(MI, 0);
540  MCOperand *MO1 = MCInst_getOperand(MI, 1);
541  MCOperand *MO2 = MCInst_getOperand(MI, 2);
542 
543  opc = ARM_AM_getSORegShOp((unsigned int)MCOperand_getImm(MO2));
545  switch(opc) {
546  default:
547  break;
548  case ARM_AM_asr:
550  break;
551  case ARM_AM_lsl:
553  break;
554  case ARM_AM_lsr:
556  break;
557  case ARM_AM_ror:
559  break;
560  case ARM_AM_rrx:
562  break;
563  }
564  printSBitModifierOperand(MI, 5, O);
565  printPredicateOperand(MI, 3, O);
566 
567  SStream_concat0(O, "\t");
568  printRegName(MI->csh, O, MCOperand_getReg(Dst));
569  if (MI->csh->detail) {
570  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
571  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(Dst);
572  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_WRITE;
573  MI->flat_insn->detail->arm.op_count++;
574  }
575 
576  SStream_concat0(O, ", ");
577  printRegName(MI->csh, O, MCOperand_getReg(MO1));
578  if (MI->csh->detail) {
579  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
580  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO1);
581  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;
582  MI->flat_insn->detail->arm.op_count++;
583  }
584 
585  if (opc == ARM_AM_rrx) {
586  //printAnnotation(O, Annot);
587  return;
588  }
589 
590  SStream_concat0(O, ", ");
591  tmp = translateShiftImm(getSORegOffset((unsigned int)MCOperand_getImm(MO2)));
593  if (MI->csh->detail) {
594  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.type =
595  (arm_shifter)opc;
596  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.value = tmp;
597  }
598  return;
599  }
600 
601  // A8.6.123 PUSH
602  case ARM_STMDB_UPD:
603  case ARM_t2STMDB_UPD:
604  if (MCOperand_getReg(MCInst_getOperand(MI, 0)) == ARM_SP &&
605  MCInst_getNumOperands(MI) > 5) {
606  // Should only print PUSH if there are at least two registers in the list.
607  SStream_concat0(O, "push");
609  printPredicateOperand(MI, 2, O);
610  if (Opcode == ARM_t2STMDB_UPD)
611  SStream_concat0(O, ".w");
612  SStream_concat0(O, "\t");
613 
614  if (MI->csh->detail) {
615  MI->flat_insn->detail->regs_read[MI->flat_insn->detail->regs_read_count] = ARM_REG_SP;
616  MI->flat_insn->detail->regs_read_count++;
617  MI->flat_insn->detail->regs_write[MI->flat_insn->detail->regs_write_count] = ARM_REG_SP;
618  MI->flat_insn->detail->regs_write_count++;
619  }
620 
621  printRegisterList(MI, 4, O);
622  return;
623  }
624  break;
625 
626  case ARM_STR_PRE_IMM:
627  if (MCOperand_getReg(MCInst_getOperand(MI, 2)) == ARM_SP &&
628  MCOperand_getImm(MCInst_getOperand(MI, 3)) == -4) {
629  SStream_concat0(O, "push");
631  printPredicateOperand(MI, 4, O);
632  SStream_concat0(O, "\t{");
633  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, 1)));
634  if (MI->csh->detail) {
635 #ifndef CAPSTONE_DIET
636  uint8_t access;
637 #endif
638  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
639  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, 1));
640 #ifndef CAPSTONE_DIET
641  access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
642  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
643  MI->ac_idx++;
644 #endif
645  MI->flat_insn->detail->arm.op_count++;
646  }
647  SStream_concat0(O, "}");
648  return;
649  }
650  break;
651 
652  // A8.6.122 POP
653  case ARM_LDMIA_UPD:
654  case ARM_t2LDMIA_UPD:
655  if (MCOperand_getReg(MCInst_getOperand(MI, 0)) == ARM_SP &&
656  MCInst_getNumOperands(MI) > 5) {
657  // Should only print POP if there are at least two registers in the list.
658  SStream_concat0(O, "pop");
660  printPredicateOperand(MI, 2, O);
661  if (Opcode == ARM_t2LDMIA_UPD)
662  SStream_concat0(O, ".w");
663  SStream_concat0(O, "\t");
664  // unlike LDM, POP only write to registers, so skip the 1st access code
665  MI->ac_idx = 1;
666  if (MI->csh->detail) {
667  MI->flat_insn->detail->regs_read[MI->flat_insn->detail->regs_read_count] = ARM_REG_SP;
668  MI->flat_insn->detail->regs_read_count++;
669  MI->flat_insn->detail->regs_write[MI->flat_insn->detail->regs_write_count] = ARM_REG_SP;
670  MI->flat_insn->detail->regs_write_count++;
671  }
672 
673  printRegisterList(MI, 4, O);
674  return;
675  }
676  break;
677 
678  case ARM_LDR_POST_IMM:
679  if (MCOperand_getReg(MCInst_getOperand(MI, 2)) == ARM_SP) {
680  MCOperand *MO2 = MCInst_getOperand(MI, 4);
681  if ((getAM2Op((unsigned int)MCOperand_getImm(MO2)) == ARM_AM_add &&
682  getAM2Offset((unsigned int)MCOperand_getImm(MO2)) == 4) ||
683  MCOperand_getImm(MO2) == 4) {
684  SStream_concat0(O, "pop");
686  printPredicateOperand(MI, 5, O);
687  SStream_concat0(O, "\t{");
688  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, 0)));
689  if (MI->csh->detail) {
690  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
691  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, 0));
692  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_WRITE;
693  MI->flat_insn->detail->arm.op_count++;
694  // this instruction implicitly read/write SP register
695  MI->flat_insn->detail->regs_read[MI->flat_insn->detail->regs_read_count] = ARM_REG_SP;
696  MI->flat_insn->detail->regs_read_count++;
697  MI->flat_insn->detail->regs_write[MI->flat_insn->detail->regs_write_count] = ARM_REG_SP;
698  MI->flat_insn->detail->regs_write_count++;
699  }
700  SStream_concat0(O, "}");
701  return;
702  }
703  }
704  break;
705 
706  // A8.6.355 VPUSH
707  case ARM_VSTMSDB_UPD:
708  case ARM_VSTMDDB_UPD:
709  if (MCOperand_getReg(MCInst_getOperand(MI, 0)) == ARM_SP) {
710  SStream_concat0(O, "vpush");
712  printPredicateOperand(MI, 2, O);
713  SStream_concat0(O, "\t");
714  printRegisterList(MI, 4, O);
715  return;
716  }
717  break;
718 
719  // A8.6.354 VPOP
720  case ARM_VLDMSIA_UPD:
721  case ARM_VLDMDIA_UPD:
722  if (MCOperand_getReg(MCInst_getOperand(MI, 0)) == ARM_SP) {
723  SStream_concat0(O, "vpop");
725  printPredicateOperand(MI, 2, O);
726  SStream_concat0(O, "\t");
727  printRegisterList(MI, 4, O);
728  return;
729  }
730  break;
731 
732  case ARM_tLDMIA: {
733  bool Writeback = true;
734  unsigned BaseReg = MCOperand_getReg(MCInst_getOperand(MI, 0));
735  unsigned i;
736  for (i = 3; i < MCInst_getNumOperands(MI); ++i) {
737  if (MCOperand_getReg(MCInst_getOperand(MI, i)) == BaseReg)
738  Writeback = false;
739  }
740 
741  SStream_concat0(O, "ldm");
743 
744  printPredicateOperand(MI, 1, O);
745  SStream_concat0(O, "\t");
746  printRegName(MI->csh, O, BaseReg);
747  if (MI->csh->detail) {
748  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
749  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = BaseReg;
750  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ | CS_AC_WRITE;
751  MI->flat_insn->detail->arm.op_count++;
752  }
753  if (Writeback) {
754  MI->writeback = true;
755  SStream_concat0(O, "!");
756  }
757  SStream_concat0(O, ", ");
758  printRegisterList(MI, 3, O);
759  return;
760  }
761 
762  // Combine 2 GPRs from disassember into a GPRPair to match with instr def.
763  // ldrexd/strexd require even/odd GPR pair. To enforce this constraint,
764  // a single GPRPair reg operand is used in the .td file to replace the two
765  // GPRs. However, when decoding them, the two GRPs cannot be automatically
766  // expressed as a GPRPair, so we have to manually merge them.
767  // FIXME: We would really like to be able to tablegen'erate this.
768  case ARM_LDREXD:
769  case ARM_STREXD:
770  case ARM_LDAEXD:
771  case ARM_STLEXD: {
772  const MCRegisterClass* MRC = MCRegisterInfo_getRegClass(MRI, ARM_GPRRegClassID);
773  bool isStore = Opcode == ARM_STREXD || Opcode == ARM_STLEXD;
774  unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, isStore ? 1 : 0));
775 
776  if (MCRegisterClass_contains(MRC, Reg)) {
777  MCInst NewMI;
778 
779  MCInst_Init(&NewMI);
780  MCInst_setOpcode(&NewMI, Opcode);
781 
782  if (isStore)
783  MCInst_addOperand2(&NewMI, MCInst_getOperand(MI, 0));
784 
786  MCRegisterInfo_getRegClass(MRI, ARM_GPRPairRegClassID)));
787 
788  // Copy the rest operands into NewMI.
789  for(i = isStore ? 3 : 2; i < MCInst_getNumOperands(MI); ++i)
790  MCInst_addOperand2(&NewMI, MCInst_getOperand(MI, i));
791 
792  printInstruction(&NewMI, O, MRI);
793  return;
794  }
795  break;
796  }
797  // B9.3.3 ERET (Thumb)
798  // For a target that has Virtualization Extensions, ERET is the preferred
799  // disassembly of SUBS PC, LR, #0
800  case ARM_t2SUBS_PC_LR: {
801  MCOperand *opc = MCInst_getOperand(MI, 0);
802  if (MCInst_getNumOperands(MI) == 3 &&
803  MCOperand_isImm(opc) &&
804  MCOperand_getImm(opc) == 0 &&
805  (ARM_getFeatureBits(MI->csh->mode) & ARM_FeatureVirtualization)) {
806  SStream_concat0(O, "eret");
808  printPredicateOperand(MI, 1, O);
809  return;
810  }
811  break;
812  }
813  }
814 
815  //if (printAliasInstr(MI, O, MRI))
816  // printInstruction(MI, O, MRI);
817  printInstruction(MI, O, MRI);
818 }
819 
820 static void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
821 {
822  int32_t imm;
823  MCOperand *Op = MCInst_getOperand(MI, OpNo);
824  if (MCOperand_isReg(Op)) {
825  unsigned Reg = MCOperand_getReg(Op);
826  printRegName(MI->csh, O, Reg);
827  if (MI->csh->detail) {
828  if (MI->csh->doing_mem) {
829  if (MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base == ARM_REG_INVALID)
830  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = Reg;
831  else
832  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = Reg;
833  } else {
834 #ifndef CAPSTONE_DIET
835  uint8_t access;
836 #endif
837 
838  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
839  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg;
840 #ifndef CAPSTONE_DIET
841  access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
842  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
843  MI->ac_idx++;
844 #endif
845  MI->flat_insn->detail->arm.op_count++;
846  }
847  }
848  } else if (MCOperand_isImm(Op)) {
849  unsigned int opc = MCInst_getOpcode(MI);
850 
852 
853  // relative branch only has relative offset, so we have to update it
854  // to reflect absolute address.
855  // Note: in ARM, PC is always 2 instructions ahead, so we have to
856  // add 8 in ARM mode, or 4 in Thumb mode
857  // printf(">> opcode: %u\n", MCInst_getOpcode(MI));
858  if (ARM_rel_branch(MI->csh, opc)) {
859  uint32_t address;
860 
861  // only do this for relative branch
862  if (MI->csh->mode & CS_MODE_THUMB) {
863  address = (uint32_t)MI->address + 4;
864  if (ARM_blx_to_arm_mode(MI->csh, opc)) {
865  // here need to align down to the nearest 4-byte address
866 #define _ALIGN_DOWN(v, align_width) ((v/align_width)*align_width)
867  address = _ALIGN_DOWN(address, 4);
868 #undef _ALIGN_DOWN
869  }
870  } else {
871  address = (uint32_t)MI->address + 8;
872  }
873 
874  imm += address;
876  } else {
877  switch(MI->flat_insn->id) {
878  default:
879  if (MI->csh->imm_unsigned)
881  else
882  printInt32Bang(O, imm);
883  break;
884  case ARM_INS_AND:
885  case ARM_INS_ORR:
886  case ARM_INS_EOR:
887  case ARM_INS_BIC:
888  case ARM_INS_MVN:
889  // do not print number in negative form
891  break;
892  }
893  }
894 
895  if (MI->csh->detail) {
896  if (MI->csh->doing_mem)
897  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = imm;
898  else {
899  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
900  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = imm;
901  MI->flat_insn->detail->arm.op_count++;
902  }
903  }
904  }
905 }
906 
907 static void printThumbLdrLabelOperand(MCInst *MI, unsigned OpNum, SStream *O)
908 {
909  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
910  int32_t OffImm;
911  bool isSub;
912  SStream_concat0(O, "[pc, ");
913 
914  OffImm = (int32_t)MCOperand_getImm(MO1);
915  isSub = OffImm < 0;
916 
917  // Special value for #-0. All others are normal.
918  if (OffImm == INT32_MIN)
919  OffImm = 0;
920  if (isSub) {
921  SStream_concat(O, "#-0x%x", -OffImm);
922  } else {
923  printUInt32Bang(O, OffImm);
924  }
925 
926  SStream_concat0(O, "]");
927 
928  if (MI->csh->detail) {
929  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_MEM;
930  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = ARM_REG_PC;
931  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = ARM_REG_INVALID;
932  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.scale = 1;
933  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = OffImm;
934  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;
935  MI->flat_insn->detail->arm.op_count++;
936  }
937 }
938 
939 // so_reg is a 4-operand unit corresponding to register forms of the A5.1
940 // "Addressing Mode 1 - Data-processing operands" forms. This includes:
941 // REG 0 0 - e.g. R5
942 // REG REG 0,SH_OPC - e.g. R5, ROR R3
943 // REG 0 IMM,SH_OPC - e.g. R5, LSL #3
944 static void printSORegRegOperand(MCInst *MI, unsigned OpNum, SStream *O)
945 {
946  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
947  MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
948  MCOperand *MO3 = MCInst_getOperand(MI, OpNum+2);
949  ARM_AM_ShiftOpc ShOpc;
950 
951  printRegName(MI->csh, O, MCOperand_getReg(MO1));
952 
953  if (MI->csh->detail) {
954  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
955  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO1);
956  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;
957 
958  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.type = (MCOperand_getImm(MO3) & 7) + ARM_SFT_ASR_REG - 1;
959  MI->flat_insn->detail->arm.op_count++;
960  }
961 
962  // Print the shift opc.
963  ShOpc = ARM_AM_getSORegShOp((unsigned int)MCOperand_getImm(MO3));
964  SStream_concat0(O, ", ");
966  if (ShOpc == ARM_AM_rrx)
967  return;
968 
969  SStream_concat0(O, " ");
970  printRegName(MI->csh, O, MCOperand_getReg(MO2));
971  if (MI->csh->detail)
972  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.value = MCOperand_getReg(MO2);
973  //assert(ARM_AM_getSORegOffset(MO3.getImm()) == 0);
974 }
975 
976 static void printSORegImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
977 {
978  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
979  MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
980 
981  printRegName(MI->csh, O, MCOperand_getReg(MO1));
982  if (MI->csh->detail) {
983  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
984  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO1);
985  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;
986  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.type = MCOperand_getImm(MO2) & 7;
987  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.value = (unsigned int)MCOperand_getImm(MO2) >> 3;
988  MI->flat_insn->detail->arm.op_count++;
989  }
990 
991  // Print the shift opc.
992  printRegImmShift(MI, O, ARM_AM_getSORegShOp((unsigned int)MCOperand_getImm(MO2)),
993  getSORegOffset((unsigned int)MCOperand_getImm(MO2)));
994 }
995 
996 //===--------------------------------------------------------------------===//
997 // Addressing Mode #2
998 //===--------------------------------------------------------------------===//
999 
1000 static void printAM2PreOrOffsetIndexOp(MCInst *MI, unsigned Op, SStream *O)
1001 {
1002  MCOperand *MO1 = MCInst_getOperand(MI, Op);
1003  MCOperand *MO2 = MCInst_getOperand(MI, Op + 1);
1004  MCOperand *MO3 = MCInst_getOperand(MI, Op + 2);
1005  ARM_AM_AddrOpc subtracted = getAM2Op((unsigned int)MCOperand_getImm(MO3));
1006 
1007  SStream_concat0(O, "[");
1008  set_mem_access(MI, true);
1009 
1010  printRegName(MI->csh, O, MCOperand_getReg(MO1));
1011  if (MI->csh->detail) {
1012  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
1013  }
1014 
1015  if (!MCOperand_getReg(MO2)) {
1016  unsigned tmp = getAM2Offset((unsigned int)MCOperand_getImm(MO3));
1017  if (tmp) { // Don't print +0.
1018  subtracted = getAM2Op((unsigned int)MCOperand_getImm(MO3));
1019 
1020  SStream_concat0(O, ", ");
1021  if (tmp > HEX_THRESHOLD)
1022  SStream_concat(O, "#%s0x%x", ARM_AM_getAddrOpcStr(subtracted), tmp);
1023  else
1024  SStream_concat(O, "#%s%u", ARM_AM_getAddrOpcStr(subtracted), tmp);
1025  if (MI->csh->detail) {
1026  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.type = (arm_shifter)getAM2Op((unsigned int)MCOperand_getImm(MO3));
1027  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.value = tmp;
1028  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;
1029  }
1030  }
1031  SStream_concat0(O, "]");
1032  set_mem_access(MI, false);
1033  return;
1034  }
1035 
1036  SStream_concat0(O, ", ");
1037  SStream_concat0(O, ARM_AM_getAddrOpcStr(subtracted));
1038  printRegName(MI->csh, O, MCOperand_getReg(MO2));
1039  if (MI->csh->detail) {
1040  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = MCOperand_getReg(MO2);
1041  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;
1042  }
1043 
1044  printRegImmShift(MI, O, getAM2ShiftOpc((unsigned int)MCOperand_getImm(MO3)),
1045  getAM2Offset((unsigned int)MCOperand_getImm(MO3)));
1046  SStream_concat0(O, "]");
1047  set_mem_access(MI, false);
1048 }
1049 
1050 static void printAddrModeTBB(MCInst *MI, unsigned Op, SStream *O)
1051 {
1052  MCOperand *MO1 = MCInst_getOperand(MI, Op);
1053  MCOperand *MO2 = MCInst_getOperand(MI, Op+1);
1054  SStream_concat0(O, "[");
1055  set_mem_access(MI, true);
1056  printRegName(MI->csh, O, MCOperand_getReg(MO1));
1057  if (MI->csh->detail)
1058  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
1059  SStream_concat0(O, ", ");
1060  printRegName(MI->csh, O, MCOperand_getReg(MO2));
1061  if (MI->csh->detail)
1062  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = MCOperand_getReg(MO2);
1063  SStream_concat0(O, "]");
1064  set_mem_access(MI, false);
1065 }
1066 
1067 static void printAddrModeTBH(MCInst *MI, unsigned Op, SStream *O)
1068 {
1069  MCOperand *MO1 = MCInst_getOperand(MI, Op);
1070  MCOperand *MO2 = MCInst_getOperand(MI, Op+1);
1071  SStream_concat0(O, "[");
1072  set_mem_access(MI, true);
1073  printRegName(MI->csh, O, MCOperand_getReg(MO1));
1074  if (MI->csh->detail)
1075  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
1076  SStream_concat0(O, ", ");
1077  printRegName(MI->csh, O, MCOperand_getReg(MO2));
1078  if (MI->csh->detail)
1079  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = MCOperand_getReg(MO2);
1080  SStream_concat0(O, ", lsl #1]");
1081  if (MI->csh->detail) {
1082  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.type = ARM_SFT_LSL;
1083  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.value = 1;
1084  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.lshift = 1;
1085  }
1086  set_mem_access(MI, false);
1087 }
1088 
1089 static void printAddrMode2Operand(MCInst *MI, unsigned Op, SStream *O)
1090 {
1091  MCOperand *MO1 = MCInst_getOperand(MI, Op);
1092 
1093  if (!MCOperand_isReg(MO1)) { // FIXME: This is for CP entries, but isn't right.
1094  printOperand(MI, Op, O);
1095  return;
1096  }
1097 
1098  printAM2PreOrOffsetIndexOp(MI, Op, O);
1099 }
1100 
1101 static void printAddrMode2OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O)
1102 {
1103  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1104  MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
1105  ARM_AM_AddrOpc subtracted = getAM2Op((unsigned int)MCOperand_getImm(MO2));
1106 
1107  if (!MCOperand_getReg(MO1)) {
1108  unsigned ImmOffs = getAM2Offset((unsigned int)MCOperand_getImm(MO2));
1109  if (ImmOffs > HEX_THRESHOLD)
1110  SStream_concat(O, "#%s0x%x",
1111  ARM_AM_getAddrOpcStr(subtracted), ImmOffs);
1112  else
1113  SStream_concat(O, "#%s%u",
1114  ARM_AM_getAddrOpcStr(subtracted), ImmOffs);
1115  if (MI->csh->detail) {
1116  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
1117  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = ImmOffs;
1118  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;
1119  MI->flat_insn->detail->arm.op_count++;
1120  }
1121  return;
1122  }
1123 
1124  SStream_concat0(O, ARM_AM_getAddrOpcStr(subtracted));
1125  printRegName(MI->csh, O, MCOperand_getReg(MO1));
1126  if (MI->csh->detail) {
1127  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
1128  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO1);
1129  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;
1130  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;
1131  MI->flat_insn->detail->arm.op_count++;
1132  }
1133 
1134  printRegImmShift(MI, O, getAM2ShiftOpc((unsigned int)MCOperand_getImm(MO2)),
1135  getAM2Offset((unsigned int)MCOperand_getImm(MO2)));
1136 }
1137 
1138 //===--------------------------------------------------------------------===//
1139 // Addressing Mode #3
1140 //===--------------------------------------------------------------------===//
1141 
1142 static void printAM3PreOrOffsetIndexOp(MCInst *MI, unsigned Op, SStream *O,
1143  bool AlwaysPrintImm0)
1144 {
1145  MCOperand *MO1 = MCInst_getOperand(MI, Op);
1146  MCOperand *MO2 = MCInst_getOperand(MI, Op+1);
1147  MCOperand *MO3 = MCInst_getOperand(MI, Op+2);
1148  ARM_AM_AddrOpc sign = getAM3Op((unsigned int)MCOperand_getImm(MO3));
1149  unsigned ImmOffs;
1150 
1151  SStream_concat0(O, "[");
1152  set_mem_access(MI, true);
1153  printRegName(MI->csh, O, MCOperand_getReg(MO1));
1154  if (MI->csh->detail)
1155  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
1156 
1157  if (MCOperand_getReg(MO2)) {
1158  SStream_concat0(O, ", ");
1160  printRegName(MI->csh, O, MCOperand_getReg(MO2));
1161  if (MI->csh->detail) {
1162  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = MCOperand_getReg(MO2);
1163  if (sign == ARM_AM_sub) {
1164  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.scale = -1;
1165  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = true;
1166  }
1167  }
1168  SStream_concat0(O, "]");
1169  set_mem_access(MI, false);
1170  return;
1171  }
1172 
1173  //If the op is sub we have to print the immediate even if it is 0
1174  ImmOffs = getAM3Offset((unsigned int)MCOperand_getImm(MO3));
1175 
1176  if (AlwaysPrintImm0 || ImmOffs || (sign == ARM_AM_sub)) {
1177  if (ImmOffs > HEX_THRESHOLD)
1178  SStream_concat(O, ", #%s0x%x", ARM_AM_getAddrOpcStr(sign), ImmOffs);
1179  else
1180  SStream_concat(O, ", #%s%u", ARM_AM_getAddrOpcStr(sign), ImmOffs);
1181  }
1182 
1183  if (MI->csh->detail) {
1184  if (sign == ARM_AM_sub) {
1185  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = -(int)ImmOffs;
1186  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = true;
1187  } else
1188  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = (int)ImmOffs;
1189  }
1190 
1191  SStream_concat0(O, "]");
1192  set_mem_access(MI, false);
1193 }
1194 
1195 static void printAddrMode3Operand(MCInst *MI, unsigned Op, SStream *O,
1196  bool AlwaysPrintImm0)
1197 {
1198  MCOperand *MO1 = MCInst_getOperand(MI, Op);
1199  if (!MCOperand_isReg(MO1)) { // For label symbolic references.
1200  printOperand(MI, Op, O);
1201  return;
1202  }
1203 
1204  printAM3PreOrOffsetIndexOp(MI, Op, O, AlwaysPrintImm0);
1205 }
1206 
1207 static void printAddrMode3OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O)
1208 {
1209  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1210  MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
1211  ARM_AM_AddrOpc subtracted = getAM3Op((unsigned int)MCOperand_getImm(MO2));
1212  unsigned ImmOffs;
1213 
1214  if (MCOperand_getReg(MO1)) {
1215  SStream_concat0(O, ARM_AM_getAddrOpcStr(subtracted));
1216  printRegName(MI->csh, O, MCOperand_getReg(MO1));
1217  if (MI->csh->detail) {
1218  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
1219  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO1);
1220  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;
1221  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;
1222  MI->flat_insn->detail->arm.op_count++;
1223  }
1224  return;
1225  }
1226 
1227  ImmOffs = getAM3Offset((unsigned int)MCOperand_getImm(MO2));
1228  if (ImmOffs > HEX_THRESHOLD)
1229  SStream_concat(O, "#%s0x%x", ARM_AM_getAddrOpcStr(subtracted), ImmOffs);
1230  else
1231  SStream_concat(O, "#%s%u", ARM_AM_getAddrOpcStr(subtracted), ImmOffs);
1232  if (MI->csh->detail) {
1233  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
1234  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = ImmOffs;
1235  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].subtracted = subtracted == ARM_AM_sub;
1236  MI->flat_insn->detail->arm.op_count++;
1237  }
1238 }
1239 
1240 static void printPostIdxImm8Operand(MCInst *MI, unsigned OpNum, SStream *O)
1241 {
1242  MCOperand *MO = MCInst_getOperand(MI, OpNum);
1243  unsigned Imm = (unsigned int)MCOperand_getImm(MO);
1244  if ((Imm & 0xff) > HEX_THRESHOLD)
1245  SStream_concat(O, "#%s0x%x", ((Imm & 256) ? "" : "-"), (Imm & 0xff));
1246  else
1247  SStream_concat(O, "#%s%u", ((Imm & 256) ? "" : "-"), (Imm & 0xff));
1248  if (MI->csh->detail) {
1249  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
1250  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = Imm & 0xff;
1251  MI->flat_insn->detail->arm.op_count++;
1252  }
1253 }
1254 
1255 static void printPostIdxRegOperand(MCInst *MI, unsigned OpNum, SStream *O)
1256 {
1257  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1258  MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
1259 
1260  SStream_concat0(O, (MCOperand_getImm(MO2) ? "" : "-"));
1261  printRegName(MI->csh, O, MCOperand_getReg(MO1));
1262  if (MI->csh->detail) {
1263  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
1264  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO1);
1265  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;
1266  MI->flat_insn->detail->arm.op_count++;
1267  }
1268 }
1269 
1270 static void printPostIdxImm8s4Operand(MCInst *MI, unsigned OpNum, SStream *O)
1271 {
1272  MCOperand *MO = MCInst_getOperand(MI, OpNum);
1273  int Imm = (int)MCOperand_getImm(MO);
1274 
1275  if (((Imm & 0xff) << 2) > HEX_THRESHOLD) {
1276  SStream_concat(O, "#%s0x%x", ((Imm & 256) ? "" : "-"), ((Imm & 0xff) << 2));
1277  } else {
1278  SStream_concat(O, "#%s%u", ((Imm & 256) ? "" : "-"), ((Imm & 0xff) << 2));
1279  }
1280 
1281  if (MI->csh->detail) {
1282  int v = (Imm & 256) ? ((Imm & 0xff) << 2) : -((Imm & 0xff) << 2);
1283  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
1284  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = v;
1285  MI->flat_insn->detail->arm.op_count++;
1286  }
1287 }
1288 
1289 static void printAddrMode5Operand(MCInst *MI, unsigned OpNum, SStream *O,
1290  bool AlwaysPrintImm0)
1291 {
1292  unsigned ImmOffs;
1293  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1294  MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
1295  ARM_AM_AddrOpc subtracted = ARM_AM_getAM5Op((unsigned int)MCOperand_getImm(MO2));
1296 
1297  if (!MCOperand_isReg(MO1)) { // FIXME: This is for CP entries, but isn't right.
1298  printOperand(MI, OpNum, O);
1299  return;
1300  }
1301 
1302  SStream_concat0(O, "[");
1303  printRegName(MI->csh, O, MCOperand_getReg(MO1));
1304 
1305  if (MI->csh->detail) {
1306  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_MEM;
1307  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
1308  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = ARM_REG_INVALID;
1309  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.scale = 1;
1310  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = 0;
1311  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;
1312  }
1313 
1314  ImmOffs = ARM_AM_getAM5Offset((unsigned int)MCOperand_getImm(MO2));
1315  if (AlwaysPrintImm0 || ImmOffs || subtracted == ARM_AM_sub) {
1316  if (ImmOffs * 4 > HEX_THRESHOLD)
1317  SStream_concat(O, ", #%s0x%x",
1318  ARM_AM_getAddrOpcStr(subtracted),
1319  ImmOffs * 4);
1320  else
1321  SStream_concat(O, ", #%s%u",
1322  ARM_AM_getAddrOpcStr(subtracted),
1323  ImmOffs * 4);
1324  if (MI->csh->detail) {
1325  if (subtracted)
1326  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = ImmOffs * 4;
1327  else
1328  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = -(int)ImmOffs * 4;
1329  }
1330  }
1331  SStream_concat0(O, "]");
1332 
1333  if (MI->csh->detail) {
1334  MI->flat_insn->detail->arm.op_count++;
1335  }
1336 }
1337 
1338 static void printAddrMode6Operand(MCInst *MI, unsigned OpNum, SStream *O)
1339 {
1340  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1341  MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
1342  unsigned tmp;
1343 
1344  SStream_concat0(O, "[");
1345  set_mem_access(MI, true);
1346  printRegName(MI->csh, O, MCOperand_getReg(MO1));
1347  if (MI->csh->detail)
1348  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
1349  tmp = (unsigned int)MCOperand_getImm(MO2);
1350  if (tmp) {
1351  if (tmp << 3 > HEX_THRESHOLD)
1352  SStream_concat(O, ":0x%x", (tmp << 3));
1353  else
1354  SStream_concat(O, ":%u", (tmp << 3));
1355  if (MI->csh->detail)
1356  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = tmp << 3;
1357  }
1358  SStream_concat0(O, "]");
1359  set_mem_access(MI, false);
1360 }
1361 
1362 static void printAddrMode7Operand(MCInst *MI, unsigned OpNum, SStream *O)
1363 {
1364  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1365  SStream_concat0(O, "[");
1366  set_mem_access(MI, true);
1367  printRegName(MI->csh, O, MCOperand_getReg(MO1));
1368  if (MI->csh->detail)
1369  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
1370  SStream_concat0(O, "]");
1371  set_mem_access(MI, false);
1372 }
1373 
1374 static void printAddrMode6OffsetOperand(MCInst *MI, unsigned OpNum, SStream *O)
1375 {
1376  MCOperand *MO = MCInst_getOperand(MI, OpNum);
1377  if (MCOperand_getReg(MO) == 0) {
1378  MI->writeback = true;
1379  SStream_concat0(O, "!");
1380  } else {
1381  SStream_concat0(O, ", ");
1382  printRegName(MI->csh, O, MCOperand_getReg(MO));
1383  if (MI->csh->detail) {
1384  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
1385  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MO);
1386  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;
1387  MI->flat_insn->detail->arm.op_count++;
1388  }
1389  }
1390 }
1391 
1392 static void printBitfieldInvMaskImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
1393 {
1394  MCOperand *MO = MCInst_getOperand(MI, OpNum);
1397  int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb;
1398 
1399  //assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!");
1400  printUInt32Bang(O, lsb);
1401 
1402  if (width > HEX_THRESHOLD)
1403  SStream_concat(O, ", #0x%x", width);
1404  else
1405  SStream_concat(O, ", #%u", width);
1406 
1407  if (MI->csh->detail) {
1408  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
1409  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = lsb;
1410  MI->flat_insn->detail->arm.op_count++;
1411  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
1412  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = width;
1413  MI->flat_insn->detail->arm.op_count++;
1414  }
1415 }
1416 
1417 static void printMemBOption(MCInst *MI, unsigned OpNum, SStream *O)
1418 {
1419  unsigned val = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1421  (ARM_getFeatureBits(MI->csh->mode) & ARM_HasV8Ops) != 0));
1422 
1423  if (MI->csh->detail) {
1424  MI->flat_insn->detail->arm.mem_barrier = (arm_mem_barrier)(val + 1);
1425  }
1426 }
1427 
1428 void printInstSyncBOption(MCInst *MI, unsigned OpNum, SStream *O)
1429 {
1430  unsigned val = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1432 }
1433 
1434 static void printShiftImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
1435 {
1436  unsigned ShiftOp = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1437  bool isASR = (ShiftOp & (1 << 5)) != 0;
1438  unsigned Amt = ShiftOp & 0x1f;
1439  if (isASR) {
1440  unsigned tmp = Amt == 0 ? 32 : Amt;
1441  if (tmp > HEX_THRESHOLD)
1442  SStream_concat(O, ", asr #0x%x", tmp);
1443  else
1444  SStream_concat(O, ", asr #%u", tmp);
1445  if (MI->csh->detail) {
1446  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.type = ARM_SFT_ASR;
1447  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.value = tmp;
1448  }
1449  } else if (Amt) {
1450  if (Amt > HEX_THRESHOLD)
1451  SStream_concat(O, ", lsl #0x%x", Amt);
1452  else
1453  SStream_concat(O, ", lsl #%u", Amt);
1454  if (MI->csh->detail) {
1455  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.type = ARM_SFT_LSL;
1456  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.value = Amt;
1457  }
1458  }
1459 }
1460 
1461 static void printPKHLSLShiftImm(MCInst *MI, unsigned OpNum, SStream *O)
1462 {
1463  unsigned Imm = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1464  if (Imm == 0)
1465  return;
1466  //assert(Imm > 0 && Imm < 32 && "Invalid PKH shift immediate value!");
1467  if (Imm > HEX_THRESHOLD)
1468  SStream_concat(O, ", lsl #0x%x", Imm);
1469  else
1470  SStream_concat(O, ", lsl #%u", Imm);
1471  if (MI->csh->detail) {
1472  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.type = ARM_SFT_LSL;
1473  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.value = Imm;
1474  }
1475 }
1476 
1477 static void printPKHASRShiftImm(MCInst *MI, unsigned OpNum, SStream *O)
1478 {
1479  unsigned Imm = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1480  // A shift amount of 32 is encoded as 0.
1481  if (Imm == 0)
1482  Imm = 32;
1483  //assert(Imm > 0 && Imm <= 32 && "Invalid PKH shift immediate value!");
1484  if (Imm > HEX_THRESHOLD)
1485  SStream_concat(O, ", asr #0x%x", Imm);
1486  else
1487  SStream_concat(O, ", asr #%u", Imm);
1488  if (MI->csh->detail) {
1489  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.type = ARM_SFT_ASR;
1490  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.value = Imm;
1491  }
1492 }
1493 
1494 // FIXME: push {r1, r2, r3, ...} can exceed the number of operands in MCInst struct
1495 static void printRegisterList(MCInst *MI, unsigned OpNum, SStream *O)
1496 {
1497  unsigned i, e;
1498 #ifndef CAPSTONE_DIET
1499  uint8_t access = 0;
1500 #endif
1501 
1502  SStream_concat0(O, "{");
1503 
1504 #ifndef CAPSTONE_DIET
1505  if (MI->csh->detail) {
1506  access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1507  }
1508 #endif
1509 
1510  for (i = OpNum, e = MCInst_getNumOperands(MI); i != e; ++i) {
1511  if (i != OpNum) SStream_concat0(O, ", ");
1512  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, i)));
1513  if (MI->csh->detail) {
1514  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
1515  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, i));
1516 #ifndef CAPSTONE_DIET
1517  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
1518 #endif
1519  MI->flat_insn->detail->arm.op_count++;
1520  }
1521  }
1522  SStream_concat0(O, "}");
1523 
1524 #ifndef CAPSTONE_DIET
1525  if (MI->csh->detail) {
1526  MI->ac_idx++;
1527  }
1528 #endif
1529 }
1530 
1531 static void printGPRPairOperand(MCInst *MI, unsigned OpNum, SStream *O,
1532  MCRegisterInfo *MRI)
1533 {
1534  unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
1535  printRegName(MI->csh, O, MCRegisterInfo_getSubReg(MRI, Reg, ARM_gsub_0));
1536  if (MI->csh->detail) {
1537  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
1538  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCRegisterInfo_getSubReg(MRI, Reg, ARM_gsub_0);
1539  MI->flat_insn->detail->arm.op_count++;
1540  }
1541  SStream_concat0(O, ", ");
1542  printRegName(MI->csh, O, MCRegisterInfo_getSubReg(MRI, Reg, ARM_gsub_1));
1543  if (MI->csh->detail) {
1544  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
1545  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCRegisterInfo_getSubReg(MRI, Reg, ARM_gsub_1);
1546  MI->flat_insn->detail->arm.op_count++;
1547  }
1548 }
1549 
1550 // SETEND BE/LE
1551 static void printSetendOperand(MCInst *MI, unsigned OpNum, SStream *O)
1552 {
1553  MCOperand *Op = MCInst_getOperand(MI, OpNum);
1554  if (MCOperand_getImm(Op)) {
1555  SStream_concat0(O, "be");
1556  if (MI->csh->detail) {
1557  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_SETEND;
1558  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].setend = ARM_SETEND_BE;
1559  MI->flat_insn->detail->arm.op_count++;
1560  }
1561  } else {
1562  SStream_concat0(O, "le");
1563  if (MI->csh->detail) {
1564  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_SETEND;
1565  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].setend = ARM_SETEND_LE;
1566  MI->flat_insn->detail->arm.op_count++;
1567  }
1568  }
1569 }
1570 
1571 static void printCPSIMod(MCInst *MI, unsigned OpNum, SStream *O)
1572 {
1573  MCOperand *Op = MCInst_getOperand(MI, OpNum);
1574  unsigned int mode = (unsigned int)MCOperand_getImm(Op);
1575 
1577 
1578  if (MI->csh->detail) {
1579  MI->flat_insn->detail->arm.cps_mode = mode;
1580  }
1581 }
1582 
1583 static void printCPSIFlag(MCInst *MI, unsigned OpNum, SStream *O)
1584 {
1585  MCOperand *Op = MCInst_getOperand(MI, OpNum);
1586  unsigned IFlags = (unsigned int)MCOperand_getImm(Op);
1587  int i;
1588 
1589  for (i = 2; i >= 0; --i)
1590  if (IFlags & (1 << i)) {
1592  }
1593 
1594  if (IFlags == 0) {
1595  SStream_concat0(O, "none");
1596  IFlags = ARM_CPSFLAG_NONE;
1597  }
1598 
1599  if (MI->csh->detail) {
1600  MI->flat_insn->detail->arm.cps_flag = IFlags;
1601  }
1602 }
1603 
1604 static void printMSRMaskOperand(MCInst *MI, unsigned OpNum, SStream *O)
1605 {
1606  MCOperand *Op = MCInst_getOperand(MI, OpNum);
1607  unsigned SpecRegRBit = (unsigned)MCOperand_getImm(Op) >> 4;
1608  unsigned Mask = (unsigned)MCOperand_getImm(Op) & 0xf;
1609  unsigned reg;
1610  uint64_t FeatureBits = ARM_getFeatureBits(MI->csh->mode);
1611 
1612  if (FeatureBits & ARM_FeatureMClass) {
1613  unsigned SYSm = (unsigned)MCOperand_getImm(Op);
1614  unsigned Opcode = MCInst_getOpcode(MI);
1615 
1616  // For writes, handle extended mask bits if the DSP extension is present.
1617  if (Opcode == ARM_t2MSR_M && (FeatureBits & ARM_FeatureDSPThumb2)) {
1618  switch (SYSm) {
1619  case 0x400: SStream_concat0(O, "apsr_g"); ARM_addSysReg(MI, ARM_SYSREG_APSR_G); return;
1620  case 0xc00: SStream_concat0(O, "apsr_nzcvqg"); ARM_addSysReg(MI, ARM_SYSREG_APSR_NZCVQG); return;
1621  case 0x401: SStream_concat0(O, "iapsr_g"); ARM_addSysReg(MI, ARM_SYSREG_IAPSR_G); return;
1622  case 0xc01: SStream_concat0(O, "iapsr_nzcvqg"); ARM_addSysReg(MI, ARM_SYSREG_IAPSR_NZCVQG); return;
1623  case 0x402: SStream_concat0(O, "eapsr_g"); ARM_addSysReg(MI, ARM_SYSREG_EAPSR_G); return;
1624  case 0xc02: SStream_concat0(O, "eapsr_nzcvqg"); ARM_addSysReg(MI, ARM_SYSREG_EAPSR_NZCVQG); return;
1625  case 0x403: SStream_concat0(O, "xpsr_g"); ARM_addSysReg(MI, ARM_SYSREG_XPSR_G); return;
1626  case 0xc03: SStream_concat0(O, "xpsr_nzcvqg"); ARM_addSysReg(MI, ARM_SYSREG_XPSR_NZCVQG); return;
1627  }
1628  }
1629 
1630  // Handle the basic 8-bit mask.
1631  SYSm &= 0xff;
1632 
1633  if (Opcode == ARM_t2MSR_M && (FeatureBits & ARM_HasV7Ops)) {
1634  // ARMv7-M deprecates using MSR APSR without a _<bits> qualifier as an
1635  // alias for MSR APSR_nzcvq.
1636  switch (SYSm) {
1637  case 0: SStream_concat0(O, "apsr_nzcvq"); ARM_addSysReg(MI, ARM_SYSREG_APSR_NZCVQ); return;
1638  case 1: SStream_concat0(O, "iapsr_nzcvq"); ARM_addSysReg(MI, ARM_SYSREG_IAPSR_NZCVQ); return;
1639  case 2: SStream_concat0(O, "eapsr_nzcvq"); ARM_addSysReg(MI, ARM_SYSREG_EAPSR_NZCVQ); return;
1640  case 3: SStream_concat0(O, "xpsr_nzcvq"); ARM_addSysReg(MI, ARM_SYSREG_XPSR_NZCVQ); return;
1641  }
1642  }
1643 
1644 
1645  switch (SYSm) {
1646  default: //llvm_unreachable("Unexpected mask value!");
1647  case 0: SStream_concat0(O, "apsr"); ARM_addSysReg(MI, ARM_SYSREG_APSR); return;
1648  case 1: SStream_concat0(O, "iapsr"); ARM_addSysReg(MI, ARM_SYSREG_IAPSR); return;
1649  case 2: SStream_concat0(O, "eapsr"); ARM_addSysReg(MI, ARM_SYSREG_EAPSR); return;
1650  case 3: SStream_concat0(O, "xpsr"); ARM_addSysReg(MI, ARM_SYSREG_XPSR); return;
1651  case 5: SStream_concat0(O, "ipsr"); ARM_addSysReg(MI, ARM_SYSREG_IPSR); return;
1652  case 6: SStream_concat0(O, "epsr"); ARM_addSysReg(MI, ARM_SYSREG_EPSR); return;
1653  case 7: SStream_concat0(O, "iepsr"); ARM_addSysReg(MI, ARM_SYSREG_IEPSR); return;
1654  case 8: SStream_concat0(O, "msp"); ARM_addSysReg(MI, ARM_SYSREG_MSP); return;
1655  case 9: SStream_concat0(O, "psp"); ARM_addSysReg(MI, ARM_SYSREG_PSP); return;
1656  case 16: SStream_concat0(O, "primask"); ARM_addSysReg(MI, ARM_SYSREG_PRIMASK); return;
1657  case 17: SStream_concat0(O, "basepri"); ARM_addSysReg(MI, ARM_SYSREG_BASEPRI); return;
1658  case 18: SStream_concat0(O, "basepri_max"); ARM_addSysReg(MI, ARM_SYSREG_BASEPRI_MAX); return;
1659  case 19: SStream_concat0(O, "faultmask"); ARM_addSysReg(MI, ARM_SYSREG_FAULTMASK); return;
1660  case 20: SStream_concat0(O, "control"); ARM_addSysReg(MI, ARM_SYSREG_CONTROL); return;
1661  }
1662  }
1663 
1664  // As special cases, CPSR_f, CPSR_s and CPSR_fs prefer printing as
1665  // APSR_nzcvq, APSR_g and APSRnzcvqg, respectively.
1666  if (!SpecRegRBit && (Mask == 8 || Mask == 4 || Mask == 12)) {
1667  SStream_concat0(O, "apsr_");
1668  switch (Mask) {
1669  default: // llvm_unreachable("Unexpected mask value!");
1670  case 4: SStream_concat0(O, "g"); ARM_addSysReg(MI, ARM_SYSREG_APSR_G); return;
1671  case 8: SStream_concat0(O, "nzcvq"); ARM_addSysReg(MI, ARM_SYSREG_APSR_NZCVQ); return;
1672  case 12: SStream_concat0(O, "nzcvqg"); ARM_addSysReg(MI, ARM_SYSREG_APSR_NZCVQG); return;
1673  }
1674  }
1675 
1676  reg = 0;
1677  if (SpecRegRBit) {
1678  SStream_concat0(O, "spsr");
1679  if (Mask) {
1680  SStream_concat0(O, "_");
1681  if (Mask & 8) {
1682  SStream_concat0(O, "f");
1684  }
1685 
1686  if (Mask & 4) {
1687  SStream_concat0(O, "s");
1689  }
1690 
1691  if (Mask & 2) {
1692  SStream_concat0(O, "x");
1694  }
1695 
1696  if (Mask & 1) {
1697  SStream_concat0(O, "c");
1699  }
1700  ARM_addSysReg(MI, reg);
1701  }
1702  } else {
1703  SStream_concat0(O, "cpsr");
1704  if (Mask) {
1705  SStream_concat0(O, "_");
1706  if (Mask & 8) {
1707  SStream_concat0(O, "f");
1709  }
1710 
1711  if (Mask & 4) {
1712  SStream_concat0(O, "s");
1714  }
1715 
1716  if (Mask & 2) {
1717  SStream_concat0(O, "x");
1719  }
1720 
1721  if (Mask & 1) {
1722  SStream_concat0(O, "c");
1724  }
1725  ARM_addSysReg(MI, reg);
1726  }
1727  }
1728 }
1729 
1730 static void printBankedRegOperand(MCInst *MI, unsigned OpNum, SStream *O)
1731 {
1732  uint32_t Banked = (uint32_t)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1733  uint32_t R = (Banked & 0x20) >> 5;
1734  uint32_t SysM = Banked & 0x1f;
1735  const char *RegNames[] = {
1736  "r8_usr", "r9_usr", "r10_usr", "r11_usr", "r12_usr", "sp_usr", "lr_usr", "",
1737  "r8_fiq", "r9_fiq", "r10_fiq", "r11_fiq", "r12_fiq", "sp_fiq", "lr_fiq", "",
1738  "lr_irq", "sp_irq", "lr_svc", "sp_svc", "lr_abt", "sp_abt", "lr_und", "sp_und",
1739  "", "", "", "", "lr_mon", "sp_mon", "elr_hyp", "sp_hyp"
1740  };
1741  arm_sysreg RegIds[] = {
1751  };
1752  const char *Name = RegNames[SysM];
1753 
1754  // Nothing much we can do about this, the encodings are specified in B9.2.3 of
1755  // the ARM ARM v7C, and are all over the shop.
1756  if (R) {
1757  SStream_concat0(O, "SPSR_");
1758 
1759  switch(SysM) {
1760  default: // llvm_unreachable("Invalid banked SPSR register");
1761  case 0x0e: SStream_concat0(O, "fiq"); ARM_addSysReg(MI, ARM_SYSREG_SPSR_FIQ); return;
1762  case 0x10: SStream_concat0(O, "irq"); ARM_addSysReg(MI, ARM_SYSREG_SPSR_IRQ); return;
1763  case 0x12: SStream_concat0(O, "svc"); ARM_addSysReg(MI, ARM_SYSREG_SPSR_SVC); return;
1764  case 0x14: SStream_concat0(O, "abt"); ARM_addSysReg(MI, ARM_SYSREG_SPSR_ABT); return;
1765  case 0x16: SStream_concat0(O, "und"); ARM_addSysReg(MI, ARM_SYSREG_SPSR_UND); return;
1766  case 0x1c: SStream_concat0(O, "mon"); ARM_addSysReg(MI, ARM_SYSREG_SPSR_MON); return;
1767  case 0x1e: SStream_concat0(O, "hyp"); ARM_addSysReg(MI, ARM_SYSREG_SPSR_HYP); return;
1768  }
1769  }
1770 
1771  //assert(!R && "should have dealt with SPSR regs");
1772  //assert(Name[0] && "invalid banked register operand");
1773 
1774  SStream_concat0(O, Name);
1775  ARM_addSysReg(MI, RegIds[SysM]);
1776 }
1777 
1778 static void printPredicateOperand(MCInst *MI, unsigned OpNum, SStream *O)
1779 {
1781  // Handle the undefined 15 CC value here for printing so we don't abort().
1782  if ((unsigned)CC == 15) {
1783  SStream_concat0(O, "<und>");
1784  if (MI->csh->detail)
1785  MI->flat_insn->detail->arm.cc = ARM_CC_INVALID;
1786  } else {
1787  if (CC != ARMCC_AL) {
1789  }
1790  if (MI->csh->detail)
1791  MI->flat_insn->detail->arm.cc = CC + 1;
1792  }
1793 }
1794 
1795 // TODO: test this
1796 static void printMandatoryPredicateOperand(MCInst *MI, unsigned OpNum, SStream *O)
1797 {
1800  if (MI->csh->detail)
1801  MI->flat_insn->detail->arm.cc = CC + 1;
1802 }
1803 
1804 static void printSBitModifierOperand(MCInst *MI, unsigned OpNum, SStream *O)
1805 {
1806  if (MCOperand_getReg(MCInst_getOperand(MI, OpNum))) {
1807  //assert(MCOperand_getReg(MCInst_getOperand(MI, OpNum)) == ARM_CPSR &&
1808  // "Expect ARM CPSR register!");
1809  SStream_concat0(O, "s");
1810  if (MI->csh->detail)
1811  MI->flat_insn->detail->arm.update_flags = true;
1812  }
1813 }
1814 
1815 static void printNoHashImmediate(MCInst *MI, unsigned OpNum, SStream *O)
1816 {
1817  unsigned tmp = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1818  printUInt32(O, tmp);
1819  if (MI->csh->detail) {
1820  if (MI->csh->doing_mem) {
1821  MI->flat_insn->detail->arm.op_count--;
1822  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].neon_lane = (int8_t)tmp;
1823  MI->ac_idx--; // consecutive operands share the same access right
1824  } else {
1825  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
1826  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = tmp;
1827  MI->flat_insn->detail->arm.op_count++;
1828  }
1829  }
1830 }
1831 
1832 static void printPImmediate(MCInst *MI, unsigned OpNum, SStream *O)
1833 {
1834  unsigned imm = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1835 
1836  SStream_concat(O, "p%u", imm);
1837  if (MI->csh->detail) {
1838  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_PIMM;
1839  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = imm;
1840  MI->flat_insn->detail->arm.op_count++;
1841  }
1842 }
1843 
1844 static void printCImmediate(MCInst *MI, unsigned OpNum, SStream *O)
1845 {
1846  unsigned imm = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1847 
1848  SStream_concat(O, "c%u", imm);
1849  if (MI->csh->detail) {
1850  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_CIMM;
1851  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = imm;
1852  MI->flat_insn->detail->arm.op_count++;
1853  }
1854 }
1855 
1856 static void printCoprocOptionImm(MCInst *MI, unsigned OpNum, SStream *O)
1857 {
1858  unsigned tmp = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1859  if (tmp > HEX_THRESHOLD)
1860  SStream_concat(O, "{0x%x}", tmp);
1861  else
1862  SStream_concat(O, "{%u}", tmp);
1863  if (MI->csh->detail) {
1864  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
1865  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = tmp;
1866  MI->flat_insn->detail->arm.op_count++;
1867  }
1868 }
1869 
1870 static void printAdrLabelOperand(MCInst *MI, unsigned OpNum, SStream *O, unsigned scale)
1871 {
1872  MCOperand *MO = MCInst_getOperand(MI, OpNum);
1873 
1874  int32_t OffImm = (int32_t)MCOperand_getImm(MO) << scale;
1875 
1876  if (OffImm == INT32_MIN) {
1877  SStream_concat0(O, "#-0");
1878  if (MI->csh->detail) {
1879  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
1880  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = 0;
1881  MI->flat_insn->detail->arm.op_count++;
1882  }
1883  } else {
1884  if (OffImm < 0)
1885  SStream_concat(O, "#-0x%x", -OffImm);
1886  else {
1887  if (OffImm > HEX_THRESHOLD)
1888  SStream_concat(O, "#0x%x", OffImm);
1889  else
1890  SStream_concat(O, "#%u", OffImm);
1891  }
1892  if (MI->csh->detail) {
1893  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
1894  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = OffImm;
1895  MI->flat_insn->detail->arm.op_count++;
1896  }
1897  }
1898 }
1899 
1900 static void printThumbS4ImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
1901 {
1902  unsigned tmp = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum)) * 4;
1903 
1904  printUInt32Bang(O, tmp);
1905 
1906  if (MI->csh->detail) {
1907  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
1908  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = tmp;
1909  MI->flat_insn->detail->arm.op_count++;
1910  }
1911 }
1912 
1913 static void printThumbSRImm(MCInst *MI, unsigned OpNum, SStream *O)
1914 {
1915  unsigned Imm = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1916  unsigned tmp = Imm == 0 ? 32 : Imm;
1917 
1918  printUInt32Bang(O, tmp);
1919 
1920  if (MI->csh->detail) {
1921  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
1922  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = tmp;
1923  MI->flat_insn->detail->arm.op_count++;
1924  }
1925 }
1926 
1927 static void printThumbITMask(MCInst *MI, unsigned OpNum, SStream *O)
1928 {
1929  // (3 - the number of trailing zeros) is the number of then / else.
1930  unsigned Mask = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1931  unsigned Firstcond = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum-1));
1932  unsigned CondBit0 = Firstcond & 1;
1933  unsigned NumTZ = CountTrailingZeros_32(Mask);
1934  //assert(NumTZ <= 3 && "Invalid IT mask!");
1935  unsigned Pos, e;
1936  for (Pos = 3, e = NumTZ; Pos > e; --Pos) {
1937  bool T = ((Mask >> Pos) & 1) == CondBit0;
1938  if (T)
1939  SStream_concat0(O, "t");
1940  else
1941  SStream_concat0(O, "e");
1942  }
1943 }
1944 
1945 static void printThumbAddrModeRROperand(MCInst *MI, unsigned Op, SStream *O)
1946 {
1947  MCOperand *MO1 = MCInst_getOperand(MI, Op);
1948  MCOperand *MO2 = MCInst_getOperand(MI, Op + 1);
1949  unsigned RegNum;
1950 
1951  if (!MCOperand_isReg(MO1)) { // FIXME: This is for CP entries, but isn't right.
1952  printOperand(MI, Op, O);
1953  return;
1954  }
1955 
1956  SStream_concat0(O, "[");
1957  set_mem_access(MI, true);
1958  printRegName(MI->csh, O, MCOperand_getReg(MO1));
1959  if (MI->csh->detail)
1960  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
1961  RegNum = MCOperand_getReg(MO2);
1962  if (RegNum) {
1963  SStream_concat0(O, ", ");
1964  printRegName(MI->csh, O, RegNum);
1965  if (MI->csh->detail)
1966  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = RegNum;
1967  }
1968  SStream_concat0(O, "]");
1969  set_mem_access(MI, false);
1970 }
1971 
1972 static void printThumbAddrModeImm5SOperand(MCInst *MI, unsigned Op, SStream *O,
1973  unsigned Scale)
1974 {
1975  MCOperand *MO1 = MCInst_getOperand(MI, Op);
1976  MCOperand *MO2 = MCInst_getOperand(MI, Op + 1);
1977  unsigned ImmOffs, tmp;
1978 
1979  if (!MCOperand_isReg(MO1)) { // FIXME: This is for CP entries, but isn't right.
1980  printOperand(MI, Op, O);
1981  return;
1982  }
1983 
1984  SStream_concat0(O, "[");
1985  set_mem_access(MI, true);
1986  printRegName(MI->csh, O, MCOperand_getReg(MO1));
1987  if (MI->csh->detail)
1988  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
1989  ImmOffs = (unsigned int)MCOperand_getImm(MO2);
1990  if (ImmOffs) {
1991  tmp = ImmOffs * Scale;
1992  SStream_concat0(O, ", ");
1993  printUInt32Bang(O, tmp);
1994  if (MI->csh->detail)
1995  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = tmp;
1996  }
1997  SStream_concat0(O, "]");
1998  set_mem_access(MI, false);
1999 }
2000 
2001 static void printThumbAddrModeImm5S1Operand(MCInst *MI, unsigned Op, SStream *O)
2002 {
2003  printThumbAddrModeImm5SOperand(MI, Op, O, 1);
2004 }
2005 
2006 static void printThumbAddrModeImm5S2Operand(MCInst *MI, unsigned Op, SStream *O)
2007 {
2008  printThumbAddrModeImm5SOperand(MI, Op, O, 2);
2009 }
2010 
2011 static void printThumbAddrModeImm5S4Operand(MCInst *MI, unsigned Op, SStream *O)
2012 {
2013  printThumbAddrModeImm5SOperand(MI, Op, O, 4);
2014 }
2015 
2016 static void printThumbAddrModeSPOperand(MCInst *MI, unsigned Op, SStream *O)
2017 {
2018  printThumbAddrModeImm5SOperand(MI, Op, O, 4);
2019 }
2020 
2021 // Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
2022 // register with shift forms.
2023 // REG 0 0 - e.g. R5
2024 // REG IMM, SH_OPC - e.g. R5, LSL #3
2025 static void printT2SOOperand(MCInst *MI, unsigned OpNum, SStream *O)
2026 {
2027  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
2028  MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
2029 
2030  unsigned Reg = MCOperand_getReg(MO1);
2031  printRegName(MI->csh, O, Reg);
2032  if (MI->csh->detail) {
2033  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2034  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg;
2035  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = CS_AC_READ;
2036  MI->flat_insn->detail->arm.op_count++;
2037  }
2038 
2039  // Print the shift opc.
2040  //assert(MO2.isImm() && "Not a valid t2_so_reg value!");
2041  printRegImmShift(MI, O, ARM_AM_getSORegShOp((unsigned int)MCOperand_getImm(MO2)),
2042  getSORegOffset((unsigned int)MCOperand_getImm(MO2)));
2043 }
2044 
2045 static void printAddrModeImm12Operand(MCInst *MI, unsigned OpNum,
2046  SStream *O, bool AlwaysPrintImm0)
2047 {
2048  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
2049  MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
2050  int32_t OffImm;
2051  bool isSub;
2052 
2053  if (!MCOperand_isReg(MO1)) { // FIXME: This is for CP entries, but isn't right.
2054  printOperand(MI, OpNum, O);
2055  return;
2056  }
2057 
2058  SStream_concat0(O, "[");
2059  set_mem_access(MI, true);
2060  printRegName(MI->csh, O, MCOperand_getReg(MO1));
2061 
2062  if (MI->csh->detail)
2063  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
2064 
2065  OffImm = (int32_t)MCOperand_getImm(MO2);
2066  isSub = OffImm < 0;
2067  // Special value for #-0. All others are normal.
2068  if (OffImm == INT32_MIN)
2069  OffImm = 0;
2070  if (isSub) {
2071  if (OffImm < -HEX_THRESHOLD)
2072  SStream_concat(O, ", #-0x%x", -OffImm);
2073  else
2074  SStream_concat(O, ", #-%u", -OffImm);
2075  } else if (AlwaysPrintImm0 || OffImm > 0) {
2076  if (OffImm >= 0) {
2077  if (OffImm > HEX_THRESHOLD)
2078  SStream_concat(O, ", #0x%x", OffImm);
2079  else
2080  SStream_concat(O, ", #%u", OffImm);
2081  } else {
2082  if (OffImm < -HEX_THRESHOLD)
2083  SStream_concat(O, ", #-0x%x", -OffImm);
2084  else
2085  SStream_concat(O, ", #-%u", -OffImm);
2086  }
2087  }
2088  if (MI->csh->detail)
2089  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = OffImm;
2090  SStream_concat0(O, "]");
2091  set_mem_access(MI, false);
2092 }
2093 
2094 static void printT2AddrModeImm8Operand(MCInst *MI, unsigned OpNum, SStream *O,
2095  bool AlwaysPrintImm0)
2096 {
2097  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
2098  MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
2099  int32_t OffImm;
2100  bool isSub;
2101 
2102  SStream_concat0(O, "[");
2103  set_mem_access(MI, true);
2104 
2105  printRegName(MI->csh, O, MCOperand_getReg(MO1));
2106  if (MI->csh->detail)
2107  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
2108 
2109  OffImm = (int32_t)MCOperand_getImm(MO2);
2110  isSub = OffImm < 0;
2111  // Don't print +0.
2112  if (OffImm == INT32_MIN)
2113  OffImm = 0;
2114 
2115  if (isSub)
2116  SStream_concat(O, ", #-0x%x", -OffImm);
2117  else if (AlwaysPrintImm0 || OffImm > 0) {
2118  if (OffImm > HEX_THRESHOLD)
2119  SStream_concat(O, ", #0x%x", OffImm);
2120  else
2121  SStream_concat(O, ", #%u", OffImm);
2122  }
2123 
2124  if (MI->csh->detail)
2125  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = OffImm;
2126  SStream_concat0(O, "]");
2127  set_mem_access(MI, false);
2128 }
2129 
2130 static void printT2AddrModeImm8s4Operand(MCInst *MI,
2131  unsigned OpNum, SStream *O, bool AlwaysPrintImm0)
2132 {
2133  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
2134  MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
2135  int32_t OffImm;
2136  bool isSub;
2137 
2138  if (!MCOperand_isReg(MO1)) { // For label symbolic references.
2139  printOperand(MI, OpNum, O);
2140  return;
2141  }
2142 
2143  SStream_concat0(O, "[");
2144  set_mem_access(MI, true);
2145  printRegName(MI->csh, O, MCOperand_getReg(MO1));
2146  if (MI->csh->detail)
2147  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
2148 
2149  OffImm = (int32_t)MCOperand_getImm(MO2);
2150  isSub = OffImm < 0;
2151 
2152  //assert(((OffImm & 0x3) == 0) && "Not a valid immediate!");
2153 
2154  // Don't print +0.
2155  if (OffImm == INT32_MIN)
2156  OffImm = 0;
2157  if (isSub) {
2158  SStream_concat(O, ", #-0x%x", -OffImm);
2159  } else if (AlwaysPrintImm0 || OffImm > 0) {
2160  if (OffImm > HEX_THRESHOLD)
2161  SStream_concat(O, ", #0x%x", OffImm);
2162  else
2163  SStream_concat(O, ", #%u", OffImm);
2164  }
2165  if (MI->csh->detail)
2166  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = OffImm;
2167 
2168  SStream_concat0(O, "]");
2169  set_mem_access(MI, false);
2170 }
2171 
2172 static void printT2AddrModeImm0_1020s4Operand(MCInst *MI, unsigned OpNum, SStream *O)
2173 {
2174  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
2175  MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
2176  unsigned tmp;
2177 
2178  SStream_concat0(O, "[");
2179  set_mem_access(MI, true);
2180  printRegName(MI->csh, O, MCOperand_getReg(MO1));
2181  if (MI->csh->detail)
2182  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
2183  if (MCOperand_getImm(MO2)) {
2184  SStream_concat0(O, ", ");
2185  tmp = (unsigned int)MCOperand_getImm(MO2) * 4;
2186  printUInt32Bang(O, tmp);
2187  if (MI->csh->detail)
2188  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.disp = tmp;
2189  }
2190  SStream_concat0(O, "]");
2191  set_mem_access(MI, false);
2192 }
2193 
2194 static void printT2AddrModeImm8OffsetOperand(MCInst *MI,
2195  unsigned OpNum, SStream *O)
2196 {
2197  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
2198  int32_t OffImm = (int32_t)MCOperand_getImm(MO1);
2199  SStream_concat0(O, ", ");
2200  if (OffImm == INT32_MIN) {
2201  SStream_concat0(O, "#-0");
2202  if (MI->csh->detail) {
2203  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
2204  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = 0;
2205  MI->flat_insn->detail->arm.op_count++;
2206  }
2207  } else {
2208  printInt32Bang(O, OffImm);
2209  if (MI->csh->detail) {
2210  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
2211  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = OffImm;
2212  MI->flat_insn->detail->arm.op_count++;
2213  }
2214  }
2215 }
2216 
2217 static void printT2AddrModeImm8s4OffsetOperand(MCInst *MI,
2218  unsigned OpNum, SStream *O)
2219 {
2220  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
2221  int32_t OffImm = (int32_t)MCOperand_getImm(MO1);
2222 
2223  //assert(((OffImm & 0x3) == 0) && "Not a valid immediate!");
2224 
2225  SStream_concat0(O, ", ");
2226  if (OffImm == INT32_MIN) {
2227  SStream_concat0(O, "#-0");
2228  if (MI->csh->detail) {
2229  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
2230  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = 0;
2231  MI->flat_insn->detail->arm.op_count++;
2232  }
2233  } else {
2234  printInt32Bang(O, OffImm);
2235  if (MI->csh->detail) {
2236  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
2237  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = OffImm;
2238  MI->flat_insn->detail->arm.op_count++;
2239  }
2240  }
2241 }
2242 
2243 static void printT2AddrModeSoRegOperand(MCInst *MI,
2244  unsigned OpNum, SStream *O)
2245 {
2246  MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
2247  MCOperand *MO2 = MCInst_getOperand(MI, OpNum+1);
2248  MCOperand *MO3 = MCInst_getOperand(MI, OpNum+2);
2249  unsigned ShAmt;
2250 
2251  SStream_concat0(O, "[");
2252  set_mem_access(MI, true);
2253  printRegName(MI->csh, O, MCOperand_getReg(MO1));
2254  if (MI->csh->detail)
2255  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.base = MCOperand_getReg(MO1);
2256 
2257  //assert(MCOperand_getReg(MO2.getReg() && "Invalid so_reg load / store address!");
2258  SStream_concat0(O, ", ");
2259  printRegName(MI->csh, O, MCOperand_getReg(MO2));
2260  if (MI->csh->detail)
2261  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].mem.index = MCOperand_getReg(MO2);
2262 
2263  ShAmt = (unsigned int)MCOperand_getImm(MO3);
2264  if (ShAmt) {
2265  //assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");
2266  SStream_concat0(O, ", lsl ");
2267  SStream_concat(O, "#%d", ShAmt);
2268  if (MI->csh->detail) {
2269  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.type = ARM_SFT_LSL;
2270  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].shift.value = ShAmt;
2271  }
2272  }
2273 
2274  SStream_concat0(O, "]");
2275  set_mem_access(MI, false);
2276 }
2277 
2278 static void printFPImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
2279 {
2280  MCOperand *MO = MCInst_getOperand(MI, OpNum);
2281 
2282 #if defined(_KERNEL_MODE)
2283  // Issue #681: Windows kernel does not support formatting float point
2284  SStream_concat(O, "#<float_point_unsupported>");
2285 #else
2286  SStream_concat(O, "#%e", getFPImmFloat((unsigned int)MCOperand_getImm(MO)));
2287 #endif
2288  if (MI->csh->detail) {
2289  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_FP;
2290  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].fp = getFPImmFloat((unsigned int)MCOperand_getImm(MO));
2291  MI->flat_insn->detail->arm.op_count++;
2292  }
2293 }
2294 
2295 static void printNEONModImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
2296 {
2297  unsigned EncodedImm = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2298  unsigned EltBits;
2299  uint64_t Val = ARM_AM_decodeNEONModImm(EncodedImm, &EltBits);
2300  if (Val > HEX_THRESHOLD)
2301  SStream_concat(O, "#0x%"PRIx64, Val);
2302  else
2303  SStream_concat(O, "#%"PRIu64, Val);
2304  if (MI->csh->detail) {
2305  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
2306  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = (unsigned int)Val;
2307  MI->flat_insn->detail->arm.op_count++;
2308  }
2309 }
2310 
2311 static void printImmPlusOneOperand(MCInst *MI, unsigned OpNum, SStream *O)
2312 {
2313  unsigned Imm = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2314  printUInt32Bang(O, Imm + 1);
2315  if (MI->csh->detail) {
2316  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
2317  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = Imm + 1;
2318  MI->flat_insn->detail->arm.op_count++;
2319  }
2320 }
2321 
2322 static void printRotImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
2323 {
2324  unsigned Imm = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2325  if (Imm == 0)
2326  return;
2327  SStream_concat0(O, ", ror #");
2328  switch (Imm) {
2329  default: //assert (0 && "illegal ror immediate!");
2330  case 1: SStream_concat0(O, "8"); break;
2331  case 2: SStream_concat0(O, "16"); break;
2332  case 3: SStream_concat0(O, "24"); break;
2333  }
2334  if (MI->csh->detail) {
2335  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.type = ARM_SFT_ROR;
2336  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].shift.value = Imm * 8;
2337  }
2338 }
2339 
2340 static void printModImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
2341 {
2342  MCOperand *Op = MCInst_getOperand(MI, OpNum);
2343  unsigned Bits = MCOperand_getImm(Op) & 0xFF;
2344  unsigned Rot = (MCOperand_getImm(Op) & 0xF00) >> 7;
2345  int32_t Rotated;
2346 
2347  bool PrintUnsigned = false;
2348  switch (MCInst_getOpcode(MI)) {
2349  case ARM_MOVi:
2350  // Movs to PC should be treated unsigned
2351  PrintUnsigned = (MCOperand_getReg(MCInst_getOperand(MI, OpNum - 1)) == ARM_PC);
2352  break;
2353  case ARM_MSRi:
2354  // Movs to special registers should be treated unsigned
2355  PrintUnsigned = true;
2356  break;
2357  }
2358 
2359  Rotated = rotr32(Bits, Rot);
2360  if (getSOImmVal(Rotated) == MCOperand_getImm(Op)) {
2361  // #rot has the least possible value
2362  if (PrintUnsigned) {
2363  if (Rotated > HEX_THRESHOLD || Rotated < -HEX_THRESHOLD)
2364  SStream_concat(O, "#0x%x", Rotated);
2365  else
2366  SStream_concat(O, "#%u", Rotated);
2367  } else if (Rotated >= 0) {
2368  if (Rotated > HEX_THRESHOLD)
2369  SStream_concat(O, "#0x%x", Rotated);
2370  else
2371  SStream_concat(O, "#%u", Rotated);
2372  } else {
2373  SStream_concat(O, "#0x%x", Rotated);
2374  }
2375  if (MI->csh->detail) {
2376  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
2377  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = Rotated;
2378  MI->flat_insn->detail->arm.op_count++;
2379  }
2380  return;
2381  }
2382 
2383  // Explicit #bits, #rot implied
2384  SStream_concat(O, "#%u, #%u", Bits, Rot);
2385  if (MI->csh->detail) {
2386  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
2387  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = Bits;
2388  MI->flat_insn->detail->arm.op_count++;
2389  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
2390  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = Rot;
2391  MI->flat_insn->detail->arm.op_count++;
2392  }
2393 }
2394 
2395 static void printFBits16(MCInst *MI, unsigned OpNum, SStream *O)
2396 {
2397  unsigned tmp;
2398 
2399  tmp = 16 - (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2400  printUInt32Bang(O, tmp);
2401 
2402  if (MI->csh->detail) {
2403  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
2404  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = tmp;
2405  MI->flat_insn->detail->arm.op_count++;
2406  }
2407 }
2408 
2409 static void printFBits32(MCInst *MI, unsigned OpNum, SStream *O)
2410 {
2411  unsigned tmp;
2412 
2413  tmp = 32 - (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2414  printUInt32Bang(O, tmp);
2415 
2416  if (MI->csh->detail) {
2417  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_IMM;
2418  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].imm = tmp;
2419  MI->flat_insn->detail->arm.op_count++;
2420  }
2421 }
2422 
2423 static void printVectorIndex(MCInst *MI, unsigned OpNum, SStream *O)
2424 {
2425  unsigned tmp = (unsigned int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2426  if (tmp > HEX_THRESHOLD)
2427  SStream_concat(O, "[0x%x]", tmp);
2428  else
2429  SStream_concat(O, "[%u]", tmp);
2430  if (MI->csh->detail) {
2431  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count - 1].vector_index = tmp;
2432  }
2433 }
2434 
2435 static void printVectorListOne(MCInst *MI, unsigned OpNum, SStream *O)
2436 {
2437  SStream_concat0(O, "{");
2438  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
2439  if (MI->csh->detail) {
2440 #ifndef CAPSTONE_DIET
2441  uint8_t access;
2442 
2443  access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2444 #endif
2445 
2446  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2447  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2448 #ifndef CAPSTONE_DIET
2449  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2450 #endif
2451  MI->flat_insn->detail->arm.op_count++;
2452 
2453 #ifndef CAPSTONE_DIET
2454  MI->ac_idx++;
2455 #endif
2456  }
2457  SStream_concat0(O, "}");
2458 }
2459 
2460 static void printVectorListTwo(MCInst *MI, unsigned OpNum,
2461  SStream *O, MCRegisterInfo *MRI)
2462 {
2463 #ifndef CAPSTONE_DIET
2464  uint8_t access;
2465 #endif
2466  unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2467  unsigned Reg0 = MCRegisterInfo_getSubReg(MRI, Reg, ARM_dsub_0);
2468  unsigned Reg1 = MCRegisterInfo_getSubReg(MRI, Reg, ARM_dsub_1);
2469 
2470 #ifndef CAPSTONE_DIET
2471  access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2472 #endif
2473 
2474  SStream_concat0(O, "{");
2475  printRegName(MI->csh, O, Reg0);
2476  if (MI->csh->detail) {
2477  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2478  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg0;
2479 #ifndef CAPSTONE_DIET
2480  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2481 #endif
2482  MI->flat_insn->detail->arm.op_count++;
2483  }
2484  SStream_concat0(O, ", ");
2485  printRegName(MI->csh, O, Reg1);
2486  if (MI->csh->detail) {
2487  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2488  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg1;
2489 #ifndef CAPSTONE_DIET
2490  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2491 #endif
2492  MI->flat_insn->detail->arm.op_count++;
2493  }
2494  SStream_concat0(O, "}");
2495 
2496 #ifndef CAPSTONE_DIET
2497  MI->ac_idx++;
2498 #endif
2499 }
2500 
2501 static void printVectorListTwoSpaced(MCInst *MI, unsigned OpNum,
2502  SStream *O, MCRegisterInfo *MRI)
2503 {
2504 #ifndef CAPSTONE_DIET
2505  uint8_t access;
2506 #endif
2507  unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2508  unsigned Reg0 = MCRegisterInfo_getSubReg(MRI, Reg, ARM_dsub_0);
2509  unsigned Reg1 = MCRegisterInfo_getSubReg(MRI, Reg, ARM_dsub_2);
2510 
2511 #ifndef CAPSTONE_DIET
2512  access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2513 #endif
2514 
2515  SStream_concat0(O, "{");
2516  printRegName(MI->csh, O, Reg0);
2517  if (MI->csh->detail) {
2518  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2519  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg0;
2520 #ifndef CAPSTONE_DIET
2521  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2522 #endif
2523  MI->flat_insn->detail->arm.op_count++;
2524  }
2525  SStream_concat0(O, ", ");
2526  printRegName(MI->csh, O, Reg1);
2527  if (MI->csh->detail) {
2528  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2529  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg1;
2530 #ifndef CAPSTONE_DIET
2531  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2532 #endif
2533  MI->flat_insn->detail->arm.op_count++;
2534  }
2535  SStream_concat0(O, "}");
2536 
2537 #ifndef CAPSTONE_DIET
2538  MI->ac_idx++;
2539 #endif
2540 }
2541 
2542 static void printVectorListThree(MCInst *MI, unsigned OpNum, SStream *O)
2543 {
2544 #ifndef CAPSTONE_DIET
2545  uint8_t access;
2546 
2547  access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2548 #endif
2549 
2550  // Normally, it's not safe to use register enum values directly with
2551  // addition to get the next register, but for VFP registers, the
2552  // sort order is guaranteed because they're all of the form D<n>.
2553  SStream_concat0(O, "{");
2554  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
2555  if (MI->csh->detail) {
2556  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2557  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2558 #ifndef CAPSTONE_DIET
2559  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2560 #endif
2561  MI->flat_insn->detail->arm.op_count++;
2562  }
2563  SStream_concat0(O, ", ");
2564  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1);
2565  if (MI->csh->detail) {
2566  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2567  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1;
2568 #ifndef CAPSTONE_DIET
2569  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2570 #endif
2571  MI->flat_insn->detail->arm.op_count++;
2572  }
2573  SStream_concat0(O, ", ");
2574  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);
2575  if (MI->csh->detail) {
2576  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2577  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;
2578 #ifndef CAPSTONE_DIET
2579  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2580 #endif
2581  MI->flat_insn->detail->arm.op_count++;
2582  }
2583  SStream_concat0(O, "}");
2584 
2585 #ifndef CAPSTONE_DIET
2586  MI->ac_idx++;
2587 #endif
2588 }
2589 
2590 static void printVectorListFour(MCInst *MI, unsigned OpNum, SStream *O)
2591 {
2592 #ifndef CAPSTONE_DIET
2593  uint8_t access;
2594 
2595  access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2596 #endif
2597 
2598  // Normally, it's not safe to use register enum values directly with
2599  // addition to get the next register, but for VFP registers, the
2600  // sort order is guaranteed because they're all of the form D<n>.
2601  SStream_concat0(O, "{");
2602  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
2603  if (MI->csh->detail) {
2604  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2605  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2606 #ifndef CAPSTONE_DIET
2607  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2608 #endif
2609  MI->flat_insn->detail->arm.op_count++;
2610  }
2611  SStream_concat0(O, ", ");
2612  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1);
2613  if (MI->csh->detail) {
2614  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2615  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1;
2616 #ifndef CAPSTONE_DIET
2617  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2618 #endif
2619  MI->flat_insn->detail->arm.op_count++;
2620  }
2621  SStream_concat0(O, ", ");
2622  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);
2623  if (MI->csh->detail) {
2624  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2625  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;
2626 #ifndef CAPSTONE_DIET
2627  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2628 #endif
2629  MI->flat_insn->detail->arm.op_count++;
2630  }
2631  SStream_concat0(O, ", ");
2632  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 3);
2633  if (MI->csh->detail) {
2634  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2635  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 3;
2636 #ifndef CAPSTONE_DIET
2637  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2638 #endif
2639  MI->flat_insn->detail->arm.op_count++;
2640  }
2641  SStream_concat0(O, "}");
2642 
2643 #ifndef CAPSTONE_DIET
2644  MI->ac_idx++;
2645 #endif
2646 }
2647 
2648 static void printVectorListOneAllLanes(MCInst *MI, unsigned OpNum, SStream *O)
2649 {
2650 #ifndef CAPSTONE_DIET
2651  uint8_t access;
2652 
2653  access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2654 #endif
2655 
2656  SStream_concat0(O, "{");
2657  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
2658  if (MI->csh->detail) {
2659  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2660  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2661 #ifndef CAPSTONE_DIET
2662  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2663 #endif
2664  MI->flat_insn->detail->arm.op_count++;
2665  }
2666  SStream_concat0(O, "[]}");
2667 
2668 #ifndef CAPSTONE_DIET
2669  MI->ac_idx++;
2670 #endif
2671 }
2672 
2673 static void printVectorListTwoAllLanes(MCInst *MI, unsigned OpNum,
2674  SStream *O, MCRegisterInfo *MRI)
2675 {
2676 #ifndef CAPSTONE_DIET
2677  uint8_t access;
2678 #endif
2679  unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2680  unsigned Reg0 = MCRegisterInfo_getSubReg(MRI, Reg, ARM_dsub_0);
2681  unsigned Reg1 = MCRegisterInfo_getSubReg(MRI, Reg, ARM_dsub_1);
2682 
2683 #ifndef CAPSTONE_DIET
2684  access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2685 #endif
2686 
2687  SStream_concat0(O, "{");
2688  printRegName(MI->csh, O, Reg0);
2689  if (MI->csh->detail) {
2690  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2691  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg0;
2692 #ifndef CAPSTONE_DIET
2693  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2694 #endif
2695  MI->flat_insn->detail->arm.op_count++;
2696  }
2697  SStream_concat0(O, "[], ");
2698  printRegName(MI->csh, O, Reg1);
2699  if (MI->csh->detail) {
2700  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2701  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg1;
2702 #ifndef CAPSTONE_DIET
2703  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2704 #endif
2705  MI->flat_insn->detail->arm.op_count++;
2706  }
2707  SStream_concat0(O, "[]}");
2708 
2709 #ifndef CAPSTONE_DIET
2710  MI->ac_idx++;
2711 #endif
2712 }
2713 
2714 static void printVectorListThreeAllLanes(MCInst *MI, unsigned OpNum, SStream *O)
2715 {
2716 #ifndef CAPSTONE_DIET
2717  uint8_t access;
2718 
2719  access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2720 #endif
2721 
2722  // Normally, it's not safe to use register enum values directly with
2723  // addition to get the next register, but for VFP registers, the
2724  // sort order is guaranteed because they're all of the form D<n>.
2725  SStream_concat0(O, "{");
2726  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
2727  if (MI->csh->detail) {
2728  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2729  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2730 #ifndef CAPSTONE_DIET
2731  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2732 #endif
2733  MI->flat_insn->detail->arm.op_count++;
2734  }
2735  SStream_concat0(O, "[], ");
2736  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1);
2737  if (MI->csh->detail) {
2738  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2739  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1;
2740 #ifndef CAPSTONE_DIET
2741  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2742 #endif
2743  MI->flat_insn->detail->arm.op_count++;
2744  }
2745  SStream_concat0(O, "[], ");
2746  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);
2747  if (MI->csh->detail) {
2748  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2749  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;
2750 #ifndef CAPSTONE_DIET
2751  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2752 #endif
2753  MI->flat_insn->detail->arm.op_count++;
2754  }
2755  SStream_concat0(O, "[]}");
2756 
2757 #ifndef CAPSTONE_DIET
2758  MI->ac_idx++;
2759 #endif
2760 }
2761 
2762 static void printVectorListFourAllLanes(MCInst *MI, unsigned OpNum, SStream *O)
2763 {
2764 #ifndef CAPSTONE_DIET
2765  uint8_t access;
2766 
2767  access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2768 #endif
2769 
2770  // Normally, it's not safe to use register enum values directly with
2771  // addition to get the next register, but for VFP registers, the
2772  // sort order is guaranteed because they're all of the form D<n>.
2773  SStream_concat0(O, "{");
2774  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
2775  if (MI->csh->detail) {
2776  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2777  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2778 #ifndef CAPSTONE_DIET
2779  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2780 #endif
2781  MI->flat_insn->detail->arm.op_count++;
2782  }
2783  SStream_concat0(O, "[], ");
2784  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1);
2785  if (MI->csh->detail) {
2786  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2787  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 1;
2788 #ifndef CAPSTONE_DIET
2789  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2790 #endif
2791  MI->flat_insn->detail->arm.op_count++;
2792  }
2793  SStream_concat0(O, "[], ");
2794  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);
2795  if (MI->csh->detail) {
2796  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2797  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;
2798 #ifndef CAPSTONE_DIET
2799  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2800 #endif
2801  MI->flat_insn->detail->arm.op_count++;
2802  }
2803  SStream_concat0(O, "[], ");
2804  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 3);
2805  if (MI->csh->detail) {
2806  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2807  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 3;
2808 #ifndef CAPSTONE_DIET
2809  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2810 #endif
2811  MI->flat_insn->detail->arm.op_count++;
2812  }
2813  SStream_concat0(O, "[]}");
2814 
2815 #ifndef CAPSTONE_DIET
2816  MI->ac_idx++;
2817 #endif
2818 }
2819 
2820 static void printVectorListTwoSpacedAllLanes(MCInst *MI,
2821  unsigned OpNum, SStream *O, MCRegisterInfo *MRI)
2822 {
2823 #ifndef CAPSTONE_DIET
2824  uint8_t access;
2825 #endif
2826  unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2827  unsigned Reg0 = MCRegisterInfo_getSubReg(MRI, Reg, ARM_dsub_0);
2828  unsigned Reg1 = MCRegisterInfo_getSubReg(MRI, Reg, ARM_dsub_2);
2829 
2830 #ifndef CAPSTONE_DIET
2831  access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2832 #endif
2833 
2834  SStream_concat0(O, "{");
2835  printRegName(MI->csh, O, Reg0);
2836  if (MI->csh->detail) {
2837  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2838  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg0;
2839 #ifndef CAPSTONE_DIET
2840  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2841 #endif
2842  MI->flat_insn->detail->arm.op_count++;
2843  }
2844  SStream_concat0(O, "[], ");
2845  printRegName(MI->csh, O, Reg1);
2846  if (MI->csh->detail) {
2847  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2848  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = Reg1;
2849 #ifndef CAPSTONE_DIET
2850  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2851 #endif
2852  MI->flat_insn->detail->arm.op_count++;
2853  }
2854  SStream_concat0(O, "[]}");
2855 
2856 #ifndef CAPSTONE_DIET
2857  MI->ac_idx++;
2858 #endif
2859 }
2860 
2861 static void printVectorListThreeSpacedAllLanes(MCInst *MI,
2862  unsigned OpNum, SStream *O)
2863 {
2864 #ifndef CAPSTONE_DIET
2865  uint8_t access;
2866 
2867  access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2868 #endif
2869 
2870  // Normally, it's not safe to use register enum values directly with
2871  // addition to get the next register, but for VFP registers, the
2872  // sort order is guaranteed because they're all of the form D<n>.
2873  SStream_concat0(O, "{");
2874  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
2875  if (MI->csh->detail) {
2876  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2877  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2878 #ifndef CAPSTONE_DIET
2879  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2880 #endif
2881  MI->flat_insn->detail->arm.op_count++;
2882  }
2883  SStream_concat0(O, "[], ");
2884  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);
2885  if (MI->csh->detail) {
2886  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2887  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;
2888 #ifndef CAPSTONE_DIET
2889  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2890 #endif
2891  MI->flat_insn->detail->arm.op_count++;
2892  }
2893  SStream_concat0(O, "[], ");
2894  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4);
2895  if (MI->csh->detail) {
2896  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2897  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4;
2898 #ifndef CAPSTONE_DIET
2899  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2900 #endif
2901  MI->flat_insn->detail->arm.op_count++;
2902  }
2903  SStream_concat0(O, "[]}");
2904 
2905 #ifndef CAPSTONE_DIET
2906  MI->ac_idx++;
2907 #endif
2908 }
2909 
2910 static void printVectorListFourSpacedAllLanes(MCInst *MI,
2911  unsigned OpNum, SStream *O)
2912 {
2913 #ifndef CAPSTONE_DIET
2914  uint8_t access;
2915 
2916  access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2917 #endif
2918 
2919  // Normally, it's not safe to use register enum values directly with
2920  // addition to get the next register, but for VFP registers, the
2921  // sort order is guaranteed because they're all of the form D<n>.
2922  SStream_concat0(O, "{");
2923  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
2924  if (MI->csh->detail) {
2925  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2926  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2927 #ifndef CAPSTONE_DIET
2928  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2929 #endif
2930  MI->flat_insn->detail->arm.op_count++;
2931  }
2932  SStream_concat0(O, "[], ");
2933  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);
2934  if (MI->csh->detail) {
2935  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2936  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;
2937 #ifndef CAPSTONE_DIET
2938  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2939 #endif
2940  MI->flat_insn->detail->arm.op_count++;
2941  }
2942  SStream_concat0(O, "[], ");
2943  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4);
2944  if (MI->csh->detail) {
2945  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2946  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4;
2947 #ifndef CAPSTONE_DIET
2948  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2949 #endif
2950  MI->flat_insn->detail->arm.op_count++;
2951  }
2952  SStream_concat0(O, "[], ");
2953  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 6);
2954  if (MI->csh->detail) {
2955  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2956  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 6;
2957 #ifndef CAPSTONE_DIET
2958  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2959 #endif
2960  MI->flat_insn->detail->arm.op_count++;
2961  }
2962  SStream_concat0(O, "[]}");
2963 
2964 #ifndef CAPSTONE_DIET
2965  MI->ac_idx++;
2966 #endif
2967 }
2968 
2969 static void printVectorListThreeSpaced(MCInst *MI, unsigned OpNum, SStream *O)
2970 {
2971 #ifndef CAPSTONE_DIET
2972  uint8_t access;
2973 
2974  access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2975 #endif
2976 
2977  // Normally, it's not safe to use register enum values directly with
2978  // addition to get the next register, but for VFP registers, the
2979  // sort order is guaranteed because they're all of the form D<n>.
2980  SStream_concat0(O, "{");
2981  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
2982  if (MI->csh->detail) {
2983  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2984  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2985 #ifndef CAPSTONE_DIET
2986  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2987 #endif
2988  MI->flat_insn->detail->arm.op_count++;
2989  }
2990  SStream_concat0(O, ", ");
2991  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);
2992  if (MI->csh->detail) {
2993  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
2994  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;
2995 #ifndef CAPSTONE_DIET
2996  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
2997 #endif
2998  MI->flat_insn->detail->arm.op_count++;
2999  }
3000  SStream_concat0(O, ", ");
3001  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4);
3002  if (MI->csh->detail) {
3003  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
3004  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4;
3005 #ifndef CAPSTONE_DIET
3006  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
3007 #endif
3008  MI->flat_insn->detail->arm.op_count++;
3009  }
3010  SStream_concat0(O, "}");
3011 
3012 #ifndef CAPSTONE_DIET
3013  MI->ac_idx++;
3014 #endif
3015 }
3016 
3017 static void printVectorListFourSpaced(MCInst *MI, unsigned OpNum, SStream *O)
3018 {
3019 #ifndef CAPSTONE_DIET
3020  uint8_t access;
3021 
3022  access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
3023 #endif
3024 
3025  // Normally, it's not safe to use register enum values directly with
3026  // addition to get the next register, but for VFP registers, the
3027  // sort order is guaranteed because they're all of the form D<n>.
3028  SStream_concat0(O, "{");
3029  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)));
3030  if (MI->csh->detail) {
3031  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
3032  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
3033 #ifndef CAPSTONE_DIET
3034  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
3035 #endif
3036  MI->flat_insn->detail->arm.op_count++;
3037  }
3038  SStream_concat0(O, ", ");
3039  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2);
3040  if (MI->csh->detail) {
3041  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
3042  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 2;
3043 #ifndef CAPSTONE_DIET
3044  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
3045 #endif
3046  MI->flat_insn->detail->arm.op_count++;
3047  }
3048  SStream_concat0(O, ", ");
3049  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4);
3050  if (MI->csh->detail) {
3051  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
3052  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 4;
3053 #ifndef CAPSTONE_DIET
3054  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
3055 #endif
3056  MI->flat_insn->detail->arm.op_count++;
3057  }
3058  SStream_concat0(O, ", ");
3059  printRegName(MI->csh, O, MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 6);
3060  if (MI->csh->detail) {
3061  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
3062  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) + 6;
3063 #ifndef CAPSTONE_DIET
3064  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].access = access;
3065 #endif
3066  MI->flat_insn->detail->arm.op_count++;
3067  }
3068  SStream_concat0(O, "}");
3069 
3070 #ifndef CAPSTONE_DIET
3071  MI->ac_idx++;
3072 #endif
3073 }
3074 
3076 {
3077  if (MI->csh->detail) {
3078  MI->flat_insn->detail->arm.vector_data = vd;
3079  }
3080 }
3081 
3082 void ARM_addVectorDataSize(MCInst *MI, int size)
3083 {
3084  if (MI->csh->detail) {
3085  MI->flat_insn->detail->arm.vector_size = size;
3086  }
3087 }
3088 
3089 void ARM_addReg(MCInst *MI, int reg)
3090 {
3091  if (MI->csh->detail) {
3092  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_REG;
3093  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = reg;
3094  MI->flat_insn->detail->arm.op_count++;
3095  }
3096 }
3097 
3098 void ARM_addUserMode(MCInst *MI)
3099 {
3100  if (MI->csh->detail) {
3101  MI->flat_insn->detail->arm.usermode = true;
3102  }
3103 }
3104 
3106 {
3107  if (MI->csh->detail) {
3108  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].type = ARM_OP_SYSREG;
3109  MI->flat_insn->detail->arm.operands[MI->flat_insn->detail->arm.op_count].reg = reg;
3110  MI->flat_insn->detail->arm.op_count++;
3111  }
3112 }
3113 
3114 #endif
#define T(op)
static uint64_t ARM_AM_decodeNEONModImm(unsigned ModImm, unsigned *EltBits)
static ARM_AM_ShiftOpc getAM2ShiftOpc(unsigned AM2Opc)
static unsigned char getAM3Offset(unsigned AM3Opc)
static unsigned getSORegOffset(unsigned Op)
static ARM_AM_ShiftOpc ARM_AM_getSORegShOp(unsigned Op)
static const char * ARM_AM_getAddrOpcStr(ARM_AM_AddrOpc Op)
ARM_AM_ShiftOpc
ARM_AM - ARM Addressing Mode Stuff.
@ ARM_AM_rrx
@ ARM_AM_ror
@ ARM_AM_lsl
@ ARM_AM_lsr
@ ARM_AM_no_shift
@ ARM_AM_asr
static unsigned rotr32(unsigned Val, unsigned Amt)
static const char * ARM_AM_getShiftOpcStr(ARM_AM_ShiftOpc Op)
static unsigned char ARM_AM_getAM5Offset(unsigned AM5Opc)
static ARM_AM_AddrOpc getAM2Op(unsigned AM2Opc)
static ARM_AM_AddrOpc getAM3Op(unsigned AM3Opc)
static ARM_AM_AddrOpc ARM_AM_getAM5Op(unsigned AM5Opc)
static int getSOImmVal(unsigned Arg)
static unsigned getAM2Offset(unsigned AM2Opc)
ARM_AM_AddrOpc
@ ARM_AM_sub
@ ARM_AM_add
static float getFPImmFloat(unsigned Imm)
static const char * ARMCC_ARMCondCodeToString(ARMCC_CondCodes CC)
Definition: ARMBaseInfo.h:73
static const char * ARM_PROC_IFlagsToString(unsigned val)
Definition: ARMBaseInfo.h:95
ARMCC_CondCodes
Definition: ARMBaseInfo.h:34
@ ARMCC_AL
Definition: ARMBaseInfo.h:49
static const char * ARM_ISB_InstSyncBOptToString(unsigned val)
Definition: ARMBaseInfo.h:156
static const char * ARM_MB_MemBOptToString(unsigned val, bool HasV8)
Definition: ARMBaseInfo.h:114
static const char * ARM_PROC_IModToString(unsigned val)
Definition: ARMBaseInfo.h:105
uint64_t ARM_getFeatureBits(unsigned int mode)
void ARM_addVectorDataType(MCInst *MI, arm_vectordata_type vd)
void ARM_addSysReg(MCInst *MI, arm_sysreg reg)
void ARM_addVectorDataSize(MCInst *MI, int size)
void ARM_post_printer(csh handle, cs_insn *pub_insn, char *mnem, MCInst *mci)
void ARM_printInst(MCInst *MI, SStream *O, void *Info)
void ARM_getRegName(cs_struct *handle, int value)
void ARM_addReg(MCInst *MI, int reg)
void ARM_addUserMode(MCInst *MI)
const char * ARM_reg_name2(csh handle, unsigned int reg)
const char * ARM_reg_name(csh handle, unsigned int reg)
uint8_t * ARM_get_op_access(cs_struct *h, unsigned int id)
bool ARM_blx_to_arm_mode(cs_struct *h, unsigned int insn_id)
bool ARM_rel_branch(cs_struct *h, unsigned int insn_id)
unsigned MCInst_getOpcode(const MCInst *inst)
Definition: MCInst.c:68
unsigned MCInst_getNumOperands(const MCInst *inst)
Definition: MCInst.c:83
MCOperand * MCInst_getOperand(MCInst *inst, unsigned i)
Definition: MCInst.c:78
bool MCOperand_isReg(const MCOperand *op)
Definition: MCInst.c:101
void MCInst_Init(MCInst *inst)
Definition: MCInst.c:18
void MCOperand_CreateReg0(MCInst *mcInst, unsigned Reg)
Definition: MCInst.c:158
void MCInst_setOpcodePub(MCInst *inst, unsigned Op)
Definition: MCInst.c:63
int64_t MCOperand_getImm(MCOperand *op)
Definition: MCInst.c:128
unsigned MCOperand_getReg(const MCOperand *op)
getReg - Returns the register number.
Definition: MCInst.c:117
void MCInst_addOperand2(MCInst *inst, MCOperand *Op)
Definition: MCInst.c:89
void MCInst_setOpcode(MCInst *inst, unsigned Op)
Definition: MCInst.c:58
bool MCOperand_isImm(const MCOperand *op)
Definition: MCInst.c:106
unsigned MCRegisterInfo_getMatchingSuperReg(const MCRegisterInfo *RI, unsigned Reg, unsigned SubIdx, const MCRegisterClass *RC)
const MCRegisterClass * MCRegisterInfo_getRegClass(const MCRegisterInfo *RI, unsigned i)
bool MCRegisterClass_contains(const MCRegisterClass *c, unsigned Reg)
unsigned MCRegisterInfo_getSubReg(const MCRegisterInfo *RI, unsigned Reg, unsigned Idx)
static unsigned CountLeadingZeros_32(uint32_t Value)
Definition: MathExtras.h:95
static unsigned CountTrailingZeros_32(uint32_t Value)
Definition: MathExtras.h:190
void printUInt32Bang(SStream *O, uint32_t val)
Definition: SStream.c:156
void SStream_concat(SStream *ss, const char *fmt,...)
Definition: SStream.c:45
void printInt32Bang(SStream *O, int32_t val)
Definition: SStream.c:118
void SStream_concat0(SStream *ss, const char *s)
Definition: SStream.c:31
void printUInt32(SStream *O, uint32_t val)
Definition: SStream.c:164
void op_addImm(MCInst *MI, int v)
#define e(frag)
#define imm
lzma_index ** i
Definition: index.h:629
#define R(x, b, m)
Definition: arc.h:168
@ ARM_PC
Definition: armass64.c:25
@ ARM_SP
Definition: armass64.c:24
ut16 val
Definition: armass64_const.h:6
static mcore_handle handle
Definition: asm_mcore.c:8
@ ARM_INS_VPOP
Definition: arm.h:879
@ ARM_INS_TEQ
Definition: arm.h:670
@ ARM_INS_UADD8
Definition: arm.h:674
@ ARM_INS_SEVL
Definition: arm.h:877
@ ARM_INS_ADC
Definition: arm.h:446
@ ARM_INS_ORN
Definition: arm.h:860
@ ARM_INS_SUB
Definition: arm.h:660
@ ARM_INS_ASR
Definition: arm.h:853
@ ARM_INS_RSB
Definition: arm.h:562
@ ARM_INS_AND
Definition: arm.h:453
@ ARM_INS_SMULL
Definition: arm.h:618
@ ARM_INS_TST
Definition: arm.h:672
@ ARM_INS_SEV
Definition: arm.h:876
@ ARM_INS_PUSH
Definition: arm.h:869
@ ARM_INS_MOV
Definition: arm.h:527
@ ARM_INS_LDM
Definition: arm.h:504
@ ARM_INS_VPUSH
Definition: arm.h:878
@ ARM_INS_WFI
Definition: arm.h:875
@ ARM_INS_LSL
Definition: arm.h:858
@ ARM_INS_LSR
Definition: arm.h:859
@ ARM_INS_UMULL
Definition: arm.h:687
@ ARM_INS_BIC
Definition: arm.h:456
@ ARM_INS_MUL
Definition: arm.h:536
@ ARM_INS_UMLAL
Definition: arm.h:686
@ ARM_INS_EOR
Definition: arm.h:479
@ ARM_INS_NOP
Definition: arm.h:872
@ ARM_INS_ADD
Definition: arm.h:447
@ ARM_INS_POP
Definition: arm.h:868
@ ARM_INS_RSC
Definition: arm.h:563
@ ARM_INS_CMN
Definition: arm.h:467
@ ARM_INS_ERET
Definition: arm.h:480
@ ARM_INS_ROR
Definition: arm.h:861
@ ARM_INS_SBC
Definition: arm.h:567
@ ARM_INS_MVN
Definition: arm.h:537
@ ARM_INS_SMLAL
Definition: arm.h:593
@ ARM_INS_MLA
Definition: arm.h:525
@ ARM_INS_CMP
Definition: arm.h:468
@ ARM_INS_YIELD
Definition: arm.h:873
@ ARM_INS_RRX
Definition: arm.h:862
@ ARM_INS_ORR
Definition: arm.h:538
@ ARM_INS_WFE
Definition: arm.h:874
arm_shifter
ARM shift type.
Definition: arm.h:18
@ ARM_SFT_ASR
shift with immediate const
Definition: arm.h:20
@ ARM_SFT_ROR
shift with immediate const
Definition: arm.h:23
@ ARM_SFT_LSL
shift with immediate const
Definition: arm.h:21
@ ARM_SFT_ASR_REG
shift with register
Definition: arm.h:25
@ ARM_SETEND_LE
LE operand.
Definition: arm.h:177
@ ARM_SETEND_BE
BE operand.
Definition: arm.h:176
arm_sysreg
Definition: arm.h:52
@ ARM_SYSREG_BASEPRI
Definition: arm.h:96
@ ARM_SYSREG_SP_MON
Definition: arm.h:125
@ ARM_SYSREG_LR_USR
Definition: arm.h:108
@ ARM_SYSREG_SP_UND
Definition: arm.h:123
@ ARM_SYSREG_R9_FIQ
Definition: arm.h:110
@ ARM_SYSREG_BASEPRI_MAX
Definition: arm.h:97
@ ARM_SYSREG_ELR_HYP
Definition: arm.h:126
@ ARM_SYSREG_EAPSR_NZCVQG
Definition: arm.h:81
@ ARM_SYSREG_R9_USR
Definition: arm.h:103
@ ARM_SYSREG_EAPSR
Definition: arm.h:79
@ ARM_SYSREG_R10_FIQ
Definition: arm.h:111
@ ARM_SYSREG_APSR_NZCVQG
Definition: arm.h:72
@ ARM_SYSREG_LR_MON
Definition: arm.h:124
@ ARM_SYSREG_R11_USR
Definition: arm.h:105
@ ARM_SYSREG_SPSR_SVC
Definition: arm.h:131
@ ARM_SYSREG_CPSR_C
Definition: arm.h:63
@ ARM_SYSREG_IAPSR_NZCVQG
Definition: arm.h:76
@ ARM_SYSREG_EAPSR_G
Definition: arm.h:80
@ ARM_SYSREG_IAPSR
Definition: arm.h:74
@ ARM_SYSREG_PSP
Definition: arm.h:94
@ ARM_SYSREG_SP_IRQ
Definition: arm.h:117
@ ARM_SYSREG_SPSR_FIQ
Definition: arm.h:129
@ ARM_SYSREG_IPSR
Definition: arm.h:89
@ ARM_SYSREG_R12_USR
Definition: arm.h:106
@ ARM_SYSREG_SPSR_MON
Definition: arm.h:134
@ ARM_SYSREG_IAPSR_G
Definition: arm.h:75
@ ARM_SYSREG_LR_UND
Definition: arm.h:122
@ ARM_SYSREG_SPSR_ABT
Definition: arm.h:132
@ ARM_SYSREG_EPSR
Definition: arm.h:90
@ ARM_SYSREG_LR_FIQ
Definition: arm.h:115
@ ARM_SYSREG_XPSR_NZCVQG
Definition: arm.h:86
@ ARM_SYSREG_LR_IRQ
Definition: arm.h:116
@ ARM_SYSREG_SPSR_HYP
Definition: arm.h:135
@ ARM_SYSREG_SP_SVC
Definition: arm.h:119
@ ARM_SYSREG_XPSR_G
Definition: arm.h:85
@ ARM_SYSREG_IAPSR_NZCVQ
Definition: arm.h:77
@ ARM_SYSREG_SPSR_UND
Definition: arm.h:133
@ ARM_SYSREG_EAPSR_NZCVQ
Definition: arm.h:82
@ ARM_SYSREG_R8_FIQ
Definition: arm.h:109
@ ARM_SYSREG_SPSR_S
Definition: arm.h:59
@ ARM_SYSREG_SP_ABT
Definition: arm.h:121
@ ARM_SYSREG_SP_HYP
Definition: arm.h:127
@ ARM_SYSREG_XPSR
Definition: arm.h:84
@ ARM_SYSREG_CPSR_X
Definition: arm.h:64
@ ARM_SYSREG_SP_FIQ
Definition: arm.h:114
@ ARM_SYSREG_APSR_G
Definition: arm.h:70
@ ARM_SYSREG_R12_FIQ
Definition: arm.h:113
@ ARM_SYSREG_SPSR_X
Definition: arm.h:58
@ ARM_SYSREG_FAULTMASK
Definition: arm.h:98
@ ARM_SYSREG_APSR
Definition: arm.h:69
@ ARM_SYSREG_CPSR_S
Definition: arm.h:65
@ ARM_SYSREG_SP_USR
Definition: arm.h:107
@ ARM_SYSREG_R11_FIQ
Definition: arm.h:112
@ ARM_SYSREG_CONTROL
Definition: arm.h:99
@ ARM_SYSREG_R10_USR
Definition: arm.h:104
@ ARM_SYSREG_MSP
Definition: arm.h:93
@ ARM_SYSREG_LR_ABT
Definition: arm.h:120
@ ARM_SYSREG_APSR_NZCVQ
Definition: arm.h:71
@ ARM_SYSREG_SPSR_IRQ
Definition: arm.h:130
@ ARM_SYSREG_PRIMASK
Definition: arm.h:95
@ ARM_SYSREG_LR_SVC
Definition: arm.h:118
@ ARM_SYSREG_R8_USR
Definition: arm.h:102
@ ARM_SYSREG_SPSR_F
Definition: arm.h:60
@ ARM_SYSREG_SPSR_C
Definition: arm.h:57
@ ARM_SYSREG_XPSR_NZCVQ
Definition: arm.h:87
@ ARM_SYSREG_IEPSR
Definition: arm.h:91
@ ARM_SYSREG_CPSR_F
Definition: arm.h:66
arm_mem_barrier
Definition: arm.h:140
@ ARM_OP_IMM
= CS_OP_IMM (Immediate operand).
Definition: arm.h:164
@ ARM_OP_REG
= CS_OP_REG (Register operand).
Definition: arm.h:163
@ ARM_OP_CIMM
C-Immediate (coprocessor registers)
Definition: arm.h:167
@ ARM_OP_SETEND
operand for SETEND instruction
Definition: arm.h:169
@ ARM_OP_PIMM
P-Immediate (coprocessor registers)
Definition: arm.h:168
@ ARM_OP_MEM
= CS_OP_MEM (Memory operand).
Definition: arm.h:165
@ ARM_OP_FP
= CS_OP_FP (Floating-Point operand).
Definition: arm.h:166
@ ARM_OP_SYSREG
MSR/MRS special register operand.
Definition: arm.h:170
@ ARM_CC_AL
Always (unconditional) Always (unconditional)
Definition: arm.h:49
@ ARM_CC_INVALID
Definition: arm.h:34
@ ARM_CPSFLAG_NONE
no flag
Definition: arm.h:192
arm_vectordata_type
Data type for elements of vector instructions.
Definition: arm.h:196
@ ARM_REG_INVALID
Definition: arm.h:253
@ ARM_REG_CPSR
Definition: arm.h:256
@ ARM_REG_LR
Definition: arm.h:263
@ ARM_REG_SP
Definition: arm.h:265
@ ARM_REG_PC
Definition: arm.h:264
@ CS_MODE_THUMB
ARM's Thumb mode, including Thumb-2.
Definition: capstone.h:108
size_t csh
Definition: capstone.h:71
@ CS_OPT_SYNTAX_NOREGNAME
Prints register name with only number (CS_OPT_SYNTAX)
Definition: capstone.h:187
@ CS_OPT_ON
Turn ON an option (CS_OPT_DETAIL, CS_OPT_SKIPDATA).
Definition: capstone.h:183
@ CS_AC_READ
Operand read from memory or register.
Definition: capstone.h:204
@ CS_AC_WRITE
Operand write to memory or register.
Definition: capstone.h:205
static int value
Definition: cmd_api.c:93
#define NULL
Definition: cris-opc.c:27
ush Pos
Definition: deflate.h:92
static ut64 opc
Definition: desil.c:33
const char * v
Definition: dsignal.c:12
@ OS
Definition: inflate.h:24
voidpf void uLong size
Definition: ioapi.h:138
const char int mode
Definition: ioapi.h:137
#define reg(n)
#define PRIu64
Definition: macros.h:18
static static fork const void static count static fd const char static mode const char static pathname const char static path const char static dev const char static group static getpid static getuid void void static data static pause access
Definition: sflib.h:64
static const char struct stat static buf struct stat static buf static vhangup int status
Definition: sflib.h:145
static void struct sockaddr socklen_t static fromlen static backlog static fork char char char static envp int struct rusage static rusage struct utsname static buf struct sembuf unsigned
Definition: sflib.h:97
#define ARR_SIZE(a)
Definition: ocaml.c:13
#define O
Definition: rcond.c:14
static int
Definition: sfsocketcall.h:114
int int32_t
Definition: sftypes.h:33
unsigned int uint32_t
Definition: sftypes.h:29
unsigned long uint64_t
Definition: sftypes.h:28
unsigned char uint8_t
Definition: sftypes.h:31
char int8_t
Definition: sftypes.h:35
#define h(i)
Definition: sha256.c:48
#define INT32_MIN
Definition: MCInst.h:88
cs_insn * flat_insn
Definition: MCInst.h:95
cs_struct * csh
Definition: MCInst.h:97
uint8_t ac_idx
Definition: MCInst.h:107
unsigned Opcode
Definition: MCInst.h:93
bool writeback
Definition: MCInst.h:105
uint64_t address
Definition: MCInst.h:96
Definition: SStream.h:9
bool doing_mem
Definition: cs_priv.h:70
cs_mode mode
Definition: cs_priv.h:56
cs_opt_value imm_unsigned
Definition: cs_priv.h:68
cs_opt_value detail
Definition: cs_priv.h:68
Definition: utils.h:36
Definition: z80asm.h:102
#define HEX_THRESHOLD
Definition: utils.h:16
#define CS_AC_IGNORE
Definition: utils.h:64
int width
Definition: main.c:10
#define PRIx64
Definition: sysdefs.h:94
if(dbg->bits==RZ_SYS_BITS_64)
Definition: windows-arm64.h:4