Coverage Report

Created: 2024-08-21 06:24

/src/capstonenext/arch/RISCV/RISCVMapping.c
Line
Count
Source (jump to first uncovered line)
1
2
#ifdef CAPSTONE_HAS_RISCV
3
4
#include <stdio.h>    // debug
5
#include <string.h>
6
7
#include "../../Mapping.h"
8
#include "../../utils.h"
9
#include "../../cs_simple_types.h"
10
11
#include "RISCVMapping.h"
12
#include "RISCVInstPrinter.h"
13
14
#define GET_INSTRINFO_ENUM
15
#include "RISCVGenInstrInfo.inc"
16
17
#ifndef CAPSTONE_DIET
18
static const name_map reg_name_maps[] = {
19
  { RISCV_REG_INVALID, NULL },
20
21
  { RISCV_REG_X0, "zero" },
22
  { RISCV_REG_X1, "ra" },
23
  { RISCV_REG_X2, "sp" },
24
  { RISCV_REG_X3, "gp" },
25
  { RISCV_REG_X4, "tp" },
26
  { RISCV_REG_X5, "t0" },
27
  { RISCV_REG_X6, "t1" },
28
  { RISCV_REG_X7, "t2" },
29
  { RISCV_REG_X8, "s0" },
30
  { RISCV_REG_X9, "s1" },
31
  { RISCV_REG_X10, "a0" },
32
  { RISCV_REG_X11, "a1" },
33
  { RISCV_REG_X12, "a2" },
34
  { RISCV_REG_X13, "a3" },
35
  { RISCV_REG_X14, "a4" },
36
  { RISCV_REG_X15, "a5" },
37
  { RISCV_REG_X16, "a6" },
38
  { RISCV_REG_X17, "a7" },
39
  { RISCV_REG_X18, "s2" },
40
  { RISCV_REG_X19, "s3" },
41
  { RISCV_REG_X20, "s4" },
42
  { RISCV_REG_X21, "s5" },
43
  { RISCV_REG_X22, "s6" },
44
  { RISCV_REG_X23, "s7" },
45
  { RISCV_REG_X24, "s8" },
46
  { RISCV_REG_X25, "s9" },
47
  { RISCV_REG_X26, "s10" },
48
  { RISCV_REG_X27, "s11" },
49
  { RISCV_REG_X28, "t3" },
50
  { RISCV_REG_X29, "t4" },
51
  { RISCV_REG_X30, "t5" },
52
  { RISCV_REG_X31, "t6" },
53
54
  { RISCV_REG_F0_32, "ft0" },
55
  { RISCV_REG_F0_64, "ft0" },
56
  { RISCV_REG_F1_32, "ft1" },
57
  { RISCV_REG_F1_64, "ft1" },
58
  { RISCV_REG_F2_32, "ft2" },
59
  { RISCV_REG_F2_64, "ft2" },
60
  { RISCV_REG_F3_32, "ft3" },
61
  { RISCV_REG_F3_64, "ft3" },
62
  { RISCV_REG_F4_32, "ft4" },
63
  { RISCV_REG_F4_64, "ft4" },
64
  { RISCV_REG_F5_32, "ft5" },
65
  { RISCV_REG_F5_64, "ft5" },
66
  { RISCV_REG_F6_32, "ft6" },
67
  { RISCV_REG_F6_64, "ft6" },
68
  { RISCV_REG_F7_32, "ft7" },
69
  { RISCV_REG_F7_64, "ft7" },
70
  { RISCV_REG_F8_32, "fs0" },
71
  { RISCV_REG_F8_64, "fs0" },
72
  { RISCV_REG_F9_32, "fs1" },
73
  { RISCV_REG_F9_64, "fs1" },
74
  { RISCV_REG_F10_32, "fa0" },
75
  { RISCV_REG_F10_64, "fa0" },
76
  { RISCV_REG_F11_32, "fa1" },
77
  { RISCV_REG_F11_64, "fa1" },
78
  { RISCV_REG_F12_32, "fa2" },
79
  { RISCV_REG_F12_64, "fa2" },
80
  { RISCV_REG_F13_32, "fa3" },
81
  { RISCV_REG_F13_64, "fa3" },
82
  { RISCV_REG_F14_32, "fa4" },
83
  { RISCV_REG_F14_64, "fa4" },
84
  { RISCV_REG_F15_32, "fa5" },
85
  { RISCV_REG_F15_64, "fa5" },
86
  { RISCV_REG_F16_32, "fa6" },
87
  { RISCV_REG_F16_64, "fa6" },
88
  { RISCV_REG_F17_32, "fa7" },
89
  { RISCV_REG_F17_64, "fa7" },
90
  { RISCV_REG_F18_32, "fs2" },
91
  { RISCV_REG_F18_64, "fs2" },
92
  { RISCV_REG_F19_32, "fs3" },
93
  { RISCV_REG_F19_64, "fs3" },
94
  { RISCV_REG_F20_32, "fs4" },
95
  { RISCV_REG_F20_64, "fs4" },
96
  { RISCV_REG_F21_32, "fs5" },
97
  { RISCV_REG_F21_64, "fs5" },
98
  { RISCV_REG_F22_32, "fs6" },
99
  { RISCV_REG_F22_64, "fs6" },
100
  { RISCV_REG_F23_32, "fs7" },
101
  { RISCV_REG_F23_64, "fs7" },
102
  { RISCV_REG_F24_32, "fs8" },
103
  { RISCV_REG_F24_64, "fs8" },
104
  { RISCV_REG_F25_32, "fs9" },
105
  { RISCV_REG_F25_64, "fs9" },
106
  { RISCV_REG_F26_32, "fs10" },
107
  { RISCV_REG_F26_64, "fs10" },
108
  { RISCV_REG_F27_32, "fs11" },
109
  { RISCV_REG_F27_64, "fs11" },
110
  { RISCV_REG_F28_32, "ft8" },
111
  { RISCV_REG_F28_64, "ft8" },
112
  { RISCV_REG_F29_32, "ft9" },
113
  { RISCV_REG_F29_64, "ft9" },
114
  { RISCV_REG_F30_32, "ft10" },
115
  { RISCV_REG_F30_64, "ft10" },
116
  { RISCV_REG_F31_32, "ft11" },
117
  { RISCV_REG_F31_64, "ft11" },
118
};
119
#endif
120
121
const char *RISCV_reg_name(csh handle, unsigned int reg)
122
0
{
123
0
#ifndef CAPSTONE_DIET
124
0
  if (reg >= RISCV_REG_ENDING)
125
0
    return NULL;
126
0
  return reg_name_maps[reg].name;
127
#else
128
  return NULL;
129
#endif
130
0
}
131
132
static const insn_map insns[] = {
133
  // dummy item
134
  {
135
   0, 0,
136
#ifndef CAPSTONE_DIET
137
   {0}, {0}, {0}, 0, 0
138
#endif
139
   },
140
141
#include "RISCVMappingInsn.inc"
142
};
143
144
#ifndef CAPSTONE_DIET
145
146
static const map_insn_ops insn_operands[] = {
147
#include "RISCVMappingInsnOp.inc"
148
};
149
150
#endif
151
152
157k
void RISCV_add_cs_detail(MCInst *MI, unsigned OpNum) {
153
157k
  if (!detail_is_set(MI))
154
0
    return;
155
156
157k
  cs_op_type op_type = map_get_op_type(MI, OpNum);
157
158
157k
  if (op_type == CS_OP_IMM) {
159
24.8k
    RISCV_get_detail_op(MI, 0)->type = RISCV_OP_IMM;
160
24.8k
    RISCV_get_detail_op(MI, 0)->imm = MCInst_getOpVal(MI, OpNum);
161
24.8k
    RISCV_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
162
24.8k
    RISCV_inc_op_count(MI);
163
24.8k
  }
164
132k
  else if (op_type == CS_OP_REG) {
165
132k
    RISCV_get_detail_op(MI, 0)->type = RISCV_OP_REG;
166
132k
    RISCV_get_detail_op(MI, 0)->reg = MCInst_getOpVal(MI, OpNum);
167
132k
    RISCV_get_detail_op(MI, 0)->access = map_get_op_access(MI, OpNum);
168
132k
    RISCV_inc_op_count(MI);
169
132k
  }
170
0
  else {
171
0
    CS_ASSERT(0 && "Op type not handled.");
172
0
  }
173
157k
}
174
175
// given internal insn id, return public instruction info
176
void RISCV_get_insn_id(cs_struct * h, cs_insn * insn, unsigned int id) 
177
95.2k
{
178
95.2k
    unsigned int i;
179
180
95.2k
    i = insn_find(insns, ARR_SIZE(insns), id, &h->insn_cache);
181
95.2k
    if (i != 0) {
182
95.2k
        insn->id = insns[i].mapid;
183
184
95.2k
        if (h->detail_opt) {
185
95.2k
#ifndef CAPSTONE_DIET
186
95.2k
            memcpy(insn->detail->regs_read,
187
95.2k
            insns[i].regs_use, sizeof(insns[i].regs_use));
188
95.2k
            insn->detail->regs_read_count = (uint8_t)count_positive(insns[i].regs_use);
189
190
95.2k
            memcpy(insn->detail->regs_write, insns[i].regs_mod, sizeof(insns[i].regs_mod));
191
95.2k
            insn->detail->regs_write_count = (uint8_t)count_positive(insns[i].regs_mod);
192
193
95.2k
          memcpy(insn->detail->groups, insns[i].groups, sizeof(insns[i].groups));
194
95.2k
            insn->detail->groups_count = (uint8_t)count_positive8(insns[i].groups);
195
196
95.2k
            if (insns[i].branch || insns[i].indirect_branch) {
197
              // this insn also belongs to JUMP group. add JUMP group
198
2.64k
              insn->detail->groups[insn->detail->groups_count] = RISCV_GRP_JUMP;
199
2.64k
              insn->detail->groups_count++;
200
2.64k
            }
201
95.2k
#endif
202
95.2k
        }
203
95.2k
    }
204
95.2k
}
205
206
static const name_map insn_name_maps[] = {
207
    {RISCV_INS_INVALID, NULL},
208
209
#include "RISCVGenInsnNameMaps.inc"
210
};
211
212
const char *RISCV_insn_name(csh handle, unsigned int id) 
213
95.2k
{
214
95.2k
#ifndef CAPSTONE_DIET
215
95.2k
    if (id >= RISCV_INS_ENDING)
216
0
        return NULL;
217
218
95.2k
    return insn_name_maps[id].name;
219
#else
220
    return NULL;
221
#endif
222
95.2k
}
223
224
#ifndef CAPSTONE_DIET
225
static const name_map group_name_maps[] = {
226
    // generic groups
227
    { RISCV_GRP_INVALID,    NULL },
228
    { RISCV_GRP_JUMP,       "jump" },
229
    { RISCV_GRP_CALL,       "call" },
230
    { RISCV_GRP_RET,        "ret" },
231
    { RISCV_GRP_INT,        "int" },
232
    { RISCV_GRP_IRET,       "iret" },
233
    { RISCV_GRP_PRIVILEGE,  "privileged" },
234
    { RISCV_GRP_BRANCH_RELATIVE, "branch_relative" },
235
  
236
    // architecture specific
237
    { RISCV_GRP_ISRV32,     "isrv32" },
238
    { RISCV_GRP_ISRV64,     "isrv64" },
239
    { RISCV_GRP_HASSTDEXTA, "hasStdExtA" },
240
    { RISCV_GRP_HASSTDEXTC, "hasStdExtC" },
241
    { RISCV_GRP_HASSTDEXTD, "hasStdExtD" },
242
    { RISCV_GRP_HASSTDEXTF, "hasStdExtF" },
243
    { RISCV_GRP_HASSTDEXTM, "hasStdExtM" },
244
  
245
    /*
246
    { RISCV_GRP_ISRVA,      "isrva" },
247
    { RISCV_GRP_ISRVC,      "isrvc" },
248
    { RISCV_GRP_ISRVD,      "isrvd" },
249
    { RISCV_GRP_ISRVCD,     "isrvcd" },
250
    { RISCV_GRP_ISRVF,      "isrvf" },
251
    { RISCV_GRP_ISRV32C,    "isrv32c" },
252
    { RISCV_GRP_ISRV32CF,   "isrv32cf" },
253
    { RISCV_GRP_ISRVM,      "isrvm" },
254
    { RISCV_GRP_ISRV64A,    "isrv64a" },
255
    { RISCV_GRP_ISRV64C,    "isrv64c" },
256
    { RISCV_GRP_ISRV64D,    "isrv64d" },
257
    { RISCV_GRP_ISRV64F,    "isrv64f" },
258
    { RISCV_GRP_ISRV64M,    "isrv64m" }
259
    */
260
    { RISCV_GRP_ENDING,     NULL }
261
};
262
#endif
263
264
const char *RISCV_group_name(csh handle, unsigned int id)
265
42.2k
{
266
42.2k
#ifndef CAPSTONE_DIET
267
  // verify group id
268
42.2k
  if (id >= RISCV_GRP_ENDING || 
269
42.2k
            (id > RISCV_GRP_BRANCH_RELATIVE && id < RISCV_GRP_ISRV32))
270
0
    return NULL;
271
42.2k
  return id2name(group_name_maps, ARR_SIZE(group_name_maps), id);
272
#else
273
  return NULL;
274
#endif
275
42.2k
}
276
277
// map instruction name to public instruction ID
278
riscv_reg RISCV_map_insn(const char *name)
279
0
{
280
  // handle special alias first
281
0
  unsigned int i;
282
283
  // NOTE: skip first NULL name in insn_name_maps
284
0
  i = name2id(&insn_name_maps[1], ARR_SIZE(insn_name_maps) - 1, name);
285
286
0
  return (i != -1) ? i : RISCV_REG_INVALID;
287
0
}
288
289
// map internal raw register to 'public' register
290
riscv_reg RISCV_map_register(unsigned int r)
291
0
{
292
0
  static const unsigned int map[] = { 0,
293
0
    RISCV_REG_X0,
294
0
    RISCV_REG_X1,
295
0
    RISCV_REG_X2,
296
0
    RISCV_REG_X3,
297
0
    RISCV_REG_X4,
298
0
    RISCV_REG_X5,
299
0
    RISCV_REG_X6,
300
0
    RISCV_REG_X7,
301
0
    RISCV_REG_X8,
302
0
    RISCV_REG_X9,
303
0
    RISCV_REG_X10,
304
0
    RISCV_REG_X11,
305
0
    RISCV_REG_X12,
306
0
    RISCV_REG_X13,
307
0
    RISCV_REG_X14,
308
0
    RISCV_REG_X15,
309
0
    RISCV_REG_X16,
310
0
    RISCV_REG_X17,
311
0
    RISCV_REG_X18,
312
0
    RISCV_REG_X19,
313
0
    RISCV_REG_X20,
314
0
    RISCV_REG_X21,
315
0
    RISCV_REG_X22,
316
0
    RISCV_REG_X23,
317
0
    RISCV_REG_X24,
318
0
    RISCV_REG_X25,
319
0
    RISCV_REG_X26,
320
0
    RISCV_REG_X27,
321
0
    RISCV_REG_X28,
322
0
    RISCV_REG_X29,
323
0
    RISCV_REG_X30,
324
0
    RISCV_REG_X31,
325
326
0
    RISCV_REG_F0_32,
327
0
    RISCV_REG_F0_64,
328
0
    RISCV_REG_F1_32,
329
0
    RISCV_REG_F1_64,
330
0
    RISCV_REG_F2_32,
331
0
    RISCV_REG_F2_64,
332
0
    RISCV_REG_F3_32,
333
0
    RISCV_REG_F3_64,
334
0
    RISCV_REG_F4_32,
335
0
    RISCV_REG_F4_64,
336
0
    RISCV_REG_F5_32,
337
0
    RISCV_REG_F5_64,
338
0
    RISCV_REG_F6_32,
339
0
    RISCV_REG_F6_64,
340
0
    RISCV_REG_F7_32,
341
0
    RISCV_REG_F7_64,
342
0
    RISCV_REG_F8_32,
343
0
    RISCV_REG_F8_64,
344
0
    RISCV_REG_F9_32,
345
0
    RISCV_REG_F9_64,
346
0
    RISCV_REG_F10_32,
347
0
    RISCV_REG_F10_64,
348
0
    RISCV_REG_F11_32,
349
0
    RISCV_REG_F11_64,
350
0
    RISCV_REG_F12_32,
351
0
    RISCV_REG_F12_64,
352
0
    RISCV_REG_F13_32,
353
0
    RISCV_REG_F13_64,
354
0
    RISCV_REG_F14_32,
355
0
    RISCV_REG_F14_64,
356
0
    RISCV_REG_F15_32,
357
0
    RISCV_REG_F15_64,
358
0
    RISCV_REG_F16_32,
359
0
    RISCV_REG_F16_64,
360
0
    RISCV_REG_F17_32,
361
0
    RISCV_REG_F17_64,
362
0
    RISCV_REG_F18_32,
363
0
    RISCV_REG_F18_64,
364
0
    RISCV_REG_F19_32,
365
0
    RISCV_REG_F19_64,
366
0
    RISCV_REG_F20_32,
367
0
    RISCV_REG_F20_64,
368
0
    RISCV_REG_F21_32,
369
0
    RISCV_REG_F21_64,
370
0
    RISCV_REG_F22_32,
371
0
    RISCV_REG_F22_64,
372
0
    RISCV_REG_F23_32,
373
0
    RISCV_REG_F23_64,
374
0
    RISCV_REG_F24_32,
375
0
    RISCV_REG_F24_64,
376
0
    RISCV_REG_F25_32,
377
0
    RISCV_REG_F25_64,
378
0
    RISCV_REG_F26_32,
379
0
    RISCV_REG_F26_64,
380
0
    RISCV_REG_F27_32,
381
0
    RISCV_REG_F27_64,
382
0
    RISCV_REG_F28_32,
383
0
    RISCV_REG_F28_64,
384
0
    RISCV_REG_F29_32,
385
0
    RISCV_REG_F29_64,
386
0
    RISCV_REG_F30_32,
387
0
    RISCV_REG_F30_64,
388
0
    RISCV_REG_F31_32,
389
0
    RISCV_REG_F31_64,
390
0
  };
391
392
0
  if (r < ARR_SIZE(map))
393
0
    return map[r];
394
395
  // cannot find this register
396
0
  return 0;
397
0
}
398
399
#endif