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