259 lines · cpp
1//===-- RISCVBaseInfo.cpp - Top level definitions for RISC-V MC -----------===//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-exception6//7//===----------------------------------------------------------------------===//8//9// This file contains small standalone enum definitions for the RISC-V target10// useful for the compiler back-end and the MC libraries.11//12//===----------------------------------------------------------------------===//13 14#include "RISCVBaseInfo.h"15#include "llvm/MC/MCInst.h"16#include "llvm/MC/MCRegisterInfo.h"17#include "llvm/MC/MCSubtargetInfo.h"18#include "llvm/Support/raw_ostream.h"19#include "llvm/TargetParser/TargetParser.h"20#include "llvm/TargetParser/Triple.h"21 22namespace llvm {23 24extern const SubtargetFeatureKV RISCVFeatureKV[RISCV::NumSubtargetFeatures];25 26namespace RISCVSysReg {27#define GET_SysRegsList_IMPL28#include "RISCVGenSearchableTables.inc"29} // namespace RISCVSysReg30 31namespace RISCVInsnOpcode {32#define GET_RISCVOpcodesList_IMPL33#include "RISCVGenSearchableTables.inc"34} // namespace RISCVInsnOpcode35 36namespace RISCVVInversePseudosTable {37using namespace RISCV;38#define GET_RISCVVInversePseudosTable_IMPL39#include "RISCVGenSearchableTables.inc"40} // namespace RISCVVInversePseudosTable41 42namespace RISCV {43#define GET_RISCVVSSEGTable_IMPL44#define GET_RISCVVLSEGTable_IMPL45#define GET_RISCVVLXSEGTable_IMPL46#define GET_RISCVVSXSEGTable_IMPL47#define GET_RISCVVLETable_IMPL48#define GET_RISCVVSETable_IMPL49#define GET_RISCVVLXTable_IMPL50#define GET_RISCVVSXTable_IMPL51#define GET_RISCVNDSVLNTable_IMPL52#include "RISCVGenSearchableTables.inc"53} // namespace RISCV54 55namespace RISCVABI {56ABI computeTargetABI(const Triple &TT, const FeatureBitset &FeatureBits,57 StringRef ABIName) {58 auto TargetABI = getTargetABI(ABIName);59 bool IsRV64 = TT.isArch64Bit();60 bool IsRVE = FeatureBits[RISCV::FeatureStdExtE];61 62 if (!ABIName.empty() && TargetABI == ABI_Unknown) {63 errs()64 << "'" << ABIName65 << "' is not a recognized ABI for this target (ignoring target-abi)\n";66 } else if (ABIName.starts_with("ilp32") && IsRV64) {67 errs() << "32-bit ABIs are not supported for 64-bit targets (ignoring "68 "target-abi)\n";69 TargetABI = ABI_Unknown;70 } else if (ABIName.starts_with("lp64") && !IsRV64) {71 errs() << "64-bit ABIs are not supported for 32-bit targets (ignoring "72 "target-abi)\n";73 TargetABI = ABI_Unknown;74 } else if (!IsRV64 && IsRVE && TargetABI != ABI_ILP32E &&75 TargetABI != ABI_Unknown) {76 // TODO: move this checking to RISCVTargetLowering and RISCVAsmParser77 errs()78 << "Only the ilp32e ABI is supported for RV32E (ignoring target-abi)\n";79 TargetABI = ABI_Unknown;80 } else if (IsRV64 && IsRVE && TargetABI != ABI_LP64E &&81 TargetABI != ABI_Unknown) {82 // TODO: move this checking to RISCVTargetLowering and RISCVAsmParser83 errs()84 << "Only the lp64e ABI is supported for RV64E (ignoring target-abi)\n";85 TargetABI = ABI_Unknown;86 }87 88 if ((TargetABI == RISCVABI::ABI::ABI_ILP32E ||89 (TargetABI == ABI_Unknown && IsRVE && !IsRV64)) &&90 FeatureBits[RISCV::FeatureStdExtD])91 reportFatalUsageError("ILP32E cannot be used with the D ISA extension");92 93 if (TargetABI != ABI_Unknown)94 return TargetABI;95 96 // If no explicit ABI is given, try to compute the default ABI.97 auto ISAInfo = RISCVFeatures::parseFeatureBits(IsRV64, FeatureBits);98 if (!ISAInfo)99 reportFatalUsageError(ISAInfo.takeError());100 return getTargetABI((*ISAInfo)->computeDefaultABI());101}102 103ABI getTargetABI(StringRef ABIName) {104 auto TargetABI = StringSwitch<ABI>(ABIName)105 .Case("ilp32", ABI_ILP32)106 .Case("ilp32f", ABI_ILP32F)107 .Case("ilp32d", ABI_ILP32D)108 .Case("ilp32e", ABI_ILP32E)109 .Case("lp64", ABI_LP64)110 .Case("lp64f", ABI_LP64F)111 .Case("lp64d", ABI_LP64D)112 .Case("lp64e", ABI_LP64E)113 .Default(ABI_Unknown);114 return TargetABI;115}116 117// To avoid the BP value clobbered by a function call, we need to choose a118// callee saved register to save the value. RV32E only has X8 and X9 as callee119// saved registers and X8 will be used as fp. So we choose X9 as bp.120MCRegister getBPReg() { return RISCV::X9; }121 122// Returns the register holding shadow call stack pointer.123MCRegister getSCSPReg() { return RISCV::X3; }124 125} // namespace RISCVABI126 127namespace RISCVFeatures {128 129void validate(const Triple &TT, const FeatureBitset &FeatureBits) {130 if (TT.isArch64Bit() && !FeatureBits[RISCV::Feature64Bit])131 reportFatalUsageError("RV64 target requires an RV64 CPU");132 if (!TT.isArch64Bit() && !FeatureBits[RISCV::Feature32Bit])133 reportFatalUsageError("RV32 target requires an RV32 CPU");134 if (FeatureBits[RISCV::Feature32Bit] &&135 FeatureBits[RISCV::Feature64Bit])136 reportFatalUsageError("RV32 and RV64 can't be combined");137}138 139llvm::Expected<std::unique_ptr<RISCVISAInfo>>140parseFeatureBits(bool IsRV64, const FeatureBitset &FeatureBits) {141 unsigned XLen = IsRV64 ? 64 : 32;142 std::vector<std::string> FeatureVector;143 // Convert FeatureBitset to FeatureVector.144 for (auto Feature : RISCVFeatureKV) {145 if (FeatureBits[Feature.Value] &&146 llvm::RISCVISAInfo::isSupportedExtensionFeature(Feature.Key))147 FeatureVector.push_back(std::string("+") + Feature.Key);148 }149 return llvm::RISCVISAInfo::parseFeatures(XLen, FeatureVector);150}151 152} // namespace RISCVFeatures153 154// Include the auto-generated portion of the compress emitter.155#define GEN_UNCOMPRESS_INSTR156#define GEN_COMPRESS_INSTR157#include "RISCVGenCompressInstEmitter.inc"158 159bool RISCVRVC::compress(MCInst &OutInst, const MCInst &MI,160 const MCSubtargetInfo &STI) {161 return compressInst(OutInst, MI, STI);162}163 164bool RISCVRVC::uncompress(MCInst &OutInst, const MCInst &MI,165 const MCSubtargetInfo &STI) {166 return uncompressInst(OutInst, MI, STI);167}168 169// Lookup table for fli.s for entries 2-31.170static constexpr std::pair<uint8_t, uint8_t> LoadFP32ImmArr[] = {171 {0b01101111, 0b00}, {0b01110000, 0b00}, {0b01110111, 0b00},172 {0b01111000, 0b00}, {0b01111011, 0b00}, {0b01111100, 0b00},173 {0b01111101, 0b00}, {0b01111101, 0b01}, {0b01111101, 0b10},174 {0b01111101, 0b11}, {0b01111110, 0b00}, {0b01111110, 0b01},175 {0b01111110, 0b10}, {0b01111110, 0b11}, {0b01111111, 0b00},176 {0b01111111, 0b01}, {0b01111111, 0b10}, {0b01111111, 0b11},177 {0b10000000, 0b00}, {0b10000000, 0b01}, {0b10000000, 0b10},178 {0b10000001, 0b00}, {0b10000010, 0b00}, {0b10000011, 0b00},179 {0b10000110, 0b00}, {0b10000111, 0b00}, {0b10001110, 0b00},180 {0b10001111, 0b00}, {0b11111111, 0b00}, {0b11111111, 0b10},181};182 183int RISCVLoadFPImm::getLoadFPImm(APFloat FPImm) {184 assert((&FPImm.getSemantics() == &APFloat::IEEEsingle() ||185 &FPImm.getSemantics() == &APFloat::IEEEdouble() ||186 &FPImm.getSemantics() == &APFloat::IEEEhalf()) &&187 "Unexpected semantics");188 189 // Handle the minimum normalized value which is different for each type.190 if (FPImm.isSmallestNormalized() && !FPImm.isNegative())191 return 1;192 193 // Convert to single precision to use its lookup table.194 bool LosesInfo;195 APFloat::opStatus Status = FPImm.convert(196 APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven, &LosesInfo);197 if (Status != APFloat::opOK || LosesInfo)198 return -1;199 200 APInt Imm = FPImm.bitcastToAPInt();201 202 if (Imm.extractBitsAsZExtValue(21, 0) != 0)203 return -1;204 205 bool Sign = Imm.extractBitsAsZExtValue(1, 31);206 uint8_t Mantissa = Imm.extractBitsAsZExtValue(2, 21);207 uint8_t Exp = Imm.extractBitsAsZExtValue(8, 23);208 209 auto EMI = llvm::lower_bound(LoadFP32ImmArr, std::make_pair(Exp, Mantissa));210 if (EMI == std::end(LoadFP32ImmArr) || EMI->first != Exp ||211 EMI->second != Mantissa)212 return -1;213 214 // Table doesn't have entry 0 or 1.215 int Entry = std::distance(std::begin(LoadFP32ImmArr), EMI) + 2;216 217 // The only legal negative value is -1.0(entry 0). 1.0 is entry 16.218 if (Sign) {219 if (Entry == 16)220 return 0;221 return -1;222 }223 224 return Entry;225}226 227float RISCVLoadFPImm::getFPImm(unsigned Imm) {228 assert(Imm != 1 && Imm != 30 && Imm != 31 && "Unsupported immediate");229 230 // Entry 0 is -1.0, the only negative value. Entry 16 is 1.0.231 uint32_t Sign = 0;232 if (Imm == 0) {233 Sign = 0b1;234 Imm = 16;235 }236 237 uint32_t Exp = LoadFP32ImmArr[Imm - 2].first;238 uint32_t Mantissa = LoadFP32ImmArr[Imm - 2].second;239 240 uint32_t I = Sign << 31 | Exp << 23 | Mantissa << 21;241 return bit_cast<float>(I);242}243 244void RISCVZC::printRegList(unsigned RlistEncode, raw_ostream &OS) {245 assert(RlistEncode >= RLISTENCODE::RA &&246 RlistEncode <= RLISTENCODE::RA_S0_S11 && "Invalid Rlist");247 OS << "{ra";248 if (RlistEncode > RISCVZC::RA) {249 OS << ", s0";250 if (RlistEncode == RISCVZC::RA_S0_S11)251 OS << "-s11";252 else if (RlistEncode > RISCVZC::RA_S0 && RlistEncode <= RISCVZC::RA_S0_S11)253 OS << "-s" << (RlistEncode - RISCVZC::RA_S0);254 }255 OS << "}";256}257 258} // namespace llvm259