1 | //===--- Mips.cpp - Tools Implementations -----------------------*- 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 | #include "Mips.h" |
10 | #include "ToolChains/CommonArgs.h" |
11 | #include "clang/Driver/Driver.h" |
12 | #include "clang/Driver/DriverDiagnostic.h" |
13 | #include "clang/Driver/Options.h" |
14 | #include "llvm/ADT/StringSwitch.h" |
15 | #include "llvm/Option/ArgList.h" |
16 | |
17 | using namespace clang::driver; |
18 | using namespace clang::driver::tools; |
19 | using namespace clang; |
20 | using namespace llvm::opt; |
21 | |
22 | // Get CPU and ABI names. They are not independent |
23 | // so we have to calculate them together. |
24 | void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple, |
25 | StringRef &CPUName, StringRef &ABIName) { |
26 | const char *DefMips32CPU = "mips32r2" ; |
27 | const char *DefMips64CPU = "mips64r2" ; |
28 | |
29 | // MIPS32r6 is the default for mips(el)?-img-linux-gnu and MIPS64r6 is the |
30 | // default for mips64(el)?-img-linux-gnu. |
31 | if (Triple.getVendor() == llvm::Triple::ImaginationTechnologies && |
32 | Triple.isGNUEnvironment()) { |
33 | DefMips32CPU = "mips32r6" ; |
34 | DefMips64CPU = "mips64r6" ; |
35 | } |
36 | |
37 | if (Triple.getSubArch() == llvm::Triple::MipsSubArch_r6) { |
38 | DefMips32CPU = "mips32r6" ; |
39 | DefMips64CPU = "mips64r6" ; |
40 | } |
41 | |
42 | // MIPS3 is the default for mips64*-unknown-openbsd. |
43 | if (Triple.isOSOpenBSD()) |
44 | DefMips64CPU = "mips3" ; |
45 | |
46 | // MIPS2 is the default for mips(el)?-unknown-freebsd. |
47 | // MIPS3 is the default for mips64(el)?-unknown-freebsd. |
48 | if (Triple.isOSFreeBSD()) { |
49 | DefMips32CPU = "mips2" ; |
50 | DefMips64CPU = "mips3" ; |
51 | } |
52 | |
53 | if (Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ, |
54 | options::OPT_mcpu_EQ)) |
55 | CPUName = A->getValue(); |
56 | |
57 | if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) { |
58 | ABIName = A->getValue(); |
59 | // Convert a GNU style Mips ABI name to the name |
60 | // accepted by LLVM Mips backend. |
61 | ABIName = llvm::StringSwitch<llvm::StringRef>(ABIName) |
62 | .Case(S: "32" , Value: "o32" ) |
63 | .Case(S: "64" , Value: "n64" ) |
64 | .Default(Value: ABIName); |
65 | } |
66 | |
67 | // Setup default CPU and ABI names. |
68 | if (CPUName.empty() && ABIName.empty()) { |
69 | switch (Triple.getArch()) { |
70 | default: |
71 | llvm_unreachable("Unexpected triple arch name" ); |
72 | case llvm::Triple::mips: |
73 | case llvm::Triple::mipsel: |
74 | CPUName = DefMips32CPU; |
75 | break; |
76 | case llvm::Triple::mips64: |
77 | case llvm::Triple::mips64el: |
78 | CPUName = DefMips64CPU; |
79 | break; |
80 | } |
81 | } |
82 | |
83 | if (ABIName.empty() && (Triple.getEnvironment() == llvm::Triple::GNUABIN32)) |
84 | ABIName = "n32" ; |
85 | |
86 | if (ABIName.empty() && |
87 | (Triple.getVendor() == llvm::Triple::MipsTechnologies || |
88 | Triple.getVendor() == llvm::Triple::ImaginationTechnologies)) { |
89 | ABIName = llvm::StringSwitch<const char *>(CPUName) |
90 | .Case(S: "mips1" , Value: "o32" ) |
91 | .Case(S: "mips2" , Value: "o32" ) |
92 | .Case(S: "mips3" , Value: "n64" ) |
93 | .Case(S: "mips4" , Value: "n64" ) |
94 | .Case(S: "mips5" , Value: "n64" ) |
95 | .Case(S: "mips32" , Value: "o32" ) |
96 | .Case(S: "mips32r2" , Value: "o32" ) |
97 | .Case(S: "mips32r3" , Value: "o32" ) |
98 | .Case(S: "mips32r5" , Value: "o32" ) |
99 | .Case(S: "mips32r6" , Value: "o32" ) |
100 | .Case(S: "mips64" , Value: "n64" ) |
101 | .Case(S: "mips64r2" , Value: "n64" ) |
102 | .Case(S: "mips64r3" , Value: "n64" ) |
103 | .Case(S: "mips64r5" , Value: "n64" ) |
104 | .Case(S: "mips64r6" , Value: "n64" ) |
105 | .Case(S: "octeon" , Value: "n64" ) |
106 | .Case(S: "p5600" , Value: "o32" ) |
107 | .Default(Value: "" ); |
108 | } |
109 | |
110 | if (ABIName.empty()) { |
111 | // Deduce ABI name from the target triple. |
112 | ABIName = Triple.isMIPS32() ? "o32" : "n64" ; |
113 | } |
114 | |
115 | if (CPUName.empty()) { |
116 | // Deduce CPU name from ABI name. |
117 | CPUName = llvm::StringSwitch<const char *>(ABIName) |
118 | .Case(S: "o32" , Value: DefMips32CPU) |
119 | .Cases(S0: "n32" , S1: "n64" , Value: DefMips64CPU) |
120 | .Default(Value: "" ); |
121 | } |
122 | |
123 | // FIXME: Warn on inconsistent use of -march and -mabi. |
124 | } |
125 | |
126 | std::string mips::getMipsABILibSuffix(const ArgList &Args, |
127 | const llvm::Triple &Triple) { |
128 | StringRef CPUName, ABIName; |
129 | tools::mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName); |
130 | return llvm::StringSwitch<std::string>(ABIName) |
131 | .Case(S: "o32" , Value: "" ) |
132 | .Case(S: "n32" , Value: "32" ) |
133 | .Case(S: "n64" , Value: "64" ); |
134 | } |
135 | |
136 | // Convert ABI name to the GNU tools acceptable variant. |
137 | StringRef mips::getGnuCompatibleMipsABIName(StringRef ABI) { |
138 | return llvm::StringSwitch<llvm::StringRef>(ABI) |
139 | .Case(S: "o32" , Value: "32" ) |
140 | .Case(S: "n64" , Value: "64" ) |
141 | .Default(Value: ABI); |
142 | } |
143 | |
144 | // Select the MIPS float ABI as determined by -msoft-float, -mhard-float, |
145 | // and -mfloat-abi=. |
146 | mips::FloatABI mips::getMipsFloatABI(const Driver &D, const ArgList &Args, |
147 | const llvm::Triple &Triple) { |
148 | mips::FloatABI ABI = mips::FloatABI::Invalid; |
149 | if (Arg *A = |
150 | Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, |
151 | options::OPT_mfloat_abi_EQ)) { |
152 | if (A->getOption().matches(options::ID: OPT_msoft_float)) |
153 | ABI = mips::FloatABI::Soft; |
154 | else if (A->getOption().matches(options::ID: OPT_mhard_float)) |
155 | ABI = mips::FloatABI::Hard; |
156 | else { |
157 | ABI = llvm::StringSwitch<mips::FloatABI>(A->getValue()) |
158 | .Case(S: "soft" , Value: mips::FloatABI::Soft) |
159 | .Case(S: "hard" , Value: mips::FloatABI::Hard) |
160 | .Default(Value: mips::FloatABI::Invalid); |
161 | if (ABI == mips::FloatABI::Invalid && !StringRef(A->getValue()).empty()) { |
162 | D.Diag(clang::diag::DiagID: err_drv_invalid_mfloat_abi) << A->getAsString(Args); |
163 | ABI = mips::FloatABI::Hard; |
164 | } |
165 | } |
166 | } |
167 | |
168 | // If unspecified, choose the default based on the platform. |
169 | if (ABI == mips::FloatABI::Invalid) { |
170 | if (Triple.isOSFreeBSD()) { |
171 | // For FreeBSD, assume "soft" on all flavors of MIPS. |
172 | ABI = mips::FloatABI::Soft; |
173 | } else { |
174 | // Assume "hard", because it's a default value used by gcc. |
175 | // When we start to recognize specific target MIPS processors, |
176 | // we will be able to select the default more correctly. |
177 | ABI = mips::FloatABI::Hard; |
178 | } |
179 | } |
180 | |
181 | assert(ABI != mips::FloatABI::Invalid && "must select an ABI" ); |
182 | return ABI; |
183 | } |
184 | |
185 | void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple, |
186 | const ArgList &Args, |
187 | std::vector<StringRef> &Features) { |
188 | StringRef CPUName; |
189 | StringRef ABIName; |
190 | getMipsCPUAndABI(Args, Triple, CPUName, ABIName); |
191 | ABIName = getGnuCompatibleMipsABIName(ABI: ABIName); |
192 | |
193 | // Historically, PIC code for MIPS was associated with -mabicalls, a.k.a |
194 | // SVR4 abicalls. Static code does not use SVR4 calling sequences. An ABI |
195 | // extension was developed by Richard Sandiford & Code Sourcery to support |
196 | // static code calling PIC code (CPIC). For O32 and N32 this means we have |
197 | // several combinations of PIC/static and abicalls. Pure static, static |
198 | // with the CPIC extension, and pure PIC code. |
199 | |
200 | // At final link time, O32 and N32 with CPIC will have another section |
201 | // added to the binary which contains the stub functions to perform |
202 | // any fixups required for PIC code. |
203 | |
204 | // For N64, the situation is more regular: code can either be static |
205 | // (non-abicalls) or PIC (abicalls). GCC has traditionally picked PIC code |
206 | // code for N64. Since Clang has already built the relocation model portion |
207 | // of the commandline, we pick add +noabicalls feature in the N64 static |
208 | // case. |
209 | |
210 | // The is another case to be accounted for: -msym32, which enforces that all |
211 | // symbols have 32 bits in size. In this case, N64 can in theory use CPIC |
212 | // but it is unsupported. |
213 | |
214 | // The combinations for N64 are: |
215 | // a) Static without abicalls and 64bit symbols. |
216 | // b) Static with abicalls and 32bit symbols. |
217 | // c) PIC with abicalls and 64bit symbols. |
218 | |
219 | // For case (a) we need to add +noabicalls for N64. |
220 | |
221 | bool IsN64 = ABIName == "64" ; |
222 | bool IsPIC = false; |
223 | bool NonPIC = false; |
224 | bool HasNaN2008Opt = false; |
225 | |
226 | Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC, |
227 | options::OPT_fpic, options::OPT_fno_pic, |
228 | options::OPT_fPIE, options::OPT_fno_PIE, |
229 | options::OPT_fpie, options::OPT_fno_pie); |
230 | if (LastPICArg) { |
231 | Option O = LastPICArg->getOption(); |
232 | NonPIC = |
233 | (O.matches(options::ID: OPT_fno_PIC) || O.matches(options::ID: OPT_fno_pic) || |
234 | O.matches(options::ID: OPT_fno_PIE) || O.matches(options::ID: OPT_fno_pie)); |
235 | IsPIC = |
236 | (O.matches(options::ID: OPT_fPIC) || O.matches(options::ID: OPT_fpic) || |
237 | O.matches(options::ID: OPT_fPIE) || O.matches(options::ID: OPT_fpie)); |
238 | } |
239 | |
240 | bool UseAbiCalls = false; |
241 | |
242 | Arg *ABICallsArg = |
243 | Args.getLastArg(options::OPT_mabicalls, options::OPT_mno_abicalls); |
244 | UseAbiCalls = |
245 | !ABICallsArg || ABICallsArg->getOption().matches(options::ID: OPT_mabicalls); |
246 | |
247 | if (IsN64 && NonPIC && (!ABICallsArg || UseAbiCalls)) { |
248 | D.Diag(diag::DiagID: warn_drv_unsupported_pic_with_mabicalls) |
249 | << LastPICArg->getAsString(Args) << (!ABICallsArg ? 0 : 1); |
250 | } |
251 | |
252 | if (ABICallsArg && !UseAbiCalls && IsPIC) { |
253 | D.Diag(diag::DiagID: err_drv_unsupported_noabicalls_pic); |
254 | } |
255 | |
256 | if (!UseAbiCalls) |
257 | Features.push_back(x: "+noabicalls" ); |
258 | else |
259 | Features.push_back(x: "-noabicalls" ); |
260 | |
261 | if (Arg *A = Args.getLastArg(options::OPT_mlong_calls, |
262 | options::OPT_mno_long_calls)) { |
263 | if (A->getOption().matches(options::ID: OPT_mno_long_calls)) |
264 | Features.push_back(x: "-long-calls" ); |
265 | else if (!UseAbiCalls) |
266 | Features.push_back(x: "+long-calls" ); |
267 | else |
268 | D.Diag(diag::DiagID: warn_drv_unsupported_longcalls) << (ABICallsArg ? 0 : 1); |
269 | } |
270 | |
271 | if (Arg *A = Args.getLastArg(options::OPT_mxgot, options::OPT_mno_xgot)) { |
272 | if (A->getOption().matches(options::ID: OPT_mxgot)) |
273 | Features.push_back(x: "+xgot" ); |
274 | else |
275 | Features.push_back(x: "-xgot" ); |
276 | } |
277 | |
278 | mips::FloatABI FloatABI = mips::getMipsFloatABI(D, Args, Triple); |
279 | if (FloatABI == mips::FloatABI::Soft) { |
280 | // FIXME: Note, this is a hack. We need to pass the selected float |
281 | // mode to the MipsTargetInfoBase to define appropriate macros there. |
282 | // Now it is the only method. |
283 | Features.push_back(x: "+soft-float" ); |
284 | } |
285 | |
286 | if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) { |
287 | StringRef Val = StringRef(A->getValue()); |
288 | if (Val == "2008" ) { |
289 | if (mips::getIEEE754Standard(CPU&: CPUName) & mips::Std2008) { |
290 | Features.push_back(x: "+nan2008" ); |
291 | HasNaN2008Opt = true; |
292 | } else { |
293 | Features.push_back(x: "-nan2008" ); |
294 | D.Diag(diag::DiagID: warn_target_unsupported_nan2008) << CPUName; |
295 | } |
296 | } else if (Val == "legacy" ) { |
297 | if (mips::getIEEE754Standard(CPU&: CPUName) & mips::Legacy) |
298 | Features.push_back(x: "-nan2008" ); |
299 | else { |
300 | Features.push_back(x: "+nan2008" ); |
301 | D.Diag(diag::DiagID: warn_target_unsupported_nanlegacy) << CPUName; |
302 | } |
303 | } else |
304 | D.Diag(diag::DiagID: err_drv_unsupported_option_argument) |
305 | << A->getSpelling() << Val; |
306 | } |
307 | |
308 | if (Arg *A = Args.getLastArg(options::OPT_mabs_EQ)) { |
309 | StringRef Val = StringRef(A->getValue()); |
310 | if (Val == "2008" ) { |
311 | if (mips::getIEEE754Standard(CPU&: CPUName) & mips::Std2008) { |
312 | Features.push_back(x: "+abs2008" ); |
313 | } else { |
314 | Features.push_back(x: "-abs2008" ); |
315 | D.Diag(diag::DiagID: warn_target_unsupported_abs2008) << CPUName; |
316 | } |
317 | } else if (Val == "legacy" ) { |
318 | if (mips::getIEEE754Standard(CPU&: CPUName) & mips::Legacy) { |
319 | Features.push_back(x: "-abs2008" ); |
320 | } else { |
321 | Features.push_back(x: "+abs2008" ); |
322 | D.Diag(diag::DiagID: warn_target_unsupported_abslegacy) << CPUName; |
323 | } |
324 | } else { |
325 | D.Diag(diag::DiagID: err_drv_unsupported_option_argument) |
326 | << A->getSpelling() << Val; |
327 | } |
328 | } else if (HasNaN2008Opt) { |
329 | Features.push_back(x: "+abs2008" ); |
330 | } |
331 | |
332 | AddTargetFeature(Args, Features, options::OPT_msingle_float, |
333 | options::OPT_mdouble_float, "single-float" ); |
334 | AddTargetFeature(Args, Features, options::OPT_mips16, options::OPT_mno_mips16, |
335 | "mips16" ); |
336 | AddTargetFeature(Args, Features, options::OPT_mmicromips, |
337 | options::OPT_mno_micromips, "micromips" ); |
338 | AddTargetFeature(Args, Features, options::OPT_mdsp, options::OPT_mno_dsp, |
339 | "dsp" ); |
340 | AddTargetFeature(Args, Features, options::OPT_mdspr2, options::OPT_mno_dspr2, |
341 | "dspr2" ); |
342 | AddTargetFeature(Args, Features, options::OPT_mmsa, options::OPT_mno_msa, |
343 | "msa" ); |
344 | if (Arg *A = Args.getLastArg( |
345 | options::OPT_mstrict_align, options::OPT_mno_strict_align, |
346 | options::OPT_mno_unaligned_access, options::OPT_munaligned_access)) { |
347 | if (A->getOption().matches(options::OPT_mstrict_align) || |
348 | A->getOption().matches(options::OPT_mno_unaligned_access)) |
349 | Features.push_back(x: Args.MakeArgString(Str: "+strict-align" )); |
350 | else |
351 | Features.push_back(x: Args.MakeArgString(Str: "-strict-align" )); |
352 | } |
353 | |
354 | // Add the last -mfp32/-mfpxx/-mfp64, if none are given and the ABI is O32 |
355 | // pass -mfpxx, or if none are given and fp64a is default, pass fp64 and |
356 | // nooddspreg. |
357 | if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfpxx, |
358 | options::OPT_mfp64)) { |
359 | if (A->getOption().matches(options::OPT_mfp32)) |
360 | Features.push_back(x: "-fp64" ); |
361 | else if (A->getOption().matches(options::OPT_mfpxx)) { |
362 | Features.push_back(x: "+fpxx" ); |
363 | Features.push_back(x: "+nooddspreg" ); |
364 | } else |
365 | Features.push_back(x: "+fp64" ); |
366 | } else if (mips::shouldUseFPXX(Args, Triple, CPUName, ABIName, FloatABI)) { |
367 | Features.push_back(x: "+fpxx" ); |
368 | Features.push_back(x: "+nooddspreg" ); |
369 | } else if (mips::isFP64ADefault(Triple, CPUName)) { |
370 | Features.push_back(x: "+fp64" ); |
371 | Features.push_back(x: "+nooddspreg" ); |
372 | } |
373 | |
374 | AddTargetFeature(Args, Features, options::OPT_mno_odd_spreg, |
375 | options::OPT_modd_spreg, "nooddspreg" ); |
376 | AddTargetFeature(Args, Features, options::OPT_mno_madd4, options::OPT_mmadd4, |
377 | "nomadd4" ); |
378 | AddTargetFeature(Args, Features, options::OPT_mmt, options::OPT_mno_mt, "mt" ); |
379 | AddTargetFeature(Args, Features, options::OPT_mcrc, options::OPT_mno_crc, |
380 | "crc" ); |
381 | AddTargetFeature(Args, Features, options::OPT_mvirt, options::OPT_mno_virt, |
382 | "virt" ); |
383 | AddTargetFeature(Args, Features, options::OPT_mginv, options::OPT_mno_ginv, |
384 | "ginv" ); |
385 | |
386 | if (Arg *A = Args.getLastArg(options::OPT_mindirect_jump_EQ)) { |
387 | StringRef Val = StringRef(A->getValue()); |
388 | if (Val == "hazard" ) { |
389 | Arg *B = |
390 | Args.getLastArg(options::OPT_mmicromips, options::OPT_mno_micromips); |
391 | Arg *C = Args.getLastArg(options::OPT_mips16, options::OPT_mno_mips16); |
392 | |
393 | if (B && B->getOption().matches(options::OPT_mmicromips)) |
394 | D.Diag(diag::err_drv_unsupported_indirect_jump_opt) |
395 | << "hazard" << "micromips" ; |
396 | else if (C && C->getOption().matches(options::OPT_mips16)) |
397 | D.Diag(diag::err_drv_unsupported_indirect_jump_opt) |
398 | << "hazard" << "mips16" ; |
399 | else if (mips::supportsIndirectJumpHazardBarrier(CPU&: CPUName)) |
400 | Features.push_back(x: "+use-indirect-jump-hazard" ); |
401 | else |
402 | D.Diag(diag::err_drv_unsupported_indirect_jump_opt) |
403 | << "hazard" << CPUName; |
404 | } else |
405 | D.Diag(diag::err_drv_unknown_indirect_jump_opt) << Val; |
406 | } |
407 | } |
408 | |
409 | mips::IEEE754Standard mips::getIEEE754Standard(StringRef &CPU) { |
410 | // Strictly speaking, mips32r2 and mips64r2 do not conform to the |
411 | // IEEE754-2008 standard. Support for this standard was first introduced |
412 | // in Release 3. However, other compilers have traditionally allowed it |
413 | // for Release 2 so we should do the same. |
414 | return (IEEE754Standard)llvm::StringSwitch<int>(CPU) |
415 | .Case(S: "mips1" , Value: Legacy) |
416 | .Case(S: "mips2" , Value: Legacy) |
417 | .Case(S: "mips3" , Value: Legacy) |
418 | .Case(S: "mips4" , Value: Legacy) |
419 | .Case(S: "mips5" , Value: Legacy) |
420 | .Case(S: "mips32" , Value: Legacy) |
421 | .Case(S: "mips32r2" , Value: Legacy | Std2008) |
422 | .Case(S: "mips32r3" , Value: Legacy | Std2008) |
423 | .Case(S: "mips32r5" , Value: Legacy | Std2008) |
424 | .Case(S: "mips32r6" , Value: Std2008) |
425 | .Case(S: "mips64" , Value: Legacy) |
426 | .Case(S: "mips64r2" , Value: Legacy | Std2008) |
427 | .Case(S: "mips64r3" , Value: Legacy | Std2008) |
428 | .Case(S: "mips64r5" , Value: Legacy | Std2008) |
429 | .Case(S: "mips64r6" , Value: Std2008) |
430 | .Default(Value: Std2008); |
431 | } |
432 | |
433 | bool mips::hasCompactBranches(StringRef &CPU) { |
434 | // mips32r6 and mips64r6 have compact branches. |
435 | return llvm::StringSwitch<bool>(CPU) |
436 | .Case(S: "mips32r6" , Value: true) |
437 | .Case(S: "mips64r6" , Value: true) |
438 | .Default(Value: false); |
439 | } |
440 | |
441 | bool mips::hasMipsAbiArg(const ArgList &Args, const char *Value) { |
442 | Arg *A = Args.getLastArg(options::OPT_mabi_EQ); |
443 | return A && (A->getValue() == StringRef(Value)); |
444 | } |
445 | |
446 | bool mips::isUCLibc(const ArgList &Args) { |
447 | Arg *A = Args.getLastArg(options::OPT_m_libc_Group); |
448 | return A && A->getOption().matches(options::OPT_muclibc); |
449 | } |
450 | |
451 | bool mips::isNaN2008(const Driver &D, const ArgList &Args, |
452 | const llvm::Triple &Triple) { |
453 | if (Arg *NaNArg = Args.getLastArg(options::OPT_mnan_EQ)) |
454 | return llvm::StringSwitch<bool>(NaNArg->getValue()) |
455 | .Case(S: "2008" , Value: true) |
456 | .Case(S: "legacy" , Value: false) |
457 | .Default(Value: false); |
458 | |
459 | // NaN2008 is the default for MIPS32r6/MIPS64r6. |
460 | return llvm::StringSwitch<bool>(getCPUName(D, Args, T: Triple)) |
461 | .Cases(S0: "mips32r6" , S1: "mips64r6" , Value: true) |
462 | .Default(Value: false); |
463 | } |
464 | |
465 | bool mips::isFP64ADefault(const llvm::Triple &Triple, StringRef CPUName) { |
466 | if (!Triple.isAndroid()) |
467 | return false; |
468 | |
469 | // Android MIPS32R6 defaults to FP64A. |
470 | return llvm::StringSwitch<bool>(CPUName) |
471 | .Case(S: "mips32r6" , Value: true) |
472 | .Default(Value: false); |
473 | } |
474 | |
475 | bool mips::isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName, |
476 | StringRef ABIName, mips::FloatABI FloatABI) { |
477 | if (ABIName != "32" ) |
478 | return false; |
479 | |
480 | // FPXX shouldn't be used if either -msoft-float or -mfloat-abi=soft is |
481 | // present. |
482 | if (FloatABI == mips::FloatABI::Soft) |
483 | return false; |
484 | |
485 | return llvm::StringSwitch<bool>(CPUName) |
486 | .Cases(S0: "mips2" , S1: "mips3" , S2: "mips4" , S3: "mips5" , Value: true) |
487 | .Cases(S0: "mips32" , S1: "mips32r2" , S2: "mips32r3" , S3: "mips32r5" , Value: true) |
488 | .Cases(S0: "mips64" , S1: "mips64r2" , S2: "mips64r3" , S3: "mips64r5" , Value: true) |
489 | .Default(Value: false); |
490 | } |
491 | |
492 | bool mips::shouldUseFPXX(const ArgList &Args, const llvm::Triple &Triple, |
493 | StringRef CPUName, StringRef ABIName, |
494 | mips::FloatABI FloatABI) { |
495 | bool UseFPXX = isFPXXDefault(Triple, CPUName, ABIName, FloatABI); |
496 | |
497 | // FPXX shouldn't be used if -msingle-float is present. |
498 | if (Arg *A = Args.getLastArg(options::OPT_msingle_float, |
499 | options::OPT_mdouble_float)) |
500 | if (A->getOption().matches(options::OPT_msingle_float)) |
501 | UseFPXX = false; |
502 | |
503 | return UseFPXX; |
504 | } |
505 | |
506 | bool mips::supportsIndirectJumpHazardBarrier(StringRef &CPU) { |
507 | // Supporting the hazard barrier method of dealing with indirect |
508 | // jumps requires MIPSR2 support. |
509 | return llvm::StringSwitch<bool>(CPU) |
510 | .Case(S: "mips32r2" , Value: true) |
511 | .Case(S: "mips32r3" , Value: true) |
512 | .Case(S: "mips32r5" , Value: true) |
513 | .Case(S: "mips32r6" , Value: true) |
514 | .Case(S: "mips64r2" , Value: true) |
515 | .Case(S: "mips64r3" , Value: true) |
516 | .Case(S: "mips64r5" , Value: true) |
517 | .Case(S: "mips64r6" , Value: true) |
518 | .Case(S: "octeon" , Value: true) |
519 | .Case(S: "p5600" , Value: true) |
520 | .Default(Value: false); |
521 | } |
522 | |