1 //===-- RISCVBaseInfo.cpp - Top level definitions for RISC-V MC -----------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file contains small standalone enum definitions for the RISC-V target
10 // useful for the compiler back-end and the MC libraries.
12 //===----------------------------------------------------------------------===//
14 #include "RISCVBaseInfo.h"
15 #include "llvm/ADT/ArrayRef.h"
16 #include "llvm/MC/MCInst.h"
17 #include "llvm/MC/MCRegisterInfo.h"
18 #include "llvm/MC/MCSubtargetInfo.h"
19 #include "llvm/Support/RISCVISAInfo.h"
20 #include "llvm/Support/raw_ostream.h"
21 #include "llvm/TargetParser/TargetParser.h"
22 #include "llvm/TargetParser/Triple.h"
26 extern const SubtargetFeatureKV RISCVFeatureKV
[RISCV::NumSubtargetFeatures
];
28 namespace RISCVSysReg
{
29 #define GET_SysRegsList_IMPL
30 #define GET_SiFiveRegsList_IMPL
31 #include "RISCVGenSearchableTables.inc"
32 } // namespace RISCVSysReg
34 namespace RISCVInsnOpcode
{
35 #define GET_RISCVOpcodesList_IMPL
36 #include "RISCVGenSearchableTables.inc"
37 } // namespace RISCVInsnOpcode
40 ABI
computeTargetABI(const Triple
&TT
, const FeatureBitset
&FeatureBits
,
42 auto TargetABI
= getTargetABI(ABIName
);
43 bool IsRV64
= TT
.isArch64Bit();
44 bool IsRVE
= FeatureBits
[RISCV::FeatureRVE
];
46 if (!ABIName
.empty() && TargetABI
== ABI_Unknown
) {
49 << "' is not a recognized ABI for this target (ignoring target-abi)\n";
50 } else if (ABIName
.startswith("ilp32") && IsRV64
) {
51 errs() << "32-bit ABIs are not supported for 64-bit targets (ignoring "
53 TargetABI
= ABI_Unknown
;
54 } else if (ABIName
.startswith("lp64") && !IsRV64
) {
55 errs() << "64-bit ABIs are not supported for 32-bit targets (ignoring "
57 TargetABI
= ABI_Unknown
;
58 } else if (!IsRV64
&& IsRVE
&& TargetABI
!= ABI_ILP32E
&&
59 TargetABI
!= ABI_Unknown
) {
60 // TODO: move this checking to RISCVTargetLowering and RISCVAsmParser
62 << "Only the ilp32e ABI is supported for RV32E (ignoring target-abi)\n";
63 TargetABI
= ABI_Unknown
;
64 } else if (IsRV64
&& IsRVE
&& TargetABI
!= ABI_LP64E
&&
65 TargetABI
!= ABI_Unknown
) {
66 // TODO: move this checking to RISCVTargetLowering and RISCVAsmParser
68 << "Only the lp64e ABI is supported for RV64E (ignoring target-abi)\n";
69 TargetABI
= ABI_Unknown
;
72 if (TargetABI
!= ABI_Unknown
)
75 // If no explicit ABI is given, try to compute the default ABI.
76 auto ISAInfo
= RISCVFeatures::parseFeatureBits(IsRV64
, FeatureBits
);
78 report_fatal_error(ISAInfo
.takeError());
79 return getTargetABI((*ISAInfo
)->computeDefaultABI());
82 ABI
getTargetABI(StringRef ABIName
) {
83 auto TargetABI
= StringSwitch
<ABI
>(ABIName
)
84 .Case("ilp32", ABI_ILP32
)
85 .Case("ilp32f", ABI_ILP32F
)
86 .Case("ilp32d", ABI_ILP32D
)
87 .Case("ilp32e", ABI_ILP32E
)
88 .Case("lp64", ABI_LP64
)
89 .Case("lp64f", ABI_LP64F
)
90 .Case("lp64d", ABI_LP64D
)
91 .Case("lp64e", ABI_LP64E
)
92 .Default(ABI_Unknown
);
96 // To avoid the BP value clobbered by a function call, we need to choose a
97 // callee saved register to save the value. RV32E only has X8 and X9 as callee
98 // saved registers and X8 will be used as fp. So we choose X9 as bp.
99 MCRegister
getBPReg() { return RISCV::X9
; }
101 // Returns the register holding shadow call stack pointer.
102 MCRegister
getSCSPReg() { return RISCV::X3
; }
104 } // namespace RISCVABI
106 namespace RISCVFeatures
{
108 void validate(const Triple
&TT
, const FeatureBitset
&FeatureBits
) {
109 if (TT
.isArch64Bit() && !FeatureBits
[RISCV::Feature64Bit
])
110 report_fatal_error("RV64 target requires an RV64 CPU");
111 if (!TT
.isArch64Bit() && !FeatureBits
[RISCV::Feature32Bit
])
112 report_fatal_error("RV32 target requires an RV32 CPU");
113 if (FeatureBits
[RISCV::Feature32Bit
] &&
114 FeatureBits
[RISCV::Feature64Bit
])
115 report_fatal_error("RV32 and RV64 can't be combined");
118 llvm::Expected
<std::unique_ptr
<RISCVISAInfo
>>
119 parseFeatureBits(bool IsRV64
, const FeatureBitset
&FeatureBits
) {
120 unsigned XLen
= IsRV64
? 64 : 32;
121 std::vector
<std::string
> FeatureVector
;
122 // Convert FeatureBitset to FeatureVector.
123 for (auto Feature
: RISCVFeatureKV
) {
124 if (FeatureBits
[Feature
.Value
] &&
125 llvm::RISCVISAInfo::isSupportedExtensionFeature(Feature
.Key
))
126 FeatureVector
.push_back(std::string("+") + Feature
.Key
);
128 return llvm::RISCVISAInfo::parseFeatures(XLen
, FeatureVector
);
131 } // namespace RISCVFeatures
133 // Encode VTYPE into the binary format used by the the VSETVLI instruction which
134 // is used by our MC layer representation.
136 // Bits | Name | Description
137 // -----+------------+------------------------------------------------
138 // 7 | vma | Vector mask agnostic
139 // 6 | vta | Vector tail agnostic
140 // 5:3 | vsew[2:0] | Standard element width (SEW) setting
141 // 2:0 | vlmul[2:0] | Vector register group multiplier (LMUL) setting
142 unsigned RISCVVType::encodeVTYPE(RISCVII::VLMUL VLMUL
, unsigned SEW
,
143 bool TailAgnostic
, bool MaskAgnostic
) {
144 assert(isValidSEW(SEW
) && "Invalid SEW");
145 unsigned VLMULBits
= static_cast<unsigned>(VLMUL
);
146 unsigned VSEWBits
= encodeSEW(SEW
);
147 unsigned VTypeI
= (VSEWBits
<< 3) | (VLMULBits
& 0x7);
156 std::pair
<unsigned, bool> RISCVVType::decodeVLMUL(RISCVII::VLMUL VLMUL
) {
159 llvm_unreachable("Unexpected LMUL value!");
160 case RISCVII::VLMUL::LMUL_1
:
161 case RISCVII::VLMUL::LMUL_2
:
162 case RISCVII::VLMUL::LMUL_4
:
163 case RISCVII::VLMUL::LMUL_8
:
164 return std::make_pair(1 << static_cast<unsigned>(VLMUL
), false);
165 case RISCVII::VLMUL::LMUL_F2
:
166 case RISCVII::VLMUL::LMUL_F4
:
167 case RISCVII::VLMUL::LMUL_F8
:
168 return std::make_pair(1 << (8 - static_cast<unsigned>(VLMUL
)), true);
172 void RISCVVType::printVType(unsigned VType
, raw_ostream
&OS
) {
173 unsigned Sew
= getSEW(VType
);
178 std::tie(LMul
, Fractional
) = decodeVLMUL(getVLMUL(VType
));
186 if (isTailAgnostic(VType
))
191 if (isMaskAgnostic(VType
))
197 unsigned RISCVVType::getSEWLMULRatio(unsigned SEW
, RISCVII::VLMUL VLMul
) {
200 std::tie(LMul
, Fractional
) = decodeVLMUL(VLMul
);
202 // Convert LMul to a fixed point value with 3 fractional bits.
203 LMul
= Fractional
? (8 / LMul
) : (LMul
* 8);
205 assert(SEW
>= 8 && "Unexpected SEW value");
206 return (SEW
* 8) / LMul
;
209 std::optional
<RISCVII::VLMUL
>
210 RISCVVType::getSameRatioLMUL(unsigned SEW
, RISCVII::VLMUL VLMUL
, unsigned EEW
) {
211 unsigned Ratio
= RISCVVType::getSEWLMULRatio(SEW
, VLMUL
);
212 unsigned EMULFixedPoint
= (EEW
* 8) / Ratio
;
213 bool Fractional
= EMULFixedPoint
< 8;
214 unsigned EMUL
= Fractional
? 8 / EMULFixedPoint
: EMULFixedPoint
/ 8;
215 if (!isValidLMUL(EMUL
, Fractional
))
217 return RISCVVType::encodeLMUL(EMUL
, Fractional
);
220 // Include the auto-generated portion of the compress emitter.
221 #define GEN_UNCOMPRESS_INSTR
222 #define GEN_COMPRESS_INSTR
223 #include "RISCVGenCompressInstEmitter.inc"
225 bool RISCVRVC::compress(MCInst
&OutInst
, const MCInst
&MI
,
226 const MCSubtargetInfo
&STI
) {
227 return compressInst(OutInst
, MI
, STI
);
230 bool RISCVRVC::uncompress(MCInst
&OutInst
, const MCInst
&MI
,
231 const MCSubtargetInfo
&STI
) {
232 return uncompressInst(OutInst
, MI
, STI
);
235 // Lookup table for fli.s for entries 2-31.
236 static constexpr std::pair
<uint8_t, uint8_t> LoadFP32ImmArr
[] = {
237 {0b01101111, 0b00}, {0b01110000, 0b00}, {0b01110111, 0b00},
238 {0b01111000, 0b00}, {0b01111011, 0b00}, {0b01111100, 0b00},
239 {0b01111101, 0b00}, {0b01111101, 0b01}, {0b01111101, 0b10},
240 {0b01111101, 0b11}, {0b01111110, 0b00}, {0b01111110, 0b01},
241 {0b01111110, 0b10}, {0b01111110, 0b11}, {0b01111111, 0b00},
242 {0b01111111, 0b01}, {0b01111111, 0b10}, {0b01111111, 0b11},
243 {0b10000000, 0b00}, {0b10000000, 0b01}, {0b10000000, 0b10},
244 {0b10000001, 0b00}, {0b10000010, 0b00}, {0b10000011, 0b00},
245 {0b10000110, 0b00}, {0b10000111, 0b00}, {0b10001110, 0b00},
246 {0b10001111, 0b00}, {0b11111111, 0b00}, {0b11111111, 0b10},
249 int RISCVLoadFPImm::getLoadFPImm(APFloat FPImm
) {
250 assert((&FPImm
.getSemantics() == &APFloat::IEEEsingle() ||
251 &FPImm
.getSemantics() == &APFloat::IEEEdouble() ||
252 &FPImm
.getSemantics() == &APFloat::IEEEhalf()) &&
253 "Unexpected semantics");
255 // Handle the minimum normalized value which is different for each type.
256 if (FPImm
.isSmallestNormalized() && !FPImm
.isNegative())
259 // Convert to single precision to use its lookup table.
261 APFloat::opStatus Status
= FPImm
.convert(
262 APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven
, &LosesInfo
);
263 if (Status
!= APFloat::opOK
|| LosesInfo
)
266 APInt Imm
= FPImm
.bitcastToAPInt();
268 if (Imm
.extractBitsAsZExtValue(21, 0) != 0)
271 bool Sign
= Imm
.extractBitsAsZExtValue(1, 31);
272 uint8_t Mantissa
= Imm
.extractBitsAsZExtValue(2, 21);
273 uint8_t Exp
= Imm
.extractBitsAsZExtValue(8, 23);
275 auto EMI
= llvm::lower_bound(LoadFP32ImmArr
, std::make_pair(Exp
, Mantissa
));
276 if (EMI
== std::end(LoadFP32ImmArr
) || EMI
->first
!= Exp
||
277 EMI
->second
!= Mantissa
)
280 // Table doesn't have entry 0 or 1.
281 int Entry
= std::distance(std::begin(LoadFP32ImmArr
), EMI
) + 2;
283 // The only legal negative value is -1.0(entry 0). 1.0 is entry 16.
293 float RISCVLoadFPImm::getFPImm(unsigned Imm
) {
294 assert(Imm
!= 1 && Imm
!= 30 && Imm
!= 31 && "Unsupported immediate");
296 // Entry 0 is -1.0, the only negative value. Entry 16 is 1.0.
303 uint32_t Exp
= LoadFP32ImmArr
[Imm
- 2].first
;
304 uint32_t Mantissa
= LoadFP32ImmArr
[Imm
- 2].second
;
306 uint32_t I
= Sign
<< 31 | Exp
<< 23 | Mantissa
<< 21;
307 return bit_cast
<float>(I
);
310 void RISCVZC::printRlist(unsigned SlistEncode
, raw_ostream
&OS
) {
312 if (SlistEncode
> 4) {
314 if (SlistEncode
== 15)
316 else if (SlistEncode
> 5 && SlistEncode
<= 14)
317 OS
<< "-s" << (SlistEncode
- 5);
322 void RISCVZC::printSpimm(int64_t Spimm
, raw_ostream
&OS
) { OS
<< Spimm
; }