Coverage Report

Created: 2026-09-28 06:34

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/capstonev5/arch/AArch64/AArch64Mapping.c
Line
Count
Source
1
/* Capstone Disassembly Engine */
2
/* By Nguyen Anh Quynh <aquynh@gmail.com>, 2013-2019 */
3
4
#ifdef CAPSTONE_HAS_ARM64
5
6
#include <stdio.h>  // debug
7
#include <string.h>
8
9
#include "../../utils.h"
10
11
#include "AArch64Mapping.h"
12
13
#define GET_INSTRINFO_ENUM
14
#include "AArch64GenInstrInfo.inc"
15
16
#ifndef CAPSTONE_DIET
17
// NOTE: this reg_name_maps[] reflects the order of registers in arm64_reg
18
static const char * const reg_name_maps[] = {
19
  NULL, /* ARM64_REG_INVALID */
20
21
  "ffr",
22
    "fp",
23
    "lr",
24
    "nzcv",
25
    "sp",
26
    "vg",
27
    "wsp",
28
    "wzr",
29
    "xzr",
30
31
    "za",
32
33
    "b0",
34
    "b1",
35
    "b2",
36
    "b3",
37
    "b4",
38
    "b5",
39
    "b6",
40
    "b7",
41
    "b8",
42
    "b9",
43
    "b10",
44
    "b11",
45
    "b12",
46
    "b13",
47
    "b14",
48
    "b15",
49
    "b16",
50
    "b17",
51
    "b18",
52
    "b19",
53
    "b20",
54
    "b21",
55
    "b22",
56
    "b23",
57
    "b24",
58
    "b25",
59
    "b26",
60
    "b27",
61
    "b28",
62
    "b29",
63
    "b30",
64
    "b31",
65
66
    "d0",
67
    "d1",
68
    "d2",
69
    "d3",
70
    "d4",
71
    "d5",
72
    "d6",
73
    "d7",
74
    "d8",
75
    "d9",
76
    "d10",
77
    "d11",
78
    "d12",
79
    "d13",
80
    "d14",
81
    "d15",
82
    "d16",
83
    "d17",
84
    "d18",
85
    "d19",
86
    "d20",
87
    "d21",
88
    "d22",
89
    "d23",
90
    "d24",
91
    "d25",
92
    "d26",
93
    "d27",
94
    "d28",
95
    "d29",
96
    "d30",
97
    "d31",
98
99
    "h0",
100
    "h1",
101
    "h2",
102
    "h3",
103
    "h4",
104
    "h5",
105
    "h6",
106
    "h7",
107
    "h8",
108
    "h9",
109
    "h10",
110
    "h11",
111
    "h12",
112
    "h13",
113
    "h14",
114
    "h15",
115
    "h16",
116
    "h17",
117
    "h18",
118
    "h19",
119
    "h20",
120
    "h21",
121
    "h22",
122
    "h23",
123
    "h24",
124
    "h25",
125
    "h26",
126
    "h27",
127
    "h28",
128
    "h29",
129
    "h30",
130
    "h31",
131
132
    "p0",
133
    "p1",
134
    "p2",
135
    "p3",
136
    "p4",
137
    "p5",
138
    "p6",
139
    "p7",
140
    "p8",
141
    "p9",
142
    "p10",
143
    "p11",
144
    "p12",
145
    "p13",
146
    "p14",
147
    "p15",
148
149
    "q0",
150
    "q1",
151
    "q2",
152
    "q3",
153
    "q4",
154
    "q5",
155
    "q6",
156
    "q7",
157
    "q8",
158
    "q9",
159
    "q10",
160
    "q11",
161
    "q12",
162
    "q13",
163
    "q14",
164
    "q15",
165
    "q16",
166
    "q17",
167
    "q18",
168
    "q19",
169
    "q20",
170
    "q21",
171
    "q22",
172
    "q23",
173
    "q24",
174
    "q25",
175
    "q26",
176
    "q27",
177
    "q28",
178
    "q29",
179
    "q30",
180
    "q31",
181
182
    "s0",
183
    "s1",
184
    "s2",
185
    "s3",
186
    "s4",
187
    "s5",
188
    "s6",
189
    "s7",
190
    "s8",
191
    "s9",
192
    "s10",
193
    "s11",
194
    "s12",
195
    "s13",
196
    "s14",
197
    "s15",
198
    "s16",
199
    "s17",
200
    "s18",
201
    "s19",
202
    "s20",
203
    "s21",
204
    "s22",
205
    "s23",
206
    "s24",
207
    "s25",
208
    "s26",
209
    "s27",
210
    "s28",
211
    "s29",
212
    "s30",
213
    "s31",
214
215
    "w0",
216
    "w1",
217
    "w2",
218
    "w3",
219
    "w4",
220
    "w5",
221
    "w6",
222
    "w7",
223
    "w8",
224
    "w9",
225
    "w10",
226
    "w11",
227
    "w12",
228
    "w13",
229
    "w14",
230
    "w15",
231
    "w16",
232
    "w17",
233
    "w18",
234
    "w19",
235
    "w20",
236
    "w21",
237
    "w22",
238
    "w23",
239
    "w24",
240
    "w25",
241
    "w26",
242
    "w27",
243
    "w28",
244
    "w29",
245
    "w30",
246
247
    "x0",
248
    "x1",
249
    "x2",
250
    "x3",
251
    "x4",
252
    "x5",
253
    "x6",
254
    "x7",
255
    "x8",
256
    "x9",
257
    "x10",
258
    "x11",
259
    "x12",
260
    "x13",
261
    "x14",
262
    "x15",
263
    "x16",
264
    "x17",
265
    "x18",
266
    "x19",
267
    "x20",
268
    "x21",
269
    "x22",
270
    "x23",
271
    "x24",
272
    "x25",
273
    "x26",
274
    "x27",
275
    "x28",
276
277
    "z0",
278
    "z1",
279
    "z2",
280
    "z3",
281
    "z4",
282
    "z5",
283
    "z6",
284
    "z7",
285
    "z8",
286
    "z9",
287
    "z10",
288
    "z11",
289
    "z12",
290
    "z13",
291
    "z14",
292
    "z15",
293
    "z16",
294
    "z17",
295
    "z18",
296
    "z19",
297
    "z20",
298
    "z21",
299
    "z22",
300
    "z23",
301
    "z24",
302
    "z25",
303
    "z26",
304
    "z27",
305
    "z28",
306
    "z29",
307
    "z30",
308
    "z31",
309
310
    "zab0",
311
312
    "zad0",
313
    "zad1",
314
    "zad2",
315
    "zad3",
316
    "zad4",
317
    "zad5",
318
    "zad6",
319
    "zad7",
320
321
    "zah0",
322
    "zah1",
323
324
    "zaq0",
325
    "zaq1",
326
    "zaq2",
327
    "zaq3",
328
    "zaq4",
329
    "zaq5",
330
    "zaq6",
331
    "zaq7",
332
    "zaq8",
333
    "zaq9",
334
    "zaq10",
335
    "zaq11",
336
    "zaq12",
337
    "zaq13",
338
    "zaq14",
339
    "zaq15",
340
341
    "zas0",
342
    "zas1",
343
    "zas2",
344
    "zas3",
345
346
    "v0",
347
    "v1",
348
    "v2",
349
    "v3",
350
    "v4",
351
    "v5",
352
    "v6",
353
    "v7",
354
    "v8",
355
    "v9",
356
    "v10",
357
    "v11",
358
    "v12",
359
    "v13",
360
    "v14",
361
    "v15",
362
    "v16",
363
    "v17",
364
    "v18",
365
    "v19",
366
    "v20",
367
    "v21",
368
    "v22",
369
    "v23",
370
    "v24",
371
    "v25",
372
    "v26",
373
    "v27",
374
    "v28",
375
    "v29",
376
    "v30",
377
    "v31",
378
};
379
#endif
380
381
const char *AArch64_reg_name(csh handle, unsigned int reg)
382
13.1k
{
383
13.1k
#ifndef CAPSTONE_DIET
384
13.1k
  if (reg >= ARR_SIZE(reg_name_maps))
385
0
    return NULL;
386
387
13.1k
  return reg_name_maps[reg];
388
#else
389
  return NULL;
390
#endif
391
13.1k
}
392
393
static const insn_map insns[] = {
394
  // dummy item
395
  {
396
    0, 0,
397
#ifndef CAPSTONE_DIET
398
    { 0 }, { 0 }, { 0 }, 0, 0
399
#endif
400
  },
401
402
#include "AArch64MappingInsn.inc"
403
};
404
405
// given internal insn id, return public instruction info
406
void AArch64_get_insn_id(cs_struct *h, cs_insn *insn, unsigned int id)
407
235k
{
408
235k
  int i = insn_find(insns, ARR_SIZE(insns), id, &h->insn_cache);
409
235k
  if (i != 0) {
410
235k
    insn->id = insns[i].mapid;
411
412
235k
    if (h->detail) {
413
235k
#ifndef CAPSTONE_DIET
414
235k
      cs_struct handle;
415
235k
      handle.detail = h->detail;
416
417
235k
      memcpy(insn->detail->regs_read, insns[i].regs_use, sizeof(insns[i].regs_use));
418
235k
      insn->detail->regs_read_count = (uint8_t)count_positive(insns[i].regs_use);
419
420
235k
      memcpy(insn->detail->regs_write, insns[i].regs_mod, sizeof(insns[i].regs_mod));
421
235k
      insn->detail->regs_write_count = (uint8_t)count_positive(insns[i].regs_mod);
422
423
235k
      memcpy(insn->detail->groups, insns[i].groups, sizeof(insns[i].groups));
424
235k
      insn->detail->groups_count = (uint8_t)count_positive8(insns[i].groups);
425
426
235k
      insn->detail->arm64.update_flags = cs_reg_write((csh)&handle, insn, ARM64_REG_NZCV);
427
235k
#endif
428
235k
    }
429
235k
  }
430
235k
}
431
432
static const char * const insn_name_maps[] = {
433
  NULL, // ARM64_INS_INVALID
434
#include "AArch64MappingInsnName.inc"
435
  "sbfiz",
436
  "ubfiz",
437
  "sbfx",
438
  "ubfx",
439
  "bfi",
440
  "bfxil",
441
  "ic",
442
  "dc",
443
  "at",
444
  "tlbi",
445
  "smstart",
446
    "smstop",
447
};
448
449
const char *AArch64_insn_name(csh handle, unsigned int id)
450
235k
{
451
235k
#ifndef CAPSTONE_DIET
452
235k
  if (id >= ARM64_INS_ENDING)
453
0
    return NULL;
454
455
235k
  if (id < ARR_SIZE(insn_name_maps))
456
235k
    return insn_name_maps[id];
457
458
  // not found
459
0
  return NULL;
460
#else
461
  return NULL;
462
#endif
463
235k
}
464
465
#ifndef CAPSTONE_DIET
466
static const name_map group_name_maps[] = {
467
  // generic groups
468
  { ARM64_GRP_INVALID, NULL },
469
  { ARM64_GRP_JUMP, "jump" },
470
  { ARM64_GRP_CALL, "call" },
471
  { ARM64_GRP_RET, "return" },
472
  { ARM64_GRP_PRIVILEGE, "privilege" },
473
  { ARM64_GRP_INT, "int" },
474
  { ARM64_GRP_BRANCH_RELATIVE, "branch_relative" },
475
  { ARM64_GRP_PAC, "pointer authentication" },
476
477
  // architecture-specific groups
478
  { ARM64_GRP_CRYPTO, "crypto" },
479
  { ARM64_GRP_FPARMV8, "fparmv8" },
480
  { ARM64_GRP_NEON, "neon" },
481
  { ARM64_GRP_CRC, "crc" },
482
483
  { ARM64_GRP_AES, "aes" },
484
  { ARM64_GRP_DOTPROD, "dotprod" },
485
  { ARM64_GRP_FULLFP16, "fullfp16" },
486
  { ARM64_GRP_LSE, "lse" },
487
  { ARM64_GRP_RCPC, "rcpc" },
488
  { ARM64_GRP_RDM, "rdm" },
489
  { ARM64_GRP_SHA2, "sha2" },
490
  { ARM64_GRP_SHA3, "sha3" },
491
  { ARM64_GRP_SM4, "sm4" },
492
  { ARM64_GRP_SVE, "sve" },
493
  { ARM64_GRP_SVE2, "sve2" },
494
    { ARM64_GRP_SVE2AES, "sve2-aes" },
495
    { ARM64_GRP_SVE2BitPerm, "sve2-bitperm" },
496
    { ARM64_GRP_SVE2SHA3, "sve2-sha3" },
497
    { ARM64_GRP_SVE2SM4, "sve2-sm4" },
498
    { ARM64_GRP_SME, "sme" },
499
    { ARM64_GRP_SMEF64, "sme-f64" },
500
    { ARM64_GRP_SMEI64, "sme-i64" },
501
    { ARM64_GRP_MatMulFP32, "f32mm" },
502
    { ARM64_GRP_MatMulFP64, "f64mm" },
503
    { ARM64_GRP_MatMulInt8, "i8mm" },
504
  { ARM64_GRP_V8_1A, "v8_1a" },
505
  { ARM64_GRP_V8_3A, "v8_3a" },
506
  { ARM64_GRP_V8_4A, "v8_4a" },
507
};
508
#endif
509
510
const char *AArch64_group_name(csh handle, unsigned int id)
511
88.8k
{
512
88.8k
#ifndef CAPSTONE_DIET
513
88.8k
  return id2name(group_name_maps, ARR_SIZE(group_name_maps), id);
514
#else
515
  return NULL;
516
#endif
517
88.8k
}
518
519
// map instruction name to public instruction ID
520
arm64_insn AArch64_map_insn(const char *name)
521
35.2k
{
522
35.2k
  unsigned int i;
523
524
23.8M
  for(i = 1; i < ARR_SIZE(insn_name_maps); i++) {
525
23.8M
    if (!strcmp(name, insn_name_maps[i]))
526
35.1k
      return i;
527
23.8M
  }
528
529
  // not found
530
129
  return ARM64_INS_INVALID;
531
35.2k
}
532
533
// map internal raw vregister to 'public' register
534
arm64_reg AArch64_map_vregister(unsigned int r)
535
162k
{
536
162k
  static const unsigned short RegAsmOffsetvreg[] = {
537
162k
#include "AArch64GenRegisterV.inc"
538
162k
  };
539
540
162k
  if (r < ARR_SIZE(RegAsmOffsetvreg))
541
162k
    return RegAsmOffsetvreg[r - 1];
542
543
  // cannot find this register
544
0
  return 0;
545
162k
}
546
547
static const name_map sys_op_name_map[] = {
548
  { ARM64_TLBI_ALLE1, "alle1"} ,
549
    { ARM64_TLBI_ALLE1IS, "alle1is"} ,
550
    { ARM64_TLBI_ALLE1ISNXS, "alle1isnxs"} ,
551
    { ARM64_TLBI_ALLE1NXS, "alle1nxs"} ,
552
    { ARM64_TLBI_ALLE1OS, "alle1os"} ,
553
    { ARM64_TLBI_ALLE1OSNXS, "alle1osnxs"} ,
554
    { ARM64_TLBI_ALLE2, "alle2"} ,
555
    { ARM64_TLBI_ALLE2IS, "alle2is"} ,
556
    { ARM64_TLBI_ALLE2ISNXS, "alle2isnxs"} ,
557
    { ARM64_TLBI_ALLE2NXS, "alle2nxs"} ,
558
    { ARM64_TLBI_ALLE2OS, "alle2os"} ,
559
    { ARM64_TLBI_ALLE2OSNXS, "alle2osnxs"} ,
560
    { ARM64_TLBI_ALLE3, "alle3"} ,
561
    { ARM64_TLBI_ALLE3IS, "alle3is"} ,
562
    { ARM64_TLBI_ALLE3ISNXS, "alle3isnxs"} ,
563
    { ARM64_TLBI_ALLE3NXS, "alle3nxs"} ,
564
    { ARM64_TLBI_ALLE3OS, "alle3os"} ,
565
    { ARM64_TLBI_ALLE3OSNXS, "alle3osnxs"} ,
566
    { ARM64_TLBI_ASIDE1, "aside1"} ,
567
    { ARM64_TLBI_ASIDE1IS, "aside1is"} ,
568
    { ARM64_TLBI_ASIDE1ISNXS, "aside1isnxs"} ,
569
    { ARM64_TLBI_ASIDE1NXS, "aside1nxs"} ,
570
    { ARM64_TLBI_ASIDE1OS, "aside1os"} ,
571
    { ARM64_TLBI_ASIDE1OSNXS, "aside1osnxs"} ,
572
    { ARM64_TLBI_IPAS2E1, "ipas2e1"} ,
573
    { ARM64_TLBI_IPAS2E1IS, "ipas2e1is"} ,
574
    { ARM64_TLBI_IPAS2E1ISNXS, "ipas2e1isnxs"} ,
575
    { ARM64_TLBI_IPAS2E1NXS, "ipas2e1nxs"} ,
576
    { ARM64_TLBI_IPAS2E1OS, "ipas2e1os"} ,
577
    { ARM64_TLBI_IPAS2E1OSNXS, "ipas2e1osnxs"} ,
578
    { ARM64_TLBI_IPAS2LE1, "ipas2le1"} ,
579
    { ARM64_TLBI_IPAS2LE1IS, "ipas2le1is"} ,
580
    { ARM64_TLBI_IPAS2LE1ISNXS, "ipas2le1isnxs"} ,
581
    { ARM64_TLBI_IPAS2LE1NXS, "ipas2le1nxs"} ,
582
    { ARM64_TLBI_IPAS2LE1OS, "ipas2le1os"} ,
583
    { ARM64_TLBI_IPAS2LE1OSNXS, "ipas2le1osnxs"} ,
584
    { ARM64_TLBI_PAALL, "paall"} ,
585
    { ARM64_TLBI_PAALLNXS, "paallnxs"} ,
586
    { ARM64_TLBI_PAALLOS, "paallos"} ,
587
    { ARM64_TLBI_PAALLOSNXS, "paallosnxs"} ,
588
    { ARM64_TLBI_RIPAS2E1, "ripas2e1"} ,
589
    { ARM64_TLBI_RIPAS2E1IS, "ripas2e1is"} ,
590
    { ARM64_TLBI_RIPAS2E1ISNXS, "ripas2e1isnxs"} ,
591
    { ARM64_TLBI_RIPAS2E1NXS, "ripas2e1nxs"} ,
592
    { ARM64_TLBI_RIPAS2E1OS, "ripas2e1os"} ,
593
    { ARM64_TLBI_RIPAS2E1OSNXS, "ripas2e1osnxs"} ,
594
    { ARM64_TLBI_RIPAS2LE1, "ripas2le1"} ,
595
    { ARM64_TLBI_RIPAS2LE1IS, "ripas2le1is"} ,
596
    { ARM64_TLBI_RIPAS2LE1ISNXS, "ripas2le1isnxs"} ,
597
    { ARM64_TLBI_RIPAS2LE1NXS, "ripas2le1nxs"} ,
598
    { ARM64_TLBI_RIPAS2LE1OS, "ripas2le1os"} ,
599
    { ARM64_TLBI_RIPAS2LE1OSNXS, "ripas2le1osnxs"} ,
600
    { ARM64_TLBI_RPALOS, "rpalos"} ,
601
    { ARM64_TLBI_RPALOSNXS, "rpalosnxs"} ,
602
    { ARM64_TLBI_RPAOS, "rpaos"} ,
603
    { ARM64_TLBI_RPAOSNXS, "rpaosnxs"} ,
604
    { ARM64_TLBI_RVAAE1, "rvaae1"} ,
605
    { ARM64_TLBI_RVAAE1IS, "rvaae1is"} ,
606
    { ARM64_TLBI_RVAAE1ISNXS, "rvaae1isnxs"} ,
607
    { ARM64_TLBI_RVAAE1NXS, "rvaae1nxs"} ,
608
    { ARM64_TLBI_RVAAE1OS, "rvaae1os"} ,
609
    { ARM64_TLBI_RVAAE1OSNXS, "rvaae1osnxs"} ,
610
    { ARM64_TLBI_RVAALE1, "rvaale1"} ,
611
    { ARM64_TLBI_RVAALE1IS, "rvaale1is"} ,
612
    { ARM64_TLBI_RVAALE1ISNXS, "rvaale1isnxs"} ,
613
    { ARM64_TLBI_RVAALE1NXS, "rvaale1nxs"} ,
614
    { ARM64_TLBI_RVAALE1OS, "rvaale1os"} ,
615
    { ARM64_TLBI_RVAALE1OSNXS, "rvaale1osnxs"} ,
616
    { ARM64_TLBI_RVAE1, "rvae1"} ,
617
    { ARM64_TLBI_RVAE1IS, "rvae1is"} ,
618
    { ARM64_TLBI_RVAE1ISNXS, "rvae1isnxs"} ,
619
    { ARM64_TLBI_RVAE1NXS, "rvae1nxs"} ,
620
    { ARM64_TLBI_RVAE1OS, "rvae1os"} ,
621
    { ARM64_TLBI_RVAE1OSNXS, "rvae1osnxs"} ,
622
    { ARM64_TLBI_RVAE2, "rvae2"} ,
623
    { ARM64_TLBI_RVAE2IS, "rvae2is"} ,
624
    { ARM64_TLBI_RVAE2ISNXS, "rvae2isnxs"} ,
625
    { ARM64_TLBI_RVAE2NXS, "rvae2nxs"} ,
626
    { ARM64_TLBI_RVAE2OS, "rvae2os"} ,
627
    { ARM64_TLBI_RVAE2OSNXS, "rvae2osnxs"} ,
628
    { ARM64_TLBI_RVAE3, "rvae3"} ,
629
    { ARM64_TLBI_RVAE3IS, "rvae3is"} ,
630
    { ARM64_TLBI_RVAE3ISNXS, "rvae3isnxs"} ,
631
    { ARM64_TLBI_RVAE3NXS, "rvae3nxs"} ,
632
    { ARM64_TLBI_RVAE3OS, "rvae3os"} ,
633
    { ARM64_TLBI_RVAE3OSNXS, "rvae3osnxs"} ,
634
    { ARM64_TLBI_RVALE1, "rvale1"} ,
635
    { ARM64_TLBI_RVALE1IS, "rvale1is"} ,
636
    { ARM64_TLBI_RVALE1ISNXS, "rvale1isnxs"} ,
637
    { ARM64_TLBI_RVALE1NXS, "rvale1nxs"} ,
638
    { ARM64_TLBI_RVALE1OS, "rvale1os"} ,
639
    { ARM64_TLBI_RVALE1OSNXS, "rvale1osnxs"} ,
640
    { ARM64_TLBI_RVALE2, "rvale2"} ,
641
    { ARM64_TLBI_RVALE2IS, "rvale2is"} ,
642
    { ARM64_TLBI_RVALE2ISNXS, "rvale2isnxs"} ,
643
    { ARM64_TLBI_RVALE2NXS, "rvale2nxs"} ,
644
    { ARM64_TLBI_RVALE2OS, "rvale2os"} ,
645
    { ARM64_TLBI_RVALE2OSNXS, "rvale2osnxs"} ,
646
    { ARM64_TLBI_RVALE3, "rvale3"} ,
647
    { ARM64_TLBI_RVALE3IS, "rvale3is"} ,
648
    { ARM64_TLBI_RVALE3ISNXS, "rvale3isnxs"} ,
649
    { ARM64_TLBI_RVALE3NXS, "rvale3nxs"} ,
650
    { ARM64_TLBI_RVALE3OS, "rvale3os"} ,
651
    { ARM64_TLBI_RVALE3OSNXS, "rvale3osnxs"} ,
652
    { ARM64_TLBI_VAAE1, "vaae1"} ,
653
    { ARM64_TLBI_VAAE1IS, "vaae1is"} ,
654
    { ARM64_TLBI_VAAE1ISNXS, "vaae1isnxs"} ,
655
    { ARM64_TLBI_VAAE1NXS, "vaae1nxs"} ,
656
    { ARM64_TLBI_VAAE1OS, "vaae1os"} ,
657
    { ARM64_TLBI_VAAE1OSNXS, "vaae1osnxs"} ,
658
    { ARM64_TLBI_VAALE1, "vaale1"} ,
659
    { ARM64_TLBI_VAALE1IS, "vaale1is"} ,
660
    { ARM64_TLBI_VAALE1ISNXS, "vaale1isnxs"} ,
661
    { ARM64_TLBI_VAALE1NXS, "vaale1nxs"} ,
662
    { ARM64_TLBI_VAALE1OS, "vaale1os"} ,
663
    { ARM64_TLBI_VAALE1OSNXS, "vaale1osnxs"} ,
664
    { ARM64_TLBI_VAE1, "vae1"} ,
665
    { ARM64_TLBI_VAE1IS, "vae1is"} ,
666
    { ARM64_TLBI_VAE1ISNXS, "vae1isnxs"} ,
667
    { ARM64_TLBI_VAE1NXS, "vae1nxs"} ,
668
    { ARM64_TLBI_VAE1OS, "vae1os"} ,
669
    { ARM64_TLBI_VAE1OSNXS, "vae1osnxs"} ,
670
    { ARM64_TLBI_VAE2, "vae2"} ,
671
    { ARM64_TLBI_VAE2IS, "vae2is"} ,
672
    { ARM64_TLBI_VAE2ISNXS, "vae2isnxs"} ,
673
    { ARM64_TLBI_VAE2NXS, "vae2nxs"} ,
674
    { ARM64_TLBI_VAE2OS, "vae2os"} ,
675
    { ARM64_TLBI_VAE2OSNXS, "vae2osnxs"} ,
676
    { ARM64_TLBI_VAE3, "vae3"} ,
677
    { ARM64_TLBI_VAE3IS, "vae3is"} ,
678
    { ARM64_TLBI_VAE3ISNXS, "vae3isnxs"} ,
679
    { ARM64_TLBI_VAE3NXS, "vae3nxs"} ,
680
    { ARM64_TLBI_VAE3OS, "vae3os"} ,
681
    { ARM64_TLBI_VAE3OSNXS, "vae3osnxs"} ,
682
    { ARM64_TLBI_VALE1, "vale1"} ,
683
    { ARM64_TLBI_VALE1IS, "vale1is"} ,
684
    { ARM64_TLBI_VALE1ISNXS, "vale1isnxs"} ,
685
    { ARM64_TLBI_VALE1NXS, "vale1nxs"} ,
686
    { ARM64_TLBI_VALE1OS, "vale1os"} ,
687
    { ARM64_TLBI_VALE1OSNXS, "vale1osnxs"} ,
688
    { ARM64_TLBI_VALE2, "vale2"} ,
689
    { ARM64_TLBI_VALE2IS, "vale2is"} ,
690
    { ARM64_TLBI_VALE2ISNXS, "vale2isnxs"} ,
691
    { ARM64_TLBI_VALE2NXS, "vale2nxs"} ,
692
    { ARM64_TLBI_VALE2OS, "vale2os"} ,
693
    { ARM64_TLBI_VALE2OSNXS, "vale2osnxs"} ,
694
    { ARM64_TLBI_VALE3, "vale3"} ,
695
    { ARM64_TLBI_VALE3IS, "vale3is"} ,
696
    { ARM64_TLBI_VALE3ISNXS, "vale3isnxs"} ,
697
    { ARM64_TLBI_VALE3NXS, "vale3nxs"} ,
698
    { ARM64_TLBI_VALE3OS, "vale3os"} ,
699
    { ARM64_TLBI_VALE3OSNXS, "vale3osnxs"} ,
700
    { ARM64_TLBI_VMALLE1, "vmalle1"} ,
701
    { ARM64_TLBI_VMALLE1IS, "vmalle1is"} ,
702
    { ARM64_TLBI_VMALLE1ISNXS, "vmalle1isnxs"} ,
703
    { ARM64_TLBI_VMALLE1NXS, "vmalle1nxs"} ,
704
    { ARM64_TLBI_VMALLE1OS, "vmalle1os"} ,
705
    { ARM64_TLBI_VMALLE1OSNXS, "vmalle1osnxs"} ,
706
    { ARM64_TLBI_VMALLS12E1, "vmalls12e1"} ,
707
    { ARM64_TLBI_VMALLS12E1IS, "vmalls12e1is"} ,
708
    { ARM64_TLBI_VMALLS12E1ISNXS, "vmalls12e1isnxs"} ,
709
    { ARM64_TLBI_VMALLS12E1NXS, "vmalls12e1nxs"} ,
710
    { ARM64_TLBI_VMALLS12E1OS, "vmalls12e1os"} ,
711
    { ARM64_TLBI_VMALLS12E1OSNXS, "vmalls12e1osnxs"} ,
712
    { ARM64_AT_S1E1R, "s1e1r"} ,
713
    { ARM64_AT_S1E2R, "s1e2r"} ,
714
    { ARM64_AT_S1E3R, "s1e3r"} ,
715
    { ARM64_AT_S1E1W, "s1e1w"} ,
716
    { ARM64_AT_S1E2W, "s1e2w"} ,
717
    { ARM64_AT_S1E3W, "s1e3w"} ,
718
    { ARM64_AT_S1E0R, "s1e0r"} ,
719
    { ARM64_AT_S1E0W, "s1e0w"} ,
720
    { ARM64_AT_S12E1R, "s12e1r"} ,
721
    { ARM64_AT_S12E1W, "s12e1w"} ,
722
    { ARM64_AT_S12E0R, "s12e0r"} ,
723
    { ARM64_AT_S12E0W, "s12e0w"} ,
724
    { ARM64_AT_S1E1RP, "s1e1rp"} ,
725
    { ARM64_AT_S1E1WP, "s1e1wp"} ,
726
    { ARM64_DC_CGDSW, "cgdsw"} ,
727
    { ARM64_DC_CGDVAC, "cgdvac"} ,
728
    { ARM64_DC_CGDVADP, "cgdvadp"} ,
729
    { ARM64_DC_CGDVAP, "cgdvap"} ,
730
    { ARM64_DC_CGSW, "cgsw"} ,
731
    { ARM64_DC_CGVAC, "cgvac"} ,
732
    { ARM64_DC_CGVADP, "cgvadp"} ,
733
    { ARM64_DC_CGVAP, "cgvap"} ,
734
    { ARM64_DC_CIGDSW, "cigdsw"} ,
735
    { ARM64_DC_CIGDVAC, "cigdvac"} ,
736
    { ARM64_DC_CIGSW, "cigsw"} ,
737
    { ARM64_DC_CIGVAC, "cigvac"} ,
738
    { ARM64_DC_CISW, "cisw"} ,
739
    { ARM64_DC_CIVAC, "civac"} ,
740
    { ARM64_DC_CSW, "csw"} ,
741
    { ARM64_DC_CVAC, "cvac"} ,
742
    { ARM64_DC_CVADP, "cvadp"} ,
743
    { ARM64_DC_CVAP, "cvap"} ,
744
    { ARM64_DC_CVAU, "cvau"} ,
745
    { ARM64_DC_GVA, "gva"} ,
746
    { ARM64_DC_GZVA, "gzva"} ,
747
    { ARM64_DC_IGDSW, "igdsw"} ,
748
    { ARM64_DC_IGDVAC, "igdvac"} ,
749
    { ARM64_DC_IGSW, "igsw"} ,
750
    { ARM64_DC_IGVAC, "igvac"} ,
751
    { ARM64_DC_ISW, "isw"} ,
752
    { ARM64_DC_IVAC, "ivac"} ,
753
    { ARM64_DC_ZVA, "zva"} ,
754
    { ARM64_IC_IALLUIS, "ialluis"} ,
755
    { ARM64_IC_IALLU, "iallu"} ,
756
    { ARM64_IC_IVAU, "ivau"} ,
757
};
758
759
arm64_sys_op AArch64_map_sys_op(const char *name)
760
1.52k
{
761
1.52k
  int result = name2id(sys_op_name_map, ARR_SIZE(sys_op_name_map), name);
762
1.52k
  if (result == -1) {
763
0
    return ARM64_SYS_INVALID;
764
0
  }
765
1.52k
  return result;
766
1.52k
}
767
768
void arm64_op_addReg(MCInst *MI, int reg)
769
0
{
770
0
  if (MI->csh->detail) {
771
0
    MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_REG;
772
0
    MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].reg = reg;
773
0
    MI->flat_insn->detail->arm64.op_count++;
774
0
  }
775
0
}
776
777
void arm64_op_addVectorArrSpecifier(MCInst * MI, int sp)
778
42.3k
{
779
42.3k
  if (MI->csh->detail) {
780
42.3k
    MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count - 1].vas = sp;
781
42.3k
  }
782
42.3k
}
783
784
void arm64_op_addFP(MCInst *MI, float fp)
785
857
{
786
857
  if (MI->csh->detail) {
787
857
    MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_FP;
788
857
    MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].fp = fp;
789
857
    MI->flat_insn->detail->arm64.op_count++;
790
857
  }
791
857
}
792
793
void arm64_op_addImm(MCInst *MI, int64_t imm)
794
5.03k
{
795
5.03k
  if (MI->csh->detail) {
796
5.03k
    MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].type = ARM64_OP_IMM;
797
5.03k
    MI->flat_insn->detail->arm64.operands[MI->flat_insn->detail->arm64.op_count].imm = (int)imm;
798
5.03k
    MI->flat_insn->detail->arm64.op_count++;
799
5.03k
  }
800
5.03k
}
801
802
#ifndef CAPSTONE_DIET
803
804
// map instruction to its characteristics
805
typedef struct insn_op {
806
  unsigned int eflags_update; // how this instruction update status flags
807
  uint8_t access[5];
808
} insn_op;
809
810
static const insn_op insn_ops[] = {
811
    {
812
         /* NULL item */
813
        0, { 0 }
814
    },
815
816
#include "AArch64MappingInsnOp.inc"
817
};
818
819
// given internal insn id, return operand access info
820
const uint8_t *AArch64_get_op_access(cs_struct *h, unsigned int id)
821
674k
{
822
674k
  int i = insn_find(insns, ARR_SIZE(insns), id, &h->insn_cache);
823
674k
  if (i != 0) {
824
674k
    return insn_ops[i].access;
825
674k
  }
826
827
0
  return NULL;
828
674k
}
829
830
static bool is_casp(unsigned int id);
831
static void add_casp_register_pair_access(const cs_arm64 *arm64,
832
    cs_regs regs_read, uint8_t *read_count,
833
    cs_regs regs_write, uint8_t *write_count);
834
835
void AArch64_reg_access(const cs_insn *insn,
836
    cs_regs regs_read, uint8_t *regs_read_count,
837
    cs_regs regs_write, uint8_t *regs_write_count)
838
0
{
839
0
  uint8_t i;
840
0
  uint8_t read_count, write_count;
841
0
  cs_arm64 *arm64 = &(insn->detail->arm64);
842
843
0
  read_count = insn->detail->regs_read_count;
844
0
  write_count = insn->detail->regs_write_count;
845
846
  // implicit registers
847
0
  memcpy(regs_read, insn->detail->regs_read, read_count * sizeof(insn->detail->regs_read[0]));
848
0
  memcpy(regs_write, insn->detail->regs_write, write_count * sizeof(insn->detail->regs_write[0]));
849
850
  // explicit registers
851
0
  for (i = 0; i < arm64->op_count; i++) {
852
0
    cs_arm64_op *op = &(arm64->operands[i]);
853
0
    switch((int)op->type) {
854
0
      case ARM64_OP_REG:
855
0
        if ((op->access & CS_AC_READ) && !arr_exist(regs_read, read_count, op->reg)) {
856
0
          regs_read[read_count] = (uint16_t)op->reg;
857
0
          read_count++;
858
0
        }
859
0
        if ((op->access & CS_AC_WRITE) && !arr_exist(regs_write, write_count, op->reg)) {
860
0
          regs_write[write_count] = (uint16_t)op->reg;
861
0
          write_count++;
862
0
        }
863
0
        break;
864
0
      case ARM_OP_MEM:
865
        // registers appeared in memory references always being read
866
0
        if ((op->mem.base != ARM64_REG_INVALID) && !arr_exist(regs_read, read_count, op->mem.base)) {
867
0
          regs_read[read_count] = (uint16_t)op->mem.base;
868
0
          read_count++;
869
0
        }
870
0
        if ((op->mem.index != ARM64_REG_INVALID) && !arr_exist(regs_read, read_count, op->mem.index)) {
871
0
          regs_read[read_count] = (uint16_t)op->mem.index;
872
0
          read_count++;
873
0
        }
874
0
        if ((arm64->writeback) && (op->mem.base != ARM64_REG_INVALID) && !arr_exist(regs_write, write_count, op->mem.base)) {
875
0
          regs_write[write_count] = (uint16_t)op->mem.base;
876
0
          write_count++;
877
0
        }
878
0
      default:
879
0
        break;
880
0
    }
881
0
  }
882
883
0
  if (is_casp(insn->id))
884
0
    add_casp_register_pair_access(arm64, regs_read, &read_count, regs_write, &write_count);
885
886
0
  *regs_read_count = read_count;
887
0
  *regs_write_count = write_count;
888
0
}
889
890
static bool is_casp(unsigned int id)
891
0
{
892
0
  return id == ARM64_INS_CASP || id == ARM64_INS_CASPA ||
893
0
    id == ARM64_INS_CASPAL || id == ARM64_INS_CASPL;
894
0
}
895
896
// The CASP register-pair operands have their second element printed without any
897
// operand-access info, so populate it here: operands 0..1 are read and written,
898
// 2..3 are read.
899
static void add_casp_register_pair_access(const cs_arm64 *arm64,
900
    cs_regs regs_read, uint8_t *read_count,
901
    cs_regs regs_write, uint8_t *write_count)
902
0
{
903
0
  uint8_t i;
904
905
0
  for (i = 0; i < 4 && i < arm64->op_count; i++) {
906
0
    arm64_reg reg = arm64->operands[i].reg;
907
0
    if (!arr_exist(regs_read, *read_count, reg)) {
908
0
      regs_read[*read_count] = (uint16_t)reg;
909
0
      (*read_count)++;
910
0
    }
911
0
    if (i < 2 && !arr_exist(regs_write, *write_count, reg)) {
912
0
      regs_write[*write_count] = (uint16_t)reg;
913
0
      (*write_count)++;
914
0
    }
915
0
  }
916
0
}
917
#endif
918
919
#endif