Coverage Report

Created: 2026-08-31 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/capstonenext/arch/AArch64/AArch64Mapping.c
Line
Count
Source
1
/* Capstone Disassembly Engine */
2
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
3
4
#ifdef CAPSTONE_HAS_AARCH64
5
6
#include <stdio.h> // debug
7
#include <string.h>
8
9
#include "capstone/aarch64.h"
10
11
#include "../../cs_simple_types.h"
12
#include "../../Mapping.h"
13
#include "../../MathExtras.h"
14
#include "../../utils.h"
15
16
#include "AArch64AddressingModes.h"
17
#include "AArch64BaseInfo.h"
18
#include "AArch64DisassemblerExtension.h"
19
#include "AArch64Linkage.h"
20
#include "AArch64Mapping.h"
21
22
2.31k
#define CHAR(c) #c[0]
23
24
static float aarch64_exact_fp_to_fp(aarch64_exactfpimm exact)
25
6.75k
{
26
6.75k
  switch (exact) {
27
0
  default:
28
0
    CS_ASSERT(0 && "Not handled.");
29
0
    return 999.0;
30
144
  case AARCH64_EXACTFPIMM_HALF:
31
144
    return 0.5;
32
95
  case AARCH64_EXACTFPIMM_ONE:
33
95
    return 1.0;
34
29
  case AARCH64_EXACTFPIMM_TWO:
35
29
    return 2.0;
36
6.48k
  case AARCH64_EXACTFPIMM_ZERO:
37
6.48k
    return 0.0;
38
6.75k
  }
39
6.75k
}
40
41
#ifndef CAPSTONE_DIET
42
static const aarch64_reg aarch64_flag_regs[] = {
43
  AARCH64_REG_NZCV,
44
};
45
46
static const aarch64_sysreg aarch64_flag_sys_regs[] = {
47
  AARCH64_SYSREG_NZCV, AARCH64_SYSREG_PMOVSCLR_EL0,
48
  AARCH64_SYSREG_PMOVSSET_EL0, AARCH64_SYSREG_SPMOVSCLR_EL0,
49
  AARCH64_SYSREG_SPMOVSSET_EL0
50
};
51
#endif // CAPSTONE_DIET
52
53
static AArch64Layout_VectorLayout sme_reg_to_vas(aarch64_reg reg)
54
0
{
55
0
  switch (reg) {
56
0
  default:
57
0
    return AARCH64LAYOUT_INVALID;
58
0
  case AARCH64_REG_ZAB0:
59
0
    return AARCH64LAYOUT_VL_B;
60
0
  case AARCH64_REG_ZAH0:
61
0
  case AARCH64_REG_ZAH1:
62
0
    return AARCH64LAYOUT_VL_H;
63
0
  case AARCH64_REG_ZAS0:
64
0
  case AARCH64_REG_ZAS1:
65
0
  case AARCH64_REG_ZAS2:
66
0
  case AARCH64_REG_ZAS3:
67
0
    return AARCH64LAYOUT_VL_S;
68
0
  case AARCH64_REG_ZAD0:
69
0
  case AARCH64_REG_ZAD1:
70
0
  case AARCH64_REG_ZAD2:
71
0
  case AARCH64_REG_ZAD3:
72
0
  case AARCH64_REG_ZAD4:
73
0
  case AARCH64_REG_ZAD5:
74
0
  case AARCH64_REG_ZAD6:
75
0
  case AARCH64_REG_ZAD7:
76
0
    return AARCH64LAYOUT_VL_D;
77
0
  case AARCH64_REG_ZAQ0:
78
0
  case AARCH64_REG_ZAQ1:
79
0
  case AARCH64_REG_ZAQ2:
80
0
  case AARCH64_REG_ZAQ3:
81
0
  case AARCH64_REG_ZAQ4:
82
0
  case AARCH64_REG_ZAQ5:
83
0
  case AARCH64_REG_ZAQ6:
84
0
  case AARCH64_REG_ZAQ7:
85
0
  case AARCH64_REG_ZAQ8:
86
0
  case AARCH64_REG_ZAQ9:
87
0
  case AARCH64_REG_ZAQ10:
88
0
  case AARCH64_REG_ZAQ11:
89
0
  case AARCH64_REG_ZAQ12:
90
0
  case AARCH64_REG_ZAQ13:
91
0
  case AARCH64_REG_ZAQ14:
92
0
  case AARCH64_REG_ZAQ15:
93
0
    return AARCH64LAYOUT_VL_Q;
94
0
  case AARCH64_REG_ZA:
95
0
    return AARCH64LAYOUT_VL_COMPLETE;
96
0
  }
97
0
}
98
99
void AArch64_init_mri(MCRegisterInfo *MRI)
100
9.53k
{
101
9.53k
  MCRegisterInfo_InitMCRegisterInfo(
102
9.53k
    MRI, AArch64RegDesc, AARCH64_REG_ENDING, 0, 0,
103
9.53k
    AArch64MCRegisterClasses, ARR_SIZE(AArch64MCRegisterClasses), 0,
104
9.53k
    0, AArch64RegDiffLists, 0, AArch64SubRegIdxLists,
105
9.53k
    ARR_SIZE(AArch64SubRegIdxLists), 0);
106
9.53k
}
107
108
/// Sets up a new SME matrix operand at the currently active detail operand.
109
static void setup_sme_operand(MCInst *MI)
110
26.2k
{
111
26.2k
  if (!detail_is_set(MI))
112
0
    return;
113
114
26.2k
  AArch64_get_detail_op(MI, 0)->type = AARCH64_OP_SME;
115
26.2k
  AArch64_get_detail_op(MI, 0)->sme.type = AARCH64_SME_OP_INVALID;
116
26.2k
  AArch64_get_detail_op(MI, 0)->sme.tile = AARCH64_REG_INVALID;
117
26.2k
  AArch64_get_detail_op(MI, 0)->sme.slice_reg = AARCH64_REG_INVALID;
118
26.2k
  AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm =
119
26.2k
    AARCH64_SLICE_IMM_INVALID;
120
26.2k
  AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm_range.first =
121
26.2k
    AARCH64_SLICE_IMM_RANGE_INVALID;
122
26.2k
  AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm_range.offset =
123
26.2k
    AARCH64_SLICE_IMM_RANGE_INVALID;
124
26.2k
}
125
126
static void setup_pred_operand(MCInst *MI)
127
69.7k
{
128
69.7k
  if (!detail_is_set(MI))
129
0
    return;
130
131
69.7k
  AArch64_get_detail_op(MI, 0)->type = AARCH64_OP_PRED;
132
69.7k
  AArch64_get_detail_op(MI, 0)->pred.imm_index = -1;
133
69.7k
}
134
135
const insn_map aarch64_insns[] = {
136
#include "AArch64GenCSMappingInsn.inc"
137
};
138
139
static const name_map insn_alias_mnem_map[] = {
140
#include "AArch64GenCSAliasMnemMap.inc"
141
  { AARCH64_INS_ALIAS_CFP, "cfp" },
142
  { AARCH64_INS_ALIAS_DVP, "dvp" },
143
  { AARCH64_INS_ALIAS_COSP, "cosp" },
144
  { AARCH64_INS_ALIAS_CPP, "cpp" },
145
  { AARCH64_INS_ALIAS_IC, "ic" },
146
  { AARCH64_INS_ALIAS_DC, "dc" },
147
  { AARCH64_INS_ALIAS_AT, "at" },
148
  { AARCH64_INS_ALIAS_TLBI, "tlbi" },
149
  { AARCH64_INS_ALIAS_TLBIP, "tlbip" },
150
  { AARCH64_INS_ALIAS_RPRFM, "rprfm" },
151
  { AARCH64_INS_ALIAS_LSL, "lsl" },
152
  { AARCH64_INS_ALIAS_SBFX, "sbfx" },
153
  { AARCH64_INS_ALIAS_UBFX, "ubfx" },
154
  { AARCH64_INS_ALIAS_SBFIZ, "sbfiz" },
155
  { AARCH64_INS_ALIAS_UBFIZ, "ubfiz" },
156
  { AARCH64_INS_ALIAS_BFC, "bfc" },
157
  { AARCH64_INS_ALIAS_BFI, "bfi" },
158
  { AARCH64_INS_ALIAS_BFXIL, "bfxil" },
159
  { AARCH64_INS_ALIAS_END, NULL },
160
};
161
162
static const char *get_custom_reg_alias(unsigned reg)
163
71.0k
{
164
71.0k
  switch (reg) {
165
164
  case AARCH64_REG_X29:
166
164
    return "fp";
167
2.81k
  case AARCH64_REG_X30:
168
2.81k
    return "lr";
169
71.0k
  }
170
68.0k
  return NULL;
171
71.0k
}
172
173
/// Very annoyingly LLVM hard codes the vector layout post-fixes into the asm string.
174
/// In this function we check for these cases and add the vectorlayout/arrangement
175
/// specifier.
176
void AArch64_add_vas(MCInst *MI, const SStream *OS)
177
328k
{
178
328k
  if (!detail_is_set(MI)) {
179
0
    return;
180
0
  }
181
182
328k
  if (AArch64_get_detail(MI)->op_count == 0) {
183
864
    return;
184
864
  }
185
327k
  if (MCInst_getOpcode(MI) == AArch64_MUL53HI ||
186
327k
      MCInst_getOpcode(MI) == AArch64_MUL53LO) {
187
    // Proprietary Apple instrucions.
188
0
    AArch64_get_detail(MI)->operands[0].vas = AARCH64LAYOUT_VL_2D;
189
0
    AArch64_get_detail(MI)->operands[1].vas = AARCH64LAYOUT_VL_2D;
190
0
    return;
191
0
  }
192
193
  // Search for r".[0-9]{1,2}[bhsdq]\W"
194
  // with poor mans regex
195
327k
  const char *vl_ptr = strchr(OS->buffer, '.');
196
705k
  while (vl_ptr) {
197
    // Number after dot?
198
377k
    unsigned num = 0;
199
377k
    if (strchr("1248", vl_ptr[1])) {
200
97.2k
      num = atoi(vl_ptr + 1);
201
97.2k
      vl_ptr = num > 9 ? vl_ptr + 3 : vl_ptr + 2;
202
280k
    } else {
203
280k
      vl_ptr++;
204
280k
    }
205
206
    // Layout letter
207
377k
    char letter = '\0';
208
377k
    if (strchr("bhsdq", vl_ptr[0])) {
209
367k
      letter = vl_ptr[0];
210
367k
    }
211
377k
    if (!letter) {
212
9.34k
      goto next_dot_continue;
213
9.34k
    }
214
215
367k
    AArch64Layout_VectorLayout vl = AARCH64LAYOUT_INVALID;
216
367k
    switch (letter) {
217
0
    default:
218
0
      CS_ASSERT_RET(0 && "Unhandled vector layout letter.");
219
0
      return;
220
81.6k
    case 'b':
221
81.6k
      vl = AARCH64LAYOUT_VL_B;
222
81.6k
      break;
223
100k
    case 'h':
224
100k
      vl = AARCH64LAYOUT_VL_H;
225
100k
      break;
226
94.9k
    case 's':
227
94.9k
      vl = AARCH64LAYOUT_VL_S;
228
94.9k
      break;
229
87.5k
    case 'd':
230
87.5k
      vl = AARCH64LAYOUT_VL_D;
231
87.5k
      break;
232
3.48k
    case 'q':
233
3.48k
      vl = AARCH64LAYOUT_VL_Q;
234
3.48k
      break;
235
367k
    }
236
367k
    vl |= (num << 8);
237
238
    // Determine op index by searching for trailing commata after op string
239
367k
    uint32_t op_idx = 0;
240
367k
    const char *comma_ptr = strchr(OS->buffer, ',');
241
367k
    ;
242
798k
    while (comma_ptr && comma_ptr < vl_ptr) {
243
430k
      ++op_idx;
244
430k
      comma_ptr = strchr(comma_ptr + 1, ',');
245
430k
    }
246
367k
    if (!comma_ptr) {
247
      // Last op doesn't have a trailing commata.
248
57.1k
      op_idx = AArch64_get_detail(MI)->op_count - 1;
249
57.1k
    }
250
367k
    if (op_idx >= AArch64_get_detail(MI)->op_count) {
251
      // A memory operand with a commata in [base, dist]
252
11.8k
      op_idx = AArch64_get_detail(MI)->op_count - 1;
253
11.8k
    }
254
255
    // Search for the operand this one belongs to.
256
367k
    cs_aarch64_op *op = &AArch64_get_detail(MI)->operands[op_idx];
257
367k
    if ((op->type != AARCH64_OP_REG &&
258
53.2k
         op->type != AARCH64_OP_SME) ||
259
336k
        op->vas != AARCH64LAYOUT_INVALID) {
260
292k
      goto next_dot_continue;
261
292k
    }
262
75.1k
    op->vas = vl;
263
264
377k
next_dot_continue:
265
377k
    vl_ptr = strchr(vl_ptr + 1, '.');
266
377k
  }
267
327k
}
268
269
const char *AArch64_reg_name(csh handle, unsigned int reg)
270
71.0k
{
271
71.0k
  int syntax_opt = ((cs_struct *)(uintptr_t)handle)->syntax;
272
71.0k
  const char *alias = get_custom_reg_alias(reg);
273
71.0k
  if ((syntax_opt & CS_OPT_SYNTAX_CS_REG_ALIAS) && alias)
274
0
    return alias;
275
276
71.0k
  if (((cs_struct *)(uintptr_t)handle)->syntax &
277
71.0k
      CS_OPT_SYNTAX_NOREGNAME) {
278
0
    return AArch64_LLVM_getRegisterName(reg, AArch64_NoRegAltName);
279
0
  }
280
  // TODO Add options for the other register names
281
71.0k
  return AArch64_LLVM_getRegisterName(reg, AArch64_NoRegAltName);
282
71.0k
}
283
284
void AArch64_setup_op(cs_aarch64_op *op)
285
5.39M
{
286
5.39M
  memset(op, 0, sizeof(cs_aarch64_op));
287
5.39M
  op->type = AARCH64_OP_INVALID;
288
5.39M
  op->vector_index = -1;
289
5.39M
}
290
291
void AArch64_init_cs_detail(MCInst *MI)
292
336k
{
293
336k
  if (detail_is_set(MI)) {
294
336k
    memset(get_detail(MI), 0,
295
336k
           offsetof(cs_detail, aarch64) + sizeof(cs_aarch64));
296
5.71M
    for (int i = 0; i < ARR_SIZE(AArch64_get_detail(MI)->operands);
297
5.37M
         i++)
298
5.37M
      AArch64_setup_op(&AArch64_get_detail(MI)->operands[i]);
299
336k
    AArch64_get_detail(MI)->cc = AArch64CC_Invalid;
300
336k
  }
301
336k
}
302
303
/// Unfortunately, the AARCH64 definitions do not indicate in any way
304
/// (exception are the instruction identifiers), if memory accesses
305
/// is post- or pre-indexed.
306
/// So the only generic way to determine, if the memory access is in
307
/// post-indexed addressing mode, is by search for "<membase>], #<memdisp>" in
308
/// @p OS.
309
/// Searching the asm string to determine such a property is enormously ugly
310
/// and wastes resources.
311
/// Sorry, I know and do feel bad about it. But for now it works.
312
static bool AArch64_check_post_index_am(const MCInst *MI, const SStream *OS)
313
328k
{
314
328k
  if (AArch64_get_detail(MI)->post_index) {
315
0
    return true;
316
0
  }
317
328k
  cs_aarch64_op *memop = NULL;
318
1.14M
  for (int i = 0; i < AArch64_get_detail(MI)->op_count; ++i) {
319
931k
    if (AArch64_get_detail(MI)->operands[i].type & CS_OP_MEM) {
320
119k
      memop = &AArch64_get_detail(MI)->operands[i];
321
119k
      break;
322
119k
    }
323
931k
  }
324
328k
  if (!memop)
325
208k
    return false;
326
119k
  if (memop->mem.base == AARCH64_REG_INVALID) {
327
    // Load/Store from/to label. Has no register base.
328
7.68k
    return false;
329
7.68k
  }
330
112k
  const char *membase = AArch64_LLVM_getRegisterName(
331
112k
    memop->mem.base, AArch64_NoRegAltName);
332
112k
  int64_t memdisp = memop->mem.disp;
333
112k
  SStream pattern = { 0 };
334
112k
  SStream_concat(&pattern, membase);
335
112k
  SStream_concat(&pattern, "], ");
336
112k
  printInt32Bang(&pattern, memdisp);
337
112k
  return strstr(OS->buffer, pattern.buffer) != NULL;
338
119k
}
339
340
static void AArch64_check_updates_flags(MCInst *MI)
341
328k
{
342
328k
#ifndef CAPSTONE_DIET
343
328k
  if (!detail_is_set(MI))
344
0
    return;
345
328k
  cs_detail *detail = get_detail(MI);
346
  // Implicitly written registers
347
361k
  for (int i = 0; i < detail->regs_write_count; ++i) {
348
48.5k
    if (detail->regs_write[i] == 0)
349
0
      break;
350
81.7k
    for (int j = 0; j < ARR_SIZE(aarch64_flag_regs); ++j) {
351
48.5k
      if (detail->regs_write[i] == aarch64_flag_regs[j]) {
352
15.3k
        detail->aarch64.update_flags = true;
353
15.3k
        return;
354
15.3k
      }
355
48.5k
    }
356
48.5k
  }
357
1.21M
  for (int i = 0; i < detail->aarch64.op_count; ++i) {
358
897k
    if (detail->aarch64.operands[i].type == AARCH64_OP_SYSREG &&
359
6.57k
        detail->aarch64.operands[i].sysop.sub_type ==
360
6.57k
          AARCH64_OP_REG_MSR) {
361
22.9k
      for (int j = 0; j < ARR_SIZE(aarch64_flag_sys_regs);
362
18.9k
           ++j)
363
19.1k
        if (detail->aarch64.operands[i]
364
19.1k
              .sysop.reg.sysreg ==
365
19.1k
            aarch64_flag_sys_regs[j]) {
366
194
          detail->aarch64.update_flags = true;
367
194
          return;
368
194
        }
369
893k
    } else if (detail->aarch64.operands[i].type == AARCH64_OP_REG &&
370
574k
         detail->aarch64.operands[i].access & CS_AC_WRITE) {
371
563k
      for (int j = 0; j < ARR_SIZE(aarch64_flag_regs); ++j)
372
281k
        if (detail->aarch64.operands[i].reg ==
373
281k
            aarch64_flag_regs[j]) {
374
0
          detail->aarch64.update_flags = true;
375
0
          return;
376
0
        }
377
281k
    }
378
897k
  }
379
313k
#endif // CAPSTONE_DIET
380
313k
}
381
382
/// Surfaces system-register accesses which alias an architectural
383
/// register Capstone models. MRS Xt, NZCV reads (and MSR NZCV, Xt
384
/// writes) the same flags every flag-setting instruction implicitly
385
/// defines, but the generated implicit register lists cannot express
386
/// it: MRS/MSR are single generic instructions whose system register
387
/// is an immediate operand, so LLVM's static Uses/Defs do not depend
388
/// on it. Add the aliased register to the implicit lists so
389
/// cs_regs_access() reports it like any other NZCV reader/writer.
390
/// The 128-bit pair forms MRRS/MSRR are deliberately excluded: NZCV
391
/// is not a valid 128-bit system register, so those encodings are
392
/// UNDEFINED rather than flag accesses.
393
static void AArch64_add_sysreg_alias_access(MCInst *MI)
394
328k
{
395
328k
#ifndef CAPSTONE_DIET
396
328k
  if (!detail_is_set(MI))
397
0
    return;
398
328k
  const unsigned opcode = MCInst_getOpcode(MI);
399
328k
  if (opcode != AArch64_MRS && opcode != AArch64_MSR)
400
323k
    return;
401
4.97k
  cs_detail *detail = get_detail(MI);
402
14.9k
  for (int i = 0; i < detail->aarch64.op_count; ++i) {
403
9.94k
    const cs_aarch64_op *op = &detail->aarch64.operands[i];
404
9.94k
    if (op->type != AARCH64_OP_SYSREG)
405
4.97k
      continue;
406
4.97k
    if (op->sysop.sub_type == AARCH64_OP_REG_MRS &&
407
1.14k
        op->sysop.reg.sysreg == AARCH64_SYSREG_NZCV)
408
83
      map_add_implicit_read(MI, AARCH64_REG_NZCV);
409
4.88k
    else if (op->sysop.sub_type == AARCH64_OP_REG_MSR &&
410
3.82k
       op->sysop.reg.sysreg == AARCH64_SYSREG_NZCV)
411
51
      map_add_implicit_write(MI, AARCH64_REG_NZCV);
412
4.97k
  }
413
4.97k
#endif // CAPSTONE_DIET
414
4.97k
}
415
416
static aarch64_shifter id_to_shifter(unsigned Opcode)
417
498
{
418
498
  switch (Opcode) {
419
0
  default:
420
0
    return AARCH64_SFT_INVALID;
421
34
  case AArch64_RORVXr:
422
103
  case AArch64_RORVWr:
423
103
    return AARCH64_SFT_ROR_REG;
424
41
  case AArch64_LSRVXr:
425
131
  case AArch64_LSRVWr:
426
131
    return AARCH64_SFT_LSR_REG;
427
37
  case AArch64_LSLVXr:
428
110
  case AArch64_LSLVWr:
429
110
    return AARCH64_SFT_LSL_REG;
430
51
  case AArch64_ASRVXr:
431
154
  case AArch64_ASRVWr:
432
154
    return AARCH64_SFT_ASR_REG;
433
498
  }
434
498
}
435
436
static void add_non_alias_details(MCInst *MI)
437
288k
{
438
288k
  unsigned Opcode = MCInst_getOpcode(MI);
439
288k
  switch (Opcode) {
440
274k
  default:
441
274k
    break;
442
274k
  case AArch64_RORVXr:
443
103
  case AArch64_RORVWr:
444
144
  case AArch64_LSRVXr:
445
234
  case AArch64_LSRVWr:
446
271
  case AArch64_LSLVXr:
447
344
  case AArch64_LSLVWr:
448
395
  case AArch64_ASRVXr:
449
498
  case AArch64_ASRVWr:
450
498
    if (AArch64_get_detail(MI)->op_count != 3) {
451
0
      return;
452
0
    }
453
498
    CS_ASSERT_RET(AArch64_get_detail_op(MI, -1)->type ==
454
498
            AARCH64_OP_REG);
455
456
    // The shift by register instructions don't set the shift value properly.
457
    // Correct it here.
458
498
    uint64_t shift = AArch64_get_detail_op(MI, -1)->reg;
459
498
    cs_aarch64_op *op1 = AArch64_get_detail_op(MI, -2);
460
498
    op1->shift.type = id_to_shifter(Opcode);
461
498
    op1->shift.value = shift;
462
498
    AArch64_dec_op_count(MI);
463
498
    break;
464
75
  case AArch64_FCMPDri:
465
110
  case AArch64_FCMPEDri:
466
160
  case AArch64_FCMPEHri:
467
250
  case AArch64_FCMPESri:
468
310
  case AArch64_FCMPHri:
469
368
  case AArch64_FCMPSri:
470
368
    AArch64_insert_detail_op_reg_at(MI, -1, AARCH64_REG_XZR,
471
368
            CS_AC_READ);
472
368
    break;
473
78
  case AArch64_CMEQv16i8rz:
474
603
  case AArch64_CMEQv1i64rz:
475
1.03k
  case AArch64_CMEQv2i32rz:
476
1.22k
  case AArch64_CMEQv2i64rz:
477
1.45k
  case AArch64_CMEQv4i16rz:
478
1.50k
  case AArch64_CMEQv4i32rz:
479
1.52k
  case AArch64_CMEQv8i16rz:
480
1.83k
  case AArch64_CMEQv8i8rz:
481
1.91k
  case AArch64_CMGEv16i8rz:
482
1.93k
  case AArch64_CMGEv1i64rz:
483
2.07k
  case AArch64_CMGEv2i32rz:
484
2.37k
  case AArch64_CMGEv2i64rz:
485
2.48k
  case AArch64_CMGEv4i16rz:
486
2.61k
  case AArch64_CMGEv4i32rz:
487
2.71k
  case AArch64_CMGEv8i16rz:
488
3.13k
  case AArch64_CMGEv8i8rz:
489
3.33k
  case AArch64_CMGTv16i8rz:
490
3.38k
  case AArch64_CMGTv1i64rz:
491
3.41k
  case AArch64_CMGTv2i32rz:
492
3.66k
  case AArch64_CMGTv2i64rz:
493
3.75k
  case AArch64_CMGTv4i16rz:
494
4.02k
  case AArch64_CMGTv4i32rz:
495
4.17k
  case AArch64_CMGTv8i16rz:
496
4.64k
  case AArch64_CMGTv8i8rz:
497
4.65k
  case AArch64_CMLEv16i8rz:
498
4.72k
  case AArch64_CMLEv1i64rz:
499
4.80k
  case AArch64_CMLEv2i32rz:
500
4.83k
  case AArch64_CMLEv2i64rz:
501
4.90k
  case AArch64_CMLEv4i16rz:
502
4.97k
  case AArch64_CMLEv4i32rz:
503
5.01k
  case AArch64_CMLEv8i16rz:
504
5.37k
  case AArch64_CMLEv8i8rz:
505
5.46k
  case AArch64_CMLTv16i8rz:
506
5.52k
  case AArch64_CMLTv1i64rz:
507
5.91k
  case AArch64_CMLTv2i32rz:
508
6.23k
  case AArch64_CMLTv2i64rz:
509
6.34k
  case AArch64_CMLTv4i16rz:
510
6.42k
  case AArch64_CMLTv4i32rz:
511
6.45k
  case AArch64_CMLTv8i16rz:
512
6.47k
  case AArch64_CMLTv8i8rz:
513
6.47k
    AArch64_insert_detail_op_imm_at(MI, -1, 0);
514
6.47k
    break;
515
124
  case AArch64_FCMEQ_PPzZ0_D:
516
134
  case AArch64_FCMEQ_PPzZ0_H:
517
542
  case AArch64_FCMEQ_PPzZ0_S:
518
663
  case AArch64_FCMEQv1i16rz:
519
732
  case AArch64_FCMEQv1i32rz:
520
772
  case AArch64_FCMEQv1i64rz:
521
814
  case AArch64_FCMEQv2i32rz:
522
824
  case AArch64_FCMEQv2i64rz:
523
860
  case AArch64_FCMEQv4i16rz:
524
943
  case AArch64_FCMEQv4i32rz:
525
1.03k
  case AArch64_FCMEQv8i16rz:
526
1.20k
  case AArch64_FCMGE_PPzZ0_D:
527
1.66k
  case AArch64_FCMGE_PPzZ0_H:
528
1.78k
  case AArch64_FCMGE_PPzZ0_S:
529
1.85k
  case AArch64_FCMGEv1i16rz:
530
1.94k
  case AArch64_FCMGEv1i32rz:
531
1.97k
  case AArch64_FCMGEv1i64rz:
532
2.71k
  case AArch64_FCMGEv2i32rz:
533
2.76k
  case AArch64_FCMGEv2i64rz:
534
2.80k
  case AArch64_FCMGEv4i16rz:
535
2.85k
  case AArch64_FCMGEv4i32rz:
536
3.43k
  case AArch64_FCMGEv8i16rz:
537
3.46k
  case AArch64_FCMGT_PPzZ0_D:
538
3.49k
  case AArch64_FCMGT_PPzZ0_H:
539
3.63k
  case AArch64_FCMGT_PPzZ0_S:
540
3.68k
  case AArch64_FCMGTv1i16rz:
541
3.73k
  case AArch64_FCMGTv1i32rz:
542
3.74k
  case AArch64_FCMGTv1i64rz:
543
3.79k
  case AArch64_FCMGTv2i32rz:
544
3.82k
  case AArch64_FCMGTv2i64rz:
545
3.87k
  case AArch64_FCMGTv4i16rz:
546
3.97k
  case AArch64_FCMGTv4i32rz:
547
4.22k
  case AArch64_FCMGTv8i16rz:
548
4.27k
  case AArch64_FCMLE_PPzZ0_D:
549
4.31k
  case AArch64_FCMLE_PPzZ0_H:
550
4.45k
  case AArch64_FCMLE_PPzZ0_S:
551
4.75k
  case AArch64_FCMLEv1i16rz:
552
4.76k
  case AArch64_FCMLEv1i32rz:
553
4.83k
  case AArch64_FCMLEv1i64rz:
554
4.87k
  case AArch64_FCMLEv2i32rz:
555
5.04k
  case AArch64_FCMLEv2i64rz:
556
5.10k
  case AArch64_FCMLEv4i16rz:
557
5.19k
  case AArch64_FCMLEv4i32rz:
558
5.23k
  case AArch64_FCMLEv8i16rz:
559
5.29k
  case AArch64_FCMLT_PPzZ0_D:
560
5.31k
  case AArch64_FCMLT_PPzZ0_H:
561
5.52k
  case AArch64_FCMLT_PPzZ0_S:
562
5.55k
  case AArch64_FCMLTv1i16rz:
563
5.63k
  case AArch64_FCMLTv1i32rz:
564
5.70k
  case AArch64_FCMLTv1i64rz:
565
5.75k
  case AArch64_FCMLTv2i32rz:
566
5.79k
  case AArch64_FCMLTv2i64rz:
567
5.80k
  case AArch64_FCMLTv4i16rz:
568
5.84k
  case AArch64_FCMLTv4i32rz:
569
5.97k
  case AArch64_FCMLTv8i16rz:
570
5.98k
  case AArch64_FCMNE_PPzZ0_D:
571
6.10k
  case AArch64_FCMNE_PPzZ0_H:
572
6.17k
  case AArch64_FCMNE_PPzZ0_S: {
573
6.17k
    aarch64_sysop sysop = { 0 };
574
6.17k
    sysop.imm.exactfpimm = AARCH64_EXACTFPIMM_ZERO;
575
6.17k
    sysop.sub_type = AARCH64_OP_EXACTFPIMM;
576
6.17k
    AArch64_insert_detail_op_sys(MI, -1, sysop, AARCH64_OP_SYSIMM);
577
6.17k
    break;
578
6.10k
  }
579
288k
  }
580
288k
}
581
582
#define ADD_ZA0_S \
583
1.15k
  { \
584
1.15k
    aarch64_op_sme za0_op = { \
585
1.15k
      .type = AARCH64_SME_OP_TILE, \
586
1.15k
      .tile = AARCH64_REG_ZAS0, \
587
1.15k
      .slice_reg = AARCH64_REG_INVALID, \
588
1.15k
      .slice_offset = { -1 }, \
589
1.15k
      .has_range_offset = false, \
590
1.15k
      .is_vertical = false, \
591
1.15k
    }; \
592
1.15k
    AArch64_insert_detail_op_sme(MI, -1, za0_op); \
593
1.15k
    AArch64_get_detail_op(MI, -1)->vas = AARCH64LAYOUT_VL_S; \
594
1.15k
    AArch64_get_detail_op(MI, -1)->access = CS_AC_WRITE; \
595
1.15k
  }
596
#define ADD_ZA1_S \
597
640
  { \
598
640
    aarch64_op_sme za1_op = { \
599
640
      .type = AARCH64_SME_OP_TILE, \
600
640
      .tile = AARCH64_REG_ZAS1, \
601
640
      .slice_reg = AARCH64_REG_INVALID, \
602
640
      .slice_offset = { -1 }, \
603
640
      .has_range_offset = false, \
604
640
      .is_vertical = false, \
605
640
    }; \
606
640
    AArch64_insert_detail_op_sme(MI, -1, za1_op); \
607
640
    AArch64_get_detail_op(MI, -1)->vas = AARCH64LAYOUT_VL_S; \
608
640
    AArch64_get_detail_op(MI, -1)->access = CS_AC_WRITE; \
609
640
  }
610
#define ADD_ZA2_S \
611
497
  { \
612
497
    aarch64_op_sme za2_op = { \
613
497
      .type = AARCH64_SME_OP_TILE, \
614
497
      .tile = AARCH64_REG_ZAS2, \
615
497
      .slice_reg = AARCH64_REG_INVALID, \
616
497
      .slice_offset = { -1 }, \
617
497
      .has_range_offset = false, \
618
497
      .is_vertical = false, \
619
497
    }; \
620
497
    AArch64_insert_detail_op_sme(MI, -1, za2_op); \
621
497
    AArch64_get_detail_op(MI, -1)->vas = AARCH64LAYOUT_VL_S; \
622
497
    AArch64_get_detail_op(MI, -1)->access = CS_AC_WRITE; \
623
497
  }
624
#define ADD_ZA3_S \
625
767
  { \
626
767
    aarch64_op_sme za3_op = { \
627
767
      .type = AARCH64_SME_OP_TILE, \
628
767
      .tile = AARCH64_REG_ZAS3, \
629
767
      .slice_reg = AARCH64_REG_INVALID, \
630
767
      .slice_offset = { -1 }, \
631
767
      .has_range_offset = false, \
632
767
      .is_vertical = false, \
633
767
    }; \
634
767
    AArch64_insert_detail_op_sme(MI, -1, za3_op); \
635
767
    AArch64_get_detail_op(MI, -1)->vas = AARCH64LAYOUT_VL_S; \
636
767
    AArch64_get_detail_op(MI, -1)->access = CS_AC_WRITE; \
637
767
  }
638
#define ADD_ZA \
639
344
  { \
640
344
    aarch64_op_sme za_op = { \
641
344
      .type = AARCH64_SME_OP_TILE, \
642
344
      .tile = AARCH64_REG_ZA, \
643
344
      .slice_reg = AARCH64_REG_INVALID, \
644
344
      .slice_offset = { -1 }, \
645
344
      .has_range_offset = false, \
646
344
      .is_vertical = false, \
647
344
    }; \
648
344
    AArch64_insert_detail_op_sme(MI, -1, za_op); \
649
344
    AArch64_get_detail_op(MI, -1)->access = CS_AC_WRITE; \
650
344
  }
651
652
static void AArch64_add_not_defined_ops(MCInst *MI, const SStream *OS)
653
328k
{
654
328k
  if (!detail_is_set(MI))
655
0
    return;
656
657
328k
  if (!MI->flat_insn->is_alias || !MI->flat_insn->usesAliasDetails) {
658
288k
    add_non_alias_details(MI);
659
288k
    return;
660
288k
  }
661
662
  // Alias details
663
40.4k
  switch (MI->flat_insn->alias_id) {
664
32.0k
  default:
665
32.0k
    return;
666
32.0k
  case AARCH64_INS_ALIAS_ROR:
667
61
    if (AArch64_get_detail(MI)->op_count != 3) {
668
0
      return;
669
0
    }
670
    // The ROR alias doesn't set the shift value properly.
671
    // Correct it here.
672
61
    bool reg_shift = AArch64_get_detail_op(MI, -1)->type ==
673
61
         AARCH64_OP_REG;
674
61
    uint64_t shift = reg_shift ?
675
0
           AArch64_get_detail_op(MI, -1)->reg :
676
61
           AArch64_get_detail_op(MI, -1)->imm;
677
61
    cs_aarch64_op *op1 = AArch64_get_detail_op(MI, -2);
678
61
    op1->shift.type = reg_shift ? AARCH64_SFT_ROR_REG :
679
61
                AARCH64_SFT_ROR;
680
61
    op1->shift.value = shift;
681
61
    AArch64_dec_op_count(MI);
682
61
    break;
683
316
  case AARCH64_INS_ALIAS_FMOV:
684
316
    if (AArch64_get_detail_op(MI, -1)->type == AARCH64_OP_FP) {
685
316
      break;
686
316
    }
687
0
    AArch64_insert_detail_op_float_at(MI, -1, 0.0f, CS_AC_READ);
688
0
    break;
689
602
  case AARCH64_INS_ALIAS_LD1:
690
826
  case AARCH64_INS_ALIAS_LD1R:
691
1.24k
  case AARCH64_INS_ALIAS_LD2:
692
1.38k
  case AARCH64_INS_ALIAS_LD2R:
693
3.01k
  case AARCH64_INS_ALIAS_LD3:
694
3.52k
  case AARCH64_INS_ALIAS_LD3R:
695
4.19k
  case AARCH64_INS_ALIAS_LD4:
696
4.40k
  case AARCH64_INS_ALIAS_LD4R:
697
4.88k
  case AARCH64_INS_ALIAS_ST1:
698
5.14k
  case AARCH64_INS_ALIAS_ST2:
699
5.23k
  case AARCH64_INS_ALIAS_ST3:
700
5.69k
  case AARCH64_INS_ALIAS_ST4: {
701
    // Add post-index disp
702
5.69k
    const char *disp_off = strrchr(OS->buffer, '#');
703
5.69k
    if (!disp_off)
704
0
      return;
705
5.69k
    unsigned disp = atoi(disp_off + 1);
706
5.69k
    AArch64_get_detail_op(MI, -1)->type = AARCH64_OP_MEM;
707
5.69k
    AArch64_get_detail_op(MI, -1)->mem.base =
708
5.69k
      AArch64_get_detail_op(MI, -1)->reg;
709
5.69k
    AArch64_get_detail_op(MI, -1)->mem.disp = disp;
710
5.69k
    AArch64_get_detail(MI)->post_index = true;
711
5.69k
    break;
712
5.69k
  }
713
3
  case AARCH64_INS_ALIAS_GCSB:
714
    // TODO
715
    // Only CSYNC is defined in LLVM. So we need to add it.
716
    //     /* 2825 */ "gcsb dsync\0"
717
3
    break;
718
220
  case AARCH64_INS_ALIAS_SMSTART:
719
388
  case AARCH64_INS_ALIAS_SMSTOP: {
720
388
    const char *disp_off = NULL;
721
388
    disp_off = strstr(OS->buffer, "smstart\tza");
722
388
    if (disp_off) {
723
13
      aarch64_sysop sysop = { 0 };
724
13
      sysop.alias.svcr = AARCH64_SVCR_SVCRZA;
725
13
      sysop.sub_type = AARCH64_OP_SVCR;
726
13
      AArch64_insert_detail_op_sys(MI, -1, sysop,
727
13
                 AARCH64_OP_SYSALIAS);
728
13
      return;
729
13
    }
730
375
    disp_off = strstr(OS->buffer, "smstart\tsm");
731
375
    if (disp_off) {
732
178
      aarch64_sysop sysop = { 0 };
733
178
      sysop.alias.svcr = AARCH64_SVCR_SVCRSM;
734
178
      sysop.sub_type = AARCH64_OP_SVCR;
735
178
      AArch64_insert_detail_op_sys(MI, -1, sysop,
736
178
                 AARCH64_OP_SYSALIAS);
737
178
      return;
738
178
    }
739
197
    break;
740
375
  }
741
1.91k
  case AARCH64_INS_ALIAS_ZERO: {
742
    // It is ugly, but the hard coded search patterns do it for now.
743
1.91k
    const char *disp_off = NULL;
744
745
1.91k
    disp_off = strstr(OS->buffer, "{za}");
746
1.91k
    if (disp_off) {
747
344
      ADD_ZA;
748
344
      return;
749
344
    }
750
1.57k
    disp_off = strstr(OS->buffer, "{za1.h}");
751
1.57k
    if (disp_off) {
752
87
      aarch64_op_sme op = {
753
87
        .type = AARCH64_SME_OP_TILE,
754
87
        .tile = AARCH64_REG_ZAH1,
755
87
        .slice_reg = AARCH64_REG_INVALID,
756
87
        .slice_offset = { -1 },
757
87
        .has_range_offset = false,
758
87
        .is_vertical = false,
759
87
      };
760
87
      AArch64_insert_detail_op_sme(MI, -1, op);
761
87
      AArch64_get_detail_op(MI, -1)->vas = AARCH64LAYOUT_VL_H;
762
87
      AArch64_get_detail_op(MI, -1)->access = CS_AC_WRITE;
763
87
      return;
764
87
    }
765
1.48k
    disp_off = strstr(OS->buffer, "{za0.h}");
766
1.48k
    if (disp_off) {
767
83
      aarch64_op_sme op = {
768
83
        .type = AARCH64_SME_OP_TILE,
769
83
        .tile = AARCH64_REG_ZAH0,
770
83
        .slice_reg = AARCH64_REG_INVALID,
771
83
        .slice_offset = { -1 },
772
83
        .has_range_offset = false,
773
83
        .is_vertical = false,
774
83
      };
775
83
      AArch64_insert_detail_op_sme(MI, -1, op);
776
83
      AArch64_get_detail_op(MI, -1)->vas = AARCH64LAYOUT_VL_H;
777
83
      AArch64_get_detail_op(MI, -1)->access = CS_AC_WRITE;
778
83
      return;
779
83
    }
780
1.40k
    disp_off = strstr(OS->buffer, "{za0.s}");
781
1.40k
    if (disp_off) {
782
73
      ADD_ZA0_S;
783
73
      return;
784
73
    }
785
1.32k
    disp_off = strstr(OS->buffer, "{za1.s}");
786
1.32k
    if (disp_off) {
787
39
      ADD_ZA1_S;
788
39
      return;
789
39
    }
790
1.29k
    disp_off = strstr(OS->buffer, "{za2.s}");
791
1.29k
    if (disp_off) {
792
33
      ADD_ZA2_S;
793
33
      return;
794
33
    }
795
1.25k
    disp_off = strstr(OS->buffer, "{za3.s}");
796
1.25k
    if (disp_off) {
797
83
      ADD_ZA3_S;
798
83
      return;
799
83
    }
800
1.17k
    disp_off = strstr(OS->buffer, "{za0.s,za1.s}");
801
1.17k
    if (disp_off) {
802
356
      ADD_ZA0_S;
803
356
      ADD_ZA1_S;
804
356
      return;
805
356
    }
806
818
    disp_off = strstr(OS->buffer, "{za0.s,za3.s}");
807
818
    if (disp_off) {
808
283
      ADD_ZA0_S;
809
283
      ADD_ZA3_S;
810
283
      return;
811
283
    }
812
535
    disp_off = strstr(OS->buffer, "{za1.s,za2.s}");
813
535
    if (disp_off) {
814
12
      ADD_ZA1_S;
815
12
      ADD_ZA2_S;
816
12
      return;
817
12
    }
818
523
    disp_off = strstr(OS->buffer, "{za2.s,za3.s}");
819
523
    if (disp_off) {
820
41
      ADD_ZA2_S;
821
41
      ADD_ZA3_S;
822
41
      return;
823
41
    }
824
482
    disp_off = strstr(OS->buffer, "{za0.s,za1.s,za2.s}");
825
482
    if (disp_off) {
826
122
      ADD_ZA0_S;
827
122
      ADD_ZA1_S;
828
122
      ADD_ZA2_S;
829
122
      return;
830
122
    }
831
360
    disp_off = strstr(OS->buffer, "{za0.s,za1.s,za3.s}");
832
360
    if (disp_off) {
833
71
      ADD_ZA0_S;
834
71
      ADD_ZA1_S;
835
71
      ADD_ZA3_S;
836
71
      return;
837
71
    }
838
289
    disp_off = strstr(OS->buffer, "{za0.s,za2.s,za3.s}");
839
289
    if (disp_off) {
840
249
      ADD_ZA0_S;
841
249
      ADD_ZA2_S;
842
249
      ADD_ZA3_S;
843
249
      return;
844
249
    }
845
40
    disp_off = strstr(OS->buffer, "{za1.s,za2.s,za3.s}");
846
40
    if (disp_off) {
847
40
      ADD_ZA1_S;
848
40
      ADD_ZA2_S;
849
40
      ADD_ZA3_S;
850
40
      return;
851
40
    }
852
0
    break;
853
40
  }
854
40.4k
  }
855
40.4k
}
856
857
void AArch64_set_instr_map_data(MCInst *MI)
858
336k
{
859
336k
  map_cs_id(MI, aarch64_insns, ARR_SIZE(aarch64_insns));
860
336k
  map_implicit_reads(MI, aarch64_insns);
861
336k
  map_implicit_writes(MI, aarch64_insns);
862
336k
  map_groups(MI, aarch64_insns);
863
336k
}
864
865
bool AArch64_getInstruction(csh handle, const uint8_t *code, size_t code_len,
866
          MCInst *MI, uint16_t *size, uint64_t address,
867
          void *info)
868
336k
{
869
336k
  AArch64_init_cs_detail(MI);
870
336k
  DecodeStatus Result = AArch64_LLVM_getInstruction(
871
336k
    handle, code, code_len, MI, size, address, info);
872
336k
  AArch64_set_instr_map_data(MI);
873
336k
  if (Result == MCDisassembler_SoftFail) {
874
7.59k
    MCInst_setSoftFail(MI);
875
7.59k
  }
876
336k
  return Result != MCDisassembler_Fail;
877
336k
}
878
879
/// Patches the register names with Capstone specific alias.
880
/// Those are common alias for registers (e.g. r15 = pc)
881
/// which are not set in LLVM.
882
static void patch_cs_reg_alias(char *asm_str)
883
0
{
884
0
  bool skip_sub = false;
885
0
  char *x29 = strstr(asm_str, "x29");
886
0
  if (x29 > asm_str && strstr(asm_str, "0x29") == (x29 - 1)) {
887
    // Check for hex prefix
888
0
    skip_sub = true;
889
0
  }
890
0
  while (x29 && !skip_sub) {
891
0
    x29[0] = 'f';
892
0
    x29[1] = 'p';
893
0
    memmove(x29 + 2, x29 + 3, strlen(x29 + 3));
894
0
    asm_str[strlen(asm_str) - 1] = '\0';
895
0
    x29 = strstr(asm_str, "x29");
896
0
  }
897
0
  skip_sub = false;
898
0
  char *x30 = strstr(asm_str, "x30");
899
0
  if (x30 > asm_str && strstr(asm_str, "0x30") == (x30 - 1)) {
900
    // Check for hex prefix
901
0
    skip_sub = true;
902
0
  }
903
0
  while (x30 && !skip_sub) {
904
0
    x30[0] = 'l';
905
0
    x30[1] = 'r';
906
0
    memmove(x30 + 2, x30 + 3, strlen(x30 + 3));
907
0
    asm_str[strlen(asm_str) - 1] = '\0';
908
0
    x30 = strstr(asm_str, "x30");
909
0
  }
910
0
}
911
912
/// Adds group to the instruction which are not defined in LLVM.
913
static void AArch64_add_cs_groups(MCInst *MI)
914
328k
{
915
328k
  unsigned Opcode = MI->flat_insn->id;
916
328k
  switch (Opcode) {
917
322k
  default:
918
322k
    return;
919
322k
  case AARCH64_INS_SVC:
920
103
    add_group(MI, AARCH64_GRP_INT);
921
103
    break;
922
65
  case AARCH64_INS_SMC:
923
4.55k
  case AARCH64_INS_MSR:
924
5.69k
  case AARCH64_INS_MRS:
925
5.69k
    add_group(MI, AARCH64_GRP_PRIVILEGE);
926
5.69k
    break;
927
34
  case AARCH64_INS_RET:
928
103
  case AARCH64_INS_RETAA:
929
316
  case AARCH64_INS_RETAB:
930
316
    add_group(MI, AARCH64_GRP_RET);
931
316
    break;
932
328k
  }
933
328k
}
934
935
static void AArch64_correct_mem_access(MCInst *MI)
936
328k
{
937
328k
#ifndef CAPSTONE_DIET
938
328k
  if (!detail_is_set(MI))
939
0
    return;
940
328k
  cs_ac_type access =
941
328k
    aarch64_insns[MI->Opcode].suppl_info.aarch64.mem_acc;
942
328k
  if (access == CS_AC_INVALID) {
943
213k
    return;
944
213k
  }
945
242k
  for (int i = 0; i < AArch64_get_detail(MI)->op_count; ++i) {
946
240k
    if (AArch64_get_detail_op(MI, -i)->type == AARCH64_OP_MEM) {
947
113k
      AArch64_get_detail_op(MI, -i)->access = access;
948
113k
      return;
949
113k
    }
950
240k
  }
951
115k
#endif
952
115k
}
953
954
void AArch64_printer(MCInst *MI, SStream *O, void * /* MCRegisterInfo* */ info)
955
328k
{
956
328k
  MCRegisterInfo *MRI = (MCRegisterInfo *)info;
957
328k
  MI->MRI = MRI;
958
328k
  MI->fillDetailOps = detail_is_set(MI);
959
328k
  MI->flat_insn->usesAliasDetails = map_use_alias_details(MI);
960
328k
  AArch64_LLVM_printInstruction(MI, O, info);
961
328k
  if (detail_is_set(MI)) {
962
328k
    if (AArch64_get_detail(MI)->is_doing_sme) {
963
      // Last operand still needs to be closed.
964
5.39k
      AArch64_get_detail(MI)->is_doing_sme = false;
965
5.39k
      AArch64_inc_op_count(MI);
966
5.39k
    }
967
328k
    AArch64_get_detail(MI)->post_index =
968
328k
      AArch64_check_post_index_am(MI, O);
969
328k
  }
970
328k
  AArch64_check_updates_flags(MI);
971
328k
  AArch64_add_sysreg_alias_access(MI);
972
328k
  map_set_alias_id(MI, O, insn_alias_mnem_map,
973
328k
       ARR_SIZE(insn_alias_mnem_map) - 1);
974
328k
  int syntax_opt = MI->csh->syntax;
975
328k
  if (syntax_opt & CS_OPT_SYNTAX_CS_REG_ALIAS)
976
0
    patch_cs_reg_alias(O->buffer);
977
328k
  AArch64_add_not_defined_ops(MI, O);
978
328k
  AArch64_add_cs_groups(MI);
979
328k
  AArch64_add_vas(MI, O);
980
328k
  AArch64_correct_mem_access(MI);
981
328k
}
982
983
// given internal insn id, return public instruction info
984
void AArch64_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
985
328k
{
986
  // Done after disassembly
987
328k
  return;
988
328k
}
989
990
static const char *const insn_name_maps[] = {
991
#include "AArch64GenCSMappingInsnName.inc"
992
};
993
994
const char *AArch64_insn_name(csh handle, unsigned int id)
995
328k
{
996
328k
#ifndef CAPSTONE_DIET
997
328k
  if (id < AARCH64_INS_ALIAS_END && id > AARCH64_INS_ALIAS_BEGIN) {
998
0
    if (id - AARCH64_INS_ALIAS_BEGIN >=
999
0
        ARR_SIZE(insn_alias_mnem_map))
1000
0
      return NULL;
1001
1002
0
    return insn_alias_mnem_map[id - AARCH64_INS_ALIAS_BEGIN - 1]
1003
0
      .name;
1004
0
  }
1005
328k
  if (id >= AARCH64_INS_ENDING)
1006
0
    return NULL;
1007
1008
328k
  if (id < ARR_SIZE(insn_name_maps))
1009
328k
    return insn_name_maps[id];
1010
1011
  // not found
1012
0
  return NULL;
1013
#else
1014
  return NULL;
1015
#endif
1016
328k
}
1017
1018
#ifndef CAPSTONE_DIET
1019
static const name_map group_name_maps[] = {
1020
  // generic groups
1021
  { AARCH64_GRP_INVALID, NULL },
1022
  { AARCH64_GRP_JUMP, "jump" },
1023
  { AARCH64_GRP_CALL, "call" },
1024
  { AARCH64_GRP_RET, "return" },
1025
  { AARCH64_GRP_PRIVILEGE, "privilege" },
1026
  { AARCH64_GRP_INT, "int" },
1027
  { AARCH64_GRP_BRANCH_RELATIVE, "branch_relative" },
1028
1029
// architecture-specific groups
1030
#include "AArch64GenCSFeatureName.inc"
1031
};
1032
#endif
1033
1034
const char *AArch64_group_name(csh handle, unsigned int id)
1035
259k
{
1036
259k
#ifndef CAPSTONE_DIET
1037
259k
  return id2name(group_name_maps, ARR_SIZE(group_name_maps), id);
1038
#else
1039
  return NULL;
1040
#endif
1041
259k
}
1042
1043
// map instruction name to public instruction ID
1044
aarch64_insn AArch64_map_insn(const char *name)
1045
0
{
1046
0
  unsigned int i;
1047
1048
0
  for (i = 1; i < ARR_SIZE(insn_name_maps); i++) {
1049
0
    if (!strcmp(name, insn_name_maps[i]))
1050
0
      return i;
1051
0
  }
1052
1053
  // not found
1054
0
  return AARCH64_INS_INVALID;
1055
0
}
1056
1057
#ifndef CAPSTONE_DIET
1058
1059
static const map_insn_ops insn_operands[] = {
1060
#include "AArch64GenCSMappingInsnOp.inc"
1061
};
1062
1063
void AArch64_reg_access(const cs_insn *insn, cs_regs regs_read,
1064
      uint8_t *regs_read_count, cs_regs regs_write,
1065
      uint8_t *regs_write_count)
1066
0
{
1067
0
  uint8_t i;
1068
0
  uint8_t read_count, write_count;
1069
0
  cs_aarch64 *aarch64 = &(insn->detail->aarch64);
1070
1071
0
  read_count = insn->detail->regs_read_count;
1072
0
  write_count = insn->detail->regs_write_count;
1073
1074
  // implicit registers
1075
0
  memcpy(regs_read, insn->detail->regs_read,
1076
0
         read_count * sizeof(insn->detail->regs_read[0]));
1077
0
  memcpy(regs_write, insn->detail->regs_write,
1078
0
         write_count * sizeof(insn->detail->regs_write[0]));
1079
1080
  // explicit registers
1081
0
  for (i = 0; i < aarch64->op_count; i++) {
1082
0
    cs_aarch64_op *op = &(aarch64->operands[i]);
1083
0
    switch ((int)op->type) {
1084
0
    case AARCH64_OP_REG:
1085
0
      if ((op->access & CS_AC_READ) &&
1086
0
          !arr_exist(regs_read, read_count, op->reg)) {
1087
0
        regs_read[read_count] = (uint16_t)op->reg;
1088
0
        read_count++;
1089
0
      }
1090
0
      if ((op->access & CS_AC_WRITE) &&
1091
0
          !arr_exist(regs_write, write_count, op->reg)) {
1092
0
        regs_write[write_count] = (uint16_t)op->reg;
1093
0
        write_count++;
1094
0
      }
1095
0
      break;
1096
0
    case AARCH64_OP_MEM:
1097
      // registers appeared in memory references always being read
1098
0
      if ((op->mem.base != AARCH64_REG_INVALID) &&
1099
0
          !arr_exist(regs_read, read_count, op->mem.base)) {
1100
0
        regs_read[read_count] = (uint16_t)op->mem.base;
1101
0
        read_count++;
1102
0
      }
1103
0
      if ((op->mem.index != AARCH64_REG_INVALID) &&
1104
0
          !arr_exist(regs_read, read_count, op->mem.index)) {
1105
0
        regs_read[read_count] = (uint16_t)op->mem.index;
1106
0
        read_count++;
1107
0
      }
1108
0
      if ((insn->detail->writeback) &&
1109
0
          (op->mem.base != AARCH64_REG_INVALID) &&
1110
0
          !arr_exist(regs_write, write_count, op->mem.base)) {
1111
0
        regs_write[write_count] =
1112
0
          (uint16_t)op->mem.base;
1113
0
        write_count++;
1114
0
      }
1115
0
      break;
1116
0
    case AARCH64_OP_SME:
1117
0
      if ((op->access & CS_AC_READ) &&
1118
0
          (op->sme.tile != AARCH64_REG_INVALID) &&
1119
0
          !arr_exist(regs_read, read_count, op->sme.tile)) {
1120
0
        regs_read[read_count] = (uint16_t)op->sme.tile;
1121
0
        read_count++;
1122
0
      }
1123
0
      if ((op->access & CS_AC_WRITE) &&
1124
0
          (op->sme.tile != AARCH64_REG_INVALID) &&
1125
0
          !arr_exist(regs_write, write_count, op->sme.tile)) {
1126
0
        regs_write[write_count] =
1127
0
          (uint16_t)op->sme.tile;
1128
0
        write_count++;
1129
0
      }
1130
0
      if ((op->sme.slice_reg != AARCH64_REG_INVALID) &&
1131
0
          !arr_exist(regs_read, read_count,
1132
0
               op->sme.slice_reg)) {
1133
0
        regs_read[read_count] =
1134
0
          (uint16_t)op->sme.slice_reg;
1135
0
        read_count++;
1136
0
      }
1137
0
      break;
1138
0
    case AARCH64_OP_PRED:
1139
0
      if ((op->access & CS_AC_READ) &&
1140
0
          (op->pred.reg != AARCH64_REG_INVALID) &&
1141
0
          !arr_exist(regs_read, read_count, op->pred.reg)) {
1142
0
        regs_read[read_count] = (uint16_t)op->pred.reg;
1143
0
        read_count++;
1144
0
      }
1145
0
      if ((op->access & CS_AC_WRITE) &&
1146
0
          (op->pred.reg != AARCH64_REG_INVALID) &&
1147
0
          !arr_exist(regs_write, write_count, op->pred.reg)) {
1148
0
        regs_write[write_count] =
1149
0
          (uint16_t)op->pred.reg;
1150
0
        write_count++;
1151
0
      }
1152
0
      if ((op->pred.vec_select != AARCH64_REG_INVALID) &&
1153
0
          !arr_exist(regs_read, read_count,
1154
0
               op->pred.vec_select)) {
1155
0
        regs_read[read_count] =
1156
0
          (uint16_t)op->pred.vec_select;
1157
0
        read_count++;
1158
0
      }
1159
0
      break;
1160
0
    default:
1161
0
      break;
1162
0
    }
1163
0
    if (op->shift.type >= AARCH64_SFT_LSL_REG) {
1164
0
      if (!arr_exist(regs_read, read_count,
1165
0
               op->shift.value)) {
1166
0
        regs_read[read_count] =
1167
0
          (uint16_t)op->shift.value;
1168
0
        read_count++;
1169
0
      }
1170
0
    }
1171
0
  }
1172
1173
0
  switch (insn->alias_id) {
1174
0
  default:
1175
0
    break;
1176
0
  case AARCH64_INS_ALIAS_RET:
1177
0
    regs_read[read_count] = AARCH64_REG_X30;
1178
0
    read_count++;
1179
0
    break;
1180
0
  }
1181
1182
0
  *regs_read_count = read_count;
1183
0
  *regs_write_count = write_count;
1184
0
}
1185
#endif
1186
1187
static AArch64Layout_VectorLayout get_vl_by_suffix(const char suffix)
1188
197k
{
1189
197k
  switch (suffix) {
1190
57.6k
  default:
1191
57.6k
    return AARCH64LAYOUT_INVALID;
1192
29.6k
  case 'b':
1193
29.6k
  case 'B':
1194
29.6k
    return AARCH64LAYOUT_VL_B;
1195
41.7k
  case 'h':
1196
41.7k
  case 'H':
1197
41.7k
    return AARCH64LAYOUT_VL_H;
1198
29.1k
  case 's':
1199
29.1k
  case 'S':
1200
29.1k
    return AARCH64LAYOUT_VL_S;
1201
36.6k
  case 'd':
1202
36.6k
  case 'D':
1203
36.6k
    return AARCH64LAYOUT_VL_D;
1204
2.72k
  case 'q':
1205
2.72k
  case 'Q':
1206
2.72k
    return AARCH64LAYOUT_VL_Q;
1207
197k
  }
1208
197k
}
1209
1210
static unsigned get_vec_list_num_regs(MCInst *MI, unsigned Reg)
1211
64.6k
{
1212
  // Work out how many registers there are in the list (if there is an actual
1213
  // list).
1214
64.6k
  unsigned NumRegs = 1;
1215
64.6k
  if (MCRegisterClass_contains(
1216
64.6k
        MCRegisterInfo_getRegClass(MI->MRI, AArch64_DDRegClassID),
1217
64.6k
        Reg) ||
1218
63.9k
      MCRegisterClass_contains(
1219
63.9k
        MCRegisterInfo_getRegClass(MI->MRI, AArch64_ZPR2RegClassID),
1220
63.9k
        Reg) ||
1221
52.5k
      MCRegisterClass_contains(
1222
52.5k
        MCRegisterInfo_getRegClass(MI->MRI, AArch64_QQRegClassID),
1223
52.5k
        Reg) ||
1224
46.5k
      MCRegisterClass_contains(
1225
46.5k
        MCRegisterInfo_getRegClass(MI->MRI, AArch64_PPR2RegClassID),
1226
46.5k
        Reg) ||
1227
45.2k
      MCRegisterClass_contains(
1228
45.2k
        MCRegisterInfo_getRegClass(MI->MRI,
1229
45.2k
                 AArch64_ZPR2StridedRegClassID),
1230
45.2k
        Reg))
1231
21.9k
    NumRegs = 2;
1232
42.6k
  else if (MCRegisterClass_contains(
1233
42.6k
       MCRegisterInfo_getRegClass(MI->MRI,
1234
42.6k
                AArch64_DDDRegClassID),
1235
42.6k
       Reg) ||
1236
41.0k
     MCRegisterClass_contains(
1237
41.0k
       MCRegisterInfo_getRegClass(MI->MRI,
1238
41.0k
                AArch64_ZPR3RegClassID),
1239
41.0k
       Reg) ||
1240
40.1k
     MCRegisterClass_contains(
1241
40.1k
       MCRegisterInfo_getRegClass(MI->MRI,
1242
40.1k
                AArch64_QQQRegClassID),
1243
40.1k
       Reg))
1244
10.1k
    NumRegs = 3;
1245
32.4k
  else if (MCRegisterClass_contains(
1246
32.4k
       MCRegisterInfo_getRegClass(MI->MRI,
1247
32.4k
                AArch64_DDDDRegClassID),
1248
32.4k
       Reg) ||
1249
32.1k
     MCRegisterClass_contains(
1250
32.1k
       MCRegisterInfo_getRegClass(MI->MRI,
1251
32.1k
                AArch64_ZPR4RegClassID),
1252
32.1k
       Reg) ||
1253
25.0k
     MCRegisterClass_contains(
1254
25.0k
       MCRegisterInfo_getRegClass(MI->MRI,
1255
25.0k
                AArch64_QQQQRegClassID),
1256
25.0k
       Reg) ||
1257
19.4k
     MCRegisterClass_contains(
1258
19.4k
       MCRegisterInfo_getRegClass(
1259
19.4k
         MI->MRI, AArch64_ZPR4StridedRegClassID),
1260
19.4k
       Reg))
1261
15.3k
    NumRegs = 4;
1262
64.6k
  return NumRegs;
1263
64.6k
}
1264
1265
static unsigned get_vec_list_stride(MCInst *MI, unsigned Reg)
1266
64.6k
{
1267
64.6k
  unsigned Stride = 1;
1268
64.6k
  if (MCRegisterClass_contains(
1269
64.6k
        MCRegisterInfo_getRegClass(MI->MRI,
1270
64.6k
                 AArch64_ZPR2StridedRegClassID),
1271
64.6k
        Reg))
1272
2.65k
    Stride = 8;
1273
61.9k
  else if (MCRegisterClass_contains(
1274
61.9k
       MCRegisterInfo_getRegClass(
1275
61.9k
         MI->MRI, AArch64_ZPR4StridedRegClassID),
1276
61.9k
       Reg))
1277
2.31k
    Stride = 4;
1278
64.6k
  return Stride;
1279
64.6k
}
1280
1281
static unsigned get_vec_list_first_reg(MCInst *MI, unsigned RegL)
1282
64.6k
{
1283
64.6k
  unsigned Reg = RegL;
1284
  // Now forget about the list and find out what the first register is.
1285
64.6k
  if (MCRegisterInfo_getSubReg(MI->MRI, RegL, AArch64_dsub0))
1286
2.62k
    Reg = MCRegisterInfo_getSubReg(MI->MRI, RegL, AArch64_dsub0);
1287
62.0k
  else if (MCRegisterInfo_getSubReg(MI->MRI, RegL, AArch64_qsub0))
1288
19.3k
    Reg = MCRegisterInfo_getSubReg(MI->MRI, RegL, AArch64_qsub0);
1289
42.6k
  else if (MCRegisterInfo_getSubReg(MI->MRI, RegL, AArch64_zsub0))
1290
24.2k
    Reg = MCRegisterInfo_getSubReg(MI->MRI, RegL, AArch64_zsub0);
1291
18.3k
  else if (MCRegisterInfo_getSubReg(MI->MRI, RegL, AArch64_psub0))
1292
1.23k
    Reg = MCRegisterInfo_getSubReg(MI->MRI, RegL, AArch64_psub0);
1293
1294
  // If it's a D-reg, we need to promote it to the equivalent Q-reg before
1295
  // printing (otherwise getRegisterName fails).
1296
64.6k
  if (MCRegisterClass_contains(MCRegisterInfo_getRegClass(
1297
64.6k
               MI->MRI, AArch64_FPR64RegClassID),
1298
64.6k
             Reg)) {
1299
2.98k
    const MCRegisterClass *FPR128RC = MCRegisterInfo_getRegClass(
1300
2.98k
      MI->MRI, AArch64_FPR128RegClassID);
1301
2.98k
    Reg = MCRegisterInfo_getMatchingSuperReg(
1302
2.98k
      MI->MRI, Reg, AArch64_dsub, FPR128RC);
1303
2.98k
  }
1304
64.6k
  return Reg;
1305
64.6k
}
1306
1307
static bool is_vector_reg(unsigned Reg)
1308
233k
{
1309
233k
  if ((Reg >= AArch64_Q0) && (Reg <= AArch64_Q31))
1310
70.3k
    return true;
1311
162k
  else if ((Reg >= AArch64_Z0) && (Reg <= AArch64_Z31))
1312
160k
    return true;
1313
2.55k
  else if ((Reg >= AArch64_P0) && (Reg <= AArch64_P15))
1314
2.55k
    return true;
1315
0
  return false;
1316
233k
}
1317
1318
static unsigned getNextVectorRegister(unsigned Reg, unsigned Stride /* = 1 */)
1319
153k
{
1320
386k
  while (Stride--) {
1321
233k
    if (!is_vector_reg(Reg)) {
1322
0
      CS_ASSERT(0 && "Vector register expected!");
1323
0
      return 0;
1324
0
    }
1325
    // Vector lists can wrap around.
1326
233k
    else if (Reg == AArch64_Q31)
1327
1.76k
      Reg = AArch64_Q0;
1328
    // Vector lists can wrap around.
1329
231k
    else if (Reg == AArch64_Z31)
1330
2.26k
      Reg = AArch64_Z0;
1331
    // Vector lists can wrap around.
1332
229k
    else if (Reg == AArch64_P15)
1333
160
      Reg = AArch64_P0;
1334
229k
    else
1335
      // Assume ordered registers
1336
229k
      ++Reg;
1337
233k
  }
1338
153k
  return Reg;
1339
153k
}
1340
1341
static aarch64_extender llvm_to_cs_ext(AArch64_AM_ShiftExtendType ExtType)
1342
15.9k
{
1343
15.9k
  switch (ExtType) {
1344
12.5k
  default:
1345
12.5k
    return AARCH64_EXT_INVALID;
1346
371
  case AArch64_AM_UXTB:
1347
371
    return AARCH64_EXT_UXTB;
1348
359
  case AArch64_AM_UXTH:
1349
359
    return AARCH64_EXT_UXTH;
1350
370
  case AArch64_AM_UXTW:
1351
370
    return AARCH64_EXT_UXTW;
1352
1.64k
  case AArch64_AM_UXTX:
1353
1.64k
    return AARCH64_EXT_UXTX;
1354
201
  case AArch64_AM_SXTB:
1355
201
    return AARCH64_EXT_SXTB;
1356
97
  case AArch64_AM_SXTH:
1357
97
    return AARCH64_EXT_SXTH;
1358
264
  case AArch64_AM_SXTW:
1359
264
    return AARCH64_EXT_SXTW;
1360
133
  case AArch64_AM_SXTX:
1361
133
    return AARCH64_EXT_SXTX;
1362
15.9k
  }
1363
15.9k
}
1364
1365
static aarch64_shifter llvm_to_cs_shift(AArch64_AM_ShiftExtendType ShiftExtType)
1366
12.5k
{
1367
12.5k
  switch (ShiftExtType) {
1368
0
  default:
1369
0
    return AARCH64_SFT_INVALID;
1370
6.72k
  case AArch64_AM_LSL:
1371
6.72k
    return AARCH64_SFT_LSL;
1372
2.49k
  case AArch64_AM_LSR:
1373
2.49k
    return AARCH64_SFT_LSR;
1374
1.43k
  case AArch64_AM_ASR:
1375
1.43k
    return AARCH64_SFT_ASR;
1376
1.38k
  case AArch64_AM_ROR:
1377
1.38k
    return AARCH64_SFT_ROR;
1378
476
  case AArch64_AM_MSL:
1379
476
    return AARCH64_SFT_MSL;
1380
12.5k
  }
1381
12.5k
}
1382
1383
/// Initializes or finishes a memory operand of Capstone (depending on \p
1384
/// status). A memory operand in Capstone can be assembled by two LLVM operands.
1385
/// E.g. the base register and the immediate disponent.
1386
void AArch64_set_mem_access(MCInst *MI, bool status)
1387
393k
{
1388
393k
  if (!detail_is_set(MI))
1389
0
    return;
1390
393k
  set_doing_mem(MI, status);
1391
393k
  if (status) {
1392
196k
    if (AArch64_get_detail(MI)->op_count > 0 &&
1393
194k
        AArch64_get_detail_op(MI, -1)->type == AARCH64_OP_MEM &&
1394
77.1k
        AArch64_get_detail_op(MI, -1)->mem.index ==
1395
77.1k
          AARCH64_REG_INVALID &&
1396
75.9k
        AArch64_get_detail_op(MI, -1)->mem.disp == 0) {
1397
      // Previous memory operand not done yet. Select it.
1398
75.9k
      AArch64_dec_op_count(MI);
1399
75.9k
      return;
1400
75.9k
    }
1401
1402
    // Init a new one.
1403
120k
    AArch64_get_detail_op(MI, 0)->type = AARCH64_OP_MEM;
1404
120k
    AArch64_get_detail_op(MI, 0)->mem.base = AARCH64_REG_INVALID;
1405
120k
    AArch64_get_detail_op(MI, 0)->mem.index = AARCH64_REG_INVALID;
1406
120k
    AArch64_get_detail_op(MI, 0)->mem.disp = 0;
1407
1408
120k
#ifndef CAPSTONE_DIET
1409
120k
    uint8_t access =
1410
120k
      map_get_op_access(MI, AArch64_get_detail(MI)->op_count);
1411
120k
    AArch64_get_detail_op(MI, 0)->access = access;
1412
120k
#endif
1413
196k
  } else {
1414
    // done, select the next operand slot
1415
196k
    AArch64_inc_op_count(MI);
1416
196k
  }
1417
393k
}
1418
1419
/// Common prefix for all AArch64_add_cs_detail_* functions
1420
static bool add_cs_detail_begin(MCInst *MI, unsigned op_num)
1421
1.01M
{
1422
1.01M
  if (!detail_is_set(MI) || !map_fill_detail_ops(MI))
1423
0
    return false;
1424
1425
1.01M
  if (AArch64_get_detail(MI)->is_doing_sme) {
1426
    // Unset the flag if there is no bound operand anymore.
1427
113k
    if (!(map_get_op_type(MI, op_num) & CS_OP_BOUND)) {
1428
81.6k
      AArch64_get_detail(MI)->is_doing_sme = false;
1429
81.6k
      AArch64_inc_op_count(MI);
1430
81.6k
    }
1431
113k
  }
1432
1.01M
  return true;
1433
1.01M
}
1434
1435
/// Fills cs_detail with the data of the operand.
1436
/// This function handles operands which's original printer function has no
1437
/// specialities.
1438
void AArch64_add_cs_detail_0(MCInst *MI, aarch64_op_group op_group,
1439
           unsigned OpNum)
1440
609k
{
1441
609k
  if (!add_cs_detail_begin(MI, OpNum))
1442
0
    return;
1443
1444
  // Fill cs_detail
1445
609k
  switch (op_group) {
1446
0
  default:
1447
0
    printf("ERROR: Operand group %d not handled!\n", op_group);
1448
0
    CS_ASSERT_RET(0);
1449
436k
  case AArch64_OP_GROUP_Operand: {
1450
436k
    cs_op_type primary_op_type = map_get_op_type(MI, OpNum) &
1451
436k
               ~(CS_OP_MEM | CS_OP_BOUND);
1452
436k
    switch (primary_op_type) {
1453
0
    default:
1454
0
      printf("Unhandled operand type 0x%x\n",
1455
0
             primary_op_type);
1456
0
      CS_ASSERT_RET(0);
1457
376k
    case AARCH64_OP_REG:
1458
376k
      AArch64_set_detail_op_reg(MI, OpNum,
1459
376k
              MCInst_getOpVal(MI, OpNum));
1460
376k
      break;
1461
59.2k
    case AARCH64_OP_IMM:
1462
59.2k
      AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
1463
59.2k
              MCInst_getOpVal(MI, OpNum));
1464
59.2k
      break;
1465
901
    case AARCH64_OP_FP: {
1466
      // printOperand does not handle FP operands. But sometimes
1467
      // is used to print FP operands as normal immediate.
1468
901
      AArch64_get_detail_op(MI, 0)->type = AARCH64_OP_IMM;
1469
901
      AArch64_get_detail_op(MI, 0)->imm =
1470
901
        MCInst_getOpVal(MI, OpNum);
1471
901
      AArch64_get_detail_op(MI, 0)->access =
1472
901
        map_get_op_access(MI, OpNum);
1473
901
      AArch64_inc_op_count(MI);
1474
901
      break;
1475
0
    }
1476
436k
    }
1477
436k
    break;
1478
436k
  }
1479
436k
  case AArch64_OP_GROUP_AddSubImm: {
1480
3.61k
    unsigned Val = (MCInst_getOpVal(MI, OpNum) & 0xfff);
1481
3.61k
    AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM, Val);
1482
    // Shift is added in printShifter()
1483
3.61k
    break;
1484
436k
  }
1485
0
  case AArch64_OP_GROUP_AdrLabel: {
1486
0
    if (MCOperand_isImm(MCInst_getOperand(MI, OpNum))) {
1487
0
      int64_t Offset = MCInst_getOpVal(MI, OpNum);
1488
0
      AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
1489
0
              (MI->address & -4) + Offset);
1490
0
    } else {
1491
      // Expression
1492
0
      AArch64_set_detail_op_imm(
1493
0
        MI, OpNum, AARCH64_OP_IMM,
1494
0
        MCOperand_isImm(MCInst_getOperand(MI, OpNum)));
1495
0
    }
1496
0
    break;
1497
436k
  }
1498
0
  case AArch64_OP_GROUP_AdrpLabel: {
1499
0
    if (MCOperand_isImm(MCInst_getOperand(MI, OpNum))) {
1500
0
      int64_t Offset = MCInst_getOpVal(MI, OpNum) * 4096;
1501
0
      AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
1502
0
              (MI->address & -4096) +
1503
0
                Offset);
1504
0
    } else {
1505
      // Expression
1506
0
      AArch64_set_detail_op_imm(
1507
0
        MI, OpNum, AARCH64_OP_IMM,
1508
0
        MCOperand_isImm(MCInst_getOperand(MI, OpNum)));
1509
0
    }
1510
0
    break;
1511
436k
  }
1512
8.02k
  case AArch64_OP_GROUP_AdrAdrpLabel: {
1513
8.02k
    if (!MCOperand_isImm(MCInst_getOperand(MI, OpNum))) {
1514
      // Expression
1515
0
      AArch64_set_detail_op_imm(
1516
0
        MI, OpNum, AARCH64_OP_IMM,
1517
0
        MCOperand_isImm(MCInst_getOperand(MI, OpNum)));
1518
0
      break;
1519
0
    }
1520
8.02k
    int64_t Offset = MCInst_getOpVal(MI, OpNum);
1521
8.02k
    uint64_t Address = MI->address;
1522
8.02k
    if (MCInst_getOpcode(MI) == AArch64_ADRP) {
1523
1.94k
      Offset = Offset * 4096;
1524
1.94k
      Address = Address & -4096;
1525
1.94k
    }
1526
8.02k
    AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
1527
8.02k
            Address + Offset);
1528
8.02k
    break;
1529
8.02k
  }
1530
16.5k
  case AArch64_OP_GROUP_AlignedLabel: {
1531
16.5k
    if (MCOperand_isImm(MCInst_getOperand(MI, OpNum))) {
1532
16.4k
      int64_t Offset = MCInst_getOpVal(MI, OpNum) * 4;
1533
16.4k
      AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
1534
16.4k
              MI->address + Offset);
1535
16.4k
    } else {
1536
      // Expression
1537
88
      AArch64_set_detail_op_imm(
1538
88
        MI, OpNum, AARCH64_OP_IMM,
1539
88
        MCOperand_isImm(MCInst_getOperand(MI, OpNum)));
1540
88
    }
1541
16.5k
    break;
1542
8.02k
  }
1543
0
  case AArch64_OP_GROUP_AMNoIndex: {
1544
0
    AArch64_set_detail_op_mem(MI, OpNum,
1545
0
            MCInst_getOpVal(MI, OpNum));
1546
0
    break;
1547
8.02k
  }
1548
3.44k
  case AArch64_OP_GROUP_ArithExtend: {
1549
3.44k
    unsigned Val = MCInst_getOpVal(MI, OpNum);
1550
3.44k
    AArch64_AM_ShiftExtendType ExtType =
1551
3.44k
      AArch64_AM_getArithExtendType(Val);
1552
3.44k
    unsigned ShiftVal = AArch64_AM_getArithShiftValue(Val);
1553
1554
3.44k
    AArch64_get_detail_op(MI, -1)->ext = llvm_to_cs_ext(ExtType);
1555
3.44k
    AArch64_get_detail_op(MI, -1)->shift.value = ShiftVal;
1556
3.44k
    AArch64_get_detail_op(MI, -1)->shift.type = AARCH64_SFT_LSL;
1557
3.44k
    break;
1558
8.02k
  }
1559
106
  case AArch64_OP_GROUP_BarriernXSOption: {
1560
106
    unsigned Val = MCInst_getOpVal(MI, OpNum);
1561
106
    aarch64_sysop sysop = { 0 };
1562
106
    const AArch64DBnXS_DBnXS *DB =
1563
106
      AArch64DBnXS_lookupDBnXSByEncoding(Val);
1564
106
    if (DB)
1565
106
      sysop.imm.dbnxs = (aarch64_dbnxs)DB->SysImm.dbnxs;
1566
0
    else
1567
0
      sysop.imm.raw_val = Val;
1568
106
    sysop.sub_type = AARCH64_OP_DBNXS;
1569
106
    AArch64_set_detail_op_sys(MI, OpNum, sysop, AARCH64_OP_SYSIMM);
1570
106
    break;
1571
8.02k
  }
1572
250
  case AArch64_OP_GROUP_AppleSysBarrierOption: {
1573
    // Proprietary stuff. We just add the
1574
    // immediate here.
1575
250
    unsigned Val = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1576
250
    AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM, Val);
1577
250
    break;
1578
8.02k
  }
1579
1.21k
  case AArch64_OP_GROUP_BarrierOption: {
1580
1.21k
    unsigned Val = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
1581
1.21k
    unsigned Opcode = MCInst_getOpcode(MI);
1582
1.21k
    aarch64_sysop sysop = { 0 };
1583
1584
1.21k
    if (Opcode == AArch64_ISB) {
1585
195
      const AArch64ISB_ISB *ISB =
1586
195
        AArch64ISB_lookupISBByEncoding(Val);
1587
195
      if (ISB)
1588
0
        sysop.alias.isb =
1589
0
          (aarch64_isb)ISB->SysAlias.isb;
1590
195
      else
1591
195
        sysop.alias.raw_val = Val;
1592
195
      sysop.sub_type = AARCH64_OP_ISB;
1593
195
      AArch64_set_detail_op_sys(MI, OpNum, sysop,
1594
195
              AARCH64_OP_SYSALIAS);
1595
1.01k
    } else if (Opcode == AArch64_TSB) {
1596
330
      const AArch64TSB_TSB *TSB =
1597
330
        AArch64TSB_lookupTSBByEncoding(Val);
1598
330
      if (TSB)
1599
330
        sysop.alias.tsb =
1600
330
          (aarch64_tsb)TSB->SysAlias.tsb;
1601
0
      else
1602
0
        sysop.alias.raw_val = Val;
1603
330
      sysop.sub_type = AARCH64_OP_TSB;
1604
330
      AArch64_set_detail_op_sys(MI, OpNum, sysop,
1605
330
              AARCH64_OP_SYSALIAS);
1606
686
    } else {
1607
686
      const AArch64DB_DB *DB =
1608
686
        AArch64DB_lookupDBByEncoding(Val);
1609
686
      if (DB)
1610
537
        sysop.alias.db = (aarch64_db)DB->SysAlias.db;
1611
149
      else
1612
149
        sysop.alias.raw_val = Val;
1613
686
      sysop.sub_type = AARCH64_OP_DB;
1614
686
      AArch64_set_detail_op_sys(MI, OpNum, sysop,
1615
686
              AARCH64_OP_SYSALIAS);
1616
686
    }
1617
1.21k
    break;
1618
8.02k
  }
1619
193
  case AArch64_OP_GROUP_BTIHintOp: {
1620
193
    aarch64_sysop sysop = { 0 };
1621
193
    unsigned btihintop = MCInst_getOpVal(MI, OpNum) ^ 32;
1622
193
    const AArch64BTIHint_BTI *BTI =
1623
193
      AArch64BTIHint_lookupBTIByEncoding(btihintop);
1624
193
    if (BTI)
1625
193
      sysop.alias.bti = (aarch64_bti)BTI->SysAlias.bti;
1626
0
    else
1627
0
      sysop.alias.raw_val = btihintop;
1628
193
    sysop.sub_type = AARCH64_OP_BTI;
1629
193
    AArch64_set_detail_op_sys(MI, OpNum, sysop,
1630
193
            AARCH64_OP_SYSALIAS);
1631
193
    break;
1632
8.02k
  }
1633
4.02k
  case AArch64_OP_GROUP_CondCode: {
1634
4.02k
    AArch64_get_detail(MI)->cc = MCInst_getOpVal(MI, OpNum);
1635
4.02k
    break;
1636
8.02k
  }
1637
1.75k
  case AArch64_OP_GROUP_ExtendedRegister: {
1638
1.75k
    AArch64_set_detail_op_reg(MI, OpNum,
1639
1.75k
            MCInst_getOpVal(MI, OpNum));
1640
1.75k
    break;
1641
8.02k
  }
1642
1.27k
  case AArch64_OP_GROUP_FPImmOperand: {
1643
1.27k
    MCOperand *MO = MCInst_getOperand(MI, (OpNum));
1644
1.27k
    float FPImm =
1645
1.27k
      MCOperand_isDFPImm(MO) ?
1646
0
        BitsToDouble(MCOperand_getImm(MO)) :
1647
1.27k
        AArch64_AM_getFPImmFloat(MCOperand_getImm(MO));
1648
1.27k
    AArch64_set_detail_op_float(MI, OpNum, FPImm);
1649
1.27k
    break;
1650
8.02k
  }
1651
3.77k
  case AArch64_OP_GROUP_GPR64as32: {
1652
3.77k
    unsigned Reg = MCInst_getOpVal(MI, OpNum);
1653
3.77k
    AArch64_set_detail_op_reg(MI, OpNum, getWRegFromXReg(Reg));
1654
3.77k
    break;
1655
8.02k
  }
1656
239
  case AArch64_OP_GROUP_GPR64x8: {
1657
239
    unsigned Reg = MCInst_getOpVal(MI, (OpNum));
1658
239
    Reg = MCRegisterInfo_getSubReg(MI->MRI, Reg, AArch64_x8sub_0);
1659
239
    AArch64_set_detail_op_reg(MI, OpNum, Reg);
1660
239
    break;
1661
8.02k
  }
1662
5.37k
  case AArch64_OP_GROUP_Imm:
1663
5.55k
  case AArch64_OP_GROUP_ImmHex:
1664
5.55k
    AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
1665
5.55k
            MCInst_getOpVal(MI, OpNum));
1666
5.55k
    break;
1667
0
  case AArch64_OP_GROUP_ImplicitlyTypedVectorList:
1668
    // The TypedVectorList implements the logic of implicitly typed operand.
1669
0
    AArch64_add_cs_detail_2(
1670
0
      MI, AArch64_OP_GROUP_TypedVectorList_0_b, OpNum, 0, 0);
1671
0
    break;
1672
441
  case AArch64_OP_GROUP_InverseCondCode: {
1673
441
    AArch64CC_CondCode CC = (AArch64CC_CondCode)MCOperand_getImm(
1674
441
      MCInst_getOperand(MI, (OpNum)));
1675
441
    AArch64_get_detail(MI)->cc = AArch64CC_getInvertedCondCode(CC);
1676
441
    break;
1677
5.37k
  }
1678
2.35k
  case AArch64_OP_GROUP_MatrixTile: {
1679
2.35k
    const char *RegName = AArch64_LLVM_getRegisterName(
1680
2.35k
      MCInst_getOpVal(MI, OpNum), AArch64_NoRegAltName);
1681
2.35k
    const char *Dot = strstr(RegName, ".");
1682
2.35k
    AArch64Layout_VectorLayout vas = AARCH64LAYOUT_INVALID;
1683
2.35k
    if (!Dot) {
1684
      // The matrix dimensions are machine dependent.
1685
      // Currently we do not support differentiation of machines.
1686
      // So we just indicate the use of the complete matrix.
1687
0
      vas = sme_reg_to_vas(MCInst_getOpVal(MI, OpNum));
1688
0
    } else
1689
2.35k
      vas = get_vl_by_suffix(Dot[1]);
1690
2.35k
    AArch64_set_detail_op_sme(MI, OpNum, AARCH64_SME_MATRIX_TILE,
1691
2.35k
            vas, 0, 0);
1692
2.35k
    break;
1693
5.37k
  }
1694
939
  case AArch64_OP_GROUP_MatrixTileList: {
1695
939
    unsigned MaxRegs = 8;
1696
939
    unsigned RegMask = MCInst_getOpVal(MI, (OpNum));
1697
1698
8.45k
    for (unsigned I = 0; I < MaxRegs; ++I) {
1699
7.51k
      unsigned Reg = RegMask & (1 << I);
1700
7.51k
      if (Reg == 0)
1701
4.44k
        continue;
1702
3.07k
      AArch64_get_detail_op(MI, 0)->is_list_member = true;
1703
3.07k
      AArch64_set_detail_op_sme(MI, OpNum,
1704
3.07k
              AARCH64_SME_MATRIX_TILE_LIST,
1705
3.07k
              AARCH64LAYOUT_VL_D,
1706
3.07k
              (int)(AARCH64_REG_ZAD0 + I),
1707
3.07k
              0);
1708
3.07k
      AArch64_inc_op_count(MI);
1709
3.07k
    }
1710
939
    AArch64_get_detail(MI)->is_doing_sme = false;
1711
939
    break;
1712
5.37k
  }
1713
1.55k
  case AArch64_OP_GROUP_MRSSystemRegister:
1714
5.48k
  case AArch64_OP_GROUP_MSRSystemRegister: {
1715
5.48k
    unsigned Val = MCInst_getOpVal(MI, OpNum);
1716
5.48k
    const AArch64SysReg_SysReg *Reg =
1717
5.48k
      AArch64SysReg_lookupSysRegByEncoding(Val);
1718
5.48k
    bool Read = (op_group == AArch64_OP_GROUP_MRSSystemRegister) ?
1719
5.48k
            true :
1720
5.48k
            false;
1721
1722
5.48k
    bool isValidSysReg =
1723
5.48k
      (Reg && (Read ? Reg->Readable : Reg->Writeable) &&
1724
661
       AArch64_testFeatureList(MI->csh->mode,
1725
661
             Reg->FeaturesRequired));
1726
1727
5.48k
    if (Reg && !isValidSysReg)
1728
915
      Reg = AArch64SysReg_lookupSysRegByName(Reg->AltName);
1729
5.48k
    aarch64_sysop sysop = { 0 };
1730
    // If Reg is NULL it is a generic system register.
1731
5.48k
    if (Reg)
1732
1.53k
      sysop.reg.sysreg = (aarch64_sysreg)Reg->SysReg.sysreg;
1733
3.94k
    else {
1734
3.94k
      sysop.reg.raw_val = Val;
1735
3.94k
    }
1736
5.48k
    aarch64_op_type type =
1737
5.48k
      (op_group == AArch64_OP_GROUP_MRSSystemRegister) ?
1738
1.55k
        AARCH64_OP_REG_MRS :
1739
5.48k
        AARCH64_OP_REG_MSR;
1740
5.48k
    sysop.sub_type = type;
1741
5.48k
    AArch64_set_detail_op_sys(MI, OpNum, sysop, AARCH64_OP_SYSREG);
1742
5.48k
    break;
1743
1.55k
  }
1744
381
  case AArch64_OP_GROUP_PSBHintOp: {
1745
381
    unsigned psbhintop = MCInst_getOpVal(MI, OpNum);
1746
381
    const AArch64PSBHint_PSB *PSB =
1747
381
      AArch64PSBHint_lookupPSBByEncoding(psbhintop);
1748
381
    aarch64_sysop sysop = { 0 };
1749
381
    if (PSB)
1750
381
      sysop.alias.psb = (aarch64_psb)PSB->SysAlias.psb;
1751
0
    else
1752
0
      sysop.alias.raw_val = psbhintop;
1753
381
    sysop.sub_type = AARCH64_OP_PSB;
1754
381
    AArch64_set_detail_op_sys(MI, OpNum, sysop,
1755
381
            AARCH64_OP_SYSALIAS);
1756
381
    break;
1757
1.55k
  }
1758
340
  case AArch64_OP_GROUP_RPRFMOperand: {
1759
340
    unsigned prfop = MCInst_getOpVal(MI, OpNum);
1760
340
    const AArch64PRFM_PRFM *PRFM =
1761
340
      AArch64PRFM_lookupPRFMByEncoding(prfop);
1762
340
    aarch64_sysop sysop = { 0 };
1763
340
    if (PRFM)
1764
109
      sysop.alias.prfm = (aarch64_prfm)PRFM->SysAlias.prfm;
1765
231
    else
1766
231
      sysop.alias.raw_val = prfop;
1767
340
    sysop.sub_type = AARCH64_OP_PRFM;
1768
340
    AArch64_set_detail_op_sys(MI, OpNum, sysop,
1769
340
            AARCH64_OP_SYSALIAS);
1770
340
    break;
1771
1.55k
  }
1772
7.91k
  case AArch64_OP_GROUP_ShiftedRegister: {
1773
7.91k
    AArch64_set_detail_op_reg(MI, OpNum,
1774
7.91k
            MCInst_getOpVal(MI, OpNum));
1775
    // Shift part is handled in printShifter()
1776
7.91k
    break;
1777
1.55k
  }
1778
12.5k
  case AArch64_OP_GROUP_Shifter: {
1779
12.5k
    unsigned Val = MCInst_getOpVal(MI, OpNum);
1780
12.5k
    AArch64_AM_ShiftExtendType ShExtType =
1781
12.5k
      AArch64_AM_getShiftType(Val);
1782
12.5k
    AArch64_get_detail_op(MI, -1)->ext = llvm_to_cs_ext(ShExtType);
1783
12.5k
    AArch64_get_detail_op(MI, -1)->shift.type =
1784
12.5k
      llvm_to_cs_shift(ShExtType);
1785
12.5k
    AArch64_get_detail_op(MI, -1)->shift.value =
1786
12.5k
      AArch64_AM_getShiftValue(Val);
1787
12.5k
    break;
1788
1.55k
  }
1789
1.50k
  case AArch64_OP_GROUP_SIMDType10Operand: {
1790
1.50k
    unsigned RawVal = MCInst_getOpVal(MI, OpNum);
1791
1.50k
    uint64_t Val = AArch64_AM_decodeAdvSIMDModImmType10(RawVal);
1792
1.50k
    AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM, Val);
1793
1.50k
    break;
1794
1.55k
  }
1795
0
  case AArch64_OP_GROUP_SVCROp: {
1796
0
    unsigned svcrop = MCInst_getOpVal(MI, OpNum);
1797
0
    const AArch64SVCR_SVCR *SVCR =
1798
0
      AArch64SVCR_lookupSVCRByEncoding(svcrop);
1799
0
    aarch64_sysop sysop = { 0 };
1800
0
    if (SVCR)
1801
0
      sysop.alias.svcr = (aarch64_svcr)SVCR->SysAlias.svcr;
1802
0
    else
1803
0
      sysop.alias.raw_val = svcrop;
1804
0
    sysop.sub_type = AARCH64_OP_SVCR;
1805
0
    AArch64_set_detail_op_sys(MI, OpNum, sysop,
1806
0
            AARCH64_OP_SYSALIAS);
1807
0
    break;
1808
1.55k
  }
1809
4.97k
  case AArch64_OP_GROUP_SVEPattern: {
1810
4.97k
    unsigned Val = MCInst_getOpVal(MI, OpNum);
1811
4.97k
    const AArch64SVEPredPattern_SVEPREDPAT *Pat =
1812
4.97k
      AArch64SVEPredPattern_lookupSVEPREDPATByEncoding(Val);
1813
4.97k
    if (!Pat) {
1814
1.94k
      AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
1815
1.94k
              Val);
1816
1.94k
      break;
1817
1.94k
    }
1818
3.03k
    aarch64_sysop sysop = { 0 };
1819
3.03k
    sysop.alias = Pat->SysAlias;
1820
3.03k
    sysop.sub_type = AARCH64_OP_SVEPREDPAT;
1821
3.03k
    AArch64_set_detail_op_sys(MI, OpNum, sysop,
1822
3.03k
            AARCH64_OP_SYSALIAS);
1823
3.03k
    break;
1824
4.97k
  }
1825
1.12k
  case AArch64_OP_GROUP_SVEVecLenSpecifier: {
1826
1.12k
    unsigned Val = MCInst_getOpVal(MI, OpNum);
1827
    // Pattern has only 1 bit
1828
1.12k
    if (Val > 1)
1829
0
      CS_ASSERT_RET(0 && "Invalid vector length specifier");
1830
1.12k
    const AArch64SVEVecLenSpecifier_SVEVECLENSPECIFIER *Pat =
1831
1.12k
      AArch64SVEVecLenSpecifier_lookupSVEVECLENSPECIFIERByEncoding(
1832
1.12k
        Val);
1833
1.12k
    if (!Pat)
1834
0
      break;
1835
1.12k
    aarch64_sysop sysop = { 0 };
1836
1.12k
    sysop.alias = Pat->SysAlias;
1837
1.12k
    sysop.sub_type = AARCH64_OP_SVEVECLENSPECIFIER;
1838
1.12k
    AArch64_set_detail_op_sys(MI, OpNum, sysop,
1839
1.12k
            AARCH64_OP_SYSALIAS);
1840
1.12k
    break;
1841
1.12k
  }
1842
8.96k
  case AArch64_OP_GROUP_SysCROperand: {
1843
8.96k
    uint64_t cimm = MCInst_getOpVal(MI, OpNum);
1844
8.96k
    AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_CIMM, cimm);
1845
8.96k
    break;
1846
1.12k
  }
1847
721
  case AArch64_OP_GROUP_SyspXzrPair: {
1848
721
    unsigned Reg = MCInst_getOpVal(MI, OpNum);
1849
721
    AArch64_set_detail_op_reg(MI, OpNum, Reg);
1850
721
    AArch64_set_detail_op_reg(MI, OpNum, Reg);
1851
721
    break;
1852
1.12k
  }
1853
272
  case AArch64_OP_GROUP_SystemPStateField: {
1854
272
    unsigned Val = MCInst_getOpVal(MI, OpNum);
1855
1856
272
    aarch64_sysop sysop = { 0 };
1857
272
    const AArch64PState_PStateImm0_15 *PStateImm15 =
1858
272
      AArch64PState_lookupPStateImm0_15ByEncoding(Val);
1859
272
    const AArch64PState_PStateImm0_1 *PStateImm1 =
1860
272
      AArch64PState_lookupPStateImm0_1ByEncoding(Val);
1861
272
    if (PStateImm15 &&
1862
112
        AArch64_testFeatureList(MI->csh->mode,
1863
112
              PStateImm15->FeaturesRequired)) {
1864
112
      sysop.alias = PStateImm15->SysAlias;
1865
112
      sysop.sub_type = AARCH64_OP_PSTATEIMM0_15;
1866
112
      AArch64_set_detail_op_sys(MI, OpNum, sysop,
1867
112
              AARCH64_OP_SYSALIAS);
1868
160
    } else if (PStateImm1 &&
1869
160
         AArch64_testFeatureList(
1870
160
           MI->csh->mode,
1871
160
           PStateImm1->FeaturesRequired)) {
1872
160
      sysop.alias = PStateImm1->SysAlias;
1873
160
      sysop.sub_type = AARCH64_OP_PSTATEIMM0_1;
1874
160
      AArch64_set_detail_op_sys(MI, OpNum, sysop,
1875
160
              AARCH64_OP_SYSALIAS);
1876
160
    } else {
1877
0
      AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
1878
0
              Val);
1879
0
    }
1880
272
    break;
1881
1.12k
  }
1882
75.0k
  case AArch64_OP_GROUP_VRegOperand: {
1883
75.0k
    unsigned Reg = MCInst_getOpVal(MI, OpNum);
1884
75.0k
    AArch64_get_detail_op(MI, 0)->is_vreg = true;
1885
75.0k
    AArch64_set_detail_op_reg(MI, OpNum, Reg);
1886
75.0k
    break;
1887
1.12k
  }
1888
609k
  }
1889
609k
}
1890
1891
/// Fills cs_detail with the data of the operand.
1892
/// This function handles operands which original printer function is a template
1893
/// with one argument.
1894
void AArch64_add_cs_detail_1(MCInst *MI, aarch64_op_group op_group,
1895
           unsigned OpNum, uint64_t temp_arg_0)
1896
310k
{
1897
310k
  if (!add_cs_detail_begin(MI, OpNum))
1898
0
    return;
1899
310k
  switch (op_group) {
1900
0
  default:
1901
0
    printf("ERROR: Operand group %d not handled!\n", op_group);
1902
0
    CS_ASSERT_RET(0);
1903
206
  case AArch64_OP_GROUP_GPRSeqPairsClassOperand_32:
1904
1.81k
  case AArch64_OP_GROUP_GPRSeqPairsClassOperand_64: {
1905
1.81k
    unsigned size = temp_arg_0;
1906
1.81k
    unsigned Reg = MCInst_getOpVal(MI, (OpNum));
1907
1908
1.81k
    unsigned Sube = (size == 32) ? AArch64_sube32 : AArch64_sube64;
1909
1.81k
    unsigned Subo = (size == 32) ? AArch64_subo32 : AArch64_subo64;
1910
1911
1.81k
    unsigned Even = MCRegisterInfo_getSubReg(MI->MRI, Reg, Sube);
1912
1.81k
    unsigned Odd = MCRegisterInfo_getSubReg(MI->MRI, Reg, Subo);
1913
1.81k
    AArch64_set_detail_op_reg(MI, OpNum, Even);
1914
1.81k
    AArch64_set_detail_op_reg(MI, OpNum, Odd);
1915
1.81k
    break;
1916
206
  }
1917
463
  case AArch64_OP_GROUP_Imm8OptLsl_int16_t:
1918
835
  case AArch64_OP_GROUP_Imm8OptLsl_int32_t:
1919
1.20k
  case AArch64_OP_GROUP_Imm8OptLsl_int64_t:
1920
1.88k
  case AArch64_OP_GROUP_Imm8OptLsl_int8_t:
1921
2.15k
  case AArch64_OP_GROUP_Imm8OptLsl_uint16_t:
1922
2.42k
  case AArch64_OP_GROUP_Imm8OptLsl_uint32_t:
1923
2.63k
  case AArch64_OP_GROUP_Imm8OptLsl_uint64_t:
1924
2.74k
  case AArch64_OP_GROUP_Imm8OptLsl_uint8_t: {
1925
2.74k
    unsigned UnscaledVal = MCInst_getOpVal(MI, (OpNum));
1926
2.74k
    unsigned Shift = MCInst_getOpVal(MI, (OpNum + 1));
1927
1928
2.74k
    if ((UnscaledVal == 0) &&
1929
851
        (AArch64_AM_getShiftValue(Shift) != 0)) {
1930
433
      AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
1931
433
              UnscaledVal);
1932
      // Shift is handled in printShifter()
1933
433
      break;
1934
433
    }
1935
1936
2.31k
#define SCALE_SET(T) \
1937
2.31k
  do { \
1938
2.31k
    T Val; \
1939
2.31k
    if (CHAR(T) == 'i') /* Signed */ \
1940
2.31k
      Val = (int8_t)UnscaledVal * \
1941
1.70k
            (1 << AArch64_AM_getShiftValue(Shift)); \
1942
2.31k
    else \
1943
2.31k
      Val = (uint8_t)UnscaledVal * \
1944
603
            (1 << AArch64_AM_getShiftValue(Shift)); \
1945
2.31k
    AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM, Val); \
1946
2.31k
  } while (0)
1947
1948
2.31k
    switch (op_group) {
1949
0
    default:
1950
0
      CS_ASSERT_RET(
1951
0
        0 &&
1952
0
        "Operand group for Imm8OptLsl not handled.");
1953
385
    case AArch64_OP_GROUP_Imm8OptLsl_int16_t: {
1954
385
      SCALE_SET(int16_t);
1955
385
      break;
1956
0
    }
1957
348
    case AArch64_OP_GROUP_Imm8OptLsl_int32_t: {
1958
348
      SCALE_SET(int32_t);
1959
348
      break;
1960
0
    }
1961
300
    case AArch64_OP_GROUP_Imm8OptLsl_int64_t: {
1962
300
      SCALE_SET(int64_t);
1963
300
      break;
1964
0
    }
1965
674
    case AArch64_OP_GROUP_Imm8OptLsl_int8_t: {
1966
674
      SCALE_SET(int8_t);
1967
674
      break;
1968
0
    }
1969
167
    case AArch64_OP_GROUP_Imm8OptLsl_uint16_t: {
1970
167
      SCALE_SET(uint16_t);
1971
167
      break;
1972
0
    }
1973
168
    case AArch64_OP_GROUP_Imm8OptLsl_uint32_t: {
1974
168
      SCALE_SET(uint32_t);
1975
168
      break;
1976
0
    }
1977
157
    case AArch64_OP_GROUP_Imm8OptLsl_uint64_t: {
1978
157
      SCALE_SET(uint64_t);
1979
157
      break;
1980
0
    }
1981
111
    case AArch64_OP_GROUP_Imm8OptLsl_uint8_t: {
1982
111
      SCALE_SET(uint8_t);
1983
111
      break;
1984
0
    }
1985
2.31k
    }
1986
2.31k
    break;
1987
2.31k
  }
1988
4.75k
  case AArch64_OP_GROUP_ImmScale_16:
1989
6.19k
  case AArch64_OP_GROUP_ImmScale_2:
1990
6.79k
  case AArch64_OP_GROUP_ImmScale_3:
1991
6.86k
  case AArch64_OP_GROUP_ImmScale_32:
1992
16.8k
  case AArch64_OP_GROUP_ImmScale_4:
1993
24.4k
  case AArch64_OP_GROUP_ImmScale_8: {
1994
24.4k
    unsigned Scale = temp_arg_0;
1995
24.4k
    AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
1996
24.4k
            Scale * MCInst_getOpVal(MI, OpNum));
1997
24.4k
    break;
1998
16.8k
  }
1999
1.40k
  case AArch64_OP_GROUP_LogicalImm_int16_t:
2000
3.12k
  case AArch64_OP_GROUP_LogicalImm_int32_t:
2001
6.27k
  case AArch64_OP_GROUP_LogicalImm_int64_t:
2002
8.29k
  case AArch64_OP_GROUP_LogicalImm_int8_t: {
2003
8.29k
    unsigned TypeSize = temp_arg_0;
2004
8.29k
    uint64_t Val = AArch64_AM_decodeLogicalImmediate(
2005
8.29k
      MCInst_getOpVal(MI, OpNum), 8 * TypeSize);
2006
8.29k
    AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM, Val);
2007
8.29k
    break;
2008
6.27k
  }
2009
1.03k
  case AArch64_OP_GROUP_Matrix_0:
2010
2.94k
  case AArch64_OP_GROUP_Matrix_16:
2011
7.18k
  case AArch64_OP_GROUP_Matrix_32:
2012
8.94k
  case AArch64_OP_GROUP_Matrix_64: {
2013
8.94k
    unsigned EltSize = temp_arg_0;
2014
8.94k
    AArch64_set_detail_op_sme(MI, OpNum, AARCH64_SME_MATRIX_TILE,
2015
8.94k
            (AArch64Layout_VectorLayout)EltSize,
2016
8.94k
            0, 0);
2017
8.94k
    break;
2018
7.18k
  }
2019
0
  case AArch64_OP_GROUP_MatrixIndex_0:
2020
9.69k
  case AArch64_OP_GROUP_MatrixIndex_1:
2021
9.89k
  case AArch64_OP_GROUP_MatrixIndex_8: {
2022
9.89k
    unsigned scale = temp_arg_0;
2023
9.89k
    if (AArch64_get_detail_op(MI, 0)->type == AARCH64_OP_SME) {
2024
      // The index is part of an SME matrix
2025
8.80k
      AArch64_set_detail_op_sme(
2026
8.80k
        MI, OpNum, AARCH64_SME_MATRIX_SLICE_OFF,
2027
8.80k
        AARCH64LAYOUT_INVALID,
2028
8.80k
        (uint32_t)(MCInst_getOpVal(MI, OpNum) * scale),
2029
8.80k
        0);
2030
8.80k
    } else if (AArch64_get_detail_op(MI, 0)->type ==
2031
1.08k
         AARCH64_OP_PRED) {
2032
      // The index is part of a predicate
2033
831
      AArch64_set_detail_op_pred(MI, OpNum);
2034
831
    } else {
2035
      // The index is used for an SVE2 instruction.
2036
258
      AArch64_set_detail_op_imm(
2037
258
        MI, OpNum, AARCH64_OP_IMM,
2038
258
        scale * MCInst_getOpVal(MI, OpNum));
2039
258
    }
2040
9.89k
    break;
2041
9.69k
  }
2042
3.16k
  case AArch64_OP_GROUP_MatrixTileVector_0:
2043
5.96k
  case AArch64_OP_GROUP_MatrixTileVector_1: {
2044
5.96k
    bool isVertical = temp_arg_0;
2045
5.96k
    const char *RegName = AArch64_LLVM_getRegisterName(
2046
5.96k
      MCInst_getOpVal(MI, OpNum), AArch64_NoRegAltName);
2047
5.96k
    const char *Dot = strstr(RegName, ".");
2048
5.96k
    AArch64Layout_VectorLayout vas = AARCH64LAYOUT_INVALID;
2049
5.96k
    if (!Dot) {
2050
      // The matrix dimensions are machine dependent.
2051
      // Currently we do not support differentiation of machines.
2052
      // So we just indicate the use of the complete matrix.
2053
0
      vas = sme_reg_to_vas(MCInst_getOpVal(MI, OpNum));
2054
0
    } else
2055
5.96k
      vas = get_vl_by_suffix(Dot[1]);
2056
5.96k
    setup_sme_operand(MI);
2057
5.96k
    AArch64_set_detail_op_sme(MI, OpNum, AARCH64_SME_MATRIX_TILE,
2058
5.96k
            vas, 0, 0);
2059
5.96k
    AArch64_get_detail_op(MI, 0)->sme.is_vertical = isVertical;
2060
5.96k
    break;
2061
3.16k
  }
2062
887
  case AArch64_OP_GROUP_PostIncOperand_1:
2063
1.41k
  case AArch64_OP_GROUP_PostIncOperand_12:
2064
2.61k
  case AArch64_OP_GROUP_PostIncOperand_16:
2065
3.54k
  case AArch64_OP_GROUP_PostIncOperand_2:
2066
4.89k
  case AArch64_OP_GROUP_PostIncOperand_24:
2067
5.76k
  case AArch64_OP_GROUP_PostIncOperand_3:
2068
6.23k
  case AArch64_OP_GROUP_PostIncOperand_32:
2069
7.35k
  case AArch64_OP_GROUP_PostIncOperand_4:
2070
7.37k
  case AArch64_OP_GROUP_PostIncOperand_48:
2071
8.78k
  case AArch64_OP_GROUP_PostIncOperand_6:
2072
8.91k
  case AArch64_OP_GROUP_PostIncOperand_64:
2073
10.3k
  case AArch64_OP_GROUP_PostIncOperand_8: {
2074
10.3k
    uint64_t Imm = temp_arg_0;
2075
10.3k
    unsigned Reg = MCInst_getOpVal(MI, OpNum);
2076
10.3k
    if (Reg == AArch64_XZR) {
2077
0
      AArch64_get_detail_op(MI, -1)->mem.disp = Imm;
2078
0
      AArch64_get_detail(MI)->post_index = true;
2079
0
      AArch64_inc_op_count(MI);
2080
0
    } else
2081
10.3k
      AArch64_set_detail_op_reg(MI, OpNum, Reg);
2082
10.3k
    break;
2083
8.91k
  }
2084
7.60k
  case AArch64_OP_GROUP_PredicateAsCounter_0:
2085
7.74k
  case AArch64_OP_GROUP_PredicateAsCounter_16:
2086
7.94k
  case AArch64_OP_GROUP_PredicateAsCounter_32:
2087
8.64k
  case AArch64_OP_GROUP_PredicateAsCounter_64:
2088
8.76k
  case AArch64_OP_GROUP_PredicateAsCounter_8: {
2089
8.76k
    unsigned EltSize = temp_arg_0;
2090
8.76k
    AArch64_get_detail_op(MI, 0)->vas = EltSize;
2091
8.76k
    AArch64_set_detail_op_reg(MI, OpNum,
2092
8.76k
            MCInst_getOpVal(MI, OpNum));
2093
8.76k
    break;
2094
8.64k
  }
2095
4.29k
  case AArch64_OP_GROUP_PrefetchOp_0:
2096
8.57k
  case AArch64_OP_GROUP_PrefetchOp_1: {
2097
8.57k
    bool IsSVEPrefetch = (bool)temp_arg_0;
2098
8.57k
    unsigned prfop = MCInst_getOpVal(MI, (OpNum));
2099
8.57k
    aarch64_sysop sysop = { 0 };
2100
8.57k
    if (IsSVEPrefetch) {
2101
4.28k
      const AArch64SVEPRFM_SVEPRFM *PRFM =
2102
4.28k
        AArch64SVEPRFM_lookupSVEPRFMByEncoding(prfop);
2103
4.28k
      if (PRFM) {
2104
3.80k
        sysop.alias = PRFM->SysAlias;
2105
3.80k
        sysop.sub_type = AARCH64_OP_SVEPRFM;
2106
3.80k
        AArch64_set_detail_op_sys(MI, OpNum, sysop,
2107
3.80k
                AARCH64_OP_SYSALIAS);
2108
3.80k
        break;
2109
3.80k
      }
2110
4.29k
    } else {
2111
4.29k
      const AArch64PRFM_PRFM *PRFM =
2112
4.29k
        AArch64PRFM_lookupPRFMByEncoding(prfop);
2113
4.29k
      if (PRFM &&
2114
2.27k
          AArch64_testFeatureList(MI->csh->mode,
2115
2.27k
                PRFM->FeaturesRequired)) {
2116
2.27k
        sysop.alias = PRFM->SysAlias;
2117
2.27k
        sysop.sub_type = AARCH64_OP_PRFM;
2118
2.27k
        AArch64_set_detail_op_sys(MI, OpNum, sysop,
2119
2.27k
                AARCH64_OP_SYSALIAS);
2120
2.27k
        break;
2121
2.27k
      }
2122
4.29k
    }
2123
2.49k
    AArch64_get_detail_op(MI, 0)->type = AARCH64_OP_IMM;
2124
2.49k
    AArch64_get_detail_op(MI, 0)->imm = prfop;
2125
2.49k
    AArch64_get_detail_op(MI, 0)->access =
2126
2.49k
      map_get_op_access(MI, OpNum);
2127
2.49k
    AArch64_inc_op_count(MI);
2128
2.49k
    break;
2129
8.57k
  }
2130
773
  case AArch64_OP_GROUP_SImm_16:
2131
1.76k
  case AArch64_OP_GROUP_SImm_8: {
2132
1.76k
    AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
2133
1.76k
            MCInst_getOpVal(MI, OpNum));
2134
1.76k
    break;
2135
773
  }
2136
1.13k
  case AArch64_OP_GROUP_SVELogicalImm_int16_t:
2137
1.96k
  case AArch64_OP_GROUP_SVELogicalImm_int32_t:
2138
3.00k
  case AArch64_OP_GROUP_SVELogicalImm_int64_t: {
2139
    // General issue here that we do not save the operand type
2140
    // for each operand. So we choose the largest type.
2141
3.00k
    uint64_t Val = MCInst_getOpVal(MI, OpNum);
2142
3.00k
    uint64_t DecodedVal =
2143
3.00k
      AArch64_AM_decodeLogicalImmediate(Val, 64);
2144
3.00k
    AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
2145
3.00k
            DecodedVal);
2146
3.00k
    break;
2147
1.96k
  }
2148
49.6k
  case AArch64_OP_GROUP_SVERegOp_0:
2149
78.0k
  case AArch64_OP_GROUP_SVERegOp_b:
2150
103k
  case AArch64_OP_GROUP_SVERegOp_d:
2151
143k
  case AArch64_OP_GROUP_SVERegOp_h:
2152
145k
  case AArch64_OP_GROUP_SVERegOp_q:
2153
170k
  case AArch64_OP_GROUP_SVERegOp_s: {
2154
170k
    char Suffix = (char)temp_arg_0;
2155
170k
    AArch64_get_detail_op(MI, 0)->vas = get_vl_by_suffix(Suffix);
2156
170k
    AArch64_set_detail_op_reg(MI, OpNum,
2157
170k
            MCInst_getOpVal(MI, OpNum));
2158
170k
    break;
2159
145k
  }
2160
2.61k
  case AArch64_OP_GROUP_UImm12Offset_1:
2161
3.00k
  case AArch64_OP_GROUP_UImm12Offset_16:
2162
4.96k
  case AArch64_OP_GROUP_UImm12Offset_2:
2163
6.13k
  case AArch64_OP_GROUP_UImm12Offset_4:
2164
7.03k
  case AArch64_OP_GROUP_UImm12Offset_8: {
2165
    // Otherwise it is an expression. For which we only add the immediate
2166
7.03k
    unsigned Scale = MCOperand_isImm(MCInst_getOperand(MI, OpNum)) ?
2167
7.03k
           temp_arg_0 :
2168
7.03k
           1;
2169
7.03k
    AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM,
2170
7.03k
            Scale * MCInst_getOpVal(MI, OpNum));
2171
7.03k
    break;
2172
6.13k
  }
2173
36.5k
  case AArch64_OP_GROUP_VectorIndex_1:
2174
36.5k
  case AArch64_OP_GROUP_VectorIndex_8: {
2175
36.5k
    CS_ASSERT_RET(AArch64_get_detail(MI)->op_count > 0);
2176
36.5k
    unsigned Scale = temp_arg_0;
2177
36.5k
    unsigned VIndex = Scale * MCInst_getOpVal(MI, OpNum);
2178
    // The index can either be for one operand, or for each operand of a list.
2179
36.5k
    if (!AArch64_get_detail_op(MI, -1)->is_list_member) {
2180
20.1k
      AArch64_get_detail_op(MI, -1)->vector_index = VIndex;
2181
20.1k
      break;
2182
20.1k
    }
2183
58.1k
    for (int i = AArch64_get_detail(MI)->op_count - 1; i >= 0;
2184
41.8k
         --i) {
2185
41.8k
      if (!AArch64_get_detail(MI)->operands[i].is_list_member)
2186
0
        break;
2187
41.8k
      AArch64_get_detail(MI)->operands[i].vector_index =
2188
41.8k
        VIndex;
2189
41.8k
    }
2190
16.3k
    break;
2191
36.5k
  }
2192
72
  case AArch64_OP_GROUP_ZPRasFPR_128:
2193
1.11k
  case AArch64_OP_GROUP_ZPRasFPR_16:
2194
1.45k
  case AArch64_OP_GROUP_ZPRasFPR_32:
2195
2.09k
  case AArch64_OP_GROUP_ZPRasFPR_64:
2196
2.28k
  case AArch64_OP_GROUP_ZPRasFPR_8: {
2197
2.28k
    unsigned Base = AArch64_NoRegister;
2198
2.28k
    unsigned Width = temp_arg_0;
2199
2.28k
    switch (Width) {
2200
189
    case 8:
2201
189
      Base = AArch64_B0;
2202
189
      break;
2203
1.04k
    case 16:
2204
1.04k
      Base = AArch64_H0;
2205
1.04k
      break;
2206
340
    case 32:
2207
340
      Base = AArch64_S0;
2208
340
      break;
2209
643
    case 64:
2210
643
      Base = AArch64_D0;
2211
643
      break;
2212
72
    case 128:
2213
72
      Base = AArch64_Q0;
2214
72
      break;
2215
0
    default:
2216
0
      CS_ASSERT_RET(0 && "Unsupported width");
2217
2.28k
    }
2218
2.28k
    unsigned Reg = MCInst_getOpVal(MI, (OpNum));
2219
2.28k
    AArch64_set_detail_op_reg(MI, OpNum, Reg - AArch64_Z0 + Base);
2220
2.28k
    break;
2221
2.28k
  }
2222
310k
  }
2223
310k
}
2224
2225
/// Fills cs_detail with the data of the operand.
2226
/// This function handles operands which original printer function is a template
2227
/// with two arguments.
2228
void AArch64_add_cs_detail_2(MCInst *MI, aarch64_op_group op_group,
2229
           unsigned OpNum, uint64_t temp_arg_0,
2230
           uint64_t temp_arg_1)
2231
77.4k
{
2232
77.4k
  if (!add_cs_detail_begin(MI, OpNum))
2233
0
    return;
2234
77.4k
  switch (op_group) {
2235
0
  default:
2236
0
    printf("ERROR: Operand group %d not handled!\n", op_group);
2237
0
    CS_ASSERT_RET(0);
2238
489
  case AArch64_OP_GROUP_ComplexRotationOp_180_90:
2239
3.02k
  case AArch64_OP_GROUP_ComplexRotationOp_90_0: {
2240
3.02k
    unsigned Angle = temp_arg_0;
2241
3.02k
    unsigned Remainder = temp_arg_1;
2242
3.02k
    unsigned Imm = (MCInst_getOpVal(MI, OpNum) * Angle) + Remainder;
2243
3.02k
    AArch64_set_detail_op_imm(MI, OpNum, AARCH64_OP_IMM, Imm);
2244
3.02k
    break;
2245
489
  }
2246
179
  case AArch64_OP_GROUP_ExactFPImm_AArch64ExactFPImm_half_AArch64ExactFPImm_one:
2247
256
  case AArch64_OP_GROUP_ExactFPImm_AArch64ExactFPImm_half_AArch64ExactFPImm_two:
2248
578
  case AArch64_OP_GROUP_ExactFPImm_AArch64ExactFPImm_zero_AArch64ExactFPImm_one: {
2249
578
    aarch64_exactfpimm ImmIs0 = temp_arg_0;
2250
578
    aarch64_exactfpimm ImmIs1 = temp_arg_1;
2251
578
    const AArch64ExactFPImm_ExactFPImm *Imm0Desc =
2252
578
      AArch64ExactFPImm_lookupExactFPImmByEnum(ImmIs0);
2253
578
    const AArch64ExactFPImm_ExactFPImm *Imm1Desc =
2254
578
      AArch64ExactFPImm_lookupExactFPImmByEnum(ImmIs1);
2255
578
    unsigned Val = MCInst_getOpVal(MI, (OpNum));
2256
578
    aarch64_sysop sysop = { 0 };
2257
578
    sysop.imm = Val ? Imm1Desc->SysImm : Imm0Desc->SysImm;
2258
578
    sysop.sub_type = AARCH64_OP_EXACTFPIMM;
2259
578
    AArch64_set_detail_op_sys(MI, OpNum, sysop, AARCH64_OP_SYSIMM);
2260
578
    break;
2261
256
  }
2262
3.07k
  case AArch64_OP_GROUP_ImmRangeScale_2_1:
2263
6.09k
  case AArch64_OP_GROUP_ImmRangeScale_4_3: {
2264
6.09k
    uint64_t Scale = temp_arg_0;
2265
6.09k
    uint64_t Offset = temp_arg_1;
2266
6.09k
    unsigned FirstImm = Scale * MCInst_getOpVal(MI, (OpNum));
2267
6.09k
    AArch64_set_detail_op_imm_range(MI, OpNum, FirstImm,
2268
6.09k
            FirstImm + Offset);
2269
6.09k
    break;
2270
3.07k
  }
2271
42
  case AArch64_OP_GROUP_MemExtend_w_128:
2272
160
  case AArch64_OP_GROUP_MemExtend_w_16:
2273
190
  case AArch64_OP_GROUP_MemExtend_w_32:
2274
806
  case AArch64_OP_GROUP_MemExtend_w_64:
2275
1.15k
  case AArch64_OP_GROUP_MemExtend_w_8:
2276
1.23k
  case AArch64_OP_GROUP_MemExtend_x_128:
2277
1.68k
  case AArch64_OP_GROUP_MemExtend_x_16:
2278
1.73k
  case AArch64_OP_GROUP_MemExtend_x_32:
2279
2.67k
  case AArch64_OP_GROUP_MemExtend_x_64:
2280
3.12k
  case AArch64_OP_GROUP_MemExtend_x_8: {
2281
3.12k
    char SrcRegKind = (char)temp_arg_0;
2282
3.12k
    unsigned ExtWidth = temp_arg_1;
2283
3.12k
    bool SignExtend = MCInst_getOpVal(MI, OpNum);
2284
3.12k
    bool DoShift = MCInst_getOpVal(MI, OpNum + 1);
2285
3.12k
    AArch64_set_detail_shift_ext(MI, OpNum, SignExtend, DoShift,
2286
3.12k
               ExtWidth, SrcRegKind);
2287
3.12k
    break;
2288
2.67k
  }
2289
11.6k
  case AArch64_OP_GROUP_TypedVectorList_0_b:
2290
27.1k
  case AArch64_OP_GROUP_TypedVectorList_0_d:
2291
39.7k
  case AArch64_OP_GROUP_TypedVectorList_0_h:
2292
40.1k
  case AArch64_OP_GROUP_TypedVectorList_0_q:
2293
53.7k
  case AArch64_OP_GROUP_TypedVectorList_0_s:
2294
53.8k
  case AArch64_OP_GROUP_TypedVectorList_0_0:
2295
56.7k
  case AArch64_OP_GROUP_TypedVectorList_16_b:
2296
57.6k
  case AArch64_OP_GROUP_TypedVectorList_1_d:
2297
59.1k
  case AArch64_OP_GROUP_TypedVectorList_2_d:
2298
59.9k
  case AArch64_OP_GROUP_TypedVectorList_2_s:
2299
60.4k
  case AArch64_OP_GROUP_TypedVectorList_4_h:
2300
61.8k
  case AArch64_OP_GROUP_TypedVectorList_4_s:
2301
62.5k
  case AArch64_OP_GROUP_TypedVectorList_8_b:
2302
64.6k
  case AArch64_OP_GROUP_TypedVectorList_8_h: {
2303
64.6k
    uint8_t NumLanes = (uint8_t)temp_arg_0;
2304
64.6k
    char LaneKind = (char)temp_arg_1;
2305
64.6k
    uint16_t Pair = ((NumLanes << 8) | LaneKind);
2306
2307
64.6k
    AArch64Layout_VectorLayout vas = AARCH64LAYOUT_INVALID;
2308
64.6k
    switch (Pair) {
2309
0
    default:
2310
0
      printf("Typed vector list with NumLanes = %d and LaneKind = %c not handled.\n",
2311
0
             NumLanes, LaneKind);
2312
0
      CS_ASSERT_RET(0);
2313
745
    case ((8 << 8) | 'b'):
2314
745
      vas = AARCH64LAYOUT_VL_8B;
2315
745
      break;
2316
535
    case ((4 << 8) | 'h'):
2317
535
      vas = AARCH64LAYOUT_VL_4H;
2318
535
      break;
2319
734
    case ((2 << 8) | 's'):
2320
734
      vas = AARCH64LAYOUT_VL_2S;
2321
734
      break;
2322
972
    case ((1 << 8) | 'd'):
2323
972
      vas = AARCH64LAYOUT_VL_1D;
2324
972
      break;
2325
2.87k
    case ((16 << 8) | 'b'):
2326
2.87k
      vas = AARCH64LAYOUT_VL_16B;
2327
2.87k
      break;
2328
2.05k
    case ((8 << 8) | 'h'):
2329
2.05k
      vas = AARCH64LAYOUT_VL_8H;
2330
2.05k
      break;
2331
1.38k
    case ((4 << 8) | 's'):
2332
1.38k
      vas = AARCH64LAYOUT_VL_4S;
2333
1.38k
      break;
2334
1.51k
    case ((2 << 8) | 'd'):
2335
1.51k
      vas = AARCH64LAYOUT_VL_2D;
2336
1.51k
      break;
2337
11.6k
    case 'b':
2338
11.6k
      vas = AARCH64LAYOUT_VL_B;
2339
11.6k
      break;
2340
12.6k
    case 'h':
2341
12.6k
      vas = AARCH64LAYOUT_VL_H;
2342
12.6k
      break;
2343
13.5k
    case 's':
2344
13.5k
      vas = AARCH64LAYOUT_VL_S;
2345
13.5k
      break;
2346
15.4k
    case 'd':
2347
15.4k
      vas = AARCH64LAYOUT_VL_D;
2348
15.4k
      break;
2349
357
    case 'q':
2350
357
      vas = AARCH64LAYOUT_VL_Q;
2351
357
      break;
2352
112
    case '0':
2353
      // Implicitly Typed register
2354
112
      break;
2355
64.6k
    }
2356
2357
64.6k
    unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
2358
64.6k
    unsigned NumRegs = get_vec_list_num_regs(MI, Reg);
2359
64.6k
    unsigned Stride = get_vec_list_stride(MI, Reg);
2360
64.6k
    Reg = get_vec_list_first_reg(MI, Reg);
2361
2362
64.6k
    if ((MCRegisterClass_contains(
2363
64.6k
           MCRegisterInfo_getRegClass(MI->MRI,
2364
64.6k
              AArch64_ZPRRegClassID),
2365
64.6k
           Reg) ||
2366
28.3k
         MCRegisterClass_contains(
2367
28.3k
           MCRegisterInfo_getRegClass(MI->MRI,
2368
28.3k
              AArch64_PPRRegClassID),
2369
28.3k
           Reg)) &&
2370
37.5k
        NumRegs > 1 && Stride == 1 &&
2371
20.5k
        Reg < getNextVectorRegister(Reg, NumRegs - 1)) {
2372
20.3k
      AArch64_get_detail_op(MI, 0)->is_list_member = true;
2373
20.3k
      AArch64_get_detail_op(MI, 0)->vas = vas;
2374
20.3k
      AArch64_set_detail_op_reg(MI, OpNum, Reg);
2375
20.3k
      if (NumRegs > 1) {
2376
        // Add all registers of the list to the details.
2377
55.7k
        for (size_t i = 0; i < NumRegs - 1; ++i) {
2378
35.3k
          AArch64_get_detail_op(MI, 0)
2379
35.3k
            ->is_list_member = true;
2380
35.3k
          AArch64_get_detail_op(MI, 0)->vas = vas;
2381
35.3k
          AArch64_set_detail_op_reg(
2382
35.3k
            MI, OpNum,
2383
35.3k
            getNextVectorRegister(Reg + i,
2384
35.3k
                      1));
2385
35.3k
        }
2386
20.3k
      }
2387
44.3k
    } else {
2388
141k
      for (unsigned i = 0; i < NumRegs;
2389
97.4k
           ++i, Reg = getNextVectorRegister(Reg, Stride)) {
2390
97.4k
        if (!(MCRegisterClass_contains(
2391
97.4k
                MCRegisterInfo_getRegClass(
2392
97.4k
                  MI->MRI,
2393
97.4k
                  AArch64_ZPRRegClassID),
2394
97.4k
                Reg) ||
2395
70.5k
              MCRegisterClass_contains(
2396
70.5k
                MCRegisterInfo_getRegClass(
2397
70.5k
                  MI->MRI,
2398
70.5k
                  AArch64_PPRRegClassID),
2399
70.5k
                Reg))) {
2400
70.3k
          AArch64_get_detail_op(MI, 0)->is_vreg =
2401
70.3k
            true;
2402
70.3k
        }
2403
97.4k
        AArch64_get_detail_op(MI, 0)->is_list_member =
2404
97.4k
          true;
2405
97.4k
        AArch64_get_detail_op(MI, 0)->vas = vas;
2406
97.4k
        AArch64_set_detail_op_reg(MI, OpNum, Reg);
2407
97.4k
      }
2408
44.3k
    }
2409
64.6k
  }
2410
77.4k
  }
2411
77.4k
}
2412
2413
/// Fills cs_detail with the data of the operand.
2414
/// This function handles operands which original printer function is a template
2415
/// with four arguments.
2416
void AArch64_add_cs_detail_4(MCInst *MI, aarch64_op_group op_group,
2417
           unsigned OpNum, uint64_t temp_arg_0,
2418
           uint64_t temp_arg_1, uint64_t temp_arg_2,
2419
           uint64_t temp_arg_3)
2420
18.9k
{
2421
18.9k
  if (!add_cs_detail_begin(MI, OpNum))
2422
0
    return;
2423
18.9k
  switch (op_group) {
2424
0
  default:
2425
0
    printf("ERROR: Operand group %d not handled!\n", op_group);
2426
0
    CS_ASSERT_RET(0);
2427
532
  case AArch64_OP_GROUP_RegWithShiftExtend_0_128_x_0:
2428
1.34k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_16_w_d:
2429
1.48k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_16_w_s:
2430
3.43k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_16_x_0:
2431
3.62k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_16_x_d:
2432
3.70k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_16_x_s:
2433
4.57k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_32_w_d:
2434
4.70k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_32_w_s:
2435
6.33k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_32_x_0:
2436
6.71k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_32_x_d:
2437
6.73k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_32_x_s:
2438
7.54k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_64_w_d:
2439
7.58k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_64_w_s:
2440
9.13k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_64_x_0:
2441
9.93k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_64_x_d:
2442
10.0k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_64_x_s:
2443
10.7k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_8_w_d:
2444
10.9k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_8_w_s:
2445
13.2k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_8_x_0:
2446
15.1k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_8_x_d:
2447
15.1k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_8_x_s:
2448
15.6k
  case AArch64_OP_GROUP_RegWithShiftExtend_1_16_w_d:
2449
15.7k
  case AArch64_OP_GROUP_RegWithShiftExtend_1_16_w_s:
2450
16.1k
  case AArch64_OP_GROUP_RegWithShiftExtend_1_32_w_d:
2451
16.3k
  case AArch64_OP_GROUP_RegWithShiftExtend_1_32_w_s:
2452
16.9k
  case AArch64_OP_GROUP_RegWithShiftExtend_1_64_w_d:
2453
17.2k
  case AArch64_OP_GROUP_RegWithShiftExtend_1_64_w_s:
2454
18.4k
  case AArch64_OP_GROUP_RegWithShiftExtend_1_8_w_d:
2455
18.9k
  case AArch64_OP_GROUP_RegWithShiftExtend_1_8_w_s: {
2456
    // signed (s) and unsigned (u) extend
2457
18.9k
    bool SignExtend = (bool)temp_arg_0;
2458
    // Extend width
2459
18.9k
    int ExtWidth = (int)temp_arg_1;
2460
    // w = word, x = doubleword
2461
18.9k
    char SrcRegKind = (char)temp_arg_2;
2462
    // Vector register element/arrangement specifier:
2463
    // B = 8bit, H = 16bit, S = 32bit, D = 64bit, Q = 128bit
2464
    // No suffix = complete register
2465
    // According to: ARM Reference manual supplement, doc number: DDI 0584
2466
18.9k
    char Suffix = (char)temp_arg_3;
2467
2468
    // Register will be added in printOperand() afterwards. Here we only handle
2469
    // shift and extend.
2470
18.9k
    AArch64_get_detail_op(MI, -1)->vas = get_vl_by_suffix(Suffix);
2471
2472
18.9k
    bool DoShift = ExtWidth != 8;
2473
18.9k
    if (!(SignExtend || DoShift || SrcRegKind == 'w'))
2474
4.24k
      return;
2475
2476
14.7k
    AArch64_set_detail_shift_ext(MI, OpNum, SignExtend, DoShift,
2477
14.7k
               ExtWidth, SrcRegKind);
2478
14.7k
    break;
2479
18.9k
  }
2480
18.9k
  }
2481
18.9k
}
2482
2483
/// Adds a register AArch64 operand at position OpNum and increases the op_count by
2484
/// one.
2485
void AArch64_set_detail_op_reg(MCInst *MI, unsigned OpNum, aarch64_reg Reg)
2486
828k
{
2487
828k
  if (!detail_is_set(MI))
2488
0
    return;
2489
828k
  AArch64_check_safe_inc(MI);
2490
2491
828k
  if (Reg == AARCH64_REG_ZA ||
2492
828k
      (Reg >= AARCH64_REG_ZAB0 && Reg < AARCH64_REG_ZT0)) {
2493
    // A tile register should be treated as SME operand.
2494
0
    AArch64_set_detail_op_sme(MI, OpNum, AARCH64_SME_MATRIX_TILE,
2495
0
            sme_reg_to_vas(Reg), 0, 0);
2496
0
    return;
2497
828k
  } else if (((Reg >= AARCH64_REG_P0) && (Reg <= AARCH64_REG_P15)) ||
2498
765k
       ((Reg >= AARCH64_REG_PN0) && (Reg <= AARCH64_REG_PN15))) {
2499
    // SME/SVE predicate register.
2500
71.0k
    AArch64_set_detail_op_pred(MI, OpNum);
2501
71.0k
    return;
2502
757k
  } else if (AArch64_get_detail(MI)->is_doing_sme) {
2503
15.7k
    CS_ASSERT_RET(map_get_op_type(MI, OpNum) & CS_OP_BOUND);
2504
15.7k
    if (AArch64_get_detail_op(MI, 0)->type == AARCH64_OP_SME) {
2505
14.9k
      AArch64_set_detail_op_sme(MI, OpNum,
2506
14.9k
              AARCH64_SME_MATRIX_SLICE_REG,
2507
14.9k
              AARCH64LAYOUT_INVALID, 0, 0);
2508
14.9k
    } else if (AArch64_get_detail_op(MI, 0)->type ==
2509
831
         AARCH64_OP_PRED) {
2510
831
      AArch64_set_detail_op_pred(MI, OpNum);
2511
831
    } else {
2512
0
      CS_ASSERT_RET(0 && "Unkown SME/SVE operand type");
2513
0
    }
2514
15.7k
    return;
2515
15.7k
  }
2516
741k
  if (map_get_op_type(MI, OpNum) & CS_OP_MEM) {
2517
137k
    AArch64_set_detail_op_mem(MI, OpNum, Reg);
2518
137k
    return;
2519
137k
  }
2520
2521
604k
  CS_ASSERT_RET(!(map_get_op_type(MI, OpNum) & CS_OP_BOUND));
2522
604k
  CS_ASSERT_RET(!(map_get_op_type(MI, OpNum) & CS_OP_MEM));
2523
604k
  CS_ASSERT_RET(map_get_op_type(MI, OpNum) == CS_OP_REG);
2524
2525
604k
  AArch64_get_detail_op(MI, 0)->type = AARCH64_OP_REG;
2526
604k
  AArch64_get_detail_op(MI, 0)->reg = Reg;
2527
604k
  AArch64_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
2528
604k
  AArch64_inc_op_count(MI);
2529
604k
}
2530
2531
/// Check if the previous operand is a memory operand
2532
/// with only the base register set AND if this base register
2533
/// is write-back.
2534
/// This indicates the following immediate is a post-indexed
2535
/// memory offset.
2536
static bool prev_is_membase_wb(MCInst *MI)
2537
112k
{
2538
112k
  return AArch64_get_detail(MI)->op_count > 0 &&
2539
94.3k
         AArch64_get_detail_op(MI, -1)->type == AARCH64_OP_MEM &&
2540
7.92k
         AArch64_get_detail_op(MI, -1)->mem.disp == 0 &&
2541
7.92k
         get_detail(MI)->writeback;
2542
112k
}
2543
2544
/// Adds an immediate AArch64 operand at position OpNum and increases the op_count
2545
/// by one.
2546
void AArch64_set_detail_op_imm(MCInst *MI, unsigned OpNum,
2547
             aarch64_op_type ImmType, int64_t Imm)
2548
164k
{
2549
164k
  if (!detail_is_set(MI))
2550
0
    return;
2551
164k
  AArch64_check_safe_inc(MI);
2552
2553
164k
  if (AArch64_get_detail(MI)->is_doing_sme) {
2554
0
    CS_ASSERT_RET(map_get_op_type(MI, OpNum) & CS_OP_BOUND);
2555
0
    if (AArch64_get_detail_op(MI, 0)->type == AARCH64_OP_SME) {
2556
0
      AArch64_set_detail_op_sme(MI, OpNum,
2557
0
              AARCH64_SME_MATRIX_SLICE_OFF,
2558
0
              AARCH64LAYOUT_INVALID,
2559
0
              (uint32_t)1, 0);
2560
0
    } else if (AArch64_get_detail_op(MI, 0)->type ==
2561
0
         AARCH64_OP_PRED) {
2562
0
      AArch64_set_detail_op_pred(MI, OpNum);
2563
0
    } else {
2564
0
      CS_ASSERT_RET(0 && "Unkown SME operand type");
2565
0
    }
2566
0
    return;
2567
0
  }
2568
164k
  if (map_get_op_type(MI, OpNum) & CS_OP_MEM || prev_is_membase_wb(MI)) {
2569
59.8k
    AArch64_set_detail_op_mem(MI, OpNum, Imm);
2570
59.8k
    return;
2571
59.8k
  }
2572
2573
104k
  CS_ASSERT_RET(!(map_get_op_type(MI, OpNum) & CS_OP_MEM));
2574
104k
  CS_ASSERT_RET((map_get_op_type(MI, OpNum) & ~CS_OP_BOUND) == CS_OP_IMM);
2575
104k
  CS_ASSERT_RET(ImmType == AARCH64_OP_IMM || ImmType == AARCH64_OP_CIMM);
2576
2577
104k
  AArch64_get_detail_op(MI, 0)->type = ImmType;
2578
104k
  AArch64_get_detail_op(MI, 0)->imm = Imm;
2579
104k
  AArch64_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
2580
104k
  AArch64_inc_op_count(MI);
2581
104k
}
2582
2583
void AArch64_set_detail_op_imm_range(MCInst *MI, unsigned OpNum,
2584
             uint32_t FirstImm, uint32_t Offset)
2585
6.09k
{
2586
6.09k
  if (!detail_is_set(MI))
2587
0
    return;
2588
6.09k
  AArch64_check_safe_inc(MI);
2589
2590
6.09k
  if (AArch64_get_detail(MI)->is_doing_sme) {
2591
6.09k
    CS_ASSERT_RET(map_get_op_type(MI, OpNum) & CS_OP_BOUND);
2592
6.09k
    if (AArch64_get_detail_op(MI, 0)->type == AARCH64_OP_SME) {
2593
6.09k
      AArch64_set_detail_op_sme(
2594
6.09k
        MI, OpNum, AARCH64_SME_MATRIX_SLICE_OFF_RANGE,
2595
6.09k
        AARCH64LAYOUT_INVALID, (uint32_t)FirstImm,
2596
6.09k
        (uint32_t)Offset);
2597
6.09k
    } else if (AArch64_get_detail_op(MI, 0)->type ==
2598
0
         AARCH64_OP_PRED) {
2599
0
      CS_ASSERT_RET(0 &&
2600
0
              "Unkown SME predicate imm range type");
2601
0
    } else {
2602
0
      CS_ASSERT_RET(0 && "Unkown SME operand type");
2603
0
    }
2604
6.09k
    return;
2605
6.09k
  }
2606
2607
0
  CS_ASSERT_RET(!(map_get_op_type(MI, OpNum) & CS_OP_MEM));
2608
0
  CS_ASSERT_RET(map_get_op_type(MI, OpNum) == CS_OP_IMM);
2609
2610
0
  AArch64_get_detail_op(MI, 0)->type = AARCH64_OP_IMM_RANGE;
2611
0
  AArch64_get_detail_op(MI, 0)->imm_range.first = FirstImm;
2612
0
  AArch64_get_detail_op(MI, 0)->imm_range.offset = Offset;
2613
0
  AArch64_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
2614
0
  AArch64_inc_op_count(MI);
2615
0
}
2616
2617
/// Adds a memory AARCH64 operand at position OpNum. op_count is *not* increased by
2618
/// one. This is done by set_mem_access().
2619
void AArch64_set_detail_op_mem(MCInst *MI, unsigned OpNum, uint64_t Val)
2620
196k
{
2621
196k
  if (!detail_is_set(MI))
2622
0
    return;
2623
196k
  AArch64_check_safe_inc(MI);
2624
2625
196k
  AArch64_set_mem_access(MI, true);
2626
2627
196k
  cs_op_type secondary_type = map_get_op_type(MI, OpNum) & ~CS_OP_MEM;
2628
196k
  switch (secondary_type) {
2629
0
  default:
2630
0
    CS_ASSERT_RET(0 && "Secondary type not supported yet.");
2631
137k
  case CS_OP_REG: {
2632
137k
    bool is_index_reg = AArch64_get_detail_op(MI, 0)->mem.base !=
2633
137k
            AARCH64_REG_INVALID;
2634
137k
    if (is_index_reg)
2635
24.7k
      AArch64_get_detail_op(MI, 0)->mem.index = Val;
2636
112k
    else {
2637
112k
      AArch64_get_detail_op(MI, 0)->mem.base = Val;
2638
112k
    }
2639
2640
137k
    if (MCInst_opIsTying(MI, OpNum)) {
2641
      // Especially base registers can be writeback registers.
2642
      // For this they tie an MC operand which has write
2643
      // access. But this one is never processed in the printer
2644
      // (because it is never emitted). Therefor it is never
2645
      // added to the modified list.
2646
      // Here we check for this case and add the memory register
2647
      // to the modified list.
2648
29.6k
      map_add_implicit_write(MI, MCInst_getOpVal(MI, OpNum));
2649
29.6k
    }
2650
137k
    break;
2651
0
  }
2652
59.8k
  case CS_OP_IMM: {
2653
59.8k
    AArch64_get_detail_op(MI, 0)->mem.disp = Val;
2654
59.8k
    break;
2655
0
  }
2656
196k
  }
2657
2658
196k
  AArch64_get_detail_op(MI, 0)->type = AARCH64_OP_MEM;
2659
196k
  AArch64_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
2660
196k
  AArch64_set_mem_access(MI, false);
2661
196k
}
2662
2663
/// Adds the shift and sign extend info to the previous operand.
2664
/// op_count is *not* incremented by one.
2665
void AArch64_set_detail_shift_ext(MCInst *MI, unsigned OpNum, bool SignExtend,
2666
          bool DoShift, unsigned ExtWidth,
2667
          char SrcRegKind)
2668
17.8k
{
2669
17.8k
  bool IsLSL = !SignExtend && SrcRegKind == 'x';
2670
17.8k
  if (IsLSL)
2671
8.12k
    AArch64_get_detail_op(MI, -1)->shift.type = AARCH64_SFT_LSL;
2672
9.73k
  else {
2673
9.73k
    aarch64_extender ext = SignExtend ? AARCH64_EXT_SXTB :
2674
9.73k
                AARCH64_EXT_UXTB;
2675
9.73k
    switch (SrcRegKind) {
2676
0
    default:
2677
0
      CS_ASSERT_RET(0 && "Extender not handled\n");
2678
0
    case 'b':
2679
0
      ext += 0;
2680
0
      break;
2681
0
    case 'h':
2682
0
      ext += 1;
2683
0
      break;
2684
8.68k
    case 'w':
2685
8.68k
      ext += 2;
2686
8.68k
      break;
2687
1.04k
    case 'x':
2688
1.04k
      ext += 3;
2689
1.04k
      break;
2690
9.73k
    }
2691
9.73k
    AArch64_get_detail_op(MI, -1)->ext = ext;
2692
9.73k
  }
2693
17.8k
  if (DoShift || IsLSL) {
2694
14.3k
    unsigned ShiftAmount = DoShift ? Log2_32(ExtWidth / 8) : 0;
2695
14.3k
    AArch64_get_detail_op(MI, -1)->shift.type = AARCH64_SFT_LSL;
2696
14.3k
    AArch64_get_detail_op(MI, -1)->shift.value = ShiftAmount;
2697
14.3k
  }
2698
17.8k
}
2699
2700
/// Transforms the immediate of the operand to a float and stores it.
2701
/// Increments the op_counter by one.
2702
void AArch64_set_detail_op_float(MCInst *MI, unsigned OpNum, float Val)
2703
1.27k
{
2704
1.27k
  if (!detail_is_set(MI))
2705
0
    return;
2706
1.27k
  AArch64_check_safe_inc(MI);
2707
2708
1.27k
  AArch64_get_detail_op(MI, 0)->type = AARCH64_OP_FP;
2709
1.27k
  AArch64_get_detail_op(MI, 0)->fp = Val;
2710
1.27k
  AArch64_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
2711
1.27k
  AArch64_inc_op_count(MI);
2712
1.27k
}
2713
2714
/// Adds a the system operand and increases the op_count by
2715
/// one.
2716
void AArch64_set_detail_op_sys(MCInst *MI, unsigned OpNum, aarch64_sysop sys_op,
2717
             aarch64_op_type type)
2718
18.8k
{
2719
18.8k
  if (!detail_is_set(MI))
2720
0
    return;
2721
18.8k
  AArch64_check_safe_inc(MI);
2722
2723
18.8k
  AArch64_get_detail_op(MI, 0)->type = type;
2724
18.8k
  AArch64_get_detail_op(MI, 0)->sysop = sys_op;
2725
18.8k
  if (sys_op.sub_type == AARCH64_OP_EXACTFPIMM) {
2726
578
    AArch64_get_detail_op(MI, 0)->fp =
2727
578
      aarch64_exact_fp_to_fp(sys_op.imm.exactfpimm);
2728
578
  }
2729
18.8k
  AArch64_inc_op_count(MI);
2730
18.8k
}
2731
2732
void AArch64_set_detail_op_pred(MCInst *MI, unsigned OpNum)
2733
72.6k
{
2734
72.6k
  if (!detail_is_set(MI))
2735
0
    return;
2736
72.6k
  AArch64_check_safe_inc(MI);
2737
2738
72.6k
  if (AArch64_get_detail_op(MI, 0)->type == AARCH64_OP_INVALID) {
2739
69.7k
    setup_pred_operand(MI);
2740
69.7k
  }
2741
72.6k
  aarch64_op_pred *p = &AArch64_get_detail_op(MI, 0)->pred;
2742
72.6k
  if (p->reg == AARCH64_REG_INVALID) {
2743
69.7k
    p->reg = MCInst_getOpVal(MI, OpNum);
2744
69.7k
    AArch64_get_detail_op(MI, 0)->access =
2745
69.7k
      map_get_op_access(MI, OpNum);
2746
69.7k
    AArch64_get_detail(MI)->is_doing_sme = true;
2747
69.7k
    return;
2748
69.7k
  } else if (p->vec_select == AARCH64_REG_INVALID) {
2749
2.06k
    p->vec_select = MCInst_getOpVal(MI, OpNum);
2750
2.06k
    return;
2751
2.06k
  } else if (p->imm_index == -1) {
2752
831
    p->imm_index = MCInst_getOpVal(MI, OpNum);
2753
831
    return;
2754
831
  }
2755
0
  CS_ASSERT_RET(0 && "Should not be reached.");
2756
0
}
2757
2758
/// Adds a SME matrix component to a SME operand.
2759
void AArch64_set_detail_op_sme(MCInst *MI, unsigned OpNum,
2760
             aarch64_sme_op_part part,
2761
             AArch64Layout_VectorLayout vas, uint64_t arg_0,
2762
             uint64_t arg_1)
2763
50.1k
{
2764
50.1k
  if (!detail_is_set(MI))
2765
0
    return;
2766
50.1k
  AArch64_check_safe_inc(MI);
2767
2768
50.1k
  AArch64_get_detail_op(MI, 0)->type = AARCH64_OP_SME;
2769
50.1k
  switch (part) {
2770
0
  default:
2771
0
    printf("Unhandled SME operand part %d\n", part);
2772
0
    CS_ASSERT_RET(0);
2773
3.07k
  case AARCH64_SME_MATRIX_TILE_LIST: {
2774
3.07k
    setup_sme_operand(MI);
2775
3.07k
    int Tile = arg_0;
2776
3.07k
    AArch64_get_detail_op(MI, 0)->sme.type = AARCH64_SME_OP_TILE;
2777
3.07k
    AArch64_get_detail_op(MI, 0)->sme.tile = Tile;
2778
3.07k
    AArch64_get_detail_op(MI, 0)->vas = vas;
2779
3.07k
    AArch64_get_detail_op(MI, 0)->access =
2780
3.07k
      map_get_op_access(MI, OpNum);
2781
3.07k
    AArch64_get_detail(MI)->is_doing_sme = true;
2782
3.07k
    break;
2783
0
  }
2784
17.2k
  case AARCH64_SME_MATRIX_TILE:
2785
17.2k
    CS_ASSERT_RET(map_get_op_type(MI, OpNum) == CS_OP_REG);
2786
2787
17.2k
    setup_sme_operand(MI);
2788
17.2k
    AArch64_get_detail_op(MI, 0)->sme.type = AARCH64_SME_OP_TILE;
2789
17.2k
    AArch64_get_detail_op(MI, 0)->sme.tile =
2790
17.2k
      MCInst_getOpVal(MI, OpNum);
2791
17.2k
    AArch64_get_detail_op(MI, 0)->vas = vas;
2792
17.2k
    AArch64_get_detail_op(MI, 0)->access =
2793
17.2k
      map_get_op_access(MI, OpNum);
2794
17.2k
    AArch64_get_detail(MI)->is_doing_sme = true;
2795
17.2k
    break;
2796
14.9k
  case AARCH64_SME_MATRIX_SLICE_REG:
2797
14.9k
    CS_ASSERT_RET((map_get_op_type(MI, OpNum) &
2798
14.9k
             ~(CS_OP_MEM | CS_OP_BOUND)) == CS_OP_REG);
2799
14.9k
    CS_ASSERT_RET(AArch64_get_detail_op(MI, 0)->type ==
2800
14.9k
            AARCH64_OP_SME);
2801
2802
    // SME operand already present. Add the slice to it.
2803
14.9k
    AArch64_get_detail_op(MI, 0)->sme.type =
2804
14.9k
      AARCH64_SME_OP_TILE_VEC;
2805
14.9k
    AArch64_get_detail_op(MI, 0)->sme.slice_reg =
2806
14.9k
      MCInst_getOpVal(MI, OpNum);
2807
14.9k
    break;
2808
8.80k
  case AARCH64_SME_MATRIX_SLICE_OFF: {
2809
8.80k
    CS_ASSERT_RET((map_get_op_type(MI, OpNum) &
2810
8.80k
             ~(CS_OP_MEM | CS_OP_BOUND)) == CS_OP_IMM);
2811
    // Because we took care of the slice register before, the op at -1 must be a SME operand.
2812
8.80k
    CS_ASSERT_RET(AArch64_get_detail_op(MI, 0)->type ==
2813
8.80k
            AARCH64_OP_SME);
2814
8.80k
    CS_ASSERT_RET(
2815
8.80k
      AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm ==
2816
8.80k
      AARCH64_SLICE_IMM_INVALID);
2817
8.80k
    uint16_t offset = arg_0;
2818
8.80k
    AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm = offset;
2819
8.80k
    break;
2820
8.80k
  }
2821
6.09k
  case AARCH64_SME_MATRIX_SLICE_OFF_RANGE: {
2822
6.09k
    uint8_t First = arg_0;
2823
6.09k
    uint8_t Offset = arg_1;
2824
6.09k
    AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm_range.first =
2825
6.09k
      First;
2826
6.09k
    AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm_range.offset =
2827
6.09k
      Offset;
2828
6.09k
    AArch64_get_detail_op(MI, 0)->sme.has_range_offset = true;
2829
6.09k
    break;
2830
8.80k
  }
2831
50.1k
  }
2832
50.1k
}
2833
2834
static void insert_op(MCInst *MI, unsigned index, cs_aarch64_op op)
2835
16.7k
{
2836
16.7k
  if (!detail_is_set(MI)) {
2837
0
    return;
2838
0
  }
2839
2840
16.7k
  AArch64_check_safe_inc(MI);
2841
16.7k
  cs_aarch64_op *ops = AArch64_get_detail(MI)->operands;
2842
16.7k
  int i = AArch64_get_detail(MI)->op_count;
2843
16.7k
  if (index == -1) {
2844
16.7k
    ops[i] = op;
2845
16.7k
    AArch64_inc_op_count(MI);
2846
16.7k
    return;
2847
16.7k
  }
2848
0
  for (; i > 0 && i > index; --i) {
2849
0
    ops[i] = ops[i - 1];
2850
0
  }
2851
0
  ops[index] = op;
2852
0
  AArch64_inc_op_count(MI);
2853
0
}
2854
2855
/// Inserts a float to the detail operands at @index.
2856
/// If @index == -1, it pushes the operand to the end of the ops array.
2857
/// Already present operands are moved.
2858
void AArch64_insert_detail_op_float_at(MCInst *MI, unsigned index, double val,
2859
               cs_ac_type access)
2860
0
{
2861
0
  if (!detail_is_set(MI))
2862
0
    return;
2863
2864
0
  AArch64_check_safe_inc(MI);
2865
2866
0
  cs_aarch64_op op;
2867
0
  AArch64_setup_op(&op);
2868
0
  op.type = AARCH64_OP_FP;
2869
0
  op.fp = val;
2870
0
  op.access = access;
2871
2872
0
  insert_op(MI, index, op);
2873
0
}
2874
2875
/// Inserts a register to the detail operands at @index.
2876
/// If @index == -1, it pushes the operand to the end of the ops array.
2877
/// Already present operands are moved.
2878
void AArch64_insert_detail_op_reg_at(MCInst *MI, unsigned index,
2879
             aarch64_reg Reg, cs_ac_type access)
2880
368
{
2881
368
  if (!detail_is_set(MI))
2882
0
    return;
2883
2884
368
  AArch64_check_safe_inc(MI);
2885
2886
368
  cs_aarch64_op op;
2887
368
  AArch64_setup_op(&op);
2888
368
  op.type = AARCH64_OP_REG;
2889
368
  op.reg = Reg;
2890
368
  op.access = access;
2891
2892
368
  insert_op(MI, index, op);
2893
368
}
2894
2895
/// Inserts a immediate to the detail operands at @index.
2896
/// If @index == -1, it pushes the operand to the end of the ops array.
2897
/// Already present operands are moved.
2898
void AArch64_insert_detail_op_imm_at(MCInst *MI, unsigned index, int64_t Imm)
2899
6.47k
{
2900
6.47k
  if (!detail_is_set(MI))
2901
0
    return;
2902
6.47k
  AArch64_check_safe_inc(MI);
2903
2904
6.47k
  cs_aarch64_op op;
2905
6.47k
  AArch64_setup_op(&op);
2906
6.47k
  op.type = AARCH64_OP_IMM;
2907
6.47k
  op.imm = Imm;
2908
6.47k
  op.access = CS_AC_READ;
2909
2910
6.47k
  insert_op(MI, index, op);
2911
6.47k
}
2912
2913
void AArch64_insert_detail_op_sys(MCInst *MI, unsigned index,
2914
          aarch64_sysop sys_op, aarch64_op_type type)
2915
6.36k
{
2916
6.36k
  if (!detail_is_set(MI))
2917
0
    return;
2918
6.36k
  AArch64_check_safe_inc(MI);
2919
2920
6.36k
  cs_aarch64_op op;
2921
6.36k
  AArch64_setup_op(&op);
2922
6.36k
  op.type = type;
2923
6.36k
  op.sysop = sys_op;
2924
6.36k
  if (op.sysop.sub_type == AARCH64_OP_EXACTFPIMM) {
2925
6.17k
    op.fp = aarch64_exact_fp_to_fp(op.sysop.imm.exactfpimm);
2926
6.17k
  }
2927
6.36k
  insert_op(MI, index, op);
2928
6.36k
}
2929
2930
void AArch64_insert_detail_op_sme(MCInst *MI, unsigned index,
2931
          aarch64_op_sme sme_op)
2932
3.57k
{
2933
3.57k
  if (!detail_is_set(MI))
2934
0
    return;
2935
3.57k
  AArch64_check_safe_inc(MI);
2936
2937
3.57k
  cs_aarch64_op op;
2938
3.57k
  AArch64_setup_op(&op);
2939
3.57k
  op.type = AARCH64_OP_SME;
2940
3.57k
  op.sme = sme_op;
2941
3.57k
  insert_op(MI, index, op);
2942
3.57k
}
2943
2944
#endif