1 //===- MipsABIFlagsSection.h - Mips ELF ABI Flags Section -------*- 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 #ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSABIFLAGSSECTION_H 10 #define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSABIFLAGSSECTION_H 11 12 #include "llvm/ADT/StringRef.h" 13 #include "llvm/ADT/Optional.h" 14 #include "llvm/MC/MCTargetOptions.h" 15 #include "llvm/Support/ErrorHandling.h" 16 #include "llvm/Support/MipsABIFlags.h" 17 #include <cstdint> 18 19 #include "MipsABIInfo.h" 20 21 namespace llvm { 22 23 class MCStreamer; 24 25 struct MipsABIFlagsSection { 26 // Internal representation of the fp_abi related values used in .module. 27 enum class FpABIKind { ANY, XX, S32, S64, SOFT }; 28 29 // Version of flags structure. 30 uint16_t Version = 0; 31 // The level of the ISA: 1-5, 32, 64. 32 uint8_t ISALevel = 0; 33 // The revision of ISA: 0 for MIPS V and below, 1-n otherwise. 34 uint8_t ISARevision = 0; 35 // The size of general purpose registers. 36 Mips::AFL_REG GPRSize = Mips::AFL_REG_NONE; 37 // The size of co-processor 1 registers. 38 Mips::AFL_REG CPR1Size = Mips::AFL_REG_NONE; 39 // The size of co-processor 2 registers. 40 Mips::AFL_REG CPR2Size = Mips::AFL_REG_NONE; 41 // Processor-specific extension. 42 Mips::AFL_EXT ISAExtension = Mips::AFL_EXT_NONE; 43 // Mask of ASEs used. 44 uint32_t ASESet = 0; 45 46 bool OddSPReg = false; 47 48 bool Is32BitABI = false; 49 50 protected: 51 // The floating-point ABI. 52 FpABIKind FpABI = FpABIKind::ANY; 53 54 public: 55 MipsABIFlagsSection() = default; 56 getVersionValueMipsABIFlagsSection57 uint16_t getVersionValue() { return (uint16_t)Version; } getISALevelValueMipsABIFlagsSection58 uint8_t getISALevelValue() { return (uint8_t)ISALevel; } getISARevisionValueMipsABIFlagsSection59 uint8_t getISARevisionValue() { return (uint8_t)ISARevision; } getGPRSizeValueMipsABIFlagsSection60 uint8_t getGPRSizeValue() { return (uint8_t)GPRSize; } 61 uint8_t getCPR1SizeValue(); getCPR2SizeValueMipsABIFlagsSection62 uint8_t getCPR2SizeValue() { return (uint8_t)CPR2Size; } 63 uint8_t getFpABIValue(); getISAExtensionValueMipsABIFlagsSection64 uint32_t getISAExtensionValue() { return (uint32_t)ISAExtension; } getASESetValueMipsABIFlagsSection65 uint32_t getASESetValue() { return (uint32_t)ASESet; } 66 getFlags1ValueMipsABIFlagsSection67 uint32_t getFlags1Value() { 68 uint32_t Value = 0; 69 70 if (OddSPReg) 71 Value |= (uint32_t)Mips::AFL_FLAGS1_ODDSPREG; 72 73 return Value; 74 } 75 getFlags2ValueMipsABIFlagsSection76 uint32_t getFlags2Value() { return 0; } 77 getFpABIMipsABIFlagsSection78 FpABIKind getFpABI() { return FpABI; } setFpABIMipsABIFlagsSection79 void setFpABI(FpABIKind Value, bool IsABI32Bit) { 80 FpABI = Value; 81 Is32BitABI = IsABI32Bit; 82 } 83 84 StringRef getFpABIString(FpABIKind Value); 85 86 template <class PredicateLibrary> setISALevelAndRevisionFromPredicatesMipsABIFlagsSection87 void setISALevelAndRevisionFromPredicates(const PredicateLibrary &P) { 88 if (P.hasMips64()) { 89 ISALevel = 64; 90 if (P.hasMips64r6()) 91 ISARevision = 6; 92 else if (P.hasMips64r5()) 93 ISARevision = 5; 94 else if (P.hasMips64r3()) 95 ISARevision = 3; 96 else if (P.hasMips64r2()) 97 ISARevision = 2; 98 else 99 ISARevision = 1; 100 } else if (P.hasMips32()) { 101 ISALevel = 32; 102 if (P.hasMips32r6()) 103 ISARevision = 6; 104 else if (P.hasMips32r5()) 105 ISARevision = 5; 106 else if (P.hasMips32r3()) 107 ISARevision = 3; 108 else if (P.hasMips32r2()) 109 ISARevision = 2; 110 else 111 ISARevision = 1; 112 } else { 113 ISARevision = 0; 114 if (P.hasMips5()) 115 ISALevel = 5; 116 else if (P.hasMips4()) 117 ISALevel = 4; 118 else if (P.hasMips3()) 119 ISALevel = 3; 120 else if (P.hasMips2()) 121 ISALevel = 2; 122 else if (P.hasMips1()) 123 ISALevel = 1; 124 else 125 llvm_unreachable("Unknown ISA level!"); 126 } 127 } 128 129 template <class PredicateLibrary> setGPRSizeFromPredicatesMipsABIFlagsSection130 void setGPRSizeFromPredicates(const PredicateLibrary &P) { 131 GPRSize = P.isGP64bit() ? Mips::AFL_REG_64 : Mips::AFL_REG_32; 132 } 133 134 template <class PredicateLibrary> setCPR1SizeFromPredicatesMipsABIFlagsSection135 void setCPR1SizeFromPredicates(const PredicateLibrary &P) { 136 if (P.useSoftFloat()) 137 CPR1Size = Mips::AFL_REG_NONE; 138 else if (P.hasMSA()) 139 CPR1Size = Mips::AFL_REG_128; 140 else 141 CPR1Size = P.isFP64bit() ? Mips::AFL_REG_64 : Mips::AFL_REG_32; 142 } 143 144 template <class PredicateLibrary> setISAExtensionFromPredicatesMipsABIFlagsSection145 void setISAExtensionFromPredicates(const PredicateLibrary &P, const MipsABIInfo& ABI) { 146 if (ABI.IsCheriPureCap()) 147 ISAExtension = CheriPurecapISA_EXT(ABI); 148 else if (P.hasCnMipsP()) 149 ISAExtension = Mips::AFL_EXT_OCTEONP; 150 else if (P.hasCnMips()) 151 ISAExtension = Mips::AFL_EXT_OCTEON; 152 else 153 ISAExtension = Mips::AFL_EXT_NONE; 154 } 155 156 template <class PredicateLibrary> setASESetFromPredicatesMipsABIFlagsSection157 void setASESetFromPredicates(const PredicateLibrary &P) { 158 ASESet = 0; 159 if (P.hasDSP()) 160 ASESet |= Mips::AFL_ASE_DSP; 161 if (P.hasDSPR2()) 162 ASESet |= Mips::AFL_ASE_DSPR2; 163 if (P.hasMSA()) 164 ASESet |= Mips::AFL_ASE_MSA; 165 if (P.inMicroMipsMode()) 166 ASESet |= Mips::AFL_ASE_MICROMIPS; 167 if (P.inMips16Mode()) 168 ASESet |= Mips::AFL_ASE_MIPS16; 169 if (P.hasMT()) 170 ASESet |= Mips::AFL_ASE_MT; 171 if (P.hasCRC()) 172 ASESet |= Mips::AFL_ASE_CRC; 173 if (P.hasVirt()) 174 ASESet |= Mips::AFL_ASE_VIRT; 175 if (P.hasGINV()) 176 ASESet |= Mips::AFL_ASE_GINV; 177 } 178 179 template <class PredicateLibrary> setFpAbiFromPredicatesMipsABIFlagsSection180 void setFpAbiFromPredicates(const PredicateLibrary &P) { 181 Is32BitABI = P.isABI_O32(); 182 183 FpABI = FpABIKind::ANY; 184 if (P.useSoftFloat()) 185 FpABI = FpABIKind::SOFT; 186 else if (P.isABI_N32() || P.isABI_N64()) 187 FpABI = FpABIKind::S64; 188 else if (P.isABI_O32()) { 189 if (P.isABI_FPXX()) 190 FpABI = FpABIKind::XX; 191 else if (P.isFP64bit()) 192 FpABI = FpABIKind::S64; 193 else 194 FpABI = FpABIKind::S32; 195 } 196 } 197 198 template <class PredicateLibrary> setAllFromPredicatesMipsABIFlagsSection199 void setAllFromPredicates(const PredicateLibrary &P, const MipsABIInfo& ABI) { 200 setISALevelAndRevisionFromPredicates(P); 201 setGPRSizeFromPredicates(P); 202 setCPR1SizeFromPredicates(P); 203 setISAExtensionFromPredicates(P, ABI); 204 setASESetFromPredicates(P); 205 setFpAbiFromPredicates(P); 206 OddSPReg = P.useOddSPReg(); 207 } 208 private: CheriPurecapISA_EXTMipsABIFlagsSection209 Mips::AFL_EXT CheriPurecapISA_EXT(const MipsABIInfo& ABI) const { 210 CheriCapabilityTableABI CTA = ABI.CapabilityTableABI(); 211 if ((int)CTA == 0) 212 return Mips::AFL_EXT_CHERI_ABI_LEGACY; 213 switch (CTA) { 214 case CheriCapabilityTableABI::PLT: 215 return Mips::AFL_EXT_CHERI_ABI_PLT; 216 case CheriCapabilityTableABI::Pcrel: 217 return Mips::AFL_EXT_CHERI_ABI_PCREL; 218 case CheriCapabilityTableABI::FunctionDescriptor: 219 return Mips::AFL_EXT_CHERI_ABI_FNDESC; 220 } 221 llvm_unreachable("CheriCapabilityTableABI not set"); 222 } 223 }; 224 225 MCStreamer &operator<<(MCStreamer &OS, MipsABIFlagsSection &ABIFlagsSection); 226 227 } // end namespace llvm 228 229 #endif // LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSABIFLAGSSECTION_H 230