1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_MIPS_H |
14 | #define LLVM_CLANG_LIB_BASIC_TARGETS_MIPS_H |
15 | |
16 | #include "clang/Basic/TargetInfo.h" |
17 | #include "clang/Basic/TargetOptions.h" |
18 | #include "llvm/ADT/Triple.h" |
19 | #include "llvm/Support/Compiler.h" |
20 | |
21 | namespace clang { |
22 | namespace targets { |
23 | |
24 | class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo { |
25 | void setDataLayout() { |
26 | StringRef Layout; |
27 | |
28 | if (ABI == "o32") |
29 | Layout = "m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64"; |
30 | else if (ABI == "n32") |
31 | Layout = "m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32:64-S128"; |
32 | else if (ABI == "n64") |
33 | Layout = "m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128"; |
34 | else |
35 | llvm_unreachable("Invalid ABI"); |
36 | |
37 | if (BigEndian) |
38 | resetDataLayout(("E-" + Layout).str()); |
39 | else |
40 | resetDataLayout(("e-" + Layout).str()); |
41 | } |
42 | |
43 | static const Builtin::Info BuiltinInfo[]; |
44 | std::string CPU; |
45 | bool IsMips16; |
46 | bool IsMicromips; |
47 | bool IsNan2008; |
48 | bool IsAbs2008; |
49 | bool IsSingleFloat; |
50 | bool IsNoABICalls; |
51 | bool CanUseBSDABICalls; |
52 | enum MipsFloatABI { HardFloat, SoftFloat } FloatABI; |
53 | enum DspRevEnum { NoDSP, DSP1, DSP2 } DspRev; |
54 | bool HasMSA; |
55 | bool DisableMadd4; |
56 | bool UseIndirectJumpHazard; |
57 | |
58 | protected: |
59 | enum FPModeEnum { FPXX, FP32, FP64 } FPMode; |
60 | std::string ABI; |
61 | |
62 | public: |
63 | MipsTargetInfo(const llvm::Triple &Triple, const TargetOptions &) |
64 | : TargetInfo(Triple), IsMips16(false), IsMicromips(false), |
65 | IsNan2008(false), IsAbs2008(false), IsSingleFloat(false), |
66 | IsNoABICalls(false), CanUseBSDABICalls(false), FloatABI(HardFloat), |
67 | DspRev(NoDSP), HasMSA(false), DisableMadd4(false), |
68 | UseIndirectJumpHazard(false), FPMode(FPXX) { |
69 | TheCXXABI.set(TargetCXXABI::GenericMIPS); |
70 | |
71 | if (Triple.isMIPS32()) |
72 | setABI("o32"); |
73 | else if (Triple.getEnvironment() == llvm::Triple::GNUABIN32) |
74 | setABI("n32"); |
75 | else |
76 | setABI("n64"); |
77 | |
78 | CPU = ABI == "o32" ? "mips32r2" : "mips64r2"; |
79 | |
80 | CanUseBSDABICalls = Triple.isOSFreeBSD() || |
81 | Triple.isOSOpenBSD(); |
82 | } |
83 | |
84 | bool isIEEE754_2008Default() const { |
85 | return CPU == "mips32r6" || CPU == "mips64r6"; |
86 | } |
87 | |
88 | bool isFP64Default() const { |
89 | return CPU == "mips32r6" || ABI == "n32" || ABI == "n64" || ABI == "64"; |
90 | } |
91 | |
92 | bool isNan2008() const override { return IsNan2008; } |
93 | |
94 | bool processorSupportsGPR64() const; |
95 | |
96 | StringRef getABI() const override { return ABI; } |
97 | |
98 | bool setABI(const std::string &Name) override { |
99 | if (Name == "o32") { |
100 | setO32ABITypes(); |
101 | ABI = Name; |
102 | return true; |
103 | } |
104 | |
105 | if (Name == "n32") { |
106 | setN32ABITypes(); |
107 | ABI = Name; |
108 | return true; |
109 | } |
110 | if (Name == "n64") { |
111 | setN64ABITypes(); |
112 | ABI = Name; |
113 | return true; |
114 | } |
115 | return false; |
116 | } |
117 | |
118 | void setO32ABITypes() { |
119 | Int64Type = SignedLongLong; |
120 | IntMaxType = Int64Type; |
121 | LongDoubleFormat = &llvm::APFloat::IEEEdouble(); |
122 | LongDoubleWidth = LongDoubleAlign = 64; |
123 | LongWidth = LongAlign = 32; |
124 | MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32; |
125 | PointerWidth = PointerAlign = 32; |
126 | PtrDiffType = SignedInt; |
127 | SizeType = UnsignedInt; |
128 | SuitableAlign = 64; |
129 | } |
130 | |
131 | void setN32N64ABITypes() { |
132 | LongDoubleWidth = LongDoubleAlign = 128; |
133 | LongDoubleFormat = &llvm::APFloat::IEEEquad(); |
134 | if (getTriple().isOSFreeBSD()) { |
135 | LongDoubleWidth = LongDoubleAlign = 64; |
136 | LongDoubleFormat = &llvm::APFloat::IEEEdouble(); |
137 | } |
138 | MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; |
139 | SuitableAlign = 128; |
140 | } |
141 | |
142 | void setN64ABITypes() { |
143 | setN32N64ABITypes(); |
144 | if (getTriple().isOSOpenBSD()) { |
145 | Int64Type = SignedLongLong; |
146 | } else { |
147 | Int64Type = SignedLong; |
148 | } |
149 | IntMaxType = Int64Type; |
150 | LongWidth = LongAlign = 64; |
151 | PointerWidth = PointerAlign = 64; |
152 | PtrDiffType = SignedLong; |
153 | SizeType = UnsignedLong; |
154 | } |
155 | |
156 | void setN32ABITypes() { |
157 | setN32N64ABITypes(); |
158 | Int64Type = SignedLongLong; |
159 | IntMaxType = Int64Type; |
160 | LongWidth = LongAlign = 32; |
161 | PointerWidth = PointerAlign = 32; |
162 | PtrDiffType = SignedInt; |
163 | SizeType = UnsignedInt; |
164 | } |
165 | |
166 | bool isValidCPUName(StringRef Name) const override; |
167 | void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; |
168 | |
169 | bool setCPU(const std::string &Name) override { |
170 | CPU = Name; |
171 | return isValidCPUName(Name); |
172 | } |
173 | |
174 | const std::string &getCPU() const { return CPU; } |
175 | bool |
176 | initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, |
177 | StringRef CPU, |
178 | const std::vector<std::string> &FeaturesVec) const override { |
179 | if (CPU.empty()) |
180 | CPU = getCPU(); |
181 | if (CPU == "octeon") |
182 | Features["mips64r2"] = Features["cnmips"] = true; |
183 | else |
184 | Features[CPU] = true; |
185 | return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec); |
186 | } |
187 | |
188 | unsigned getISARev() const; |
189 | |
190 | void getTargetDefines(const LangOptions &Opts, |
191 | MacroBuilder &Builder) const override; |
192 | |
193 | ArrayRef<Builtin::Info> getTargetBuiltins() const override; |
194 | |
195 | bool hasFeature(StringRef Feature) const override; |
196 | |
197 | BuiltinVaListKind getBuiltinVaListKind() const override { |
198 | return TargetInfo::VoidPtrBuiltinVaList; |
199 | } |
200 | |
201 | ArrayRef<const char *> getGCCRegNames() const override { |
202 | static const char *const GCCRegNames[] = { |
203 | |
204 | |
205 | "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", |
206 | "$11", "$12", "$13", "$14", "$15", "$16", "$17", "$18", "$19", "$20", |
207 | "$21", "$22", "$23", "$24", "$25", "$26", "$27", "$28", "$29", "$30", |
208 | "$31", |
209 | |
210 | "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "$f8", "$f9", |
211 | "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", "$f16", "$f17", "$f18", |
212 | "$f19", "$f20", "$f21", "$f22", "$f23", "$f24", "$f25", "$f26", "$f27", |
213 | "$f28", "$f29", "$f30", "$f31", |
214 | |
215 | "hi", "lo", "", "$fcc0", "$fcc1", "$fcc2", "$fcc3", "$fcc4", "$fcc5", |
216 | "$fcc6", "$fcc7", "$ac1hi", "$ac1lo", "$ac2hi", "$ac2lo", "$ac3hi", |
217 | "$ac3lo", |
218 | |
219 | "$w0", "$w1", "$w2", "$w3", "$w4", "$w5", "$w6", "$w7", "$w8", "$w9", |
220 | "$w10", "$w11", "$w12", "$w13", "$w14", "$w15", "$w16", "$w17", "$w18", |
221 | "$w19", "$w20", "$w21", "$w22", "$w23", "$w24", "$w25", "$w26", "$w27", |
222 | "$w28", "$w29", "$w30", "$w31", |
223 | |
224 | "$msair", "$msacsr", "$msaaccess", "$msasave", "$msamodify", |
225 | "$msarequest", "$msamap", "$msaunmap" |
226 | }; |
227 | return llvm::makeArrayRef(GCCRegNames); |
228 | } |
229 | |
230 | bool validateAsmConstraint(const char *&Name, |
231 | TargetInfo::ConstraintInfo &Info) const override { |
232 | switch (*Name) { |
233 | default: |
234 | return false; |
235 | case 'r': |
236 | case 'd': |
237 | case 'y': |
238 | case 'f': |
239 | case 'c': |
240 | case 'l': |
241 | case 'x': |
242 | Info.setAllowsRegister(); |
243 | return true; |
244 | case 'I': |
245 | case 'J': |
246 | case 'K': |
247 | case 'L': |
248 | case 'M': |
249 | case 'N': |
250 | case 'O': |
251 | case 'P': |
252 | return true; |
253 | case 'R': |
254 | Info.setAllowsMemory(); |
255 | return true; |
256 | case 'Z': |
257 | if (Name[1] == 'C') { |
258 | Info.setAllowsMemory(); |
259 | Name++; |
260 | return true; |
261 | } |
262 | return false; |
263 | } |
264 | } |
265 | |
266 | std::string convertConstraint(const char *&Constraint) const override { |
267 | std::string R; |
268 | switch (*Constraint) { |
269 | case 'Z': |
270 | if (Constraint[1] == 'C') { |
271 | R = std::string("^") + std::string(Constraint, 2); |
272 | Constraint++; |
273 | return R; |
274 | } |
275 | break; |
276 | } |
277 | return TargetInfo::convertConstraint(Constraint); |
278 | } |
279 | |
280 | const char *getClobbers() const override { |
281 | |
282 | |
283 | |
284 | |
285 | |
286 | |
287 | |
288 | |
289 | |
290 | |
291 | |
292 | |
293 | |
294 | |
295 | |
296 | |
297 | |
298 | |
299 | |
300 | |
301 | |
302 | return "~{$1}"; |
303 | } |
304 | |
305 | bool handleTargetFeatures(std::vector<std::string> &Features, |
306 | DiagnosticsEngine &Diags) override { |
307 | IsMips16 = false; |
308 | IsMicromips = false; |
309 | IsNan2008 = isIEEE754_2008Default(); |
310 | IsAbs2008 = isIEEE754_2008Default(); |
311 | IsSingleFloat = false; |
312 | FloatABI = HardFloat; |
313 | DspRev = NoDSP; |
314 | FPMode = isFP64Default() ? FP64 : FPXX; |
315 | |
316 | for (const auto &Feature : Features) { |
317 | if (Feature == "+single-float") |
318 | IsSingleFloat = true; |
319 | else if (Feature == "+soft-float") |
320 | FloatABI = SoftFloat; |
321 | else if (Feature == "+mips16") |
322 | IsMips16 = true; |
323 | else if (Feature == "+micromips") |
324 | IsMicromips = true; |
325 | else if (Feature == "+dsp") |
326 | DspRev = std::max(DspRev, DSP1); |
327 | else if (Feature == "+dspr2") |
328 | DspRev = std::max(DspRev, DSP2); |
329 | else if (Feature == "+msa") |
330 | HasMSA = true; |
331 | else if (Feature == "+nomadd4") |
332 | DisableMadd4 = true; |
333 | else if (Feature == "+fp64") |
334 | FPMode = FP64; |
335 | else if (Feature == "-fp64") |
336 | FPMode = FP32; |
337 | else if (Feature == "+fpxx") |
338 | FPMode = FPXX; |
339 | else if (Feature == "+nan2008") |
340 | IsNan2008 = true; |
341 | else if (Feature == "-nan2008") |
342 | IsNan2008 = false; |
343 | else if (Feature == "+abs2008") |
344 | IsAbs2008 = true; |
345 | else if (Feature == "-abs2008") |
346 | IsAbs2008 = false; |
347 | else if (Feature == "+noabicalls") |
348 | IsNoABICalls = true; |
349 | else if (Feature == "+use-indirect-jump-hazard") |
350 | UseIndirectJumpHazard = true; |
351 | } |
352 | |
353 | setDataLayout(); |
354 | |
355 | return true; |
356 | } |
357 | |
358 | int getEHDataRegisterNumber(unsigned RegNo) const override { |
359 | if (RegNo == 0) |
360 | return 4; |
361 | if (RegNo == 1) |
362 | return 5; |
363 | return -1; |
364 | } |
365 | |
366 | bool isCLZForZeroUndef() const override { return false; } |
367 | |
368 | ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override { |
369 | static const TargetInfo::GCCRegAlias O32RegAliases[] = { |
370 | {{"at"}, "$1"}, {{"v0"}, "$2"}, {{"v1"}, "$3"}, |
371 | {{"a0"}, "$4"}, {{"a1"}, "$5"}, {{"a2"}, "$6"}, |
372 | {{"a3"}, "$7"}, {{"t0"}, "$8"}, {{"t1"}, "$9"}, |
373 | {{"t2"}, "$10"}, {{"t3"}, "$11"}, {{"t4"}, "$12"}, |
374 | {{"t5"}, "$13"}, {{"t6"}, "$14"}, {{"t7"}, "$15"}, |
375 | {{"s0"}, "$16"}, {{"s1"}, "$17"}, {{"s2"}, "$18"}, |
376 | {{"s3"}, "$19"}, {{"s4"}, "$20"}, {{"s5"}, "$21"}, |
377 | {{"s6"}, "$22"}, {{"s7"}, "$23"}, {{"t8"}, "$24"}, |
378 | {{"t9"}, "$25"}, {{"k0"}, "$26"}, {{"k1"}, "$27"}, |
379 | {{"gp"}, "$28"}, {{"sp", "$sp"}, "$29"}, {{"fp", "$fp"}, "$30"}, |
380 | {{"ra"}, "$31"} |
381 | }; |
382 | static const TargetInfo::GCCRegAlias NewABIRegAliases[] = { |
383 | {{"at"}, "$1"}, {{"v0"}, "$2"}, {{"v1"}, "$3"}, |
384 | {{"a0"}, "$4"}, {{"a1"}, "$5"}, {{"a2"}, "$6"}, |
385 | {{"a3"}, "$7"}, {{"a4"}, "$8"}, {{"a5"}, "$9"}, |
386 | {{"a6"}, "$10"}, {{"a7"}, "$11"}, {{"t0"}, "$12"}, |
387 | {{"t1"}, "$13"}, {{"t2"}, "$14"}, {{"t3"}, "$15"}, |
388 | {{"s0"}, "$16"}, {{"s1"}, "$17"}, {{"s2"}, "$18"}, |
389 | {{"s3"}, "$19"}, {{"s4"}, "$20"}, {{"s5"}, "$21"}, |
390 | {{"s6"}, "$22"}, {{"s7"}, "$23"}, {{"t8"}, "$24"}, |
391 | {{"t9"}, "$25"}, {{"k0"}, "$26"}, {{"k1"}, "$27"}, |
392 | {{"gp"}, "$28"}, {{"sp", "$sp"}, "$29"}, {{"fp", "$fp"}, "$30"}, |
393 | {{"ra"}, "$31"} |
394 | }; |
395 | if (ABI == "o32") |
396 | return llvm::makeArrayRef(O32RegAliases); |
397 | return llvm::makeArrayRef(NewABIRegAliases); |
398 | } |
399 | |
400 | bool hasInt128Type() const override { |
401 | return (ABI == "n32" || ABI == "n64") || getTargetOpts().ForceEnableInt128; |
402 | } |
403 | |
404 | unsigned getUnwindWordWidth() const override; |
405 | |
406 | bool validateTarget(DiagnosticsEngine &Diags) const override; |
407 | }; |
408 | } |
409 | } |
410 | |
411 | #endif |
412 | |