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