1*06c3fb27SDimitry Andric //===-- RISCVBaseInfo.h - Top level definitions for RISC-V MC ---*- C++ -*-===// 2e8d8bef9SDimitry Andric // 3e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e8d8bef9SDimitry Andric // 7e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 8e8d8bef9SDimitry Andric // 9*06c3fb27SDimitry Andric // This file contains small standalone enum definitions for the RISC-V target 10e8d8bef9SDimitry Andric // useful for the compiler back-end and the MC libraries. 11e8d8bef9SDimitry Andric // 12e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 13e8d8bef9SDimitry Andric #ifndef LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVBASEINFO_H 14e8d8bef9SDimitry Andric #define LLVM_LIB_TARGET_RISCV_MCTARGETDESC_RISCVBASEINFO_H 15e8d8bef9SDimitry Andric 16e8d8bef9SDimitry Andric #include "MCTargetDesc/RISCVMCTargetDesc.h" 17*06c3fb27SDimitry Andric #include "llvm/ADT/APFloat.h" 18*06c3fb27SDimitry Andric #include "llvm/ADT/APInt.h" 19e8d8bef9SDimitry Andric #include "llvm/ADT/StringRef.h" 20e8d8bef9SDimitry Andric #include "llvm/ADT/StringSwitch.h" 21e8d8bef9SDimitry Andric #include "llvm/MC/MCInstrDesc.h" 2281ad6265SDimitry Andric #include "llvm/Support/RISCVISAInfo.h" 23*06c3fb27SDimitry Andric #include "llvm/TargetParser/SubtargetFeature.h" 24e8d8bef9SDimitry Andric 25e8d8bef9SDimitry Andric namespace llvm { 26e8d8bef9SDimitry Andric 27e8d8bef9SDimitry Andric // RISCVII - This namespace holds all of the target specific flags that 28e8d8bef9SDimitry Andric // instruction info tracks. All definitions must match RISCVInstrFormats.td. 29e8d8bef9SDimitry Andric namespace RISCVII { 30e8d8bef9SDimitry Andric enum { 31e8d8bef9SDimitry Andric InstFormatPseudo = 0, 32e8d8bef9SDimitry Andric InstFormatR = 1, 33e8d8bef9SDimitry Andric InstFormatR4 = 2, 34e8d8bef9SDimitry Andric InstFormatI = 3, 35e8d8bef9SDimitry Andric InstFormatS = 4, 36e8d8bef9SDimitry Andric InstFormatB = 5, 37e8d8bef9SDimitry Andric InstFormatU = 6, 38e8d8bef9SDimitry Andric InstFormatJ = 7, 39e8d8bef9SDimitry Andric InstFormatCR = 8, 40e8d8bef9SDimitry Andric InstFormatCI = 9, 41e8d8bef9SDimitry Andric InstFormatCSS = 10, 42e8d8bef9SDimitry Andric InstFormatCIW = 11, 43e8d8bef9SDimitry Andric InstFormatCL = 12, 44e8d8bef9SDimitry Andric InstFormatCS = 13, 45e8d8bef9SDimitry Andric InstFormatCA = 14, 46e8d8bef9SDimitry Andric InstFormatCB = 15, 47e8d8bef9SDimitry Andric InstFormatCJ = 16, 48*06c3fb27SDimitry Andric InstFormatCU = 17, 49*06c3fb27SDimitry Andric InstFormatCLB = 18, 50*06c3fb27SDimitry Andric InstFormatCLH = 19, 51*06c3fb27SDimitry Andric InstFormatCSB = 20, 52*06c3fb27SDimitry Andric InstFormatCSH = 21, 53*06c3fb27SDimitry Andric InstFormatOther = 22, 54e8d8bef9SDimitry Andric 55e8d8bef9SDimitry Andric InstFormatMask = 31, 56fe6060f1SDimitry Andric InstFormatShift = 0, 57e8d8bef9SDimitry Andric 58fe6060f1SDimitry Andric ConstraintShift = InstFormatShift + 5, 59*06c3fb27SDimitry Andric VS2Constraint = 0b001 << ConstraintShift, 60*06c3fb27SDimitry Andric VS1Constraint = 0b010 << ConstraintShift, 61*06c3fb27SDimitry Andric VMConstraint = 0b100 << ConstraintShift, 62e8d8bef9SDimitry Andric ConstraintMask = 0b111 << ConstraintShift, 63e8d8bef9SDimitry Andric 64e8d8bef9SDimitry Andric VLMulShift = ConstraintShift + 3, 65e8d8bef9SDimitry Andric VLMulMask = 0b111 << VLMulShift, 66e8d8bef9SDimitry Andric 67fe6060f1SDimitry Andric // Force a tail agnostic policy even this instruction has a tied destination. 68*06c3fb27SDimitry Andric ForceTailAgnosticShift = VLMulShift + 3, 69fe6060f1SDimitry Andric ForceTailAgnosticMask = 1 << ForceTailAgnosticShift, 70e8d8bef9SDimitry Andric 71*06c3fb27SDimitry Andric // Is this a _TIED vector pseudo instruction. For these instructions we 72*06c3fb27SDimitry Andric // shouldn't skip the tied operand when converting to MC instructions. 73*06c3fb27SDimitry Andric IsTiedPseudoShift = ForceTailAgnosticShift + 1, 74*06c3fb27SDimitry Andric IsTiedPseudoMask = 1 << IsTiedPseudoShift, 75e8d8bef9SDimitry Andric 76e8d8bef9SDimitry Andric // Does this instruction have a SEW operand. It will be the last explicit 77349cc55cSDimitry Andric // operand unless there is a vector policy operand. Used by RVV Pseudos. 78*06c3fb27SDimitry Andric HasSEWOpShift = IsTiedPseudoShift + 1, 79e8d8bef9SDimitry Andric HasSEWOpMask = 1 << HasSEWOpShift, 80e8d8bef9SDimitry Andric 81e8d8bef9SDimitry Andric // Does this instruction have a VL operand. It will be the second to last 82349cc55cSDimitry Andric // explicit operand unless there is a vector policy operand. Used by RVV 83349cc55cSDimitry Andric // Pseudos. 84e8d8bef9SDimitry Andric HasVLOpShift = HasSEWOpShift + 1, 85e8d8bef9SDimitry Andric HasVLOpMask = 1 << HasVLOpShift, 86349cc55cSDimitry Andric 87349cc55cSDimitry Andric // Does this instruction have a vector policy operand. It will be the last 88349cc55cSDimitry Andric // explicit operand. Used by RVV Pseudos. 89349cc55cSDimitry Andric HasVecPolicyOpShift = HasVLOpShift + 1, 90349cc55cSDimitry Andric HasVecPolicyOpMask = 1 << HasVecPolicyOpShift, 91349cc55cSDimitry Andric 92349cc55cSDimitry Andric // Is this instruction a vector widening reduction instruction. Used by RVV 93349cc55cSDimitry Andric // Pseudos. 94349cc55cSDimitry Andric IsRVVWideningReductionShift = HasVecPolicyOpShift + 1, 95349cc55cSDimitry Andric IsRVVWideningReductionMask = 1 << IsRVVWideningReductionShift, 9681ad6265SDimitry Andric 9781ad6265SDimitry Andric // Does this instruction care about mask policy. If it is not, the mask policy 9881ad6265SDimitry Andric // could be either agnostic or undisturbed. For example, unmasked, store, and 9981ad6265SDimitry Andric // reduction operations result would not be affected by mask policy, so 10081ad6265SDimitry Andric // compiler has free to select either one. 10181ad6265SDimitry Andric UsesMaskPolicyShift = IsRVVWideningReductionShift + 1, 10281ad6265SDimitry Andric UsesMaskPolicyMask = 1 << UsesMaskPolicyShift, 103bdd1243dSDimitry Andric 104bdd1243dSDimitry Andric // Indicates that the result can be considered sign extended from bit 31. Some 105bdd1243dSDimitry Andric // instructions with this flag aren't W instructions, but are either sign 106bdd1243dSDimitry Andric // extended from a smaller size, always outputs a small integer, or put zeros 107bdd1243dSDimitry Andric // in bits 63:31. Used by the SExtWRemoval pass. 108bdd1243dSDimitry Andric IsSignExtendingOpWShift = UsesMaskPolicyShift + 1, 109bdd1243dSDimitry Andric IsSignExtendingOpWMask = 1ULL << IsSignExtendingOpWShift, 110e8d8bef9SDimitry Andric 111*06c3fb27SDimitry Andric HasRoundModeOpShift = IsSignExtendingOpWShift + 1, 112*06c3fb27SDimitry Andric HasRoundModeOpMask = 1 << HasRoundModeOpShift, 113*06c3fb27SDimitry Andric 114*06c3fb27SDimitry Andric UsesVXRMShift = HasRoundModeOpShift + 1, 115*06c3fb27SDimitry Andric UsesVXRMMask = 1 << UsesVXRMShift, 116e8d8bef9SDimitry Andric }; 117e8d8bef9SDimitry Andric 118fe6060f1SDimitry Andric enum VLMUL : uint8_t { 119fe6060f1SDimitry Andric LMUL_1 = 0, 120fe6060f1SDimitry Andric LMUL_2, 121fe6060f1SDimitry Andric LMUL_4, 122fe6060f1SDimitry Andric LMUL_8, 123fe6060f1SDimitry Andric LMUL_RESERVED, 124fe6060f1SDimitry Andric LMUL_F8, 125fe6060f1SDimitry Andric LMUL_F4, 126fe6060f1SDimitry Andric LMUL_F2 127fe6060f1SDimitry Andric }; 128fe6060f1SDimitry Andric 129349cc55cSDimitry Andric enum { 130bdd1243dSDimitry Andric TAIL_UNDISTURBED_MASK_UNDISTURBED = 0, 131349cc55cSDimitry Andric TAIL_AGNOSTIC = 1, 13281ad6265SDimitry Andric MASK_AGNOSTIC = 2, 133349cc55cSDimitry Andric }; 134349cc55cSDimitry Andric 135fe6060f1SDimitry Andric // Helper functions to read TSFlags. 136fe6060f1SDimitry Andric /// \returns the format of the instruction. 137fe6060f1SDimitry Andric static inline unsigned getFormat(uint64_t TSFlags) { 138fe6060f1SDimitry Andric return (TSFlags & InstFormatMask) >> InstFormatShift; 139fe6060f1SDimitry Andric } 140fe6060f1SDimitry Andric /// \returns the LMUL for the instruction. 141fe6060f1SDimitry Andric static inline VLMUL getLMul(uint64_t TSFlags) { 142fe6060f1SDimitry Andric return static_cast<VLMUL>((TSFlags & VLMulMask) >> VLMulShift); 143fe6060f1SDimitry Andric } 144fe6060f1SDimitry Andric /// \returns true if tail agnostic is enforced for the instruction. 145fe6060f1SDimitry Andric static inline bool doesForceTailAgnostic(uint64_t TSFlags) { 146fe6060f1SDimitry Andric return TSFlags & ForceTailAgnosticMask; 147fe6060f1SDimitry Andric } 148*06c3fb27SDimitry Andric /// \returns true if this a _TIED pseudo. 149*06c3fb27SDimitry Andric static inline bool isTiedPseudo(uint64_t TSFlags) { 150*06c3fb27SDimitry Andric return TSFlags & IsTiedPseudoMask; 151fe6060f1SDimitry Andric } 152fe6060f1SDimitry Andric /// \returns true if there is a SEW operand for the instruction. 153fe6060f1SDimitry Andric static inline bool hasSEWOp(uint64_t TSFlags) { 154fe6060f1SDimitry Andric return TSFlags & HasSEWOpMask; 155fe6060f1SDimitry Andric } 156fe6060f1SDimitry Andric /// \returns true if there is a VL operand for the instruction. 157fe6060f1SDimitry Andric static inline bool hasVLOp(uint64_t TSFlags) { 158fe6060f1SDimitry Andric return TSFlags & HasVLOpMask; 159fe6060f1SDimitry Andric } 160349cc55cSDimitry Andric /// \returns true if there is a vector policy operand for this instruction. 161349cc55cSDimitry Andric static inline bool hasVecPolicyOp(uint64_t TSFlags) { 162349cc55cSDimitry Andric return TSFlags & HasVecPolicyOpMask; 163349cc55cSDimitry Andric } 164349cc55cSDimitry Andric /// \returns true if it is a vector widening reduction instruction. 165349cc55cSDimitry Andric static inline bool isRVVWideningReduction(uint64_t TSFlags) { 166349cc55cSDimitry Andric return TSFlags & IsRVVWideningReductionMask; 167349cc55cSDimitry Andric } 16881ad6265SDimitry Andric /// \returns true if mask policy is valid for the instruction. 16981ad6265SDimitry Andric static inline bool usesMaskPolicy(uint64_t TSFlags) { 17081ad6265SDimitry Andric return TSFlags & UsesMaskPolicyMask; 17181ad6265SDimitry Andric } 17281ad6265SDimitry Andric 173*06c3fb27SDimitry Andric /// \returns true if there is a rounding mode operand for this instruction 174*06c3fb27SDimitry Andric static inline bool hasRoundModeOp(uint64_t TSFlags) { 175*06c3fb27SDimitry Andric return TSFlags & HasRoundModeOpMask; 176bdd1243dSDimitry Andric } 177bdd1243dSDimitry Andric 178*06c3fb27SDimitry Andric /// \returns true if this instruction uses vxrm 179*06c3fb27SDimitry Andric static inline bool usesVXRM(uint64_t TSFlags) { return TSFlags & UsesVXRMMask; } 180*06c3fb27SDimitry Andric 18181ad6265SDimitry Andric static inline unsigned getVLOpNum(const MCInstrDesc &Desc) { 18281ad6265SDimitry Andric const uint64_t TSFlags = Desc.TSFlags; 18381ad6265SDimitry Andric // This method is only called if we expect to have a VL operand, and all 18481ad6265SDimitry Andric // instructions with VL also have SEW. 18581ad6265SDimitry Andric assert(hasSEWOp(TSFlags) && hasVLOp(TSFlags)); 18681ad6265SDimitry Andric unsigned Offset = 2; 18781ad6265SDimitry Andric if (hasVecPolicyOp(TSFlags)) 18881ad6265SDimitry Andric Offset = 3; 18981ad6265SDimitry Andric return Desc.getNumOperands() - Offset; 19081ad6265SDimitry Andric } 19181ad6265SDimitry Andric 19281ad6265SDimitry Andric static inline unsigned getSEWOpNum(const MCInstrDesc &Desc) { 19381ad6265SDimitry Andric const uint64_t TSFlags = Desc.TSFlags; 19481ad6265SDimitry Andric assert(hasSEWOp(TSFlags)); 19581ad6265SDimitry Andric unsigned Offset = 1; 19681ad6265SDimitry Andric if (hasVecPolicyOp(TSFlags)) 19781ad6265SDimitry Andric Offset = 2; 19881ad6265SDimitry Andric return Desc.getNumOperands() - Offset; 19981ad6265SDimitry Andric } 200fe6060f1SDimitry Andric 201bdd1243dSDimitry Andric static inline unsigned getVecPolicyOpNum(const MCInstrDesc &Desc) { 202bdd1243dSDimitry Andric assert(hasVecPolicyOp(Desc.TSFlags)); 203bdd1243dSDimitry Andric return Desc.getNumOperands() - 1; 204bdd1243dSDimitry Andric } 205bdd1243dSDimitry Andric 206*06c3fb27SDimitry Andric // Is the first def operand tied to the first use operand. This is true for 207*06c3fb27SDimitry Andric // vector pseudo instructions that have a merge operand for tail/mask 208*06c3fb27SDimitry Andric // undisturbed. It's also true for vector FMA instructions where one of the 209*06c3fb27SDimitry Andric // operands is also the destination register. 210*06c3fb27SDimitry Andric static inline bool isFirstDefTiedToFirstUse(const MCInstrDesc &Desc) { 211*06c3fb27SDimitry Andric return Desc.getNumDefs() < Desc.getNumOperands() && 212*06c3fb27SDimitry Andric Desc.getOperandConstraint(Desc.getNumDefs(), MCOI::TIED_TO) == 0; 213*06c3fb27SDimitry Andric } 214*06c3fb27SDimitry Andric 215e8d8bef9SDimitry Andric // RISC-V Specific Machine Operand Flags 216e8d8bef9SDimitry Andric enum { 217e8d8bef9SDimitry Andric MO_None = 0, 218e8d8bef9SDimitry Andric MO_CALL = 1, 219e8d8bef9SDimitry Andric MO_PLT = 2, 220e8d8bef9SDimitry Andric MO_LO = 3, 221e8d8bef9SDimitry Andric MO_HI = 4, 222e8d8bef9SDimitry Andric MO_PCREL_LO = 5, 223e8d8bef9SDimitry Andric MO_PCREL_HI = 6, 224e8d8bef9SDimitry Andric MO_GOT_HI = 7, 225e8d8bef9SDimitry Andric MO_TPREL_LO = 8, 226e8d8bef9SDimitry Andric MO_TPREL_HI = 9, 227e8d8bef9SDimitry Andric MO_TPREL_ADD = 10, 228e8d8bef9SDimitry Andric MO_TLS_GOT_HI = 11, 229e8d8bef9SDimitry Andric MO_TLS_GD_HI = 12, 230e8d8bef9SDimitry Andric 231e8d8bef9SDimitry Andric // Used to differentiate between target-specific "direct" flags and "bitmask" 232e8d8bef9SDimitry Andric // flags. A machine operand can only have one "direct" flag, but can have 233e8d8bef9SDimitry Andric // multiple "bitmask" flags. 234e8d8bef9SDimitry Andric MO_DIRECT_FLAG_MASK = 15 235e8d8bef9SDimitry Andric }; 236e8d8bef9SDimitry Andric } // namespace RISCVII 237e8d8bef9SDimitry Andric 238e8d8bef9SDimitry Andric namespace RISCVOp { 239e8d8bef9SDimitry Andric enum OperandType : unsigned { 240e8d8bef9SDimitry Andric OPERAND_FIRST_RISCV_IMM = MCOI::OPERAND_FIRST_TARGET, 241*06c3fb27SDimitry Andric OPERAND_UIMM1 = OPERAND_FIRST_RISCV_IMM, 242*06c3fb27SDimitry Andric OPERAND_UIMM2, 243*06c3fb27SDimitry Andric OPERAND_UIMM2_LSB0, 244349cc55cSDimitry Andric OPERAND_UIMM3, 245349cc55cSDimitry Andric OPERAND_UIMM4, 246e8d8bef9SDimitry Andric OPERAND_UIMM5, 247*06c3fb27SDimitry Andric OPERAND_UIMM6, 248349cc55cSDimitry Andric OPERAND_UIMM7, 249bdd1243dSDimitry Andric OPERAND_UIMM7_LSB00, 250bdd1243dSDimitry Andric OPERAND_UIMM8_LSB00, 251*06c3fb27SDimitry Andric OPERAND_UIMM8, 252bdd1243dSDimitry Andric OPERAND_UIMM8_LSB000, 253*06c3fb27SDimitry Andric OPERAND_UIMM8_GE32, 254*06c3fb27SDimitry Andric OPERAND_UIMM9_LSB000, 255*06c3fb27SDimitry Andric OPERAND_UIMM10_LSB00_NONZERO, 256e8d8bef9SDimitry Andric OPERAND_UIMM12, 257bdd1243dSDimitry Andric OPERAND_ZERO, 258bdd1243dSDimitry Andric OPERAND_SIMM5, 259bdd1243dSDimitry Andric OPERAND_SIMM5_PLUS1, 260bdd1243dSDimitry Andric OPERAND_SIMM6, 261bdd1243dSDimitry Andric OPERAND_SIMM6_NONZERO, 262bdd1243dSDimitry Andric OPERAND_SIMM10_LSB0000_NONZERO, 263e8d8bef9SDimitry Andric OPERAND_SIMM12, 26481ad6265SDimitry Andric OPERAND_SIMM12_LSB00000, 265e8d8bef9SDimitry Andric OPERAND_UIMM20, 266e8d8bef9SDimitry Andric OPERAND_UIMMLOG2XLEN, 267bdd1243dSDimitry Andric OPERAND_UIMMLOG2XLEN_NONZERO, 268*06c3fb27SDimitry Andric OPERAND_CLUI_IMM, 269bdd1243dSDimitry Andric OPERAND_VTYPEI10, 270bdd1243dSDimitry Andric OPERAND_VTYPEI11, 27104eeddc0SDimitry Andric OPERAND_RVKRNUM, 272*06c3fb27SDimitry Andric OPERAND_RVKRNUM_0_7, 273*06c3fb27SDimitry Andric OPERAND_RVKRNUM_1_10, 274*06c3fb27SDimitry Andric OPERAND_RVKRNUM_2_14, 275*06c3fb27SDimitry Andric OPERAND_LAST_RISCV_IMM = OPERAND_RVKRNUM_2_14, 276fe6060f1SDimitry Andric // Operand is either a register or uimm5, this is used by V extension pseudo 277fe6060f1SDimitry Andric // instructions to represent a value that be passed as AVL to either vsetvli 278fe6060f1SDimitry Andric // or vsetivli. 279fe6060f1SDimitry Andric OPERAND_AVL, 280e8d8bef9SDimitry Andric }; 281e8d8bef9SDimitry Andric } // namespace RISCVOp 282e8d8bef9SDimitry Andric 283e8d8bef9SDimitry Andric // Describes the predecessor/successor bits used in the FENCE instruction. 284e8d8bef9SDimitry Andric namespace RISCVFenceField { 285e8d8bef9SDimitry Andric enum FenceField { 286e8d8bef9SDimitry Andric I = 8, 287e8d8bef9SDimitry Andric O = 4, 288e8d8bef9SDimitry Andric R = 2, 289e8d8bef9SDimitry Andric W = 1 290e8d8bef9SDimitry Andric }; 291e8d8bef9SDimitry Andric } 292e8d8bef9SDimitry Andric 293e8d8bef9SDimitry Andric // Describes the supported floating point rounding mode encodings. 294e8d8bef9SDimitry Andric namespace RISCVFPRndMode { 295e8d8bef9SDimitry Andric enum RoundingMode { 296e8d8bef9SDimitry Andric RNE = 0, 297e8d8bef9SDimitry Andric RTZ = 1, 298e8d8bef9SDimitry Andric RDN = 2, 299e8d8bef9SDimitry Andric RUP = 3, 300e8d8bef9SDimitry Andric RMM = 4, 301e8d8bef9SDimitry Andric DYN = 7, 302e8d8bef9SDimitry Andric Invalid 303e8d8bef9SDimitry Andric }; 304e8d8bef9SDimitry Andric 305e8d8bef9SDimitry Andric inline static StringRef roundingModeToString(RoundingMode RndMode) { 306e8d8bef9SDimitry Andric switch (RndMode) { 307e8d8bef9SDimitry Andric default: 308e8d8bef9SDimitry Andric llvm_unreachable("Unknown floating point rounding mode"); 309e8d8bef9SDimitry Andric case RISCVFPRndMode::RNE: 310e8d8bef9SDimitry Andric return "rne"; 311e8d8bef9SDimitry Andric case RISCVFPRndMode::RTZ: 312e8d8bef9SDimitry Andric return "rtz"; 313e8d8bef9SDimitry Andric case RISCVFPRndMode::RDN: 314e8d8bef9SDimitry Andric return "rdn"; 315e8d8bef9SDimitry Andric case RISCVFPRndMode::RUP: 316e8d8bef9SDimitry Andric return "rup"; 317e8d8bef9SDimitry Andric case RISCVFPRndMode::RMM: 318e8d8bef9SDimitry Andric return "rmm"; 319e8d8bef9SDimitry Andric case RISCVFPRndMode::DYN: 320e8d8bef9SDimitry Andric return "dyn"; 321e8d8bef9SDimitry Andric } 322e8d8bef9SDimitry Andric } 323e8d8bef9SDimitry Andric 324e8d8bef9SDimitry Andric inline static RoundingMode stringToRoundingMode(StringRef Str) { 325e8d8bef9SDimitry Andric return StringSwitch<RoundingMode>(Str) 326e8d8bef9SDimitry Andric .Case("rne", RISCVFPRndMode::RNE) 327e8d8bef9SDimitry Andric .Case("rtz", RISCVFPRndMode::RTZ) 328e8d8bef9SDimitry Andric .Case("rdn", RISCVFPRndMode::RDN) 329e8d8bef9SDimitry Andric .Case("rup", RISCVFPRndMode::RUP) 330e8d8bef9SDimitry Andric .Case("rmm", RISCVFPRndMode::RMM) 331e8d8bef9SDimitry Andric .Case("dyn", RISCVFPRndMode::DYN) 332e8d8bef9SDimitry Andric .Default(RISCVFPRndMode::Invalid); 333e8d8bef9SDimitry Andric } 334e8d8bef9SDimitry Andric 335e8d8bef9SDimitry Andric inline static bool isValidRoundingMode(unsigned Mode) { 336e8d8bef9SDimitry Andric switch (Mode) { 337e8d8bef9SDimitry Andric default: 338e8d8bef9SDimitry Andric return false; 339e8d8bef9SDimitry Andric case RISCVFPRndMode::RNE: 340e8d8bef9SDimitry Andric case RISCVFPRndMode::RTZ: 341e8d8bef9SDimitry Andric case RISCVFPRndMode::RDN: 342e8d8bef9SDimitry Andric case RISCVFPRndMode::RUP: 343e8d8bef9SDimitry Andric case RISCVFPRndMode::RMM: 344e8d8bef9SDimitry Andric case RISCVFPRndMode::DYN: 345e8d8bef9SDimitry Andric return true; 346e8d8bef9SDimitry Andric } 347e8d8bef9SDimitry Andric } 348e8d8bef9SDimitry Andric } // namespace RISCVFPRndMode 349e8d8bef9SDimitry Andric 350*06c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 351*06c3fb27SDimitry Andric // Floating-point Immediates 352*06c3fb27SDimitry Andric // 353*06c3fb27SDimitry Andric 354*06c3fb27SDimitry Andric namespace RISCVLoadFPImm { 355*06c3fb27SDimitry Andric float getFPImm(unsigned Imm); 356*06c3fb27SDimitry Andric 357*06c3fb27SDimitry Andric /// getLoadFPImm - Return a 5-bit binary encoding of the floating-point 358*06c3fb27SDimitry Andric /// immediate value. If the value cannot be represented as a 5-bit binary 359*06c3fb27SDimitry Andric /// encoding, then return -1. 360*06c3fb27SDimitry Andric int getLoadFPImm(APFloat FPImm); 361*06c3fb27SDimitry Andric } // namespace RISCVLoadFPImm 362*06c3fb27SDimitry Andric 363e8d8bef9SDimitry Andric namespace RISCVSysReg { 364e8d8bef9SDimitry Andric struct SysReg { 365e8d8bef9SDimitry Andric const char *Name; 366fe6060f1SDimitry Andric const char *DeprecatedName; 367fe6060f1SDimitry Andric unsigned Encoding; 368e8d8bef9SDimitry Andric // FIXME: add these additional fields when needed. 369e8d8bef9SDimitry Andric // Privilege Access: Read, Write, Read-Only. 370e8d8bef9SDimitry Andric // unsigned ReadWrite; 371e8d8bef9SDimitry Andric // Privilege Mode: User, System or Machine. 372e8d8bef9SDimitry Andric // unsigned Mode; 373e8d8bef9SDimitry Andric // Check field name. 374e8d8bef9SDimitry Andric // unsigned Extra; 375e8d8bef9SDimitry Andric // Register number without the privilege bits. 376e8d8bef9SDimitry Andric // unsigned Number; 377e8d8bef9SDimitry Andric FeatureBitset FeaturesRequired; 378e8d8bef9SDimitry Andric bool isRV32Only; 379e8d8bef9SDimitry Andric 380fe6060f1SDimitry Andric bool haveRequiredFeatures(const FeatureBitset &ActiveFeatures) const { 381e8d8bef9SDimitry Andric // Not in 32-bit mode. 382e8d8bef9SDimitry Andric if (isRV32Only && ActiveFeatures[RISCV::Feature64Bit]) 383e8d8bef9SDimitry Andric return false; 384e8d8bef9SDimitry Andric // No required feature associated with the system register. 385e8d8bef9SDimitry Andric if (FeaturesRequired.none()) 386e8d8bef9SDimitry Andric return true; 387e8d8bef9SDimitry Andric return (FeaturesRequired & ActiveFeatures) == FeaturesRequired; 388e8d8bef9SDimitry Andric } 389*06c3fb27SDimitry Andric 390*06c3fb27SDimitry Andric bool haveVendorRequiredFeatures(const FeatureBitset &ActiveFeatures) const { 391*06c3fb27SDimitry Andric // Not in 32-bit mode. 392*06c3fb27SDimitry Andric if (isRV32Only && ActiveFeatures[RISCV::Feature64Bit]) 393*06c3fb27SDimitry Andric return false; 394*06c3fb27SDimitry Andric // No required feature associated with the system register. 395*06c3fb27SDimitry Andric if (FeaturesRequired.none()) 396*06c3fb27SDimitry Andric return false; 397*06c3fb27SDimitry Andric return (FeaturesRequired & ActiveFeatures) == FeaturesRequired; 398*06c3fb27SDimitry Andric } 399e8d8bef9SDimitry Andric }; 400e8d8bef9SDimitry Andric 401*06c3fb27SDimitry Andric struct SiFiveReg : SysReg {}; 402*06c3fb27SDimitry Andric 403e8d8bef9SDimitry Andric #define GET_SysRegsList_DECL 404*06c3fb27SDimitry Andric #define GET_SiFiveRegsList_DECL 405e8d8bef9SDimitry Andric #include "RISCVGenSearchableTables.inc" 406e8d8bef9SDimitry Andric } // end namespace RISCVSysReg 407e8d8bef9SDimitry Andric 4080eae32dcSDimitry Andric namespace RISCVInsnOpcode { 4090eae32dcSDimitry Andric struct RISCVOpcode { 4100eae32dcSDimitry Andric const char *Name; 4110eae32dcSDimitry Andric unsigned Value; 4120eae32dcSDimitry Andric }; 4130eae32dcSDimitry Andric 4140eae32dcSDimitry Andric #define GET_RISCVOpcodesList_DECL 4150eae32dcSDimitry Andric #include "RISCVGenSearchableTables.inc" 4160eae32dcSDimitry Andric } // end namespace RISCVInsnOpcode 4170eae32dcSDimitry Andric 418e8d8bef9SDimitry Andric namespace RISCVABI { 419e8d8bef9SDimitry Andric 420e8d8bef9SDimitry Andric enum ABI { 421e8d8bef9SDimitry Andric ABI_ILP32, 422e8d8bef9SDimitry Andric ABI_ILP32F, 423e8d8bef9SDimitry Andric ABI_ILP32D, 424e8d8bef9SDimitry Andric ABI_ILP32E, 425e8d8bef9SDimitry Andric ABI_LP64, 426e8d8bef9SDimitry Andric ABI_LP64F, 427e8d8bef9SDimitry Andric ABI_LP64D, 428*06c3fb27SDimitry Andric ABI_LP64E, 429e8d8bef9SDimitry Andric ABI_Unknown 430e8d8bef9SDimitry Andric }; 431e8d8bef9SDimitry Andric 432e8d8bef9SDimitry Andric // Returns the target ABI, or else a StringError if the requested ABIName is 433e8d8bef9SDimitry Andric // not supported for the given TT and FeatureBits combination. 434*06c3fb27SDimitry Andric ABI computeTargetABI(const Triple &TT, const FeatureBitset &FeatureBits, 435e8d8bef9SDimitry Andric StringRef ABIName); 436e8d8bef9SDimitry Andric 437e8d8bef9SDimitry Andric ABI getTargetABI(StringRef ABIName); 438e8d8bef9SDimitry Andric 439e8d8bef9SDimitry Andric // Returns the register used to hold the stack pointer after realignment. 440e8d8bef9SDimitry Andric MCRegister getBPReg(); 441e8d8bef9SDimitry Andric 442e8d8bef9SDimitry Andric // Returns the register holding shadow call stack pointer. 443e8d8bef9SDimitry Andric MCRegister getSCSPReg(); 444e8d8bef9SDimitry Andric 445e8d8bef9SDimitry Andric } // namespace RISCVABI 446e8d8bef9SDimitry Andric 447e8d8bef9SDimitry Andric namespace RISCVFeatures { 448e8d8bef9SDimitry Andric 449e8d8bef9SDimitry Andric // Validates if the given combination of features are valid for the target 450e8d8bef9SDimitry Andric // triple. Exits with report_fatal_error if not. 451e8d8bef9SDimitry Andric void validate(const Triple &TT, const FeatureBitset &FeatureBits); 452e8d8bef9SDimitry Andric 45381ad6265SDimitry Andric llvm::Expected<std::unique_ptr<RISCVISAInfo>> 45481ad6265SDimitry Andric parseFeatureBits(bool IsRV64, const FeatureBitset &FeatureBits); 455349cc55cSDimitry Andric 456e8d8bef9SDimitry Andric } // namespace RISCVFeatures 457e8d8bef9SDimitry Andric 458e8d8bef9SDimitry Andric namespace RISCVVType { 459e8d8bef9SDimitry Andric // Is this a SEW value that can be encoded into the VTYPE format. 460e8d8bef9SDimitry Andric inline static bool isValidSEW(unsigned SEW) { 461e8d8bef9SDimitry Andric return isPowerOf2_32(SEW) && SEW >= 8 && SEW <= 1024; 462e8d8bef9SDimitry Andric } 463e8d8bef9SDimitry Andric 464e8d8bef9SDimitry Andric // Is this a LMUL value that can be encoded into the VTYPE format. 465e8d8bef9SDimitry Andric inline static bool isValidLMUL(unsigned LMUL, bool Fractional) { 466e8d8bef9SDimitry Andric return isPowerOf2_32(LMUL) && LMUL <= 8 && (!Fractional || LMUL != 1); 467e8d8bef9SDimitry Andric } 468e8d8bef9SDimitry Andric 469fe6060f1SDimitry Andric unsigned encodeVTYPE(RISCVII::VLMUL VLMUL, unsigned SEW, bool TailAgnostic, 470fe6060f1SDimitry Andric bool MaskAgnostic); 471e8d8bef9SDimitry Andric 472fe6060f1SDimitry Andric inline static RISCVII::VLMUL getVLMUL(unsigned VType) { 473e8d8bef9SDimitry Andric unsigned VLMUL = VType & 0x7; 474fe6060f1SDimitry Andric return static_cast<RISCVII::VLMUL>(VLMUL); 475e8d8bef9SDimitry Andric } 476e8d8bef9SDimitry Andric 477fe6060f1SDimitry Andric // Decode VLMUL into 1,2,4,8 and fractional indicator. 478fe6060f1SDimitry Andric std::pair<unsigned, bool> decodeVLMUL(RISCVII::VLMUL VLMUL); 479fe6060f1SDimitry Andric 48081ad6265SDimitry Andric inline static RISCVII::VLMUL encodeLMUL(unsigned LMUL, bool Fractional) { 48181ad6265SDimitry Andric assert(isValidLMUL(LMUL, Fractional) && "Unsupported LMUL"); 48281ad6265SDimitry Andric unsigned LmulLog2 = Log2_32(LMUL); 48381ad6265SDimitry Andric return static_cast<RISCVII::VLMUL>(Fractional ? 8 - LmulLog2 : LmulLog2); 48481ad6265SDimitry Andric } 48581ad6265SDimitry Andric 486fe6060f1SDimitry Andric inline static unsigned decodeVSEW(unsigned VSEW) { 487fe6060f1SDimitry Andric assert(VSEW < 8 && "Unexpected VSEW value"); 488fe6060f1SDimitry Andric return 1 << (VSEW + 3); 489fe6060f1SDimitry Andric } 490fe6060f1SDimitry Andric 49181ad6265SDimitry Andric inline static unsigned encodeSEW(unsigned SEW) { 49281ad6265SDimitry Andric assert(isValidSEW(SEW) && "Unexpected SEW value"); 49381ad6265SDimitry Andric return Log2_32(SEW) - 3; 49481ad6265SDimitry Andric } 49581ad6265SDimitry Andric 496fe6060f1SDimitry Andric inline static unsigned getSEW(unsigned VType) { 497e8d8bef9SDimitry Andric unsigned VSEW = (VType >> 3) & 0x7; 498fe6060f1SDimitry Andric return decodeVSEW(VSEW); 499e8d8bef9SDimitry Andric } 500e8d8bef9SDimitry Andric 501e8d8bef9SDimitry Andric inline static bool isTailAgnostic(unsigned VType) { return VType & 0x40; } 502e8d8bef9SDimitry Andric 503e8d8bef9SDimitry Andric inline static bool isMaskAgnostic(unsigned VType) { return VType & 0x80; } 504e8d8bef9SDimitry Andric 505e8d8bef9SDimitry Andric void printVType(unsigned VType, raw_ostream &OS); 506e8d8bef9SDimitry Andric 507bdd1243dSDimitry Andric unsigned getSEWLMULRatio(unsigned SEW, RISCVII::VLMUL VLMul); 508bdd1243dSDimitry Andric 509e8d8bef9SDimitry Andric } // namespace RISCVVType 510e8d8bef9SDimitry Andric 511bdd1243dSDimitry Andric namespace RISCVRVC { 512bdd1243dSDimitry Andric bool compress(MCInst &OutInst, const MCInst &MI, const MCSubtargetInfo &STI); 513bdd1243dSDimitry Andric bool uncompress(MCInst &OutInst, const MCInst &MI, const MCSubtargetInfo &STI); 514bdd1243dSDimitry Andric } // namespace RISCVRVC 515bdd1243dSDimitry Andric 516*06c3fb27SDimitry Andric namespace RISCVZC { 517*06c3fb27SDimitry Andric enum RLISTENCODE { 518*06c3fb27SDimitry Andric RA = 4, 519*06c3fb27SDimitry Andric RA_S0, 520*06c3fb27SDimitry Andric RA_S0_S1, 521*06c3fb27SDimitry Andric RA_S0_S2, 522*06c3fb27SDimitry Andric RA_S0_S3, 523*06c3fb27SDimitry Andric RA_S0_S4, 524*06c3fb27SDimitry Andric RA_S0_S5, 525*06c3fb27SDimitry Andric RA_S0_S6, 526*06c3fb27SDimitry Andric RA_S0_S7, 527*06c3fb27SDimitry Andric RA_S0_S8, 528*06c3fb27SDimitry Andric RA_S0_S9, 529*06c3fb27SDimitry Andric // note - to include s10, s11 must also be included 530*06c3fb27SDimitry Andric RA_S0_S11, 531*06c3fb27SDimitry Andric INVALID_RLIST, 532*06c3fb27SDimitry Andric }; 533*06c3fb27SDimitry Andric 534*06c3fb27SDimitry Andric inline unsigned encodeRlist(MCRegister EndReg, bool IsRV32E = false) { 535*06c3fb27SDimitry Andric assert((!IsRV32E || EndReg <= RISCV::X9) && "Invalid Rlist for RV32E"); 536*06c3fb27SDimitry Andric switch (EndReg) { 537*06c3fb27SDimitry Andric case RISCV::X1: 538*06c3fb27SDimitry Andric return RLISTENCODE::RA; 539*06c3fb27SDimitry Andric case RISCV::X8: 540*06c3fb27SDimitry Andric return RLISTENCODE::RA_S0; 541*06c3fb27SDimitry Andric case RISCV::X9: 542*06c3fb27SDimitry Andric return RLISTENCODE::RA_S0_S1; 543*06c3fb27SDimitry Andric case RISCV::X18: 544*06c3fb27SDimitry Andric return RLISTENCODE::RA_S0_S2; 545*06c3fb27SDimitry Andric case RISCV::X19: 546*06c3fb27SDimitry Andric return RLISTENCODE::RA_S0_S3; 547*06c3fb27SDimitry Andric case RISCV::X20: 548*06c3fb27SDimitry Andric return RLISTENCODE::RA_S0_S4; 549*06c3fb27SDimitry Andric case RISCV::X21: 550*06c3fb27SDimitry Andric return RLISTENCODE::RA_S0_S5; 551*06c3fb27SDimitry Andric case RISCV::X22: 552*06c3fb27SDimitry Andric return RLISTENCODE::RA_S0_S6; 553*06c3fb27SDimitry Andric case RISCV::X23: 554*06c3fb27SDimitry Andric return RLISTENCODE::RA_S0_S7; 555*06c3fb27SDimitry Andric case RISCV::X24: 556*06c3fb27SDimitry Andric return RLISTENCODE::RA_S0_S8; 557*06c3fb27SDimitry Andric case RISCV::X25: 558*06c3fb27SDimitry Andric return RLISTENCODE::RA_S0_S9; 559*06c3fb27SDimitry Andric case RISCV::X26: 560*06c3fb27SDimitry Andric return RLISTENCODE::INVALID_RLIST; 561*06c3fb27SDimitry Andric case RISCV::X27: 562*06c3fb27SDimitry Andric return RLISTENCODE::RA_S0_S11; 563*06c3fb27SDimitry Andric default: 564*06c3fb27SDimitry Andric llvm_unreachable("Undefined input."); 565*06c3fb27SDimitry Andric } 566*06c3fb27SDimitry Andric } 567*06c3fb27SDimitry Andric 568*06c3fb27SDimitry Andric inline static unsigned getStackAdjBase(unsigned RlistVal, bool IsRV64, 569*06c3fb27SDimitry Andric bool IsEABI) { 570*06c3fb27SDimitry Andric assert(RlistVal != RLISTENCODE::INVALID_RLIST && 571*06c3fb27SDimitry Andric "{ra, s0-s10} is not supported, s11 must be included."); 572*06c3fb27SDimitry Andric if (IsEABI) 573*06c3fb27SDimitry Andric return 16; 574*06c3fb27SDimitry Andric if (!IsRV64) { 575*06c3fb27SDimitry Andric switch (RlistVal) { 576*06c3fb27SDimitry Andric case RLISTENCODE::RA: 577*06c3fb27SDimitry Andric case RLISTENCODE::RA_S0: 578*06c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S1: 579*06c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S2: 580*06c3fb27SDimitry Andric return 16; 581*06c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S3: 582*06c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S4: 583*06c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S5: 584*06c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S6: 585*06c3fb27SDimitry Andric return 32; 586*06c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S7: 587*06c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S8: 588*06c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S9: 589*06c3fb27SDimitry Andric return 48; 590*06c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S11: 591*06c3fb27SDimitry Andric return 64; 592*06c3fb27SDimitry Andric } 593*06c3fb27SDimitry Andric } else { 594*06c3fb27SDimitry Andric switch (RlistVal) { 595*06c3fb27SDimitry Andric case RLISTENCODE::RA: 596*06c3fb27SDimitry Andric case RLISTENCODE::RA_S0: 597*06c3fb27SDimitry Andric return 16; 598*06c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S1: 599*06c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S2: 600*06c3fb27SDimitry Andric return 32; 601*06c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S3: 602*06c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S4: 603*06c3fb27SDimitry Andric return 48; 604*06c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S5: 605*06c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S6: 606*06c3fb27SDimitry Andric return 64; 607*06c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S7: 608*06c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S8: 609*06c3fb27SDimitry Andric return 80; 610*06c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S9: 611*06c3fb27SDimitry Andric return 96; 612*06c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S11: 613*06c3fb27SDimitry Andric return 112; 614*06c3fb27SDimitry Andric } 615*06c3fb27SDimitry Andric } 616*06c3fb27SDimitry Andric llvm_unreachable("Unexpected RlistVal"); 617*06c3fb27SDimitry Andric } 618*06c3fb27SDimitry Andric 619*06c3fb27SDimitry Andric inline static bool getSpimm(unsigned RlistVal, unsigned &SpimmVal, 620*06c3fb27SDimitry Andric int64_t StackAdjustment, bool IsRV64, bool IsEABI) { 621*06c3fb27SDimitry Andric if (RlistVal == RLISTENCODE::INVALID_RLIST) 622*06c3fb27SDimitry Andric return false; 623*06c3fb27SDimitry Andric unsigned stackAdj = getStackAdjBase(RlistVal, IsRV64, IsEABI); 624*06c3fb27SDimitry Andric SpimmVal = (StackAdjustment - stackAdj) / 16; 625*06c3fb27SDimitry Andric if (SpimmVal > 3) 626*06c3fb27SDimitry Andric return false; 627*06c3fb27SDimitry Andric return true; 628*06c3fb27SDimitry Andric } 629*06c3fb27SDimitry Andric 630*06c3fb27SDimitry Andric void printRlist(unsigned SlistEncode, raw_ostream &OS); 631*06c3fb27SDimitry Andric void printSpimm(int64_t Spimm, raw_ostream &OS); 632*06c3fb27SDimitry Andric } // namespace RISCVZC 633*06c3fb27SDimitry Andric 634e8d8bef9SDimitry Andric } // namespace llvm 635e8d8bef9SDimitry Andric 636e8d8bef9SDimitry Andric #endif 637