Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/capstone/arch/AArch64/AArch64InstPrinter.c
4389 views
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 <[email protected]>, 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, uint64_t Address, unsigned OpIdx,
51
unsigned PrintMethodIdx, SStream *OS);
52
53
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
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
77
static void set_sme_index(MCInst *MI, bool status)
78
{
79
// Doing SME Index operand
80
MI->csh->doing_SME_Index = status;
81
82
if (MI->csh->detail != CS_OPT_ON)
83
return;
84
85
if (status) {
86
unsigned prevOpNum = MI->flat_insn->detail->arm64.op_count - 1;
87
unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, prevOpNum));
88
// Replace previous SME register operand with an OP_SME_INDEX operand
89
MI->flat_insn->detail->arm64.operands[prevOpNum].type = ARM64_OP_SME_INDEX;
90
MI->flat_insn->detail->arm64.operands[prevOpNum].sme_index.reg = Reg;
91
MI->flat_insn->detail->arm64.operands[prevOpNum].sme_index.base = ARM64_REG_INVALID;
92
MI->flat_insn->detail->arm64.operands[prevOpNum].sme_index.disp = 0;
93
}
94
}
95
96
static void set_mem_access(MCInst *MI, bool status)
97
{
98
// If status == false, check if this is meant for SME_index
99
if(!status && MI->csh->doing_SME_Index) {
100
MI->csh->doing_SME_Index = status;
101
return;
102
}
103
104
// Doing Memory Operation
105
MI->csh->doing_mem = status;
106
107
108
if (MI->csh->detail != CS_OPT_ON)
109
return;
110
111
if (status) {
112
#ifndef CAPSTONE_DIET
113
uint8_t access;
114
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
115
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
116
MI->ac_idx++;
117
#endif
118
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_MEM;
119
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].mem.base = ARM64_REG_INVALID;
120
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].mem.index = ARM64_REG_INVALID;
121
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].mem.disp = 0;
122
} else {
123
// done, create the next operand slot
124
MI->flat_insn->detail->arm64.op_count++;
125
}
126
}
127
128
void AArch64_printInst(MCInst *MI, SStream *O, void *Info)
129
{
130
// Check for special encodings and print the canonical alias instead.
131
unsigned Opcode = MCInst_getOpcode(MI);
132
int LSB, Width;
133
char *mnem;
134
135
// printf(">>> opcode = %u\n", MCInst_getOpcode(MI));
136
137
if (Opcode == AArch64_SYSxt && printSysAlias(MI, O))
138
return;
139
140
// SBFM/UBFM should print to a nicer aliased form if possible.
141
if (Opcode == AArch64_SBFMXri || Opcode == AArch64_SBFMWri ||
142
Opcode == AArch64_UBFMXri || Opcode == AArch64_UBFMWri) {
143
bool IsSigned = (Opcode == AArch64_SBFMXri || Opcode == AArch64_SBFMWri);
144
bool Is64Bit = (Opcode == AArch64_SBFMXri || Opcode == AArch64_UBFMXri);
145
146
MCOperand *Op0 = MCInst_getOperand(MI, 0);
147
MCOperand *Op1 = MCInst_getOperand(MI, 1);
148
MCOperand *Op2 = MCInst_getOperand(MI, 2);
149
MCOperand *Op3 = MCInst_getOperand(MI, 3);
150
151
if (MCOperand_isImm(Op2) && MCOperand_getImm(Op2) == 0 && MCOperand_isImm(Op3)) {
152
const char *AsmMnemonic = NULL;
153
154
switch (MCOperand_getImm(Op3)) {
155
default:
156
break;
157
158
case 7:
159
if (IsSigned)
160
AsmMnemonic = "sxtb";
161
else if (!Is64Bit)
162
AsmMnemonic = "uxtb";
163
break;
164
165
case 15:
166
if (IsSigned)
167
AsmMnemonic = "sxth";
168
else if (!Is64Bit)
169
AsmMnemonic = "uxth";
170
break;
171
172
case 31:
173
// *xtw is only valid for signed 64-bit operations.
174
if (Is64Bit && IsSigned)
175
AsmMnemonic = "sxtw";
176
break;
177
}
178
179
if (AsmMnemonic) {
180
SStream_concat(O, "%s\t%s, %s", AsmMnemonic,
181
getRegisterName(MCOperand_getReg(Op0), AArch64_NoRegAltName),
182
getRegisterName(getWRegFromXReg(MCOperand_getReg(Op1)), AArch64_NoRegAltName));
183
184
if (MI->csh->detail) {
185
#ifndef CAPSTONE_DIET
186
uint8_t access;
187
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
188
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
189
MI->ac_idx++;
190
#endif
191
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
192
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op0);
193
MI->flat_insn->detail->arm64.op_count++;
194
#ifndef CAPSTONE_DIET
195
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
196
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
197
MI->ac_idx++;
198
#endif
199
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
200
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = getWRegFromXReg(MCOperand_getReg(Op1));
201
MI->flat_insn->detail->arm64.op_count++;
202
}
203
204
MCInst_setOpcodePub(MI, AArch64_map_insn(AsmMnemonic));
205
206
return;
207
}
208
}
209
210
// All immediate shifts are aliases, implemented using the Bitfield
211
// instruction. In all cases the immediate shift amount shift must be in
212
// the range 0 to (reg.size -1).
213
if (MCOperand_isImm(Op2) && MCOperand_isImm(Op3)) {
214
const char *AsmMnemonic = NULL;
215
int shift = 0;
216
int immr = (int)MCOperand_getImm(Op2);
217
int imms = (int)MCOperand_getImm(Op3);
218
219
if (Opcode == AArch64_UBFMWri && imms != 0x1F && ((imms + 1) == immr)) {
220
AsmMnemonic = "lsl";
221
shift = 31 - imms;
222
} else if (Opcode == AArch64_UBFMXri && imms != 0x3f &&
223
((imms + 1 == immr))) {
224
AsmMnemonic = "lsl";
225
shift = 63 - imms;
226
} else if (Opcode == AArch64_UBFMWri && imms == 0x1f) {
227
AsmMnemonic = "lsr";
228
shift = immr;
229
} else if (Opcode == AArch64_UBFMXri && imms == 0x3f) {
230
AsmMnemonic = "lsr";
231
shift = immr;
232
} else if (Opcode == AArch64_SBFMWri && imms == 0x1f) {
233
AsmMnemonic = "asr";
234
shift = immr;
235
} else if (Opcode == AArch64_SBFMXri && imms == 0x3f) {
236
AsmMnemonic = "asr";
237
shift = immr;
238
}
239
240
if (AsmMnemonic) {
241
SStream_concat(O, "%s\t%s, %s, ", AsmMnemonic,
242
getRegisterName(MCOperand_getReg(Op0), AArch64_NoRegAltName),
243
getRegisterName(MCOperand_getReg(Op1), AArch64_NoRegAltName));
244
245
printInt32Bang(O, shift);
246
247
MCInst_setOpcodePub(MI, AArch64_map_insn(AsmMnemonic));
248
249
if (MI->csh->detail) {
250
#ifndef CAPSTONE_DIET
251
uint8_t access;
252
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
253
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
254
MI->ac_idx++;
255
#endif
256
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
257
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op0);
258
MI->flat_insn->detail->arm64.op_count++;
259
#ifndef CAPSTONE_DIET
260
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
261
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
262
MI->ac_idx++;
263
#endif
264
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
265
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op1);
266
MI->flat_insn->detail->arm64.op_count++;
267
#ifndef CAPSTONE_DIET
268
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
269
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
270
MI->ac_idx++;
271
#endif
272
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
273
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = shift;
274
MI->flat_insn->detail->arm64.op_count++;
275
}
276
277
return;
278
}
279
}
280
281
// SBFIZ/UBFIZ aliases
282
if (MCOperand_getImm(Op2) > MCOperand_getImm(Op3)) {
283
SStream_concat(O, "%s\t%s, %s, ", (IsSigned ? "sbfiz" : "ubfiz"),
284
getRegisterName(MCOperand_getReg(Op0), AArch64_NoRegAltName),
285
getRegisterName(MCOperand_getReg(Op1), AArch64_NoRegAltName));
286
287
printInt32Bang(O, (int)((Is64Bit ? 64 : 32) - MCOperand_getImm(Op2)));
288
289
SStream_concat0(O, ", ");
290
291
printInt32Bang(O, (int)MCOperand_getImm(Op3) + 1);
292
293
MCInst_setOpcodePub(MI, AArch64_map_insn(IsSigned ? "sbfiz" : "ubfiz"));
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 = (Is64Bit ? 64 : 32) - (int)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) + 1;
328
MI->flat_insn->detail->arm64.op_count++;
329
}
330
331
return;
332
}
333
334
// Otherwise SBFX/UBFX is the preferred form
335
SStream_concat(O, "%s\t%s, %s, ", (IsSigned ? "sbfx" : "ubfx"),
336
getRegisterName(MCOperand_getReg(Op0), AArch64_NoRegAltName),
337
getRegisterName(MCOperand_getReg(Op1), AArch64_NoRegAltName));
338
339
printInt32Bang(O, (int)MCOperand_getImm(Op2));
340
SStream_concat0(O, ", ");
341
printInt32Bang(O, (int)MCOperand_getImm(Op3) - (int)MCOperand_getImm(Op2) + 1);
342
343
MCInst_setOpcodePub(MI, AArch64_map_insn(IsSigned ? "sbfx" : "ubfx"));
344
345
if (MI->csh->detail) {
346
#ifndef CAPSTONE_DIET
347
uint8_t access;
348
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
349
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
350
MI->ac_idx++;
351
#endif
352
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
353
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op0);
354
MI->flat_insn->detail->arm64.op_count++;
355
#ifndef CAPSTONE_DIET
356
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
357
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
358
MI->ac_idx++;
359
#endif
360
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
361
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op1);
362
MI->flat_insn->detail->arm64.op_count++;
363
#ifndef CAPSTONE_DIET
364
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
365
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
366
MI->ac_idx++;
367
#endif
368
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
369
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = MCOperand_getImm(Op2);
370
MI->flat_insn->detail->arm64.op_count++;
371
#ifndef CAPSTONE_DIET
372
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
373
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
374
MI->ac_idx++;
375
#endif
376
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
377
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = MCOperand_getImm(Op3) - MCOperand_getImm(Op2) + 1;
378
MI->flat_insn->detail->arm64.op_count++;
379
}
380
381
return;
382
}
383
384
if (Opcode == AArch64_BFMXri || Opcode == AArch64_BFMWri) {
385
MCOperand *Op0 = MCInst_getOperand(MI, 0); // Op1 == Op0
386
MCOperand *Op2 = MCInst_getOperand(MI, 2);
387
int ImmR = (int)MCOperand_getImm(MCInst_getOperand(MI, 3));
388
int ImmS = (int)MCOperand_getImm(MCInst_getOperand(MI, 4));
389
390
if ((MCOperand_getReg(Op2) == AArch64_WZR || MCOperand_getReg(Op2) == AArch64_XZR) &&
391
(ImmR == 0 || ImmS < ImmR)) {
392
// BFC takes precedence over its entire range, sligtly differently to BFI.
393
int BitWidth = Opcode == AArch64_BFMXri ? 64 : 32;
394
int LSB = (BitWidth - ImmR) % BitWidth;
395
int Width = ImmS + 1;
396
397
SStream_concat(O, "bfc\t%s, ",
398
getRegisterName(MCOperand_getReg(Op0), AArch64_NoRegAltName));
399
400
printInt32Bang(O, LSB);
401
SStream_concat0(O, ", ");
402
printInt32Bang(O, Width);
403
MCInst_setOpcodePub(MI, AArch64_map_insn("bfc"));
404
405
if (MI->csh->detail) {
406
#ifndef CAPSTONE_DIET
407
uint8_t access;
408
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
409
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
410
MI->ac_idx++;
411
#endif
412
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
413
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op0);
414
MI->flat_insn->detail->arm64.op_count++;
415
416
#ifndef CAPSTONE_DIET
417
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
418
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
419
MI->ac_idx++;
420
#endif
421
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
422
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = LSB;
423
MI->flat_insn->detail->arm64.op_count++;
424
#ifndef CAPSTONE_DIET
425
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
426
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
427
MI->ac_idx++;
428
#endif
429
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
430
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = Width;
431
MI->flat_insn->detail->arm64.op_count++;
432
}
433
434
return;
435
} else if (ImmS < ImmR) {
436
// BFI alias
437
int BitWidth = Opcode == AArch64_BFMXri ? 64 : 32;
438
LSB = (BitWidth - ImmR) % BitWidth;
439
Width = ImmS + 1;
440
441
SStream_concat(O, "bfi\t%s, %s, ",
442
getRegisterName(MCOperand_getReg(Op0), AArch64_NoRegAltName),
443
getRegisterName(MCOperand_getReg(Op2), AArch64_NoRegAltName));
444
445
printInt32Bang(O, LSB);
446
SStream_concat0(O, ", ");
447
printInt32Bang(O, Width);
448
449
MCInst_setOpcodePub(MI, AArch64_map_insn("bfi"));
450
451
if (MI->csh->detail) {
452
#ifndef CAPSTONE_DIET
453
uint8_t access;
454
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
455
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
456
MI->ac_idx++;
457
#endif
458
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
459
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op0);
460
MI->flat_insn->detail->arm64.op_count++;
461
#ifndef CAPSTONE_DIET
462
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
463
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
464
MI->ac_idx++;
465
#endif
466
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
467
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op2);
468
MI->flat_insn->detail->arm64.op_count++;
469
#ifndef CAPSTONE_DIET
470
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
471
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
472
MI->ac_idx++;
473
#endif
474
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
475
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = LSB;
476
MI->flat_insn->detail->arm64.op_count++;
477
#ifndef CAPSTONE_DIET
478
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
479
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
480
MI->ac_idx++;
481
#endif
482
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
483
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = Width;
484
MI->flat_insn->detail->arm64.op_count++;
485
}
486
487
return;
488
}
489
490
LSB = ImmR;
491
Width = ImmS - ImmR + 1;
492
// Otherwise BFXIL the preferred form
493
SStream_concat(O, "bfxil\t%s, %s, ",
494
getRegisterName(MCOperand_getReg(Op0), AArch64_NoRegAltName),
495
getRegisterName(MCOperand_getReg(Op2), AArch64_NoRegAltName));
496
497
printInt32Bang(O, LSB);
498
SStream_concat0(O, ", ");
499
printInt32Bang(O, Width);
500
501
MCInst_setOpcodePub(MI, AArch64_map_insn("bfxil"));
502
503
if (MI->csh->detail) {
504
#ifndef CAPSTONE_DIET
505
uint8_t access;
506
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
507
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
508
MI->ac_idx++;
509
#endif
510
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
511
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op0);
512
MI->flat_insn->detail->arm64.op_count++;
513
#ifndef CAPSTONE_DIET
514
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
515
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
516
MI->ac_idx++;
517
#endif
518
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
519
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(Op2);
520
MI->flat_insn->detail->arm64.op_count++;
521
#ifndef CAPSTONE_DIET
522
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
523
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
524
MI->ac_idx++;
525
#endif
526
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
527
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = LSB;
528
MI->flat_insn->detail->arm64.op_count++;
529
#ifndef CAPSTONE_DIET
530
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
531
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
532
MI->ac_idx++;
533
#endif
534
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
535
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = Width;
536
MI->flat_insn->detail->arm64.op_count++;
537
}
538
539
return;
540
}
541
542
// MOVZ, MOVN and "ORR wzr, #imm" instructions are aliases for MOV, but their
543
// domains overlap so they need to be prioritized. The chain is "MOVZ lsl #0 >
544
// MOVZ lsl #N > MOVN lsl #0 > MOVN lsl #N > ORR". The highest instruction
545
// that can represent the move is the MOV alias, and the rest get printed
546
// normally.
547
if ((Opcode == AArch64_MOVZXi || Opcode == AArch64_MOVZWi) &&
548
MCOperand_isImm(MCInst_getOperand(MI, 1)) && MCOperand_isImm(MCInst_getOperand(MI, 2))) {
549
int RegWidth = Opcode == AArch64_MOVZXi ? 64 : 32;
550
int Shift = MCOperand_getImm(MCInst_getOperand(MI, 2));
551
uint64_t Value = (uint64_t)MCOperand_getImm(MCInst_getOperand(MI, 1)) << Shift;
552
553
if (isMOVZMovAlias(Value, Shift,
554
Opcode == AArch64_MOVZXi ? 64 : 32)) {
555
SStream_concat(O, "mov\t%s, ", getRegisterName(MCOperand_getReg(MCInst_getOperand(MI, 0)), AArch64_NoRegAltName));
556
557
printInt64Bang(O, SignExtend64(Value, RegWidth));
558
559
if (MI->csh->detail) {
560
#ifndef CAPSTONE_DIET
561
uint8_t access;
562
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
563
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
564
MI->ac_idx++;
565
#endif
566
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
567
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, 0));
568
MI->flat_insn->detail->arm64.op_count++;
569
570
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
571
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = SignExtend64(Value, RegWidth);
572
MI->flat_insn->detail->arm64.op_count++;
573
}
574
575
MCInst_setOpcodePub(MI, AArch64_map_insn("mov"));
576
577
return;
578
}
579
}
580
581
if ((Opcode == AArch64_MOVNXi || Opcode == AArch64_MOVNWi) &&
582
MCOperand_isImm(MCInst_getOperand(MI, 1)) && MCOperand_isImm(MCInst_getOperand(MI, 2))) {
583
int RegWidth = Opcode == AArch64_MOVNXi ? 64 : 32;
584
int Shift = MCOperand_getImm(MCInst_getOperand(MI, 2));
585
uint64_t Value = ~((uint64_t)MCOperand_getImm(MCInst_getOperand(MI, 1)) << Shift);
586
587
if (RegWidth == 32)
588
Value = Value & 0xffffffff;
589
590
if (AArch64_AM_isMOVNMovAlias(Value, Shift, RegWidth)) {
591
SStream_concat(O, "mov\t%s, ", getRegisterName(MCOperand_getReg(MCInst_getOperand(MI, 0)), AArch64_NoRegAltName));
592
593
printInt64Bang(O, SignExtend64(Value, RegWidth));
594
595
if (MI->csh->detail) {
596
#ifndef CAPSTONE_DIET
597
uint8_t access;
598
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
599
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
600
MI->ac_idx++;
601
#endif
602
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
603
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, 0));
604
MI->flat_insn->detail->arm64.op_count++;
605
606
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
607
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = SignExtend64(Value, RegWidth);
608
MI->flat_insn->detail->arm64.op_count++;
609
}
610
611
MCInst_setOpcodePub(MI, AArch64_map_insn("mov"));
612
613
return;
614
}
615
}
616
617
if ((Opcode == AArch64_ORRXri || Opcode == AArch64_ORRWri) &&
618
(MCOperand_getReg(MCInst_getOperand(MI, 1)) == AArch64_XZR ||
619
MCOperand_getReg(MCInst_getOperand(MI, 1)) == AArch64_WZR) &&
620
MCOperand_isImm(MCInst_getOperand(MI, 2))) {
621
int RegWidth = Opcode == AArch64_ORRXri ? 64 : 32;
622
uint64_t Value = AArch64_AM_decodeLogicalImmediate(
623
MCOperand_getImm(MCInst_getOperand(MI, 2)), RegWidth);
624
SStream_concat(O, "mov\t%s, ", getRegisterName(MCOperand_getReg(MCInst_getOperand(MI, 0)), AArch64_NoRegAltName));
625
626
printInt64Bang(O, SignExtend64(Value, RegWidth));
627
628
if (MI->csh->detail) {
629
#ifndef CAPSTONE_DIET
630
uint8_t access;
631
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
632
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
633
MI->ac_idx++;
634
#endif
635
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
636
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, 0));
637
MI->flat_insn->detail->arm64.op_count++;
638
639
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
640
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = SignExtend64(Value, RegWidth);
641
MI->flat_insn->detail->arm64.op_count++;
642
}
643
644
MCInst_setOpcodePub(MI, AArch64_map_insn("mov"));
645
646
return;
647
}
648
649
// Instruction TSB is specified as a one operand instruction, but 'csync' is
650
// not encoded, so for printing it is treated as a special case here:
651
if (Opcode == AArch64_TSB) {
652
SStream_concat0(O, "tsb\tcsync");
653
MCInst_setOpcodePub(MI, AArch64_map_insn("tsb"));
654
return;
655
}
656
657
MI->MRI = Info;
658
659
mnem = printAliasInstr(MI, O, (MCRegisterInfo *)Info);
660
if (mnem) {
661
MCInst_setOpcodePub(MI, AArch64_map_insn(mnem));
662
cs_mem_free(mnem);
663
664
switch(MCInst_getOpcode(MI)) {
665
default: break;
666
case AArch64_LD1i8_POST:
667
arm64_op_addImm(MI, 1);
668
break;
669
case AArch64_LD1i16_POST:
670
arm64_op_addImm(MI, 2);
671
break;
672
case AArch64_LD1i32_POST:
673
arm64_op_addImm(MI, 4);
674
break;
675
case AArch64_LD1Onev1d_POST:
676
case AArch64_LD1Onev2s_POST:
677
case AArch64_LD1Onev4h_POST:
678
case AArch64_LD1Onev8b_POST:
679
case AArch64_LD1i64_POST:
680
arm64_op_addImm(MI, 8);
681
break;
682
case AArch64_LD1Onev16b_POST:
683
case AArch64_LD1Onev2d_POST:
684
case AArch64_LD1Onev4s_POST:
685
case AArch64_LD1Onev8h_POST:
686
case AArch64_LD1Twov1d_POST:
687
case AArch64_LD1Twov2s_POST:
688
case AArch64_LD1Twov4h_POST:
689
case AArch64_LD1Twov8b_POST:
690
arm64_op_addImm(MI, 16);
691
break;
692
case AArch64_LD1Threev1d_POST:
693
case AArch64_LD1Threev2s_POST:
694
case AArch64_LD1Threev4h_POST:
695
case AArch64_LD1Threev8b_POST:
696
arm64_op_addImm(MI, 24);
697
break;
698
case AArch64_LD1Fourv1d_POST:
699
case AArch64_LD1Fourv2s_POST:
700
case AArch64_LD1Fourv4h_POST:
701
case AArch64_LD1Fourv8b_POST:
702
case AArch64_LD1Twov16b_POST:
703
case AArch64_LD1Twov2d_POST:
704
case AArch64_LD1Twov4s_POST:
705
case AArch64_LD1Twov8h_POST:
706
arm64_op_addImm(MI, 32);
707
break;
708
case AArch64_LD1Threev16b_POST:
709
case AArch64_LD1Threev2d_POST:
710
case AArch64_LD1Threev4s_POST:
711
case AArch64_LD1Threev8h_POST:
712
arm64_op_addImm(MI, 48);
713
break;
714
case AArch64_LD1Fourv16b_POST:
715
case AArch64_LD1Fourv2d_POST:
716
case AArch64_LD1Fourv4s_POST:
717
case AArch64_LD1Fourv8h_POST:
718
arm64_op_addImm(MI, 64);
719
break;
720
case AArch64_UMOVvi64:
721
arm64_op_addVectorArrSpecifier(MI, ARM64_VAS_1D);
722
break;
723
case AArch64_UMOVvi32:
724
arm64_op_addVectorArrSpecifier(MI, ARM64_VAS_1S);
725
break;
726
case AArch64_INSvi8gpr:
727
case AArch64_DUP_ZI_B:
728
case AArch64_CPY_ZPmI_B:
729
case AArch64_CPY_ZPzI_B:
730
case AArch64_CPY_ZPmV_B:
731
case AArch64_CPY_ZPmR_B:
732
case AArch64_DUP_ZR_B:
733
if (MI->csh->detail) {
734
MI->flat_insn->detail->arm64.operands[0].vas = ARM64_VAS_1B;
735
}
736
break;
737
case AArch64_INSvi16gpr:
738
case AArch64_DUP_ZI_H:
739
case AArch64_CPY_ZPmI_H:
740
case AArch64_CPY_ZPzI_H:
741
case AArch64_CPY_ZPmV_H:
742
case AArch64_CPY_ZPmR_H:
743
case AArch64_DUP_ZR_H:
744
case AArch64_FCPY_ZPmI_H:
745
case AArch64_FDUP_ZI_H:
746
if (MI->csh->detail) {
747
MI->flat_insn->detail->arm64.operands[0].vas = ARM64_VAS_1H;
748
}
749
break;
750
case AArch64_INSvi32gpr:
751
case AArch64_DUP_ZI_S:
752
case AArch64_CPY_ZPmI_S:
753
case AArch64_CPY_ZPzI_S:
754
case AArch64_CPY_ZPmV_S:
755
case AArch64_CPY_ZPmR_S:
756
case AArch64_DUP_ZR_S:
757
case AArch64_FCPY_ZPmI_S:
758
case AArch64_FDUP_ZI_S:
759
if (MI->csh->detail) {
760
MI->flat_insn->detail->arm64.operands[0].vas = ARM64_VAS_1S;
761
}
762
break;
763
case AArch64_INSvi64gpr:
764
case AArch64_DUP_ZI_D:
765
case AArch64_CPY_ZPmI_D:
766
case AArch64_CPY_ZPzI_D:
767
case AArch64_CPY_ZPmV_D:
768
case AArch64_CPY_ZPmR_D:
769
case AArch64_DUP_ZR_D:
770
case AArch64_FCPY_ZPmI_D:
771
case AArch64_FDUP_ZI_D:
772
if (MI->csh->detail) {
773
MI->flat_insn->detail->arm64.operands[0].vas = ARM64_VAS_1D;
774
}
775
break;
776
case AArch64_INSvi8lane:
777
case AArch64_ORR_PPzPP:
778
case AArch64_ORRS_PPzPP:
779
if (MI->csh->detail) {
780
MI->flat_insn->detail->arm64.operands[0].vas = ARM64_VAS_1B;
781
MI->flat_insn->detail->arm64.operands[1].vas = ARM64_VAS_1B;
782
}
783
break;
784
case AArch64_INSvi16lane:
785
if (MI->csh->detail) {
786
MI->flat_insn->detail->arm64.operands[0].vas = ARM64_VAS_1H;
787
MI->flat_insn->detail->arm64.operands[1].vas = ARM64_VAS_1H;
788
}
789
break;
790
case AArch64_INSvi32lane:
791
if (MI->csh->detail) {
792
MI->flat_insn->detail->arm64.operands[0].vas = ARM64_VAS_1S;
793
MI->flat_insn->detail->arm64.operands[1].vas = ARM64_VAS_1S;
794
}
795
break;
796
case AArch64_INSvi64lane:
797
case AArch64_ORR_ZZZ:
798
if (MI->csh->detail) {
799
MI->flat_insn->detail->arm64.operands[0].vas = ARM64_VAS_1D;
800
MI->flat_insn->detail->arm64.operands[1].vas = ARM64_VAS_1D;
801
}
802
break;
803
case AArch64_ORRv16i8:
804
case AArch64_NOTv16i8:
805
if (MI->csh->detail) {
806
MI->flat_insn->detail->arm64.operands[0].vas = ARM64_VAS_16B;
807
MI->flat_insn->detail->arm64.operands[1].vas = ARM64_VAS_16B;
808
}
809
break;
810
case AArch64_ORRv8i8:
811
case AArch64_NOTv8i8:
812
if (MI->csh->detail) {
813
MI->flat_insn->detail->arm64.operands[0].vas = ARM64_VAS_8B;
814
MI->flat_insn->detail->arm64.operands[1].vas = ARM64_VAS_8B;
815
}
816
break;
817
case AArch64_AND_PPzPP:
818
case AArch64_ANDS_PPzPP:
819
case AArch64_EOR_PPzPP:
820
case AArch64_EORS_PPzPP:
821
case AArch64_SEL_PPPP:
822
case AArch64_SEL_ZPZZ_B:
823
if (MI->csh->detail) {
824
MI->flat_insn->detail->arm64.operands[0].vas = ARM64_VAS_1B;
825
MI->flat_insn->detail->arm64.operands[2].vas = ARM64_VAS_1B;
826
}
827
break;
828
case AArch64_SEL_ZPZZ_D:
829
if (MI->csh->detail) {
830
MI->flat_insn->detail->arm64.operands[0].vas = ARM64_VAS_1D;
831
MI->flat_insn->detail->arm64.operands[2].vas = ARM64_VAS_1D;
832
}
833
break;
834
case AArch64_SEL_ZPZZ_H:
835
if (MI->csh->detail) {
836
MI->flat_insn->detail->arm64.operands[0].vas = ARM64_VAS_1H;
837
MI->flat_insn->detail->arm64.operands[2].vas = ARM64_VAS_1H;
838
}
839
break;
840
case AArch64_SEL_ZPZZ_S:
841
if (MI->csh->detail) {
842
MI->flat_insn->detail->arm64.operands[0].vas = ARM64_VAS_1S;
843
MI->flat_insn->detail->arm64.operands[2].vas = ARM64_VAS_1S;
844
}
845
break;
846
case AArch64_DUP_ZZI_B:
847
if (MI->csh->detail) {
848
MI->flat_insn->detail->arm64.operands[0].vas = ARM64_VAS_1B;
849
if (MI->flat_insn->detail->arm64.op_count == 1) {
850
arm64_op_addReg(MI, ARM64_REG_B0 + MCOperand_getReg(MCInst_getOperand(MI, 1)) - ARM64_REG_Z0);
851
} else {
852
MI->flat_insn->detail->arm64.operands[1].vas = ARM64_VAS_1B;
853
}
854
}
855
break;
856
case AArch64_DUP_ZZI_D:
857
if (MI->csh->detail) {
858
MI->flat_insn->detail->arm64.operands[0].vas = ARM64_VAS_1D;
859
if (MI->flat_insn->detail->arm64.op_count == 1) {
860
arm64_op_addReg(MI, ARM64_REG_D0 + MCOperand_getReg(MCInst_getOperand(MI, 1)) - ARM64_REG_Z0);
861
} else {
862
MI->flat_insn->detail->arm64.operands[1].vas = ARM64_VAS_1D;
863
}
864
}
865
break;
866
case AArch64_DUP_ZZI_H:
867
if (MI->csh->detail) {
868
MI->flat_insn->detail->arm64.operands[0].vas = ARM64_VAS_1H;
869
if (MI->flat_insn->detail->arm64.op_count == 1) {
870
arm64_op_addReg(MI, ARM64_REG_H0 + MCOperand_getReg(MCInst_getOperand(MI, 1)) - ARM64_REG_Z0);
871
} else {
872
MI->flat_insn->detail->arm64.operands[1].vas = ARM64_VAS_1H;
873
}
874
}
875
break;
876
case AArch64_DUP_ZZI_Q:
877
if (MI->csh->detail) {
878
MI->flat_insn->detail->arm64.operands[0].vas = ARM64_VAS_1Q;
879
if (MI->flat_insn->detail->arm64.op_count == 1) {
880
arm64_op_addReg(MI, ARM64_REG_Q0 + MCOperand_getReg(MCInst_getOperand(MI, 1)) - ARM64_REG_Z0);
881
} else {
882
MI->flat_insn->detail->arm64.operands[1].vas = ARM64_VAS_1Q;
883
}
884
}
885
break;
886
case AArch64_DUP_ZZI_S:
887
if (MI->csh->detail) {
888
MI->flat_insn->detail->arm64.operands[0].vas = ARM64_VAS_1S;
889
if (MI->flat_insn->detail->arm64.op_count == 1) {
890
arm64_op_addReg(MI, ARM64_REG_S0 + MCOperand_getReg(MCInst_getOperand(MI, 1)) - ARM64_REG_Z0);
891
} else {
892
MI->flat_insn->detail->arm64.operands[1].vas = ARM64_VAS_1S;
893
}
894
}
895
break;
896
// Hacky detail filling of SMSTART and SMSTOP alias'
897
case AArch64_MSRpstatesvcrImm1:{
898
if(MI->csh->detail){
899
MI->flat_insn->detail->arm64.op_count = 2;
900
#ifndef CAPSTONE_DIET
901
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
902
MI->ac_idx++;
903
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
904
MI->ac_idx++;
905
#endif
906
MI->flat_insn->detail->arm64.operands[0].type = ARM64_OP_SVCR;
907
MI->flat_insn->detail->arm64.operands[0].sys = (unsigned)ARM64_SYSREG_SVCR;
908
MI->flat_insn->detail->arm64.operands[0].svcr = lookupSVCRByEncoding(MCOperand_getImm(MCInst_getOperand(MI, 0)))->Encoding;
909
MI->flat_insn->detail->arm64.operands[1].type = ARM64_OP_IMM;
910
MI->flat_insn->detail->arm64.operands[1].imm = MCOperand_getImm(MCInst_getOperand(MI, 1));
911
}
912
break;
913
}
914
}
915
} else {
916
printInstruction(MI, O);
917
}
918
}
919
920
static bool printSysAlias(MCInst *MI, SStream *O)
921
{
922
// unsigned Opcode = MCInst_getOpcode(MI);
923
//assert(Opcode == AArch64_SYSxt && "Invalid opcode for SYS alias!");
924
925
const char *Ins;
926
uint16_t Encoding;
927
bool NeedsReg;
928
char Name[64];
929
MCOperand *Op1 = MCInst_getOperand(MI, 0);
930
MCOperand *Cn = MCInst_getOperand(MI, 1);
931
MCOperand *Cm = MCInst_getOperand(MI, 2);
932
MCOperand *Op2 = MCInst_getOperand(MI, 3);
933
934
unsigned Op1Val = (unsigned)MCOperand_getImm(Op1);
935
unsigned CnVal = (unsigned)MCOperand_getImm(Cn);
936
unsigned CmVal = (unsigned)MCOperand_getImm(Cm);
937
unsigned Op2Val = (unsigned)MCOperand_getImm(Op2);
938
939
Encoding = Op2Val;
940
Encoding |= CmVal << 3;
941
Encoding |= CnVal << 7;
942
Encoding |= Op1Val << 11;
943
944
if (CnVal == 7) {
945
switch (CmVal) {
946
default:
947
return false;
948
949
// IC aliases
950
case 1: case 5: {
951
const IC *IC = lookupICByEncoding(Encoding);
952
// if (!IC || !IC->haveFeatures(STI.getFeatureBits()))
953
if (!IC)
954
return false;
955
956
NeedsReg = IC->NeedsReg;
957
Ins = "ic";
958
strncpy(Name, IC->Name, sizeof(Name) - 1);
959
}
960
break;
961
962
// DC aliases
963
case 4: case 6: case 10: case 11: case 12: case 14: {
964
const DC *DC = lookupDCByEncoding(Encoding);
965
// if (!DC || !DC->haveFeatures(STI.getFeatureBits()))
966
if (!DC)
967
return false;
968
969
NeedsReg = true;
970
Ins = "dc";
971
strncpy(Name, DC->Name, sizeof(Name) - 1);
972
}
973
break;
974
975
// AT aliases
976
case 8: case 9: {
977
const AT *AT = lookupATByEncoding(Encoding);
978
// if (!AT || !AT->haveFeatures(STI.getFeatureBits()))
979
if (!AT)
980
return false;
981
982
NeedsReg = true;
983
Ins = "at";
984
strncpy(Name, AT->Name, sizeof(Name) - 1);
985
}
986
break;
987
}
988
} else if (CnVal == 8) {
989
// TLBI aliases
990
const TLBI *TLBI = lookupTLBIByEncoding(Encoding);
991
// if (!TLBI || !TLBI->haveFeatures(STI.getFeatureBits()))
992
if (!TLBI)
993
return false;
994
995
NeedsReg = TLBI->NeedsReg;
996
Ins = "tlbi";
997
strncpy(Name, TLBI->Name, sizeof(Name) - 1);
998
} else
999
return false;
1000
1001
SStream_concat(O, "%s\t%s", Ins, Name);
1002
1003
if (NeedsReg) {
1004
SStream_concat(O, ", %s", getRegisterName(MCOperand_getReg(MCInst_getOperand(MI, 4)), AArch64_NoRegAltName));
1005
}
1006
1007
MCInst_setOpcodePub(MI, AArch64_map_insn(Ins));
1008
1009
if (MI->csh->detail) {
1010
#if 0
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
#endif
1018
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_SYS;
1019
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].sys = AArch64_map_sys_op(Name);
1020
MI->flat_insn->detail->arm64.op_count++;
1021
1022
if (NeedsReg) {
1023
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
1024
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, 4));
1025
MI->flat_insn->detail->arm64.op_count++;
1026
}
1027
}
1028
1029
return true;
1030
}
1031
1032
static void printOperand(MCInst *MI, unsigned OpNum, SStream *O)
1033
{
1034
MCOperand *Op = MCInst_getOperand(MI, OpNum);
1035
1036
if (MCOperand_isReg(Op)) {
1037
unsigned Reg = MCOperand_getReg(Op);
1038
1039
SStream_concat0(O, getRegisterName(Reg, AArch64_NoRegAltName));
1040
1041
if (MI->csh->detail) {
1042
if (MI->csh->doing_mem) {
1043
if (MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].mem.base == ARM64_REG_INVALID) {
1044
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].mem.base = Reg;
1045
}
1046
else if (MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].mem.index == ARM64_REG_INVALID) {
1047
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].mem.index = Reg;
1048
}
1049
} else if (MI->csh->doing_SME_Index) {
1050
// Access op_count-1 as We want to add info to previous operand, not create a new one
1051
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count-1].sme_index.base = Reg;
1052
} else {
1053
#ifndef CAPSTONE_DIET
1054
uint8_t access;
1055
1056
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1057
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1058
MI->ac_idx++;
1059
#endif
1060
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
1061
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = Reg;
1062
MI->flat_insn->detail->arm64.op_count++;
1063
}
1064
}
1065
} else if (MCOperand_isImm(Op)) {
1066
int64_t imm = MCOperand_getImm(Op);
1067
1068
if (MI->Opcode == AArch64_ADR) {
1069
imm += MI->address;
1070
printUInt64Bang(O, imm);
1071
} else {
1072
if (MI->csh->doing_mem) {
1073
if (MI->csh->imm_unsigned) {
1074
printUInt64Bang(O, imm);
1075
} else {
1076
printInt64Bang(O, imm);
1077
}
1078
} else
1079
printUInt64Bang(O, imm);
1080
}
1081
1082
if (MI->csh->detail) {
1083
if (MI->csh->doing_mem) {
1084
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].mem.disp = (int32_t)imm;
1085
} else if (MI->csh->doing_SME_Index) {
1086
// Access op_count-1 as We want to add info to previous operand, not create a new one
1087
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count-1].sme_index.disp = (int32_t)imm;
1088
} else {
1089
#ifndef CAPSTONE_DIET
1090
uint8_t access;
1091
1092
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1093
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1094
#endif
1095
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
1096
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = imm;
1097
MI->flat_insn->detail->arm64.op_count++;
1098
}
1099
}
1100
}
1101
}
1102
1103
static void printImm(MCInst *MI, unsigned OpNum, SStream *O)
1104
{
1105
MCOperand *Op = MCInst_getOperand(MI, OpNum);
1106
printUInt64Bang(O, MCOperand_getImm(Op));
1107
1108
if (MI->csh->detail) {
1109
#ifndef CAPSTONE_DIET
1110
uint8_t access;
1111
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1112
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1113
MI->ac_idx++;
1114
#endif
1115
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
1116
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = MCOperand_getImm(Op);
1117
MI->flat_insn->detail->arm64.op_count++;
1118
}
1119
}
1120
1121
static void printImmHex(MCInst *MI, unsigned OpNum, SStream *O)
1122
{
1123
MCOperand *Op = MCInst_getOperand(MI, OpNum);
1124
printUInt64Bang(O, MCOperand_getImm(Op));
1125
1126
if (MI->csh->detail) {
1127
#ifndef CAPSTONE_DIET
1128
uint8_t access;
1129
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1130
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1131
MI->ac_idx++;
1132
#endif
1133
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
1134
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = MCOperand_getImm(Op);
1135
MI->flat_insn->detail->arm64.op_count++;
1136
}
1137
}
1138
1139
static void printSImm(MCInst *MI, unsigned OpNo, SStream *O, int Size) {
1140
MCOperand *Op = MCInst_getOperand(MI, OpNo);
1141
if (Size == 8)
1142
printInt64Bang(O, (signed char) MCOperand_getImm(Op));
1143
else if (Size == 16)
1144
printInt64Bang(O, (signed short) MCOperand_getImm(Op));
1145
else
1146
printInt64Bang(O, MCOperand_getImm(Op));
1147
1148
if (MI->csh->detail) {
1149
#ifndef CAPSTONE_DIET
1150
uint8_t access;
1151
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1152
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1153
MI->ac_idx++;
1154
#endif
1155
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
1156
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = MCOperand_getImm(Op);
1157
MI->flat_insn->detail->arm64.op_count++;
1158
}
1159
}
1160
1161
static void printPostIncOperand(MCInst *MI, unsigned OpNum, SStream *O,
1162
unsigned Imm)
1163
{
1164
MCOperand *Op = MCInst_getOperand(MI, OpNum);
1165
1166
if (MCOperand_isReg(Op)) {
1167
unsigned Reg = MCOperand_getReg(Op);
1168
if (Reg == AArch64_XZR) {
1169
printInt32Bang(O, Imm);
1170
1171
if (MI->csh->detail) {
1172
#ifndef CAPSTONE_DIET
1173
uint8_t access;
1174
1175
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1176
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1177
MI->ac_idx++;
1178
#endif
1179
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
1180
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = Imm;
1181
MI->flat_insn->detail->arm64.op_count++;
1182
}
1183
} else {
1184
SStream_concat0(O, getRegisterName(Reg, AArch64_NoRegAltName));
1185
1186
if (MI->csh->detail) {
1187
#ifndef CAPSTONE_DIET
1188
uint8_t access;
1189
1190
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1191
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1192
MI->ac_idx++;
1193
#endif
1194
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
1195
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = Reg;
1196
MI->flat_insn->detail->arm64.op_count++;
1197
}
1198
}
1199
}
1200
//llvm_unreachable("unknown operand kind in printPostIncOperand64");
1201
}
1202
1203
static void printVRegOperand(MCInst *MI, unsigned OpNum, SStream *O)
1204
{
1205
MCOperand *Op = MCInst_getOperand(MI, OpNum);
1206
//assert(Op.isReg() && "Non-register vreg operand!");
1207
unsigned Reg = MCOperand_getReg(Op);
1208
1209
SStream_concat0(O, getRegisterName(Reg, AArch64_vreg));
1210
1211
if (MI->csh->detail) {
1212
#ifndef CAPSTONE_DIET
1213
uint8_t access;
1214
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1215
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1216
MI->ac_idx++;
1217
#endif
1218
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
1219
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = AArch64_map_vregister(Reg);
1220
MI->flat_insn->detail->arm64.op_count++;
1221
}
1222
}
1223
1224
static void printSysCROperand(MCInst *MI, unsigned OpNum, SStream *O)
1225
{
1226
MCOperand *Op = MCInst_getOperand(MI, OpNum);
1227
//assert(Op.isImm() && "System instruction C[nm] operands must be immediates!");
1228
SStream_concat(O, "c%u", MCOperand_getImm(Op));
1229
1230
if (MI->csh->detail) {
1231
#ifndef CAPSTONE_DIET
1232
uint8_t access;
1233
1234
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1235
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1236
MI->ac_idx++;
1237
#endif
1238
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_CIMM;
1239
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = MCOperand_getImm(Op);
1240
MI->flat_insn->detail->arm64.op_count++;
1241
}
1242
}
1243
1244
static void printAddSubImm(MCInst *MI, unsigned OpNum, SStream *O)
1245
{
1246
MCOperand *MO = MCInst_getOperand(MI, OpNum);
1247
if (MCOperand_isImm(MO)) {
1248
unsigned Val = (MCOperand_getImm(MO) & 0xfff);
1249
//assert(Val == MO.getImm() && "Add/sub immediate out of range!");
1250
unsigned Shift = AArch64_AM_getShiftValue((int)MCOperand_getImm(MCInst_getOperand(MI, OpNum + 1)));
1251
1252
printInt32Bang(O, Val);
1253
1254
if (MI->csh->detail) {
1255
#ifndef CAPSTONE_DIET
1256
uint8_t access;
1257
1258
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1259
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1260
MI->ac_idx++;
1261
#endif
1262
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
1263
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = Val;
1264
MI->flat_insn->detail->arm64.op_count++;
1265
}
1266
1267
if (Shift != 0)
1268
printShifter(MI, OpNum + 1, O);
1269
}
1270
}
1271
1272
static void printLogicalImm32(MCInst *MI, unsigned OpNum, SStream *O)
1273
{
1274
int64_t Val = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1275
1276
Val = AArch64_AM_decodeLogicalImmediate(Val, 32);
1277
printUInt32Bang(O, (int)Val);
1278
1279
if (MI->csh->detail) {
1280
#ifndef CAPSTONE_DIET
1281
uint8_t access;
1282
1283
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1284
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1285
MI->ac_idx++;
1286
#endif
1287
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
1288
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = Val;
1289
MI->flat_insn->detail->arm64.op_count++;
1290
}
1291
}
1292
1293
static void printLogicalImm64(MCInst *MI, unsigned OpNum, SStream *O)
1294
{
1295
int64_t Val = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1296
Val = AArch64_AM_decodeLogicalImmediate(Val, 64);
1297
1298
switch(MI->flat_insn->id) {
1299
default:
1300
printInt64Bang(O, Val);
1301
break;
1302
1303
case ARM64_INS_ORR:
1304
case ARM64_INS_AND:
1305
case ARM64_INS_EOR:
1306
case ARM64_INS_TST:
1307
// do not print number in negative form
1308
if (Val >= 0 && Val <= HEX_THRESHOLD)
1309
SStream_concat(O, "#%u", (int)Val);
1310
else
1311
SStream_concat(O, "#0x%"PRIx64, Val);
1312
break;
1313
}
1314
1315
if (MI->csh->detail) {
1316
#ifndef CAPSTONE_DIET
1317
uint8_t access;
1318
1319
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1320
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1321
MI->ac_idx++;
1322
#endif
1323
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
1324
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = (int64_t)Val;
1325
MI->flat_insn->detail->arm64.op_count++;
1326
}
1327
}
1328
1329
static void printShifter(MCInst *MI, unsigned OpNum, SStream *O)
1330
{
1331
unsigned Val = (unsigned)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1332
1333
// LSL #0 should not be printed.
1334
if (AArch64_AM_getShiftType(Val) == AArch64_AM_LSL &&
1335
AArch64_AM_getShiftValue(Val) == 0)
1336
return;
1337
1338
SStream_concat(O, ", %s ", AArch64_AM_getShiftExtendName(AArch64_AM_getShiftType(Val)));
1339
printInt32BangDec(O, AArch64_AM_getShiftValue(Val));
1340
1341
if (MI->csh->detail) {
1342
arm64_shifter shifter = ARM64_SFT_INVALID;
1343
1344
switch(AArch64_AM_getShiftType(Val)) {
1345
default: // never reach
1346
case AArch64_AM_LSL:
1347
shifter = ARM64_SFT_LSL;
1348
break;
1349
1350
case AArch64_AM_LSR:
1351
shifter = ARM64_SFT_LSR;
1352
break;
1353
1354
case AArch64_AM_ASR:
1355
shifter = ARM64_SFT_ASR;
1356
break;
1357
1358
case AArch64_AM_ROR:
1359
shifter = ARM64_SFT_ROR;
1360
break;
1361
1362
case AArch64_AM_MSL:
1363
shifter = ARM64_SFT_MSL;
1364
break;
1365
}
1366
1367
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].shift.type = shifter;
1368
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].shift.value = AArch64_AM_getShiftValue(Val);
1369
}
1370
}
1371
1372
static void printShiftedRegister(MCInst *MI, unsigned OpNum, SStream *O)
1373
{
1374
SStream_concat0(O, getRegisterName(MCOperand_getReg(MCInst_getOperand(MI, OpNum)), AArch64_NoRegAltName));
1375
1376
if (MI->csh->detail) {
1377
#ifndef CAPSTONE_DIET
1378
uint8_t access;
1379
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1380
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1381
MI->ac_idx++;
1382
#endif
1383
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
1384
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
1385
MI->flat_insn->detail->arm64.op_count++;
1386
}
1387
1388
printShifter(MI, OpNum + 1, O);
1389
}
1390
1391
static void printArithExtend(MCInst *MI, unsigned OpNum, SStream *O)
1392
{
1393
unsigned Val = (unsigned)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1394
AArch64_AM_ShiftExtendType ExtType = AArch64_AM_getArithExtendType(Val);
1395
unsigned ShiftVal = AArch64_AM_getArithShiftValue(Val);
1396
1397
// If the destination or first source register operand is [W]SP, print
1398
// UXTW/UXTX as LSL, and if the shift amount is also zero, print nothing at
1399
// all.
1400
if (ExtType == AArch64_AM_UXTW || ExtType == AArch64_AM_UXTX) {
1401
unsigned Dest = MCOperand_getReg(MCInst_getOperand(MI, 0));
1402
unsigned Src1 = MCOperand_getReg(MCInst_getOperand(MI, 1));
1403
1404
if (((Dest == AArch64_SP || Src1 == AArch64_SP) &&
1405
ExtType == AArch64_AM_UXTX) ||
1406
((Dest == AArch64_WSP || Src1 == AArch64_WSP) &&
1407
ExtType == AArch64_AM_UXTW)) {
1408
if (ShiftVal != 0) {
1409
SStream_concat0(O, ", lsl ");
1410
printInt32Bang(O, ShiftVal);
1411
1412
if (MI->csh->detail) {
1413
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].shift.type = ARM64_SFT_LSL;
1414
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].shift.value = ShiftVal;
1415
}
1416
}
1417
1418
return;
1419
}
1420
}
1421
1422
SStream_concat(O, ", %s", AArch64_AM_getShiftExtendName(ExtType));
1423
1424
if (MI->csh->detail) {
1425
arm64_extender ext = ARM64_EXT_INVALID;
1426
switch(ExtType) {
1427
default: // never reach
1428
1429
case AArch64_AM_UXTB:
1430
ext = ARM64_EXT_UXTB;
1431
break;
1432
1433
case AArch64_AM_UXTH:
1434
ext = ARM64_EXT_UXTH;
1435
break;
1436
1437
case AArch64_AM_UXTW:
1438
ext = ARM64_EXT_UXTW;
1439
break;
1440
1441
case AArch64_AM_UXTX:
1442
ext = ARM64_EXT_UXTX;
1443
break;
1444
1445
case AArch64_AM_SXTB:
1446
ext = ARM64_EXT_SXTB;
1447
break;
1448
1449
case AArch64_AM_SXTH:
1450
ext = ARM64_EXT_SXTH;
1451
break;
1452
1453
case AArch64_AM_SXTW:
1454
ext = ARM64_EXT_SXTW;
1455
break;
1456
1457
case AArch64_AM_SXTX:
1458
ext = ARM64_EXT_SXTX;
1459
break;
1460
}
1461
1462
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].ext = ext;
1463
}
1464
1465
if (ShiftVal != 0) {
1466
SStream_concat0(O, " ");
1467
printInt32Bang(O, ShiftVal);
1468
1469
if (MI->csh->detail) {
1470
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].shift.type = ARM64_SFT_LSL;
1471
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].shift.value = ShiftVal;
1472
}
1473
}
1474
}
1475
1476
static void printExtendedRegister(MCInst *MI, unsigned OpNum, SStream *O)
1477
{
1478
unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
1479
1480
SStream_concat0(O, getRegisterName(Reg, AArch64_NoRegAltName));
1481
1482
if (MI->csh->detail) {
1483
#ifndef CAPSTONE_DIET
1484
uint8_t access;
1485
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1486
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1487
MI->ac_idx++;
1488
#endif
1489
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
1490
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = Reg;
1491
MI->flat_insn->detail->arm64.op_count++;
1492
}
1493
1494
printArithExtend(MI, OpNum + 1, O);
1495
}
1496
1497
static void printMemExtendImpl(MCInst *MI, bool SignExtend, bool DoShift, unsigned Width,
1498
char SrcRegKind, SStream *O)
1499
{
1500
// sxtw, sxtx, uxtw or lsl (== uxtx)
1501
bool IsLSL = !SignExtend && SrcRegKind == 'x';
1502
if (IsLSL) {
1503
SStream_concat0(O, "lsl");
1504
1505
if (MI->csh->detail) {
1506
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].shift.type = ARM64_SFT_LSL;
1507
}
1508
} else {
1509
SStream_concat(O, "%cxt%c", (SignExtend ? 's' : 'u'), SrcRegKind);
1510
1511
if (MI->csh->detail) {
1512
if (!SignExtend) {
1513
switch(SrcRegKind) {
1514
default: break;
1515
case 'b':
1516
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].ext = ARM64_EXT_UXTB;
1517
break;
1518
case 'h':
1519
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].ext = ARM64_EXT_UXTH;
1520
break;
1521
case 'w':
1522
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].ext = ARM64_EXT_UXTW;
1523
break;
1524
}
1525
} else {
1526
switch(SrcRegKind) {
1527
default: break;
1528
case 'b':
1529
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].ext = ARM64_EXT_SXTB;
1530
break;
1531
case 'h':
1532
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].ext = ARM64_EXT_SXTH;
1533
break;
1534
case 'w':
1535
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].ext = ARM64_EXT_SXTW;
1536
break;
1537
case 'x':
1538
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].ext = ARM64_EXT_SXTX;
1539
break;
1540
}
1541
}
1542
}
1543
}
1544
1545
if (DoShift || IsLSL) {
1546
SStream_concat(O, " #%u", Log2_32(Width / 8));
1547
1548
if (MI->csh->detail) {
1549
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].shift.type = ARM64_SFT_LSL;
1550
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].shift.value = Log2_32(Width / 8);
1551
}
1552
}
1553
}
1554
1555
static void printMemExtend(MCInst *MI, unsigned OpNum, SStream *O, char SrcRegKind, unsigned Width)
1556
{
1557
unsigned SignExtend = (unsigned)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1558
unsigned DoShift = (unsigned)MCOperand_getImm(MCInst_getOperand(MI, OpNum + 1));
1559
1560
printMemExtendImpl(MI, SignExtend, DoShift, Width, SrcRegKind, O);
1561
}
1562
1563
static void printRegWithShiftExtend(MCInst *MI, unsigned OpNum, SStream *O,
1564
bool SignExtend, int ExtWidth,
1565
char SrcRegKind, char Suffix)
1566
{
1567
bool DoShift;
1568
1569
printOperand(MI, OpNum, O);
1570
1571
if (Suffix == 's' || Suffix == 'd')
1572
SStream_concat(O, ".%c", Suffix);
1573
1574
DoShift = ExtWidth != 8;
1575
if (SignExtend || DoShift || SrcRegKind == 'w') {
1576
SStream_concat0(O, ", ");
1577
printMemExtendImpl(MI, SignExtend, DoShift, ExtWidth, SrcRegKind, O);
1578
}
1579
}
1580
1581
static void printCondCode(MCInst *MI, unsigned OpNum, SStream *O)
1582
{
1583
AArch64CC_CondCode CC = (AArch64CC_CondCode)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1584
SStream_concat0(O, getCondCodeName(CC));
1585
1586
if (MI->csh->detail)
1587
MI->flat_insn->detail->arm64.cc = (arm64_cc)(CC + 1);
1588
}
1589
1590
static void printInverseCondCode(MCInst *MI, unsigned OpNum, SStream *O)
1591
{
1592
AArch64CC_CondCode CC = (AArch64CC_CondCode)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1593
SStream_concat0(O, getCondCodeName(getInvertedCondCode(CC)));
1594
1595
if (MI->csh->detail) {
1596
MI->flat_insn->detail->arm64.cc = (arm64_cc)(getInvertedCondCode(CC) + 1);
1597
}
1598
}
1599
1600
static void printImmScale(MCInst *MI, unsigned OpNum, SStream *O, int Scale)
1601
{
1602
int64_t val = Scale * MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1603
1604
printInt64Bang(O, val);
1605
1606
if (MI->csh->detail) {
1607
if (MI->csh->doing_mem) {
1608
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].mem.disp = (int32_t)val;
1609
} else {
1610
#ifndef CAPSTONE_DIET
1611
uint8_t access;
1612
1613
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1614
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1615
MI->ac_idx++;
1616
#endif
1617
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
1618
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = val;
1619
MI->flat_insn->detail->arm64.op_count++;
1620
}
1621
}
1622
}
1623
1624
static void printUImm12Offset(MCInst *MI, unsigned OpNum, SStream *O, unsigned Scale)
1625
{
1626
MCOperand *MO = MCInst_getOperand(MI, OpNum);
1627
1628
if (MCOperand_isImm(MO)) {
1629
int64_t val = Scale * MCOperand_getImm(MO);
1630
printInt64Bang(O, val);
1631
1632
if (MI->csh->detail) {
1633
if (MI->csh->doing_mem) {
1634
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].mem.disp = (int32_t)val;
1635
} else {
1636
#ifndef CAPSTONE_DIET
1637
uint8_t access;
1638
1639
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1640
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1641
MI->ac_idx++;
1642
#endif
1643
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
1644
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = (int)val;
1645
MI->flat_insn->detail->arm64.op_count++;
1646
}
1647
}
1648
}
1649
}
1650
1651
#if 0
1652
static void printAMIndexedWB(MCInst *MI, unsigned OpNum, SStream *O, unsigned int Scale)
1653
{
1654
MCOperand *MO = MCInst_getOperand(MI, OpNum + 1);
1655
1656
SStream_concat(O, "[%s", getRegisterName(MCOperand_getReg(MCInst_getOperand(MI, OpNum)), AArch64_NoRegAltName));
1657
1658
if (MCOperand_isImm(MO)) {
1659
int64_t val = Scale * MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1660
printInt64Bang(O, val);
1661
// } else {
1662
// // assert(MO1.isExpr() && "Unexpected operand type!");
1663
// SStream_concat0(O, ", ");
1664
// MO1.getExpr()->print(O, &MAI);
1665
}
1666
1667
SStream_concat0(O, "]");
1668
}
1669
#endif
1670
1671
// IsSVEPrefetch = false
1672
static void printPrefetchOp(MCInst *MI, unsigned OpNum, SStream *O, bool IsSVEPrefetch)
1673
{
1674
unsigned prfop = (unsigned)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1675
1676
if (IsSVEPrefetch) {
1677
const SVEPRFM *PRFM = lookupSVEPRFMByEncoding(prfop);
1678
if (PRFM)
1679
SStream_concat0(O, PRFM->Name);
1680
1681
return;
1682
} else {
1683
const PRFM *PRFM = lookupPRFMByEncoding(prfop);
1684
if (PRFM)
1685
SStream_concat0(O, PRFM->Name);
1686
1687
return;
1688
}
1689
1690
// FIXME: set OpcodePub?
1691
1692
printInt32Bang(O, prfop);
1693
1694
if (MI->csh->detail) {
1695
#ifndef CAPSTONE_DIET
1696
uint8_t access;
1697
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1698
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1699
MI->ac_idx++;
1700
#endif
1701
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
1702
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = prfop;
1703
MI->flat_insn->detail->arm64.op_count++;
1704
}
1705
}
1706
1707
static void printPSBHintOp(MCInst *MI, unsigned OpNum, SStream *O)
1708
{
1709
MCOperand *Op = MCInst_getOperand(MI, OpNum);
1710
unsigned int psbhintop = MCOperand_getImm(Op);
1711
1712
const PSB *PSB = lookupPSBByEncoding(psbhintop);
1713
if (PSB)
1714
SStream_concat0(O, PSB->Name);
1715
else
1716
printUInt32Bang(O, psbhintop);
1717
}
1718
1719
static void printBTIHintOp(MCInst *MI, unsigned OpNum, SStream *O) {
1720
unsigned btihintop = MCOperand_getImm(MCInst_getOperand(MI, OpNum)) ^ 32;
1721
1722
const BTI *BTI = lookupBTIByEncoding(btihintop);
1723
if (BTI)
1724
SStream_concat0(O, BTI->Name);
1725
else
1726
printUInt32Bang(O, btihintop);
1727
}
1728
1729
static void printFPImmOperand(MCInst *MI, unsigned OpNum, SStream *O)
1730
{
1731
MCOperand *MO = MCInst_getOperand(MI, OpNum);
1732
float FPImm = MCOperand_isFPImm(MO) ? MCOperand_getFPImm(MO) : AArch64_AM_getFPImmFloat((int)MCOperand_getImm(MO));
1733
1734
// 8 decimal places are enough to perfectly represent permitted floats.
1735
#if defined(_KERNEL_MODE)
1736
// Issue #681: Windows kernel does not support formatting float point
1737
SStream_concat0(O, "#<float_point_unsupported>");
1738
#else
1739
SStream_concat(O, "#%.8f", FPImm);
1740
#endif
1741
1742
if (MI->csh->detail) {
1743
#ifndef CAPSTONE_DIET
1744
uint8_t access;
1745
1746
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1747
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1748
MI->ac_idx++;
1749
#endif
1750
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_FP;
1751
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].fp = FPImm;
1752
MI->flat_insn->detail->arm64.op_count++;
1753
}
1754
}
1755
1756
//static unsigned getNextVectorRegister(unsigned Reg, unsigned Stride = 1)
1757
static unsigned getNextVectorRegister(unsigned Reg, unsigned Stride)
1758
{
1759
while (Stride--) {
1760
if (Reg >= AArch64_Q0 && Reg <= AArch64_Q30) // AArch64_Q0 .. AArch64_Q30
1761
Reg += 1;
1762
else if (Reg == AArch64_Q31) // Vector lists can wrap around.
1763
Reg = AArch64_Q0;
1764
else if (Reg >= AArch64_Z0 && Reg <= AArch64_Z30) // AArch64_Z0 .. AArch64_Z30
1765
Reg += 1;
1766
else if (Reg == AArch64_Z31) // Vector lists can wrap around.
1767
Reg = AArch64_Z0;
1768
}
1769
1770
return Reg;
1771
}
1772
1773
static void printGPRSeqPairsClassOperand(MCInst *MI, unsigned OpNum, SStream *O, unsigned int size)
1774
{
1775
// static_assert(size == 64 || size == 32,
1776
// "Template parameter must be either 32 or 64");
1777
unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
1778
unsigned Sube = (size == 32) ? AArch64_sube32 : AArch64_sube64;
1779
unsigned Subo = (size == 32) ? AArch64_subo32 : AArch64_subo64;
1780
unsigned Even = MCRegisterInfo_getSubReg(MI->MRI, Reg, Sube);
1781
unsigned Odd = MCRegisterInfo_getSubReg(MI->MRI, Reg, Subo);
1782
1783
SStream_concat(O, "%s, %s", getRegisterName(Even, AArch64_NoRegAltName),
1784
getRegisterName(Odd, AArch64_NoRegAltName));
1785
1786
if (MI->csh->detail) {
1787
#ifndef CAPSTONE_DIET
1788
uint8_t access;
1789
1790
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1791
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1792
MI->ac_idx++;
1793
#endif
1794
1795
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
1796
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = Even;
1797
MI->flat_insn->detail->arm64.op_count++;
1798
1799
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
1800
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = Odd;
1801
MI->flat_insn->detail->arm64.op_count++;
1802
}
1803
}
1804
1805
static void printVectorList(MCInst *MI, unsigned OpNum, SStream *O,
1806
char *LayoutSuffix, MCRegisterInfo *MRI, arm64_vas vas)
1807
{
1808
#define GETREGCLASS_CONTAIN0(_class, _reg) MCRegisterClass_contains(MCRegisterInfo_getRegClass(MRI, _class), _reg)
1809
unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
1810
unsigned NumRegs = 1, FirstReg, i;
1811
1812
SStream_concat0(O, "{");
1813
1814
// Work out how many registers there are in the list (if there is an actual
1815
// list).
1816
if (GETREGCLASS_CONTAIN0(AArch64_DDRegClassID , Reg) ||
1817
GETREGCLASS_CONTAIN0(AArch64_ZPR2RegClassID, Reg) ||
1818
GETREGCLASS_CONTAIN0(AArch64_QQRegClassID, Reg))
1819
NumRegs = 2;
1820
else if (GETREGCLASS_CONTAIN0(AArch64_DDDRegClassID, Reg) ||
1821
GETREGCLASS_CONTAIN0(AArch64_ZPR3RegClassID, Reg) ||
1822
GETREGCLASS_CONTAIN0(AArch64_QQQRegClassID, Reg))
1823
NumRegs = 3;
1824
else if (GETREGCLASS_CONTAIN0(AArch64_DDDDRegClassID, Reg) ||
1825
GETREGCLASS_CONTAIN0(AArch64_ZPR4RegClassID, Reg) ||
1826
GETREGCLASS_CONTAIN0(AArch64_QQQQRegClassID, Reg))
1827
NumRegs = 4;
1828
1829
// Now forget about the list and find out what the first register is.
1830
if ((FirstReg = MCRegisterInfo_getSubReg(MRI, Reg, AArch64_dsub0)))
1831
Reg = FirstReg;
1832
else if ((FirstReg = MCRegisterInfo_getSubReg(MRI, Reg, AArch64_qsub0)))
1833
Reg = FirstReg;
1834
else if ((FirstReg = MCRegisterInfo_getSubReg(MRI, Reg, AArch64_zsub0)))
1835
Reg = FirstReg;
1836
1837
// If it's a D-reg, we need to promote it to the equivalent Q-reg before
1838
// printing (otherwise getRegisterName fails).
1839
if (GETREGCLASS_CONTAIN0(AArch64_FPR64RegClassID, Reg)) {
1840
const MCRegisterClass *FPR128RC = MCRegisterInfo_getRegClass(MRI, AArch64_FPR128RegClassID);
1841
Reg = MCRegisterInfo_getMatchingSuperReg(MRI, Reg, AArch64_dsub, FPR128RC);
1842
}
1843
1844
for (i = 0; i < NumRegs; ++i, Reg = getNextVectorRegister(Reg, 1)) {
1845
bool isZReg = GETREGCLASS_CONTAIN0(AArch64_ZPRRegClassID, Reg);
1846
if (isZReg)
1847
SStream_concat(O, "%s%s", getRegisterName(Reg, AArch64_NoRegAltName), LayoutSuffix);
1848
else
1849
SStream_concat(O, "%s%s", getRegisterName(Reg, AArch64_vreg), LayoutSuffix);
1850
1851
if (MI->csh->detail) {
1852
#ifndef CAPSTONE_DIET
1853
uint8_t access;
1854
1855
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
1856
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
1857
MI->ac_idx++;
1858
#endif
1859
unsigned regForDetail = isZReg ? Reg : AArch64_map_vregister(Reg);
1860
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
1861
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = regForDetail;
1862
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].vas = vas;
1863
MI->flat_insn->detail->arm64.op_count++;
1864
}
1865
1866
if (i + 1 != NumRegs)
1867
SStream_concat0(O, ", ");
1868
}
1869
1870
SStream_concat0(O, "}");
1871
}
1872
1873
static void printTypedVectorList(MCInst *MI, unsigned OpNum, SStream *O, unsigned NumLanes, char LaneKind)
1874
{
1875
char Suffix[32];
1876
arm64_vas vas = 0;
1877
1878
if (NumLanes) {
1879
cs_snprintf(Suffix, sizeof(Suffix), ".%u%c", NumLanes, LaneKind);
1880
1881
switch(LaneKind) {
1882
default: break;
1883
case 'b':
1884
switch(NumLanes) {
1885
default: break;
1886
case 1:
1887
vas = ARM64_VAS_1B;
1888
break;
1889
case 4:
1890
vas = ARM64_VAS_4B;
1891
break;
1892
case 8:
1893
vas = ARM64_VAS_8B;
1894
break;
1895
case 16:
1896
vas = ARM64_VAS_16B;
1897
break;
1898
}
1899
break;
1900
case 'h':
1901
switch(NumLanes) {
1902
default: break;
1903
case 1:
1904
vas = ARM64_VAS_1H;
1905
break;
1906
case 2:
1907
vas = ARM64_VAS_2H;
1908
break;
1909
case 4:
1910
vas = ARM64_VAS_4H;
1911
break;
1912
case 8:
1913
vas = ARM64_VAS_8H;
1914
break;
1915
}
1916
break;
1917
case 's':
1918
switch(NumLanes) {
1919
default: break;
1920
case 1:
1921
vas = ARM64_VAS_1S;
1922
break;
1923
case 2:
1924
vas = ARM64_VAS_2S;
1925
break;
1926
case 4:
1927
vas = ARM64_VAS_4S;
1928
break;
1929
}
1930
break;
1931
case 'd':
1932
switch(NumLanes) {
1933
default: break;
1934
case 1:
1935
vas = ARM64_VAS_1D;
1936
break;
1937
case 2:
1938
vas = ARM64_VAS_2D;
1939
break;
1940
}
1941
break;
1942
case 'q':
1943
switch(NumLanes) {
1944
default: break;
1945
case 1:
1946
vas = ARM64_VAS_1Q;
1947
break;
1948
}
1949
break;
1950
}
1951
} else {
1952
cs_snprintf(Suffix, sizeof(Suffix), ".%c", LaneKind);
1953
1954
switch(LaneKind) {
1955
default: break;
1956
case 'b':
1957
vas = ARM64_VAS_1B;
1958
break;
1959
case 'h':
1960
vas = ARM64_VAS_1H;
1961
break;
1962
case 's':
1963
vas = ARM64_VAS_1S;
1964
break;
1965
case 'd':
1966
vas = ARM64_VAS_1D;
1967
break;
1968
case 'q':
1969
vas = ARM64_VAS_1Q;
1970
break;
1971
}
1972
}
1973
1974
printVectorList(MI, OpNum, O, Suffix, MI->MRI, vas);
1975
}
1976
1977
static void printVectorIndex(MCInst *MI, unsigned OpNum, SStream *O)
1978
{
1979
SStream_concat0(O, "[");
1980
printInt32(O, (int)MCOperand_getImm(MCInst_getOperand(MI, OpNum)));
1981
SStream_concat0(O, "]");
1982
1983
if (MI->csh->detail) {
1984
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].vector_index = (int)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1985
}
1986
}
1987
1988
static void printAlignedLabel(MCInst *MI, unsigned OpNum, SStream *O)
1989
{
1990
MCOperand *Op = MCInst_getOperand(MI, OpNum);
1991
1992
// If the label has already been resolved to an immediate offset (say, when
1993
// we're running the disassembler), just print the immediate.
1994
if (MCOperand_isImm(Op)) {
1995
uint64_t imm = (MCOperand_getImm(Op) * 4) + MI->address;
1996
printUInt64Bang(O, imm);
1997
1998
if (MI->csh->detail) {
1999
#ifndef CAPSTONE_DIET
2000
uint8_t access;
2001
2002
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2003
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
2004
MI->ac_idx++;
2005
#endif
2006
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
2007
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = imm;
2008
MI->flat_insn->detail->arm64.op_count++;
2009
}
2010
}
2011
}
2012
2013
static void printAdrpLabel(MCInst *MI, unsigned OpNum, SStream *O)
2014
{
2015
MCOperand *Op = MCInst_getOperand(MI, OpNum);
2016
2017
if (MCOperand_isImm(Op)) {
2018
// ADRP sign extends a 21-bit offset, shifts it left by 12
2019
// and adds it to the value of the PC with its bottom 12 bits cleared
2020
uint64_t imm = (MCOperand_getImm(Op) * 0x1000) + (MI->address & ~0xfff);
2021
printUInt64Bang(O, imm);
2022
2023
if (MI->csh->detail) {
2024
#ifndef CAPSTONE_DIET
2025
uint8_t access;
2026
2027
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2028
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
2029
MI->ac_idx++;
2030
#endif
2031
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
2032
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = imm;
2033
MI->flat_insn->detail->arm64.op_count++;
2034
}
2035
}
2036
}
2037
2038
static void printBarrierOption(MCInst *MI, unsigned OpNum, SStream *O)
2039
{
2040
unsigned Val = (unsigned)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2041
unsigned Opcode = MCInst_getOpcode(MI);
2042
const char *Name = NULL;
2043
2044
if (Opcode == AArch64_ISB) {
2045
const ISB *ISB = lookupISBByEncoding(Val);
2046
Name = ISB ? ISB->Name : NULL;
2047
} else if (Opcode == AArch64_TSB) {
2048
const TSB *TSB = lookupTSBByEncoding(Val);
2049
Name = TSB ? TSB->Name : NULL;
2050
} else {
2051
const DB *DB = lookupDBByEncoding(Val);
2052
Name = DB ? DB->Name : NULL;
2053
}
2054
2055
if (Name) {
2056
SStream_concat0(O, Name);
2057
2058
if (MI->csh->detail) {
2059
#ifndef CAPSTONE_DIET
2060
uint8_t access;
2061
2062
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2063
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
2064
MI->ac_idx++;
2065
#endif
2066
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_BARRIER;
2067
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].barrier = Val;
2068
MI->flat_insn->detail->arm64.op_count++;
2069
}
2070
} else {
2071
printUInt32Bang(O, Val);
2072
2073
if (MI->csh->detail) {
2074
#ifndef CAPSTONE_DIET
2075
uint8_t access;
2076
2077
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2078
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
2079
MI->ac_idx++;
2080
#endif
2081
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
2082
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = Val;
2083
MI->flat_insn->detail->arm64.op_count++;
2084
}
2085
}
2086
}
2087
2088
static void printBarriernXSOption(MCInst *MI, unsigned OpNo, SStream *O) {
2089
unsigned Val = MCOperand_getImm(MCInst_getOperand(MI, OpNo));
2090
// assert(MI->getOpcode() == AArch64::DSBnXS);
2091
2092
const char *Name = NULL;
2093
const DBnXS *DB = lookupDBnXSByEncoding(Val);
2094
Name = DB ? DB->Name : NULL;
2095
2096
if (Name) {
2097
SStream_concat0(O, Name);
2098
2099
if (MI->csh->detail) {
2100
#ifndef CAPSTONE_DIET
2101
uint8_t access;
2102
2103
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2104
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
2105
MI->ac_idx++;
2106
#endif
2107
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_BARRIER;
2108
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].barrier = Val;
2109
MI->flat_insn->detail->arm64.op_count++;
2110
}
2111
}
2112
else {
2113
printUInt32Bang(O, Val);
2114
2115
if (MI->csh->detail) {
2116
#ifndef CAPSTONE_DIET
2117
uint8_t access;
2118
2119
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2120
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
2121
MI->ac_idx++;
2122
#endif
2123
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
2124
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = Val;
2125
MI->flat_insn->detail->arm64.op_count++;
2126
}
2127
}
2128
}
2129
2130
static void printMRSSystemRegister(MCInst *MI, unsigned OpNum, SStream *O)
2131
{
2132
unsigned Val = (unsigned)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2133
const SysReg *Reg = lookupSysRegByEncoding(Val);
2134
2135
// Horrible hack for the one register that has identical encodings but
2136
// different names in MSR and MRS. Because of this, one of MRS and MSR is
2137
// going to get the wrong entry
2138
if (Val == ARM64_SYSREG_DBGDTRRX_EL0) {
2139
SStream_concat0(O, "dbgdtrrx_el0");
2140
2141
if (MI->csh->detail) {
2142
#ifndef CAPSTONE_DIET
2143
uint8_t access;
2144
2145
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2146
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
2147
MI->ac_idx++;
2148
#endif
2149
2150
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_SYS;
2151
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].sys = Val;
2152
MI->flat_insn->detail->arm64.op_count++;
2153
}
2154
2155
return;
2156
}
2157
2158
// Another hack for a register which has an alternative name which is not an alias,
2159
// and is not in the Armv9-A documentation.
2160
if( Val == ARM64_SYSREG_VSCTLR_EL2){
2161
SStream_concat0(O, "ttbr0_el2");
2162
2163
if (MI->csh->detail) {
2164
#ifndef CAPSTONE_DIET
2165
uint8_t access;
2166
2167
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2168
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
2169
MI->ac_idx++;
2170
#endif
2171
2172
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_SYS;
2173
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].sys = Val;
2174
MI->flat_insn->detail->arm64.op_count++;
2175
}
2176
2177
return;
2178
}
2179
2180
// if (Reg && Reg->Readable && Reg->haveFeatures(STI.getFeatureBits()))
2181
if (Reg && Reg->Readable) {
2182
SStream_concat0(O, Reg->Name);
2183
2184
if (MI->csh->detail) {
2185
#ifndef CAPSTONE_DIET
2186
uint8_t access;
2187
2188
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2189
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
2190
MI->ac_idx++;
2191
#endif
2192
2193
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_SYS;
2194
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].sys = Reg->Encoding;
2195
MI->flat_insn->detail->arm64.op_count++;
2196
}
2197
} else {
2198
char result[128];
2199
2200
AArch64SysReg_genericRegisterString(Val, result);
2201
SStream_concat0(O, result);
2202
2203
if (MI->csh->detail) {
2204
#ifndef CAPSTONE_DIET
2205
uint8_t access;
2206
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2207
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
2208
MI->ac_idx++;
2209
#endif
2210
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG_MRS;
2211
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = Val;
2212
MI->flat_insn->detail->arm64.op_count++;
2213
}
2214
}
2215
}
2216
2217
static void printMSRSystemRegister(MCInst *MI, unsigned OpNum, SStream *O)
2218
{
2219
unsigned Val = (unsigned)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2220
const SysReg *Reg = lookupSysRegByEncoding(Val);
2221
2222
// Horrible hack for the one register that has identical encodings but
2223
// different names in MSR and MRS. Because of this, one of MRS and MSR is
2224
// going to get the wrong entry
2225
if (Val == ARM64_SYSREG_DBGDTRTX_EL0) {
2226
SStream_concat0(O, "dbgdtrtx_el0");
2227
2228
if (MI->csh->detail) {
2229
#ifndef CAPSTONE_DIET
2230
uint8_t access;
2231
2232
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2233
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
2234
MI->ac_idx++;
2235
#endif
2236
2237
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_SYS;
2238
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].sys = Val;
2239
MI->flat_insn->detail->arm64.op_count++;
2240
}
2241
2242
return;
2243
}
2244
2245
// Another hack for a register which has an alternative name which is not an alias,
2246
// and is not in the Armv9-A documentation.
2247
if( Val == ARM64_SYSREG_VSCTLR_EL2){
2248
SStream_concat0(O, "ttbr0_el2");
2249
2250
if (MI->csh->detail) {
2251
#ifndef CAPSTONE_DIET
2252
uint8_t access;
2253
2254
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2255
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
2256
MI->ac_idx++;
2257
#endif
2258
2259
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_SYS;
2260
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].sys = Val;
2261
MI->flat_insn->detail->arm64.op_count++;
2262
}
2263
2264
return;
2265
}
2266
2267
// if (Reg && Reg->Writeable && Reg->haveFeatures(STI.getFeatureBits()))
2268
if (Reg && Reg->Writeable) {
2269
SStream_concat0(O, Reg->Name);
2270
2271
if (MI->csh->detail) {
2272
#ifndef CAPSTONE_DIET
2273
uint8_t access;
2274
2275
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2276
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
2277
MI->ac_idx++;
2278
#endif
2279
2280
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_SYS;
2281
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].sys = Reg->Encoding;
2282
MI->flat_insn->detail->arm64.op_count++;
2283
}
2284
} else {
2285
char result[128];
2286
2287
AArch64SysReg_genericRegisterString(Val, result);
2288
SStream_concat0(O, result);
2289
2290
if (MI->csh->detail) {
2291
#ifndef CAPSTONE_DIET
2292
uint8_t access;
2293
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2294
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
2295
MI->ac_idx++;
2296
#endif
2297
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG_MRS;
2298
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = Val;
2299
MI->flat_insn->detail->arm64.op_count++;
2300
}
2301
}
2302
}
2303
2304
static void printSystemPStateField(MCInst *MI, unsigned OpNum, SStream *O)
2305
{
2306
unsigned Val = (unsigned)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2307
2308
const PState *PState = lookupPStateByEncoding(Val);
2309
2310
if (PState) {
2311
SStream_concat0(O, PState->Name);
2312
2313
if (MI->csh->detail) {
2314
#ifndef CAPSTONE_DIET
2315
uint8_t access;
2316
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2317
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
2318
MI->ac_idx++;
2319
#endif
2320
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_PSTATE;
2321
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].pstate = Val;
2322
MI->flat_insn->detail->arm64.op_count++;
2323
}
2324
} else {
2325
printUInt32Bang(O, Val);
2326
2327
if (MI->csh->detail) {
2328
#ifndef CAPSTONE_DIET
2329
unsigned char access;
2330
2331
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2332
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
2333
MI->ac_idx++;
2334
#endif
2335
2336
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
2337
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = Val;
2338
MI->flat_insn->detail->arm64.op_count++;
2339
}
2340
}
2341
}
2342
2343
static void printSIMDType10Operand(MCInst *MI, unsigned OpNum, SStream *O)
2344
{
2345
uint8_t RawVal = (uint8_t)MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2346
uint64_t Val = AArch64_AM_decodeAdvSIMDModImmType10(RawVal);
2347
2348
SStream_concat(O, "#%#016llx", Val);
2349
2350
if (MI->csh->detail) {
2351
#ifndef CAPSTONE_DIET
2352
unsigned char access;
2353
2354
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2355
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
2356
MI->ac_idx++;
2357
#endif
2358
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
2359
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = Val;
2360
MI->flat_insn->detail->arm64.op_count++;
2361
}
2362
}
2363
2364
static void printComplexRotationOp(MCInst *MI, unsigned OpNum, SStream *O, int64_t Angle, int64_t Remainder)
2365
{
2366
unsigned int Val = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2367
printInt64Bang(O, (Val * Angle) + Remainder);
2368
op_addImm(MI, (Val * Angle) + Remainder);
2369
}
2370
2371
static void printSVCROp(MCInst *MI, unsigned OpNum, SStream *O)
2372
{
2373
MCOperand *MO = MCInst_getOperand(MI, OpNum);
2374
// assert(MCOperand_isImm(MO) && "Unexpected operand type!");
2375
unsigned svcrop = MCOperand_getImm(MO);
2376
const SVCR *svcr = lookupSVCRByEncoding(svcrop);
2377
// assert(svcr && "Unexpected SVCR operand!");
2378
SStream_concat0(O, svcr->Name);
2379
2380
if (MI->csh->detail) {
2381
#ifndef CAPSTONE_DIET
2382
uint8_t access;
2383
2384
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2385
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
2386
MI->ac_idx++;
2387
#endif
2388
2389
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_SVCR;
2390
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].sys = (unsigned)ARM64_SYSREG_SVCR;
2391
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].svcr = svcr->Encoding;
2392
MI->flat_insn->detail->arm64.op_count++;
2393
}
2394
}
2395
2396
static void printMatrix(MCInst *MI, unsigned OpNum, SStream *O, int EltSize)
2397
{
2398
MCOperand *RegOp = MCInst_getOperand(MI, OpNum);
2399
// assert(MCOperand_isReg(RegOp) && "Unexpected operand type!");
2400
unsigned Reg = MCOperand_getReg(RegOp);
2401
2402
SStream_concat0(O, getRegisterName(Reg, AArch64_NoRegAltName));
2403
const char *sizeStr = "";
2404
switch (EltSize) {
2405
case 0:
2406
sizeStr = "";
2407
break;
2408
case 8:
2409
sizeStr = ".b";
2410
break;
2411
case 16:
2412
sizeStr = ".h";
2413
break;
2414
case 32:
2415
sizeStr = ".s";
2416
break;
2417
case 64:
2418
sizeStr = ".d";
2419
break;
2420
case 128:
2421
sizeStr = ".q";
2422
break;
2423
default:
2424
break;
2425
// llvm_unreachable("Unsupported element size");
2426
}
2427
SStream_concat0(O, sizeStr);
2428
2429
if (MI->csh->detail) {
2430
#ifndef CAPSTONE_DIET
2431
uint8_t access;
2432
2433
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2434
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
2435
MI->ac_idx++;
2436
#endif
2437
2438
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
2439
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = Reg;
2440
MI->flat_insn->detail->arm64.op_count++;
2441
}
2442
}
2443
2444
static void printMatrixIndex(MCInst *MI, unsigned OpNum, SStream *O)
2445
{
2446
int64_t imm = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2447
printInt64(O, imm);
2448
2449
if (MI->csh->detail) {
2450
if (MI->csh->doing_SME_Index) {
2451
// Access op_count-1 as We want to add info to previous operand, not create a new one
2452
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count-1].sme_index.disp = imm;
2453
}
2454
}
2455
}
2456
2457
static void printMatrixTile(MCInst *MI, unsigned OpNum, SStream *O)
2458
{
2459
MCOperand *RegOp = MCInst_getOperand(MI, OpNum);
2460
// assert(MCOperand_isReg(RegOp) && "Unexpected operand type!");
2461
unsigned Reg = MCOperand_getReg(RegOp);
2462
SStream_concat0(O, getRegisterName(Reg, AArch64_NoRegAltName));
2463
2464
if (MI->csh->detail) {
2465
#ifndef CAPSTONE_DIET
2466
uint8_t access;
2467
2468
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2469
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
2470
MI->ac_idx++;
2471
#endif
2472
2473
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
2474
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = Reg;
2475
MI->flat_insn->detail->arm64.op_count++;
2476
}
2477
}
2478
2479
static void printMatrixTileVector(MCInst *MI, unsigned OpNum, SStream *O, bool IsVertical)
2480
{
2481
MCOperand *RegOp = MCInst_getOperand(MI, OpNum);
2482
// assert(MCOperand_isReg(RegOp) && "Unexpected operand type!");
2483
unsigned Reg = MCOperand_getReg(RegOp);
2484
#ifndef CAPSTONE_DIET
2485
const char *RegName = getRegisterName(Reg, AArch64_NoRegAltName);
2486
2487
const size_t strLn = strlen(RegName);
2488
// +2 for extra chars, + 1 for null char \0
2489
char *RegNameNew = cs_mem_malloc(sizeof(char) * (strLn + 2 + 1));
2490
int index = 0, i;
2491
for (i = 0; i < (strLn + 2); i++){
2492
if(RegName[i] != '.'){
2493
RegNameNew[index] = RegName[i];
2494
index++;
2495
}
2496
else{
2497
RegNameNew[index] = IsVertical ? 'v' : 'h';
2498
RegNameNew[index + 1] = '.';
2499
index += 2;
2500
}
2501
}
2502
SStream_concat0(O, RegNameNew);
2503
#endif
2504
2505
if (MI->csh->detail) {
2506
#ifndef CAPSTONE_DIET
2507
uint8_t access;
2508
2509
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2510
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
2511
MI->ac_idx++;
2512
#endif
2513
2514
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
2515
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = Reg;
2516
MI->flat_insn->detail->arm64.op_count++;
2517
}
2518
#ifndef CAPSTONE_DIET
2519
cs_mem_free(RegNameNew);
2520
#endif
2521
}
2522
2523
static const unsigned MatrixZADRegisterTable[] = {
2524
AArch64_ZAD0, AArch64_ZAD1, AArch64_ZAD2, AArch64_ZAD3,
2525
AArch64_ZAD4, AArch64_ZAD5, AArch64_ZAD6, AArch64_ZAD7
2526
};
2527
2528
static void printMatrixTileList(MCInst *MI, unsigned OpNum, SStream *O){
2529
unsigned MaxRegs = 8;
2530
unsigned RegMask = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2531
2532
unsigned NumRegs = 0, I;
2533
for (I = 0; I < MaxRegs; ++I)
2534
if ((RegMask & (1 << I)) != 0)
2535
++NumRegs;
2536
2537
SStream_concat0(O, "{");
2538
unsigned Printed = 0, J;
2539
for (J = 0; J < MaxRegs; ++J) {
2540
unsigned Reg = RegMask & (1 << J);
2541
if (Reg == 0)
2542
continue;
2543
SStream_concat0(O, getRegisterName(MatrixZADRegisterTable[J], AArch64_NoRegAltName));
2544
2545
if (MI->csh->detail) {
2546
#ifndef CAPSTONE_DIET
2547
uint8_t access;
2548
2549
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2550
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
2551
MI->ac_idx++;
2552
#endif
2553
2554
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
2555
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = MatrixZADRegisterTable[J];
2556
MI->flat_insn->detail->arm64.op_count++;
2557
}
2558
2559
if (Printed + 1 != NumRegs)
2560
SStream_concat0(O, ", ");
2561
++Printed;
2562
}
2563
SStream_concat0(O, "}");
2564
}
2565
2566
static void printSVEPattern(MCInst *MI, unsigned OpNum, SStream *O)
2567
{
2568
unsigned Val = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2569
2570
const SVEPREDPAT *Pat = lookupSVEPREDPATByEncoding(Val);
2571
if (Pat)
2572
SStream_concat0(O, Pat->Name);
2573
else
2574
printUInt32Bang(O, Val);
2575
}
2576
2577
// default suffix = 0
2578
static void printSVERegOp(MCInst *MI, unsigned OpNum, SStream *O, char suffix)
2579
{
2580
unsigned int Reg;
2581
2582
#if 0
2583
switch (suffix) {
2584
case 0:
2585
case 'b':
2586
case 'h':
2587
case 's':
2588
case 'd':
2589
case 'q':
2590
break;
2591
default:
2592
// llvm_unreachable("Invalid kind specifier.");
2593
}
2594
#endif
2595
2596
Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2597
2598
if (MI->csh->detail) {
2599
#ifndef CAPSTONE_DIET
2600
uint8_t access;
2601
2602
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2603
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
2604
MI->ac_idx++;
2605
#endif
2606
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
2607
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = Reg;
2608
MI->flat_insn->detail->arm64.op_count++;
2609
}
2610
2611
SStream_concat0(O, getRegisterName(Reg, AArch64_NoRegAltName));
2612
2613
if (suffix != '\0')
2614
SStream_concat(O, ".%c", suffix);
2615
}
2616
2617
static void printImmSVE16(int16_t Val, SStream *O)
2618
{
2619
printUInt32Bang(O, Val);
2620
}
2621
2622
static void printImmSVE32(int32_t Val, SStream *O)
2623
{
2624
printUInt32Bang(O, Val);
2625
}
2626
2627
static void printImmSVE64(int64_t Val, SStream *O)
2628
{
2629
printUInt64Bang(O, Val);
2630
}
2631
2632
static void printImm8OptLsl32(MCInst *MI, unsigned OpNum, SStream *O)
2633
{
2634
unsigned UnscaledVal = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2635
unsigned Shift = MCOperand_getImm(MCInst_getOperand(MI, OpNum + 1));
2636
uint32_t Val;
2637
2638
// assert(AArch64_AM::getShiftType(Shift) == AArch64_AM::LSL &&
2639
// "Unexepected shift type!");
2640
2641
// #0 lsl #8 is never pretty printed
2642
if ((UnscaledVal == 0) && (AArch64_AM_getShiftValue(Shift) != 0)) {
2643
printUInt32Bang(O, UnscaledVal);
2644
printShifter(MI, OpNum + 1, O);
2645
return;
2646
}
2647
2648
Val = UnscaledVal * (1 << AArch64_AM_getShiftValue(Shift));
2649
printImmSVE32(Val, O);
2650
}
2651
2652
static void printImm8OptLsl64(MCInst *MI, unsigned OpNum, SStream *O)
2653
{
2654
unsigned UnscaledVal = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2655
unsigned Shift = MCOperand_getImm(MCInst_getOperand(MI, OpNum + 1));
2656
uint64_t Val;
2657
2658
// assert(AArch64_AM::getShiftType(Shift) == AArch64_AM::LSL &&
2659
// "Unexepected shift type!");
2660
2661
// #0 lsl #8 is never pretty printed
2662
if ((UnscaledVal == 0) && (AArch64_AM_getShiftValue(Shift) != 0)) {
2663
printUInt32Bang(O, UnscaledVal);
2664
printShifter(MI, OpNum + 1, O);
2665
return;
2666
}
2667
2668
Val = UnscaledVal * (1 << AArch64_AM_getShiftValue(Shift));
2669
printImmSVE64(Val, O);
2670
}
2671
2672
static void printSVELogicalImm16(MCInst *MI, unsigned OpNum, SStream *O)
2673
{
2674
uint64_t Val = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2675
uint64_t PrintVal = AArch64_AM_decodeLogicalImmediate(Val, 64);
2676
2677
// Prefer the default format for 16bit values, hex otherwise.
2678
printImmSVE16(PrintVal, O);
2679
}
2680
2681
static void printSVELogicalImm32(MCInst *MI, unsigned OpNum, SStream *O)
2682
{
2683
uint64_t Val = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2684
uint64_t PrintVal = AArch64_AM_decodeLogicalImmediate(Val, 64);
2685
2686
// Prefer the default format for 16bit values, hex otherwise.
2687
if ((uint16_t)PrintVal == (uint32_t)PrintVal)
2688
printImmSVE16(PrintVal, O);
2689
else
2690
printUInt64Bang(O, PrintVal);
2691
}
2692
2693
static void printSVELogicalImm64(MCInst *MI, unsigned OpNum, SStream *O)
2694
{
2695
uint64_t Val = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2696
uint64_t PrintVal = AArch64_AM_decodeLogicalImmediate(Val, 64);
2697
2698
printImmSVE64(PrintVal, O);
2699
}
2700
2701
static void printZPRasFPR(MCInst *MI, unsigned OpNum, SStream *O, int Width)
2702
{
2703
unsigned int Base, Reg;
2704
2705
switch (Width) {
2706
default: // llvm_unreachable("Unsupported width");
2707
case 8: Base = AArch64_B0; break;
2708
case 16: Base = AArch64_H0; break;
2709
case 32: Base = AArch64_S0; break;
2710
case 64: Base = AArch64_D0; break;
2711
case 128: Base = AArch64_Q0; break;
2712
}
2713
2714
Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum)) - AArch64_Z0 + Base;
2715
2716
SStream_concat0(O, getRegisterName(Reg, AArch64_NoRegAltName));
2717
2718
if (MI->csh->detail) {
2719
#ifndef CAPSTONE_DIET
2720
uint8_t access;
2721
2722
access = get_op_access(MI->csh, MCInst_getOpcode(MI), MI->ac_idx);
2723
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].access = access;
2724
MI->ac_idx++;
2725
#endif
2726
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
2727
MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = Reg;
2728
MI->flat_insn->detail->arm64.op_count++;
2729
}
2730
}
2731
2732
static void printExactFPImm(MCInst *MI, unsigned OpNum, SStream *O, unsigned ImmIs0, unsigned ImmIs1)
2733
{
2734
const ExactFPImm *Imm0Desc = lookupExactFPImmByEnum(ImmIs0);
2735
const ExactFPImm *Imm1Desc = lookupExactFPImmByEnum(ImmIs1);
2736
unsigned Val = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2737
2738
SStream_concat0(O, Val ? Imm1Desc->Repr : Imm0Desc->Repr);
2739
}
2740
2741
static void printGPR64as32(MCInst *MI, unsigned OpNum, SStream *O)
2742
{
2743
unsigned int Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2744
2745
SStream_concat0(O, getRegisterName(getWRegFromXReg(Reg), AArch64_NoRegAltName));
2746
}
2747
2748
static void printGPR64x8(MCInst *MI, unsigned OpNum, SStream *O)
2749
{
2750
unsigned int Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2751
2752
SStream_concat0(O, getRegisterName(MCRegisterInfo_getSubReg(MI->MRI, Reg, AArch64_x8sub_0), AArch64_NoRegAltName));
2753
}
2754
2755
#define PRINT_ALIAS_INSTR
2756
#include "AArch64GenAsmWriter.inc"
2757
#include "AArch64GenRegisterName.inc"
2758
2759
void AArch64_post_printer(csh handle, cs_insn *flat_insn, char *insn_asm, MCInst *mci)
2760
{
2761
if (((cs_struct *)handle)->detail != CS_OPT_ON)
2762
return;
2763
2764
if (mci->csh->detail) {
2765
unsigned opcode = MCInst_getOpcode(mci);
2766
2767
switch (opcode) {
2768
default:
2769
break;
2770
case AArch64_LD1Fourv16b_POST:
2771
case AArch64_LD1Fourv1d_POST:
2772
case AArch64_LD1Fourv2d_POST:
2773
case AArch64_LD1Fourv2s_POST:
2774
case AArch64_LD1Fourv4h_POST:
2775
case AArch64_LD1Fourv4s_POST:
2776
case AArch64_LD1Fourv8b_POST:
2777
case AArch64_LD1Fourv8h_POST:
2778
case AArch64_LD1Onev16b_POST:
2779
case AArch64_LD1Onev1d_POST:
2780
case AArch64_LD1Onev2d_POST:
2781
case AArch64_LD1Onev2s_POST:
2782
case AArch64_LD1Onev4h_POST:
2783
case AArch64_LD1Onev4s_POST:
2784
case AArch64_LD1Onev8b_POST:
2785
case AArch64_LD1Onev8h_POST:
2786
case AArch64_LD1Rv16b_POST:
2787
case AArch64_LD1Rv1d_POST:
2788
case AArch64_LD1Rv2d_POST:
2789
case AArch64_LD1Rv2s_POST:
2790
case AArch64_LD1Rv4h_POST:
2791
case AArch64_LD1Rv4s_POST:
2792
case AArch64_LD1Rv8b_POST:
2793
case AArch64_LD1Rv8h_POST:
2794
case AArch64_LD1Threev16b_POST:
2795
case AArch64_LD1Threev1d_POST:
2796
case AArch64_LD1Threev2d_POST:
2797
case AArch64_LD1Threev2s_POST:
2798
case AArch64_LD1Threev4h_POST:
2799
case AArch64_LD1Threev4s_POST:
2800
case AArch64_LD1Threev8b_POST:
2801
case AArch64_LD1Threev8h_POST:
2802
case AArch64_LD1Twov16b_POST:
2803
case AArch64_LD1Twov1d_POST:
2804
case AArch64_LD1Twov2d_POST:
2805
case AArch64_LD1Twov2s_POST:
2806
case AArch64_LD1Twov4h_POST:
2807
case AArch64_LD1Twov4s_POST:
2808
case AArch64_LD1Twov8b_POST:
2809
case AArch64_LD1Twov8h_POST:
2810
case AArch64_LD1i16_POST:
2811
case AArch64_LD1i32_POST:
2812
case AArch64_LD1i64_POST:
2813
case AArch64_LD1i8_POST:
2814
case AArch64_LD2Rv16b_POST:
2815
case AArch64_LD2Rv1d_POST:
2816
case AArch64_LD2Rv2d_POST:
2817
case AArch64_LD2Rv2s_POST:
2818
case AArch64_LD2Rv4h_POST:
2819
case AArch64_LD2Rv4s_POST:
2820
case AArch64_LD2Rv8b_POST:
2821
case AArch64_LD2Rv8h_POST:
2822
case AArch64_LD2Twov16b_POST:
2823
case AArch64_LD2Twov2d_POST:
2824
case AArch64_LD2Twov2s_POST:
2825
case AArch64_LD2Twov4h_POST:
2826
case AArch64_LD2Twov4s_POST:
2827
case AArch64_LD2Twov8b_POST:
2828
case AArch64_LD2Twov8h_POST:
2829
case AArch64_LD2i16_POST:
2830
case AArch64_LD2i32_POST:
2831
case AArch64_LD2i64_POST:
2832
case AArch64_LD2i8_POST:
2833
case AArch64_LD3Rv16b_POST:
2834
case AArch64_LD3Rv1d_POST:
2835
case AArch64_LD3Rv2d_POST:
2836
case AArch64_LD3Rv2s_POST:
2837
case AArch64_LD3Rv4h_POST:
2838
case AArch64_LD3Rv4s_POST:
2839
case AArch64_LD3Rv8b_POST:
2840
case AArch64_LD3Rv8h_POST:
2841
case AArch64_LD3Threev16b_POST:
2842
case AArch64_LD3Threev2d_POST:
2843
case AArch64_LD3Threev2s_POST:
2844
case AArch64_LD3Threev4h_POST:
2845
case AArch64_LD3Threev4s_POST:
2846
case AArch64_LD3Threev8b_POST:
2847
case AArch64_LD3Threev8h_POST:
2848
case AArch64_LD3i16_POST:
2849
case AArch64_LD3i32_POST:
2850
case AArch64_LD3i64_POST:
2851
case AArch64_LD3i8_POST:
2852
case AArch64_LD4Fourv16b_POST:
2853
case AArch64_LD4Fourv2d_POST:
2854
case AArch64_LD4Fourv2s_POST:
2855
case AArch64_LD4Fourv4h_POST:
2856
case AArch64_LD4Fourv4s_POST:
2857
case AArch64_LD4Fourv8b_POST:
2858
case AArch64_LD4Fourv8h_POST:
2859
case AArch64_LD4Rv16b_POST:
2860
case AArch64_LD4Rv1d_POST:
2861
case AArch64_LD4Rv2d_POST:
2862
case AArch64_LD4Rv2s_POST:
2863
case AArch64_LD4Rv4h_POST:
2864
case AArch64_LD4Rv4s_POST:
2865
case AArch64_LD4Rv8b_POST:
2866
case AArch64_LD4Rv8h_POST:
2867
case AArch64_LD4i16_POST:
2868
case AArch64_LD4i32_POST:
2869
case AArch64_LD4i64_POST:
2870
case AArch64_LD4i8_POST:
2871
case AArch64_LDRBBpost:
2872
case AArch64_LDRBpost:
2873
case AArch64_LDRDpost:
2874
case AArch64_LDRHHpost:
2875
case AArch64_LDRHpost:
2876
case AArch64_LDRQpost:
2877
case AArch64_LDPDpost:
2878
case AArch64_LDPQpost:
2879
case AArch64_LDPSWpost:
2880
case AArch64_LDPSpost:
2881
case AArch64_LDPWpost:
2882
case AArch64_LDPXpost:
2883
case AArch64_ST1Fourv16b_POST:
2884
case AArch64_ST1Fourv1d_POST:
2885
case AArch64_ST1Fourv2d_POST:
2886
case AArch64_ST1Fourv2s_POST:
2887
case AArch64_ST1Fourv4h_POST:
2888
case AArch64_ST1Fourv4s_POST:
2889
case AArch64_ST1Fourv8b_POST:
2890
case AArch64_ST1Fourv8h_POST:
2891
case AArch64_ST1Onev16b_POST:
2892
case AArch64_ST1Onev1d_POST:
2893
case AArch64_ST1Onev2d_POST:
2894
case AArch64_ST1Onev2s_POST:
2895
case AArch64_ST1Onev4h_POST:
2896
case AArch64_ST1Onev4s_POST:
2897
case AArch64_ST1Onev8b_POST:
2898
case AArch64_ST1Onev8h_POST:
2899
case AArch64_ST1Threev16b_POST:
2900
case AArch64_ST1Threev1d_POST:
2901
case AArch64_ST1Threev2d_POST:
2902
case AArch64_ST1Threev2s_POST:
2903
case AArch64_ST1Threev4h_POST:
2904
case AArch64_ST1Threev4s_POST:
2905
case AArch64_ST1Threev8b_POST:
2906
case AArch64_ST1Threev8h_POST:
2907
case AArch64_ST1Twov16b_POST:
2908
case AArch64_ST1Twov1d_POST:
2909
case AArch64_ST1Twov2d_POST:
2910
case AArch64_ST1Twov2s_POST:
2911
case AArch64_ST1Twov4h_POST:
2912
case AArch64_ST1Twov4s_POST:
2913
case AArch64_ST1Twov8b_POST:
2914
case AArch64_ST1Twov8h_POST:
2915
case AArch64_ST1i16_POST:
2916
case AArch64_ST1i32_POST:
2917
case AArch64_ST1i64_POST:
2918
case AArch64_ST1i8_POST:
2919
case AArch64_ST2GPostIndex:
2920
case AArch64_ST2Twov16b_POST:
2921
case AArch64_ST2Twov2d_POST:
2922
case AArch64_ST2Twov2s_POST:
2923
case AArch64_ST2Twov4h_POST:
2924
case AArch64_ST2Twov4s_POST:
2925
case AArch64_ST2Twov8b_POST:
2926
case AArch64_ST2Twov8h_POST:
2927
case AArch64_ST2i16_POST:
2928
case AArch64_ST2i32_POST:
2929
case AArch64_ST2i64_POST:
2930
case AArch64_ST2i8_POST:
2931
case AArch64_ST3Threev16b_POST:
2932
case AArch64_ST3Threev2d_POST:
2933
case AArch64_ST3Threev2s_POST:
2934
case AArch64_ST3Threev4h_POST:
2935
case AArch64_ST3Threev4s_POST:
2936
case AArch64_ST3Threev8b_POST:
2937
case AArch64_ST3Threev8h_POST:
2938
case AArch64_ST3i16_POST:
2939
case AArch64_ST3i32_POST:
2940
case AArch64_ST3i64_POST:
2941
case AArch64_ST3i8_POST:
2942
case AArch64_ST4Fourv16b_POST:
2943
case AArch64_ST4Fourv2d_POST:
2944
case AArch64_ST4Fourv2s_POST:
2945
case AArch64_ST4Fourv4h_POST:
2946
case AArch64_ST4Fourv4s_POST:
2947
case AArch64_ST4Fourv8b_POST:
2948
case AArch64_ST4Fourv8h_POST:
2949
case AArch64_ST4i16_POST:
2950
case AArch64_ST4i32_POST:
2951
case AArch64_ST4i64_POST:
2952
case AArch64_ST4i8_POST:
2953
case AArch64_STPDpost:
2954
case AArch64_STPQpost:
2955
case AArch64_STPSpost:
2956
case AArch64_STPWpost:
2957
case AArch64_STPXpost:
2958
case AArch64_STRBBpost:
2959
case AArch64_STRBpost:
2960
case AArch64_STRDpost:
2961
case AArch64_STRHHpost:
2962
case AArch64_STRHpost:
2963
case AArch64_STRQpost:
2964
case AArch64_STRSpost:
2965
case AArch64_STRWpost:
2966
case AArch64_STRXpost:
2967
case AArch64_STZ2GPostIndex:
2968
case AArch64_STZGPostIndex:
2969
case AArch64_STGPostIndex:
2970
case AArch64_STGPpost:
2971
case AArch64_LDRSBWpost:
2972
case AArch64_LDRSBXpost:
2973
case AArch64_LDRSHWpost:
2974
case AArch64_LDRSHXpost:
2975
case AArch64_LDRSWpost:
2976
case AArch64_LDRSpost:
2977
case AArch64_LDRWpost:
2978
case AArch64_LDRXpost:
2979
flat_insn->detail->arm64.writeback = true;
2980
flat_insn->detail->arm64.post_index = true;
2981
break;
2982
case AArch64_LDRAAwriteback:
2983
case AArch64_LDRABwriteback:
2984
case AArch64_ST2GPreIndex:
2985
case AArch64_LDPDpre:
2986
case AArch64_LDPQpre:
2987
case AArch64_LDPSWpre:
2988
case AArch64_LDPSpre:
2989
case AArch64_LDPWpre:
2990
case AArch64_LDPXpre:
2991
case AArch64_LDRBBpre:
2992
case AArch64_LDRBpre:
2993
case AArch64_LDRDpre:
2994
case AArch64_LDRHHpre:
2995
case AArch64_LDRHpre:
2996
case AArch64_LDRQpre:
2997
case AArch64_LDRSBWpre:
2998
case AArch64_LDRSBXpre:
2999
case AArch64_LDRSHWpre:
3000
case AArch64_LDRSHXpre:
3001
case AArch64_LDRSWpre:
3002
case AArch64_LDRSpre:
3003
case AArch64_LDRWpre:
3004
case AArch64_LDRXpre:
3005
case AArch64_STGPreIndex:
3006
case AArch64_STPDpre:
3007
case AArch64_STPQpre:
3008
case AArch64_STPSpre:
3009
case AArch64_STPWpre:
3010
case AArch64_STPXpre:
3011
case AArch64_STRBBpre:
3012
case AArch64_STRBpre:
3013
case AArch64_STRDpre:
3014
case AArch64_STRHHpre:
3015
case AArch64_STRHpre:
3016
case AArch64_STRQpre:
3017
case AArch64_STRSpre:
3018
case AArch64_STRWpre:
3019
case AArch64_STRXpre:
3020
case AArch64_STZ2GPreIndex:
3021
case AArch64_STZGPreIndex:
3022
case AArch64_STGPpre:
3023
flat_insn->detail->arm64.writeback = true;
3024
break;
3025
}
3026
}
3027
}
3028
3029
#endif
3030
3031