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/Options/Options.h"
13#include "llvm/ADT/StringSwitch.h"
14#include "llvm/Option/ArgList.h"
15
16using namespace clang::driver;
17using namespace clang::driver::tools;
18using namespace clang;
19using namespace llvm::opt;
20
21// Get CPU and ABI names. They are not independent
22// so we have to calculate them together.
23void 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: options::OPT_march_EQ, Ids: options::OPT_mcpu_EQ))
53 CPUName = A->getValue();
54
55 if (Arg *A = Args.getLastArg(Ids: options::OPT_mabi_EQ)) {
56 ABIName = A->getValue();
57 // Convert a GNU style Mips ABI name to the name
58 // accepted by LLVM Mips backend.
59 ABIName = llvm::StringSwitch<llvm::StringRef>(ABIName)
60 .Case(S: "32", Value: "o32")
61 .Case(S: "64", Value: "n64")
62 .Default(Value: ABIName);
63 }
64
65 // Setup default CPU and ABI names.
66 if (CPUName.empty() && ABIName.empty()) {
67 switch (Triple.getArch()) {
68 default:
69 llvm_unreachable("Unexpected triple arch name");
70 case llvm::Triple::mips:
71 case llvm::Triple::mipsel:
72 CPUName = DefMips32CPU;
73 break;
74 case llvm::Triple::mips64:
75 case llvm::Triple::mips64el:
76 CPUName = DefMips64CPU;
77 break;
78 }
79 }
80
81 if (ABIName.empty() && Triple.isABIN32())
82 ABIName = "n32";
83
84 if (ABIName.empty() &&
85 (Triple.getVendor() == llvm::Triple::MipsTechnologies ||
86 Triple.getVendor() == llvm::Triple::ImaginationTechnologies)) {
87 ABIName = llvm::StringSwitch<const char *>(CPUName)
88 .Case(S: "mips1", Value: "o32")
89 .Case(S: "mips2", Value: "o32")
90 .Case(S: "mips3", Value: "n64")
91 .Case(S: "mips4", Value: "n64")
92 .Case(S: "mips5", Value: "n64")
93 .Case(S: "mips32", Value: "o32")
94 .Case(S: "mips32r2", Value: "o32")
95 .Case(S: "mips32r3", Value: "o32")
96 .Case(S: "mips32r5", Value: "o32")
97 .Case(S: "mips32r6", Value: "o32")
98 .Case(S: "mips64", Value: "n64")
99 .Case(S: "mips64r2", Value: "n64")
100 .Case(S: "mips64r3", Value: "n64")
101 .Case(S: "mips64r5", Value: "n64")
102 .Case(S: "mips64r6", Value: "n64")
103 .Case(S: "octeon", Value: "n64")
104 .Case(S: "p5600", Value: "o32")
105 .Case(S: "i6400", Value: "n64")
106 .Case(S: "i6500", Value: "n64")
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(CaseStrings: {"n32", "n64"}, Value: DefMips64CPU)
120 .Default(Value: "");
121 }
122
123 // FIXME: Warn on inconsistent use of -march and -mabi.
124}
125
126std::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.
137StringRef 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=.
146mips::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(Ids: options::OPT_msoft_float, Ids: options::OPT_mhard_float,
151 Ids: options::OPT_mfloat_abi_EQ)) {
152 if (A->getOption().matches(ID: options::OPT_msoft_float))
153 ABI = mips::FloatABI::Soft;
154 else if (A->getOption().matches(ID: options::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(DiagID: clang::diag::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
185void 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 // Handle features corresponding to GCC's -ffixed-REG options. MIPS spells
194 // its GPRs numerically, so preserve that spelling in the driver interface.
195#define RESERVE_GPR(REG) \
196 if (Args.hasArg(options::OPT_ffixed_##REG)) \
197 Features.push_back("+reserve-gpr" #REG);
198 RESERVE_GPR(1)
199 RESERVE_GPR(2)
200 RESERVE_GPR(3)
201 RESERVE_GPR(4)
202 RESERVE_GPR(5)
203 RESERVE_GPR(6)
204 RESERVE_GPR(7)
205 RESERVE_GPR(8)
206 RESERVE_GPR(9)
207 RESERVE_GPR(10)
208 RESERVE_GPR(11)
209 RESERVE_GPR(12)
210 RESERVE_GPR(13)
211 RESERVE_GPR(14)
212 RESERVE_GPR(15)
213 RESERVE_GPR(16)
214 RESERVE_GPR(17)
215 RESERVE_GPR(18)
216 RESERVE_GPR(19)
217 RESERVE_GPR(20)
218 RESERVE_GPR(21)
219 RESERVE_GPR(22)
220 RESERVE_GPR(23)
221 RESERVE_GPR(24)
222 RESERVE_GPR(25)
223 RESERVE_GPR(26)
224 RESERVE_GPR(27)
225 RESERVE_GPR(28)
226 RESERVE_GPR(29)
227 RESERVE_GPR(30)
228 RESERVE_GPR(31)
229#undef RESERVE_GPR
230
231 // Historically, PIC code for MIPS was associated with -mabicalls, a.k.a
232 // SVR4 abicalls. Static code does not use SVR4 calling sequences. An ABI
233 // extension was developed by Richard Sandiford & Code Sourcery to support
234 // static code calling PIC code (CPIC). For O32 and N32 this means we have
235 // several combinations of PIC/static and abicalls. Pure static, static
236 // with the CPIC extension, and pure PIC code.
237
238 // At final link time, O32 and N32 with CPIC will have another section
239 // added to the binary which contains the stub functions to perform
240 // any fixups required for PIC code.
241
242 // For N64, the situation is more regular: code can either be static
243 // (non-abicalls) or PIC (abicalls). GCC has traditionally picked PIC code
244 // code for N64. Since Clang has already built the relocation model portion
245 // of the commandline, we pick add +noabicalls feature in the N64 static
246 // case.
247
248 // The is another case to be accounted for: -msym32, which enforces that all
249 // symbols have 32 bits in size. In this case, N64 can in theory use CPIC
250 // but it is unsupported.
251
252 // The combinations for N64 are:
253 // a) Static without abicalls and 64bit symbols.
254 // b) Static with abicalls and 32bit symbols.
255 // c) PIC with abicalls and 64bit symbols.
256
257 // For case (a) we need to add +noabicalls for N64.
258
259 bool IsN64 = ABIName == "64";
260 bool IsPIC = false;
261 bool NonPIC = false;
262 bool HasNaN2008Opt = false;
263
264 Arg *LastPICArg = Args.getLastArg(Ids: options::OPT_fPIC, Ids: options::OPT_fno_PIC,
265 Ids: options::OPT_fpic, Ids: options::OPT_fno_pic,
266 Ids: options::OPT_fPIE, Ids: options::OPT_fno_PIE,
267 Ids: options::OPT_fpie, Ids: options::OPT_fno_pie);
268 if (LastPICArg) {
269 Option O = LastPICArg->getOption();
270 NonPIC =
271 (O.matches(ID: options::OPT_fno_PIC) || O.matches(ID: options::OPT_fno_pic) ||
272 O.matches(ID: options::OPT_fno_PIE) || O.matches(ID: options::OPT_fno_pie));
273 IsPIC =
274 (O.matches(ID: options::OPT_fPIC) || O.matches(ID: options::OPT_fpic) ||
275 O.matches(ID: options::OPT_fPIE) || O.matches(ID: options::OPT_fpie));
276 }
277
278 bool UseAbiCalls = false;
279
280 Arg *ABICallsArg =
281 Args.getLastArg(Ids: options::OPT_mabicalls, Ids: options::OPT_mno_abicalls);
282 UseAbiCalls =
283 !ABICallsArg || ABICallsArg->getOption().matches(ID: options::OPT_mabicalls);
284
285 if (IsN64 && NonPIC && (!ABICallsArg || UseAbiCalls)) {
286 D.Diag(DiagID: diag::warn_drv_unsupported_pic_with_mabicalls)
287 << LastPICArg->getAsString(Args) << (!ABICallsArg ? 0 : 1);
288 }
289
290 if (ABICallsArg && !UseAbiCalls && IsPIC) {
291 D.Diag(DiagID: diag::err_drv_unsupported_noabicalls_pic);
292 }
293
294 if (CPUName == "i6500" || CPUName == "i6400") {
295 // MIPS cpu i6400 and i6500 support MSA (Mips SIMD Architecture)
296 // by default.
297 Features.push_back(x: "+msa");
298 }
299
300 if (!UseAbiCalls)
301 Features.push_back(x: "+noabicalls");
302 else
303 Features.push_back(x: "-noabicalls");
304
305 if (Arg *A = Args.getLastArg(Ids: options::OPT_mlong_calls,
306 Ids: options::OPT_mno_long_calls)) {
307 if (A->getOption().matches(ID: options::OPT_mno_long_calls))
308 Features.push_back(x: "-long-calls");
309 else if (!UseAbiCalls)
310 Features.push_back(x: "+long-calls");
311 else
312 D.Diag(DiagID: diag::warn_drv_unsupported_longcalls) << (ABICallsArg ? 0 : 1);
313 }
314
315 if (Arg *A = Args.getLastArg(Ids: options::OPT_mxgot, Ids: options::OPT_mno_xgot)) {
316 if (A->getOption().matches(ID: options::OPT_mxgot))
317 Features.push_back(x: "+xgot");
318 else
319 Features.push_back(x: "-xgot");
320 }
321
322 mips::FloatABI FloatABI = mips::getMipsFloatABI(D, Args, Triple);
323 if (FloatABI == mips::FloatABI::Soft) {
324 // FIXME: Note, this is a hack. We need to pass the selected float
325 // mode to the MipsTargetInfoBase to define appropriate macros there.
326 // Now it is the only method.
327 Features.push_back(x: "+soft-float");
328 }
329
330 if (Arg *A = Args.getLastArg(Ids: options::OPT_mnan_EQ)) {
331 StringRef Val = StringRef(A->getValue());
332 if (Val == "2008") {
333 if (mips::getIEEE754Standard(CPU&: CPUName) & mips::Std2008) {
334 Features.push_back(x: "+nan2008");
335 HasNaN2008Opt = true;
336 } else {
337 Features.push_back(x: "-nan2008");
338 D.Diag(DiagID: diag::warn_target_unsupported_nan2008) << CPUName;
339 }
340 } else if (Val == "legacy") {
341 if (mips::getIEEE754Standard(CPU&: CPUName) & mips::Legacy)
342 Features.push_back(x: "-nan2008");
343 else {
344 Features.push_back(x: "+nan2008");
345 D.Diag(DiagID: diag::warn_target_unsupported_nanlegacy) << CPUName;
346 }
347 } else
348 D.Diag(DiagID: diag::err_drv_unsupported_option_argument)
349 << A->getSpelling() << Val;
350 }
351
352 if (Arg *A = Args.getLastArg(Ids: options::OPT_mabs_EQ)) {
353 StringRef Val = StringRef(A->getValue());
354 if (Val == "2008") {
355 if (mips::getIEEE754Standard(CPU&: CPUName) & mips::Std2008) {
356 Features.push_back(x: "+abs2008");
357 } else {
358 Features.push_back(x: "-abs2008");
359 D.Diag(DiagID: diag::warn_target_unsupported_abs2008) << CPUName;
360 }
361 } else if (Val == "legacy") {
362 if (mips::getIEEE754Standard(CPU&: CPUName) & mips::Legacy) {
363 Features.push_back(x: "-abs2008");
364 } else {
365 Features.push_back(x: "+abs2008");
366 D.Diag(DiagID: diag::warn_target_unsupported_abslegacy) << CPUName;
367 }
368 } else {
369 D.Diag(DiagID: diag::err_drv_unsupported_option_argument)
370 << A->getSpelling() << Val;
371 }
372 } else if (HasNaN2008Opt) {
373 Features.push_back(x: "+abs2008");
374 }
375
376 AddTargetFeature(Args, Features, OnOpt: options::OPT_msingle_float,
377 OffOpt: options::OPT_mdouble_float, FeatureName: "single-float");
378 AddTargetFeature(Args, Features, OnOpt: options::OPT_mips16, OffOpt: options::OPT_mno_mips16,
379 FeatureName: "mips16");
380 AddTargetFeature(Args, Features, OnOpt: options::OPT_mmicromips,
381 OffOpt: options::OPT_mno_micromips, FeatureName: "micromips");
382 AddTargetFeature(Args, Features, OnOpt: options::OPT_mdsp, OffOpt: options::OPT_mno_dsp,
383 FeatureName: "dsp");
384 AddTargetFeature(Args, Features, OnOpt: options::OPT_mdspr2, OffOpt: options::OPT_mno_dspr2,
385 FeatureName: "dspr2");
386 AddTargetFeature(Args, Features, OnOpt: options::OPT_mmsa, OffOpt: options::OPT_mno_msa,
387 FeatureName: "msa");
388 if (Arg *A = Args.getLastArg(
389 Ids: options::OPT_mstrict_align, Ids: options::OPT_mno_strict_align,
390 Ids: options::OPT_mno_unaligned_access, Ids: options::OPT_munaligned_access)) {
391 if (A->getOption().matches(ID: options::OPT_mstrict_align) ||
392 A->getOption().matches(ID: options::OPT_mno_unaligned_access))
393 Features.push_back(x: Args.MakeArgString(Str: "+strict-align"));
394 else
395 Features.push_back(x: Args.MakeArgString(Str: "-strict-align"));
396 }
397
398 // Add the last -mfp32/-mfpxx/-mfp64, if none are given and the ABI is O32
399 // pass -mfpxx, or if none are given and fp64a is default, pass fp64 and
400 // nooddspreg.
401 if (Arg *A = Args.getLastArg(Ids: options::OPT_mfp32, Ids: options::OPT_mfpxx,
402 Ids: options::OPT_mfp64)) {
403 if (A->getOption().matches(ID: options::OPT_mfp32))
404 Features.push_back(x: "-fp64");
405 else if (A->getOption().matches(ID: options::OPT_mfpxx)) {
406 Features.push_back(x: "+fpxx");
407 Features.push_back(x: "+nooddspreg");
408 } else
409 Features.push_back(x: "+fp64");
410 } else if (mips::shouldUseFPXX(Args, Triple, CPUName, ABIName, FloatABI)) {
411 Features.push_back(x: "+fpxx");
412 Features.push_back(x: "+nooddspreg");
413 } else if (Arg *A = Args.getLastArg(Ids: options::OPT_mmsa)) {
414 if (A->getOption().matches(ID: options::OPT_mmsa))
415 Features.push_back(x: "+fp64");
416 }
417
418 AddTargetFeature(Args, Features, OnOpt: options::OPT_mno_odd_spreg,
419 OffOpt: options::OPT_modd_spreg, FeatureName: "nooddspreg");
420 AddTargetFeature(Args, Features, OnOpt: options::OPT_mno_madd4, OffOpt: options::OPT_mmadd4,
421 FeatureName: "nomadd4");
422 AddTargetFeature(Args, Features, OnOpt: options::OPT_mmt, OffOpt: options::OPT_mno_mt, FeatureName: "mt");
423 AddTargetFeature(Args, Features, OnOpt: options::OPT_mcrc, OffOpt: options::OPT_mno_crc,
424 FeatureName: "crc");
425 AddTargetFeature(Args, Features, OnOpt: options::OPT_mvirt, OffOpt: options::OPT_mno_virt,
426 FeatureName: "virt");
427 AddTargetFeature(Args, Features, OnOpt: options::OPT_mginv, OffOpt: options::OPT_mno_ginv,
428 FeatureName: "ginv");
429 AddTargetFeature(Args, Features, OnOpt: options::OPT_mfix_r5900,
430 OffOpt: options::OPT_mno_fix_r5900, FeatureName: "fix-r5900");
431
432 if (Arg *A = Args.getLastArg(Ids: options::OPT_mindirect_jump_EQ)) {
433 StringRef Val = StringRef(A->getValue());
434 if (Val == "hazard") {
435 Arg *B =
436 Args.getLastArg(Ids: options::OPT_mmicromips, Ids: options::OPT_mno_micromips);
437 Arg *C = Args.getLastArg(Ids: options::OPT_mips16, Ids: options::OPT_mno_mips16);
438
439 if (B && B->getOption().matches(ID: options::OPT_mmicromips))
440 D.Diag(DiagID: diag::err_drv_unsupported_indirect_jump_opt)
441 << "hazard" << "micromips";
442 else if (C && C->getOption().matches(ID: options::OPT_mips16))
443 D.Diag(DiagID: diag::err_drv_unsupported_indirect_jump_opt)
444 << "hazard" << "mips16";
445 else if (mips::supportsIndirectJumpHazardBarrier(CPU&: CPUName))
446 Features.push_back(x: "+use-indirect-jump-hazard");
447 else
448 D.Diag(DiagID: diag::err_drv_unsupported_indirect_jump_opt)
449 << "hazard" << CPUName;
450 } else
451 D.Diag(DiagID: diag::err_drv_unknown_indirect_jump_opt) << Val;
452 }
453}
454
455mips::IEEE754Standard mips::getIEEE754Standard(StringRef &CPU) {
456 // Strictly speaking, mips32r2 and mips64r2 do not conform to the
457 // IEEE754-2008 standard. Support for this standard was first introduced
458 // in Release 3. However, other compilers have traditionally allowed it
459 // for Release 2 so we should do the same.
460 return (IEEE754Standard)llvm::StringSwitch<int>(CPU)
461 .Case(S: "mips1", Value: Legacy)
462 .Case(S: "mips2", Value: Legacy)
463 .Case(S: "mips3", Value: Legacy)
464 .Case(S: "mips4", Value: Legacy)
465 .Case(S: "mips5", Value: Legacy)
466 .Case(S: "mips32", Value: Legacy)
467 .Case(S: "mips32r2", Value: Legacy | Std2008)
468 .Case(S: "mips32r3", Value: Legacy | Std2008)
469 .Case(S: "mips32r5", Value: Legacy | Std2008)
470 .Case(S: "mips32r6", Value: Std2008)
471 .Case(S: "mips64", Value: Legacy)
472 .Case(S: "mips64r2", Value: Legacy | Std2008)
473 .Case(S: "mips64r3", Value: Legacy | Std2008)
474 .Case(S: "mips64r5", Value: Legacy | Std2008)
475 .Case(S: "mips64r6", Value: Std2008)
476 .Default(Value: Std2008);
477}
478
479bool mips::hasCompactBranches(StringRef &CPU) {
480 // mips32r6 and mips64r6 have compact branches.
481 return llvm::StringSwitch<bool>(CPU)
482 .Case(S: "mips32r6", Value: true)
483 .Case(S: "mips64r6", Value: true)
484 .Case(S: "i6400", Value: true)
485 .Case(S: "i6500", Value: true)
486 .Default(Value: false);
487}
488
489bool mips::hasMipsAbiArg(const ArgList &Args, const char *Value) {
490 Arg *A = Args.getLastArg(Ids: options::OPT_mabi_EQ);
491 return A && (A->getValue() == StringRef(Value));
492}
493
494bool mips::isUCLibc(const ArgList &Args) {
495 Arg *A = Args.getLastArg(Ids: options::OPT_m_libc_Group);
496 return A && A->getOption().matches(ID: options::OPT_muclibc);
497}
498
499bool mips::isNaN2008(const Driver &D, const ArgList &Args,
500 const llvm::Triple &Triple) {
501 if (Arg *NaNArg = Args.getLastArg(Ids: options::OPT_mnan_EQ))
502 return llvm::StringSwitch<bool>(NaNArg->getValue())
503 .Case(S: "2008", Value: true)
504 .Case(S: "legacy", Value: false)
505 .Default(Value: false);
506
507 // NaN2008 is the default for MIPS32r6/MIPS64r6.
508 return llvm::StringSwitch<bool>(getCPUName(D, Args, T: Triple))
509 .Cases(CaseStrings: {"mips32r6", "mips64r6"}, Value: true)
510 .Default(Value: false);
511}
512
513bool mips::isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName,
514 StringRef ABIName, mips::FloatABI FloatABI) {
515 if (ABIName != "32")
516 return false;
517
518 // FPXX shouldn't be used if either -msoft-float or -mfloat-abi=soft is
519 // present.
520 if (FloatABI == mips::FloatABI::Soft)
521 return false;
522
523 return llvm::StringSwitch<bool>(CPUName)
524 .Cases(CaseStrings: {"mips2", "mips3", "mips4", "mips5"}, Value: true)
525 .Cases(CaseStrings: {"mips32", "mips32r2", "mips32r3", "mips32r5"}, Value: true)
526 .Cases(CaseStrings: {"mips64", "mips64r2", "mips64r3", "mips64r5"}, Value: true)
527 .Default(Value: false);
528}
529
530bool mips::shouldUseFPXX(const ArgList &Args, const llvm::Triple &Triple,
531 StringRef CPUName, StringRef ABIName,
532 mips::FloatABI FloatABI) {
533 bool UseFPXX = isFPXXDefault(Triple, CPUName, ABIName, FloatABI);
534
535 // FPXX shouldn't be used if -msingle-float is present.
536 if (Arg *A = Args.getLastArg(Ids: options::OPT_msingle_float,
537 Ids: options::OPT_mdouble_float))
538 if (A->getOption().matches(ID: options::OPT_msingle_float))
539 UseFPXX = false;
540 // FP64 should be used for MSA.
541 if (Arg *A = Args.getLastArg(Ids: options::OPT_mmsa))
542 if (A->getOption().matches(ID: options::OPT_mmsa))
543 UseFPXX = llvm::StringSwitch<bool>(CPUName)
544 .Cases(CaseStrings: {"mips32r2", "mips32r3", "mips32r5"}, Value: false)
545 .Cases(CaseStrings: {"mips64r2", "mips64r3", "mips64r5"}, Value: false)
546 .Default(Value: UseFPXX);
547
548 return UseFPXX;
549}
550
551bool mips::supportsIndirectJumpHazardBarrier(StringRef &CPU) {
552 // Supporting the hazard barrier method of dealing with indirect
553 // jumps requires MIPSR2 support.
554 return llvm::StringSwitch<bool>(CPU)
555 .Case(S: "mips32r2", Value: true)
556 .Case(S: "mips32r3", Value: true)
557 .Case(S: "mips32r5", Value: true)
558 .Case(S: "mips32r6", Value: true)
559 .Case(S: "mips64r2", Value: true)
560 .Case(S: "mips64r3", Value: true)
561 .Case(S: "mips64r5", Value: true)
562 .Case(S: "mips64r6", Value: true)
563 .Case(S: "octeon", Value: true)
564 .Case(S: "p5600", Value: true)
565 .Case(S: "i6400", Value: true)
566 .Case(S: "i6500", Value: true)
567 .Default(Value: false);
568}
569