diff options
Diffstat (limited to 'contrib/llvm/lib/Target/Mips')
96 files changed, 5981 insertions, 2924 deletions
diff --git a/contrib/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/contrib/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 699dfae..9c054e5 100644 --- a/contrib/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/contrib/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +#include "MCTargetDesc/MipsABIInfo.h" #include "MCTargetDesc/MipsMCExpr.h" #include "MCTargetDesc/MipsMCTargetDesc.h" #include "MipsRegisterInfo.h" @@ -28,6 +29,7 @@ #include "llvm/Support/MathExtras.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/raw_ostream.h" #include <memory> using namespace llvm; @@ -41,18 +43,24 @@ class MCInstrInfo; namespace { class MipsAssemblerOptions { public: - MipsAssemblerOptions(uint64_t Features_) : + MipsAssemblerOptions(const FeatureBitset &Features_) : ATReg(1), Reorder(true), Macro(true), Features(Features_) {} MipsAssemblerOptions(const MipsAssemblerOptions *Opts) { - ATReg = Opts->getATRegNum(); + ATReg = Opts->getATRegIndex(); Reorder = Opts->isReorder(); Macro = Opts->isMacro(); Features = Opts->getFeatures(); } - unsigned getATRegNum() const { return ATReg; } - bool setATReg(unsigned Reg); + unsigned getATRegIndex() const { return ATReg; } + bool setATRegIndex(unsigned Reg) { + if (Reg > 31) + return false; + + ATReg = Reg; + return true; + } bool isReorder() const { return Reorder; } void setReorder() { Reorder = true; } @@ -62,31 +70,35 @@ public: void setMacro() { Macro = true; } void setNoMacro() { Macro = false; } - uint64_t getFeatures() const { return Features; } - void setFeatures(uint64_t Features_) { Features = Features_; } + const FeatureBitset &getFeatures() const { return Features; } + void setFeatures(const FeatureBitset &Features_) { Features = Features_; } // Set of features that are either architecture features or referenced // by them (e.g.: FeatureNaN2008 implied by FeatureMips32r6). // The full table can be found in MipsGenSubtargetInfo.inc (MipsFeatureKV[]). // The reason we need this mask is explained in the selectArch function. // FIXME: Ideally we would like TableGen to generate this information. - static const uint64_t AllArchRelatedMask = - Mips::FeatureMips1 | Mips::FeatureMips2 | Mips::FeatureMips3 | - Mips::FeatureMips3_32 | Mips::FeatureMips3_32r2 | Mips::FeatureMips4 | - Mips::FeatureMips4_32 | Mips::FeatureMips4_32r2 | Mips::FeatureMips5 | - Mips::FeatureMips5_32r2 | Mips::FeatureMips32 | Mips::FeatureMips32r2 | - Mips::FeatureMips32r6 | Mips::FeatureMips64 | Mips::FeatureMips64r2 | - Mips::FeatureMips64r6 | Mips::FeatureCnMips | Mips::FeatureFP64Bit | - Mips::FeatureGP64Bit | Mips::FeatureNaN2008; + static const FeatureBitset AllArchRelatedMask; private: unsigned ATReg; bool Reorder; bool Macro; - uint64_t Features; + FeatureBitset Features; }; } +const FeatureBitset MipsAssemblerOptions::AllArchRelatedMask = { + Mips::FeatureMips1, Mips::FeatureMips2, Mips::FeatureMips3, + Mips::FeatureMips3_32, Mips::FeatureMips3_32r2, Mips::FeatureMips4, + Mips::FeatureMips4_32, Mips::FeatureMips4_32r2, Mips::FeatureMips5, + Mips::FeatureMips5_32r2, Mips::FeatureMips32, Mips::FeatureMips32r2, + Mips::FeatureMips32r3, Mips::FeatureMips32r5, Mips::FeatureMips32r6, + Mips::FeatureMips64, Mips::FeatureMips64r2, Mips::FeatureMips64r3, + Mips::FeatureMips64r5, Mips::FeatureMips64r6, Mips::FeatureCnMips, + Mips::FeatureFP64Bit, Mips::FeatureGP64Bit, Mips::FeatureNaN2008 +}; + namespace { class MipsAsmParser : public MCTargetAsmParser { MipsTargetStreamer &getTargetStreamer() { @@ -95,6 +107,7 @@ class MipsAsmParser : public MCTargetAsmParser { } MCSubtargetInfo &STI; + MipsABIInfo ABI; SmallVector<std::unique_ptr<MipsAssemblerOptions>, 2> AssemblerOptions; MCSymbol *CurrentFn; // Pointer to the function being parsed. It may be a // nullptr, which indicates that no function is currently @@ -150,6 +163,9 @@ class MipsAsmParser : public MCTargetAsmParser { parseRegisterPair (OperandVector &Operands); MipsAsmParser::OperandMatchResultTy + parseMovePRegPair(OperandVector &Operands); + + MipsAsmParser::OperandMatchResultTy parseRegisterList (OperandVector &Operands); bool searchSymbolAlias(OperandVector &Operands); @@ -163,21 +179,41 @@ class MipsAsmParser : public MCTargetAsmParser { bool expandInstruction(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions); - bool expandLoadImm(MCInst &Inst, SMLoc IDLoc, + bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions); + + bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg, + bool Is32BitImm, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions); + + bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions); - bool expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc, + bool expandLoadAddressImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions); - bool expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc, + bool expandLoadAddressReg(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions); + bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions); - void expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc, + void expandLoadAddressSym(const MCOperand &DstRegOp, const MCOperand &SymOp, + bool Is32BitSym, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions); void expandMemInst(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions, bool isLoad, bool isImmOpnd); + + bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions); + + void createNop(bool hasShortDelaySlot, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions); + + void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg, + SmallVectorImpl<MCInst> &Instructions); + bool reportParseError(Twine ErrorMsg); bool reportParseError(SMLoc Loc, Twine ErrorMsg); @@ -195,6 +231,7 @@ class MipsAsmParser : public MCTargetAsmParser { bool parseDirectiveNaN(); bool parseDirectiveSet(); bool parseDirectiveOption(); + bool parseInsnDirective(); bool parseSetAtDirective(); bool parseSetNoAtDirective(); @@ -210,6 +247,8 @@ class MipsAsmParser : public MCTargetAsmParser { bool parseSetFpDirective(); bool parseSetPopDirective(); bool parseSetPushDirective(); + bool parseSetSoftFloatDirective(); + bool parseSetHardFloatDirective(); bool parseSetAssignment(); @@ -221,6 +260,8 @@ class MipsAsmParser : public MCTargetAsmParser { bool parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI, StringRef Directive); + bool parseInternalDirectiveReallowModule(); + MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol); bool eatComma(StringRef ErrorStr); @@ -245,7 +286,10 @@ class MipsAsmParser : public MCTargetAsmParser { unsigned getGPR(int RegNo); - int getATReg(SMLoc Loc); + /// Returns the internal register number for the current AT. Also checks if + /// the current AT is unavailable (set to $0) and gives an error if it is. + /// This should be used in pseudo-instruction expansions which need AT. + unsigned getATReg(SMLoc Loc); bool processInstruction(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions); @@ -278,28 +322,28 @@ class MipsAsmParser : public MCTargetAsmParser { // FeatureMipsGP64 | FeatureMips1) // Clearing Mips3 is equivalent to clear (FeatureMips3 | FeatureMips4). void selectArch(StringRef ArchFeature) { - uint64_t FeatureBits = STI.getFeatureBits(); + FeatureBitset FeatureBits = STI.getFeatureBits(); FeatureBits &= ~MipsAssemblerOptions::AllArchRelatedMask; STI.setFeatureBits(FeatureBits); setAvailableFeatures( ComputeAvailableFeatures(STI.ToggleFeature(ArchFeature))); - AssemblerOptions.back()->setFeatures(getAvailableFeatures()); + AssemblerOptions.back()->setFeatures(STI.getFeatureBits()); } void setFeatureBits(uint64_t Feature, StringRef FeatureString) { - if (!(STI.getFeatureBits() & Feature)) { + if (!(STI.getFeatureBits()[Feature])) { setAvailableFeatures( ComputeAvailableFeatures(STI.ToggleFeature(FeatureString))); + AssemblerOptions.back()->setFeatures(STI.getFeatureBits()); } - AssemblerOptions.back()->setFeatures(getAvailableFeatures()); } void clearFeatureBits(uint64_t Feature, StringRef FeatureString) { - if (STI.getFeatureBits() & Feature) { + if (STI.getFeatureBits()[Feature]) { setAvailableFeatures( ComputeAvailableFeatures(STI.ToggleFeature(FeatureString))); + AssemblerOptions.back()->setFeatures(STI.getFeatureBits()); } - AssemblerOptions.back()->setFeatures(getAvailableFeatures()); } public: @@ -313,28 +357,26 @@ public: MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser, const MCInstrInfo &MII, const MCTargetOptions &Options) - : MCTargetAsmParser(), STI(sti) { + : MCTargetAsmParser(), STI(sti), + ABI(MipsABIInfo::computeTargetABI(Triple(sti.getTargetTriple()), + sti.getCPU(), Options)) { MCAsmParserExtension::Initialize(parser); + parser.addAliasForDirective(".asciiz", ".asciz"); + // Initialize the set of available features. setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits())); // Remember the initial assembler options. The user can not modify these. AssemblerOptions.push_back( - make_unique<MipsAssemblerOptions>(getAvailableFeatures())); + llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits())); // Create an assembler options environment for the user to modify. AssemblerOptions.push_back( - make_unique<MipsAssemblerOptions>(getAvailableFeatures())); + llvm::make_unique<MipsAssemblerOptions>(STI.getFeatureBits())); getTargetStreamer().updateABIInfo(*this); - // Assert exactly one ABI was chosen. - assert((((STI.getFeatureBits() & Mips::FeatureO32) != 0) + - ((STI.getFeatureBits() & Mips::FeatureEABI) != 0) + - ((STI.getFeatureBits() & Mips::FeatureN32) != 0) + - ((STI.getFeatureBits() & Mips::FeatureN64) != 0)) == 1); - if (!isABI_O32() && !useOddSPReg() != 0) report_fatal_error("-mno-odd-spreg requires the O32 ABI"); @@ -344,55 +386,76 @@ public: /// True if all of $fcc0 - $fcc7 exist for the current ISA. bool hasEightFccRegisters() const { return hasMips4() || hasMips32(); } - bool isGP64bit() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; } - bool isFP64bit() const { return STI.getFeatureBits() & Mips::FeatureFP64Bit; } - bool isABI_N32() const { return STI.getFeatureBits() & Mips::FeatureN32; } - bool isABI_N64() const { return STI.getFeatureBits() & Mips::FeatureN64; } - bool isABI_O32() const { return STI.getFeatureBits() & Mips::FeatureO32; } - bool isABI_FPXX() const { return STI.getFeatureBits() & Mips::FeatureFPXX; } + bool isGP64bit() const { return STI.getFeatureBits()[Mips::FeatureGP64Bit]; } + bool isFP64bit() const { return STI.getFeatureBits()[Mips::FeatureFP64Bit]; } + const MipsABIInfo &getABI() const { return ABI; } + bool isABI_N32() const { return ABI.IsN32(); } + bool isABI_N64() const { return ABI.IsN64(); } + bool isABI_O32() const { return ABI.IsO32(); } + bool isABI_FPXX() const { return STI.getFeatureBits()[Mips::FeatureFPXX]; } bool useOddSPReg() const { - return !(STI.getFeatureBits() & Mips::FeatureNoOddSPReg); + return !(STI.getFeatureBits()[Mips::FeatureNoOddSPReg]); } bool inMicroMipsMode() const { - return STI.getFeatureBits() & Mips::FeatureMicroMips; + return STI.getFeatureBits()[Mips::FeatureMicroMips]; } - bool hasMips1() const { return STI.getFeatureBits() & Mips::FeatureMips1; } - bool hasMips2() const { return STI.getFeatureBits() & Mips::FeatureMips2; } - bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; } - bool hasMips4() const { return STI.getFeatureBits() & Mips::FeatureMips4; } - bool hasMips5() const { return STI.getFeatureBits() & Mips::FeatureMips5; } + bool hasMips1() const { return STI.getFeatureBits()[Mips::FeatureMips1]; } + bool hasMips2() const { return STI.getFeatureBits()[Mips::FeatureMips2]; } + bool hasMips3() const { return STI.getFeatureBits()[Mips::FeatureMips3]; } + bool hasMips4() const { return STI.getFeatureBits()[Mips::FeatureMips4]; } + bool hasMips5() const { return STI.getFeatureBits()[Mips::FeatureMips5]; } bool hasMips32() const { - return (STI.getFeatureBits() & Mips::FeatureMips32); + return STI.getFeatureBits()[Mips::FeatureMips32]; } bool hasMips64() const { - return (STI.getFeatureBits() & Mips::FeatureMips64); + return STI.getFeatureBits()[Mips::FeatureMips64]; } bool hasMips32r2() const { - return (STI.getFeatureBits() & Mips::FeatureMips32r2); + return STI.getFeatureBits()[Mips::FeatureMips32r2]; } bool hasMips64r2() const { - return (STI.getFeatureBits() & Mips::FeatureMips64r2); + return STI.getFeatureBits()[Mips::FeatureMips64r2]; + } + bool hasMips32r3() const { + return (STI.getFeatureBits()[Mips::FeatureMips32r3]); + } + bool hasMips64r3() const { + return (STI.getFeatureBits()[Mips::FeatureMips64r3]); + } + bool hasMips32r5() const { + return (STI.getFeatureBits()[Mips::FeatureMips32r5]); + } + bool hasMips64r5() const { + return (STI.getFeatureBits()[Mips::FeatureMips64r5]); } bool hasMips32r6() const { - return (STI.getFeatureBits() & Mips::FeatureMips32r6); + return STI.getFeatureBits()[Mips::FeatureMips32r6]; } bool hasMips64r6() const { - return (STI.getFeatureBits() & Mips::FeatureMips64r6); + return STI.getFeatureBits()[Mips::FeatureMips64r6]; + } + + bool hasDSP() const { return STI.getFeatureBits()[Mips::FeatureDSP]; } + bool hasDSPR2() const { return STI.getFeatureBits()[Mips::FeatureDSPR2]; } + bool hasMSA() const { return STI.getFeatureBits()[Mips::FeatureMSA]; } + bool hasCnMips() const { + return (STI.getFeatureBits()[Mips::FeatureCnMips]); } - bool hasDSP() const { return (STI.getFeatureBits() & Mips::FeatureDSP); } - bool hasDSPR2() const { return (STI.getFeatureBits() & Mips::FeatureDSPR2); } - bool hasMSA() const { return (STI.getFeatureBits() & Mips::FeatureMSA); } bool inMips16Mode() const { - return STI.getFeatureBits() & Mips::FeatureMips16; + return STI.getFeatureBits()[Mips::FeatureMips16]; } - // TODO: see how can we get this info. - bool abiUsesSoftFloat() const { return false; } - /// Warn if RegNo is the current assembler temporary. - void warnIfAssemblerTemporary(int RegNo, SMLoc Loc); + bool useSoftFloat() const { + return STI.getFeatureBits()[Mips::FeatureSoftFloat]; + } + + /// Warn if RegIndex is the same as the current AT. + void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc); + + void warnIfNoMacro(SMLoc Loc); }; } @@ -501,7 +564,7 @@ public: /// target. unsigned getGPR32Reg() const { assert(isRegIdx() && (RegIdx.Kind & RegKind_GPR) && "Invalid access!"); - AsmParser.warnIfAssemblerTemporary(RegIdx.Index, StartLoc); + AsmParser.warnIfRegIndexIsAT(RegIdx.Index, StartLoc); unsigned ClassID = Mips::GPR32RegClassID; return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index); } @@ -643,11 +706,11 @@ public: void addExpr(MCInst &Inst, const MCExpr *Expr) const { // Add as immediate when possible. Null MCExpr = 0. if (!Expr) - Inst.addOperand(MCOperand::CreateImm(0)); + Inst.addOperand(MCOperand::createImm(0)); else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr)) - Inst.addOperand(MCOperand::CreateImm(CE->getValue())); + Inst.addOperand(MCOperand::createImm(CE->getValue())); else - Inst.addOperand(MCOperand::CreateExpr(Expr)); + Inst.addOperand(MCOperand::createExpr(Expr)); } void addRegOperands(MCInst &Inst, unsigned N) const { @@ -659,17 +722,22 @@ public: /// is not a k_RegisterIndex compatible with RegKind_GPR void addGPR32AsmRegOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getGPR32Reg())); + Inst.addOperand(MCOperand::createReg(getGPR32Reg())); } void addGPRMM16AsmRegOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg())); + Inst.addOperand(MCOperand::createReg(getGPRMM16Reg())); } void addGPRMM16AsmRegZeroOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getGPRMM16Reg())); + Inst.addOperand(MCOperand::createReg(getGPRMM16Reg())); + } + + void addGPRMM16AsmRegMovePOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::createReg(getGPRMM16Reg())); } /// Render the operand to an MCInst as a GPR64 @@ -677,22 +745,22 @@ public: /// is not a k_RegisterIndex compatible with RegKind_GPR void addGPR64AsmRegOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getGPR64Reg())); + Inst.addOperand(MCOperand::createReg(getGPR64Reg())); } void addAFGR64AsmRegOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getAFGR64Reg())); + Inst.addOperand(MCOperand::createReg(getAFGR64Reg())); } void addFGR64AsmRegOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getFGR64Reg())); + Inst.addOperand(MCOperand::createReg(getFGR64Reg())); } void addFGR32AsmRegOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getFGR32Reg())); + Inst.addOperand(MCOperand::createReg(getFGR32Reg())); // FIXME: We ought to do this for -integrated-as without -via-file-asm too. if (!AsmParser.useOddSPReg() && RegIdx.Index & 1) AsmParser.Error(StartLoc, "-mno-odd-spreg prohibits the use of odd FPU " @@ -701,57 +769,57 @@ public: void addFGRH32AsmRegOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getFGRH32Reg())); + Inst.addOperand(MCOperand::createReg(getFGRH32Reg())); } void addFCCAsmRegOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getFCCReg())); + Inst.addOperand(MCOperand::createReg(getFCCReg())); } void addMSA128AsmRegOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getMSA128Reg())); + Inst.addOperand(MCOperand::createReg(getMSA128Reg())); } void addMSACtrlAsmRegOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getMSACtrlReg())); + Inst.addOperand(MCOperand::createReg(getMSACtrlReg())); } void addCOP2AsmRegOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getCOP2Reg())); + Inst.addOperand(MCOperand::createReg(getCOP2Reg())); } void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getCOP3Reg())); + Inst.addOperand(MCOperand::createReg(getCOP3Reg())); } void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg())); + Inst.addOperand(MCOperand::createReg(getACC64DSPReg())); } void addHI32DSPAsmRegOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getHI32DSPReg())); + Inst.addOperand(MCOperand::createReg(getHI32DSPReg())); } void addLO32DSPAsmRegOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getLO32DSPReg())); + Inst.addOperand(MCOperand::createReg(getLO32DSPReg())); } void addCCRAsmRegOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getCCRReg())); + Inst.addOperand(MCOperand::createReg(getCCRReg())); } void addHWRegsAsmRegOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getHWRegsReg())); + Inst.addOperand(MCOperand::createReg(getHWRegsReg())); } void addImmOperands(MCInst &Inst, unsigned N) const { @@ -763,7 +831,7 @@ public: void addMemOperands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPR32Reg())); + Inst.addOperand(MCOperand::createReg(getMemBase()->getGPR32Reg())); const MCExpr *Expr = getMemOff(); addExpr(Inst, Expr); @@ -772,7 +840,7 @@ public: void addMicroMipsMemOperands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); - Inst.addOperand(MCOperand::CreateReg(getMemBase()->getGPRMM16Reg())); + Inst.addOperand(MCOperand::createReg(getMemBase()->getGPRMM16Reg())); const MCExpr *Expr = getMemOff(); addExpr(Inst, Expr); @@ -782,14 +850,20 @@ public: assert(N == 1 && "Invalid number of operands!"); for (auto RegNo : getRegList()) - Inst.addOperand(MCOperand::CreateReg(RegNo)); + Inst.addOperand(MCOperand::createReg(RegNo)); } void addRegPairOperands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); unsigned RegNo = getRegPair(); - Inst.addOperand(MCOperand::CreateReg(RegNo++)); - Inst.addOperand(MCOperand::CreateReg(RegNo)); + Inst.addOperand(MCOperand::createReg(RegNo++)); + Inst.addOperand(MCOperand::createReg(RegNo)); + } + + void addMovePRegPairOperands(MCInst &Inst, unsigned N) const { + assert(N == 2 && "Invalid number of operands!"); + for (auto RegNo : getRegList()) + Inst.addOperand(MCOperand::createReg(RegNo)); } bool isReg() const override { @@ -856,6 +930,25 @@ public: return 1 <= Val && Val <= 4; } bool isRegList() const { return Kind == k_RegList; } + bool isMovePRegPair() const { + if (Kind != k_RegList || RegList.List->size() != 2) + return false; + + unsigned R0 = RegList.List->front(); + unsigned R1 = RegList.List->back(); + + if ((R0 == Mips::A1 && R1 == Mips::A2) || + (R0 == Mips::A1 && R1 == Mips::A3) || + (R0 == Mips::A2 && R1 == Mips::A3) || + (R0 == Mips::A0 && R1 == Mips::S5) || + (R0 == Mips::A0 && R1 == Mips::S6) || + (R0 == Mips::A0 && R1 == Mips::A1) || + (R0 == Mips::A0 && R1 == Mips::A2) || + (R0 == Mips::A0 && R1 == Mips::A3)) + return true; + + return false; + } StringRef getToken() const { assert(Kind == k_Token && "Invalid access!"); @@ -1009,9 +1102,7 @@ public: assert (Regs.size() > 0 && "Empty list not allowed"); auto Op = make_unique<MipsOperand>(k_RegList, Parser); - Op->RegList.List = new SmallVector<unsigned, 10>(); - for (auto Reg : Regs) - Op->RegList.List->push_back(Reg); + Op->RegList.List = new SmallVector<unsigned, 10>(Regs.begin(), Regs.end()); Op->StartLoc = StartLoc; Op->EndLoc = EndLoc; return Op; @@ -1042,6 +1133,12 @@ public: (RegIdx.Index >= 2 && RegIdx.Index <= 7) || RegIdx.Index == 17); } + bool isMM16AsmRegMoveP() const { + if (!(isRegIdx() && RegIdx.Kind)) + return false; + return (RegIdx.Index == 0 || (RegIdx.Index >= 2 && RegIdx.Index <= 3) || + (RegIdx.Index >= 16 && RegIdx.Index <= 20)); + } bool isFGRAsmReg() const { // AFGR64 is $0-$15 but we handle this in getAFGR64() return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31; @@ -1101,14 +1198,14 @@ public: switch (Kind) { case k_Immediate: OS << "Imm<"; - Imm.Val->print(OS); + OS << *Imm.Val; OS << ">"; break; case k_Memory: OS << "Mem<"; Mem.Base->print(OS); OS << ", "; - Mem.Off->print(OS); + OS << *Mem.Off; OS << ">"; break; case k_PhysRegister: @@ -1167,6 +1264,13 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, switch (Opcode) { default: break; + case Mips::BBIT0: + case Mips::BBIT032: + case Mips::BBIT1: + case Mips::BBIT132: + assert(hasCnMips() && "instruction only valid for octeon cpus"); + // Fall through + case Mips::BEQ: case Mips::BNE: case Mips::BEQ_MM: @@ -1229,23 +1333,72 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, "nop instruction"); } - if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) { - // If this instruction has a delay slot and .set reorder is active, - // emit a NOP after it. - Instructions.push_back(Inst); - MCInst NopInst; - if (hasShortDelaySlot(Inst.getOpcode())) { - NopInst.setOpcode(Mips::MOVE16_MM); - NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); - NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); - } else { - NopInst.setOpcode(Mips::SLL); - NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); - NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); - NopInst.addOperand(MCOperand::CreateImm(0)); + if (hasCnMips()) { + const unsigned Opcode = Inst.getOpcode(); + MCOperand Opnd; + int Imm; + + switch (Opcode) { + default: + break; + + case Mips::BBIT0: + case Mips::BBIT032: + case Mips::BBIT1: + case Mips::BBIT132: + assert(MCID.getNumOperands() == 3 && "unexpected number of operands"); + // The offset is handled above + Opnd = Inst.getOperand(1); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (Imm < 0 || Imm > (Opcode == Mips::BBIT0 || + Opcode == Mips::BBIT1 ? 63 : 31)) + return Error(IDLoc, "immediate operand value out of range"); + if (Imm > 31) { + Inst.setOpcode(Opcode == Mips::BBIT0 ? Mips::BBIT032 + : Mips::BBIT132); + Inst.getOperand(1).setImm(Imm - 32); + } + break; + + case Mips::CINS: + case Mips::CINS32: + case Mips::EXTS: + case Mips::EXTS32: + assert(MCID.getNumOperands() == 4 && "unexpected number of operands"); + // Check length + Opnd = Inst.getOperand(3); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (Imm < 0 || Imm > 31) + return Error(IDLoc, "immediate operand value out of range"); + // Check position + Opnd = Inst.getOperand(2); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (Imm < 0 || Imm > (Opcode == Mips::CINS || + Opcode == Mips::EXTS ? 63 : 31)) + return Error(IDLoc, "immediate operand value out of range"); + if (Imm > 31) { + Inst.setOpcode(Opcode == Mips::CINS ? Mips::CINS32 : Mips::EXTS32); + Inst.getOperand(2).setImm(Imm - 32); + } + break; + + case Mips::SEQi: + case Mips::SNEi: + assert(MCID.getNumOperands() == 3 && "unexpected number of operands"); + Opnd = Inst.getOperand(2); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + Imm = Opnd.getImm(); + if (!isInt<10>(Imm)) + return Error(IDLoc, "immediate operand value out of range"); + break; } - Instructions.push_back(NopInst); - return false; } if (MCID.mayLoad() || MCID.mayStore()) { @@ -1282,8 +1435,38 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, } // for } // if load/store - // TODO: Handle this with the AsmOperandClass.PredicateMethod. if (inMicroMipsMode()) { + if (MCID.mayLoad()) { + // Try to create 16-bit GP relative load instruction. + for (unsigned i = 0; i < MCID.getNumOperands(); i++) { + const MCOperandInfo &OpInfo = MCID.OpInfo[i]; + if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY) || + (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) { + MCOperand &Op = Inst.getOperand(i); + if (Op.isImm()) { + int MemOffset = Op.getImm(); + MCOperand &DstReg = Inst.getOperand(0); + MCOperand &BaseReg = Inst.getOperand(1); + if (isIntN(9, MemOffset) && (MemOffset % 4 == 0) && + getContext().getRegisterInfo()->getRegClass( + Mips::GPRMM16RegClassID).contains(DstReg.getReg()) && + BaseReg.getReg() == Mips::GP) { + MCInst TmpInst; + TmpInst.setLoc(IDLoc); + TmpInst.setOpcode(Mips::LWGP_MM); + TmpInst.addOperand(MCOperand::createReg(DstReg.getReg())); + TmpInst.addOperand(MCOperand::createReg(Mips::GP)); + TmpInst.addOperand(MCOperand::createImm(MemOffset)); + Instructions.push_back(TmpInst); + return false; + } + } + } + } // for + } // if load + + // TODO: Handle this with the AsmOperandClass.PredicateMethod. + MCOperand Opnd; int Imm; @@ -1396,24 +1579,43 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, if (!isUInt<5>(Imm)) return Error(IDLoc, "immediate operand value out of range"); break; + case Mips::ADDIUPC_MM: + MCOperand Opnd = Inst.getOperand(1); + if (!Opnd.isImm()) + return Error(IDLoc, "expected immediate operand kind"); + int Imm = Opnd.getImm(); + if ((Imm % 4 != 0) || !isIntN(25, Imm)) + return Error(IDLoc, "immediate operand value out of range"); + break; } } - if (needsExpansion(Inst)) - return expandInstruction(Inst, IDLoc, Instructions); - else + if (needsExpansion(Inst)) { + if (expandInstruction(Inst, IDLoc, Instructions)) + return true; + } else Instructions.push_back(Inst); + // If this instruction has a delay slot and .set reorder is active, + // emit a NOP after it. + if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) + createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions); + return false; } bool MipsAsmParser::needsExpansion(MCInst &Inst) { switch (Inst.getOpcode()) { - case Mips::LoadImm32Reg: - case Mips::LoadAddr32Imm: - case Mips::LoadAddr32Reg: - case Mips::LoadImm64Reg: + case Mips::LoadImm32: + case Mips::LoadImm64: + case Mips::LoadAddrImm32: + case Mips::LoadAddrReg32: + case Mips::B_MM_Pseudo: + case Mips::LWM_MM: + case Mips::SWM_MM: + case Mips::JalOneReg: + case Mips::JalTwoReg: return true; default: return false; @@ -1424,264 +1626,334 @@ bool MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { switch (Inst.getOpcode()) { default: llvm_unreachable("unimplemented expansion"); - case Mips::LoadImm32Reg: - return expandLoadImm(Inst, IDLoc, Instructions); - case Mips::LoadImm64Reg: - if (!isGP64bit()) { - Error(IDLoc, "instruction requires a 64-bit architecture"); - return true; - } - return expandLoadImm(Inst, IDLoc, Instructions); - case Mips::LoadAddr32Imm: - return expandLoadAddressImm(Inst, IDLoc, Instructions); - case Mips::LoadAddr32Reg: - return expandLoadAddressReg(Inst, IDLoc, Instructions); + case Mips::LoadImm32: + return expandLoadImm(Inst, true, IDLoc, Instructions); + case Mips::LoadImm64: + return expandLoadImm(Inst, false, IDLoc, Instructions); + case Mips::LoadAddrImm32: + return expandLoadAddressImm(Inst, true, IDLoc, Instructions); + case Mips::LoadAddrReg32: + return expandLoadAddressReg(Inst, true, IDLoc, Instructions); + case Mips::B_MM_Pseudo: + return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions); + case Mips::SWM_MM: + case Mips::LWM_MM: + return expandLoadStoreMultiple(Inst, IDLoc, Instructions); + case Mips::JalOneReg: + case Mips::JalTwoReg: + return expandJalWithRegs(Inst, IDLoc, Instructions); } } namespace { -template <bool PerformShift> -void createShiftOr(MCOperand Operand, unsigned RegNo, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions) { +template <unsigned ShiftAmount> +void createLShiftOri(MCOperand Operand, unsigned RegNo, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions) { MCInst tmpInst; - if (PerformShift) { + if (ShiftAmount >= 32) { + tmpInst.setOpcode(Mips::DSLL32); + tmpInst.addOperand(MCOperand::createReg(RegNo)); + tmpInst.addOperand(MCOperand::createReg(RegNo)); + tmpInst.addOperand(MCOperand::createImm(ShiftAmount - 32)); + tmpInst.setLoc(IDLoc); + Instructions.push_back(tmpInst); + tmpInst.clear(); + } else if (ShiftAmount > 0) { tmpInst.setOpcode(Mips::DSLL); - tmpInst.addOperand(MCOperand::CreateReg(RegNo)); - tmpInst.addOperand(MCOperand::CreateReg(RegNo)); - tmpInst.addOperand(MCOperand::CreateImm(16)); + tmpInst.addOperand(MCOperand::createReg(RegNo)); + tmpInst.addOperand(MCOperand::createReg(RegNo)); + tmpInst.addOperand(MCOperand::createImm(ShiftAmount)); tmpInst.setLoc(IDLoc); Instructions.push_back(tmpInst); tmpInst.clear(); } + // There's no need for an ORi if the immediate is 0. + if (Operand.isImm() && Operand.getImm() == 0) + return; + tmpInst.setOpcode(Mips::ORi); - tmpInst.addOperand(MCOperand::CreateReg(RegNo)); - tmpInst.addOperand(MCOperand::CreateReg(RegNo)); + tmpInst.addOperand(MCOperand::createReg(RegNo)); + tmpInst.addOperand(MCOperand::createReg(RegNo)); tmpInst.addOperand(Operand); tmpInst.setLoc(IDLoc); Instructions.push_back(tmpInst); } -template <int Shift, bool PerformShift> -void createShiftOr(int64_t Value, unsigned RegNo, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions) { - createShiftOr<PerformShift>( - MCOperand::CreateImm(((Value & (0xffffLL << Shift)) >> Shift)), RegNo, - IDLoc, Instructions); +template <unsigned ShiftAmount> +void createLShiftOri(int64_t Value, unsigned RegNo, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions) { + createLShiftOri<ShiftAmount>(MCOperand::createImm(Value), RegNo, IDLoc, + Instructions); } } -bool MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc, +bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions) { + // Create a JALR instruction which is going to replace the pseudo-JAL. + MCInst JalrInst; + JalrInst.setLoc(IDLoc); + const MCOperand FirstRegOp = Inst.getOperand(0); + const unsigned Opcode = Inst.getOpcode(); + + if (Opcode == Mips::JalOneReg) { + // jal $rs => jalr $rs + if (inMicroMipsMode()) { + JalrInst.setOpcode(Mips::JALR16_MM); + JalrInst.addOperand(FirstRegOp); + } else { + JalrInst.setOpcode(Mips::JALR); + JalrInst.addOperand(MCOperand::createReg(Mips::RA)); + JalrInst.addOperand(FirstRegOp); + } + } else if (Opcode == Mips::JalTwoReg) { + // jal $rd, $rs => jalr $rd, $rs + JalrInst.setOpcode(inMicroMipsMode() ? Mips::JALR_MM : Mips::JALR); + JalrInst.addOperand(FirstRegOp); + const MCOperand SecondRegOp = Inst.getOperand(1); + JalrInst.addOperand(SecondRegOp); + } + Instructions.push_back(JalrInst); + + // If .set reorder is active, emit a NOP after it. + if (AssemblerOptions.back()->isReorder()) { + // This is a 32-bit NOP because these 2 pseudo-instructions + // do not have a short delay slot. + MCInst NopInst; + NopInst.setOpcode(Mips::SLL); + NopInst.addOperand(MCOperand::createReg(Mips::ZERO)); + NopInst.addOperand(MCOperand::createReg(Mips::ZERO)); + NopInst.addOperand(MCOperand::createImm(0)); + Instructions.push_back(NopInst); + } + + return false; +} + +bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg, + unsigned SrcReg, bool Is32BitImm, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { + if (!Is32BitImm && !isGP64bit()) { + Error(IDLoc, "instruction requires a 64-bit architecture"); + return true; + } + + bool UseSrcReg = false; + if (SrcReg != Mips::NoRegister) + UseSrcReg = true; + MCInst tmpInst; - const MCOperand &ImmOp = Inst.getOperand(1); - assert(ImmOp.isImm() && "expected immediate operand kind"); - const MCOperand &RegOp = Inst.getOperand(0); - assert(RegOp.isReg() && "expected register operand kind"); - int64_t ImmValue = ImmOp.getImm(); tmpInst.setLoc(IDLoc); // FIXME: gas has a special case for values that are 000...1111, which // becomes a li -1 and then a dsrl if (0 <= ImmValue && ImmValue <= 65535) { - // For 0 <= j <= 65535. + // For unsigned and positive signed 16-bit values (0 <= j <= 65535): // li d,j => ori d,$zero,j + if (!UseSrcReg) + SrcReg = isGP64bit() ? Mips::ZERO_64 : Mips::ZERO; tmpInst.setOpcode(Mips::ORi); - tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg())); - tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); - tmpInst.addOperand(MCOperand::CreateImm(ImmValue)); + tmpInst.addOperand(MCOperand::createReg(DstReg)); + tmpInst.addOperand(MCOperand::createReg(SrcReg)); + tmpInst.addOperand(MCOperand::createImm(ImmValue)); Instructions.push_back(tmpInst); } else if (ImmValue < 0 && ImmValue >= -32768) { - // For -32768 <= j < 0. + // For negative signed 16-bit values (-32768 <= j < 0): // li d,j => addiu d,$zero,j + if (!UseSrcReg) + SrcReg = Mips::ZERO; tmpInst.setOpcode(Mips::ADDiu); - tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg())); - tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); - tmpInst.addOperand(MCOperand::CreateImm(ImmValue)); + tmpInst.addOperand(MCOperand::createReg(DstReg)); + tmpInst.addOperand(MCOperand::createReg(SrcReg)); + tmpInst.addOperand(MCOperand::createImm(ImmValue)); Instructions.push_back(tmpInst); - } else if ((ImmValue & 0xffffffff) == ImmValue) { - // For any value of j that is representable as a 32-bit integer, create - // a sequence of: + } else if (isInt<32>(ImmValue) || isUInt<32>(ImmValue)) { + warnIfNoMacro(IDLoc); + + // For all other values which are representable as a 32-bit integer: // li d,j => lui d,hi16(j) // ori d,d,lo16(j) - tmpInst.setOpcode(Mips::LUi); - tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg())); - tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16)); - Instructions.push_back(tmpInst); - createShiftOr<0, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions); + uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff; + uint16_t Bits15To0 = ImmValue & 0xffff; + + if (!Is32BitImm && !isInt<32>(ImmValue)) { + // For DLI, expand to an ORi instead of a LUi to avoid sign-extending the + // upper 32 bits. + tmpInst.setOpcode(Mips::ORi); + tmpInst.addOperand(MCOperand::createReg(DstReg)); + tmpInst.addOperand(MCOperand::createReg(Mips::ZERO)); + tmpInst.addOperand(MCOperand::createImm(Bits31To16)); + tmpInst.setLoc(IDLoc); + Instructions.push_back(tmpInst); + // Move the value to the upper 16 bits by doing a 16-bit left shift. + createLShiftOri<16>(0, DstReg, IDLoc, Instructions); + } else { + tmpInst.setOpcode(Mips::LUi); + tmpInst.addOperand(MCOperand::createReg(DstReg)); + tmpInst.addOperand(MCOperand::createImm(Bits31To16)); + Instructions.push_back(tmpInst); + } + createLShiftOri<0>(Bits15To0, DstReg, IDLoc, Instructions); + + if (UseSrcReg) + createAddu(DstReg, DstReg, SrcReg, Instructions); + } else if ((ImmValue & (0xffffLL << 48)) == 0) { - if (!isGP64bit()) { - Error(IDLoc, "instruction requires a 64-bit architecture"); + if (Is32BitImm) { + Error(IDLoc, "instruction requires a 32-bit immediate"); return true; } + warnIfNoMacro(IDLoc); // <------- lo32 ------> // <------- hi32 ------> // <- hi16 -> <- lo16 -> // _________________________________ // | | | | - // | 16-bytes | 16-bytes | 16-bytes | + // | 16-bits | 16-bits | 16-bits | // |__________|__________|__________| // - // For any value of j that is representable as a 48-bit integer, create - // a sequence of: + // For any 64-bit value that is representable as a 48-bit integer: // li d,j => lui d,hi16(j) // ori d,d,hi16(lo32(j)) // dsll d,d,16 // ori d,d,lo16(lo32(j)) + uint16_t Bits47To32 = (ImmValue >> 32) & 0xffff; + uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff; + uint16_t Bits15To0 = ImmValue & 0xffff; + tmpInst.setOpcode(Mips::LUi); - tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg())); - tmpInst.addOperand( - MCOperand::CreateImm((ImmValue & (0xffffLL << 32)) >> 32)); + tmpInst.addOperand(MCOperand::createReg(DstReg)); + tmpInst.addOperand(MCOperand::createImm(Bits47To32)); Instructions.push_back(tmpInst); - createShiftOr<16, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions); - createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions); + createLShiftOri<0>(Bits31To16, DstReg, IDLoc, Instructions); + createLShiftOri<16>(Bits15To0, DstReg, IDLoc, Instructions); + + if (UseSrcReg) + createAddu(DstReg, DstReg, SrcReg, Instructions); + } else { - if (!isGP64bit()) { - Error(IDLoc, "instruction requires a 64-bit architecture"); + if (Is32BitImm) { + Error(IDLoc, "instruction requires a 32-bit immediate"); return true; } + warnIfNoMacro(IDLoc); // <------- hi32 ------> <------- lo32 ------> // <- hi16 -> <- lo16 -> // ___________________________________________ // | | | | | - // | 16-bytes | 16-bytes | 16-bytes | 16-bytes | + // | 16-bits | 16-bits | 16-bits | 16-bits | // |__________|__________|__________|__________| // - // For any value of j that isn't representable as a 48-bit integer. + // For all other values which are representable as a 64-bit integer: // li d,j => lui d,hi16(j) // ori d,d,lo16(hi32(j)) // dsll d,d,16 // ori d,d,hi16(lo32(j)) // dsll d,d,16 // ori d,d,lo16(lo32(j)) + uint16_t Bits63To48 = (ImmValue >> 48) & 0xffff; + uint16_t Bits47To32 = (ImmValue >> 32) & 0xffff; + uint16_t Bits31To16 = (ImmValue >> 16) & 0xffff; + uint16_t Bits15To0 = ImmValue & 0xffff; + tmpInst.setOpcode(Mips::LUi); - tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg())); - tmpInst.addOperand( - MCOperand::CreateImm((ImmValue & (0xffffLL << 48)) >> 48)); + tmpInst.addOperand(MCOperand::createReg(DstReg)); + tmpInst.addOperand(MCOperand::createImm(Bits63To48)); Instructions.push_back(tmpInst); - createShiftOr<32, false>(ImmValue, RegOp.getReg(), IDLoc, Instructions); - createShiftOr<16, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions); - createShiftOr<0, true>(ImmValue, RegOp.getReg(), IDLoc, Instructions); + createLShiftOri<0>(Bits47To32, DstReg, IDLoc, Instructions); + + // When Bits31To16 is 0, do a left shift of 32 bits instead of doing + // two left shifts of 16 bits. + if (Bits31To16 == 0) { + createLShiftOri<32>(Bits15To0, DstReg, IDLoc, Instructions); + } else { + createLShiftOri<16>(Bits31To16, DstReg, IDLoc, Instructions); + createLShiftOri<16>(Bits15To0, DstReg, IDLoc, Instructions); + } + + if (UseSrcReg) + createAddu(DstReg, DstReg, SrcReg, Instructions); } return false; } +bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions) { + const MCOperand &ImmOp = Inst.getOperand(1); + assert(ImmOp.isImm() && "expected immediate operand kind"); + const MCOperand &DstRegOp = Inst.getOperand(0); + assert(DstRegOp.isReg() && "expected register operand kind"); + + if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister, + Is32BitImm, IDLoc, Instructions)) + return true; + + return false; +} + bool -MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc, +MipsAsmParser::expandLoadAddressReg(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { - MCInst tmpInst; + const MCOperand &DstRegOp = Inst.getOperand(0); + assert(DstRegOp.isReg() && "expected register operand kind"); + const MCOperand &ImmOp = Inst.getOperand(2); assert((ImmOp.isImm() || ImmOp.isExpr()) && "expected immediate operand kind"); if (!ImmOp.isImm()) { - expandLoadAddressSym(Inst, IDLoc, Instructions); + expandLoadAddressSym(DstRegOp, ImmOp, Is32BitImm, IDLoc, Instructions); return false; } const MCOperand &SrcRegOp = Inst.getOperand(1); assert(SrcRegOp.isReg() && "expected register operand kind"); - const MCOperand &DstRegOp = Inst.getOperand(0); - assert(DstRegOp.isReg() && "expected register operand kind"); - int ImmValue = ImmOp.getImm(); - if (-32768 <= ImmValue && ImmValue <= 65535) { - // For -32768 <= j <= 65535. - // la d,j(s) => addiu d,s,j - tmpInst.setOpcode(Mips::ADDiu); - tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg())); - tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg())); - tmpInst.addOperand(MCOperand::CreateImm(ImmValue)); - Instructions.push_back(tmpInst); - } else { - // For any other value of j that is representable as a 32-bit integer. - // la d,j(s) => lui d,hi16(j) - // ori d,d,lo16(j) - // addu d,d,s - tmpInst.setOpcode(Mips::LUi); - tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg())); - tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16)); - Instructions.push_back(tmpInst); - tmpInst.clear(); - tmpInst.setOpcode(Mips::ORi); - tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg())); - tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg())); - tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff)); - Instructions.push_back(tmpInst); - tmpInst.clear(); - tmpInst.setOpcode(Mips::ADDu); - tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg())); - tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg())); - tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg())); - Instructions.push_back(tmpInst); - } + + if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), SrcRegOp.getReg(), + Is32BitImm, IDLoc, Instructions)) + return true; + return false; } bool -MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc, +MipsAsmParser::expandLoadAddressImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { - MCInst tmpInst; + const MCOperand &DstRegOp = Inst.getOperand(0); + assert(DstRegOp.isReg() && "expected register operand kind"); + const MCOperand &ImmOp = Inst.getOperand(1); assert((ImmOp.isImm() || ImmOp.isExpr()) && "expected immediate operand kind"); if (!ImmOp.isImm()) { - expandLoadAddressSym(Inst, IDLoc, Instructions); + expandLoadAddressSym(DstRegOp, ImmOp, Is32BitImm, IDLoc, Instructions); return false; } - const MCOperand &RegOp = Inst.getOperand(0); - assert(RegOp.isReg() && "expected register operand kind"); - int ImmValue = ImmOp.getImm(); - if (-32768 <= ImmValue && ImmValue <= 65535) { - // For -32768 <= j <= 65535. - // la d,j => addiu d,$zero,j - tmpInst.setOpcode(Mips::ADDiu); - tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg())); - tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO)); - tmpInst.addOperand(MCOperand::CreateImm(ImmValue)); - Instructions.push_back(tmpInst); - } else { - // For any other value of j that is representable as a 32-bit integer. - // la d,j => lui d,hi16(j) - // ori d,d,lo16(j) - tmpInst.setOpcode(Mips::LUi); - tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg())); - tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16)); - Instructions.push_back(tmpInst); - tmpInst.clear(); - tmpInst.setOpcode(Mips::ORi); - tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg())); - tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg())); - tmpInst.addOperand(MCOperand::CreateImm(ImmValue & 0xffff)); - Instructions.push_back(tmpInst); - } + + if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister, + Is32BitImm, IDLoc, Instructions)) + return true; + return false; } -void -MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions) { - // FIXME: If we do have a valid at register to use, we should generate a - // slightly shorter sequence here. +void MipsAsmParser::expandLoadAddressSym( + const MCOperand &DstRegOp, const MCOperand &SymOp, bool Is32BitSym, + SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { + warnIfNoMacro(IDLoc); + + if (Is32BitSym && isABI_N64()) + Warning(IDLoc, "instruction loads the 32-bit address of a 64-bit symbol"); + MCInst tmpInst; - int ExprOperandNo = 1; - // Sometimes the assembly parser will get the immediate expression as - // a $zero + an immediate. - if (Inst.getNumOperands() == 3) { - assert(Inst.getOperand(1).getReg() == - (isGP64bit() ? Mips::ZERO_64 : Mips::ZERO)); - ExprOperandNo = 2; - } - const MCOperand &SymOp = Inst.getOperand(ExprOperandNo); - assert(SymOp.isExpr() && "expected symbol operand kind"); - const MCOperand &RegOp = Inst.getOperand(0); - unsigned RegNo = RegOp.getReg(); + unsigned RegNo = DstRegOp.getReg(); const MCSymbolRefExpr *Symbol = cast<MCSymbolRefExpr>(SymOp.getExpr()); const MCSymbolRefExpr *HiExpr = - MCSymbolRefExpr::Create(Symbol->getSymbol().getName(), + MCSymbolRefExpr::create(Symbol->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI, getContext()); const MCSymbolRefExpr *LoExpr = - MCSymbolRefExpr::Create(Symbol->getSymbol().getName(), + MCSymbolRefExpr::create(Symbol->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO, getContext()); - if (isGP64bit()) { + if (!Is32BitSym) { // If it's a 64-bit architecture, expand to: // la d,sym => lui d,highest(sym) // ori d,d,higher(sym) @@ -1690,37 +1962,76 @@ MipsAsmParser::expandLoadAddressSym(MCInst &Inst, SMLoc IDLoc, // dsll d,d,16 // ori d,d,lo16(sym) const MCSymbolRefExpr *HighestExpr = - MCSymbolRefExpr::Create(Symbol->getSymbol().getName(), + MCSymbolRefExpr::create(Symbol->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_HIGHEST, getContext()); const MCSymbolRefExpr *HigherExpr = - MCSymbolRefExpr::Create(Symbol->getSymbol().getName(), + MCSymbolRefExpr::create(Symbol->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_HIGHER, getContext()); tmpInst.setOpcode(Mips::LUi); - tmpInst.addOperand(MCOperand::CreateReg(RegNo)); - tmpInst.addOperand(MCOperand::CreateExpr(HighestExpr)); + tmpInst.addOperand(MCOperand::createReg(RegNo)); + tmpInst.addOperand(MCOperand::createExpr(HighestExpr)); Instructions.push_back(tmpInst); - createShiftOr<false>(MCOperand::CreateExpr(HigherExpr), RegNo, SMLoc(), - Instructions); - createShiftOr<true>(MCOperand::CreateExpr(HiExpr), RegNo, SMLoc(), + createLShiftOri<0>(MCOperand::createExpr(HigherExpr), RegNo, SMLoc(), + Instructions); + createLShiftOri<16>(MCOperand::createExpr(HiExpr), RegNo, SMLoc(), Instructions); - createShiftOr<true>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(), + createLShiftOri<16>(MCOperand::createExpr(LoExpr), RegNo, SMLoc(), Instructions); } else { // Otherwise, expand to: // la d,sym => lui d,hi16(sym) // ori d,d,lo16(sym) tmpInst.setOpcode(Mips::LUi); - tmpInst.addOperand(MCOperand::CreateReg(RegNo)); - tmpInst.addOperand(MCOperand::CreateExpr(HiExpr)); + tmpInst.addOperand(MCOperand::createReg(RegNo)); + tmpInst.addOperand(MCOperand::createExpr(HiExpr)); Instructions.push_back(tmpInst); - createShiftOr<false>(MCOperand::CreateExpr(LoExpr), RegNo, SMLoc(), - Instructions); + createLShiftOri<0>(MCOperand::createExpr(LoExpr), RegNo, SMLoc(), + Instructions); } } +bool MipsAsmParser::expandUncondBranchMMPseudo( + MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { + assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 && + "unexpected number of operands"); + + MCOperand Offset = Inst.getOperand(0); + if (Offset.isExpr()) { + Inst.clear(); + Inst.setOpcode(Mips::BEQ_MM); + Inst.addOperand(MCOperand::createReg(Mips::ZERO)); + Inst.addOperand(MCOperand::createReg(Mips::ZERO)); + Inst.addOperand(MCOperand::createExpr(Offset.getExpr())); + } else { + assert(Offset.isImm() && "expected immediate operand kind"); + if (isIntN(11, Offset.getImm())) { + // If offset fits into 11 bits then this instruction becomes microMIPS + // 16-bit unconditional branch instruction. + Inst.setOpcode(Mips::B16_MM); + } else { + if (!isIntN(17, Offset.getImm())) + Error(IDLoc, "branch target out of range"); + if (OffsetToAlignment(Offset.getImm(), 1LL << 1)) + Error(IDLoc, "branch to misaligned address"); + Inst.clear(); + Inst.setOpcode(Mips::BEQ_MM); + Inst.addOperand(MCOperand::createReg(Mips::ZERO)); + Inst.addOperand(MCOperand::createReg(Mips::ZERO)); + Inst.addOperand(MCOperand::createImm(Offset.getImm())); + } + } + Instructions.push_back(Inst); + + // If .set reorder is active, emit a NOP after the branch instruction. + if (AssemblerOptions.back()->isReorder()) + createNop(true, IDLoc, Instructions); + + return false; +} + void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions, bool isLoad, bool isImmOpnd) { @@ -1779,29 +2090,27 @@ void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, if (isLoad && IsGPR && (BaseRegNum != RegOpNum)) TmpRegNum = RegOpNum; else { - int AT = getATReg(IDLoc); // At this point we need AT to perform the expansions and we exit if it is // not available. - if (!AT) + TmpRegNum = getATReg(IDLoc); + if (!TmpRegNum) return; - TmpRegNum = getReg( - (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, AT); } TempInst.setOpcode(Mips::LUi); - TempInst.addOperand(MCOperand::CreateReg(TmpRegNum)); + TempInst.addOperand(MCOperand::createReg(TmpRegNum)); if (isImmOpnd) - TempInst.addOperand(MCOperand::CreateImm(HiOffset)); + TempInst.addOperand(MCOperand::createImm(HiOffset)); else { if (ExprOffset->getKind() == MCExpr::SymbolRef) { SR = static_cast<const MCSymbolRefExpr *>(ExprOffset); - const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create( + const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::create( SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI, getContext()); - TempInst.addOperand(MCOperand::CreateExpr(HiExpr)); + TempInst.addOperand(MCOperand::createExpr(HiExpr)); } else { const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi"); - TempInst.addOperand(MCOperand::CreateExpr(HiExpr)); + TempInst.addOperand(MCOperand::createExpr(HiExpr)); } } // Add the instruction to the list. @@ -1809,34 +2118,86 @@ void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, // Prepare TempInst for next instruction. TempInst.clear(); // Add temp register to base. - TempInst.setOpcode(Mips::ADDu); - TempInst.addOperand(MCOperand::CreateReg(TmpRegNum)); - TempInst.addOperand(MCOperand::CreateReg(TmpRegNum)); - TempInst.addOperand(MCOperand::CreateReg(BaseRegNum)); - Instructions.push_back(TempInst); - TempInst.clear(); + if (BaseRegNum != Mips::ZERO) { + TempInst.setOpcode(Mips::ADDu); + TempInst.addOperand(MCOperand::createReg(TmpRegNum)); + TempInst.addOperand(MCOperand::createReg(TmpRegNum)); + TempInst.addOperand(MCOperand::createReg(BaseRegNum)); + Instructions.push_back(TempInst); + TempInst.clear(); + } // And finally, create original instruction with low part // of offset and new base. TempInst.setOpcode(Inst.getOpcode()); - TempInst.addOperand(MCOperand::CreateReg(RegOpNum)); - TempInst.addOperand(MCOperand::CreateReg(TmpRegNum)); + TempInst.addOperand(MCOperand::createReg(RegOpNum)); + TempInst.addOperand(MCOperand::createReg(TmpRegNum)); if (isImmOpnd) - TempInst.addOperand(MCOperand::CreateImm(LoOffset)); + TempInst.addOperand(MCOperand::createImm(LoOffset)); else { if (ExprOffset->getKind() == MCExpr::SymbolRef) { - const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create( + const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::create( SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO, getContext()); - TempInst.addOperand(MCOperand::CreateExpr(LoExpr)); + TempInst.addOperand(MCOperand::createExpr(LoExpr)); } else { const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo"); - TempInst.addOperand(MCOperand::CreateExpr(LoExpr)); + TempInst.addOperand(MCOperand::createExpr(LoExpr)); } } Instructions.push_back(TempInst); TempInst.clear(); } +bool +MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions) { + unsigned OpNum = Inst.getNumOperands(); + unsigned Opcode = Inst.getOpcode(); + unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM; + + assert (Inst.getOperand(OpNum - 1).isImm() && + Inst.getOperand(OpNum - 2).isReg() && + Inst.getOperand(OpNum - 3).isReg() && "Invalid instruction operand."); + + if (OpNum < 8 && Inst.getOperand(OpNum - 1).getImm() <= 60 && + Inst.getOperand(OpNum - 1).getImm() >= 0 && + Inst.getOperand(OpNum - 2).getReg() == Mips::SP && + Inst.getOperand(OpNum - 3).getReg() == Mips::RA) + // It can be implemented as SWM16 or LWM16 instruction. + NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM16_MM : Mips::LWM16_MM; + + Inst.setOpcode(NewOpcode); + Instructions.push_back(Inst); + return false; +} + +void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc, + SmallVectorImpl<MCInst> &Instructions) { + MCInst NopInst; + if (hasShortDelaySlot) { + NopInst.setOpcode(Mips::MOVE16_MM); + NopInst.addOperand(MCOperand::createReg(Mips::ZERO)); + NopInst.addOperand(MCOperand::createReg(Mips::ZERO)); + } else { + NopInst.setOpcode(Mips::SLL); + NopInst.addOperand(MCOperand::createReg(Mips::ZERO)); + NopInst.addOperand(MCOperand::createReg(Mips::ZERO)); + NopInst.addOperand(MCOperand::createImm(0)); + } + Instructions.push_back(NopInst); +} + +void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg, + unsigned TrgReg, + SmallVectorImpl<MCInst> &Instructions) { + MCInst AdduInst; + AdduInst.setOpcode(Mips::ADDu); + AdduInst.addOperand(MCOperand::createReg(DstReg)); + AdduInst.addOperand(MCOperand::createReg(SrcReg)); + AdduInst.addOperand(MCOperand::createReg(TrgReg)); + Instructions.push_back(AdduInst); +} + unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) { // As described by the Mips32r2 spec, the registers Rd and Rs for // jalr.hb must be different. @@ -1893,15 +2254,15 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, llvm_unreachable("Implement any new match types added!"); } -void MipsAsmParser::warnIfAssemblerTemporary(int RegIndex, SMLoc Loc) { - if ((RegIndex != 0) && - ((int)AssemblerOptions.back()->getATRegNum() == RegIndex)) { - if (RegIndex == 1) - Warning(Loc, "used $at without \".set noat\""); - else - Warning(Loc, Twine("used $") + Twine(RegIndex) + " with \".set at=$" + - Twine(RegIndex) + "\""); - } +void MipsAsmParser::warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc) { + if (RegIndex != 0 && AssemblerOptions.back()->getATRegIndex() == RegIndex) + Warning(Loc, "used $at (currently $" + Twine(RegIndex) + + ") without \".set noat\""); +} + +void MipsAsmParser::warnIfNoMacro(SMLoc Loc) { + if (!AssemblerOptions.back()->isMacro()) + Warning(Loc, "macro instruction expanded into multiple instructions"); } void @@ -2075,19 +2436,15 @@ int MipsAsmParser::matchMSA128CtrlRegisterName(StringRef Name) { return CC; } -bool MipsAssemblerOptions::setATReg(unsigned Reg) { - if (Reg > 31) - return false; - - ATReg = Reg; - return true; -} - -int MipsAsmParser::getATReg(SMLoc Loc) { - int AT = AssemblerOptions.back()->getATRegNum(); - if (AT == 0) +unsigned MipsAsmParser::getATReg(SMLoc Loc) { + unsigned ATIndex = AssemblerOptions.back()->getATRegIndex(); + if (ATIndex == 0) { reportParseError(Loc, "pseudo-instruction requires $at, which is not available"); + return 0; + } + unsigned AT = getReg( + (isGP64bit()) ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, ATIndex); return AT; } @@ -2147,10 +2504,10 @@ bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { return true; SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); - MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier); + MCSymbol *Sym = getContext().getOrCreateSymbol("$" + Identifier); // Otherwise create a symbol reference. const MCExpr *Res = - MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None, getContext()); + MCSymbolRefExpr::create(Sym, MCSymbolRefExpr::VK_None, getContext()); Operands.push_back(MipsOperand::CreateImm(Res, S, E, *this)); return false; @@ -2210,14 +2567,14 @@ const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr, default: report_fatal_error("unsupported reloc value"); } - return MCConstantExpr::Create(Val, getContext()); + return MCConstantExpr::create(Val, getContext()); } if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) { // It's a symbol, create a symbolic expression from the symbol. StringRef Symbol = MSRE->getSymbol().getName(); MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr); - Res = MCSymbolRefExpr::Create(Symbol, VK, getContext()); + Res = MCSymbolRefExpr::create(Symbol, VK, getContext()); return Res; } @@ -2226,17 +2583,17 @@ const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr, // Try to create target expression. if (MipsMCExpr::isSupportedBinaryExpr(VK, BE)) - return MipsMCExpr::Create(VK, Expr, getContext()); + return MipsMCExpr::create(VK, Expr, getContext()); const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr); const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr); - Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext()); + Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext()); return Res; } if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) { const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr); - Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext()); + Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext()); return Res; } // Just return the original expression. @@ -2271,7 +2628,7 @@ bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) { if (Tok.isNot(AsmToken::Identifier)) return true; - std::string Str = Tok.getIdentifier().str(); + std::string Str = Tok.getIdentifier(); Parser.Lex(); // Eat the identifier. // Now make an expression from the rest of the operand. @@ -2424,7 +2781,7 @@ MipsAsmParser::parseMemOperand(OperandVector &Operands) { Parser.Lex(); // Eat the ')' token. if (!IdVal) - IdVal = MCConstantExpr::Create(0, getContext()); + IdVal = MCConstantExpr::create(0, getContext()); // Replace the register operand with the memory operand. std::unique_ptr<MipsOperand> op( @@ -2435,10 +2792,10 @@ MipsAsmParser::parseMemOperand(OperandVector &Operands) { // Add the memory operand. if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) { int64_t Imm; - if (IdVal->EvaluateAsAbsolute(Imm)) - IdVal = MCConstantExpr::Create(Imm, getContext()); + if (IdVal->evaluateAsAbsolute(Imm)) + IdVal = MCConstantExpr::create(Imm, getContext()); else if (BE->getLHS()->getKind() != MCExpr::SymbolRef) - IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(), + IdVal = MCBinaryExpr::create(BE->getOpcode(), BE->getRHS(), BE->getLHS(), getContext()); } @@ -2448,7 +2805,7 @@ MipsAsmParser::parseMemOperand(OperandVector &Operands) { bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) { MCAsmParser &Parser = getParser(); - MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier()); + MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier()); if (Sym) { SMLoc S = Parser.getTok().getLoc(); const MCExpr *Expr; @@ -2655,7 +3012,7 @@ MipsAsmParser::parseInvNum(OperandVector &Operands) { int64_t Val = MCE->getValue(); SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1); Operands.push_back(MipsOperand::CreateImm( - MCConstantExpr::Create(0 - Val, getContext()), S, E, *this)); + MCConstantExpr::create(0 - Val, getContext()), S, E, *this)); return MatchOperand_Success; } @@ -2679,7 +3036,7 @@ MipsAsmParser::parseLSAImm(OperandVector &Operands) { return MatchOperand_ParseFail; int64_t Val; - if (!Expr->EvaluateAsAbsolute(Val)) { + if (!Expr->evaluateAsAbsolute(Val)) { Error(S, "expected immediate value"); return MatchOperand_ParseFail; } @@ -2791,6 +3148,45 @@ MipsAsmParser::parseRegisterPair(OperandVector &Operands) { return MatchOperand_Success; } +MipsAsmParser::OperandMatchResultTy +MipsAsmParser::parseMovePRegPair(OperandVector &Operands) { + MCAsmParser &Parser = getParser(); + SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands; + SmallVector<unsigned, 10> Regs; + + if (Parser.getTok().isNot(AsmToken::Dollar)) + return MatchOperand_ParseFail; + + SMLoc S = Parser.getTok().getLoc(); + + if (parseAnyRegister(TmpOperands) != MatchOperand_Success) + return MatchOperand_ParseFail; + + MipsOperand *Reg = &static_cast<MipsOperand &>(*TmpOperands.back()); + unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg(); + Regs.push_back(RegNo); + + SMLoc E = Parser.getTok().getLoc(); + if (Parser.getTok().isNot(AsmToken::Comma)) { + Error(E, "',' expected"); + return MatchOperand_ParseFail; + } + + // Remove comma. + Parser.Lex(); + + if (parseAnyRegister(TmpOperands) != MatchOperand_Success) + return MatchOperand_ParseFail; + + Reg = &static_cast<MipsOperand &>(*TmpOperands.back()); + RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg(); + Regs.push_back(RegNo); + + Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this)); + + return MatchOperand_Success; +} + MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) { MCSymbolRefExpr::VariantKind VK = @@ -2953,67 +3349,84 @@ bool MipsAsmParser::reportParseError(SMLoc Loc, Twine ErrorMsg) { bool MipsAsmParser::parseSetNoAtDirective() { MCAsmParser &Parser = getParser(); // Line should look like: ".set noat". - // set at reg to 0. - AssemblerOptions.back()->setATReg(0); - // eat noat - Parser.Lex(); + + // Set the $at register to $0. + AssemblerOptions.back()->setATRegIndex(0); + + Parser.Lex(); // Eat "noat". + // If this is not the end of the statement, report an error. if (getLexer().isNot(AsmToken::EndOfStatement)) { reportParseError("unexpected token, expected end of statement"); return false; } + + getTargetStreamer().emitDirectiveSetNoAt(); Parser.Lex(); // Consume the EndOfStatement. return false; } bool MipsAsmParser::parseSetAtDirective() { + // Line can be: ".set at", which sets $at to $1 + // or ".set at=$reg", which sets $at to $reg. MCAsmParser &Parser = getParser(); - // Line can be .set at - defaults to $1 - // or .set at=$reg - int AtRegNo; - getParser().Lex(); + Parser.Lex(); // Eat "at". + if (getLexer().is(AsmToken::EndOfStatement)) { - AssemblerOptions.back()->setATReg(1); + // No register was specified, so we set $at to $1. + AssemblerOptions.back()->setATRegIndex(1); + + getTargetStreamer().emitDirectiveSetAt(); Parser.Lex(); // Consume the EndOfStatement. return false; - } else if (getLexer().is(AsmToken::Equal)) { - getParser().Lex(); // Eat the '='. - if (getLexer().isNot(AsmToken::Dollar)) { - reportParseError("unexpected token, expected dollar sign '$'"); + } + + if (getLexer().isNot(AsmToken::Equal)) { + reportParseError("unexpected token, expected equals sign"); + return false; + } + Parser.Lex(); // Eat "=". + + if (getLexer().isNot(AsmToken::Dollar)) { + if (getLexer().is(AsmToken::EndOfStatement)) { + reportParseError("no register specified"); return false; - } - Parser.Lex(); // Eat the '$'. - const AsmToken &Reg = Parser.getTok(); - if (Reg.is(AsmToken::Identifier)) { - AtRegNo = matchCPURegisterName(Reg.getIdentifier()); - } else if (Reg.is(AsmToken::Integer)) { - AtRegNo = Reg.getIntVal(); } else { - reportParseError("unexpected token, expected identifier or integer"); - return false; - } - - if (AtRegNo < 0 || AtRegNo > 31) { - reportParseError("unexpected token in statement"); + reportParseError("unexpected token, expected dollar sign '$'"); return false; } + } + Parser.Lex(); // Eat "$". - if (!AssemblerOptions.back()->setATReg(AtRegNo)) { - reportParseError("invalid register"); - return false; - } - getParser().Lex(); // Eat the register. + // Find out what "reg" is. + unsigned AtRegNo; + const AsmToken &Reg = Parser.getTok(); + if (Reg.is(AsmToken::Identifier)) { + AtRegNo = matchCPURegisterName(Reg.getIdentifier()); + } else if (Reg.is(AsmToken::Integer)) { + AtRegNo = Reg.getIntVal(); + } else { + reportParseError("unexpected token, expected identifier or integer"); + return false; + } - if (getLexer().isNot(AsmToken::EndOfStatement)) { - reportParseError("unexpected token, expected end of statement"); - return false; - } - Parser.Lex(); // Consume the EndOfStatement. + // Check if $reg is a valid register. If it is, set $at to $reg. + if (!AssemblerOptions.back()->setATRegIndex(AtRegNo)) { + reportParseError("invalid register"); return false; - } else { - reportParseError("unexpected token in statement"); + } + Parser.Lex(); // Eat "reg". + + // If this is not the end of the statement, report an error. + if (getLexer().isNot(AsmToken::EndOfStatement)) { + reportParseError("unexpected token, expected end of statement"); return false; } + + getTargetStreamer().emitDirectiveSetAtWithArg(AtRegNo); + + Parser.Lex(); // Consume the EndOfStatement. + return false; } bool MipsAsmParser::parseSetReorderDirective() { @@ -3053,6 +3466,7 @@ bool MipsAsmParser::parseSetMacroDirective() { return false; } AssemblerOptions.back()->setMacro(); + getTargetStreamer().emitDirectiveSetMacro(); Parser.Lex(); // Consume the EndOfStatement. return false; } @@ -3070,6 +3484,7 @@ bool MipsAsmParser::parseSetNoMacroDirective() { return false; } AssemblerOptions.back()->setNoMacro(); + getTargetStreamer().emitDirectiveSetNoMacro(); Parser.Lex(); // Consume the EndOfStatement. return false; } @@ -3188,7 +3603,9 @@ bool MipsAsmParser::parseSetPopDirective() { return reportParseError(Loc, ".set pop with no .set push"); AssemblerOptions.pop_back(); - setAvailableFeatures(AssemblerOptions.back()->getFeatures()); + setAvailableFeatures( + ComputeAvailableFeatures(AssemblerOptions.back()->getFeatures())); + STI.setFeatureBits(AssemblerOptions.back()->getFeatures()); getTargetStreamer().emitDirectiveSetPop(); return false; @@ -3208,6 +3625,28 @@ bool MipsAsmParser::parseSetPushDirective() { return false; } +bool MipsAsmParser::parseSetSoftFloatDirective() { + MCAsmParser &Parser = getParser(); + Parser.Lex(); + if (getLexer().isNot(AsmToken::EndOfStatement)) + return reportParseError("unexpected token, expected end of statement"); + + setFeatureBits(Mips::FeatureSoftFloat, "soft-float"); + getTargetStreamer().emitDirectiveSetSoftFloat(); + return false; +} + +bool MipsAsmParser::parseSetHardFloatDirective() { + MCAsmParser &Parser = getParser(); + Parser.Lex(); + if (getLexer().isNot(AsmToken::EndOfStatement)) + return reportParseError("unexpected token, expected end of statement"); + + clearFeatureBits(Mips::FeatureSoftFloat, "soft-float"); + getTargetStreamer().emitDirectiveSetHardFloat(); + return false; +} + bool MipsAsmParser::parseSetAssignment() { StringRef Name; const MCExpr *Value; @@ -3223,11 +3662,7 @@ bool MipsAsmParser::parseSetAssignment() { if (Parser.parseExpression(Value)) return reportParseError("expected valid expression after comma"); - // Check if the Name already exists as a symbol. - MCSymbol *Sym = getContext().LookupSymbol(Name); - if (Sym) - return reportParseError("symbol already defined"); - Sym = getContext().GetOrCreateSymbol(Name); + MCSymbol *Sym = getContext().getOrCreateSymbol(Name); Sym->setVariableValue(Value); return false; @@ -3240,7 +3675,9 @@ bool MipsAsmParser::parseSetMips0Directive() { return reportParseError("unexpected token, expected end of statement"); // Reset assembler options to their initial values. - setAvailableFeatures(AssemblerOptions.front()->getFeatures()); + setAvailableFeatures( + ComputeAvailableFeatures(AssemblerOptions.front()->getFeatures())); + STI.setFeatureBits(AssemblerOptions.front()->getFeatures()); AssemblerOptions.back()->setFeatures(AssemblerOptions.front()->getFeatures()); getTargetStreamer().emitDirectiveSetMips0(); @@ -3267,9 +3704,13 @@ bool MipsAsmParser::parseSetArchDirective() { .Case("mips5", "mips5") .Case("mips32", "mips32") .Case("mips32r2", "mips32r2") + .Case("mips32r3", "mips32r3") + .Case("mips32r5", "mips32r5") .Case("mips32r6", "mips32r6") .Case("mips64", "mips64") .Case("mips64r2", "mips64r2") + .Case("mips64r3", "mips64r3") + .Case("mips64r5", "mips64r5") .Case("mips64r6", "mips64r6") .Case("cnmips", "cnmips") .Case("r4000", "mips3") // This is an implementation of Mips3. @@ -3327,6 +3768,14 @@ bool MipsAsmParser::parseSetFeature(uint64_t Feature) { selectArch("mips32r2"); getTargetStreamer().emitDirectiveSetMips32R2(); break; + case Mips::FeatureMips32r3: + selectArch("mips32r3"); + getTargetStreamer().emitDirectiveSetMips32R3(); + break; + case Mips::FeatureMips32r5: + selectArch("mips32r5"); + getTargetStreamer().emitDirectiveSetMips32R5(); + break; case Mips::FeatureMips32r6: selectArch("mips32r6"); getTargetStreamer().emitDirectiveSetMips32R6(); @@ -3339,6 +3788,14 @@ bool MipsAsmParser::parseSetFeature(uint64_t Feature) { selectArch("mips64r2"); getTargetStreamer().emitDirectiveSetMips64R2(); break; + case Mips::FeatureMips64r3: + selectArch("mips64r3"); + getTargetStreamer().emitDirectiveSetMips64R3(); + break; + case Mips::FeatureMips64r5: + selectArch("mips64r5"); + getTargetStreamer().emitDirectiveSetMips64R5(); + break; case Mips::FeatureMips64r6: selectArch("mips64r6"); getTargetStreamer().emitDirectiveSetMips64R6(); @@ -3443,12 +3900,20 @@ bool MipsAsmParser::parseDirectiveCPSetup() { if (!eatComma("unexpected token, expected comma")) return true; - StringRef Name; - if (Parser.parseIdentifier(Name)) - reportParseError("expected identifier"); - MCSymbol *Sym = getContext().GetOrCreateSymbol(Name); + const MCExpr *Expr; + if (Parser.parseExpression(Expr)) { + reportParseError("expected expression"); + return false; + } - getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg); + if (Expr->getKind() != MCExpr::SymbolRef) { + reportParseError("expected symbol"); + return false; + } + const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr); + + getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, Ref->getSymbol(), + SaveIsReg); return false; } @@ -3524,12 +3989,20 @@ bool MipsAsmParser::parseDirectiveSet() { return parseSetFeature(Mips::FeatureMips32); } else if (Tok.getString() == "mips32r2") { return parseSetFeature(Mips::FeatureMips32r2); + } else if (Tok.getString() == "mips32r3") { + return parseSetFeature(Mips::FeatureMips32r3); + } else if (Tok.getString() == "mips32r5") { + return parseSetFeature(Mips::FeatureMips32r5); } else if (Tok.getString() == "mips32r6") { return parseSetFeature(Mips::FeatureMips32r6); } else if (Tok.getString() == "mips64") { return parseSetFeature(Mips::FeatureMips64); } else if (Tok.getString() == "mips64r2") { return parseSetFeature(Mips::FeatureMips64r2); + } else if (Tok.getString() == "mips64r3") { + return parseSetFeature(Mips::FeatureMips64r3); + } else if (Tok.getString() == "mips64r5") { + return parseSetFeature(Mips::FeatureMips64r5); } else if (Tok.getString() == "mips64r6") { return parseSetFeature(Mips::FeatureMips64r6); } else if (Tok.getString() == "dsp") { @@ -3540,6 +4013,10 @@ bool MipsAsmParser::parseDirectiveSet() { return parseSetMsaDirective(); } else if (Tok.getString() == "nomsa") { return parseSetNoMsaDirective(); + } else if (Tok.getString() == "softfloat") { + return parseSetSoftFloatDirective(); + } else if (Tok.getString() == "hardfloat") { + return parseSetHardFloatDirective(); } else { // It is just an identifier, look for an assignment. parseSetAssignment(); @@ -3652,6 +4129,23 @@ bool MipsAsmParser::parseDirectiveOption() { return false; } +/// parseInsnDirective +/// ::= .insn +bool MipsAsmParser::parseInsnDirective() { + // If this is not the end of the statement, report an error. + if (getLexer().isNot(AsmToken::EndOfStatement)) { + reportParseError("unexpected token, expected end of statement"); + return false; + } + + // The actual label marking happens in + // MipsELFStreamer::createPendingLabelRelocs(). + getTargetStreamer().emitDirectiveInsn(); + + getParser().Lex(); // Eat EndOfStatement token. + return false; +} + /// parseDirectiveModule /// ::= .module oddspreg /// ::= .module nooddspreg @@ -3824,7 +4318,7 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) { reportParseError("expected number after comma"); return false; } - if (!DummyNumber->EvaluateAsAbsolute(DummyNumberVal)) { + if (!DummyNumber->evaluateAsAbsolute(DummyNumberVal)) { reportParseError("expected an absolute expression after comma"); return false; } @@ -3836,7 +4330,7 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) { return false; } - MCSymbol *Sym = getContext().GetOrCreateSymbol(SymbolName); + MCSymbol *Sym = getContext().getOrCreateSymbol(SymbolName); getTargetStreamer().emitDirectiveEnt(*Sym); CurrentFn = Sym; @@ -3904,7 +4398,7 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) { return false; } - if (!FrameSize->EvaluateAsAbsolute(FrameSizeVal)) { + if (!FrameSize->evaluateAsAbsolute(FrameSizeVal)) { reportParseError("frame size not an absolute expression"); return false; } @@ -3965,7 +4459,7 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) { return false; } - if (!BitMask->EvaluateAsAbsolute(BitMaskVal)) { + if (!BitMask->evaluateAsAbsolute(BitMaskVal)) { reportParseError("bitmask not an absolute expression"); return false; } @@ -3986,7 +4480,7 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) { return false; } - if (!FrameOffset->EvaluateAsAbsolute(FrameOffsetVal)) { + if (!FrameOffset->evaluateAsAbsolute(FrameOffsetVal)) { reportParseError("frame offset not an absolute expression"); return false; } @@ -4042,9 +4536,28 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) { if (IDVal == ".module") return parseDirectiveModule(); + if (IDVal == ".llvm_internal_mips_reallow_module_directive") + return parseInternalDirectiveReallowModule(); + + if (IDVal == ".insn") + return parseInsnDirective(); + return true; } +bool MipsAsmParser::parseInternalDirectiveReallowModule() { + // If this is not the end of the statement, report an error. + if (getLexer().isNot(AsmToken::EndOfStatement)) { + reportParseError("unexpected token, expected end of statement"); + return false; + } + + getTargetStreamer().reallowModuleDirective(); + + getParser().Lex(); // Eat EndOfStatement token. + return false; +} + extern "C" void LLVMInitializeMipsAsmParser() { RegisterMCAsmParser<MipsAsmParser> X(TheMipsTarget); RegisterMCAsmParser<MipsAsmParser> Y(TheMipselTarget); diff --git a/contrib/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/contrib/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp index d42b948..c8629b5 100644 --- a/contrib/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ b/contrib/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -30,41 +30,24 @@ typedef MCDisassembler::DecodeStatus DecodeStatus; namespace { -/// A disasembler class for Mips. -class MipsDisassemblerBase : public MCDisassembler { +class MipsDisassembler : public MCDisassembler { + bool IsMicroMips; + bool IsBigEndian; public: - MipsDisassemblerBase(const MCSubtargetInfo &STI, MCContext &Ctx, - bool IsBigEndian) + MipsDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx, bool IsBigEndian) : MCDisassembler(STI, Ctx), - IsGP64Bit(STI.getFeatureBits() & Mips::FeatureGP64Bit), + IsMicroMips(STI.getFeatureBits()[Mips::FeatureMicroMips]), IsBigEndian(IsBigEndian) {} - virtual ~MipsDisassemblerBase() {} - - bool isGP64Bit() const { return IsGP64Bit; } - -private: - bool IsGP64Bit; -protected: - bool IsBigEndian; -}; - -/// A disasembler class for Mips32. -class MipsDisassembler : public MipsDisassemblerBase { - bool IsMicroMips; -public: - MipsDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx, bool bigEndian) - : MipsDisassemblerBase(STI, Ctx, bigEndian) { - IsMicroMips = STI.getFeatureBits() & Mips::FeatureMicroMips; - } - - bool hasMips3() const { return STI.getFeatureBits() & Mips::FeatureMips3; } - bool hasMips32() const { return STI.getFeatureBits() & Mips::FeatureMips32; } + bool hasMips3() const { return STI.getFeatureBits()[Mips::FeatureMips3]; } + bool hasMips32() const { return STI.getFeatureBits()[Mips::FeatureMips32]; } bool hasMips32r6() const { - return STI.getFeatureBits() & Mips::FeatureMips32r6; + return STI.getFeatureBits()[Mips::FeatureMips32r6]; } - bool isGP64() const { return STI.getFeatureBits() & Mips::FeatureGP64Bit; } + bool isGP64() const { return STI.getFeatureBits()[Mips::FeatureGP64Bit]; } + + bool hasCnMips() const { return STI.getFeatureBits()[Mips::FeatureCnMips]; } bool hasCOP3() const { // Only present in MIPS-I and MIPS-II @@ -77,19 +60,6 @@ public: raw_ostream &CStream) const override; }; -/// A disasembler class for Mips64. -class Mips64Disassembler : public MipsDisassemblerBase { -public: - Mips64Disassembler(const MCSubtargetInfo &STI, MCContext &Ctx, - bool bigEndian) : - MipsDisassemblerBase(STI, Ctx, bigEndian) {} - - DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size, - ArrayRef<uint8_t> Bytes, uint64_t Address, - raw_ostream &VStream, - raw_ostream &CStream) const override; -}; - } // end anonymous namespace // Forward declare these because the autogenerated code will reference them. @@ -114,6 +84,11 @@ static DecodeStatus DecodeGPRMM16ZeroRegisterClass(MCInst &Inst, uint64_t Address, const void *Decoder); +static DecodeStatus DecodeGPRMM16MovePRegisterClass(MCInst &Inst, + unsigned RegNo, + uint64_t Address, + const void *Decoder); + static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, @@ -235,6 +210,13 @@ static DecodeStatus DecodeBranchTarget7MM(MCInst &Inst, uint64_t Address, const void *Decoder); +// DecodeBranchTarget10MM - Decode microMIPS branch offset, which is +// shifted left by 1 bit. +static DecodeStatus DecodeBranchTarget10MM(MCInst &Inst, + unsigned Offset, + uint64_t Address, + const void *Decoder); + // DecodeBranchTargetMM - Decode microMIPS branch offset, which is // shifted left by 1 bit. static DecodeStatus DecodeBranchTargetMM(MCInst &Inst, @@ -287,6 +269,16 @@ static DecodeStatus DecodeMemMMSPImm5Lsl2(MCInst &Inst, uint64_t Address, const void *Decoder); +static DecodeStatus DecodeMemMMGPImm7Lsl2(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder); + +static DecodeStatus DecodeMemMMReglistImm4Lsl2(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder); + static DecodeStatus DecodeMemMMImm12(MCInst &Inst, unsigned Insn, uint64_t Address, @@ -375,6 +367,9 @@ static DecodeStatus DecodeANDI16Imm(MCInst &Inst, unsigned Insn, static DecodeStatus DecodeUImm5lsl2(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder); +static DecodeStatus DecodeSimm23Lsl2(MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder); + /// INSVE_[BHWD] have an implicit operand that the generated decoder doesn't /// handle. template <typename InsnType> @@ -419,6 +414,10 @@ static DecodeStatus DecodeRegListOperand16(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder); +static DecodeStatus DecodeMovePRegPair(MCInst &Inst, unsigned Insn, + uint64_t Address, + const void *Decoder); + namespace llvm { extern Target TheMipselTarget, TheMipsTarget, TheMips64Target, TheMips64elTarget; @@ -438,20 +437,6 @@ static MCDisassembler *createMipselDisassembler( return new MipsDisassembler(STI, Ctx, false); } -static MCDisassembler *createMips64Disassembler( - const Target &T, - const MCSubtargetInfo &STI, - MCContext &Ctx) { - return new Mips64Disassembler(STI, Ctx, true); -} - -static MCDisassembler *createMips64elDisassembler( - const Target &T, - const MCSubtargetInfo &STI, - MCContext &Ctx) { - return new Mips64Disassembler(STI, Ctx, false); -} - extern "C" void LLVMInitializeMipsDisassembler() { // Register the disassembler. TargetRegistry::RegisterMCDisassembler(TheMipsTarget, @@ -459,15 +444,15 @@ extern "C" void LLVMInitializeMipsDisassembler() { TargetRegistry::RegisterMCDisassembler(TheMipselTarget, createMipselDisassembler); TargetRegistry::RegisterMCDisassembler(TheMips64Target, - createMips64Disassembler); + createMipsDisassembler); TargetRegistry::RegisterMCDisassembler(TheMips64elTarget, - createMips64elDisassembler); + createMipselDisassembler); } #include "MipsGenDisassemblerTables.inc" static unsigned getReg(const void *D, unsigned RC, unsigned RegNo) { - const MipsDisassemblerBase *Dis = static_cast<const MipsDisassemblerBase*>(D); + const MipsDisassembler *Dis = static_cast<const MipsDisassembler*>(D); const MCRegisterInfo *RegInfo = Dis->getContext().getRegisterInfo(); return *(RegInfo->getRegClass(RC).begin() + RegNo); } @@ -507,13 +492,13 @@ static DecodeStatus DecodeINSVE_DF(MCInst &MI, InsnType insn, uint64_t Address, return MCDisassembler::Fail; // $n tmp = fieldFromInstruction(insn, 16, NSize); - MI.addOperand(MCOperand::CreateImm(tmp)); + MI.addOperand(MCOperand::createImm(tmp)); // $ws tmp = fieldFromInstruction(insn, 11, 5); if (RegDecoder(MI, tmp, Address, Decoder) == MCDisassembler::Fail) return MCDisassembler::Fail; // $n2 - MI.addOperand(MCOperand::CreateImm(0)); + MI.addOperand(MCOperand::createImm(0)); return MCDisassembler::Success; } @@ -547,12 +532,12 @@ static DecodeStatus DecodeAddiGroupBranch(MCInst &MI, InsnType insn, MI.setOpcode(Mips::BEQZALC); if (HasRs) - MI.addOperand(MCOperand::CreateReg(getReg(Decoder, Mips::GPR32RegClassID, + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, Rs))); - MI.addOperand(MCOperand::CreateReg(getReg(Decoder, Mips::GPR32RegClassID, + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, Rt))); - MI.addOperand(MCOperand::CreateImm(Imm)); + MI.addOperand(MCOperand::createImm(Imm)); return MCDisassembler::Success; } @@ -586,12 +571,12 @@ static DecodeStatus DecodeDaddiGroupBranch(MCInst &MI, InsnType insn, MI.setOpcode(Mips::BNEZALC); if (HasRs) - MI.addOperand(MCOperand::CreateReg(getReg(Decoder, Mips::GPR32RegClassID, + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, Rs))); - MI.addOperand(MCOperand::CreateReg(getReg(Decoder, Mips::GPR32RegClassID, + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, Rt))); - MI.addOperand(MCOperand::CreateImm(Imm)); + MI.addOperand(MCOperand::createImm(Imm)); return MCDisassembler::Success; } @@ -628,13 +613,13 @@ static DecodeStatus DecodeBlezlGroupBranch(MCInst &MI, InsnType insn, } if (HasRs) - MI.addOperand(MCOperand::CreateReg(getReg(Decoder, Mips::GPR32RegClassID, + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, Rs))); - MI.addOperand(MCOperand::CreateReg(getReg(Decoder, Mips::GPR32RegClassID, + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, Rt))); - MI.addOperand(MCOperand::CreateImm(Imm)); + MI.addOperand(MCOperand::createImm(Imm)); return MCDisassembler::Success; } @@ -672,13 +657,13 @@ static DecodeStatus DecodeBgtzlGroupBranch(MCInst &MI, InsnType insn, } if (HasRs) - MI.addOperand(MCOperand::CreateReg(getReg(Decoder, Mips::GPR32RegClassID, + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, Rs))); - MI.addOperand(MCOperand::CreateReg(getReg(Decoder, Mips::GPR32RegClassID, + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, Rt))); - MI.addOperand(MCOperand::CreateImm(Imm)); + MI.addOperand(MCOperand::createImm(Imm)); return MCDisassembler::Success; } @@ -720,14 +705,14 @@ static DecodeStatus DecodeBgtzGroupBranch(MCInst &MI, InsnType insn, } if (HasRs) - MI.addOperand(MCOperand::CreateReg(getReg(Decoder, Mips::GPR32RegClassID, + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, Rs))); if (HasRt) - MI.addOperand(MCOperand::CreateReg(getReg(Decoder, Mips::GPR32RegClassID, + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, Rt))); - MI.addOperand(MCOperand::CreateImm(Imm)); + MI.addOperand(MCOperand::createImm(Imm)); return MCDisassembler::Success; } @@ -764,12 +749,12 @@ static DecodeStatus DecodeBlezGroupBranch(MCInst &MI, InsnType insn, } if (HasRs) - MI.addOperand(MCOperand::CreateReg(getReg(Decoder, Mips::GPR32RegClassID, + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, Rs))); - MI.addOperand(MCOperand::CreateReg(getReg(Decoder, Mips::GPR32RegClassID, + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, Rt))); - MI.addOperand(MCOperand::CreateImm(Imm)); + MI.addOperand(MCOperand::createImm(Imm)); return MCDisassembler::Success; } @@ -854,10 +839,17 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, if (Result == MCDisassembler::Fail) return MCDisassembler::Fail; - DEBUG(dbgs() << "Trying MicroMips32 table (32-bit instructions):\n"); - // Calling the auto-generated decoder function. - Result = decodeInstruction(DecoderTableMicroMips32, Instr, Insn, Address, - this, STI); + if (hasMips32r6()) { + DEBUG(dbgs() << "Trying MicroMips32r632 table (32-bit instructions):\n"); + // Calling the auto-generated decoder function. + Result = decodeInstruction(DecoderTableMicroMips32r632, Instr, Insn, Address, + this, STI); + } else { + DEBUG(dbgs() << "Trying MicroMips32 table (32-bit instructions):\n"); + // Calling the auto-generated decoder function. + Result = decodeInstruction(DecoderTableMicroMips32, Instr, Insn, Address, + this, STI); + } if (Result != MCDisassembler::Fail) { Size = 4; return Result; @@ -899,39 +891,29 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, } } - DEBUG(dbgs() << "Trying Mips table (32-bit opcodes):\n"); - // Calling the auto-generated decoder function. - Result = - decodeInstruction(DecoderTableMips32, Instr, Insn, Address, this, STI); - if (Result != MCDisassembler::Fail) { - Size = 4; - return Result; + if (hasCnMips()) { + DEBUG(dbgs() << "Trying CnMips table (32-bit opcodes):\n"); + Result = decodeInstruction(DecoderTableCnMips32, Instr, Insn, + Address, this, STI); + if (Result != MCDisassembler::Fail) { + Size = 4; + return Result; + } } - return MCDisassembler::Fail; -} - -DecodeStatus Mips64Disassembler::getInstruction(MCInst &Instr, uint64_t &Size, - ArrayRef<uint8_t> Bytes, - uint64_t Address, - raw_ostream &VStream, - raw_ostream &CStream) const { - uint32_t Insn; - - DecodeStatus Result = - readInstruction32(Bytes, Address, Size, Insn, IsBigEndian, false); - if (Result == MCDisassembler::Fail) - return MCDisassembler::Fail; + if (isGP64()) { + DEBUG(dbgs() << "Trying Mips64 (GPR64) table (32-bit opcodes):\n"); + Result = decodeInstruction(DecoderTableMips6432, Instr, Insn, + Address, this, STI); + if (Result != MCDisassembler::Fail) { + Size = 4; + return Result; + } + } + DEBUG(dbgs() << "Trying Mips table (32-bit opcodes):\n"); // Calling the auto-generated decoder function. Result = - decodeInstruction(DecoderTableMips6432, Instr, Insn, Address, this, STI); - if (Result != MCDisassembler::Fail) { - Size = 4; - return Result; - } - // If we fail to decode in Mips64 decoder space we can try in Mips32 - Result = decodeInstruction(DecoderTableMips32, Instr, Insn, Address, this, STI); if (Result != MCDisassembler::Fail) { Size = 4; @@ -959,7 +941,7 @@ static DecodeStatus DecodeGPR64RegisterClass(MCInst &Inst, return MCDisassembler::Fail; unsigned Reg = getReg(Decoder, Mips::GPR64RegClassID, RegNo); - Inst.addOperand(MCOperand::CreateReg(Reg)); + Inst.addOperand(MCOperand::createReg(Reg)); return MCDisassembler::Success; } @@ -970,7 +952,7 @@ static DecodeStatus DecodeGPRMM16RegisterClass(MCInst &Inst, if (RegNo > 7) return MCDisassembler::Fail; unsigned Reg = getReg(Decoder, Mips::GPRMM16RegClassID, RegNo); - Inst.addOperand(MCOperand::CreateReg(Reg)); + Inst.addOperand(MCOperand::createReg(Reg)); return MCDisassembler::Success; } @@ -981,7 +963,18 @@ static DecodeStatus DecodeGPRMM16ZeroRegisterClass(MCInst &Inst, if (RegNo > 7) return MCDisassembler::Fail; unsigned Reg = getReg(Decoder, Mips::GPRMM16ZeroRegClassID, RegNo); - Inst.addOperand(MCOperand::CreateReg(Reg)); + Inst.addOperand(MCOperand::createReg(Reg)); + return MCDisassembler::Success; +} + +static DecodeStatus DecodeGPRMM16MovePRegisterClass(MCInst &Inst, + unsigned RegNo, + uint64_t Address, + const void *Decoder) { + if (RegNo > 7) + return MCDisassembler::Fail; + unsigned Reg = getReg(Decoder, Mips::GPRMM16MovePRegClassID, RegNo); + Inst.addOperand(MCOperand::createReg(Reg)); return MCDisassembler::Success; } @@ -992,7 +985,7 @@ static DecodeStatus DecodeGPR32RegisterClass(MCInst &Inst, if (RegNo > 31) return MCDisassembler::Fail; unsigned Reg = getReg(Decoder, Mips::GPR32RegClassID, RegNo); - Inst.addOperand(MCOperand::CreateReg(Reg)); + Inst.addOperand(MCOperand::createReg(Reg)); return MCDisassembler::Success; } @@ -1000,7 +993,7 @@ static DecodeStatus DecodePtrRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decoder) { - if (static_cast<const MipsDisassembler *>(Decoder)->isGP64Bit()) + if (static_cast<const MipsDisassembler *>(Decoder)->isGP64()) return DecodeGPR64RegisterClass(Inst, RegNo, Address, Decoder); return DecodeGPR32RegisterClass(Inst, RegNo, Address, Decoder); @@ -1021,7 +1014,7 @@ static DecodeStatus DecodeFGR64RegisterClass(MCInst &Inst, return MCDisassembler::Fail; unsigned Reg = getReg(Decoder, Mips::FGR64RegClassID, RegNo); - Inst.addOperand(MCOperand::CreateReg(Reg)); + Inst.addOperand(MCOperand::createReg(Reg)); return MCDisassembler::Success; } @@ -1033,7 +1026,7 @@ static DecodeStatus DecodeFGR32RegisterClass(MCInst &Inst, return MCDisassembler::Fail; unsigned Reg = getReg(Decoder, Mips::FGR32RegClassID, RegNo); - Inst.addOperand(MCOperand::CreateReg(Reg)); + Inst.addOperand(MCOperand::createReg(Reg)); return MCDisassembler::Success; } @@ -1044,7 +1037,7 @@ static DecodeStatus DecodeCCRRegisterClass(MCInst &Inst, if (RegNo > 31) return MCDisassembler::Fail; unsigned Reg = getReg(Decoder, Mips::CCRRegClassID, RegNo); - Inst.addOperand(MCOperand::CreateReg(Reg)); + Inst.addOperand(MCOperand::createReg(Reg)); return MCDisassembler::Success; } @@ -1055,7 +1048,7 @@ static DecodeStatus DecodeFCCRegisterClass(MCInst &Inst, if (RegNo > 7) return MCDisassembler::Fail; unsigned Reg = getReg(Decoder, Mips::FCCRegClassID, RegNo); - Inst.addOperand(MCOperand::CreateReg(Reg)); + Inst.addOperand(MCOperand::createReg(Reg)); return MCDisassembler::Success; } @@ -1066,7 +1059,7 @@ static DecodeStatus DecodeFGRCCRegisterClass(MCInst &Inst, unsigned RegNo, return MCDisassembler::Fail; unsigned Reg = getReg(Decoder, Mips::FGRCCRegClassID, RegNo); - Inst.addOperand(MCOperand::CreateReg(Reg)); + Inst.addOperand(MCOperand::createReg(Reg)); return MCDisassembler::Success; } @@ -1083,12 +1076,12 @@ static DecodeStatus DecodeMem(MCInst &Inst, if(Inst.getOpcode() == Mips::SC || Inst.getOpcode() == Mips::SCD){ - Inst.addOperand(MCOperand::CreateReg(Reg)); + Inst.addOperand(MCOperand::createReg(Reg)); } - Inst.addOperand(MCOperand::CreateReg(Reg)); - Inst.addOperand(MCOperand::CreateReg(Base)); - Inst.addOperand(MCOperand::CreateImm(Offset)); + Inst.addOperand(MCOperand::createReg(Reg)); + Inst.addOperand(MCOperand::createReg(Base)); + Inst.addOperand(MCOperand::createImm(Offset)); return MCDisassembler::Success; } @@ -1103,9 +1096,9 @@ static DecodeStatus DecodeCacheOp(MCInst &Inst, Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - Inst.addOperand(MCOperand::CreateReg(Base)); - Inst.addOperand(MCOperand::CreateImm(Offset)); - Inst.addOperand(MCOperand::CreateImm(Hint)); + Inst.addOperand(MCOperand::createReg(Base)); + Inst.addOperand(MCOperand::createImm(Offset)); + Inst.addOperand(MCOperand::createImm(Hint)); return MCDisassembler::Success; } @@ -1120,9 +1113,9 @@ static DecodeStatus DecodeCacheOpMM(MCInst &Inst, Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - Inst.addOperand(MCOperand::CreateReg(Base)); - Inst.addOperand(MCOperand::CreateImm(Offset)); - Inst.addOperand(MCOperand::CreateImm(Hint)); + Inst.addOperand(MCOperand::createReg(Base)); + Inst.addOperand(MCOperand::createImm(Offset)); + Inst.addOperand(MCOperand::createImm(Hint)); return MCDisassembler::Success; } @@ -1137,9 +1130,9 @@ static DecodeStatus DecodeCacheOpR6(MCInst &Inst, Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - Inst.addOperand(MCOperand::CreateReg(Base)); - Inst.addOperand(MCOperand::CreateImm(Offset)); - Inst.addOperand(MCOperand::CreateImm(Hint)); + Inst.addOperand(MCOperand::createReg(Base)); + Inst.addOperand(MCOperand::createImm(Offset)); + Inst.addOperand(MCOperand::createImm(Hint)); return MCDisassembler::Success; } @@ -1153,8 +1146,8 @@ static DecodeStatus DecodeSyncI(MCInst &Inst, Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - Inst.addOperand(MCOperand::CreateReg(Base)); - Inst.addOperand(MCOperand::CreateImm(Offset)); + Inst.addOperand(MCOperand::createReg(Base)); + Inst.addOperand(MCOperand::createImm(Offset)); return MCDisassembler::Success; } @@ -1168,8 +1161,8 @@ static DecodeStatus DecodeMSA128Mem(MCInst &Inst, unsigned Insn, Reg = getReg(Decoder, Mips::MSA128BRegClassID, Reg); Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - Inst.addOperand(MCOperand::CreateReg(Reg)); - Inst.addOperand(MCOperand::CreateReg(Base)); + Inst.addOperand(MCOperand::createReg(Reg)); + Inst.addOperand(MCOperand::createReg(Base)); // The immediate field of an LD/ST instruction is scaled which means it must // be multiplied (when decoding) by the size (in bytes) of the instructions' @@ -1186,19 +1179,19 @@ static DecodeStatus DecodeMSA128Mem(MCInst &Inst, unsigned Insn, break; case Mips::LD_B: case Mips::ST_B: - Inst.addOperand(MCOperand::CreateImm(Offset)); + Inst.addOperand(MCOperand::createImm(Offset)); break; case Mips::LD_H: case Mips::ST_H: - Inst.addOperand(MCOperand::CreateImm(Offset * 2)); + Inst.addOperand(MCOperand::createImm(Offset * 2)); break; case Mips::LD_W: case Mips::ST_W: - Inst.addOperand(MCOperand::CreateImm(Offset * 4)); + Inst.addOperand(MCOperand::createImm(Offset * 4)); break; case Mips::LD_D: case Mips::ST_D: - Inst.addOperand(MCOperand::CreateImm(Offset * 8)); + Inst.addOperand(MCOperand::createImm(Offset * 8)); break; } @@ -1237,20 +1230,20 @@ static DecodeStatus DecodeMemMMImm4(MCInst &Inst, switch (Inst.getOpcode()) { case Mips::LBU16_MM: if (Offset == 0xf) - Inst.addOperand(MCOperand::CreateImm(-1)); + Inst.addOperand(MCOperand::createImm(-1)); else - Inst.addOperand(MCOperand::CreateImm(Offset)); + Inst.addOperand(MCOperand::createImm(Offset)); break; case Mips::SB16_MM: - Inst.addOperand(MCOperand::CreateImm(Offset)); + Inst.addOperand(MCOperand::createImm(Offset)); break; case Mips::LHU16_MM: case Mips::SH16_MM: - Inst.addOperand(MCOperand::CreateImm(Offset << 1)); + Inst.addOperand(MCOperand::createImm(Offset << 1)); break; case Mips::LW16_MM: case Mips::SW16_MM: - Inst.addOperand(MCOperand::CreateImm(Offset << 2)); + Inst.addOperand(MCOperand::createImm(Offset << 2)); break; } @@ -1266,9 +1259,41 @@ static DecodeStatus DecodeMemMMSPImm5Lsl2(MCInst &Inst, Reg = getReg(Decoder, Mips::GPR32RegClassID, Reg); - Inst.addOperand(MCOperand::CreateReg(Reg)); - Inst.addOperand(MCOperand::CreateReg(Mips::SP)); - Inst.addOperand(MCOperand::CreateImm(Offset << 2)); + Inst.addOperand(MCOperand::createReg(Reg)); + Inst.addOperand(MCOperand::createReg(Mips::SP)); + Inst.addOperand(MCOperand::createImm(Offset << 2)); + + return MCDisassembler::Success; +} + +static DecodeStatus DecodeMemMMGPImm7Lsl2(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + unsigned Offset = Insn & 0x7F; + unsigned Reg = fieldFromInstruction(Insn, 7, 3); + + Reg = getReg(Decoder, Mips::GPR32RegClassID, Reg); + + Inst.addOperand(MCOperand::createReg(Reg)); + Inst.addOperand(MCOperand::createReg(Mips::GP)); + Inst.addOperand(MCOperand::createImm(Offset << 2)); + + return MCDisassembler::Success; +} + +static DecodeStatus DecodeMemMMReglistImm4Lsl2(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + int Offset = SignExtend32<4>(Insn & 0xf); + + if (DecodeRegListOperand16(Inst, Insn, Address, Decoder) + == MCDisassembler::Fail) + return MCDisassembler::Fail; + + Inst.addOperand(MCOperand::createReg(Mips::SP)); + Inst.addOperand(MCOperand::createImm(Offset << 2)); return MCDisassembler::Success; } @@ -1290,19 +1315,19 @@ static DecodeStatus DecodeMemMMImm12(MCInst &Inst, if (DecodeRegListOperand(Inst, Insn, Address, Decoder) == MCDisassembler::Fail) return MCDisassembler::Fail; - Inst.addOperand(MCOperand::CreateReg(Base)); - Inst.addOperand(MCOperand::CreateImm(Offset)); + Inst.addOperand(MCOperand::createReg(Base)); + Inst.addOperand(MCOperand::createImm(Offset)); break; case Mips::SC_MM: - Inst.addOperand(MCOperand::CreateReg(Reg)); + Inst.addOperand(MCOperand::createReg(Reg)); // fallthrough default: - Inst.addOperand(MCOperand::CreateReg(Reg)); + Inst.addOperand(MCOperand::createReg(Reg)); if (Inst.getOpcode() == Mips::LWP_MM || Inst.getOpcode() == Mips::SWP_MM) - Inst.addOperand(MCOperand::CreateReg(Reg+1)); + Inst.addOperand(MCOperand::createReg(Reg+1)); - Inst.addOperand(MCOperand::CreateReg(Base)); - Inst.addOperand(MCOperand::CreateImm(Offset)); + Inst.addOperand(MCOperand::createReg(Base)); + Inst.addOperand(MCOperand::createImm(Offset)); } return MCDisassembler::Success; @@ -1319,9 +1344,9 @@ static DecodeStatus DecodeMemMMImm16(MCInst &Inst, Reg = getReg(Decoder, Mips::GPR32RegClassID, Reg); Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - Inst.addOperand(MCOperand::CreateReg(Reg)); - Inst.addOperand(MCOperand::CreateReg(Base)); - Inst.addOperand(MCOperand::CreateImm(Offset)); + Inst.addOperand(MCOperand::createReg(Reg)); + Inst.addOperand(MCOperand::createReg(Base)); + Inst.addOperand(MCOperand::createImm(Offset)); return MCDisassembler::Success; } @@ -1337,9 +1362,9 @@ static DecodeStatus DecodeFMem(MCInst &Inst, Reg = getReg(Decoder, Mips::FGR64RegClassID, Reg); Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - Inst.addOperand(MCOperand::CreateReg(Reg)); - Inst.addOperand(MCOperand::CreateReg(Base)); - Inst.addOperand(MCOperand::CreateImm(Offset)); + Inst.addOperand(MCOperand::createReg(Reg)); + Inst.addOperand(MCOperand::createReg(Base)); + Inst.addOperand(MCOperand::createImm(Offset)); return MCDisassembler::Success; } @@ -1355,9 +1380,9 @@ static DecodeStatus DecodeFMem2(MCInst &Inst, Reg = getReg(Decoder, Mips::COP2RegClassID, Reg); Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - Inst.addOperand(MCOperand::CreateReg(Reg)); - Inst.addOperand(MCOperand::CreateReg(Base)); - Inst.addOperand(MCOperand::CreateImm(Offset)); + Inst.addOperand(MCOperand::createReg(Reg)); + Inst.addOperand(MCOperand::createReg(Base)); + Inst.addOperand(MCOperand::createImm(Offset)); return MCDisassembler::Success; } @@ -1373,9 +1398,9 @@ static DecodeStatus DecodeFMem3(MCInst &Inst, Reg = getReg(Decoder, Mips::COP3RegClassID, Reg); Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - Inst.addOperand(MCOperand::CreateReg(Reg)); - Inst.addOperand(MCOperand::CreateReg(Base)); - Inst.addOperand(MCOperand::CreateImm(Offset)); + Inst.addOperand(MCOperand::createReg(Reg)); + Inst.addOperand(MCOperand::createReg(Base)); + Inst.addOperand(MCOperand::createImm(Offset)); return MCDisassembler::Success; } @@ -1391,9 +1416,9 @@ static DecodeStatus DecodeFMemCop2R6(MCInst &Inst, Reg = getReg(Decoder, Mips::COP2RegClassID, Reg); Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - Inst.addOperand(MCOperand::CreateReg(Reg)); - Inst.addOperand(MCOperand::CreateReg(Base)); - Inst.addOperand(MCOperand::CreateImm(Offset)); + Inst.addOperand(MCOperand::createReg(Reg)); + Inst.addOperand(MCOperand::createReg(Base)); + Inst.addOperand(MCOperand::createImm(Offset)); return MCDisassembler::Success; } @@ -1409,12 +1434,12 @@ static DecodeStatus DecodeSpecial3LlSc(MCInst &Inst, Base = getReg(Decoder, Mips::GPR32RegClassID, Base); if(Inst.getOpcode() == Mips::SC_R6 || Inst.getOpcode() == Mips::SCD_R6){ - Inst.addOperand(MCOperand::CreateReg(Rt)); + Inst.addOperand(MCOperand::createReg(Rt)); } - Inst.addOperand(MCOperand::CreateReg(Rt)); - Inst.addOperand(MCOperand::CreateReg(Base)); - Inst.addOperand(MCOperand::CreateImm(Offset)); + Inst.addOperand(MCOperand::createReg(Rt)); + Inst.addOperand(MCOperand::createReg(Base)); + Inst.addOperand(MCOperand::createImm(Offset)); return MCDisassembler::Success; } @@ -1426,7 +1451,7 @@ static DecodeStatus DecodeHWRegsRegisterClass(MCInst &Inst, // Currently only hardware register 29 is supported. if (RegNo != 29) return MCDisassembler::Fail; - Inst.addOperand(MCOperand::CreateReg(Mips::HWR29)); + Inst.addOperand(MCOperand::createReg(Mips::HWR29)); return MCDisassembler::Success; } @@ -1439,7 +1464,7 @@ static DecodeStatus DecodeAFGR64RegisterClass(MCInst &Inst, ; unsigned Reg = getReg(Decoder, Mips::AFGR64RegClassID, RegNo /2); - Inst.addOperand(MCOperand::CreateReg(Reg)); + Inst.addOperand(MCOperand::createReg(Reg)); return MCDisassembler::Success; } @@ -1451,7 +1476,7 @@ static DecodeStatus DecodeACC64DSPRegisterClass(MCInst &Inst, return MCDisassembler::Fail; unsigned Reg = getReg(Decoder, Mips::ACC64DSPRegClassID, RegNo); - Inst.addOperand(MCOperand::CreateReg(Reg)); + Inst.addOperand(MCOperand::createReg(Reg)); return MCDisassembler::Success; } @@ -1463,7 +1488,7 @@ static DecodeStatus DecodeHI32DSPRegisterClass(MCInst &Inst, return MCDisassembler::Fail; unsigned Reg = getReg(Decoder, Mips::HI32DSPRegClassID, RegNo); - Inst.addOperand(MCOperand::CreateReg(Reg)); + Inst.addOperand(MCOperand::createReg(Reg)); return MCDisassembler::Success; } @@ -1475,7 +1500,7 @@ static DecodeStatus DecodeLO32DSPRegisterClass(MCInst &Inst, return MCDisassembler::Fail; unsigned Reg = getReg(Decoder, Mips::LO32DSPRegClassID, RegNo); - Inst.addOperand(MCOperand::CreateReg(Reg)); + Inst.addOperand(MCOperand::createReg(Reg)); return MCDisassembler::Success; } @@ -1487,7 +1512,7 @@ static DecodeStatus DecodeMSA128BRegisterClass(MCInst &Inst, return MCDisassembler::Fail; unsigned Reg = getReg(Decoder, Mips::MSA128BRegClassID, RegNo); - Inst.addOperand(MCOperand::CreateReg(Reg)); + Inst.addOperand(MCOperand::createReg(Reg)); return MCDisassembler::Success; } @@ -1499,7 +1524,7 @@ static DecodeStatus DecodeMSA128HRegisterClass(MCInst &Inst, return MCDisassembler::Fail; unsigned Reg = getReg(Decoder, Mips::MSA128HRegClassID, RegNo); - Inst.addOperand(MCOperand::CreateReg(Reg)); + Inst.addOperand(MCOperand::createReg(Reg)); return MCDisassembler::Success; } @@ -1511,7 +1536,7 @@ static DecodeStatus DecodeMSA128WRegisterClass(MCInst &Inst, return MCDisassembler::Fail; unsigned Reg = getReg(Decoder, Mips::MSA128WRegClassID, RegNo); - Inst.addOperand(MCOperand::CreateReg(Reg)); + Inst.addOperand(MCOperand::createReg(Reg)); return MCDisassembler::Success; } @@ -1523,7 +1548,7 @@ static DecodeStatus DecodeMSA128DRegisterClass(MCInst &Inst, return MCDisassembler::Fail; unsigned Reg = getReg(Decoder, Mips::MSA128DRegClassID, RegNo); - Inst.addOperand(MCOperand::CreateReg(Reg)); + Inst.addOperand(MCOperand::createReg(Reg)); return MCDisassembler::Success; } @@ -1535,7 +1560,7 @@ static DecodeStatus DecodeMSACtrlRegisterClass(MCInst &Inst, return MCDisassembler::Fail; unsigned Reg = getReg(Decoder, Mips::MSACtrlRegClassID, RegNo); - Inst.addOperand(MCOperand::CreateReg(Reg)); + Inst.addOperand(MCOperand::createReg(Reg)); return MCDisassembler::Success; } @@ -1547,7 +1572,7 @@ static DecodeStatus DecodeCOP2RegisterClass(MCInst &Inst, return MCDisassembler::Fail; unsigned Reg = getReg(Decoder, Mips::COP2RegClassID, RegNo); - Inst.addOperand(MCOperand::CreateReg(Reg)); + Inst.addOperand(MCOperand::createReg(Reg)); return MCDisassembler::Success; } @@ -1556,7 +1581,7 @@ static DecodeStatus DecodeBranchTarget(MCInst &Inst, uint64_t Address, const void *Decoder) { int32_t BranchOffset = (SignExtend32<16>(Offset) * 4) + 4; - Inst.addOperand(MCOperand::CreateImm(BranchOffset)); + Inst.addOperand(MCOperand::createImm(BranchOffset)); return MCDisassembler::Success; } @@ -1566,7 +1591,7 @@ static DecodeStatus DecodeJumpTarget(MCInst &Inst, const void *Decoder) { unsigned JumpOffset = fieldFromInstruction(Insn, 0, 26) << 2; - Inst.addOperand(MCOperand::CreateImm(JumpOffset)); + Inst.addOperand(MCOperand::createImm(JumpOffset)); return MCDisassembler::Success; } @@ -1576,7 +1601,7 @@ static DecodeStatus DecodeBranchTarget21(MCInst &Inst, const void *Decoder) { int32_t BranchOffset = SignExtend32<21>(Offset) * 4; - Inst.addOperand(MCOperand::CreateImm(BranchOffset)); + Inst.addOperand(MCOperand::createImm(BranchOffset)); return MCDisassembler::Success; } @@ -1586,7 +1611,7 @@ static DecodeStatus DecodeBranchTarget26(MCInst &Inst, const void *Decoder) { int32_t BranchOffset = SignExtend32<26>(Offset) * 4; - Inst.addOperand(MCOperand::CreateImm(BranchOffset)); + Inst.addOperand(MCOperand::createImm(BranchOffset)); return MCDisassembler::Success; } @@ -1595,7 +1620,16 @@ static DecodeStatus DecodeBranchTarget7MM(MCInst &Inst, uint64_t Address, const void *Decoder) { int32_t BranchOffset = SignExtend32<7>(Offset) << 1; - Inst.addOperand(MCOperand::CreateImm(BranchOffset)); + Inst.addOperand(MCOperand::createImm(BranchOffset)); + return MCDisassembler::Success; +} + +static DecodeStatus DecodeBranchTarget10MM(MCInst &Inst, + unsigned Offset, + uint64_t Address, + const void *Decoder) { + int32_t BranchOffset = SignExtend32<10>(Offset) << 1; + Inst.addOperand(MCOperand::createImm(BranchOffset)); return MCDisassembler::Success; } @@ -1604,7 +1638,7 @@ static DecodeStatus DecodeBranchTargetMM(MCInst &Inst, uint64_t Address, const void *Decoder) { int32_t BranchOffset = SignExtend32<16>(Offset) * 2; - Inst.addOperand(MCOperand::CreateImm(BranchOffset)); + Inst.addOperand(MCOperand::createImm(BranchOffset)); return MCDisassembler::Success; } @@ -1613,7 +1647,7 @@ static DecodeStatus DecodeJumpTargetMM(MCInst &Inst, uint64_t Address, const void *Decoder) { unsigned JumpOffset = fieldFromInstruction(Insn, 0, 26) << 1; - Inst.addOperand(MCOperand::CreateImm(JumpOffset)); + Inst.addOperand(MCOperand::createImm(JumpOffset)); return MCDisassembler::Success; } @@ -1622,11 +1656,11 @@ static DecodeStatus DecodeAddiur2Simm7(MCInst &Inst, uint64_t Address, const void *Decoder) { if (Value == 0) - Inst.addOperand(MCOperand::CreateImm(1)); + Inst.addOperand(MCOperand::createImm(1)); else if (Value == 0x7) - Inst.addOperand(MCOperand::CreateImm(-1)); + Inst.addOperand(MCOperand::createImm(-1)); else - Inst.addOperand(MCOperand::CreateImm(Value << 2)); + Inst.addOperand(MCOperand::createImm(Value << 2)); return MCDisassembler::Success; } @@ -1634,7 +1668,7 @@ static DecodeStatus DecodeUImm6Lsl2(MCInst &Inst, unsigned Value, uint64_t Address, const void *Decoder) { - Inst.addOperand(MCOperand::CreateImm(Value << 2)); + Inst.addOperand(MCOperand::createImm(Value << 2)); return MCDisassembler::Success; } @@ -1643,9 +1677,9 @@ static DecodeStatus DecodeLiSimm7(MCInst &Inst, uint64_t Address, const void *Decoder) { if (Value == 0x7F) - Inst.addOperand(MCOperand::CreateImm(-1)); + Inst.addOperand(MCOperand::createImm(-1)); else - Inst.addOperand(MCOperand::CreateImm(Value)); + Inst.addOperand(MCOperand::createImm(Value)); return MCDisassembler::Success; } @@ -1653,7 +1687,7 @@ static DecodeStatus DecodeSimm4(MCInst &Inst, unsigned Value, uint64_t Address, const void *Decoder) { - Inst.addOperand(MCOperand::CreateImm(SignExtend32<4>(Value))); + Inst.addOperand(MCOperand::createImm(SignExtend32<4>(Value))); return MCDisassembler::Success; } @@ -1661,7 +1695,7 @@ static DecodeStatus DecodeSimm16(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { - Inst.addOperand(MCOperand::CreateImm(SignExtend32<16>(Insn))); + Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Insn))); return MCDisassembler::Success; } @@ -1670,7 +1704,7 @@ static DecodeStatus DecodeLSAImm(MCInst &Inst, uint64_t Address, const void *Decoder) { // We add one to the immediate field as it was encoded as 'imm - 1'. - Inst.addOperand(MCOperand::CreateImm(Insn + 1)); + Inst.addOperand(MCOperand::createImm(Insn + 1)); return MCDisassembler::Success; } @@ -1681,7 +1715,7 @@ static DecodeStatus DecodeInsSize(MCInst &Inst, // First we need to grab the pos(lsb) from MCInst. int Pos = Inst.getOperand(2).getImm(); int Size = (int) Insn - Pos + 1; - Inst.addOperand(MCOperand::CreateImm(SignExtend32<16>(Size))); + Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Size))); return MCDisassembler::Success; } @@ -1690,19 +1724,19 @@ static DecodeStatus DecodeExtSize(MCInst &Inst, uint64_t Address, const void *Decoder) { int Size = (int) Insn + 1; - Inst.addOperand(MCOperand::CreateImm(SignExtend32<16>(Size))); + Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Size))); return MCDisassembler::Success; } static DecodeStatus DecodeSimm19Lsl2(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { - Inst.addOperand(MCOperand::CreateImm(SignExtend32<19>(Insn) * 4)); + Inst.addOperand(MCOperand::createImm(SignExtend32<19>(Insn) * 4)); return MCDisassembler::Success; } static DecodeStatus DecodeSimm18Lsl3(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { - Inst.addOperand(MCOperand::CreateImm(SignExtend32<18>(Insn) * 8)); + Inst.addOperand(MCOperand::createImm(SignExtend32<18>(Insn) * 8)); return MCDisassembler::Success; } @@ -1716,7 +1750,7 @@ static DecodeStatus DecodeSimm9SP(MCInst &Inst, unsigned Insn, case 511: DecodedValue = -257; break; default: DecodedValue = SignExtend32<9>(Insn); break; } - Inst.addOperand(MCOperand::CreateImm(DecodedValue * 4)); + Inst.addOperand(MCOperand::createImm(DecodedValue * 4)); return MCDisassembler::Success; } @@ -1726,13 +1760,13 @@ static DecodeStatus DecodeANDI16Imm(MCInst &Inst, unsigned Insn, assert(Insn < 16); int32_t DecodedValues[] = {128, 1, 2, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 255, 32768, 65535}; - Inst.addOperand(MCOperand::CreateImm(DecodedValues[Insn])); + Inst.addOperand(MCOperand::createImm(DecodedValues[Insn])); return MCDisassembler::Success; } static DecodeStatus DecodeUImm5lsl2(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { - Inst.addOperand(MCOperand::CreateImm(Insn << 2)); + Inst.addOperand(MCOperand::createImm(Insn << 2)); return MCDisassembler::Success; } @@ -1751,10 +1785,10 @@ static DecodeStatus DecodeRegListOperand(MCInst &Inst, RegNum = RegLst & 0xf; for (unsigned i = 0; i < RegNum; i++) - Inst.addOperand(MCOperand::CreateReg(Regs[i])); + Inst.addOperand(MCOperand::createReg(Regs[i])); if (RegLst & 0x10) - Inst.addOperand(MCOperand::CreateReg(Mips::RA)); + Inst.addOperand(MCOperand::createReg(Mips::RA)); return MCDisassembler::Success; } @@ -1763,18 +1797,64 @@ static DecodeStatus DecodeRegListOperand16(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder) { unsigned Regs[] = {Mips::S0, Mips::S1, Mips::S2, Mips::S3}; - unsigned RegNum; - unsigned RegLst = fieldFromInstruction(Insn, 4, 2); - // Empty register lists are not allowed. - if (RegLst == 0) - return MCDisassembler::Fail; + unsigned RegNum = RegLst & 0x3; - RegNum = RegLst & 0x3; - for (unsigned i = 0; i < RegNum - 1; i++) - Inst.addOperand(MCOperand::CreateReg(Regs[i])); + for (unsigned i = 0; i <= RegNum; i++) + Inst.addOperand(MCOperand::createReg(Regs[i])); + + Inst.addOperand(MCOperand::createReg(Mips::RA)); + + return MCDisassembler::Success; +} - Inst.addOperand(MCOperand::CreateReg(Mips::RA)); +static DecodeStatus DecodeMovePRegPair(MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + unsigned RegPair = fieldFromInstruction(Insn, 7, 3); + + switch (RegPair) { + default: + return MCDisassembler::Fail; + case 0: + Inst.addOperand(MCOperand::createReg(Mips::A1)); + Inst.addOperand(MCOperand::createReg(Mips::A2)); + break; + case 1: + Inst.addOperand(MCOperand::createReg(Mips::A1)); + Inst.addOperand(MCOperand::createReg(Mips::A3)); + break; + case 2: + Inst.addOperand(MCOperand::createReg(Mips::A2)); + Inst.addOperand(MCOperand::createReg(Mips::A3)); + break; + case 3: + Inst.addOperand(MCOperand::createReg(Mips::A0)); + Inst.addOperand(MCOperand::createReg(Mips::S5)); + break; + case 4: + Inst.addOperand(MCOperand::createReg(Mips::A0)); + Inst.addOperand(MCOperand::createReg(Mips::S6)); + break; + case 5: + Inst.addOperand(MCOperand::createReg(Mips::A0)); + Inst.addOperand(MCOperand::createReg(Mips::A1)); + break; + case 6: + Inst.addOperand(MCOperand::createReg(Mips::A0)); + Inst.addOperand(MCOperand::createReg(Mips::A2)); + break; + case 7: + Inst.addOperand(MCOperand::createReg(Mips::A0)); + Inst.addOperand(MCOperand::createReg(Mips::A3)); + break; + } + + return MCDisassembler::Success; +} + +static DecodeStatus DecodeSimm23Lsl2(MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + Inst.addOperand(MCOperand::createImm(SignExtend32<23>(Insn) << 2)); return MCDisassembler::Success; } diff --git a/contrib/llvm/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp b/contrib/llvm/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp index 61743ff..a5637b1 100644 --- a/contrib/llvm/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp +++ b/contrib/llvm/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp @@ -77,7 +77,7 @@ void MipsInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const { } void MipsInstPrinter::printInst(const MCInst *MI, raw_ostream &O, - StringRef Annot) { + StringRef Annot, const MCSubtargetInfo &STI) { switch (MI->getOpcode()) { default: break; @@ -122,7 +122,8 @@ void MipsInstPrinter::printInst(const MCInst *MI, raw_ostream &O, } } -static void printExpr(const MCExpr *Expr, raw_ostream &OS) { +static void printExpr(const MCExpr *Expr, const MCAsmInfo *MAI, + raw_ostream &OS) { int Offset = 0; const MCSymbolRefExpr *SRE; @@ -132,7 +133,7 @@ static void printExpr(const MCExpr *Expr, raw_ostream &OS) { assert(SRE && CE && "Binary expression must be sym+const."); Offset = CE->getValue(); } else if (const MipsMCExpr *ME = dyn_cast<MipsMCExpr>(Expr)) { - ME->print(OS); + ME->print(OS, MAI); return; } else SRE = cast<MCSymbolRefExpr>(Expr); @@ -170,7 +171,7 @@ static void printExpr(const MCExpr *Expr, raw_ostream &OS) { case MCSymbolRefExpr::VK_Mips_PCREL_LO16: OS << "%pcrel_lo("; break; } - OS << SRE->getSymbol(); + SRE->getSymbol().print(OS, MAI); if (Offset) { if (Offset > 0) @@ -199,7 +200,7 @@ void MipsInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, } assert(Op.isExpr() && "unknown operand kind in printOperand"); - printExpr(Op.getExpr(), O); + printExpr(Op.getExpr(), &MAI, O); } void MipsInstPrinter::printUnsignedImm(const MCInst *MI, int opNum, @@ -290,6 +291,7 @@ bool MipsInstPrinter::printAlias(const char *Str, const MCInst &MI, bool MipsInstPrinter::printAlias(const MCInst &MI, raw_ostream &OS) { switch (MI.getOpcode()) { case Mips::BEQ: + case Mips::BEQ_MM: // beq $zero, $zero, $L2 => b $L2 // beq $r0, $zero, $L2 => beqz $r0, $L2 return (isReg<Mips::ZERO>(MI, 0) && isReg<Mips::ZERO>(MI, 1) && diff --git a/contrib/llvm/lib/Target/Mips/InstPrinter/MipsInstPrinter.h b/contrib/llvm/lib/Target/Mips/InstPrinter/MipsInstPrinter.h index 468dc07..713f35c 100644 --- a/contrib/llvm/lib/Target/Mips/InstPrinter/MipsInstPrinter.h +++ b/contrib/llvm/lib/Target/Mips/InstPrinter/MipsInstPrinter.h @@ -86,7 +86,8 @@ public: static const char *getRegisterName(unsigned RegNo); void printRegName(raw_ostream &OS, unsigned RegNo) const override; - void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot) override; + void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot, + const MCSubtargetInfo &STI) override; bool printAliasInstr(const MCInst *MI, raw_ostream &OS); void printCustomAliasOperand(const MCInst *MI, unsigned OpIdx, diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp index 5b0f950..70b9cca 100644 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp +++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp @@ -14,15 +14,18 @@ using namespace llvm; uint8_t MipsABIFlagsSection::getFpABIValue() { switch (FpABI) { case FpABIKind::ANY: - return Val_GNU_MIPS_ABI_FP_ANY; + return Mips::Val_GNU_MIPS_ABI_FP_ANY; + case FpABIKind::SOFT: + return Mips::Val_GNU_MIPS_ABI_FP_SOFT; case FpABIKind::XX: - return Val_GNU_MIPS_ABI_FP_XX; + return Mips::Val_GNU_MIPS_ABI_FP_XX; case FpABIKind::S32: - return Val_GNU_MIPS_ABI_FP_DOUBLE; + return Mips::Val_GNU_MIPS_ABI_FP_DOUBLE; case FpABIKind::S64: if (Is32BitABI) - return OddSPReg ? Val_GNU_MIPS_ABI_FP_64 : Val_GNU_MIPS_ABI_FP_64A; - return Val_GNU_MIPS_ABI_FP_DOUBLE; + return OddSPReg ? Mips::Val_GNU_MIPS_ABI_FP_64 + : Mips::Val_GNU_MIPS_ABI_FP_64A; + return Mips::Val_GNU_MIPS_ABI_FP_DOUBLE; } llvm_unreachable("unexpected fp abi value"); @@ -43,7 +46,7 @@ StringRef MipsABIFlagsSection::getFpABIString(FpABIKind Value) { uint8_t MipsABIFlagsSection::getCPR1SizeValue() { if (FpABI == FpABIKind::XX) - return (uint8_t)AFL_REG_32; + return (uint8_t)Mips::AFL_REG_32; return (uint8_t)CPR1Size; } diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h index 8bcfb0f..b078cd3 100644 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h +++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h @@ -11,74 +11,16 @@ #define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSABIFLAGSSECTION_H #include "llvm/MC/MCStreamer.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MipsABIFlags.h" namespace llvm { class MCStreamer; struct MipsABIFlagsSection { - // Values for the xxx_size bytes of an ABI flags structure. - enum AFL_REG { - AFL_REG_NONE = 0x00, // No registers. - AFL_REG_32 = 0x01, // 32-bit registers. - AFL_REG_64 = 0x02, // 64-bit registers. - AFL_REG_128 = 0x03 // 128-bit registers. - }; - - // Masks for the ases word of an ABI flags structure. - enum AFL_ASE { - AFL_ASE_DSP = 0x00000001, // DSP ASE. - AFL_ASE_DSPR2 = 0x00000002, // DSP R2 ASE. - AFL_ASE_EVA = 0x00000004, // Enhanced VA Scheme. - AFL_ASE_MCU = 0x00000008, // MCU (MicroController) ASE. - AFL_ASE_MDMX = 0x00000010, // MDMX ASE. - AFL_ASE_MIPS3D = 0x00000020, // MIPS-3D ASE. - AFL_ASE_MT = 0x00000040, // MT ASE. - AFL_ASE_SMARTMIPS = 0x00000080, // SmartMIPS ASE. - AFL_ASE_VIRT = 0x00000100, // VZ ASE. - AFL_ASE_MSA = 0x00000200, // MSA ASE. - AFL_ASE_MIPS16 = 0x00000400, // MIPS16 ASE. - AFL_ASE_MICROMIPS = 0x00000800, // MICROMIPS ASE. - AFL_ASE_XPA = 0x00001000 // XPA ASE. - }; - - // Values for the isa_ext word of an ABI flags structure. - enum AFL_EXT { - AFL_EXT_XLR = 1, // RMI Xlr instruction. - AFL_EXT_OCTEON2 = 2, // Cavium Networks Octeon2. - AFL_EXT_OCTEONP = 3, // Cavium Networks OcteonP. - AFL_EXT_LOONGSON_3A = 4, // Loongson 3A. - AFL_EXT_OCTEON = 5, // Cavium Networks Octeon. - AFL_EXT_5900 = 6, // MIPS R5900 instruction. - AFL_EXT_4650 = 7, // MIPS R4650 instruction. - AFL_EXT_4010 = 8, // LSI R4010 instruction. - AFL_EXT_4100 = 9, // NEC VR4100 instruction. - AFL_EXT_3900 = 10, // Toshiba R3900 instruction. - AFL_EXT_10000 = 11, // MIPS R10000 instruction. - AFL_EXT_SB1 = 12, // Broadcom SB-1 instruction. - AFL_EXT_4111 = 13, // NEC VR4111/VR4181 instruction. - AFL_EXT_4120 = 14, // NEC VR4120 instruction. - AFL_EXT_5400 = 15, // NEC VR5400 instruction. - AFL_EXT_5500 = 16, // NEC VR5500 instruction. - AFL_EXT_LOONGSON_2E = 17, // ST Microelectronics Loongson 2E. - AFL_EXT_LOONGSON_2F = 18 // ST Microelectronics Loongson 2F. - }; - - // Values for the fp_abi word of an ABI flags structure. - enum Val_GNU_MIPS_ABI { - Val_GNU_MIPS_ABI_FP_ANY = 0, - Val_GNU_MIPS_ABI_FP_DOUBLE = 1, - Val_GNU_MIPS_ABI_FP_XX = 5, - Val_GNU_MIPS_ABI_FP_64 = 6, - Val_GNU_MIPS_ABI_FP_64A = 7 - }; - - enum AFL_FLAGS1 { - AFL_FLAGS1_ODDSPREG = 1 - }; - - // Internal representation of the values used in .module fp=value - enum class FpABIKind { ANY, XX, S32, S64 }; + // Internal representation of the fp_abi related values used in .module. + enum class FpABIKind { ANY, XX, S32, S64, SOFT }; // Version of flags structure. uint16_t Version; @@ -87,11 +29,11 @@ struct MipsABIFlagsSection { // The revision of ISA: 0 for MIPS V and below, 1-n otherwise. uint8_t ISARevision; // The size of general purpose registers. - AFL_REG GPRSize; + Mips::AFL_REG GPRSize; // The size of co-processor 1 registers. - AFL_REG CPR1Size; + Mips::AFL_REG CPR1Size; // The size of co-processor 2 registers. - AFL_REG CPR2Size; + Mips::AFL_REG CPR2Size; // Processor-specific extension. uint32_t ISAExtensionSet; // Mask of ASEs used. @@ -107,9 +49,10 @@ protected: public: MipsABIFlagsSection() - : Version(0), ISALevel(0), ISARevision(0), GPRSize(AFL_REG_NONE), - CPR1Size(AFL_REG_NONE), CPR2Size(AFL_REG_NONE), ISAExtensionSet(0), - ASESet(0), OddSPReg(false), Is32BitABI(false), FpABI(FpABIKind::ANY) {} + : Version(0), ISALevel(0), ISARevision(0), GPRSize(Mips::AFL_REG_NONE), + CPR1Size(Mips::AFL_REG_NONE), CPR2Size(Mips::AFL_REG_NONE), + ISAExtensionSet(0), ASESet(0), OddSPReg(false), Is32BitABI(false), + FpABI(FpABIKind::ANY) {} uint16_t getVersionValue() { return (uint16_t)Version; } uint8_t getISALevelValue() { return (uint8_t)ISALevel; } @@ -125,7 +68,7 @@ public: uint32_t Value = 0; if (OddSPReg) - Value |= (uint32_t)AFL_FLAGS1_ODDSPREG; + Value |= (uint32_t)Mips::AFL_FLAGS1_ODDSPREG; return Value; } @@ -145,6 +88,10 @@ public: ISALevel = 64; if (P.hasMips64r6()) ISARevision = 6; + else if (P.hasMips64r5()) + ISARevision = 5; + else if (P.hasMips64r3()) + ISARevision = 3; else if (P.hasMips64r2()) ISARevision = 2; else @@ -153,6 +100,10 @@ public: ISALevel = 32; if (P.hasMips32r6()) ISARevision = 6; + else if (P.hasMips32r5()) + ISARevision = 5; + else if (P.hasMips32r3()) + ISARevision = 3; else if (P.hasMips32r2()) ISARevision = 2; else @@ -176,32 +127,32 @@ public: template <class PredicateLibrary> void setGPRSizeFromPredicates(const PredicateLibrary &P) { - GPRSize = P.isGP64bit() ? AFL_REG_64 : AFL_REG_32; + GPRSize = P.isGP64bit() ? Mips::AFL_REG_64 : Mips::AFL_REG_32; } template <class PredicateLibrary> void setCPR1SizeFromPredicates(const PredicateLibrary &P) { - if (P.abiUsesSoftFloat()) - CPR1Size = AFL_REG_NONE; + if (P.useSoftFloat()) + CPR1Size = Mips::AFL_REG_NONE; else if (P.hasMSA()) - CPR1Size = AFL_REG_128; + CPR1Size = Mips::AFL_REG_128; else - CPR1Size = P.isFP64bit() ? AFL_REG_64 : AFL_REG_32; + CPR1Size = P.isFP64bit() ? Mips::AFL_REG_64 : Mips::AFL_REG_32; } template <class PredicateLibrary> void setASESetFromPredicates(const PredicateLibrary &P) { ASESet = 0; if (P.hasDSP()) - ASESet |= AFL_ASE_DSP; + ASESet |= Mips::AFL_ASE_DSP; if (P.hasDSPR2()) - ASESet |= AFL_ASE_DSPR2; + ASESet |= Mips::AFL_ASE_DSPR2; if (P.hasMSA()) - ASESet |= AFL_ASE_MSA; + ASESet |= Mips::AFL_ASE_MSA; if (P.inMicroMipsMode()) - ASESet |= AFL_ASE_MICROMIPS; + ASESet |= Mips::AFL_ASE_MICROMIPS; if (P.inMips16Mode()) - ASESet |= AFL_ASE_MIPS16; + ASESet |= Mips::AFL_ASE_MIPS16; } template <class PredicateLibrary> @@ -209,7 +160,9 @@ public: Is32BitABI = P.isABI_O32(); FpABI = FpABIKind::ANY; - if (P.isABI_N32() || P.isABI_N64()) + if (P.useSoftFloat()) + FpABI = FpABIKind::SOFT; + else if (P.isABI_N32() || P.isABI_N64()) FpABI = FpABIKind::S64; else if (P.isABI_O32()) { if (P.isABI_FPXX()) diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp index f885369..bf8f7d1 100644 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp +++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp @@ -9,6 +9,9 @@ #include "MipsABIInfo.h" #include "MipsRegisterInfo.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/MC/MCTargetOptions.h" using namespace llvm; @@ -43,3 +46,83 @@ unsigned MipsABIInfo::GetCalleeAllocdArgSizeInBytes(CallingConv::ID CC) const { return 0; llvm_unreachable("Unhandled ABI"); } + +MipsABIInfo MipsABIInfo::computeTargetABI(Triple TT, StringRef CPU, + const MCTargetOptions &Options) { + if (Options.getABIName().startswith("o32")) + return MipsABIInfo::O32(); + else if (Options.getABIName().startswith("n32")) + return MipsABIInfo::N32(); + else if (Options.getABIName().startswith("n64")) + return MipsABIInfo::N64(); + else if (Options.getABIName().startswith("eabi")) + return MipsABIInfo::EABI(); + else if (!Options.getABIName().empty()) + llvm_unreachable("Unknown ABI option for MIPS"); + + // FIXME: This shares code with the selectMipsCPU routine that's + // used and not shared in a couple of other places. This needs unifying + // at some level. + if (CPU.empty() || CPU == "generic") { + if (TT.getArch() == Triple::mips || TT.getArch() == Triple::mipsel) + CPU = "mips32"; + else + CPU = "mips64"; + } + + return StringSwitch<MipsABIInfo>(CPU) + .Case("mips1", MipsABIInfo::O32()) + .Case("mips2", MipsABIInfo::O32()) + .Case("mips32", MipsABIInfo::O32()) + .Case("mips32r2", MipsABIInfo::O32()) + .Case("mips32r3", MipsABIInfo::O32()) + .Case("mips32r5", MipsABIInfo::O32()) + .Case("mips32r6", MipsABIInfo::O32()) + .Case("mips16", MipsABIInfo::O32()) + .Case("mips3", MipsABIInfo::N64()) + .Case("mips4", MipsABIInfo::N64()) + .Case("mips5", MipsABIInfo::N64()) + .Case("mips64", MipsABIInfo::N64()) + .Case("mips64r2", MipsABIInfo::N64()) + .Case("mips64r3", MipsABIInfo::N64()) + .Case("mips64r5", MipsABIInfo::N64()) + .Case("mips64r6", MipsABIInfo::N64()) + .Case("octeon", MipsABIInfo::N64()) + .Default(MipsABIInfo::Unknown()); +} + +unsigned MipsABIInfo::GetStackPtr() const { + return ArePtrs64bit() ? Mips::SP_64 : Mips::SP; +} + +unsigned MipsABIInfo::GetFramePtr() const { + return ArePtrs64bit() ? Mips::FP_64 : Mips::FP; +} + +unsigned MipsABIInfo::GetBasePtr() const { + return ArePtrs64bit() ? Mips::S7_64 : Mips::S7; +} + +unsigned MipsABIInfo::GetNullPtr() const { + return ArePtrs64bit() ? Mips::ZERO_64 : Mips::ZERO; +} + +unsigned MipsABIInfo::GetPtrAdduOp() const { + return ArePtrs64bit() ? Mips::DADDu : Mips::ADDu; +} + +unsigned MipsABIInfo::GetPtrAddiuOp() const { + return ArePtrs64bit() ? Mips::DADDiu : Mips::ADDiu; +} + +unsigned MipsABIInfo::GetEhDataReg(unsigned I) const { + static const unsigned EhDataReg[] = { + Mips::A0, Mips::A1, Mips::A2, Mips::A3 + }; + static const unsigned EhDataReg64[] = { + Mips::A0_64, Mips::A1_64, Mips::A2_64, Mips::A3_64 + }; + + return IsN64() ? EhDataReg64[I] : EhDataReg[I]; +} + diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h index eccb50d8..d20dc90 100644 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h +++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h @@ -7,15 +7,20 @@ // //===----------------------------------------------------------------------===// -#ifndef MIPSABIINFO_H -#define MIPSABIINFO_H +#ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSABIINFO_H +#define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSABIINFO_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Triple.h" #include "llvm/IR/CallingConv.h" #include "llvm/MC/MCRegisterInfo.h" namespace llvm { +class MCTargetOptions; +class StringRef; +class TargetRegisterClass; + class MipsABIInfo { public: enum class ABI { Unknown, O32, N32, N64, EABI }; @@ -31,6 +36,8 @@ public: static MipsABIInfo N32() { return MipsABIInfo(ABI::N32); } static MipsABIInfo N64() { return MipsABIInfo(ABI::N64); } static MipsABIInfo EABI() { return MipsABIInfo(ABI::EABI); } + static MipsABIInfo computeTargetABI(Triple TT, StringRef CPU, + const MCTargetOptions &Options); bool IsKnown() const { return ThisABI != ABI::Unknown; } bool IsO32() const { return ThisABI == ABI::O32; } @@ -55,6 +62,16 @@ public: bool operator<(const MipsABIInfo Other) const { return ThisABI < Other.GetEnumValue(); } + + unsigned GetStackPtr() const; + unsigned GetFramePtr() const; + unsigned GetBasePtr() const; + unsigned GetNullPtr() const; + unsigned GetPtrAdduOp() const; + unsigned GetPtrAddiuOp() const; + inline bool ArePtrs64bit() const { return IsN64(); } + + unsigned GetEhDataReg(unsigned I) const; }; } diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp index 6670dc2..d823ffc 100644 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp +++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp @@ -68,14 +68,14 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, Value = (int64_t)Value / 4; // We now check if Value can be encoded as a 16-bit signed immediate. if (!isIntN(16, Value) && Ctx) - Ctx->FatalError(Fixup.getLoc(), "out of range PC16 fixup"); + Ctx->reportFatalError(Fixup.getLoc(), "out of range PC16 fixup"); break; case Mips::fixup_MIPS_PC19_S2: // Forcing a signed division because Value can be negative. Value = (int64_t)Value / 4; // We now check if Value can be encoded as a 19-bit signed immediate. if (!isIntN(19, Value) && Ctx) - Ctx->FatalError(Fixup.getLoc(), "out of range PC19 fixup"); + Ctx->reportFatalError(Fixup.getLoc(), "out of range PC19 fixup"); break; case Mips::fixup_Mips_26: // So far we are only using this type for jumps. @@ -109,7 +109,15 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, Value = (int64_t) Value / 2; // We now check if Value can be encoded as a 7-bit signed immediate. if (!isIntN(7, Value) && Ctx) - Ctx->FatalError(Fixup.getLoc(), "out of range PC7 fixup"); + Ctx->reportFatalError(Fixup.getLoc(), "out of range PC7 fixup"); + break; + case Mips::fixup_MICROMIPS_PC10_S1: + Value -= 2; + // Forcing a signed division because Value can be negative. + Value = (int64_t) Value / 2; + // We now check if Value can be encoded as a 10-bit signed immediate. + if (!isIntN(10, Value) && Ctx) + Ctx->reportFatalError(Fixup.getLoc(), "out of range PC10 fixup"); break; case Mips::fixup_MICROMIPS_PC16_S1: Value -= 4; @@ -117,14 +125,14 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, Value = (int64_t)Value / 2; // We now check if Value can be encoded as a 16-bit signed immediate. if (!isIntN(16, Value) && Ctx) - Ctx->FatalError(Fixup.getLoc(), "out of range PC16 fixup"); + Ctx->reportFatalError(Fixup.getLoc(), "out of range PC16 fixup"); break; case Mips::fixup_MIPS_PC18_S3: // Forcing a signed division because Value can be negative. Value = (int64_t)Value / 8; // We now check if Value can be encoded as a 18-bit signed immediate. if (!isIntN(18, Value) && Ctx) - Ctx->FatalError(Fixup.getLoc(), "out of range PC18 fixup"); + Ctx->reportFatalError(Fixup.getLoc(), "out of range PC18 fixup"); break; case Mips::fixup_MIPS_PC21_S2: Value -= 4; @@ -132,7 +140,7 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, Value = (int64_t) Value / 4; // We now check if Value can be encoded as a 21-bit signed immediate. if (!isIntN(21, Value) && Ctx) - Ctx->FatalError(Fixup.getLoc(), "out of range PC21 fixup"); + Ctx->reportFatalError(Fixup.getLoc(), "out of range PC21 fixup"); break; case Mips::fixup_MIPS_PC26_S2: Value -= 4; @@ -140,14 +148,15 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, Value = (int64_t) Value / 4; // We now check if Value can be encoded as a 26-bit signed immediate. if (!isIntN(26, Value) && Ctx) - Ctx->FatalError(Fixup.getLoc(), "out of range PC26 fixup"); + Ctx->reportFatalError(Fixup.getLoc(), "out of range PC26 fixup"); break; } return Value; } -MCObjectWriter *MipsAsmBackend::createObjectWriter(raw_ostream &OS) const { +MCObjectWriter * +MipsAsmBackend::createObjectWriter(raw_pwrite_stream &OS) const { return createMipsELFObjectWriter(OS, MCELFObjectTargetWriter::getOSABI(OSType), IsLittle, Is64Bit); } @@ -157,7 +166,8 @@ MCObjectWriter *MipsAsmBackend::createObjectWriter(raw_ostream &OS) const { // microMIPS: x | x | a | b static bool needsMMLEByteOrder(unsigned Kind) { - return Kind >= Mips::fixup_MICROMIPS_26_S1 && + return Kind != Mips::fixup_MICROMIPS_PC10_S1 && + Kind >= Mips::fixup_MICROMIPS_26_S1 && Kind < Mips::LastTargetFixupKind; } @@ -190,6 +200,7 @@ void MipsAsmBackend::applyFixup(const MCFixup &Fixup, char *Data, switch ((unsigned)Kind) { case FK_Data_2: case Mips::fixup_Mips_16: + case Mips::fixup_MICROMIPS_PC10_S1: FullSize = 2; break; case FK_Data_8: @@ -280,6 +291,7 @@ getFixupKindInfo(MCFixupKind Kind) const { { "fixup_MICROMIPS_LO16", 0, 16, 0 }, { "fixup_MICROMIPS_GOT16", 0, 16, 0 }, { "fixup_MICROMIPS_PC7_S1", 0, 7, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_MICROMIPS_PC10_S1", 0, 10, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_MICROMIPS_PC16_S1", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_MICROMIPS_CALL16", 0, 16, 0 }, { "fixup_MICROMIPS_GOT_DISP", 0, 16, 0 }, @@ -344,6 +356,7 @@ getFixupKindInfo(MCFixupKind Kind) const { { "fixup_MICROMIPS_LO16", 16, 16, 0 }, { "fixup_MICROMIPS_GOT16", 16, 16, 0 }, { "fixup_MICROMIPS_PC7_S1", 9, 7, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_MICROMIPS_PC10_S1", 6, 10, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_MICROMIPS_PC16_S1",16, 16, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_MICROMIPS_CALL16", 16, 16, 0 }, { "fixup_MICROMIPS_GOT_DISP", 16, 16, 0 }, @@ -381,12 +394,7 @@ bool MipsAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { // If the count is not 4-byte aligned, we must be writing data into the text // section (otherwise we have unaligned instructions, and thus have far // bigger problems), so just write zeros instead. - for (uint64_t i = 0, e = Count % 4; i != e; ++i) - OW->Write8(0); - - uint64_t NumNops = Count / 4; - for (uint64_t i = 0; i != NumNops; ++i) - OW->Write32(0); + OW->WriteZeros(Count); return true; } diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h index dd0e54c..b3d5a49 100644 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h +++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h @@ -32,12 +32,11 @@ class MipsAsmBackend : public MCAsmBackend { bool Is64Bit; // 32 or 64 bit words public: - MipsAsmBackend(const Target &T, Triple::OSType _OSType, bool _isLittle, - bool _is64Bit) - : MCAsmBackend(), OSType(_OSType), IsLittle(_isLittle), - Is64Bit(_is64Bit) {} + MipsAsmBackend(const Target &T, Triple::OSType OSType, bool IsLittle, + bool Is64Bit) + : MCAsmBackend(), OSType(OSType), IsLittle(IsLittle), Is64Bit(Is64Bit) {} - MCObjectWriter *createObjectWriter(raw_ostream &OS) const override; + MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override; void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, uint64_t Value, bool IsPCRel) const override; diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp index 56aac4e..982a7f5 100644 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp +++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp @@ -10,11 +10,12 @@ #include "MCTargetDesc/MipsBaseInfo.h" #include "MCTargetDesc/MipsFixupKinds.h" #include "MCTargetDesc/MipsMCTargetDesc.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/MC/MCAssembler.h" -#include "llvm/MC/MCELF.h" #include "llvm/MC/MCELFObjectWriter.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCSection.h" +#include "llvm/MC/MCSymbolELF.h" #include "llvm/MC/MCValue.h" #include "llvm/Support/ErrorHandling.h" #include <list> @@ -22,25 +23,41 @@ using namespace llvm; namespace { +// A helper structure based on ELFRelocationEntry, used for sorting entries in +// the relocation table. +struct MipsRelocationEntry { + MipsRelocationEntry(const ELFRelocationEntry &R) + : R(R), SortOffset(R.Offset), HasMatchingHi(false) {} + const ELFRelocationEntry R; + // SortOffset equals R.Offset except for the *HI16 relocations, for which it + // will be set based on the R.Offset of the matching *LO16 relocation. + int64_t SortOffset; + // True when this is a *LO16 relocation chosen as a match for a *HI16 + // relocation. + bool HasMatchingHi; +}; + class MipsELFObjectWriter : public MCELFObjectTargetWriter { public: MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI, bool _isN64, bool IsLittleEndian); - virtual ~MipsELFObjectWriter(); + ~MipsELFObjectWriter() override; unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const override; - bool needsRelocateWithSymbol(const MCSymbolData &SD, + bool needsRelocateWithSymbol(const MCSymbol &Sym, unsigned Type) const override; + virtual void sortRelocs(const MCAssembler &Asm, + std::vector<ELFRelocationEntry> &Relocs) override; }; } MipsELFObjectWriter::MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI, bool _isN64, bool IsLittleEndian) - : MCELFObjectTargetWriter(_is64Bit, OSABI, ELF::EM_MIPS, - /*HasRelocationAddend*/ (_isN64) ? true : false, - /*IsN64*/ _isN64) {} + : MCELFObjectTargetWriter(_is64Bit, OSABI, ELF::EM_MIPS, + /*HasRelocationAddend*/ _isN64, + /*IsN64*/ _isN64) {} MipsELFObjectWriter::~MipsELFObjectWriter() {} @@ -48,181 +65,299 @@ unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const { // determine the type of the relocation - unsigned Type = (unsigned)ELF::R_MIPS_NONE; unsigned Kind = (unsigned)Fixup.getKind(); switch (Kind) { - default: - llvm_unreachable("invalid fixup kind!"); + case Mips::fixup_Mips_32: case FK_Data_4: - Type = ELF::R_MIPS_32; - break; + return IsPCRel ? ELF::R_MIPS_PC32 : ELF::R_MIPS_32; + case Mips::fixup_Mips_64: case FK_Data_8: - Type = ELF::R_MIPS_64; - break; + return ELF::R_MIPS_64; case FK_GPRel_4: if (isN64()) { + unsigned Type = (unsigned)ELF::R_MIPS_NONE; Type = setRType((unsigned)ELF::R_MIPS_GPREL32, Type); Type = setRType2((unsigned)ELF::R_MIPS_64, Type); Type = setRType3((unsigned)ELF::R_MIPS_NONE, Type); + return Type; } - else - Type = ELF::R_MIPS_GPREL32; - break; + return ELF::R_MIPS_GPREL32; case Mips::fixup_Mips_GPREL16: - Type = ELF::R_MIPS_GPREL16; - break; + return ELF::R_MIPS_GPREL16; case Mips::fixup_Mips_26: - Type = ELF::R_MIPS_26; - break; + return ELF::R_MIPS_26; case Mips::fixup_Mips_CALL16: - Type = ELF::R_MIPS_CALL16; - break; + return ELF::R_MIPS_CALL16; case Mips::fixup_Mips_GOT_Global: case Mips::fixup_Mips_GOT_Local: - Type = ELF::R_MIPS_GOT16; - break; + return ELF::R_MIPS_GOT16; case Mips::fixup_Mips_HI16: - Type = ELF::R_MIPS_HI16; - break; + return ELF::R_MIPS_HI16; case Mips::fixup_Mips_LO16: - Type = ELF::R_MIPS_LO16; - break; + return ELF::R_MIPS_LO16; case Mips::fixup_Mips_TLSGD: - Type = ELF::R_MIPS_TLS_GD; - break; + return ELF::R_MIPS_TLS_GD; case Mips::fixup_Mips_GOTTPREL: - Type = ELF::R_MIPS_TLS_GOTTPREL; - break; + return ELF::R_MIPS_TLS_GOTTPREL; case Mips::fixup_Mips_TPREL_HI: - Type = ELF::R_MIPS_TLS_TPREL_HI16; - break; + return ELF::R_MIPS_TLS_TPREL_HI16; case Mips::fixup_Mips_TPREL_LO: - Type = ELF::R_MIPS_TLS_TPREL_LO16; - break; + return ELF::R_MIPS_TLS_TPREL_LO16; case Mips::fixup_Mips_TLSLDM: - Type = ELF::R_MIPS_TLS_LDM; - break; + return ELF::R_MIPS_TLS_LDM; case Mips::fixup_Mips_DTPREL_HI: - Type = ELF::R_MIPS_TLS_DTPREL_HI16; - break; + return ELF::R_MIPS_TLS_DTPREL_HI16; case Mips::fixup_Mips_DTPREL_LO: - Type = ELF::R_MIPS_TLS_DTPREL_LO16; - break; + return ELF::R_MIPS_TLS_DTPREL_LO16; case Mips::fixup_Mips_Branch_PCRel: case Mips::fixup_Mips_PC16: - Type = ELF::R_MIPS_PC16; - break; + return ELF::R_MIPS_PC16; case Mips::fixup_Mips_GOT_PAGE: - Type = ELF::R_MIPS_GOT_PAGE; - break; + return ELF::R_MIPS_GOT_PAGE; case Mips::fixup_Mips_GOT_OFST: - Type = ELF::R_MIPS_GOT_OFST; - break; + return ELF::R_MIPS_GOT_OFST; case Mips::fixup_Mips_GOT_DISP: - Type = ELF::R_MIPS_GOT_DISP; - break; - case Mips::fixup_Mips_GPOFF_HI: + return ELF::R_MIPS_GOT_DISP; + case Mips::fixup_Mips_GPOFF_HI: { + unsigned Type = (unsigned)ELF::R_MIPS_NONE; Type = setRType((unsigned)ELF::R_MIPS_GPREL16, Type); Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type); Type = setRType3((unsigned)ELF::R_MIPS_HI16, Type); - break; - case Mips::fixup_Mips_GPOFF_LO: + return Type; + } + case Mips::fixup_Mips_GPOFF_LO: { + unsigned Type = (unsigned)ELF::R_MIPS_NONE; Type = setRType((unsigned)ELF::R_MIPS_GPREL16, Type); Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type); Type = setRType3((unsigned)ELF::R_MIPS_LO16, Type); - break; + return Type; + } case Mips::fixup_Mips_HIGHER: - Type = ELF::R_MIPS_HIGHER; - break; + return ELF::R_MIPS_HIGHER; case Mips::fixup_Mips_HIGHEST: - Type = ELF::R_MIPS_HIGHEST; - break; + return ELF::R_MIPS_HIGHEST; case Mips::fixup_Mips_GOT_HI16: - Type = ELF::R_MIPS_GOT_HI16; - break; + return ELF::R_MIPS_GOT_HI16; case Mips::fixup_Mips_GOT_LO16: - Type = ELF::R_MIPS_GOT_LO16; - break; + return ELF::R_MIPS_GOT_LO16; case Mips::fixup_Mips_CALL_HI16: - Type = ELF::R_MIPS_CALL_HI16; - break; + return ELF::R_MIPS_CALL_HI16; case Mips::fixup_Mips_CALL_LO16: - Type = ELF::R_MIPS_CALL_LO16; - break; + return ELF::R_MIPS_CALL_LO16; case Mips::fixup_MICROMIPS_26_S1: - Type = ELF::R_MICROMIPS_26_S1; - break; + return ELF::R_MICROMIPS_26_S1; case Mips::fixup_MICROMIPS_HI16: - Type = ELF::R_MICROMIPS_HI16; - break; + return ELF::R_MICROMIPS_HI16; case Mips::fixup_MICROMIPS_LO16: - Type = ELF::R_MICROMIPS_LO16; - break; + return ELF::R_MICROMIPS_LO16; case Mips::fixup_MICROMIPS_GOT16: - Type = ELF::R_MICROMIPS_GOT16; - break; + return ELF::R_MICROMIPS_GOT16; case Mips::fixup_MICROMIPS_PC7_S1: - Type = ELF::R_MICROMIPS_PC7_S1; - break; + return ELF::R_MICROMIPS_PC7_S1; + case Mips::fixup_MICROMIPS_PC10_S1: + return ELF::R_MICROMIPS_PC10_S1; case Mips::fixup_MICROMIPS_PC16_S1: - Type = ELF::R_MICROMIPS_PC16_S1; - break; + return ELF::R_MICROMIPS_PC16_S1; case Mips::fixup_MICROMIPS_CALL16: - Type = ELF::R_MICROMIPS_CALL16; - break; + return ELF::R_MICROMIPS_CALL16; case Mips::fixup_MICROMIPS_GOT_DISP: - Type = ELF::R_MICROMIPS_GOT_DISP; - break; + return ELF::R_MICROMIPS_GOT_DISP; case Mips::fixup_MICROMIPS_GOT_PAGE: - Type = ELF::R_MICROMIPS_GOT_PAGE; - break; + return ELF::R_MICROMIPS_GOT_PAGE; case Mips::fixup_MICROMIPS_GOT_OFST: - Type = ELF::R_MICROMIPS_GOT_OFST; - break; + return ELF::R_MICROMIPS_GOT_OFST; case Mips::fixup_MICROMIPS_TLS_GD: - Type = ELF::R_MICROMIPS_TLS_GD; - break; + return ELF::R_MICROMIPS_TLS_GD; case Mips::fixup_MICROMIPS_TLS_LDM: - Type = ELF::R_MICROMIPS_TLS_LDM; - break; + return ELF::R_MICROMIPS_TLS_LDM; case Mips::fixup_MICROMIPS_TLS_DTPREL_HI16: - Type = ELF::R_MICROMIPS_TLS_DTPREL_HI16; - break; + return ELF::R_MICROMIPS_TLS_DTPREL_HI16; case Mips::fixup_MICROMIPS_TLS_DTPREL_LO16: - Type = ELF::R_MICROMIPS_TLS_DTPREL_LO16; - break; + return ELF::R_MICROMIPS_TLS_DTPREL_LO16; case Mips::fixup_MICROMIPS_TLS_TPREL_HI16: - Type = ELF::R_MICROMIPS_TLS_TPREL_HI16; - break; + return ELF::R_MICROMIPS_TLS_TPREL_HI16; case Mips::fixup_MICROMIPS_TLS_TPREL_LO16: - Type = ELF::R_MICROMIPS_TLS_TPREL_LO16; - break; + return ELF::R_MICROMIPS_TLS_TPREL_LO16; case Mips::fixup_MIPS_PC19_S2: - Type = ELF::R_MIPS_PC19_S2; - break; + return ELF::R_MIPS_PC19_S2; case Mips::fixup_MIPS_PC18_S3: - Type = ELF::R_MIPS_PC18_S3; - break; + return ELF::R_MIPS_PC18_S3; case Mips::fixup_MIPS_PC21_S2: - Type = ELF::R_MIPS_PC21_S2; - break; + return ELF::R_MIPS_PC21_S2; case Mips::fixup_MIPS_PC26_S2: - Type = ELF::R_MIPS_PC26_S2; - break; + return ELF::R_MIPS_PC26_S2; case Mips::fixup_MIPS_PCHI16: - Type = ELF::R_MIPS_PCHI16; - break; + return ELF::R_MIPS_PCHI16; case Mips::fixup_MIPS_PCLO16: - Type = ELF::R_MIPS_PCLO16; - break; + return ELF::R_MIPS_PCLO16; + } + llvm_unreachable("invalid fixup kind!"); +} + +// Sort entries by SortOffset in descending order. +// When there are more *HI16 relocs paired with one *LO16 reloc, the 2nd rule +// sorts them in ascending order of R.Offset. +static int cmpRelMips(const MipsRelocationEntry *AP, + const MipsRelocationEntry *BP) { + const MipsRelocationEntry &A = *AP; + const MipsRelocationEntry &B = *BP; + if (A.SortOffset != B.SortOffset) + return B.SortOffset - A.SortOffset; + if (A.R.Offset != B.R.Offset) + return A.R.Offset - B.R.Offset; + if (B.R.Type != A.R.Type) + return B.R.Type - A.R.Type; + //llvm_unreachable("ELFRelocs might be unstable!"); + return 0; +} + +// For the given Reloc.Type, return the matching relocation type, as in the +// table below. +static unsigned getMatchingLoType(const MCAssembler &Asm, + const ELFRelocationEntry &Reloc) { + unsigned Type = Reloc.Type; + if (Type == ELF::R_MIPS_HI16) + return ELF::R_MIPS_LO16; + if (Type == ELF::R_MICROMIPS_HI16) + return ELF::R_MICROMIPS_LO16; + if (Type == ELF::R_MIPS16_HI16) + return ELF::R_MIPS16_LO16; + + if (Reloc.Symbol->getBinding() != ELF::STB_LOCAL) + return ELF::R_MIPS_NONE; + + if (Type == ELF::R_MIPS_GOT16) + return ELF::R_MIPS_LO16; + if (Type == ELF::R_MICROMIPS_GOT16) + return ELF::R_MICROMIPS_LO16; + if (Type == ELF::R_MIPS16_GOT16) + return ELF::R_MIPS16_LO16; + + return ELF::R_MIPS_NONE; +} + +// Return true if First needs a matching *LO16, its matching *LO16 type equals +// Second's type and both relocations are against the same symbol. +static bool areMatchingHiAndLo(const MCAssembler &Asm, + const ELFRelocationEntry &First, + const ELFRelocationEntry &Second) { + return getMatchingLoType(Asm, First) != ELF::R_MIPS_NONE && + getMatchingLoType(Asm, First) == Second.Type && + First.Symbol && First.Symbol == Second.Symbol; +} + +// Return true if MipsRelocs[Index] is a *LO16 preceded by a matching *HI16. +static bool +isPrecededByMatchingHi(const MCAssembler &Asm, uint32_t Index, + std::vector<MipsRelocationEntry> &MipsRelocs) { + return Index < MipsRelocs.size() - 1 && + areMatchingHiAndLo(Asm, MipsRelocs[Index + 1].R, MipsRelocs[Index].R); +} + +// Return true if MipsRelocs[Index] is a *LO16 not preceded by a matching *HI16 +// and not chosen by a *HI16 as a match. +static bool isFreeLo(const MCAssembler &Asm, uint32_t Index, + std::vector<MipsRelocationEntry> &MipsRelocs) { + return Index < MipsRelocs.size() && !MipsRelocs[Index].HasMatchingHi && + !isPrecededByMatchingHi(Asm, Index, MipsRelocs); +} + +// Lo is chosen as a match for Hi, set their fields accordingly. +// Mips instructions have fixed length of at least two bytes (two for +// micromips/mips16, four for mips32/64), so we can set HI's SortOffset to +// matching LO's Offset minus one to simplify the sorting function. +static void setMatch(MipsRelocationEntry &Hi, MipsRelocationEntry &Lo) { + Lo.HasMatchingHi = true; + Hi.SortOffset = Lo.R.Offset - 1; +} + +// We sort relocation table entries by offset, except for one additional rule +// required by MIPS ABI: every *HI16 relocation must be immediately followed by +// the corresponding *LO16 relocation. We also support a GNU extension that +// allows more *HI16s paired with one *LO16. +// +// *HI16 relocations and their matching *LO16 are: +// +// +---------------------------------------------+-------------------+ +// | *HI16 | matching *LO16 | +// |---------------------------------------------+-------------------| +// | R_MIPS_HI16, local R_MIPS_GOT16 | R_MIPS_LO16 | +// | R_MICROMIPS_HI16, local R_MICROMIPS_GOT16 | R_MICROMIPS_LO16 | +// | R_MIPS16_HI16, local R_MIPS16_GOT16 | R_MIPS16_LO16 | +// +---------------------------------------------+-------------------+ +// +// (local R_*_GOT16 meaning R_*_GOT16 against the local symbol.) +// +// To handle *HI16 and *LO16 relocations, the linker needs a combined addend +// ("AHL") calculated from both *HI16 ("AHI") and *LO16 ("ALO") relocations: +// AHL = (AHI << 16) + (short)ALO; +// +// We are reusing gnu as sorting algorithm so we are emitting the relocation +// table sorted the same way as gnu as would sort it, for easier comparison of +// the generated .o files. +// +// The logic is: +// search the table (starting from the highest offset and going back to zero) +// for all *HI16 relocations that don't have a matching *LO16. +// For every such HI, find a matching LO with highest offset that isn't already +// matched with another HI. If there are no free LOs, match it with the first +// found (starting from lowest offset). +// When there are more HIs matched with one LO, sort them in descending order by +// offset. +// +// In other words, when searching for a matching LO: +// - don't look for a 'better' match for the HIs that are already followed by a +// matching LO; +// - prefer LOs without a pair; +// - prefer LOs with higher offset; +void MipsELFObjectWriter::sortRelocs(const MCAssembler &Asm, + std::vector<ELFRelocationEntry> &Relocs) { + if (Relocs.size() < 2) + return; + + // The default function sorts entries by Offset in descending order. + MCELFObjectTargetWriter::sortRelocs(Asm, Relocs); + + // Init MipsRelocs from Relocs. + std::vector<MipsRelocationEntry> MipsRelocs; + for (unsigned I = 0, E = Relocs.size(); I != E; ++I) + MipsRelocs.push_back(MipsRelocationEntry(Relocs[I])); + + // Find a matching LO for all HIs that need it. + for (int32_t I = 0, E = MipsRelocs.size(); I != E; ++I) { + if (getMatchingLoType(Asm, MipsRelocs[I].R) == ELF::R_MIPS_NONE || + (I > 0 && isPrecededByMatchingHi(Asm, I - 1, MipsRelocs))) + continue; + + int32_t MatchedLoIndex = -1; + + // Search the list in the ascending order of Offset. + for (int32_t J = MipsRelocs.size() - 1, N = -1; J != N; --J) { + // check for a match + if (areMatchingHiAndLo(Asm, MipsRelocs[I].R, MipsRelocs[J].R) && + (MatchedLoIndex == -1 || // first match + // or we already have a match, + // but this one is with higher offset and it's free + (MatchedLoIndex > J && isFreeLo(Asm, J, MipsRelocs)))) + MatchedLoIndex = J; + } + + if (MatchedLoIndex != -1) + // We have a match. + setMatch(MipsRelocs[I], MipsRelocs[MatchedLoIndex]); } - return Type; + + // SortOffsets are calculated, call the sorting function. + array_pod_sort(MipsRelocs.begin(), MipsRelocs.end(), cmpRelMips); + + // Copy sorted MipsRelocs back to Relocs. + for (unsigned I = 0, E = MipsRelocs.size(); I != E; ++I) + Relocs[I] = MipsRelocs[I].R; } -bool -MipsELFObjectWriter::needsRelocateWithSymbol(const MCSymbolData &SD, - unsigned Type) const { +bool MipsELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym, + unsigned Type) const { // FIXME: This is extremely conservative. This really needs to use a // whitelist with a clear explanation for why each realocation needs to // point to the symbol, not to the section. @@ -249,7 +384,7 @@ MipsELFObjectWriter::needsRelocateWithSymbol(const MCSymbolData &SD, return true; case ELF::R_MIPS_32: - if (MCELF::getOther(SD) & (ELF::STO_MIPS_MICROMIPS >> 2)) + if (cast<MCSymbolELF>(Sym).getOther() & ELF::STO_MIPS_MICROMIPS) return true; // falltrough case ELF::R_MIPS_26: @@ -259,12 +394,11 @@ MipsELFObjectWriter::needsRelocateWithSymbol(const MCSymbolData &SD, } } -MCObjectWriter *llvm::createMipsELFObjectWriter(raw_ostream &OS, +MCObjectWriter *llvm::createMipsELFObjectWriter(raw_pwrite_stream &OS, uint8_t OSABI, bool IsLittleEndian, bool Is64Bit) { - MCELFObjectTargetWriter *MOTW = new MipsELFObjectWriter(Is64Bit, OSABI, - (Is64Bit) ? true : false, - IsLittleEndian); + MCELFObjectTargetWriter *MOTW = + new MipsELFObjectWriter(Is64Bit, OSABI, Is64Bit, IsLittleEndian); return createELFObjectWriter(MOTW, OS, IsLittleEndian); } diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp index 18c4a20..b45d9cf 100644 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp +++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp @@ -9,8 +9,8 @@ #include "MipsELFStreamer.h" #include "MipsTargetStreamer.h" -#include "llvm/MC/MCELF.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCSymbolELF.h" #include "llvm/Support/ELF.h" using namespace llvm; @@ -21,8 +21,6 @@ void MipsELFStreamer::EmitInstruction(const MCInst &Inst, MCContext &Context = getContext(); const MCRegisterInfo *MCRegInfo = Context.getRegisterInfo(); - MipsTargetELFStreamer *ELFTargetStreamer = - static_cast<MipsTargetELFStreamer *>(getTargetStreamer()); for (unsigned OpIndex = 0; OpIndex < Inst.getNumOperands(); ++OpIndex) { const MCOperand &Op = Inst.getOperand(OpIndex); @@ -34,13 +32,19 @@ void MipsELFStreamer::EmitInstruction(const MCInst &Inst, RegInfoRecord->SetPhysRegUsed(Reg, MCRegInfo); } + createPendingLabelRelocs(); +} + +void MipsELFStreamer::createPendingLabelRelocs() { + MipsTargetELFStreamer *ELFTargetStreamer = + static_cast<MipsTargetELFStreamer *>(getTargetStreamer()); + + // FIXME: Also mark labels when in MIPS16 mode. if (ELFTargetStreamer->isMicroMipsEnabled()) { - for (auto Label : Labels) { - MCSymbolData &Data = getOrCreateSymbolData(Label); - // The "other" values are stored in the last 6 bits of the second byte. - // The traditional defines for STO values assume the full byte and thus - // the shift to pack it. - MCELF::setOther(Data, ELF::STO_MIPS_MICROMIPS >> 2); + for (auto *L : Labels) { + auto *Label = cast<MCSymbolELF>(L); + getAssembler().registerSymbol(*Label); + Label->setOther(ELF::STO_MIPS_MICROMIPS); } } @@ -52,7 +56,7 @@ void MipsELFStreamer::EmitLabel(MCSymbol *Symbol) { Labels.push_back(Symbol); } -void MipsELFStreamer::SwitchSection(const MCSection * Section, +void MipsELFStreamer::SwitchSection(MCSection *Section, const MCExpr *Subsection) { MCELFStreamer::SwitchSection(Section, Subsection); Labels.clear(); @@ -69,11 +73,10 @@ void MipsELFStreamer::EmitMipsOptionRecords() { I->EmitMipsOptionRecord(); } -namespace llvm { -MCELFStreamer *createMipsELFStreamer(MCContext &Context, MCAsmBackend &MAB, - raw_ostream &OS, MCCodeEmitter *Emitter, - const MCSubtargetInfo &STI, - bool RelaxAll) { - return new MipsELFStreamer(Context, MAB, OS, Emitter, STI); -} +MCELFStreamer *llvm::createMipsELFStreamer(MCContext &Context, + MCAsmBackend &MAB, + raw_pwrite_stream &OS, + MCCodeEmitter *Emitter, + bool RelaxAll) { + return new MipsELFStreamer(Context, MAB, OS, Emitter); } diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h index 136146b..af9311f 100644 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h +++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h @@ -33,11 +33,11 @@ class MipsELFStreamer : public MCELFStreamer { public: - MipsELFStreamer(MCContext &Context, MCAsmBackend &MAB, raw_ostream &OS, - MCCodeEmitter *Emitter, const MCSubtargetInfo &STI) + MipsELFStreamer(MCContext &Context, MCAsmBackend &MAB, raw_pwrite_stream &OS, + MCCodeEmitter *Emitter) : MCELFStreamer(Context, MAB, OS, Emitter) { - RegInfoRecord = new MipsRegInfoRecord(this, Context, STI); + RegInfoRecord = new MipsRegInfoRecord(this, Context); MipsOptionRecords.push_back( std::unique_ptr<MipsRegInfoRecord>(RegInfoRecord)); } @@ -55,7 +55,7 @@ public: /// Overriding this function allows us to dismiss all labels that are /// candidates for marking as microMIPS when .section directive is processed. - void SwitchSection(const MCSection *Section, + void SwitchSection(MCSection *Section, const MCExpr *Subsection = nullptr) override; /// Overriding this function allows us to dismiss all labels that are @@ -65,10 +65,13 @@ public: /// Emits all the option records stored up until the point it's called. void EmitMipsOptionRecords(); + + /// Mark labels as microMIPS, if necessary for the subtarget. + void createPendingLabelRelocs(); }; MCELFStreamer *createMipsELFStreamer(MCContext &Context, MCAsmBackend &MAB, - raw_ostream &OS, MCCodeEmitter *Emitter, - const MCSubtargetInfo &STI, bool RelaxAll); + raw_pwrite_stream &OS, + MCCodeEmitter *Emitter, bool RelaxAll); } // namespace llvm. #endif diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h index 71c11d7..e601963 100644 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h +++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h @@ -18,7 +18,7 @@ namespace Mips { // one can have multiple fixup types for a given relocation and thus need // to be uniquely named. // - // This table *must* be in the save order of + // This table *must* be in the same order of // MCFixupKindInfo Infos[Mips::NumTargetFixupKinds] // in MipsAsmBackend.cpp. // @@ -161,6 +161,9 @@ namespace Mips { // resulting in - R_MICROMIPS_PC7_S1 fixup_MICROMIPS_PC7_S1, + // resulting in - R_MICROMIPS_PC10_S1 + fixup_MICROMIPS_PC10_S1, + // resulting in - R_MICROMIPS_PC16_S1 fixup_MICROMIPS_PC16_S1, diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp index e2bd5a8..4d55458 100644 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp +++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp @@ -18,8 +18,7 @@ using namespace llvm; void MipsMCAsmInfo::anchor() { } -MipsMCAsmInfo::MipsMCAsmInfo(StringRef TT) { - Triple TheTriple(TT); +MipsMCAsmInfo::MipsMCAsmInfo(const Triple &TheTriple) { if ((TheTriple.getArch() == Triple::mips) || (TheTriple.getArch() == Triple::mips64)) IsLittleEndian = false; diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h index 59ff1c4..5d23fcb 100644 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h +++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h @@ -17,12 +17,12 @@ #include "llvm/MC/MCAsmInfoELF.h" namespace llvm { - class StringRef; + class Triple; class MipsMCAsmInfo : public MCAsmInfoELF { void anchor() override; public: - explicit MipsMCAsmInfo(StringRef TT); + explicit MipsMCAsmInfo(const Triple &TheTriple); }; } // namespace llvm diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp index a54a2eb..93925bf 100644 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -23,6 +23,7 @@ #include "llvm/MC/MCFixup.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/raw_ostream.h" @@ -35,14 +36,12 @@ namespace llvm { MCCodeEmitter *createMipsMCCodeEmitterEB(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, - const MCSubtargetInfo &STI, MCContext &Ctx) { return new MipsMCCodeEmitter(MCII, Ctx, false); } MCCodeEmitter *createMipsMCCodeEmitterEL(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, - const MCSubtargetInfo &STI, MCContext &Ctx) { return new MipsMCCodeEmitter(MCII, Ctx, true); } @@ -114,7 +113,11 @@ static void LowerDextDins(MCInst& InstIn) { } bool MipsMCCodeEmitter::isMicroMips(const MCSubtargetInfo &STI) const { - return STI.getFeatureBits() & Mips::FeatureMicroMips; + return STI.getFeatureBits()[Mips::FeatureMicroMips]; +} + +bool MipsMCCodeEmitter::isMips32r6(const MCSubtargetInfo &STI) const { + return STI.getFeatureBits()[Mips::FeatureMips32r6]; } void MipsMCCodeEmitter::EmitByte(unsigned char C, raw_ostream &OS) const { @@ -139,10 +142,10 @@ void MipsMCCodeEmitter::EmitInstruction(uint64_t Val, unsigned Size, } } -/// EncodeInstruction - Emit the instruction. +/// encodeInstruction - Emit the instruction. /// Size the instruction with Desc.getSize(). void MipsMCCodeEmitter:: -EncodeInstruction(const MCInst &MI, raw_ostream &OS, +encodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { @@ -175,13 +178,22 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, unsigned Opcode = TmpInst.getOpcode(); if ((Opcode != Mips::NOP) && (Opcode != Mips::SLL) && (Opcode != Mips::SLL_MM) && !Binary) - llvm_unreachable("unimplemented opcode in EncodeInstruction()"); + llvm_unreachable("unimplemented opcode in encodeInstruction()"); + + int NewOpcode = -1; + if (isMicroMips(STI)) { + if (isMips32r6(STI)) { + NewOpcode = Mips::MipsR62MicroMipsR6(Opcode, Mips::Arch_micromipsr6); + if (NewOpcode == -1) + NewOpcode = Mips::Std2MicroMipsR6(Opcode, Mips::Arch_micromipsr6); + } + else + NewOpcode = Mips::Std2MicroMips(Opcode, Mips::Arch_micromips); - if (STI.getFeatureBits() & Mips::FeatureMicroMips) { - int NewOpcode = Mips::Std2MicroMips (Opcode, Mips::Arch_micromips); if (NewOpcode != -1) { if (Fixups.size() > N) Fixups.pop_back(); + Opcode = NewOpcode; TmpInst.setOpcode (NewOpcode); Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); @@ -215,7 +227,7 @@ getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, "getBranchTargetOpValue expects only expressions or immediates"); const MCExpr *Expr = MO.getExpr(); - Fixups.push_back(MCFixup::Create(0, Expr, + Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(Mips::fixup_Mips_PC16))); return 0; } @@ -237,11 +249,33 @@ getBranchTarget7OpValueMM(const MCInst &MI, unsigned OpNo, "getBranchTargetOpValueMM expects only expressions or immediates"); const MCExpr *Expr = MO.getExpr(); - Fixups.push_back(MCFixup::Create(0, Expr, + Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(Mips::fixup_MICROMIPS_PC7_S1))); return 0; } +/// getBranchTargetOpValueMMPC10 - Return binary encoding of the microMIPS +/// 10-bit branch target operand. If the machine operand requires relocation, +/// record the relocation and return zero. +unsigned MipsMCCodeEmitter:: +getBranchTargetOpValueMMPC10(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + + const MCOperand &MO = MI.getOperand(OpNo); + + // If the destination is an immediate, divide by 2. + if (MO.isImm()) return MO.getImm() >> 1; + + assert(MO.isExpr() && + "getBranchTargetOpValuePC10 expects only expressions or immediates"); + + const MCExpr *Expr = MO.getExpr(); + Fixups.push_back(MCFixup::create(0, Expr, + MCFixupKind(Mips::fixup_MICROMIPS_PC10_S1))); + return 0; +} + /// getBranchTargetOpValue - Return binary encoding of the microMIPS branch /// target operand. If the machine operand requires relocation, /// record the relocation and return zero. @@ -259,7 +293,7 @@ getBranchTargetOpValueMM(const MCInst &MI, unsigned OpNo, "getBranchTargetOpValueMM expects only expressions or immediates"); const MCExpr *Expr = MO.getExpr(); - Fixups.push_back(MCFixup::Create(0, Expr, + Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(Mips:: fixup_MICROMIPS_PC16_S1))); return 0; @@ -282,7 +316,7 @@ getBranchTarget21OpValue(const MCInst &MI, unsigned OpNo, "getBranchTarget21OpValue expects only expressions or immediates"); const MCExpr *Expr = MO.getExpr(); - Fixups.push_back(MCFixup::Create(0, Expr, + Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(Mips::fixup_MIPS_PC21_S2))); return 0; } @@ -304,7 +338,7 @@ getBranchTarget26OpValue(const MCInst &MI, unsigned OpNo, "getBranchTarget26OpValue expects only expressions or immediates"); const MCExpr *Expr = MO.getExpr(); - Fixups.push_back(MCFixup::Create(0, Expr, + Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(Mips::fixup_MIPS_PC26_S2))); return 0; } @@ -344,7 +378,7 @@ getJumpTargetOpValue(const MCInst &MI, unsigned OpNo, "getJumpTargetOpValue expects only expressions or an immediate"); const MCExpr *Expr = MO.getExpr(); - Fixups.push_back(MCFixup::Create(0, Expr, + Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(Mips::fixup_Mips_26))); return 0; } @@ -362,7 +396,7 @@ getJumpTargetOpValueMM(const MCInst &MI, unsigned OpNo, "getJumpTargetOpValueMM expects only expressions or an immediate"); const MCExpr *Expr = MO.getExpr(); - Fixups.push_back(MCFixup::Create(0, Expr, + Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(Mips::fixup_MICROMIPS_26_S1))); return 0; } @@ -429,11 +463,11 @@ getSImm9AddiuspValue(const MCInst &MI, unsigned OpNo, } unsigned MipsMCCodeEmitter:: -getExprOpValue(const MCExpr *Expr,SmallVectorImpl<MCFixup> &Fixups, +getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { int64_t Res; - if (Expr->EvaluateAsAbsolute(Res)) + if (Expr->evaluateAsAbsolute(Res)) return Res; MCExpr::ExprKind Kind = Expr->getKind(); @@ -468,7 +502,7 @@ getExprOpValue(const MCExpr *Expr,SmallVectorImpl<MCFixup> &Fixups, : Mips::fixup_Mips_LO16; break; } - Fixups.push_back(MCFixup::Create(0, MipsExpr, MCFixupKind(FixupKind))); + Fixups.push_back(MCFixup::create(0, MipsExpr, MCFixupKind(FixupKind))); return 0; } @@ -478,6 +512,9 @@ getExprOpValue(const MCExpr *Expr,SmallVectorImpl<MCFixup> &Fixups, switch(cast<MCSymbolRefExpr>(Expr)->getKind()) { default: llvm_unreachable("Unknown fixup kind!"); break; + case MCSymbolRefExpr::VK_None: + FixupKind = Mips::fixup_Mips_32; // FIXME: This is ok for O32/N32 but not N64. + break; case MCSymbolRefExpr::VK_Mips_GPOFF_HI : FixupKind = Mips::fixup_Mips_GPOFF_HI; break; @@ -572,7 +609,7 @@ getExprOpValue(const MCExpr *Expr,SmallVectorImpl<MCFixup> &Fixups, break; } // switch - Fixups.push_back(MCFixup::Create(0, Expr, MCFixupKind(FixupKind))); + Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(FixupKind))); return 0; } return 0; @@ -714,6 +751,21 @@ getMemEncodingMMSPImm5Lsl2(const MCInst &MI, unsigned OpNo, } unsigned MipsMCCodeEmitter:: +getMemEncodingMMGPImm7Lsl2(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + // Register is encoded in bits 9-7, offset is encoded in bits 6-0. + assert(MI.getOperand(OpNo).isReg() && + MI.getOperand(OpNo).getReg() == Mips::GP && + "Unexpected base register!"); + + unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), + Fixups, STI) >> 2; + + return OffBits & 0x7F; +} + +unsigned MipsMCCodeEmitter:: getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { @@ -808,7 +860,7 @@ MipsMCCodeEmitter::getSimm19Lsl2Encoding(const MCInst &MI, unsigned OpNo, "getSimm19Lsl2Encoding expects only expressions or an immediate"); const MCExpr *Expr = MO.getExpr(); - Fixups.push_back(MCFixup::Create(0, Expr, + Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(Mips::fixup_MIPS_PC19_S2))); return 0; } @@ -829,7 +881,7 @@ MipsMCCodeEmitter::getSimm18Lsl3Encoding(const MCInst &MI, unsigned OpNo, "getSimm18Lsl2Encoding expects only expressions or an immediate"); const MCExpr *Expr = MO.getExpr(); - Fixups.push_back(MCFixup::Create(0, Expr, + Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(Mips::fixup_MIPS_PC18_S3))); return 0; } @@ -905,4 +957,50 @@ MipsMCCodeEmitter::getRegisterPairOpValue(const MCInst &MI, unsigned OpNo, return getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI); } +unsigned +MipsMCCodeEmitter::getMovePRegPairOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + unsigned res = 0; + + if (MI.getOperand(0).getReg() == Mips::A1 && + MI.getOperand(1).getReg() == Mips::A2) + res = 0; + else if (MI.getOperand(0).getReg() == Mips::A1 && + MI.getOperand(1).getReg() == Mips::A3) + res = 1; + else if (MI.getOperand(0).getReg() == Mips::A2 && + MI.getOperand(1).getReg() == Mips::A3) + res = 2; + else if (MI.getOperand(0).getReg() == Mips::A0 && + MI.getOperand(1).getReg() == Mips::S5) + res = 3; + else if (MI.getOperand(0).getReg() == Mips::A0 && + MI.getOperand(1).getReg() == Mips::S6) + res = 4; + else if (MI.getOperand(0).getReg() == Mips::A0 && + MI.getOperand(1).getReg() == Mips::A1) + res = 5; + else if (MI.getOperand(0).getReg() == Mips::A0 && + MI.getOperand(1).getReg() == Mips::A2) + res = 6; + else if (MI.getOperand(0).getReg() == Mips::A0 && + MI.getOperand(1).getReg() == Mips::A3) + res = 7; + + return res; +} + +unsigned +MipsMCCodeEmitter::getSimm23Lsl2Encoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpNo); + assert(MO.isImm() && "getSimm23Lsl2Encoding expects only an immediate"); + // The immediate is encoded as 'immediate >> 2'. + unsigned Res = static_cast<unsigned>(MO.getImm()); + assert((Res & 3) == 0); + return Res >> 2; +} + #include "MipsGenMCCodeEmitter.inc" diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h index 0f0f49d..911cc2f 100644 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h +++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h @@ -31,26 +31,27 @@ class MCSubtargetInfo; class raw_ostream; class MipsMCCodeEmitter : public MCCodeEmitter { - MipsMCCodeEmitter(const MipsMCCodeEmitter &) LLVM_DELETED_FUNCTION; - void operator=(const MipsMCCodeEmitter &) LLVM_DELETED_FUNCTION; + MipsMCCodeEmitter(const MipsMCCodeEmitter &) = delete; + void operator=(const MipsMCCodeEmitter &) = delete; const MCInstrInfo &MCII; MCContext &Ctx; bool IsLittleEndian; bool isMicroMips(const MCSubtargetInfo &STI) const; + bool isMips32r6(const MCSubtargetInfo &STI) const; public: MipsMCCodeEmitter(const MCInstrInfo &mcii, MCContext &Ctx_, bool IsLittle) : MCII(mcii), Ctx(Ctx_), IsLittleEndian(IsLittle) {} - ~MipsMCCodeEmitter() {} + ~MipsMCCodeEmitter() override {} void EmitByte(unsigned char C, raw_ostream &OS) const; void EmitInstruction(uint64_t Val, unsigned Size, const MCSubtargetInfo &STI, raw_ostream &OS) const; - void EncodeInstruction(const MCInst &MI, raw_ostream &OS, + void encodeInstruction(const MCInst &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const override; @@ -108,6 +109,13 @@ public: SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; + // getBranchTargetOpValueMMPC10 - Return binary encoding of the microMIPS + // 10-bit branch target operand. If the machine operand requires relocation, + // record the relocation and return zero. + unsigned getBranchTargetOpValueMMPC10(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; + // getBranchTargetOpValue - Return binary encoding of the microMIPS branch // target operand. If the machine operand requires relocation, // record the relocation and return zero. @@ -161,6 +169,9 @@ public: unsigned getMemEncodingMMSPImm5Lsl2(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; + unsigned getMemEncodingMMGPImm7Lsl2(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; unsigned getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; @@ -198,6 +209,14 @@ public: SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; + unsigned getMovePRegPairOpValue(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; + + unsigned getSimm23Lsl2Encoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; + unsigned getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp index 74490f3..c85fc48 100644 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp +++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp @@ -41,7 +41,7 @@ bool MipsMCExpr::isSupportedBinaryExpr(MCSymbolRefExpr::VariantKind VK, } const MipsMCExpr* -MipsMCExpr::Create(MCSymbolRefExpr::VariantKind VK, const MCExpr *Expr, +MipsMCExpr::create(MCSymbolRefExpr::VariantKind VK, const MCExpr *Expr, MCContext &Ctx) { VariantKind Kind; switch (VK) { @@ -64,7 +64,7 @@ MipsMCExpr::Create(MCSymbolRefExpr::VariantKind VK, const MCExpr *Expr, return new (Ctx) MipsMCExpr(Kind, Expr); } -void MipsMCExpr::PrintImpl(raw_ostream &OS) const { +void MipsMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { switch (Kind) { default: llvm_unreachable("Invalid kind!"); case VK_Mips_LO: OS << "%lo"; break; @@ -74,15 +74,15 @@ void MipsMCExpr::PrintImpl(raw_ostream &OS) const { } OS << '('; - Expr->print(OS); + Expr->print(OS, MAI); OS << ')'; } bool -MipsMCExpr::EvaluateAsRelocatableImpl(MCValue &Res, +MipsMCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout, const MCFixup *Fixup) const { - return getSubExpr()->EvaluateAsRelocatable(Res, Layout, Fixup); + return getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup); } void MipsMCExpr::visitUsedExpr(MCStreamer &Streamer) const { diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h index 2b8f0c8..fd2ed17 100644 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h +++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h @@ -37,7 +37,7 @@ public: static bool isSupportedBinaryExpr(MCSymbolRefExpr::VariantKind VK, const MCBinaryExpr *BE); - static const MipsMCExpr *Create(MCSymbolRefExpr::VariantKind VK, + static const MipsMCExpr *create(MCSymbolRefExpr::VariantKind VK, const MCExpr *Expr, MCContext &Ctx); /// getOpcode - Get the kind of this expression. @@ -46,13 +46,13 @@ public: /// getSubExpr - Get the child of this expression. const MCExpr *getSubExpr() const { return Expr; } - void PrintImpl(raw_ostream &OS) const override; - bool EvaluateAsRelocatableImpl(MCValue &Res, + void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override; + bool evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout, const MCFixup *Fixup) const override; void visitUsedExpr(MCStreamer &Streamer) const override; - const MCSection *FindAssociatedSection() const override { - return getSubExpr()->FindAssociatedSection(); + MCSection *findAssociatedSection() const override { + return getSubExpr()->findAssociatedSection(); } // There are no TLS MipsMCExprs at the moment. diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h index e756b47..687b800 100644 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h +++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h @@ -23,10 +23,8 @@ bool baseRegNeedsLoadStoreMask(unsigned Reg); // This function creates an MCELFStreamer for Mips NaCl. MCELFStreamer *createMipsNaClELFStreamer(MCContext &Context, MCAsmBackend &TAB, - raw_ostream &OS, - MCCodeEmitter *Emitter, - const MCSubtargetInfo &STI, - bool RelaxAll); + raw_pwrite_stream &OS, + MCCodeEmitter *Emitter, bool RelaxAll); } #endif diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp index bab4254..54d8863 100644 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp +++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp @@ -43,7 +43,7 @@ using namespace llvm; /// Select the Mips CPU for the given triple and cpu name. /// FIXME: Merge with the copy in MipsSubtarget.cpp -static inline StringRef selectMipsCPU(StringRef TT, StringRef CPU) { +StringRef MIPS_MC::selectMipsCPU(StringRef TT, StringRef CPU) { if (CPU.empty() || CPU == "generic") { Triple TheTriple(TT); if (TheTriple.getArch() == Triple::mips || @@ -69,13 +69,14 @@ static MCRegisterInfo *createMipsMCRegisterInfo(StringRef TT) { static MCSubtargetInfo *createMipsMCSubtargetInfo(StringRef TT, StringRef CPU, StringRef FS) { - CPU = selectMipsCPU(TT, CPU); + CPU = MIPS_MC::selectMipsCPU(TT, CPU); MCSubtargetInfo *X = new MCSubtargetInfo(); InitMipsMCSubtargetInfo(X, TT, CPU, FS); return X; } -static MCAsmInfo *createMipsMCAsmInfo(const MCRegisterInfo &MRI, StringRef TT) { +static MCAsmInfo *createMipsMCAsmInfo(const MCRegisterInfo &MRI, + const Triple &TT) { MCAsmInfo *MAI = new MipsMCAsmInfo(TT); unsigned SP = MRI.getDwarfRegNum(Mips::SP, true); @@ -93,108 +94,85 @@ static MCCodeGenInfo *createMipsMCCodeGenInfo(StringRef TT, Reloc::Model RM, RM = Reloc::Static; else if (RM == Reloc::Default) RM = Reloc::PIC_; - X->InitMCCodeGenInfo(RM, CM, OL); + X->initMCCodeGenInfo(RM, CM, OL); return X; } -static MCInstPrinter *createMipsMCInstPrinter(const Target &T, +static MCInstPrinter *createMipsMCInstPrinter(const Triple &T, unsigned SyntaxVariant, const MCAsmInfo &MAI, const MCInstrInfo &MII, - const MCRegisterInfo &MRI, - const MCSubtargetInfo &STI) { + const MCRegisterInfo &MRI) { return new MipsInstPrinter(MAI, MII, MRI); } -static MCStreamer *createMCStreamer(const Target &T, StringRef TT, - MCContext &Context, MCAsmBackend &MAB, - raw_ostream &OS, MCCodeEmitter *Emitter, - const MCSubtargetInfo &STI, bool RelaxAll) { +static MCStreamer *createMCStreamer(const Triple &T, MCContext &Context, + MCAsmBackend &MAB, raw_pwrite_stream &OS, + MCCodeEmitter *Emitter, bool RelaxAll) { MCStreamer *S; - if (!Triple(TT).isOSNaCl()) - S = createMipsELFStreamer(Context, MAB, OS, Emitter, STI, RelaxAll); + if (!T.isOSNaCl()) + S = createMipsELFStreamer(Context, MAB, OS, Emitter, RelaxAll); else - S = createMipsNaClELFStreamer(Context, MAB, OS, Emitter, STI, RelaxAll); - new MipsTargetELFStreamer(*S, STI); + S = createMipsNaClELFStreamer(Context, MAB, OS, Emitter, RelaxAll); return S; } -static MCStreamer * -createMCAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, - bool isVerboseAsm, bool useDwarfDirectory, - MCInstPrinter *InstPrint, MCCodeEmitter *CE, - MCAsmBackend *TAB, bool ShowInst) { - MCStreamer *S = llvm::createAsmStreamer( - Ctx, OS, isVerboseAsm, useDwarfDirectory, InstPrint, CE, TAB, ShowInst); - new MipsTargetAsmStreamer(*S, OS); - return S; +static MCTargetStreamer *createMipsAsmTargetStreamer(MCStreamer &S, + formatted_raw_ostream &OS, + MCInstPrinter *InstPrint, + bool isVerboseAsm) { + return new MipsTargetAsmStreamer(S, OS); } -static MCStreamer *createMipsNullStreamer(MCContext &Ctx) { - MCStreamer *S = llvm::createNullStreamer(Ctx); - new MipsTargetStreamer(*S); - return S; +static MCTargetStreamer *createMipsNullTargetStreamer(MCStreamer &S) { + return new MipsTargetStreamer(S); +} + +static MCTargetStreamer * +createMipsObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) { + return new MipsTargetELFStreamer(S, STI); } extern "C" void LLVMInitializeMipsTargetMC() { - // Register the MC asm info. - RegisterMCAsmInfoFn X(TheMipsTarget, createMipsMCAsmInfo); - RegisterMCAsmInfoFn Y(TheMipselTarget, createMipsMCAsmInfo); - RegisterMCAsmInfoFn A(TheMips64Target, createMipsMCAsmInfo); - RegisterMCAsmInfoFn B(TheMips64elTarget, createMipsMCAsmInfo); - - // Register the MC codegen info. - TargetRegistry::RegisterMCCodeGenInfo(TheMipsTarget, - createMipsMCCodeGenInfo); - TargetRegistry::RegisterMCCodeGenInfo(TheMipselTarget, - createMipsMCCodeGenInfo); - TargetRegistry::RegisterMCCodeGenInfo(TheMips64Target, - createMipsMCCodeGenInfo); - TargetRegistry::RegisterMCCodeGenInfo(TheMips64elTarget, - createMipsMCCodeGenInfo); - - // Register the MC instruction info. - TargetRegistry::RegisterMCInstrInfo(TheMipsTarget, createMipsMCInstrInfo); - TargetRegistry::RegisterMCInstrInfo(TheMipselTarget, createMipsMCInstrInfo); - TargetRegistry::RegisterMCInstrInfo(TheMips64Target, createMipsMCInstrInfo); - TargetRegistry::RegisterMCInstrInfo(TheMips64elTarget, - createMipsMCInstrInfo); - - // Register the MC register info. - TargetRegistry::RegisterMCRegInfo(TheMipsTarget, createMipsMCRegisterInfo); - TargetRegistry::RegisterMCRegInfo(TheMipselTarget, createMipsMCRegisterInfo); - TargetRegistry::RegisterMCRegInfo(TheMips64Target, createMipsMCRegisterInfo); - TargetRegistry::RegisterMCRegInfo(TheMips64elTarget, - createMipsMCRegisterInfo); + for (Target *T : {&TheMipsTarget, &TheMipselTarget, &TheMips64Target, + &TheMips64elTarget}) { + // Register the MC asm info. + RegisterMCAsmInfoFn X(*T, createMipsMCAsmInfo); + + // Register the MC codegen info. + TargetRegistry::RegisterMCCodeGenInfo(*T, createMipsMCCodeGenInfo); + + // Register the MC instruction info. + TargetRegistry::RegisterMCInstrInfo(*T, createMipsMCInstrInfo); + + // Register the MC register info. + TargetRegistry::RegisterMCRegInfo(*T, createMipsMCRegisterInfo); + + // Register the elf streamer. + TargetRegistry::RegisterELFStreamer(*T, createMCStreamer); + + // Register the asm target streamer. + TargetRegistry::RegisterAsmTargetStreamer(*T, createMipsAsmTargetStreamer); + + TargetRegistry::RegisterNullTargetStreamer(*T, + createMipsNullTargetStreamer); + + // Register the MC subtarget info. + TargetRegistry::RegisterMCSubtargetInfo(*T, createMipsMCSubtargetInfo); + + // Register the MCInstPrinter. + TargetRegistry::RegisterMCInstPrinter(*T, createMipsMCInstPrinter); + + TargetRegistry::RegisterObjectTargetStreamer( + *T, createMipsObjectTargetStreamer); + } // Register the MC Code Emitter - TargetRegistry::RegisterMCCodeEmitter(TheMipsTarget, - createMipsMCCodeEmitterEB); - TargetRegistry::RegisterMCCodeEmitter(TheMipselTarget, - createMipsMCCodeEmitterEL); - TargetRegistry::RegisterMCCodeEmitter(TheMips64Target, - createMipsMCCodeEmitterEB); - TargetRegistry::RegisterMCCodeEmitter(TheMips64elTarget, - createMipsMCCodeEmitterEL); - - // Register the object streamer. - TargetRegistry::RegisterMCObjectStreamer(TheMipsTarget, createMCStreamer); - TargetRegistry::RegisterMCObjectStreamer(TheMipselTarget, createMCStreamer); - TargetRegistry::RegisterMCObjectStreamer(TheMips64Target, createMCStreamer); - TargetRegistry::RegisterMCObjectStreamer(TheMips64elTarget, - createMCStreamer); - - // Register the asm streamer. - TargetRegistry::RegisterAsmStreamer(TheMipsTarget, createMCAsmStreamer); - TargetRegistry::RegisterAsmStreamer(TheMipselTarget, createMCAsmStreamer); - TargetRegistry::RegisterAsmStreamer(TheMips64Target, createMCAsmStreamer); - TargetRegistry::RegisterAsmStreamer(TheMips64elTarget, createMCAsmStreamer); - - TargetRegistry::RegisterNullStreamer(TheMipsTarget, createMipsNullStreamer); - TargetRegistry::RegisterNullStreamer(TheMipselTarget, createMipsNullStreamer); - TargetRegistry::RegisterNullStreamer(TheMips64Target, createMipsNullStreamer); - TargetRegistry::RegisterNullStreamer(TheMips64elTarget, - createMipsNullStreamer); + for (Target *T : {&TheMipsTarget, &TheMips64Target}) + TargetRegistry::RegisterMCCodeEmitter(*T, createMipsMCCodeEmitterEB); + + for (Target *T : {&TheMipselTarget, &TheMips64elTarget}) + TargetRegistry::RegisterMCCodeEmitter(*T, createMipsMCCodeEmitterEL); // Register the asm backend. TargetRegistry::RegisterMCAsmBackend(TheMipsTarget, @@ -206,23 +184,4 @@ extern "C" void LLVMInitializeMipsTargetMC() { TargetRegistry::RegisterMCAsmBackend(TheMips64elTarget, createMipsAsmBackendEL64); - // Register the MC subtarget info. - TargetRegistry::RegisterMCSubtargetInfo(TheMipsTarget, - createMipsMCSubtargetInfo); - TargetRegistry::RegisterMCSubtargetInfo(TheMipselTarget, - createMipsMCSubtargetInfo); - TargetRegistry::RegisterMCSubtargetInfo(TheMips64Target, - createMipsMCSubtargetInfo); - TargetRegistry::RegisterMCSubtargetInfo(TheMips64elTarget, - createMipsMCSubtargetInfo); - - // Register the MCInstPrinter. - TargetRegistry::RegisterMCInstPrinter(TheMipsTarget, - createMipsMCInstPrinter); - TargetRegistry::RegisterMCInstPrinter(TheMipselTarget, - createMipsMCInstPrinter); - TargetRegistry::RegisterMCInstPrinter(TheMips64Target, - createMipsMCInstPrinter); - TargetRegistry::RegisterMCInstPrinter(TheMips64elTarget, - createMipsMCInstPrinter); } diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h index f08a8f4..577a8b3 100644 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h +++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h @@ -27,6 +27,7 @@ class MCSubtargetInfo; class StringRef; class Target; class raw_ostream; +class raw_pwrite_stream; extern Target TheMipsTarget; extern Target TheMipselTarget; @@ -35,11 +36,9 @@ extern Target TheMips64elTarget; MCCodeEmitter *createMipsMCCodeEmitterEB(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, - const MCSubtargetInfo &STI, MCContext &Ctx); MCCodeEmitter *createMipsMCCodeEmitterEL(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, - const MCSubtargetInfo &STI, MCContext &Ctx); MCAsmBackend *createMipsAsmBackendEB32(const Target &T, @@ -55,10 +54,13 @@ MCAsmBackend *createMipsAsmBackendEL64(const Target &T, const MCRegisterInfo &MRI, StringRef TT, StringRef CPU); -MCObjectWriter *createMipsELFObjectWriter(raw_ostream &OS, - uint8_t OSABI, - bool IsLittleEndian, - bool Is64Bit); +MCObjectWriter *createMipsELFObjectWriter(raw_pwrite_stream &OS, uint8_t OSABI, + bool IsLittleEndian, bool Is64Bit); + +namespace MIPS_MC { +StringRef selectMipsCPU(StringRef TT, StringRef CPU); +} + } // End llvm namespace // Defines symbolic names for Mips registers. This defines a mapping from diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp index 92b8455..aef9bd3 100644 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp +++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp @@ -36,11 +36,11 @@ const unsigned LoadStoreStackMaskReg = Mips::T7; class MipsNaClELFStreamer : public MipsELFStreamer { public: - MipsNaClELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, - MCCodeEmitter *Emitter, const MCSubtargetInfo &STI) - : MipsELFStreamer(Context, TAB, OS, Emitter, STI), PendingCall(false) {} + MipsNaClELFStreamer(MCContext &Context, MCAsmBackend &TAB, + raw_pwrite_stream &OS, MCCodeEmitter *Emitter) + : MipsELFStreamer(Context, TAB, OS, Emitter), PendingCall(false) {} - ~MipsNaClELFStreamer() {} + ~MipsNaClELFStreamer() override {} private: // Whether we started the sandboxing sequence for calls. Calls are bundled @@ -94,9 +94,9 @@ private: const MCSubtargetInfo &STI) { MCInst MaskInst; MaskInst.setOpcode(Mips::AND); - MaskInst.addOperand(MCOperand::CreateReg(AddrReg)); - MaskInst.addOperand(MCOperand::CreateReg(AddrReg)); - MaskInst.addOperand(MCOperand::CreateReg(MaskReg)); + MaskInst.addOperand(MCOperand::createReg(AddrReg)); + MaskInst.addOperand(MCOperand::createReg(AddrReg)); + MaskInst.addOperand(MCOperand::createReg(MaskReg)); MipsELFStreamer::EmitInstruction(MaskInst, STI); } @@ -252,12 +252,10 @@ bool baseRegNeedsLoadStoreMask(unsigned Reg) { } MCELFStreamer *createMipsNaClELFStreamer(MCContext &Context, MCAsmBackend &TAB, - raw_ostream &OS, + raw_pwrite_stream &OS, MCCodeEmitter *Emitter, - const MCSubtargetInfo &STI, bool RelaxAll) { - MipsNaClELFStreamer *S = new MipsNaClELFStreamer(Context, TAB, OS, Emitter, - STI); + MipsNaClELFStreamer *S = new MipsNaClELFStreamer(Context, TAB, OS, Emitter); if (RelaxAll) S->getAssembler().setRelaxAll(true); diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp index 0ef2208..4911632 100644 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp +++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsOptionRecord.cpp @@ -9,14 +9,15 @@ #include "MipsOptionRecord.h" #include "MipsELFStreamer.h" +#include "MipsTargetStreamer.h" #include "llvm/MC/MCSectionELF.h" using namespace llvm; void MipsRegInfoRecord::EmitMipsOptionRecord() { MCAssembler &MCA = Streamer->getAssembler(); - Triple T(STI.getTargetTriple()); - uint64_t Features = STI.getFeatureBits(); + MipsTargetStreamer *MTS = + static_cast<MipsTargetStreamer *>(Streamer->getTargetStreamer()); Streamer->PushSection(); @@ -24,17 +25,17 @@ void MipsRegInfoRecord::EmitMipsOptionRecord() { // we don't emit .Mips.options for other ELFs other than N64. // Since .reginfo has the same information as .Mips.options (ODK_REGINFO), // we can use the same abstraction (MipsRegInfoRecord class) to handle both. - if (Features & Mips::FeatureN64) { + if (MTS->getABI().IsN64()) { // The EntrySize value of 1 seems strange since the records are neither // 1-byte long nor fixed length but it matches the value GAS emits. - const MCSectionELF *Sec = + MCSectionELF *Sec = Context.getELFSection(".MIPS.options", ELF::SHT_MIPS_OPTIONS, - ELF::SHF_ALLOC | ELF::SHF_MIPS_NOSTRIP, - SectionKind::getMetadata(), 1, ""); - MCA.getOrCreateSectionData(*Sec).setAlignment(8); + ELF::SHF_ALLOC | ELF::SHF_MIPS_NOSTRIP, 1, ""); + MCA.registerSection(*Sec); + Sec->setAlignment(8); Streamer->SwitchSection(Sec); - Streamer->EmitIntValue(1, 1); // kind + Streamer->EmitIntValue(ELF::ODK_REGINFO, 1); // kind Streamer->EmitIntValue(40, 1); // size Streamer->EmitIntValue(0, 2); // section Streamer->EmitIntValue(0, 4); // info @@ -46,11 +47,10 @@ void MipsRegInfoRecord::EmitMipsOptionRecord() { Streamer->EmitIntValue(ri_cprmask[3], 4); Streamer->EmitIntValue(ri_gp_value, 8); } else { - const MCSectionELF *Sec = - Context.getELFSection(".reginfo", ELF::SHT_MIPS_REGINFO, ELF::SHF_ALLOC, - SectionKind::getMetadata(), 24, ""); - MCA.getOrCreateSectionData(*Sec) - .setAlignment(Features & Mips::FeatureN32 ? 8 : 4); + MCSectionELF *Sec = Context.getELFSection(".reginfo", ELF::SHT_MIPS_REGINFO, + ELF::SHF_ALLOC, 24, ""); + MCA.registerSection(*Sec); + Sec->setAlignment(MTS->getABI().IsN32() ? 8 : 4); Streamer->SwitchSection(Sec); Streamer->EmitIntValue(ri_gprmask, 4); diff --git a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp index 1e092f2..a051f4c 100644 --- a/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ b/contrib/llvm/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -17,10 +17,9 @@ #include "MipsTargetObjectFile.h" #include "MipsTargetStreamer.h" #include "llvm/MC/MCContext.h" -#include "llvm/MC/MCELF.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCSubtargetInfo.h" -#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCSymbolELF.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ELF.h" #include "llvm/Support/ErrorHandling.h" @@ -43,6 +42,9 @@ void MipsTargetStreamer::emitDirectiveSetNoMacro() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetMsa() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetNoMsa() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetAt() { forbidModuleDirective(); } +void MipsTargetStreamer::emitDirectiveSetAtWithArg(unsigned RegNo) { + forbidModuleDirective(); +} void MipsTargetStreamer::emitDirectiveSetNoAt() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveEnd(StringRef Name) {} void MipsTargetStreamer::emitDirectiveEnt(const MCSymbol &Symbol) {} @@ -51,6 +53,7 @@ void MipsTargetStreamer::emitDirectiveNaN2008() {} void MipsTargetStreamer::emitDirectiveNaNLegacy() {} void MipsTargetStreamer::emitDirectiveOptionPic0() {} void MipsTargetStreamer::emitDirectiveOptionPic2() {} +void MipsTargetStreamer::emitDirectiveInsn() { forbidModuleDirective(); } void MipsTargetStreamer::emitFrame(unsigned StackReg, unsigned StackSize, unsigned ReturnReg) {} void MipsTargetStreamer::emitMask(unsigned CPUBitmask, int CPUTopSavedRegOff) {} @@ -59,7 +62,7 @@ void MipsTargetStreamer::emitFMask(unsigned FPUBitmask, int FPUTopSavedRegOff) { void MipsTargetStreamer::emitDirectiveSetArch(StringRef Arch) { forbidModuleDirective(); } -void MipsTargetStreamer::emitDirectiveSetMips0() {} +void MipsTargetStreamer::emitDirectiveSetMips0() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetMips1() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetMips2() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetMips3() { forbidModuleDirective(); } @@ -67,12 +70,22 @@ void MipsTargetStreamer::emitDirectiveSetMips4() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetMips5() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetMips32() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetMips32R2() { forbidModuleDirective(); } +void MipsTargetStreamer::emitDirectiveSetMips32R3() { forbidModuleDirective(); } +void MipsTargetStreamer::emitDirectiveSetMips32R5() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetMips32R6() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetMips64() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetMips64R2() { forbidModuleDirective(); } +void MipsTargetStreamer::emitDirectiveSetMips64R3() { forbidModuleDirective(); } +void MipsTargetStreamer::emitDirectiveSetMips64R5() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetMips64R6() { forbidModuleDirective(); } -void MipsTargetStreamer::emitDirectiveSetPop() {} -void MipsTargetStreamer::emitDirectiveSetPush() {} +void MipsTargetStreamer::emitDirectiveSetPop() { forbidModuleDirective(); } +void MipsTargetStreamer::emitDirectiveSetPush() { forbidModuleDirective(); } +void MipsTargetStreamer::emitDirectiveSetSoftFloat() { + forbidModuleDirective(); +} +void MipsTargetStreamer::emitDirectiveSetHardFloat() { + forbidModuleDirective(); +} void MipsTargetStreamer::emitDirectiveSetDsp() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetNoDsp() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveCpLoad(unsigned RegNo) {} @@ -84,6 +97,10 @@ void MipsTargetStreamer::emitDirectiveModuleOddSPReg(bool Enabled, if (!Enabled && !IsO32ABI) report_fatal_error("+nooddspreg is only valid for O32"); } +void MipsTargetStreamer::emitDirectiveSetFp( + MipsABIFlagsSection::FpABIKind Value) { + forbidModuleDirective(); +} MipsTargetAsmStreamer::MipsTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS) @@ -144,6 +161,11 @@ void MipsTargetAsmStreamer::emitDirectiveSetAt() { MipsTargetStreamer::emitDirectiveSetAt(); } +void MipsTargetAsmStreamer::emitDirectiveSetAtWithArg(unsigned RegNo) { + OS << "\t.set\tat=$" << Twine(RegNo) << "\n"; + MipsTargetStreamer::emitDirectiveSetAtWithArg(RegNo); +} + void MipsTargetAsmStreamer::emitDirectiveSetNoAt() { OS << "\t.set\tnoat\n"; MipsTargetStreamer::emitDirectiveSetNoAt(); @@ -173,6 +195,11 @@ void MipsTargetAsmStreamer::emitDirectiveOptionPic2() { OS << "\t.option\tpic2\n"; } +void MipsTargetAsmStreamer::emitDirectiveInsn() { + MipsTargetStreamer::emitDirectiveInsn(); + OS << "\t.insn\n"; +} + void MipsTargetAsmStreamer::emitFrame(unsigned StackReg, unsigned StackSize, unsigned ReturnReg) { OS << "\t.frame\t$" @@ -186,7 +213,10 @@ void MipsTargetAsmStreamer::emitDirectiveSetArch(StringRef Arch) { MipsTargetStreamer::emitDirectiveSetArch(Arch); } -void MipsTargetAsmStreamer::emitDirectiveSetMips0() { OS << "\t.set\tmips0\n"; } +void MipsTargetAsmStreamer::emitDirectiveSetMips0() { + OS << "\t.set\tmips0\n"; + MipsTargetStreamer::emitDirectiveSetMips0(); +} void MipsTargetAsmStreamer::emitDirectiveSetMips1() { OS << "\t.set\tmips1\n"; @@ -223,6 +253,16 @@ void MipsTargetAsmStreamer::emitDirectiveSetMips32R2() { MipsTargetStreamer::emitDirectiveSetMips32R2(); } +void MipsTargetAsmStreamer::emitDirectiveSetMips32R3() { + OS << "\t.set\tmips32r3\n"; + MipsTargetStreamer::emitDirectiveSetMips32R3(); +} + +void MipsTargetAsmStreamer::emitDirectiveSetMips32R5() { + OS << "\t.set\tmips32r5\n"; + MipsTargetStreamer::emitDirectiveSetMips32R5(); +} + void MipsTargetAsmStreamer::emitDirectiveSetMips32R6() { OS << "\t.set\tmips32r6\n"; MipsTargetStreamer::emitDirectiveSetMips32R6(); @@ -238,6 +278,16 @@ void MipsTargetAsmStreamer::emitDirectiveSetMips64R2() { MipsTargetStreamer::emitDirectiveSetMips64R2(); } +void MipsTargetAsmStreamer::emitDirectiveSetMips64R3() { + OS << "\t.set\tmips64r3\n"; + MipsTargetStreamer::emitDirectiveSetMips64R3(); +} + +void MipsTargetAsmStreamer::emitDirectiveSetMips64R5() { + OS << "\t.set\tmips64r5\n"; + MipsTargetStreamer::emitDirectiveSetMips64R5(); +} + void MipsTargetAsmStreamer::emitDirectiveSetMips64R6() { OS << "\t.set\tmips64r6\n"; MipsTargetStreamer::emitDirectiveSetMips64R6(); @@ -253,9 +303,25 @@ void MipsTargetAsmStreamer::emitDirectiveSetNoDsp() { MipsTargetStreamer::emitDirectiveSetNoDsp(); } -void MipsTargetAsmStreamer::emitDirectiveSetPop() { OS << "\t.set\tpop\n"; } +void MipsTargetAsmStreamer::emitDirectiveSetPop() { + OS << "\t.set\tpop\n"; + MipsTargetStreamer::emitDirectiveSetPop(); +} -void MipsTargetAsmStreamer::emitDirectiveSetPush() { OS << "\t.set\tpush\n"; } +void MipsTargetAsmStreamer::emitDirectiveSetPush() { + OS << "\t.set\tpush\n"; + MipsTargetStreamer::emitDirectiveSetPush(); +} + +void MipsTargetAsmStreamer::emitDirectiveSetSoftFloat() { + OS << "\t.set\tsoftfloat\n"; + MipsTargetStreamer::emitDirectiveSetSoftFloat(); +} + +void MipsTargetAsmStreamer::emitDirectiveSetHardFloat() { + OS << "\t.set\thardfloat\n"; + MipsTargetStreamer::emitDirectiveSetHardFloat(); +} // Print a 32 bit hex number with all numbers. static void printHex32(unsigned Value, raw_ostream &OS) { @@ -307,22 +373,18 @@ void MipsTargetAsmStreamer::emitDirectiveModuleFP( MipsABIFlagsSection::FpABIKind Value, bool Is32BitABI) { MipsTargetStreamer::emitDirectiveModuleFP(Value, Is32BitABI); - StringRef ModuleValue; OS << "\t.module\tfp="; OS << ABIFlagsSection.getFpABIString(Value) << "\n"; } void MipsTargetAsmStreamer::emitDirectiveSetFp( MipsABIFlagsSection::FpABIKind Value) { - StringRef ModuleValue; + MipsTargetStreamer::emitDirectiveSetFp(Value); + OS << "\t.set\tfp="; OS << ABIFlagsSection.getFpABIString(Value) << "\n"; } -void MipsTargetAsmStreamer::emitMipsAbiFlags() { - // No action required for text output. -} - void MipsTargetAsmStreamer::emitDirectiveModuleOddSPReg(bool Enabled, bool IsO32ABI) { MipsTargetStreamer::emitDirectiveModuleOddSPReg(Enabled, IsO32ABI); @@ -335,77 +397,72 @@ MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI) : MipsTargetStreamer(S), MicroMipsEnabled(false), STI(STI) { MCAssembler &MCA = getStreamer().getAssembler(); - uint64_t Features = STI.getFeatureBits(); - Triple T(STI.getTargetTriple()); - Pic = (MCA.getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_) - ? true - : false; - - // Update e_header flags - unsigned EFlags = 0; + Pic = MCA.getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_; + + const FeatureBitset &Features = STI.getFeatureBits(); + + // Set the header flags that we can in the constructor. + // FIXME: This is a fairly terrible hack. We set the rest + // of these in the destructor. The problem here is two-fold: + // + // a: Some of the eflags can be set/reset by directives. + // b: There aren't any usage paths that initialize the ABI + // pointer until after we initialize either an assembler + // or the target machine. + // We can fix this by making the target streamer construct + // the ABI, but this is fraught with wide ranging dependency + // issues as well. + unsigned EFlags = MCA.getELFHeaderEFlags(); // Architecture - if (Features & Mips::FeatureMips64r6) + if (Features[Mips::FeatureMips64r6]) EFlags |= ELF::EF_MIPS_ARCH_64R6; - else if (Features & Mips::FeatureMips64r2) + else if (Features[Mips::FeatureMips64r2] || + Features[Mips::FeatureMips64r3] || + Features[Mips::FeatureMips64r5]) EFlags |= ELF::EF_MIPS_ARCH_64R2; - else if (Features & Mips::FeatureMips64) + else if (Features[Mips::FeatureMips64]) EFlags |= ELF::EF_MIPS_ARCH_64; - else if (Features & Mips::FeatureMips5) + else if (Features[Mips::FeatureMips5]) EFlags |= ELF::EF_MIPS_ARCH_5; - else if (Features & Mips::FeatureMips4) + else if (Features[Mips::FeatureMips4]) EFlags |= ELF::EF_MIPS_ARCH_4; - else if (Features & Mips::FeatureMips3) + else if (Features[Mips::FeatureMips3]) EFlags |= ELF::EF_MIPS_ARCH_3; - else if (Features & Mips::FeatureMips32r6) + else if (Features[Mips::FeatureMips32r6]) EFlags |= ELF::EF_MIPS_ARCH_32R6; - else if (Features & Mips::FeatureMips32r2) + else if (Features[Mips::FeatureMips32r2] || + Features[Mips::FeatureMips32r3] || + Features[Mips::FeatureMips32r5]) EFlags |= ELF::EF_MIPS_ARCH_32R2; - else if (Features & Mips::FeatureMips32) + else if (Features[Mips::FeatureMips32]) EFlags |= ELF::EF_MIPS_ARCH_32; - else if (Features & Mips::FeatureMips2) + else if (Features[Mips::FeatureMips2]) EFlags |= ELF::EF_MIPS_ARCH_2; else EFlags |= ELF::EF_MIPS_ARCH_1; - // ABI - // N64 does not require any ABI bits. - if (Features & Mips::FeatureO32) - EFlags |= ELF::EF_MIPS_ABI_O32; - else if (Features & Mips::FeatureN32) - EFlags |= ELF::EF_MIPS_ABI2; - - if (Features & Mips::FeatureGP64Bit) { - if (Features & Mips::FeatureO32) - EFlags |= ELF::EF_MIPS_32BITMODE; /* Compatibility Mode */ - } else if (Features & Mips::FeatureMips64r2 || Features & Mips::FeatureMips64) - EFlags |= ELF::EF_MIPS_32BITMODE; - // Other options. - if (Features & Mips::FeatureNaN2008) + if (Features[Mips::FeatureNaN2008]) EFlags |= ELF::EF_MIPS_NAN2008; // -mabicalls and -mplt are not implemented but we should act as if they were // given. EFlags |= ELF::EF_MIPS_CPIC; - if (Features & Mips::FeatureN64) - EFlags |= ELF::EF_MIPS_PIC; MCA.setELFHeaderEFlags(EFlags); } -void MipsTargetELFStreamer::emitLabel(MCSymbol *Symbol) { +void MipsTargetELFStreamer::emitLabel(MCSymbol *S) { + auto *Symbol = cast<MCSymbolELF>(S); if (!isMicroMipsEnabled()) return; - MCSymbolData &Data = getStreamer().getOrCreateSymbolData(Symbol); - uint8_t Type = MCELF::GetType(Data); + getStreamer().getAssembler().registerSymbol(*Symbol); + uint8_t Type = Symbol->getType(); if (Type != ELF::STT_FUNC) return; - // The "other" values are stored in the last 6 bits of the second byte - // The traditional defines for STO values assume the full byte and thus - // the shift to pack it. - MCELF::setOther(Data, ELF::STO_MIPS_MICROMIPS >> 2); + Symbol->setOther(ELF::STO_MIPS_MICROMIPS); } void MipsTargetELFStreamer::finish() { @@ -413,16 +470,42 @@ void MipsTargetELFStreamer::finish() { const MCObjectFileInfo &OFI = *MCA.getContext().getObjectFileInfo(); // .bss, .text and .data are always at least 16-byte aligned. - MCSectionData &TextSectionData = - MCA.getOrCreateSectionData(*OFI.getTextSection()); - MCSectionData &DataSectionData = - MCA.getOrCreateSectionData(*OFI.getDataSection()); - MCSectionData &BSSSectionData = - MCA.getOrCreateSectionData(*OFI.getBSSSection()); + MCSection &TextSection = *OFI.getTextSection(); + MCA.registerSection(TextSection); + MCSection &DataSection = *OFI.getDataSection(); + MCA.registerSection(DataSection); + MCSection &BSSSection = *OFI.getBSSSection(); + MCA.registerSection(BSSSection); + + TextSection.setAlignment(std::max(16u, TextSection.getAlignment())); + DataSection.setAlignment(std::max(16u, DataSection.getAlignment())); + BSSSection.setAlignment(std::max(16u, BSSSection.getAlignment())); + + const FeatureBitset &Features = STI.getFeatureBits(); + + // Update e_header flags. See the FIXME and comment above in + // the constructor for a full rundown on this. + unsigned EFlags = MCA.getELFHeaderEFlags(); + + // ABI + // N64 does not require any ABI bits. + if (getABI().IsO32()) + EFlags |= ELF::EF_MIPS_ABI_O32; + else if (getABI().IsN32()) + EFlags |= ELF::EF_MIPS_ABI2; - TextSectionData.setAlignment(std::max(16u, TextSectionData.getAlignment())); - DataSectionData.setAlignment(std::max(16u, DataSectionData.getAlignment())); - BSSSectionData.setAlignment(std::max(16u, BSSSectionData.getAlignment())); + if (Features[Mips::FeatureGP64Bit]) { + if (getABI().IsO32()) + EFlags |= ELF::EF_MIPS_32BITMODE; /* Compatibility Mode */ + } else if (Features[Mips::FeatureMips64r2] || Features[Mips::FeatureMips64]) + EFlags |= ELF::EF_MIPS_32BITMODE; + + // If we've set the cpic eflag and we're n64, go ahead and set the pic + // one as well. + if (EFlags & ELF::EF_MIPS_CPIC && getABI().IsN64()) + EFlags |= ELF::EF_MIPS_PIC; + + MCA.setELFHeaderEFlags(EFlags); // Emit all the option records. // At the moment we are only emitting .Mips.options (ODK_REGINFO) and @@ -433,24 +516,18 @@ void MipsTargetELFStreamer::finish() { emitMipsAbiFlags(); } -void MipsTargetELFStreamer::emitAssignment(MCSymbol *Symbol, - const MCExpr *Value) { +void MipsTargetELFStreamer::emitAssignment(MCSymbol *S, const MCExpr *Value) { + auto *Symbol = cast<MCSymbolELF>(S); // If on rhs is micromips symbol then mark Symbol as microMips. if (Value->getKind() != MCExpr::SymbolRef) return; - const MCSymbol &RhsSym = - static_cast<const MCSymbolRefExpr *>(Value)->getSymbol(); - MCSymbolData &Data = getStreamer().getOrCreateSymbolData(&RhsSym); - uint8_t Type = MCELF::GetType(Data); - if ((Type != ELF::STT_FUNC) || - !(MCELF::getOther(Data) & (ELF::STO_MIPS_MICROMIPS >> 2))) + const auto &RhsSym = cast<MCSymbolELF>( + static_cast<const MCSymbolRefExpr *>(Value)->getSymbol()); + + if (!(RhsSym.getOther() & ELF::STO_MIPS_MICROMIPS)) return; - MCSymbolData &SymbolData = getStreamer().getOrCreateSymbolData(Symbol); - // The "other" values are stored in the last 6 bits of the second byte. - // The traditional defines for STO values assume the full byte and thus - // the shift to pack it. - MCELF::setOther(SymbolData, ELF::STO_MIPS_MICROMIPS >> 2); + Symbol->setOther(ELF::STO_MIPS_MICROMIPS); } MCELFStreamer &MipsTargetELFStreamer::getStreamer() { @@ -493,15 +570,14 @@ void MipsTargetELFStreamer::emitDirectiveEnd(StringRef Name) { MCContext &Context = MCA.getContext(); MCStreamer &OS = getStreamer(); - const MCSectionELF *Sec = Context.getELFSection(".pdr", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC | ELF::SHT_REL, - SectionKind::getMetadata()); + MCSectionELF *Sec = Context.getELFSection(".pdr", ELF::SHT_PROGBITS, + ELF::SHF_ALLOC | ELF::SHT_REL); const MCSymbolRefExpr *ExprRef = - MCSymbolRefExpr::Create(Name, MCSymbolRefExpr::VK_None, Context); + MCSymbolRefExpr::create(Name, MCSymbolRefExpr::VK_None, Context); - MCSectionData &SecData = MCA.getOrCreateSectionData(*Sec); - SecData.setAlignment(4); + MCA.registerSection(*Sec); + Sec->setAlignment(4); OS.PushSection(); @@ -572,6 +648,12 @@ void MipsTargetELFStreamer::emitDirectiveOptionPic2() { MCA.setELFHeaderEFlags(Flags); } +void MipsTargetELFStreamer::emitDirectiveInsn() { + MipsTargetStreamer::emitDirectiveInsn(); + MipsELFStreamer &MEF = static_cast<MipsELFStreamer &>(Streamer); + MEF.createPendingLabelRelocs(); +} + void MipsTargetELFStreamer::emitFrame(unsigned StackReg, unsigned StackSize, unsigned ReturnReg_) { MCContext &Context = getStreamer().getAssembler().getContext(); @@ -604,7 +686,7 @@ void MipsTargetELFStreamer::emitDirectiveCpLoad(unsigned RegNo) { // addui $gp, $gp, %lo(_gp_disp) // addu $gp, $gp, $reg // when support for position independent code is enabled. - if (!Pic || (isN32() || isN64())) + if (!Pic || (getABI().IsN32() || getABI().IsN64())) return; // There's a GNU extension controlled by -mno-shared that allows @@ -616,33 +698,33 @@ void MipsTargetELFStreamer::emitDirectiveCpLoad(unsigned RegNo) { StringRef SymName("_gp_disp"); MCAssembler &MCA = getStreamer().getAssembler(); - MCSymbol *GP_Disp = MCA.getContext().GetOrCreateSymbol(SymName); - MCA.getOrCreateSymbolData(*GP_Disp); + MCSymbol *GP_Disp = MCA.getContext().getOrCreateSymbol(SymName); + MCA.registerSymbol(*GP_Disp); MCInst TmpInst; TmpInst.setOpcode(Mips::LUi); - TmpInst.addOperand(MCOperand::CreateReg(Mips::GP)); - const MCSymbolRefExpr *HiSym = MCSymbolRefExpr::Create( + TmpInst.addOperand(MCOperand::createReg(Mips::GP)); + const MCSymbolRefExpr *HiSym = MCSymbolRefExpr::create( "_gp_disp", MCSymbolRefExpr::VK_Mips_ABS_HI, MCA.getContext()); - TmpInst.addOperand(MCOperand::CreateExpr(HiSym)); + TmpInst.addOperand(MCOperand::createExpr(HiSym)); getStreamer().EmitInstruction(TmpInst, STI); TmpInst.clear(); TmpInst.setOpcode(Mips::ADDiu); - TmpInst.addOperand(MCOperand::CreateReg(Mips::GP)); - TmpInst.addOperand(MCOperand::CreateReg(Mips::GP)); - const MCSymbolRefExpr *LoSym = MCSymbolRefExpr::Create( + TmpInst.addOperand(MCOperand::createReg(Mips::GP)); + TmpInst.addOperand(MCOperand::createReg(Mips::GP)); + const MCSymbolRefExpr *LoSym = MCSymbolRefExpr::create( "_gp_disp", MCSymbolRefExpr::VK_Mips_ABS_LO, MCA.getContext()); - TmpInst.addOperand(MCOperand::CreateExpr(LoSym)); + TmpInst.addOperand(MCOperand::createExpr(LoSym)); getStreamer().EmitInstruction(TmpInst, STI); TmpInst.clear(); TmpInst.setOpcode(Mips::ADDu); - TmpInst.addOperand(MCOperand::CreateReg(Mips::GP)); - TmpInst.addOperand(MCOperand::CreateReg(Mips::GP)); - TmpInst.addOperand(MCOperand::CreateReg(RegNo)); + TmpInst.addOperand(MCOperand::createReg(Mips::GP)); + TmpInst.addOperand(MCOperand::createReg(Mips::GP)); + TmpInst.addOperand(MCOperand::createReg(RegNo)); getStreamer().EmitInstruction(TmpInst, STI); forbidModuleDirective(); @@ -653,7 +735,7 @@ void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo, const MCSymbol &Sym, bool IsReg) { // Only N32 and N64 emit anything for .cpsetup iff PIC is set. - if (!Pic || !(isN32() || isN64())) + if (!Pic || !(getABI().IsN32() || getABI().IsN64())) return; MCAssembler &MCA = getStreamer().getAssembler(); @@ -663,43 +745,44 @@ void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo, if (IsReg) { // move $save, $gpreg Inst.setOpcode(Mips::DADDu); - Inst.addOperand(MCOperand::CreateReg(RegOrOffset)); - Inst.addOperand(MCOperand::CreateReg(Mips::GP)); - Inst.addOperand(MCOperand::CreateReg(Mips::ZERO)); + Inst.addOperand(MCOperand::createReg(RegOrOffset)); + Inst.addOperand(MCOperand::createReg(Mips::GP)); + Inst.addOperand(MCOperand::createReg(Mips::ZERO)); } else { // sd $gpreg, offset($sp) Inst.setOpcode(Mips::SD); - Inst.addOperand(MCOperand::CreateReg(Mips::GP)); - Inst.addOperand(MCOperand::CreateReg(Mips::SP)); - Inst.addOperand(MCOperand::CreateImm(RegOrOffset)); + Inst.addOperand(MCOperand::createReg(Mips::GP)); + Inst.addOperand(MCOperand::createReg(Mips::SP)); + Inst.addOperand(MCOperand::createImm(RegOrOffset)); } getStreamer().EmitInstruction(Inst, STI); Inst.clear(); - const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create( - Sym.getName(), MCSymbolRefExpr::VK_Mips_GPOFF_HI, MCA.getContext()); - const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create( - Sym.getName(), MCSymbolRefExpr::VK_Mips_GPOFF_LO, MCA.getContext()); + const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::create( + &Sym, MCSymbolRefExpr::VK_Mips_GPOFF_HI, MCA.getContext()); + const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::create( + &Sym, MCSymbolRefExpr::VK_Mips_GPOFF_LO, MCA.getContext()); + // lui $gp, %hi(%neg(%gp_rel(funcSym))) Inst.setOpcode(Mips::LUi); - Inst.addOperand(MCOperand::CreateReg(Mips::GP)); - Inst.addOperand(MCOperand::CreateExpr(HiExpr)); + Inst.addOperand(MCOperand::createReg(Mips::GP)); + Inst.addOperand(MCOperand::createExpr(HiExpr)); getStreamer().EmitInstruction(Inst, STI); Inst.clear(); // addiu $gp, $gp, %lo(%neg(%gp_rel(funcSym))) Inst.setOpcode(Mips::ADDiu); - Inst.addOperand(MCOperand::CreateReg(Mips::GP)); - Inst.addOperand(MCOperand::CreateReg(Mips::GP)); - Inst.addOperand(MCOperand::CreateExpr(LoExpr)); + Inst.addOperand(MCOperand::createReg(Mips::GP)); + Inst.addOperand(MCOperand::createReg(Mips::GP)); + Inst.addOperand(MCOperand::createExpr(LoExpr)); getStreamer().EmitInstruction(Inst, STI); Inst.clear(); // daddu $gp, $gp, $funcreg Inst.setOpcode(Mips::DADDu); - Inst.addOperand(MCOperand::CreateReg(Mips::GP)); - Inst.addOperand(MCOperand::CreateReg(Mips::GP)); - Inst.addOperand(MCOperand::CreateReg(RegNo)); + Inst.addOperand(MCOperand::createReg(Mips::GP)); + Inst.addOperand(MCOperand::createReg(Mips::GP)); + Inst.addOperand(MCOperand::createReg(RegNo)); getStreamer().EmitInstruction(Inst, STI); forbidModuleDirective(); @@ -709,11 +792,10 @@ void MipsTargetELFStreamer::emitMipsAbiFlags() { MCAssembler &MCA = getStreamer().getAssembler(); MCContext &Context = MCA.getContext(); MCStreamer &OS = getStreamer(); - const MCSectionELF *Sec = - Context.getELFSection(".MIPS.abiflags", ELF::SHT_MIPS_ABIFLAGS, - ELF::SHF_ALLOC, SectionKind::getMetadata(), 24, ""); - MCSectionData &ABIShndxSD = MCA.getOrCreateSectionData(*Sec); - ABIShndxSD.setAlignment(8); + MCSectionELF *Sec = Context.getELFSection( + ".MIPS.abiflags", ELF::SHT_MIPS_ABIFLAGS, ELF::SHF_ALLOC, 24, ""); + MCA.registerSection(*Sec); + Sec->setAlignment(8); OS.SwitchSection(Sec); OS << ABIFlagsSection; diff --git a/contrib/llvm/lib/Target/Mips/MicroMips32r6InstrFormats.td b/contrib/llvm/lib/Target/Mips/MicroMips32r6InstrFormats.td new file mode 100644 index 0000000..7350b97 --- /dev/null +++ b/contrib/llvm/lib/Target/Mips/MicroMips32r6InstrFormats.td @@ -0,0 +1,223 @@ +//=- MicroMips32r6InstrFormats.td - Mips32r6 Instruction Formats -*- tablegen -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes microMIPS32r6 instruction formats. +// +//===----------------------------------------------------------------------===// + +class MMR6Arch<string opstr> { + string Arch = "micromipsr6"; + string BaseOpcode = opstr; +} + +class POOL32A_BITSWAP_FM_MMR6<bits<6> funct> : MipsR6Inst { + bits<5> rd; + bits<5> rt; + + bits<32> Inst; + + let Inst{31-26} = 0b000000; + let Inst{25-21} = rt; + let Inst{20-16} = rd; + let Inst{15-12} = 0b0000; + let Inst{11-6} = funct; + let Inst{5-0} = 0b111100; +} + +class CACHE_PREF_FM_MMR6<bits<6> opgroup, bits<4> funct> : MipsR6Inst { + bits<21> addr; + bits<5> hint; + + bits<32> Inst; + + let Inst{31-26} = opgroup; + let Inst{25-21} = hint; + let Inst{20-16} = addr{20-16}; + let Inst{15-12} = funct; + let Inst{11-0} = addr{11-0}; +} + +class ARITH_FM_MMR6<string instr_asm, bits<10> funct> : MMR6Arch<instr_asm> { + bits<5> rd; + bits<5> rt; + bits<5> rs; + + bits<32> Inst; + + let Inst{31-26} = 0; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-11} = rd; + let Inst{10} = 0; + let Inst{9-0} = funct; +} + +class ADDI_FM_MMR6<string instr_asm, bits<6> op> : MMR6Arch<instr_asm> { + bits<5> rt; + bits<5> rs; + bits<16> imm16; + + bits<32> Inst; + + let Inst{31-26} = op; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-0} = imm16; +} + +class SIGN_EXTEND_FM_MMR6<string instr_asm, bits<10> funct> + : MMR6Arch<instr_asm> { + bits<5> rd; + bits<5> rt; + + bits<32> Inst; + + let Inst{31-26} = 0b000000; + let Inst{25-21} = rd; + let Inst{20-16} = rt; + let Inst{15-6} = funct; + let Inst{5-0} = 0b111100; +} + +class PCREL19_FM_MMR6<bits<2> funct> : MipsR6Inst { + bits<5> rt; + bits<19> imm; + + bits<32> Inst; + + let Inst{31-26} = 0b011110; + let Inst{25-21} = rt; + let Inst{20-19} = funct; + let Inst{18-0} = imm; +} + +class PCREL16_FM_MMR6<bits<5> funct> : MipsR6Inst { + bits<5> rt; + bits<16> imm; + + bits<32> Inst; + + let Inst{31-26} = 0b011110; + let Inst{25-21} = rt; + let Inst{20-16} = funct; + let Inst{15-0} = imm; +} + +class POOL32A_FM_MMR6<bits<10> funct> : MipsR6Inst { + bits<5> rd; + bits<5> rs; + bits<5> rt; + + bits<32> Inst; + + let Inst{31-26} = 0b000000; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-11} = rd; + let Inst{10} = 0; + let Inst{9-0} = funct; +} + +class POOL32A_2R_FM_MMR6<bits<10> funct> : MipsR6Inst { + bits<5> rs; + bits<5> rt; + + bits<32> Inst; + + let Inst{31-26} = 0b000000; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-6} = funct; + let Inst{5-0} = 0b111100; +} + +class SPECIAL_2R_FM_MMR6<bits<6> funct> : MipsR6Inst { + bits<5> rs; + bits<5> rt; + + bits<32> Inst; + + let Inst{31-26} = 0b000000; + let Inst{25-21} = rs; + let Inst{20-16} = 0b00000; + let Inst{15-11} = rt; + let Inst{10-6} = 0b00001; + let Inst{5-0} = funct; +} + +class POOL32A_ALIGN_FM_MMR6<bits<6> funct> : MipsR6Inst { + bits<5> rd; + bits<5> rs; + bits<5> rt; + bits<2> bp; + + bits<32> Inst; + + let Inst{31-26} = 0b000000; + let Inst{25-21} = rs; + let Inst{20-16} = rt; + let Inst{15-11} = rd; + let Inst{10-9} = bp; + let Inst{8-6} = 0b000; + let Inst{5-0} = funct; +} + +class AUI_FM_MMR6 : MipsR6Inst { + bits<5> rs; + bits<5> rt; + bits<16> imm; + + bits<32> Inst; + + let Inst{31-26} = 0b000100; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-0} = imm; +} + +class POOL32A_LSA_FM<bits<6> funct> : MipsR6Inst { + bits<5> rd; + bits<5> rs; + bits<5> rt; + bits<2> imm2; + + bits<32> Inst; + + let Inst{31-26} = 0b000000; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-11} = rd; + let Inst{10-9} = imm2; + let Inst{8-6} = 0b000; + let Inst{5-0} = funct; +} + +class CMP_BRANCH_1R_RT_OFF16_FM_MMR6<bits<6> funct> : MipsR6Inst { + bits<5> rt; + bits<16> offset; + + bits<32> Inst; + + let Inst{31-26} = funct; + let Inst{25-21} = rt; + let Inst{20-16} = 0b00000; + let Inst{15-0} = offset; +} + +class CMP_BRANCH_1R_BOTH_OFF16_FM_MMR6<bits<6> funct> : MipsR6Inst { + bits<5> rt; + bits<16> offset; + + bits<32> Inst; + + let Inst{31-26} = funct; + let Inst{25-21} = rt; + let Inst{20-16} = rt; + let Inst{15-0} = offset; +} diff --git a/contrib/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td b/contrib/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td new file mode 100644 index 0000000..2259d5d --- /dev/null +++ b/contrib/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td @@ -0,0 +1,329 @@ +//=- MicroMips32r6InstrInfo.td - MicroMips r6 Instruction Information -*- tablegen -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes microMIPSr6 instructions. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// +// Instruction Encodings +// +//===----------------------------------------------------------------------===// +class ADD_MMR6_ENC : ARITH_FM_MMR6<"add", 0x110>; +class ADDIU_MMR6_ENC : ADDI_FM_MMR6<"addiu", 0xc>; +class ADDU_MMR6_ENC : ARITH_FM_MMR6<"addu", 0x150>; +class ADDIUPC_MMR6_ENC : PCREL19_FM_MMR6<0b00>; +class ALUIPC_MMR6_ENC : PCREL16_FM_MMR6<0b11111>; +class AND_MMR6_ENC : ARITH_FM_MMR6<"and", 0x250>; +class ANDI_MMR6_ENC : ADDI_FM_MMR6<"andi", 0x34>; +class AUIPC_MMR6_ENC : PCREL16_FM_MMR6<0b11110>; +class ALIGN_MMR6_ENC : POOL32A_ALIGN_FM_MMR6<0b011111>; +class AUI_MMR6_ENC : AUI_FM_MMR6; +class BALC_MMR6_ENC : BRANCH_OFF26_FM<0b101101>; +class BC_MMR6_ENC : BRANCH_OFF26_FM<0b100101>; +class BITSWAP_MMR6_ENC : POOL32A_BITSWAP_FM_MMR6<0b101100>; +class BEQZALC_MMR6_ENC : CMP_BRANCH_1R_RT_OFF16_FM_MMR6<0b011101>; +class BNEZALC_MMR6_ENC : CMP_BRANCH_1R_RT_OFF16_FM_MMR6<0b011111>; +class BGTZALC_MMR6_ENC : CMP_BRANCH_1R_RT_OFF16_FM_MMR6<0b111000>; +class BLTZALC_MMR6_ENC : CMP_BRANCH_1R_BOTH_OFF16_FM_MMR6<0b111000>; +class BGEZALC_MMR6_ENC : CMP_BRANCH_1R_BOTH_OFF16_FM_MMR6<0b110000>; +class BLEZALC_MMR6_ENC : CMP_BRANCH_1R_RT_OFF16_FM_MMR6<0b110000>; +class CACHE_MMR6_ENC : CACHE_PREF_FM_MMR6<0b001000, 0b0110>; +class CLO_MMR6_ENC : POOL32A_2R_FM_MMR6<0b0100101100>; +class CLZ_MMR6_ENC : SPECIAL_2R_FM_MMR6<0b010000>; +class DIV_MMR6_ENC : ARITH_FM_MMR6<"div", 0x118>; +class DIVU_MMR6_ENC : ARITH_FM_MMR6<"divu", 0x198>; +class JIALC_MMR6_ENC : JMP_IDX_COMPACT_FM<0b100000>; +class JIC_MMR6_ENC : JMP_IDX_COMPACT_FM<0b101000>; +class LSA_MMR6_ENC : POOL32A_LSA_FM<0b001111>; +class LWPC_MMR6_ENC : PCREL19_FM_MMR6<0b01>; +class MOD_MMR6_ENC : ARITH_FM_MMR6<"mod", 0x158>; +class MODU_MMR6_ENC : ARITH_FM_MMR6<"modu", 0x1d8>; +class MUL_MMR6_ENC : ARITH_FM_MMR6<"mul", 0x18>; +class MUH_MMR6_ENC : ARITH_FM_MMR6<"muh", 0x58>; +class MULU_MMR6_ENC : ARITH_FM_MMR6<"mulu", 0x98>; +class MUHU_MMR6_ENC : ARITH_FM_MMR6<"muhu", 0xd8>; +class NOR_MMR6_ENC : ARITH_FM_MMR6<"nor", 0x2d0>; +class OR_MMR6_ENC : ARITH_FM_MMR6<"or", 0x290>; +class ORI_MMR6_ENC : ADDI_FM_MMR6<"ori", 0x14>; +class PREF_MMR6_ENC : CACHE_PREF_FM_MMR6<0b011000, 0b0010>; +class SEB_MMR6_ENC : SIGN_EXTEND_FM_MMR6<"seb", 0b0010101100>; +class SEH_MMR6_ENC : SIGN_EXTEND_FM_MMR6<"seh", 0b0011101100>; +class SELEQZ_MMR6_ENC : POOL32A_FM_MMR6<0b0101000000>; +class SELNEZ_MMR6_ENC : POOL32A_FM_MMR6<0b0110000000>; +class SUB_MMR6_ENC : ARITH_FM_MMR6<"sub", 0x190>; +class SUBU_MMR6_ENC : ARITH_FM_MMR6<"subu", 0x1d0>; +class XOR_MMR6_ENC : ARITH_FM_MMR6<"xor", 0x310>; +class XORI_MMR6_ENC : ADDI_FM_MMR6<"xori", 0x1c>; + +class CMP_CBR_RT_Z_MMR6_DESC_BASE<string instr_asm, DAGOperand opnd, + RegisterOperand GPROpnd> + : BRANCH_DESC_BASE, MMR6Arch<instr_asm> { + dag InOperandList = (ins GPROpnd:$rt, opnd:$offset); + dag OutOperandList = (outs); + string AsmString = !strconcat(instr_asm, "\t$rt, $offset"); + list<Register> Defs = [AT]; +} + +class BEQZALC_MMR6_DESC : CMP_CBR_RT_Z_MMR6_DESC_BASE<"beqzalc", brtarget_mm, + GPR32Opnd> { + list<Register> Defs = [RA]; +} + +class BGEZALC_MMR6_DESC : CMP_CBR_RT_Z_MMR6_DESC_BASE<"bgezalc", brtarget_mm, + GPR32Opnd> { + list<Register> Defs = [RA]; +} + +class BGTZALC_MMR6_DESC : CMP_CBR_RT_Z_MMR6_DESC_BASE<"bgtzalc", brtarget_mm, + GPR32Opnd> { + list<Register> Defs = [RA]; +} + +class BLEZALC_MMR6_DESC : CMP_CBR_RT_Z_MMR6_DESC_BASE<"blezalc", brtarget_mm, + GPR32Opnd> { + list<Register> Defs = [RA]; +} + +class BLTZALC_MMR6_DESC : CMP_CBR_RT_Z_MMR6_DESC_BASE<"bltzalc", brtarget_mm, + GPR32Opnd> { + list<Register> Defs = [RA]; +} + +class BNEZALC_MMR6_DESC : CMP_CBR_RT_Z_MMR6_DESC_BASE<"bnezalc", brtarget_mm, + GPR32Opnd> { + list<Register> Defs = [RA]; +} + +//===----------------------------------------------------------------------===// +// +// Instruction Descriptions +// +//===----------------------------------------------------------------------===// + +class ADD_MMR6_DESC : ArithLogicR<"add", GPR32Opnd>; +class ADDIU_MMR6_DESC : ArithLogicI<"addiu", simm16, GPR32Opnd>; +class ADDU_MMR6_DESC : ArithLogicR<"addu", GPR32Opnd>; +class MUL_MMR6_DESC : ArithLogicR<"mul", GPR32Opnd>; +class MUH_MMR6_DESC : ArithLogicR<"muh", GPR32Opnd>; +class MULU_MMR6_DESC : ArithLogicR<"mulu", GPR32Opnd>; +class MUHU_MMR6_DESC : ArithLogicR<"muhu", GPR32Opnd>; + +class BC_MMR6_DESC_BASE<string instr_asm, DAGOperand opnd> + : BRANCH_DESC_BASE, MMR6Arch<instr_asm> { + dag InOperandList = (ins opnd:$offset); + dag OutOperandList = (outs); + string AsmString = !strconcat(instr_asm, "\t$offset"); + bit isBarrier = 1; +} + +class BALC_MMR6_DESC : BC_MMR6_DESC_BASE<"balc", brtarget26> { + bit isCall = 1; + list<Register> Defs = [RA]; +} +class BC_MMR6_DESC : BC_MMR6_DESC_BASE<"bc", brtarget26>; +class SUB_MMR6_DESC : ArithLogicR<"sub", GPR32Opnd>; +class SUBU_MMR6_DESC : ArithLogicR<"subu", GPR32Opnd>; + +class BITSWAP_MMR6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> + : MMR6Arch<instr_asm> { + dag OutOperandList = (outs GPROpnd:$rd); + dag InOperandList = (ins GPROpnd:$rt); + string AsmString = !strconcat(instr_asm, "\t$rd, $rt"); + list<dag> Pattern = []; +} + +class BITSWAP_MMR6_DESC : BITSWAP_MMR6_DESC_BASE<"bitswap", GPR32Opnd>; + +class CACHE_HINT_MMR6_DESC<string instr_asm, Operand MemOpnd, + RegisterOperand GPROpnd> : MMR6Arch<instr_asm> { + dag OutOperandList = (outs); + dag InOperandList = (ins MemOpnd:$addr, uimm5:$hint); + string AsmString = !strconcat(instr_asm, "\t$hint, $addr"); + list<dag> Pattern = []; + string DecoderMethod = "DecodeCacheOpMM"; +} + +class CACHE_MMR6_DESC : CACHE_HINT_MMR6_DESC<"cache", mem_mm_12, GPR32Opnd>; +class PREF_MMR6_DESC : CACHE_HINT_MMR6_DESC<"pref", mem_mm_12, GPR32Opnd>; + +class CLO_CLZ_MMR6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> + : MMR6Arch<instr_asm> { + dag OutOperandList = (outs GPROpnd:$rt); + dag InOperandList = (ins GPROpnd:$rs); + string AsmString = !strconcat(instr_asm, "\t$rt, $rs"); +} + +class CLO_MMR6_DESC : CLO_CLZ_MMR6_DESC_BASE<"clo", GPR32Opnd>; +class CLZ_MMR6_DESC : CLO_CLZ_MMR6_DESC_BASE<"clz", GPR32Opnd>; + +class JMP_MMR6_IDX_COMPACT_DESC_BASE<string opstr, DAGOperand opnd, + RegisterOperand GPROpnd> + : MMR6Arch<opstr> { + dag InOperandList = (ins GPROpnd:$rt, opnd:$offset); + string AsmString = !strconcat(opstr, "\t$rt, $offset"); + list<dag> Pattern = []; + bit isTerminator = 1; + bit hasDelaySlot = 0; +} + +class JIALC_MMR6_DESC : JMP_MMR6_IDX_COMPACT_DESC_BASE<"jialc", calloffset16, + GPR32Opnd> { + bit isCall = 1; + list<Register> Defs = [RA]; +} + +class JIC_MMR6_DESC : JMP_MMR6_IDX_COMPACT_DESC_BASE<"jic", jmpoffset16, + GPR32Opnd> { + bit isBarrier = 1; + list<Register> Defs = [AT]; +} + +class ALIGN_MMR6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, + Operand ImmOpnd> : MMR6Arch<instr_asm> { + dag OutOperandList = (outs GPROpnd:$rd); + dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt, ImmOpnd:$bp); + string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt, $bp"); + list<dag> Pattern = []; +} + +class ALIGN_MMR6_DESC : ALIGN_MMR6_DESC_BASE<"align", GPR32Opnd, uimm2>; + +class AUI_MMR6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> + : MMR6Arch<instr_asm> { + dag OutOperandList = (outs GPROpnd:$rt); + dag InOperandList = (ins GPROpnd:$rs, simm16:$imm); + string AsmString = !strconcat(instr_asm, "\t$rt, $rs, $imm"); + list<dag> Pattern = []; +} + +class AUI_MMR6_DESC : AUI_MMR6_DESC_BASE<"aui", GPR32Opnd>; + +class SEB_MMR6_DESC : SignExtInReg<"seb", i8, GPR32Opnd, II_SEB>; +class SEH_MMR6_DESC : SignExtInReg<"seh", i16, GPR32Opnd, II_SEH>; +class ALUIPC_MMR6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> + : MMR6Arch<instr_asm> { + dag OutOperandList = (outs GPROpnd:$rt); + dag InOperandList = (ins simm16:$imm); + string AsmString = !strconcat(instr_asm, "\t$rt, $imm"); + list<dag> Pattern = []; +} + +class ALUIPC_MMR6_DESC : ALUIPC_MMR6_DESC_BASE<"aluipc", GPR32Opnd>; +class AUIPC_MMR6_DESC : ALUIPC_MMR6_DESC_BASE<"auipc", GPR32Opnd>; + +class LSA_MMR6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, + Operand ImmOpnd> : MMR6Arch<instr_asm> { + dag OutOperandList = (outs GPROpnd:$rd); + dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt, ImmOpnd:$imm2); + string AsmString = !strconcat(instr_asm, "\t$rt, $rs, $rd, $imm2"); + list<dag> Pattern = []; +} + +class LSA_MMR6_DESC : LSA_MMR6_DESC_BASE<"lsa", GPR32Opnd, uimm2>; + +class PCREL_MMR6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, + Operand ImmOpnd> : MMR6Arch<instr_asm> { + dag OutOperandList = (outs GPROpnd:$rt); + dag InOperandList = (ins ImmOpnd:$imm); + string AsmString = !strconcat(instr_asm, "\t$rt, $imm"); + list<dag> Pattern = []; +} + +class ADDIUPC_MMR6_DESC : PCREL_MMR6_DESC_BASE<"addiupc", GPR32Opnd, simm19_lsl2>; +class LWPC_MMR6_DESC: PCREL_MMR6_DESC_BASE<"lwpc", GPR32Opnd, simm19_lsl2>; + +class SELEQNE_Z_MMR6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> + : MMR6Arch<instr_asm> { + dag OutOperandList = (outs GPROpnd:$rd); + dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt); + string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt"); + list<dag> Pattern = []; +} + +class SELEQZ_MMR6_DESC : SELEQNE_Z_MMR6_DESC_BASE<"seleqz", GPR32Opnd>; +class SELNEZ_MMR6_DESC : SELEQNE_Z_MMR6_DESC_BASE<"selnez", GPR32Opnd>; +class DIV_MMR6_DESC : ArithLogicR<"div", GPR32Opnd>; +class DIVU_MMR6_DESC : ArithLogicR<"divu", GPR32Opnd>; +class MOD_MMR6_DESC : ArithLogicR<"mod", GPR32Opnd>; +class MODU_MMR6_DESC : ArithLogicR<"modu", GPR32Opnd>; +class AND_MMR6_DESC : ArithLogicR<"and", GPR32Opnd>; +class ANDI_MMR6_DESC : ArithLogicI<"andi", simm16, GPR32Opnd>; +class NOR_MMR6_DESC : ArithLogicR<"nor", GPR32Opnd>; +class OR_MMR6_DESC : ArithLogicR<"or", GPR32Opnd>; +class ORI_MMR6_DESC : ArithLogicI<"ori", simm16, GPR32Opnd>; +class XOR_MMR6_DESC : ArithLogicR<"xor", GPR32Opnd>; +class XORI_MMR6_DESC : ArithLogicI<"xori", simm16, GPR32Opnd>; + +//===----------------------------------------------------------------------===// +// +// Instruction Definitions +// +//===----------------------------------------------------------------------===// + +let DecoderNamespace = "MicroMips32r6" in { +def ADD_MMR6 : StdMMR6Rel, ADD_MMR6_DESC, ADD_MMR6_ENC, ISA_MICROMIPS32R6; +def ADDIU_MMR6 : StdMMR6Rel, ADDIU_MMR6_DESC, ADDIU_MMR6_ENC, ISA_MICROMIPS32R6; +def ADDU_MMR6 : StdMMR6Rel, ADDU_MMR6_DESC, ADDU_MMR6_ENC, ISA_MICROMIPS32R6; +def ADDIUPC_MMR6 : R6MMR6Rel, ADDIUPC_MMR6_ENC, ADDIUPC_MMR6_DESC, + ISA_MICROMIPS32R6; +def ALUIPC_MMR6 : R6MMR6Rel, ALUIPC_MMR6_ENC, ALUIPC_MMR6_DESC, + ISA_MICROMIPS32R6; +def AND_MMR6 : StdMMR6Rel, AND_MMR6_DESC, AND_MMR6_ENC, ISA_MICROMIPS32R6; +def ANDI_MMR6 : StdMMR6Rel, ANDI_MMR6_DESC, ANDI_MMR6_ENC, ISA_MICROMIPS32R6; +def AUIPC_MMR6 : R6MMR6Rel, AUIPC_MMR6_ENC, AUIPC_MMR6_DESC, ISA_MICROMIPS32R6; +def ALIGN_MMR6 : R6MMR6Rel, ALIGN_MMR6_ENC, ALIGN_MMR6_DESC, ISA_MICROMIPS32R6; +def AUI_MMR6 : R6MMR6Rel, AUI_MMR6_ENC, AUI_MMR6_DESC, ISA_MICROMIPS32R6; +def BALC_MMR6 : R6MMR6Rel, BALC_MMR6_ENC, BALC_MMR6_DESC, ISA_MICROMIPS32R6; +def BC_MMR6 : R6MMR6Rel, BC_MMR6_ENC, BC_MMR6_DESC, ISA_MICROMIPS32R6; +def BITSWAP_MMR6 : R6MMR6Rel, BITSWAP_MMR6_ENC, BITSWAP_MMR6_DESC, + ISA_MICROMIPS32R6; +def BEQZALC_MMR6 : R6MMR6Rel, BEQZALC_MMR6_ENC, BEQZALC_MMR6_DESC, + ISA_MICROMIPS32R6; +def BGEZALC_MMR6 : R6MMR6Rel, BGEZALC_MMR6_ENC, BGEZALC_MMR6_DESC, + ISA_MICROMIPS32R6; +def BGTZALC_MMR6 : R6MMR6Rel, BGTZALC_MMR6_ENC, BGTZALC_MMR6_DESC, + ISA_MICROMIPS32R6; +def BLEZALC_MMR6 : R6MMR6Rel, BLEZALC_MMR6_ENC, BLEZALC_MMR6_DESC, + ISA_MICROMIPS32R6; +def BLTZALC_MMR6 : R6MMR6Rel, BLTZALC_MMR6_ENC, BLTZALC_MMR6_DESC, + ISA_MICROMIPS32R6; +def BNEZALC_MMR6 : R6MMR6Rel, BNEZALC_MMR6_ENC, BNEZALC_MMR6_DESC, + ISA_MICROMIPS32R6; +def CACHE_MMR6 : R6MMR6Rel, CACHE_MMR6_ENC, CACHE_MMR6_DESC, ISA_MICROMIPS32R6; +def CLO_MMR6 : R6MMR6Rel, CLO_MMR6_ENC, CLO_MMR6_DESC, ISA_MICROMIPS32R6; +def CLZ_MMR6 : R6MMR6Rel, CLZ_MMR6_ENC, CLZ_MMR6_DESC, ISA_MICROMIPS32R6; +def DIV_MMR6 : R6MMR6Rel, DIV_MMR6_DESC, DIV_MMR6_ENC, ISA_MICROMIPS32R6; +def DIVU_MMR6 : R6MMR6Rel, DIVU_MMR6_DESC, DIVU_MMR6_ENC, ISA_MICROMIPS32R6; +def JIALC_MMR6 : R6MMR6Rel, JIALC_MMR6_ENC, JIALC_MMR6_DESC, ISA_MICROMIPS32R6; +def JIC_MMR6 : R6MMR6Rel, JIC_MMR6_ENC, JIC_MMR6_DESC, ISA_MICROMIPS32R6; +def LSA_MMR6 : R6MMR6Rel, LSA_MMR6_ENC, LSA_MMR6_DESC, ISA_MICROMIPS32R6; +def LWPC_MMR6 : R6MMR6Rel, LWPC_MMR6_ENC, LWPC_MMR6_DESC, ISA_MICROMIPS32R6; +def MOD_MMR6 : R6MMR6Rel, MOD_MMR6_DESC, MOD_MMR6_ENC, ISA_MICROMIPS32R6; +def MODU_MMR6 : R6MMR6Rel, MODU_MMR6_DESC, MODU_MMR6_ENC, ISA_MICROMIPS32R6; +def MUL_MMR6 : R6MMR6Rel, MUL_MMR6_DESC, MUL_MMR6_ENC, ISA_MICROMIPS32R6; +def MUH_MMR6 : R6MMR6Rel, MUH_MMR6_DESC, MUH_MMR6_ENC, ISA_MICROMIPS32R6; +def MULU_MMR6 : R6MMR6Rel, MULU_MMR6_DESC, MULU_MMR6_ENC, ISA_MICROMIPS32R6; +def MUHU_MMR6 : R6MMR6Rel, MUHU_MMR6_DESC, MUHU_MMR6_ENC, ISA_MICROMIPS32R6; +def NOR_MMR6 : StdMMR6Rel, NOR_MMR6_DESC, NOR_MMR6_ENC, ISA_MICROMIPS32R6; +def OR_MMR6 : StdMMR6Rel, OR_MMR6_DESC, OR_MMR6_ENC, ISA_MICROMIPS32R6; +def ORI_MMR6 : StdMMR6Rel, ORI_MMR6_DESC, ORI_MMR6_ENC, ISA_MICROMIPS32R6; +def PREF_MMR6 : R6MMR6Rel, PREF_MMR6_ENC, PREF_MMR6_DESC, ISA_MICROMIPS32R6; +def SEB_MMR6 : StdMMR6Rel, SEB_MMR6_DESC, SEB_MMR6_ENC, ISA_MICROMIPS32R6; +def SEH_MMR6 : StdMMR6Rel, SEH_MMR6_DESC, SEH_MMR6_ENC, ISA_MICROMIPS32R6; +def SELEQZ_MMR6 : R6MMR6Rel, SELEQZ_MMR6_ENC, SELEQZ_MMR6_DESC, + ISA_MICROMIPS32R6; +def SELNEZ_MMR6 : R6MMR6Rel, SELNEZ_MMR6_ENC, SELNEZ_MMR6_DESC, + ISA_MICROMIPS32R6; +def SUB_MMR6 : StdMMR6Rel, SUB_MMR6_DESC, SUB_MMR6_ENC, ISA_MICROMIPS32R6; +def SUBU_MMR6 : StdMMR6Rel, SUBU_MMR6_DESC, SUBU_MMR6_ENC, ISA_MICROMIPS32R6; +def XOR_MMR6 : StdMMR6Rel, XOR_MMR6_DESC, XOR_MMR6_ENC, ISA_MICROMIPS32R6; +def XORI_MMR6 : StdMMR6Rel, XORI_MMR6_DESC, XORI_MMR6_ENC, ISA_MICROMIPS32R6; +} diff --git a/contrib/llvm/lib/Target/Mips/MicroMipsInstrFPU.td b/contrib/llvm/lib/Target/Mips/MicroMipsInstrFPU.td index fae7059..004b0d5 100644 --- a/contrib/llvm/lib/Target/Mips/MicroMipsInstrFPU.td +++ b/contrib/llvm/lib/Target/Mips/MicroMipsInstrFPU.td @@ -95,7 +95,7 @@ def FNEG_MM : MMRel, ABSS_FT<"neg.d", AFGR64Opnd, AFGR64Opnd, II_NEG, fneg>, ABS_FM_MM<1, 0x2d>; def FMOV_D32_MM : MMRel, ABSS_FT<"mov.d", AFGR64Opnd, AFGR64Opnd, II_MOV_D>, - ABS_FM_MM<1, 0x1>, AdditionalRequires<[NotFP64bit]>; + ABS_FM_MM<1, 0x1>, FGR_32; def MOVZ_I_S_MM : MMRel, CMov_I_F_FT<"movz.s", GPR32Opnd, FGR32Opnd, II_MOVZ_S>, CMov_I_F_FM_MM<0x78, 0>; @@ -124,9 +124,9 @@ def MFC1_MM : MMRel, MFC1_FT<"mfc1", GPR32Opnd, FGR32Opnd, def MTC1_MM : MMRel, MTC1_FT<"mtc1", FGR32Opnd, GPR32Opnd, II_MTC1, bitconvert>, MFC1_FM_MM<0xa0>; def MFHC1_MM : MMRel, MFC1_FT<"mfhc1", GPR32Opnd, AFGR64Opnd, II_MFHC1>, - MFC1_FM_MM<0xc0>, ISA_MIPS32R2, AdditionalRequires<[NotFP64bit]>; + MFC1_FM_MM<0xc0>, ISA_MIPS32R2, FGR_32; def MTHC1_MM : MMRel, MTC1_64_FT<"mthc1", AFGR64Opnd, GPR32Opnd, II_MTHC1>, - MFC1_FM_MM<0xe0>, ISA_MIPS32R2, AdditionalRequires<[NotFP64bit]>; + MFC1_FM_MM<0xe0>, ISA_MIPS32R2, FGR_32; def MADD_S_MM : MMRel, MADDS_FT<"madd.s", FGR32Opnd, II_MADD_S, fadd>, MADDS_FM_MM<0x1>; diff --git a/contrib/llvm/lib/Target/Mips/MicroMipsInstrFormats.td b/contrib/llvm/lib/Target/Mips/MicroMipsInstrFormats.td index 51b5c0c..560afa4 100644 --- a/contrib/llvm/lib/Target/Mips/MicroMipsInstrFormats.td +++ b/contrib/llvm/lib/Target/Mips/MicroMipsInstrFormats.td @@ -131,6 +131,17 @@ class LOAD_STORE_SP_FM_MM16<bits<6> op> { let Inst{4-0} = offset; } +class LOAD_GP_FM_MM16<bits<6> op> { + bits<3> rt; + bits<7> offset; + + bits<16> Inst; + + let Inst{15-10} = op; + let Inst{9-7} = rt; + let Inst{6-0} = offset; +} + class ADDIUS5_FM_MM16 { bits<5> rd; bits<4> imm; @@ -238,6 +249,29 @@ class BEQNEZ_FM_MM16<bits<6> op> { let Inst{6-0} = offset; } +class B16_FM { + bits<10> offset; + + bits<16> Inst; + + let Inst{15-10} = 0x33; + let Inst{9-0} = offset; +} + +class MOVEP_FM_MM16 { + bits<3> dst_regs; + bits<3> rt; + bits<3> rs; + + bits<16> Inst; + + let Inst{15-10} = 0x21; + let Inst{9-7} = dst_regs; + let Inst{6-4} = rt; + let Inst{3-1} = rs; + let Inst{0} = 0; +} + //===----------------------------------------------------------------------===// // MicroMIPS 32-bit Instruction Formats //===----------------------------------------------------------------------===// @@ -898,3 +932,14 @@ class BARRIER_FM_MM<bits<5> op> : MMArch { let Inst{10-6} = 0x0; let Inst{5-0} = 0x0; } + +class ADDIUPC_FM_MM { + bits<3> rs; + bits<23> imm; + + bits<32> Inst; + + let Inst{31-26} = 0x1e; + let Inst{25-23} = rs; + let Inst{22-0} = imm; +} diff --git a/contrib/llvm/lib/Target/Mips/MicroMipsInstrInfo.td b/contrib/llvm/lib/Target/Mips/MicroMipsInstrInfo.td index 241f452..2aab739 100644 --- a/contrib/llvm/lib/Target/Mips/MicroMipsInstrInfo.td +++ b/contrib/llvm/lib/Target/Mips/MicroMipsInstrInfo.td @@ -1,8 +1,10 @@ def addrimm12 : ComplexPattern<iPTR, 2, "selectIntAddrMM", [frameindex]>; +def addrimm4lsl2 : ComplexPattern<iPTR, 2, "selectIntAddrLSL2MM", [frameindex]>; def simm4 : Operand<i32> { let DecoderMethod = "DecodeSimm4"; } +def simm7 : Operand<i32>; def li_simm7 : Operand<i32> { let DecoderMethod = "DecodeLiSimm7"; } @@ -64,7 +66,7 @@ def MicroMipsMemGPRMM16AsmOperand : AsmOperandClass { class mem_mm_4_generic : Operand<i32> { let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops ptr_rc, simm4); + let MIOperandInfo = (ops GPRMM16, simm4); let OperandType = "OPERAND_MEMORY"; let ParserMatchClass = MicroMipsMemGPRMM16AsmOperand; } @@ -96,6 +98,13 @@ def mem_mm_sp_imm5_lsl2 : Operand<i32> { let EncoderMethod = "getMemEncodingMMSPImm5Lsl2"; } +def mem_mm_gp_imm7_lsl2 : Operand<i32> { + let PrintMethod = "printMemOperand"; + let MIOperandInfo = (ops GPRMM16:$base, simm7:$offset); + let OperandType = "OPERAND_MEMORY"; + let EncoderMethod = "getMemEncodingMMGPImm7Lsl2"; +} + def mem_mm_12 : Operand<i32> { let PrintMethod = "printMemOperand"; let MIOperandInfo = (ops GPR32, simm12); @@ -135,10 +144,23 @@ def brtarget7_mm : Operand<OtherVT> { let ParserMatchClass = MipsJumpTargetAsmOperand; } +def brtarget10_mm : Operand<OtherVT> { + let EncoderMethod = "getBranchTargetOpValueMMPC10"; + let OperandType = "OPERAND_PCREL"; + let DecoderMethod = "DecodeBranchTarget10MM"; + let ParserMatchClass = MipsJumpTargetAsmOperand; +} + def brtarget_mm : Operand<OtherVT> { let EncoderMethod = "getBranchTargetOpValueMM"; let OperandType = "OPERAND_PCREL"; let DecoderMethod = "DecodeBranchTargetMM"; + let ParserMatchClass = MipsJumpTargetAsmOperand; +} + +def simm23_lsl2 : Operand<i32> { + let EncoderMethod = "getSimm23Lsl2Encoding"; + let DecoderMethod = "DecodeSimm23Lsl2"; } class CompactBranchMM<string opstr, DAGOperand opnd, PatFrag cond_op, @@ -170,6 +192,28 @@ class StoreLeftRightMM<string opstr, SDNode OpNode, RegisterOperand RO, let DecoderMethod = "DecodeMemMMImm12"; } +/// A register pair used by movep instruction. +def MovePRegPairAsmOperand : AsmOperandClass { + let Name = "MovePRegPair"; + let ParserMethod = "parseMovePRegPair"; + let PredicateMethod = "isMovePRegPair"; +} + +def movep_regpair : Operand<i32> { + let EncoderMethod = "getMovePRegPairOpValue"; + let ParserMatchClass = MovePRegPairAsmOperand; + let PrintMethod = "printRegisterList"; + let DecoderMethod = "DecodeMovePRegPair"; + let MIOperandInfo = (ops GPR32Opnd, GPR32Opnd); +} + +class MovePMM16<string opstr, RegisterOperand RO> : +MicroMipsInst16<(outs movep_regpair:$dst_regs), (ins RO:$rs, RO:$rt), + !strconcat(opstr, "\t$dst_regs, $rs, $rt"), [], + NoItinerary, FrmR> { + let isReMaterializable = 1; +} + /// A register pair used by load/store pair instructions. def RegPairAsmOperand : AsmOperandClass { let Name = "RegPair"; @@ -294,6 +338,15 @@ class StoreSPMM16<string opstr, DAGOperand RO, InstrItinClass Itin, let mayStore = 1; } +class LoadGPMM16<string opstr, DAGOperand RO, InstrItinClass Itin, + Operand MemOpnd> : + MicroMipsInst16<(outs RO:$rt), (ins MemOpnd:$offset), + !strconcat(opstr, "\t$rt, $offset"), [], Itin, FrmI> { + let DecoderMethod = "DecodeMemMMGPImm7Lsl2"; + let canFoldAsLoad = 1; + let mayLoad = 1; +} + class AddImmUR2<string opstr, RegisterOperand RO> : MicroMipsInst16<(outs RO:$rd), (ins RO:$rs, simm3_lsa2:$imm), !strconcat(opstr, "\t$rd, $rs, $imm"), @@ -422,6 +475,10 @@ class LoadWordIndexedScaledMM<string opstr, RegisterOperand RO, InstSE<(outs RO:$rd), (ins PtrRC:$base, PtrRC:$index), !strconcat(opstr, "\t$rd, ${index}(${base})"), [], Itin, FrmFI>; +class AddImmUPC<string opstr, RegisterOperand RO> : + InstSE<(outs RO:$rs), (ins simm23_lsl2:$imm), + !strconcat(opstr, "\t$rs, $imm"), [], NoItinerary, FrmR>; + /// A list of registers used by load/store multiple instructions. def RegListAsmOperand : AsmOperandClass { let Name = "RegList"; @@ -470,6 +527,7 @@ class StoreMultMM16<string opstr, ComplexPattern Addr = addr> : MicroMipsInst16<(outs), (ins reglist16:$rt, mem_mm_4sp:$addr), !strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI> { + let DecoderMethod = "DecodeMemMMReglistImm4Lsl2"; let mayStore = 1; } @@ -478,9 +536,22 @@ class LoadMultMM16<string opstr, ComplexPattern Addr = addr> : MicroMipsInst16<(outs reglist16:$rt), (ins mem_mm_4sp:$addr), !strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI> { + let DecoderMethod = "DecodeMemMMReglistImm4Lsl2"; let mayLoad = 1; } +class UncondBranchMM16<string opstr> : + MicroMipsInst16<(outs), (ins brtarget10_mm:$offset), + !strconcat(opstr, "\t$offset"), + [], IIBranch, FrmI> { + let isBranch = 1; + let isTerminator = 1; + let isBarrier = 1; + let hasDelaySlot = 1; + let Predicates = [RelocPIC, InMicroMips]; + let Defs = [AT]; +} + def ADDU16_MM : ArithRMM16<"addu16", GPRMM16Opnd, 1, II_ADDU, add>, ARITH_FM_MM16<0>; def SUBU16_MM : ArithRMM16<"subu16", GPRMM16Opnd, 0, II_SUBU, sub>, @@ -510,6 +581,8 @@ def SH16_MM : StoreMM16<"sh16", GPRMM16OpndZero, GPRMM16Opnd, truncstorei16, LOAD_STORE_FM_MM16<0x2a>; def SW16_MM : StoreMM16<"sw16", GPRMM16OpndZero, GPRMM16Opnd, store, II_SW, mem_mm_4_lsl2>, LOAD_STORE_FM_MM16<0x3a>; +def LWGP_MM : LoadGPMM16<"lw", GPRMM16Opnd, II_LW, mem_mm_gp_imm7_lsl2>, + LOAD_GP_FM_MM16<0x19>; def LWSP_MM : LoadSPMM16<"lw", GPR32Opnd, II_LW, mem_mm_sp_imm5_lsl2>, LOAD_STORE_SP_FM_MM16<0x12>; def SWSP_MM : StoreSPMM16<"sw", GPR32Opnd, II_SW, mem_mm_sp_imm5_lsl2>, @@ -521,6 +594,7 @@ def ADDIUSP_MM : AddImmUSP<"addiusp">, ADDIUSP_FM_MM16; def MFHI16_MM : MoveFromHILOMM<"mfhi", GPR32Opnd, AC0>, MFHILO_FM_MM16<0x10>; def MFLO16_MM : MoveFromHILOMM<"mflo", GPR32Opnd, AC0>, MFHILO_FM_MM16<0x12>; def MOVE16_MM : MoveMM16<"move", GPR32Opnd>, MOVE_FM_MM16<0x03>; +def MOVEP_MM : MovePMM16<"movep", GPRMM16OpndMoveP>, MOVEP_FM_MM16; def LI16_MM : LoadImmMM16<"li16", li_simm7, GPRMM16Opnd>, LI_FM_MM16, IsAsCheapAsAMove; def JALR16_MM : JumpLinkRegMM16<"jalr", GPR32Opnd>, JALR_FM_MM16<0x0e>; @@ -532,6 +606,7 @@ def BEQZ16_MM : CBranchZeroMM<"beqz16", brtarget7_mm, GPRMM16Opnd>, BEQNEZ_FM_MM16<0x23>; def BNEZ16_MM : CBranchZeroMM<"bnez16", brtarget7_mm, GPRMM16Opnd>, BEQNEZ_FM_MM16<0x2b>; +def B16_MM : UncondBranchMM16<"b16">, B16_FM; def BREAK16_MM : BrkSdbbp16MM<"break16">, BRKSDBBP16_FM_MM<0x28>; def SDBBP16_MM : BrkSdbbp16MM<"sdbbp16">, BRKSDBBP16_FM_MM<0x2C>; @@ -567,8 +642,10 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in { LW_FM_MM<0xc>; /// Arithmetic Instructions (3-Operand, R-Type) - def ADDu_MM : MMRel, ArithLogicR<"addu", GPR32Opnd>, ADD_FM_MM<0, 0x150>; - def SUBu_MM : MMRel, ArithLogicR<"subu", GPR32Opnd>, ADD_FM_MM<0, 0x1d0>; + def ADDu_MM : MMRel, ArithLogicR<"addu", GPR32Opnd, 1, II_ADDU, add>, + ADD_FM_MM<0, 0x150>; + def SUBu_MM : MMRel, ArithLogicR<"subu", GPR32Opnd, 0, II_SUBU, sub>, + ADD_FM_MM<0, 0x1d0>; def MUL_MM : MMRel, ArithLogicR<"mul", GPR32Opnd>, ADD_FM_MM<0, 0x210>; def ADD_MM : MMRel, ArithLogicR<"add", GPR32Opnd>, ADD_FM_MM<0, 0x110>; def SUB_MM : MMRel, ArithLogicR<"sub", GPR32Opnd>, ADD_FM_MM<0, 0x190>; @@ -591,6 +668,9 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in { def UDIV_MM : MMRel, Div<"divu", II_DIVU, GPR32Opnd, [HI0, LO0]>, MULT_FM_MM<0x2ec>; + /// Arithmetic Instructions with PC and Immediate + def ADDIUPC_MM : AddImmUPC<"addiupc", GPRMM16Opnd>, ADDIUPC_FM_MM; + /// Shift Instructions def SLL_MM : MMRel, shift_rotate_imm<"sll", uimm5, GPR32Opnd, II_SLL>, SRA_FM_MM<0, 0>; @@ -645,6 +725,19 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in { def SWP_MM : StorePairMM<"swp">, LWM_FM_MM<0x9>; def LWP_MM : LoadPairMM<"lwp">, LWM_FM_MM<0x1>; + /// Load and Store multiple pseudo Instructions + class LoadWordMultMM<string instr_asm > : + MipsAsmPseudoInst<(outs reglist:$rt), (ins mem_mm_12:$addr), + !strconcat(instr_asm, "\t$rt, $addr")> ; + + class StoreWordMultMM<string instr_asm > : + MipsAsmPseudoInst<(outs), (ins reglist:$rt, mem_mm_12:$addr), + !strconcat(instr_asm, "\t$rt, $addr")> ; + + + def SWM_MM : StoreWordMultMM<"swm">; + def LWM_MM : LoadWordMultMM<"lwm">; + /// Move Conditional def MOVZ_I_MM : MMRel, CMov_I_I_FT<"movz", GPR32Opnd, GPR32Opnd, NoItinerary>, ADD_FM_MM<0, 0x58>; @@ -697,6 +790,7 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in { def J_MM : MMRel, JumpFJ<jmptarget_mm, "j", br, bb, "j">, J_FM_MM<0x35>; def JAL_MM : MMRel, JumpLink<"jal", calltarget_mm>, J_FM_MM<0x3d>; + def JALX_MM : MMRel, JumpLink<"jalx", calltarget>, J_FM_MM<0x3c>; } def JR_MM : MMRel, IndirectBranch<"jr", GPR32Opnd>, JR_FM_MM<0x3c>; def JALR_MM : JumpLinkReg<"jalr", GPR32Opnd>, JALR_FM_MM<0x03c>; @@ -791,6 +885,8 @@ def : MipsPat<(i32 immSExt16:$imm), (ADDiu_MM ZERO, immSExt16:$imm)>; def : MipsPat<(i32 immZExt16:$imm), (ORi_MM ZERO, immZExt16:$imm)>; +def : MipsPat<(not GPR32:$in), + (NOR_MM GPR32Opnd:$in, ZERO)>; def : MipsPat<(add GPRMM16:$src, immSExtAddiur2:$imm), (ADDIUR2_MM GPRMM16:$src, immSExtAddiur2:$imm)>; @@ -814,10 +910,26 @@ def : MipsPat<(srl GPRMM16:$src, immZExt2Shift:$imm), def : MipsPat<(srl GPR32:$src, immZExt5:$imm), (SRL_MM GPR32:$src, immZExt5:$imm)>; +def : MipsPat<(store GPRMM16:$src, addrimm4lsl2:$addr), + (SW16_MM GPRMM16:$src, addrimm4lsl2:$addr)>; +def : MipsPat<(store GPR32:$src, addr:$addr), + (SW_MM GPR32:$src, addr:$addr)>; + +def : MipsPat<(load addrimm4lsl2:$addr), + (LW16_MM addrimm4lsl2:$addr)>; +def : MipsPat<(load addr:$addr), + (LW_MM addr:$addr)>; + //===----------------------------------------------------------------------===// // MicroMips instruction aliases //===----------------------------------------------------------------------===// +class UncondBranchMMPseudo<string opstr> : + MipsAsmPseudoInst<(outs), (ins brtarget_mm:$offset), + !strconcat(opstr, "\t$offset")>; + + def B_MM_Pseudo : UncondBranchMMPseudo<"b">; + def : MipsInstAlias<"wait", (WAIT_MM 0x0), 1>; def : MipsInstAlias<"nop", (SLL_MM ZERO, ZERO, 0), 1>; def : MipsInstAlias<"nop", (MOVE16_MM ZERO, ZERO), 1>; diff --git a/contrib/llvm/lib/Target/Mips/Mips.h b/contrib/llvm/lib/Target/Mips/Mips.h index 87f1b04..671d7a8 100644 --- a/contrib/llvm/lib/Target/Mips/Mips.h +++ b/contrib/llvm/lib/Target/Mips/Mips.h @@ -20,9 +20,13 @@ namespace llvm { class MipsTargetMachine; + class ModulePass; class FunctionPass; - FunctionPass *createMipsISelDag(MipsTargetMachine &TM); + ModulePass *createMipsOs16Pass(MipsTargetMachine &TM); + ModulePass *createMips16HardFloatPass(MipsTargetMachine &TM); + + FunctionPass *createMipsModuleISelDagPass(MipsTargetMachine &TM); FunctionPass *createMipsOptimizePICCallPass(MipsTargetMachine &TM); FunctionPass *createMipsDelaySlotFillerPass(MipsTargetMachine &TM); FunctionPass *createMipsLongBranchPass(MipsTargetMachine &TM); diff --git a/contrib/llvm/lib/Target/Mips/Mips.td b/contrib/llvm/lib/Target/Mips/Mips.td index 5ad5683..dbb5f7b 100644 --- a/contrib/llvm/lib/Target/Mips/Mips.td +++ b/contrib/llvm/lib/Target/Mips/Mips.td @@ -28,12 +28,15 @@ class PredicateControl { list<Predicate> FGRPredicates = []; // Predicates for the instruction group membership such as ISA's and ASE's list<Predicate> InsnPredicates = []; + // Predicate for marking the instruction as usable in hard-float mode only. + list<Predicate> HardFloatPredicate = []; // Predicates for anything else list<Predicate> AdditionalPredicates = []; list<Predicate> Predicates = !listconcat(EncodingPredicates, GPRPredicates, FGRPredicates, InsnPredicates, + HardFloatPredicate, AdditionalPredicates); } @@ -69,14 +72,8 @@ def FeatureNaN2008 : SubtargetFeature<"nan2008", "IsNaN2008bit", "true", "IEEE 754-2008 NaN encoding">; def FeatureSingleFloat : SubtargetFeature<"single-float", "IsSingleFloat", "true", "Only supports single precision float">; -def FeatureO32 : SubtargetFeature<"o32", "ABI", "MipsABIInfo::O32()", - "Enable o32 ABI">; -def FeatureN32 : SubtargetFeature<"n32", "ABI", "MipsABIInfo::N32()", - "Enable n32 ABI">; -def FeatureN64 : SubtargetFeature<"n64", "ABI", "MipsABIInfo::N64()", - "Enable n64 ABI">; -def FeatureEABI : SubtargetFeature<"eabi", "ABI", "MipsABIInfo::EABI()", - "Enable eabi ABI">; +def FeatureSoftFloat : SubtargetFeature<"soft-float", "IsSoftFloat", "true", + "Does not support floating point instructions">; def FeatureNoOddSPReg : SubtargetFeature<"nooddspreg", "UseOddSPReg", "false", "Disable odd numbered single-precision " "registers">; @@ -122,10 +119,16 @@ def FeatureMips32r2 : SubtargetFeature<"mips32r2", "MipsArchVersion", "Mips32r2", "Mips32r2 ISA Support", [FeatureMips3_32r2, FeatureMips4_32r2, FeatureMips5_32r2, FeatureMips32]>; +def FeatureMips32r3 : SubtargetFeature<"mips32r3", "MipsArchVersion", + "Mips32r3", "Mips32r3 ISA Support", + [FeatureMips32r2]>; +def FeatureMips32r5 : SubtargetFeature<"mips32r5", "MipsArchVersion", + "Mips32r5", "Mips32r5 ISA Support", + [FeatureMips32r3]>; def FeatureMips32r6 : SubtargetFeature<"mips32r6", "MipsArchVersion", "Mips32r6", "Mips32r6 ISA Support [experimental]", - [FeatureMips32r2, FeatureFP64Bit, + [FeatureMips32r5, FeatureFP64Bit, FeatureNaN2008]>; def FeatureMips64 : SubtargetFeature<"mips64", "MipsArchVersion", "Mips64", "Mips64 ISA Support", @@ -133,10 +136,16 @@ def FeatureMips64 : SubtargetFeature<"mips64", "MipsArchVersion", def FeatureMips64r2 : SubtargetFeature<"mips64r2", "MipsArchVersion", "Mips64r2", "Mips64r2 ISA Support", [FeatureMips64, FeatureMips32r2]>; +def FeatureMips64r3 : SubtargetFeature<"mips64r3", "MipsArchVersion", + "Mips64r3", "Mips64r3 ISA Support", + [FeatureMips64r2, FeatureMips32r3]>; +def FeatureMips64r5 : SubtargetFeature<"mips64r5", "MipsArchVersion", + "Mips64r5", "Mips64r5 ISA Support", + [FeatureMips64r3, FeatureMips32r5]>; def FeatureMips64r6 : SubtargetFeature<"mips64r6", "MipsArchVersion", "Mips64r6", "Mips64r6 ISA Support [experimental]", - [FeatureMips32r6, FeatureMips64r2, + [FeatureMips32r6, FeatureMips64r5, FeatureNaN2008]>; def FeatureMips16 : SubtargetFeature<"mips16", "InMips16Mode", "true", @@ -162,20 +171,24 @@ def FeatureCnMips : SubtargetFeature<"cnmips", "HasCnMips", class Proc<string Name, list<SubtargetFeature> Features> : Processor<Name, MipsGenericItineraries, Features>; -def : Proc<"mips1", [FeatureMips1, FeatureO32]>; -def : Proc<"mips2", [FeatureMips2, FeatureO32]>; -def : Proc<"mips32", [FeatureMips32, FeatureO32]>; -def : Proc<"mips32r2", [FeatureMips32r2, FeatureO32]>; -def : Proc<"mips32r6", [FeatureMips32r6, FeatureO32]>; - -def : Proc<"mips3", [FeatureMips3, FeatureN64]>; -def : Proc<"mips4", [FeatureMips4, FeatureN64]>; -def : Proc<"mips5", [FeatureMips5, FeatureN64]>; -def : Proc<"mips64", [FeatureMips64, FeatureN64]>; -def : Proc<"mips64r2", [FeatureMips64r2, FeatureN64]>; -def : Proc<"mips64r6", [FeatureMips64r6, FeatureN64]>; -def : Proc<"mips16", [FeatureMips16, FeatureO32]>; -def : Proc<"octeon", [FeatureMips64r2, FeatureN64, FeatureCnMips]>; +def : Proc<"mips1", [FeatureMips1]>; +def : Proc<"mips2", [FeatureMips2]>; +def : Proc<"mips32", [FeatureMips32]>; +def : Proc<"mips32r2", [FeatureMips32r2]>; +def : Proc<"mips32r3", [FeatureMips32r3]>; +def : Proc<"mips32r5", [FeatureMips32r5]>; +def : Proc<"mips32r6", [FeatureMips32r6]>; + +def : Proc<"mips3", [FeatureMips3]>; +def : Proc<"mips4", [FeatureMips4]>; +def : Proc<"mips5", [FeatureMips5]>; +def : Proc<"mips64", [FeatureMips64]>; +def : Proc<"mips64r2", [FeatureMips64r2]>; +def : Proc<"mips64r3", [FeatureMips64r3]>; +def : Proc<"mips64r5", [FeatureMips64r5]>; +def : Proc<"mips64r6", [FeatureMips64r6]>; +def : Proc<"mips16", [FeatureMips16]>; +def : Proc<"octeon", [FeatureMips64r2, FeatureCnMips]>; def MipsAsmParser : AsmParser { let ShouldEmitMatchRegisterName = 0; diff --git a/contrib/llvm/lib/Target/Mips/Mips16FrameLowering.cpp b/contrib/llvm/lib/Target/Mips/Mips16FrameLowering.cpp index 6070276..db2a924 100644 --- a/contrib/llvm/lib/Target/Mips/Mips16FrameLowering.cpp +++ b/contrib/llvm/lib/Target/Mips/Mips16FrameLowering.cpp @@ -32,11 +32,12 @@ using namespace llvm; Mips16FrameLowering::Mips16FrameLowering(const MipsSubtarget &STI) : MipsFrameLowering(STI, STI.stackAlignment()) {} -void Mips16FrameLowering::emitPrologue(MachineFunction &MF) const { - MachineBasicBlock &MBB = MF.front(); +void Mips16FrameLowering::emitPrologue(MachineFunction &MF, + MachineBasicBlock &MBB) const { + assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported"); MachineFrameInfo *MFI = MF.getFrameInfo(); const Mips16InstrInfo &TII = - *static_cast<const Mips16InstrInfo *>(MF.getSubtarget().getInstrInfo()); + *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo()); MachineBasicBlock::iterator MBBI = MBB.begin(); DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); uint64_t StackSize = MFI->getStackSize(); @@ -84,7 +85,7 @@ void Mips16FrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); MachineFrameInfo *MFI = MF.getFrameInfo(); const Mips16InstrInfo &TII = - *static_cast<const Mips16InstrInfo *>(MF.getSubtarget().getInstrInfo()); + *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo()); DebugLoc dl = MBBI->getDebugLoc(); uint64_t StackSize = MFI->getStackSize(); @@ -143,25 +144,6 @@ bool Mips16FrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB, return true; } -// Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions -void Mips16FrameLowering:: -eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const { - if (!hasReservedCallFrame(MF)) { - int64_t Amount = I->getOperand(0).getImm(); - - if (I->getOpcode() == Mips::ADJCALLSTACKDOWN) - Amount = -Amount; - - const Mips16InstrInfo &TII = - *static_cast<const Mips16InstrInfo *>(MF.getSubtarget().getInstrInfo()); - - TII.adjustStackPtr(Mips::SP, Amount, MBB, I); - } - - MBB.erase(I); -} - bool Mips16FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { const MachineFrameInfo *MFI = MF.getFrameInfo(); @@ -174,7 +156,7 @@ void Mips16FrameLowering:: processFunctionBeforeCalleeSavedScan(MachineFunction &MF, RegScavenger *RS) const { const Mips16InstrInfo &TII = - *static_cast<const Mips16InstrInfo *>(MF.getSubtarget().getInstrInfo()); + *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo()); const MipsRegisterInfo &RI = TII.getRegisterInfo(); const BitVector Reserved = RI.getReservedRegs(MF); bool SaveS2 = Reserved[Mips::S2]; diff --git a/contrib/llvm/lib/Target/Mips/Mips16FrameLowering.h b/contrib/llvm/lib/Target/Mips/Mips16FrameLowering.h index 012d558..f281c92 100644 --- a/contrib/llvm/lib/Target/Mips/Mips16FrameLowering.h +++ b/contrib/llvm/lib/Target/Mips/Mips16FrameLowering.h @@ -23,13 +23,9 @@ public: /// emitProlog/emitEpilog - These methods insert prolog and epilog code into /// the function. - void emitPrologue(MachineFunction &MF) const override; + void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; - void eliminateCallFramePseudoInstr(MachineFunction &MF, - MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const override; - bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const std::vector<CalleeSavedInfo> &CSI, diff --git a/contrib/llvm/lib/Target/Mips/Mips16HardFloat.cpp b/contrib/llvm/lib/Target/Mips/Mips16HardFloat.cpp index 32dc90a..893fc7c 100644 --- a/contrib/llvm/lib/Target/Mips/Mips16HardFloat.cpp +++ b/contrib/llvm/lib/Target/Mips/Mips16HardFloat.cpp @@ -11,7 +11,7 @@ // //===----------------------------------------------------------------------===// -#include "Mips16HardFloat.h" +#include "MipsTargetMachine.h" #include "llvm/IR/Module.h" #include "llvm/IR/Value.h" #include "llvm/Support/Debug.h" @@ -19,38 +19,51 @@ #include <algorithm> #include <string> -#define DEBUG_TYPE "mips16-hard-float" +using namespace llvm; -static void inlineAsmOut - (LLVMContext &C, StringRef AsmString, BasicBlock *BB ) { - std::vector<llvm::Type *> AsmArgTypes; - std::vector<llvm::Value*> AsmArgs; - llvm::FunctionType *AsmFTy = - llvm::FunctionType::get(Type::getVoidTy(C), - AsmArgTypes, false); - llvm::InlineAsm *IA = - llvm::InlineAsm::get(AsmFTy, AsmString, "", true, - /* IsAlignStack */ false, - llvm::InlineAsm::AD_ATT); - CallInst::Create(IA, AsmArgs, "", BB); -} +#define DEBUG_TYPE "mips16-hard-float" namespace { + class Mips16HardFloat : public ModulePass { + public: + static char ID; -class InlineAsmHelper { - LLVMContext &C; - BasicBlock *BB; -public: - InlineAsmHelper(LLVMContext &C_, BasicBlock *BB_) : - C(C_), BB(BB_) { - } + Mips16HardFloat(MipsTargetMachine &TM_) : ModulePass(ID), TM(TM_) {} - void Out(StringRef AsmString) { - inlineAsmOut(C, AsmString, BB); - } + const char *getPassName() const override { + return "MIPS16 Hard Float Pass"; + } -}; + bool runOnModule(Module &M) override; + + protected: + const MipsTargetMachine &TM; + }; + + class InlineAsmHelper { + LLVMContext &C; + BasicBlock *BB; + public: + InlineAsmHelper(LLVMContext &C_, BasicBlock *BB_) : + C(C_), BB(BB_) { + } + + void Out(StringRef AsmString) { + std::vector<llvm::Type *> AsmArgTypes; + std::vector<llvm::Value*> AsmArgs; + + llvm::FunctionType *AsmFTy = llvm::FunctionType::get(Type::getVoidTy(C), + AsmArgTypes, false); + llvm::InlineAsm *IA = llvm::InlineAsm::get(AsmFTy, AsmString, "", true, + /* IsAlignStack */ false, + llvm::InlineAsm::AD_ATT); + CallInst::Create(IA, AsmArgs, "", BB); + } + }; + + char Mips16HardFloat::ID = 0; } + // // Return types that matter for hard float are: // float, double, complex float, and complex double @@ -154,11 +167,11 @@ static bool needsFPStubFromParams(Function &F) { if (F.arg_size() >=1) { Type *ArgType = F.getFunctionType()->getParamType(0); switch (ArgType->getTypeID()) { - case Type::FloatTyID: - case Type::DoubleTyID: - return true; - default: - break; + case Type::FloatTyID: + case Type::DoubleTyID: + return true; + default: + break; } } return false; @@ -182,10 +195,8 @@ static bool needsFPHelperFromSig(Function &F) { // We swap between FP and Integer registers to allow Mips16 and Mips32 to // interoperate // - -static void swapFPIntParams - (FPParamVariant PV, Module *M, InlineAsmHelper &IAH, - bool LE, bool ToFP) { +static void swapFPIntParams(FPParamVariant PV, Module *M, InlineAsmHelper &IAH, + bool LE, bool ToFP) { //LLVMContext &Context = M->getContext(); std::string MI = ToFP? "mtc1 ": "mfc1 "; switch (PV) { @@ -242,6 +253,7 @@ static void swapFPIntParams return; } } + // // Make sure that we know we already need a stub for this function. // Having called needsFPHelperFromSig @@ -297,8 +309,8 @@ static void assureFPCallStub(Function &F, Module *M, break; case CFRet: if (LE) { - IAH.Out("mfc1 $$2,$$f0"); - IAH.Out("mfc1 $$3,$$f2"); + IAH.Out("mfc1 $$2,$$f0"); + IAH.Out("mfc1 $$3,$$f2"); } else { IAH.Out("mfc1 $$3,$$f0"); IAH.Out("mfc1 $$3,$$f2"); @@ -331,28 +343,27 @@ static void assureFPCallStub(Function &F, Module *M, // // Functions that are llvm intrinsics and don't need helpers. // -static const char *IntrinsicInline[] = - {"fabs", - "fabsf", - "llvm.ceil.f32", "llvm.ceil.f64", - "llvm.copysign.f32", "llvm.copysign.f64", - "llvm.cos.f32", "llvm.cos.f64", - "llvm.exp.f32", "llvm.exp.f64", - "llvm.exp2.f32", "llvm.exp2.f64", - "llvm.fabs.f32", "llvm.fabs.f64", - "llvm.floor.f32", "llvm.floor.f64", - "llvm.fma.f32", "llvm.fma.f64", - "llvm.log.f32", "llvm.log.f64", - "llvm.log10.f32", "llvm.log10.f64", - "llvm.nearbyint.f32", "llvm.nearbyint.f64", - "llvm.pow.f32", "llvm.pow.f64", - "llvm.powi.f32", "llvm.powi.f64", - "llvm.rint.f32", "llvm.rint.f64", - "llvm.round.f32", "llvm.round.f64", - "llvm.sin.f32", "llvm.sin.f64", - "llvm.sqrt.f32", "llvm.sqrt.f64", - "llvm.trunc.f32", "llvm.trunc.f64", - }; +static const char *IntrinsicInline[] = { + "fabs", "fabsf", + "llvm.ceil.f32", "llvm.ceil.f64", + "llvm.copysign.f32", "llvm.copysign.f64", + "llvm.cos.f32", "llvm.cos.f64", + "llvm.exp.f32", "llvm.exp.f64", + "llvm.exp2.f32", "llvm.exp2.f64", + "llvm.fabs.f32", "llvm.fabs.f64", + "llvm.floor.f32", "llvm.floor.f64", + "llvm.fma.f32", "llvm.fma.f64", + "llvm.log.f32", "llvm.log.f64", + "llvm.log10.f32", "llvm.log10.f64", + "llvm.nearbyint.f32", "llvm.nearbyint.f64", + "llvm.pow.f32", "llvm.pow.f64", + "llvm.powi.f32", "llvm.powi.f64", + "llvm.rint.f32", "llvm.rint.f64", + "llvm.round.f32", "llvm.round.f64", + "llvm.sin.f32", "llvm.sin.f64", + "llvm.sqrt.f32", "llvm.sqrt.f64", + "llvm.trunc.f32", "llvm.trunc.f64", +}; static bool isIntrinsicInline(Function *F) { return std::binary_search(std::begin(IntrinsicInline), @@ -384,9 +395,10 @@ static bool fixupFPReturnAndCall(Function &F, Module *M, Type *T = RVal->getType(); FPReturnVariant RV = whichFPReturnVariant(T); if (RV == NoFPRet) continue; - static const char* Helper[NoFPRet] = - {"__mips16_ret_sf", "__mips16_ret_df", "__mips16_ret_sc", - "__mips16_ret_dc"}; + static const char* Helper[NoFPRet] = { + "__mips16_ret_sf", "__mips16_ret_df", "__mips16_ret_sc", + "__mips16_ret_dc" + }; const char *Name = Helper[RV]; AttributeSet A; Value *Params[] = {RVal}; @@ -406,33 +418,33 @@ static bool fixupFPReturnAndCall(Function &F, Module *M, Value *F = (M->getOrInsertFunction(Name, A, MyVoid, T, nullptr)); CallInst::Create(F, Params, "", &Inst ); } else if (const CallInst *CI = dyn_cast<CallInst>(I)) { - const Value* V = CI->getCalledValue(); - const Type* T = nullptr; - if (V) T = V->getType(); - const PointerType *PFT=nullptr; - if (T) PFT = dyn_cast<PointerType>(T); - const FunctionType *FT=nullptr; - if (PFT) FT = dyn_cast<FunctionType>(PFT->getElementType()); - Function *F_ = CI->getCalledFunction(); - if (FT && needsFPReturnHelper(*FT) && - !(F_ && isIntrinsicInline(F_))) { + const Value* V = CI->getCalledValue(); + const Type* T = nullptr; + if (V) T = V->getType(); + const PointerType *PFT=nullptr; + if (T) PFT = dyn_cast<PointerType>(T); + const FunctionType *FT=nullptr; + if (PFT) FT = dyn_cast<FunctionType>(PFT->getElementType()); + Function *F_ = CI->getCalledFunction(); + if (FT && needsFPReturnHelper(*FT) && + !(F_ && isIntrinsicInline(F_))) { + Modified=true; + F.addFnAttr("saveS2"); + } + if (F_ && !isIntrinsicInline(F_)) { + // pic mode calls are handled by already defined + // helper functions + if (needsFPReturnHelper(*F_)) { Modified=true; F.addFnAttr("saveS2"); } - if (F_ && !isIntrinsicInline(F_)) { - // pic mode calls are handled by already defined - // helper functions - if (needsFPReturnHelper(*F_)) { + if (TM.getRelocationModel() != Reloc::PIC_ ) { + if (needsFPHelperFromSig(*F_)) { + assureFPCallStub(*F_, M, TM); Modified=true; - F.addFnAttr("saveS2"); - } - if (TM.getRelocationModel() != Reloc::PIC_ ) { - if (needsFPHelperFromSig(*F_)) { - assureFPCallStub(*F_, M, TM); - Modified=true; - } } } + } } } return Modified; @@ -489,7 +501,6 @@ static void removeUseSoftFloat(Function &F) { F.addAttributes(AttributeSet::FunctionIndex, A); } -namespace llvm { // // This pass only makes sense when the underlying chip has floating point but @@ -530,11 +541,7 @@ bool Mips16HardFloat::runOnModule(Module &M) { return Modified; } -char Mips16HardFloat::ID = 0; - -} -ModulePass *llvm::createMips16HardFloat(MipsTargetMachine &TM) { +ModulePass *llvm::createMips16HardFloatPass(MipsTargetMachine &TM) { return new Mips16HardFloat(TM); } - diff --git a/contrib/llvm/lib/Target/Mips/Mips16HardFloat.h b/contrib/llvm/lib/Target/Mips/Mips16HardFloat.h deleted file mode 100644 index 586cc25..0000000 --- a/contrib/llvm/lib/Target/Mips/Mips16HardFloat.h +++ /dev/null @@ -1,43 +0,0 @@ -//===---- Mips16HardFloat.h for Mips16 Hard Float --------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines a phase which implements part of the floating point -// interoperability between Mips16 and Mips32 code. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MIPS16HARDFLOAT_H -#define LLVM_LIB_TARGET_MIPS_MIPS16HARDFLOAT_H - -#include "MCTargetDesc/MipsMCTargetDesc.h" -#include "MipsTargetMachine.h" -#include "llvm/Pass.h" -#include "llvm/Target/TargetMachine.h" - -using namespace llvm; - -namespace llvm { - -class Mips16HardFloat : public ModulePass { -public: - static char ID; - - Mips16HardFloat(MipsTargetMachine &TM_) : ModulePass(ID), TM(TM_) {} - - const char *getPassName() const override { return "MIPS16 Hard Float Pass"; } - bool runOnModule(Module &M) override; - -protected: - const MipsTargetMachine &TM; -}; - -ModulePass *createMips16HardFloat(MipsTargetMachine &TM); - -} -#endif diff --git a/contrib/llvm/lib/Target/Mips/Mips16ISelDAGToDAG.cpp b/contrib/llvm/lib/Target/Mips/Mips16ISelDAGToDAG.cpp index 36b3ac9..7b6a2a1 100644 --- a/contrib/llvm/lib/Target/Mips/Mips16ISelDAGToDAG.cpp +++ b/contrib/llvm/lib/Target/Mips/Mips16ISelDAGToDAG.cpp @@ -37,7 +37,7 @@ using namespace llvm; #define DEBUG_TYPE "mips-isel" bool Mips16DAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { - Subtarget = &TM.getSubtarget<MipsSubtarget>(); + Subtarget = &static_cast<const MipsSubtarget &>(MF.getSubtarget()); if (!Subtarget->inMips16Mode()) return false; return MipsDAGToDAGISel::runOnMachineFunction(MF); @@ -72,7 +72,7 @@ void Mips16DAGToDAGISel::initGlobalBaseReg(MachineFunction &MF) { MachineBasicBlock &MBB = MF.front(); MachineBasicBlock::iterator I = MBB.begin(); MachineRegisterInfo &RegInfo = MF.getRegInfo(); - const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); + const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc(); unsigned V0, V1, V2, GlobalBaseReg = MipsFI->getGlobalBaseReg(); const TargetRegisterClass *RC = &Mips::CPU16RegsRegClass; @@ -102,7 +102,7 @@ void Mips16DAGToDAGISel::initMips16SPAliasReg(MachineFunction &MF) { MachineBasicBlock &MBB = MF.front(); MachineBasicBlock::iterator I = MBB.begin(); - const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); + const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc(); unsigned Mips16SPAliasReg = MipsFI->getMips16SPAliasReg(); @@ -134,7 +134,7 @@ void Mips16DAGToDAGISel::getMips16SPRefReg(SDNode *Parent, SDValue &AliasReg) { switch (SD->getMemoryVT().getSizeInBits()) { case 8: case 16: - AliasReg = TM.getSubtargetImpl()->getFrameLowering()->hasFP(*MF) + AliasReg = Subtarget->getFrameLowering()->hasFP(*MF) ? AliasFPReg : getMips16SPAliasReg(); return; @@ -146,7 +146,7 @@ void Mips16DAGToDAGISel::getMips16SPRefReg(SDNode *Parent, SDValue &AliasReg) { switch (SD->getMemoryVT().getSizeInBits()) { case 8: case 16: - AliasReg = TM.getSubtargetImpl()->getFrameLowering()->hasFP(*MF) + AliasReg = Subtarget->getFrameLowering()->hasFP(*MF) ? AliasFPReg : getMips16SPAliasReg(); return; @@ -163,14 +163,15 @@ void Mips16DAGToDAGISel::getMips16SPRefReg(SDNode *Parent, SDValue &AliasReg) { bool Mips16DAGToDAGISel::selectAddr16( SDNode *Parent, SDValue Addr, SDValue &Base, SDValue &Offset, SDValue &Alias) { + SDLoc DL(Addr); EVT ValTy = Addr.getValueType(); - Alias = CurDAG->getTargetConstant(0, ValTy); + Alias = CurDAG->getTargetConstant(0, DL, ValTy); // if Address is FI, get the TargetFrameIndex. if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); - Offset = CurDAG->getTargetConstant(0, ValTy); + Offset = CurDAG->getTargetConstant(0, DL, ValTy); getMips16SPRefReg(Parent, Alias); return true; } @@ -199,7 +200,7 @@ bool Mips16DAGToDAGISel::selectAddr16( else Base = Addr.getOperand(0); - Offset = CurDAG->getTargetConstant(CN->getZExtValue(), ValTy); + Offset = CurDAG->getTargetConstant(CN->getZExtValue(), DL, ValTy); return true; } } @@ -235,7 +236,7 @@ bool Mips16DAGToDAGISel::selectAddr16( } } Base = Addr; - Offset = CurDAG->getTargetConstant(0, ValTy); + Offset = CurDAG->getTargetConstant(0, DL, ValTy); return true; } diff --git a/contrib/llvm/lib/Target/Mips/Mips16ISelLowering.cpp b/contrib/llvm/lib/Target/Mips/Mips16ISelLowering.cpp index 7479695..846e3c9 100644 --- a/contrib/llvm/lib/Target/Mips/Mips16ISelLowering.cpp +++ b/contrib/llvm/lib/Target/Mips/Mips16ISelLowering.cpp @@ -127,7 +127,7 @@ Mips16TargetLowering::Mips16TargetLowering(const MipsTargetMachine &TM, // Set up the register classes addRegisterClass(MVT::i32, &Mips::CPU16RegsRegClass); - if (!TM.Options.UseSoftFloat) + if (!Subtarget.useSoftFloat()) setMips16HardFloatLibCalls(); setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Expand); @@ -149,7 +149,7 @@ Mips16TargetLowering::Mips16TargetLowering(const MipsTargetMachine &TM, setOperationAction(ISD::BSWAP, MVT::i32, Expand); setOperationAction(ISD::BSWAP, MVT::i64, Expand); - computeRegisterProperties(); + computeRegisterProperties(STI.getRegisterInfo()); } const MipsTargetLowering * @@ -522,8 +522,7 @@ MachineBasicBlock *Mips16TargetLowering:: emitSel16(unsigned Opc, MachineInstr *MI, MachineBasicBlock *BB) const { if (DontExpandCondPseudos16) return BB; - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); DebugLoc DL = MI->getDebugLoc(); // To "insert" a SELECT_CC instruction, we actually have to insert the // diamond control-flow pattern. The incoming instruction knows the @@ -580,13 +579,12 @@ emitSel16(unsigned Opc, MachineInstr *MI, MachineBasicBlock *BB) const { return BB; } -MachineBasicBlock *Mips16TargetLowering::emitSelT16 - (unsigned Opc1, unsigned Opc2, - MachineInstr *MI, MachineBasicBlock *BB) const { +MachineBasicBlock * +Mips16TargetLowering::emitSelT16(unsigned Opc1, unsigned Opc2, MachineInstr *MI, + MachineBasicBlock *BB) const { if (DontExpandCondPseudos16) return BB; - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); DebugLoc DL = MI->getDebugLoc(); // To "insert" a SELECT_CC instruction, we actually have to insert the // diamond control-flow pattern. The incoming instruction knows the @@ -645,13 +643,13 @@ MachineBasicBlock *Mips16TargetLowering::emitSelT16 } -MachineBasicBlock *Mips16TargetLowering::emitSeliT16 - (unsigned Opc1, unsigned Opc2, - MachineInstr *MI, MachineBasicBlock *BB) const { +MachineBasicBlock * +Mips16TargetLowering::emitSeliT16(unsigned Opc1, unsigned Opc2, + MachineInstr *MI, + MachineBasicBlock *BB) const { if (DontExpandCondPseudos16) return BB; - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); DebugLoc DL = MI->getDebugLoc(); // To "insert" a SELECT_CC instruction, we actually have to insert the // diamond control-flow pattern. The incoming instruction knows the @@ -710,14 +708,13 @@ MachineBasicBlock *Mips16TargetLowering::emitSeliT16 } -MachineBasicBlock - *Mips16TargetLowering::emitFEXT_T8I816_ins(unsigned BtOpc, unsigned CmpOpc, - MachineInstr *MI, - MachineBasicBlock *BB) const { +MachineBasicBlock * +Mips16TargetLowering::emitFEXT_T8I816_ins(unsigned BtOpc, unsigned CmpOpc, + MachineInstr *MI, + MachineBasicBlock *BB) const { if (DontExpandCondPseudos16) return BB; - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); unsigned regX = MI->getOperand(0).getReg(); unsigned regY = MI->getOperand(1).getReg(); MachineBasicBlock *target = MI->getOperand(2).getMBB(); @@ -729,12 +726,11 @@ MachineBasicBlock } MachineBasicBlock *Mips16TargetLowering::emitFEXT_T8I8I16_ins( - unsigned BtOpc, unsigned CmpiOpc, unsigned CmpiXOpc, bool ImmSigned, - MachineInstr *MI, MachineBasicBlock *BB) const { + unsigned BtOpc, unsigned CmpiOpc, unsigned CmpiXOpc, bool ImmSigned, + MachineInstr *MI, MachineBasicBlock *BB) const { if (DontExpandCondPseudos16) return BB; - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); unsigned regX = MI->getOperand(0).getReg(); int64_t imm = MI->getOperand(1).getImm(); MachineBasicBlock *target = MI->getOperand(2).getMBB(); @@ -763,13 +759,12 @@ static unsigned Mips16WhichOp8uOr16simm llvm_unreachable("immediate field not usable"); } -MachineBasicBlock *Mips16TargetLowering::emitFEXT_CCRX16_ins( - unsigned SltOpc, - MachineInstr *MI, MachineBasicBlock *BB) const { +MachineBasicBlock * +Mips16TargetLowering::emitFEXT_CCRX16_ins(unsigned SltOpc, MachineInstr *MI, + MachineBasicBlock *BB) const { if (DontExpandCondPseudos16) return BB; - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); unsigned CC = MI->getOperand(0).getReg(); unsigned regX = MI->getOperand(1).getReg(); unsigned regY = MI->getOperand(2).getReg(); @@ -781,13 +776,13 @@ MachineBasicBlock *Mips16TargetLowering::emitFEXT_CCRX16_ins( return BB; } -MachineBasicBlock *Mips16TargetLowering::emitFEXT_CCRXI16_ins( - unsigned SltiOpc, unsigned SltiXOpc, - MachineInstr *MI, MachineBasicBlock *BB )const { +MachineBasicBlock * +Mips16TargetLowering::emitFEXT_CCRXI16_ins(unsigned SltiOpc, unsigned SltiXOpc, + MachineInstr *MI, + MachineBasicBlock *BB) const { if (DontExpandCondPseudos16) return BB; - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); unsigned CC = MI->getOperand(0).getReg(); unsigned regX = MI->getOperand(1).getReg(); int64_t Imm = MI->getOperand(2).getImm(); diff --git a/contrib/llvm/lib/Target/Mips/Mips16InstrInfo.cpp b/contrib/llvm/lib/Target/Mips/Mips16InstrInfo.cpp index 7e1fbfd..a49572e 100644 --- a/contrib/llvm/lib/Target/Mips/Mips16InstrInfo.cpp +++ b/contrib/llvm/lib/Target/Mips/Mips16InstrInfo.cpp @@ -1,4 +1,3 @@ - //===-- Mips16InstrInfo.cpp - Mips16 Instruction Information --------------===// // // The LLVM Compiler Infrastructure @@ -25,6 +24,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TargetRegistry.h" +#include "llvm/Support/raw_ostream.h" #include <cctype> using namespace llvm; @@ -32,7 +32,7 @@ using namespace llvm; #define DEBUG_TYPE "mips16-instrinfo" Mips16InstrInfo::Mips16InstrInfo(const MipsSubtarget &STI) - : MipsInstrInfo(STI, Mips::Bimm16), RI(STI) {} + : MipsInstrInfo(STI, Mips::Bimm16), RI() {} const MipsRegisterInfo &Mips16InstrInfo::getRegisterInfo() const { return RI; diff --git a/contrib/llvm/lib/Target/Mips/Mips16InstrInfo.h b/contrib/llvm/lib/Target/Mips/Mips16InstrInfo.h index e7d0c07..6540b40 100644 --- a/contrib/llvm/lib/Target/Mips/Mips16InstrInfo.h +++ b/contrib/llvm/lib/Target/Mips/Mips16InstrInfo.h @@ -18,7 +18,7 @@ #include "MipsInstrInfo.h" namespace llvm { - +class MipsSubtarget; class Mips16InstrInfo : public MipsInstrInfo { const Mips16RegisterInfo RI; @@ -77,7 +77,7 @@ public: /// Adjust SP by Amount bytes. void adjustStackPtr(unsigned SP, int64_t Amount, MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const; + MachineBasicBlock::iterator I) const override; /// Emit a series of instructions to load an immediate. // This is to adjust some FrameReg. We return the new register to be used diff --git a/contrib/llvm/lib/Target/Mips/Mips16RegisterInfo.cpp b/contrib/llvm/lib/Target/Mips/Mips16RegisterInfo.cpp index 0bb452a..ebd51d7 100644 --- a/contrib/llvm/lib/Target/Mips/Mips16RegisterInfo.cpp +++ b/contrib/llvm/lib/Target/Mips/Mips16RegisterInfo.cpp @@ -41,8 +41,7 @@ using namespace llvm; #define DEBUG_TYPE "mips16-registerinfo" -Mips16RegisterInfo::Mips16RegisterInfo(const MipsSubtarget &ST) - : MipsRegisterInfo(ST) {} +Mips16RegisterInfo::Mips16RegisterInfo() : MipsRegisterInfo() {} bool Mips16RegisterInfo::requiresRegisterScavenging (const MachineFunction &MF) const { @@ -140,8 +139,7 @@ void Mips16RegisterInfo::eliminateFI(MachineBasicBlock::iterator II, DebugLoc DL = II->getDebugLoc(); unsigned NewImm; const Mips16InstrInfo &TII = - *static_cast<const Mips16InstrInfo *>( - MBB.getParent()->getSubtarget().getInstrInfo()); + *static_cast<const Mips16InstrInfo *>(MF.getSubtarget().getInstrInfo()); FrameReg = TII.loadImmediate(FrameReg, Offset, MBB, II, DL, NewImm); Offset = SignExtend64<16>(NewImm); IsKill = true; diff --git a/contrib/llvm/lib/Target/Mips/Mips16RegisterInfo.h b/contrib/llvm/lib/Target/Mips/Mips16RegisterInfo.h index 3cdf836..d67a79b 100644 --- a/contrib/llvm/lib/Target/Mips/Mips16RegisterInfo.h +++ b/contrib/llvm/lib/Target/Mips/Mips16RegisterInfo.h @@ -21,7 +21,7 @@ class Mips16InstrInfo; class Mips16RegisterInfo : public MipsRegisterInfo { public: - Mips16RegisterInfo(const MipsSubtarget &Subtarget); + Mips16RegisterInfo(); bool requiresRegisterScavenging(const MachineFunction &MF) const override; diff --git a/contrib/llvm/lib/Target/Mips/Mips32r6InstrFormats.td b/contrib/llvm/lib/Target/Mips/Mips32r6InstrFormats.td index e9a4289..13216be 100644 --- a/contrib/llvm/lib/Target/Mips/Mips32r6InstrFormats.td +++ b/contrib/llvm/lib/Target/Mips/Mips32r6InstrFormats.td @@ -11,6 +11,25 @@ // //===----------------------------------------------------------------------===// +class R6MMR6Rel; + +def MipsR62MicroMipsR6 : InstrMapping { + let FilterClass = "R6MMR6Rel"; + // Instructions with the same BaseOpcode and isNVStore values form a row. + let RowFields = ["BaseOpcode"]; + // Instructions with the same predicate sense form a column. + let ColFields = ["Arch"]; + // The key column is the unpredicated instructions. + let KeyCol = ["mipsr6"]; + // Value columns are PredSense=true and PredSense=false + let ValueCols = [["mipsr6"], ["micromipsr6"]]; +} + +class MipsR6Arch<string opstr> { + string Arch = "mipsr6"; + string BaseOpcode = opstr; +} + class MipsR6Inst : MipsInst<(outs), (ins), "", [], NoItinerary, FrmOther>, PredicateControl { let DecoderNamespace = "Mips32r6_64r6"; diff --git a/contrib/llvm/lib/Target/Mips/Mips32r6InstrInfo.td b/contrib/llvm/lib/Target/Mips/Mips32r6InstrInfo.td index 49c6322..d6ab8a6 100644 --- a/contrib/llvm/lib/Target/Mips/Mips32r6InstrInfo.td +++ b/contrib/llvm/lib/Target/Mips/Mips32r6InstrInfo.td @@ -188,52 +188,52 @@ multiclass CMP_CC_M <FIELD_CMP_FORMAT Format, string Typestr, RegisterOperand FGROpnd>{ def CMP_F_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_AF>, CMP_CONDN_DESC_BASE<"af", Typestr, FGROpnd>, - ISA_MIPS32R6; + ISA_MIPS32R6, HARDFLOAT; def CMP_UN_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_UN>, CMP_CONDN_DESC_BASE<"un", Typestr, FGROpnd, setuo>, - ISA_MIPS32R6; + ISA_MIPS32R6, HARDFLOAT; def CMP_EQ_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_EQ>, CMP_CONDN_DESC_BASE<"eq", Typestr, FGROpnd, setoeq>, - ISA_MIPS32R6; + ISA_MIPS32R6, HARDFLOAT; def CMP_UEQ_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_UEQ>, CMP_CONDN_DESC_BASE<"ueq", Typestr, FGROpnd, setueq>, - ISA_MIPS32R6; + ISA_MIPS32R6, HARDFLOAT; def CMP_LT_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_LT>, CMP_CONDN_DESC_BASE<"lt", Typestr, FGROpnd, setolt>, - ISA_MIPS32R6; + ISA_MIPS32R6, HARDFLOAT; def CMP_ULT_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_ULT>, CMP_CONDN_DESC_BASE<"ult", Typestr, FGROpnd, setult>, - ISA_MIPS32R6; + ISA_MIPS32R6, HARDFLOAT; def CMP_LE_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_LE>, CMP_CONDN_DESC_BASE<"le", Typestr, FGROpnd, setole>, - ISA_MIPS32R6; + ISA_MIPS32R6, HARDFLOAT; def CMP_ULE_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_ULE>, CMP_CONDN_DESC_BASE<"ule", Typestr, FGROpnd, setule>, - ISA_MIPS32R6; + ISA_MIPS32R6, HARDFLOAT; def CMP_SAF_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_SAF>, CMP_CONDN_DESC_BASE<"saf", Typestr, FGROpnd>, - ISA_MIPS32R6; + ISA_MIPS32R6, HARDFLOAT; def CMP_SUN_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_SUN>, CMP_CONDN_DESC_BASE<"sun", Typestr, FGROpnd>, - ISA_MIPS32R6; + ISA_MIPS32R6, HARDFLOAT; def CMP_SEQ_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_SEQ>, CMP_CONDN_DESC_BASE<"seq", Typestr, FGROpnd>, - ISA_MIPS32R6; + ISA_MIPS32R6, HARDFLOAT; def CMP_SUEQ_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_SUEQ>, CMP_CONDN_DESC_BASE<"sueq", Typestr, FGROpnd>, - ISA_MIPS32R6; + ISA_MIPS32R6, HARDFLOAT; def CMP_SLT_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_SLT>, CMP_CONDN_DESC_BASE<"slt", Typestr, FGROpnd>, - ISA_MIPS32R6; + ISA_MIPS32R6, HARDFLOAT; def CMP_SULT_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_SULT>, CMP_CONDN_DESC_BASE<"sult", Typestr, FGROpnd>, - ISA_MIPS32R6; + ISA_MIPS32R6, HARDFLOAT; def CMP_SLE_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_SLE>, CMP_CONDN_DESC_BASE<"sle", Typestr, FGROpnd>, - ISA_MIPS32R6; + ISA_MIPS32R6, HARDFLOAT; def CMP_SULE_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_SULE>, CMP_CONDN_DESC_BASE<"sule", Typestr, FGROpnd>, - ISA_MIPS32R6; + ISA_MIPS32R6, HARDFLOAT; } //===----------------------------------------------------------------------===// @@ -243,7 +243,7 @@ multiclass CMP_CC_M <FIELD_CMP_FORMAT Format, string Typestr, //===----------------------------------------------------------------------===// class PCREL_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - Operand ImmOpnd> { + Operand ImmOpnd> : MipsR6Arch<instr_asm> { dag OutOperandList = (outs GPROpnd:$rs); dag InOperandList = (ins ImmOpnd:$imm); string AsmString = !strconcat(instr_asm, "\t$rs, $imm"); @@ -255,7 +255,7 @@ class LWPC_DESC: PCREL_DESC_BASE<"lwpc", GPR32Opnd, simm19_lsl2>; class LWUPC_DESC: PCREL_DESC_BASE<"lwupc", GPR32Opnd, simm19_lsl2>; class ALIGN_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - Operand ImmOpnd> { + Operand ImmOpnd> : MipsR6Arch<instr_asm> { dag OutOperandList = (outs GPROpnd:$rd); dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt, ImmOpnd:$bp); string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt, $bp"); @@ -264,7 +264,8 @@ class ALIGN_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, class ALIGN_DESC : ALIGN_DESC_BASE<"align", GPR32Opnd, uimm2>; -class ALUIPC_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> { +class ALUIPC_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> + : MipsR6Arch<instr_asm> { dag OutOperandList = (outs GPROpnd:$rs); dag InOperandList = (ins simm16:$imm); string AsmString = !strconcat(instr_asm, "\t$rs, $imm"); @@ -274,7 +275,8 @@ class ALUIPC_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> { class ALUIPC_DESC : ALUIPC_DESC_BASE<"aluipc", GPR32Opnd>; class AUIPC_DESC : ALUIPC_DESC_BASE<"auipc", GPR32Opnd>; -class AUI_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> { +class AUI_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> + : MipsR6Arch<instr_asm> { dag OutOperandList = (outs GPROpnd:$rs); dag InOperandList = (ins GPROpnd:$rt, simm16:$imm); string AsmString = !strconcat(instr_asm, "\t$rs, $rt, $imm"); @@ -289,7 +291,8 @@ class BRANCH_DESC_BASE { bit hasDelaySlot = 0; } -class BC_DESC_BASE<string instr_asm, DAGOperand opnd> : BRANCH_DESC_BASE { +class BC_DESC_BASE<string instr_asm, DAGOperand opnd> : BRANCH_DESC_BASE, + MipsR6Arch<instr_asm> { dag InOperandList = (ins opnd:$offset); dag OutOperandList = (outs); string AsmString = !strconcat(instr_asm, "\t$offset"); @@ -313,7 +316,8 @@ class CMP_CBR_EQNE_Z_DESC_BASE<string instr_asm, DAGOperand opnd, } class CMP_CBR_RT_Z_DESC_BASE<string instr_asm, DAGOperand opnd, - RegisterOperand GPROpnd> : BRANCH_DESC_BASE { + RegisterOperand GPROpnd> + : BRANCH_DESC_BASE, MipsR6Arch<instr_asm> { dag InOperandList = (ins GPROpnd:$rt, opnd:$offset); dag OutOperandList = (outs); string AsmString = !strconcat(instr_asm, "\t$rt, $offset"); @@ -373,7 +377,8 @@ class BOVC_DESC : CMP_BC_DESC_BASE<"bovc", brtarget, GPR32Opnd>; class BNVC_DESC : CMP_BC_DESC_BASE<"bnvc", brtarget, GPR32Opnd>; class JMP_IDX_COMPACT_DESC_BASE<string opstr, DAGOperand opnd, - RegisterOperand GPROpnd> { + RegisterOperand GPROpnd> + : MipsR6Arch<opstr> { dag InOperandList = (ins GPROpnd:$rt, opnd:$offset); string AsmString = !strconcat(opstr, "\t$rt, $offset"); list<dag> Pattern = []; @@ -400,7 +405,8 @@ class JR_HB_R6_DESC : JR_HB_DESC_BASE<"jr.hb", GPR32Opnd> { bit isBarrier=1; } -class BITSWAP_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> { +class BITSWAP_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> + : MipsR6Arch<instr_asm> { dag OutOperandList = (outs GPROpnd:$rd); dag InOperandList = (ins GPROpnd:$rt); string AsmString = !strconcat(instr_asm, "\t$rd, $rt"); @@ -410,7 +416,8 @@ class BITSWAP_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> { class BITSWAP_DESC : BITSWAP_DESC_BASE<"bitswap", GPR32Opnd>; class DIVMOD_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - SDPatternOperator Op=null_frag> { + SDPatternOperator Op=null_frag> + : MipsR6Arch<instr_asm> { dag OutOperandList = (outs GPROpnd:$rd); dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt); string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt"); @@ -451,7 +458,7 @@ class BNEZALC_DESC : CMP_CBR_RT_Z_DESC_BASE<"bnezalc", brtarget, GPR32Opnd> { } class MUL_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - SDPatternOperator Op=null_frag> { + SDPatternOperator Op=null_frag> : MipsR6Arch<instr_asm> { dag OutOperandList = (outs GPROpnd:$rd); dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt); string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt"); @@ -479,7 +486,8 @@ class SEL_D_DESC : COP1_SEL_DESC_BASE<"sel.d", FGR64Opnd> { } class SEL_S_DESC : COP1_SEL_DESC_BASE<"sel.s", FGR32Opnd>; -class SELEQNE_Z_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> { +class SELEQNE_Z_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> + : MipsR6Arch<instr_asm> { dag OutOperandList = (outs GPROpnd:$rd); dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt); string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt"); @@ -544,7 +552,7 @@ class CLASS_S_DESC : CLASS_RINT_DESC_BASE<"class.s", FGR32Opnd>; class CLASS_D_DESC : CLASS_RINT_DESC_BASE<"class.d", FGR64Opnd>; class CACHE_HINT_DESC<string instr_asm, Operand MemOpnd, - RegisterOperand GPROpnd> { + RegisterOperand GPROpnd> : MipsR6Arch<instr_asm> { dag OutOperandList = (outs); dag InOperandList = (ins MemOpnd:$addr, uimm5:$hint); string AsmString = !strconcat(instr_asm, "\t$hint, $addr"); @@ -580,7 +588,7 @@ class SDC2_R6_DESC : COP2ST_DESC_BASE<"sdc2", COP2Opnd>; class SWC2_R6_DESC : COP2ST_DESC_BASE<"swc2", COP2Opnd>; class LSA_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - Operand ImmOpnd> { + Operand ImmOpnd> : MipsR6Arch<instr_asm> { dag OutOperandList = (outs GPROpnd:$rd); dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt, ImmOpnd:$imm2); string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt, $imm2"); @@ -610,7 +618,8 @@ class SC_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> { class SC_R6_DESC : SC_R6_DESC_BASE<"sc", GPR32Opnd>; -class CLO_CLZ_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> { +class CLO_CLZ_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> + : MipsR6Arch<instr_asm> { dag OutOperandList = (outs GPROpnd:$rd); dag InOperandList = (ins GPROpnd:$rs); string AsmString = !strconcat(instr_asm, "\t$rd, $rs"); @@ -642,90 +651,90 @@ class SDBBP_R6_DESC { // //===----------------------------------------------------------------------===// -def ADDIUPC : ADDIUPC_ENC, ADDIUPC_DESC, ISA_MIPS32R6; -def ALIGN : ALIGN_ENC, ALIGN_DESC, ISA_MIPS32R6; -def ALUIPC : ALUIPC_ENC, ALUIPC_DESC, ISA_MIPS32R6; -def AUI : AUI_ENC, AUI_DESC, ISA_MIPS32R6; -def AUIPC : AUIPC_ENC, AUIPC_DESC, ISA_MIPS32R6; +def ADDIUPC : R6MMR6Rel, ADDIUPC_ENC, ADDIUPC_DESC, ISA_MIPS32R6; +def ALIGN : R6MMR6Rel, ALIGN_ENC, ALIGN_DESC, ISA_MIPS32R6; +def ALUIPC : R6MMR6Rel, ALUIPC_ENC, ALUIPC_DESC, ISA_MIPS32R6; +def AUI : R6MMR6Rel, AUI_ENC, AUI_DESC, ISA_MIPS32R6; +def AUIPC : R6MMR6Rel, AUIPC_ENC, AUIPC_DESC, ISA_MIPS32R6; def BAL : BAL_ENC, BAL_DESC, ISA_MIPS32R6; -def BALC : BALC_ENC, BALC_DESC, ISA_MIPS32R6; -def BC1EQZ : BC1EQZ_ENC, BC1EQZ_DESC, ISA_MIPS32R6; -def BC1NEZ : BC1NEZ_ENC, BC1NEZ_DESC, ISA_MIPS32R6; +def BALC : R6MMR6Rel, BALC_ENC, BALC_DESC, ISA_MIPS32R6; +def BC1EQZ : BC1EQZ_ENC, BC1EQZ_DESC, ISA_MIPS32R6, HARDFLOAT; +def BC1NEZ : BC1NEZ_ENC, BC1NEZ_DESC, ISA_MIPS32R6, HARDFLOAT; def BC2EQZ : BC2EQZ_ENC, BC2EQZ_DESC, ISA_MIPS32R6; def BC2NEZ : BC2NEZ_ENC, BC2NEZ_DESC, ISA_MIPS32R6; -def BC : BC_ENC, BC_DESC, ISA_MIPS32R6; +def BC : R6MMR6Rel, BC_ENC, BC_DESC, ISA_MIPS32R6; def BEQC : BEQC_ENC, BEQC_DESC, ISA_MIPS32R6; -def BEQZALC : BEQZALC_ENC, BEQZALC_DESC, ISA_MIPS32R6; +def BEQZALC : R6MMR6Rel, BEQZALC_ENC, BEQZALC_DESC, ISA_MIPS32R6; def BEQZC : BEQZC_ENC, BEQZC_DESC, ISA_MIPS32R6; def BGEC : BGEC_ENC, BGEC_DESC, ISA_MIPS32R6; def BGEUC : BGEUC_ENC, BGEUC_DESC, ISA_MIPS32R6; -def BGEZALC : BGEZALC_ENC, BGEZALC_DESC, ISA_MIPS32R6; +def BGEZALC : R6MMR6Rel, BGEZALC_ENC, BGEZALC_DESC, ISA_MIPS32R6; def BGEZC : BGEZC_ENC, BGEZC_DESC, ISA_MIPS32R6; -def BGTZALC : BGTZALC_ENC, BGTZALC_DESC, ISA_MIPS32R6; +def BGTZALC : R6MMR6Rel, BGTZALC_ENC, BGTZALC_DESC, ISA_MIPS32R6; def BGTZC : BGTZC_ENC, BGTZC_DESC, ISA_MIPS32R6; -def BITSWAP : BITSWAP_ENC, BITSWAP_DESC, ISA_MIPS32R6; -def BLEZALC : BLEZALC_ENC, BLEZALC_DESC, ISA_MIPS32R6; +def BITSWAP : R6MMR6Rel, BITSWAP_ENC, BITSWAP_DESC, ISA_MIPS32R6; +def BLEZALC : R6MMR6Rel, BLEZALC_ENC, BLEZALC_DESC, ISA_MIPS32R6; def BLEZC : BLEZC_ENC, BLEZC_DESC, ISA_MIPS32R6; def BLTC : BLTC_ENC, BLTC_DESC, ISA_MIPS32R6; def BLTUC : BLTUC_ENC, BLTUC_DESC, ISA_MIPS32R6; -def BLTZALC : BLTZALC_ENC, BLTZALC_DESC, ISA_MIPS32R6; +def BLTZALC : R6MMR6Rel, BLTZALC_ENC, BLTZALC_DESC, ISA_MIPS32R6; def BLTZC : BLTZC_ENC, BLTZC_DESC, ISA_MIPS32R6; def BNEC : BNEC_ENC, BNEC_DESC, ISA_MIPS32R6; -def BNEZALC : BNEZALC_ENC, BNEZALC_DESC, ISA_MIPS32R6; +def BNEZALC : R6MMR6Rel, BNEZALC_ENC, BNEZALC_DESC, ISA_MIPS32R6; def BNEZC : BNEZC_ENC, BNEZC_DESC, ISA_MIPS32R6; def BNVC : BNVC_ENC, BNVC_DESC, ISA_MIPS32R6; def BOVC : BOVC_ENC, BOVC_DESC, ISA_MIPS32R6; -def CACHE_R6 : CACHE_ENC, CACHE_DESC, ISA_MIPS32R6; -def CLASS_D : CLASS_D_ENC, CLASS_D_DESC, ISA_MIPS32R6; -def CLASS_S : CLASS_S_ENC, CLASS_S_DESC, ISA_MIPS32R6; -def CLO_R6 : CLO_R6_ENC, CLO_R6_DESC, ISA_MIPS32R6; -def CLZ_R6 : CLZ_R6_ENC, CLZ_R6_DESC, ISA_MIPS32R6; +def CACHE_R6 : R6MMR6Rel, CACHE_ENC, CACHE_DESC, ISA_MIPS32R6; +def CLASS_D : CLASS_D_ENC, CLASS_D_DESC, ISA_MIPS32R6, HARDFLOAT; +def CLASS_S : CLASS_S_ENC, CLASS_S_DESC, ISA_MIPS32R6, HARDFLOAT; +def CLO_R6 : R6MMR6Rel, CLO_R6_ENC, CLO_R6_DESC, ISA_MIPS32R6; +def CLZ_R6 : R6MMR6Rel, CLZ_R6_ENC, CLZ_R6_DESC, ISA_MIPS32R6; defm S : CMP_CC_M<FIELD_CMP_FORMAT_S, "s", FGR32Opnd>; defm D : CMP_CC_M<FIELD_CMP_FORMAT_D, "d", FGR64Opnd>; -def DIV : DIV_ENC, DIV_DESC, ISA_MIPS32R6; -def DIVU : DIVU_ENC, DIVU_DESC, ISA_MIPS32R6; -def JIALC : JIALC_ENC, JIALC_DESC, ISA_MIPS32R6; -def JIC : JIC_ENC, JIC_DESC, ISA_MIPS32R6; +def DIV : R6MMR6Rel, DIV_ENC, DIV_DESC, ISA_MIPS32R6; +def DIVU : R6MMR6Rel, DIVU_ENC, DIVU_DESC, ISA_MIPS32R6; +def JIALC : R6MMR6Rel, JIALC_ENC, JIALC_DESC, ISA_MIPS32R6; +def JIC : R6MMR6Rel, JIC_ENC, JIC_DESC, ISA_MIPS32R6; def JR_HB_R6 : JR_HB_R6_ENC, JR_HB_R6_DESC, ISA_MIPS32R6; def LDC2_R6 : LDC2_R6_ENC, LDC2_R6_DESC, ISA_MIPS32R6; def LL_R6 : LL_R6_ENC, LL_R6_DESC, ISA_MIPS32R6; -def LSA_R6 : LSA_R6_ENC, LSA_R6_DESC, ISA_MIPS32R6; +def LSA_R6 : R6MMR6Rel, LSA_R6_ENC, LSA_R6_DESC, ISA_MIPS32R6; def LWC2_R6 : LWC2_R6_ENC, LWC2_R6_DESC, ISA_MIPS32R6; -def LWPC : LWPC_ENC, LWPC_DESC, ISA_MIPS32R6; +def LWPC : R6MMR6Rel, LWPC_ENC, LWPC_DESC, ISA_MIPS32R6; def LWUPC : LWUPC_ENC, LWUPC_DESC, ISA_MIPS32R6; -def MADDF_S : MADDF_S_ENC, MADDF_S_DESC, ISA_MIPS32R6; -def MADDF_D : MADDF_D_ENC, MADDF_D_DESC, ISA_MIPS32R6; -def MAXA_D : MAXA_D_ENC, MAXA_D_DESC, ISA_MIPS32R6; -def MAXA_S : MAXA_S_ENC, MAXA_S_DESC, ISA_MIPS32R6; -def MAX_D : MAX_D_ENC, MAX_D_DESC, ISA_MIPS32R6; -def MAX_S : MAX_S_ENC, MAX_S_DESC, ISA_MIPS32R6; -def MINA_D : MINA_D_ENC, MINA_D_DESC, ISA_MIPS32R6; -def MINA_S : MINA_S_ENC, MINA_S_DESC, ISA_MIPS32R6; -def MIN_D : MIN_D_ENC, MIN_D_DESC, ISA_MIPS32R6; -def MIN_S : MIN_S_ENC, MIN_S_DESC, ISA_MIPS32R6; -def MOD : MOD_ENC, MOD_DESC, ISA_MIPS32R6; -def MODU : MODU_ENC, MODU_DESC, ISA_MIPS32R6; -def MSUBF_S : MSUBF_S_ENC, MSUBF_S_DESC, ISA_MIPS32R6; -def MSUBF_D : MSUBF_D_ENC, MSUBF_D_DESC, ISA_MIPS32R6; -def MUH : MUH_ENC, MUH_DESC, ISA_MIPS32R6; -def MUHU : MUHU_ENC, MUHU_DESC, ISA_MIPS32R6; -def MUL_R6 : MUL_R6_ENC, MUL_R6_DESC, ISA_MIPS32R6; -def MULU : MULU_ENC, MULU_DESC, ISA_MIPS32R6; +def MADDF_S : MADDF_S_ENC, MADDF_S_DESC, ISA_MIPS32R6, HARDFLOAT; +def MADDF_D : MADDF_D_ENC, MADDF_D_DESC, ISA_MIPS32R6, HARDFLOAT; +def MAXA_D : MAXA_D_ENC, MAXA_D_DESC, ISA_MIPS32R6, HARDFLOAT; +def MAXA_S : MAXA_S_ENC, MAXA_S_DESC, ISA_MIPS32R6, HARDFLOAT; +def MAX_D : MAX_D_ENC, MAX_D_DESC, ISA_MIPS32R6, HARDFLOAT; +def MAX_S : MAX_S_ENC, MAX_S_DESC, ISA_MIPS32R6, HARDFLOAT; +def MINA_D : MINA_D_ENC, MINA_D_DESC, ISA_MIPS32R6, HARDFLOAT; +def MINA_S : MINA_S_ENC, MINA_S_DESC, ISA_MIPS32R6, HARDFLOAT; +def MIN_D : MIN_D_ENC, MIN_D_DESC, ISA_MIPS32R6, HARDFLOAT; +def MIN_S : MIN_S_ENC, MIN_S_DESC, ISA_MIPS32R6, HARDFLOAT; +def MOD : R6MMR6Rel, MOD_ENC, MOD_DESC, ISA_MIPS32R6; +def MODU : R6MMR6Rel, MODU_ENC, MODU_DESC, ISA_MIPS32R6; +def MSUBF_S : MSUBF_S_ENC, MSUBF_S_DESC, ISA_MIPS32R6, HARDFLOAT; +def MSUBF_D : MSUBF_D_ENC, MSUBF_D_DESC, ISA_MIPS32R6, HARDFLOAT; +def MUH : R6MMR6Rel, MUH_ENC, MUH_DESC, ISA_MIPS32R6; +def MUHU : R6MMR6Rel, MUHU_ENC, MUHU_DESC, ISA_MIPS32R6; +def MUL_R6 : R6MMR6Rel, MUL_R6_ENC, MUL_R6_DESC, ISA_MIPS32R6; +def MULU : R6MMR6Rel, MULU_ENC, MULU_DESC, ISA_MIPS32R6; def NAL; // BAL with rd=0 -def PREF_R6 : PREF_ENC, PREF_DESC, ISA_MIPS32R6; -def RINT_D : RINT_D_ENC, RINT_D_DESC, ISA_MIPS32R6; -def RINT_S : RINT_S_ENC, RINT_S_DESC, ISA_MIPS32R6; +def PREF_R6 : R6MMR6Rel, PREF_ENC, PREF_DESC, ISA_MIPS32R6; +def RINT_D : RINT_D_ENC, RINT_D_DESC, ISA_MIPS32R6, HARDFLOAT; +def RINT_S : RINT_S_ENC, RINT_S_DESC, ISA_MIPS32R6, HARDFLOAT; def SC_R6 : SC_R6_ENC, SC_R6_DESC, ISA_MIPS32R6; def SDBBP_R6 : SDBBP_R6_ENC, SDBBP_R6_DESC, ISA_MIPS32R6; def SDC2_R6 : SDC2_R6_ENC, SDC2_R6_DESC, ISA_MIPS32R6; -def SELEQZ : SELEQZ_ENC, SELEQZ_DESC, ISA_MIPS32R6, GPR_32; -def SELEQZ_D : SELEQZ_D_ENC, SELEQZ_D_DESC, ISA_MIPS32R6; -def SELEQZ_S : SELEQZ_S_ENC, SELEQZ_S_DESC, ISA_MIPS32R6; -def SELNEZ : SELNEZ_ENC, SELNEZ_DESC, ISA_MIPS32R6, GPR_32; -def SELNEZ_D : SELNEZ_D_ENC, SELNEZ_D_DESC, ISA_MIPS32R6; -def SELNEZ_S : SELNEZ_S_ENC, SELNEZ_S_DESC, ISA_MIPS32R6; -def SEL_D : SEL_D_ENC, SEL_D_DESC, ISA_MIPS32R6; -def SEL_S : SEL_S_ENC, SEL_S_DESC, ISA_MIPS32R6; +def SELEQZ : R6MMR6Rel, SELEQZ_ENC, SELEQZ_DESC, ISA_MIPS32R6, GPR_32; +def SELEQZ_D : SELEQZ_D_ENC, SELEQZ_D_DESC, ISA_MIPS32R6, HARDFLOAT; +def SELEQZ_S : SELEQZ_S_ENC, SELEQZ_S_DESC, ISA_MIPS32R6, HARDFLOAT; +def SELNEZ : R6MMR6Rel, SELNEZ_ENC, SELNEZ_DESC, ISA_MIPS32R6, GPR_32; +def SELNEZ_D : SELNEZ_D_ENC, SELNEZ_D_DESC, ISA_MIPS32R6, HARDFLOAT; +def SELNEZ_S : SELNEZ_S_ENC, SELNEZ_S_DESC, ISA_MIPS32R6, HARDFLOAT; +def SEL_D : SEL_D_ENC, SEL_D_DESC, ISA_MIPS32R6, HARDFLOAT; +def SEL_S : SEL_S_ENC, SEL_S_DESC, ISA_MIPS32R6, HARDFLOAT; def SWC2_R6 : SWC2_R6_ENC, SWC2_R6_DESC, ISA_MIPS32R6; //===----------------------------------------------------------------------===// diff --git a/contrib/llvm/lib/Target/Mips/Mips64InstrInfo.td b/contrib/llvm/lib/Target/Mips/Mips64InstrInfo.td index d6628d4..8a27874 100644 --- a/contrib/llvm/lib/Target/Mips/Mips64InstrInfo.td +++ b/contrib/llvm/lib/Target/Mips/Mips64InstrInfo.td @@ -16,6 +16,10 @@ //===----------------------------------------------------------------------===// // Unsigned Operand +def uimm5_64 : Operand<i64> { + let PrintMethod = "printUnsignedImm"; +} + def uimm16_64 : Operand<i64> { let PrintMethod = "printUnsignedImm"; } @@ -41,6 +45,38 @@ def immSExt10_64 : PatLeaf<(i64 imm), def immZExt16_64 : PatLeaf<(i64 imm), [{ return isInt<16>(N->getZExtValue()); }]>; +def immZExt5_64 : ImmLeaf<i64, [{ return Imm == (Imm & 0x1f); }]>; + +// Transformation function: get log2 of low 32 bits of immediate +def Log2LO : SDNodeXForm<imm, [{ + return getImm(N, Log2_64((unsigned) N->getZExtValue())); +}]>; + +// Transformation function: get log2 of high 32 bits of immediate +def Log2HI : SDNodeXForm<imm, [{ + return getImm(N, Log2_64((unsigned) (N->getZExtValue() >> 32))); +}]>; + +// Predicate: True if immediate is a power of 2 and fits 32 bits +def PowerOf2LO : PatLeaf<(imm), [{ + if (N->getValueType(0) == MVT::i64) { + uint64_t Imm = N->getZExtValue(); + return isPowerOf2_64(Imm) && (Imm & 0xffffffff) == Imm; + } + else + return false; +}]>; + +// Predicate: True if immediate is a power of 2 and exceeds 32 bits +def PowerOf2HI : PatLeaf<(imm), [{ + if (N->getValueType(0) == MVT::i64) { + uint64_t Imm = N->getZExtValue(); + return isPowerOf2_64(Imm) && (Imm & 0xffffffff00000000) == Imm; + } + else + return false; +}]>; + //===----------------------------------------------------------------------===// // Instructions specific format //===----------------------------------------------------------------------===// @@ -269,8 +305,9 @@ let isCodeGenOnly = 1, rs = 0, shamt = 0 in { def LONG_BRANCH_DADDiu : PseudoSE<(outs GPR64Opnd:$dst), (ins GPR64Opnd:$src, brtarget:$tgt, brtarget:$baltgt), []>; -// Cavium Octeon cmMIPS instructions -let EncodingPredicates = []<Predicate>, // FIXME: The lack of HasStdEnc is probably a bug +// Cavium Octeon cnMIPS instructions +let DecoderNamespace = "CnMips", + EncodingPredicates = []<Predicate>, // FIXME: The lack of HasStdEnc is probably a bug AdditionalPredicates = [HasCnMips] in { class Count1s<string opstr, RegisterOperand RO>: @@ -305,12 +342,38 @@ class SetCC64_I<string opstr, PatFrag cond_op>: let TwoOperandAliasConstraint = "$rt = $rs"; } +class CBranchBitNum<string opstr, DAGOperand opnd, PatFrag cond_op, + RegisterOperand RO, bits<64> shift = 1> : + InstSE<(outs), (ins RO:$rs, uimm5_64:$p, opnd:$offset), + !strconcat(opstr, "\t$rs, $p, $offset"), + [(brcond (i32 (cond_op (and RO:$rs, (shl shift, immZExt5_64:$p)), 0)), + bb:$offset)], IIBranch, FrmI, opstr> { + let isBranch = 1; + let isTerminator = 1; + let hasDelaySlot = 1; + let Defs = [AT]; +} + +class MFC2OP<string asmstr, RegisterOperand RO> : + InstSE<(outs RO:$rt, uimm16:$imm16), (ins), + !strconcat(asmstr, "\t$rt, $imm16"), [], NoItinerary, FrmFR>; + // Unsigned Byte Add let Pattern = [(set GPR64Opnd:$rd, (and (add GPR64Opnd:$rs, GPR64Opnd:$rt), 255))] in def BADDu : ArithLogicR<"baddu", GPR64Opnd, 1, II_BADDU>, ADD_FM<0x1c, 0x28>; +// Branch on Bit Clear /+32 +def BBIT0 : CBranchBitNum<"bbit0", brtarget, seteq, GPR64Opnd>, BBIT_FM<0x32>; +def BBIT032: CBranchBitNum<"bbit032", brtarget, seteq, GPR64Opnd, 0x100000000>, + BBIT_FM<0x36>; + +// Branch on Bit Set /+32 +def BBIT1 : CBranchBitNum<"bbit1", brtarget, setne, GPR64Opnd>, BBIT_FM<0x3a>; +def BBIT132: CBranchBitNum<"bbit132", brtarget, setne, GPR64Opnd, 0x100000000>, + BBIT_FM<0x3e>; + // Multiply Doubleword to GPR let Defs = [HI0, LO0, P0, P1, P2] in def DMUL : ArithLogicR<"dmul", GPR64Opnd, 1, II_DMUL, mul>, @@ -357,8 +420,19 @@ let Defs = [MPL1, MPL2, P0, P1, P2] in def VMULU : ArithLogicR<"vmulu", GPR64Opnd, 0, II_DMUL>, ADD_FM<0x1c, 0x0f>; +// Move between CPU and coprocessor registers +def DMFC2_OCTEON : MFC2OP<"dmfc2", GPR64Opnd>, MFC2OP_FM<0x12, 1>; +def DMTC2_OCTEON : MFC2OP<"dmtc2", GPR64Opnd>, MFC2OP_FM<0x12, 5>; +} + } +/// Move between CPU and coprocessor registers +let DecoderNamespace = "Mips64", Predicates = [HasMips64] in { +def DMFC0 : MFC3OP<"dmfc0", GPR64Opnd>, MFC3OP_FM<0x10, 1>; +def DMTC0 : MFC3OP<"dmtc0", GPR64Opnd>, MFC3OP_FM<0x10, 5>, ISA_MIPS3; +def DMFC2 : MFC3OP<"dmfc2", GPR64Opnd>, MFC3OP_FM<0x12, 1>, ISA_MIPS3; +def DMTC2 : MFC3OP<"dmtc2", GPR64Opnd>, MFC3OP_FM<0x12, 5>, ISA_MIPS3; } //===----------------------------------------------------------------------===// @@ -428,6 +502,24 @@ def : MipsPat<(trunc (assertzext GPR64:$src)), def : MipsPat<(i32 (trunc GPR64:$src)), (SLL (EXTRACT_SUBREG GPR64:$src, sub_32), 0)>; +// Bypass trunc nodes for bitwise ops. +def : MipsPat<(i32 (trunc (and GPR64:$lhs, GPR64:$rhs))), + (EXTRACT_SUBREG (AND64 GPR64:$lhs, GPR64:$rhs), sub_32)>; +def : MipsPat<(i32 (trunc (or GPR64:$lhs, GPR64:$rhs))), + (EXTRACT_SUBREG (OR64 GPR64:$lhs, GPR64:$rhs), sub_32)>; +def : MipsPat<(i32 (trunc (xor GPR64:$lhs, GPR64:$rhs))), + (EXTRACT_SUBREG (XOR64 GPR64:$lhs, GPR64:$rhs), sub_32)>; + +// variable shift instructions patterns +def : MipsPat<(shl GPR64:$rt, (i32 (trunc GPR64:$rs))), + (DSLLV GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>; +def : MipsPat<(srl GPR64:$rt, (i32 (trunc GPR64:$rs))), + (DSRLV GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>; +def : MipsPat<(sra GPR64:$rt, (i32 (trunc GPR64:$rs))), + (DSRAV GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>; +def : MipsPat<(rotr GPR64:$rt, (i32 (trunc GPR64:$rs))), + (DROTRV GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>; + // 32-to-64-bit extension def : MipsPat<(i64 (anyext GPR32:$src)), (SLL64_32 GPR32:$src)>; def : MipsPat<(i64 (zext GPR32:$src)), (DSRL (DSLL64_32 GPR32:$src), 32)>; @@ -450,6 +542,18 @@ let AdditionalPredicates = [NotDSP] in { (DADDiu GPR64:$lhs, imm:$imm)>; } +// Octeon bbit0/bbit1 MipsPattern +let Predicates = [HasMips64, HasCnMips] in { +def : MipsPat<(brcond (i32 (seteq (and i64:$lhs, PowerOf2LO:$mask), 0)), bb:$dst), + (BBIT0 i64:$lhs, (Log2LO PowerOf2LO:$mask), bb:$dst)>; +def : MipsPat<(brcond (i32 (seteq (and i64:$lhs, PowerOf2HI:$mask), 0)), bb:$dst), + (BBIT032 i64:$lhs, (Log2HI PowerOf2HI:$mask), bb:$dst)>; +def : MipsPat<(brcond (i32 (setne (and i64:$lhs, PowerOf2LO:$mask), 0)), bb:$dst), + (BBIT1 i64:$lhs, (Log2LO PowerOf2LO:$mask), bb:$dst)>; +def : MipsPat<(brcond (i32 (setne (and i64:$lhs, PowerOf2HI:$mask), 0)), bb:$dst), + (BBIT132 i64:$lhs, (Log2HI PowerOf2HI:$mask), bb:$dst)>; +} + //===----------------------------------------------------------------------===// // Instruction aliases //===----------------------------------------------------------------------===// @@ -471,6 +575,15 @@ def : MipsInstAlias<"dadd $rs, $imm", def : MipsInstAlias<"dsll $rd, $rt, $rs", (DSLLV GPR64Opnd:$rd, GPR64Opnd:$rt, GPR32Opnd:$rs), 0>, ISA_MIPS3; +def : MipsInstAlias<"dneg $rt, $rs", + (DSUB GPR64Opnd:$rt, ZERO_64, GPR64Opnd:$rs), 1>, + ISA_MIPS3; +def : MipsInstAlias<"dneg $rt", + (DSUB GPR64Opnd:$rt, ZERO_64, GPR64Opnd:$rt), 0>, + ISA_MIPS3; +def : MipsInstAlias<"dnegu $rt, $rs", + (DSUBu GPR64Opnd:$rt, ZERO_64, GPR64Opnd:$rs), 1>, + ISA_MIPS3; def : MipsInstAlias<"dsubu $rt, $rs, $imm", (DADDiu GPR64Opnd:$rt, GPR64Opnd:$rs, InvertedImOperand64:$imm), 0>, ISA_MIPS3; @@ -501,19 +614,6 @@ def : MipsInstAlias<"dsrl $rd, $rt, $rs", (DSRLV GPR64Opnd:$rd, GPR64Opnd:$rt, GPR32Opnd:$rs), 0>, ISA_MIPS3; -class LoadImm64< string instr_asm, Operand Od, RegisterOperand RO> : - MipsAsmPseudoInst<(outs RO:$rt), (ins Od:$imm64), - !strconcat(instr_asm, "\t$rt, $imm64")> ; -def LoadImm64Reg : LoadImm64<"dli", imm64, GPR64Opnd>; - -/// Move between CPU and coprocessor registers -let DecoderNamespace = "Mips64", Predicates = [HasMips64] in { -def DMFC0 : MFC3OP<"dmfc0", GPR64Opnd>, MFC3OP_FM<0x10, 1>; -def DMTC0 : MFC3OP<"dmtc0", GPR64Opnd>, MFC3OP_FM<0x10, 5>, ISA_MIPS3; -def DMFC2 : MFC3OP<"dmfc2", GPR64Opnd>, MFC3OP_FM<0x12, 1>, ISA_MIPS3; -def DMTC2 : MFC3OP<"dmtc2", GPR64Opnd>, MFC3OP_FM<0x12, 5>, ISA_MIPS3; -} - // Two operand (implicit 0 selector) versions: def : MipsInstAlias<"dmfc0 $rt, $rd", (DMFC0 GPR64Opnd:$rt, GPR64Opnd:$rd, 0), 0>; def : MipsInstAlias<"dmtc0 $rt, $rd", (DMTC0 GPR64Opnd:$rt, GPR64Opnd:$rd, 0), 0>; @@ -526,3 +626,12 @@ def : MipsInstAlias<"syncs", (SYNC 0x6), 0>; def : MipsInstAlias<"syncw", (SYNC 0x4), 0>; def : MipsInstAlias<"syncws", (SYNC 0x5), 0>; } + +//===----------------------------------------------------------------------===// +// Assembler Pseudo Instructions +//===----------------------------------------------------------------------===// + +class LoadImmediate64<string instr_asm, Operand Od, RegisterOperand RO> : + MipsAsmPseudoInst<(outs RO:$rt), (ins Od:$imm64), + !strconcat(instr_asm, "\t$rt, $imm64")> ; +def LoadImm64 : LoadImmediate64<"dli", imm64, GPR64Opnd>; diff --git a/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.cpp b/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.cpp index 50c0441..f84666b 100644 --- a/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.cpp @@ -19,9 +19,9 @@ #include "MipsAsmPrinter.h" #include "MipsInstrInfo.h" #include "MipsMCInstLower.h" +#include "MipsTargetMachine.h" #include "MipsTargetStreamer.h" #include "llvm/ADT/SmallString.h" -#include "llvm/ADT/StringExtras.h" #include "llvm/ADT/Twine.h" #include "llvm/CodeGen/MachineConstantPool.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -41,7 +41,7 @@ #include "llvm/MC/MCInst.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCSectionELF.h" -#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/MCSymbolELF.h" #include "llvm/Support/ELF.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" @@ -54,11 +54,11 @@ using namespace llvm; #define DEBUG_TYPE "mips-asm-printer" MipsTargetStreamer &MipsAsmPrinter::getTargetStreamer() const { - return static_cast<MipsTargetStreamer &>(*OutStreamer.getTargetStreamer()); + return static_cast<MipsTargetStreamer &>(*OutStreamer->getTargetStreamer()); } bool MipsAsmPrinter::runOnMachineFunction(MachineFunction &MF) { - Subtarget = &TM.getSubtarget<MipsSubtarget>(); + Subtarget = &MF.getSubtarget<MipsSubtarget>(); // Initialize TargetLoweringObjectFile. const_cast<TargetLoweringObjectFile &>(getObjFileLowering()) @@ -120,7 +120,7 @@ void MipsAsmPrinter::emitPseudoIndirectBranch(MCStreamer &OutStreamer, if (HasLinkReg) { unsigned ZeroReg = Subtarget->isGP64bit() ? Mips::ZERO_64 : Mips::ZERO; - TmpInst0.addOperand(MCOperand::CreateReg(ZeroReg)); + TmpInst0.addOperand(MCOperand::createReg(ZeroReg)); } lowerOperand(MI->getOperand(0), MCOp); @@ -143,7 +143,7 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { // If we just ended a constant pool, mark it as such. if (InConstantPool && MI->getOpcode() != Mips::CONSTPOOL_ENTRY) { - OutStreamer.EmitDataRegion(MCDR_DataRegionEnd); + OutStreamer->EmitDataRegion(MCDR_DataRegionEnd); InConstantPool = false; } if (MI->getOpcode() == Mips::CONSTPOOL_ENTRY) { @@ -159,11 +159,11 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { // If this is the first entry of the pool, mark it. if (!InConstantPool) { - OutStreamer.EmitDataRegion(MCDR_DataRegion); + OutStreamer->EmitDataRegion(MCDR_DataRegion); InConstantPool = true; } - OutStreamer.EmitLabel(GetCPISymbol(LabelId)); + OutStreamer->EmitLabel(GetCPISymbol(LabelId)); const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx]; if (MCPE.isMachineConstantPoolEntry()) @@ -179,14 +179,14 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { do { // Do any auto-generated pseudo lowerings. - if (emitPseudoExpansionLowering(OutStreamer, &*I)) + if (emitPseudoExpansionLowering(*OutStreamer, &*I)) continue; if (I->getOpcode() == Mips::PseudoReturn || I->getOpcode() == Mips::PseudoReturn64 || I->getOpcode() == Mips::PseudoIndirectBranch || I->getOpcode() == Mips::PseudoIndirectBranch64) { - emitPseudoIndirectBranch(OutStreamer, &*I); + emitPseudoIndirectBranch(*OutStreamer, &*I); continue; } @@ -203,7 +203,7 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { MCInst TmpInst0; MCInstLowering.Lower(I, TmpInst0); - EmitToStreamer(OutStreamer, TmpInst0); + EmitToStreamer(*OutStreamer, TmpInst0); } while ((++I != E) && I->isInsideBundle()); // Delay slot check } @@ -251,6 +251,7 @@ void MipsAsmPrinter::printSavedRegsBitmask() { // Set the CPU and FPU Bitmasks const MachineFrameInfo *MFI = MF->getFrameInfo(); + const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); // size of stack area to which FP callee-saved regs are saved. unsigned CPURegSize = Mips::GPR32RegClass.getSize(); @@ -258,33 +259,22 @@ void MipsAsmPrinter::printSavedRegsBitmask() { unsigned AFGR64RegSize = Mips::AFGR64RegClass.getSize(); bool HasAFGR64Reg = false; unsigned CSFPRegsSize = 0; - unsigned i, e = CSI.size(); - // Set FPU Bitmask. - for (i = 0; i != e; ++i) { - unsigned Reg = CSI[i].getReg(); - if (Mips::GPR32RegClass.contains(Reg)) - break; + for (const auto &I : CSI) { + unsigned Reg = I.getReg(); + unsigned RegNum = TRI->getEncodingValue(Reg); - unsigned RegNum = - TM.getSubtargetImpl()->getRegisterInfo()->getEncodingValue(Reg); - if (Mips::AFGR64RegClass.contains(Reg)) { + // If it's a floating point register, set the FPU Bitmask. + // If it's a general purpose register, set the CPU Bitmask. + if (Mips::FGR32RegClass.contains(Reg)) { + FPUBitmask |= (1 << RegNum); + CSFPRegsSize += FGR32RegSize; + } else if (Mips::AFGR64RegClass.contains(Reg)) { FPUBitmask |= (3 << RegNum); CSFPRegsSize += AFGR64RegSize; HasAFGR64Reg = true; - continue; - } - - FPUBitmask |= (1 << RegNum); - CSFPRegsSize += FGR32RegSize; - } - - // Set CPU Bitmask. - for (; i != e; ++i) { - unsigned Reg = CSI[i].getReg(); - unsigned RegNum = - TM.getSubtargetImpl()->getRegisterInfo()->getEncodingValue(Reg); - CPUBitmask |= (1 << RegNum); + } else if (Mips::GPR32RegClass.contains(Reg)) + CPUBitmask |= (1 << RegNum); } // FP Regs are saved right below where the virtual frame pointer points to. @@ -308,7 +298,7 @@ void MipsAsmPrinter::printSavedRegsBitmask() { /// Frame Directive void MipsAsmPrinter::emitFrameDirective() { - const TargetRegisterInfo &RI = *TM.getSubtargetImpl()->getRegisterInfo(); + const TargetRegisterInfo &RI = *MF->getSubtarget().getRegisterInfo(); unsigned stackReg = RI.getFrameRegister(*MF); unsigned returnReg = RI.getRARegister(); @@ -319,7 +309,7 @@ void MipsAsmPrinter::emitFrameDirective() { /// Emit Set directives. const char *MipsAsmPrinter::getCurrentABIString() const { - switch (Subtarget->getABI().GetEnumValue()) { + switch (static_cast<MipsTargetMachine &>(TM).getABI().GetEnumValue()) { case MipsABIInfo::ABI::O32: return "abi32"; case MipsABIInfo::ABI::N32: return "abiN32"; case MipsABIInfo::ABI::N64: return "abi64"; @@ -347,7 +337,7 @@ void MipsAsmPrinter::EmitFunctionEntryLabel() { TS.emitDirectiveSetNoMips16(); TS.emitDirectiveEnt(*CurrentFnSym); - OutStreamer.EmitLabel(CurrentFnSym); + OutStreamer->EmitLabel(CurrentFnSym); } /// EmitFunctionBodyStart - Targets can override this to emit stuff before @@ -357,10 +347,7 @@ void MipsAsmPrinter::EmitFunctionBodyStart() { MCInstLowering.Initialize(&MF->getContext()); - bool IsNakedFunction = - MF->getFunction()-> - getAttributes().hasAttribute(AttributeSet::FunctionIndex, - Attribute::Naked); + bool IsNakedFunction = MF->getFunction()->hasFnAttribute(Attribute::Naked); if (!IsNakedFunction) emitFrameDirective(); @@ -393,7 +380,13 @@ void MipsAsmPrinter::EmitFunctionBodyEnd() { if (!InConstantPool) return; InConstantPool = false; - OutStreamer.EmitDataRegion(MCDR_DataRegionEnd); + OutStreamer->EmitDataRegion(MCDR_DataRegionEnd); +} + +void MipsAsmPrinter::EmitBasicBlockEnd(const MachineBasicBlock &MBB) { + MipsTargetStreamer &TS = getTargetStreamer(); + if (MBB.size() == 0) + TS.emitDirectiveInsn(); } /// isBlockOnlyReachableByFallthough - Return true if the basic block has @@ -440,7 +433,7 @@ bool MipsAsmPrinter::isBlockOnlyReachableByFallthrough(const MachineBasicBlock* // Print out an operand for an inline asm expression. bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, - unsigned AsmVariant,const char *ExtraCode, + unsigned AsmVariant, const char *ExtraCode, raw_ostream &O) { // Does this asm operand have a single letter operand modifier? if (ExtraCode && ExtraCode[0]) { @@ -454,12 +447,12 @@ bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, case 'X': // hex const int if ((MO.getType()) != MachineOperand::MO_Immediate) return true; - O << "0x" << StringRef(utohexstr(MO.getImm())).lower(); + O << "0x" << Twine::utohexstr(MO.getImm()); return false; case 'x': // hex const int (low 16 bits) if ((MO.getType()) != MachineOperand::MO_Immediate) return true; - O << "0x" << StringRef(utohexstr(MO.getImm() & 0xffff)).lower(); + O << "0x" << Twine::utohexstr(MO.getImm() & 0xffff); return false; case 'd': // decimal const int if ((MO.getType()) != MachineOperand::MO_Immediate) @@ -542,25 +535,31 @@ bool MipsAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, unsigned AsmVariant, const char *ExtraCode, raw_ostream &O) { - int Offset = 0; + assert(OpNum + 1 < MI->getNumOperands() && "Insufficient operands"); + const MachineOperand &BaseMO = MI->getOperand(OpNum); + const MachineOperand &OffsetMO = MI->getOperand(OpNum + 1); + assert(BaseMO.isReg() && "Unexpected base pointer for inline asm memory operand."); + assert(OffsetMO.isImm() && "Unexpected offset for inline asm memory operand."); + int Offset = OffsetMO.getImm(); + // Currently we are expecting either no ExtraCode or 'D' if (ExtraCode) { if (ExtraCode[0] == 'D') - Offset = 4; + Offset += 4; else return true; // Unknown modifier. + // FIXME: M = high order bits + // FIXME: L = low order bits } - const MachineOperand &MO = MI->getOperand(OpNum); - assert(MO.isReg() && "unexpected inline asm memory operand"); - O << Offset << "($" << MipsInstPrinter::getRegisterName(MO.getReg()) << ")"; + O << Offset << "($" << MipsInstPrinter::getRegisterName(BaseMO.getReg()) << ")"; return false; } void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum, raw_ostream &O) { - const DataLayout *DL = TM.getSubtargetImpl()->getDataLayout(); + const DataLayout *DL = TM.getDataLayout(); const MachineOperand &MO = MI->getOperand(opNum); bool closeP = false; @@ -595,11 +594,11 @@ void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum, break; case MachineOperand::MO_MachineBasicBlock: - O << *MO.getMBB()->getSymbol(); + MO.getMBB()->getSymbol()->print(O, MAI); return; case MachineOperand::MO_GlobalAddress: - O << *getSymbol(MO.getGlobal()); + getSymbol(MO.getGlobal())->print(O, MAI); break; case MachineOperand::MO_BlockAddress: { @@ -689,7 +688,21 @@ printRegisterList(const MachineInstr *MI, int opNum, raw_ostream &O) { } void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { - bool IsABICalls = Subtarget->isABICalls(); + + // Compute MIPS architecture attributes based on the default subtarget + // that we'd have constructed. Module level directives aren't LTO + // clean anyhow. + // FIXME: For ifunc related functions we could iterate over and look + // for a feature string that doesn't match the default one. + StringRef TT = TM.getTargetTriple(); + StringRef CPU = + MIPS_MC::selectMipsCPU(TM.getTargetTriple(), TM.getTargetCPU()); + StringRef FS = TM.getTargetFeatureString(); + const MipsTargetMachine &MTM = static_cast<const MipsTargetMachine &>(TM); + const MipsSubtarget STI(TT, CPU, FS, MTM.isLittleEndian(), MTM); + + bool IsABICalls = STI.isABICalls(); + const MipsABIInfo &ABI = MTM.getABI(); if (IsABICalls) { getTargetStreamer().emitDirectiveAbiCalls(); Reloc::Model RM = TM.getRelocationModel(); @@ -697,54 +710,49 @@ void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { // Ideally it should test for properties of the ABI and not the ABI // itself. // For the moment, I'm only correcting enough to make MIPS-IV work. - if (RM == Reloc::Static && !Subtarget->isABI_N64()) + if (RM == Reloc::Static && !ABI.IsN64()) getTargetStreamer().emitDirectiveOptionPic0(); } // Tell the assembler which ABI we are using std::string SectionName = std::string(".mdebug.") + getCurrentABIString(); - OutStreamer.SwitchSection(OutContext.getELFSection( - SectionName, ELF::SHT_PROGBITS, 0, SectionKind::getDataRel())); + OutStreamer->SwitchSection( + OutContext.getELFSection(SectionName, ELF::SHT_PROGBITS, 0)); // NaN: At the moment we only support: // 1. .nan legacy (default) // 2. .nan 2008 - Subtarget->isNaN2008() ? getTargetStreamer().emitDirectiveNaN2008() - : getTargetStreamer().emitDirectiveNaNLegacy(); + STI.isNaN2008() ? getTargetStreamer().emitDirectiveNaN2008() + : getTargetStreamer().emitDirectiveNaNLegacy(); // TODO: handle O64 ABI - if (Subtarget->isABI_EABI()) { - if (Subtarget->isGP32bit()) - OutStreamer.SwitchSection( - OutContext.getELFSection(".gcc_compiled_long32", ELF::SHT_PROGBITS, 0, - SectionKind::getDataRel())); + if (ABI.IsEABI()) { + if (STI.isGP32bit()) + OutStreamer->SwitchSection(OutContext.getELFSection(".gcc_compiled_long32", + ELF::SHT_PROGBITS, 0)); else - OutStreamer.SwitchSection( - OutContext.getELFSection(".gcc_compiled_long64", ELF::SHT_PROGBITS, 0, - SectionKind::getDataRel())); + OutStreamer->SwitchSection(OutContext.getELFSection(".gcc_compiled_long64", + ELF::SHT_PROGBITS, 0)); } - getTargetStreamer().updateABIInfo(*Subtarget); + getTargetStreamer().updateABIInfo(STI); // We should always emit a '.module fp=...' but binutils 2.24 does not accept // it. We therefore emit it when it contradicts the ABI defaults (-mfpxx or // -mfp64) and omit it otherwise. - if (Subtarget->isABI_O32() && (Subtarget->isABI_FPXX() || - Subtarget->isFP64bit())) + if (ABI.IsO32() && (STI.isABI_FPXX() || STI.isFP64bit())) getTargetStreamer().emitDirectiveModuleFP(); // We should always emit a '.module [no]oddspreg' but binutils 2.24 does not // accept it. We therefore emit it when it contradicts the default or an // option has changed the default (i.e. FPXX) and omit it otherwise. - if (Subtarget->isABI_O32() && (!Subtarget->useOddSPReg() || - Subtarget->isABI_FPXX())) - getTargetStreamer().emitDirectiveModuleOddSPReg(Subtarget->useOddSPReg(), - Subtarget->isABI_O32()); + if (ABI.IsO32() && (!STI.useOddSPReg() || STI.isABI_FPXX())) + getTargetStreamer().emitDirectiveModuleOddSPReg(STI.useOddSPReg(), + ABI.IsO32()); } -void MipsAsmPrinter::emitInlineAsmStart( - const MCSubtargetInfo &StartInfo) const { +void MipsAsmPrinter::emitInlineAsmStart() const { MipsTargetStreamer &TS = getTargetStreamer(); // GCC's choice of assembler options for inline assembly code ('at', 'macro' @@ -757,31 +765,33 @@ void MipsAsmPrinter::emitInlineAsmStart( TS.emitDirectiveSetAt(); TS.emitDirectiveSetMacro(); TS.emitDirectiveSetReorder(); - OutStreamer.AddBlankLine(); + OutStreamer->AddBlankLine(); } void MipsAsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo, const MCSubtargetInfo *EndInfo) const { - OutStreamer.AddBlankLine(); + OutStreamer->AddBlankLine(); getTargetStreamer().emitDirectiveSetPop(); } -void MipsAsmPrinter::EmitJal(MCSymbol *Symbol) { +void MipsAsmPrinter::EmitJal(const MCSubtargetInfo &STI, MCSymbol *Symbol) { MCInst I; I.setOpcode(Mips::JAL); I.addOperand( - MCOperand::CreateExpr(MCSymbolRefExpr::Create(Symbol, OutContext))); - OutStreamer.EmitInstruction(I, getSubtargetInfo()); + MCOperand::createExpr(MCSymbolRefExpr::create(Symbol, OutContext))); + OutStreamer->EmitInstruction(I, STI); } -void MipsAsmPrinter::EmitInstrReg(unsigned Opcode, unsigned Reg) { +void MipsAsmPrinter::EmitInstrReg(const MCSubtargetInfo &STI, unsigned Opcode, + unsigned Reg) { MCInst I; I.setOpcode(Opcode); - I.addOperand(MCOperand::CreateReg(Reg)); - OutStreamer.EmitInstruction(I, getSubtargetInfo()); + I.addOperand(MCOperand::createReg(Reg)); + OutStreamer->EmitInstruction(I, STI); } -void MipsAsmPrinter::EmitInstrRegReg(unsigned Opcode, unsigned Reg1, +void MipsAsmPrinter::EmitInstrRegReg(const MCSubtargetInfo &STI, + unsigned Opcode, unsigned Reg1, unsigned Reg2) { MCInst I; // @@ -795,22 +805,24 @@ void MipsAsmPrinter::EmitInstrRegReg(unsigned Opcode, unsigned Reg1, Reg2 = Temp; } I.setOpcode(Opcode); - I.addOperand(MCOperand::CreateReg(Reg1)); - I.addOperand(MCOperand::CreateReg(Reg2)); - OutStreamer.EmitInstruction(I, getSubtargetInfo()); + I.addOperand(MCOperand::createReg(Reg1)); + I.addOperand(MCOperand::createReg(Reg2)); + OutStreamer->EmitInstruction(I, STI); } -void MipsAsmPrinter::EmitInstrRegRegReg(unsigned Opcode, unsigned Reg1, +void MipsAsmPrinter::EmitInstrRegRegReg(const MCSubtargetInfo &STI, + unsigned Opcode, unsigned Reg1, unsigned Reg2, unsigned Reg3) { MCInst I; I.setOpcode(Opcode); - I.addOperand(MCOperand::CreateReg(Reg1)); - I.addOperand(MCOperand::CreateReg(Reg2)); - I.addOperand(MCOperand::CreateReg(Reg3)); - OutStreamer.EmitInstruction(I, getSubtargetInfo()); + I.addOperand(MCOperand::createReg(Reg1)); + I.addOperand(MCOperand::createReg(Reg2)); + I.addOperand(MCOperand::createReg(Reg3)); + OutStreamer->EmitInstruction(I, STI); } -void MipsAsmPrinter::EmitMovFPIntPair(unsigned MovOpc, unsigned Reg1, +void MipsAsmPrinter::EmitMovFPIntPair(const MCSubtargetInfo &STI, + unsigned MovOpc, unsigned Reg1, unsigned Reg2, unsigned FPReg1, unsigned FPReg2, bool LE) { if (!LE) { @@ -818,59 +830,60 @@ void MipsAsmPrinter::EmitMovFPIntPair(unsigned MovOpc, unsigned Reg1, Reg1 = Reg2; Reg2 = temp; } - EmitInstrRegReg(MovOpc, Reg1, FPReg1); - EmitInstrRegReg(MovOpc, Reg2, FPReg2); + EmitInstrRegReg(STI, MovOpc, Reg1, FPReg1); + EmitInstrRegReg(STI, MovOpc, Reg2, FPReg2); } -void MipsAsmPrinter::EmitSwapFPIntParams(Mips16HardFloatInfo::FPParamVariant PV, +void MipsAsmPrinter::EmitSwapFPIntParams(const MCSubtargetInfo &STI, + Mips16HardFloatInfo::FPParamVariant PV, bool LE, bool ToFP) { using namespace Mips16HardFloatInfo; unsigned MovOpc = ToFP ? Mips::MTC1 : Mips::MFC1; switch (PV) { case FSig: - EmitInstrRegReg(MovOpc, Mips::A0, Mips::F12); + EmitInstrRegReg(STI, MovOpc, Mips::A0, Mips::F12); break; case FFSig: - EmitMovFPIntPair(MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F14, LE); + EmitMovFPIntPair(STI, MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F14, LE); break; case FDSig: - EmitInstrRegReg(MovOpc, Mips::A0, Mips::F12); - EmitMovFPIntPair(MovOpc, Mips::A2, Mips::A3, Mips::F14, Mips::F15, LE); + EmitInstrRegReg(STI, MovOpc, Mips::A0, Mips::F12); + EmitMovFPIntPair(STI, MovOpc, Mips::A2, Mips::A3, Mips::F14, Mips::F15, LE); break; case DSig: - EmitMovFPIntPair(MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F13, LE); + EmitMovFPIntPair(STI, MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F13, LE); break; case DDSig: - EmitMovFPIntPair(MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F13, LE); - EmitMovFPIntPair(MovOpc, Mips::A2, Mips::A3, Mips::F14, Mips::F15, LE); + EmitMovFPIntPair(STI, MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F13, LE); + EmitMovFPIntPair(STI, MovOpc, Mips::A2, Mips::A3, Mips::F14, Mips::F15, LE); break; case DFSig: - EmitMovFPIntPair(MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F13, LE); - EmitInstrRegReg(MovOpc, Mips::A2, Mips::F14); + EmitMovFPIntPair(STI, MovOpc, Mips::A0, Mips::A1, Mips::F12, Mips::F13, LE); + EmitInstrRegReg(STI, MovOpc, Mips::A2, Mips::F14); break; case NoSig: return; } } -void -MipsAsmPrinter::EmitSwapFPIntRetval(Mips16HardFloatInfo::FPReturnVariant RV, - bool LE) { +void MipsAsmPrinter::EmitSwapFPIntRetval( + const MCSubtargetInfo &STI, Mips16HardFloatInfo::FPReturnVariant RV, + bool LE) { using namespace Mips16HardFloatInfo; unsigned MovOpc = Mips::MFC1; switch (RV) { case FRet: - EmitInstrRegReg(MovOpc, Mips::V0, Mips::F0); + EmitInstrRegReg(STI, MovOpc, Mips::V0, Mips::F0); break; case DRet: - EmitMovFPIntPair(MovOpc, Mips::V0, Mips::V1, Mips::F0, Mips::F1, LE); + EmitMovFPIntPair(STI, MovOpc, Mips::V0, Mips::V1, Mips::F0, Mips::F1, LE); break; case CFRet: - EmitMovFPIntPair(MovOpc, Mips::V0, Mips::V1, Mips::F0, Mips::F1, LE); + EmitMovFPIntPair(STI, MovOpc, Mips::V0, Mips::V1, Mips::F0, Mips::F1, LE); break; case CDRet: - EmitMovFPIntPair(MovOpc, Mips::V0, Mips::V1, Mips::F0, Mips::F1, LE); - EmitMovFPIntPair(MovOpc, Mips::A0, Mips::A1, Mips::F2, Mips::F3, LE); + EmitMovFPIntPair(STI, MovOpc, Mips::V0, Mips::V1, Mips::F0, Mips::F1, LE); + EmitMovFPIntPair(STI, MovOpc, Mips::A0, Mips::A1, Mips::F2, Mips::F3, LE); break; case NoFPRet: break; @@ -879,13 +892,20 @@ MipsAsmPrinter::EmitSwapFPIntRetval(Mips16HardFloatInfo::FPReturnVariant RV, void MipsAsmPrinter::EmitFPCallStub( const char *Symbol, const Mips16HardFloatInfo::FuncSignature *Signature) { - MCSymbol *MSymbol = OutContext.GetOrCreateSymbol(StringRef(Symbol)); + MCSymbol *MSymbol = OutContext.getOrCreateSymbol(StringRef(Symbol)); using namespace Mips16HardFloatInfo; - bool LE = Subtarget->isLittle(); + bool LE = getDataLayout().isLittleEndian(); + // Construct a local MCSubtargetInfo here. + // This is because the MachineFunction won't exist (but have not yet been + // freed) and since we're at the global level we can use the default + // constructed subtarget. + std::unique_ptr<MCSubtargetInfo> STI(TM.getTarget().createMCSubtargetInfo( + TM.getTargetTriple(), TM.getTargetCPU(), TM.getTargetFeatureString())); + // // .global xxxx // - OutStreamer.EmitSymbolAttribute(MSymbol, MCSA_Global); + OutStreamer->EmitSymbolAttribute(MSymbol, MCSA_Global); const char *RetType; // // make the comment field identifying the return and parameter @@ -933,23 +953,23 @@ void MipsAsmPrinter::EmitFPCallStub( Parms = ""; break; } - OutStreamer.AddComment("\t# Stub function to call " + Twine(RetType) + " " + - Twine(Symbol) + " (" + Twine(Parms) + ")"); + OutStreamer->AddComment("\t# Stub function to call " + Twine(RetType) + " " + + Twine(Symbol) + " (" + Twine(Parms) + ")"); // // probably not necessary but we save and restore the current section state // - OutStreamer.PushSection(); + OutStreamer->PushSection(); // // .section mips16.call.fpxxxx,"ax",@progbits // - const MCSectionELF *M = OutContext.getELFSection( + MCSectionELF *M = OutContext.getELFSection( ".mips16.call.fp." + std::string(Symbol), ELF::SHT_PROGBITS, - ELF::SHF_ALLOC | ELF::SHF_EXECINSTR, SectionKind::getText()); - OutStreamer.SwitchSection(M, nullptr); + ELF::SHF_ALLOC | ELF::SHF_EXECINSTR); + OutStreamer->SwitchSection(M, nullptr); // // .align 2 // - OutStreamer.EmitValueToAlignment(4); + OutStreamer->EmitValueToAlignment(4); MipsTargetStreamer &TS = getTargetStreamer(); // // .set nomips16 @@ -963,19 +983,17 @@ void MipsAsmPrinter::EmitFPCallStub( // __call_stub_fp_xxxx: // std::string x = "__call_stub_fp_" + std::string(Symbol); - MCSymbol *Stub = OutContext.GetOrCreateSymbol(StringRef(x)); + MCSymbolELF *Stub = + cast<MCSymbolELF>(OutContext.getOrCreateSymbol(StringRef(x))); TS.emitDirectiveEnt(*Stub); MCSymbol *MType = - OutContext.GetOrCreateSymbol("__call_stub_fp_" + Twine(Symbol)); - OutStreamer.EmitSymbolAttribute(MType, MCSA_ELF_TypeFunction); - OutStreamer.EmitLabel(Stub); - // - // we just handle non pic for now. these function will not be - // called otherwise. when the full stub generation is moved here - // we need to deal with pic. - // - if (TM.getRelocationModel() == Reloc::PIC_) - llvm_unreachable("should not be here if we are compiling pic"); + OutContext.getOrCreateSymbol("__call_stub_fp_" + Twine(Symbol)); + OutStreamer->EmitSymbolAttribute(MType, MCSA_ELF_TypeFunction); + OutStreamer->EmitLabel(Stub); + + // Only handle non-pic for now. + assert(TM.getRelocationModel() != Reloc::PIC_ && + "should not be here if we are compiling pic"); TS.emitDirectiveSetReorder(); // // We need to add a MipsMCExpr class to MCTargetDesc to fully implement @@ -992,31 +1010,31 @@ void MipsAsmPrinter::EmitFPCallStub( // // Mov $18, $31 - EmitInstrRegRegReg(Mips::ADDu, Mips::S2, Mips::RA, Mips::ZERO); + EmitInstrRegRegReg(*STI, Mips::ADDu, Mips::S2, Mips::RA, Mips::ZERO); - EmitSwapFPIntParams(Signature->ParamSig, LE, true); + EmitSwapFPIntParams(*STI, Signature->ParamSig, LE, true); // Jal xxxx // - EmitJal(MSymbol); + EmitJal(*STI, MSymbol); // fix return values - EmitSwapFPIntRetval(Signature->RetSig, LE); + EmitSwapFPIntRetval(*STI, Signature->RetSig, LE); // // do the return // if (Signature->RetSig == NoFPRet) // llvm_unreachable("should not be any stubs here with no return value"); // else - EmitInstrReg(Mips::JR, Mips::S2); - - MCSymbol *Tmp = OutContext.CreateTempSymbol(); - OutStreamer.EmitLabel(Tmp); - const MCSymbolRefExpr *E = MCSymbolRefExpr::Create(Stub, OutContext); - const MCSymbolRefExpr *T = MCSymbolRefExpr::Create(Tmp, OutContext); - const MCExpr *T_min_E = MCBinaryExpr::CreateSub(T, E, OutContext); - OutStreamer.EmitELFSize(Stub, T_min_E); + EmitInstrReg(*STI, Mips::JR, Mips::S2); + + MCSymbol *Tmp = OutContext.createTempSymbol(); + OutStreamer->EmitLabel(Tmp); + const MCSymbolRefExpr *E = MCSymbolRefExpr::create(Stub, OutContext); + const MCSymbolRefExpr *T = MCSymbolRefExpr::create(Tmp, OutContext); + const MCExpr *T_min_E = MCBinaryExpr::createSub(T, E, OutContext); + OutStreamer->emitELFSize(Stub, T_min_E); TS.emitDirectiveEnd(x); - OutStreamer.PopSection(); + OutStreamer->PopSection(); } void MipsAsmPrinter::EmitEndOfAsmFile(Module &M) { @@ -1032,7 +1050,7 @@ void MipsAsmPrinter::EmitEndOfAsmFile(Module &M) { EmitFPCallStub(Symbol, Signature); } // return to the text section - OutStreamer.SwitchSection(OutContext.getObjectFileInfo()->getTextSection()); + OutStreamer->SwitchSection(OutContext.getObjectFileInfo()->getTextSection()); } void MipsAsmPrinter::PrintDebugValueComment(const MachineInstr *MI, diff --git a/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.h b/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.h index 723155f..a7f3304 100644 --- a/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.h +++ b/contrib/llvm/lib/Target/Mips/MipsAsmPrinter.h @@ -60,27 +60,31 @@ private: std::map<const char *, const llvm::Mips16HardFloatInfo::FuncSignature *> StubsNeeded; - void emitInlineAsmStart(const MCSubtargetInfo &StartInfo) const override; + void emitInlineAsmStart() const override; void emitInlineAsmEnd(const MCSubtargetInfo &StartInfo, const MCSubtargetInfo *EndInfo) const override; - void EmitJal(MCSymbol *Symbol); + void EmitJal(const MCSubtargetInfo &STI, MCSymbol *Symbol); - void EmitInstrReg(unsigned Opcode, unsigned Reg); + void EmitInstrReg(const MCSubtargetInfo &STI, unsigned Opcode, unsigned Reg); - void EmitInstrRegReg(unsigned Opcode, unsigned Reg1, unsigned Reg2); + void EmitInstrRegReg(const MCSubtargetInfo &STI, unsigned Opcode, + unsigned Reg1, unsigned Reg2); - void EmitInstrRegRegReg(unsigned Opcode, unsigned Reg1, unsigned Reg2, - unsigned Reg3); + void EmitInstrRegRegReg(const MCSubtargetInfo &STI, unsigned Opcode, + unsigned Reg1, unsigned Reg2, unsigned Reg3); - void EmitMovFPIntPair(unsigned MovOpc, unsigned Reg1, unsigned Reg2, - unsigned FPReg1, unsigned FPReg2, bool LE); + void EmitMovFPIntPair(const MCSubtargetInfo &STI, unsigned MovOpc, + unsigned Reg1, unsigned Reg2, unsigned FPReg1, + unsigned FPReg2, bool LE); - void EmitSwapFPIntParams(Mips16HardFloatInfo::FPParamVariant, bool LE, + void EmitSwapFPIntParams(const MCSubtargetInfo &STI, + Mips16HardFloatInfo::FPParamVariant, bool LE, bool ToFP); - void EmitSwapFPIntRetval(Mips16HardFloatInfo::FPReturnVariant, bool LE); + void EmitSwapFPIntRetval(const MCSubtargetInfo &STI, + Mips16HardFloatInfo::FPReturnVariant, bool LE); void EmitFPCallStub(const char *, const Mips16HardFloatInfo::FuncSignature *); @@ -94,14 +98,10 @@ public: const MipsFunctionInfo *MipsFI; MipsMCInstLower MCInstLowering; - // We initialize the subtarget here and in runOnMachineFunction - // since there are certain target specific flags (ABI) that could - // reside on the TargetMachine, but are on the subtarget currently - // and we need them for the beginning of file output before we've - // seen a single function. - explicit MipsAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) - : AsmPrinter(TM, Streamer), MCP(nullptr), InConstantPool(false), - Subtarget(&TM.getSubtarget<MipsSubtarget>()), MCInstLowering(*this) {} + explicit MipsAsmPrinter(TargetMachine &TM, + std::unique_ptr<MCStreamer> Streamer) + : AsmPrinter(TM, std::move(Streamer)), MCP(nullptr), + InConstantPool(false), MCInstLowering(*this) {} const char *getPassName() const override { return "Mips Assembly Printer"; @@ -124,6 +124,7 @@ public: void EmitFunctionEntryLabel() override; void EmitFunctionBodyStart() override; void EmitFunctionBodyEnd() override; + void EmitBasicBlockEnd(const MachineBasicBlock &MBB) override; bool isBlockOnlyReachableByFallthrough( const MachineBasicBlock* MBB) const override; bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, diff --git a/contrib/llvm/lib/Target/Mips/MipsCCState.h b/contrib/llvm/lib/Target/Mips/MipsCCState.h index 9a08ade..081c393 100644 --- a/contrib/llvm/lib/Target/Mips/MipsCCState.h +++ b/contrib/llvm/lib/Target/Mips/MipsCCState.h @@ -85,10 +85,10 @@ public: // provide a means of accessing ArgListEntry::IsFixed. Delete them from this // class. This doesn't stop them being used via the base class though. void AnalyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Outs, - CCAssignFn Fn) LLVM_DELETED_FUNCTION; + CCAssignFn Fn) = delete; void AnalyzeCallOperands(const SmallVectorImpl<MVT> &Outs, SmallVectorImpl<ISD::ArgFlagsTy> &Flags, - CCAssignFn Fn) LLVM_DELETED_FUNCTION; + CCAssignFn Fn) = delete; void AnalyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Ins, CCAssignFn Fn) { diff --git a/contrib/llvm/lib/Target/Mips/MipsCallingConv.td b/contrib/llvm/lib/Target/Mips/MipsCallingConv.td index dcd88f2..93e1908 100644 --- a/contrib/llvm/lib/Target/Mips/MipsCallingConv.td +++ b/contrib/llvm/lib/Target/Mips/MipsCallingConv.td @@ -64,9 +64,9 @@ def RetCC_F128HardFloat : CallingConv<[ // Handle F128 specially since we can't identify the original type during the // tablegen-erated code. def RetCC_F128 : CallingConv<[ - CCIfSubtarget<"abiUsesSoftFloat()", + CCIfSubtarget<"useSoftFloat()", CCIfType<[i64], CCDelegateTo<RetCC_F128SoftFloat>>>, - CCIfSubtargetNot<"abiUsesSoftFloat()", + CCIfSubtargetNot<"useSoftFloat()", CCIfType<[i64], CCDelegateTo<RetCC_F128HardFloat>>> ]>; @@ -90,6 +90,9 @@ def CC_MipsO32 : CallingConv<[ // Only the return rules are defined here for O32. The rules for argument // passing are defined in MipsISelLowering.cpp. def RetCC_MipsO32 : CallingConv<[ + // Promote i1/i8/i16 return values to i32. + CCIfType<[i1, i8, i16], CCPromoteToType<i32>>, + // i32 are returned in registers V0, V1, A0, A1 CCIfType<[i32], CCAssignToReg<[V0, V1, A0, A1]>>, @@ -131,7 +134,7 @@ def CC_MipsN : CallingConv<[ CCIfType<[i8, i16, i32], CCIfOrigArgWasNotFloat<CCPromoteToType<i64>>>, // The only i32's we have left are soft-float arguments. - CCIfSubtarget<"abiUsesSoftFloat()", CCIfType<[i32], CCDelegateTo<CC_MipsN_SoftFloat>>>, + CCIfSubtarget<"useSoftFloat()", CCIfType<[i32], CCDelegateTo<CC_MipsN_SoftFloat>>>, // Integer arguments are passed in integer registers. CCIfType<[i64], CCAssignToRegWithShadow<[A0_64, A1_64, A2_64, A3_64, @@ -369,7 +372,7 @@ def CC_Mips_FixedArg : CallingConv<[ // f128 should only occur for the N64 ABI where long double is 128-bit. On // N32, long double is equivalent to double. CCIfType<[i64], - CCIfSubtargetNot<"abiUsesSoftFloat()", + CCIfSubtargetNot<"useSoftFloat()", CCIfOrigArgWasF128<CCBitConvertToType<f64>>>>, CCIfCC<"CallingConv::Fast", CCDelegateTo<CC_Mips_FastCC>>, diff --git a/contrib/llvm/lib/Target/Mips/MipsCondMov.td b/contrib/llvm/lib/Target/Mips/MipsCondMov.td index af10cd4..2d96d9b 100644 --- a/contrib/llvm/lib/Target/Mips/MipsCondMov.td +++ b/contrib/llvm/lib/Target/Mips/MipsCondMov.td @@ -27,7 +27,8 @@ class CMov_I_I_FT<string opstr, RegisterOperand CRC, RegisterOperand DRC, class CMov_I_F_FT<string opstr, RegisterOperand CRC, RegisterOperand DRC, InstrItinClass Itin> : InstSE<(outs DRC:$fd), (ins DRC:$fs, CRC:$rt, DRC:$F), - !strconcat(opstr, "\t$fd, $fs, $rt"), [], Itin, FrmFR, opstr> { + !strconcat(opstr, "\t$fd, $fs, $rt"), [], Itin, FrmFR, opstr>, + HARDFLOAT { let Constraints = "$F = $fd"; } @@ -37,7 +38,7 @@ class CMov_F_I_FT<string opstr, RegisterOperand RC, InstrItinClass Itin, InstSE<(outs RC:$rd), (ins RC:$rs, FCCRegsOpnd:$fcc, RC:$F), !strconcat(opstr, "\t$rd, $rs, $fcc"), [(set RC:$rd, (OpNode RC:$rs, FCCRegsOpnd:$fcc, RC:$F))], - Itin, FrmFR, opstr> { + Itin, FrmFR, opstr>, HARDFLOAT { let Constraints = "$F = $rd"; } @@ -47,7 +48,7 @@ class CMov_F_F_FT<string opstr, RegisterOperand RC, InstrItinClass Itin, InstSE<(outs RC:$fd), (ins RC:$fs, FCCRegsOpnd:$fcc, RC:$F), !strconcat(opstr, "\t$fd, $fs, $fcc"), [(set RC:$fd, (OpNode RC:$fs, FCCRegsOpnd:$fcc, RC:$F))], - Itin, FrmFR, opstr> { + Itin, FrmFR, opstr>, HARDFLOAT { let Constraints = "$F = $fd"; } diff --git a/contrib/llvm/lib/Target/Mips/MipsConstantIslandPass.cpp b/contrib/llvm/lib/Target/Mips/MipsConstantIslandPass.cpp index c4e5ac0..96553d2 100644 --- a/contrib/llvm/lib/Target/Mips/MipsConstantIslandPass.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsConstantIslandPass.cpp @@ -448,14 +448,12 @@ bool MipsConstantIslands::runOnMachineFunction(MachineFunction &mf) { // FIXME: MF = &mf; MCP = mf.getConstantPool(); - STI = &mf.getTarget().getSubtarget<MipsSubtarget>(); + STI = &static_cast<const MipsSubtarget &>(mf.getSubtarget()); DEBUG(dbgs() << "constant island machine function " << "\n"); if (!STI->inMips16Mode() || !MipsSubtarget::useConstantIslands()) { return false; } - TII = (const Mips16InstrInfo *)MF->getTarget() - .getSubtargetImpl() - ->getInstrInfo(); + TII = (const Mips16InstrInfo *)STI->getInstrInfo(); MFI = MF->getInfo<MipsFunctionInfo>(); DEBUG(dbgs() << "constant island processing " << "\n"); // @@ -562,7 +560,7 @@ MipsConstantIslands::doInitialPlacement(std::vector<MachineInstr*> &CPEMIs) { // identity mapping of CPI's to CPE's. const std::vector<MachineConstantPoolEntry> &CPs = MCP->getConstants(); - const DataLayout &TD = *MF->getSubtarget().getDataLayout(); + const DataLayout &TD = *MF->getTarget().getDataLayout(); for (unsigned i = 0, e = CPs.size(); i != e; ++i) { unsigned Size = TD.getTypeAllocSize(CPs[i].getType()); assert(Size >= 4 && "Too small constant pool entry"); diff --git a/contrib/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp b/contrib/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp index d5027b9..4faeb33 100644 --- a/contrib/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsDelaySlotFiller.cpp @@ -69,7 +69,7 @@ namespace { class RegDefsUses { public: - RegDefsUses(TargetMachine &TM); + RegDefsUses(const TargetRegisterInfo &TRI); void init(const MachineInstr &MI); /// This function sets all caller-saved registers in Defs. @@ -140,7 +140,7 @@ namespace { /// memory instruction can be moved to a delay slot. class MemDefsUses : public InspectMemInstr { public: - MemDefsUses(const MachineFrameInfo *MFI); + MemDefsUses(const DataLayout &DL, const MachineFrameInfo *MFI); private: typedef PointerUnion<const Value *, const PseudoSourceValue *> ValueType; @@ -158,6 +158,7 @@ namespace { const MachineFrameInfo *MFI; SmallPtrSet<ValueType, 4> Uses, Defs; + const DataLayout &DL; /// Flags indicating whether loads or stores with no underlying objects have /// been seen. @@ -199,6 +200,9 @@ namespace { Iter replaceWithCompactBranch(MachineBasicBlock &MBB, Iter Branch, DebugLoc DL); + Iter replaceWithCompactJump(MachineBasicBlock &MBB, + Iter Jump, DebugLoc DL); + /// This function checks if it is valid to move Candidate to the delay slot /// and returns true if it isn't. It also updates memory and register /// dependence information. @@ -209,8 +213,8 @@ namespace { /// moved to the delay slot. Returns true on success. template<typename IterTy> bool searchRange(MachineBasicBlock &MBB, IterTy Begin, IterTy End, - RegDefsUses &RegDU, InspectMemInstr &IM, - IterTy &Filler, Iter Slot) const; + RegDefsUses &RegDU, InspectMemInstr &IM, Iter Slot, + IterTy &Filler) const; /// This function searches in the backward direction for an instruction that /// can be moved to the delay slot. Returns true on success. @@ -278,11 +282,7 @@ static void addLiveInRegs(Iter Filler, MachineBasicBlock &MBB) { #ifndef NDEBUG const MachineFunction &MF = *MBB.getParent(); - assert(MF.getTarget() - .getSubtargetImpl() - ->getRegisterInfo() - ->getAllocatableSet(MF) - .test(R) && + assert(MF.getSubtarget().getRegisterInfo()->getAllocatableSet(MF).test(R) && "Shouldn't move an instruction with unallocatable registers across " "basic block boundaries."); #endif @@ -292,9 +292,8 @@ static void addLiveInRegs(Iter Filler, MachineBasicBlock &MBB) { } } -RegDefsUses::RegDefsUses(TargetMachine &TM) - : TRI(*TM.getSubtargetImpl()->getRegisterInfo()), - Defs(TRI.getNumRegs(), false), Uses(TRI.getNumRegs(), false) {} +RegDefsUses::RegDefsUses(const TargetRegisterInfo &TRI) + : TRI(TRI), Defs(TRI.getNumRegs(), false), Uses(TRI.getNumRegs(), false) {} void RegDefsUses::init(const MachineInstr &MI) { // Add all register operands which are explicit and non-variadic. @@ -316,13 +315,22 @@ void RegDefsUses::init(const MachineInstr &MI) { void RegDefsUses::setCallerSaved(const MachineInstr &MI) { assert(MI.isCall()); + // Add RA/RA_64 to Defs to prevent users of RA/RA_64 from going into + // the delay slot. The reason is that RA/RA_64 must not be changed + // in the delay slot so that the callee can return to the caller. + if (MI.definesRegister(Mips::RA) || MI.definesRegister(Mips::RA_64)) { + Defs.set(Mips::RA); + Defs.set(Mips::RA_64); + } + // If MI is a call, add all caller-saved registers to Defs. BitVector CallerSavedRegs(TRI.getNumRegs(), true); CallerSavedRegs.reset(Mips::ZERO); CallerSavedRegs.reset(Mips::ZERO_64); - for (const MCPhysReg *R = TRI.getCalleeSavedRegs(); *R; ++R) + for (const MCPhysReg *R = TRI.getCalleeSavedRegs(MI.getParent()->getParent()); + *R; ++R) for (MCRegAliasIterator AI(*R, &TRI, true); AI.isValid(); ++AI) CallerSavedRegs.reset(*AI); @@ -429,9 +437,9 @@ bool LoadFromStackOrConst::hasHazard_(const MachineInstr &MI) { return true; } -MemDefsUses::MemDefsUses(const MachineFrameInfo *MFI_) - : InspectMemInstr(false), MFI(MFI_), SeenNoObjLoad(false), - SeenNoObjStore(false) {} +MemDefsUses::MemDefsUses(const DataLayout &DL, const MachineFrameInfo *MFI_) + : InspectMemInstr(false), MFI(MFI_), DL(DL), SeenNoObjLoad(false), + SeenNoObjStore(false) {} bool MemDefsUses::hasHazard_(const MachineInstr &MI) { bool HasHazard = false; @@ -484,7 +492,7 @@ getUnderlyingObjects(const MachineInstr &MI, const Value *V = (*MI.memoperands_begin())->getValue(); SmallVector<Value *, 4> Objs; - GetUnderlyingObjects(const_cast<Value *>(V), Objs); + GetUnderlyingObjects(const_cast<Value *>(V), Objs, DL); for (SmallVectorImpl<Value *>::iterator I = Objs.begin(), E = Objs.end(); I != E; ++I) { @@ -500,8 +508,8 @@ getUnderlyingObjects(const MachineInstr &MI, // Replace Branch with the compact branch instruction. Iter Filler::replaceWithCompactBranch(MachineBasicBlock &MBB, Iter Branch, DebugLoc DL) { - const MipsInstrInfo *TII= static_cast<const MipsInstrInfo *>( - TM.getSubtargetImpl()->getInstrInfo()); + const MipsInstrInfo *TII = + MBB.getParent()->getSubtarget<MipsSubtarget>().getInstrInfo(); unsigned NewOpcode = (((unsigned) Branch->getOpcode()) == Mips::BEQ) ? Mips::BEQZC_MM @@ -520,6 +528,24 @@ Iter Filler::replaceWithCompactBranch(MachineBasicBlock &MBB, return Branch; } +// Replace Jumps with the compact jump instruction. +Iter Filler::replaceWithCompactJump(MachineBasicBlock &MBB, + Iter Jump, DebugLoc DL) { + const MipsInstrInfo *TII = + MBB.getParent()->getSubtarget<MipsSubtarget>().getInstrInfo(); + + const MCInstrDesc &NewDesc = TII->get(Mips::JRC16_MM); + MachineInstrBuilder MIB = BuildMI(MBB, Jump, DL, NewDesc); + + MIB.addReg(Jump->getOperand(0).getReg()); + + Iter tmpIter = Jump; + Jump = std::prev(Jump); + MBB.erase(tmpIter); + + return Jump; +} + // For given opcode returns opcode of corresponding instruction with short // delay slot. static int getEquivalentCallShort(int Opcode) { @@ -543,9 +569,9 @@ static int getEquivalentCallShort(int Opcode) { /// We assume there is only one delay slot per delayed instruction. bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) { bool Changed = false; - bool InMicroMipsMode = TM.getSubtarget<MipsSubtarget>().inMicroMipsMode(); - const MipsInstrInfo *TII = - static_cast<const MipsInstrInfo *>(TM.getSubtargetImpl()->getInstrInfo()); + const MipsSubtarget &STI = MBB.getParent()->getSubtarget<MipsSubtarget>(); + bool InMicroMipsMode = STI.inMicroMipsMode(); + const MipsInstrInfo *TII = STI.getInstrInfo(); for (Iter I = MBB.begin(); I != MBB.end(); ++I) { if (!hasUnoccupiedSlot(&*I)) @@ -587,17 +613,29 @@ bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) { // adding NOP replace this instruction with the corresponding compact // branch instruction, i.e. BEQZC or BNEZC. unsigned Opcode = I->getOpcode(); - if (InMicroMipsMode && - (Opcode == Mips::BEQ || Opcode == Mips::BNE) && - ((unsigned) I->getOperand(1).getReg()) == Mips::ZERO) { - - I = replaceWithCompactBranch(MBB, I, I->getDebugLoc()); - - } else { - // Bundle the NOP to the instruction with the delay slot. - BuildMI(MBB, std::next(I), I->getDebugLoc(), TII->get(Mips::NOP)); - MIBundleBuilder(MBB, I, std::next(I, 2)); + if (InMicroMipsMode) { + switch (Opcode) { + case Mips::BEQ: + case Mips::BNE: + if (((unsigned) I->getOperand(1).getReg()) == Mips::ZERO) { + I = replaceWithCompactBranch(MBB, I, I->getDebugLoc()); + continue; + } + break; + case Mips::JR: + case Mips::PseudoReturn: + case Mips::PseudoIndirectBranch: + // For microMIPS the PseudoReturn and PseudoIndirectBranch are allways + // expanded to JR_MM, so they can be replaced with JRC16_MM. + I = replaceWithCompactJump(MBB, I, I->getDebugLoc()); + continue; + default: + break; + } } + // Bundle the NOP to the instruction with the delay slot. + BuildMI(MBB, std::next(I), I->getDebugLoc(), TII->get(Mips::NOP)); + MIBundleBuilder(MBB, I, std::next(I, 2)); } return Changed; @@ -611,45 +649,60 @@ FunctionPass *llvm::createMipsDelaySlotFillerPass(MipsTargetMachine &tm) { template<typename IterTy> bool Filler::searchRange(MachineBasicBlock &MBB, IterTy Begin, IterTy End, - RegDefsUses &RegDU, InspectMemInstr& IM, - IterTy &Filler, Iter Slot) const { - for (IterTy I = Begin; I != End; ++I) { + RegDefsUses &RegDU, InspectMemInstr& IM, Iter Slot, + IterTy &Filler) const { + bool IsReverseIter = std::is_convertible<IterTy, ReverseIter>::value; + + for (IterTy I = Begin; I != End;) { + IterTy CurrI = I; + ++I; + // skip debug value - if (I->isDebugValue()) + if (CurrI->isDebugValue()) continue; - if (terminateSearch(*I)) + if (terminateSearch(*CurrI)) break; - assert((!I->isCall() && !I->isReturn() && !I->isBranch()) && + assert((!CurrI->isCall() && !CurrI->isReturn() && !CurrI->isBranch()) && "Cannot put calls, returns or branches in delay slot."); - if (delayHasHazard(*I, RegDU, IM)) + if (CurrI->isKill()) { + CurrI->eraseFromParent(); + + // This special case is needed for reverse iterators, because when we + // erase an instruction, the iterators are updated to point to the next + // instruction. + if (IsReverseIter && I != End) + I = CurrI; + continue; + } + + if (delayHasHazard(*CurrI, RegDU, IM)) continue; - if (TM.getSubtarget<MipsSubtarget>().isTargetNaCl()) { + const MipsSubtarget &STI = MBB.getParent()->getSubtarget<MipsSubtarget>(); + if (STI.isTargetNaCl()) { // In NaCl, instructions that must be masked are forbidden in delay slots. // We only check for loads, stores and SP changes. Calls, returns and // branches are not checked because non-NaCl targets never put them in // delay slots. unsigned AddrIdx; - if ((isBasePlusOffsetMemoryAccess(I->getOpcode(), &AddrIdx) && - baseRegNeedsLoadStoreMask(I->getOperand(AddrIdx).getReg())) || - I->modifiesRegister(Mips::SP, - TM.getSubtargetImpl()->getRegisterInfo())) + if ((isBasePlusOffsetMemoryAccess(CurrI->getOpcode(), &AddrIdx) && + baseRegNeedsLoadStoreMask(CurrI->getOperand(AddrIdx).getReg())) || + CurrI->modifiesRegister(Mips::SP, STI.getRegisterInfo())) continue; } - bool InMicroMipsMode = TM.getSubtarget<MipsSubtarget>().inMicroMipsMode(); - const MipsInstrInfo *TII = static_cast<const MipsInstrInfo *>( - TM.getSubtargetImpl()->getInstrInfo()); + bool InMicroMipsMode = STI.inMicroMipsMode(); + const MipsInstrInfo *TII = STI.getInstrInfo(); unsigned Opcode = (*Slot).getOpcode(); - if (InMicroMipsMode && TII->GetInstSizeInBytes(&(*I)) == 2 && + if (InMicroMipsMode && TII->GetInstSizeInBytes(&(*CurrI)) == 2 && (Opcode == Mips::JR || Opcode == Mips::PseudoIndirectBranch || Opcode == Mips::PseudoReturn)) continue; - Filler = I; + Filler = CurrI; return true; } @@ -660,14 +713,14 @@ bool Filler::searchBackward(MachineBasicBlock &MBB, Iter Slot) const { if (DisableBackwardSearch) return false; - RegDefsUses RegDU(TM); - MemDefsUses MemDU(MBB.getParent()->getFrameInfo()); + RegDefsUses RegDU(*MBB.getParent()->getSubtarget().getRegisterInfo()); + MemDefsUses MemDU(*TM.getDataLayout(), MBB.getParent()->getFrameInfo()); ReverseIter Filler; RegDU.init(*Slot); - if (!searchRange(MBB, ReverseIter(Slot), MBB.rend(), RegDU, MemDU, Filler, - Slot)) + if (!searchRange(MBB, ReverseIter(Slot), MBB.rend(), RegDU, MemDU, Slot, + Filler)) return false; MBB.splice(std::next(Slot), &MBB, std::next(Filler).base()); @@ -681,13 +734,13 @@ bool Filler::searchForward(MachineBasicBlock &MBB, Iter Slot) const { if (DisableForwardSearch || !Slot->isCall()) return false; - RegDefsUses RegDU(TM); + RegDefsUses RegDU(*MBB.getParent()->getSubtarget().getRegisterInfo()); NoMemInstr NM; Iter Filler; RegDU.setCallerSaved(*Slot); - if (!searchRange(MBB, std::next(Slot), MBB.end(), RegDU, NM, Filler, Slot)) + if (!searchRange(MBB, std::next(Slot), MBB.end(), RegDU, NM, Slot, Filler)) return false; MBB.splice(std::next(Slot), &MBB, Filler); @@ -705,7 +758,7 @@ bool Filler::searchSuccBBs(MachineBasicBlock &MBB, Iter Slot) const { if (!SuccBB) return false; - RegDefsUses RegDU(TM); + RegDefsUses RegDU(*MBB.getParent()->getSubtarget().getRegisterInfo()); bool HasMultipleSuccs = false; BB2BrMap BrMap; std::unique_ptr<InspectMemInstr> IM; @@ -727,11 +780,11 @@ bool Filler::searchSuccBBs(MachineBasicBlock &MBB, Iter Slot) const { IM.reset(new LoadFromStackOrConst()); } else { const MachineFrameInfo *MFI = MBB.getParent()->getFrameInfo(); - IM.reset(new MemDefsUses(MFI)); + IM.reset(new MemDefsUses(*TM.getDataLayout(), MFI)); } - if (!searchRange(MBB, SuccBB->begin(), SuccBB->end(), RegDU, *IM, Filler, - Slot)) + if (!searchRange(MBB, SuccBB->begin(), SuccBB->end(), RegDU, *IM, Slot, + Filler)) return false; insertDelayFiller(Filler, BrMap); @@ -758,7 +811,7 @@ MachineBasicBlock *Filler::selectSuccBB(MachineBasicBlock &B) const { std::pair<MipsInstrInfo::BranchType, MachineInstr *> Filler::getBranch(MachineBasicBlock &MBB, const MachineBasicBlock &Dst) const { const MipsInstrInfo *TII = - static_cast<const MipsInstrInfo *>(TM.getSubtargetImpl()->getInstrInfo()); + MBB.getParent()->getSubtarget<MipsSubtarget>().getInstrInfo(); MachineBasicBlock *TrueBB = nullptr, *FalseBB = nullptr; SmallVector<MachineInstr*, 2> BranchInstrs; SmallVector<MachineOperand, 2> Cond; @@ -814,7 +867,10 @@ bool Filler::examinePred(MachineBasicBlock &Pred, const MachineBasicBlock &Succ, bool Filler::delayHasHazard(const MachineInstr &Candidate, RegDefsUses &RegDU, InspectMemInstr &IM) const { - bool HasHazard = (Candidate.isImplicitDef() || Candidate.isKill()); + assert(!Candidate.isKill() && + "KILL instructions should have been eliminated at this point."); + + bool HasHazard = Candidate.isImplicitDef(); HasHazard |= IM.hasHazard(Candidate); HasHazard |= RegDU.update(Candidate, 0, Candidate.getNumOperands()); diff --git a/contrib/llvm/lib/Target/Mips/MipsFastISel.cpp b/contrib/llvm/lib/Target/Mips/MipsFastISel.cpp index 4588f40..3d020ab 100644 --- a/contrib/llvm/lib/Target/Mips/MipsFastISel.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsFastISel.cpp @@ -1,19 +1,22 @@ //===-- MipsastISel.cpp - Mips FastISel implementation //---------------------===// -#include "llvm/CodeGen/FunctionLoweringInfo.h" #include "MipsCCState.h" +#include "MipsInstrInfo.h" #include "MipsISelLowering.h" #include "MipsMachineFunction.h" #include "MipsRegisterInfo.h" #include "MipsSubtarget.h" #include "MipsTargetMachine.h" +#include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/CodeGen/FastISel.h" +#include "llvm/CodeGen/FunctionLoweringInfo.h" #include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/IR/GetElementPtrTypeIterator.h" #include "llvm/IR/GlobalAlias.h" #include "llvm/IR/GlobalVariable.h" #include "llvm/Target/TargetInstrInfo.h" -#include "llvm/Target/TargetLibraryInfo.h" using namespace llvm; @@ -43,6 +46,7 @@ class MipsFastISel final : public FastISel { void setKind(BaseKind K) { Kind = K; } BaseKind getKind() const { return Kind; } bool isRegBase() const { return Kind == RegBase; } + bool isFIBase() const { return Kind == FrameIndexBase; } void setReg(unsigned Reg) { assert(isRegBase() && "Invalid base register access!"); Base.Reg = Reg; @@ -51,6 +55,15 @@ class MipsFastISel final : public FastISel { assert(isRegBase() && "Invalid base register access!"); return Base.Reg; } + void setFI(unsigned FI) { + assert(isFIBase() && "Invalid base frame index access!"); + Base.FI = FI; + } + unsigned getFI() const { + assert(isFIBase() && "Invalid base frame index access!"); + return Base.FI; + } + void setOffset(int64_t Offset_) { Offset = Offset_; } int64_t getOffset() const { return Offset; } void setGlobalValue(const GlobalValue *G) { GV = G; } @@ -60,15 +73,16 @@ class MipsFastISel final : public FastISel { /// Subtarget - Keep a pointer to the MipsSubtarget around so that we can /// make the right decision when generating code for different targets. const TargetMachine &TM; + const MipsSubtarget *Subtarget; const TargetInstrInfo &TII; const TargetLowering &TLI; - const MipsSubtarget *Subtarget; MipsFunctionInfo *MFI; // Convenience variables to avoid some queries. LLVMContext *Context; bool fastLowerCall(CallLoweringInfo &CLI) override; + bool fastLowerIntrinsicCall(const IntrinsicInst *II) override; bool TargetSupported; bool UnsupportedFPMode; // To allow fast-isel to proceed and just not handle @@ -77,9 +91,11 @@ class MipsFastISel final : public FastISel { private: // Selection routines. + bool selectLogicalOp(const Instruction *I); bool selectLoad(const Instruction *I); bool selectStore(const Instruction *I); bool selectBranch(const Instruction *I); + bool selectSelect(const Instruction *I); bool selectCmp(const Instruction *I); bool selectFPExt(const Instruction *I); bool selectFPTrunc(const Instruction *I); @@ -87,12 +103,16 @@ private: bool selectRet(const Instruction *I); bool selectTrunc(const Instruction *I); bool selectIntExt(const Instruction *I); + bool selectShift(const Instruction *I); + bool selectDivRem(const Instruction *I, unsigned ISDOpcode); // Utility helper routines. bool isTypeLegal(Type *Ty, MVT &VT); + bool isTypeSupported(Type *Ty, MVT &VT); bool isLoadTypeLegal(Type *Ty, MVT &VT); bool computeAddress(const Value *Obj, Address &Addr); bool computeCallAddress(const Value *V, Address &Addr); + void simplifyAddress(Address &Addr); // Emit helper routines. bool emitCmp(unsigned DestReg, const CmpInst *CI); @@ -116,10 +136,14 @@ private: unsigned getRegEnsuringSimpleIntegerWidening(const Value *, bool IsUnsigned); + unsigned emitLogicalOp(unsigned ISDOpc, MVT RetVT, const Value *LHS, + const Value *RHS); + unsigned materializeFP(const ConstantFP *CFP, MVT VT); unsigned materializeGV(const GlobalValue *GV, MVT VT); unsigned materializeInt(const Constant *C, MVT VT); unsigned materialize32BitInt(int64_t Imm, const TargetRegisterClass *RC); + unsigned materializeExternalCallSym(const char *SynName); MachineInstrBuilder emitInst(unsigned Opc) { return BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)); @@ -136,6 +160,12 @@ private: unsigned MemReg, int64_t MemOffset) { return emitInst(Opc, DstReg).addReg(MemReg).addImm(MemOffset); } + + unsigned fastEmitInst_rr(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, bool Op0IsKill, + unsigned Op1, bool Op1IsKill); + // for some reason, this default is not generated by tablegen // so we explicitly generate it here. // @@ -157,17 +187,18 @@ public: explicit MipsFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo) : FastISel(funcInfo, libInfo), TM(funcInfo.MF->getTarget()), - TII(*TM.getSubtargetImpl()->getInstrInfo()), - TLI(*TM.getSubtargetImpl()->getTargetLowering()), - Subtarget(&TM.getSubtarget<MipsSubtarget>()) { + Subtarget(&funcInfo.MF->getSubtarget<MipsSubtarget>()), + TII(*Subtarget->getInstrInfo()), TLI(*Subtarget->getTargetLowering()) { MFI = funcInfo.MF->getInfo<MipsFunctionInfo>(); Context = &funcInfo.Fn->getContext(); - TargetSupported = ((TM.getRelocationModel() == Reloc::PIC_) && - ((Subtarget->hasMips32r2() || Subtarget->hasMips32()) && - (Subtarget->isABI_O32()))); + TargetSupported = + ((TM.getRelocationModel() == Reloc::PIC_) && + ((Subtarget->hasMips32r2() || Subtarget->hasMips32()) && + (static_cast<const MipsTargetMachine &>(TM).getABI().IsO32()))); UnsupportedFPMode = Subtarget->isFP64bit(); } + unsigned fastMaterializeAlloca(const AllocaInst *AI) override; unsigned fastMaterializeConstant(const Constant *C) override; bool fastSelectInstruction(const Instruction *I) override; @@ -185,9 +216,9 @@ static bool CC_MipsO32_FP32(unsigned ValNo, MVT ValVT, MVT LocVT, llvm_unreachable("should not be called"); } -bool CC_MipsO32_FP64(unsigned ValNo, MVT ValVT, MVT LocVT, - CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, - CCState &State) { +static bool CC_MipsO32_FP64(unsigned ValNo, MVT ValVT, MVT LocVT, + CCValAssign::LocInfo LocInfo, + ISD::ArgFlagsTy ArgFlags, CCState &State) { llvm_unreachable("should not be called"); } @@ -197,6 +228,62 @@ CCAssignFn *MipsFastISel::CCAssignFnForCall(CallingConv::ID CC) const { return CC_MipsO32; } +unsigned MipsFastISel::emitLogicalOp(unsigned ISDOpc, MVT RetVT, + const Value *LHS, const Value *RHS) { + // Canonicalize immediates to the RHS first. + if (isa<ConstantInt>(LHS) && !isa<ConstantInt>(RHS)) + std::swap(LHS, RHS); + + unsigned Opc; + if (ISDOpc == ISD::AND) { + Opc = Mips::AND; + } else if (ISDOpc == ISD::OR) { + Opc = Mips::OR; + } else if (ISDOpc == ISD::XOR) { + Opc = Mips::XOR; + } else + llvm_unreachable("unexpected opcode"); + + unsigned LHSReg = getRegForValue(LHS); + unsigned ResultReg = createResultReg(&Mips::GPR32RegClass); + if (!ResultReg) + return 0; + + unsigned RHSReg; + if (!LHSReg) + return 0; + + if (const auto *C = dyn_cast<ConstantInt>(RHS)) + RHSReg = materializeInt(C, MVT::i32); + else + RHSReg = getRegForValue(RHS); + + if (!RHSReg) + return 0; + + emitInst(Opc, ResultReg).addReg(LHSReg).addReg(RHSReg); + return ResultReg; +} + +unsigned MipsFastISel::fastMaterializeAlloca(const AllocaInst *AI) { + assert(TLI.getValueType(AI->getType(), true) == MVT::i32 && + "Alloca should always return a pointer."); + + DenseMap<const AllocaInst *, int>::iterator SI = + FuncInfo.StaticAllocaMap.find(AI); + + if (SI != FuncInfo.StaticAllocaMap.end()) { + unsigned ResultReg = createResultReg(&Mips::GPR32RegClass); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::LEA_ADDiu), + ResultReg) + .addFrameIndex(SI->second) + .addImm(0); + return ResultReg; + } + + return 0; +} + unsigned MipsFastISel::materializeInt(const Constant *C, MVT VT) { if (VT != MVT::i32 && VT != MVT::i16 && VT != MVT::i8 && VT != MVT::i1) return 0; @@ -282,6 +369,15 @@ unsigned MipsFastISel::materializeGV(const GlobalValue *GV, MVT VT) { return DestReg; } +unsigned MipsFastISel::materializeExternalCallSym(const char *SymName) { + const TargetRegisterClass *RC = &Mips::GPR32RegClass; + unsigned DestReg = createResultReg(RC); + emitInst(Mips::LW, DestReg) + .addReg(MFI->getGlobalBaseReg()) + .addExternalSymbol(SymName, MipsII::MO_GOT); + return DestReg; +} + // Materialize a constant into a register, and return the register // number (or zero if we failed to handle it). unsigned MipsFastISel::fastMaterializeConstant(const Constant *C) { @@ -303,28 +399,134 @@ unsigned MipsFastISel::fastMaterializeConstant(const Constant *C) { } bool MipsFastISel::computeAddress(const Value *Obj, Address &Addr) { - // This construct looks a big awkward but it is how other ports handle this - // and as this function is more fully completed, these cases which - // return false will have additional code in them. - // - if (isa<Instruction>(Obj)) - return false; - else if (isa<ConstantExpr>(Obj)) - return false; + + const User *U = nullptr; + unsigned Opcode = Instruction::UserOp1; + if (const Instruction *I = dyn_cast<Instruction>(Obj)) { + // Don't walk into other basic blocks unless the object is an alloca from + // another block, otherwise it may not have a virtual register assigned. + if (FuncInfo.StaticAllocaMap.count(static_cast<const AllocaInst *>(Obj)) || + FuncInfo.MBBMap[I->getParent()] == FuncInfo.MBB) { + Opcode = I->getOpcode(); + U = I; + } + } else if (const ConstantExpr *C = dyn_cast<ConstantExpr>(Obj)) { + Opcode = C->getOpcode(); + U = C; + } + switch (Opcode) { + default: + break; + case Instruction::BitCast: { + // Look through bitcasts. + return computeAddress(U->getOperand(0), Addr); + } + case Instruction::GetElementPtr: { + Address SavedAddr = Addr; + uint64_t TmpOffset = Addr.getOffset(); + // Iterate through the GEP folding the constants into offsets where + // we can. + gep_type_iterator GTI = gep_type_begin(U); + for (User::const_op_iterator i = U->op_begin() + 1, e = U->op_end(); i != e; + ++i, ++GTI) { + const Value *Op = *i; + if (StructType *STy = dyn_cast<StructType>(*GTI)) { + const StructLayout *SL = DL.getStructLayout(STy); + unsigned Idx = cast<ConstantInt>(Op)->getZExtValue(); + TmpOffset += SL->getElementOffset(Idx); + } else { + uint64_t S = DL.getTypeAllocSize(GTI.getIndexedType()); + for (;;) { + if (const ConstantInt *CI = dyn_cast<ConstantInt>(Op)) { + // Constant-offset addressing. + TmpOffset += CI->getSExtValue() * S; + break; + } + if (canFoldAddIntoGEP(U, Op)) { + // A compatible add with a constant operand. Fold the constant. + ConstantInt *CI = + cast<ConstantInt>(cast<AddOperator>(Op)->getOperand(1)); + TmpOffset += CI->getSExtValue() * S; + // Iterate on the other operand. + Op = cast<AddOperator>(Op)->getOperand(0); + continue; + } + // Unsupported + goto unsupported_gep; + } + } + } + // Try to grab the base operand now. + Addr.setOffset(TmpOffset); + if (computeAddress(U->getOperand(0), Addr)) + return true; + // We failed, restore everything and try the other options. + Addr = SavedAddr; + unsupported_gep: + break; + } + case Instruction::Alloca: { + const AllocaInst *AI = cast<AllocaInst>(Obj); + DenseMap<const AllocaInst *, int>::iterator SI = + FuncInfo.StaticAllocaMap.find(AI); + if (SI != FuncInfo.StaticAllocaMap.end()) { + Addr.setKind(Address::FrameIndexBase); + Addr.setFI(SI->second); + return true; + } + break; + } + } Addr.setReg(getRegForValue(Obj)); return Addr.getReg() != 0; } bool MipsFastISel::computeCallAddress(const Value *V, Address &Addr) { - const GlobalValue *GV = dyn_cast<GlobalValue>(V); - if (GV && isa<Function>(GV) && dyn_cast<Function>(GV)->isIntrinsic()) - return false; - if (!GV) - return false; + const User *U = nullptr; + unsigned Opcode = Instruction::UserOp1; + + if (const auto *I = dyn_cast<Instruction>(V)) { + // Check if the value is defined in the same basic block. This information + // is crucial to know whether or not folding an operand is valid. + if (I->getParent() == FuncInfo.MBB->getBasicBlock()) { + Opcode = I->getOpcode(); + U = I; + } + } else if (const auto *C = dyn_cast<ConstantExpr>(V)) { + Opcode = C->getOpcode(); + U = C; + } + + switch (Opcode) { + default: + break; + case Instruction::BitCast: + // Look past bitcasts if its operand is in the same BB. + return computeCallAddress(U->getOperand(0), Addr); + break; + case Instruction::IntToPtr: + // Look past no-op inttoptrs if its operand is in the same BB. + if (TLI.getValueType(U->getOperand(0)->getType()) == TLI.getPointerTy()) + return computeCallAddress(U->getOperand(0), Addr); + break; + case Instruction::PtrToInt: + // Look past no-op ptrtoints if its operand is in the same BB. + if (TLI.getValueType(U->getType()) == TLI.getPointerTy()) + return computeCallAddress(U->getOperand(0), Addr); + break; + } + if (const GlobalValue *GV = dyn_cast<GlobalValue>(V)) { Addr.setGlobalValue(GV); return true; } + + // If all else fails, try to materialize the value in a register. + if (!Addr.getGlobalValue()) { + Addr.setReg(getRegForValue(V)); + return Addr.getReg() != 0; + } + return false; } @@ -340,6 +542,21 @@ bool MipsFastISel::isTypeLegal(Type *Ty, MVT &VT) { return TLI.isTypeLegal(VT); } +bool MipsFastISel::isTypeSupported(Type *Ty, MVT &VT) { + if (Ty->isVectorTy()) + return false; + + if (isTypeLegal(Ty, VT)) + return true; + + // If this is a type than can be sign or zero-extended to a basic operation + // go ahead and accept it now. + if (VT == MVT::i1 || VT == MVT::i8 || VT == MVT::i16) + return true; + + return false; +} + bool MipsFastISel::isLoadTypeLegal(Type *Ty, MVT &VT) { if (isTypeLegal(Ty, VT)) return true; @@ -516,8 +733,26 @@ bool MipsFastISel::emitLoad(MVT VT, unsigned &ResultReg, Address &Addr, default: return false; } - emitInstLoad(Opc, ResultReg, Addr.getReg(), Addr.getOffset()); - return true; + if (Addr.isRegBase()) { + simplifyAddress(Addr); + emitInstLoad(Opc, ResultReg, Addr.getReg(), Addr.getOffset()); + return true; + } + if (Addr.isFIBase()) { + unsigned FI = Addr.getFI(); + unsigned Align = 4; + unsigned Offset = Addr.getOffset(); + MachineFrameInfo &MFI = *MF->getFrameInfo(); + MachineMemOperand *MMO = MF->getMachineMemOperand( + MachinePointerInfo::getFixedStack(FI), MachineMemOperand::MOLoad, + MFI.getObjectSize(FI), Align); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg) + .addFrameIndex(FI) + .addImm(Offset) + .addMemOperand(MMO); + return true; + } + return false; } bool MipsFastISel::emitStore(MVT VT, unsigned SrcReg, Address &Addr, @@ -549,7 +784,53 @@ bool MipsFastISel::emitStore(MVT VT, unsigned SrcReg, Address &Addr, default: return false; } - emitInstStore(Opc, SrcReg, Addr.getReg(), Addr.getOffset()); + if (Addr.isRegBase()) { + simplifyAddress(Addr); + emitInstStore(Opc, SrcReg, Addr.getReg(), Addr.getOffset()); + return true; + } + if (Addr.isFIBase()) { + unsigned FI = Addr.getFI(); + unsigned Align = 4; + unsigned Offset = Addr.getOffset(); + MachineFrameInfo &MFI = *MF->getFrameInfo(); + MachineMemOperand *MMO = MF->getMachineMemOperand( + MachinePointerInfo::getFixedStack(FI), MachineMemOperand::MOLoad, + MFI.getObjectSize(FI), Align); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)) + .addReg(SrcReg) + .addFrameIndex(FI) + .addImm(Offset) + .addMemOperand(MMO); + return true; + } + return false; +} + +bool MipsFastISel::selectLogicalOp(const Instruction *I) { + MVT VT; + if (!isTypeSupported(I->getType(), VT)) + return false; + + unsigned ResultReg; + switch (I->getOpcode()) { + default: + llvm_unreachable("Unexpected instruction."); + case Instruction::And: + ResultReg = emitLogicalOp(ISD::AND, VT, I->getOperand(0), I->getOperand(1)); + break; + case Instruction::Or: + ResultReg = emitLogicalOp(ISD::OR, VT, I->getOperand(0), I->getOperand(1)); + break; + case Instruction::Xor: + ResultReg = emitLogicalOp(ISD::XOR, VT, I->getOperand(0), I->getOperand(1)); + break; + } + + if (!ResultReg) + return false; + + updateValueMap(I, ResultReg); return true; } @@ -667,6 +948,50 @@ bool MipsFastISel::selectFPExt(const Instruction *I) { return true; } +bool MipsFastISel::selectSelect(const Instruction *I) { + assert(isa<SelectInst>(I) && "Expected a select instruction."); + + MVT VT; + if (!isTypeSupported(I->getType(), VT)) + return false; + + unsigned CondMovOpc; + const TargetRegisterClass *RC; + + if (VT.isInteger() && !VT.isVector() && VT.getSizeInBits() <= 32) { + CondMovOpc = Mips::MOVN_I_I; + RC = &Mips::GPR32RegClass; + } else if (VT == MVT::f32) { + CondMovOpc = Mips::MOVN_I_S; + RC = &Mips::FGR32RegClass; + } else if (VT == MVT::f64) { + CondMovOpc = Mips::MOVN_I_D32; + RC = &Mips::AFGR64RegClass; + } else + return false; + + const SelectInst *SI = cast<SelectInst>(I); + const Value *Cond = SI->getCondition(); + unsigned Src1Reg = getRegForValue(SI->getTrueValue()); + unsigned Src2Reg = getRegForValue(SI->getFalseValue()); + unsigned CondReg = getRegForValue(Cond); + + if (!Src1Reg || !Src2Reg || !CondReg) + return false; + + unsigned ResultReg = createResultReg(RC); + unsigned TempReg = createResultReg(RC); + + if (!ResultReg || !TempReg) + return false; + + emitInst(TargetOpcode::COPY, TempReg).addReg(Src2Reg); + emitInst(CondMovOpc, ResultReg) + .addReg(Src1Reg).addReg(CondReg).addReg(TempReg); + updateValueMap(I, ResultReg); + return true; +} + // Attempt to fast-select a floating-point truncate instruction. bool MipsFastISel::selectFPTrunc(const Instruction *I) { if (UnsupportedFPMode) @@ -775,7 +1100,9 @@ bool MipsFastISel::processCallArgs(CallLoweringInfo &CLI, } } } - if (((ArgVT == MVT::i32) || (ArgVT == MVT::f32)) && VA.isMemLoc()) { + if (((ArgVT == MVT::i32) || (ArgVT == MVT::f32) || (ArgVT == MVT::i16) || + (ArgVT == MVT::i8)) && + VA.isMemLoc()) { switch (VA.getLocMemOffset()) { case 0: VA.convertToReg(Mips::A0); @@ -889,6 +1216,8 @@ bool MipsFastISel::finishCall(CallLoweringInfo &CLI, MVT RetVT, CopyVT = MVT::i32; unsigned ResultReg = createResultReg(TLI.getRegClassFor(CopyVT)); + if (!ResultReg) + return false; BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(TargetOpcode::COPY), ResultReg).addReg(RVLocs[0].getLocReg()); @@ -905,7 +1234,7 @@ bool MipsFastISel::fastLowerCall(CallLoweringInfo &CLI) { bool IsTailCall = CLI.IsTailCall; bool IsVarArg = CLI.IsVarArg; const Value *Callee = CLI.Callee; - // const char *SymName = CLI.SymName; + const char *SymName = CLI.SymName; // Allow SelectionDAG isel to handle tail calls. if (IsTailCall) @@ -919,7 +1248,7 @@ bool MipsFastISel::fastLowerCall(CallLoweringInfo &CLI) { MVT RetVT; if (CLI.RetTy->isVoidTy()) RetVT = MVT::isVoid; - else if (!isTypeLegal(CLI.RetTy, RetVT)) + else if (!isTypeSupported(CLI.RetTy, RetVT)) return false; for (auto Flag : CLI.OutFlags) @@ -952,8 +1281,15 @@ bool MipsFastISel::fastLowerCall(CallLoweringInfo &CLI) { if (!processCallArgs(CLI, OutVTs, NumBytes)) return false; + if (!Addr.getGlobalValue()) + return false; + // Issue the call. - unsigned DestAddress = materializeGV(Addr.getGlobalValue(), MVT::i32); + unsigned DestAddress; + if (SymName) + DestAddress = materializeExternalCallSym(SymName); + else + DestAddress = materializeGV(Addr.getGlobalValue(), MVT::i32); emitInst(TargetOpcode::COPY, Mips::T9).addReg(DestAddress); MachineInstrBuilder MIB = BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::JALR), @@ -965,32 +1301,188 @@ bool MipsFastISel::fastLowerCall(CallLoweringInfo &CLI) { // Add a register mask with the call-preserved registers. // Proper defs for return values will be added by setPhysRegsDeadExcept(). - MIB.addRegMask(TRI.getCallPreservedMask(CC)); + MIB.addRegMask(TRI.getCallPreservedMask(*FuncInfo.MF, CC)); CLI.Call = MIB; - // Add implicit physical register uses to the call. - for (auto Reg : CLI.OutRegs) - MIB.addReg(Reg, RegState::Implicit); - - // Add a register mask with the call-preserved registers. Proper - // defs for return values will be added by setPhysRegsDeadExcept(). - MIB.addRegMask(TRI.getCallPreservedMask(CC)); - - CLI.Call = MIB; // Finish off the call including any return values. return finishCall(CLI, RetVT, NumBytes); } +bool MipsFastISel::fastLowerIntrinsicCall(const IntrinsicInst *II) { + switch (II->getIntrinsicID()) { + default: + return false; + case Intrinsic::bswap: { + Type *RetTy = II->getCalledFunction()->getReturnType(); + + MVT VT; + if (!isTypeSupported(RetTy, VT)) + return false; + + unsigned SrcReg = getRegForValue(II->getOperand(0)); + if (SrcReg == 0) + return false; + unsigned DestReg = createResultReg(&Mips::GPR32RegClass); + if (DestReg == 0) + return false; + if (VT == MVT::i16) { + if (Subtarget->hasMips32r2()) { + emitInst(Mips::WSBH, DestReg).addReg(SrcReg); + updateValueMap(II, DestReg); + return true; + } else { + unsigned TempReg[3]; + for (int i = 0; i < 3; i++) { + TempReg[i] = createResultReg(&Mips::GPR32RegClass); + if (TempReg[i] == 0) + return false; + } + emitInst(Mips::SLL, TempReg[0]).addReg(SrcReg).addImm(8); + emitInst(Mips::SRL, TempReg[1]).addReg(SrcReg).addImm(8); + emitInst(Mips::OR, TempReg[2]).addReg(TempReg[0]).addReg(TempReg[1]); + emitInst(Mips::ANDi, DestReg).addReg(TempReg[2]).addImm(0xFFFF); + updateValueMap(II, DestReg); + return true; + } + } else if (VT == MVT::i32) { + if (Subtarget->hasMips32r2()) { + unsigned TempReg = createResultReg(&Mips::GPR32RegClass); + emitInst(Mips::WSBH, TempReg).addReg(SrcReg); + emitInst(Mips::ROTR, DestReg).addReg(TempReg).addImm(16); + updateValueMap(II, DestReg); + return true; + } else { + unsigned TempReg[8]; + for (int i = 0; i < 8; i++) { + TempReg[i] = createResultReg(&Mips::GPR32RegClass); + if (TempReg[i] == 0) + return false; + } + + emitInst(Mips::SRL, TempReg[0]).addReg(SrcReg).addImm(8); + emitInst(Mips::SRL, TempReg[1]).addReg(SrcReg).addImm(24); + emitInst(Mips::ANDi, TempReg[2]).addReg(TempReg[0]).addImm(0xFF00); + emitInst(Mips::OR, TempReg[3]).addReg(TempReg[1]).addReg(TempReg[2]); + + emitInst(Mips::ANDi, TempReg[4]).addReg(SrcReg).addImm(0xFF00); + emitInst(Mips::SLL, TempReg[5]).addReg(TempReg[4]).addImm(8); + + emitInst(Mips::SLL, TempReg[6]).addReg(SrcReg).addImm(24); + emitInst(Mips::OR, TempReg[7]).addReg(TempReg[3]).addReg(TempReg[5]); + emitInst(Mips::OR, DestReg).addReg(TempReg[6]).addReg(TempReg[7]); + updateValueMap(II, DestReg); + return true; + } + } + return false; + } + case Intrinsic::memcpy: + case Intrinsic::memmove: { + const auto *MTI = cast<MemTransferInst>(II); + // Don't handle volatile. + if (MTI->isVolatile()) + return false; + if (!MTI->getLength()->getType()->isIntegerTy(32)) + return false; + const char *IntrMemName = isa<MemCpyInst>(II) ? "memcpy" : "memmove"; + return lowerCallTo(II, IntrMemName, II->getNumArgOperands() - 2); + } + case Intrinsic::memset: { + const MemSetInst *MSI = cast<MemSetInst>(II); + // Don't handle volatile. + if (MSI->isVolatile()) + return false; + if (!MSI->getLength()->getType()->isIntegerTy(32)) + return false; + return lowerCallTo(II, "memset", II->getNumArgOperands() - 2); + } + } + return false; +} + bool MipsFastISel::selectRet(const Instruction *I) { + const Function &F = *I->getParent()->getParent(); const ReturnInst *Ret = cast<ReturnInst>(I); if (!FuncInfo.CanLowerReturn) return false; + + // Build a list of return value registers. + SmallVector<unsigned, 4> RetRegs; + if (Ret->getNumOperands() > 0) { - return false; + CallingConv::ID CC = F.getCallingConv(); + SmallVector<ISD::OutputArg, 4> Outs; + GetReturnInfo(F.getReturnType(), F.getAttributes(), Outs, TLI); + // Analyze operands of the call, assigning locations to each operand. + SmallVector<CCValAssign, 16> ValLocs; + MipsCCState CCInfo(CC, F.isVarArg(), *FuncInfo.MF, ValLocs, + I->getContext()); + CCAssignFn *RetCC = RetCC_Mips; + CCInfo.AnalyzeReturn(Outs, RetCC); + + // Only handle a single return value for now. + if (ValLocs.size() != 1) + return false; + + CCValAssign &VA = ValLocs[0]; + const Value *RV = Ret->getOperand(0); + + // Don't bother handling odd stuff for now. + if ((VA.getLocInfo() != CCValAssign::Full) && + (VA.getLocInfo() != CCValAssign::BCvt)) + return false; + + // Only handle register returns for now. + if (!VA.isRegLoc()) + return false; + + unsigned Reg = getRegForValue(RV); + if (Reg == 0) + return false; + + unsigned SrcReg = Reg + VA.getValNo(); + unsigned DestReg = VA.getLocReg(); + // Avoid a cross-class copy. This is very unlikely. + if (!MRI.getRegClass(SrcReg)->contains(DestReg)) + return false; + + EVT RVEVT = TLI.getValueType(RV->getType()); + if (!RVEVT.isSimple()) + return false; + + if (RVEVT.isVector()) + return false; + + MVT RVVT = RVEVT.getSimpleVT(); + if (RVVT == MVT::f128) + return false; + + MVT DestVT = VA.getValVT(); + // Special handling for extended integers. + if (RVVT != DestVT) { + if (RVVT != MVT::i1 && RVVT != MVT::i8 && RVVT != MVT::i16) + return false; + + if (Outs[0].Flags.isZExt() || Outs[0].Flags.isSExt()) { + bool IsZExt = Outs[0].Flags.isZExt(); + SrcReg = emitIntExt(RVVT, SrcReg, DestVT, IsZExt); + if (SrcReg == 0) + return false; + } + } + + // Make the copy. + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, + TII.get(TargetOpcode::COPY), DestReg).addReg(SrcReg); + + // Add register to return instruction. + RetRegs.push_back(VA.getLocReg()); } - emitInst(Mips::RetRA); + MachineInstrBuilder MIB = emitInst(Mips::RetRA); + for (unsigned i = 0, e = RetRegs.size(); i != e; ++i) + MIB.addReg(RetRegs[i], RegState::Implicit); return true; } @@ -1107,6 +1599,13 @@ bool MipsFastISel::emitIntZExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, bool MipsFastISel::emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, unsigned DestReg, bool IsZExt) { + // FastISel does not have plumbing to deal with extensions where the SrcVT or + // DestVT are odd things, so test to make sure that they are both types we can + // handle (i1/i8/i16/i32 for SrcVT and i8/i16/i32/i64 for DestVT), otherwise + // bail out to SelectionDAG. + if (((DestVT != MVT::i8) && (DestVT != MVT::i16) && (DestVT != MVT::i32)) || + ((SrcVT != MVT::i1) && (SrcVT != MVT::i8) && (SrcVT != MVT::i16))) + return false; if (IsZExt) return emitIntZExt(SrcVT, SrcReg, DestVT, DestReg); return emitIntSExt(SrcVT, SrcReg, DestVT, DestReg); @@ -1115,7 +1614,127 @@ bool MipsFastISel::emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, unsigned MipsFastISel::emitIntExt(MVT SrcVT, unsigned SrcReg, MVT DestVT, bool isZExt) { unsigned DestReg = createResultReg(&Mips::GPR32RegClass); - return emitIntExt(SrcVT, SrcReg, DestVT, DestReg, isZExt); + bool Success = emitIntExt(SrcVT, SrcReg, DestVT, DestReg, isZExt); + return Success ? DestReg : 0; +} + +bool MipsFastISel::selectDivRem(const Instruction *I, unsigned ISDOpcode) { + EVT DestEVT = TLI.getValueType(I->getType(), true); + if (!DestEVT.isSimple()) + return false; + + MVT DestVT = DestEVT.getSimpleVT(); + if (DestVT != MVT::i32) + return false; + + unsigned DivOpc; + switch (ISDOpcode) { + default: + return false; + case ISD::SDIV: + case ISD::SREM: + DivOpc = Mips::SDIV; + break; + case ISD::UDIV: + case ISD::UREM: + DivOpc = Mips::UDIV; + break; + } + + unsigned Src0Reg = getRegForValue(I->getOperand(0)); + unsigned Src1Reg = getRegForValue(I->getOperand(1)); + if (!Src0Reg || !Src1Reg) + return false; + + emitInst(DivOpc).addReg(Src0Reg).addReg(Src1Reg); + emitInst(Mips::TEQ).addReg(Src1Reg).addReg(Mips::ZERO).addImm(7); + + unsigned ResultReg = createResultReg(&Mips::GPR32RegClass); + if (!ResultReg) + return false; + + unsigned MFOpc = (ISDOpcode == ISD::SREM || ISDOpcode == ISD::UREM) + ? Mips::MFHI + : Mips::MFLO; + emitInst(MFOpc, ResultReg); + + updateValueMap(I, ResultReg); + return true; +} + +bool MipsFastISel::selectShift(const Instruction *I) { + MVT RetVT; + + if (!isTypeSupported(I->getType(), RetVT)) + return false; + + unsigned ResultReg = createResultReg(&Mips::GPR32RegClass); + if (!ResultReg) + return false; + + unsigned Opcode = I->getOpcode(); + const Value *Op0 = I->getOperand(0); + unsigned Op0Reg = getRegForValue(Op0); + if (!Op0Reg) + return false; + + // If AShr or LShr, then we need to make sure the operand0 is sign extended. + if (Opcode == Instruction::AShr || Opcode == Instruction::LShr) { + unsigned TempReg = createResultReg(&Mips::GPR32RegClass); + if (!TempReg) + return false; + + MVT Op0MVT = TLI.getValueType(Op0->getType(), true).getSimpleVT(); + bool IsZExt = Opcode == Instruction::LShr; + if (!emitIntExt(Op0MVT, Op0Reg, MVT::i32, TempReg, IsZExt)) + return false; + + Op0Reg = TempReg; + } + + if (const auto *C = dyn_cast<ConstantInt>(I->getOperand(1))) { + uint64_t ShiftVal = C->getZExtValue(); + + switch (Opcode) { + default: + llvm_unreachable("Unexpected instruction."); + case Instruction::Shl: + Opcode = Mips::SLL; + break; + case Instruction::AShr: + Opcode = Mips::SRA; + break; + case Instruction::LShr: + Opcode = Mips::SRL; + break; + } + + emitInst(Opcode, ResultReg).addReg(Op0Reg).addImm(ShiftVal); + updateValueMap(I, ResultReg); + return true; + } + + unsigned Op1Reg = getRegForValue(I->getOperand(1)); + if (!Op1Reg) + return false; + + switch (Opcode) { + default: + llvm_unreachable("Unexpected instruction."); + case Instruction::Shl: + Opcode = Mips::SLLV; + break; + case Instruction::AShr: + Opcode = Mips::SRAV; + break; + case Instruction::LShr: + Opcode = Mips::SRLV; + break; + } + + emitInst(Opcode, ResultReg).addReg(Op0Reg).addReg(Op1Reg); + updateValueMap(I, ResultReg); + return true; } bool MipsFastISel::fastSelectInstruction(const Instruction *I) { @@ -1128,6 +1747,30 @@ bool MipsFastISel::fastSelectInstruction(const Instruction *I) { return selectLoad(I); case Instruction::Store: return selectStore(I); + case Instruction::SDiv: + if (!selectBinaryOp(I, ISD::SDIV)) + return selectDivRem(I, ISD::SDIV); + return true; + case Instruction::UDiv: + if (!selectBinaryOp(I, ISD::UDIV)) + return selectDivRem(I, ISD::UDIV); + return true; + case Instruction::SRem: + if (!selectBinaryOp(I, ISD::SREM)) + return selectDivRem(I, ISD::SREM); + return true; + case Instruction::URem: + if (!selectBinaryOp(I, ISD::UREM)) + return selectDivRem(I, ISD::UREM); + return true; + case Instruction::Shl: + case Instruction::LShr: + case Instruction::AShr: + return selectShift(I); + case Instruction::And: + case Instruction::Or: + case Instruction::Xor: + return selectLogicalOp(I); case Instruction::Br: return selectBranch(I); case Instruction::Ret: @@ -1148,6 +1791,8 @@ bool MipsFastISel::fastSelectInstruction(const Instruction *I) { case Instruction::ICmp: case Instruction::FCmp: return selectCmp(I); + case Instruction::Select: + return selectSelect(I); } return false; } @@ -1167,6 +1812,44 @@ unsigned MipsFastISel::getRegEnsuringSimpleIntegerWidening(const Value *V, return VReg; } +void MipsFastISel::simplifyAddress(Address &Addr) { + if (!isInt<16>(Addr.getOffset())) { + unsigned TempReg = + materialize32BitInt(Addr.getOffset(), &Mips::GPR32RegClass); + unsigned DestReg = createResultReg(&Mips::GPR32RegClass); + emitInst(Mips::ADDu, DestReg).addReg(TempReg).addReg(Addr.getReg()); + Addr.setReg(DestReg); + Addr.setOffset(0); + } +} + +unsigned MipsFastISel::fastEmitInst_rr(unsigned MachineInstOpcode, + const TargetRegisterClass *RC, + unsigned Op0, bool Op0IsKill, + unsigned Op1, bool Op1IsKill) { + // We treat the MUL instruction in a special way because it clobbers + // the HI0 & LO0 registers. The TableGen definition of this instruction can + // mark these registers only as implicitly defined. As a result, the + // register allocator runs out of registers when this instruction is + // followed by another instruction that defines the same registers too. + // We can fix this by explicitly marking those registers as dead. + if (MachineInstOpcode == Mips::MUL) { + unsigned ResultReg = createResultReg(RC); + const MCInstrDesc &II = TII.get(MachineInstOpcode); + Op0 = constrainOperandRegClass(II, Op0, II.getNumDefs()); + Op1 = constrainOperandRegClass(II, Op1, II.getNumDefs() + 1); + BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, II, ResultReg) + .addReg(Op0, getKillRegState(Op0IsKill)) + .addReg(Op1, getKillRegState(Op1IsKill)) + .addReg(Mips::HI0, RegState::ImplicitDefine | RegState::Dead) + .addReg(Mips::LO0, RegState::ImplicitDefine | RegState::Dead); + return ResultReg; + } + + return FastISel::fastEmitInst_rr(MachineInstOpcode, RC, Op0, Op0IsKill, Op1, + Op1IsKill); +} + namespace llvm { FastISel *Mips::createFastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo) { diff --git a/contrib/llvm/lib/Target/Mips/MipsFrameLowering.cpp b/contrib/llvm/lib/Target/Mips/MipsFrameLowering.cpp index 3014a0d..a74c8ab 100644 --- a/contrib/llvm/lib/Target/Mips/MipsFrameLowering.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsFrameLowering.cpp @@ -90,17 +90,28 @@ const MipsFrameLowering *MipsFrameLowering::create(const MipsSubtarget &ST) { } // hasFP - Return true if the specified function should have a dedicated frame -// pointer register. This is true if the function has variable sized allocas or -// if frame pointer elimination is disabled. +// pointer register. This is true if the function has variable sized allocas, +// if it needs dynamic stack realignment, if frame pointer elimination is +// disabled, or if the frame address is taken. bool MipsFrameLowering::hasFP(const MachineFunction &MF) const { const MachineFrameInfo *MFI = MF.getFrameInfo(); + const TargetRegisterInfo *TRI = STI.getRegisterInfo(); + return MF.getTarget().Options.DisableFramePointerElim(MF) || - MFI->hasVarSizedObjects() || MFI->isFrameAddressTaken(); + MFI->hasVarSizedObjects() || MFI->isFrameAddressTaken() || + TRI->needsStackRealignment(MF); +} + +bool MipsFrameLowering::hasBP(const MachineFunction &MF) const { + const MachineFrameInfo *MFI = MF.getFrameInfo(); + const TargetRegisterInfo *TRI = STI.getRegisterInfo(); + + return MFI->hasVarSizedObjects() && TRI->needsStackRealignment(MF); } uint64_t MipsFrameLowering::estimateStackSize(const MachineFunction &MF) const { const MachineFrameInfo *MFI = MF.getFrameInfo(); - const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo(); + const TargetRegisterInfo &TRI = *STI.getRegisterInfo(); int64_t Offset = 0; @@ -131,3 +142,20 @@ uint64_t MipsFrameLowering::estimateStackSize(const MachineFunction &MF) const { return RoundUpToAlignment(Offset, getStackAlignment()); } + +// Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions +void MipsFrameLowering:: +eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const { + unsigned SP = STI.getABI().IsN64() ? Mips::SP_64 : Mips::SP; + + if (!hasReservedCallFrame(MF)) { + int64_t Amount = I->getOperand(0).getImm(); + if (I->getOpcode() == Mips::ADJCALLSTACKDOWN) + Amount = -Amount; + + STI.getInstrInfo()->adjustStackPtr(SP, Amount, MBB, I); + } + + MBB.erase(I); +} diff --git a/contrib/llvm/lib/Target/Mips/MipsFrameLowering.h b/contrib/llvm/lib/Target/Mips/MipsFrameLowering.h index 90a8d2a..5eabd58 100644 --- a/contrib/llvm/lib/Target/Mips/MipsFrameLowering.h +++ b/contrib/llvm/lib/Target/Mips/MipsFrameLowering.h @@ -32,6 +32,15 @@ public: bool hasFP(const MachineFunction &MF) const override; + bool hasBP(const MachineFunction &MF) const; + + bool isFPCloseToIncomingSP() const override { return false; } + + void + eliminateCallFramePseudoInstr(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const override; + protected: uint64_t estimateStackSize(const MachineFunction &MF) const; }; diff --git a/contrib/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp b/contrib/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp index 0bdabf3..2c9868a 100644 --- a/contrib/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsISelDAGToDAG.cpp @@ -47,7 +47,7 @@ using namespace llvm; //===----------------------------------------------------------------------===// bool MipsDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { - Subtarget = &TM.getSubtarget<MipsSubtarget>(); + Subtarget = &static_cast<const MipsSubtarget &>(MF.getSubtarget()); bool Ret = SelectionDAGISel::runOnMachineFunction(MF); processFunctionAfterISel(MF); @@ -95,6 +95,12 @@ bool MipsDAGToDAGISel::selectIntAddrMM(SDValue Addr, SDValue &Base, return false; } +bool MipsDAGToDAGISel::selectIntAddrLSL2MM(SDValue Addr, SDValue &Base, + SDValue &Offset) const { + llvm_unreachable("Unimplemented function."); + return false; +} + bool MipsDAGToDAGISel::selectIntAddrMSA(SDValue Addr, SDValue &Base, SDValue &Offset) const { llvm_unreachable("Unimplemented function."); @@ -107,7 +113,8 @@ bool MipsDAGToDAGISel::selectAddr16(SDNode *Parent, SDValue N, SDValue &Base, return false; } -bool MipsDAGToDAGISel::selectVSplat(SDNode *N, APInt &Imm) const { +bool MipsDAGToDAGISel::selectVSplat(SDNode *N, APInt &Imm, + unsigned MinSizeInBits) const { llvm_unreachable("Unimplemented function."); return false; } @@ -224,18 +231,18 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { } bool MipsDAGToDAGISel:: -SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, +SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, std::vector<SDValue> &OutOps) { - assert(ConstraintCode == 'm' && "unexpected asm memory constraint"); - OutOps.push_back(Op); - return false; -} - -/// createMipsISelDag - This pass converts a legalized DAG into a -/// MIPS-specific DAG, ready for instruction scheduling. -FunctionPass *llvm::createMipsISelDag(MipsTargetMachine &TM) { - if (TM.getSubtargetImpl()->inMips16Mode()) - return llvm::createMips16ISelDag(TM); - - return llvm::createMipsSEISelDag(TM); + // All memory constraints can at least accept raw pointers. + switch(ConstraintID) { + default: + llvm_unreachable("Unexpected asm memory constraint"); + case InlineAsm::Constraint_i: + case InlineAsm::Constraint_m: + case InlineAsm::Constraint_R: + case InlineAsm::Constraint_ZC: + OutOps.push_back(Op); + return false; + } + return true; } diff --git a/contrib/llvm/lib/Target/Mips/MipsISelDAGToDAG.h b/contrib/llvm/lib/Target/Mips/MipsISelDAGToDAG.h index ff8760d..1426d0f 100644 --- a/contrib/llvm/lib/Target/Mips/MipsISelDAGToDAG.h +++ b/contrib/llvm/lib/Target/Mips/MipsISelDAGToDAG.h @@ -73,6 +73,9 @@ private: virtual bool selectIntAddrMM(SDValue Addr, SDValue &Base, SDValue &Offset) const; + virtual bool selectIntAddrLSL2MM(SDValue Addr, SDValue &Base, + SDValue &Offset) const; + /// Match addr+simm10 and addr virtual bool selectIntAddrMSA(SDValue Addr, SDValue &Base, SDValue &Offset) const; @@ -81,7 +84,8 @@ private: SDValue &Offset, SDValue &Alias); /// \brief Select constant vector splats. - virtual bool selectVSplat(SDNode *N, APInt &Imm) const; + virtual bool selectVSplat(SDNode *N, APInt &Imm, + unsigned MinSizeInBits) const; /// \brief Select constant vector splats whose value fits in a uimm1. virtual bool selectVSplatUimm1(SDValue N, SDValue &Imm) const; /// \brief Select constant vector splats whose value fits in a uimm2. @@ -116,20 +120,15 @@ private: // getImm - Return a target constant with the specified value. inline SDValue getImm(const SDNode *Node, uint64_t Imm) { - return CurDAG->getTargetConstant(Imm, Node->getValueType(0)); + return CurDAG->getTargetConstant(Imm, SDLoc(Node), Node->getValueType(0)); } virtual void processFunctionAfterISel(MachineFunction &MF) = 0; bool SelectInlineAsmMemoryOperand(const SDValue &Op, - char ConstraintCode, + unsigned ConstraintID, std::vector<SDValue> &OutOps) override; }; - -/// createMipsISelDag - This pass converts a legalized DAG into a -/// MIPS-specific DAG, ready for instruction scheduling. -FunctionPass *createMipsISelDag(MipsTargetMachine &TM); - } #endif diff --git a/contrib/llvm/lib/Target/Mips/MipsISelLowering.cpp b/contrib/llvm/lib/Target/Mips/MipsISelLowering.cpp index 37fc784..67ddcc4 100644 --- a/contrib/llvm/lib/Target/Mips/MipsISelLowering.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -70,7 +70,7 @@ static bool isShiftedMask(uint64_t I, uint64_t &Pos, uint64_t &Size) { if (!isShiftedMask_64(I)) return false; - Size = CountPopulation_64(I); + Size = countPopulation(I); Pos = countTrailingZeros(I); return true; } @@ -112,7 +112,8 @@ SDValue MipsTargetLowering::getTargetNode(ConstantPoolSDNode *N, EVT Ty, } const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { - switch (Opcode) { + switch ((MipsISD::NodeType)Opcode) { + case MipsISD::FIRST_NUMBER: break; case MipsISD::JmpLink: return "MipsISD::JmpLink"; case MipsISD::TailCall: return "MipsISD::TailCall"; case MipsISD::Hi: return "MipsISD::Hi"; @@ -142,6 +143,7 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { case MipsISD::BuildPairF64: return "MipsISD::BuildPairF64"; case MipsISD::ExtractElementF64: return "MipsISD::ExtractElementF64"; case MipsISD::Wrapper: return "MipsISD::Wrapper"; + case MipsISD::DynAlloc: return "MipsISD::DynAlloc"; case MipsISD::Sync: return "MipsISD::Sync"; case MipsISD::Ext: return "MipsISD::Ext"; case MipsISD::Ins: return "MipsISD::Ins"; @@ -161,6 +163,28 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { case MipsISD::EXTR_RS_W: return "MipsISD::EXTR_RS_W"; case MipsISD::SHILO: return "MipsISD::SHILO"; case MipsISD::MTHLIP: return "MipsISD::MTHLIP"; + case MipsISD::MULSAQ_S_W_PH: return "MipsISD::MULSAQ_S_W_PH"; + case MipsISD::MAQ_S_W_PHL: return "MipsISD::MAQ_S_W_PHL"; + case MipsISD::MAQ_S_W_PHR: return "MipsISD::MAQ_S_W_PHR"; + case MipsISD::MAQ_SA_W_PHL: return "MipsISD::MAQ_SA_W_PHL"; + case MipsISD::MAQ_SA_W_PHR: return "MipsISD::MAQ_SA_W_PHR"; + case MipsISD::DPAU_H_QBL: return "MipsISD::DPAU_H_QBL"; + case MipsISD::DPAU_H_QBR: return "MipsISD::DPAU_H_QBR"; + case MipsISD::DPSU_H_QBL: return "MipsISD::DPSU_H_QBL"; + case MipsISD::DPSU_H_QBR: return "MipsISD::DPSU_H_QBR"; + case MipsISD::DPAQ_S_W_PH: return "MipsISD::DPAQ_S_W_PH"; + case MipsISD::DPSQ_S_W_PH: return "MipsISD::DPSQ_S_W_PH"; + case MipsISD::DPAQ_SA_L_W: return "MipsISD::DPAQ_SA_L_W"; + case MipsISD::DPSQ_SA_L_W: return "MipsISD::DPSQ_SA_L_W"; + case MipsISD::DPA_W_PH: return "MipsISD::DPA_W_PH"; + case MipsISD::DPS_W_PH: return "MipsISD::DPS_W_PH"; + case MipsISD::DPAQX_S_W_PH: return "MipsISD::DPAQX_S_W_PH"; + case MipsISD::DPAQX_SA_W_PH: return "MipsISD::DPAQX_SA_W_PH"; + case MipsISD::DPAX_W_PH: return "MipsISD::DPAX_W_PH"; + case MipsISD::DPSX_W_PH: return "MipsISD::DPSX_W_PH"; + case MipsISD::DPSQX_S_W_PH: return "MipsISD::DPSQX_S_W_PH"; + case MipsISD::DPSQX_SA_W_PH: return "MipsISD::DPSQX_SA_W_PH"; + case MipsISD::MULSA_W_PH: return "MipsISD::MULSA_W_PH"; case MipsISD::MULT: return "MipsISD::MULT"; case MipsISD::MULTU: return "MipsISD::MULTU"; case MipsISD::MADD_DSP: return "MipsISD::MADD_DSP"; @@ -197,13 +221,13 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { case MipsISD::PCKEV: return "MipsISD::PCKEV"; case MipsISD::PCKOD: return "MipsISD::PCKOD"; case MipsISD::INSVE: return "MipsISD::INSVE"; - default: return nullptr; } + return nullptr; } MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, const MipsSubtarget &STI) - : TargetLowering(TM), Subtarget(STI) { + : TargetLowering(TM), Subtarget(STI), ABI(TM.getABI()) { // Mips does not have i1 type, so use i32 for // setcc operations results (slt, sgt, ...). setBooleanContents(ZeroOrOneBooleanContent); @@ -221,9 +245,23 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, setLoadExtAction(ISD::SEXTLOAD, VT, MVT::i1, Promote); } - // MIPS doesn't have extending float->double load/store - for (MVT VT : MVT::fp_valuetypes()) + // MIPS doesn't have extending float->double load/store. Set LoadExtAction + // for f32, f16 + for (MVT VT : MVT::fp_valuetypes()) { setLoadExtAction(ISD::EXTLOAD, VT, MVT::f32, Expand); + setLoadExtAction(ISD::EXTLOAD, VT, MVT::f16, Expand); + } + + // Set LoadExtAction for f16 vectors to Expand + for (MVT VT : MVT::fp_vector_valuetypes()) { + MVT F16VT = MVT::getVectorVT(MVT::f16, VT.getVectorNumElements()); + if (F16VT.isValid()) + setLoadExtAction(ISD::EXTLOAD, VT, F16VT, Expand); + } + + setTruncStoreAction(MVT::f32, MVT::f16, Expand); + setTruncStoreAction(MVT::f64, MVT::f16, Expand); + setTruncStoreAction(MVT::f64, MVT::f32, Expand); // Used by legalize types to correctly generate the setcc result. @@ -339,6 +377,12 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, setOperationAction(ISD::FREM, MVT::f32, Expand); setOperationAction(ISD::FREM, MVT::f64, Expand); + // Lower f16 conversion operations into library calls + setOperationAction(ISD::FP16_TO_FP, MVT::f32, Expand); + setOperationAction(ISD::FP_TO_FP16, MVT::f32, Expand); + setOperationAction(ISD::FP16_TO_FP, MVT::f64, Expand); + setOperationAction(ISD::FP_TO_FP16, MVT::f64, Expand); + setOperationAction(ISD::EH_RETURN, MVT::Other, Custom); setOperationAction(ISD::VASTART, MVT::Other, Custom); @@ -393,14 +437,12 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, // The arguments on the stack are defined in terms of 4-byte slots on O32 // and 8-byte slots on N32/N64. - setMinStackArgumentAlignment( - (Subtarget.isABI_N32() || Subtarget.isABI_N64()) ? 8 : 4); + setMinStackArgumentAlignment((ABI.IsN32() || ABI.IsN64()) ? 8 : 4); - setStackPointerRegisterToSaveRestore(Subtarget.isABI_N64() ? Mips::SP_64 - : Mips::SP); + setStackPointerRegisterToSaveRestore(ABI.IsN64() ? Mips::SP_64 : Mips::SP); - setExceptionPointerRegister(Subtarget.isABI_N64() ? Mips::A0_64 : Mips::A0); - setExceptionSelectorRegister(Subtarget.isABI_N64() ? Mips::A1_64 : Mips::A1); + setExceptionPointerRegister(ABI.IsN64() ? Mips::A0_64 : Mips::A0); + setExceptionSelectorRegister(ABI.IsN64() ? Mips::A1_64 : Mips::A1); MaxStoresPerMemcpy = 16; @@ -526,7 +568,7 @@ static SDValue createFPCmp(SelectionDAG &DAG, const SDValue &Op) { ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get(); return DAG.getNode(MipsISD::FPCmp, DL, MVT::Glue, LHS, RHS, - DAG.getConstant(condCodeToFCC(CC), MVT::i32)); + DAG.getConstant(condCodeToFCC(CC), DL, MVT::i32)); } // Creates and returns a CMovFPT/F node. @@ -681,9 +723,11 @@ static SDValue performANDCombine(SDNode *N, SelectionDAG &DAG, if (SMPos != 0 || Pos + SMSize > ValTy.getSizeInBits()) return SDValue(); - return DAG.getNode(MipsISD::Ext, SDLoc(N), ValTy, - ShiftRight.getOperand(0), DAG.getConstant(Pos, MVT::i32), - DAG.getConstant(SMSize, MVT::i32)); + SDLoc DL(N); + return DAG.getNode(MipsISD::Ext, DL, ValTy, + ShiftRight.getOperand(0), + DAG.getConstant(Pos, DL, MVT::i32), + DAG.getConstant(SMSize, DL, MVT::i32)); } static SDValue performORCombine(SDNode *N, SelectionDAG &DAG, @@ -735,9 +779,11 @@ static SDValue performORCombine(SDNode *N, SelectionDAG &DAG, if ((Shamt != SMPos0) || (SMPos0 + SMSize0 > ValTy.getSizeInBits())) return SDValue(); - return DAG.getNode(MipsISD::Ins, SDLoc(N), ValTy, Shl.getOperand(0), - DAG.getConstant(SMPos0, MVT::i32), - DAG.getConstant(SMSize0, MVT::i32), And0.getOperand(0)); + SDLoc DL(N); + return DAG.getNode(MipsISD::Ins, DL, ValTy, Shl.getOperand(0), + DAG.getConstant(SMPos0, DL, MVT::i32), + DAG.getConstant(SMSize0, DL, MVT::i32), + And0.getOperand(0)); } static SDValue performADDCombine(SDNode *N, SelectionDAG &DAG, @@ -969,16 +1015,14 @@ MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, case Mips::DIVU: case Mips::MOD: case Mips::MODU: - return insertDivByZeroTrap( - MI, *BB, *getTargetMachine().getSubtargetImpl()->getInstrInfo(), false); + return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), false); case Mips::PseudoDSDIV: case Mips::PseudoDUDIV: case Mips::DDIV: case Mips::DDIVU: case Mips::DMOD: case Mips::DMODU: - return insertDivByZeroTrap( - MI, *BB, *getTargetMachine().getSubtargetImpl()->getInstrInfo(), true); + return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), true); case Mips::SEL_D: return emitSEL_D(MI, BB); @@ -1014,8 +1058,7 @@ MipsTargetLowering::emitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB, MachineFunction *MF = BB->getParent(); MachineRegisterInfo &RegInfo = MF->getRegInfo(); const TargetRegisterClass *RC = getRegClassFor(MVT::getIntegerVT(Size * 8)); - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned LL, SC, AND, NOR, ZERO, BEQ; @@ -1098,8 +1141,7 @@ MipsTargetLowering::emitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB, MachineBasicBlock *MipsTargetLowering::emitSignExtendToI32InReg( MachineInstr *MI, MachineBasicBlock *BB, unsigned Size, unsigned DstReg, unsigned SrcReg) const { - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); DebugLoc DL = MI->getDebugLoc(); if (Subtarget.hasMips32r2() && Size == 1) { @@ -1135,8 +1177,7 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword( MachineFunction *MF = BB->getParent(); MachineRegisterInfo &RegInfo = MF->getRegInfo(); const TargetRegisterClass *RC = getRegClassFor(MVT::i32); - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned Dest = MI->getOperand(0).getReg(); @@ -1288,8 +1329,7 @@ MachineBasicBlock * MipsTargetLowering::emitAtomicCmpSwap(MachineInstr *MI, MachineFunction *MF = BB->getParent(); MachineRegisterInfo &RegInfo = MF->getRegInfo(); const TargetRegisterClass *RC = getRegClassFor(MVT::getIntegerVT(Size * 8)); - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned LL, SC, ZERO, BNE, BEQ; @@ -1371,8 +1411,7 @@ MipsTargetLowering::emitAtomicCmpSwapPartword(MachineInstr *MI, MachineFunction *MF = BB->getParent(); MachineRegisterInfo &RegInfo = MF->getRegInfo(); const TargetRegisterClass *RC = getRegClassFor(MVT::i32); - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned Dest = MI->getOperand(0).getReg(); @@ -1509,10 +1548,8 @@ MipsTargetLowering::emitAtomicCmpSwapPartword(MachineInstr *MI, MachineBasicBlock *MipsTargetLowering::emitSEL_D(MachineInstr *MI, MachineBasicBlock *BB) const { MachineFunction *MF = BB->getParent(); - const TargetRegisterInfo *TRI = - getTargetMachine().getSubtargetImpl()->getRegisterInfo(); - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineRegisterInfo &RegInfo = MF->getRegInfo(); DebugLoc DL = MI->getDebugLoc(); MachineBasicBlock::iterator II(MI); @@ -1547,7 +1584,7 @@ SDValue MipsTargetLowering::lowerBR_JT(SDValue Op, SelectionDAG &DAG) const { DAG.getMachineFunction().getJumpTableInfo()->getEntrySize(*getDataLayout()); Index = DAG.getNode(ISD::MUL, DL, PTy, Index, - DAG.getConstant(EntrySize, PTy)); + DAG.getConstant(EntrySize, DL, PTy)); SDValue Addr = DAG.getNode(ISD::ADD, DL, PTy, Index, Table); EVT MemVT = EVT::getIntegerVT(*DAG.getContext(), EntrySize * 8); @@ -1556,8 +1593,7 @@ SDValue MipsTargetLowering::lowerBR_JT(SDValue Op, SelectionDAG &DAG) const { false, 0); Chain = Addr.getValue(1); - if ((getTargetMachine().getRelocationModel() == Reloc::PIC_) || - Subtarget.isABI_N64()) { + if ((getTargetMachine().getRelocationModel() == Reloc::PIC_) || ABI.IsN64()) { // For PIC, the sequence is: // BRIND(load(Jumptable + index) + RelocBase) // RelocBase can be JumpTable, GOT or some sort of global base. @@ -1586,7 +1622,7 @@ SDValue MipsTargetLowering::lowerBRCOND(SDValue Op, SelectionDAG &DAG) const { Mips::CondCode CC = (Mips::CondCode)cast<ConstantSDNode>(CCNode)->getZExtValue(); unsigned Opc = invertFPCondCodeUser(CC) ? Mips::BRANCH_F : Mips::BRANCH_T; - SDValue BrCode = DAG.getConstant(Opc, MVT::i32); + SDValue BrCode = DAG.getConstant(Opc, DL, MVT::i32); SDValue FCC0 = DAG.getRegister(Mips::FCC0, MVT::i32); return DAG.getNode(MipsISD::FPBrcond, DL, Op.getValueType(), Chain, BrCode, FCC0, Dest, CondRes); @@ -1627,10 +1663,11 @@ SDValue MipsTargetLowering::lowerSETCC(SDValue Op, SelectionDAG &DAG) const { assert(Cond.getOpcode() == MipsISD::FPCmp && "Floating point operand expected."); - SDValue True = DAG.getConstant(1, MVT::i32); - SDValue False = DAG.getConstant(0, MVT::i32); + SDLoc DL(Op); + SDValue True = DAG.getConstant(1, DL, MVT::i32); + SDValue False = DAG.getConstant(0, DL, MVT::i32); - return createCMovFP(DAG, Cond, True, False, SDLoc(Op)); + return createCMovFP(DAG, Cond, True, False, DL); } SDValue MipsTargetLowering::lowerGlobalAddress(SDValue Op, @@ -1639,12 +1676,11 @@ SDValue MipsTargetLowering::lowerGlobalAddress(SDValue Op, GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op); const GlobalValue *GV = N->getGlobal(); - if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && - !Subtarget.isABI_N64()) { - const MipsTargetObjectFile &TLOF = - (const MipsTargetObjectFile&)getObjFileLowering(); - - if (TLOF.IsGlobalInSmallSection(GV, getTargetMachine())) + if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !ABI.IsN64()) { + const MipsTargetObjectFile *TLOF = + static_cast<const MipsTargetObjectFile *>( + getTargetMachine().getObjFileLowering()); + if (TLOF->IsGlobalInSmallSection(GV, getTargetMachine())) // %gp_rel relocation return getAddrGPRel(N, SDLoc(N), Ty, DAG); @@ -1653,8 +1689,7 @@ SDValue MipsTargetLowering::lowerGlobalAddress(SDValue Op, } if (GV->hasInternalLinkage() || (GV->hasLocalLinkage() && !isa<Function>(GV))) - return getAddrLocal(N, SDLoc(N), Ty, DAG, - Subtarget.isABI_N32() || Subtarget.isABI_N64()); + return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64()); if (LargeGOT) return getAddrGlobalLargeGOT(N, SDLoc(N), Ty, DAG, MipsII::MO_GOT_HI16, @@ -1662,9 +1697,8 @@ SDValue MipsTargetLowering::lowerGlobalAddress(SDValue Op, MachinePointerInfo::getGOT()); return getAddrGlobal(N, SDLoc(N), Ty, DAG, - (Subtarget.isABI_N32() || Subtarget.isABI_N64()) - ? MipsII::MO_GOT_DISP - : MipsII::MO_GOT16, + (ABI.IsN32() || ABI.IsN64()) ? MipsII::MO_GOT_DISP + : MipsII::MO_GOT16, DAG.getEntryNode(), MachinePointerInfo::getGOT()); } @@ -1673,12 +1707,10 @@ SDValue MipsTargetLowering::lowerBlockAddress(SDValue Op, BlockAddressSDNode *N = cast<BlockAddressSDNode>(Op); EVT Ty = Op.getValueType(); - if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && - !Subtarget.isABI_N64()) + if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !ABI.IsN64()) return getAddrNonPIC(N, SDLoc(N), Ty, DAG); - return getAddrLocal(N, SDLoc(N), Ty, DAG, - Subtarget.isABI_N32() || Subtarget.isABI_N64()); + return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64()); } SDValue MipsTargetLowering:: @@ -1766,12 +1798,10 @@ lowerJumpTable(SDValue Op, SelectionDAG &DAG) const JumpTableSDNode *N = cast<JumpTableSDNode>(Op); EVT Ty = Op.getValueType(); - if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && - !Subtarget.isABI_N64()) + if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !ABI.IsN64()) return getAddrNonPIC(N, SDLoc(N), Ty, DAG); - return getAddrLocal(N, SDLoc(N), Ty, DAG, - Subtarget.isABI_N32() || Subtarget.isABI_N64()); + return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64()); } SDValue MipsTargetLowering:: @@ -1780,20 +1810,19 @@ lowerConstantPool(SDValue Op, SelectionDAG &DAG) const ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op); EVT Ty = Op.getValueType(); - if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && - !Subtarget.isABI_N64()) { - const MipsTargetObjectFile &TLOF = - (const MipsTargetObjectFile&)getObjFileLowering(); + if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !ABI.IsN64()) { + const MipsTargetObjectFile *TLOF = + static_cast<const MipsTargetObjectFile *>( + getTargetMachine().getObjFileLowering()); - if (TLOF.IsConstantInSmallSection(N->getConstVal(), getTargetMachine())) + if (TLOF->IsConstantInSmallSection(N->getConstVal(), getTargetMachine())) // %gp_rel relocation return getAddrGPRel(N, SDLoc(N), Ty, DAG); return getAddrNonPIC(N, SDLoc(N), Ty, DAG); } - return getAddrLocal(N, SDLoc(N), Ty, DAG, - Subtarget.isABI_N32() || Subtarget.isABI_N64()); + return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64()); } SDValue MipsTargetLowering::lowerVASTART(SDValue Op, SelectionDAG &DAG) const { @@ -1819,8 +1848,7 @@ SDValue MipsTargetLowering::lowerVAARG(SDValue Op, SelectionDAG &DAG) const { unsigned Align = Node->getConstantOperandVal(3); const Value *SV = cast<SrcValueSDNode>(Node->getOperand(2))->getValue(); SDLoc DL(Node); - unsigned ArgSlotSizeInBytes = - (Subtarget.isABI_N32() || Subtarget.isABI_N64()) ? 8 : 4; + unsigned ArgSlotSizeInBytes = (ABI.IsN32() || ABI.IsN64()) ? 8 : 4; SDValue VAListLoad = DAG.getLoad(getPointerTy(), DL, Chain, VAListPtr, MachinePointerInfo(SV), false, false, false, @@ -1838,19 +1866,19 @@ SDValue MipsTargetLowering::lowerVAARG(SDValue Op, SelectionDAG &DAG) const { assert(((Align & (Align-1)) == 0) && "Expected Align to be a power of 2"); VAList = DAG.getNode(ISD::ADD, DL, VAList.getValueType(), VAList, - DAG.getConstant(Align - 1, - VAList.getValueType())); + DAG.getConstant(Align - 1, DL, VAList.getValueType())); VAList = DAG.getNode(ISD::AND, DL, VAList.getValueType(), VAList, - DAG.getConstant(-(int64_t)Align, + DAG.getConstant(-(int64_t)Align, DL, VAList.getValueType())); } // Increment the pointer, VAList, to the next vaarg. unsigned ArgSizeInBytes = getDataLayout()->getTypeAllocSize(VT.getTypeForEVT(*DAG.getContext())); SDValue Tmp3 = DAG.getNode(ISD::ADD, DL, VAList.getValueType(), VAList, - DAG.getConstant(RoundUpToAlignment(ArgSizeInBytes, ArgSlotSizeInBytes), - VAList.getValueType())); + DAG.getConstant(RoundUpToAlignment(ArgSizeInBytes, + ArgSlotSizeInBytes), + DL, VAList.getValueType())); // Store the incremented VAList to the legalized pointer Chain = DAG.getStore(VAListLoad.getValue(1), DL, Tmp3, VAListPtr, MachinePointerInfo(SV), false, false, 0); @@ -1863,7 +1891,7 @@ SDValue MipsTargetLowering::lowerVAARG(SDValue Op, SelectionDAG &DAG) const { if (!Subtarget.isLittle() && ArgSizeInBytes < ArgSlotSizeInBytes) { unsigned Adjustment = ArgSlotSizeInBytes - ArgSizeInBytes; VAList = DAG.getNode(ISD::ADD, DL, VAListPtr.getValueType(), VAList, - DAG.getIntPtrConstant(Adjustment)); + DAG.getIntPtrConstant(Adjustment, DL)); } // Load the actual argument out of the pointer VAList return DAG.getLoad(VT, DL, Chain, VAList, MachinePointerInfo(), false, false, @@ -1874,9 +1902,9 @@ static SDValue lowerFCOPYSIGN32(SDValue Op, SelectionDAG &DAG, bool HasExtractInsert) { EVT TyX = Op.getOperand(0).getValueType(); EVT TyY = Op.getOperand(1).getValueType(); - SDValue Const1 = DAG.getConstant(1, MVT::i32); - SDValue Const31 = DAG.getConstant(31, MVT::i32); SDLoc DL(Op); + SDValue Const1 = DAG.getConstant(1, DL, MVT::i32); + SDValue Const31 = DAG.getConstant(31, DL, MVT::i32); SDValue Res; // If operand is of type f64, extract the upper 32-bit. Otherwise, bitcast it @@ -1912,7 +1940,8 @@ static SDValue lowerFCOPYSIGN32(SDValue Op, SelectionDAG &DAG, return DAG.getNode(ISD::BITCAST, DL, Op.getOperand(0).getValueType(), Res); SDValue LowX = DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, - Op.getOperand(0), DAG.getConstant(0, MVT::i32)); + Op.getOperand(0), + DAG.getConstant(0, DL, MVT::i32)); return DAG.getNode(MipsISD::BuildPairF64, DL, MVT::f64, LowX, Res); } @@ -1921,8 +1950,8 @@ static SDValue lowerFCOPYSIGN64(SDValue Op, SelectionDAG &DAG, unsigned WidthX = Op.getOperand(0).getValueSizeInBits(); unsigned WidthY = Op.getOperand(1).getValueSizeInBits(); EVT TyX = MVT::getIntegerVT(WidthX), TyY = MVT::getIntegerVT(WidthY); - SDValue Const1 = DAG.getConstant(1, MVT::i32); SDLoc DL(Op); + SDValue Const1 = DAG.getConstant(1, DL, MVT::i32); // Bitcast to integer nodes. SDValue X = DAG.getNode(ISD::BITCAST, DL, TyX, Op.getOperand(0)); @@ -1932,7 +1961,7 @@ static SDValue lowerFCOPYSIGN64(SDValue Op, SelectionDAG &DAG, // ext E, Y, width(Y) - 1, 1 ; extract bit width(Y)-1 of Y // ins X, E, width(X) - 1, 1 ; insert extracted bit at bit width(X)-1 of X SDValue E = DAG.getNode(MipsISD::Ext, DL, TyY, Y, - DAG.getConstant(WidthY - 1, MVT::i32), Const1); + DAG.getConstant(WidthY - 1, DL, MVT::i32), Const1); if (WidthX > WidthY) E = DAG.getNode(ISD::ZERO_EXTEND, DL, TyX, E); @@ -1940,7 +1969,8 @@ static SDValue lowerFCOPYSIGN64(SDValue Op, SelectionDAG &DAG, E = DAG.getNode(ISD::TRUNCATE, DL, TyX, E); SDValue I = DAG.getNode(MipsISD::Ins, DL, TyX, E, - DAG.getConstant(WidthX - 1, MVT::i32), Const1, X); + DAG.getConstant(WidthX - 1, DL, MVT::i32), Const1, + X); return DAG.getNode(ISD::BITCAST, DL, Op.getOperand(0).getValueType(), I); } @@ -1952,7 +1982,7 @@ static SDValue lowerFCOPYSIGN64(SDValue Op, SelectionDAG &DAG, SDValue SllX = DAG.getNode(ISD::SHL, DL, TyX, X, Const1); SDValue SrlX = DAG.getNode(ISD::SRL, DL, TyX, SllX, Const1); SDValue SrlY = DAG.getNode(ISD::SRL, DL, TyY, Y, - DAG.getConstant(WidthY - 1, MVT::i32)); + DAG.getConstant(WidthY - 1, DL, MVT::i32)); if (WidthX > WidthY) SrlY = DAG.getNode(ISD::ZERO_EXTEND, DL, TyX, SrlY); @@ -1960,7 +1990,7 @@ static SDValue lowerFCOPYSIGN64(SDValue Op, SelectionDAG &DAG, SrlY = DAG.getNode(ISD::TRUNCATE, DL, TyX, SrlY); SDValue SllY = DAG.getNode(ISD::SHL, DL, TyX, SrlY, - DAG.getConstant(WidthX - 1, MVT::i32)); + DAG.getConstant(WidthX - 1, DL, MVT::i32)); SDValue Or = DAG.getNode(ISD::OR, DL, TyX, SrlX, SllY); return DAG.getNode(ISD::BITCAST, DL, Op.getOperand(0).getValueType(), Or); } @@ -1983,9 +2013,8 @@ lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const { MFI->setFrameAddressIsTaken(true); EVT VT = Op.getValueType(); SDLoc DL(Op); - SDValue FrameAddr = - DAG.getCopyFromReg(DAG.getEntryNode(), DL, - Subtarget.isABI_N64() ? Mips::FP_64 : Mips::FP, VT); + SDValue FrameAddr = DAG.getCopyFromReg( + DAG.getEntryNode(), DL, ABI.IsN64() ? Mips::FP_64 : Mips::FP, VT); return FrameAddr; } @@ -2001,7 +2030,7 @@ SDValue MipsTargetLowering::lowerRETURNADDR(SDValue Op, MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); MVT VT = Op.getSimpleValueType(); - unsigned RA = Subtarget.isABI_N64() ? Mips::RA_64 : Mips::RA; + unsigned RA = ABI.IsN64() ? Mips::RA_64 : Mips::RA; MFI->setReturnAddressIsTaken(true); // Return RA, which contains the return address. Mark it an implicit live-in. @@ -2023,12 +2052,12 @@ SDValue MipsTargetLowering::lowerEH_RETURN(SDValue Op, SelectionDAG &DAG) SDValue Offset = Op.getOperand(1); SDValue Handler = Op.getOperand(2); SDLoc DL(Op); - EVT Ty = Subtarget.isABI_N64() ? MVT::i64 : MVT::i32; + EVT Ty = ABI.IsN64() ? MVT::i64 : MVT::i32; // Store stack offset in V1, store jump target in V0. Glue CopyToReg and // EH_RETURN nodes, so that instructions are emitted back-to-back. - unsigned OffsetReg = Subtarget.isABI_N64() ? Mips::V1_64 : Mips::V1; - unsigned AddrReg = Subtarget.isABI_N64() ? Mips::V0_64 : Mips::V0; + unsigned OffsetReg = ABI.IsN64() ? Mips::V1_64 : Mips::V1; + unsigned AddrReg = ABI.IsN64() ? Mips::V0_64 : Mips::V0; Chain = DAG.getCopyToReg(Chain, DL, OffsetReg, Offset, SDValue()); Chain = DAG.getCopyToReg(Chain, DL, AddrReg, Handler, Chain.getValue(1)); return DAG.getNode(MipsISD::EH_RETURN, DL, MVT::Other, Chain, @@ -2044,7 +2073,7 @@ SDValue MipsTargetLowering::lowerATOMIC_FENCE(SDValue Op, unsigned SType = 0; SDLoc DL(Op); return DAG.getNode(MipsISD::Sync, DL, MVT::Other, Op.getOperand(0), - DAG.getConstant(SType, MVT::i32)); + DAG.getConstant(SType, DL, MVT::i32)); } SDValue MipsTargetLowering::lowerShiftLeftParts(SDValue Op, @@ -2061,17 +2090,17 @@ SDValue MipsTargetLowering::lowerShiftLeftParts(SDValue Op, // lo = 0 // hi = (shl lo, shamt[4:0]) SDValue Not = DAG.getNode(ISD::XOR, DL, MVT::i32, Shamt, - DAG.getConstant(-1, MVT::i32)); + DAG.getConstant(-1, DL, MVT::i32)); SDValue ShiftRight1Lo = DAG.getNode(ISD::SRL, DL, VT, Lo, - DAG.getConstant(1, VT)); + DAG.getConstant(1, DL, VT)); SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, VT, ShiftRight1Lo, Not); SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, VT, Hi, Shamt); SDValue Or = DAG.getNode(ISD::OR, DL, VT, ShiftLeftHi, ShiftRightLo); SDValue ShiftLeftLo = DAG.getNode(ISD::SHL, DL, VT, Lo, Shamt); SDValue Cond = DAG.getNode(ISD::AND, DL, MVT::i32, Shamt, - DAG.getConstant(VT.getSizeInBits(), MVT::i32)); + DAG.getConstant(VT.getSizeInBits(), DL, MVT::i32)); Lo = DAG.getNode(ISD::SELECT, DL, VT, Cond, - DAG.getConstant(0, VT), ShiftLeftLo); + DAG.getConstant(0, DL, VT), ShiftLeftLo); Hi = DAG.getNode(ISD::SELECT, DL, VT, Cond, ShiftLeftLo, Or); SDValue Ops[2] = {Lo, Hi}; @@ -2099,21 +2128,21 @@ SDValue MipsTargetLowering::lowerShiftRightParts(SDValue Op, SelectionDAG &DAG, // lo = (srl hi, shamt[4:0]) // hi = 0 SDValue Not = DAG.getNode(ISD::XOR, DL, MVT::i32, Shamt, - DAG.getConstant(-1, MVT::i32)); + DAG.getConstant(-1, DL, MVT::i32)); SDValue ShiftLeft1Hi = DAG.getNode(ISD::SHL, DL, VT, Hi, - DAG.getConstant(1, VT)); + DAG.getConstant(1, DL, VT)); SDValue ShiftLeftHi = DAG.getNode(ISD::SHL, DL, VT, ShiftLeft1Hi, Not); SDValue ShiftRightLo = DAG.getNode(ISD::SRL, DL, VT, Lo, Shamt); SDValue Or = DAG.getNode(ISD::OR, DL, VT, ShiftLeftHi, ShiftRightLo); SDValue ShiftRightHi = DAG.getNode(IsSRA ? ISD::SRA : ISD::SRL, DL, VT, Hi, Shamt); SDValue Cond = DAG.getNode(ISD::AND, DL, MVT::i32, Shamt, - DAG.getConstant(VT.getSizeInBits(), MVT::i32)); + DAG.getConstant(VT.getSizeInBits(), DL, MVT::i32)); SDValue Ext = DAG.getNode(ISD::SRA, DL, VT, Hi, - DAG.getConstant(VT.getSizeInBits() - 1, VT)); + DAG.getConstant(VT.getSizeInBits() - 1, DL, VT)); Lo = DAG.getNode(ISD::SELECT, DL, VT, Cond, ShiftRightHi, Or); Hi = DAG.getNode(ISD::SELECT, DL, VT, Cond, - IsSRA ? Ext : DAG.getConstant(0, VT), ShiftRightHi); + IsSRA ? Ext : DAG.getConstant(0, DL, VT), ShiftRightHi); SDValue Ops[2] = {Lo, Hi}; return DAG.getMergeValues(Ops, DL); @@ -2129,7 +2158,7 @@ static SDValue createLoadLR(unsigned Opc, SelectionDAG &DAG, LoadSDNode *LD, if (Offset) Ptr = DAG.getNode(ISD::ADD, DL, BasePtrVT, Ptr, - DAG.getConstant(Offset, BasePtrVT)); + DAG.getConstant(Offset, DL, BasePtrVT)); SDValue Ops[] = { Chain, Ptr, Src }; return DAG.getMemIntrinsicNode(Opc, DL, VTList, Ops, MemVT, @@ -2194,7 +2223,7 @@ SDValue MipsTargetLowering::lowerLOAD(SDValue Op, SelectionDAG &DAG) const { // (set tmp2, (shl tmp1, 32)) // (set dst, (srl tmp2, 32)) SDLoc DL(LD); - SDValue Const32 = DAG.getConstant(32, MVT::i32); + SDValue Const32 = DAG.getConstant(32, DL, MVT::i32); SDValue SLL = DAG.getNode(ISD::SHL, DL, MVT::i64, LWR, Const32); SDValue SRL = DAG.getNode(ISD::SRL, DL, MVT::i64, SLL, Const32); SDValue Ops[] = { SRL, LWR.getValue(1) }; @@ -2210,7 +2239,7 @@ static SDValue createStoreLR(unsigned Opc, SelectionDAG &DAG, StoreSDNode *SD, if (Offset) Ptr = DAG.getNode(ISD::ADD, DL, BasePtrVT, Ptr, - DAG.getConstant(Offset, BasePtrVT)); + DAG.getConstant(Offset, DL, BasePtrVT)); SDValue Ops[] = { Chain, Value, Ptr }; return DAG.getMemIntrinsicNode(Opc, DL, VTList, Ops, MemVT, @@ -2292,8 +2321,9 @@ SDValue MipsTargetLowering::lowerADD(SDValue Op, SelectionDAG &DAG) const { EVT ValTy = Op->getValueType(0); int FI = MFI->CreateFixedObject(Op.getValueSizeInBits() / 8, 0, false); SDValue InArgsAddr = DAG.getFrameIndex(FI, ValTy); - return DAG.getNode(ISD::ADD, SDLoc(Op), ValTy, InArgsAddr, - DAG.getConstant(0, ValTy)); + SDLoc DL(Op); + return DAG.getNode(ISD::ADD, DL, ValTy, InArgsAddr, + DAG.getConstant(0, DL, ValTy)); } SDValue MipsTargetLowering::lowerFP_TO_SINT(SDValue Op, @@ -2325,12 +2355,9 @@ SDValue MipsTargetLowering::lowerFP_TO_SINT(SDValue Op, static bool CC_MipsO32(unsigned ValNo, MVT ValVT, MVT LocVT, CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags, - CCState &State, const MCPhysReg *F64Regs) { - const MipsSubtarget &Subtarget = - State.getMachineFunction().getTarget() - .getSubtarget<const MipsSubtarget>(); - - static const unsigned IntRegsSize = 4, FloatRegsSize = 2; + CCState &State, ArrayRef<MCPhysReg> F64Regs) { + const MipsSubtarget &Subtarget = static_cast<const MipsSubtarget &>( + State.getMachineFunction().getSubtarget()); static const MCPhysReg IntRegs[] = { Mips::A0, Mips::A1, Mips::A2, Mips::A3 }; static const MCPhysReg F32Regs[] = { Mips::F12, Mips::F14 }; @@ -2368,39 +2395,39 @@ static bool CC_MipsO32(unsigned ValNo, MVT ValVT, MVT LocVT, // f32 and f64 are allocated in A0, A1, A2, A3 when either of the following // is true: function is vararg, argument is 3rd or higher, there is previous // argument which is not f32 or f64. - bool AllocateFloatsInIntReg = State.isVarArg() || ValNo > 1 - || State.getFirstUnallocated(F32Regs, FloatRegsSize) != ValNo; + bool AllocateFloatsInIntReg = State.isVarArg() || ValNo > 1 || + State.getFirstUnallocated(F32Regs) != ValNo; unsigned OrigAlign = ArgFlags.getOrigAlign(); bool isI64 = (ValVT == MVT::i32 && OrigAlign == 8); if (ValVT == MVT::i32 || (ValVT == MVT::f32 && AllocateFloatsInIntReg)) { - Reg = State.AllocateReg(IntRegs, IntRegsSize); + Reg = State.AllocateReg(IntRegs); // If this is the first part of an i64 arg, // the allocated register must be either A0 or A2. if (isI64 && (Reg == Mips::A1 || Reg == Mips::A3)) - Reg = State.AllocateReg(IntRegs, IntRegsSize); + Reg = State.AllocateReg(IntRegs); LocVT = MVT::i32; } else if (ValVT == MVT::f64 && AllocateFloatsInIntReg) { // Allocate int register and shadow next int register. If first // available register is Mips::A1 or Mips::A3, shadow it too. - Reg = State.AllocateReg(IntRegs, IntRegsSize); + Reg = State.AllocateReg(IntRegs); if (Reg == Mips::A1 || Reg == Mips::A3) - Reg = State.AllocateReg(IntRegs, IntRegsSize); - State.AllocateReg(IntRegs, IntRegsSize); + Reg = State.AllocateReg(IntRegs); + State.AllocateReg(IntRegs); LocVT = MVT::i32; } else if (ValVT.isFloatingPoint() && !AllocateFloatsInIntReg) { // we are guaranteed to find an available float register if (ValVT == MVT::f32) { - Reg = State.AllocateReg(F32Regs, FloatRegsSize); + Reg = State.AllocateReg(F32Regs); // Shadow int register - State.AllocateReg(IntRegs, IntRegsSize); + State.AllocateReg(IntRegs); } else { - Reg = State.AllocateReg(F64Regs, FloatRegsSize); + Reg = State.AllocateReg(F64Regs); // Shadow int registers - unsigned Reg2 = State.AllocateReg(IntRegs, IntRegsSize); + unsigned Reg2 = State.AllocateReg(IntRegs); if (Reg2 == Mips::A1 || Reg2 == Mips::A3) - State.AllocateReg(IntRegs, IntRegsSize); - State.AllocateReg(IntRegs, IntRegsSize); + State.AllocateReg(IntRegs); + State.AllocateReg(IntRegs); } } else llvm_unreachable("Cannot handle this ValVT."); @@ -2453,7 +2480,7 @@ MipsTargetLowering::passArgOnStack(SDValue StackPtr, unsigned Offset, bool IsTailCall, SelectionDAG &DAG) const { if (!IsTailCall) { SDValue PtrOff = DAG.getNode(ISD::ADD, DL, getPointerTy(), StackPtr, - DAG.getIntPtrConstant(Offset)); + DAG.getIntPtrConstant(Offset, DL)); return DAG.getStore(Chain, DL, Arg, PtrOff, MachinePointerInfo(), false, false, 0); } @@ -2482,8 +2509,8 @@ getOpndList(SmallVectorImpl<SDValue> &Ops, // used for the function (that is, Mips linker doesn't generate lazy binding // stub for a function whose address is taken in the program). if (IsPICCall && !InternalLinkage && IsCallReloc) { - unsigned GPReg = Subtarget.isABI_N64() ? Mips::GP_64 : Mips::GP; - EVT Ty = Subtarget.isABI_N64() ? MVT::i64 : MVT::i32; + unsigned GPReg = ABI.IsN64() ? Mips::GP_64 : Mips::GP; + EVT Ty = ABI.IsN64() ? MVT::i64 : MVT::i32; RegsToPass.push_back(std::make_pair(GPReg, getGlobalReg(CLI.DAG, Ty))); } @@ -2506,9 +2533,9 @@ getOpndList(SmallVectorImpl<SDValue> &Ops, RegsToPass[i].second.getValueType())); // Add a register mask operand representing the call-preserved registers. - const TargetRegisterInfo *TRI = - getTargetMachine().getSubtargetImpl()->getRegisterInfo(); - const uint32_t *Mask = TRI->getCallPreservedMask(CLI.CallConv); + const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); + const uint32_t *Mask = + TRI->getCallPreservedMask(CLI.DAG.getMachineFunction(), CLI.CallConv); assert(Mask && "Missing call preserved mask for calling convention"); if (Subtarget.inMips16HardFloat()) { if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(CLI.Callee)) { @@ -2543,7 +2570,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); - const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering(); + const TargetFrameLowering *TFL = Subtarget.getFrameLowering(); MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>(); bool IsPIC = getTargetMachine().getRelocationModel() == Reloc::PIC_; @@ -2555,7 +2582,6 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, // Allocate the reserved argument area. It seems strange to do this from the // caller side but removing it breaks the frame size calculation. - const MipsABIInfo &ABI = Subtarget.getABI(); CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(CallConv), 1); CCInfo.AnalyzeCallOperands(Outs, CC_Mips, CLI.getArgs(), Callee.getNode()); @@ -2580,14 +2606,13 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, // byval arguments to the stack. unsigned StackAlignment = TFL->getStackAlignment(); NextStackOffset = RoundUpToAlignment(NextStackOffset, StackAlignment); - SDValue NextStackOffsetVal = DAG.getIntPtrConstant(NextStackOffset, true); + SDValue NextStackOffsetVal = DAG.getIntPtrConstant(NextStackOffset, DL, true); if (!IsTailCall) Chain = DAG.getCALLSEQ_START(Chain, NextStackOffsetVal, DL); SDValue StackPtr = DAG.getCopyFromReg( - Chain, DL, Subtarget.isABI_N64() ? Mips::SP_64 : Mips::SP, - getPointerTy()); + Chain, DL, ABI.IsN64() ? Mips::SP_64 : Mips::SP, getPointerTy()); // With EABI is it possible to have 16 args on registers. std::deque< std::pair<unsigned, SDValue> > RegsToPass; @@ -2633,9 +2658,9 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, Arg = DAG.getNode(ISD::BITCAST, DL, LocVT, Arg); else if (ValVT == MVT::f64 && LocVT == MVT::i32) { SDValue Lo = DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, - Arg, DAG.getConstant(0, MVT::i32)); + Arg, DAG.getConstant(0, DL, MVT::i32)); SDValue Hi = DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, - Arg, DAG.getConstant(1, MVT::i32)); + Arg, DAG.getConstant(1, DL, MVT::i32)); if (!Subtarget.isLittle()) std::swap(Lo, Hi); unsigned LocRegLo = VA.getLocReg(); @@ -2674,7 +2699,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, unsigned LocSizeInBits = VA.getLocVT().getSizeInBits(); Arg = DAG.getNode( ISD::SHL, DL, VA.getLocVT(), Arg, - DAG.getConstant(LocSizeInBits - ValSizeInBits, VA.getLocVT())); + DAG.getConstant(LocSizeInBits - ValSizeInBits, DL, VA.getLocVT())); } // Arguments that can be passed on register must be kept at @@ -2701,9 +2726,8 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol // node so that legalize doesn't hack it. - bool IsPICCall = - (Subtarget.isABI_N64() || IsPIC); // true if calls are translated to - // jalr $25 + bool IsPICCall = (ABI.IsN64() || IsPIC); // true if calls are translated to + // jalr $25 bool GlobalOrExternal = false, InternalLinkage = false, IsCallReloc = false; SDValue CalleeLo; EVT Ty = Callee.getValueType(); @@ -2714,8 +2738,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, InternalLinkage = Val->hasInternalLinkage(); if (InternalLinkage) - Callee = getAddrLocal(G, DL, Ty, DAG, - Subtarget.isABI_N32() || Subtarget.isABI_N64()); + Callee = getAddrLocal(G, DL, Ty, DAG, ABI.IsN32() || ABI.IsN64()); else if (LargeGOT) { Callee = getAddrGlobalLargeGOT(G, DL, Ty, DAG, MipsII::MO_CALL_HI16, MipsII::MO_CALL_LO16, Chain, @@ -2734,7 +2757,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) { const char *Sym = S->getSymbol(); - if (!Subtarget.isABI_N64() && !IsPIC) // !N64 && static + if (!ABI.IsN64() && !IsPIC) // !N64 && static Callee = DAG.getTargetExternalSymbol(Sym, getPointerTy(), MipsII::MO_NO_FLAG); else if (LargeGOT) { @@ -2765,7 +2788,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, // Create the CALLSEQ_END node. Chain = DAG.getCALLSEQ_END(Chain, NextStackOffsetVal, - DAG.getIntPtrConstant(0, true), InFlag, DL); + DAG.getIntPtrConstant(0, DL, true), InFlag, DL); InFlag = Chain.getValue(1); // Handle result values, copying them out of physregs into vregs that we @@ -2804,7 +2827,7 @@ SDValue MipsTargetLowering::LowerCallResult( VA.getLocInfo() == CCValAssign::ZExtUpper ? ISD::SRL : ISD::SRA; Val = DAG.getNode( Shift, DL, VA.getLocVT(), Val, - DAG.getConstant(LocSizeInBits - ValSizeInBits, VA.getLocVT())); + DAG.getConstant(LocSizeInBits - ValSizeInBits, DL, VA.getLocVT())); } switch (VA.getLocInfo()) { @@ -2857,7 +2880,7 @@ static SDValue UnpackFromArgumentSlot(SDValue Val, const CCValAssign &VA, VA.getLocInfo() == CCValAssign::ZExtUpper ? ISD::SRL : ISD::SRA; Val = DAG.getNode( Opcode, DL, VA.getLocVT(), Val, - DAG.getConstant(LocSizeInBits - ValSizeInBits, VA.getLocVT())); + DAG.getConstant(LocSizeInBits - ValSizeInBits, DL, VA.getLocVT())); break; } } @@ -2919,7 +2942,6 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, SmallVector<CCValAssign, 16> ArgLocs; MipsCCState CCInfo(CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, *DAG.getContext()); - const MipsABIInfo &ABI = Subtarget.getABI(); CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(CallConv), 1); Function::const_arg_iterator FuncArg = DAG.getMachineFunction().getFunction()->arg_begin(); @@ -2975,7 +2997,7 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, (RegVT == MVT::i64 && ValVT == MVT::f64) || (RegVT == MVT::f64 && ValVT == MVT::i64)) ArgValue = DAG.getNode(ISD::BITCAST, DL, ValVT, ArgValue); - else if (Subtarget.isABI_O32() && RegVT == MVT::i32 && + else if (ABI.IsO32() && RegVT == MVT::i32 && ValVT == MVT::f64) { unsigned Reg2 = addLiveIn(DAG.getMachineFunction(), getNextIntArgReg(ArgReg), RC); @@ -2990,12 +3012,12 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, } else { // VA.isRegLoc() MVT LocVT = VA.getLocVT(); - if (Subtarget.isABI_O32()) { + if (ABI.IsO32()) { // We ought to be able to use LocVT directly but O32 sets it to i32 // when allocating floating point values to integer registers. // This shouldn't influence how we load the value into registers unless // we are targetting softfloat. - if (VA.getValVT().isFloatingPoint() && !Subtarget.abiUsesSoftFloat()) + if (VA.getValVT().isFloatingPoint() && !Subtarget.useSoftFloat()) LocVT = VA.getValVT(); } @@ -3027,7 +3049,7 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, unsigned Reg = MipsFI->getSRetReturnReg(); if (!Reg) { Reg = MF.getRegInfo().createVirtualRegister( - getRegClassFor(Subtarget.isABI_N64() ? MVT::i64 : MVT::i32)); + getRegClassFor(ABI.IsN64() ? MVT::i64 : MVT::i32)); MipsFI->setSRetReturnReg(Reg); } SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), DL, Reg, InVals[i]); @@ -3065,7 +3087,7 @@ MipsTargetLowering::CanLowerReturn(CallingConv::ID CallConv, bool MipsTargetLowering::shouldSignExtendTypeInLibCall(EVT Type, bool IsSigned) const { - if (Subtarget.hasMips3() && Subtarget.abiUsesSoftFloat()) { + if (Subtarget.hasMips3() && Subtarget.useSoftFloat()) { if (Type == MVT::i32) return true; } @@ -3132,7 +3154,7 @@ MipsTargetLowering::LowerReturn(SDValue Chain, unsigned LocSizeInBits = VA.getLocVT().getSizeInBits(); Val = DAG.getNode( ISD::SHL, DL, VA.getLocVT(), Val, - DAG.getConstant(LocSizeInBits - ValSizeInBits, VA.getLocVT())); + DAG.getConstant(LocSizeInBits - ValSizeInBits, DL, VA.getLocVT())); } Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), Val, Flag); @@ -3153,7 +3175,7 @@ MipsTargetLowering::LowerReturn(SDValue Chain, if (!Reg) llvm_unreachable("sret virtual register not created in the entry block"); SDValue Val = DAG.getCopyFromReg(Chain, DL, Reg, getPointerTy()); - unsigned V0 = Subtarget.isABI_N64() ? Mips::V0_64 : Mips::V0; + unsigned V0 = ABI.IsN64() ? Mips::V0_64 : Mips::V0; Chain = DAG.getCopyToReg(Chain, DL, V0, Val, Flag); Flag = Chain.getValue(1); @@ -3204,6 +3226,10 @@ getConstraintType(const std::string &Constraint) const return C_Memory; } } + + if (Constraint == "ZC") + return C_Memory; + return TargetLowering::getConstraintType(Constraint); } @@ -3288,7 +3314,7 @@ parsePhysicalReg(StringRef C, std::string &Prefix, std::pair<unsigned, const TargetRegisterClass *> MipsTargetLowering:: parseRegForInlineAsmConstraint(StringRef C, MVT VT) const { const TargetRegisterInfo *TRI = - getTargetMachine().getSubtargetImpl()->getRegisterInfo(); + Subtarget.getRegisterInfo(); const TargetRegisterClass *RC; std::string Prefix; unsigned long long Reg; @@ -3362,9 +3388,10 @@ parseRegForInlineAsmConstraint(StringRef C, MVT VT) const { /// Given a register class constraint, like 'r', if this corresponds directly /// to an LLVM register class, return a register of 0 and the register class /// pointer. -std::pair<unsigned, const TargetRegisterClass*> MipsTargetLowering:: -getRegForInlineAsmConstraint(const std::string &Constraint, MVT VT) const -{ +std::pair<unsigned, const TargetRegisterClass *> +MipsTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, + const std::string &Constraint, + MVT VT) const { if (Constraint.size() == 1) { switch (Constraint[0]) { case 'd': // Address register. Same as 'r' unless generating MIPS16 code. @@ -3420,7 +3447,7 @@ getRegForInlineAsmConstraint(const std::string &Constraint, MVT VT) const if (R.second) return R; - return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT); + return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT); } /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops @@ -3429,6 +3456,7 @@ void MipsTargetLowering::LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint, std::vector<SDValue>&Ops, SelectionDAG &DAG) const { + SDLoc DL(Op); SDValue Result; // Only support length 1 constraints for now. @@ -3443,7 +3471,7 @@ void MipsTargetLowering::LowerAsmOperandForConstraint(SDValue Op, EVT Type = Op.getValueType(); int64_t Val = C->getSExtValue(); if (isInt<16>(Val)) { - Result = DAG.getTargetConstant(Val, Type); + Result = DAG.getTargetConstant(Val, DL, Type); break; } } @@ -3453,7 +3481,7 @@ void MipsTargetLowering::LowerAsmOperandForConstraint(SDValue Op, EVT Type = Op.getValueType(); int64_t Val = C->getZExtValue(); if (Val == 0) { - Result = DAG.getTargetConstant(0, Type); + Result = DAG.getTargetConstant(0, DL, Type); break; } } @@ -3463,7 +3491,7 @@ void MipsTargetLowering::LowerAsmOperandForConstraint(SDValue Op, EVT Type = Op.getValueType(); uint64_t Val = (uint64_t)C->getZExtValue(); if (isUInt<16>(Val)) { - Result = DAG.getTargetConstant(Val, Type); + Result = DAG.getTargetConstant(Val, DL, Type); break; } } @@ -3473,7 +3501,7 @@ void MipsTargetLowering::LowerAsmOperandForConstraint(SDValue Op, EVT Type = Op.getValueType(); int64_t Val = C->getSExtValue(); if ((isInt<32>(Val)) && ((Val & 0xffff) == 0)){ - Result = DAG.getTargetConstant(Val, Type); + Result = DAG.getTargetConstant(Val, DL, Type); break; } } @@ -3483,7 +3511,7 @@ void MipsTargetLowering::LowerAsmOperandForConstraint(SDValue Op, EVT Type = Op.getValueType(); int64_t Val = C->getSExtValue(); if ((Val >= -65535) && (Val <= -1)) { - Result = DAG.getTargetConstant(Val, Type); + Result = DAG.getTargetConstant(Val, DL, Type); break; } } @@ -3493,7 +3521,7 @@ void MipsTargetLowering::LowerAsmOperandForConstraint(SDValue Op, EVT Type = Op.getValueType(); int64_t Val = C->getSExtValue(); if ((isInt<15>(Val))) { - Result = DAG.getTargetConstant(Val, Type); + Result = DAG.getTargetConstant(Val, DL, Type); break; } } @@ -3503,7 +3531,7 @@ void MipsTargetLowering::LowerAsmOperandForConstraint(SDValue Op, EVT Type = Op.getValueType(); int64_t Val = C->getSExtValue(); if ((Val <= 65535) && (Val >= 1)) { - Result = DAG.getTargetConstant(Val, Type); + Result = DAG.getTargetConstant(Val, DL, Type); break; } } @@ -3519,7 +3547,8 @@ void MipsTargetLowering::LowerAsmOperandForConstraint(SDValue Op, } bool MipsTargetLowering::isLegalAddressingMode(const AddrMode &AM, - Type *Ty) const { + Type *Ty, + unsigned AS) const { // No global is ever allowed as a base. if (AM.BaseGV) return false; @@ -3564,12 +3593,16 @@ bool MipsTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const { } unsigned MipsTargetLowering::getJumpTableEncoding() const { - if (Subtarget.isABI_N64()) + if (ABI.IsN64()) return MachineJumpTableInfo::EK_GPRel64BlockAddress; return TargetLowering::getJumpTableEncoding(); } +bool MipsTargetLowering::useSoftFloat() const { + return Subtarget.useSoftFloat(); +} + void MipsTargetLowering::copyByValRegs( SDValue Chain, SDLoc DL, std::vector<SDValue> &OutChains, SelectionDAG &DAG, const ISD::ArgFlagsTy &Flags, SmallVectorImpl<SDValue> &InVals, @@ -3582,7 +3615,6 @@ void MipsTargetLowering::copyByValRegs( unsigned RegAreaSize = NumRegs * GPRSizeInBytes; unsigned FrameObjSize = std::max(Flags.getByValSize(), RegAreaSize); int FrameObjOffset; - const MipsABIInfo &ABI = Subtarget.getABI(); ArrayRef<MCPhysReg> ByValArgRegs = ABI.GetByValArgRegs(); if (RegAreaSize) @@ -3610,7 +3642,7 @@ void MipsTargetLowering::copyByValRegs( unsigned VReg = addLiveIn(MF, ArgReg, RC); unsigned Offset = I * GPRSizeInBytes; SDValue StorePtr = DAG.getNode(ISD::ADD, DL, PtrTy, FIN, - DAG.getConstant(Offset, PtrTy)); + DAG.getConstant(Offset, DL, PtrTy)); SDValue Store = DAG.getStore(Chain, DL, DAG.getRegister(VReg, RegTy), StorePtr, MachinePointerInfo(FuncArg, Offset), false, false, 0); @@ -3634,14 +3666,14 @@ void MipsTargetLowering::passByValArg( unsigned NumRegs = LastReg - FirstReg; if (NumRegs) { - const ArrayRef<MCPhysReg> ArgRegs = Subtarget.getABI().GetByValArgRegs(); + const ArrayRef<MCPhysReg> ArgRegs = ABI.GetByValArgRegs(); bool LeftoverBytes = (NumRegs * RegSizeInBytes > ByValSizeInBytes); unsigned I = 0; // Copy words to registers. for (; I < NumRegs - LeftoverBytes; ++I, OffsetInBytes += RegSizeInBytes) { SDValue LoadPtr = DAG.getNode(ISD::ADD, DL, PtrTy, Arg, - DAG.getConstant(OffsetInBytes, PtrTy)); + DAG.getConstant(OffsetInBytes, DL, PtrTy)); SDValue LoadVal = DAG.getLoad(RegTy, DL, Chain, LoadPtr, MachinePointerInfo(), false, false, false, Alignment); @@ -3667,7 +3699,8 @@ void MipsTargetLowering::passByValArg( // Load subword. SDValue LoadPtr = DAG.getNode(ISD::ADD, DL, PtrTy, Arg, - DAG.getConstant(OffsetInBytes, PtrTy)); + DAG.getConstant(OffsetInBytes, DL, + PtrTy)); SDValue LoadVal = DAG.getExtLoad( ISD::ZEXTLOAD, DL, RegTy, Chain, LoadPtr, MachinePointerInfo(), MVT::getIntegerVT(LoadSizeInBytes * 8), false, false, false, @@ -3683,7 +3716,7 @@ void MipsTargetLowering::passByValArg( Shamt = (RegSizeInBytes - (TotalBytesLoaded + LoadSizeInBytes)) * 8; SDValue Shift = DAG.getNode(ISD::SHL, DL, RegTy, LoadVal, - DAG.getConstant(Shamt, MVT::i32)); + DAG.getConstant(Shamt, DL, MVT::i32)); if (Val.getNode()) Val = DAG.getNode(ISD::OR, DL, RegTy, Val, Shift); @@ -3704,11 +3737,13 @@ void MipsTargetLowering::passByValArg( // Copy remainder of byval arg to it with memcpy. unsigned MemCpySize = ByValSizeInBytes - OffsetInBytes; SDValue Src = DAG.getNode(ISD::ADD, DL, PtrTy, Arg, - DAG.getConstant(OffsetInBytes, PtrTy)); + DAG.getConstant(OffsetInBytes, DL, PtrTy)); SDValue Dst = DAG.getNode(ISD::ADD, DL, PtrTy, StackPtr, - DAG.getIntPtrConstant(VA.getLocMemOffset())); - Chain = DAG.getMemcpy(Chain, DL, Dst, Src, DAG.getConstant(MemCpySize, PtrTy), + DAG.getIntPtrConstant(VA.getLocMemOffset(), DL)); + Chain = DAG.getMemcpy(Chain, DL, Dst, Src, + DAG.getConstant(MemCpySize, DL, PtrTy), Alignment, /*isVolatile=*/false, /*AlwaysInline=*/false, + /*isTailCall=*/false, MachinePointerInfo(), MachinePointerInfo()); MemOpChains.push_back(Chain); } @@ -3717,8 +3752,8 @@ void MipsTargetLowering::writeVarArgRegs(std::vector<SDValue> &OutChains, SDValue Chain, SDLoc DL, SelectionDAG &DAG, CCState &State) const { - const ArrayRef<MCPhysReg> ArgRegs = Subtarget.getABI().GetVarArgRegs(); - unsigned Idx = State.getFirstUnallocated(ArgRegs.data(), ArgRegs.size()); + const ArrayRef<MCPhysReg> ArgRegs = ABI.GetVarArgRegs(); + unsigned Idx = State.getFirstUnallocated(ArgRegs); unsigned RegSizeInBytes = Subtarget.getGPRSizeInBytes(); MVT RegTy = MVT::getIntegerVT(RegSizeInBytes * 8); const TargetRegisterClass *RC = getRegClassFor(RegTy); @@ -3733,7 +3768,6 @@ void MipsTargetLowering::writeVarArgRegs(std::vector<SDValue> &OutChains, VaArgOffset = RoundUpToAlignment(State.getNextStackOffset(), RegSizeInBytes); else { - const MipsABIInfo &ABI = Subtarget.getABI(); VaArgOffset = (int)ABI.GetCalleeAllocdArgSizeInBytes(State.getCallingConv()) - (int)(RegSizeInBytes * (ArgRegs.size() - Idx)); @@ -3764,8 +3798,7 @@ void MipsTargetLowering::writeVarArgRegs(std::vector<SDValue> &OutChains, void MipsTargetLowering::HandleByVal(CCState *State, unsigned &Size, unsigned Align) const { - MachineFunction &MF = State->getMachineFunction(); - const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering(); + const TargetFrameLowering *TFL = Subtarget.getFrameLowering(); assert(Size && "Byval argument's size shouldn't be 0."); @@ -3776,10 +3809,10 @@ void MipsTargetLowering::HandleByVal(CCState *State, unsigned &Size, if (State->getCallingConv() != CallingConv::Fast) { unsigned RegSizeInBytes = Subtarget.getGPRSizeInBytes(); - const ArrayRef<MCPhysReg> IntArgRegs = Subtarget.getABI().GetByValArgRegs(); + const ArrayRef<MCPhysReg> IntArgRegs = ABI.GetByValArgRegs(); // FIXME: The O32 case actually describes no shadow registers. const MCPhysReg *ShadowRegs = - Subtarget.isABI_O32() ? IntArgRegs.data() : Mips64DPRegs; + ABI.IsO32() ? IntArgRegs.data() : Mips64DPRegs; // We used to check the size as well but we can't do that anymore since // CCState::HandleByVal() rounds up the size after calling this function. @@ -3787,7 +3820,7 @@ void MipsTargetLowering::HandleByVal(CCState *State, unsigned &Size, "Byval argument's alignment should be a multiple of" "RegSizeInBytes."); - FirstReg = State->getFirstUnallocated(IntArgRegs.data(), IntArgRegs.size()); + FirstReg = State->getFirstUnallocated(IntArgRegs); // If Align > RegSizeInBytes, the first arg register must be even. // FIXME: This condition happens to do the right thing but it's not the @@ -3816,7 +3849,7 @@ MipsTargetLowering::emitPseudoSELECT(MachineInstr *MI, MachineBasicBlock *BB, "conditional-move instructions."); const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + Subtarget.getInstrInfo(); DebugLoc DL = MI->getDebugLoc(); // To "insert" a SELECT instruction, we actually have to insert the diff --git a/contrib/llvm/lib/Target/Mips/MipsISelLowering.h b/contrib/llvm/lib/Target/Mips/MipsISelLowering.h index 4da337a..bc9a1ce 100644 --- a/contrib/llvm/lib/Target/Mips/MipsISelLowering.h +++ b/contrib/llvm/lib/Target/Mips/MipsISelLowering.h @@ -15,6 +15,7 @@ #ifndef LLVM_LIB_TARGET_MIPS_MIPSISELLOWERING_H #define LLVM_LIB_TARGET_MIPS_MIPSISELLOWERING_H +#include "MCTargetDesc/MipsABIInfo.h" #include "MCTargetDesc/MipsBaseInfo.h" #include "Mips.h" #include "llvm/CodeGen/CallingConvLower.h" @@ -26,7 +27,7 @@ namespace llvm { namespace MipsISD { - enum NodeType { + enum NodeType : unsigned { // Start the numbering from where ISD NodeType finishes. FIRST_NUMBER = ISD::BUILTIN_OP_END, @@ -361,6 +362,8 @@ namespace llvm { // Subtarget Info const MipsSubtarget &Subtarget; + // Cache the ABI from the TargetMachine, we use it everywhere. + const MipsABIInfo &ABI; private: // Create a TargetGlobalAddress node. @@ -488,9 +491,10 @@ namespace llvm { std::pair<unsigned, const TargetRegisterClass *> parseRegForInlineAsmConstraint(StringRef C, MVT VT) const; - std::pair<unsigned, const TargetRegisterClass*> - getRegForInlineAsmConstraint(const std::string &Constraint, - MVT VT) const override; + std::pair<unsigned, const TargetRegisterClass *> + getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, + const std::string &Constraint, + MVT VT) const override; /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops /// vector. If it is invalid, don't add anything to Ops. If hasMemory is @@ -501,7 +505,17 @@ namespace llvm { std::vector<SDValue> &Ops, SelectionDAG &DAG) const override; - bool isLegalAddressingMode(const AddrMode &AM, Type *Ty) const override; + unsigned getInlineAsmMemConstraint( + const std::string &ConstraintCode) const override { + if (ConstraintCode == "R") + return InlineAsm::Constraint_R; + else if (ConstraintCode == "ZC") + return InlineAsm::Constraint_ZC; + return TargetLowering::getInlineAsmMemConstraint(ConstraintCode); + } + + bool isLegalAddressingMode(const AddrMode &AM, Type *Ty, + unsigned AS) const override; bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override; @@ -517,6 +531,7 @@ namespace llvm { bool isFPImmLegal(const APFloat &Imm, EVT VT) const override; unsigned getJumpTableEncoding() const override; + bool useSoftFloat() const override; /// Emit a sign-extension using sll/sra, seb, or seh appropriately. MachineBasicBlock *emitSignExtendToI32InReg(MachineInstr *MI, diff --git a/contrib/llvm/lib/Target/Mips/MipsInstrFPU.td b/contrib/llvm/lib/Target/Mips/MipsInstrFPU.td index ed97cb4..cb91225 100644 --- a/contrib/llvm/lib/Target/Mips/MipsInstrFPU.td +++ b/contrib/llvm/lib/Target/Mips/MipsInstrFPU.td @@ -65,6 +65,8 @@ def IsSingleFloat : Predicate<"Subtarget->isSingleFloat()">, AssemblerPredicate<"FeatureSingleFloat">; def IsNotSingleFloat : Predicate<"!Subtarget->isSingleFloat()">, AssemblerPredicate<"!FeatureSingleFloat">; +def IsNotSoftFloat : Predicate<"!Subtarget->useSoftFloat()">, + AssemblerPredicate<"!FeatureSoftFloat">; //===----------------------------------------------------------------------===// // Mips FGR size adjectives. @@ -73,6 +75,7 @@ def IsNotSingleFloat : Predicate<"!Subtarget->isSingleFloat()">, class FGR_32 { list<Predicate> FGRPredicates = [NotFP64bit]; } class FGR_64 { list<Predicate> FGRPredicates = [IsFP64bit]; } +class HARDFLOAT { list<Predicate> HardFloatPredicate = [IsNotSoftFloat]; } //===----------------------------------------------------------------------===// @@ -98,22 +101,19 @@ def fpimm0neg : PatLeaf<(fpimm), [{ // // Only S32 and D32 are supported right now. //===----------------------------------------------------------------------===// - class ADDS_FT<string opstr, RegisterOperand RC, InstrItinClass Itin, bit IsComm, SDPatternOperator OpNode= null_frag> : InstSE<(outs RC:$fd), (ins RC:$fs, RC:$ft), !strconcat(opstr, "\t$fd, $fs, $ft"), - [(set RC:$fd, (OpNode RC:$fs, RC:$ft))], Itin, FrmFR, opstr> { + [(set RC:$fd, (OpNode RC:$fs, RC:$ft))], Itin, FrmFR, opstr>, + HARDFLOAT { let isCommutable = IsComm; } multiclass ADDS_M<string opstr, InstrItinClass Itin, bit IsComm, SDPatternOperator OpNode = null_frag> { - def _D32 : MMRel, ADDS_FT<opstr, AFGR64Opnd, Itin, IsComm, OpNode>, - AdditionalRequires<[NotFP64bit]>; - def _D64 : ADDS_FT<opstr, FGR64Opnd, Itin, - IsComm, OpNode>, - AdditionalRequires<[IsFP64bit]> { + def _D32 : MMRel, ADDS_FT<opstr, AFGR64Opnd, Itin, IsComm, OpNode>, FGR_32; + def _D64 : ADDS_FT<opstr, FGR64Opnd, Itin, IsComm, OpNode>, FGR_64 { string DecoderNamespace = "Mips64"; } } @@ -122,23 +122,21 @@ class ABSS_FT<string opstr, RegisterOperand DstRC, RegisterOperand SrcRC, InstrItinClass Itin, SDPatternOperator OpNode= null_frag> : InstSE<(outs DstRC:$fd), (ins SrcRC:$fs), !strconcat(opstr, "\t$fd, $fs"), [(set DstRC:$fd, (OpNode SrcRC:$fs))], Itin, FrmFR, opstr>, + HARDFLOAT, NeverHasSideEffects; multiclass ABSS_M<string opstr, InstrItinClass Itin, SDPatternOperator OpNode= null_frag> { def _D32 : MMRel, ABSS_FT<opstr, AFGR64Opnd, AFGR64Opnd, Itin, OpNode>, - AdditionalRequires<[NotFP64bit]>; - def _D64 : ABSS_FT<opstr, FGR64Opnd, FGR64Opnd, Itin, OpNode>, - AdditionalRequires<[IsFP64bit]> { + FGR_32; + def _D64 : ABSS_FT<opstr, FGR64Opnd, FGR64Opnd, Itin, OpNode>, FGR_64 { string DecoderNamespace = "Mips64"; } } multiclass ROUND_M<string opstr, InstrItinClass Itin> { - def _D32 : MMRel, ABSS_FT<opstr, FGR32Opnd, AFGR64Opnd, Itin>, - AdditionalRequires<[NotFP64bit]>; - def _D64 : ABSS_FT<opstr, FGR32Opnd, FGR64Opnd, Itin>, - AdditionalRequires<[IsFP64bit]> { + def _D32 : MMRel, ABSS_FT<opstr, FGR32Opnd, AFGR64Opnd, Itin>, FGR_32; + def _D64 : ABSS_FT<opstr, FGR32Opnd, FGR64Opnd, Itin>, FGR_64 { let DecoderNamespace = "Mips64"; } } @@ -146,17 +144,17 @@ multiclass ROUND_M<string opstr, InstrItinClass Itin> { class MFC1_FT<string opstr, RegisterOperand DstRC, RegisterOperand SrcRC, InstrItinClass Itin, SDPatternOperator OpNode= null_frag> : InstSE<(outs DstRC:$rt), (ins SrcRC:$fs), !strconcat(opstr, "\t$rt, $fs"), - [(set DstRC:$rt, (OpNode SrcRC:$fs))], Itin, FrmFR, opstr>; + [(set DstRC:$rt, (OpNode SrcRC:$fs))], Itin, FrmFR, opstr>, HARDFLOAT; class MTC1_FT<string opstr, RegisterOperand DstRC, RegisterOperand SrcRC, InstrItinClass Itin, SDPatternOperator OpNode= null_frag> : InstSE<(outs DstRC:$fs), (ins SrcRC:$rt), !strconcat(opstr, "\t$rt, $fs"), - [(set DstRC:$fs, (OpNode SrcRC:$rt))], Itin, FrmFR, opstr>; + [(set DstRC:$fs, (OpNode SrcRC:$rt))], Itin, FrmFR, opstr>, HARDFLOAT; class MTC1_64_FT<string opstr, RegisterOperand DstRC, RegisterOperand SrcRC, InstrItinClass Itin> : InstSE<(outs DstRC:$fs), (ins DstRC:$fs_in, SrcRC:$rt), - !strconcat(opstr, "\t$rt, $fs"), [], Itin, FrmFR, opstr> { + !strconcat(opstr, "\t$rt, $fs"), [], Itin, FrmFR, opstr>, HARDFLOAT { // $fs_in is part of a white lie to work around a widespread bug in the FPU // implementation. See expandBuildPairF64 for details. let Constraints = "$fs = $fs_in"; @@ -165,7 +163,8 @@ class MTC1_64_FT<string opstr, RegisterOperand DstRC, RegisterOperand SrcRC, class LW_FT<string opstr, RegisterOperand RC, InstrItinClass Itin, SDPatternOperator OpNode= null_frag> : InstSE<(outs RC:$rt), (ins mem:$addr), !strconcat(opstr, "\t$rt, $addr"), - [(set RC:$rt, (OpNode addrDefault:$addr))], Itin, FrmFI, opstr> { + [(set RC:$rt, (OpNode addrDefault:$addr))], Itin, FrmFI, opstr>, + HARDFLOAT { let DecoderMethod = "DecodeFMem"; let mayLoad = 1; } @@ -173,7 +172,7 @@ class LW_FT<string opstr, RegisterOperand RC, InstrItinClass Itin, class SW_FT<string opstr, RegisterOperand RC, InstrItinClass Itin, SDPatternOperator OpNode= null_frag> : InstSE<(outs), (ins RC:$rt, mem:$addr), !strconcat(opstr, "\t$rt, $addr"), - [(OpNode RC:$rt, addrDefault:$addr)], Itin, FrmFI, opstr> { + [(OpNode RC:$rt, addrDefault:$addr)], Itin, FrmFI, opstr>, HARDFLOAT { let DecoderMethod = "DecodeFMem"; let mayStore = 1; } @@ -183,21 +182,21 @@ class MADDS_FT<string opstr, RegisterOperand RC, InstrItinClass Itin, InstSE<(outs RC:$fd), (ins RC:$fr, RC:$fs, RC:$ft), !strconcat(opstr, "\t$fd, $fr, $fs, $ft"), [(set RC:$fd, (OpNode (fmul RC:$fs, RC:$ft), RC:$fr))], Itin, - FrmFR, opstr>; + FrmFR, opstr>, HARDFLOAT; class NMADDS_FT<string opstr, RegisterOperand RC, InstrItinClass Itin, SDPatternOperator OpNode = null_frag> : InstSE<(outs RC:$fd), (ins RC:$fr, RC:$fs, RC:$ft), !strconcat(opstr, "\t$fd, $fr, $fs, $ft"), [(set RC:$fd, (fsub fpimm0, (OpNode (fmul RC:$fs, RC:$ft), RC:$fr)))], - Itin, FrmFR, opstr>; + Itin, FrmFR, opstr>, HARDFLOAT; class LWXC1_FT<string opstr, RegisterOperand DRC, InstrItinClass Itin, SDPatternOperator OpNode = null_frag> : InstSE<(outs DRC:$fd), (ins PtrRC:$base, PtrRC:$index), !strconcat(opstr, "\t$fd, ${index}(${base})"), [(set DRC:$fd, (OpNode (add iPTR:$base, iPTR:$index)))], Itin, - FrmFI, opstr> { + FrmFI, opstr>, HARDFLOAT { let AddedComplexity = 20; } @@ -206,7 +205,7 @@ class SWXC1_FT<string opstr, RegisterOperand DRC, InstSE<(outs), (ins DRC:$fs, PtrRC:$base, PtrRC:$index), !strconcat(opstr, "\t$fs, ${index}(${base})"), [(OpNode DRC:$fs, (add iPTR:$base, iPTR:$index))], Itin, - FrmFI, opstr> { + FrmFI, opstr>, HARDFLOAT { let AddedComplexity = 20; } @@ -215,7 +214,7 @@ class BC1F_FT<string opstr, DAGOperand opnd, InstrItinClass Itin, InstSE<(outs), (ins FCCRegsOpnd:$fcc, opnd:$offset), !strconcat(opstr, "\t$fcc, $offset"), [(MipsFPBrcond Op, FCCRegsOpnd:$fcc, bb:$offset)], Itin, - FrmFI, opstr> { + FrmFI, opstr>, HARDFLOAT { let isBranch = 1; let isTerminator = 1; let hasDelaySlot = DelaySlot; @@ -227,7 +226,7 @@ class CEQS_FT<string typestr, RegisterClass RC, InstrItinClass Itin, InstSE<(outs), (ins RC:$fs, RC:$ft, condcode:$cond), !strconcat("c.$cond.", typestr, "\t$fs, $ft"), [(OpNode RC:$fs, RC:$ft, imm:$cond)], Itin, FrmFR, - !strconcat("c.$cond.", typestr)> { + !strconcat("c.$cond.", typestr)>, HARDFLOAT { let Defs = [FCC0]; let isCodeGenOnly = 1; } @@ -236,7 +235,7 @@ class C_COND_FT<string CondStr, string Typestr, RegisterOperand RC, InstrItinClass itin> : InstSE<(outs), (ins RC:$fs, RC:$ft), !strconcat("c.", CondStr, ".", Typestr, "\t$fs, $ft"), [], itin, - FrmFR>; + FrmFR>, HARDFLOAT; multiclass C_COND_M<string TypeStr, RegisterOperand RC, bits<5> fmt, InstrItinClass itin> { @@ -260,10 +259,10 @@ multiclass C_COND_M<string TypeStr, RegisterOperand RC, bits<5> fmt, defm S : C_COND_M<"s", FGR32Opnd, 16, II_C_CC_S>, ISA_MIPS1_NOT_32R6_64R6; defm D32 : C_COND_M<"d", AFGR64Opnd, 17, II_C_CC_D>, ISA_MIPS1_NOT_32R6_64R6, - AdditionalRequires<[NotFP64bit]>; + FGR_32; let DecoderNamespace = "Mips64" in defm D64 : C_COND_M<"d", FGR64Opnd, 17, II_C_CC_D>, ISA_MIPS1_NOT_32R6_64R6, - AdditionalRequires<[IsFP64bit]>; + FGR_64; //===----------------------------------------------------------------------===// // Floating Point Instructions @@ -363,15 +362,15 @@ def MFC1 : MMRel, MFC1_FT<"mfc1", GPR32Opnd, FGR32Opnd, II_MFC1, def MTC1 : MMRel, MTC1_FT<"mtc1", FGR32Opnd, GPR32Opnd, II_MTC1, bitconvert>, MFC1_FM<4>; def MFHC1_D32 : MMRel, MFC1_FT<"mfhc1", GPR32Opnd, AFGR64Opnd, II_MFHC1>, - MFC1_FM<3>, ISA_MIPS32R2, AdditionalRequires<[NotFP64bit]>; + MFC1_FM<3>, ISA_MIPS32R2, FGR_32; def MFHC1_D64 : MFC1_FT<"mfhc1", GPR32Opnd, FGR64Opnd, II_MFHC1>, - MFC1_FM<3>, ISA_MIPS32R2, AdditionalRequires<[IsFP64bit]> { + MFC1_FM<3>, ISA_MIPS32R2, FGR_64 { let DecoderNamespace = "Mips64"; } def MTHC1_D32 : MMRel, MTC1_64_FT<"mthc1", AFGR64Opnd, GPR32Opnd, II_MTHC1>, - MFC1_FM<7>, ISA_MIPS32R2, AdditionalRequires<[NotFP64bit]>; + MFC1_FM<7>, ISA_MIPS32R2, FGR_32; def MTHC1_D64 : MTC1_64_FT<"mthc1", FGR64Opnd, GPR32Opnd, II_MTHC1>, - MFC1_FM<7>, ISA_MIPS32R2, AdditionalRequires<[IsFP64bit]> { + MFC1_FM<7>, ISA_MIPS32R2, FGR_64 { let DecoderNamespace = "Mips64"; } def DMFC1 : MFC1_FT<"dmfc1", GPR64Opnd, FGR64Opnd, II_DMFC1, @@ -382,9 +381,9 @@ def DMTC1 : MTC1_FT<"dmtc1", FGR64Opnd, GPR64Opnd, II_DMTC1, def FMOV_S : MMRel, ABSS_FT<"mov.s", FGR32Opnd, FGR32Opnd, II_MOV_S>, ABSS_FM<0x6, 16>; def FMOV_D32 : MMRel, ABSS_FT<"mov.d", AFGR64Opnd, AFGR64Opnd, II_MOV_D>, - ABSS_FM<0x6, 17>, AdditionalRequires<[NotFP64bit]>; + ABSS_FM<0x6, 17>, FGR_32; def FMOV_D64 : ABSS_FT<"mov.d", FGR64Opnd, FGR64Opnd, II_MOV_D>, - ABSS_FM<0x6, 17>, AdditionalRequires<[IsFP64bit]> { + ABSS_FM<0x6, 17>, FGR_64 { let DecoderNamespace = "Mips64"; } @@ -513,36 +512,14 @@ def BC1T : MMRel, BC1F_FT<"bc1t", brtarget, IIBranch, MIPS_BRANCH_T>, def BC1TL : MMRel, BC1F_FT<"bc1tl", brtarget, IIBranch, MIPS_BRANCH_T, 0>, BC1F_FM<1, 1>, ISA_MIPS2_NOT_32R6_64R6; -//===----------------------------------------------------------------------===// -// Floating Point Flag Conditions -//===----------------------------------------------------------------------===// -// Mips condition codes. They must correspond to condcode in MipsInstrInfo.h. -// They must be kept in synch. -def MIPS_FCOND_F : PatLeaf<(i32 0)>; -def MIPS_FCOND_UN : PatLeaf<(i32 1)>; -def MIPS_FCOND_OEQ : PatLeaf<(i32 2)>; -def MIPS_FCOND_UEQ : PatLeaf<(i32 3)>; -def MIPS_FCOND_OLT : PatLeaf<(i32 4)>; -def MIPS_FCOND_ULT : PatLeaf<(i32 5)>; -def MIPS_FCOND_OLE : PatLeaf<(i32 6)>; -def MIPS_FCOND_ULE : PatLeaf<(i32 7)>; -def MIPS_FCOND_SF : PatLeaf<(i32 8)>; -def MIPS_FCOND_NGLE : PatLeaf<(i32 9)>; -def MIPS_FCOND_SEQ : PatLeaf<(i32 10)>; -def MIPS_FCOND_NGL : PatLeaf<(i32 11)>; -def MIPS_FCOND_LT : PatLeaf<(i32 12)>; -def MIPS_FCOND_NGE : PatLeaf<(i32 13)>; -def MIPS_FCOND_LE : PatLeaf<(i32 14)>; -def MIPS_FCOND_NGT : PatLeaf<(i32 15)>; - /// Floating Point Compare def FCMP_S32 : MMRel, CEQS_FT<"s", FGR32, II_C_CC_S, MipsFPCmp>, CEQS_FM<16>, ISA_MIPS1_NOT_32R6_64R6; def FCMP_D32 : MMRel, CEQS_FT<"d", AFGR64, II_C_CC_D, MipsFPCmp>, CEQS_FM<17>, - ISA_MIPS1_NOT_32R6_64R6, AdditionalRequires<[NotFP64bit]>; + ISA_MIPS1_NOT_32R6_64R6, FGR_32; let DecoderNamespace = "Mips64" in def FCMP_D64 : CEQS_FT<"d", FGR64, II_C_CC_D, MipsFPCmp>, CEQS_FM<17>, - ISA_MIPS1_NOT_32R6_64R6, AdditionalRequires<[IsFP64bit]>; + ISA_MIPS1_NOT_32R6_64R6, FGR_64; //===----------------------------------------------------------------------===// // Floating Point Pseudo-Instructions @@ -554,10 +531,8 @@ class BuildPairF64Base<RegisterOperand RO> : PseudoSE<(outs RO:$dst), (ins GPR32Opnd:$lo, GPR32Opnd:$hi), [(set RO:$dst, (MipsBuildPairF64 GPR32Opnd:$lo, GPR32Opnd:$hi))]>; -def BuildPairF64 : BuildPairF64Base<AFGR64Opnd>, - AdditionalRequires<[NotFP64bit]>; -def BuildPairF64_64 : BuildPairF64Base<FGR64Opnd>, - AdditionalRequires<[IsFP64bit]>; +def BuildPairF64 : BuildPairF64Base<AFGR64Opnd>, FGR_32, HARDFLOAT; +def BuildPairF64_64 : BuildPairF64Base<FGR64Opnd>, FGR_64, HARDFLOAT; // This pseudo instr gets expanded into 2 mfc1 instrs after register // allocation. @@ -567,22 +542,20 @@ class ExtractElementF64Base<RegisterOperand RO> : PseudoSE<(outs GPR32Opnd:$dst), (ins RO:$src, i32imm:$n), [(set GPR32Opnd:$dst, (MipsExtractElementF64 RO:$src, imm:$n))]>; -def ExtractElementF64 : ExtractElementF64Base<AFGR64Opnd>, - AdditionalRequires<[NotFP64bit]>; -def ExtractElementF64_64 : ExtractElementF64Base<FGR64Opnd>, - AdditionalRequires<[IsFP64bit]>; +def ExtractElementF64 : ExtractElementF64Base<AFGR64Opnd>, FGR_32, HARDFLOAT; +def ExtractElementF64_64 : ExtractElementF64Base<FGR64Opnd>, FGR_64, HARDFLOAT; //===----------------------------------------------------------------------===// // InstAliases. //===----------------------------------------------------------------------===// def : MipsInstAlias<"bc1t $offset", (BC1T FCC0, brtarget:$offset)>, - ISA_MIPS1_NOT_32R6_64R6; + ISA_MIPS1_NOT_32R6_64R6, HARDFLOAT; def : MipsInstAlias<"bc1tl $offset", (BC1TL FCC0, brtarget:$offset)>, - ISA_MIPS2_NOT_32R6_64R6; + ISA_MIPS2_NOT_32R6_64R6, HARDFLOAT; def : MipsInstAlias<"bc1f $offset", (BC1F FCC0, brtarget:$offset)>, - ISA_MIPS1_NOT_32R6_64R6; + ISA_MIPS1_NOT_32R6_64R6, HARDFLOAT; def : MipsInstAlias<"bc1fl $offset", (BC1FL FCC0, brtarget:$offset)>, - ISA_MIPS2_NOT_32R6_64R6; + ISA_MIPS2_NOT_32R6_64R6, HARDFLOAT; //===----------------------------------------------------------------------===// // Floating Point Patterns diff --git a/contrib/llvm/lib/Target/Mips/MipsInstrFormats.td b/contrib/llvm/lib/Target/Mips/MipsInstrFormats.td index d8dae25..5f4fcc3 100644 --- a/contrib/llvm/lib/Target/Mips/MipsInstrFormats.td +++ b/contrib/llvm/lib/Target/Mips/MipsInstrFormats.td @@ -50,6 +50,20 @@ def Std2MicroMips : InstrMapping { let ValueCols = [["se"], ["micromips"]]; } +class StdMMR6Rel; + +def Std2MicroMipsR6 : InstrMapping { + let FilterClass = "StdMMR6Rel"; + // Instructions with the same BaseOpcode and isNVStore values form a row. + let RowFields = ["BaseOpcode"]; + // Instructions with the same predicate sense form a column. + let ColFields = ["Arch"]; + // The key column is the unpredicated instructions. + let KeyCol = ["se"]; + // Value columns are PredSense=true and PredSense=false + let ValueCols = [["se"], ["micromipsr6"]]; +} + class StdArch { string Arch = "se"; } @@ -212,6 +226,18 @@ class MFC3OP_FM<bits<6> op, bits<5> mfmt> let Inst{2-0} = sel; } +class MFC2OP_FM<bits<6> op, bits<5> mfmt> : StdArch { + bits<5> rt; + bits<16> imm16; + + bits<32> Inst; + + let Inst{31-26} = op; + let Inst{25-21} = mfmt; + let Inst{20-16} = rt; + let Inst{15-0} = imm16; +} + class ADD_FM<bits<6> op, bits<6> funct> : StdArch { bits<5> rd; bits<5> rs; @@ -297,6 +323,19 @@ class BGEZ_FM<bits<6> op, bits<5> funct> : StdArch { let Inst{15-0} = offset; } +class BBIT_FM<bits<6> op> : StdArch { + bits<5> rs; + bits<5> p; + bits<16> offset; + + bits<32> Inst; + + let Inst{31-26} = op; + let Inst{25-21} = rs; + let Inst{20-16} = p; + let Inst{15-0} = offset; +} + class SLTI_FM<bits<6> op> : StdArch { bits<5> rt; bits<5> rs; diff --git a/contrib/llvm/lib/Target/Mips/MipsInstrInfo.h b/contrib/llvm/lib/Target/Mips/MipsInstrInfo.h index db149d4..4589535 100644 --- a/contrib/llvm/lib/Target/Mips/MipsInstrInfo.h +++ b/contrib/llvm/lib/Target/Mips/MipsInstrInfo.h @@ -29,7 +29,7 @@ #include "MipsGenInstrInfo.inc" namespace llvm { - +class MipsSubtarget; class MipsInstrInfo : public MipsGenInstrInfo { virtual void anchor(); protected: @@ -117,6 +117,10 @@ public: const TargetRegisterInfo *TRI, int64_t Offset) const = 0; + virtual void adjustStackPtr(unsigned SP, int64_t Amount, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator I) const = 0; + /// Create an instruction which has the same operands and memory operands /// as MI but has a new opcode. MachineInstrBuilder genInstrWithNewOpc(unsigned NewOpc, diff --git a/contrib/llvm/lib/Target/Mips/MipsInstrInfo.td b/contrib/llvm/lib/Target/Mips/MipsInstrInfo.td index aef1039..58791cf 100644 --- a/contrib/llvm/lib/Target/Mips/MipsInstrInfo.td +++ b/contrib/llvm/lib/Target/Mips/MipsInstrInfo.td @@ -182,14 +182,14 @@ def HasMips64r6 : Predicate<"Subtarget->hasMips64r6()">, AssemblerPredicate<"FeatureMips64r6">; def NotMips64r6 : Predicate<"!Subtarget->hasMips64r6()">, AssemblerPredicate<"!FeatureMips64r6">; +def HasMicroMips32r6 : Predicate<"Subtarget->inMicroMips32r6Mode()">, + AssemblerPredicate<"FeatureMicroMips,FeatureMips32r6">; def InMips16Mode : Predicate<"Subtarget->inMips16Mode()">, AssemblerPredicate<"FeatureMips16">; def HasCnMips : Predicate<"Subtarget->hasCnMips()">, AssemblerPredicate<"FeatureCnMips">; -def RelocStatic : Predicate<"TM.getRelocationModel() == Reloc::Static">, - AssemblerPredicate<"FeatureMips32">; -def RelocPIC : Predicate<"TM.getRelocationModel() == Reloc::PIC_">, - AssemblerPredicate<"FeatureMips32">; +def RelocStatic : Predicate<"TM.getRelocationModel() == Reloc::Static">; +def RelocPIC : Predicate<"TM.getRelocationModel() == Reloc::PIC_">; def NoNaNsFPMath : Predicate<"TM.Options.NoNaNsFPMath">; def HasStdEnc : Predicate<"Subtarget->hasStandardEncoding()">, AssemblerPredicate<"!FeatureMips16">; @@ -249,6 +249,9 @@ class ISA_MIPS64_NOT_64R6 { class ISA_MIPS64R2 { list<Predicate> InsnPredicates = [HasMips64r2]; } class ISA_MIPS32R6 { list<Predicate> InsnPredicates = [HasMips32r6]; } class ISA_MIPS64R6 { list<Predicate> InsnPredicates = [HasMips64r6]; } +class ISA_MICROMIPS32R6 { + list<Predicate> InsnPredicates = [HasMicroMips32r6]; +} // The portions of MIPS-III that were also added to MIPS32 class INSN_MIPS3_32 { list<Predicate> InsnPredicates = [HasMips3_32]; } @@ -1000,7 +1003,7 @@ class ExtBase<string opstr, RegisterOperand RO, Operand PosOpnd, SDPatternOperator Op = null_frag>: InstSE<(outs RO:$rt), (ins RO:$rs, PosOpnd:$pos, size_ext:$size), !strconcat(opstr, " $rt, $rs, $pos, $size"), - [(set RO:$rt, (Op RO:$rs, imm:$pos, imm:$size))], NoItinerary, + [(set RO:$rt, (Op RO:$rs, imm:$pos, imm:$size))], II_EXT, FrmR, opstr>, ISA_MIPS32R2; class InsBase<string opstr, RegisterOperand RO, Operand PosOpnd, @@ -1008,7 +1011,7 @@ class InsBase<string opstr, RegisterOperand RO, Operand PosOpnd, InstSE<(outs RO:$rt), (ins RO:$rs, PosOpnd:$pos, size_ins:$size, RO:$src), !strconcat(opstr, " $rt, $rs, $pos, $size"), [(set RO:$rt, (Op RO:$rs, imm:$pos, imm:$size, RO:$src))], - NoItinerary, FrmR, opstr>, ISA_MIPS32R2 { + II_INS, FrmR, opstr>, ISA_MIPS32R2 { let Constraints = "$src = $rt"; } @@ -1120,8 +1123,9 @@ def LONG_BRANCH_ADDiu : PseudoSE<(outs GPR32Opnd:$dst), /// Arithmetic Instructions (ALU Immediate) let AdditionalPredicates = [NotInMicroMips] in { -def ADDiu : MMRel, ArithLogicI<"addiu", simm16, GPR32Opnd, II_ADDIU, immSExt16, - add>, ADDI_FM<0x9>, IsAsCheapAsAMove; +def ADDiu : MMRel, StdMMR6Rel, ArithLogicI<"addiu", simm16, GPR32Opnd, + II_ADDIU, immSExt16, add>, + ADDI_FM<0x9>, IsAsCheapAsAMove; } def ADDi : MMRel, ArithLogicI<"addi", simm16, GPR32Opnd>, ADDI_FM<0x8>, ISA_MIPS1_NOT_32R6_64R6; @@ -1130,36 +1134,40 @@ def SLTi : MMRel, SetCC_I<"slti", setlt, simm16, immSExt16, GPR32Opnd>, def SLTiu : MMRel, SetCC_I<"sltiu", setult, simm16, immSExt16, GPR32Opnd>, SLTI_FM<0xb>; let AdditionalPredicates = [NotInMicroMips] in { -def ANDi : MMRel, ArithLogicI<"andi", uimm16, GPR32Opnd, II_ANDI, immZExt16, - and>, ADDI_FM<0xc>; +def ANDi : MMRel, StdMMR6Rel, + ArithLogicI<"andi", uimm16, GPR32Opnd, II_ANDI, immZExt16, and>, + ADDI_FM<0xc>; } -def ORi : MMRel, ArithLogicI<"ori", uimm16, GPR32Opnd, II_ORI, immZExt16, - or>, +def ORi : MMRel, StdMMR6Rel, + ArithLogicI<"ori", uimm16, GPR32Opnd, II_ORI, immZExt16, or>, ADDI_FM<0xd>; -def XORi : MMRel, ArithLogicI<"xori", uimm16, GPR32Opnd, II_XORI, immZExt16, - xor>, +def XORi : MMRel, StdMMR6Rel, + ArithLogicI<"xori", uimm16, GPR32Opnd, II_XORI, immZExt16, xor>, ADDI_FM<0xe>; def LUi : MMRel, LoadUpper<"lui", GPR32Opnd, uimm16>, LUI_FM; - +let AdditionalPredicates = [NotInMicroMips] in { /// Arithmetic Instructions (3-Operand, R-Type) -def ADDu : MMRel, ArithLogicR<"addu", GPR32Opnd, 1, II_ADDU, add>, +def ADDu : MMRel, StdMMR6Rel, ArithLogicR<"addu", GPR32Opnd, 1, II_ADDU, add>, ADD_FM<0, 0x21>; def SUBu : MMRel, ArithLogicR<"subu", GPR32Opnd, 0, II_SUBU, sub>, ADD_FM<0, 0x23>; +} let Defs = [HI0, LO0] in def MUL : MMRel, ArithLogicR<"mul", GPR32Opnd, 1, II_MUL, mul>, ADD_FM<0x1c, 2>, ISA_MIPS32_NOT_32R6_64R6; -def ADD : MMRel, ArithLogicR<"add", GPR32Opnd>, ADD_FM<0, 0x20>; +def ADD : MMRel, StdMMR6Rel, ArithLogicR<"add", GPR32Opnd>, ADD_FM<0, 0x20>; def SUB : MMRel, ArithLogicR<"sub", GPR32Opnd>, ADD_FM<0, 0x22>; def SLT : MMRel, SetCC_R<"slt", setlt, GPR32Opnd>, ADD_FM<0, 0x2a>; def SLTu : MMRel, SetCC_R<"sltu", setult, GPR32Opnd>, ADD_FM<0, 0x2b>; -def AND : MMRel, ArithLogicR<"and", GPR32Opnd, 1, II_AND, and>, +let AdditionalPredicates = [NotInMicroMips] in { +def AND : MMRel, StdMMR6Rel, ArithLogicR<"and", GPR32Opnd, 1, II_AND, and>, ADD_FM<0, 0x24>; -def OR : MMRel, ArithLogicR<"or", GPR32Opnd, 1, II_OR, or>, +def OR : MMRel, StdMMR6Rel, ArithLogicR<"or", GPR32Opnd, 1, II_OR, or>, ADD_FM<0, 0x25>; -def XOR : MMRel, ArithLogicR<"xor", GPR32Opnd, 1, II_XOR, xor>, +def XOR : MMRel, StdMMR6Rel, ArithLogicR<"xor", GPR32Opnd, 1, II_XOR, xor>, ADD_FM<0, 0x26>; -def NOR : MMRel, LogicNOR<"nor", GPR32Opnd>, ADD_FM<0, 0x27>; +} +def NOR : MMRel, StdMMR6Rel, LogicNOR<"nor", GPR32Opnd>, ADD_FM<0, 0x27>; /// Shift Instructions let AdditionalPredicates = [NotInMicroMips] in { @@ -1192,11 +1200,15 @@ def LBu : Load<"lbu", GPR32Opnd, zextloadi8, II_LBU, addrDefault>, MMRel, def LH : Load<"lh", GPR32Opnd, sextloadi16, II_LH, addrDefault>, MMRel, LW_FM<0x21>; def LHu : Load<"lhu", GPR32Opnd, zextloadi16, II_LHU>, MMRel, LW_FM<0x25>; +let AdditionalPredicates = [NotInMicroMips] in { def LW : Load<"lw", GPR32Opnd, load, II_LW, addrDefault>, MMRel, LW_FM<0x23>; +} def SB : Store<"sb", GPR32Opnd, truncstorei8, II_SB>, MMRel, LW_FM<0x28>; def SH : Store<"sh", GPR32Opnd, truncstorei16, II_SH>, MMRel, LW_FM<0x29>; +let AdditionalPredicates = [NotInMicroMips] in { def SW : Store<"sw", GPR32Opnd, store, II_SW>, MMRel, LW_FM<0x2b>; +} /// load/store left/right let EncodingPredicates = []<Predicate>, // FIXME: Lack of HasStdEnc is probably a bug @@ -1211,6 +1223,7 @@ def SWR : StoreLeftRight<"swr", MipsSWR, GPR32Opnd, II_SWR>, LW_FM<0x2e>, ISA_MIPS1_NOT_32R6_64R6; } +let AdditionalPredicates = [NotInMicroMips] in { // COP2 Memory Instructions def LWC2 : LW_FT2<"lwc2", COP2Opnd, NoItinerary, load>, LW_FM<0x32>, ISA_MIPS1_NOT_32R6_64R6; @@ -1230,6 +1243,7 @@ let DecoderNamespace = "COP3_" in { def SDC3 : SW_FT3<"sdc3", COP3Opnd, NoItinerary, store>, LW_FM<0x3f>, ISA_MIPS2; } +} def SYNC : MMRel, SYNC_FT<"sync">, SYNC_FM, ISA_MIPS32; def SYNCI : MMRel, SYNCI_FT<"synci">, SYNCI_FM, ISA_MIPS32R2; @@ -1308,8 +1322,8 @@ let AdditionalPredicates = [NotInMicroMips] in { def JALRPseudo : JumpLinkRegPseudo<GPR32Opnd, JALR, RA>; } -// FIXME: JALX really requires either MIPS16 or microMIPS in addition to MIPS32. -def JALX : JumpLink<"jalx", calltarget>, FJ<0x1D>, ISA_MIPS32_NOT_32R6_64R6; +def JALX : MMRel, JumpLink<"jalx", calltarget>, FJ<0x1D>, + ISA_MIPS32_NOT_32R6_64R6; def BGEZAL : MMRel, BGEZAL_FT<"bgezal", brtarget, GPR32Opnd>, BGEZAL_FM<0x11>, ISA_MIPS1_NOT_32R6_64R6; def BGEZALL : MMRel, BGEZAL_FT<"bgezall", brtarget, GPR32Opnd, 0>, @@ -1396,9 +1410,9 @@ def MFLO : MMRel, MoveFromLOHI<"mflo", GPR32Opnd, AC0>, MFLO_FM<0x12>, } /// Sign Ext In Register Instructions. -def SEB : MMRel, SignExtInReg<"seb", i8, GPR32Opnd, II_SEB>, +def SEB : MMRel, StdMMR6Rel, SignExtInReg<"seb", i8, GPR32Opnd, II_SEB>, SEB_FM<0x10, 0x20>, ISA_MIPS32R2; -def SEH : MMRel, SignExtInReg<"seh", i16, GPR32Opnd, II_SEH>, +def SEH : MMRel, StdMMR6Rel, SignExtInReg<"seh", i16, GPR32Opnd, II_SEH>, SEB_FM<0x18, 0x20>, ISA_MIPS32R2; /// Count Leading @@ -1556,8 +1570,6 @@ def : MipsInstAlias<"j $rs", (JR GPR32Opnd:$rs), 0>; let Predicates = [NotInMicroMips] in { def : MipsInstAlias<"jalr $rs", (JALR RA, GPR32Opnd:$rs), 0>; } -def : MipsInstAlias<"jal $rs", (JALR RA, GPR32Opnd:$rs), 0>; -def : MipsInstAlias<"jal $rd,$rs", (JALR GPR32Opnd:$rd, GPR32Opnd:$rs), 0>; def : MipsInstAlias<"jalr.hb $rs", (JALR_HB RA, GPR32Opnd:$rs), 1>, ISA_MIPS32; def : MipsInstAlias<"not $rt, $rs", (NOR GPR32Opnd:$rt, GPR32Opnd:$rs, ZERO), 0>; @@ -1573,6 +1585,8 @@ def : MipsInstAlias<"sltu $rt, $rs, $imm", (SLTiu GPR32Opnd:$rt, GPR32Opnd:$rs, simm16:$imm), 0>; def : MipsInstAlias<"xor $rs, $rt, $imm", (XORi GPR32Opnd:$rs, GPR32Opnd:$rt, uimm16:$imm), 0>; +def : MipsInstAlias<"xor $rs, $imm", + (XORi GPR32Opnd:$rs, GPR32Opnd:$rs, uimm16:$imm), 0>; def : MipsInstAlias<"or $rs, $rt, $imm", (ORi GPR32Opnd:$rs, GPR32Opnd:$rt, uimm16:$imm), 0>; def : MipsInstAlias<"or $rs, $imm", @@ -1582,11 +1596,17 @@ def : MipsInstAlias<"mfc0 $rt, $rd", (MFC0 GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>; def : MipsInstAlias<"mtc0 $rt, $rd", (MTC0 GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>; def : MipsInstAlias<"mfc2 $rt, $rd", (MFC2 GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>; def : MipsInstAlias<"mtc2 $rt, $rd", (MTC2 GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>; +let AdditionalPredicates = [NotInMicroMips] in { def : MipsInstAlias<"b $offset", (BEQ ZERO, ZERO, brtarget:$offset), 0>; +} def : MipsInstAlias<"bnez $rs,$offset", (BNE GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>; +def : MipsInstAlias<"bnezl $rs,$offset", + (BNEL GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>; def : MipsInstAlias<"beqz $rs,$offset", (BEQ GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>; +def : MipsInstAlias<"beqzl $rs,$offset", + (BEQL GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>; def : MipsInstAlias<"syscall", (SYSCALL 0), 1>; def : MipsInstAlias<"break", (BREAK 0, 0), 1>; @@ -1631,20 +1651,26 @@ def : MipsInstAlias<"sync", // Assembler Pseudo Instructions //===----------------------------------------------------------------------===// -class LoadImm32< string instr_asm, Operand Od, RegisterOperand RO> : +class LoadImmediate32<string instr_asm, Operand Od, RegisterOperand RO> : MipsAsmPseudoInst<(outs RO:$rt), (ins Od:$imm32), !strconcat(instr_asm, "\t$rt, $imm32")> ; -def LoadImm32Reg : LoadImm32<"li", uimm5, GPR32Opnd>; +def LoadImm32 : LoadImmediate32<"li", uimm5, GPR32Opnd>; -class LoadAddress<string instr_asm, Operand MemOpnd, RegisterOperand RO> : +class LoadAddressFromReg32<string instr_asm, Operand MemOpnd, + RegisterOperand RO> : MipsAsmPseudoInst<(outs RO:$rt), (ins MemOpnd:$addr), !strconcat(instr_asm, "\t$rt, $addr")> ; -def LoadAddr32Reg : LoadAddress<"la", mem, GPR32Opnd>; +def LoadAddrReg32 : LoadAddressFromReg32<"la", mem, GPR32Opnd>; -class LoadAddressImm<string instr_asm, Operand Od, RegisterOperand RO> : +class LoadAddressFromImm32<string instr_asm, Operand Od, RegisterOperand RO> : MipsAsmPseudoInst<(outs RO:$rt), (ins Od:$imm32), !strconcat(instr_asm, "\t$rt, $imm32")> ; -def LoadAddr32Imm : LoadAddressImm<"la", uimm5, GPR32Opnd>; +def LoadAddrImm32 : LoadAddressFromImm32<"la", uimm5, GPR32Opnd>; + +def JalTwoReg : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), (ins GPR32Opnd:$rs), + "jal\t$rd, $rs"> ; +def JalOneReg : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs), + "jal\t$rs"> ; //===----------------------------------------------------------------------===// // Arbitrary patterns that map to one or more instructions @@ -1748,9 +1774,11 @@ def : WrapperPat<tblockaddress, ADDiu, GPR32>; def : WrapperPat<tjumptable, ADDiu, GPR32>; def : WrapperPat<tglobaltlsaddr, ADDiu, GPR32>; +let AdditionalPredicates = [NotInMicroMips] in { // Mips does not have "not", so we expand our way def : MipsPat<(not GPR32:$in), (NOR GPR32Opnd:$in, ZERO)>; +} // extended loads def : MipsPat<(i32 (extloadi1 addr:$src)), (LBu addr:$src)>; @@ -1853,7 +1881,9 @@ def : MipsPat<(bswap GPR32:$rt), (ROTR (WSBH GPR32:$rt), 16)>; let AddedComplexity = 40 in { def : LoadRegImmPat<LBu, i32, zextloadi8>; def : LoadRegImmPat<LH, i32, sextloadi16>; + let AdditionalPredicates = [NotInMicroMips] in { def : LoadRegImmPat<LW, i32, load>; + } } //===----------------------------------------------------------------------===// @@ -1885,3 +1915,7 @@ include "MipsMSAInstrInfo.td" include "MicroMipsInstrFormats.td" include "MicroMipsInstrInfo.td" include "MicroMipsInstrFPU.td" + +// Micromips r6 +include "MicroMips32r6InstrFormats.td" +include "MicroMips32r6InstrInfo.td" diff --git a/contrib/llvm/lib/Target/Mips/MipsLongBranch.cpp b/contrib/llvm/lib/Target/Mips/MipsLongBranch.cpp index aae0922..90f8cc0 100644 --- a/contrib/llvm/lib/Target/Mips/MipsLongBranch.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsLongBranch.cpp @@ -63,11 +63,9 @@ namespace { public: static char ID; MipsLongBranch(TargetMachine &tm) - : MachineFunctionPass(ID), TM(tm), - IsPIC(TM.getRelocationModel() == Reloc::PIC_), - ABI(TM.getSubtarget<MipsSubtarget>().getABI()), - LongBranchSeqSize(!IsPIC ? 2 : (ABI.IsN64() ? 10 : - (!TM.getSubtarget<MipsSubtarget>().isTargetNaCl() ? 9 : 10))) {} + : MachineFunctionPass(ID), TM(tm), + IsPIC(TM.getRelocationModel() == Reloc::PIC_), + ABI(static_cast<const MipsTargetMachine &>(TM).getABI()) {} const char *getPassName() const override { return "Mips Long Branch"; @@ -170,7 +168,7 @@ void MipsLongBranch::initMBBInfo() { MBBInfos.resize(MF->size()); const MipsInstrInfo *TII = - static_cast<const MipsInstrInfo *>(TM.getSubtargetImpl()->getInstrInfo()); + static_cast<const MipsInstrInfo *>(MF->getSubtarget().getInstrInfo()); for (unsigned I = 0, E = MBBInfos.size(); I < E; ++I) { MachineBasicBlock *MBB = MF->getBlockNumbered(I); @@ -216,8 +214,8 @@ int64_t MipsLongBranch::computeOffset(const MachineInstr *Br) { // MachineBasicBlock operand MBBOpnd. void MipsLongBranch::replaceBranch(MachineBasicBlock &MBB, Iter Br, DebugLoc DL, MachineBasicBlock *MBBOpnd) { - const MipsInstrInfo *TII = - static_cast<const MipsInstrInfo *>(TM.getSubtargetImpl()->getInstrInfo()); + const MipsInstrInfo *TII = static_cast<const MipsInstrInfo *>( + MBB.getParent()->getSubtarget().getInstrInfo()); unsigned NewOpc = TII->getOppositeBranchOpc(Br->getOpcode()); const MCInstrDesc &NewDesc = TII->get(NewOpc); @@ -258,9 +256,10 @@ void MipsLongBranch::expandToLongBranch(MBBInfo &I) { const BasicBlock *BB = MBB->getBasicBlock(); MachineFunction::iterator FallThroughMBB = ++MachineFunction::iterator(MBB); MachineBasicBlock *LongBrMBB = MF->CreateMachineBasicBlock(BB); - + const MipsSubtarget &Subtarget = + static_cast<const MipsSubtarget &>(MF->getSubtarget()); const MipsInstrInfo *TII = - static_cast<const MipsInstrInfo *>(TM.getSubtargetImpl()->getInstrInfo()); + static_cast<const MipsInstrInfo *>(Subtarget.getInstrInfo()); MF->insert(FallThroughMBB, LongBrMBB); MBB->removeSuccessor(TgtMBB); @@ -275,8 +274,6 @@ void MipsLongBranch::expandToLongBranch(MBBInfo &I) { // We must select between the MIPS32r6/MIPS64r6 BAL (which is a normal // instruction) and the pre-MIPS32r6/MIPS64r6 definition (which is an // pseudo-instruction wrapping BGEZAL). - - const MipsSubtarget &Subtarget = TM.getSubtarget<MipsSubtarget>(); unsigned BalOp = Subtarget.hasMips32r6() ? Mips::BAL : Mips::BAL_BR; if (!ABI.IsN64()) { @@ -333,7 +330,7 @@ void MipsLongBranch::expandToLongBranch(MBBInfo &I) { BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::LW), Mips::RA) .addReg(Mips::SP).addImm(0); - if (!TM.getSubtarget<MipsSubtarget>().isTargetNaCl()) { + if (!Subtarget.isTargetNaCl()) { MIBundleBuilder(*BalTgtMBB, Pos) .append(BuildMI(*MF, DL, TII->get(Mips::JR)).addReg(Mips::AT)) .append(BuildMI(*MF, DL, TII->get(Mips::ADDiu), Mips::SP) @@ -452,14 +449,17 @@ static void emitGPDisp(MachineFunction &F, const MipsInstrInfo *TII) { } bool MipsLongBranch::runOnMachineFunction(MachineFunction &F) { + const MipsSubtarget &STI = + static_cast<const MipsSubtarget &>(F.getSubtarget()); const MipsInstrInfo *TII = - static_cast<const MipsInstrInfo *>(TM.getSubtargetImpl()->getInstrInfo()); + static_cast<const MipsInstrInfo *>(STI.getInstrInfo()); + LongBranchSeqSize = + !IsPIC ? 2 : (ABI.IsN64() ? 10 : (!STI.isTargetNaCl() ? 9 : 10)); - const MipsSubtarget &STI = TM.getSubtarget<MipsSubtarget>(); if (STI.inMips16Mode() || !STI.enableLongBranchPass()) return false; if ((TM.getRelocationModel() == Reloc::PIC_) && - TM.getSubtarget<MipsSubtarget>().isABI_O32() && + static_cast<const MipsTargetMachine &>(TM).getABI().IsO32() && F.getInfo<MipsFunctionInfo>()->globalBaseRegSet()) emitGPDisp(F, TII); @@ -481,10 +481,10 @@ bool MipsLongBranch::runOnMachineFunction(MachineFunction &F) { if (!I->Br || I->HasLongBranch) continue; - int ShVal = TM.getSubtarget<MipsSubtarget>().inMicroMipsMode() ? 2 : 4; + int ShVal = STI.inMicroMipsMode() ? 2 : 4; int64_t Offset = computeOffset(I->Br) / ShVal; - if (TM.getSubtarget<MipsSubtarget>().isTargetNaCl()) { + if (STI.isTargetNaCl()) { // The offset calculation does not include sandboxing instructions // that will be added later in the MC layer. Since at this point we // don't know the exact amount of code that "sandboxing" will add, we diff --git a/contrib/llvm/lib/Target/Mips/MipsMCInstLower.cpp b/contrib/llvm/lib/Target/Mips/MipsMCInstLower.cpp index 821392e..6b2a44d 100644 --- a/contrib/llvm/lib/Target/Mips/MipsMCInstLower.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsMCInstLower.cpp @@ -22,6 +22,7 @@ #include "llvm/MC/MCContext.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCStreamer.h" using namespace llvm; @@ -100,17 +101,17 @@ MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO, llvm_unreachable("<unknown operand type>"); } - const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::Create(Symbol, Kind, *Ctx); + const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::create(Symbol, Kind, *Ctx); if (!Offset) - return MCOperand::CreateExpr(MCSym); + return MCOperand::createExpr(MCSym); // Assume offset is never negative. assert(Offset > 0); - const MCConstantExpr *OffsetExpr = MCConstantExpr::Create(Offset, *Ctx); - const MCBinaryExpr *Add = MCBinaryExpr::CreateAdd(MCSym, OffsetExpr, *Ctx); - return MCOperand::CreateExpr(Add); + const MCConstantExpr *OffsetExpr = MCConstantExpr::create(Offset, *Ctx); + const MCBinaryExpr *Add = MCBinaryExpr::createAdd(MCSym, OffsetExpr, *Ctx); + return MCOperand::createExpr(Add); } /* @@ -134,9 +135,9 @@ MCOperand MipsMCInstLower::LowerOperand(const MachineOperand &MO, case MachineOperand::MO_Register: // Ignore all implicit register operands. if (MO.isImplicit()) break; - return MCOperand::CreateReg(MO.getReg()); + return MCOperand::createReg(MO.getReg()); case MachineOperand::MO_Immediate: - return MCOperand::CreateImm(MO.getImm() + offset); + return MCOperand::createImm(MO.getImm() + offset); case MachineOperand::MO_MachineBasicBlock: case MachineOperand::MO_GlobalAddress: case MachineOperand::MO_ExternalSymbol: @@ -154,11 +155,11 @@ MCOperand MipsMCInstLower::LowerOperand(const MachineOperand &MO, MCOperand MipsMCInstLower::createSub(MachineBasicBlock *BB1, MachineBasicBlock *BB2, MCSymbolRefExpr::VariantKind Kind) const { - const MCSymbolRefExpr *Sym1 = MCSymbolRefExpr::Create(BB1->getSymbol(), *Ctx); - const MCSymbolRefExpr *Sym2 = MCSymbolRefExpr::Create(BB2->getSymbol(), *Ctx); - const MCBinaryExpr *Sub = MCBinaryExpr::CreateSub(Sym1, Sym2, *Ctx); + const MCSymbolRefExpr *Sym1 = MCSymbolRefExpr::create(BB1->getSymbol(), *Ctx); + const MCSymbolRefExpr *Sym2 = MCSymbolRefExpr::create(BB2->getSymbol(), *Ctx); + const MCBinaryExpr *Sub = MCBinaryExpr::createSub(Sym1, Sym2, *Ctx); - return MCOperand::CreateExpr(MipsMCExpr::Create(Kind, Sub, *Ctx)); + return MCOperand::createExpr(MipsMCExpr::create(Kind, Sub, *Ctx)); } void MipsMCInstLower:: diff --git a/contrib/llvm/lib/Target/Mips/MipsMSAInstrInfo.td b/contrib/llvm/lib/Target/Mips/MipsMSAInstrInfo.td index 68230e6..970e98e 100644 --- a/contrib/llvm/lib/Target/Mips/MipsMSAInstrInfo.td +++ b/contrib/llvm/lib/Target/Mips/MipsMSAInstrInfo.td @@ -63,6 +63,9 @@ def MipsVExtractSExt : SDNode<"MipsISD::VEXTRACT_SEXT_ELT", def MipsVExtractZExt : SDNode<"MipsISD::VEXTRACT_ZEXT_ELT", SDTypeProfile<1, 3, [SDTCisPtrTy<2>]>, []>; +def immZExt4Ptr : ImmLeaf<iPTR, [{return isUInt<4>(Imm);}]>; +def immZExt6Ptr : ImmLeaf<iPTR, [{return isUInt<6>(Imm);}]>; + // Operands // The immediate of an LSA instruction needs special handling @@ -84,6 +87,14 @@ def uimm4 : Operand<i32> { let PrintMethod = "printUnsignedImm8"; } +def uimm4_ptr : Operand<iPTR> { + let PrintMethod = "printUnsignedImm8"; +} + +def uimm6_ptr : Operand<iPTR> { + let PrintMethod = "printUnsignedImm8"; +} + def uimm8 : Operand<i32> { let PrintMethod = "printUnsignedImm8"; } @@ -364,7 +375,7 @@ def vsplat_imm_eq_1 : PatLeaf<(build_vector), [{ APInt Imm; EVT EltTy = N->getValueType(0).getVectorElementType(); - return selectVSplat (N, Imm) && + return selectVSplat(N, Imm, EltTy.getSizeInBits()) && Imm.getBitWidth() == EltTy.getSizeInBits() && Imm == 1; }]>; @@ -373,7 +384,7 @@ def vsplati64_imm_eq_1 : PatLeaf<(bitconvert (v4i32 (build_vector))), [{ SDNode *BV = N->getOperand(0).getNode(); EVT EltTy = N->getValueType(0).getVectorElementType(); - return selectVSplat (BV, Imm) && + return selectVSplat(BV, Imm, EltTy.getSizeInBits()) && Imm.getBitWidth() == EltTy.getSizeInBits() && Imm == 1; }]>; @@ -1273,9 +1284,9 @@ class MSA_COPY_DESC_BASE<string instr_asm, SDPatternOperator OpNode, RegisterOperand ROWS, InstrItinClass itin = NoItinerary> { dag OutOperandList = (outs ROD:$rd); - dag InOperandList = (ins ROWS:$ws, uimm4:$n); + dag InOperandList = (ins ROWS:$ws, uimm4_ptr:$n); string AsmString = !strconcat(instr_asm, "\t$rd, $ws[$n]"); - list<dag> Pattern = [(set ROD:$rd, (OpNode (VecTy ROWS:$ws), immZExt4:$n))]; + list<dag> Pattern = [(set ROD:$rd, (OpNode (VecTy ROWS:$ws), immZExt4Ptr:$n))]; InstrItinClass Itinerary = itin; } @@ -1293,8 +1304,8 @@ class MSA_ELM_SLD_DESC_BASE<string instr_asm, SDPatternOperator OpNode, class MSA_COPY_PSEUDO_BASE<SDPatternOperator OpNode, ValueType VecTy, RegisterClass RCD, RegisterClass RCWS> : - MSAPseudo<(outs RCD:$wd), (ins RCWS:$ws, uimm4:$n), - [(set RCD:$wd, (OpNode (VecTy RCWS:$ws), immZExt4:$n))]> { + MSAPseudo<(outs RCD:$wd), (ins RCWS:$ws, uimm4_ptr:$n), + [(set RCD:$wd, (OpNode (VecTy RCWS:$ws), immZExt4Ptr:$n))]> { bit usesCustomInserter = 1; } @@ -1479,29 +1490,30 @@ class MSA_INSERT_DESC_BASE<string instr_asm, SDPatternOperator OpNode, RegisterOperand ROWD, RegisterOperand ROS, InstrItinClass itin = NoItinerary> { dag OutOperandList = (outs ROWD:$wd); - dag InOperandList = (ins ROWD:$wd_in, ROS:$rs, uimm6:$n); + dag InOperandList = (ins ROWD:$wd_in, ROS:$rs, uimm6_ptr:$n); string AsmString = !strconcat(instr_asm, "\t$wd[$n], $rs"); list<dag> Pattern = [(set ROWD:$wd, (OpNode ROWD:$wd_in, ROS:$rs, - immZExt6:$n))]; + immZExt6Ptr:$n))]; InstrItinClass Itinerary = itin; string Constraints = "$wd = $wd_in"; } class MSA_INSERT_PSEUDO_BASE<SDPatternOperator OpNode, ValueType Ty, RegisterOperand ROWD, RegisterOperand ROFS> : - MSAPseudo<(outs ROWD:$wd), (ins ROWD:$wd_in, uimm6:$n, ROFS:$fs), + MSAPseudo<(outs ROWD:$wd), (ins ROWD:$wd_in, uimm6_ptr:$n, ROFS:$fs), [(set ROWD:$wd, (OpNode (Ty ROWD:$wd_in), ROFS:$fs, - immZExt6:$n))]> { + immZExt6Ptr:$n))]> { bit usesCustomInserter = 1; string Constraints = "$wd = $wd_in"; } class MSA_INSERT_VIDX_PSEUDO_BASE<SDPatternOperator OpNode, ValueType Ty, - RegisterOperand ROWD, RegisterOperand ROFS> : - MSAPseudo<(outs ROWD:$wd), (ins ROWD:$wd_in, GPR32Opnd:$n, ROFS:$fs), + RegisterOperand ROWD, RegisterOperand ROFS, + RegisterOperand ROIdx> : + MSAPseudo<(outs ROWD:$wd), (ins ROWD:$wd_in, ROIdx:$n, ROFS:$fs), [(set ROWD:$wd, (OpNode (Ty ROWD:$wd_in), ROFS:$fs, - GPR32Opnd:$n))]> { + ROIdx:$n))]> { bit usesCustomInserter = 1; string Constraints = "$wd = $wd_in"; } @@ -2302,13 +2314,13 @@ class INSERT_D_DESC : MSA_INSERT_DESC_BASE<"insert.d", vinsert_v2i64, MSA128DOpnd, GPR64Opnd>; class INSERT_B_VIDX_PSEUDO_DESC : - MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v16i8, MSA128BOpnd, GPR32Opnd>; + MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v16i8, MSA128BOpnd, GPR32Opnd, GPR32Opnd>; class INSERT_H_VIDX_PSEUDO_DESC : - MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v8i16, MSA128HOpnd, GPR32Opnd>; + MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v8i16, MSA128HOpnd, GPR32Opnd, GPR32Opnd>; class INSERT_W_VIDX_PSEUDO_DESC : - MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v4i32, MSA128WOpnd, GPR32Opnd>; + MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v4i32, MSA128WOpnd, GPR32Opnd, GPR32Opnd>; class INSERT_D_VIDX_PSEUDO_DESC : - MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v2i64, MSA128DOpnd, GPR64Opnd>; + MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v2i64, MSA128DOpnd, GPR64Opnd, GPR32Opnd>; class INSERT_FW_PSEUDO_DESC : MSA_INSERT_PSEUDO_BASE<vector_insert, v4f32, MSA128WOpnd, FGR32Opnd>; @@ -2316,9 +2328,23 @@ class INSERT_FD_PSEUDO_DESC : MSA_INSERT_PSEUDO_BASE<vector_insert, v2f64, MSA128DOpnd, FGR64Opnd>; class INSERT_FW_VIDX_PSEUDO_DESC : - MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v4f32, MSA128WOpnd, FGR32Opnd>; + MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v4f32, MSA128WOpnd, FGR32Opnd, GPR32Opnd>; class INSERT_FD_VIDX_PSEUDO_DESC : - MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v2f64, MSA128DOpnd, FGR64Opnd>; + MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v2f64, MSA128DOpnd, FGR64Opnd, GPR32Opnd>; + +class INSERT_B_VIDX64_PSEUDO_DESC : + MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v16i8, MSA128BOpnd, GPR32Opnd, GPR64Opnd>; +class INSERT_H_VIDX64_PSEUDO_DESC : + MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v8i16, MSA128HOpnd, GPR32Opnd, GPR64Opnd>; +class INSERT_W_VIDX64_PSEUDO_DESC : + MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v4i32, MSA128WOpnd, GPR32Opnd, GPR64Opnd>; +class INSERT_D_VIDX64_PSEUDO_DESC : + MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v2i64, MSA128DOpnd, GPR64Opnd, GPR64Opnd>; + +class INSERT_FW_VIDX64_PSEUDO_DESC : + MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v4f32, MSA128WOpnd, FGR32Opnd, GPR64Opnd>; +class INSERT_FD_VIDX64_PSEUDO_DESC : + MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v2f64, MSA128DOpnd, FGR64Opnd, GPR64Opnd>; class INSVE_B_DESC : MSA_INSVE_DESC_BASE<"insve.b", insve_v16i8, MSA128BOpnd>; @@ -3236,6 +3262,13 @@ def INSERT_D_VIDX_PSEUDO : INSERT_D_VIDX_PSEUDO_DESC; def INSERT_FW_VIDX_PSEUDO : INSERT_FW_VIDX_PSEUDO_DESC; def INSERT_FD_VIDX_PSEUDO : INSERT_FD_VIDX_PSEUDO_DESC; +def INSERT_B_VIDX64_PSEUDO : INSERT_B_VIDX64_PSEUDO_DESC; +def INSERT_H_VIDX64_PSEUDO : INSERT_H_VIDX64_PSEUDO_DESC; +def INSERT_W_VIDX64_PSEUDO : INSERT_W_VIDX64_PSEUDO_DESC; +def INSERT_D_VIDX64_PSEUDO : INSERT_D_VIDX64_PSEUDO_DESC; +def INSERT_FW_VIDX64_PSEUDO : INSERT_FW_VIDX64_PSEUDO_DESC; +def INSERT_FD_VIDX64_PSEUDO : INSERT_FD_VIDX64_PSEUDO_DESC; + def LD_B: LD_B_ENC, LD_B_DESC; def LD_H: LD_H_ENC, LD_H_DESC; def LD_W: LD_W_ENC, LD_W_DESC; @@ -3805,3 +3838,93 @@ def : MSAPat<(f64 (vector_extract v2f64:$ws, i32:$idx)), (f64 (EXTRACT_SUBREG (SPLAT_D v2f64:$ws, i32:$idx), sub_64))>; + +// Vector extraction with variable index (N64 ABI) +def : MSAPat< + (i32 (vextract_sext_i8 v16i8:$ws, i64:$idx)), + (SRA (COPY_TO_REGCLASS + (i32 (EXTRACT_SUBREG + (SPLAT_B v16i8:$ws, + (COPY_TO_REGCLASS + (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), + sub_lo)), + GPR32), + (i32 24))>; +def : MSAPat< + (i32 (vextract_sext_i16 v8i16:$ws, i64:$idx)), + (SRA (COPY_TO_REGCLASS + (i32 (EXTRACT_SUBREG + (SPLAT_H v8i16:$ws, + (COPY_TO_REGCLASS + (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), + sub_lo)), + GPR32), + (i32 16))>; +def : MSAPat< + (i32 (vextract_sext_i32 v4i32:$ws, i64:$idx)), + (COPY_TO_REGCLASS + (i32 (EXTRACT_SUBREG + (SPLAT_W v4i32:$ws, + (COPY_TO_REGCLASS + (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), + sub_lo)), + GPR32)>; +def : MSAPat< + (i64 (vextract_sext_i64 v2i64:$ws, i64:$idx)), + (COPY_TO_REGCLASS + (i64 (EXTRACT_SUBREG + (SPLAT_D v2i64:$ws, + (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), + sub_64)), + GPR64), [HasMSA, IsGP64bit]>; + +def : MSAPat< + (i32 (vextract_zext_i8 v16i8:$ws, i64:$idx)), + (SRL (COPY_TO_REGCLASS + (i32 (EXTRACT_SUBREG + (SPLAT_B v16i8:$ws, + (COPY_TO_REGCLASS + (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), + sub_lo)), + GPR32), + (i32 24))>; +def : MSAPat< + (i32 (vextract_zext_i16 v8i16:$ws, i64:$idx)), + (SRL (COPY_TO_REGCLASS + (i32 (EXTRACT_SUBREG + (SPLAT_H v8i16:$ws, + (COPY_TO_REGCLASS + (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), + sub_lo)), + GPR32), + (i32 16))>; +def : MSAPat< + (i32 (vextract_zext_i32 v4i32:$ws, i64:$idx)), + (COPY_TO_REGCLASS + (i32 (EXTRACT_SUBREG + (SPLAT_W v4i32:$ws, + (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), + sub_lo)), + GPR32)>; +def : MSAPat< + (i64 (vextract_zext_i64 v2i64:$ws, i64:$idx)), + (COPY_TO_REGCLASS + (i64 (EXTRACT_SUBREG + (SPLAT_D v2i64:$ws, + (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), + sub_64)), + GPR64), + [HasMSA, IsGP64bit]>; + +def : MSAPat< + (f32 (vector_extract v4f32:$ws, i64:$idx)), + (f32 (EXTRACT_SUBREG + (SPLAT_W v4f32:$ws, + (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), + sub_lo))>; +def : MSAPat< + (f64 (vector_extract v2f64:$ws, i64:$idx)), + (f64 (EXTRACT_SUBREG + (SPLAT_D v2f64:$ws, + (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG i64:$idx, sub_32)), GPR32)), + sub_64))>; diff --git a/contrib/llvm/lib/Target/Mips/MipsMachineFunction.cpp b/contrib/llvm/lib/Target/Mips/MipsMachineFunction.cpp index 19babc7..0d1ee04 100644 --- a/contrib/llvm/lib/Target/Mips/MipsMachineFunction.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsMachineFunction.cpp @@ -7,10 +7,11 @@ // //===----------------------------------------------------------------------===// -#include "MipsMachineFunction.h" #include "MCTargetDesc/MipsBaseInfo.h" #include "MipsInstrInfo.h" +#include "MipsMachineFunction.h" #include "MipsSubtarget.h" +#include "MipsTargetMachine.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/IR/Function.h" @@ -59,15 +60,7 @@ void MipsCallEntry::printCustom(raw_ostream &O) const { #endif } -MipsFunctionInfo::~MipsFunctionInfo() { - for (StringMap<const MipsCallEntry *>::iterator - I = ExternalCallEntries.begin(), E = ExternalCallEntries.end(); I != E; - ++I) - delete I->getValue(); - - for (const auto &Entry : GlobalCallEntries) - delete Entry.second; -} +MipsFunctionInfo::~MipsFunctionInfo() {} bool MipsFunctionInfo::globalBaseRegSet() const { return GlobalBaseReg; @@ -78,12 +71,19 @@ unsigned MipsFunctionInfo::getGlobalBaseReg() { if (GlobalBaseReg) return GlobalBaseReg; - const MipsSubtarget &ST = MF.getTarget().getSubtarget<MipsSubtarget>(); + MipsSubtarget const &STI = + static_cast<const MipsSubtarget &>(MF.getSubtarget()); const TargetRegisterClass *RC = - ST.inMips16Mode() ? &Mips::CPU16RegsRegClass - : ST.isABI_N64() ? &Mips::GPR64RegClass - : &Mips::GPR32RegClass; + STI.inMips16Mode() + ? &Mips::CPU16RegsRegClass + : STI.inMicroMipsMode() + ? &Mips::GPRMM16RegClass + : static_cast<const MipsTargetMachine &>(MF.getTarget()) + .getABI() + .IsN64() + ? &Mips::GPR64RegClass + : &Mips::GPR32RegClass; return GlobalBaseReg = MF.getRegInfo().createVirtualRegister(RC); } @@ -101,9 +101,10 @@ unsigned MipsFunctionInfo::getMips16SPAliasReg() { void MipsFunctionInfo::createEhDataRegsFI() { for (int I = 0; I < 4; ++I) { - const MipsSubtarget &ST = MF.getTarget().getSubtarget<MipsSubtarget>(); - const TargetRegisterClass *RC = ST.isABI_N64() ? - &Mips::GPR64RegClass : &Mips::GPR32RegClass; + const TargetRegisterClass *RC = + static_cast<const MipsTargetMachine &>(MF.getTarget()).getABI().IsN64() + ? &Mips::GPR64RegClass + : &Mips::GPR32RegClass; EhDataRegFI[I] = MF.getFrameInfo()->CreateStackObject(RC->getSize(), RC->getAlignment(), false); @@ -116,21 +117,21 @@ bool MipsFunctionInfo::isEhDataRegFI(int FI) const { } MachinePointerInfo MipsFunctionInfo::callPtrInfo(StringRef Name) { - const MipsCallEntry *&E = ExternalCallEntries[Name]; + std::unique_ptr<const MipsCallEntry> &E = ExternalCallEntries[Name]; if (!E) - E = new MipsCallEntry(Name); + E = llvm::make_unique<MipsCallEntry>(Name); - return MachinePointerInfo(E); + return MachinePointerInfo(E.get()); } MachinePointerInfo MipsFunctionInfo::callPtrInfo(const GlobalValue *Val) { - const MipsCallEntry *&E = GlobalCallEntries[Val]; + std::unique_ptr<const MipsCallEntry> &E = GlobalCallEntries[Val]; if (!E) - E = new MipsCallEntry(Val); + E = llvm::make_unique<MipsCallEntry>(Val); - return MachinePointerInfo(E); + return MachinePointerInfo(E.get()); } int MipsFunctionInfo::getMoveF64ViaSpillFI(const TargetRegisterClass *RC) { diff --git a/contrib/llvm/lib/Target/Mips/MipsMachineFunction.h b/contrib/llvm/lib/Target/Mips/MipsMachineFunction.h index 217f307..32436ef 100644 --- a/contrib/llvm/lib/Target/Mips/MipsMachineFunction.h +++ b/contrib/llvm/lib/Target/Mips/MipsMachineFunction.h @@ -144,8 +144,9 @@ private: int MoveF64ViaSpillFI; /// MipsCallEntry maps. - StringMap<const MipsCallEntry *> ExternalCallEntries; - ValueMap<const GlobalValue *, const MipsCallEntry *> GlobalCallEntries; + StringMap<std::unique_ptr<const MipsCallEntry>> ExternalCallEntries; + ValueMap<const GlobalValue *, std::unique_ptr<const MipsCallEntry>> + GlobalCallEntries; }; } // end of namespace llvm diff --git a/contrib/llvm/lib/Target/Mips/MipsModuleISelDAGToDAG.cpp b/contrib/llvm/lib/Target/Mips/MipsModuleISelDAGToDAG.cpp index b011e8f..b18a673 100644 --- a/contrib/llvm/lib/Target/Mips/MipsModuleISelDAGToDAG.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsModuleISelDAGToDAG.cpp @@ -8,15 +8,36 @@ // //===----------------------------------------------------------------------===// -#include "MipsISelDAGToDAG.h" -#include "MipsModuleISelDAGToDAG.h" -#include "llvm/Support/Casting.h" +#include "Mips.h" +#include "MipsTargetMachine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" +using namespace llvm; + #define DEBUG_TYPE "mips-isel" -namespace llvm { +namespace { + class MipsModuleDAGToDAGISel : public MachineFunctionPass { + public: + static char ID; + + explicit MipsModuleDAGToDAGISel(MipsTargetMachine &TM_) + : MachineFunctionPass(ID), TM(TM_) {} + + // Pass Name + const char *getPassName() const override { + return "MIPS DAG->DAG Pattern Instruction Selection"; + } + + bool runOnMachineFunction(MachineFunction &MF) override; + + protected: + MipsTargetMachine &TM; + }; + + char MipsModuleDAGToDAGISel::ID = 0; +} bool MipsModuleDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { DEBUG(errs() << "In MipsModuleDAGToDAGISel::runMachineFunction\n"); @@ -24,13 +45,6 @@ bool MipsModuleDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { return false; } -char MipsModuleDAGToDAGISel::ID = 0; - -} - - -llvm::FunctionPass *llvm::createMipsModuleISelDag(MipsTargetMachine &TM) { +llvm::FunctionPass *llvm::createMipsModuleISelDagPass(MipsTargetMachine &TM) { return new MipsModuleDAGToDAGISel(TM); } - - diff --git a/contrib/llvm/lib/Target/Mips/MipsModuleISelDAGToDAG.h b/contrib/llvm/lib/Target/Mips/MipsModuleISelDAGToDAG.h deleted file mode 100644 index 85bae47..0000000 --- a/contrib/llvm/lib/Target/Mips/MipsModuleISelDAGToDAG.h +++ /dev/null @@ -1,58 +0,0 @@ -//===---- MipsModuleISelDAGToDAG.h - Change Subtarget --------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines a pass used to change the subtarget for the -// Mips Instruction selector. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MIPSMODULEISELDAGTODAG_H -#define LLVM_LIB_TARGET_MIPS_MIPSMODULEISELDAGTODAG_H - -#include "Mips.h" -#include "MipsSubtarget.h" -#include "MipsTargetMachine.h" -#include "llvm/CodeGen/SelectionDAGISel.h" - - -//===----------------------------------------------------------------------===// -// Instruction Selector Implementation -//===----------------------------------------------------------------------===// - -//===----------------------------------------------------------------------===// -// MipsModuleDAGToDAGISel - MIPS specific code to select MIPS machine -// instructions for SelectionDAG operations. -//===----------------------------------------------------------------------===// -namespace llvm { - -class MipsModuleDAGToDAGISel : public MachineFunctionPass { -public: - - static char ID; - - explicit MipsModuleDAGToDAGISel(MipsTargetMachine &TM_) - : MachineFunctionPass(ID), TM(TM_) {} - - // Pass Name - const char *getPassName() const override { - return "MIPS DAG->DAG Pattern Instruction Selection"; - } - - bool runOnMachineFunction(MachineFunction &MF) override; - -protected: - MipsTargetMachine &TM; -}; - -/// createMipsISelDag - This pass converts a legalized DAG into a -/// MIPS-specific DAG, ready for instruction scheduling. -FunctionPass *createMipsModuleISelDag(MipsTargetMachine &TM); -} - -#endif diff --git a/contrib/llvm/lib/Target/Mips/MipsOptimizePICCall.cpp b/contrib/llvm/lib/Target/Mips/MipsOptimizePICCall.cpp index 22c524e..7c940ee 100644 --- a/contrib/llvm/lib/Target/Mips/MipsOptimizePICCall.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsOptimizePICCall.cpp @@ -174,7 +174,7 @@ void MBBInfo::postVisit() { // OptimizePICCall methods. bool OptimizePICCall::runOnMachineFunction(MachineFunction &F) { - if (F.getTarget().getSubtarget<MipsSubtarget>().inMips16Mode()) + if (static_cast<const MipsSubtarget &>(F.getSubtarget()).inMips16Mode()) return false; // Do a pre-order traversal of the dominator tree. diff --git a/contrib/llvm/lib/Target/Mips/MipsOptionRecord.h b/contrib/llvm/lib/Target/Mips/MipsOptionRecord.h index f82544a..746feab 100644 --- a/contrib/llvm/lib/Target/Mips/MipsOptionRecord.h +++ b/contrib/llvm/lib/Target/Mips/MipsOptionRecord.h @@ -36,9 +36,8 @@ public: class MipsRegInfoRecord : public MipsOptionRecord { public: - MipsRegInfoRecord(MipsELFStreamer *S, MCContext &Context, - const MCSubtargetInfo &STI) - : Streamer(S), Context(Context), STI(STI) { + MipsRegInfoRecord(MipsELFStreamer *S, MCContext &Context) + : Streamer(S), Context(Context) { ri_gprmask = 0; ri_cprmask[0] = ri_cprmask[1] = ri_cprmask[2] = ri_cprmask[3] = 0; ri_gp_value = 0; @@ -53,7 +52,7 @@ public: COP2RegClass = &(TRI->getRegClass(Mips::COP2RegClassID)); COP3RegClass = &(TRI->getRegClass(Mips::COP3RegClassID)); } - ~MipsRegInfoRecord() {} + ~MipsRegInfoRecord() override {} void EmitMipsOptionRecord() override; void SetPhysRegUsed(unsigned Reg, const MCRegisterInfo *MCRegInfo); @@ -61,7 +60,6 @@ public: private: MipsELFStreamer *Streamer; MCContext &Context; - const MCSubtargetInfo &STI; const MCRegisterClass *GPR32RegClass; const MCRegisterClass *GPR64RegClass; const MCRegisterClass *FGR32RegClass; diff --git a/contrib/llvm/lib/Target/Mips/MipsOs16.cpp b/contrib/llvm/lib/Target/Mips/MipsOs16.cpp index 7aae964..b6cd791 100644 --- a/contrib/llvm/lib/Target/Mips/MipsOs16.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsOs16.cpp @@ -11,14 +11,16 @@ // //===----------------------------------------------------------------------===// -#include "MipsOs16.h" +#include "llvm/IR/Instructions.h" +#include "Mips.h" #include "llvm/IR/Module.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" -#define DEBUG_TYPE "mips-os16" +using namespace llvm; +#define DEBUG_TYPE "mips-os16" static cl::opt<std::string> Mips32FunctionMask( "mips32-function-mask", @@ -27,70 +29,83 @@ static cl::opt<std::string> Mips32FunctionMask( cl::Hidden); namespace { + class MipsOs16 : public ModulePass { + public: + static char ID; + + MipsOs16() : ModulePass(ID) {} + + const char *getPassName() const override { + return "MIPS Os16 Optimization"; + } + + bool runOnModule(Module &M) override; + }; + + char MipsOs16::ID = 0; +} - // Figure out if we need float point based on the function signature. - // We need to move variables in and/or out of floating point - // registers because of the ABI - // - bool needsFPFromSig(Function &F) { - Type* RetType = F.getReturnType(); - switch (RetType->getTypeID()) { +// Figure out if we need float point based on the function signature. +// We need to move variables in and/or out of floating point +// registers because of the ABI +// +static bool needsFPFromSig(Function &F) { + Type* RetType = F.getReturnType(); + switch (RetType->getTypeID()) { + case Type::FloatTyID: + case Type::DoubleTyID: + return true; + default: + ; + } + if (F.arg_size() >=1) { + Argument &Arg = F.getArgumentList().front(); + switch (Arg.getType()->getTypeID()) { case Type::FloatTyID: case Type::DoubleTyID: return true; default: ; } - if (F.arg_size() >=1) { - Argument &Arg = F.getArgumentList().front(); - switch (Arg.getType()->getTypeID()) { - case Type::FloatTyID: - case Type::DoubleTyID: - return true; - default: - ; - } - } - return false; } + return false; +} - // Figure out if the function will need floating point operations - // - bool needsFP(Function &F) { - if (needsFPFromSig(F)) - return true; - for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB) - for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); +// Figure out if the function will need floating point operations +// +static bool needsFP(Function &F) { + if (needsFPFromSig(F)) + return true; + for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB) + for (BasicBlock::const_iterator I = BB->begin(), E = BB->end(); I != E; ++I) { - const Instruction &Inst = *I; - switch (Inst.getOpcode()) { - case Instruction::FAdd: - case Instruction::FSub: - case Instruction::FMul: - case Instruction::FDiv: - case Instruction::FRem: - case Instruction::FPToUI: - case Instruction::FPToSI: - case Instruction::UIToFP: - case Instruction::SIToFP: - case Instruction::FPTrunc: - case Instruction::FPExt: - case Instruction::FCmp: + const Instruction &Inst = *I; + switch (Inst.getOpcode()) { + case Instruction::FAdd: + case Instruction::FSub: + case Instruction::FMul: + case Instruction::FDiv: + case Instruction::FRem: + case Instruction::FPToUI: + case Instruction::FPToSI: + case Instruction::UIToFP: + case Instruction::SIToFP: + case Instruction::FPTrunc: + case Instruction::FPExt: + case Instruction::FCmp: + return true; + default: + ; + } + if (const CallInst *CI = dyn_cast<CallInst>(I)) { + DEBUG(dbgs() << "Working on call" << "\n"); + Function &F_ = *CI->getCalledFunction(); + if (needsFPFromSig(F_)) return true; - default: - ; - } - if (const CallInst *CI = dyn_cast<CallInst>(I)) { - DEBUG(dbgs() << "Working on call" << "\n"); - Function &F_ = *CI->getCalledFunction(); - if (needsFPFromSig(F_)) - return true; - } } - return false; - } + } + return false; } -namespace llvm { bool MipsOs16::runOnModule(Module &M) { @@ -136,12 +151,6 @@ bool MipsOs16::runOnModule(Module &M) { return modified; } -char MipsOs16::ID = 0; - -} - -ModulePass *llvm::createMipsOs16(MipsTargetMachine &TM) { +ModulePass *llvm::createMipsOs16Pass(MipsTargetMachine &TM) { return new MipsOs16; } - - diff --git a/contrib/llvm/lib/Target/Mips/MipsOs16.h b/contrib/llvm/lib/Target/Mips/MipsOs16.h deleted file mode 100644 index 77183ec..0000000 --- a/contrib/llvm/lib/Target/Mips/MipsOs16.h +++ /dev/null @@ -1,47 +0,0 @@ -//===---- MipsOs16.h for Mips Option -Os16 --------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines an optimization phase for the MIPS target. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_LIB_TARGET_MIPS_MIPSOS16_H -#define LLVM_LIB_TARGET_MIPS_MIPSOS16_H - -#include "MCTargetDesc/MipsMCTargetDesc.h" -#include "MipsTargetMachine.h" -#include "llvm/Pass.h" -#include "llvm/Target/TargetMachine.h" - -using namespace llvm; - -namespace llvm { - -class MipsOs16 : public ModulePass { - -public: - static char ID; - - MipsOs16() : ModulePass(ID) { - - } - - const char *getPassName() const override { - return "MIPS Os16 Optimization"; - } - - bool runOnModule(Module &M) override; - -}; - -ModulePass *createMipsOs16(MipsTargetMachine &TM); - -} - -#endif diff --git a/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.cpp b/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.cpp index 20ef3f3..f6647e6 100644 --- a/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.cpp @@ -17,9 +17,11 @@ #include "MipsInstrInfo.h" #include "MipsMachineFunction.h" #include "MipsSubtarget.h" +#include "MipsTargetMachine.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/CodeGen/MachineFrameInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/IR/Constants.h" @@ -42,15 +44,15 @@ using namespace llvm; #define GET_REGINFO_TARGET_DESC #include "MipsGenRegisterInfo.inc" -MipsRegisterInfo::MipsRegisterInfo(const MipsSubtarget &ST) - : MipsGenRegisterInfo(Mips::RA), Subtarget(ST) {} +MipsRegisterInfo::MipsRegisterInfo() : MipsGenRegisterInfo(Mips::RA) {} unsigned MipsRegisterInfo::getPICCallReg() { return Mips::T9; } const TargetRegisterClass * MipsRegisterInfo::getPointerRegClass(const MachineFunction &MF, unsigned Kind) const { - return Subtarget.isABI_N64() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; + MipsABIInfo ABI = MF.getSubtarget<MipsSubtarget>().getABI(); + return ABI.ArePtrs64bit() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; } unsigned @@ -81,6 +83,7 @@ MipsRegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC, /// Mips Callee Saved Registers const MCPhysReg * MipsRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { + const MipsSubtarget &Subtarget = MF->getSubtarget<MipsSubtarget>(); if (Subtarget.isSingleFloat()) return CSR_SingleFloatOnly_SaveList; @@ -99,8 +102,10 @@ MipsRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { return CSR_O32_SaveList; } -const uint32_t* -MipsRegisterInfo::getCallPreservedMask(CallingConv::ID) const { +const uint32_t * +MipsRegisterInfo::getCallPreservedMask(const MachineFunction &MF, + CallingConv::ID) const { + const MipsSubtarget &Subtarget = MF.getSubtarget<MipsSubtarget>(); if (Subtarget.isSingleFloat()) return CSR_SingleFloatOnly_RegMask; @@ -134,6 +139,7 @@ getReservedRegs(const MachineFunction &MF) const { }; BitVector Reserved(getNumRegs()); + const MipsSubtarget &Subtarget = MF.getSubtarget<MipsSubtarget>(); typedef TargetRegisterClass::const_iterator RegIter; for (unsigned I = 0; I < array_lengthof(ReservedGPR32); ++I) @@ -167,12 +173,21 @@ getReservedRegs(const MachineFunction &MF) const { Reserved.set(*Reg); } // Reserve FP if this function should have a dedicated frame pointer register. - if (MF.getSubtarget().getFrameLowering()->hasFP(MF)) { + if (Subtarget.getFrameLowering()->hasFP(MF)) { if (Subtarget.inMips16Mode()) Reserved.set(Mips::S0); else { Reserved.set(Mips::FP); Reserved.set(Mips::FP_64); + + // Reserve the base register if we need to both realign the stack and + // allocate variable-sized objects at runtime. This should test the + // same conditions as MipsFrameLowering::hasBP(). + if (needsStackRealignment(MF) && + MF.getFrameInfo()->hasVarSizedObjects()) { + Reserved.set(Mips::S7); + Reserved.set(Mips::S7_64); + } } } @@ -256,14 +271,77 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, unsigned MipsRegisterInfo:: getFrameRegister(const MachineFunction &MF) const { - const TargetFrameLowering *TFI = MF.getSubtarget().getFrameLowering(); - bool IsN64 = Subtarget.isABI_N64(); + const MipsSubtarget &Subtarget = MF.getSubtarget<MipsSubtarget>(); + const TargetFrameLowering *TFI = Subtarget.getFrameLowering(); + bool IsN64 = + static_cast<const MipsTargetMachine &>(MF.getTarget()).getABI().IsN64(); if (Subtarget.inMips16Mode()) return TFI->hasFP(MF) ? Mips::S0 : Mips::SP; else return TFI->hasFP(MF) ? (IsN64 ? Mips::FP_64 : Mips::FP) : (IsN64 ? Mips::SP_64 : Mips::SP); +} + +bool MipsRegisterInfo::canRealignStack(const MachineFunction &MF) const { + const MipsSubtarget &Subtarget = MF.getSubtarget<MipsSubtarget>(); + unsigned FP = Subtarget.isGP32bit() ? Mips::FP : Mips::FP_64; + unsigned BP = Subtarget.isGP32bit() ? Mips::S7 : Mips::S7_64; + + // Support dynamic stack realignment only for targets with standard encoding. + if (!Subtarget.hasStandardEncoding()) + return false; + + // We can't perform dynamic stack realignment if we can't reserve the + // frame pointer register. + if (!MF.getRegInfo().canReserveReg(FP)) + return false; + + // We can realign the stack if we know the maximum call frame size and we + // don't have variable sized objects. + if (Subtarget.getFrameLowering()->hasReservedCallFrame(MF)) + return true; + // We have to reserve the base pointer register in the presence of variable + // sized objects. + return MF.getRegInfo().canReserveReg(BP); } +bool MipsRegisterInfo::needsStackRealignment(const MachineFunction &MF) const { + const MipsSubtarget &Subtarget = MF.getSubtarget<MipsSubtarget>(); + const MachineFrameInfo *MFI = MF.getFrameInfo(); + + bool CanRealign = canRealignStack(MF); + + // Avoid realigning functions that explicitly do not want to be realigned. + // Normally, we should report an error when a function should be dynamically + // realigned but also has the attribute no-realign-stack. Unfortunately, + // with this attribute, MachineFrameInfo clamps each new object's alignment + // to that of the stack's alignment as specified by the ABI. As a result, + // the information of whether we have objects with larger alignment + // requirement than the stack's alignment is already lost at this point. + if (MF.getFunction()->hasFnAttribute("no-realign-stack")) + return false; + + const Function *F = MF.getFunction(); + if (F->hasFnAttribute(Attribute::StackAlignment)) { +#ifdef DEBUG + if (!CanRealign) + DEBUG(dbgs() << "It's not possible to realign the stack of the function: " + << F->getName() << "\n"); +#endif + return CanRealign; + } + + unsigned StackAlignment = Subtarget.getFrameLowering()->getStackAlignment(); + if (MFI->getMaxAlignment() > StackAlignment) { +#ifdef DEBUG + if (!CanRealign) + DEBUG(dbgs() << "It's not possible to realign the stack of the function: " + << F->getName() << "\n"); +#endif + return CanRealign; + } + + return false; +} diff --git a/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.h b/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.h index 9ec4a38..ee1f6bc 100644 --- a/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.h +++ b/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.h @@ -21,15 +21,9 @@ #include "MipsGenRegisterInfo.inc" namespace llvm { -class MipsSubtarget; -class Type; - class MipsRegisterInfo : public MipsGenRegisterInfo { -protected: - const MipsSubtarget &Subtarget; - public: - MipsRegisterInfo(const MipsSubtarget &Subtarget); + MipsRegisterInfo(); /// getRegisterNumbering - Given the enum value for some register, e.g. /// Mips::RA, return the number that it corresponds to (e.g. 31). @@ -47,9 +41,9 @@ public: unsigned getRegPressureLimit(const TargetRegisterClass *RC, MachineFunction &MF) const override; - const MCPhysReg * - getCalleeSavedRegs(const MachineFunction *MF = nullptr) const override; - const uint32_t *getCallPreservedMask(CallingConv::ID) const override; + const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF) const override; + const uint32_t *getCallPreservedMask(const MachineFunction &MF, + CallingConv::ID) const override; static const uint32_t *getMips16RetHelperMask(); BitVector getReservedRegs(const MachineFunction &MF) const override; @@ -66,6 +60,11 @@ public: void processFunctionBeforeFrameFinalized(MachineFunction &MF, RegScavenger *RS = nullptr) const; + // Stack realignment queries. + bool canRealignStack(const MachineFunction &MF) const; + + bool needsStackRealignment(const MachineFunction &MF) const override; + /// Debug information queries. unsigned getFrameRegister(const MachineFunction &MF) const override; diff --git a/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.td b/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.td index 1eb8d9a..7497a25 100644 --- a/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.td +++ b/contrib/llvm/lib/Target/Mips/MipsRegisterInfo.td @@ -302,6 +302,16 @@ def GPRMM16Zero : RegisterClass<"Mips", [i32], 32, (add // Return Values and Arguments V0, V1, A0, A1, A2, A3)>; +def GPRMM16MoveP : RegisterClass<"Mips", [i32], 32, (add + // Reserved + ZERO, + // Callee save + S1, + // Return Values and Arguments + V0, V1, + // Callee save + S0, S2, S3, S4)>; + def GPR64 : RegisterClass<"Mips", [i64], 64, (add // Reserved ZERO_64, AT_64, @@ -461,6 +471,11 @@ def GPRMM16AsmOperandZero : MipsAsmRegOperand { let PredicateMethod = "isMM16AsmRegZero"; } +def GPRMM16AsmOperandMoveP : MipsAsmRegOperand { + let Name = "GPRMM16AsmRegMoveP"; + let PredicateMethod = "isMM16AsmRegMoveP"; +} + def ACC64DSPAsmOperand : MipsAsmRegOperand { let Name = "ACC64DSPAsmReg"; let PredicateMethod = "isACCAsmReg"; @@ -524,6 +539,10 @@ def GPRMM16OpndZero : RegisterOperand<GPRMM16Zero> { let ParserMatchClass = GPRMM16AsmOperandZero; } +def GPRMM16OpndMoveP : RegisterOperand<GPRMM16MoveP> { + let ParserMatchClass = GPRMM16AsmOperandMoveP; +} + def GPR64Opnd : RegisterOperand<GPR64> { let ParserMatchClass = GPR64AsmOperand; } diff --git a/contrib/llvm/lib/Target/Mips/MipsSEFrameLowering.cpp b/contrib/llvm/lib/Target/Mips/MipsSEFrameLowering.cpp index 97d9edf..ec7bf31 100644 --- a/contrib/llvm/lib/Target/Mips/MipsSEFrameLowering.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsSEFrameLowering.cpp @@ -71,11 +71,17 @@ private: MachineFunction &MF; MachineRegisterInfo &MRI; + const MipsSubtarget &Subtarget; + const MipsSEInstrInfo &TII; + const MipsRegisterInfo &RegInfo; }; } ExpandPseudo::ExpandPseudo(MachineFunction &MF_) - : MF(MF_), MRI(MF.getRegInfo()) {} + : MF(MF_), MRI(MF.getRegInfo()), + Subtarget(static_cast<const MipsSubtarget &>(MF.getSubtarget())), + TII(*static_cast<const MipsSEInstrInfo *>(Subtarget.getInstrInfo())), + RegInfo(*Subtarget.getRegisterInfo()) {} bool ExpandPseudo::expand() { bool Expanded = false; @@ -146,11 +152,6 @@ void ExpandPseudo::expandLoadCCond(MachineBasicBlock &MBB, Iter I) { assert(I->getOperand(0).isReg() && I->getOperand(1).isFI()); - const MipsSEInstrInfo &TII = - *static_cast<const MipsSEInstrInfo *>(MF.getSubtarget().getInstrInfo()); - const MipsRegisterInfo &RegInfo = *static_cast<const MipsRegisterInfo *>( - MF.getSubtarget().getRegisterInfo()); - const TargetRegisterClass *RC = RegInfo.intRegClass(4); unsigned VR = MRI.createVirtualRegister(RC); unsigned Dst = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex(); @@ -166,11 +167,6 @@ void ExpandPseudo::expandStoreCCond(MachineBasicBlock &MBB, Iter I) { assert(I->getOperand(0).isReg() && I->getOperand(1).isFI()); - const MipsSEInstrInfo &TII = - *static_cast<const MipsSEInstrInfo *>(MF.getSubtarget().getInstrInfo()); - const MipsRegisterInfo &RegInfo = *static_cast<const MipsRegisterInfo *>( - MF.getSubtarget().getRegisterInfo()); - const TargetRegisterClass *RC = RegInfo.intRegClass(4); unsigned VR = MRI.createVirtualRegister(RC); unsigned Src = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex(); @@ -189,11 +185,6 @@ void ExpandPseudo::expandLoadACC(MachineBasicBlock &MBB, Iter I, assert(I->getOperand(0).isReg() && I->getOperand(1).isFI()); - const MipsSEInstrInfo &TII = - *static_cast<const MipsSEInstrInfo *>(MF.getSubtarget().getInstrInfo()); - const MipsRegisterInfo &RegInfo = *static_cast<const MipsRegisterInfo *>( - MF.getSubtarget().getRegisterInfo()); - const TargetRegisterClass *RC = RegInfo.intRegClass(RegSize); unsigned VR0 = MRI.createVirtualRegister(RC); unsigned VR1 = MRI.createVirtualRegister(RC); @@ -219,11 +210,6 @@ void ExpandPseudo::expandStoreACC(MachineBasicBlock &MBB, Iter I, assert(I->getOperand(0).isReg() && I->getOperand(1).isFI()); - const MipsSEInstrInfo &TII = - *static_cast<const MipsSEInstrInfo *>(MF.getSubtarget().getInstrInfo()); - const MipsRegisterInfo &RegInfo = *static_cast<const MipsRegisterInfo *>( - MF.getSubtarget().getRegisterInfo()); - const TargetRegisterClass *RC = RegInfo.intRegClass(RegSize); unsigned VR0 = MRI.createVirtualRegister(RC); unsigned VR1 = MRI.createVirtualRegister(RC); @@ -254,11 +240,6 @@ bool ExpandPseudo::expandCopyACC(MachineBasicBlock &MBB, Iter I, // mfhi $vr1, src // copy dst_hi, $vr1 - const MipsSEInstrInfo &TII = - *static_cast<const MipsSEInstrInfo *>(MF.getSubtarget().getInstrInfo()); - const MipsRegisterInfo &RegInfo = *static_cast<const MipsRegisterInfo *>( - MF.getSubtarget().getRegisterInfo()); - unsigned Dst = I->getOperand(0).getReg(), Src = I->getOperand(1).getReg(); unsigned VRegSize = RegInfo.getMinimalPhysRegClass(Dst)->getSize() / 2; const TargetRegisterClass *RC = RegInfo.intRegClass(VRegSize); @@ -298,16 +279,8 @@ bool ExpandPseudo::expandBuildPairF64(MachineBasicBlock &MBB, // register). Unfortunately, we have to make this decision before register // allocation so for now we use a spill/reload sequence for all // double-precision values in regardless of being an odd/even register. - - const TargetMachine &TM = MF.getTarget(); - const MipsSubtarget &Subtarget = TM.getSubtarget<MipsSubtarget>(); if ((Subtarget.isABI_FPXX() && !Subtarget.hasMTHC1()) || (FP64 && !Subtarget.useOddSPReg())) { - const MipsSEInstrInfo &TII = *static_cast<const MipsSEInstrInfo *>( - TM.getSubtargetImpl()->getInstrInfo()); - const MipsRegisterInfo &TRI = *static_cast<const MipsRegisterInfo *>( - TM.getSubtargetImpl()->getRegisterInfo()); - unsigned DstReg = I->getOperand(0).getReg(); unsigned LoReg = I->getOperand(1).getReg(); unsigned HiReg = I->getOperand(2).getReg(); @@ -327,11 +300,11 @@ bool ExpandPseudo::expandBuildPairF64(MachineBasicBlock &MBB, int FI = MF.getInfo<MipsFunctionInfo>()->getMoveF64ViaSpillFI(RC2); if (!Subtarget.isLittle()) std::swap(LoReg, HiReg); - TII.storeRegToStack(MBB, I, LoReg, I->getOperand(1).isKill(), FI, RC, &TRI, - 0); - TII.storeRegToStack(MBB, I, HiReg, I->getOperand(2).isKill(), FI, RC, &TRI, - 4); - TII.loadRegFromStack(MBB, I, DstReg, FI, RC2, &TRI, 0); + TII.storeRegToStack(MBB, I, LoReg, I->getOperand(1).isKill(), FI, RC, + &RegInfo, 0); + TII.storeRegToStack(MBB, I, HiReg, I->getOperand(2).isKill(), FI, RC, + &RegInfo, 4); + TII.loadRegFromStack(MBB, I, DstReg, FI, RC2, &RegInfo, 0); return true; } @@ -359,15 +332,8 @@ bool ExpandPseudo::expandExtractElementF64(MachineBasicBlock &MBB, // allocation so for now we use a spill/reload sequence for all // double-precision values in regardless of being an odd/even register. - const TargetMachine &TM = MF.getTarget(); - const MipsSubtarget &Subtarget = TM.getSubtarget<MipsSubtarget>(); if ((Subtarget.isABI_FPXX() && !Subtarget.hasMTHC1()) || (FP64 && !Subtarget.useOddSPReg())) { - const MipsSEInstrInfo &TII = *static_cast<const MipsSEInstrInfo *>( - TM.getSubtargetImpl()->getInstrInfo()); - const MipsRegisterInfo &TRI = *static_cast<const MipsRegisterInfo *>( - TM.getSubtargetImpl()->getRegisterInfo()); - unsigned DstReg = I->getOperand(0).getReg(); unsigned SrcReg = I->getOperand(1).getReg(); unsigned N = I->getOperand(2).getImm(); @@ -386,9 +352,9 @@ bool ExpandPseudo::expandExtractElementF64(MachineBasicBlock &MBB, // We re-use the same spill slot each time so that the stack frame doesn't // grow too much in functions with a large number of moves. int FI = MF.getInfo<MipsFunctionInfo>()->getMoveF64ViaSpillFI(RC); - TII.storeRegToStack(MBB, I, SrcReg, I->getOperand(1).isKill(), FI, RC, &TRI, - 0); - TII.loadRegFromStack(MBB, I, DstReg, FI, RC2, &TRI, Offset); + TII.storeRegToStack(MBB, I, SrcReg, I->getOperand(1).isKill(), FI, RC, + &RegInfo, 0); + TII.loadRegFromStack(MBB, I, DstReg, FI, RC2, &RegInfo, Offset); return true; } @@ -398,33 +364,29 @@ bool ExpandPseudo::expandExtractElementF64(MachineBasicBlock &MBB, MipsSEFrameLowering::MipsSEFrameLowering(const MipsSubtarget &STI) : MipsFrameLowering(STI, STI.stackAlignment()) {} -unsigned MipsSEFrameLowering::ehDataReg(unsigned I) const { - static const unsigned EhDataReg[] = { - Mips::A0, Mips::A1, Mips::A2, Mips::A3 - }; - static const unsigned EhDataReg64[] = { - Mips::A0_64, Mips::A1_64, Mips::A2_64, Mips::A3_64 - }; - - return STI.isABI_N64() ? EhDataReg64[I] : EhDataReg[I]; -} - -void MipsSEFrameLowering::emitPrologue(MachineFunction &MF) const { - MachineBasicBlock &MBB = MF.front(); +void MipsSEFrameLowering::emitPrologue(MachineFunction &MF, + MachineBasicBlock &MBB) const { + assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported"); MachineFrameInfo *MFI = MF.getFrameInfo(); MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); const MipsSEInstrInfo &TII = - *static_cast<const MipsSEInstrInfo *>(MF.getSubtarget().getInstrInfo()); - const MipsRegisterInfo &RegInfo = *static_cast<const MipsRegisterInfo *>( - MF.getSubtarget().getRegisterInfo()); + *static_cast<const MipsSEInstrInfo *>(STI.getInstrInfo()); + const MipsRegisterInfo &RegInfo = + *static_cast<const MipsRegisterInfo *>(STI.getRegisterInfo()); MachineBasicBlock::iterator MBBI = MBB.begin(); DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); - unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP; - unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP; - unsigned ZERO = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO; - unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu; + MipsABIInfo ABI = STI.getABI(); + unsigned SP = ABI.GetStackPtr(); + unsigned FP = ABI.GetFramePtr(); + unsigned ZERO = ABI.GetNullPtr(); + unsigned ADDu = ABI.GetPtrAdduOp(); + unsigned ADDiu = ABI.GetPtrAddiuOp(); + unsigned AND = ABI.IsN64() ? Mips::AND64 : Mips::AND; + + const TargetRegisterClass *RC = ABI.ArePtrs64bit() ? + &Mips::GPR64RegClass : &Mips::GPR32RegClass; // First, compute final stack size. uint64_t StackSize = MFI->getStackSize(); @@ -507,21 +469,18 @@ void MipsSEFrameLowering::emitPrologue(MachineFunction &MF) const { } if (MipsFI->callsEhReturn()) { - const TargetRegisterClass *RC = STI.isABI_N64() ? - &Mips::GPR64RegClass : &Mips::GPR32RegClass; - // Insert instructions that spill eh data registers. for (int I = 0; I < 4; ++I) { - if (!MBB.isLiveIn(ehDataReg(I))) - MBB.addLiveIn(ehDataReg(I)); - TII.storeRegToStackSlot(MBB, MBBI, ehDataReg(I), false, + if (!MBB.isLiveIn(ABI.GetEhDataReg(I))) + MBB.addLiveIn(ABI.GetEhDataReg(I)); + TII.storeRegToStackSlot(MBB, MBBI, ABI.GetEhDataReg(I), false, MipsFI->getEhDataRegFI(I), RC, &RegInfo); } // Emit .cfi_offset directives for eh data registers. for (int I = 0; I < 4; ++I) { int64_t Offset = MFI->getObjectOffset(MipsFI->getEhDataRegFI(I)); - unsigned Reg = MRI->getDwarfRegNum(ehDataReg(I), true); + unsigned Reg = MRI->getDwarfRegNum(ABI.GetEhDataReg(I), true); unsigned CFIIndex = MMI.addFrameInst( MCCFIInstruction::createOffset(nullptr, Reg, Offset)); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) @@ -540,6 +499,26 @@ void MipsSEFrameLowering::emitPrologue(MachineFunction &MF) const { nullptr, MRI->getDwarfRegNum(FP, true))); BuildMI(MBB, MBBI, dl, TII.get(TargetOpcode::CFI_INSTRUCTION)) .addCFIIndex(CFIIndex); + + if (RegInfo.needsStackRealignment(MF)) { + // addiu $Reg, $zero, -MaxAlignment + // andi $sp, $sp, $Reg + unsigned VR = MF.getRegInfo().createVirtualRegister(RC); + assert(isInt<16>(MFI->getMaxAlignment()) && + "Function's alignment size requirement is not supported."); + int MaxAlign = - (signed) MFI->getMaxAlignment(); + + BuildMI(MBB, MBBI, dl, TII.get(ADDiu), VR).addReg(ZERO) .addImm(MaxAlign); + BuildMI(MBB, MBBI, dl, TII.get(AND), SP).addReg(SP).addReg(VR); + + if (hasBP(MF)) { + // move $s7, $sp + unsigned BP = STI.isABI_N64() ? Mips::S7_64 : Mips::S7; + BuildMI(MBB, MBBI, dl, TII.get(ADDu), BP) + .addReg(SP) + .addReg(ZERO); + } + } } } @@ -550,15 +529,16 @@ void MipsSEFrameLowering::emitEpilogue(MachineFunction &MF, MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); const MipsSEInstrInfo &TII = - *static_cast<const MipsSEInstrInfo *>(MF.getSubtarget().getInstrInfo()); - const MipsRegisterInfo &RegInfo = *static_cast<const MipsRegisterInfo *>( - MF.getSubtarget().getRegisterInfo()); + *static_cast<const MipsSEInstrInfo *>(STI.getInstrInfo()); + const MipsRegisterInfo &RegInfo = + *static_cast<const MipsRegisterInfo *>(STI.getRegisterInfo()); DebugLoc dl = MBBI->getDebugLoc(); - unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP; - unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP; - unsigned ZERO = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO; - unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu; + MipsABIInfo ABI = STI.getABI(); + unsigned SP = ABI.GetStackPtr(); + unsigned FP = ABI.GetFramePtr(); + unsigned ZERO = ABI.GetNullPtr(); + unsigned ADDu = ABI.GetPtrAdduOp(); // if framepointer enabled, restore the stack pointer. if (hasFP(MF)) { @@ -573,8 +553,8 @@ void MipsSEFrameLowering::emitEpilogue(MachineFunction &MF, } if (MipsFI->callsEhReturn()) { - const TargetRegisterClass *RC = STI.isABI_N64() ? - &Mips::GPR64RegClass : &Mips::GPR32RegClass; + const TargetRegisterClass *RC = + ABI.ArePtrs64bit() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; // Find first instruction that restores a callee-saved register. MachineBasicBlock::iterator I = MBBI; @@ -583,8 +563,8 @@ void MipsSEFrameLowering::emitEpilogue(MachineFunction &MF, // Insert instructions that restore eh data registers. for (int J = 0; J < 4; ++J) { - TII.loadRegFromStackSlot(MBB, I, ehDataReg(J), MipsFI->getEhDataRegFI(J), - RC, &RegInfo); + TII.loadRegFromStackSlot(MBB, I, ABI.GetEhDataReg(J), + MipsFI->getEhDataRegFI(J), RC, &RegInfo); } } @@ -605,7 +585,7 @@ spillCalleeSavedRegisters(MachineBasicBlock &MBB, const TargetRegisterInfo *TRI) const { MachineFunction *MF = MBB.getParent(); MachineBasicBlock *EntryBlock = MF->begin(); - const TargetInstrInfo &TII = *MF->getSubtarget().getInstrInfo(); + const TargetInstrInfo &TII = *STI.getInstrInfo(); for (unsigned i = 0, e = CSI.size(); i != e; ++i) { // Add the callee-saved register as live-in. Do not add if the register is @@ -641,36 +621,21 @@ MipsSEFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { !MFI->hasVarSizedObjects(); } -// Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions -void MipsSEFrameLowering:: -eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const { - const MipsSEInstrInfo &TII = - *static_cast<const MipsSEInstrInfo *>(MF.getSubtarget().getInstrInfo()); - - if (!hasReservedCallFrame(MF)) { - int64_t Amount = I->getOperand(0).getImm(); - - if (I->getOpcode() == Mips::ADJCALLSTACKDOWN) - Amount = -Amount; - - unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP; - TII.adjustStackPtr(SP, Amount, MBB, I); - } - - MBB.erase(I); -} - void MipsSEFrameLowering:: processFunctionBeforeCalleeSavedScan(MachineFunction &MF, RegScavenger *RS) const { MachineRegisterInfo &MRI = MF.getRegInfo(); MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); - unsigned FP = STI.isABI_N64() ? Mips::FP_64 : Mips::FP; + MipsABIInfo ABI = STI.getABI(); + unsigned FP = ABI.GetFramePtr(); + unsigned BP = ABI.IsN64() ? Mips::S7_64 : Mips::S7; // Mark $fp as used if function has dedicated frame pointer. if (hasFP(MF)) MRI.setPhysRegUsed(FP); + // Mark $s7 as used if function has dedicated base pointer. + if (hasBP(MF)) + MRI.setPhysRegUsed(BP); // Create spill slots for eh data registers if function calls eh_return. if (MipsFI->callsEhReturn()) @@ -695,8 +660,8 @@ processFunctionBeforeCalleeSavedScan(MachineFunction &MF, if (isInt<16>(MaxSPOffset)) return; - const TargetRegisterClass *RC = STI.isABI_N64() ? - &Mips::GPR64RegClass : &Mips::GPR32RegClass; + const TargetRegisterClass *RC = + ABI.ArePtrs64bit() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; int FI = MF.getFrameInfo()->CreateStackObject(RC->getSize(), RC->getAlignment(), false); RS->addScavengingFrameIndex(FI); diff --git a/contrib/llvm/lib/Target/Mips/MipsSEFrameLowering.h b/contrib/llvm/lib/Target/Mips/MipsSEFrameLowering.h index 0eca1df..2fcd6bb 100644 --- a/contrib/llvm/lib/Target/Mips/MipsSEFrameLowering.h +++ b/contrib/llvm/lib/Target/Mips/MipsSEFrameLowering.h @@ -24,13 +24,9 @@ public: /// emitProlog/emitEpilog - These methods insert prolog and epilog code into /// the function. - void emitPrologue(MachineFunction &MF) const override; + void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override; void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; - void eliminateCallFramePseudoInstr(MachineFunction &MF, - MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const override; - bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const std::vector<CalleeSavedInfo> &CSI, diff --git a/contrib/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp b/contrib/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp index 8c2620c..990a2f8 100644 --- a/contrib/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.cpp @@ -37,7 +37,7 @@ using namespace llvm; #define DEBUG_TYPE "mips-isel" bool MipsSEDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { - Subtarget = &TM.getSubtarget<MipsSubtarget>(); + Subtarget = &static_cast<const MipsSubtarget &>(MF.getSubtarget()); if (Subtarget->inMips16Mode()) return false; return MipsDAGToDAGISel::runOnMachineFunction(MF); @@ -130,17 +130,17 @@ void MipsSEDAGToDAGISel::initGlobalBaseReg(MachineFunction &MF) { MachineBasicBlock &MBB = MF.front(); MachineBasicBlock::iterator I = MBB.begin(); MachineRegisterInfo &RegInfo = MF.getRegInfo(); - const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); + const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc(); unsigned V0, V1, GlobalBaseReg = MipsFI->getGlobalBaseReg(); const TargetRegisterClass *RC; - - RC = (Subtarget->isABI_N64()) ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; + const MipsABIInfo &ABI = static_cast<const MipsTargetMachine &>(TM).getABI(); + RC = (ABI.IsN64()) ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; V0 = RegInfo.createVirtualRegister(RC); V1 = RegInfo.createVirtualRegister(RC); - if (Subtarget->isABI_N64()) { + if (ABI.IsN64()) { MF.getRegInfo().addLiveIn(Mips::T9_64); MBB.addLiveIn(Mips::T9_64); @@ -172,7 +172,7 @@ void MipsSEDAGToDAGISel::initGlobalBaseReg(MachineFunction &MF) { MF.getRegInfo().addLiveIn(Mips::T9); MBB.addLiveIn(Mips::T9); - if (Subtarget->isABI_N32()) { + if (ABI.IsN32()) { // lui $v0, %hi(%neg(%gp_rel(fname))) // addu $v1, $v0, $t9 // addiu $globalbasereg, $v1, %lo(%neg(%gp_rel(fname))) @@ -185,7 +185,7 @@ void MipsSEDAGToDAGISel::initGlobalBaseReg(MachineFunction &MF) { return; } - assert(Subtarget->isABI_O32()); + assert(ABI.IsO32()); // For O32 ABI, the following instruction sequence is emitted to initialize // the global base register: @@ -253,9 +253,10 @@ SDNode *MipsSEDAGToDAGISel::selectAddESubE(unsigned MOp, SDValue InFlag, // that SLTu64 produces an i32. We need to fix this in the long run but for // now, just make the DAG type-correct by asserting the upper bits are zero. Carry = CurDAG->getMachineNode(Mips::SUBREG_TO_REG, DL, VT, - CurDAG->getTargetConstant(0, VT), + CurDAG->getTargetConstant(0, DL, VT), SDValue(Carry, 0), - CurDAG->getTargetConstant(Mips::sub_32, VT)); + CurDAG->getTargetConstant(Mips::sub_32, DL, + VT)); } // Generate a second addition only if we know that RHS is not a @@ -276,7 +277,7 @@ bool MipsSEDAGToDAGISel::selectAddrFrameIndex(SDValue Addr, SDValue &Base, EVT ValTy = Addr.getValueType(); Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); - Offset = CurDAG->getTargetConstant(0, ValTy); + Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), ValTy); return true; } return false; @@ -298,7 +299,8 @@ bool MipsSEDAGToDAGISel::selectAddrFrameIndexOffset(SDValue Addr, SDValue &Base, else Base = Addr.getOperand(0); - Offset = CurDAG->getTargetConstant(CN->getZExtValue(), ValTy); + Offset = CurDAG->getTargetConstant(CN->getZExtValue(), SDLoc(Addr), + ValTy); return true; } } @@ -372,7 +374,7 @@ bool MipsSEDAGToDAGISel::selectAddrRegReg(SDValue Addr, SDValue &Base, bool MipsSEDAGToDAGISel::selectAddrDefault(SDValue Addr, SDValue &Base, SDValue &Offset) const { Base = Addr; - Offset = CurDAG->getTargetConstant(0, Addr.getValueType()); + Offset = CurDAG->getTargetConstant(0, SDLoc(Addr), Addr.getValueType()); return true; } @@ -382,6 +384,17 @@ bool MipsSEDAGToDAGISel::selectIntAddr(SDValue Addr, SDValue &Base, selectAddrDefault(Addr, Base, Offset); } +bool MipsSEDAGToDAGISel::selectAddrRegImm9(SDValue Addr, SDValue &Base, + SDValue &Offset) const { + if (selectAddrFrameIndex(Addr, Base, Offset)) + return true; + + if (selectAddrFrameIndexOffset(Addr, Base, Offset, 9)) + return true; + + return false; +} + bool MipsSEDAGToDAGISel::selectAddrRegImm10(SDValue Addr, SDValue &Base, SDValue &Offset) const { if (selectAddrFrameIndex(Addr, Base, Offset)) @@ -405,12 +418,45 @@ bool MipsSEDAGToDAGISel::selectAddrRegImm12(SDValue Addr, SDValue &Base, return false; } +bool MipsSEDAGToDAGISel::selectAddrRegImm16(SDValue Addr, SDValue &Base, + SDValue &Offset) const { + if (selectAddrFrameIndex(Addr, Base, Offset)) + return true; + + if (selectAddrFrameIndexOffset(Addr, Base, Offset, 16)) + return true; + + return false; +} + bool MipsSEDAGToDAGISel::selectIntAddrMM(SDValue Addr, SDValue &Base, SDValue &Offset) const { return selectAddrRegImm12(Addr, Base, Offset) || selectAddrDefault(Addr, Base, Offset); } +bool MipsSEDAGToDAGISel::selectIntAddrLSL2MM(SDValue Addr, SDValue &Base, + SDValue &Offset) const { + if (selectAddrFrameIndexOffset(Addr, Base, Offset, 7)) { + if (isa<FrameIndexSDNode>(Base)) + return false; + + if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Offset)) { + unsigned CnstOff = CN->getZExtValue(); + return (CnstOff == (CnstOff & 0x3c)); + } + + return false; + } + + // For all other cases where "lw" would be selected, don't select "lw16" + // because it would result in additional instructions to prepare operands. + if (selectAddrRegImm(Addr, Base, Offset)) + return false; + + return selectAddrDefault(Addr, Base, Offset); +} + bool MipsSEDAGToDAGISel::selectIntAddrMSA(SDValue Addr, SDValue &Base, SDValue &Offset) const { if (selectAddrRegImm10(Addr, Base, Offset)) @@ -427,7 +473,8 @@ bool MipsSEDAGToDAGISel::selectIntAddrMSA(SDValue Addr, SDValue &Base, // Returns true and sets Imm if: // * MSA is enabled // * N is a ISD::BUILD_VECTOR representing a constant splat -bool MipsSEDAGToDAGISel::selectVSplat(SDNode *N, APInt &Imm) const { +bool MipsSEDAGToDAGISel::selectVSplat(SDNode *N, APInt &Imm, + unsigned MinSizeInBits) const { if (!Subtarget->hasMSA()) return false; @@ -440,9 +487,8 @@ bool MipsSEDAGToDAGISel::selectVSplat(SDNode *N, APInt &Imm) const { unsigned SplatBitSize; bool HasAnyUndefs; - if (!Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, - HasAnyUndefs, 8, - !Subtarget->isLittle())) + if (!Node->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs, + MinSizeInBits, !Subtarget->isLittle())) return false; Imm = SplatValue; @@ -475,11 +521,12 @@ selectVSplatCommon(SDValue N, SDValue &Imm, bool Signed, if (N->getOpcode() == ISD::BITCAST) N = N->getOperand(0); - if (selectVSplat (N.getNode(), ImmValue) && + if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) && ImmValue.getBitWidth() == EltTy.getSizeInBits()) { + if (( Signed && ImmValue.isSignedIntN(ImmBitSize)) || (!Signed && ImmValue.isIntN(ImmBitSize))) { - Imm = CurDAG->getTargetConstant(ImmValue, EltTy); + Imm = CurDAG->getTargetConstant(ImmValue, SDLoc(N), EltTy); return true; } } @@ -550,12 +597,12 @@ bool MipsSEDAGToDAGISel::selectVSplatUimmPow2(SDValue N, SDValue &Imm) const { if (N->getOpcode() == ISD::BITCAST) N = N->getOperand(0); - if (selectVSplat (N.getNode(), ImmValue) && + if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) && ImmValue.getBitWidth() == EltTy.getSizeInBits()) { int32_t Log2 = ImmValue.exactLogBase2(); if (Log2 != -1) { - Imm = CurDAG->getTargetConstant(Log2, EltTy); + Imm = CurDAG->getTargetConstant(Log2, SDLoc(N), EltTy); return true; } } @@ -581,14 +628,15 @@ bool MipsSEDAGToDAGISel::selectVSplatMaskL(SDValue N, SDValue &Imm) const { if (N->getOpcode() == ISD::BITCAST) N = N->getOperand(0); - if (selectVSplat(N.getNode(), ImmValue) && + if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) && ImmValue.getBitWidth() == EltTy.getSizeInBits()) { // Extract the run of set bits starting with bit zero from the bitwise // inverse of ImmValue, and test that the inverse of this is the same // as the original value. if (ImmValue == ~(~ImmValue & ~(~ImmValue + 1))) { - Imm = CurDAG->getTargetConstant(ImmValue.countPopulation(), EltTy); + Imm = CurDAG->getTargetConstant(ImmValue.countPopulation(), SDLoc(N), + EltTy); return true; } } @@ -614,12 +662,13 @@ bool MipsSEDAGToDAGISel::selectVSplatMaskR(SDValue N, SDValue &Imm) const { if (N->getOpcode() == ISD::BITCAST) N = N->getOperand(0); - if (selectVSplat(N.getNode(), ImmValue) && + if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) && ImmValue.getBitWidth() == EltTy.getSizeInBits()) { // Extract the run of set bits starting with bit zero, and test that the // result is the same as the original value if (ImmValue == (ImmValue & ~(ImmValue + 1))) { - Imm = CurDAG->getTargetConstant(ImmValue.countPopulation(), EltTy); + Imm = CurDAG->getTargetConstant(ImmValue.countPopulation(), SDLoc(N), + EltTy); return true; } } @@ -635,12 +684,12 @@ bool MipsSEDAGToDAGISel::selectVSplatUimmInvPow2(SDValue N, if (N->getOpcode() == ISD::BITCAST) N = N->getOperand(0); - if (selectVSplat(N.getNode(), ImmValue) && + if (selectVSplat(N.getNode(), ImmValue, EltTy.getSizeInBits()) && ImmValue.getBitWidth() == EltTy.getSizeInBits()) { int32_t Log2 = (~ImmValue).exactLogBase2(); if (Log2 != -1) { - Imm = CurDAG->getTargetConstant(Log2, EltTy); + Imm = CurDAG->getTargetConstant(Log2, SDLoc(N), EltTy); return true; } } @@ -718,7 +767,7 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) { SDLoc DL(CN); SDNode *RegOpnd; SDValue ImmOpnd = CurDAG->getTargetConstant(SignExtend64<16>(Inst->ImmOpnd), - MVT::i64); + DL, MVT::i64); // The first instruction can be a LUi which is different from other // instructions (ADDiu, ORI and SLL) in that it does not have a register @@ -733,7 +782,7 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) { // The remaining instructions in the sequence are handled here. for (++Inst; Inst != Seq.end(); ++Inst) { - ImmOpnd = CurDAG->getTargetConstant(SignExtend64<16>(Inst->ImmOpnd), + ImmOpnd = CurDAG->getTargetConstant(SignExtend64<16>(Inst->ImmOpnd), DL, MVT::i64); RegOpnd = CurDAG->getMachineNode(Inst->Opc, DL, MVT::i64, SDValue(RegOpnd, 0), ImmOpnd); @@ -804,7 +853,7 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) { } SDNode *Rdhwr = - CurDAG->getMachineNode(RdhwrOpc, SDLoc(Node), + CurDAG->getMachineNode(RdhwrOpc, DL, Node->getValueType(0), CurDAG->getRegister(Mips::HWR29, MVT::i32)); SDValue Chain = CurDAG->getCopyToReg(CurDAG->getEntryNode(), DL, DestReg, @@ -867,10 +916,10 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) { if (!SplatValue.isSignedIntN(10)) return std::make_pair(false, nullptr); - SDValue Imm = CurDAG->getTargetConstant(SplatValue, + SDValue Imm = CurDAG->getTargetConstant(SplatValue, DL, ViaVecTy.getVectorElementType()); - SDNode *Res = CurDAG->getMachineNode(LdiOp, SDLoc(Node), ViaVecTy, Imm); + SDNode *Res = CurDAG->getMachineNode(LdiOp, DL, ViaVecTy, Imm); if (ResVecTy != ViaVecTy) { // If LdiOp is writing to a different register class to ResVecTy, then @@ -880,9 +929,9 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) { const TargetLowering *TLI = getTargetLowering(); MVT ResVecTySimple = ResVecTy.getSimpleVT(); const TargetRegisterClass *RC = TLI->getRegClassFor(ResVecTySimple); - Res = CurDAG->getMachineNode(Mips::COPY_TO_REGCLASS, SDLoc(Node), + Res = CurDAG->getMachineNode(Mips::COPY_TO_REGCLASS, DL, ResVecTy, SDValue(Res, 0), - CurDAG->getTargetConstant(RC->getID(), + CurDAG->getTargetConstant(RC->getID(), DL, MVT::i32)); } @@ -894,6 +943,73 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) { return std::make_pair(false, nullptr); } +bool MipsSEDAGToDAGISel:: +SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, + std::vector<SDValue> &OutOps) { + SDValue Base, Offset; + + switch(ConstraintID) { + default: + llvm_unreachable("Unexpected asm memory constraint"); + // All memory constraints can at least accept raw pointers. + case InlineAsm::Constraint_i: + OutOps.push_back(Op); + OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32)); + return false; + case InlineAsm::Constraint_m: + if (selectAddrRegImm16(Op, Base, Offset)) { + OutOps.push_back(Base); + OutOps.push_back(Offset); + return false; + } + OutOps.push_back(Op); + OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32)); + return false; + case InlineAsm::Constraint_R: + // The 'R' constraint is supposed to be much more complicated than this. + // However, it's becoming less useful due to architectural changes and + // ought to be replaced by other constraints such as 'ZC'. + // For now, support 9-bit signed offsets which is supportable by all + // subtargets for all instructions. + if (selectAddrRegImm9(Op, Base, Offset)) { + OutOps.push_back(Base); + OutOps.push_back(Offset); + return false; + } + OutOps.push_back(Op); + OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32)); + return false; + case InlineAsm::Constraint_ZC: + // ZC matches whatever the pref, ll, and sc instructions can handle for the + // given subtarget. + if (Subtarget->inMicroMipsMode()) { + // On microMIPS, they can handle 12-bit offsets. + if (selectAddrRegImm12(Op, Base, Offset)) { + OutOps.push_back(Base); + OutOps.push_back(Offset); + return false; + } + } else if (Subtarget->hasMips32r6()) { + // On MIPS32r6/MIPS64r6, they can only handle 9-bit offsets. + if (selectAddrRegImm9(Op, Base, Offset)) { + OutOps.push_back(Base); + OutOps.push_back(Offset); + return false; + } + } else if (selectAddrRegImm16(Op, Base, Offset)) { + // Prior to MIPS32r6/MIPS64r6, they can handle 16-bit offsets. + OutOps.push_back(Base); + OutOps.push_back(Offset); + return false; + } + // In all cases, 0-bit offsets are acceptable. + OutOps.push_back(Op); + OutOps.push_back(CurDAG->getTargetConstant(0, SDLoc(Op), MVT::i32)); + return false; + } + return true; +} + FunctionPass *llvm::createMipsSEISelDag(MipsTargetMachine &TM) { return new MipsSEDAGToDAGISel(TM); } diff --git a/contrib/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.h b/contrib/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.h index 2e11fa7..a894034 100644 --- a/contrib/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.h +++ b/contrib/llvm/lib/Target/Mips/MipsSEISelDAGToDAG.h @@ -56,20 +56,30 @@ private: bool selectIntAddr(SDValue Addr, SDValue &Base, SDValue &Offset) const override; + bool selectAddrRegImm9(SDValue Addr, SDValue &Base, + SDValue &Offset) const; + bool selectAddrRegImm10(SDValue Addr, SDValue &Base, SDValue &Offset) const; bool selectAddrRegImm12(SDValue Addr, SDValue &Base, SDValue &Offset) const; + bool selectAddrRegImm16(SDValue Addr, SDValue &Base, + SDValue &Offset) const; + bool selectIntAddrMM(SDValue Addr, SDValue &Base, SDValue &Offset) const override; + bool selectIntAddrLSL2MM(SDValue Addr, SDValue &Base, + SDValue &Offset) const override; + bool selectIntAddrMSA(SDValue Addr, SDValue &Base, SDValue &Offset) const override; /// \brief Select constant vector splats. - bool selectVSplat(SDNode *N, APInt &Imm) const override; + bool selectVSplat(SDNode *N, APInt &Imm, + unsigned MinSizeInBits) const override; /// \brief Select constant vector splats whose value fits in a given integer. bool selectVSplatCommon(SDValue N, SDValue &Imm, bool Signed, unsigned ImmBitSize) const; @@ -108,6 +118,10 @@ private: // Insert instructions to initialize the global base register in the // first MBB of the function. void initGlobalBaseReg(MachineFunction &MF); + + bool SelectInlineAsmMemoryOperand(const SDValue &Op, + unsigned ConstraintID, + std::vector<SDValue> &OutOps) override; }; FunctionPass *createMipsSEISelDag(MipsTargetMachine &TM); diff --git a/contrib/llvm/lib/Target/Mips/MipsSEISelLowering.cpp b/contrib/llvm/lib/Target/Mips/MipsSEISelLowering.cpp index 2c033ce..ae2837a 100644 --- a/contrib/llvm/lib/Target/Mips/MipsSEISelLowering.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsSEISelLowering.cpp @@ -99,7 +99,7 @@ MipsSETargetLowering::MipsSETargetLowering(const MipsTargetMachine &TM, setTargetDAGCombine(ISD::XOR); } - if (!Subtarget.abiUsesSoftFloat()) { + if (!Subtarget.useSoftFloat()) { addRegisterClass(MVT::f32, &Mips::FGR32RegClass); // When dealing with single precision only, use libcalls @@ -224,7 +224,7 @@ MipsSETargetLowering::MipsSETargetLowering(const MipsTargetMachine &TM, setOperationAction(ISD::SELECT_CC, MVT::i64, Expand); } - computeRegisterProperties(); + computeRegisterProperties(Subtarget.getRegisterInfo()); } const MipsTargetLowering * @@ -800,7 +800,7 @@ static SDValue genConstMult(SDValue X, uint64_t C, SDLoc DL, EVT VT, // Return 0. if (C == 0) - return DAG.getConstant(0, VT); + return DAG.getConstant(0, DL, VT); // Return x. if (C == 1) @@ -809,7 +809,7 @@ static SDValue genConstMult(SDValue X, uint64_t C, SDLoc DL, EVT VT, // If c is power of 2, return (shl x, log2(c)). if (isPowerOf2_64(C)) return DAG.getNode(ISD::SHL, DL, VT, X, - DAG.getConstant(Log2_64(C), ShiftTy)); + DAG.getConstant(Log2_64(C), DL, ShiftTy)); unsigned Log2Ceil = Log2_64_Ceil(C); uint64_t Floor = 1LL << Log2_64(C); @@ -864,8 +864,9 @@ static SDValue performDSPShiftCombine(unsigned Opc, SDNode *N, EVT Ty, (SplatValue.getZExtValue() >= EltSize)) return SDValue(); - return DAG.getNode(Opc, SDLoc(N), Ty, N->getOperand(0), - DAG.getConstant(SplatValue.getZExtValue(), MVT::i32)); + SDLoc DL(N); + return DAG.getNode(Opc, DL, Ty, N->getOperand(0), + DAG.getConstant(SplatValue.getZExtValue(), DL, MVT::i32)); } static SDValue performSHLCombine(SDNode *N, SelectionDAG &DAG, @@ -1145,16 +1146,22 @@ MipsSETargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, case Mips::INSERT_FD_PSEUDO: return emitINSERT_FD(MI, BB); case Mips::INSERT_B_VIDX_PSEUDO: + case Mips::INSERT_B_VIDX64_PSEUDO: return emitINSERT_DF_VIDX(MI, BB, 1, false); case Mips::INSERT_H_VIDX_PSEUDO: + case Mips::INSERT_H_VIDX64_PSEUDO: return emitINSERT_DF_VIDX(MI, BB, 2, false); case Mips::INSERT_W_VIDX_PSEUDO: + case Mips::INSERT_W_VIDX64_PSEUDO: return emitINSERT_DF_VIDX(MI, BB, 4, false); case Mips::INSERT_D_VIDX_PSEUDO: + case Mips::INSERT_D_VIDX64_PSEUDO: return emitINSERT_DF_VIDX(MI, BB, 8, false); case Mips::INSERT_FW_VIDX_PSEUDO: + case Mips::INSERT_FW_VIDX64_PSEUDO: return emitINSERT_DF_VIDX(MI, BB, 4, true); case Mips::INSERT_FD_VIDX_PSEUDO: + case Mips::INSERT_FD_VIDX64_PSEUDO: return emitINSERT_DF_VIDX(MI, BB, 8, true); case Mips::FILL_FW_PSEUDO: return emitFILL_FW(MI, BB); @@ -1212,7 +1219,7 @@ SDValue MipsSETargetLowering::lowerLOAD(SDValue Op, SelectionDAG &DAG) const { Nd.getAlignment()); // i32 load from higher address. - Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, Ptr, DAG.getConstant(4, PtrVT)); + Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, Ptr, DAG.getConstant(4, DL, PtrVT)); SDValue Hi = DAG.getLoad(MVT::i32, DL, Lo.getValue(1), Ptr, MachinePointerInfo(), Nd.isVolatile(), Nd.isNonTemporal(), Nd.isInvariant(), @@ -1237,9 +1244,9 @@ SDValue MipsSETargetLowering::lowerSTORE(SDValue Op, SelectionDAG &DAG) const { SDValue Val = Nd.getValue(), Ptr = Nd.getBasePtr(), Chain = Nd.getChain(); EVT PtrVT = Ptr.getValueType(); SDValue Lo = DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, - Val, DAG.getConstant(0, MVT::i32)); + Val, DAG.getConstant(0, DL, MVT::i32)); SDValue Hi = DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, - Val, DAG.getConstant(1, MVT::i32)); + Val, DAG.getConstant(1, DL, MVT::i32)); if (!Subtarget.isLittle()) std::swap(Lo, Hi); @@ -1250,7 +1257,7 @@ SDValue MipsSETargetLowering::lowerSTORE(SDValue Op, SelectionDAG &DAG) const { Nd.getAAInfo()); // i32 store to higher address. - Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, Ptr, DAG.getConstant(4, PtrVT)); + Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, Ptr, DAG.getConstant(4, DL, PtrVT)); return DAG.getStore(Chain, DL, Hi, Ptr, MachinePointerInfo(), Nd.isVolatile(), Nd.isNonTemporal(), std::min(Nd.getAlignment(), 4U), Nd.getAAInfo()); @@ -1283,9 +1290,9 @@ SDValue MipsSETargetLowering::lowerMulDiv(SDValue Op, unsigned NewOpc, static SDValue initAccumulator(SDValue In, SDLoc DL, SelectionDAG &DAG) { SDValue InLo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, In, - DAG.getConstant(0, MVT::i32)); + DAG.getConstant(0, DL, MVT::i32)); SDValue InHi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, In, - DAG.getConstant(1, MVT::i32)); + DAG.getConstant(1, DL, MVT::i32)); return DAG.getNode(MipsISD::MTLOHI, DL, MVT::Untyped, InLo, InHi); } @@ -1381,7 +1388,7 @@ static SDValue lowerMSASplatZExt(SDValue Op, unsigned OpNr, SelectionDAG &DAG) { SDValue LaneB = Op->getOperand(2); if (ResVecTy == MVT::v2i64) { - LaneA = DAG.getConstant(0, MVT::i32); + LaneA = DAG.getConstant(0, DL, MVT::i32); ViaVecTy = MVT::v4i32; } else LaneA = LaneB; @@ -1399,7 +1406,8 @@ static SDValue lowerMSASplatZExt(SDValue Op, unsigned OpNr, SelectionDAG &DAG) { } static SDValue lowerMSASplatImm(SDValue Op, unsigned ImmOp, SelectionDAG &DAG) { - return DAG.getConstant(Op->getConstantOperandVal(ImmOp), Op->getValueType(0)); + return DAG.getConstant(Op->getConstantOperandVal(ImmOp), SDLoc(Op), + Op->getValueType(0)); } static SDValue getBuildVectorSplat(EVT VecTy, SDValue SplatValue, @@ -1415,7 +1423,7 @@ static SDValue getBuildVectorSplat(EVT VecTy, SDValue SplatValue, SplatValueA = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, SplatValue); SplatValueB = DAG.getNode(ISD::SRL, DL, MVT::i64, SplatValue, - DAG.getConstant(32, MVT::i32)); + DAG.getConstant(32, DL, MVT::i32)); SplatValueB = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, SplatValueB); } @@ -1451,8 +1459,9 @@ static SDValue lowerMSABinaryBitImmIntr(SDValue Op, SelectionDAG &DAG, if (ConstantSDNode *CImm = dyn_cast<ConstantSDNode>(Imm)) { APInt BitImm = APInt(64, 1) << CImm->getAPIntValue(); - SDValue BitImmHiOp = DAG.getConstant(BitImm.lshr(32).trunc(32), MVT::i32); - SDValue BitImmLoOp = DAG.getConstant(BitImm.trunc(32), MVT::i32); + SDValue BitImmHiOp = DAG.getConstant(BitImm.lshr(32).trunc(32), DL, + MVT::i32); + SDValue BitImmLoOp = DAG.getConstant(BitImm.trunc(32), DL, MVT::i32); if (BigEndian) std::swap(BitImmLoOp, BitImmHiOp); @@ -1474,8 +1483,8 @@ static SDValue lowerMSABinaryBitImmIntr(SDValue Op, SelectionDAG &DAG, Exp2Imm = getBuildVectorSplat(VecTy, Imm, BigEndian, DAG); - Exp2Imm = - DAG.getNode(ISD::SHL, DL, VecTy, DAG.getConstant(1, VecTy), Exp2Imm); + Exp2Imm = DAG.getNode(ISD::SHL, DL, VecTy, DAG.getConstant(1, DL, VecTy), + Exp2Imm); } return DAG.getNode(Opc, DL, VecTy, Op->getOperand(1), Exp2Imm); @@ -1484,7 +1493,7 @@ static SDValue lowerMSABinaryBitImmIntr(SDValue Op, SelectionDAG &DAG, static SDValue lowerMSABitClear(SDValue Op, SelectionDAG &DAG) { EVT ResTy = Op->getValueType(0); SDLoc DL(Op); - SDValue One = DAG.getConstant(1, ResTy); + SDValue One = DAG.getConstant(1, DL, ResTy); SDValue Bit = DAG.getNode(ISD::SHL, DL, ResTy, One, Op->getOperand(2)); return DAG.getNode(ISD::AND, DL, ResTy, Op->getOperand(1), @@ -1496,7 +1505,7 @@ static SDValue lowerMSABitClearImm(SDValue Op, SelectionDAG &DAG) { EVT ResTy = Op->getValueType(0); APInt BitImm = APInt(ResTy.getVectorElementType().getSizeInBits(), 1) << cast<ConstantSDNode>(Op->getOperand(2))->getAPIntValue(); - SDValue BitMask = DAG.getConstant(~BitImm, ResTy); + SDValue BitMask = DAG.getConstant(~BitImm, DL, ResTy); return DAG.getNode(ISD::AND, DL, ResTy, Op->getOperand(1), BitMask); } @@ -1578,8 +1587,8 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op, APInt Mask = APInt::getHighBitsSet(EltTy.getSizeInBits(), Op->getConstantOperandVal(3)); return DAG.getNode(ISD::VSELECT, DL, VecTy, - DAG.getConstant(Mask, VecTy, true), Op->getOperand(2), - Op->getOperand(1)); + DAG.getConstant(Mask, DL, VecTy, true), + Op->getOperand(2), Op->getOperand(1)); } case Intrinsic::mips_binsri_b: case Intrinsic::mips_binsri_h: @@ -1591,8 +1600,8 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op, APInt Mask = APInt::getLowBitsSet(EltTy.getSizeInBits(), Op->getConstantOperandVal(3)); return DAG.getNode(ISD::VSELECT, DL, VecTy, - DAG.getConstant(Mask, VecTy, true), Op->getOperand(2), - Op->getOperand(1)); + DAG.getConstant(Mask, DL, VecTy, true), + Op->getOperand(2), Op->getOperand(1)); } case Intrinsic::mips_bmnz_v: return DAG.getNode(ISD::VSELECT, DL, Op->getValueType(0), Op->getOperand(3), @@ -1613,7 +1622,7 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op, case Intrinsic::mips_bneg_w: case Intrinsic::mips_bneg_d: { EVT VecTy = Op->getValueType(0); - SDValue One = DAG.getConstant(1, VecTy); + SDValue One = DAG.getConstant(1, DL, VecTy); return DAG.getNode(ISD::XOR, DL, VecTy, Op->getOperand(1), DAG.getNode(ISD::SHL, DL, VecTy, One, @@ -1649,7 +1658,7 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op, case Intrinsic::mips_bset_w: case Intrinsic::mips_bset_d: { EVT VecTy = Op->getValueType(0); - SDValue One = DAG.getConstant(1, VecTy); + SDValue One = DAG.getConstant(1, DL, VecTy); return DAG.getNode(ISD::OR, DL, VecTy, Op->getOperand(1), DAG.getNode(ISD::SHL, DL, VecTy, One, @@ -1836,11 +1845,9 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op, case Intrinsic::mips_fill_h: case Intrinsic::mips_fill_w: case Intrinsic::mips_fill_d: { - SmallVector<SDValue, 16> Ops; EVT ResTy = Op->getValueType(0); - - for (unsigned i = 0; i < ResTy.getVectorNumElements(); ++i) - Ops.push_back(Op->getOperand(1)); + SmallVector<SDValue, 16> Ops(ResTy.getVectorNumElements(), + Op->getOperand(1)); // If ResTy is v2i64 then the type legalizer will break this node down into // an equivalent v4i32. @@ -1925,7 +1932,7 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op, case Intrinsic::mips_insve_d: return DAG.getNode(MipsISD::INSVE, DL, Op->getValueType(0), Op->getOperand(1), Op->getOperand(2), Op->getOperand(3), - DAG.getConstant(0, MVT::i32)); + DAG.getConstant(0, DL, MVT::i32)); case Intrinsic::mips_ldi_b: case Intrinsic::mips_ldi_h: case Intrinsic::mips_ldi_w: @@ -2291,9 +2298,9 @@ lowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const { static bool isConstantOrUndef(const SDValue Op) { if (Op->getOpcode() == ISD::UNDEF) return true; - if (dyn_cast<ConstantSDNode>(Op)) + if (isa<ConstantSDNode>(Op)) return true; - if (dyn_cast<ConstantFPSDNode>(Op)) + if (isa<ConstantFPSDNode>(Op)) return true; return false; } @@ -2365,7 +2372,7 @@ SDValue MipsSETargetLowering::lowerBUILD_VECTOR(SDValue Op, } // SelectionDAG::getConstant will promote SplatValue appropriately. - SDValue Result = DAG.getConstant(SplatValue, ViaVecTy); + SDValue Result = DAG.getConstant(SplatValue, DL, ViaVecTy); // Bitcast to the type we originally wanted if (ViaVecTy != ResTy) @@ -2387,7 +2394,7 @@ SDValue MipsSETargetLowering::lowerBUILD_VECTOR(SDValue Op, for (unsigned i = 0; i < NumElts; ++i) { Vector = DAG.getNode(ISD::INSERT_VECTOR_ELT, DL, ResTy, Vector, Node->getOperand(i), - DAG.getConstant(i, MVT::i32)); + DAG.getConstant(i, DL, MVT::i32)); } return Vector; } @@ -2403,7 +2410,7 @@ SDValue MipsSETargetLowering::lowerBUILD_VECTOR(SDValue Op, // It is therefore possible to lower into SHF when the mask takes the form: // <a, b, c, d, a+4, b+4, c+4, d+4, a+8, b+8, c+8, d+8, ...> // When undef's appear they are treated as if they were whatever value is -// necessary in order to fit the above form. +// necessary in order to fit the above forms. // // For example: // %2 = shufflevector <8 x i16> %0, <8 x i16> undef, @@ -2457,181 +2464,331 @@ static SDValue lowerVECTOR_SHUFFLE_SHF(SDValue Op, EVT ResTy, Imm |= Idx & 0x3; } - return DAG.getNode(MipsISD::SHF, SDLoc(Op), ResTy, - DAG.getConstant(Imm, MVT::i32), Op->getOperand(0)); + SDLoc DL(Op); + return DAG.getNode(MipsISD::SHF, DL, ResTy, + DAG.getConstant(Imm, DL, MVT::i32), Op->getOperand(0)); +} + +/// Determine whether a range fits a regular pattern of values. +/// This function accounts for the possibility of jumping over the End iterator. +template <typename ValType> +static bool +fitsRegularPattern(typename SmallVectorImpl<ValType>::const_iterator Begin, + unsigned CheckStride, + typename SmallVectorImpl<ValType>::const_iterator End, + ValType ExpectedIndex, unsigned ExpectedIndexStride) { + auto &I = Begin; + + while (I != End) { + if (*I != -1 && *I != ExpectedIndex) + return false; + ExpectedIndex += ExpectedIndexStride; + + // Incrementing past End is undefined behaviour so we must increment one + // step at a time and check for End at each step. + for (unsigned n = 0; n < CheckStride && I != End; ++n, ++I) + ; // Empty loop body. + } + return true; +} + +// Determine whether VECTOR_SHUFFLE is a SPLATI. +// +// It is a SPLATI when the mask is: +// <x, x, x, ...> +// where x is any valid index. +// +// When undef's appear in the mask they are treated as if they were whatever +// value is necessary in order to fit the above form. +static bool isVECTOR_SHUFFLE_SPLATI(SDValue Op, EVT ResTy, + SmallVector<int, 16> Indices, + SelectionDAG &DAG) { + assert((Indices.size() % 2) == 0); + + int SplatIndex = -1; + for (const auto &V : Indices) { + if (V != -1) { + SplatIndex = V; + break; + } + } + + return fitsRegularPattern<int>(Indices.begin(), 1, Indices.end(), SplatIndex, + 0); } // Lower VECTOR_SHUFFLE into ILVEV (if possible). // // ILVEV interleaves the even elements from each vector. // -// It is possible to lower into ILVEV when the mask takes the form: -// <0, n, 2, n+2, 4, n+4, ...> +// It is possible to lower into ILVEV when the mask consists of two of the +// following forms interleaved: +// <0, 2, 4, ...> +// <n, n+2, n+4, ...> // where n is the number of elements in the vector. +// For example: +// <0, 0, 2, 2, 4, 4, ...> +// <0, n, 2, n+2, 4, n+4, ...> // // When undef's appear in the mask they are treated as if they were whatever -// value is necessary in order to fit the above form. +// value is necessary in order to fit the above forms. static SDValue lowerVECTOR_SHUFFLE_ILVEV(SDValue Op, EVT ResTy, SmallVector<int, 16> Indices, SelectionDAG &DAG) { - assert ((Indices.size() % 2) == 0); - int WsIdx = 0; - int WtIdx = ResTy.getVectorNumElements(); + assert((Indices.size() % 2) == 0); + + SDValue Wt; + SDValue Ws; + const auto &Begin = Indices.begin(); + const auto &End = Indices.end(); + + // Check even elements are taken from the even elements of one half or the + // other and pick an operand accordingly. + if (fitsRegularPattern<int>(Begin, 2, End, 0, 2)) + Wt = Op->getOperand(0); + else if (fitsRegularPattern<int>(Begin, 2, End, Indices.size(), 2)) + Wt = Op->getOperand(1); + else + return SDValue(); - for (unsigned i = 0; i < Indices.size(); i += 2) { - if (Indices[i] != -1 && Indices[i] != WsIdx) - return SDValue(); - if (Indices[i+1] != -1 && Indices[i+1] != WtIdx) - return SDValue(); - WsIdx += 2; - WtIdx += 2; - } + // Check odd elements are taken from the even elements of one half or the + // other and pick an operand accordingly. + if (fitsRegularPattern<int>(Begin + 1, 2, End, 0, 2)) + Ws = Op->getOperand(0); + else if (fitsRegularPattern<int>(Begin + 1, 2, End, Indices.size(), 2)) + Ws = Op->getOperand(1); + else + return SDValue(); - return DAG.getNode(MipsISD::ILVEV, SDLoc(Op), ResTy, Op->getOperand(0), - Op->getOperand(1)); + return DAG.getNode(MipsISD::ILVEV, SDLoc(Op), ResTy, Ws, Wt); } // Lower VECTOR_SHUFFLE into ILVOD (if possible). // // ILVOD interleaves the odd elements from each vector. // -// It is possible to lower into ILVOD when the mask takes the form: -// <1, n+1, 3, n+3, 5, n+5, ...> +// It is possible to lower into ILVOD when the mask consists of two of the +// following forms interleaved: +// <1, 3, 5, ...> +// <n+1, n+3, n+5, ...> // where n is the number of elements in the vector. +// For example: +// <1, 1, 3, 3, 5, 5, ...> +// <1, n+1, 3, n+3, 5, n+5, ...> // // When undef's appear in the mask they are treated as if they were whatever -// value is necessary in order to fit the above form. +// value is necessary in order to fit the above forms. static SDValue lowerVECTOR_SHUFFLE_ILVOD(SDValue Op, EVT ResTy, SmallVector<int, 16> Indices, SelectionDAG &DAG) { - assert ((Indices.size() % 2) == 0); - int WsIdx = 1; - int WtIdx = ResTy.getVectorNumElements() + 1; + assert((Indices.size() % 2) == 0); + + SDValue Wt; + SDValue Ws; + const auto &Begin = Indices.begin(); + const auto &End = Indices.end(); + + // Check even elements are taken from the odd elements of one half or the + // other and pick an operand accordingly. + if (fitsRegularPattern<int>(Begin, 2, End, 1, 2)) + Wt = Op->getOperand(0); + else if (fitsRegularPattern<int>(Begin, 2, End, Indices.size() + 1, 2)) + Wt = Op->getOperand(1); + else + return SDValue(); - for (unsigned i = 0; i < Indices.size(); i += 2) { - if (Indices[i] != -1 && Indices[i] != WsIdx) - return SDValue(); - if (Indices[i+1] != -1 && Indices[i+1] != WtIdx) - return SDValue(); - WsIdx += 2; - WtIdx += 2; - } + // Check odd elements are taken from the odd elements of one half or the + // other and pick an operand accordingly. + if (fitsRegularPattern<int>(Begin + 1, 2, End, 1, 2)) + Ws = Op->getOperand(0); + else if (fitsRegularPattern<int>(Begin + 1, 2, End, Indices.size() + 1, 2)) + Ws = Op->getOperand(1); + else + return SDValue(); - return DAG.getNode(MipsISD::ILVOD, SDLoc(Op), ResTy, Op->getOperand(0), - Op->getOperand(1)); + return DAG.getNode(MipsISD::ILVOD, SDLoc(Op), ResTy, Wt, Ws); } -// Lower VECTOR_SHUFFLE into ILVL (if possible). +// Lower VECTOR_SHUFFLE into ILVR (if possible). // -// ILVL interleaves consecutive elements from the left half of each vector. +// ILVR interleaves consecutive elements from the right (lowest-indexed) half of +// each vector. // -// It is possible to lower into ILVL when the mask takes the form: -// <0, n, 1, n+1, 2, n+2, ...> +// It is possible to lower into ILVR when the mask consists of two of the +// following forms interleaved: +// <0, 1, 2, ...> +// <n, n+1, n+2, ...> // where n is the number of elements in the vector. +// For example: +// <0, 0, 1, 1, 2, 2, ...> +// <0, n, 1, n+1, 2, n+2, ...> // // When undef's appear in the mask they are treated as if they were whatever -// value is necessary in order to fit the above form. -static SDValue lowerVECTOR_SHUFFLE_ILVL(SDValue Op, EVT ResTy, +// value is necessary in order to fit the above forms. +static SDValue lowerVECTOR_SHUFFLE_ILVR(SDValue Op, EVT ResTy, SmallVector<int, 16> Indices, SelectionDAG &DAG) { - assert ((Indices.size() % 2) == 0); - int WsIdx = 0; - int WtIdx = ResTy.getVectorNumElements(); + assert((Indices.size() % 2) == 0); + + SDValue Wt; + SDValue Ws; + const auto &Begin = Indices.begin(); + const auto &End = Indices.end(); + + // Check even elements are taken from the right (lowest-indexed) elements of + // one half or the other and pick an operand accordingly. + if (fitsRegularPattern<int>(Begin, 2, End, 0, 1)) + Wt = Op->getOperand(0); + else if (fitsRegularPattern<int>(Begin, 2, End, Indices.size(), 1)) + Wt = Op->getOperand(1); + else + return SDValue(); - for (unsigned i = 0; i < Indices.size(); i += 2) { - if (Indices[i] != -1 && Indices[i] != WsIdx) - return SDValue(); - if (Indices[i+1] != -1 && Indices[i+1] != WtIdx) - return SDValue(); - WsIdx ++; - WtIdx ++; - } + // Check odd elements are taken from the right (lowest-indexed) elements of + // one half or the other and pick an operand accordingly. + if (fitsRegularPattern<int>(Begin + 1, 2, End, 0, 1)) + Ws = Op->getOperand(0); + else if (fitsRegularPattern<int>(Begin + 1, 2, End, Indices.size(), 1)) + Ws = Op->getOperand(1); + else + return SDValue(); - return DAG.getNode(MipsISD::ILVL, SDLoc(Op), ResTy, Op->getOperand(0), - Op->getOperand(1)); + return DAG.getNode(MipsISD::ILVR, SDLoc(Op), ResTy, Ws, Wt); } -// Lower VECTOR_SHUFFLE into ILVR (if possible). +// Lower VECTOR_SHUFFLE into ILVL (if possible). // -// ILVR interleaves consecutive elements from the right half of each vector. +// ILVL interleaves consecutive elements from the left (highest-indexed) half +// of each vector. // -// It is possible to lower into ILVR when the mask takes the form: -// <x, n+x, x+1, n+x+1, x+2, n+x+2, ...> +// It is possible to lower into ILVL when the mask consists of two of the +// following forms interleaved: +// <x, x+1, x+2, ...> +// <n+x, n+x+1, n+x+2, ...> // where n is the number of elements in the vector and x is half n. +// For example: +// <x, x, x+1, x+1, x+2, x+2, ...> +// <x, n+x, x+1, n+x+1, x+2, n+x+2, ...> // // When undef's appear in the mask they are treated as if they were whatever -// value is necessary in order to fit the above form. -static SDValue lowerVECTOR_SHUFFLE_ILVR(SDValue Op, EVT ResTy, +// value is necessary in order to fit the above forms. +static SDValue lowerVECTOR_SHUFFLE_ILVL(SDValue Op, EVT ResTy, SmallVector<int, 16> Indices, SelectionDAG &DAG) { - assert ((Indices.size() % 2) == 0); - unsigned NumElts = ResTy.getVectorNumElements(); - int WsIdx = NumElts / 2; - int WtIdx = NumElts + NumElts / 2; + assert((Indices.size() % 2) == 0); + + unsigned HalfSize = Indices.size() / 2; + SDValue Wt; + SDValue Ws; + const auto &Begin = Indices.begin(); + const auto &End = Indices.end(); + + // Check even elements are taken from the left (highest-indexed) elements of + // one half or the other and pick an operand accordingly. + if (fitsRegularPattern<int>(Begin, 2, End, HalfSize, 1)) + Wt = Op->getOperand(0); + else if (fitsRegularPattern<int>(Begin, 2, End, Indices.size() + HalfSize, 1)) + Wt = Op->getOperand(1); + else + return SDValue(); - for (unsigned i = 0; i < Indices.size(); i += 2) { - if (Indices[i] != -1 && Indices[i] != WsIdx) - return SDValue(); - if (Indices[i+1] != -1 && Indices[i+1] != WtIdx) - return SDValue(); - WsIdx ++; - WtIdx ++; - } + // Check odd elements are taken from the left (highest-indexed) elements of + // one half or the other and pick an operand accordingly. + if (fitsRegularPattern<int>(Begin + 1, 2, End, HalfSize, 1)) + Ws = Op->getOperand(0); + else if (fitsRegularPattern<int>(Begin + 1, 2, End, Indices.size() + HalfSize, + 1)) + Ws = Op->getOperand(1); + else + return SDValue(); - return DAG.getNode(MipsISD::ILVR, SDLoc(Op), ResTy, Op->getOperand(0), - Op->getOperand(1)); + return DAG.getNode(MipsISD::ILVL, SDLoc(Op), ResTy, Ws, Wt); } // Lower VECTOR_SHUFFLE into PCKEV (if possible). // // PCKEV copies the even elements of each vector into the result vector. // -// It is possible to lower into PCKEV when the mask takes the form: -// <0, 2, 4, ..., n, n+2, n+4, ...> +// It is possible to lower into PCKEV when the mask consists of two of the +// following forms concatenated: +// <0, 2, 4, ...> +// <n, n+2, n+4, ...> // where n is the number of elements in the vector. +// For example: +// <0, 2, 4, ..., 0, 2, 4, ...> +// <0, 2, 4, ..., n, n+2, n+4, ...> // // When undef's appear in the mask they are treated as if they were whatever -// value is necessary in order to fit the above form. +// value is necessary in order to fit the above forms. static SDValue lowerVECTOR_SHUFFLE_PCKEV(SDValue Op, EVT ResTy, SmallVector<int, 16> Indices, SelectionDAG &DAG) { - assert ((Indices.size() % 2) == 0); - int Idx = 0; + assert((Indices.size() % 2) == 0); + + SDValue Wt; + SDValue Ws; + const auto &Begin = Indices.begin(); + const auto &Mid = Indices.begin() + Indices.size() / 2; + const auto &End = Indices.end(); + + if (fitsRegularPattern<int>(Begin, 1, Mid, 0, 2)) + Wt = Op->getOperand(0); + else if (fitsRegularPattern<int>(Begin, 1, Mid, Indices.size(), 2)) + Wt = Op->getOperand(1); + else + return SDValue(); - for (unsigned i = 0; i < Indices.size(); ++i) { - if (Indices[i] != -1 && Indices[i] != Idx) - return SDValue(); - Idx += 2; - } + if (fitsRegularPattern<int>(Mid, 1, End, 0, 2)) + Ws = Op->getOperand(0); + else if (fitsRegularPattern<int>(Mid, 1, End, Indices.size(), 2)) + Ws = Op->getOperand(1); + else + return SDValue(); - return DAG.getNode(MipsISD::PCKEV, SDLoc(Op), ResTy, Op->getOperand(0), - Op->getOperand(1)); + return DAG.getNode(MipsISD::PCKEV, SDLoc(Op), ResTy, Ws, Wt); } // Lower VECTOR_SHUFFLE into PCKOD (if possible). // // PCKOD copies the odd elements of each vector into the result vector. // -// It is possible to lower into PCKOD when the mask takes the form: -// <1, 3, 5, ..., n+1, n+3, n+5, ...> +// It is possible to lower into PCKOD when the mask consists of two of the +// following forms concatenated: +// <1, 3, 5, ...> +// <n+1, n+3, n+5, ...> // where n is the number of elements in the vector. +// For example: +// <1, 3, 5, ..., 1, 3, 5, ...> +// <1, 3, 5, ..., n+1, n+3, n+5, ...> // // When undef's appear in the mask they are treated as if they were whatever -// value is necessary in order to fit the above form. +// value is necessary in order to fit the above forms. static SDValue lowerVECTOR_SHUFFLE_PCKOD(SDValue Op, EVT ResTy, SmallVector<int, 16> Indices, SelectionDAG &DAG) { - assert ((Indices.size() % 2) == 0); - int Idx = 1; + assert((Indices.size() % 2) == 0); + + SDValue Wt; + SDValue Ws; + const auto &Begin = Indices.begin(); + const auto &Mid = Indices.begin() + Indices.size() / 2; + const auto &End = Indices.end(); + + if (fitsRegularPattern<int>(Begin, 1, Mid, 1, 2)) + Wt = Op->getOperand(0); + else if (fitsRegularPattern<int>(Begin, 1, Mid, Indices.size() + 1, 2)) + Wt = Op->getOperand(1); + else + return SDValue(); - for (unsigned i = 0; i < Indices.size(); ++i) { - if (Indices[i] != -1 && Indices[i] != Idx) - return SDValue(); - Idx += 2; - } + if (fitsRegularPattern<int>(Mid, 1, End, 1, 2)) + Ws = Op->getOperand(0); + else if (fitsRegularPattern<int>(Mid, 1, End, Indices.size() + 1, 2)) + Ws = Op->getOperand(1); + else + return SDValue(); - return DAG.getNode(MipsISD::PCKOD, SDLoc(Op), ResTy, Op->getOperand(0), - Op->getOperand(1)); + return DAG.getNode(MipsISD::PCKOD, SDLoc(Op), ResTy, Ws, Wt); } // Lower VECTOR_SHUFFLE into VSHF. @@ -2667,7 +2824,7 @@ static SDValue lowerVECTOR_SHUFFLE_VSHF(SDValue Op, EVT ResTy, for (SmallVector<int, 16>::iterator I = Indices.begin(); I != Indices.end(); ++I) - Ops.push_back(DAG.getTargetConstant(*I, MaskEltTy)); + Ops.push_back(DAG.getTargetConstant(*I, DL, MaskEltTy)); SDValue MaskVec = DAG.getNode(ISD::BUILD_VECTOR, DL, MaskVecTy, Ops); @@ -2707,10 +2864,11 @@ SDValue MipsSETargetLowering::lowerVECTOR_SHUFFLE(SDValue Op, for (int i = 0; i < ResTyNumElts; ++i) Indices.push_back(Node->getMaskElt(i)); - SDValue Result = lowerVECTOR_SHUFFLE_SHF(Op, ResTy, Indices, DAG); - if (Result.getNode()) - return Result; - Result = lowerVECTOR_SHUFFLE_ILVEV(Op, ResTy, Indices, DAG); + // splati.[bhwd] is preferable to the others but is matched from + // MipsISD::VSHF. + if (isVECTOR_SHUFFLE_SPLATI(Op, ResTy, Indices, DAG)) + return lowerVECTOR_SHUFFLE_VSHF(Op, ResTy, Indices, DAG); + SDValue Result = lowerVECTOR_SHUFFLE_ILVEV(Op, ResTy, Indices, DAG); if (Result.getNode()) return Result; Result = lowerVECTOR_SHUFFLE_ILVOD(Op, ResTy, Indices, DAG); @@ -2728,6 +2886,9 @@ SDValue MipsSETargetLowering::lowerVECTOR_SHUFFLE(SDValue Op, Result = lowerVECTOR_SHUFFLE_PCKOD(Op, ResTy, Indices, DAG); if (Result.getNode()) return Result; + Result = lowerVECTOR_SHUFFLE_SHF(Op, ResTy, Indices, DAG); + if (Result.getNode()) + return Result; return lowerVECTOR_SHUFFLE_VSHF(Op, ResTy, Indices, DAG); } @@ -2747,8 +2908,7 @@ emitBPOSGE32(MachineInstr *MI, MachineBasicBlock *BB) const{ // $vr0 = phi($vr2, $fbb, $vr1, $tbb) MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); const TargetRegisterClass *RC = &Mips::GPR32RegClass; DebugLoc DL = MI->getDebugLoc(); const BasicBlock *LLVM_BB = BB->getBasicBlock(); @@ -2813,8 +2973,7 @@ emitMSACBranchPseudo(MachineInstr *MI, MachineBasicBlock *BB, // $rd = phi($rd1, $fbb, $rd2, $tbb) MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); const TargetRegisterClass *RC = &Mips::GPR32RegClass; DebugLoc DL = MI->getDebugLoc(); const BasicBlock *LLVM_BB = BB->getBasicBlock(); @@ -2875,8 +3034,7 @@ emitMSACBranchPseudo(MachineInstr *MI, MachineBasicBlock *BB, // for lane 1 because it would require FR=0 mode which isn't supported by MSA. MachineBasicBlock * MipsSETargetLowering:: emitCOPY_FW(MachineInstr *MI, MachineBasicBlock *BB) const{ - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned Fd = MI->getOperand(0).getReg(); @@ -2921,8 +3079,7 @@ MachineBasicBlock * MipsSETargetLowering:: emitCOPY_FD(MachineInstr *MI, MachineBasicBlock *BB) const{ assert(Subtarget.isFP64bit()); - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); unsigned Fd = MI->getOperand(0).getReg(); unsigned Ws = MI->getOperand(1).getReg(); @@ -2951,8 +3108,7 @@ emitCOPY_FD(MachineInstr *MI, MachineBasicBlock *BB) const{ MachineBasicBlock * MipsSETargetLowering::emitINSERT_FW(MachineInstr *MI, MachineBasicBlock *BB) const { - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned Wd = MI->getOperand(0).getReg(); @@ -2988,8 +3144,7 @@ MipsSETargetLowering::emitINSERT_FD(MachineInstr *MI, MachineBasicBlock *BB) const { assert(Subtarget.isFP64bit()); - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned Wd = MI->getOperand(0).getReg(); @@ -3037,8 +3192,7 @@ MipsSETargetLowering::emitINSERT_DF_VIDX(MachineInstr *MI, MachineBasicBlock *BB, unsigned EltSizeInBytes, bool IsFP) const { - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned Wd = MI->getOperand(0).getReg(); @@ -3048,7 +3202,7 @@ MipsSETargetLowering::emitINSERT_DF_VIDX(MachineInstr *MI, const TargetRegisterClass *VecRC = nullptr; const TargetRegisterClass *GPRRC = - Subtarget.isGP64bit() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; + Subtarget.isABI_N64() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; unsigned EltLog2Size; unsigned InsertOp = 0; unsigned InsveOp = 0; @@ -3126,8 +3280,9 @@ MipsSETargetLowering::emitINSERT_DF_VIDX(MachineInstr *MI, // sld.df inteprets $rt modulo the number of columns so we only need to negate // the lane index to do this. unsigned LaneTmp2 = RegInfo.createVirtualRegister(GPRRC); - BuildMI(*BB, MI, DL, TII->get(Mips::SUB), LaneTmp2) - .addReg(Mips::ZERO) + BuildMI(*BB, MI, DL, TII->get(Subtarget.isABI_N64() ? Mips::DSUB : Mips::SUB), + LaneTmp2) + .addReg(Subtarget.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO) .addReg(LaneReg); BuildMI(*BB, MI, DL, TII->get(Mips::SLD_B), Wd) .addReg(WdTmp2) @@ -3148,8 +3303,7 @@ MipsSETargetLowering::emitINSERT_DF_VIDX(MachineInstr *MI, MachineBasicBlock * MipsSETargetLowering::emitFILL_FW(MachineInstr *MI, MachineBasicBlock *BB) const { - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned Wd = MI->getOperand(0).getReg(); @@ -3180,8 +3334,7 @@ MipsSETargetLowering::emitFILL_FD(MachineInstr *MI, MachineBasicBlock *BB) const { assert(Subtarget.isFP64bit()); - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); DebugLoc DL = MI->getDebugLoc(); unsigned Wd = MI->getOperand(0).getReg(); @@ -3209,8 +3362,7 @@ MipsSETargetLowering::emitFILL_FD(MachineInstr *MI, MachineBasicBlock * MipsSETargetLowering::emitFEXP2_W_1(MachineInstr *MI, MachineBasicBlock *BB) const { - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); const TargetRegisterClass *RC = &Mips::MSA128WRegClass; unsigned Ws1 = RegInfo.createVirtualRegister(RC); @@ -3239,8 +3391,7 @@ MipsSETargetLowering::emitFEXP2_W_1(MachineInstr *MI, MachineBasicBlock * MipsSETargetLowering::emitFEXP2_D_1(MachineInstr *MI, MachineBasicBlock *BB) const { - const TargetInstrInfo *TII = - getTargetMachine().getSubtargetImpl()->getInstrInfo(); + const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); const TargetRegisterClass *RC = &Mips::MSA128DRegClass; unsigned Ws1 = RegInfo.createVirtualRegister(RC); diff --git a/contrib/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp b/contrib/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp index 180b043..786307b 100644 --- a/contrib/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsSEInstrInfo.cpp @@ -27,7 +27,7 @@ using namespace llvm; MipsSEInstrInfo::MipsSEInstrInfo(const MipsSubtarget &STI) : MipsInstrInfo(STI, STI.getRelocationModel() == Reloc::PIC_ ? Mips::B : Mips::J), - RI(STI) {} + RI() {} const MipsRegisterInfo &MipsSEInstrInfo::getRegisterInfo() const { return RI; @@ -359,10 +359,10 @@ unsigned MipsSEInstrInfo::getOppositeBranchOpc(unsigned Opc) const { void MipsSEInstrInfo::adjustStackPtr(unsigned SP, int64_t Amount, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { - const MipsSubtarget &STI = Subtarget; + MipsABIInfo ABI = Subtarget.getABI(); DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc(); - unsigned ADDu = STI.isABI_N64() ? Mips::DADDu : Mips::ADDu; - unsigned ADDiu = STI.isABI_N64() ? Mips::DADDiu : Mips::ADDiu; + unsigned ADDu = ABI.GetPtrAdduOp(); + unsigned ADDiu = ABI.GetPtrAddiuOp(); if (Amount == 0) return; @@ -610,7 +610,8 @@ void MipsSEInstrInfo::expandEhReturn(MachineBasicBlock &MBB, // This pseudo instruction is generated as part of the lowering of // ISD::EH_RETURN. We convert it to a stack increment by OffsetReg, and // indirect jump to TargetReg - unsigned ADDU = Subtarget.isABI_N64() ? Mips::DADDu : Mips::ADDu; + MipsABIInfo ABI = Subtarget.getABI(); + unsigned ADDU = ABI.GetPtrAdduOp(); unsigned SP = Subtarget.isGP64bit() ? Mips::SP_64 : Mips::SP; unsigned RA = Subtarget.isGP64bit() ? Mips::RA_64 : Mips::RA; unsigned T9 = Subtarget.isGP64bit() ? Mips::T9_64 : Mips::T9; diff --git a/contrib/llvm/lib/Target/Mips/MipsSEInstrInfo.h b/contrib/llvm/lib/Target/Mips/MipsSEInstrInfo.h index d16fab2..bebbabf 100644 --- a/contrib/llvm/lib/Target/Mips/MipsSEInstrInfo.h +++ b/contrib/llvm/lib/Target/Mips/MipsSEInstrInfo.h @@ -68,7 +68,7 @@ public: /// Adjust SP by Amount bytes. void adjustStackPtr(unsigned SP, int64_t Amount, MachineBasicBlock &MBB, - MachineBasicBlock::iterator I) const; + MachineBasicBlock::iterator I) const override; /// Emit a series of instructions to load an immediate. If NewImm is a /// non-NULL parameter, the last instruction is not emitted, but instead diff --git a/contrib/llvm/lib/Target/Mips/MipsSERegisterInfo.cpp b/contrib/llvm/lib/Target/Mips/MipsSERegisterInfo.cpp index 55c6638..132c3a1 100644 --- a/contrib/llvm/lib/Target/Mips/MipsSERegisterInfo.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsSERegisterInfo.cpp @@ -18,6 +18,7 @@ #include "MipsMachineFunction.h" #include "MipsSEInstrInfo.h" #include "MipsSubtarget.h" +#include "MipsTargetMachine.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/CodeGen/MachineFrameInfo.h" @@ -41,8 +42,7 @@ using namespace llvm; #define DEBUG_TYPE "mips-reg-info" -MipsSERegisterInfo::MipsSERegisterInfo(const MipsSubtarget &ST) - : MipsRegisterInfo(ST) {} +MipsSERegisterInfo::MipsSERegisterInfo() : MipsRegisterInfo() {} bool MipsSERegisterInfo:: requiresRegisterScavenging(const MachineFunction &MF) const { @@ -111,6 +111,11 @@ void MipsSERegisterInfo::eliminateFI(MachineBasicBlock::iterator II, MachineFrameInfo *MFI = MF.getFrameInfo(); MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); + MipsABIInfo ABI = + static_cast<const MipsTargetMachine &>(MF.getTarget()).getABI(); + const MipsRegisterInfo *RegInfo = + static_cast<const MipsRegisterInfo *>(MF.getSubtarget().getRegisterInfo()); + const std::vector<CalleeSavedInfo> &CSI = MFI->getCalleeSavedInfo(); int MinCSFI = 0; int MaxCSFI = -1; @@ -132,8 +137,15 @@ void MipsSERegisterInfo::eliminateFI(MachineBasicBlock::iterator II, unsigned FrameReg; if ((FrameIndex >= MinCSFI && FrameIndex <= MaxCSFI) || EhDataRegFI) - FrameReg = Subtarget.isABI_N64() ? Mips::SP_64 : Mips::SP; - else + FrameReg = ABI.GetStackPtr(); + else if (RegInfo->needsStackRealignment(MF)) { + if (MFI->hasVarSizedObjects() && !MFI->isFixedObjectIndex(FrameIndex)) + FrameReg = ABI.GetBasePtr(); + else if (MFI->isFixedObjectIndex(FrameIndex)) + FrameReg = getFrameRegister(MF); + else + FrameReg = ABI.GetStackPtr(); + } else FrameReg = getFrameRegister(MF); // Calculate final offset. @@ -165,15 +177,16 @@ void MipsSERegisterInfo::eliminateFI(MachineBasicBlock::iterator II, // (where n < 16) and doesn't, but does fit into 16-bits then use an ADDiu MachineBasicBlock &MBB = *MI.getParent(); DebugLoc DL = II->getDebugLoc(); - unsigned ADDiu = Subtarget.isABI_N64() ? Mips::DADDiu : Mips::ADDiu; - const TargetRegisterClass *RC = - Subtarget.isABI_N64() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; + const TargetRegisterClass *PtrRC = + ABI.ArePtrs64bit() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo(); - unsigned Reg = RegInfo.createVirtualRegister(RC); + unsigned Reg = RegInfo.createVirtualRegister(PtrRC); const MipsSEInstrInfo &TII = *static_cast<const MipsSEInstrInfo *>( MBB.getParent()->getSubtarget().getInstrInfo()); - BuildMI(MBB, II, DL, TII.get(ADDiu), Reg).addReg(FrameReg).addImm(Offset); + BuildMI(MBB, II, DL, TII.get(ABI.GetPtrAddiuOp()), Reg) + .addReg(FrameReg) + .addImm(Offset); FrameReg = Reg; Offset = 0; @@ -183,14 +196,13 @@ void MipsSERegisterInfo::eliminateFI(MachineBasicBlock::iterator II, // instructions. MachineBasicBlock &MBB = *MI.getParent(); DebugLoc DL = II->getDebugLoc(); - unsigned ADDu = Subtarget.isABI_N64() ? Mips::DADDu : Mips::ADDu; unsigned NewImm = 0; const MipsSEInstrInfo &TII = *static_cast<const MipsSEInstrInfo *>( MBB.getParent()->getSubtarget().getInstrInfo()); unsigned Reg = TII.loadImmediate(Offset, MBB, II, DL, OffsetBitSize == 16 ? &NewImm : nullptr); - BuildMI(MBB, II, DL, TII.get(ADDu), Reg).addReg(FrameReg) + BuildMI(MBB, II, DL, TII.get(ABI.GetPtrAdduOp()), Reg).addReg(FrameReg) .addReg(Reg, RegState::Kill); FrameReg = Reg; diff --git a/contrib/llvm/lib/Target/Mips/MipsSERegisterInfo.h b/contrib/llvm/lib/Target/Mips/MipsSERegisterInfo.h index 6b70d07..ebae190 100644 --- a/contrib/llvm/lib/Target/Mips/MipsSERegisterInfo.h +++ b/contrib/llvm/lib/Target/Mips/MipsSERegisterInfo.h @@ -22,7 +22,7 @@ class MipsSEInstrInfo; class MipsSERegisterInfo : public MipsRegisterInfo { public: - MipsSERegisterInfo(const MipsSubtarget &Subtarget); + MipsSERegisterInfo(); bool requiresRegisterScavenging(const MachineFunction &MF) const override; diff --git a/contrib/llvm/lib/Target/Mips/MipsSchedule.td b/contrib/llvm/lib/Target/Mips/MipsSchedule.td index ea98199..54b5d28 100644 --- a/contrib/llvm/lib/Target/Mips/MipsSchedule.td +++ b/contrib/llvm/lib/Target/Mips/MipsSchedule.td @@ -65,7 +65,9 @@ def II_DSRL32 : InstrItinClass; def II_DSRLV : InstrItinClass; def II_DSUBU : InstrItinClass; def II_DSUB : InstrItinClass; +def II_EXT : InstrItinClass; // Any EXT instruction def II_FLOOR : InstrItinClass; +def II_INS : InstrItinClass; // Any INS instruction def II_LB : InstrItinClass; def II_LBU : InstrItinClass; def II_LD : InstrItinClass; @@ -198,6 +200,8 @@ def MipsGenericItineraries : ProcessorItineraries<[ALU, IMULDIV], [], [ InstrItinData<II_DSUB , [InstrStage<1, [ALU]>]>, InstrItinData<II_DROTR , [InstrStage<1, [ALU]>]>, InstrItinData<II_DROTRV , [InstrStage<1, [ALU]>]>, + InstrItinData<II_EXT , [InstrStage<1, [ALU]>]>, + InstrItinData<II_INS , [InstrStage<1, [ALU]>]>, InstrItinData<II_LUI , [InstrStage<1, [ALU]>]>, InstrItinData<II_MOVF , [InstrStage<1, [ALU]>]>, InstrItinData<II_MOVN , [InstrStage<1, [ALU]>]>, diff --git a/contrib/llvm/lib/Target/Mips/MipsSubtarget.cpp b/contrib/llvm/lib/Target/Mips/MipsSubtarget.cpp index d035ebe..7ea10eb 100644 --- a/contrib/llvm/lib/Target/Mips/MipsSubtarget.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsSubtarget.cpp @@ -33,93 +33,46 @@ using namespace llvm; // FIXME: Maybe this should be on by default when Mips16 is specified // -static cl::opt<bool> Mixed16_32( - "mips-mixed-16-32", - cl::init(false), - cl::desc("Allow for a mixture of Mips16 " - "and Mips32 code in a single source file"), - cl::Hidden); - -static cl::opt<bool> Mips_Os16( - "mips-os16", - cl::init(false), - cl::desc("Compile all functions that don' use " - "floating point as Mips 16"), - cl::Hidden); - static cl::opt<bool> -Mips16HardFloat("mips16-hard-float", cl::NotHidden, - cl::desc("MIPS: mips16 hard float enable."), - cl::init(false)); + Mixed16_32("mips-mixed-16-32", cl::init(false), + cl::desc("Allow for a mixture of Mips16 " + "and Mips32 code in a single output file"), + cl::Hidden); + +static cl::opt<bool> Mips_Os16("mips-os16", cl::init(false), + cl::desc("Compile all functions that don't use " + "floating point as Mips 16"), + cl::Hidden); + +static cl::opt<bool> Mips16HardFloat("mips16-hard-float", cl::NotHidden, + cl::desc("Enable mips16 hard float."), + cl::init(false)); static cl::opt<bool> -Mips16ConstantIslands( - "mips16-constant-islands", cl::NotHidden, - cl::desc("MIPS: mips16 constant islands enable."), - cl::init(true)); + Mips16ConstantIslands("mips16-constant-islands", cl::NotHidden, + cl::desc("Enable mips16 constant islands."), + cl::init(true)); static cl::opt<bool> -GPOpt("mgpopt", cl::Hidden, - cl::desc("MIPS: Enable gp-relative addressing of small data items")); - -/// Select the Mips CPU for the given triple and cpu name. -/// FIXME: Merge with the copy in MipsMCTargetDesc.cpp -static StringRef selectMipsCPU(Triple TT, StringRef CPU) { - if (CPU.empty() || CPU == "generic") { - if (TT.getArch() == Triple::mips || TT.getArch() == Triple::mipsel) - CPU = "mips32"; - else - CPU = "mips64"; - } - return CPU; -} + GPOpt("mgpopt", cl::Hidden, + cl::desc("Enable gp-relative addressing of mips small data items")); void MipsSubtarget::anchor() { } -static std::string computeDataLayout(const MipsSubtarget &ST) { - std::string Ret = ""; - - // There are both little and big endian mips. - if (ST.isLittle()) - Ret += "e"; - else - Ret += "E"; - - Ret += "-m:m"; - - // Pointers are 32 bit on some ABIs. - if (!ST.isABI_N64()) - Ret += "-p:32:32"; - - // 8 and 16 bit integers only need no have natural alignment, but try to - // align them to 32 bits. 64 bit integers have natural alignment. - Ret += "-i8:8:32-i16:16:32-i64:64"; - - // 32 bit registers are always available and the stack is at least 64 bit - // aligned. On N64 64 bit registers are also available and the stack is - // 128 bit aligned. - if (ST.isABI_N64() || ST.isABI_N32()) - Ret += "-n32:64-S128"; - else - Ret += "-n32-S64"; - - return Ret; -} - MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU, const std::string &FS, bool little, const MipsTargetMachine &TM) : MipsGenSubtargetInfo(TT, CPU, FS), MipsArchVersion(MipsDefault), - ABI(MipsABIInfo::Unknown()), IsLittle(little), IsSingleFloat(false), - IsFPXX(false), NoABICalls(false), IsFP64bit(false), UseOddSPReg(true), + IsLittle(little), IsSoftFloat(false), IsSingleFloat(false), IsFPXX(false), + NoABICalls(false), IsFP64bit(false), UseOddSPReg(true), IsNaN2008bit(false), IsGP64bit(false), HasVFPU(false), HasCnMips(false), HasMips3_32(false), HasMips3_32r2(false), HasMips4_32(false), HasMips4_32r2(false), HasMips5_32r2(false), InMips16Mode(false), InMips16HardFloat(Mips16HardFloat), InMicroMipsMode(false), HasDSP(false), HasDSPR2(false), AllowMixed16_32(Mixed16_32 | Mips_Os16), Os16(Mips_Os16), - HasMSA(false), TM(TM), TargetTriple(TT), - DL(computeDataLayout(initializeSubtargetDependencies(CPU, FS, TM))), - TSInfo(DL), InstrInfo(MipsInstrInfo::create(*this)), + HasMSA(false), TM(TM), TargetTriple(TT), TSInfo(*TM.getDataLayout()), + InstrInfo( + MipsInstrInfo::create(initializeSubtargetDependencies(CPU, FS, TM))), FrameLowering(MipsFrameLowering::create(*this)), TLInfo(MipsTargetLowering::create(TM, *this)) { @@ -135,13 +88,6 @@ MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU, if (MipsArchVersion == Mips5) report_fatal_error("Code generation for MIPS-V is not implemented", false); - // Assert exactly one ABI was chosen. - assert(ABI.IsKnown()); - assert((((getFeatureBits() & Mips::FeatureO32) != 0) + - ((getFeatureBits() & Mips::FeatureEABI) != 0) + - ((getFeatureBits() & Mips::FeatureN32) != 0) + - ((getFeatureBits() & Mips::FeatureN64) != 0)) == 1); - // Check if Architecture and ABI are compatible. assert(((!isGP64bit() && (isABI_O32() || isABI_EABI())) || (isGP64bit() && (isABI_N32() || isABI_N64()))) && @@ -195,23 +141,19 @@ CodeGenOpt::Level MipsSubtarget::getOptLevelToEnablePostRAScheduler() const { MipsSubtarget & MipsSubtarget::initializeSubtargetDependencies(StringRef CPU, StringRef FS, const TargetMachine &TM) { - std::string CPUName = selectMipsCPU(TargetTriple, CPU); - + std::string CPUName = MIPS_MC::selectMipsCPU(TM.getTargetTriple(), CPU); + // Parse features string. ParseSubtargetFeatures(CPUName, FS); // Initialize scheduling itinerary for the specified CPU. InstrItins = getInstrItineraryForCPU(CPUName); - if (InMips16Mode && !TM.Options.UseSoftFloat) + if (InMips16Mode && !IsSoftFloat) InMips16HardFloat = true; return *this; } -bool MipsSubtarget::abiUsesSoftFloat() const { - return TM.Options.UseSoftFloat && !InMips16HardFloat; -} - bool MipsSubtarget::useConstantIslands() { DEBUG(dbgs() << "use constant islands " << Mips16ConstantIslands << "\n"); return Mips16ConstantIslands; @@ -220,3 +162,9 @@ bool MipsSubtarget::useConstantIslands() { Reloc::Model MipsSubtarget::getRelocationModel() const { return TM.getRelocationModel(); } + +bool MipsSubtarget::isABI_EABI() const { return getABI().IsEABI(); } +bool MipsSubtarget::isABI_N64() const { return getABI().IsN64(); } +bool MipsSubtarget::isABI_N32() const { return getABI().IsN32(); } +bool MipsSubtarget::isABI_O32() const { return getABI().IsO32(); } +const MipsABIInfo &MipsSubtarget::getABI() const { return TM.getABI(); } diff --git a/contrib/llvm/lib/Target/Mips/MipsSubtarget.h b/contrib/llvm/lib/Target/Mips/MipsSubtarget.h index aca69a6..0bfafc8 100644 --- a/contrib/llvm/lib/Target/Mips/MipsSubtarget.h +++ b/contrib/llvm/lib/Target/Mips/MipsSubtarget.h @@ -38,19 +38,19 @@ class MipsSubtarget : public MipsGenSubtargetInfo { enum MipsArchEnum { MipsDefault, - Mips1, Mips2, Mips32, Mips32r2, Mips32r6, Mips3, Mips4, Mips5, Mips64, - Mips64r2, Mips64r6 + Mips1, Mips2, Mips32, Mips32r2, Mips32r3, Mips32r5, Mips32r6, Mips32Max, + Mips3, Mips4, Mips5, Mips64, Mips64r2, Mips64r3, Mips64r5, Mips64r6 }; // Mips architecture version MipsArchEnum MipsArchVersion; - // Selected ABI - MipsABIInfo ABI; - // IsLittle - The target is Little Endian bool IsLittle; + // IsSoftFloat - The target does not support any floating point instructions. + bool IsSoftFloat; + // IsSingleFloat - The target only supports single precision float // point operations. This enable the target to use all 32 32-bit // floating point registers instead of only using even ones. @@ -140,7 +140,6 @@ class MipsSubtarget : public MipsGenSubtargetInfo { Triple TargetTriple; - const DataLayout DL; // Calculates type size & alignment const MipsSelectionDAGInfo TSInfo; std::unique_ptr<const MipsInstrInfo> InstrInfo; std::unique_ptr<const MipsFrameLowering> FrameLowering; @@ -153,12 +152,12 @@ public: CodeGenOpt::Level getOptLevelToEnablePostRAScheduler() const override; /// Only O32 and EABI supported right now. - bool isABI_EABI() const { return ABI.IsEABI(); } - bool isABI_N64() const { return ABI.IsN64(); } - bool isABI_N32() const { return ABI.IsN32(); } - bool isABI_O32() const { return ABI.IsO32(); } + bool isABI_EABI() const; + bool isABI_N64() const; + bool isABI_N32() const; + bool isABI_O32() const; + const MipsABIInfo &getABI() const; bool isABI_FPXX() const { return isABI_O32() && IsFPXX; } - const MipsABIInfo &getABI() const { return ABI; } /// This constructor initializes the data members to match that /// of the specified triple. @@ -178,21 +177,30 @@ public: bool hasMips4_32() const { return HasMips4_32; } bool hasMips4_32r2() const { return HasMips4_32r2; } bool hasMips32() const { - return MipsArchVersion >= Mips32 && MipsArchVersion != Mips3 && - MipsArchVersion != Mips4 && MipsArchVersion != Mips5; + return (MipsArchVersion >= Mips32 && MipsArchVersion < Mips32Max) || + hasMips64(); } bool hasMips32r2() const { - return MipsArchVersion == Mips32r2 || MipsArchVersion == Mips32r6 || - MipsArchVersion == Mips64r2 || MipsArchVersion == Mips64r6; + return (MipsArchVersion >= Mips32r2 && MipsArchVersion < Mips32Max) || + hasMips64r2(); + } + bool hasMips32r3() const { + return (MipsArchVersion >= Mips32r3 && MipsArchVersion < Mips32Max) || + hasMips64r2(); + } + bool hasMips32r5() const { + return (MipsArchVersion >= Mips32r5 && MipsArchVersion < Mips32Max) || + hasMips64r2(); } bool hasMips32r6() const { - return MipsArchVersion == Mips32r6 || MipsArchVersion == Mips64r6; + return (MipsArchVersion >= Mips32r6 && MipsArchVersion < Mips32Max) || + hasMips64r6(); } bool hasMips64() const { return MipsArchVersion >= Mips64; } - bool hasMips64r2() const { - return MipsArchVersion == Mips64r2 || MipsArchVersion == Mips64r6; - } - bool hasMips64r6() const { return MipsArchVersion == Mips64r6; } + bool hasMips64r2() const { return MipsArchVersion >= Mips64r2; } + bool hasMips64r3() const { return MipsArchVersion >= Mips64r3; } + bool hasMips64r5() const { return MipsArchVersion >= Mips64r5; } + bool hasMips64r6() const { return MipsArchVersion >= Mips64r6; } bool hasCnMips() const { return HasCnMips; } @@ -220,6 +228,7 @@ public: return inMips16Mode() && InMips16HardFloat; } bool inMicroMipsMode() const { return InMicroMipsMode; } + bool inMicroMips32r6Mode() const { return InMicroMipsMode && hasMips32r6(); } bool hasDSP() const { return HasDSP; } bool hasDSPR2() const { return HasDSPR2; } bool hasMSA() const { return HasMSA; } @@ -227,7 +236,7 @@ public: bool hasStandardEncoding() const { return !inMips16Mode(); } - bool abiUsesSoftFloat() const; + bool useSoftFloat() const { return IsSoftFloat; } bool enableLongBranchPass() const { return hasStandardEncoding() || allowMixed16_32(); @@ -238,9 +247,9 @@ public: bool hasMTHC1() const { return hasMips32r2(); } bool allowMixed16_32() const { return inMips16ModeDefault() | - AllowMixed16_32;} + AllowMixed16_32; } - bool os16() const { return Os16;}; + bool os16() const { return Os16; } bool isTargetNaCl() const { return TargetTriple.isOSNaCl(); } @@ -270,7 +279,6 @@ public: const MipsSelectionDAGInfo *getSelectionDAGInfo() const override { return &TSInfo; } - const DataLayout *getDataLayout() const override { return &DL; } const MipsInstrInfo *getInstrInfo() const override { return InstrInfo.get(); } const TargetFrameLowering *getFrameLowering() const override { return FrameLowering.get(); diff --git a/contrib/llvm/lib/Target/Mips/MipsTargetMachine.cpp b/contrib/llvm/lib/Target/Mips/MipsTargetMachine.cpp index 426b71d..b279184 100644 --- a/contrib/llvm/lib/Target/Mips/MipsTargetMachine.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsTargetMachine.cpp @@ -14,14 +14,11 @@ #include "MipsTargetMachine.h" #include "Mips.h" #include "Mips16FrameLowering.h" -#include "Mips16HardFloat.h" #include "Mips16ISelDAGToDAG.h" #include "Mips16ISelLowering.h" #include "Mips16InstrInfo.h" #include "MipsFrameLowering.h" #include "MipsInstrInfo.h" -#include "MipsModuleISelDAGToDAG.h" -#include "MipsOs16.h" #include "MipsSEFrameLowering.h" #include "MipsSEISelDAGToDAG.h" #include "MipsSEISelLowering.h" @@ -29,11 +26,12 @@ #include "MipsTargetObjectFile.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/CodeGen/Passes.h" -#include "llvm/PassManager.h" +#include "llvm/IR/LegacyPassManager.h" #include "llvm/Support/Debug.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Scalar.h" + using namespace llvm; #define DEBUG_TYPE "mips" @@ -46,6 +44,40 @@ extern "C" void LLVMInitializeMipsTarget() { RegisterTargetMachine<MipselTargetMachine> B(TheMips64elTarget); } +static std::string computeDataLayout(StringRef TT, StringRef CPU, + const TargetOptions &Options, + bool isLittle) { + std::string Ret = ""; + MipsABIInfo ABI = + MipsABIInfo::computeTargetABI(Triple(TT), CPU, Options.MCOptions); + + // There are both little and big endian mips. + if (isLittle) + Ret += "e"; + else + Ret += "E"; + + Ret += "-m:m"; + + // Pointers are 32 bit on some ABIs. + if (!ABI.IsN64()) + Ret += "-p:32:32"; + + // 8 and 16 bit integers only need no have natural alignment, but try to + // align them to 32 bits. 64 bit integers have natural alignment. + Ret += "-i8:8:32-i16:16:32-i64:64"; + + // 32 bit registers are always available and the stack is at least 64 bit + // aligned. On N64 64 bit registers are also available and the stack is + // 128 bit aligned. + if (ABI.IsN64() || ABI.IsN32()) + Ret += "-n32:64-S128"; + else + Ret += "-n32-S64"; + + return Ret; +} + // On function prologue, the stack is created by decrementing // its pointer. Once decremented, all references are done with positive // offset from the stack/frame pointer, using StackGrowsUp enables @@ -56,11 +88,11 @@ MipsTargetMachine::MipsTargetMachine(const Target &T, StringRef TT, const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL, bool isLittle) - : LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL), - isLittle(isLittle), - TLOF(make_unique<MipsTargetObjectFile>()), - Subtarget(nullptr), - DefaultSubtarget(TT, CPU, FS, isLittle, *this), + : LLVMTargetMachine(T, computeDataLayout(TT, CPU, Options, isLittle), TT, + CPU, FS, Options, RM, CM, OL), + isLittle(isLittle), TLOF(make_unique<MipsTargetObjectFile>()), + ABI(MipsABIInfo::computeTargetABI(Triple(TT), CPU, Options.MCOptions)), + Subtarget(nullptr), DefaultSubtarget(TT, CPU, FS, isLittle, *this), NoMips16Subtarget(TT, CPU, FS.empty() ? "-mips16" : FS.str() + ",-mips16", isLittle, *this), Mips16Subtarget(TT, CPU, FS.empty() ? "+mips16" : FS.str() + ",+mips16", @@ -91,11 +123,8 @@ MipselTargetMachine(const Target &T, StringRef TT, const MipsSubtarget * MipsTargetMachine::getSubtargetImpl(const Function &F) const { - AttributeSet FnAttrs = F.getAttributes(); - Attribute CPUAttr = - FnAttrs.getAttribute(AttributeSet::FunctionIndex, "target-cpu"); - Attribute FSAttr = - FnAttrs.getAttribute(AttributeSet::FunctionIndex, "target-features"); + Attribute CPUAttr = F.getFnAttribute("target-cpu"); + Attribute FSAttr = F.getFnAttribute("target-features"); std::string CPU = !CPUAttr.hasAttribute(Attribute::None) ? CPUAttr.getValueAsString().str() @@ -104,30 +133,25 @@ MipsTargetMachine::getSubtargetImpl(const Function &F) const { ? FSAttr.getValueAsString().str() : TargetFS; bool hasMips16Attr = - !FnAttrs.getAttribute(AttributeSet::FunctionIndex, "mips16") - .hasAttribute(Attribute::None); + !F.getFnAttribute("mips16").hasAttribute(Attribute::None); bool hasNoMips16Attr = - !FnAttrs.getAttribute(AttributeSet::FunctionIndex, "nomips16") - .hasAttribute(Attribute::None); + !F.getFnAttribute("nomips16").hasAttribute(Attribute::None); // FIXME: This is related to the code below to reset the target options, // we need to know whether or not the soft float flag is set on the - // function before we can generate a subtarget. We also need to use - // it as a key for the subtarget since that can be the only difference - // between two functions. - Attribute SFAttr = - FnAttrs.getAttribute(AttributeSet::FunctionIndex, "use-soft-float"); - bool softFloat = !SFAttr.hasAttribute(Attribute::None) - ? SFAttr.getValueAsString() == "true" - : Options.UseSoftFloat; + // function, so we can enable it as a subtarget feature. + bool softFloat = + F.hasFnAttribute("use-soft-float") && + F.getFnAttribute("use-soft-float").getValueAsString() == "true"; if (hasMips16Attr) FS += FS.empty() ? "+mips16" : ",+mips16"; else if (hasNoMips16Attr) FS += FS.empty() ? "-mips16" : ",-mips16"; + if (softFloat) + FS += FS.empty() ? "+soft-float" : ",+soft-float"; - auto &I = SubtargetMap[CPU + FS + (softFloat ? "use-soft-float=true" - : "use-soft-float=false")]; + auto &I = SubtargetMap[CPU + FS]; if (!I) { // This needs to be done before we create a new subtarget since any // creation will depend on the TM and the code generation flags on the @@ -185,14 +209,14 @@ void MipsPassConfig::addIRPasses() { TargetPassConfig::addIRPasses(); addPass(createAtomicExpandPass(&getMipsTargetMachine())); if (getMipsSubtarget().os16()) - addPass(createMipsOs16(getMipsTargetMachine())); + addPass(createMipsOs16Pass(getMipsTargetMachine())); if (getMipsSubtarget().inMips16HardFloat()) - addPass(createMips16HardFloat(getMipsTargetMachine())); + addPass(createMips16HardFloatPass(getMipsTargetMachine())); } // Install an instruction selector pass using // the ISelDag to gen Mips code. bool MipsPassConfig::addInstSelector() { - addPass(createMipsModuleISelDag(getMipsTargetMachine())); + addPass(createMipsModuleISelDagPass(getMipsTargetMachine())); addPass(createMips16ISelDag(getMipsTargetMachine())); addPass(createMipsSEISelDag(getMipsTargetMachine())); return false; @@ -208,17 +232,17 @@ void MipsPassConfig::addPreRegAlloc() { addPass(createMipsOptimizePICCallPass(getMipsTargetMachine())); } -void MipsTargetMachine::addAnalysisPasses(PassManagerBase &PM) { - if (Subtarget->allowMixed16_32()) { - DEBUG(errs() << "No "); - //FIXME: The Basic Target Transform Info - // pass needs to become a function pass instead of - // being an immutable pass and then this method as it exists now - // would be unnecessary. - PM.add(createNoTargetTransformInfoPass()); - } else - LLVMTargetMachine::addAnalysisPasses(PM); - DEBUG(errs() << "Target Transform Info Pass Added\n"); +TargetIRAnalysis MipsTargetMachine::getTargetIRAnalysis() { + return TargetIRAnalysis([this](Function &F) { + if (Subtarget->allowMixed16_32()) { + DEBUG(errs() << "No Target Transform Info Pass Added\n"); + // FIXME: This is no longer necessary as the TTI returned is per-function. + return TargetTransformInfo(getDataLayout()); + } + + DEBUG(errs() << "Target Transform Info Pass Added\n"); + return TargetTransformInfo(BasicTTIImpl(this, F)); + }); } // Implemented by targets that want to run passes immediately before diff --git a/contrib/llvm/lib/Target/Mips/MipsTargetMachine.h b/contrib/llvm/lib/Target/Mips/MipsTargetMachine.h index 4b097a2..5427d6a 100644 --- a/contrib/llvm/lib/Target/Mips/MipsTargetMachine.h +++ b/contrib/llvm/lib/Target/Mips/MipsTargetMachine.h @@ -14,7 +14,9 @@ #ifndef LLVM_LIB_TARGET_MIPS_MIPSTARGETMACHINE_H #define LLVM_LIB_TARGET_MIPS_MIPSTARGETMACHINE_H +#include "MCTargetDesc/MipsABIInfo.h" #include "MipsSubtarget.h" +#include "llvm/CodeGen/BasicTTIImpl.h" #include "llvm/CodeGen/Passes.h" #include "llvm/CodeGen/SelectionDAGISel.h" #include "llvm/Target/TargetFrameLowering.h" @@ -27,6 +29,8 @@ class MipsRegisterInfo; class MipsTargetMachine : public LLVMTargetMachine { bool isLittle; std::unique_ptr<TargetLoweringObjectFile> TLOF; + // Selected ABI + MipsABIInfo ABI; MipsSubtarget *Subtarget; MipsSubtarget DefaultSubtarget; MipsSubtarget NoMips16Subtarget; @@ -40,9 +44,9 @@ public: CodeModel::Model CM, CodeGenOpt::Level OL, bool isLittle); ~MipsTargetMachine() override; - void addAnalysisPasses(PassManagerBase &PM) override; + TargetIRAnalysis getTargetIRAnalysis() override; - const MipsSubtarget *getSubtargetImpl() const override { + const MipsSubtarget *getSubtargetImpl() const { if (Subtarget) return Subtarget; return &DefaultSubtarget; @@ -61,6 +65,7 @@ public: } bool isLittleEndian() const { return isLittle; } + const MipsABIInfo &getABI() const { return ABI; } }; /// MipsebTargetMachine - Mips32/64 big endian target machine. diff --git a/contrib/llvm/lib/Target/Mips/MipsTargetObjectFile.cpp b/contrib/llvm/lib/Target/Mips/MipsTargetObjectFile.cpp index b56c39b..0f2db60 100644 --- a/contrib/llvm/lib/Target/Mips/MipsTargetObjectFile.cpp +++ b/contrib/llvm/lib/Target/Mips/MipsTargetObjectFile.cpp @@ -9,6 +9,7 @@ #include "MipsTargetObjectFile.h" #include "MipsSubtarget.h" +#include "MipsTargetMachine.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/GlobalVariable.h" @@ -39,16 +40,12 @@ void MipsTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM){ TargetLoweringObjectFileELF::Initialize(Ctx, TM); InitializeELF(TM.Options.UseInitArray); - SmallDataSection = - getContext().getELFSection(".sdata", ELF::SHT_PROGBITS, - ELF::SHF_WRITE |ELF::SHF_ALLOC, - SectionKind::getDataRel()); + SmallDataSection = getContext().getELFSection( + ".sdata", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC); - SmallBSSSection = - getContext().getELFSection(".sbss", ELF::SHT_NOBITS, - ELF::SHF_WRITE |ELF::SHF_ALLOC, - SectionKind::getBSS()); - this->TM = &TM; + SmallBSSSection = getContext().getELFSection(".sbss", ELF::SHT_NOBITS, + ELF::SHF_WRITE | ELF::SHF_ALLOC); + this->TM = &static_cast<const MipsTargetMachine &>(TM); } // A address must be loaded from a small section if its size is less than the @@ -88,7 +85,8 @@ IsGlobalInSmallSection(const GlobalValue *GV, const TargetMachine &TM, bool MipsTargetObjectFile:: IsGlobalInSmallSectionImpl(const GlobalValue *GV, const TargetMachine &TM) const { - const MipsSubtarget &Subtarget = TM.getSubtarget<MipsSubtarget>(); + const MipsSubtarget &Subtarget = + *static_cast<const MipsTargetMachine &>(TM).getSubtargetImpl(); // Return if small section is not available. if (!Subtarget.useSmallSection()) @@ -109,13 +107,13 @@ IsGlobalInSmallSectionImpl(const GlobalValue *GV, return false; Type *Ty = GV->getType()->getElementType(); - return IsInSmallSection( - TM.getSubtargetImpl()->getDataLayout()->getTypeAllocSize(Ty)); + return IsInSmallSection(TM.getDataLayout()->getTypeAllocSize(Ty)); } -const MCSection *MipsTargetObjectFile:: -SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, - Mangler &Mang, const TargetMachine &TM) const { +MCSection * +MipsTargetObjectFile::SelectSectionForGlobal(const GlobalValue *GV, + SectionKind Kind, Mangler &Mang, + const TargetMachine &TM) const { // TODO: Could also support "weak" symbols as well with ".gnu.linkonce.s.*" // sections? @@ -132,14 +130,16 @@ SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, /// Return true if this constant should be placed into small data section. bool MipsTargetObjectFile:: IsConstantInSmallSection(const Constant *CN, const TargetMachine &TM) const { - return (TM.getSubtarget<MipsSubtarget>().useSmallSection() && - LocalSData && - IsInSmallSection(TM.getSubtargetImpl()->getDataLayout() - ->getTypeAllocSize(CN->getType()))); + return (static_cast<const MipsTargetMachine &>(TM) + .getSubtargetImpl() + ->useSmallSection() && + LocalSData && IsInSmallSection(TM.getDataLayout()->getTypeAllocSize( + CN->getType()))); } -const MCSection *MipsTargetObjectFile:: -getSectionForConstant(SectionKind Kind, const Constant *C) const { +MCSection * +MipsTargetObjectFile::getSectionForConstant(SectionKind Kind, + const Constant *C) const { if (IsConstantInSmallSection(C, *TM)) return SmallDataSection; diff --git a/contrib/llvm/lib/Target/Mips/MipsTargetObjectFile.h b/contrib/llvm/lib/Target/Mips/MipsTargetObjectFile.h index 3a2b298..725f2ff 100644 --- a/contrib/llvm/lib/Target/Mips/MipsTargetObjectFile.h +++ b/contrib/llvm/lib/Target/Mips/MipsTargetObjectFile.h @@ -13,11 +13,11 @@ #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" namespace llvm { - +class MipsTargetMachine; class MipsTargetObjectFile : public TargetLoweringObjectFileELF { - const MCSection *SmallDataSection; - const MCSection *SmallBSSSection; - const TargetMachine *TM; + MCSection *SmallDataSection; + MCSection *SmallBSSSection; + const MipsTargetMachine *TM; public: void Initialize(MCContext &Ctx, const TargetMachine &TM) override; @@ -31,16 +31,16 @@ namespace llvm { bool IsGlobalInSmallSectionImpl(const GlobalValue *GV, const TargetMachine &TM) const; - const MCSection *SelectSectionForGlobal(const GlobalValue *GV, - SectionKind Kind, Mangler &Mang, - const TargetMachine &TM) const override; + MCSection *SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, + Mangler &Mang, + const TargetMachine &TM) const override; /// Return true if this constant should be placed into small data section. bool IsConstantInSmallSection(const Constant *CN, const TargetMachine &TM) const; - const MCSection *getSectionForConstant(SectionKind Kind, - const Constant *C) const override; + MCSection *getSectionForConstant(SectionKind Kind, + const Constant *C) const override; }; } // end namespace llvm diff --git a/contrib/llvm/lib/Target/Mips/MipsTargetStreamer.h b/contrib/llvm/lib/Target/Mips/MipsTargetStreamer.h index 6dcd15a..fed0600 100644 --- a/contrib/llvm/lib/Target/Mips/MipsTargetStreamer.h +++ b/contrib/llvm/lib/Target/Mips/MipsTargetStreamer.h @@ -11,6 +11,7 @@ #define LLVM_LIB_TARGET_MIPS_MIPSTARGETSTREAMER_H #include "MCTargetDesc/MipsABIFlagsSection.h" +#include "MCTargetDesc/MipsABIInfo.h" #include "llvm/MC/MCELFStreamer.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCStreamer.h" @@ -34,6 +35,7 @@ public: virtual void emitDirectiveSetMsa(); virtual void emitDirectiveSetNoMsa(); virtual void emitDirectiveSetAt(); + virtual void emitDirectiveSetAtWithArg(unsigned RegNo); virtual void emitDirectiveSetNoAt(); virtual void emitDirectiveEnd(StringRef Name); @@ -43,6 +45,7 @@ public: virtual void emitDirectiveNaNLegacy(); virtual void emitDirectiveOptionPic0(); virtual void emitDirectiveOptionPic2(); + virtual void emitDirectiveInsn(); virtual void emitFrame(unsigned StackReg, unsigned StackSize, unsigned ReturnReg); virtual void emitMask(unsigned CPUBitmask, int CPUTopSavedRegOff); @@ -57,14 +60,20 @@ public: virtual void emitDirectiveSetMips5(); virtual void emitDirectiveSetMips32(); virtual void emitDirectiveSetMips32R2(); + virtual void emitDirectiveSetMips32R3(); + virtual void emitDirectiveSetMips32R5(); virtual void emitDirectiveSetMips32R6(); virtual void emitDirectiveSetMips64(); virtual void emitDirectiveSetMips64R2(); + virtual void emitDirectiveSetMips64R3(); + virtual void emitDirectiveSetMips64R5(); virtual void emitDirectiveSetMips64R6(); virtual void emitDirectiveSetDsp(); virtual void emitDirectiveSetNoDsp(); virtual void emitDirectiveSetPop(); virtual void emitDirectiveSetPush(); + virtual void emitDirectiveSetSoftFloat(); + virtual void emitDirectiveSetHardFloat(); // PIC support virtual void emitDirectiveCpLoad(unsigned RegNo); @@ -86,21 +95,27 @@ public: } virtual void emitDirectiveModuleOddSPReg(bool Enabled, bool IsO32ABI); - virtual void emitDirectiveSetFp(MipsABIFlagsSection::FpABIKind Value){}; - virtual void emitMipsAbiFlags(){}; + virtual void emitDirectiveSetFp(MipsABIFlagsSection::FpABIKind Value); void forbidModuleDirective() { ModuleDirectiveAllowed = false; } + void reallowModuleDirective() { ModuleDirectiveAllowed = true; } bool isModuleDirectiveAllowed() { return ModuleDirectiveAllowed; } // This method enables template classes to set internal abi flags // structure values. template <class PredicateLibrary> void updateABIInfo(const PredicateLibrary &P) { + ABI = &P.getABI(); ABIFlagsSection.setAllFromPredicates(P); } MipsABIFlagsSection &getABIFlagsSection() { return ABIFlagsSection; } + const MipsABIInfo &getABI() const { + assert(ABI && "ABI hasn't been set!"); + return *ABI; + } protected: + const MipsABIInfo *ABI; MipsABIFlagsSection ABIFlagsSection; bool GPRInfoSet; @@ -138,6 +153,7 @@ public: void emitDirectiveSetMsa() override; void emitDirectiveSetNoMsa() override; void emitDirectiveSetAt() override; + void emitDirectiveSetAtWithArg(unsigned RegNo) override; void emitDirectiveSetNoAt() override; void emitDirectiveEnd(StringRef Name) override; @@ -147,6 +163,7 @@ public: void emitDirectiveNaNLegacy() override; void emitDirectiveOptionPic0() override; void emitDirectiveOptionPic2() override; + void emitDirectiveInsn() override; void emitFrame(unsigned StackReg, unsigned StackSize, unsigned ReturnReg) override; void emitMask(unsigned CPUBitmask, int CPUTopSavedRegOff) override; @@ -161,14 +178,20 @@ public: void emitDirectiveSetMips5() override; void emitDirectiveSetMips32() override; void emitDirectiveSetMips32R2() override; + void emitDirectiveSetMips32R3() override; + void emitDirectiveSetMips32R5() override; void emitDirectiveSetMips32R6() override; void emitDirectiveSetMips64() override; void emitDirectiveSetMips64R2() override; + void emitDirectiveSetMips64R3() override; + void emitDirectiveSetMips64R5() override; void emitDirectiveSetMips64R6() override; void emitDirectiveSetDsp() override; void emitDirectiveSetNoDsp() override; void emitDirectiveSetPop() override; void emitDirectiveSetPush() override; + void emitDirectiveSetSoftFloat() override; + void emitDirectiveSetHardFloat() override; // PIC support void emitDirectiveCpLoad(unsigned RegNo) override; @@ -180,7 +203,6 @@ public: bool Is32BitABI) override; void emitDirectiveModuleOddSPReg(bool Enabled, bool IsO32ABI) override; void emitDirectiveSetFp(MipsABIFlagsSection::FpABIKind Value) override; - void emitMipsAbiFlags() override; }; // This part is for ELF object output @@ -211,6 +233,7 @@ public: void emitDirectiveNaNLegacy() override; void emitDirectiveOptionPic0() override; void emitDirectiveOptionPic2() override; + void emitDirectiveInsn() override; void emitFrame(unsigned StackReg, unsigned StackSize, unsigned ReturnReg) override; void emitMask(unsigned CPUBitmask, int CPUTopSavedRegOff) override; @@ -223,12 +246,7 @@ public: // ABI Flags void emitDirectiveModuleOddSPReg(bool Enabled, bool IsO32ABI) override; - void emitMipsAbiFlags() override; - -protected: - bool isO32() const { return STI.getFeatureBits() & Mips::FeatureO32; } - bool isN32() const { return STI.getFeatureBits() & Mips::FeatureN32; } - bool isN64() const { return STI.getFeatureBits() & Mips::FeatureN64; } + void emitMipsAbiFlags(); }; } #endif diff --git a/contrib/llvm/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp b/contrib/llvm/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp index 3615c14..6a65943 100644 --- a/contrib/llvm/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp +++ b/contrib/llvm/lib/Target/Mips/TargetInfo/MipsTargetInfo.cpp @@ -23,9 +23,9 @@ extern "C" void LLVMInitializeMipsTargetInfo() { /*HasJIT=*/true> Y(TheMipselTarget, "mipsel", "Mipsel"); RegisterTarget<Triple::mips64, - /*HasJIT=*/false> A(TheMips64Target, "mips64", "Mips64 [experimental]"); + /*HasJIT=*/true> A(TheMips64Target, "mips64", "Mips64 [experimental]"); RegisterTarget<Triple::mips64el, - /*HasJIT=*/false> B(TheMips64elTarget, + /*HasJIT=*/true> B(TheMips64elTarget, "mips64el", "Mips64el [experimental]"); } |