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/Support/ErrorHandling.h"
13#include "llvm/Support/MipsABIFlags.h"
14#include <cstdint>
15
16namespace llvm {
17
18class MCStreamer;
19class StringRef;
20
21struct 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
46protected:
47 // The floating-point ABI.
48 FpABIKind FpABI = FpABIKind::ANY;
49
50public:
51 MipsABIFlagsSection() = default;
52
53 uint16_t getVersionValue() { return (uint16_t)Version; }
54 uint8_t getISALevelValue() { return (uint8_t)ISALevel; }
55 uint8_t getISARevisionValue() { return (uint8_t)ISARevision; }
56 uint8_t getGPRSizeValue() { return (uint8_t)GPRSize; }
57 uint8_t getCPR1SizeValue();
58 uint8_t getCPR2SizeValue() { return (uint8_t)CPR2Size; }
59 uint8_t getFpABIValue();
60 uint32_t getISAExtensionValue() { return (uint32_t)ISAExtension; }
61 uint32_t getASESetValue() { return (uint32_t)ASESet; }
62
63 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
72 uint32_t getFlags2Value() { return 0; }
73
74 FpABIKind getFpABI() { return FpABI; }
75 void setFpABI(FpABIKind Value, bool IsABI32Bit) {
76 FpABI = Value;
77 Is32BitABI = IsABI32Bit;
78 }
79
80 StringRef getFpABIString(FpABIKind Value);
81
82 template <class PredicateLibrary>
83 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>
126 void setGPRSizeFromPredicates(const PredicateLibrary &P) {
127 GPRSize = P.isGP64bit() ? Mips::AFL_REG_64 : Mips::AFL_REG_32;
128 }
129
130 template <class PredicateLibrary>
131 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>
141 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>
151 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>
174 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>
193 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
204MCStreamer &operator<<(MCStreamer &OS, MipsABIFlagsSection &ABIFlagsSection);
205
206} // end namespace llvm
207
208#endif // LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSABIFLAGSSECTION_H
209