106c3fb27SDimitry 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 // 906c3fb27SDimitry 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" 1706c3fb27SDimitry Andric #include "llvm/ADT/APFloat.h" 1806c3fb27SDimitry 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" 22*0fca6ea1SDimitry Andric #include "llvm/TargetParser/RISCVISAInfo.h" 23*0fca6ea1SDimitry Andric #include "llvm/TargetParser/RISCVTargetParser.h" 2406c3fb27SDimitry Andric #include "llvm/TargetParser/SubtargetFeature.h" 25e8d8bef9SDimitry Andric 26e8d8bef9SDimitry Andric namespace llvm { 27e8d8bef9SDimitry Andric 28e8d8bef9SDimitry Andric // RISCVII - This namespace holds all of the target specific flags that 29e8d8bef9SDimitry Andric // instruction info tracks. All definitions must match RISCVInstrFormats.td. 30e8d8bef9SDimitry Andric namespace RISCVII { 31e8d8bef9SDimitry Andric enum { 32e8d8bef9SDimitry Andric InstFormatPseudo = 0, 33e8d8bef9SDimitry Andric InstFormatR = 1, 34e8d8bef9SDimitry Andric InstFormatR4 = 2, 35e8d8bef9SDimitry Andric InstFormatI = 3, 36e8d8bef9SDimitry Andric InstFormatS = 4, 37e8d8bef9SDimitry Andric InstFormatB = 5, 38e8d8bef9SDimitry Andric InstFormatU = 6, 39e8d8bef9SDimitry Andric InstFormatJ = 7, 40e8d8bef9SDimitry Andric InstFormatCR = 8, 41e8d8bef9SDimitry Andric InstFormatCI = 9, 42e8d8bef9SDimitry Andric InstFormatCSS = 10, 43e8d8bef9SDimitry Andric InstFormatCIW = 11, 44e8d8bef9SDimitry Andric InstFormatCL = 12, 45e8d8bef9SDimitry Andric InstFormatCS = 13, 46e8d8bef9SDimitry Andric InstFormatCA = 14, 47e8d8bef9SDimitry Andric InstFormatCB = 15, 48e8d8bef9SDimitry Andric InstFormatCJ = 16, 4906c3fb27SDimitry Andric InstFormatCU = 17, 5006c3fb27SDimitry Andric InstFormatCLB = 18, 5106c3fb27SDimitry Andric InstFormatCLH = 19, 5206c3fb27SDimitry Andric InstFormatCSB = 20, 5306c3fb27SDimitry Andric InstFormatCSH = 21, 5406c3fb27SDimitry Andric InstFormatOther = 22, 55e8d8bef9SDimitry Andric 56e8d8bef9SDimitry Andric InstFormatMask = 31, 57fe6060f1SDimitry Andric InstFormatShift = 0, 58e8d8bef9SDimitry Andric 59fe6060f1SDimitry Andric ConstraintShift = InstFormatShift + 5, 6006c3fb27SDimitry Andric VS2Constraint = 0b001 << ConstraintShift, 6106c3fb27SDimitry Andric VS1Constraint = 0b010 << ConstraintShift, 6206c3fb27SDimitry Andric VMConstraint = 0b100 << ConstraintShift, 63e8d8bef9SDimitry Andric ConstraintMask = 0b111 << ConstraintShift, 64e8d8bef9SDimitry Andric 65e8d8bef9SDimitry Andric VLMulShift = ConstraintShift + 3, 66e8d8bef9SDimitry Andric VLMulMask = 0b111 << VLMulShift, 67e8d8bef9SDimitry Andric 68fe6060f1SDimitry Andric // Force a tail agnostic policy even this instruction has a tied destination. 6906c3fb27SDimitry Andric ForceTailAgnosticShift = VLMulShift + 3, 70fe6060f1SDimitry Andric ForceTailAgnosticMask = 1 << ForceTailAgnosticShift, 71e8d8bef9SDimitry Andric 7206c3fb27SDimitry Andric // Is this a _TIED vector pseudo instruction. For these instructions we 7306c3fb27SDimitry Andric // shouldn't skip the tied operand when converting to MC instructions. 7406c3fb27SDimitry Andric IsTiedPseudoShift = ForceTailAgnosticShift + 1, 7506c3fb27SDimitry Andric IsTiedPseudoMask = 1 << IsTiedPseudoShift, 76e8d8bef9SDimitry Andric 77e8d8bef9SDimitry Andric // Does this instruction have a SEW operand. It will be the last explicit 78349cc55cSDimitry Andric // operand unless there is a vector policy operand. Used by RVV Pseudos. 7906c3fb27SDimitry Andric HasSEWOpShift = IsTiedPseudoShift + 1, 80e8d8bef9SDimitry Andric HasSEWOpMask = 1 << HasSEWOpShift, 81e8d8bef9SDimitry Andric 82e8d8bef9SDimitry Andric // Does this instruction have a VL operand. It will be the second to last 83349cc55cSDimitry Andric // explicit operand unless there is a vector policy operand. Used by RVV 84349cc55cSDimitry Andric // Pseudos. 85e8d8bef9SDimitry Andric HasVLOpShift = HasSEWOpShift + 1, 86e8d8bef9SDimitry Andric HasVLOpMask = 1 << HasVLOpShift, 87349cc55cSDimitry Andric 88349cc55cSDimitry Andric // Does this instruction have a vector policy operand. It will be the last 89349cc55cSDimitry Andric // explicit operand. Used by RVV Pseudos. 90349cc55cSDimitry Andric HasVecPolicyOpShift = HasVLOpShift + 1, 91349cc55cSDimitry Andric HasVecPolicyOpMask = 1 << HasVecPolicyOpShift, 92349cc55cSDimitry Andric 93349cc55cSDimitry Andric // Is this instruction a vector widening reduction instruction. Used by RVV 94349cc55cSDimitry Andric // Pseudos. 95349cc55cSDimitry Andric IsRVVWideningReductionShift = HasVecPolicyOpShift + 1, 96349cc55cSDimitry Andric IsRVVWideningReductionMask = 1 << IsRVVWideningReductionShift, 9781ad6265SDimitry Andric 9881ad6265SDimitry Andric // Does this instruction care about mask policy. If it is not, the mask policy 9981ad6265SDimitry Andric // could be either agnostic or undisturbed. For example, unmasked, store, and 10081ad6265SDimitry Andric // reduction operations result would not be affected by mask policy, so 10181ad6265SDimitry Andric // compiler has free to select either one. 10281ad6265SDimitry Andric UsesMaskPolicyShift = IsRVVWideningReductionShift + 1, 10381ad6265SDimitry Andric UsesMaskPolicyMask = 1 << UsesMaskPolicyShift, 104bdd1243dSDimitry Andric 105bdd1243dSDimitry Andric // Indicates that the result can be considered sign extended from bit 31. Some 106bdd1243dSDimitry Andric // instructions with this flag aren't W instructions, but are either sign 107bdd1243dSDimitry Andric // extended from a smaller size, always outputs a small integer, or put zeros 108bdd1243dSDimitry Andric // in bits 63:31. Used by the SExtWRemoval pass. 109bdd1243dSDimitry Andric IsSignExtendingOpWShift = UsesMaskPolicyShift + 1, 110bdd1243dSDimitry Andric IsSignExtendingOpWMask = 1ULL << IsSignExtendingOpWShift, 111e8d8bef9SDimitry Andric 11206c3fb27SDimitry Andric HasRoundModeOpShift = IsSignExtendingOpWShift + 1, 11306c3fb27SDimitry Andric HasRoundModeOpMask = 1 << HasRoundModeOpShift, 11406c3fb27SDimitry Andric 11506c3fb27SDimitry Andric UsesVXRMShift = HasRoundModeOpShift + 1, 11606c3fb27SDimitry Andric UsesVXRMMask = 1 << UsesVXRMShift, 117cb14a3feSDimitry Andric 118cb14a3feSDimitry Andric // Indicates whether these instructions can partially overlap between source 119cb14a3feSDimitry Andric // registers and destination registers according to the vector spec. 120cb14a3feSDimitry Andric // 0 -> not a vector pseudo 121cb14a3feSDimitry Andric // 1 -> default value for vector pseudos. not widening or narrowing. 122cb14a3feSDimitry Andric // 2 -> narrowing case 123cb14a3feSDimitry Andric // 3 -> widening case 124cb14a3feSDimitry Andric TargetOverlapConstraintTypeShift = UsesVXRMShift + 1, 125cb14a3feSDimitry Andric TargetOverlapConstraintTypeMask = 3ULL << TargetOverlapConstraintTypeShift, 126e8d8bef9SDimitry Andric }; 127e8d8bef9SDimitry Andric 128fe6060f1SDimitry Andric // Helper functions to read TSFlags. 129fe6060f1SDimitry Andric /// \returns the format of the instruction. 130fe6060f1SDimitry Andric static inline unsigned getFormat(uint64_t TSFlags) { 131fe6060f1SDimitry Andric return (TSFlags & InstFormatMask) >> InstFormatShift; 132fe6060f1SDimitry Andric } 133fe6060f1SDimitry Andric /// \returns the LMUL for the instruction. 134fe6060f1SDimitry Andric static inline VLMUL getLMul(uint64_t TSFlags) { 135fe6060f1SDimitry Andric return static_cast<VLMUL>((TSFlags & VLMulMask) >> VLMulShift); 136fe6060f1SDimitry Andric } 137fe6060f1SDimitry Andric /// \returns true if tail agnostic is enforced for the instruction. 138fe6060f1SDimitry Andric static inline bool doesForceTailAgnostic(uint64_t TSFlags) { 139fe6060f1SDimitry Andric return TSFlags & ForceTailAgnosticMask; 140fe6060f1SDimitry Andric } 14106c3fb27SDimitry Andric /// \returns true if this a _TIED pseudo. 14206c3fb27SDimitry Andric static inline bool isTiedPseudo(uint64_t TSFlags) { 14306c3fb27SDimitry Andric return TSFlags & IsTiedPseudoMask; 144fe6060f1SDimitry Andric } 145fe6060f1SDimitry Andric /// \returns true if there is a SEW operand for the instruction. 146fe6060f1SDimitry Andric static inline bool hasSEWOp(uint64_t TSFlags) { 147fe6060f1SDimitry Andric return TSFlags & HasSEWOpMask; 148fe6060f1SDimitry Andric } 149fe6060f1SDimitry Andric /// \returns true if there is a VL operand for the instruction. 150fe6060f1SDimitry Andric static inline bool hasVLOp(uint64_t TSFlags) { 151fe6060f1SDimitry Andric return TSFlags & HasVLOpMask; 152fe6060f1SDimitry Andric } 153349cc55cSDimitry Andric /// \returns true if there is a vector policy operand for this instruction. 154349cc55cSDimitry Andric static inline bool hasVecPolicyOp(uint64_t TSFlags) { 155349cc55cSDimitry Andric return TSFlags & HasVecPolicyOpMask; 156349cc55cSDimitry Andric } 157349cc55cSDimitry Andric /// \returns true if it is a vector widening reduction instruction. 158349cc55cSDimitry Andric static inline bool isRVVWideningReduction(uint64_t TSFlags) { 159349cc55cSDimitry Andric return TSFlags & IsRVVWideningReductionMask; 160349cc55cSDimitry Andric } 16181ad6265SDimitry Andric /// \returns true if mask policy is valid for the instruction. 16281ad6265SDimitry Andric static inline bool usesMaskPolicy(uint64_t TSFlags) { 16381ad6265SDimitry Andric return TSFlags & UsesMaskPolicyMask; 16481ad6265SDimitry Andric } 16581ad6265SDimitry Andric 16606c3fb27SDimitry Andric /// \returns true if there is a rounding mode operand for this instruction 16706c3fb27SDimitry Andric static inline bool hasRoundModeOp(uint64_t TSFlags) { 16806c3fb27SDimitry Andric return TSFlags & HasRoundModeOpMask; 169bdd1243dSDimitry Andric } 170bdd1243dSDimitry Andric 17106c3fb27SDimitry Andric /// \returns true if this instruction uses vxrm 17206c3fb27SDimitry Andric static inline bool usesVXRM(uint64_t TSFlags) { return TSFlags & UsesVXRMMask; } 17306c3fb27SDimitry Andric 17481ad6265SDimitry Andric static inline unsigned getVLOpNum(const MCInstrDesc &Desc) { 17581ad6265SDimitry Andric const uint64_t TSFlags = Desc.TSFlags; 17681ad6265SDimitry Andric // This method is only called if we expect to have a VL operand, and all 17781ad6265SDimitry Andric // instructions with VL also have SEW. 17881ad6265SDimitry Andric assert(hasSEWOp(TSFlags) && hasVLOp(TSFlags)); 17981ad6265SDimitry Andric unsigned Offset = 2; 18081ad6265SDimitry Andric if (hasVecPolicyOp(TSFlags)) 18181ad6265SDimitry Andric Offset = 3; 18281ad6265SDimitry Andric return Desc.getNumOperands() - Offset; 18381ad6265SDimitry Andric } 18481ad6265SDimitry Andric 18581ad6265SDimitry Andric static inline unsigned getSEWOpNum(const MCInstrDesc &Desc) { 18681ad6265SDimitry Andric const uint64_t TSFlags = Desc.TSFlags; 18781ad6265SDimitry Andric assert(hasSEWOp(TSFlags)); 18881ad6265SDimitry Andric unsigned Offset = 1; 18981ad6265SDimitry Andric if (hasVecPolicyOp(TSFlags)) 19081ad6265SDimitry Andric Offset = 2; 19181ad6265SDimitry Andric return Desc.getNumOperands() - Offset; 19281ad6265SDimitry Andric } 193fe6060f1SDimitry Andric 194bdd1243dSDimitry Andric static inline unsigned getVecPolicyOpNum(const MCInstrDesc &Desc) { 195bdd1243dSDimitry Andric assert(hasVecPolicyOp(Desc.TSFlags)); 196bdd1243dSDimitry Andric return Desc.getNumOperands() - 1; 197bdd1243dSDimitry Andric } 198bdd1243dSDimitry Andric 1995f757f3fSDimitry Andric /// \returns the index to the rounding mode immediate value if any, otherwise 2005f757f3fSDimitry Andric /// returns -1. 2015f757f3fSDimitry Andric static inline int getFRMOpNum(const MCInstrDesc &Desc) { 2025f757f3fSDimitry Andric const uint64_t TSFlags = Desc.TSFlags; 2035f757f3fSDimitry Andric if (!hasRoundModeOp(TSFlags) || usesVXRM(TSFlags)) 2045f757f3fSDimitry Andric return -1; 2055f757f3fSDimitry Andric 2065f757f3fSDimitry Andric // The operand order 2075f757f3fSDimitry Andric // -------------------------------------- 2085f757f3fSDimitry Andric // | n-1 (if any) | n-2 | n-3 | n-4 | 2095f757f3fSDimitry Andric // | policy | sew | vl | frm | 2105f757f3fSDimitry Andric // -------------------------------------- 2115f757f3fSDimitry Andric return getVLOpNum(Desc) - 1; 2125f757f3fSDimitry Andric } 2135f757f3fSDimitry Andric 2145f757f3fSDimitry Andric /// \returns the index to the rounding mode immediate value if any, otherwise 2155f757f3fSDimitry Andric /// returns -1. 2165f757f3fSDimitry Andric static inline int getVXRMOpNum(const MCInstrDesc &Desc) { 2175f757f3fSDimitry Andric const uint64_t TSFlags = Desc.TSFlags; 2185f757f3fSDimitry Andric if (!hasRoundModeOp(TSFlags) || !usesVXRM(TSFlags)) 2195f757f3fSDimitry Andric return -1; 2205f757f3fSDimitry Andric // The operand order 2215f757f3fSDimitry Andric // -------------------------------------- 2225f757f3fSDimitry Andric // | n-1 (if any) | n-2 | n-3 | n-4 | 2235f757f3fSDimitry Andric // | policy | sew | vl | vxrm | 2245f757f3fSDimitry Andric // -------------------------------------- 2255f757f3fSDimitry Andric return getVLOpNum(Desc) - 1; 2265f757f3fSDimitry Andric } 2275f757f3fSDimitry Andric 22806c3fb27SDimitry Andric // Is the first def operand tied to the first use operand. This is true for 22906c3fb27SDimitry Andric // vector pseudo instructions that have a merge operand for tail/mask 23006c3fb27SDimitry Andric // undisturbed. It's also true for vector FMA instructions where one of the 23106c3fb27SDimitry Andric // operands is also the destination register. 23206c3fb27SDimitry Andric static inline bool isFirstDefTiedToFirstUse(const MCInstrDesc &Desc) { 23306c3fb27SDimitry Andric return Desc.getNumDefs() < Desc.getNumOperands() && 23406c3fb27SDimitry Andric Desc.getOperandConstraint(Desc.getNumDefs(), MCOI::TIED_TO) == 0; 23506c3fb27SDimitry Andric } 23606c3fb27SDimitry Andric 237e8d8bef9SDimitry Andric // RISC-V Specific Machine Operand Flags 238e8d8bef9SDimitry Andric enum { 239e8d8bef9SDimitry Andric MO_None = 0, 240e8d8bef9SDimitry Andric MO_CALL = 1, 241e8d8bef9SDimitry Andric MO_LO = 3, 242e8d8bef9SDimitry Andric MO_HI = 4, 243e8d8bef9SDimitry Andric MO_PCREL_LO = 5, 244e8d8bef9SDimitry Andric MO_PCREL_HI = 6, 245e8d8bef9SDimitry Andric MO_GOT_HI = 7, 246e8d8bef9SDimitry Andric MO_TPREL_LO = 8, 247e8d8bef9SDimitry Andric MO_TPREL_HI = 9, 248e8d8bef9SDimitry Andric MO_TPREL_ADD = 10, 249e8d8bef9SDimitry Andric MO_TLS_GOT_HI = 11, 250e8d8bef9SDimitry Andric MO_TLS_GD_HI = 12, 2517a6dacacSDimitry Andric MO_TLSDESC_HI = 13, 2527a6dacacSDimitry Andric MO_TLSDESC_LOAD_LO = 14, 2537a6dacacSDimitry Andric MO_TLSDESC_ADD_LO = 15, 2547a6dacacSDimitry Andric MO_TLSDESC_CALL = 16, 255e8d8bef9SDimitry Andric 256e8d8bef9SDimitry Andric // Used to differentiate between target-specific "direct" flags and "bitmask" 257e8d8bef9SDimitry Andric // flags. A machine operand can only have one "direct" flag, but can have 258e8d8bef9SDimitry Andric // multiple "bitmask" flags. 2597a6dacacSDimitry Andric MO_DIRECT_FLAG_MASK = 31 260e8d8bef9SDimitry Andric }; 261e8d8bef9SDimitry Andric } // namespace RISCVII 262e8d8bef9SDimitry Andric 263e8d8bef9SDimitry Andric namespace RISCVOp { 264e8d8bef9SDimitry Andric enum OperandType : unsigned { 265e8d8bef9SDimitry Andric OPERAND_FIRST_RISCV_IMM = MCOI::OPERAND_FIRST_TARGET, 26606c3fb27SDimitry Andric OPERAND_UIMM1 = OPERAND_FIRST_RISCV_IMM, 26706c3fb27SDimitry Andric OPERAND_UIMM2, 26806c3fb27SDimitry Andric OPERAND_UIMM2_LSB0, 269349cc55cSDimitry Andric OPERAND_UIMM3, 270349cc55cSDimitry Andric OPERAND_UIMM4, 271e8d8bef9SDimitry Andric OPERAND_UIMM5, 272*0fca6ea1SDimitry Andric OPERAND_UIMM5_LSB0, 27306c3fb27SDimitry Andric OPERAND_UIMM6, 274*0fca6ea1SDimitry Andric OPERAND_UIMM6_LSB0, 275349cc55cSDimitry Andric OPERAND_UIMM7, 276bdd1243dSDimitry Andric OPERAND_UIMM7_LSB00, 277bdd1243dSDimitry Andric OPERAND_UIMM8_LSB00, 27806c3fb27SDimitry Andric OPERAND_UIMM8, 279bdd1243dSDimitry Andric OPERAND_UIMM8_LSB000, 28006c3fb27SDimitry Andric OPERAND_UIMM8_GE32, 28106c3fb27SDimitry Andric OPERAND_UIMM9_LSB000, 28206c3fb27SDimitry Andric OPERAND_UIMM10_LSB00_NONZERO, 283e8d8bef9SDimitry Andric OPERAND_UIMM12, 284*0fca6ea1SDimitry Andric OPERAND_UIMM16, 285*0fca6ea1SDimitry Andric OPERAND_UIMM32, 286bdd1243dSDimitry Andric OPERAND_ZERO, 287bdd1243dSDimitry Andric OPERAND_SIMM5, 288bdd1243dSDimitry Andric OPERAND_SIMM5_PLUS1, 289bdd1243dSDimitry Andric OPERAND_SIMM6, 290bdd1243dSDimitry Andric OPERAND_SIMM6_NONZERO, 291bdd1243dSDimitry Andric OPERAND_SIMM10_LSB0000_NONZERO, 292e8d8bef9SDimitry Andric OPERAND_SIMM12, 29381ad6265SDimitry Andric OPERAND_SIMM12_LSB00000, 294e8d8bef9SDimitry Andric OPERAND_UIMM20, 295e8d8bef9SDimitry Andric OPERAND_UIMMLOG2XLEN, 296bdd1243dSDimitry Andric OPERAND_UIMMLOG2XLEN_NONZERO, 29706c3fb27SDimitry Andric OPERAND_CLUI_IMM, 298bdd1243dSDimitry Andric OPERAND_VTYPEI10, 299bdd1243dSDimitry Andric OPERAND_VTYPEI11, 30004eeddc0SDimitry Andric OPERAND_RVKRNUM, 30106c3fb27SDimitry Andric OPERAND_RVKRNUM_0_7, 30206c3fb27SDimitry Andric OPERAND_RVKRNUM_1_10, 30306c3fb27SDimitry Andric OPERAND_RVKRNUM_2_14, 304*0fca6ea1SDimitry Andric OPERAND_SPIMM, 305*0fca6ea1SDimitry Andric OPERAND_LAST_RISCV_IMM = OPERAND_SPIMM, 306fe6060f1SDimitry Andric // Operand is either a register or uimm5, this is used by V extension pseudo 307fe6060f1SDimitry Andric // instructions to represent a value that be passed as AVL to either vsetvli 308fe6060f1SDimitry Andric // or vsetivli. 309fe6060f1SDimitry Andric OPERAND_AVL, 310e8d8bef9SDimitry Andric }; 311e8d8bef9SDimitry Andric } // namespace RISCVOp 312e8d8bef9SDimitry Andric 313e8d8bef9SDimitry Andric // Describes the predecessor/successor bits used in the FENCE instruction. 314e8d8bef9SDimitry Andric namespace RISCVFenceField { 315e8d8bef9SDimitry Andric enum FenceField { 316e8d8bef9SDimitry Andric I = 8, 317e8d8bef9SDimitry Andric O = 4, 318e8d8bef9SDimitry Andric R = 2, 319e8d8bef9SDimitry Andric W = 1 320e8d8bef9SDimitry Andric }; 321e8d8bef9SDimitry Andric } 322e8d8bef9SDimitry Andric 323e8d8bef9SDimitry Andric // Describes the supported floating point rounding mode encodings. 324e8d8bef9SDimitry Andric namespace RISCVFPRndMode { 325e8d8bef9SDimitry Andric enum RoundingMode { 326e8d8bef9SDimitry Andric RNE = 0, 327e8d8bef9SDimitry Andric RTZ = 1, 328e8d8bef9SDimitry Andric RDN = 2, 329e8d8bef9SDimitry Andric RUP = 3, 330e8d8bef9SDimitry Andric RMM = 4, 331e8d8bef9SDimitry Andric DYN = 7, 332e8d8bef9SDimitry Andric Invalid 333e8d8bef9SDimitry Andric }; 334e8d8bef9SDimitry Andric 335e8d8bef9SDimitry Andric inline static StringRef roundingModeToString(RoundingMode RndMode) { 336e8d8bef9SDimitry Andric switch (RndMode) { 337e8d8bef9SDimitry Andric default: 338e8d8bef9SDimitry Andric llvm_unreachable("Unknown floating point rounding mode"); 339e8d8bef9SDimitry Andric case RISCVFPRndMode::RNE: 340e8d8bef9SDimitry Andric return "rne"; 341e8d8bef9SDimitry Andric case RISCVFPRndMode::RTZ: 342e8d8bef9SDimitry Andric return "rtz"; 343e8d8bef9SDimitry Andric case RISCVFPRndMode::RDN: 344e8d8bef9SDimitry Andric return "rdn"; 345e8d8bef9SDimitry Andric case RISCVFPRndMode::RUP: 346e8d8bef9SDimitry Andric return "rup"; 347e8d8bef9SDimitry Andric case RISCVFPRndMode::RMM: 348e8d8bef9SDimitry Andric return "rmm"; 349e8d8bef9SDimitry Andric case RISCVFPRndMode::DYN: 350e8d8bef9SDimitry Andric return "dyn"; 351e8d8bef9SDimitry Andric } 352e8d8bef9SDimitry Andric } 353e8d8bef9SDimitry Andric 354e8d8bef9SDimitry Andric inline static RoundingMode stringToRoundingMode(StringRef Str) { 355e8d8bef9SDimitry Andric return StringSwitch<RoundingMode>(Str) 356e8d8bef9SDimitry Andric .Case("rne", RISCVFPRndMode::RNE) 357e8d8bef9SDimitry Andric .Case("rtz", RISCVFPRndMode::RTZ) 358e8d8bef9SDimitry Andric .Case("rdn", RISCVFPRndMode::RDN) 359e8d8bef9SDimitry Andric .Case("rup", RISCVFPRndMode::RUP) 360e8d8bef9SDimitry Andric .Case("rmm", RISCVFPRndMode::RMM) 361e8d8bef9SDimitry Andric .Case("dyn", RISCVFPRndMode::DYN) 362e8d8bef9SDimitry Andric .Default(RISCVFPRndMode::Invalid); 363e8d8bef9SDimitry Andric } 364e8d8bef9SDimitry Andric 365e8d8bef9SDimitry Andric inline static bool isValidRoundingMode(unsigned Mode) { 366e8d8bef9SDimitry Andric switch (Mode) { 367e8d8bef9SDimitry Andric default: 368e8d8bef9SDimitry Andric return false; 369e8d8bef9SDimitry Andric case RISCVFPRndMode::RNE: 370e8d8bef9SDimitry Andric case RISCVFPRndMode::RTZ: 371e8d8bef9SDimitry Andric case RISCVFPRndMode::RDN: 372e8d8bef9SDimitry Andric case RISCVFPRndMode::RUP: 373e8d8bef9SDimitry Andric case RISCVFPRndMode::RMM: 374e8d8bef9SDimitry Andric case RISCVFPRndMode::DYN: 375e8d8bef9SDimitry Andric return true; 376e8d8bef9SDimitry Andric } 377e8d8bef9SDimitry Andric } 378e8d8bef9SDimitry Andric } // namespace RISCVFPRndMode 379e8d8bef9SDimitry Andric 380*0fca6ea1SDimitry Andric namespace RISCVVXRndMode { 381*0fca6ea1SDimitry Andric enum RoundingMode { 382*0fca6ea1SDimitry Andric RNU = 0, 383*0fca6ea1SDimitry Andric RNE = 1, 384*0fca6ea1SDimitry Andric RDN = 2, 385*0fca6ea1SDimitry Andric ROD = 3, 386*0fca6ea1SDimitry Andric }; 387*0fca6ea1SDimitry Andric } // namespace RISCVVXRndMode 388*0fca6ea1SDimitry Andric 38906c3fb27SDimitry Andric //===----------------------------------------------------------------------===// 39006c3fb27SDimitry Andric // Floating-point Immediates 39106c3fb27SDimitry Andric // 39206c3fb27SDimitry Andric 39306c3fb27SDimitry Andric namespace RISCVLoadFPImm { 39406c3fb27SDimitry Andric float getFPImm(unsigned Imm); 39506c3fb27SDimitry Andric 39606c3fb27SDimitry Andric /// getLoadFPImm - Return a 5-bit binary encoding of the floating-point 39706c3fb27SDimitry Andric /// immediate value. If the value cannot be represented as a 5-bit binary 39806c3fb27SDimitry Andric /// encoding, then return -1. 39906c3fb27SDimitry Andric int getLoadFPImm(APFloat FPImm); 40006c3fb27SDimitry Andric } // namespace RISCVLoadFPImm 40106c3fb27SDimitry Andric 402e8d8bef9SDimitry Andric namespace RISCVSysReg { 403e8d8bef9SDimitry Andric struct SysReg { 404e8d8bef9SDimitry Andric const char *Name; 405647cbc5dSDimitry Andric const char *AltName; 406fe6060f1SDimitry Andric const char *DeprecatedName; 407fe6060f1SDimitry Andric unsigned Encoding; 408e8d8bef9SDimitry Andric // FIXME: add these additional fields when needed. 409e8d8bef9SDimitry Andric // Privilege Access: Read, Write, Read-Only. 410e8d8bef9SDimitry Andric // unsigned ReadWrite; 411e8d8bef9SDimitry Andric // Privilege Mode: User, System or Machine. 412e8d8bef9SDimitry Andric // unsigned Mode; 413e8d8bef9SDimitry Andric // Check field name. 414e8d8bef9SDimitry Andric // unsigned Extra; 415e8d8bef9SDimitry Andric // Register number without the privilege bits. 416e8d8bef9SDimitry Andric // unsigned Number; 417e8d8bef9SDimitry Andric FeatureBitset FeaturesRequired; 418e8d8bef9SDimitry Andric bool isRV32Only; 419e8d8bef9SDimitry Andric 420fe6060f1SDimitry Andric bool haveRequiredFeatures(const FeatureBitset &ActiveFeatures) const { 421e8d8bef9SDimitry Andric // Not in 32-bit mode. 422e8d8bef9SDimitry Andric if (isRV32Only && ActiveFeatures[RISCV::Feature64Bit]) 423e8d8bef9SDimitry Andric return false; 424e8d8bef9SDimitry Andric // No required feature associated with the system register. 425e8d8bef9SDimitry Andric if (FeaturesRequired.none()) 426e8d8bef9SDimitry Andric return true; 427e8d8bef9SDimitry Andric return (FeaturesRequired & ActiveFeatures) == FeaturesRequired; 428e8d8bef9SDimitry Andric } 429e8d8bef9SDimitry Andric }; 430e8d8bef9SDimitry Andric 431e8d8bef9SDimitry Andric #define GET_SysRegsList_DECL 432e8d8bef9SDimitry Andric #include "RISCVGenSearchableTables.inc" 433e8d8bef9SDimitry Andric } // end namespace RISCVSysReg 434e8d8bef9SDimitry Andric 4350eae32dcSDimitry Andric namespace RISCVInsnOpcode { 4360eae32dcSDimitry Andric struct RISCVOpcode { 4370eae32dcSDimitry Andric const char *Name; 4380eae32dcSDimitry Andric unsigned Value; 4390eae32dcSDimitry Andric }; 4400eae32dcSDimitry Andric 4410eae32dcSDimitry Andric #define GET_RISCVOpcodesList_DECL 4420eae32dcSDimitry Andric #include "RISCVGenSearchableTables.inc" 4430eae32dcSDimitry Andric } // end namespace RISCVInsnOpcode 4440eae32dcSDimitry Andric 445e8d8bef9SDimitry Andric namespace RISCVABI { 446e8d8bef9SDimitry Andric 447e8d8bef9SDimitry Andric enum ABI { 448e8d8bef9SDimitry Andric ABI_ILP32, 449e8d8bef9SDimitry Andric ABI_ILP32F, 450e8d8bef9SDimitry Andric ABI_ILP32D, 451e8d8bef9SDimitry Andric ABI_ILP32E, 452e8d8bef9SDimitry Andric ABI_LP64, 453e8d8bef9SDimitry Andric ABI_LP64F, 454e8d8bef9SDimitry Andric ABI_LP64D, 45506c3fb27SDimitry Andric ABI_LP64E, 456e8d8bef9SDimitry Andric ABI_Unknown 457e8d8bef9SDimitry Andric }; 458e8d8bef9SDimitry Andric 459e8d8bef9SDimitry Andric // Returns the target ABI, or else a StringError if the requested ABIName is 460e8d8bef9SDimitry Andric // not supported for the given TT and FeatureBits combination. 46106c3fb27SDimitry Andric ABI computeTargetABI(const Triple &TT, const FeatureBitset &FeatureBits, 462e8d8bef9SDimitry Andric StringRef ABIName); 463e8d8bef9SDimitry Andric 464e8d8bef9SDimitry Andric ABI getTargetABI(StringRef ABIName); 465e8d8bef9SDimitry Andric 466e8d8bef9SDimitry Andric // Returns the register used to hold the stack pointer after realignment. 467e8d8bef9SDimitry Andric MCRegister getBPReg(); 468e8d8bef9SDimitry Andric 469e8d8bef9SDimitry Andric // Returns the register holding shadow call stack pointer. 470e8d8bef9SDimitry Andric MCRegister getSCSPReg(); 471e8d8bef9SDimitry Andric 472e8d8bef9SDimitry Andric } // namespace RISCVABI 473e8d8bef9SDimitry Andric 474e8d8bef9SDimitry Andric namespace RISCVFeatures { 475e8d8bef9SDimitry Andric 476e8d8bef9SDimitry Andric // Validates if the given combination of features are valid for the target 477e8d8bef9SDimitry Andric // triple. Exits with report_fatal_error if not. 478e8d8bef9SDimitry Andric void validate(const Triple &TT, const FeatureBitset &FeatureBits); 479e8d8bef9SDimitry Andric 48081ad6265SDimitry Andric llvm::Expected<std::unique_ptr<RISCVISAInfo>> 48181ad6265SDimitry Andric parseFeatureBits(bool IsRV64, const FeatureBitset &FeatureBits); 482349cc55cSDimitry Andric 483e8d8bef9SDimitry Andric } // namespace RISCVFeatures 484e8d8bef9SDimitry Andric 485bdd1243dSDimitry Andric namespace RISCVRVC { 486bdd1243dSDimitry Andric bool compress(MCInst &OutInst, const MCInst &MI, const MCSubtargetInfo &STI); 487bdd1243dSDimitry Andric bool uncompress(MCInst &OutInst, const MCInst &MI, const MCSubtargetInfo &STI); 488bdd1243dSDimitry Andric } // namespace RISCVRVC 489bdd1243dSDimitry Andric 49006c3fb27SDimitry Andric namespace RISCVZC { 49106c3fb27SDimitry Andric enum RLISTENCODE { 49206c3fb27SDimitry Andric RA = 4, 49306c3fb27SDimitry Andric RA_S0, 49406c3fb27SDimitry Andric RA_S0_S1, 49506c3fb27SDimitry Andric RA_S0_S2, 49606c3fb27SDimitry Andric RA_S0_S3, 49706c3fb27SDimitry Andric RA_S0_S4, 49806c3fb27SDimitry Andric RA_S0_S5, 49906c3fb27SDimitry Andric RA_S0_S6, 50006c3fb27SDimitry Andric RA_S0_S7, 50106c3fb27SDimitry Andric RA_S0_S8, 50206c3fb27SDimitry Andric RA_S0_S9, 50306c3fb27SDimitry Andric // note - to include s10, s11 must also be included 50406c3fb27SDimitry Andric RA_S0_S11, 50506c3fb27SDimitry Andric INVALID_RLIST, 50606c3fb27SDimitry Andric }; 50706c3fb27SDimitry Andric 50806c3fb27SDimitry Andric inline unsigned encodeRlist(MCRegister EndReg, bool IsRV32E = false) { 50906c3fb27SDimitry Andric assert((!IsRV32E || EndReg <= RISCV::X9) && "Invalid Rlist for RV32E"); 51006c3fb27SDimitry Andric switch (EndReg) { 51106c3fb27SDimitry Andric case RISCV::X1: 51206c3fb27SDimitry Andric return RLISTENCODE::RA; 51306c3fb27SDimitry Andric case RISCV::X8: 51406c3fb27SDimitry Andric return RLISTENCODE::RA_S0; 51506c3fb27SDimitry Andric case RISCV::X9: 51606c3fb27SDimitry Andric return RLISTENCODE::RA_S0_S1; 51706c3fb27SDimitry Andric case RISCV::X18: 51806c3fb27SDimitry Andric return RLISTENCODE::RA_S0_S2; 51906c3fb27SDimitry Andric case RISCV::X19: 52006c3fb27SDimitry Andric return RLISTENCODE::RA_S0_S3; 52106c3fb27SDimitry Andric case RISCV::X20: 52206c3fb27SDimitry Andric return RLISTENCODE::RA_S0_S4; 52306c3fb27SDimitry Andric case RISCV::X21: 52406c3fb27SDimitry Andric return RLISTENCODE::RA_S0_S5; 52506c3fb27SDimitry Andric case RISCV::X22: 52606c3fb27SDimitry Andric return RLISTENCODE::RA_S0_S6; 52706c3fb27SDimitry Andric case RISCV::X23: 52806c3fb27SDimitry Andric return RLISTENCODE::RA_S0_S7; 52906c3fb27SDimitry Andric case RISCV::X24: 53006c3fb27SDimitry Andric return RLISTENCODE::RA_S0_S8; 53106c3fb27SDimitry Andric case RISCV::X25: 53206c3fb27SDimitry Andric return RLISTENCODE::RA_S0_S9; 53306c3fb27SDimitry Andric case RISCV::X26: 53406c3fb27SDimitry Andric return RLISTENCODE::INVALID_RLIST; 53506c3fb27SDimitry Andric case RISCV::X27: 53606c3fb27SDimitry Andric return RLISTENCODE::RA_S0_S11; 53706c3fb27SDimitry Andric default: 53806c3fb27SDimitry Andric llvm_unreachable("Undefined input."); 53906c3fb27SDimitry Andric } 54006c3fb27SDimitry Andric } 54106c3fb27SDimitry Andric 542*0fca6ea1SDimitry Andric inline static unsigned getStackAdjBase(unsigned RlistVal, bool IsRV64) { 54306c3fb27SDimitry Andric assert(RlistVal != RLISTENCODE::INVALID_RLIST && 54406c3fb27SDimitry Andric "{ra, s0-s10} is not supported, s11 must be included."); 54506c3fb27SDimitry Andric if (!IsRV64) { 54606c3fb27SDimitry Andric switch (RlistVal) { 54706c3fb27SDimitry Andric case RLISTENCODE::RA: 54806c3fb27SDimitry Andric case RLISTENCODE::RA_S0: 54906c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S1: 55006c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S2: 55106c3fb27SDimitry Andric return 16; 55206c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S3: 55306c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S4: 55406c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S5: 55506c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S6: 55606c3fb27SDimitry Andric return 32; 55706c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S7: 55806c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S8: 55906c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S9: 56006c3fb27SDimitry Andric return 48; 56106c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S11: 56206c3fb27SDimitry Andric return 64; 56306c3fb27SDimitry Andric } 56406c3fb27SDimitry Andric } else { 56506c3fb27SDimitry Andric switch (RlistVal) { 56606c3fb27SDimitry Andric case RLISTENCODE::RA: 56706c3fb27SDimitry Andric case RLISTENCODE::RA_S0: 56806c3fb27SDimitry Andric return 16; 56906c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S1: 57006c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S2: 57106c3fb27SDimitry Andric return 32; 57206c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S3: 57306c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S4: 57406c3fb27SDimitry Andric return 48; 57506c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S5: 57606c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S6: 57706c3fb27SDimitry Andric return 64; 57806c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S7: 57906c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S8: 58006c3fb27SDimitry Andric return 80; 58106c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S9: 58206c3fb27SDimitry Andric return 96; 58306c3fb27SDimitry Andric case RLISTENCODE::RA_S0_S11: 58406c3fb27SDimitry Andric return 112; 58506c3fb27SDimitry Andric } 58606c3fb27SDimitry Andric } 58706c3fb27SDimitry Andric llvm_unreachable("Unexpected RlistVal"); 58806c3fb27SDimitry Andric } 58906c3fb27SDimitry Andric 59006c3fb27SDimitry Andric inline static bool getSpimm(unsigned RlistVal, unsigned &SpimmVal, 591*0fca6ea1SDimitry Andric int64_t StackAdjustment, bool IsRV64) { 59206c3fb27SDimitry Andric if (RlistVal == RLISTENCODE::INVALID_RLIST) 59306c3fb27SDimitry Andric return false; 594*0fca6ea1SDimitry Andric unsigned StackAdjBase = getStackAdjBase(RlistVal, IsRV64); 595*0fca6ea1SDimitry Andric StackAdjustment -= StackAdjBase; 596*0fca6ea1SDimitry Andric if (StackAdjustment % 16 != 0) 597*0fca6ea1SDimitry Andric return false; 598*0fca6ea1SDimitry Andric SpimmVal = StackAdjustment / 16; 59906c3fb27SDimitry Andric if (SpimmVal > 3) 60006c3fb27SDimitry Andric return false; 60106c3fb27SDimitry Andric return true; 60206c3fb27SDimitry Andric } 60306c3fb27SDimitry Andric 60406c3fb27SDimitry Andric void printRlist(unsigned SlistEncode, raw_ostream &OS); 60506c3fb27SDimitry Andric } // namespace RISCVZC 60606c3fb27SDimitry Andric 607e8d8bef9SDimitry Andric } // namespace llvm 608e8d8bef9SDimitry Andric 609e8d8bef9SDimitry Andric #endif 610