Coverage Report

Created: 2025-11-24 06:12

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