Coverage Report

Created: 2024-08-21 06:24

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