Coverage Report

Created: 2024-08-21 06:24

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