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)));
592  printUInt32Bang(O, tmp);
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 
851  imm = (int32_t)MCOperand_getImm(Op);
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;
875  printUInt32Bang(O, imm);
876  } else {
877  switch(MI->flat_insn->id) {
878  default:
879  if (MI->csh->imm_unsigned)
880  printUInt32Bang(O, imm);
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
890  printUInt32Bang(O, imm);
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");
1683  reg += ARM_SYSREG_SPSR_F;
1684  }
1685 
1686  if (Mask & 4) {
1687  SStream_concat0(O, "s");
1688  reg += ARM_SYSREG_SPSR_S;
1689  }
1690 
1691  if (Mask & 2) {
1692  SStream_concat0(O, "x");
1693  reg += ARM_SYSREG_SPSR_X;
1694  }
1695 
1696  if (Mask & 1) {
1697  SStream_concat0(O, "c");
1698  reg += ARM_SYSREG_SPSR_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");
1708  reg += ARM_SYSREG_CPSR_F;
1709  }
1710 
1711  if (Mask & 4) {
1712  SStream_concat0(O, "s");
1713  reg += ARM_SYSREG_CPSR_S;
1714  }
1715 
1716  if (Mask & 2) {
1717  SStream_concat0(O, "x");
1718  reg += ARM_SYSREG_CPSR_X;
1719  }
1720 
1721  if (Mask & 1) {
1722  SStream_concat0(O, "c");
1723  reg += ARM_SYSREG_CPSR_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 
3105 void ARM_addSysReg(MCInst *MI, arm_sysreg reg)
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
ARM_SYSREG_SP_ABT
@ ARM_SYSREG_SP_ABT
Definition: arm.h:121
ARM_SYSREG_LR_MON
@ ARM_SYSREG_LR_MON
Definition: arm.h:124
ARM_INS_MLA
@ ARM_INS_MLA
Definition: arm.h:525
MCOperand_getReg
unsigned MCOperand_getReg(const MCOperand *op)
getReg - Returns the register number.
Definition: MCInst.c:114
ARM_get_op_access
uint8_t * ARM_get_op_access(cs_struct *h, unsigned int id)
width
int width
Definition: libuv/docs/code/tty-gravity/main.c:10
ARM_post_printer
void ARM_post_printer(csh handle, cs_insn *pub_insn, char *mnem, MCInst *mci)
CS_OPT_SYNTAX_NOREGNAME
@ CS_OPT_SYNTAX_NOREGNAME
Prints register name with only number (CS_OPT_SYNTAX)
Definition: capstone.h:188
cs_struct::mode
cs_mode mode
Definition: cs_priv.h:53
ARM_SYSREG_SP_SVC
@ ARM_SYSREG_SP_SVC
Definition: arm.h:119
ARM_SYSREG_CONTROL
@ ARM_SYSREG_CONTROL
Definition: arm.h:99
ARM_SYSREG_LR_UND
@ ARM_SYSREG_LR_UND
Definition: arm.h:122
absl::str_format_internal::LengthMod::j
@ j
ARM_SYSREG_SP_HYP
@ ARM_SYSREG_SP_HYP
Definition: arm.h:127
cs_struct::doing_mem
bool doing_mem
Definition: cs_priv.h:67
ARM_SYSREG_SP_FIQ
@ ARM_SYSREG_SP_FIQ
Definition: arm.h:114
ARM_SYSREG_IEPSR
@ ARM_SYSREG_IEPSR
Definition: arm.h:91
ARM_REG_CPSR
@ ARM_REG_CPSR
Definition: arm.h:256
ARM_AM_decodeNEONModImm
static uint64_t ARM_AM_decodeNEONModImm(unsigned ModImm, unsigned *EltBits)
Definition: ARMAddressingModes.h:599
MCInst_addOperand2
void MCInst_addOperand2(MCInst *inst, MCOperand *Op)
Definition: MCInst.c:86
ARM_SYSREG_SPSR_SVC
@ ARM_SYSREG_SPSR_SVC
Definition: arm.h:131
MCOperand
Definition: MCInst.h:30
arm_sysreg
arm_sysreg
Definition: arm.h:52
ARMInstPrinter.h
cs_struct::imm_unsigned
cs_opt_value imm_unsigned
Definition: cs_priv.h:65
MCOperand_CreateReg0
void MCOperand_CreateReg0(MCInst *mcInst, unsigned Reg)
Definition: MCInst.c:155
MCInst::Opcode
unsigned Opcode
Definition: MCInst.h:93
ARM_rel_branch
bool ARM_rel_branch(cs_struct *h, unsigned int insn_id)
ARM_MB_MemBOptToString
static const char * ARM_MB_MemBOptToString(unsigned val, bool HasV8)
Definition: ARMBaseInfo.h:114
ARM_AM_getAddrOpcStr
static const char * ARM_AM_getAddrOpcStr(ARM_AM_AddrOpc Op)
Definition: ARMAddressingModes.h:38
MCInst::address
uint64_t address
Definition: MCInst.h:96
ARM_AM_rrx
@ ARM_AM_rrx
Definition: ARMAddressingModes.h:30
ARM_SYSREG_SPSR_C
@ ARM_SYSREG_SPSR_C
Definition: arm.h:57
ARMCC_AL
@ ARMCC_AL
Definition: ARMBaseInfo.h:49
ARM_AM_ShiftOpc
ARM_AM_ShiftOpc
ARM_AM - ARM Addressing Mode Stuff.
Definition: ARMAddressingModes.h:24
ARM_INS_MVN
@ ARM_INS_MVN
Definition: arm.h:537
string.h
ARM_INS_RSB
@ ARM_INS_RSB
Definition: arm.h:562
ARM_INS_PUSH
@ ARM_INS_PUSH
Definition: arm.h:869
ARM_SYSREG_SPSR_S
@ ARM_SYSREG_SPSR_S
Definition: arm.h:59
ARM_SYSREG_R10_USR
@ ARM_SYSREG_R10_USR
Definition: arm.h:104
ARM_SYSREG_R8_USR
@ ARM_SYSREG_R8_USR
Definition: arm.h:102
ARMCC_CondCodes
ARMCC_CondCodes
Definition: ARMBaseInfo.h:34
MCInst_getOperand
MCOperand * MCInst_getOperand(MCInst *inst, unsigned i)
Definition: MCInst.c:75
ARM_SYSREG_EAPSR_NZCVQG
@ ARM_SYSREG_EAPSR_NZCVQG
Definition: arm.h:81
ARM_AM_getSORegShOp
static ARM_AM_ShiftOpc ARM_AM_getSORegShOp(unsigned Op)
Definition: ARMAddressingModes.h:125
MCRegisterInfo_getSubReg
unsigned MCRegisterInfo_getSubReg(const MCRegisterInfo *RI, unsigned Reg, unsigned Idx)
Definition: MCRegisterInfo.c:108
Pos
ush Pos
Definition: bloaty/third_party/zlib/deflate.h:92
arm_vectordata_type
arm_vectordata_type
Data type for elements of vector instructions.
Definition: arm.h:196
ARM_CPSFLAG_NONE
@ ARM_CPSFLAG_NONE
no flag
Definition: arm.h:192
ARM_SYSREG_IAPSR_G
@ ARM_SYSREG_IAPSR_G
Definition: arm.h:75
ARM_SYSREG_SPSR_IRQ
@ ARM_SYSREG_SPSR_IRQ
Definition: arm.h:130
status
absl::Status status
Definition: rls.cc:251
ARM_SYSREG_IPSR
@ ARM_SYSREG_IPSR
Definition: arm.h:89
mode
const char int mode
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:135
setup.name
name
Definition: setup.py:542
ARM_SYSREG_R11_USR
@ ARM_SYSREG_R11_USR
Definition: arm.h:105
ARM_getFeatureBits
uint64_t ARM_getFeatureBits(unsigned int mode)
ARM_printInst
void ARM_printInst(MCInst *MI, SStream *O, void *Info)
detail
Definition: test_winkernel.cpp:39
ARM_SYSREG_IAPSR_NZCVQG
@ ARM_SYSREG_IAPSR_NZCVQG
Definition: arm.h:76
ARM_INS_TEQ
@ ARM_INS_TEQ
Definition: arm.h:670
ARM_SYSREG_LR_ABT
@ ARM_SYSREG_LR_ABT
Definition: arm.h:120
uint8_t
unsigned char uint8_t
Definition: stdint-msvc2008.h:78
ARM_SYSREG_SPSR_ABT
@ ARM_SYSREG_SPSR_ABT
Definition: arm.h:132
ARM_SYSREG_PRIMASK
@ ARM_SYSREG_PRIMASK
Definition: arm.h:95
MCInst::csh
cs_struct * csh
Definition: MCInst.h:97
ARM_REG_PC
@ ARM_REG_PC
Definition: arm.h:264
T
#define T(upbtypeconst, upbtype, ctype, default_value)
CS_AC_READ
@ CS_AC_READ
Operand read from memory or register.
Definition: capstone.h:205
ARM_AM_asr
@ ARM_AM_asr
Definition: ARMAddressingModes.h:26
ARM_PROC_IFlagsToString
static const char * ARM_PROC_IFlagsToString(unsigned val)
Definition: ARMBaseInfo.h:95
MCOperand_getImm
int64_t MCOperand_getImm(MCOperand *op)
Definition: MCInst.c:125
uint32_t
unsigned int uint32_t
Definition: stdint-msvc2008.h:80
ARM_INS_POP
@ ARM_INS_POP
Definition: arm.h:868
cs_struct
Definition: cs_priv.h:51
ARM_INS_ADD
@ ARM_INS_ADD
Definition: arm.h:447
printInt32Bang
void printInt32Bang(SStream *O, int32_t val)
Definition: SStream.c:115
ARM_INS_LSR
@ ARM_INS_LSR
Definition: arm.h:859
ARM_REG_INVALID
@ ARM_REG_INVALID
Definition: arm.h:253
absl::FormatConversionChar::e
@ e
printUInt32Bang
void printUInt32Bang(SStream *O, uint32_t val)
Definition: SStream.c:153
ARM_SYSREG_R12_FIQ
@ ARM_SYSREG_R12_FIQ
Definition: arm.h:113
ARM_REG_SP
@ ARM_REG_SP
Definition: arm.h:265
ARM_SYSREG_R8_FIQ
@ ARM_SYSREG_R8_FIQ
Definition: arm.h:109
MCInst_getNumOperands
unsigned MCInst_getNumOperands(const MCInst *inst)
Definition: MCInst.c:80
ARM_INS_SEV
@ ARM_INS_SEV
Definition: arm.h:876
ARM_SYSREG_SP_UND
@ ARM_SYSREG_SP_UND
Definition: arm.h:123
xds_interop_client.int
int
Definition: xds_interop_client.py:113
ARM_ISB_InstSyncBOptToString
static const char * ARM_ISB_InstSyncBOptToString(unsigned val)
Definition: ARMBaseInfo.h:156
ARM_INS_CMN
@ ARM_INS_CMN
Definition: arm.h:467
SStream
Definition: SStream.h:9
MCRegisterClass_contains
bool MCRegisterClass_contains(const MCRegisterClass *c, unsigned Reg)
Definition: MCRegisterInfo.c:134
getAM2Offset
static unsigned getAM2Offset(unsigned AM2Opc)
Definition: ARMAddressingModes.h:450
ARM_INS_TST
@ ARM_INS_TST
Definition: arm.h:672
ARM_INS_LSL
@ ARM_INS_LSL
Definition: arm.h:858
arm_shifter
arm_shifter
ARM shift type.
Definition: arm.h:18
ARM_AM_lsr
@ ARM_AM_lsr
Definition: ARMAddressingModes.h:28
ARM_SYSREG_APSR_NZCVQG
@ ARM_SYSREG_APSR_NZCVQG
Definition: arm.h:72
HEX_THRESHOLD
#define HEX_THRESHOLD
Definition: utils.h:16
ARM_SYSREG_R10_FIQ
@ ARM_SYSREG_R10_FIQ
Definition: arm.h:111
ARM_INS_LDM
@ ARM_INS_LDM
Definition: arm.h:504
setup.v
v
Definition: third_party/bloaty/third_party/capstone/bindings/python/setup.py:42
ARM_getRegName
void ARM_getRegName(cs_struct *handle, int value)
ARM_INS_CMP
@ ARM_INS_CMP
Definition: arm.h:468
ARM_SFT_ASR_REG
@ ARM_SFT_ASR_REG
shift with register
Definition: arm.h:25
ARM_SFT_LSL
@ ARM_SFT_LSL
shift with immediate const
Definition: arm.h:21
ARM_SYSREG_ELR_HYP
@ ARM_SYSREG_ELR_HYP
Definition: arm.h:126
ARM_SYSREG_XPSR_NZCVQ
@ ARM_SYSREG_XPSR_NZCVQ
Definition: arm.h:87
platform.h
uint64_t
unsigned __int64 uint64_t
Definition: stdint-msvc2008.h:90
ARM_INS_ROR
@ ARM_INS_ROR
Definition: arm.h:861
ARM_SYSREG_CPSR_S
@ ARM_SYSREG_CPSR_S
Definition: arm.h:65
ARM_OP_PIMM
@ ARM_OP_PIMM
P-Immediate (coprocessor registers)
Definition: arm.h:168
ARM_addVectorDataSize
void ARM_addVectorDataSize(MCInst *MI, int size)
getAM2ShiftOpc
static ARM_AM_ShiftOpc getAM2ShiftOpc(unsigned AM2Opc)
Definition: ARMAddressingModes.h:460
ARM_SETEND_LE
@ ARM_SETEND_LE
LE operand.
Definition: arm.h:177
ARM_SYSREG_BASEPRI_MAX
@ ARM_SYSREG_BASEPRI_MAX
Definition: arm.h:97
ARM_INS_SUB
@ ARM_INS_SUB
Definition: arm.h:660
op_addImm
void op_addImm(MCInst *MI, int v)
cs_struct::detail
cs_opt_value detail
Definition: cs_priv.h:65
ARM_AM_getShiftOpcStr
static const char * ARM_AM_getShiftOpcStr(ARM_AM_ShiftOpc Op)
Definition: ARMAddressingModes.h:43
ARM_SYSREG_LR_SVC
@ ARM_SYSREG_LR_SVC
Definition: arm.h:118
MCRegisterClass
Definition: MCRegisterInfo.h:29
SStream_concat0
void SStream_concat0(SStream *ss, const char *s)
Definition: SStream.c:31
arm_mem_barrier
arm_mem_barrier
Definition: arm.h:140
CS_OPT_ON
@ CS_OPT_ON
Turn ON an option (CS_OPT_DETAIL, CS_OPT_SKIPDATA).
Definition: capstone.h:184
ARM_SYSREG_FAULTMASK
@ ARM_SYSREG_FAULTMASK
Definition: arm.h:98
MCInst::ac_idx
uint8_t ac_idx
Definition: MCInst.h:107
getSOImmVal
static int getSOImmVal(unsigned Arg)
Definition: ARMAddressingModes.h:184
CS_MODE_THUMB
@ CS_MODE_THUMB
ARM's Thumb mode, including Thumb-2.
Definition: capstone.h:109
ARM_SYSREG_PSP
@ ARM_SYSREG_PSP
Definition: arm.h:94
ARM_CC_INVALID
@ ARM_CC_INVALID
Definition: arm.h:34
ARM_INS_SBC
@ ARM_INS_SBC
Definition: arm.h:567
RegNames
static const char * RegNames[]
Definition: MOS65XXDisassembler.c:271
ARM_SYSREG_CPSR_F
@ ARM_SYSREG_CPSR_F
Definition: arm.h:66
ARM_SYSREG_R11_FIQ
@ ARM_SYSREG_R11_FIQ
Definition: arm.h:112
ARM_OP_REG
@ ARM_OP_REG
= CS_OP_REG (Register operand).
Definition: arm.h:163
bm_speedup.scale
def scale(a, mul)
Definition: bm_speedup.py:24
ARM_SYSREG_R12_USR
@ ARM_SYSREG_R12_USR
Definition: arm.h:106
ARM_INS_SEVL
@ ARM_INS_SEVL
Definition: arm.h:877
ARM_SYSREG_EAPSR
@ ARM_SYSREG_EAPSR
Definition: arm.h:79
getFPImmFloat
static float getFPImmFloat(unsigned Imm)
Definition: ARMAddressingModes.h:643
ARM_INS_NOP
@ ARM_INS_NOP
Definition: arm.h:872
ARM_INS_UMLAL
@ ARM_INS_UMLAL
Definition: arm.h:686
ARM_SYSREG_EPSR
@ ARM_SYSREG_EPSR
Definition: arm.h:90
ARM_OP_SYSREG
@ ARM_OP_SYSREG
MSR/MRS special register operand.
Definition: arm.h:170
ARM_SYSREG_LR_USR
@ ARM_SYSREG_LR_USR
Definition: arm.h:108
ARM_OP_FP
@ ARM_OP_FP
= CS_OP_FP (Floating-Point operand).
Definition: arm.h:166
ARM_PROC_IModToString
static const char * ARM_PROC_IModToString(unsigned val)
Definition: ARMBaseInfo.h:105
ARM_INS_ERET
@ ARM_INS_ERET
Definition: arm.h:480
ARM_INS_YIELD
@ ARM_INS_YIELD
Definition: arm.h:873
ARM_SYSREG_R9_USR
@ ARM_SYSREG_R9_USR
Definition: arm.h:103
ARM_INS_WFI
@ ARM_INS_WFI
Definition: arm.h:875
ARM_SYSREG_CPSR_X
@ ARM_SYSREG_CPSR_X
Definition: arm.h:64
ARM_INS_RRX
@ ARM_INS_RRX
Definition: arm.h:862
ARM_INS_BIC
@ ARM_INS_BIC
Definition: arm.h:456
ARM_INS_MUL
@ ARM_INS_MUL
Definition: arm.h:536
ARM_INS_AND
@ ARM_INS_AND
Definition: arm.h:453
value
const char * value
Definition: hpack_parser_table.cc:165
csh
size_t csh
Definition: capstone.h:71
ARMDisassembler.h
ARM_AM_AddrOpc
ARM_AM_AddrOpc
Definition: ARMAddressingModes.h:33
ARMBaseInfo.h
CS_AC_IGNORE
#define CS_AC_IGNORE
Definition: utils.h:64
MCInst
Definition: MCInst.h:88
ARM_blx_to_arm_mode
bool ARM_blx_to_arm_mode(cs_struct *h, unsigned int insn_id)
ARM_SYSREG_SPSR_X
@ ARM_SYSREG_SPSR_X
Definition: arm.h:58
MCRegisterInfo_getMatchingSuperReg
unsigned MCRegisterInfo_getMatchingSuperReg(const MCRegisterInfo *RI, unsigned Reg, unsigned SubIdx, const MCRegisterClass *RC)
Definition: MCRegisterInfo.c:86
ARM_CC_AL
@ ARM_CC_AL
Always (unconditional) Always (unconditional)
Definition: arm.h:49
OS
#define OS
Definition: config_freebsd/ares_config.h:360
getAM2Op
static ARM_AM_AddrOpc getAM2Op(unsigned AM2Opc)
Definition: ARMAddressingModes.h:455
ARMAddressingModes.h
INT32_MIN
#define INT32_MIN
Definition: stdint-msvc2008.h:136
ARM_SYSREG_APSR_NZCVQ
@ ARM_SYSREG_APSR_NZCVQ
Definition: arm.h:71
getSORegOffset
static unsigned getSORegOffset(unsigned Op)
Definition: ARMAddressingModes.h:120
ARM_addSysReg
void ARM_addSysReg(MCInst *MI, arm_sysreg reg)
ARM_INS_ADC
@ ARM_INS_ADC
Definition: arm.h:446
ARM_addUserMode
void ARM_addUserMode(MCInst *MI)
ARM_AM_no_shift
@ ARM_AM_no_shift
Definition: ARMAddressingModes.h:25
ARM_INS_ORR
@ ARM_INS_ORR
Definition: arm.h:538
ARM_INS_ASR
@ ARM_INS_ASR
Definition: arm.h:853
ARM_INS_ORN
@ ARM_INS_ORN
Definition: arm.h:860
ARM_REG_LR
@ ARM_REG_LR
Definition: arm.h:263
ARM_INS_SMULL
@ ARM_INS_SMULL
Definition: arm.h:618
absl::str_format_internal::CC
FormatConversionCharInternal CC
Definition: third_party/abseil-cpp/absl/strings/internal/str_format/parser.cc:34
ARM_INS_UADD8
@ ARM_INS_UADD8
Definition: arm.h:674
ARMMapping.h
index
int index
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/protobuf.h:1184
MCInst::writeback
bool writeback
Definition: MCInst.h:105
CountTrailingZeros_32
static unsigned CountTrailingZeros_32(uint32_t Value)
Definition: MathExtras.h:190
MCInst_Init
void MCInst_Init(MCInst *inst)
Definition: MCInst.c:18
ARM_SYSREG_SPSR_FIQ
@ ARM_SYSREG_SPSR_FIQ
Definition: arm.h:129
ARM_SYSREG_CPSR_C
@ ARM_SYSREG_CPSR_C
Definition: arm.h:63
ARM_OP_IMM
@ ARM_OP_IMM
= CS_OP_IMM (Immediate operand).
Definition: arm.h:164
ARM_SYSREG_XPSR_NZCVQG
@ ARM_SYSREG_XPSR_NZCVQG
Definition: arm.h:86
MCInst_getOpcode
unsigned MCInst_getOpcode(const MCInst *inst)
Definition: MCInst.c:65
CountLeadingZeros_32
static unsigned CountLeadingZeros_32(uint32_t Value)
Definition: MathExtras.h:95
ARMCC_ARMCondCodeToString
static const char * ARMCC_ARMCondCodeToString(ARMCC_CondCodes CC)
Definition: ARMBaseInfo.h:73
ARM_SYSREG_SPSR_F
@ ARM_SYSREG_SPSR_F
Definition: arm.h:60
ARM_reg_name
const char * ARM_reg_name(csh handle, unsigned int reg)
ARM_SYSREG_SP_MON
@ ARM_SYSREG_SP_MON
Definition: arm.h:125
rotr32
static unsigned rotr32(unsigned Val, unsigned Amt)
Definition: ARMAddressingModes.h:87
MCOperand_isImm
bool MCOperand_isImm(const MCOperand *op)
Definition: MCInst.c:103
ARM_SYSREG_APSR_G
@ ARM_SYSREG_APSR_G
Definition: arm.h:70
ARM_SYSREG_IAPSR_NZCVQ
@ ARM_SYSREG_IAPSR_NZCVQ
Definition: arm.h:77
ARM_SYSREG_BASEPRI
@ ARM_SYSREG_BASEPRI
Definition: arm.h:96
ARM_SFT_ASR
@ ARM_SFT_ASR
shift with immediate const
Definition: arm.h:20
SStream_concat
void SStream_concat(SStream *ss, const char *fmt,...)
Definition: SStream.c:42
ARM_OP_CIMM
@ ARM_OP_CIMM
C-Immediate (coprocessor registers)
Definition: arm.h:167
ARM_INS_EOR
@ ARM_INS_EOR
Definition: arm.h:479
getAM3Offset
static unsigned char getAM3Offset(unsigned AM3Opc)
Definition: ARMAddressingModes.h:492
ARM_SYSREG_SPSR_UND
@ ARM_SYSREG_SPSR_UND
Definition: arm.h:133
MCRegisterInfo_getRegClass
const MCRegisterClass * MCRegisterInfo_getRegClass(const MCRegisterInfo *RI, unsigned i)
Definition: MCRegisterInfo.c:126
ARM_AM_ror
@ ARM_AM_ror
Definition: ARMAddressingModes.h:29
ARM_AM_getAM5Op
static ARM_AM_AddrOpc ARM_AM_getAM5Op(unsigned AM5Opc)
Definition: ARMAddressingModes.h:553
ARM_SYSREG_EAPSR_NZCVQ
@ ARM_SYSREG_EAPSR_NZCVQ
Definition: arm.h:82
Reg
Reg
Definition: X86DisassemblerDecoder.h:466
getAM3Op
static ARM_AM_AddrOpc getAM3Op(unsigned AM3Opc)
Definition: ARMAddressingModes.h:497
ARM_addVectorDataType
void ARM_addVectorDataType(MCInst *MI, arm_vectordata_type vd)
handle
static csh handle
Definition: test_arm_regression.c:16
ARM_SYSREG_APSR
@ ARM_SYSREG_APSR
Definition: arm.h:69
ARM_INS_RSC
@ ARM_INS_RSC
Definition: arm.h:563
ARM_AM_add
@ ARM_AM_add
Definition: ARMAddressingModes.h:35
ARM_AM_sub
@ ARM_AM_sub
Definition: ARMAddressingModes.h:34
ARM_SETEND_BE
@ ARM_SETEND_BE
BE operand.
Definition: arm.h:176
ARM_INS_VPUSH
@ ARM_INS_VPUSH
Definition: arm.h:878
MCRegisterInfo
Definition: MCRegisterInfo.h:78
ARM_SYSREG_SPSR_MON
@ ARM_SYSREG_SPSR_MON
Definition: arm.h:134
ARM_INS_WFE
@ ARM_INS_WFE
Definition: arm.h:874
ARM_SYSREG_LR_FIQ
@ ARM_SYSREG_LR_FIQ
Definition: arm.h:115
ARM_OP_SETEND
@ ARM_OP_SETEND
operand for SETEND instruction
Definition: arm.h:169
ARM_OP_MEM
@ ARM_OP_MEM
= CS_OP_MEM (Memory operand).
Definition: arm.h:165
ARM_SYSREG_SP_IRQ
@ ARM_SYSREG_SP_IRQ
Definition: arm.h:117
ARM_AM_getAM5Offset
static unsigned char ARM_AM_getAM5Offset(unsigned AM5Opc)
Definition: ARMAddressingModes.h:549
int8_t
signed char int8_t
Definition: stdint-msvc2008.h:75
ARM_SYSREG_LR_IRQ
@ ARM_SYSREG_LR_IRQ
Definition: arm.h:116
ARM_SYSREG_XPSR_G
@ ARM_SYSREG_XPSR_G
Definition: arm.h:85
ARM_SYSREG_R9_FIQ
@ ARM_SYSREG_R9_FIQ
Definition: arm.h:110
autogen_x86imm.tmp
tmp
Definition: autogen_x86imm.py:12
size
voidpf void uLong size
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
ARM_SYSREG_SP_USR
@ ARM_SYSREG_SP_USR
Definition: arm.h:107
ARM_SFT_ROR
@ ARM_SFT_ROR
shift with immediate const
Definition: arm.h:23
ARM_addReg
void ARM_addReg(MCInst *MI, int reg)
ARM_SYSREG_XPSR
@ ARM_SYSREG_XPSR
Definition: arm.h:84
MCInst_setOpcode
void MCInst_setOpcode(MCInst *inst, unsigned Op)
Definition: MCInst.c:55
int32_t
signed int int32_t
Definition: stdint-msvc2008.h:77
access
Definition: bloaty/third_party/zlib/examples/zran.c:75
MCInst_setOpcodePub
void MCInst_setOpcodePub(MCInst *inst, unsigned Op)
Definition: MCInst.c:60
ARM_SYSREG_SPSR_HYP
@ ARM_SYSREG_SPSR_HYP
Definition: arm.h:135
ARM_INS_SMLAL
@ ARM_INS_SMLAL
Definition: arm.h:593
ARM_SYSREG_IAPSR
@ ARM_SYSREG_IAPSR
Definition: arm.h:74
absl::str_format_internal::LengthMod::h
@ h
ARM_reg_name2
const char * ARM_reg_name2(csh handle, unsigned int reg)
ARM_INS_MOV
@ ARM_INS_MOV
Definition: arm.h:527
ARM_INS_VPOP
@ ARM_INS_VPOP
Definition: arm.h:879
if
if(p->owned &&p->wrapped !=NULL)
Definition: call.c:42
MCInst::flat_insn
cs_insn * flat_insn
Definition: MCInst.h:95
name_map
Definition: utils.h:36
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
ARM_INS_UMULL
@ ARM_INS_UMULL
Definition: arm.h:687
CS_AC_WRITE
@ CS_AC_WRITE
Operand write to memory or register.
Definition: capstone.h:206
ARM_SYSREG_EAPSR_G
@ ARM_SYSREG_EAPSR_G
Definition: arm.h:80
printUInt32
void printUInt32(SStream *O, uint32_t val)
Definition: SStream.c:161
MCOperand_isReg
bool MCOperand_isReg(const MCOperand *op)
Definition: MCInst.c:98
ARM_SYSREG_MSP
@ ARM_SYSREG_MSP
Definition: arm.h:93
ARM_AM_lsl
@ ARM_AM_lsl
Definition: ARMAddressingModes.h:27
ARR_SIZE
#define ARR_SIZE(a)
Definition: ocaml.c:13


grpc
Author(s):
autogenerated on Thu Mar 13 2025 02:58:34