• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- RISCVDisassembler.cpp - Disassembler for RISCV --------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements the RISCVDisassembler class.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "MCTargetDesc/RISCVMCTargetDesc.h"
14 #include "TargetInfo/RISCVTargetInfo.h"
15 #include "Utils/RISCVBaseInfo.h"
16 #include "llvm/CodeGen/Register.h"
17 #include "llvm/MC/MCContext.h"
18 #include "llvm/MC/MCDisassembler/MCDisassembler.h"
19 #include "llvm/MC/MCFixedLenDisassembler.h"
20 #include "llvm/MC/MCInst.h"
21 #include "llvm/MC/MCRegisterInfo.h"
22 #include "llvm/MC/MCSubtargetInfo.h"
23 #include "llvm/Support/Endian.h"
24 #include "llvm/Support/TargetRegistry.h"
25 
26 using namespace llvm;
27 
28 #define DEBUG_TYPE "riscv-disassembler"
29 
30 typedef MCDisassembler::DecodeStatus DecodeStatus;
31 
32 namespace {
33 class RISCVDisassembler : public MCDisassembler {
34 
35 public:
RISCVDisassembler(const MCSubtargetInfo & STI,MCContext & Ctx)36   RISCVDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx)
37       : MCDisassembler(STI, Ctx) {}
38 
39   DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
40                               ArrayRef<uint8_t> Bytes, uint64_t Address,
41                               raw_ostream &CStream) const override;
42 };
43 } // end anonymous namespace
44 
createRISCVDisassembler(const Target & T,const MCSubtargetInfo & STI,MCContext & Ctx)45 static MCDisassembler *createRISCVDisassembler(const Target &T,
46                                                const MCSubtargetInfo &STI,
47                                                MCContext &Ctx) {
48   return new RISCVDisassembler(STI, Ctx);
49 }
50 
LLVMInitializeRISCVDisassembler()51 extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVDisassembler() {
52   // Register the disassembler for each target.
53   TargetRegistry::RegisterMCDisassembler(getTheRISCV32Target(),
54                                          createRISCVDisassembler);
55   TargetRegistry::RegisterMCDisassembler(getTheRISCV64Target(),
56                                          createRISCVDisassembler);
57 }
58 
DecodeGPRRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)59 static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint64_t RegNo,
60                                            uint64_t Address,
61                                            const void *Decoder) {
62   const FeatureBitset &FeatureBits =
63       static_cast<const MCDisassembler *>(Decoder)
64           ->getSubtargetInfo()
65           .getFeatureBits();
66   bool IsRV32E = FeatureBits[RISCV::FeatureRV32E];
67 
68   if (RegNo >= 32 || (IsRV32E && RegNo >= 16))
69     return MCDisassembler::Fail;
70 
71   Register Reg = RISCV::X0 + RegNo;
72   Inst.addOperand(MCOperand::createReg(Reg));
73   return MCDisassembler::Success;
74 }
75 
DecodeFPR32RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)76 static DecodeStatus DecodeFPR32RegisterClass(MCInst &Inst, uint64_t RegNo,
77                                              uint64_t Address,
78                                              const void *Decoder) {
79   if (RegNo >= 32)
80     return MCDisassembler::Fail;
81 
82   Register Reg = RISCV::F0_F + RegNo;
83   Inst.addOperand(MCOperand::createReg(Reg));
84   return MCDisassembler::Success;
85 }
86 
DecodeFPR32CRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)87 static DecodeStatus DecodeFPR32CRegisterClass(MCInst &Inst, uint64_t RegNo,
88                                               uint64_t Address,
89                                               const void *Decoder) {
90   if (RegNo >= 8) {
91     return MCDisassembler::Fail;
92   }
93   Register Reg = RISCV::F8_F + RegNo;
94   Inst.addOperand(MCOperand::createReg(Reg));
95   return MCDisassembler::Success;
96 }
97 
DecodeFPR64RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)98 static DecodeStatus DecodeFPR64RegisterClass(MCInst &Inst, uint64_t RegNo,
99                                              uint64_t Address,
100                                              const void *Decoder) {
101   if (RegNo >= 32)
102     return MCDisassembler::Fail;
103 
104   Register Reg = RISCV::F0_D + RegNo;
105   Inst.addOperand(MCOperand::createReg(Reg));
106   return MCDisassembler::Success;
107 }
108 
DecodeFPR64CRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)109 static DecodeStatus DecodeFPR64CRegisterClass(MCInst &Inst, uint64_t RegNo,
110                                               uint64_t Address,
111                                               const void *Decoder) {
112   if (RegNo >= 8) {
113     return MCDisassembler::Fail;
114   }
115   Register Reg = RISCV::F8_D + RegNo;
116   Inst.addOperand(MCOperand::createReg(Reg));
117   return MCDisassembler::Success;
118 }
119 
DecodeGPRNoX0RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)120 static DecodeStatus DecodeGPRNoX0RegisterClass(MCInst &Inst, uint64_t RegNo,
121                                                uint64_t Address,
122                                                const void *Decoder) {
123   if (RegNo == 0) {
124     return MCDisassembler::Fail;
125   }
126 
127   return DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder);
128 }
129 
DecodeGPRNoX0X2RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)130 static DecodeStatus DecodeGPRNoX0X2RegisterClass(MCInst &Inst, uint64_t RegNo,
131                                                  uint64_t Address,
132                                                  const void *Decoder) {
133   if (RegNo == 2) {
134     return MCDisassembler::Fail;
135   }
136 
137   return DecodeGPRNoX0RegisterClass(Inst, RegNo, Address, Decoder);
138 }
139 
DecodeGPRCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const void * Decoder)140 static DecodeStatus DecodeGPRCRegisterClass(MCInst &Inst, uint64_t RegNo,
141                                             uint64_t Address,
142                                             const void *Decoder) {
143   if (RegNo >= 8)
144     return MCDisassembler::Fail;
145 
146   Register Reg = RISCV::X8 + RegNo;
147   Inst.addOperand(MCOperand::createReg(Reg));
148   return MCDisassembler::Success;
149 }
150 
151 // Add implied SP operand for instructions *SP compressed instructions. The SP
152 // operand isn't explicitly encoded in the instruction.
addImplySP(MCInst & Inst,int64_t Address,const void * Decoder)153 static void addImplySP(MCInst &Inst, int64_t Address, const void *Decoder) {
154   if (Inst.getOpcode() == RISCV::C_LWSP || Inst.getOpcode() == RISCV::C_SWSP ||
155       Inst.getOpcode() == RISCV::C_LDSP || Inst.getOpcode() == RISCV::C_SDSP ||
156       Inst.getOpcode() == RISCV::C_FLWSP ||
157       Inst.getOpcode() == RISCV::C_FSWSP ||
158       Inst.getOpcode() == RISCV::C_FLDSP ||
159       Inst.getOpcode() == RISCV::C_FSDSP ||
160       Inst.getOpcode() == RISCV::C_ADDI4SPN) {
161     DecodeGPRRegisterClass(Inst, 2, Address, Decoder);
162   }
163   if (Inst.getOpcode() == RISCV::C_ADDI16SP) {
164     DecodeGPRRegisterClass(Inst, 2, Address, Decoder);
165     DecodeGPRRegisterClass(Inst, 2, Address, Decoder);
166   }
167 }
168 
169 template <unsigned N>
decodeUImmOperand(MCInst & Inst,uint64_t Imm,int64_t Address,const void * Decoder)170 static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm,
171                                       int64_t Address, const void *Decoder) {
172   assert(isUInt<N>(Imm) && "Invalid immediate");
173   addImplySP(Inst, Address, Decoder);
174   Inst.addOperand(MCOperand::createImm(Imm));
175   return MCDisassembler::Success;
176 }
177 
178 template <unsigned N>
decodeUImmNonZeroOperand(MCInst & Inst,uint64_t Imm,int64_t Address,const void * Decoder)179 static DecodeStatus decodeUImmNonZeroOperand(MCInst &Inst, uint64_t Imm,
180                                              int64_t Address,
181                                              const void *Decoder) {
182   if (Imm == 0)
183     return MCDisassembler::Fail;
184   return decodeUImmOperand<N>(Inst, Imm, Address, Decoder);
185 }
186 
187 template <unsigned N>
decodeSImmOperand(MCInst & Inst,uint64_t Imm,int64_t Address,const void * Decoder)188 static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm,
189                                       int64_t Address, const void *Decoder) {
190   assert(isUInt<N>(Imm) && "Invalid immediate");
191   addImplySP(Inst, Address, Decoder);
192   // Sign-extend the number in the bottom N bits of Imm
193   Inst.addOperand(MCOperand::createImm(SignExtend64<N>(Imm)));
194   return MCDisassembler::Success;
195 }
196 
197 template <unsigned N>
decodeSImmNonZeroOperand(MCInst & Inst,uint64_t Imm,int64_t Address,const void * Decoder)198 static DecodeStatus decodeSImmNonZeroOperand(MCInst &Inst, uint64_t Imm,
199                                              int64_t Address,
200                                              const void *Decoder) {
201   if (Imm == 0)
202     return MCDisassembler::Fail;
203   return decodeSImmOperand<N>(Inst, Imm, Address, Decoder);
204 }
205 
206 template <unsigned N>
decodeSImmOperandAndLsl1(MCInst & Inst,uint64_t Imm,int64_t Address,const void * Decoder)207 static DecodeStatus decodeSImmOperandAndLsl1(MCInst &Inst, uint64_t Imm,
208                                              int64_t Address,
209                                              const void *Decoder) {
210   assert(isUInt<N>(Imm) && "Invalid immediate");
211   // Sign-extend the number in the bottom N bits of Imm after accounting for
212   // the fact that the N bit immediate is stored in N-1 bits (the LSB is
213   // always zero)
214   Inst.addOperand(MCOperand::createImm(SignExtend64<N>(Imm << 1)));
215   return MCDisassembler::Success;
216 }
217 
decodeCLUIImmOperand(MCInst & Inst,uint64_t Imm,int64_t Address,const void * Decoder)218 static DecodeStatus decodeCLUIImmOperand(MCInst &Inst, uint64_t Imm,
219                                          int64_t Address,
220                                          const void *Decoder) {
221   assert(isUInt<6>(Imm) && "Invalid immediate");
222   if (Imm > 31) {
223     Imm = (SignExtend64<6>(Imm) & 0xfffff);
224   }
225   Inst.addOperand(MCOperand::createImm(Imm));
226   return MCDisassembler::Success;
227 }
228 
decodeFRMArg(MCInst & Inst,uint64_t Imm,int64_t Address,const void * Decoder)229 static DecodeStatus decodeFRMArg(MCInst &Inst, uint64_t Imm,
230                                  int64_t Address,
231                                  const void *Decoder) {
232   assert(isUInt<3>(Imm) && "Invalid immediate");
233   if (!llvm::RISCVFPRndMode::isValidRoundingMode(Imm))
234     return MCDisassembler::Fail;
235 
236   Inst.addOperand(MCOperand::createImm(Imm));
237   return MCDisassembler::Success;
238 }
239 
240 static DecodeStatus decodeRVCInstrSImm(MCInst &Inst, unsigned Insn,
241                                        uint64_t Address, const void *Decoder);
242 
243 static DecodeStatus decodeRVCInstrRdSImm(MCInst &Inst, unsigned Insn,
244                                          uint64_t Address, const void *Decoder);
245 
246 static DecodeStatus decodeRVCInstrRdRs1UImm(MCInst &Inst, unsigned Insn,
247                                             uint64_t Address,
248                                             const void *Decoder);
249 
250 static DecodeStatus decodeRVCInstrRdRs2(MCInst &Inst, unsigned Insn,
251                                         uint64_t Address, const void *Decoder);
252 
253 static DecodeStatus decodeRVCInstrRdRs1Rs2(MCInst &Inst, unsigned Insn,
254                                            uint64_t Address,
255                                            const void *Decoder);
256 
257 #include "RISCVGenDisassemblerTables.inc"
258 
decodeRVCInstrSImm(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)259 static DecodeStatus decodeRVCInstrSImm(MCInst &Inst, unsigned Insn,
260                                        uint64_t Address, const void *Decoder) {
261   uint64_t SImm6 =
262       fieldFromInstruction(Insn, 12, 1) << 5 | fieldFromInstruction(Insn, 2, 5);
263   DecodeStatus Result = decodeSImmOperand<6>(Inst, SImm6, Address, Decoder);
264   (void)Result;
265   assert(Result == MCDisassembler::Success && "Invalid immediate");
266   return MCDisassembler::Success;
267 }
268 
decodeRVCInstrRdSImm(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)269 static DecodeStatus decodeRVCInstrRdSImm(MCInst &Inst, unsigned Insn,
270                                          uint64_t Address,
271                                          const void *Decoder) {
272   DecodeGPRRegisterClass(Inst, 0, Address, Decoder);
273   uint64_t SImm6 =
274       fieldFromInstruction(Insn, 12, 1) << 5 | fieldFromInstruction(Insn, 2, 5);
275   DecodeStatus Result = decodeSImmOperand<6>(Inst, SImm6, Address, Decoder);
276   (void)Result;
277   assert(Result == MCDisassembler::Success && "Invalid immediate");
278   return MCDisassembler::Success;
279 }
280 
decodeRVCInstrRdRs1UImm(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)281 static DecodeStatus decodeRVCInstrRdRs1UImm(MCInst &Inst, unsigned Insn,
282                                             uint64_t Address,
283                                             const void *Decoder) {
284   DecodeGPRRegisterClass(Inst, 0, Address, Decoder);
285   Inst.addOperand(Inst.getOperand(0));
286   uint64_t UImm6 =
287       fieldFromInstruction(Insn, 12, 1) << 5 | fieldFromInstruction(Insn, 2, 5);
288   DecodeStatus Result = decodeUImmOperand<6>(Inst, UImm6, Address, Decoder);
289   (void)Result;
290   assert(Result == MCDisassembler::Success && "Invalid immediate");
291   return MCDisassembler::Success;
292 }
293 
decodeRVCInstrRdRs2(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)294 static DecodeStatus decodeRVCInstrRdRs2(MCInst &Inst, unsigned Insn,
295                                         uint64_t Address, const void *Decoder) {
296   unsigned Rd = fieldFromInstruction(Insn, 7, 5);
297   unsigned Rs2 = fieldFromInstruction(Insn, 2, 5);
298   DecodeGPRRegisterClass(Inst, Rd, Address, Decoder);
299   DecodeGPRRegisterClass(Inst, Rs2, Address, Decoder);
300   return MCDisassembler::Success;
301 }
302 
decodeRVCInstrRdRs1Rs2(MCInst & Inst,unsigned Insn,uint64_t Address,const void * Decoder)303 static DecodeStatus decodeRVCInstrRdRs1Rs2(MCInst &Inst, unsigned Insn,
304                                            uint64_t Address,
305                                            const void *Decoder) {
306   unsigned Rd = fieldFromInstruction(Insn, 7, 5);
307   unsigned Rs2 = fieldFromInstruction(Insn, 2, 5);
308   DecodeGPRRegisterClass(Inst, Rd, Address, Decoder);
309   Inst.addOperand(Inst.getOperand(0));
310   DecodeGPRRegisterClass(Inst, Rs2, Address, Decoder);
311   return MCDisassembler::Success;
312 }
313 
getInstruction(MCInst & MI,uint64_t & Size,ArrayRef<uint8_t> Bytes,uint64_t Address,raw_ostream & CS) const314 DecodeStatus RISCVDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
315                                                ArrayRef<uint8_t> Bytes,
316                                                uint64_t Address,
317                                                raw_ostream &CS) const {
318   // TODO: This will need modification when supporting instruction set
319   // extensions with instructions > 32-bits (up to 176 bits wide).
320   uint32_t Insn;
321   DecodeStatus Result;
322 
323   // It's a 32 bit instruction if bit 0 and 1 are 1.
324   if ((Bytes[0] & 0x3) == 0x3) {
325     if (Bytes.size() < 4) {
326       Size = 0;
327       return MCDisassembler::Fail;
328     }
329     Insn = support::endian::read32le(Bytes.data());
330     LLVM_DEBUG(dbgs() << "Trying RISCV32 table :\n");
331     Result = decodeInstruction(DecoderTable32, MI, Insn, Address, this, STI);
332     Size = 4;
333   } else {
334     if (Bytes.size() < 2) {
335       Size = 0;
336       return MCDisassembler::Fail;
337     }
338     Insn = support::endian::read16le(Bytes.data());
339 
340     if (!STI.getFeatureBits()[RISCV::Feature64Bit]) {
341       LLVM_DEBUG(
342           dbgs() << "Trying RISCV32Only_16 table (16-bit Instruction):\n");
343       // Calling the auto-generated decoder function.
344       Result = decodeInstruction(DecoderTableRISCV32Only_16, MI, Insn, Address,
345                                  this, STI);
346       if (Result != MCDisassembler::Fail) {
347         Size = 2;
348         return Result;
349       }
350     }
351 
352     LLVM_DEBUG(dbgs() << "Trying RISCV_C table (16-bit Instruction):\n");
353     // Calling the auto-generated decoder function.
354     Result = decodeInstruction(DecoderTable16, MI, Insn, Address, this, STI);
355     Size = 2;
356   }
357 
358   return Result;
359 }
360