Coverage Report

Created: 2025-07-11 06:32

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