Coverage Report

Created: 2025-08-28 06:43

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