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