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 "AArch64BaseInfo.h"
25 #include "../../utils.h"
26 #include "../../MCInst.h"
27 #include "../../SStream.h"
28 #include "../../MCRegisterInfo.h"
29 #include "../../MathExtras.h"
30 
31 #include "AArch64Mapping.h"
32 #include "AArch64AddressingModes.h"
33 
34 #define GET_REGINFO_ENUM
35 #include "AArch64GenRegisterInfo.inc"
36 
37 #define GET_INSTRINFO_ENUM
38 #include "AArch64GenInstrInfo.inc"
39 
40 
41 static const char *getRegisterName(unsigned RegNo, int AltIdx);
42 static void printOperand(MCInst *MI, unsigned OpNo, SStream *O);
43 static bool printSysAlias(MCInst *MI, SStream *O);
44 static char *printAliasInstr(MCInst *MI, SStream *OS, void *info);
45 static void printInstruction(MCInst *MI, SStream *O, MCRegisterInfo *MRI);
46 static void printShifter(MCInst *MI, unsigned OpNum, SStream *O);
47 
get_op_access(cs_struct * h,unsigned int id,unsigned int index)48 static cs_ac_type get_op_access(cs_struct *h, unsigned int id, unsigned int index)
49 {
50 #ifndef CAPSTONE_DIET
51 	uint8_t *arr = AArch64_get_op_access(h, id);
52 
53 	if (arr[index] == CS_AC_IGNORE)
54 		return 0;
55 
56 	return arr[index];
57 #else
58 	return 0;
59 #endif
60 }
61 
set_mem_access(MCInst * MI,bool status)62 static void set_mem_access(MCInst *MI, bool status)
63 {
64 	MI->csh->doing_mem = status;
65 
66 	if (MI->csh->detail != CS_OPT_ON)
67 		return;
68 
69 	if (status) {
70 #ifndef CAPSTONE_DIET
71 		uint8_t access;
72 		access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
73 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
74 		MI->ac_idx++;
75 #endif
76 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_MEM;
77 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].mem.base = ARM64_REG_INVALID;
78 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].mem.index = ARM64_REG_INVALID;
79 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].mem.disp = 0;
80 	} else {
81 		// done, create the next operand slot
82 		MI->flat_insn->detail->arm64.op_count++;
83 	}
84 }
85 
AArch64_printInst(MCInst * MI,SStream * O,void * Info)86 void AArch64_printInst(MCInst *MI, SStream *O, void *Info)
87 {
88 	// Check for special encodings and print the canonical alias instead.
89 	unsigned Opcode = MCInst_getOpcode(MI);
90 	int LSB;
91 	int Width;
92 	char *mnem;
93 
94 	if (Opcode == AArch64_SYSxt && printSysAlias(MI, O))
95 		return;
96 
97 	// SBFM/UBFM should print to a nicer aliased form if possible.
98 	if (Opcode == AArch64_SBFMXri || Opcode == AArch64_SBFMWri ||
99 			Opcode == AArch64_UBFMXri || Opcode == AArch64_UBFMWri) {
100 		MCOperand *Op0 = MCInst_getOperand(MI, 0);
101 		MCOperand *Op1 = MCInst_getOperand(MI, 1);
102 		MCOperand *Op2 = MCInst_getOperand(MI, 2);
103 		MCOperand *Op3 = MCInst_getOperand(MI, 3);
104 
105 		bool IsSigned = (Opcode == AArch64_SBFMXri || Opcode == AArch64_SBFMWri);
106 		bool Is64Bit = (Opcode == AArch64_SBFMXri || Opcode == AArch64_UBFMXri);
107 
108 		if (MCOperand_isImm(Op2) && MCOperand_getImm(Op2) == 0 && MCOperand_isImm(Op3)) {
109 			const char *AsmMnemonic = NULL;
110 
111 			switch (MCOperand_getImm(Op3)) {
112 				default:
113 					break;
114 				case 7:
115 					if (IsSigned)
116 						AsmMnemonic = "sxtb";
117 					else if (!Is64Bit)
118 						AsmMnemonic = "uxtb";
119 					break;
120 				case 15:
121 					if (IsSigned)
122 						AsmMnemonic = "sxth";
123 					else if (!Is64Bit)
124 						AsmMnemonic = "uxth";
125 					break;
126 				case 31:
127 					// *xtw is only valid for signed 64-bit operations.
128 					if (Is64Bit && IsSigned)
129 						AsmMnemonic = "sxtw";
130 					break;
131 			}
132 
133 			if (AsmMnemonic) {
134 				SStream_concat(O, "%s\t%s, %s", AsmMnemonic,
135 						getRegisterName(MCOperand_getReg(Op0), AArch64_NoRegAltName),
136 						getRegisterName(getWRegFromXReg(MCOperand_getReg(Op1)), AArch64_NoRegAltName));
137 
138 				if (MI->csh->detail) {
139 #ifndef CAPSTONE_DIET
140 					uint8_t access;
141 					access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
142 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
143 					MI->ac_idx++;
144 #endif
145 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
146 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op0);
147 					MI->flat_insn->detail->arm64.op_count++;
148 #ifndef CAPSTONE_DIET
149 					access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
150 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
151 					MI->ac_idx++;
152 #endif
153 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
154 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = getWRegFromXReg(MCOperand_getReg(Op1));
155 					MI->flat_insn->detail->arm64.op_count++;
156 				}
157 
158 				MCInst_setOpcodePub(MI, AArch64_map_insn(AsmMnemonic));
159 
160 				return;
161 			}
162 		}
163 
164 		// All immediate shifts are aliases, implemented using the Bitfield
165 		// instruction. In all cases the immediate shift amount shift must be in
166 		// the range 0 to (reg.size -1).
167 		if (MCOperand_isImm(Op2) && MCOperand_isImm(Op3)) {
168 			const char *AsmMnemonic = NULL;
169 			int shift = 0;
170 			int immr = (int)MCOperand_getImm(Op2);
171 			int imms = (int)MCOperand_getImm(Op3);
172 
173 			if (Opcode == AArch64_UBFMWri && imms != 0x1F && ((imms + 1) == immr)) {
174 				AsmMnemonic = "lsl";
175 				shift = 31 - imms;
176 			} else if (Opcode == AArch64_UBFMXri && imms != 0x3f &&
177 					((imms + 1 == immr))) {
178 				AsmMnemonic = "lsl";
179 				shift = 63 - imms;
180 			} else if (Opcode == AArch64_UBFMWri && imms == 0x1f) {
181 				AsmMnemonic = "lsr";
182 				shift = immr;
183 			} else if (Opcode == AArch64_UBFMXri && imms == 0x3f) {
184 				AsmMnemonic = "lsr";
185 				shift = immr;
186 			} else if (Opcode == AArch64_SBFMWri && imms == 0x1f) {
187 				AsmMnemonic = "asr";
188 				shift = immr;
189 			} else if (Opcode == AArch64_SBFMXri && imms == 0x3f) {
190 				AsmMnemonic = "asr";
191 				shift = immr;
192 			}
193 
194 			if (AsmMnemonic) {
195 				SStream_concat(O, "%s\t%s, %s, ", AsmMnemonic,
196 						getRegisterName(MCOperand_getReg(Op0), AArch64_NoRegAltName),
197 						getRegisterName(MCOperand_getReg(Op1), AArch64_NoRegAltName));
198 
199 				printInt32Bang(O, shift);
200 
201 				MCInst_setOpcodePub(MI, AArch64_map_insn(AsmMnemonic));
202 
203 				if (MI->csh->detail) {
204 #ifndef CAPSTONE_DIET
205 					uint8_t access;
206 					access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
207 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
208 					MI->ac_idx++;
209 #endif
210 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
211 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op0);
212 					MI->flat_insn->detail->arm64.op_count++;
213 #ifndef CAPSTONE_DIET
214 					access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
215 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
216 					MI->ac_idx++;
217 #endif
218 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
219 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op1);
220 					MI->flat_insn->detail->arm64.op_count++;
221 #ifndef CAPSTONE_DIET
222 					access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
223 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
224 					MI->ac_idx++;
225 #endif
226 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
227 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = shift;
228 					MI->flat_insn->detail->arm64.op_count++;
229 				}
230 
231 				return;
232 			}
233 		}
234 
235 		// SBFIZ/UBFIZ aliases
236 		if (MCOperand_getImm(Op2) > MCOperand_getImm(Op3)) {
237 			SStream_concat(O, "%s\t%s, %s, ", (IsSigned ? "sbfiz" : "ubfiz"),
238 					getRegisterName(MCOperand_getReg(Op0), AArch64_NoRegAltName),
239 					getRegisterName(MCOperand_getReg(Op1), AArch64_NoRegAltName));
240 			printInt32Bang(O, (int)((Is64Bit ? 64 : 32) - MCOperand_getImm(Op2)));
241 			SStream_concat0(O, ", ");
242 			printInt32Bang(O, (int)MCOperand_getImm(Op3) + 1);
243 
244 			MCInst_setOpcodePub(MI, AArch64_map_insn(IsSigned ? "sbfiz" : "ubfiz"));
245 
246 			if (MI->csh->detail) {
247 #ifndef CAPSTONE_DIET
248 				uint8_t access;
249 				access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
250 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
251 				MI->ac_idx++;
252 #endif
253 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
254 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op0);
255 				MI->flat_insn->detail->arm64.op_count++;
256 #ifndef CAPSTONE_DIET
257 				access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
258 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
259 				MI->ac_idx++;
260 #endif
261 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
262 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op1);
263 				MI->flat_insn->detail->arm64.op_count++;
264 #ifndef CAPSTONE_DIET
265 				access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
266 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
267 				MI->ac_idx++;
268 #endif
269 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
270 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = (Is64Bit ? 64 : 32) - (int)MCOperand_getImm(Op2);
271 				MI->flat_insn->detail->arm64.op_count++;
272 #ifndef CAPSTONE_DIET
273 				access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
274 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
275 				MI->ac_idx++;
276 #endif
277 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
278 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = MCOperand_getImm(Op3) + 1;
279 				MI->flat_insn->detail->arm64.op_count++;
280 			}
281 
282 			return;
283 		}
284 
285 		// Otherwise SBFX/UBFX is the preferred form
286 		SStream_concat(O, "%s\t%s, %s, ", (IsSigned ? "sbfx" : "ubfx"),
287 				getRegisterName(MCOperand_getReg(Op0), AArch64_NoRegAltName),
288 				getRegisterName(MCOperand_getReg(Op1), AArch64_NoRegAltName));
289 		printInt32Bang(O, (int)MCOperand_getImm(Op2));
290 		SStream_concat0(O, ", ");
291 		printInt32Bang(O, (int)MCOperand_getImm(Op3) - (int)MCOperand_getImm(Op2) + 1);
292 
293 		MCInst_setOpcodePub(MI, AArch64_map_insn(IsSigned ? "sbfx" : "ubfx"));
294 
295 		if (MI->csh->detail) {
296 #ifndef CAPSTONE_DIET
297 			uint8_t access;
298 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
299 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
300 			MI->ac_idx++;
301 #endif
302 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
303 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op0);
304 			MI->flat_insn->detail->arm64.op_count++;
305 #ifndef CAPSTONE_DIET
306 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
307 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
308 			MI->ac_idx++;
309 #endif
310 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
311 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op1);
312 			MI->flat_insn->detail->arm64.op_count++;
313 #ifndef CAPSTONE_DIET
314 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
315 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
316 			MI->ac_idx++;
317 #endif
318 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
319 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = MCOperand_getImm(Op2);
320 			MI->flat_insn->detail->arm64.op_count++;
321 #ifndef CAPSTONE_DIET
322 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
323 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
324 			MI->ac_idx++;
325 #endif
326 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
327 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = MCOperand_getImm(Op3) - MCOperand_getImm(Op2) + 1;
328 			MI->flat_insn->detail->arm64.op_count++;
329 		}
330 
331 		return;
332 	}
333 
334 	if (Opcode == AArch64_BFMXri || Opcode == AArch64_BFMWri) {
335 		MCOperand *Op0 = MCInst_getOperand(MI, 0); // Op1 == Op0
336 		MCOperand *Op2 = MCInst_getOperand(MI, 2);
337 		int ImmR = (int)MCOperand_getImm(MCInst_getOperand(MI, 3));
338 		int ImmS = (int)MCOperand_getImm(MCInst_getOperand(MI, 4));
339 
340 		// BFI alias
341 		if (ImmS < ImmR) {
342 			int BitWidth = Opcode == AArch64_BFMXri ? 64 : 32;
343 			LSB = (BitWidth - ImmR) % BitWidth;
344 			Width = ImmS + 1;
345 
346 			SStream_concat(O, "bfi\t%s, %s, ",
347 					getRegisterName(MCOperand_getReg(Op0), AArch64_NoRegAltName),
348 					getRegisterName(MCOperand_getReg(Op2), AArch64_NoRegAltName));
349 			printInt32Bang(O, LSB);
350 			SStream_concat0(O, ", ");
351 			printInt32Bang(O, Width);
352 			MCInst_setOpcodePub(MI, AArch64_map_insn("bfi"));
353 
354 			if (MI->csh->detail) {
355 #ifndef CAPSTONE_DIET
356 				uint8_t access;
357 				access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
358 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
359 				MI->ac_idx++;
360 #endif
361 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
362 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op0);
363 				MI->flat_insn->detail->arm64.op_count++;
364 #ifndef CAPSTONE_DIET
365 				access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
366 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
367 				MI->ac_idx++;
368 #endif
369 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
370 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op2);
371 				MI->flat_insn->detail->arm64.op_count++;
372 #ifndef CAPSTONE_DIET
373 				access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
374 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
375 				MI->ac_idx++;
376 #endif
377 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
378 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = LSB;
379 				MI->flat_insn->detail->arm64.op_count++;
380 #ifndef CAPSTONE_DIET
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_IMM;
386 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = Width;
387 				MI->flat_insn->detail->arm64.op_count++;
388 			}
389 
390 			return;
391 		}
392 
393 		LSB = ImmR;
394 		Width = ImmS - ImmR + 1;
395 		// Otherwise BFXIL the preferred form
396 		SStream_concat(O, "bfxil\t%s, %s, ",
397 				getRegisterName(MCOperand_getReg(Op0), AArch64_NoRegAltName),
398 				getRegisterName(MCOperand_getReg(Op2), AArch64_NoRegAltName));
399 		printInt32Bang(O, LSB);
400 		SStream_concat0(O, ", ");
401 		printInt32Bang(O, Width);
402 		MCInst_setOpcodePub(MI, AArch64_map_insn("bfxil"));
403 
404 		if (MI->csh->detail) {
405 #ifndef CAPSTONE_DIET
406 			uint8_t access;
407 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
408 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
409 			MI->ac_idx++;
410 #endif
411 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
412 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op0);
413 			MI->flat_insn->detail->arm64.op_count++;
414 #ifndef CAPSTONE_DIET
415 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
416 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
417 			MI->ac_idx++;
418 #endif
419 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
420 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op2);
421 			MI->flat_insn->detail->arm64.op_count++;
422 #ifndef CAPSTONE_DIET
423 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
424 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
425 			MI->ac_idx++;
426 #endif
427 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
428 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = LSB;
429 			MI->flat_insn->detail->arm64.op_count++;
430 #ifndef CAPSTONE_DIET
431 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
432 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
433 			MI->ac_idx++;
434 #endif
435 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
436 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = Width;
437 			MI->flat_insn->detail->arm64.op_count++;
438 		}
439 
440 		return;
441 	}
442 
443 	mnem = printAliasInstr(MI, O, Info);
444 	if (mnem) {
445 		MCInst_setOpcodePub(MI, AArch64_map_insn(mnem));
446 		cs_mem_free(mnem);
447 	} else {
448 		printInstruction(MI, O, Info);
449 	}
450 }
451 
printSysAlias(MCInst * MI,SStream * O)452 static bool printSysAlias(MCInst *MI, SStream *O)
453 {
454 	// unsigned Opcode = MCInst_getOpcode(MI);
455 	//assert(Opcode == AArch64_SYSxt && "Invalid opcode for SYS alias!");
456 
457 	const char *Asm = NULL;
458 	MCOperand *Op1 = MCInst_getOperand(MI, 0);
459 	MCOperand *Cn = MCInst_getOperand(MI, 1);
460 	MCOperand *Cm = MCInst_getOperand(MI, 2);
461 	MCOperand *Op2 = MCInst_getOperand(MI, 3);
462 
463 	unsigned Op1Val = (unsigned)MCOperand_getImm(Op1);
464 	unsigned CnVal = (unsigned)MCOperand_getImm(Cn);
465 	unsigned CmVal = (unsigned)MCOperand_getImm(Cm);
466 	unsigned Op2Val = (unsigned)MCOperand_getImm(Op2);
467 	unsigned insn_id = ARM64_INS_INVALID;
468 	unsigned op_ic = 0, op_dc = 0, op_at = 0, op_tlbi = 0;
469 
470 	if (CnVal == 7) {
471 		switch (CmVal) {
472 			default:
473 				break;
474 
475 				// IC aliases
476 			case 1:
477 				if (Op1Val == 0 && Op2Val == 0) {
478 					Asm = "ic\tialluis";
479 					insn_id = ARM64_INS_IC;
480 					op_ic = ARM64_IC_IALLUIS;
481 				}
482 				break;
483 			case 5:
484 				if (Op1Val == 0 && Op2Val == 0) {
485 					Asm = "ic\tiallu";
486 					insn_id = ARM64_INS_IC;
487 					op_ic = ARM64_IC_IALLU;
488 				} else if (Op1Val == 3 && Op2Val == 1) {
489 					Asm = "ic\tivau";
490 					insn_id = ARM64_INS_IC;
491 					op_ic = ARM64_IC_IVAU;
492 				}
493 				break;
494 
495 				// DC aliases
496 			case 4:
497 				if (Op1Val == 3 && Op2Val == 1) {
498 					Asm = "dc\tzva";
499 					insn_id = ARM64_INS_DC;
500 					op_dc = ARM64_DC_ZVA;
501 				}
502 				break;
503 			case 6:
504 				if (Op1Val == 0 && Op2Val == 1) {
505 					Asm = "dc\tivac";
506 					insn_id = ARM64_INS_DC;
507 					op_dc = ARM64_DC_IVAC;
508 				}
509 				if (Op1Val == 0 && Op2Val == 2) {
510 					Asm = "dc\tisw";
511 					insn_id = ARM64_INS_DC;
512 					op_dc = ARM64_DC_ISW;
513 				}
514 				break;
515 			case 10:
516 				if (Op1Val == 3 && Op2Val == 1) {
517 					Asm = "dc\tcvac";
518 					insn_id = ARM64_INS_DC;
519 					op_dc = ARM64_DC_CVAC;
520 				} else if (Op1Val == 0 && Op2Val == 2) {
521 					Asm = "dc\tcsw";
522 					insn_id = ARM64_INS_DC;
523 					op_dc = ARM64_DC_CSW;
524 				}
525 				break;
526 			case 11:
527 				if (Op1Val == 3 && Op2Val == 1) {
528 					Asm = "dc\tcvau";
529 					insn_id = ARM64_INS_DC;
530 					op_dc = ARM64_DC_CVAU;
531 				}
532 				break;
533 			case 14:
534 				if (Op1Val == 3 && Op2Val == 1) {
535 					Asm = "dc\tcivac";
536 					insn_id = ARM64_INS_DC;
537 					op_dc = ARM64_DC_CIVAC;
538 				} else if (Op1Val == 0 && Op2Val == 2) {
539 					Asm = "dc\tcisw";
540 					insn_id = ARM64_INS_DC;
541 					op_dc = ARM64_DC_CISW;
542 				}
543 				break;
544 
545 				// AT aliases
546 			case 8:
547 				switch (Op1Val) {
548 					default:
549 						break;
550 					case 0:
551 						switch (Op2Val) {
552 							default:
553 								break;
554 							case 0: Asm = "at\ts1e1r"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E1R; break;
555 							case 1: Asm = "at\ts1e1w"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E1W; break;
556 							case 2: Asm = "at\ts1e0r"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E0R; break;
557 							case 3: Asm = "at\ts1e0w"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E0W; break;
558 						}
559 						break;
560 					case 4:
561 						switch (Op2Val) {
562 							default:
563 								break;
564 							case 0: Asm = "at\ts1e2r"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E2R; break;
565 							case 1: Asm = "at\ts1e2w"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E2W; break;
566 							case 4: Asm = "at\ts12e1r"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E1R; break;
567 							case 5: Asm = "at\ts12e1w"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E1W; break;
568 							case 6: Asm = "at\ts12e0r"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E0R; break;
569 							case 7: Asm = "at\ts12e0w"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E0W; break;
570 						}
571 						break;
572 					case 6:
573 						switch (Op2Val) {
574 							default:
575 								break;
576 							case 0: Asm = "at\ts1e3r"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E3R; break;
577 							case 1: Asm = "at\ts1e3w"; insn_id = ARM64_INS_AT; op_at = ARM64_AT_S1E3W; break;
578 						}
579 						break;
580 				}
581 				break;
582 		}
583 	} else if (CnVal == 8) {
584 		// TLBI aliases
585 		switch (CmVal) {
586 			default:
587 				break;
588 			case 3:
589 				switch (Op1Val) {
590 					default:
591 						break;
592 					case 0:
593 						switch (Op2Val) {
594 							default:
595 								break;
596 							case 0: Asm = "tlbi\tvmalle1is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VMALLE1IS; break;
597 							case 1: Asm = "tlbi\tvae1is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VAE1IS; break;
598 							case 2: Asm = "tlbi\taside1is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_ASIDE1IS; break;
599 							case 3: Asm = "tlbi\tvaae1is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VAAE1IS; break;
600 							case 5: Asm = "tlbi\tvale1is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VALE1IS; break;
601 							case 7: Asm = "tlbi\tvaale1is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VAALE1IS; break;
602 						}
603 						break;
604 					case 4:
605 						switch (Op2Val) {
606 							default:
607 								break;
608 							case 0: Asm = "tlbi\talle2is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_ALLE2IS; break;
609 							case 1: Asm = "tlbi\tvae2is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VAE2IS; break;
610 							case 4: Asm = "tlbi\talle1is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_ALLE1IS; break;
611 							case 5: Asm = "tlbi\tvale2is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VALE2IS; break;
612 							case 6: Asm = "tlbi\tvmalls12e1is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VMALLS12E1IS; break;
613 						}
614 						break;
615 					case 6:
616 						switch (Op2Val) {
617 							default:
618 								break;
619 							case 0: Asm = "tlbi\talle3is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_ALLE3IS; break;
620 							case 1: Asm = "tlbi\tvae3is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VAE3IS; break;
621 							case 5: Asm = "tlbi\tvale3is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VALE3IS; break;
622 						}
623 						break;
624 				}
625 				break;
626 			case 0:
627 				switch (Op1Val) {
628 					default:
629 						break;
630 					case 4:
631 						switch (Op2Val) {
632 							default:
633 								break;
634 							case 1: Asm = "tlbi\tipas2e1is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_IPAS2E1IS; break;
635 							case 5: Asm = "tlbi\tipas2le1is"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_IPAS2LE1IS; break;
636 						}
637 						break;
638 				}
639 				break;
640 			case 4:
641 				switch (Op1Val) {
642 					default:
643 						break;
644 					case 4:
645 						switch (Op2Val) {
646 							default:
647 								break;
648 							case 1: Asm = "tlbi\tipas2e1"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_IPAS2E1; break;
649 							case 5: Asm = "tlbi\tipas2le1"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_IPAS2LE1; break;
650 						}
651 						break;
652 				}
653 				break;
654 			case 7:
655 				switch (Op1Val) {
656 					default:
657 						break;
658 					case 0:
659 						switch (Op2Val) {
660 							default:
661 								break;
662 							case 0: Asm = "tlbi\tvmalle1"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VMALLE1; break;
663 							case 1: Asm = "tlbi\tvae1"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VAE1; break;
664 							case 2: Asm = "tlbi\taside1"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_ASIDE1; break;
665 							case 3: Asm = "tlbi\tvaae1"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VAAE1; break;
666 							case 5: Asm = "tlbi\tvale1"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VALE1; break;
667 							case 7: Asm = "tlbi\tvaale1"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VAALE1; break;
668 						}
669 						break;
670 					case 4:
671 						switch (Op2Val) {
672 							default:
673 								break;
674 							case 0: Asm = "tlbi\talle2"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_ALLE2; break;
675 							case 1: Asm = "tlbi\tvae2"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VAE2; break;
676 							case 4: Asm = "tlbi\talle1"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_ALLE1; break;
677 							case 5: Asm = "tlbi\tvale2"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VALE2; break;
678 							case 6: Asm = "tlbi\tvmalls12e1"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VMALLS12E1; break;
679 						}
680 						break;
681 					case 6:
682 						switch (Op2Val) {
683 							default:
684 								break;
685 							case 0: Asm = "tlbi\talle3"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_ALLE3; break;
686 							case 1: Asm = "tlbi\tvae3"; insn_id = ARM64_INS_TLBI;  op_tlbi = ARM64_TLBI_VAE3; break;
687 							case 5: Asm = "tlbi\tvale3"; insn_id = ARM64_INS_TLBI; op_tlbi = ARM64_TLBI_VALE3; break;
688 						}
689 						break;
690 				}
691 				break;
692 		}
693 	}
694 
695 	if (Asm) {
696 		MCInst_setOpcodePub(MI, insn_id);
697 		SStream_concat0(O, Asm);
698 		if (MI->csh->detail) {
699 #ifndef CAPSTONE_DIET
700 			uint8_t access;
701 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
702 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
703 			MI->ac_idx++;
704 #endif
705 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_SYS;
706 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].sys = op_ic + op_dc + op_at + op_tlbi;
707 			MI->flat_insn->detail->arm64.op_count++;
708 		}
709 
710 		if (!strstr(Asm, "all")) {
711 			unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, 4));
712 			SStream_concat(O, ", %s", getRegisterName(Reg, AArch64_NoRegAltName));
713 			if (MI->csh->detail) {
714 #ifndef CAPSTONE_DIET
715 				uint8_t access;
716 				access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
717 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
718 				MI->ac_idx++;
719 #endif
720 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
721 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = Reg;
722 				MI->flat_insn->detail->arm64.op_count++;
723 			}
724 		}
725 	}
726 
727 	return Asm != NULL;
728 }
729 
printOperand(MCInst * MI,unsigned OpNo,SStream * O)730 static void printOperand(MCInst *MI, unsigned OpNo, SStream *O)
731 {
732 	MCOperand *Op = MCInst_getOperand(MI, OpNo);
733 
734 	if (MCOperand_isReg(Op)) {
735 		unsigned Reg = MCOperand_getReg(Op);
736 		SStream_concat0(O, getRegisterName(Reg, AArch64_NoRegAltName));
737 		if (MI->csh->detail) {
738 			if (MI->csh->doing_mem) {
739 				if (MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].mem.base == ARM64_REG_INVALID) {
740 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].mem.base = Reg;
741 				}
742 				else if (MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].mem.index == ARM64_REG_INVALID) {
743 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].mem.index = Reg;
744 				}
745 			} else {
746 #ifndef CAPSTONE_DIET
747 				uint8_t access;
748 				access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
749 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
750 				MI->ac_idx++;
751 #endif
752 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
753 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = Reg;
754 				MI->flat_insn->detail->arm64.op_count++;
755 			}
756 		}
757 	} else if (MCOperand_isImm(Op)) {
758 		int64_t imm = MCOperand_getImm(Op);
759 
760 		if (MI->Opcode == AArch64_ADR) {
761 			imm += MI->address;
762 			printUInt64Bang(O, imm);
763 		} else {
764 			if (MI->csh->doing_mem) {
765 				if (MI->csh->imm_unsigned) {
766 					printUInt64Bang(O, imm);
767 				} else {
768 					printInt64Bang(O, imm);
769 				}
770 			} else
771 				printUInt64Bang(O, imm);
772 		}
773 
774 		if (MI->csh->detail) {
775 			if (MI->csh->doing_mem) {
776 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].mem.disp = (int32_t)imm;
777 			} else {
778 #ifndef CAPSTONE_DIET
779 				uint8_t access;
780 				access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
781 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
782 				MI->ac_idx++;
783 #endif
784 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
785 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = imm;
786 				MI->flat_insn->detail->arm64.op_count++;
787 			}
788 		}
789 	}
790 }
791 
printHexImm(MCInst * MI,unsigned OpNo,SStream * O)792 static void printHexImm(MCInst *MI, unsigned OpNo, SStream *O)
793 {
794 	MCOperand *Op = MCInst_getOperand(MI, OpNo);
795 	SStream_concat(O, "#%#llx", MCOperand_getImm(Op));
796 	if (MI->csh->detail) {
797 #ifndef CAPSTONE_DIET
798 		uint8_t access;
799 		access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
800 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
801 		MI->ac_idx++;
802 #endif
803 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
804 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = MCOperand_getImm(Op);
805 		MI->flat_insn->detail->arm64.op_count++;
806 	}
807 }
808 
printPostIncOperand(MCInst * MI,unsigned OpNo,unsigned Imm,SStream * O)809 static void printPostIncOperand(MCInst *MI, unsigned OpNo,
810 		unsigned Imm, SStream *O)
811 {
812 	MCOperand *Op = MCInst_getOperand(MI, OpNo);
813 
814 	if (MCOperand_isReg(Op)) {
815 		unsigned Reg = MCOperand_getReg(Op);
816 		if (Reg == AArch64_XZR) {
817 			printInt32Bang(O, Imm);
818 			if (MI->csh->detail) {
819 #ifndef CAPSTONE_DIET
820 				uint8_t access;
821 				access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
822 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
823 				MI->ac_idx++;
824 #endif
825 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
826 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = Imm;
827 				MI->flat_insn->detail->arm64.op_count++;
828 			}
829 		} else {
830 			SStream_concat0(O, getRegisterName(Reg, AArch64_NoRegAltName));
831 			if (MI->csh->detail) {
832 #ifndef CAPSTONE_DIET
833 				uint8_t access;
834 				access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
835 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
836 				MI->ac_idx++;
837 #endif
838 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
839 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = Reg;
840 				MI->flat_insn->detail->arm64.op_count++;
841 			}
842 		}
843 	}
844 	//llvm_unreachable("unknown operand kind in printPostIncOperand64");
845 }
846 
printPostIncOperand2(MCInst * MI,unsigned OpNo,SStream * O,int Amount)847 static void printPostIncOperand2(MCInst *MI, unsigned OpNo, SStream *O, int Amount)
848 {
849 	printPostIncOperand(MI, OpNo, Amount, O);
850 }
851 
printVRegOperand(MCInst * MI,unsigned OpNo,SStream * O)852 static void printVRegOperand(MCInst *MI, unsigned OpNo, SStream *O)
853 {
854 	MCOperand *Op = MCInst_getOperand(MI, OpNo);
855 	//assert(Op.isReg() && "Non-register vreg operand!");
856 	unsigned Reg = MCOperand_getReg(Op);
857 	SStream_concat0(O, getRegisterName(Reg, AArch64_vreg));
858 	if (MI->csh->detail) {
859 #ifndef CAPSTONE_DIET
860 		uint8_t access;
861 		access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
862 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
863 		MI->ac_idx++;
864 #endif
865 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
866 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = AArch64_map_vregister(Reg);
867 		MI->flat_insn->detail->arm64.op_count++;
868 	}
869 }
870 
printSysCROperand(MCInst * MI,unsigned OpNo,SStream * O)871 static void printSysCROperand(MCInst *MI, unsigned OpNo, SStream *O)
872 {
873 	MCOperand *Op = MCInst_getOperand(MI, OpNo);
874 	//assert(Op.isImm() && "System instruction C[nm] operands must be immediates!");
875 	SStream_concat(O, "c%u", MCOperand_getImm(Op));
876 	if (MI->csh->detail) {
877 #ifndef CAPSTONE_DIET
878 		uint8_t access;
879 		access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
880 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
881 		MI->ac_idx++;
882 #endif
883 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_CIMM;
884 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = MCOperand_getImm(Op);
885 		MI->flat_insn->detail->arm64.op_count++;
886 	}
887 }
888 
printAddSubImm(MCInst * MI,unsigned OpNum,SStream * O)889 static void printAddSubImm(MCInst *MI, unsigned OpNum, SStream *O)
890 {
891 	MCOperand *MO = MCInst_getOperand(MI, OpNum);
892 	if (MCOperand_isImm(MO)) {
893 		unsigned Val = (MCOperand_getImm(MO) & 0xfff);
894 		//assert(Val == MO.getImm() && "Add/sub immediate out of range!");
895 		unsigned Shift = AArch64_AM_getShiftValue((int)MCOperand_getImm(MCInst_getOperand(MI, OpNum + 1)));
896 
897 		printInt32Bang(O, Val);
898 
899 		if (MI->csh->detail) {
900 #ifndef CAPSTONE_DIET
901 			uint8_t access;
902 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
903 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
904 			MI->ac_idx++;
905 #endif
906 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
907 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = Val;
908 			MI->flat_insn->detail->arm64.op_count++;
909 		}
910 
911 		if (Shift != 0)
912 			printShifter(MI, OpNum + 1, O);
913 	}
914 }
915 
printLogicalImm32(MCInst * MI,unsigned OpNum,SStream * O)916 static void printLogicalImm32(MCInst *MI, unsigned OpNum, SStream *O)
917 {
918 	int64_t Val = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
919 
920 	Val = AArch64_AM_decodeLogicalImmediate(Val, 32);
921 	printUInt32Bang(O, (int)Val);
922 
923 	if (MI->csh->detail) {
924 #ifndef CAPSTONE_DIET
925 		uint8_t access;
926 		access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
927 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
928 		MI->ac_idx++;
929 #endif
930 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
931 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = Val;
932 		MI->flat_insn->detail->arm64.op_count++;
933 	}
934 }
935 
printLogicalImm64(MCInst * MI,unsigned OpNum,SStream * O)936 static void printLogicalImm64(MCInst *MI, unsigned OpNum, SStream *O)
937 {
938 	int64_t Val = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
939 	Val = AArch64_AM_decodeLogicalImmediate(Val, 64);
940 
941 	switch(MI->flat_insn->id) {
942 		default:
943 			printInt64Bang(O, Val);
944 			break;
945 		case ARM64_INS_ORR:
946 		case ARM64_INS_AND:
947 		case ARM64_INS_EOR:
948 		case ARM64_INS_TST:
949 			// do not print number in negative form
950 			if (Val >= 0 && Val <= HEX_THRESHOLD)
951 				SStream_concat(O, "#%u", (int)Val);
952 			else
953 				SStream_concat(O, "#0x%"PRIx64, Val);
954 			break;
955 	}
956 
957 	if (MI->csh->detail) {
958 #ifndef CAPSTONE_DIET
959 		uint8_t access;
960 		access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
961 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
962 		MI->ac_idx++;
963 #endif
964 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
965 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = (int64_t)Val;
966 		MI->flat_insn->detail->arm64.op_count++;
967 	}
968 }
969 
printShifter(MCInst * MI,unsigned OpNum,SStream * O)970 static void printShifter(MCInst *MI, unsigned OpNum, SStream *O)
971 {
972 	unsigned Val = (unsigned)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
973 
974 	// LSL #0 should not be printed.
975 	if (AArch64_AM_getShiftType(Val) == AArch64_AM_LSL &&
976 			AArch64_AM_getShiftValue(Val) == 0)
977 		return;
978 
979 	SStream_concat(O, ", %s ", AArch64_AM_getShiftExtendName(AArch64_AM_getShiftType(Val)));
980 	printInt32BangDec(O, AArch64_AM_getShiftValue(Val));
981 	if (MI->csh->detail) {
982 		arm64_shifter shifter = ARM64_SFT_INVALID;
983 		switch(AArch64_AM_getShiftType(Val)) {
984 			default:	// never reach
985 			case AArch64_AM_LSL:
986 				shifter = ARM64_SFT_LSL;
987 				break;
988 			case AArch64_AM_LSR:
989 				shifter = ARM64_SFT_LSR;
990 				break;
991 			case AArch64_AM_ASR:
992 				shifter = ARM64_SFT_ASR;
993 				break;
994 			case AArch64_AM_ROR:
995 				shifter = ARM64_SFT_ROR;
996 				break;
997 			case AArch64_AM_MSL:
998 				shifter = ARM64_SFT_MSL;
999 				break;
1000 		}
1001 
1002 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].shift.type = shifter;
1003 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].shift.value = AArch64_AM_getShiftValue(Val);
1004 	}
1005 }
1006 
printShiftedRegister(MCInst * MI,unsigned OpNum,SStream * O)1007 static void printShiftedRegister(MCInst *MI, unsigned OpNum, SStream *O)
1008 {
1009 	SStream_concat0(O, getRegisterName(MCOperand_getReg(MCInst_getOperand(MI, OpNum)), AArch64_NoRegAltName));
1010 	if (MI->csh->detail) {
1011 #ifndef CAPSTONE_DIET
1012 		uint8_t access;
1013 		access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1014 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1015 		MI->ac_idx++;
1016 #endif
1017 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
1018 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
1019 		MI->flat_insn->detail->arm64.op_count++;
1020 	}
1021 	printShifter(MI, OpNum + 1, O);
1022 }
1023 
printArithExtend(MCInst * MI,unsigned OpNum,SStream * O)1024 static void printArithExtend(MCInst *MI, unsigned OpNum, SStream *O)
1025 {
1026 	unsigned Val = (unsigned)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1027 	AArch64_AM_ShiftExtendType ExtType = AArch64_AM_getArithExtendType(Val);
1028 	unsigned ShiftVal = AArch64_AM_getArithShiftValue(Val);
1029 
1030 	// If the destination or first source register operand is [W]SP, print
1031 	// UXTW/UXTX as LSL, and if the shift amount is also zero, print nothing at
1032 	// all.
1033 	if (ExtType == AArch64_AM_UXTW || ExtType == AArch64_AM_UXTX) {
1034 		unsigned Dest = MCOperand_getReg(MCInst_getOperand(MI, 0));
1035 		unsigned Src1 = MCOperand_getReg(MCInst_getOperand(MI, 1));
1036 		if ( ((Dest == AArch64_SP || Src1 == AArch64_SP) &&
1037 					ExtType == AArch64_AM_UXTX) ||
1038 				((Dest == AArch64_WSP || Src1 == AArch64_WSP) &&
1039 				 ExtType == AArch64_AM_UXTW) ) {
1040 			if (ShiftVal != 0) {
1041 				SStream_concat0(O, ", lsl ");
1042 				printInt32Bang(O, ShiftVal);
1043 				if (MI->csh->detail) {
1044 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].shift.type = ARM64_SFT_LSL;
1045 					MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].shift.value = ShiftVal;
1046 				}
1047 			}
1048 
1049 			return;
1050 		}
1051 	}
1052 
1053 	SStream_concat(O, ", %s", AArch64_AM_getShiftExtendName(ExtType));
1054 	if (MI->csh->detail) {
1055 		arm64_extender ext = ARM64_EXT_INVALID;
1056 		switch(ExtType) {
1057 			default:	// never reach
1058 			case AArch64_AM_UXTB:
1059 				ext = ARM64_EXT_UXTB;
1060 				break;
1061 			case AArch64_AM_UXTH:
1062 				ext = ARM64_EXT_UXTH;
1063 				break;
1064 			case AArch64_AM_UXTW:
1065 				ext = ARM64_EXT_UXTW;
1066 				break;
1067 			case AArch64_AM_UXTX:
1068 				ext = ARM64_EXT_UXTX;
1069 				break;
1070 			case AArch64_AM_SXTB:
1071 				ext = ARM64_EXT_SXTB;
1072 				break;
1073 			case AArch64_AM_SXTH:
1074 				ext = ARM64_EXT_SXTH;
1075 				break;
1076 			case AArch64_AM_SXTW:
1077 				ext = ARM64_EXT_SXTW;
1078 				break;
1079 			case AArch64_AM_SXTX:
1080 				ext = ARM64_EXT_SXTX;
1081 				break;
1082 		}
1083 
1084 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].ext = ext;
1085 	}
1086 
1087 	if (ShiftVal != 0) {
1088 		SStream_concat0(O, " ");
1089 		printInt32Bang(O, ShiftVal);
1090 		if (MI->csh->detail) {
1091 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].shift.type = ARM64_SFT_LSL;
1092 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].shift.value = ShiftVal;
1093 		}
1094 	}
1095 }
1096 
printExtendedRegister(MCInst * MI,unsigned OpNum,SStream * O)1097 static void printExtendedRegister(MCInst *MI, unsigned OpNum, SStream *O)
1098 {
1099 	unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
1100 
1101 	SStream_concat0(O, getRegisterName(Reg, AArch64_NoRegAltName));
1102 	if (MI->csh->detail) {
1103 #ifndef CAPSTONE_DIET
1104 		uint8_t access;
1105 		access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1106 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1107 		MI->ac_idx++;
1108 #endif
1109 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
1110 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = Reg;
1111 		MI->flat_insn->detail->arm64.op_count++;
1112 	}
1113 
1114 	printArithExtend(MI, OpNum + 1, O);
1115 }
1116 
printMemExtend(MCInst * MI,unsigned OpNum,SStream * O,char SrcRegKind,unsigned Width)1117 static void printMemExtend(MCInst *MI, unsigned OpNum, SStream *O, char SrcRegKind, unsigned Width)
1118 {
1119 	unsigned SignExtend = (unsigned)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1120 	unsigned DoShift = (unsigned)MCOperand_getImm(MCInst_getOperand(MI, OpNum + 1));
1121 
1122 	// sxtw, sxtx, uxtw or lsl (== uxtx)
1123 	bool IsLSL = !SignExtend && SrcRegKind == 'x';
1124 	if (IsLSL) {
1125 		SStream_concat0(O, "lsl");
1126 		if (MI->csh->detail) {
1127 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].shift.type = ARM64_SFT_LSL;
1128 		}
1129 	} else {
1130 		SStream_concat(O, "%cxt%c", (SignExtend ? 's' : 'u'), SrcRegKind);
1131 		if (MI->csh->detail) {
1132 			if (!SignExtend) {
1133 				switch(SrcRegKind) {
1134 					default: break;
1135 					case 'b':
1136 							 MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].ext = ARM64_EXT_UXTB;
1137 							 break;
1138 					case 'h':
1139 							 MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].ext = ARM64_EXT_UXTH;
1140 							 break;
1141 					case 'w':
1142 							 MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].ext = ARM64_EXT_UXTW;
1143 							 break;
1144 				}
1145 			} else {
1146 					switch(SrcRegKind) {
1147 						default: break;
1148 						case 'b':
1149 							MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].ext = ARM64_EXT_SXTB;
1150 							break;
1151 						case 'h':
1152 							MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].ext = ARM64_EXT_SXTH;
1153 							break;
1154 						case 'w':
1155 							MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].ext = ARM64_EXT_SXTW;
1156 							break;
1157 						case 'x':
1158 							MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].ext = ARM64_EXT_SXTX;
1159 							break;
1160 					}
1161 			}
1162 		}
1163 	}
1164 
1165 	if (DoShift || IsLSL) {
1166 		SStream_concat(O, " #%u", Log2_32(Width / 8));
1167 		if (MI->csh->detail) {
1168 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].shift.type = ARM64_SFT_LSL;
1169 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].shift.value = Log2_32(Width / 8);
1170 		}
1171 	}
1172 }
1173 
printCondCode(MCInst * MI,unsigned OpNum,SStream * O)1174 static void printCondCode(MCInst *MI, unsigned OpNum, SStream *O)
1175 {
1176 	A64CC_CondCode CC = (A64CC_CondCode)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1177 	SStream_concat0(O, getCondCodeName(CC));
1178 
1179 	if (MI->csh->detail)
1180 		MI->flat_insn->detail->arm64.cc = (arm64_cc)(CC + 1);
1181 }
1182 
printInverseCondCode(MCInst * MI,unsigned OpNum,SStream * O)1183 static void printInverseCondCode(MCInst *MI, unsigned OpNum, SStream *O)
1184 {
1185 	A64CC_CondCode CC = (A64CC_CondCode)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1186 	SStream_concat0(O, getCondCodeName(getInvertedCondCode(CC)));
1187 
1188 	if (MI->csh->detail) {
1189 		MI->flat_insn->detail->arm64.cc = (arm64_cc)(getInvertedCondCode(CC) + 1);
1190 	}
1191 }
1192 
printImmScale(MCInst * MI,unsigned OpNum,SStream * O,int Scale)1193 static void printImmScale(MCInst *MI, unsigned OpNum, SStream *O, int Scale)
1194 {
1195 	int64_t val = Scale * MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1196 
1197 	printInt64Bang(O, val);
1198 
1199 	if (MI->csh->detail) {
1200 		if (MI->csh->doing_mem) {
1201 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].mem.disp = (int32_t)val;
1202 		} else {
1203 #ifndef CAPSTONE_DIET
1204 			uint8_t access;
1205 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1206 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1207 			MI->ac_idx++;
1208 #endif
1209 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
1210 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = val;
1211 			MI->flat_insn->detail->arm64.op_count++;
1212 		}
1213 	}
1214 }
1215 
printUImm12Offset(MCInst * MI,unsigned OpNum,unsigned Scale,SStream * O)1216 static void printUImm12Offset(MCInst *MI, unsigned OpNum, unsigned Scale, SStream *O)
1217 {
1218 	MCOperand *MO = MCInst_getOperand(MI, OpNum);
1219 
1220 	if (MCOperand_isImm(MO)) {
1221 		int64_t val = Scale * MCOperand_getImm(MO);
1222 		printInt64Bang(O, val);
1223 		if (MI->csh->detail) {
1224 			if (MI->csh->doing_mem) {
1225 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].mem.disp = (int32_t)val;
1226 			} else {
1227 #ifndef CAPSTONE_DIET
1228 				uint8_t access;
1229 				access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1230 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1231 				MI->ac_idx++;
1232 #endif
1233 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
1234 				MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = (int)val;
1235 				MI->flat_insn->detail->arm64.op_count++;
1236 			}
1237 		}
1238 	}
1239 }
1240 
printUImm12Offset2(MCInst * MI,unsigned OpNum,SStream * O,int Scale)1241 static void printUImm12Offset2(MCInst *MI, unsigned OpNum, SStream *O, int Scale)
1242 {
1243 	printUImm12Offset(MI, OpNum, Scale, O);
1244 }
1245 
printPrefetchOp(MCInst * MI,unsigned OpNum,SStream * O)1246 static void printPrefetchOp(MCInst *MI, unsigned OpNum, SStream *O)
1247 {
1248 	unsigned prfop = (unsigned)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1249 	bool Valid;
1250 	const char *Name = A64NamedImmMapper_toString(&A64PRFM_PRFMMapper, prfop, &Valid);
1251 
1252 	if (Valid) {
1253 		SStream_concat0(O, Name);
1254 		if (MI->csh->detail) {
1255 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_PREFETCH;
1256 			// we have to plus 1 to prfop because 0 is a valid value of prfop
1257 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].prefetch = prfop + 1;
1258 			MI->flat_insn->detail->arm64.op_count++;
1259 		}
1260 	} else {
1261 		printInt32Bang(O, prfop);
1262 		if (MI->csh->detail) {
1263 #ifndef CAPSTONE_DIET
1264 			uint8_t access;
1265 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1266 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1267 			MI->ac_idx++;
1268 #endif
1269 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
1270 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = prfop;
1271 			MI->flat_insn->detail->arm64.op_count++;
1272 		}
1273 	}
1274 }
1275 
printFPImmOperand(MCInst * MI,unsigned OpNum,SStream * O)1276 static void printFPImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
1277 {
1278 	MCOperand *MO = MCInst_getOperand(MI, OpNum);
1279 	double FPImm = MCOperand_isFPImm(MO) ? MCOperand_getFPImm(MO) : AArch64_AM_getFPImmFloat((int)MCOperand_getImm(MO));
1280 
1281 	// 8 decimal places are enough to perfectly represent permitted floats.
1282 #if defined(_KERNEL_MODE)
1283 	// Issue #681: Windows kernel does not support formatting float point
1284 	SStream_concat(O, "#<float_point_unsupported>");
1285 #else
1286 	SStream_concat(O, "#%.8f", FPImm);
1287 #endif
1288 	if (MI->csh->detail) {
1289 #ifndef CAPSTONE_DIET
1290 		uint8_t access;
1291 		access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1292 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1293 		MI->ac_idx++;
1294 #endif
1295 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_FP;
1296 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].fp = FPImm;
1297 		MI->flat_insn->detail->arm64.op_count++;
1298 	}
1299 }
1300 
1301 //static unsigned getNextVectorRegister(unsigned Reg, unsigned Stride = 1)
getNextVectorRegister(unsigned Reg,unsigned Stride)1302 static unsigned getNextVectorRegister(unsigned Reg, unsigned Stride)
1303 {
1304 	while (Stride--) {
1305 		switch (Reg) {
1306 			default:
1307 				// llvm_unreachable("Vector register expected!");
1308 			case AArch64_Q0:  Reg = AArch64_Q1;  break;
1309 			case AArch64_Q1:  Reg = AArch64_Q2;  break;
1310 			case AArch64_Q2:  Reg = AArch64_Q3;  break;
1311 			case AArch64_Q3:  Reg = AArch64_Q4;  break;
1312 			case AArch64_Q4:  Reg = AArch64_Q5;  break;
1313 			case AArch64_Q5:  Reg = AArch64_Q6;  break;
1314 			case AArch64_Q6:  Reg = AArch64_Q7;  break;
1315 			case AArch64_Q7:  Reg = AArch64_Q8;  break;
1316 			case AArch64_Q8:  Reg = AArch64_Q9;  break;
1317 			case AArch64_Q9:  Reg = AArch64_Q10; break;
1318 			case AArch64_Q10: Reg = AArch64_Q11; break;
1319 			case AArch64_Q11: Reg = AArch64_Q12; break;
1320 			case AArch64_Q12: Reg = AArch64_Q13; break;
1321 			case AArch64_Q13: Reg = AArch64_Q14; break;
1322 			case AArch64_Q14: Reg = AArch64_Q15; break;
1323 			case AArch64_Q15: Reg = AArch64_Q16; break;
1324 			case AArch64_Q16: Reg = AArch64_Q17; break;
1325 			case AArch64_Q17: Reg = AArch64_Q18; break;
1326 			case AArch64_Q18: Reg = AArch64_Q19; break;
1327 			case AArch64_Q19: Reg = AArch64_Q20; break;
1328 			case AArch64_Q20: Reg = AArch64_Q21; break;
1329 			case AArch64_Q21: Reg = AArch64_Q22; break;
1330 			case AArch64_Q22: Reg = AArch64_Q23; break;
1331 			case AArch64_Q23: Reg = AArch64_Q24; break;
1332 			case AArch64_Q24: Reg = AArch64_Q25; break;
1333 			case AArch64_Q25: Reg = AArch64_Q26; break;
1334 			case AArch64_Q26: Reg = AArch64_Q27; break;
1335 			case AArch64_Q27: Reg = AArch64_Q28; break;
1336 			case AArch64_Q28: Reg = AArch64_Q29; break;
1337 			case AArch64_Q29: Reg = AArch64_Q30; break;
1338 			case AArch64_Q30: Reg = AArch64_Q31; break;
1339 							   // Vector lists can wrap around.
1340 			case AArch64_Q31: Reg = AArch64_Q0; break;
1341 		}
1342 	}
1343 
1344 	return Reg;
1345 }
1346 
printVectorList(MCInst * MI,unsigned OpNum,SStream * O,char * LayoutSuffix,MCRegisterInfo * MRI,arm64_vas vas,arm64_vess vess)1347 static void printVectorList(MCInst *MI, unsigned OpNum, SStream *O, char *LayoutSuffix, MCRegisterInfo *MRI, arm64_vas vas, arm64_vess vess)
1348 {
1349 #define GETREGCLASS_CONTAIN0(_class, _reg) MCRegisterClass_contains(MCRegisterInfo_getRegClass(MRI, _class), _reg)
1350 
1351 	unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
1352 	unsigned NumRegs = 1, FirstReg, i;
1353 
1354 	SStream_concat0(O, "{");
1355 
1356 	// Work out how many registers there are in the list (if there is an actual
1357 	// list).
1358 	if (GETREGCLASS_CONTAIN0(AArch64_DDRegClassID , Reg) ||
1359 			GETREGCLASS_CONTAIN0(AArch64_QQRegClassID, Reg))
1360 		NumRegs = 2;
1361 	else if (GETREGCLASS_CONTAIN0(AArch64_DDDRegClassID, Reg) ||
1362 			GETREGCLASS_CONTAIN0(AArch64_QQQRegClassID, Reg))
1363 		NumRegs = 3;
1364 	else if (GETREGCLASS_CONTAIN0(AArch64_DDDDRegClassID, Reg) ||
1365 			GETREGCLASS_CONTAIN0(AArch64_QQQQRegClassID, Reg))
1366 		NumRegs = 4;
1367 
1368 	// Now forget about the list and find out what the first register is.
1369 	if ((FirstReg = MCRegisterInfo_getSubReg(MRI, Reg, AArch64_dsub0)))
1370 		Reg = FirstReg;
1371 	else if ((FirstReg = MCRegisterInfo_getSubReg(MRI, Reg, AArch64_qsub0)))
1372 		Reg = FirstReg;
1373 
1374 	// If it's a D-reg, we need to promote it to the equivalent Q-reg before
1375 	// printing (otherwise getRegisterName fails).
1376 	if (GETREGCLASS_CONTAIN0(AArch64_FPR64RegClassID, Reg)) {
1377 		const MCRegisterClass *FPR128RC = MCRegisterInfo_getRegClass(MRI, AArch64_FPR128RegClassID);
1378 		Reg = MCRegisterInfo_getMatchingSuperReg(MRI, Reg, AArch64_dsub, FPR128RC);
1379 	}
1380 
1381 	for (i = 0; i < NumRegs; ++i, Reg = getNextVectorRegister(Reg, 1)) {
1382 		SStream_concat(O, "%s%s", getRegisterName(Reg, AArch64_vreg), LayoutSuffix);
1383 		if (i + 1 != NumRegs)
1384 			SStream_concat0(O, ", ");
1385 		if (MI->csh->detail) {
1386 #ifndef CAPSTONE_DIET
1387 			uint8_t access;
1388 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1389 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1390 			MI->ac_idx++;
1391 #endif
1392 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
1393 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = AArch64_map_vregister(Reg);
1394 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].vas = vas;
1395 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].vess = vess;
1396 			MI->flat_insn->detail->arm64.op_count++;
1397 		}
1398 	}
1399 
1400 	SStream_concat0(O, "}");
1401 }
1402 
printTypedVectorList(MCInst * MI,unsigned OpNum,SStream * O,unsigned NumLanes,char LaneKind,MCRegisterInfo * MRI)1403 static void printTypedVectorList(MCInst *MI, unsigned OpNum, SStream *O, unsigned NumLanes, char LaneKind, MCRegisterInfo *MRI)
1404 {
1405 	char Suffix[32];
1406 	arm64_vas vas = 0;
1407 	arm64_vess vess = 0;
1408 
1409 	if (NumLanes) {
1410 		cs_snprintf(Suffix, sizeof(Suffix), ".%u%c", NumLanes, LaneKind);
1411 		switch(LaneKind) {
1412 			default: break;
1413 			case 'b':
1414 				switch(NumLanes) {
1415 					default: break;
1416 					case 8:
1417 							 vas = ARM64_VAS_8B;
1418 							 break;
1419 					case 16:
1420 							 vas = ARM64_VAS_16B;
1421 							 break;
1422 				}
1423 				break;
1424 			case 'h':
1425 				switch(NumLanes) {
1426 					default: break;
1427 					case 4:
1428 							 vas = ARM64_VAS_4H;
1429 							 break;
1430 					case 8:
1431 							 vas = ARM64_VAS_8H;
1432 							 break;
1433 				}
1434 				break;
1435 			case 's':
1436 				switch(NumLanes) {
1437 					default: break;
1438 					case 2:
1439 							 vas = ARM64_VAS_2S;
1440 							 break;
1441 					case 4:
1442 							 vas = ARM64_VAS_4S;
1443 							 break;
1444 				}
1445 				break;
1446 			case 'd':
1447 				switch(NumLanes) {
1448 					default: break;
1449 					case 1:
1450 							 vas = ARM64_VAS_1D;
1451 							 break;
1452 					case 2:
1453 							 vas = ARM64_VAS_2D;
1454 							 break;
1455 				}
1456 				break;
1457 			case 'q':
1458 				switch(NumLanes) {
1459 					default: break;
1460 					case 1:
1461 							 vas = ARM64_VAS_1Q;
1462 							 break;
1463 				}
1464 				break;
1465 		}
1466 	} else {
1467 		cs_snprintf(Suffix, sizeof(Suffix), ".%c", LaneKind);
1468 		switch(LaneKind) {
1469 			default: break;
1470 			case 'b':
1471 					 vess = ARM64_VESS_B;
1472 					 break;
1473 			case 'h':
1474 					 vess = ARM64_VESS_H;
1475 					 break;
1476 			case 's':
1477 					 vess = ARM64_VESS_S;
1478 					 break;
1479 			case 'd':
1480 					 vess = ARM64_VESS_D;
1481 					 break;
1482 		}
1483 	}
1484 
1485 	printVectorList(MI, OpNum, O, Suffix, MRI, vas, vess);
1486 }
1487 
printVectorIndex(MCInst * MI,unsigned OpNum,SStream * O)1488 static void printVectorIndex(MCInst *MI, unsigned OpNum, SStream *O)
1489 {
1490 	SStream_concat0(O, "[");
1491 	printInt32(O, (int)MCOperand_getImm(MCInst_getOperand(MI, OpNum)));
1492 	SStream_concat0(O, "]");
1493 	if (MI->csh->detail) {
1494 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].vector_index = (int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1495 	}
1496 }
1497 
printAlignedLabel(MCInst * MI,unsigned OpNum,SStream * O)1498 static void printAlignedLabel(MCInst *MI, unsigned OpNum, SStream *O)
1499 {
1500 	MCOperand *Op = MCInst_getOperand(MI, OpNum);
1501 
1502 	// If the label has already been resolved to an immediate offset (say, when
1503 	// we're running the disassembler), just print the immediate.
1504 	if (MCOperand_isImm(Op)) {
1505 		uint64_t imm = (MCOperand_getImm(Op) * 4) + MI->address;
1506 		printUInt64Bang(O, imm);
1507 		if (MI->csh->detail) {
1508 #ifndef CAPSTONE_DIET
1509 			uint8_t access;
1510 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1511 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1512 			MI->ac_idx++;
1513 #endif
1514 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
1515 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = imm;
1516 			MI->flat_insn->detail->arm64.op_count++;
1517 		}
1518 		return;
1519 	}
1520 }
1521 
printAdrpLabel(MCInst * MI,unsigned OpNum,SStream * O)1522 static void printAdrpLabel(MCInst *MI, unsigned OpNum, SStream *O)
1523 {
1524 	MCOperand *Op = MCInst_getOperand(MI, OpNum);
1525 
1526 	if (MCOperand_isImm(Op)) {
1527 		// ADRP sign extends a 21-bit offset, shifts it left by 12
1528 		// and adds it to the value of the PC with its bottom 12 bits cleared
1529 		uint64_t imm = (MCOperand_getImm(Op) * 0x1000) + (MI->address & ~0xfff);
1530 		printUInt64Bang(O, imm);
1531 
1532 		if (MI->csh->detail) {
1533 #ifndef CAPSTONE_DIET
1534 			uint8_t access;
1535 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1536 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1537 			MI->ac_idx++;
1538 #endif
1539 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
1540 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = imm;
1541 			MI->flat_insn->detail->arm64.op_count++;
1542 		}
1543 		return;
1544 	}
1545 }
1546 
printBarrierOption(MCInst * MI,unsigned OpNo,SStream * O)1547 static void printBarrierOption(MCInst *MI, unsigned OpNo, SStream *O)
1548 {
1549 	unsigned Val = (unsigned)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
1550 	unsigned Opcode = MCInst_getOpcode(MI);
1551 	bool Valid;
1552 	const char *Name;
1553 
1554 	if (Opcode == AArch64_ISB)
1555 		Name = A64NamedImmMapper_toString(&A64ISB_ISBMapper, Val, &Valid);
1556 	else
1557 		Name = A64NamedImmMapper_toString(&A64DB_DBarrierMapper, Val, &Valid);
1558 
1559 	if (Valid) {
1560 		SStream_concat0(O, Name);
1561 		if (MI->csh->detail) {
1562 #ifndef CAPSTONE_DIET
1563 			uint8_t access;
1564 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1565 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1566 			MI->ac_idx++;
1567 #endif
1568 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_BARRIER;
1569 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].barrier = Val;
1570 			MI->flat_insn->detail->arm64.op_count++;
1571 		}
1572 	} else {
1573 		printUInt32Bang(O, Val);
1574 		if (MI->csh->detail) {
1575 #ifndef CAPSTONE_DIET
1576 			uint8_t access;
1577 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1578 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1579 			MI->ac_idx++;
1580 #endif
1581 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
1582 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = Val;
1583 			MI->flat_insn->detail->arm64.op_count++;
1584 		}
1585 	}
1586 }
1587 
printMRSSystemRegister(MCInst * MI,unsigned OpNo,SStream * O)1588 static void printMRSSystemRegister(MCInst *MI, unsigned OpNo, SStream *O)
1589 {
1590 	unsigned Val = (unsigned)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
1591 	char Name[128];
1592 
1593 	A64SysRegMapper_toString(&AArch64_MRSMapper, Val, Name);
1594 
1595 	SStream_concat0(O, Name);
1596 	if (MI->csh->detail) {
1597 #ifndef CAPSTONE_DIET
1598 		uint8_t access;
1599 		access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1600 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1601 		MI->ac_idx++;
1602 #endif
1603 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG_MRS;
1604 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = Val;
1605 		MI->flat_insn->detail->arm64.op_count++;
1606 	}
1607 }
1608 
printMSRSystemRegister(MCInst * MI,unsigned OpNo,SStream * O)1609 static void printMSRSystemRegister(MCInst *MI, unsigned OpNo, SStream *O)
1610 {
1611 	unsigned Val = (unsigned)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
1612 	char Name[128];
1613 
1614 	A64SysRegMapper_toString(&AArch64_MSRMapper, Val, Name);
1615 
1616 	SStream_concat0(O, Name);
1617 	if (MI->csh->detail) {
1618 #ifndef CAPSTONE_DIET
1619 		uint8_t access;
1620 		access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1621 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1622 		MI->ac_idx++;
1623 #endif
1624 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG_MSR;
1625 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = Val;
1626 		MI->flat_insn->detail->arm64.op_count++;
1627 	}
1628 }
1629 
printSystemPStateField(MCInst * MI,unsigned OpNo,SStream * O)1630 static void printSystemPStateField(MCInst *MI, unsigned OpNo, SStream *O)
1631 {
1632 	unsigned Val = (unsigned)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
1633 	bool Valid;
1634 	const char *Name;
1635 
1636 	Name = A64NamedImmMapper_toString(&A64PState_PStateMapper, Val, &Valid);
1637 	if (Valid) {
1638 		SStream_concat0(O, Name);
1639 		if (MI->csh->detail) {
1640 #ifndef CAPSTONE_DIET
1641 			uint8_t access;
1642 			access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1643 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1644 			MI->ac_idx++;
1645 #endif
1646 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_PSTATE;
1647 			MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].pstate = Val;
1648 			MI->flat_insn->detail->arm64.op_count++;
1649 		}
1650 	} else {
1651 #ifndef CAPSTONE_DIET
1652 		unsigned char access;
1653 #endif
1654 		printInt32Bang(O, Val);
1655 #ifndef CAPSTONE_DIET
1656 		access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1657 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1658 		MI->ac_idx++;
1659 #endif
1660 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
1661 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = Val;
1662 		MI->flat_insn->detail->arm64.op_count++;
1663 	}
1664 }
1665 
printSIMDType10Operand(MCInst * MI,unsigned OpNo,SStream * O)1666 static void printSIMDType10Operand(MCInst *MI, unsigned OpNo, SStream *O)
1667 {
1668 	uint8_t RawVal = (uint8_t)MCOperand_getImm(MCInst_getOperand(MI, OpNo));
1669 	uint64_t Val = AArch64_AM_decodeAdvSIMDModImmType10(RawVal);
1670 	SStream_concat(O, "#%#016llx", Val);
1671 	if (MI->csh->detail) {
1672 #ifndef CAPSTONE_DIET
1673 		unsigned char access;
1674 		access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1675 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1676 		MI->ac_idx++;
1677 #endif
1678 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
1679 		MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = Val;
1680 		MI->flat_insn->detail->arm64.op_count++;
1681 	}
1682 }
1683 
1684 
1685 #define PRINT_ALIAS_INSTR
1686 #include "AArch64GenAsmWriter.inc"
1687 
AArch64_post_printer(csh handle,cs_insn * flat_insn,char * insn_asm,MCInst * mci)1688 void AArch64_post_printer(csh handle, cs_insn *flat_insn, char *insn_asm, MCInst *mci)
1689 {
1690 	if (((cs_struct *)handle)->detail != CS_OPT_ON)
1691 		return;
1692 
1693 	if (mci->csh->detail) {
1694 		unsigned opcode = MCInst_getOpcode(mci);
1695 		switch (opcode) {
1696 			default:
1697 				break;
1698 			case AArch64_LD1Fourv16b_POST:
1699 			case AArch64_LD1Fourv1d_POST:
1700 			case AArch64_LD1Fourv2d_POST:
1701 			case AArch64_LD1Fourv2s_POST:
1702 			case AArch64_LD1Fourv4h_POST:
1703 			case AArch64_LD1Fourv4s_POST:
1704 			case AArch64_LD1Fourv8b_POST:
1705 			case AArch64_LD1Fourv8h_POST:
1706 			case AArch64_LD1Onev16b_POST:
1707 			case AArch64_LD1Onev1d_POST:
1708 			case AArch64_LD1Onev2d_POST:
1709 			case AArch64_LD1Onev2s_POST:
1710 			case AArch64_LD1Onev4h_POST:
1711 			case AArch64_LD1Onev4s_POST:
1712 			case AArch64_LD1Onev8b_POST:
1713 			case AArch64_LD1Onev8h_POST:
1714 			case AArch64_LD1Rv16b_POST:
1715 			case AArch64_LD1Rv1d_POST:
1716 			case AArch64_LD1Rv2d_POST:
1717 			case AArch64_LD1Rv2s_POST:
1718 			case AArch64_LD1Rv4h_POST:
1719 			case AArch64_LD1Rv4s_POST:
1720 			case AArch64_LD1Rv8b_POST:
1721 			case AArch64_LD1Rv8h_POST:
1722 			case AArch64_LD1Threev16b_POST:
1723 			case AArch64_LD1Threev1d_POST:
1724 			case AArch64_LD1Threev2d_POST:
1725 			case AArch64_LD1Threev2s_POST:
1726 			case AArch64_LD1Threev4h_POST:
1727 			case AArch64_LD1Threev4s_POST:
1728 			case AArch64_LD1Threev8b_POST:
1729 			case AArch64_LD1Threev8h_POST:
1730 			case AArch64_LD1Twov16b_POST:
1731 			case AArch64_LD1Twov1d_POST:
1732 			case AArch64_LD1Twov2d_POST:
1733 			case AArch64_LD1Twov2s_POST:
1734 			case AArch64_LD1Twov4h_POST:
1735 			case AArch64_LD1Twov4s_POST:
1736 			case AArch64_LD1Twov8b_POST:
1737 			case AArch64_LD1Twov8h_POST:
1738 			case AArch64_LD1i16_POST:
1739 			case AArch64_LD1i32_POST:
1740 			case AArch64_LD1i64_POST:
1741 			case AArch64_LD1i8_POST:
1742 			case AArch64_LD2Rv16b_POST:
1743 			case AArch64_LD2Rv1d_POST:
1744 			case AArch64_LD2Rv2d_POST:
1745 			case AArch64_LD2Rv2s_POST:
1746 			case AArch64_LD2Rv4h_POST:
1747 			case AArch64_LD2Rv4s_POST:
1748 			case AArch64_LD2Rv8b_POST:
1749 			case AArch64_LD2Rv8h_POST:
1750 			case AArch64_LD2Twov16b_POST:
1751 			case AArch64_LD2Twov2d_POST:
1752 			case AArch64_LD2Twov2s_POST:
1753 			case AArch64_LD2Twov4h_POST:
1754 			case AArch64_LD2Twov4s_POST:
1755 			case AArch64_LD2Twov8b_POST:
1756 			case AArch64_LD2Twov8h_POST:
1757 			case AArch64_LD2i16_POST:
1758 			case AArch64_LD2i32_POST:
1759 			case AArch64_LD2i64_POST:
1760 			case AArch64_LD2i8_POST:
1761 			case AArch64_LD3Rv16b_POST:
1762 			case AArch64_LD3Rv1d_POST:
1763 			case AArch64_LD3Rv2d_POST:
1764 			case AArch64_LD3Rv2s_POST:
1765 			case AArch64_LD3Rv4h_POST:
1766 			case AArch64_LD3Rv4s_POST:
1767 			case AArch64_LD3Rv8b_POST:
1768 			case AArch64_LD3Rv8h_POST:
1769 			case AArch64_LD3Threev16b_POST:
1770 			case AArch64_LD3Threev2d_POST:
1771 			case AArch64_LD3Threev2s_POST:
1772 			case AArch64_LD3Threev4h_POST:
1773 			case AArch64_LD3Threev4s_POST:
1774 			case AArch64_LD3Threev8b_POST:
1775 			case AArch64_LD3Threev8h_POST:
1776 			case AArch64_LD3i16_POST:
1777 			case AArch64_LD3i32_POST:
1778 			case AArch64_LD3i64_POST:
1779 			case AArch64_LD3i8_POST:
1780 			case AArch64_LD4Fourv16b_POST:
1781 			case AArch64_LD4Fourv2d_POST:
1782 			case AArch64_LD4Fourv2s_POST:
1783 			case AArch64_LD4Fourv4h_POST:
1784 			case AArch64_LD4Fourv4s_POST:
1785 			case AArch64_LD4Fourv8b_POST:
1786 			case AArch64_LD4Fourv8h_POST:
1787 			case AArch64_LD4Rv16b_POST:
1788 			case AArch64_LD4Rv1d_POST:
1789 			case AArch64_LD4Rv2d_POST:
1790 			case AArch64_LD4Rv2s_POST:
1791 			case AArch64_LD4Rv4h_POST:
1792 			case AArch64_LD4Rv4s_POST:
1793 			case AArch64_LD4Rv8b_POST:
1794 			case AArch64_LD4Rv8h_POST:
1795 			case AArch64_LD4i16_POST:
1796 			case AArch64_LD4i32_POST:
1797 			case AArch64_LD4i64_POST:
1798 			case AArch64_LD4i8_POST:
1799 			case AArch64_LDPDpost:
1800 			case AArch64_LDPDpre:
1801 			case AArch64_LDPQpost:
1802 			case AArch64_LDPQpre:
1803 			case AArch64_LDPSWpost:
1804 			case AArch64_LDPSWpre:
1805 			case AArch64_LDPSpost:
1806 			case AArch64_LDPSpre:
1807 			case AArch64_LDPWpost:
1808 			case AArch64_LDPWpre:
1809 			case AArch64_LDPXpost:
1810 			case AArch64_LDPXpre:
1811 			case AArch64_LDRBBpost:
1812 			case AArch64_LDRBBpre:
1813 			case AArch64_LDRBpost:
1814 			case AArch64_LDRBpre:
1815 			case AArch64_LDRDpost:
1816 			case AArch64_LDRDpre:
1817 			case AArch64_LDRHHpost:
1818 			case AArch64_LDRHHpre:
1819 			case AArch64_LDRHpost:
1820 			case AArch64_LDRHpre:
1821 			case AArch64_LDRQpost:
1822 			case AArch64_LDRQpre:
1823 			case AArch64_LDRSBWpost:
1824 			case AArch64_LDRSBWpre:
1825 			case AArch64_LDRSBXpost:
1826 			case AArch64_LDRSBXpre:
1827 			case AArch64_LDRSHWpost:
1828 			case AArch64_LDRSHWpre:
1829 			case AArch64_LDRSHXpost:
1830 			case AArch64_LDRSHXpre:
1831 			case AArch64_LDRSWpost:
1832 			case AArch64_LDRSWpre:
1833 			case AArch64_LDRSpost:
1834 			case AArch64_LDRSpre:
1835 			case AArch64_LDRWpost:
1836 			case AArch64_LDRWpre:
1837 			case AArch64_LDRXpost:
1838 			case AArch64_LDRXpre:
1839 			case AArch64_ST1Fourv16b_POST:
1840 			case AArch64_ST1Fourv1d_POST:
1841 			case AArch64_ST1Fourv2d_POST:
1842 			case AArch64_ST1Fourv2s_POST:
1843 			case AArch64_ST1Fourv4h_POST:
1844 			case AArch64_ST1Fourv4s_POST:
1845 			case AArch64_ST1Fourv8b_POST:
1846 			case AArch64_ST1Fourv8h_POST:
1847 			case AArch64_ST1Onev16b_POST:
1848 			case AArch64_ST1Onev1d_POST:
1849 			case AArch64_ST1Onev2d_POST:
1850 			case AArch64_ST1Onev2s_POST:
1851 			case AArch64_ST1Onev4h_POST:
1852 			case AArch64_ST1Onev4s_POST:
1853 			case AArch64_ST1Onev8b_POST:
1854 			case AArch64_ST1Onev8h_POST:
1855 			case AArch64_ST1Threev16b_POST:
1856 			case AArch64_ST1Threev1d_POST:
1857 			case AArch64_ST1Threev2d_POST:
1858 			case AArch64_ST1Threev2s_POST:
1859 			case AArch64_ST1Threev4h_POST:
1860 			case AArch64_ST1Threev4s_POST:
1861 			case AArch64_ST1Threev8b_POST:
1862 			case AArch64_ST1Threev8h_POST:
1863 			case AArch64_ST1Twov16b_POST:
1864 			case AArch64_ST1Twov1d_POST:
1865 			case AArch64_ST1Twov2d_POST:
1866 			case AArch64_ST1Twov2s_POST:
1867 			case AArch64_ST1Twov4h_POST:
1868 			case AArch64_ST1Twov4s_POST:
1869 			case AArch64_ST1Twov8b_POST:
1870 			case AArch64_ST1Twov8h_POST:
1871 			case AArch64_ST1i16_POST:
1872 			case AArch64_ST1i32_POST:
1873 			case AArch64_ST1i64_POST:
1874 			case AArch64_ST1i8_POST:
1875 			case AArch64_ST2Twov16b_POST:
1876 			case AArch64_ST2Twov2d_POST:
1877 			case AArch64_ST2Twov2s_POST:
1878 			case AArch64_ST2Twov4h_POST:
1879 			case AArch64_ST2Twov4s_POST:
1880 			case AArch64_ST2Twov8b_POST:
1881 			case AArch64_ST2Twov8h_POST:
1882 			case AArch64_ST2i16_POST:
1883 			case AArch64_ST2i32_POST:
1884 			case AArch64_ST2i64_POST:
1885 			case AArch64_ST2i8_POST:
1886 			case AArch64_ST3Threev16b_POST:
1887 			case AArch64_ST3Threev2d_POST:
1888 			case AArch64_ST3Threev2s_POST:
1889 			case AArch64_ST3Threev4h_POST:
1890 			case AArch64_ST3Threev4s_POST:
1891 			case AArch64_ST3Threev8b_POST:
1892 			case AArch64_ST3Threev8h_POST:
1893 			case AArch64_ST3i16_POST:
1894 			case AArch64_ST3i32_POST:
1895 			case AArch64_ST3i64_POST:
1896 			case AArch64_ST3i8_POST:
1897 			case AArch64_ST4Fourv16b_POST:
1898 			case AArch64_ST4Fourv2d_POST:
1899 			case AArch64_ST4Fourv2s_POST:
1900 			case AArch64_ST4Fourv4h_POST:
1901 			case AArch64_ST4Fourv4s_POST:
1902 			case AArch64_ST4Fourv8b_POST:
1903 			case AArch64_ST4Fourv8h_POST:
1904 			case AArch64_ST4i16_POST:
1905 			case AArch64_ST4i32_POST:
1906 			case AArch64_ST4i64_POST:
1907 			case AArch64_ST4i8_POST:
1908 			case AArch64_STPDpost:
1909 			case AArch64_STPDpre:
1910 			case AArch64_STPQpost:
1911 			case AArch64_STPQpre:
1912 			case AArch64_STPSpost:
1913 			case AArch64_STPSpre:
1914 			case AArch64_STPWpost:
1915 			case AArch64_STPWpre:
1916 			case AArch64_STPXpost:
1917 			case AArch64_STPXpre:
1918 			case AArch64_STRBBpost:
1919 			case AArch64_STRBBpre:
1920 			case AArch64_STRBpost:
1921 			case AArch64_STRBpre:
1922 			case AArch64_STRDpost:
1923 			case AArch64_STRDpre:
1924 			case AArch64_STRHHpost:
1925 			case AArch64_STRHHpre:
1926 			case AArch64_STRHpost:
1927 			case AArch64_STRHpre:
1928 			case AArch64_STRQpost:
1929 			case AArch64_STRQpre:
1930 			case AArch64_STRSpost:
1931 			case AArch64_STRSpre:
1932 			case AArch64_STRWpost:
1933 			case AArch64_STRWpre:
1934 			case AArch64_STRXpost:
1935 			case AArch64_STRXpre:
1936 				flat_insn->detail->arm64.writeback = true;
1937 				break;
1938 		}
1939 	}
1940 }
1941 
1942 #endif
1943