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