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