1*0b57cec5SDimitry Andric //===--- Mips.h - Declare Mips target feature support -----------*- C++ -*-===// 2*0b57cec5SDimitry Andric // 3*0b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*0b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*0b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*0b57cec5SDimitry Andric // 7*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8*0b57cec5SDimitry Andric // 9*0b57cec5SDimitry Andric // This file declares Mips TargetInfo objects. 10*0b57cec5SDimitry Andric // 11*0b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 12*0b57cec5SDimitry Andric 13*0b57cec5SDimitry Andric #ifndef LLVM_CLANG_LIB_BASIC_TARGETS_MIPS_H 14*0b57cec5SDimitry Andric #define LLVM_CLANG_LIB_BASIC_TARGETS_MIPS_H 15*0b57cec5SDimitry Andric 16*0b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h" 17*0b57cec5SDimitry Andric #include "clang/Basic/TargetOptions.h" 18*0b57cec5SDimitry Andric #include "llvm/ADT/Triple.h" 19*0b57cec5SDimitry Andric #include "llvm/Support/Compiler.h" 20*0b57cec5SDimitry Andric 21*0b57cec5SDimitry Andric namespace clang { 22*0b57cec5SDimitry Andric namespace targets { 23*0b57cec5SDimitry Andric 24*0b57cec5SDimitry Andric class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo { 25*0b57cec5SDimitry Andric void setDataLayout() { 26*0b57cec5SDimitry Andric StringRef Layout; 27*0b57cec5SDimitry Andric 28*0b57cec5SDimitry Andric if (ABI == "o32") 29*0b57cec5SDimitry Andric Layout = "m:m-p:32:32-i8:8:32-i16:16:32-i64:64-n32-S64"; 30*0b57cec5SDimitry Andric else if (ABI == "n32") 31*0b57cec5SDimitry Andric Layout = "m:e-p:32:32-i8:8:32-i16:16:32-i64:64-n32:64-S128"; 32*0b57cec5SDimitry Andric else if (ABI == "n64") 33*0b57cec5SDimitry Andric Layout = "m:e-i8:8:32-i16:16:32-i64:64-n32:64-S128"; 34*0b57cec5SDimitry Andric else 35*0b57cec5SDimitry Andric llvm_unreachable("Invalid ABI"); 36*0b57cec5SDimitry Andric 37*0b57cec5SDimitry Andric if (BigEndian) 38*0b57cec5SDimitry Andric resetDataLayout(("E-" + Layout).str()); 39*0b57cec5SDimitry Andric else 40*0b57cec5SDimitry Andric resetDataLayout(("e-" + Layout).str()); 41*0b57cec5SDimitry Andric } 42*0b57cec5SDimitry Andric 43*0b57cec5SDimitry Andric static const Builtin::Info BuiltinInfo[]; 44*0b57cec5SDimitry Andric std::string CPU; 45*0b57cec5SDimitry Andric bool IsMips16; 46*0b57cec5SDimitry Andric bool IsMicromips; 47*0b57cec5SDimitry Andric bool IsNan2008; 48*0b57cec5SDimitry Andric bool IsAbs2008; 49*0b57cec5SDimitry Andric bool IsSingleFloat; 50*0b57cec5SDimitry Andric bool IsNoABICalls; 51*0b57cec5SDimitry Andric bool CanUseBSDABICalls; 52*0b57cec5SDimitry Andric enum MipsFloatABI { HardFloat, SoftFloat } FloatABI; 53*0b57cec5SDimitry Andric enum DspRevEnum { NoDSP, DSP1, DSP2 } DspRev; 54*0b57cec5SDimitry Andric bool HasMSA; 55*0b57cec5SDimitry Andric bool DisableMadd4; 56*0b57cec5SDimitry Andric bool UseIndirectJumpHazard; 57*0b57cec5SDimitry Andric 58*0b57cec5SDimitry Andric protected: 59*0b57cec5SDimitry Andric enum FPModeEnum { FPXX, FP32, FP64 } FPMode; 60*0b57cec5SDimitry Andric std::string ABI; 61*0b57cec5SDimitry Andric 62*0b57cec5SDimitry Andric public: 63*0b57cec5SDimitry Andric MipsTargetInfo(const llvm::Triple &Triple, const TargetOptions &) 64*0b57cec5SDimitry Andric : TargetInfo(Triple), IsMips16(false), IsMicromips(false), 65*0b57cec5SDimitry Andric IsNan2008(false), IsAbs2008(false), IsSingleFloat(false), 66*0b57cec5SDimitry Andric IsNoABICalls(false), CanUseBSDABICalls(false), FloatABI(HardFloat), 67*0b57cec5SDimitry Andric DspRev(NoDSP), HasMSA(false), DisableMadd4(false), 68*0b57cec5SDimitry Andric UseIndirectJumpHazard(false), FPMode(FPXX) { 69*0b57cec5SDimitry Andric TheCXXABI.set(TargetCXXABI::GenericMIPS); 70*0b57cec5SDimitry Andric 71*0b57cec5SDimitry Andric if (Triple.isMIPS32()) 72*0b57cec5SDimitry Andric setABI("o32"); 73*0b57cec5SDimitry Andric else if (Triple.getEnvironment() == llvm::Triple::GNUABIN32) 74*0b57cec5SDimitry Andric setABI("n32"); 75*0b57cec5SDimitry Andric else 76*0b57cec5SDimitry Andric setABI("n64"); 77*0b57cec5SDimitry Andric 78*0b57cec5SDimitry Andric CPU = ABI == "o32" ? "mips32r2" : "mips64r2"; 79*0b57cec5SDimitry Andric 80*0b57cec5SDimitry Andric CanUseBSDABICalls = Triple.isOSFreeBSD() || 81*0b57cec5SDimitry Andric Triple.isOSOpenBSD(); 82*0b57cec5SDimitry Andric } 83*0b57cec5SDimitry Andric 84*0b57cec5SDimitry Andric bool isIEEE754_2008Default() const { 85*0b57cec5SDimitry Andric return CPU == "mips32r6" || CPU == "mips64r6"; 86*0b57cec5SDimitry Andric } 87*0b57cec5SDimitry Andric 88*0b57cec5SDimitry Andric bool isFP64Default() const { 89*0b57cec5SDimitry Andric return CPU == "mips32r6" || ABI == "n32" || ABI == "n64" || ABI == "64"; 90*0b57cec5SDimitry Andric } 91*0b57cec5SDimitry Andric 92*0b57cec5SDimitry Andric bool isNan2008() const override { return IsNan2008; } 93*0b57cec5SDimitry Andric 94*0b57cec5SDimitry Andric bool processorSupportsGPR64() const; 95*0b57cec5SDimitry Andric 96*0b57cec5SDimitry Andric StringRef getABI() const override { return ABI; } 97*0b57cec5SDimitry Andric 98*0b57cec5SDimitry Andric bool setABI(const std::string &Name) override { 99*0b57cec5SDimitry Andric if (Name == "o32") { 100*0b57cec5SDimitry Andric setO32ABITypes(); 101*0b57cec5SDimitry Andric ABI = Name; 102*0b57cec5SDimitry Andric return true; 103*0b57cec5SDimitry Andric } 104*0b57cec5SDimitry Andric 105*0b57cec5SDimitry Andric if (Name == "n32") { 106*0b57cec5SDimitry Andric setN32ABITypes(); 107*0b57cec5SDimitry Andric ABI = Name; 108*0b57cec5SDimitry Andric return true; 109*0b57cec5SDimitry Andric } 110*0b57cec5SDimitry Andric if (Name == "n64") { 111*0b57cec5SDimitry Andric setN64ABITypes(); 112*0b57cec5SDimitry Andric ABI = Name; 113*0b57cec5SDimitry Andric return true; 114*0b57cec5SDimitry Andric } 115*0b57cec5SDimitry Andric return false; 116*0b57cec5SDimitry Andric } 117*0b57cec5SDimitry Andric 118*0b57cec5SDimitry Andric void setO32ABITypes() { 119*0b57cec5SDimitry Andric Int64Type = SignedLongLong; 120*0b57cec5SDimitry Andric IntMaxType = Int64Type; 121*0b57cec5SDimitry Andric LongDoubleFormat = &llvm::APFloat::IEEEdouble(); 122*0b57cec5SDimitry Andric LongDoubleWidth = LongDoubleAlign = 64; 123*0b57cec5SDimitry Andric LongWidth = LongAlign = 32; 124*0b57cec5SDimitry Andric MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 32; 125*0b57cec5SDimitry Andric PointerWidth = PointerAlign = 32; 126*0b57cec5SDimitry Andric PtrDiffType = SignedInt; 127*0b57cec5SDimitry Andric SizeType = UnsignedInt; 128*0b57cec5SDimitry Andric SuitableAlign = 64; 129*0b57cec5SDimitry Andric } 130*0b57cec5SDimitry Andric 131*0b57cec5SDimitry Andric void setN32N64ABITypes() { 132*0b57cec5SDimitry Andric LongDoubleWidth = LongDoubleAlign = 128; 133*0b57cec5SDimitry Andric LongDoubleFormat = &llvm::APFloat::IEEEquad(); 134*0b57cec5SDimitry Andric if (getTriple().isOSFreeBSD()) { 135*0b57cec5SDimitry Andric LongDoubleWidth = LongDoubleAlign = 64; 136*0b57cec5SDimitry Andric LongDoubleFormat = &llvm::APFloat::IEEEdouble(); 137*0b57cec5SDimitry Andric } 138*0b57cec5SDimitry Andric MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; 139*0b57cec5SDimitry Andric SuitableAlign = 128; 140*0b57cec5SDimitry Andric } 141*0b57cec5SDimitry Andric 142*0b57cec5SDimitry Andric void setN64ABITypes() { 143*0b57cec5SDimitry Andric setN32N64ABITypes(); 144*0b57cec5SDimitry Andric if (getTriple().isOSOpenBSD()) { 145*0b57cec5SDimitry Andric Int64Type = SignedLongLong; 146*0b57cec5SDimitry Andric } else { 147*0b57cec5SDimitry Andric Int64Type = SignedLong; 148*0b57cec5SDimitry Andric } 149*0b57cec5SDimitry Andric IntMaxType = Int64Type; 150*0b57cec5SDimitry Andric LongWidth = LongAlign = 64; 151*0b57cec5SDimitry Andric PointerWidth = PointerAlign = 64; 152*0b57cec5SDimitry Andric PtrDiffType = SignedLong; 153*0b57cec5SDimitry Andric SizeType = UnsignedLong; 154*0b57cec5SDimitry Andric } 155*0b57cec5SDimitry Andric 156*0b57cec5SDimitry Andric void setN32ABITypes() { 157*0b57cec5SDimitry Andric setN32N64ABITypes(); 158*0b57cec5SDimitry Andric Int64Type = SignedLongLong; 159*0b57cec5SDimitry Andric IntMaxType = Int64Type; 160*0b57cec5SDimitry Andric LongWidth = LongAlign = 32; 161*0b57cec5SDimitry Andric PointerWidth = PointerAlign = 32; 162*0b57cec5SDimitry Andric PtrDiffType = SignedInt; 163*0b57cec5SDimitry Andric SizeType = UnsignedInt; 164*0b57cec5SDimitry Andric } 165*0b57cec5SDimitry Andric 166*0b57cec5SDimitry Andric bool isValidCPUName(StringRef Name) const override; 167*0b57cec5SDimitry Andric void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override; 168*0b57cec5SDimitry Andric 169*0b57cec5SDimitry Andric bool setCPU(const std::string &Name) override { 170*0b57cec5SDimitry Andric CPU = Name; 171*0b57cec5SDimitry Andric return isValidCPUName(Name); 172*0b57cec5SDimitry Andric } 173*0b57cec5SDimitry Andric 174*0b57cec5SDimitry Andric const std::string &getCPU() const { return CPU; } 175*0b57cec5SDimitry Andric bool 176*0b57cec5SDimitry Andric initFeatureMap(llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, 177*0b57cec5SDimitry Andric StringRef CPU, 178*0b57cec5SDimitry Andric const std::vector<std::string> &FeaturesVec) const override { 179*0b57cec5SDimitry Andric if (CPU.empty()) 180*0b57cec5SDimitry Andric CPU = getCPU(); 181*0b57cec5SDimitry Andric if (CPU == "octeon") 182*0b57cec5SDimitry Andric Features["mips64r2"] = Features["cnmips"] = true; 183*0b57cec5SDimitry Andric else if (CPU == "octeon+") 184*0b57cec5SDimitry Andric Features["mips64r2"] = Features["cnmips"] = Features["cnmipsp"] = true; 185*0b57cec5SDimitry Andric else 186*0b57cec5SDimitry Andric Features[CPU] = true; 187*0b57cec5SDimitry Andric return TargetInfo::initFeatureMap(Features, Diags, CPU, FeaturesVec); 188*0b57cec5SDimitry Andric } 189*0b57cec5SDimitry Andric 190*0b57cec5SDimitry Andric unsigned getISARev() const; 191*0b57cec5SDimitry Andric 192*0b57cec5SDimitry Andric void getTargetDefines(const LangOptions &Opts, 193*0b57cec5SDimitry Andric MacroBuilder &Builder) const override; 194*0b57cec5SDimitry Andric 195*0b57cec5SDimitry Andric ArrayRef<Builtin::Info> getTargetBuiltins() const override; 196*0b57cec5SDimitry Andric 197*0b57cec5SDimitry Andric bool hasFeature(StringRef Feature) const override; 198*0b57cec5SDimitry Andric 199*0b57cec5SDimitry Andric BuiltinVaListKind getBuiltinVaListKind() const override { 200*0b57cec5SDimitry Andric return TargetInfo::VoidPtrBuiltinVaList; 201*0b57cec5SDimitry Andric } 202*0b57cec5SDimitry Andric 203*0b57cec5SDimitry Andric ArrayRef<const char *> getGCCRegNames() const override { 204*0b57cec5SDimitry Andric static const char *const GCCRegNames[] = { 205*0b57cec5SDimitry Andric // CPU register names 206*0b57cec5SDimitry Andric // Must match second column of GCCRegAliases 207*0b57cec5SDimitry Andric "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7", "$8", "$9", "$10", 208*0b57cec5SDimitry Andric "$11", "$12", "$13", "$14", "$15", "$16", "$17", "$18", "$19", "$20", 209*0b57cec5SDimitry Andric "$21", "$22", "$23", "$24", "$25", "$26", "$27", "$28", "$29", "$30", 210*0b57cec5SDimitry Andric "$31", 211*0b57cec5SDimitry Andric // Floating point register names 212*0b57cec5SDimitry Andric "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", "$f8", "$f9", 213*0b57cec5SDimitry Andric "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", "$f16", "$f17", "$f18", 214*0b57cec5SDimitry Andric "$f19", "$f20", "$f21", "$f22", "$f23", "$f24", "$f25", "$f26", "$f27", 215*0b57cec5SDimitry Andric "$f28", "$f29", "$f30", "$f31", 216*0b57cec5SDimitry Andric // Hi/lo and condition register names 217*0b57cec5SDimitry Andric "hi", "lo", "", "$fcc0", "$fcc1", "$fcc2", "$fcc3", "$fcc4", "$fcc5", 218*0b57cec5SDimitry Andric "$fcc6", "$fcc7", "$ac1hi", "$ac1lo", "$ac2hi", "$ac2lo", "$ac3hi", 219*0b57cec5SDimitry Andric "$ac3lo", 220*0b57cec5SDimitry Andric // MSA register names 221*0b57cec5SDimitry Andric "$w0", "$w1", "$w2", "$w3", "$w4", "$w5", "$w6", "$w7", "$w8", "$w9", 222*0b57cec5SDimitry Andric "$w10", "$w11", "$w12", "$w13", "$w14", "$w15", "$w16", "$w17", "$w18", 223*0b57cec5SDimitry Andric "$w19", "$w20", "$w21", "$w22", "$w23", "$w24", "$w25", "$w26", "$w27", 224*0b57cec5SDimitry Andric "$w28", "$w29", "$w30", "$w31", 225*0b57cec5SDimitry Andric // MSA control register names 226*0b57cec5SDimitry Andric "$msair", "$msacsr", "$msaaccess", "$msasave", "$msamodify", 227*0b57cec5SDimitry Andric "$msarequest", "$msamap", "$msaunmap" 228*0b57cec5SDimitry Andric }; 229*0b57cec5SDimitry Andric return llvm::makeArrayRef(GCCRegNames); 230*0b57cec5SDimitry Andric } 231*0b57cec5SDimitry Andric 232*0b57cec5SDimitry Andric bool validateAsmConstraint(const char *&Name, 233*0b57cec5SDimitry Andric TargetInfo::ConstraintInfo &Info) const override { 234*0b57cec5SDimitry Andric switch (*Name) { 235*0b57cec5SDimitry Andric default: 236*0b57cec5SDimitry Andric return false; 237*0b57cec5SDimitry Andric case 'r': // CPU registers. 238*0b57cec5SDimitry Andric case 'd': // Equivalent to "r" unless generating MIPS16 code. 239*0b57cec5SDimitry Andric case 'y': // Equivalent to "r", backward compatibility only. 240*0b57cec5SDimitry Andric case 'f': // floating-point registers. 241*0b57cec5SDimitry Andric case 'c': // $25 for indirect jumps 242*0b57cec5SDimitry Andric case 'l': // lo register 243*0b57cec5SDimitry Andric case 'x': // hilo register pair 244*0b57cec5SDimitry Andric Info.setAllowsRegister(); 245*0b57cec5SDimitry Andric return true; 246*0b57cec5SDimitry Andric case 'I': // Signed 16-bit constant 247*0b57cec5SDimitry Andric case 'J': // Integer 0 248*0b57cec5SDimitry Andric case 'K': // Unsigned 16-bit constant 249*0b57cec5SDimitry Andric case 'L': // Signed 32-bit constant, lower 16-bit zeros (for lui) 250*0b57cec5SDimitry Andric case 'M': // Constants not loadable via lui, addiu, or ori 251*0b57cec5SDimitry Andric case 'N': // Constant -1 to -65535 252*0b57cec5SDimitry Andric case 'O': // A signed 15-bit constant 253*0b57cec5SDimitry Andric case 'P': // A constant between 1 go 65535 254*0b57cec5SDimitry Andric return true; 255*0b57cec5SDimitry Andric case 'R': // An address that can be used in a non-macro load or store 256*0b57cec5SDimitry Andric Info.setAllowsMemory(); 257*0b57cec5SDimitry Andric return true; 258*0b57cec5SDimitry Andric case 'Z': 259*0b57cec5SDimitry Andric if (Name[1] == 'C') { // An address usable by ll, and sc. 260*0b57cec5SDimitry Andric Info.setAllowsMemory(); 261*0b57cec5SDimitry Andric Name++; // Skip over 'Z'. 262*0b57cec5SDimitry Andric return true; 263*0b57cec5SDimitry Andric } 264*0b57cec5SDimitry Andric return false; 265*0b57cec5SDimitry Andric } 266*0b57cec5SDimitry Andric } 267*0b57cec5SDimitry Andric 268*0b57cec5SDimitry Andric std::string convertConstraint(const char *&Constraint) const override { 269*0b57cec5SDimitry Andric std::string R; 270*0b57cec5SDimitry Andric switch (*Constraint) { 271*0b57cec5SDimitry Andric case 'Z': // Two-character constraint; add "^" hint for later parsing. 272*0b57cec5SDimitry Andric if (Constraint[1] == 'C') { 273*0b57cec5SDimitry Andric R = std::string("^") + std::string(Constraint, 2); 274*0b57cec5SDimitry Andric Constraint++; 275*0b57cec5SDimitry Andric return R; 276*0b57cec5SDimitry Andric } 277*0b57cec5SDimitry Andric break; 278*0b57cec5SDimitry Andric } 279*0b57cec5SDimitry Andric return TargetInfo::convertConstraint(Constraint); 280*0b57cec5SDimitry Andric } 281*0b57cec5SDimitry Andric 282*0b57cec5SDimitry Andric const char *getClobbers() const override { 283*0b57cec5SDimitry Andric // In GCC, $1 is not widely used in generated code (it's used only in a few 284*0b57cec5SDimitry Andric // specific situations), so there is no real need for users to add it to 285*0b57cec5SDimitry Andric // the clobbers list if they want to use it in their inline assembly code. 286*0b57cec5SDimitry Andric // 287*0b57cec5SDimitry Andric // In LLVM, $1 is treated as a normal GPR and is always allocatable during 288*0b57cec5SDimitry Andric // code generation, so using it in inline assembly without adding it to the 289*0b57cec5SDimitry Andric // clobbers list can cause conflicts between the inline assembly code and 290*0b57cec5SDimitry Andric // the surrounding generated code. 291*0b57cec5SDimitry Andric // 292*0b57cec5SDimitry Andric // Another problem is that LLVM is allowed to choose $1 for inline assembly 293*0b57cec5SDimitry Andric // operands, which will conflict with the ".set at" assembler option (which 294*0b57cec5SDimitry Andric // we use only for inline assembly, in order to maintain compatibility with 295*0b57cec5SDimitry Andric // GCC) and will also conflict with the user's usage of $1. 296*0b57cec5SDimitry Andric // 297*0b57cec5SDimitry Andric // The easiest way to avoid these conflicts and keep $1 as an allocatable 298*0b57cec5SDimitry Andric // register for generated code is to automatically clobber $1 for all inline 299*0b57cec5SDimitry Andric // assembly code. 300*0b57cec5SDimitry Andric // 301*0b57cec5SDimitry Andric // FIXME: We should automatically clobber $1 only for inline assembly code 302*0b57cec5SDimitry Andric // which actually uses it. This would allow LLVM to use $1 for inline 303*0b57cec5SDimitry Andric // assembly operands if the user's assembly code doesn't use it. 304*0b57cec5SDimitry Andric return "~{$1}"; 305*0b57cec5SDimitry Andric } 306*0b57cec5SDimitry Andric 307*0b57cec5SDimitry Andric bool handleTargetFeatures(std::vector<std::string> &Features, 308*0b57cec5SDimitry Andric DiagnosticsEngine &Diags) override { 309*0b57cec5SDimitry Andric IsMips16 = false; 310*0b57cec5SDimitry Andric IsMicromips = false; 311*0b57cec5SDimitry Andric IsNan2008 = isIEEE754_2008Default(); 312*0b57cec5SDimitry Andric IsAbs2008 = isIEEE754_2008Default(); 313*0b57cec5SDimitry Andric IsSingleFloat = false; 314*0b57cec5SDimitry Andric FloatABI = HardFloat; 315*0b57cec5SDimitry Andric DspRev = NoDSP; 316*0b57cec5SDimitry Andric FPMode = isFP64Default() ? FP64 : FPXX; 317*0b57cec5SDimitry Andric 318*0b57cec5SDimitry Andric for (const auto &Feature : Features) { 319*0b57cec5SDimitry Andric if (Feature == "+single-float") 320*0b57cec5SDimitry Andric IsSingleFloat = true; 321*0b57cec5SDimitry Andric else if (Feature == "+soft-float") 322*0b57cec5SDimitry Andric FloatABI = SoftFloat; 323*0b57cec5SDimitry Andric else if (Feature == "+mips16") 324*0b57cec5SDimitry Andric IsMips16 = true; 325*0b57cec5SDimitry Andric else if (Feature == "+micromips") 326*0b57cec5SDimitry Andric IsMicromips = true; 327*0b57cec5SDimitry Andric else if (Feature == "+dsp") 328*0b57cec5SDimitry Andric DspRev = std::max(DspRev, DSP1); 329*0b57cec5SDimitry Andric else if (Feature == "+dspr2") 330*0b57cec5SDimitry Andric DspRev = std::max(DspRev, DSP2); 331*0b57cec5SDimitry Andric else if (Feature == "+msa") 332*0b57cec5SDimitry Andric HasMSA = true; 333*0b57cec5SDimitry Andric else if (Feature == "+nomadd4") 334*0b57cec5SDimitry Andric DisableMadd4 = true; 335*0b57cec5SDimitry Andric else if (Feature == "+fp64") 336*0b57cec5SDimitry Andric FPMode = FP64; 337*0b57cec5SDimitry Andric else if (Feature == "-fp64") 338*0b57cec5SDimitry Andric FPMode = FP32; 339*0b57cec5SDimitry Andric else if (Feature == "+fpxx") 340*0b57cec5SDimitry Andric FPMode = FPXX; 341*0b57cec5SDimitry Andric else if (Feature == "+nan2008") 342*0b57cec5SDimitry Andric IsNan2008 = true; 343*0b57cec5SDimitry Andric else if (Feature == "-nan2008") 344*0b57cec5SDimitry Andric IsNan2008 = false; 345*0b57cec5SDimitry Andric else if (Feature == "+abs2008") 346*0b57cec5SDimitry Andric IsAbs2008 = true; 347*0b57cec5SDimitry Andric else if (Feature == "-abs2008") 348*0b57cec5SDimitry Andric IsAbs2008 = false; 349*0b57cec5SDimitry Andric else if (Feature == "+noabicalls") 350*0b57cec5SDimitry Andric IsNoABICalls = true; 351*0b57cec5SDimitry Andric else if (Feature == "+use-indirect-jump-hazard") 352*0b57cec5SDimitry Andric UseIndirectJumpHazard = true; 353*0b57cec5SDimitry Andric } 354*0b57cec5SDimitry Andric 355*0b57cec5SDimitry Andric setDataLayout(); 356*0b57cec5SDimitry Andric 357*0b57cec5SDimitry Andric return true; 358*0b57cec5SDimitry Andric } 359*0b57cec5SDimitry Andric 360*0b57cec5SDimitry Andric int getEHDataRegisterNumber(unsigned RegNo) const override { 361*0b57cec5SDimitry Andric if (RegNo == 0) 362*0b57cec5SDimitry Andric return 4; 363*0b57cec5SDimitry Andric if (RegNo == 1) 364*0b57cec5SDimitry Andric return 5; 365*0b57cec5SDimitry Andric return -1; 366*0b57cec5SDimitry Andric } 367*0b57cec5SDimitry Andric 368*0b57cec5SDimitry Andric bool isCLZForZeroUndef() const override { return false; } 369*0b57cec5SDimitry Andric 370*0b57cec5SDimitry Andric ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override { 371*0b57cec5SDimitry Andric static const TargetInfo::GCCRegAlias O32RegAliases[] = { 372*0b57cec5SDimitry Andric {{"at"}, "$1"}, {{"v0"}, "$2"}, {{"v1"}, "$3"}, 373*0b57cec5SDimitry Andric {{"a0"}, "$4"}, {{"a1"}, "$5"}, {{"a2"}, "$6"}, 374*0b57cec5SDimitry Andric {{"a3"}, "$7"}, {{"t0"}, "$8"}, {{"t1"}, "$9"}, 375*0b57cec5SDimitry Andric {{"t2"}, "$10"}, {{"t3"}, "$11"}, {{"t4"}, "$12"}, 376*0b57cec5SDimitry Andric {{"t5"}, "$13"}, {{"t6"}, "$14"}, {{"t7"}, "$15"}, 377*0b57cec5SDimitry Andric {{"s0"}, "$16"}, {{"s1"}, "$17"}, {{"s2"}, "$18"}, 378*0b57cec5SDimitry Andric {{"s3"}, "$19"}, {{"s4"}, "$20"}, {{"s5"}, "$21"}, 379*0b57cec5SDimitry Andric {{"s6"}, "$22"}, {{"s7"}, "$23"}, {{"t8"}, "$24"}, 380*0b57cec5SDimitry Andric {{"t9"}, "$25"}, {{"k0"}, "$26"}, {{"k1"}, "$27"}, 381*0b57cec5SDimitry Andric {{"gp"}, "$28"}, {{"sp", "$sp"}, "$29"}, {{"fp", "$fp"}, "$30"}, 382*0b57cec5SDimitry Andric {{"ra"}, "$31"} 383*0b57cec5SDimitry Andric }; 384*0b57cec5SDimitry Andric static const TargetInfo::GCCRegAlias NewABIRegAliases[] = { 385*0b57cec5SDimitry Andric {{"at"}, "$1"}, {{"v0"}, "$2"}, {{"v1"}, "$3"}, 386*0b57cec5SDimitry Andric {{"a0"}, "$4"}, {{"a1"}, "$5"}, {{"a2"}, "$6"}, 387*0b57cec5SDimitry Andric {{"a3"}, "$7"}, {{"a4"}, "$8"}, {{"a5"}, "$9"}, 388*0b57cec5SDimitry Andric {{"a6"}, "$10"}, {{"a7"}, "$11"}, {{"t0"}, "$12"}, 389*0b57cec5SDimitry Andric {{"t1"}, "$13"}, {{"t2"}, "$14"}, {{"t3"}, "$15"}, 390*0b57cec5SDimitry Andric {{"s0"}, "$16"}, {{"s1"}, "$17"}, {{"s2"}, "$18"}, 391*0b57cec5SDimitry Andric {{"s3"}, "$19"}, {{"s4"}, "$20"}, {{"s5"}, "$21"}, 392*0b57cec5SDimitry Andric {{"s6"}, "$22"}, {{"s7"}, "$23"}, {{"t8"}, "$24"}, 393*0b57cec5SDimitry Andric {{"t9"}, "$25"}, {{"k0"}, "$26"}, {{"k1"}, "$27"}, 394*0b57cec5SDimitry Andric {{"gp"}, "$28"}, {{"sp", "$sp"}, "$29"}, {{"fp", "$fp"}, "$30"}, 395*0b57cec5SDimitry Andric {{"ra"}, "$31"} 396*0b57cec5SDimitry Andric }; 397*0b57cec5SDimitry Andric if (ABI == "o32") 398*0b57cec5SDimitry Andric return llvm::makeArrayRef(O32RegAliases); 399*0b57cec5SDimitry Andric return llvm::makeArrayRef(NewABIRegAliases); 400*0b57cec5SDimitry Andric } 401*0b57cec5SDimitry Andric 402*0b57cec5SDimitry Andric bool hasInt128Type() const override { 403*0b57cec5SDimitry Andric return (ABI == "n32" || ABI == "n64") || getTargetOpts().ForceEnableInt128; 404*0b57cec5SDimitry Andric } 405*0b57cec5SDimitry Andric 406*0b57cec5SDimitry Andric unsigned getUnwindWordWidth() const override; 407*0b57cec5SDimitry Andric 408*0b57cec5SDimitry Andric bool validateTarget(DiagnosticsEngine &Diags) const override; 409*0b57cec5SDimitry Andric }; 410*0b57cec5SDimitry Andric } // namespace targets 411*0b57cec5SDimitry Andric } // namespace clang 412*0b57cec5SDimitry Andric 413*0b57cec5SDimitry Andric #endif // LLVM_CLANG_LIB_BASIC_TARGETS_MIPS_H 414