18ab4a969SAlex Bradbury //===-- RISCVDisassembler.cpp - Disassembler for RISCV --------------------===//
28ab4a969SAlex Bradbury //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
68ab4a969SAlex Bradbury //
78ab4a969SAlex Bradbury //===----------------------------------------------------------------------===//
88ab4a969SAlex Bradbury //
98ab4a969SAlex Bradbury // This file implements the RISCVDisassembler class.
108ab4a969SAlex Bradbury //
118ab4a969SAlex Bradbury //===----------------------------------------------------------------------===//
128ab4a969SAlex Bradbury 
13387d3c24SCraig Topper #include "MCTargetDesc/RISCVBaseInfo.h"
148ab4a969SAlex Bradbury #include "MCTargetDesc/RISCVMCTargetDesc.h"
1551fc56d6SRichard Trieu #include "TargetInfo/RISCVTargetInfo.h"
168ab4a969SAlex Bradbury #include "llvm/MC/MCContext.h"
17*c644488aSSheng #include "llvm/MC/MCDecoderOps.h"
188ab4a969SAlex Bradbury #include "llvm/MC/MCDisassembler/MCDisassembler.h"
198ab4a969SAlex Bradbury #include "llvm/MC/MCInst.h"
2066da87dcSHsiangkai Wang #include "llvm/MC/MCInstrInfo.h"
218ab4a969SAlex Bradbury #include "llvm/MC/MCRegisterInfo.h"
228ab4a969SAlex Bradbury #include "llvm/MC/MCSubtargetInfo.h"
2389b57061SReid Kleckner #include "llvm/MC/TargetRegistry.h"
248ab4a969SAlex Bradbury #include "llvm/Support/Endian.h"
258ab4a969SAlex Bradbury 
268ab4a969SAlex Bradbury using namespace llvm;
278ab4a969SAlex Bradbury 
288ab4a969SAlex Bradbury #define DEBUG_TYPE "riscv-disassembler"
298ab4a969SAlex Bradbury 
308ab4a969SAlex Bradbury typedef MCDisassembler::DecodeStatus DecodeStatus;
318ab4a969SAlex Bradbury 
328ab4a969SAlex Bradbury namespace {
338ab4a969SAlex Bradbury class RISCVDisassembler : public MCDisassembler {
3466da87dcSHsiangkai Wang   std::unique_ptr<MCInstrInfo const> const MCII;
358ab4a969SAlex Bradbury 
368ab4a969SAlex Bradbury public:
RISCVDisassembler(const MCSubtargetInfo & STI,MCContext & Ctx,MCInstrInfo const * MCII)3766da87dcSHsiangkai Wang   RISCVDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
3866da87dcSHsiangkai Wang                     MCInstrInfo const *MCII)
3966da87dcSHsiangkai Wang       : MCDisassembler(STI, Ctx), MCII(MCII) {}
408ab4a969SAlex Bradbury 
418ab4a969SAlex Bradbury   DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
428ab4a969SAlex Bradbury                               ArrayRef<uint8_t> Bytes, uint64_t Address,
438ab4a969SAlex Bradbury                               raw_ostream &CStream) const override;
448ab4a969SAlex Bradbury };
458ab4a969SAlex Bradbury } // end anonymous namespace
468ab4a969SAlex Bradbury 
createRISCVDisassembler(const Target & T,const MCSubtargetInfo & STI,MCContext & Ctx)478ab4a969SAlex Bradbury static MCDisassembler *createRISCVDisassembler(const Target &T,
488ab4a969SAlex Bradbury                                                const MCSubtargetInfo &STI,
498ab4a969SAlex Bradbury                                                MCContext &Ctx) {
5066da87dcSHsiangkai Wang   return new RISCVDisassembler(STI, Ctx, T.createMCInstrInfo());
518ab4a969SAlex Bradbury }
528ab4a969SAlex Bradbury 
LLVMInitializeRISCVDisassembler()530dbcb363STom Stellard extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeRISCVDisassembler() {
548ab4a969SAlex Bradbury   // Register the disassembler for each target.
558ab4a969SAlex Bradbury   TargetRegistry::RegisterMCDisassembler(getTheRISCV32Target(),
568ab4a969SAlex Bradbury                                          createRISCVDisassembler);
578ab4a969SAlex Bradbury   TargetRegistry::RegisterMCDisassembler(getTheRISCV64Target(),
588ab4a969SAlex Bradbury                                          createRISCVDisassembler);
598ab4a969SAlex Bradbury }
608ab4a969SAlex Bradbury 
DecodeGPRRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)618ab4a969SAlex Bradbury static DecodeStatus DecodeGPRRegisterClass(MCInst &Inst, uint64_t RegNo,
628ab4a969SAlex Bradbury                                            uint64_t Address,
634ae9745aSMaksim Panchenko                                            const MCDisassembler *Decoder) {
64dab1f6fcSAlex Bradbury   const FeatureBitset &FeatureBits =
654ae9745aSMaksim Panchenko       Decoder->getSubtargetInfo().getFeatureBits();
66dab1f6fcSAlex Bradbury   bool IsRV32E = FeatureBits[RISCV::FeatureRV32E];
67dab1f6fcSAlex Bradbury 
68aae97bfdSLuis Marques   if (RegNo >= 32 || (IsRV32E && RegNo >= 16))
698ab4a969SAlex Bradbury     return MCDisassembler::Fail;
708ab4a969SAlex Bradbury 
710add5f91SCraig Topper   MCRegister Reg = RISCV::X0 + RegNo;
728ab4a969SAlex Bradbury   Inst.addOperand(MCOperand::createReg(Reg));
738ab4a969SAlex Bradbury   return MCDisassembler::Success;
748ab4a969SAlex Bradbury }
758ab4a969SAlex Bradbury 
DecodeFPR16RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)76f7bc7c29SHsiangkai Wang static DecodeStatus DecodeFPR16RegisterClass(MCInst &Inst, uint64_t RegNo,
77f7bc7c29SHsiangkai Wang                                              uint64_t Address,
784ae9745aSMaksim Panchenko                                              const MCDisassembler *Decoder) {
79f7bc7c29SHsiangkai Wang   if (RegNo >= 32)
80f7bc7c29SHsiangkai Wang     return MCDisassembler::Fail;
81f7bc7c29SHsiangkai Wang 
82f7bc7c29SHsiangkai Wang   MCRegister Reg = RISCV::F0_H + RegNo;
83f7bc7c29SHsiangkai Wang   Inst.addOperand(MCOperand::createReg(Reg));
84f7bc7c29SHsiangkai Wang   return MCDisassembler::Success;
85f7bc7c29SHsiangkai Wang }
86f7bc7c29SHsiangkai Wang 
DecodeFPR32RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)870d6cf906SAlex Bradbury static DecodeStatus DecodeFPR32RegisterClass(MCInst &Inst, uint64_t RegNo,
880d6cf906SAlex Bradbury                                              uint64_t Address,
894ae9745aSMaksim Panchenko                                              const MCDisassembler *Decoder) {
90aae97bfdSLuis Marques   if (RegNo >= 32)
910d6cf906SAlex Bradbury     return MCDisassembler::Fail;
920d6cf906SAlex Bradbury 
930add5f91SCraig Topper   MCRegister Reg = RISCV::F0_F + RegNo;
940d6cf906SAlex Bradbury   Inst.addOperand(MCOperand::createReg(Reg));
950d6cf906SAlex Bradbury   return MCDisassembler::Success;
960d6cf906SAlex Bradbury }
970d6cf906SAlex Bradbury 
DecodeFPR32CRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)9860714f98SAlex Bradbury static DecodeStatus DecodeFPR32CRegisterClass(MCInst &Inst, uint64_t RegNo,
9960714f98SAlex Bradbury                                               uint64_t Address,
1004ae9745aSMaksim Panchenko                                               const MCDisassembler *Decoder) {
101aae97bfdSLuis Marques   if (RegNo >= 8) {
10260714f98SAlex Bradbury     return MCDisassembler::Fail;
10360714f98SAlex Bradbury   }
1040add5f91SCraig Topper   MCRegister Reg = RISCV::F8_F + RegNo;
10560714f98SAlex Bradbury   Inst.addOperand(MCOperand::createReg(Reg));
10660714f98SAlex Bradbury   return MCDisassembler::Success;
10760714f98SAlex Bradbury }
10860714f98SAlex Bradbury 
DecodeFPR64RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)1097bc2a95bSAlex Bradbury static DecodeStatus DecodeFPR64RegisterClass(MCInst &Inst, uint64_t RegNo,
1107bc2a95bSAlex Bradbury                                              uint64_t Address,
1114ae9745aSMaksim Panchenko                                              const MCDisassembler *Decoder) {
112aae97bfdSLuis Marques   if (RegNo >= 32)
1137bc2a95bSAlex Bradbury     return MCDisassembler::Fail;
1147bc2a95bSAlex Bradbury 
1150add5f91SCraig Topper   MCRegister Reg = RISCV::F0_D + RegNo;
1167bc2a95bSAlex Bradbury   Inst.addOperand(MCOperand::createReg(Reg));
1177bc2a95bSAlex Bradbury   return MCDisassembler::Success;
1187bc2a95bSAlex Bradbury }
1197bc2a95bSAlex Bradbury 
DecodeFPR64CRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)12060714f98SAlex Bradbury static DecodeStatus DecodeFPR64CRegisterClass(MCInst &Inst, uint64_t RegNo,
12160714f98SAlex Bradbury                                               uint64_t Address,
1224ae9745aSMaksim Panchenko                                               const MCDisassembler *Decoder) {
123aae97bfdSLuis Marques   if (RegNo >= 8) {
12460714f98SAlex Bradbury     return MCDisassembler::Fail;
12560714f98SAlex Bradbury   }
1260add5f91SCraig Topper   MCRegister Reg = RISCV::F8_D + RegNo;
12760714f98SAlex Bradbury   Inst.addOperand(MCOperand::createReg(Reg));
12860714f98SAlex Bradbury   return MCDisassembler::Success;
12960714f98SAlex Bradbury }
13060714f98SAlex Bradbury 
DecodeGPRNoX0RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)1319f6aec4bSAlex Bradbury static DecodeStatus DecodeGPRNoX0RegisterClass(MCInst &Inst, uint64_t RegNo,
1329f6aec4bSAlex Bradbury                                                uint64_t Address,
1334ae9745aSMaksim Panchenko                                                const MCDisassembler *Decoder) {
1349f6aec4bSAlex Bradbury   if (RegNo == 0) {
1359f6aec4bSAlex Bradbury     return MCDisassembler::Fail;
1369f6aec4bSAlex Bradbury   }
1379f6aec4bSAlex Bradbury 
1389f6aec4bSAlex Bradbury   return DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder);
1399f6aec4bSAlex Bradbury }
1409f6aec4bSAlex Bradbury 
1414ae9745aSMaksim Panchenko static DecodeStatus
DecodeGPRNoX0X2RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)1424ae9745aSMaksim Panchenko DecodeGPRNoX0X2RegisterClass(MCInst &Inst, uint64_t RegNo, uint64_t Address,
1434ae9745aSMaksim Panchenko                              const MCDisassembler *Decoder) {
14460714f98SAlex Bradbury   if (RegNo == 2) {
14560714f98SAlex Bradbury     return MCDisassembler::Fail;
14660714f98SAlex Bradbury   }
14760714f98SAlex Bradbury 
14860714f98SAlex Bradbury   return DecodeGPRNoX0RegisterClass(Inst, RegNo, Address, Decoder);
14960714f98SAlex Bradbury }
15060714f98SAlex Bradbury 
DecodeGPRCRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)1519f6aec4bSAlex Bradbury static DecodeStatus DecodeGPRCRegisterClass(MCInst &Inst, uint64_t RegNo,
1529f6aec4bSAlex Bradbury                                             uint64_t Address,
1534ae9745aSMaksim Panchenko                                             const MCDisassembler *Decoder) {
154aae97bfdSLuis Marques   if (RegNo >= 8)
1559f6aec4bSAlex Bradbury     return MCDisassembler::Fail;
1569f6aec4bSAlex Bradbury 
1570add5f91SCraig Topper   MCRegister Reg = RISCV::X8 + RegNo;
1589f6aec4bSAlex Bradbury   Inst.addOperand(MCOperand::createReg(Reg));
1599f6aec4bSAlex Bradbury   return MCDisassembler::Success;
1609f6aec4bSAlex Bradbury }
1619f6aec4bSAlex Bradbury 
DecodeGPRPF64RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)1620e38b295SShao-Ce SUN static DecodeStatus DecodeGPRPF64RegisterClass(MCInst &Inst, uint64_t RegNo,
1630e38b295SShao-Ce SUN                                                uint64_t Address,
1644ae9745aSMaksim Panchenko                                                const MCDisassembler *Decoder) {
1650e38b295SShao-Ce SUN   if (RegNo >= 32 || RegNo & 1)
1660e38b295SShao-Ce SUN     return MCDisassembler::Fail;
1670e38b295SShao-Ce SUN 
1680e38b295SShao-Ce SUN   MCRegister Reg = RISCV::X0 + RegNo;
1690e38b295SShao-Ce SUN   Inst.addOperand(MCOperand::createReg(Reg));
1700e38b295SShao-Ce SUN   return MCDisassembler::Success;
1710e38b295SShao-Ce SUN }
1720e38b295SShao-Ce SUN 
DecodeVRRegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)17366da87dcSHsiangkai Wang static DecodeStatus DecodeVRRegisterClass(MCInst &Inst, uint64_t RegNo,
17466da87dcSHsiangkai Wang                                           uint64_t Address,
1754ae9745aSMaksim Panchenko                                           const MCDisassembler *Decoder) {
17666da87dcSHsiangkai Wang   if (RegNo >= 32)
17766da87dcSHsiangkai Wang     return MCDisassembler::Fail;
17866da87dcSHsiangkai Wang 
1790add5f91SCraig Topper   MCRegister Reg = RISCV::V0 + RegNo;
18066da87dcSHsiangkai Wang   Inst.addOperand(MCOperand::createReg(Reg));
18166da87dcSHsiangkai Wang   return MCDisassembler::Success;
18266da87dcSHsiangkai Wang }
18366da87dcSHsiangkai Wang 
DecodeVRM2RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)184a2d19badSHsiangkai Wang static DecodeStatus DecodeVRM2RegisterClass(MCInst &Inst, uint64_t RegNo,
185a2d19badSHsiangkai Wang                                             uint64_t Address,
1864ae9745aSMaksim Panchenko                                             const MCDisassembler *Decoder) {
187a2d19badSHsiangkai Wang   if (RegNo >= 32)
188a2d19badSHsiangkai Wang     return MCDisassembler::Fail;
189a2d19badSHsiangkai Wang 
190a2d19badSHsiangkai Wang   if (RegNo % 2)
191a2d19badSHsiangkai Wang     return MCDisassembler::Fail;
192a2d19badSHsiangkai Wang 
193a2d19badSHsiangkai Wang   const RISCVDisassembler *Dis =
194a2d19badSHsiangkai Wang       static_cast<const RISCVDisassembler *>(Decoder);
195a2d19badSHsiangkai Wang   const MCRegisterInfo *RI = Dis->getContext().getRegisterInfo();
196a2d19badSHsiangkai Wang   MCRegister Reg =
197a2d19badSHsiangkai Wang       RI->getMatchingSuperReg(RISCV::V0 + RegNo, RISCV::sub_vrm1_0,
198a2d19badSHsiangkai Wang                               &RISCVMCRegisterClasses[RISCV::VRM2RegClassID]);
199a2d19badSHsiangkai Wang 
200a2d19badSHsiangkai Wang   Inst.addOperand(MCOperand::createReg(Reg));
201a2d19badSHsiangkai Wang   return MCDisassembler::Success;
202a2d19badSHsiangkai Wang }
203a2d19badSHsiangkai Wang 
DecodeVRM4RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)204a2d19badSHsiangkai Wang static DecodeStatus DecodeVRM4RegisterClass(MCInst &Inst, uint64_t RegNo,
205a2d19badSHsiangkai Wang                                             uint64_t Address,
2064ae9745aSMaksim Panchenko                                             const MCDisassembler *Decoder) {
207a2d19badSHsiangkai Wang   if (RegNo >= 32)
208a2d19badSHsiangkai Wang     return MCDisassembler::Fail;
209a2d19badSHsiangkai Wang 
210a2d19badSHsiangkai Wang   if (RegNo % 4)
211a2d19badSHsiangkai Wang     return MCDisassembler::Fail;
212a2d19badSHsiangkai Wang 
213a2d19badSHsiangkai Wang   const RISCVDisassembler *Dis =
214a2d19badSHsiangkai Wang       static_cast<const RISCVDisassembler *>(Decoder);
215a2d19badSHsiangkai Wang   const MCRegisterInfo *RI = Dis->getContext().getRegisterInfo();
216a2d19badSHsiangkai Wang   MCRegister Reg =
217a2d19badSHsiangkai Wang       RI->getMatchingSuperReg(RISCV::V0 + RegNo, RISCV::sub_vrm1_0,
218a2d19badSHsiangkai Wang                               &RISCVMCRegisterClasses[RISCV::VRM4RegClassID]);
219a2d19badSHsiangkai Wang 
220a2d19badSHsiangkai Wang   Inst.addOperand(MCOperand::createReg(Reg));
221a2d19badSHsiangkai Wang   return MCDisassembler::Success;
222a2d19badSHsiangkai Wang }
223a2d19badSHsiangkai Wang 
DecodeVRM8RegisterClass(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)224a2d19badSHsiangkai Wang static DecodeStatus DecodeVRM8RegisterClass(MCInst &Inst, uint64_t RegNo,
225a2d19badSHsiangkai Wang                                             uint64_t Address,
2264ae9745aSMaksim Panchenko                                             const MCDisassembler *Decoder) {
227a2d19badSHsiangkai Wang   if (RegNo >= 32)
228a2d19badSHsiangkai Wang     return MCDisassembler::Fail;
229a2d19badSHsiangkai Wang 
230a2d19badSHsiangkai Wang   if (RegNo % 8)
231a2d19badSHsiangkai Wang     return MCDisassembler::Fail;
232a2d19badSHsiangkai Wang 
233a2d19badSHsiangkai Wang   const RISCVDisassembler *Dis =
234a2d19badSHsiangkai Wang       static_cast<const RISCVDisassembler *>(Decoder);
235a2d19badSHsiangkai Wang   const MCRegisterInfo *RI = Dis->getContext().getRegisterInfo();
236a2d19badSHsiangkai Wang   MCRegister Reg =
237a2d19badSHsiangkai Wang       RI->getMatchingSuperReg(RISCV::V0 + RegNo, RISCV::sub_vrm1_0,
238a2d19badSHsiangkai Wang                               &RISCVMCRegisterClasses[RISCV::VRM8RegClassID]);
239a2d19badSHsiangkai Wang 
240a2d19badSHsiangkai Wang   Inst.addOperand(MCOperand::createReg(Reg));
241a2d19badSHsiangkai Wang   return MCDisassembler::Success;
242a2d19badSHsiangkai Wang }
243a2d19badSHsiangkai Wang 
decodeVMaskReg(MCInst & Inst,uint64_t RegNo,uint64_t Address,const MCDisassembler * Decoder)24466da87dcSHsiangkai Wang static DecodeStatus decodeVMaskReg(MCInst &Inst, uint64_t RegNo,
2454ae9745aSMaksim Panchenko                                    uint64_t Address,
2464ae9745aSMaksim Panchenko                                    const MCDisassembler *Decoder) {
2470add5f91SCraig Topper   MCRegister Reg = RISCV::NoRegister;
24866da87dcSHsiangkai Wang   switch (RegNo) {
24966da87dcSHsiangkai Wang   default:
25066da87dcSHsiangkai Wang     return MCDisassembler::Fail;
25166da87dcSHsiangkai Wang   case 0:
25266da87dcSHsiangkai Wang     Reg = RISCV::V0;
25366da87dcSHsiangkai Wang     break;
25466da87dcSHsiangkai Wang   case 1:
25566da87dcSHsiangkai Wang     break;
25666da87dcSHsiangkai Wang   }
25766da87dcSHsiangkai Wang   Inst.addOperand(MCOperand::createReg(Reg));
25866da87dcSHsiangkai Wang   return MCDisassembler::Success;
25966da87dcSHsiangkai Wang }
26066da87dcSHsiangkai Wang 
2619f6aec4bSAlex Bradbury // Add implied SP operand for instructions *SP compressed instructions. The SP
2629f6aec4bSAlex Bradbury // operand isn't explicitly encoded in the instruction.
addImplySP(MCInst & Inst,int64_t Address,const MCDisassembler * Decoder)2634ae9745aSMaksim Panchenko static void addImplySP(MCInst &Inst, int64_t Address,
2644ae9745aSMaksim Panchenko                        const MCDisassembler *Decoder) {
26519c9314aSAlex Bradbury   if (Inst.getOpcode() == RISCV::C_LWSP || Inst.getOpcode() == RISCV::C_SWSP ||
26619c9314aSAlex Bradbury       Inst.getOpcode() == RISCV::C_LDSP || Inst.getOpcode() == RISCV::C_SDSP ||
26719c9314aSAlex Bradbury       Inst.getOpcode() == RISCV::C_FLWSP ||
26819c9314aSAlex Bradbury       Inst.getOpcode() == RISCV::C_FSWSP ||
26919c9314aSAlex Bradbury       Inst.getOpcode() == RISCV::C_FLDSP ||
27019c9314aSAlex Bradbury       Inst.getOpcode() == RISCV::C_FSDSP ||
27119c9314aSAlex Bradbury       Inst.getOpcode() == RISCV::C_ADDI4SPN) {
27260714f98SAlex Bradbury     DecodeGPRRegisterClass(Inst, 2, Address, Decoder);
27360714f98SAlex Bradbury   }
27419c9314aSAlex Bradbury   if (Inst.getOpcode() == RISCV::C_ADDI16SP) {
27560714f98SAlex Bradbury     DecodeGPRRegisterClass(Inst, 2, Address, Decoder);
2769f6aec4bSAlex Bradbury     DecodeGPRRegisterClass(Inst, 2, Address, Decoder);
2779f6aec4bSAlex Bradbury   }
2789f6aec4bSAlex Bradbury }
2799f6aec4bSAlex Bradbury 
2808ab4a969SAlex Bradbury template <unsigned N>
decodeUImmOperand(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)2818ab4a969SAlex Bradbury static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm,
2824ae9745aSMaksim Panchenko                                       int64_t Address,
2834ae9745aSMaksim Panchenko                                       const MCDisassembler *Decoder) {
2848ab4a969SAlex Bradbury   assert(isUInt<N>(Imm) && "Invalid immediate");
2859f6aec4bSAlex Bradbury   addImplySP(Inst, Address, Decoder);
2868ab4a969SAlex Bradbury   Inst.addOperand(MCOperand::createImm(Imm));
2878ab4a969SAlex Bradbury   return MCDisassembler::Success;
2888ab4a969SAlex Bradbury }
2898ab4a969SAlex Bradbury 
2908ab4a969SAlex Bradbury template <unsigned N>
decodeUImmNonZeroOperand(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)291b0799ddaSAna Pazos static DecodeStatus decodeUImmNonZeroOperand(MCInst &Inst, uint64_t Imm,
292b0799ddaSAna Pazos                                              int64_t Address,
2934ae9745aSMaksim Panchenko                                              const MCDisassembler *Decoder) {
294b0799ddaSAna Pazos   if (Imm == 0)
295b0799ddaSAna Pazos     return MCDisassembler::Fail;
296b0799ddaSAna Pazos   return decodeUImmOperand<N>(Inst, Imm, Address, Decoder);
297b0799ddaSAna Pazos }
298b0799ddaSAna Pazos 
299b0799ddaSAna Pazos template <unsigned N>
decodeSImmOperand(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)3008ab4a969SAlex Bradbury static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm,
3014ae9745aSMaksim Panchenko                                       int64_t Address,
3024ae9745aSMaksim Panchenko                                       const MCDisassembler *Decoder) {
3038ab4a969SAlex Bradbury   assert(isUInt<N>(Imm) && "Invalid immediate");
30460714f98SAlex Bradbury   addImplySP(Inst, Address, Decoder);
3058ab4a969SAlex Bradbury   // Sign-extend the number in the bottom N bits of Imm
3068ab4a969SAlex Bradbury   Inst.addOperand(MCOperand::createImm(SignExtend64<N>(Imm)));
3078ab4a969SAlex Bradbury   return MCDisassembler::Success;
3088ab4a969SAlex Bradbury }
3098ab4a969SAlex Bradbury 
3108ab4a969SAlex Bradbury template <unsigned N>
decodeSImmNonZeroOperand(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)311b0799ddaSAna Pazos static DecodeStatus decodeSImmNonZeroOperand(MCInst &Inst, uint64_t Imm,
312b0799ddaSAna Pazos                                              int64_t Address,
3134ae9745aSMaksim Panchenko                                              const MCDisassembler *Decoder) {
314b0799ddaSAna Pazos   if (Imm == 0)
315b0799ddaSAna Pazos     return MCDisassembler::Fail;
316b0799ddaSAna Pazos   return decodeSImmOperand<N>(Inst, Imm, Address, Decoder);
317b0799ddaSAna Pazos }
318b0799ddaSAna Pazos 
319b0799ddaSAna Pazos template <unsigned N>
decodeSImmOperandAndLsl1(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)3208ab4a969SAlex Bradbury static DecodeStatus decodeSImmOperandAndLsl1(MCInst &Inst, uint64_t Imm,
3218ab4a969SAlex Bradbury                                              int64_t Address,
3224ae9745aSMaksim Panchenko                                              const MCDisassembler *Decoder) {
3238ab4a969SAlex Bradbury   assert(isUInt<N>(Imm) && "Invalid immediate");
3248ab4a969SAlex Bradbury   // Sign-extend the number in the bottom N bits of Imm after accounting for
3258ab4a969SAlex Bradbury   // the fact that the N bit immediate is stored in N-1 bits (the LSB is
3268ab4a969SAlex Bradbury   // always zero)
3278ab4a969SAlex Bradbury   Inst.addOperand(MCOperand::createImm(SignExtend64<N>(Imm << 1)));
3288ab4a969SAlex Bradbury   return MCDisassembler::Success;
3298ab4a969SAlex Bradbury }
3308ab4a969SAlex Bradbury 
decodeCLUIImmOperand(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)3317c17242bSShiva Chen static DecodeStatus decodeCLUIImmOperand(MCInst &Inst, uint64_t Imm,
3327c17242bSShiva Chen                                          int64_t Address,
3334ae9745aSMaksim Panchenko                                          const MCDisassembler *Decoder) {
3347c17242bSShiva Chen   assert(isUInt<6>(Imm) && "Invalid immediate");
3357c17242bSShiva Chen   if (Imm > 31) {
3367c17242bSShiva Chen     Imm = (SignExtend64<6>(Imm) & 0xfffff);
3377c17242bSShiva Chen   }
3387c17242bSShiva Chen   Inst.addOperand(MCOperand::createImm(Imm));
3397c17242bSShiva Chen   return MCDisassembler::Success;
3407c17242bSShiva Chen }
3417c17242bSShiva Chen 
decodeFRMArg(MCInst & Inst,uint64_t Imm,int64_t Address,const MCDisassembler * Decoder)3424ae9745aSMaksim Panchenko static DecodeStatus decodeFRMArg(MCInst &Inst, uint64_t Imm, int64_t Address,
3434ae9745aSMaksim Panchenko                                  const MCDisassembler *Decoder) {
344b2ed11a0SAna Pazos   assert(isUInt<3>(Imm) && "Invalid immediate");
345b2ed11a0SAna Pazos   if (!llvm::RISCVFPRndMode::isValidRoundingMode(Imm))
346b2ed11a0SAna Pazos     return MCDisassembler::Fail;
347b2ed11a0SAna Pazos 
348b2ed11a0SAna Pazos   Inst.addOperand(MCOperand::createImm(Imm));
349b2ed11a0SAna Pazos   return MCDisassembler::Success;
350b2ed11a0SAna Pazos }
351b2ed11a0SAna Pazos 
352c3bf3d14SLuis Marques static DecodeStatus decodeRVCInstrSImm(MCInst &Inst, unsigned Insn,
3534ae9745aSMaksim Panchenko                                        uint64_t Address,
3544ae9745aSMaksim Panchenko                                        const MCDisassembler *Decoder);
355c3bf3d14SLuis Marques 
356c3bf3d14SLuis Marques static DecodeStatus decodeRVCInstrRdSImm(MCInst &Inst, unsigned Insn,
3574ae9745aSMaksim Panchenko                                          uint64_t Address,
3584ae9745aSMaksim Panchenko                                          const MCDisassembler *Decoder);
359c3bf3d14SLuis Marques 
360c3bf3d14SLuis Marques static DecodeStatus decodeRVCInstrRdRs1UImm(MCInst &Inst, unsigned Insn,
361c3bf3d14SLuis Marques                                             uint64_t Address,
3624ae9745aSMaksim Panchenko                                             const MCDisassembler *Decoder);
363c3bf3d14SLuis Marques 
364c3bf3d14SLuis Marques static DecodeStatus decodeRVCInstrRdRs2(MCInst &Inst, unsigned Insn,
3654ae9745aSMaksim Panchenko                                         uint64_t Address,
3664ae9745aSMaksim Panchenko                                         const MCDisassembler *Decoder);
367c3bf3d14SLuis Marques 
368c3bf3d14SLuis Marques static DecodeStatus decodeRVCInstrRdRs1Rs2(MCInst &Inst, unsigned Insn,
369c3bf3d14SLuis Marques                                            uint64_t Address,
3704ae9745aSMaksim Panchenko                                            const MCDisassembler *Decoder);
371c3bf3d14SLuis Marques 
3728ab4a969SAlex Bradbury #include "RISCVGenDisassemblerTables.inc"
3738ab4a969SAlex Bradbury 
decodeRVCInstrSImm(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)374c3bf3d14SLuis Marques static DecodeStatus decodeRVCInstrSImm(MCInst &Inst, unsigned Insn,
3754ae9745aSMaksim Panchenko                                        uint64_t Address,
3764ae9745aSMaksim Panchenko                                        const MCDisassembler *Decoder) {
377c3bf3d14SLuis Marques   uint64_t SImm6 =
378c3bf3d14SLuis Marques       fieldFromInstruction(Insn, 12, 1) << 5 | fieldFromInstruction(Insn, 2, 5);
3794f488b59SLuis Marques   DecodeStatus Result = decodeSImmOperand<6>(Inst, SImm6, Address, Decoder);
3804f488b59SLuis Marques   (void)Result;
3814f488b59SLuis Marques   assert(Result == MCDisassembler::Success && "Invalid immediate");
382c3bf3d14SLuis Marques   return MCDisassembler::Success;
383c3bf3d14SLuis Marques }
384c3bf3d14SLuis Marques 
decodeRVCInstrRdSImm(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)385c3bf3d14SLuis Marques static DecodeStatus decodeRVCInstrRdSImm(MCInst &Inst, unsigned Insn,
386c3bf3d14SLuis Marques                                          uint64_t Address,
3874ae9745aSMaksim Panchenko                                          const MCDisassembler *Decoder) {
388c3bf3d14SLuis Marques   DecodeGPRRegisterClass(Inst, 0, Address, Decoder);
389c3bf3d14SLuis Marques   uint64_t SImm6 =
390c3bf3d14SLuis Marques       fieldFromInstruction(Insn, 12, 1) << 5 | fieldFromInstruction(Insn, 2, 5);
3914f488b59SLuis Marques   DecodeStatus Result = decodeSImmOperand<6>(Inst, SImm6, Address, Decoder);
3924f488b59SLuis Marques   (void)Result;
3934f488b59SLuis Marques   assert(Result == MCDisassembler::Success && "Invalid immediate");
394c3bf3d14SLuis Marques   return MCDisassembler::Success;
395c3bf3d14SLuis Marques }
396c3bf3d14SLuis Marques 
decodeRVCInstrRdRs1UImm(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)397c3bf3d14SLuis Marques static DecodeStatus decodeRVCInstrRdRs1UImm(MCInst &Inst, unsigned Insn,
398c3bf3d14SLuis Marques                                             uint64_t Address,
3994ae9745aSMaksim Panchenko                                             const MCDisassembler *Decoder) {
400c3bf3d14SLuis Marques   DecodeGPRRegisterClass(Inst, 0, Address, Decoder);
401c3bf3d14SLuis Marques   Inst.addOperand(Inst.getOperand(0));
402c3bf3d14SLuis Marques   uint64_t UImm6 =
403c3bf3d14SLuis Marques       fieldFromInstruction(Insn, 12, 1) << 5 | fieldFromInstruction(Insn, 2, 5);
4044f488b59SLuis Marques   DecodeStatus Result = decodeUImmOperand<6>(Inst, UImm6, Address, Decoder);
4054f488b59SLuis Marques   (void)Result;
4064f488b59SLuis Marques   assert(Result == MCDisassembler::Success && "Invalid immediate");
407c3bf3d14SLuis Marques   return MCDisassembler::Success;
408c3bf3d14SLuis Marques }
409c3bf3d14SLuis Marques 
decodeRVCInstrRdRs2(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)410c3bf3d14SLuis Marques static DecodeStatus decodeRVCInstrRdRs2(MCInst &Inst, unsigned Insn,
4114ae9745aSMaksim Panchenko                                         uint64_t Address,
4124ae9745aSMaksim Panchenko                                         const MCDisassembler *Decoder) {
413c3bf3d14SLuis Marques   unsigned Rd = fieldFromInstruction(Insn, 7, 5);
414c3bf3d14SLuis Marques   unsigned Rs2 = fieldFromInstruction(Insn, 2, 5);
415c3bf3d14SLuis Marques   DecodeGPRRegisterClass(Inst, Rd, Address, Decoder);
416c3bf3d14SLuis Marques   DecodeGPRRegisterClass(Inst, Rs2, Address, Decoder);
417c3bf3d14SLuis Marques   return MCDisassembler::Success;
418c3bf3d14SLuis Marques }
419c3bf3d14SLuis Marques 
decodeRVCInstrRdRs1Rs2(MCInst & Inst,unsigned Insn,uint64_t Address,const MCDisassembler * Decoder)420c3bf3d14SLuis Marques static DecodeStatus decodeRVCInstrRdRs1Rs2(MCInst &Inst, unsigned Insn,
421c3bf3d14SLuis Marques                                            uint64_t Address,
4224ae9745aSMaksim Panchenko                                            const MCDisassembler *Decoder) {
423c3bf3d14SLuis Marques   unsigned Rd = fieldFromInstruction(Insn, 7, 5);
424c3bf3d14SLuis Marques   unsigned Rs2 = fieldFromInstruction(Insn, 2, 5);
425c3bf3d14SLuis Marques   DecodeGPRRegisterClass(Inst, Rd, Address, Decoder);
426c3bf3d14SLuis Marques   Inst.addOperand(Inst.getOperand(0));
427c3bf3d14SLuis Marques   DecodeGPRRegisterClass(Inst, Rs2, Address, Decoder);
428c3bf3d14SLuis Marques   return MCDisassembler::Success;
429c3bf3d14SLuis Marques }
430c3bf3d14SLuis Marques 
getInstruction(MCInst & MI,uint64_t & Size,ArrayRef<uint8_t> Bytes,uint64_t Address,raw_ostream & CS) const4318ab4a969SAlex Bradbury DecodeStatus RISCVDisassembler::getInstruction(MCInst &MI, uint64_t &Size,
4328ab4a969SAlex Bradbury                                                ArrayRef<uint8_t> Bytes,
4338ab4a969SAlex Bradbury                                                uint64_t Address,
4348ab4a969SAlex Bradbury                                                raw_ostream &CS) const {
4359f6aec4bSAlex Bradbury   // TODO: This will need modification when supporting instruction set
4369f6aec4bSAlex Bradbury   // extensions with instructions > 32-bits (up to 176 bits wide).
4379f6aec4bSAlex Bradbury   uint32_t Insn;
4389f6aec4bSAlex Bradbury   DecodeStatus Result;
4399f6aec4bSAlex Bradbury 
4409f6aec4bSAlex Bradbury   // It's a 32 bit instruction if bit 0 and 1 are 1.
4419f6aec4bSAlex Bradbury   if ((Bytes[0] & 0x3) == 0x3) {
442b97d1894SAna Pazos     if (Bytes.size() < 4) {
443b97d1894SAna Pazos       Size = 0;
444b97d1894SAna Pazos       return MCDisassembler::Fail;
445b97d1894SAna Pazos     }
4469f6aec4bSAlex Bradbury     Insn = support::endian::read32le(Bytes.data());
4470e38b295SShao-Ce SUN     if (STI.getFeatureBits()[RISCV::FeatureStdExtZdinx] &&
4480e38b295SShao-Ce SUN         !STI.getFeatureBits()[RISCV::Feature64Bit]) {
4490e38b295SShao-Ce SUN       LLVM_DEBUG(dbgs() << "Trying RV32Zdinx table (Double in Integer and"
4500e38b295SShao-Ce SUN                            "rv32)\n");
4510e38b295SShao-Ce SUN       Result = decodeInstruction(DecoderTableRV32Zdinx32, MI, Insn, Address,
4520e38b295SShao-Ce SUN                                  this, STI);
4530e38b295SShao-Ce SUN       if (Result != MCDisassembler::Fail) {
4540e38b295SShao-Ce SUN         Size = 4;
4550e38b295SShao-Ce SUN         return Result;
4560e38b295SShao-Ce SUN       }
4570e38b295SShao-Ce SUN     }
4580e38b295SShao-Ce SUN 
4590e38b295SShao-Ce SUN     if (STI.getFeatureBits()[RISCV::FeatureStdExtZfinx]) {
4600e38b295SShao-Ce SUN       LLVM_DEBUG(dbgs() << "Trying RVZfinx table (Float in Integer):\n");
4610e38b295SShao-Ce SUN       Result = decodeInstruction(DecoderTableRVZfinx32, MI, Insn, Address, this,
4620e38b295SShao-Ce SUN                                  STI);
4630e38b295SShao-Ce SUN       if (Result != MCDisassembler::Fail) {
4640e38b295SShao-Ce SUN         Size = 4;
4650e38b295SShao-Ce SUN         return Result;
4660e38b295SShao-Ce SUN       }
4670e38b295SShao-Ce SUN     }
468d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "Trying RISCV32 table :\n");
4699f6aec4bSAlex Bradbury     Result = decodeInstruction(DecoderTable32, MI, Insn, Address, this, STI);
4708ab4a969SAlex Bradbury     Size = 4;
4719f6aec4bSAlex Bradbury   } else {
472b97d1894SAna Pazos     if (Bytes.size() < 2) {
473b97d1894SAna Pazos       Size = 0;
474b97d1894SAna Pazos       return MCDisassembler::Fail;
475b97d1894SAna Pazos     }
4769f6aec4bSAlex Bradbury     Insn = support::endian::read16le(Bytes.data());
47760714f98SAlex Bradbury 
47860714f98SAlex Bradbury     if (!STI.getFeatureBits()[RISCV::Feature64Bit]) {
479d34e60caSNicola Zaghen       LLVM_DEBUG(
480d34e60caSNicola Zaghen           dbgs() << "Trying RISCV32Only_16 table (16-bit Instruction):\n");
48160714f98SAlex Bradbury       // Calling the auto-generated decoder function.
48260714f98SAlex Bradbury       Result = decodeInstruction(DecoderTableRISCV32Only_16, MI, Insn, Address,
48360714f98SAlex Bradbury                                  this, STI);
48460714f98SAlex Bradbury       if (Result != MCDisassembler::Fail) {
48560714f98SAlex Bradbury         Size = 2;
48660714f98SAlex Bradbury         return Result;
48760714f98SAlex Bradbury       }
48860714f98SAlex Bradbury     }
48960714f98SAlex Bradbury 
490d34e60caSNicola Zaghen     LLVM_DEBUG(dbgs() << "Trying RISCV_C table (16-bit Instruction):\n");
4919f6aec4bSAlex Bradbury     // Calling the auto-generated decoder function.
4929f6aec4bSAlex Bradbury     Result = decodeInstruction(DecoderTable16, MI, Insn, Address, this, STI);
4939f6aec4bSAlex Bradbury     Size = 2;
4948ab4a969SAlex Bradbury   }
4958ab4a969SAlex Bradbury 
4969f6aec4bSAlex Bradbury   return Result;
4978ab4a969SAlex Bradbury }
498