10b57cec5SDimitry Andric //===--- Mips.cpp - Tools Implementations -----------------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
90b57cec5SDimitry Andric #include "Mips.h"
100b57cec5SDimitry Andric #include "ToolChains/CommonArgs.h"
110b57cec5SDimitry Andric #include "clang/Driver/Driver.h"
120b57cec5SDimitry Andric #include "clang/Driver/DriverDiagnostic.h"
130b57cec5SDimitry Andric #include "clang/Driver/Options.h"
140b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
150b57cec5SDimitry Andric #include "llvm/Option/ArgList.h"
160b57cec5SDimitry Andric
170b57cec5SDimitry Andric using namespace clang::driver;
180b57cec5SDimitry Andric using namespace clang::driver::tools;
190b57cec5SDimitry Andric using namespace clang;
200b57cec5SDimitry Andric using namespace llvm::opt;
210b57cec5SDimitry Andric
220b57cec5SDimitry Andric // Get CPU and ABI names. They are not independent
230b57cec5SDimitry Andric // so we have to calculate them together.
getMipsCPUAndABI(const ArgList & Args,const llvm::Triple & Triple,StringRef & CPUName,StringRef & ABIName)240b57cec5SDimitry Andric void mips::getMipsCPUAndABI(const ArgList &Args, const llvm::Triple &Triple,
250b57cec5SDimitry Andric StringRef &CPUName, StringRef &ABIName) {
260b57cec5SDimitry Andric const char *DefMips32CPU = "mips32r2";
270b57cec5SDimitry Andric const char *DefMips64CPU = "mips64r2";
280b57cec5SDimitry Andric
290b57cec5SDimitry Andric // MIPS32r6 is the default for mips(el)?-img-linux-gnu and MIPS64r6 is the
300b57cec5SDimitry Andric // default for mips64(el)?-img-linux-gnu.
310b57cec5SDimitry Andric if (Triple.getVendor() == llvm::Triple::ImaginationTechnologies &&
320b57cec5SDimitry Andric Triple.isGNUEnvironment()) {
330b57cec5SDimitry Andric DefMips32CPU = "mips32r6";
340b57cec5SDimitry Andric DefMips64CPU = "mips64r6";
350b57cec5SDimitry Andric }
360b57cec5SDimitry Andric
370b57cec5SDimitry Andric if (Triple.getSubArch() == llvm::Triple::MipsSubArch_r6) {
380b57cec5SDimitry Andric DefMips32CPU = "mips32r6";
390b57cec5SDimitry Andric DefMips64CPU = "mips64r6";
400b57cec5SDimitry Andric }
410b57cec5SDimitry Andric
420b57cec5SDimitry Andric // MIPS3 is the default for mips64*-unknown-openbsd.
430b57cec5SDimitry Andric if (Triple.isOSOpenBSD())
440b57cec5SDimitry Andric DefMips64CPU = "mips3";
450b57cec5SDimitry Andric
460b57cec5SDimitry Andric // MIPS2 is the default for mips(el)?-unknown-freebsd.
470b57cec5SDimitry Andric // MIPS3 is the default for mips64(el)?-unknown-freebsd.
480b57cec5SDimitry Andric if (Triple.isOSFreeBSD()) {
490b57cec5SDimitry Andric DefMips32CPU = "mips2";
500b57cec5SDimitry Andric DefMips64CPU = "mips3";
510b57cec5SDimitry Andric }
520b57cec5SDimitry Andric
530b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(clang::driver::options::OPT_march_EQ,
540b57cec5SDimitry Andric options::OPT_mcpu_EQ))
550b57cec5SDimitry Andric CPUName = A->getValue();
560b57cec5SDimitry Andric
570b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
580b57cec5SDimitry Andric ABIName = A->getValue();
590b57cec5SDimitry Andric // Convert a GNU style Mips ABI name to the name
600b57cec5SDimitry Andric // accepted by LLVM Mips backend.
610b57cec5SDimitry Andric ABIName = llvm::StringSwitch<llvm::StringRef>(ABIName)
620b57cec5SDimitry Andric .Case("32", "o32")
630b57cec5SDimitry Andric .Case("64", "n64")
640b57cec5SDimitry Andric .Default(ABIName);
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric
670b57cec5SDimitry Andric // Setup default CPU and ABI names.
680b57cec5SDimitry Andric if (CPUName.empty() && ABIName.empty()) {
690b57cec5SDimitry Andric switch (Triple.getArch()) {
700b57cec5SDimitry Andric default:
710b57cec5SDimitry Andric llvm_unreachable("Unexpected triple arch name");
720b57cec5SDimitry Andric case llvm::Triple::mips:
730b57cec5SDimitry Andric case llvm::Triple::mipsel:
740b57cec5SDimitry Andric CPUName = DefMips32CPU;
750b57cec5SDimitry Andric break;
760b57cec5SDimitry Andric case llvm::Triple::mips64:
770b57cec5SDimitry Andric case llvm::Triple::mips64el:
780b57cec5SDimitry Andric CPUName = DefMips64CPU;
790b57cec5SDimitry Andric break;
800b57cec5SDimitry Andric }
810b57cec5SDimitry Andric }
820b57cec5SDimitry Andric
830b57cec5SDimitry Andric if (ABIName.empty() && (Triple.getEnvironment() == llvm::Triple::GNUABIN32))
840b57cec5SDimitry Andric ABIName = "n32";
850b57cec5SDimitry Andric
860b57cec5SDimitry Andric if (ABIName.empty() &&
870b57cec5SDimitry Andric (Triple.getVendor() == llvm::Triple::MipsTechnologies ||
880b57cec5SDimitry Andric Triple.getVendor() == llvm::Triple::ImaginationTechnologies)) {
890b57cec5SDimitry Andric ABIName = llvm::StringSwitch<const char *>(CPUName)
900b57cec5SDimitry Andric .Case("mips1", "o32")
910b57cec5SDimitry Andric .Case("mips2", "o32")
920b57cec5SDimitry Andric .Case("mips3", "n64")
930b57cec5SDimitry Andric .Case("mips4", "n64")
940b57cec5SDimitry Andric .Case("mips5", "n64")
950b57cec5SDimitry Andric .Case("mips32", "o32")
960b57cec5SDimitry Andric .Case("mips32r2", "o32")
970b57cec5SDimitry Andric .Case("mips32r3", "o32")
980b57cec5SDimitry Andric .Case("mips32r5", "o32")
990b57cec5SDimitry Andric .Case("mips32r6", "o32")
1000b57cec5SDimitry Andric .Case("mips64", "n64")
1010b57cec5SDimitry Andric .Case("mips64r2", "n64")
1020b57cec5SDimitry Andric .Case("mips64r3", "n64")
1030b57cec5SDimitry Andric .Case("mips64r5", "n64")
1040b57cec5SDimitry Andric .Case("mips64r6", "n64")
1050b57cec5SDimitry Andric .Case("octeon", "n64")
1060b57cec5SDimitry Andric .Case("p5600", "o32")
1070b57cec5SDimitry Andric .Default("");
1080b57cec5SDimitry Andric }
1090b57cec5SDimitry Andric
1100b57cec5SDimitry Andric if (ABIName.empty()) {
1110b57cec5SDimitry Andric // Deduce ABI name from the target triple.
1120b57cec5SDimitry Andric ABIName = Triple.isMIPS32() ? "o32" : "n64";
1130b57cec5SDimitry Andric }
1140b57cec5SDimitry Andric
1150b57cec5SDimitry Andric if (CPUName.empty()) {
1160b57cec5SDimitry Andric // Deduce CPU name from ABI name.
1170b57cec5SDimitry Andric CPUName = llvm::StringSwitch<const char *>(ABIName)
1180b57cec5SDimitry Andric .Case("o32", DefMips32CPU)
1190b57cec5SDimitry Andric .Cases("n32", "n64", DefMips64CPU)
1200b57cec5SDimitry Andric .Default("");
1210b57cec5SDimitry Andric }
1220b57cec5SDimitry Andric
1230b57cec5SDimitry Andric // FIXME: Warn on inconsistent use of -march and -mabi.
1240b57cec5SDimitry Andric }
1250b57cec5SDimitry Andric
getMipsABILibSuffix(const ArgList & Args,const llvm::Triple & Triple)1260b57cec5SDimitry Andric std::string mips::getMipsABILibSuffix(const ArgList &Args,
1270b57cec5SDimitry Andric const llvm::Triple &Triple) {
1280b57cec5SDimitry Andric StringRef CPUName, ABIName;
1290b57cec5SDimitry Andric tools::mips::getMipsCPUAndABI(Args, Triple, CPUName, ABIName);
1300b57cec5SDimitry Andric return llvm::StringSwitch<std::string>(ABIName)
1310b57cec5SDimitry Andric .Case("o32", "")
1320b57cec5SDimitry Andric .Case("n32", "32")
1330b57cec5SDimitry Andric .Case("n64", "64");
1340b57cec5SDimitry Andric }
1350b57cec5SDimitry Andric
1360b57cec5SDimitry Andric // Convert ABI name to the GNU tools acceptable variant.
getGnuCompatibleMipsABIName(StringRef ABI)1370b57cec5SDimitry Andric StringRef mips::getGnuCompatibleMipsABIName(StringRef ABI) {
1380b57cec5SDimitry Andric return llvm::StringSwitch<llvm::StringRef>(ABI)
1390b57cec5SDimitry Andric .Case("o32", "32")
1400b57cec5SDimitry Andric .Case("n64", "64")
1410b57cec5SDimitry Andric .Default(ABI);
1420b57cec5SDimitry Andric }
1430b57cec5SDimitry Andric
1440b57cec5SDimitry Andric // Select the MIPS float ABI as determined by -msoft-float, -mhard-float,
1450b57cec5SDimitry Andric // and -mfloat-abi=.
getMipsFloatABI(const Driver & D,const ArgList & Args,const llvm::Triple & Triple)1460b57cec5SDimitry Andric mips::FloatABI mips::getMipsFloatABI(const Driver &D, const ArgList &Args,
1470b57cec5SDimitry Andric const llvm::Triple &Triple) {
1480b57cec5SDimitry Andric mips::FloatABI ABI = mips::FloatABI::Invalid;
1490b57cec5SDimitry Andric if (Arg *A =
1500b57cec5SDimitry Andric Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
1510b57cec5SDimitry Andric options::OPT_mfloat_abi_EQ)) {
1520b57cec5SDimitry Andric if (A->getOption().matches(options::OPT_msoft_float))
1530b57cec5SDimitry Andric ABI = mips::FloatABI::Soft;
1540b57cec5SDimitry Andric else if (A->getOption().matches(options::OPT_mhard_float))
1550b57cec5SDimitry Andric ABI = mips::FloatABI::Hard;
1560b57cec5SDimitry Andric else {
1570b57cec5SDimitry Andric ABI = llvm::StringSwitch<mips::FloatABI>(A->getValue())
1580b57cec5SDimitry Andric .Case("soft", mips::FloatABI::Soft)
1590b57cec5SDimitry Andric .Case("hard", mips::FloatABI::Hard)
1600b57cec5SDimitry Andric .Default(mips::FloatABI::Invalid);
1610b57cec5SDimitry Andric if (ABI == mips::FloatABI::Invalid && !StringRef(A->getValue()).empty()) {
1620b57cec5SDimitry Andric D.Diag(clang::diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
1630b57cec5SDimitry Andric ABI = mips::FloatABI::Hard;
1640b57cec5SDimitry Andric }
1650b57cec5SDimitry Andric }
1660b57cec5SDimitry Andric }
1670b57cec5SDimitry Andric
1680b57cec5SDimitry Andric // If unspecified, choose the default based on the platform.
1690b57cec5SDimitry Andric if (ABI == mips::FloatABI::Invalid) {
1700b57cec5SDimitry Andric if (Triple.isOSFreeBSD()) {
1710b57cec5SDimitry Andric // For FreeBSD, assume "soft" on all flavors of MIPS.
1720b57cec5SDimitry Andric ABI = mips::FloatABI::Soft;
1730b57cec5SDimitry Andric } else {
1740b57cec5SDimitry Andric // Assume "hard", because it's a default value used by gcc.
1750b57cec5SDimitry Andric // When we start to recognize specific target MIPS processors,
1760b57cec5SDimitry Andric // we will be able to select the default more correctly.
1770b57cec5SDimitry Andric ABI = mips::FloatABI::Hard;
1780b57cec5SDimitry Andric }
1790b57cec5SDimitry Andric }
1800b57cec5SDimitry Andric
1810b57cec5SDimitry Andric assert(ABI != mips::FloatABI::Invalid && "must select an ABI");
1820b57cec5SDimitry Andric return ABI;
1830b57cec5SDimitry Andric }
1840b57cec5SDimitry Andric
getMIPSTargetFeatures(const Driver & D,const llvm::Triple & Triple,const ArgList & Args,std::vector<StringRef> & Features)1850b57cec5SDimitry Andric void mips::getMIPSTargetFeatures(const Driver &D, const llvm::Triple &Triple,
1860b57cec5SDimitry Andric const ArgList &Args,
1870b57cec5SDimitry Andric std::vector<StringRef> &Features) {
1880b57cec5SDimitry Andric StringRef CPUName;
1890b57cec5SDimitry Andric StringRef ABIName;
1900b57cec5SDimitry Andric getMipsCPUAndABI(Args, Triple, CPUName, ABIName);
1910b57cec5SDimitry Andric ABIName = getGnuCompatibleMipsABIName(ABIName);
1920b57cec5SDimitry Andric
1930b57cec5SDimitry Andric // Historically, PIC code for MIPS was associated with -mabicalls, a.k.a
1940b57cec5SDimitry Andric // SVR4 abicalls. Static code does not use SVR4 calling sequences. An ABI
1950b57cec5SDimitry Andric // extension was developed by Richard Sandiford & Code Sourcery to support
1960b57cec5SDimitry Andric // static code calling PIC code (CPIC). For O32 and N32 this means we have
1970b57cec5SDimitry Andric // several combinations of PIC/static and abicalls. Pure static, static
1980b57cec5SDimitry Andric // with the CPIC extension, and pure PIC code.
1990b57cec5SDimitry Andric
2000b57cec5SDimitry Andric // At final link time, O32 and N32 with CPIC will have another section
2010b57cec5SDimitry Andric // added to the binary which contains the stub functions to perform
2020b57cec5SDimitry Andric // any fixups required for PIC code.
2030b57cec5SDimitry Andric
2040b57cec5SDimitry Andric // For N64, the situation is more regular: code can either be static
2050b57cec5SDimitry Andric // (non-abicalls) or PIC (abicalls). GCC has traditionally picked PIC code
2060b57cec5SDimitry Andric // code for N64. Since Clang has already built the relocation model portion
2070b57cec5SDimitry Andric // of the commandline, we pick add +noabicalls feature in the N64 static
2080b57cec5SDimitry Andric // case.
2090b57cec5SDimitry Andric
2100b57cec5SDimitry Andric // The is another case to be accounted for: -msym32, which enforces that all
2110b57cec5SDimitry Andric // symbols have 32 bits in size. In this case, N64 can in theory use CPIC
2120b57cec5SDimitry Andric // but it is unsupported.
2130b57cec5SDimitry Andric
2140b57cec5SDimitry Andric // The combinations for N64 are:
2150b57cec5SDimitry Andric // a) Static without abicalls and 64bit symbols.
2160b57cec5SDimitry Andric // b) Static with abicalls and 32bit symbols.
2170b57cec5SDimitry Andric // c) PIC with abicalls and 64bit symbols.
2180b57cec5SDimitry Andric
2190b57cec5SDimitry Andric // For case (a) we need to add +noabicalls for N64.
2200b57cec5SDimitry Andric
2210b57cec5SDimitry Andric bool IsN64 = ABIName == "64";
2220b57cec5SDimitry Andric bool IsPIC = false;
2230b57cec5SDimitry Andric bool NonPIC = false;
2241db9f3b2SDimitry Andric bool HasNaN2008Opt = false;
2250b57cec5SDimitry Andric
2260b57cec5SDimitry Andric Arg *LastPICArg = Args.getLastArg(options::OPT_fPIC, options::OPT_fno_PIC,
2270b57cec5SDimitry Andric options::OPT_fpic, options::OPT_fno_pic,
2280b57cec5SDimitry Andric options::OPT_fPIE, options::OPT_fno_PIE,
2290b57cec5SDimitry Andric options::OPT_fpie, options::OPT_fno_pie);
2300b57cec5SDimitry Andric if (LastPICArg) {
2310b57cec5SDimitry Andric Option O = LastPICArg->getOption();
2320b57cec5SDimitry Andric NonPIC =
2330b57cec5SDimitry Andric (O.matches(options::OPT_fno_PIC) || O.matches(options::OPT_fno_pic) ||
2340b57cec5SDimitry Andric O.matches(options::OPT_fno_PIE) || O.matches(options::OPT_fno_pie));
2350b57cec5SDimitry Andric IsPIC =
2360b57cec5SDimitry Andric (O.matches(options::OPT_fPIC) || O.matches(options::OPT_fpic) ||
2370b57cec5SDimitry Andric O.matches(options::OPT_fPIE) || O.matches(options::OPT_fpie));
2380b57cec5SDimitry Andric }
2390b57cec5SDimitry Andric
2400b57cec5SDimitry Andric bool UseAbiCalls = false;
2410b57cec5SDimitry Andric
2420b57cec5SDimitry Andric Arg *ABICallsArg =
2430b57cec5SDimitry Andric Args.getLastArg(options::OPT_mabicalls, options::OPT_mno_abicalls);
2440b57cec5SDimitry Andric UseAbiCalls =
2450b57cec5SDimitry Andric !ABICallsArg || ABICallsArg->getOption().matches(options::OPT_mabicalls);
2460b57cec5SDimitry Andric
2470b57cec5SDimitry Andric if (IsN64 && NonPIC && (!ABICallsArg || UseAbiCalls)) {
2480b57cec5SDimitry Andric D.Diag(diag::warn_drv_unsupported_pic_with_mabicalls)
2490b57cec5SDimitry Andric << LastPICArg->getAsString(Args) << (!ABICallsArg ? 0 : 1);
2500b57cec5SDimitry Andric }
2510b57cec5SDimitry Andric
2520b57cec5SDimitry Andric if (ABICallsArg && !UseAbiCalls && IsPIC) {
2530b57cec5SDimitry Andric D.Diag(diag::err_drv_unsupported_noabicalls_pic);
2540b57cec5SDimitry Andric }
2550b57cec5SDimitry Andric
2560b57cec5SDimitry Andric if (!UseAbiCalls)
2570b57cec5SDimitry Andric Features.push_back("+noabicalls");
2580b57cec5SDimitry Andric else
2590b57cec5SDimitry Andric Features.push_back("-noabicalls");
2600b57cec5SDimitry Andric
2610b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_mlong_calls,
2620b57cec5SDimitry Andric options::OPT_mno_long_calls)) {
2630b57cec5SDimitry Andric if (A->getOption().matches(options::OPT_mno_long_calls))
2640b57cec5SDimitry Andric Features.push_back("-long-calls");
2650b57cec5SDimitry Andric else if (!UseAbiCalls)
2660b57cec5SDimitry Andric Features.push_back("+long-calls");
2670b57cec5SDimitry Andric else
2680b57cec5SDimitry Andric D.Diag(diag::warn_drv_unsupported_longcalls) << (ABICallsArg ? 0 : 1);
2690b57cec5SDimitry Andric }
2700b57cec5SDimitry Andric
271a7dea167SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_mxgot, options::OPT_mno_xgot)) {
272a7dea167SDimitry Andric if (A->getOption().matches(options::OPT_mxgot))
273a7dea167SDimitry Andric Features.push_back("+xgot");
274a7dea167SDimitry Andric else
275a7dea167SDimitry Andric Features.push_back("-xgot");
276a7dea167SDimitry Andric }
277a7dea167SDimitry Andric
2780b57cec5SDimitry Andric mips::FloatABI FloatABI = mips::getMipsFloatABI(D, Args, Triple);
2790b57cec5SDimitry Andric if (FloatABI == mips::FloatABI::Soft) {
2800b57cec5SDimitry Andric // FIXME: Note, this is a hack. We need to pass the selected float
2810b57cec5SDimitry Andric // mode to the MipsTargetInfoBase to define appropriate macros there.
2820b57cec5SDimitry Andric // Now it is the only method.
2830b57cec5SDimitry Andric Features.push_back("+soft-float");
2840b57cec5SDimitry Andric }
2850b57cec5SDimitry Andric
2860b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_mnan_EQ)) {
2870b57cec5SDimitry Andric StringRef Val = StringRef(A->getValue());
2880b57cec5SDimitry Andric if (Val == "2008") {
2891db9f3b2SDimitry Andric if (mips::getIEEE754Standard(CPUName) & mips::Std2008) {
2900b57cec5SDimitry Andric Features.push_back("+nan2008");
2911db9f3b2SDimitry Andric HasNaN2008Opt = true;
2921db9f3b2SDimitry Andric } else {
2930b57cec5SDimitry Andric Features.push_back("-nan2008");
2940b57cec5SDimitry Andric D.Diag(diag::warn_target_unsupported_nan2008) << CPUName;
2950b57cec5SDimitry Andric }
2960b57cec5SDimitry Andric } else if (Val == "legacy") {
2970b57cec5SDimitry Andric if (mips::getIEEE754Standard(CPUName) & mips::Legacy)
2980b57cec5SDimitry Andric Features.push_back("-nan2008");
2990b57cec5SDimitry Andric else {
3000b57cec5SDimitry Andric Features.push_back("+nan2008");
3010b57cec5SDimitry Andric D.Diag(diag::warn_target_unsupported_nanlegacy) << CPUName;
3020b57cec5SDimitry Andric }
3030b57cec5SDimitry Andric } else
3040b57cec5SDimitry Andric D.Diag(diag::err_drv_unsupported_option_argument)
305bdd1243dSDimitry Andric << A->getSpelling() << Val;
3060b57cec5SDimitry Andric }
3070b57cec5SDimitry Andric
3080b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_mabs_EQ)) {
3090b57cec5SDimitry Andric StringRef Val = StringRef(A->getValue());
3100b57cec5SDimitry Andric if (Val == "2008") {
3110b57cec5SDimitry Andric if (mips::getIEEE754Standard(CPUName) & mips::Std2008) {
3120b57cec5SDimitry Andric Features.push_back("+abs2008");
3130b57cec5SDimitry Andric } else {
3140b57cec5SDimitry Andric Features.push_back("-abs2008");
3150b57cec5SDimitry Andric D.Diag(diag::warn_target_unsupported_abs2008) << CPUName;
3160b57cec5SDimitry Andric }
3170b57cec5SDimitry Andric } else if (Val == "legacy") {
3180b57cec5SDimitry Andric if (mips::getIEEE754Standard(CPUName) & mips::Legacy) {
3190b57cec5SDimitry Andric Features.push_back("-abs2008");
3200b57cec5SDimitry Andric } else {
3210b57cec5SDimitry Andric Features.push_back("+abs2008");
3220b57cec5SDimitry Andric D.Diag(diag::warn_target_unsupported_abslegacy) << CPUName;
3230b57cec5SDimitry Andric }
3240b57cec5SDimitry Andric } else {
3250b57cec5SDimitry Andric D.Diag(diag::err_drv_unsupported_option_argument)
326bdd1243dSDimitry Andric << A->getSpelling() << Val;
3270b57cec5SDimitry Andric }
3281db9f3b2SDimitry Andric } else if (HasNaN2008Opt) {
3291db9f3b2SDimitry Andric Features.push_back("+abs2008");
3300b57cec5SDimitry Andric }
3310b57cec5SDimitry Andric
3320b57cec5SDimitry Andric AddTargetFeature(Args, Features, options::OPT_msingle_float,
3330b57cec5SDimitry Andric options::OPT_mdouble_float, "single-float");
3340b57cec5SDimitry Andric AddTargetFeature(Args, Features, options::OPT_mips16, options::OPT_mno_mips16,
3350b57cec5SDimitry Andric "mips16");
3360b57cec5SDimitry Andric AddTargetFeature(Args, Features, options::OPT_mmicromips,
3370b57cec5SDimitry Andric options::OPT_mno_micromips, "micromips");
3380b57cec5SDimitry Andric AddTargetFeature(Args, Features, options::OPT_mdsp, options::OPT_mno_dsp,
3390b57cec5SDimitry Andric "dsp");
3400b57cec5SDimitry Andric AddTargetFeature(Args, Features, options::OPT_mdspr2, options::OPT_mno_dspr2,
3410b57cec5SDimitry Andric "dspr2");
3420b57cec5SDimitry Andric AddTargetFeature(Args, Features, options::OPT_mmsa, options::OPT_mno_msa,
3430b57cec5SDimitry Andric "msa");
344*0fca6ea1SDimitry Andric if (Arg *A = Args.getLastArg(
345*0fca6ea1SDimitry Andric options::OPT_mstrict_align, options::OPT_mno_strict_align,
346*0fca6ea1SDimitry Andric options::OPT_mno_unaligned_access, options::OPT_munaligned_access)) {
347*0fca6ea1SDimitry Andric if (A->getOption().matches(options::OPT_mstrict_align) ||
348*0fca6ea1SDimitry Andric A->getOption().matches(options::OPT_mno_unaligned_access))
349*0fca6ea1SDimitry Andric Features.push_back(Args.MakeArgString("+strict-align"));
350*0fca6ea1SDimitry Andric else
351*0fca6ea1SDimitry Andric Features.push_back(Args.MakeArgString("-strict-align"));
352*0fca6ea1SDimitry Andric }
3530b57cec5SDimitry Andric
3540b57cec5SDimitry Andric // Add the last -mfp32/-mfpxx/-mfp64, if none are given and the ABI is O32
3550b57cec5SDimitry Andric // pass -mfpxx, or if none are given and fp64a is default, pass fp64 and
3560b57cec5SDimitry Andric // nooddspreg.
3570b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_mfp32, options::OPT_mfpxx,
3580b57cec5SDimitry Andric options::OPT_mfp64)) {
3590b57cec5SDimitry Andric if (A->getOption().matches(options::OPT_mfp32))
3600b57cec5SDimitry Andric Features.push_back("-fp64");
3610b57cec5SDimitry Andric else if (A->getOption().matches(options::OPT_mfpxx)) {
3620b57cec5SDimitry Andric Features.push_back("+fpxx");
3630b57cec5SDimitry Andric Features.push_back("+nooddspreg");
3640b57cec5SDimitry Andric } else
3650b57cec5SDimitry Andric Features.push_back("+fp64");
3660b57cec5SDimitry Andric } else if (mips::shouldUseFPXX(Args, Triple, CPUName, ABIName, FloatABI)) {
3670b57cec5SDimitry Andric Features.push_back("+fpxx");
3680b57cec5SDimitry Andric Features.push_back("+nooddspreg");
3690b57cec5SDimitry Andric } else if (mips::isFP64ADefault(Triple, CPUName)) {
3700b57cec5SDimitry Andric Features.push_back("+fp64");
3710b57cec5SDimitry Andric Features.push_back("+nooddspreg");
372*0fca6ea1SDimitry Andric } else if (Arg *A = Args.getLastArg(options::OPT_mmsa)) {
373*0fca6ea1SDimitry Andric if (A->getOption().matches(options::OPT_mmsa))
374*0fca6ea1SDimitry Andric Features.push_back("+fp64");
3750b57cec5SDimitry Andric }
3760b57cec5SDimitry Andric
3770b57cec5SDimitry Andric AddTargetFeature(Args, Features, options::OPT_mno_odd_spreg,
3780b57cec5SDimitry Andric options::OPT_modd_spreg, "nooddspreg");
3790b57cec5SDimitry Andric AddTargetFeature(Args, Features, options::OPT_mno_madd4, options::OPT_mmadd4,
3800b57cec5SDimitry Andric "nomadd4");
3810b57cec5SDimitry Andric AddTargetFeature(Args, Features, options::OPT_mmt, options::OPT_mno_mt, "mt");
3820b57cec5SDimitry Andric AddTargetFeature(Args, Features, options::OPT_mcrc, options::OPT_mno_crc,
3830b57cec5SDimitry Andric "crc");
3840b57cec5SDimitry Andric AddTargetFeature(Args, Features, options::OPT_mvirt, options::OPT_mno_virt,
3850b57cec5SDimitry Andric "virt");
3860b57cec5SDimitry Andric AddTargetFeature(Args, Features, options::OPT_mginv, options::OPT_mno_ginv,
3870b57cec5SDimitry Andric "ginv");
3880b57cec5SDimitry Andric
3890b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_mindirect_jump_EQ)) {
3900b57cec5SDimitry Andric StringRef Val = StringRef(A->getValue());
3910b57cec5SDimitry Andric if (Val == "hazard") {
3920b57cec5SDimitry Andric Arg *B =
3930b57cec5SDimitry Andric Args.getLastArg(options::OPT_mmicromips, options::OPT_mno_micromips);
3940b57cec5SDimitry Andric Arg *C = Args.getLastArg(options::OPT_mips16, options::OPT_mno_mips16);
3950b57cec5SDimitry Andric
3960b57cec5SDimitry Andric if (B && B->getOption().matches(options::OPT_mmicromips))
3970b57cec5SDimitry Andric D.Diag(diag::err_drv_unsupported_indirect_jump_opt)
3980b57cec5SDimitry Andric << "hazard" << "micromips";
3990b57cec5SDimitry Andric else if (C && C->getOption().matches(options::OPT_mips16))
4000b57cec5SDimitry Andric D.Diag(diag::err_drv_unsupported_indirect_jump_opt)
4010b57cec5SDimitry Andric << "hazard" << "mips16";
4020b57cec5SDimitry Andric else if (mips::supportsIndirectJumpHazardBarrier(CPUName))
4030b57cec5SDimitry Andric Features.push_back("+use-indirect-jump-hazard");
4040b57cec5SDimitry Andric else
4050b57cec5SDimitry Andric D.Diag(diag::err_drv_unsupported_indirect_jump_opt)
4060b57cec5SDimitry Andric << "hazard" << CPUName;
4070b57cec5SDimitry Andric } else
4080b57cec5SDimitry Andric D.Diag(diag::err_drv_unknown_indirect_jump_opt) << Val;
4090b57cec5SDimitry Andric }
4100b57cec5SDimitry Andric }
4110b57cec5SDimitry Andric
getIEEE754Standard(StringRef & CPU)4120b57cec5SDimitry Andric mips::IEEE754Standard mips::getIEEE754Standard(StringRef &CPU) {
4130b57cec5SDimitry Andric // Strictly speaking, mips32r2 and mips64r2 do not conform to the
4140b57cec5SDimitry Andric // IEEE754-2008 standard. Support for this standard was first introduced
4150b57cec5SDimitry Andric // in Release 3. However, other compilers have traditionally allowed it
4160b57cec5SDimitry Andric // for Release 2 so we should do the same.
4170b57cec5SDimitry Andric return (IEEE754Standard)llvm::StringSwitch<int>(CPU)
4180b57cec5SDimitry Andric .Case("mips1", Legacy)
4190b57cec5SDimitry Andric .Case("mips2", Legacy)
4200b57cec5SDimitry Andric .Case("mips3", Legacy)
4210b57cec5SDimitry Andric .Case("mips4", Legacy)
4220b57cec5SDimitry Andric .Case("mips5", Legacy)
4230b57cec5SDimitry Andric .Case("mips32", Legacy)
4240b57cec5SDimitry Andric .Case("mips32r2", Legacy | Std2008)
4250b57cec5SDimitry Andric .Case("mips32r3", Legacy | Std2008)
4260b57cec5SDimitry Andric .Case("mips32r5", Legacy | Std2008)
4270b57cec5SDimitry Andric .Case("mips32r6", Std2008)
4280b57cec5SDimitry Andric .Case("mips64", Legacy)
4290b57cec5SDimitry Andric .Case("mips64r2", Legacy | Std2008)
4300b57cec5SDimitry Andric .Case("mips64r3", Legacy | Std2008)
4310b57cec5SDimitry Andric .Case("mips64r5", Legacy | Std2008)
4320b57cec5SDimitry Andric .Case("mips64r6", Std2008)
4330b57cec5SDimitry Andric .Default(Std2008);
4340b57cec5SDimitry Andric }
4350b57cec5SDimitry Andric
hasCompactBranches(StringRef & CPU)4360b57cec5SDimitry Andric bool mips::hasCompactBranches(StringRef &CPU) {
4370b57cec5SDimitry Andric // mips32r6 and mips64r6 have compact branches.
4380b57cec5SDimitry Andric return llvm::StringSwitch<bool>(CPU)
4390b57cec5SDimitry Andric .Case("mips32r6", true)
4400b57cec5SDimitry Andric .Case("mips64r6", true)
4410b57cec5SDimitry Andric .Default(false);
4420b57cec5SDimitry Andric }
4430b57cec5SDimitry Andric
hasMipsAbiArg(const ArgList & Args,const char * Value)4440b57cec5SDimitry Andric bool mips::hasMipsAbiArg(const ArgList &Args, const char *Value) {
4450b57cec5SDimitry Andric Arg *A = Args.getLastArg(options::OPT_mabi_EQ);
4460b57cec5SDimitry Andric return A && (A->getValue() == StringRef(Value));
4470b57cec5SDimitry Andric }
4480b57cec5SDimitry Andric
isUCLibc(const ArgList & Args)4490b57cec5SDimitry Andric bool mips::isUCLibc(const ArgList &Args) {
4500b57cec5SDimitry Andric Arg *A = Args.getLastArg(options::OPT_m_libc_Group);
4510b57cec5SDimitry Andric return A && A->getOption().matches(options::OPT_muclibc);
4520b57cec5SDimitry Andric }
4530b57cec5SDimitry Andric
isNaN2008(const Driver & D,const ArgList & Args,const llvm::Triple & Triple)454349cc55cSDimitry Andric bool mips::isNaN2008(const Driver &D, const ArgList &Args,
455349cc55cSDimitry Andric const llvm::Triple &Triple) {
4560b57cec5SDimitry Andric if (Arg *NaNArg = Args.getLastArg(options::OPT_mnan_EQ))
4570b57cec5SDimitry Andric return llvm::StringSwitch<bool>(NaNArg->getValue())
4580b57cec5SDimitry Andric .Case("2008", true)
4590b57cec5SDimitry Andric .Case("legacy", false)
4600b57cec5SDimitry Andric .Default(false);
4610b57cec5SDimitry Andric
4620b57cec5SDimitry Andric // NaN2008 is the default for MIPS32r6/MIPS64r6.
463349cc55cSDimitry Andric return llvm::StringSwitch<bool>(getCPUName(D, Args, Triple))
4640b57cec5SDimitry Andric .Cases("mips32r6", "mips64r6", true)
4650b57cec5SDimitry Andric .Default(false);
4660b57cec5SDimitry Andric }
4670b57cec5SDimitry Andric
isFP64ADefault(const llvm::Triple & Triple,StringRef CPUName)4680b57cec5SDimitry Andric bool mips::isFP64ADefault(const llvm::Triple &Triple, StringRef CPUName) {
4690b57cec5SDimitry Andric if (!Triple.isAndroid())
4700b57cec5SDimitry Andric return false;
4710b57cec5SDimitry Andric
4720b57cec5SDimitry Andric // Android MIPS32R6 defaults to FP64A.
4730b57cec5SDimitry Andric return llvm::StringSwitch<bool>(CPUName)
4740b57cec5SDimitry Andric .Case("mips32r6", true)
4750b57cec5SDimitry Andric .Default(false);
4760b57cec5SDimitry Andric }
4770b57cec5SDimitry Andric
isFPXXDefault(const llvm::Triple & Triple,StringRef CPUName,StringRef ABIName,mips::FloatABI FloatABI)4780b57cec5SDimitry Andric bool mips::isFPXXDefault(const llvm::Triple &Triple, StringRef CPUName,
4790b57cec5SDimitry Andric StringRef ABIName, mips::FloatABI FloatABI) {
4800b57cec5SDimitry Andric if (ABIName != "32")
4810b57cec5SDimitry Andric return false;
4820b57cec5SDimitry Andric
4830b57cec5SDimitry Andric // FPXX shouldn't be used if either -msoft-float or -mfloat-abi=soft is
4840b57cec5SDimitry Andric // present.
4850b57cec5SDimitry Andric if (FloatABI == mips::FloatABI::Soft)
4860b57cec5SDimitry Andric return false;
4870b57cec5SDimitry Andric
4880b57cec5SDimitry Andric return llvm::StringSwitch<bool>(CPUName)
4890b57cec5SDimitry Andric .Cases("mips2", "mips3", "mips4", "mips5", true)
4900b57cec5SDimitry Andric .Cases("mips32", "mips32r2", "mips32r3", "mips32r5", true)
4910b57cec5SDimitry Andric .Cases("mips64", "mips64r2", "mips64r3", "mips64r5", true)
4920b57cec5SDimitry Andric .Default(false);
4930b57cec5SDimitry Andric }
4940b57cec5SDimitry Andric
shouldUseFPXX(const ArgList & Args,const llvm::Triple & Triple,StringRef CPUName,StringRef ABIName,mips::FloatABI FloatABI)4950b57cec5SDimitry Andric bool mips::shouldUseFPXX(const ArgList &Args, const llvm::Triple &Triple,
4960b57cec5SDimitry Andric StringRef CPUName, StringRef ABIName,
4970b57cec5SDimitry Andric mips::FloatABI FloatABI) {
4980b57cec5SDimitry Andric bool UseFPXX = isFPXXDefault(Triple, CPUName, ABIName, FloatABI);
4990b57cec5SDimitry Andric
5000b57cec5SDimitry Andric // FPXX shouldn't be used if -msingle-float is present.
5010b57cec5SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_msingle_float,
5020b57cec5SDimitry Andric options::OPT_mdouble_float))
5030b57cec5SDimitry Andric if (A->getOption().matches(options::OPT_msingle_float))
5040b57cec5SDimitry Andric UseFPXX = false;
505*0fca6ea1SDimitry Andric // FP64 should be used for MSA.
506*0fca6ea1SDimitry Andric if (Arg *A = Args.getLastArg(options::OPT_mmsa))
507*0fca6ea1SDimitry Andric if (A->getOption().matches(options::OPT_mmsa))
508*0fca6ea1SDimitry Andric UseFPXX = llvm::StringSwitch<bool>(CPUName)
509*0fca6ea1SDimitry Andric .Cases("mips32r2", "mips32r3", "mips32r5", false)
510*0fca6ea1SDimitry Andric .Cases("mips64r2", "mips64r3", "mips64r5", false)
511*0fca6ea1SDimitry Andric .Default(UseFPXX);
5120b57cec5SDimitry Andric
5130b57cec5SDimitry Andric return UseFPXX;
5140b57cec5SDimitry Andric }
5150b57cec5SDimitry Andric
supportsIndirectJumpHazardBarrier(StringRef & CPU)5160b57cec5SDimitry Andric bool mips::supportsIndirectJumpHazardBarrier(StringRef &CPU) {
5170b57cec5SDimitry Andric // Supporting the hazard barrier method of dealing with indirect
5180b57cec5SDimitry Andric // jumps requires MIPSR2 support.
5190b57cec5SDimitry Andric return llvm::StringSwitch<bool>(CPU)
5200b57cec5SDimitry Andric .Case("mips32r2", true)
5210b57cec5SDimitry Andric .Case("mips32r3", true)
5220b57cec5SDimitry Andric .Case("mips32r5", true)
5230b57cec5SDimitry Andric .Case("mips32r6", true)
5240b57cec5SDimitry Andric .Case("mips64r2", true)
5250b57cec5SDimitry Andric .Case("mips64r3", true)
5260b57cec5SDimitry Andric .Case("mips64r5", true)
5270b57cec5SDimitry Andric .Case("mips64r6", true)
5280b57cec5SDimitry Andric .Case("octeon", true)
5290b57cec5SDimitry Andric .Case("p5600", true)
5300b57cec5SDimitry Andric .Default(false);
5310b57cec5SDimitry Andric }
532