1 //===-- RISCVBaseInfo.h - Top level definitions for RISCV MC ----*- C++ -*-===// 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 RISCV target 10 // useful for the compiler back-end and the MC libraries. 11 // 12 //===----------------------------------------------------------------------===// 13 #ifndef LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVBASEINFO_H 14 #define LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVBASEINFO_H 15 16 #include "MCTargetDesc/RISCVMCTargetDesc.h" 17 #include "llvm/ADT/StringRef.h" 18 #include "llvm/ADT/StringSwitch.h" 19 #include "llvm/MC/MCInstrDesc.h" 20 #include "llvm/MC/SubtargetFeature.h" 21 22 namespace llvm { 23 24 // RISCVII - This namespace holds all of the target specific flags that 25 // instruction info tracks. All definitions must match RISCVInstrFormats.td. 26 namespace RISCVII { 27 enum { 28 InstFormatPseudo = 0, 29 InstFormatR = 1, 30 InstFormatR4 = 2, 31 InstFormatI = 3, 32 InstFormatS = 4, 33 InstFormatB = 5, 34 InstFormatU = 6, 35 InstFormatJ = 7, 36 InstFormatCR = 8, 37 InstFormatCI = 9, 38 InstFormatCSS = 10, 39 InstFormatCIW = 11, 40 InstFormatCL = 12, 41 InstFormatCS = 13, 42 InstFormatCA = 14, 43 InstFormatCB = 15, 44 InstFormatCJ = 16, 45 InstFormatOther = 17, 46 47 InstFormatMask = 31, 48 InstFormatShift = 0, 49 50 ConstraintShift = InstFormatShift + 5, 51 ConstraintMask = 0b111 << ConstraintShift, 52 53 VLMulShift = ConstraintShift + 3, 54 VLMulMask = 0b111 << VLMulShift, 55 56 // Do we need to add a dummy mask op when converting RVV Pseudo to MCInst. 57 HasDummyMaskOpShift = VLMulShift + 3, 58 HasDummyMaskOpMask = 1 << HasDummyMaskOpShift, 59 60 // Force a tail agnostic policy even this instruction has a tied destination. 61 ForceTailAgnosticShift = HasDummyMaskOpShift + 1, 62 ForceTailAgnosticMask = 1 << ForceTailAgnosticShift, 63 64 // Does this instruction have a merge operand that must be removed when 65 // converting to MCInst. It will be the first explicit use operand. Used by 66 // RVV Pseudos. 67 HasMergeOpShift = ForceTailAgnosticShift + 1, 68 HasMergeOpMask = 1 << HasMergeOpShift, 69 70 // Does this instruction have a SEW operand. It will be the last explicit 71 // operand. Used by RVV Pseudos. 72 HasSEWOpShift = HasMergeOpShift + 1, 73 HasSEWOpMask = 1 << HasSEWOpShift, 74 75 // Does this instruction have a VL operand. It will be the second to last 76 // explicit operand. Used by RVV Pseudos. 77 HasVLOpShift = HasSEWOpShift + 1, 78 HasVLOpMask = 1 << HasVLOpShift, 79 }; 80 81 // Match with the definitions in RISCVInstrFormatsV.td 82 enum VConstraintType { 83 NoConstraint = 0, 84 VS2Constraint = 0b001, 85 VS1Constraint = 0b010, 86 VMConstraint = 0b100, 87 }; 88 89 enum VLMUL : uint8_t { 90 LMUL_1 = 0, 91 LMUL_2, 92 LMUL_4, 93 LMUL_8, 94 LMUL_RESERVED, 95 LMUL_F8, 96 LMUL_F4, 97 LMUL_F2 98 }; 99 100 // Helper functions to read TSFlags. 101 /// \returns the format of the instruction. 102 static inline unsigned getFormat(uint64_t TSFlags) { 103 return (TSFlags & InstFormatMask) >> InstFormatShift; 104 } 105 /// \returns the constraint for the instruction. 106 static inline VConstraintType getConstraint(uint64_t TSFlags) { 107 return static_cast<VConstraintType> 108 ((TSFlags & ConstraintMask) >> ConstraintShift); 109 } 110 /// \returns the LMUL for the instruction. 111 static inline VLMUL getLMul(uint64_t TSFlags) { 112 return static_cast<VLMUL>((TSFlags & VLMulMask) >> VLMulShift); 113 } 114 /// \returns true if there is a dummy mask operand for the instruction. 115 static inline bool hasDummyMaskOp(uint64_t TSFlags) { 116 return TSFlags & HasDummyMaskOpMask; 117 } 118 /// \returns true if tail agnostic is enforced for the instruction. 119 static inline bool doesForceTailAgnostic(uint64_t TSFlags) { 120 return TSFlags & ForceTailAgnosticMask; 121 } 122 /// \returns true if there is a merge operand for the instruction. 123 static inline bool hasMergeOp(uint64_t TSFlags) { 124 return TSFlags & HasMergeOpMask; 125 } 126 /// \returns true if there is a SEW operand for the instruction. 127 static inline bool hasSEWOp(uint64_t TSFlags) { 128 return TSFlags & HasSEWOpMask; 129 } 130 /// \returns true if there is a VL operand for the instruction. 131 static inline bool hasVLOp(uint64_t TSFlags) { 132 return TSFlags & HasVLOpMask; 133 } 134 135 // RISC-V Specific Machine Operand Flags 136 enum { 137 MO_None = 0, 138 MO_CALL = 1, 139 MO_PLT = 2, 140 MO_LO = 3, 141 MO_HI = 4, 142 MO_PCREL_LO = 5, 143 MO_PCREL_HI = 6, 144 MO_GOT_HI = 7, 145 MO_TPREL_LO = 8, 146 MO_TPREL_HI = 9, 147 MO_TPREL_ADD = 10, 148 MO_TLS_GOT_HI = 11, 149 MO_TLS_GD_HI = 12, 150 151 // Used to differentiate between target-specific "direct" flags and "bitmask" 152 // flags. A machine operand can only have one "direct" flag, but can have 153 // multiple "bitmask" flags. 154 MO_DIRECT_FLAG_MASK = 15 155 }; 156 } // namespace RISCVII 157 158 namespace RISCVOp { 159 enum OperandType : unsigned { 160 OPERAND_FIRST_RISCV_IMM = MCOI::OPERAND_FIRST_TARGET, 161 OPERAND_UIMM4 = OPERAND_FIRST_RISCV_IMM, 162 OPERAND_UIMM5, 163 OPERAND_UIMM12, 164 OPERAND_SIMM12, 165 OPERAND_UIMM20, 166 OPERAND_UIMMLOG2XLEN, 167 OPERAND_LAST_RISCV_IMM = OPERAND_UIMMLOG2XLEN, 168 // Operand is either a register or uimm5, this is used by V extension pseudo 169 // instructions to represent a value that be passed as AVL to either vsetvli 170 // or vsetivli. 171 OPERAND_AVL, 172 }; 173 } // namespace RISCVOp 174 175 // Describes the predecessor/successor bits used in the FENCE instruction. 176 namespace RISCVFenceField { 177 enum FenceField { 178 I = 8, 179 O = 4, 180 R = 2, 181 W = 1 182 }; 183 } 184 185 // Describes the supported floating point rounding mode encodings. 186 namespace RISCVFPRndMode { 187 enum RoundingMode { 188 RNE = 0, 189 RTZ = 1, 190 RDN = 2, 191 RUP = 3, 192 RMM = 4, 193 DYN = 7, 194 Invalid 195 }; 196 197 inline static StringRef roundingModeToString(RoundingMode RndMode) { 198 switch (RndMode) { 199 default: 200 llvm_unreachable("Unknown floating point rounding mode"); 201 case RISCVFPRndMode::RNE: 202 return "rne"; 203 case RISCVFPRndMode::RTZ: 204 return "rtz"; 205 case RISCVFPRndMode::RDN: 206 return "rdn"; 207 case RISCVFPRndMode::RUP: 208 return "rup"; 209 case RISCVFPRndMode::RMM: 210 return "rmm"; 211 case RISCVFPRndMode::DYN: 212 return "dyn"; 213 } 214 } 215 216 inline static RoundingMode stringToRoundingMode(StringRef Str) { 217 return StringSwitch<RoundingMode>(Str) 218 .Case("rne", RISCVFPRndMode::RNE) 219 .Case("rtz", RISCVFPRndMode::RTZ) 220 .Case("rdn", RISCVFPRndMode::RDN) 221 .Case("rup", RISCVFPRndMode::RUP) 222 .Case("rmm", RISCVFPRndMode::RMM) 223 .Case("dyn", RISCVFPRndMode::DYN) 224 .Default(RISCVFPRndMode::Invalid); 225 } 226 227 inline static bool isValidRoundingMode(unsigned Mode) { 228 switch (Mode) { 229 default: 230 return false; 231 case RISCVFPRndMode::RNE: 232 case RISCVFPRndMode::RTZ: 233 case RISCVFPRndMode::RDN: 234 case RISCVFPRndMode::RUP: 235 case RISCVFPRndMode::RMM: 236 case RISCVFPRndMode::DYN: 237 return true; 238 } 239 } 240 } // namespace RISCVFPRndMode 241 242 namespace RISCVSysReg { 243 struct SysReg { 244 const char *Name; 245 const char *AltName; 246 const char *DeprecatedName; 247 unsigned Encoding; 248 // FIXME: add these additional fields when needed. 249 // Privilege Access: Read, Write, Read-Only. 250 // unsigned ReadWrite; 251 // Privilege Mode: User, System or Machine. 252 // unsigned Mode; 253 // Check field name. 254 // unsigned Extra; 255 // Register number without the privilege bits. 256 // unsigned Number; 257 FeatureBitset FeaturesRequired; 258 bool isRV32Only; 259 260 bool haveRequiredFeatures(const FeatureBitset &ActiveFeatures) const { 261 // Not in 32-bit mode. 262 if (isRV32Only && ActiveFeatures[RISCV::Feature64Bit]) 263 return false; 264 // No required feature associated with the system register. 265 if (FeaturesRequired.none()) 266 return true; 267 return (FeaturesRequired & ActiveFeatures) == FeaturesRequired; 268 } 269 }; 270 271 #define GET_SysRegsList_DECL 272 #include "RISCVGenSearchableTables.inc" 273 } // end namespace RISCVSysReg 274 275 namespace RISCVABI { 276 277 enum ABI { 278 ABI_ILP32, 279 ABI_ILP32F, 280 ABI_ILP32D, 281 ABI_ILP32E, 282 ABI_LP64, 283 ABI_LP64F, 284 ABI_LP64D, 285 ABI_Unknown 286 }; 287 288 // Returns the target ABI, or else a StringError if the requested ABIName is 289 // not supported for the given TT and FeatureBits combination. 290 ABI computeTargetABI(const Triple &TT, FeatureBitset FeatureBits, 291 StringRef ABIName); 292 293 ABI getTargetABI(StringRef ABIName); 294 295 // Returns the register used to hold the stack pointer after realignment. 296 MCRegister getBPReg(); 297 298 // Returns the register holding shadow call stack pointer. 299 MCRegister getSCSPReg(); 300 301 } // namespace RISCVABI 302 303 namespace RISCVFeatures { 304 305 // Validates if the given combination of features are valid for the target 306 // triple. Exits with report_fatal_error if not. 307 void validate(const Triple &TT, const FeatureBitset &FeatureBits); 308 309 } // namespace RISCVFeatures 310 311 namespace RISCVVType { 312 // Is this a SEW value that can be encoded into the VTYPE format. 313 inline static bool isValidSEW(unsigned SEW) { 314 return isPowerOf2_32(SEW) && SEW >= 8 && SEW <= 1024; 315 } 316 317 // Is this a LMUL value that can be encoded into the VTYPE format. 318 inline static bool isValidLMUL(unsigned LMUL, bool Fractional) { 319 return isPowerOf2_32(LMUL) && LMUL <= 8 && (!Fractional || LMUL != 1); 320 } 321 322 unsigned encodeVTYPE(RISCVII::VLMUL VLMUL, unsigned SEW, bool TailAgnostic, 323 bool MaskAgnostic); 324 325 inline static RISCVII::VLMUL getVLMUL(unsigned VType) { 326 unsigned VLMUL = VType & 0x7; 327 return static_cast<RISCVII::VLMUL>(VLMUL); 328 } 329 330 // Decode VLMUL into 1,2,4,8 and fractional indicator. 331 std::pair<unsigned, bool> decodeVLMUL(RISCVII::VLMUL VLMUL); 332 333 inline static unsigned decodeVSEW(unsigned VSEW) { 334 assert(VSEW < 8 && "Unexpected VSEW value"); 335 return 1 << (VSEW + 3); 336 } 337 338 inline static unsigned getSEW(unsigned VType) { 339 unsigned VSEW = (VType >> 3) & 0x7; 340 return decodeVSEW(VSEW); 341 } 342 343 inline static bool isTailAgnostic(unsigned VType) { return VType & 0x40; } 344 345 inline static bool isMaskAgnostic(unsigned VType) { return VType & 0x80; } 346 347 void printVType(unsigned VType, raw_ostream &OS); 348 349 } // namespace RISCVVType 350 351 } // namespace llvm 352 353 #endif 354