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