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