Coverage Report

Created: 2025-08-03 07:00

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