Coverage Report

Created: 2026-11-12 06:22

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