Coverage Report

Created: 2026-09-03 07:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/capstonenext/arch/ARM/ARMMapping.c
Line
Count
Source
1
/* Capstone Disassembly Engine */
2
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
3
/*    Rot127 <unisono@quyllur.org>, 2022-2023 */
4
5
#ifdef CAPSTONE_HAS_ARM
6
7
#include <stdio.h>
8
#include <string.h>
9
10
#include "capstone/arm.h"
11
#include "capstone/capstone.h"
12
13
#include "../../Mapping.h"
14
#include "../../MCDisassembler.h"
15
#include "../../cs_priv.h"
16
#include "../../cs_simple_types.h"
17
18
#include "ARMAddressingModes.h"
19
#include "ARMDisassemblerExtension.h"
20
#include "ARMBaseInfo.h"
21
#include "ARMLinkage.h"
22
#include "ARMInstPrinter.h"
23
#include "ARMMapping.h"
24
25
static const name_map insn_alias_mnem_map[] = {
26
#include "ARMGenCSAliasMnemMap.inc"
27
  { ARM_INS_ALIAS_ASR, "asr" },    { ARM_INS_ALIAS_LSL, "lsl" },
28
  { ARM_INS_ALIAS_LSR, "lsr" },    { ARM_INS_ALIAS_ROR, "ror" },
29
  { ARM_INS_ALIAS_RRX, "rrx" },    { ARM_INS_ALIAS_UXTW, "uxtw" },
30
  { ARM_INS_ALIAS_LDM, "ldm" },    { ARM_INS_ALIAS_POP, "pop" },
31
  { ARM_INS_ALIAS_PUSH, "push" },    { ARM_INS_ALIAS_POPW, "pop.w" },
32
  { ARM_INS_ALIAS_PUSHW, "push.w" }, { ARM_INS_ALIAS_VPOP, "vpop" },
33
  { ARM_INS_ALIAS_VPUSH, "vpush" },  { ARM_INS_ALIAS_END, NULL }
34
};
35
36
static const char *get_custom_reg_alias(unsigned reg)
37
867k
{
38
867k
  switch (reg) {
39
6.41k
  case ARM_REG_R9:
40
6.41k
    return "sb";
41
3.78k
  case ARM_REG_R10:
42
3.78k
    return "sl";
43
2.21k
  case ARM_REG_R11:
44
2.21k
    return "fp";
45
5.75k
  case ARM_REG_R12:
46
5.75k
    return "ip";
47
60.1k
  case ARM_REG_R13:
48
60.1k
    return "sp";
49
16.0k
  case ARM_REG_R14:
50
16.0k
    return "lr";
51
8.33k
  case ARM_REG_R15:
52
8.33k
    return "pc";
53
867k
  }
54
764k
  return NULL;
55
867k
}
56
57
const char *ARM_reg_name(csh handle, unsigned int reg)
58
867k
{
59
867k
  int syntax_opt = ((cs_struct *)(uintptr_t)handle)->syntax;
60
867k
  const char *alias = get_custom_reg_alias(reg);
61
867k
  if ((syntax_opt & CS_OPT_SYNTAX_CS_REG_ALIAS) && alias)
62
0
    return alias;
63
64
867k
  if (reg == ARM_REG_INVALID || reg >= ARM_REG_ENDING) {
65
    // This might be a system register or banked register encoding.
66
    // Note: The system and banked register encodings can overlap.
67
    // So this might return a system register name although a
68
    // banked register name is expected.
69
0
    const ARMSysReg_MClassSysReg *sys_reg =
70
0
      ARMSysReg_lookupMClassSysRegByEncoding(reg);
71
0
    if (sys_reg)
72
0
      return sys_reg->Name;
73
0
    const ARMBankedReg_BankedReg *banked_reg =
74
0
      ARMBankedReg_lookupBankedRegByEncoding(reg);
75
0
    if (banked_reg)
76
0
      return banked_reg->Name;
77
0
  }
78
79
867k
  if (syntax_opt & CS_OPT_SYNTAX_NOREGNAME) {
80
0
    return ARM_LLVM_getRegisterName(reg, ARM_NoRegAltName);
81
0
  }
82
867k
  return ARM_LLVM_getRegisterName(reg, ARM_RegNamesRaw);
83
867k
}
84
85
const insn_map arm_insns[] = {
86
#include "ARMGenCSMappingInsn.inc"
87
};
88
89
void ARM_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
90
1.31M
{
91
  // Not used by ARM. Information is set after disassembly.
92
1.31M
}
93
94
0
#define BETWEEN(x, y, z) (x <= y && y <= z)
95
/// Patches the register names with Capstone specific alias.
96
/// Those are common alias for registers (e.g. r15 = pc)
97
/// which are not set in LLVM.
98
static void patch_cs_reg_alias(char *asm_str)
99
0
{
100
0
  char *src = asm_str;
101
0
  size_t src_len = strlen(src);
102
0
  char *dst = asm_str;
103
104
0
  while (*src && src_len >= 2) {
105
0
    if (!(src[0] == 'r' && BETWEEN('0', src[1], '9'))) {
106
      // No r0-r9 register.
107
0
      *dst++ = *src++;
108
0
      src_len--;
109
0
      continue;
110
0
    }
111
112
0
    if (src[1] == '9') {
113
0
      if (src_len >= 3 ? !BETWEEN('0', src[2], '9') : true) {
114
        // r9 = sb
115
0
        *dst++ = 's';
116
0
        *dst++ = 'b';
117
0
        src += 2;
118
0
      } else {
119
0
        *dst++ = *src++;
120
0
        *dst++ = *src++;
121
0
      }
122
0
      src_len -= 2;
123
0
      continue;
124
0
    }
125
126
0
    if (src_len < 3) {
127
0
      break;
128
0
    }
129
0
    if (src[1] == '1' && BETWEEN('0', src[2], '5')) {
130
0
      switch (src[2]) {
131
0
      case '0':
132
0
        *dst++ = 's';
133
0
        *dst++ = 'l';
134
0
        break;
135
0
      case '1':
136
0
        *dst++ = 'f';
137
0
        *dst++ = 'p';
138
0
        break;
139
0
      case '2':
140
0
        *dst++ = 'i';
141
0
        *dst++ = 'p';
142
0
        break;
143
0
      case '3':
144
0
        *dst++ = 's';
145
0
        *dst++ = 'p';
146
0
        break;
147
0
      case '4':
148
0
        *dst++ = 'l';
149
0
        *dst++ = 'r';
150
0
        break;
151
0
      case '5':
152
0
        *dst++ = 'p';
153
0
        *dst++ = 'c';
154
0
        break;
155
0
      }
156
0
      src += 3;
157
0
      src_len -= 3;
158
0
      continue;
159
0
    }
160
0
    src_len--;
161
0
    *dst++ = *src++;
162
0
  }
163
0
  while (*src) {
164
0
    *dst++ = *src++;
165
0
  }
166
0
  *dst = '\0';
167
0
}
168
#undef BETWEEN
169
170
/// Check if PC is updated from stack. Those POP instructions
171
/// are considered of group RETURN.
172
static void check_pop_return(MCInst *MI)
173
1.31M
{
174
1.31M
  if (!MI->flat_insn->detail)
175
0
    return;
176
1.31M
  if (MI->flat_insn->id != ARM_INS_POP &&
177
1.30M
      MI->flat_insn->alias_id != ARM_INS_ALIAS_POP) {
178
1.30M
    return;
179
1.30M
  }
180
39.9k
  for (size_t i = 0; i < ARM_get_detail(MI)->op_count; ++i) {
181
35.9k
    cs_arm_op *op = &ARM_get_detail(MI)->operands[i];
182
35.9k
    if (op->type == ARM_OP_REG && op->reg == ARM_REG_PC) {
183
2.92k
      add_group(MI, ARM_GRP_RET);
184
2.92k
      return;
185
2.92k
    }
186
35.9k
  }
187
6.93k
}
188
189
/// Check if PC is directly written.Those instructions
190
/// are considered of group BRANCH.
191
static void check_writes_to_pc(MCInst *MI)
192
1.31M
{
193
1.31M
  if (!MI->flat_insn->detail)
194
0
    return;
195
4.70M
  for (size_t i = 0; i < ARM_get_detail(MI)->op_count; ++i) {
196
3.41M
    cs_arm_op *op = &ARM_get_detail(MI)->operands[i];
197
3.41M
    if (op->type == ARM_OP_REG && op->reg == ARM_REG_PC &&
198
53.6k
        (op->access & CS_AC_WRITE)) {
199
23.2k
      add_group(MI, ARM_GRP_JUMP);
200
23.2k
      return;
201
23.2k
    }
202
3.41M
  }
203
1.31M
}
204
205
/// Adds group to the instruction which are not defined in LLVM.
206
static void ARM_add_cs_groups(MCInst *MI)
207
1.31M
{
208
1.31M
  if (!MI->flat_insn->detail)
209
0
    return;
210
1.31M
  check_pop_return(MI);
211
1.31M
  check_writes_to_pc(MI);
212
1.31M
  unsigned Opcode = MI->flat_insn->id;
213
1.31M
  switch (Opcode) {
214
1.25M
  default:
215
1.25M
    return;
216
1.25M
  case ARM_INS_SVC:
217
10.2k
    add_group(MI, ARM_GRP_INT);
218
10.2k
    break;
219
12.9k
  case ARM_INS_CDP:
220
28.4k
  case ARM_INS_CDP2:
221
31.5k
  case ARM_INS_MCR:
222
34.7k
  case ARM_INS_MCR2:
223
35.5k
  case ARM_INS_MCRR:
224
36.9k
  case ARM_INS_MCRR2:
225
39.9k
  case ARM_INS_MRC:
226
43.2k
  case ARM_INS_MRC2:
227
43.3k
  case ARM_INS_SMC:
228
43.3k
    add_group(MI, ARM_GRP_PRIVILEGE);
229
43.3k
    break;
230
1.31M
  }
231
1.31M
}
232
233
static void add_alias_details(MCInst *MI)
234
29.4k
{
235
29.4k
  if (!detail_is_set(MI))
236
0
    return;
237
29.4k
  switch (MI->flat_insn->alias_id) {
238
6.37k
  default:
239
6.37k
    return;
240
6.37k
  case ARM_INS_ALIAS_POP:
241
    // Doesn't get set because memop is not printed.
242
1.28k
    if (ARM_get_detail(MI)->op_count == 1) {
243
666
      CS_ASSERT_RET(
244
666
        MI->flat_insn->usesAliasDetails &&
245
666
        "Not valid assumption for non alias details.");
246
      // Only single register pop is post-indexed
247
      // Assumes only alias details are passed here.
248
666
      ARM_get_detail(MI)->post_index = true;
249
666
    }
250
    // fallthrough
251
1.44k
  case ARM_INS_ALIAS_PUSH:
252
1.48k
  case ARM_INS_ALIAS_VPUSH:
253
2.50k
  case ARM_INS_ALIAS_VPOP:
254
2.50k
    map_add_implicit_read(MI, ARM_REG_SP);
255
2.50k
    map_add_implicit_write(MI, ARM_REG_SP);
256
2.50k
    break;
257
19.2k
  case ARM_INS_ALIAS_LDM: {
258
19.2k
    bool Writeback = true;
259
19.2k
    unsigned BaseReg = MCInst_getOpVal(MI, 0);
260
105k
    for (unsigned i = 3; i < MCInst_getNumOperands(MI); ++i) {
261
85.9k
      if (MCInst_getOpVal(MI, i) == BaseReg)
262
9.35k
        Writeback = false;
263
85.9k
    }
264
19.2k
    if (Writeback && detail_is_set(MI)) {
265
9.94k
      ARM_get_detail(MI)->operands[0].access |= CS_AC_WRITE;
266
9.94k
      MI->flat_insn->detail->writeback = true;
267
9.94k
    }
268
19.2k
    break;
269
1.48k
  }
270
127
  case ARM_INS_ALIAS_ASR:
271
743
  case ARM_INS_ALIAS_LSL:
272
1.15k
  case ARM_INS_ALIAS_LSR:
273
1.29k
  case ARM_INS_ALIAS_ROR: {
274
1.29k
    unsigned shift_value = 0;
275
1.29k
    arm_shifter shift_type = ARM_SFT_INVALID;
276
1.29k
    switch (MCInst_getOpcode(MI)) {
277
0
    default:
278
0
      CS_ASSERT_RET(0 &&
279
0
              "ASR, LSL, LSR, ROR alias not handled");
280
0
      return;
281
698
    case ARM_MOVsi: {
282
698
      MCOperand *MO2 = MCInst_getOperand(MI, 2);
283
698
      shift_type = (arm_shifter)ARM_AM_getSORegShOp(
284
698
        MCOperand_getImm(MO2));
285
286
698
      if (ARM_AM_getSORegShOp(MCOperand_getImm(MO2)) ==
287
698
          ARM_AM_rrx) {
288
0
        break;
289
0
      }
290
698
      shift_value = translateShiftImm(
291
698
        ARM_AM_getSORegOffset(MCOperand_getImm(MO2)));
292
698
      ARM_insert_detail_op_imm_at(MI, -1, shift_value,
293
698
                CS_AC_READ);
294
698
      break;
295
698
    }
296
595
    case ARM_MOVsr: {
297
595
      MCOperand *MO3 = MCInst_getOperand(MI, (3));
298
595
      shift_type =
299
595
        ARM_AM_getSORegShOp(MCOperand_getImm(MO3)) +
300
595
        ARM_SFT_REG;
301
595
      shift_value = MCInst_getOpVal(MI, 2);
302
595
      break;
303
698
    }
304
1.29k
    }
305
1.29k
    ARM_get_detail_op(MI, -2)->shift.type = shift_type;
306
1.29k
    ARM_get_detail_op(MI, -2)->shift.value = shift_value;
307
1.29k
    break;
308
1.29k
  }
309
29.4k
  }
310
29.4k
}
311
312
/// Some instructions have their operands not defined but
313
/// hardcoded as string.
314
/// Here we add those oprands to detail.
315
static void ARM_add_not_defined_ops(MCInst *MI)
316
1.31M
{
317
1.31M
  if (!detail_is_set(MI))
318
0
    return;
319
320
1.31M
  if (MI->flat_insn->is_alias && MI->flat_insn->usesAliasDetails) {
321
29.4k
    add_alias_details(MI);
322
29.4k
    return;
323
29.4k
  }
324
325
1.28M
  unsigned Opcode = MCInst_getOpcode(MI);
326
1.28M
  switch (Opcode) {
327
1.26M
  default:
328
1.26M
    return;
329
1.26M
  case ARM_t2MOVsra_glue:
330
0
  case ARM_t2MOVsrl_glue:
331
0
    ARM_insert_detail_op_imm_at(MI, 2, 1, CS_AC_READ);
332
0
    break;
333
32
  case ARM_VCMPEZD:
334
118
  case ARM_VCMPZD:
335
1.71k
  case ARM_tRSB:
336
1.92k
  case ARM_VCMPEZH:
337
1.99k
  case ARM_VCMPEZS:
338
2.44k
  case ARM_VCMPZH:
339
2.51k
  case ARM_VCMPZS:
340
2.51k
    ARM_insert_detail_op_imm_at(MI, -1, 0, CS_AC_READ);
341
2.51k
    break;
342
351
  case ARM_MVE_VSHLL_lws16bh:
343
436
  case ARM_MVE_VSHLL_lws16th:
344
460
  case ARM_MVE_VSHLL_lwu16bh:
345
634
  case ARM_MVE_VSHLL_lwu16th:
346
634
    ARM_insert_detail_op_imm_at(MI, 2, 16, CS_AC_READ);
347
634
    break;
348
283
  case ARM_MVE_VSHLL_lws8bh:
349
464
  case ARM_MVE_VSHLL_lws8th:
350
515
  case ARM_MVE_VSHLL_lwu8bh:
351
657
  case ARM_MVE_VSHLL_lwu8th:
352
657
    ARM_insert_detail_op_imm_at(MI, 2, 8, CS_AC_READ);
353
657
    break;
354
38
  case ARM_VCEQzv16i8:
355
145
  case ARM_VCEQzv2f32:
356
263
  case ARM_VCEQzv2i32:
357
541
  case ARM_VCEQzv4f16:
358
561
  case ARM_VCEQzv4f32:
359
697
  case ARM_VCEQzv4i16:
360
745
  case ARM_VCEQzv4i32:
361
1.04k
  case ARM_VCEQzv8f16:
362
1.11k
  case ARM_VCEQzv8i16:
363
1.41k
  case ARM_VCEQzv8i8:
364
1.48k
  case ARM_VCGEzv16i8:
365
1.96k
  case ARM_VCGEzv2f32:
366
2.13k
  case ARM_VCGEzv2i32:
367
2.18k
  case ARM_VCGEzv4f16:
368
2.25k
  case ARM_VCGEzv4f32:
369
2.34k
  case ARM_VCGEzv4i16:
370
2.52k
  case ARM_VCGEzv4i32:
371
2.59k
  case ARM_VCGEzv8f16:
372
2.70k
  case ARM_VCGEzv8i16:
373
2.95k
  case ARM_VCGEzv8i8:
374
3.07k
  case ARM_VCLEzv16i8:
375
3.17k
  case ARM_VCLEzv2f32:
376
3.26k
  case ARM_VCLEzv2i32:
377
3.50k
  case ARM_VCLEzv4f16:
378
3.59k
  case ARM_VCLEzv4f32:
379
3.66k
  case ARM_VCLEzv4i16:
380
3.69k
  case ARM_VCLEzv4i32:
381
3.70k
  case ARM_VCLEzv8f16:
382
4.04k
  case ARM_VCLEzv8i16:
383
4.31k
  case ARM_VCLEzv8i8:
384
4.37k
  case ARM_VCLTzv16i8:
385
4.44k
  case ARM_VCLTzv2f32:
386
4.55k
  case ARM_VCLTzv2i32:
387
4.67k
  case ARM_VCLTzv4f16:
388
4.81k
  case ARM_VCLTzv4f32:
389
5.26k
  case ARM_VCLTzv4i16:
390
5.30k
  case ARM_VCLTzv4i32:
391
5.42k
  case ARM_VCLTzv8f16:
392
5.47k
  case ARM_VCLTzv8i16:
393
5.50k
  case ARM_VCLTzv8i8:
394
5.65k
  case ARM_VCGTzv16i8:
395
5.79k
  case ARM_VCGTzv2f32:
396
6.05k
  case ARM_VCGTzv2i32:
397
6.18k
  case ARM_VCGTzv4f16:
398
6.34k
  case ARM_VCGTzv4f32:
399
6.45k
  case ARM_VCGTzv4i16:
400
6.50k
  case ARM_VCGTzv4i32:
401
6.69k
  case ARM_VCGTzv8f16:
402
7.12k
  case ARM_VCGTzv8i16:
403
7.24k
  case ARM_VCGTzv8i8:
404
7.24k
    ARM_insert_detail_op_imm_at(MI, 2, 0, CS_AC_READ);
405
7.24k
    break;
406
45
  case ARM_BX_RET:
407
45
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_LR, CS_AC_READ);
408
45
    break;
409
388
  case ARM_MOVPCLR:
410
492
  case ARM_t2SUBS_PC_LR:
411
492
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_PC, CS_AC_WRITE);
412
492
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_LR, CS_AC_READ);
413
492
    break;
414
106
  case ARM_FMSTAT:
415
106
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_APSR_NZCV,
416
106
              CS_AC_WRITE);
417
106
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_FPSCR, CS_AC_READ);
418
106
    break;
419
83
  case ARM_VLDR_FPCXTNS_off:
420
262
  case ARM_VLDR_FPCXTNS_post:
421
301
  case ARM_VLDR_FPCXTNS_pre:
422
301
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_FPCXTNS,
423
301
              CS_AC_WRITE);
424
301
    break;
425
36
  case ARM_VSTR_FPCXTNS_off:
426
64
  case ARM_VSTR_FPCXTNS_post:
427
183
  case ARM_VSTR_FPCXTNS_pre:
428
183
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_FPCXTNS, CS_AC_READ);
429
183
    break;
430
83
  case ARM_VLDR_FPCXTS_off:
431
106
  case ARM_VLDR_FPCXTS_post:
432
197
  case ARM_VLDR_FPCXTS_pre:
433
197
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_FPCXTS, CS_AC_WRITE);
434
197
    break;
435
81
  case ARM_VSTR_FPCXTS_off:
436
93
  case ARM_VSTR_FPCXTS_post:
437
125
  case ARM_VSTR_FPCXTS_pre:
438
125
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_FPCXTS, CS_AC_READ);
439
125
    break;
440
288
  case ARM_VLDR_FPSCR_NZCVQC_off:
441
366
  case ARM_VLDR_FPSCR_NZCVQC_post:
442
733
  case ARM_VLDR_FPSCR_NZCVQC_pre:
443
733
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_FPSCR_NZCVQC,
444
733
              CS_AC_WRITE);
445
733
    break;
446
40
  case ARM_VSTR_FPSCR_NZCVQC_off:
447
118
  case ARM_VSTR_FPSCR_NZCVQC_post:
448
616
  case ARM_VSTR_FPSCR_NZCVQC_pre:
449
616
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_FPSCR_NZCVQC,
450
616
              CS_AC_READ);
451
616
    break;
452
79
  case ARM_VMSR:
453
101
  case ARM_VLDR_FPSCR_off:
454
691
  case ARM_VLDR_FPSCR_post:
455
1.33k
  case ARM_VLDR_FPSCR_pre:
456
1.33k
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_FPSCR, CS_AC_WRITE);
457
1.33k
    break;
458
75
  case ARM_VSTR_FPSCR_off:
459
124
  case ARM_VSTR_FPSCR_post:
460
654
  case ARM_VSTR_FPSCR_pre:
461
654
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_FPSCR, CS_AC_READ);
462
654
    break;
463
0
  case ARM_VLDR_P0_off:
464
0
  case ARM_VLDR_P0_post:
465
0
  case ARM_VLDR_P0_pre:
466
0
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_P0, CS_AC_WRITE);
467
0
    break;
468
0
  case ARM_VSTR_P0_off:
469
0
  case ARM_VSTR_P0_post:
470
0
  case ARM_VSTR_P0_pre:
471
0
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_P0, CS_AC_READ);
472
0
    break;
473
0
  case ARM_VLDR_VPR_off:
474
0
  case ARM_VLDR_VPR_post:
475
0
  case ARM_VLDR_VPR_pre:
476
0
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_VPR, CS_AC_WRITE);
477
0
    break;
478
0
  case ARM_VSTR_VPR_off:
479
0
  case ARM_VSTR_VPR_post:
480
0
  case ARM_VSTR_VPR_pre:
481
0
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_VPR, CS_AC_READ);
482
0
    break;
483
102
  case ARM_VMSR_FPEXC:
484
102
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_FPEXC, CS_AC_WRITE);
485
102
    break;
486
97
  case ARM_VMSR_FPINST:
487
97
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_FPINST, CS_AC_WRITE);
488
97
    break;
489
18
  case ARM_VMSR_FPINST2:
490
18
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_FPINST2,
491
18
              CS_AC_WRITE);
492
18
    break;
493
69
  case ARM_VMSR_FPSID:
494
69
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_FPSID, CS_AC_WRITE);
495
69
    break;
496
53
  case ARM_t2SRSDB:
497
71
  case ARM_t2SRSIA:
498
71
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_SP, CS_AC_WRITE);
499
71
    break;
500
42
  case ARM_t2SRSDB_UPD:
501
62
  case ARM_t2SRSIA_UPD:
502
62
    ARM_insert_detail_op_reg_at(MI, 0, ARM_REG_SP,
503
62
              CS_AC_READ | CS_AC_WRITE);
504
62
    break;
505
144
  case ARM_MRSsys:
506
185
  case ARM_t2MRSsys_AR:
507
185
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_SPSR, CS_AC_READ);
508
185
    break;
509
524
  case ARM_MRS:
510
571
  case ARM_t2MRS_AR:
511
571
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_APSR, CS_AC_READ);
512
571
    break;
513
264
  case ARM_VMRS:
514
264
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_FPSCR, CS_AC_READ);
515
264
    break;
516
51
  case ARM_VMRS_FPCXTNS:
517
51
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_FPCXTNS, CS_AC_READ);
518
51
    break;
519
96
  case ARM_VMRS_FPCXTS:
520
96
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_FPCXTS, CS_AC_READ);
521
96
    break;
522
82
  case ARM_VMRS_FPEXC:
523
82
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_FPEXC, CS_AC_READ);
524
82
    break;
525
218
  case ARM_VMRS_FPINST:
526
218
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_FPINST, CS_AC_READ);
527
218
    break;
528
125
  case ARM_VMRS_FPINST2:
529
125
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_FPINST2, CS_AC_READ);
530
125
    break;
531
273
  case ARM_VMRS_FPSCR_NZCVQC:
532
273
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_FPSCR_NZCVQC,
533
273
              CS_AC_READ);
534
273
    break;
535
76
  case ARM_VMRS_FPSID:
536
76
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_FPSID, CS_AC_READ);
537
76
    break;
538
74
  case ARM_VMRS_MVFR0:
539
74
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_MVFR0, CS_AC_READ);
540
74
    break;
541
38
  case ARM_VMRS_MVFR1:
542
38
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_MVFR1, CS_AC_READ);
543
38
    break;
544
474
  case ARM_VMRS_MVFR2:
545
474
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_MVFR2, CS_AC_READ);
546
474
    break;
547
0
  case ARM_VMRS_P0:
548
0
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_P0, CS_AC_READ);
549
0
    break;
550
0
  case ARM_VMRS_VPR:
551
0
    ARM_insert_detail_op_reg_at(MI, 1, ARM_REG_VPR, CS_AC_READ);
552
0
    break;
553
0
  case ARM_MOVsr:
554
    // Add shift information
555
0
    ARM_get_detail(MI)->operands[1].shift.type =
556
0
      (arm_shifter)ARM_AM_getSORegShOp(
557
0
        MCInst_getOpVal(MI, 3)) +
558
0
      ARM_SFT_REG;
559
0
    ARM_get_detail(MI)->operands[1].shift.value =
560
0
      MCInst_getOpVal(MI, 2);
561
0
    break;
562
0
  case ARM_MOVsi:
563
0
    if (ARM_AM_getSORegShOp(MCInst_getOpVal(MI, 2)) == ARM_AM_rrx) {
564
0
      ARM_get_detail_op(MI, -1)->shift.type = ARM_SFT_RRX;
565
0
      ARM_get_detail_op(MI, -1)->shift.value =
566
0
        translateShiftImm(ARM_AM_getSORegOffset(
567
0
          MCInst_getOpVal(MI, 2)));
568
0
      return;
569
0
    }
570
571
0
    ARM_get_detail_op(MI, -1)->shift.type =
572
0
      (arm_shifter)ARM_AM_getSORegShOp(
573
0
        MCInst_getOpVal(MI, 2));
574
0
    ARM_get_detail_op(MI, -1)->shift.value = translateShiftImm(
575
0
      ARM_AM_getSORegOffset(MCInst_getOpVal(MI, 2)));
576
0
    break;
577
0
  case ARM_tLDMIA: {
578
0
    bool Writeback = true;
579
0
    unsigned BaseReg = MCInst_getOpVal(MI, 0);
580
0
    for (unsigned i = 3; i < MCInst_getNumOperands(MI); ++i) {
581
0
      if (MCInst_getOpVal(MI, i) == BaseReg)
582
0
        Writeback = false;
583
0
    }
584
0
    if (Writeback && detail_is_set(MI)) {
585
0
      ARM_get_detail(MI)->operands[0].access |= CS_AC_WRITE;
586
0
      MI->flat_insn->detail->writeback = true;
587
0
    }
588
0
    break;
589
0
  }
590
213
  case ARM_RFEDA_UPD:
591
261
  case ARM_RFEDB_UPD:
592
378
  case ARM_RFEIA_UPD:
593
671
  case ARM_RFEIB_UPD:
594
671
    get_detail(MI)->writeback = true;
595
    // fallthrough
596
885
  case ARM_RFEDA:
597
923
  case ARM_RFEDB:
598
1.00k
  case ARM_RFEIA:
599
1.08k
  case ARM_RFEIB: {
600
1.08k
    arm_reg base_reg = ARM_get_detail_op(MI, -1)->reg;
601
1.08k
    ARM_get_detail_op(MI, -1)->type = ARM_OP_MEM;
602
1.08k
    ARM_get_detail_op(MI, -1)->mem.base = base_reg;
603
1.08k
  }
604
1.28M
  }
605
1.28M
}
606
607
/// Unfortunately there is currently no way to easily extract
608
/// information about the vector data usage (sign and width used).
609
/// See: https://github.com/capstone-engine/capstone/issues/2152
610
void ARM_add_vector_data(MCInst *MI, arm_vectordata_type data_type)
611
70.5k
{
612
70.5k
  if (!detail_is_set(MI))
613
0
    return;
614
70.5k
  ARM_get_detail(MI)->vector_data = data_type;
615
70.5k
}
616
617
/// Unfortunately there is currently no way to easily extract
618
/// information about the vector size.
619
/// See: https://github.com/capstone-engine/capstone/issues/2152
620
void ARM_add_vector_size(MCInst *MI, unsigned size)
621
68.6k
{
622
68.6k
  if (!detail_is_set(MI))
623
0
    return;
624
68.6k
  ARM_get_detail(MI)->vector_size = size;
625
68.6k
}
626
627
/// For ARM the attributation of post-indexed instructions is poor.
628
/// Disponents or index register are sometimes not defined as such.
629
/// Here we try to detect such cases. We check if the base register
630
/// is a writeback register, but no other memory operand
631
/// was disassembled.
632
/// Because there must be a second memory operand (disponent/index)
633
/// We assume that the following operand is actually
634
/// the disponent/index reg.
635
static void ARM_post_index_detection(MCInst *MI)
636
1.31M
{
637
1.31M
  if (!detail_is_set(MI) || ARM_get_detail(MI)->post_index)
638
36.2k
    return;
639
640
1.27M
  int i = 0;
641
4.25M
  for (; i < ARM_get_detail(MI)->op_count; ++i) {
642
3.35M
    if (ARM_get_detail(MI)->operands[i].type & ARM_OP_MEM)
643
377k
      break;
644
3.35M
  }
645
1.27M
  if (i >= ARM_get_detail(MI)->op_count) {
646
    // Last operand
647
897k
    return;
648
897k
  }
649
650
377k
  cs_arm_op *op = &ARM_get_detail(MI)->operands[i];
651
377k
  cs_arm_op op_next = ARM_get_detail(MI)->operands[i + 1];
652
377k
  if (op_next.type == ARM_OP_INVALID || op->mem.disp != 0 ||
653
15.7k
      op->mem.index != ARM_REG_INVALID)
654
361k
    return;
655
656
15.7k
  if (op_next.type & CS_OP_IMM)
657
4.90k
    op->mem.disp = op_next.imm;
658
10.7k
  else if (op_next.type & CS_OP_REG)
659
10.7k
    op->mem.index = op_next.reg;
660
661
15.7k
  op->subtracted = op_next.subtracted;
662
15.7k
  ARM_get_detail(MI)->post_index = true;
663
15.7k
  MI->flat_insn->detail->writeback = true;
664
15.7k
  ARM_dec_op_count(MI);
665
15.7k
}
666
667
void ARM_check_mem_access_validity(MCInst *MI)
668
1.31M
{
669
1.31M
#ifndef CAPSTONE_DIET
670
1.31M
  if (!detail_is_set(MI))
671
0
    return;
672
1.31M
  const arm_suppl_info *suppl = map_get_suppl_info(MI, arm_insns);
673
1.31M
  CS_ASSERT_RET(suppl);
674
1.31M
  if (suppl->mem_acc == CS_AC_INVALID) {
675
841k
    return;
676
841k
  }
677
469k
  cs_detail *detail = get_detail(MI);
678
1.76M
  for (int i = 0; i < detail->arm.op_count; ++i) {
679
1.34M
    if (detail->arm.operands[i].type == ARM_OP_MEM &&
680
405k
        detail->arm.operands[i].access != suppl->mem_acc) {
681
42.4k
      detail->arm.operands[i].access = suppl->mem_acc;
682
42.4k
      return;
683
42.4k
    }
684
1.34M
  }
685
469k
#endif // CAPSTONE_DIET
686
469k
}
687
688
/// Decodes the asm string for a given instruction
689
/// and fills the detail information about the instruction and its operands.
690
void ARM_printer(MCInst *MI, SStream *O, void * /* MCRegisterInfo* */ info)
691
1.31M
{
692
1.31M
  MCRegisterInfo *MRI = (MCRegisterInfo *)info;
693
1.31M
  MI->MRI = MRI;
694
1.31M
  MI->fillDetailOps = detail_is_set(MI);
695
1.31M
  MI->flat_insn->usesAliasDetails = map_use_alias_details(MI);
696
1.31M
  ARM_LLVM_printInstruction(MI, O, info);
697
1.31M
  map_set_alias_id(MI, O, insn_alias_mnem_map,
698
1.31M
       ARR_SIZE(insn_alias_mnem_map) - 1);
699
1.31M
  ARM_add_not_defined_ops(MI);
700
1.31M
  ARM_post_index_detection(MI);
701
1.31M
  ARM_check_mem_access_validity(MI);
702
1.31M
  ARM_add_cs_groups(MI);
703
1.31M
  int syntax_opt = MI->csh->syntax;
704
1.31M
  if (syntax_opt & CS_OPT_SYNTAX_CS_REG_ALIAS)
705
0
    patch_cs_reg_alias(O->buffer);
706
1.31M
}
707
708
#ifndef CAPSTONE_DIET
709
static const char *const insn_name_maps[] = {
710
#include "ARMGenCSMappingInsnName.inc"
711
  // Hard coded alias in LLVM, not defined as alias or instruction.
712
  // We give them a unique ID for convenience.
713
  "vpop",
714
  "vpush",
715
};
716
#endif
717
718
#ifndef CAPSTONE_DIET
719
static const arm_reg arm_flag_regs[] = {
720
  ARM_REG_APSR,       ARM_REG_APSR_NZCV, ARM_REG_CPSR,
721
  ARM_REG_FPCXTNS,      ARM_REG_FPCXTS,  ARM_REG_FPEXC,
722
  ARM_REG_FPINST,       ARM_REG_FPSCR,   ARM_REG_FPSCR_NZCV,
723
  ARM_REG_FPSCR_NZCVQC,
724
};
725
#endif // CAPSTONE_DIET
726
727
const char *ARM_insn_name(csh handle, unsigned int id)
728
1.31M
{
729
1.31M
#ifndef CAPSTONE_DIET
730
1.31M
  if (id < ARM_INS_ALIAS_END && id > ARM_INS_ALIAS_BEGIN) {
731
0
    if (id - ARM_INS_ALIAS_BEGIN >= ARR_SIZE(insn_alias_mnem_map))
732
0
      return NULL;
733
734
0
    return insn_alias_mnem_map[id - ARM_INS_ALIAS_BEGIN - 1].name;
735
0
  }
736
1.31M
  if (id >= ARM_INS_ENDING)
737
0
    return NULL;
738
739
1.31M
  if (id < ARR_SIZE(insn_name_maps))
740
1.31M
    return insn_name_maps[id];
741
742
  // not found
743
0
  return NULL;
744
#else
745
  return NULL;
746
#endif
747
1.31M
}
748
749
#ifndef CAPSTONE_DIET
750
static const name_map group_name_maps[] = {
751
  // generic groups
752
  { ARM_GRP_INVALID, NULL },
753
  { ARM_GRP_JUMP, "jump" },
754
  { ARM_GRP_CALL, "call" },
755
  { ARM_GRP_RET, "return" },
756
  { ARM_GRP_INT, "int" },
757
  { ARM_GRP_PRIVILEGE, "privilege" },
758
  { ARM_GRP_BRANCH_RELATIVE, "branch_relative" },
759
760
// architecture-specific groups
761
#include "ARMGenCSFeatureName.inc"
762
};
763
#endif
764
765
const char *ARM_group_name(csh handle, unsigned int id)
766
1.70M
{
767
1.70M
#ifndef CAPSTONE_DIET
768
1.70M
  return id2name(group_name_maps, ARR_SIZE(group_name_maps), id);
769
#else
770
  return NULL;
771
#endif
772
1.70M
}
773
774
// list all relative branch instructions
775
// ie: insns[i].branch && !insns[i].indirect_branch
776
static const unsigned int insn_rel[] = {
777
  ARM_BL,   ARM_BLX_pred, ARM_Bcc,   ARM_t2B,  ARM_t2Bcc,
778
  ARM_tB,   ARM_tBcc, ARM_tCBNZ, ARM_tCBZ, ARM_BL_pred,
779
  ARM_BLXi, ARM_tBL,  ARM_tBLXi, 0
780
};
781
782
static const unsigned int insn_blx_rel_to_arm[] = { ARM_tBLXi, 0 };
783
784
// check if this insn is relative branch
785
bool ARM_rel_branch(cs_struct *h, unsigned int id)
786
397k
{
787
397k
  int i;
788
789
5.56M
  for (i = 0; insn_rel[i]; i++) {
790
5.16M
    if (id == insn_rel[i]) {
791
0
      return true;
792
0
    }
793
5.16M
  }
794
795
  // not found
796
397k
  return false;
797
397k
}
798
799
bool ARM_blx_to_arm_mode(cs_struct *h, unsigned int id)
800
0
{
801
0
  int i;
802
803
0
  for (i = 0; insn_blx_rel_to_arm[i]; i++)
804
0
    if (id == insn_blx_rel_to_arm[i])
805
0
      return true;
806
807
  // not found
808
0
  return false;
809
0
}
810
811
void ARM_check_updates_flags(MCInst *MI)
812
1.31M
{
813
1.31M
#ifndef CAPSTONE_DIET
814
1.31M
  if (!detail_is_set(MI))
815
0
    return;
816
1.31M
  cs_detail *detail = get_detail(MI);
817
1.37M
  for (int i = 0; i < detail->regs_write_count; ++i) {
818
202k
    if (detail->regs_write[i] == 0)
819
0
      return;
820
1.04M
    for (int j = 0; j < ARR_SIZE(arm_flag_regs); ++j) {
821
989k
      if (detail->regs_write[i] == arm_flag_regs[j]) {
822
150k
        detail->arm.update_flags = true;
823
150k
        return;
824
150k
      }
825
989k
    }
826
202k
  }
827
1.31M
#endif // CAPSTONE_DIET
828
1.31M
}
829
830
void ARM_set_instr_map_data(MCInst *MI)
831
1.31M
{
832
1.31M
  map_cs_id(MI, arm_insns, ARR_SIZE(arm_insns));
833
1.31M
  map_implicit_reads(MI, arm_insns);
834
1.31M
  map_implicit_writes(MI, arm_insns);
835
1.31M
  ARM_check_updates_flags(MI);
836
1.31M
  map_groups(MI, arm_insns);
837
1.31M
}
838
839
bool ARM_getInstruction(csh handle, const uint8_t *code, size_t code_len,
840
      MCInst *instr, uint16_t *size, uint64_t address,
841
      void *info)
842
1.31M
{
843
1.31M
  ARM_init_cs_detail(instr);
844
1.31M
  DecodeStatus Result = ARM_LLVM_getInstruction(
845
1.31M
    handle, code, code_len, instr, size, address, info);
846
1.31M
  ARM_set_instr_map_data(instr);
847
1.31M
  if (Result == MCDisassembler_SoftFail) {
848
114k
    MCInst_setSoftFail(instr);
849
114k
  }
850
1.31M
  return Result != MCDisassembler_Fail;
851
1.31M
}
852
853
#define GET_REGINFO_MC_DESC
854
#include "ARMGenRegisterInfo.inc"
855
856
void ARM_init_mri(MCRegisterInfo *MRI)
857
12.1k
{
858
12.1k
  MCRegisterInfo_InitMCRegisterInfo(MRI, ARMRegDesc, ARM_REG_ENDING, 0, 0,
859
12.1k
            ARMMCRegisterClasses,
860
12.1k
            ARR_SIZE(ARMMCRegisterClasses), 0, 0,
861
12.1k
            ARMRegDiffLists, 0, ARMSubRegIdxLists,
862
12.1k
            ARR_SIZE(ARMSubRegIdxLists), 0);
863
12.1k
}
864
865
#ifndef CAPSTONE_DIET
866
static const map_insn_ops insn_operands[] = {
867
#include "ARMGenCSMappingInsnOp.inc"
868
};
869
870
void ARM_reg_access(const cs_insn *insn, cs_regs regs_read,
871
        uint8_t *regs_read_count, cs_regs regs_write,
872
        uint8_t *regs_write_count)
873
0
{
874
0
  uint8_t i;
875
0
  uint8_t read_count, write_count;
876
0
  cs_arm *arm = &(insn->detail->arm);
877
878
0
  read_count = insn->detail->regs_read_count;
879
0
  write_count = insn->detail->regs_write_count;
880
881
  // implicit registers
882
0
  memcpy(regs_read, insn->detail->regs_read,
883
0
         read_count * sizeof(insn->detail->regs_read[0]));
884
0
  memcpy(regs_write, insn->detail->regs_write,
885
0
         write_count * sizeof(insn->detail->regs_write[0]));
886
887
  // explicit registers
888
0
  for (i = 0; i < arm->op_count; i++) {
889
0
    cs_arm_op *op = &(arm->operands[i]);
890
0
    switch ((int)op->type) {
891
0
    case ARM_OP_REG:
892
0
      if ((op->access & CS_AC_READ) &&
893
0
          !arr_exist(regs_read, read_count, op->reg)) {
894
0
        regs_read[read_count] = (uint16_t)op->reg;
895
0
        read_count++;
896
0
      }
897
0
      if ((op->access & CS_AC_WRITE) &&
898
0
          !arr_exist(regs_write, write_count, op->reg)) {
899
0
        regs_write[write_count] = (uint16_t)op->reg;
900
0
        write_count++;
901
0
      }
902
0
      break;
903
0
    case ARM_OP_MEM:
904
      // registers appeared in memory references always being read
905
0
      if ((op->mem.base != ARM_REG_INVALID) &&
906
0
          !arr_exist(regs_read, read_count, op->mem.base)) {
907
0
        regs_read[read_count] = (uint16_t)op->mem.base;
908
0
        read_count++;
909
0
      }
910
0
      if ((op->mem.index != ARM_REG_INVALID) &&
911
0
          !arr_exist(regs_read, read_count, op->mem.index)) {
912
0
        regs_read[read_count] = (uint16_t)op->mem.index;
913
0
        read_count++;
914
0
      }
915
0
      if ((insn->detail->writeback) &&
916
0
          (op->mem.base != ARM_REG_INVALID) &&
917
0
          !arr_exist(regs_write, write_count, op->mem.base)) {
918
0
        regs_write[write_count] =
919
0
          (uint16_t)op->mem.base;
920
0
        write_count++;
921
0
      }
922
0
    default:
923
0
      break;
924
0
    }
925
0
  }
926
927
0
  *regs_read_count = read_count;
928
0
  *regs_write_count = write_count;
929
0
}
930
#endif
931
932
void ARM_setup_op(cs_arm_op *op)
933
47.4M
{
934
47.4M
  memset(op, 0, sizeof(cs_arm_op));
935
47.4M
  op->type = ARM_OP_INVALID;
936
47.4M
  op->vector_index = -1;
937
47.4M
  op->neon_lane = -1;
938
47.4M
}
939
940
void ARM_init_cs_detail(MCInst *MI)
941
1.31M
{
942
1.31M
  if (detail_is_set(MI)) {
943
1.31M
    unsigned int i;
944
945
1.31M
    memset(get_detail(MI), 0,
946
1.31M
           offsetof(cs_detail, arm) + sizeof(cs_arm));
947
948
48.7M
    for (i = 0; i < ARR_SIZE(ARM_get_detail(MI)->operands); i++)
949
47.4M
      ARM_setup_op(&ARM_get_detail(MI)->operands[i]);
950
1.31M
    ARM_get_detail(MI)->cc = ARMCC_UNDEF;
951
1.31M
    ARM_get_detail(MI)->vcc = ARMVCC_None;
952
1.31M
  }
953
1.31M
}
954
955
static uint64_t t_add_pc(MCInst *MI, uint64_t v)
956
397k
{
957
397k
  int32_t imm = (int32_t)v;
958
397k
  if (ARM_rel_branch(MI->csh, MI->Opcode)) {
959
0
    uint32_t address;
960
961
    // only do this for relative branch
962
0
    if (MI->csh->mode & CS_MODE_THUMB) {
963
0
      address = (uint32_t)MI->address + 4;
964
0
      if (ARM_blx_to_arm_mode(MI->csh, MI->Opcode)) {
965
        // here need to align down to the nearest 4-byte address
966
0
#define _ALIGN_DOWN(v, align_width) ((v / align_width) * align_width)
967
0
        address = _ALIGN_DOWN(address, 4);
968
0
#undef _ALIGN_DOWN
969
0
      }
970
0
    } else {
971
0
      address = (uint32_t)MI->address + 8;
972
0
    }
973
974
0
    imm += address;
975
0
    return imm;
976
0
  }
977
397k
  return v;
978
397k
}
979
980
/// Transform a Qs register to its corresponding Ds + Offset register.
981
static uint64_t t_qpr_to_dpr_list(MCInst *MI, unsigned OpNum, uint8_t offset)
982
35.5k
{
983
35.5k
  uint64_t v = MCOperand_getReg(MCInst_getOperand(MI, OpNum));
984
35.5k
  if (v >= ARM_REG_Q0 && v <= ARM_REG_Q15)
985
0
    return ARM_REG_D0 + offset + (v - ARM_REG_Q0) * 2;
986
35.5k
  return v + offset;
987
35.5k
}
988
989
static uint64_t t_mod_imm_rotate(uint64_t v)
990
15.6k
{
991
15.6k
  unsigned Bits = v & 0xFF;
992
15.6k
  unsigned Rot = (v & 0xF00) >> 7;
993
15.6k
  int32_t Rotated = ARM_AM_rotr32(Bits, Rot);
994
15.6k
  return Rotated;
995
15.6k
}
996
997
inline static uint64_t t_mod_imm_bits(uint64_t v)
998
2.49k
{
999
2.49k
  unsigned Bits = v & 0xFF;
1000
2.49k
  return Bits;
1001
2.49k
}
1002
1003
inline static uint64_t t_mod_imm_rot(uint64_t v)
1004
2.49k
{
1005
2.49k
  unsigned Rot = (v & 0xF00) >> 7;
1006
2.49k
  return Rot;
1007
2.49k
}
1008
1009
static uint64_t t_vmov_mod_imm(uint64_t v)
1010
4.43k
{
1011
4.43k
  unsigned EltBits;
1012
4.43k
  uint64_t Val = ARM_AM_decodeVMOVModImm(v, &EltBits);
1013
4.43k
  return Val;
1014
4.43k
}
1015
1016
/// Initializes or finishes a memory operand of Capstone (depending on \p
1017
/// status). A memory operand in Capstone can be assembled by two LLVM operands.
1018
/// E.g. the base register and the immediate disponent.
1019
static void ARM_set_mem_access(MCInst *MI, bool status)
1020
716k
{
1021
716k
  if (!detail_is_set(MI))
1022
0
    return;
1023
716k
  set_doing_mem(MI, status);
1024
716k
  if (status) {
1025
358k
    ARM_get_detail_op(MI, 0)->type = ARM_OP_MEM;
1026
358k
    ARM_get_detail_op(MI, 0)->mem.base = ARM_REG_INVALID;
1027
358k
    ARM_get_detail_op(MI, 0)->mem.index = ARM_REG_INVALID;
1028
358k
    ARM_get_detail_op(MI, 0)->mem.scale = 1;
1029
358k
    ARM_get_detail_op(MI, 0)->mem.disp = 0;
1030
1031
358k
#ifndef CAPSTONE_DIET
1032
358k
    uint8_t access =
1033
358k
      map_get_op_access(MI, ARM_get_detail(MI)->op_count);
1034
358k
    ARM_get_detail_op(MI, 0)->access = access;
1035
358k
#endif
1036
358k
  } else {
1037
    // done, select the next operand slot
1038
358k
    ARM_check_safe_inc(MI);
1039
358k
    ARM_inc_op_count(MI);
1040
358k
  }
1041
716k
}
1042
1043
/// Fills cs_detail with operand shift information for the last added operand.
1044
static void add_cs_detail_RegImmShift(MCInst *MI, ARM_AM_ShiftOpc ShOpc,
1045
              unsigned ShImm)
1046
54.1k
{
1047
54.1k
  if (ShOpc == ARM_AM_no_shift || (ShOpc == ARM_AM_lsl && !ShImm))
1048
1.93k
    return;
1049
1050
52.2k
  if (!detail_is_set(MI))
1051
0
    return;
1052
1053
52.2k
  if (doing_mem(MI))
1054
5.78k
    ARM_get_detail_op(MI, 0)->shift.type = (arm_shifter)ShOpc;
1055
46.4k
  else
1056
46.4k
    ARM_get_detail_op(MI, -1)->shift.type = (arm_shifter)ShOpc;
1057
1058
52.2k
  if (ShOpc != ARM_AM_rrx) {
1059
49.6k
    if (doing_mem(MI))
1060
5.39k
      ARM_get_detail_op(MI, 0)->shift.value =
1061
5.39k
        translateShiftImm(ShImm);
1062
44.2k
    else
1063
44.2k
      ARM_get_detail_op(MI, -1)->shift.value =
1064
44.2k
        translateShiftImm(ShImm);
1065
49.6k
  }
1066
52.2k
}
1067
1068
/// Fills cs_detail with the data of the operand.
1069
/// This function handles operands which's original printer function has no
1070
/// specialities.
1071
static void add_cs_detail_general(MCInst *MI, arm_op_group op_group,
1072
          unsigned OpNum)
1073
4.61M
{
1074
4.61M
  if (!detail_is_set(MI))
1075
0
    return;
1076
4.61M
  cs_op_type op_type = map_get_op_type(MI, OpNum);
1077
1078
  // Fill cs_detail
1079
4.61M
  switch (op_group) {
1080
0
  default:
1081
0
    printf("ERROR: Operand group %d not handled!\n", op_group);
1082
0
    CS_ASSERT_RET(0);
1083
1.11M
  case ARM_OP_GROUP_PredicateOperand:
1084
1.14M
  case ARM_OP_GROUP_MandatoryPredicateOperand:
1085
1.14M
  case ARM_OP_GROUP_MandatoryInvertedPredicateOperand:
1086
1.15M
  case ARM_OP_GROUP_MandatoryRestrictedPredicateOperand: {
1087
1.15M
    ARMCC_CondCodes CC = (ARMCC_CondCodes)MCOperand_getImm(
1088
1.15M
      MCInst_getOperand(MI, OpNum));
1089
1.15M
    if ((unsigned)CC == 15 &&
1090
2.36k
        op_group == ARM_OP_GROUP_PredicateOperand) {
1091
2.36k
      ARM_get_detail(MI)->cc = ARMCC_UNDEF;
1092
2.36k
      return;
1093
2.36k
    }
1094
1.15M
    if (CC == ARMCC_HS &&
1095
15.3k
        op_group ==
1096
15.3k
          ARM_OP_GROUP_MandatoryRestrictedPredicateOperand) {
1097
817
      ARM_get_detail(MI)->cc = ARMCC_HS;
1098
817
      return;
1099
817
    }
1100
1.15M
    ARM_get_detail(MI)->cc = CC;
1101
1.15M
    if (CC != ARMCC_AL)
1102
215k
      map_add_implicit_read(MI, ARM_REG_CPSR);
1103
1.15M
    break;
1104
1.15M
  }
1105
35.3k
  case ARM_OP_GROUP_VPTPredicateOperand: {
1106
35.3k
    ARMVCC_VPTCodes VCC = (ARMVCC_VPTCodes)MCOperand_getImm(
1107
35.3k
      MCInst_getOperand(MI, OpNum));
1108
35.3k
    CS_ASSERT_RET(VCC <= ARMVCC_Else);
1109
35.3k
    if (VCC != ARMVCC_None)
1110
2.35k
      ARM_get_detail(MI)->vcc = VCC;
1111
35.3k
    break;
1112
35.3k
  }
1113
2.12M
  case ARM_OP_GROUP_Operand:
1114
2.12M
    if (op_type == CS_OP_IMM) {
1115
397k
      if (doing_mem(MI)) {
1116
0
        ARM_set_detail_op_mem(MI, OpNum, false, 0,
1117
0
                  MCInst_getOpVal(MI,
1118
0
                      OpNum));
1119
397k
      } else {
1120
397k
        ARM_set_detail_op_imm(
1121
397k
          MI, OpNum, ARM_OP_IMM,
1122
397k
          t_add_pc(MI,
1123
397k
             MCInst_getOpVal(MI, OpNum)));
1124
397k
      }
1125
1.73M
    } else if (op_type == CS_OP_REG)
1126
1.73M
      if (doing_mem(MI)) {
1127
0
        bool is_index_reg = map_get_op_type(MI, OpNum) &
1128
0
                CS_OP_MEM;
1129
0
        ARM_set_detail_op_mem(MI, OpNum, is_index_reg,
1130
0
                  is_index_reg ? 1 : 0,
1131
0
                  MCInst_getOpVal(MI,
1132
0
                      OpNum));
1133
1.73M
      } else {
1134
1.73M
        ARM_set_detail_op_reg(
1135
1.73M
          MI, OpNum, MCInst_getOpVal(MI, OpNum));
1136
1.73M
      }
1137
0
    else
1138
0
      CS_ASSERT_RET(0 && "Op type not handled.");
1139
2.12M
    break;
1140
2.12M
  case ARM_OP_GROUP_PImmediate:
1141
86.5k
    ARM_set_detail_op_imm(MI, OpNum, ARM_OP_PIMM,
1142
86.5k
              MCInst_getOpVal(MI, OpNum));
1143
86.5k
    break;
1144
155k
  case ARM_OP_GROUP_CImmediate:
1145
155k
    ARM_set_detail_op_imm(MI, OpNum, ARM_OP_CIMM,
1146
155k
              MCInst_getOpVal(MI, OpNum));
1147
155k
    break;
1148
49.5k
  case ARM_OP_GROUP_AddrMode6Operand:
1149
49.5k
    if (!doing_mem(MI))
1150
49.5k
      ARM_set_mem_access(MI, true);
1151
49.5k
    ARM_set_detail_op_mem(MI, OpNum, false, 0,
1152
49.5k
              MCInst_getOpVal(MI, OpNum));
1153
49.5k
    ARM_get_detail_op(MI, 0)->mem.align =
1154
49.5k
      MCInst_getOpVal(MI, OpNum + 1) << 3;
1155
49.5k
    ARM_set_mem_access(MI, false);
1156
49.5k
    break;
1157
16.5k
  case ARM_OP_GROUP_AddrMode6OffsetOperand: {
1158
16.5k
    arm_reg reg = MCInst_getOpVal(MI, OpNum);
1159
16.5k
    if (reg != 0) {
1160
9.66k
      ARM_set_detail_op_mem_offset(MI, OpNum, reg, false);
1161
9.66k
    }
1162
16.5k
    break;
1163
2.12M
  }
1164
47.5k
  case ARM_OP_GROUP_AddrMode7Operand:
1165
47.5k
    if (!doing_mem(MI))
1166
47.5k
      ARM_set_mem_access(MI, true);
1167
47.5k
    ARM_set_detail_op_mem(MI, OpNum, false, 0,
1168
47.5k
              MCInst_getOpVal(MI, OpNum));
1169
47.5k
    ARM_set_mem_access(MI, false);
1170
47.5k
    break;
1171
357k
  case ARM_OP_GROUP_SBitModifierOperand: {
1172
357k
    unsigned SBit = MCInst_getOpVal(MI, OpNum);
1173
1174
357k
    if (SBit == 0) {
1175
      // Does not edit set flags.
1176
38.0k
      map_remove_implicit_write(MI, ARM_CPSR);
1177
38.0k
      ARM_get_detail(MI)->update_flags = false;
1178
38.0k
      break;
1179
38.0k
    }
1180
    // Add the implicit write again. Some instruction miss it.
1181
318k
    map_add_implicit_write(MI, ARM_CPSR);
1182
318k
    ARM_get_detail(MI)->update_flags = true;
1183
318k
    break;
1184
357k
  }
1185
2.21k
  case ARM_OP_GROUP_VectorListOne:
1186
2.33k
  case ARM_OP_GROUP_VectorListOneAllLanes:
1187
2.33k
    ARM_set_detail_op_reg(MI, OpNum,
1188
2.33k
              t_qpr_to_dpr_list(MI, OpNum, 0));
1189
2.33k
    break;
1190
8.15k
  case ARM_OP_GROUP_VectorListTwo:
1191
10.2k
  case ARM_OP_GROUP_VectorListTwoAllLanes: {
1192
10.2k
    unsigned Reg = MCInst_getOpVal(MI, OpNum);
1193
10.2k
    ARM_set_detail_op_reg(MI, OpNum,
1194
10.2k
              MCRegisterInfo_getSubReg(MI->MRI, Reg,
1195
10.2k
                     ARM_dsub_0));
1196
10.2k
    ARM_set_detail_op_reg(MI, OpNum,
1197
10.2k
              MCRegisterInfo_getSubReg(MI->MRI, Reg,
1198
10.2k
                     ARM_dsub_1));
1199
10.2k
    break;
1200
8.15k
  }
1201
1.43k
  case ARM_OP_GROUP_VectorListTwoSpacedAllLanes:
1202
4.37k
  case ARM_OP_GROUP_VectorListTwoSpaced: {
1203
4.37k
    unsigned Reg = MCInst_getOpVal(MI, OpNum);
1204
4.37k
    ARM_set_detail_op_reg(MI, OpNum,
1205
4.37k
              MCRegisterInfo_getSubReg(MI->MRI, Reg,
1206
4.37k
                     ARM_dsub_0));
1207
4.37k
    ARM_set_detail_op_reg(MI, OpNum,
1208
4.37k
              MCRegisterInfo_getSubReg(MI->MRI, Reg,
1209
4.37k
                     ARM_dsub_2));
1210
4.37k
    break;
1211
1.43k
  }
1212
3.12k
  case ARM_OP_GROUP_VectorListThree:
1213
3.12k
  case ARM_OP_GROUP_VectorListThreeAllLanes:
1214
3.12k
    ARM_set_detail_op_reg(MI, OpNum,
1215
3.12k
              t_qpr_to_dpr_list(MI, OpNum, 0));
1216
3.12k
    ARM_set_detail_op_reg(MI, OpNum,
1217
3.12k
              t_qpr_to_dpr_list(MI, OpNum, 1));
1218
3.12k
    ARM_set_detail_op_reg(MI, OpNum,
1219
3.12k
              t_qpr_to_dpr_list(MI, OpNum, 2));
1220
3.12k
    break;
1221
0
  case ARM_OP_GROUP_VectorListThreeSpacedAllLanes:
1222
0
  case ARM_OP_GROUP_VectorListThreeSpaced:
1223
0
    ARM_set_detail_op_reg(MI, OpNum,
1224
0
              t_qpr_to_dpr_list(MI, OpNum, 0));
1225
0
    ARM_set_detail_op_reg(MI, OpNum,
1226
0
              t_qpr_to_dpr_list(MI, OpNum, 2));
1227
0
    ARM_set_detail_op_reg(MI, OpNum,
1228
0
              t_qpr_to_dpr_list(MI, OpNum, 4));
1229
0
    break;
1230
5.95k
  case ARM_OP_GROUP_VectorListFour:
1231
5.95k
  case ARM_OP_GROUP_VectorListFourAllLanes:
1232
5.95k
    ARM_set_detail_op_reg(MI, OpNum,
1233
5.95k
              t_qpr_to_dpr_list(MI, OpNum, 0));
1234
5.95k
    ARM_set_detail_op_reg(MI, OpNum,
1235
5.95k
              t_qpr_to_dpr_list(MI, OpNum, 1));
1236
5.95k
    ARM_set_detail_op_reg(MI, OpNum,
1237
5.95k
              t_qpr_to_dpr_list(MI, OpNum, 2));
1238
5.95k
    ARM_set_detail_op_reg(MI, OpNum,
1239
5.95k
              t_qpr_to_dpr_list(MI, OpNum, 3));
1240
5.95k
    break;
1241
0
  case ARM_OP_GROUP_VectorListFourSpacedAllLanes:
1242
0
  case ARM_OP_GROUP_VectorListFourSpaced:
1243
0
    ARM_set_detail_op_reg(MI, OpNum,
1244
0
              t_qpr_to_dpr_list(MI, OpNum, 0));
1245
0
    ARM_set_detail_op_reg(MI, OpNum,
1246
0
              t_qpr_to_dpr_list(MI, OpNum, 2));
1247
0
    ARM_set_detail_op_reg(MI, OpNum,
1248
0
              t_qpr_to_dpr_list(MI, OpNum, 4));
1249
0
    ARM_set_detail_op_reg(MI, OpNum,
1250
0
              t_qpr_to_dpr_list(MI, OpNum, 6));
1251
0
    break;
1252
30.4k
  case ARM_OP_GROUP_NoHashImmediate:
1253
30.4k
    ARM_set_detail_op_neon_lane(MI, OpNum);
1254
30.4k
    break;
1255
63.8k
  case ARM_OP_GROUP_RegisterList: {
1256
    // All operands n MI from OpNum on are registers.
1257
    // But the MappingInsnOps.inc has only a single entry for the whole
1258
    // list. So all registers in the list share those attributes.
1259
63.8k
    unsigned access = map_get_op_access(MI, OpNum);
1260
401k
    for (unsigned i = OpNum, e = MCInst_getNumOperands(MI); i != e;
1261
337k
         ++i) {
1262
337k
      unsigned Reg =
1263
337k
        MCOperand_getReg(MCInst_getOperand(MI, i));
1264
1265
337k
      ARM_check_safe_inc(MI);
1266
337k
      ARM_get_detail_op(MI, 0)->type = ARM_OP_REG;
1267
337k
      ARM_get_detail_op(MI, 0)->reg = Reg;
1268
337k
      ARM_get_detail_op(MI, 0)->access = access;
1269
337k
      ARM_inc_op_count(MI);
1270
337k
    }
1271
63.8k
    break;
1272
0
  }
1273
15.6k
  case ARM_OP_GROUP_ThumbITMask: {
1274
15.6k
    unsigned Mask = MCInst_getOpVal(MI, OpNum);
1275
15.6k
    unsigned Firstcond = MCInst_getOpVal(MI, OpNum - 1);
1276
15.6k
    unsigned CondBit0 = Firstcond & 1;
1277
15.6k
    unsigned NumTZ = CountTrailingZeros_32(Mask);
1278
15.6k
    unsigned Pos, e;
1279
15.6k
    ARM_PredBlockMask PredMask = ARM_PredBlockMaskInvalid;
1280
1281
    // Check the documentation of ARM_PredBlockMask how the bits are set.
1282
57.5k
    for (Pos = 3, e = NumTZ; Pos > e; --Pos) {
1283
41.8k
      bool Then = ((Mask >> Pos) & 1) == CondBit0;
1284
41.8k
      if (Then)
1285
12.2k
        PredMask <<= 1;
1286
29.5k
      else {
1287
29.5k
        PredMask |= 1;
1288
29.5k
        PredMask <<= 1;
1289
29.5k
      }
1290
41.8k
    }
1291
15.6k
    PredMask |= 1;
1292
15.6k
    ARM_get_detail(MI)->pred_mask = PredMask;
1293
15.6k
    break;
1294
0
  }
1295
7.68k
  case ARM_OP_GROUP_VPTMask: {
1296
7.68k
    unsigned Mask = MCInst_getOpVal(MI, OpNum);
1297
7.68k
    unsigned NumTZ = CountTrailingZeros_32(Mask);
1298
7.68k
    ARM_PredBlockMask PredMask = ARM_PredBlockMaskInvalid;
1299
1300
    // Check the documentation of ARM_PredBlockMask how the bits are set.
1301
25.9k
    for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
1302
18.3k
      bool T = ((Mask >> Pos) & 1) == 0;
1303
18.3k
      if (T)
1304
8.63k
        PredMask <<= 1;
1305
9.67k
      else {
1306
9.67k
        PredMask |= 1;
1307
9.67k
        PredMask <<= 1;
1308
9.67k
      }
1309
18.3k
    }
1310
7.68k
    PredMask |= 1;
1311
7.68k
    ARM_get_detail(MI)->pred_mask = PredMask;
1312
7.68k
    break;
1313
0
  }
1314
9.40k
  case ARM_OP_GROUP_MSRMaskOperand: {
1315
9.40k
    MCOperand *Op = MCInst_getOperand(MI, OpNum);
1316
9.40k
    unsigned SpecRegRBit = (unsigned)MCOperand_getImm(Op) >> 4;
1317
9.40k
    unsigned Mask = (unsigned)MCOperand_getImm(Op) & 0xf;
1318
9.40k
    bool IsOutReg = OpNum == 0;
1319
1320
9.40k
    if (ARM_getFeatureBits(MI->csh->mode, ARM_FeatureMClass)) {
1321
7.30k
      const ARMSysReg_MClassSysReg *TheReg;
1322
7.30k
      unsigned SYSm = (unsigned)MCOperand_getImm(Op) &
1323
7.30k
          0xFFF; // 12-bit SYMm
1324
7.30k
      unsigned Opcode = MCInst_getOpcode(MI);
1325
1326
7.30k
      if (Opcode == ARM_t2MSR_M &&
1327
5.67k
          ARM_getFeatureBits(MI->csh->mode, ARM_FeatureDSP)) {
1328
5.67k
        TheReg =
1329
5.67k
          ARMSysReg_lookupMClassSysRegBy12bitSYSmValue(
1330
5.67k
            SYSm);
1331
5.67k
        if (TheReg && MClassSysReg_isInRequiredFeatures(
1332
1.81k
                  TheReg, ARM_FeatureDSP)) {
1333
385
          ARM_set_detail_op_sysop(
1334
385
            MI, TheReg->sysreg.mclasssysreg,
1335
385
            ARM_OP_SYSREG, IsOutReg, Mask,
1336
385
            SYSm);
1337
385
          return;
1338
385
        }
1339
5.67k
      }
1340
1341
6.92k
      SYSm &= 0xff;
1342
6.92k
      if (Opcode == ARM_t2MSR_M &&
1343
5.29k
          ARM_getFeatureBits(MI->csh->mode, ARM_HasV7Ops)) {
1344
5.29k
        TheReg =
1345
5.29k
          ARMSysReg_lookupMClassSysRegAPSRNonDeprecated(
1346
5.29k
            SYSm);
1347
5.29k
        if (TheReg) {
1348
541
          ARM_set_detail_op_sysop(
1349
541
            MI, TheReg->sysreg.mclasssysreg,
1350
541
            ARM_OP_SYSREG, IsOutReg, Mask,
1351
541
            SYSm);
1352
541
          return;
1353
541
        }
1354
5.29k
      }
1355
1356
6.38k
      TheReg = ARMSysReg_lookupMClassSysRegBy8bitSYSmValue(
1357
6.38k
        SYSm);
1358
6.38k
      if (TheReg) {
1359
5.63k
        ARM_set_detail_op_sysop(
1360
5.63k
          MI, TheReg->sysreg.mclasssysreg,
1361
5.63k
          ARM_OP_SYSREG, IsOutReg, Mask, SYSm);
1362
5.63k
        return;
1363
5.63k
      }
1364
1365
745
      if (detail_is_set(MI))
1366
745
        MCOperand_CreateImm0(MI, SYSm);
1367
1368
745
      ARM_set_detail_op_sysop(MI, SYSm, ARM_OP_SYSREG,
1369
745
            IsOutReg, Mask, SYSm);
1370
1371
745
      return;
1372
6.38k
    }
1373
1374
2.09k
    if (!SpecRegRBit && (Mask == 8 || Mask == 4 || Mask == 12)) {
1375
907
      switch (Mask) {
1376
0
      default:
1377
0
        CS_ASSERT_RET(0 && "Unexpected mask value!");
1378
8
      case 4:
1379
8
        ARM_set_detail_op_sysop(MI,
1380
8
              ARM_MCLASSSYSREG_APSR_G,
1381
8
              ARM_OP_SYSREG, IsOutReg,
1382
8
              Mask, UINT16_MAX);
1383
8
        return;
1384
75
      case 8:
1385
75
        ARM_set_detail_op_sysop(
1386
75
          MI, ARM_MCLASSSYSREG_APSR_NZCVQ,
1387
75
          ARM_OP_SYSREG, IsOutReg, Mask,
1388
75
          UINT16_MAX);
1389
75
        return;
1390
824
      case 12:
1391
824
        ARM_set_detail_op_sysop(
1392
824
          MI, ARM_MCLASSSYSREG_APSR_NZCVQG,
1393
824
          ARM_OP_SYSREG, IsOutReg, Mask,
1394
824
          UINT16_MAX);
1395
824
        return;
1396
907
      }
1397
907
    }
1398
1399
1.19k
    unsigned field = 0;
1400
1.19k
    if (Mask) {
1401
621
      if (Mask & 8)
1402
519
        field += SpecRegRBit ? ARM_FIELD_SPSR_F :
1403
519
                   ARM_FIELD_CPSR_F;
1404
621
      if (Mask & 4)
1405
540
        field += SpecRegRBit ? ARM_FIELD_SPSR_S :
1406
540
                   ARM_FIELD_CPSR_S;
1407
621
      if (Mask & 2)
1408
214
        field += SpecRegRBit ? ARM_FIELD_SPSR_X :
1409
214
                   ARM_FIELD_CPSR_X;
1410
621
      if (Mask & 1)
1411
385
        field += SpecRegRBit ? ARM_FIELD_SPSR_C :
1412
385
                   ARM_FIELD_CPSR_C;
1413
1414
621
      ARM_set_detail_op_sysop(MI, field,
1415
621
            SpecRegRBit ? ARM_OP_SPSR :
1416
621
                    ARM_OP_CPSR,
1417
621
            IsOutReg, Mask, UINT16_MAX);
1418
621
    }
1419
1.19k
    break;
1420
2.09k
  }
1421
7.08k
  case ARM_OP_GROUP_SORegRegOperand: {
1422
7.08k
    int64_t imm =
1423
7.08k
      MCOperand_getImm(MCInst_getOperand(MI, OpNum + 2));
1424
7.08k
    ARM_get_detail_op(MI, 0)->shift.type =
1425
7.08k
      ARM_AM_getSORegShOp(imm) + ARM_SFT_REG;
1426
7.08k
    if (ARM_AM_getSORegShOp(imm) != ARM_AM_rrx)
1427
7.08k
      ARM_get_detail_op(MI, 0)->shift.value =
1428
7.08k
        MCInst_getOpVal(MI, OpNum + 1);
1429
1430
7.08k
    ARM_set_detail_op_reg(MI, OpNum, MCInst_getOpVal(MI, OpNum));
1431
7.08k
    break;
1432
2.09k
  }
1433
9.07k
  case ARM_OP_GROUP_ModImmOperand: {
1434
9.07k
    int64_t imm = MCInst_getOpVal(MI, OpNum);
1435
9.07k
    int32_t Rotated = t_mod_imm_rotate(imm);
1436
9.07k
    if (ARM_AM_getSOImmVal(Rotated) == imm) {
1437
6.57k
      ARM_set_detail_op_imm(MI, OpNum, ARM_OP_IMM,
1438
6.57k
                t_mod_imm_rotate(imm));
1439
6.57k
      return;
1440
6.57k
    }
1441
2.49k
    ARM_set_detail_op_imm(MI, OpNum, ARM_OP_IMM,
1442
2.49k
              t_mod_imm_bits(imm));
1443
2.49k
    ARM_set_detail_op_imm(MI, OpNum, ARM_OP_IMM,
1444
2.49k
              t_mod_imm_rot(imm));
1445
2.49k
    break;
1446
9.07k
  }
1447
4.43k
  case ARM_OP_GROUP_VMOVModImmOperand:
1448
4.43k
    ARM_set_detail_op_imm(
1449
4.43k
      MI, OpNum, ARM_OP_IMM,
1450
4.43k
      t_vmov_mod_imm(MCInst_getOpVal(MI, OpNum)));
1451
4.43k
    break;
1452
753
  case ARM_OP_GROUP_FPImmOperand:
1453
753
    ARM_set_detail_op_float(MI, OpNum, MCInst_getOpVal(MI, OpNum));
1454
753
    break;
1455
1.40k
  case ARM_OP_GROUP_ImmPlusOneOperand:
1456
1.40k
    ARM_set_detail_op_imm(MI, OpNum, ARM_OP_IMM,
1457
1.40k
              MCInst_getOpVal(MI, OpNum) + 1);
1458
1.40k
    break;
1459
1.21k
  case ARM_OP_GROUP_RotImmOperand: {
1460
1.21k
    unsigned RotImm = MCInst_getOpVal(MI, OpNum);
1461
1.21k
    if (RotImm == 0)
1462
196
      return;
1463
1.01k
    ARM_get_detail_op(MI, -1)->shift.type = ARM_SFT_ROR;
1464
1.01k
    ARM_get_detail_op(MI, -1)->shift.value = RotImm * 8;
1465
1.01k
    break;
1466
1.21k
  }
1467
1.48k
  case ARM_OP_GROUP_FBits16:
1468
1.48k
    ARM_set_detail_op_imm(MI, OpNum, ARM_OP_IMM,
1469
1.48k
              16 - MCInst_getOpVal(MI, OpNum));
1470
1.48k
    break;
1471
1.24k
  case ARM_OP_GROUP_FBits32:
1472
1.24k
    ARM_set_detail_op_imm(MI, OpNum, ARM_OP_IMM,
1473
1.24k
              32 - MCInst_getOpVal(MI, OpNum));
1474
1.24k
    break;
1475
3.00k
  case ARM_OP_GROUP_T2SOOperand:
1476
16.8k
  case ARM_OP_GROUP_SORegImmOperand:
1477
16.8k
    ARM_set_detail_op_reg(MI, OpNum, MCInst_getOpVal(MI, OpNum));
1478
16.8k
    uint64_t imm = MCInst_getOpVal(MI, OpNum + 1);
1479
16.8k
    ARM_AM_ShiftOpc ShOpc = ARM_AM_getSORegShOp(imm);
1480
16.8k
    unsigned ShImm = ARM_AM_getSORegOffset(imm);
1481
16.8k
    if (op_group == ARM_OP_GROUP_SORegImmOperand) {
1482
13.8k
      if (ShOpc == ARM_AM_no_shift ||
1483
13.8k
          (ShOpc == ARM_AM_lsl && !ShImm))
1484
0
        return;
1485
13.8k
    }
1486
16.8k
    add_cs_detail_RegImmShift(MI, ShOpc, ShImm);
1487
16.8k
    break;
1488
1.43k
  case ARM_OP_GROUP_PostIdxRegOperand: {
1489
1.43k
    bool sub = MCInst_getOpVal(MI, OpNum + 1) ? false : true;
1490
1.43k
    ARM_set_detail_op_mem_offset(MI, OpNum,
1491
1.43k
               MCInst_getOpVal(MI, OpNum), sub);
1492
1.43k
    ARM_get_detail(MI)->post_index = true;
1493
1.43k
    break;
1494
16.8k
  }
1495
1.49k
  case ARM_OP_GROUP_PostIdxImm8Operand: {
1496
1.49k
    unsigned Imm8 = MCInst_getOpVal(MI, OpNum);
1497
1.49k
    bool sub = !(Imm8 & 256);
1498
1.49k
    ARM_set_detail_op_mem_offset(MI, OpNum, (Imm8 & 0xff), sub);
1499
1.49k
    ARM_get_detail(MI)->post_index = true;
1500
1.49k
    break;
1501
16.8k
  }
1502
11.4k
  case ARM_OP_GROUP_PostIdxImm8s4Operand: {
1503
11.4k
    unsigned Imm8s = MCInst_getOpVal(MI, OpNum);
1504
11.4k
    bool sub = !(Imm8s & 256);
1505
11.4k
    ARM_set_detail_op_mem_offset(MI, OpNum, (Imm8s & 0xff) << 2,
1506
11.4k
               sub);
1507
11.4k
    ARM_get_detail(MI)->post_index = true;
1508
11.4k
    break;
1509
16.8k
  }
1510
73
  case ARM_OP_GROUP_AddrModeTBB:
1511
898
  case ARM_OP_GROUP_AddrModeTBH:
1512
898
    ARM_set_mem_access(MI, true);
1513
898
    ARM_set_detail_op_mem(MI, OpNum, false, 0,
1514
898
              MCInst_getOpVal(MI, OpNum));
1515
898
    ARM_set_detail_op_mem(MI, OpNum + 1, true, 1,
1516
898
              MCInst_getOpVal(MI, OpNum + 1));
1517
898
    if (op_group == ARM_OP_GROUP_AddrModeTBH) {
1518
825
      ARM_get_detail_op(MI, 0)->shift.type = ARM_SFT_LSL;
1519
825
      ARM_get_detail_op(MI, 0)->shift.value = 1;
1520
825
    }
1521
898
    ARM_set_mem_access(MI, false);
1522
898
    break;
1523
5.96k
  case ARM_OP_GROUP_AddrMode2Operand: {
1524
5.96k
    MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1525
5.96k
    if (!MCOperand_isReg(MO1))
1526
      // Handled in printOperand
1527
0
      break;
1528
1529
5.96k
    ARM_set_mem_access(MI, true);
1530
5.96k
    ARM_set_detail_op_mem(MI, OpNum, false, 0,
1531
5.96k
              MCInst_getOpVal(MI, OpNum));
1532
5.96k
    unsigned int imm3 = MCInst_getOpVal(MI, OpNum + 2);
1533
5.96k
    unsigned ShOff = ARM_AM_getAM2Offset(imm3);
1534
5.96k
    ARM_AM_AddrOpc subtracted = ARM_AM_getAM2Op(imm3);
1535
5.96k
    if (!MCOperand_getReg(MCInst_getOperand(MI, OpNum + 1)) &&
1536
0
        ShOff) {
1537
0
      ARM_get_detail_op(MI, 0)->shift.value = ShOff;
1538
0
      ARM_get_detail_op(MI, 0)->subtracted = subtracted ==
1539
0
                     ARM_AM_sub;
1540
0
      ARM_set_mem_access(MI, false);
1541
0
      break;
1542
0
    }
1543
5.96k
    ARM_set_detail_op_mem(MI, OpNum + 1, true,
1544
5.96k
              subtracted == ARM_AM_sub ? -1 : 1,
1545
5.96k
              MCInst_getOpVal(MI, OpNum + 1));
1546
5.96k
    add_cs_detail_RegImmShift(MI, ARM_AM_getAM2ShiftOpc(imm3),
1547
5.96k
            ARM_AM_getAM2Offset(imm3));
1548
5.96k
    ARM_set_mem_access(MI, false);
1549
5.96k
    break;
1550
5.96k
  }
1551
11.1k
  case ARM_OP_GROUP_AddrMode2OffsetOperand: {
1552
11.1k
    uint64_t imm2 = MCInst_getOpVal(MI, OpNum + 1);
1553
11.1k
    ARM_AM_AddrOpc subtracted = ARM_AM_getAM2Op(imm2);
1554
11.1k
    if (!MCInst_getOpVal(MI, OpNum)) {
1555
7.12k
      ARM_set_detail_op_mem_offset(MI, OpNum + 1,
1556
7.12k
                 ARM_AM_getAM2Offset(imm2),
1557
7.12k
                 subtracted == ARM_AM_sub);
1558
7.12k
      ARM_get_detail(MI)->post_index = true;
1559
7.12k
      return;
1560
7.12k
    }
1561
4.02k
    ARM_set_detail_op_mem_offset(MI, OpNum,
1562
4.02k
               MCInst_getOpVal(MI, OpNum),
1563
4.02k
               subtracted == ARM_AM_sub);
1564
4.02k
    ARM_get_detail(MI)->post_index = true;
1565
4.02k
    add_cs_detail_RegImmShift(MI, ARM_AM_getAM2ShiftOpc(imm2),
1566
4.02k
            ARM_AM_getAM2Offset(imm2));
1567
4.02k
    break;
1568
11.1k
  }
1569
4.78k
  case ARM_OP_GROUP_AddrMode3OffsetOperand: {
1570
4.78k
    MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1571
4.78k
    MCOperand *MO2 = MCInst_getOperand(MI, OpNum + 1);
1572
4.78k
    ARM_AM_AddrOpc subtracted =
1573
4.78k
      ARM_AM_getAM3Op(MCOperand_getImm(MO2));
1574
4.78k
    if (MCOperand_getReg(MO1)) {
1575
3.24k
      ARM_set_detail_op_mem_offset(MI, OpNum,
1576
3.24k
                 MCInst_getOpVal(MI, OpNum),
1577
3.24k
                 subtracted == ARM_AM_sub);
1578
3.24k
      ARM_get_detail(MI)->post_index = true;
1579
3.24k
      return;
1580
3.24k
    }
1581
1.54k
    ARM_set_detail_op_mem_offset(
1582
1.54k
      MI, OpNum + 1,
1583
1.54k
      ARM_AM_getAM3Offset(MCInst_getOpVal(MI, OpNum + 1)),
1584
1.54k
      subtracted == ARM_AM_sub);
1585
1.54k
    ARM_get_detail(MI)->post_index = true;
1586
1.54k
    break;
1587
4.78k
  }
1588
31.7k
  case ARM_OP_GROUP_ThumbAddrModeSPOperand:
1589
73.9k
  case ARM_OP_GROUP_ThumbAddrModeImm5S1Operand:
1590
127k
  case ARM_OP_GROUP_ThumbAddrModeImm5S2Operand:
1591
181k
  case ARM_OP_GROUP_ThumbAddrModeImm5S4Operand: {
1592
181k
    MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1593
181k
    if (!MCOperand_isReg(MO1))
1594
      // Handled in printOperand
1595
0
      break;
1596
1597
181k
    ARM_set_mem_access(MI, true);
1598
181k
    ARM_set_detail_op_mem(MI, OpNum, false, 0,
1599
181k
              MCInst_getOpVal(MI, OpNum));
1600
181k
    unsigned ImmOffs = MCInst_getOpVal(MI, OpNum + 1);
1601
181k
    if (ImmOffs) {
1602
169k
      unsigned Scale = 0;
1603
169k
      switch (op_group) {
1604
0
      default:
1605
0
        CS_ASSERT_RET(
1606
0
          0 &&
1607
0
          "Cannot determine scale. Operand group not handled.");
1608
36.3k
      case ARM_OP_GROUP_ThumbAddrModeImm5S1Operand:
1609
36.3k
        Scale = 1;
1610
36.3k
        break;
1611
50.9k
      case ARM_OP_GROUP_ThumbAddrModeImm5S2Operand:
1612
50.9k
        Scale = 2;
1613
50.9k
        break;
1614
53.0k
      case ARM_OP_GROUP_ThumbAddrModeImm5S4Operand:
1615
82.4k
      case ARM_OP_GROUP_ThumbAddrModeSPOperand:
1616
82.4k
        Scale = 4;
1617
82.4k
        break;
1618
169k
      }
1619
169k
      ARM_set_detail_op_mem(MI, OpNum + 1, false, 0,
1620
169k
                ImmOffs * Scale);
1621
169k
    }
1622
181k
    ARM_set_mem_access(MI, false);
1623
181k
    break;
1624
181k
  }
1625
29.4k
  case ARM_OP_GROUP_ThumbAddrModeRROperand: {
1626
29.4k
    MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1627
29.4k
    if (!MCOperand_isReg(MO1))
1628
      // Handled in printOperand
1629
0
      break;
1630
1631
29.4k
    ARM_set_mem_access(MI, true);
1632
29.4k
    ARM_set_detail_op_mem(MI, OpNum, false, 0,
1633
29.4k
              MCInst_getOpVal(MI, OpNum));
1634
29.4k
    arm_reg RegNum = MCInst_getOpVal(MI, OpNum + 1);
1635
29.4k
    if (RegNum)
1636
29.4k
      ARM_set_detail_op_mem(MI, OpNum + 1, true, 1, RegNum);
1637
29.4k
    ARM_set_mem_access(MI, false);
1638
29.4k
    break;
1639
29.4k
  }
1640
3.11k
  case ARM_OP_GROUP_T2AddrModeImm8OffsetOperand:
1641
5.32k
  case ARM_OP_GROUP_T2AddrModeImm8s4OffsetOperand: {
1642
5.32k
    int32_t OffImm = MCInst_getOpVal(MI, OpNum);
1643
5.32k
    if (OffImm == INT32_MIN)
1644
1.44k
      ARM_set_detail_op_mem_offset(MI, OpNum, 0, false);
1645
3.87k
    else {
1646
3.87k
      bool sub = OffImm < 0;
1647
3.87k
      OffImm = OffImm < 0 ? OffImm * -1 : OffImm;
1648
3.87k
      ARM_set_detail_op_mem_offset(MI, OpNum, OffImm, sub);
1649
3.87k
    }
1650
5.32k
    ARM_get_detail(MI)->post_index = true;
1651
5.32k
    break;
1652
3.11k
  }
1653
1.67k
  case ARM_OP_GROUP_T2AddrModeSoRegOperand: {
1654
1.67k
    if (!doing_mem(MI))
1655
1.67k
      ARM_set_mem_access(MI, true);
1656
1657
1.67k
    ARM_set_detail_op_mem(MI, OpNum, false, 0,
1658
1.67k
              MCInst_getOpVal(MI, OpNum));
1659
1.67k
    ARM_set_detail_op_mem(MI, OpNum + 1, true, 1,
1660
1.67k
              MCInst_getOpVal(MI, OpNum + 1));
1661
1.67k
    unsigned ShAmt = MCInst_getOpVal(MI, OpNum + 2);
1662
1.67k
    if (ShAmt) {
1663
487
      ARM_get_detail_op(MI, 0)->shift.type = ARM_SFT_LSL;
1664
487
      ARM_get_detail_op(MI, 0)->shift.value = ShAmt;
1665
487
    }
1666
1.67k
    ARM_set_mem_access(MI, false);
1667
1.67k
    break;
1668
3.11k
  }
1669
1.04k
  case ARM_OP_GROUP_T2AddrModeImm0_1020s4Operand:
1670
1.04k
    ARM_set_mem_access(MI, true);
1671
1.04k
    ARM_set_detail_op_mem(MI, OpNum, false, 0,
1672
1.04k
              MCInst_getOpVal(MI, OpNum));
1673
1.04k
    int64_t Imm0_1024s4 = MCInst_getOpVal(MI, OpNum + 1);
1674
1.04k
    if (Imm0_1024s4)
1675
871
      ARM_set_detail_op_mem(MI, OpNum + 1, false, 0,
1676
871
                Imm0_1024s4 * 4);
1677
1.04k
    ARM_set_mem_access(MI, false);
1678
1.04k
    break;
1679
1.10k
  case ARM_OP_GROUP_PKHLSLShiftImm: {
1680
1.10k
    unsigned ShiftImm = MCInst_getOpVal(MI, OpNum);
1681
1.10k
    if (ShiftImm == 0)
1682
274
      return;
1683
827
    ARM_get_detail_op(MI, -1)->shift.type = ARM_SFT_LSL;
1684
827
    ARM_get_detail_op(MI, -1)->shift.value = ShiftImm;
1685
827
    break;
1686
1.10k
  }
1687
823
  case ARM_OP_GROUP_PKHASRShiftImm: {
1688
823
    unsigned RShiftImm = MCInst_getOpVal(MI, OpNum);
1689
823
    if (RShiftImm == 0)
1690
216
      RShiftImm = 32;
1691
823
    ARM_get_detail_op(MI, -1)->shift.type = ARM_SFT_ASR;
1692
823
    ARM_get_detail_op(MI, -1)->shift.value = RShiftImm;
1693
823
    break;
1694
1.10k
  }
1695
19.8k
  case ARM_OP_GROUP_ThumbS4ImmOperand:
1696
19.8k
    ARM_set_detail_op_imm(MI, OpNum, ARM_OP_IMM,
1697
19.8k
              MCInst_getOpVal(MI, OpNum) * 4);
1698
19.8k
    break;
1699
58.2k
  case ARM_OP_GROUP_ThumbSRImm: {
1700
58.2k
    unsigned SRImm = MCInst_getOpVal(MI, OpNum);
1701
58.2k
    ARM_set_detail_op_imm(MI, OpNum, ARM_OP_IMM,
1702
58.2k
              SRImm == 0 ? 32 : SRImm);
1703
58.2k
    break;
1704
1.10k
  }
1705
1.12k
  case ARM_OP_GROUP_BitfieldInvMaskImmOperand: {
1706
1.12k
    uint32_t v = ~MCInst_getOpVal(MI, OpNum);
1707
1.12k
    int32_t lsb = CountTrailingZeros_32(v);
1708
1.12k
    int32_t width = (32 - countLeadingZeros(v)) - lsb;
1709
1.12k
    ARM_set_detail_op_imm(MI, OpNum, ARM_OP_IMM, lsb);
1710
1.12k
    ARM_set_detail_op_imm(MI, OpNum, ARM_OP_IMM, width);
1711
1.12k
    break;
1712
1.10k
  }
1713
1.13k
  case ARM_OP_GROUP_CPSIMod: {
1714
1.13k
    unsigned Mode = MCInst_getOpVal(MI, OpNum);
1715
1.13k
    ARM_get_detail(MI)->cps_mode = Mode;
1716
1.13k
    break;
1717
1.10k
  }
1718
1.13k
  case ARM_OP_GROUP_CPSIFlag: {
1719
1.13k
    unsigned IFlags = MCInst_getOpVal(MI, OpNum);
1720
1.13k
    ARM_get_detail(MI)->cps_flag = IFlags == 0 ? ARM_CPSFLAG_NONE :
1721
1.13k
                   IFlags;
1722
1.13k
    break;
1723
1.10k
  }
1724
1.62k
  case ARM_OP_GROUP_GPRPairOperand: {
1725
1.62k
    unsigned Reg = MCInst_getOpVal(MI, OpNum);
1726
1.62k
    ARM_set_detail_op_reg(MI, OpNum,
1727
1.62k
              MCRegisterInfo_getSubReg(MI->MRI, Reg,
1728
1.62k
                     ARM_gsub_0));
1729
1.62k
    ARM_set_detail_op_reg(MI, OpNum,
1730
1.62k
              MCRegisterInfo_getSubReg(MI->MRI, Reg,
1731
1.62k
                     ARM_gsub_1));
1732
1.62k
    break;
1733
1.10k
  }
1734
1.81k
  case ARM_OP_GROUP_MemBOption:
1735
2.89k
  case ARM_OP_GROUP_InstSyncBOption:
1736
2.89k
  case ARM_OP_GROUP_TraceSyncBOption:
1737
2.89k
    ARM_get_detail(MI)->mem_barrier = MCInst_getOpVal(MI, OpNum);
1738
2.89k
    break;
1739
1.67k
  case ARM_OP_GROUP_ShiftImmOperand: {
1740
1.67k
    unsigned ShiftOp = MCInst_getOpVal(MI, OpNum);
1741
1.67k
    bool isASR = (ShiftOp & (1 << 5)) != 0;
1742
1.67k
    unsigned Amt = ShiftOp & 0x1f;
1743
1.67k
    if (isASR) {
1744
553
      unsigned tmp = Amt == 0 ? 32 : Amt;
1745
553
      ARM_get_detail_op(MI, -1)->shift.type = ARM_SFT_ASR;
1746
553
      ARM_get_detail_op(MI, -1)->shift.value = tmp;
1747
1.11k
    } else if (Amt) {
1748
866
      ARM_get_detail_op(MI, -1)->shift.type = ARM_SFT_LSL;
1749
866
      ARM_get_detail_op(MI, -1)->shift.value = Amt;
1750
866
    }
1751
1.67k
    break;
1752
2.89k
  }
1753
5.78k
  case ARM_OP_GROUP_VectorIndex:
1754
5.78k
    ARM_get_detail_op(MI, -1)->vector_index =
1755
5.78k
      MCInst_getOpVal(MI, OpNum);
1756
5.78k
    break;
1757
4.90k
  case ARM_OP_GROUP_CoprocOptionImm:
1758
4.90k
    ARM_set_detail_op_imm(MI, OpNum, ARM_OP_IMM,
1759
4.90k
              MCInst_getOpVal(MI, OpNum));
1760
4.90k
    break;
1761
27.7k
  case ARM_OP_GROUP_ThumbLdrLabelOperand: {
1762
27.7k
    int32_t OffImm = MCInst_getOpVal(MI, OpNum);
1763
27.7k
    if (OffImm == INT32_MIN)
1764
1.01k
      OffImm = 0;
1765
27.7k
    ARM_check_safe_inc(MI);
1766
27.7k
    ARM_get_detail_op(MI, 0)->type = ARM_OP_MEM;
1767
27.7k
    ARM_get_detail_op(MI, 0)->mem.base = ARM_REG_PC;
1768
27.7k
    ARM_get_detail_op(MI, 0)->mem.index = ARM_REG_INVALID;
1769
27.7k
    ARM_get_detail_op(MI, 0)->mem.scale = 1;
1770
27.7k
    ARM_get_detail_op(MI, 0)->mem.disp = OffImm;
1771
27.7k
    ARM_get_detail_op(MI, 0)->access = CS_AC_READ;
1772
27.7k
    ARM_inc_op_count(MI);
1773
27.7k
    break;
1774
2.89k
  }
1775
854
  case ARM_OP_GROUP_BankedRegOperand: {
1776
854
    uint32_t Banked = MCInst_getOpVal(MI, OpNum);
1777
854
    const ARMBankedReg_BankedReg *TheReg =
1778
854
      ARMBankedReg_lookupBankedRegByEncoding(Banked);
1779
854
    bool IsOutReg = OpNum == 0;
1780
854
    ARM_set_detail_op_sysop(MI, TheReg->sysreg.bankedreg,
1781
854
          ARM_OP_BANKEDREG, IsOutReg, UINT8_MAX,
1782
854
          TheReg->Encoding &
1783
854
            0xf); // Bit[4:0] are SYSm
1784
854
    break;
1785
2.89k
  }
1786
154
  case ARM_OP_GROUP_SetendOperand: {
1787
154
    bool be = MCInst_getOpVal(MI, OpNum) != 0;
1788
154
    ARM_check_safe_inc(MI);
1789
154
    if (be) {
1790
140
      ARM_get_detail_op(MI, 0)->type = ARM_OP_SETEND;
1791
140
      ARM_get_detail_op(MI, 0)->setend = ARM_SETEND_BE;
1792
140
    } else {
1793
14
      ARM_get_detail_op(MI, 0)->type = ARM_OP_SETEND;
1794
14
      ARM_get_detail_op(MI, 0)->setend = ARM_SETEND_LE;
1795
14
    }
1796
154
    ARM_inc_op_count(MI);
1797
154
    break;
1798
2.89k
  }
1799
0
  case ARM_OP_GROUP_MveSaturateOp: {
1800
0
    uint32_t Val = MCInst_getOpVal(MI, OpNum);
1801
0
    Val = Val == 1 ? 48 : 64;
1802
0
    ARM_set_detail_op_imm(MI, OpNum, ARM_OP_IMM, Val);
1803
0
    break;
1804
2.89k
  }
1805
4.61M
  }
1806
4.61M
}
1807
1808
/// Fills cs_detail with the data of the operand.
1809
/// This function handles operands which original printer function is a template
1810
/// with one argument.
1811
static void add_cs_detail_template_1(MCInst *MI, arm_op_group op_group,
1812
             unsigned OpNum, uint64_t temp_arg_0)
1813
91.7k
{
1814
91.7k
  if (!detail_is_set(MI))
1815
0
    return;
1816
91.7k
  switch (op_group) {
1817
0
  default:
1818
0
    printf("ERROR: Operand group %d not handled!\n", op_group);
1819
0
    CS_ASSERT_RET(0);
1820
6.27k
  case ARM_OP_GROUP_AddrModeImm12Operand_0:
1821
10.7k
  case ARM_OP_GROUP_AddrModeImm12Operand_1:
1822
12.5k
  case ARM_OP_GROUP_T2AddrModeImm8s4Operand_0:
1823
22.3k
  case ARM_OP_GROUP_T2AddrModeImm8s4Operand_1: {
1824
22.3k
    MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1825
22.3k
    if (!MCOperand_isReg(MO1))
1826
      // Handled in printOperand
1827
0
      return;
1828
22.3k
  }
1829
  // fallthrough
1830
30.8k
  case ARM_OP_GROUP_T2AddrModeImm8Operand_0:
1831
34.2k
  case ARM_OP_GROUP_T2AddrModeImm8Operand_1: {
1832
34.2k
    bool AlwaysPrintImm0 = temp_arg_0;
1833
34.2k
    ARM_set_mem_access(MI, true);
1834
34.2k
    ARM_set_detail_op_mem(MI, OpNum, false, 0,
1835
34.2k
              MCInst_getOpVal(MI, OpNum));
1836
34.2k
    int32_t Imm8 = MCInst_getOpVal(MI, OpNum + 1);
1837
34.2k
    if (Imm8 == INT32_MIN)
1838
6.98k
      Imm8 = 0;
1839
34.2k
    ARM_set_detail_op_mem(MI, OpNum + 1, false, 0, Imm8);
1840
34.2k
    if (AlwaysPrintImm0)
1841
17.6k
      map_add_implicit_write(MI, MCInst_getOpVal(MI, OpNum));
1842
1843
34.2k
    ARM_set_mem_access(MI, false);
1844
34.2k
    break;
1845
30.8k
  }
1846
429
  case ARM_OP_GROUP_AdrLabelOperand_0:
1847
22.1k
  case ARM_OP_GROUP_AdrLabelOperand_2: {
1848
22.1k
    unsigned Scale = temp_arg_0;
1849
22.1k
    int32_t OffImm = MCInst_getOpVal(MI, OpNum) << Scale;
1850
22.1k
    if (OffImm == INT32_MIN)
1851
0
      OffImm = 0;
1852
22.1k
    ARM_set_detail_op_imm(MI, OpNum, ARM_OP_IMM, OffImm);
1853
22.1k
    break;
1854
429
  }
1855
3.30k
  case ARM_OP_GROUP_AddrMode3Operand_0:
1856
5.35k
  case ARM_OP_GROUP_AddrMode3Operand_1: {
1857
5.35k
    bool AlwaysPrintImm0 = temp_arg_0;
1858
5.35k
    MCOperand *MO1 = MCInst_getOperand(MI, OpNum);
1859
5.35k
    if (!MCOperand_isReg(MO1))
1860
      // Handled in printOperand
1861
0
      break;
1862
1863
5.35k
    ARM_set_mem_access(MI, true);
1864
5.35k
    ARM_set_detail_op_mem(MI, OpNum, false, 0,
1865
5.35k
              MCInst_getOpVal(MI, OpNum));
1866
1867
5.35k
    MCOperand *MO2 = MCInst_getOperand(MI, OpNum + 1);
1868
5.35k
    ARM_AM_AddrOpc Sign =
1869
5.35k
      ARM_AM_getAM3Op(MCInst_getOpVal(MI, OpNum + 2));
1870
1871
5.35k
    if (MCOperand_getReg(MO2)) {
1872
2.56k
      ARM_set_detail_op_mem(MI, OpNum + 1, true,
1873
2.56k
                Sign == ARM_AM_sub ? -1 : 1,
1874
2.56k
                MCInst_getOpVal(MI, OpNum + 1));
1875
2.56k
      ARM_get_detail_op(MI, 0)->subtracted = Sign ==
1876
2.56k
                     ARM_AM_sub;
1877
2.56k
      ARM_set_mem_access(MI, false);
1878
2.56k
      break;
1879
2.56k
    }
1880
2.78k
    unsigned ImmOffs =
1881
2.78k
      ARM_AM_getAM3Offset(MCInst_getOpVal(MI, OpNum + 2));
1882
1883
2.78k
    if (AlwaysPrintImm0 || ImmOffs || Sign == ARM_AM_sub) {
1884
2.65k
      ARM_set_detail_op_mem(MI, OpNum + 2, false, 0, ImmOffs);
1885
2.65k
      ARM_get_detail_op(MI, 0)->subtracted = Sign ==
1886
2.65k
                     ARM_AM_sub;
1887
2.65k
    }
1888
2.78k
    ARM_set_mem_access(MI, false);
1889
2.78k
    break;
1890
5.35k
  }
1891
10.8k
  case ARM_OP_GROUP_AddrMode5Operand_0:
1892
25.3k
  case ARM_OP_GROUP_AddrMode5Operand_1:
1893
25.8k
  case ARM_OP_GROUP_AddrMode5FP16Operand_0: {
1894
25.8k
    bool AlwaysPrintImm0 = temp_arg_0;
1895
1896
25.8k
    if (AlwaysPrintImm0) {
1897
14.4k
      get_detail(MI)->writeback = true;
1898
14.4k
      map_add_implicit_write(MI, MCInst_getOpVal(MI, OpNum));
1899
14.4k
    }
1900
1901
25.8k
    ARM_check_safe_inc(MI);
1902
25.8k
    cs_arm_op *Op = ARM_get_detail_op(MI, 0);
1903
25.8k
    Op->type = ARM_OP_MEM;
1904
25.8k
    Op->mem.base = MCInst_getOpVal(MI, OpNum);
1905
25.8k
    Op->mem.index = ARM_REG_INVALID;
1906
25.8k
    Op->mem.scale = 1;
1907
25.8k
    Op->mem.disp = 0;
1908
25.8k
    Op->access = CS_AC_READ;
1909
1910
25.8k
    ARM_AM_AddrOpc SubFlag =
1911
25.8k
      ARM_AM_getAM5Op(MCInst_getOpVal(MI, OpNum + 1));
1912
25.8k
    unsigned ImmOffs =
1913
25.8k
      ARM_AM_getAM5Offset(MCInst_getOpVal(MI, OpNum + 1));
1914
1915
25.8k
    if (AlwaysPrintImm0 || ImmOffs || SubFlag == ARM_AM_sub) {
1916
25.2k
      if (op_group == ARM_OP_GROUP_AddrMode5FP16Operand_0) {
1917
384
        Op->mem.disp = ImmOffs * 2;
1918
24.8k
      } else {
1919
24.8k
        Op->mem.disp = ImmOffs * 4;
1920
24.8k
      }
1921
25.2k
      Op->subtracted = SubFlag == ARM_AM_sub;
1922
25.2k
    }
1923
25.8k
    ARM_inc_op_count(MI);
1924
25.8k
    break;
1925
25.3k
  }
1926
221
  case ARM_OP_GROUP_MveAddrModeRQOperand_0:
1927
294
  case ARM_OP_GROUP_MveAddrModeRQOperand_1:
1928
369
  case ARM_OP_GROUP_MveAddrModeRQOperand_2:
1929
462
  case ARM_OP_GROUP_MveAddrModeRQOperand_3: {
1930
462
    unsigned Shift = temp_arg_0;
1931
462
    ARM_set_mem_access(MI, true);
1932
462
    ARM_set_detail_op_mem(MI, OpNum, false, 0,
1933
462
              MCInst_getOpVal(MI, OpNum));
1934
462
    ARM_set_detail_op_mem(MI, OpNum + 1, true, 1,
1935
462
              MCInst_getOpVal(MI, OpNum + 1));
1936
462
    if (Shift > 0) {
1937
241
      add_cs_detail_RegImmShift(MI, ARM_AM_uxtw, Shift);
1938
241
    }
1939
462
    ARM_set_mem_access(MI, false);
1940
462
    break;
1941
369
  }
1942
1.81k
  case ARM_OP_GROUP_MVEVectorList_2:
1943
3.69k
  case ARM_OP_GROUP_MVEVectorList_4: {
1944
3.69k
    unsigned NumRegs = temp_arg_0;
1945
3.69k
    arm_reg Reg = MCInst_getOpVal(MI, OpNum);
1946
14.8k
    for (unsigned i = 0; i < NumRegs; ++i) {
1947
11.1k
      arm_reg SubReg = MCRegisterInfo_getSubReg(
1948
11.1k
        MI->MRI, Reg, ARM_qsub_0 + i);
1949
11.1k
      ARM_set_detail_op_reg(MI, OpNum, SubReg);
1950
11.1k
    }
1951
3.69k
    break;
1952
1.81k
  }
1953
91.7k
  }
1954
91.7k
}
1955
1956
/// Fills cs_detail with the data of the operand.
1957
/// This function handles operands which's original printer function is a
1958
/// template with two arguments.
1959
static void add_cs_detail_template_2(MCInst *MI, arm_op_group op_group,
1960
             unsigned OpNum, uint64_t temp_arg_0,
1961
             uint64_t temp_arg_1)
1962
2.95k
{
1963
2.95k
  if (!detail_is_set(MI))
1964
0
    return;
1965
2.95k
  switch (op_group) {
1966
0
  default:
1967
0
    printf("ERROR: Operand group %d not handled!\n", op_group);
1968
0
    CS_ASSERT_RET(0);
1969
1.61k
  case ARM_OP_GROUP_ComplexRotationOp_90_0:
1970
2.95k
  case ARM_OP_GROUP_ComplexRotationOp_180_90: {
1971
2.95k
    unsigned Angle = temp_arg_0;
1972
2.95k
    unsigned Remainder = temp_arg_1;
1973
2.95k
    unsigned Rotation =
1974
2.95k
      (MCInst_getOpVal(MI, OpNum) * Angle) + Remainder;
1975
2.95k
    ARM_set_detail_op_imm(MI, OpNum, ARM_OP_IMM, Rotation);
1976
2.95k
    break;
1977
1.61k
  }
1978
2.95k
  }
1979
2.95k
}
1980
1981
/// Fills cs_detail with the data of the operand.
1982
/// Calls to this function are should not be added by hand! Please checkout the
1983
/// patch `AddCSDetail` of the CppTranslator.
1984
static void ARM_add_cs_detail(MCInst *MI, int /* arm_op_group */ op_group,
1985
            size_t op_num, uint64_t templ_arg_0,
1986
            uint64_t templ_arg_1)
1987
4.73M
{
1988
4.73M
  if (!detail_is_set(MI) || !map_fill_detail_ops(MI))
1989
0
    return;
1990
4.73M
  switch (op_group) {
1991
27.0k
  case ARM_OP_GROUP_RegImmShift: {
1992
27.0k
    ARM_AM_ShiftOpc shift_opc = (ARM_AM_ShiftOpc)templ_arg_0;
1993
27.0k
    unsigned shift_imm = templ_arg_1;
1994
27.0k
    add_cs_detail_RegImmShift(MI, shift_opc, shift_imm);
1995
27.0k
    return;
1996
0
  }
1997
429
  case ARM_OP_GROUP_AdrLabelOperand_0:
1998
22.1k
  case ARM_OP_GROUP_AdrLabelOperand_2:
1999
25.4k
  case ARM_OP_GROUP_AddrMode3Operand_0:
2000
27.5k
  case ARM_OP_GROUP_AddrMode3Operand_1:
2001
38.3k
  case ARM_OP_GROUP_AddrMode5Operand_0:
2002
52.8k
  case ARM_OP_GROUP_AddrMode5Operand_1:
2003
59.1k
  case ARM_OP_GROUP_AddrModeImm12Operand_0:
2004
63.6k
  case ARM_OP_GROUP_AddrModeImm12Operand_1:
2005
72.1k
  case ARM_OP_GROUP_T2AddrModeImm8Operand_0:
2006
75.5k
  case ARM_OP_GROUP_T2AddrModeImm8Operand_1:
2007
77.3k
  case ARM_OP_GROUP_T2AddrModeImm8s4Operand_0:
2008
87.0k
  case ARM_OP_GROUP_T2AddrModeImm8s4Operand_1:
2009
88.8k
  case ARM_OP_GROUP_MVEVectorList_2:
2010
90.7k
  case ARM_OP_GROUP_MVEVectorList_4:
2011
91.2k
  case ARM_OP_GROUP_AddrMode5FP16Operand_0:
2012
91.4k
  case ARM_OP_GROUP_MveAddrModeRQOperand_0:
2013
91.5k
  case ARM_OP_GROUP_MveAddrModeRQOperand_3:
2014
91.6k
  case ARM_OP_GROUP_MveAddrModeRQOperand_1:
2015
91.7k
  case ARM_OP_GROUP_MveAddrModeRQOperand_2: {
2016
91.7k
    add_cs_detail_template_1(MI, op_group, op_num, templ_arg_0);
2017
91.7k
    return;
2018
91.6k
  }
2019
1.34k
  case ARM_OP_GROUP_ComplexRotationOp_180_90:
2020
2.95k
  case ARM_OP_GROUP_ComplexRotationOp_90_0: {
2021
2.95k
    add_cs_detail_template_2(MI, op_group, op_num, templ_arg_0,
2022
2.95k
           templ_arg_1);
2023
2.95k
    return;
2024
1.34k
  }
2025
4.73M
  }
2026
4.61M
  add_cs_detail_general(MI, op_group, op_num);
2027
4.61M
}
2028
2029
void ARM_add_cs_detail_0(MCInst *MI, int /* arm_op_group */ op_group,
2030
       size_t op_num)
2031
4.61M
{
2032
4.61M
  ARM_add_cs_detail(MI, op_group, op_num, 0, 0);
2033
4.61M
}
2034
2035
void ARM_add_cs_detail_1(MCInst *MI, int /* arm_op_group */ op_group,
2036
       size_t op_num, uint64_t templ_arg_0)
2037
91.7k
{
2038
91.7k
  ARM_add_cs_detail(MI, op_group, op_num, templ_arg_0, 0);
2039
91.7k
}
2040
2041
void ARM_add_cs_detail_2(MCInst *MI, int /* arm_op_group */ op_group,
2042
       size_t op_num, uint64_t templ_arg_0,
2043
       uint64_t templ_arg_1)
2044
30.0k
{
2045
30.0k
  ARM_add_cs_detail(MI, op_group, op_num, templ_arg_0, templ_arg_1);
2046
30.0k
}
2047
2048
static void insert_op(MCInst *MI, unsigned index, cs_arm_op op)
2049
20.0k
{
2050
20.0k
  if (!detail_is_set(MI)) {
2051
0
    return;
2052
0
  }
2053
20.0k
  ARM_check_safe_inc(MI);
2054
2055
20.0k
  cs_arm_op *ops = ARM_get_detail(MI)->operands;
2056
20.0k
  int i = ARM_get_detail(MI)->op_count;
2057
20.0k
  if (index == -1) {
2058
3.21k
    ops[i] = op;
2059
3.21k
    ARM_inc_op_count(MI);
2060
3.21k
    return;
2061
3.21k
  }
2062
21.6k
  for (; i > 0 && i > index; --i) {
2063
4.76k
    ops[i] = ops[i - 1];
2064
4.76k
  }
2065
16.8k
  ops[index] = op;
2066
16.8k
  ARM_inc_op_count(MI);
2067
16.8k
}
2068
2069
/// Inserts a register to the detail operands at @index.
2070
/// Already present operands are moved.
2071
/// If @index is -1 the operand is appended.
2072
void ARM_insert_detail_op_reg_at(MCInst *MI, unsigned index, arm_reg Reg,
2073
         cs_ac_type access)
2074
8.32k
{
2075
8.32k
  if (!detail_is_set(MI))
2076
0
    return;
2077
2078
8.32k
  cs_arm_op op;
2079
8.32k
  ARM_setup_op(&op);
2080
8.32k
  op.type = ARM_OP_REG;
2081
8.32k
  op.reg = Reg;
2082
8.32k
  op.access = access;
2083
8.32k
  insert_op(MI, index, op);
2084
8.32k
}
2085
2086
/// Inserts a immediate to the detail operands at @index.
2087
/// Already present operands are moved.
2088
/// If @index is -1 the operand is appended.
2089
void ARM_insert_detail_op_imm_at(MCInst *MI, unsigned index, int64_t Val,
2090
         cs_ac_type access)
2091
11.7k
{
2092
11.7k
  if (!detail_is_set(MI))
2093
0
    return;
2094
11.7k
  ARM_check_safe_inc(MI);
2095
2096
11.7k
  cs_arm_op op;
2097
11.7k
  ARM_setup_op(&op);
2098
11.7k
  op.type = ARM_OP_IMM;
2099
11.7k
  op.imm = Val;
2100
11.7k
  op.access = access;
2101
2102
11.7k
  insert_op(MI, index, op);
2103
11.7k
}
2104
2105
/// Adds a register ARM operand at position OpNum and increases the op_count by
2106
/// one.
2107
void ARM_set_detail_op_reg(MCInst *MI, unsigned OpNum, arm_reg Reg)
2108
1.83M
{
2109
1.83M
  if (!detail_is_set(MI))
2110
0
    return;
2111
1.83M
  ARM_check_safe_inc(MI);
2112
1.83M
  CS_ASSERT_RET(!(map_get_op_type(MI, OpNum) & CS_OP_MEM));
2113
1.83M
  CS_ASSERT_RET(map_get_op_type(MI, OpNum) == CS_OP_REG);
2114
2115
1.83M
  ARM_get_detail_op(MI, 0)->type = ARM_OP_REG;
2116
1.83M
  ARM_get_detail_op(MI, 0)->reg = Reg;
2117
1.83M
  ARM_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
2118
1.83M
  ARM_inc_op_count(MI);
2119
1.83M
}
2120
2121
/// Adds an immediate ARM operand at position OpNum and increases the op_count
2122
/// by one.
2123
void ARM_set_detail_op_imm(MCInst *MI, unsigned OpNum, arm_op_type ImmType,
2124
         int64_t Imm)
2125
848k
{
2126
848k
  if (!detail_is_set(MI))
2127
0
    return;
2128
848k
  ARM_check_safe_inc(MI);
2129
848k
  CS_ASSERT_RET(!(map_get_op_type(MI, OpNum) & CS_OP_MEM));
2130
848k
  CS_ASSERT_RET(map_get_op_type(MI, OpNum) == CS_OP_IMM);
2131
848k
  CS_ASSERT_RET(ImmType == ARM_OP_IMM || ImmType == ARM_OP_PIMM ||
2132
848k
          ImmType == ARM_OP_CIMM);
2133
2134
848k
  ARM_get_detail_op(MI, 0)->type = ImmType;
2135
848k
  ARM_get_detail_op(MI, 0)->imm = Imm;
2136
848k
  ARM_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
2137
848k
  ARM_inc_op_count(MI);
2138
848k
}
2139
2140
/// Adds the operand as to the previously added memory operand.
2141
void ARM_set_detail_op_mem_offset(MCInst *MI, unsigned OpNum, uint64_t Val,
2142
          bool subtracted)
2143
45.2k
{
2144
45.2k
  CS_ASSERT_RET(map_get_op_type(MI, OpNum) & CS_OP_MEM);
2145
2146
45.2k
  if (!doing_mem(MI)) {
2147
45.2k
    CS_ASSERT_RET((ARM_get_detail_op(MI, -1) != NULL) &&
2148
45.2k
            (ARM_get_detail_op(MI, -1)->type == ARM_OP_MEM));
2149
45.2k
    ARM_dec_op_count(MI);
2150
45.2k
  }
2151
2152
45.2k
  if ((map_get_op_type(MI, OpNum) & ~CS_OP_MEM) == CS_OP_IMM)
2153
26.9k
    ARM_set_detail_op_mem(MI, OpNum, false, 0, Val);
2154
18.3k
  else if ((map_get_op_type(MI, OpNum) & ~CS_OP_MEM) == CS_OP_REG)
2155
18.3k
    ARM_set_detail_op_mem(MI, OpNum, true, subtracted ? -1 : 1,
2156
18.3k
              Val);
2157
0
  else
2158
0
    CS_ASSERT_RET(0 && "Memory type incorrect.");
2159
45.2k
  ARM_get_detail_op(MI, 0)->subtracted = subtracted;
2160
2161
45.2k
  if (!doing_mem(MI))
2162
45.2k
    ARM_inc_op_count(MI);
2163
45.2k
}
2164
2165
/// Adds a memory ARM operand at position OpNum. op_count is *not* increased by
2166
/// one. This is done by ARM_set_mem_access().
2167
void ARM_set_detail_op_mem(MCInst *MI, unsigned OpNum, bool is_index_reg,
2168
         int scale, uint64_t Val)
2169
651k
{
2170
651k
  if (!detail_is_set(MI))
2171
0
    return;
2172
651k
  CS_ASSERT_RET(map_get_op_type(MI, OpNum) & CS_OP_MEM);
2173
651k
  cs_op_type secondary_type = map_get_op_type(MI, OpNum) & ~CS_OP_MEM;
2174
651k
  switch (secondary_type) {
2175
0
  default:
2176
0
    CS_ASSERT_RET(0 && "Secondary type not supported yet.");
2177
417k
  case CS_OP_REG: {
2178
417k
    CS_ASSERT_RET(secondary_type == CS_OP_REG);
2179
417k
    if (!is_index_reg) {
2180
358k
      ARM_get_detail_op(MI, 0)->mem.base = Val;
2181
358k
      if (MCInst_opIsTying(MI, OpNum) ||
2182
271k
          MCInst_opIsTied(MI, OpNum)) {
2183
        // Base registers can be writeback registers.
2184
        // For this they tie an MC operand which has write
2185
        // access. But this one is never processed in the printer
2186
        // (because it is never emitted). Therefor it is never
2187
        // added to the modified list.
2188
        // Here we check for this case and add the memory register
2189
        // to the modified list.
2190
87.0k
        map_add_implicit_write(
2191
87.0k
          MI, MCInst_getOpVal(MI, OpNum));
2192
87.0k
        MI->flat_insn->detail->writeback = true;
2193
271k
      } else {
2194
        // If the base register is not tied, set the writebak flag to false.
2195
        // Writeback for ARM only refers to the memory base register.
2196
        // But other registers might be marked as tied as well.
2197
271k
        MI->flat_insn->detail->writeback = false;
2198
271k
      }
2199
358k
    } else {
2200
59.3k
      ARM_get_detail_op(MI, 0)->mem.index = Val;
2201
59.3k
    }
2202
417k
    ARM_get_detail_op(MI, 0)->mem.scale = scale;
2203
2204
417k
    break;
2205
417k
  }
2206
234k
  case CS_OP_IMM: {
2207
234k
    CS_ASSERT_RET(secondary_type == CS_OP_IMM);
2208
234k
    if (((int32_t)Val) < 0)
2209
11.6k
      ARM_get_detail_op(MI, 0)->subtracted = true;
2210
234k
    ARM_get_detail_op(MI, 0)->mem.disp = ((int64_t)Val < 0) ? -Val :
2211
234k
                    Val;
2212
234k
    break;
2213
234k
  }
2214
651k
  }
2215
2216
651k
  ARM_get_detail_op(MI, 0)->type = ARM_OP_MEM;
2217
651k
  ARM_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
2218
651k
}
2219
2220
/// Sets the neon_lane in the previous operand to the value of
2221
/// MI->operands[OpNum] Decrements op_count by 1.
2222
void ARM_set_detail_op_neon_lane(MCInst *MI, unsigned OpNum)
2223
30.4k
{
2224
30.4k
  if (!detail_is_set(MI))
2225
0
    return;
2226
30.4k
  CS_ASSERT_RET(map_get_op_type(MI, OpNum) == CS_OP_IMM);
2227
30.4k
  unsigned Val = MCOperand_getImm(MCInst_getOperand(MI, OpNum));
2228
2229
30.4k
  ARM_get_detail_op(MI, -1)->neon_lane = Val;
2230
30.4k
}
2231
2232
/// Adds a System Register and increments op_count by one.
2233
/// @type ARM_OP_SYSREG, ARM_OP_BANKEDREG, ARM_OP_SYSM...
2234
/// @p Mask is the MSR mask or UINT8_MAX if not set.
2235
void ARM_set_detail_op_sysop(MCInst *MI, int Val, arm_op_type type,
2236
           bool IsOutReg, uint8_t Mask, uint16_t Sysm)
2237
9.69k
{
2238
9.69k
  if (!detail_is_set(MI))
2239
0
    return;
2240
9.69k
  ARM_check_safe_inc(MI);
2241
2242
9.69k
  ARM_get_detail_op(MI, 0)->type = type;
2243
9.69k
  switch (type) {
2244
0
  default:
2245
0
    CS_ASSERT_RET(0 && "Unknown system operand type.");
2246
8.21k
  case ARM_OP_SYSREG:
2247
    // NOLINTBEGIN(clang-analyzer-optin.core.EnumCastOutOfRange)
2248
8.21k
    ARM_get_detail_op(MI, 0)->sysop.reg.mclasssysreg = Val;
2249
    // NOLINTEND(clang-analyzer-optin.core.EnumCastOutOfRange)
2250
8.21k
    break;
2251
854
  case ARM_OP_BANKEDREG:
2252
854
    ARM_get_detail_op(MI, 0)->sysop.reg.bankedreg = Val;
2253
854
    break;
2254
194
  case ARM_OP_SPSR:
2255
621
  case ARM_OP_CPSR:
2256
621
    ARM_get_detail_op(MI, 0)->reg =
2257
621
      type == ARM_OP_SPSR ? ARM_REG_SPSR : ARM_REG_CPSR;
2258
    // NOLINTBEGIN(clang-analyzer-optin.core.EnumCastOutOfRange)
2259
621
    ARM_get_detail_op(MI, 0)->sysop.psr_bits = Val;
2260
    // NOLINTEND(clang-analyzer-optin.core.EnumCastOutOfRange)
2261
621
    break;
2262
9.69k
  }
2263
9.69k
  ARM_get_detail_op(MI, 0)->sysop.sysm = Sysm;
2264
9.69k
  ARM_get_detail_op(MI, 0)->sysop.msr_mask = Mask;
2265
9.69k
  ARM_get_detail_op(MI, 0)->access = IsOutReg ? CS_AC_WRITE : CS_AC_READ;
2266
9.69k
  ARM_inc_op_count(MI);
2267
9.69k
}
2268
2269
/// Transforms the immediate of the operand to a float and stores it.
2270
/// Increments the op_counter by one.
2271
void ARM_set_detail_op_float(MCInst *MI, unsigned OpNum, uint64_t Imm)
2272
753
{
2273
753
  if (!detail_is_set(MI))
2274
0
    return;
2275
753
  ARM_check_safe_inc(MI);
2276
2277
753
  ARM_get_detail_op(MI, 0)->type = ARM_OP_FP;
2278
753
  ARM_get_detail_op(MI, 0)->fp = ARM_AM_getFPImmFloat(Imm);
2279
753
  ARM_inc_op_count(MI);
2280
753
}
2281
2282
#endif