Coverage Report

Created: 2024-08-21 06:24

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