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-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains small standalone enum definitions for the RISC-V target
10// 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_IMPL
28#include "RISCVGenSearchableTables.inc"
29} // namespace RISCVSysReg
30
31namespace RISCVInsnOpcode {
32#define GET_RISCVOpcodesList_IMPL
33#include "RISCVGenSearchableTables.inc"
34} // namespace RISCVInsnOpcode
35
36namespace RISCVVInversePseudosTable {
37using namespace RISCV;
38#define GET_RISCVVInversePseudosTable_IMPL
39#include "RISCVGenSearchableTables.inc"
40} // namespace RISCVVInversePseudosTable
41
42namespace RISCV {
43#define GET_RISCVVSSEGTable_IMPL
44#define GET_RISCVVLSEGTable_IMPL
45#define GET_RISCVVLXSEGTable_IMPL
46#define GET_RISCVVSXSEGTable_IMPL
47#define GET_RISCVVLETable_IMPL
48#define GET_RISCVVSETable_IMPL
49#define GET_RISCVVLXTable_IMPL
50#define GET_RISCVVSXTable_IMPL
51#include "RISCVGenSearchableTables.inc"
52} // namespace RISCV
53
54// Report an error but don't ask the user to report a bug.
55// TODO: Remove these wrappers.
56[[noreturn]] static void reportError(const char *Reason) {
57 reportFatalUsageError(reason: Reason);
58}
59[[noreturn]] static void reportError(Error Err) {
60 reportFatalUsageError(Err: std::move(Err));
61}
62
63namespace RISCVABI {
64ABI computeTargetABI(const Triple &TT, const FeatureBitset &FeatureBits,
65 StringRef ABIName) {
66 auto TargetABI = getTargetABI(ABIName);
67 bool IsRV64 = TT.isArch64Bit();
68 bool IsRVE = FeatureBits[RISCV::FeatureStdExtE];
69
70 if (!ABIName.empty() && TargetABI == ABI_Unknown) {
71 errs()
72 << "'" << ABIName
73 << "' is not a recognized ABI for this target (ignoring target-abi)\n";
74 } else if (ABIName.starts_with(Prefix: "ilp32") && IsRV64) {
75 errs() << "32-bit ABIs are not supported for 64-bit targets (ignoring "
76 "target-abi)\n";
77 TargetABI = ABI_Unknown;
78 } else if (ABIName.starts_with(Prefix: "lp64") && !IsRV64) {
79 errs() << "64-bit ABIs are not supported for 32-bit targets (ignoring "
80 "target-abi)\n";
81 TargetABI = ABI_Unknown;
82 } else if (!IsRV64 && IsRVE && TargetABI != ABI_ILP32E &&
83 TargetABI != ABI_Unknown) {
84 // TODO: move this checking to RISCVTargetLowering and RISCVAsmParser
85 errs()
86 << "Only the ilp32e ABI is supported for RV32E (ignoring target-abi)\n";
87 TargetABI = ABI_Unknown;
88 } else if (IsRV64 && IsRVE && TargetABI != ABI_LP64E &&
89 TargetABI != ABI_Unknown) {
90 // TODO: move this checking to RISCVTargetLowering and RISCVAsmParser
91 errs()
92 << "Only the lp64e ABI is supported for RV64E (ignoring target-abi)\n";
93 TargetABI = ABI_Unknown;
94 }
95
96 if ((TargetABI == RISCVABI::ABI::ABI_ILP32E ||
97 (TargetABI == ABI_Unknown && IsRVE && !IsRV64)) &&
98 FeatureBits[RISCV::FeatureStdExtD])
99 reportError(Reason: "ILP32E cannot be used with the D ISA extension");
100
101 if (TargetABI != ABI_Unknown)
102 return TargetABI;
103
104 // If no explicit ABI is given, try to compute the default ABI.
105 auto ISAInfo = RISCVFeatures::parseFeatureBits(IsRV64, FeatureBits);
106 if (!ISAInfo)
107 reportError(Err: ISAInfo.takeError());
108 return getTargetABI(ABIName: (*ISAInfo)->computeDefaultABI());
109}
110
111ABI getTargetABI(StringRef ABIName) {
112 auto TargetABI = StringSwitch<ABI>(ABIName)
113 .Case(S: "ilp32", Value: ABI_ILP32)
114 .Case(S: "ilp32f", Value: ABI_ILP32F)
115 .Case(S: "ilp32d", Value: ABI_ILP32D)
116 .Case(S: "ilp32e", Value: ABI_ILP32E)
117 .Case(S: "lp64", Value: ABI_LP64)
118 .Case(S: "lp64f", Value: ABI_LP64F)
119 .Case(S: "lp64d", Value: ABI_LP64D)
120 .Case(S: "lp64e", Value: ABI_LP64E)
121 .Default(Value: ABI_Unknown);
122 return TargetABI;
123}
124
125// To avoid the BP value clobbered by a function call, we need to choose a
126// callee saved register to save the value. RV32E only has X8 and X9 as callee
127// saved registers and X8 will be used as fp. So we choose X9 as bp.
128MCRegister getBPReg() { return RISCV::X9; }
129
130// Returns the register holding shadow call stack pointer.
131MCRegister getSCSPReg() { return RISCV::X3; }
132
133} // namespace RISCVABI
134
135namespace RISCVFeatures {
136
137void validate(const Triple &TT, const FeatureBitset &FeatureBits) {
138 if (TT.isArch64Bit() && !FeatureBits[RISCV::Feature64Bit])
139 reportError(Reason: "RV64 target requires an RV64 CPU");
140 if (!TT.isArch64Bit() && !FeatureBits[RISCV::Feature32Bit])
141 reportError(Reason: "RV32 target requires an RV32 CPU");
142 if (FeatureBits[RISCV::Feature32Bit] &&
143 FeatureBits[RISCV::Feature64Bit])
144 reportError(Reason: "RV32 and RV64 can't be combined");
145}
146
147llvm::Expected<std::unique_ptr<RISCVISAInfo>>
148parseFeatureBits(bool IsRV64, const FeatureBitset &FeatureBits) {
149 unsigned XLen = IsRV64 ? 64 : 32;
150 std::vector<std::string> FeatureVector;
151 // Convert FeatureBitset to FeatureVector.
152 for (auto Feature : RISCVFeatureKV) {
153 if (FeatureBits[Feature.Value] &&
154 llvm::RISCVISAInfo::isSupportedExtensionFeature(Ext: Feature.Key))
155 FeatureVector.push_back(x: std::string("+") + Feature.Key);
156 }
157 return llvm::RISCVISAInfo::parseFeatures(XLen, Features: FeatureVector);
158}
159
160} // namespace RISCVFeatures
161
162// Include the auto-generated portion of the compress emitter.
163#define GEN_UNCOMPRESS_INSTR
164#define GEN_COMPRESS_INSTR
165#include "RISCVGenCompressInstEmitter.inc"
166
167bool RISCVRVC::compress(MCInst &OutInst, const MCInst &MI,
168 const MCSubtargetInfo &STI) {
169 return compressInst(OutInst, MI, STI);
170}
171
172bool RISCVRVC::uncompress(MCInst &OutInst, const MCInst &MI,
173 const MCSubtargetInfo &STI) {
174 return uncompressInst(OutInst, MI, STI);
175}
176
177// Lookup table for fli.s for entries 2-31.
178static constexpr std::pair<uint8_t, uint8_t> LoadFP32ImmArr[] = {
179 {0b01101111, 0b00}, {0b01110000, 0b00}, {0b01110111, 0b00},
180 {0b01111000, 0b00}, {0b01111011, 0b00}, {0b01111100, 0b00},
181 {0b01111101, 0b00}, {0b01111101, 0b01}, {0b01111101, 0b10},
182 {0b01111101, 0b11}, {0b01111110, 0b00}, {0b01111110, 0b01},
183 {0b01111110, 0b10}, {0b01111110, 0b11}, {0b01111111, 0b00},
184 {0b01111111, 0b01}, {0b01111111, 0b10}, {0b01111111, 0b11},
185 {0b10000000, 0b00}, {0b10000000, 0b01}, {0b10000000, 0b10},
186 {0b10000001, 0b00}, {0b10000010, 0b00}, {0b10000011, 0b00},
187 {0b10000110, 0b00}, {0b10000111, 0b00}, {0b10001110, 0b00},
188 {0b10001111, 0b00}, {0b11111111, 0b00}, {0b11111111, 0b10},
189};
190
191int RISCVLoadFPImm::getLoadFPImm(APFloat FPImm) {
192 assert((&FPImm.getSemantics() == &APFloat::IEEEsingle() ||
193 &FPImm.getSemantics() == &APFloat::IEEEdouble() ||
194 &FPImm.getSemantics() == &APFloat::IEEEhalf()) &&
195 "Unexpected semantics");
196
197 // Handle the minimum normalized value which is different for each type.
198 if (FPImm.isSmallestNormalized() && !FPImm.isNegative())
199 return 1;
200
201 // Convert to single precision to use its lookup table.
202 bool LosesInfo;
203 APFloat::opStatus Status = FPImm.convert(
204 ToSemantics: APFloat::IEEEsingle(), RM: APFloat::rmNearestTiesToEven, losesInfo: &LosesInfo);
205 if (Status != APFloat::opOK || LosesInfo)
206 return -1;
207
208 APInt Imm = FPImm.bitcastToAPInt();
209
210 if (Imm.extractBitsAsZExtValue(numBits: 21, bitPosition: 0) != 0)
211 return -1;
212
213 bool Sign = Imm.extractBitsAsZExtValue(numBits: 1, bitPosition: 31);
214 uint8_t Mantissa = Imm.extractBitsAsZExtValue(numBits: 2, bitPosition: 21);
215 uint8_t Exp = Imm.extractBitsAsZExtValue(numBits: 8, bitPosition: 23);
216
217 auto EMI = llvm::lower_bound(Range: LoadFP32ImmArr, Value: std::make_pair(x&: Exp, y&: Mantissa));
218 if (EMI == std::end(arr: LoadFP32ImmArr) || EMI->first != Exp ||
219 EMI->second != Mantissa)
220 return -1;
221
222 // Table doesn't have entry 0 or 1.
223 int Entry = std::distance(first: std::begin(arr: LoadFP32ImmArr), last: EMI) + 2;
224
225 // The only legal negative value is -1.0(entry 0). 1.0 is entry 16.
226 if (Sign) {
227 if (Entry == 16)
228 return 0;
229 return -1;
230 }
231
232 return Entry;
233}
234
235float RISCVLoadFPImm::getFPImm(unsigned Imm) {
236 assert(Imm != 1 && Imm != 30 && Imm != 31 && "Unsupported immediate");
237
238 // Entry 0 is -1.0, the only negative value. Entry 16 is 1.0.
239 uint32_t Sign = 0;
240 if (Imm == 0) {
241 Sign = 0b1;
242 Imm = 16;
243 }
244
245 uint32_t Exp = LoadFP32ImmArr[Imm - 2].first;
246 uint32_t Mantissa = LoadFP32ImmArr[Imm - 2].second;
247
248 uint32_t I = Sign << 31 | Exp << 23 | Mantissa << 21;
249 return bit_cast<float>(from: I);
250}
251
252void RISCVZC::printRegList(unsigned RlistEncode, raw_ostream &OS) {
253 assert(RlistEncode >= RLISTENCODE::RA &&
254 RlistEncode <= RLISTENCODE::RA_S0_S11 && "Invalid Rlist");
255 OS << "{ra";
256 if (RlistEncode > RISCVZC::RA) {
257 OS << ", s0";
258 if (RlistEncode == RISCVZC::RA_S0_S11)
259 OS << "-s11";
260 else if (RlistEncode > RISCVZC::RA_S0 && RlistEncode <= RISCVZC::RA_S0_S11)
261 OS << "-s" << (RlistEncode - RISCVZC::RA_S0);
262 }
263 OS << "}";
264}
265
266} // namespace llvm
267