1 //===- MipsABIFlagsSection.h - Mips ELF ABI Flags Section -------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSABIFLAGSSECTION_H
11 #define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSABIFLAGSSECTION_H
12 
13 #include "llvm/ADT/StringRef.h"
14 #include "llvm/Support/ErrorHandling.h"
15 #include "llvm/Support/MipsABIFlags.h"
16 #include <cstdint>
17 
18 namespace llvm {
19 
20 class MCStreamer;
21 
22 struct MipsABIFlagsSection {
23   // Internal representation of the fp_abi related values used in .module.
24   enum class FpABIKind { ANY, XX, S32, S64, SOFT };
25 
26   // Version of flags structure.
27   uint16_t Version = 0;
28   // The level of the ISA: 1-5, 32, 64.
29   uint8_t ISALevel = 0;
30   // The revision of ISA: 0 for MIPS V and below, 1-n otherwise.
31   uint8_t ISARevision = 0;
32   // The size of general purpose registers.
33   Mips::AFL_REG GPRSize = Mips::AFL_REG_NONE;
34   // The size of co-processor 1 registers.
35   Mips::AFL_REG CPR1Size = Mips::AFL_REG_NONE;
36   // The size of co-processor 2 registers.
37   Mips::AFL_REG CPR2Size = Mips::AFL_REG_NONE;
38   // Processor-specific extension.
39   Mips::AFL_EXT ISAExtension = Mips::AFL_EXT_NONE;
40   // Mask of ASEs used.
41   uint32_t ASESet = 0;
42 
43   bool OddSPReg = false;
44 
45   bool Is32BitABI = false;
46 
47 protected:
48   // The floating-point ABI.
49   FpABIKind FpABI = FpABIKind::ANY;
50 
51 public:
52   MipsABIFlagsSection() = default;
53 
getVersionValueMipsABIFlagsSection54   uint16_t getVersionValue() { return (uint16_t)Version; }
getISALevelValueMipsABIFlagsSection55   uint8_t getISALevelValue() { return (uint8_t)ISALevel; }
getISARevisionValueMipsABIFlagsSection56   uint8_t getISARevisionValue() { return (uint8_t)ISARevision; }
getGPRSizeValueMipsABIFlagsSection57   uint8_t getGPRSizeValue() { return (uint8_t)GPRSize; }
58   uint8_t getCPR1SizeValue();
getCPR2SizeValueMipsABIFlagsSection59   uint8_t getCPR2SizeValue() { return (uint8_t)CPR2Size; }
60   uint8_t getFpABIValue();
getISAExtensionValueMipsABIFlagsSection61   uint32_t getISAExtensionValue() { return (uint32_t)ISAExtension; }
getASESetValueMipsABIFlagsSection62   uint32_t getASESetValue() { return (uint32_t)ASESet; }
63 
getFlags1ValueMipsABIFlagsSection64   uint32_t getFlags1Value() {
65     uint32_t Value = 0;
66 
67     if (OddSPReg)
68       Value |= (uint32_t)Mips::AFL_FLAGS1_ODDSPREG;
69 
70     return Value;
71   }
72 
getFlags2ValueMipsABIFlagsSection73   uint32_t getFlags2Value() { return 0; }
74 
getFpABIMipsABIFlagsSection75   FpABIKind getFpABI() { return FpABI; }
setFpABIMipsABIFlagsSection76   void setFpABI(FpABIKind Value, bool IsABI32Bit) {
77     FpABI = Value;
78     Is32BitABI = IsABI32Bit;
79   }
80 
81   StringRef getFpABIString(FpABIKind Value);
82 
83   template <class PredicateLibrary>
setISALevelAndRevisionFromPredicatesMipsABIFlagsSection84   void setISALevelAndRevisionFromPredicates(const PredicateLibrary &P) {
85     if (P.hasMips64()) {
86       ISALevel = 64;
87       if (P.hasMips64r6())
88         ISARevision = 6;
89       else if (P.hasMips64r5())
90         ISARevision = 5;
91       else if (P.hasMips64r3())
92         ISARevision = 3;
93       else if (P.hasMips64r2())
94         ISARevision = 2;
95       else
96         ISARevision = 1;
97     } else if (P.hasMips32()) {
98       ISALevel = 32;
99       if (P.hasMips32r6())
100         ISARevision = 6;
101       else if (P.hasMips32r5())
102         ISARevision = 5;
103       else if (P.hasMips32r3())
104         ISARevision = 3;
105       else if (P.hasMips32r2())
106         ISARevision = 2;
107       else
108         ISARevision = 1;
109     } else {
110       ISARevision = 0;
111       if (P.hasMips5())
112         ISALevel = 5;
113       else if (P.hasMips4())
114         ISALevel = 4;
115       else if (P.hasMips3())
116         ISALevel = 3;
117       else if (P.hasMips2())
118         ISALevel = 2;
119       else if (P.hasMips1())
120         ISALevel = 1;
121       else
122         llvm_unreachable("Unknown ISA level!");
123     }
124   }
125 
126   template <class PredicateLibrary>
setGPRSizeFromPredicatesMipsABIFlagsSection127   void setGPRSizeFromPredicates(const PredicateLibrary &P) {
128     GPRSize = P.isGP64bit() ? Mips::AFL_REG_64 : Mips::AFL_REG_32;
129   }
130 
131   template <class PredicateLibrary>
setCPR1SizeFromPredicatesMipsABIFlagsSection132   void setCPR1SizeFromPredicates(const PredicateLibrary &P) {
133     if (P.useSoftFloat())
134       CPR1Size = Mips::AFL_REG_NONE;
135     else if (P.hasMSA())
136       CPR1Size = Mips::AFL_REG_128;
137     else
138       CPR1Size = P.isFP64bit() ? Mips::AFL_REG_64 : Mips::AFL_REG_32;
139   }
140 
141   template <class PredicateLibrary>
setISAExtensionFromPredicatesMipsABIFlagsSection142   void setISAExtensionFromPredicates(const PredicateLibrary &P) {
143     if (P.hasCnMips())
144       ISAExtension = Mips::AFL_EXT_OCTEON;
145     else
146       ISAExtension = Mips::AFL_EXT_NONE;
147   }
148 
149   template <class PredicateLibrary>
setASESetFromPredicatesMipsABIFlagsSection150   void setASESetFromPredicates(const PredicateLibrary &P) {
151     ASESet = 0;
152     if (P.hasDSP())
153       ASESet |= Mips::AFL_ASE_DSP;
154     if (P.hasDSPR2())
155       ASESet |= Mips::AFL_ASE_DSPR2;
156     if (P.hasMSA())
157       ASESet |= Mips::AFL_ASE_MSA;
158     if (P.inMicroMipsMode())
159       ASESet |= Mips::AFL_ASE_MICROMIPS;
160     if (P.inMips16Mode())
161       ASESet |= Mips::AFL_ASE_MIPS16;
162     if (P.hasMT())
163       ASESet |= Mips::AFL_ASE_MT;
164     if (P.hasCRC())
165       ASESet |= Mips::AFL_ASE_CRC;
166     if (P.hasVirt())
167       ASESet |= Mips::AFL_ASE_VIRT;
168     if (P.hasGINV())
169       ASESet |= Mips::AFL_ASE_GINV;
170   }
171 
172   template <class PredicateLibrary>
setFpAbiFromPredicatesMipsABIFlagsSection173   void setFpAbiFromPredicates(const PredicateLibrary &P) {
174     Is32BitABI = P.isABI_O32();
175 
176     FpABI = FpABIKind::ANY;
177     if (P.useSoftFloat())
178       FpABI = FpABIKind::SOFT;
179     else if (P.isABI_N32() || P.isABI_N64())
180       FpABI = FpABIKind::S64;
181     else if (P.isABI_O32()) {
182       if (P.isABI_FPXX())
183         FpABI = FpABIKind::XX;
184       else if (P.isFP64bit())
185         FpABI = FpABIKind::S64;
186       else
187         FpABI = FpABIKind::S32;
188     }
189   }
190 
191   template <class PredicateLibrary>
setAllFromPredicatesMipsABIFlagsSection192   void setAllFromPredicates(const PredicateLibrary &P) {
193     setISALevelAndRevisionFromPredicates(P);
194     setGPRSizeFromPredicates(P);
195     setCPR1SizeFromPredicates(P);
196     setISAExtensionFromPredicates(P);
197     setASESetFromPredicates(P);
198     setFpAbiFromPredicates(P);
199     OddSPReg = P.useOddSPReg();
200   }
201 };
202 
203 MCStreamer &operator<<(MCStreamer &OS, MipsABIFlagsSection &ABIFlagsSection);
204 
205 } // end namespace llvm
206 
207 #endif // LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSABIFLAGSSECTION_H
208