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