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/Support/ErrorHandling.h"
14 #include "llvm/Support/MipsABIFlags.h"
15 #include <cstdint>
16 
17 namespace llvm {
18 
19 class MCStreamer;
20 
21 struct MipsABIFlagsSection {
22   // Internal representation of the fp_abi related values used in .module.
23   enum class FpABIKind { ANY, XX, S32, S64, SOFT };
24 
25   // Version of flags structure.
26   uint16_t Version = 0;
27   // The level of the ISA: 1-5, 32, 64.
28   uint8_t ISALevel = 0;
29   // The revision of ISA: 0 for MIPS V and below, 1-n otherwise.
30   uint8_t ISARevision = 0;
31   // The size of general purpose registers.
32   Mips::AFL_REG GPRSize = Mips::AFL_REG_NONE;
33   // The size of co-processor 1 registers.
34   Mips::AFL_REG CPR1Size = Mips::AFL_REG_NONE;
35   // The size of co-processor 2 registers.
36   Mips::AFL_REG CPR2Size = Mips::AFL_REG_NONE;
37   // Processor-specific extension.
38   Mips::AFL_EXT ISAExtension = Mips::AFL_EXT_NONE;
39   // Mask of ASEs used.
40   uint32_t ASESet = 0;
41 
42   bool OddSPReg = false;
43 
44   bool Is32BitABI = false;
45 
46 protected:
47   // The floating-point ABI.
48   FpABIKind FpABI = FpABIKind::ANY;
49 
50 public:
51   MipsABIFlagsSection() = default;
52 
getVersionValueMipsABIFlagsSection53   uint16_t getVersionValue() { return (uint16_t)Version; }
getISALevelValueMipsABIFlagsSection54   uint8_t getISALevelValue() { return (uint8_t)ISALevel; }
getISARevisionValueMipsABIFlagsSection55   uint8_t getISARevisionValue() { return (uint8_t)ISARevision; }
getGPRSizeValueMipsABIFlagsSection56   uint8_t getGPRSizeValue() { return (uint8_t)GPRSize; }
57   uint8_t getCPR1SizeValue();
getCPR2SizeValueMipsABIFlagsSection58   uint8_t getCPR2SizeValue() { return (uint8_t)CPR2Size; }
59   uint8_t getFpABIValue();
getISAExtensionValueMipsABIFlagsSection60   uint32_t getISAExtensionValue() { return (uint32_t)ISAExtension; }
getASESetValueMipsABIFlagsSection61   uint32_t getASESetValue() { return (uint32_t)ASESet; }
62 
getFlags1ValueMipsABIFlagsSection63   uint32_t getFlags1Value() {
64     uint32_t Value = 0;
65 
66     if (OddSPReg)
67       Value |= (uint32_t)Mips::AFL_FLAGS1_ODDSPREG;
68 
69     return Value;
70   }
71 
getFlags2ValueMipsABIFlagsSection72   uint32_t getFlags2Value() { return 0; }
73 
getFpABIMipsABIFlagsSection74   FpABIKind getFpABI() { return FpABI; }
setFpABIMipsABIFlagsSection75   void setFpABI(FpABIKind Value, bool IsABI32Bit) {
76     FpABI = Value;
77     Is32BitABI = IsABI32Bit;
78   }
79 
80   StringRef getFpABIString(FpABIKind Value);
81 
82   template <class PredicateLibrary>
setISALevelAndRevisionFromPredicatesMipsABIFlagsSection83   void setISALevelAndRevisionFromPredicates(const PredicateLibrary &P) {
84     if (P.hasMips64()) {
85       ISALevel = 64;
86       if (P.hasMips64r6())
87         ISARevision = 6;
88       else if (P.hasMips64r5())
89         ISARevision = 5;
90       else if (P.hasMips64r3())
91         ISARevision = 3;
92       else if (P.hasMips64r2())
93         ISARevision = 2;
94       else
95         ISARevision = 1;
96     } else if (P.hasMips32()) {
97       ISALevel = 32;
98       if (P.hasMips32r6())
99         ISARevision = 6;
100       else if (P.hasMips32r5())
101         ISARevision = 5;
102       else if (P.hasMips32r3())
103         ISARevision = 3;
104       else if (P.hasMips32r2())
105         ISARevision = 2;
106       else
107         ISARevision = 1;
108     } else {
109       ISARevision = 0;
110       if (P.hasMips5())
111         ISALevel = 5;
112       else if (P.hasMips4())
113         ISALevel = 4;
114       else if (P.hasMips3())
115         ISALevel = 3;
116       else if (P.hasMips2())
117         ISALevel = 2;
118       else if (P.hasMips1())
119         ISALevel = 1;
120       else
121         llvm_unreachable("Unknown ISA level!");
122     }
123   }
124 
125   template <class PredicateLibrary>
setGPRSizeFromPredicatesMipsABIFlagsSection126   void setGPRSizeFromPredicates(const PredicateLibrary &P) {
127     GPRSize = P.isGP64bit() ? Mips::AFL_REG_64 : Mips::AFL_REG_32;
128   }
129 
130   template <class PredicateLibrary>
setCPR1SizeFromPredicatesMipsABIFlagsSection131   void setCPR1SizeFromPredicates(const PredicateLibrary &P) {
132     if (P.useSoftFloat())
133       CPR1Size = Mips::AFL_REG_NONE;
134     else if (P.hasMSA())
135       CPR1Size = Mips::AFL_REG_128;
136     else
137       CPR1Size = P.isFP64bit() ? Mips::AFL_REG_64 : Mips::AFL_REG_32;
138   }
139 
140   template <class PredicateLibrary>
setISAExtensionFromPredicatesMipsABIFlagsSection141   void setISAExtensionFromPredicates(const PredicateLibrary &P) {
142     if (P.hasCnMipsP())
143       ISAExtension = Mips::AFL_EXT_OCTEONP;
144     else if (P.hasCnMips())
145       ISAExtension = Mips::AFL_EXT_OCTEON;
146     else
147       ISAExtension = Mips::AFL_EXT_NONE;
148   }
149 
150   template <class PredicateLibrary>
setASESetFromPredicatesMipsABIFlagsSection151   void setASESetFromPredicates(const PredicateLibrary &P) {
152     ASESet = 0;
153     if (P.hasDSP())
154       ASESet |= Mips::AFL_ASE_DSP;
155     if (P.hasDSPR2())
156       ASESet |= Mips::AFL_ASE_DSPR2;
157     if (P.hasMSA())
158       ASESet |= Mips::AFL_ASE_MSA;
159     if (P.inMicroMipsMode())
160       ASESet |= Mips::AFL_ASE_MICROMIPS;
161     if (P.inMips16Mode())
162       ASESet |= Mips::AFL_ASE_MIPS16;
163     if (P.hasMT())
164       ASESet |= Mips::AFL_ASE_MT;
165     if (P.hasCRC())
166       ASESet |= Mips::AFL_ASE_CRC;
167     if (P.hasVirt())
168       ASESet |= Mips::AFL_ASE_VIRT;
169     if (P.hasGINV())
170       ASESet |= Mips::AFL_ASE_GINV;
171   }
172 
173   template <class PredicateLibrary>
setFpAbiFromPredicatesMipsABIFlagsSection174   void setFpAbiFromPredicates(const PredicateLibrary &P) {
175     Is32BitABI = P.isABI_O32();
176 
177     FpABI = FpABIKind::ANY;
178     if (P.useSoftFloat())
179       FpABI = FpABIKind::SOFT;
180     else if (P.isABI_N32() || P.isABI_N64())
181       FpABI = FpABIKind::S64;
182     else if (P.isABI_O32()) {
183       if (P.isABI_FPXX())
184         FpABI = FpABIKind::XX;
185       else if (P.isFP64bit())
186         FpABI = FpABIKind::S64;
187       else
188         FpABI = FpABIKind::S32;
189     }
190   }
191 
192   template <class PredicateLibrary>
setAllFromPredicatesMipsABIFlagsSection193   void setAllFromPredicates(const PredicateLibrary &P) {
194     setISALevelAndRevisionFromPredicates(P);
195     setGPRSizeFromPredicates(P);
196     setCPR1SizeFromPredicates(P);
197     setISAExtensionFromPredicates(P);
198     setASESetFromPredicates(P);
199     setFpAbiFromPredicates(P);
200     OddSPReg = P.useOddSPReg();
201   }
202 };
203 
204 MCStreamer &operator<<(MCStreamer &OS, MipsABIFlagsSection &ABIFlagsSection);
205 
206 } // end namespace llvm
207 
208 #endif // LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSABIFLAGSSECTION_H
209