Coverage Report

Created: 2026-02-26 07:11

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