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