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: 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 45 static MCDisassembler *createRISCVDisassembler(const Target &T, 46 const MCSubtargetInfo &STI, 47 MCContext &Ctx) { 48 return new RISCVDisassembler(STI, Ctx); 49 } 50 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 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 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 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 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 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 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 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 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. 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> 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> 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> 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> 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> 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 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 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 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 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 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 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 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 314 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