1 //==-- AArch64InstPrinter.cpp - Convert AArch64 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 AArch64 MCInst to a .s file.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 /* Capstone Disassembly Engine */
15 /* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2016 */
16 
17 #ifdef CAPSTONE_HAS_ARM64
18 
19 #include <capstone/platform.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 
23 #include "AArch64InstPrinter.h"
24 #include "AArch64Disassembler.h"
25 #include "AArch64BaseInfo.h"
26 #include "../../utils.h"
27 #include "../../MCInst.h"
28 #include "../../SStream.h"
29 #include "../../MCRegisterInfo.h"
30 #include "../../MathExtras.h"
31 
32 #include "AArch64Mapping.h"
33 #include "AArch64AddressingModes.h"
34 
35 #define GET_REGINFO_ENUM
36 #include "AArch64GenRegisterInfo.inc"
37 
38 #define GET_INSTRINFO_ENUM
39 #include "AArch64GenInstrInfo.inc"
40 
41 #include "AArch64GenSubtargetInfo.inc"
42 
43 
44 static const char *getRegisterName(unsigned RegNo, unsigned AltIdx);
45 static void printOperand(MCInst *MI, unsigned OpNum, SStream *O);
46 static bool printSysAlias(MCInst *MI, SStream *O);
47 static char *printAliasInstr(MCInst *MI, SStream *OS, MCRegisterInfo *MRI);
48 static void printInstruction(MCInst *MI, SStream *O);
49 static void printShifter(MCInst *MI, unsigned OpNum, SStream *O);
50 static void printCustomAliasOperand(MCInst *MI, unsigned OpIdx,
51 		unsigned PrintMethodIdx, SStream *OS);
52 
53 
get_op_access(cs_struct * h,unsigned int id,unsigned int index)54 static cs_ac_type get_op_access(cs_struct *h, unsigned int id, unsigned int index)
55 {
56 #ifndef CAPSTONE_DIET
57 	const uint8_t *arr = AArch64_get_op_access(h, id);
58 
59 	if (arr[index] == CS_AC_IGNORE)
60 		return 0;
61 
62 	return arr[index];
63 #else
64 	return 0;
65 #endif
66 }
67 
op_addImm(MCInst * MI,int v)68 static void op_addImm(MCInst *MI, int v)
69 {
70 	if (MI->csh->detail) {
71 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
72 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = v;
73 		MI->flat_insn->detail->arm64.op_count++;
74 	}
75 }
76 
set_mem_access(MCInst * MI,bool status)77 static void set_mem_access(MCInst *MI, bool status)
78 {
79 	MI->csh->doing_mem = status;
80 
81 	if (MI->csh->detail != CS_OPT_ON)
82 		return;
83 
84 	if (status) {
85 #ifndef CAPSTONE_DIET
86 		uint8_t access;
87 		access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
88 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
89 		MI->ac_idx++;
90 #endif
91 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_MEM;
92 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].mem.base = ARM64_REG_INVALID;
93 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].mem.index = ARM64_REG_INVALID;
94 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].mem.disp = 0;
95 	} else {
96 		// done, create the next operand slot
97 		MI->flat_insn->detail->arm64.op_count++;
98 	}
99 }
100 
AArch64_printInst(MCInst * MI,SStream * O,void * Info)101 void AArch64_printInst(MCInst *MI, SStream *O, void *Info)
102 {
103 	// Check for special encodings and print the canonical alias instead.
104 	unsigned Opcode = MCInst_getOpcode(MI);
105 	int LSB, Width;
106 	char *mnem;
107 
108 	// printf(">>> opcode = %u\n", MCInst_getOpcode(MI));
109 
110 	if (Opcode == AArch64_SYSxt && printSysAlias(MI, O))
111 		return;
112 
113 	// SBFM/UBFM should print to a nicer aliased form if possible.
114 	if (Opcode == AArch64_SBFMXri || Opcode == AArch64_SBFMWri ||
115 			Opcode == AArch64_UBFMXri || Opcode == AArch64_UBFMWri) {
116 		bool IsSigned = (Opcode == AArch64_SBFMXri || Opcode == AArch64_SBFMWri);
117 		bool Is64Bit = (Opcode == AArch64_SBFMXri || Opcode == AArch64_UBFMXri);
118 
119 		MCOperand *Op0 = MCInst_getOperand(MI, 0);
120 		MCOperand *Op1 = MCInst_getOperand(MI, 1);
121 		MCOperand *Op2 = MCInst_getOperand(MI, 2);
122 		MCOperand *Op3 = MCInst_getOperand(MI, 3);
123 
124 		if (MCOperand_isImm(Op2) && MCOperand_getImm(Op2) == 0 && MCOperand_isImm(Op3)) {
125 			const char *AsmMnemonic = NULL;
126 
127 			switch (MCOperand_getImm(Op3)) {
128 				default:
129 					break;
130 
131 				case 7:
132 					if (IsSigned)
133 						AsmMnemonic = "sxtb";
134 					else if (!Is64Bit)
135 						AsmMnemonic = "uxtb";
136 					break;
137 
138 				case 15:
139 					if (IsSigned)
140 						AsmMnemonic = "sxth";
141 					else if (!Is64Bit)
142 						AsmMnemonic = "uxth";
143 					break;
144 
145 				case 31:
146 					// *xtw is only valid for signed 64-bit operations.
147 					if (Is64Bit && IsSigned)
148 						AsmMnemonic = "sxtw";
149 					break;
150 			}
151 
152 			if (AsmMnemonic) {
153 				SStream_concat(O, "%s\t%s, %s", AsmMnemonic,
154 						getRegisterName(MCOperand_getReg(Op0), AArch64_NoRegAltName),
155 						getRegisterName(getWRegFromXReg(MCOperand_getReg(Op1)), AArch64_NoRegAltName));
156 
157 				if (MI->csh->detail) {
158 #ifndef CAPSTONE_DIET
159 					uint8_t access;
160 					access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
161 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
162 					MI->ac_idx++;
163 #endif
164 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
165 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op0);
166 					MI->flat_insn->detail->arm64.op_count++;
167 #ifndef CAPSTONE_DIET
168 					access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
169 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
170 					MI->ac_idx++;
171 #endif
172 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
173 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = getWRegFromXReg(MCOperand_getReg(Op1));
174 					MI->flat_insn->detail->arm64.op_count++;
175 				}
176 
177 				MCInst_setOpcodePub(MI, AArch64_map_insn(AsmMnemonic));
178 
179 				return;
180 			}
181 		}
182 
183 		// All immediate shifts are aliases, implemented using the Bitfield
184 		// instruction. In all cases the immediate shift amount shift must be in
185 		// the range 0 to (reg.size -1).
186 		if (MCOperand_isImm(Op2) && MCOperand_isImm(Op3)) {
187 			const char *AsmMnemonic = NULL;
188 			int shift = 0;
189 			int immr = (int)MCOperand_getImm(Op2);
190 			int imms = (int)MCOperand_getImm(Op3);
191 
192 			if (Opcode == AArch64_UBFMWri && imms != 0x1F && ((imms + 1) == immr)) {
193 				AsmMnemonic = "lsl";
194 				shift = 31 - imms;
195 			} else if (Opcode == AArch64_UBFMXri && imms != 0x3f &&
196 					((imms + 1 == immr))) {
197 				AsmMnemonic = "lsl";
198 				shift = 63 - imms;
199 			} else if (Opcode == AArch64_UBFMWri && imms == 0x1f) {
200 				AsmMnemonic = "lsr";
201 				shift = immr;
202 			} else if (Opcode == AArch64_UBFMXri && imms == 0x3f) {
203 				AsmMnemonic = "lsr";
204 				shift = immr;
205 			} else if (Opcode == AArch64_SBFMWri && imms == 0x1f) {
206 				AsmMnemonic = "asr";
207 				shift = immr;
208 			} else if (Opcode == AArch64_SBFMXri && imms == 0x3f) {
209 				AsmMnemonic = "asr";
210 				shift = immr;
211 			}
212 
213 			if (AsmMnemonic) {
214 				SStream_concat(O, "%s\t%s, %s, ", AsmMnemonic,
215 						getRegisterName(MCOperand_getReg(Op0), AArch64_NoRegAltName),
216 						getRegisterName(MCOperand_getReg(Op1), AArch64_NoRegAltName));
217 
218 				printInt32Bang(O, shift);
219 
220 				MCInst_setOpcodePub(MI, AArch64_map_insn(AsmMnemonic));
221 
222 				if (MI->csh->detail) {
223 #ifndef CAPSTONE_DIET
224 					uint8_t access;
225 					access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
226 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
227 					MI->ac_idx++;
228 #endif
229 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
230 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op0);
231 					MI->flat_insn->detail->arm64.op_count++;
232 #ifndef CAPSTONE_DIET
233 					access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
234 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
235 					MI->ac_idx++;
236 #endif
237 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
238 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op1);
239 					MI->flat_insn->detail->arm64.op_count++;
240 #ifndef CAPSTONE_DIET
241 					access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
242 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
243 					MI->ac_idx++;
244 #endif
245 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
246 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = shift;
247 					MI->flat_insn->detail->arm64.op_count++;
248 				}
249 
250 				return;
251 			}
252 		}
253 
254 		// SBFIZ/UBFIZ aliases
255 		if (MCOperand_getImm(Op2) > MCOperand_getImm(Op3)) {
256 			SStream_concat(O, "%s\t%s, %s, ", (IsSigned ? "sbfiz" : "ubfiz"),
257 					getRegisterName(MCOperand_getReg(Op0), AArch64_NoRegAltName),
258 					getRegisterName(MCOperand_getReg(Op1), AArch64_NoRegAltName));
259 
260 			printInt32Bang(O, (int)((Is64Bit ? 64 : 32) - MCOperand_getImm(Op2)));
261 
262 			SStream_concat0(O, ", ");
263 
264 			printInt32Bang(O, (int)MCOperand_getImm(Op3) + 1);
265 
266 			MCInst_setOpcodePub(MI, AArch64_map_insn(IsSigned ? "sbfiz" : "ubfiz"));
267 
268 			if (MI->csh->detail) {
269 #ifndef CAPSTONE_DIET
270 				uint8_t access;
271 				access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
272 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
273 				MI->ac_idx++;
274 #endif
275 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
276 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op0);
277 				MI->flat_insn->detail->arm64.op_count++;
278 #ifndef CAPSTONE_DIET
279 				access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
280 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
281 				MI->ac_idx++;
282 #endif
283 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
284 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op1);
285 				MI->flat_insn->detail->arm64.op_count++;
286 #ifndef CAPSTONE_DIET
287 				access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
288 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
289 				MI->ac_idx++;
290 #endif
291 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
292 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = (Is64Bit ? 64 : 32) - (int)MCOperand_getImm(Op2);
293 				MI->flat_insn->detail->arm64.op_count++;
294 #ifndef CAPSTONE_DIET
295 				access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
296 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
297 				MI->ac_idx++;
298 #endif
299 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
300 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = MCOperand_getImm(Op3) + 1;
301 				MI->flat_insn->detail->arm64.op_count++;
302 			}
303 
304 			return;
305 		}
306 
307 		// Otherwise SBFX/UBFX is the preferred form
308 		SStream_concat(O, "%s\t%s, %s, ", (IsSigned ? "sbfx" : "ubfx"),
309 				getRegisterName(MCOperand_getReg(Op0), AArch64_NoRegAltName),
310 				getRegisterName(MCOperand_getReg(Op1), AArch64_NoRegAltName));
311 
312 		printInt32Bang(O, (int)MCOperand_getImm(Op2));
313 		SStream_concat0(O, ", ");
314 		printInt32Bang(O, (int)MCOperand_getImm(Op3) - (int)MCOperand_getImm(Op2) + 1);
315 
316 		MCInst_setOpcodePub(MI, AArch64_map_insn(IsSigned ? "sbfx" : "ubfx"));
317 
318 		if (MI->csh->detail) {
319 #ifndef CAPSTONE_DIET
320 			uint8_t access;
321 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
322 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
323 			MI->ac_idx++;
324 #endif
325 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
326 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op0);
327 			MI->flat_insn->detail->arm64.op_count++;
328 #ifndef CAPSTONE_DIET
329 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
330 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
331 			MI->ac_idx++;
332 #endif
333 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
334 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op1);
335 			MI->flat_insn->detail->arm64.op_count++;
336 #ifndef CAPSTONE_DIET
337 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
338 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
339 			MI->ac_idx++;
340 #endif
341 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
342 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = MCOperand_getImm(Op2);
343 			MI->flat_insn->detail->arm64.op_count++;
344 #ifndef CAPSTONE_DIET
345 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
346 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
347 			MI->ac_idx++;
348 #endif
349 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
350 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = MCOperand_getImm(Op3) - MCOperand_getImm(Op2) + 1;
351 			MI->flat_insn->detail->arm64.op_count++;
352 		}
353 
354 		return;
355 	}
356 
357 	if (Opcode == AArch64_BFMXri || Opcode == AArch64_BFMWri) {
358 		MCOperand *Op0 = MCInst_getOperand(MI, 0); // Op1 == Op0
359 		MCOperand *Op2 = MCInst_getOperand(MI, 2);
360 		int ImmR = (int)MCOperand_getImm(MCInst_getOperand(MI, 3));
361 		int ImmS = (int)MCOperand_getImm(MCInst_getOperand(MI, 4));
362 
363 		if ((MCOperand_getReg(Op2) == AArch64_WZR || MCOperand_getReg(Op2) == AArch64_XZR) &&
364 				(ImmR == 0 || ImmS < ImmR)) {
365 			// BFC takes precedence over its entire range, sligtly differently to BFI.
366 			int BitWidth = Opcode == AArch64_BFMXri ? 64 : 32;
367 			int LSB = (BitWidth - ImmR) % BitWidth;
368 			int Width = ImmS + 1;
369 
370 			SStream_concat(O, "bfc\t%s, ",
371 					getRegisterName(MCOperand_getReg(Op0), AArch64_NoRegAltName));
372 
373 			printInt32Bang(O, LSB);
374 			SStream_concat0(O, ", ");
375 			printInt32Bang(O, Width);
376 			MCInst_setOpcodePub(MI, AArch64_map_insn("bfc"));
377 
378 			if (MI->csh->detail) {
379 #ifndef CAPSTONE_DIET
380 				uint8_t access;
381 				access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
382 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
383 				MI->ac_idx++;
384 #endif
385 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
386 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op0);
387 				MI->flat_insn->detail->arm64.op_count++;
388 
389 #ifndef CAPSTONE_DIET
390 				access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
391 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
392 				MI->ac_idx++;
393 #endif
394 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
395 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = LSB;
396 				MI->flat_insn->detail->arm64.op_count++;
397 #ifndef CAPSTONE_DIET
398 				access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
399 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
400 				MI->ac_idx++;
401 #endif
402 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
403 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = Width;
404 				MI->flat_insn->detail->arm64.op_count++;
405 			}
406 
407 			return;
408 		} else if (ImmS < ImmR) {
409 			// BFI alias
410 			int BitWidth = Opcode == AArch64_BFMXri ? 64 : 32;
411 			LSB = (BitWidth - ImmR) % BitWidth;
412 			Width = ImmS + 1;
413 
414 			SStream_concat(O, "bfi\t%s, %s, ",
415 					getRegisterName(MCOperand_getReg(Op0), AArch64_NoRegAltName),
416 					getRegisterName(MCOperand_getReg(Op2), AArch64_NoRegAltName));
417 
418 			printInt32Bang(O, LSB);
419 			SStream_concat0(O, ", ");
420 			printInt32Bang(O, Width);
421 
422 			MCInst_setOpcodePub(MI, AArch64_map_insn("bfi"));
423 
424 			if (MI->csh->detail) {
425 #ifndef CAPSTONE_DIET
426 				uint8_t access;
427 				access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
428 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
429 				MI->ac_idx++;
430 #endif
431 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
432 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op0);
433 				MI->flat_insn->detail->arm64.op_count++;
434 #ifndef CAPSTONE_DIET
435 				access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
436 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
437 				MI->ac_idx++;
438 #endif
439 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
440 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op2);
441 				MI->flat_insn->detail->arm64.op_count++;
442 #ifndef CAPSTONE_DIET
443 				access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
444 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
445 				MI->ac_idx++;
446 #endif
447 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
448 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = LSB;
449 				MI->flat_insn->detail->arm64.op_count++;
450 #ifndef CAPSTONE_DIET
451 				access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
452 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
453 				MI->ac_idx++;
454 #endif
455 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
456 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = Width;
457 				MI->flat_insn->detail->arm64.op_count++;
458 			}
459 
460 			return;
461 		}
462 
463 		LSB = ImmR;
464 		Width = ImmS - ImmR + 1;
465 		// Otherwise BFXIL the preferred form
466 		SStream_concat(O, "bfxil\t%s, %s, ",
467 				getRegisterName(MCOperand_getReg(Op0), AArch64_NoRegAltName),
468 				getRegisterName(MCOperand_getReg(Op2), AArch64_NoRegAltName));
469 
470 		printInt32Bang(O, LSB);
471 		SStream_concat0(O, ", ");
472 		printInt32Bang(O, Width);
473 
474 		MCInst_setOpcodePub(MI, AArch64_map_insn("bfxil"));
475 
476 		if (MI->csh->detail) {
477 #ifndef CAPSTONE_DIET
478 			uint8_t access;
479 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
480 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
481 			MI->ac_idx++;
482 #endif
483 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
484 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op0);
485 			MI->flat_insn->detail->arm64.op_count++;
486 #ifndef CAPSTONE_DIET
487 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
488 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
489 			MI->ac_idx++;
490 #endif
491 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
492 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op2);
493 			MI->flat_insn->detail->arm64.op_count++;
494 #ifndef CAPSTONE_DIET
495 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
496 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
497 			MI->ac_idx++;
498 #endif
499 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
500 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = LSB;
501 			MI->flat_insn->detail->arm64.op_count++;
502 #ifndef CAPSTONE_DIET
503 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
504 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
505 			MI->ac_idx++;
506 #endif
507 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
508 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = Width;
509 			MI->flat_insn->detail->arm64.op_count++;
510 		}
511 
512 		return;
513 	}
514 
515 	// MOVZ, MOVN and "ORR wzr, #imm" instructions are aliases for MOV, but their
516 	// domains overlap so they need to be prioritized. The chain is "MOVZ lsl #0 >
517 	// MOVZ lsl #N > MOVN lsl #0 > MOVN lsl #N > ORR". The highest instruction
518 	// that can represent the move is the MOV alias, and the rest get printed
519 	// normally.
520 	if ((Opcode == AArch64_MOVZXi || Opcode == AArch64_MOVZWi) &&
521 			MCOperand_isImm(MCInst_getOperand(MI, 1)) && MCOperand_isImm(MCInst_getOperand(MI, 2))) {
522 		int RegWidth = Opcode == AArch64_MOVZXi ? 64 : 32;
523 		int Shift = MCOperand_getImm(MCInst_getOperand(MI, 2));
524 		uint64_t Value = (uint64_t)MCOperand_getImm(MCInst_getOperand(MI, 1)) << Shift;
525 
526 		if (isMOVZMovAlias(Value, Shift,
527 					Opcode == AArch64_MOVZXi ? 64 : 32)) {
528 			SStream_concat(O, "mov\t%s, ", getRegisterName(MCOperand_getReg(MCInst_getOperand(MI, 0)), AArch64_NoRegAltName));
529 
530 			printInt64Bang(O, SignExtend64(Value, RegWidth));
531 
532 			if (MI->csh->detail) {
533 #ifndef CAPSTONE_DIET
534 				uint8_t access;
535 				access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
536 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
537 				MI->ac_idx++;
538 #endif
539 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
540 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, 0));
541 				MI->flat_insn->detail->arm64.op_count++;
542 
543 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
544 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = SignExtend64(Value, RegWidth);
545 				MI->flat_insn->detail->arm64.op_count++;
546 			}
547 
548 			MCInst_setOpcodePub(MI, AArch64_map_insn("mov"));
549 
550 			return;
551 		}
552 	}
553 
554 	if ((Opcode == AArch64_MOVNXi || Opcode == AArch64_MOVNWi) &&
555 			MCOperand_isImm(MCInst_getOperand(MI, 1)) && MCOperand_isImm(MCInst_getOperand(MI, 2))) {
556 		int RegWidth = Opcode == AArch64_MOVNXi ? 64 : 32;
557 		int Shift = MCOperand_getImm(MCInst_getOperand(MI, 2));
558 		uint64_t Value = ~((uint64_t)MCOperand_getImm(MCInst_getOperand(MI, 1)) << Shift);
559 
560 		if (RegWidth == 32)
561 			Value = Value & 0xffffffff;
562 
563 		if (AArch64_AM_isMOVNMovAlias(Value, Shift, RegWidth)) {
564 			SStream_concat(O, "mov\t%s, ", getRegisterName(MCOperand_getReg(MCInst_getOperand(MI, 0)), AArch64_NoRegAltName));
565 
566 			printInt64Bang(O, SignExtend64(Value, RegWidth));
567 
568 			if (MI->csh->detail) {
569 #ifndef CAPSTONE_DIET
570 				uint8_t access;
571 				access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
572 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
573 				MI->ac_idx++;
574 #endif
575 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
576 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, 0));
577 				MI->flat_insn->detail->arm64.op_count++;
578 
579 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
580 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = SignExtend64(Value, RegWidth);
581 				MI->flat_insn->detail->arm64.op_count++;
582 			}
583 
584 			MCInst_setOpcodePub(MI, AArch64_map_insn("mov"));
585 
586 			return;
587 		}
588 	}
589 
590 	if ((Opcode == AArch64_ORRXri || Opcode == AArch64_ORRWri) &&
591 			(MCOperand_getReg(MCInst_getOperand(MI, 0)) == AArch64_XZR ||
592 			 MCOperand_getReg(MCInst_getOperand(MI, 1)) == AArch64_WZR) &&
593 			MCOperand_isImm(MCInst_getOperand(MI, 2))) {
594 		int RegWidth = Opcode == AArch64_ORRXri ? 64 : 32;
595 		uint64_t Value = AArch64_AM_decodeLogicalImmediate(
596 				MCOperand_getImm(MCInst_getOperand(MI, 2)), RegWidth);
597 		if (!AArch64_AM_isAnyMOVWMovAlias(Value, RegWidth)) {
598 			SStream_concat(O, "mov\t%s, ", getRegisterName(MCOperand_getReg(MCInst_getOperand(MI, 0)), AArch64_NoRegAltName));
599 
600 			printInt64Bang(O, SignExtend64(Value, RegWidth));
601 
602 			if (MI->csh->detail) {
603 #ifndef CAPSTONE_DIET
604 				uint8_t access;
605 				access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
606 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
607 				MI->ac_idx++;
608 #endif
609 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
610 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, 0));
611 				MI->flat_insn->detail->arm64.op_count++;
612 
613 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
614 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = SignExtend64(Value, RegWidth);
615 				MI->flat_insn->detail->arm64.op_count++;
616 			}
617 
618 			MCInst_setOpcodePub(MI, AArch64_map_insn("mov"));
619 
620 			return;
621 		}
622 	}
623 
624 	// Instruction TSB is specified as a one operand instruction, but 'csync' is
625 	// not encoded, so for printing it is treated as a special case here:
626 	if (Opcode == AArch64_TSB) {
627 		SStream_concat0(O, "tsb\tcsync");
628 		MCInst_setOpcodePub(MI, AArch64_map_insn("tsb"));
629 		return;
630 	}
631 
632 	MI->MRI = Info;
633 
634 	mnem = printAliasInstr(MI, O, (MCRegisterInfo *)Info);
635 	if (mnem) {
636 		MCInst_setOpcodePub(MI, AArch64_map_insn(mnem));
637 		cs_mem_free(mnem);
638 
639 		switch(MCInst_getOpcode(MI)) {
640 			default: break;
641 			case AArch64_LD1i8_POST:
642 				 arm64_op_addImm(MI, 1);
643 				 break;
644 			case AArch64_LD1i16_POST:
645 				 arm64_op_addImm(MI, 2);
646 				 break;
647 			case AArch64_LD1i32_POST:
648 				 arm64_op_addImm(MI, 4);
649 				 break;
650 			case AArch64_LD1Onev1d_POST:
651 			case AArch64_LD1Onev2s_POST:
652 			case AArch64_LD1Onev4h_POST:
653 			case AArch64_LD1Onev8b_POST:
654 			case AArch64_LD1i64_POST:
655 				 arm64_op_addImm(MI, 8);
656 				 break;
657 			case AArch64_LD1Onev16b_POST:
658 			case AArch64_LD1Onev2d_POST:
659 			case AArch64_LD1Onev4s_POST:
660 			case AArch64_LD1Onev8h_POST:
661 			case AArch64_LD1Twov1d_POST:
662 			case AArch64_LD1Twov2s_POST:
663 			case AArch64_LD1Twov4h_POST:
664 			case AArch64_LD1Twov8b_POST:
665 				 arm64_op_addImm(MI, 16);
666 				 break;
667 			case AArch64_LD1Threev1d_POST:
668 			case AArch64_LD1Threev2s_POST:
669 			case AArch64_LD1Threev4h_POST:
670 			case AArch64_LD1Threev8b_POST:
671 				 arm64_op_addImm(MI, 24);
672 				 break;
673 			case AArch64_LD1Fourv1d_POST:
674 			case AArch64_LD1Fourv2s_POST:
675 			case AArch64_LD1Fourv4h_POST:
676 			case AArch64_LD1Fourv8b_POST:
677 			case AArch64_LD1Twov16b_POST:
678 			case AArch64_LD1Twov2d_POST:
679 			case AArch64_LD1Twov4s_POST:
680 			case AArch64_LD1Twov8h_POST:
681 				 arm64_op_addImm(MI, 32);
682 				 break;
683 			case AArch64_LD1Threev16b_POST:
684 			case AArch64_LD1Threev2d_POST:
685 			case AArch64_LD1Threev4s_POST:
686 			case AArch64_LD1Threev8h_POST:
687 				 arm64_op_addImm(MI, 48);
688 				 break;
689 			case AArch64_LD1Fourv16b_POST:
690 			case AArch64_LD1Fourv2d_POST:
691 			case AArch64_LD1Fourv4s_POST:
692 			case AArch64_LD1Fourv8h_POST:
693 				 arm64_op_addImm(MI, 64);
694 				 break;
695 			case AArch64_UMOVvi64:
696 				 arm64_op_addVectorArrSpecifier(MI, ARM64_VAS_1D);
697 				 break;
698 			case AArch64_UMOVvi32:
699 				 arm64_op_addVectorArrSpecifier(MI, ARM64_VAS_1S);
700 				 break;
701 		}
702 	} else {
703 		printInstruction(MI, O);
704 	}
705 }
706 
printSysAlias(MCInst * MI,SStream * O)707 static bool printSysAlias(MCInst *MI, SStream *O)
708 {
709 	// unsigned Opcode = MCInst_getOpcode(MI);
710 	//assert(Opcode == AArch64_SYSxt && "Invalid opcode for SYS alias!");
711 
712 	const char *Ins;
713 	uint16_t Encoding;
714 	bool NeedsReg;
715 	char Name[64];
716 	MCOperand *Op1 = MCInst_getOperand(MI, 0);
717 	MCOperand *Cn = MCInst_getOperand(MI, 1);
718 	MCOperand *Cm = MCInst_getOperand(MI, 2);
719 	MCOperand *Op2 = MCInst_getOperand(MI, 3);
720 
721 	unsigned Op1Val = (unsigned)MCOperand_getImm(Op1);
722 	unsigned CnVal = (unsigned)MCOperand_getImm(Cn);
723 	unsigned CmVal = (unsigned)MCOperand_getImm(Cm);
724 	unsigned Op2Val = (unsigned)MCOperand_getImm(Op2);
725 
726 	Encoding = Op2Val;
727 	Encoding |= CmVal << 3;
728 	Encoding |= CnVal << 7;
729 	Encoding |= Op1Val << 11;
730 
731 	if (CnVal == 7) {
732 		switch (CmVal) {
733 			default:
734 				return false;
735 
736 			// IC aliases
737 			case 1: case 5: {
738 				const IC *IC = lookupICByEncoding(Encoding);
739 				// if (!IC || !IC->haveFeatures(STI.getFeatureBits()))
740 				if (!IC)
741 					return false;
742 
743 				NeedsReg = IC->NeedsReg;
744 				Ins = "ic";
745 				strncpy(Name, IC->Name, sizeof(Name) - 1);
746 			}
747 			break;
748 
749 			// DC aliases
750 			case 4: case 6: case 10: case 11: case 12: case 14: {
751 				const DC *DC = lookupDCByEncoding(Encoding);
752 				// if (!DC || !DC->haveFeatures(STI.getFeatureBits()))
753 				if (!DC)
754 					return false;
755 
756 				NeedsReg = true;
757 				Ins = "dc";
758 				strncpy(Name, DC->Name, sizeof(Name) - 1);
759 			}
760 			break;
761 
762 			// AT aliases
763 			case 8: case 9: {
764 				const AT *AT = lookupATByEncoding(Encoding);
765 				// if (!AT || !AT->haveFeatures(STI.getFeatureBits()))
766 				if (!AT)
767 					return false;
768 
769 				NeedsReg = true;
770 				Ins = "at";
771 				strncpy(Name, AT->Name, sizeof(Name) - 1);
772 			}
773 			break;
774 		}
775 	} else if (CnVal == 8) {
776 		// TLBI aliases
777 		const TLBI *TLBI = lookupTLBIByEncoding(Encoding);
778 		// if (!TLBI || !TLBI->haveFeatures(STI.getFeatureBits()))
779 		if (!TLBI)
780 			return false;
781 
782 		NeedsReg = TLBI->NeedsReg;
783 		Ins = "tlbi";
784 		strncpy(Name, TLBI->Name, sizeof(Name) - 1);
785 	} else
786 		return false;
787 
788 	SStream_concat(O, "%s\t%s", Ins, Name);
789 
790 	if (NeedsReg) {
791 		SStream_concat(O, ", %s", getRegisterName(MCOperand_getReg(MCInst_getOperand(MI, 4)), AArch64_NoRegAltName));
792 	}
793 
794 	MCInst_setOpcodePub(MI, AArch64_map_insn(Ins));
795 
796 	if (MI->csh->detail) {
797 #if 0
798 #ifndef CAPSTONE_DIET
799 		uint8_t access;
800 		access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
801 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
802 		MI->ac_idx++;
803 #endif
804 #endif
805 
806 		if (NeedsReg) {
807 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
808 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, 4));
809 			MI->flat_insn->detail->arm64.op_count++;
810 		}
811 	}
812 
813 	return true;
814 }
815 
printOperand(MCInst * MI,unsigned OpNum,SStream * O)816 static void printOperand(MCInst *MI, unsigned OpNum, SStream *O)
817 {
818 	MCOperand *Op = MCInst_getOperand(MI, OpNum);
819 
820 	if (MCOperand_isReg(Op)) {
821 		unsigned Reg = MCOperand_getReg(Op);
822 
823 		SStream_concat0(O, getRegisterName(Reg, AArch64_NoRegAltName));
824 
825 		if (MI->csh->detail) {
826 			if (MI->csh->doing_mem) {
827 				if (MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].mem.base == ARM64_REG_INVALID) {
828 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].mem.base = Reg;
829 				}
830 				else if (MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].mem.index == ARM64_REG_INVALID) {
831 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].mem.index = Reg;
832 				}
833 			} else {
834 #ifndef CAPSTONE_DIET
835 				uint8_t access;
836 
837 				access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
838 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
839 				MI->ac_idx++;
840 #endif
841 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
842 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = Reg;
843 				MI->flat_insn->detail->arm64.op_count++;
844 			}
845 		}
846 	} else if (MCOperand_isImm(Op)) {
847 		int64_t imm = MCOperand_getImm(Op);
848 
849 		if (MI->Opcode == AArch64_ADR) {
850 			imm += MI->address;
851 			printUInt64Bang(O, imm);
852 		} else {
853 			if (MI->csh->doing_mem) {
854 				if (MI->csh->imm_unsigned) {
855 					printUInt64Bang(O, imm);
856 				} else {
857 					printInt64Bang(O, imm);
858 				}
859 			} else
860 				printUInt64Bang(O, imm);
861 		}
862 
863 		if (MI->csh->detail) {
864 			if (MI->csh->doing_mem) {
865 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].mem.disp = (int32_t)imm;
866 			} else {
867 #ifndef CAPSTONE_DIET
868 				uint8_t access;
869 
870 				access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
871 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
872 				MI->ac_idx++;
873 #endif
874 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
875 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = imm;
876 				MI->flat_insn->detail->arm64.op_count++;
877 			}
878 		}
879 	}
880 }
881 
printImm(MCInst * MI,unsigned OpNum,SStream * O)882 static void printImm(MCInst *MI, unsigned OpNum, SStream *O)
883 {
884 	MCOperand *Op = MCInst_getOperand(MI, OpNum);
885 	printUInt64Bang(O, MCOperand_getImm(Op));
886 
887 	if (MI->csh->detail) {
888 #ifndef CAPSTONE_DIET
889 		uint8_t access;
890 		access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
891 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
892 		MI->ac_idx++;
893 #endif
894 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
895 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = MCOperand_getImm(Op);
896 		MI->flat_insn->detail->arm64.op_count++;
897 	}
898 }
899 
printImmHex(MCInst * MI,unsigned OpNum,SStream * O)900 static void printImmHex(MCInst *MI, unsigned OpNum, SStream *O)
901 {
902 	MCOperand *Op = MCInst_getOperand(MI, OpNum);
903 	printUInt64Bang(O, MCOperand_getImm(Op));
904 
905 	if (MI->csh->detail) {
906 #ifndef CAPSTONE_DIET
907 		uint8_t access;
908 		access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
909 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
910 		MI->ac_idx++;
911 #endif
912 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
913 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = MCOperand_getImm(Op);
914 		MI->flat_insn->detail->arm64.op_count++;
915 	}
916 }
917 
printPostIncOperand(MCInst * MI,unsigned OpNum,SStream * O,unsigned Imm)918 static void printPostIncOperand(MCInst *MI, unsigned OpNum, SStream *O,
919 		unsigned Imm)
920 {
921 	MCOperand *Op = MCInst_getOperand(MI, OpNum);
922 
923 	if (MCOperand_isReg(Op)) {
924 		unsigned Reg = MCOperand_getReg(Op);
925 		if (Reg == AArch64_XZR) {
926 			printInt32Bang(O, Imm);
927 
928 			if (MI->csh->detail) {
929 #ifndef CAPSTONE_DIET
930 				uint8_t access;
931 
932 				access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
933 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
934 				MI->ac_idx++;
935 #endif
936 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
937 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = Imm;
938 				MI->flat_insn->detail->arm64.op_count++;
939 			}
940 		} else {
941 			SStream_concat0(O, getRegisterName(Reg, AArch64_NoRegAltName));
942 
943 			if (MI->csh->detail) {
944 #ifndef CAPSTONE_DIET
945 				uint8_t access;
946 
947 				access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
948 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
949 				MI->ac_idx++;
950 #endif
951 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
952 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = Reg;
953 				MI->flat_insn->detail->arm64.op_count++;
954 			}
955 		}
956 	}
957 	//llvm_unreachable("unknown operand kind in printPostIncOperand64");
958 }
959 
printVRegOperand(MCInst * MI,unsigned OpNum,SStream * O)960 static void printVRegOperand(MCInst *MI, unsigned OpNum, SStream *O)
961 {
962 	MCOperand *Op = MCInst_getOperand(MI, OpNum);
963 	//assert(Op.isReg() && "Non-register vreg operand!");
964 	unsigned Reg = MCOperand_getReg(Op);
965 
966 	SStream_concat0(O, getRegisterName(Reg, AArch64_vreg));
967 
968 	if (MI->csh->detail) {
969 #ifndef CAPSTONE_DIET
970 		uint8_t access;
971 		access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
972 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
973 		MI->ac_idx++;
974 #endif
975 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
976 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = AArch64_map_vregister(Reg);
977 		MI->flat_insn->detail->arm64.op_count++;
978 	}
979 }
980 
printSysCROperand(MCInst * MI,unsigned OpNum,SStream * O)981 static void printSysCROperand(MCInst *MI, unsigned OpNum, SStream *O)
982 {
983 	MCOperand *Op = MCInst_getOperand(MI, OpNum);
984 	//assert(Op.isImm() && "System instruction C[nm] operands must be immediates!");
985 	SStream_concat(O, "c%u", MCOperand_getImm(Op));
986 
987 	if (MI->csh->detail) {
988 #ifndef CAPSTONE_DIET
989 		uint8_t access;
990 
991 		access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
992 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
993 		MI->ac_idx++;
994 #endif
995 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_CIMM;
996 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = MCOperand_getImm(Op);
997 		MI->flat_insn->detail->arm64.op_count++;
998 	}
999 }
1000 
printAddSubImm(MCInst * MI,unsigned OpNum,SStream * O)1001 static void printAddSubImm(MCInst *MI, unsigned OpNum, SStream *O)
1002 {
1003 	MCOperand *MO = MCInst_getOperand(MI, OpNum);
1004 	if (MCOperand_isImm(MO)) {
1005 		unsigned Val = (MCOperand_getImm(MO) & 0xfff);
1006 		//assert(Val == MO.getImm() && "Add/sub immediate out of range!");
1007 		unsigned Shift = AArch64_AM_getShiftValue((int)MCOperand_getImm(MCInst_getOperand(MI, OpNum + 1)));
1008 
1009 		printInt32Bang(O, Val);
1010 
1011 		if (MI->csh->detail) {
1012 #ifndef CAPSTONE_DIET
1013 			uint8_t access;
1014 
1015 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1016 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1017 			MI->ac_idx++;
1018 #endif
1019 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
1020 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = Val;
1021 			MI->flat_insn->detail->arm64.op_count++;
1022 		}
1023 
1024 		if (Shift != 0)
1025 			printShifter(MI, OpNum + 1, O);
1026 	}
1027 }
1028 
printLogicalImm32(MCInst * MI,unsigned OpNum,SStream * O)1029 static void printLogicalImm32(MCInst *MI, unsigned OpNum, SStream *O)
1030 {
1031 	int64_t Val = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1032 
1033 	Val = AArch64_AM_decodeLogicalImmediate(Val, 32);
1034 	printUInt32Bang(O, (int)Val);
1035 
1036 	if (MI->csh->detail) {
1037 #ifndef CAPSTONE_DIET
1038 		uint8_t access;
1039 
1040 		access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1041 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1042 		MI->ac_idx++;
1043 #endif
1044 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
1045 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = Val;
1046 		MI->flat_insn->detail->arm64.op_count++;
1047 	}
1048 }
1049 
printLogicalImm64(MCInst * MI,unsigned OpNum,SStream * O)1050 static void printLogicalImm64(MCInst *MI, unsigned OpNum, SStream *O)
1051 {
1052 	int64_t Val = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1053 	Val = AArch64_AM_decodeLogicalImmediate(Val, 64);
1054 
1055 	switch(MI->flat_insn->id) {
1056 		default:
1057 			printInt64Bang(O, Val);
1058 			break;
1059 
1060 		case ARM64_INS_ORR:
1061 		case ARM64_INS_AND:
1062 		case ARM64_INS_EOR:
1063 		case ARM64_INS_TST:
1064 			// do not print number in negative form
1065 			if (Val >= 0 && Val <= HEX_THRESHOLD)
1066 				SStream_concat(O, "#%u", (int)Val);
1067 			else
1068 				SStream_concat(O, "#0x%"PRIx64, Val);
1069 			break;
1070 	}
1071 
1072 	if (MI->csh->detail) {
1073 #ifndef CAPSTONE_DIET
1074 		uint8_t access;
1075 
1076 		access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1077 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1078 		MI->ac_idx++;
1079 #endif
1080 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
1081 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = (int64_t)Val;
1082 		MI->flat_insn->detail->arm64.op_count++;
1083 	}
1084 }
1085 
printShifter(MCInst * MI,unsigned OpNum,SStream * O)1086 static void printShifter(MCInst *MI, unsigned OpNum, SStream *O)
1087 {
1088 	unsigned Val = (unsigned)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1089 
1090 	// LSL #0 should not be printed.
1091 	if (AArch64_AM_getShiftType(Val) == AArch64_AM_LSL &&
1092 			AArch64_AM_getShiftValue(Val) == 0)
1093 		return;
1094 
1095 	SStream_concat(O, ", %s ", AArch64_AM_getShiftExtendName(AArch64_AM_getShiftType(Val)));
1096 	printInt32BangDec(O, AArch64_AM_getShiftValue(Val));
1097 
1098 	if (MI->csh->detail) {
1099 		arm64_shifter shifter = ARM64_SFT_INVALID;
1100 
1101 		switch(AArch64_AM_getShiftType(Val)) {
1102 			default:	// never reach
1103 			case AArch64_AM_LSL:
1104 				shifter = ARM64_SFT_LSL;
1105 				break;
1106 
1107 			case AArch64_AM_LSR:
1108 				shifter = ARM64_SFT_LSR;
1109 				break;
1110 
1111 			case AArch64_AM_ASR:
1112 				shifter = ARM64_SFT_ASR;
1113 				break;
1114 
1115 			case AArch64_AM_ROR:
1116 				shifter = ARM64_SFT_ROR;
1117 				break;
1118 
1119 			case AArch64_AM_MSL:
1120 				shifter = ARM64_SFT_MSL;
1121 				break;
1122 		}
1123 
1124 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].shift.type = shifter;
1125 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].shift.value = AArch64_AM_getShiftValue(Val);
1126 	}
1127 }
1128 
printShiftedRegister(MCInst * MI,unsigned OpNum,SStream * O)1129 static void printShiftedRegister(MCInst *MI, unsigned OpNum, SStream *O)
1130 {
1131 	SStream_concat0(O, getRegisterName(MCOperand_getReg(MCInst_getOperand(MI, OpNum)), AArch64_NoRegAltName));
1132 
1133 	if (MI->csh->detail) {
1134 #ifndef CAPSTONE_DIET
1135 		uint8_t access;
1136 		access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1137 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1138 		MI->ac_idx++;
1139 #endif
1140 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
1141 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
1142 		MI->flat_insn->detail->arm64.op_count++;
1143 	}
1144 
1145 	printShifter(MI, OpNum + 1, O);
1146 }
1147 
printArithExtend(MCInst * MI,unsigned OpNum,SStream * O)1148 static void printArithExtend(MCInst *MI, unsigned OpNum, SStream *O)
1149 {
1150 	unsigned Val = (unsigned)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1151 	AArch64_AM_ShiftExtendType ExtType = AArch64_AM_getArithExtendType(Val);
1152 	unsigned ShiftVal = AArch64_AM_getArithShiftValue(Val);
1153 
1154 	// If the destination or first source register operand is [W]SP, print
1155 	// UXTW/UXTX as LSL, and if the shift amount is also zero, print nothing at
1156 	// all.
1157 	if (ExtType == AArch64_AM_UXTW || ExtType == AArch64_AM_UXTX) {
1158 		unsigned Dest = MCOperand_getReg(MCInst_getOperand(MI, 0));
1159 		unsigned Src1 = MCOperand_getReg(MCInst_getOperand(MI, 1));
1160 
1161 		if (((Dest == AArch64_SP || Src1 == AArch64_SP) &&
1162 					ExtType == AArch64_AM_UXTX) ||
1163 				((Dest == AArch64_WSP || Src1 == AArch64_WSP) &&
1164 				 ExtType == AArch64_AM_UXTW)) {
1165 			if (ShiftVal != 0) {
1166 				SStream_concat0(O, ", lsl ");
1167 				printInt32Bang(O, ShiftVal);
1168 
1169 				if (MI->csh->detail) {
1170 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].shift.type = ARM64_SFT_LSL;
1171 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].shift.value = ShiftVal;
1172 				}
1173 			}
1174 
1175 			return;
1176 		}
1177 	}
1178 
1179 	SStream_concat(O, ", %s", AArch64_AM_getShiftExtendName(ExtType));
1180 
1181 	if (MI->csh->detail) {
1182 		arm64_extender ext = ARM64_EXT_INVALID;
1183 		switch(ExtType) {
1184 			default:	// never reach
1185 
1186 			case AArch64_AM_UXTB:
1187 				ext = ARM64_EXT_UXTB;
1188 				break;
1189 
1190 			case AArch64_AM_UXTH:
1191 				ext = ARM64_EXT_UXTH;
1192 				break;
1193 
1194 			case AArch64_AM_UXTW:
1195 				ext = ARM64_EXT_UXTW;
1196 				break;
1197 
1198 			case AArch64_AM_UXTX:
1199 				ext = ARM64_EXT_UXTX;
1200 				break;
1201 
1202 			case AArch64_AM_SXTB:
1203 				ext = ARM64_EXT_SXTB;
1204 				break;
1205 
1206 			case AArch64_AM_SXTH:
1207 				ext = ARM64_EXT_SXTH;
1208 				break;
1209 
1210 			case AArch64_AM_SXTW:
1211 				ext = ARM64_EXT_SXTW;
1212 				break;
1213 
1214 			case AArch64_AM_SXTX:
1215 				ext = ARM64_EXT_SXTX;
1216 				break;
1217 		}
1218 
1219 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].ext = ext;
1220 	}
1221 
1222 	if (ShiftVal != 0) {
1223 		SStream_concat0(O, " ");
1224 		printInt32Bang(O, ShiftVal);
1225 
1226 		if (MI->csh->detail) {
1227 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].shift.type = ARM64_SFT_LSL;
1228 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].shift.value = ShiftVal;
1229 		}
1230 	}
1231 }
1232 
printExtendedRegister(MCInst * MI,unsigned OpNum,SStream * O)1233 static void printExtendedRegister(MCInst *MI, unsigned OpNum, SStream *O)
1234 {
1235 	unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
1236 
1237 	SStream_concat0(O, getRegisterName(Reg, AArch64_NoRegAltName));
1238 
1239 	if (MI->csh->detail) {
1240 #ifndef CAPSTONE_DIET
1241 		uint8_t access;
1242 		access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1243 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1244 		MI->ac_idx++;
1245 #endif
1246 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
1247 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = Reg;
1248 		MI->flat_insn->detail->arm64.op_count++;
1249 	}
1250 
1251 	printArithExtend(MI, OpNum + 1, O);
1252 }
1253 
printMemExtendImpl(MCInst * MI,bool SignExtend,bool DoShift,unsigned Width,char SrcRegKind,SStream * O)1254 static void printMemExtendImpl(MCInst *MI, bool SignExtend, bool DoShift, unsigned Width,
1255 			       char SrcRegKind, SStream *O)
1256 {
1257 	// sxtw, sxtx, uxtw or lsl (== uxtx)
1258 	bool IsLSL = !SignExtend && SrcRegKind == 'x';
1259 	if (IsLSL) {
1260 		SStream_concat0(O, "lsl");
1261 
1262 		if (MI->csh->detail) {
1263 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].shift.type = ARM64_SFT_LSL;
1264 		}
1265 	} else {
1266 		SStream_concat(O, "%cxt%c", (SignExtend ? 's' : 'u'), SrcRegKind);
1267 
1268 		if (MI->csh->detail) {
1269 			if (!SignExtend) {
1270 				switch(SrcRegKind) {
1271 					default: break;
1272 					case 'b':
1273 							 MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].ext = ARM64_EXT_UXTB;
1274 							 break;
1275 					case 'h':
1276 							 MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].ext = ARM64_EXT_UXTH;
1277 							 break;
1278 					case 'w':
1279 							 MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].ext = ARM64_EXT_UXTW;
1280 							 break;
1281 				}
1282 			} else {
1283 					switch(SrcRegKind) {
1284 						default: break;
1285 						case 'b':
1286 							MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].ext = ARM64_EXT_SXTB;
1287 							break;
1288 						case 'h':
1289 							MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].ext = ARM64_EXT_SXTH;
1290 							break;
1291 						case 'w':
1292 							MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].ext = ARM64_EXT_SXTW;
1293 							break;
1294 						case 'x':
1295 							MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].ext = ARM64_EXT_SXTX;
1296 							break;
1297 					}
1298 			}
1299 		}
1300 	}
1301 
1302 	if (DoShift || IsLSL) {
1303 		SStream_concat(O, " #%u", Log2_32(Width / 8));
1304 
1305 		if (MI->csh->detail) {
1306 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].shift.type = ARM64_SFT_LSL;
1307 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].shift.value = Log2_32(Width / 8);
1308 		}
1309 	}
1310 }
1311 
printMemExtend(MCInst * MI,unsigned OpNum,SStream * O,char SrcRegKind,unsigned Width)1312 static void printMemExtend(MCInst *MI, unsigned OpNum, SStream *O, char SrcRegKind, unsigned Width)
1313 {
1314 	unsigned SignExtend = (unsigned)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1315 	unsigned DoShift = (unsigned)MCOperand_getImm(MCInst_getOperand(MI, OpNum + 1));
1316 
1317 	printMemExtendImpl(MI, SignExtend, DoShift, Width, SrcRegKind, O);
1318 }
1319 
printRegWithShiftExtend(MCInst * MI,unsigned OpNum,SStream * O,bool SignExtend,int ExtWidth,char SrcRegKind,char Suffix)1320 static void printRegWithShiftExtend(MCInst *MI, unsigned OpNum, SStream *O,
1321 				    bool SignExtend, int ExtWidth,
1322 				    char SrcRegKind, char Suffix)
1323 {
1324 	bool DoShift;
1325 
1326 	printOperand(MI, OpNum, O);
1327 
1328 	if (Suffix == 's' || Suffix == 'd')
1329 		SStream_concat(O, ".%c", Suffix);
1330 
1331 	DoShift = ExtWidth != 8;
1332 	if (SignExtend || DoShift || SrcRegKind == 'w') {
1333 		SStream_concat0(O, ", ");
1334 		printMemExtendImpl(MI, SignExtend, DoShift, ExtWidth, SrcRegKind, O);
1335 	}
1336 }
1337 
printCondCode(MCInst * MI,unsigned OpNum,SStream * O)1338 static void printCondCode(MCInst *MI, unsigned OpNum, SStream *O)
1339 {
1340 	AArch64CC_CondCode CC = (AArch64CC_CondCode)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1341 	SStream_concat0(O, getCondCodeName(CC));
1342 
1343 	if (MI->csh->detail)
1344 		MI->flat_insn->detail->arm64.cc = (arm64_cc)(CC + 1);
1345 }
1346 
printInverseCondCode(MCInst * MI,unsigned OpNum,SStream * O)1347 static void printInverseCondCode(MCInst *MI, unsigned OpNum, SStream *O)
1348 {
1349 	AArch64CC_CondCode CC = (AArch64CC_CondCode)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1350 	SStream_concat0(O, getCondCodeName(getInvertedCondCode(CC)));
1351 
1352 	if (MI->csh->detail) {
1353 		MI->flat_insn->detail->arm64.cc = (arm64_cc)(getInvertedCondCode(CC) + 1);
1354 	}
1355 }
1356 
printImmScale(MCInst * MI,unsigned OpNum,SStream * O,int Scale)1357 static void printImmScale(MCInst *MI, unsigned OpNum, SStream *O, int Scale)
1358 {
1359 	int64_t val = Scale * MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1360 
1361 	printInt64Bang(O, val);
1362 
1363 	if (MI->csh->detail) {
1364 		if (MI->csh->doing_mem) {
1365 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].mem.disp = (int32_t)val;
1366 		} else {
1367 #ifndef CAPSTONE_DIET
1368 			uint8_t access;
1369 
1370 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1371 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1372 			MI->ac_idx++;
1373 #endif
1374 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
1375 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = val;
1376 			MI->flat_insn->detail->arm64.op_count++;
1377 		}
1378 	}
1379 }
1380 
printUImm12Offset(MCInst * MI,unsigned OpNum,SStream * O,unsigned Scale)1381 static void printUImm12Offset(MCInst *MI, unsigned OpNum, SStream *O, unsigned Scale)
1382 {
1383 	MCOperand *MO = MCInst_getOperand(MI, OpNum);
1384 
1385 	if (MCOperand_isImm(MO)) {
1386 		int64_t val = Scale * MCOperand_getImm(MO);
1387 		printInt64Bang(O, val);
1388 
1389 		if (MI->csh->detail) {
1390 			if (MI->csh->doing_mem) {
1391 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].mem.disp = (int32_t)val;
1392 			} else {
1393 #ifndef CAPSTONE_DIET
1394 				uint8_t access;
1395 
1396 				access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1397 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1398 				MI->ac_idx++;
1399 #endif
1400 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
1401 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = (int)val;
1402 				MI->flat_insn->detail->arm64.op_count++;
1403 			}
1404 		}
1405 	}
1406 }
1407 
1408 #if 0
1409 static void printAMIndexedWB(MCInst *MI, unsigned OpNum, SStream *O, unsigned int Scale)
1410 {
1411 	MCOperand *MO = MCInst_getOperand(MI, OpNum + 1);
1412 
1413 	SStream_concat(O, "[%s", getRegisterName(MCOperand_getReg(MCInst_getOperand(MI, OpNum)), AArch64_NoRegAltName));
1414 
1415 	if (MCOperand_isImm(MO)) {
1416 		int64_t val = Scale * MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1417 		printInt64Bang(O, val);
1418 	// } else {
1419 	//   // assert(MO1.isExpr() && "Unexpected operand type!");
1420 	//   SStream_concat0(O, ", ");
1421 	//   MO1.getExpr()->print(O, &MAI);
1422 	}
1423 
1424 	SStream_concat0(O, "]");
1425 }
1426 #endif
1427 
1428 // IsSVEPrefetch = false
printPrefetchOp(MCInst * MI,unsigned OpNum,SStream * O,bool IsSVEPrefetch)1429 static void printPrefetchOp(MCInst *MI, unsigned OpNum, SStream *O, bool IsSVEPrefetch)
1430 {
1431 	unsigned prfop = (unsigned)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1432 
1433 	if (IsSVEPrefetch) {
1434 		const SVEPRFM *PRFM = lookupSVEPRFMByEncoding(prfop);
1435 		if (PRFM)
1436 			SStream_concat0(O, PRFM->Name);
1437 
1438 		return;
1439 	} else {
1440 		const PRFM *PRFM = lookupPRFMByEncoding(prfop);
1441 		if (PRFM)
1442 			SStream_concat0(O, PRFM->Name);
1443 
1444 		return;
1445 	}
1446 
1447 	// FIXME: set OpcodePub?
1448 
1449 	printInt32Bang(O, prfop);
1450 
1451 	if (MI->csh->detail) {
1452 #ifndef CAPSTONE_DIET
1453 		uint8_t access;
1454 		access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1455 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1456 		MI->ac_idx++;
1457 #endif
1458 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
1459 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = prfop;
1460 		MI->flat_insn->detail->arm64.op_count++;
1461 	}
1462 }
1463 
printPSBHintOp(MCInst * MI,unsigned OpNum,SStream * O)1464 static void printPSBHintOp(MCInst *MI, unsigned OpNum, SStream *O)
1465 {
1466 	MCOperand *Op = MCInst_getOperand(MI, OpNum);
1467 	unsigned int psbhintop = MCOperand_getImm(Op);
1468 
1469 	const PSB *PSB = AArch64PSBHint_lookupPSBByEncoding(psbhintop);
1470 	if (PSB)
1471 		SStream_concat0(O, PSB->Name);
1472 	else
1473 		printUInt32Bang(O, psbhintop);
1474 }
1475 
printFPImmOperand(MCInst * MI,unsigned OpNum,SStream * O)1476 static void printFPImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
1477 {
1478 	MCOperand *MO = MCInst_getOperand(MI, OpNum);
1479 	float FPImm = MCOperand_isFPImm(MO) ? MCOperand_getFPImm(MO) : AArch64_AM_getFPImmFloat((int)MCOperand_getImm(MO));
1480 
1481 	// 8 decimal places are enough to perfectly represent permitted floats.
1482 #if defined(_KERNEL_MODE)
1483 	// Issue #681: Windows kernel does not support formatting float point
1484 	SStream_concat(O, "#<float_point_unsupported>");
1485 #else
1486 	SStream_concat(O, "#%.8f", FPImm);
1487 #endif
1488 
1489 	if (MI->csh->detail) {
1490 #ifndef CAPSTONE_DIET
1491 		uint8_t access;
1492 
1493 		access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1494 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1495 		MI->ac_idx++;
1496 #endif
1497 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_FP;
1498 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].fp = FPImm;
1499 		MI->flat_insn->detail->arm64.op_count++;
1500 	}
1501 }
1502 
1503 //static unsigned getNextVectorRegister(unsigned Reg, unsigned Stride = 1)
getNextVectorRegister(unsigned Reg,unsigned Stride)1504 static unsigned getNextVectorRegister(unsigned Reg, unsigned Stride)
1505 {
1506 	while (Stride--) {
1507 		if (Reg >= AArch64_Q0 && Reg <= AArch64_Q30) // AArch64_Q0 .. AArch64_Q30
1508 			Reg += 1;
1509 		else if (Reg == AArch64_Q31) // Vector lists can wrap around.
1510 			Reg = AArch64_Q0;
1511 		else if (Reg >= AArch64_Z0 && Reg <= AArch64_Z30) // AArch64_Z0 .. AArch64_Z30
1512 			Reg += 1;
1513 		else if (Reg == AArch64_Z31) // Vector lists can wrap around.
1514 			Reg = AArch64_Z0;
1515 	}
1516 
1517 	return Reg;
1518 }
1519 
printGPRSeqPairsClassOperand(MCInst * MI,unsigned OpNum,SStream * O,unsigned int size)1520 static void printGPRSeqPairsClassOperand(MCInst *MI, unsigned OpNum, SStream *O, unsigned int size)
1521 {
1522 	// static_assert(size == 64 || size == 32,
1523 	//		"Template parameter must be either 32 or 64");
1524 	unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
1525 	unsigned Sube = (size == 32) ? AArch64_sube32 : AArch64_sube64;
1526 	unsigned Subo = (size == 32) ? AArch64_subo32 : AArch64_subo64;
1527 	unsigned Even = MCRegisterInfo_getSubReg(MI->MRI, Reg, Sube);
1528 	unsigned Odd = MCRegisterInfo_getSubReg(MI->MRI, Reg, Subo);
1529 
1530 	SStream_concat(O, "%s, %s", getRegisterName(Even, AArch64_NoRegAltName),
1531 			getRegisterName(Odd, AArch64_NoRegAltName));
1532 
1533 	if (MI->csh->detail) {
1534 #ifndef CAPSTONE_DIET
1535 		uint8_t access;
1536 
1537 		access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1538 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1539 		MI->ac_idx++;
1540 #endif
1541 
1542 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
1543 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = AArch64_map_vregister(Even);
1544 		MI->flat_insn->detail->arm64.op_count++;
1545 
1546 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
1547 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = AArch64_map_vregister(Odd);
1548 		MI->flat_insn->detail->arm64.op_count++;
1549 	}
1550 }
1551 
printVectorList(MCInst * MI,unsigned OpNum,SStream * O,char * LayoutSuffix,MCRegisterInfo * MRI,arm64_vas vas)1552 static void printVectorList(MCInst *MI, unsigned OpNum, SStream *O,
1553 		char *LayoutSuffix, MCRegisterInfo *MRI, arm64_vas vas)
1554 {
1555 #define GETREGCLASS_CONTAIN0(_class, _reg) MCRegisterClass_contains(MCRegisterInfo_getRegClass(MRI, _class), _reg)
1556 	unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
1557 	unsigned NumRegs = 1, FirstReg, i;
1558 
1559 	SStream_concat0(O, "{");
1560 
1561 	// Work out how many registers there are in the list (if there is an actual
1562 	// list).
1563 	if (GETREGCLASS_CONTAIN0(AArch64_DDRegClassID , Reg) ||
1564 			GETREGCLASS_CONTAIN0(AArch64_ZPR2RegClassID, Reg) ||
1565 			GETREGCLASS_CONTAIN0(AArch64_QQRegClassID, Reg))
1566 		NumRegs = 2;
1567 	else if (GETREGCLASS_CONTAIN0(AArch64_DDDRegClassID, Reg) ||
1568 			GETREGCLASS_CONTAIN0(AArch64_ZPR3RegClassID, Reg) ||
1569 			GETREGCLASS_CONTAIN0(AArch64_QQQRegClassID, Reg))
1570 		NumRegs = 3;
1571 	else if (GETREGCLASS_CONTAIN0(AArch64_DDDDRegClassID, Reg) ||
1572 			GETREGCLASS_CONTAIN0(AArch64_ZPR4RegClassID, Reg) ||
1573 			GETREGCLASS_CONTAIN0(AArch64_QQQQRegClassID, Reg))
1574 		NumRegs = 4;
1575 
1576 	// Now forget about the list and find out what the first register is.
1577 	if ((FirstReg = MCRegisterInfo_getSubReg(MRI, Reg, AArch64_dsub0)))
1578 		Reg = FirstReg;
1579 	else if ((FirstReg = MCRegisterInfo_getSubReg(MRI, Reg, AArch64_qsub0)))
1580 		Reg = FirstReg;
1581 	else if ((FirstReg = MCRegisterInfo_getSubReg(MRI, Reg, AArch64_zsub0)))
1582 		Reg = FirstReg;
1583 
1584 	// If it's a D-reg, we need to promote it to the equivalent Q-reg before
1585 	// printing (otherwise getRegisterName fails).
1586 	if (GETREGCLASS_CONTAIN0(AArch64_FPR64RegClassID, Reg)) {
1587 		const MCRegisterClass *FPR128RC = MCRegisterInfo_getRegClass(MRI, AArch64_FPR128RegClassID);
1588 		Reg = MCRegisterInfo_getMatchingSuperReg(MRI, Reg, AArch64_dsub, FPR128RC);
1589 	}
1590 
1591 	for (i = 0; i < NumRegs; ++i, Reg = getNextVectorRegister(Reg, 1)) {
1592 		if (GETREGCLASS_CONTAIN0(AArch64_ZPRRegClassID, Reg))
1593 			SStream_concat(O, "%s%s", getRegisterName(Reg, AArch64_NoRegAltName), LayoutSuffix);
1594 		else
1595 			SStream_concat(O, "%s%s", getRegisterName(Reg, AArch64_vreg), LayoutSuffix);
1596 
1597 		if (MI->csh->detail) {
1598 #ifndef CAPSTONE_DIET
1599 			uint8_t access;
1600 
1601 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1602 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1603 			MI->ac_idx++;
1604 #endif
1605 
1606 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
1607 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = AArch64_map_vregister(Reg);
1608 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].vas = vas;
1609 			MI->flat_insn->detail->arm64.op_count++;
1610 		}
1611 
1612 		if (i + 1 != NumRegs)
1613 			SStream_concat0(O, ", ");
1614 	}
1615 
1616 	SStream_concat0(O, "}");
1617 }
1618 
printTypedVectorList(MCInst * MI,unsigned OpNum,SStream * O,unsigned NumLanes,char LaneKind)1619 static void printTypedVectorList(MCInst *MI, unsigned OpNum, SStream *O, unsigned NumLanes, char LaneKind)
1620 {
1621 	char Suffix[32];
1622 	arm64_vas vas = 0;
1623 
1624 	if (NumLanes) {
1625 		cs_snprintf(Suffix, sizeof(Suffix), ".%u%c", NumLanes, LaneKind);
1626 
1627 		switch(LaneKind) {
1628 			default: break;
1629 			case 'b':
1630 				switch(NumLanes) {
1631 					default: break;
1632 					case 1:
1633 							 vas = ARM64_VAS_1B;
1634 							 break;
1635 					case 4:
1636 							 vas = ARM64_VAS_4B;
1637 							 break;
1638 					case 8:
1639 							 vas = ARM64_VAS_8B;
1640 							 break;
1641 					case 16:
1642 							 vas = ARM64_VAS_16B;
1643 							 break;
1644 				}
1645 				break;
1646 			case 'h':
1647 				switch(NumLanes) {
1648 					default: break;
1649 					case 1:
1650 							 vas = ARM64_VAS_1H;
1651 							 break;
1652 					case 2:
1653 							 vas = ARM64_VAS_2H;
1654 							 break;
1655 					case 4:
1656 							 vas = ARM64_VAS_4H;
1657 							 break;
1658 					case 8:
1659 							 vas = ARM64_VAS_8H;
1660 							 break;
1661 				}
1662 				break;
1663 			case 's':
1664 				switch(NumLanes) {
1665 					default: break;
1666 					case 1:
1667 							 vas = ARM64_VAS_1S;
1668 							 break;
1669 					case 2:
1670 							 vas = ARM64_VAS_2S;
1671 							 break;
1672 					case 4:
1673 							 vas = ARM64_VAS_4S;
1674 							 break;
1675 				}
1676 				break;
1677 			case 'd':
1678 				switch(NumLanes) {
1679 					default: break;
1680 					case 1:
1681 							 vas = ARM64_VAS_1D;
1682 							 break;
1683 					case 2:
1684 							 vas = ARM64_VAS_2D;
1685 							 break;
1686 				}
1687 				break;
1688 			case 'q':
1689 				switch(NumLanes) {
1690 					default: break;
1691 					case 1:
1692 							 vas = ARM64_VAS_1Q;
1693 							 break;
1694 				}
1695 				break;
1696 		}
1697 	} else {
1698 		cs_snprintf(Suffix, sizeof(Suffix), ".%c", LaneKind);
1699 
1700 		switch(LaneKind) {
1701 			default: break;
1702 			case 'b':
1703 					 vas = ARM64_VAS_1B;
1704 					 break;
1705 			case 'h':
1706 					 vas = ARM64_VAS_1H;
1707 					 break;
1708 			case 's':
1709 					 vas = ARM64_VAS_1S;
1710 					 break;
1711 			case 'd':
1712 					 vas = ARM64_VAS_1D;
1713 					 break;
1714 			case 'q':
1715 					 vas = ARM64_VAS_1Q;
1716 					 break;
1717 		}
1718 	}
1719 
1720 	printVectorList(MI, OpNum, O, Suffix, MI->MRI, vas);
1721 }
1722 
printVectorIndex(MCInst * MI,unsigned OpNum,SStream * O)1723 static void printVectorIndex(MCInst *MI, unsigned OpNum, SStream *O)
1724 {
1725 	SStream_concat0(O, "[");
1726 	printInt32(O, (int)MCOperand_getImm(MCInst_getOperand(MI, OpNum)));
1727 	SStream_concat0(O, "]");
1728 
1729 	if (MI->csh->detail) {
1730 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].vector_index = (int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1731 	}
1732 }
1733 
printAlignedLabel(MCInst * MI,unsigned OpNum,SStream * O)1734 static void printAlignedLabel(MCInst *MI, unsigned OpNum, SStream *O)
1735 {
1736 	MCOperand *Op = MCInst_getOperand(MI, OpNum);
1737 
1738 	// If the label has already been resolved to an immediate offset (say, when
1739 	// we're running the disassembler), just print the immediate.
1740 	if (MCOperand_isImm(Op)) {
1741 		uint64_t imm = (MCOperand_getImm(Op) * 4) + MI->address;
1742 		printUInt64Bang(O, imm);
1743 
1744 		if (MI->csh->detail) {
1745 #ifndef CAPSTONE_DIET
1746 			uint8_t access;
1747 
1748 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1749 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1750 			MI->ac_idx++;
1751 #endif
1752 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
1753 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = imm;
1754 			MI->flat_insn->detail->arm64.op_count++;
1755 		}
1756 	}
1757 }
1758 
printAdrpLabel(MCInst * MI,unsigned OpNum,SStream * O)1759 static void printAdrpLabel(MCInst *MI, unsigned OpNum, SStream *O)
1760 {
1761 	MCOperand *Op = MCInst_getOperand(MI, OpNum);
1762 
1763 	if (MCOperand_isImm(Op)) {
1764 		// ADRP sign extends a 21-bit offset, shifts it left by 12
1765 		// and adds it to the value of the PC with its bottom 12 bits cleared
1766 		uint64_t imm = (MCOperand_getImm(Op) * 0x1000) + (MI->address & ~0xfff);
1767 		printUInt64Bang(O, imm);
1768 
1769 		if (MI->csh->detail) {
1770 #ifndef CAPSTONE_DIET
1771 			uint8_t access;
1772 
1773 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1774 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1775 			MI->ac_idx++;
1776 #endif
1777 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
1778 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = imm;
1779 			MI->flat_insn->detail->arm64.op_count++;
1780 		}
1781 	}
1782 }
1783 
printBarrierOption(MCInst * MI,unsigned OpNum,SStream * O)1784 static void printBarrierOption(MCInst *MI, unsigned OpNum, SStream *O)
1785 {
1786 	unsigned Val = (unsigned)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1787 	unsigned Opcode = MCInst_getOpcode(MI);
1788 	const char *Name = NULL;
1789 
1790 	if (Opcode == AArch64_ISB) {
1791 		const ISB *ISB = lookupISBByEncoding(Val);
1792 		Name = ISB ? ISB->Name : NULL;
1793 	} else if (Opcode == AArch64_TSB) {
1794 		const TSB *TSB = lookupTSBByEncoding(Val);
1795 		Name = TSB ? TSB->Name : NULL;
1796 	} else {
1797 		const DB *DB = lookupDBByEncoding(Val);
1798 		Name = DB ? DB->Name : NULL;
1799 	}
1800 
1801 	if (Name) {
1802 		SStream_concat0(O, Name);
1803 
1804 		if (MI->csh->detail) {
1805 #ifndef CAPSTONE_DIET
1806 			uint8_t access;
1807 
1808 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1809 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1810 			MI->ac_idx++;
1811 #endif
1812 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_BARRIER;
1813 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].barrier = Val;
1814 			MI->flat_insn->detail->arm64.op_count++;
1815 		}
1816 	} else {
1817 		printUInt32Bang(O, Val);
1818 
1819 		if (MI->csh->detail) {
1820 #ifndef CAPSTONE_DIET
1821 			uint8_t access;
1822 
1823 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1824 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1825 			MI->ac_idx++;
1826 #endif
1827 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
1828 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = Val;
1829 			MI->flat_insn->detail->arm64.op_count++;
1830 		}
1831 	}
1832 }
1833 
printMRSSystemRegister(MCInst * MI,unsigned OpNum,SStream * O)1834 static void printMRSSystemRegister(MCInst *MI, unsigned OpNum, SStream *O)
1835 {
1836 	unsigned Val = (unsigned)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1837 	const SysReg *Reg = lookupSysRegByEncoding(Val);
1838 
1839 	// Horrible hack for the one register that has identical encodings but
1840 	// different names in MSR and MRS. Because of this, one of MRS and MSR is
1841 	// going to get the wrong entry
1842 	if (Val == ARM64_SYSREG_DBGDTRRX_EL0) {
1843 		SStream_concat0(O, "dbgdtrrx_el0");
1844 
1845 		if (MI->csh->detail) {
1846 #ifndef CAPSTONE_DIET
1847 			uint8_t access;
1848 
1849 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1850 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1851 			MI->ac_idx++;
1852 #endif
1853 
1854 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_SYS;
1855 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].sys = Val;
1856 			MI->flat_insn->detail->arm64.op_count++;
1857 		}
1858 
1859 		return;
1860 	}
1861 
1862 	// if (Reg && Reg->Readable && Reg->haveFeatures(STI.getFeatureBits()))
1863 	if (Reg && Reg->Readable) {
1864 		SStream_concat0(O, Reg->Name);
1865 
1866 		if (MI->csh->detail) {
1867 #ifndef CAPSTONE_DIET
1868 			uint8_t access;
1869 
1870 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1871 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1872 			MI->ac_idx++;
1873 #endif
1874 
1875 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_SYS;
1876 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].sys = Reg->Encoding;
1877 			MI->flat_insn->detail->arm64.op_count++;
1878 		}
1879 	} else {
1880 		char result[128];
1881 
1882 		AArch64SysReg_genericRegisterString(Val, result);
1883 		SStream_concat0(O, result);
1884 
1885 		if (MI->csh->detail) {
1886 #ifndef CAPSTONE_DIET
1887 			uint8_t access;
1888 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1889 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1890 			MI->ac_idx++;
1891 #endif
1892 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG_MRS;
1893 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = Val;
1894 			MI->flat_insn->detail->arm64.op_count++;
1895 		}
1896 	}
1897 }
1898 
printMSRSystemRegister(MCInst * MI,unsigned OpNum,SStream * O)1899 static void printMSRSystemRegister(MCInst *MI, unsigned OpNum, SStream *O)
1900 {
1901 	unsigned Val = (unsigned)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1902 	const SysReg *Reg = lookupSysRegByEncoding(Val);
1903 
1904 	// Horrible hack for the one register that has identical encodings but
1905 	// different names in MSR and MRS. Because of this, one of MRS and MSR is
1906 	// going to get the wrong entry
1907 	if (Val == ARM64_SYSREG_DBGDTRTX_EL0) {
1908 		SStream_concat0(O, "dbgdtrtx_el0");
1909 
1910 		if (MI->csh->detail) {
1911 #ifndef CAPSTONE_DIET
1912 			uint8_t access;
1913 
1914 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1915 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1916 			MI->ac_idx++;
1917 #endif
1918 
1919 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_SYS;
1920 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].sys = Val;
1921 			MI->flat_insn->detail->arm64.op_count++;
1922 		}
1923 
1924 		return;
1925 	}
1926 
1927 	// if (Reg && Reg->Writeable && Reg->haveFeatures(STI.getFeatureBits()))
1928 	if (Reg && Reg->Writeable) {
1929 		SStream_concat0(O, Reg->Name);
1930 
1931 		if (MI->csh->detail) {
1932 #ifndef CAPSTONE_DIET
1933 			uint8_t access;
1934 
1935 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1936 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1937 			MI->ac_idx++;
1938 #endif
1939 
1940 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_SYS;
1941 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].sys = Reg->Encoding;
1942 			MI->flat_insn->detail->arm64.op_count++;
1943 		}
1944 	} else {
1945 		char result[128];
1946 
1947 		AArch64SysReg_genericRegisterString(Val, result);
1948 		SStream_concat0(O, result);
1949 
1950 		if (MI->csh->detail) {
1951 #ifndef CAPSTONE_DIET
1952 			uint8_t access;
1953 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1954 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1955 			MI->ac_idx++;
1956 #endif
1957 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG_MRS;
1958 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = Val;
1959 			MI->flat_insn->detail->arm64.op_count++;
1960 		}
1961 	}
1962 }
1963 
printSystemPStateField(MCInst * MI,unsigned OpNum,SStream * O)1964 static void printSystemPStateField(MCInst *MI, unsigned OpNum, SStream *O)
1965 {
1966 	unsigned Val = (unsigned)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1967 
1968 	const PState *PState = lookupPStateByEncoding(Val);
1969 
1970 	if (PState) {
1971 		SStream_concat0(O, PState->Name);
1972 
1973 		if (MI->csh->detail) {
1974 #ifndef CAPSTONE_DIET
1975 			uint8_t access;
1976 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1977 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1978 			MI->ac_idx++;
1979 #endif
1980 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_PSTATE;
1981 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].pstate = Val;
1982 			MI->flat_insn->detail->arm64.op_count++;
1983 		}
1984 	} else {
1985 		printUInt32Bang(O, Val);
1986 
1987 		if (MI->csh->detail) {
1988 #ifndef CAPSTONE_DIET
1989 			unsigned char access;
1990 
1991 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1992 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1993 			MI->ac_idx++;
1994 #endif
1995 
1996 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
1997 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = Val;
1998 			MI->flat_insn->detail->arm64.op_count++;
1999 		}
2000 	}
2001 }
2002 
printSIMDType10Operand(MCInst * MI,unsigned OpNum,SStream * O)2003 static void printSIMDType10Operand(MCInst *MI, unsigned OpNum, SStream *O)
2004 {
2005 	uint8_t RawVal = (uint8_t)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2006 	uint64_t Val = AArch64_AM_decodeAdvSIMDModImmType10(RawVal);
2007 
2008 	SStream_concat(O, "#%#016llx", Val);
2009 
2010 	if (MI->csh->detail) {
2011 #ifndef CAPSTONE_DIET
2012 		unsigned char access;
2013 
2014 		access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2015 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
2016 		MI->ac_idx++;
2017 #endif
2018 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
2019 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = Val;
2020 		MI->flat_insn->detail->arm64.op_count++;
2021 	}
2022 }
2023 
printComplexRotationOp(MCInst * MI,unsigned OpNum,SStream * O,int64_t Angle,int64_t Remainder)2024 static void printComplexRotationOp(MCInst *MI, unsigned OpNum, SStream *O, int64_t Angle, int64_t Remainder)
2025 {
2026 	unsigned int Val = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2027 	printInt64Bang(O, (Val * Angle) + Remainder);
2028 	op_addImm(MI, (Val * Angle) + Remainder);
2029 }
2030 
printSVEPattern(MCInst * MI,unsigned OpNum,SStream * O)2031 static void printSVEPattern(MCInst *MI, unsigned OpNum, SStream *O)
2032 {
2033 	unsigned Val = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2034 
2035 	const SVEPREDPAT *Pat = lookupSVEPREDPATByEncoding(Val);
2036 	if (Pat)
2037 		SStream_concat0(O, Pat->Name);
2038 	else
2039 		printUInt32Bang(O, Val);
2040 }
2041 
2042 // default suffix = 0
printSVERegOp(MCInst * MI,unsigned OpNum,SStream * O,char suffix)2043 static void printSVERegOp(MCInst *MI, unsigned OpNum, SStream *O, char suffix)
2044 {
2045 	unsigned int Reg;
2046 
2047 #if 0
2048 	switch (suffix) {
2049 		case 0:
2050 		case 'b':
2051 		case 'h':
2052 		case 's':
2053 		case 'd':
2054 		case 'q':
2055 			break;
2056 		default:
2057 			// llvm_unreachable("Invalid kind specifier.");
2058 	}
2059 #endif
2060 
2061 	Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2062 
2063 	if (MI->csh->detail) {
2064 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
2065 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = Reg;
2066 		MI->flat_insn->detail->arm64.op_count++;
2067 	}
2068 
2069 	SStream_concat0(O, getRegisterName(Reg, AArch64_NoRegAltName));
2070 
2071 	if (suffix != '\0')
2072 		SStream_concat(O, ".%c", suffix);
2073 }
2074 
printImmSVE16(int16_t Val,SStream * O)2075 static void printImmSVE16(int16_t Val, SStream *O)
2076 {
2077 	printUInt32Bang(O, Val);
2078 }
2079 
printImmSVE32(int32_t Val,SStream * O)2080 static void printImmSVE32(int32_t Val, SStream *O)
2081 {
2082 	printUInt32Bang(O, Val);
2083 }
2084 
printImmSVE64(int64_t Val,SStream * O)2085 static void printImmSVE64(int64_t Val, SStream *O)
2086 {
2087 	printUInt64Bang(O, Val);
2088 }
2089 
printImm8OptLsl32(MCInst * MI,unsigned OpNum,SStream * O)2090 static void printImm8OptLsl32(MCInst *MI, unsigned OpNum, SStream *O)
2091 {
2092 	unsigned UnscaledVal = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2093 	unsigned Shift = MCOperand_getImm(MCInst_getOperand(MI, OpNum + 1));
2094 	uint32_t Val;
2095 
2096 	// assert(AArch64_AM::getShiftType(Shift) == AArch64_AM::LSL &&
2097 	// 	"Unexepected shift type!");
2098 
2099 	// #0 lsl #8 is never pretty printed
2100 	if ((UnscaledVal == 0) && (AArch64_AM_getShiftValue(Shift) != 0)) {
2101 		printUInt32Bang(O, UnscaledVal);
2102 		printShifter(MI, OpNum + 1, O);
2103 		return;
2104 	}
2105 
2106 	Val = UnscaledVal * (1 << AArch64_AM_getShiftValue(Shift));
2107 	printImmSVE32(Val, O);
2108 }
2109 
printImm8OptLsl64(MCInst * MI,unsigned OpNum,SStream * O)2110 static void printImm8OptLsl64(MCInst *MI, unsigned OpNum, SStream *O)
2111 {
2112 	unsigned UnscaledVal = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2113 	unsigned Shift = MCOperand_getImm(MCInst_getOperand(MI, OpNum + 1));
2114 	uint64_t Val;
2115 
2116 	// assert(AArch64_AM::getShiftType(Shift) == AArch64_AM::LSL &&
2117 	// 	"Unexepected shift type!");
2118 
2119 	// #0 lsl #8 is never pretty printed
2120 	if ((UnscaledVal == 0) && (AArch64_AM_getShiftValue(Shift) != 0)) {
2121 		printUInt32Bang(O, UnscaledVal);
2122 		printShifter(MI, OpNum + 1, O);
2123 		return;
2124 	}
2125 
2126 	Val = UnscaledVal * (1 << AArch64_AM_getShiftValue(Shift));
2127 	printImmSVE64(Val, O);
2128 }
2129 
printSVELogicalImm16(MCInst * MI,unsigned OpNum,SStream * O)2130 static void printSVELogicalImm16(MCInst *MI, unsigned OpNum, SStream *O)
2131 {
2132 	uint64_t Val = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2133 	uint64_t PrintVal = AArch64_AM_decodeLogicalImmediate(Val, 64);
2134 
2135 	// Prefer the default format for 16bit values, hex otherwise.
2136 	printImmSVE16(PrintVal, O);
2137 }
2138 
printSVELogicalImm32(MCInst * MI,unsigned OpNum,SStream * O)2139 static void printSVELogicalImm32(MCInst *MI, unsigned OpNum, SStream *O)
2140 {
2141 	uint64_t Val = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2142 	uint64_t PrintVal = AArch64_AM_decodeLogicalImmediate(Val, 64);
2143 
2144 	// Prefer the default format for 16bit values, hex otherwise.
2145 	if ((uint16_t)PrintVal == (uint32_t)PrintVal)
2146 		printImmSVE16(PrintVal, O);
2147 	else
2148 		printUInt64Bang(O, PrintVal);
2149 }
2150 
printSVELogicalImm64(MCInst * MI,unsigned OpNum,SStream * O)2151 static void printSVELogicalImm64(MCInst *MI, unsigned OpNum, SStream *O)
2152 {
2153 	uint64_t Val = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2154 	uint64_t PrintVal = AArch64_AM_decodeLogicalImmediate(Val, 64);
2155 
2156 	printImmSVE64(PrintVal, O);
2157 }
2158 
printZPRasFPR(MCInst * MI,unsigned OpNum,SStream * O,int Width)2159 static void printZPRasFPR(MCInst *MI, unsigned OpNum, SStream *O, int Width)
2160 {
2161 	unsigned int Base, Reg;
2162 
2163 	switch (Width) {
2164 		default: // llvm_unreachable("Unsupported width");
2165 		case 8:   Base = AArch64_B0; break;
2166 		case 16:  Base = AArch64_H0; break;
2167 		case 32:  Base = AArch64_S0; break;
2168 		case 64:  Base = AArch64_D0; break;
2169 		case 128: Base = AArch64_Q0; break;
2170 	}
2171 
2172 	Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2173 
2174 	SStream_concat0(O, getRegisterName(Reg - AArch64_Z0 + Base, AArch64_NoRegAltName));
2175 }
2176 
printExactFPImm(MCInst * MI,unsigned OpNum,SStream * O,unsigned ImmIs0,unsigned ImmIs1)2177 static void printExactFPImm(MCInst *MI, unsigned OpNum, SStream *O, unsigned ImmIs0, unsigned ImmIs1)
2178 {
2179 	const ExactFPImm *Imm0Desc = lookupExactFPImmByEnum(ImmIs0);
2180 	const ExactFPImm *Imm1Desc = lookupExactFPImmByEnum(ImmIs1);
2181 	unsigned Val = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2182 
2183 	SStream_concat0(O, Val ? Imm1Desc->Repr : Imm0Desc->Repr);
2184 }
2185 
printGPR64as32(MCInst * MI,unsigned OpNum,SStream * O)2186 static void printGPR64as32(MCInst *MI, unsigned OpNum, SStream *O)
2187 {
2188 	unsigned int Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2189 
2190 	SStream_concat0(O, getRegisterName(getWRegFromXReg(Reg), AArch64_NoRegAltName));
2191 }
2192 
2193 #define PRINT_ALIAS_INSTR
2194 #include "AArch64GenAsmWriter.inc"
2195 #include "AArch64GenRegisterName.inc"
2196 
AArch64_post_printer(csh handle,cs_insn * flat_insn,char * insn_asm,MCInst * mci)2197 void AArch64_post_printer(csh handle, cs_insn *flat_insn, char *insn_asm, MCInst *mci)
2198 {
2199 	if (((cs_struct *)handle)->detail != CS_OPT_ON)
2200 		return;
2201 
2202 	if (mci->csh->detail) {
2203 		unsigned opcode = MCInst_getOpcode(mci);
2204 
2205 		switch (opcode) {
2206 			default:
2207 				break;
2208 			case AArch64_LD1Fourv16b_POST:
2209 			case AArch64_LD1Fourv1d_POST:
2210 			case AArch64_LD1Fourv2d_POST:
2211 			case AArch64_LD1Fourv2s_POST:
2212 			case AArch64_LD1Fourv4h_POST:
2213 			case AArch64_LD1Fourv4s_POST:
2214 			case AArch64_LD1Fourv8b_POST:
2215 			case AArch64_LD1Fourv8h_POST:
2216 			case AArch64_LD1Onev16b_POST:
2217 			case AArch64_LD1Onev1d_POST:
2218 			case AArch64_LD1Onev2d_POST:
2219 			case AArch64_LD1Onev2s_POST:
2220 			case AArch64_LD1Onev4h_POST:
2221 			case AArch64_LD1Onev4s_POST:
2222 			case AArch64_LD1Onev8b_POST:
2223 			case AArch64_LD1Onev8h_POST:
2224 			case AArch64_LD1Rv16b_POST:
2225 			case AArch64_LD1Rv1d_POST:
2226 			case AArch64_LD1Rv2d_POST:
2227 			case AArch64_LD1Rv2s_POST:
2228 			case AArch64_LD1Rv4h_POST:
2229 			case AArch64_LD1Rv4s_POST:
2230 			case AArch64_LD1Rv8b_POST:
2231 			case AArch64_LD1Rv8h_POST:
2232 			case AArch64_LD1Threev16b_POST:
2233 			case AArch64_LD1Threev1d_POST:
2234 			case AArch64_LD1Threev2d_POST:
2235 			case AArch64_LD1Threev2s_POST:
2236 			case AArch64_LD1Threev4h_POST:
2237 			case AArch64_LD1Threev4s_POST:
2238 			case AArch64_LD1Threev8b_POST:
2239 			case AArch64_LD1Threev8h_POST:
2240 			case AArch64_LD1Twov16b_POST:
2241 			case AArch64_LD1Twov1d_POST:
2242 			case AArch64_LD1Twov2d_POST:
2243 			case AArch64_LD1Twov2s_POST:
2244 			case AArch64_LD1Twov4h_POST:
2245 			case AArch64_LD1Twov4s_POST:
2246 			case AArch64_LD1Twov8b_POST:
2247 			case AArch64_LD1Twov8h_POST:
2248 			case AArch64_LD1i16_POST:
2249 			case AArch64_LD1i32_POST:
2250 			case AArch64_LD1i64_POST:
2251 			case AArch64_LD1i8_POST:
2252 			case AArch64_LD2Rv16b_POST:
2253 			case AArch64_LD2Rv1d_POST:
2254 			case AArch64_LD2Rv2d_POST:
2255 			case AArch64_LD2Rv2s_POST:
2256 			case AArch64_LD2Rv4h_POST:
2257 			case AArch64_LD2Rv4s_POST:
2258 			case AArch64_LD2Rv8b_POST:
2259 			case AArch64_LD2Rv8h_POST:
2260 			case AArch64_LD2Twov16b_POST:
2261 			case AArch64_LD2Twov2d_POST:
2262 			case AArch64_LD2Twov2s_POST:
2263 			case AArch64_LD2Twov4h_POST:
2264 			case AArch64_LD2Twov4s_POST:
2265 			case AArch64_LD2Twov8b_POST:
2266 			case AArch64_LD2Twov8h_POST:
2267 			case AArch64_LD2i16_POST:
2268 			case AArch64_LD2i32_POST:
2269 			case AArch64_LD2i64_POST:
2270 			case AArch64_LD2i8_POST:
2271 			case AArch64_LD3Rv16b_POST:
2272 			case AArch64_LD3Rv1d_POST:
2273 			case AArch64_LD3Rv2d_POST:
2274 			case AArch64_LD3Rv2s_POST:
2275 			case AArch64_LD3Rv4h_POST:
2276 			case AArch64_LD3Rv4s_POST:
2277 			case AArch64_LD3Rv8b_POST:
2278 			case AArch64_LD3Rv8h_POST:
2279 			case AArch64_LD3Threev16b_POST:
2280 			case AArch64_LD3Threev2d_POST:
2281 			case AArch64_LD3Threev2s_POST:
2282 			case AArch64_LD3Threev4h_POST:
2283 			case AArch64_LD3Threev4s_POST:
2284 			case AArch64_LD3Threev8b_POST:
2285 			case AArch64_LD3Threev8h_POST:
2286 			case AArch64_LD3i16_POST:
2287 			case AArch64_LD3i32_POST:
2288 			case AArch64_LD3i64_POST:
2289 			case AArch64_LD3i8_POST:
2290 			case AArch64_LD4Fourv16b_POST:
2291 			case AArch64_LD4Fourv2d_POST:
2292 			case AArch64_LD4Fourv2s_POST:
2293 			case AArch64_LD4Fourv4h_POST:
2294 			case AArch64_LD4Fourv4s_POST:
2295 			case AArch64_LD4Fourv8b_POST:
2296 			case AArch64_LD4Fourv8h_POST:
2297 			case AArch64_LD4Rv16b_POST:
2298 			case AArch64_LD4Rv1d_POST:
2299 			case AArch64_LD4Rv2d_POST:
2300 			case AArch64_LD4Rv2s_POST:
2301 			case AArch64_LD4Rv4h_POST:
2302 			case AArch64_LD4Rv4s_POST:
2303 			case AArch64_LD4Rv8b_POST:
2304 			case AArch64_LD4Rv8h_POST:
2305 			case AArch64_LD4i16_POST:
2306 			case AArch64_LD4i32_POST:
2307 			case AArch64_LD4i64_POST:
2308 			case AArch64_LD4i8_POST:
2309 			case AArch64_LDPDpost:
2310 			case AArch64_LDPDpre:
2311 			case AArch64_LDPQpost:
2312 			case AArch64_LDPQpre:
2313 			case AArch64_LDPSWpost:
2314 			case AArch64_LDPSWpre:
2315 			case AArch64_LDPSpost:
2316 			case AArch64_LDPSpre:
2317 			case AArch64_LDPWpost:
2318 			case AArch64_LDPWpre:
2319 			case AArch64_LDPXpost:
2320 			case AArch64_LDPXpre:
2321 			case AArch64_LDRBBpost:
2322 			case AArch64_LDRBBpre:
2323 			case AArch64_LDRBpost:
2324 			case AArch64_LDRBpre:
2325 			case AArch64_LDRDpost:
2326 			case AArch64_LDRDpre:
2327 			case AArch64_LDRHHpost:
2328 			case AArch64_LDRHHpre:
2329 			case AArch64_LDRHpost:
2330 			case AArch64_LDRHpre:
2331 			case AArch64_LDRQpost:
2332 			case AArch64_LDRQpre:
2333 			case AArch64_LDRSBWpost:
2334 			case AArch64_LDRSBWpre:
2335 			case AArch64_LDRSBXpost:
2336 			case AArch64_LDRSBXpre:
2337 			case AArch64_LDRSHWpost:
2338 			case AArch64_LDRSHWpre:
2339 			case AArch64_LDRSHXpost:
2340 			case AArch64_LDRSHXpre:
2341 			case AArch64_LDRSWpost:
2342 			case AArch64_LDRSWpre:
2343 			case AArch64_LDRSpost:
2344 			case AArch64_LDRSpre:
2345 			case AArch64_LDRWpost:
2346 			case AArch64_LDRWpre:
2347 			case AArch64_LDRXpost:
2348 			case AArch64_LDRXpre:
2349 			case AArch64_ST1Fourv16b_POST:
2350 			case AArch64_ST1Fourv1d_POST:
2351 			case AArch64_ST1Fourv2d_POST:
2352 			case AArch64_ST1Fourv2s_POST:
2353 			case AArch64_ST1Fourv4h_POST:
2354 			case AArch64_ST1Fourv4s_POST:
2355 			case AArch64_ST1Fourv8b_POST:
2356 			case AArch64_ST1Fourv8h_POST:
2357 			case AArch64_ST1Onev16b_POST:
2358 			case AArch64_ST1Onev1d_POST:
2359 			case AArch64_ST1Onev2d_POST:
2360 			case AArch64_ST1Onev2s_POST:
2361 			case AArch64_ST1Onev4h_POST:
2362 			case AArch64_ST1Onev4s_POST:
2363 			case AArch64_ST1Onev8b_POST:
2364 			case AArch64_ST1Onev8h_POST:
2365 			case AArch64_ST1Threev16b_POST:
2366 			case AArch64_ST1Threev1d_POST:
2367 			case AArch64_ST1Threev2d_POST:
2368 			case AArch64_ST1Threev2s_POST:
2369 			case AArch64_ST1Threev4h_POST:
2370 			case AArch64_ST1Threev4s_POST:
2371 			case AArch64_ST1Threev8b_POST:
2372 			case AArch64_ST1Threev8h_POST:
2373 			case AArch64_ST1Twov16b_POST:
2374 			case AArch64_ST1Twov1d_POST:
2375 			case AArch64_ST1Twov2d_POST:
2376 			case AArch64_ST1Twov2s_POST:
2377 			case AArch64_ST1Twov4h_POST:
2378 			case AArch64_ST1Twov4s_POST:
2379 			case AArch64_ST1Twov8b_POST:
2380 			case AArch64_ST1Twov8h_POST:
2381 			case AArch64_ST1i16_POST:
2382 			case AArch64_ST1i32_POST:
2383 			case AArch64_ST1i64_POST:
2384 			case AArch64_ST1i8_POST:
2385 			case AArch64_ST2Twov16b_POST:
2386 			case AArch64_ST2Twov2d_POST:
2387 			case AArch64_ST2Twov2s_POST:
2388 			case AArch64_ST2Twov4h_POST:
2389 			case AArch64_ST2Twov4s_POST:
2390 			case AArch64_ST2Twov8b_POST:
2391 			case AArch64_ST2Twov8h_POST:
2392 			case AArch64_ST2i16_POST:
2393 			case AArch64_ST2i32_POST:
2394 			case AArch64_ST2i64_POST:
2395 			case AArch64_ST2i8_POST:
2396 			case AArch64_ST3Threev16b_POST:
2397 			case AArch64_ST3Threev2d_POST:
2398 			case AArch64_ST3Threev2s_POST:
2399 			case AArch64_ST3Threev4h_POST:
2400 			case AArch64_ST3Threev4s_POST:
2401 			case AArch64_ST3Threev8b_POST:
2402 			case AArch64_ST3Threev8h_POST:
2403 			case AArch64_ST3i16_POST:
2404 			case AArch64_ST3i32_POST:
2405 			case AArch64_ST3i64_POST:
2406 			case AArch64_ST3i8_POST:
2407 			case AArch64_ST4Fourv16b_POST:
2408 			case AArch64_ST4Fourv2d_POST:
2409 			case AArch64_ST4Fourv2s_POST:
2410 			case AArch64_ST4Fourv4h_POST:
2411 			case AArch64_ST4Fourv4s_POST:
2412 			case AArch64_ST4Fourv8b_POST:
2413 			case AArch64_ST4Fourv8h_POST:
2414 			case AArch64_ST4i16_POST:
2415 			case AArch64_ST4i32_POST:
2416 			case AArch64_ST4i64_POST:
2417 			case AArch64_ST4i8_POST:
2418 			case AArch64_STPDpost:
2419 			case AArch64_STPDpre:
2420 			case AArch64_STPQpost:
2421 			case AArch64_STPQpre:
2422 			case AArch64_STPSpost:
2423 			case AArch64_STPSpre:
2424 			case AArch64_STPWpost:
2425 			case AArch64_STPWpre:
2426 			case AArch64_STPXpost:
2427 			case AArch64_STPXpre:
2428 			case AArch64_STRBBpost:
2429 			case AArch64_STRBBpre:
2430 			case AArch64_STRBpost:
2431 			case AArch64_STRBpre:
2432 			case AArch64_STRDpost:
2433 			case AArch64_STRDpre:
2434 			case AArch64_STRHHpost:
2435 			case AArch64_STRHHpre:
2436 			case AArch64_STRHpost:
2437 			case AArch64_STRHpre:
2438 			case AArch64_STRQpost:
2439 			case AArch64_STRQpre:
2440 			case AArch64_STRSpost:
2441 			case AArch64_STRSpre:
2442 			case AArch64_STRWpost:
2443 			case AArch64_STRWpre:
2444 			case AArch64_STRXpost:
2445 			case AArch64_STRXpre:
2446 				flat_insn->detail->arm64.writeback = true;
2447 				break;
2448 		}
2449 	}
2450 }
2451 
2452 #endif
2453