Coverage Report

Created: 2025-08-28 06:43

/src/capstonenext/arch/RISCV/RISCVDisassembler.c
Line
Count
Source (jump to first uncovered line)
1
//===-- RISCVDisassembler.cpp - Disassembler for RISCV --------------------===//
2
//
3
//                     The LLVM Compiler Infrastructure
4
//
5
// This file is distributed under the University of Illinois Open Source
6
// License. See LICENSE.TXT for details.
7
//
8
//===----------------------------------------------------------------------===//
9
10
/* Capstone Disassembly Engine */
11
/* RISC-V Backend By Rodrigo Cortes Porto <porto703@gmail.com> & 
12
   Shawn Chang <citypw@gmail.com>, HardenedLinux@2018 */
13
14
#ifdef CAPSTONE_HAS_RISCV
15
16
#include <stdio.h> // DEBUG
17
#include <stdlib.h>
18
#include <string.h>
19
20
#include "../../cs_priv.h"
21
#include "../../utils.h"
22
23
#include "../../MCInst.h"
24
#include "../../MCInstrDesc.h"
25
#include "../../MCFixedLenDisassembler.h"
26
#include "../../MCRegisterInfo.h"
27
#include "../../MCDisassembler.h"
28
#include "../../MathExtras.h"
29
#include "../../Mapping.h"
30
#include "RISCVBaseInfo.h"
31
#include "RISCVDisassembler.h"
32
33
/* Need the feature infos define in 
34
  RISCVGenSubtargetInfo.inc. */
35
#define GET_SUBTARGETINFO_ENUM
36
#include "RISCVGenSubtargetInfo.inc"
37
38
/* When we specify the RISCV64 mode, It means It is RV64IMAFD.
39
  Similar, RISCV32 means RV32IMAFD.
40
*/
41
static uint64_t getFeatureBits(int mode)
42
190k
{
43
190k
  uint64_t ret = RISCV_FeatureStdExtM | RISCV_FeatureStdExtA |
44
190k
           RISCV_FeatureStdExtF | RISCV_FeatureStdExtD;
45
46
190k
  if (mode & CS_MODE_RISCV64)
47
110k
    ret |= RISCV_Feature64Bit;
48
190k
  if (mode & CS_MODE_RISCVC)
49
0
    ret |= RISCV_FeatureStdExtC;
50
51
190k
  return ret;
52
190k
}
53
54
#define GET_REGINFO_ENUM
55
#define GET_REGINFO_MC_DESC
56
#include "RISCVGenRegisterInfo.inc"
57
#define GET_INSTRINFO_ENUM
58
#include "RISCVGenInstrInfo.inc"
59
60
static const unsigned GPRDecoderTable[] = {
61
  RISCV_X0,  RISCV_X1,  RISCV_X2,  RISCV_X3,  RISCV_X4,  RISCV_X5,
62
  RISCV_X6,  RISCV_X7,  RISCV_X8,  RISCV_X9,  RISCV_X10, RISCV_X11,
63
  RISCV_X12, RISCV_X13, RISCV_X14, RISCV_X15, RISCV_X16, RISCV_X17,
64
  RISCV_X18, RISCV_X19, RISCV_X20, RISCV_X21, RISCV_X22, RISCV_X23,
65
  RISCV_X24, RISCV_X25, RISCV_X26, RISCV_X27, RISCV_X28, RISCV_X29,
66
  RISCV_X30, RISCV_X31
67
};
68
69
static DecodeStatus DecodeGPRRegisterClass(MCInst *Inst, uint64_t RegNo,
70
             uint64_t Address,
71
             const void *Decoder)
72
249k
{
73
249k
  unsigned Reg = 0;
74
75
249k
  if (RegNo >= ARR_SIZE(GPRDecoderTable))
76
0
    return MCDisassembler_Fail;
77
78
  // We must define our own mapping from RegNo to register identifier.
79
  // Accessing index RegNo in the register class will work in the case that
80
  // registers were added in ascending order, but not in general.
81
249k
  Reg = GPRDecoderTable[RegNo];
82
  //Inst.addOperand(MCOperand::createReg(Reg));
83
249k
  MCOperand_CreateReg0(Inst, Reg);
84
249k
  return MCDisassembler_Success;
85
249k
}
86
87
static const unsigned FPR32DecoderTable[] = {
88
  RISCV_F0_32,  RISCV_F1_32,  RISCV_F2_32,  RISCV_F3_32,  RISCV_F4_32,
89
  RISCV_F5_32,  RISCV_F6_32,  RISCV_F7_32,  RISCV_F8_32,  RISCV_F9_32,
90
  RISCV_F10_32, RISCV_F11_32, RISCV_F12_32, RISCV_F13_32, RISCV_F14_32,
91
  RISCV_F15_32, RISCV_F16_32, RISCV_F17_32, RISCV_F18_32, RISCV_F19_32,
92
  RISCV_F20_32, RISCV_F21_32, RISCV_F22_32, RISCV_F23_32, RISCV_F24_32,
93
  RISCV_F25_32, RISCV_F26_32, RISCV_F27_32, RISCV_F28_32, RISCV_F29_32,
94
  RISCV_F30_32, RISCV_F31_32
95
};
96
97
static DecodeStatus DecodeFPR32RegisterClass(MCInst *Inst, uint64_t RegNo,
98
               uint64_t Address,
99
               const void *Decoder)
100
66.1k
{
101
66.1k
  unsigned Reg = 0;
102
103
66.1k
  if (RegNo >= ARR_SIZE(FPR32DecoderTable))
104
0
    return MCDisassembler_Fail;
105
106
  // We must define our own mapping from RegNo to register identifier.
107
  // Accessing index RegNo in the register class will work in the case that
108
  // registers were added in ascending order, but not in general.
109
66.1k
  Reg = FPR32DecoderTable[RegNo];
110
66.1k
  MCOperand_CreateReg0(Inst, Reg);
111
66.1k
  return MCDisassembler_Success;
112
66.1k
}
113
114
static DecodeStatus DecodeFPR32CRegisterClass(MCInst *Inst, uint64_t RegNo,
115
                uint64_t Address,
116
                const void *Decoder)
117
0
{
118
0
  unsigned Reg = 0;
119
120
0
  if (RegNo > 8)
121
0
    return MCDisassembler_Fail;
122
0
  Reg = FPR32DecoderTable[RegNo + 8];
123
0
  MCOperand_CreateReg0(Inst, Reg);
124
0
  return MCDisassembler_Success;
125
0
}
126
127
static const unsigned FPR64DecoderTable[] = {
128
  RISCV_F0_64,  RISCV_F1_64,  RISCV_F2_64,  RISCV_F3_64,  RISCV_F4_64,
129
  RISCV_F5_64,  RISCV_F6_64,  RISCV_F7_64,  RISCV_F8_64,  RISCV_F9_64,
130
  RISCV_F10_64, RISCV_F11_64, RISCV_F12_64, RISCV_F13_64, RISCV_F14_64,
131
  RISCV_F15_64, RISCV_F16_64, RISCV_F17_64, RISCV_F18_64, RISCV_F19_64,
132
  RISCV_F20_64, RISCV_F21_64, RISCV_F22_64, RISCV_F23_64, RISCV_F24_64,
133
  RISCV_F25_64, RISCV_F26_64, RISCV_F27_64, RISCV_F28_64, RISCV_F29_64,
134
  RISCV_F30_64, RISCV_F31_64
135
};
136
137
static DecodeStatus DecodeFPR64RegisterClass(MCInst *Inst, uint64_t RegNo,
138
               uint64_t Address,
139
               const void *Decoder)
140
44.5k
{
141
44.5k
  unsigned Reg = 0;
142
143
44.5k
  if (RegNo >= ARR_SIZE(FPR64DecoderTable))
144
0
    return MCDisassembler_Fail;
145
146
  // We must define our own mapping from RegNo to register identifier.
147
  // Accessing index RegNo in the register class will work in the case that
148
  // registers were added in ascending order, but not in general.
149
44.5k
  Reg = FPR64DecoderTable[RegNo];
150
44.5k
  MCOperand_CreateReg0(Inst, Reg);
151
44.5k
  return MCDisassembler_Success;
152
44.5k
}
153
154
static DecodeStatus DecodeFPR64CRegisterClass(MCInst *Inst, uint64_t RegNo,
155
                uint64_t Address,
156
                const void *Decoder)
157
0
{
158
0
  unsigned Reg = 0;
159
160
0
  if (RegNo > 8)
161
0
    return MCDisassembler_Fail;
162
0
  Reg = FPR64DecoderTable[RegNo + 8];
163
0
  MCOperand_CreateReg0(Inst, Reg);
164
0
  return MCDisassembler_Success;
165
0
}
166
167
static DecodeStatus DecodeGPRNoX0RegisterClass(MCInst *Inst, uint64_t RegNo,
168
                 uint64_t Address,
169
                 const void *Decoder)
170
0
{
171
0
  if (RegNo == 0)
172
0
    return MCDisassembler_Fail;
173
0
  return DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder);
174
0
}
175
176
static DecodeStatus DecodeGPRNoX0X2RegisterClass(MCInst *Inst, uint64_t RegNo,
177
             uint64_t Address,
178
             const void *Decoder)
179
0
{
180
0
  if (RegNo == 2)
181
0
    return MCDisassembler_Fail;
182
0
  return DecodeGPRNoX0RegisterClass(Inst, RegNo, Address, Decoder);
183
0
}
184
185
static DecodeStatus DecodeGPRCRegisterClass(MCInst *Inst, uint64_t RegNo,
186
              uint64_t Address,
187
              const void *Decoder)
188
0
{
189
0
  unsigned Reg = 0;
190
191
0
  if (RegNo > 8)
192
0
    return MCDisassembler_Fail;
193
194
0
  Reg = GPRDecoderTable[RegNo + 8];
195
0
  MCOperand_CreateReg0(Inst, Reg);
196
0
  return MCDisassembler_Success;
197
0
}
198
199
// Add implied SP operand for instructions *SP compressed instructions. The SP
200
// operand isn't explicitly encoded in the instruction.
201
static void addImplySP(MCInst *Inst, int64_t Address, const void *Decoder)
202
166k
{
203
166k
  if (MCInst_getOpcode(Inst) == RISCV_C_LWSP ||
204
166k
      MCInst_getOpcode(Inst) == RISCV_C_SWSP ||
205
166k
      MCInst_getOpcode(Inst) == RISCV_C_LDSP ||
206
166k
      MCInst_getOpcode(Inst) == RISCV_C_SDSP ||
207
166k
      MCInst_getOpcode(Inst) == RISCV_C_FLWSP ||
208
166k
      MCInst_getOpcode(Inst) == RISCV_C_FSWSP ||
209
166k
      MCInst_getOpcode(Inst) == RISCV_C_FLDSP ||
210
166k
      MCInst_getOpcode(Inst) == RISCV_C_FSDSP ||
211
166k
      MCInst_getOpcode(Inst) == RISCV_C_ADDI4SPN) {
212
0
    DecodeGPRRegisterClass(Inst, 2, Address, Decoder);
213
0
  }
214
215
166k
  if (MCInst_getOpcode(Inst) == RISCV_C_ADDI16SP) {
216
0
    DecodeGPRRegisterClass(Inst, 2, Address, Decoder);
217
0
    DecodeGPRRegisterClass(Inst, 2, Address, Decoder);
218
0
  }
219
166k
}
220
221
static DecodeStatus decodeUImmOperand(MCInst *Inst, uint64_t Imm,
222
              int64_t Address, const void *Decoder,
223
              unsigned N)
224
155k
{
225
  //CS_ASSERT(isUInt<N>(Imm) && "Invalid immediate");
226
155k
  addImplySP(Inst, Address, Decoder);
227
  //Inst.addOperand(MCOperand::createImm(Imm));
228
155k
  MCOperand_CreateImm0(Inst, Imm);
229
155k
  return MCDisassembler_Success;
230
155k
}
231
232
static DecodeStatus decodeUImmNonZeroOperand(MCInst *Inst, uint64_t Imm,
233
               int64_t Address,
234
               const void *Decoder, unsigned N)
235
0
{
236
0
  if (Imm == 0)
237
0
    return MCDisassembler_Fail;
238
0
  return decodeUImmOperand(Inst, Imm, Address, Decoder, N);
239
0
}
240
241
static DecodeStatus decodeSImmOperand(MCInst *Inst, uint64_t Imm,
242
              int64_t Address, const void *Decoder,
243
              unsigned N)
244
10.8k
{
245
  //CS_ASSERT(isUInt<N>(Imm) && "Invalid immediate");
246
10.8k
  addImplySP(Inst, Address, Decoder);
247
  // Sign-extend the number in the bottom N bits of Imm
248
  //Inst.addOperand(MCOperand::createImm(SignExtend64<N>(Imm)));
249
10.8k
  MCOperand_CreateImm0(Inst, SignExtend64(Imm, N));
250
10.8k
  return MCDisassembler_Success;
251
10.8k
}
252
253
static DecodeStatus decodeSImmNonZeroOperand(MCInst *Inst, uint64_t Imm,
254
               int64_t Address,
255
               const void *Decoder, unsigned N)
256
0
{
257
0
  if (Imm == 0)
258
0
    return MCDisassembler_Fail;
259
0
  return decodeSImmOperand(Inst, Imm, Address, Decoder, N);
260
0
}
261
262
static DecodeStatus decodeSImmOperandAndLsl1(MCInst *Inst, uint64_t Imm,
263
               int64_t Address,
264
               const void *Decoder, unsigned N)
265
5.59k
{
266
  //CS_ASSERT(isUInt<N>(Imm) && "Invalid immediate");
267
  // Sign-extend the number in the bottom N bits of Imm after accounting for
268
  // the fact that the N bit immediate is stored in N-1 bits (the LSB is
269
  // always zero)
270
  //Inst.addOperand(MCOperand::createImm(SignExtend64<N>(Imm << 1)));
271
5.59k
  MCOperand_CreateImm0(Inst, SignExtend64(Imm << 1, N));
272
5.59k
  return MCDisassembler_Success;
273
5.59k
}
274
275
static DecodeStatus decodeCLUIImmOperand(MCInst *Inst, uint64_t Imm,
276
           int64_t Address, const void *Decoder)
277
0
{
278
  //CS_ASSERT(isUInt<6>(Imm) && "Invalid immediate");
279
0
  if (Imm > 31) {
280
0
    Imm = (SignExtend64(Imm, 6) & 0xfffff);
281
0
  }
282
  //Inst.addOperand(MCOperand::createImm(Imm));
283
0
  MCOperand_CreateImm0(Inst, Imm);
284
0
  return MCDisassembler_Success;
285
0
}
286
287
static DecodeStatus decodeFRMArg(MCInst *Inst, uint64_t Imm, int64_t Address,
288
         const void *Decoder)
289
35.0k
{
290
  //CS_ASSERT(isUInt<3>(Imm) && "Invalid immediate");
291
35.0k
  if (!RISCVFPRndMode_isValidRoundingMode(Imm))
292
39
    return MCDisassembler_Fail;
293
294
  //Inst.addOperand(MCOperand::createImm(Imm));
295
35.0k
  MCOperand_CreateImm0(Inst, Imm);
296
35.0k
  return MCDisassembler_Success;
297
35.0k
}
298
299
#include "RISCVGenDisassemblerTables.inc"
300
301
static void init_MI_insn_detail(MCInst *MI)
302
188k
{
303
188k
  if (MI->flat_insn->detail) {
304
188k
    memset(MI->flat_insn->detail, 0, sizeof(cs_detail));
305
188k
  }
306
307
188k
  return;
308
188k
}
309
310
// mark the load/store instructions through the opcode.
311
static void markLSInsn(MCInst *MI, uint32_t in)
312
71.5k
{
313
  /* 
314
     I   ld 0000011 = 0x03
315
         st 0100011 = 0x23
316
     F/D ld 0000111 = 0x07
317
         st 0100111 = 0x27
318
         st 0101111 = 0x2f
319
  */
320
71.5k
#define MASK_LS_INSN 0x0000007f
321
71.5k
  uint32_t opcode = in & MASK_LS_INSN;
322
71.5k
  if (0 == (opcode ^ 0x03) || 0 == (opcode ^ 0x07) ||
323
71.5k
      0 == (opcode ^ 0x23) || 0 == (opcode ^ 0x27) ||
324
71.5k
      0 == (opcode ^ 0x2f))
325
11.9k
    MI->flat_insn->detail->riscv.need_effective_addr = true;
326
71.5k
#undef MASK_LS_INSN
327
71.5k
  return;
328
71.5k
}
329
330
static void markCLSInsn(MCInst *MI, uint32_t in)
331
719
{
332
  // Unfortunately there is no obvious pattern in terms of RISC-V C instructions
333
  // Thus, we compare the instruction IDs to see if it is a load/store instruction
334
719
  unsigned id = MCInst_getOpcode(MI);
335
719
  if (id == RISCV_C_FLD || id == RISCV_C_LW || id == RISCV_C_FLW ||
336
719
      id == RISCV_C_LD || id == RISCV_C_FSD || id == RISCV_C_SW ||
337
719
      id == RISCV_C_FSW || id == RISCV_C_SD || id == RISCV_C_FLDSP ||
338
719
      id == RISCV_C_LWSP || id == RISCV_C_FLWSP || id == RISCV_C_LDSP ||
339
719
      id == RISCV_C_FSDSP || id == RISCV_C_SWSP || id == RISCV_C_FSWSP ||
340
719
      id == RISCV_C_SDSP) {
341
0
    RISCV_get_detail(MI)->need_effective_addr = true;
342
0
  }
343
719
  return;
344
719
}
345
346
static DecodeStatus
347
RISCVDisassembler_getInstruction(int mode, MCInst *MI, const uint8_t *code,
348
         size_t code_len, uint16_t *Size,
349
         uint64_t Address, MCRegisterInfo *MRI)
350
72.9k
{
351
  // TODO: This will need modification when supporting instruction set
352
  // extensions with instructions > 32-bits (up to 176 bits wide).
353
72.9k
  uint32_t Inst = 0;
354
72.9k
  DecodeStatus Result;
355
356
  // It's a 32 bit instruction if bit 0 and 1 are 1.
357
72.9k
  if ((code[0] & 0x3) == 0x3) {
358
72.0k
    if (code_len < 4) {
359
473
      *Size = 0;
360
473
      return MCDisassembler_Fail;
361
473
    }
362
363
71.5k
    *Size = 4;
364
    // Get the four bytes of the instruction.
365
    //Encoded as little endian 32 bits.
366
71.5k
    Inst = code[0] | (code[1] << 8) | (code[2] << 16) |
367
71.5k
           ((uint32_t)code[3] << 24);
368
71.5k
    init_MI_insn_detail(MI);
369
    // Now we need mark what instruction need fix effective address output.
370
71.5k
    if (MI->csh->detail_opt)
371
71.5k
      markLSInsn(MI, Inst);
372
71.5k
    Result = decodeInstruction(DecoderTable32, MI, Inst, Address,
373
71.5k
             MRI, mode);
374
71.5k
  } else {
375
960
    if (code_len < 2) {
376
241
      *Size = 0;
377
241
      return MCDisassembler_Fail;
378
241
    }
379
380
    // If not b4bit.
381
719
    if (!(getFeatureBits(mode) & ((uint64_t)RISCV_Feature64Bit))) {
382
      // Trying RISCV32Only_16 table (16-bit Instruction)
383
317
      Inst = code[0] | (code[1] << 8);
384
317
      init_MI_insn_detail(MI);
385
317
      Result = decodeInstruction(DecoderTableRISCV32Only_16,
386
317
               MI, Inst, Address, MRI,
387
317
               mode);
388
317
      if (Result != MCDisassembler_Fail) {
389
0
        *Size = 2;
390
0
        return Result;
391
0
      }
392
317
    }
393
394
    // Trying RISCV_C table (16-bit Instruction)
395
719
    Inst = code[0] | (code[1] << 8);
396
719
    init_MI_insn_detail(MI);
397
    // Calling the auto-generated decoder function.
398
719
    Result = decodeInstruction(DecoderTable16, MI, Inst, Address,
399
719
             MRI, mode);
400
    // Now we need mark what instruction need fix effective address output.
401
    // Note that we mark it AFTER the instruction is decoded
402
    // This is because there is no obvious pattern in terms of RISC-V C instructions
403
    // So we compare the instruction IDs one by one
404
719
    if (detail_is_set(MI))
405
719
      markCLSInsn(MI, Inst);
406
719
    *Size = 2;
407
719
  }
408
409
72.2k
  return Result;
410
72.9k
}
411
412
bool RISCV_getInstruction(csh ud, const uint8_t *code, size_t code_len,
413
        MCInst *instr, uint16_t *size, uint64_t address,
414
        void *info)
415
72.9k
{
416
72.9k
  cs_struct *handle = (cs_struct *)(uintptr_t)ud;
417
418
72.9k
  DecodeStatus Result = RISCVDisassembler_getInstruction(
419
72.9k
    handle->mode, instr, code, code_len, size, address,
420
72.9k
    (MCRegisterInfo *)info);
421
72.9k
  if (Result == MCDisassembler_SoftFail) {
422
0
    MCInst_setSoftFail(instr);
423
0
  }
424
72.9k
  return Result != MCDisassembler_Fail;
425
72.9k
}
426
427
void RISCV_init(MCRegisterInfo *MRI)
428
5.75k
{
429
  /*
430
    InitMCRegisterInfo(RISCVRegDesc, 97, RA, PC,
431
                     RISCVMCRegisterClasses, 11,
432
                     RISCVRegUnitRoots,
433
                     64,
434
                     RISCVRegDiffLists,
435
                     RISCVLaneMaskLists,
436
                     RISCVRegStrings,
437
                     RISCVRegClassStrings,
438
                     RISCVSubRegIdxLists,
439
                     2,
440
                     RISCVSubRegIdxRanges,
441
                     RISCVRegEncodingTable);
442
    */
443
444
5.75k
  MCRegisterInfo_InitMCRegisterInfo(MRI, RISCVRegDesc, 97, 0, 0,
445
5.75k
            RISCVMCRegisterClasses, 11, 0, 0,
446
5.75k
            RISCVRegDiffLists, 0,
447
5.75k
            RISCVSubRegIdxLists, 2, 0);
448
5.75k
}
449
450
#endif