Coverage Report

Created: 2026-11-12 06:22

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