10b57cec5SDimitry Andric //===--- Mips.h - Declare Mips target feature support -----------*- 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 // This file declares Mips TargetInfo objects. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_MIPS_H 140b57cec5SDimitry Andric #define LLVM_CLANG_LIB_BASIC_TARGETS_MIPS_H 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h" 170b57cec5SDimitry Andric #include "clang/Basic/TargetOptions.h" 180b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 1906c3fb27SDimitry Andric #include "llvm/TargetParser/Triple.h" 200b57cec5SDimitry Andric 210b57cec5SDimitry Andric namespace clang { 220b57cec5SDimitry Andric namespace targets { 230b57cec5SDimitry Andric 240b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo { 250b57cec5SDimitry Andric void setDataLayout() { 260b57cec5SDimitry Andric StringRef Layout; 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric if (ABI == "o32") 290b57cec5SDimitry Andric Layout = "m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64"; 300b57cec5SDimitry Andric else if (ABI == "n32") 310b57cec5SDimitry Andric Layout = "m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32:64-S128"; 320b57cec5SDimitry Andric else if (ABI == "n64") 330b57cec5SDimitry Andric Layout = "m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128"; 340b57cec5SDimitry Andric else 350b57cec5SDimitry Andric llvm_unreachable("Invalid ABI"); 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric if (BigEndian) 380b57cec5SDimitry Andric resetDataLayout(("E-" + Layout).str()); 390b57cec5SDimitry Andric else 400b57cec5SDimitry Andric resetDataLayout(("e-" + Layout).str()); 410b57cec5SDimitry Andric } 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric std::string CPU; 440b57cec5SDimitry Andric bool IsMips16; 450b57cec5SDimitry Andric bool IsMicromips; 460b57cec5SDimitry Andric bool IsNan2008; 470b57cec5SDimitry Andric bool IsAbs2008; 480b57cec5SDimitry Andric bool IsSingleFloat; 490b57cec5SDimitry Andric bool IsNoABICalls; 500b57cec5SDimitry Andric bool CanUseBSDABICalls; 510b57cec5SDimitry Andric enum MipsFloatABI { HardFloat, SoftFloat } FloatABI; 520b57cec5SDimitry Andric enum DspRevEnum { NoDSP, DSP1, DSP2 } DspRev; 530b57cec5SDimitry Andric bool HasMSA; 540b57cec5SDimitry Andric bool DisableMadd4; 550b57cec5SDimitry Andric bool UseIndirectJumpHazard; 565f757f3fSDimitry Andric bool NoOddSpreg; 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric protected: 590b57cec5SDimitry Andric enum FPModeEnum { FPXX, FP32, FP64 } FPMode; 600b57cec5SDimitry Andric std::string ABI; 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric public: 630b57cec5SDimitry Andric MipsTargetInfo(const llvm::Triple &Triple, const TargetOptions &) 640b57cec5SDimitry Andric : TargetInfo(Triple), IsMips16(false), IsMicromips(false), 650b57cec5SDimitry Andric IsNan2008(false), IsAbs2008(false), IsSingleFloat(false), 660b57cec5SDimitry Andric IsNoABICalls(false), CanUseBSDABICalls(false), FloatABI(HardFloat), 670b57cec5SDimitry Andric DspRev(NoDSP), HasMSA(false), DisableMadd4(false), 680b57cec5SDimitry Andric UseIndirectJumpHazard(false), FPMode(FPXX) { 690b57cec5SDimitry Andric TheCXXABI.set(TargetCXXABI::GenericMIPS); 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric if (Triple.isMIPS32()) 720b57cec5SDimitry Andric setABI("o32"); 730b57cec5SDimitry Andric else if (Triple.getEnvironment() == llvm::Triple::GNUABIN32) 740b57cec5SDimitry Andric setABI("n32"); 750b57cec5SDimitry Andric else 760b57cec5SDimitry Andric setABI("n64"); 770b57cec5SDimitry Andric 780b57cec5SDimitry Andric CPU = ABI == "o32" ? "mips32r2" : "mips64r2"; 790b57cec5SDimitry Andric 800b57cec5SDimitry Andric CanUseBSDABICalls = Triple.isOSFreeBSD() || 810b57cec5SDimitry Andric Triple.isOSOpenBSD(); 820b57cec5SDimitry Andric } 830b57cec5SDimitry Andric 840b57cec5SDimitry Andric bool isIEEE754_2008Default() const { 850b57cec5SDimitry Andric return CPU == "mips32r6" || CPU == "mips64r6"; 860b57cec5SDimitry Andric } 870b57cec5SDimitry Andric 88*0fca6ea1SDimitry Andric enum FPModeEnum getDefaultFPMode() const { 89*0fca6ea1SDimitry Andric if (CPU == "mips32r6" || ABI == "n32" || ABI == "n64" || ABI == "64") 90*0fca6ea1SDimitry Andric return FP64; 91*0fca6ea1SDimitry Andric else if (CPU == "mips1") 92*0fca6ea1SDimitry Andric return FP32; 93*0fca6ea1SDimitry Andric else 94*0fca6ea1SDimitry Andric return FPXX; 950b57cec5SDimitry Andric } 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric bool isNan2008() const override { return IsNan2008; } 980b57cec5SDimitry Andric 990b57cec5SDimitry Andric bool processorSupportsGPR64() const; 1000b57cec5SDimitry Andric 1010b57cec5SDimitry Andric StringRef getABI() const override { return ABI; } 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric bool setABI(const std::string &Name) override { 1040b57cec5SDimitry Andric if (Name == "o32") { 1050b57cec5SDimitry Andric setO32ABITypes(); 1060b57cec5SDimitry Andric ABI = Name; 1070b57cec5SDimitry Andric return true; 1080b57cec5SDimitry Andric } 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric if (Name == "n32") { 1110b57cec5SDimitry Andric setN32ABITypes(); 1120b57cec5SDimitry Andric ABI = Name; 1130b57cec5SDimitry Andric return true; 1140b57cec5SDimitry Andric } 1150b57cec5SDimitry Andric if (Name == "n64") { 1160b57cec5SDimitry Andric setN64ABITypes(); 1170b57cec5SDimitry Andric ABI = Name; 1180b57cec5SDimitry Andric return true; 1190b57cec5SDimitry Andric } 1200b57cec5SDimitry Andric return false; 1210b57cec5SDimitry Andric } 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric void setO32ABITypes() { 1240b57cec5SDimitry Andric Int64Type = SignedLongLong; 1250b57cec5SDimitry Andric IntMaxType = Int64Type; 1260b57cec5SDimitry Andric LongDoubleFormat = &llvm::APFloat::IEEEdouble(); 1270b57cec5SDimitry Andric LongDoubleWidth = LongDoubleAlign = 64; 1280b57cec5SDimitry Andric LongWidth = LongAlign = 32; 1290b57cec5SDimitry Andric MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32; 1300b57cec5SDimitry Andric PointerWidth = PointerAlign = 32; 1310b57cec5SDimitry Andric PtrDiffType = SignedInt; 1320b57cec5SDimitry Andric SizeType = UnsignedInt; 1330b57cec5SDimitry Andric SuitableAlign = 64; 1340b57cec5SDimitry Andric } 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric void setN32N64ABITypes() { 1370b57cec5SDimitry Andric LongDoubleWidth = LongDoubleAlign = 128; 1380b57cec5SDimitry Andric LongDoubleFormat = &llvm::APFloat::IEEEquad(); 1390b57cec5SDimitry Andric if (getTriple().isOSFreeBSD()) { 1400b57cec5SDimitry Andric LongDoubleWidth = LongDoubleAlign = 64; 1410b57cec5SDimitry Andric LongDoubleFormat = &llvm::APFloat::IEEEdouble(); 1420b57cec5SDimitry Andric } 1430b57cec5SDimitry Andric MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; 1440b57cec5SDimitry Andric SuitableAlign = 128; 1450b57cec5SDimitry Andric } 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric void setN64ABITypes() { 1480b57cec5SDimitry Andric setN32N64ABITypes(); 1490b57cec5SDimitry Andric if (getTriple().isOSOpenBSD()) { 1500b57cec5SDimitry Andric Int64Type = SignedLongLong; 1510b57cec5SDimitry Andric } else { 1520b57cec5SDimitry Andric Int64Type = SignedLong; 1530b57cec5SDimitry Andric } 1540b57cec5SDimitry Andric IntMaxType = Int64Type; 1550b57cec5SDimitry Andric LongWidth = LongAlign = 64; 1560b57cec5SDimitry Andric PointerWidth = PointerAlign = 64; 1570b57cec5SDimitry Andric PtrDiffType = SignedLong; 1580b57cec5SDimitry Andric SizeType = UnsignedLong; 1590b57cec5SDimitry Andric } 1600b57cec5SDimitry Andric 1610b57cec5SDimitry Andric void setN32ABITypes() { 1620b57cec5SDimitry Andric setN32N64ABITypes(); 1630b57cec5SDimitry Andric Int64Type = SignedLongLong; 1640b57cec5SDimitry Andric IntMaxType = Int64Type; 1650b57cec5SDimitry Andric LongWidth = LongAlign = 32; 1660b57cec5SDimitry Andric PointerWidth = PointerAlign = 32; 1670b57cec5SDimitry Andric PtrDiffType = SignedInt; 1680b57cec5SDimitry Andric SizeType = UnsignedInt; 1690b57cec5SDimitry Andric } 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric bool isValidCPUName(StringRef Name) const override; 1720b57cec5SDimitry Andric void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; 1730b57cec5SDimitry Andric 1740b57cec5SDimitry Andric bool setCPU(const std::string &Name) override { 1750b57cec5SDimitry Andric CPU = Name; 1760b57cec5SDimitry Andric return isValidCPUName(Name); 1770b57cec5SDimitry Andric } 1780b57cec5SDimitry Andric 1790b57cec5SDimitry Andric const std::string &getCPU() const { return CPU; } 1800b57cec5SDimitry Andric bool 1810b57cec5SDimitry Andric initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, 1820b57cec5SDimitry Andric StringRef CPU, 1830b57cec5SDimitry Andric const std::vector<std::string> &FeaturesVec) const override { 1840b57cec5SDimitry Andric if (CPU.empty()) 1850b57cec5SDimitry Andric CPU = getCPU(); 1860b57cec5SDimitry Andric if (CPU == "octeon") 1870b57cec5SDimitry Andric Features["mips64r2"] = Features["cnmips"] = true; 1880b57cec5SDimitry Andric else if (CPU == "octeon+") 1890b57cec5SDimitry Andric Features["mips64r2"] = Features["cnmips"] = Features["cnmipsp"] = true; 1900b57cec5SDimitry Andric else 1910b57cec5SDimitry Andric Features[CPU] = true; 1920b57cec5SDimitry Andric return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec); 1930b57cec5SDimitry Andric } 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric unsigned getISARev() const; 1960b57cec5SDimitry Andric 1970b57cec5SDimitry Andric void getTargetDefines(const LangOptions &Opts, 1980b57cec5SDimitry Andric MacroBuilder &Builder) const override; 1990b57cec5SDimitry Andric 2000b57cec5SDimitry Andric ArrayRef<Builtin::Info> getTargetBuiltins() const override; 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric bool hasFeature(StringRef Feature) const override; 2030b57cec5SDimitry Andric 2040b57cec5SDimitry Andric BuiltinVaListKind getBuiltinVaListKind() const override { 2050b57cec5SDimitry Andric return TargetInfo::VoidPtrBuiltinVaList; 2060b57cec5SDimitry Andric } 2070b57cec5SDimitry Andric 2080b57cec5SDimitry Andric ArrayRef<const char *> getGCCRegNames() const override { 2090b57cec5SDimitry Andric static const char *const GCCRegNames[] = { 2100b57cec5SDimitry Andric // CPU register names 2110b57cec5SDimitry Andric // Must match second column of GCCRegAliases 2120b57cec5SDimitry Andric "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", 2130b57cec5SDimitry Andric "$11", "$12", "$13", "$14", "$15", "$16", "$17", "$18", "$19", "$20", 2140b57cec5SDimitry Andric "$21", "$22", "$23", "$24", "$25", "$26", "$27", "$28", "$29", "$30", 2150b57cec5SDimitry Andric "$31", 2160b57cec5SDimitry Andric // Floating point register names 2170b57cec5SDimitry Andric "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "$f8", "$f9", 2180b57cec5SDimitry Andric "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", "$f16", "$f17", "$f18", 2190b57cec5SDimitry Andric "$f19", "$f20", "$f21", "$f22", "$f23", "$f24", "$f25", "$f26", "$f27", 2200b57cec5SDimitry Andric "$f28", "$f29", "$f30", "$f31", 2210b57cec5SDimitry Andric // Hi/lo and condition register names 2220b57cec5SDimitry Andric "hi", "lo", "", "$fcc0", "$fcc1", "$fcc2", "$fcc3", "$fcc4", "$fcc5", 2230b57cec5SDimitry Andric "$fcc6", "$fcc7", "$ac1hi", "$ac1lo", "$ac2hi", "$ac2lo", "$ac3hi", 2240b57cec5SDimitry Andric "$ac3lo", 2250b57cec5SDimitry Andric // MSA register names 2260b57cec5SDimitry Andric "$w0", "$w1", "$w2", "$w3", "$w4", "$w5", "$w6", "$w7", "$w8", "$w9", 2270b57cec5SDimitry Andric "$w10", "$w11", "$w12", "$w13", "$w14", "$w15", "$w16", "$w17", "$w18", 2280b57cec5SDimitry Andric "$w19", "$w20", "$w21", "$w22", "$w23", "$w24", "$w25", "$w26", "$w27", 2290b57cec5SDimitry Andric "$w28", "$w29", "$w30", "$w31", 2300b57cec5SDimitry Andric // MSA control register names 2310b57cec5SDimitry Andric "$msair", "$msacsr", "$msaaccess", "$msasave", "$msamodify", 2320b57cec5SDimitry Andric "$msarequest", "$msamap", "$msaunmap" 2330b57cec5SDimitry Andric }; 234bdd1243dSDimitry Andric return llvm::ArrayRef(GCCRegNames); 2350b57cec5SDimitry Andric } 2360b57cec5SDimitry Andric 2370b57cec5SDimitry Andric bool validateAsmConstraint(const char *&Name, 2380b57cec5SDimitry Andric TargetInfo::ConstraintInfo &Info) const override { 2390b57cec5SDimitry Andric switch (*Name) { 2400b57cec5SDimitry Andric default: 2410b57cec5SDimitry Andric return false; 2420b57cec5SDimitry Andric case 'r': // CPU registers. 2430b57cec5SDimitry Andric case 'd': // Equivalent to "r" unless generating MIPS16 code. 2440b57cec5SDimitry Andric case 'y': // Equivalent to "r", backward compatibility only. 2450b57cec5SDimitry Andric case 'c': // $25 for indirect jumps 2460b57cec5SDimitry Andric case 'l': // lo register 2470b57cec5SDimitry Andric case 'x': // hilo register pair 2480b57cec5SDimitry Andric Info.setAllowsRegister(); 2490b57cec5SDimitry Andric return true; 2504c2d3b02SDimitry Andric case 'f': // floating-point registers. 2514c2d3b02SDimitry Andric Info.setAllowsRegister(); 2524c2d3b02SDimitry Andric return FloatABI != SoftFloat; 2530b57cec5SDimitry Andric case 'I': // Signed 16-bit constant 2540b57cec5SDimitry Andric case 'J': // Integer 0 2550b57cec5SDimitry Andric case 'K': // Unsigned 16-bit constant 2560b57cec5SDimitry Andric case 'L': // Signed 32-bit constant, lower 16-bit zeros (for lui) 2570b57cec5SDimitry Andric case 'M': // Constants not loadable via lui, addiu, or ori 2580b57cec5SDimitry Andric case 'N': // Constant -1 to -65535 2590b57cec5SDimitry Andric case 'O': // A signed 15-bit constant 2600b57cec5SDimitry Andric case 'P': // A constant between 1 go 65535 2610b57cec5SDimitry Andric return true; 2620b57cec5SDimitry Andric case 'R': // An address that can be used in a non-macro load or store 2630b57cec5SDimitry Andric Info.setAllowsMemory(); 2640b57cec5SDimitry Andric return true; 2650b57cec5SDimitry Andric case 'Z': 2660b57cec5SDimitry Andric if (Name[1] == 'C') { // An address usable by ll, and sc. 2670b57cec5SDimitry Andric Info.setAllowsMemory(); 2680b57cec5SDimitry Andric Name++; // Skip over 'Z'. 2690b57cec5SDimitry Andric return true; 2700b57cec5SDimitry Andric } 2710b57cec5SDimitry Andric return false; 2720b57cec5SDimitry Andric } 2730b57cec5SDimitry Andric } 2740b57cec5SDimitry Andric 2750b57cec5SDimitry Andric std::string convertConstraint(const char *&Constraint) const override { 2760b57cec5SDimitry Andric std::string R; 2770b57cec5SDimitry Andric switch (*Constraint) { 2780b57cec5SDimitry Andric case 'Z': // Two-character constraint; add "^" hint for later parsing. 2790b57cec5SDimitry Andric if (Constraint[1] == 'C') { 2800b57cec5SDimitry Andric R = std::string("^") + std::string(Constraint, 2); 2810b57cec5SDimitry Andric Constraint++; 2820b57cec5SDimitry Andric return R; 2830b57cec5SDimitry Andric } 2840b57cec5SDimitry Andric break; 2850b57cec5SDimitry Andric } 2860b57cec5SDimitry Andric return TargetInfo::convertConstraint(Constraint); 2870b57cec5SDimitry Andric } 2880b57cec5SDimitry Andric 28906c3fb27SDimitry Andric std::string_view getClobbers() const override { 2900b57cec5SDimitry Andric // In GCC, $1 is not widely used in generated code (it's used only in a few 2910b57cec5SDimitry Andric // specific situations), so there is no real need for users to add it to 2920b57cec5SDimitry Andric // the clobbers list if they want to use it in their inline assembly code. 2930b57cec5SDimitry Andric // 2940b57cec5SDimitry Andric // In LLVM, $1 is treated as a normal GPR and is always allocatable during 2950b57cec5SDimitry Andric // code generation, so using it in inline assembly without adding it to the 2960b57cec5SDimitry Andric // clobbers list can cause conflicts between the inline assembly code and 2970b57cec5SDimitry Andric // the surrounding generated code. 2980b57cec5SDimitry Andric // 2990b57cec5SDimitry Andric // Another problem is that LLVM is allowed to choose $1 for inline assembly 3000b57cec5SDimitry Andric // operands, which will conflict with the ".set at" assembler option (which 3010b57cec5SDimitry Andric // we use only for inline assembly, in order to maintain compatibility with 3020b57cec5SDimitry Andric // GCC) and will also conflict with the user's usage of $1. 3030b57cec5SDimitry Andric // 3040b57cec5SDimitry Andric // The easiest way to avoid these conflicts and keep $1 as an allocatable 3050b57cec5SDimitry Andric // register for generated code is to automatically clobber $1 for all inline 3060b57cec5SDimitry Andric // assembly code. 3070b57cec5SDimitry Andric // 3080b57cec5SDimitry Andric // FIXME: We should automatically clobber $1 only for inline assembly code 3090b57cec5SDimitry Andric // which actually uses it. This would allow LLVM to use $1 for inline 3100b57cec5SDimitry Andric // assembly operands if the user's assembly code doesn't use it. 3110b57cec5SDimitry Andric return "~{$1}"; 3120b57cec5SDimitry Andric } 3130b57cec5SDimitry Andric 3140b57cec5SDimitry Andric bool handleTargetFeatures(std::vector<std::string> &Features, 3150b57cec5SDimitry Andric DiagnosticsEngine &Diags) override { 3160b57cec5SDimitry Andric IsMips16 = false; 3170b57cec5SDimitry Andric IsMicromips = false; 3180b57cec5SDimitry Andric IsNan2008 = isIEEE754_2008Default(); 3190b57cec5SDimitry Andric IsAbs2008 = isIEEE754_2008Default(); 3200b57cec5SDimitry Andric IsSingleFloat = false; 3210b57cec5SDimitry Andric FloatABI = HardFloat; 3220b57cec5SDimitry Andric DspRev = NoDSP; 3235f757f3fSDimitry Andric NoOddSpreg = false; 324*0fca6ea1SDimitry Andric FPMode = getDefaultFPMode(); 3255f757f3fSDimitry Andric bool OddSpregGiven = false; 326*0fca6ea1SDimitry Andric bool StrictAlign = false; 327*0fca6ea1SDimitry Andric bool FpGiven = false; 3280b57cec5SDimitry Andric 3290b57cec5SDimitry Andric for (const auto &Feature : Features) { 3300b57cec5SDimitry Andric if (Feature == "+single-float") 3310b57cec5SDimitry Andric IsSingleFloat = true; 3320b57cec5SDimitry Andric else if (Feature == "+soft-float") 3330b57cec5SDimitry Andric FloatABI = SoftFloat; 3340b57cec5SDimitry Andric else if (Feature == "+mips16") 3350b57cec5SDimitry Andric IsMips16 = true; 3360b57cec5SDimitry Andric else if (Feature == "+micromips") 3370b57cec5SDimitry Andric IsMicromips = true; 338*0fca6ea1SDimitry Andric else if (Feature == "+mips32r6" || Feature == "+mips64r6") 339*0fca6ea1SDimitry Andric HasUnalignedAccess = true; 340*0fca6ea1SDimitry Andric // We cannot be sure that the order of strict-align vs mips32r6. 341*0fca6ea1SDimitry Andric // Thus we need an extra variable here. 342*0fca6ea1SDimitry Andric else if (Feature == "+strict-align") 343*0fca6ea1SDimitry Andric StrictAlign = true; 3440b57cec5SDimitry Andric else if (Feature == "+dsp") 3450b57cec5SDimitry Andric DspRev = std::max(DspRev, DSP1); 3460b57cec5SDimitry Andric else if (Feature == "+dspr2") 3470b57cec5SDimitry Andric DspRev = std::max(DspRev, DSP2); 3480b57cec5SDimitry Andric else if (Feature == "+msa") 3490b57cec5SDimitry Andric HasMSA = true; 3500b57cec5SDimitry Andric else if (Feature == "+nomadd4") 3510b57cec5SDimitry Andric DisableMadd4 = true; 352*0fca6ea1SDimitry Andric else if (Feature == "+fp64") { 3530b57cec5SDimitry Andric FPMode = FP64; 354*0fca6ea1SDimitry Andric FpGiven = true; 355*0fca6ea1SDimitry Andric } else if (Feature == "-fp64") { 3560b57cec5SDimitry Andric FPMode = FP32; 357*0fca6ea1SDimitry Andric FpGiven = true; 358*0fca6ea1SDimitry Andric } else if (Feature == "+fpxx") { 3590b57cec5SDimitry Andric FPMode = FPXX; 360*0fca6ea1SDimitry Andric FpGiven = true; 361*0fca6ea1SDimitry Andric } else if (Feature == "+nan2008") 3620b57cec5SDimitry Andric IsNan2008 = true; 3630b57cec5SDimitry Andric else if (Feature == "-nan2008") 3640b57cec5SDimitry Andric IsNan2008 = false; 3650b57cec5SDimitry Andric else if (Feature == "+abs2008") 3660b57cec5SDimitry Andric IsAbs2008 = true; 3670b57cec5SDimitry Andric else if (Feature == "-abs2008") 3680b57cec5SDimitry Andric IsAbs2008 = false; 3690b57cec5SDimitry Andric else if (Feature == "+noabicalls") 3700b57cec5SDimitry Andric IsNoABICalls = true; 3710b57cec5SDimitry Andric else if (Feature == "+use-indirect-jump-hazard") 3720b57cec5SDimitry Andric UseIndirectJumpHazard = true; 3735f757f3fSDimitry Andric else if (Feature == "+nooddspreg") { 3745f757f3fSDimitry Andric NoOddSpreg = true; 3755f757f3fSDimitry Andric OddSpregGiven = false; 3765f757f3fSDimitry Andric } else if (Feature == "-nooddspreg") { 3775f757f3fSDimitry Andric NoOddSpreg = false; 3785f757f3fSDimitry Andric OddSpregGiven = true; 3790b57cec5SDimitry Andric } 3805f757f3fSDimitry Andric } 3815f757f3fSDimitry Andric 3825f757f3fSDimitry Andric if (FPMode == FPXX && !OddSpregGiven) 3835f757f3fSDimitry Andric NoOddSpreg = true; 3840b57cec5SDimitry Andric 385*0fca6ea1SDimitry Andric if (StrictAlign) 386*0fca6ea1SDimitry Andric HasUnalignedAccess = false; 387*0fca6ea1SDimitry Andric 388*0fca6ea1SDimitry Andric if (HasMSA && !FpGiven) { 389*0fca6ea1SDimitry Andric FPMode = FP64; 390*0fca6ea1SDimitry Andric Features.push_back("+fp64"); 391*0fca6ea1SDimitry Andric } 392*0fca6ea1SDimitry Andric 3930b57cec5SDimitry Andric setDataLayout(); 3940b57cec5SDimitry Andric 3950b57cec5SDimitry Andric return true; 3960b57cec5SDimitry Andric } 3970b57cec5SDimitry Andric 3980b57cec5SDimitry Andric int getEHDataRegisterNumber(unsigned RegNo) const override { 3990b57cec5SDimitry Andric if (RegNo == 0) 4000b57cec5SDimitry Andric return 4; 4010b57cec5SDimitry Andric if (RegNo == 1) 4020b57cec5SDimitry Andric return 5; 4030b57cec5SDimitry Andric return -1; 4040b57cec5SDimitry Andric } 4050b57cec5SDimitry Andric 4060b57cec5SDimitry Andric bool isCLZForZeroUndef() const override { return false; } 4070b57cec5SDimitry Andric 4080b57cec5SDimitry Andric ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override { 4090b57cec5SDimitry Andric static const TargetInfo::GCCRegAlias O32RegAliases[] = { 4100b57cec5SDimitry Andric {{"at"}, "$1"}, {{"v0"}, "$2"}, {{"v1"}, "$3"}, 4110b57cec5SDimitry Andric {{"a0"}, "$4"}, {{"a1"}, "$5"}, {{"a2"}, "$6"}, 4120b57cec5SDimitry Andric {{"a3"}, "$7"}, {{"t0"}, "$8"}, {{"t1"}, "$9"}, 4130b57cec5SDimitry Andric {{"t2"}, "$10"}, {{"t3"}, "$11"}, {{"t4"}, "$12"}, 4140b57cec5SDimitry Andric {{"t5"}, "$13"}, {{"t6"}, "$14"}, {{"t7"}, "$15"}, 4150b57cec5SDimitry Andric {{"s0"}, "$16"}, {{"s1"}, "$17"}, {{"s2"}, "$18"}, 4160b57cec5SDimitry Andric {{"s3"}, "$19"}, {{"s4"}, "$20"}, {{"s5"}, "$21"}, 4170b57cec5SDimitry Andric {{"s6"}, "$22"}, {{"s7"}, "$23"}, {{"t8"}, "$24"}, 4180b57cec5SDimitry Andric {{"t9"}, "$25"}, {{"k0"}, "$26"}, {{"k1"}, "$27"}, 4190b57cec5SDimitry Andric {{"gp"}, "$28"}, {{"sp", "$sp"}, "$29"}, {{"fp", "$fp"}, "$30"}, 4200b57cec5SDimitry Andric {{"ra"}, "$31"} 4210b57cec5SDimitry Andric }; 4220b57cec5SDimitry Andric static const TargetInfo::GCCRegAlias NewABIRegAliases[] = { 4230b57cec5SDimitry Andric {{"at"}, "$1"}, {{"v0"}, "$2"}, {{"v1"}, "$3"}, 4240b57cec5SDimitry Andric {{"a0"}, "$4"}, {{"a1"}, "$5"}, {{"a2"}, "$6"}, 4250b57cec5SDimitry Andric {{"a3"}, "$7"}, {{"a4"}, "$8"}, {{"a5"}, "$9"}, 4260b57cec5SDimitry Andric {{"a6"}, "$10"}, {{"a7"}, "$11"}, {{"t0"}, "$12"}, 4270b57cec5SDimitry Andric {{"t1"}, "$13"}, {{"t2"}, "$14"}, {{"t3"}, "$15"}, 4280b57cec5SDimitry Andric {{"s0"}, "$16"}, {{"s1"}, "$17"}, {{"s2"}, "$18"}, 4290b57cec5SDimitry Andric {{"s3"}, "$19"}, {{"s4"}, "$20"}, {{"s5"}, "$21"}, 4300b57cec5SDimitry Andric {{"s6"}, "$22"}, {{"s7"}, "$23"}, {{"t8"}, "$24"}, 4310b57cec5SDimitry Andric {{"t9"}, "$25"}, {{"k0"}, "$26"}, {{"k1"}, "$27"}, 4320b57cec5SDimitry Andric {{"gp"}, "$28"}, {{"sp", "$sp"}, "$29"}, {{"fp", "$fp"}, "$30"}, 4330b57cec5SDimitry Andric {{"ra"}, "$31"} 4340b57cec5SDimitry Andric }; 4350b57cec5SDimitry Andric if (ABI == "o32") 436bdd1243dSDimitry Andric return llvm::ArrayRef(O32RegAliases); 437bdd1243dSDimitry Andric return llvm::ArrayRef(NewABIRegAliases); 4380b57cec5SDimitry Andric } 4390b57cec5SDimitry Andric 4400b57cec5SDimitry Andric bool hasInt128Type() const override { 4410b57cec5SDimitry Andric return (ABI == "n32" || ABI == "n64") || getTargetOpts().ForceEnableInt128; 4420b57cec5SDimitry Andric } 4430b57cec5SDimitry Andric 4440b57cec5SDimitry Andric unsigned getUnwindWordWidth() const override; 4450b57cec5SDimitry Andric 4460b57cec5SDimitry Andric bool validateTarget(DiagnosticsEngine &Diags) const override; 4470eae32dcSDimitry Andric bool hasBitIntType() const override { return true; } 448*0fca6ea1SDimitry Andric 449*0fca6ea1SDimitry Andric std::pair<unsigned, unsigned> hardwareInterferenceSizes() const override { 450*0fca6ea1SDimitry Andric return std::make_pair(32, 32); 451*0fca6ea1SDimitry Andric } 4520b57cec5SDimitry Andric }; 4530b57cec5SDimitry Andric } // namespace targets 4540b57cec5SDimitry Andric } // namespace clang 4550b57cec5SDimitry Andric 4560b57cec5SDimitry Andric #endif // LLVM_CLANG_LIB_BASIC_TARGETS_MIPS_H 457