Coverage Report

Created: 2023-12-08 06:05

/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 aarch64_reg aarch64_flag_regs[] = {
24
  AArch64_REG_NZCV,
25
};
26
27
static aarch64_sysreg aarch64_flag_sys_regs[] = {
28
  AArch64_SYSREG_NZCV,
29
  AArch64_SYSREG_PMOVSCLR_EL0,
30
  AArch64_SYSREG_PMOVSSET_EL0,
31
  AArch64_SYSREG_SPMOVSCLR_EL0,
32
  AArch64_SYSREG_SPMOVSSET_EL0
33
};
34
#endif // CAPSTONE_DIET
35
36
575
static AArch64Layout_VectorLayout sme_reg_to_vas(aarch64_reg reg) {
37
575
  switch (reg) {
38
249
  default:
39
249
    return AArch64Layout_Invalid;
40
0
  case AArch64_REG_ZAB0:
41
0
    return AArch64Layout_VL_B;
42
0
  case AArch64_REG_ZAH0:
43
0
  case AArch64_REG_ZAH1:
44
0
    return AArch64Layout_VL_H;
45
0
  case AArch64_REG_ZAS0:
46
0
  case AArch64_REG_ZAS1:
47
0
  case AArch64_REG_ZAS2:
48
0
  case AArch64_REG_ZAS3:
49
0
    return AArch64Layout_VL_S;
50
0
  case AArch64_REG_ZAD0:
51
0
  case AArch64_REG_ZAD1:
52
0
  case AArch64_REG_ZAD2:
53
0
  case AArch64_REG_ZAD3:
54
0
  case AArch64_REG_ZAD4:
55
0
  case AArch64_REG_ZAD5:
56
0
  case AArch64_REG_ZAD6:
57
0
  case AArch64_REG_ZAD7:
58
0
    return AArch64Layout_VL_D;
59
0
  case AArch64_REG_ZAQ0:
60
0
  case AArch64_REG_ZAQ1:
61
0
  case AArch64_REG_ZAQ2:
62
0
  case AArch64_REG_ZAQ3:
63
0
  case AArch64_REG_ZAQ4:
64
0
  case AArch64_REG_ZAQ5:
65
0
  case AArch64_REG_ZAQ6:
66
0
  case AArch64_REG_ZAQ7:
67
0
  case AArch64_REG_ZAQ8:
68
0
  case AArch64_REG_ZAQ9:
69
0
  case AArch64_REG_ZAQ10:
70
0
  case AArch64_REG_ZAQ11:
71
0
  case AArch64_REG_ZAQ12:
72
0
  case AArch64_REG_ZAQ13:
73
0
  case AArch64_REG_ZAQ14:
74
0
  case AArch64_REG_ZAQ15:
75
0
    return AArch64Layout_VL_Q;
76
326
  case AArch64_REG_ZA:
77
326
    return AArch64Layout_VL_Complete;
78
575
  }
79
575
}
80
81
void AArch64_init_mri(MCRegisterInfo *MRI)
82
9.04k
{
83
9.04k
  MCRegisterInfo_InitMCRegisterInfo(
84
9.04k
    MRI, AArch64RegDesc, AArch64_REG_ENDING, 0, 0, AArch64MCRegisterClasses,
85
9.04k
    ARR_SIZE(AArch64MCRegisterClasses), 0, 0,
86
9.04k
    AArch64RegDiffLists, 0, AArch64SubRegIdxLists, ARR_SIZE(AArch64SubRegIdxLists), 0);
87
9.04k
}
88
89
const insn_map aarch64_insns[] = {
90
#include "AArch64GenCSMappingInsn.inc"
91
};
92
93
static const name_map insn_alias_mnem_map[] = {
94
#include "AArch64GenCSAliasMnemMap.inc"
95
  { AArch64_INS_ALIAS_CFP, "cfp" },
96
  { AArch64_INS_ALIAS_DVP, "dvp" },
97
  { AArch64_INS_ALIAS_COSP, "cosp" },
98
  { AArch64_INS_ALIAS_CPP, "cpp" },
99
  { AArch64_INS_ALIAS_IC, "ic" },
100
  { AArch64_INS_ALIAS_DC, "dc" },
101
  { AArch64_INS_ALIAS_AT, "at" },
102
  { AArch64_INS_ALIAS_TLBI, "tlbi" },
103
  { AArch64_INS_ALIAS_TLBIP, "tlbip" },
104
  { AArch64_INS_ALIAS_RPRFM, "rprfm" },
105
  { AArch64_INS_ALIAS_LSL, "lsl" },
106
  { AArch64_INS_ALIAS_SBFX, "sbfx" },
107
  { AArch64_INS_ALIAS_UBFX, "ubfx" },
108
  { AArch64_INS_ALIAS_SBFIZ, "sbfiz" },
109
  { AArch64_INS_ALIAS_UBFIZ, "ubfiz" },
110
  { AArch64_INS_ALIAS_BFC, "bfc" },
111
  { AArch64_INS_ALIAS_BFI, "bfi" },
112
  { AArch64_INS_ALIAS_BFXIL, "bfxil" },
113
  { AArch64_INS_ALIAS_END, NULL },
114
};
115
116
static const char *get_custom_reg_alias(unsigned reg)
117
48.6k
{
118
48.6k
  switch (reg) {
119
131
  case AArch64_REG_X29:
120
131
    return "fp";
121
1.75k
  case AArch64_REG_X30:
122
1.75k
    return "lr";
123
48.6k
  }
124
46.7k
  return NULL;
125
48.6k
}
126
127
/// Very annoyingly LLVM hard codes the vector layout post-fixes into the asm string.
128
/// In this function we check for these cases and add the vectorlayout/arrangement
129
/// specifier.
130
204k
void AArch64_add_vas(MCInst *MI, const SStream *OS) {
131
204k
  if (!detail_is_set(MI)) {
132
0
    return;
133
0
  }
134
135
204k
  if (AArch64_get_detail(MI)->op_count == 0) {
136
74
    return;
137
74
  }
138
139
  // Search for r".[0-9]{1,2}[bhsdq]\W"
140
  // with poor mans regex
141
204k
  const char *vl_ptr = strchr(OS->buffer, '.');
142
415k
  while (vl_ptr) {
143
    // Number after dot?
144
211k
    unsigned num = 0;
145
211k
    if (strchr("1248", vl_ptr[1])) {
146
54.1k
      num = atoi(vl_ptr + 1);
147
54.1k
      vl_ptr = num > 9 ? vl_ptr + 3 : vl_ptr + 2;
148
157k
    } else {
149
157k
      vl_ptr++;
150
157k
    }
151
152
    // Layout letter
153
211k
    char letter = '\0';
154
211k
    if (strchr("bhsdq", vl_ptr[0])) {
155
203k
      letter = vl_ptr[0];
156
203k
    }
157
211k
    if (!letter) {
158
7.59k
      goto next_dot_continue;
159
7.59k
    }
160
161
203k
    AArch64Layout_VectorLayout vl = AArch64Layout_Invalid;
162
203k
    switch (letter) {
163
0
    default:
164
0
      assert(0 && "Unhandled vector layout letter.");
165
0
      return;
166
40.5k
    case 'b':
167
40.5k
      vl = AArch64Layout_VL_B;
168
40.5k
      break;
169
52.7k
    case 'h':
170
52.7k
      vl = AArch64Layout_VL_H;
171
52.7k
      break;
172
59.1k
    case 's':
173
59.1k
      vl = AArch64Layout_VL_S;
174
59.1k
      break;
175
49.5k
    case 'd':
176
49.5k
      vl = AArch64Layout_VL_D;
177
49.5k
      break;
178
1.61k
    case 'q':
179
1.61k
      vl = AArch64Layout_VL_Q;
180
1.61k
      break;
181
203k
    }
182
203k
    vl |= (num << 8);
183
184
    // Determine op index by searching for trainling commata after op string
185
203k
    uint32_t op_idx = 0;
186
203k
    const char *comma_ptr = strchr(OS->buffer, ',');;
187
445k
    while (comma_ptr && comma_ptr < vl_ptr) {
188
241k
      ++op_idx;
189
241k
      comma_ptr = strchr(comma_ptr + 1, ',');
190
241k
    }
191
203k
    if (!comma_ptr) {
192
      // Last op doesn't have a trailing commata.
193
36.7k
      op_idx = AArch64_get_detail(MI)->op_count - 1;
194
36.7k
    }
195
203k
    if (op_idx >= AArch64_get_detail(MI)->op_count) {
196
      // A memory operand with a commata in [base, dist]
197
5.02k
      op_idx = AArch64_get_detail(MI)->op_count - 1;
198
5.02k
    }
199
200
    // Search for the operand this one belongs to.
201
203k
    cs_aarch64_op *op = &AArch64_get_detail(MI)->operands[op_idx];
202
203k
    if ((op->type != AArch64_OP_REG && op->type != AArch64_OP_SME_MATRIX) || op->vas != AArch64Layout_Invalid) {
203
163k
      goto next_dot_continue;
204
163k
    }
205
39.7k
    op->vas = vl;
206
207
211k
next_dot_continue:
208
211k
    vl_ptr = strchr(vl_ptr + 1, '.');
209
211k
  }
210
204k
}
211
212
const char *AArch64_reg_name(csh handle, unsigned int reg)
213
48.6k
{
214
48.6k
  int syntax_opt = ((cs_struct *)(uintptr_t)handle)->syntax;
215
48.6k
  const char *alias = get_custom_reg_alias(reg);
216
48.6k
  if ((syntax_opt & CS_OPT_SYNTAX_CS_REG_ALIAS) && alias)
217
0
    return alias;
218
219
48.6k
  if (((cs_struct *)(uintptr_t)handle)->syntax & CS_OPT_SYNTAX_NOREGNAME) {
220
0
    return AArch64_LLVM_getRegisterName(reg, AArch64_NoRegAltName);
221
0
  }
222
  // TODO Add options for the other register names
223
48.6k
  return AArch64_LLVM_getRegisterName(reg, AArch64_NoRegAltName);
224
48.6k
}
225
226
void AArch64_setup_op(cs_aarch64_op *op)
227
1.69M
{
228
1.69M
  memset(op, 0, sizeof(cs_aarch64_op));
229
1.69M
  op->type = AArch64_OP_INVALID;
230
1.69M
  op->vector_index = -1;
231
1.69M
}
232
233
void AArch64_init_cs_detail(MCInst *MI)
234
211k
{
235
211k
  if (detail_is_set(MI)) {
236
211k
    memset(get_detail(MI), 0,
237
211k
         offsetof(cs_detail, aarch64) + sizeof(cs_aarch64));
238
1.89M
    for (int i = 0; i < ARR_SIZE(AArch64_get_detail(MI)->operands); i++)
239
1.68M
      AArch64_setup_op(&AArch64_get_detail(MI)->operands[i]);
240
211k
    AArch64_get_detail(MI)->cc = AArch64CC_Invalid;
241
211k
  }
242
211k
}
243
244
/// Unfortunately, the AArch64 definitions do not indicate in any way
245
/// (exception are the instruction identifiers), if memory accesses
246
/// is post- or pre-indexed.
247
/// So the only generic way to determine, if the memory access is in
248
/// post-indexed addressing mode, is by search for "<membase>], #<memdisp>" in
249
/// @p OS.
250
/// Searching the asm string to determine such a property is enourmously ugly
251
/// and wastes resources.
252
/// Sorry, I know and do feel bad about it. But for now it works.
253
204k
static bool AArch64_check_post_index_am(const MCInst *MI, const SStream *OS) {
254
204k
  if (AArch64_get_detail(MI)->post_index) {
255
0
    return true;
256
0
  }
257
204k
  cs_aarch64_op *memop = NULL;
258
700k
  for (int i = 0; i < AArch64_get_detail(MI)->op_count; ++i) {
259
557k
    if (AArch64_get_detail(MI)->operands[i].type & CS_OP_MEM) {
260
61.5k
      memop = &AArch64_get_detail(MI)->operands[i];
261
61.5k
      break;
262
61.5k
    }
263
557k
  }
264
204k
  if (!memop)
265
142k
    return false;
266
267
61.5k
  const char *membase = AArch64_LLVM_getRegisterName(memop->mem.base, AArch64_NoRegAltName);
268
61.5k
  int64_t memdisp = memop->mem.disp;
269
61.5k
  SStream pattern = { 0 };
270
61.5k
  SStream_concat(&pattern, membase);
271
61.5k
  SStream_concat(&pattern, "], ");
272
61.5k
  printInt32Bang(&pattern, memdisp);
273
61.5k
  return strstr(OS->buffer, pattern.buffer) != NULL;
274
204k
}
275
276
static void AArch64_check_updates_flags(MCInst *MI)
277
204k
{
278
204k
#ifndef CAPSTONE_DIET
279
204k
  if (!detail_is_set(MI))
280
0
    return;
281
204k
  cs_detail *detail = get_detail(MI);
282
  // Implicity written registers
283
224k
  for (int i = 0; i < detail->regs_write_count; ++i) {
284
33.4k
    if (detail->regs_write[i] == 0)
285
0
      break;
286
54.0k
    for (int j = 0; j < ARR_SIZE(aarch64_flag_regs); ++j) {
287
33.4k
      if (detail->regs_write[i] == aarch64_flag_regs[j]) {
288
12.8k
        detail->aarch64.update_flags = true;
289
12.8k
        return;
290
12.8k
      }
291
33.4k
    }
292
33.4k
  }
293
720k
  for (int i = 0; i < detail->aarch64.op_count; ++i) {
294
529k
    if (detail->aarch64.operands[i].type == AArch64_OP_SYSREG &&
295
529k
      detail->aarch64.operands[i].sysop.sub_type == AArch64_OP_REG_MSR) {
296
11.1k
      for (int j = 0; j < ARR_SIZE(aarch64_flag_sys_regs); ++j)
297
9.35k
        if (detail->aarch64.operands[i].sysop.reg.sysreg == aarch64_flag_sys_regs[j]) {
298
76
          detail->aarch64.update_flags = true;
299
76
          return;
300
76
        }
301
527k
    } else if (detail->aarch64.operands[i].type == AArch64_OP_REG &&
302
527k
        detail->aarch64.operands[i].access & CS_AC_WRITE) {
303
331k
      for (int j = 0; j < ARR_SIZE(aarch64_flag_regs); ++j)
304
165k
        if (detail->aarch64.operands[i].reg == aarch64_flag_regs[j]) {
305
0
          detail->aarch64.update_flags = true;
306
0
          return;
307
0
        }
308
165k
    }
309
529k
  }
310
191k
#endif // CAPSTONE_DIET
311
191k
}
312
313
178k
static void add_non_alias_details(MCInst *MI) {
314
178k
  unsigned Opcode = MCInst_getOpcode(MI);
315
178k
  switch (Opcode) {
316
171k
  default:
317
171k
    break;
318
171k
  case AArch64_FCMPDri:
319
44
  case AArch64_FCMPEDri:
320
63
  case AArch64_FCMPEHri:
321
1.82k
  case AArch64_FCMPESri:
322
1.93k
  case AArch64_FCMPHri:
323
2.76k
  case AArch64_FCMPSri:
324
2.76k
    AArch64_insert_detail_op_reg_at(MI, -1, AArch64_REG_XZR, CS_AC_READ);
325
2.76k
    break;
326
10
  case AArch64_CMEQv16i8rz:
327
134
  case AArch64_CMEQv1i64rz:
328
166
  case AArch64_CMEQv2i32rz:
329
222
  case AArch64_CMEQv2i64rz:
330
253
  case AArch64_CMEQv4i16rz:
331
274
  case AArch64_CMEQv4i32rz:
332
297
  case AArch64_CMEQv8i16rz:
333
381
  case AArch64_CMEQv8i8rz:
334
407
  case AArch64_CMGEv16i8rz:
335
417
  case AArch64_CMGEv1i64rz:
336
544
  case AArch64_CMGEv2i32rz:
337
561
  case AArch64_CMGEv2i64rz:
338
582
  case AArch64_CMGEv4i16rz:
339
588
  case AArch64_CMGEv4i32rz:
340
599
  case AArch64_CMGEv8i16rz:
341
609
  case AArch64_CMGEv8i8rz:
342
619
  case AArch64_CMGTv16i8rz:
343
655
  case AArch64_CMGTv1i64rz:
344
667
  case AArch64_CMGTv2i32rz:
345
678
  case AArch64_CMGTv2i64rz:
346
699
  case AArch64_CMGTv4i16rz:
347
709
  case AArch64_CMGTv4i32rz:
348
719
  case AArch64_CMGTv8i16rz:
349
730
  case AArch64_CMGTv8i8rz:
350
816
  case AArch64_CMLEv16i8rz:
351
826
  case AArch64_CMLEv1i64rz:
352
848
  case AArch64_CMLEv2i32rz:
353
875
  case AArch64_CMLEv2i64rz:
354
893
  case AArch64_CMLEv4i16rz:
355
956
  case AArch64_CMLEv4i32rz:
356
966
  case AArch64_CMLEv8i16rz:
357
1.09k
  case AArch64_CMLEv8i8rz:
358
1.10k
  case AArch64_CMLTv16i8rz:
359
1.14k
  case AArch64_CMLTv1i64rz:
360
1.14k
  case AArch64_CMLTv2i32rz:
361
1.30k
  case AArch64_CMLTv2i64rz:
362
1.35k
  case AArch64_CMLTv4i16rz:
363
1.40k
  case AArch64_CMLTv4i32rz:
364
1.43k
  case AArch64_CMLTv8i16rz:
365
1.44k
  case AArch64_CMLTv8i8rz:
366
1.44k
    AArch64_insert_detail_op_imm_at(MI, -1, 0);
367
1.44k
    break;
368
6
  case AArch64_FCMEQv1i16rz:
369
24
  case AArch64_FCMEQv1i32rz:
370
42
  case AArch64_FCMEQv1i64rz:
371
52
  case AArch64_FCMEQv2i32rz:
372
60
  case AArch64_FCMEQv2i64rz:
373
72
  case AArch64_FCMEQv4i16rz:
374
90
  case AArch64_FCMEQv4i32rz:
375
130
  case AArch64_FCMEQv8i16rz:
376
148
  case AArch64_FCMGEv1i16rz:
377
160
  case AArch64_FCMGEv1i32rz:
378
181
  case AArch64_FCMGEv2i32rz:
379
191
  case AArch64_FCMGEv2i64rz:
380
204
  case AArch64_FCMGEv4i16rz:
381
214
  case AArch64_FCMGEv4i32rz:
382
224
  case AArch64_FCMGEv8i16rz:
383
230
  case AArch64_FCMGTv2i32rz:
384
329
  case AArch64_FCMGTv2i64rz:
385
339
  case AArch64_FCMGTv4i16rz:
386
357
  case AArch64_FCMGTv4i32rz:
387
368
  case AArch64_FCMGTv8i16rz:
388
437
  case AArch64_FCMLEv2i32rz:
389
457
  case AArch64_FCMLEv2i64rz:
390
478
  case AArch64_FCMLEv4i16rz:
391
489
  case AArch64_FCMLEv4i32rz:
392
511
  case AArch64_FCMLEv8i16rz:
393
521
  case AArch64_FCMEQ_PPzZ0_D:
394
540
  case AArch64_FCMEQ_PPzZ0_H:
395
865
  case AArch64_FCMEQ_PPzZ0_S:
396
871
  case AArch64_FCMGE_PPzZ0_D:
397
882
  case AArch64_FCMGE_PPzZ0_H:
398
1.71k
  case AArch64_FCMGE_PPzZ0_S:
399
1.73k
  case AArch64_FCMGT_PPzZ0_D:
400
1.74k
  case AArch64_FCMGT_PPzZ0_H:
401
1.82k
  case AArch64_FCMGT_PPzZ0_S:
402
1.86k
  case AArch64_FCMLE_PPzZ0_D:
403
1.87k
  case AArch64_FCMLE_PPzZ0_H:
404
1.88k
  case AArch64_FCMLE_PPzZ0_S:
405
1.92k
  case AArch64_FCMLT_PPzZ0_D:
406
1.93k
  case AArch64_FCMLT_PPzZ0_H:
407
1.97k
  case AArch64_FCMLT_PPzZ0_S:
408
1.98k
  case AArch64_FCMNE_PPzZ0_D:
409
2.00k
  case AArch64_FCMNE_PPzZ0_H:
410
2.01k
  case AArch64_FCMNE_PPzZ0_S:
411
2.02k
  case AArch64_FCMLTv2i32rz:
412
2.03k
  case AArch64_FCMLTv2i64rz:
413
2.04k
  case AArch64_FCMLTv4i16rz:
414
2.05k
  case AArch64_FCMLTv4i32rz:
415
2.07k
  case AArch64_FCMLTv8i16rz:
416
2.07k
    AArch64_insert_detail_op_float_at(MI, -1, 0.0f, CS_AC_READ);
417
2.07k
    break;
418
178k
  }
419
178k
}
420
421
static void AArch64_add_not_defined_ops(MCInst *MI, const SStream *OS)
422
204k
{
423
204k
  if (!detail_is_set(MI))
424
0
    return;
425
426
204k
  if (!MI->flat_insn->is_alias || !MI->flat_insn->usesAliasDetails) {
427
178k
    add_non_alias_details(MI);
428
178k
    return;
429
178k
  }
430
431
  // Alias details
432
26.0k
  switch(MI->flat_insn->alias_id) {
433
20.2k
  default:
434
20.2k
    return;
435
20.2k
  case AArch64_INS_ALIAS_FMOV:
436
209
    AArch64_insert_detail_op_float_at(MI, -1, 0.0f, CS_AC_READ);
437
209
    break;
438
1.83k
  case AArch64_INS_ALIAS_LD1:
439
1.87k
  case AArch64_INS_ALIAS_LD1R:
440
2.19k
  case AArch64_INS_ALIAS_LD2:
441
2.25k
  case AArch64_INS_ALIAS_LD2R:
442
2.79k
  case AArch64_INS_ALIAS_LD3:
443
2.80k
  case AArch64_INS_ALIAS_LD3R:
444
3.66k
  case AArch64_INS_ALIAS_LD4:
445
3.68k
  case AArch64_INS_ALIAS_LD4R:
446
4.25k
  case AArch64_INS_ALIAS_ST1:
447
4.35k
  case AArch64_INS_ALIAS_ST2:
448
5.48k
  case AArch64_INS_ALIAS_ST3:
449
5.56k
  case AArch64_INS_ALIAS_ST4: {
450
    // Add post-index disp
451
5.56k
    const char *disp_off = strrchr(OS->buffer, '#');
452
5.56k
    if (!disp_off)
453
0
      return;
454
5.56k
    unsigned disp = atoi(disp_off + 1);
455
5.56k
    AArch64_get_detail_op(MI, -1)->type = AArch64_OP_MEM;
456
5.56k
    AArch64_get_detail_op(MI, -1)->mem.base = AArch64_get_detail_op(MI, -1)->reg;
457
5.56k
    AArch64_get_detail_op(MI, -1)->mem.disp = disp;
458
5.56k
    AArch64_get_detail(MI)->post_index = true;
459
5.56k
    break;
460
5.56k
  }
461
26.0k
  }
462
26.0k
}
463
464
void AArch64_set_instr_map_data(MCInst *MI)
465
211k
{
466
211k
  map_cs_id(MI, aarch64_insns, ARR_SIZE(aarch64_insns));
467
211k
  map_implicit_reads(MI, aarch64_insns);
468
211k
  map_implicit_writes(MI, aarch64_insns);
469
211k
  map_groups(MI, aarch64_insns);
470
211k
}
471
472
bool AArch64_getInstruction(csh handle, const uint8_t *code, size_t code_len,
473
            MCInst *MI, uint16_t *size, uint64_t address,
474
211k
            void *info) {
475
211k
  AArch64_init_cs_detail(MI);
476
211k
  bool Result = AArch64_LLVM_getInstruction(handle, code, code_len, MI, size, address,
477
211k
                 info) != MCDisassembler_Fail;
478
211k
  AArch64_set_instr_map_data(MI);
479
211k
  return Result;
480
211k
}
481
482
/// Patches the register names with Capstone specific alias.
483
/// Those are common alias for registers (e.g. r15 = pc)
484
/// which are not set in LLVM.
485
static void patch_cs_reg_alias(char *asm_str)
486
0
{
487
0
  bool skip_sub = false;
488
0
  char *x29 = strstr(asm_str, "x29");
489
0
  if (x29 > asm_str && strstr(asm_str, "0x29") == (x29 - 1)) {
490
    // Check for hex prefix
491
0
    skip_sub = true;
492
0
  }
493
0
  while (x29 && !skip_sub) {
494
0
    x29[0] = 'f';
495
0
    x29[1] = 'p';
496
0
    memmove(x29 + 2, x29 + 3, strlen(x29 + 3));
497
0
    asm_str[strlen(asm_str) - 1] = '\0';
498
0
    x29 = strstr(asm_str, "x29");
499
0
  }
500
0
  skip_sub = false;
501
0
  char *x30 = strstr(asm_str, "x30");
502
0
  if (x30 > asm_str && strstr(asm_str, "0x30") == (x30 - 1)) {
503
    // Check for hex prefix
504
0
    skip_sub = true;
505
0
  }
506
0
  while (x30 && !skip_sub) {
507
0
    x30[0] = 'l';
508
0
    x30[1] = 'r';
509
0
    memmove(x30 + 2, x30 + 3, strlen(x30 + 3));
510
0
    asm_str[strlen(asm_str) - 1] = '\0';
511
0
    x30 = strstr(asm_str, "x30");
512
0
  }
513
0
}
514
515
/// Adds group to the instruction which are not defined in LLVM.
516
static void AArch64_add_cs_groups(MCInst *MI)
517
204k
{
518
204k
  unsigned Opcode = MI->flat_insn->id;
519
204k
  switch (Opcode) {
520
201k
  default:
521
201k
    return;
522
201k
  case AArch64_INS_SVC:
523
23
    add_group(MI, AArch64_GRP_INT);
524
23
    break;
525
10
  case AArch64_INS_SMC:
526
2.11k
  case AArch64_INS_MSR:
527
2.67k
  case AArch64_INS_MRS:
528
2.67k
    add_group(MI, AArch64_GRP_PRIVILEGE);
529
2.67k
    break;
530
37
  case AArch64_INS_RET:
531
37
  case AArch64_INS_RETAA:
532
37
  case AArch64_INS_RETAB:
533
37
    add_group(MI, AArch64_GRP_RET);
534
37
    break;
535
204k
  }
536
204k
}
537
538
204k
void AArch64_printer(MCInst *MI, SStream *O, void * /* MCRegisterInfo* */ info) {
539
204k
  MCRegisterInfo *MRI = (MCRegisterInfo *)info;
540
204k
  MI->MRI = MRI;
541
204k
  MI->fillDetailOps = detail_is_set(MI);
542
204k
  MI->flat_insn->usesAliasDetails = map_use_alias_details(MI);
543
204k
  AArch64_LLVM_printInstruction(MI, O, info);
544
204k
  if (detail_is_set(MI))
545
204k
    AArch64_get_detail(MI)->post_index = AArch64_check_post_index_am(MI, O);
546
204k
  AArch64_check_updates_flags(MI);
547
204k
  map_set_alias_id(MI, O, insn_alias_mnem_map, ARR_SIZE(insn_alias_mnem_map) - 1);
548
204k
  int syntax_opt = MI->csh->syntax;
549
204k
  if (syntax_opt & CS_OPT_SYNTAX_CS_REG_ALIAS)
550
0
    patch_cs_reg_alias(O->buffer);
551
204k
  AArch64_add_not_defined_ops(MI, O);
552
204k
  AArch64_add_cs_groups(MI);
553
204k
  AArch64_add_vas(MI, O);
554
204k
}
555
556
// given internal insn id, return public instruction info
557
void AArch64_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
558
204k
{
559
  // Done after disassembly
560
204k
  return;
561
204k
}
562
563
static const char *const insn_name_maps[] = {
564
#include "AArch64GenCSMappingInsnName.inc"
565
};
566
567
const char *AArch64_insn_name(csh handle, unsigned int id)
568
204k
{
569
204k
#ifndef CAPSTONE_DIET
570
204k
  if (id < AArch64_INS_ALIAS_END && id > AArch64_INS_ALIAS_BEGIN) {
571
0
    if (id - AArch64_INS_ALIAS_BEGIN >= ARR_SIZE(insn_alias_mnem_map))
572
0
      return NULL;
573
574
0
    return insn_alias_mnem_map[id - AArch64_INS_ALIAS_BEGIN - 1].name;
575
0
  }
576
204k
  if (id >= AArch64_INS_ENDING)
577
0
    return NULL;
578
579
204k
  if (id < ARR_SIZE(insn_name_maps))
580
204k
    return insn_name_maps[id];
581
582
  // not found
583
0
  return NULL;
584
#else
585
  return NULL;
586
#endif
587
204k
}
588
589
#ifndef CAPSTONE_DIET
590
static const name_map group_name_maps[] = {
591
  // generic groups
592
  { AArch64_GRP_INVALID, NULL },
593
  { AArch64_GRP_JUMP, "jump" },
594
  { AArch64_GRP_CALL, "call" },
595
  { AArch64_GRP_RET, "return" },
596
  { AArch64_GRP_PRIVILEGE, "privilege" },
597
  { AArch64_GRP_INT, "int" },
598
  { AArch64_GRP_BRANCH_RELATIVE, "branch_relative" },
599
600
  // architecture-specific groups
601
  #include "AArch64GenCSFeatureName.inc"
602
};
603
#endif
604
605
const char *AArch64_group_name(csh handle, unsigned int id)
606
221k
{
607
221k
#ifndef CAPSTONE_DIET
608
221k
  return id2name(group_name_maps, ARR_SIZE(group_name_maps), id);
609
#else
610
  return NULL;
611
#endif
612
221k
}
613
614
// map instruction name to public instruction ID
615
aarch64_insn AArch64_map_insn(const char *name)
616
46.9k
{
617
46.9k
  unsigned int i;
618
619
31.6M
  for(i = 1; i < ARR_SIZE(insn_name_maps); i++) {
620
31.6M
    if (!strcmp(name, insn_name_maps[i]))
621
46.8k
      return i;
622
31.6M
  }
623
624
  // not found
625
92
  return AArch64_INS_INVALID;
626
46.9k
}
627
628
#ifndef CAPSTONE_DIET
629
630
static const map_insn_ops insn_operands[] = {
631
#include "AArch64GenCSMappingInsnOp.inc"
632
};
633
634
void AArch64_reg_access(const cs_insn *insn,
635
    cs_regs regs_read, uint8_t *regs_read_count,
636
    cs_regs regs_write, uint8_t *regs_write_count)
637
0
{
638
0
  uint8_t i;
639
0
  uint8_t read_count, write_count;
640
0
  cs_aarch64 *aarch64 = &(insn->detail->aarch64);
641
642
0
  read_count = insn->detail->regs_read_count;
643
0
  write_count = insn->detail->regs_write_count;
644
645
  // implicit registers
646
0
  memcpy(regs_read, insn->detail->regs_read, read_count * sizeof(insn->detail->regs_read[0]));
647
0
  memcpy(regs_write, insn->detail->regs_write, write_count * sizeof(insn->detail->regs_write[0]));
648
649
  // explicit registers
650
0
  for (i = 0; i < aarch64->op_count; i++) {
651
0
    cs_aarch64_op *op = &(aarch64->operands[i]);
652
0
    switch((int)op->type) {
653
0
      case AArch64_OP_REG:
654
0
        if ((op->access & CS_AC_READ) && !arr_exist(regs_read, read_count, op->reg)) {
655
0
          regs_read[read_count] = (uint16_t)op->reg;
656
0
          read_count++;
657
0
        }
658
0
        if ((op->access & CS_AC_WRITE) && !arr_exist(regs_write, write_count, op->reg)) {
659
0
          regs_write[write_count] = (uint16_t)op->reg;
660
0
          write_count++;
661
0
        }
662
0
        break;
663
0
      case AArch64_OP_MEM:
664
        // registers appeared in memory references always being read
665
0
        if ((op->mem.base != AArch64_REG_INVALID) && !arr_exist(regs_read, read_count, op->mem.base)) {
666
0
          regs_read[read_count] = (uint16_t)op->mem.base;
667
0
          read_count++;
668
0
        }
669
0
        if ((op->mem.index != AArch64_REG_INVALID) && !arr_exist(regs_read, read_count, op->mem.index)) {
670
0
          regs_read[read_count] = (uint16_t)op->mem.index;
671
0
          read_count++;
672
0
        }
673
0
        if ((insn->detail->writeback) && (op->mem.base != AArch64_REG_INVALID) && !arr_exist(regs_write, write_count, op->mem.base)) {
674
0
          regs_write[write_count] = (uint16_t)op->mem.base;
675
0
          write_count++;
676
0
        }
677
0
      default:
678
0
        break;
679
0
    }
680
0
  }
681
682
0
  *regs_read_count = read_count;
683
0
  *regs_write_count = write_count;
684
0
}
685
#endif
686
687
137k
static AArch64Layout_VectorLayout get_vl_by_suffix(const char suffix) {
688
137k
  switch (suffix) {
689
40.9k
  default:
690
40.9k
    return AArch64Layout_Invalid;
691
13.7k
  case 'b':
692
13.7k
  case 'B':
693
13.7k
    return AArch64Layout_VL_B;
694
24.5k
  case 'h':
695
24.5k
  case 'H':
696
24.5k
    return AArch64Layout_VL_H;
697
29.0k
  case 's':
698
29.0k
  case 'S':
699
29.0k
    return AArch64Layout_VL_S;
700
27.6k
  case 'd':
701
27.6k
  case 'D':
702
27.6k
    return AArch64Layout_VL_D;
703
1.02k
  case 'q':
704
1.02k
  case 'Q':
705
1.02k
    return AArch64Layout_VL_Q;
706
137k
  }
707
137k
}
708
709
30.8k
static unsigned get_vec_list_num_regs(MCInst *MI, unsigned Reg) {
710
  // Work out how many registers there are in the list (if there is an actual
711
  // list).
712
30.8k
  unsigned NumRegs = 1;
713
30.8k
  if (MCRegisterClass_contains(
714
30.8k
      MCRegisterInfo_getRegClass(MI->MRI, AArch64_DDRegClassID), Reg) ||
715
30.8k
    MCRegisterClass_contains(
716
30.0k
      MCRegisterInfo_getRegClass(MI->MRI, AArch64_ZPR2RegClassID),
717
30.0k
      Reg) ||
718
30.8k
    MCRegisterClass_contains(
719
26.9k
      MCRegisterInfo_getRegClass(MI->MRI, AArch64_QQRegClassID), Reg) ||
720
30.8k
    MCRegisterClass_contains(
721
24.9k
      MCRegisterInfo_getRegClass(MI->MRI, AArch64_PPR2RegClassID),
722
24.9k
      Reg) ||
723
30.8k
    MCRegisterClass_contains(
724
24.6k
      MCRegisterInfo_getRegClass(MI->MRI, AArch64_ZPR2StridedRegClassID),
725
24.6k
      Reg))
726
7.15k
    NumRegs = 2;
727
23.7k
  else if (MCRegisterClass_contains(
728
23.7k
         MCRegisterInfo_getRegClass(MI->MRI, AArch64_DDDRegClassID),
729
23.7k
         Reg) ||
730
23.7k
       MCRegisterClass_contains(
731
22.6k
         MCRegisterInfo_getRegClass(MI->MRI, AArch64_ZPR3RegClassID),
732
22.6k
         Reg) ||
733
23.7k
       MCRegisterClass_contains(
734
22.3k
         MCRegisterInfo_getRegClass(MI->MRI, AArch64_QQQRegClassID),
735
22.3k
         Reg))
736
4.72k
    NumRegs = 3;
737
19.0k
  else if (MCRegisterClass_contains(
738
19.0k
         MCRegisterInfo_getRegClass(MI->MRI, AArch64_DDDDRegClassID),
739
19.0k
         Reg) ||
740
19.0k
       MCRegisterClass_contains(
741
17.9k
         MCRegisterInfo_getRegClass(MI->MRI, AArch64_ZPR4RegClassID),
742
17.9k
         Reg) ||
743
19.0k
       MCRegisterClass_contains(
744
14.8k
         MCRegisterInfo_getRegClass(MI->MRI, AArch64_QQQQRegClassID),
745
14.8k
         Reg) ||
746
19.0k
       MCRegisterClass_contains(
747
11.3k
         MCRegisterInfo_getRegClass(MI->MRI,
748
11.3k
                       AArch64_ZPR4StridedRegClassID),
749
11.3k
         Reg))
750
8.15k
    NumRegs = 4;
751
30.8k
  return NumRegs;
752
30.8k
}
753
754
30.8k
static unsigned get_vec_list_stride(MCInst *MI, unsigned Reg) {
755
30.8k
  unsigned Stride = 1;
756
30.8k
  if (MCRegisterClass_contains(
757
30.8k
      MCRegisterInfo_getRegClass(MI->MRI, AArch64_ZPR2StridedRegClassID),
758
30.8k
      Reg))
759
871
    Stride = 8;
760
30.0k
  else if (MCRegisterClass_contains(
761
30.0k
         MCRegisterInfo_getRegClass(MI->MRI,
762
30.0k
                       AArch64_ZPR4StridedRegClassID),
763
30.0k
         Reg))
764
477
    Stride = 4;
765
30.8k
  return Stride;
766
30.8k
}
767
768
30.8k
static unsigned get_vec_list_first_reg(MCInst *MI, unsigned RegL) {
769
30.8k
  unsigned Reg = RegL;
770
  // Now forget about the list and find out what the first register is.
771
30.8k
  if (MCRegisterInfo_getSubReg(MI->MRI, RegL, AArch64_dsub0))
772
3.03k
    Reg = MCRegisterInfo_getSubReg(MI->MRI, RegL, AArch64_dsub0);
773
27.8k
  else if (MCRegisterInfo_getSubReg(MI->MRI, RegL, AArch64_qsub0))
774
8.73k
    Reg = MCRegisterInfo_getSubReg(MI->MRI, RegL, AArch64_qsub0);
775
19.1k
  else if (MCRegisterInfo_getSubReg(MI->MRI, RegL, AArch64_zsub0))
776
7.87k
    Reg = MCRegisterInfo_getSubReg(MI->MRI, RegL, AArch64_zsub0);
777
11.2k
  else if (MCRegisterInfo_getSubReg(MI->MRI, RegL, AArch64_psub0))
778
390
    Reg = MCRegisterInfo_getSubReg(MI->MRI, RegL, AArch64_psub0);
779
780
  // If it's a D-reg, we need to promote it to the equivalent Q-reg before
781
  // printing (otherwise getRegisterName fails).
782
30.8k
  if (MCRegisterClass_contains(
783
30.8k
      MCRegisterInfo_getRegClass(MI->MRI, AArch64_FPR64RegClassID),
784
30.8k
      Reg)) {
785
4.47k
    const MCRegisterClass *FPR128RC =
786
4.47k
      MCRegisterInfo_getRegClass(MI->MRI, AArch64_FPR128RegClassID);
787
4.47k
    Reg = MCRegisterInfo_getMatchingSuperReg(MI->MRI, Reg, AArch64_dsub,
788
4.47k
                   FPR128RC);
789
4.47k
  }
790
30.8k
  return Reg;
791
30.8k
}
792
793
96.4k
static bool is_vector_reg(unsigned Reg) {
794
96.4k
  if ((Reg >= AArch64_Q0) && (Reg <= AArch64_Q31))
795
41.0k
    return true;
796
55.3k
  else if ((Reg >= AArch64_Z0) && (Reg <= AArch64_Z31))
797
54.5k
    return true;
798
803
  else if ((Reg >= AArch64_P0) && (Reg <= AArch64_P15))
799
803
    return true;
800
0
  return false;
801
96.4k
}
802
803
static unsigned getNextVectorRegister(unsigned Reg, unsigned Stride /* = 1 */)
804
65.8k
{
805
162k
  while (Stride--) {
806
96.4k
    if (!is_vector_reg(Reg)) {
807
0
      assert(0 && "Vector register expected!");
808
0
      return 0;
809
0
    }
810
    // Vector lists can wrap around.
811
96.4k
    else if (Reg == AArch64_Q31)
812
1.39k
      Reg = AArch64_Q0;
813
    // Vector lists can wrap around.
814
95.0k
    else if (Reg == AArch64_Z31)
815
1.22k
      Reg = AArch64_Z0;
816
    // Vector lists can wrap around.
817
93.8k
    else if (Reg == AArch64_P15)
818
46
      Reg = AArch64_P0;
819
93.7k
    else
820
      // Assume ordered registers
821
93.7k
      ++Reg;
822
96.4k
  }
823
65.8k
  return Reg;
824
65.8k
}
825
826
10.5k
static aarch64_extender llvm_to_cs_ext(AArch64_AM_ShiftExtendType ExtType) {
827
10.5k
  switch(ExtType) {
828
8.53k
  default:
829
8.53k
    return AArch64_EXT_INVALID;
830
129
  case AArch64_AM_UXTB:
831
129
    return AArch64_EXT_UXTB;
832
418
  case AArch64_AM_UXTH:
833
418
    return AArch64_EXT_UXTH;
834
437
  case AArch64_AM_UXTW:
835
437
    return AArch64_EXT_UXTW;
836
406
  case AArch64_AM_UXTX:
837
406
    return AArch64_EXT_UXTX;
838
178
  case AArch64_AM_SXTB:
839
178
    return AArch64_EXT_SXTB;
840
191
  case AArch64_AM_SXTH:
841
191
    return AArch64_EXT_SXTH;
842
26
  case AArch64_AM_SXTW:
843
26
    return AArch64_EXT_SXTW;
844
203
  case AArch64_AM_SXTX:
845
203
    return AArch64_EXT_SXTX;
846
10.5k
  }
847
10.5k
}
848
849
8.53k
static aarch64_shifter llvm_to_cs_shift(AArch64_AM_ShiftExtendType ShiftExtType) {
850
8.53k
  switch(ShiftExtType) {
851
0
  default:
852
0
    return AArch64_SFT_INVALID;
853
5.45k
  case AArch64_AM_LSL:
854
5.45k
    return AArch64_SFT_LSL;
855
1.35k
  case AArch64_AM_LSR:
856
1.35k
    return AArch64_SFT_LSR;
857
1.09k
  case AArch64_AM_ASR:
858
1.09k
    return AArch64_SFT_ASR;
859
576
  case AArch64_AM_ROR:
860
576
    return AArch64_SFT_ROR;
861
63
  case AArch64_AM_MSL:
862
63
    return AArch64_SFT_MSL;
863
8.53k
  }
864
8.53k
}
865
866
/// Initializes or finishes a memory operand of Capstone (depending on \p
867
/// status). A memory operand in Capstone can be assembled by two LLVM operands.
868
/// E.g. the base register and the immediate disponent.
869
void AArch64_set_mem_access(MCInst *MI, bool status)
870
215k
{
871
215k
  if (!detail_is_set(MI))
872
0
    return;
873
215k
  set_doing_mem(MI, status);
874
215k
  if (status) {
875
107k
    if (AArch64_get_detail(MI)->op_count > 0 &&
876
107k
      AArch64_get_detail_op(MI, -1)->type == AArch64_OP_MEM &&
877
107k
      AArch64_get_detail_op(MI, -1)->mem.index == AArch64_REG_INVALID &&
878
107k
      AArch64_get_detail_op(MI, -1)->mem.disp == 0) {
879
      // Previous memory operand not done yet. Select it.
880
45.1k
      AArch64_dec_op_count(MI);
881
45.1k
      return;
882
45.1k
    }
883
884
    // Init a new one.
885
62.5k
    AArch64_get_detail_op(MI, 0)->type = AArch64_OP_MEM;
886
62.5k
    AArch64_get_detail_op(MI, 0)->mem.base = AArch64_REG_INVALID;
887
62.5k
    AArch64_get_detail_op(MI, 0)->mem.index = AArch64_REG_INVALID;
888
62.5k
    AArch64_get_detail_op(MI, 0)->mem.disp = 0;
889
890
62.5k
#ifndef CAPSTONE_DIET
891
62.5k
    uint8_t access =
892
62.5k
      map_get_op_access(MI, AArch64_get_detail(MI)->op_count);
893
62.5k
    AArch64_get_detail_op(MI, 0)->access = access;
894
62.5k
#endif
895
107k
  } else {
896
    // done, select the next operand slot
897
107k
    AArch64_inc_op_count(MI);
898
107k
  }
899
215k
}
900
901
/// Fills cs_detail with the data of the operand.
902
/// This function handles operands which's original printer function has no
903
/// specialities.
904
static void add_cs_detail_general(MCInst *MI, aarch64_op_group op_group,
905
363k
                  unsigned OpNum) {
906
363k
  if (!detail_is_set(MI))
907
0
    return;
908
909
  // Fill cs_detail
910
363k
  switch (op_group) {
911
0
  default:
912
0
    printf("ERROR: Operand group %d not handled!\n", op_group);
913
0
    assert(0);
914
258k
  case AArch64_OP_GROUP_Operand: {
915
258k
    cs_op_type primary_op_type = map_get_op_type(MI, OpNum) & ~CS_OP_MEM;
916
258k
    switch (primary_op_type) {
917
0
    default:
918
0
      printf("Unhandled operand type 0x%x\n", primary_op_type);
919
0
      assert(0);
920
216k
    case AArch64_OP_REG:
921
216k
      AArch64_set_detail_op_reg(MI, OpNum, MCInst_getOpVal(MI, OpNum));
922
216k
      break;
923
41.6k
    case AArch64_OP_IMM:
924
41.6k
      AArch64_set_detail_op_imm(MI, OpNum, AArch64_OP_IMM,
925
41.6k
            MCInst_getOpVal(MI, OpNum));
926
41.6k
      break;
927
380
    case AArch64_OP_FP: {
928
      // printOperand does not handle FP operands. But sometimes
929
      // is is used to print FP operands as normal immediate.
930
380
      AArch64_get_detail_op(MI, 0)->type = AArch64_OP_IMM;
931
380
      AArch64_get_detail_op(MI, 0)->imm = MCInst_getOpVal(MI, OpNum);
932
380
      AArch64_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
933
380
      AArch64_inc_op_count(MI);
934
380
      break;
935
0
    }
936
258k
    }
937
258k
    break;
938
258k
  }
939
258k
  case AArch64_OP_GROUP_AddSubImm: {
940
1.95k
    unsigned Val = (MCInst_getOpVal(MI, OpNum) & 0xfff);
941
1.95k
    AArch64_set_detail_op_imm(MI, OpNum, AArch64_OP_IMM, Val);
942
    // Shift is added in printShifter()
943
1.95k
    break;
944
258k
  }
945
2.69k
  case AArch64_OP_GROUP_AdrLabel: {
946
2.69k
    int64_t Offset = MCInst_getOpVal(MI, OpNum);
947
2.69k
    AArch64_set_detail_op_imm(MI, OpNum, AArch64_OP_IMM, (MI->address & -4096) + Offset);
948
2.69k
    break;
949
258k
  }
950
1.86k
  case AArch64_OP_GROUP_AdrpLabel: {
951
1.86k
    int64_t Offset = MCInst_getOpVal(MI, OpNum) * 4096;
952
1.86k
    AArch64_set_detail_op_imm(MI, OpNum, AArch64_OP_IMM, (MI->address & -4096) + Offset);
953
1.86k
    break;
954
258k
  }
955
13.8k
  case AArch64_OP_GROUP_AlignedLabel: {
956
13.8k
    int64_t Offset = MCInst_getOpVal(MI, OpNum) * 4;
957
13.8k
    AArch64_set_detail_op_imm(MI, OpNum, AArch64_OP_IMM, MI->address + Offset);
958
13.8k
    break;
959
258k
  }
960
0
  case AArch64_OP_GROUP_AMNoIndex: {
961
0
    AArch64_set_detail_op_mem(MI, OpNum, MCInst_getOpVal(MI, OpNum));
962
0
    break;
963
258k
  }
964
1.98k
  case AArch64_OP_GROUP_ArithExtend: {
965
1.98k
    unsigned Val = MCInst_getOpVal(MI, OpNum);
966
1.98k
    AArch64_AM_ShiftExtendType ExtType = AArch64_AM_getArithExtendType(Val);
967
1.98k
    unsigned ShiftVal = AArch64_AM_getArithShiftValue(Val);
968
969
1.98k
    AArch64_get_detail_op(MI, -1)->ext = llvm_to_cs_ext(ExtType);
970
1.98k
    AArch64_get_detail_op(MI, -1)->shift.value = ShiftVal;
971
1.98k
    AArch64_get_detail_op(MI, -1)->shift.type = AArch64_SFT_LSL;
972
1.98k
    break;
973
258k
  }
974
6
  case AArch64_OP_GROUP_BarriernXSOption: {
975
6
    unsigned Val = MCInst_getOpVal(MI, OpNum);
976
6
    aarch64_sysop sysop;
977
6
    const AArch64DBnXS_DBnXS *DB = AArch64DBnXS_lookupDBnXSByEncoding(Val);
978
6
        if (DB)
979
6
            sysop.imm = DB->SysImm;
980
0
        else
981
0
            sysop.imm.raw_val = Val;
982
6
    sysop.sub_type = AArch64_OP_DBNXS;
983
6
    AArch64_set_detail_op_sys(MI, OpNum, sysop, AArch64_OP_SYSIMM);
984
6
    break;
985
258k
  }
986
628
  case AArch64_OP_GROUP_BarrierOption: {
987
628
    unsigned Val = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
988
628
    unsigned Opcode = MCInst_getOpcode(MI);
989
628
    aarch64_sysop sysop;
990
991
628
    if (Opcode == AArch64_ISB) {
992
29
      const AArch64ISB_ISB *ISB = AArch64ISB_lookupISBByEncoding(Val);
993
29
            if (ISB)
994
0
                sysop.alias = ISB->SysAlias;
995
29
            else
996
29
                sysop.alias.raw_val = Val;
997
29
      sysop.sub_type = AArch64_OP_ISB;
998
29
      AArch64_set_detail_op_sys(MI, OpNum, sysop, AArch64_OP_SYSALIAS);
999
599
    } else if (Opcode == AArch64_TSB) {
1000
10
      const AArch64TSB_TSB *TSB = AArch64TSB_lookupTSBByEncoding(Val);
1001
10
            if (TSB)
1002
10
                sysop.alias = TSB->SysAlias;
1003
0
            else
1004
0
                sysop.alias.raw_val = Val;
1005
10
      sysop.sub_type = AArch64_OP_TSB;
1006
10
      AArch64_set_detail_op_sys(MI, OpNum, sysop, AArch64_OP_SYSALIAS);
1007
589
    } else {
1008
589
      const AArch64DB_DB *DB = AArch64DB_lookupDBByEncoding(Val);
1009
589
            if (DB)
1010
434
                sysop.alias = DB->SysAlias;
1011
155
            else
1012
155
                sysop.alias.raw_val = Val;
1013
589
      sysop.sub_type = AArch64_OP_DB;
1014
589
      AArch64_set_detail_op_sys(MI, OpNum, sysop, AArch64_OP_SYSALIAS);
1015
589
    }
1016
628
    break;
1017
258k
  }
1018
37
  case AArch64_OP_GROUP_BTIHintOp: {
1019
37
    aarch64_sysop sysop;
1020
37
    unsigned btihintop = MCInst_getOpVal(MI, OpNum) ^ 32;
1021
37
    const AArch64BTIHint_BTI *BTI = AArch64BTIHint_lookupBTIByEncoding(btihintop);
1022
37
        if (BTI)
1023
37
            sysop.alias = BTI->SysAlias;
1024
0
        else
1025
0
            sysop.alias.raw_val = btihintop;
1026
37
    sysop.sub_type = AArch64_OP_BTI;
1027
37
    AArch64_set_detail_op_sys(MI, OpNum, sysop, AArch64_OP_SYSALIAS);
1028
37
    break;
1029
258k
  }
1030
1.87k
  case AArch64_OP_GROUP_CondCode: {
1031
1.87k
    AArch64_get_detail(MI)->cc = MCInst_getOpVal(MI, OpNum);
1032
1.87k
    break;
1033
258k
  }
1034
1.39k
  case AArch64_OP_GROUP_ExtendedRegister: {
1035
1.39k
    AArch64_set_detail_op_reg(MI, OpNum, MCInst_getOpVal(MI, OpNum));
1036
1.39k
    break;
1037
258k
  }
1038
1.38k
  case AArch64_OP_GROUP_FPImmOperand: {
1039
1.38k
    MCOperand *MO = MCInst_getOperand(MI, (OpNum));
1040
1.38k
    float FPImm = MCOperand_isDFPImm(MO)
1041
1.38k
              ? BitsToDouble(MCOperand_getImm(MO))
1042
1.38k
              : AArch64_AM_getFPImmFloat(MCOperand_getImm(MO));
1043
1.38k
    AArch64_set_detail_op_float(MI, OpNum, FPImm);
1044
1.38k
    break;
1045
258k
  }
1046
4.40k
  case AArch64_OP_GROUP_GPR64as32: {
1047
4.40k
    unsigned Reg = MCInst_getOpVal(MI, OpNum);
1048
4.40k
    AArch64_set_detail_op_reg(MI, OpNum, getWRegFromXReg(Reg));
1049
4.40k
    break;
1050
258k
  }
1051
64
  case AArch64_OP_GROUP_GPR64x8: {
1052
64
    unsigned Reg = MCInst_getOpVal(MI, (OpNum));
1053
64
    Reg = MCRegisterInfo_getSubReg(MI->MRI, Reg, AArch64_x8sub_0);
1054
64
    AArch64_set_detail_op_reg(MI, OpNum, Reg);
1055
64
    break;
1056
258k
  }
1057
3.14k
  case AArch64_OP_GROUP_Imm:
1058
3.23k
  case AArch64_OP_GROUP_ImmHex:
1059
3.23k
    AArch64_set_detail_op_imm(MI, OpNum, AArch64_OP_IMM, MCInst_getOpVal(MI, OpNum));
1060
3.23k
    break;
1061
0
  case AArch64_OP_GROUP_ImplicitlyTypedVectorList:
1062
    // The TypedVectorList implements the logic of implicitly typed operand.
1063
0
    add_cs_detail(MI, AArch64_OP_GROUP_TypedVectorList_0_b, OpNum, 0, 0);
1064
0
    break;
1065
17
  case AArch64_OP_GROUP_InverseCondCode: {
1066
17
    AArch64CC_CondCode CC =
1067
17
      (AArch64CC_CondCode)MCOperand_getImm(MCInst_getOperand(MI, (OpNum)));
1068
17
    AArch64_get_detail(MI)->cc = AArch64CC_getInvertedCondCode(CC);
1069
17
    break;
1070
3.14k
  }
1071
3.31k
  case AArch64_OP_GROUP_MatrixIndex: {
1072
3.31k
    assert(AArch64_get_detail(MI)->op_count >= 1);
1073
3.31k
    if (AArch64_get_detail_op(MI, -1)->type == AArch64_OP_SME_MATRIX)
1074
      // The index is part of an SME matrix
1075
2.68k
      AArch64_set_detail_op_sme(MI, OpNum, AArch64_SME_MATRIX_SLICE_OFF, AArch64Layout_Invalid);
1076
629
    else
1077
      // The index is used for an SVE2 instruction.
1078
629
      AArch64_set_detail_op_imm(MI, OpNum, AArch64_OP_IMM, MCInst_getOpVal(MI, OpNum));
1079
1080
3.31k
    break;
1081
3.31k
  }
1082
1.22k
  case AArch64_OP_GROUP_MatrixTile: {
1083
1.22k
    const char *RegName = AArch64_LLVM_getRegisterName(MCInst_getOpVal(MI, OpNum), AArch64_NoRegAltName);
1084
1.22k
    const char *Dot = strstr(RegName, ".");
1085
1.22k
    AArch64Layout_VectorLayout vas = AArch64Layout_Invalid;
1086
1.22k
    if (!Dot) {
1087
      // The matrix dimensions are machine dependendent.
1088
      // Currently we do not support differentiation of machines.
1089
      // So we just indicate the use of the complete matrix.
1090
0
      vas = sme_reg_to_vas(MCInst_getOpVal(MI, OpNum));
1091
0
    } else
1092
1.22k
      vas = get_vl_by_suffix(Dot[1]);
1093
1.22k
    AArch64_set_detail_op_sme(MI, OpNum, AArch64_SME_MATRIX_TILE, vas);
1094
1.22k
    break;
1095
3.31k
  }
1096
47
  case AArch64_OP_GROUP_MatrixTileList: {
1097
47
    unsigned MaxRegs = 8;
1098
47
    unsigned RegMask = MCInst_getOpVal(MI, (OpNum));
1099
1100
423
    for (unsigned I = 0; I < MaxRegs; ++I) {
1101
376
      unsigned Reg = RegMask & (1 << I);
1102
376
      if (Reg == 0)
1103
186
        continue;
1104
190
      AArch64_get_detail_op(MI, 0)->is_list_member = true;
1105
190
      AArch64_set_detail_op_sme(MI, OpNum, AArch64_SME_MATRIX_TILE_LIST, AArch64Layout_VL_D, AArch64_REG_ZAD0 + I);
1106
190
    }
1107
47
    break;
1108
3.31k
  }
1109
585
  case AArch64_OP_GROUP_MRSSystemRegister:
1110
2.49k
  case AArch64_OP_GROUP_MSRSystemRegister: {
1111
2.49k
    unsigned Val = MCInst_getOpVal(MI, OpNum);
1112
2.49k
    const AArch64SysReg_SysReg *Reg = AArch64SysReg_lookupSysRegByEncoding(Val);
1113
2.49k
    bool Read = (op_group == AArch64_OP_GROUP_MRSSystemRegister)
1114
2.49k
                   ? true
1115
2.49k
                   : false;
1116
1117
2.49k
    bool isValidSysReg = (Reg && (Read ? Reg->Readable : Reg->Writeable) &&
1118
2.49k
      AArch64_testFeatureList(MI->csh->mode, Reg->FeaturesRequired));
1119
1120
2.49k
    if (Reg && !isValidSysReg)
1121
213
      Reg = AArch64SysReg_lookupSysRegByName(Reg->AltName);
1122
2.49k
    aarch64_sysop sysop;
1123
    // If Reg is NULL it is a generic system register.
1124
2.49k
        if (Reg)
1125
267
          sysop.reg = Reg->SysReg;
1126
2.22k
        else {
1127
2.22k
          sysop.reg.raw_val = Val;
1128
2.22k
        }
1129
2.49k
    aarch64_op_type type = (op_group == AArch64_OP_GROUP_MRSSystemRegister)
1130
2.49k
                   ? AArch64_OP_REG_MRS
1131
2.49k
                   : AArch64_OP_REG_MSR;
1132
2.49k
    sysop.sub_type = type;
1133
2.49k
    AArch64_set_detail_op_sys(MI, OpNum, sysop, AArch64_OP_SYSREG);
1134
2.49k
    break;
1135
585
  }
1136
3
  case AArch64_OP_GROUP_PSBHintOp: {
1137
3
    unsigned psbhintop = MCInst_getOpVal(MI, OpNum);
1138
3
    const AArch64PSBHint_PSB *PSB = AArch64PSBHint_lookupPSBByEncoding(psbhintop);
1139
3
    aarch64_sysop sysop;
1140
3
        if (PSB)
1141
3
            sysop.alias = PSB->SysAlias;
1142
0
        else
1143
0
            sysop.alias.raw_val = psbhintop;
1144
3
    sysop.sub_type = AArch64_OP_PSB;
1145
3
    AArch64_set_detail_op_sys(MI, OpNum, sysop, AArch64_OP_SYSALIAS);
1146
3
    break;
1147
585
  }
1148
41
  case AArch64_OP_GROUP_RPRFMOperand: {
1149
41
    unsigned prfop = MCInst_getOpVal(MI, OpNum);
1150
41
    const AArch64PRFM_PRFM *PRFM = AArch64PRFM_lookupPRFMByEncoding(prfop);
1151
41
    aarch64_sysop sysop;
1152
41
        if (PRFM)
1153
18
            sysop.alias = PRFM->SysAlias;
1154
23
        else
1155
23
            sysop.alias.raw_val = prfop;
1156
41
    sysop.sub_type = AArch64_OP_PRFM;
1157
41
    AArch64_set_detail_op_sys(MI, OpNum, sysop, AArch64_OP_SYSALIAS);
1158
41
    break;
1159
585
  }
1160
5.67k
  case AArch64_OP_GROUP_ShiftedRegister: {
1161
5.67k
    AArch64_set_detail_op_reg(MI, OpNum, MCInst_getOpVal(MI, OpNum));
1162
    // Shift part is handled in printShifter()
1163
5.67k
    break;
1164
585
  }
1165
8.53k
  case AArch64_OP_GROUP_Shifter: {
1166
8.53k
    unsigned Val = MCInst_getOpVal(MI, OpNum);
1167
8.53k
    AArch64_AM_ShiftExtendType ShExtType = AArch64_AM_getShiftType(Val);
1168
8.53k
    AArch64_get_detail_op(MI, -1)->ext = llvm_to_cs_ext(ShExtType);
1169
8.53k
    AArch64_get_detail_op(MI, -1)->shift.type = llvm_to_cs_shift(ShExtType);
1170
8.53k
    AArch64_get_detail_op(MI, -1)->shift.value = AArch64_AM_getShiftValue(Val);
1171
8.53k
    break;
1172
585
  }
1173
143
  case AArch64_OP_GROUP_SIMDType10Operand: {
1174
143
    unsigned RawVal = MCInst_getOpVal(MI, OpNum);
1175
143
    uint64_t Val = AArch64_AM_decodeAdvSIMDModImmType10(RawVal);
1176
143
    AArch64_set_detail_op_imm(MI, OpNum, AArch64_OP_IMM, Val);
1177
143
    break;
1178
585
  }
1179
0
  case AArch64_OP_GROUP_SVCROp: {
1180
0
    unsigned svcrop = MCInst_getOpVal(MI, OpNum);
1181
0
    const AArch64SVCR_SVCR *SVCR = AArch64SVCR_lookupSVCRByEncoding(svcrop);
1182
0
    aarch64_sysop sysop;
1183
0
        if (SVCR)
1184
0
            sysop.alias = SVCR->SysAlias;
1185
0
        else
1186
0
            sysop.alias.raw_val = svcrop;
1187
0
    sysop.sub_type = AArch64_OP_SVCR;
1188
0
    AArch64_set_detail_op_sys(MI, OpNum, sysop, AArch64_OP_SYSALIAS);
1189
0
    break;
1190
585
  }
1191
2.39k
  case AArch64_OP_GROUP_SVEPattern: {
1192
2.39k
    unsigned Val = MCInst_getOpVal(MI, OpNum);
1193
2.39k
    const AArch64SVEPredPattern_SVEPREDPAT *Pat = AArch64SVEPredPattern_lookupSVEPREDPATByEncoding(Val);
1194
2.39k
    if (!Pat)
1195
302
      break;
1196
2.09k
    aarch64_sysop sysop;
1197
2.09k
    sysop.alias = Pat->SysAlias;
1198
2.09k
    sysop.sub_type = AArch64_OP_SVEPREDPAT;
1199
2.09k
    AArch64_set_detail_op_sys(MI, OpNum, sysop, AArch64_OP_SYSALIAS);
1200
2.09k
    break;
1201
2.39k
  }
1202
140
  case AArch64_OP_GROUP_SVEVecLenSpecifier: {
1203
140
    unsigned Val = MCInst_getOpVal(MI, OpNum);
1204
    // Pattern has only 1 bit
1205
140
    if (Val > 1)
1206
0
      assert(0 && "Invalid vector length specifier");
1207
140
    const AArch64SVEVecLenSpecifier_SVEVECLENSPECIFIER *Pat =
1208
140
      AArch64SVEVecLenSpecifier_lookupSVEVECLENSPECIFIERByEncoding(Val);
1209
140
    if (!Pat)
1210
0
      break;
1211
140
    aarch64_sysop sysop;
1212
140
    sysop.alias = Pat->SysAlias;
1213
140
    sysop.sub_type = AArch64_OP_SVEVECLENSPECIFIER;
1214
140
    AArch64_set_detail_op_sys(MI, OpNum, sysop, AArch64_OP_SYSALIAS);
1215
140
    break;
1216
140
  }
1217
5.16k
  case AArch64_OP_GROUP_SysCROperand: {
1218
5.16k
    uint64_t cimm = MCInst_getOpVal(MI, OpNum);
1219
5.16k
    AArch64_set_detail_op_imm(MI, OpNum, AArch64_OP_CIMM, cimm);
1220
5.16k
    break;
1221
140
  }
1222
52
  case AArch64_OP_GROUP_SyspXzrPair: {
1223
52
    unsigned Reg = MCInst_getOpVal(MI, OpNum);
1224
52
    AArch64_set_detail_op_reg(MI, OpNum, Reg);
1225
52
    AArch64_set_detail_op_reg(MI, OpNum, Reg);
1226
52
    break;
1227
140
  }
1228
224
  case AArch64_OP_GROUP_SystemPStateField: {
1229
224
    unsigned Val = MCInst_getOpVal(MI, OpNum);
1230
1231
224
    aarch64_sysop sysop;
1232
224
    const AArch64PState_PStateImm0_15 *PStateImm15 = AArch64PState_lookupPStateImm0_15ByEncoding(Val);
1233
224
    const AArch64PState_PStateImm0_1 *PStateImm1 = AArch64PState_lookupPStateImm0_1ByEncoding(Val);
1234
224
    if (PStateImm15 && AArch64_testFeatureList(MI->csh->mode, PStateImm15->FeaturesRequired)) {
1235
195
      sysop.alias = PStateImm15->SysAlias;
1236
195
    sysop.sub_type = AArch64_OP_PSTATEIMM0_15;
1237
195
      AArch64_set_detail_op_sys(MI, OpNum, sysop, AArch64_OP_SYSALIAS);
1238
195
    }
1239
29
    else if (PStateImm1 && AArch64_testFeatureList(MI->csh->mode, PStateImm1->FeaturesRequired)) {
1240
29
      sysop.alias = PStateImm1->SysAlias;
1241
29
    sysop.sub_type = AArch64_OP_PSTATEIMM0_1;
1242
29
      AArch64_set_detail_op_sys(MI, OpNum, sysop, AArch64_OP_SYSALIAS);
1243
29
    }
1244
0
    else {
1245
0
      AArch64_set_detail_op_imm(MI, OpNum, AArch64_OP_IMM, Val);
1246
0
    }
1247
224
    break;
1248
140
  }
1249
39.7k
  case AArch64_OP_GROUP_VRegOperand: {
1250
39.7k
    unsigned Reg = MCInst_getOpVal(MI, OpNum);
1251
39.7k
    AArch64_set_detail_op_reg(MI, OpNum, Reg);
1252
39.7k
    break;
1253
140
  }
1254
363k
  }
1255
363k
}
1256
1257
/// Fills cs_detail with the data of the operand.
1258
/// This function handles operands which original printer function is a template
1259
/// with one argument.
1260
static void add_cs_detail_template_1(MCInst *MI, aarch64_op_group op_group,
1261
                   unsigned OpNum, uint64_t temp_arg_0)
1262
192k
{
1263
192k
  if (!detail_is_set(MI))
1264
0
    return;
1265
192k
  switch (op_group) {
1266
0
  default:
1267
0
    printf("ERROR: Operand group %d not handled!\n", op_group);
1268
0
    assert(0);
1269
68
  case AArch64_OP_GROUP_GPRSeqPairsClassOperand_32:
1270
1.53k
  case AArch64_OP_GROUP_GPRSeqPairsClassOperand_64: {
1271
1.53k
    unsigned size = temp_arg_0;
1272
1.53k
    unsigned Reg = MCInst_getOpVal(MI, (OpNum));
1273
1274
1.53k
    unsigned Sube = (size == 32) ? AArch64_sube32 : AArch64_sube64;
1275
1.53k
    unsigned Subo = (size == 32) ? AArch64_subo32 : AArch64_subo64;
1276
1277
1.53k
    unsigned Even = MCRegisterInfo_getSubReg(MI->MRI, Reg, Sube);
1278
1.53k
    unsigned Odd = MCRegisterInfo_getSubReg(MI->MRI, Reg, Subo);
1279
1.53k
    AArch64_set_detail_op_reg(MI, OpNum, Even);
1280
1.53k
    AArch64_set_detail_op_reg(MI, OpNum, Odd);
1281
1.53k
    break;
1282
68
  }
1283
573
  case AArch64_OP_GROUP_Imm8OptLsl_int16_t:
1284
815
  case AArch64_OP_GROUP_Imm8OptLsl_int32_t:
1285
1.24k
  case AArch64_OP_GROUP_Imm8OptLsl_int64_t:
1286
1.37k
  case AArch64_OP_GROUP_Imm8OptLsl_int8_t:
1287
1.72k
  case AArch64_OP_GROUP_Imm8OptLsl_uint16_t:
1288
1.81k
  case AArch64_OP_GROUP_Imm8OptLsl_uint32_t:
1289
1.87k
  case AArch64_OP_GROUP_Imm8OptLsl_uint64_t:
1290
1.94k
  case AArch64_OP_GROUP_Imm8OptLsl_uint8_t: {
1291
1.94k
    unsigned UnscaledVal = MCInst_getOpVal(MI, (OpNum));
1292
1.94k
    unsigned Shift = MCInst_getOpVal(MI, (OpNum + 1));
1293
1294
1.94k
    if ((UnscaledVal == 0) && (AArch64_AM_getShiftValue(Shift) != 0)) {
1295
101
      AArch64_set_detail_op_imm(MI, OpNum, AArch64_OP_IMM, UnscaledVal);
1296
      // Shift is handled in printShifter()
1297
101
      break;
1298
101
    }
1299
1.84k
    switch (op_group) {
1300
0
    default:
1301
0
      assert(0 && "Operand group for Imm8OptLsl not handled.");
1302
567
    case AArch64_OP_GROUP_Imm8OptLsl_int16_t:
1303
781
    case AArch64_OP_GROUP_Imm8OptLsl_int32_t:
1304
1.17k
    case AArch64_OP_GROUP_Imm8OptLsl_int64_t:
1305
1.30k
    case AArch64_OP_GROUP_Imm8OptLsl_int8_t: {
1306
1.30k
      int8_t Val =
1307
1.30k
        (int8_t)UnscaledVal * (1 << AArch64_AM_getShiftValue(Shift));
1308
1.30k
      AArch64_set_detail_op_imm(MI, OpNum, AArch64_OP_IMM, Val);
1309
1.30k
    }
1310
1.65k
    case AArch64_OP_GROUP_Imm8OptLsl_uint16_t:
1311
1.73k
    case AArch64_OP_GROUP_Imm8OptLsl_uint32_t:
1312
1.77k
    case AArch64_OP_GROUP_Imm8OptLsl_uint64_t:
1313
1.84k
    case AArch64_OP_GROUP_Imm8OptLsl_uint8_t: {
1314
1.84k
      uint8_t Val =
1315
1.84k
          (uint8_t)UnscaledVal * (1 << AArch64_AM_getShiftValue(Shift));
1316
1.84k
      AArch64_set_detail_op_imm(MI, OpNum, AArch64_OP_IMM, Val);
1317
1.84k
    }
1318
1.84k
    }
1319
1.84k
    break;
1320
1.84k
  }
1321
5.52k
  case AArch64_OP_GROUP_ImmScale_16:
1322
6.71k
  case AArch64_OP_GROUP_ImmScale_2:
1323
6.83k
  case AArch64_OP_GROUP_ImmScale_3:
1324
6.97k
  case AArch64_OP_GROUP_ImmScale_32:
1325
11.9k
  case AArch64_OP_GROUP_ImmScale_4:
1326
16.5k
  case AArch64_OP_GROUP_ImmScale_8: {
1327
16.5k
    unsigned Scale = temp_arg_0;
1328
16.5k
    AArch64_set_detail_op_imm(MI, OpNum, AArch64_OP_IMM,
1329
16.5k
          Scale * MCInst_getOpVal(MI, OpNum));
1330
16.5k
    break;
1331
11.9k
  }
1332
672
  case AArch64_OP_GROUP_LogicalImm_int16_t:
1333
3.00k
  case AArch64_OP_GROUP_LogicalImm_int32_t:
1334
4.10k
  case AArch64_OP_GROUP_LogicalImm_int64_t:
1335
4.43k
  case AArch64_OP_GROUP_LogicalImm_int8_t: {
1336
4.43k
    unsigned TypeSize = temp_arg_0;
1337
4.43k
    uint64_t Val = AArch64_AM_decodeLogicalImmediate(MCInst_getOpVal(MI, OpNum), 8 * TypeSize);
1338
4.43k
    AArch64_set_detail_op_imm(MI, OpNum, AArch64_OP_IMM, Val);
1339
4.43k
    break;
1340
4.10k
  }
1341
45
  case AArch64_OP_GROUP_Matrix_0:
1342
104
  case AArch64_OP_GROUP_Matrix_16:
1343
1.31k
  case AArch64_OP_GROUP_Matrix_32:
1344
1.78k
  case AArch64_OP_GROUP_Matrix_64: {
1345
1.78k
    unsigned EltSize = temp_arg_0;
1346
1.78k
    AArch64_set_detail_op_sme(MI, OpNum, AArch64_SME_MATRIX_TILE, (AArch64Layout_VectorLayout) EltSize);
1347
1.78k
    break;
1348
1.31k
  }
1349
793
  case AArch64_OP_GROUP_MatrixTileVector_0:
1350
2.73k
  case AArch64_OP_GROUP_MatrixTileVector_1: {
1351
2.73k
    bool isVertical = temp_arg_0;
1352
2.73k
    const char *RegName = AArch64_LLVM_getRegisterName(MCInst_getOpVal(MI, OpNum), AArch64_NoRegAltName);
1353
2.73k
    const char *Dot = strstr(RegName, ".");
1354
2.73k
    AArch64Layout_VectorLayout vas = AArch64Layout_Invalid;
1355
2.73k
    if (!Dot) {
1356
      // The matrix dimensions are machine dependendent.
1357
      // Currently we do not support differentiation of machines.
1358
      // So we just indicate the use of the complete matrix.
1359
0
      vas = sme_reg_to_vas(MCInst_getOpVal(MI, OpNum));
1360
0
    } else
1361
2.73k
      vas = get_vl_by_suffix(Dot[1]);
1362
2.73k
    AArch64_set_detail_op_sme(MI, OpNum, AArch64_SME_MATRIX_TILE, vas);
1363
2.73k
    AArch64_get_detail_op(MI, -1)->sme.is_vertical = isVertical;
1364
2.73k
    break;
1365
793
  }
1366
333
  case AArch64_OP_GROUP_PostIncOperand_1:
1367
374
  case AArch64_OP_GROUP_PostIncOperand_12:
1368
1.57k
  case AArch64_OP_GROUP_PostIncOperand_16:
1369
2.15k
  case AArch64_OP_GROUP_PostIncOperand_2:
1370
2.94k
  case AArch64_OP_GROUP_PostIncOperand_24:
1371
3.05k
  case AArch64_OP_GROUP_PostIncOperand_3:
1372
4.08k
  case AArch64_OP_GROUP_PostIncOperand_32:
1373
4.60k
  case AArch64_OP_GROUP_PostIncOperand_4:
1374
4.66k
  case AArch64_OP_GROUP_PostIncOperand_48:
1375
4.74k
  case AArch64_OP_GROUP_PostIncOperand_6:
1376
4.84k
  case AArch64_OP_GROUP_PostIncOperand_64:
1377
5.61k
  case AArch64_OP_GROUP_PostIncOperand_8: {
1378
5.61k
    uint64_t Imm = temp_arg_0;
1379
5.61k
    unsigned Reg = MCInst_getOpVal(MI, OpNum);
1380
5.61k
    if (Reg == AArch64_XZR) {
1381
0
      AArch64_get_detail_op(MI, -1)->mem.disp = Imm;
1382
0
      AArch64_get_detail(MI)->post_index = true;
1383
0
      AArch64_inc_op_count(MI);
1384
0
    } else
1385
5.61k
      AArch64_set_detail_op_reg(MI, OpNum, Reg);
1386
5.61k
    break;
1387
4.84k
  }
1388
1.94k
  case AArch64_OP_GROUP_PredicateAsCounter_0:
1389
2.01k
  case AArch64_OP_GROUP_PredicateAsCounter_16:
1390
2.03k
  case AArch64_OP_GROUP_PredicateAsCounter_32:
1391
2.07k
  case AArch64_OP_GROUP_PredicateAsCounter_64:
1392
2.09k
  case AArch64_OP_GROUP_PredicateAsCounter_8: {
1393
2.09k
    unsigned EltSize = temp_arg_0;
1394
2.09k
    AArch64_get_detail_op(MI, 0)->vas = EltSize;
1395
2.09k
    AArch64_set_detail_op_reg(MI, OpNum,
1396
2.09k
        MCInst_getOpVal(MI, OpNum) - AArch64_P0);
1397
2.09k
    break;
1398
2.07k
  }
1399
1.88k
  case AArch64_OP_GROUP_PrefetchOp_0:
1400
4.27k
  case AArch64_OP_GROUP_PrefetchOp_1: {
1401
4.27k
    bool IsSVEPrefetch = (bool) temp_arg_0;
1402
4.27k
    unsigned prfop = MCInst_getOpVal(MI, (OpNum));
1403
4.27k
    aarch64_sysop sysop;
1404
4.27k
    if (IsSVEPrefetch) {
1405
2.38k
      const AArch64SVEPRFM_SVEPRFM *PRFM = AArch64SVEPRFM_lookupSVEPRFMByEncoding(prfop);
1406
2.38k
      if (PRFM) {
1407
2.06k
        sysop.alias = PRFM->SysAlias;
1408
2.06k
        sysop.sub_type = AArch64_OP_SVEPRFM;
1409
2.06k
        AArch64_set_detail_op_sys(MI, OpNum, sysop, AArch64_OP_SYSALIAS);
1410
2.06k
        break;
1411
2.06k
      }
1412
2.38k
    } else {
1413
1.88k
      const AArch64PRFM_PRFM *PRFM = AArch64PRFM_lookupPRFMByEncoding(prfop);
1414
1.88k
      if (PRFM && AArch64_testFeatureList(MI->csh->mode, PRFM->FeaturesRequired)) {
1415
1.10k
        sysop.alias = PRFM->SysAlias;
1416
1.10k
        sysop.sub_type = AArch64_OP_PRFM;
1417
1.10k
        AArch64_set_detail_op_sys(MI, OpNum, sysop, AArch64_OP_SYSALIAS);
1418
1.10k
        break;
1419
1.10k
      }
1420
1.88k
    }
1421
1.10k
    AArch64_get_detail_op(MI, 0)->type = AArch64_OP_IMM;
1422
1.10k
    AArch64_get_detail_op(MI, 0)->imm = prfop;
1423
1.10k
    AArch64_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
1424
1.10k
    AArch64_inc_op_count(MI);
1425
1.10k
    break;
1426
4.27k
  }
1427
234
  case AArch64_OP_GROUP_SImm_16:
1428
517
  case AArch64_OP_GROUP_SImm_8: {
1429
517
    AArch64_set_detail_op_imm(MI, OpNum, AArch64_OP_IMM,
1430
517
        MCInst_getOpVal(MI, OpNum));
1431
517
    break;
1432
234
  }
1433
1.76k
  case AArch64_OP_GROUP_SVELogicalImm_int16_t:
1434
2.79k
  case AArch64_OP_GROUP_SVELogicalImm_int32_t:
1435
3.02k
  case AArch64_OP_GROUP_SVELogicalImm_int64_t: {
1436
    // General issue here that we do not save the operand type
1437
    // for each operand. So we choose the largest type.
1438
3.02k
    uint64_t Val = MCInst_getOpVal(MI, OpNum);
1439
3.02k
    uint64_t DecodedVal = AArch64_AM_decodeLogicalImmediate(Val, 64);
1440
3.02k
    AArch64_set_detail_op_imm(MI, OpNum, AArch64_OP_IMM, DecodedVal);
1441
3.02k
    break;
1442
2.79k
  }
1443
37.5k
  case AArch64_OP_GROUP_SVERegOp_0:
1444
50.9k
  case AArch64_OP_GROUP_SVERegOp_b:
1445
73.1k
  case AArch64_OP_GROUP_SVERegOp_d:
1446
97.3k
  case AArch64_OP_GROUP_SVERegOp_h:
1447
97.9k
  case AArch64_OP_GROUP_SVERegOp_q:
1448
123k
  case AArch64_OP_GROUP_SVERegOp_s: {
1449
123k
    char Suffix = (char) temp_arg_0;
1450
123k
    AArch64_get_detail_op(MI, 0)->vas = get_vl_by_suffix(Suffix);
1451
123k
    AArch64_set_detail_op_reg(MI, OpNum, MCInst_getOpVal(MI, OpNum));
1452
123k
    break;
1453
97.9k
  }
1454
1.75k
  case AArch64_OP_GROUP_UImm12Offset_1:
1455
1.91k
  case AArch64_OP_GROUP_UImm12Offset_16:
1456
4.60k
  case AArch64_OP_GROUP_UImm12Offset_2:
1457
5.30k
  case AArch64_OP_GROUP_UImm12Offset_4:
1458
6.34k
  case AArch64_OP_GROUP_UImm12Offset_8: {
1459
6.34k
    unsigned Scale = temp_arg_0;
1460
6.34k
    AArch64_set_detail_op_imm(MI, OpNum, AArch64_OP_IMM,
1461
6.34k
        Scale * MCInst_getOpVal(MI, OpNum));
1462
6.34k
    break;
1463
5.30k
  }
1464
17.4k
  case AArch64_OP_GROUP_VectorIndex_1:
1465
17.4k
  case AArch64_OP_GROUP_VectorIndex_8: {
1466
17.4k
    assert(AArch64_get_detail(MI)->op_count > 0);
1467
17.4k
    unsigned Scale = temp_arg_0;
1468
17.4k
    unsigned VIndex = Scale * MCInst_getOpVal(MI, OpNum);
1469
    // The index can ether be for one operand, or for each operand of a list.
1470
17.4k
    if (!AArch64_get_detail_op(MI, -1)->is_list_member) {
1471
9.60k
      AArch64_get_detail_op(MI, -1)->vector_index = VIndex;
1472
9.60k
      break;
1473
9.60k
    }
1474
29.0k
    for (int i = AArch64_get_detail(MI)->op_count - 1; i >= 0; --i) {
1475
21.1k
      if (!AArch64_get_detail(MI)->operands[i].is_list_member)
1476
0
        break;
1477
21.1k
      AArch64_get_detail(MI)->operands[i].vector_index = VIndex;
1478
21.1k
    }
1479
7.88k
    break;
1480
17.4k
  }
1481
11
  case AArch64_OP_GROUP_ZPRasFPR_128:
1482
140
  case AArch64_OP_GROUP_ZPRasFPR_16:
1483
308
  case AArch64_OP_GROUP_ZPRasFPR_32:
1484
430
  case AArch64_OP_GROUP_ZPRasFPR_64:
1485
493
  case AArch64_OP_GROUP_ZPRasFPR_8: {
1486
493
    unsigned Base;
1487
493
    unsigned Width = temp_arg_0;
1488
493
    switch (Width) {
1489
63
    case 8:
1490
63
      Base = AArch64_B0;
1491
63
      break;
1492
129
    case 16:
1493
129
      Base = AArch64_H0;
1494
129
      break;
1495
168
    case 32:
1496
168
      Base = AArch64_S0;
1497
168
      break;
1498
122
    case 64:
1499
122
      Base = AArch64_D0;
1500
122
      break;
1501
11
    case 128:
1502
11
      Base = AArch64_Q0;
1503
11
      break;
1504
0
    default:
1505
0
      assert(0 && "Unsupported width");
1506
493
    }
1507
493
    unsigned Reg = MCInst_getOpVal(MI, (OpNum));
1508
493
    AArch64_set_detail_op_reg(MI, OpNum, Reg - AArch64_Z0 + Base);
1509
493
    break;
1510
493
  }
1511
192k
  }
1512
192k
}
1513
1514
/// Fills cs_detail with the data of the operand.
1515
/// This function handles operands which original printer function is a template
1516
/// with two arguments.
1517
static void add_cs_detail_template_2(MCInst *MI, aarch64_op_group op_group,
1518
                   unsigned OpNum, uint64_t temp_arg_0, uint64_t temp_arg_1)
1519
36.3k
{
1520
36.3k
  if (!detail_is_set(MI))
1521
0
    return;
1522
36.3k
  switch (op_group) {
1523
0
  default:
1524
0
    printf("ERROR: Operand group %d not handled!\n", op_group);
1525
0
    assert(0);
1526
339
  case AArch64_OP_GROUP_ComplexRotationOp_180_90:
1527
1.36k
  case AArch64_OP_GROUP_ComplexRotationOp_90_0: {
1528
1.36k
    unsigned Angle = temp_arg_0;
1529
1.36k
    unsigned Remainder = temp_arg_1;
1530
1.36k
    unsigned Imm = (MCInst_getOpVal(MI, OpNum) * Angle) + Remainder;
1531
1.36k
    AArch64_set_detail_op_imm(MI, OpNum, AArch64_OP_IMM, Imm);
1532
1.36k
    break;
1533
339
  }
1534
41
  case AArch64_OP_GROUP_ExactFPImm_AArch64ExactFPImm_half_AArch64ExactFPImm_one:
1535
107
  case AArch64_OP_GROUP_ExactFPImm_AArch64ExactFPImm_half_AArch64ExactFPImm_two:
1536
728
  case AArch64_OP_GROUP_ExactFPImm_AArch64ExactFPImm_zero_AArch64ExactFPImm_one: {
1537
728
    aarch64_exactfpimm ImmIs0 = temp_arg_0;
1538
728
    aarch64_exactfpimm ImmIs1 = temp_arg_1;
1539
728
    const AArch64ExactFPImm_ExactFPImm *Imm0Desc = AArch64ExactFPImm_lookupExactFPImmByEnum(ImmIs0);
1540
728
    const AArch64ExactFPImm_ExactFPImm *Imm1Desc = AArch64ExactFPImm_lookupExactFPImmByEnum(ImmIs1);
1541
728
    unsigned Val = MCInst_getOpVal(MI, (OpNum));
1542
728
    aarch64_sysop sysop;
1543
728
    sysop.imm = Val ? Imm1Desc->SysImm : Imm0Desc->SysImm;
1544
728
    sysop.sub_type = AArch64_OP_EXACTFPIMM;
1545
728
    AArch64_set_detail_op_sys(MI, OpNum, sysop, AArch64_OP_SYSIMM);
1546
728
    break;
1547
107
  }
1548
477
  case AArch64_OP_GROUP_ImmRangeScale_2_1:
1549
1.83k
  case AArch64_OP_GROUP_ImmRangeScale_4_3: {
1550
1.83k
    uint64_t Scale = temp_arg_0;
1551
1.83k
    uint64_t Offset = temp_arg_1;
1552
1.83k
    unsigned FirstImm = Scale * MCInst_getOpVal(MI, (OpNum));
1553
1.83k
    AArch64_set_detail_op_imm_range(MI, OpNum, FirstImm, Offset);
1554
1.83k
    break;
1555
477
  }
1556
14
  case AArch64_OP_GROUP_MemExtend_w_128:
1557
101
  case AArch64_OP_GROUP_MemExtend_w_16:
1558
146
  case AArch64_OP_GROUP_MemExtend_w_32:
1559
382
  case AArch64_OP_GROUP_MemExtend_w_64:
1560
435
  case AArch64_OP_GROUP_MemExtend_w_8:
1561
446
  case AArch64_OP_GROUP_MemExtend_x_128:
1562
1.20k
  case AArch64_OP_GROUP_MemExtend_x_16:
1563
1.22k
  case AArch64_OP_GROUP_MemExtend_x_32:
1564
1.46k
  case AArch64_OP_GROUP_MemExtend_x_64:
1565
1.52k
  case AArch64_OP_GROUP_MemExtend_x_8: {
1566
1.52k
    char SrcRegKind = (char) temp_arg_0;
1567
1.52k
    unsigned ExtWidth = temp_arg_1;
1568
1.52k
    bool SignExtend = MCInst_getOpVal(MI, OpNum);
1569
1.52k
    bool DoShift = MCInst_getOpVal(MI, OpNum + 1);
1570
1.52k
    AArch64_set_detail_shift_ext(MI, OpNum, SignExtend, DoShift, ExtWidth,
1571
1.52k
                   SrcRegKind);
1572
1.52k
    break;
1573
1.46k
  }
1574
3.77k
  case AArch64_OP_GROUP_TypedVectorList_0_b:
1575
11.6k
  case AArch64_OP_GROUP_TypedVectorList_0_d:
1576
16.9k
  case AArch64_OP_GROUP_TypedVectorList_0_h:
1577
17.2k
  case AArch64_OP_GROUP_TypedVectorList_0_q:
1578
23.0k
  case AArch64_OP_GROUP_TypedVectorList_0_s:
1579
25.4k
  case AArch64_OP_GROUP_TypedVectorList_16_b:
1580
25.8k
  case AArch64_OP_GROUP_TypedVectorList_1_d:
1581
26.0k
  case AArch64_OP_GROUP_TypedVectorList_2_d:
1582
27.8k
  case AArch64_OP_GROUP_TypedVectorList_2_s:
1583
28.2k
  case AArch64_OP_GROUP_TypedVectorList_4_h:
1584
28.6k
  case AArch64_OP_GROUP_TypedVectorList_4_s:
1585
30.5k
  case AArch64_OP_GROUP_TypedVectorList_8_b:
1586
30.8k
  case AArch64_OP_GROUP_TypedVectorList_8_h: {
1587
30.8k
    uint8_t NumLanes = (uint8_t) temp_arg_0;
1588
30.8k
    char LaneKind = (char) temp_arg_1;
1589
30.8k
    uint16_t Pair = ((NumLanes << 8) | LaneKind);
1590
1591
30.8k
    AArch64Layout_VectorLayout vas = AArch64Layout_Invalid;
1592
30.8k
    switch (Pair) {
1593
0
    default:
1594
0
      printf("Typed vector list with NumLanes = %d and LaneKind = %c not handled.\n",
1595
0
            NumLanes, LaneKind);
1596
0
      assert(0);
1597
1.84k
    case ((8 << 8) | 'b'):
1598
1.84k
      vas = AArch64Layout_VL_8B;
1599
1.84k
      break;
1600
413
    case ((4 << 8) | 'h'):
1601
413
      vas = AArch64Layout_VL_4H;
1602
413
      break;
1603
1.78k
    case ((2 << 8) | 's'):
1604
1.78k
      vas = AArch64Layout_VL_2S;
1605
1.78k
      break;
1606
440
    case ((1 << 8) | 'd'):
1607
440
      vas = AArch64Layout_VL_1D;
1608
440
      break;
1609
2.31k
    case ((16 << 8) | 'b'):
1610
2.31k
      vas = AArch64Layout_VL_16B;
1611
2.31k
      break;
1612
364
    case ((8 << 8) | 'h'):
1613
364
      vas = AArch64Layout_VL_8H;
1614
364
      break;
1615
403
    case ((4 << 8) | 's'):
1616
403
      vas = AArch64Layout_VL_4S;
1617
403
      break;
1618
238
    case ((2 << 8) | 'd'):
1619
238
      vas = AArch64Layout_VL_2D;
1620
238
      break;
1621
3.77k
    case 'b':
1622
3.77k
      vas = AArch64Layout_VL_B;
1623
3.77k
      break;
1624
5.26k
    case 'h':
1625
5.26k
      vas = AArch64Layout_VL_H;
1626
5.26k
      break;
1627
5.82k
    case 's':
1628
5.82k
      vas = AArch64Layout_VL_S;
1629
5.82k
      break;
1630
7.90k
    case 'd':
1631
7.90k
      vas = AArch64Layout_VL_D;
1632
7.90k
      break;
1633
329
    case 'q':
1634
329
      vas = AArch64Layout_VL_Q;
1635
329
      break;
1636
0
    case '\0':
1637
      // Implicitly Typed register
1638
0
      break;
1639
30.8k
    }
1640
1641
30.8k
    unsigned Reg = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
1642
30.8k
    unsigned NumRegs = get_vec_list_num_regs(MI, Reg);
1643
30.8k
    unsigned Stride = get_vec_list_stride(MI, Reg);
1644
30.8k
    Reg = get_vec_list_first_reg(MI, Reg);
1645
1646
30.8k
    if ((MCRegisterClass_contains(
1647
30.8k
         MCRegisterInfo_getRegClass(MI->MRI, AArch64_ZPRRegClassID),
1648
30.8k
         Reg) ||
1649
30.8k
       MCRegisterClass_contains(
1650
16.0k
         MCRegisterInfo_getRegClass(MI->MRI, AArch64_PPRRegClassID),
1651
16.0k
         Reg)) &&
1652
30.8k
      NumRegs > 1 && Stride == 1 &&
1653
30.8k
      Reg < getNextVectorRegister(Reg, NumRegs - 1)) {
1654
6.75k
        AArch64_get_detail_op(MI, 0)->is_list_member = true;
1655
6.75k
        AArch64_get_detail_op(MI, 0)->vas = vas;
1656
6.75k
        AArch64_set_detail_op_reg(MI, OpNum, Reg);
1657
6.75k
        if (NumRegs > 1) {
1658
6.75k
          AArch64_get_detail_op(MI, 0)->is_list_member = true;
1659
6.75k
          AArch64_get_detail_op(MI, 0)->vas = vas;
1660
6.75k
          AArch64_set_detail_op_reg(MI, OpNum, getNextVectorRegister(Reg, NumRegs - 1));
1661
6.75k
        }
1662
24.1k
    } else {
1663
76.3k
      for (unsigned i = 0; i < NumRegs;
1664
52.2k
         ++i, Reg = getNextVectorRegister(Reg, Stride)) {
1665
52.2k
        AArch64_get_detail_op(MI, 0)->is_list_member = true;
1666
52.2k
        AArch64_get_detail_op(MI, 0)->vas = vas;
1667
52.2k
        AArch64_set_detail_op_reg(MI, OpNum, Reg);
1668
52.2k
      }
1669
24.1k
    }
1670
30.8k
  }
1671
36.3k
  }
1672
36.3k
}
1673
1674
/// Fills cs_detail with the data of the operand.
1675
/// This function handles operands which original printer function is a template
1676
/// with four arguments.
1677
static void add_cs_detail_template_4(MCInst *MI, aarch64_op_group op_group,
1678
                   unsigned OpNum, uint64_t temp_arg_0, uint64_t temp_arg_1,
1679
                   uint64_t temp_arg_2, uint64_t temp_arg_3)
1680
9.12k
{
1681
9.12k
  if (!detail_is_set(MI))
1682
0
    return;
1683
9.12k
  switch (op_group) {
1684
0
  default:
1685
0
    printf("ERROR: Operand group %d not handled!\n", op_group);
1686
0
    assert(0);
1687
262
  case AArch64_OP_GROUP_RegWithShiftExtend_0_128_x_0:
1688
523
  case AArch64_OP_GROUP_RegWithShiftExtend_0_16_w_d:
1689
651
  case AArch64_OP_GROUP_RegWithShiftExtend_0_16_w_s:
1690
1.72k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_16_x_0:
1691
2.08k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_16_x_d:
1692
2.26k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_16_x_s:
1693
2.60k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_32_w_d:
1694
2.71k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_32_w_s:
1695
3.15k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_32_x_0:
1696
3.54k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_32_x_d:
1697
3.57k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_32_x_s:
1698
3.63k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_64_w_d:
1699
3.65k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_64_w_s:
1700
4.36k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_64_x_0:
1701
4.51k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_64_x_d:
1702
4.54k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_64_x_s:
1703
5.02k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_8_w_d:
1704
5.34k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_8_w_s:
1705
6.19k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_8_x_0:
1706
7.40k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_8_x_d:
1707
7.59k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_8_x_s:
1708
7.83k
  case AArch64_OP_GROUP_RegWithShiftExtend_1_16_w_d:
1709
8.00k
  case AArch64_OP_GROUP_RegWithShiftExtend_1_16_w_s:
1710
8.18k
  case AArch64_OP_GROUP_RegWithShiftExtend_1_32_w_d:
1711
8.42k
  case AArch64_OP_GROUP_RegWithShiftExtend_1_32_w_s:
1712
8.50k
  case AArch64_OP_GROUP_RegWithShiftExtend_1_64_w_d:
1713
8.69k
  case AArch64_OP_GROUP_RegWithShiftExtend_1_64_w_s:
1714
8.95k
  case AArch64_OP_GROUP_RegWithShiftExtend_1_8_w_d:
1715
9.12k
  case AArch64_OP_GROUP_RegWithShiftExtend_1_8_w_s: {
1716
    // signed (s) and unsigned (u) extend
1717
9.12k
    bool SignExtend = (bool) temp_arg_0;
1718
    // Extend width
1719
9.12k
    int ExtWidth = (int) temp_arg_1;
1720
    // w = word, x = doubleword
1721
9.12k
    char SrcRegKind = (char) temp_arg_2;
1722
    // Vector register element/arrangement specifier:
1723
    // B = 8bit, H = 16bit, S = 32bit, D = 64bit, Q = 128bit
1724
    // No suffix = complete register
1725
    // According to: ARM Reference manual supplement, doc number: DDI 0584
1726
9.12k
    char Suffix = (char) temp_arg_3;
1727
1728
    // Register will be added in printOperand() afterwards. Here we only handle
1729
    // shift and extend.
1730
9.12k
    AArch64_get_detail_op(MI, -1)->vas = get_vl_by_suffix(Suffix);
1731
1732
9.12k
    bool DoShift = ExtWidth != 8;
1733
9.12k
    if (!(SignExtend || DoShift || SrcRegKind == 'w'))
1734
2.25k
      return;
1735
1736
6.86k
    AArch64_set_detail_shift_ext(MI, OpNum, SignExtend, DoShift, ExtWidth,
1737
6.86k
                   SrcRegKind);
1738
6.86k
    break;
1739
9.12k
  }
1740
9.12k
  }
1741
9.12k
}
1742
1743
void AArch64_add_cs_detail(MCInst *MI, int /* aarch64_op_group */ op_group,
1744
601k
             va_list args) {
1745
601k
  if (!detail_is_set(MI) || !map_fill_detail_ops(MI))
1746
0
    return;
1747
1748
601k
  switch (op_group) {
1749
0
  default:
1750
0
    printf("Operand group %d not handled\n", op_group);
1751
0
    break;
1752
1.95k
  case AArch64_OP_GROUP_AddSubImm:
1753
4.64k
  case AArch64_OP_GROUP_AdrLabel:
1754
6.50k
  case AArch64_OP_GROUP_AdrpLabel:
1755
20.3k
  case AArch64_OP_GROUP_AlignedLabel:
1756
20.3k
  case AArch64_OP_GROUP_AMNoIndex:
1757
22.2k
  case AArch64_OP_GROUP_ArithExtend:
1758
22.3k
  case AArch64_OP_GROUP_BarriernXSOption:
1759
22.9k
  case AArch64_OP_GROUP_BarrierOption:
1760
22.9k
  case AArch64_OP_GROUP_BTIHintOp:
1761
24.8k
  case AArch64_OP_GROUP_CondCode:
1762
26.2k
  case AArch64_OP_GROUP_ExtendedRegister:
1763
27.6k
  case AArch64_OP_GROUP_FPImmOperand:
1764
32.0k
  case AArch64_OP_GROUP_GPR64as32:
1765
32.0k
  case AArch64_OP_GROUP_GPR64x8:
1766
35.2k
  case AArch64_OP_GROUP_Imm:
1767
35.3k
  case AArch64_OP_GROUP_ImmHex:
1768
35.3k
  case AArch64_OP_GROUP_ImplicitlyTypedVectorList:
1769
35.3k
  case AArch64_OP_GROUP_InverseCondCode:
1770
38.6k
  case AArch64_OP_GROUP_MatrixIndex:
1771
39.8k
  case AArch64_OP_GROUP_MatrixTile:
1772
39.9k
  case AArch64_OP_GROUP_MatrixTileList:
1773
40.5k
  case AArch64_OP_GROUP_MRSSystemRegister:
1774
42.4k
  case AArch64_OP_GROUP_MSRSystemRegister:
1775
301k
  case AArch64_OP_GROUP_Operand:
1776
301k
  case AArch64_OP_GROUP_PSBHintOp:
1777
301k
  case AArch64_OP_GROUP_RPRFMOperand:
1778
306k
  case AArch64_OP_GROUP_ShiftedRegister:
1779
315k
  case AArch64_OP_GROUP_Shifter:
1780
315k
  case AArch64_OP_GROUP_SIMDType10Operand:
1781
315k
  case AArch64_OP_GROUP_SVCROp:
1782
317k
  case AArch64_OP_GROUP_SVEPattern:
1783
317k
  case AArch64_OP_GROUP_SVEVecLenSpecifier:
1784
323k
  case AArch64_OP_GROUP_SysCROperand:
1785
323k
  case AArch64_OP_GROUP_SyspXzrPair:
1786
323k
  case AArch64_OP_GROUP_SystemPStateField:
1787
363k
  case AArch64_OP_GROUP_VRegOperand: {
1788
363k
    unsigned op_num = va_arg(args, unsigned);
1789
363k
    add_cs_detail_general(MI, op_group, op_num);
1790
363k
    break;
1791
323k
  }
1792
68
  case AArch64_OP_GROUP_GPRSeqPairsClassOperand_32:
1793
1.53k
  case AArch64_OP_GROUP_GPRSeqPairsClassOperand_64:
1794
2.10k
  case AArch64_OP_GROUP_Imm8OptLsl_int16_t:
1795
2.35k
  case AArch64_OP_GROUP_Imm8OptLsl_int32_t:
1796
2.77k
  case AArch64_OP_GROUP_Imm8OptLsl_int64_t:
1797
2.90k
  case AArch64_OP_GROUP_Imm8OptLsl_int8_t:
1798
3.25k
  case AArch64_OP_GROUP_Imm8OptLsl_uint16_t:
1799
3.35k
  case AArch64_OP_GROUP_Imm8OptLsl_uint32_t:
1800
3.41k
  case AArch64_OP_GROUP_Imm8OptLsl_uint64_t:
1801
3.48k
  case AArch64_OP_GROUP_Imm8OptLsl_uint8_t:
1802
9.00k
  case AArch64_OP_GROUP_ImmScale_16:
1803
10.1k
  case AArch64_OP_GROUP_ImmScale_2:
1804
10.3k
  case AArch64_OP_GROUP_ImmScale_3:
1805
10.4k
  case AArch64_OP_GROUP_ImmScale_32:
1806
15.3k
  case AArch64_OP_GROUP_ImmScale_4:
1807
19.9k
  case AArch64_OP_GROUP_ImmScale_8:
1808
20.6k
  case AArch64_OP_GROUP_LogicalImm_int16_t:
1809
23.0k
  case AArch64_OP_GROUP_LogicalImm_int32_t:
1810
24.1k
  case AArch64_OP_GROUP_LogicalImm_int64_t:
1811
24.4k
  case AArch64_OP_GROUP_LogicalImm_int8_t:
1812
24.4k
  case AArch64_OP_GROUP_Matrix_0:
1813
24.5k
  case AArch64_OP_GROUP_Matrix_16:
1814
25.7k
  case AArch64_OP_GROUP_Matrix_32:
1815
26.2k
  case AArch64_OP_GROUP_Matrix_64:
1816
27.0k
  case AArch64_OP_GROUP_MatrixTileVector_0:
1817
28.9k
  case AArch64_OP_GROUP_MatrixTileVector_1:
1818
29.2k
  case AArch64_OP_GROUP_PostIncOperand_1:
1819
29.3k
  case AArch64_OP_GROUP_PostIncOperand_12:
1820
30.5k
  case AArch64_OP_GROUP_PostIncOperand_16:
1821
31.1k
  case AArch64_OP_GROUP_PostIncOperand_2:
1822
31.8k
  case AArch64_OP_GROUP_PostIncOperand_24:
1823
32.0k
  case AArch64_OP_GROUP_PostIncOperand_3:
1824
33.0k
  case AArch64_OP_GROUP_PostIncOperand_32:
1825
33.5k
  case AArch64_OP_GROUP_PostIncOperand_4:
1826
33.6k
  case AArch64_OP_GROUP_PostIncOperand_48:
1827
33.6k
  case AArch64_OP_GROUP_PostIncOperand_6:
1828
33.7k
  case AArch64_OP_GROUP_PostIncOperand_64:
1829
34.5k
  case AArch64_OP_GROUP_PostIncOperand_8:
1830
36.5k
  case AArch64_OP_GROUP_PredicateAsCounter_0:
1831
36.5k
  case AArch64_OP_GROUP_PredicateAsCounter_16:
1832
36.5k
  case AArch64_OP_GROUP_PredicateAsCounter_32:
1833
36.6k
  case AArch64_OP_GROUP_PredicateAsCounter_64:
1834
36.6k
  case AArch64_OP_GROUP_PredicateAsCounter_8:
1835
38.5k
  case AArch64_OP_GROUP_PrefetchOp_0:
1836
40.9k
  case AArch64_OP_GROUP_PrefetchOp_1:
1837
41.1k
  case AArch64_OP_GROUP_SImm_16:
1838
41.4k
  case AArch64_OP_GROUP_SImm_8:
1839
43.2k
  case AArch64_OP_GROUP_SVELogicalImm_int16_t:
1840
44.2k
  case AArch64_OP_GROUP_SVELogicalImm_int32_t:
1841
44.4k
  case AArch64_OP_GROUP_SVELogicalImm_int64_t:
1842
82.0k
  case AArch64_OP_GROUP_SVERegOp_0:
1843
95.4k
  case AArch64_OP_GROUP_SVERegOp_b:
1844
117k
  case AArch64_OP_GROUP_SVERegOp_d:
1845
141k
  case AArch64_OP_GROUP_SVERegOp_h:
1846
142k
  case AArch64_OP_GROUP_SVERegOp_q:
1847
168k
  case AArch64_OP_GROUP_SVERegOp_s:
1848
170k
  case AArch64_OP_GROUP_UImm12Offset_1:
1849
170k
  case AArch64_OP_GROUP_UImm12Offset_16:
1850
173k
  case AArch64_OP_GROUP_UImm12Offset_2:
1851
173k
  case AArch64_OP_GROUP_UImm12Offset_4:
1852
174k
  case AArch64_OP_GROUP_UImm12Offset_8:
1853
192k
  case AArch64_OP_GROUP_VectorIndex_1:
1854
192k
  case AArch64_OP_GROUP_VectorIndex_8:
1855
192k
  case AArch64_OP_GROUP_ZPRasFPR_128:
1856
192k
  case AArch64_OP_GROUP_ZPRasFPR_16:
1857
192k
  case AArch64_OP_GROUP_ZPRasFPR_32:
1858
192k
  case AArch64_OP_GROUP_ZPRasFPR_64:
1859
192k
  case AArch64_OP_GROUP_ZPRasFPR_8: {
1860
192k
    unsigned op_num = va_arg(args, unsigned);
1861
192k
    uint64_t temp_arg_0 = va_arg(args, uint64_t);
1862
192k
    add_cs_detail_template_1(MI, op_group, op_num, temp_arg_0);
1863
192k
    break;
1864
192k
  }
1865
339
  case AArch64_OP_GROUP_ComplexRotationOp_180_90:
1866
1.36k
  case AArch64_OP_GROUP_ComplexRotationOp_90_0:
1867
1.40k
  case AArch64_OP_GROUP_ExactFPImm_AArch64ExactFPImm_half_AArch64ExactFPImm_one:
1868
1.47k
  case AArch64_OP_GROUP_ExactFPImm_AArch64ExactFPImm_half_AArch64ExactFPImm_two:
1869
2.09k
  case AArch64_OP_GROUP_ExactFPImm_AArch64ExactFPImm_zero_AArch64ExactFPImm_one:
1870
2.56k
  case AArch64_OP_GROUP_ImmRangeScale_2_1:
1871
3.92k
  case AArch64_OP_GROUP_ImmRangeScale_4_3:
1872
3.94k
  case AArch64_OP_GROUP_MemExtend_w_128:
1873
4.02k
  case AArch64_OP_GROUP_MemExtend_w_16:
1874
4.07k
  case AArch64_OP_GROUP_MemExtend_w_32:
1875
4.30k
  case AArch64_OP_GROUP_MemExtend_w_64:
1876
4.36k
  case AArch64_OP_GROUP_MemExtend_w_8:
1877
4.37k
  case AArch64_OP_GROUP_MemExtend_x_128:
1878
5.13k
  case AArch64_OP_GROUP_MemExtend_x_16:
1879
5.15k
  case AArch64_OP_GROUP_MemExtend_x_32:
1880
5.38k
  case AArch64_OP_GROUP_MemExtend_x_64:
1881
5.45k
  case AArch64_OP_GROUP_MemExtend_x_8:
1882
9.22k
  case AArch64_OP_GROUP_TypedVectorList_0_b:
1883
17.1k
  case AArch64_OP_GROUP_TypedVectorList_0_d:
1884
22.3k
  case AArch64_OP_GROUP_TypedVectorList_0_h:
1885
22.7k
  case AArch64_OP_GROUP_TypedVectorList_0_q:
1886
28.5k
  case AArch64_OP_GROUP_TypedVectorList_0_s:
1887
30.8k
  case AArch64_OP_GROUP_TypedVectorList_16_b:
1888
31.2k
  case AArch64_OP_GROUP_TypedVectorList_1_d:
1889
31.5k
  case AArch64_OP_GROUP_TypedVectorList_2_d:
1890
33.3k
  case AArch64_OP_GROUP_TypedVectorList_2_s:
1891
33.7k
  case AArch64_OP_GROUP_TypedVectorList_4_h:
1892
34.1k
  case AArch64_OP_GROUP_TypedVectorList_4_s:
1893
35.9k
  case AArch64_OP_GROUP_TypedVectorList_8_b:
1894
36.3k
  case AArch64_OP_GROUP_TypedVectorList_8_h: {
1895
36.3k
    unsigned op_num = va_arg(args, unsigned);
1896
36.3k
    uint64_t temp_arg_0 = va_arg(args, uint64_t);
1897
36.3k
    uint64_t temp_arg_1 = va_arg(args, uint64_t);
1898
36.3k
    add_cs_detail_template_2(MI, op_group, op_num, temp_arg_0, temp_arg_1);
1899
36.3k
    break;
1900
35.9k
  }
1901
262
  case AArch64_OP_GROUP_RegWithShiftExtend_0_128_x_0:
1902
523
  case AArch64_OP_GROUP_RegWithShiftExtend_0_16_w_d:
1903
651
  case AArch64_OP_GROUP_RegWithShiftExtend_0_16_w_s:
1904
1.72k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_16_x_0:
1905
2.08k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_16_x_d:
1906
2.26k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_16_x_s:
1907
2.60k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_32_w_d:
1908
2.71k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_32_w_s:
1909
3.15k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_32_x_0:
1910
3.54k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_32_x_d:
1911
3.57k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_32_x_s:
1912
3.63k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_64_w_d:
1913
3.65k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_64_w_s:
1914
4.36k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_64_x_0:
1915
4.51k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_64_x_d:
1916
4.54k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_64_x_s:
1917
5.02k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_8_w_d:
1918
5.34k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_8_w_s:
1919
6.19k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_8_x_0:
1920
7.40k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_8_x_d:
1921
7.59k
  case AArch64_OP_GROUP_RegWithShiftExtend_0_8_x_s:
1922
7.83k
  case AArch64_OP_GROUP_RegWithShiftExtend_1_16_w_d:
1923
8.00k
  case AArch64_OP_GROUP_RegWithShiftExtend_1_16_w_s:
1924
8.18k
  case AArch64_OP_GROUP_RegWithShiftExtend_1_32_w_d:
1925
8.42k
  case AArch64_OP_GROUP_RegWithShiftExtend_1_32_w_s:
1926
8.50k
  case AArch64_OP_GROUP_RegWithShiftExtend_1_64_w_d:
1927
8.69k
  case AArch64_OP_GROUP_RegWithShiftExtend_1_64_w_s:
1928
8.95k
  case AArch64_OP_GROUP_RegWithShiftExtend_1_8_w_d:
1929
9.12k
  case AArch64_OP_GROUP_RegWithShiftExtend_1_8_w_s: {
1930
9.12k
    unsigned op_num = va_arg(args, unsigned);
1931
9.12k
    uint64_t temp_arg_0 = va_arg(args, uint64_t);
1932
9.12k
    uint64_t temp_arg_1 = va_arg(args, uint64_t);
1933
9.12k
    uint64_t temp_arg_2 = va_arg(args, uint64_t);
1934
9.12k
    uint64_t temp_arg_3 = va_arg(args, uint64_t);
1935
9.12k
    add_cs_detail_template_4(MI, op_group, op_num, temp_arg_0, temp_arg_1,
1936
9.12k
                 temp_arg_2, temp_arg_3);
1937
9.12k
    break;
1938
8.95k
  }
1939
601k
  }
1940
601k
}
1941
1942
/// Adds a register AArch64 operand at position OpNum and increases the op_count by
1943
/// one.
1944
void AArch64_set_detail_op_reg(MCInst *MI, unsigned OpNum, aarch64_reg Reg)
1945
481k
{
1946
481k
  if (!detail_is_set(MI))
1947
0
    return;
1948
481k
  if (Reg == AArch64_REG_ZA || (Reg >= AArch64_REG_ZAB0 && Reg <= AArch64_REG_ZT0)) {
1949
    // A tile register should be treated as SME operand.
1950
575
    AArch64_set_detail_op_sme(MI, OpNum, AArch64_SME_MATRIX_TILE, sme_reg_to_vas(Reg));
1951
575
    return;
1952
480k
  } else if (AArch64_get_detail(MI)->is_doing_sme && map_get_op_type(MI, OpNum) & CS_OP_MEM) {
1953
4.67k
    AArch64_set_detail_op_sme(MI, OpNum, AArch64_SME_MATRIX_SLICE_REG, AArch64Layout_Invalid);
1954
4.67k
    return;
1955
4.67k
  }
1956
476k
  if (map_get_op_type(MI, OpNum) & CS_OP_MEM) {
1957
73.9k
    AArch64_set_detail_op_mem(MI, OpNum, Reg);
1958
73.9k
    return;
1959
73.9k
  }
1960
1961
402k
  assert(!(map_get_op_type(MI, OpNum) & CS_OP_MEM));
1962
402k
  assert(map_get_op_type(MI, OpNum) == CS_OP_REG);
1963
1964
402k
  AArch64_get_detail_op(MI, 0)->type = AArch64_OP_REG;
1965
402k
  AArch64_get_detail_op(MI, 0)->reg = Reg;
1966
402k
  AArch64_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
1967
402k
  AArch64_inc_op_count(MI);
1968
402k
  AArch64_get_detail(MI)->is_doing_sme = false; // Disable any sme operations.
1969
402k
}
1970
1971
/// Adds an immediate AArch64 operand at position OpNum and increases the op_count
1972
/// by one.
1973
void AArch64_set_detail_op_imm(MCInst *MI, unsigned OpNum, aarch64_op_type ImmType,
1974
               int64_t Imm)
1975
113k
{
1976
113k
  if (!detail_is_set(MI))
1977
0
    return;
1978
1979
113k
  if (AArch64_get_detail(MI)->is_doing_sme && map_get_op_type(MI, OpNum) & CS_OP_MEM) {
1980
32
    AArch64_set_detail_op_sme(MI, OpNum, AArch64_SME_MATRIX_SLICE_OFF, AArch64Layout_Invalid);
1981
32
    return;
1982
32
  }
1983
113k
  AArch64_get_detail(MI)->is_doing_sme = false; // Disable any sme operations.
1984
113k
  if (map_get_op_type(MI, OpNum) & CS_OP_MEM) {
1985
33.6k
    AArch64_set_detail_op_mem(MI, OpNum, Imm);
1986
33.6k
    return;
1987
33.6k
  }
1988
1989
1990
80.2k
  assert(!(map_get_op_type(MI, OpNum) & CS_OP_MEM));
1991
80.2k
  assert(map_get_op_type(MI, OpNum) == CS_OP_IMM);
1992
80.2k
  assert(ImmType == AArch64_OP_IMM || ImmType == AArch64_OP_CIMM);
1993
1994
80.2k
  AArch64_get_detail_op(MI, 0)->type = ImmType;
1995
80.2k
  AArch64_get_detail_op(MI, 0)->imm = Imm;
1996
80.2k
  AArch64_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
1997
80.2k
  AArch64_inc_op_count(MI);
1998
80.2k
}
1999
2000
void AArch64_set_detail_op_imm_range(MCInst *MI, unsigned OpNum,
2001
               int64_t FirstImm, int64_t Offset)
2002
1.83k
{
2003
1.83k
  if (!detail_is_set(MI))
2004
0
    return;
2005
2006
1.83k
  if (AArch64_get_detail(MI)->is_doing_sme && map_get_op_type(MI, OpNum) & CS_OP_MEM) {
2007
1.83k
    AArch64_set_detail_op_sme(MI, OpNum, AArch64_SME_MATRIX_SLICE_OFF_RANGE, AArch64Layout_Invalid, FirstImm, Offset);
2008
1.83k
    return;
2009
1.83k
  }
2010
2011
0
  assert(!(map_get_op_type(MI, OpNum) & CS_OP_MEM));
2012
0
  assert(map_get_op_type(MI, OpNum) == CS_OP_IMM);
2013
2014
0
  AArch64_get_detail_op(MI, 0)->type = AArch64_OP_IMM_RANGE;
2015
0
  AArch64_get_detail_op(MI, 0)->imm_range.first = FirstImm;
2016
0
  AArch64_get_detail_op(MI, 0)->imm_range.offset = Offset;
2017
0
  AArch64_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
2018
0
  AArch64_inc_op_count(MI);
2019
0
}
2020
2021
/// Adds a memory AArch64 operand at position OpNum. op_count is *not* increased by
2022
/// one. This is done by set_mem_access().
2023
void AArch64_set_detail_op_mem(MCInst *MI, unsigned OpNum, uint64_t Val)
2024
107k
{
2025
107k
  if (!detail_is_set(MI))
2026
0
    return;
2027
107k
  assert(map_get_op_type(MI, OpNum) & CS_OP_MEM);
2028
2029
107k
  AArch64_set_mem_access(MI, true);
2030
2031
107k
  cs_op_type secondary_type = map_get_op_type(MI, OpNum) & ~CS_OP_MEM;
2032
107k
  switch (secondary_type) {
2033
0
  default:
2034
0
    assert(0 && "Secondary type not supported yet.");
2035
73.9k
  case CS_OP_REG: {
2036
73.9k
    assert(secondary_type == CS_OP_REG);
2037
73.9k
    bool is_index_reg = AArch64_get_detail_op(MI, 0)->mem.base != AArch64_REG_INVALID;
2038
73.9k
    if (is_index_reg)
2039
11.4k
      AArch64_get_detail_op(MI, 0)->mem.index = Val;
2040
62.5k
    else {
2041
62.5k
      AArch64_get_detail_op(MI, 0)->mem.base = Val;
2042
62.5k
    }
2043
2044
73.9k
    if (MCInst_opIsTying(MI, OpNum)) {
2045
      // Especially base registers can be writeback registers.
2046
      // For this they tie an MC operand which has write
2047
      // access. But this one is never processed in the printer
2048
      // (because it is never emitted). Therefor it is never
2049
      // added to the modified list.
2050
      // Here we check for this case and add the memory register
2051
      // to the modified list.
2052
17.6k
      map_add_implicit_write(MI, MCInst_getOpVal(MI, OpNum));
2053
17.6k
    }
2054
73.9k
    break;
2055
73.9k
  }
2056
33.6k
  case CS_OP_IMM: {
2057
33.6k
    assert(secondary_type == CS_OP_IMM);
2058
33.6k
    AArch64_get_detail_op(MI, 0)->mem.disp = Val;
2059
33.6k
    break;
2060
33.6k
  }
2061
107k
  }
2062
2063
107k
  AArch64_get_detail_op(MI, 0)->type = AArch64_OP_MEM;
2064
107k
  AArch64_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
2065
107k
  AArch64_set_mem_access(MI, false);
2066
107k
  AArch64_get_detail(MI)->is_doing_sme = false; // Disable any sme operations.
2067
107k
}
2068
2069
/// Adds the shift and sign extend info to the previous operand.
2070
/// op_count is *not* incremented by one.
2071
void AArch64_set_detail_shift_ext(MCInst *MI, unsigned OpNum, bool SignExtend,
2072
8.39k
                  bool DoShift, unsigned ExtWidth, char SrcRegKind) {
2073
8.39k
  bool IsLSL = !SignExtend && SrcRegKind == 'x';
2074
8.39k
  if (IsLSL)
2075
4.42k
    AArch64_get_detail_op(MI, -1)->shift.type = AArch64_SFT_LSL;
2076
3.96k
  else {
2077
3.96k
    aarch64_extender ext = SignExtend ? AArch64_EXT_SXTB : AArch64_EXT_UXTB;
2078
3.96k
    switch (SrcRegKind) {
2079
0
      default:
2080
0
        assert(0 && "Extender not handled\n");
2081
0
      case 'b':
2082
0
        ext += 0;
2083
0
        break;
2084
0
      case 'h':
2085
0
        ext += 1;
2086
0
        break;
2087
3.67k
      case 'w':
2088
3.67k
        ext += 2;
2089
3.67k
        break;
2090
297
      case 'x':
2091
297
        ext += 3;
2092
297
        break;
2093
3.96k
    }
2094
3.96k
    AArch64_get_detail_op(MI, -1)->ext = ext;
2095
3.96k
  }
2096
8.39k
  if (DoShift || IsLSL) {
2097
7.02k
    unsigned ShiftAmount = DoShift ? Log2_32(ExtWidth / 8) : 0;
2098
7.02k
    AArch64_get_detail_op(MI, -1)->shift.type = AArch64_SFT_LSL;
2099
7.02k
    AArch64_get_detail_op(MI, -1)->shift.value = ShiftAmount;
2100
7.02k
  }
2101
8.39k
}
2102
2103
/// Transforms the immediate of the operand to a float and stores it.
2104
/// Increments the op_counter by one.
2105
void AArch64_set_detail_op_float(MCInst *MI, unsigned OpNum, float Val)
2106
1.38k
{
2107
1.38k
  if (!detail_is_set(MI))
2108
0
    return;
2109
1.38k
  AArch64_get_detail_op(MI, 0)->type = AArch64_OP_FP;
2110
1.38k
  AArch64_get_detail_op(MI, 0)->fp = Val;
2111
1.38k
  AArch64_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
2112
1.38k
  AArch64_inc_op_count(MI);
2113
1.38k
  AArch64_get_detail(MI)->is_doing_sme = false; // Disable any sme operations.
2114
1.38k
}
2115
2116
/// Adds a the system operand and increases the op_count by
2117
/// one.
2118
void AArch64_set_detail_op_sys(MCInst *MI, unsigned OpNum,
2119
  aarch64_sysop sys_op, aarch64_op_type type)
2120
9.55k
{
2121
9.55k
  if (!detail_is_set(MI))
2122
0
    return;
2123
9.55k
  AArch64_get_detail_op(MI, 0)->type = type;
2124
9.55k
  AArch64_get_detail_op(MI, 0)->sysop = sys_op;
2125
9.55k
  AArch64_inc_op_count(MI);
2126
9.55k
  AArch64_get_detail(MI)->is_doing_sme = false; // Disable any sme operations.
2127
9.55k
}
2128
2129
/// Sets up a new SME operand at the currently active detail operand.
2130
6.50k
static void setup_sme_operand(MCInst *MI) {
2131
6.50k
  if (!detail_is_set(MI))
2132
0
    return;
2133
2134
6.50k
  memset(AArch64_get_detail_op(MI, 0), 0, sizeof(cs_aarch64));
2135
6.50k
  AArch64_get_detail_op(MI, 0)->type = AArch64_OP_SME_MATRIX;
2136
6.50k
  AArch64_get_detail_op(MI, 0)->sme.type = AArch64_SME_OP_INVALID;
2137
6.50k
  AArch64_get_detail_op(MI, 0)->sme.tile = AArch64_REG_INVALID;
2138
6.50k
  AArch64_get_detail_op(MI, 0)->sme.slice_reg = AArch64_REG_INVALID;
2139
6.50k
  AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm = -1;
2140
6.50k
  AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm_range.first = -1;
2141
6.50k
  AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm_range.offset = -1;
2142
6.50k
}
2143
2144
/// Adds a SME matrix component to a SME operand.
2145
void AArch64_set_detail_op_sme(MCInst *MI, unsigned OpNum, aarch64_sme_op_part part, AArch64Layout_VectorLayout vas, ...)
2146
15.7k
{
2147
  /// Unfortunately SME operand components are not consistently set with unique printer functions.
2148
  /// For example slice registers are set via normal printOperand.
2149
  /// Here we check for any previously added SME operands at index -1 and -2 whenever this is called.
2150
  /// And add it to it or create a new one and compine both of them.
2151
15.7k
  if (!detail_is_set(MI))
2152
0
    return;
2153
2154
15.7k
  va_list args;
2155
15.7k
  switch(part) {
2156
0
  default:
2157
0
    printf("Unhandled SME operand part %d\n", part);
2158
0
    assert(0);
2159
190
  case AArch64_SME_MATRIX_TILE_LIST:
2160
190
    setup_sme_operand(MI);
2161
190
    va_start(args, vas);
2162
190
    int Tile = va_arg(args, int);
2163
190
    AArch64_get_detail_op(MI, 0)->sme.type = AArch64_SME_OP_TILE;
2164
190
    AArch64_get_detail_op(MI, 0)->sme.tile = Tile;
2165
190
    AArch64_get_detail_op(MI, 0)->vas = vas;
2166
190
    break;
2167
6.31k
  case AArch64_SME_MATRIX_TILE:
2168
6.31k
    assert(map_get_op_type(MI, OpNum) == CS_OP_REG);
2169
6.31k
    setup_sme_operand(MI);
2170
6.31k
    AArch64_get_detail_op(MI, 0)->sme.type = AArch64_SME_OP_TILE;
2171
6.31k
    AArch64_get_detail_op(MI, 0)->sme.tile = MCInst_getOpVal(MI, OpNum);
2172
6.31k
    AArch64_get_detail_op(MI, 0)->vas = vas;
2173
6.31k
    AArch64_get_detail(MI)->is_doing_sme = true;
2174
6.31k
    break;
2175
4.67k
  case AArch64_SME_MATRIX_SLICE_REG:
2176
4.67k
    assert((map_get_op_type(MI, OpNum) & ~CS_OP_MEM) == CS_OP_REG);
2177
4.67k
    assert(AArch64_get_detail(MI)->op_count > 0);
2178
2179
4.67k
    if (AArch64_get_detail_op(MI, -1)->type == AArch64_OP_SME_MATRIX) {
2180
      // SME operand already present. Add the slice to it.
2181
4.67k
      AArch64_get_detail_op(MI, -1)->sme.type = AArch64_SME_OP_TILE_VEC;
2182
4.67k
      AArch64_get_detail_op(MI, -1)->sme.slice_reg = MCInst_getOpVal(MI, OpNum);
2183
4.67k
      return;
2184
4.67k
    }
2185
    // No previous SME oeprand present. But the previous one should be the tile register.
2186
    // Create a new one with that.
2187
0
    AArch64_dec_op_count(MI);
2188
0
    assert(AArch64_get_detail_op(MI, 0)->type == AArch64_OP_REG);
2189
0
    assert(AArch64_get_detail_op(MI, 0)->access == map_get_op_access(MI, OpNum));
2190
2191
0
    aarch64_reg tile = AArch64_get_detail_op(MI, 0)->reg;
2192
0
    setup_sme_operand(MI);
2193
0
    AArch64_get_detail_op(MI, 0)->sme.type = AArch64_SME_OP_TILE_VEC;
2194
0
    AArch64_get_detail_op(MI, 0)->sme.tile = tile;
2195
0
    AArch64_get_detail_op(MI, 0)->sme.slice_reg = MCInst_getOpVal(MI, OpNum);
2196
0
    break;
2197
2.71k
  case AArch64_SME_MATRIX_SLICE_OFF:
2198
2.71k
    assert(AArch64_get_detail(MI)->op_count > 0);
2199
2.71k
    assert((map_get_op_type(MI, OpNum) & ~CS_OP_MEM) == CS_OP_IMM);
2200
    // Because we took care of the slice register before, the op at -1 must be a SME operand.
2201
2.71k
    assert(AArch64_get_detail_op(MI, -1)->type == AArch64_OP_SME_MATRIX);
2202
2.71k
    assert(AArch64_get_detail_op(MI, -1)->sme.slice_offset.imm == -1);
2203
2204
2.71k
    AArch64_dec_op_count(MI);
2205
2.71k
    AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm = MCInst_getOpVal(MI, OpNum);
2206
2.71k
    AArch64_get_detail(MI)->is_doing_sme = false;
2207
2.71k
    break;
2208
1.83k
  case AArch64_SME_MATRIX_SLICE_OFF_RANGE:
2209
1.83k
    AArch64_dec_op_count(MI);
2210
1.83k
    va_start(args, vas);
2211
1.83k
    int8_t First = va_arg(args, int);
2212
1.83k
    int8_t Offset = va_arg(args, int);
2213
1.83k
    AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm_range.first = First;
2214
1.83k
    AArch64_get_detail_op(MI, 0)->sme.slice_offset.imm_range.offset = Offset;
2215
1.83k
    AArch64_get_detail_op(MI, 0)->sme.has_range_offset = true;
2216
1.83k
    AArch64_get_detail(MI)->is_doing_sme = false;
2217
1.83k
    va_end(args);
2218
1.83k
    break;
2219
15.7k
  }
2220
11.0k
  AArch64_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
2221
11.0k
  AArch64_inc_op_count(MI);
2222
11.0k
}
2223
2224
6.48k
static void insert_op(MCInst *MI, unsigned index, cs_aarch64_op op) {
2225
6.48k
  if (!detail_is_set(MI)) {
2226
0
    return;
2227
0
  }
2228
2229
6.48k
  cs_aarch64_op *ops = AArch64_get_detail(MI)->operands;
2230
6.48k
  int i = AArch64_get_detail(MI)->op_count;
2231
6.48k
  assert(i < MAX_AARCH64_OPS);
2232
6.48k
  if (index == -1) {
2233
6.48k
    ops[i] = op;
2234
6.48k
    AArch64_inc_op_count(MI);
2235
6.48k
    return;
2236
6.48k
  }
2237
0
  for (; i > 0 && i > index; --i) {
2238
0
    ops[i] = ops[i - 1];
2239
0
  }
2240
0
  ops[index] = op;
2241
0
  AArch64_inc_op_count(MI);
2242
0
}
2243
2244
/// Inserts a float to the detail operands at @index.
2245
/// If @index == -1, it pushes the operand to the end of the ops array.
2246
/// Already present operands are moved.
2247
void AArch64_insert_detail_op_float_at(MCInst *MI, unsigned index, double val,
2248
         cs_ac_type access)
2249
2.28k
{
2250
2.28k
  if (!detail_is_set(MI))
2251
0
    return;
2252
2253
2.28k
  assert(AArch64_get_detail(MI)->op_count < MAX_AARCH64_OPS);
2254
2255
2.28k
  cs_aarch64_op op;
2256
2.28k
  AArch64_setup_op(&op);
2257
2.28k
  op.type = AArch64_OP_FP;
2258
2.28k
  op.fp = val;
2259
2.28k
  op.access = access;
2260
2261
2.28k
  insert_op(MI, index, op);
2262
2.28k
}
2263
2264
/// Inserts a register to the detail operands at @index.
2265
/// If @index == -1, it pushes the operand to the end of the ops array.
2266
/// Already present operands are moved.
2267
void AArch64_insert_detail_op_reg_at(MCInst *MI, unsigned index, aarch64_reg Reg,
2268
         cs_ac_type access)
2269
2.76k
{
2270
2.76k
  if (!detail_is_set(MI))
2271
0
    return;
2272
2273
2.76k
  assert(AArch64_get_detail(MI)->op_count < MAX_AARCH64_OPS);
2274
2275
2.76k
  cs_aarch64_op op;
2276
2.76k
  AArch64_setup_op(&op);
2277
2.76k
  op.type = AArch64_OP_REG;
2278
2.76k
  op.reg = Reg;
2279
2.76k
  op.access = access;
2280
2281
2.76k
  insert_op(MI, index, op);
2282
2.76k
}
2283
2284
/// Inserts a immediate to the detail operands at @index.
2285
/// If @index == -1, it pushes the operand to the end of the ops array.
2286
/// Already present operands are moved.
2287
void AArch64_insert_detail_op_imm_at(MCInst *MI, unsigned index, int64_t Imm)
2288
1.44k
{
2289
1.44k
  if (!detail_is_set(MI))
2290
0
    return;
2291
2292
1.44k
  assert(AArch64_get_detail(MI)->op_count < MAX_AARCH64_OPS);
2293
2294
1.44k
  cs_aarch64_op op;
2295
1.44k
  AArch64_setup_op(&op);
2296
1.44k
  op.type = AArch64_OP_IMM;
2297
1.44k
  op.imm = Imm;
2298
1.44k
  op.access = CS_AC_READ;
2299
2300
1.44k
  insert_op(MI, index, op);
2301
1.44k
}
2302
2303
#endif