diff options
Diffstat (limited to 'lib/Target/Mips')
102 files changed, 8171 insertions, 4053 deletions
diff --git a/lib/Target/Mips/AsmParser/Makefile b/lib/Target/Mips/AsmParser/Makefile deleted file mode 100644 index 679acee9fe724..0000000000000 --- a/lib/Target/Mips/AsmParser/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Target/Mips/AsmParser/Makefile ------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMMipsAsmParser - -# Hack: we need to include 'main' mips target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index d4e061f00d3ac..b51d0200b0b1a 100644 --- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -13,7 +13,6 @@ #include "MipsRegisterInfo.h" #include "MipsTargetObjectFile.h" #include "MipsTargetStreamer.h" -#include "llvm/ADT/APInt.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/MC/MCContext.h" @@ -22,11 +21,13 @@ #include "llvm/MC/MCInstBuilder.h" #include "llvm/MC/MCParser/MCAsmLexer.h" #include "llvm/MC/MCParser/MCParsedAsmOperand.h" +#include "llvm/MC/MCParser/MCTargetAsmParser.h" +#include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCTargetAsmParser.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/ELF.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/TargetRegistry.h" @@ -157,7 +158,6 @@ class MipsAsmParser : public MCTargetAsmParser { OperandMatchResultTy parseImm(OperandVector &Operands); OperandMatchResultTy parseJumpTarget(OperandVector &Operands); OperandMatchResultTy parseInvNum(OperandVector &Operands); - OperandMatchResultTy parseLSAImm(OperandVector &Operands); OperandMatchResultTy parseRegisterPair(OperandVector &Operands); OperandMatchResultTy parseMovePRegPair(OperandVector &Operands); OperandMatchResultTy parseRegisterList(OperandVector &Operands); @@ -173,74 +173,77 @@ class MipsAsmParser : public MCTargetAsmParser { }; // Expands assembly pseudo instructions. - MacroExpanderResultTy - tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions); + MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, + MCStreamer &Out, + const MCSubtargetInfo *STI); - bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions); + bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI); bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg, bool Is32BitImm, bool IsAddress, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions); + MCStreamer &Out, const MCSubtargetInfo *STI); bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions); + MCStreamer &Out, const MCSubtargetInfo *STI); bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions); + MCStreamer &Out, const MCSubtargetInfo *STI); bool expandLoadAddress(unsigned DstReg, unsigned BaseReg, const MCOperand &Offset, bool Is32BitAddress, - SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions); + SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI); - bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions); + bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI); - void expandMemInst(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions, bool isLoad, - bool isImmOpnd); + void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI, bool IsLoad, bool IsImmOpnd); - bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions); + void expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI, bool IsImmOpnd); - bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions); + void expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI, bool IsImmOpnd); - bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions); + bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI); - bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions); + bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI); - bool expandDiv(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions, const bool IsMips64, - const bool Signed); + bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI); - bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions); + bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI); - bool expandUlw(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions); + bool expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI, const bool IsMips64, + const bool Signed); - bool expandRotation(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions); - bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions); - bool expandDRotation(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions); - bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions); + bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc, + MCStreamer &Out, const MCSubtargetInfo *STI); - void createNop(bool hasShortDelaySlot, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions); + bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI); - void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg, - bool Is64Bit, SmallVectorImpl<MCInst> &Instructions); + bool expandUlw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI); - void createCpRestoreMemOp(bool IsLoad, int StackOffset, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions); + bool expandRotation(MCInst &Inst, SMLoc IDLoc, + MCStreamer &Out, const MCSubtargetInfo *STI); + bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI); + bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI); + bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI); + + bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI); bool reportParseError(Twine ErrorMsg); bool reportParseError(SMLoc Loc, Twine ErrorMsg); @@ -263,6 +266,7 @@ class MipsAsmParser : public MCTargetAsmParser { bool parseDirectiveSet(); bool parseDirectiveOption(); bool parseInsnDirective(); + bool parseSSectionDirective(StringRef Section, unsigned Type); bool parseSetAtDirective(); bool parseSetNoAtDirective(); @@ -295,16 +299,12 @@ class MipsAsmParser : public MCTargetAsmParser { bool parseInternalDirectiveReallowModule(); - MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol); - bool eatComma(StringRef ErrorStr); int matchCPURegisterName(StringRef Symbol); int matchHWRegsRegisterName(StringRef Symbol); - int matchRegisterByNumber(unsigned RegNum, unsigned RegClass); - int matchFPURegisterName(StringRef Name); int matchFCCRegisterName(StringRef Name); @@ -317,15 +317,13 @@ class MipsAsmParser : public MCTargetAsmParser { unsigned getReg(int RC, int RegNo); - unsigned getGPR(int RegNo); - /// 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); + bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI); // Helper function that checks if the value of a vector index is within the // boundaries of accepted values for each RegisterKind @@ -395,6 +393,8 @@ class MipsAsmParser : public MCTargetAsmParser { public: enum MipsMatchResultTy { Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY, + Match_RequiresDifferentOperands, + Match_RequiresNoZeroRegister, #define GET_OPERAND_DIAGNOSTIC_TYPES #include "MipsGenAsmMatcher.inc" #undef GET_OPERAND_DIAGNOSTIC_TYPES @@ -427,13 +427,12 @@ public: CurrentFn = nullptr; - IsPicEnabled = - (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_); + IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent(); IsCpRestoreSet = false; CpRestoreOffset = -1; - Triple TheTriple(sti.getTargetTriple()); + const Triple &TheTriple = sti.getTargetTriple(); if ((TheTriple.getArch() == Triple::mips) || (TheTriple.getArch() == Triple::mips64)) IsLittleEndian = false; @@ -584,7 +583,6 @@ private: enum KindTy { k_Immediate, /// An immediate (possibly involving symbol references) k_Memory, /// Base + Offset Memory Address - k_PhysRegister, /// A physical register from the Mips namespace k_RegisterIndex, /// A register index in one or more RegKind. k_Token, /// A simple token k_RegList, /// A physical register list @@ -604,10 +602,6 @@ private: unsigned Length; }; - struct PhysRegOp { - unsigned Num; /// Register Number - }; - struct RegIdxOp { unsigned Index; /// Index into the register class RegKind Kind; /// Bitfield of the kinds it could possibly be @@ -629,7 +623,6 @@ private: union { struct Token Tok; - struct PhysRegOp PhysReg; struct RegIdxOp RegIdx; struct ImmOp Imm; struct MemOp Mem; @@ -938,6 +931,34 @@ public: Inst.addOperand(MCOperand::createImm(Imm)); } + template <unsigned Bits> + void addSImmOperands(MCInst &Inst, unsigned N) const { + if (isImm() && !isConstantImm()) { + addExpr(Inst, getImm()); + return; + } + addConstantSImmOperands<Bits, 0, 0>(Inst, N); + } + + template <unsigned Bits> + void addUImmOperands(MCInst &Inst, unsigned N) const { + if (isImm() && !isConstantImm()) { + addExpr(Inst, getImm()); + return; + } + addConstantUImmOperands<Bits, 0, 0>(Inst, N); + } + + template <unsigned Bits, int Offset = 0, int AdjustOffset = 0> + void addConstantSImmOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + int64_t Imm = getConstantImm() - Offset; + Imm = SignExtend64<Bits>(Imm); + Imm += Offset; + Imm += AdjustOffset; + Inst.addOperand(MCOperand::createImm(Imm)); + } + void addImmOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); const MCExpr *Expr = getImm(); @@ -973,9 +994,19 @@ public: void addRegPairOperands(MCInst &Inst, unsigned N) const { assert(N == 2 && "Invalid number of operands!"); + assert((RegIdx.Kind & RegKind_GPR) && "Invalid access!"); unsigned RegNo = getRegPair(); - Inst.addOperand(MCOperand::createReg(RegNo++)); - Inst.addOperand(MCOperand::createReg(RegNo)); + AsmParser.warnIfRegIndexIsAT(RegNo, StartLoc); + Inst.addOperand(MCOperand::createReg( + RegIdx.RegInfo->getRegClass( + AsmParser.getABI().AreGprs64bit() + ? Mips::GPR64RegClassID + : Mips::GPR32RegClassID).getRegister(RegNo++))); + Inst.addOperand(MCOperand::createReg( + RegIdx.RegInfo->getRegClass( + AsmParser.getABI().AreGprs64bit() + ? Mips::GPR64RegClassID + : Mips::GPR32RegClassID).getRegister(RegNo))); } void addMovePRegPairOperands(MCInst &Inst, unsigned N) const { @@ -985,12 +1016,9 @@ public: } bool isReg() const override { - // As a special case until we sort out the definition of div/divu, pretend - // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly. - if (isGPRAsmReg() && RegIdx.Index == 0) - return true; - - return Kind == k_PhysRegister; + // As a special case until we sort out the definition of div/divu, accept + // $0/$zero here so that MCK_ZERO works correctly. + return isGPRAsmReg() && RegIdx.Index == 0; } bool isRegIdx() const { return Kind == k_RegisterIndex; } bool isImm() const override { return Kind == k_Immediate; } @@ -1003,8 +1031,23 @@ public: template <unsigned Bits, int Offset = 0> bool isConstantUImm() const { return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset); } - template <unsigned Bits> bool isConstantSImm() const { - return isConstantImm() && isInt<Bits>(getConstantImm()); + template <unsigned Bits> bool isSImm() const { + return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm(); + } + template <unsigned Bits> bool isUImm() const { + return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm(); + } + template <unsigned Bits> bool isAnyImm() const { + return isConstantImm() ? (isInt<Bits>(getConstantImm()) || + isUInt<Bits>(getConstantImm())) + : isImm(); + } + template <unsigned Bits, int Offset = 0> bool isConstantSImm() const { + return isConstantImm() && isInt<Bits>(getConstantImm() - Offset); + } + template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const { + return isConstantImm() && getConstantImm() >= Bottom && + getConstantImm() <= Top; } bool isToken() const override { // Note: It's not possible to pretend that other operand kinds are tokens. @@ -1015,13 +1058,22 @@ public: bool isConstantMemOff() const { return isMem() && isa<MCConstantExpr>(getMemOff()); } - template <unsigned Bits> bool isMemWithSimmOffset() const { - return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) - && getMemBase()->isGPRAsmReg(); - } - template <unsigned Bits> bool isMemWithSimmOffsetGPR() const { - return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) && - getMemBase()->isGPRAsmReg(); + // Allow relocation operators. + // FIXME: This predicate and others need to look through binary expressions + // and determine whether a Value is a constant or not. + template <unsigned Bits, unsigned ShiftAmount = 0> + bool isMemWithSimmOffset() const { + if (!isMem()) + return false; + if (!getMemBase()->isGPRAsmReg()) + return false; + if (isa<MCTargetExpr>(getMemOff()) || + (isConstantMemOff() && + isShiftedInt<Bits, ShiftAmount>(getConstantMemOff()))) + return true; + MCValue Res; + bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr); + return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant()); } bool isMemWithGRPMM16Base() const { return isMem() && getMemBase()->isMM16AsmReg(); @@ -1035,11 +1087,21 @@ public: && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx() && (getMemBase()->getGPR32Reg() == Mips::SP); } + template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const { + return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) + && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx() + && (getMemBase()->getGPR32Reg() == Mips::GP); + } template <unsigned Bits, unsigned ShiftLeftAmount> bool isScaledUImm() const { return isConstantImm() && isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm()); } + template <unsigned Bits, unsigned ShiftLeftAmount> + bool isScaledSImm() const { + return isConstantImm() && + isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm()); + } bool isRegList16() const { if (!isRegList()) return false; @@ -1086,7 +1148,15 @@ public: (R0 == Mips::A0 && R1 == Mips::S6) || (R0 == Mips::A0 && R1 == Mips::A1) || (R0 == Mips::A0 && R1 == Mips::A2) || - (R0 == Mips::A0 && R1 == Mips::A3)) + (R0 == Mips::A0 && R1 == Mips::A3) || + (R0 == Mips::A1_64 && R1 == Mips::A2_64) || + (R0 == Mips::A1_64 && R1 == Mips::A3_64) || + (R0 == Mips::A2_64 && R1 == Mips::A3_64) || + (R0 == Mips::A0_64 && R1 == Mips::S5_64) || + (R0 == Mips::A0_64 && R1 == Mips::S6_64) || + (R0 == Mips::A0_64 && R1 == Mips::A1_64) || + (R0 == Mips::A0_64 && R1 == Mips::A2_64) || + (R0 == Mips::A0_64 && R1 == Mips::A3_64)) return true; return false; @@ -1096,17 +1166,19 @@ public: assert(Kind == k_Token && "Invalid access!"); return StringRef(Tok.Data, Tok.Length); } - bool isRegPair() const { return Kind == k_RegPair; } + bool isRegPair() const { + return Kind == k_RegPair && RegIdx.Index <= 30; + } unsigned getReg() const override { - // As a special case until we sort out the definition of div/divu, pretend - // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly. + // As a special case until we sort out the definition of div/divu, accept + // $0/$zero here so that MCK_ZERO works correctly. if (Kind == k_RegisterIndex && RegIdx.Index == 0 && RegIdx.Kind & RegKind_GPR) return getGPR32Reg(); // FIXME: GPR64 too - assert(Kind == k_PhysRegister && "Invalid access!"); - return PhysReg.Num; + llvm_unreachable("Invalid access!"); + return 0; } const MCExpr *getImm() const { @@ -1250,10 +1322,13 @@ public: return Op; } - static std::unique_ptr<MipsOperand> - CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) { + static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP, + SMLoc S, SMLoc E, + MipsAsmParser &Parser) { auto Op = make_unique<MipsOperand>(k_RegPair, Parser); - Op->RegIdx.Index = RegNo; + Op->RegIdx.Index = MOP.RegIdx.Index; + Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo; + Op->RegIdx.Kind = MOP.RegIdx.Kind; Op->StartLoc = S; Op->EndLoc = E; return Op; @@ -1331,7 +1406,6 @@ public: break; case k_RegList: delete RegList.List; - case k_PhysRegister: case k_RegisterIndex: case k_Token: case k_RegPair: @@ -1353,9 +1427,6 @@ public: OS << *Mem.Off; OS << ">"; break; - case k_PhysRegister: - OS << "PhysReg<" << PhysReg.Num << ">"; - break; case k_RegisterIndex: OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">"; break; @@ -1434,83 +1505,10 @@ static unsigned countMCSymbolRefExpr(const MCExpr *Expr) { return 0; } -namespace { -void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions) { - MCInst tmpInst; - tmpInst.setOpcode(Opcode); - tmpInst.addOperand(MCOperand::createReg(Reg0)); - tmpInst.addOperand(Op1); - tmpInst.setLoc(IDLoc); - Instructions.push_back(tmpInst); -} - -void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions) { - emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions); -} - -void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions) { - emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions); -} - -void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions) { - MCInst tmpInst; - tmpInst.setOpcode(Opcode); - tmpInst.addOperand(MCOperand::createImm(Imm1)); - tmpInst.addOperand(MCOperand::createImm(Imm2)); - tmpInst.setLoc(IDLoc); - Instructions.push_back(tmpInst); -} - -void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions) { - MCInst tmpInst; - tmpInst.setOpcode(Opcode); - tmpInst.addOperand(MCOperand::createReg(Reg0)); - tmpInst.setLoc(IDLoc); - Instructions.push_back(tmpInst); -} - -void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2, - SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { - MCInst tmpInst; - tmpInst.setOpcode(Opcode); - tmpInst.addOperand(MCOperand::createReg(Reg0)); - tmpInst.addOperand(MCOperand::createReg(Reg1)); - tmpInst.addOperand(Op2); - tmpInst.setLoc(IDLoc); - Instructions.push_back(tmpInst); -} - -void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2, - SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { - emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc, - Instructions); -} - -void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm, - SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { - emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc, - Instructions); -} - -void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount, - SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { - if (ShiftAmount >= 32) { - emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc, - Instructions); - return; - } - - emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions); -} -} // end anonymous namespace. - bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions) { + MCStreamer &Out, + const MCSubtargetInfo *STI) { + MipsTargetStreamer &TOut = getTargetStreamer(); const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode()); bool ExpandedJalSym = false; @@ -1560,6 +1558,10 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, case Mips::BLTZAL_MM: case Mips::BC1F_MM: case Mips::BC1T_MM: + case Mips::BC1EQZC_MMR6: + case Mips::BC1NEZC_MMR6: + case Mips::BC2EQZC_MMR6: + case Mips::BC2NEZC_MMR6: assert(MCID.getNumOperands() == 2 && "unexpected number of operands"); Offset = Inst.getOperand(1); if (!Offset.isImm()) @@ -1650,9 +1652,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode"); // FIXME: This is checking the expression can be handled by the later stages - // of the assembler. We ought to leave it to those later stages but - // we can't do that until we stop evaluateRelocExpr() rewriting the - // expressions into non-equivalent forms. + // of the assembler. We ought to leave it to those later stages. const MCSymbol *JalSym = getSingleMCSymbol(JalExpr); // FIXME: Add support for label+offset operands (currently causes an error). @@ -1666,33 +1666,38 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, // addiu $25, $25, 0 // R_(MICRO)MIPS_LO16 label // jalr $25 - const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got"); - const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo"); - - emitRRX(Mips::LW, Mips::T9, Mips::GP, - MCOperand::createExpr(Got16RelocExpr), IDLoc, Instructions); - emitRRX(Mips::ADDiu, Mips::T9, Mips::T9, - MCOperand::createExpr(Lo16RelocExpr), IDLoc, Instructions); + const MCExpr *Got16RelocExpr = + MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext()); + const MCExpr *Lo16RelocExpr = + MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext()); + + TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP, + MCOperand::createExpr(Got16RelocExpr), IDLoc, STI); + TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9, + MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI); } else if (isABI_N32() || isABI_N64()) { // If it's a local symbol and the N32/N64 ABIs are being used, // we expand to: // lw/ld $25, 0($gp) // R_(MICRO)MIPS_GOT_DISP label // jalr $25 - const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp"); + const MCExpr *GotDispRelocExpr = + MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext()); - emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP, - MCOperand::createExpr(GotDispRelocExpr), IDLoc, Instructions); + TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, + Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc, + STI); } } else { // If it's an external/weak symbol, we expand to: // lw/ld $25, 0($gp) // R_(MICRO)MIPS_CALL16 label // jalr $25 - const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16"); + const MCExpr *Call16RelocExpr = + MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext()); - emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP, - MCOperand::createExpr(Call16RelocExpr), IDLoc, Instructions); + TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP, + MCOperand::createExpr(Call16RelocExpr), IDLoc, STI); } MCInst JalrInst; @@ -1723,7 +1728,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, int MemOffset = Op.getImm(); if (MemOffset < -32768 || MemOffset > 32767) { // Offset can't exceed 16bit value. - expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true); + expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true); return false; } } else if (Op.isExpr()) { @@ -1733,11 +1738,11 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, static_cast<const MCSymbolRefExpr *>(Expr); if (SR->getKind() == MCSymbolRefExpr::VK_None) { // Expand symbol. - expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false); + expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false); return false; } } else if (!isEvaluated(Expr)) { - expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false); + expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false); return false; } } @@ -1763,8 +1768,8 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, (BaseReg.getReg() == Mips::GP || BaseReg.getReg() == Mips::GP_64)) { - emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset, - IDLoc, Instructions); + TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset, + IDLoc, STI); return false; } } @@ -1780,14 +1785,6 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, switch (Inst.getOpcode()) { default: break; - case Mips::ADDIUS5_MM: - Opnd = Inst.getOperand(2); - if (!Opnd.isImm()) - return Error(IDLoc, "expected immediate operand kind"); - Imm = Opnd.getImm(); - if (Imm < -8 || Imm > 7) - return Error(IDLoc, "immediate operand value out of range"); - break; case Mips::ADDIUSP_MM: Opnd = Inst.getOperand(0); if (!Opnd.isImm()) @@ -1823,16 +1820,6 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, ((Imm % 4 == 0) && Imm < 28 && Imm > 0))) return Error(IDLoc, "immediate operand value out of range"); break; - case Mips::ADDIUR1SP_MM: - Opnd = Inst.getOperand(1); - if (!Opnd.isImm()) - return Error(IDLoc, "expected immediate operand kind"); - Imm = Opnd.getImm(); - if (OffsetToAlignment(Imm, 4LL)) - return Error(IDLoc, "misaligned immediate operand value"); - if (Imm < 0 || Imm > 255) - return Error(IDLoc, "immediate operand value out of range"); - break; case Mips::ANDI16_MM: Opnd = Inst.getOperand(2); if (!Opnd.isImm()) @@ -1851,12 +1838,6 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, if (Imm < -1 || Imm > 14) return Error(IDLoc, "immediate operand value out of range"); break; - case Mips::TEQ_MM: - case Mips::TGE_MM: - case Mips::TGEU_MM: - case Mips::TLT_MM: - case Mips::TLTU_MM: - case Mips::TNE_MM: case Mips::SB16_MM: case Mips::SB16_MMR6: Opnd = Inst.getOperand(2); @@ -1897,11 +1878,16 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, } } + bool FillDelaySlot = + MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder(); + if (FillDelaySlot) + TOut.emitDirectiveSetNoReorder(); + MacroExpanderResultTy ExpandResult = - tryExpandInstruction(Inst, IDLoc, Instructions); + tryExpandInstruction(Inst, IDLoc, Out, STI); switch (ExpandResult) { case MER_NotAMacro: - Instructions.push_back(Inst); + Out.EmitInstruction(Inst, *STI); break; case MER_Success: break; @@ -1909,10 +1895,17 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, return true; } + // We know we emitted an instruction on the MER_NotAMacro or MER_Success path. + // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS. + if (inMicroMipsMode()) + TOut.setUsesMicroMips(); + // 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); + if (FillDelaySlot) { + TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI); + TOut.emitDirectiveSetReorder(); + } if ((Inst.getOpcode() == Mips::JalOneReg || Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) && @@ -1922,16 +1915,11 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, // If .set reorder has been used, we've already emitted a NOP. // If .set noreorder has been used, we need to emit a NOP at this point. if (!AssemblerOptions.back()->isReorder()) - createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions); + TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, + STI); // Load the $gp from the stack. - SmallVector<MCInst, 3> LoadInsts; - createCpRestoreMemOp(true /*IsLoad*/, CpRestoreOffset /*StackOffset*/, - IDLoc, LoadInsts); - - for (const MCInst &Inst : LoadInsts) - Instructions.push_back(Inst); - + TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI); } else Warning(IDLoc, "no .cprestore used in PIC mode"); } @@ -1940,17 +1928,15 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, } MipsAsmParser::MacroExpanderResultTy -MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions) { +MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI) { switch (Inst.getOpcode()) { default: return MER_NotAMacro; case Mips::LoadImm32: - return expandLoadImm(Inst, true, IDLoc, Instructions) ? MER_Fail - : MER_Success; + return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success; case Mips::LoadImm64: - return expandLoadImm(Inst, false, IDLoc, Instructions) ? MER_Fail - : MER_Success; + return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success; case Mips::LoadAddrImm32: case Mips::LoadAddrImm64: assert(Inst.getOperand(0).isReg() && "expected register operand kind"); @@ -1960,7 +1946,7 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister, Inst.getOperand(1), Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc, - Instructions) + Out, STI) ? MER_Fail : MER_Success; case Mips::LoadAddrReg32: @@ -1973,24 +1959,23 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, return expandLoadAddress(Inst.getOperand(0).getReg(), Inst.getOperand(1).getReg(), Inst.getOperand(2), Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc, - Instructions) + Out, STI) ? MER_Fail : MER_Success; case Mips::B_MM_Pseudo: case Mips::B_MMR6_Pseudo: - return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions) ? MER_Fail - : MER_Success; + return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail + : MER_Success; case Mips::SWM_MM: case Mips::LWM_MM: - return expandLoadStoreMultiple(Inst, IDLoc, Instructions) ? MER_Fail - : MER_Success; + return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail + : MER_Success; case Mips::JalOneReg: case Mips::JalTwoReg: - return expandJalWithRegs(Inst, IDLoc, Instructions) ? MER_Fail - : MER_Success; + return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; case Mips::BneImm: case Mips::BeqImm: - return expandBranchImm(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success; + return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; case Mips::BLT: case Mips::BLE: case Mips::BGE: @@ -2023,29 +2008,36 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, case Mips::BLEULImmMacro: case Mips::BGEULImmMacro: case Mips::BGTULImmMacro: - return expandCondBranches(Inst, IDLoc, Instructions) ? MER_Fail - : MER_Success; + return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; case Mips::SDivMacro: - return expandDiv(Inst, IDLoc, Instructions, false, true) ? MER_Fail - : MER_Success; + return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail + : MER_Success; case Mips::DSDivMacro: - return expandDiv(Inst, IDLoc, Instructions, true, true) ? MER_Fail - : MER_Success; + return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail + : MER_Success; case Mips::UDivMacro: - return expandDiv(Inst, IDLoc, Instructions, false, false) ? MER_Fail - : MER_Success; + return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail + : MER_Success; case Mips::DUDivMacro: - return expandDiv(Inst, IDLoc, Instructions, true, false) ? MER_Fail - : MER_Success; + return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail + : MER_Success; + case Mips::PseudoTRUNC_W_S: + return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail + : MER_Success; + case Mips::PseudoTRUNC_W_D32: + return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail + : MER_Success; + case Mips::PseudoTRUNC_W_D: + return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail + : MER_Success; case Mips::Ulh: - return expandUlh(Inst, true, IDLoc, Instructions) ? MER_Fail : MER_Success; + return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success; case Mips::Ulhu: - return expandUlh(Inst, false, IDLoc, Instructions) ? MER_Fail : MER_Success; + return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success; case Mips::Ulw: - return expandUlw(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success; + return expandUlw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; case Mips::NORImm: - return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail - : MER_Success; + return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; case Mips::ADDi: case Mips::ADDiu: case Mips::SLTi: @@ -2055,8 +2047,8 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, int64_t ImmValue = Inst.getOperand(2).getImm(); if (isInt<16>(ImmValue)) return MER_NotAMacro; - return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail - : MER_Success; + return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail + : MER_Success; } return MER_NotAMacro; case Mips::ANDi: @@ -2067,31 +2059,32 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, int64_t ImmValue = Inst.getOperand(2).getImm(); if (isUInt<16>(ImmValue)) return MER_NotAMacro; - return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail - : MER_Success; + return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail + : MER_Success; } return MER_NotAMacro; case Mips::ROL: case Mips::ROR: - return expandRotation(Inst, IDLoc, Instructions) ? MER_Fail - : MER_Success; + return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; case Mips::ROLImm: case Mips::RORImm: - return expandRotationImm(Inst, IDLoc, Instructions) ? MER_Fail - : MER_Success; + return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; case Mips::DROL: case Mips::DROR: - return expandDRotation(Inst, IDLoc, Instructions) ? MER_Fail - : MER_Success; + return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; case Mips::DROLImm: case Mips::DRORImm: - return expandDRotationImm(Inst, IDLoc, Instructions) ? MER_Fail - : MER_Success; + return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; + case Mips::ABSMacro: + return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; } } bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions) { + MCStreamer &Out, + const MCSubtargetInfo *STI) { + MipsTargetStreamer &TOut = getTargetStreamer(); + // Create a JALR instruction which is going to replace the pseudo-JAL. MCInst JalrInst; JalrInst.setLoc(IDLoc); @@ -2121,14 +2114,14 @@ bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, const MCOperand SecondRegOp = Inst.getOperand(1); JalrInst.addOperand(SecondRegOp); } - Instructions.push_back(JalrInst); + Out.EmitInstruction(JalrInst, *STI); // If .set reorder is active and branch instruction has a delay slot, // emit a NOP after it. const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode()); - if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) { - createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions); - } + if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) + TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, + STI); return false; } @@ -2150,11 +2143,12 @@ template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) { /// @param IsAddress True if the immediate represents an address. False if it /// is an integer. /// @param IDLoc Location of the immediate in the source file. -/// @param Instructions The instructions emitted by this expansion. bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg, bool Is32BitImm, - bool IsAddress, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions) { + bool IsAddress, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI) { + MipsTargetStreamer &TOut = getTargetStreamer(); + if (!Is32BitImm && !isGP64bit()) { Error(IDLoc, "instruction requires a 64-bit architecture"); return true; @@ -2180,7 +2174,8 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg, UseSrcReg = true; unsigned TmpReg = DstReg; - if (UseSrcReg && (DstReg == SrcReg)) { + if (UseSrcReg && + getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) { // At this point we need AT to perform the expansions and we exit if it is // not available. unsigned ATReg = getATReg(IDLoc); @@ -2197,11 +2192,11 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg, // traditional assembler behaviour. N32 would normally use addiu for both // integers and addresses. if (IsAddress && !Is32BitImm) { - emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions); + TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI); return false; } - emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions); + TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI); return false; } @@ -2213,9 +2208,9 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg, return true; } - emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions); + TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI); if (UseSrcReg) - emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions); + TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI); return false; } @@ -2229,29 +2224,29 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg, // Traditional behaviour seems to special case this particular value. It's // not clear why other masks are handled differently. if (ImmValue == 0xffffffff) { - emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions); - emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions); + TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI); + TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI); if (UseSrcReg) - emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions); + TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI); return false; } // Expand to an ORi instead of a LUi to avoid sign-extending into the // upper 32 bits. - emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions); - emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions); + TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI); + TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI); if (Bits15To0) - emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions); + TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI); if (UseSrcReg) - emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions); + TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI); return false; } - emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions); + TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI); if (Bits15To0) - emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions); + TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI); if (UseSrcReg) - emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions); + TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI); return false; } @@ -2267,11 +2262,11 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned LastSet = findLastSet((uint64_t)ImmValue); unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet)); uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff; - emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions); - emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions); + TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI); + TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI); if (UseSrcReg) - emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions); + TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI); return false; } @@ -2284,7 +2279,7 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg, // Load bits 32-63 of ImmValue into bits 0-31 of the temporary register. if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false, - IDLoc, Instructions)) + IDLoc, Out, STI)) return false; // Shift and accumulate into the register. If a 16-bit chunk is zero, then @@ -2294,9 +2289,8 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg, uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff; if (ImmChunk != 0) { - emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, - Instructions); - emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions); + TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI); + TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI); ShiftCarriedForwards = 0; } @@ -2306,24 +2300,23 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg, // Finish any remaining shifts left by trailing zeros. if (ShiftCarriedForwards) - emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, - Instructions); + TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI); if (UseSrcReg) - emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions); + TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI); return false; } bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions) { + MCStreamer &Out, const MCSubtargetInfo *STI) { 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, false, IDLoc, Instructions)) + Is32BitImm, false, IDLoc, Out, STI)) return true; return false; @@ -2332,7 +2325,8 @@ bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc, bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg, const MCOperand &Offset, bool Is32BitAddress, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions) { + MCStreamer &Out, + const MCSubtargetInfo *STI) { // la can't produce a usable address when addresses are 64-bit. if (Is32BitAddress && ABI.ArePtrs64bit()) { // FIXME: Demote this to a warning and continue as if we had 'dla' instead. @@ -2344,31 +2338,109 @@ bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg, } // dla requires 64-bit addresses. - if (!Is32BitAddress && !ABI.ArePtrs64bit()) { + if (!Is32BitAddress && !hasMips3()) { Error(IDLoc, "instruction requires a 64-bit architecture"); return true; } if (!Offset.isImm()) return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg, - Is32BitAddress, IDLoc, Instructions); + Is32BitAddress, IDLoc, Out, STI); + + if (!ABI.ArePtrs64bit()) { + // Continue as if we had 'la' whether we had 'la' or 'dla'. + Is32BitAddress = true; + } return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true, - IDLoc, Instructions); + IDLoc, Out, STI); } -bool MipsAsmParser::loadAndAddSymbolAddress( - const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym, - SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { +bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr, + unsigned DstReg, unsigned SrcReg, + bool Is32BitSym, SMLoc IDLoc, + MCStreamer &Out, + const MCSubtargetInfo *STI) { + MipsTargetStreamer &TOut = getTargetStreamer(); + bool UseSrcReg = SrcReg != Mips::NoRegister; warnIfNoMacro(IDLoc); - const MCExpr *Symbol = cast<MCExpr>(SymExpr); - const MipsMCExpr *HiExpr = MipsMCExpr::create( - MCSymbolRefExpr::VK_Mips_ABS_HI, Symbol, getContext()); - const MipsMCExpr *LoExpr = MipsMCExpr::create( - MCSymbolRefExpr::VK_Mips_ABS_LO, Symbol, getContext()); + if (inPicMode() && ABI.IsO32()) { + MCValue Res; + if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) { + Error(IDLoc, "expected relocatable expression"); + return true; + } + if (Res.getSymB() != nullptr) { + Error(IDLoc, "expected relocatable expression with only one symbol"); + return true; + } + + // The case where the result register is $25 is somewhat special. If the + // symbol in the final relocation is external and not modified with a + // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16. + if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg && + Res.getConstant() == 0 && !Res.getSymA()->getSymbol().isInSection() && + !Res.getSymA()->getSymbol().isTemporary()) { + const MCExpr *CallExpr = + MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext()); + TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(), + MCOperand::createExpr(CallExpr), IDLoc, STI); + return false; + } - bool UseSrcReg = SrcReg != Mips::NoRegister; + // The remaining cases are: + // External GOT: lw $tmp, %got(symbol+offset)($gp) + // >addiu $tmp, $tmp, %lo(offset) + // >addiu $rd, $tmp, $rs + // Local GOT: lw $tmp, %got(symbol+offset)($gp) + // addiu $tmp, $tmp, %lo(symbol+offset)($gp) + // >addiu $rd, $tmp, $rs + // The addiu's marked with a '>' may be omitted if they are redundant. If + // this happens then the last instruction must use $rd as the result + // register. + const MipsMCExpr *GotExpr = + MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext()); + const MCExpr *LoExpr = nullptr; + if (Res.getSymA()->getSymbol().isInSection() || + Res.getSymA()->getSymbol().isTemporary()) + LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext()); + else if (Res.getConstant() != 0) { + // External symbols fully resolve the symbol with just the %got(symbol) + // but we must still account for any offset to the symbol for expressions + // like symbol+8. + LoExpr = MCConstantExpr::create(Res.getConstant(), getContext()); + } + + unsigned TmpReg = DstReg; + if (UseSrcReg && + getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, + SrcReg)) { + // If $rs is the same as $rd, we need to use AT. + // If it is not available we exit. + unsigned ATReg = getATReg(IDLoc); + if (!ATReg) + return true; + TmpReg = ATReg; + } + + TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(), + MCOperand::createExpr(GotExpr), IDLoc, STI); + + if (LoExpr) + TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), + IDLoc, STI); + + if (UseSrcReg) + TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI); + + return false; + } + + const MipsMCExpr *HiExpr = + MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext()); + const MipsMCExpr *LoExpr = + MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext()); // This is the 64-bit symbol address expansion. if (ABI.ArePtrs64bit() && isGP64bit()) { @@ -2378,12 +2450,14 @@ bool MipsAsmParser::loadAndAddSymbolAddress( if (!ATReg) return true; - const MipsMCExpr *HighestExpr = MipsMCExpr::create( - MCSymbolRefExpr::VK_Mips_HIGHEST, Symbol, getContext()); - const MipsMCExpr *HigherExpr = MipsMCExpr::create( - MCSymbolRefExpr::VK_Mips_HIGHER, Symbol, getContext()); + const MipsMCExpr *HighestExpr = + MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext()); + const MipsMCExpr *HigherExpr = + MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext()); - if (UseSrcReg && (DstReg == SrcReg)) { + if (UseSrcReg && + getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, + SrcReg)) { // If $rs is the same as $rd: // (d)la $rd, sym($rd) => lui $at, %highest(sym) // daddiu $at, $at, %higher(sym) @@ -2392,17 +2466,17 @@ bool MipsAsmParser::loadAndAddSymbolAddress( // dsll $at, $at, 16 // daddiu $at, $at, %lo(sym) // daddu $rd, $at, $rd - emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc, - Instructions); - emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr), - IDLoc, Instructions); - emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions); - emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc, - Instructions); - emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions); - emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc, - Instructions); - emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions); + TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc, + STI); + TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, + MCOperand::createExpr(HigherExpr), IDLoc, STI); + TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI); + TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), + IDLoc, STI); + TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI); + TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), + IDLoc, STI); + TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI); return false; } @@ -2415,18 +2489,17 @@ bool MipsAsmParser::loadAndAddSymbolAddress( // dsll32 $rd, $rd, 0 // daddu $rd, $rd, $at // (daddu $rd, $rd, $rs) - emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc, - Instructions); - emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, - Instructions); - emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr), - IDLoc, Instructions); - emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc, - Instructions); - emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions); - emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions); + TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc, + STI); + TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI); + TOut.emitRRX(Mips::DADDiu, DstReg, DstReg, + MCOperand::createExpr(HigherExpr), IDLoc, STI); + TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), + IDLoc, STI); + TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI); + TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI); if (UseSrcReg) - emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions); + TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI); return false; } @@ -2441,7 +2514,8 @@ bool MipsAsmParser::loadAndAddSymbolAddress( // ori $rd, $rd, %lo(sym) // (addu $rd, $rd, $rs) unsigned TmpReg = DstReg; - if (UseSrcReg && (DstReg == SrcReg)) { + if (UseSrcReg && + getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) { // If $rs is the same as $rd, we need to use AT. // If it is not available we exit. unsigned ATReg = getATReg(IDLoc); @@ -2450,20 +2524,24 @@ bool MipsAsmParser::loadAndAddSymbolAddress( TmpReg = ATReg; } - emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions); - emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc, - Instructions); + TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI); + TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), + IDLoc, STI); if (UseSrcReg) - emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions); + TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI); else - assert(DstReg == TmpReg); + assert( + getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg)); return false; } -bool MipsAsmParser::expandUncondBranchMMPseudo( - MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) { +bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, + MCStreamer &Out, + const MCSubtargetInfo *STI) { + MipsTargetStreamer &TOut = getTargetStreamer(); + assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 && "unexpected number of operands"); @@ -2493,19 +2571,20 @@ bool MipsAsmParser::expandUncondBranchMMPseudo( Inst.addOperand(MCOperand::createImm(Offset.getImm())); } } - Instructions.push_back(Inst); + Out.EmitInstruction(Inst, *STI); // If .set reorder is active and branch instruction has a delay slot, // emit a NOP after it. const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode()); if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) - createNop(true, IDLoc, Instructions); + TOut.emitEmptyDelaySlot(true, IDLoc, STI); return false; } -bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions) { +bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI) { + MipsTargetStreamer &TOut = getTargetStreamer(); const MCOperand &DstRegOp = Inst.getOperand(0); assert(DstRegOp.isReg() && "expected register operand kind"); @@ -2513,7 +2592,8 @@ bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, assert(ImmOp.isImm() && "expected immediate operand kind"); const MCOperand &MemOffsetOp = Inst.getOperand(2); - assert(MemOffsetOp.isImm() && "expected immediate operand kind"); + assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) && + "expected immediate or expression operand"); unsigned OpCode = 0; switch(Inst.getOpcode()) { @@ -2530,8 +2610,8 @@ bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, int64_t ImmValue = ImmOp.getImm(); if (ImmValue == 0) - emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc, - Instructions); + TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc, + STI); else { warnIfNoMacro(IDLoc); @@ -2540,94 +2620,112 @@ bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, return true; if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true, - IDLoc, Instructions)) + IDLoc, Out, STI)) return true; - emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, Instructions); + TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI); } return false; } -void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions, - bool isLoad, bool isImmOpnd) { - unsigned ImmOffset, HiOffset, LoOffset; - const MCExpr *ExprOffset; - unsigned TmpRegNum; - // 1st operand is either the source or destination register. - assert(Inst.getOperand(0).isReg() && "expected register operand kind"); - unsigned RegOpNum = Inst.getOperand(0).getReg(); - // 2nd operand is the base register. - assert(Inst.getOperand(1).isReg() && "expected register operand kind"); - unsigned BaseRegNum = Inst.getOperand(1).getReg(); - // 3rd operand is either an immediate or expression. - if (isImmOpnd) { - assert(Inst.getOperand(2).isImm() && "expected immediate operand kind"); - ImmOffset = Inst.getOperand(2).getImm(); - LoOffset = ImmOffset & 0x0000ffff; - HiOffset = (ImmOffset & 0xffff0000) >> 16; - // If msb of LoOffset is 1(negative number) we must increment HiOffset. - if (LoOffset & 0x8000) - HiOffset++; - } else - ExprOffset = Inst.getOperand(2).getExpr(); - // These are some of the types of expansions we perform here: - // 1) lw $8, sym => lui $8, %hi(sym) - // lw $8, %lo(sym)($8) - // 2) lw $8, offset($9) => lui $8, %hi(offset) - // add $8, $8, $9 - // lw $8, %lo(offset)($9) - // 3) lw $8, offset($8) => lui $at, %hi(offset) - // add $at, $at, $8 - // lw $8, %lo(offset)($at) - // 4) sw $8, sym => lui $at, %hi(sym) - // sw $8, %lo(sym)($at) - // 5) sw $8, offset($8) => lui $at, %hi(offset) - // add $at, $at, $8 - // sw $8, %lo(offset)($at) - // 6) ldc1 $f0, sym => lui $at, %hi(sym) - // ldc1 $f0, %lo(sym)($at) - // - // For load instructions we can use the destination register as a temporary - // if base and dst are different (examples 1 and 2) and if the base register - // is general purpose otherwise we must use $at (example 6) and error if it's - // not available. For stores we must use $at (examples 4 and 5) because we - // must not clobber the source register setting up the offset. +void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI, bool IsLoad, + bool IsImmOpnd) { + if (IsLoad) { + expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd); + return; + } + expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd); +} + +void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI, bool IsImmOpnd) { + MipsTargetStreamer &TOut = getTargetStreamer(); + + unsigned DstReg = Inst.getOperand(0).getReg(); + unsigned BaseReg = Inst.getOperand(1).getReg(); + const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode()); - int16_t RegClassOp0 = Desc.OpInfo[0].RegClass; - unsigned RegClassIDOp0 = - getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID(); - bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) || - (RegClassIDOp0 == Mips::GPR64RegClassID); - if (isLoad && IsGPR && (BaseRegNum != RegOpNum)) - TmpRegNum = RegOpNum; - else { + int16_t DstRegClass = Desc.OpInfo[0].RegClass; + unsigned DstRegClassID = + getContext().getRegisterInfo()->getRegClass(DstRegClass).getID(); + bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) || + (DstRegClassID == Mips::GPR64RegClassID); + + if (IsImmOpnd) { + // Try to use DstReg as the temporary. + if (IsGPR && (BaseReg != DstReg)) { + TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg, + Inst.getOperand(2).getImm(), DstReg, IDLoc, + STI); + return; + } + // At this point we need AT to perform the expansions and we exit if it is // not available. - TmpRegNum = getATReg(IDLoc); - if (!TmpRegNum) + unsigned ATReg = getATReg(IDLoc); + if (!ATReg) return; + + TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg, + Inst.getOperand(2).getImm(), ATReg, IDLoc, STI); + return; } - emitRX(Mips::LUi, TmpRegNum, - isImmOpnd ? MCOperand::createImm(HiOffset) - : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi")), - IDLoc, Instructions); - // Add temp register to base. - if (BaseRegNum != Mips::ZERO) - emitRRR(Mips::ADDu, TmpRegNum, TmpRegNum, BaseRegNum, IDLoc, Instructions); - // And finally, create original instruction with low part - // of offset and new base. - emitRRX(Inst.getOpcode(), RegOpNum, TmpRegNum, - isImmOpnd - ? MCOperand::createImm(LoOffset) - : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo")), - IDLoc, Instructions); + const MCExpr *ExprOffset = Inst.getOperand(2).getExpr(); + MCOperand LoOperand = MCOperand::createExpr( + MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext())); + MCOperand HiOperand = MCOperand::createExpr( + MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext())); + + // Try to use DstReg as the temporary. + if (IsGPR && (BaseReg != DstReg)) { + TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand, + LoOperand, DstReg, IDLoc, STI); + return; + } + + // At this point we need AT to perform the expansions and we exit if it is + // not available. + unsigned ATReg = getATReg(IDLoc); + if (!ATReg) + return; + + TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand, + LoOperand, ATReg, IDLoc, STI); } -bool -MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions) { +void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI, + bool IsImmOpnd) { + MipsTargetStreamer &TOut = getTargetStreamer(); + + unsigned SrcReg = Inst.getOperand(0).getReg(); + unsigned BaseReg = Inst.getOperand(1).getReg(); + + if (IsImmOpnd) { + TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg, + Inst.getOperand(2).getImm(), + [&]() { return getATReg(IDLoc); }, IDLoc, STI); + return; + } + + unsigned ATReg = getATReg(IDLoc); + if (!ATReg) + return; + + const MCExpr *ExprOffset = Inst.getOperand(2).getExpr(); + MCOperand LoOperand = MCOperand::createExpr( + MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext())); + MCOperand HiOperand = MCOperand::createExpr( + MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext())); + TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand, + LoOperand, ATReg, IDLoc, STI); +} + +bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, + MCStreamer &Out, + const MCSubtargetInfo *STI) { unsigned OpNum = Inst.getNumOperands(); unsigned Opcode = Inst.getOpcode(); unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM; @@ -2650,12 +2748,14 @@ MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, } Inst.setOpcode(NewOpcode); - Instructions.push_back(Inst); + Out.EmitInstruction(Inst, *STI); return false; } bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions) { + MCStreamer &Out, + const MCSubtargetInfo *STI) { + MipsTargetStreamer &TOut = getTargetStreamer(); bool EmittedNoMacroWarning = false; unsigned PseudoOpcode = Inst.getOpcode(); unsigned SrcReg = Inst.getOperand(0).getReg(); @@ -2730,7 +2830,7 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc, } if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(), - false, IDLoc, Instructions)) + false, IDLoc, Out, STI)) return true; } @@ -2790,37 +2890,37 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc, // with GAS' behaviour. However, they may not generate the most efficient // code in some circumstances. if (PseudoOpcode == Mips::BLT) { - emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc, - Instructions); + TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), + IDLoc, STI); return false; } if (PseudoOpcode == Mips::BLE) { - emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc, - Instructions); + TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), + IDLoc, STI); Warning(IDLoc, "branch is always taken"); return false; } if (PseudoOpcode == Mips::BGE) { - emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc, - Instructions); + TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), + IDLoc, STI); Warning(IDLoc, "branch is always taken"); return false; } if (PseudoOpcode == Mips::BGT) { - emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc, - Instructions); + TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), + IDLoc, STI); return false; } if (PseudoOpcode == Mips::BGTU) { - emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO, - MCOperand::createExpr(OffsetExpr), IDLoc, Instructions); + TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO, + MCOperand::createExpr(OffsetExpr), IDLoc, STI); return false; } if (AcceptsEquality) { // If both registers are $0 and the pseudo-branch accepts equality, it // will always be taken, so we emit an unconditional branch. - emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO, - MCOperand::createExpr(OffsetExpr), IDLoc, Instructions); + TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO, + MCOperand::createExpr(OffsetExpr), IDLoc, STI); Warning(IDLoc, "branch is always taken"); return false; } @@ -2844,8 +2944,8 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc, // the pseudo-branch will always be taken, so we emit an unconditional // branch. // This only applies to unsigned pseudo-branches. - emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO, - MCOperand::createExpr(OffsetExpr), IDLoc, Instructions); + TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO, + MCOperand::createExpr(OffsetExpr), IDLoc, STI); Warning(IDLoc, "branch is always taken"); return false; } @@ -2862,17 +2962,17 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc, // // Because only BLEU and BGEU branch on equality, we can use the // AcceptsEquality variable to decide when to emit the BEQZ. - emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE, - IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO, - MCOperand::createExpr(OffsetExpr), IDLoc, Instructions); + TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE, + IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO, + MCOperand::createExpr(OffsetExpr), IDLoc, STI); return false; } // If we have a signed pseudo-branch and one of the registers is $0, // we can use an appropriate compare-to-zero branch. We select which one // to use in the switch statement above. - emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode, - IsSrcRegZero ? TrgReg : SrcReg, MCOperand::createExpr(OffsetExpr), - IDLoc, Instructions); + TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode, + IsSrcRegZero ? TrgReg : SrcReg, + MCOperand::createExpr(OffsetExpr), IDLoc, STI); return false; } @@ -2900,32 +3000,33 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc, // // The same applies to the unsigned variants, except that SLTu is used // instead of SLT. - emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum, - ReverseOrderSLT ? TrgReg : SrcReg, ReverseOrderSLT ? SrcReg : TrgReg, - IDLoc, Instructions); - - emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL) - : (AcceptsEquality ? Mips::BEQ : Mips::BNE), - ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc, - Instructions); + TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum, + ReverseOrderSLT ? TrgReg : SrcReg, + ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI); + + TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL) + : (AcceptsEquality ? Mips::BEQ : Mips::BNE), + ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc, + STI); return false; } -bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions, - const bool IsMips64, const bool Signed) { - if (hasMips32r6()) { - Error(IDLoc, "instruction not supported on mips32r6 or mips64r6"); - return false; - } +bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI, const bool IsMips64, + const bool Signed) { + MipsTargetStreamer &TOut = getTargetStreamer(); warnIfNoMacro(IDLoc); - const MCOperand &RsRegOp = Inst.getOperand(0); + const MCOperand &RdRegOp = Inst.getOperand(0); + assert(RdRegOp.isReg() && "expected register operand kind"); + unsigned RdReg = RdRegOp.getReg(); + + const MCOperand &RsRegOp = Inst.getOperand(1); assert(RsRegOp.isReg() && "expected register operand kind"); unsigned RsReg = RsRegOp.getReg(); - const MCOperand &RtRegOp = Inst.getOperand(1); + const MCOperand &RtRegOp = Inst.getOperand(2); assert(RtRegOp.isReg() && "expected register operand kind"); unsigned RtReg = RtRegOp.getReg(); unsigned DivOp; @@ -2947,15 +3048,15 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, if (IsMips64) { if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) { if (UseTraps) { - emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions); + TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI); return false; } - emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions); + TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI); return false; } } else { - emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions); + TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI); return false; } } @@ -2964,11 +3065,11 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, Warning(IDLoc, "division by zero"); if (Signed) { if (UseTraps) { - emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions); + TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI); return false; } - emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions); + TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI); return false; } } @@ -2980,22 +3081,21 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, if (UseTraps) { BranchTarget = IsMips64 ? 12 : 8; - emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions); + TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI); } else { BranchTarget = IsMips64 ? 20 : 16; BranchTargetNoTraps = 8; // Branch to the li instruction. - emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc, - Instructions); + TOut.emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc, STI); } - emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions); + TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI); if (!UseTraps) - emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions); + TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI); if (!Signed) { - emitR(Mips::MFLO, RsReg, IDLoc, Instructions); + TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI); return false; } @@ -3003,32 +3103,73 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, if (!ATReg) return true; - emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions); + TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI); if (IsMips64) { // Branch to the mflo instruction. - emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions); - emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions); - emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions); + TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI); + TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI); + TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI); } else { // Branch to the mflo instruction. - emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions); - emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions); + TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI); + TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI); } if (UseTraps) - emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions); + TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI); else { // Branch to the mflo instruction. - emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions); - emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions); - emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions); + TOut.emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, STI); + TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI); + TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI); + } + TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI); + return false; +} + +bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, + SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI) { + MipsTargetStreamer &TOut = getTargetStreamer(); + + assert(Inst.getNumOperands() == 3 && "Invalid operand count"); + assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() && + Inst.getOperand(2).isReg() && "Invalid instruction operand."); + + unsigned FirstReg = Inst.getOperand(0).getReg(); + unsigned SecondReg = Inst.getOperand(1).getReg(); + unsigned ThirdReg = Inst.getOperand(2).getReg(); + + if (hasMips1() && !hasMips2()) { + unsigned ATReg = getATReg(IDLoc); + if (!ATReg) + return true; + TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI); + TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI); + TOut.emitNop(IDLoc, STI); + TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI); + TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI); + TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI); + TOut.emitNop(IDLoc, STI); + TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32) + : Mips::CVT_W_S, + FirstReg, SecondReg, IDLoc, STI); + TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI); + TOut.emitNop(IDLoc, STI); + return false; } - emitR(Mips::MFLO, RsReg, IDLoc, Instructions); + + TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32) + : Mips::TRUNC_W_S, + FirstReg, SecondReg, IDLoc, STI); + return false; } bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions) { + MCStreamer &Out, const MCSubtargetInfo *STI) { + MipsTargetStreamer &TOut = getTargetStreamer(); + if (hasMips32r6() || hasMips64r6()) { Error(IDLoc, "instruction not supported on mips32r6 or mips64r6"); return false; @@ -3063,7 +3204,7 @@ bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, LoadedOffsetInAT = true; if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(), - true, IDLoc, Instructions)) + true, IDLoc, Out, STI)) return true; // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate() @@ -3073,7 +3214,7 @@ bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, // NOTE: If there is no source register specified in the ULHU, the parser // will interpret it as $0. if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64) - createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions); + TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI); } unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg; @@ -3091,21 +3232,23 @@ bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg; - emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg, - FirstLbuOffset, IDLoc, Instructions); + TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg, + FirstLbuOffset, IDLoc, STI); - emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc, - Instructions); + TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc, + STI); - emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, Instructions); + TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI); - emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, Instructions); + TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI); return false; } -bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions) { +bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI) { + MipsTargetStreamer &TOut = getTargetStreamer(); + if (hasMips32r6() || hasMips64r6()) { Error(IDLoc, "instruction not supported on mips32r6 or mips64r6"); return false; @@ -3137,7 +3280,7 @@ bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc, warnIfNoMacro(IDLoc); if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(), - true, IDLoc, Instructions)) + true, IDLoc, Out, STI)) return true; // NOTE: We do this (D)ADDu here instead of doing it in loadImmediate() @@ -3147,7 +3290,7 @@ bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc, // NOTE: If there is no source register specified in the ULW, the parser // will interpret it as $0. if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64) - createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions); + TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI); } unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg; @@ -3160,17 +3303,19 @@ bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc, RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3); } - emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc, - Instructions); + TOut.emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc, + STI); - emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset, IDLoc, - Instructions); + TOut.emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset, + IDLoc, STI); return false; } bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions) { + MCStreamer &Out, + const MCSubtargetInfo *STI) { + MipsTargetStreamer &TOut = getTargetStreamer(); assert (Inst.getNumOperands() == 3 && "Invalid operand count"); assert (Inst.getOperand(0).isReg() && @@ -3195,7 +3340,7 @@ bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, DstReg = ATReg; } - if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Instructions)) { + if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) { switch (FinalOpcode) { default: llvm_unreachable("unimplemented expansion"); @@ -3226,17 +3371,17 @@ bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, } if (FinalDstReg == Mips::NoRegister) - emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, Instructions); + TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI); else - emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, - Instructions); + TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI); return false; } return true; } -bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions) { +bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI) { + MipsTargetStreamer &TOut = getTargetStreamer(); unsigned ATReg = Mips::NoRegister; unsigned DReg = Inst.getOperand(0).getReg(); unsigned SReg = Inst.getOperand(1).getReg(); @@ -3255,13 +3400,13 @@ bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, } if (Inst.getOpcode() == Mips::ROL) { - emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions); - emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions); + TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI); + TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI); return false; } if (Inst.getOpcode() == Mips::ROR) { - emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions); + TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI); return false; } @@ -3287,10 +3432,10 @@ bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, if (!ATReg) return true; - emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions); - emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions); - emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions); - emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions); + TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI); + TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI); + TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI); + TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI); return false; } @@ -3299,8 +3444,9 @@ bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, } bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions) { - + MCStreamer &Out, + const MCSubtargetInfo *STI) { + MipsTargetStreamer &TOut = getTargetStreamer(); unsigned ATReg = Mips::NoRegister; unsigned DReg = Inst.getOperand(0).getReg(); unsigned SReg = Inst.getOperand(1).getReg(); @@ -3316,12 +3462,12 @@ bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc, uint64_t ShiftValue = ImmValue; if (ImmValue != 0) ShiftValue = MaxShift - ImmValue; - emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions); + TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI); return false; } if (Inst.getOpcode() == Mips::RORImm) { - emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), Instructions); + TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI); return false; } @@ -3331,7 +3477,7 @@ bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc, if (hasMips32()) { if (ImmValue == 0) { - emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), Instructions); + TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI); return false; } @@ -3352,9 +3498,9 @@ bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc, if (!ATReg) return true; - emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), Instructions); - emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), Instructions); - emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions); + TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI); + TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI); + TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI); return false; } @@ -3362,9 +3508,9 @@ bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc, return true; } -bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions) { - +bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI) { + MipsTargetStreamer &TOut = getTargetStreamer(); unsigned ATReg = Mips::NoRegister; unsigned DReg = Inst.getOperand(0).getReg(); unsigned SReg = Inst.getOperand(1).getReg(); @@ -3383,13 +3529,13 @@ bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, } if (Inst.getOpcode() == Mips::DROL) { - emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions); - emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions); + TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI); + TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI); return false; } if (Inst.getOpcode() == Mips::DROR) { - emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions); + TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI); return false; } @@ -3415,10 +3561,10 @@ bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, if (!ATReg) return true; - emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions); - emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions); - emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions); - emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions); + TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI); + TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI); + TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI); + TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI); return false; } @@ -3427,8 +3573,9 @@ bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, } bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions) { - + MCStreamer &Out, + const MCSubtargetInfo *STI) { + MipsTargetStreamer &TOut = getTargetStreamer(); unsigned ATReg = Mips::NoRegister; unsigned DReg = Inst.getOperand(0).getReg(); unsigned SReg = Inst.getOperand(1).getReg(); @@ -3462,7 +3609,7 @@ bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc, if (Inst.getOpcode() == Mips::DROLImm) ShiftValue = (32 - ImmValue % 32) % 32; - emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions); + TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI); return false; } @@ -3470,7 +3617,7 @@ bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc, if (hasMips64()) { if (ImmValue == 0) { - emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), Instructions); + TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI); return false; } @@ -3511,9 +3658,10 @@ bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc, if (!ATReg) return true; - emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), Instructions); - emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32, Inst.getLoc(), Instructions); - emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions); + TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI); + TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32, + Inst.getLoc(), STI); + TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI); return false; } @@ -3521,49 +3669,76 @@ bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc, return true; } -void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions) { - if (hasShortDelaySlot) - emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, Instructions); - else - emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, Instructions); -} +bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI) { + MipsTargetStreamer &TOut = getTargetStreamer(); + unsigned FirstRegOp = Inst.getOperand(0).getReg(); + unsigned SecondRegOp = Inst.getOperand(1).getReg(); -void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg, - unsigned TrgReg, bool Is64Bit, - SmallVectorImpl<MCInst> &Instructions) { - emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(), - Instructions); -} - -void MipsAsmParser::createCpRestoreMemOp( - bool IsLoad, int StackOffset, SMLoc IDLoc, - SmallVectorImpl<MCInst> &Instructions) { - // If the offset can not fit into 16 bits, we need to expand. - if (!isInt<16>(StackOffset)) { - MCInst MemInst; - MemInst.setOpcode(IsLoad ? Mips::LW : Mips::SW); - MemInst.addOperand(MCOperand::createReg(Mips::GP)); - MemInst.addOperand(MCOperand::createReg(Mips::SP)); - MemInst.addOperand(MCOperand::createImm(StackOffset)); - expandMemInst(MemInst, IDLoc, Instructions, IsLoad, true /*HasImmOpnd*/); - return; - } + TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI); + if (FirstRegOp != SecondRegOp) + TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI); + else + TOut.emitEmptyDelaySlot(false, IDLoc, STI); + TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI); - emitRRI(IsLoad ? Mips::LW : Mips::SW, Mips::GP, Mips::SP, StackOffset, IDLoc, - Instructions); + return false; } unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) { + switch (Inst.getOpcode()) { // As described by the Mips32r2 spec, the registers Rd and Rs for // jalr.hb must be different. - unsigned Opcode = Inst.getOpcode(); - - if (Opcode == Mips::JALR_HB && - (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())) - return Match_RequiresDifferentSrcAndDst; - - return Match_Success; + // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction + // and registers Rd and Base for microMIPS lwp instruction + case Mips::JALR_HB: + case Mips::JALRC_HB_MMR6: + case Mips::JALRC_MMR6: + if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()) + return Match_RequiresDifferentSrcAndDst; + return Match_Success; + case Mips::LWP_MM: + case Mips::LWP_MMR6: + if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg()) + return Match_RequiresDifferentSrcAndDst; + return Match_Success; + // As described the MIPSR6 spec, the compact branches that compare registers + // must: + // a) Not use the zero register. + // b) Not use the same register twice. + // c) rs < rt for bnec, beqc. + // NB: For this case, the encoding will swap the operands as their + // ordering doesn't matter. GAS performs this transformation too. + // Hence, that constraint does not have to be enforced. + // + // The compact branches that branch iff the signed addition of two registers + // would overflow must have rs >= rt. That can be handled like beqc/bnec with + // operand swapping. They do not have restriction of using the zero register. + case Mips::BLEZC: + case Mips::BGEZC: + case Mips::BGTZC: + case Mips::BLTZC: + case Mips::BEQZC: + case Mips::BNEZC: + if (Inst.getOperand(0).getReg() == Mips::ZERO) + return Match_RequiresNoZeroRegister; + return Match_Success; + case Mips::BGEC: + case Mips::BLTC: + case Mips::BGEUC: + case Mips::BLTUC: + case Mips::BEQC: + case Mips::BNEC: + if (Inst.getOperand(0).getReg() == Mips::ZERO) + return Match_RequiresNoZeroRegister; + if (Inst.getOperand(1).getReg() == Mips::ZERO) + return Match_RequiresNoZeroRegister; + if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()) + return Match_RequiresDifferentOperands; + return Match_Success; + default: + return Match_Success; + } } static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands, @@ -3584,16 +3759,13 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, bool MatchingInlineAsm) { MCInst Inst; - SmallVector<MCInst, 8> Instructions; unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm); switch (MatchResult) { case Match_Success: { - if (processInstruction(Inst, IDLoc, Instructions)) + if (processInstruction(Inst, IDLoc, Out, STI)) return true; - for (unsigned i = 0; i < Instructions.size(); i++) - Out.EmitInstruction(Instructions[i], getSTI()); return false; } case Match_MissingFeature: @@ -3616,6 +3788,10 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, return Error(IDLoc, "invalid instruction"); case Match_RequiresDifferentSrcAndDst: return Error(IDLoc, "source and destination must be different"); + case Match_RequiresDifferentOperands: + return Error(IDLoc, "registers must be different"); + case Match_RequiresNoZeroRegister: + return Error(IDLoc, "invalid operand ($zero) for instruction"); case Match_Immz: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'"); case Match_UImm1_0: @@ -3633,9 +3809,15 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, case Match_UImm4_0: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected 4-bit unsigned immediate"); + case Match_SImm4_0: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected 4-bit signed immediate"); case Match_UImm5_0: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected 5-bit unsigned immediate"); + case Match_SImm5_0: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected 5-bit signed immediate"); case Match_UImm5_1: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected immediate in range 1 .. 32"); @@ -3653,21 +3835,81 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, case Match_UImm5_Lsl2: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected both 7-bit unsigned immediate and multiple of 4"); + case Match_UImmRange2_64: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected immediate in range 2 .. 64"); case Match_UImm6_0: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected 6-bit unsigned immediate"); - case Match_SImm6: + case Match_UImm6_Lsl2: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected both 8-bit unsigned immediate and multiple of 4"); + case Match_SImm6_0: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected 6-bit signed immediate"); case Match_UImm7_0: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected 7-bit unsigned immediate"); + case Match_UImm7_N1: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected immediate in range -1 .. 126"); + case Match_SImm7_Lsl2: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected both 9-bit signed immediate and multiple of 4"); case Match_UImm8_0: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected 8-bit unsigned immediate"); case Match_UImm10_0: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected 10-bit unsigned immediate"); + case Match_SImm10_0: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected 10-bit signed immediate"); + case Match_SImm11_0: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected 11-bit signed immediate"); + case Match_UImm16: + case Match_UImm16_Relaxed: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected 16-bit unsigned immediate"); + case Match_SImm16: + case Match_SImm16_Relaxed: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected 16-bit signed immediate"); + case Match_UImm20_0: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected 20-bit unsigned immediate"); + case Match_UImm26_0: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected 26-bit unsigned immediate"); + case Match_SImm32: + case Match_SImm32_Relaxed: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected 32-bit signed immediate"); + case Match_MemSImm9: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected memory with 9-bit signed offset"); + case Match_MemSImm10: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected memory with 10-bit signed offset"); + case Match_MemSImm10Lsl1: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected memory with 11-bit signed offset and multiple of 2"); + case Match_MemSImm10Lsl2: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected memory with 12-bit signed offset and multiple of 4"); + case Match_MemSImm10Lsl3: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected memory with 13-bit signed offset and multiple of 8"); + case Match_MemSImm11: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected memory with 11-bit signed offset"); + case Match_MemSImm12: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected memory with 12-bit signed offset"); + case Match_MemSImm16: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected memory with 16-bit signed offset"); } llvm_unreachable("Implement any new match types added!"); @@ -3871,19 +4113,6 @@ unsigned MipsAsmParser::getReg(int RC, int RegNo) { return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo); } -unsigned MipsAsmParser::getGPR(int RegNo) { - return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID, - RegNo); -} - -int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) { - if (RegNum > - getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1) - return -1; - - return getReg(RegClass, RegNum); -} - bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { MCAsmParser &Parser = getParser(); DEBUG(dbgs() << "parseOperand\n"); @@ -3960,63 +4189,41 @@ bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr) { - const MCExpr *Res; - // Check the type of the expression. - if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) { - // It's a constant, evaluate reloc value. - int16_t Val; - switch (getVariantKind(RelocStr)) { - case MCSymbolRefExpr::VK_Mips_ABS_LO: - // Get the 1st 16-bits. - Val = MCE->getValue() & 0xffff; - break; - case MCSymbolRefExpr::VK_Mips_ABS_HI: - // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low - // 16 bits being negative. - Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff; - break; - case MCSymbolRefExpr::VK_Mips_HIGHER: - // Get the 3rd 16-bits. - Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff; - break; - case MCSymbolRefExpr::VK_Mips_HIGHEST: - // Get the 4th 16-bits. - Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff; - break; - default: - report_fatal_error("unsupported reloc value"); - } - return MCConstantExpr::create(Val, getContext()); - } - - if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) { - // It's a symbol, create a symbolic expression from the symbol. - const MCSymbol *Symbol = &MSRE->getSymbol(); - MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr); - Res = MCSymbolRefExpr::create(Symbol, VK, getContext()); - return Res; - } - - if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) { - MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr); - - // Try to create target expression. - if (MipsMCExpr::isSupportedBinaryExpr(VK, BE)) - 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()); - return Res; - } - - if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) { - const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr); - Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext()); - return Res; - } - // Just return the original expression. - return Expr; + if (RelocStr == "hi(%neg(%gp_rel") + return MipsMCExpr::createGpOff(MipsMCExpr::MEK_HI, Expr, getContext()); + else if (RelocStr == "lo(%neg(%gp_rel") + return MipsMCExpr::createGpOff(MipsMCExpr::MEK_LO, Expr, getContext()); + + MipsMCExpr::MipsExprKind Kind = + StringSwitch<MipsMCExpr::MipsExprKind>(RelocStr) + .Case("call16", MipsMCExpr::MEK_GOT_CALL) + .Case("call_hi", MipsMCExpr::MEK_CALL_HI16) + .Case("call_lo", MipsMCExpr::MEK_CALL_LO16) + .Case("dtprel_hi", MipsMCExpr::MEK_DTPREL_HI) + .Case("dtprel_lo", MipsMCExpr::MEK_DTPREL_LO) + .Case("got", MipsMCExpr::MEK_GOT) + .Case("got_disp", MipsMCExpr::MEK_GOT_DISP) + .Case("got_hi", MipsMCExpr::MEK_GOT_HI16) + .Case("got_lo", MipsMCExpr::MEK_GOT_LO16) + .Case("got_ofst", MipsMCExpr::MEK_GOT_OFST) + .Case("got_page", MipsMCExpr::MEK_GOT_PAGE) + .Case("gottprel", MipsMCExpr::MEK_GOTTPREL) + .Case("gp_rel", MipsMCExpr::MEK_GPREL) + .Case("hi", MipsMCExpr::MEK_HI) + .Case("higher", MipsMCExpr::MEK_HIGHER) + .Case("highest", MipsMCExpr::MEK_HIGHEST) + .Case("lo", MipsMCExpr::MEK_LO) + .Case("neg", MipsMCExpr::MEK_NEG) + .Case("pcrel_hi", MipsMCExpr::MEK_PCREL_HI16) + .Case("pcrel_lo", MipsMCExpr::MEK_PCREL_LO16) + .Case("tlsgd", MipsMCExpr::MEK_TLSGD) + .Case("tlsldm", MipsMCExpr::MEK_TLSLDM) + .Case("tprel_hi", MipsMCExpr::MEK_TPREL_HI) + .Case("tprel_lo", MipsMCExpr::MEK_TPREL_LO) + .Default(MipsMCExpr::MEK_None); + + assert(Kind != MipsMCExpr::MEK_None); + return MipsMCExpr::create(Kind, Expr, getContext()); } bool MipsAsmParser::isEvaluated(const MCExpr *Expr) { @@ -4248,12 +4455,6 @@ bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) { llvm_unreachable("Should never ParseFail"); return false; } - } else if (Expr->getKind() == MCExpr::Constant) { - Parser.Lex(); - const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr); - Operands.push_back( - MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this)); - return true; } } return false; @@ -4439,46 +4640,6 @@ MipsAsmParser::parseInvNum(OperandVector &Operands) { } MipsAsmParser::OperandMatchResultTy -MipsAsmParser::parseLSAImm(OperandVector &Operands) { - MCAsmParser &Parser = getParser(); - switch (getLexer().getKind()) { - default: - return MatchOperand_NoMatch; - case AsmToken::LParen: - case AsmToken::Plus: - case AsmToken::Minus: - case AsmToken::Integer: - break; - } - - const MCExpr *Expr; - SMLoc S = Parser.getTok().getLoc(); - - if (getParser().parseExpression(Expr)) - return MatchOperand_ParseFail; - - int64_t Val; - if (!Expr->evaluateAsAbsolute(Val)) { - Error(S, "expected immediate value"); - return MatchOperand_ParseFail; - } - - // The LSA instruction allows a 2-bit unsigned immediate. For this reason - // and because the CPU always adds one to the immediate field, the allowed - // range becomes 1..4. We'll only check the range here and will deal - // with the addition/subtraction when actually decoding/encoding - // the instruction. - if (Val < 1 || Val > 4) { - Error(S, "immediate not in range (1..4)"); - return MatchOperand_ParseFail; - } - - Operands.push_back( - MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this)); - return MatchOperand_Success; -} - -MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseRegisterList(OperandVector &Operands) { MCAsmParser &Parser = getParser(); SmallVector<unsigned, 10> Regs; @@ -4573,10 +4734,10 @@ MipsAsmParser::parseRegisterPair(OperandVector &Operands) { return MatchOperand_ParseFail; SMLoc E = Parser.getTok().getLoc(); - MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back()); - unsigned Reg = Op.getGPR32Reg(); + MipsOperand Op = static_cast<MipsOperand &>(*Operands.back()); + Operands.pop_back(); - Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this)); + Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this)); return MatchOperand_Success; } @@ -4619,42 +4780,6 @@ MipsAsmParser::parseMovePRegPair(OperandVector &Operands) { return MatchOperand_Success; } -MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) { - - MCSymbolRefExpr::VariantKind VK = - StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol) - .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI) - .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO) - .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL) - .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL) - .Case("got", MCSymbolRefExpr::VK_Mips_GOT) - .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD) - .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM) - .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI) - .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO) - .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL) - .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI) - .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO) - .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP) - .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE) - .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST) - .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI) - .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO) - .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16) - .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16) - .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16) - .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16) - .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER) - .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST) - .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16) - .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16) - .Default(MCSymbolRefExpr::VK_None); - - assert(VK != MCSymbolRefExpr::VK_None); - - return VK; -} - /// Sometimes (i.e. load/stores) the operand may be followed immediately by /// either this. /// ::= '(', register, ')' @@ -4767,6 +4892,8 @@ bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, return false; } +// FIXME: Given that these have the same name, these should both be +// consistent on affecting the Parser. bool MipsAsmParser::reportParseError(Twine ErrorMsg) { MCAsmParser &Parser = getParser(); SMLoc Loc = getLexer().getLoc(); @@ -5174,7 +5301,7 @@ bool MipsAsmParser::parseSetArchDirective() { .Case("mips64r3", "mips64r3") .Case("mips64r5", "mips64r5") .Case("mips64r6", "mips64r6") - .Case("cnmips", "cnmips") + .Case("octeon", "cnmips") .Case("r4000", "mips3") // This is an implementation of Mips3. .Default(""); @@ -5200,6 +5327,7 @@ bool MipsAsmParser::parseSetFeature(uint64_t Feature) { getTargetStreamer().emitDirectiveSetDsp(); break; case Mips::FeatureMicroMips: + setFeatureBits(Mips::FeatureMicroMips, "micromips"); getTargetStreamer().emitDirectiveSetMicroMips(); break; case Mips::FeatureMips1: @@ -5356,12 +5484,9 @@ bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) { return false; } - // Store the $gp on the stack. - SmallVector<MCInst, 3> StoreInsts; - createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc, - StoreInsts); - - getTargetStreamer().emitDirectiveCpRestore(StoreInsts, CpRestoreOffset); + if (!getTargetStreamer().emitDirectiveCpRestore( + CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI)) + return true; Parser.Lex(); // Consume the EndOfStatement. return false; } @@ -5376,7 +5501,6 @@ bool MipsAsmParser::parseDirectiveCPSetup() { OperandMatchResultTy ResTy = parseAnyRegister(TmpReg); if (ResTy == MatchOperand_NoMatch) { reportParseError("expected register containing function address"); - Parser.eatToEndOfStatement(); return false; } @@ -5502,6 +5626,7 @@ bool MipsAsmParser::parseDirectiveSet() { } else if (Tok.getString() == "nomips16") { return parseSetNoMips16Directive(); } else if (Tok.getString() == "nomicromips") { + clearFeatureBits(Mips::FeatureMicroMips, "micromips"); getTargetStreamer().emitDirectiveSetNoMicroMips(); Parser.eatToEndOfStatement(); return false; @@ -5686,6 +5811,24 @@ bool MipsAsmParser::parseInsnDirective() { return false; } +/// parseSSectionDirective +/// ::= .sbss +/// ::= .sdata +bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) { + // 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; + } + + MCSection *ELFSection = getContext().getELFSection( + Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL); + getParser().getStreamer().SwitchSection(ELFSection); + + getParser().Lex(); // Eat EndOfStatement token. + return false; +} + /// parseDirectiveModule /// ::= .module oddspreg /// ::= .module nooddspreg @@ -5905,13 +6048,22 @@ bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI, } bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) { + // This returns false if this function recognizes the directive + // regardless of whether it is successfully handles or reports an + // error. Otherwise it returns true to give the generic parser a + // chance at recognizing it. + MCAsmParser &Parser = getParser(); StringRef IDVal = DirectiveID.getString(); - if (IDVal == ".cpload") - return parseDirectiveCpLoad(DirectiveID.getLoc()); - if (IDVal == ".cprestore") - return parseDirectiveCpRestore(DirectiveID.getLoc()); + if (IDVal == ".cpload") { + parseDirectiveCpLoad(DirectiveID.getLoc()); + return false; + } + if (IDVal == ".cprestore") { + parseDirectiveCpRestore(DirectiveID.getLoc()); + return false; + } if (IDVal == ".dword") { parseDataDirective(8, DirectiveID.getLoc()); return false; @@ -6068,7 +6220,8 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) { } if (IDVal == ".set") { - return parseDirectiveSet(); + parseDirectiveSet(); + return false; } if (IDVal == ".mask" || IDVal == ".fmask") { @@ -6147,8 +6300,15 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) { return false; } - if (IDVal == ".option") - return parseDirectiveOption(); + if (IDVal == ".hword") { + parseDataDirective(2, DirectiveID.getLoc()); + return false; + } + + if (IDVal == ".option") { + parseDirectiveOption(); + return false; + } if (IDVal == ".abicalls") { getTargetStreamer().emitDirectiveAbiCalls(); @@ -6161,20 +6321,34 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) { return false; } - if (IDVal == ".cpsetup") - return parseDirectiveCPSetup(); - - if (IDVal == ".cpreturn") - return parseDirectiveCPReturn(); - - if (IDVal == ".module") - return parseDirectiveModule(); - - if (IDVal == ".llvm_internal_mips_reallow_module_directive") - return parseInternalDirectiveReallowModule(); - - if (IDVal == ".insn") - return parseInsnDirective(); + if (IDVal == ".cpsetup") { + parseDirectiveCPSetup(); + return false; + } + if (IDVal == ".cpreturn") { + parseDirectiveCPReturn(); + return false; + } + if (IDVal == ".module") { + parseDirectiveModule(); + return false; + } + if (IDVal == ".llvm_internal_mips_reallow_module_directive") { + parseInternalDirectiveReallowModule(); + return false; + } + if (IDVal == ".insn") { + parseInsnDirective(); + return false; + } + if (IDVal == ".sbss") { + parseSSectionDirective(IDVal, ELF::SHT_NOBITS); + return false; + } + if (IDVal == ".sdata") { + parseSSectionDirective(IDVal, ELF::SHT_PROGBITS); + return false; + } return true; } diff --git a/lib/Target/Mips/CMakeLists.txt b/lib/Target/Mips/CMakeLists.txt index bde843afd3d28..3650cc9fe0728 100644 --- a/lib/Target/Mips/CMakeLists.txt +++ b/lib/Target/Mips/CMakeLists.txt @@ -27,6 +27,7 @@ add_llvm_target(MipsCodeGen MipsConstantIslandPass.cpp MipsDelaySlotFiller.cpp MipsFastISel.cpp + MipsHazardSchedule.cpp MipsInstrInfo.cpp MipsISelDAGToDAG.cpp MipsISelLowering.cpp diff --git a/lib/Target/Mips/Disassembler/Makefile b/lib/Target/Mips/Disassembler/Makefile deleted file mode 100644 index 7900373dd2b21..0000000000000 --- a/lib/Target/Mips/Disassembler/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/Mips/Disassembler/Makefile ---------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMMipsDisassembler - -# Hack: we need to include 'main' Mips target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp index 3c1a771f97e95..aebb4ef419d18 100644 --- a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -15,7 +15,7 @@ #include "MipsRegisterInfo.h" #include "MipsSubtarget.h" #include "llvm/MC/MCContext.h" -#include "llvm/MC/MCDisassembler.h" +#include "llvm/MC/MCDisassembler/MCDisassembler.h" #include "llvm/MC/MCFixedLenDisassembler.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCSubtargetInfo.h" @@ -39,14 +39,18 @@ public: IsMicroMips(STI.getFeatureBits()[Mips::FeatureMicroMips]), IsBigEndian(IsBigEndian) {} + bool hasMips2() const { return STI.getFeatureBits()[Mips::FeatureMips2]; } bool hasMips3() const { return STI.getFeatureBits()[Mips::FeatureMips3]; } bool hasMips32() const { return STI.getFeatureBits()[Mips::FeatureMips32]; } bool hasMips32r6() const { return STI.getFeatureBits()[Mips::FeatureMips32r6]; } + bool isFP64() const { return STI.getFeatureBits()[Mips::FeatureFP64Bit]; } bool isGP64() const { return STI.getFeatureBits()[Mips::FeatureGP64Bit]; } + bool isPTR64() const { return STI.getFeatureBits()[Mips::FeaturePTR64Bit]; } + bool hasCnMips() const { return STI.getFeatureBits()[Mips::FeatureCnMips]; } bool hasCOP3() const { @@ -193,6 +197,11 @@ static DecodeStatus DecodeBranchTarget(MCInst &Inst, uint64_t Address, const void *Decoder); +static DecodeStatus DecodeBranchTarget1SImm16(MCInst &Inst, + unsigned Offset, + uint64_t Address, + const void *Decoder); + static DecodeStatus DecodeJumpTarget(MCInst &Inst, unsigned Insn, uint64_t Address, @@ -203,6 +212,11 @@ static DecodeStatus DecodeBranchTarget21(MCInst &Inst, uint64_t Address, const void *Decoder); +static DecodeStatus DecodeBranchTarget21MM(MCInst &Inst, + unsigned Offset, + uint64_t Address, + const void *Decoder); + static DecodeStatus DecodeBranchTarget26(MCInst &Inst, unsigned Offset, uint64_t Address, @@ -340,6 +354,10 @@ static DecodeStatus DecodeFMem(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder); +static DecodeStatus DecodeFMemMMR2(MCInst &Inst, unsigned Insn, + uint64_t Address, + const void *Decoder); + static DecodeStatus DecodeFMem2(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder); @@ -352,6 +370,10 @@ static DecodeStatus DecodeFMemCop2R6(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder); +static DecodeStatus DecodeFMemCop2MMR6(MCInst &Inst, unsigned Insn, + uint64_t Address, + const void *Decoder); + static DecodeStatus DecodeSpecial3LlSc(MCInst &Inst, unsigned Insn, uint64_t Address, @@ -362,12 +384,7 @@ static DecodeStatus DecodeAddiur2Simm7(MCInst &Inst, uint64_t Address, const void *Decoder); -static DecodeStatus DecodeUImm6Lsl2(MCInst &Inst, - unsigned Value, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeLiSimm7(MCInst &Inst, +static DecodeStatus DecodeLi16Imm(MCInst &Inst, unsigned Value, uint64_t Address, const void *Decoder); @@ -377,19 +394,23 @@ static DecodeStatus DecodePOOL16BEncodedField(MCInst &Inst, uint64_t Address, const void *Decoder); -static DecodeStatus DecodeSimm4(MCInst &Inst, - unsigned Value, - uint64_t Address, - const void *Decoder); - -static DecodeStatus DecodeSimm16(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder); +template <unsigned Bits, int Offset, int Scale> +static DecodeStatus DecodeUImmWithOffsetAndScale(MCInst &Inst, unsigned Value, + uint64_t Address, + const void *Decoder); template <unsigned Bits, int Offset> static DecodeStatus DecodeUImmWithOffset(MCInst &Inst, unsigned Value, - uint64_t Address, const void *Decoder); + uint64_t Address, + const void *Decoder) { + return DecodeUImmWithOffsetAndScale<Bits, Offset, 1>(Inst, Value, Address, + Decoder); +} + +template <unsigned Bits, int Offset = 0, int ScaleBy = 1> +static DecodeStatus DecodeSImmWithOffsetAndScale(MCInst &Inst, unsigned Value, + uint64_t Address, + const void *Decoder); static DecodeStatus DecodeInsSize(MCInst &Inst, unsigned Insn, @@ -408,9 +429,6 @@ static DecodeStatus DecodeSimm9SP(MCInst &Inst, unsigned Insn, static DecodeStatus DecodeANDI16Imm(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder); -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); @@ -427,11 +445,21 @@ DecodeAddiGroupBranch(MCInst &MI, InsnType insn, uint64_t Address, template <typename InsnType> static DecodeStatus +DecodePOP35GroupBranchMMR6(MCInst &MI, InsnType insn, uint64_t Address, + const void *Decoder); + +template <typename InsnType> +static DecodeStatus DecodeDaddiGroupBranch(MCInst &MI, InsnType insn, uint64_t Address, const void *Decoder); template <typename InsnType> static DecodeStatus +DecodePOP37GroupBranchMMR6(MCInst &MI, InsnType insn, uint64_t Address, + const void *Decoder); + +template <typename InsnType> +static DecodeStatus DecodeBlezlGroupBranch(MCInst &MI, InsnType insn, uint64_t Address, const void *Decoder); @@ -450,6 +478,16 @@ static DecodeStatus DecodeBlezGroupBranch(MCInst &MI, InsnType insn, uint64_t Address, const void *Decoder); +template <typename InsnType> +static DecodeStatus +DecodeBgtzGroupBranchMMR6(MCInst &MI, InsnType insn, uint64_t Address, + const void *Decoder); + +template <typename InsnType> +static DecodeStatus +DecodeBlezGroupBranchMMR6(MCInst &MI, InsnType insn, uint64_t Address, + const void *Decoder); + static DecodeStatus DecodeRegListOperand(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder); @@ -563,7 +601,7 @@ static DecodeStatus DecodeAddiGroupBranch(MCInst &MI, InsnType insn, InsnType Rs = fieldFromInstruction(insn, 21, 5); InsnType Rt = fieldFromInstruction(insn, 16, 5); - InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4; + int64_t Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4 + 4; bool HasRs = false; if (Rs >= Rt) { @@ -587,6 +625,37 @@ static DecodeStatus DecodeAddiGroupBranch(MCInst &MI, InsnType insn, } template <typename InsnType> +static DecodeStatus DecodePOP35GroupBranchMMR6(MCInst &MI, InsnType insn, + uint64_t Address, + const void *Decoder) { + InsnType Rt = fieldFromInstruction(insn, 21, 5); + InsnType Rs = fieldFromInstruction(insn, 16, 5); + InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 2; + + if (Rs >= Rt) { + MI.setOpcode(Mips::BOVC_MMR6); + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, + Rt))); + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, + Rs))); + } else if (Rs != 0 && Rs < Rt) { + MI.setOpcode(Mips::BEQC_MMR6); + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, + Rs))); + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, + Rt))); + } else { + MI.setOpcode(Mips::BEQZALC_MMR6); + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, + Rt))); + } + + MI.addOperand(MCOperand::createImm(Imm)); + + return MCDisassembler::Success; +} + +template <typename InsnType> static DecodeStatus DecodeDaddiGroupBranch(MCInst &MI, InsnType insn, uint64_t Address, const void *Decoder) { @@ -602,7 +671,7 @@ static DecodeStatus DecodeDaddiGroupBranch(MCInst &MI, InsnType insn, InsnType Rs = fieldFromInstruction(insn, 21, 5); InsnType Rt = fieldFromInstruction(insn, 16, 5); - InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4; + int64_t Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4 + 4; bool HasRs = false; if (Rs >= Rt) { @@ -626,6 +695,37 @@ static DecodeStatus DecodeDaddiGroupBranch(MCInst &MI, InsnType insn, } template <typename InsnType> +static DecodeStatus DecodePOP37GroupBranchMMR6(MCInst &MI, InsnType insn, + uint64_t Address, + const void *Decoder) { + InsnType Rt = fieldFromInstruction(insn, 21, 5); + InsnType Rs = fieldFromInstruction(insn, 16, 5); + InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 2; + + if (Rs >= Rt) { + MI.setOpcode(Mips::BNVC_MMR6); + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, + Rt))); + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, + Rs))); + } else if (Rs != 0 && Rs < Rt) { + MI.setOpcode(Mips::BNEC_MMR6); + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, + Rs))); + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, + Rt))); + } else { + MI.setOpcode(Mips::BNEZALC_MMR6); + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, + Rt))); + } + + MI.addOperand(MCOperand::createImm(Imm)); + + return MCDisassembler::Success; +} + +template <typename InsnType> static DecodeStatus DecodeBlezlGroupBranch(MCInst &MI, InsnType insn, uint64_t Address, const void *Decoder) { @@ -642,7 +742,7 @@ static DecodeStatus DecodeBlezlGroupBranch(MCInst &MI, InsnType insn, InsnType Rs = fieldFromInstruction(insn, 21, 5); InsnType Rt = fieldFromInstruction(insn, 16, 5); - InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4; + int64_t Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4 + 4; bool HasRs = false; if (Rt == 0) @@ -687,7 +787,7 @@ static DecodeStatus DecodeBgtzlGroupBranch(MCInst &MI, InsnType insn, InsnType Rs = fieldFromInstruction(insn, 21, 5); InsnType Rt = fieldFromInstruction(insn, 16, 5); - InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4; + int64_t Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4 + 4; if (Rt == 0) return MCDisassembler::Fail; @@ -729,7 +829,7 @@ static DecodeStatus DecodeBgtzGroupBranch(MCInst &MI, InsnType insn, InsnType Rs = fieldFromInstruction(insn, 21, 5); InsnType Rt = fieldFromInstruction(insn, 16, 5); - InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4; + int64_t Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4 + 4; bool HasRs = false; bool HasRt = false; @@ -778,7 +878,7 @@ static DecodeStatus DecodeBlezGroupBranch(MCInst &MI, InsnType insn, InsnType Rs = fieldFromInstruction(insn, 21, 5); InsnType Rt = fieldFromInstruction(insn, 16, 5); - InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4; + int64_t Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4 + 4; bool HasRs = false; if (Rt == 0) @@ -917,6 +1017,17 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, Size = 4; return Result; } + + if (hasMips32r6() && isFP64()) { + DEBUG(dbgs() << "Trying MicroMips32r6FP64 table (32-bit opcodes):\n"); + Result = decodeInstruction(DecoderTableMicroMips32r6FP6432, Instr, Insn, + Address, this, STI); + if (Result != MCDisassembler::Fail) { + Size = 4; + return Result; + } + } + // This is an invalid instruction. Let the disassembler move forward by the // minimum instruction size. Size = 2; @@ -949,6 +1060,16 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, } } + if (hasMips32r6() && isPTR64()) { + DEBUG(dbgs() << "Trying Mips32r6_64r6 (PTR64) table (32-bit opcodes):\n"); + Result = decodeInstruction(DecoderTableMips32r6_64r6_PTR6432, Instr, Insn, + Address, this, STI); + if (Result != MCDisassembler::Fail) { + Size = 4; + return Result; + } + } + if (hasMips32r6()) { DEBUG(dbgs() << "Trying Mips32r6_64r6 table (32-bit opcodes):\n"); Result = decodeInstruction(DecoderTableMips32r6_64r632, Instr, Insn, @@ -959,6 +1080,16 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, } } + if (hasMips2() && isPTR64()) { + DEBUG(dbgs() << "Trying Mips32r6_64r6 (PTR64) table (32-bit opcodes):\n"); + Result = decodeInstruction(DecoderTableMips32_64_PTR6432, 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, @@ -1534,7 +1665,8 @@ static DecodeStatus DecodeMemMMImm12(MCInst &Inst, // fallthrough default: Inst.addOperand(MCOperand::createReg(Reg)); - if (Inst.getOpcode() == Mips::LWP_MM || Inst.getOpcode() == Mips::SWP_MM) + if (Inst.getOpcode() == Mips::LWP_MM || Inst.getOpcode() == Mips::SWP_MM || + Inst.getOpcode() == Mips::LWP_MMR6 || Inst.getOpcode() == Mips::SWP_MMR6) Inst.addOperand(MCOperand::createReg(Reg+1)); Inst.addOperand(MCOperand::createReg(Base)); @@ -1580,6 +1712,24 @@ static DecodeStatus DecodeFMem(MCInst &Inst, return MCDisassembler::Success; } +static DecodeStatus DecodeFMemMMR2(MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + // This function is the same as DecodeFMem but with the Reg and Base fields + // swapped according to microMIPS spec. + int Offset = SignExtend32<16>(Insn & 0xffff); + unsigned Base = fieldFromInstruction(Insn, 16, 5); + unsigned Reg = fieldFromInstruction(Insn, 21, 5); + + 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)); + + return MCDisassembler::Success; +} + static DecodeStatus DecodeFMem2(MCInst &Inst, unsigned Insn, uint64_t Address, @@ -1633,6 +1783,23 @@ static DecodeStatus DecodeFMemCop2R6(MCInst &Inst, return MCDisassembler::Success; } + +static DecodeStatus DecodeFMemCop2MMR6(MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { + int Offset = SignExtend32<11>(Insn & 0x07ff); + unsigned Reg = fieldFromInstruction(Insn, 21, 5); + unsigned Base = fieldFromInstruction(Insn, 16, 5); + + 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)); + + return MCDisassembler::Success; +} + static DecodeStatus DecodeSpecial3LlSc(MCInst &Inst, unsigned Insn, uint64_t Address, @@ -1808,6 +1975,15 @@ static DecodeStatus DecodeBranchTarget(MCInst &Inst, return MCDisassembler::Success; } +static DecodeStatus DecodeBranchTarget1SImm16(MCInst &Inst, + unsigned Offset, + uint64_t Address, + const void *Decoder) { + int32_t BranchOffset = (SignExtend32<16>(Offset) * 2); + Inst.addOperand(MCOperand::createImm(BranchOffset)); + return MCDisassembler::Success; +} + static DecodeStatus DecodeJumpTarget(MCInst &Inst, unsigned Insn, uint64_t Address, @@ -1822,7 +1998,17 @@ static DecodeStatus DecodeBranchTarget21(MCInst &Inst, unsigned Offset, uint64_t Address, const void *Decoder) { - int32_t BranchOffset = SignExtend32<21>(Offset) * 4; + int32_t BranchOffset = SignExtend32<21>(Offset) * 4 + 4; + + Inst.addOperand(MCOperand::createImm(BranchOffset)); + return MCDisassembler::Success; +} + +static DecodeStatus DecodeBranchTarget21MM(MCInst &Inst, + unsigned Offset, + uint64_t Address, + const void *Decoder) { + int32_t BranchOffset = SignExtend32<21>(Offset) << 1; Inst.addOperand(MCOperand::createImm(BranchOffset)); return MCDisassembler::Success; @@ -1832,7 +2018,7 @@ static DecodeStatus DecodeBranchTarget26(MCInst &Inst, unsigned Offset, uint64_t Address, const void *Decoder) { - int32_t BranchOffset = SignExtend32<26>(Offset) * 4; + int32_t BranchOffset = SignExtend32<26>(Offset) * 4 + 4; Inst.addOperand(MCOperand::createImm(BranchOffset)); return MCDisassembler::Success; @@ -1897,15 +2083,7 @@ static DecodeStatus DecodeAddiur2Simm7(MCInst &Inst, return MCDisassembler::Success; } -static DecodeStatus DecodeUImm6Lsl2(MCInst &Inst, - unsigned Value, - uint64_t Address, - const void *Decoder) { - Inst.addOperand(MCOperand::createImm(Value << 2)); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeLiSimm7(MCInst &Inst, +static DecodeStatus DecodeLi16Imm(MCInst &Inst, unsigned Value, uint64_t Address, const void *Decoder) { @@ -1924,28 +2102,22 @@ static DecodeStatus DecodePOOL16BEncodedField(MCInst &Inst, return MCDisassembler::Success; } -static DecodeStatus DecodeSimm4(MCInst &Inst, - unsigned Value, - uint64_t Address, - const void *Decoder) { - Inst.addOperand(MCOperand::createImm(SignExtend32<4>(Value))); - return MCDisassembler::Success; -} - -static DecodeStatus DecodeSimm16(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder) { - Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Insn))); +template <unsigned Bits, int Offset, int Scale> +static DecodeStatus DecodeUImmWithOffsetAndScale(MCInst &Inst, unsigned Value, + uint64_t Address, + const void *Decoder) { + Value &= ((1 << Bits) - 1); + Value *= Scale; + Inst.addOperand(MCOperand::createImm(Value + Offset)); return MCDisassembler::Success; } -template <unsigned Bits, int Offset> -static DecodeStatus DecodeUImmWithOffset(MCInst &Inst, unsigned Value, - uint64_t Address, - const void *Decoder) { - Value &= ((1 << Bits) - 1); - Inst.addOperand(MCOperand::createImm(Value + Offset)); +template <unsigned Bits, int Offset, int ScaleBy> +static DecodeStatus DecodeSImmWithOffsetAndScale(MCInst &Inst, unsigned Value, + uint64_t Address, + const void *Decoder) { + int32_t Imm = SignExtend32<Bits>(Value) * ScaleBy; + Inst.addOperand(MCOperand::createImm(Imm + Offset)); return MCDisassembler::Success; } @@ -1996,12 +2168,6 @@ static DecodeStatus DecodeANDI16Imm(MCInst &Inst, unsigned Insn, return MCDisassembler::Success; } -static DecodeStatus DecodeUImm5lsl2(MCInst &Inst, unsigned Insn, - uint64_t Address, const void *Decoder) { - Inst.addOperand(MCOperand::createImm(Insn << 2)); - return MCDisassembler::Success; -} - static DecodeStatus DecodeRegListOperand(MCInst &Inst, unsigned Insn, uint64_t Address, @@ -2105,3 +2271,87 @@ static DecodeStatus DecodeSimm23Lsl2(MCInst &Inst, unsigned Insn, Inst.addOperand(MCOperand::createImm(SignExtend32<25>(Insn << 2))); return MCDisassembler::Success; } + +template <typename InsnType> +static DecodeStatus DecodeBgtzGroupBranchMMR6(MCInst &MI, InsnType insn, + uint64_t Address, + const void *Decoder) { + // We have: + // 0b000111 ttttt sssss iiiiiiiiiiiiiiii + // Invalid if rt == 0 + // BGTZALC_MMR6 if rs == 0 && rt != 0 + // BLTZALC_MMR6 if rs != 0 && rs == rt + // BLTUC_MMR6 if rs != 0 && rs != rt + + InsnType Rt = fieldFromInstruction(insn, 21, 5); + InsnType Rs = fieldFromInstruction(insn, 16, 5); + InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 2; + bool HasRs = false; + bool HasRt = false; + + if (Rt == 0) + return MCDisassembler::Fail; + else if (Rs == 0) { + MI.setOpcode(Mips::BGTZALC_MMR6); + HasRt = true; + } + else if (Rs == Rt) { + MI.setOpcode(Mips::BLTZALC_MMR6); + HasRs = true; + } + else { + MI.setOpcode(Mips::BLTUC_MMR6); + HasRs = true; + HasRt = true; + } + + if (HasRs) + MI.addOperand( + MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, Rs))); + + if (HasRt) + MI.addOperand( + MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, Rt))); + + MI.addOperand(MCOperand::createImm(Imm)); + + return MCDisassembler::Success; +} + +template <typename InsnType> +static DecodeStatus DecodeBlezGroupBranchMMR6(MCInst &MI, InsnType insn, + uint64_t Address, + const void *Decoder) { + // We have: + // 0b000110 ttttt sssss iiiiiiiiiiiiiiii + // Invalid if rs == 0 + // BLEZALC_MMR6 if rs == 0 && rt != 0 + // BGEZALC_MMR6 if rs == rt && rt != 0 + // BGEUC_MMR6 if rs != rt && rs != 0 && rt != 0 + + InsnType Rt = fieldFromInstruction(insn, 21, 5); + InsnType Rs = fieldFromInstruction(insn, 16, 5); + InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 2; + bool HasRs = false; + + if (Rt == 0) + return MCDisassembler::Fail; + else if (Rs == 0) + MI.setOpcode(Mips::BLEZALC_MMR6); + else if (Rs == Rt) + MI.setOpcode(Mips::BGEZALC_MMR6); + else { + HasRs = true; + MI.setOpcode(Mips::BGEUC_MMR6); + } + + if (HasRs) + MI.addOperand( + MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, Rs))); + MI.addOperand( + MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, Rt))); + + MI.addOperand(MCOperand::createImm(Imm)); + + return MCDisassembler::Success; +} diff --git a/lib/Target/Mips/InstPrinter/Makefile b/lib/Target/Mips/InstPrinter/Makefile deleted file mode 100644 index f07f3ed381ee2..0000000000000 --- a/lib/Target/Mips/InstPrinter/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -##===- lib/Target/Mips/AsmPrinter/Makefile -----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMMipsAsmPrinter - -# Hack: we need to include 'main' mips target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common diff --git a/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp b/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp index a7b7d2e080eeb..0fd593fcfbe16 100644 --- a/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp +++ b/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp @@ -122,70 +122,6 @@ void MipsInstPrinter::printInst(const MCInst *MI, raw_ostream &O, } } -static void printExpr(const MCExpr *Expr, const MCAsmInfo *MAI, - raw_ostream &OS) { - int Offset = 0; - const MCSymbolRefExpr *SRE; - - if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) { - SRE = dyn_cast<MCSymbolRefExpr>(BE->getLHS()); - const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(BE->getRHS()); - assert(SRE && CE && "Binary expression must be sym+const."); - Offset = CE->getValue(); - } else if (const MipsMCExpr *ME = dyn_cast<MipsMCExpr>(Expr)) { - ME->print(OS, MAI); - return; - } else - SRE = cast<MCSymbolRefExpr>(Expr); - - MCSymbolRefExpr::VariantKind Kind = SRE->getKind(); - - switch (Kind) { - default: llvm_unreachable("Invalid kind!"); - case MCSymbolRefExpr::VK_None: break; - case MCSymbolRefExpr::VK_Mips_GPREL: OS << "%gp_rel("; break; - case MCSymbolRefExpr::VK_Mips_GOT_CALL: OS << "%call16("; break; - case MCSymbolRefExpr::VK_Mips_GOT16: OS << "%got("; break; - case MCSymbolRefExpr::VK_Mips_GOT: OS << "%got("; break; - case MCSymbolRefExpr::VK_Mips_ABS_HI: OS << "%hi("; break; - case MCSymbolRefExpr::VK_Mips_ABS_LO: OS << "%lo("; break; - case MCSymbolRefExpr::VK_Mips_TLSGD: OS << "%tlsgd("; break; - case MCSymbolRefExpr::VK_Mips_TLSLDM: OS << "%tlsldm("; break; - case MCSymbolRefExpr::VK_Mips_DTPREL_HI: OS << "%dtprel_hi("; break; - case MCSymbolRefExpr::VK_Mips_DTPREL_LO: OS << "%dtprel_lo("; break; - case MCSymbolRefExpr::VK_Mips_GOTTPREL: OS << "%gottprel("; break; - case MCSymbolRefExpr::VK_Mips_TPREL_HI: OS << "%tprel_hi("; break; - case MCSymbolRefExpr::VK_Mips_TPREL_LO: OS << "%tprel_lo("; break; - case MCSymbolRefExpr::VK_Mips_GPOFF_HI: OS << "%hi(%neg(%gp_rel("; break; - case MCSymbolRefExpr::VK_Mips_GPOFF_LO: OS << "%lo(%neg(%gp_rel("; break; - case MCSymbolRefExpr::VK_Mips_GOT_DISP: OS << "%got_disp("; break; - case MCSymbolRefExpr::VK_Mips_GOT_PAGE: OS << "%got_page("; break; - case MCSymbolRefExpr::VK_Mips_GOT_OFST: OS << "%got_ofst("; break; - case MCSymbolRefExpr::VK_Mips_HIGHER: OS << "%higher("; break; - case MCSymbolRefExpr::VK_Mips_HIGHEST: OS << "%highest("; break; - case MCSymbolRefExpr::VK_Mips_GOT_HI16: OS << "%got_hi("; break; - case MCSymbolRefExpr::VK_Mips_GOT_LO16: OS << "%got_lo("; break; - case MCSymbolRefExpr::VK_Mips_CALL_HI16: OS << "%call_hi("; break; - case MCSymbolRefExpr::VK_Mips_CALL_LO16: OS << "%call_lo("; break; - case MCSymbolRefExpr::VK_Mips_PCREL_HI16: OS << "%pcrel_hi("; break; - case MCSymbolRefExpr::VK_Mips_PCREL_LO16: OS << "%pcrel_lo("; break; - } - - SRE->getSymbol().print(OS, MAI); - - if (Offset) { - if (Offset > 0) - OS << '+'; - OS << Offset; - } - - if ((Kind == MCSymbolRefExpr::VK_Mips_GPOFF_HI) || - (Kind == MCSymbolRefExpr::VK_Mips_GPOFF_LO)) - OS << ")))"; - else if (Kind != MCSymbolRefExpr::VK_None) - OS << ')'; -} - void MipsInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O) { const MCOperand &Op = MI->getOperand(OpNo); @@ -195,30 +131,27 @@ void MipsInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, } if (Op.isImm()) { - O << Op.getImm(); + O << formatImm(Op.getImm()); return; } assert(Op.isExpr() && "unknown operand kind in printOperand"); - printExpr(Op.getExpr(), &MAI, O); + Op.getExpr()->print(O, &MAI, true); } -void MipsInstPrinter::printUnsignedImm(const MCInst *MI, int opNum, - raw_ostream &O) { +template <unsigned Bits, unsigned Offset> +void MipsInstPrinter::printUImm(const MCInst *MI, int opNum, raw_ostream &O) { const MCOperand &MO = MI->getOperand(opNum); - if (MO.isImm()) - O << (unsigned short int)MO.getImm(); - else - printOperand(MI, opNum, O); -} + if (MO.isImm()) { + uint64_t Imm = MO.getImm(); + Imm -= Offset; + Imm &= (1 << Bits) - 1; + Imm += Offset; + O << formatImm(Imm); + return; + } -void MipsInstPrinter::printUnsignedImm8(const MCInst *MI, int opNum, - raw_ostream &O) { - const MCOperand &MO = MI->getOperand(opNum); - if (MO.isImm()) - O << (unsigned short int)(unsigned char)MO.getImm(); - else - printOperand(MI, opNum, O); + printOperand(MI, opNum, O); } void MipsInstPrinter:: @@ -325,6 +258,7 @@ bool MipsInstPrinter::printAlias(const MCInst &MI, raw_ostream &OS) { return isReg<Mips::RA_64>(MI, 0) && printAlias("jalr", MI, 1, OS); case Mips::NOR: case Mips::NOR_MM: + case Mips::NOR_MMR6: // nor $r0, $r1, $zero => not $r0, $r1 return isReg<Mips::ZERO>(MI, 2) && printAlias("not", MI, 0, 1, OS); case Mips::NOR64: @@ -343,7 +277,7 @@ void MipsInstPrinter::printSaveRestore(const MCInst *MI, raw_ostream &O) { if (MI->getOperand(i).isReg()) printRegName(O, MI->getOperand(i).getReg()); else - printUnsignedImm(MI, i, O); + printUImm<16>(MI, i, O); } } diff --git a/lib/Target/Mips/InstPrinter/MipsInstPrinter.h b/lib/Target/Mips/InstPrinter/MipsInstPrinter.h index 0e61ea61899a3..4a76b5acac790 100644 --- a/lib/Target/Mips/InstPrinter/MipsInstPrinter.h +++ b/lib/Target/Mips/InstPrinter/MipsInstPrinter.h @@ -93,8 +93,8 @@ public: private: void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); - void printUnsignedImm(const MCInst *MI, int opNum, raw_ostream &O); - void printUnsignedImm8(const MCInst *MI, int opNum, raw_ostream &O); + template <unsigned Bits, unsigned Offset = 0> + void printUImm(const MCInst *MI, int opNum, raw_ostream &O); void printMemOperand(const MCInst *MI, int opNum, raw_ostream &O); void printMemOperandEA(const MCInst *MI, int opNum, raw_ostream &O); void printFCCOperand(const MCInst *MI, int opNum, raw_ostream &O); diff --git a/lib/Target/Mips/MCTargetDesc/Makefile b/lib/Target/Mips/MCTargetDesc/Makefile deleted file mode 100644 index 22a27218f28d5..0000000000000 --- a/lib/Target/Mips/MCTargetDesc/Makefile +++ /dev/null @@ -1,17 +0,0 @@ -##===- lib/Target/Mips/TargetDesc/Makefile -----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../../.. -LIBRARYNAME = LLVMMipsDesc - -# Hack: we need to include 'main' target directory to grab private headers -CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common - diff --git a/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp b/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp index 70b9cca8cf6e7..932d38a0b9fe2 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp @@ -53,17 +53,17 @@ uint8_t MipsABIFlagsSection::getCPR1SizeValue() { namespace llvm { MCStreamer &operator<<(MCStreamer &OS, MipsABIFlagsSection &ABIFlagsSection) { // Write out a Elf_Internal_ABIFlags_v0 struct - OS.EmitIntValue(ABIFlagsSection.getVersionValue(), 2); // version - OS.EmitIntValue(ABIFlagsSection.getISALevelValue(), 1); // isa_level - OS.EmitIntValue(ABIFlagsSection.getISARevisionValue(), 1); // isa_rev - OS.EmitIntValue(ABIFlagsSection.getGPRSizeValue(), 1); // gpr_size - OS.EmitIntValue(ABIFlagsSection.getCPR1SizeValue(), 1); // cpr1_size - OS.EmitIntValue(ABIFlagsSection.getCPR2SizeValue(), 1); // cpr2_size - OS.EmitIntValue(ABIFlagsSection.getFpABIValue(), 1); // fp_abi - OS.EmitIntValue(ABIFlagsSection.getISAExtensionSetValue(), 4); // isa_ext - OS.EmitIntValue(ABIFlagsSection.getASESetValue(), 4); // ases - OS.EmitIntValue(ABIFlagsSection.getFlags1Value(), 4); // flags1 - OS.EmitIntValue(ABIFlagsSection.getFlags2Value(), 4); // flags2 + OS.EmitIntValue(ABIFlagsSection.getVersionValue(), 2); // version + OS.EmitIntValue(ABIFlagsSection.getISALevelValue(), 1); // isa_level + OS.EmitIntValue(ABIFlagsSection.getISARevisionValue(), 1); // isa_rev + OS.EmitIntValue(ABIFlagsSection.getGPRSizeValue(), 1); // gpr_size + OS.EmitIntValue(ABIFlagsSection.getCPR1SizeValue(), 1); // cpr1_size + OS.EmitIntValue(ABIFlagsSection.getCPR2SizeValue(), 1); // cpr2_size + OS.EmitIntValue(ABIFlagsSection.getFpABIValue(), 1); // fp_abi + OS.EmitIntValue(ABIFlagsSection.getISAExtensionValue(), 4); // isa_ext + OS.EmitIntValue(ABIFlagsSection.getASESetValue(), 4); // ases + OS.EmitIntValue(ABIFlagsSection.getFlags1Value(), 4); // flags1 + OS.EmitIntValue(ABIFlagsSection.getFlags2Value(), 4); // flags2 return OS; } } diff --git a/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h b/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h index b078cd30a87bd..3966cae9fe33d 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h +++ b/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h @@ -35,7 +35,7 @@ struct MipsABIFlagsSection { // The size of co-processor 2 registers. Mips::AFL_REG CPR2Size; // Processor-specific extension. - uint32_t ISAExtensionSet; + Mips::AFL_EXT ISAExtension; // Mask of ASEs used. uint32_t ASESet; @@ -51,8 +51,8 @@ public: MipsABIFlagsSection() : 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) {} + ISAExtension(Mips::AFL_EXT_NONE), ASESet(0), OddSPReg(false), + Is32BitABI(false), FpABI(FpABIKind::ANY) {} uint16_t getVersionValue() { return (uint16_t)Version; } uint8_t getISALevelValue() { return (uint8_t)ISALevel; } @@ -61,7 +61,7 @@ public: uint8_t getCPR1SizeValue(); uint8_t getCPR2SizeValue() { return (uint8_t)CPR2Size; } uint8_t getFpABIValue(); - uint32_t getISAExtensionSetValue() { return (uint32_t)ISAExtensionSet; } + uint32_t getISAExtensionValue() { return (uint32_t)ISAExtension; } uint32_t getASESetValue() { return (uint32_t)ASESet; } uint32_t getFlags1Value() { @@ -141,6 +141,14 @@ public: } template <class PredicateLibrary> + void setISAExtensionFromPredicates(const PredicateLibrary &P) { + if (P.hasCnMips()) + ISAExtension = Mips::AFL_EXT_OCTEON; + else + ISAExtension = Mips::AFL_EXT_NONE; + } + + template <class PredicateLibrary> void setASESetFromPredicates(const PredicateLibrary &P) { ASESet = 0; if (P.hasDSP()) @@ -179,6 +187,7 @@ public: setISALevelAndRevisionFromPredicates(P); setGPRSizeFromPredicates(P); setCPR1SizeFromPredicates(P); + setISAExtensionFromPredicates(P); setASESetFromPredicates(P); setFpAbiFromPredicates(P); OddSPReg = P.useOddSPReg(); diff --git a/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp b/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp index cdcc3923b81e6..3cf632e789dea 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp @@ -42,7 +42,7 @@ ArrayRef<MCPhysReg> MipsABIInfo::GetVarArgRegs() const { unsigned MipsABIInfo::GetCalleeAllocdArgSizeInBytes(CallingConv::ID CC) const { if (IsO32()) return CC != CallingConv::Fast ? 16 : 0; - if (IsN32() || IsN64() || IsEABI()) + if (IsN32() || IsN64()) return 0; llvm_unreachable("Unhandled ABI"); } @@ -55,39 +55,12 @@ MipsABIInfo MipsABIInfo::computeTargetABI(const Triple &TT, StringRef CPU, 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("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()); + if (TT.getArch() == Triple::mips64 || TT.getArch() == Triple::mips64el) + return MipsABIInfo::N64(); + return MipsABIInfo::O32(); } unsigned MipsABIInfo::GetStackPtr() const { @@ -102,6 +75,10 @@ unsigned MipsABIInfo::GetBasePtr() const { return ArePtrs64bit() ? Mips::S7_64 : Mips::S7; } +unsigned MipsABIInfo::GetGlobalPtr() const { + return ArePtrs64bit() ? Mips::GP_64 : Mips::GP; +} + unsigned MipsABIInfo::GetNullPtr() const { return ArePtrs64bit() ? Mips::ZERO_64 : Mips::ZERO; } @@ -118,6 +95,14 @@ unsigned MipsABIInfo::GetPtrAddiuOp() const { return ArePtrs64bit() ? Mips::DADDiu : Mips::ADDiu; } +unsigned MipsABIInfo::GetPtrSubuOp() const { + return ArePtrs64bit() ? Mips::DSUBu : Mips::SUBu; +} + +unsigned MipsABIInfo::GetPtrAndOp() const { + return ArePtrs64bit() ? Mips::AND64 : Mips::AND; +} + unsigned MipsABIInfo::GetGPRMoveOp() const { return ArePtrs64bit() ? Mips::OR64 : Mips::OR; } diff --git a/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h b/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h index ffa2c765e79bc..9372a3c2bb1f8 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h +++ b/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h @@ -10,20 +10,20 @@ #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 { +template <typename T> class ArrayRef; class MCTargetOptions; class StringRef; class TargetRegisterClass; class MipsABIInfo { public: - enum class ABI { Unknown, O32, N32, N64, EABI }; + enum class ABI { Unknown, O32, N32, N64 }; protected: ABI ThisABI; @@ -35,7 +35,6 @@ public: static MipsABIInfo O32() { return MipsABIInfo(ABI::O32); } static MipsABIInfo N32() { return MipsABIInfo(ABI::N32); } static MipsABIInfo N64() { return MipsABIInfo(ABI::N64); } - static MipsABIInfo EABI() { return MipsABIInfo(ABI::EABI); } static MipsABIInfo computeTargetABI(const Triple &TT, StringRef CPU, const MCTargetOptions &Options); @@ -43,7 +42,6 @@ public: bool IsO32() const { return ThisABI == ABI::O32; } bool IsN32() const { return ThisABI == ABI::N32; } bool IsN64() const { return ThisABI == ABI::N64; } - bool IsEABI() const { return ThisABI == ABI::EABI; } ABI GetEnumValue() const { return ThisABI; } /// The registers to use for byval arguments. @@ -66,10 +64,13 @@ public: unsigned GetStackPtr() const; unsigned GetFramePtr() const; unsigned GetBasePtr() const; + unsigned GetGlobalPtr() const; unsigned GetNullPtr() const; unsigned GetZeroReg() const; unsigned GetPtrAdduOp() const; unsigned GetPtrAddiuOp() const; + unsigned GetPtrSubuOp() const; + unsigned GetPtrAndOp() const; unsigned GetGPRMoveOp() const; inline bool ArePtrs64bit() const { return IsN64(); } inline bool AreGprs64bit() const { return IsN32() || IsN64(); } diff --git a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp index e4865e2455ee4..8292d6b4c55aa 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp @@ -14,6 +14,7 @@ #include "MCTargetDesc/MipsFixupKinds.h" #include "MCTargetDesc/MipsAsmBackend.h" +#include "MCTargetDesc/MipsMCExpr.h" #include "MCTargetDesc/MipsMCTargetDesc.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAssembler.h" @@ -23,7 +24,9 @@ #include "llvm/MC/MCFixupKindInfo.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSubtargetInfo.h" +#include "llvm/MC/MCValue.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Format.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" @@ -40,9 +43,6 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, default: return 0; case FK_Data_2: - case FK_GPRel_4: - case FK_Data_4: - case FK_Data_8: case Mips::fixup_Mips_LO16: case Mips::fixup_Mips_GPREL16: case Mips::fixup_Mips_GPOFF_HI: @@ -57,6 +57,11 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, case Mips::fixup_MICROMIPS_GOT_OFST: case Mips::fixup_MICROMIPS_GOT_DISP: case Mips::fixup_MIPS_PCLO16: + Value &= 0xffff; + break; + case FK_GPRel_4: + case FK_Data_4: + case FK_Data_8: break; case Mips::fixup_Mips_PC16: // The displacement is then divided by 4 to give us an 18 bit @@ -69,6 +74,7 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, } break; case Mips::fixup_MIPS_PC19_S2: + case Mips::fixup_MICROMIPS_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. @@ -84,7 +90,8 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, Value >>= 2; break; case Mips::fixup_Mips_HI16: - case Mips::fixup_Mips_GOT_Local: + case Mips::fixup_Mips_GOT: + case Mips::fixup_MICROMIPS_GOT16: case Mips::fixup_Mips_GOT_HI16: case Mips::fixup_Mips_CALL_HI16: case Mips::fixup_MICROMIPS_HI16: @@ -142,6 +149,19 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, return 0; } break; + case Mips::fixup_MICROMIPS_PC18_S3: + // Check alignment. + if ((Value & 7) && Ctx) { + Ctx->reportError(Fixup.getLoc(), "out of range PC18 fixup"); + } + // 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 (!isInt<18>(Value) && Ctx) { + Ctx->reportError(Fixup.getLoc(), "out of range PC18 fixup"); + return 0; + } + break; case Mips::fixup_MIPS_PC21_S2: // Forcing a signed division because Value can be negative. Value = (int64_t) Value / 4; @@ -160,6 +180,24 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, return 0; } break; + case Mips::fixup_MICROMIPS_PC26_S1: + // Forcing a signed division because Value can be negative. + Value = (int64_t)Value / 2; + // We now check if Value can be encoded as a 26-bit signed immediate. + if (!isInt<26>(Value) && Ctx) { + Ctx->reportFatalError(Fixup.getLoc(), "out of range PC26 fixup"); + return 0; + } + break; + case Mips::fixup_MICROMIPS_PC21_S1: + // Forcing a signed division because Value can be negative. + Value = (int64_t)Value / 2; + // We now check if Value can be encoded as a 21-bit signed immediate. + if (!isInt<21>(Value) && Ctx) { + Ctx->reportError(Fixup.getLoc(), "out of range PC21 fixup"); + return 0; + } + break; } return Value; @@ -248,16 +286,11 @@ void MipsAsmBackend::applyFixup(const MCFixup &Fixup, char *Data, } } -bool MipsAsmBackend::getFixupKind(StringRef Name, MCFixupKind &MappedKind) const { - if (Name == "R_MIPS_NONE") { - MappedKind = (MCFixupKind)Mips::fixup_Mips_NONE; - return true; - } - if (Name == "R_MIPS_32") { - MappedKind = FK_Data_4; - return true; - } - return MCAsmBackend::getFixupKind(Name, MappedKind); +Optional<MCFixupKind> MipsAsmBackend::getFixupKind(StringRef Name) const { + return StringSwitch<Optional<MCFixupKind>>(Name) + .Case("R_MIPS_NONE", (MCFixupKind)Mips::fixup_Mips_NONE) + .Case("R_MIPS_32", FK_Data_4) + .Default(MCAsmBackend::getFixupKind(Name)); } const MCFixupKindInfo &MipsAsmBackend:: @@ -276,8 +309,7 @@ getFixupKindInfo(MCFixupKind Kind) const { { "fixup_Mips_LO16", 0, 16, 0 }, { "fixup_Mips_GPREL16", 0, 16, 0 }, { "fixup_Mips_LITERAL", 0, 16, 0 }, - { "fixup_Mips_GOT_Global", 0, 16, 0 }, - { "fixup_Mips_GOT_Local", 0, 16, 0 }, + { "fixup_Mips_GOT", 0, 16, 0 }, { "fixup_Mips_PC16", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_Mips_CALL16", 0, 16, 0 }, { "fixup_Mips_GPREL32", 0, 32, 0 }, @@ -316,6 +348,10 @@ getFixupKindInfo(MCFixupKind Kind) const { { "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_PC26_S1", 0, 26, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_MICROMIPS_PC19_S2", 0, 19, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_MICROMIPS_PC18_S3", 0, 18, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_MICROMIPS_PC21_S1", 0, 21, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_MICROMIPS_CALL16", 0, 16, 0 }, { "fixup_MICROMIPS_GOT_DISP", 0, 16, 0 }, { "fixup_MICROMIPS_GOT_PAGE", 0, 16, 0 }, @@ -342,8 +378,7 @@ getFixupKindInfo(MCFixupKind Kind) const { { "fixup_Mips_LO16", 16, 16, 0 }, { "fixup_Mips_GPREL16", 16, 16, 0 }, { "fixup_Mips_LITERAL", 16, 16, 0 }, - { "fixup_Mips_GOT_Global", 16, 16, 0 }, - { "fixup_Mips_GOT_Local", 16, 16, 0 }, + { "fixup_Mips_GOT", 16, 16, 0 }, { "fixup_Mips_PC16", 16, 16, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_Mips_CALL16", 16, 16, 0 }, { "fixup_Mips_GPREL32", 0, 32, 0 }, @@ -382,6 +417,10 @@ getFixupKindInfo(MCFixupKind Kind) const { { "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_PC26_S1", 6, 26, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_MICROMIPS_PC19_S2",13, 19, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_MICROMIPS_PC18_S3",14, 18, MCFixupKindInfo::FKF_IsPCRel }, + { "fixup_MICROMIPS_PC21_S1",11, 21, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_MICROMIPS_CALL16", 16, 16, 0 }, { "fixup_MICROMIPS_GOT_DISP", 16, 16, 0 }, { "fixup_MICROMIPS_GOT_PAGE", 16, 16, 0 }, @@ -435,6 +474,8 @@ void MipsAsmBackend::processFixupValue(const MCAssembler &Asm, // we are only checking if the fixup can be applied correctly. We have // access to MCContext from here which allows us to report a fatal error // with *possibly* a source code location. + // The caller will also ignore any changes we make to Value + // (recordRelocation() overwrites it with it's own calculation). (void)adjustFixupValue(Fixup, Value, &Asm.getContext()); } diff --git a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h index 1c9af9227ffe5..f260cfa566c90 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h +++ b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h @@ -41,7 +41,7 @@ public: void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, uint64_t Value, bool IsPCRel) const override; - bool getFixupKind(StringRef Name, MCFixupKind &MappedKind) const override; + Optional<MCFixupKind> getFixupKind(StringRef Name) const override; const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override; unsigned getNumFixupKinds() const override { @@ -75,7 +75,8 @@ public: /// \param Inst - The instruction to relax, which may be the same /// as the output. /// \param [out] Res On return, the relaxed instruction. - void relaxInstruction(const MCInst &Inst, MCInst &Res) const override {} + void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI, + MCInst &Res) const override {} /// @} diff --git a/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h b/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h index ff7779ec1e789..2bcff881788c4 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h +++ b/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h @@ -33,9 +33,8 @@ namespace MipsII { MO_NO_FLAG, - /// MO_GOT16 - Represents the offset into the global offset table at which + /// MO_GOT - Represents the offset into the global offset table at which /// the address the relocation entry symbol resides during execution. - MO_GOT16, MO_GOT, /// MO_GOT_CALL - Represents the offset into the global offset table at @@ -117,7 +116,12 @@ namespace MipsII { /// FrmOther - This form is for instructions that have no specific format. FrmOther = 6, - FormMask = 15 + FormMask = 15, + /// IsCTI - Instruction is a Control Transfer Instruction. + IsCTI = 1 << 4, + /// HasForbiddenSlot - Instruction has a forbidden slot. + HasForbiddenSlot = 1 << 5 + }; } } diff --git a/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp b/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp index 5b9f02b89be5d..cdad7ce1b73a5 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp @@ -7,8 +7,11 @@ // //===----------------------------------------------------------------------===// +#include <algorithm> +#include <list> #include "MCTargetDesc/MipsBaseInfo.h" #include "MCTargetDesc/MipsFixupKinds.h" +#include "MCTargetDesc/MipsMCExpr.h" #include "MCTargetDesc/MipsMCTargetDesc.h" #include "llvm/ADT/STLExtras.h" #include "llvm/MC/MCAssembler.h" @@ -17,42 +20,190 @@ #include "llvm/MC/MCSection.h" #include "llvm/MC/MCSymbolELF.h" #include "llvm/MC/MCValue.h" +#include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" -#include <list> + +#define DEBUG_TYPE "mips-elf-object-writer" using namespace llvm; namespace { -// A helper structure based on ELFRelocationEntry, used for sorting entries in -// the relocation table. +/// Holds additional information needed by the relocation ordering algorithm. 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; + const ELFRelocationEntry R; ///< The relocation. + bool Matched; ///< Is this relocation part of a match. + + MipsRelocationEntry(const ELFRelocationEntry &R) : R(R), Matched(false) {} + + void print(raw_ostream &Out) const { + R.print(Out); + Out << ", Matched=" << Matched; + } +}; + +#ifndef NDEBUG +raw_ostream &operator<<(raw_ostream &OS, const MipsRelocationEntry &RHS) { + RHS.print(OS); + return OS; +} +#endif + +class MipsELFObjectWriter : public MCELFObjectTargetWriter { +public: + MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI, bool _isN64, + bool IsLittleEndian); + + ~MipsELFObjectWriter() override; + + unsigned getRelocType(MCContext &Ctx, const MCValue &Target, + const MCFixup &Fixup, bool IsPCRel) const override; + bool needsRelocateWithSymbol(const MCSymbol &Sym, + unsigned Type) const override; + virtual void sortRelocs(const MCAssembler &Asm, + std::vector<ELFRelocationEntry> &Relocs) override; +}; + +/// Copy elements in the range [First, Last) to d1 when the predicate is true or +/// d2 when the predicate is false. This is essentially both std::copy_if and +/// std::remove_copy_if combined into a single pass. +template <class InputIt, class OutputIt1, class OutputIt2, class UnaryPredicate> +std::pair<OutputIt1, OutputIt2> copy_if_else(InputIt First, InputIt Last, + OutputIt1 d1, OutputIt2 d2, + UnaryPredicate Predicate) { + for (InputIt I = First; I != Last; ++I) { + if (Predicate(*I)) { + *d1 = *I; + d1++; + } else { + *d2 = *I; + d2++; + } + } + + return std::make_pair(d1, d2); +} + +/// The possible results of the Predicate function used by find_best. +enum FindBestPredicateResult { + FindBest_NoMatch = 0, ///< The current element is not a match. + FindBest_Match, ///< The current element is a match but better ones are + /// possible. + FindBest_PerfectMatch, ///< The current element is an unbeatable match. }; - class MipsELFObjectWriter : public MCELFObjectTargetWriter { - public: - MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI, - bool _isN64, bool IsLittleEndian); +/// Find the best match in the range [First, Last). +/// +/// An element matches when Predicate(X) returns FindBest_Match or +/// FindBest_PerfectMatch. A value of FindBest_PerfectMatch also terminates +/// the search. BetterThan(A, B) is a comparator that returns true when A is a +/// better match than B. The return value is the position of the best match. +/// +/// This is similar to std::find_if but finds the best of multiple possible +/// matches. +template <class InputIt, class UnaryPredicate, class Comparator> +InputIt find_best(InputIt First, InputIt Last, UnaryPredicate Predicate, + Comparator BetterThan) { + InputIt Best = Last; + + for (InputIt I = First; I != Last; ++I) { + unsigned Matched = Predicate(*I); + if (Matched != FindBest_NoMatch) { + DEBUG(dbgs() << std::distance(First, I) << " is a match ("; + I->print(dbgs()); dbgs() << ")\n"); + if (Best == Last || BetterThan(*I, *Best)) { + DEBUG(dbgs() << ".. and it beats the last one\n"); + Best = I; + } + } + if (Matched == FindBest_PerfectMatch) { + DEBUG(dbgs() << ".. and it is unbeatable\n"); + break; + } + } + + return Best; +} + +/// Determine the low relocation that matches the given relocation. +/// If the relocation does not need a low relocation then the return value +/// is ELF::R_MIPS_NONE. +/// +/// The relocations that need a matching low part are +/// R_(MIPS|MICROMIPS|MIPS16)_HI16 for all symbols and +/// R_(MIPS|MICROMIPS|MIPS16)_GOT16 for local symbols only. +static unsigned getMatchingLoType(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.OriginalSymbol->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; +} - ~MipsELFObjectWriter() override; +/// Determine whether a relocation (X) matches the one given in R. +/// +/// A relocation matches if: +/// - It's type matches that of a corresponding low part. This is provided in +/// MatchingType for efficiency. +/// - It's based on the same symbol. +/// - It's offset of greater or equal to that of the one given in R. +/// It should be noted that this rule assumes the programmer does not use +/// offsets that exceed the alignment of the symbol. The carry-bit will be +/// incorrect if this is not true. +/// +/// A matching relocation is unbeatable if: +/// - It is not already involved in a match. +/// - It's offset is exactly that of the one given in R. +static FindBestPredicateResult isMatchingReloc(const MipsRelocationEntry &X, + const ELFRelocationEntry &R, + unsigned MatchingType) { + if (X.R.Type == MatchingType && X.R.OriginalSymbol == R.OriginalSymbol) { + if (!X.Matched && + X.R.OriginalAddend == R.OriginalAddend) + return FindBest_PerfectMatch; + else if (X.R.OriginalAddend >= R.OriginalAddend) + return FindBest_Match; + } + return FindBest_NoMatch; +} - unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, - bool IsPCRel) const override; - bool needsRelocateWithSymbol(const MCSymbol &Sym, - unsigned Type) const override; - virtual void sortRelocs(const MCAssembler &Asm, - std::vector<ELFRelocationEntry> &Relocs) override; - }; +/// Determine whether Candidate or PreviousBest is the better match. +/// The return value is true if Candidate is the better match. +/// +/// A matching relocation is a better match if: +/// - It has a smaller addend. +/// - It is not already involved in a match. +static bool compareMatchingRelocs(const MipsRelocationEntry &Candidate, + const MipsRelocationEntry &PreviousBest) { + if (Candidate.R.OriginalAddend != PreviousBest.R.OriginalAddend) + return Candidate.R.OriginalAddend < PreviousBest.R.OriginalAddend; + return PreviousBest.Matched && !Candidate.Matched; } +#ifndef NDEBUG +/// Print all the relocations. +template <class Container> +static void dumpRelocs(const char *Prefix, const Container &Relocs) { + for (const auto &R : Relocs) + dbgs() << Prefix << R << "\n"; +} +#endif + +} // end anonymous namespace + MipsELFObjectWriter::MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI, bool _isN64, bool IsLittleEndian) : MCELFObjectTargetWriter(_is64Bit, OSABI, ELF::EM_MIPS, @@ -61,7 +212,8 @@ MipsELFObjectWriter::MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI, MipsELFObjectWriter::~MipsELFObjectWriter() {} -unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target, +unsigned MipsELFObjectWriter::getRelocType(MCContext &Ctx, + const MCValue &Target, const MCFixup &Fixup, bool IsPCRel) const { // Determine the type of the relocation. @@ -89,6 +241,14 @@ unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target, return ELF::R_MICROMIPS_PC10_S1; case Mips::fixup_MICROMIPS_PC16_S1: return ELF::R_MICROMIPS_PC16_S1; + case Mips::fixup_MICROMIPS_PC26_S1: + return ELF::R_MICROMIPS_PC26_S1; + case Mips::fixup_MICROMIPS_PC19_S2: + return ELF::R_MICROMIPS_PC19_S2; + case Mips::fixup_MICROMIPS_PC18_S3: + return ELF::R_MICROMIPS_PC18_S3; + case Mips::fixup_MICROMIPS_PC21_S1: + return ELF::R_MICROMIPS_PC21_S1; case Mips::fixup_MIPS_PC19_S2: return ELF::R_MIPS_PC19_S2; case Mips::fixup_MIPS_PC18_S3: @@ -125,8 +285,7 @@ unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target, return ELF::R_MIPS_26; case Mips::fixup_Mips_CALL16: return ELF::R_MIPS_CALL16; - case Mips::fixup_Mips_GOT_Global: - case Mips::fixup_Mips_GOT_Local: + case Mips::fixup_Mips_GOT: return ELF::R_MIPS_GOT16; case Mips::fixup_Mips_HI16: return ELF::R_MIPS_HI16; @@ -211,213 +370,266 @@ unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target, 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; - -static int cmpRel(const ELFRelocationEntry *AP, const ELFRelocationEntry *BP) { - const ELFRelocationEntry &A = *AP; - const ELFRelocationEntry &B = *BP; - if (A.Offset != B.Offset) - return B.Offset - A.Offset; - if (B.Type != A.Type) - return A.Type - B.Type; - return 0; -} - +/// Sort relocation table entries by offset except where another order is +/// required by the MIPS ABI. +/// +/// MIPS has a few relocations that have an AHL component in the expression used +/// to evaluate them. This AHL component is an addend with the same number of +/// bits as a symbol value but not all of our ABI's are able to supply a +/// sufficiently sized addend in a single relocation. +/// +/// The O32 ABI for example, uses REL relocations which store the addend in the +/// section data. All the relocations with AHL components affect 16-bit fields +/// so the addend for a single relocation is limited to 16-bit. This ABI +/// resolves the limitation by linking relocations (e.g. R_MIPS_HI16 and +/// R_MIPS_LO16) and distributing the addend between the linked relocations. The +/// ABI mandates that such relocations must be next to each other in a +/// particular order (e.g. R_MIPS_HI16 must be immediately followed by a +/// matching R_MIPS_LO16) but the rule is less strict in practice. +/// +/// The de facto standard is lenient in the following ways: +/// - 'Immediately following' does not refer to the next relocation entry but +/// the next matching relocation. +/// - There may be multiple high parts relocations for one low part relocation. +/// - There may be multiple low part relocations for one high part relocation. +/// - The AHL addend in each part does not have to be exactly equal as long as +/// the difference does not affect the carry bit from bit 15 into 16. This is +/// to allow, for example, the use of %lo(foo) and %lo(foo+4) when loading +/// both halves of a long long. +/// +/// See getMatchingLoType() for a description of which high part relocations +/// match which low part relocations. One particular thing to note is that +/// R_MIPS_GOT16 and similar only have AHL addends if they refer to local +/// symbols. +/// +/// It should also be noted that this function is not affected by whether +/// the symbol was kept or rewritten into a section-relative equivalent. We +/// always match using the expressions from the source. void MipsELFObjectWriter::sortRelocs(const MCAssembler &Asm, std::vector<ELFRelocationEntry> &Relocs) { if (Relocs.size() < 2) return; - // Sorts entries by Offset in descending order. - array_pod_sort(Relocs.begin(), Relocs.end(), cmpRel); - - // 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]); + // Sort relocations by the address they are applied to. + std::sort(Relocs.begin(), Relocs.end(), + [](const ELFRelocationEntry &A, const ELFRelocationEntry &B) { + return A.Offset < B.Offset; + }); + + std::list<MipsRelocationEntry> Sorted; + std::list<ELFRelocationEntry> Remainder; + + DEBUG(dumpRelocs("R: ", Relocs)); + + // Separate the movable relocations (AHL relocations using the high bits) from + // the immobile relocations (everything else). This does not preserve high/low + // matches that already existed in the input. + copy_if_else(Relocs.begin(), Relocs.end(), std::back_inserter(Remainder), + std::back_inserter(Sorted), [](const ELFRelocationEntry &Reloc) { + return getMatchingLoType(Reloc) != ELF::R_MIPS_NONE; + }); + + for (auto &R : Remainder) { + DEBUG(dbgs() << "Matching: " << R << "\n"); + + unsigned MatchingType = getMatchingLoType(R); + assert(MatchingType != ELF::R_MIPS_NONE && + "Wrong list for reloc that doesn't need a match"); + + // Find the best matching relocation for the current high part. + // See isMatchingReloc for a description of a matching relocation and + // compareMatchingRelocs for a description of what 'best' means. + auto InsertionPoint = + find_best(Sorted.begin(), Sorted.end(), + [&R, &MatchingType](const MipsRelocationEntry &X) { + return isMatchingReloc(X, R, MatchingType); + }, + compareMatchingRelocs); + + // If we matched then insert the high part in front of the match and mark + // both relocations as being involved in a match. We only mark the high + // part for cosmetic reasons in the debug output. + // + // If we failed to find a match then the high part is orphaned. This is not + // permitted since the relocation cannot be evaluated without knowing the + // carry-in. We can sometimes handle this using a matching low part that is + // already used in a match but we already cover that case in + // isMatchingReloc and compareMatchingRelocs. For the remaining cases we + // should insert the high part at the end of the list. This will cause the + // linker to fail but the alternative is to cause the linker to bind the + // high part to a semi-matching low part and silently calculate the wrong + // value. Unfortunately we have no means to warn the user that we did this + // so leave it up to the linker to complain about it. + if (InsertionPoint != Sorted.end()) + InsertionPoint->Matched = true; + Sorted.insert(InsertionPoint, R)->Matched = true; } - // SortOffsets are calculated, call the sorting function. - array_pod_sort(MipsRelocs.begin(), MipsRelocs.end(), cmpRelMips); + DEBUG(dumpRelocs("S: ", Sorted)); + + assert(Relocs.size() == Sorted.size() && "Some relocs were not consumed"); - // Copy sorted MipsRelocs back to Relocs. - for (unsigned I = 0, E = MipsRelocs.size(); I != E; ++I) - Relocs[I] = MipsRelocs[I].R; + // Overwrite the original vector with the sorted elements. The caller expects + // them in reverse order. + unsigned CopyTo = 0; + for (const auto &R : reverse(Sorted)) + Relocs[CopyTo++] = R.R; } 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. + // If it's a compound relocation for N64 then we need the relocation if any + // sub-relocation needs it. + if (!isUInt<8>(Type)) + return needsRelocateWithSymbol(Sym, Type & 0xff) || + needsRelocateWithSymbol(Sym, (Type >> 8) & 0xff) || + needsRelocateWithSymbol(Sym, (Type >> 16) & 0xff); + switch (Type) { default: + errs() << Type << "\n"; + llvm_unreachable("Unexpected relocation"); return true; + // This relocation doesn't affect the section data. + case ELF::R_MIPS_NONE: + return false; + + // On REL ABI's (e.g. O32), these relocations form pairs. The pairing is done + // by the static linker by matching the symbol and offset. + // We only see one relocation at a time but it's still safe to relocate with + // the section so long as both relocations make the same decision. + // + // Some older linkers may require the symbol for particular cases. Such cases + // are not supported yet but can be added as required. case ELF::R_MIPS_GOT16: case ELF::R_MIPS16_GOT16: case ELF::R_MICROMIPS_GOT16: - llvm_unreachable("Should have been handled already"); - - // These relocations might be paired with another relocation. The pairing is - // done by the static linker by matching the symbol. Since we only see one - // relocation at a time, we have to force them to relocate with a symbol to - // avoid ending up with a pair where one points to a section and another - // points to a symbol. case ELF::R_MIPS_HI16: case ELF::R_MIPS16_HI16: case ELF::R_MICROMIPS_HI16: case ELF::R_MIPS_LO16: case ELF::R_MIPS16_LO16: case ELF::R_MICROMIPS_LO16: - return true; + // FIXME: It should be safe to return false for the STO_MIPS_MICROMIPS but + // we neglect to handle the adjustment to the LSB of the addend that + // it causes in applyFixup() and similar. + if (cast<MCSymbolELF>(Sym).getOther() & ELF::STO_MIPS_MICROMIPS) + return true; + return false; + case ELF::R_MIPS_16: case ELF::R_MIPS_32: + case ELF::R_MIPS_GPREL32: if (cast<MCSymbolELF>(Sym).getOther() & ELF::STO_MIPS_MICROMIPS) return true; - // falltrough + // fallthrough case ELF::R_MIPS_26: case ELF::R_MIPS_64: case ELF::R_MIPS_GPREL16: + case ELF::R_MIPS_PC16: + case ELF::R_MIPS_SUB: return false; + + // FIXME: Many of these relocations should probably return false but this + // hasn't been confirmed to be safe yet. + case ELF::R_MIPS_REL32: + case ELF::R_MIPS_LITERAL: + case ELF::R_MIPS_CALL16: + case ELF::R_MIPS_SHIFT5: + case ELF::R_MIPS_SHIFT6: + case ELF::R_MIPS_GOT_DISP: + case ELF::R_MIPS_GOT_PAGE: + case ELF::R_MIPS_GOT_OFST: + case ELF::R_MIPS_GOT_HI16: + case ELF::R_MIPS_GOT_LO16: + case ELF::R_MIPS_INSERT_A: + case ELF::R_MIPS_INSERT_B: + case ELF::R_MIPS_DELETE: + case ELF::R_MIPS_HIGHER: + case ELF::R_MIPS_HIGHEST: + case ELF::R_MIPS_CALL_HI16: + case ELF::R_MIPS_CALL_LO16: + case ELF::R_MIPS_SCN_DISP: + case ELF::R_MIPS_REL16: + case ELF::R_MIPS_ADD_IMMEDIATE: + case ELF::R_MIPS_PJUMP: + case ELF::R_MIPS_RELGOT: + case ELF::R_MIPS_JALR: + case ELF::R_MIPS_TLS_DTPMOD32: + case ELF::R_MIPS_TLS_DTPREL32: + case ELF::R_MIPS_TLS_DTPMOD64: + case ELF::R_MIPS_TLS_DTPREL64: + case ELF::R_MIPS_TLS_GD: + case ELF::R_MIPS_TLS_LDM: + case ELF::R_MIPS_TLS_DTPREL_HI16: + case ELF::R_MIPS_TLS_DTPREL_LO16: + case ELF::R_MIPS_TLS_GOTTPREL: + case ELF::R_MIPS_TLS_TPREL32: + case ELF::R_MIPS_TLS_TPREL64: + case ELF::R_MIPS_TLS_TPREL_HI16: + case ELF::R_MIPS_TLS_TPREL_LO16: + case ELF::R_MIPS_GLOB_DAT: + case ELF::R_MIPS_PC21_S2: + case ELF::R_MIPS_PC26_S2: + case ELF::R_MIPS_PC18_S3: + case ELF::R_MIPS_PC19_S2: + case ELF::R_MIPS_PCHI16: + case ELF::R_MIPS_PCLO16: + case ELF::R_MIPS_COPY: + case ELF::R_MIPS_JUMP_SLOT: + case ELF::R_MIPS_NUM: + case ELF::R_MIPS_PC32: + case ELF::R_MIPS_EH: + case ELF::R_MICROMIPS_26_S1: + case ELF::R_MICROMIPS_GPREL16: + case ELF::R_MICROMIPS_LITERAL: + case ELF::R_MICROMIPS_PC7_S1: + case ELF::R_MICROMIPS_PC10_S1: + case ELF::R_MICROMIPS_PC16_S1: + case ELF::R_MICROMIPS_CALL16: + case ELF::R_MICROMIPS_GOT_DISP: + case ELF::R_MICROMIPS_GOT_PAGE: + case ELF::R_MICROMIPS_GOT_OFST: + case ELF::R_MICROMIPS_GOT_HI16: + case ELF::R_MICROMIPS_GOT_LO16: + case ELF::R_MICROMIPS_SUB: + case ELF::R_MICROMIPS_HIGHER: + case ELF::R_MICROMIPS_HIGHEST: + case ELF::R_MICROMIPS_CALL_HI16: + case ELF::R_MICROMIPS_CALL_LO16: + case ELF::R_MICROMIPS_SCN_DISP: + case ELF::R_MICROMIPS_JALR: + case ELF::R_MICROMIPS_HI0_LO16: + case ELF::R_MICROMIPS_TLS_GD: + case ELF::R_MICROMIPS_TLS_LDM: + case ELF::R_MICROMIPS_TLS_DTPREL_HI16: + case ELF::R_MICROMIPS_TLS_DTPREL_LO16: + case ELF::R_MICROMIPS_TLS_GOTTPREL: + case ELF::R_MICROMIPS_TLS_TPREL_HI16: + case ELF::R_MICROMIPS_TLS_TPREL_LO16: + case ELF::R_MICROMIPS_GPREL7_S2: + case ELF::R_MICROMIPS_PC23_S2: + case ELF::R_MICROMIPS_PC21_S1: + case ELF::R_MICROMIPS_PC26_S1: + case ELF::R_MICROMIPS_PC18_S3: + case ELF::R_MICROMIPS_PC19_S2: + return true; + + // FIXME: Many of these should probably return false but MIPS16 isn't + // supported by the integrated assembler. + case ELF::R_MIPS16_26: + case ELF::R_MIPS16_GPREL: + case ELF::R_MIPS16_CALL16: + case ELF::R_MIPS16_TLS_GD: + case ELF::R_MIPS16_TLS_LDM: + case ELF::R_MIPS16_TLS_DTPREL_HI16: + case ELF::R_MIPS16_TLS_DTPREL_LO16: + case ELF::R_MIPS16_TLS_GOTTPREL: + case ELF::R_MIPS16_TLS_TPREL_HI16: + case ELF::R_MIPS16_TLS_TPREL_LO16: + llvm_unreachable("Unsupported MIPS16 relocation"); + return true; } } diff --git a/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h b/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h index 3652f4bab0d43..b4d8e9494650a 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h +++ b/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h @@ -50,11 +50,8 @@ namespace Mips { // 16 bit literal fixup resulting in - R_MIPS_LITERAL. fixup_Mips_LITERAL, - // Global symbol fixup resulting in - R_MIPS_GOT16. - fixup_Mips_GOT_Global, - - // Local symbol fixup resulting in - R_MIPS_GOT16. - fixup_Mips_GOT_Local, + // Symbol fixup resulting in - R_MIPS_GOT16. + fixup_Mips_GOT, // PC relative branch fixup resulting in - R_MIPS_PC16. fixup_Mips_PC16, @@ -170,6 +167,18 @@ namespace Mips { // resulting in - R_MICROMIPS_PC16_S1 fixup_MICROMIPS_PC16_S1, + // resulting in - R_MICROMIPS_PC26_S1 + fixup_MICROMIPS_PC26_S1, + + // resulting in - R_MICROMIPS_PC19_S2 + fixup_MICROMIPS_PC19_S2, + + // resulting in - R_MICROMIPS_PC18_S3 + fixup_MICROMIPS_PC18_S3, + + // resulting in - R_MICROMIPS_PC21_S1 + fixup_MICROMIPS_PC21_S1, + // resulting in - R_MICROMIPS_CALL16 fixup_MICROMIPS_CALL16, diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp index 4d554583dc782..1622b22126653 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp @@ -42,4 +42,9 @@ MipsMCAsmInfo::MipsMCAsmInfo(const Triple &TheTriple) { SupportsDebugInformation = true; ExceptionsType = ExceptionHandling::DwarfCFI; DwarfRegNumForCFI = true; + + // Enable IAS by default for O32. + if (TheTriple.getArch() == Triple::mips || + TheTriple.getArch() == Triple::mipsel) + UseIntegratedAssembler = true; } diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp index 4b030ebfce8c5..401c7d42c4cea 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -78,19 +78,25 @@ static void LowerLargeShift(MCInst& Inst) { case Mips::DROTR: Inst.setOpcode(Mips::DROTR32); return; + case Mips::DSLL_MM64R6: + Inst.setOpcode(Mips::DSLL32_MM64R6); + return; + case Mips::DSRL_MM64R6: + Inst.setOpcode(Mips::DSRL32_MM64R6); + return; + case Mips::DSRA_MM64R6: + Inst.setOpcode(Mips::DSRA32_MM64R6); + return; + case Mips::DROTR_MM64R6: + Inst.setOpcode(Mips::DROTR32_MM64R6); + return; } } -// Pick a DEXT or DINS instruction variant based on the pos and size operands -static void LowerDextDins(MCInst& InstIn) { - int Opcode = InstIn.getOpcode(); - - if (Opcode == Mips::DEXT) - assert(InstIn.getNumOperands() == 4 && - "Invalid no. of machine operands for DEXT!"); - else // Only DEXT and DINS are possible - assert(InstIn.getNumOperands() == 5 && - "Invalid no. of machine operands for DINS!"); +// Pick a DINS instruction variant based on the pos and size operands +static void LowerDins(MCInst& InstIn) { + assert(InstIn.getNumOperands() == 5 && + "Invalid no. of machine operands for DINS!"); assert(InstIn.getOperand(2).isImm()); int64_t pos = InstIn.getOperand(2).getImm(); @@ -98,20 +104,50 @@ static void LowerDextDins(MCInst& InstIn) { int64_t size = InstIn.getOperand(3).getImm(); if (size <= 32) { - if (pos < 32) // DEXT/DINS, do nothing + if (pos < 32) // DINS, do nothing return; - // DEXTU/DINSU + // DINSU InstIn.getOperand(2).setImm(pos - 32); - InstIn.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTU : Mips::DINSU); + InstIn.setOpcode(Mips::DINSU); return; } - // DEXTM/DINSM - assert(pos < 32 && "DEXT/DINS cannot have both size and pos > 32"); + // DINSM + assert(pos < 32 && "DINS cannot have both size and pos > 32"); InstIn.getOperand(3).setImm(size - 32); - InstIn.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTM : Mips::DINSM); + InstIn.setOpcode(Mips::DINSM); return; } +// Fix a bad compact branch encoding for beqc/bnec. +void MipsMCCodeEmitter::LowerCompactBranch(MCInst& Inst) const { + + // Encoding may be illegal !(rs < rt), but this situation is + // easily fixed. + unsigned RegOp0 = Inst.getOperand(0).getReg(); + unsigned RegOp1 = Inst.getOperand(1).getReg(); + + unsigned Reg0 = Ctx.getRegisterInfo()->getEncodingValue(RegOp0); + unsigned Reg1 = Ctx.getRegisterInfo()->getEncodingValue(RegOp1); + + if (Inst.getOpcode() == Mips::BNEC || Inst.getOpcode() == Mips::BEQC) { + assert(Reg0 != Reg1 && "Instruction has bad operands ($rs == $rt)!"); + if (Reg0 < Reg1) + return; + } else if (Inst.getOpcode() == Mips::BNVC || Inst.getOpcode() == Mips::BOVC) { + if (Reg0 >= Reg1) + return; + } else if (Inst.getOpcode() == Mips::BNVC_MMR6 || + Inst.getOpcode() == Mips::BOVC_MMR6) { + if (Reg1 >= Reg0) + return; + } else + llvm_unreachable("Cannot rewrite unknown branch!"); + + Inst.getOperand(0).setReg(RegOp1); + Inst.getOperand(1).setReg(RegOp0); + +} + bool MipsMCCodeEmitter::isMicroMips(const MCSubtargetInfo &STI) const { return STI.getFeatureBits()[Mips::FeatureMicroMips]; } @@ -161,12 +197,24 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS, case Mips::DSRL: case Mips::DSRA: case Mips::DROTR: + case Mips::DSLL_MM64R6: + case Mips::DSRL_MM64R6: + case Mips::DSRA_MM64R6: + case Mips::DROTR_MM64R6: LowerLargeShift(TmpInst); break; // Double extract instruction is chosen by pos and size operands - case Mips::DEXT: case Mips::DINS: - LowerDextDins(TmpInst); + LowerDins(TmpInst); + break; + // Compact branches, enforce encoding restrictions. + case Mips::BEQC: + case Mips::BNEC: + case Mips::BOVC: + case Mips::BOVC_MMR6: + case Mips::BNVC: + case Mips::BNVC_MMR6: + LowerCompactBranch(TmpInst); } unsigned long N = Fixups.size(); @@ -237,6 +285,53 @@ getBranchTargetOpValue(const MCInst &MI, unsigned OpNo, return 0; } +/// getBranchTargetOpValue1SImm16 - Return binary encoding of the branch +/// target operand. If the machine operand requires relocation, +/// record the relocation and return zero. +unsigned MipsMCCodeEmitter:: +getBranchTargetOpValue1SImm16(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() && + "getBranchTargetOpValue expects only expressions or immediates"); + + const MCExpr *FixupExpression = MCBinaryExpr::createAdd( + MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx); + Fixups.push_back(MCFixup::create(0, FixupExpression, + MCFixupKind(Mips::fixup_Mips_PC16))); + return 0; +} + +/// getBranchTargetOpValueMMR6 - Return binary encoding of the branch +/// target operand. If the machine operand requires relocation, +/// record the relocation and return zero. +unsigned MipsMCCodeEmitter:: +getBranchTargetOpValueMMR6(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() && + "getBranchTargetOpValueMMR6 expects only expressions or immediates"); + + const MCExpr *FixupExpression = MCBinaryExpr::createAdd( + MO.getExpr(), MCConstantExpr::create(-2, Ctx), Ctx); + Fixups.push_back(MCFixup::create(0, FixupExpression, + MCFixupKind(Mips::fixup_Mips_PC16))); + return 0; +} + /// getBranchTarget7OpValueMM - Return binary encoding of the microMIPS branch /// target operand. If the machine operand requires relocation, /// record the relocation and return zero. @@ -327,6 +422,29 @@ getBranchTarget21OpValue(const MCInst &MI, unsigned OpNo, return 0; } +/// getBranchTarget21OpValueMM - Return binary encoding of the branch +/// target operand for microMIPS. If the machine operand requires +/// relocation, record the relocation and return zero. +unsigned MipsMCCodeEmitter:: +getBranchTarget21OpValueMM(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() && + "getBranchTarget21OpValueMM expects only expressions or immediates"); + + const MCExpr *FixupExpression = MCBinaryExpr::createAdd( + MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx); + Fixups.push_back(MCFixup::create(0, FixupExpression, + MCFixupKind(Mips::fixup_MICROMIPS_PC21_S1))); + return 0; +} + /// getBranchTarget26OpValue - Return binary encoding of the branch /// target operand. If the machine operand requires relocation, /// record the relocation and return zero. @@ -363,7 +481,13 @@ unsigned MipsMCCodeEmitter::getBranchTarget26OpValueMM( if (MO.isImm()) return MO.getImm() >> 1; - // TODO: Push 26 PC fixup. + assert(MO.isExpr() && + "getBranchTarget26OpValueMM expects only expressions or immediates"); + + const MCExpr *FixupExpression = MCBinaryExpr::createAdd( + MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx); + Fixups.push_back(MCFixup::create(0, FixupExpression, + MCFixupKind(Mips::fixup_MICROMIPS_PC26_S1))); return 0; } @@ -510,126 +634,117 @@ getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups, Mips::Fixups FixupKind = Mips::Fixups(0); switch (MipsExpr->getKind()) { - default: llvm_unreachable("Unsupported fixup kind for target expression!"); - case MipsMCExpr::VK_Mips_HIGHEST: - FixupKind = Mips::fixup_Mips_HIGHEST; + case MipsMCExpr::MEK_NEG: + case MipsMCExpr::MEK_None: + case MipsMCExpr::MEK_Special: + llvm_unreachable("Unhandled fixup kind!"); break; - case MipsMCExpr::VK_Mips_HIGHER: - FixupKind = Mips::fixup_Mips_HIGHER; + case MipsMCExpr::MEK_CALL_HI16: + FixupKind = Mips::fixup_Mips_CALL_HI16; break; - case MipsMCExpr::VK_Mips_HI: - FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HI16 - : Mips::fixup_Mips_HI16; + case MipsMCExpr::MEK_CALL_LO16: + FixupKind = Mips::fixup_Mips_CALL_LO16; break; - case MipsMCExpr::VK_Mips_LO: - FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16 - : Mips::fixup_Mips_LO16; + case MipsMCExpr::MEK_DTPREL_HI: + FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_HI16 + : Mips::fixup_Mips_DTPREL_HI; break; - } - Fixups.push_back(MCFixup::create(0, MipsExpr, MCFixupKind(FixupKind))); - return 0; - } - - if (Kind == MCExpr::SymbolRef) { - Mips::Fixups FixupKind = Mips::Fixups(0); - - switch(cast<MCSymbolRefExpr>(Expr)->getKind()) { - default: llvm_unreachable("Unknown fixup kind!"); + case MipsMCExpr::MEK_DTPREL_LO: + FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_LO16 + : Mips::fixup_Mips_DTPREL_LO; break; - case MCSymbolRefExpr::VK_None: - FixupKind = Mips::fixup_Mips_32; // FIXME: This is ok for O32/N32 but not N64. + case MipsMCExpr::MEK_GOTTPREL: + FixupKind = Mips::fixup_Mips_GOTTPREL; + break; + case MipsMCExpr::MEK_GOT: + FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT16 + : Mips::fixup_Mips_GOT; + break; + case MipsMCExpr::MEK_GOT_CALL: + FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_CALL16 + : Mips::fixup_Mips_CALL16; + break; + case MipsMCExpr::MEK_GOT_DISP: + FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_DISP + : Mips::fixup_Mips_GOT_DISP; break; - case MCSymbolRefExpr::VK_Mips_GPOFF_HI : - FixupKind = Mips::fixup_Mips_GPOFF_HI; + case MipsMCExpr::MEK_GOT_HI16: + FixupKind = Mips::fixup_Mips_GOT_HI16; break; - case MCSymbolRefExpr::VK_Mips_GPOFF_LO : - FixupKind = Mips::fixup_Mips_GPOFF_LO; + case MipsMCExpr::MEK_GOT_LO16: + FixupKind = Mips::fixup_Mips_GOT_LO16; break; - case MCSymbolRefExpr::VK_Mips_GOT_PAGE : + case MipsMCExpr::MEK_GOT_PAGE: FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_PAGE - : Mips::fixup_Mips_GOT_PAGE; + : Mips::fixup_Mips_GOT_PAGE; break; - case MCSymbolRefExpr::VK_Mips_GOT_OFST : + case MipsMCExpr::MEK_GOT_OFST: FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_OFST - : Mips::fixup_Mips_GOT_OFST; + : Mips::fixup_Mips_GOT_OFST; break; - case MCSymbolRefExpr::VK_Mips_GOT_DISP : - FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_DISP - : Mips::fixup_Mips_GOT_DISP; - break; - case MCSymbolRefExpr::VK_Mips_GPREL: + case MipsMCExpr::MEK_GPREL: FixupKind = Mips::fixup_Mips_GPREL16; break; - case MCSymbolRefExpr::VK_Mips_GOT_CALL: - FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_CALL16 - : Mips::fixup_Mips_CALL16; + case MipsMCExpr::MEK_LO: { + // Check for %lo(%neg(%gp_rel(X))) + if (MipsExpr->isGpOff()) { + FixupKind = Mips::fixup_Mips_GPOFF_LO; + break; + } + FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16 + : Mips::fixup_Mips_LO16; break; - case MCSymbolRefExpr::VK_Mips_GOT16: - FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT16 - : Mips::fixup_Mips_GOT_Global; + } + case MipsMCExpr::MEK_HIGHEST: + FixupKind = Mips::fixup_Mips_HIGHEST; break; - case MCSymbolRefExpr::VK_Mips_GOT: - FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT16 - : Mips::fixup_Mips_GOT_Local; + case MipsMCExpr::MEK_HIGHER: + FixupKind = Mips::fixup_Mips_HIGHER; break; - case MCSymbolRefExpr::VK_Mips_ABS_HI: + case MipsMCExpr::MEK_HI: + // Check for %hi(%neg(%gp_rel(X))) + if (MipsExpr->isGpOff()) { + FixupKind = Mips::fixup_Mips_GPOFF_HI; + break; + } FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HI16 - : Mips::fixup_Mips_HI16; + : Mips::fixup_Mips_HI16; break; - case MCSymbolRefExpr::VK_Mips_ABS_LO: - FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16 - : Mips::fixup_Mips_LO16; + case MipsMCExpr::MEK_PCREL_HI16: + FixupKind = Mips::fixup_MIPS_PCHI16; + break; + case MipsMCExpr::MEK_PCREL_LO16: + FixupKind = Mips::fixup_MIPS_PCLO16; break; - case MCSymbolRefExpr::VK_Mips_TLSGD: + case MipsMCExpr::MEK_TLSGD: FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_GD - : Mips::fixup_Mips_TLSGD; + : Mips::fixup_Mips_TLSGD; break; - case MCSymbolRefExpr::VK_Mips_TLSLDM: + case MipsMCExpr::MEK_TLSLDM: FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_LDM - : Mips::fixup_Mips_TLSLDM; - break; - case MCSymbolRefExpr::VK_Mips_DTPREL_HI: - FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_HI16 - : Mips::fixup_Mips_DTPREL_HI; - break; - case MCSymbolRefExpr::VK_Mips_DTPREL_LO: - FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_LO16 - : Mips::fixup_Mips_DTPREL_LO; - break; - case MCSymbolRefExpr::VK_Mips_GOTTPREL: - FixupKind = Mips::fixup_Mips_GOTTPREL; + : Mips::fixup_Mips_TLSLDM; break; - case MCSymbolRefExpr::VK_Mips_TPREL_HI: + case MipsMCExpr::MEK_TPREL_HI: FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_HI16 - : Mips::fixup_Mips_TPREL_HI; + : Mips::fixup_Mips_TPREL_HI; break; - case MCSymbolRefExpr::VK_Mips_TPREL_LO: + case MipsMCExpr::MEK_TPREL_LO: FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_LO16 - : Mips::fixup_Mips_TPREL_LO; + : Mips::fixup_Mips_TPREL_LO; break; - case MCSymbolRefExpr::VK_Mips_HIGHER: - FixupKind = Mips::fixup_Mips_HIGHER; - break; - case MCSymbolRefExpr::VK_Mips_HIGHEST: - FixupKind = Mips::fixup_Mips_HIGHEST; - break; - case MCSymbolRefExpr::VK_Mips_GOT_HI16: - FixupKind = Mips::fixup_Mips_GOT_HI16; - break; - case MCSymbolRefExpr::VK_Mips_GOT_LO16: - FixupKind = Mips::fixup_Mips_GOT_LO16; - break; - case MCSymbolRefExpr::VK_Mips_CALL_HI16: - FixupKind = Mips::fixup_Mips_CALL_HI16; - break; - case MCSymbolRefExpr::VK_Mips_CALL_LO16: - FixupKind = Mips::fixup_Mips_CALL_LO16; - break; - case MCSymbolRefExpr::VK_Mips_PCREL_HI16: - FixupKind = Mips::fixup_MIPS_PCHI16; + } + Fixups.push_back(MCFixup::create(0, MipsExpr, MCFixupKind(FixupKind))); + return 0; + } + + if (Kind == MCExpr::SymbolRef) { + Mips::Fixups FixupKind = Mips::Fixups(0); + + switch(cast<MCSymbolRefExpr>(Expr)->getKind()) { + default: llvm_unreachable("Unknown fixup kind!"); break; - case MCSymbolRefExpr::VK_Mips_PCREL_LO16: - FixupKind = Mips::fixup_MIPS_PCLO16; + case MCSymbolRefExpr::VK_None: + FixupKind = Mips::fixup_Mips_32; // FIXME: This is ok for O32/N32 but not N64. break; } // switch @@ -660,61 +775,20 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO, return getExprOpValue(MO.getExpr(),Fixups, STI); } -/// getMSAMemEncoding - Return binary encoding of memory operand for LD/ST -/// instructions. -unsigned -MipsMCCodeEmitter::getMSAMemEncoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - // Base register is encoded in bits 20-16, offset is encoded in bits 15-0. - assert(MI.getOperand(OpNo).isReg()); - unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups, STI) << 16; - unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); - - // The immediate field of an LD/ST instruction is scaled which means it must - // be divided (when encoding) by the size (in bytes) of the instructions' - // data format. - // .b - 1 byte - // .h - 2 bytes - // .w - 4 bytes - // .d - 8 bytes - switch(MI.getOpcode()) - { - default: - assert (0 && "Unexpected instruction"); - break; - case Mips::LD_B: - case Mips::ST_B: - // We don't need to scale the offset in this case - break; - case Mips::LD_H: - case Mips::ST_H: - OffBits >>= 1; - break; - case Mips::LD_W: - case Mips::ST_W: - OffBits >>= 2; - break; - case Mips::LD_D: - case Mips::ST_D: - OffBits >>= 3; - break; - } - - return (OffBits & 0xFFFF) | RegBits; -} - -/// getMemEncoding - Return binary encoding of memory related operand. +/// Return binary encoding of memory related operand. /// If the offset operand requires relocation, record the relocation. -unsigned -MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { +template <unsigned ShiftAmount> +unsigned MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { // Base register is encoded in bits 20-16, offset is encoded in bits 15-0. assert(MI.getOperand(OpNo).isReg()); unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups, STI) << 16; unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); + // Apply the scale factor if there is one. + OffBits >>= ShiftAmount; + return (OffBits & 0xFFFF) | RegBits; } @@ -804,6 +878,19 @@ getMemEncodingMMImm9(const MCInst &MI, unsigned OpNo, } unsigned MipsMCCodeEmitter:: +getMemEncodingMMImm11(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + // Base register is encoded in bits 20-16, offset is encoded in bits 10-0. + assert(MI.getOperand(OpNo).isReg()); + unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, + STI) << 16; + unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI); + + return (OffBits & 0x07FF) | RegBits; +} + +unsigned MipsMCCodeEmitter:: getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { @@ -906,8 +993,9 @@ 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, - MCFixupKind(Mips::fixup_MIPS_PC19_S2))); + Mips::Fixups FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_PC19_S2 + : Mips::fixup_MIPS_PC19_S2; + Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(FixupKind))); return 0; } @@ -927,8 +1015,9 @@ 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, - MCFixupKind(Mips::fixup_MIPS_PC18_S3))); + Mips::Fixups FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_PC18_S3 + : Mips::fixup_MIPS_PC18_S3; + Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(FixupKind))); return 0; } diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h index fdacd172e3a23..0f4dfe1200c0b 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h +++ b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h @@ -102,6 +102,20 @@ public: SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; + // getBranchTargetOpValue1SImm16 - Return binary encoding of the branch + // target operand. If the machine operand requires relocation, + // record the relocation and return zero. + unsigned getBranchTargetOpValue1SImm16(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; + + // getBranchTargetOpValueMMR6 - Return binary encoding of the branch + // target operand. If the machine operand requires relocation, + // record the relocation and return zero. + unsigned getBranchTargetOpValueMMR6(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; + // getBranchTarget7OpValue - Return binary encoding of the microMIPS branch // target operand. If the machine operand requires relocation, // record the relocation and return zero. @@ -130,6 +144,13 @@ public: SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; + // getBranchTarget21OpValueMM - Return binary encoding of the branch + // offset operand for microMIPS. If the machine operand requires + // relocation,record the relocation and return zero. + unsigned getBranchTarget21OpValueMM(const MCInst &MI, unsigned OpNo, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; + // getBranchTarget26OpValue - Return binary encoding of the branch // offset operand. If the machine operand requires relocation, // record the relocation and return zero. @@ -161,6 +182,7 @@ public: SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; + template <unsigned ShiftAmount = 0> unsigned getMemEncoding(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; @@ -182,6 +204,9 @@ public: unsigned getMemEncodingMMImm9(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; + unsigned getMemEncodingMMImm11(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; @@ -238,6 +263,8 @@ public: unsigned getRegisterListOpValue16(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; + private: + void LowerCompactBranch(MCInst& Inst) const; }; // class MipsMCCodeEmitter } // namespace llvm. diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp index c85fc4816b086..082bb87fcb8a1 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp @@ -12,69 +12,110 @@ #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCObjectStreamer.h" +#include "llvm/MC/MCSymbolELF.h" +#include "llvm/Support/ELF.h" using namespace llvm; #define DEBUG_TYPE "mipsmcexpr" -bool MipsMCExpr::isSupportedBinaryExpr(MCSymbolRefExpr::VariantKind VK, - const MCBinaryExpr *BE) { - switch (VK) { - case MCSymbolRefExpr::VK_Mips_ABS_LO: - case MCSymbolRefExpr::VK_Mips_ABS_HI: - case MCSymbolRefExpr::VK_Mips_HIGHER: - case MCSymbolRefExpr::VK_Mips_HIGHEST: - break; - default: - return false; - } +const MipsMCExpr *MipsMCExpr::create(MipsMCExpr::MipsExprKind Kind, + const MCExpr *Expr, MCContext &Ctx) { + return new (Ctx) MipsMCExpr(Kind, Expr); +} - // We support expressions of the form "(sym1 binop1 sym2) binop2 const", - // where "binop2 const" is optional. - if (isa<MCBinaryExpr>(BE->getLHS())) { - if (!isa<MCConstantExpr>(BE->getRHS())) - return false; - BE = cast<MCBinaryExpr>(BE->getLHS()); - } - return (isa<MCSymbolRefExpr>(BE->getLHS()) - && isa<MCSymbolRefExpr>(BE->getRHS())); +const MipsMCExpr *MipsMCExpr::createGpOff(MipsMCExpr::MipsExprKind Kind, + const MCExpr *Expr, MCContext &Ctx) { + return create(Kind, create(MEK_NEG, create(MEK_GPREL, Expr, Ctx), Ctx), Ctx); } -const MipsMCExpr* -MipsMCExpr::create(MCSymbolRefExpr::VariantKind VK, const MCExpr *Expr, - MCContext &Ctx) { - VariantKind Kind; - switch (VK) { - case MCSymbolRefExpr::VK_Mips_ABS_LO: - Kind = VK_Mips_LO; +void MipsMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { + int64_t AbsVal; + + switch (Kind) { + case MEK_None: + case MEK_Special: + llvm_unreachable("MEK_None and MEK_Special are invalid"); break; - case MCSymbolRefExpr::VK_Mips_ABS_HI: - Kind = VK_Mips_HI; + case MEK_CALL_HI16: + OS << "%call_hi"; break; - case MCSymbolRefExpr::VK_Mips_HIGHER: - Kind = VK_Mips_HIGHER; + case MEK_CALL_LO16: + OS << "%call_lo"; break; - case MCSymbolRefExpr::VK_Mips_HIGHEST: - Kind = VK_Mips_HIGHEST; + case MEK_DTPREL_HI: + OS << "%dtprel_hi"; + break; + case MEK_DTPREL_LO: + OS << "%dtprel_lo"; + break; + case MEK_GOT: + OS << "%got"; + break; + case MEK_GOTTPREL: + OS << "%gottprel"; + break; + case MEK_GOT_CALL: + OS << "%call16"; + break; + case MEK_GOT_DISP: + OS << "%got_disp"; + break; + case MEK_GOT_HI16: + OS << "%got_hi"; + break; + case MEK_GOT_LO16: + OS << "%got_lo"; + break; + case MEK_GOT_PAGE: + OS << "%got_page"; + break; + case MEK_GOT_OFST: + OS << "%got_ofst"; + break; + case MEK_GPREL: + OS << "%gp_rel"; + break; + case MEK_HI: + OS << "%hi"; + break; + case MEK_HIGHER: + OS << "%higher"; + break; + case MEK_HIGHEST: + OS << "%highest"; + break; + case MEK_LO: + OS << "%lo"; + break; + case MEK_NEG: + OS << "%neg"; + break; + case MEK_PCREL_HI16: + OS << "%pcrel_hi"; + break; + case MEK_PCREL_LO16: + OS << "%pcrel_lo"; + break; + case MEK_TLSGD: + OS << "%tlsgd"; + break; + case MEK_TLSLDM: + OS << "%tlsldm"; + break; + case MEK_TPREL_HI: + OS << "%tprel_hi"; + break; + case MEK_TPREL_LO: + OS << "%tprel_lo"; break; - default: - llvm_unreachable("Invalid kind!"); - } - - return new (Ctx) MipsMCExpr(Kind, Expr); -} - -void MipsMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const { - switch (Kind) { - default: llvm_unreachable("Invalid kind!"); - case VK_Mips_LO: OS << "%lo"; break; - case VK_Mips_HI: OS << "%hi"; break; - case VK_Mips_HIGHER: OS << "%higher"; break; - case VK_Mips_HIGHEST: OS << "%highest"; break; } OS << '('; - Expr->print(OS, MAI); + if (Expr->evaluateAsAbsolute(AbsVal)) + OS << AbsVal; + else + Expr->print(OS, MAI, true); OS << ')'; } @@ -82,9 +123,165 @@ bool MipsMCExpr::evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout, const MCFixup *Fixup) const { - return getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup); + // Look for the %hi(%neg(%gp_rel(X))) and %lo(%neg(%gp_rel(X))) special cases. + if (isGpOff()) { + const MCExpr *SubExpr = + cast<MipsMCExpr>(cast<MipsMCExpr>(getSubExpr())->getSubExpr()) + ->getSubExpr(); + if (!SubExpr->evaluateAsRelocatable(Res, Layout, Fixup)) + return false; + + Res = MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(), + MEK_Special); + return true; + } + + if (!getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup)) + return false; + + if (Res.getRefKind() != MCSymbolRefExpr::VK_None) + return false; + + // evaluateAsAbsolute() and evaluateAsValue() require that we evaluate the + // %hi/%lo/etc. here. Fixup is a null pointer when either of these is the + // caller. + if (Res.isAbsolute() && Fixup == nullptr) { + int64_t AbsVal = Res.getConstant(); + switch (Kind) { + case MEK_None: + case MEK_Special: + llvm_unreachable("MEK_None and MEK_Special are invalid"); + case MEK_DTPREL_HI: + case MEK_DTPREL_LO: + case MEK_GOT: + case MEK_GOTTPREL: + case MEK_GOT_CALL: + case MEK_GOT_DISP: + case MEK_GOT_HI16: + case MEK_GOT_LO16: + case MEK_GOT_OFST: + case MEK_GOT_PAGE: + case MEK_GPREL: + case MEK_PCREL_HI16: + case MEK_PCREL_LO16: + case MEK_TLSGD: + case MEK_TLSLDM: + case MEK_TPREL_HI: + case MEK_TPREL_LO: + return false; + case MEK_LO: + case MEK_CALL_LO16: + AbsVal = SignExtend64<16>(AbsVal); + break; + case MEK_CALL_HI16: + case MEK_HI: + AbsVal = SignExtend64<16>((AbsVal + 0x8000) >> 16); + break; + case MEK_HIGHER: + AbsVal = SignExtend64<16>((AbsVal + 0x80008000LL) >> 32); + break; + case MEK_HIGHEST: + AbsVal = SignExtend64<16>((AbsVal + 0x800080008000LL) >> 48); + break; + case MEK_NEG: + AbsVal = -AbsVal; + break; + } + Res = MCValue::get(AbsVal); + return true; + } + + // We want to defer it for relocatable expressions since the constant is + // applied to the whole symbol value. + // + // The value of getKind() that is given to MCValue is only intended to aid + // debugging when inspecting MCValue objects. It shouldn't be relied upon + // for decision making. + Res = MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(), getKind()); + + return true; } void MipsMCExpr::visitUsedExpr(MCStreamer &Streamer) const { Streamer.visitUsedExpr(*getSubExpr()); } + +static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) { + switch (Expr->getKind()) { + case MCExpr::Target: + fixELFSymbolsInTLSFixupsImpl(cast<MipsMCExpr>(Expr)->getSubExpr(), Asm); + break; + case MCExpr::Constant: + break; + case MCExpr::Binary: { + const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr); + fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm); + fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm); + break; + } + case MCExpr::SymbolRef: { + // We're known to be under a TLS fixup, so any symbol should be + // modified. There should be only one. + const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr); + cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS); + break; + } + case MCExpr::Unary: + fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm); + break; + } +} + +void MipsMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const { + switch (getKind()) { + case MEK_None: + case MEK_Special: + llvm_unreachable("MEK_None and MEK_Special are invalid"); + break; + case MEK_CALL_HI16: + case MEK_CALL_LO16: + case MEK_DTPREL_HI: + case MEK_DTPREL_LO: + case MEK_GOT: + case MEK_GOT_CALL: + case MEK_GOT_DISP: + case MEK_GOT_HI16: + case MEK_GOT_LO16: + case MEK_GOT_OFST: + case MEK_GOT_PAGE: + case MEK_GPREL: + case MEK_HI: + case MEK_HIGHER: + case MEK_HIGHEST: + case MEK_LO: + case MEK_NEG: + case MEK_PCREL_HI16: + case MEK_PCREL_LO16: + case MEK_TLSLDM: + // If we do have nested target-specific expressions, they will be in + // a consecutive chain. + if (const MipsMCExpr *E = dyn_cast<const MipsMCExpr>(getSubExpr())) + E->fixELFSymbolsInTLSFixups(Asm); + break; + case MEK_GOTTPREL: + case MEK_TLSGD: + case MEK_TPREL_HI: + case MEK_TPREL_LO: + fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm); + break; + } +} + +bool MipsMCExpr::isGpOff(MipsExprKind &Kind) const { + if (getKind() == MEK_HI || getKind() == MEK_LO) { + if (const MipsMCExpr *S1 = dyn_cast<const MipsMCExpr>(getSubExpr())) { + if (const MipsMCExpr *S2 = dyn_cast<const MipsMCExpr>(S1->getSubExpr())) { + if (S1->getKind() == MEK_NEG && S2->getKind() == MEK_GPREL) { + Kind = getKind(); + return true; + } + } + } + } + return false; +} diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h b/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h index e889972c5c0e8..d1a4334ec640a 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h +++ b/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h @@ -18,49 +18,73 @@ namespace llvm { class MipsMCExpr : public MCTargetExpr { public: - enum VariantKind { - VK_Mips_None, - VK_Mips_LO, - VK_Mips_HI, - VK_Mips_HIGHER, - VK_Mips_HIGHEST + enum MipsExprKind { + MEK_None, + MEK_CALL_HI16, + MEK_CALL_LO16, + MEK_DTPREL_HI, + MEK_DTPREL_LO, + MEK_GOT, + MEK_GOTTPREL, + MEK_GOT_CALL, + MEK_GOT_DISP, + MEK_GOT_HI16, + MEK_GOT_LO16, + MEK_GOT_OFST, + MEK_GOT_PAGE, + MEK_GPREL, + MEK_HI, + MEK_HIGHER, + MEK_HIGHEST, + MEK_LO, + MEK_NEG, + MEK_PCREL_HI16, + MEK_PCREL_LO16, + MEK_TLSGD, + MEK_TLSLDM, + MEK_TPREL_HI, + MEK_TPREL_LO, + MEK_Special, }; private: - const VariantKind Kind; + const MipsExprKind Kind; const MCExpr *Expr; - explicit MipsMCExpr(VariantKind Kind, const MCExpr *Expr) - : Kind(Kind), Expr(Expr) {} + explicit MipsMCExpr(MipsExprKind Kind, const MCExpr *Expr) + : Kind(Kind), Expr(Expr) {} public: - static bool isSupportedBinaryExpr(MCSymbolRefExpr::VariantKind VK, - const MCBinaryExpr *BE); + static const MipsMCExpr *create(MipsExprKind Kind, const MCExpr *Expr, + MCContext &Ctx); + static const MipsMCExpr *createGpOff(MipsExprKind Kind, const MCExpr *Expr, + MCContext &Ctx); - static const MipsMCExpr *create(MCSymbolRefExpr::VariantKind VK, - const MCExpr *Expr, MCContext &Ctx); + /// Get the kind of this expression. + MipsExprKind getKind() const { return Kind; } - /// getOpcode - Get the kind of this expression. - VariantKind getKind() const { return Kind; } - - /// getSubExpr - Get the child of this expression. + /// Get the child of this expression. const MCExpr *getSubExpr() const { return Expr; } void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override; - bool evaluateAsRelocatableImpl(MCValue &Res, - const MCAsmLayout *Layout, + bool evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout, const MCFixup *Fixup) const override; void visitUsedExpr(MCStreamer &Streamer) const override; MCFragment *findAssociatedFragment() const override { return getSubExpr()->findAssociatedFragment(); } - // There are no TLS MipsMCExprs at the moment. - void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override {} + void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override; static bool classof(const MCExpr *E) { return E->getKind() == MCExpr::Target; } + + bool isGpOff(MipsExprKind &Kind) const; + bool isGpOff() const { + MipsExprKind Kind; + return isGpOff(Kind); + } }; } // end namespace llvm diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp index 949ee1474f96a..a055739509741 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp @@ -11,21 +11,20 @@ // //===----------------------------------------------------------------------===// +#include "MipsMCTargetDesc.h" #include "InstPrinter/MipsInstPrinter.h" #include "MipsELFStreamer.h" #include "MipsMCAsmInfo.h" #include "MipsMCNaCl.h" -#include "MipsMCTargetDesc.h" #include "MipsTargetStreamer.h" #include "llvm/ADT/Triple.h" -#include "llvm/MC/MCCodeGenInfo.h" #include "llvm/MC/MCELFStreamer.h" +#include "llvm/MC/MCInstrAnalysis.h" #include "llvm/MC/MCInstrInfo.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbol.h" #include "llvm/MC/MachineLocation.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" #include "llvm/Support/TargetRegistry.h" @@ -82,18 +81,6 @@ static MCAsmInfo *createMipsMCAsmInfo(const MCRegisterInfo &MRI, return MAI; } -static MCCodeGenInfo *createMipsMCCodeGenInfo(const Triple &TT, Reloc::Model RM, - CodeModel::Model CM, - CodeGenOpt::Level OL) { - MCCodeGenInfo *X = new MCCodeGenInfo(); - if (CM == CodeModel::JITDefault) - RM = Reloc::Static; - else if (RM == Reloc::Default) - RM = Reloc::PIC_; - X->initMCCodeGenInfo(RM, CM, OL); - return X; -} - static MCInstPrinter *createMipsMCInstPrinter(const Triple &T, unsigned SyntaxVariant, const MCAsmInfo &MAI, @@ -129,15 +116,44 @@ createMipsObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) { return new MipsTargetELFStreamer(S, STI); } +namespace { + +class MipsMCInstrAnalysis : public MCInstrAnalysis { +public: + MipsMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {} + + bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size, + uint64_t &Target) const override { + unsigned NumOps = Inst.getNumOperands(); + if (NumOps == 0) + return false; + switch (Info->get(Inst.getOpcode()).OpInfo[NumOps - 1].OperandType) { + case MCOI::OPERAND_UNKNOWN: + case MCOI::OPERAND_IMMEDIATE: + // jal, bal ... + Target = Inst.getOperand(NumOps - 1).getImm(); + return true; + case MCOI::OPERAND_PCREL: + // b, j, beq ... + Target = Addr + Inst.getOperand(NumOps - 1).getImm(); + return true; + default: + return false; + } + } +}; +} + +static MCInstrAnalysis *createMipsMCInstrAnalysis(const MCInstrInfo *Info) { + return new MipsMCInstrAnalysis(Info); +} + extern "C" void LLVMInitializeMipsTargetMC() { 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); @@ -156,6 +172,9 @@ extern "C" void LLVMInitializeMipsTargetMC() { // Register the MC subtarget info. TargetRegistry::RegisterMCSubtargetInfo(*T, createMipsMCSubtargetInfo); + // Register the MC instruction analyzer. + TargetRegistry::RegisterMCInstrAnalysis(*T, createMipsMCInstrAnalysis); + // Register the MCInstPrinter. TargetRegistry::RegisterMCInstPrinter(*T, createMipsMCInstPrinter); diff --git a/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp b/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp index e5fa7556053f9..7f79eb400f597 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -11,11 +11,12 @@ // //===----------------------------------------------------------------------===// +#include "MipsTargetStreamer.h" #include "InstPrinter/MipsInstPrinter.h" #include "MipsELFStreamer.h" +#include "MipsMCExpr.h" #include "MipsMCTargetDesc.h" #include "MipsTargetObjectFile.h" -#include "MipsTargetStreamer.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCSectionELF.h" #include "llvm/MC/MCSubtargetInfo.h" @@ -27,12 +28,19 @@ using namespace llvm; +namespace { +static cl::opt<bool> RoundSectionSizes( + "mips-round-section-sizes", cl::init(false), + cl::desc("Round section sizes up to the section alignment"), cl::Hidden); +} // end anonymous namespace + MipsTargetStreamer::MipsTargetStreamer(MCStreamer &S) : MCTargetStreamer(S), ModuleDirectiveAllowed(true) { GPRInfoSet = FPRInfoSet = FrameInfoSet = false; } void MipsTargetStreamer::emitDirectiveSetMicroMips() {} void MipsTargetStreamer::emitDirectiveSetNoMicroMips() {} +void MipsTargetStreamer::setUsesMicroMips() {} void MipsTargetStreamer::emitDirectiveSetMips16() {} void MipsTargetStreamer::emitDirectiveSetNoMips16() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetReorder() { forbidModuleDirective(); } @@ -89,9 +97,11 @@ void MipsTargetStreamer::emitDirectiveSetHardFloat() { void MipsTargetStreamer::emitDirectiveSetDsp() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetNoDsp() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveCpLoad(unsigned RegNo) {} -void MipsTargetStreamer::emitDirectiveCpRestore( - SmallVector<MCInst, 3> &StoreInsts, int Offset) { +bool MipsTargetStreamer::emitDirectiveCpRestore( + int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc, + const MCSubtargetInfo *STI) { forbidModuleDirective(); + return true; } void MipsTargetStreamer::emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, const MCSymbol &Sym, bool IsReg) { @@ -116,6 +126,217 @@ void MipsTargetStreamer::emitDirectiveSetNoOddSPReg() { forbidModuleDirective(); } +void MipsTargetStreamer::emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc, + const MCSubtargetInfo *STI) { + MCInst TmpInst; + TmpInst.setOpcode(Opcode); + TmpInst.addOperand(MCOperand::createReg(Reg0)); + TmpInst.setLoc(IDLoc); + getStreamer().EmitInstruction(TmpInst, *STI); +} + +void MipsTargetStreamer::emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, + SMLoc IDLoc, const MCSubtargetInfo *STI) { + MCInst TmpInst; + TmpInst.setOpcode(Opcode); + TmpInst.addOperand(MCOperand::createReg(Reg0)); + TmpInst.addOperand(Op1); + TmpInst.setLoc(IDLoc); + getStreamer().EmitInstruction(TmpInst, *STI); +} + +void MipsTargetStreamer::emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, + SMLoc IDLoc, const MCSubtargetInfo *STI) { + emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, STI); +} + +void MipsTargetStreamer::emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, + SMLoc IDLoc, const MCSubtargetInfo *STI) { + emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, STI); +} + +void MipsTargetStreamer::emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, + SMLoc IDLoc, const MCSubtargetInfo *STI) { + MCInst TmpInst; + TmpInst.setOpcode(Opcode); + TmpInst.addOperand(MCOperand::createImm(Imm1)); + TmpInst.addOperand(MCOperand::createImm(Imm2)); + TmpInst.setLoc(IDLoc); + getStreamer().EmitInstruction(TmpInst, *STI); +} + +void MipsTargetStreamer::emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, + MCOperand Op2, SMLoc IDLoc, + const MCSubtargetInfo *STI) { + MCInst TmpInst; + TmpInst.setOpcode(Opcode); + TmpInst.addOperand(MCOperand::createReg(Reg0)); + TmpInst.addOperand(MCOperand::createReg(Reg1)); + TmpInst.addOperand(Op2); + TmpInst.setLoc(IDLoc); + getStreamer().EmitInstruction(TmpInst, *STI); +} + +void MipsTargetStreamer::emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, + unsigned Reg2, SMLoc IDLoc, + const MCSubtargetInfo *STI) { + emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc, STI); +} + +void MipsTargetStreamer::emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, + int16_t Imm, SMLoc IDLoc, + const MCSubtargetInfo *STI) { + emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc, STI); +} + +void MipsTargetStreamer::emitAddu(unsigned DstReg, unsigned SrcReg, + unsigned TrgReg, bool Is64Bit, + const MCSubtargetInfo *STI) { + emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(), + STI); +} + +void MipsTargetStreamer::emitDSLL(unsigned DstReg, unsigned SrcReg, + int16_t ShiftAmount, SMLoc IDLoc, + const MCSubtargetInfo *STI) { + if (ShiftAmount >= 32) { + emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc, STI); + return; + } + + emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, STI); +} + +void MipsTargetStreamer::emitEmptyDelaySlot(bool hasShortDelaySlot, SMLoc IDLoc, + const MCSubtargetInfo *STI) { + if (hasShortDelaySlot) + emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, STI); + else + emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI); +} + +void MipsTargetStreamer::emitNop(SMLoc IDLoc, const MCSubtargetInfo *STI) { + emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI); +} + +/// Emit the $gp restore operation for .cprestore. +void MipsTargetStreamer::emitGPRestore(int Offset, SMLoc IDLoc, + const MCSubtargetInfo *STI) { + emitLoadWithImmOffset(Mips::LW, Mips::GP, Mips::SP, Offset, Mips::GP, IDLoc, + STI); +} + +/// Emit a store instruction with an immediate offset. +void MipsTargetStreamer::emitStoreWithImmOffset( + unsigned Opcode, unsigned SrcReg, unsigned BaseReg, int64_t Offset, + function_ref<unsigned()> GetATReg, SMLoc IDLoc, + const MCSubtargetInfo *STI) { + if (isInt<16>(Offset)) { + emitRRI(Opcode, SrcReg, BaseReg, Offset, IDLoc, STI); + return; + } + + // sw $8, offset($8) => lui $at, %hi(offset) + // add $at, $at, $8 + // sw $8, %lo(offset)($at) + + unsigned ATReg = GetATReg(); + if (!ATReg) + return; + + unsigned LoOffset = Offset & 0x0000ffff; + unsigned HiOffset = (Offset & 0xffff0000) >> 16; + + // If msb of LoOffset is 1(negative number) we must increment HiOffset + // to account for the sign-extension of the low part. + if (LoOffset & 0x8000) + HiOffset++; + + // Generate the base address in ATReg. + emitRI(Mips::LUi, ATReg, HiOffset, IDLoc, STI); + if (BaseReg != Mips::ZERO) + emitRRR(Mips::ADDu, ATReg, ATReg, BaseReg, IDLoc, STI); + // Emit the store with the adjusted base and offset. + emitRRI(Opcode, SrcReg, ATReg, LoOffset, IDLoc, STI); +} + +/// Emit a store instruction with an symbol offset. Symbols are assumed to be +/// out of range for a simm16 will be expanded to appropriate instructions. +void MipsTargetStreamer::emitStoreWithSymOffset( + unsigned Opcode, unsigned SrcReg, unsigned BaseReg, MCOperand &HiOperand, + MCOperand &LoOperand, unsigned ATReg, SMLoc IDLoc, + const MCSubtargetInfo *STI) { + // sw $8, sym => lui $at, %hi(sym) + // sw $8, %lo(sym)($at) + + // Generate the base address in ATReg. + emitRX(Mips::LUi, ATReg, HiOperand, IDLoc, STI); + if (BaseReg != Mips::ZERO) + emitRRR(Mips::ADDu, ATReg, ATReg, BaseReg, IDLoc, STI); + // Emit the store with the adjusted base and offset. + emitRRX(Opcode, SrcReg, ATReg, LoOperand, IDLoc, STI); +} + +/// Emit a load instruction with an immediate offset. DstReg and TmpReg are +/// permitted to be the same register iff DstReg is distinct from BaseReg and +/// DstReg is a GPR. It is the callers responsibility to identify such cases +/// and pass the appropriate register in TmpReg. +void MipsTargetStreamer::emitLoadWithImmOffset(unsigned Opcode, unsigned DstReg, + unsigned BaseReg, int64_t Offset, + unsigned TmpReg, SMLoc IDLoc, + const MCSubtargetInfo *STI) { + if (isInt<16>(Offset)) { + emitRRI(Opcode, DstReg, BaseReg, Offset, IDLoc, STI); + return; + } + + // 1) lw $8, offset($9) => lui $8, %hi(offset) + // add $8, $8, $9 + // lw $8, %lo(offset)($9) + // 2) lw $8, offset($8) => lui $at, %hi(offset) + // add $at, $at, $8 + // lw $8, %lo(offset)($at) + + unsigned LoOffset = Offset & 0x0000ffff; + unsigned HiOffset = (Offset & 0xffff0000) >> 16; + + // If msb of LoOffset is 1(negative number) we must increment HiOffset + // to account for the sign-extension of the low part. + if (LoOffset & 0x8000) + HiOffset++; + + // Generate the base address in TmpReg. + emitRI(Mips::LUi, TmpReg, HiOffset, IDLoc, STI); + if (BaseReg != Mips::ZERO) + emitRRR(Mips::ADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI); + // Emit the load with the adjusted base and offset. + emitRRI(Opcode, DstReg, TmpReg, LoOffset, IDLoc, STI); +} + +/// Emit a load instruction with an symbol offset. Symbols are assumed to be +/// out of range for a simm16 will be expanded to appropriate instructions. +/// DstReg and TmpReg are permitted to be the same register iff DstReg is a +/// GPR. It is the callers responsibility to identify such cases and pass the +/// appropriate register in TmpReg. +void MipsTargetStreamer::emitLoadWithSymOffset(unsigned Opcode, unsigned DstReg, + unsigned BaseReg, + MCOperand &HiOperand, + MCOperand &LoOperand, + unsigned TmpReg, SMLoc IDLoc, + const MCSubtargetInfo *STI) { + // 1) lw $8, sym => lui $8, %hi(sym) + // lw $8, %lo(sym)($8) + // 2) ldc1 $f0, sym => lui $at, %hi(sym) + // ldc1 $f0, %lo(sym)($at) + + // Generate the base address in TmpReg. + emitRX(Mips::LUi, TmpReg, HiOperand, IDLoc, STI); + if (BaseReg != Mips::ZERO) + emitRRR(Mips::ADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI); + // Emit the load with the adjusted base and offset. + emitRRX(Opcode, DstReg, TmpReg, LoOperand, IDLoc, STI); +} + MipsTargetAsmStreamer::MipsTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS) : MipsTargetStreamer(S), OS(OS) {} @@ -364,10 +585,12 @@ void MipsTargetAsmStreamer::emitDirectiveCpLoad(unsigned RegNo) { forbidModuleDirective(); } -void MipsTargetAsmStreamer::emitDirectiveCpRestore( - SmallVector<MCInst, 3> &StoreInsts, int Offset) { - MipsTargetStreamer::emitDirectiveCpRestore(StoreInsts, Offset); +bool MipsTargetAsmStreamer::emitDirectiveCpRestore( + int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc, + const MCSubtargetInfo *STI) { + MipsTargetStreamer::emitDirectiveCpRestore(Offset, GetATReg, IDLoc, STI); OS << "\t.cprestore\t" << Offset << "\n"; + return true; } void MipsTargetAsmStreamer::emitDirectiveCpsetup(unsigned RegNo, @@ -437,7 +660,15 @@ MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI) : MipsTargetStreamer(S), MicroMipsEnabled(false), STI(STI) { MCAssembler &MCA = getStreamer().getAssembler(); - Pic = MCA.getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_; + + // It's possible that MCObjectFileInfo isn't fully initialized at this point + // due to an initialization order problem where LLVMTargetMachine creates the + // target streamer before TargetLoweringObjectFile calls + // InitializeMCObjectFileInfo. There doesn't seem to be a single place that + // covers all cases so this statement covers most cases and direct object + // emission must call setPic() once MCObjectFileInfo has been initialized. The + // cases we don't handle here are covered by MipsAsmPrinter. + Pic = MCA.getContext().getObjectFileInfo()->isPositionIndependent(); const FeatureBitset &Features = STI.getFeatureBits(); @@ -482,6 +713,10 @@ MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S, else EFlags |= ELF::EF_MIPS_ARCH_1; + // Machine + if (Features[Mips::FeatureCnMips]) + EFlags |= ELF::EF_MIPS_MACH_OCTEON; + // Other options. if (Features[Mips::FeatureNaN2008]) EFlags |= ELF::EF_MIPS_NAN2008; @@ -521,6 +756,26 @@ void MipsTargetELFStreamer::finish() { DataSection.setAlignment(std::max(16u, DataSection.getAlignment())); BSSSection.setAlignment(std::max(16u, BSSSection.getAlignment())); + if (RoundSectionSizes) { + // Make sections sizes a multiple of the alignment. This is useful for + // verifying the output of IAS against the output of other assemblers but + // it's not necessary to produce a correct object and increases section + // size. + MCStreamer &OS = getStreamer(); + for (MCSection &S : MCA) { + MCSectionELF &Section = static_cast<MCSectionELF &>(S); + + unsigned Alignment = Section.getAlignment(); + if (Alignment) { + OS.SwitchSection(&Section); + if (Section.UseCodeAlign()) + OS.EmitCodeAlignment(Alignment, Alignment); + else + OS.EmitValueToAlignment(Alignment, 0, 1, Alignment); + } + } + } + const FeatureBitset &Features = STI.getFeatureBits(); // Update e_header flags. See the FIXME and comment above in @@ -576,11 +831,6 @@ MCELFStreamer &MipsTargetELFStreamer::getStreamer() { void MipsTargetELFStreamer::emitDirectiveSetMicroMips() { MicroMipsEnabled = true; - - MCAssembler &MCA = getStreamer().getAssembler(); - unsigned Flags = MCA.getELFHeaderEFlags(); - Flags |= ELF::EF_MIPS_MICROMIPS; - MCA.setELFHeaderEFlags(Flags); forbidModuleDirective(); } @@ -589,6 +839,13 @@ void MipsTargetELFStreamer::emitDirectiveSetNoMicroMips() { forbidModuleDirective(); } +void MipsTargetELFStreamer::setUsesMicroMips() { + MCAssembler &MCA = getStreamer().getAssembler(); + unsigned Flags = MCA.getELFHeaderEFlags(); + Flags |= ELF::EF_MIPS_MICROMIPS; + MCA.setELFHeaderEFlags(Flags); +} + void MipsTargetELFStreamer::emitDirectiveSetMips16() { MCAssembler &MCA = getStreamer().getAssembler(); unsigned Flags = MCA.getELFHeaderEFlags(); @@ -610,8 +867,7 @@ void MipsTargetELFStreamer::emitDirectiveEnd(StringRef Name) { MCContext &Context = MCA.getContext(); MCStreamer &OS = getStreamer(); - MCSectionELF *Sec = Context.getELFSection(".pdr", ELF::SHT_PROGBITS, - ELF::SHF_ALLOC | ELF::SHT_REL); + MCSectionELF *Sec = Context.getELFSection(".pdr", ELF::SHT_PROGBITS, 0); MCSymbol *Sym = Context.getOrCreateSymbol(Name); const MCSymbolRefExpr *ExprRef = @@ -760,8 +1016,11 @@ void MipsTargetELFStreamer::emitDirectiveCpLoad(unsigned RegNo) { MCInst TmpInst; TmpInst.setOpcode(Mips::LUi); TmpInst.addOperand(MCOperand::createReg(Mips::GP)); - const MCSymbolRefExpr *HiSym = MCSymbolRefExpr::create( - "_gp_disp", MCSymbolRefExpr::VK_Mips_ABS_HI, MCA.getContext()); + const MCExpr *HiSym = MipsMCExpr::create( + MipsMCExpr::MEK_HI, + MCSymbolRefExpr::create("_gp_disp", MCSymbolRefExpr::VK_None, + MCA.getContext()), + MCA.getContext()); TmpInst.addOperand(MCOperand::createExpr(HiSym)); getStreamer().EmitInstruction(TmpInst, STI); @@ -770,8 +1029,11 @@ void MipsTargetELFStreamer::emitDirectiveCpLoad(unsigned RegNo) { TmpInst.setOpcode(Mips::ADDiu); 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()); + const MCExpr *LoSym = MipsMCExpr::create( + MipsMCExpr::MEK_LO, + MCSymbolRefExpr::create("_gp_disp", MCSymbolRefExpr::VK_None, + MCA.getContext()), + MCA.getContext()); TmpInst.addOperand(MCOperand::createExpr(LoSym)); getStreamer().EmitInstruction(TmpInst, STI); @@ -786,9 +1048,10 @@ void MipsTargetELFStreamer::emitDirectiveCpLoad(unsigned RegNo) { forbidModuleDirective(); } -void MipsTargetELFStreamer::emitDirectiveCpRestore( - SmallVector<MCInst, 3> &StoreInsts, int Offset) { - MipsTargetStreamer::emitDirectiveCpRestore(StoreInsts, Offset); +bool MipsTargetELFStreamer::emitDirectiveCpRestore( + int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc, + const MCSubtargetInfo *STI) { + MipsTargetStreamer::emitDirectiveCpRestore(Offset, GetATReg, IDLoc, STI); // .cprestore offset // When PIC mode is enabled and the O32 ABI is used, this directive expands // to: @@ -798,10 +1061,12 @@ void MipsTargetELFStreamer::emitDirectiveCpRestore( // Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it // is used in non-PIC mode. if (!Pic || (getABI().IsN32() || getABI().IsN64())) - return; + return true; - for (const MCInst &Inst : StoreInsts) - getStreamer().EmitInstruction(Inst, STI); + // Store the $gp on the stack. + emitStoreWithImmOffset(Mips::SW, Mips::GP, Mips::SP, Offset, GetATReg, IDLoc, + STI); + return true; } void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo, @@ -812,54 +1077,55 @@ void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo, if (!Pic || !(getABI().IsN32() || getABI().IsN64())) return; + forbidModuleDirective(); + MCAssembler &MCA = getStreamer().getAssembler(); MCInst Inst; // Either store the old $gp in a register or on the stack if (IsReg) { // move $save, $gpreg - Inst.setOpcode(Mips::OR64); - Inst.addOperand(MCOperand::createReg(RegOrOffset)); - Inst.addOperand(MCOperand::createReg(Mips::GP)); - Inst.addOperand(MCOperand::createReg(Mips::ZERO)); + emitRRR(Mips::OR64, RegOrOffset, Mips::GP, Mips::ZERO, SMLoc(), &STI); } 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)); + emitRRI(Mips::SD, Mips::GP, Mips::SP, RegOrOffset, SMLoc(), &STI); } - getStreamer().EmitInstruction(Inst, STI); - Inst.clear(); - 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()); + if (getABI().IsN32()) { + MCSymbol *GPSym = MCA.getContext().getOrCreateSymbol("__gnu_local_gp"); + const MipsMCExpr *HiExpr = MipsMCExpr::create( + MipsMCExpr::MEK_HI, MCSymbolRefExpr::create(GPSym, MCA.getContext()), + MCA.getContext()); + const MipsMCExpr *LoExpr = MipsMCExpr::create( + MipsMCExpr::MEK_LO, MCSymbolRefExpr::create(GPSym, MCA.getContext()), + MCA.getContext()); + + // lui $gp, %hi(__gnu_local_gp) + emitRX(Mips::LUi, Mips::GP, MCOperand::createExpr(HiExpr), SMLoc(), &STI); + + // addiu $gp, $gp, %lo(__gnu_local_gp) + emitRRX(Mips::ADDiu, Mips::GP, Mips::GP, MCOperand::createExpr(LoExpr), + SMLoc(), &STI); + + return; + } + + const MipsMCExpr *HiExpr = MipsMCExpr::createGpOff( + MipsMCExpr::MEK_HI, MCSymbolRefExpr::create(&Sym, MCA.getContext()), + MCA.getContext()); + const MipsMCExpr *LoExpr = MipsMCExpr::createGpOff( + MipsMCExpr::MEK_LO, MCSymbolRefExpr::create(&Sym, MCA.getContext()), + MCA.getContext()); // lui $gp, %hi(%neg(%gp_rel(funcSym))) - Inst.setOpcode(Mips::LUi); - Inst.addOperand(MCOperand::createReg(Mips::GP)); - Inst.addOperand(MCOperand::createExpr(HiExpr)); - getStreamer().EmitInstruction(Inst, STI); - Inst.clear(); + emitRX(Mips::LUi, Mips::GP, MCOperand::createExpr(HiExpr), SMLoc(), &STI); // 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)); - getStreamer().EmitInstruction(Inst, STI); - Inst.clear(); + emitRRX(Mips::ADDiu, Mips::GP, Mips::GP, MCOperand::createExpr(LoExpr), + SMLoc(), &STI); // 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)); - getStreamer().EmitInstruction(Inst, STI); - - forbidModuleDirective(); + emitRRR(Mips::DADDu, Mips::GP, Mips::GP, RegNo, SMLoc(), &STI); } void MipsTargetELFStreamer::emitDirectiveCpreturn(unsigned SaveLocation, diff --git a/lib/Target/Mips/Makefile b/lib/Target/Mips/Makefile deleted file mode 100644 index 56db450f6961a..0000000000000 --- a/lib/Target/Mips/Makefile +++ /dev/null @@ -1,25 +0,0 @@ -##===- lib/Target/Mips/Makefile ----------------------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## - -LEVEL = ../../.. -LIBRARYNAME = LLVMMipsCodeGen -TARGET = Mips - -# Make sure that tblgen is run, first thing. -BUILT_SOURCES = MipsGenRegisterInfo.inc MipsGenInstrInfo.inc \ - MipsGenAsmWriter.inc MipsGenFastISel.inc \ - MipsGenDAGISel.inc MipsGenCallingConv.inc \ - MipsGenSubtargetInfo.inc MipsGenMCCodeEmitter.inc \ - MipsGenDisassemblerTables.inc \ - MipsGenMCPseudoLowering.inc MipsGenAsmMatcher.inc - -DIRS = InstPrinter Disassembler AsmParser TargetInfo MCTargetDesc - -include $(LEVEL)/Makefile.common - diff --git a/lib/Target/Mips/MicroMips32r6InstrFormats.td b/lib/Target/Mips/MicroMips32r6InstrFormats.td index 400f6eef3fb0c..2f0933277e81a 100644 --- a/lib/Target/Mips/MicroMips32r6InstrFormats.td +++ b/lib/Target/Mips/MicroMips32r6InstrFormats.td @@ -14,6 +14,7 @@ class MMR6Arch<string opstr> { string Arch = "micromipsr6"; string BaseOpcode = opstr; + string DecoderNamespace = "MicroMipsR6"; } // Class used for microMIPS32r6 and microMIPS64r6 instructions. @@ -22,6 +23,24 @@ class MicroMipsR6Inst16 : PredicateControl { let InsnPredicates = [HasMicroMips32r6]; } +//===----------------------------------------------------------------------===// +// +// Disambiguators +// +//===----------------------------------------------------------------------===// +// +// Some encodings are ambiguous except by comparing field values. + +class MMDecodeDisambiguatedBy<string Name> : DecodeDisambiguates<Name> { + string DecoderNamespace = "MicroMipsR6_Ambiguous"; +} + +//===----------------------------------------------------------------------===// +// +// Encoding Formats +// +//===----------------------------------------------------------------------===// + class BC16_FM_MM16R6 { bits<10> offset; @@ -52,6 +71,32 @@ class POOL16C_JALRC_FM_MM16R6<bits<5> op> { let Inst{4-0} = op; } +class POP35_BOVC_FM_MMR6<string instr_asm> : MipsR6Inst, MMR6Arch<instr_asm> { + bits<5> rt; + bits<5> rs; + bits<16> offset; + + bits<32> Inst; + + let Inst{31-26} = 0b011101; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-0} = offset; +} + +class POP37_BNVC_FM_MMR6<string instr_asm> : MipsR6Inst, MMR6Arch<instr_asm> { + bits<5> rt; + bits<5> rs; + bits<16> offset; + + bits<32> Inst; + + let Inst{31-26} = 0b011111; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-0} = offset; +} + class POOL16C_JRCADDIUSP_FM_MM16R6<bits<5> op> { bits<5> imm; @@ -449,7 +494,8 @@ class LOAD_UPPER_IMM_FM_MMR6 { let Inst{15-0} = imm16; } -class CMP_BRANCH_1R_RT_OFF16_FM_MMR6<bits<6> funct> : MipsR6Inst { +class CMP_BRANCH_1R_RT_OFF16_FM_MMR6<string instr_asm, bits<6> funct> + : MMR6Arch<instr_asm>, MipsR6Inst { bits<5> rt; bits<16> offset; @@ -461,7 +507,8 @@ class CMP_BRANCH_1R_RT_OFF16_FM_MMR6<bits<6> funct> : MipsR6Inst { let Inst{15-0} = offset; } -class CMP_BRANCH_1R_BOTH_OFF16_FM_MMR6<bits<6> funct> : MipsR6Inst { +class CMP_BRANCH_1R_BOTH_OFF16_FM_MMR6<string instr_asm, bits<6> funct> + : MMR6Arch<instr_asm>, MipsR6Inst { bits<5> rt; bits<16> offset; @@ -473,6 +520,37 @@ class CMP_BRANCH_1R_BOTH_OFF16_FM_MMR6<bits<6> funct> : MipsR6Inst { let Inst{15-0} = offset; } +class POOL32A_JALRC_FM_MMR6<string instr_asm, bits<10> funct> + : MipsR6Inst, MMR6Arch<instr_asm> { + 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-6} = funct; + let Inst{5-0} = 0b111100; +} + +class POOL32A_EXT_INS_FM_MMR6<string instr_asm, bits<6> funct> + : MMR6Arch<instr_asm>, MipsR6Inst { + bits<5> rt; + bits<5> rs; + bits<5> size; + bits<5> pos; + + bits<32> Inst; + + let Inst{31-26} = 0; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-11} = size; + let Inst{10-6} = pos; + let Inst{5-0} = funct; +} + class POOL32A_ERET_FM_MMR6<string instr_asm, bits<10> funct> : MMR6Arch<instr_asm> { bits<32> Inst; @@ -751,7 +829,7 @@ class POOL16C_NOT16_FM_MMR6 : MicroMipsR6Inst16 { let Inst{3-0} = 0b0000; } -class POOL16C_OR16_XOR16_FM_MMR6<bits<4> op> { +class POOL16C_OR16_XOR16_FM_MMR6<bits<4> op> : MicroMipsR6Inst16 { bits<3> rt; bits<3> rs; @@ -860,3 +938,157 @@ class POOL32F_CLASS_FM_MMR6<string instr_asm, bits<2> fmt, bits<9> funct> let Inst{10-9} = fmt; let Inst{8-0} = funct; } + +class POOL32A_TLBINV_FM_MMR6<string instr_asm, bits<10> funct> + : MMR6Arch<instr_asm>, MipsR6Inst { + bits<32> Inst; + + let Inst{31-26} = 0x0; + let Inst{25-16} = 0x0; + let Inst{15-6} = funct; + let Inst{5-0} = 0b111100; +} + +class POOL32A_MFTC0_FM_MMR6<string instr_asm, bits<5> funct, bits<6> opcode> + : MMR6Arch<instr_asm>, MipsR6Inst { + bits<5> rt; + bits<5> rs; + bits<3> sel; + + bits<32> Inst; + + let Inst{31-26} = 0b000000; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-14} = 0; + let Inst{13-11} = sel; + let Inst{10-6} = funct; + let Inst{5-0} = opcode; +} + +class POOL32F_MFTC1_FM_MMR6<string instr_asm, bits<8> funct> + : MMR6Arch<instr_asm> { + bits<5> rt; + bits<5> fs; + + bits<32> Inst; + + let Inst{31-26} = 0b010101; + let Inst{25-21} = rt; + let Inst{20-16} = fs; + let Inst{15-14} = 0; + let Inst{13-6} = funct; + let Inst{5-0} = 0b111011; +} + +class POOL32A_MFTC2_FM_MMR6<string instr_asm, bits<10> funct> + : MMR6Arch<instr_asm>, MipsR6Inst { + bits<5> rt; + bits<5> impl; + + bits<32> Inst; + + let Inst{31-26} = 0b000000; + let Inst{25-21} = rt; + let Inst{20-16} = impl; + let Inst{15-6} = funct; + let Inst{5-0} = 0b111100; +} + +class CMP_BRANCH_2R_OFF16_FM_MMR6<string opstr, bits<6> funct> + : MipsR6Inst, MMR6Arch<opstr> { + bits<5> rt; + bits<5> rs; + bits<16> offset; + + bits<32> Inst; + + let Inst{31-26} = funct; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-0} = offset; +} + +class POOL32A_DVPEVP_FM_MMR6<string instr_asm, bits<10> funct> + : MMR6Arch<instr_asm>, MipsR6Inst { + bits<5> rs; + + bits<32> Inst; + + let Inst{31-26} = 0b000000; + let Inst{25-21} = 0b00000; + let Inst{20-16} = rs; + let Inst{15-6} = funct; + let Inst{5-0} = 0b111100; +} + +class POOL32B_LWP_SWP_FM_MMR6<bits<4> funct> : MipsR6Inst { + bits<5> rd; + bits<21> addr; + bits<5> base = addr{20-16}; + bits<12> offset = addr{11-0}; + + bits<32> Inst; + + let Inst{31-26} = 0x8; + let Inst{25-21} = rd; + let Inst{20-16} = base; + let Inst{15-12} = funct; + let Inst{11-0} = offset; +} + +class CMP_BRANCH_OFF21_FM_MMR6<string opstr, bits<6> funct> : MipsR6Inst { + bits<5> rs; + bits<21> offset; + + bits<32> Inst; + + let Inst{31-26} = funct; + let Inst{25-21} = rs; + let Inst{20-0} = offset; +} + +class POOL32I_BRANCH_COP_1_2_FM_MMR6<string instr_asm, bits<5> funct> + : MMR6Arch<instr_asm> { + bits<5> rt; + bits<16> offset; + + bits<32> Inst; + + let Inst{31-26} = 0b010000; + let Inst{25-21} = funct; + let Inst{20-16} = rt; + let Inst{15-0} = offset; +} + +class LDWC1_SDWC1_FM_MMR6<string instr_asm, bits<6> funct> + : MMR6Arch<instr_asm> { + bits<5> ft; + bits<21> addr; + bits<5> base = addr{20-16}; + bits<16> offset = addr{15-0}; + + bits<32> Inst; + + let Inst{31-26} = funct; + let Inst{25-21} = ft; + let Inst{20-16} = base; + let Inst{15-0} = offset; +} + +class POOL32B_LDWC2_SDWC2_FM_MMR6<string instr_asm, bits<4> funct> + : MMR6Arch<instr_asm>, MipsR6Inst { + bits<5> rt; + bits<21> addr; + bits<5> base = addr{20-16}; + bits<11> offset = addr{10-0}; + + bits<32> Inst; + + let Inst{31-26} = 0b001000; + let Inst{25-21} = rt; + let Inst{20-16} = base; + let Inst{15-12} = funct; + let Inst{11} = 0; + let Inst{10-0} = offset; +} diff --git a/lib/Target/Mips/MicroMips32r6InstrInfo.td b/lib/Target/Mips/MicroMips32r6InstrInfo.td index 31b5db036daa6..2b636cfe3bfe7 100644 --- a/lib/Target/Mips/MicroMips32r6InstrInfo.td +++ b/lib/Target/Mips/MicroMips32r6InstrInfo.td @@ -11,6 +11,13 @@ // //===----------------------------------------------------------------------===// +def brtarget21_mm : Operand<OtherVT> { + let EncoderMethod = "getBranchTarget21OpValueMM"; + let OperandType = "OPERAND_PCREL"; + let DecoderMethod = "DecodeBranchTarget21MM"; + let ParserMatchClass = MipsJumpTargetAsmOperand; +} + def brtarget26_mm : Operand<OtherVT> { let EncoderMethod = "getBranchTarget26OpValueMM"; let OperandType = "OPERAND_PCREL"; @@ -18,6 +25,13 @@ def brtarget26_mm : Operand<OtherVT> { let ParserMatchClass = MipsJumpTargetAsmOperand; } +def brtargetr6 : Operand<OtherVT> { + let EncoderMethod = "getBranchTargetOpValueMMR6"; + let OperandType = "OPERAND_PCREL"; + let DecoderMethod = "DecodeBranchTargetMM"; + let ParserMatchClass = MipsJumpTargetAsmOperand; +} + //===----------------------------------------------------------------------===// // // Instruction Encodings @@ -40,12 +54,26 @@ class BEQZC16_MMR6_ENC : BEQZC_BNEZC_FM_MM16R6<0x23>; class BNEZC16_MMR6_ENC : BEQZC_BNEZC_FM_MM16R6<0x2b>; class BITSWAP_MMR6_ENC : POOL32A_BITSWAP_FM_MMR6<0b101100>; class BRK_MMR6_ENC : BREAK_MMR6_ENC<"break">; -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 BEQZC_MMR6_ENC : CMP_BRANCH_OFF21_FM_MMR6<"beqzc", 0b100000>; +class BNEZC_MMR6_ENC : CMP_BRANCH_OFF21_FM_MMR6<"bnezc", 0b101000>; +class BGEC_MMR6_ENC : CMP_BRANCH_2R_OFF16_FM_MMR6<"bgec", 0b111001>; +class BGEUC_MMR6_ENC : CMP_BRANCH_2R_OFF16_FM_MMR6<"bgeuc", 0b110000>, + DecodeDisambiguates<"BlezGroupBranchMMR6">; +class BLTC_MMR6_ENC : CMP_BRANCH_2R_OFF16_FM_MMR6<"bltc", 0b110001>; +class BLTUC_MMR6_ENC : CMP_BRANCH_2R_OFF16_FM_MMR6<"bltuc", 0b111000>, + DecodeDisambiguates<"BgtzGroupBranchMMR6">; +class BEQC_MMR6_ENC : CMP_BRANCH_2R_OFF16_FM_MMR6<"beqc", 0b011101>; +class BNEC_MMR6_ENC : CMP_BRANCH_2R_OFF16_FM_MMR6<"bnec", 0b011111>; +class BEQZALC_MMR6_ENC : CMP_BRANCH_1R_RT_OFF16_FM_MMR6<"beqzalc", 0b011101>; +class BNEZALC_MMR6_ENC : CMP_BRANCH_1R_RT_OFF16_FM_MMR6<"bnezalc", 0b011111>; +class BGTZALC_MMR6_ENC : CMP_BRANCH_1R_RT_OFF16_FM_MMR6<"bgtzalc", 0b111000>, + MMDecodeDisambiguatedBy<"BgtzGroupBranchMMR6">; +class BLTZALC_MMR6_ENC : CMP_BRANCH_1R_BOTH_OFF16_FM_MMR6<"bltzalc", 0b111000>, + MMDecodeDisambiguatedBy<"BgtzGroupBranchMMR6">; +class BGEZALC_MMR6_ENC : CMP_BRANCH_1R_BOTH_OFF16_FM_MMR6<"bgezalc", 0b110000>, + MMDecodeDisambiguatedBy<"BlezGroupBranchMMR6">; +class BLEZALC_MMR6_ENC : CMP_BRANCH_1R_RT_OFF16_FM_MMR6<"blezalc", 0b110000>, + MMDecodeDisambiguatedBy<"BlezGroupBranchMMR6">; 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>; @@ -63,14 +91,27 @@ class JIC_MMR6_ENC : JMP_IDX_COMPACT_FM<0b101000>; class JRC16_MMR6_ENC: POOL16C_JALRC_FM_MM16R6<0x3>; class JRCADDIUSP_MMR6_ENC : POOL16C_JRCADDIUSP_FM_MM16R6<0x13>; class LSA_MMR6_ENC : POOL32A_LSA_FM<0b001111>; +class LWP_MMR6_ENC : POOL32B_LWP_SWP_FM_MMR6<0x1>; class LWPC_MMR6_ENC : PCREL19_FM_MMR6<0b01>; class LWM16_MMR6_ENC : POOL16C_LWM_SWM_FM_MM16R6<0x2>; +class MFC0_MMR6_ENC : POOL32A_MFTC0_FM_MMR6<"mfc0", 0b00011, 0b111100>; +class MFC1_MMR6_ENC : POOL32F_MFTC1_FM_MMR6<"mfc1", 0b10000000>; +class MFC2_MMR6_ENC : POOL32A_MFTC2_FM_MMR6<"mfc2", 0b0100110100>; +class MFHC0_MMR6_ENC : POOL32A_MFTC0_FM_MMR6<"mfhc0", 0b00011, 0b110100>; +class MFHC1_MMR6_ENC : POOL32F_MFTC1_FM_MMR6<"mfhc1", 0b11000000>; +class MFHC2_MMR6_ENC : POOL32A_MFTC2_FM_MMR6<"mfhc2", 0b1000110100>; 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 MTC0_MMR6_ENC : POOL32A_MFTC0_FM_MMR6<"mtc0", 0b01011, 0b111100>; +class MTC1_MMR6_ENC : POOL32F_MFTC1_FM_MMR6<"mtc1", 0b10100000>; +class MTC2_MMR6_ENC : POOL32A_MFTC2_FM_MMR6<"mtc2", 0b0101110100>; +class MTHC0_MMR6_ENC : POOL32A_MFTC0_FM_MMR6<"mthc0", 0b01011, 0b110100>; +class MTHC1_MMR6_ENC : POOL32F_MFTC1_FM_MMR6<"mthc1", 0b11100000>; +class MTHC2_MMR6_ENC : POOL32A_MFTC2_FM_MMR6<"mthc2", 0b1001110100>; 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>; @@ -89,6 +130,7 @@ class SWE_MMR6_ENC : POOL32C_SWE_FM_MMR6<"swe", 0x18, 0xa, 0x7>; class SW16_MMR6_ENC : LOAD_STORE_FM_MM16<0x3a>; class SWM16_MMR6_ENC : POOL16C_LWM_SWM_FM_MM16R6<0xa>; class SWSP_MMR6_ENC : LOAD_STORE_SP_FM_MM16<0x32>; +class SWP_MMR6_ENC : POOL32B_LWP_SWP_FM_MMR6<0x9>; class PREFE_MMR6_ENC : POOL32C_ST_EVA_FM_MMR6<0b011000, 0b010>; class CACHEE_MMR6_ENC : POOL32C_ST_EVA_FM_MMR6<0b011000, 0b011>; class WRPGPR_MMR6_ENC : POOL32A_WRPGPR_WSBH_FM_MMR6<0x3c5>; @@ -134,6 +176,7 @@ class LLE_MMR6_ENC : LOAD_WORD_EVA_FM_MMR6<0b110>; class LWE_MMR6_ENC : LOAD_WORD_EVA_FM_MMR6<0b111>; class LW_MMR6_ENC : LOAD_WORD_FM_MMR6; class LUI_MMR6_ENC : LOAD_UPPER_IMM_FM_MMR6; +class JALRC_HB_MMR6_ENC : POOL32A_JALRC_FM_MMR6<"jalrc.hb", 0b0001111100>; class RECIP_S_MMR6_ENC : POOL32F_RECIP_ROUND_FM_MMR6<"recip.s", 0, 0b01001000>; class RECIP_D_MMR6_ENC : POOL32F_RECIP_ROUND_FM_MMR6<"recip.d", 1, 0b01001000>; class RINT_S_MMR6_ENC : POOL32F_RINT_FM_MMR6<"rint.s", 0>; @@ -150,11 +193,15 @@ class SEL_S_MMR6_ENC : POOL32F_SEL_FM_MMR6<"sel.s", 0, 0b010111000>; class SEL_D_MMR6_ENC : POOL32F_SEL_FM_MMR6<"sel.d", 1, 0b010111000>; class SELEQZ_S_MMR6_ENC : POOL32F_SEL_FM_MMR6<"seleqz.s", 0, 0b000111000>; class SELEQZ_D_MMR6_ENC : POOL32F_SEL_FM_MMR6<"seleqz.d", 1, 0b000111000>; -class SELENZ_S_MMR6_ENC : POOL32F_SEL_FM_MMR6<"selenz.s", 0, 0b001111000>; -class SELENZ_D_MMR6_ENC : POOL32F_SEL_FM_MMR6<"selenz.d", 1, 0b001111000>; +class SELNEZ_S_MMR6_ENC : POOL32F_SEL_FM_MMR6<"selnez.s", 0, 0b001111000>; +class SELNEZ_D_MMR6_ENC : POOL32F_SEL_FM_MMR6<"selnez.d", 1, 0b001111000>; class CLASS_S_MMR6_ENC : POOL32F_CLASS_FM_MMR6<"class.s", 0, 0b001100000>; class CLASS_D_MMR6_ENC : POOL32F_CLASS_FM_MMR6<"class.d", 1, 0b001100000>; - +class EXT_MMR6_ENC : POOL32A_EXT_INS_FM_MMR6<"ext", 0b101100>; +class INS_MMR6_ENC : POOL32A_EXT_INS_FM_MMR6<"ins", 0b001100>; +class JALRC_MMR6_ENC : POOL32A_JALRC_FM_MMR6<"jalrc", 0b0000111100>; +class BOVC_MMR6_ENC : POP35_BOVC_FM_MMR6<"bovc">; +class BNVC_MMR6_ENC : POP37_BNVC_FM_MMR6<"bnvc">; class ADDU16_MMR6_ENC : POOL16A_ADDU16_FM_MMR6; class AND16_MMR6_ENC : POOL16C_AND16_FM_MMR6; class ANDI16_MMR6_ENC : ANDI_FM_MM16<0b001011>, MicroMipsR6Inst16; @@ -168,10 +215,24 @@ class MOVE16_MMR6_ENC : MOVE_FM_MM16<0b000011>; class SDBBP16_MMR6_ENC : POOL16C_BREAKPOINT_FM_MMR6<0b111011>; class SUBU16_MMR6_ENC : POOL16A_SUBU16_FM_MMR6; class XOR16_MMR6_ENC : POOL16C_OR16_XOR16_FM_MMR6<0b1000>; +class TLBINV_MMR6_ENC : POOL32A_TLBINV_FM_MMR6<"tlbinv", 0x10d>; +class TLBINVF_MMR6_ENC : POOL32A_TLBINV_FM_MMR6<"tlbinvf", 0x14d>; +class DVP_MMR6_ENC : POOL32A_DVPEVP_FM_MMR6<"dvp", 0b0001100101>; +class EVP_MMR6_ENC : POOL32A_DVPEVP_FM_MMR6<"evp", 0b0011100101>; +class BC1EQZC_MMR6_ENC : POOL32I_BRANCH_COP_1_2_FM_MMR6<"bc1eqzc", 0b01000>; +class BC1NEZC_MMR6_ENC : POOL32I_BRANCH_COP_1_2_FM_MMR6<"bc1nezc", 0b01001>; +class BC2EQZC_MMR6_ENC : POOL32I_BRANCH_COP_1_2_FM_MMR6<"bc2eqzc", 0b01010>; +class BC2NEZC_MMR6_ENC : POOL32I_BRANCH_COP_1_2_FM_MMR6<"bc2nezc", 0b01011>; +class LDC1_MMR6_ENC : LDWC1_SDWC1_FM_MMR6<"ldc1", 0b101111>; +class SDC1_MMR6_ENC : LDWC1_SDWC1_FM_MMR6<"sdc1", 0b101110>; +class LDC2_MMR6_ENC : POOL32B_LDWC2_SDWC2_FM_MMR6<"ldc2", 0b0010>; +class SDC2_MMR6_ENC : POOL32B_LDWC2_SDWC2_FM_MMR6<"sdc2", 0b1010>; +class LWC2_MMR6_ENC : POOL32B_LDWC2_SDWC2_FM_MMR6<"lwc2", 0b0000>; +class SWC2_MMR6_ENC : POOL32B_LDWC2_SDWC2_FM_MMR6<"swc2", 0b1000>; class CMP_CBR_RT_Z_MMR6_DESC_BASE<string instr_asm, DAGOperand opnd, RegisterOperand GPROpnd> - : BRANCH_DESC_BASE, MMR6Arch<instr_asm> { + : BRANCH_DESC_BASE { dag InOperandList = (ins GPROpnd:$rt, opnd:$offset); dag OutOperandList = (outs); string AsmString = !strconcat(instr_asm, "\t$rt, $offset"); @@ -208,6 +269,27 @@ class BNEZALC_MMR6_DESC : CMP_CBR_RT_Z_MMR6_DESC_BASE<"bnezalc", brtarget_mm, list<Register> Defs = [RA]; } +class CMP_CBR_2R_MMR6_DESC_BASE<string instr_asm, DAGOperand opnd, + RegisterOperand GPROpnd> : BRANCH_DESC_BASE { + dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt, opnd:$offset); + dag OutOperandList = (outs); + string AsmString = !strconcat(instr_asm, "\t$rs, $rt, $offset"); + list<Register> Defs = [AT]; +} + +class BGEC_MMR6_DESC : CMP_CBR_2R_MMR6_DESC_BASE<"bgec", brtarget_mm, + GPR32Opnd>; +class BGEUC_MMR6_DESC : CMP_CBR_2R_MMR6_DESC_BASE<"bgeuc", brtarget_mm, + GPR32Opnd>; +class BLTC_MMR6_DESC : CMP_CBR_2R_MMR6_DESC_BASE<"bltc", brtarget_mm, + GPR32Opnd>; +class BLTUC_MMR6_DESC : CMP_CBR_2R_MMR6_DESC_BASE<"bltuc", brtarget_mm, + GPR32Opnd>; +class BEQC_MMR6_DESC : CMP_CBR_2R_MMR6_DESC_BASE<"beqc", brtarget_mm, + GPR32Opnd>; +class BNEC_MMR6_DESC : CMP_CBR_2R_MMR6_DESC_BASE<"bnec", brtarget_mm, + GPR32Opnd>; + /// Floating Point Instructions class FADD_S_MMR6_ENC : POOL32F_ARITH_FM_MMR6<"add.s", 0, 0b00110000>; class FADD_D_MMR6_ENC : POOL32F_ARITH_FM_MMR6<"add.d", 1, 0b00110000>; @@ -252,12 +334,12 @@ class CVT_S_L_MMR6_ENC : POOL32F_CVT_DS_FM<"cvt.s.l", 2, 0b1101101>; //===----------------------------------------------------------------------===// class ADD_MMR6_DESC : ArithLogicR<"add", GPR32Opnd>; -class ADDIU_MMR6_DESC : ArithLogicI<"addiu", simm16, GPR32Opnd>; +class ADDIU_MMR6_DESC : ArithLogicI<"addiu", simm16, GPR32Opnd, II_ADDIU, immSExt16, add>; 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 MUL_MMR6_DESC : ArithLogicR<"mul", GPR32Opnd, 1, II_MUL, mul>; +class MUH_MMR6_DESC : ArithLogicR<"muh", GPR32Opnd, 1, II_MUH, mulhs>; +class MULU_MMR6_DESC : ArithLogicR<"mulu", GPR32Opnd, 1, II_MULU>; +class MUHU_MMR6_DESC : ArithLogicR<"muhu", GPR32Opnd, 1, II_MUHU, mulhu>; class BC_MMR6_DESC_BASE<string instr_asm, DAGOperand opnd> : BRANCH_DESC_BASE, MMR6Arch<instr_asm> { @@ -476,6 +558,32 @@ class PCREL_MMR6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, 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 LWP_MMR6_DESC : MMR6Arch<"lwp"> { + dag OutOperandList = (outs regpair:$rd); + dag InOperandList = (ins mem_simm12:$addr); + string AsmString = !strconcat("lwp", "\t$rd, $addr"); + list<dag> Pattern = []; + InstrItinClass Itin = NoItinerary; + ComplexPattern Addr = addr; + Format f = FrmI; + string BaseOpcode = "lwp"; + string DecoderMethod = "DecodeMemMMImm12"; + bit mayLoad = 1; +} + +class SWP_MMR6_DESC : MMR6Arch<"swp"> { + dag OutOperandList = (outs); + dag InOperandList = (ins regpair:$rd, mem_simm12:$addr); + string AsmString = !strconcat("swp", "\t$rd, $addr"); + list<dag> Pattern = []; + InstrItinClass Itin = NoItinerary; + ComplexPattern Addr = addr; + Format f = FrmI; + string BaseOpcode = "swp"; + string DecoderMethod = "DecodeMemMMImm12"; + bit mayStore = 1; +} + class SELEQNE_Z_MMR6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> : MMR6Arch<instr_asm> { dag OutOperandList = (outs GPROpnd:$rd); @@ -499,17 +607,38 @@ class RDHWR_MMR6_DESC : MMR6Arch<"rdhwr">, MipsR6Inst { class WAIT_MMR6_DESC : WaitMM<"wait">; class SSNOP_MMR6_DESC : Barrier<"ssnop">; class SLL_MMR6_DESC : shift_rotate_imm<"sll", uimm5, GPR32Opnd, II_SLL>; -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>; + +class DIVMOD_MMR6_DESC_BASE<string opstr, RegisterOperand GPROpnd, + SDPatternOperator OpNode=null_frag> + : MipsR6Inst { + dag OutOperandList = (outs GPROpnd:$rd); + dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt); + string AsmString = !strconcat(opstr, "\t$rd, $rs, $rt"); + list<dag> Pattern = [(set GPROpnd:$rd, (OpNode GPROpnd:$rs, GPROpnd:$rt))]; + string BaseOpcode = opstr; + Format f = FrmR; + let isCommutable = 0; + let isReMaterializable = 1; + + // This instruction doesn't trap division by zero itself. We must insert + // teq instructions as well. + bit usesCustomInserter = 1; +} +class DIV_MMR6_DESC : DIVMOD_MMR6_DESC_BASE<"div", GPR32Opnd, sdiv>; +class DIVU_MMR6_DESC : DIVMOD_MMR6_DESC_BASE<"divu", GPR32Opnd, udiv>; +class MOD_MMR6_DESC : DIVMOD_MMR6_DESC_BASE<"mod", GPR32Opnd, srem>; +class MODU_MMR6_DESC : DIVMOD_MMR6_DESC_BASE<"modu", GPR32Opnd, urem>; +class AND_MMR6_DESC : ArithLogicR<"and", GPR32Opnd, 1, II_AND, and>; +class ANDI_MMR6_DESC : ArithLogicI<"andi", uimm16, GPR32Opnd, II_ANDI>; +class NOR_MMR6_DESC : LogicNOR<"nor", GPR32Opnd>; +class OR_MMR6_DESC : ArithLogicR<"or", GPR32Opnd, 1, II_OR, or>; +class ORI_MMR6_DESC : ArithLogicI<"ori", uimm16, GPR32Opnd, II_ORI, immZExt16, + or> { + int AddedComplexity = 1; +} +class XOR_MMR6_DESC : ArithLogicR<"xor", GPR32Opnd, 1, II_XOR, xor>; +class XORI_MMR6_DESC : ArithLogicI<"xori", uimm16, GPR32Opnd, II_XORI, + immZExt16, xor>; class SWE_MMR6_DESC_BASE<string opstr, DAGOperand RO, DAGOperand MO, SDPatternOperator OpNode = null_frag, @@ -536,6 +665,155 @@ class WRPGPR_WSBH_MMR6_DESC_BASE<string instr_asm, RegisterOperand RO> class WRPGPR_MMR6_DESC : WRPGPR_WSBH_MMR6_DESC_BASE<"wrpgpr", GPR32Opnd>; class WSBH_MMR6_DESC : WRPGPR_WSBH_MMR6_DESC_BASE<"wsbh", GPR32Opnd>; +class MTC0_MMR6_DESC_BASE<string opstr, RegisterOperand DstRC, + RegisterOperand SrcRC> { + dag InOperandList = (ins SrcRC:$rt, uimm3:$sel); + dag OutOperandList = (outs DstRC:$rs); + string AsmString = !strconcat(opstr, "\t$rt, $rs, $sel"); + list<dag> Pattern = []; + Format f = FrmFR; + string BaseOpcode = opstr; +} +class MTC1_MMR6_DESC_BASE< + string opstr, RegisterOperand DstRC, RegisterOperand SrcRC, + InstrItinClass Itin = NoItinerary, SDPatternOperator OpNode = null_frag> + : MipsR6Inst { + dag InOperandList = (ins SrcRC:$rt); + dag OutOperandList = (outs DstRC:$fs); + string AsmString = !strconcat(opstr, "\t$rt, $fs"); + list<dag> Pattern = [(set DstRC:$fs, (OpNode SrcRC:$rt))]; + Format f = FrmFR; + InstrItinClass Itinerary = Itin; + string BaseOpcode = opstr; +} +class MTC1_64_MMR6_DESC_BASE< + string opstr, RegisterOperand DstRC, RegisterOperand SrcRC, + InstrItinClass Itin = NoItinerary> : MipsR6Inst { + dag InOperandList = (ins DstRC:$fs_in, SrcRC:$rt); + dag OutOperandList = (outs DstRC:$fs); + string AsmString = !strconcat(opstr, "\t$rt, $fs"); + list<dag> Pattern = []; + Format f = FrmFR; + InstrItinClass Itinerary = Itin; + string BaseOpcode = opstr; + // $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"; +} +class MTC2_MMR6_DESC_BASE<string opstr, RegisterOperand DstRC, + RegisterOperand SrcRC> { + dag InOperandList = (ins SrcRC:$rt); + dag OutOperandList = (outs DstRC:$impl); + string AsmString = !strconcat(opstr, "\t$rt, $impl"); + list<dag> Pattern = []; + Format f = FrmFR; + string BaseOpcode = opstr; +} + +class MTC0_MMR6_DESC : MTC0_MMR6_DESC_BASE<"mtc0", COP0Opnd, GPR32Opnd>; +class MTC1_MMR6_DESC : MTC1_MMR6_DESC_BASE<"mtc1", FGR32Opnd, GPR32Opnd, + II_MTC1, bitconvert>, HARDFLOAT; +class MTC2_MMR6_DESC : MTC2_MMR6_DESC_BASE<"mtc2", COP2Opnd, GPR32Opnd>; +class MTHC0_MMR6_DESC : MTC0_MMR6_DESC_BASE<"mthc0", COP0Opnd, GPR32Opnd>; +class MTHC1_D32_MMR6_DESC : MTC1_64_MMR6_DESC_BASE<"mthc1", AFGR64Opnd, GPR32Opnd>, + HARDFLOAT, FGR_32; +class MTHC1_D64_MMR6_DESC : MTC1_64_MMR6_DESC_BASE<"mthc1", FGR64Opnd, GPR32Opnd>, + HARDFLOAT, FGR_64; +class MTHC2_MMR6_DESC : MTC2_MMR6_DESC_BASE<"mthc2", COP2Opnd, GPR32Opnd>; + +class MFC0_MMR6_DESC_BASE<string opstr, RegisterOperand DstRC, + RegisterOperand SrcRC> { + dag InOperandList = (ins SrcRC:$rs, uimm3:$sel); + dag OutOperandList = (outs DstRC:$rt); + string AsmString = !strconcat(opstr, "\t$rt, $rs, $sel"); + list<dag> Pattern = []; + Format f = FrmFR; + string BaseOpcode = opstr; +} +class MFC1_MMR6_DESC_BASE<string opstr, RegisterOperand DstRC, + RegisterOperand SrcRC, + InstrItinClass Itin = NoItinerary, + SDPatternOperator OpNode = null_frag> : MipsR6Inst { + dag InOperandList = (ins SrcRC:$fs); + dag OutOperandList = (outs DstRC:$rt); + string AsmString = !strconcat(opstr, "\t$rt, $fs"); + list<dag> Pattern = [(set DstRC:$rt, (OpNode SrcRC:$fs))]; + Format f = FrmFR; + InstrItinClass Itinerary = Itin; + string BaseOpcode = opstr; +} +class MFC2_MMR6_DESC_BASE<string opstr, RegisterOperand DstRC, + RegisterOperand SrcRC> { + dag InOperandList = (ins SrcRC:$impl); + dag OutOperandList = (outs DstRC:$rt); + string AsmString = !strconcat(opstr, "\t$rt, $impl"); + list<dag> Pattern = []; + Format f = FrmFR; + string BaseOpcode = opstr; +} +class MFC0_MMR6_DESC : MFC0_MMR6_DESC_BASE<"mfc0", GPR32Opnd, COP0Opnd>; +class MFC1_MMR6_DESC : MFC1_MMR6_DESC_BASE<"mfc1", GPR32Opnd, FGR32Opnd, + II_MFC1, bitconvert>, HARDFLOAT; +class MFC2_MMR6_DESC : MFC2_MMR6_DESC_BASE<"mfc2", GPR32Opnd, COP2Opnd>; +class MFHC0_MMR6_DESC : MFC0_MMR6_DESC_BASE<"mfhc0", GPR32Opnd, COP0Opnd>; +class MFHC1_D32_MMR6_DESC : MFC1_MMR6_DESC_BASE<"mfhc1", GPR32Opnd, AFGR64Opnd, + II_MFHC1>, HARDFLOAT, FGR_32; +class MFHC1_D64_MMR6_DESC : MFC1_MMR6_DESC_BASE<"mfhc1", GPR32Opnd, FGR64Opnd, + II_MFHC1>, HARDFLOAT, FGR_64; +class MFHC2_MMR6_DESC : MFC2_MMR6_DESC_BASE<"mfhc2", GPR32Opnd, COP2Opnd>; + +class LDC1_D64_MMR6_DESC : MipsR6Inst, HARDFLOAT, FGR_64 { + dag InOperandList = (ins mem_mm_16:$addr); + dag OutOperandList = (outs FGR64Opnd:$ft); + string AsmString = !strconcat("ldc1", "\t$ft, $addr"); + list<dag> Pattern = [(set FGR64Opnd:$ft, (load addrimm16:$addr))]; + Format f = FrmFI; + InstrItinClass Itinerary = II_LDC1; + string BaseOpcode = "ldc1"; + bit mayLoad = 1; + let DecoderMethod = "DecodeFMemMMR2"; +} + +class SDC1_D64_MMR6_DESC : MipsR6Inst, HARDFLOAT, FGR_64 { + dag InOperandList = (ins FGR64Opnd:$ft, mem_mm_16:$addr); + dag OutOperandList = (outs); + string AsmString = !strconcat("sdc1", "\t$ft, $addr"); + list<dag> Pattern = [(store FGR64Opnd:$ft, addrimm16:$addr)]; + Format f = FrmFI; + InstrItinClass Itinerary = II_SDC1; + string BaseOpcode = "sdc1"; + bit mayStore = 1; + let DecoderMethod = "DecodeFMemMMR2"; +} + +class LDC2_LWC2_MMR6_DESC_BASE<string opstr> { + dag OutOperandList = (outs COP2Opnd:$rt); + dag InOperandList = (ins mem_mm_11:$addr); + string AsmString = !strconcat(opstr, "\t$rt, $addr"); + list<dag> Pattern = [(set COP2Opnd:$rt, (load addrimm11:$addr))]; + Format f = FrmFI; + InstrItinClass Itinerary = NoItinerary; + string BaseOpcode = opstr; + bit mayLoad = 1; + string DecoderMethod = "DecodeFMemCop2MMR6"; +} +class LDC2_MMR6_DESC : LDC2_LWC2_MMR6_DESC_BASE<"ldc2">; +class LWC2_MMR6_DESC : LDC2_LWC2_MMR6_DESC_BASE<"lwc2">; + +class SDC2_SWC2_MMR6_DESC_BASE<string opstr> { + dag OutOperandList = (outs); + dag InOperandList = (ins COP2Opnd:$rt, mem_mm_11:$addr); + string AsmString = !strconcat(opstr, "\t$rt, $addr"); + list<dag> Pattern = [(store COP2Opnd:$rt, addrimm11:$addr)]; + Format f = FrmFI; + InstrItinClass Itinerary = NoItinerary; + string BaseOpcode = opstr; + bit mayStore = 1; + string DecoderMethod = "DecodeFMemCop2MMR6"; +} +class SDC2_MMR6_DESC : SDC2_SWC2_MMR6_DESC_BASE<"sdc2">; +class SWC2_MMR6_DESC : SDC2_SWC2_MMR6_DESC_BASE<"swc2">; + /// Floating Point Instructions class FARITH_MMR6_DESC_BASE<string instr_asm, RegisterOperand RC, InstrItinClass Itin, bit isComm, @@ -633,69 +911,69 @@ class CVT_S_L_MMR6_DESC : CVT_MMR6_DESC_BASE<"cvt.s.l", FGR64Opnd, FGR32Opnd, multiclass CMP_CC_MMR6<bits<6> format, string Typestr, RegisterOperand FGROpnd> { - def CMP_AF_#NAME : POOL32F_CMP_FM< + def CMP_AF_#NAME : R6MMR6Rel, POOL32F_CMP_FM< !strconcat("cmp.af.", Typestr), format, FIELD_CMP_COND_AF>, - CMP_CONDN_DESC_BASE<"af", Typestr, FGROpnd>, HARDFLOAT, R6MMR6Rel, + CMP_CONDN_DESC_BASE<"af", Typestr, FGROpnd>, HARDFLOAT, ISA_MICROMIPS32R6; - def CMP_UN_#NAME : POOL32F_CMP_FM< + def CMP_UN_#NAME : R6MMR6Rel, POOL32F_CMP_FM< !strconcat("cmp.un.", Typestr), format, FIELD_CMP_COND_UN>, - CMP_CONDN_DESC_BASE<"un", Typestr, FGROpnd>, HARDFLOAT, R6MMR6Rel, + CMP_CONDN_DESC_BASE<"un", Typestr, FGROpnd, setuo>, HARDFLOAT, ISA_MICROMIPS32R6; - def CMP_EQ_#NAME : POOL32F_CMP_FM< + def CMP_EQ_#NAME : R6MMR6Rel, POOL32F_CMP_FM< !strconcat("cmp.eq.", Typestr), format, FIELD_CMP_COND_EQ>, - CMP_CONDN_DESC_BASE<"eq", Typestr, FGROpnd>, HARDFLOAT, R6MMR6Rel, + CMP_CONDN_DESC_BASE<"eq", Typestr, FGROpnd, setoeq>, HARDFLOAT, ISA_MICROMIPS32R6; - def CMP_UEQ_#NAME : POOL32F_CMP_FM< + def CMP_UEQ_#NAME : R6MMR6Rel, POOL32F_CMP_FM< !strconcat("cmp.ueq.", Typestr), format, FIELD_CMP_COND_UEQ>, - CMP_CONDN_DESC_BASE<"ueq", Typestr, FGROpnd>, HARDFLOAT, R6MMR6Rel, + CMP_CONDN_DESC_BASE<"ueq", Typestr, FGROpnd, setueq>, HARDFLOAT, ISA_MICROMIPS32R6; - def CMP_LT_#NAME : POOL32F_CMP_FM< + def CMP_LT_#NAME : R6MMR6Rel, POOL32F_CMP_FM< !strconcat("cmp.lt.", Typestr), format, FIELD_CMP_COND_LT>, - CMP_CONDN_DESC_BASE<"lt", Typestr, FGROpnd>, HARDFLOAT, R6MMR6Rel, + CMP_CONDN_DESC_BASE<"lt", Typestr, FGROpnd, setolt>, HARDFLOAT, ISA_MICROMIPS32R6; - def CMP_ULT_#NAME : POOL32F_CMP_FM< + def CMP_ULT_#NAME : R6MMR6Rel, POOL32F_CMP_FM< !strconcat("cmp.ult.", Typestr), format, FIELD_CMP_COND_ULT>, - CMP_CONDN_DESC_BASE<"ult", Typestr, FGROpnd>, HARDFLOAT, R6MMR6Rel, + CMP_CONDN_DESC_BASE<"ult", Typestr, FGROpnd, setult>, HARDFLOAT, ISA_MICROMIPS32R6; - def CMP_LE_#NAME : POOL32F_CMP_FM< + def CMP_LE_#NAME : R6MMR6Rel, POOL32F_CMP_FM< !strconcat("cmp.le.", Typestr), format, FIELD_CMP_COND_LE>, - CMP_CONDN_DESC_BASE<"le", Typestr, FGROpnd>, HARDFLOAT, R6MMR6Rel, + CMP_CONDN_DESC_BASE<"le", Typestr, FGROpnd, setole>, HARDFLOAT, ISA_MICROMIPS32R6; - def CMP_ULE_#NAME : POOL32F_CMP_FM< + def CMP_ULE_#NAME : R6MMR6Rel, POOL32F_CMP_FM< !strconcat("cmp.ule.", Typestr), format, FIELD_CMP_COND_ULE>, - CMP_CONDN_DESC_BASE<"ule", Typestr, FGROpnd>, HARDFLOAT, R6MMR6Rel, + CMP_CONDN_DESC_BASE<"ule", Typestr, FGROpnd, setule>, HARDFLOAT, ISA_MICROMIPS32R6; - def CMP_SAF_#NAME : POOL32F_CMP_FM< + def CMP_SAF_#NAME : R6MMR6Rel, POOL32F_CMP_FM< !strconcat("cmp.saf.", Typestr), format, FIELD_CMP_COND_SAF>, - CMP_CONDN_DESC_BASE<"saf", Typestr, FGROpnd>, HARDFLOAT, R6MMR6Rel, + CMP_CONDN_DESC_BASE<"saf", Typestr, FGROpnd>, HARDFLOAT, ISA_MICROMIPS32R6; - def CMP_SUN_#NAME : POOL32F_CMP_FM< + def CMP_SUN_#NAME : R6MMR6Rel, POOL32F_CMP_FM< !strconcat("cmp.sun.", Typestr), format, FIELD_CMP_COND_SUN>, - CMP_CONDN_DESC_BASE<"sun", Typestr, FGROpnd>, HARDFLOAT, R6MMR6Rel, + CMP_CONDN_DESC_BASE<"sun", Typestr, FGROpnd>, HARDFLOAT, ISA_MICROMIPS32R6; - def CMP_SEQ_#NAME : POOL32F_CMP_FM< + def CMP_SEQ_#NAME : R6MMR6Rel, POOL32F_CMP_FM< !strconcat("cmp.seq.", Typestr), format, FIELD_CMP_COND_SEQ>, - CMP_CONDN_DESC_BASE<"seq", Typestr, FGROpnd>, HARDFLOAT, R6MMR6Rel, + CMP_CONDN_DESC_BASE<"seq", Typestr, FGROpnd>, HARDFLOAT, ISA_MICROMIPS32R6; - def CMP_SUEQ_#NAME : POOL32F_CMP_FM< + def CMP_SUEQ_#NAME : R6MMR6Rel, POOL32F_CMP_FM< !strconcat("cmp.sueq.", Typestr), format, FIELD_CMP_COND_SUEQ>, - CMP_CONDN_DESC_BASE<"sueq", Typestr, FGROpnd>, HARDFLOAT, R6MMR6Rel, + CMP_CONDN_DESC_BASE<"sueq", Typestr, FGROpnd>, HARDFLOAT, ISA_MICROMIPS32R6; - def CMP_SLT_#NAME : POOL32F_CMP_FM< + def CMP_SLT_#NAME : R6MMR6Rel, POOL32F_CMP_FM< !strconcat("cmp.slt.", Typestr), format, FIELD_CMP_COND_SLT>, - CMP_CONDN_DESC_BASE<"slt", Typestr, FGROpnd>, HARDFLOAT, R6MMR6Rel, + CMP_CONDN_DESC_BASE<"slt", Typestr, FGROpnd>, HARDFLOAT, ISA_MICROMIPS32R6; - def CMP_SULT_#NAME : POOL32F_CMP_FM< + def CMP_SULT_#NAME : R6MMR6Rel, POOL32F_CMP_FM< !strconcat("cmp.sult.", Typestr), format, FIELD_CMP_COND_SULT>, - CMP_CONDN_DESC_BASE<"sult", Typestr, FGROpnd>, HARDFLOAT, R6MMR6Rel, + CMP_CONDN_DESC_BASE<"sult", Typestr, FGROpnd>, HARDFLOAT, ISA_MICROMIPS32R6; - def CMP_SLE_#NAME : POOL32F_CMP_FM< + def CMP_SLE_#NAME : R6MMR6Rel, POOL32F_CMP_FM< !strconcat("cmp.sle.", Typestr), format, FIELD_CMP_COND_SLE>, - CMP_CONDN_DESC_BASE<"sle", Typestr, FGROpnd>, HARDFLOAT, R6MMR6Rel, + CMP_CONDN_DESC_BASE<"sle", Typestr, FGROpnd>, HARDFLOAT, ISA_MICROMIPS32R6; - def CMP_SULE_#NAME : POOL32F_CMP_FM< + def CMP_SULE_#NAME : R6MMR6Rel, POOL32F_CMP_FM< !strconcat("cmp.sule.", Typestr), format, FIELD_CMP_COND_SULE>, - CMP_CONDN_DESC_BASE<"sule", Typestr, FGROpnd>, HARDFLOAT, R6MMR6Rel, + CMP_CONDN_DESC_BASE<"sule", Typestr, FGROpnd>, HARDFLOAT, ISA_MICROMIPS32R6; } @@ -769,8 +1047,8 @@ class SEL_D_MMR6_DESC : COP1_SEL_DESC_BASE<"sel.d", FGR64Opnd> { class SELEQZ_S_MMR6_DESC : SELEQNEZ_DESC_BASE<"seleqz.s", FGR32Opnd>; class SELEQZ_D_MMR6_DESC : SELEQNEZ_DESC_BASE<"seleqz.d", FGR64Opnd>; -class SELENZ_S_MMR6_DESC : SELEQNEZ_DESC_BASE<"selnez.s", FGR32Opnd>; -class SELENZ_D_MMR6_DESC : SELEQNEZ_DESC_BASE<"selnez.d", FGR64Opnd>; +class SELNEZ_S_MMR6_DESC : SELEQNEZ_DESC_BASE<"selnez.s", FGR32Opnd>; +class SELNEZ_D_MMR6_DESC : SELEQNEZ_DESC_BASE<"selnez.d", FGR64Opnd>; class RINT_S_MMR6_DESC : CLASS_RINT_DESC_BASE<"rint.s", FGR32Opnd>; class RINT_D_MMR6_DESC : CLASS_RINT_DESC_BASE<"rint.d", FGR64Opnd>; class CLASS_S_MMR6_DESC : CLASS_RINT_DESC_BASE<"class.s", FGR32Opnd>; @@ -785,7 +1063,7 @@ class SB_MMR6_DESC : STORE_MMR6_DESC_BASE<"sb", GPR32Opnd>; class STORE_EVA_MMR6_DESC_BASE<string instr_asm, RegisterOperand RO> : MMR6Arch<instr_asm>, MipsR6Inst { dag OutOperandList = (outs); - dag InOperandList = (ins RO:$rt, mem_mm_9:$addr); + dag InOperandList = (ins RO:$rt, mem_simm9:$addr); string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); string DecoderMethod = "DecodeStoreEvaOpMM"; bit mayStore = 1; @@ -797,7 +1075,7 @@ class SHE_MMR6_DESC : STORE_EVA_MMR6_DESC_BASE<"she", GPR32Opnd>; class LOAD_WORD_EVA_MMR6_DESC_BASE<string instr_asm, RegisterOperand RO> : MMR6Arch<instr_asm>, MipsR6Inst { dag OutOperandList = (outs RO:$rt); - dag InOperandList = (ins mem_mm_12:$addr); + dag InOperandList = (ins mem_simm9:$addr); string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); string DecoderMethod = "DecodeMemMMImm9"; bit mayLoad = 1; @@ -805,30 +1083,42 @@ class LOAD_WORD_EVA_MMR6_DESC_BASE<string instr_asm, RegisterOperand RO> : class LLE_MMR6_DESC : LOAD_WORD_EVA_MMR6_DESC_BASE<"lle", GPR32Opnd>; class LWE_MMR6_DESC : LOAD_WORD_EVA_MMR6_DESC_BASE<"lwe", GPR32Opnd>; class ADDU16_MMR6_DESC : ArithRMM16<"addu16", GPRMM16Opnd, 1, II_ADDU, add>, - MMR6Arch<"addu16">; + MMR6Arch<"addu16"> { + int AddedComplexity = 1; +} class AND16_MMR6_DESC : LogicRMM16<"and16", GPRMM16Opnd, II_AND, and>, - MMR6Arch<"and16">; + MMR6Arch<"and16"> { + int AddedComplexity = 1; +} class ANDI16_MMR6_DESC : AndImmMM16<"andi16", GPRMM16Opnd, II_AND>, MMR6Arch<"andi16">; -class NOT16_MMR6_DESC : NotMM16<"not16", GPRMM16Opnd>, MMR6Arch<"not16">; +class NOT16_MMR6_DESC : NotMM16<"not16", GPRMM16Opnd>, MMR6Arch<"not16"> { + int AddedComplexity = 1; +} class OR16_MMR6_DESC : LogicRMM16<"or16", GPRMM16Opnd, II_OR, or>, - MMR6Arch<"or16">; + MMR6Arch<"or16"> { + int AddedComplexity = 1; +} class SLL16_MMR6_DESC : ShiftIMM16<"sll16", uimm3_shift, GPRMM16Opnd, II_SLL>, MMR6Arch<"sll16">; class SRL16_MMR6_DESC : ShiftIMM16<"srl16", uimm3_shift, GPRMM16Opnd, II_SRL>, MMR6Arch<"srl16">; -class BREAK16_MMR6_DESC : BrkSdbbp16MM<"break16">, MMR6Arch<"srl16">, +class BREAK16_MMR6_DESC : BrkSdbbp16MM<"break16">, MMR6Arch<"break16">, MicroMipsR6Inst16; -class LI16_MMR6_DESC : LoadImmMM16<"li16", li_simm7, GPRMM16Opnd>, - MMR6Arch<"srl16">, MicroMipsR6Inst16, IsAsCheapAsAMove; -class MOVE16_MMR6_DESC : MoveMM16<"move16", GPR32Opnd>, MMR6Arch<"srl16">, +class LI16_MMR6_DESC : LoadImmMM16<"li16", li16_imm, GPRMM16Opnd>, + MMR6Arch<"li16">, MicroMipsR6Inst16, IsAsCheapAsAMove; +class MOVE16_MMR6_DESC : MoveMM16<"move16", GPR32Opnd>, MMR6Arch<"move16">, MicroMipsR6Inst16; class SDBBP16_MMR6_DESC : BrkSdbbp16MM<"sdbbp16">, MMR6Arch<"sdbbp16">, MicroMipsR6Inst16; class SUBU16_MMR6_DESC : ArithRMM16<"subu16", GPRMM16Opnd, 0, II_SUBU, sub>, - MMR6Arch<"sdbbp16">, MicroMipsR6Inst16; + MMR6Arch<"subu16">, MicroMipsR6Inst16 { + int AddedComplexity = 1; +} class XOR16_MMR6_DESC : LogicRMM16<"xor16", GPRMM16Opnd, II_XOR, xor>, - MMR6Arch<"sdbbp16">, MicroMipsR6Inst16; + MMR6Arch<"xor16"> { + int AddedComplexity = 1; +} class LW_MMR6_DESC : MMR6Arch<"lw">, MipsR6Inst { dag OutOperandList = (outs GPR32Opnd:$rt); @@ -854,9 +1144,9 @@ class LUI_MMR6_DESC : IsAsCheapAsAMove, MMR6Arch<"lui">, MipsR6Inst{ class SYNC_MMR6_DESC : MMR6Arch<"sync">, MipsR6Inst { dag OutOperandList = (outs); - dag InOperandList = (ins i32imm:$stype); + dag InOperandList = (ins uimm5:$stype); string AsmString = !strconcat("sync", "\t$stype"); - list<dag> Pattern = [(MipsSync imm:$stype)]; + list<dag> Pattern = [(MipsSync immZExt5:$stype)]; InstrItinClass Itinerary = NoItinerary; bit HasSideEffects = 1; } @@ -924,6 +1214,111 @@ class SWSP_MMR6_DESC let mayStore = 1; } +class JALRC_HB_MMR6_DESC { + dag OutOperandList = (outs GPR32Opnd:$rt); + dag InOperandList = (ins GPR32Opnd:$rs); + string AsmString = !strconcat("jalrc.hb", "\t$rt, $rs"); + list<dag> Pattern = []; + InstrItinClass Itinerary = NoItinerary; + Format Form = FrmJ; + bit isIndirectBranch = 1; + bit hasDelaySlot = 0; +} + +class TLBINV_MMR6_DESC_BASE<string opstr> { + dag OutOperandList = (outs); + dag InOperandList = (ins); + string AsmString = opstr; + list<dag> Pattern = []; +} + +class TLBINV_MMR6_DESC : TLBINV_MMR6_DESC_BASE<"tlbinv">; +class TLBINVF_MMR6_DESC : TLBINV_MMR6_DESC_BASE<"tlbinvf">; + +class DVPEVP_MMR6_DESC_BASE<string opstr> { + dag OutOperandList = (outs); + dag InOperandList = (ins GPR32Opnd:$rs); + string AsmString = !strconcat(opstr, "\t$rs"); + list<dag> Pattern = []; +} + +class DVP_MMR6_DESC : DVPEVP_MMR6_DESC_BASE<"dvp">; +class EVP_MMR6_DESC : DVPEVP_MMR6_DESC_BASE<"evp">; + +class BEQZC_MMR6_DESC + : CMP_CBR_EQNE_Z_DESC_BASE<"beqzc", brtarget21_mm, GPR32Opnd>, + MMR6Arch<"beqzc">; +class BNEZC_MMR6_DESC + : CMP_CBR_EQNE_Z_DESC_BASE<"bnezc", brtarget21_mm, GPR32Opnd>, + MMR6Arch<"bnezc">; + +class BRANCH_COP1_MMR6_DESC_BASE<string opstr> : + InstSE<(outs), (ins FGR64Opnd:$rt, brtarget_mm:$offset), + !strconcat(opstr, "\t$rt, $offset"), [], II_BC1CCZ, FrmI>, + HARDFLOAT, BRANCH_DESC_BASE { + list<Register> Defs = [AT]; +} + +class BC1EQZC_MMR6_DESC : BRANCH_COP1_MMR6_DESC_BASE<"bc1eqzc">; +class BC1NEZC_MMR6_DESC : BRANCH_COP1_MMR6_DESC_BASE<"bc1nezc">; + +class BRANCH_COP2_MMR6_DESC_BASE<string opstr> : BRANCH_DESC_BASE { + dag InOperandList = (ins COP2Opnd:$rt, brtarget_mm:$offset); + dag OutOperandList = (outs); + string AsmString = !strconcat(opstr, "\t$rt, $offset"); + list<Register> Defs = [AT]; +} + +class BC2EQZC_MMR6_DESC : BRANCH_COP2_MMR6_DESC_BASE<"bc2eqzc">; +class BC2NEZC_MMR6_DESC : BRANCH_COP2_MMR6_DESC_BASE<"bc2nezc">; + +class EXT_MMR6_DESC { + dag OutOperandList = (outs GPR32Opnd:$rt); + dag InOperandList = (ins GPR32Opnd:$rs, uimm5:$pos, uimm5_plus1:$size); + string AsmString = !strconcat("ext", "\t$rt, $rs, $pos, $size"); + list<dag> Pattern = [(set GPR32Opnd:$rt, (MipsExt GPR32Opnd:$rs, imm:$pos, + imm:$size))]; + InstrItinClass Itinerary = II_EXT; + Format Form = FrmR; + string BaseOpcode = "ext"; +} + +class INS_MMR6_DESC { + dag OutOperandList = (outs GPR32Opnd:$rt); + dag InOperandList = (ins GPR32Opnd:$rs, uimm5:$pos, uimm5_inssize_plus1:$size, + GPR32Opnd:$src); + string AsmString = !strconcat("ins", "\t$rt, $rs, $pos, $size"); + list<dag> Pattern = [(set GPR32Opnd:$rt, (MipsIns GPR32Opnd:$rs, imm:$pos, + imm:$size, GPR32Opnd:$src))]; + InstrItinClass Itinerary = II_INS; + Format Form = FrmR; + string BaseOpcode = "ins"; + string Constraints = "$src = $rt"; +} + +class JALRC_MMR6_DESC { + dag OutOperandList = (outs GPR32Opnd:$rt); + dag InOperandList = (ins GPR32Opnd:$rs); + string AsmString = !strconcat("jalrc", "\t$rt, $rs"); + list<dag> Pattern = []; + InstrItinClass Itinerary = II_JALRC; + bit isCall = 1; + bit hasDelaySlot = 0; + list<Register> Defs = [RA]; +} + +class BOVC_BNVC_MMR6_DESC_BASE<string instr_asm, Operand opnd, + RegisterOperand GPROpnd> + : BRANCH_DESC_BASE { + dag InOperandList = (ins GPROpnd:$rt, GPROpnd:$rs, opnd:$offset); + dag OutOperandList = (outs); + string AsmString = !strconcat(instr_asm, "\t$rt, $rs, $offset"); + list<Register> Defs = [AT]; +} + +class BOVC_MMR6_DESC : BOVC_BNVC_MMR6_DESC_BASE<"bovc", brtargetr6, GPR32Opnd>; +class BNVC_MMR6_DESC : BOVC_BNVC_MMR6_DESC_BASE<"bnvc", brtargetr6, GPR32Opnd>; + //===----------------------------------------------------------------------===// // // Instruction Definitions @@ -946,22 +1341,18 @@ 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 BC16_MMR6 : StdMMR6Rel, BC16_MMR6_DESC, BC16_MMR6_ENC, ISA_MICROMIPS32R6; +def BEQZC_MMR6 : R6MMR6Rel, BEQZC_MMR6_ENC, BEQZC_MMR6_DESC, + ISA_MICROMIPS32R6; def BEQZC16_MMR6 : StdMMR6Rel, BEQZC16_MMR6_DESC, BEQZC16_MMR6_ENC, ISA_MICROMIPS32R6; +def BNEZC_MMR6 : R6MMR6Rel, BNEZC_MMR6_ENC, BNEZC_MMR6_DESC, + ISA_MICROMIPS32R6; def BNEZC16_MMR6 : StdMMR6Rel, BNEZC16_MMR6_DESC, BNEZC16_MMR6_ENC, 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 BREAK_MMR6 : StdMMR6Rel, BRK_MMR6_DESC, BRK_MMR6_ENC, ISA_MICROMIPS32R6; @@ -985,8 +1376,30 @@ def JRC16_MMR6 : R6MMR6Rel, JRC16_MMR6_DESC, JRC16_MMR6_ENC, ISA_MICROMIPS32R6; def JRCADDIUSP_MMR6 : R6MMR6Rel, JRCADDIUSP_MMR6_DESC, JRCADDIUSP_MMR6_ENC, ISA_MICROMIPS32R6; def LSA_MMR6 : R6MMR6Rel, LSA_MMR6_ENC, LSA_MMR6_DESC, ISA_MICROMIPS32R6; +def LWP_MMR6 : StdMMR6Rel, LWP_MMR6_ENC, LWP_MMR6_DESC, ISA_MICROMIPS32R6; def LWPC_MMR6 : R6MMR6Rel, LWPC_MMR6_ENC, LWPC_MMR6_DESC, ISA_MICROMIPS32R6; def LWM16_MMR6 : StdMMR6Rel, LWM16_MMR6_DESC, LWM16_MMR6_ENC, ISA_MICROMIPS32R6; +def MTC0_MMR6 : StdMMR6Rel, MTC0_MMR6_ENC, MTC0_MMR6_DESC, ISA_MICROMIPS32R6; +def MTC1_MMR6 : StdMMR6Rel, MTC1_MMR6_DESC, MTC1_MMR6_ENC, ISA_MICROMIPS32R6; +def MTC2_MMR6 : StdMMR6Rel, MTC2_MMR6_ENC, MTC2_MMR6_DESC, ISA_MICROMIPS32R6; +def MTHC0_MMR6 : R6MMR6Rel, MTHC0_MMR6_ENC, MTHC0_MMR6_DESC, ISA_MICROMIPS32R6; +def MTHC1_D32_MMR6 : StdMMR6Rel, MTHC1_D32_MMR6_DESC, MTHC1_MMR6_ENC, ISA_MICROMIPS32R6; +let DecoderNamespace = "MicroMips32r6FP64" in { + def MTHC1_D64_MMR6 : R6MMR6Rel, MTHC1_D64_MMR6_DESC, MTHC1_MMR6_ENC, + ISA_MICROMIPS32R6; +} +def MTHC2_MMR6 : StdMMR6Rel, MTHC2_MMR6_ENC, MTHC2_MMR6_DESC, ISA_MICROMIPS32R6; +def MFC0_MMR6 : StdMMR6Rel, MFC0_MMR6_ENC, MFC0_MMR6_DESC, ISA_MICROMIPS32R6; +def MFC1_MMR6 : StdMMR6Rel, MFC1_MMR6_DESC, MFC1_MMR6_ENC, ISA_MICROMIPS32R6; +def MFC2_MMR6 : StdMMR6Rel, MFC2_MMR6_ENC, MFC2_MMR6_DESC, ISA_MICROMIPS32R6; +def MFHC0_MMR6 : R6MMR6Rel, MFHC0_MMR6_ENC, MFHC0_MMR6_DESC, ISA_MICROMIPS32R6; +def MFHC1_D32_MMR6 : StdMMR6Rel, MFHC1_D32_MMR6_DESC, MFHC1_MMR6_ENC, + ISA_MICROMIPS32R6; +let DecoderNamespace = "MicroMips32r6FP64" in { + def MFHC1_D64_MMR6 : StdMMR6Rel, MFHC1_D64_MMR6_DESC, MFHC1_MMR6_ENC, + ISA_MICROMIPS32R6; +} +def MFHC2_MMR6 : StdMMR6Rel, MFHC2_MMR6_ENC, MFHC2_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; @@ -1011,6 +1424,7 @@ def SUBU_MMR6 : StdMMR6Rel, SUBU_MMR6_DESC, SUBU_MMR6_ENC, ISA_MICROMIPS32R6; def SW16_MMR6 : StdMMR6Rel, SW16_MMR6_DESC, SW16_MMR6_ENC, ISA_MICROMIPS32R6; def SWM16_MMR6 : StdMMR6Rel, SWM16_MMR6_DESC, SWM16_MMR6_ENC, ISA_MICROMIPS32R6; def SWSP_MMR6 : StdMMR6Rel, SWSP_MMR6_DESC, SWSP_MMR6_ENC, ISA_MICROMIPS32R6; +def SWP_MMR6 : StdMMR6Rel, SWP_MMR6_ENC, SWP_MMR6_DESC, ISA_MICROMIPS32R6; def PREFE_MMR6 : StdMMR6Rel, PREFE_MMR6_ENC, PREFE_MMR6_DESC, ISA_MICROMIPS32R6; def CACHEE_MMR6 : StdMMR6Rel, CACHEE_MMR6_ENC, CACHEE_MMR6_DESC, ISA_MICROMIPS32R6; @@ -1174,6 +1588,11 @@ def SUBU16_MMR6 : StdMMR6Rel, SUBU16_MMR6_DESC, SUBU16_MMR6_ENC, ISA_MICROMIPS32R6; def XOR16_MMR6 : StdMMR6Rel, XOR16_MMR6_DESC, XOR16_MMR6_ENC, ISA_MICROMIPS32R6; +def JALRC_HB_MMR6 : R6MMR6Rel, JALRC_HB_MMR6_ENC, JALRC_HB_MMR6_DESC, + ISA_MICROMIPS32R6; +def EXT_MMR6 : StdMMR6Rel, EXT_MMR6_ENC, EXT_MMR6_DESC, ISA_MICROMIPS32R6; +def INS_MMR6 : StdMMR6Rel, INS_MMR6_ENC, INS_MMR6_DESC, ISA_MICROMIPS32R6; +def JALRC_MMR6 : R6MMR6Rel, JALRC_MMR6_ENC, JALRC_MMR6_DESC, ISA_MICROMIPS32R6; def RECIP_S_MMR6 : StdMMR6Rel, RECIP_S_MMR6_ENC, RECIP_S_MMR6_DESC, ISA_MICROMIPS32R6; def RECIP_D_MMR6 : StdMMR6Rel, RECIP_D_MMR6_ENC, RECIP_D_MMR6_DESC, ISA_MICROMIPS32R6; @@ -1188,22 +1607,69 @@ def ROUND_W_S_MMR6 : StdMMR6Rel, ROUND_W_S_MMR6_ENC, ROUND_W_S_MMR6_DESC, ISA_MICROMIPS32R6; def ROUND_W_D_MMR6 : StdMMR6Rel, ROUND_W_D_MMR6_ENC, ROUND_W_D_MMR6_DESC, ISA_MICROMIPS32R6; -def SEL_S_MMR6 : StdMMR6Rel, SEL_S_MMR6_ENC, SEL_S_MMR6_DESC, ISA_MICROMIPS32R6; -def SEL_D_MMR6 : StdMMR6Rel, SEL_D_MMR6_ENC, SEL_D_MMR6_DESC, ISA_MICROMIPS32R6; -def SELEQZ_S_MMR6 : StdMMR6Rel, SELEQZ_S_MMR6_ENC, SELEQZ_S_MMR6_DESC, +def SEL_S_MMR6 : R6MMR6Rel, SEL_S_MMR6_ENC, SEL_S_MMR6_DESC, ISA_MICROMIPS32R6; +def SEL_D_MMR6 : R6MMR6Rel, SEL_D_MMR6_ENC, SEL_D_MMR6_DESC, ISA_MICROMIPS32R6; +def SELEQZ_S_MMR6 : R6MMR6Rel, SELEQZ_S_MMR6_ENC, SELEQZ_S_MMR6_DESC, ISA_MICROMIPS32R6; -def SELEQZ_D_MMR6 : StdMMR6Rel, SELEQZ_D_MMR6_ENC, SELEQZ_D_MMR6_DESC, +def SELEQZ_D_MMR6 : R6MMR6Rel, SELEQZ_D_MMR6_ENC, SELEQZ_D_MMR6_DESC, ISA_MICROMIPS32R6; -def SELENZ_S_MMR6 : StdMMR6Rel, SELENZ_S_MMR6_ENC, SELENZ_S_MMR6_DESC, +def SELNEZ_S_MMR6 : R6MMR6Rel, SELNEZ_S_MMR6_ENC, SELNEZ_S_MMR6_DESC, ISA_MICROMIPS32R6; -def SELENZ_D_MMR6 : StdMMR6Rel, SELENZ_D_MMR6_ENC, SELENZ_D_MMR6_DESC, +def SELNEZ_D_MMR6 : R6MMR6Rel, SELNEZ_D_MMR6_ENC, SELNEZ_D_MMR6_DESC, ISA_MICROMIPS32R6; def CLASS_S_MMR6 : StdMMR6Rel, CLASS_S_MMR6_ENC, CLASS_S_MMR6_DESC, ISA_MICROMIPS32R6; def CLASS_D_MMR6 : StdMMR6Rel, CLASS_D_MMR6_ENC, CLASS_D_MMR6_DESC, ISA_MICROMIPS32R6; +def TLBINV_MMR6 : StdMMR6Rel, TLBINV_MMR6_ENC, TLBINV_MMR6_DESC, + ISA_MICROMIPS32R6; +def TLBINVF_MMR6 : StdMMR6Rel, TLBINVF_MMR6_ENC, TLBINVF_MMR6_DESC, + ISA_MICROMIPS32R6; +def DVP_MMR6 : R6MMR6Rel, DVP_MMR6_ENC, DVP_MMR6_DESC, ISA_MICROMIPS32R6; +def EVP_MMR6 : R6MMR6Rel, EVP_MMR6_ENC, EVP_MMR6_DESC, ISA_MICROMIPS32R6; +def BC1EQZC_MMR6 : R6MMR6Rel, BC1EQZC_MMR6_DESC, BC1EQZC_MMR6_ENC, + ISA_MICROMIPS32R6; +def BC1NEZC_MMR6 : R6MMR6Rel, BC1NEZC_MMR6_DESC, BC1NEZC_MMR6_ENC, + ISA_MICROMIPS32R6; +def BC2EQZC_MMR6 : R6MMR6Rel, MipsR6Inst, BC2EQZC_MMR6_ENC, BC2EQZC_MMR6_DESC, + ISA_MICROMIPS32R6; +def BC2NEZC_MMR6 : R6MMR6Rel, MipsR6Inst, BC2NEZC_MMR6_ENC, BC2NEZC_MMR6_DESC, + ISA_MICROMIPS32R6; +let DecoderNamespace = "MicroMips32r6FP64" in { + def LDC1_D64_MMR6 : StdMMR6Rel, LDC1_D64_MMR6_DESC, LDC1_MMR6_ENC, + ISA_MICROMIPS32R6 { + let BaseOpcode = "LDC164"; + } + def SDC1_D64_MMR6 : StdMMR6Rel, SDC1_D64_MMR6_DESC, SDC1_MMR6_ENC, + ISA_MICROMIPS32R6; +} +def LDC2_MMR6 : StdMMR6Rel, LDC2_MMR6_ENC, LDC2_MMR6_DESC, ISA_MICROMIPS32R6; +def SDC2_MMR6 : StdMMR6Rel, SDC2_MMR6_ENC, SDC2_MMR6_DESC, ISA_MICROMIPS32R6; +def LWC2_MMR6 : StdMMR6Rel, LWC2_MMR6_ENC, LWC2_MMR6_DESC, ISA_MICROMIPS32R6; +def SWC2_MMR6 : StdMMR6Rel, SWC2_MMR6_ENC, SWC2_MMR6_DESC, ISA_MICROMIPS32R6; } +def BOVC_MMR6 : R6MMR6Rel, BOVC_MMR6_ENC, BOVC_MMR6_DESC, ISA_MICROMIPS32R6, + MMDecodeDisambiguatedBy<"POP35GroupBranchMMR6">; +def BNVC_MMR6 : R6MMR6Rel, BNVC_MMR6_ENC, BNVC_MMR6_DESC, ISA_MICROMIPS32R6, + MMDecodeDisambiguatedBy<"POP37GroupBranchMMR6">; +def BGEC_MMR6 : R6MMR6Rel, BGEC_MMR6_ENC, BGEC_MMR6_DESC, ISA_MICROMIPS32R6; +def BGEUC_MMR6 : R6MMR6Rel, BGEUC_MMR6_ENC, BGEUC_MMR6_DESC, ISA_MICROMIPS32R6; +def BLTC_MMR6 : R6MMR6Rel, BLTC_MMR6_ENC, BLTC_MMR6_DESC, ISA_MICROMIPS32R6; +def BLTUC_MMR6 : R6MMR6Rel, BLTUC_MMR6_ENC, BLTUC_MMR6_DESC, ISA_MICROMIPS32R6; +def BEQC_MMR6 : R6MMR6Rel, BEQC_MMR6_ENC, BEQC_MMR6_DESC, ISA_MICROMIPS32R6, + DecodeDisambiguates<"POP35GroupBranchMMR6">; +def BNEC_MMR6 : R6MMR6Rel, BNEC_MMR6_ENC, BNEC_MMR6_DESC, ISA_MICROMIPS32R6, + DecodeDisambiguates<"POP37GroupBranchMMR6">; +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; + //===----------------------------------------------------------------------===// // // MicroMips instruction aliases @@ -1222,6 +1688,45 @@ def : MipsInstAlias<"sdbbp", (SDBBP_MMR6 0), 1>, ISA_MICROMIPS32R6; def : MipsInstAlias<"rdhwr $rt, $rs", (RDHWR_MMR6 GPR32Opnd:$rt, HWRegsOpnd:$rs, 0), 1>, ISA_MICROMIPS32R6; +def : MipsInstAlias<"mtc0 $rt, $rs", + (MTC0_MMR6 COP0Opnd:$rs, GPR32Opnd:$rt, 0), 0>, + ISA_MICROMIPS32R6; +def : MipsInstAlias<"mthc0 $rt, $rs", + (MTHC0_MMR6 COP0Opnd:$rs, GPR32Opnd:$rt, 0), 0>, + ISA_MICROMIPS32R6; +def : MipsInstAlias<"mfc0 $rt, $rs", + (MFC0_MMR6 GPR32Opnd:$rt, COP0Opnd:$rs, 0), 0>, + ISA_MICROMIPS32R6; +def : MipsInstAlias<"mfhc0 $rt, $rs", + (MFHC0_MMR6 GPR32Opnd:$rt, COP0Opnd:$rs, 0), 0>, + ISA_MICROMIPS32R6; +def : MipsInstAlias<"jalrc.hb $rs", (JALRC_HB_MMR6 RA, GPR32Opnd:$rs), 1>, + ISA_MICROMIPS32R6; +def : MipsInstAlias<"dvp", (DVP_MMR6 ZERO), 0>, ISA_MICROMIPS32R6; +def : MipsInstAlias<"evp", (EVP_MMR6 ZERO), 0>, ISA_MICROMIPS32R6; +def : MipsInstAlias<"jalrc $rs", (JALRC_MMR6 RA, GPR32Opnd:$rs), 1>, + ISA_MICROMIPS32R6; +def : MipsInstAlias<"and $rs, $rt, $imm", + (ANDI_MMR6 GPR32Opnd:$rs, GPR32Opnd:$rt, uimm16:$imm), 0>, + ISA_MICROMIPS32R6; +def : MipsInstAlias<"and $rs, $imm", + (ANDI_MMR6 GPR32Opnd:$rs, GPR32Opnd:$rs, uimm16:$imm), 0>, + ISA_MICROMIPS32R6; +def : MipsInstAlias<"or $rs, $rt, $imm", + (ORI_MMR6 GPR32Opnd:$rs, GPR32Opnd:$rt, uimm16:$imm), 0>, + ISA_MICROMIPS32R6; +def : MipsInstAlias<"or $rs, $imm", + (ORI_MMR6 GPR32Opnd:$rs, GPR32Opnd:$rs, uimm16:$imm), 0>, + ISA_MICROMIPS32R6; +def : MipsInstAlias<"xor $rs, $rt, $imm", + (XORI_MMR6 GPR32Opnd:$rs, GPR32Opnd:$rt, uimm16:$imm), 0>, + ISA_MICROMIPS32R6; +def : MipsInstAlias<"xor $rs, $imm", + (XORI_MMR6 GPR32Opnd:$rs, GPR32Opnd:$rs, uimm16:$imm), 0>, + ISA_MICROMIPS32R6; +def : MipsInstAlias<"not $rt, $rs", + (NOR_MMR6 GPR32Opnd:$rt, GPR32Opnd:$rs, ZERO), 0>, + ISA_MICROMIPS32R6; //===----------------------------------------------------------------------===// // @@ -1231,3 +1736,39 @@ def : MipsInstAlias<"rdhwr $rt, $rs", def : MipsPat<(store GPRMM16:$src, addrimm4lsl2:$addr), (SW16_MMR6 GPRMM16:$src, addrimm4lsl2:$addr)>, ISA_MICROMIPS32R6; +def : MipsPat<(subc GPR32:$lhs, GPR32:$rhs), + (SUBU_MMR6 GPR32:$lhs, GPR32:$rhs)>, ISA_MICROMIPS32R6; + +def : MipsPat<(select i32:$cond, i32:$t, i32:$f), + (OR_MM (SELNEZ_MMR6 i32:$t, i32:$cond), + (SELEQZ_MMR6 i32:$f, i32:$cond))>, + ISA_MICROMIPS32R6; +def : MipsPat<(select i32:$cond, i32:$t, immz), + (SELNEZ_MMR6 i32:$t, i32:$cond)>, + ISA_MICROMIPS32R6; +def : MipsPat<(select i32:$cond, immz, i32:$f), + (SELEQZ_MMR6 i32:$f, i32:$cond)>, + ISA_MICROMIPS32R6; + +defm : SelectInt_Pats<i32, OR_MM, XORI_MMR6, SLTi_MM, SLTiu_MM, SELEQZ_MMR6, + SELNEZ_MMR6, immZExt16, i32>, ISA_MICROMIPS32R6; + +defm S_MMR6 : Cmp_Pats<f32, NOR_MMR6, ZERO>, ISA_MICROMIPS32R6; +defm D_MMR6 : Cmp_Pats<f64, NOR_MMR6, ZERO>, ISA_MICROMIPS32R6; + +def : MipsPat<(and GPRMM16:$src, immZExtAndi16:$imm), + (ANDI16_MMR6 GPRMM16:$src, immZExtAndi16:$imm)>, + ISA_MICROMIPS32R6; +def : MipsPat<(and GPR32:$src, immZExt16:$imm), + (ANDI_MMR6 GPR32:$src, immZExt16:$imm)>, ISA_MICROMIPS32R6; +def : MipsPat<(i32 immZExt16:$imm), + (XORI_MMR6 ZERO, immZExt16:$imm)>, ISA_MICROMIPS32R6; +def : MipsPat<(not GPRMM16:$in), + (NOT16_MMR6 GPRMM16:$in)>, ISA_MICROMIPS32R6; +def : MipsPat<(not GPR32:$in), + (NOR_MMR6 GPR32Opnd:$in, ZERO)>, ISA_MICROMIPS32R6; +// Patterns for load with a reg+imm operand. +let AddedComplexity = 41 in { + def : LoadRegImmPat<LDC1_D64_MMR6, f64, load>, FGR_64, ISA_MICROMIPS32R6; + def : StoreRegImmPat<SDC1_D64_MMR6, f64>, FGR_64, ISA_MICROMIPS32R6; +} diff --git a/lib/Target/Mips/MicroMips64r6InstrFormats.td b/lib/Target/Mips/MicroMips64r6InstrFormats.td index da305a2d508aa..4add305522f75 100644 --- a/lib/Target/Mips/MicroMips64r6InstrFormats.td +++ b/lib/Target/Mips/MicroMips64r6InstrFormats.td @@ -71,16 +71,151 @@ class POOL32S_DALIGN_FM_MMR6 { class POOL32A_DIVMOD_FM_MMR6<string instr_asm, bits<9> funct> : MMR6Arch<instr_asm> { + bits<5> rt; + bits<5> rs; bits<5> rd; + + bits<32> Inst; + + let Inst{31-26} = 0b010110; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-11} = rd; + let Inst{10-9} = 0b00; + let Inst{8-0} = funct; +} + +class POOL32S_DMFTC0_FM_MMR6<string instr_asm, bits<5> funct> + : MMR6Arch<instr_asm>, MipsR6Inst { + bits<5> rt; bits<5> rs; + bits<3> sel; + + bits<32> Inst; + + let Inst{31-26} = 0b010110; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-14} = 0; + let Inst{13-11} = sel; + let Inst{10-6} = funct; + let Inst{5-0} = 0b111100; +} + +class POOL32S_ARITH_FM_MMR6<string opstr, bits<9> funct> + : MMR6Arch<opstr> { bits<5> rt; + bits<5> rs; + bits<5> rd; bits<32> Inst; let Inst{31-26} = 0b010110; - let Inst{25-21} = rd; + let Inst{25-21} = rt; let Inst{20-16} = rs; - let Inst{15-11} = rt; + let Inst{15-11} = rd; let Inst{10-9} = 0b00; - let Inst{8-0} = funct; + let Inst{8-0} = funct; +} + +class DADDIU_FM_MMR6<string opstr> : MMR6Arch<opstr> { + bits<5> rt; + bits<5> rs; + bits<16> imm16; + + bits<32> Inst; + + let Inst{31-26} = 0b010111; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-0} = imm16; +} + +class PCREL18_FM_MMR6<bits<3> funct> : MipsR6Inst { + bits<5> rt; + bits<18> imm; + + bits<32> Inst; + + let Inst{31-26} = 0b011110; + let Inst{25-21} = rt; + let Inst{20-18} = funct; + let Inst{17-0} = imm; +} + +class POOL32S_2R_FM_MMR6<string instr_asm, bits<10> funct> + : MMR6Arch<instr_asm>, MipsR6Inst { + bits<5> rt; + bits<5> rs; + + bits<32> Inst; + + let Inst{31-26} = 0b010110; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-6} = funct; + let Inst{5-0} = 0b111100; +} + +class POOL32S_2RSA5B0_FM_MMR6<string instr_asm, bits<9> funct> + : MMR6Arch<instr_asm>, MipsR6Inst { + bits<5> rt; + bits<5> rs; + bits<5> sa; + + bits<32> Inst; + + let Inst{31-26} = 0b010110; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-11} = sa; + let Inst{10-9} = 0b00; + let Inst{8-0} = funct; +} + +class LD_SD_32_2R_OFFSET16_FM_MMR6<string instr_asm, bits<6> op> + : MMR6Arch<instr_asm>, MipsR6Inst { + bits<5> rt; + bits<21> addr; + bits<5> base = addr{20-16}; + bits<16> offset = addr{15-0}; + + bits<32> Inst; + + let Inst{31-26} = op; + let Inst{25-21} = rt; + let Inst{20-16} = base; + let Inst{15-0} = offset; +} + +class POOL32C_2R_OFFSET12_FM_MMR6<string instr_asm, bits<4> funct> + : MMR6Arch<instr_asm>, MipsR6Inst { + bits<5> rt; + bits<21> addr; + bits<5> base = addr{20-16}; + bits<12> offset = addr{11-0}; + + bits<32> Inst; + + let Inst{31-26} = 0b011000; + let Inst{25-21} = rt; + let Inst{20-16} = base; + let Inst{15-12} = funct; + let Inst{11-0} = offset; +} + +class POOL32S_3R_FM_MMR6<string instr_asm, bits<9> funct> + : MMR6Arch<instr_asm>, MipsR6Inst { + bits<5> rt; + bits<5> rs; + bits<5> rd; + + bits<32> Inst; + + let Inst{31-26} = 0b010110; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-11} = rd; + let Inst{10-9} = 0b00; + let Inst{8-0} = funct; } diff --git a/lib/Target/Mips/MicroMips64r6InstrInfo.td b/lib/Target/Mips/MicroMips64r6InstrInfo.td index ec1aef86a9426..87c41deb85af8 100644 --- a/lib/Target/Mips/MicroMips64r6InstrInfo.td +++ b/lib/Target/Mips/MicroMips64r6InstrInfo.td @@ -28,6 +28,45 @@ class DDIV_MM64R6_ENC : POOL32A_DIVMOD_FM_MMR6<"ddiv", 0b100011000>; class DMOD_MM64R6_ENC : POOL32A_DIVMOD_FM_MMR6<"dmod", 0b101011000>; class DDIVU_MM64R6_ENC : POOL32A_DIVMOD_FM_MMR6<"ddivu", 0b110011000>; class DMODU_MM64R6_ENC : POOL32A_DIVMOD_FM_MMR6<"dmodu", 0b111011000>; +class DINSU_MM64R6_ENC : POOL32S_EXTBITS_FM_MMR6<0b110100>; +class DINSM_MM64R6_ENC : POOL32S_EXTBITS_FM_MMR6<0b000100>; +class DINS_MM64R6_ENC : POOL32S_EXTBITS_FM_MMR6<0b001100>; +class DMTC0_MM64R6_ENC : POOL32S_DMFTC0_FM_MMR6<"dmtc0", 0b01011>; +class DMTC1_MM64R6_ENC : POOL32F_MFTC1_FM_MMR6<"dmtc1", 0b10110000>; +class DMTC2_MM64R6_ENC : POOL32A_MFTC2_FM_MMR6<"dmtc2", 0b0111110100>; +class DMFC0_MM64R6_ENC : POOL32S_DMFTC0_FM_MMR6<"dmfc0", 0b00011>; +class DMFC1_MM64R6_ENC : POOL32F_MFTC1_FM_MMR6<"dmfc1", 0b10010000>; +class DMFC2_MM64R6_ENC : POOL32A_MFTC2_FM_MMR6<"dmfc2", 0b0110110100>; +class DADD_MM64R6_ENC : POOL32S_ARITH_FM_MMR6<"dadd", 0b100010000>; +class DADDIU_MM64R6_ENC : DADDIU_FM_MMR6<"daddiu">; +class DADDU_MM64R6_ENC : POOL32S_ARITH_FM_MMR6<"daddu", 0b101010000>; +class LDPC_MMR646_ENC : PCREL18_FM_MMR6<0b110>; +class DSUB_MM64R6_ENC : POOL32S_ARITH_FM_MMR6<"dsub", 0b110010000>; +class DSUBU_MM64R6_ENC : POOL32S_ARITH_FM_MMR6<"dsubu", 0b111010000>; +class DMUL_MM64R6_ENC : POOL32S_ARITH_FM_MMR6<"dmul", 0b000011000>; +class DMUH_MM64R6_ENC : POOL32S_ARITH_FM_MMR6<"dmuh", 0b001011000>; +class DMULU_MM64R6_ENC : POOL32S_ARITH_FM_MMR6<"dmulu", 0b010011000>; +class DMUHU_MM64R6_ENC : POOL32S_ARITH_FM_MMR6<"dmuhu", 0b011011000>; +class DSBH_MM64R6_ENC : POOL32S_2R_FM_MMR6<"dsbh", 0b0111101100>; +class DSHD_MM64R6_ENC : POOL32S_2R_FM_MMR6<"dshd", 0b1111101100>; +class DSLL_MM64R6_ENC : POOL32S_2RSA5B0_FM_MMR6<"dsll", 0b000000000>; +class DSLL32_MM64R6_ENC : POOL32S_2RSA5B0_FM_MMR6<"dsll32", 0b000001000>; +class DSLLV_MM64R6_ENC : POOL32S_3R_FM_MMR6<"dsllv", 0b000010000>; +class DSRAV_MM64R6_ENC : POOL32S_3R_FM_MMR6<"dsrav", 0b010010000>; +class DSRA_MM64R6_ENC : POOL32S_2RSA5B0_FM_MMR6<"dsra", 0b010000000>; +class DSRA32_MM64R6_ENC : POOL32S_2RSA5B0_FM_MMR6<"dsra32", 0b010000100>; +class DCLO_MM64R6_ENC : POOL32S_2R_FM_MMR6<"dclo", 0b0100101100>; +class DCLZ_MM64R6_ENC : POOL32S_2R_FM_MMR6<"dclz", 0b0101101100>; +class DROTR_MM64R6_ENC : POOL32S_2RSA5B0_FM_MMR6<"drotr", 0b011000000>; +class DROTR32_MM64R6_ENC : POOL32S_2RSA5B0_FM_MMR6<"drotr32", 0b011001000>; +class DROTRV_MM64R6_ENC : POOL32S_3R_FM_MMR6<"drotrv", 0b011010000>; +class LD_MM64R6_ENC : LD_SD_32_2R_OFFSET16_FM_MMR6<"ld", 0b110111>; +class LLD_MM64R6_ENC : POOL32C_2R_OFFSET12_FM_MMR6<"lld", 0b0111>; +class LWU_MM64R6_ENC : POOL32C_2R_OFFSET12_FM_MMR6<"lwu", 0b1110>; +class SD_MM64R6_ENC : LD_SD_32_2R_OFFSET16_FM_MMR6<"sd", 0b110110>; +class DSRL_MM64R6_ENC : POOL32S_2RSA5B0_FM_MMR6<"dsrl", 0b001000000>; +class DSRL32_MM64R6_ENC : POOL32S_2RSA5B0_FM_MMR6<"dsrl32", 0b001001000>; +class DSRLV_MM64R6_ENC : POOL32S_3R_FM_MMR6<"dsrlv", 0b001010000>; //===----------------------------------------------------------------------===// // @@ -68,7 +107,7 @@ class EXTBITS_DESC_BASE<string instr_asm, RegisterOperand RO, Operand PosOpnd, // TODO: Add 'pos + size' constraint check to dext* instructions // DEXT: 0 < pos + size <= 63 // DEXTM, DEXTU: 32 < pos + size <= 64 -class DEXT_MMR6_DESC : EXTBITS_DESC_BASE<"dext", GPR64Opnd, uimm5, +class DEXT_MMR6_DESC : EXTBITS_DESC_BASE<"dext", GPR64Opnd, uimm5_report_uimm6, uimm5_plus1, MipsExt>; class DEXTM_MMR6_DESC : EXTBITS_DESC_BASE<"dextm", GPR64Opnd, uimm5, uimm5_plus33, MipsExt>; @@ -85,10 +124,189 @@ class DALIGN_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, class DALIGN_MMR6_DESC : DALIGN_DESC_BASE<"dalign", GPR64Opnd, uimm3>; -class DDIV_MM64R6_DESC : ArithLogicR<"ddiv", GPR32Opnd>; -class DMOD_MM64R6_DESC : ArithLogicR<"dmod", GPR32Opnd>; -class DDIVU_MM64R6_DESC : ArithLogicR<"ddivu", GPR32Opnd>; -class DMODU_MM64R6_DESC : ArithLogicR<"dmodu", GPR32Opnd>; +class DDIV_MM64R6_DESC : DIVMOD_MMR6_DESC_BASE<"ddiv", GPR64Opnd, sdiv>; +class DMOD_MM64R6_DESC : DIVMOD_MMR6_DESC_BASE<"dmod", GPR64Opnd, srem>; +class DDIVU_MM64R6_DESC : DIVMOD_MMR6_DESC_BASE<"ddivu", GPR64Opnd, udiv>; +class DMODU_MM64R6_DESC : DIVMOD_MMR6_DESC_BASE<"dmodu", GPR64Opnd, urem>; + +class DCLO_MM64R6_DESC { + dag OutOperandList = (outs GPR64Opnd:$rt); + dag InOperandList = (ins GPR64Opnd:$rs); + string AsmString = !strconcat("dclo", "\t$rt, $rs"); + list<dag> Pattern = [(set GPR64Opnd:$rt, (ctlz (not GPR64Opnd:$rs)))]; + InstrItinClass Itinerary = II_CLO; + Format Form = FrmR; + string BaseOpcode = "dclo"; +} + +class DCLZ_MM64R6_DESC { + dag OutOperandList = (outs GPR64Opnd:$rt); + dag InOperandList = (ins GPR64Opnd:$rs); + string AsmString = !strconcat("dclz", "\t$rt, $rs"); + list<dag> Pattern = [(set GPR64Opnd:$rt, (ctlz GPR64Opnd:$rs))]; + InstrItinClass Itinerary = II_CLZ; + Format Form = FrmR; + string BaseOpcode = "dclz"; +} + +class DINSU_MM64R6_DESC : InsBase<"dinsu", GPR64Opnd, uimm5_plus32, + uimm5_inssize_plus1, MipsIns>; +class DINSM_MM64R6_DESC : InsBase<"dinsm", GPR64Opnd, uimm5, uimm_range_2_64>; +class DINS_MM64R6_DESC : InsBase<"dins", GPR64Opnd, uimm5, uimm5_inssize_plus1, + MipsIns>; +class DMTC0_MM64R6_DESC : MTC0_MMR6_DESC_BASE<"dmtc0", COP0Opnd, GPR64Opnd>; +class DMTC1_MM64R6_DESC : MTC1_MMR6_DESC_BASE<"dmtc1", FGR64Opnd, GPR64Opnd, + II_DMTC1, bitconvert>; +class DMTC2_MM64R6_DESC : MTC2_MMR6_DESC_BASE<"dmtc2", COP2Opnd, GPR64Opnd>; + +class DMFC0_MM64R6_DESC : MFC0_MMR6_DESC_BASE<"dmfc0", GPR64Opnd, COP0Opnd>; +class DMFC1_MM64R6_DESC : MFC1_MMR6_DESC_BASE<"dmfc1", GPR64Opnd, FGR64Opnd, + II_DMFC1, bitconvert>; +class DMFC2_MM64R6_DESC : MFC2_MMR6_DESC_BASE<"dmfc2", GPR64Opnd, COP2Opnd>; + +class DADD_MM64R6_DESC : ArithLogicR<"dadd", GPR64Opnd, 1, II_DADD>; +class DADDIU_MM64R6_DESC : ArithLogicI<"daddiu", simm16_64, GPR64Opnd, + II_DADDIU, immSExt16, add>, + IsAsCheapAsAMove; +class DADDU_MM64R6_DESC : ArithLogicR<"daddu", GPR64Opnd, 1, II_DADDU, add>; + +class DSUB_DESC_BASE<string instr_asm, RegisterOperand RO, + InstrItinClass Itin = NoItinerary, + SDPatternOperator OpNode = null_frag> + : MipsR6Inst { + dag OutOperandList = (outs RO:$rd); + dag InOperandList = (ins RO:$rs, RO:$rt); + string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt"); + list<dag> Pattern = [(set RO:$rd, (OpNode RO:$rs, RO:$rt))]; + InstrItinClass Itinerary = Itin; + Format Form = FrmR; + string BaseOpcode = instr_asm; + let isCommutable = 0; + let isReMaterializable = 1; + let TwoOperandAliasConstraint = "$rd = $rs"; +} +class DSUB_MM64R6_DESC : DSUB_DESC_BASE<"dsub", GPR64Opnd, II_DSUB>; +class DSUBU_MM64R6_DESC : DSUB_DESC_BASE<"dsubu", GPR64Opnd, II_DSUBU, sub>; + +class LDPC_MM64R6_DESC : PCREL_MMR6_DESC_BASE<"ldpc", GPR64Opnd, simm18_lsl3>; + +class MUL_MM64R6_DESC_BASE<string opstr, RegisterOperand GPROpnd, + InstrItinClass Itin = NoItinerary, + SDPatternOperator Op = null_frag> : MipsR6Inst { + dag OutOperandList = (outs GPROpnd:$rd); + dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt); + string AsmString = !strconcat(opstr, "\t$rd, $rs, $rt"); + InstrItinClass Itinerary = Itin; + list<dag> Pattern = [(set GPROpnd:$rd, (Op GPROpnd:$rs, GPROpnd:$rt))]; +} + +class DMUL_MM64R6_DESC : MUL_MM64R6_DESC_BASE<"dmul", GPR64Opnd, II_DMUL, mul>; +class DMUH_MM64R6_DESC : MUL_MM64R6_DESC_BASE<"dmuh", GPR64Opnd, II_DMUH, + mulhs>; +class DMULU_MM64R6_DESC : MUL_MM64R6_DESC_BASE<"dmulu", GPR64Opnd, II_DMULU>; +class DMUHU_MM64R6_DESC : MUL_MM64R6_DESC_BASE<"dmuhu", GPR64Opnd, II_DMUHU, + mulhu>; + +class DSBH_DSHD_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> { + dag OutOperandList = (outs GPROpnd:$rt); + dag InOperandList = (ins GPROpnd:$rs); + string AsmString = !strconcat(instr_asm, "\t$rt, $rs"); + bit hasSideEffects = 0; + list<dag> Pattern = []; + InstrItinClass Itinerary = NoItinerary; + Format Form = FrmR; + string BaseOpcode = instr_asm; +} + +class DSBH_MM64R6_DESC : DSBH_DSHD_DESC_BASE<"dsbh", GPR64Opnd>; +class DSHD_MM64R6_DESC : DSBH_DSHD_DESC_BASE<"dshd", GPR64Opnd>; + +class SHIFT_ROTATE_IMM_MM64R6<string instr_asm, Operand ImmOpnd, + InstrItinClass itin, + SDPatternOperator OpNode = null_frag, + SDPatternOperator PO = null_frag> { + dag OutOperandList = (outs GPR64Opnd:$rt); + dag InOperandList = (ins GPR64Opnd:$rs, ImmOpnd:$sa); + string AsmString = !strconcat(instr_asm, "\t$rt, $rs, $sa"); + list<dag> Pattern = [(set GPR64Opnd:$rt, (OpNode GPR64Opnd:$rs, PO:$sa))]; + InstrItinClass Itinerary = itin; + Format Form = FrmR; + string TwoOperandAliasConstraint = "$rs = $rt"; + string BaseOpcode = instr_asm; +} + +class SHIFT_ROTATE_REG_MM64R6<string instr_asm, InstrItinClass itin, + SDPatternOperator OpNode = null_frag> { + dag OutOperandList = (outs GPR64Opnd:$rd); + dag InOperandList = (ins GPR64Opnd:$rt, GPR32Opnd:$rs); + string AsmString = !strconcat(instr_asm, "\t$rd, $rt, $rs"); + list<dag> Pattern = [(set GPR64Opnd:$rd, + (OpNode GPR64Opnd:$rt, GPR32Opnd:$rs))]; + InstrItinClass Itinerary = itin; + Format Form = FrmR; + string BaseOpcode = instr_asm; +} + +class DSLL_MM64R6_DESC : SHIFT_ROTATE_IMM_MM64R6<"dsll", uimm6, II_DSLL, shl, + immZExt6>; +class DSLL32_MM64R6_DESC : SHIFT_ROTATE_IMM_MM64R6<"dsll32", uimm5, II_DSLL32>; +class DSLLV_MM64R6_DESC : SHIFT_ROTATE_REG_MM64R6<"dsllv", II_DSLLV, shl>; +class DSRAV_MM64R6_DESC : SHIFT_ROTATE_REG_MM64R6<"dsrav", II_DSRAV, sra>; +class DSRA_MM64R6_DESC : SHIFT_ROTATE_IMM_MM64R6<"dsra", uimm6, II_DSRA, sra, + immZExt6>; +class DSRA32_MM64R6_DESC : SHIFT_ROTATE_IMM_MM64R6<"dsra32", uimm5, II_DSRA32>; +class DROTR_MM64R6_DESC : SHIFT_ROTATE_IMM_MM64R6<"drotr", uimm6, II_DROTR, + rotr, immZExt6>; +class DROTR32_MM64R6_DESC : SHIFT_ROTATE_IMM_MM64R6<"drotr32", uimm5, + II_DROTR32>; +class DROTRV_MM64R6_DESC : SHIFT_ROTATE_REG_MM64R6<"drotrv", II_DROTRV, rotr>; +class DSRL_MM64R6_DESC : SHIFT_ROTATE_IMM_MM64R6<"dsrl", uimm6, II_DSRL, srl, + immZExt6>; +class DSRL32_MM64R6_DESC : SHIFT_ROTATE_IMM_MM64R6<"dsrl32", uimm5, II_DSRL32>; +class DSRLV_MM64R6_DESC : SHIFT_ROTATE_REG_MM64R6<"dsrlv", II_DSRLV, srl>; + +class Load_MM64R6<string instr_asm, Operand MemOpnd, InstrItinClass itin, + SDPatternOperator OpNode = null_frag> { + dag OutOperandList = (outs GPR64Opnd:$rt); + dag InOperandList = (ins MemOpnd:$addr); + string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); + list<dag> Pattern = [(set GPR64Opnd:$rt, (OpNode addr:$addr))]; + InstrItinClass Itinerary = itin; + Format Form = FrmI; + bit mayLoad = 1; + bit canFoldAsLoad = 1; + string BaseOpcode = instr_asm; +} + +class LD_MM64R6_DESC : Load_MM64R6<"ld", mem_simm16, II_LD, load> { + string DecoderMethod = "DecodeMemMMImm16"; +} +class LWU_MM64R6_DESC : Load_MM64R6<"lwu", mem_simm12, II_LWU, zextloadi32>{ + string DecoderMethod = "DecodeMemMMImm12"; +} + +class LLD_MM64R6_DESC { + dag OutOperandList = (outs GPR64Opnd:$rt); + dag InOperandList = (ins mem_simm12:$addr); + string AsmString = "lld\t$rt, $addr"; + list<dag> Pattern = []; + bit mayLoad = 1; + InstrItinClass Itinerary = II_LLD; + string BaseOpcode = "lld"; + string DecoderMethod = "DecodeMemMMImm12"; +} + +class SD_MM64R6_DESC { + dag OutOperandList = (outs); + dag InOperandList = (ins GPR64Opnd:$rt, mem_simm16:$addr); + string AsmString = "sd\t$rt, $addr"; + list<dag> Pattern = [(store GPR64Opnd:$rt, addr:$addr)]; + InstrItinClass Itinerary = II_SD; + Format Form = FrmI; + bit mayStore = 1; + string BaseOpcode = "sd"; + string DecoderMethod = "DecodeMemMMImm16"; +} //===----------------------------------------------------------------------===// // @@ -116,4 +334,180 @@ let DecoderNamespace = "MicroMipsR6" in { ISA_MICROMIPS64R6; def DMODU_MM64R6 : R6MMR6Rel, DMODU_MM64R6_DESC, DMODU_MM64R6_ENC, ISA_MICROMIPS64R6; + def DINSU_MM64R6: R6MMR6Rel, DINSU_MM64R6_DESC, DINSU_MM64R6_ENC, + ISA_MICROMIPS64R6; + def DINSM_MM64R6: R6MMR6Rel, DINSM_MM64R6_DESC, DINSM_MM64R6_ENC, + ISA_MICROMIPS64R6; + def DINS_MM64R6: R6MMR6Rel, DINS_MM64R6_DESC, DINS_MM64R6_ENC, + ISA_MICROMIPS64R6; + def DMTC0_MM64R6 : StdMMR6Rel, DMTC0_MM64R6_ENC, DMTC0_MM64R6_DESC, + ISA_MICROMIPS64R6; + def DMTC1_MM64R6 : StdMMR6Rel, DMTC1_MM64R6_DESC, DMTC1_MM64R6_ENC, + ISA_MICROMIPS64R6; + def DMTC2_MM64R6 : StdMMR6Rel, DMTC2_MM64R6_ENC, DMTC2_MM64R6_DESC, + ISA_MICROMIPS64R6; + def DMFC0_MM64R6 : StdMMR6Rel, DMFC0_MM64R6_ENC, DMFC0_MM64R6_DESC, + ISA_MICROMIPS64R6; + def DMFC1_MM64R6 : StdMMR6Rel, DMFC1_MM64R6_DESC, DMFC1_MM64R6_ENC, + ISA_MICROMIPS64R6; + def DMFC2_MM64R6 : StdMMR6Rel, DMFC2_MM64R6_ENC, DMFC2_MM64R6_DESC, + ISA_MICROMIPS64R6; + def DADD_MM64R6: StdMMR6Rel, DADD_MM64R6_DESC, DADD_MM64R6_ENC, + ISA_MICROMIPS64R6; + def DADDIU_MM64R6: StdMMR6Rel, DADDIU_MM64R6_DESC, DADDIU_MM64R6_ENC, + ISA_MICROMIPS64R6; + def DADDU_MM64R6: StdMMR6Rel, DADDU_MM64R6_DESC, DADDU_MM64R6_ENC, + ISA_MICROMIPS64R6; + def LDPC_MM64R6 : R6MMR6Rel, LDPC_MMR646_ENC, LDPC_MM64R6_DESC, + ISA_MICROMIPS64R6; + def DSUB_MM64R6 : StdMMR6Rel, DSUB_MM64R6_DESC, DSUB_MM64R6_ENC, + ISA_MICROMIPS64R6; + def DSUBU_MM64R6 : StdMMR6Rel, DSUBU_MM64R6_DESC, DSUBU_MM64R6_ENC, + ISA_MICROMIPS64R6; + def DMUL_MM64R6 : R6MMR6Rel, DMUL_MM64R6_DESC, DMUL_MM64R6_ENC, + ISA_MICROMIPS64R6; + def DMUH_MM64R6 : R6MMR6Rel, DMUH_MM64R6_DESC, DMUH_MM64R6_ENC, + ISA_MICROMIPS64R6; + def DMULU_MM64R6 : R6MMR6Rel, DMULU_MM64R6_DESC, DMULU_MM64R6_ENC, + ISA_MICROMIPS64R6; + def DMUHU_MM64R6 : R6MMR6Rel, DMUHU_MM64R6_DESC, DMUHU_MM64R6_ENC, + ISA_MICROMIPS64R6; + def DSBH_MM64R6 : R6MMR6Rel, DSBH_MM64R6_ENC, DSBH_MM64R6_DESC, + ISA_MICROMIPS64R6; + def DSHD_MM64R6 : R6MMR6Rel, DSHD_MM64R6_ENC, DSHD_MM64R6_DESC, + ISA_MICROMIPS64R6; + def DSLL_MM64R6 : StdMMR6Rel, DSLL_MM64R6_ENC, DSLL_MM64R6_DESC, + ISA_MICROMIPS64R6; + def DSLL32_MM64R6 : StdMMR6Rel, DSLL32_MM64R6_ENC, DSLL32_MM64R6_DESC, + ISA_MICROMIPS64R6; + def DSLLV_MM64R6 : StdMMR6Rel, DSLLV_MM64R6_ENC, DSLLV_MM64R6_DESC, + ISA_MICROMIPS64R6; + def DSRAV_MM64R6 : StdMMR6Rel, DSRAV_MM64R6_ENC, DSRAV_MM64R6_DESC, + ISA_MICROMIPS64R6; + def DSRA_MM64R6 : StdMMR6Rel, DSRA_MM64R6_ENC, DSRA_MM64R6_DESC, + ISA_MICROMIPS64R6; + def DSRA32_MM64R6 : StdMMR6Rel, DSRA32_MM64R6_ENC, DSRA32_MM64R6_DESC, + ISA_MICROMIPS64R6; + def DCLO_MM64R6 : StdMMR6Rel, R6MMR6Rel, DCLO_MM64R6_ENC, DCLO_MM64R6_DESC, + ISA_MICROMIPS64R6; + def DCLZ_MM64R6 : StdMMR6Rel, R6MMR6Rel, DCLZ_MM64R6_ENC, DCLZ_MM64R6_DESC, + ISA_MICROMIPS64R6; + def DROTR_MM64R6 : StdMMR6Rel, DROTR_MM64R6_ENC, DROTR_MM64R6_DESC, + ISA_MICROMIPS64R6; + def DROTR32_MM64R6 : StdMMR6Rel, DROTR32_MM64R6_ENC, DROTR32_MM64R6_DESC, + ISA_MICROMIPS64R6; + def DROTRV_MM64R6 : StdMMR6Rel, DROTRV_MM64R6_ENC, DROTRV_MM64R6_DESC, + ISA_MICROMIPS64R6; + def LD_MM64R6 : StdMMR6Rel, LD_MM64R6_ENC, LD_MM64R6_DESC, + ISA_MICROMIPS64R6; + def LLD_MM64R6 : StdMMR6Rel, R6MMR6Rel, LLD_MM64R6_ENC, LLD_MM64R6_DESC, + ISA_MICROMIPS64R6; + def LWU_MM64R6 : StdMMR6Rel, LWU_MM64R6_ENC, LWU_MM64R6_DESC, + ISA_MICROMIPS64R6; + def SD_MM64R6 : StdMMR6Rel, SD_MM64R6_ENC, SD_MM64R6_DESC, + ISA_MICROMIPS64R6; + def DSRL_MM64R6 : StdMMR6Rel, DSRL_MM64R6_ENC, DSRL_MM64R6_DESC, + ISA_MICROMIPS64R6; + def DSRL32_MM64R6 : StdMMR6Rel, DSRL32_MM64R6_ENC, DSRL32_MM64R6_DESC, + ISA_MICROMIPS64R6; + def DSRLV_MM64R6 : StdMMR6Rel, DSRLV_MM64R6_ENC, DSRLV_MM64R6_DESC, + ISA_MICROMIPS64R6; } + +//===----------------------------------------------------------------------===// +// +// Arbitrary patterns that map to one or more instructions +// +//===----------------------------------------------------------------------===// + +def : MipsPat<(MipsLo tglobaladdr:$in), + (DADDIU_MM64R6 ZERO_64, tglobaladdr:$in)>, ISA_MICROMIPS64R6; +def : MipsPat<(MipsLo tblockaddress:$in), + (DADDIU_MM64R6 ZERO_64, tblockaddress:$in)>, ISA_MICROMIPS64R6; +def : MipsPat<(MipsLo tjumptable:$in), + (DADDIU_MM64R6 ZERO_64, tjumptable:$in)>, ISA_MICROMIPS64R6; +def : MipsPat<(MipsLo tconstpool:$in), + (DADDIU_MM64R6 ZERO_64, tconstpool:$in)>, ISA_MICROMIPS64R6; +def : MipsPat<(MipsLo tglobaltlsaddr:$in), + (DADDIU_MM64R6 ZERO_64, tglobaltlsaddr:$in)>, ISA_MICROMIPS64R6; +def : MipsPat<(MipsLo texternalsym:$in), + (DADDIU_MM64R6 ZERO_64, texternalsym:$in)>, ISA_MICROMIPS64R6; + +def : MipsPat<(add GPR64:$hi, (MipsLo tglobaladdr:$lo)), + (DADDIU_MM64R6 GPR64:$hi, tglobaladdr:$lo)>, ISA_MICROMIPS64R6; +def : MipsPat<(add GPR64:$hi, (MipsLo tblockaddress:$lo)), + (DADDIU_MM64R6 GPR64:$hi, tblockaddress:$lo)>, ISA_MICROMIPS64R6; +def : MipsPat<(add GPR64:$hi, (MipsLo tjumptable:$lo)), + (DADDIU_MM64R6 GPR64:$hi, tjumptable:$lo)>, ISA_MICROMIPS64R6; +def : MipsPat<(add GPR64:$hi, (MipsLo tconstpool:$lo)), + (DADDIU_MM64R6 GPR64:$hi, tconstpool:$lo)>, ISA_MICROMIPS64R6; +def : MipsPat<(add GPR64:$hi, (MipsLo tglobaltlsaddr:$lo)), + (DADDIU_MM64R6 GPR64:$hi, tglobaltlsaddr:$lo)>, ISA_MICROMIPS64R6; + +def : MipsPat<(addc GPR64:$lhs, GPR64:$rhs), + (DADDU_MM64R6 GPR64:$lhs, GPR64:$rhs)>, ISA_MICROMIPS64R6; +def : MipsPat<(addc GPR64:$lhs, immSExt16:$imm), + (DADDIU_MM64R6 GPR64:$lhs, imm:$imm)>, ISA_MICROMIPS64R6; + + +def : MipsPat<(rotr GPR64:$rt, (i32 (trunc GPR64:$rs))), + (DROTRV_MM64R6 GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>, + ISA_MICROMIPS64R6; + + +def : WrapperPat<tglobaladdr, DADDIU_MM64R6, GPR64>, ISA_MICROMIPS64R6; +def : WrapperPat<tconstpool, DADDIU_MM64R6, GPR64>, ISA_MICROMIPS64R6; +def : WrapperPat<texternalsym, DADDIU_MM64R6, GPR64>, ISA_MICROMIPS64R6; +def : WrapperPat<tblockaddress, DADDIU_MM64R6, GPR64>, ISA_MICROMIPS64R6; +def : WrapperPat<tjumptable, DADDIU_MM64R6, GPR64>, ISA_MICROMIPS64R6; +def : WrapperPat<tglobaltlsaddr, DADDIU_MM64R6, GPR64>, ISA_MICROMIPS64R6; + +// Carry pattern +def : MipsPat<(subc GPR64:$lhs, GPR64:$rhs), + (DSUBU_MM64R6 GPR64:$lhs, GPR64:$rhs)>, ISA_MICROMIPS64R6; + +def : MipsPat<(atomic_load_64 addr:$a), (LD_MM64R6 addr:$a)>, ISA_MICROMIPS64R6; + +//===----------------------------------------------------------------------===// +// +// Instruction aliases +// +//===----------------------------------------------------------------------===// + +def : MipsInstAlias<"dmtc0 $rt, $rd", + (DMTC0_MM64R6 COP0Opnd:$rd, GPR64Opnd:$rt, 0), 0>; +def : MipsInstAlias<"dmfc0 $rt, $rd", + (DMFC0_MM64R6 GPR64Opnd:$rt, COP0Opnd:$rd, 0), 0>, + ISA_MICROMIPS64R6; +def : MipsInstAlias<"daddu $rs, $rt, $imm", + (DADDIU_MM64R6 GPR64Opnd:$rs, + GPR64Opnd:$rt, + simm16_64:$imm), + 0>, ISA_MICROMIPS64R6; +def : MipsInstAlias<"daddu $rs, $imm", + (DADDIU_MM64R6 GPR64Opnd:$rs, + GPR64Opnd:$rs, + simm16_64:$imm), + 0>, ISA_MICROMIPS64R6; +def : MipsInstAlias<"dsubu $rt, $rs, $imm", + (DADDIU_MM64R6 GPR64Opnd:$rt, + GPR64Opnd:$rs, + InvertedImOperand64:$imm), + 0>, ISA_MICROMIPS64R6; +def : MipsInstAlias<"dsubu $rs, $imm", + (DADDIU_MM64R6 GPR64Opnd:$rs, + GPR64Opnd:$rs, + InvertedImOperand64:$imm), + 0>, ISA_MICROMIPS64R6; +def : MipsInstAlias<"dneg $rt, $rs", + (DSUB_MM64R6 GPR64Opnd:$rt, ZERO_64, GPR64Opnd:$rs), 1>, + ISA_MICROMIPS64R6; +def : MipsInstAlias<"dneg $rt", + (DSUB_MM64R6 GPR64Opnd:$rt, ZERO_64, GPR64Opnd:$rt), 0>, + ISA_MICROMIPS64R6; +def : MipsInstAlias<"dnegu $rt, $rs", + (DSUBU_MM64R6 GPR64Opnd:$rt, ZERO_64, GPR64Opnd:$rs), 1>, + ISA_MICROMIPS64R6; +def : MipsInstAlias<"dnegu $rt", + (DSUBU_MM64R6 GPR64Opnd:$rt, ZERO_64, GPR64Opnd:$rt), 0>, + ISA_MICROMIPS64R6; diff --git a/lib/Target/Mips/MicroMipsDSPInstrFormats.td b/lib/Target/Mips/MicroMipsDSPInstrFormats.td index f11c09abfc367..af6473c468d9b 100644 --- a/lib/Target/Mips/MicroMipsDSPInstrFormats.td +++ b/lib/Target/Mips/MicroMipsDSPInstrFormats.td @@ -242,3 +242,61 @@ class POOL32A_5B01RAC_FMT<string opstr, bits<8> op> : MMDSPInst<opstr> { let Inst{13-6} = op; let Inst{5-0} = 0b111100; } + +class POOL32I_IMMB0_FMT<string opstr, bits<5> op> : MMDSPInst<opstr> { + bits<16> offset; + + let Inst{31-26} = 0b010000; + let Inst{25-21} = op; + let Inst{20-16} = 0; + let Inst{15-0} = offset; +} + +class POOL32A_2RBP_FMT<string opstr> : MMDSPInst<opstr> { + bits<5> rt; + bits<5> rs; + bits<2> bp; + + let Inst{31-26} = 0; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-14} = bp; + let Inst{13-6} = 0b00100010; + let Inst{5-0} = 0b111100; +} + +class POOL32A_2RB0_FMT<string opstr, bits<10> op> : MMDSPInst<opstr> { + bits<5> rt; + bits<5> rs; + + let Inst{31-26} = 0; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-10} = 0; + let Inst{9-0} = op; +} + +class POOL32S_3RB0_FMT<string opstr, bits<10> op> : MMDSPInst<opstr> { + bits<5> rt; + bits<5> rs; + bits<5> rd; + + let Inst{31-26} = 0b010110; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-11} = rd; + let Inst{10} = 0b0; + let Inst{9-0} = op; +} + +class POOL32A_2R2B0_FMT<string opstr, bits<10> op> : MMDSPInst<opstr> { + bits<5> rt; + bits<5> rs; + + let Inst{31-26} = 0; + let Inst{25-21} = rt; + let Inst{20-16} = rs; + let Inst{15-11} = 0; + let Inst{10} = 0; + let Inst{9-0} = op; +} diff --git a/lib/Target/Mips/MicroMipsDSPInstrInfo.td b/lib/Target/Mips/MicroMipsDSPInstrInfo.td index b342e2371df4c..f82f82fc7e45b 100644 --- a/lib/Target/Mips/MicroMipsDSPInstrInfo.td +++ b/lib/Target/Mips/MicroMipsDSPInstrInfo.td @@ -155,6 +155,26 @@ class PICK_QB_MM_ENC : POOL32A_3RB0_FMT<"pick.qb", 0b0111101101>; class SHILO_MM_ENC : POOL32A_4B0SHIFT6AC4B0_FMT<"shilo", 0b0000011101>; class SHILOV_MM_ENC : POOL32A_5B01RAC_FMT<"shilov", 0b01001001>; class WRDSP_MM_ENC : POOL32A_1RMASK7_FMT<"wrdsp", 0b01011001>; +class APPEND_MMR2_ENC : POOL32A_2RSA5B0_FMT<"append", 0b1000010101>; +class MODSUB_MM_ENC : POOL32A_3RB0_FMT<"modsub", 0b1010010101>; +class MULSA_W_PH_MMR2_ENC : POOL32A_2RAC_FMT<"mulsa.w.ph", 0b10110010>; +class MULSAQ_S_W_PH_MM_ENC : POOL32A_2RAC_FMT<"mulsaq_s.w.ph", 0b11110010>; +class BPOSGE32C_MMR3_ENC : POOL32I_IMMB0_FMT<"bposge32c", 0b11001>; +class BITREV_MM_ENC : POOL32A_2R_FMT<"bitrev", 0b0011000100>; +class BALIGN_MMR2_ENC : POOL32A_2RBP_FMT<"balign">; +class BPOSGE32_MM_ENC : POOL32I_IMMB0_FMT<"bposge32", 0b11011>; +class CMP_EQ_PH_MM_ENC : POOL32A_2RB0_FMT<"cmp.eq.ph", 0b0000000101>; +class CMP_LE_PH_MM_ENC : POOL32A_2RB0_FMT<"cmp.le.ph", 0b0010000101>; +class CMP_LT_PH_MM_ENC : POOL32A_2RB0_FMT<"cmp.lt.ph", 0b0001000101>; +class CMPGDU_EQ_QB_MMR2_ENC : POOL32A_3RB0_FMT<"cmpgdu.eq.qb", 0b0110000101>; +class CMPGDU_LT_QB_MMR2_ENC : POOL32A_3RB0_FMT<"cmpgdu.lt.qb", 0b0111000101>; +class CMPGDU_LE_QB_MMR2_ENC : POOL32A_3RB0_FMT<"cmpgdu.le.qb", 0b1000000101>; +class CMPGU_EQ_QB_MM_ENC : POOL32S_3RB0_FMT<"cmpgu.eq.qb", 0b0011000101>; +class CMPGU_LT_QB_MM_ENC : POOL32S_3RB0_FMT<"cmpgu.lt.qb", 0b0100000101>; +class CMPGU_LE_QB_MM_ENC : POOL32S_3RB0_FMT<"cmpgu.le.qb", 0b0101000101>; +class CMPU_EQ_QB_MM_ENC : POOL32A_2R2B0_FMT<"cmpu.eq.qb", 0b1001000101>; +class CMPU_LT_QB_MM_ENC : POOL32A_2R2B0_FMT<"cmpu.lt.qb", 0b1010000101>; +class CMPU_LE_QB_MM_ENC : POOL32A_2R2B0_FMT<"cmpu.le.qb", 0b1011000101>; // Instruction desc. class ABSQ_S_PH_MM_R2_DESC_BASE<string opstr, SDPatternOperator OpNode, @@ -339,15 +359,15 @@ class RADDU_W_QB_MM_DESC { class RDDSP_MM_DESC { dag OutOperandList = (outs GPR32Opnd:$rt); - dag InOperandList = (ins uimm16:$mask); + dag InOperandList = (ins uimm7:$mask); string AsmString = !strconcat("rddsp", "\t$rt, $mask"); - list<dag> Pattern = [(set GPR32Opnd:$rt, (int_mips_rddsp immZExt10:$mask))]; + list<dag> Pattern = [(set GPR32Opnd:$rt, (int_mips_rddsp immZExt7:$mask))]; InstrItinClass Itinerary = NoItinerary; } class REPL_QB_MM_DESC { dag OutOperandList = (outs DSPROpnd:$rt); - dag InOperandList = (ins uimm16:$imm); + dag InOperandList = (ins uimm8:$imm); string AsmString = !strconcat("repl.qb", "\t$rt, $imm"); list<dag> Pattern = [(set DSPROpnd:$rt, (int_mips_repl_qb immZExt8:$imm))]; InstrItinClass Itinerary = NoItinerary; @@ -368,6 +388,33 @@ class WRDSP_MM_DESC { InstrItinClass Itinerary = NoItinerary; } +class BPOSGE32C_MMR3_DESC { + dag OutOperandList = (outs); + dag InOperandList = (ins brtarget1SImm16:$offset); + string AsmString = !strconcat("bposge32c", "\t$offset"); + InstrItinClass Itinerary = NoItinerary; + bit isBranch = 1; + bit isTerminator = 1; + bit hasDelaySlot = 0; +} + +class BALIGN_MMR2_DESC { + dag OutOperandList = (outs GPR32Opnd:$rt); + dag InOperandList = (ins GPR32Opnd:$rs, uimm2:$bp, GPR32Opnd:$src); + string AsmString = !strconcat("balign", "\t$rt, $rs, $bp"); + list<dag> Pattern = [(set GPR32Opnd:$rt, (int_mips_balign GPR32Opnd:$src, + GPR32Opnd:$rs, + immZExt2:$bp))]; + InstrItinClass Itinerary = NoItinerary; + string Constraints = "$src = $rt"; +} + +class BITREV_MM_DESC : ABSQ_S_PH_MM_R2_DESC_BASE<"bitrev", int_mips_bitrev, + NoItinerary, GPR32Opnd>; + +class BPOSGE32_MM_DESC : BPOSGE32_DESC_BASE<"bposge32", brtarget_mm, + NoItinerary>; + // Instruction defs. // microMIPS DSP Rev 1 def ADDQ_PH_MM : DspMMRel, ADDQ_PH_MM_ENC, ADDQ_PH_DESC; @@ -472,6 +519,20 @@ def PICK_QB_MM : DspMMRel, PICK_QB_MM_ENC, PICK_QB_DESC; def SHILO_MM : DspMMRel, SHILO_MM_ENC, SHILO_DESC; def SHILOV_MM : DspMMRel, SHILOV_MM_ENC, SHILOV_DESC; def WRDSP_MM : DspMMRel, WRDSP_MM_ENC, WRDSP_MM_DESC; +def MODSUB_MM : DspMMRel, MODSUB_MM_ENC, MODSUB_DESC; +def MULSAQ_S_W_PH_MM : DspMMRel, MULSAQ_S_W_PH_MM_ENC, MULSAQ_S_W_PH_DESC; +def BITREV_MM : DspMMRel, BITREV_MM_ENC, BITREV_MM_DESC; +def BPOSGE32_MM : DspMMRel, BPOSGE32_MM_ENC, BPOSGE32_MM_DESC, + ISA_MIPS1_NOT_32R6_64R6; +def CMP_EQ_PH_MM : DspMMRel, CMP_EQ_PH_MM_ENC, CMP_EQ_PH_DESC; +def CMP_LT_PH_MM : DspMMRel, CMP_LT_PH_MM_ENC, CMP_LT_PH_DESC; +def CMP_LE_PH_MM : DspMMRel, CMP_LE_PH_MM_ENC, CMP_LE_PH_DESC; +def CMPGU_EQ_QB_MM : DspMMRel, CMPGU_EQ_QB_MM_ENC, CMPGU_EQ_QB_DESC; +def CMPGU_LT_QB_MM : DspMMRel, CMPGU_LT_QB_MM_ENC, CMPGU_LT_QB_DESC; +def CMPGU_LE_QB_MM : DspMMRel, CMPGU_LE_QB_MM_ENC, CMPGU_LE_QB_DESC; +def CMPU_EQ_QB_MM : DspMMRel, CMPU_EQ_QB_MM_ENC, CMPU_EQ_QB_DESC; +def CMPU_LT_QB_MM : DspMMRel, CMPU_LT_QB_MM_ENC, CMPU_LT_QB_DESC; +def CMPU_LE_QB_MM : DspMMRel, CMPU_LE_QB_MM_ENC, CMPU_LE_QB_DESC; // microMIPS DSP Rev 2 def ABSQ_S_QB_MMR2 : DspMMRel, ABSQ_S_QB_MMR2_ENC, ABSQ_S_QB_MMR2_DESC, ISA_DSPR2; @@ -495,6 +556,13 @@ def SHRA_R_QB_MMR2 : DspMMRel, SHRA_R_QB_MMR2_ENC, SHRA_R_QB_MMR2_DESC, def SHRAV_QB_MMR2 : DspMMRel, SHRAV_QB_MMR2_ENC, SHRAV_QB_MMR2_DESC, ISA_DSPR2; def SHRAV_R_QB_MMR2 : DspMMRel, SHRAV_R_QB_MMR2_ENC, SHRAV_R_QB_MMR2_DESC, ISA_DSPR2; +def BALIGN_MMR2 : DspMMRel, BALIGN_MMR2_ENC, BALIGN_MMR2_DESC, ISA_DSPR2; +def CMPGDU_EQ_QB_MMR2 : DspMMRel, CMPGDU_EQ_QB_MMR2_ENC, CMPGDU_EQ_QB_DESC, + ISA_DSPR2; +def CMPGDU_LT_QB_MMR2 : DspMMRel, CMPGDU_LT_QB_MMR2_ENC, CMPGDU_LT_QB_DESC, + ISA_DSPR2; +def CMPGDU_LE_QB_MMR2 : DspMMRel, CMPGDU_LE_QB_MMR2_ENC, CMPGDU_LE_QB_DESC, + ISA_DSPR2; def SHRL_PH_MMR2 : DspMMRel, SHRL_PH_MMR2_ENC, SHRL_PH_MMR2_DESC, ISA_DSPR2; def SHRLV_PH_MMR2 : DspMMRel, SHRLV_PH_MMR2_ENC, SHRLV_PH_MMR2_DESC, ISA_DSPR2; def SUBQH_PH_MMR2 : DspMMRel, SUBQH_PH_MMR2_ENC, SUBQH_PH_DESC, ISA_DSPR2; @@ -526,3 +594,8 @@ def PREPEND_MMR2 : DspMMRel, PREPEND_MMR2_ENC, PREPEND_DESC, ISA_DSPR2; // Instruction alias. def : MMDSPInstAlias<"wrdsp $rt", (WRDSP_MM GPR32Opnd:$rt, 0x1F), 1>; +def APPEND_MMR2 : DspMMRel, APPEND_MMR2_ENC, APPEND_DESC, ISA_DSPR2; +def MULSA_W_PH_MMR2 : DspMMRel, MULSA_W_PH_MMR2_ENC, MULSA_W_PH_DESC, ISA_DSPR2; +// microMIPS DSP Rev 3 +def BPOSGE32C_MMR3 : DspMMRel, BPOSGE32C_MMR3_ENC, BPOSGE32C_MMR3_DESC, + ISA_DSPR3; diff --git a/lib/Target/Mips/MicroMipsInstrFPU.td b/lib/Target/Mips/MicroMipsInstrFPU.td index 756e6c92c1d11..7b0e00bd1c3c6 100644 --- a/lib/Target/Mips/MicroMipsInstrFPU.td +++ b/lib/Target/Mips/MicroMipsInstrFPU.td @@ -17,12 +17,6 @@ def FMUL_MM : MMRel, ADDS_FT<"mul.d", AFGR64Opnd, II_MUL_D, 1, fmul>, def FSUB_MM : MMRel, ADDS_FT<"sub.d", AFGR64Opnd, II_SUB_D, 0, fsub>, ADDS_FM_MM<1, 0x70>; -def LWC1_MM : MMRel, LW_FT<"lwc1", FGR32Opnd, II_LWC1, load>, LW_FM_MM<0x27>; -def SWC1_MM : MMRel, SW_FT<"swc1", FGR32Opnd, II_SWC1, store>, - LW_FM_MM<0x26>; -def LDC1_MM : MMRel, LW_FT<"ldc1", AFGR64Opnd, II_LDC1, load>, LW_FM_MM<0x2f>; -def SDC1_MM : MMRel, SW_FT<"sdc1", AFGR64Opnd, II_SDC1, store>, - LW_FM_MM<0x2e>; def LWXC1_MM : MMRel, LWXC1_FT<"lwxc1", FGR32Opnd, II_LWXC1, load>, LWXC1_FM_MM<0x48>, INSN_MIPS4_32R2_NOT_32R6_64R6; def SWXC1_MM : MMRel, SWXC1_FT<"swxc1", FGR32Opnd, II_SWXC1, store>, @@ -114,10 +108,6 @@ def MFC1_MM : MMRel, MFC1_FT<"mfc1", GPR32Opnd, FGR32Opnd, II_MFC1, bitconvert>, MFC1_FM_MM<0x80>; 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, FGR_32; -def MTHC1_MM : MMRel, MTC1_64_FT<"mthc1", AFGR64Opnd, GPR32Opnd, II_MTHC1>, - 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>; @@ -147,4 +137,33 @@ let AdditionalPredicates = [InMicroMips] in { ROUND_W_FM_MM<0, 0x6c>; def FSQRT_S_MM : MMRel, ABSS_FT<"sqrt.s", FGR32Opnd, FGR32Opnd, II_SQRT_S, fsqrt>, ROUND_W_FM_MM<0, 0x28>; + def MTHC1_MM : MMRel, MTC1_64_FT<"mthc1", AFGR64Opnd, GPR32Opnd, II_MTHC1>, + MFC1_FM_MM<0xe0>, ISA_MIPS32R2, FGR_32; + def MFHC1_MM : MMRel, MFC1_FT<"mfhc1", GPR32Opnd, AFGR64Opnd, II_MFHC1>, + MFC1_FM_MM<0xc0>, ISA_MIPS32R2, FGR_32; + let DecoderNamespace = "MicroMips", DecoderMethod = "DecodeFMemMMR2" in { + def LDC1_MM : MMRel, LW_FT<"ldc1", AFGR64Opnd, mem_mm_16, II_LDC1, load>, + LW_FM_MM<0x2f>, FGR_32 { + let BaseOpcode = "LDC132"; + } + def SDC1_MM : MMRel, SW_FT<"sdc1", AFGR64Opnd, mem_mm_16, II_SDC1, store>, + LW_FM_MM<0x2e>, FGR_32; + def LWC1_MM : MMRel, LW_FT<"lwc1", FGR32Opnd, mem_mm_16, II_LWC1, load>, + LW_FM_MM<0x27>; + def SWC1_MM : MMRel, SW_FT<"swc1", FGR32Opnd, mem_mm_16, II_SWC1, store>, + LW_FM_MM<0x26>; + } +} + +//===----------------------------------------------------------------------===// +// Floating Point Patterns +//===----------------------------------------------------------------------===// +let AdditionalPredicates = [InMicroMips] in { + // Patterns for loads/stores with a reg+imm operand. + let AddedComplexity = 40 in { + def : LoadRegImmPat<LDC1_MM, f64, load>, FGR_32; + def : StoreRegImmPat<SDC1_MM, f64>, FGR_32; + def : LoadRegImmPat<LWC1_MM, f32, load>; + def : StoreRegImmPat<SWC1_MM, f32>; + } } diff --git a/lib/Target/Mips/MicroMipsInstrFormats.td b/lib/Target/Mips/MicroMipsInstrFormats.td index b736367ee5fa5..79ef6482180db 100644 --- a/lib/Target/Mips/MicroMipsInstrFormats.td +++ b/lib/Target/Mips/MicroMipsInstrFormats.td @@ -278,7 +278,6 @@ class MOVEP_FM_MM16 { class MMArch { string Arch = "micromips"; - list<dag> Pattern = []; } class ADD_FM_MM<bits<6> op, bits<10> funct> : MMArch { @@ -380,13 +379,15 @@ class SRLV_FM_MM<bits<10> funct, bit rotate> : MMArch { class LW_FM_MM<bits<6> op> : MMArch { bits<5> rt; bits<21> addr; + bits<5> base = addr{20-16}; + bits<16> offset = addr{15-0}; bits<32> Inst; let Inst{31-26} = op; let Inst{25-21} = rt; - let Inst{20-16} = addr{20-16}; - let Inst{15-0} = addr{15-0}; + let Inst{20-16} = base; + let Inst{15-0} = offset; } class POOL32C_LHUE_FM_MM<bits<6> op, bits<4> fmt, bits<3> funct> : MMArch { @@ -674,7 +675,7 @@ class TEQI_FM_MM<bits<5> funct> : MMArch { let Inst{15-0} = imm16; } -class LL_FM_MM<bits<4> funct> { +class LL_FM_MM<bits<4> funct> : MMArch { bits<5> rt; bits<21> addr; diff --git a/lib/Target/Mips/MicroMipsInstrInfo.td b/lib/Target/Mips/MicroMipsInstrInfo.td index 99f0f446deabe..f27370f57fa00 100644 --- a/lib/Target/Mips/MicroMipsInstrInfo.td +++ b/lib/Target/Mips/MicroMipsInstrInfo.td @@ -1,23 +1,8 @@ -def addrimm12 : ComplexPattern<iPTR, 2, "selectIntAddrMM", [frameindex]>; +def addrimm11 : ComplexPattern<iPTR, 2, "selectIntAddr11MM", [frameindex]>; +def addrimm12 : ComplexPattern<iPTR, 2, "selectIntAddr12MM", [frameindex]>; +def addrimm16 : ComplexPattern<iPTR, 2, "selectIntAddr16MM", [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"; -} - -def simm12 : Operand<i32> { - let DecoderMethod = "DecodeSimm12"; -} - -def uimm6_lsl2 : Operand<i32> { - let EncoderMethod = "getUImm6Lsl2Encoding"; - let DecoderMethod = "DecodeUImm6Lsl2"; -} - def simm9_addiusp : Operand<i32> { let EncoderMethod = "getSImm9AddiuspValue"; let DecoderMethod = "DecodeSimm9SP"; @@ -60,9 +45,15 @@ def MicroMipsMemGPRMM16AsmOperand : AsmOperandClass { let PredicateMethod = "isMemWithGRPMM16Base"; } +// Define the classes of pointers used by microMIPS. +// The numbers must match those in MipsRegisterInfo::MipsPtrClass. +def ptr_gpr16mm_rc : PointerLikeRegClass<1>; +def ptr_sp_rc : PointerLikeRegClass<2>; +def ptr_gp_rc : PointerLikeRegClass<3>; + class mem_mm_4_generic : Operand<i32> { let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops GPRMM16, simm4); + let MIOperandInfo = (ops ptr_gpr16mm_rc, simm4); let OperandType = "OPERAND_MEMORY"; let ParserMatchClass = MicroMipsMemGPRMM16AsmOperand; } @@ -86,32 +77,48 @@ def MicroMipsMemSPAsmOperand : AsmOperandClass { let PredicateMethod = "isMemWithUimmWordAlignedOffsetSP<7>"; } +def MicroMipsMemGPAsmOperand : AsmOperandClass { + let Name = "MicroMipsMemGP"; + let RenderMethod = "addMemOperands"; + let ParserMethod = "parseMemOperand"; + let PredicateMethod = "isMemWithSimmWordAlignedOffsetGP<9>"; +} + def mem_mm_sp_imm5_lsl2 : Operand<i32> { let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops GPR32:$base, simm5:$offset); + let MIOperandInfo = (ops ptr_sp_rc:$base, simm5:$offset); let OperandType = "OPERAND_MEMORY"; let ParserMatchClass = MicroMipsMemSPAsmOperand; let EncoderMethod = "getMemEncodingMMSPImm5Lsl2"; } -def mem_mm_gp_imm7_lsl2 : Operand<i32> { +def mem_mm_gp_simm7_lsl2 : Operand<i32> { let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops GPRMM16:$base, simm7:$offset); + let MIOperandInfo = (ops ptr_gp_rc:$base, simm7_lsl2:$offset); let OperandType = "OPERAND_MEMORY"; + let ParserMatchClass = MicroMipsMemGPAsmOperand; let EncoderMethod = "getMemEncodingMMGPImm7Lsl2"; } def mem_mm_9 : Operand<i32> { let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops GPR32, simm9); + let MIOperandInfo = (ops ptr_rc, simm9); let EncoderMethod = "getMemEncodingMMImm9"; - let ParserMatchClass = MipsMemAsmOperand; + let ParserMatchClass = MipsMemSimm9AsmOperand; + let OperandType = "OPERAND_MEMORY"; +} + +def mem_mm_11 : Operand<i32> { + let PrintMethod = "printMemOperand"; + let MIOperandInfo = (ops GPR32, simm11); + let EncoderMethod = "getMemEncodingMMImm11"; + let ParserMatchClass = MipsMemSimm11AsmOperand; let OperandType = "OPERAND_MEMORY"; } def mem_mm_12 : Operand<i32> { let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops GPR32, simm12); + let MIOperandInfo = (ops ptr_rc, simm12); let EncoderMethod = "getMemEncodingMMImm12"; let ParserMatchClass = MipsMemAsmOperand; let OperandType = "OPERAND_MEMORY"; @@ -119,9 +126,9 @@ def mem_mm_12 : Operand<i32> { def mem_mm_16 : Operand<i32> { let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops GPR32, simm16); + let MIOperandInfo = (ops ptr_rc, simm16); let EncoderMethod = "getMemEncodingMMImm16"; - let ParserMatchClass = MipsMemAsmOperand; + let ParserMatchClass = MipsMemSimm16AsmOperand; let OperandType = "OPERAND_MEMORY"; } @@ -135,7 +142,7 @@ def MipsMemUimm4AsmOperand : AsmOperandClass { def mem_mm_4sp : Operand<i32> { let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops GPR32, uimm8); + let MIOperandInfo = (ops ptr_sp_rc, uimm8); let EncoderMethod = "getMemEncodingMMImm4sp"; let ParserMatchClass = MipsMemUimm4AsmOperand; let OperandType = "OPERAND_MEMORY"; @@ -216,7 +223,7 @@ def movep_regpair : Operand<i32> { let ParserMatchClass = MovePRegPairAsmOperand; let PrintMethod = "printRegisterList"; let DecoderMethod = "DecodeMovePRegPair"; - let MIOperandInfo = (ops GPR32Opnd, GPR32Opnd); + let MIOperandInfo = (ops ptr_rc, ptr_rc); } class MovePMM16<string opstr, RegisterOperand RO> : @@ -230,6 +237,7 @@ MicroMipsInst16<(outs movep_regpair:$dst_regs), (ins RO:$rs, RO:$rt), def RegPairAsmOperand : AsmOperandClass { let Name = "RegPair"; let ParserMethod = "parseRegisterPair"; + let PredicateMethod = "isRegPair"; } def regpair : Operand<i32> { @@ -237,12 +245,12 @@ def regpair : Operand<i32> { let ParserMatchClass = RegPairAsmOperand; let PrintMethod = "printRegisterPair"; let DecoderMethod = "DecodeRegPairOperand"; - let MIOperandInfo = (ops GPR32Opnd, GPR32Opnd); + let MIOperandInfo = (ops ptr_rc, ptr_rc); } class StorePairMM<string opstr, InstrItinClass Itin = NoItinerary, ComplexPattern Addr = addr> : - InstSE<(outs), (ins regpair:$rt, mem_mm_12:$addr), + InstSE<(outs), (ins regpair:$rt, mem_simm12:$addr), !strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI, opstr> { let DecoderMethod = "DecodeMemMMImm12"; let mayStore = 1; @@ -250,7 +258,7 @@ class StorePairMM<string opstr, InstrItinClass Itin = NoItinerary, class LoadPairMM<string opstr, InstrItinClass Itin = NoItinerary, ComplexPattern Addr = addr> : - InstSE<(outs regpair:$rt), (ins mem_mm_12:$addr), + InstSE<(outs regpair:$rt), (ins mem_simm12:$addr), !strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI, opstr> { let DecoderMethod = "DecodeMemMMImm12"; let mayLoad = 1; @@ -264,7 +272,7 @@ class LLBaseMM<string opstr, RegisterOperand RO> : } class LLEBaseMM<string opstr, RegisterOperand RO> : - InstSE<(outs RO:$rt), (ins mem_mm_12:$addr), + InstSE<(outs RO:$rt), (ins mem_simm9:$addr), !strconcat(opstr, "\t$rt, $addr"), [], NoItinerary, FrmI> { let DecoderMethod = "DecodeMemMMImm9"; let mayLoad = 1; @@ -279,7 +287,7 @@ class SCBaseMM<string opstr, RegisterOperand RO> : } class SCEBaseMM<string opstr, RegisterOperand RO> : - InstSE<(outs RO:$dst), (ins RO:$rt, mem_mm_12:$addr), + InstSE<(outs RO:$dst), (ins RO:$rt, mem_simm9:$addr), !strconcat(opstr, "\t$rt, $addr"), [], NoItinerary, FrmI> { let DecoderMethod = "DecodeMemMMImm9"; let mayStore = 1; @@ -287,10 +295,10 @@ class SCEBaseMM<string opstr, RegisterOperand RO> : } class LoadMM<string opstr, DAGOperand RO, SDPatternOperator OpNode = null_frag, - InstrItinClass Itin = NoItinerary> : - InstSE<(outs RO:$rt), (ins mem_mm_12:$addr), + InstrItinClass Itin = NoItinerary, DAGOperand MO = mem_mm_12> : + InstSE<(outs RO:$rt), (ins MO:$addr), !strconcat(opstr, "\t$rt, $addr"), - [(set RO:$rt, (OpNode addrimm12:$addr))], Itin, FrmI> { + [(set RO:$rt, (OpNode addrimm12:$addr))], Itin, FrmI, opstr> { let DecoderMethod = "DecodeMemMMImm12"; let canFoldAsLoad = 1; let mayLoad = 1; @@ -615,7 +623,7 @@ 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>, +def LWGP_MM : LoadGPMM16<"lw", GPRMM16Opnd, II_LW, mem_mm_gp_simm7_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>; @@ -629,7 +637,7 @@ 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, +def LI16_MM : LoadImmMM16<"li16", li16_imm, GPRMM16Opnd>, LI_FM_MM16, IsAsCheapAsAMove; def JALR16_MM : JumpLinkRegMM16<"jalr", GPR32Opnd>, JALR_FM_MM16<0x0e>, ISA_MICROMIPS32_NOT_MIPS32R6; @@ -677,11 +685,11 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in { SLTI_FM_MM<0x2c>; def ANDi_MM : MMRel, ArithLogicI<"andi", uimm16, GPR32Opnd>, ADDI_FM_MM<0x34>; - def ORi_MM : MMRel, ArithLogicI<"ori", uimm16, GPR32Opnd>, - ADDI_FM_MM<0x14>; - def XORi_MM : MMRel, ArithLogicI<"xori", uimm16, GPR32Opnd>, - ADDI_FM_MM<0x1c>; - def LUi_MM : MMRel, LoadUpper<"lui", GPR32Opnd, uimm16>, LUI_FM_MM; + def ORi_MM : MMRel, ArithLogicI<"ori", uimm16, GPR32Opnd, II_ORI, immZExt16, + or>, ADDI_FM_MM<0x14>; + def XORi_MM : MMRel, ArithLogicI<"xori", uimm16, GPR32Opnd, II_XORI, + immZExt16, xor>, ADDI_FM_MM<0x1c>; + def LUi_MM : MMRel, LoadUpper<"lui", GPR32Opnd, uimm16_relaxed>, LUI_FM_MM; def LEA_ADDiu_MM : MMRel, EffectiveAddress<"addiu", GPR32Opnd>, LW_FM_MM<0xc>; @@ -709,9 +717,9 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in { def MULTu_MM : MMRel, Mult<"multu", II_MULTU, GPR32Opnd, [HI0, LO0]>, MULT_FM_MM<0x26c>; def SDIV_MM : MMRel, Div<"div", II_DIV, GPR32Opnd, [HI0, LO0]>, - MULT_FM_MM<0x2ac>; + MULT_FM_MM<0x2ac>, ISA_MIPS1_NOT_32R6_64R6; def UDIV_MM : MMRel, Div<"divu", II_DIVU, GPR32Opnd, [HI0, LO0]>, - MULT_FM_MM<0x2ec>; + MULT_FM_MM<0x2ec>, ISA_MIPS1_NOT_32R6_64R6; /// Arithmetic Instructions with PC and Immediate def ADDIUPC_MM : AddImmUPC<"addiupc", GPRMM16Opnd>, ADDIUPC_FM_MM; @@ -730,16 +738,24 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in { def SRAV_MM : MMRel, shift_rotate_reg<"srav", GPR32Opnd, II_SRAV>, SRLV_FM_MM<0x90, 0>; def ROTR_MM : MMRel, shift_rotate_imm<"rotr", uimm5, GPR32Opnd, II_ROTR>, - SRA_FM_MM<0xc0, 0>; + SRA_FM_MM<0xc0, 0> { + list<dag> Pattern = [(set GPR32Opnd:$rd, + (rotr GPR32Opnd:$rt, immZExt5:$shamt))]; + } def ROTRV_MM : MMRel, shift_rotate_reg<"rotrv", GPR32Opnd, II_ROTRV>, - SRLV_FM_MM<0xd0, 0>; + SRLV_FM_MM<0xd0, 0> { + list<dag> Pattern = [(set GPR32Opnd:$rd, + (rotr GPR32Opnd:$rt, GPR32Opnd:$rs))]; + } /// Load and Store Instructions - aligned let DecoderMethod = "DecodeMemMMImm16" in { - def LB_MM : Load<"lb", GPR32Opnd>, MMRel, LW_FM_MM<0x7>; - def LBu_MM : Load<"lbu", GPR32Opnd>, MMRel, LW_FM_MM<0x5>; - def LH_MM : Load<"lh", GPR32Opnd>, MMRel, LW_FM_MM<0xf>; - def LHu_MM : Load<"lhu", GPR32Opnd>, MMRel, LW_FM_MM<0xd>; + def LB_MM : LoadMemory<"lb", GPR32Opnd, mem_mm_16>, MMRel, LW_FM_MM<0x7>; + def LBu_MM : LoadMemory<"lbu", GPR32Opnd, mem_mm_16>, MMRel, LW_FM_MM<0x5>; + def LH_MM : LoadMemory<"lh", GPR32Opnd, mem_simm16, sextloadi16, II_LH, + addrDefault>, MMRel, LW_FM_MM<0xf>; + def LHu_MM : LoadMemory<"lhu", GPR32Opnd, mem_simm16, zextloadi16, II_LHU>, + MMRel, LW_FM_MM<0xd>; def LW_MM : Load<"lw", GPR32Opnd>, MMRel, LW_FM_MM<0x3f>; def SB_MM : Store<"sb", GPR32Opnd>, MMRel, LW_FM_MM<0x6>; def SH_MM : Store<"sh", GPR32Opnd>, MMRel, LW_FM_MM<0xe>; @@ -749,19 +765,22 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in { let DecoderMethod = "DecodeMemMMImm9" in { def LBE_MM : Load<"lbe", GPR32Opnd>, POOL32C_LHUE_FM_MM<0x18, 0x6, 0x4>; def LBuE_MM : Load<"lbue", GPR32Opnd>, POOL32C_LHUE_FM_MM<0x18, 0x6, 0x0>; - def LHE_MM : Load<"lhe", GPR32Opnd>, POOL32C_LHUE_FM_MM<0x18, 0x6, 0x5>; - def LHuE_MM : Load<"lhue", GPR32Opnd>, POOL32C_LHUE_FM_MM<0x18, 0x6, 0x1>; - def LWE_MM : Load<"lwe", GPR32Opnd>, POOL32C_LHUE_FM_MM<0x18, 0x6, 0x7>; - def SBE_MM : Store<"sbe", GPR32Opnd>, POOL32C_LHUE_FM_MM<0x18, 0xa, 0x4>; - def SHE_MM : Store<"she", GPR32Opnd>, POOL32C_LHUE_FM_MM<0x18, 0xa, 0x5>; - def SWE_MM : StoreMemory<"swe", GPR32Opnd, mem_simm9gpr>, + def LHE_MM : LoadMemory<"lhe", GPR32Opnd, mem_simm9>, + POOL32C_LHUE_FM_MM<0x18, 0x6, 0x5>; + def LHuE_MM : LoadMemory<"lhue", GPR32Opnd, mem_simm9>, + POOL32C_LHUE_FM_MM<0x18, 0x6, 0x1>; + def LWE_MM : LoadMemory<"lwe", GPR32Opnd, mem_simm9>, + POOL32C_LHUE_FM_MM<0x18, 0x6, 0x7>; + def SBE_MM : StoreMemory<"sbe", GPR32Opnd, mem_simm9>, + POOL32C_LHUE_FM_MM<0x18, 0xa, 0x4>; + def SHE_MM : StoreMemory<"she", GPR32Opnd, mem_simm9>, + POOL32C_LHUE_FM_MM<0x18, 0xa, 0x5>; + def SWE_MM : StoreMemory<"swe", GPR32Opnd, mem_simm9>, POOL32C_LHUE_FM_MM<0x18, 0xa, 0x7>; } def LWXS_MM : LoadWordIndexedScaledMM<"lwxs", GPR32Opnd>, LWXS_FM_MM<0x118>; - def LWU_MM : LoadMM<"lwu", GPR32Opnd, zextloadi32, II_LWU>, LL_FM_MM<0xe>; - /// Load and Store Instructions - unaligned def LWL_MM : LoadLeftRightMM<"lwl", MipsLWL, GPR32Opnd, mem_mm_12>, LWL_FM_MM<0x0>; @@ -772,13 +791,13 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in { def SWR_MM : StoreLeftRightMM<"swr", MipsSWR, GPR32Opnd, mem_mm_12>, LWL_FM_MM<0x9>; let DecoderMethod = "DecodeMemMMImm9" in { - def LWLE_MM : LoadLeftRightMM<"lwle", MipsLWL, GPR32Opnd, mem_mm_12>, + def LWLE_MM : LoadLeftRightMM<"lwle", MipsLWL, GPR32Opnd, mem_mm_9>, POOL32C_STEVA_LDEVA_FM_MM<0x6, 0x2>; - def LWRE_MM : LoadLeftRightMM<"lwre", MipsLWR, GPR32Opnd, mem_mm_12>, + def LWRE_MM : LoadLeftRightMM<"lwre", MipsLWR, GPR32Opnd, mem_mm_9>, POOL32C_STEVA_LDEVA_FM_MM<0x6, 0x3>; - def SWLE_MM : StoreLeftRightMM<"swle", MipsSWL, GPR32Opnd, mem_mm_12>, + def SWLE_MM : StoreLeftRightMM<"swle", MipsSWL, GPR32Opnd, mem_mm_9>, POOL32C_STEVA_LDEVA_FM_MM<0xa, 0x0>; - def SWRE_MM : StoreLeftRightMM<"swre", MipsSWR, GPR32Opnd, mem_mm_12>, + def SWRE_MM : StoreLeftRightMM<"swre", MipsSWR, GPR32Opnd, mem_mm_9>, POOL32C_STEVA_LDEVA_FM_MM<0xa, 0x1>, ISA_MIPS1_NOT_32R6_64R6; } @@ -845,10 +864,10 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in { def WSBH_MM : MMRel, SubwordSwap<"wsbh", GPR32Opnd, II_WSBH>, SEB_FM_MM<0x1ec>, ISA_MIPS32R2; // TODO: Add '0 < pos+size <= 32' constraint check to ext instruction - def EXT_MM : MMRel, ExtBase<"ext", GPR32Opnd, uimm5, uimm5_plus1, - MipsExt>, EXT_FM_MM<0x2c>; - def INS_MM : MMRel, InsBase<"ins", GPR32Opnd, uimm5, MipsIns>, - EXT_FM_MM<0x0c>; + def EXT_MM : MMRel, ExtBase<"ext", GPR32Opnd, uimm5, uimm5_plus1, immZExt5, + immZExt5Plus1, MipsExt>, EXT_FM_MM<0x2c>; + def INS_MM : MMRel, InsBase<"ins", GPR32Opnd, uimm5, uimm5_inssize_plus1, + MipsIns>, EXT_FM_MM<0x0c>; /// Jump Instructions let DecoderMethod = "DecodeJumpTargetMM" in { @@ -857,7 +876,8 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in { 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 JR_MM : MMRel, IndirectBranch<"jr", GPR32Opnd>, JR_FM_MM<0x3c>, + ISA_MICROMIPS32_NOT_MIPS32R6; def JALR_MM : JumpLinkReg<"jalr", GPR32Opnd>, JALR_FM_MM<0x03c>; /// Jump Instructions - Short Delay Slot @@ -891,7 +911,7 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in { /// Control Instructions def SYNC_MM : MMRel, SYNC_FT<"sync">, SYNC_FM_MM; def BREAK_MM : MMRel, BRK_FT<"break">, BRK_FM_MM; - def SYSCALL_MM : MMRel, SYS_FT<"syscall">, SYS_FM_MM; + def SYSCALL_MM : MMRel, SYS_FT<"syscall", uimm10>, SYS_FM_MM; def WAIT_MM : WaitMM<"wait">, WAIT_FM_MM; def ERET_MM : MMRel, ER_FT<"eret">, ER_FM_MM<0x3cd>; def DERET_MM : MMRel, ER_FT<"deret">, ER_FM_MM<0x38d>; @@ -901,12 +921,12 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in { ISA_MIPS32R2; /// Trap Instructions - def TEQ_MM : MMRel, TEQ_FT<"teq", GPR32Opnd>, TEQ_FM_MM<0x0>; - def TGE_MM : MMRel, TEQ_FT<"tge", GPR32Opnd>, TEQ_FM_MM<0x08>; - def TGEU_MM : MMRel, TEQ_FT<"tgeu", GPR32Opnd>, TEQ_FM_MM<0x10>; - def TLT_MM : MMRel, TEQ_FT<"tlt", GPR32Opnd>, TEQ_FM_MM<0x20>; - def TLTU_MM : MMRel, TEQ_FT<"tltu", GPR32Opnd>, TEQ_FM_MM<0x28>; - def TNE_MM : MMRel, TEQ_FT<"tne", GPR32Opnd>, TEQ_FM_MM<0x30>; + def TEQ_MM : MMRel, TEQ_FT<"teq", GPR32Opnd, uimm4>, TEQ_FM_MM<0x0>; + def TGE_MM : MMRel, TEQ_FT<"tge", GPR32Opnd, uimm4>, TEQ_FM_MM<0x08>; + def TGEU_MM : MMRel, TEQ_FT<"tgeu", GPR32Opnd, uimm4>, TEQ_FM_MM<0x10>; + def TLT_MM : MMRel, TEQ_FT<"tlt", GPR32Opnd, uimm4>, TEQ_FM_MM<0x20>; + def TLTU_MM : MMRel, TEQ_FT<"tltu", GPR32Opnd, uimm4>, TEQ_FM_MM<0x28>; + def TNE_MM : MMRel, TEQ_FT<"tne", GPR32Opnd, uimm4>, TEQ_FM_MM<0x30>; def TEQI_MM : MMRel, TEQI_FT<"teqi", GPR32Opnd>, TEQI_FM_MM<0x0e>; def TGEI_MM : MMRel, TEQI_FT<"tgei", GPR32Opnd>, TEQI_FM_MM<0x09>; @@ -931,9 +951,9 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in { let DecoderMethod = "DecodePrefeOpMM" in { def PREFE_MM : MMRel, CacheOp<"prefe", mem_mm_9>, - CACHE_PREFE_FM_MM<0x18, 0x2>; + CACHE_PREFE_FM_MM<0x18, 0x2>; def CACHEE_MM : MMRel, CacheOp<"cachee", mem_mm_9>, - CACHE_PREFE_FM_MM<0x18, 0x3>; + CACHE_PREFE_FM_MM<0x18, 0x3>; } def SSNOP_MM : MMRel, Barrier<"ssnop">, BARRIER_FM_MM<0x1>; def EHB_MM : MMRel, Barrier<"ehb">, BARRIER_FM_MM<0x3>; @@ -944,7 +964,7 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in { def TLBWI_MM : MMRel, TLB<"tlbwi">, COP0_TLB_FM_MM<0x8d>; def TLBWR_MM : MMRel, TLB<"tlbwr">, COP0_TLB_FM_MM<0xcd>; - def SDBBP_MM : MMRel, SYS_FT<"sdbbp">, SDBBP_FM_MM; + def SDBBP_MM : MMRel, SYS_FT<"sdbbp", uimm10>, SDBBP_FM_MM; def PREFX_MM : PrefetchIndexed<"prefx">, POOL32F_PREFX_FM_MM<0x15, 0x1A0>; } @@ -952,54 +972,80 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in { let DecoderNamespace = "MicroMips" in { def RDHWR_MM : MMRel, R6MMR6Rel, ReadHardware<GPR32Opnd, HWRegsOpnd>, RDHWR_FM_MM, ISA_MICROMIPS32_NOT_MIPS32R6; + def LWU_MM : MMRel, LoadMM<"lwu", GPR32Opnd, zextloadi32, II_LWU, + mem_simm12>, LL_FM_MM<0xe>, + ISA_MICROMIPS32_NOT_MIPS32R6; } -let Predicates = [InMicroMips] in { - //===----------------------------------------------------------------------===// // MicroMips arbitrary patterns that map to one or more instructions //===----------------------------------------------------------------------===// -def : MipsPat<(i32 immLi16:$imm), - (LI16_MM immLi16:$imm)>; -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)>; -def : MipsPat<(add GPR32:$src, immSExtAddius5:$imm), - (ADDIUS5_MM GPR32:$src, immSExtAddius5:$imm)>; -def : MipsPat<(add GPR32:$src, immSExt16:$imm), - (ADDiu_MM GPR32:$src, immSExt16:$imm)>; - -def : MipsPat<(and GPRMM16:$src, immZExtAndi16:$imm), - (ANDI16_MM GPRMM16:$src, immZExtAndi16:$imm)>; -def : MipsPat<(and GPR32:$src, immZExt16:$imm), - (ANDi_MM GPR32:$src, immZExt16:$imm)>; - -def : MipsPat<(shl GPRMM16:$src, immZExt2Shift:$imm), - (SLL16_MM GPRMM16:$src, immZExt2Shift:$imm)>; -def : MipsPat<(shl GPR32:$src, immZExt5:$imm), - (SLL_MM GPR32:$src, immZExt5:$imm)>; - -def : MipsPat<(srl GPRMM16:$src, immZExt2Shift:$imm), - (SRL16_MM 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)>; +let Predicates = [InMicroMips] in { + def : MipsPat<(i32 immLi16:$imm), + (LI16_MM immLi16:$imm)>; + def : MipsPat<(i32 immSExt16:$imm), + (ADDiu_MM ZERO, immSExt16:$imm)>; + def : MipsPat<(i32 immZExt16:$imm), + (ORi_MM ZERO, immZExt16:$imm)>; + + def : MipsPat<(not GPRMM16:$in), + (NOT16_MM GPRMM16:$in)>; + def : MipsPat<(not GPR32:$in), + (NOR_MM GPR32Opnd:$in, ZERO)>; + + def : MipsPat<(add GPRMM16:$src, immSExtAddiur2:$imm), + (ADDIUR2_MM GPRMM16:$src, immSExtAddiur2:$imm)>; + def : MipsPat<(add GPR32:$src, immSExtAddius5:$imm), + (ADDIUS5_MM GPR32:$src, immSExtAddius5:$imm)>; + def : MipsPat<(add GPR32:$src, immSExt16:$imm), + (ADDiu_MM GPR32:$src, immSExt16:$imm)>; + + def : MipsPat<(and GPRMM16:$src, immZExtAndi16:$imm), + (ANDI16_MM GPRMM16:$src, immZExtAndi16:$imm)>; + def : MipsPat<(and GPR32:$src, immZExt16:$imm), + (ANDi_MM GPR32:$src, immZExt16:$imm)>; + + def : MipsPat<(shl GPRMM16:$src, immZExt2Shift:$imm), + (SLL16_MM GPRMM16:$src, immZExt2Shift:$imm)>; + def : MipsPat<(shl GPR32:$src, immZExt5:$imm), + (SLL_MM GPR32:$src, immZExt5:$imm)>; + def : MipsPat<(shl GPR32:$lhs, GPR32:$rhs), + (SLLV_MM GPR32:$lhs, GPR32:$rhs)>; + + def : MipsPat<(srl GPRMM16:$src, immZExt2Shift:$imm), + (SRL16_MM GPRMM16:$src, immZExt2Shift:$imm)>; + def : MipsPat<(srl GPR32:$src, immZExt5:$imm), + (SRL_MM GPR32:$src, immZExt5:$imm)>; + def : MipsPat<(srl GPR32:$lhs, GPR32:$rhs), + (SRLV_MM GPR32:$lhs, GPR32:$rhs)>; + + def : MipsPat<(sra GPR32:$src, immZExt5:$imm), + (SRA_MM GPR32:$src, immZExt5:$imm)>; + def : MipsPat<(sra GPR32:$lhs, GPR32:$rhs), + (SRAV_MM GPR32:$lhs, GPR32:$rhs)>; + + 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)>; + def : MipsPat<(subc GPR32:$lhs, GPR32:$rhs), + (SUBu_MM GPR32:$lhs, GPR32:$rhs)>; +} + +let AddedComplexity = 40 in { + def : MipsPat<(i32 (sextloadi16 addrRegImm:$a)), + (LH_MM addrRegImm:$a)>; +} +def : MipsPat<(atomic_load_16 addr:$a), + (LH_MM addr:$a)>; +def : MipsPat<(i32 (extloadi16 addr:$src)), + (LHu_MM addr:$src)>; //===----------------------------------------------------------------------===// // MicroMips instruction aliases @@ -1011,24 +1057,62 @@ class UncondBranchMMPseudo<string opstr> : def B_MM_Pseudo : UncondBranchMMPseudo<"b">, ISA_MICROMIPS; +let Predicates = [InMicroMips] in { + def SDIV_MM_Pseudo : MultDivPseudo<SDIV_MM, ACC64, GPR32Opnd, MipsDivRem, + II_DIV, 0, 1, 1>, ISA_MIPS1_NOT_32R6_64R6; + def UDIV_MM_Pseudo : MultDivPseudo<UDIV_MM, ACC64, GPR32Opnd, MipsDivRemU, + II_DIVU, 0, 1, 1>, ISA_MIPS1_NOT_32R6_64R6; + def : MipsInstAlias<"wait", (WAIT_MM 0x0), 1>; def : MipsInstAlias<"nop", (SLL_MM ZERO, ZERO, 0), 1>; def : MipsInstAlias<"nop", (MOVE16_MM ZERO, ZERO), 1>; -} - -let Predicates = [InMicroMips] in { -def : MipsInstAlias<"ei", (EI_MM ZERO), 1>, ISA_MIPS32R2; -def : MipsInstAlias<"di", (DI_MM ZERO), 1>, ISA_MIPS32R2; -def : MipsInstAlias<"teq $rs, $rt", - (TEQ_MM GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>; -def : MipsInstAlias<"tge $rs, $rt", - (TGE_MM GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>; -def : MipsInstAlias<"tgeu $rs, $rt", - (TGEU_MM GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>; -def : MipsInstAlias<"tlt $rs, $rt", - (TLT_MM GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>; -def : MipsInstAlias<"tltu $rs, $rt", - (TLTU_MM GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>; -def : MipsInstAlias<"tne $rs, $rt", - (TNE_MM GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>; + def : MipsInstAlias<"ei", (EI_MM ZERO), 1>, ISA_MIPS32R2; + def : MipsInstAlias<"di", (DI_MM ZERO), 1>, ISA_MIPS32R2; + def : MipsInstAlias<"teq $rs, $rt", + (TEQ_MM GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>; + def : MipsInstAlias<"tge $rs, $rt", + (TGE_MM GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>; + def : MipsInstAlias<"tgeu $rs, $rt", + (TGEU_MM GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>; + def : MipsInstAlias<"tlt $rs, $rt", + (TLT_MM GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>; + def : MipsInstAlias<"tltu $rs, $rt", + (TLTU_MM GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>; + def : MipsInstAlias<"tne $rs, $rt", + (TNE_MM GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>; + def : MipsInstAlias<"sll $rd, $rt, $rs", + (SLLV_MM GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>; + def : MipsInstAlias<"sra $rd, $rt, $rs", + (SRAV_MM GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>; + def : MipsInstAlias<"srl $rd, $rt, $rs", + (SRLV_MM GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>; + def : MipsInstAlias<"sll $rd, $rt", + (SLLV_MM GPR32Opnd:$rd, GPR32Opnd:$rd, GPR32Opnd:$rt), 0>; + def : MipsInstAlias<"sra $rd, $rt", + (SRAV_MM GPR32Opnd:$rd, GPR32Opnd:$rd, GPR32Opnd:$rt), 0>; + def : MipsInstAlias<"srl $rd, $rt", + (SRLV_MM GPR32Opnd:$rd, GPR32Opnd:$rd, GPR32Opnd:$rt), 0>; + def : MipsInstAlias<"sll $rd, $shamt", + (SLL_MM GPR32Opnd:$rd, GPR32Opnd:$rd, uimm5:$shamt), 0>; + def : MipsInstAlias<"sra $rd, $shamt", + (SRA_MM GPR32Opnd:$rd, GPR32Opnd:$rd, uimm5:$shamt), 0>; + def : MipsInstAlias<"srl $rd, $shamt", + (SRL_MM GPR32Opnd:$rd, GPR32Opnd:$rd, uimm5:$shamt), 0>; + def : MipsInstAlias<"rotr $rt, $imm", + (ROTR_MM GPR32Opnd:$rt, GPR32Opnd:$rt, uimm5:$imm), 0>; + def : MipsInstAlias<"syscall", (SYSCALL_MM 0), 1>; + def : MipsInstAlias<"and $rs, $rt, $imm", + (ANDi_MM GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>; + def : MipsInstAlias<"and $rs, $imm", + (ANDi_MM GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm), 0>; + def : MipsInstAlias<"or $rs, $rt, $imm", + (ORi_MM GPR32Opnd:$rs, GPR32Opnd:$rt, uimm16:$imm), 0>; + def : MipsInstAlias<"or $rs, $imm", + (ORi_MM GPR32Opnd:$rs, GPR32Opnd:$rs, uimm16:$imm), 0>; + def : MipsInstAlias<"xor $rs, $rt, $imm", + (XORi_MM GPR32Opnd:$rs, GPR32Opnd:$rt, uimm16:$imm), 0>; + def : MipsInstAlias<"xor $rs, $imm", + (XORi_MM GPR32Opnd:$rs, GPR32Opnd:$rs, uimm16:$imm), 0>; + def : MipsInstAlias<"not $rt, $rs", + (NOR_MM GPR32Opnd:$rt, GPR32Opnd:$rs, ZERO), 0>; } diff --git a/lib/Target/Mips/Mips.h b/lib/Target/Mips/Mips.h index 671d7a87cc3d9..d9faf3325cacd 100644 --- a/lib/Target/Mips/Mips.h +++ b/lib/Target/Mips/Mips.h @@ -29,8 +29,9 @@ namespace llvm { FunctionPass *createMipsModuleISelDagPass(MipsTargetMachine &TM); FunctionPass *createMipsOptimizePICCallPass(MipsTargetMachine &TM); FunctionPass *createMipsDelaySlotFillerPass(MipsTargetMachine &TM); + FunctionPass *createMipsHazardSchedule(); FunctionPass *createMipsLongBranchPass(MipsTargetMachine &TM); - FunctionPass *createMipsConstantIslandPass(MipsTargetMachine &tm); + FunctionPass *createMipsConstantIslandPass(); } // end namespace llvm; #endif diff --git a/lib/Target/Mips/Mips.td b/lib/Target/Mips/Mips.td index 35352b6115c54..ea3fa0a9578e1 100644 --- a/lib/Target/Mips/Mips.td +++ b/lib/Target/Mips/Mips.td @@ -24,6 +24,8 @@ class PredicateControl { list<Predicate> EncodingPredicates = []; // Predicates for the GPR size such as IsGP64bit list<Predicate> GPRPredicates = []; + // Predicates for the PTR size such as IsPTR64bit + list<Predicate> PTRPredicates = []; // Predicates for the FGR size and layout such as IsFP64bit list<Predicate> FGRPredicates = []; // Predicates for the instruction group membership such as ISA's and ASE's @@ -34,6 +36,7 @@ class PredicateControl { list<Predicate> AdditionalPredicates = []; list<Predicate> Predicates = !listconcat(EncodingPredicates, GPRPredicates, + PTRPredicates, FGRPredicates, InsnPredicates, HardFloatPredicate, @@ -62,6 +65,8 @@ def MipsInstrInfo : InstrInfo; def FeatureNoABICalls : SubtargetFeature<"noabicalls", "NoABICalls", "true", "Disable SVR4-style position-independent code">; +def FeaturePTR64Bit : SubtargetFeature<"ptr64", "IsPTR64bit", "true", + "Pointers are 64-bit wide">; def FeatureGP64Bit : SubtargetFeature<"gp64", "IsGP64bit", "true", "General Purpose Registers are 64-bit wide">; def FeatureFP64Bit : SubtargetFeature<"fp64", "IsFP64bit", "true", diff --git a/lib/Target/Mips/Mips16FrameLowering.cpp b/lib/Target/Mips/Mips16FrameLowering.cpp index 26426c087164f..e937ffa7a7ab9 100644 --- a/lib/Target/Mips/Mips16FrameLowering.cpp +++ b/lib/Target/Mips/Mips16FrameLowering.cpp @@ -24,7 +24,6 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Target/TargetOptions.h" using namespace llvm; diff --git a/lib/Target/Mips/Mips16HardFloat.cpp b/lib/Target/Mips/Mips16HardFloat.cpp index b2bc7e74c706d..d2d1c65e40d94 100644 --- a/lib/Target/Mips/Mips16HardFloat.cpp +++ b/lib/Target/Mips/Mips16HardFloat.cpp @@ -261,7 +261,7 @@ static std::string swapFPIntParams(FPParamVariant PV, Module *M, bool LE, static void assureFPCallStub(Function &F, Module *M, const MipsTargetMachine &TM) { // for now we only need them for static relocation - if (TM.getRelocationModel() == Reloc::PIC_) + if (TM.isPositionIndependent()) return; LLVMContext &Context = M->getContext(); bool LE = TM.isLittleEndian(); @@ -387,11 +387,9 @@ static bool fixupFPReturnAndCall(Function &F, Module *M, bool Modified = false; LLVMContext &C = M->getContext(); Type *MyVoid = Type::getVoidTy(C); - for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB) - for (BasicBlock::iterator I = BB->begin(), E = BB->end(); - I != E; ++I) { - Instruction &Inst = *I; - if (const ReturnInst *RI = dyn_cast<ReturnInst>(I)) { + for (auto &BB: F) + for (auto &I: BB) { + if (const ReturnInst *RI = dyn_cast<ReturnInst>(&I)) { Value *RVal = RI->getReturnValue(); if (!RVal) continue; // @@ -425,17 +423,11 @@ static bool fixupFPReturnAndCall(Function &F, Module *M, A = A.addAttribute(C, AttributeSet::FunctionIndex, Attribute::NoInline); 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(); - Type* T = nullptr; - if (V) T = V->getType(); - PointerType *PFT = nullptr; - if (T) PFT = dyn_cast<PointerType>(T); - FunctionType *FT = nullptr; - if (PFT) FT = dyn_cast<FunctionType>(PFT->getElementType()); + CallInst::Create(F, Params, "", &I); + } else if (const CallInst *CI = dyn_cast<CallInst>(&I)) { + FunctionType *FT = CI->getFunctionType(); Function *F_ = CI->getCalledFunction(); - if (FT && needsFPReturnHelper(*FT) && + if (needsFPReturnHelper(*FT) && !(F_ && isIntrinsicInline(F_))) { Modified=true; F.addFnAttr("saveS2"); @@ -447,7 +439,7 @@ static bool fixupFPReturnAndCall(Function &F, Module *M, Modified=true; F.addFnAttr("saveS2"); } - if (TM.getRelocationModel() != Reloc::PIC_ ) { + if (!TM.isPositionIndependent()) { if (needsFPHelperFromSig(*F_)) { assureFPCallStub(*F_, M, TM); Modified=true; @@ -461,7 +453,7 @@ static bool fixupFPReturnAndCall(Function &F, Module *M, static void createFPFnStub(Function *F, Module *M, FPParamVariant PV, const MipsTargetMachine &TM) { - bool PicMode = TM.getRelocationModel() == Reloc::PIC_; + bool PicMode = TM.isPositionIndependent(); bool LE = TM.isLittleEndian(); LLVMContext &Context = M->getContext(); std::string Name = F->getName(); diff --git a/lib/Target/Mips/Mips16ISelDAGToDAG.cpp b/lib/Target/Mips/Mips16ISelDAGToDAG.cpp index 5a1c2c67cc704..0405291431cdb 100644 --- a/lib/Target/Mips/Mips16ISelDAGToDAG.cpp +++ b/lib/Target/Mips/Mips16ISelDAGToDAG.cpp @@ -14,7 +14,6 @@ #include "Mips16ISelDAGToDAG.h" #include "MCTargetDesc/MipsBaseInfo.h" #include "Mips.h" -#include "MipsAnalyzeImmediate.h" #include "MipsMachineFunction.h" #include "MipsRegisterInfo.h" #include "llvm/CodeGen/MachineConstantPool.h" @@ -43,8 +42,8 @@ bool Mips16DAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { return MipsDAGToDAGISel::runOnMachineFunction(MF); } /// Select multiply instructions. -std::pair<SDNode*, SDNode*> -Mips16DAGToDAGISel::selectMULT(SDNode *N, unsigned Opc, SDLoc DL, EVT Ty, +std::pair<SDNode *, SDNode *> +Mips16DAGToDAGISel::selectMULT(SDNode *N, unsigned Opc, const SDLoc &DL, EVT Ty, bool HasLo, bool HasHi) { SDNode *Lo = nullptr, *Hi = nullptr; SDNode *Mul = CurDAG->getMachineNode(Opc, DL, MVT::Glue, N->getOperand(0), @@ -81,125 +80,60 @@ void Mips16DAGToDAGISel::initGlobalBaseReg(MachineFunction &MF) { V1 = RegInfo.createVirtualRegister(RC); V2 = RegInfo.createVirtualRegister(RC); - BuildMI(MBB, I, DL, TII.get(Mips::GotPrologue16), V0). - addReg(V1, RegState::Define). - addExternalSymbol("_gp_disp", MipsII::MO_ABS_HI). - addExternalSymbol("_gp_disp", MipsII::MO_ABS_LO); + BuildMI(MBB, I, DL, TII.get(Mips::GotPrologue16), V0) + .addReg(V1, RegState::Define) + .addExternalSymbol("_gp_disp", MipsII::MO_ABS_HI) + .addExternalSymbol("_gp_disp", MipsII::MO_ABS_LO); BuildMI(MBB, I, DL, TII.get(Mips::SllX16), V2).addReg(V0).addImm(16); BuildMI(MBB, I, DL, TII.get(Mips::AdduRxRyRz16), GlobalBaseReg) - .addReg(V1).addReg(V2); -} - -// Insert instructions to initialize the Mips16 SP Alias register in the -// first MBB of the function. -// -void Mips16DAGToDAGISel::initMips16SPAliasReg(MachineFunction &MF) { - MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); - - if (!MipsFI->mips16SPAliasRegSet()) - return; - - MachineBasicBlock &MBB = MF.front(); - MachineBasicBlock::iterator I = MBB.begin(); - const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); - DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc(); - unsigned Mips16SPAliasReg = MipsFI->getMips16SPAliasReg(); - - BuildMI(MBB, I, DL, TII.get(Mips::MoveR3216), Mips16SPAliasReg) - .addReg(Mips::SP); + .addReg(V1) + .addReg(V2); } void Mips16DAGToDAGISel::processFunctionAfterISel(MachineFunction &MF) { initGlobalBaseReg(MF); - initMips16SPAliasReg(MF); -} - -/// getMips16SPAliasReg - Output the instructions required to put the -/// SP into a Mips16 accessible aliased register. -SDValue Mips16DAGToDAGISel::getMips16SPAliasReg() { - unsigned Mips16SPAliasReg = - MF->getInfo<MipsFunctionInfo>()->getMips16SPAliasReg(); - auto PtrVT = getTargetLowering()->getPointerTy(CurDAG->getDataLayout()); - return CurDAG->getRegister(Mips16SPAliasReg, PtrVT); } -void Mips16DAGToDAGISel::getMips16SPRefReg(SDNode *Parent, SDValue &AliasReg) { - auto PtrVT = getTargetLowering()->getPointerTy(CurDAG->getDataLayout()); - SDValue AliasFPReg = CurDAG->getRegister(Mips::S0, PtrVT); - if (Parent) { - switch (Parent->getOpcode()) { - case ISD::LOAD: { - LoadSDNode *SD = dyn_cast<LoadSDNode>(Parent); - switch (SD->getMemoryVT().getSizeInBits()) { - case 8: - case 16: - AliasReg = Subtarget->getFrameLowering()->hasFP(*MF) - ? AliasFPReg - : getMips16SPAliasReg(); - return; - } - break; - } - case ISD::STORE: { - StoreSDNode *SD = dyn_cast<StoreSDNode>(Parent); - switch (SD->getMemoryVT().getSizeInBits()) { - case 8: - case 16: - AliasReg = Subtarget->getFrameLowering()->hasFP(*MF) - ? AliasFPReg - : getMips16SPAliasReg(); - return; - } - break; - } - } - } - AliasReg = CurDAG->getRegister(Mips::SP, PtrVT); - return; - -} - -bool Mips16DAGToDAGISel::selectAddr16( - SDNode *Parent, SDValue Addr, SDValue &Base, SDValue &Offset, - SDValue &Alias) { +bool Mips16DAGToDAGISel::selectAddr(bool SPAllowed, SDValue Addr, SDValue &Base, + SDValue &Offset) { SDLoc DL(Addr); EVT ValTy = Addr.getValueType(); - 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, DL, ValTy); - getMips16SPRefReg(Parent, Alias); - return true; + if (SPAllowed) { + if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) { + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); + Offset = CurDAG->getTargetConstant(0, DL, ValTy); + return true; + } } // on PIC code Load GA if (Addr.getOpcode() == MipsISD::Wrapper) { - Base = Addr.getOperand(0); + Base = Addr.getOperand(0); Offset = Addr.getOperand(1); return true; } - if (TM.getRelocationModel() != Reloc::PIC_) { + if (!TM.isPositionIndependent()) { if ((Addr.getOpcode() == ISD::TargetExternalSymbol || - Addr.getOpcode() == ISD::TargetGlobalAddress)) + Addr.getOpcode() == ISD::TargetGlobalAddress)) return false; } // Addresses of the form FI+const or FI|const if (CurDAG->isBaseWithConstantOffset(Addr)) { ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)); if (isInt<16>(CN->getSExtValue())) { - // If the first operand is a FI, get the TargetFI Node - if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode> - (Addr.getOperand(0))) { - Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); - getMips16SPRefReg(Parent, Alias); + if (SPAllowed) { + if (FrameIndexSDNode *FIN = + dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) { + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy); + Offset = CurDAG->getTargetConstant(CN->getZExtValue(), DL, ValTy); + return true; + } } - else - Base = Addr.getOperand(0); + Base = Addr.getOperand(0); Offset = CurDAG->getTargetConstant(CN->getZExtValue(), DL, ValTy); return true; } @@ -224,25 +158,25 @@ bool Mips16DAGToDAGISel::selectAddr16( return true; } } - - // If an indexed floating point load/store can be emitted, return false. - const LSBaseSDNode *LS = dyn_cast<LSBaseSDNode>(Parent); - - if (LS) { - if (LS->getMemoryVT() == MVT::f32 && Subtarget->hasMips4_32r2()) - return false; - if (LS->getMemoryVT() == MVT::f64 && Subtarget->hasMips4_32r2()) - return false; - } } - Base = Addr; + Base = Addr; Offset = CurDAG->getTargetConstant(0, DL, ValTy); return true; } +bool Mips16DAGToDAGISel::selectAddr16(SDValue Addr, SDValue &Base, + SDValue &Offset) { + return selectAddr(false, Addr, Base, Offset); +} + +bool Mips16DAGToDAGISel::selectAddr16SP(SDValue Addr, SDValue &Base, + SDValue &Offset) { + return selectAddr(true, Addr, Base, Offset); +} + /// Select instructions not customized! Used for /// expanded, promoted and normal instructions -std::pair<bool, SDNode*> Mips16DAGToDAGISel::selectNode(SDNode *Node) { +bool Mips16DAGToDAGISel::trySelect(SDNode *Node) { unsigned Opcode = Node->getOpcode(); SDLoc DL(Node); @@ -253,13 +187,15 @@ std::pair<bool, SDNode*> Mips16DAGToDAGISel::selectNode(SDNode *Node) { EVT NodeTy = Node->getValueType(0); unsigned MultOpc; - switch(Opcode) { - default: break; + switch (Opcode) { + default: + break; case ISD::SUBE: case ISD::ADDE: { SDValue InFlag = Node->getOperand(2), CmpLHS; - unsigned Opc = InFlag.getOpcode(); (void)Opc; + unsigned Opc = InFlag.getOpcode(); + (void)Opc; assert(((Opc == ISD::ADDC || Opc == ISD::ADDE) || (Opc == ISD::SUBC || Opc == ISD::SUBE)) && "(ADD|SUB)E flag operand must come from (ADD|SUB)C/E insn"); @@ -273,7 +209,7 @@ std::pair<bool, SDNode*> Mips16DAGToDAGISel::selectNode(SDNode *Node) { MOp = Mips::SubuRxRyRz16; } - SDValue Ops[] = { CmpLHS, InFlag.getOperand(1) }; + SDValue Ops[] = {CmpLHS, InFlag.getOperand(1)}; SDValue LHS = Node->getOperand(0); SDValue RHS = Node->getOperand(1); @@ -283,40 +219,42 @@ std::pair<bool, SDNode*> Mips16DAGToDAGISel::selectNode(SDNode *Node) { unsigned Sltu_op = Mips::SltuRxRyRz16; SDNode *Carry = CurDAG->getMachineNode(Sltu_op, DL, VT, Ops); unsigned Addu_op = Mips::AdduRxRyRz16; - SDNode *AddCarry = CurDAG->getMachineNode(Addu_op, DL, VT, - SDValue(Carry,0), RHS); + SDNode *AddCarry = + CurDAG->getMachineNode(Addu_op, DL, VT, SDValue(Carry, 0), RHS); - SDNode *Result = CurDAG->SelectNodeTo(Node, MOp, VT, MVT::Glue, LHS, - SDValue(AddCarry,0)); - return std::make_pair(true, Result); + CurDAG->SelectNodeTo(Node, MOp, VT, MVT::Glue, LHS, SDValue(AddCarry, 0)); + return true; } /// Mul with two results case ISD::SMUL_LOHI: case ISD::UMUL_LOHI: { MultOpc = (Opcode == ISD::UMUL_LOHI ? Mips::MultuRxRy16 : Mips::MultRxRy16); - std::pair<SDNode*, SDNode*> LoHi = selectMULT(Node, MultOpc, DL, NodeTy, - true, true); + std::pair<SDNode *, SDNode *> LoHi = + selectMULT(Node, MultOpc, DL, NodeTy, true, true); if (!SDValue(Node, 0).use_empty()) ReplaceUses(SDValue(Node, 0), SDValue(LoHi.first, 0)); if (!SDValue(Node, 1).use_empty()) ReplaceUses(SDValue(Node, 1), SDValue(LoHi.second, 0)); - return std::make_pair(true, nullptr); + CurDAG->RemoveDeadNode(Node); + return true; } case ISD::MULHS: case ISD::MULHU: { MultOpc = (Opcode == ISD::MULHU ? Mips::MultuRxRy16 : Mips::MultRxRy16); - SDNode *Result = selectMULT(Node, MultOpc, DL, NodeTy, false, true).second; - return std::make_pair(true, Result); + auto LoHi = selectMULT(Node, MultOpc, DL, NodeTy, false, true); + ReplaceNode(Node, LoHi.second); + return true; } } - return std::make_pair(false, nullptr); + return false; } -FunctionPass *llvm::createMips16ISelDag(MipsTargetMachine &TM) { - return new Mips16DAGToDAGISel(TM); +FunctionPass *llvm::createMips16ISelDag(MipsTargetMachine &TM, + CodeGenOpt::Level OptLevel) { + return new Mips16DAGToDAGISel(TM, OptLevel); } diff --git a/lib/Target/Mips/Mips16ISelDAGToDAG.h b/lib/Target/Mips/Mips16ISelDAGToDAG.h index ae0e61e19d9d6..bbf8cc36f241a 100644 --- a/lib/Target/Mips/Mips16ISelDAGToDAG.h +++ b/lib/Target/Mips/Mips16ISelDAGToDAG.h @@ -20,22 +20,24 @@ namespace llvm { class Mips16DAGToDAGISel : public MipsDAGToDAGISel { public: - explicit Mips16DAGToDAGISel(MipsTargetMachine &TM) : MipsDAGToDAGISel(TM) {} + explicit Mips16DAGToDAGISel(MipsTargetMachine &TM, CodeGenOpt::Level OL) + : MipsDAGToDAGISel(TM, OL) {} private: - std::pair<SDNode*, SDNode*> selectMULT(SDNode *N, unsigned Opc, SDLoc DL, - EVT Ty, bool HasLo, bool HasHi); - - SDValue getMips16SPAliasReg(); + std::pair<SDNode *, SDNode *> selectMULT(SDNode *N, unsigned Opc, + const SDLoc &DL, EVT Ty, bool HasLo, + bool HasHi); bool runOnMachineFunction(MachineFunction &MF) override; - void getMips16SPRefReg(SDNode *Parent, SDValue &AliasReg); - - bool selectAddr16(SDNode *Parent, SDValue N, SDValue &Base, - SDValue &Offset, SDValue &Alias) override; + bool selectAddr(bool SPAllowed, SDValue Addr, SDValue &Base, + SDValue &Offset); + bool selectAddr16(SDValue Addr, SDValue &Base, + SDValue &Offset) override; + bool selectAddr16SP(SDValue Addr, SDValue &Base, + SDValue &Offset) override; - std::pair<bool, SDNode*> selectNode(SDNode *Node) override; + bool trySelect(SDNode *Node) override; void processFunctionAfterISel(MachineFunction &MF) override; @@ -46,8 +48,8 @@ private: void initMips16SPAliasReg(MachineFunction &MF); }; -FunctionPass *createMips16ISelDag(MipsTargetMachine &TM); - +FunctionPass *createMips16ISelDag(MipsTargetMachine &TM, + CodeGenOpt::Level OptLevel); } #endif diff --git a/lib/Target/Mips/Mips16ISelLowering.cpp b/lib/Target/Mips/Mips16ISelLowering.cpp index e7483253e61d8..bdb9eec4cc5ae 100644 --- a/lib/Target/Mips/Mips16ISelLowering.cpp +++ b/lib/Target/Mips/Mips16ISelLowering.cpp @@ -16,11 +16,9 @@ #include "MipsMachineFunction.h" #include "MipsRegisterInfo.h" #include "MipsTargetMachine.h" -#include "llvm/ADT/StringRef.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/Support/CommandLine.h" #include "llvm/Target/TargetInstrInfo.h" -#include <string> using namespace llvm; @@ -167,9 +165,9 @@ Mips16TargetLowering::allowsMisalignedMemoryAccesses(EVT VT, } MachineBasicBlock * -Mips16TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, +Mips16TargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *BB) const { - switch (MI->getOpcode()) { + switch (MI.getOpcode()) { default: return MipsTargetLowering::EmitInstrWithCustomInserter(MI, BB); case Mips::SelBeqZ: @@ -519,12 +517,13 @@ getOpndList(SmallVectorImpl<SDValue> &Ops, Chain); } -MachineBasicBlock *Mips16TargetLowering:: -emitSel16(unsigned Opc, MachineInstr *MI, MachineBasicBlock *BB) const { +MachineBasicBlock * +Mips16TargetLowering::emitSel16(unsigned Opc, MachineInstr &MI, + MachineBasicBlock *BB) const { if (DontExpandCondPseudos16) return BB; const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - DebugLoc DL = MI->getDebugLoc(); + 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 // destination vreg to set, the condition code register to branch on, the @@ -554,8 +553,9 @@ emitSel16(unsigned Opc, MachineInstr *MI, MachineBasicBlock *BB) const { BB->addSuccessor(copy0MBB); BB->addSuccessor(sinkMBB); - BuildMI(BB, DL, TII->get(Opc)).addReg(MI->getOperand(3).getReg()) - .addMBB(sinkMBB); + BuildMI(BB, DL, TII->get(Opc)) + .addReg(MI.getOperand(3).getReg()) + .addMBB(sinkMBB); // copy0MBB: // %FalseValue = ... @@ -570,22 +570,23 @@ emitSel16(unsigned Opc, MachineInstr *MI, MachineBasicBlock *BB) const { // ... BB = sinkMBB; - BuildMI(*BB, BB->begin(), DL, - TII->get(Mips::PHI), MI->getOperand(0).getReg()) - .addReg(MI->getOperand(1).getReg()).addMBB(thisMBB) - .addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB); + BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(0).getReg()) + .addReg(MI.getOperand(1).getReg()) + .addMBB(thisMBB) + .addReg(MI.getOperand(2).getReg()) + .addMBB(copy0MBB); - MI->eraseFromParent(); // The pseudo instruction is gone now. + MI.eraseFromParent(); // The pseudo instruction is gone now. return BB; } MachineBasicBlock * -Mips16TargetLowering::emitSelT16(unsigned Opc1, unsigned Opc2, MachineInstr *MI, +Mips16TargetLowering::emitSelT16(unsigned Opc1, unsigned Opc2, MachineInstr &MI, MachineBasicBlock *BB) const { if (DontExpandCondPseudos16) return BB; const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - DebugLoc DL = MI->getDebugLoc(); + 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 // destination vreg to set, the condition code register to branch on, the @@ -615,8 +616,9 @@ Mips16TargetLowering::emitSelT16(unsigned Opc1, unsigned Opc2, MachineInstr *MI, BB->addSuccessor(copy0MBB); BB->addSuccessor(sinkMBB); - BuildMI(BB, DL, TII->get(Opc2)).addReg(MI->getOperand(3).getReg()) - .addReg(MI->getOperand(4).getReg()); + BuildMI(BB, DL, TII->get(Opc2)) + .addReg(MI.getOperand(3).getReg()) + .addReg(MI.getOperand(4).getReg()); BuildMI(BB, DL, TII->get(Opc1)).addMBB(sinkMBB); // copy0MBB: @@ -632,24 +634,25 @@ Mips16TargetLowering::emitSelT16(unsigned Opc1, unsigned Opc2, MachineInstr *MI, // ... BB = sinkMBB; - BuildMI(*BB, BB->begin(), DL, - TII->get(Mips::PHI), MI->getOperand(0).getReg()) - .addReg(MI->getOperand(1).getReg()).addMBB(thisMBB) - .addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB); + BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(0).getReg()) + .addReg(MI.getOperand(1).getReg()) + .addMBB(thisMBB) + .addReg(MI.getOperand(2).getReg()) + .addMBB(copy0MBB); - MI->eraseFromParent(); // The pseudo instruction is gone now. + MI.eraseFromParent(); // The pseudo instruction is gone now. return BB; } MachineBasicBlock * Mips16TargetLowering::emitSeliT16(unsigned Opc1, unsigned Opc2, - MachineInstr *MI, + MachineInstr &MI, MachineBasicBlock *BB) const { if (DontExpandCondPseudos16) return BB; const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - DebugLoc DL = MI->getDebugLoc(); + 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 // destination vreg to set, the condition code register to branch on, the @@ -679,8 +682,9 @@ Mips16TargetLowering::emitSeliT16(unsigned Opc1, unsigned Opc2, BB->addSuccessor(copy0MBB); BB->addSuccessor(sinkMBB); - BuildMI(BB, DL, TII->get(Opc2)).addReg(MI->getOperand(3).getReg()) - .addImm(MI->getOperand(4).getImm()); + BuildMI(BB, DL, TII->get(Opc2)) + .addReg(MI.getOperand(3).getReg()) + .addImm(MI.getOperand(4).getImm()); BuildMI(BB, DL, TII->get(Opc1)).addMBB(sinkMBB); // copy0MBB: @@ -696,42 +700,44 @@ Mips16TargetLowering::emitSeliT16(unsigned Opc1, unsigned Opc2, // ... BB = sinkMBB; - BuildMI(*BB, BB->begin(), DL, - TII->get(Mips::PHI), MI->getOperand(0).getReg()) - .addReg(MI->getOperand(1).getReg()).addMBB(thisMBB) - .addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB); + BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(0).getReg()) + .addReg(MI.getOperand(1).getReg()) + .addMBB(thisMBB) + .addReg(MI.getOperand(2).getReg()) + .addMBB(copy0MBB); - MI->eraseFromParent(); // The pseudo instruction is gone now. + MI.eraseFromParent(); // The pseudo instruction is gone now. return BB; } MachineBasicBlock * Mips16TargetLowering::emitFEXT_T8I816_ins(unsigned BtOpc, unsigned CmpOpc, - MachineInstr *MI, + MachineInstr &MI, MachineBasicBlock *BB) const { if (DontExpandCondPseudos16) return BB; const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - unsigned regX = MI->getOperand(0).getReg(); - unsigned regY = MI->getOperand(1).getReg(); - MachineBasicBlock *target = MI->getOperand(2).getMBB(); - BuildMI(*BB, MI, MI->getDebugLoc(), TII->get(CmpOpc)).addReg(regX) - .addReg(regY); - BuildMI(*BB, MI, MI->getDebugLoc(), TII->get(BtOpc)).addMBB(target); - MI->eraseFromParent(); // The pseudo instruction is gone now. + unsigned regX = MI.getOperand(0).getReg(); + unsigned regY = MI.getOperand(1).getReg(); + MachineBasicBlock *target = MI.getOperand(2).getMBB(); + BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(CmpOpc)) + .addReg(regX) + .addReg(regY); + BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(BtOpc)).addMBB(target); + MI.eraseFromParent(); // The pseudo instruction is gone now. return BB; } MachineBasicBlock *Mips16TargetLowering::emitFEXT_T8I8I16_ins( unsigned BtOpc, unsigned CmpiOpc, unsigned CmpiXOpc, bool ImmSigned, - MachineInstr *MI, MachineBasicBlock *BB) const { + MachineInstr &MI, MachineBasicBlock *BB) const { if (DontExpandCondPseudos16) return BB; const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - unsigned regX = MI->getOperand(0).getReg(); - int64_t imm = MI->getOperand(1).getImm(); - MachineBasicBlock *target = MI->getOperand(2).getMBB(); + unsigned regX = MI.getOperand(0).getReg(); + int64_t imm = MI.getOperand(1).getImm(); + MachineBasicBlock *target = MI.getOperand(2).getMBB(); unsigned CmpOpc; if (isUInt<8>(imm)) CmpOpc = CmpiOpc; @@ -740,10 +746,9 @@ MachineBasicBlock *Mips16TargetLowering::emitFEXT_T8I8I16_ins( CmpOpc = CmpiXOpc; else llvm_unreachable("immediate field not usable"); - BuildMI(*BB, MI, MI->getDebugLoc(), TII->get(CmpOpc)).addReg(regX) - .addImm(imm); - BuildMI(*BB, MI, MI->getDebugLoc(), TII->get(BtOpc)).addMBB(target); - MI->eraseFromParent(); // The pseudo instruction is gone now. + BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(CmpOpc)).addReg(regX).addImm(imm); + BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(BtOpc)).addMBB(target); + MI.eraseFromParent(); // The pseudo instruction is gone now. return BB; } @@ -758,38 +763,38 @@ static unsigned Mips16WhichOp8uOr16simm } MachineBasicBlock * -Mips16TargetLowering::emitFEXT_CCRX16_ins(unsigned SltOpc, MachineInstr *MI, +Mips16TargetLowering::emitFEXT_CCRX16_ins(unsigned SltOpc, MachineInstr &MI, MachineBasicBlock *BB) const { if (DontExpandCondPseudos16) return BB; const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - unsigned CC = MI->getOperand(0).getReg(); - unsigned regX = MI->getOperand(1).getReg(); - unsigned regY = MI->getOperand(2).getReg(); - BuildMI(*BB, MI, MI->getDebugLoc(), TII->get(SltOpc)).addReg(regX).addReg( - regY); - BuildMI(*BB, MI, MI->getDebugLoc(), - TII->get(Mips::MoveR3216), CC).addReg(Mips::T8); - MI->eraseFromParent(); // The pseudo instruction is gone now. + unsigned CC = MI.getOperand(0).getReg(); + unsigned regX = MI.getOperand(1).getReg(); + unsigned regY = MI.getOperand(2).getReg(); + BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(SltOpc)) + .addReg(regX) + .addReg(regY); + BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(Mips::MoveR3216), CC) + .addReg(Mips::T8); + MI.eraseFromParent(); // The pseudo instruction is gone now. return BB; } MachineBasicBlock * Mips16TargetLowering::emitFEXT_CCRXI16_ins(unsigned SltiOpc, unsigned SltiXOpc, - MachineInstr *MI, + MachineInstr &MI, MachineBasicBlock *BB) const { if (DontExpandCondPseudos16) return BB; const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - unsigned CC = MI->getOperand(0).getReg(); - unsigned regX = MI->getOperand(1).getReg(); - int64_t Imm = MI->getOperand(2).getImm(); + unsigned CC = MI.getOperand(0).getReg(); + unsigned regX = MI.getOperand(1).getReg(); + int64_t Imm = MI.getOperand(2).getImm(); unsigned SltOpc = Mips16WhichOp8uOr16simm(SltiOpc, SltiXOpc, Imm); - BuildMI(*BB, MI, MI->getDebugLoc(), - TII->get(SltOpc)).addReg(regX).addImm(Imm); - BuildMI(*BB, MI, MI->getDebugLoc(), - TII->get(Mips::MoveR3216), CC).addReg(Mips::T8); - MI->eraseFromParent(); // The pseudo instruction is gone now. + BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(SltOpc)).addReg(regX).addImm(Imm); + BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(Mips::MoveR3216), CC) + .addReg(Mips::T8); + MI.eraseFromParent(); // The pseudo instruction is gone now. return BB; } diff --git a/lib/Target/Mips/Mips16ISelLowering.h b/lib/Target/Mips/Mips16ISelLowering.h index d3b9f750f3471..0ee0b816ef70f 100644 --- a/lib/Target/Mips/Mips16ISelLowering.h +++ b/lib/Target/Mips/Mips16ISelLowering.h @@ -27,7 +27,7 @@ namespace llvm { bool *Fast) const override; MachineBasicBlock * - EmitInstrWithCustomInserter(MachineInstr *MI, + EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const override; private: @@ -50,32 +50,32 @@ namespace llvm { bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee, SDValue Chain) const override; - MachineBasicBlock *emitSel16(unsigned Opc, MachineInstr *MI, + MachineBasicBlock *emitSel16(unsigned Opc, MachineInstr &MI, MachineBasicBlock *BB) const; MachineBasicBlock *emitSeliT16(unsigned Opc1, unsigned Opc2, - MachineInstr *MI, + MachineInstr &MI, MachineBasicBlock *BB) const; MachineBasicBlock *emitSelT16(unsigned Opc1, unsigned Opc2, - MachineInstr *MI, + MachineInstr &MI, MachineBasicBlock *BB) const; MachineBasicBlock *emitFEXT_T8I816_ins(unsigned BtOpc, unsigned CmpOpc, - MachineInstr *MI, + MachineInstr &MI, MachineBasicBlock *BB) const; - MachineBasicBlock *emitFEXT_T8I8I16_ins( - unsigned BtOpc, unsigned CmpiOpc, unsigned CmpiXOpc, bool ImmSigned, - MachineInstr *MI, MachineBasicBlock *BB) const; + MachineBasicBlock *emitFEXT_T8I8I16_ins(unsigned BtOpc, unsigned CmpiOpc, + unsigned CmpiXOpc, bool ImmSigned, + MachineInstr &MI, + MachineBasicBlock *BB) const; - MachineBasicBlock *emitFEXT_CCRX16_ins( - unsigned SltOpc, - MachineInstr *MI, MachineBasicBlock *BB) const; + MachineBasicBlock *emitFEXT_CCRX16_ins(unsigned SltOpc, MachineInstr &MI, + MachineBasicBlock *BB) const; - MachineBasicBlock *emitFEXT_CCRXI16_ins( - unsigned SltiOpc, unsigned SltiXOpc, - MachineInstr *MI, MachineBasicBlock *BB )const; + MachineBasicBlock *emitFEXT_CCRXI16_ins(unsigned SltiOpc, unsigned SltiXOpc, + MachineInstr &MI, + MachineBasicBlock *BB) const; }; } diff --git a/lib/Target/Mips/Mips16InstrInfo.cpp b/lib/Target/Mips/Mips16InstrInfo.cpp index da8ada4e53917..daa1355ffefd0 100644 --- a/lib/Target/Mips/Mips16InstrInfo.cpp +++ b/lib/Target/Mips/Mips16InstrInfo.cpp @@ -15,12 +15,10 @@ #include "MipsMachineFunction.h" #include "MipsTargetMachine.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/ADT/StringRef.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/RegisterScavenging.h" #include "llvm/MC/MCAsmInfo.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/TargetRegistry.h" @@ -43,7 +41,7 @@ const MipsRegisterInfo &Mips16InstrInfo::getRegisterInfo() const { /// the destination along with the FrameIndex of the loaded stack slot. If /// not, return 0. This predicate must return 0 if the instruction has /// any side effects other than loading from the stack slot. -unsigned Mips16InstrInfo::isLoadFromStackSlot(const MachineInstr *MI, +unsigned Mips16InstrInfo::isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const { return 0; } @@ -53,15 +51,15 @@ unsigned Mips16InstrInfo::isLoadFromStackSlot(const MachineInstr *MI, /// the source reg along with the FrameIndex of the loaded stack slot. If /// not, return 0. This predicate must return 0 if the instruction has /// any side effects other than storing to the stack slot. -unsigned Mips16InstrInfo::isStoreToStackSlot(const MachineInstr *MI, +unsigned Mips16InstrInfo::isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const { return 0; } void Mips16InstrInfo::copyPhysReg(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, DebugLoc DL, - unsigned DestReg, unsigned SrcReg, - bool KillSrc) const { + MachineBasicBlock::iterator I, + const DebugLoc &DL, unsigned DestReg, + unsigned SrcReg, bool KillSrc) const { unsigned Opc = 0; if (Mips::CPU16RegsRegClass.contains(DestReg) && @@ -126,9 +124,9 @@ void Mips16InstrInfo::loadRegFromStack(MachineBasicBlock &MBB, .addMemOperand(MMO); } -bool Mips16InstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const { - MachineBasicBlock &MBB = *MI->getParent(); - switch(MI->getDesc().getOpcode()) { +bool Mips16InstrInfo::expandPostRAPseudo(MachineInstr &MI) const { + MachineBasicBlock &MBB = *MI.getParent(); + switch (MI.getDesc().getOpcode()) { default: return false; case Mips::RetRA16: @@ -136,7 +134,7 @@ bool Mips16InstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const { break; } - MBB.erase(MI); + MBB.erase(MI.getIterator()); return true; } @@ -307,7 +305,8 @@ void Mips16InstrInfo::adjustStackPtr(unsigned SP, int64_t Amount, unsigned Mips16InstrInfo::loadImmediate(unsigned FrameReg, int64_t Imm, MachineBasicBlock &MBB, MachineBasicBlock::iterator II, - DebugLoc DL, unsigned &NewImm) const { + const DebugLoc &DL, + unsigned &NewImm) const { // // given original instruction is: // Instr rx, T[offset] where offset is too big. @@ -326,7 +325,7 @@ unsigned Mips16InstrInfo::loadImmediate(unsigned FrameReg, int64_t Imm, int Reg =0; int SpReg = 0; - rs.enterBasicBlock(&MBB); + rs.enterBasicBlock(MBB); rs.forward(II); // // We need to know which registers can be used, in the case where there diff --git a/lib/Target/Mips/Mips16InstrInfo.h b/lib/Target/Mips/Mips16InstrInfo.h index 6540b40bc9abf..ab559799f00b0 100644 --- a/lib/Target/Mips/Mips16InstrInfo.h +++ b/lib/Target/Mips/Mips16InstrInfo.h @@ -32,7 +32,7 @@ public: /// the destination along with the FrameIndex of the loaded stack slot. If /// not, return 0. This predicate must return 0 if the instruction has /// any side effects other than loading from the stack slot. - unsigned isLoadFromStackSlot(const MachineInstr *MI, + unsigned isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override; /// isStoreToStackSlot - If the specified machine instruction is a direct @@ -40,12 +40,11 @@ public: /// the source reg along with the FrameIndex of the loaded stack slot. If /// not, return 0. This predicate must return 0 if the instruction has /// any side effects other than storing to the stack slot. - unsigned isStoreToStackSlot(const MachineInstr *MI, + unsigned isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override; - void copyPhysReg(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, DebugLoc DL, - unsigned DestReg, unsigned SrcReg, + void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, + const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, bool KillSrc) const override; void storeRegToStack(MachineBasicBlock &MBB, @@ -62,7 +61,7 @@ public: const TargetRegisterInfo *TRI, int64_t Offset) const override; - bool expandPostRAPseudo(MachineBasicBlock::iterator MI) const override; + bool expandPostRAPseudo(MachineInstr &MI) const override; unsigned getOppositeBranchOpc(unsigned Opc) const override; @@ -83,9 +82,8 @@ public: // This is to adjust some FrameReg. We return the new register to be used // in place of FrameReg and the adjusted immediate field (&NewImm) // - unsigned loadImmediate(unsigned FrameReg, - int64_t Imm, MachineBasicBlock &MBB, - MachineBasicBlock::iterator II, DebugLoc DL, + unsigned loadImmediate(unsigned FrameReg, int64_t Imm, MachineBasicBlock &MBB, + MachineBasicBlock::iterator II, const DebugLoc &DL, unsigned &NewImm) const; static bool validImmediate(unsigned Opcode, unsigned Reg, int64_t Amount); diff --git a/lib/Target/Mips/Mips16InstrInfo.td b/lib/Target/Mips/Mips16InstrInfo.td index dad6ea4c9e981..021fb86786869 100644 --- a/lib/Target/Mips/Mips16InstrInfo.td +++ b/lib/Target/Mips/Mips16InstrInfo.td @@ -14,14 +14,26 @@ // // Mips Address // -def addr16 : - ComplexPattern<iPTR, 3, "selectAddr16", [frameindex], [SDNPWantParent]>; +def addr16 : ComplexPattern<iPTR, 2, "selectAddr16", [frameindex]>; +def addr16sp : ComplexPattern<iPTR, 2, "selectAddr16SP", [frameindex]>; // // Address operand def mem16 : Operand<i32> { let PrintMethod = "printMemOperand"; - let MIOperandInfo = (ops CPU16Regs, simm16, CPU16RegsPlusSP); + let MIOperandInfo = (ops CPU16Regs, simm16); + let EncoderMethod = "getMemEncoding"; +} + +def mem16sp : Operand<i32> { + let PrintMethod = "printMemOperand"; + // This should be CPUSPReg but the MIPS16 subtarget isn't good enough at + // keeping the sp-relative load and the other varieties separate at the + // moment. This lie fixes the problem sufficiently well to fix the errors + // emitted by -verify-machineinstrs and the output ends up correct as long + // as we use an external assembler (which is already a requirement for MIPS16 + // for several other reasons). + let MIOperandInfo = (ops CPU16RegsPlusSP, simm16); let EncoderMethod = "getMemEncoding"; } @@ -31,6 +43,8 @@ def mem16_ea : Operand<i32> { let EncoderMethod = "getMemEncoding"; } +def pcrel16 : Operand<i32>; + // // I-type instruction format // @@ -115,7 +129,7 @@ class FEXT_CCRXI16_ins<string asmstr>: // class FJAL16_ins<bits<1> _X, string asmstr, InstrItinClass itin>: - FJAL16<_X, (outs), (ins simm20:$imm), + FJAL16<_X, (outs), (ins uimm26:$imm), !strconcat(asmstr, "\t$imm\n\tnop"),[], itin> { let isCodeGenOnly=1; @@ -124,7 +138,7 @@ class FJAL16_ins<bits<1> _X, string asmstr, class FJALB16_ins<bits<1> _X, string asmstr, InstrItinClass itin>: - FJAL16<_X, (outs), (ins simm20:$imm), + FJAL16<_X, (outs), (ins uimm26:$imm), !strconcat(asmstr, "\t$imm\t# branch\n\tnop"),[], itin> { let isCodeGenOnly=1; @@ -213,19 +227,6 @@ class FEXT_2RI16_ins<bits<5> _op, string asmstr, let Constraints = "$rx_ = $rx"; } - -// this has an explicit sp argument that we ignore to work around a problem -// in the compiler -class FEXT_RI16_SP_explicit_ins<bits<5> _op, string asmstr, - InstrItinClass itin>: - FEXT_RI16<_op, (outs CPU16Regs:$rx), (ins CPUSPReg:$ry, simm16:$imm), - !strconcat(asmstr, "\t$rx, $imm ( $ry ); "), [], itin>; - -class FEXT_RI16_SP_Store_explicit_ins<bits<5> _op, string asmstr, - InstrItinClass itin>: - FEXT_RI16<_op, (outs), (ins CPU16Regs:$rx, CPUSPReg:$ry, simm16:$imm), - !strconcat(asmstr, "\t$rx, $imm ( $ry ); "), [], itin>; - // // EXT-RRI instruction format // @@ -483,13 +484,11 @@ class SelT<string op1, string op2>: // // 32 bit constant // -def imm32: Operand<i32>; - def Constant32: - MipsPseudo16<(outs), (ins imm32:$imm), "\t.word $imm", []>; + MipsPseudo16<(outs), (ins simm32:$imm), "\t.word $imm", []>; def LwConstant32: - MipsPseudo16<(outs CPU16Regs:$rx), (ins imm32:$imm, imm32:$constid), + MipsPseudo16<(outs CPU16Regs:$rx), (ins simm32:$imm, simm32:$constid), "lw\t$rx, 1f\n\tb\t2f\n\t.align\t2\n1: \t.word\t$imm\n2:", []>; @@ -635,7 +634,7 @@ def BnezRxImmX16: FEXT_RI16_B_ins<0b00101, "bnez", IIM16Alu>, cbranch16; // Purpose: Breakpoint // To cause a Breakpoint exception. -def Break16: FRRBreakNull16_ins<"break 0", NoItinerary>; +def Break16: FRRBreakNull16_ins<"break 0", IIM16Alu>; // // Format: BTEQZ offset MIPS16e // Purpose: Branch on T Equal to Zero (Extended) @@ -851,9 +850,7 @@ def LwRxRyOffMemX16: FEXT_RRI16_mem_ins<0b10011, "lw", mem16, II_LW>, MayLoad{ // Purpose: Load Word (SP-Relative, Extended) // To load an SP-relative word from memory as a signed value. // -def LwRxSpImmX16: FEXT_RI16_SP_explicit_ins<0b10010, "lw", II_LW>, MayLoad{ - let Uses = [SP]; -} +def LwRxSpImmX16: FEXT_RRI16_mem_ins<0b10010, "lw", mem16sp, II_LW>, MayLoad; def LwRxPcTcp16: FRI16_TCP_ins<0b10110, "lw", II_LW>, MayLoad; @@ -1277,16 +1274,14 @@ def SubuRxRyRz16: FRRR16_ins<0b11, "subu", IIM16Alu>, ArithLogic16Defs<0>; // Purpose: Store Word (Extended) // To store a word to memory. // -def SwRxRyOffMemX16: - FEXT_RRI16_mem2_ins<0b11011, "sw", mem16, II_SW>, MayStore; +def SwRxRyOffMemX16: FEXT_RRI16_mem2_ins<0b11011, "sw", mem16, II_SW>, MayStore; // // Format: SW rx, offset(sp) MIPS16e // Purpose: Store Word rx (SP-Relative) // To store an SP-relative word to memory. // -def SwRxSpImmX16: FEXT_RI16_SP_Store_explicit_ins - <0b11010, "sw", II_SW>, MayStore; +def SwRxSpImmX16: FEXT_RRI16_mem2_ins<0b11010, "sw", mem16sp, II_SW>, MayStore; // // @@ -1340,22 +1335,21 @@ def: shift_rotate_reg16_pat<shl, SllvRxRy16>; def: shift_rotate_reg16_pat<sra, SravRxRy16>; def: shift_rotate_reg16_pat<srl, SrlvRxRy16>; -class LoadM16_pat<PatFrag OpNode, Instruction I> : - Mips16Pat<(OpNode addr16:$addr), (I addr16:$addr)>; +class LoadM16_pat<PatFrag OpNode, Instruction I, ComplexPattern Addr> : + Mips16Pat<(OpNode Addr:$addr), (I Addr:$addr)>; -def: LoadM16_pat<sextloadi8, LbRxRyOffMemX16>; -def: LoadM16_pat<zextloadi8, LbuRxRyOffMemX16>; -def: LoadM16_pat<sextloadi16, LhRxRyOffMemX16>; -def: LoadM16_pat<zextloadi16, LhuRxRyOffMemX16>; -def: LoadM16_pat<load, LwRxRyOffMemX16>; +def: LoadM16_pat<sextloadi8, LbRxRyOffMemX16, addr16>; +def: LoadM16_pat<zextloadi8, LbuRxRyOffMemX16, addr16>; +def: LoadM16_pat<sextloadi16, LhRxRyOffMemX16, addr16>; +def: LoadM16_pat<zextloadi16, LhuRxRyOffMemX16, addr16>; +def: LoadM16_pat<load, LwRxSpImmX16, addr16sp>; -class StoreM16_pat<PatFrag OpNode, Instruction I> : - Mips16Pat<(OpNode CPU16Regs:$r, addr16:$addr), - (I CPU16Regs:$r, addr16:$addr)>; +class StoreM16_pat<PatFrag OpNode, Instruction I, ComplexPattern Addr> : + Mips16Pat<(OpNode CPU16Regs:$r, Addr:$addr), (I CPU16Regs:$r, Addr:$addr)>; -def: StoreM16_pat<truncstorei8, SbRxRyOffMemX16>; -def: StoreM16_pat<truncstorei16, ShRxRyOffMemX16>; -def: StoreM16_pat<store, SwRxRyOffMemX16>; +def: StoreM16_pat<truncstorei8, SbRxRyOffMemX16, addr16>; +def: StoreM16_pat<truncstorei16, ShRxRyOffMemX16, addr16>; +def: StoreM16_pat<store, SwRxSpImmX16, addr16sp>; // Unconditional branch class UncondBranch16_pat<SDNode OpNode, Instruction I>: @@ -1401,8 +1395,7 @@ class SetCC_I16<PatFrag cond_op, PatLeaf imm_type, Instruction I>: (I CPU16Regs:$rx, imm_type:$imm16)>; -def: Mips16Pat<(i32 addr16:$addr), - (AddiuRxRyOffMemX16 addr16:$addr)>; +def: Mips16Pat<(i32 addr16sp:$addr), (AddiuRxRyOffMemX16 addr16sp:$addr)>; // Large (>16 bit) immediate loads @@ -1551,7 +1544,7 @@ def: UncondBranch16_pat<br, Bimm16>; // Small immediates def: Mips16Pat<(i32 immSExt16:$in), - (AddiuRxRxImmX16 (Move32R16 ZERO), immSExt16:$in)>; + (AddiuRxRxImmX16 (MoveR3216 ZERO), immSExt16:$in)>; def: Mips16Pat<(i32 immZExt16:$in), (LiRxImmX16 immZExt16:$in)>; diff --git a/lib/Target/Mips/Mips16RegisterInfo.cpp b/lib/Target/Mips/Mips16RegisterInfo.cpp index ebd51d7b50728..b034c26640e37 100644 --- a/lib/Target/Mips/Mips16RegisterInfo.cpp +++ b/lib/Target/Mips/Mips16RegisterInfo.cpp @@ -14,11 +14,9 @@ #include "Mips16RegisterInfo.h" #include "Mips.h" #include "Mips16InstrInfo.h" -#include "MipsAnalyzeImmediate.h" #include "MipsInstrInfo.h" #include "MipsMachineFunction.h" #include "MipsSubtarget.h" -#include "llvm/ADT/BitVector.h" #include "llvm/ADT/STLExtras.h" #include "llvm/CodeGen/MachineFrameInfo.h" #include "llvm/CodeGen/MachineFunction.h" @@ -28,7 +26,6 @@ #include "llvm/IR/DebugInfo.h" #include "llvm/IR/Function.h" #include "llvm/IR/Type.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" diff --git a/lib/Target/Mips/Mips32r6InstrFormats.td b/lib/Target/Mips/Mips32r6InstrFormats.td index 13216bebe5b66..a20c683c1e5ec 100644 --- a/lib/Target/Mips/Mips32r6InstrFormats.td +++ b/lib/Target/Mips/Mips32r6InstrFormats.td @@ -360,7 +360,7 @@ class SPECIAL_SDBBP_FM : MipsR6Inst { } // This class is ambiguous with other branches: -// BEQC/BNEC require that rs > rt +// BEQC/BNEC require that rs < rt && rs != 0 class CMP_BRANCH_2R_OFF16_FM<OPGROUP funct> : MipsR6Inst { bits<5> rs; bits<5> rt; diff --git a/lib/Target/Mips/Mips32r6InstrInfo.td b/lib/Target/Mips/Mips32r6InstrInfo.td index 82d2c8ee99053..f552f8d37afbb 100644 --- a/lib/Target/Mips/Mips32r6InstrInfo.td +++ b/lib/Target/Mips/Mips32r6InstrInfo.td @@ -182,58 +182,86 @@ class CMP_CONDN_DESC_BASE<string CondStr, string Typestr, dag InOperandList = (ins FGROpnd:$fs, FGROpnd:$ft); string AsmString = !strconcat("cmp.", CondStr, ".", Typestr, "\t$fd, $fs, $ft"); list<dag> Pattern = [(set FGRCCOpnd:$fd, (Op FGROpnd:$fs, FGROpnd:$ft))]; + bit isCTI = 1; } multiclass CMP_CC_M <FIELD_CMP_FORMAT Format, string Typestr, RegisterOperand FGROpnd>{ let AdditionalPredicates = [NotInMicroMips] in { - def CMP_F_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_AF>, + def CMP_F_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_AF>, CMP_CONDN_DESC_BASE<"af", Typestr, FGROpnd>, + MipsR6Arch<!strconcat("cmp.af.", Typestr)>, ISA_MIPS32R6, HARDFLOAT; - def CMP_UN_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_UN>, + def CMP_UN_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_UN>, CMP_CONDN_DESC_BASE<"un", Typestr, FGROpnd, setuo>, + MipsR6Arch<!strconcat("cmp.un.", Typestr)>, ISA_MIPS32R6, HARDFLOAT; - def CMP_EQ_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_EQ>, + def CMP_EQ_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_EQ>, CMP_CONDN_DESC_BASE<"eq", Typestr, FGROpnd, setoeq>, + MipsR6Arch<!strconcat("cmp.eq.", Typestr)>, ISA_MIPS32R6, HARDFLOAT; - def CMP_UEQ_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_UEQ>, + def CMP_UEQ_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, + FIELD_CMP_COND_UEQ>, CMP_CONDN_DESC_BASE<"ueq", Typestr, FGROpnd, setueq>, + MipsR6Arch<!strconcat("cmp.ueq.", Typestr)>, ISA_MIPS32R6, HARDFLOAT; - def CMP_LT_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_LT>, + def CMP_LT_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_LT>, CMP_CONDN_DESC_BASE<"lt", Typestr, FGROpnd, setolt>, + MipsR6Arch<!strconcat("cmp.lt.", Typestr)>, ISA_MIPS32R6, HARDFLOAT; - def CMP_ULT_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_ULT>, + def CMP_ULT_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, + FIELD_CMP_COND_ULT>, CMP_CONDN_DESC_BASE<"ult", Typestr, FGROpnd, setult>, + MipsR6Arch<!strconcat("cmp.ult.", Typestr)>, ISA_MIPS32R6, HARDFLOAT; - def CMP_LE_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_LE>, + def CMP_LE_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_LE>, CMP_CONDN_DESC_BASE<"le", Typestr, FGROpnd, setole>, + MipsR6Arch<!strconcat("cmp.le.", Typestr)>, ISA_MIPS32R6, HARDFLOAT; - def CMP_ULE_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_ULE>, + def CMP_ULE_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, + FIELD_CMP_COND_ULE>, CMP_CONDN_DESC_BASE<"ule", Typestr, FGROpnd, setule>, + MipsR6Arch<!strconcat("cmp.ule.", Typestr)>, ISA_MIPS32R6, HARDFLOAT; - def CMP_SAF_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_SAF>, + def CMP_SAF_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, + FIELD_CMP_COND_SAF>, CMP_CONDN_DESC_BASE<"saf", Typestr, FGROpnd>, + MipsR6Arch<!strconcat("cmp.saf.", Typestr)>, ISA_MIPS32R6, HARDFLOAT; - def CMP_SUN_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_SUN>, + def CMP_SUN_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, + FIELD_CMP_COND_SUN>, CMP_CONDN_DESC_BASE<"sun", Typestr, FGROpnd>, + MipsR6Arch<!strconcat("cmp.sun.", Typestr)>, ISA_MIPS32R6, HARDFLOAT; - def CMP_SEQ_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_SEQ>, + def CMP_SEQ_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, + FIELD_CMP_COND_SEQ>, CMP_CONDN_DESC_BASE<"seq", Typestr, FGROpnd>, + MipsR6Arch<!strconcat("cmp.seq.", Typestr)>, ISA_MIPS32R6, HARDFLOAT; - def CMP_SUEQ_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_SUEQ>, + def CMP_SUEQ_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, + FIELD_CMP_COND_SUEQ>, CMP_CONDN_DESC_BASE<"sueq", Typestr, FGROpnd>, + MipsR6Arch<!strconcat("cmp.sueq.", Typestr)>, ISA_MIPS32R6, HARDFLOAT; - def CMP_SLT_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_SLT>, + def CMP_SLT_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, + FIELD_CMP_COND_SLT>, CMP_CONDN_DESC_BASE<"slt", Typestr, FGROpnd>, + MipsR6Arch<!strconcat("cmp.slt.", Typestr)>, ISA_MIPS32R6, HARDFLOAT; - def CMP_SULT_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_SULT>, + def CMP_SULT_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, + FIELD_CMP_COND_SULT>, CMP_CONDN_DESC_BASE<"sult", Typestr, FGROpnd>, + MipsR6Arch<!strconcat("cmp.sult.", Typestr)>, ISA_MIPS32R6, HARDFLOAT; - def CMP_SLE_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_SLE>, + def CMP_SLE_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, + FIELD_CMP_COND_SLE>, CMP_CONDN_DESC_BASE<"sle", Typestr, FGROpnd>, + MipsR6Arch<!strconcat("cmp.sle.", Typestr)>, ISA_MIPS32R6, HARDFLOAT; - def CMP_SULE_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_SULE>, + def CMP_SULE_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, + FIELD_CMP_COND_SULE>, CMP_CONDN_DESC_BASE<"sule", Typestr, FGROpnd>, + MipsR6Arch<!strconcat("cmp.sule.", Typestr)>, ISA_MIPS32R6, HARDFLOAT; } } @@ -245,52 +273,62 @@ multiclass CMP_CC_M <FIELD_CMP_FORMAT Format, string Typestr, //===----------------------------------------------------------------------===// class PCREL_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - Operand ImmOpnd> : MipsR6Arch<instr_asm> { + Operand ImmOpnd, InstrItinClass itin> + : MipsR6Arch<instr_asm> { dag OutOperandList = (outs GPROpnd:$rs); dag InOperandList = (ins ImmOpnd:$imm); string AsmString = !strconcat(instr_asm, "\t$rs, $imm"); list<dag> Pattern = []; + InstrItinClass Itinerary = itin; } -class ADDIUPC_DESC : PCREL_DESC_BASE<"addiupc", GPR32Opnd, simm19_lsl2>; -class LWPC_DESC: PCREL_DESC_BASE<"lwpc", GPR32Opnd, simm19_lsl2>; -class LWUPC_DESC: PCREL_DESC_BASE<"lwupc", GPR32Opnd, simm19_lsl2>; +class ADDIUPC_DESC : PCREL_DESC_BASE<"addiupc", GPR32Opnd, simm19_lsl2, + II_ADDIUPC>; +class LWPC_DESC: PCREL_DESC_BASE<"lwpc", GPR32Opnd, simm19_lsl2, II_LWPC>; +class LWUPC_DESC: PCREL_DESC_BASE<"lwupc", GPR32Opnd, simm19_lsl2, II_LWUPC>; class ALIGN_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - Operand ImmOpnd> : MipsR6Arch<instr_asm> { + Operand ImmOpnd, InstrItinClass itin> + : 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"); list<dag> Pattern = []; + InstrItinClass Itinerary = itin; } -class ALIGN_DESC : ALIGN_DESC_BASE<"align", GPR32Opnd, uimm2>; +class ALIGN_DESC : ALIGN_DESC_BASE<"align", GPR32Opnd, uimm2, II_ALIGN>; -class ALUIPC_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> - : MipsR6Arch<instr_asm> { +class ALUIPC_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, + InstrItinClass itin = NoItinerary> + : MipsR6Arch<instr_asm> { dag OutOperandList = (outs GPROpnd:$rs); dag InOperandList = (ins simm16:$imm); string AsmString = !strconcat(instr_asm, "\t$rs, $imm"); list<dag> Pattern = []; + InstrItinClass Itinerary = itin; } -class ALUIPC_DESC : ALUIPC_DESC_BASE<"aluipc", GPR32Opnd>; -class AUIPC_DESC : ALUIPC_DESC_BASE<"auipc", GPR32Opnd>; +class ALUIPC_DESC : ALUIPC_DESC_BASE<"aluipc", GPR32Opnd, II_ALUIPC>; +class AUIPC_DESC : ALUIPC_DESC_BASE<"auipc", GPR32Opnd, II_AUIPC>; -class AUI_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> - : MipsR6Arch<instr_asm> { +class AUI_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, + InstrItinClass itin = NoItinerary> + : MipsR6Arch<instr_asm> { dag OutOperandList = (outs GPROpnd:$rs); dag InOperandList = (ins GPROpnd:$rt, simm16:$imm); string AsmString = !strconcat(instr_asm, "\t$rs, $rt, $imm"); list<dag> Pattern = []; + InstrItinClass Itinerary = itin; } -class AUI_DESC : AUI_DESC_BASE<"aui", GPR32Opnd>; +class AUI_DESC : AUI_DESC_BASE<"aui", GPR32Opnd, II_AUI>; class BRANCH_DESC_BASE { bit isBranch = 1; bit isTerminator = 1; bit hasDelaySlot = 0; + bit isCTI = 1; } class BC_DESC_BASE<string instr_asm, DAGOperand opnd> : BRANCH_DESC_BASE, @@ -299,22 +337,32 @@ class BC_DESC_BASE<string instr_asm, DAGOperand opnd> : BRANCH_DESC_BASE, dag OutOperandList = (outs); string AsmString = !strconcat(instr_asm, "\t$offset"); bit isBarrier = 1; + InstrItinClass Itinerary = II_BC; + bit isCTI = 1; } class CMP_BC_DESC_BASE<string instr_asm, DAGOperand opnd, - RegisterOperand GPROpnd> : BRANCH_DESC_BASE { + RegisterOperand GPROpnd> : BRANCH_DESC_BASE, + MipsR6Arch<instr_asm> { dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt, opnd:$offset); dag OutOperandList = (outs); string AsmString = !strconcat(instr_asm, "\t$rs, $rt, $offset"); list<Register> Defs = [AT]; + InstrItinClass Itinerary = II_BCCC; + bit hasForbiddenSlot = 1; + bit isCTI = 1; } class CMP_CBR_EQNE_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:$rs, opnd:$offset); dag OutOperandList = (outs); string AsmString = !strconcat(instr_asm, "\t$rs, $offset"); list<Register> Defs = [AT]; + InstrItinClass Itinerary = II_BCCZC; + bit hasForbiddenSlot = 1; + bit isCTI = 1; } class CMP_CBR_RT_Z_DESC_BASE<string instr_asm, DAGOperand opnd, @@ -324,17 +372,23 @@ class CMP_CBR_RT_Z_DESC_BASE<string instr_asm, DAGOperand opnd, dag OutOperandList = (outs); string AsmString = !strconcat(instr_asm, "\t$rt, $offset"); list<Register> Defs = [AT]; + InstrItinClass Itinerary = II_BCCZC; + bit hasForbiddenSlot = 1; + bit isCTI = 1; } class BAL_DESC : BC_DESC_BASE<"bal", brtarget> { bit isCall = 1; bit hasDelaySlot = 1; list<Register> Defs = [RA]; + bit isCTI = 1; } class BALC_DESC : BC_DESC_BASE<"balc", brtarget26> { bit isCall = 1; list<Register> Defs = [RA]; + InstrItinClass Itinerary = II_BALC; + bit isCTI = 1; } class BC_DESC : BC_DESC_BASE<"bc", brtarget26>; @@ -360,6 +414,7 @@ class COP1_BCCZ_DESC_BASE<string instr_asm> : BRANCH_DESC_BASE { dag OutOperandList = (outs); string AsmString = instr_asm; bit hasDelaySlot = 1; + InstrItinClass Itinerary = II_BC1CCZ; } class BC1EQZ_DESC : COP1_BCCZ_DESC_BASE<"bc1eqz $ft, $offset">; @@ -370,6 +425,7 @@ class COP2_BCCZ_DESC_BASE<string instr_asm> : BRANCH_DESC_BASE { dag OutOperandList = (outs); string AsmString = instr_asm; bit hasDelaySlot = 1; + bit isCTI = 1; } class BC2EQZ_DESC : COP2_BCCZ_DESC_BASE<"bc2eqz $ct, $offset">; @@ -379,23 +435,29 @@ 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, + InstrItinClass itin = NoItinerary> : MipsR6Arch<opstr> { dag InOperandList = (ins GPROpnd:$rt, opnd:$offset); string AsmString = !strconcat(opstr, "\t$rt, $offset"); list<dag> Pattern = []; - bit isTerminator = 1; bit hasDelaySlot = 0; + InstrItinClass Itinerary = itin; + bit isCTI = 1; + bit isBranch = 1; + bit isIndirectBranch = 1; } class JIALC_DESC : JMP_IDX_COMPACT_DESC_BASE<"jialc", calloffset16, - GPR32Opnd> { + GPR32Opnd, II_JIALC> { bit isCall = 1; list<Register> Defs = [RA]; } -class JIC_DESC : JMP_IDX_COMPACT_DESC_BASE<"jic", jmpoffset16, GPR32Opnd> { +class JIC_DESC : JMP_IDX_COMPACT_DESC_BASE<"jic", jmpoffset16, + GPR32Opnd, II_JIALC> { bit isBarrier = 1; + bit isTerminator = 1; list<Register> Defs = [AT]; } @@ -405,35 +467,39 @@ class JR_HB_R6_DESC : JR_HB_DESC_BASE<"jr.hb", GPR32Opnd> { bit hasDelaySlot = 1; bit isTerminator=1; bit isBarrier=1; + bit isCTI = 1; } -class BITSWAP_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> +class BITSWAP_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, + InstrItinClass itin> : MipsR6Arch<instr_asm> { dag OutOperandList = (outs GPROpnd:$rd); dag InOperandList = (ins GPROpnd:$rt); string AsmString = !strconcat(instr_asm, "\t$rd, $rt"); list<dag> Pattern = []; + InstrItinClass Itinerary = itin; } -class BITSWAP_DESC : BITSWAP_DESC_BASE<"bitswap", GPR32Opnd>; +class BITSWAP_DESC : BITSWAP_DESC_BASE<"bitswap", GPR32Opnd, II_BITSWAP>; class DIVMOD_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, + InstrItinClass itin, 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"); list<dag> Pattern = [(set GPROpnd:$rd, (Op GPROpnd:$rs, GPROpnd:$rt))]; - + InstrItinClass Itinerary = itin; // This instruction doesn't trap division by zero itself. We must insert // teq instructions as well. bit usesCustomInserter = 1; } -class DIV_DESC : DIVMOD_DESC_BASE<"div", GPR32Opnd, sdiv>; -class DIVU_DESC : DIVMOD_DESC_BASE<"divu", GPR32Opnd, udiv>; -class MOD_DESC : DIVMOD_DESC_BASE<"mod", GPR32Opnd, srem>; -class MODU_DESC : DIVMOD_DESC_BASE<"modu", GPR32Opnd, urem>; +class DIV_DESC : DIVMOD_DESC_BASE<"div", GPR32Opnd, II_DIV, sdiv>; +class DIVU_DESC : DIVMOD_DESC_BASE<"divu", GPR32Opnd, II_DIVU, udiv>; +class MOD_DESC : DIVMOD_DESC_BASE<"mod", GPR32Opnd, II_MOD, srem>; +class MODU_DESC : DIVMOD_DESC_BASE<"modu", GPR32Opnd, II_MODU, urem>; class BEQZALC_DESC : CMP_CBR_RT_Z_DESC_BASE<"beqzalc", brtarget, GPR32Opnd> { list<Register> Defs = [RA]; @@ -460,17 +526,19 @@ class BNEZALC_DESC : CMP_CBR_RT_Z_DESC_BASE<"bnezalc", brtarget, GPR32Opnd> { } class MUL_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, + InstrItinClass itin, 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"); list<dag> Pattern = [(set GPROpnd:$rd, (Op GPROpnd:$rs, GPROpnd:$rt))]; + InstrItinClass Itinerary = itin; } -class MUH_DESC : MUL_R6_DESC_BASE<"muh", GPR32Opnd, mulhs>; -class MUHU_DESC : MUL_R6_DESC_BASE<"muhu", GPR32Opnd, mulhu>; -class MUL_R6_DESC : MUL_R6_DESC_BASE<"mul", GPR32Opnd, mul>; -class MULU_DESC : MUL_R6_DESC_BASE<"mulu", GPR32Opnd>; +class MUH_DESC : MUL_R6_DESC_BASE<"muh", GPR32Opnd, II_MUH, mulhs>; +class MUHU_DESC : MUL_R6_DESC_BASE<"muhu", GPR32Opnd, II_MUHU, mulhu>; +class MUL_R6_DESC : MUL_R6_DESC_BASE<"mul", GPR32Opnd, II_MUL, mul>; +class MULU_DESC : MUL_R6_DESC_BASE<"mulu", GPR32Opnd, II_MULU>; class COP1_SEL_DESC_BASE<string instr_asm, RegisterOperand FGROpnd> { dag OutOperandList = (outs FGROpnd:$fd); @@ -482,11 +550,11 @@ class COP1_SEL_DESC_BASE<string instr_asm, RegisterOperand FGROpnd> { string Constraints = "$fd_in = $fd"; } -class SEL_D_DESC : COP1_SEL_DESC_BASE<"sel.d", FGR64Opnd> { +class SEL_D_DESC : COP1_SEL_DESC_BASE<"sel.d", FGR64Opnd>, MipsR6Arch<"sel.d"> { // We must insert a SUBREG_TO_REG around $fd_in bit usesCustomInserter = 1; } -class SEL_S_DESC : COP1_SEL_DESC_BASE<"sel.s", FGR32Opnd>; +class SEL_S_DESC : COP1_SEL_DESC_BASE<"sel.s", FGR32Opnd>, MipsR6Arch<"sel.s">; class SELEQNE_Z_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> : MipsR6Arch<instr_asm> { @@ -494,23 +562,26 @@ class SELEQNE_Z_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt); string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt"); list<dag> Pattern = []; + InstrItinClass Itinerary = II_SELCCZ; } class SELEQZ_DESC : SELEQNE_Z_DESC_BASE<"seleqz", GPR32Opnd>; class SELNEZ_DESC : SELEQNE_Z_DESC_BASE<"selnez", GPR32Opnd>; -class COP1_4R_DESC_BASE<string instr_asm, RegisterOperand FGROpnd> { +class COP1_4R_DESC_BASE<string instr_asm, RegisterOperand FGROpnd, + InstrItinClass itin = NoItinerary> { dag OutOperandList = (outs FGROpnd:$fd); dag InOperandList = (ins FGROpnd:$fd_in, FGROpnd:$fs, FGROpnd:$ft); string AsmString = !strconcat(instr_asm, "\t$fd, $fs, $ft"); list<dag> Pattern = []; string Constraints = "$fd_in = $fd"; + InstrItinClass Itinerary = itin; } -class MADDF_S_DESC : COP1_4R_DESC_BASE<"maddf.s", FGR32Opnd>; -class MADDF_D_DESC : COP1_4R_DESC_BASE<"maddf.d", FGR64Opnd>; -class MSUBF_S_DESC : COP1_4R_DESC_BASE<"msubf.s", FGR32Opnd>; -class MSUBF_D_DESC : COP1_4R_DESC_BASE<"msubf.d", FGR64Opnd>; +class MADDF_S_DESC : COP1_4R_DESC_BASE<"maddf.s", FGR32Opnd, II_MADDF_S>; +class MADDF_D_DESC : COP1_4R_DESC_BASE<"maddf.d", FGR64Opnd, II_MADDF_D>; +class MSUBF_S_DESC : COP1_4R_DESC_BASE<"msubf.s", FGR32Opnd, II_MSUBF_S>; +class MSUBF_D_DESC : COP1_4R_DESC_BASE<"msubf.d", FGR64Opnd, II_MSUBF_D>; class MAX_MIN_DESC_BASE<string instr_asm, RegisterOperand FGROpnd> { dag OutOperandList = (outs FGROpnd:$fd); @@ -536,10 +607,14 @@ class SELEQNEZ_DESC_BASE<string instr_asm, RegisterOperand FGROpnd> { list<dag> Pattern = []; } -class SELEQZ_S_DESC : SELEQNEZ_DESC_BASE<"seleqz.s", FGR32Opnd>; -class SELEQZ_D_DESC : SELEQNEZ_DESC_BASE<"seleqz.d", FGR64Opnd>; -class SELNEZ_S_DESC : SELEQNEZ_DESC_BASE<"selnez.s", FGR32Opnd>; -class SELNEZ_D_DESC : SELEQNEZ_DESC_BASE<"selnez.d", FGR64Opnd>; +class SELEQZ_S_DESC : SELEQNEZ_DESC_BASE<"seleqz.s", FGR32Opnd>, + MipsR6Arch<"seleqz.s">; +class SELEQZ_D_DESC : SELEQNEZ_DESC_BASE<"seleqz.d", FGR64Opnd>, + MipsR6Arch<"seleqz.d">; +class SELNEZ_S_DESC : SELEQNEZ_DESC_BASE<"selnez.s", FGR32Opnd>, + MipsR6Arch<"selnez.s">; +class SELNEZ_D_DESC : SELEQNEZ_DESC_BASE<"selnez.d", FGR64Opnd>, + MipsR6Arch<"selnez.d">; class CLASS_RINT_DESC_BASE<string instr_asm, RegisterOperand FGROpnd> { dag OutOperandList = (outs FGROpnd:$fd); @@ -590,61 +665,73 @@ 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> : MipsR6Arch<instr_asm> { + Operand ImmOpnd, InstrItinClass itin> + : 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"); list<dag> Pattern = []; + InstrItinClass Itinerary = itin; } -class LSA_R6_DESC : LSA_R6_DESC_BASE<"lsa", GPR32Opnd, uimm2_plus1>; +class LSA_R6_DESC : LSA_R6_DESC_BASE<"lsa", GPR32Opnd, uimm2_plus1, II_LSA>; -class LL_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> { +class LL_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, + Operand MemOpnd, InstrItinClass itin> + : MipsR6Arch<instr_asm> { dag OutOperandList = (outs GPROpnd:$rt); - dag InOperandList = (ins mem_simm9:$addr); + dag InOperandList = (ins MemOpnd:$addr); string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); list<dag> Pattern = []; bit mayLoad = 1; + InstrItinClass Itinerary = itin; } -class LL_R6_DESC : LL_R6_DESC_BASE<"ll", GPR32Opnd>; +class LL_R6_DESC : LL_R6_DESC_BASE<"ll", GPR32Opnd, mem_simm9, II_LL>; -class SC_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> { +class SC_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, + InstrItinClass itin> { dag OutOperandList = (outs GPROpnd:$dst); dag InOperandList = (ins GPROpnd:$rt, mem_simm9:$addr); string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); list<dag> Pattern = []; bit mayStore = 1; string Constraints = "$rt = $dst"; + InstrItinClass Itinerary = itin; } -class SC_R6_DESC : SC_R6_DESC_BASE<"sc", GPR32Opnd>; +class SC_R6_DESC : SC_R6_DESC_BASE<"sc", GPR32Opnd, II_SC>; -class CLO_CLZ_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> +class CLO_CLZ_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, + InstrItinClass itin> : MipsR6Arch<instr_asm> { dag OutOperandList = (outs GPROpnd:$rd); dag InOperandList = (ins GPROpnd:$rs); string AsmString = !strconcat(instr_asm, "\t$rd, $rs"); + InstrItinClass Itinerary = itin; } -class CLO_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> : - CLO_CLZ_R6_DESC_BASE<instr_asm, GPROpnd> { +class CLO_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, + InstrItinClass itin> : + CLO_CLZ_R6_DESC_BASE<instr_asm, GPROpnd, itin> { list<dag> Pattern = [(set GPROpnd:$rd, (ctlz (not GPROpnd:$rs)))]; } -class CLZ_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> : - CLO_CLZ_R6_DESC_BASE<instr_asm, GPROpnd> { +class CLZ_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, + InstrItinClass itin> : + CLO_CLZ_R6_DESC_BASE<instr_asm, GPROpnd, itin> { list<dag> Pattern = [(set GPROpnd:$rd, (ctlz GPROpnd:$rs))]; } -class CLO_R6_DESC : CLO_R6_DESC_BASE<"clo", GPR32Opnd>; -class CLZ_R6_DESC : CLZ_R6_DESC_BASE<"clz", GPR32Opnd>; +class CLO_R6_DESC : CLO_R6_DESC_BASE<"clo", GPR32Opnd, II_CLO>; +class CLZ_R6_DESC : CLZ_R6_DESC_BASE<"clz", GPR32Opnd, II_CLZ>; class SDBBP_R6_DESC { dag OutOperandList = (outs); dag InOperandList = (ins uimm20:$code_); string AsmString = "sdbbp\t$code_"; list<dag> Pattern = []; + bit isCTI = 1; } //===----------------------------------------------------------------------===// @@ -660,16 +747,18 @@ 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 : 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; +let AdditionalPredicates = [NotInMicroMips] in { + 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 : R6MMR6Rel, BC_ENC, BC_DESC, ISA_MIPS32R6; -def BEQC : BEQC_ENC, BEQC_DESC, ISA_MIPS32R6; +def BEQC : R6MMR6Rel, BEQC_ENC, BEQC_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 BEQZC : R6MMR6Rel, BEQZC_ENC, BEQZC_DESC, ISA_MIPS32R6; +def BGEC : R6MMR6Rel, BGEC_ENC, BGEC_DESC, ISA_MIPS32R6; +def BGEUC : R6MMR6Rel, BGEUC_ENC, BGEUC_DESC, ISA_MIPS32R6; def BGEZALC : R6MMR6Rel, BGEZALC_ENC, BGEZALC_DESC, ISA_MIPS32R6; def BGEZC : BGEZC_ENC, BGEZC_DESC, ISA_MIPS32R6; def BGTZALC : R6MMR6Rel, BGTZALC_ENC, BGTZALC_DESC, ISA_MIPS32R6; @@ -677,15 +766,17 @@ def BGTZC : BGTZC_ENC, BGTZC_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 BLTC : R6MMR6Rel, BLTC_ENC, BLTC_DESC, ISA_MIPS32R6; +def BLTUC : R6MMR6Rel, BLTUC_ENC, BLTUC_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 BNEC : R6MMR6Rel, BNEC_ENC, BNEC_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 BNEZC : R6MMR6Rel, BNEZC_ENC, BNEZC_DESC, ISA_MIPS32R6; +let AdditionalPredicates = [NotInMicroMips] in { + def BNVC : R6MMR6Rel, BNVC_ENC, BNVC_DESC, ISA_MIPS32R6; + def BOVC : R6MMR6Rel, BOVC_ENC, BOVC_DESC, ISA_MIPS32R6; +} def CACHE_R6 : R6MMR6Rel, CACHE_ENC, CACHE_DESC, ISA_MIPS32R6; let AdditionalPredicates = [NotInMicroMips] in { def CLASS_D : CLASS_D_ENC, CLASS_D_DESC, ISA_MIPS32R6, HARDFLOAT; @@ -695,15 +786,21 @@ 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 : R6MMR6Rel, DIV_ENC, DIV_DESC, ISA_MIPS32R6; -def DIVU : R6MMR6Rel, DIVU_ENC, DIVU_DESC, ISA_MIPS32R6; +let AdditionalPredicates = [NotInMicroMips] in { + 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; +let AdditionalPredicates = [NotInMicroMips] in { + def LDC2_R6 : LDC2_R6_ENC, LDC2_R6_DESC, ISA_MIPS32R6; + def LL_R6 : LL_R6_ENC, LL_R6_DESC, PTR_32, 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; +let AdditionalPredicates = [NotInMicroMips] in { + def LWC2_R6 : LWC2_R6_ENC, LWC2_R6_DESC, ISA_MIPS32R6; +} def LWPC : R6MMR6Rel, LWPC_ENC, LWPC_DESC, ISA_MIPS32R6; def LWUPC : LWUPC_ENC, LWUPC_DESC, ISA_MIPS32R6; let AdditionalPredicates = [NotInMicroMips] in { @@ -717,41 +814,40 @@ let AdditionalPredicates = [NotInMicroMips] in { 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; -let AdditionalPredicates = [NotInMicroMips] in { + + 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 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 : R6MMR6Rel, PREF_ENC, PREF_DESC, ISA_MIPS32R6; let AdditionalPredicates = [NotInMicroMips] in { 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, PTR_32, ISA_MIPS32R6; + def SDBBP_R6 : SDBBP_R6_ENC, SDBBP_R6_DESC, ISA_MIPS32R6; + def SELEQZ : R6MMR6Rel, SELEQZ_ENC, SELEQZ_DESC, ISA_MIPS32R6, GPR_32; + def SELNEZ : R6MMR6Rel, SELNEZ_ENC, SELNEZ_DESC, ISA_MIPS32R6, GPR_32; + def SELEQZ_D : R6MMR6Rel, SELEQZ_D_ENC, SELEQZ_D_DESC, ISA_MIPS32R6, + HARDFLOAT; + def SELEQZ_S : R6MMR6Rel, SELEQZ_S_ENC, SELEQZ_S_DESC, ISA_MIPS32R6, + HARDFLOAT; + def SELNEZ_D : R6MMR6Rel, SELNEZ_D_ENC, SELNEZ_D_DESC, ISA_MIPS32R6, + HARDFLOAT; + def SELNEZ_S : R6MMR6Rel, SELNEZ_S_ENC, SELNEZ_S_DESC, ISA_MIPS32R6, + HARDFLOAT; + def SEL_D : R6MMR6Rel, SEL_D_ENC, SEL_D_DESC, ISA_MIPS32R6, HARDFLOAT; + def SEL_S : R6MMR6Rel, SEL_S_ENC, SEL_S_DESC, ISA_MIPS32R6, HARDFLOAT; + def SDC2_R6 : SDC2_R6_ENC, SDC2_R6_DESC, ISA_MIPS32R6; + def SWC2_R6 : SWC2_R6_ENC, SWC2_R6_DESC, ISA_MIPS32R6; } -def SC_R6 : SC_R6_ENC, SC_R6_DESC, ISA_MIPS32R6; -let AdditionalPredicates = [NotInMicroMips] in { -def SDBBP_R6 : SDBBP_R6_ENC, SDBBP_R6_DESC, ISA_MIPS32R6; -} -def SDC2_R6 : SDC2_R6_ENC, SDC2_R6_DESC, ISA_MIPS32R6; -def SELEQZ : R6MMR6Rel, SELEQZ_ENC, SELEQZ_DESC, ISA_MIPS32R6, GPR_32; -let AdditionalPredicates = [NotInMicroMips] in { - 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; -let AdditionalPredicates = [NotInMicroMips] in { - 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; //===----------------------------------------------------------------------===// // @@ -761,9 +857,14 @@ def SWC2_R6 : SWC2_R6_ENC, SWC2_R6_DESC, ISA_MIPS32R6; let AdditionalPredicates = [NotInMicroMips] in { def : MipsInstAlias<"sdbbp", (SDBBP_R6 0)>, ISA_MIPS32R6; +def : MipsInstAlias<"jr $rs", (JALR ZERO, GPR32Opnd:$rs), 1>, ISA_MIPS32R6, GPR_32; } -def : MipsInstAlias<"jr $rs", (JALR ZERO, GPR32Opnd:$rs), 1>, ISA_MIPS32R6; +def : MipsInstAlias<"jrc $rs", (JIC GPR32Opnd:$rs, 0), 1>, ISA_MIPS32R6, GPR_32; + +let AdditionalPredicates = [NotInMicroMips] in { +def : MipsInstAlias<"jalrc $rs", (JIALC GPR32Opnd:$rs, 0), 1>, ISA_MIPS32R6, GPR_32; +} //===----------------------------------------------------------------------===// // // Patterns and Pseudo Instructions @@ -792,8 +893,10 @@ def : MipsPat<(setne VT:$lhs, VT:$rhs), (NOROp (!cast<Instruction>("CMP_EQ_"#NAME) VT:$lhs, VT:$rhs), ZEROReg)>; } -defm S : Cmp_Pats<f32, NOR, ZERO>, ISA_MIPS32R6; -defm D : Cmp_Pats<f64, NOR, ZERO>, ISA_MIPS32R6; +let AdditionalPredicates = [NotInMicroMips] in { + defm S : Cmp_Pats<f32, NOR, ZERO>, ISA_MIPS32R6; + defm D : Cmp_Pats<f64, NOR, ZERO>, ISA_MIPS32R6; +} // i32 selects multiclass SelectInt_Pats<ValueType RC, Instruction OROp, Instruction XORiOp, @@ -832,6 +935,7 @@ def : MipsPat<(select (Opg (setne RC:$cond, immz)), immz, RC:$f), (SELEQZOp RC:$f, RC:$cond)>; } +let AdditionalPredicates = [NotInMicroMips] in { defm : SelectInt_Pats<i32, OR, XORi, SLTi, SLTiu, SELEQZ, SELNEZ, immZExt16, i32>, ISA_MIPS32R6; @@ -845,3 +949,4 @@ def : MipsPat<(select i32:$cond, i32:$t, immz), def : MipsPat<(select i32:$cond, immz, i32:$f), (SELEQZ i32:$f, i32:$cond)>, ISA_MIPS32R6; +} diff --git a/lib/Target/Mips/Mips64InstrInfo.td b/lib/Target/Mips/Mips64InstrInfo.td index cbdcdd788bec7..88cfec5bc13c1 100644 --- a/lib/Target/Mips/Mips64InstrInfo.td +++ b/lib/Target/Mips/Mips64InstrInfo.td @@ -15,14 +15,6 @@ // Mips Operand, Complex Patterns and Transformations Definitions. //===----------------------------------------------------------------------===// -// Unsigned Operand -def uimm16_64 : Operand<i64> { - let PrintMethod = "printUnsignedImm"; -} - -// Signed Operand -def simm10_64 : Operand<i64>; - // Transformation Function - get Imm - 32. def Subtract32 : SDNodeXForm<imm, [{ return getImm(N, (unsigned)N->getZExtValue() - 32); @@ -37,7 +29,7 @@ def immSExt10_64 : PatLeaf<(i64 imm), [{ return isInt<10>(N->getSExtValue()); }]>; def immZExt16_64 : PatLeaf<(i64 imm), - [{ return isInt<16>(N->getZExtValue()); }]>; + [{ return isUInt<16>(N->getZExtValue()); }]>; def immZExt5_64 : ImmLeaf<i64, [{ return Imm == (Imm & 0x1f); }]>; @@ -71,6 +63,10 @@ def PowerOf2HI : PatLeaf<(imm), [{ return false; }]>; +def assertzext_lt_i32 : PatFrag<(ops node:$src), (assertzext node:$src), [{ + return cast<VTSDNode>(N->getOperand(1))->getVT().bitsLT(MVT::i32); +}]>; + //===----------------------------------------------------------------------===// // Instructions specific format //===----------------------------------------------------------------------===// @@ -86,7 +82,7 @@ let usesCustomInserter = 1 in { } /// Pseudo instructions for loading and storing accumulator registers. -let isPseudo = 1, isCodeGenOnly = 1 in { +let isPseudo = 1, isCodeGenOnly = 1, hasNoSchedulingInfo = 1 in { def LOAD_ACC128 : Load<"", ACC128>; def STORE_ACC128 : Store<"", ACC128>; } @@ -96,11 +92,13 @@ let isPseudo = 1, isCodeGenOnly = 1 in { //===----------------------------------------------------------------------===// let DecoderNamespace = "Mips64" in { /// Arithmetic Instructions (ALU Immediate) -def DADDi : ArithLogicI<"daddi", simm16_64, GPR64Opnd>, ADDI_FM<0x18>, - ISA_MIPS3_NOT_32R6_64R6; -def DADDiu : ArithLogicI<"daddiu", simm16_64, GPR64Opnd, II_DADDIU, - immSExt16, add>, - ADDI_FM<0x19>, IsAsCheapAsAMove, ISA_MIPS3; +def DADDi : ArithLogicI<"daddi", simm16_64, GPR64Opnd, II_DADDI>, + ADDI_FM<0x18>, ISA_MIPS3_NOT_32R6_64R6; +let AdditionalPredicates = [NotInMicroMips] in { + def DADDiu : StdMMR6Rel, ArithLogicI<"daddiu", simm16_64, GPR64Opnd, + II_DADDIU, immSExt16, add>, + ADDI_FM<0x19>, IsAsCheapAsAMove, ISA_MIPS3; +} let isCodeGenOnly = 1 in { def SLTi64 : SetCC_I<"slti", setlt, simm16_64, immSExt16, GPR64Opnd>, @@ -113,18 +111,20 @@ def ORi64 : ArithLogicI<"ori", uimm16_64, GPR64Opnd, II_OR, immZExt16, or>, ADDI_FM<0xd>; def XORi64 : ArithLogicI<"xori", uimm16_64, GPR64Opnd, II_XOR, immZExt16, xor>, ADDI_FM<0xe>; -def LUi64 : LoadUpper<"lui", GPR64Opnd, uimm16_64>, LUI_FM; +def LUi64 : LoadUpper<"lui", GPR64Opnd, uimm16_64_relaxed>, LUI_FM; } /// Arithmetic Instructions (3-Operand, R-Type) -def DADD : ArithLogicR<"dadd", GPR64Opnd, 1, II_DADD>, ADD_FM<0, 0x2c>, - ISA_MIPS3; -def DADDu : ArithLogicR<"daddu", GPR64Opnd, 1, II_DADDU, add>, ADD_FM<0, 0x2d>, - ISA_MIPS3; -def DSUBu : ArithLogicR<"dsubu", GPR64Opnd, 0, II_DSUBU, sub>, ADD_FM<0, 0x2f>, - ISA_MIPS3; -def DSUB : ArithLogicR<"dsub", GPR64Opnd, 0, II_DSUB>, ADD_FM<0, 0x2e>, - ISA_MIPS3; +let AdditionalPredicates = [NotInMicroMips] in { + def DADD : StdMMR6Rel, ArithLogicR<"dadd", GPR64Opnd, 1, II_DADD>, + ADD_FM<0, 0x2c>, ISA_MIPS3; + def DADDu : StdMMR6Rel, ArithLogicR<"daddu", GPR64Opnd, 1, II_DADDU, add>, + ADD_FM<0, 0x2d>, ISA_MIPS3; + def DSUBu : StdMMR6Rel, ArithLogicR<"dsubu", GPR64Opnd, 0, II_DSUBU, sub>, ADD_FM<0, 0x2f>, + ISA_MIPS3; + def DSUB : StdMMR6Rel, ArithLogicR<"dsub", GPR64Opnd, 0, II_DSUB>, ADD_FM<0, 0x2e>, + ISA_MIPS3; +} let isCodeGenOnly = 1 in { def SLT64 : SetCC_R<"slt", setlt, GPR64Opnd>, ADD_FM<0, 0x2a>; @@ -136,33 +136,43 @@ def NOR64 : LogicNOR<"nor", GPR64Opnd>, ADD_FM<0, 0x27>; } /// Shift Instructions -def DSLL : shift_rotate_imm<"dsll", uimm6, GPR64Opnd, II_DSLL, shl, immZExt6>, +let AdditionalPredicates = [NotInMicroMips] in { + def DSLL : StdMMR6Rel, shift_rotate_imm<"dsll", uimm6, GPR64Opnd, II_DSLL, + shl, immZExt6>, SRA_FM<0x38, 0>, ISA_MIPS3; -def DSRL : shift_rotate_imm<"dsrl", uimm6, GPR64Opnd, II_DSRL, srl, immZExt6>, + def DSRL : StdMMR6Rel, shift_rotate_imm<"dsrl", uimm6, GPR64Opnd, II_DSRL, + srl, immZExt6>, SRA_FM<0x3a, 0>, ISA_MIPS3; -def DSRA : shift_rotate_imm<"dsra", uimm6, GPR64Opnd, II_DSRA, sra, immZExt6>, + def DSRA : StdMMR6Rel, shift_rotate_imm<"dsra", uimm6, GPR64Opnd, II_DSRA, + sra, immZExt6>, SRA_FM<0x3b, 0>, ISA_MIPS3; -def DSLLV : shift_rotate_reg<"dsllv", GPR64Opnd, II_DSLLV, shl>, - SRLV_FM<0x14, 0>, ISA_MIPS3; -def DSRLV : shift_rotate_reg<"dsrlv", GPR64Opnd, II_DSRLV, srl>, - SRLV_FM<0x16, 0>, ISA_MIPS3; -def DSRAV : shift_rotate_reg<"dsrav", GPR64Opnd, II_DSRAV, sra>, - SRLV_FM<0x17, 0>, ISA_MIPS3; -def DSLL32 : shift_rotate_imm<"dsll32", uimm5, GPR64Opnd, II_DSLL32>, - SRA_FM<0x3c, 0>, ISA_MIPS3; -def DSRL32 : shift_rotate_imm<"dsrl32", uimm5, GPR64Opnd, II_DSRL32>, - SRA_FM<0x3e, 0>, ISA_MIPS3; -def DSRA32 : shift_rotate_imm<"dsra32", uimm5, GPR64Opnd, II_DSRA32>, - SRA_FM<0x3f, 0>, ISA_MIPS3; + def DSLLV : StdMMR6Rel, shift_rotate_reg<"dsllv", GPR64Opnd, II_DSLLV, shl>, + SRLV_FM<0x14, 0>, ISA_MIPS3; + def DSRAV : StdMMR6Rel, shift_rotate_reg<"dsrav", GPR64Opnd, II_DSRAV, sra>, + SRLV_FM<0x17, 0>, ISA_MIPS3; + def DSRLV : StdMMR6Rel, shift_rotate_reg<"dsrlv", GPR64Opnd, II_DSRLV, srl>, + SRLV_FM<0x16, 0>, ISA_MIPS3; + def DSLL32 : StdMMR6Rel, shift_rotate_imm<"dsll32", uimm5, GPR64Opnd, + II_DSLL32>, + SRA_FM<0x3c, 0>, ISA_MIPS3; + def DSRL32 : StdMMR6Rel, shift_rotate_imm<"dsrl32", uimm5, GPR64Opnd, + II_DSRL32>, + SRA_FM<0x3e, 0>, ISA_MIPS3; + def DSRA32 : StdMMR6Rel, shift_rotate_imm<"dsra32", uimm5, GPR64Opnd, + II_DSRA32>, + SRA_FM<0x3f, 0>, ISA_MIPS3; // Rotate Instructions -def DROTR : shift_rotate_imm<"drotr", uimm6, GPR64Opnd, II_DROTR, rotr, - immZExt6>, - SRA_FM<0x3a, 1>, ISA_MIPS64R2; -def DROTRV : shift_rotate_reg<"drotrv", GPR64Opnd, II_DROTRV, rotr>, - SRLV_FM<0x16, 1>, ISA_MIPS64R2; -def DROTR32 : shift_rotate_imm<"drotr32", uimm5, GPR64Opnd, II_DROTR32>, - SRA_FM<0x3e, 1>, ISA_MIPS64R2; + def DROTR : StdMMR6Rel, shift_rotate_imm<"drotr", uimm6, GPR64Opnd, II_DROTR, + rotr, immZExt6>, + SRA_FM<0x3a, 1>, ISA_MIPS64R2; + def DROTRV : StdMMR6Rel, shift_rotate_reg<"drotrv", GPR64Opnd, II_DROTRV, + rotr>, + SRLV_FM<0x16, 1>, ISA_MIPS64R2; + def DROTR32 : StdMMR6Rel, shift_rotate_imm<"drotr32", uimm5, GPR64Opnd, + II_DROTR32>, + SRA_FM<0x3e, 1>, ISA_MIPS64R2; +} /// Load and Store Instructions /// aligned @@ -177,9 +187,16 @@ def SH64 : Store<"sh", GPR64Opnd, truncstorei16, II_SH>, LW_FM<0x29>; def SW64 : Store<"sw", GPR64Opnd, truncstorei32, II_SW>, LW_FM<0x2b>; } -def LWu : Load<"lwu", GPR64Opnd, zextloadi32, II_LWU>, LW_FM<0x27>, ISA_MIPS3; -def LD : Load<"ld", GPR64Opnd, load, II_LD>, LW_FM<0x37>, ISA_MIPS3; -def SD : Store<"sd", GPR64Opnd, store, II_SD>, LW_FM<0x3f>, ISA_MIPS3; +let AdditionalPredicates = [NotInMicroMips] in { + def LWu : StdMMR6Rel, MMRel, Load<"lwu", GPR64Opnd, zextloadi32, II_LWU>, + LW_FM<0x27>, ISA_MIPS3; + def LD : StdMMR6Rel, LoadMemory<"ld", GPR64Opnd, mem_simm16, load, II_LD>, + LW_FM<0x37>, ISA_MIPS3; + def SD : StdMMR6Rel, StoreMemory<"sd", GPR64Opnd, mem_simm16, store, II_SD>, + LW_FM<0x3f>, ISA_MIPS3; +} + + /// load/store left/right let isCodeGenOnly = 1 in { @@ -199,9 +216,20 @@ def SDR : StoreLeftRight<"sdr", MipsSDR, GPR64Opnd, II_SDR>, LW_FM<0x2d>, ISA_MIPS3_NOT_32R6_64R6; /// Load-linked, Store-conditional -def LLD : LLBase<"lld", GPR64Opnd>, LW_FM<0x34>, ISA_MIPS3_NOT_32R6_64R6; +let AdditionalPredicates = [NotInMicroMips] in { + def LLD : StdMMR6Rel, LLBase<"lld", GPR64Opnd, mem_simm16>, LW_FM<0x34>, + ISA_MIPS3_NOT_32R6_64R6; +} def SCD : SCBase<"scd", GPR64Opnd>, LW_FM<0x3c>, ISA_MIPS3_NOT_32R6_64R6; +let AdditionalPredicates = [NotInMicroMips], + DecoderNamespace = "Mips32_64_PTR64" in { +def LL64 : LLBase<"ll", GPR32Opnd>, LW_FM<0x30>, PTR_64, + ISA_MIPS2_NOT_32R6_64R6; +def SC64 : SCBase<"sc", GPR32Opnd>, LW_FM<0x38>, PTR_64, + ISA_MIPS2_NOT_32R6_64R6; +} + /// Jump and Branch Instructions let isCodeGenOnly = 1 in { def JR64 : IndirectBranch<"jr", GPR64Opnd>, MTLO_FM<8>; @@ -220,18 +248,22 @@ def PseudoReturn64 : PseudoReturnBase<GPR64Opnd>; def PseudoIndirectBranch64 : PseudoIndirectBranchBase<GPR64Opnd>; /// Multiply and Divide Instructions. -def DMULT : Mult<"dmult", II_DMULT, GPR64Opnd, [HI0_64, LO0_64]>, - MULT_FM<0, 0x1c>, ISA_MIPS3_NOT_32R6_64R6; -def DMULTu : Mult<"dmultu", II_DMULTU, GPR64Opnd, [HI0_64, LO0_64]>, - MULT_FM<0, 0x1d>, ISA_MIPS3_NOT_32R6_64R6; +let AdditionalPredicates = [NotInMicroMips] in { + def DMULT : Mult<"dmult", II_DMULT, GPR64Opnd, [HI0_64, LO0_64]>, + MULT_FM<0, 0x1c>, ISA_MIPS3_NOT_32R6_64R6; + def DMULTu : Mult<"dmultu", II_DMULTU, GPR64Opnd, [HI0_64, LO0_64]>, + MULT_FM<0, 0x1d>, ISA_MIPS3_NOT_32R6_64R6; +} def PseudoDMULT : MultDivPseudo<DMULT, ACC128, GPR64Opnd, MipsMult, II_DMULT>, ISA_MIPS3_NOT_32R6_64R6; def PseudoDMULTu : MultDivPseudo<DMULTu, ACC128, GPR64Opnd, MipsMultu, II_DMULTU>, ISA_MIPS3_NOT_32R6_64R6; -def DSDIV : Div<"ddiv", II_DDIV, GPR64Opnd, [HI0_64, LO0_64]>, - MULT_FM<0, 0x1e>, ISA_MIPS3_NOT_32R6_64R6; -def DUDIV : Div<"ddivu", II_DDIVU, GPR64Opnd, [HI0_64, LO0_64]>, - MULT_FM<0, 0x1f>, ISA_MIPS3_NOT_32R6_64R6; +let AdditionalPredicates = [NotInMicroMips] in { + def DSDIV : Div<"ddiv", II_DDIV, GPR64Opnd, [HI0_64, LO0_64]>, + MULT_FM<0, 0x1e>, ISA_MIPS3_NOT_32R6_64R6; + def DUDIV : Div<"ddivu", II_DDIVU, GPR64Opnd, [HI0_64, LO0_64]>, + MULT_FM<0, 0x1f>, ISA_MIPS3_NOT_32R6_64R6; +} def PseudoDSDIV : MultDivPseudo<DSDIV, ACC128, GPR64Opnd, MipsDivRem, II_DDIV, 0, 1, 1>, ISA_MIPS3_NOT_32R6_64R6; def PseudoDUDIV : MultDivPseudo<DUDIV, ACC128, GPR64Opnd, MipsDivRemU, @@ -260,12 +292,16 @@ def SEH64 : SignExtInReg<"seh", i16, GPR64Opnd, II_SEH>, SEB_FM<0x18, 0x20>, } /// Count Leading -def DCLZ : CountLeading0<"dclz", GPR64Opnd>, CLO_FM<0x24>, ISA_MIPS64_NOT_64R6; -def DCLO : CountLeading1<"dclo", GPR64Opnd>, CLO_FM<0x25>, ISA_MIPS64_NOT_64R6; +let AdditionalPredicates = [NotInMicroMips] in { + def DCLZ : StdMMR6Rel, CountLeading0<"dclz", GPR64Opnd>, CLO_FM<0x24>, + ISA_MIPS64_NOT_64R6; + def DCLO : StdMMR6Rel, CountLeading1<"dclo", GPR64Opnd>, CLO_FM<0x25>, + ISA_MIPS64_NOT_64R6; /// Double Word Swap Bytes/HalfWords -def DSBH : SubwordSwap<"dsbh", GPR64Opnd>, SEB_FM<2, 0x24>, ISA_MIPS64R2; -def DSHD : SubwordSwap<"dshd", GPR64Opnd>, SEB_FM<5, 0x24>, ISA_MIPS64R2; + def DSBH : SubwordSwap<"dsbh", GPR64Opnd>, SEB_FM<2, 0x24>, ISA_MIPS64R2; + def DSHD : SubwordSwap<"dshd", GPR64Opnd>, SEB_FM<5, 0x24>, ISA_MIPS64R2; +} def LEA_ADDiu64 : EffectiveAddress<"daddiu", GPR64Opnd>, LW_FM<0x19>; @@ -273,21 +309,24 @@ let isCodeGenOnly = 1 in def RDHWR64 : ReadHardware<GPR64Opnd, HWRegsOpnd>, RDHWR_FM; let AdditionalPredicates = [NotInMicroMips] in { - // TODO: Add 'pos + size' constraint check to dext* instructions - // DEXT: 0 < pos + size <= 63 - // DEXTM, DEXTU: 32 < pos + size <= 64 - def DEXT : ExtBase<"dext", GPR64Opnd, uimm5, uimm5_plus1, MipsExt>, - EXT_FM<3>; - def DEXTM : ExtBase<"dextm", GPR64Opnd, uimm5, uimm5_plus33, MipsExt>, - EXT_FM<1>; + // The 'pos + size' constraints are enforced by the code that lowers into + // MipsISD::Ext. + def DEXT : ExtBase<"dext", GPR64Opnd, uimm5_report_uimm6, uimm5_plus1, + immZExt5, immZExt5Plus1, MipsExt>, EXT_FM<3>, + ISA_MIPS64R2; + def DEXTM : ExtBase<"dextm", GPR64Opnd, uimm5, uimm5_plus33, immZExt5, + immZExt5Plus33, MipsExt>, EXT_FM<1>, ISA_MIPS64R2; def DEXTU : ExtBase<"dextu", GPR64Opnd, uimm5_plus32, uimm5_plus1, - MipsExt>, EXT_FM<2>; + immZExt5Plus32, immZExt5Plus1, MipsExt>, EXT_FM<2>, + ISA_MIPS64R2; + def DINS : InsBase<"dins", GPR64Opnd, uimm6, uimm5_inssize_plus1, MipsIns>, + EXT_FM<7>, ISA_MIPS64R2; + def DINSU : InsBase<"dinsu", GPR64Opnd, uimm5_plus32, uimm5_inssize_plus1>, + EXT_FM<6>, ISA_MIPS64R2; + def DINSM : InsBase<"dinsm", GPR64Opnd, uimm5, uimm5_inssize_plus1>, + EXT_FM<5>, ISA_MIPS64R2; } -def DINS : InsBase<"dins", GPR64Opnd, uimm6, MipsIns>, EXT_FM<7>; -def DINSU : InsBase<"dinsu", GPR64Opnd, uimm5_plus32>, EXT_FM<6>; -def DINSM : InsBase<"dinsm", GPR64Opnd, uimm5>, EXT_FM<5>; - let isCodeGenOnly = 1, rs = 0, shamt = 0 in { def DSLL64_32 : FR<0x00, 0x3c, (outs GPR64:$rd), (ins GPR32:$rt), "dsll\t$rd, $rt, 32", [], II_DSLL>; @@ -309,8 +348,8 @@ def LONG_BRANCH_DADDiu : PseudoSE<(outs GPR64Opnd:$dst), // Cavium Octeon cnMIPS instructions let DecoderNamespace = "CnMips", - EncodingPredicates = []<Predicate>, // FIXME: The lack of HasStdEnc is probably a bug - AdditionalPredicates = [HasCnMips] in { + // FIXME: The lack of HasStdEnc is probably a bug + EncodingPredicates = []<Predicate> in { class Count1s<string opstr, RegisterOperand RO>: InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"), @@ -361,83 +400,94 @@ class MFC2OP<string asmstr, RegisterOperand RO> : !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>; + ADD_FM<0x1c, 0x28>, ASE_CNMIPS { + let Pattern = [(set GPR64Opnd:$rd, + (and (add GPR64Opnd:$rs, GPR64Opnd:$rt), 255))]; +} // Branch on Bit Clear /+32 def BBIT0 : CBranchBitNum<"bbit0", brtarget, seteq, GPR64Opnd, - uimm5_64_report_uimm6>, BBIT_FM<0x32>; + uimm5_64_report_uimm6>, BBIT_FM<0x32>, ASE_CNMIPS; def BBIT032: CBranchBitNum<"bbit032", brtarget, seteq, GPR64Opnd, uimm5_64, - 0x100000000>, - BBIT_FM<0x36>; + 0x100000000>, BBIT_FM<0x36>, ASE_CNMIPS; // Branch on Bit Set /+32 def BBIT1 : CBranchBitNum<"bbit1", brtarget, setne, GPR64Opnd, - uimm5_64_report_uimm6>, BBIT_FM<0x3a>; + uimm5_64_report_uimm6>, BBIT_FM<0x3a>, ASE_CNMIPS; def BBIT132: CBranchBitNum<"bbit132", brtarget, setne, GPR64Opnd, uimm5_64, - 0x100000000>, BBIT_FM<0x3e>; + 0x100000000>, BBIT_FM<0x3e>, ASE_CNMIPS; // Multiply Doubleword to GPR -let Defs = [HI0, LO0, P0, P1, P2] in def DMUL : ArithLogicR<"dmul", GPR64Opnd, 1, II_DMUL, mul>, - ADD_FM<0x1c, 0x03>; + ADD_FM<0x1c, 0x03>, ASE_CNMIPS { + let Defs = [HI0, LO0, P0, P1, P2]; +} // Extract a signed bit field /+32 -def EXTS : ExtsCins<"exts">, EXTS_FM<0x3a>; -def EXTS32: ExtsCins<"exts32">, EXTS_FM<0x3b>; +def EXTS : ExtsCins<"exts">, EXTS_FM<0x3a>, ASE_CNMIPS; +def EXTS32: ExtsCins<"exts32">, EXTS_FM<0x3b>, ASE_CNMIPS; // Clear and insert a bit field /+32 -def CINS : ExtsCins<"cins">, EXTS_FM<0x32>; -def CINS32: ExtsCins<"cins32">, EXTS_FM<0x33>; +def CINS : ExtsCins<"cins">, EXTS_FM<0x32>, ASE_CNMIPS; +def CINS32: ExtsCins<"cins32">, EXTS_FM<0x33>, ASE_CNMIPS; // Move to multiplier/product register -def MTM0 : MoveToLOHI<"mtm0", GPR64Opnd, [MPL0, P0, P1, P2]>, MTMR_FM<0x08>; -def MTM1 : MoveToLOHI<"mtm1", GPR64Opnd, [MPL1, P0, P1, P2]>, MTMR_FM<0x0c>; -def MTM2 : MoveToLOHI<"mtm2", GPR64Opnd, [MPL2, P0, P1, P2]>, MTMR_FM<0x0d>; -def MTP0 : MoveToLOHI<"mtp0", GPR64Opnd, [P0]>, MTMR_FM<0x09>; -def MTP1 : MoveToLOHI<"mtp1", GPR64Opnd, [P1]>, MTMR_FM<0x0a>; -def MTP2 : MoveToLOHI<"mtp2", GPR64Opnd, [P2]>, MTMR_FM<0x0b>; +def MTM0 : MoveToLOHI<"mtm0", GPR64Opnd, [MPL0, P0, P1, P2]>, MTMR_FM<0x08>, + ASE_CNMIPS; +def MTM1 : MoveToLOHI<"mtm1", GPR64Opnd, [MPL1, P0, P1, P2]>, MTMR_FM<0x0c>, + ASE_CNMIPS; +def MTM2 : MoveToLOHI<"mtm2", GPR64Opnd, [MPL2, P0, P1, P2]>, MTMR_FM<0x0d>, + ASE_CNMIPS; +def MTP0 : MoveToLOHI<"mtp0", GPR64Opnd, [P0]>, MTMR_FM<0x09>, ASE_CNMIPS; +def MTP1 : MoveToLOHI<"mtp1", GPR64Opnd, [P1]>, MTMR_FM<0x0a>, ASE_CNMIPS; +def MTP2 : MoveToLOHI<"mtp2", GPR64Opnd, [P2]>, MTMR_FM<0x0b>, ASE_CNMIPS; // Count Ones in a Word/Doubleword -def POP : Count1s<"pop", GPR32Opnd>, POP_FM<0x2c>; -def DPOP : Count1s<"dpop", GPR64Opnd>, POP_FM<0x2d>; +def POP : Count1s<"pop", GPR32Opnd>, POP_FM<0x2c>, ASE_CNMIPS; +def DPOP : Count1s<"dpop", GPR64Opnd>, POP_FM<0x2d>, ASE_CNMIPS; // Set on equal/not equal -def SEQ : SetCC64_R<"seq", seteq>, SEQ_FM<0x2a>; -def SEQi : SetCC64_I<"seqi", seteq>, SEQI_FM<0x2e>; -def SNE : SetCC64_R<"sne", setne>, SEQ_FM<0x2b>; -def SNEi : SetCC64_I<"snei", setne>, SEQI_FM<0x2f>; +def SEQ : SetCC64_R<"seq", seteq>, SEQ_FM<0x2a>, ASE_CNMIPS; +def SEQi : SetCC64_I<"seqi", seteq>, SEQI_FM<0x2e>, ASE_CNMIPS; +def SNE : SetCC64_R<"sne", setne>, SEQ_FM<0x2b>, ASE_CNMIPS; +def SNEi : SetCC64_I<"snei", setne>, SEQI_FM<0x2f>, ASE_CNMIPS; // 192-bit x 64-bit Unsigned Multiply and Add -let Defs = [P0, P1, P2] in -def V3MULU: ArithLogicR<"v3mulu", GPR64Opnd, 0, II_DMUL>, - ADD_FM<0x1c, 0x11>; +def V3MULU: ArithLogicR<"v3mulu", GPR64Opnd, 0, II_DMUL>, ADD_FM<0x1c, 0x11>, + ASE_CNMIPS { + let Defs = [P0, P1, P2]; +} // 64-bit Unsigned Multiply and Add Move -let Defs = [MPL0, P0, P1, P2] in -def VMM0 : ArithLogicR<"vmm0", GPR64Opnd, 0, II_DMUL>, - ADD_FM<0x1c, 0x10>; +def VMM0 : ArithLogicR<"vmm0", GPR64Opnd, 0, II_DMUL>, ADD_FM<0x1c, 0x10>, + ASE_CNMIPS { + let Defs = [MPL0, P0, P1, P2]; +} // 64-bit Unsigned Multiply and Add -let Defs = [MPL1, MPL2, P0, P1, P2] in -def VMULU : ArithLogicR<"vmulu", GPR64Opnd, 0, II_DMUL>, - ADD_FM<0x1c, 0x0f>; +def VMULU : ArithLogicR<"vmulu", GPR64Opnd, 0, II_DMUL>, ADD_FM<0x1c, 0x0f>, + ASE_CNMIPS { + let Defs = [MPL1, MPL2, P0, P1, P2]; +} // 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>; +def DMFC2_OCTEON : MFC2OP<"dmfc2", GPR64Opnd>, MFC2OP_FM<0x12, 1>, ASE_CNMIPS; +def DMTC2_OCTEON : MFC2OP<"dmtc2", GPR64Opnd>, MFC2OP_FM<0x12, 5>, ASE_CNMIPS; } } /// Move between CPU and coprocessor registers let DecoderNamespace = "Mips64", Predicates = [HasMips64] in { -def DMFC0 : MFC3OP<"dmfc0", GPR64Opnd, COP0Opnd>, MFC3OP_FM<0x10, 1>, ISA_MIPS3; -def DMTC0 : MTC3OP<"dmtc0", COP0Opnd, GPR64Opnd>, MFC3OP_FM<0x10, 5>, ISA_MIPS3; -def DMFC2 : MFC3OP<"dmfc2", GPR64Opnd, COP2Opnd>, MFC3OP_FM<0x12, 1>, ISA_MIPS3; -def DMTC2 : MTC3OP<"dmtc2", COP2Opnd, GPR64Opnd>, MFC3OP_FM<0x12, 5>, ISA_MIPS3; +def DMFC0 : MFC3OP<"dmfc0", GPR64Opnd, COP0Opnd, II_DMFC0>, MFC3OP_FM<0x10, 1>, + ISA_MIPS3; +def DMTC0 : MTC3OP<"dmtc0", COP0Opnd, GPR64Opnd, II_DMTC0>, MFC3OP_FM<0x10, 5>, + ISA_MIPS3; +def DMFC2 : MFC3OP<"dmfc2", GPR64Opnd, COP2Opnd, II_DMFC2>, MFC3OP_FM<0x12, 1>, + ISA_MIPS3; +def DMTC2 : MTC3OP<"dmtc2", COP2Opnd, GPR64Opnd, II_DMTC2>, MFC3OP_FM<0x12, 5>, + ISA_MIPS3; } //===----------------------------------------------------------------------===// @@ -458,31 +508,34 @@ def : MipsPat<(MipsHi tconstpool:$in), (LUi64 tconstpool:$in)>; def : MipsPat<(MipsHi tglobaltlsaddr:$in), (LUi64 tglobaltlsaddr:$in)>; def : MipsPat<(MipsHi texternalsym:$in), (LUi64 texternalsym:$in)>; -def : MipsPat<(MipsLo tglobaladdr:$in), (DADDiu ZERO_64, tglobaladdr:$in)>; -def : MipsPat<(MipsLo tblockaddress:$in), (DADDiu ZERO_64, tblockaddress:$in)>; -def : MipsPat<(MipsLo tjumptable:$in), (DADDiu ZERO_64, tjumptable:$in)>; -def : MipsPat<(MipsLo tconstpool:$in), (DADDiu ZERO_64, tconstpool:$in)>; -def : MipsPat<(MipsLo tglobaltlsaddr:$in), - (DADDiu ZERO_64, tglobaltlsaddr:$in)>; -def : MipsPat<(MipsLo texternalsym:$in), (DADDiu ZERO_64, texternalsym:$in)>; - -def : MipsPat<(add GPR64:$hi, (MipsLo tglobaladdr:$lo)), - (DADDiu GPR64:$hi, tglobaladdr:$lo)>; -def : MipsPat<(add GPR64:$hi, (MipsLo tblockaddress:$lo)), - (DADDiu GPR64:$hi, tblockaddress:$lo)>; -def : MipsPat<(add GPR64:$hi, (MipsLo tjumptable:$lo)), - (DADDiu GPR64:$hi, tjumptable:$lo)>; -def : MipsPat<(add GPR64:$hi, (MipsLo tconstpool:$lo)), - (DADDiu GPR64:$hi, tconstpool:$lo)>; -def : MipsPat<(add GPR64:$hi, (MipsLo tglobaltlsaddr:$lo)), - (DADDiu GPR64:$hi, tglobaltlsaddr:$lo)>; - -def : WrapperPat<tglobaladdr, DADDiu, GPR64>; -def : WrapperPat<tconstpool, DADDiu, GPR64>; -def : WrapperPat<texternalsym, DADDiu, GPR64>; -def : WrapperPat<tblockaddress, DADDiu, GPR64>; -def : WrapperPat<tjumptable, DADDiu, GPR64>; -def : WrapperPat<tglobaltlsaddr, DADDiu, GPR64>; +let AdditionalPredicates = [NotInMicroMips] in { + def : MipsPat<(MipsLo tglobaladdr:$in), (DADDiu ZERO_64, tglobaladdr:$in)>; + def : MipsPat<(MipsLo tblockaddress:$in), + (DADDiu ZERO_64, tblockaddress:$in)>; + def : MipsPat<(MipsLo tjumptable:$in), (DADDiu ZERO_64, tjumptable:$in)>; + def : MipsPat<(MipsLo tconstpool:$in), (DADDiu ZERO_64, tconstpool:$in)>; + def : MipsPat<(MipsLo tglobaltlsaddr:$in), + (DADDiu ZERO_64, tglobaltlsaddr:$in)>; + def : MipsPat<(MipsLo texternalsym:$in), (DADDiu ZERO_64, texternalsym:$in)>; + + def : MipsPat<(add GPR64:$hi, (MipsLo tglobaladdr:$lo)), + (DADDiu GPR64:$hi, tglobaladdr:$lo)>; + def : MipsPat<(add GPR64:$hi, (MipsLo tblockaddress:$lo)), + (DADDiu GPR64:$hi, tblockaddress:$lo)>; + def : MipsPat<(add GPR64:$hi, (MipsLo tjumptable:$lo)), + (DADDiu GPR64:$hi, tjumptable:$lo)>; + def : MipsPat<(add GPR64:$hi, (MipsLo tconstpool:$lo)), + (DADDiu GPR64:$hi, tconstpool:$lo)>; + def : MipsPat<(add GPR64:$hi, (MipsLo tglobaltlsaddr:$lo)), + (DADDiu GPR64:$hi, tglobaltlsaddr:$lo)>; + + def : WrapperPat<tglobaladdr, DADDiu, GPR64>; + def : WrapperPat<tconstpool, DADDiu, GPR64>; + def : WrapperPat<texternalsym, DADDiu, GPR64>; + def : WrapperPat<tblockaddress, DADDiu, GPR64>; + def : WrapperPat<tjumptable, DADDiu, GPR64>; + def : WrapperPat<tglobaltlsaddr, DADDiu, GPR64>; +} defm : BrcondPats<GPR64, BEQ64, BNE64, SLT64, SLTu64, SLTi64, SLTiu64, ZERO_64>; @@ -502,7 +555,17 @@ defm : SetgeImmPats<GPR64, SLTi64, SLTiu64>; // truncate def : MipsPat<(trunc (assertsext GPR64:$src)), (EXTRACT_SUBREG GPR64:$src, sub_32)>; -def : MipsPat<(trunc (assertzext GPR64:$src)), +// The forward compatibility strategy employed by MIPS requires us to treat +// values as being sign extended to an infinite number of bits. This allows +// existing software to run without modification on any future MIPS +// implementation (e.g. 128-bit, or 1024-bit). Being compatible with this +// strategy requires that truncation acts as a sign-extension for values being +// fed into instructions operating on 32-bit values. Such instructions have +// undefined results if this is not true. +// For our case, this means that we can't issue an extract_subreg for nodes +// such as (trunc:i32 (assertzext:i64 X, i32)), because the sign-bit of the +// lower subreg would not be replicated into the upper half. +def : MipsPat<(trunc (assertzext_lt_i32 GPR64:$src)), (EXTRACT_SUBREG GPR64:$src, sub_32)>; def : MipsPat<(i32 (trunc GPR64:$src)), (SLL (EXTRACT_SUBREG GPR64:$src, sub_32), 0)>; @@ -514,11 +577,14 @@ 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))>; +let AdditionalPredicates = [NotInMicroMips] in { + 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 (anyext GPR32:$src)), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GPR32:$src, sub_32)>; def : MipsPat<(i64 (zext GPR32:$src)), (DSRL (DSLL64_32 GPR32:$src), 32)>; def : MipsPat<(i64 (sext GPR32:$src)), (SLL64_32 GPR32:$src)>; @@ -530,26 +596,24 @@ def : MipsPat<(i64 (sext_inreg GPR64:$src, i32)), def : MipsPat<(bswap GPR64:$rt), (DSHD (DSBH GPR64:$rt))>; // Carry pattern -def : MipsPat<(subc GPR64:$lhs, GPR64:$rhs), - (DSUBu GPR64:$lhs, GPR64:$rhs)>; -let AdditionalPredicates = [NotDSP] in { +let AdditionalPredicates = [NotInMicroMips] in { + def : MipsPat<(subc GPR64:$lhs, GPR64:$rhs), + (DSUBu GPR64:$lhs, GPR64:$rhs)>; def : MipsPat<(addc GPR64:$lhs, GPR64:$rhs), - (DADDu GPR64:$lhs, GPR64:$rhs)>; + (DADDu GPR64:$lhs, GPR64:$rhs)>, ASE_NOT_DSP; def : MipsPat<(addc GPR64:$lhs, immSExt16:$imm), - (DADDiu GPR64:$lhs, imm:$imm)>; + (DADDiu GPR64:$lhs, imm:$imm)>, ASE_NOT_DSP; } // 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)>; + (BBIT0 i64:$lhs, (Log2LO PowerOf2LO:$mask), bb:$dst)>, ASE_MIPS64_CNMIPS; def : MipsPat<(brcond (i32 (seteq (and i64:$lhs, PowerOf2HI:$mask), 0)), bb:$dst), - (BBIT032 i64:$lhs, (Log2HI PowerOf2HI:$mask), bb:$dst)>; + (BBIT032 i64:$lhs, (Log2HI PowerOf2HI:$mask), bb:$dst)>, ASE_MIPS64_CNMIPS; def : MipsPat<(brcond (i32 (setne (and i64:$lhs, PowerOf2LO:$mask), 0)), bb:$dst), - (BBIT1 i64:$lhs, (Log2LO PowerOf2LO:$mask), bb:$dst)>; + (BBIT1 i64:$lhs, (Log2LO PowerOf2LO:$mask), bb:$dst)>, ASE_MIPS64_CNMIPS; def : MipsPat<(brcond (i32 (setne (and i64:$lhs, PowerOf2HI:$mask), 0)), bb:$dst), - (BBIT132 i64:$lhs, (Log2HI PowerOf2HI:$mask), bb:$dst)>; -} + (BBIT132 i64:$lhs, (Log2HI PowerOf2HI:$mask), bb:$dst)>, ASE_MIPS64_CNMIPS; // Atomic load patterns. def : MipsPat<(atomic_load_8 addr:$a), (LB64 addr:$a)>; @@ -566,39 +630,40 @@ def : MipsPat<(atomic_store_64 addr:$a, GPR64:$v), (SD GPR64:$v, addr:$a)>; //===----------------------------------------------------------------------===// // Instruction aliases //===----------------------------------------------------------------------===// -def : MipsInstAlias<"move $dst, $src", - (OR64 GPR64Opnd:$dst, GPR64Opnd:$src, ZERO_64), 1>, - GPR_64; -def : MipsInstAlias<"move $dst, $src", - (DADDu GPR64Opnd:$dst, GPR64Opnd:$src, ZERO_64), 1>, - GPR_64; -def : MipsInstAlias<"daddu $rs, $rt, $imm", - (DADDiu GPR64Opnd:$rs, GPR64Opnd:$rt, simm16_64:$imm), - 0>, ISA_MIPS3; -def : MipsInstAlias<"dadd $rs, $rt, $imm", - (DADDi GPR64Opnd:$rs, GPR64Opnd:$rt, simm16_64:$imm), - 0>, ISA_MIPS3_NOT_32R6_64R6; -def : MipsInstAlias<"daddu $rs, $imm", - (DADDiu GPR64Opnd:$rs, GPR64Opnd:$rs, simm16_64:$imm), - 0>, ISA_MIPS3; -def : MipsInstAlias<"dadd $rs, $imm", - (DADDi GPR64Opnd:$rs, GPR64Opnd:$rs, simm16_64:$imm), - 0>, ISA_MIPS3_NOT_32R6_64R6; +let AdditionalPredicates = [NotInMicroMips] in { + def : MipsInstAlias<"move $dst, $src", + (OR64 GPR64Opnd:$dst, GPR64Opnd:$src, ZERO_64), 1>, + GPR_64; + def : MipsInstAlias<"move $dst, $src", + (DADDu GPR64Opnd:$dst, GPR64Opnd:$src, ZERO_64), 1>, + GPR_64; + def : MipsInstAlias<"dadd $rs, $rt, $imm", + (DADDi GPR64Opnd:$rs, GPR64Opnd:$rt, simm16_64:$imm), + 0>, ISA_MIPS3_NOT_32R6_64R6; + def : MipsInstAlias<"dadd $rs, $imm", + (DADDi GPR64Opnd:$rs, GPR64Opnd:$rs, simm16_64:$imm), + 0>, ISA_MIPS3_NOT_32R6_64R6; + def : MipsInstAlias<"daddu $rs, $rt, $imm", + (DADDiu GPR64Opnd:$rs, GPR64Opnd:$rt, simm16_64:$imm), + 0>, ISA_MIPS3; + def : MipsInstAlias<"daddu $rs, $imm", + (DADDiu GPR64Opnd:$rs, GPR64Opnd:$rs, simm16_64:$imm), + 0>, ISA_MIPS3; +} 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; +let AdditionalPredicates = [NotInMicroMips] in { + 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<"dsubi $rs, $rt, $imm", (DADDi GPR64Opnd:$rs, GPR64Opnd:$rt, InvertedImOperand64:$imm), @@ -615,29 +680,35 @@ def : MipsInstAlias<"dsub $rs, $imm", (DADDi GPR64Opnd:$rs, GPR64Opnd:$rs, InvertedImOperand64:$imm), 0>, ISA_MIPS3_NOT_32R6_64R6; -def : MipsInstAlias<"dsubu $rs, $imm", - (DADDiu GPR64Opnd:$rs, GPR64Opnd:$rs, - InvertedImOperand64:$imm), - 0>, ISA_MIPS3; +let AdditionalPredicates = [NotInMicroMips] in { + def : MipsInstAlias<"dsubu $rt, $rs, $imm", + (DADDiu GPR64Opnd:$rt, GPR64Opnd:$rs, + InvertedImOperand64:$imm), 0>, ISA_MIPS3; + def : MipsInstAlias<"dsubu $rs, $imm", + (DADDiu GPR64Opnd:$rs, GPR64Opnd:$rs, + InvertedImOperand64:$imm), 0>, ISA_MIPS3; +} def : MipsInstAlias<"dsra $rd, $rt, $rs", (DSRAV GPR64Opnd:$rd, GPR64Opnd:$rt, GPR32Opnd:$rs), 0>, ISA_MIPS3; -def : MipsInstAlias<"dsrl $rd, $rt, $rs", - (DSRLV GPR64Opnd:$rd, GPR64Opnd:$rt, GPR32Opnd:$rs), 0>, - ISA_MIPS3; +let AdditionalPredicates = [NotInMicroMips] in { + def : MipsInstAlias<"dsrl $rd, $rt, $rs", + (DSRLV GPR64Opnd:$rd, GPR64Opnd:$rt, GPR32Opnd:$rs), 0>, + ISA_MIPS3; // Two operand (implicit 0 selector) versions: -def : MipsInstAlias<"dmfc0 $rt, $rd", (DMFC0 GPR64Opnd:$rt, COP0Opnd:$rd, 0), 0>; -def : MipsInstAlias<"dmtc0 $rt, $rd", (DMTC0 COP0Opnd:$rd, GPR64Opnd:$rt, 0), 0>; + def : MipsInstAlias<"dmtc0 $rt, $rd", + (DMTC0 COP0Opnd:$rd, GPR64Opnd:$rt, 0), 0>; + def : MipsInstAlias<"dmfc0 $rt, $rd", + (DMFC0 GPR64Opnd:$rt, COP0Opnd:$rd, 0), 0>; +} def : MipsInstAlias<"dmfc2 $rt, $rd", (DMFC2 GPR64Opnd:$rt, COP2Opnd:$rd, 0), 0>; def : MipsInstAlias<"dmtc2 $rt, $rd", (DMTC2 COP2Opnd:$rd, GPR64Opnd:$rt, 0), 0>; -let Predicates = [HasMips64, HasCnMips] in { -def : MipsInstAlias<"synciobdma", (SYNC 0x2), 0>; -def : MipsInstAlias<"syncs", (SYNC 0x6), 0>; -def : MipsInstAlias<"syncw", (SYNC 0x4), 0>; -def : MipsInstAlias<"syncws", (SYNC 0x5), 0>; -} +def : MipsInstAlias<"synciobdma", (SYNC 0x2), 0>, ASE_MIPS64_CNMIPS; +def : MipsInstAlias<"syncs", (SYNC 0x6), 0>, ASE_MIPS64_CNMIPS; +def : MipsInstAlias<"syncw", (SYNC 0x4), 0>, ASE_MIPS64_CNMIPS; +def : MipsInstAlias<"syncws", (SYNC 0x5), 0>, ASE_MIPS64_CNMIPS; // cnMIPS Aliases. diff --git a/lib/Target/Mips/Mips64r6InstrInfo.td b/lib/Target/Mips/Mips64r6InstrInfo.td index 6f34dbe28d305..64effbef8a6a4 100644 --- a/lib/Target/Mips/Mips64r6InstrInfo.td +++ b/lib/Target/Mips/Mips64r6InstrInfo.td @@ -46,35 +46,50 @@ class SCD_R6_ENC : SPECIAL3_LL_SC_FM<OPCODE6_SCD>; // //===----------------------------------------------------------------------===// -class AHI_ATI_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> { +class AHI_ATI_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, InstrItinClass itin> { dag OutOperandList = (outs GPROpnd:$rs); - dag InOperandList = (ins GPROpnd:$rt, simm16:$imm); + dag InOperandList = (ins GPROpnd:$rt, simm16_relaxed:$imm); string AsmString = !strconcat(instr_asm, "\t$rt, $imm"); string Constraints = "$rs = $rt"; + InstrItinClass Itinerary = itin; } -class DALIGN_DESC : ALIGN_DESC_BASE<"dalign", GPR64Opnd, uimm3>; -class DAHI_DESC : AHI_ATI_DESC_BASE<"dahi", GPR64Opnd>; -class DATI_DESC : AHI_ATI_DESC_BASE<"dati", GPR64Opnd>; -class DAUI_DESC : AUI_DESC_BASE<"daui", GPR64Opnd>; -class DBITSWAP_DESC : BITSWAP_DESC_BASE<"dbitswap", GPR64Opnd>; -class DCLO_R6_DESC : CLO_R6_DESC_BASE<"dclo", GPR64Opnd>; -class DCLZ_R6_DESC : CLZ_R6_DESC_BASE<"dclz", GPR64Opnd>; -class DDIV_DESC : DIVMOD_DESC_BASE<"ddiv", GPR64Opnd, sdiv>; -class DDIVU_DESC : DIVMOD_DESC_BASE<"ddivu", GPR64Opnd, udiv>; -class DLSA_R6_DESC : LSA_R6_DESC_BASE<"dlsa", GPR64Opnd, uimm2_plus1>; -class DMOD_DESC : DIVMOD_DESC_BASE<"dmod", GPR64Opnd, srem>; -class DMODU_DESC : DIVMOD_DESC_BASE<"dmodu", GPR64Opnd, urem>; -class DMUH_DESC : MUL_R6_DESC_BASE<"dmuh", GPR64Opnd, mulhs>; -class DMUHU_DESC : MUL_R6_DESC_BASE<"dmuhu", GPR64Opnd, mulhu>; -class DMUL_R6_DESC : MUL_R6_DESC_BASE<"dmul", GPR64Opnd, mul>; -class DMULU_DESC : MUL_R6_DESC_BASE<"dmulu", GPR64Opnd>; -class LDPC_DESC : PCREL_DESC_BASE<"ldpc", GPR64Opnd, simm18_lsl3>; -class LLD_R6_DESC : LL_R6_DESC_BASE<"lld", GPR64Opnd>; -class SCD_R6_DESC : SC_R6_DESC_BASE<"scd", GPR64Opnd>; +class DALIGN_DESC : ALIGN_DESC_BASE<"dalign", GPR64Opnd, uimm3, II_DALIGN>; +class DAHI_DESC : AHI_ATI_DESC_BASE<"dahi", GPR64Opnd, II_DAHI>; +class DATI_DESC : AHI_ATI_DESC_BASE<"dati", GPR64Opnd, II_DATI>; +class DAUI_DESC : AUI_DESC_BASE<"daui", GPR64Opnd, II_DAUI>; +class DBITSWAP_DESC : BITSWAP_DESC_BASE<"dbitswap", GPR64Opnd, II_DBITSWAP>; +class DCLO_R6_DESC : CLO_R6_DESC_BASE<"dclo", GPR64Opnd, II_DCLO>; +class DCLZ_R6_DESC : CLZ_R6_DESC_BASE<"dclz", GPR64Opnd, II_DCLZ>; +class DDIV_DESC : DIVMOD_DESC_BASE<"ddiv", GPR64Opnd, II_DDIV, sdiv>; +class DDIVU_DESC : DIVMOD_DESC_BASE<"ddivu", GPR64Opnd, II_DDIVU, udiv>; +class DLSA_R6_DESC : LSA_R6_DESC_BASE<"dlsa", GPR64Opnd, uimm2_plus1, II_DLSA>; +class DMOD_DESC : DIVMOD_DESC_BASE<"dmod", GPR64Opnd, II_DMOD, srem>; +class DMODU_DESC : DIVMOD_DESC_BASE<"dmodu", GPR64Opnd, II_DMODU, urem>; +class DMUH_DESC : MUL_R6_DESC_BASE<"dmuh", GPR64Opnd, II_DMUH, mulhs>; +class DMUHU_DESC : MUL_R6_DESC_BASE<"dmuhu", GPR64Opnd, II_DMUHU, mulhu>; +class DMUL_R6_DESC : MUL_R6_DESC_BASE<"dmul", GPR64Opnd, II_DMUL, mul>; +class DMULU_DESC : MUL_R6_DESC_BASE<"dmulu", GPR64Opnd, II_DMUL>; +class LDPC_DESC : PCREL_DESC_BASE<"ldpc", GPR64Opnd, simm18_lsl3, II_LDPC>; +class LLD_R6_DESC : LL_R6_DESC_BASE<"lld", GPR64Opnd, mem_simm16, II_LLD>; +class SCD_R6_DESC : SC_R6_DESC_BASE<"scd", GPR64Opnd, II_SCD>; class SELEQZ64_DESC : SELEQNE_Z_DESC_BASE<"seleqz", GPR64Opnd>; class SELNEZ64_DESC : SELEQNE_Z_DESC_BASE<"selnez", GPR64Opnd>; +class JIALC64_DESC : JMP_IDX_COMPACT_DESC_BASE<"jialc", calloffset16, + GPR64Opnd> { + bit isCall = 1; + list<Register> Defs = [RA]; +} + +class JIC64_DESC : JMP_IDX_COMPACT_DESC_BASE<"jic", jmpoffset16, GPR64Opnd> { + bit isBarrier = 1; + bit isTerminator = 1; + list<Register> Defs = [AT]; +} + +class LL64_R6_DESC : LL_R6_DESC_BASE<"ll", GPR32Opnd, mem_simm9, II_LL>; +class SC64_R6_DESC : SC_R6_DESC_BASE<"sc", GPR32Opnd, II_SC>; //===----------------------------------------------------------------------===// // // Instruction Definitions @@ -88,25 +103,37 @@ let AdditionalPredicates = [NotInMicroMips] in { def DALIGN : DALIGN_ENC, DALIGN_DESC, ISA_MIPS64R6; } def DBITSWAP : DBITSWAP_ENC, DBITSWAP_DESC, ISA_MIPS64R6; -def DCLO_R6 : DCLO_R6_ENC, DCLO_R6_DESC, ISA_MIPS64R6; -def DCLZ_R6 : DCLZ_R6_ENC, DCLZ_R6_DESC, ISA_MIPS64R6; -def DDIV : DDIV_ENC, DDIV_DESC, ISA_MIPS64R6; -def DDIVU : DDIVU_ENC, DDIVU_DESC, ISA_MIPS64R6; +let AdditionalPredicates = [NotInMicroMips] in { + def DCLO_R6 : R6MMR6Rel, DCLO_R6_ENC, DCLO_R6_DESC, ISA_MIPS64R6; + def DCLZ_R6 : R6MMR6Rel, DCLZ_R6_ENC, DCLZ_R6_DESC, ISA_MIPS64R6; + def DDIV : DDIV_ENC, DDIV_DESC, ISA_MIPS64R6; + def DDIVU : DDIVU_ENC, DDIVU_DESC, ISA_MIPS64R6; + def DMOD : DMOD_ENC, DMOD_DESC, ISA_MIPS64R6; + def DMODU : DMODU_ENC, DMODU_DESC, ISA_MIPS64R6; +} def DLSA_R6 : DLSA_R6_ENC, DLSA_R6_DESC, ISA_MIPS64R6; -def DMOD : DMOD_ENC, DMOD_DESC, ISA_MIPS64R6; -def DMODU : DMODU_ENC, DMODU_DESC, ISA_MIPS64R6; -def DMUH: DMUH_ENC, DMUH_DESC, ISA_MIPS64R6; -def DMUHU: DMUHU_ENC, DMUHU_DESC, ISA_MIPS64R6; -def DMUL_R6: DMUL_R6_ENC, DMUL_R6_DESC, ISA_MIPS64R6; -def DMULU: DMULU_ENC, DMULU_DESC, ISA_MIPS64R6; -def LDPC: LDPC_ENC, LDPC_DESC, ISA_MIPS64R6; -def LLD_R6 : LLD_R6_ENC, LLD_R6_DESC, ISA_MIPS32R6; +let AdditionalPredicates = [NotInMicroMips] in { + def DMUH: DMUH_ENC, DMUH_DESC, ISA_MIPS64R6; + def DMUHU: DMUHU_ENC, DMUHU_DESC, ISA_MIPS64R6; + def DMUL_R6: DMUL_R6_ENC, DMUL_R6_DESC, ISA_MIPS64R6; + def DMULU: DMULU_ENC, DMULU_DESC, ISA_MIPS64R6; + def LLD_R6 : R6MMR6Rel, LLD_R6_ENC, LLD_R6_DESC, ISA_MIPS64R6; +} +def LDPC: R6MMR6Rel, LDPC_ENC, LDPC_DESC, ISA_MIPS64R6; def SCD_R6 : SCD_R6_ENC, SCD_R6_DESC, ISA_MIPS32R6; let DecoderNamespace = "Mips32r6_64r6_GP64" in { def SELEQZ64 : SELEQZ_ENC, SELEQZ64_DESC, ISA_MIPS32R6, GPR_64; def SELNEZ64 : SELNEZ_ENC, SELNEZ64_DESC, ISA_MIPS32R6, GPR_64; } - +let AdditionalPredicates = [NotInMicroMips], + DecoderNamespace = "Mips32r6_64r6_PTR64" in { + def LL64_R6 : LL_R6_ENC, LL64_R6_DESC, PTR_64, ISA_MIPS64R6; + def SC64_R6 : SC_R6_ENC, SC64_R6_DESC, PTR_64, ISA_MIPS64R6; +} +let isCodeGenOnly = 1 in { +def JIALC64 : JIALC_ENC, JIALC64_DESC, ISA_MIPS64R6; +def JIC64 : JIC_ENC, JIC64_DESC, ISA_MIPS64R6; +} //===----------------------------------------------------------------------===// // // Instruction Aliases @@ -115,6 +142,9 @@ let DecoderNamespace = "Mips32r6_64r6_GP64" in { def : MipsInstAlias<"jr $rs", (JALR64 ZERO_64, GPR64Opnd:$rs), 1>, ISA_MIPS64R6; +def : MipsInstAlias<"jrc $rs", (JIC64 GPR64Opnd:$rs, 0), 1>, ISA_MIPS64R6; + +def : MipsInstAlias<"jalrc $rs", (JIALC64 GPR64Opnd:$rs, 0), 1>, ISA_MIPS64R6; //===----------------------------------------------------------------------===// // // Patterns and Pseudo Instructions diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp index 957529376b372..3686c2fe3ec45 100644 --- a/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/lib/Target/Mips/MipsAsmPrinter.cpp @@ -313,7 +313,6 @@ const char *MipsAsmPrinter::getCurrentABIString() const { case MipsABIInfo::ABI::O32: return "abi32"; case MipsABIInfo::ABI::N32: return "abiN32"; case MipsABIInfo::ABI::N64: return "abi64"; - case MipsABIInfo::ABI::EABI: return "eabi32"; // TODO: handle eabi64 default: llvm_unreachable("Unknown Mips ABI"); } } @@ -326,9 +325,10 @@ void MipsAsmPrinter::EmitFunctionEntryLabel() { if (Subtarget->isTargetNaCl()) EmitAlignment(std::max(MF->getAlignment(), MIPS_NACL_BUNDLE_ALIGN)); - if (Subtarget->inMicroMipsMode()) + if (Subtarget->inMicroMipsMode()) { TS.emitDirectiveSetMicroMips(); - else + TS.setUsesMicroMips(); + } else TS.emitDirectiveSetNoMicroMips(); if (Subtarget->inMips16Mode()) @@ -620,24 +620,6 @@ void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum, if (closeP) O << ")"; } -void MipsAsmPrinter::printUnsignedImm(const MachineInstr *MI, int opNum, - raw_ostream &O) { - const MachineOperand &MO = MI->getOperand(opNum); - if (MO.isImm()) - O << (unsigned short int)MO.getImm(); - else - printOperand(MI, opNum, O); -} - -void MipsAsmPrinter::printUnsignedImm8(const MachineInstr *MI, int opNum, - raw_ostream &O) { - const MachineOperand &MO = MI->getOperand(opNum); - if (MO.isImm()) - O << (unsigned short int)(unsigned char)MO.getImm(); - else - printOperand(MI, opNum, O); -} - void MipsAsmPrinter:: printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O) { // Load/Store memory operands -- imm($reg) @@ -687,6 +669,12 @@ printRegisterList(const MachineInstr *MI, int opNum, raw_ostream &O) { } void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { + MipsTargetStreamer &TS = getTargetStreamer(); + + // MipsTargetStreamer has an initialization order problem when emitting an + // object file directly (see MipsTargetELFStreamer for full details). Work + // around it by re-initializing the PIC state here. + TS.setPic(OutContext.getObjectFileInfo()->isPositionIndependent()); // Compute MIPS architecture attributes based on the default subtarget // that we'd have constructed. Module level directives aren't LTO @@ -702,14 +690,13 @@ void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { bool IsABICalls = STI.isABICalls(); const MipsABIInfo &ABI = MTM.getABI(); if (IsABICalls) { - getTargetStreamer().emitDirectiveAbiCalls(); - Reloc::Model RM = TM.getRelocationModel(); + TS.emitDirectiveAbiCalls(); // FIXME: This condition should be a lot more complicated that it is here. // 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 && !ABI.IsN64()) - getTargetStreamer().emitDirectiveOptionPic0(); + if (!isPositionIndependent() && !ABI.IsN64()) + TS.emitDirectiveOptionPic0(); } // Tell the assembler which ABI we are using @@ -720,33 +707,24 @@ void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) { // NaN: At the moment we only support: // 1. .nan legacy (default) // 2. .nan 2008 - STI.isNaN2008() ? getTargetStreamer().emitDirectiveNaN2008() - : getTargetStreamer().emitDirectiveNaNLegacy(); + STI.isNaN2008() ? TS.emitDirectiveNaN2008() + : TS.emitDirectiveNaNLegacy(); // TODO: handle O64 ABI - 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)); - } - - getTargetStreamer().updateABIInfo(STI); + TS.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 (ABI.IsO32() && (STI.isABI_FPXX() || STI.isFP64bit())) - getTargetStreamer().emitDirectiveModuleFP(); + TS.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 (ABI.IsO32() && (!STI.useOddSPReg() || STI.isABI_FPXX())) - getTargetStreamer().emitDirectiveModuleOddSPReg(); + TS.emitDirectiveModuleOddSPReg(); } void MipsAsmPrinter::emitInlineAsmStart() const { @@ -990,7 +968,7 @@ void MipsAsmPrinter::EmitFPCallStub( OutStreamer->EmitLabel(Stub); // Only handle non-pic for now. - assert(TM.getRelocationModel() != Reloc::PIC_ && + assert(!isPositionIndependent() && "should not be here if we are compiling pic"); TS.emitDirectiveSetReorder(); // @@ -1071,10 +1049,9 @@ void MipsAsmPrinter::NaClAlignIndirectJumpTargets(MachineFunction &MF) { } // If basic block address is taken, block can be target of indirect branch. - for (MachineFunction::iterator MBB = MF.begin(), E = MF.end(); - MBB != E; ++MBB) { - if (MBB->hasAddressTaken()) - MBB->setAlignment(MIPS_NACL_BUNDLE_ALIGN); + for (auto &MBB : MF) { + if (MBB.hasAddressTaken()) + MBB.setAlignment(MIPS_NACL_BUNDLE_ALIGN); } } diff --git a/lib/Target/Mips/MipsAsmPrinter.h b/lib/Target/Mips/MipsAsmPrinter.h index a7f3304a3da8a..f30141fc918f3 100644 --- a/lib/Target/Mips/MipsAsmPrinter.h +++ b/lib/Target/Mips/MipsAsmPrinter.h @@ -134,8 +134,6 @@ public: unsigned AsmVariant, const char *ExtraCode, raw_ostream &O) override; void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O); - void printUnsignedImm(const MachineInstr *MI, int opNum, raw_ostream &O); - void printUnsignedImm8(const MachineInstr *MI, int opNum, raw_ostream &O); void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O); void printMemOperandEA(const MachineInstr *MI, int opNum, raw_ostream &O); void printFCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O, diff --git a/lib/Target/Mips/MipsCCState.cpp b/lib/Target/Mips/MipsCCState.cpp index d82063e3d2a94..7af988c1f64d9 100644 --- a/lib/Target/Mips/MipsCCState.cpp +++ b/lib/Target/Mips/MipsCCState.cpp @@ -26,8 +26,8 @@ static bool isF128SoftLibCall(const char *CallSym) { "ceill", "copysignl", "cosl", "exp2l", "expl", "floorl", "fmal", "fmodl", "log10l", "log2l", "logl", "nearbyintl", - "powl", "rintl", "sinl", "sqrtl", - "truncl"}; + "powl", "rintl", "roundl", "sinl", + "sqrtl", "truncl"}; // Check that LibCalls is sorted alphabetically. auto Comp = [](const char *S1, const char *S2) { return strcmp(S1, S2) < 0; }; diff --git a/lib/Target/Mips/MipsCallingConv.td b/lib/Target/Mips/MipsCallingConv.td index 0b4b7785af670..a57cb7badc175 100644 --- a/lib/Target/Mips/MipsCallingConv.td +++ b/lib/Target/Mips/MipsCallingConv.td @@ -212,48 +212,6 @@ def RetCC_MipsN : CallingConv<[ ]>; //===----------------------------------------------------------------------===// -// Mips EABI Calling Convention -//===----------------------------------------------------------------------===// - -def CC_MipsEABI : CallingConv<[ - // Promote i8/i16 arguments to i32. - CCIfType<[i8, i16], CCPromoteToType<i32>>, - - // Integer arguments are passed in integer registers. - CCIfType<[i32], CCAssignToReg<[A0, A1, A2, A3, T0, T1, T2, T3]>>, - - // Single fp arguments are passed in pairs within 32-bit mode - CCIfType<[f32], CCIfSubtarget<"isSingleFloat()", - CCAssignToReg<[F12, F13, F14, F15, F16, F17, F18, F19]>>>, - - CCIfType<[f32], CCIfSubtargetNot<"isSingleFloat()", - CCAssignToReg<[F12, F14, F16, F18]>>>, - - // The first 4 double fp arguments are passed in single fp registers. - CCIfType<[f64], CCIfSubtargetNot<"isSingleFloat()", - CCAssignToReg<[D6, D7, D8, D9]>>>, - - // Integer values get stored in stack slots that are 4 bytes in - // size and 4-byte aligned. - CCIfType<[i32, f32], CCAssignToStack<4, 4>>, - - // Integer values get stored in stack slots that are 8 bytes in - // size and 8-byte aligned. - CCIfType<[f64], CCIfSubtargetNot<"isSingleFloat()", CCAssignToStack<8, 8>>> -]>; - -def RetCC_MipsEABI : CallingConv<[ - // i32 are returned in registers V0, V1 - CCIfType<[i32], CCAssignToReg<[V0, V1]>>, - - // f32 are returned in registers F0, F1 - CCIfType<[f32], CCAssignToReg<[F0, F1]>>, - - // f64 are returned in register D0 - CCIfType<[f64], CCIfSubtargetNot<"isSingleFloat()", CCAssignToReg<[D0]>>> -]>; - -//===----------------------------------------------------------------------===// // Mips FastCC Calling Convention //===----------------------------------------------------------------------===// def CC_MipsO32_FastCC : CallingConv<[ @@ -325,7 +283,6 @@ def CC_Mips_FastCC : CallingConv<[ // Stack parameter slots for i32 and f32 are 32-bit words and 4-byte aligned. CCIfType<[i32, f32], CCAssignToStack<4, 4>>, - CCIfSubtarget<"isABI_EABI()", CCDelegateTo<CC_MipsEABI>>, CCIfSubtarget<"isABI_O32()", CCDelegateTo<CC_MipsO32_FastCC>>, CCDelegateTo<CC_MipsN_FastCC> ]>; @@ -335,7 +292,6 @@ def CC_Mips_FastCC : CallingConv<[ //===----------------------------------------------------------------------===// def RetCC_Mips : CallingConv<[ - CCIfSubtarget<"isABI_EABI()", CCDelegateTo<RetCC_MipsEABI>>, CCIfSubtarget<"isABI_N32()", CCDelegateTo<RetCC_MipsN>>, CCIfSubtarget<"isABI_N64()", CCDelegateTo<RetCC_MipsN>>, CCDelegateTo<RetCC_MipsO32> @@ -377,8 +333,6 @@ def CC_Mips_FixedArg : CallingConv<[ CCIfCC<"CallingConv::Fast", CCDelegateTo<CC_Mips_FastCC>>, - // FIXME: There wasn't an EABI case in the original code and it seems unlikely - // that it's the same as CC_MipsN CCIfSubtarget<"isABI_O32()", CCDelegateTo<CC_MipsO32_FP>>, CCDelegateTo<CC_MipsN> ]>; @@ -386,8 +340,6 @@ def CC_Mips_FixedArg : CallingConv<[ def CC_Mips_VarArg : CallingConv<[ CCIfByVal<CCDelegateTo<CC_Mips_ByVal>>, - // FIXME: There wasn't an EABI case in the original code and it seems unlikely - // that it's the same as CC_MipsN_VarArg CCIfSubtarget<"isABI_O32()", CCDelegateTo<CC_MipsO32_FP>>, CCDelegateTo<CC_MipsN_VarArg> ]>; diff --git a/lib/Target/Mips/MipsCondMov.td b/lib/Target/Mips/MipsCondMov.td index 2d96d9b48c0b0..fd4517f253359 100644 --- a/lib/Target/Mips/MipsCondMov.td +++ b/lib/Target/Mips/MipsCondMov.td @@ -133,16 +133,14 @@ def MOVZ_I_S : MMRel, CMov_I_F_FT<"movz.s", GPR32Opnd, FGR32Opnd, II_MOVZ_S>, let isCodeGenOnly = 1 in def MOVZ_I64_S : CMov_I_F_FT<"movz.s", GPR64Opnd, FGR32Opnd, II_MOVZ_S>, - CMov_I_F_FM<18, 16>, INSN_MIPS4_32_NOT_32R6_64R6, - AdditionalRequires<[HasMips64]>; + CMov_I_F_FM<18, 16>, INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; def MOVN_I_S : MMRel, CMov_I_F_FT<"movn.s", GPR32Opnd, FGR32Opnd, II_MOVN_S>, CMov_I_F_FM<19, 16>, INSN_MIPS4_32_NOT_32R6_64R6; let isCodeGenOnly = 1 in def MOVN_I64_S : CMov_I_F_FT<"movn.s", GPR64Opnd, FGR32Opnd, II_MOVN_S>, - CMov_I_F_FM<19, 16>, INSN_MIPS4_32_NOT_32R6_64R6, - AdditionalRequires<[IsGP64bit]>; + CMov_I_F_FM<19, 16>, INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; def MOVZ_I_D32 : MMRel, CMov_I_F_FT<"movz.d", GPR32Opnd, AFGR64Opnd, II_MOVZ_D>, CMov_I_F_FM<18, 17>, @@ -169,16 +167,14 @@ def MOVT_I : MMRel, CMov_F_I_FT<"movt", GPR32Opnd, II_MOVT, MipsCMovFP_T>, let isCodeGenOnly = 1 in def MOVT_I64 : CMov_F_I_FT<"movt", GPR64Opnd, II_MOVT, MipsCMovFP_T>, - CMov_F_I_FM<1>, INSN_MIPS4_32_NOT_32R6_64R6, - AdditionalRequires<[IsGP64bit]>; + CMov_F_I_FM<1>, INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; def MOVF_I : MMRel, CMov_F_I_FT<"movf", GPR32Opnd, II_MOVF, MipsCMovFP_F>, CMov_F_I_FM<0>, INSN_MIPS4_32_NOT_32R6_64R6; let isCodeGenOnly = 1 in def MOVF_I64 : CMov_F_I_FT<"movf", GPR64Opnd, II_MOVF, MipsCMovFP_F>, - CMov_F_I_FM<0>, INSN_MIPS4_32_NOT_32R6_64R6, - AdditionalRequires<[IsGP64bit]>; + CMov_F_I_FM<0>, INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; def MOVT_S : MMRel, CMov_F_F_FT<"movt.s", FGR32Opnd, II_MOVT_S, MipsCMovFP_T>, CMov_F_F_FM<16, 1>, INSN_MIPS4_32_NOT_32R6_64R6; diff --git a/lib/Target/Mips/MipsConstantIslandPass.cpp b/lib/Target/Mips/MipsConstantIslandPass.cpp index ea8c5871fa0ec..1ea48e0439d4d 100644 --- a/lib/Target/Mips/MipsConstantIslandPass.cpp +++ b/lib/Target/Mips/MipsConstantIslandPass.cpp @@ -97,16 +97,6 @@ static unsigned int branchTargetOperand(MachineInstr *MI) { llvm_unreachable("Unknown branch type"); } -static bool isUnconditionalBranch(unsigned int Opcode) { - switch (Opcode) { - default: return false; - case Mips::Bimm16: - case Mips::BimmX16: - case Mips::JalB16: - return true; - } -} - static unsigned int longformBranchOpcode(unsigned int Opcode) { switch (Opcode) { case Mips::Bimm16: @@ -342,8 +332,6 @@ namespace { /// the branch fix up pass. bool HasFarJump; - const TargetMachine &TM; - bool IsPIC; const MipsSubtarget *STI; const Mips16InstrInfo *TII; MipsFunctionInfo *MFI; @@ -364,10 +352,9 @@ namespace { public: static char ID; - MipsConstantIslands(TargetMachine &tm) - : MachineFunctionPass(ID), TM(tm), - IsPIC(TM.getRelocationModel() == Reloc::PIC_), STI(nullptr), - MF(nullptr), MCP(nullptr), PrescannedForConstants(false) {} + MipsConstantIslands() + : MachineFunctionPass(ID), STI(nullptr), MF(nullptr), MCP(nullptr), + PrescannedForConstants(false) {} const char *getPassName() const override { return "Mips Constant Islands"; @@ -375,9 +362,14 @@ namespace { bool runOnMachineFunction(MachineFunction &F) override; + MachineFunctionProperties getRequiredProperties() const override { + return MachineFunctionProperties().set( + MachineFunctionProperties::Property::AllVRegsAllocated); + } + void doInitialPlacement(std::vector<MachineInstr*> &CPEMIs); CPEntry *findConstPoolEntry(unsigned CPI, const MachineInstr *CPEMI); - unsigned getCPELogAlign(const MachineInstr *CPEMI); + unsigned getCPELogAlign(const MachineInstr &CPEMI); void initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs); unsigned getOffsetOf(MachineInstr *MI) const; unsigned getUserOffset(CPUser&) const; @@ -389,7 +381,7 @@ namespace { const CPUser &U); void computeBlockSize(MachineBasicBlock *MBB); - MachineBasicBlock *splitBlockBeforeInstr(MachineInstr *MI); + MachineBasicBlock *splitBlockBeforeInstr(MachineInstr &MI); void updateForInsertedWaterBlock(MachineBasicBlock *NewBB); void adjustBBOffsetsAfter(MachineBasicBlock *BB); bool decrementCPEReferenceCount(unsigned CPI, MachineInstr* CPEMI); @@ -437,10 +429,9 @@ void MipsConstantIslands::dumpBBs() { } }); } -/// createMipsLongBranchPass - Returns a pass that converts branches to long -/// branches. -FunctionPass *llvm::createMipsConstantIslandPass(MipsTargetMachine &tm) { - return new MipsConstantIslands(tm); +/// Returns a pass that converts branches to long branches. +FunctionPass *llvm::createMipsConstantIslandPass() { + return new MipsConstantIslands(); } bool MipsConstantIslands::runOnMachineFunction(MachineFunction &mf) { @@ -629,14 +620,14 @@ MipsConstantIslands::CPEntry /// getCPELogAlign - Returns the required alignment of the constant pool entry /// represented by CPEMI. Alignment is measured in log2(bytes) units. -unsigned MipsConstantIslands::getCPELogAlign(const MachineInstr *CPEMI) { - assert(CPEMI && CPEMI->getOpcode() == Mips::CONSTPOOL_ENTRY); +unsigned MipsConstantIslands::getCPELogAlign(const MachineInstr &CPEMI) { + assert(CPEMI.getOpcode() == Mips::CONSTPOOL_ENTRY); // Everything is 4-byte aligned unless AlignConstantIslands is set. if (!AlignConstantIslands) return 2; - unsigned CPI = CPEMI->getOperand(1).getIndex(); + unsigned CPI = CPEMI.getOperand(1).getIndex(); assert(CPI < MCP->getConstants().size() && "Invalid constant pool index."); unsigned Align = MCP->getConstants()[CPI].getAlignment(); assert(isPowerOf2_32(Align) && "Invalid CPE alignment"); @@ -663,21 +654,17 @@ initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) { adjustBBOffsetsAfter(&MF->front()); // Now go back through the instructions and build up our data structures. - for (MachineFunction::iterator MBBI = MF->begin(), E = MF->end(); - MBBI != E; ++MBBI) { - MachineBasicBlock &MBB = *MBBI; - + for (MachineBasicBlock &MBB : *MF) { // If this block doesn't fall through into the next MBB, then this is // 'water' that a constant pool island could be placed. if (!BBHasFallthrough(&MBB)) WaterList.push_back(&MBB); - for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end(); - I != E; ++I) { - if (I->isDebugValue()) + for (MachineInstr &MI : MBB) { + if (MI.isDebugValue()) continue; - int Opc = I->getOpcode(); - if (I->isBranch()) { + int Opc = MI.getOpcode(); + if (MI.isBranch()) { bool isCond = false; unsigned Bits = 0; unsigned Scale = 1; @@ -746,7 +733,7 @@ initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) { } // Record this immediate branch. unsigned MaxOffs = ((1 << (Bits-1))-1) * Scale; - ImmBranches.push_back(ImmBranch(I, MaxOffs, isCond, UOpc)); + ImmBranches.push_back(ImmBranch(&MI, MaxOffs, isCond, UOpc)); } if (Opc == Mips::CONSTPOOL_ENTRY) @@ -754,8 +741,8 @@ initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) { // Scan the instructions for constant pool operands. - for (unsigned op = 0, e = I->getNumOperands(); op != e; ++op) - if (I->getOperand(op).isCPI()) { + for (unsigned op = 0, e = MI.getNumOperands(); op != e; ++op) + if (MI.getOperand(op).isCPI()) { // We found one. The addressing mode tells us the max displacement // from the PC that this instruction permits. @@ -784,12 +771,12 @@ initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) { break; } // Remember that this is a user of a CP entry. - unsigned CPI = I->getOperand(op).getIndex(); + unsigned CPI = MI.getOperand(op).getIndex(); MachineInstr *CPEMI = CPEMIs[CPI]; unsigned MaxOffs = ((1 << Bits)-1) * Scale; unsigned LongFormMaxOffs = ((1 << LongFormBits)-1) * LongFormScale; - CPUsers.push_back(CPUser(I, CPEMI, MaxOffs, NegOk, - LongFormMaxOffs, LongFormOpcode)); + CPUsers.push_back(CPUser(&MI, CPEMI, MaxOffs, NegOk, LongFormMaxOffs, + LongFormOpcode)); // Increment corresponding CPEntry reference count. CPEntry *CPE = findConstPoolEntry(CPI, CPEMI); @@ -813,10 +800,8 @@ void MipsConstantIslands::computeBlockSize(MachineBasicBlock *MBB) { BasicBlockInfo &BBI = BBInfo[MBB->getNumber()]; BBI.Size = 0; - for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E; - ++I) - BBI.Size += TII->GetInstSizeInBytes(I); - + for (const MachineInstr &MI : *MBB) + BBI.Size += TII->GetInstSizeInBytes(MI); } /// getOffsetOf - Return the current offset of the specified machine instruction @@ -833,7 +818,7 @@ unsigned MipsConstantIslands::getOffsetOf(MachineInstr *MI) const { // Sum instructions before MI in MBB. for (MachineBasicBlock::iterator I = MBB->begin(); &*I != MI; ++I) { assert(I != MBB->end() && "Didn't find MI in its own basic block?"); - Offset += TII->GetInstSizeInBytes(I); + Offset += TII->GetInstSizeInBytes(*I); } return Offset; } @@ -872,9 +857,9 @@ unsigned MipsConstantIslands::getUserOffset(CPUser &U) const { /// Split the basic block containing MI into two blocks, which are joined by /// an unconditional branch. Update data structures and renumber blocks to /// account for this change and returns the newly created block. -MachineBasicBlock *MipsConstantIslands::splitBlockBeforeInstr - (MachineInstr *MI) { - MachineBasicBlock *OrigBB = MI->getParent(); +MachineBasicBlock * +MipsConstantIslands::splitBlockBeforeInstr(MachineInstr &MI) { + MachineBasicBlock *OrigBB = MI.getParent(); // Create a new MBB for the code after the OrigBB. MachineBasicBlock *NewBB = @@ -964,7 +949,7 @@ bool MipsConstantIslands::isOffsetInRange(unsigned UserOffset, bool MipsConstantIslands::isWaterInRange(unsigned UserOffset, MachineBasicBlock* Water, CPUser &U, unsigned &Growth) { - unsigned CPELogAlign = getCPELogAlign(U.CPEMI); + unsigned CPELogAlign = getCPELogAlign(*U.CPEMI); unsigned CPEOffset = BBInfo[Water->getNumber()].postOffset(CPELogAlign); unsigned NextBlockOffset, NextBlockAlignment; MachineFunction::const_iterator NextBlock = ++Water->getIterator(); @@ -985,7 +970,7 @@ bool MipsConstantIslands::isWaterInRange(unsigned UserOffset, Growth = CPEEnd - NextBlockOffset; // Compute the padding that would go at the end of the CPE to align the next // block. - Growth += OffsetToAlignment(CPEEnd, 1u << NextBlockAlignment); + Growth += OffsetToAlignment(CPEEnd, 1ULL << NextBlockAlignment); // If the CPE is to be inserted before the instruction, that will raise // the offset of the instruction. Also account for unknown alignment padding @@ -1246,7 +1231,7 @@ void MipsConstantIslands::createNewWater(unsigned CPUserIndex, CPUser &U = CPUsers[CPUserIndex]; MachineInstr *UserMI = U.MI; MachineInstr *CPEMI = U.CPEMI; - unsigned CPELogAlign = getCPELogAlign(CPEMI); + unsigned CPELogAlign = getCPELogAlign(*CPEMI); MachineBasicBlock *UserMBB = UserMI->getParent(); const BasicBlockInfo &UserBBI = BBInfo[UserMBB->getNumber()]; @@ -1312,11 +1297,12 @@ void MipsConstantIslands::createNewWater(unsigned CPUserIndex, unsigned CPUIndex = CPUserIndex+1; unsigned NumCPUsers = CPUsers.size(); //MachineInstr *LastIT = 0; - for (unsigned Offset = UserOffset+TII->GetInstSizeInBytes(UserMI); + for (unsigned Offset = UserOffset + TII->GetInstSizeInBytes(*UserMI); Offset < BaseInsertOffset; - Offset += TII->GetInstSizeInBytes(MI), MI = std::next(MI)) { + Offset += TII->GetInstSizeInBytes(*MI), MI = std::next(MI)) { assert(MI != UserMBB->end() && "Fell off end of block"); - if (CPUIndex < NumCPUsers && CPUsers[CPUIndex].MI == MI) { + if (CPUIndex < NumCPUsers && + CPUsers[CPUIndex].MI == static_cast<MachineInstr *>(MI)) { CPUser &U = CPUsers[CPUIndex]; if (!isOffsetInRange(Offset, EndInsertOffset, U)) { // Shift intertion point by one unit of alignment so it is within reach. @@ -1332,8 +1318,7 @@ void MipsConstantIslands::createNewWater(unsigned CPUserIndex, } } - --MI; - NewMBB = splitBlockBeforeInstr(MI); + NewMBB = splitBlockBeforeInstr(*--MI); } /// handleConstantPoolUser - Analyze the specified user, checking to see if it @@ -1426,7 +1411,7 @@ bool MipsConstantIslands::handleConstantPoolUser(unsigned CPUserIndex) { ++NumCPEs; // Mark the basic block as aligned as required by the const-pool entry. - NewIsland->setAlignment(getCPELogAlign(U.CPEMI)); + NewIsland->setAlignment(getCPELogAlign(*U.CPEMI)); // Increase the size of the island block to account for the new entry. BBInfo[NewIsland->getNumber()].Size += Size; @@ -1460,7 +1445,7 @@ void MipsConstantIslands::removeDeadCPEMI(MachineInstr *CPEMI) { CPEBB->setAlignment(0); } else // Entries are sorted by descending alignment, so realign from the front. - CPEBB->setAlignment(getCPELogAlign(CPEBB->begin())); + CPEBB->setAlignment(getCPELogAlign(*CPEBB->begin())); adjustBBOffsetsAfter(CPEBB); // An island has only one predecessor BB and one successor BB. Check if @@ -1610,7 +1595,7 @@ MipsConstantIslands::fixupConditionalBr(ImmBranch &Br) { ++NumCBrFixed; if (BMI != MI) { if (std::next(MachineBasicBlock::iterator(MI)) == std::prev(MBB->end()) && - isUnconditionalBranch(BMI->getOpcode())) { + BMI->isUnconditionalBranch()) { // Last MI in the BB is an unconditional branch. Can we simply invert the // condition and swap destinations: // beqz L1 @@ -1634,10 +1619,10 @@ MipsConstantIslands::fixupConditionalBr(ImmBranch &Br) { if (NeedSplit) { - splitBlockBeforeInstr(MI); + splitBlockBeforeInstr(*MI); // No need for the branch to the next block. We're adding an unconditional // branch to the destination. - int delta = TII->GetInstSizeInBytes(&MBB->back()); + int delta = TII->GetInstSizeInBytes(MBB->back()); BBInfo[MBB->getNumber()].Size -= delta; MBB->back().eraseFromParent(); // BBInfo[SplitBB].Offset is wrong temporarily, fixed below @@ -1659,14 +1644,14 @@ MipsConstantIslands::fixupConditionalBr(ImmBranch &Br) { .addMBB(NextBB); } Br.MI = &MBB->back(); - BBInfo[MBB->getNumber()].Size += TII->GetInstSizeInBytes(&MBB->back()); + BBInfo[MBB->getNumber()].Size += TII->GetInstSizeInBytes(MBB->back()); BuildMI(MBB, DebugLoc(), TII->get(Br.UncondBr)).addMBB(DestBB); - BBInfo[MBB->getNumber()].Size += TII->GetInstSizeInBytes(&MBB->back()); + BBInfo[MBB->getNumber()].Size += TII->GetInstSizeInBytes(MBB->back()); unsigned MaxDisp = getUnconditionalBrDisp(Br.UncondBr); ImmBranches.push_back(ImmBranch(&MBB->back(), MaxDisp, false, Br.UncondBr)); // Remove the old conditional branch. It may or may not still be in MBB. - BBInfo[MI->getParent()->getNumber()].Size -= TII->GetInstSizeInBytes(MI); + BBInfo[MI->getParent()->getNumber()].Size -= TII->GetInstSizeInBytes(*MI); MI->eraseFromParent(); adjustBBOffsetsAfter(MBB); return true; @@ -1710,4 +1695,3 @@ void MipsConstantIslands::prescanForConstants() { } } } - diff --git a/lib/Target/Mips/MipsDSPInstrFormats.td b/lib/Target/Mips/MipsDSPInstrFormats.td index f959bd4d8db3f..0ceb1858fb09e 100644 --- a/lib/Target/Mips/MipsDSPInstrFormats.td +++ b/lib/Target/Mips/MipsDSPInstrFormats.td @@ -32,6 +32,10 @@ class ISA_DSPR2 { list<Predicate> InsnPredicates = [HasDSPR2]; } +class ISA_DSPR3 { + list<Predicate> InsnPredicates = [HasDSPR3]; +} + // Fields. class Field6<bits<6> val> { bits<6> V = val; diff --git a/lib/Target/Mips/MipsDSPInstrInfo.td b/lib/Target/Mips/MipsDSPInstrInfo.td index da6f174e2a199..ac9a81b1bb2f7 100644 --- a/lib/Target/Mips/MipsDSPInstrInfo.td +++ b/lib/Target/Mips/MipsDSPInstrInfo.td @@ -16,7 +16,6 @@ def immZExt1 : ImmLeaf<i32, [{return isUInt<1>(Imm);}]>; def immZExt2 : ImmLeaf<i32, [{return isUInt<2>(Imm);}]>; def immZExt3 : ImmLeaf<i32, [{return isUInt<3>(Imm);}]>; def immZExt4 : ImmLeaf<i32, [{return isUInt<4>(Imm);}]>; -def immZExt7 : ImmLeaf<i32, [{return isUInt<7>(Imm);}]>; def immZExt8 : ImmLeaf<i32, [{return isUInt<8>(Imm);}]>; def immZExt10 : ImmLeaf<i32, [{return isUInt<10>(Imm);}]>; def immSExt6 : ImmLeaf<i32, [{return isInt<6>(Imm);}]>; @@ -287,6 +286,7 @@ class CMP_EQ_QB_R2_DESC_BASE<string instr_asm, SDPatternOperator OpNode, string AsmString = !strconcat(instr_asm, "\t$rs, $rt"); list<dag> Pattern = [(OpNode ROS:$rs, ROT:$rt)]; InstrItinClass Itinerary = itin; + string BaseOpcode = instr_asm; } class CMP_EQ_QB_R3_DESC_BASE<string instr_asm, SDPatternOperator OpNode, @@ -324,9 +324,10 @@ class ABSQ_S_PH_R2_DESC_BASE<string instr_asm, SDPatternOperator OpNode, } class REPL_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - ImmLeaf immPat, InstrItinClass itin, RegisterOperand RO> { + Operand ImmOp, ImmLeaf immPat, InstrItinClass itin, + RegisterOperand RO> { dag OutOperandList = (outs RO:$rd); - dag InOperandList = (ins uimm16:$imm); + dag InOperandList = (ins ImmOp:$imm); string AsmString = !strconcat(instr_asm, "\t$rd, $imm"); list<dag> Pattern = [(set RO:$rd, (OpNode immPat:$imm))]; InstrItinClass Itinerary = itin; @@ -401,7 +402,7 @@ class EXTR_W_TY1_R2_DESC_BASE<string instr_asm, SDPatternOperator OpNode, class EXTR_W_TY1_R1_DESC_BASE<string instr_asm, SDPatternOperator OpNode, InstrItinClass itin> { dag OutOperandList = (outs GPR32Opnd:$rt); - dag InOperandList = (ins ACC64DSPOpnd:$ac, uimm16:$shift_rs); + dag InOperandList = (ins ACC64DSPOpnd:$ac, uimm5:$shift_rs); string AsmString = !strconcat(instr_asm, "\t$rt, $ac, $shift_rs"); InstrItinClass Itinerary = itin; string BaseOpcode = instr_asm; @@ -440,7 +441,7 @@ class MTHLIP_DESC_BASE<string instr_asm, SDPatternOperator OpNode> { class RDDSP_DESC_BASE<string instr_asm, SDPatternOperator OpNode, InstrItinClass itin> { dag OutOperandList = (outs GPR32Opnd:$rd); - dag InOperandList = (ins uimm16:$mask); + dag InOperandList = (ins uimm10:$mask); string AsmString = !strconcat(instr_asm, "\t$rd, $mask"); list<dag> Pattern = [(set GPR32Opnd:$rd, (OpNode immZExt10:$mask))]; InstrItinClass Itinerary = itin; @@ -513,14 +514,16 @@ class BPOSGE32_PSEUDO_DESC_BASE<SDPatternOperator OpNode, InstrItinClass itin> : bit usesCustomInserter = 1; } -class BPOSGE32_DESC_BASE<string instr_asm, InstrItinClass itin> { +class BPOSGE32_DESC_BASE<string instr_asm, DAGOperand opnd, + InstrItinClass itin> { dag OutOperandList = (outs); - dag InOperandList = (ins brtarget:$offset); + dag InOperandList = (ins opnd:$offset); string AsmString = !strconcat(instr_asm, "\t$offset"); InstrItinClass Itinerary = itin; bit isBranch = 1; bit isTerminator = 1; bit hasDelaySlot = 1; + string BaseOpcode = instr_asm; } class INSV_DESC_BASE<string instr_asm, SDPatternOperator OpNode, @@ -845,11 +848,11 @@ class BITREV_DESC : ABSQ_S_PH_R2_DESC_BASE<"bitrev", int_mips_bitrev, class PACKRL_PH_DESC : CMP_EQ_QB_R3_DESC_BASE<"packrl.ph", int_mips_packrl_ph, NoItinerary, DSPROpnd, DSPROpnd>; -class REPL_QB_DESC : REPL_DESC_BASE<"repl.qb", int_mips_repl_qb, immZExt8, - NoItinerary, DSPROpnd>; +class REPL_QB_DESC : REPL_DESC_BASE<"repl.qb", int_mips_repl_qb, uimm8, + immZExt8, NoItinerary, DSPROpnd>; -class REPL_PH_DESC : REPL_DESC_BASE<"repl.ph", int_mips_repl_ph, immZExt10, - NoItinerary, DSPROpnd>; +class REPL_PH_DESC : REPL_DESC_BASE<"repl.ph", int_mips_repl_ph, uimm10, + immZExt10, NoItinerary, DSPROpnd>; class REPLV_QB_DESC : ABSQ_S_PH_R2_DESC_BASE<"replv.qb", int_mips_repl_qb, NoItinerary, DSPROpnd, GPR32Opnd>; @@ -871,7 +874,7 @@ class LHX_DESC : LX_DESC_BASE<"lhx", int_mips_lhx, NoItinerary>; class LBUX_DESC : LX_DESC_BASE<"lbux", int_mips_lbux, NoItinerary>; -class BPOSGE32_DESC : BPOSGE32_DESC_BASE<"bposge32", NoItinerary>; +class BPOSGE32_DESC : BPOSGE32_DESC_BASE<"bposge32", brtarget, NoItinerary>; // Extr class EXTP_DESC : EXTR_W_TY1_R1_DESC_BASE<"extp", MipsEXTP, NoItinerary>, @@ -1115,7 +1118,7 @@ def ADDQ_S_W : DspMMRel, ADDQ_S_W_ENC, ADDQ_S_W_DESC; def SUBQ_S_W : DspMMRel, SUBQ_S_W_ENC, SUBQ_S_W_DESC; def ADDSC : DspMMRel, ADDSC_ENC, ADDSC_DESC; def ADDWC : DspMMRel, ADDWC_ENC, ADDWC_DESC; -def MODSUB : MODSUB_ENC, MODSUB_DESC; +def MODSUB : DspMMRel, MODSUB_ENC, MODSUB_DESC; def RADDU_W_QB : DspMMRel, RADDU_W_QB_ENC, RADDU_W_QB_DESC; def ABSQ_S_PH : DspMMRel, ABSQ_S_PH_ENC, ABSQ_S_PH_DESC; def ABSQ_S_W : DspMMRel, ABSQ_S_W_ENC, ABSQ_S_W_DESC; @@ -1154,7 +1157,7 @@ def MULEU_S_PH_QBR : DspMMRel, MULEU_S_PH_QBR_ENC, MULEU_S_PH_QBR_DESC; def MULEQ_S_W_PHL : DspMMRel, MULEQ_S_W_PHL_ENC, MULEQ_S_W_PHL_DESC; def MULEQ_S_W_PHR : DspMMRel, MULEQ_S_W_PHR_ENC, MULEQ_S_W_PHR_DESC; def MULQ_RS_PH : DspMMRel, MULQ_RS_PH_ENC, MULQ_RS_PH_DESC; -def MULSAQ_S_W_PH : MULSAQ_S_W_PH_ENC, MULSAQ_S_W_PH_DESC; +def MULSAQ_S_W_PH : DspMMRel, MULSAQ_S_W_PH_ENC, MULSAQ_S_W_PH_DESC; def MAQ_S_W_PHL : DspMMRel, MAQ_S_W_PHL_ENC, MAQ_S_W_PHL_DESC; def MAQ_S_W_PHR : DspMMRel, MAQ_S_W_PHR_ENC, MAQ_S_W_PHR_DESC; def MAQ_SA_W_PHL : DspMMRel, MAQ_SA_W_PHL_ENC, MAQ_SA_W_PHL_DESC; @@ -1177,16 +1180,16 @@ def MADD_DSP : DspMMRel, MADD_DSP_ENC, MADD_DSP_DESC; def MADDU_DSP : DspMMRel, MADDU_DSP_ENC, MADDU_DSP_DESC; def MSUB_DSP : DspMMRel, MSUB_DSP_ENC, MSUB_DSP_DESC; def MSUBU_DSP : DspMMRel, MSUBU_DSP_ENC, MSUBU_DSP_DESC; -def CMPU_EQ_QB : CMPU_EQ_QB_ENC, CMPU_EQ_QB_DESC; -def CMPU_LT_QB : CMPU_LT_QB_ENC, CMPU_LT_QB_DESC; -def CMPU_LE_QB : CMPU_LE_QB_ENC, CMPU_LE_QB_DESC; -def CMPGU_EQ_QB : CMPGU_EQ_QB_ENC, CMPGU_EQ_QB_DESC; -def CMPGU_LT_QB : CMPGU_LT_QB_ENC, CMPGU_LT_QB_DESC; -def CMPGU_LE_QB : CMPGU_LE_QB_ENC, CMPGU_LE_QB_DESC; -def CMP_EQ_PH : CMP_EQ_PH_ENC, CMP_EQ_PH_DESC; -def CMP_LT_PH : CMP_LT_PH_ENC, CMP_LT_PH_DESC; -def CMP_LE_PH : CMP_LE_PH_ENC, CMP_LE_PH_DESC; -def BITREV : BITREV_ENC, BITREV_DESC; +def CMPU_EQ_QB : DspMMRel, CMPU_EQ_QB_ENC, CMPU_EQ_QB_DESC; +def CMPU_LT_QB : DspMMRel, CMPU_LT_QB_ENC, CMPU_LT_QB_DESC; +def CMPU_LE_QB : DspMMRel, CMPU_LE_QB_ENC, CMPU_LE_QB_DESC; +def CMPGU_EQ_QB : DspMMRel, CMPGU_EQ_QB_ENC, CMPGU_EQ_QB_DESC; +def CMPGU_LT_QB : DspMMRel, CMPGU_LT_QB_ENC, CMPGU_LT_QB_DESC; +def CMPGU_LE_QB : DspMMRel, CMPGU_LE_QB_ENC, CMPGU_LE_QB_DESC; +def CMP_EQ_PH : DspMMRel, CMP_EQ_PH_ENC, CMP_EQ_PH_DESC; +def CMP_LT_PH : DspMMRel, CMP_LT_PH_ENC, CMP_LT_PH_DESC; +def CMP_LE_PH : DspMMRel, CMP_LE_PH_ENC, CMP_LE_PH_DESC; +def BITREV : DspMMRel, BITREV_ENC, BITREV_DESC; def PACKRL_PH : DspMMRel, PACKRL_PH_ENC, PACKRL_PH_DESC; def REPL_QB : DspMMRel, REPL_QB_ENC, REPL_QB_DESC; def REPL_PH : DspMMRel, REPL_PH_ENC, REPL_PH_DESC; @@ -1197,7 +1200,9 @@ def PICK_PH : DspMMRel, PICK_PH_ENC, PICK_PH_DESC; def LWX : DspMMRel, LWX_ENC, LWX_DESC; def LHX : DspMMRel, LHX_ENC, LHX_DESC; def LBUX : DspMMRel, LBUX_ENC, LBUX_DESC; -def BPOSGE32 : BPOSGE32_ENC, BPOSGE32_DESC; +let AdditionalPredicates = [NotInMicroMips] in { + def BPOSGE32 : DspMMRel, BPOSGE32_ENC, BPOSGE32_DESC; +} def INSV : DspMMRel, INSV_ENC, INSV_DESC; def EXTP : DspMMRel, EXTP_ENC, EXTP_DESC; def EXTPV : DspMMRel, EXTPV_ENC, EXTPV_DESC; @@ -1224,9 +1229,9 @@ def ADDU_PH : DspMMRel, ADDU_PH_ENC, ADDU_PH_DESC, ISA_DSPR2; def ADDU_S_PH : DspMMRel, ADDU_S_PH_ENC, ADDU_S_PH_DESC, ISA_DSPR2; def SUBU_PH : DspMMRel, SUBU_PH_ENC, SUBU_PH_DESC, ISA_DSPR2; def SUBU_S_PH : DspMMRel, SUBU_S_PH_ENC, SUBU_S_PH_DESC, ISA_DSPR2; -def CMPGDU_EQ_QB : CMPGDU_EQ_QB_ENC, CMPGDU_EQ_QB_DESC, ISA_DSPR2; -def CMPGDU_LT_QB : CMPGDU_LT_QB_ENC, CMPGDU_LT_QB_DESC, ISA_DSPR2; -def CMPGDU_LE_QB : CMPGDU_LE_QB_ENC, CMPGDU_LE_QB_DESC, ISA_DSPR2; +def CMPGDU_EQ_QB : DspMMRel, CMPGDU_EQ_QB_ENC, CMPGDU_EQ_QB_DESC, ISA_DSPR2; +def CMPGDU_LT_QB : DspMMRel, CMPGDU_LT_QB_ENC, CMPGDU_LT_QB_DESC, ISA_DSPR2; +def CMPGDU_LE_QB : DspMMRel, CMPGDU_LE_QB_ENC, CMPGDU_LE_QB_DESC, ISA_DSPR2; def ABSQ_S_QB : DspMMRel, ABSQ_S_QB_ENC, ABSQ_S_QB_DESC, ISA_DSPR2; def ADDUH_QB : DspMMRel, ADDUH_QB_ENC, ADDUH_QB_DESC, ISA_DSPR2; def ADDUH_R_QB : DspMMRel, ADDUH_R_QB_ENC, ADDUH_R_QB_DESC, ISA_DSPR2; @@ -1253,7 +1258,7 @@ def DPAX_W_PH : DspMMRel, DPAX_W_PH_ENC, DPAX_W_PH_DESC, ISA_DSPR2; def DPSX_W_PH : DspMMRel, DPSX_W_PH_ENC, DPSX_W_PH_DESC, ISA_DSPR2; def DPSQX_S_W_PH : DspMMRel, DPSQX_S_W_PH_ENC, DPSQX_S_W_PH_DESC, ISA_DSPR2; def DPSQX_SA_W_PH : DspMMRel, DPSQX_SA_W_PH_ENC, DPSQX_SA_W_PH_DESC, ISA_DSPR2; -def MULSA_W_PH : MULSA_W_PH_ENC, MULSA_W_PH_DESC, ISA_DSPR2; +def MULSA_W_PH : DspMMRel, MULSA_W_PH_ENC, MULSA_W_PH_DESC, ISA_DSPR2; def PRECR_QB_PH : DspMMRel, PRECR_QB_PH_ENC, PRECR_QB_PH_DESC, ISA_DSPR2; def PRECR_SRA_PH_W : DspMMRel, PRECR_SRA_PH_W_ENC, PRECR_SRA_PH_W_DESC, ISA_DSPR2; def PRECR_SRA_R_PH_W : DspMMRel, PRECR_SRA_R_PH_W_ENC, PRECR_SRA_R_PH_W_DESC, ISA_DSPR2; @@ -1263,12 +1268,12 @@ def SHRA_R_QB : DspMMRel, SHRA_R_QB_ENC, SHRA_R_QB_DESC, ISA_DSPR2; def SHRAV_R_QB : DspMMRel, SHRAV_R_QB_ENC, SHRAV_R_QB_DESC, ISA_DSPR2; def SHRL_PH : DspMMRel, SHRL_PH_ENC, SHRL_PH_DESC, ISA_DSPR2; def SHRLV_PH : DspMMRel, SHRLV_PH_ENC, SHRLV_PH_DESC, ISA_DSPR2; -def APPEND : APPEND_ENC, APPEND_DESC, ISA_DSPR2; -def BALIGN : BALIGN_ENC, BALIGN_DESC, ISA_DSPR2; +def APPEND : DspMMRel, APPEND_ENC, APPEND_DESC, ISA_DSPR2; +def BALIGN : DspMMRel, BALIGN_ENC, BALIGN_DESC, ISA_DSPR2; def PREPEND : DspMMRel, PREPEND_ENC, PREPEND_DESC, ISA_DSPR2; // Pseudos. -let isPseudo = 1, isCodeGenOnly = 1 in { +let isPseudo = 1, isCodeGenOnly = 1, hasNoSchedulingInfo = 1 in { // Pseudo instructions for loading and storing accumulator registers. def LOAD_ACC64DSP : Load<"", ACC64DSPOpnd>; def STORE_ACC64DSP : Store<"", ACC64DSPOpnd>; diff --git a/lib/Target/Mips/MipsDelaySlotFiller.cpp b/lib/Target/Mips/MipsDelaySlotFiller.cpp index 8313d909df2a9..b5ba770df7bdc 100644 --- a/lib/Target/Mips/MipsDelaySlotFiller.cpp +++ b/lib/Target/Mips/MipsDelaySlotFiller.cpp @@ -62,6 +62,28 @@ static cl::opt<bool> DisableBackwardSearch( cl::desc("Disallow MIPS delay filler to search backward."), cl::Hidden); +enum CompactBranchPolicy { + CB_Never, ///< The policy 'never' may in some circumstances or for some + ///< ISAs not be absolutely adhered to. + CB_Optimal, ///< Optimal is the default and will produce compact branches + ///< when delay slots cannot be filled. + CB_Always ///< 'always' may in some circumstances may not be + ///< absolutely adhered to there may not be a corresponding + ///< compact form of a branch. +}; + +static cl::opt<CompactBranchPolicy> MipsCompactBranchPolicy( + "mips-compact-branches",cl::Optional, + cl::init(CB_Optimal), + cl::desc("MIPS Specific: Compact branch policy."), + cl::values( + clEnumValN(CB_Never, "never", "Do not use compact branches if possible."), + clEnumValN(CB_Optimal, "optimal", "Use compact branches where appropiate (default)."), + clEnumValN(CB_Always, "always", "Always use compact branches if possible."), + clEnumValEnd + ) +); + namespace { typedef MachineBasicBlock::iterator Iter; typedef MachineBasicBlock::reverse_iterator ReverseIter; @@ -189,6 +211,11 @@ namespace { return Changed; } + MachineFunctionProperties getRequiredProperties() const override { + return MachineFunctionProperties().set( + MachineFunctionProperties::Property::AllVRegsAllocated); + } + void getAnalysisUsage(AnalysisUsage &AU) const override { AU.addRequired<MachineBranchProbabilityInfo>(); MachineFunctionPass::getAnalysisUsage(AU); @@ -197,11 +224,8 @@ namespace { private: bool runOnMachineBasicBlock(MachineBasicBlock &MBB); - Iter replaceWithCompactBranch(MachineBasicBlock &MBB, - Iter Branch, DebugLoc DL); - - Iter replaceWithCompactJump(MachineBasicBlock &MBB, - Iter Jump, DebugLoc DL); + Iter replaceWithCompactBranch(MachineBasicBlock &MBB, Iter Branch, + const 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 @@ -505,46 +529,18 @@ getUnderlyingObjects(const MachineInstr &MI, } // Replace Branch with the compact branch instruction. -Iter Filler::replaceWithCompactBranch(MachineBasicBlock &MBB, - Iter Branch, DebugLoc DL) { - const MipsInstrInfo *TII = - MBB.getParent()->getSubtarget<MipsSubtarget>().getInstrInfo(); - - unsigned NewOpcode = - (((unsigned) Branch->getOpcode()) == Mips::BEQ) ? Mips::BEQZC_MM - : Mips::BNEZC_MM; - - const MCInstrDesc &NewDesc = TII->get(NewOpcode); - MachineInstrBuilder MIB = BuildMI(MBB, Branch, DL, NewDesc); - - MIB.addReg(Branch->getOperand(0).getReg()); - MIB.addMBB(Branch->getOperand(2).getMBB()); +Iter Filler::replaceWithCompactBranch(MachineBasicBlock &MBB, Iter Branch, + const DebugLoc &DL) { + const MipsSubtarget &STI = MBB.getParent()->getSubtarget<MipsSubtarget>(); + const MipsInstrInfo *TII = STI.getInstrInfo(); - Iter tmpIter = Branch; - Branch = std::prev(Branch); - MBB.erase(tmpIter); + unsigned NewOpcode = TII->getEquivalentCompactForm(Branch); + Branch = TII->genInstrWithNewOpc(NewOpcode, Branch); + std::next(Branch)->eraseFromParent(); 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) { @@ -572,6 +568,12 @@ bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) { bool InMicroMipsMode = STI.inMicroMipsMode(); const MipsInstrInfo *TII = STI.getInstrInfo(); + if (InMicroMipsMode && STI.hasMips32r6()) { + // This is microMIPS32r6 or microMIPS64r6 processor. Delay slot for + // branching instructions is not needed. + return Changed; + } + for (Iter I = MBB.begin(); I != MBB.end(); ++I) { if (!hasUnoccupiedSlot(&*I)) continue; @@ -583,55 +585,49 @@ bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) { if (!DisableDelaySlotFiller && (TM.getOptLevel() != CodeGenOpt::None)) { bool Filled = false; - if (searchBackward(MBB, I)) { - Filled = true; - } else if (I->isTerminator()) { - if (searchSuccBBs(MBB, I)) { + if (MipsCompactBranchPolicy.getValue() != CB_Always || + !TII->getEquivalentCompactForm(I)) { + if (searchBackward(MBB, I)) { + Filled = true; + } else if (I->isTerminator()) { + if (searchSuccBBs(MBB, I)) { + Filled = true; + } + } else if (searchForward(MBB, I)) { Filled = true; } - } else if (searchForward(MBB, I)) { - Filled = true; } if (Filled) { // Get instruction with delay slot. - MachineBasicBlock::instr_iterator DSI(I); + MachineBasicBlock::instr_iterator DSI = I.getInstrIterator(); - if (InMicroMipsMode && TII->GetInstSizeInBytes(&*std::next(DSI)) == 2 && + if (InMicroMipsMode && TII->GetInstSizeInBytes(*std::next(DSI)) == 2 && DSI->isCall()) { // If instruction in delay slot is 16b change opcode to // corresponding instruction with short delay slot. DSI->setDesc(TII->get(getEquivalentCallShort(DSI->getOpcode()))); } - continue; } } - // If instruction is BEQ or BNE with one ZERO register, then instead of - // adding NOP replace this instruction with the corresponding compact - // branch instruction, i.e. BEQZC or BNEZC. - unsigned Opcode = I->getOpcode(); - 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; - } + // For microMIPS if instruction is BEQ or BNE with one ZERO register, then + // instead of adding NOP replace this instruction with the corresponding + // compact branch instruction, i.e. BEQZC or BNEZC. Additionally + // PseudoReturn and PseudoIndirectBranch are expanded to JR_MM, so they can + // be replaced with JRC16_MM. + + // For MIPSR6 attempt to produce the corresponding compact (no delay slot) + // form of the CTI. For indirect jumps this will not require inserting a + // NOP and for branches will hopefully avoid requiring a NOP. + if ((InMicroMipsMode || + (STI.hasMips32r6() && MipsCompactBranchPolicy != CB_Never)) && + TII->getEquivalentCompactForm(I)) { + I = replaceWithCompactBranch(MBB, I, I->getDebugLoc()); + continue; } + // 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)); @@ -696,7 +692,7 @@ bool Filler::searchRange(MachineBasicBlock &MBB, IterTy Begin, IterTy End, bool InMicroMipsMode = STI.inMicroMipsMode(); const MipsInstrInfo *TII = STI.getInstrInfo(); unsigned Opcode = (*Slot).getOpcode(); - if (InMicroMipsMode && TII->GetInstSizeInBytes(&(*CurrI)) == 2 && + if (InMicroMipsMode && TII->GetInstSizeInBytes(*CurrI) == 2 && (Opcode == Mips::JR || Opcode == Mips::PseudoIndirectBranch || Opcode == Mips::PseudoReturn)) continue; @@ -819,7 +815,7 @@ Filler::getBranch(MachineBasicBlock &MBB, const MachineBasicBlock &Dst) const { SmallVector<MachineOperand, 2> Cond; MipsInstrInfo::BranchType R = - TII->AnalyzeBranch(MBB, TrueBB, FalseBB, Cond, false, BranchInstrs); + TII->analyzeBranch(MBB, TrueBB, FalseBB, Cond, false, BranchInstrs); if ((R == MipsInstrInfo::BT_None) || (R == MipsInstrInfo::BT_NoBranch)) return std::make_pair(R, nullptr); diff --git a/lib/Target/Mips/MipsEVAInstrInfo.td b/lib/Target/Mips/MipsEVAInstrInfo.td index 36c9694cbaddc..26df263d228b3 100644 --- a/lib/Target/Mips/MipsEVAInstrInfo.td +++ b/lib/Target/Mips/MipsEVAInstrInfo.td @@ -51,7 +51,8 @@ class PREFE_ENC : SPECIAL3_EVA_LOAD_STORE_FM<OPCODE6_PREFE>; //===----------------------------------------------------------------------===// // Memory Load/Store EVA descriptions -class LOAD_EVA_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> { +class LOAD_EVA_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, + InstrItinClass itin = NoItinerary> { dag OutOperandList = (outs GPROpnd:$rt); dag InOperandList = (ins mem_simm9:$addr); string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); @@ -59,30 +60,34 @@ class LOAD_EVA_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> { string DecoderMethod = "DecodeMemEVA"; bit canFoldAsLoad = 1; bit mayLoad = 1; + InstrItinClass Itinerary = itin; } -class LBE_DESC : LOAD_EVA_DESC_BASE<"lbe", GPR32Opnd>; -class LBuE_DESC : LOAD_EVA_DESC_BASE<"lbue", GPR32Opnd>; -class LHE_DESC : LOAD_EVA_DESC_BASE<"lhe", GPR32Opnd>; -class LHuE_DESC : LOAD_EVA_DESC_BASE<"lhue", GPR32Opnd>; -class LWE_DESC : LOAD_EVA_DESC_BASE<"lwe", GPR32Opnd>; +class LBE_DESC : LOAD_EVA_DESC_BASE<"lbe", GPR32Opnd, II_LBE>; +class LBuE_DESC : LOAD_EVA_DESC_BASE<"lbue", GPR32Opnd, II_LBUE>; +class LHE_DESC : LOAD_EVA_DESC_BASE<"lhe", GPR32Opnd, II_LHE>; +class LHuE_DESC : LOAD_EVA_DESC_BASE<"lhue", GPR32Opnd, II_LHUE>; +class LWE_DESC : LOAD_EVA_DESC_BASE<"lwe", GPR32Opnd, II_LWE>; class STORE_EVA_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, - SDPatternOperator OpNode = null_frag> { + SDPatternOperator OpNode = null_frag, + InstrItinClass itin = NoItinerary> { dag OutOperandList = (outs); dag InOperandList = (ins GPROpnd:$rt, mem_simm9:$addr); string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); list<dag> Pattern = []; string DecoderMethod = "DecodeMemEVA"; bit mayStore = 1; + InstrItinClass Itinerary = itin; } -class SBE_DESC : STORE_EVA_DESC_BASE<"sbe", GPR32Opnd>; -class SHE_DESC : STORE_EVA_DESC_BASE<"she", GPR32Opnd>; -class SWE_DESC : STORE_EVA_DESC_BASE<"swe", GPR32Opnd>; +class SBE_DESC : STORE_EVA_DESC_BASE<"sbe", GPR32Opnd, null_frag, II_SBE>; +class SHE_DESC : STORE_EVA_DESC_BASE<"she", GPR32Opnd, null_frag, II_SHE>; +class SWE_DESC : STORE_EVA_DESC_BASE<"swe", GPR32Opnd, null_frag, II_SWE>; // Load/Store Left/Right EVA descriptions -class LOAD_LEFT_RIGHT_EVA_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> { +class LOAD_LEFT_RIGHT_EVA_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, + InstrItinClass itin = NoItinerary> { dag OutOperandList = (outs GPROpnd:$rt); dag InOperandList = (ins mem_simm9:$addr, GPROpnd:$src); string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); @@ -90,35 +95,41 @@ class LOAD_LEFT_RIGHT_EVA_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> { string DecoderMethod = "DecodeMemEVA"; string Constraints = "$src = $rt"; bit canFoldAsLoad = 1; + InstrItinClass Itinerary = itin; } -class LWLE_DESC : LOAD_LEFT_RIGHT_EVA_DESC_BASE<"lwle", GPR32Opnd>; -class LWRE_DESC : LOAD_LEFT_RIGHT_EVA_DESC_BASE<"lwre", GPR32Opnd>; +class LWLE_DESC : LOAD_LEFT_RIGHT_EVA_DESC_BASE<"lwle", GPR32Opnd, II_LWLE>; +class LWRE_DESC : LOAD_LEFT_RIGHT_EVA_DESC_BASE<"lwre", GPR32Opnd, II_LWRE>; -class STORE_LEFT_RIGHT_EVA_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> { +class STORE_LEFT_RIGHT_EVA_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, + InstrItinClass itin = NoItinerary> { dag OutOperandList = (outs); dag InOperandList = (ins GPROpnd:$rt, mem_simm9:$addr); string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); list<dag> Pattern = []; string DecoderMethod = "DecodeMemEVA"; + InstrItinClass Itinerary = itin; } -class SWLE_DESC : LOAD_LEFT_RIGHT_EVA_DESC_BASE<"swle", GPR32Opnd>; -class SWRE_DESC : LOAD_LEFT_RIGHT_EVA_DESC_BASE<"swre", GPR32Opnd>; +class SWLE_DESC : LOAD_LEFT_RIGHT_EVA_DESC_BASE<"swle", GPR32Opnd, II_SWLE>; +class SWRE_DESC : LOAD_LEFT_RIGHT_EVA_DESC_BASE<"swre", GPR32Opnd, II_SWRE>; // Load-linked EVA, Store-conditional EVA descriptions -class LLE_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> { +class LLE_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, + InstrItinClass itin = NoItinerary> { dag OutOperandList = (outs GPROpnd:$rt); dag InOperandList = (ins mem_simm9:$addr); string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); list<dag> Pattern = []; bit mayLoad = 1; string DecoderMethod = "DecodeMemEVA"; + InstrItinClass Itinerary = itin; } -class LLE_DESC : LLE_DESC_BASE<"lle", GPR32Opnd>; +class LLE_DESC : LLE_DESC_BASE<"lle", GPR32Opnd, II_LLE>; -class SCE_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> { +class SCE_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, + InstrItinClass itin = NoItinerary> { dag OutOperandList = (outs GPROpnd:$dst); dag InOperandList = (ins GPROpnd:$rt, mem_simm9:$addr); string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); @@ -126,30 +137,34 @@ class SCE_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> { bit mayStore = 1; string Constraints = "$rt = $dst"; string DecoderMethod = "DecodeMemEVA"; + InstrItinClass Itinerary = itin; } -class SCE_DESC : SCE_DESC_BASE<"sce", GPR32Opnd>; +class SCE_DESC : SCE_DESC_BASE<"sce", GPR32Opnd, II_SCE>; -class TLB_DESC_BASE<string instr_asm> { +class TLB_DESC_BASE<string instr_asm, InstrItinClass itin = NoItinerary> { dag OutOperandList = (outs); dag InOperandList = (ins); string AsmString = instr_asm; list<dag> Pattern = []; + InstrItinClass Itinerary = itin; } -class TLBINV_DESC : TLB_DESC_BASE<"tlbinv">; -class TLBINVF_DESC : TLB_DESC_BASE<"tlbinvf">; +class TLBINV_DESC : TLB_DESC_BASE<"tlbinv", II_TLBINV>; +class TLBINVF_DESC : TLB_DESC_BASE<"tlbinvf", II_TLBINVF>; -class CACHEE_DESC_BASE<string instr_asm, Operand MemOpnd> { +class CACHEE_DESC_BASE<string instr_asm, Operand MemOpnd, + InstrItinClass itin = NoItinerary> { dag OutOperandList = (outs); dag InOperandList = (ins MemOpnd:$addr, uimm5:$hint); string AsmString = !strconcat(instr_asm, "\t$hint, $addr"); list<dag> Pattern = []; string DecoderMethod = "DecodeCacheeOp_CacheOpR6"; + InstrItinClass Itinerary = itin; } -class CACHEE_DESC : CACHEE_DESC_BASE<"cachee", mem>; -class PREFE_DESC : CACHEE_DESC_BASE<"prefe", mem>; +class CACHEE_DESC : CACHEE_DESC_BASE<"cachee", mem_simm9, II_CACHEE>; +class PREFE_DESC : CACHEE_DESC_BASE<"prefe", mem_simm9, II_PREFE>; //===----------------------------------------------------------------------===// // @@ -185,8 +200,10 @@ def LLE : LLE_ENC, LLE_DESC, INSN_EVA; def SCE : SCE_ENC, SCE_DESC, INSN_EVA; } -def TLBINV : TLBINV_ENC, TLBINV_DESC, INSN_EVA; -def TLBINVF : TLBINVF_ENC, TLBINVF_DESC, INSN_EVA; +let AdditionalPredicates = [NotInMicroMips] in { + def TLBINV : TLBINV_ENC, TLBINV_DESC, INSN_EVA; + def TLBINVF : TLBINVF_ENC, TLBINVF_DESC, INSN_EVA; +} def CACHEE : CACHEE_ENC, CACHEE_DESC, INSN_EVA; def PREFE : PREFE_ENC, PREFE_DESC, INSN_EVA; diff --git a/lib/Target/Mips/MipsFastISel.cpp b/lib/Target/Mips/MipsFastISel.cpp index e9eaf810637a6..19c201d26b245 100644 --- a/lib/Target/Mips/MipsFastISel.cpp +++ b/lib/Target/Mips/MipsFastISel.cpp @@ -1,5 +1,18 @@ -//===-- MipsastISel.cpp - Mips FastISel implementation -//---------------------===// +//===-- MipsFastISel.cpp - Mips FastISel implementation --------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief This file defines the MIPS-specific support for the FastISel class. +/// Some of the target-specific code is generated by tablegen in the file +/// MipsGenFastISel.inc, which is #included here. +/// +//===----------------------------------------------------------------------===// #include "MipsCCState.h" #include "MipsInstrInfo.h" @@ -192,9 +205,10 @@ public: TII(*Subtarget->getInstrInfo()), TLI(*Subtarget->getTargetLowering()) { MFI = funcInfo.MF->getInfo<MipsFunctionInfo>(); Context = &funcInfo.Fn->getContext(); - bool ISASupported = !Subtarget->hasMips32r6() && Subtarget->hasMips32(); + bool ISASupported = !Subtarget->hasMips32r6() && + !Subtarget->inMicroMipsMode() && Subtarget->hasMips32(); TargetSupported = - ISASupported && (TM.getRelocationModel() == Reloc::PIC_) && + ISASupported && TM.isPositionIndependent() && (static_cast<const MipsTargetMachine &>(TM).getABI().IsO32()); UnsupportedFPMode = Subtarget->isFP64bit(); } @@ -691,11 +705,10 @@ bool MipsFastISel::emitCmp(unsigned ResultReg, const CmpInst *CI) { emitInst(Mips::ADDiu, RegWithOne).addReg(Mips::ZERO).addImm(1); emitInst(Opc).addReg(LeftReg).addReg(RightReg).addReg( Mips::FCC0, RegState::ImplicitDefine); - MachineInstrBuilder MI = emitInst(CondMovOpc, ResultReg) - .addReg(RegWithOne) - .addReg(Mips::FCC0) - .addReg(RegWithZero, RegState::Implicit); - MI->tieOperands(0, 3); + emitInst(CondMovOpc, ResultReg) + .addReg(RegWithOne) + .addReg(Mips::FCC0) + .addReg(RegWithZero); break; } } @@ -802,7 +815,7 @@ bool MipsFastISel::emitStore(MVT VT, unsigned SrcReg, Address &Addr, unsigned Offset = Addr.getOffset(); MachineFrameInfo &MFI = *MF->getFrameInfo(); MachineMemOperand *MMO = MF->getMachineMemOperand( - MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOLoad, + MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOStore, MFI.getObjectSize(FI), Align); BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc)) .addReg(SrcReg) @@ -943,7 +956,7 @@ bool MipsFastISel::selectFPExt(const Instruction *I) { return false; unsigned SrcReg = - getRegForValue(Src); // his must be a 32 bit floating point register class + getRegForValue(Src); // this must be a 32bit floating point register class // maybe we should handle this differently if (!SrcReg) return false; @@ -1180,7 +1193,7 @@ bool MipsFastISel::processCallArgs(CallLoweringInfo &CLI, // for now (will return false). We need to determine the right alignment // based on the normal alignment for the underlying machine type. // - unsigned ArgSize = RoundUpToAlignment(ArgVT.getSizeInBits(), 4); + unsigned ArgSize = alignTo(ArgVT.getSizeInBits(), 4); unsigned BEAlign = 0; if (ArgSize < 8 && !Subtarget->isLittle()) @@ -1207,7 +1220,7 @@ bool MipsFastISel::processCallArgs(CallLoweringInfo &CLI, bool MipsFastISel::finishCall(CallLoweringInfo &CLI, MVT RetVT, unsigned NumBytes) { CallingConv::ID CC = CLI.CallConv; - emitInst(Mips::ADJCALLSTACKUP).addImm(16); + emitInst(Mips::ADJCALLSTACKUP).addImm(16).addImm(0); if (RetVT != MVT::isVoid) { SmallVector<CCValAssign, 16> RVLocs; CCState CCInfo(CC, false, *FuncInfo.MF, RVLocs, *Context); diff --git a/lib/Target/Mips/MipsFrameLowering.cpp b/lib/Target/Mips/MipsFrameLowering.cpp index a74c8abd2e2db..fe6f332f2bdf9 100644 --- a/lib/Target/Mips/MipsFrameLowering.cpp +++ b/lib/Target/Mips/MipsFrameLowering.cpp @@ -13,7 +13,6 @@ #include "MipsFrameLowering.h" #include "MCTargetDesc/MipsBaseInfo.h" -#include "MipsAnalyzeImmediate.h" #include "MipsInstrInfo.h" #include "MipsMachineFunction.h" #include "MipsTargetMachine.h" @@ -24,7 +23,6 @@ #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Target/TargetOptions.h" using namespace llvm; @@ -122,7 +120,7 @@ uint64_t MipsFrameLowering::estimateStackSize(const MachineFunction &MF) const { // Conservatively assume all callee-saved registers will be saved. for (const MCPhysReg *R = TRI.getCalleeSavedRegs(&MF); *R; ++R) { unsigned Size = TRI.getMinimalPhysRegClass(*R)->getSize(); - Offset = RoundUpToAlignment(Offset + Size, Size); + Offset = alignTo(Offset + Size, Size); } unsigned MaxAlign = MFI->getMaxAlignment(); @@ -133,18 +131,18 @@ uint64_t MipsFrameLowering::estimateStackSize(const MachineFunction &MF) const { // Iterate over other objects. for (unsigned I = 0, E = MFI->getObjectIndexEnd(); I != E; ++I) - Offset = RoundUpToAlignment(Offset + MFI->getObjectSize(I), MaxAlign); + Offset = alignTo(Offset + MFI->getObjectSize(I), MaxAlign); // Call frame. if (MFI->adjustsStack() && hasReservedCallFrame(MF)) - Offset = RoundUpToAlignment(Offset + MFI->getMaxCallFrameSize(), - std::max(MaxAlign, getStackAlignment())); + Offset = alignTo(Offset + MFI->getMaxCallFrameSize(), + std::max(MaxAlign, getStackAlignment())); - return RoundUpToAlignment(Offset, getStackAlignment()); + return alignTo(Offset, getStackAlignment()); } // Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions -void MipsFrameLowering:: +MachineBasicBlock::iterator MipsFrameLowering:: eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const { unsigned SP = STI.getABI().IsN64() ? Mips::SP_64 : Mips::SP; @@ -157,5 +155,5 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, STI.getInstrInfo()->adjustStackPtr(SP, Amount, MBB, I); } - MBB.erase(I); + return MBB.erase(I); } diff --git a/lib/Target/Mips/MipsFrameLowering.h b/lib/Target/Mips/MipsFrameLowering.h index 5eabd58e8686a..8c4214c4c21d0 100644 --- a/lib/Target/Mips/MipsFrameLowering.h +++ b/lib/Target/Mips/MipsFrameLowering.h @@ -36,7 +36,7 @@ public: bool isFPCloseToIncomingSP() const override { return false; } - void + MachineBasicBlock::iterator eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const override; diff --git a/lib/Target/Mips/MipsHazardSchedule.cpp b/lib/Target/Mips/MipsHazardSchedule.cpp new file mode 100644 index 0000000000000..10022ba60680d --- /dev/null +++ b/lib/Target/Mips/MipsHazardSchedule.cpp @@ -0,0 +1,147 @@ +//===-- MipsHazardSchedule.cpp - Workaround pipeline hazards --------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// This pass is used to workaround certain pipeline hazards. For now, this covers +/// compact branch hazards. In future this pass can be extended to other pipeline +/// hazards, such as various MIPS1 hazards, processor errata that require +/// instruction reorganization, etc. +/// +/// This pass has to run after the delay slot filler as that pass can introduce +/// pipeline hazards, hence the existing hazard recognizer is not suitable. +/// +/// Hazards handled: forbidden slots for MIPSR6. +/// +/// A forbidden slot hazard occurs when a compact branch instruction is executed +/// and the adjacent instruction in memory is a control transfer instruction such +/// as a branch or jump, ERET, ERETNC, DERET, WAIT and PAUSE. +/// +/// For example: +/// +/// 0x8004 bnec a1,v0,<P+0x18> +/// 0x8008 beqc a1,a2,<P+0x54> +/// +/// In such cases, the processor is required to signal a Reserved Instruction +/// exception. +/// +/// Here, if the instruction at 0x8004 is executed, the processor will raise an +/// exception as there is a control transfer instruction at 0x8008. +/// +/// There are two sources of forbidden slot hazards: +/// +/// A) A previous pass has created a compact branch directly. +/// B) Transforming a delay slot branch into compact branch. This case can be +/// difficult to process as lookahead for hazards is insufficent, as +/// backwards delay slot fillling can also produce hazards in previously +/// processed instuctions. +/// +//===----------------------------------------------------------------------===// + +#include "Mips.h" +#include "MipsInstrInfo.h" +#include "MipsSEInstrInfo.h" +#include "MipsTargetMachine.h" +#include "llvm/ADT/Statistic.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/IR/Function.h" +#include "llvm/Target/TargetInstrInfo.h" +#include "llvm/Target/TargetMachine.h" +#include "llvm/Target/TargetRegisterInfo.h" + +using namespace llvm; + +#define DEBUG_TYPE "mips-hazard-schedule" + +STATISTIC(NumInsertedNops, "Number of nops inserted"); + +namespace { + +typedef MachineBasicBlock::iterator Iter; +typedef MachineBasicBlock::reverse_iterator ReverseIter; + +class MipsHazardSchedule : public MachineFunctionPass { + +public: + MipsHazardSchedule() : MachineFunctionPass(ID) {} + + const char *getPassName() const override { return "Mips Hazard Schedule"; } + + bool runOnMachineFunction(MachineFunction &F) override; + + MachineFunctionProperties getRequiredProperties() const override { + return MachineFunctionProperties().set( + MachineFunctionProperties::Property::AllVRegsAllocated); + } + +private: + static char ID; +}; + +char MipsHazardSchedule::ID = 0; +} // end of anonymous namespace + +/// Returns a pass that clears pipeline hazards. +FunctionPass *llvm::createMipsHazardSchedule() { + return new MipsHazardSchedule(); +} + +// Find the next real instruction from the current position. +static Iter getNextMachineInstr(Iter Position) { + Iter I = Position, E = Position->getParent()->end(); + I = std::find_if_not(I, E, [](const Iter &Insn) { return Insn->isTransient(); }); + assert(I != E); + return I; +} + +bool MipsHazardSchedule::runOnMachineFunction(MachineFunction &MF) { + + const MipsSubtarget *STI = + &static_cast<const MipsSubtarget &>(MF.getSubtarget()); + + // Forbidden slot hazards are only defined for MIPSR6. + if (!STI->hasMips32r6() || STI->inMicroMipsMode()) + return false; + + bool Changed = false; + const MipsInstrInfo *TII = STI->getInstrInfo(); + + for (MachineFunction::iterator FI = MF.begin(); FI != MF.end(); ++FI) { + for (Iter I = FI->begin(); I != FI->end(); ++I) { + + // Forbidden slot hazard handling. Use lookahead over state. + if (!TII->HasForbiddenSlot(*I)) + continue; + + bool InsertNop = false; + // Next instruction in the basic block. + if (std::next(I) != FI->end() && + !TII->SafeInForbiddenSlot(*getNextMachineInstr(std::next(I)))) { + InsertNop = true; + } else { + // Next instruction in the physical successor basic block. + for (auto *Succ : FI->successors()) { + if (FI->isLayoutSuccessor(Succ) && + getNextMachineInstr(Succ->begin()) != Succ->end() && + !TII->SafeInForbiddenSlot(*getNextMachineInstr(Succ->begin()))) { + InsertNop = true; + break; + } + } + } + + if (InsertNop) { + Changed = true; + MIBundleBuilder(&*I).append( + BuildMI(MF, I->getDebugLoc(), TII->get(Mips::NOP))); + NumInsertedNops++; + } + } + } + return Changed; +} diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp index 06502397b6b8c..83763a64ab6ae 100644 --- a/lib/Target/Mips/MipsISelDAGToDAG.cpp +++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp @@ -72,12 +72,6 @@ bool MipsDAGToDAGISel::selectAddrRegImm(SDValue Addr, SDValue &Base, return false; } -bool MipsDAGToDAGISel::selectAddrRegReg(SDValue Addr, SDValue &Base, - SDValue &Offset) const { - llvm_unreachable("Unimplemented function."); - return false; -} - bool MipsDAGToDAGISel::selectAddrDefault(SDValue Addr, SDValue &Base, SDValue &Offset) const { llvm_unreachable("Unimplemented function."); @@ -90,7 +84,19 @@ bool MipsDAGToDAGISel::selectIntAddr(SDValue Addr, SDValue &Base, return false; } -bool MipsDAGToDAGISel::selectIntAddrMM(SDValue Addr, SDValue &Base, +bool MipsDAGToDAGISel::selectIntAddr11MM(SDValue Addr, SDValue &Base, + SDValue &Offset) const { + llvm_unreachable("Unimplemented function."); + return false; +} + +bool MipsDAGToDAGISel::selectIntAddr12MM(SDValue Addr, SDValue &Base, + SDValue &Offset) const { + llvm_unreachable("Unimplemented function."); + return false; +} + +bool MipsDAGToDAGISel::selectIntAddr16MM(SDValue Addr, SDValue &Base, SDValue &Offset) const { llvm_unreachable("Unimplemented function."); return false; @@ -108,8 +114,14 @@ bool MipsDAGToDAGISel::selectIntAddrMSA(SDValue Addr, SDValue &Base, return false; } -bool MipsDAGToDAGISel::selectAddr16(SDNode *Parent, SDValue N, SDValue &Base, - SDValue &Offset, SDValue &Alias) { +bool MipsDAGToDAGISel::selectAddr16(SDValue Addr, SDValue &Base, + SDValue &Offset) { + llvm_unreachable("Unimplemented function."); + return false; +} + +bool MipsDAGToDAGISel::selectAddr16SP(SDValue Addr, SDValue &Base, + SDValue &Offset) { llvm_unreachable("Unimplemented function."); return false; } @@ -182,7 +194,7 @@ bool MipsDAGToDAGISel::selectVSplatMaskR(SDValue N, SDValue &Imm) const { /// Select instructions not customized! Used for /// expanded, promoted and normal instructions -SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { +void MipsDAGToDAGISel::Select(SDNode *Node) { unsigned Opcode = Node->getOpcode(); // Dump information about the Node being selected @@ -192,21 +204,20 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { if (Node->isMachineOpcode()) { DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n"); Node->setNodeId(-1); - return nullptr; + return; } // See if subclasses can handle this node. - std::pair<bool, SDNode*> Ret = selectNode(Node); - - if (Ret.first) - return Ret.second; + if (trySelect(Node)) + return; switch(Opcode) { default: break; // Get target GOT address. case ISD::GLOBAL_OFFSET_TABLE: - return getGlobalBaseReg(); + ReplaceNode(Node, getGlobalBaseReg()); + return; #ifndef NDEBUG case ISD::LOAD: @@ -220,15 +231,7 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) { } // Select the default instruction - SDNode *ResNode = SelectCode(Node); - - DEBUG(errs() << "=> "); - if (ResNode == nullptr || ResNode == Node) - DEBUG(Node->dump(CurDAG)); - else - DEBUG(ResNode->dump(CurDAG)); - DEBUG(errs() << "\n"); - return ResNode; + SelectCode(Node); } bool MipsDAGToDAGISel:: diff --git a/lib/Target/Mips/MipsISelDAGToDAG.h b/lib/Target/Mips/MipsISelDAGToDAG.h index 1426d0fbf5161..289832a8064e3 100644 --- a/lib/Target/Mips/MipsISelDAGToDAG.h +++ b/lib/Target/Mips/MipsISelDAGToDAG.h @@ -31,8 +31,8 @@ namespace llvm { class MipsDAGToDAGISel : public SelectionDAGISel { public: - explicit MipsDAGToDAGISel(MipsTargetMachine &TM) - : SelectionDAGISel(TM), Subtarget(nullptr) {} + explicit MipsDAGToDAGISel(MipsTargetMachine &TM, CodeGenOpt::Level OL) + : SelectionDAGISel(TM, OL), Subtarget(nullptr) {} // Pass Name const char *getPassName() const override { @@ -57,11 +57,6 @@ private: virtual bool selectAddrRegImm(SDValue Addr, SDValue &Base, SDValue &Offset) const; - // Complex Pattern. - /// (reg + reg). - virtual bool selectAddrRegReg(SDValue Addr, SDValue &Base, - SDValue &Offset) const; - /// Fall back on this function if all else fails. virtual bool selectAddrDefault(SDValue Addr, SDValue &Base, SDValue &Offset) const; @@ -70,9 +65,15 @@ private: virtual bool selectIntAddr(SDValue Addr, SDValue &Base, SDValue &Offset) const; - virtual bool selectIntAddrMM(SDValue Addr, SDValue &Base, + virtual bool selectIntAddr11MM(SDValue Addr, SDValue &Base, + SDValue &Offset) const; + + virtual bool selectIntAddr12MM(SDValue Addr, SDValue &Base, SDValue &Offset) const; + virtual bool selectIntAddr16MM(SDValue Addr, SDValue &Base, + SDValue &Offset) const; + virtual bool selectIntAddrLSL2MM(SDValue Addr, SDValue &Base, SDValue &Offset) const; @@ -80,8 +81,8 @@ private: virtual bool selectIntAddrMSA(SDValue Addr, SDValue &Base, SDValue &Offset) const; - virtual bool selectAddr16(SDNode *Parent, SDValue N, SDValue &Base, - SDValue &Offset, SDValue &Alias); + virtual bool selectAddr16(SDValue Addr, SDValue &Base, SDValue &Offset); + virtual bool selectAddr16SP(SDValue Addr, SDValue &Base, SDValue &Offset); /// \brief Select constant vector splats. virtual bool selectVSplat(SDNode *N, APInt &Imm, @@ -114,9 +115,9 @@ private: /// starting at bit zero. virtual bool selectVSplatMaskR(SDValue N, SDValue &Imm) const; - SDNode *Select(SDNode *N) override; + void Select(SDNode *N) override; - virtual std::pair<bool, SDNode*> selectNode(SDNode *Node) = 0; + virtual bool trySelect(SDNode *Node) = 0; // getImm - Return a target constant with the specified value. inline SDValue getImm(const SDNode *Node, uint64_t Imm) { diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index 5680130b91b22..1d62a251cc663 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -341,10 +341,6 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, } setOperationAction(ISD::CTTZ, MVT::i32, Expand); setOperationAction(ISD::CTTZ, MVT::i64, Expand); - setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i32, Expand); - setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i64, Expand); - setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32, Expand); - setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i64, Expand); setOperationAction(ISD::ROTL, MVT::i32, Expand); setOperationAction(ISD::ROTL, MVT::i64, Expand); setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand); @@ -396,7 +392,6 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, setOperationAction(ISD::ATOMIC_STORE, MVT::i64, Expand); } - setInsertFencesForAtomic(true); if (!Subtarget.hasMips32r2()) { setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8, Expand); @@ -429,6 +424,7 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, setTargetDAGCombine(ISD::AND); setTargetDAGCombine(ISD::OR); setTargetDAGCombine(ISD::ADD); + setTargetDAGCombine(ISD::AssertZext); setMinFunctionAlignment(Subtarget.isGP64bit() ? 3 : 2); @@ -568,7 +564,7 @@ static SDValue createFPCmp(SelectionDAG &DAG, const SDValue &Op) { // Creates and returns a CMovFPT/F node. static SDValue createCMovFP(SelectionDAG &DAG, SDValue Cond, SDValue True, - SDValue False, SDLoc DL) { + SDValue False, const SDLoc &DL) { ConstantSDNode *CC = cast<ConstantSDNode>(Cond.getOperand(2)); bool invert = invertFPCondCodeUser((Mips::CondCode)CC->getSExtValue()); SDValue FCC0 = DAG.getRegister(Mips::FCC0, MVT::i32); @@ -808,6 +804,37 @@ static SDValue performADDCombine(SDNode *N, SelectionDAG &DAG, return DAG.getNode(ISD::ADD, DL, ValTy, Add1, Lo); } +static SDValue performAssertZextCombine(SDNode *N, SelectionDAG &DAG, + TargetLowering::DAGCombinerInfo &DCI, + const MipsSubtarget &Subtarget) { + SDValue N0 = N->getOperand(0); + EVT NarrowerVT = cast<VTSDNode>(N->getOperand(1))->getVT(); + + if (N0.getOpcode() != ISD::TRUNCATE) + return SDValue(); + + if (N0.getOperand(0).getOpcode() != ISD::AssertZext) + return SDValue(); + + // fold (AssertZext (trunc (AssertZext x))) -> (trunc (AssertZext x)) + // if the type of the extension of the innermost AssertZext node is + // smaller from that of the outermost node, eg: + // (AssertZext:i32 (trunc:i32 (AssertZext:i64 X, i32)), i8) + // -> (trunc:i32 (AssertZext X, i8)) + SDValue WiderAssertZext = N0.getOperand(0); + EVT WiderVT = cast<VTSDNode>(WiderAssertZext->getOperand(1))->getVT(); + + if (NarrowerVT.bitsLT(WiderVT)) { + SDValue NewAssertZext = DAG.getNode( + ISD::AssertZext, SDLoc(N), WiderAssertZext.getValueType(), + WiderAssertZext.getOperand(0), DAG.getValueType(NarrowerVT)); + return DAG.getNode(ISD::TRUNCATE, SDLoc(N), N->getValueType(0), + NewAssertZext); + } + + return SDValue(); +} + SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { SelectionDAG &DAG = DCI.DAG; @@ -829,6 +856,8 @@ SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) return performORCombine(N, DAG, DCI, Subtarget); case ISD::ADD: return performADDCombine(N, DAG, DCI, Subtarget); + case ISD::AssertZext: + return performAssertZextCombine(N, DAG, DCI, Subtarget); } return SDValue(); @@ -906,20 +935,22 @@ addLiveIn(MachineFunction &MF, unsigned PReg, const TargetRegisterClass *RC) return VReg; } -static MachineBasicBlock *insertDivByZeroTrap(MachineInstr *MI, +static MachineBasicBlock *insertDivByZeroTrap(MachineInstr &MI, MachineBasicBlock &MBB, const TargetInstrInfo &TII, - bool Is64Bit) { + bool Is64Bit, bool IsMicroMips) { if (NoZeroDivCheck) return &MBB; // Insert instruction "teq $divisor_reg, $zero, 7". MachineBasicBlock::iterator I(MI); MachineInstrBuilder MIB; - MachineOperand &Divisor = MI->getOperand(2); - MIB = BuildMI(MBB, std::next(I), MI->getDebugLoc(), TII.get(Mips::TEQ)) - .addReg(Divisor.getReg(), getKillRegState(Divisor.isKill())) - .addReg(Mips::ZERO).addImm(7); + MachineOperand &Divisor = MI.getOperand(2); + MIB = BuildMI(MBB, std::next(I), MI.getDebugLoc(), + TII.get(IsMicroMips ? Mips::TEQ_MM : Mips::TEQ)) + .addReg(Divisor.getReg(), getKillRegState(Divisor.isKill())) + .addReg(Mips::ZERO) + .addImm(7); // Use the 32-bit sub-register if this is a 64-bit division. if (Is64Bit) @@ -935,9 +966,9 @@ static MachineBasicBlock *insertDivByZeroTrap(MachineInstr *MI, } MachineBasicBlock * -MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, +MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *BB) const { - switch (MI->getOpcode()) { + switch (MI.getOpcode()) { default: llvm_unreachable("Unexpected instr type to insert"); case Mips::ATOMIC_LOAD_ADD_I8: @@ -1017,15 +1048,31 @@ MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, case Mips::DIVU: case Mips::MOD: case Mips::MODU: - return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), false); + return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), false, + false); + case Mips::SDIV_MM_Pseudo: + case Mips::UDIV_MM_Pseudo: + case Mips::SDIV_MM: + case Mips::UDIV_MM: + case Mips::DIV_MMR6: + case Mips::DIVU_MMR6: + case Mips::MOD_MMR6: + case Mips::MODU_MMR6: + return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), false, true); case Mips::PseudoDSDIV: case Mips::PseudoDUDIV: case Mips::DDIV: case Mips::DDIVU: case Mips::DMOD: case Mips::DMODU: - return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), true); + return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), true, false); + case Mips::DDIV_MM64R6: + case Mips::DDIVU_MM64R6: + case Mips::DMOD_MM64R6: + case Mips::DMODU_MM64R6: + return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), true, true); case Mips::SEL_D: + case Mips::SEL_D_MMR6: return emitSEL_D(MI, BB); case Mips::PseudoSELECT_I: @@ -1051,17 +1098,19 @@ MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, // This function also handles Mips::ATOMIC_SWAP_I32 (when BinOpcode == 0), and // Mips::ATOMIC_LOAD_NAND_I32 (when Nand == true) -MachineBasicBlock * -MipsTargetLowering::emitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB, - unsigned Size, unsigned BinOpcode, - bool Nand) const { +MachineBasicBlock *MipsTargetLowering::emitAtomicBinary(MachineInstr &MI, + MachineBasicBlock *BB, + unsigned Size, + unsigned BinOpcode, + bool Nand) const { assert((Size == 4 || Size == 8) && "Unsupported size for EmitAtomicBinary."); MachineFunction *MF = BB->getParent(); MachineRegisterInfo &RegInfo = MF->getRegInfo(); const TargetRegisterClass *RC = getRegClassFor(MVT::getIntegerVT(Size * 8)); const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - DebugLoc DL = MI->getDebugLoc(); + const bool ArePtrs64bit = ABI.ArePtrs64bit(); + DebugLoc DL = MI.getDebugLoc(); unsigned LL, SC, AND, NOR, ZERO, BEQ; if (Size == 4) { @@ -1069,9 +1118,14 @@ MipsTargetLowering::emitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB, LL = Mips::LL_MM; SC = Mips::SC_MM; } else { - LL = Subtarget.hasMips32r6() ? Mips::LL_R6 : Mips::LL; - SC = Subtarget.hasMips32r6() ? Mips::SC_R6 : Mips::SC; + LL = Subtarget.hasMips32r6() + ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6) + : (ArePtrs64bit ? Mips::LL64 : Mips::LL); + SC = Subtarget.hasMips32r6() + ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6) + : (ArePtrs64bit ? Mips::SC64 : Mips::SC); } + AND = Mips::AND; NOR = Mips::NOR; ZERO = Mips::ZERO; @@ -1085,9 +1139,9 @@ MipsTargetLowering::emitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB, BEQ = Mips::BEQ64; } - unsigned OldVal = MI->getOperand(0).getReg(); - unsigned Ptr = MI->getOperand(1).getReg(); - unsigned Incr = MI->getOperand(2).getReg(); + unsigned OldVal = MI.getOperand(0).getReg(); + unsigned Ptr = MI.getOperand(1).getReg(); + unsigned Incr = MI.getOperand(2).getReg(); unsigned StoreVal = RegInfo.createVirtualRegister(RC); unsigned AndRes = RegInfo.createVirtualRegister(RC); @@ -1134,16 +1188,16 @@ MipsTargetLowering::emitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB, BuildMI(BB, DL, TII->get(SC), Success).addReg(StoreVal).addReg(Ptr).addImm(0); BuildMI(BB, DL, TII->get(BEQ)).addReg(Success).addReg(ZERO).addMBB(loopMBB); - MI->eraseFromParent(); // The instruction is gone now. + MI.eraseFromParent(); // The instruction is gone now. return exitMBB; } MachineBasicBlock *MipsTargetLowering::emitSignExtendToI32InReg( - MachineInstr *MI, MachineBasicBlock *BB, unsigned Size, unsigned DstReg, + MachineInstr &MI, MachineBasicBlock *BB, unsigned Size, unsigned DstReg, unsigned SrcReg) const { const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - DebugLoc DL = MI->getDebugLoc(); + const DebugLoc &DL = MI.getDebugLoc(); if (Subtarget.hasMips32r2() && Size == 1) { BuildMI(BB, DL, TII->get(Mips::SEB), DstReg).addReg(SrcReg); @@ -1170,7 +1224,7 @@ MachineBasicBlock *MipsTargetLowering::emitSignExtendToI32InReg( } MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword( - MachineInstr *MI, MachineBasicBlock *BB, unsigned Size, unsigned BinOpcode, + MachineInstr &MI, MachineBasicBlock *BB, unsigned Size, unsigned BinOpcode, bool Nand) const { assert((Size == 1 || Size == 2) && "Unsupported size for EmitAtomicBinaryPartial."); @@ -1178,21 +1232,24 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword( MachineFunction *MF = BB->getParent(); MachineRegisterInfo &RegInfo = MF->getRegInfo(); const TargetRegisterClass *RC = getRegClassFor(MVT::i32); + const bool ArePtrs64bit = ABI.ArePtrs64bit(); + const TargetRegisterClass *RCp = + getRegClassFor(ArePtrs64bit ? MVT::i64 : MVT::i32); const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - DebugLoc DL = MI->getDebugLoc(); + DebugLoc DL = MI.getDebugLoc(); - unsigned Dest = MI->getOperand(0).getReg(); - unsigned Ptr = MI->getOperand(1).getReg(); - unsigned Incr = MI->getOperand(2).getReg(); + unsigned Dest = MI.getOperand(0).getReg(); + unsigned Ptr = MI.getOperand(1).getReg(); + unsigned Incr = MI.getOperand(2).getReg(); - unsigned AlignedAddr = RegInfo.createVirtualRegister(RC); + unsigned AlignedAddr = RegInfo.createVirtualRegister(RCp); unsigned ShiftAmt = RegInfo.createVirtualRegister(RC); unsigned Mask = RegInfo.createVirtualRegister(RC); unsigned Mask2 = RegInfo.createVirtualRegister(RC); unsigned NewVal = RegInfo.createVirtualRegister(RC); unsigned OldVal = RegInfo.createVirtualRegister(RC); unsigned Incr2 = RegInfo.createVirtualRegister(RC); - unsigned MaskLSB2 = RegInfo.createVirtualRegister(RC); + unsigned MaskLSB2 = RegInfo.createVirtualRegister(RCp); unsigned PtrLSB2 = RegInfo.createVirtualRegister(RC); unsigned MaskUpper = RegInfo.createVirtualRegister(RC); unsigned AndRes = RegInfo.createVirtualRegister(RC); @@ -1203,6 +1260,17 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword( unsigned SrlRes = RegInfo.createVirtualRegister(RC); unsigned Success = RegInfo.createVirtualRegister(RC); + unsigned LL, SC; + if (isMicroMips) { + LL = Mips::LL_MM; + SC = Mips::SC_MM; + } else { + LL = Subtarget.hasMips32r6() ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6) + : (ArePtrs64bit ? Mips::LL64 : Mips::LL); + SC = Subtarget.hasMips32r6() ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6) + : (ArePtrs64bit ? Mips::SC64 : Mips::SC); + } + // insert new blocks after the current block const BasicBlock *LLVM_BB = BB->getBasicBlock(); MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(LLVM_BB); @@ -1234,11 +1302,12 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword( // sll incr2,incr,shiftamt int64_t MaskImm = (Size == 1) ? 255 : 65535; - BuildMI(BB, DL, TII->get(Mips::ADDiu), MaskLSB2) - .addReg(Mips::ZERO).addImm(-4); - BuildMI(BB, DL, TII->get(Mips::AND), AlignedAddr) + BuildMI(BB, DL, TII->get(ABI.GetPtrAddiuOp()), MaskLSB2) + .addReg(ABI.GetNullPtr()).addImm(-4); + BuildMI(BB, DL, TII->get(ABI.GetPtrAndOp()), AlignedAddr) .addReg(Ptr).addReg(MaskLSB2); - BuildMI(BB, DL, TII->get(Mips::ANDi), PtrLSB2).addReg(Ptr).addImm(3); + BuildMI(BB, DL, TII->get(Mips::ANDi), PtrLSB2) + .addReg(Ptr, 0, ArePtrs64bit ? Mips::sub_32 : 0).addImm(3); if (Subtarget.isLittle()) { BuildMI(BB, DL, TII->get(Mips::SLL), ShiftAmt).addReg(PtrLSB2).addImm(3); } else { @@ -1274,7 +1343,6 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword( // beq success,$0,loopMBB BB = loopMBB; - unsigned LL = isMicroMips ? Mips::LL_MM : Mips::LL; BuildMI(BB, DL, TII->get(LL), OldVal).addReg(AlignedAddr).addImm(0); if (Nand) { // and andres, oldval, incr2 @@ -1298,7 +1366,6 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword( .addReg(OldVal).addReg(Mask2); BuildMI(BB, DL, TII->get(Mips::OR), StoreVal) .addReg(MaskedOldVal0).addReg(NewVal); - unsigned SC = isMicroMips ? Mips::SC_MM : Mips::SC; BuildMI(BB, DL, TII->get(SC), Success) .addReg(StoreVal).addReg(AlignedAddr).addImm(0); BuildMI(BB, DL, TII->get(Mips::BEQ)) @@ -1316,31 +1383,37 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword( .addReg(MaskedOldVal1).addReg(ShiftAmt); BB = emitSignExtendToI32InReg(MI, BB, Size, Dest, SrlRes); - MI->eraseFromParent(); // The instruction is gone now. + MI.eraseFromParent(); // The instruction is gone now. return exitMBB; } -MachineBasicBlock * MipsTargetLowering::emitAtomicCmpSwap(MachineInstr *MI, - MachineBasicBlock *BB, - unsigned Size) const { +MachineBasicBlock *MipsTargetLowering::emitAtomicCmpSwap(MachineInstr &MI, + MachineBasicBlock *BB, + unsigned Size) const { assert((Size == 4 || Size == 8) && "Unsupported size for EmitAtomicCmpSwap."); MachineFunction *MF = BB->getParent(); MachineRegisterInfo &RegInfo = MF->getRegInfo(); const TargetRegisterClass *RC = getRegClassFor(MVT::getIntegerVT(Size * 8)); const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - DebugLoc DL = MI->getDebugLoc(); + const bool ArePtrs64bit = ABI.ArePtrs64bit(); + DebugLoc DL = MI.getDebugLoc(); unsigned LL, SC, ZERO, BNE, BEQ; - if (Size == 4) { - if (isMicroMips) { - LL = Mips::LL_MM; - SC = Mips::SC_MM; - } else { - LL = Subtarget.hasMips32r6() ? Mips::LL_R6 : Mips::LL; - SC = Subtarget.hasMips32r6() ? Mips::SC_R6 : Mips::SC; - } + if (Size == 4) { + if (isMicroMips) { + LL = Mips::LL_MM; + SC = Mips::SC_MM; + } else { + LL = Subtarget.hasMips32r6() + ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6) + : (ArePtrs64bit ? Mips::LL64 : Mips::LL); + SC = Subtarget.hasMips32r6() + ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6) + : (ArePtrs64bit ? Mips::SC64 : Mips::SC); + } + ZERO = Mips::ZERO; BNE = Mips::BNE; BEQ = Mips::BEQ; @@ -1352,10 +1425,10 @@ MachineBasicBlock * MipsTargetLowering::emitAtomicCmpSwap(MachineInstr *MI, BEQ = Mips::BEQ64; } - unsigned Dest = MI->getOperand(0).getReg(); - unsigned Ptr = MI->getOperand(1).getReg(); - unsigned OldVal = MI->getOperand(2).getReg(); - unsigned NewVal = MI->getOperand(3).getReg(); + unsigned Dest = MI.getOperand(0).getReg(); + unsigned Ptr = MI.getOperand(1).getReg(); + unsigned OldVal = MI.getOperand(2).getReg(); + unsigned NewVal = MI.getOperand(3).getReg(); unsigned Success = RegInfo.createVirtualRegister(RC); @@ -1400,30 +1473,31 @@ MachineBasicBlock * MipsTargetLowering::emitAtomicCmpSwap(MachineInstr *MI, BuildMI(BB, DL, TII->get(BEQ)) .addReg(Success).addReg(ZERO).addMBB(loop1MBB); - MI->eraseFromParent(); // The instruction is gone now. + MI.eraseFromParent(); // The instruction is gone now. return exitMBB; } -MachineBasicBlock * -MipsTargetLowering::emitAtomicCmpSwapPartword(MachineInstr *MI, - MachineBasicBlock *BB, - unsigned Size) const { +MachineBasicBlock *MipsTargetLowering::emitAtomicCmpSwapPartword( + MachineInstr &MI, MachineBasicBlock *BB, unsigned Size) const { assert((Size == 1 || Size == 2) && "Unsupported size for EmitAtomicCmpSwapPartial."); MachineFunction *MF = BB->getParent(); MachineRegisterInfo &RegInfo = MF->getRegInfo(); const TargetRegisterClass *RC = getRegClassFor(MVT::i32); + const bool ArePtrs64bit = ABI.ArePtrs64bit(); + const TargetRegisterClass *RCp = + getRegClassFor(ArePtrs64bit ? MVT::i64 : MVT::i32); const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - DebugLoc DL = MI->getDebugLoc(); + DebugLoc DL = MI.getDebugLoc(); - unsigned Dest = MI->getOperand(0).getReg(); - unsigned Ptr = MI->getOperand(1).getReg(); - unsigned CmpVal = MI->getOperand(2).getReg(); - unsigned NewVal = MI->getOperand(3).getReg(); + unsigned Dest = MI.getOperand(0).getReg(); + unsigned Ptr = MI.getOperand(1).getReg(); + unsigned CmpVal = MI.getOperand(2).getReg(); + unsigned NewVal = MI.getOperand(3).getReg(); - unsigned AlignedAddr = RegInfo.createVirtualRegister(RC); + unsigned AlignedAddr = RegInfo.createVirtualRegister(RCp); unsigned ShiftAmt = RegInfo.createVirtualRegister(RC); unsigned Mask = RegInfo.createVirtualRegister(RC); unsigned Mask2 = RegInfo.createVirtualRegister(RC); @@ -1431,7 +1505,7 @@ MipsTargetLowering::emitAtomicCmpSwapPartword(MachineInstr *MI, unsigned OldVal = RegInfo.createVirtualRegister(RC); unsigned MaskedOldVal0 = RegInfo.createVirtualRegister(RC); unsigned ShiftedNewVal = RegInfo.createVirtualRegister(RC); - unsigned MaskLSB2 = RegInfo.createVirtualRegister(RC); + unsigned MaskLSB2 = RegInfo.createVirtualRegister(RCp); unsigned PtrLSB2 = RegInfo.createVirtualRegister(RC); unsigned MaskUpper = RegInfo.createVirtualRegister(RC); unsigned MaskedCmpVal = RegInfo.createVirtualRegister(RC); @@ -1440,6 +1514,17 @@ MipsTargetLowering::emitAtomicCmpSwapPartword(MachineInstr *MI, unsigned StoreVal = RegInfo.createVirtualRegister(RC); unsigned SrlRes = RegInfo.createVirtualRegister(RC); unsigned Success = RegInfo.createVirtualRegister(RC); + unsigned LL, SC; + + if (isMicroMips) { + LL = Mips::LL_MM; + SC = Mips::SC_MM; + } else { + LL = Subtarget.hasMips32r6() ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6) + : (ArePtrs64bit ? Mips::LL64 : Mips::LL); + SC = Subtarget.hasMips32r6() ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6) + : (ArePtrs64bit ? Mips::SC64 : Mips::SC); + } // insert new blocks after the current block const BasicBlock *LLVM_BB = BB->getBasicBlock(); @@ -1470,6 +1555,7 @@ MipsTargetLowering::emitAtomicCmpSwapPartword(MachineInstr *MI, // addiu masklsb2,$0,-4 # 0xfffffffc // and alignedaddr,ptr,masklsb2 // andi ptrlsb2,ptr,3 + // xori ptrlsb2,ptrlsb2,3 # Only for BE // sll shiftamt,ptrlsb2,3 // ori maskupper,$0,255 # 0xff // sll mask,maskupper,shiftamt @@ -1479,11 +1565,12 @@ MipsTargetLowering::emitAtomicCmpSwapPartword(MachineInstr *MI, // andi maskednewval,newval,255 // sll shiftednewval,maskednewval,shiftamt int64_t MaskImm = (Size == 1) ? 255 : 65535; - BuildMI(BB, DL, TII->get(Mips::ADDiu), MaskLSB2) - .addReg(Mips::ZERO).addImm(-4); - BuildMI(BB, DL, TII->get(Mips::AND), AlignedAddr) + BuildMI(BB, DL, TII->get(ArePtrs64bit ? Mips::DADDiu : Mips::ADDiu), MaskLSB2) + .addReg(ABI.GetNullPtr()).addImm(-4); + BuildMI(BB, DL, TII->get(ArePtrs64bit ? Mips::AND64 : Mips::AND), AlignedAddr) .addReg(Ptr).addReg(MaskLSB2); - BuildMI(BB, DL, TII->get(Mips::ANDi), PtrLSB2).addReg(Ptr).addImm(3); + BuildMI(BB, DL, TII->get(Mips::ANDi), PtrLSB2) + .addReg(Ptr, 0, ArePtrs64bit ? Mips::sub_32 : 0).addImm(3); if (Subtarget.isLittle()) { BuildMI(BB, DL, TII->get(Mips::SLL), ShiftAmt).addReg(PtrLSB2).addImm(3); } else { @@ -1511,7 +1598,6 @@ MipsTargetLowering::emitAtomicCmpSwapPartword(MachineInstr *MI, // and maskedoldval0,oldval,mask // bne maskedoldval0,shiftedcmpval,sinkMBB BB = loop1MBB; - unsigned LL = isMicroMips ? Mips::LL_MM : Mips::LL; BuildMI(BB, DL, TII->get(LL), OldVal).addReg(AlignedAddr).addImm(0); BuildMI(BB, DL, TII->get(Mips::AND), MaskedOldVal0) .addReg(OldVal).addReg(Mask); @@ -1528,7 +1614,6 @@ MipsTargetLowering::emitAtomicCmpSwapPartword(MachineInstr *MI, .addReg(OldVal).addReg(Mask2); BuildMI(BB, DL, TII->get(Mips::OR), StoreVal) .addReg(MaskedOldVal1).addReg(ShiftedNewVal); - unsigned SC = isMicroMips ? Mips::SC_MM : Mips::SC; BuildMI(BB, DL, TII->get(SC), Success) .addReg(StoreVal).addReg(AlignedAddr).addImm(0); BuildMI(BB, DL, TII->get(Mips::BEQ)) @@ -1543,21 +1628,21 @@ MipsTargetLowering::emitAtomicCmpSwapPartword(MachineInstr *MI, .addReg(MaskedOldVal0).addReg(ShiftAmt); BB = emitSignExtendToI32InReg(MI, BB, Size, Dest, SrlRes); - MI->eraseFromParent(); // The instruction is gone now. + MI.eraseFromParent(); // The instruction is gone now. return exitMBB; } -MachineBasicBlock *MipsTargetLowering::emitSEL_D(MachineInstr *MI, +MachineBasicBlock *MipsTargetLowering::emitSEL_D(MachineInstr &MI, MachineBasicBlock *BB) const { MachineFunction *MF = BB->getParent(); const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo(); const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineRegisterInfo &RegInfo = MF->getRegInfo(); - DebugLoc DL = MI->getDebugLoc(); + DebugLoc DL = MI.getDebugLoc(); MachineBasicBlock::iterator II(MI); - unsigned Fc = MI->getOperand(1).getReg(); + unsigned Fc = MI.getOperand(1).getReg(); const auto &FGR64RegClass = TRI->getRegClass(Mips::FGR64RegClassID); unsigned Fc2 = RegInfo.createVirtualRegister(FGR64RegClass); @@ -1569,7 +1654,7 @@ MachineBasicBlock *MipsTargetLowering::emitSEL_D(MachineInstr *MI, // We don't erase the original instruction, we just replace the condition // register with the 64-bit super-register. - MI->getOperand(1).setReg(Fc2); + MI.getOperand(1).setReg(Fc2); return BB; } @@ -1592,13 +1677,12 @@ SDValue MipsTargetLowering::lowerBR_JT(SDValue Op, SelectionDAG &DAG) const { SDValue Addr = DAG.getNode(ISD::ADD, DL, PTy, Index, Table); EVT MemVT = EVT::getIntegerVT(*DAG.getContext(), EntrySize * 8); - Addr = - DAG.getExtLoad(ISD::SEXTLOAD, DL, PTy, Chain, Addr, - MachinePointerInfo::getJumpTable(DAG.getMachineFunction()), - MemVT, false, false, false, 0); + Addr = DAG.getExtLoad( + ISD::SEXTLOAD, DL, PTy, Chain, Addr, + MachinePointerInfo::getJumpTable(DAG.getMachineFunction()), MemVT); Chain = Addr.getValue(1); - if ((getTargetMachine().getRelocationModel() == Reloc::PIC_) || ABI.IsN64()) { + if (isPositionIndependent() || ABI.IsN64()) { // For PIC, the sequence is: // BRIND(load(Jumptable + index) + RelocBase) // RelocBase can be JumpTable, GOT or some sort of global base. @@ -1667,7 +1751,7 @@ SDValue MipsTargetLowering::lowerGlobalAddress(SDValue Op, GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op); const GlobalValue *GV = N->getGlobal(); - if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !ABI.IsN64()) { + if (!isPositionIndependent() && !ABI.IsN64()) { const MipsTargetObjectFile *TLOF = static_cast<const MipsTargetObjectFile *>( getTargetMachine().getObjFileLowering()); @@ -1679,7 +1763,18 @@ SDValue MipsTargetLowering::lowerGlobalAddress(SDValue Op, return getAddrNonPIC(N, SDLoc(N), Ty, DAG); } - if (GV->hasInternalLinkage() || (GV->hasLocalLinkage() && !isa<Function>(GV))) + // Every other architecture would use shouldAssumeDSOLocal in here, but + // mips is special. + // * In PIC code mips requires got loads even for local statics! + // * To save on got entries, for local statics the got entry contains the + // page and an additional add instruction takes care of the low bits. + // * It is legal to access a hidden symbol with a non hidden undefined, + // so one cannot guarantee that all access to a hidden symbol will know + // it is hidden. + // * Mips linkers don't support creating a page and a full got entry for + // the same symbol. + // * Given all that, we have to use a full got entry for hidden symbols :-( + if (GV->hasLocalLinkage()) return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64()); if (LargeGOT) @@ -1690,7 +1785,7 @@ SDValue MipsTargetLowering::lowerGlobalAddress(SDValue Op, return getAddrGlobal( N, SDLoc(N), Ty, DAG, - (ABI.IsN32() || ABI.IsN64()) ? MipsII::MO_GOT_DISP : MipsII::MO_GOT16, + (ABI.IsN32() || ABI.IsN64()) ? MipsII::MO_GOT_DISP : MipsII::MO_GOT, DAG.getEntryNode(), MachinePointerInfo::getGOT(DAG.getMachineFunction())); } @@ -1699,7 +1794,7 @@ SDValue MipsTargetLowering::lowerBlockAddress(SDValue Op, BlockAddressSDNode *N = cast<BlockAddressSDNode>(Op); EVT Ty = Op.getValueType(); - if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !ABI.IsN64()) + if (!isPositionIndependent() && !ABI.IsN64()) return getAddrNonPIC(N, SDLoc(N), Ty, DAG); return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64()); @@ -1743,7 +1838,7 @@ lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const TargetLowering::CallLoweringInfo CLI(DAG); CLI.setDebugLoc(DL).setChain(DAG.getEntryNode()) - .setCallee(CallingConv::C, PtrTy, TlsGetAddr, std::move(Args), 0); + .setCallee(CallingConv::C, PtrTy, TlsGetAddr, std::move(Args)); std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI); SDValue Ret = CallResult.first; @@ -1768,9 +1863,8 @@ lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const MipsII::MO_GOTTPREL); TGA = DAG.getNode(MipsISD::Wrapper, DL, PtrVT, getGlobalReg(DAG, PtrVT), TGA); - Offset = DAG.getLoad(PtrVT, DL, - DAG.getEntryNode(), TGA, MachinePointerInfo(), - false, false, false, 0); + Offset = + DAG.getLoad(PtrVT, DL, DAG.getEntryNode(), TGA, MachinePointerInfo()); } else { // Local Exec TLS Model assert(model == TLSModel::LocalExec); @@ -1793,7 +1887,7 @@ lowerJumpTable(SDValue Op, SelectionDAG &DAG) const JumpTableSDNode *N = cast<JumpTableSDNode>(Op); EVT Ty = Op.getValueType(); - if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !ABI.IsN64()) + if (!isPositionIndependent() && !ABI.IsN64()) return getAddrNonPIC(N, SDLoc(N), Ty, DAG); return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64()); @@ -1805,7 +1899,7 @@ lowerConstantPool(SDValue Op, SelectionDAG &DAG) const ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op); EVT Ty = Op.getValueType(); - if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !ABI.IsN64()) { + if (!isPositionIndependent() && !ABI.IsN64()) { const MipsTargetObjectFile *TLOF = static_cast<const MipsTargetObjectFile *>( getTargetMachine().getObjFileLowering()); @@ -1833,7 +1927,7 @@ SDValue MipsTargetLowering::lowerVASTART(SDValue Op, SelectionDAG &DAG) const { // memory location argument. const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue(); return DAG.getStore(Op.getOperand(0), DL, FI, Op.getOperand(1), - MachinePointerInfo(SV), false, false, 0); + MachinePointerInfo(SV)); } SDValue MipsTargetLowering::lowerVAARG(SDValue Op, SelectionDAG &DAG) const { @@ -1846,9 +1940,8 @@ SDValue MipsTargetLowering::lowerVAARG(SDValue Op, SelectionDAG &DAG) const { SDLoc DL(Node); unsigned ArgSlotSizeInBytes = (ABI.IsN32() || ABI.IsN64()) ? 8 : 4; - SDValue VAListLoad = - DAG.getLoad(getPointerTy(DAG.getDataLayout()), DL, Chain, VAListPtr, - MachinePointerInfo(SV), false, false, false, 0); + SDValue VAListLoad = DAG.getLoad(getPointerTy(DAG.getDataLayout()), DL, Chain, + VAListPtr, MachinePointerInfo(SV)); SDValue VAList = VAListLoad; // Re-align the pointer if necessary. @@ -1873,13 +1966,13 @@ SDValue MipsTargetLowering::lowerVAARG(SDValue Op, SelectionDAG &DAG) const { auto &TD = DAG.getDataLayout(); unsigned ArgSizeInBytes = TD.getTypeAllocSize(VT.getTypeForEVT(*DAG.getContext())); - SDValue Tmp3 = DAG.getNode(ISD::ADD, DL, VAList.getValueType(), VAList, - DAG.getConstant(RoundUpToAlignment(ArgSizeInBytes, - ArgSlotSizeInBytes), - DL, VAList.getValueType())); + SDValue Tmp3 = + DAG.getNode(ISD::ADD, DL, VAList.getValueType(), VAList, + DAG.getConstant(alignTo(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); + MachinePointerInfo(SV)); // In big-endian mode we must adjust the pointer when the load size is smaller // than the argument slot size. We must also reduce the known alignment to @@ -1892,8 +1985,7 @@ SDValue MipsTargetLowering::lowerVAARG(SDValue Op, SelectionDAG &DAG) const { DAG.getIntPtrConstant(Adjustment, DL)); } // Load the actual argument out of the pointer VAList - return DAG.getLoad(VT, DL, Chain, VAList, MachinePointerInfo(), false, false, - false, 0); + return DAG.getLoad(VT, DL, Chain, VAList, MachinePointerInfo()); } static SDValue lowerFCOPYSIGN32(SDValue Op, SelectionDAG &DAG, @@ -2283,10 +2375,9 @@ static SDValue lowerFP_TO_SINT_STORE(StoreSDNode *SD, SelectionDAG &DAG) { EVT FPTy = EVT::getFloatingPointVT(Val.getValueSizeInBits()); SDValue Tr = DAG.getNode(MipsISD::TruncIntFP, SDLoc(Val), FPTy, Val.getOperand(0)); - return DAG.getStore(SD->getChain(), SDLoc(SD), Tr, SD->getBasePtr(), - SD->getPointerInfo(), SD->isVolatile(), - SD->isNonTemporal(), SD->getAlignment()); + SD->getPointerInfo(), SD->getAlignment(), + SD->getMemOperand()->getFlags()); } SDValue MipsTargetLowering::lowerSTORE(SDValue Op, SelectionDAG &DAG) const { @@ -2472,23 +2563,22 @@ static unsigned getNextIntArgReg(unsigned Reg) { return (Reg == Mips::A0) ? Mips::A1 : Mips::A3; } -SDValue -MipsTargetLowering::passArgOnStack(SDValue StackPtr, unsigned Offset, - SDValue Chain, SDValue Arg, SDLoc DL, - bool IsTailCall, SelectionDAG &DAG) const { +SDValue MipsTargetLowering::passArgOnStack(SDValue StackPtr, unsigned Offset, + SDValue Chain, SDValue Arg, + const SDLoc &DL, bool IsTailCall, + SelectionDAG &DAG) const { if (!IsTailCall) { SDValue PtrOff = DAG.getNode(ISD::ADD, DL, getPointerTy(DAG.getDataLayout()), StackPtr, DAG.getIntPtrConstant(Offset, DL)); - return DAG.getStore(Chain, DL, Arg, PtrOff, MachinePointerInfo(), false, - false, 0); + return DAG.getStore(Chain, DL, Arg, PtrOff, MachinePointerInfo()); } MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo(); int FI = MFI->CreateFixedObject(Arg.getValueSizeInBits() / 8, Offset, false); SDValue FIN = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); return DAG.getStore(Chain, DL, Arg, FIN, MachinePointerInfo(), - /*isVolatile=*/ true, false, 0); + /* Alignment = */ 0, MachineMemOperand::MOVolatile); } void MipsTargetLowering:: @@ -2571,7 +2661,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, MachineFrameInfo *MFI = MF.getFrameInfo(); const TargetFrameLowering *TFL = Subtarget.getFrameLowering(); MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>(); - bool IsPIC = getTargetMachine().getRelocationModel() == Reloc::PIC_; + bool IsPIC = isPositionIndependent(); // Analyze operands of the call, assigning locations to each operand. SmallVector<CCValAssign, 16> ArgLocs; @@ -2604,7 +2694,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, // ByValChain is the output chain of the last Memcpy node created for copying // byval arguments to the stack. unsigned StackAlignment = TFL->getStackAlignment(); - NextStackOffset = RoundUpToAlignment(NextStackOffset, StackAlignment); + NextStackOffset = alignTo(NextStackOffset, StackAlignment); SDValue NextStackOffsetVal = DAG.getIntPtrConstant(NextStackOffset, DL, true); if (!IsTailCall) @@ -2614,7 +2704,6 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, DAG.getCopyFromReg(Chain, DL, ABI.IsN64() ? Mips::SP_64 : Mips::SP, getPointerTy(DAG.getDataLayout())); - // With EABI is it possible to have 16 args on registers. std::deque< std::pair<unsigned, SDValue> > RegsToPass; SmallVector<SDValue, 8> MemOpChains; @@ -2802,8 +2891,8 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, /// appropriate copies out of appropriate physical registers. SDValue MipsTargetLowering::LowerCallResult( SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, bool IsVarArg, - const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc DL, SelectionDAG &DAG, - SmallVectorImpl<SDValue> &InVals, + const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL, + SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals, TargetLowering::CallLoweringInfo &CLI) const { // Assign locations to each value returned by this call. SmallVector<CCValAssign, 16> RVLocs; @@ -2864,7 +2953,8 @@ SDValue MipsTargetLowering::LowerCallResult( } static SDValue UnpackFromArgumentSlot(SDValue Val, const CCValAssign &VA, - EVT ArgVT, SDLoc DL, SelectionDAG &DAG) { + EVT ArgVT, const SDLoc &DL, + SelectionDAG &DAG) { MVT LocVT = VA.getLocVT(); EVT ValVT = VA.getValVT(); @@ -2922,14 +3012,10 @@ static SDValue UnpackFromArgumentSlot(SDValue Val, const CCValAssign &VA, //===----------------------------------------------------------------------===// /// LowerFormalArguments - transform physical registers into virtual registers /// and generate load operations for arguments places on the stack. -SDValue -MipsTargetLowering::LowerFormalArguments(SDValue Chain, - CallingConv::ID CallConv, - bool IsVarArg, - const SmallVectorImpl<ISD::InputArg> &Ins, - SDLoc DL, SelectionDAG &DAG, - SmallVectorImpl<SDValue> &InVals) - const { +SDValue MipsTargetLowering::LowerFormalArguments( + SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, + const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL, + SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const { MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); @@ -3037,8 +3123,7 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain, SDValue FIN = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); SDValue ArgValue = DAG.getLoad( LocVT, DL, Chain, FIN, - MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI), - false, false, false, 0); + MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI)); OutChains.push_back(ArgValue.getValue(1)); ArgValue = UnpackFromArgumentSlot(ArgValue, VA, Ins[i].ArgVT, DL, DAG); @@ -3102,7 +3187,8 @@ MipsTargetLowering::shouldSignExtendTypeInLibCall(EVT Type, bool IsSigned) const SDValue MipsTargetLowering::LowerInterruptReturn(SmallVectorImpl<SDValue> &RetOps, - SDLoc DL, SelectionDAG &DAG) const { + const SDLoc &DL, + SelectionDAG &DAG) const { MachineFunction &MF = DAG.getMachineFunction(); MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); @@ -3117,7 +3203,7 @@ MipsTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<SDValue> &OutVals, - SDLoc DL, SelectionDAG &DAG) const { + const SDLoc &DL, SelectionDAG &DAG) const { // CCValAssign - represent the assignment of // the return value to a location SmallVector<CCValAssign, 16> RVLocs; @@ -3625,10 +3711,11 @@ bool MipsTargetLowering::useSoftFloat() const { } void MipsTargetLowering::copyByValRegs( - SDValue Chain, SDLoc DL, std::vector<SDValue> &OutChains, SelectionDAG &DAG, - const ISD::ArgFlagsTy &Flags, SmallVectorImpl<SDValue> &InVals, - const Argument *FuncArg, unsigned FirstReg, unsigned LastReg, - const CCValAssign &VA, MipsCCState &State) const { + SDValue Chain, const SDLoc &DL, std::vector<SDValue> &OutChains, + SelectionDAG &DAG, const ISD::ArgFlagsTy &Flags, + SmallVectorImpl<SDValue> &InVals, const Argument *FuncArg, + unsigned FirstReg, unsigned LastReg, const CCValAssign &VA, + MipsCCState &State) const { MachineFunction &MF = DAG.getMachineFunction(); MachineFrameInfo *MFI = MF.getFrameInfo(); unsigned GPRSizeInBytes = Subtarget.getGPRSizeInBytes(); @@ -3665,15 +3752,14 @@ void MipsTargetLowering::copyByValRegs( SDValue StorePtr = DAG.getNode(ISD::ADD, DL, PtrTy, FIN, DAG.getConstant(Offset, DL, PtrTy)); SDValue Store = DAG.getStore(Chain, DL, DAG.getRegister(VReg, RegTy), - StorePtr, MachinePointerInfo(FuncArg, Offset), - false, false, 0); + StorePtr, MachinePointerInfo(FuncArg, Offset)); OutChains.push_back(Store); } } // Copy byVal arg to registers and stack. void MipsTargetLowering::passByValArg( - SDValue Chain, SDLoc DL, + SDValue Chain, const SDLoc &DL, std::deque<std::pair<unsigned, SDValue>> &RegsToPass, SmallVectorImpl<SDValue> &MemOpChains, SDValue StackPtr, MachineFrameInfo *MFI, SelectionDAG &DAG, SDValue Arg, unsigned FirstReg, @@ -3697,8 +3783,7 @@ void MipsTargetLowering::passByValArg( SDValue LoadPtr = DAG.getNode(ISD::ADD, DL, PtrTy, Arg, DAG.getConstant(OffsetInBytes, DL, PtrTy)); SDValue LoadVal = DAG.getLoad(RegTy, DL, Chain, LoadPtr, - MachinePointerInfo(), false, false, false, - Alignment); + MachinePointerInfo(), Alignment); MemOpChains.push_back(LoadVal.getValue(1)); unsigned ArgReg = ArgRegs[FirstReg + I]; RegsToPass.push_back(std::make_pair(ArgReg, LoadVal)); @@ -3725,8 +3810,7 @@ void MipsTargetLowering::passByValArg( PtrTy)); SDValue LoadVal = DAG.getExtLoad( ISD::ZEXTLOAD, DL, RegTy, Chain, LoadPtr, MachinePointerInfo(), - MVT::getIntegerVT(LoadSizeInBytes * 8), false, false, false, - Alignment); + MVT::getIntegerVT(LoadSizeInBytes * 8), Alignment); MemOpChains.push_back(LoadVal.getValue(1)); // Shift the loaded value. @@ -3771,7 +3855,7 @@ void MipsTargetLowering::passByValArg( } void MipsTargetLowering::writeVarArgRegs(std::vector<SDValue> &OutChains, - SDValue Chain, SDLoc DL, + SDValue Chain, const SDLoc &DL, SelectionDAG &DAG, CCState &State) const { ArrayRef<MCPhysReg> ArgRegs = ABI.GetVarArgRegs(); @@ -3787,8 +3871,7 @@ void MipsTargetLowering::writeVarArgRegs(std::vector<SDValue> &OutChains, int VaArgOffset; if (ArgRegs.size() == Idx) - VaArgOffset = - RoundUpToAlignment(State.getNextStackOffset(), RegSizeInBytes); + VaArgOffset = alignTo(State.getNextStackOffset(), RegSizeInBytes); else { VaArgOffset = (int)ABI.GetCalleeAllocdArgSizeInBytes(State.getCallingConv()) - @@ -3810,8 +3893,8 @@ void MipsTargetLowering::writeVarArgRegs(std::vector<SDValue> &OutChains, SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, RegTy); FI = MFI->CreateFixedObject(RegSizeInBytes, VaArgOffset, true); SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); - SDValue Store = DAG.getStore(Chain, DL, ArgValue, PtrOff, - MachinePointerInfo(), false, false, 0); + SDValue Store = + DAG.getStore(Chain, DL, ArgValue, PtrOff, MachinePointerInfo()); cast<StoreSDNode>(Store.getNode())->getMemOperand()->setValue( (Value *)nullptr); OutChains.push_back(Store); @@ -3854,7 +3937,7 @@ void MipsTargetLowering::HandleByVal(CCState *State, unsigned &Size, } // Mark the registers allocated. - Size = RoundUpToAlignment(Size, RegSizeInBytes); + Size = alignTo(Size, RegSizeInBytes); for (unsigned I = FirstReg; Size > 0 && (I < IntArgRegs.size()); Size -= RegSizeInBytes, ++I, ++NumRegs) State->AllocateReg(IntArgRegs[I], ShadowRegs[I]); @@ -3863,16 +3946,17 @@ void MipsTargetLowering::HandleByVal(CCState *State, unsigned &Size, State->addInRegsParamInfo(FirstReg, FirstReg + NumRegs); } -MachineBasicBlock * -MipsTargetLowering::emitPseudoSELECT(MachineInstr *MI, MachineBasicBlock *BB, - bool isFPCmp, unsigned Opc) const { +MachineBasicBlock *MipsTargetLowering::emitPseudoSELECT(MachineInstr &MI, + MachineBasicBlock *BB, + bool isFPCmp, + unsigned Opc) const { assert(!(Subtarget.hasMips4() || Subtarget.hasMips32()) && "Subtarget already supports SELECT nodes with the use of" "conditional-move instructions."); const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - DebugLoc DL = MI->getDebugLoc(); + DebugLoc DL = MI.getDebugLoc(); // To "insert" a SELECT instruction, we actually have to insert the // diamond control-flow pattern. The incoming instruction knows the @@ -3906,14 +3990,14 @@ MipsTargetLowering::emitPseudoSELECT(MachineInstr *MI, MachineBasicBlock *BB, if (isFPCmp) { // bc1[tf] cc, sinkMBB BuildMI(BB, DL, TII->get(Opc)) - .addReg(MI->getOperand(1).getReg()) - .addMBB(sinkMBB); + .addReg(MI.getOperand(1).getReg()) + .addMBB(sinkMBB); } else { // bne rs, $0, sinkMBB BuildMI(BB, DL, TII->get(Opc)) - .addReg(MI->getOperand(1).getReg()) - .addReg(Mips::ZERO) - .addMBB(sinkMBB); + .addReg(MI.getOperand(1).getReg()) + .addReg(Mips::ZERO) + .addMBB(sinkMBB); } // copy0MBB: @@ -3929,12 +4013,13 @@ MipsTargetLowering::emitPseudoSELECT(MachineInstr *MI, MachineBasicBlock *BB, // ... BB = sinkMBB; - BuildMI(*BB, BB->begin(), DL, - TII->get(Mips::PHI), MI->getOperand(0).getReg()) - .addReg(MI->getOperand(2).getReg()).addMBB(thisMBB) - .addReg(MI->getOperand(3).getReg()).addMBB(copy0MBB); + BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(0).getReg()) + .addReg(MI.getOperand(2).getReg()) + .addMBB(thisMBB) + .addReg(MI.getOperand(3).getReg()) + .addMBB(copy0MBB); - MI->eraseFromParent(); // The pseudo instruction is gone now. + MI.eraseFromParent(); // The pseudo instruction is gone now. return BB; } diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h index 0dc683e3df27f..182dc9070fc8a 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -238,6 +238,10 @@ namespace llvm { bool isCheapToSpeculateCttz() const override; bool isCheapToSpeculateCtlz() const override; + ISD::NodeType getExtendForAtomicOps() const override { + return ISD::SIGN_EXTEND; + } + void LowerOperationWrapper(SDNode *N, SmallVectorImpl<SDValue> &Results, SelectionDAG &DAG) const override; @@ -262,7 +266,7 @@ namespace llvm { SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override; MachineBasicBlock * - EmitInstrWithCustomInserter(MachineInstr *MI, + EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const override; void HandleByVal(CCState *, unsigned &, unsigned) const override; @@ -300,15 +304,14 @@ namespace llvm { // // (add (load (wrapper $gp, %got(sym)), %lo(sym)) template <class NodeTy> - SDValue getAddrLocal(NodeTy *N, SDLoc DL, EVT Ty, SelectionDAG &DAG, + SDValue getAddrLocal(NodeTy *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG, bool IsN32OrN64) const { unsigned GOTFlag = IsN32OrN64 ? MipsII::MO_GOT_PAGE : MipsII::MO_GOT; SDValue GOT = DAG.getNode(MipsISD::Wrapper, DL, Ty, getGlobalReg(DAG, Ty), getTargetNode(N, Ty, DAG, GOTFlag)); SDValue Load = DAG.getLoad(Ty, DL, DAG.getEntryNode(), GOT, - MachinePointerInfo::getGOT(DAG.getMachineFunction()), - false, false, false, 0); + MachinePointerInfo::getGOT(DAG.getMachineFunction())); unsigned LoFlag = IsN32OrN64 ? MipsII::MO_GOT_OFST : MipsII::MO_ABS_LO; SDValue Lo = DAG.getNode(MipsISD::Lo, DL, Ty, getTargetNode(N, Ty, DAG, LoFlag)); @@ -320,12 +323,12 @@ namespace llvm { // // (load (wrapper $gp, %got(sym))) template <class NodeTy> - SDValue getAddrGlobal(NodeTy *N, SDLoc DL, EVT Ty, SelectionDAG &DAG, + SDValue getAddrGlobal(NodeTy *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG, unsigned Flag, SDValue Chain, const MachinePointerInfo &PtrInfo) const { SDValue Tgt = DAG.getNode(MipsISD::Wrapper, DL, Ty, getGlobalReg(DAG, Ty), getTargetNode(N, Ty, DAG, Flag)); - return DAG.getLoad(Ty, DL, Chain, Tgt, PtrInfo, false, false, false, 0); + return DAG.getLoad(Ty, DL, Chain, Tgt, PtrInfo); } // This method creates the following nodes, which are necessary for @@ -333,7 +336,7 @@ namespace llvm { // // (load (wrapper (add %hi(sym), $gp), %lo(sym))) template <class NodeTy> - SDValue getAddrGlobalLargeGOT(NodeTy *N, SDLoc DL, EVT Ty, + SDValue getAddrGlobalLargeGOT(NodeTy *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG, unsigned HiFlag, unsigned LoFlag, SDValue Chain, const MachinePointerInfo &PtrInfo) const { @@ -342,8 +345,7 @@ namespace llvm { Hi = DAG.getNode(ISD::ADD, DL, Ty, Hi, getGlobalReg(DAG, Ty)); SDValue Wrapper = DAG.getNode(MipsISD::Wrapper, DL, Ty, Hi, getTargetNode(N, Ty, DAG, LoFlag)); - return DAG.getLoad(Ty, DL, Chain, Wrapper, PtrInfo, false, false, false, - 0); + return DAG.getLoad(Ty, DL, Chain, Wrapper, PtrInfo); } // This method creates the following nodes, which are necessary for @@ -351,7 +353,7 @@ namespace llvm { // // (add %hi(sym), %lo(sym)) template <class NodeTy> - SDValue getAddrNonPIC(NodeTy *N, SDLoc DL, EVT Ty, + SDValue getAddrNonPIC(NodeTy *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG) const { SDValue Hi = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_HI); SDValue Lo = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_LO); @@ -365,7 +367,8 @@ namespace llvm { // // (add $gp, %gp_rel(sym)) template <class NodeTy> - SDValue getAddrGPRel(NodeTy *N, SDLoc DL, EVT Ty, SelectionDAG &DAG) const { + SDValue getAddrGPRel(NodeTy *N, const SDLoc &DL, EVT Ty, + SelectionDAG &DAG) const { assert(Ty == MVT::i32); SDValue GPRel = getTargetNode(N, Ty, DAG, MipsII::MO_GPREL); return DAG.getNode(ISD::ADD, DL, Ty, @@ -417,8 +420,9 @@ namespace llvm { // Lower Operand helpers SDValue LowerCallResult(SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, bool isVarArg, - const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc dl, - SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals, + const SmallVectorImpl<ISD::InputArg> &Ins, + const SDLoc &dl, SelectionDAG &DAG, + SmallVectorImpl<SDValue> &InVals, TargetLowering::CallLoweringInfo &CLI) const; // Lower Operand specifics @@ -455,15 +459,16 @@ namespace llvm { /// copyByValArg - Copy argument registers which were used to pass a byval /// argument to the stack. Create a stack frame object for the byval /// argument. - void copyByValRegs(SDValue Chain, SDLoc DL, std::vector<SDValue> &OutChains, - SelectionDAG &DAG, const ISD::ArgFlagsTy &Flags, + void copyByValRegs(SDValue Chain, const SDLoc &DL, + std::vector<SDValue> &OutChains, SelectionDAG &DAG, + const ISD::ArgFlagsTy &Flags, SmallVectorImpl<SDValue> &InVals, const Argument *FuncArg, unsigned FirstReg, unsigned LastReg, const CCValAssign &VA, MipsCCState &State) const; /// passByValArg - Pass a byval argument in registers or on stack. - void passByValArg(SDValue Chain, SDLoc DL, + void passByValArg(SDValue Chain, const SDLoc &DL, std::deque<std::pair<unsigned, SDValue>> &RegsToPass, SmallVectorImpl<SDValue> &MemOpChains, SDValue StackPtr, MachineFrameInfo *MFI, SelectionDAG &DAG, SDValue Arg, @@ -475,17 +480,17 @@ namespace llvm { /// to the stack. Also create a stack frame object for the first variable /// argument. void writeVarArgRegs(std::vector<SDValue> &OutChains, SDValue Chain, - SDLoc DL, SelectionDAG &DAG, CCState &State) const; + const SDLoc &DL, SelectionDAG &DAG, + CCState &State) const; SDValue - LowerFormalArguments(SDValue Chain, - CallingConv::ID CallConv, bool isVarArg, - const SmallVectorImpl<ISD::InputArg> &Ins, - SDLoc dl, SelectionDAG &DAG, - SmallVectorImpl<SDValue> &InVals) const override; + LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, + const SmallVectorImpl<ISD::InputArg> &Ins, + const SDLoc &dl, SelectionDAG &DAG, + SmallVectorImpl<SDValue> &InVals) const override; SDValue passArgOnStack(SDValue StackPtr, unsigned Offset, SDValue Chain, - SDValue Arg, SDLoc DL, bool IsTailCall, + SDValue Arg, const SDLoc &DL, bool IsTailCall, SelectionDAG &DAG) const; SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, @@ -496,14 +501,13 @@ namespace llvm { const SmallVectorImpl<ISD::OutputArg> &Outs, LLVMContext &Context) const override; - SDValue LowerReturn(SDValue Chain, - CallingConv::ID CallConv, bool isVarArg, + SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg, const SmallVectorImpl<ISD::OutputArg> &Outs, const SmallVectorImpl<SDValue> &OutVals, - SDLoc dl, SelectionDAG &DAG) const override; + const SDLoc &dl, SelectionDAG &DAG) const override; - SDValue LowerInterruptReturn(SmallVectorImpl<SDValue> &RetOps, SDLoc DL, - SelectionDAG &DAG) const; + SDValue LowerInterruptReturn(SmallVectorImpl<SDValue> &RetOps, + const SDLoc &DL, SelectionDAG &DAG) const; bool shouldSignExtendTypeInLibCall(EVT Type, bool IsSigned) const override; @@ -561,25 +565,33 @@ namespace llvm { unsigned getJumpTableEncoding() const override; bool useSoftFloat() const override; + bool shouldInsertFencesForAtomic(const Instruction *I) const override { + return true; + } + /// Emit a sign-extension using sll/sra, seb, or seh appropriately. - MachineBasicBlock *emitSignExtendToI32InReg(MachineInstr *MI, + MachineBasicBlock *emitSignExtendToI32InReg(MachineInstr &MI, MachineBasicBlock *BB, unsigned Size, unsigned DstReg, unsigned SrcRec) const; - MachineBasicBlock *emitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB, - unsigned Size, unsigned BinOpcode, bool Nand = false) const; - MachineBasicBlock *emitAtomicBinaryPartword(MachineInstr *MI, - MachineBasicBlock *BB, unsigned Size, unsigned BinOpcode, - bool Nand = false) const; - MachineBasicBlock *emitAtomicCmpSwap(MachineInstr *MI, - MachineBasicBlock *BB, unsigned Size) const; - MachineBasicBlock *emitAtomicCmpSwapPartword(MachineInstr *MI, - MachineBasicBlock *BB, unsigned Size) const; - MachineBasicBlock *emitSEL_D(MachineInstr *MI, MachineBasicBlock *BB) const; - MachineBasicBlock *emitPseudoSELECT(MachineInstr *MI, - MachineBasicBlock *BB, bool isFPCmp, - unsigned Opc) const; + MachineBasicBlock *emitAtomicBinary(MachineInstr &MI, MachineBasicBlock *BB, + unsigned Size, unsigned BinOpcode, + bool Nand = false) const; + MachineBasicBlock *emitAtomicBinaryPartword(MachineInstr &MI, + MachineBasicBlock *BB, + unsigned Size, + unsigned BinOpcode, + bool Nand = false) const; + MachineBasicBlock *emitAtomicCmpSwap(MachineInstr &MI, + MachineBasicBlock *BB, + unsigned Size) const; + MachineBasicBlock *emitAtomicCmpSwapPartword(MachineInstr &MI, + MachineBasicBlock *BB, + unsigned Size) const; + MachineBasicBlock *emitSEL_D(MachineInstr &MI, MachineBasicBlock *BB) const; + MachineBasicBlock *emitPseudoSELECT(MachineInstr &MI, MachineBasicBlock *BB, + bool isFPCmp, unsigned Opc) const; }; /// Create MipsTargetLowering objects. diff --git a/lib/Target/Mips/MipsInstrFPU.td b/lib/Target/Mips/MipsInstrFPU.td index 377260f89d10e..87b02bdfdfdb2 100644 --- a/lib/Target/Mips/MipsInstrFPU.td +++ b/lib/Target/Mips/MipsInstrFPU.td @@ -160,18 +160,18 @@ class MTC1_64_FT<string opstr, RegisterOperand DstRC, RegisterOperand SrcRC, let Constraints = "$fs = $fs_in"; } -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"), +class LW_FT<string opstr, RegisterOperand RC, DAGOperand MO, + InstrItinClass Itin, SDPatternOperator OpNode = null_frag> : + InstSE<(outs RC:$rt), (ins MO:$addr), !strconcat(opstr, "\t$rt, $addr"), [(set RC:$rt, (OpNode addrDefault:$addr))], Itin, FrmFI, opstr>, HARDFLOAT { let DecoderMethod = "DecodeFMem"; let mayLoad = 1; } -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"), +class SW_FT<string opstr, RegisterOperand RC, DAGOperand MO, + InstrItinClass Itin, SDPatternOperator OpNode = null_frag> : + InstSE<(outs), (ins RC:$rt, MO:$addr), !strconcat(opstr, "\t$rt, $addr"), [(OpNode RC:$rt, addrDefault:$addr)], Itin, FrmFI, opstr>, HARDFLOAT { let DecoderMethod = "DecodeFMem"; let mayStore = 1; @@ -367,22 +367,28 @@ def MFC1 : MMRel, MFC1_FT<"mfc1", GPR32Opnd, FGR32Opnd, II_MFC1, bitconvert>, MFC1_FM<0>; 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, FGR_32; -def MFHC1_D64 : MFC1_FT<"mfhc1", GPR32Opnd, FGR64Opnd, II_MFHC1>, - 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, FGR_32; -def MTHC1_D64 : MTC1_64_FT<"mthc1", FGR64Opnd, GPR32Opnd, II_MTHC1>, - MFC1_FM<7>, ISA_MIPS32R2, FGR_64 { - let DecoderNamespace = "Mips64"; -} -def DMFC1 : MFC1_FT<"dmfc1", GPR64Opnd, FGR64Opnd, II_DMFC1, - bitconvert>, MFC1_FM<1>, ISA_MIPS3; -def DMTC1 : MTC1_FT<"dmtc1", FGR64Opnd, GPR64Opnd, II_DMTC1, - bitconvert>, MFC1_FM<5>, ISA_MIPS3; +let AdditionalPredicates = [NotInMicroMips] in { + def MFHC1_D32 : MMRel, MFC1_FT<"mfhc1", GPR32Opnd, AFGR64Opnd, II_MFHC1>, + MFC1_FM<3>, ISA_MIPS32R2, FGR_32; + def MFHC1_D64 : MFC1_FT<"mfhc1", GPR32Opnd, FGR64Opnd, II_MFHC1>, + MFC1_FM<3>, ISA_MIPS32R2, FGR_64 { + let DecoderNamespace = "Mips64"; + } +} +let AdditionalPredicates = [NotInMicroMips] in { + def MTHC1_D32 : MMRel, StdMMR6Rel, MTC1_64_FT<"mthc1", AFGR64Opnd, GPR32Opnd, II_MTHC1>, + MFC1_FM<7>, ISA_MIPS32R2, FGR_32; + def MTHC1_D64 : MTC1_64_FT<"mthc1", FGR64Opnd, GPR32Opnd, II_MTHC1>, + MFC1_FM<7>, ISA_MIPS32R2, FGR_64 { + let DecoderNamespace = "Mips64"; + } +} +let AdditionalPredicates = [NotInMicroMips] in { + def DMTC1 : MTC1_FT<"dmtc1", FGR64Opnd, GPR64Opnd, II_DMTC1, + bitconvert>, MFC1_FM<5>, ISA_MIPS3; + def DMFC1 : MFC1_FT<"dmfc1", GPR64Opnd, FGR64Opnd, II_DMFC1, + bitconvert>, MFC1_FM<1>, ISA_MIPS3; +} def FMOV_S : MMRel, ABSS_FT<"mov.s", FGR32Opnd, FGR32Opnd, II_MOV_S>, ABSS_FM<0x6, 16>; @@ -394,20 +400,30 @@ def FMOV_D64 : ABSS_FT<"mov.d", FGR64Opnd, FGR64Opnd, II_MOV_D>, } /// Floating Point Memory Instructions -def LWC1 : MMRel, LW_FT<"lwc1", FGR32Opnd, II_LWC1, load>, LW_FM<0x31>; -def SWC1 : MMRel, SW_FT<"swc1", FGR32Opnd, II_SWC1, store>, LW_FM<0x39>; +let AdditionalPredicates = [NotInMicroMips] in { + def LWC1 : MMRel, LW_FT<"lwc1", FGR32Opnd, mem_simm16, II_LWC1, load>, + LW_FM<0x31>; + def SWC1 : MMRel, SW_FT<"swc1", FGR32Opnd, mem_simm16, II_SWC1, store>, + LW_FM<0x39>; +} -let DecoderNamespace = "Mips64" in { - def LDC164 : LW_FT<"ldc1", FGR64Opnd, II_LDC1, load>, LW_FM<0x35>, ISA_MIPS2, - FGR_64; - def SDC164 : SW_FT<"sdc1", FGR64Opnd, II_SDC1, store>, LW_FM<0x3d>, ISA_MIPS2, - FGR_64; +let DecoderNamespace = "Mips64", AdditionalPredicates = [NotInMicroMips] in { + def LDC164 : StdMMR6Rel, LW_FT<"ldc1", FGR64Opnd, mem_simm16, II_LDC1, load>, + LW_FM<0x35>, ISA_MIPS2, FGR_64 { + let BaseOpcode = "LDC164"; + } + def SDC164 : StdMMR6Rel, SW_FT<"sdc1", FGR64Opnd, mem_simm16, II_SDC1, store>, + LW_FM<0x3d>, ISA_MIPS2, FGR_64; } -def LDC1 : MMRel, LW_FT<"ldc1", AFGR64Opnd, II_LDC1, load>, LW_FM<0x35>, - ISA_MIPS2, FGR_32; -def SDC1 : MMRel, SW_FT<"sdc1", AFGR64Opnd, II_SDC1, store>, LW_FM<0x3d>, - ISA_MIPS2, FGR_32; +let AdditionalPredicates = [NotInMicroMips] in { + def LDC1 : MMRel, StdMMR6Rel, LW_FT<"ldc1", AFGR64Opnd, mem_simm16, II_LDC1, + load>, LW_FM<0x35>, ISA_MIPS2, FGR_32 { + let BaseOpcode = "LDC132"; + } + def SDC1 : MMRel, SW_FT<"sdc1", AFGR64Opnd, mem_simm16, II_SDC1, store>, + LW_FM<0x3d>, ISA_MIPS2, FGR_32; +} // Indexed loads and stores. // Base register + offset register addressing mode (indicated by "x" in the @@ -519,10 +535,12 @@ def BC1TL : MMRel, BC1F_FT<"bc1tl", brtarget, II_BC1TL, MIPS_BRANCH_T, 0>, BC1F_FM<1, 1>, ISA_MIPS2_NOT_32R6_64R6; /// 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, FGR_32; +let AdditionalPredicates = [NotInMicroMips] in { + 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, 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, FGR_64; @@ -535,7 +553,8 @@ def FCMP_D64 : CEQS_FT<"d", FGR64, II_C_CC_D, MipsFPCmp>, CEQS_FM<17>, // allocation. class BuildPairF64Base<RegisterOperand RO> : PseudoSE<(outs RO:$dst), (ins GPR32Opnd:$lo, GPR32Opnd:$hi), - [(set RO:$dst, (MipsBuildPairF64 GPR32Opnd:$lo, GPR32Opnd:$hi))]>; + [(set RO:$dst, (MipsBuildPairF64 GPR32Opnd:$lo, GPR32Opnd:$hi))], + II_MTC1>; def BuildPairF64 : BuildPairF64Base<AFGR64Opnd>, FGR_32, HARDFLOAT; def BuildPairF64_64 : BuildPairF64Base<FGR64Opnd>, FGR_64, HARDFLOAT; @@ -544,13 +563,30 @@ def BuildPairF64_64 : BuildPairF64Base<FGR64Opnd>, FGR_64, HARDFLOAT; // allocation. // if n is 0, lower part of src is extracted. // if n is 1, higher part of src is extracted. +// This node has associated scheduling information as the pre RA scheduler +// asserts otherwise. class ExtractElementF64Base<RegisterOperand RO> : PseudoSE<(outs GPR32Opnd:$dst), (ins RO:$src, i32imm:$n), - [(set GPR32Opnd:$dst, (MipsExtractElementF64 RO:$src, imm:$n))]>; + [(set GPR32Opnd:$dst, (MipsExtractElementF64 RO:$src, imm:$n))], + II_MFC1>; def ExtractElementF64 : ExtractElementF64Base<AFGR64Opnd>, FGR_32, HARDFLOAT; def ExtractElementF64_64 : ExtractElementF64Base<FGR64Opnd>, FGR_64, HARDFLOAT; +def PseudoTRUNC_W_S : MipsAsmPseudoInst<(outs FGR32Opnd:$fd), + (ins FGR32Opnd:$fs, GPR32Opnd:$rs), + "trunc.w.s\t$fd, $fs, $rs">; + +def PseudoTRUNC_W_D32 : MipsAsmPseudoInst<(outs FGR32Opnd:$fd), + (ins AFGR64Opnd:$fs, GPR32Opnd:$rs), + "trunc.w.d\t$fd, $fs, $rs">, + FGR_32, HARDFLOAT; + +def PseudoTRUNC_W_D : MipsAsmPseudoInst<(outs FGR32Opnd:$fd), + (ins FGR64Opnd:$fs, GPR32Opnd:$rs), + "trunc.w.d\t$fd, $fs, $rs">, + FGR_64, HARDFLOAT; + //===----------------------------------------------------------------------===// // InstAliases. //===----------------------------------------------------------------------===// @@ -606,13 +642,15 @@ def : MipsPat<(f64 (fextend FGR32Opnd:$src)), (CVT_D64_S FGR32Opnd:$src)>, FGR_64; // Patterns for loads/stores with a reg+imm operand. -let AddedComplexity = 40 in { - def : LoadRegImmPat<LWC1, f32, load>; - def : StoreRegImmPat<SWC1, f32>; +let AdditionalPredicates = [NotInMicroMips] in { + let AddedComplexity = 40 in { + def : LoadRegImmPat<LWC1, f32, load>; + def : StoreRegImmPat<SWC1, f32>; - def : LoadRegImmPat<LDC164, f64, load>, FGR_64; - def : StoreRegImmPat<SDC164, f64>, FGR_64; + def : LoadRegImmPat<LDC164, f64, load>, FGR_64; + def : StoreRegImmPat<SDC164, f64>, FGR_64; - def : LoadRegImmPat<LDC1, f64, load>, FGR_32; - def : StoreRegImmPat<SDC1, f64>, FGR_32; + def : LoadRegImmPat<LDC1, f64, load>, FGR_32; + def : StoreRegImmPat<SDC1, f64>, FGR_32; + } } diff --git a/lib/Target/Mips/MipsInstrFormats.td b/lib/Target/Mips/MipsInstrFormats.td index 45baf27be518f..0bbb49b6b08ea 100644 --- a/lib/Target/Mips/MipsInstrFormats.td +++ b/lib/Target/Mips/MipsInstrFormats.td @@ -94,10 +94,15 @@ class MipsInst<dag outs, dag ins, string asmstr, list<dag> pattern, // // Attributes specific to Mips instructions... // - bits<4> FormBits = Form.Value; + bits<4> FormBits = Form.Value; + bit isCTI = 0; // Any form of Control Transfer Instruction. + // Required for MIPSR6 + bit hasForbiddenSlot = 0; // Instruction has a forbidden slot. // TSFlags layout should be kept in sync with MipsInstrInfo.h. let TSFlags{3-0} = FormBits; + let TSFlags{4} = isCTI; + let TSFlags{5} = hasForbiddenSlot; let DecoderNamespace = "Mips"; diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp index b1d69506c16f2..800d834e0ab8e 100644 --- a/lib/Target/Mips/MipsInstrInfo.cpp +++ b/lib/Target/Mips/MipsInstrInfo.cpp @@ -13,7 +13,6 @@ #include "MipsInstrInfo.h" #include "InstPrinter/MipsInstPrinter.h" -#include "MipsAnalyzeImmediate.h" #include "MipsMachineFunction.h" #include "MipsSubtarget.h" #include "llvm/ADT/STLExtras.h" @@ -47,6 +46,7 @@ bool MipsInstrInfo::isZeroImm(const MachineOperand &op) const { /// insertNoop - If data hazard condition is found insert the target nop /// instruction. +// FIXME: This appears to be dead code. void MipsInstrInfo:: insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const { @@ -54,14 +54,15 @@ insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const BuildMI(MBB, MI, DL, get(Mips::NOP)); } -MachineMemOperand *MipsInstrInfo::GetMemOperand(MachineBasicBlock &MBB, int FI, - unsigned Flag) const { +MachineMemOperand * +MipsInstrInfo::GetMemOperand(MachineBasicBlock &MBB, int FI, + MachineMemOperand::Flags Flags) const { MachineFunction &MF = *MBB.getParent(); MachineFrameInfo &MFI = *MF.getFrameInfo(); unsigned Align = MFI.getObjectAlignment(FI); return MF.getMachineMemOperand(MachinePointerInfo::getFixedStack(MF, FI), - Flag, MFI.getObjectSize(FI), Align); + Flags, MFI.getObjectSize(FI), Align); } //===----------------------------------------------------------------------===// @@ -83,20 +84,20 @@ void MipsInstrInfo::AnalyzeCondBr(const MachineInstr *Inst, unsigned Opc, Cond.push_back(Inst->getOperand(i)); } -bool MipsInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, +bool MipsInstrInfo::analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl<MachineOperand> &Cond, bool AllowModify) const { SmallVector<MachineInstr*, 2> BranchInstrs; - BranchType BT = AnalyzeBranch(MBB, TBB, FBB, Cond, AllowModify, BranchInstrs); + BranchType BT = analyzeBranch(MBB, TBB, FBB, Cond, AllowModify, BranchInstrs); return (BT == BT_None) || (BT == BT_Indirect); } -void -MipsInstrInfo::BuildCondBr(MachineBasicBlock &MBB, MachineBasicBlock *TBB, - DebugLoc DL, ArrayRef<MachineOperand> Cond) const { +void MipsInstrInfo::BuildCondBr(MachineBasicBlock &MBB, MachineBasicBlock *TBB, + const DebugLoc &DL, + ArrayRef<MachineOperand> Cond) const { unsigned Opc = Cond[0].getImm(); const MCInstrDesc &MCID = get(Opc); MachineInstrBuilder MIB = BuildMI(&MBB, DL, MCID); @@ -107,14 +108,16 @@ MipsInstrInfo::BuildCondBr(MachineBasicBlock &MBB, MachineBasicBlock *TBB, else if (Cond[i].isImm()) MIB.addImm(Cond[i].getImm()); else - assert(true && "Cannot copy operand"); + assert(false && "Cannot copy operand"); } MIB.addMBB(TBB); } -unsigned MipsInstrInfo::InsertBranch( - MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, - ArrayRef<MachineOperand> Cond, DebugLoc DL) const { +unsigned MipsInstrInfo::InsertBranch(MachineBasicBlock &MBB, + MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + ArrayRef<MachineOperand> Cond, + const DebugLoc &DL) const { // Shouldn't be a fall through. assert(TBB && "InsertBranch must not be told to insert a fallthrough"); @@ -174,7 +177,7 @@ bool MipsInstrInfo::ReverseBranchCondition( return false; } -MipsInstrInfo::BranchType MipsInstrInfo::AnalyzeBranch( +MipsInstrInfo::BranchType MipsInstrInfo::analyzeBranch( MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl<MachineOperand> &Cond, bool AllowModify, SmallVectorImpl<MachineInstr *> &BranchInstrs) const { @@ -185,7 +188,7 @@ MipsInstrInfo::BranchType MipsInstrInfo::AnalyzeBranch( while (I != REnd && I->isDebugValue()) ++I; - if (I == REnd || !isUnpredicatedTerminator(&*I)) { + if (I == REnd || !isUnpredicatedTerminator(*I)) { // This block ends with no branches (it just falls through to its succ). // Leave TBB/FBB null. TBB = FBB = nullptr; @@ -209,14 +212,14 @@ MipsInstrInfo::BranchType MipsInstrInfo::AnalyzeBranch( SecondLastOpc = getAnalyzableBrOpc(SecondLastInst->getOpcode()); // Not an analyzable branch (must be an indirect jump). - if (isUnpredicatedTerminator(SecondLastInst) && !SecondLastOpc) + if (isUnpredicatedTerminator(*SecondLastInst) && !SecondLastOpc) return BT_None; } // If there is only one terminator instruction, process it. if (!SecondLastOpc) { // Unconditional branch. - if (LastOpc == UncondBrOpc) { + if (LastInst->isUnconditionalBranch()) { TBB = LastInst->getOperand(0).getMBB(); return BT_Uncond; } @@ -228,14 +231,14 @@ MipsInstrInfo::BranchType MipsInstrInfo::AnalyzeBranch( // If we reached here, there are two branches. // If there are three terminators, we don't know what sort of block this is. - if (++I != REnd && isUnpredicatedTerminator(&*I)) + if (++I != REnd && isUnpredicatedTerminator(*I)) return BT_None; BranchInstrs.insert(BranchInstrs.begin(), SecondLastInst); // If second to last instruction is an unconditional branch, // analyze it and remove the last instruction. - if (SecondLastOpc == UncondBrOpc) { + if (SecondLastInst->isUnconditionalBranch()) { // Return if the last instruction cannot be removed. if (!AllowModify) return BT_None; @@ -248,7 +251,7 @@ MipsInstrInfo::BranchType MipsInstrInfo::AnalyzeBranch( // Conditional branch followed by an unconditional branch. // The last one must be unconditional. - if (LastOpc != UncondBrOpc) + if (!LastInst->isUnconditionalBranch()) return BT_None; AnalyzeCondBr(SecondLastInst, SecondLastOpc, TBB, Cond); @@ -257,20 +260,137 @@ MipsInstrInfo::BranchType MipsInstrInfo::AnalyzeBranch( return BT_CondUncond; } +/// Return the corresponding compact (no delay slot) form of a branch. +unsigned MipsInstrInfo::getEquivalentCompactForm( + const MachineBasicBlock::iterator I) const { + unsigned Opcode = I->getOpcode(); + bool canUseShortMicroMipsCTI = false; + + if (Subtarget.inMicroMipsMode()) { + switch (Opcode) { + case Mips::BNE: + case Mips::BEQ: + // microMIPS has NE,EQ branches that do not have delay slots provided one + // of the operands is zero. + if (I->getOperand(1).getReg() == Subtarget.getABI().GetZeroReg()) + canUseShortMicroMipsCTI = true; + break; + // For microMIPS the PseudoReturn and PseudoIndirectBranch are always + // expanded to JR_MM, so they can be replaced with JRC16_MM. + case Mips::JR: + case Mips::PseudoReturn: + case Mips::PseudoIndirectBranch: + canUseShortMicroMipsCTI = true; + break; + } + } + + // MIPSR6 forbids both operands being the zero register. + if (Subtarget.hasMips32r6() && (I->getNumOperands() > 1) && + (I->getOperand(0).isReg() && + (I->getOperand(0).getReg() == Mips::ZERO || + I->getOperand(0).getReg() == Mips::ZERO_64)) && + (I->getOperand(1).isReg() && + (I->getOperand(1).getReg() == Mips::ZERO || + I->getOperand(1).getReg() == Mips::ZERO_64))) + return 0; + + if (Subtarget.hasMips32r6() || canUseShortMicroMipsCTI) { + switch (Opcode) { + case Mips::B: + return Mips::BC; + case Mips::BAL: + return Mips::BALC; + case Mips::BEQ: + if (canUseShortMicroMipsCTI) + return Mips::BEQZC_MM; + else if (I->getOperand(0).getReg() == I->getOperand(1).getReg()) + return 0; + return Mips::BEQC; + case Mips::BNE: + if (canUseShortMicroMipsCTI) + return Mips::BNEZC_MM; + else if (I->getOperand(0).getReg() == I->getOperand(1).getReg()) + return 0; + return Mips::BNEC; + case Mips::BGE: + if (I->getOperand(0).getReg() == I->getOperand(1).getReg()) + return 0; + return Mips::BGEC; + case Mips::BGEU: + if (I->getOperand(0).getReg() == I->getOperand(1).getReg()) + return 0; + return Mips::BGEUC; + case Mips::BGEZ: + return Mips::BGEZC; + case Mips::BGTZ: + return Mips::BGTZC; + case Mips::BLEZ: + return Mips::BLEZC; + case Mips::BLT: + if (I->getOperand(0).getReg() == I->getOperand(1).getReg()) + return 0; + return Mips::BLTC; + case Mips::BLTU: + if (I->getOperand(0).getReg() == I->getOperand(1).getReg()) + return 0; + return Mips::BLTUC; + case Mips::BLTZ: + return Mips::BLTZC; + // For MIPSR6, the instruction 'jic' can be used for these cases. Some + // tools will accept 'jrc reg' as an alias for 'jic 0, $reg'. + case Mips::JR: + case Mips::PseudoReturn: + case Mips::PseudoIndirectBranch: + if (canUseShortMicroMipsCTI) + return Mips::JRC16_MM; + return Mips::JIC; + case Mips::JALRPseudo: + return Mips::JIALC; + case Mips::JR64: + case Mips::PseudoReturn64: + case Mips::PseudoIndirectBranch64: + return Mips::JIC64; + case Mips::JALR64Pseudo: + return Mips::JIALC64; + default: + return 0; + } + } + + return 0; +} + +/// Predicate for distingushing between control transfer instructions and all +/// other instructions for handling forbidden slots. Consider inline assembly +/// as unsafe as well. +bool MipsInstrInfo::SafeInForbiddenSlot(const MachineInstr &MI) const { + if (MI.isInlineAsm()) + return false; + + return (MI.getDesc().TSFlags & MipsII::IsCTI) == 0; + +} + +/// Predicate for distingushing instructions that have forbidden slots. +bool MipsInstrInfo::HasForbiddenSlot(const MachineInstr &MI) const { + return (MI.getDesc().TSFlags & MipsII::HasForbiddenSlot) != 0; +} + /// Return the number of bytes of code the specified instruction may be. -unsigned MipsInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const { - switch (MI->getOpcode()) { +unsigned MipsInstrInfo::GetInstSizeInBytes(const MachineInstr &MI) const { + switch (MI.getOpcode()) { default: - return MI->getDesc().getSize(); + return MI.getDesc().getSize(); case TargetOpcode::INLINEASM: { // Inline Asm: Variable size. - const MachineFunction *MF = MI->getParent()->getParent(); - const char *AsmStr = MI->getOperand(0).getSymbolName(); + const MachineFunction *MF = MI.getParent()->getParent(); + const char *AsmStr = MI.getOperand(0).getSymbolName(); return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo()); } case Mips::CONSTPOOL_ENTRY: // If this machine instr is a constant pool entry, its size is recorded as // operand #2. - return MI->getOperand(2).getImm(); + return MI.getOperand(2).getImm(); } } @@ -278,10 +398,70 @@ MachineInstrBuilder MipsInstrInfo::genInstrWithNewOpc(unsigned NewOpc, MachineBasicBlock::iterator I) const { MachineInstrBuilder MIB; + + // Certain branches have two forms: e.g beq $1, $zero, dst vs beqz $1, dest + // Pick the zero form of the branch for readable assembly and for greater + // branch distance in non-microMIPS mode. + // FIXME: Certain atomic sequences on mips64 generate 32bit references to + // Mips::ZERO, which is incorrect. This test should be updated to use + // Subtarget.getABI().GetZeroReg() when those atomic sequences and others + // are fixed. + bool BranchWithZeroOperand = + (I->isBranch() && !I->isPseudo() && I->getOperand(1).isReg() && + (I->getOperand(1).getReg() == Mips::ZERO || + I->getOperand(1).getReg() == Mips::ZERO_64)); + + if (BranchWithZeroOperand) { + switch (NewOpc) { + case Mips::BEQC: + NewOpc = Mips::BEQZC; + break; + case Mips::BNEC: + NewOpc = Mips::BNEZC; + break; + case Mips::BGEC: + NewOpc = Mips::BGEZC; + break; + case Mips::BLTC: + NewOpc = Mips::BLTZC; + break; + } + } + MIB = BuildMI(*I->getParent(), I, I->getDebugLoc(), get(NewOpc)); - for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J) - MIB.addOperand(I->getOperand(J)); + // For MIPSR6 JI*C requires an immediate 0 as an operand, JIALC(64) an + // immediate 0 as an operand and requires the removal of it's %RA<imp-def> + // implicit operand as copying the implicit operations of the instructio we're + // looking at will give us the correct flags. + if (NewOpc == Mips::JIC || NewOpc == Mips::JIALC || NewOpc == Mips::JIC64 || + NewOpc == Mips::JIALC64) { + + if (NewOpc == Mips::JIALC || NewOpc == Mips::JIALC64) + MIB->RemoveOperand(0); + + for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J) { + MIB.addOperand(I->getOperand(J)); + } + + MIB.addImm(0); + + } else if (BranchWithZeroOperand) { + // For MIPSR6 and microMIPS branches with an explicit zero operand, copy + // everything after the zero. + MIB.addOperand(I->getOperand(0)); + + for (unsigned J = 2, E = I->getDesc().getNumOperands(); J < E; ++J) { + MIB.addOperand(I->getOperand(J)); + } + } else { + // All other cases copy all other operands. + for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J) { + MIB.addOperand(I->getOperand(J)); + } + } + + MIB.copyImplicitOps(*I); MIB.setMemRefs(I->memoperands_begin(), I->memoperands_end()); return MIB; diff --git a/lib/Target/Mips/MipsInstrInfo.h b/lib/Target/Mips/MipsInstrInfo.h index 08efc35090466..2e55012eec406 100644 --- a/lib/Target/Mips/MipsInstrInfo.h +++ b/lib/Target/Mips/MipsInstrInfo.h @@ -19,7 +19,6 @@ #define LLVM_LIB_TARGET_MIPS_MIPSINSTRINFO_H #include "Mips.h" -#include "MipsAnalyzeImmediate.h" #include "MipsRegisterInfo.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/Support/ErrorHandling.h" @@ -51,7 +50,7 @@ public: static const MipsInstrInfo *create(MipsSubtarget &STI); /// Branch Analysis - bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, + bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl<MachineOperand> &Cond, bool AllowModify) const override; @@ -60,16 +59,25 @@ public: unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond, - DebugLoc DL) const override; + const DebugLoc &DL) const override; bool ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override; - BranchType AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, + BranchType analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB, SmallVectorImpl<MachineOperand> &Cond, bool AllowModify, - SmallVectorImpl<MachineInstr*> &BranchInstrs) const; + SmallVectorImpl<MachineInstr *> &BranchInstrs) const; + + /// Determine the opcode of a non-delay slot form for a branch if one exists. + unsigned getEquivalentCompactForm(const MachineBasicBlock::iterator I) const; + + /// Predicate to determine if an instruction can go in a forbidden slot. + bool SafeInForbiddenSlot(const MachineInstr &MI) const; + + /// Predicate to determine if an instruction has a forbidden slot. + bool HasForbiddenSlot(const MachineInstr &MI) const; /// Insert nop instruction when hazard condition is found void insertNoop(MachineBasicBlock &MBB, @@ -84,7 +92,7 @@ public: virtual unsigned getOppositeBranchOpc(unsigned Opc) const = 0; /// Return the number of bytes of code the specified instruction may be. - unsigned GetInstSizeInBytes(const MachineInstr *MI) const; + unsigned GetInstSizeInBytes(const MachineInstr &MI) const; void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, @@ -129,7 +137,7 @@ protected: bool isZeroImm(const MachineOperand &op) const; MachineMemOperand *GetMemOperand(MachineBasicBlock &MBB, int FI, - unsigned Flag) const; + MachineMemOperand::Flags Flags) const; private: virtual unsigned getAnalyzableBrOpc(unsigned Opc) const = 0; @@ -138,8 +146,8 @@ private: MachineBasicBlock *&BB, SmallVectorImpl<MachineOperand> &Cond) const; - void BuildCondBr(MachineBasicBlock &MBB, MachineBasicBlock *TBB, DebugLoc DL, - ArrayRef<MachineOperand> Cond) const; + void BuildCondBr(MachineBasicBlock &MBB, MachineBasicBlock *TBB, + const DebugLoc &DL, ArrayRef<MachineOperand> Cond) const; }; /// Create MipsInstrInfo objects. diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index ffda491f0c864..296f6e9b08bd0 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -179,6 +179,10 @@ def IsGP64bit : Predicate<"Subtarget->isGP64bit()">, AssemblerPredicate<"FeatureGP64Bit">; def IsGP32bit : Predicate<"!Subtarget->isGP64bit()">, AssemblerPredicate<"!FeatureGP64Bit">; +def IsPTR64bit : Predicate<"Subtarget->isABI_N64()">, + AssemblerPredicate<"FeaturePTR64Bit">; +def IsPTR32bit : Predicate<"!Subtarget->isABI_N64()">, + AssemblerPredicate<"!FeaturePTR64Bit">; def HasMips64 : Predicate<"Subtarget->hasMips64()">, AssemblerPredicate<"FeatureMips64">; def NotMips64 : Predicate<"!Subtarget->hasMips64()">, @@ -197,8 +201,8 @@ def InMips16Mode : Predicate<"Subtarget->inMips16Mode()">, AssemblerPredicate<"FeatureMips16">; def HasCnMips : Predicate<"Subtarget->hasCnMips()">, AssemblerPredicate<"FeatureCnMips">; -def RelocStatic : Predicate<"TM.getRelocationModel() == Reloc::Static">; -def RelocPIC : Predicate<"TM.getRelocationModel() == Reloc::PIC_">; +def RelocNotPIC : Predicate<"!TM.isPositionIndependent()">; +def RelocPIC : Predicate<"TM.isPositionIndependent()">; def NoNaNsFPMath : Predicate<"TM.Options.NoNaNsFPMath">; def HasStdEnc : Predicate<"Subtarget->hasStandardEncoding()">, AssemblerPredicate<"!FeatureMips16">; @@ -225,6 +229,9 @@ def HasMSA : Predicate<"Subtarget->hasMSA()">, class GPR_32 { list<Predicate> GPRPredicates = [IsGP32bit]; } class GPR_64 { list<Predicate> GPRPredicates = [IsGP64bit]; } +class PTR_32 { list<Predicate> PTRPredicates = [IsPTR32bit]; } +class PTR_64 { list<Predicate> PTRPredicates = [IsPTR64bit]; } + //===----------------------------------------------------------------------===// // Mips ISA/ASE membership and instruction group membership adjectives. // They are mutually exclusive. @@ -315,6 +322,10 @@ class ASE_CNMIPS { list<Predicate> InsnPredicates = [HasCnMips]; } +class ASE_MIPS64_CNMIPS { + list<Predicate> InsnPredicates = [HasMips64, HasCnMips]; +} + class ASE_MSA { list<Predicate> InsnPredicates = [HasMSA]; } @@ -333,6 +344,10 @@ class ISA_MICROMIPS_NOT_32R6_64R6 : PredicateControl { let InsnPredicates = [InMicroMips, NotMips32r6, NotMips64r6]; } +class ASE_NOT_DSP { + list<Predicate> InsnPredicates = [NotDSP]; +} + //===----------------------------------------------------------------------===// class MipsPat<dag pattern, dag result> : Pat<pattern, result>, PredicateControl { @@ -348,14 +363,17 @@ class IsCommutable { class IsBranch { bit isBranch = 1; + bit isCTI = 1; } class IsReturn { bit isReturn = 1; + bit isCTI = 1; } class IsCall { bit isCall = 1; + bit isCTI = 1; } class IsTailCall { @@ -365,6 +383,7 @@ class IsTailCall { bit isBarrier = 1; bit hasExtraSrcRegAllocReq = 1; bit isCodeGenOnly = 1; + bit isCTI = 1; } class IsAsCheapAsAMove { @@ -385,13 +404,13 @@ include "MipsInstrFormats.td" // Mips Operand, Complex Patterns and Transformations Definitions. //===----------------------------------------------------------------------===// -class ConstantSImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = []> - : AsmOperandClass { - let Name = "ConstantSImm" # Bits; - let RenderMethod = "addImmOperands"; - let PredicateMethod = "isConstantSImm<" # Bits # ">"; +class ConstantSImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = [], + int Offset = 0> : AsmOperandClass { + let Name = "ConstantSImm" # Bits # "_" # Offset; + let RenderMethod = "addConstantSImmOperands<" # Bits # ", " # Offset # ">"; + let PredicateMethod = "isConstantSImm<" # Bits # ", " # Offset # ">"; let SuperClasses = Supers; - let DiagnosticType = "SImm" # Bits; + let DiagnosticType = "SImm" # Bits # "_" # Offset; } class ConstantUImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = [], @@ -403,49 +422,181 @@ class ConstantUImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = [], let DiagnosticType = "UImm" # Bits # "_" # Offset; } +class ConstantUImmRangeAsmOperandClass<int Bottom, int Top, + list<AsmOperandClass> Supers = []> + : AsmOperandClass { + let Name = "ConstantUImmRange" # Bottom # "_" # Top; + let RenderMethod = "addImmOperands"; + let PredicateMethod = "isConstantUImmRange<" # Bottom # ", " # Top # ">"; + let SuperClasses = Supers; + let DiagnosticType = "UImmRange" # Bottom # "_" # Top; +} + +class SImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = []> + : AsmOperandClass { + let Name = "SImm" # Bits; + let RenderMethod = "addSImmOperands<" # Bits # ">"; + let PredicateMethod = "isSImm<" # Bits # ">"; + let SuperClasses = Supers; + let DiagnosticType = "SImm" # Bits; +} + +class UImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = []> + : AsmOperandClass { + let Name = "UImm" # Bits; + let RenderMethod = "addUImmOperands<" # Bits # ">"; + let PredicateMethod = "isUImm<" # Bits # ">"; + let SuperClasses = Supers; + let DiagnosticType = "UImm" # Bits; +} + +// AsmOperandClasses require a strict ordering which is difficult to manage +// as a hierarchy. Instead, we use a linear ordering and impose an order that +// is in some places arbitrary. +// +// Here the rules that are in use: +// * Wider immediates are a superset of narrower immediates: +// uimm4 < uimm5 < uimm6 +// * For the same bit-width, unsigned immediates are a superset of signed +// immediates:: +// simm4 < uimm4 < simm5 < uimm5 +// * For the same upper-bound, signed immediates are a superset of unsigned +// immediates: +// uimm3 < simm4 < uimm4 < simm4 +// * Modified immediates are a superset of ordinary immediates: +// uimm5 < uimm5_plus1 (1..32) < uimm5_plus32 (32..63) < uimm6 +// The term 'superset' starts to break down here since the uimm5_plus* classes +// are not true supersets of uimm5 (but they are still subsets of uimm6). +// * 'Relaxed' immediates are supersets of the corresponding unsigned immediate. +// uimm16 < uimm16_relaxed +// * The codeGen pattern type is arbitrarily ordered. +// uimm5 < uimm5_64, and uimm5 < vsplat_uimm5 +// This is entirely arbitrary. We need an ordering and what we pick is +// unimportant since only one is possible for a given mnemonic. +def SImm32RelaxedAsmOperandClass + : SImmAsmOperandClass<32, []> { + let Name = "SImm32_Relaxed"; + let PredicateMethod = "isAnyImm<32>"; + let DiagnosticType = "SImm32_Relaxed"; +} +def SImm32AsmOperandClass + : SImmAsmOperandClass<32, [SImm32RelaxedAsmOperandClass]>; +def ConstantUImm26AsmOperandClass + : ConstantUImmAsmOperandClass<26, [SImm32AsmOperandClass]>; +def ConstantUImm20AsmOperandClass + : ConstantUImmAsmOperandClass<20, [ConstantUImm26AsmOperandClass]>; +def UImm16RelaxedAsmOperandClass + : UImmAsmOperandClass<16, [ConstantUImm20AsmOperandClass]> { + let Name = "UImm16_Relaxed"; + let PredicateMethod = "isAnyImm<16>"; + let DiagnosticType = "UImm16_Relaxed"; +} +def UImm16AsmOperandClass + : UImmAsmOperandClass<16, [UImm16RelaxedAsmOperandClass]>; +def SImm16RelaxedAsmOperandClass + : SImmAsmOperandClass<16, [UImm16RelaxedAsmOperandClass]> { + let Name = "SImm16_Relaxed"; + let PredicateMethod = "isAnyImm<16>"; + let DiagnosticType = "SImm16_Relaxed"; +} +def SImm16AsmOperandClass + : SImmAsmOperandClass<16, [SImm16RelaxedAsmOperandClass]>; +def ConstantSImm10Lsl3AsmOperandClass : AsmOperandClass { + let Name = "SImm10Lsl3"; + let RenderMethod = "addImmOperands"; + let PredicateMethod = "isScaledSImm<10, 3>"; + let SuperClasses = [SImm16AsmOperandClass]; + let DiagnosticType = "SImm10_Lsl3"; +} +def ConstantSImm10Lsl2AsmOperandClass : AsmOperandClass { + let Name = "SImm10Lsl2"; + let RenderMethod = "addImmOperands"; + let PredicateMethod = "isScaledSImm<10, 2>"; + let SuperClasses = [ConstantSImm10Lsl3AsmOperandClass]; + let DiagnosticType = "SImm10_Lsl2"; +} +def ConstantSImm11AsmOperandClass + : ConstantSImmAsmOperandClass<11, [ConstantSImm10Lsl2AsmOperandClass]>; +def ConstantSImm10Lsl1AsmOperandClass : AsmOperandClass { + let Name = "SImm10Lsl1"; + let RenderMethod = "addImmOperands"; + let PredicateMethod = "isScaledSImm<10, 1>"; + let SuperClasses = [ConstantSImm11AsmOperandClass]; + let DiagnosticType = "SImm10_Lsl1"; +} def ConstantUImm10AsmOperandClass - : ConstantUImmAsmOperandClass<10, []>; + : ConstantUImmAsmOperandClass<10, [ConstantSImm10Lsl1AsmOperandClass]>; +def ConstantSImm10AsmOperandClass + : ConstantSImmAsmOperandClass<10, [ConstantUImm10AsmOperandClass]>; +def ConstantSImm9AsmOperandClass + : ConstantSImmAsmOperandClass<9, [ConstantSImm10AsmOperandClass]>; +def ConstantSImm7Lsl2AsmOperandClass : AsmOperandClass { + let Name = "SImm7Lsl2"; + let RenderMethod = "addImmOperands"; + let PredicateMethod = "isScaledSImm<7, 2>"; + let SuperClasses = [ConstantSImm9AsmOperandClass]; + let DiagnosticType = "SImm7_Lsl2"; +} def ConstantUImm8AsmOperandClass - : ConstantUImmAsmOperandClass<8, [ConstantUImm10AsmOperandClass]>; + : ConstantUImmAsmOperandClass<8, [ConstantSImm7Lsl2AsmOperandClass]>; +def ConstantUImm7Sub1AsmOperandClass + : ConstantUImmAsmOperandClass<7, [ConstantUImm8AsmOperandClass], -1> { + // Specify the names since the -1 offset causes invalid identifiers otherwise. + let Name = "UImm7_N1"; + let DiagnosticType = "UImm7_N1"; +} def ConstantUImm7AsmOperandClass - : ConstantUImmAsmOperandClass<7, [ConstantUImm8AsmOperandClass]>; + : ConstantUImmAsmOperandClass<7, [ConstantUImm7Sub1AsmOperandClass]>; +def ConstantUImm6Lsl2AsmOperandClass : AsmOperandClass { + let Name = "UImm6Lsl2"; + let RenderMethod = "addImmOperands"; + let PredicateMethod = "isScaledUImm<6, 2>"; + let SuperClasses = [ConstantUImm7AsmOperandClass]; + let DiagnosticType = "UImm6_Lsl2"; +} def ConstantUImm6AsmOperandClass - : ConstantUImmAsmOperandClass<6, [ConstantUImm7AsmOperandClass]>; + : ConstantUImmAsmOperandClass<6, [ConstantUImm6Lsl2AsmOperandClass]>; def ConstantSImm6AsmOperandClass - : ConstantSImmAsmOperandClass<6, [ConstantUImm7AsmOperandClass]>; -def ConstantUImm5Plus1AsmOperandClass - : ConstantUImmAsmOperandClass<5, [ConstantUImm6AsmOperandClass], 1>; -def ConstantUImm5Plus32AsmOperandClass - : ConstantUImmAsmOperandClass<5, [ConstantUImm6AsmOperandClass], 32>; -def ConstantUImm5Plus33AsmOperandClass - : ConstantUImmAsmOperandClass<5, [ConstantUImm6AsmOperandClass], 33>; -def ConstantUImm5Plus32NormalizeAsmOperandClass - : ConstantUImmAsmOperandClass<5, [ConstantUImm6AsmOperandClass], 32> { - let Name = "ConstantUImm5_32_Norm"; - // We must also subtract 32 when we render the operand. - let RenderMethod = "addConstantUImmOperands<5, 32, -32>"; -} + : ConstantSImmAsmOperandClass<6, [ConstantUImm6AsmOperandClass]>; def ConstantUImm5Lsl2AsmOperandClass : AsmOperandClass { let Name = "UImm5Lsl2"; let RenderMethod = "addImmOperands"; let PredicateMethod = "isScaledUImm<5, 2>"; - let SuperClasses = [ConstantUImm6AsmOperandClass]; + let SuperClasses = [ConstantSImm6AsmOperandClass]; let DiagnosticType = "UImm5_Lsl2"; } +def ConstantUImm5_Range2_64AsmOperandClass + : ConstantUImmRangeAsmOperandClass<2, 64, [ConstantUImm5Lsl2AsmOperandClass]>; +def ConstantUImm5Plus33AsmOperandClass + : ConstantUImmAsmOperandClass<5, [ConstantUImm5_Range2_64AsmOperandClass], + 33>; def ConstantUImm5ReportUImm6AsmOperandClass - : ConstantUImmAsmOperandClass<5, [ConstantUImm6AsmOperandClass]> { + : ConstantUImmAsmOperandClass<5, [ConstantUImm5Plus33AsmOperandClass]> { let Name = "ConstantUImm5_0_Report_UImm6"; let DiagnosticType = "UImm5_0_Report_UImm6"; } +def ConstantUImm5Plus32AsmOperandClass + : ConstantUImmAsmOperandClass< + 5, [ConstantUImm5ReportUImm6AsmOperandClass], 32>; +def ConstantUImm5Plus32NormalizeAsmOperandClass + : ConstantUImmAsmOperandClass<5, [ConstantUImm5Plus32AsmOperandClass], 32> { + let Name = "ConstantUImm5_32_Norm"; + // We must also subtract 32 when we render the operand. + let RenderMethod = "addConstantUImmOperands<5, 32, -32>"; +} +def ConstantUImm5Plus1AsmOperandClass + : ConstantUImmAsmOperandClass< + 5, [ConstantUImm5Plus32NormalizeAsmOperandClass], 1>; def ConstantUImm5AsmOperandClass - : ConstantUImmAsmOperandClass<5, [ConstantUImm6AsmOperandClass]>; + : ConstantUImmAsmOperandClass<5, [ConstantUImm5Plus1AsmOperandClass]>; +def ConstantSImm5AsmOperandClass + : ConstantSImmAsmOperandClass<5, [ConstantUImm5AsmOperandClass]>; def ConstantUImm4AsmOperandClass - : ConstantUImmAsmOperandClass< - 4, [ConstantUImm5AsmOperandClass, - ConstantUImm5Plus32AsmOperandClass, - ConstantUImm5Plus32NormalizeAsmOperandClass]>; + : ConstantUImmAsmOperandClass<4, [ConstantSImm5AsmOperandClass]>; +def ConstantSImm4AsmOperandClass + : ConstantSImmAsmOperandClass<4, [ConstantUImm4AsmOperandClass]>; def ConstantUImm3AsmOperandClass - : ConstantUImmAsmOperandClass<3, [ConstantUImm4AsmOperandClass]>; + : ConstantUImmAsmOperandClass<3, [ConstantSImm4AsmOperandClass]>; def ConstantUImm2Plus1AsmOperandClass : ConstantUImmAsmOperandClass<2, [ConstantUImm3AsmOperandClass], 1>; def ConstantUImm2AsmOperandClass @@ -478,6 +629,12 @@ def brtarget : Operand<OtherVT> { let DecoderMethod = "DecodeBranchTarget"; let ParserMatchClass = MipsJumpTargetAsmOperand; } +def brtarget1SImm16 : Operand<OtherVT> { + let EncoderMethod = "getBranchTargetOpValue1SImm16"; + let OperandType = "OPERAND_PCREL"; + let DecoderMethod = "DecodeBranchTarget1SImm16"; + let ParserMatchClass = MipsJumpTargetAsmOperand; +} def calltarget : Operand<iPTR> { let EncoderMethod = "getJumpTargetOpValue"; let ParserMatchClass = MipsJumpTargetAsmOperand; @@ -485,18 +642,6 @@ def calltarget : Operand<iPTR> { def imm64: Operand<i64>; -def simm6 : Operand<i32> { - let ParserMatchClass = ConstantSImm6AsmOperandClass; - let OperandType = "OPERAND_IMMEDIATE"; -} -def simm9 : Operand<i32>; -def simm10 : Operand<i32>; -def simm11 : Operand<i32>; - -def simm16 : Operand<i32> { - let DecoderMethod= "DecodeSimm16"; -} - def simm19_lsl2 : Operand<i32> { let EncoderMethod = "getSimm19Lsl2Encoding"; let DecoderMethod = "DecodeSimm19Lsl2"; @@ -509,91 +654,207 @@ def simm18_lsl3 : Operand<i32> { let ParserMatchClass = MipsJumpTargetAsmOperand; } -def simm20 : Operand<i32>; -def simm32 : Operand<i32>; - -def uimm20 : Operand<i32> { -} - -def simm16_64 : Operand<i64> { - let DecoderMethod = "DecodeSimm16"; -} - // Zero def uimmz : Operand<i32> { - let PrintMethod = "printUnsignedImm"; + let PrintMethod = "printUImm<0>"; let ParserMatchClass = ConstantImmzAsmOperandClass; } +// size operand of ins instruction +def uimm_range_2_64 : Operand<i32> { + let PrintMethod = "printUImm<6, 2>"; + let EncoderMethod = "getSizeInsEncoding"; + let DecoderMethod = "DecodeInsSize"; + let ParserMatchClass = ConstantUImm5_Range2_64AsmOperandClass; +} + // Unsigned Operands -foreach I = {1, 2, 3, 4, 5, 6, 7, 8, 10} in +foreach I = {1, 2, 3, 4, 5, 6, 7, 8, 10, 20, 26} in def uimm # I : Operand<i32> { - let PrintMethod = "printUnsignedImm"; + let PrintMethod = "printUImm<" # I # ">"; let ParserMatchClass = !cast<AsmOperandClass>("ConstantUImm" # I # "AsmOperandClass"); } def uimm2_plus1 : Operand<i32> { - let PrintMethod = "printUnsignedImm"; + let PrintMethod = "printUImm<2, 1>"; let EncoderMethod = "getUImmWithOffsetEncoding<2, 1>"; let DecoderMethod = "DecodeUImmWithOffset<2, 1>"; let ParserMatchClass = ConstantUImm2Plus1AsmOperandClass; } def uimm5_plus1 : Operand<i32> { - let PrintMethod = "printUnsignedImm"; + let PrintMethod = "printUImm<5, 1>"; let EncoderMethod = "getUImmWithOffsetEncoding<5, 1>"; let DecoderMethod = "DecodeUImmWithOffset<5, 1>"; let ParserMatchClass = ConstantUImm5Plus1AsmOperandClass; } def uimm5_plus32 : Operand<i32> { - let PrintMethod = "printUnsignedImm"; + let PrintMethod = "printUImm<5, 32>"; let ParserMatchClass = ConstantUImm5Plus32AsmOperandClass; } def uimm5_plus33 : Operand<i32> { - let PrintMethod = "printUnsignedImm"; + let PrintMethod = "printUImm<5, 33>"; let EncoderMethod = "getUImmWithOffsetEncoding<5, 1>"; let DecoderMethod = "DecodeUImmWithOffset<5, 1>"; let ParserMatchClass = ConstantUImm5Plus33AsmOperandClass; } +def uimm5_inssize_plus1 : Operand<i32> { + let PrintMethod = "printUImm<6>"; + let ParserMatchClass = ConstantUImm5Plus1AsmOperandClass; + let EncoderMethod = "getSizeInsEncoding"; + let DecoderMethod = "DecodeInsSize"; +} + def uimm5_plus32_normalize : Operand<i32> { - let PrintMethod = "printUnsignedImm"; + let PrintMethod = "printUImm<5>"; let ParserMatchClass = ConstantUImm5Plus32NormalizeAsmOperandClass; } def uimm5_lsl2 : Operand<OtherVT> { let EncoderMethod = "getUImm5Lsl2Encoding"; - let DecoderMethod = "DecodeUImm5lsl2"; + let DecoderMethod = "DecodeUImmWithOffsetAndScale<5, 0, 4>"; let ParserMatchClass = ConstantUImm5Lsl2AsmOperandClass; } def uimm5_plus32_normalize_64 : Operand<i64> { - let PrintMethod = "printUnsignedImm"; + let PrintMethod = "printUImm<5>"; let ParserMatchClass = ConstantUImm5Plus32NormalizeAsmOperandClass; } +def uimm6_lsl2 : Operand<OtherVT> { + let EncoderMethod = "getUImm6Lsl2Encoding"; + let DecoderMethod = "DecodeUImmWithOffsetAndScale<6, 0, 4>"; + let ParserMatchClass = ConstantUImm6Lsl2AsmOperandClass; +} + +foreach I = {16} in + def uimm # I : Operand<i32> { + let PrintMethod = "printUImm<" # I # ">"; + let ParserMatchClass = + !cast<AsmOperandClass>("UImm" # I # "AsmOperandClass"); + } + +// Like uimm16_64 but coerces simm16 to uimm16. +def uimm16_relaxed : Operand<i32> { + let PrintMethod = "printUImm<16>"; + let ParserMatchClass = + !cast<AsmOperandClass>("UImm16RelaxedAsmOperandClass"); +} + foreach I = {5} in def uimm # I # _64 : Operand<i64> { - let PrintMethod = "printUnsignedImm"; + let PrintMethod = "printUImm<" # I # ">"; let ParserMatchClass = !cast<AsmOperandClass>("ConstantUImm" # I # "AsmOperandClass"); } +foreach I = {16} in + def uimm # I # _64 : Operand<i64> { + let PrintMethod = "printUImm<" # I # ">"; + let ParserMatchClass = + !cast<AsmOperandClass>("UImm" # I # "AsmOperandClass"); + } + +// Like uimm16_64 but coerces simm16 to uimm16. +def uimm16_64_relaxed : Operand<i64> { + let PrintMethod = "printUImm<16>"; + let ParserMatchClass = + !cast<AsmOperandClass>("UImm16RelaxedAsmOperandClass"); +} + +// Like uimm5 but reports a less confusing error for 32-63 when +// an instruction alias permits that. +def uimm5_report_uimm6 : Operand<i32> { + let PrintMethod = "printUImm<5>"; + let ParserMatchClass = ConstantUImm5ReportUImm6AsmOperandClass; +} + // Like uimm5_64 but reports a less confusing error for 32-63 when // an instruction alias permits that. def uimm5_64_report_uimm6 : Operand<i64> { - let PrintMethod = "printUnsignedImm"; + let PrintMethod = "printUImm<5>"; let ParserMatchClass = ConstantUImm5ReportUImm6AsmOperandClass; } -def uimm16 : Operand<i32> { - let PrintMethod = "printUnsignedImm"; +foreach I = {1, 2, 3, 4} in + def uimm # I # _ptr : Operand<iPTR> { + let PrintMethod = "printUImm<" # I # ">"; + let ParserMatchClass = + !cast<AsmOperandClass>("ConstantUImm" # I # "AsmOperandClass"); + } + +foreach I = {1, 2, 3, 4, 5, 6, 8} in + def vsplat_uimm # I : Operand<vAny> { + let PrintMethod = "printUImm<" # I # ">"; + let ParserMatchClass = + !cast<AsmOperandClass>("ConstantUImm" # I # "AsmOperandClass"); + } + +// Signed operands +foreach I = {4, 5, 6, 9, 10, 11} in + def simm # I : Operand<i32> { + let DecoderMethod = "DecodeSImmWithOffsetAndScale<" # I # ">"; + let ParserMatchClass = + !cast<AsmOperandClass>("ConstantSImm" # I # "AsmOperandClass"); + } + +foreach I = {1, 2, 3} in + def simm10_lsl # I : Operand<i32> { + let DecoderMethod = "DecodeSImmWithOffsetAndScale<10, " # I # ">"; + let ParserMatchClass = + !cast<AsmOperandClass>("ConstantSImm10Lsl" # I # "AsmOperandClass"); + } + +foreach I = {10} in + def simm # I # _64 : Operand<i64> { + let DecoderMethod = "DecodeSImmWithOffsetAndScale<" # I # ">"; + let ParserMatchClass = + !cast<AsmOperandClass>("ConstantSImm" # I # "AsmOperandClass"); + } + +foreach I = {5, 10} in + def vsplat_simm # I : Operand<vAny> { + let ParserMatchClass = + !cast<AsmOperandClass>("ConstantSImm" # I # "AsmOperandClass"); + } + +def simm7_lsl2 : Operand<OtherVT> { + let EncoderMethod = "getSImm7Lsl2Encoding"; + let DecoderMethod = "DecodeSImmWithOffsetAndScale<" # I # ", 0, 4>"; + let ParserMatchClass = ConstantSImm7Lsl2AsmOperandClass; +} + +foreach I = {16, 32} in + def simm # I : Operand<i32> { + let DecoderMethod = "DecodeSImmWithOffsetAndScale<" # I # ">"; + let ParserMatchClass = !cast<AsmOperandClass>("SImm" # I # "AsmOperandClass"); + } + +// Like simm16 but coerces uimm16 to simm16. +def simm16_relaxed : Operand<i32> { + let DecoderMethod = "DecodeSImmWithOffsetAndScale<16>"; + let ParserMatchClass = !cast<AsmOperandClass>("SImm16RelaxedAsmOperandClass"); +} + +def simm16_64 : Operand<i64> { + let DecoderMethod = "DecodeSImmWithOffsetAndScale<16>"; + let ParserMatchClass = !cast<AsmOperandClass>("SImm16AsmOperandClass"); +} + +// Like simm32 but coerces uimm32 to simm32. +def simm32_relaxed : Operand<i32> { + let DecoderMethod = "DecodeSImmWithOffsetAndScale<32>"; + let ParserMatchClass = !cast<AsmOperandClass>("SImm32RelaxedAsmOperandClass"); } -def pcrel16 : Operand<i32> { +// This is almost the same as a uimm7 but 0x7f is interpreted as -1. +def li16_imm : Operand<i32> { + let DecoderMethod = "DecodeLi16Imm"; + let ParserMatchClass = ConstantUImm7Sub1AsmOperandClass; } def MipsMemAsmOperand : AsmOperandClass { @@ -607,22 +868,44 @@ def MipsMemSimm9AsmOperand : AsmOperandClass { let RenderMethod = "addMemOperands"; let ParserMethod = "parseMemOperand"; let PredicateMethod = "isMemWithSimmOffset<9>"; + let DiagnosticType = "MemSImm9"; } -def MipsMemSimm9GPRAsmOperand : AsmOperandClass { - let Name = "MemOffsetSimm9GPR"; +def MipsMemSimm10AsmOperand : AsmOperandClass { + let Name = "MemOffsetSimm10"; let SuperClasses = [MipsMemAsmOperand]; let RenderMethod = "addMemOperands"; let ParserMethod = "parseMemOperand"; - let PredicateMethod = "isMemWithSimmOffsetGPR<9>"; + let PredicateMethod = "isMemWithSimmOffset<10>"; + let DiagnosticType = "MemSImm10"; } +def MipsMemSimm12AsmOperand : AsmOperandClass { + let Name = "MemOffsetSimm12"; + let SuperClasses = [MipsMemAsmOperand]; + let RenderMethod = "addMemOperands"; + let ParserMethod = "parseMemOperand"; + let PredicateMethod = "isMemWithSimmOffset<12>"; + let DiagnosticType = "MemSImm12"; +} + +foreach I = {1, 2, 3} in + def MipsMemSimm10Lsl # I # AsmOperand : AsmOperandClass { + let Name = "MemOffsetSimm10_" # I; + let SuperClasses = [MipsMemAsmOperand]; + let RenderMethod = "addMemOperands"; + let ParserMethod = "parseMemOperand"; + let PredicateMethod = "isMemWithSimmOffset<10, " # I # ">"; + let DiagnosticType = "MemSImm10Lsl" # I; + } + def MipsMemSimm11AsmOperand : AsmOperandClass { let Name = "MemOffsetSimm11"; let SuperClasses = [MipsMemAsmOperand]; let RenderMethod = "addMemOperands"; let ParserMethod = "parseMemOperand"; let PredicateMethod = "isMemWithSimmOffset<11>"; + let DiagnosticType = "MemSImm11"; } def MipsMemSimm16AsmOperand : AsmOperandClass { @@ -631,6 +914,7 @@ def MipsMemSimm16AsmOperand : AsmOperandClass { let RenderMethod = "addMemOperands"; let ParserMethod = "parseMemOperand"; let PredicateMethod = "isMemWithSimmOffset<16>"; + let DiagnosticType = "MemSImm16"; } def MipsInvertedImmoperand : AsmOperandClass { @@ -664,24 +948,42 @@ def mem_msa : mem_generic { let EncoderMethod = "getMSAMemEncoding"; } +def simm12 : Operand<i32> { + let DecoderMethod = "DecodeSimm12"; +} + def mem_simm9 : mem_generic { let MIOperandInfo = (ops ptr_rc, simm9); let EncoderMethod = "getMemEncoding"; let ParserMatchClass = MipsMemSimm9AsmOperand; } -def mem_simm9gpr : mem_generic { - let MIOperandInfo = (ops ptr_rc, simm9); +def mem_simm10 : mem_generic { + let MIOperandInfo = (ops ptr_rc, simm10); let EncoderMethod = "getMemEncoding"; - let ParserMatchClass = MipsMemSimm9GPRAsmOperand; + let ParserMatchClass = MipsMemSimm10AsmOperand; } +foreach I = {1, 2, 3} in + def mem_simm10_lsl # I : mem_generic { + let MIOperandInfo = (ops ptr_rc, !cast<Operand>("simm10_lsl" # I)); + let EncoderMethod = "getMemEncoding<" # I # ">"; + let ParserMatchClass = + !cast<AsmOperandClass>("MipsMemSimm10Lsl" # I # "AsmOperand"); + } + def mem_simm11 : mem_generic { let MIOperandInfo = (ops ptr_rc, simm11); let EncoderMethod = "getMemEncoding"; let ParserMatchClass = MipsMemSimm11AsmOperand; } +def mem_simm12 : mem_generic { + let MIOperandInfo = (ops ptr_rc, simm12); + let EncoderMethod = "getMemEncoding"; + let ParserMatchClass = MipsMemSimm12AsmOperand; +} + def mem_simm16 : mem_generic { let MIOperandInfo = (ops ptr_rc, simm16); let EncoderMethod = "getMemEncoding"; @@ -735,6 +1037,9 @@ def immSExt16 : PatLeaf<(imm), [{ return isInt<16>(N->getSExtValue()); }]>; // e.g. addi, andi def immSExt15 : PatLeaf<(imm), [{ return isInt<15>(N->getSExtValue()); }]>; +// Node immediate fits as 7-bit zero extended on target immediate. +def immZExt7 : PatLeaf<(imm), [{ return isUInt<7>(N->getZExtValue()); }]>; + // Node immediate fits as 16-bit zero extended on target immediate. // The LO16 param means that only the lower 16 bits of the node // immediate are caught. @@ -755,6 +1060,16 @@ def immLow16Zero : PatLeaf<(imm), [{ // shamt field must fit in 5 bits. def immZExt5 : ImmLeaf<i32, [{return Imm == (Imm & 0x1f);}]>; +def immZExt5Plus1 : PatLeaf<(imm), [{ + return isUInt<5>(N->getZExtValue() - 1); +}]>; +def immZExt5Plus32 : PatLeaf<(imm), [{ + return isUInt<5>(N->getZExtValue() - 32); +}]>; +def immZExt5Plus33 : PatLeaf<(imm), [{ + return isUInt<5>(N->getZExtValue() - 33); +}]>; + // True if (N + 1) fits in 16-bit field. def immSExt16Plus1 : PatLeaf<(imm), [{ return isInt<17>(N->getSExtValue()) && isInt<16>(N->getSExtValue() + 1); @@ -768,9 +1083,6 @@ def addr : def addrRegImm : ComplexPattern<iPTR, 2, "selectAddrRegImm", [frameindex]>; -def addrRegReg : - ComplexPattern<iPTR, 2, "selectAddrRegReg", [frameindex]>; - def addrDefault : ComplexPattern<iPTR, 2, "selectAddrDefault", [frameindex]>; @@ -849,15 +1161,21 @@ class LoadUpper<string opstr, RegisterOperand RO, Operand Imm>: } // Memory Load/Store -class Load<string opstr, DAGOperand RO, SDPatternOperator OpNode = null_frag, - InstrItinClass Itin = NoItinerary, ComplexPattern Addr = addr> : - InstSE<(outs RO:$rt), (ins mem:$addr), !strconcat(opstr, "\t$rt, $addr"), +class LoadMemory<string opstr, DAGOperand RO, DAGOperand MO, + SDPatternOperator OpNode = null_frag, + InstrItinClass Itin = NoItinerary, + ComplexPattern Addr = addr> : + InstSE<(outs RO:$rt), (ins MO:$addr), !strconcat(opstr, "\t$rt, $addr"), [(set RO:$rt, (OpNode Addr:$addr))], Itin, FrmI, opstr> { let DecoderMethod = "DecodeMem"; let canFoldAsLoad = 1; let mayLoad = 1; } +class Load<string opstr, DAGOperand RO, SDPatternOperator OpNode = null_frag, + InstrItinClass Itin = NoItinerary, ComplexPattern Addr = addr> : + LoadMemory<opstr, RO, mem, OpNode, Itin, Addr>; + class StoreMemory<string opstr, DAGOperand RO, DAGOperand MO, SDPatternOperator OpNode = null_frag, InstrItinClass Itin = NoItinerary, ComplexPattern Addr = addr> : @@ -868,8 +1186,9 @@ class StoreMemory<string opstr, DAGOperand RO, DAGOperand MO, } class Store<string opstr, DAGOperand RO, SDPatternOperator OpNode = null_frag, - InstrItinClass Itin = NoItinerary, ComplexPattern Addr = addr> : - StoreMemory<opstr, RO, mem, OpNode, Itin, Addr>; + InstrItinClass Itin = NoItinerary, ComplexPattern Addr = addr, + DAGOperand MO = mem> : + StoreMemory<opstr, RO, MO, OpNode, Itin, Addr>; // Load/Store Left/Right let canFoldAsLoad = 1 in @@ -892,7 +1211,8 @@ class StoreLeftRight<string opstr, SDNode OpNode, RegisterOperand RO, // COP2 Load/Store class LW_FT2<string opstr, RegisterOperand RC, InstrItinClass Itin, SDPatternOperator OpNode= null_frag> : - InstSE<(outs RC:$rt), (ins mem:$addr), !strconcat(opstr, "\t$rt, $addr"), + InstSE<(outs RC:$rt), (ins mem_simm16:$addr), + !strconcat(opstr, "\t$rt, $addr"), [(set RC:$rt, (OpNode addrDefault:$addr))], Itin, FrmFI, opstr> { let DecoderMethod = "DecodeFMem2"; let mayLoad = 1; @@ -900,7 +1220,8 @@ class LW_FT2<string opstr, RegisterOperand RC, InstrItinClass Itin, class SW_FT2<string opstr, RegisterOperand RC, InstrItinClass Itin, SDPatternOperator OpNode= null_frag> : - InstSE<(outs), (ins RC:$rt, mem:$addr), !strconcat(opstr, "\t$rt, $addr"), + InstSE<(outs), (ins RC:$rt, mem_simm16:$addr), + !strconcat(opstr, "\t$rt, $addr"), [(OpNode RC:$rt, addrDefault:$addr)], Itin, FrmFI, opstr> { let DecoderMethod = "DecodeFMem2"; let mayStore = 1; @@ -934,6 +1255,7 @@ class CBranch<string opstr, DAGOperand opnd, PatFrag cond_op, let isTerminator = 1; let hasDelaySlot = DelaySlot; let Defs = [AT]; + bit isCTI = 1; } class CBranchZero<string opstr, DAGOperand opnd, PatFrag cond_op, @@ -946,6 +1268,7 @@ class CBranchZero<string opstr, DAGOperand opnd, PatFrag cond_op, let isTerminator = 1; let hasDelaySlot = DelaySlot; let Defs = [AT]; + bit isCTI = 1; } // SetCC @@ -972,6 +1295,7 @@ class JumpFJ<DAGOperand opnd, string opstr, SDPatternOperator operator, let hasDelaySlot = 1; let DecoderMethod = "DecodeJumpTarget"; let Defs = [AT]; + bit isCTI = 1; } // Unconditional branch @@ -984,10 +1308,11 @@ class UncondBranch<Instruction BEQInst> : let hasDelaySlot = 1; let AdditionalPredicates = [RelocPIC]; let Defs = [AT]; + bit isCTI = 1; } // Base class for indirect branch and return instruction classes. -let isTerminator=1, isBarrier=1, hasDelaySlot = 1 in +let isTerminator=1, isBarrier=1, hasDelaySlot = 1, isCTI = 1 in class JumpFR<string opstr, RegisterOperand RO, SDPatternOperator operator = null_frag>: InstSE<(outs), (ins RO:$rs), "jr\t$rs", [(operator RO:$rs)], II_JR, @@ -1000,7 +1325,7 @@ class IndirectBranch<string opstr, RegisterOperand RO> : JumpFR<opstr, RO> { } // Jump and Link (Call) -let isCall=1, hasDelaySlot=1, Defs = [RA] in { +let isCall=1, hasDelaySlot=1, isCTI=1, Defs = [RA] in { class JumpLink<string opstr, DAGOperand opnd> : InstSE<(outs), (ins opnd:$target), !strconcat(opstr, "\t$target"), [(MipsJmpLink tglobaladdr:$target)], II_JAL, FrmJ, opstr> { @@ -1026,7 +1351,7 @@ let isCall=1, hasDelaySlot=1, Defs = [RA] in { } let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, hasDelaySlot = 1, - hasExtraSrcRegAllocReq = 1, Defs = [AT] in { + hasExtraSrcRegAllocReq = 1, isCTI = 1, Defs = [AT] in { class TailCall<Instruction JumpInst> : PseudoSE<(outs), (ins calltarget:$target), [], II_J>, PseudoInstExpansion<(JumpInst jmptarget:$target)>; @@ -1045,54 +1370,61 @@ class BAL_BR_Pseudo<Instruction RealInst> : let isBarrier = 1; let hasDelaySlot = 1; let Defs = [RA]; + bit isCTI = 1; } +let isCTI = 1 in { // Syscall -class SYS_FT<string opstr> : - InstSE<(outs), (ins uimm20:$code_), - !strconcat(opstr, "\t$code_"), [], NoItinerary, FrmI, opstr>; +class SYS_FT<string opstr, Operand ImmOp, InstrItinClass itin = NoItinerary> : + InstSE<(outs), (ins ImmOp:$code_), + !strconcat(opstr, "\t$code_"), [], itin, FrmI, opstr>; // Break class BRK_FT<string opstr> : InstSE<(outs), (ins uimm10:$code_1, uimm10:$code_2), - !strconcat(opstr, "\t$code_1, $code_2"), [], NoItinerary, + !strconcat(opstr, "\t$code_1, $code_2"), [], II_BREAK, FrmOther, opstr>; // (D)Eret -class ER_FT<string opstr> : +class ER_FT<string opstr, InstrItinClass itin = NoItinerary> : InstSE<(outs), (ins), - opstr, [], NoItinerary, FrmOther, opstr>; - -// Interrupts -class DEI_FT<string opstr, RegisterOperand RO> : - InstSE<(outs RO:$rt), (ins), - !strconcat(opstr, "\t$rt"), [], NoItinerary, FrmOther, opstr>; + opstr, [], itin, FrmOther, opstr>; // Wait class WAIT_FT<string opstr> : - InstSE<(outs), (ins), opstr, [], NoItinerary, FrmOther, opstr>; + InstSE<(outs), (ins), opstr, [], II_WAIT, FrmOther, opstr>; +} + +// Interrupts +class DEI_FT<string opstr, RegisterOperand RO, + InstrItinClass itin = NoItinerary> : + InstSE<(outs RO:$rt), (ins), + !strconcat(opstr, "\t$rt"), [], itin, FrmOther, opstr>; // Sync let hasSideEffects = 1 in class SYNC_FT<string opstr> : - InstSE<(outs), (ins i32imm:$stype), "sync $stype", [(MipsSync imm:$stype)], - NoItinerary, FrmOther, opstr>; + InstSE<(outs), (ins uimm5:$stype), "sync $stype", + [(MipsSync immZExt5:$stype)], II_SYNC, FrmOther, opstr>; class SYNCI_FT<string opstr> : InstSE<(outs), (ins mem_simm16:$addr), !strconcat(opstr, "\t$addr"), [], - NoItinerary, FrmOther, opstr> { + II_SYNCI, FrmOther, opstr> { let hasSideEffects = 1; let DecoderMethod = "DecodeSyncI"; } -let hasSideEffects = 1 in -class TEQ_FT<string opstr, RegisterOperand RO> : - InstSE<(outs), (ins RO:$rs, RO:$rt, uimm16:$code_), - !strconcat(opstr, "\t$rs, $rt, $code_"), [], NoItinerary, - FrmI, opstr>; - -class TEQI_FT<string opstr, RegisterOperand RO> : - InstSE<(outs), (ins RO:$rs, uimm16:$imm16), - !strconcat(opstr, "\t$rs, $imm16"), [], NoItinerary, FrmOther, opstr>; +let hasSideEffects = 1, isCTI = 1 in { +class TEQ_FT<string opstr, RegisterOperand RO, Operand ImmOp, + InstrItinClass itin = NoItinerary> : + InstSE<(outs), (ins RO:$rs, RO:$rt, ImmOp:$code_), + !strconcat(opstr, "\t$rs, $rt, $code_"), [], itin, FrmI, opstr>; + +class TEQI_FT<string opstr, RegisterOperand RO, + InstrItinClass itin = NoItinerary> : + InstSE<(outs), (ins RO:$rs, simm16:$imm16), + !strconcat(opstr, "\t$rs, $imm16"), [], itin, FrmOther, opstr>; +} + // Mul, Div class Mult<string opstr, InstrItinClass itin, RegisterOperand RO, list<Register> DefRegs> : @@ -1163,20 +1495,23 @@ class MoveToLOHI<string opstr, RegisterOperand RO, list<Register> DefRegs>: class EffectiveAddress<string opstr, RegisterOperand RO> : InstSE<(outs RO:$rt), (ins mem_ea:$addr), !strconcat(opstr, "\t$rt, $addr"), - [(set RO:$rt, addr:$addr)], NoItinerary, FrmI, + [(set RO:$rt, addr:$addr)], II_ADDIU, FrmI, !strconcat(opstr, "_lea")> { let isCodeGenOnly = 1; + let hasNoSchedulingInfo = 1; let DecoderMethod = "DecodeMem"; } // Count Leading Ones/Zeros in Word -class CountLeading0<string opstr, RegisterOperand RO>: +class CountLeading0<string opstr, RegisterOperand RO, + InstrItinClass itin = NoItinerary>: InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"), - [(set RO:$rd, (ctlz RO:$rs))], II_CLZ, FrmR, opstr>; + [(set RO:$rd, (ctlz RO:$rs))], itin, FrmR, opstr>; -class CountLeading1<string opstr, RegisterOperand RO>: +class CountLeading1<string opstr, RegisterOperand RO, + InstrItinClass itin = NoItinerary>: InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"), - [(set RO:$rd, (ctlz (not RO:$rs)))], II_CLO, FrmR, opstr>; + [(set RO:$rd, (ctlz (not RO:$rs)))], itin, FrmR, opstr>; // Sign Extend in Register. class SignExtInReg<string opstr, ValueType vt, RegisterOperand RO, @@ -1199,15 +1534,16 @@ class ReadHardware<RegisterOperand CPURegOperand, RegisterOperand RO> : // Ext and Ins class ExtBase<string opstr, RegisterOperand RO, Operand PosOpnd, - Operand SizeOpnd, SDPatternOperator Op = null_frag> : + Operand SizeOpnd, PatFrag PosImm, PatFrag SizeImm, + SDPatternOperator Op = null_frag> : InstSE<(outs RO:$rt), (ins RO:$rs, PosOpnd:$pos, SizeOpnd:$size), !strconcat(opstr, " $rt, $rs, $pos, $size"), - [(set RO:$rt, (Op RO:$rs, imm:$pos, imm:$size))], II_EXT, + [(set RO:$rt, (Op RO:$rs, PosImm:$pos, SizeImm:$size))], II_EXT, FrmR, opstr>, ISA_MIPS32R2; class InsBase<string opstr, RegisterOperand RO, Operand PosOpnd, - SDPatternOperator Op = null_frag>: - InstSE<(outs RO:$rt), (ins RO:$rs, PosOpnd:$pos, size_ins:$size, RO:$src), + Operand SizeOpnd, SDPatternOperator Op = null_frag>: + InstSE<(outs RO:$rt), (ins RO:$rs, PosOpnd:$pos, SizeOpnd:$size, RO:$src), !strconcat(opstr, " $rt, $rs, $pos, $size"), [(set RO:$rt, (Op RO:$rs, imm:$pos, imm:$size, RO:$src))], II_INS, FrmR, opstr>, ISA_MIPS32R2 { @@ -1224,35 +1560,38 @@ class AtomicCmpSwap<PatFrag Op, RegisterClass DRC> : PseudoSE<(outs DRC:$dst), (ins PtrRC:$ptr, DRC:$cmp, DRC:$swap), [(set DRC:$dst, (Op iPTR:$ptr, DRC:$cmp, DRC:$swap))]>; -class LLBase<string opstr, RegisterOperand RO> : - InstSE<(outs RO:$rt), (ins mem:$addr), !strconcat(opstr, "\t$rt, $addr"), - [], NoItinerary, FrmI> { +class LLBase<string opstr, RegisterOperand RO, DAGOperand MO = mem> : + InstSE<(outs RO:$rt), (ins MO:$addr), !strconcat(opstr, "\t$rt, $addr"), + [], II_LL, FrmI, opstr> { let DecoderMethod = "DecodeMem"; let mayLoad = 1; } class SCBase<string opstr, RegisterOperand RO> : InstSE<(outs RO:$dst), (ins RO:$rt, mem:$addr), - !strconcat(opstr, "\t$rt, $addr"), [], NoItinerary, FrmI> { + !strconcat(opstr, "\t$rt, $addr"), [], II_SC, FrmI> { let DecoderMethod = "DecodeMem"; let mayStore = 1; let Constraints = "$rt = $dst"; } -class MFC3OP<string asmstr, RegisterOperand RO, RegisterOperand RD> : - InstSE<(outs RO:$rt), (ins RD:$rd, uimm16:$sel), - !strconcat(asmstr, "\t$rt, $rd, $sel"), [], NoItinerary, FrmFR>; +class MFC3OP<string asmstr, RegisterOperand RO, RegisterOperand RD, + InstrItinClass itin> : + InstSE<(outs RO:$rt), (ins RD:$rd, uimm3:$sel), + !strconcat(asmstr, "\t$rt, $rd, $sel"), [], itin, FrmFR>; -class MTC3OP<string asmstr, RegisterOperand RO, RegisterOperand RD> : - InstSE<(outs RO:$rd), (ins RD:$rt, uimm16:$sel), - !strconcat(asmstr, "\t$rt, $rd, $sel"), [], NoItinerary, FrmFR>; +class MTC3OP<string asmstr, RegisterOperand RO, RegisterOperand RD, + InstrItinClass itin> : + InstSE<(outs RO:$rd), (ins RD:$rt, uimm3:$sel), + !strconcat(asmstr, "\t$rt, $rd, $sel"), [], itin, FrmFR>; class TrapBase<Instruction RealInst> - : PseudoSE<(outs), (ins), [(trap)], NoItinerary>, + : PseudoSE<(outs), (ins), [(trap)], II_TRAP>, PseudoInstExpansion<(RealInst 0, 0)> { let isBarrier = 1; let isTerminator = 1; let isCodeGenOnly = 1; + let isCTI = 1; } //===----------------------------------------------------------------------===// @@ -1260,11 +1599,13 @@ class TrapBase<Instruction RealInst> //===----------------------------------------------------------------------===// // Return RA. -let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, hasCtrlDep=1 in -def RetRA : PseudoSE<(outs), (ins), [(MipsRet)]>; +let isReturn=1, isTerminator=1, isBarrier=1, hasCtrlDep=1, isCTI=1 in { + let hasDelaySlot=1 in + def RetRA : PseudoSE<(outs), (ins), [(MipsRet)]>; -let isReturn=1, isTerminator=1, isBarrier=1, hasCtrlDep=1, hasSideEffects=1 in -def ERet : PseudoSE<(outs), (ins), [(MipsERet)]>; + let hasSideEffects=1 in + def ERet : PseudoSE<(outs), (ins), [(MipsERet)]>; +} let Defs = [SP], Uses = [SP], hasSideEffects = 1 in { def ADJCALLSTACKDOWN : MipsPseudo<(outs), (ins i32imm:$amt), @@ -1303,7 +1644,7 @@ let usesCustomInserter = 1 in { } /// Pseudo instructions for loading and storing accumulator registers. -let isPseudo = 1, isCodeGenOnly = 1 in { +let isPseudo = 1, isCodeGenOnly = 1, hasNoSchedulingInfo = 1 in { def LOAD_ACC64 : Load<"", ACC64>; def STORE_ACC64 : Store<"", ACC64>; } @@ -1329,40 +1670,39 @@ def LONG_BRANCH_ADDiu : PseudoSE<(outs GPR32Opnd:$dst), /// Arithmetic Instructions (ALU Immediate) let AdditionalPredicates = [NotInMicroMips] in { -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>, + def ADDiu : MMRel, StdMMR6Rel, ArithLogicI<"addiu", simm16_relaxed, GPR32Opnd, + II_ADDIU, immSExt16, add>, + ADDI_FM<0x9>, IsAsCheapAsAMove; + + def ANDi : MMRel, StdMMR6Rel, + ArithLogicI<"andi", uimm16, GPR32Opnd, II_ANDI, immZExt16, and>, + ADDI_FM<0xc>; + def ORi : MMRel, StdMMR6Rel, + ArithLogicI<"ori", uimm16, GPR32Opnd, II_ORI, immZExt16, or>, + ADDI_FM<0xd>; + def XORi : MMRel, StdMMR6Rel, + ArithLogicI<"xori", uimm16, GPR32Opnd, II_XORI, immZExt16, xor>, + ADDI_FM<0xe>; +} +def ADDi : MMRel, ArithLogicI<"addi", simm16_relaxed, GPR32Opnd, II_ADDI>, ADDI_FM<0x8>, ISA_MIPS1_NOT_32R6_64R6; def SLTi : MMRel, SetCC_I<"slti", setlt, simm16, immSExt16, GPR32Opnd>, SLTI_FM<0xa>; def SLTiu : MMRel, SetCC_I<"sltiu", setult, simm16, immSExt16, GPR32Opnd>, SLTI_FM<0xb>; -let AdditionalPredicates = [NotInMicroMips] in { -def ANDi : MMRel, StdMMR6Rel, - ArithLogicI<"andi", uimm16, GPR32Opnd, II_ANDI, immZExt16, and>, - ADDI_FM<0xc>; -} -def ORi : MMRel, StdMMR6Rel, - ArithLogicI<"ori", uimm16, GPR32Opnd, II_ORI, immZExt16, or>, - ADDI_FM<0xd>; -def XORi : MMRel, StdMMR6Rel, - ArithLogicI<"xori", uimm16, GPR32Opnd, II_XORI, immZExt16, xor>, - ADDI_FM<0xe>; -def LUi : MMRel, LoadUpper<"lui", GPR32Opnd, uimm16>, LUI_FM; +def LUi : MMRel, LoadUpper<"lui", GPR32Opnd, uimm16_relaxed>, LUI_FM; let AdditionalPredicates = [NotInMicroMips] in { /// Arithmetic Instructions (3-Operand, R-Type) 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>, +def SUBu : MMRel, StdMMR6Rel, 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, StdMMR6Rel, ArithLogicR<"add", GPR32Opnd>, ADD_FM<0, 0x20>; -def SUB : MMRel, ArithLogicR<"sub", GPR32Opnd>, ADD_FM<0, 0x22>; +def ADD : MMRel, StdMMR6Rel, ArithLogicR<"add", GPR32Opnd, 1, II_ADD>, ADD_FM<0, 0x20>; +def SUB : MMRel, StdMMR6Rel, ArithLogicR<"sub", GPR32Opnd, 0, II_SUB>, 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>; let AdditionalPredicates = [NotInMicroMips] in { @@ -1372,8 +1712,8 @@ def OR : MMRel, StdMMR6Rel, ArithLogicR<"or", GPR32Opnd, 1, II_OR, or>, ADD_FM<0, 0x25>; def XOR : MMRel, StdMMR6Rel, ArithLogicR<"xor", GPR32Opnd, 1, II_XOR, xor>, ADD_FM<0, 0x26>; -} def NOR : MMRel, StdMMR6Rel, LogicNOR<"nor", GPR32Opnd>, ADD_FM<0, 0x27>; +} /// Shift Instructions let AdditionalPredicates = [NotInMicroMips] in { @@ -1381,7 +1721,6 @@ def SLL : MMRel, shift_rotate_imm<"sll", uimm5, GPR32Opnd, II_SLL, shl, immZExt5>, SRA_FM<0, 0>; def SRL : MMRel, shift_rotate_imm<"srl", uimm5, GPR32Opnd, II_SRL, srl, immZExt5>, SRA_FM<2, 0>; -} def SRA : MMRel, shift_rotate_imm<"sra", uimm5, GPR32Opnd, II_SRA, sra, immZExt5>, SRA_FM<3, 0>; def SLLV : MMRel, shift_rotate_reg<"sllv", GPR32Opnd, II_SLLV, shl>, @@ -1390,25 +1729,30 @@ def SRLV : MMRel, shift_rotate_reg<"srlv", GPR32Opnd, II_SRLV, srl>, SRLV_FM<6, 0>; def SRAV : MMRel, shift_rotate_reg<"srav", GPR32Opnd, II_SRAV, sra>, SRLV_FM<7, 0>; +} // Rotate Instructions -def ROTR : MMRel, shift_rotate_imm<"rotr", uimm5, GPR32Opnd, II_ROTR, rotr, - immZExt5>, - SRA_FM<2, 1>, ISA_MIPS32R2; -def ROTRV : MMRel, shift_rotate_reg<"rotrv", GPR32Opnd, II_ROTRV, rotr>, - SRLV_FM<6, 1>, ISA_MIPS32R2; +let AdditionalPredicates = [NotInMicroMips] in { + def ROTR : MMRel, shift_rotate_imm<"rotr", uimm5, GPR32Opnd, II_ROTR, rotr, + immZExt5>, + SRA_FM<2, 1>, ISA_MIPS32R2; + def ROTRV : MMRel, shift_rotate_reg<"rotrv", GPR32Opnd, II_ROTRV, rotr>, + SRLV_FM<6, 1>, ISA_MIPS32R2; +} /// Load and Store Instructions /// aligned -def LB : Load<"lb", GPR32Opnd, sextloadi8, II_LB>, MMRel, LW_FM<0x20>; -def LBu : Load<"lbu", GPR32Opnd, zextloadi8, II_LBU, addrDefault>, MMRel, - LW_FM<0x24>; -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>; +def LB : LoadMemory<"lb", GPR32Opnd, mem_simm16, sextloadi8, II_LB>, MMRel, + LW_FM<0x20>; +def LBu : LoadMemory<"lbu", GPR32Opnd, mem_simm16, zextloadi8, II_LBU, + addrDefault>, MMRel, LW_FM<0x24>; let AdditionalPredicates = [NotInMicroMips] in { -def LW : StdMMR6Rel, Load<"lw", GPR32Opnd, load, II_LW, addrDefault>, MMRel, - LW_FM<0x23>; + def LH : LoadMemory<"lh", GPR32Opnd, mem_simm16, sextloadi16, II_LH, + addrDefault>, MMRel, LW_FM<0x21>; + def LHu : LoadMemory<"lhu", GPR32Opnd, mem_simm16, zextloadi16, II_LHU>, + MMRel, LW_FM<0x25>; + def LW : StdMMR6Rel, Load<"lw", GPR32Opnd, load, II_LW, addrDefault>, MMRel, + LW_FM<0x23>; } def SB : StdMMR6Rel, Store<"sb", GPR32Opnd, truncstorei8, II_SB>, MMRel, LW_FM<0x28>; @@ -1432,82 +1776,87 @@ def SWR : StoreLeftRight<"swr", MipsSWR, GPR32Opnd, II_SWR>, LW_FM<0x2e>, let AdditionalPredicates = [NotInMicroMips] in { // COP2 Memory Instructions -def LWC2 : LW_FT2<"lwc2", COP2Opnd, NoItinerary, load>, LW_FM<0x32>, +def LWC2 : StdMMR6Rel, LW_FT2<"lwc2", COP2Opnd, II_LWC2, load>, LW_FM<0x32>, ISA_MIPS1_NOT_32R6_64R6; -def SWC2 : SW_FT2<"swc2", COP2Opnd, NoItinerary, store>, LW_FM<0x3a>, - ISA_MIPS1_NOT_32R6_64R6; -def LDC2 : LW_FT2<"ldc2", COP2Opnd, NoItinerary, load>, LW_FM<0x36>, - ISA_MIPS2_NOT_32R6_64R6; -def SDC2 : SW_FT2<"sdc2", COP2Opnd, NoItinerary, store>, LW_FM<0x3e>, +def SWC2 : StdMMR6Rel, SW_FT2<"swc2", COP2Opnd, II_SWC2, store>, + LW_FM<0x3a>, ISA_MIPS1_NOT_32R6_64R6; +def LDC2 : StdMMR6Rel, LW_FT2<"ldc2", COP2Opnd, II_LDC2, load>, LW_FM<0x36>, ISA_MIPS2_NOT_32R6_64R6; +def SDC2 : StdMMR6Rel, SW_FT2<"sdc2", COP2Opnd, II_SDC2, store>, + LW_FM<0x3e>, ISA_MIPS2_NOT_32R6_64R6; // COP3 Memory Instructions let DecoderNamespace = "COP3_" in { - def LWC3 : LW_FT3<"lwc3", COP3Opnd, NoItinerary, load>, LW_FM<0x33>; - def SWC3 : SW_FT3<"swc3", COP3Opnd, NoItinerary, store>, LW_FM<0x3b>; - def LDC3 : LW_FT3<"ldc3", COP3Opnd, NoItinerary, load>, LW_FM<0x37>, + def LWC3 : LW_FT3<"lwc3", COP3Opnd, II_LWC3, load>, LW_FM<0x33>; + def SWC3 : SW_FT3<"swc3", COP3Opnd, II_SWC3, store>, LW_FM<0x3b>; + def LDC3 : LW_FT3<"ldc3", COP3Opnd, II_LDC3, load>, LW_FM<0x37>, ISA_MIPS2; - def SDC3 : SW_FT3<"sdc3", COP3Opnd, NoItinerary, store>, LW_FM<0x3f>, + def SDC3 : SW_FT3<"sdc3", COP3Opnd, II_SDC3, store>, LW_FM<0x3f>, ISA_MIPS2; } } -def SYNC : MMRel, StdMMR6Rel, SYNC_FT<"sync">, SYNC_FM, ISA_MIPS32; +def SYNC : MMRel, StdMMR6Rel, SYNC_FT<"sync">, SYNC_FM, + ISA_MIPS32; def SYNCI : MMRel, StdMMR6Rel, SYNCI_FT<"synci">, SYNCI_FM, ISA_MIPS32R2; let AdditionalPredicates = [NotInMicroMips] in { - def TEQ : MMRel, TEQ_FT<"teq", GPR32Opnd>, TEQ_FM<0x34>, ISA_MIPS2; - def TGE : MMRel, TEQ_FT<"tge", GPR32Opnd>, TEQ_FM<0x30>, ISA_MIPS2; - def TGEU : MMRel, TEQ_FT<"tgeu", GPR32Opnd>, TEQ_FM<0x31>, ISA_MIPS2; - def TLT : MMRel, TEQ_FT<"tlt", GPR32Opnd>, TEQ_FM<0x32>, ISA_MIPS2; - def TLTU : MMRel, TEQ_FT<"tltu", GPR32Opnd>, TEQ_FM<0x33>, ISA_MIPS2; - def TNE : MMRel, TEQ_FT<"tne", GPR32Opnd>, TEQ_FM<0x36>, ISA_MIPS2; + def TEQ : MMRel, TEQ_FT<"teq", GPR32Opnd, uimm10, II_TEQ>, TEQ_FM<0x34>, ISA_MIPS2; + def TGE : MMRel, TEQ_FT<"tge", GPR32Opnd, uimm10, II_TGE>, TEQ_FM<0x30>, ISA_MIPS2; + def TGEU : MMRel, TEQ_FT<"tgeu", GPR32Opnd, uimm10, II_TGEU>, TEQ_FM<0x31>, ISA_MIPS2; + def TLT : MMRel, TEQ_FT<"tlt", GPR32Opnd, uimm10, II_TLT>, TEQ_FM<0x32>, ISA_MIPS2; + def TLTU : MMRel, TEQ_FT<"tltu", GPR32Opnd, uimm10, II_TLTU>, TEQ_FM<0x33>, ISA_MIPS2; + def TNE : MMRel, TEQ_FT<"tne", GPR32Opnd, uimm10, II_TNE>, TEQ_FM<0x36>, ISA_MIPS2; } -def TEQI : MMRel, TEQI_FT<"teqi", GPR32Opnd>, TEQI_FM<0xc>, +def TEQI : MMRel, TEQI_FT<"teqi", GPR32Opnd, II_TEQI>, TEQI_FM<0xc>, ISA_MIPS2_NOT_32R6_64R6; -def TGEI : MMRel, TEQI_FT<"tgei", GPR32Opnd>, TEQI_FM<0x8>, +def TGEI : MMRel, TEQI_FT<"tgei", GPR32Opnd, II_TGEI>, TEQI_FM<0x8>, ISA_MIPS2_NOT_32R6_64R6; -def TGEIU : MMRel, TEQI_FT<"tgeiu", GPR32Opnd>, TEQI_FM<0x9>, +def TGEIU : MMRel, TEQI_FT<"tgeiu", GPR32Opnd, II_TGEIU>, TEQI_FM<0x9>, ISA_MIPS2_NOT_32R6_64R6; -def TLTI : MMRel, TEQI_FT<"tlti", GPR32Opnd>, TEQI_FM<0xa>, +def TLTI : MMRel, TEQI_FT<"tlti", GPR32Opnd, II_TLTI>, TEQI_FM<0xa>, ISA_MIPS2_NOT_32R6_64R6; -def TTLTIU : MMRel, TEQI_FT<"tltiu", GPR32Opnd>, TEQI_FM<0xb>, +def TTLTIU : MMRel, TEQI_FT<"tltiu", GPR32Opnd, II_TTLTIU>, TEQI_FM<0xb>, ISA_MIPS2_NOT_32R6_64R6; -def TNEI : MMRel, TEQI_FT<"tnei", GPR32Opnd>, TEQI_FM<0xe>, +def TNEI : MMRel, TEQI_FT<"tnei", GPR32Opnd, II_TNEI>, TEQI_FM<0xe>, ISA_MIPS2_NOT_32R6_64R6; let AdditionalPredicates = [NotInMicroMips] in { def BREAK : MMRel, StdMMR6Rel, BRK_FT<"break">, BRK_FM<0xd>; +def SYSCALL : MMRel, SYS_FT<"syscall", uimm20, II_SYSCALL>, SYS_FM<0xc>; } -def SYSCALL : MMRel, SYS_FT<"syscall">, SYS_FM<0xc>; def TRAP : TrapBase<BREAK>; -def SDBBP : MMRel, SYS_FT<"sdbbp">, SDBBP_FM, ISA_MIPS32_NOT_32R6_64R6; +let AdditionalPredicates = [NotInMicroMips] in { +def SDBBP : MMRel, SYS_FT<"sdbbp", uimm20, II_SDBBP>, SDBBP_FM, ISA_MIPS32_NOT_32R6_64R6; +} let AdditionalPredicates = [NotInMicroMips] in { - def ERET : MMRel, ER_FT<"eret">, ER_FM<0x18, 0x0>, INSN_MIPS3_32; - def ERETNC : MMRel, ER_FT<"eretnc">, ER_FM<0x18, 0x1>, ISA_MIPS32R5; - def DERET : MMRel, ER_FT<"deret">, ER_FM<0x1f, 0x0>, ISA_MIPS32; + def ERET : MMRel, ER_FT<"eret", II_ERET>, ER_FM<0x18, 0x0>, INSN_MIPS3_32; + def ERETNC : MMRel, ER_FT<"eretnc", II_ERETNC>, ER_FM<0x18, 0x1>, ISA_MIPS32R5; + def DERET : MMRel, ER_FT<"deret", II_DERET>, ER_FM<0x1f, 0x0>, ISA_MIPS32; } let AdditionalPredicates = [NotInMicroMips] in { - def EI : MMRel, StdMMR6Rel, DEI_FT<"ei", GPR32Opnd>, EI_FM<1>, ISA_MIPS32R2; - def DI : MMRel, StdMMR6Rel, DEI_FT<"di", GPR32Opnd>, EI_FM<0>, ISA_MIPS32R2; + def EI : MMRel, StdMMR6Rel, DEI_FT<"ei", GPR32Opnd, II_EI>, EI_FM<1>, ISA_MIPS32R2; + def DI : MMRel, StdMMR6Rel, DEI_FT<"di", GPR32Opnd, II_DI>, EI_FM<0>, ISA_MIPS32R2; } let EncodingPredicates = []<Predicate>, // FIXME: Lack of HasStdEnc is probably a bug AdditionalPredicates = [NotInMicroMips] in { def WAIT : WAIT_FT<"wait">, WAIT_FM; +} +let AdditionalPredicates = [NotInMicroMips] in { /// Load-linked, Store-conditional -def LL : LLBase<"ll", GPR32Opnd>, LW_FM<0x30>, ISA_MIPS2_NOT_32R6_64R6; -def SC : SCBase<"sc", GPR32Opnd>, LW_FM<0x38>, ISA_MIPS2_NOT_32R6_64R6; +def LL : LLBase<"ll", GPR32Opnd>, LW_FM<0x30>, PTR_32, ISA_MIPS2_NOT_32R6_64R6; +def SC : SCBase<"sc", GPR32Opnd>, LW_FM<0x38>, PTR_32, ISA_MIPS2_NOT_32R6_64R6; } /// Jump and Branch Instructions def J : MMRel, JumpFJ<jmptarget, "j", br, bb, "j">, FJ<2>, - AdditionalRequires<[RelocStatic]>, IsBranch; -def JR : MMRel, IndirectBranch<"jr", GPR32Opnd>, MTLO_FM<8>; + AdditionalRequires<[RelocNotPIC]>, IsBranch; +def JR : MMRel, IndirectBranch<"jr", GPR32Opnd>, MTLO_FM<8>, ISA_MIPS1_NOT_32R6_64R6; def BEQ : MMRel, CBranch<"beq", brtarget, seteq, GPR32Opnd>, BEQ_FM<4>; def BEQL : MMRel, CBranch<"beql", brtarget, seteq, GPR32Opnd, 0>, BEQ_FM<20>, ISA_MIPS2_NOT_32R6_64R6; @@ -1562,6 +1911,7 @@ class PseudoIndirectBranchBase<RegisterOperand RO> : let hasDelaySlot = 1; let isBranch = 1; let isIndirectBranch = 1; + bit isCTI = 1; } def PseudoIndirectBranch : PseudoIndirectBranchBase<GPR32Opnd>; @@ -1579,6 +1929,7 @@ class PseudoReturnBase<RegisterOperand RO> : MipsPseudo<(outs), (ins RO:$rs), let isCodeGenOnly = 1; let hasCtrlDep = 1; let hasExtraSrcRegAllocReq = 1; + bit isCTI = 1; } def PseudoReturn : PseudoReturnBase<GPR32Opnd>; @@ -1596,7 +1947,7 @@ def SDT_MipsEHRET : SDTypeProfile<0, 2, [SDTCisInt<0>, SDTCisPtrTy<1>]>; def MIPSehret : SDNode<"MipsISD::EH_RETURN", SDT_MipsEHRET, [SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>; -let Uses = [V0, V1], isTerminator = 1, isReturn = 1, isBarrier = 1 in { +let Uses = [V0, V1], isTerminator = 1, isReturn = 1, isBarrier = 1, isCTI = 1 in { def MIPSeh_return32 : MipsPseudo<(outs), (ins GPR32:$spoff, GPR32:$dst), [(MIPSehret GPR32:$spoff, GPR32:$dst)]>; def MIPSeh_return64 : MipsPseudo<(outs), (ins GPR64:$spoff, @@ -1609,11 +1960,12 @@ def MULT : MMRel, Mult<"mult", II_MULT, GPR32Opnd, [HI0, LO0]>, MULT_FM<0, 0x18>, ISA_MIPS1_NOT_32R6_64R6; def MULTu : MMRel, Mult<"multu", II_MULTU, GPR32Opnd, [HI0, LO0]>, MULT_FM<0, 0x19>, ISA_MIPS1_NOT_32R6_64R6; -def SDIV : MMRel, Div<"div", II_DIV, GPR32Opnd, [HI0, LO0]>, - MULT_FM<0, 0x1a>, ISA_MIPS1_NOT_32R6_64R6; -def UDIV : MMRel, Div<"divu", II_DIVU, GPR32Opnd, [HI0, LO0]>, - MULT_FM<0, 0x1b>, ISA_MIPS1_NOT_32R6_64R6; - +let AdditionalPredicates = [NotInMicroMips] in { + def SDIV : MMRel, Div<"div", II_DIV, GPR32Opnd, [HI0, LO0]>, + MULT_FM<0, 0x1a>, ISA_MIPS1_NOT_32R6_64R6; + def UDIV : MMRel, Div<"divu", II_DIVU, GPR32Opnd, [HI0, LO0]>, + MULT_FM<0, 0x1b>, ISA_MIPS1_NOT_32R6_64R6; +} def MTHI : MMRel, MoveToLOHI<"mthi", GPR32Opnd, [HI0]>, MTLO_FM<0x11>, ISA_MIPS1_NOT_32R6_64R6; def MTLO : MMRel, MoveToLOHI<"mtlo", GPR32Opnd, [LO0]>, MTLO_FM<0x13>, @@ -1633,9 +1985,9 @@ def SEH : MMRel, StdMMR6Rel, SignExtInReg<"seh", i16, GPR32Opnd, II_SEH>, SEB_FM<0x18, 0x20>, ISA_MIPS32R2; /// Count Leading -def CLZ : MMRel, CountLeading0<"clz", GPR32Opnd>, CLO_FM<0x20>, +def CLZ : MMRel, CountLeading0<"clz", GPR32Opnd, II_CLZ>, CLO_FM<0x20>, ISA_MIPS32_NOT_32R6_64R6; -def CLO : MMRel, CountLeading1<"clo", GPR32Opnd>, CLO_FM<0x21>, +def CLO : MMRel, CountLeading1<"clo", GPR32Opnd, II_CLO>, CLO_FM<0x21>, ISA_MIPS32_NOT_32R6_64R6; let AdditionalPredicates = [NotInMicroMips] in { @@ -1681,29 +2033,39 @@ def PseudoMSUBU : MAddSubPseudo<MSUBU, MipsMSubu, II_MSUBU>, ISA_MIPS32_NOT_32R6_64R6; } -def PseudoSDIV : MultDivPseudo<SDIV, ACC64, GPR32Opnd, MipsDivRem, II_DIV, - 0, 1, 1>, ISA_MIPS1_NOT_32R6_64R6; -def PseudoUDIV : MultDivPseudo<UDIV, ACC64, GPR32Opnd, MipsDivRemU, II_DIVU, - 0, 1, 1>, ISA_MIPS1_NOT_32R6_64R6; let AdditionalPredicates = [NotInMicroMips] in { -def RDHWR : MMRel, ReadHardware<GPR32Opnd, HWRegsOpnd>, RDHWR_FM; + def PseudoSDIV : MultDivPseudo<SDIV, ACC64, GPR32Opnd, MipsDivRem, II_DIV, + 0, 1, 1>, ISA_MIPS1_NOT_32R6_64R6; + def PseudoUDIV : MultDivPseudo<UDIV, ACC64, GPR32Opnd, MipsDivRemU, II_DIVU, + 0, 1, 1>, ISA_MIPS1_NOT_32R6_64R6; + def RDHWR : MMRel, ReadHardware<GPR32Opnd, HWRegsOpnd>, RDHWR_FM; + // TODO: Add '0 < pos+size <= 32' constraint check to ext instruction + def EXT : MMRel, StdMMR6Rel, ExtBase<"ext", GPR32Opnd, uimm5, uimm5_plus1, + immZExt5, immZExt5Plus1, MipsExt>, + EXT_FM<0>; + def INS : MMRel, StdMMR6Rel, InsBase<"ins", GPR32Opnd, uimm5, + uimm5_inssize_plus1, MipsIns>, + EXT_FM<4>; } -// TODO: Add '0 < pos+size <= 32' constraint check to ext instruction -def EXT : MMRel, ExtBase<"ext", GPR32Opnd, uimm5, uimm5_plus1, MipsExt>, - EXT_FM<0>; -def INS : MMRel, InsBase<"ins", GPR32Opnd, uimm5, MipsIns>, EXT_FM<4>; - /// Move Control Registers From/To CPU Registers -def MFC0 : MFC3OP<"mfc0", GPR32Opnd, COP0Opnd>, MFC3OP_FM<0x10, 0>, ISA_MIPS32; -def MTC0 : MTC3OP<"mtc0", COP0Opnd, GPR32Opnd>, MFC3OP_FM<0x10, 4>, ISA_MIPS32; -def MFC2 : MFC3OP<"mfc2", GPR32Opnd, COP2Opnd>, MFC3OP_FM<0x12, 0>; -def MTC2 : MTC3OP<"mtc2", COP2Opnd, GPR32Opnd>, MFC3OP_FM<0x12, 4>; +let AdditionalPredicates = [NotInMicroMips] in { + def MTC0 : MTC3OP<"mtc0", COP0Opnd, GPR32Opnd, II_MTC0>, MFC3OP_FM<0x10, 4>, + ISA_MIPS32; + def MFC0 : MFC3OP<"mfc0", GPR32Opnd, COP0Opnd, II_MFC0>, MFC3OP_FM<0x10, 0>, + ISA_MIPS32; +} +def MFC2 : MFC3OP<"mfc2", GPR32Opnd, COP2Opnd, II_MFC2>, MFC3OP_FM<0x12, 0>; +def MTC2 : MTC3OP<"mtc2", COP2Opnd, GPR32Opnd, II_MTC2>, MFC3OP_FM<0x12, 4>; + +class Barrier<string asmstr, InstrItinClass itin = NoItinerary> : + InstSE<(outs), (ins), asmstr, [], itin, FrmOther, asmstr>; -class Barrier<string asmstr> : InstSE<(outs), (ins), asmstr, [], NoItinerary, - FrmOther, asmstr>; -def SSNOP : MMRel, StdMMR6Rel, Barrier<"ssnop">, BARRIER_FM<1>; -def EHB : MMRel, Barrier<"ehb">, BARRIER_FM<3>; -def PAUSE : MMRel, StdMMR6Rel, Barrier<"pause">, BARRIER_FM<5>, ISA_MIPS32R2; +def SSNOP : MMRel, StdMMR6Rel, Barrier<"ssnop", II_SSNOP>, BARRIER_FM<1>; +def EHB : MMRel, Barrier<"ehb", II_EHB>, BARRIER_FM<3>; + +let isCTI = 1 in +def PAUSE : MMRel, StdMMR6Rel, Barrier<"pause", II_PAUSE>, BARRIER_FM<5>, + ISA_MIPS32R2; // JR_HB and JALR_HB are defined here using the new style naming // scheme because some of this code is shared with Mips32r6InstrInfo.td @@ -1724,19 +2086,21 @@ class JALR_HB_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> { list<dag> Pattern = []; } -class JR_HB_DESC : InstSE<(outs), (ins), "", [], NoItinerary, FrmJ>, +class JR_HB_DESC : InstSE<(outs), (ins), "", [], II_JR_HB, FrmJ>, JR_HB_DESC_BASE<"jr.hb", GPR32Opnd> { let isBranch=1; let isIndirectBranch=1; let hasDelaySlot=1; let isTerminator=1; let isBarrier=1; + bit isCTI = 1; } -class JALR_HB_DESC : InstSE<(outs), (ins), "", [], NoItinerary, FrmJ>, +class JALR_HB_DESC : InstSE<(outs), (ins), "", [], II_JALR_HB, FrmJ>, JALR_HB_DESC_BASE<"jalr.hb", GPR32Opnd> { let isIndirectBranch=1; let hasDelaySlot=1; + bit isCTI = 1; } class JR_HB_ENC : JR_HB_FM<8>; @@ -1745,23 +2109,25 @@ class JALR_HB_ENC : JALR_HB_FM<9>; def JR_HB : JR_HB_DESC, JR_HB_ENC, ISA_MIPS32_NOT_32R6_64R6; def JALR_HB : JALR_HB_DESC, JALR_HB_ENC, ISA_MIPS32; -class TLB<string asmstr> : InstSE<(outs), (ins), asmstr, [], NoItinerary, - FrmOther, asmstr>; -def TLBP : MMRel, TLB<"tlbp">, COP0_TLB_FM<0x08>; -def TLBR : MMRel, TLB<"tlbr">, COP0_TLB_FM<0x01>; -def TLBWI : MMRel, TLB<"tlbwi">, COP0_TLB_FM<0x02>; -def TLBWR : MMRel, TLB<"tlbwr">, COP0_TLB_FM<0x06>; - -class CacheOp<string instr_asm, Operand MemOpnd> : +class TLB<string asmstr, InstrItinClass itin = NoItinerary> : + InstSE<(outs), (ins), asmstr, [], itin, FrmOther, asmstr>; +let AdditionalPredicates = [NotInMicroMips] in { +def TLBP : MMRel, TLB<"tlbp", II_TLBP>, COP0_TLB_FM<0x08>; +def TLBR : MMRel, TLB<"tlbr", II_TLBR>, COP0_TLB_FM<0x01>; +def TLBWI : MMRel, TLB<"tlbwi", II_TLBWI>, COP0_TLB_FM<0x02>; +def TLBWR : MMRel, TLB<"tlbwr", II_TLBWR>, COP0_TLB_FM<0x06>; +} +class CacheOp<string instr_asm, Operand MemOpnd, + InstrItinClass itin = NoItinerary> : InstSE<(outs), (ins MemOpnd:$addr, uimm5:$hint), - !strconcat(instr_asm, "\t$hint, $addr"), [], NoItinerary, FrmOther, + !strconcat(instr_asm, "\t$hint, $addr"), [], itin, FrmOther, instr_asm> { let DecoderMethod = "DecodeCacheOp"; } -def CACHE : MMRel, CacheOp<"cache", mem>, CACHEOP_FM<0b101111>, +def CACHE : MMRel, CacheOp<"cache", mem, II_CACHE>, CACHEOP_FM<0b101111>, INSN_MIPS3_32_NOT_32R6_64R6; -def PREF : MMRel, CacheOp<"pref", mem>, CACHEOP_FM<0b110011>, +def PREF : MMRel, CacheOp<"pref", mem, II_PREF>, CACHEOP_FM<0b110011>, INSN_MIPS3_32_NOT_32R6_64R6; def ROL : MipsAsmPseudoInst<(outs), @@ -1808,6 +2174,9 @@ def : MipsInstAlias<"dror $rd, $rs", def : MipsInstAlias<"dror $rd, $imm", (DRORImm GPR32Opnd:$rd, GPR32Opnd:$rd, simm16:$imm), 0>, ISA_MIPS64; +def ABSMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), (ins GPR32Opnd:$rs), + "abs\t$rd, $rs">; + //===----------------------------------------------------------------------===// // Instruction aliases //===----------------------------------------------------------------------===// @@ -1823,47 +2192,66 @@ def : MipsInstAlias<"move $dst, $src", } def : MipsInstAlias<"bal $offset", (BGEZAL ZERO, brtarget:$offset), 0>, ISA_MIPS1_NOT_32R6_64R6; -def : MipsInstAlias<"addu $rs, $rt, $imm", - (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>; -def : MipsInstAlias<"addu $rs, $imm", - (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm), 0>; -def : MipsInstAlias<"add $rs, $rt, $imm", - (ADDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>, - ISA_MIPS1_NOT_32R6_64R6; -def : MipsInstAlias<"add $rs, $imm", - (ADDi GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm), 0>, - ISA_MIPS1_NOT_32R6_64R6; -def : MipsInstAlias<"and $rs, $rt, $imm", - (ANDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>; -def : MipsInstAlias<"and $rs, $imm", - (ANDi GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm), 0>; +def : MipsInstAlias< + "addu $rs, $rt, $imm", + (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rt, simm32_relaxed:$imm), 0>; +def : MipsInstAlias< + "addu $rs, $imm", + (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rs, simm32_relaxed:$imm), 0>; +def : MipsInstAlias< + "add $rs, $rt, $imm", + (ADDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm32_relaxed:$imm), 0>, + ISA_MIPS1_NOT_32R6_64R6; +def : MipsInstAlias< + "add $rs, $imm", + (ADDi GPR32Opnd:$rs, GPR32Opnd:$rs, simm32_relaxed:$imm), 0>, + ISA_MIPS1_NOT_32R6_64R6; +def : MipsInstAlias< + "and $rs, $rt, $imm", + (ANDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm32_relaxed:$imm), 0>; +def : MipsInstAlias< + "and $rs, $imm", + (ANDi GPR32Opnd:$rs, GPR32Opnd:$rs, simm32_relaxed:$imm), 0>; def : MipsInstAlias<"j $rs", (JR GPR32Opnd:$rs), 0>; let Predicates = [NotInMicroMips] in { def : MipsInstAlias<"jalr $rs", (JALR RA, 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>; def : MipsInstAlias<"neg $rt, $rs", (SUB GPR32Opnd:$rt, ZERO, GPR32Opnd:$rs), 1>; def : MipsInstAlias<"negu $rt", (SUBu GPR32Opnd:$rt, ZERO, GPR32Opnd:$rt), 0>; def : MipsInstAlias<"negu $rt, $rs", (SUBu GPR32Opnd:$rt, ZERO, GPR32Opnd:$rs), 1>; -def : MipsInstAlias<"slt $rs, $rt, $imm", - (SLTi GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>; -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", - (ORi GPR32Opnd:$rs, GPR32Opnd:$rs, uimm16:$imm), 0>; +def : MipsInstAlias< + "slt $rs, $rt, $imm", + (SLTi GPR32Opnd:$rs, GPR32Opnd:$rt, simm32_relaxed:$imm), 0>; +def : MipsInstAlias< + "sltu $rt, $rs, $imm", + (SLTiu GPR32Opnd:$rt, GPR32Opnd:$rs, simm32_relaxed:$imm), 0>; let AdditionalPredicates = [NotInMicroMips] in { -def : MipsInstAlias<"nop", (SLL ZERO, ZERO, 0), 1>; + def : MipsInstAlias< + "and $rs, $rt, $imm", + (ANDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm32_relaxed:$imm), 0>; + def : MipsInstAlias< + "and $rs, $imm", + (ANDi GPR32Opnd:$rs, GPR32Opnd:$rs, simm32_relaxed:$imm), 0>; + def : MipsInstAlias< + "xor $rs, $rt, $imm", + (XORi GPR32Opnd:$rs, GPR32Opnd:$rt, simm32_relaxed:$imm), 0>; + def : MipsInstAlias< + "xor $rs, $imm", + (XORi GPR32Opnd:$rs, GPR32Opnd:$rs, simm32_relaxed:$imm), 0>; + def : MipsInstAlias< + "or $rs, $rt, $imm", + (ORi GPR32Opnd:$rs, GPR32Opnd:$rt, simm32_relaxed:$imm), 0>; + def : MipsInstAlias< + "or $rs, $imm", + (ORi GPR32Opnd:$rs, GPR32Opnd:$rs, simm32_relaxed:$imm), 0>; + def : MipsInstAlias< + "not $rt, $rs", + (NOR GPR32Opnd:$rt, GPR32Opnd:$rs, ZERO), 0>; + def : MipsInstAlias<"nop", (SLL ZERO, ZERO, 0), 1>; } def : MipsInstAlias<"mfc0 $rt, $rd", (MFC0 GPR32Opnd:$rt, COP0Opnd:$rd, 0), 0>; def : MipsInstAlias<"mtc0 $rt, $rd", (MTC0 COP0Opnd:$rd, GPR32Opnd:$rt, 0), 0>; @@ -1880,7 +2268,9 @@ 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>; +let AdditionalPredicates = [NotInMicroMips] in { + def : MipsInstAlias<"syscall", (SYSCALL 0), 1>; +} def : MipsInstAlias<"break", (BREAK 0, 0), 1>; def : MipsInstAlias<"break $imm", (BREAK uimm10:$imm, 0), 1>; @@ -1902,8 +2292,6 @@ let AdditionalPredicates = [NotInMicroMips] in { def : MipsInstAlias<"tne $rs, $rt", (TNE GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>, ISA_MIPS2; } -def : MipsInstAlias<"sll $rd, $rt, $rs", - (SLLV GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>; def : MipsInstAlias<"sub, $rd, $rs, $imm", (ADDi GPR32Opnd:$rd, GPR32Opnd:$rs, InvertedImOperand:$imm), 0>, ISA_MIPS1_NOT_32R6_64R6; @@ -1915,10 +2303,14 @@ def : MipsInstAlias<"subu, $rd, $rs, $imm", InvertedImOperand:$imm), 0>; def : MipsInstAlias<"subu $rs, $imm", (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rs, InvertedImOperand:$imm), 0>; -def : MipsInstAlias<"sra $rd, $rt, $rs", - (SRAV GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>; -def : MipsInstAlias<"srl $rd, $rt, $rs", - (SRLV GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>; +let AdditionalPredicates = [NotInMicroMips] in { + def : MipsInstAlias<"sll $rd, $rt, $rs", + (SLLV GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>; + def : MipsInstAlias<"sra $rd, $rt, $rs", + (SRAV GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>; + def : MipsInstAlias<"srl $rd, $rt, $rs", + (SRLV GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>; +} def : MipsInstAlias<"sdbbp", (SDBBP 0)>, ISA_MIPS32_NOT_32R6_64R6; def : MipsInstAlias<"sync", (SYNC 0), 1>, ISA_MIPS2; @@ -1926,10 +2318,11 @@ def : MipsInstAlias<"sync", // Assembler Pseudo Instructions //===----------------------------------------------------------------------===// +// We use i32imm on li/la to defer range checking to the assembler. class LoadImmediate32<string instr_asm, Operand Od, RegisterOperand RO> : MipsAsmPseudoInst<(outs RO:$rt), (ins Od:$imm32), !strconcat(instr_asm, "\t$rt, $imm32")> ; -def LoadImm32 : LoadImmediate32<"li", simm32, GPR32Opnd>; +def LoadImm32 : LoadImmediate32<"li", i32imm, GPR32Opnd>; class LoadAddressFromReg32<string instr_asm, Operand MemOpnd, RegisterOperand RO> : @@ -1940,17 +2333,18 @@ def LoadAddrReg32 : LoadAddressFromReg32<"la", mem, GPR32Opnd>; class LoadAddressFromImm32<string instr_asm, Operand Od, RegisterOperand RO> : MipsAsmPseudoInst<(outs RO:$rt), (ins Od:$imm32), !strconcat(instr_asm, "\t$rt, $imm32")> ; -def LoadAddrImm32 : LoadAddressFromImm32<"la", simm32, GPR32Opnd>; +def LoadAddrImm32 : LoadAddressFromImm32<"la", i32imm, GPR32Opnd>; def JalTwoReg : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), (ins GPR32Opnd:$rs), "jal\t$rd, $rs"> ; def JalOneReg : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs), "jal\t$rs"> ; -def NORImm : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), - "nor\t$rs, $rt, $imm"> ; +def NORImm : MipsAsmPseudoInst< + (outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt, simm32:$imm), + "nor\t$rs, $rt, $imm"> ; -let hasDelaySlot = 1 in { +let hasDelaySlot = 1, isCTI = 1 in { def BneImm : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins imm64:$imm64, brtarget:$offset), "bne\t$rt, $imm64, $offset">; @@ -1981,6 +2375,7 @@ def BLEUL: CondBranchPseudo<"bleul">, ISA_MIPS2_NOT_32R6_64R6; def BGEUL: CondBranchPseudo<"bgeul">, ISA_MIPS2_NOT_32R6_64R6; def BGTUL: CondBranchPseudo<"bgtul">, ISA_MIPS2_NOT_32R6_64R6; +let isCTI = 1 in class CondBranchImmPseudo<string instr_asm> : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, imm64:$imm, brtarget:$offset), !strconcat(instr_asm, "\t$rs, $imm, $offset")>; @@ -2008,17 +2403,34 @@ def BGTULImmMacro : CondBranchImmPseudo<"bgtul">, ISA_MIPS2_NOT_32R6_64R6; // Once the tablegen-erated errors are made better, this needs to be fixed and // predicates needs to be restored. -def SDivMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt), - "div\t$rs, $rt">; //, ISA_MIPS1_NOT_32R6_64R6; - -def UDivMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt), - "divu\t$rs, $rt">; //, ISA_MIPS1_NOT_32R6_64R6; - -def DSDivMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt), - "ddiv\t$rs, $rt">; //, ISA_MIPS64_NOT_64R6; - -def DUDivMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt), - "ddivu\t$rs, $rt">; //, ISA_MIPS64_NOT_64R6; +def SDivMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), + (ins GPR32Opnd:$rs, GPR32Opnd:$rt), + "div\t$rd, $rs, $rt">, + ISA_MIPS1_NOT_32R6_64R6; +def UDivMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), + (ins GPR32Opnd:$rs, GPR32Opnd:$rt), + "divu\t$rd, $rs, $rt">, + ISA_MIPS1_NOT_32R6_64R6; +def : MipsInstAlias<"div $rt, $rs", (SDivMacro GPR32Opnd:$rt, GPR32Opnd:$rt, + GPR32Opnd:$rs), 0>, + ISA_MIPS1_NOT_32R6_64R6; +def : MipsInstAlias<"divu $rt, $rs", (UDivMacro GPR32Opnd:$rt, GPR32Opnd:$rt, + GPR32Opnd:$rs), 0>, + ISA_MIPS1_NOT_32R6_64R6; +def DSDivMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), + (ins GPR32Opnd:$rs, GPR32Opnd:$rt), + "ddiv\t$rd, $rs, $rt">, + ISA_MIPS64_NOT_64R6; +def DUDivMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), + (ins GPR32Opnd:$rs, GPR32Opnd:$rt), + "ddivu\t$rd, $rs, $rt">, + ISA_MIPS64_NOT_64R6; +def : MipsInstAlias<"ddiv $rt, $rs", (DSDivMacro GPR32Opnd:$rt, GPR32Opnd:$rt, + GPR32Opnd:$rs), 0>, + ISA_MIPS64_NOT_64R6; +def : MipsInstAlias<"ddivu $rt, $rs", (DUDivMacro GPR32Opnd:$rt, GPR32Opnd:$rt, + GPR32Opnd:$rs), 0>, + ISA_MIPS64_NOT_64R6; def Ulh : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins mem:$addr), "ulh\t$rt, $addr">; //, ISA_MIPS1_NOT_32R6_64R6; @@ -2055,14 +2467,14 @@ def : MipsPat<(i32 imm:$imm), (ORi (LUi (HI16 imm:$imm)), (LO16 imm:$imm))>; // Carry MipsPatterns -def : MipsPat<(subc GPR32:$lhs, GPR32:$rhs), - (SUBu GPR32:$lhs, GPR32:$rhs)>; -let AdditionalPredicates = [NotDSP] in { - def : MipsPat<(addc GPR32:$lhs, GPR32:$rhs), - (ADDu GPR32:$lhs, GPR32:$rhs)>; - def : MipsPat<(addc GPR32:$src, immSExt16:$imm), - (ADDiu GPR32:$src, imm:$imm)>; +let AdditionalPredicates = [NotInMicroMips] in { + def : MipsPat<(subc GPR32:$lhs, GPR32:$rhs), + (SUBu GPR32:$lhs, GPR32:$rhs)>; } +def : MipsPat<(addc GPR32:$lhs, GPR32:$rhs), + (ADDu GPR32:$lhs, GPR32:$rhs)>, ASE_NOT_DSP; +def : MipsPat<(addc GPR32:$src, immSExt16:$imm), + (ADDiu GPR32:$src, imm:$imm)>, ASE_NOT_DSP; // Support multiplication for pre-Mips32 targets that don't have // the MUL instruction. @@ -2138,7 +2550,9 @@ def : MipsPat<(not GPR32:$in), // extended loads def : MipsPat<(i32 (extloadi1 addr:$src)), (LBu addr:$src)>; def : MipsPat<(i32 (extloadi8 addr:$src)), (LBu addr:$src)>; -def : MipsPat<(i32 (extloadi16 addr:$src)), (LHu addr:$src)>; +let AdditionalPredicates = [NotInMicroMips] in { + def : MipsPat<(i32 (extloadi16 addr:$src)), (LHu addr:$src)>; +} // peepholes def : MipsPat<(store (i32 0), addr:$dst), (SW ZERO, addr:$dst)>; @@ -2235,15 +2649,17 @@ def : MipsPat<(bswap GPR32:$rt), (ROTR (WSBH GPR32:$rt), 16)>; // Load halfword/word patterns. let AddedComplexity = 40 in { def : LoadRegImmPat<LBu, i32, zextloadi8>; - def : LoadRegImmPat<LH, i32, sextloadi16>; let AdditionalPredicates = [NotInMicroMips] in { - def : LoadRegImmPat<LW, i32, load>; + def : LoadRegImmPat<LH, i32, sextloadi16>; + def : LoadRegImmPat<LW, i32, load>; } } // Atomic load patterns. def : MipsPat<(atomic_load_8 addr:$a), (LB addr:$a)>; -def : MipsPat<(atomic_load_16 addr:$a), (LH addr:$a)>; +let AdditionalPredicates = [NotInMicroMips] in { + def : MipsPat<(atomic_load_16 addr:$a), (LH addr:$a)>; +} def : MipsPat<(atomic_load_32 addr:$a), (LW addr:$a)>; // Atomic store patterns. diff --git a/lib/Target/Mips/MipsLongBranch.cpp b/lib/Target/Mips/MipsLongBranch.cpp index 49fb99a8ec432..e721312390d2c 100644 --- a/lib/Target/Mips/MipsLongBranch.cpp +++ b/lib/Target/Mips/MipsLongBranch.cpp @@ -63,8 +63,7 @@ namespace { public: static char ID; MipsLongBranch(TargetMachine &tm) - : MachineFunctionPass(ID), TM(tm), - IsPIC(TM.getRelocationModel() == Reloc::PIC_), + : MachineFunctionPass(ID), TM(tm), IsPIC(TM.isPositionIndependent()), ABI(static_cast<const MipsTargetMachine &>(TM).getABI()) {} const char *getPassName() const override { @@ -73,11 +72,16 @@ namespace { bool runOnMachineFunction(MachineFunction &F) override; + MachineFunctionProperties getRequiredProperties() const override { + return MachineFunctionProperties().set( + MachineFunctionProperties::Property::AllVRegsAllocated); + } + private: void splitMBB(MachineBasicBlock *MBB); void initMBBInfo(); int64_t computeOffset(const MachineInstr *Br); - void replaceBranch(MachineBasicBlock &MBB, Iter Br, DebugLoc DL, + void replaceBranch(MachineBasicBlock &MBB, Iter Br, const DebugLoc &DL, MachineBasicBlock *MBBOpnd); void expandToLongBranch(MBBInfo &Info); @@ -113,7 +117,7 @@ static MachineBasicBlock *getTargetMBB(const MachineInstr &Br) { // Traverse the list of instructions backwards until a non-debug instruction is // found or it reaches E. -static ReverseIter getNonDebugInstr(ReverseIter B, ReverseIter E) { +static ReverseIter getNonDebugInstr(ReverseIter B, const ReverseIter &E) { for (; B != E; ++B) if (!B->isDebugValue()) return B; @@ -160,8 +164,8 @@ void MipsLongBranch::splitMBB(MachineBasicBlock *MBB) { void MipsLongBranch::initMBBInfo() { // Split the MBBs if they have two branches. Each basic block should have at // most one branch after this loop is executed. - for (MachineFunction::iterator I = MF->begin(), E = MF->end(); I != E;) - splitMBB(&*I++); + for (auto &MBB : *MF) + splitMBB(&MBB); MF->RenumberBlocks(); MBBInfos.clear(); @@ -175,17 +179,15 @@ void MipsLongBranch::initMBBInfo() { // Compute size of MBB. for (MachineBasicBlock::instr_iterator MI = MBB->instr_begin(); MI != MBB->instr_end(); ++MI) - MBBInfos[I].Size += TII->GetInstSizeInBytes(&*MI); + MBBInfos[I].Size += TII->GetInstSizeInBytes(*MI); // Search for MBB's branch instruction. ReverseIter End = MBB->rend(); ReverseIter Br = getNonDebugInstr(MBB->rbegin(), End); if ((Br != End) && !Br->isIndirectBranch() && - (Br->isConditionalBranch() || - (Br->isUnconditionalBranch() && - TM.getRelocationModel() == Reloc::PIC_))) - MBBInfos[I].Br = (++Br).base(); + (Br->isConditionalBranch() || (Br->isUnconditionalBranch() && IsPIC))) + MBBInfos[I].Br = &*(++Br).base(); } } @@ -213,7 +215,8 @@ int64_t MipsLongBranch::computeOffset(const MachineInstr *Br) { // Replace Br with a branch which has the opposite condition code and a // MachineBasicBlock operand MBBOpnd. void MipsLongBranch::replaceBranch(MachineBasicBlock &MBB, Iter Br, - DebugLoc DL, MachineBasicBlock *MBBOpnd) { + const DebugLoc &DL, + MachineBasicBlock *MBBOpnd) { const MipsInstrInfo *TII = static_cast<const MipsInstrInfo *>( MBB.getParent()->getSubtarget().getInstrInfo()); unsigned NewOpc = TII->getOppositeBranchOpc(Br->getOpcode()); @@ -238,7 +241,7 @@ void MipsLongBranch::replaceBranch(MachineBasicBlock &MBB, Iter Br, // Bundle the instruction in the delay slot to the newly created branch // and erase the original branch. assert(Br->isBundledWithSucc()); - MachineBasicBlock::instr_iterator II(Br); + MachineBasicBlock::instr_iterator II = Br.getInstrIterator(); MIBundleBuilder(&*MIB).append((++II)->removeFromBundle()); } Br->eraseFromParent(); @@ -329,23 +332,26 @@ void MipsLongBranch::expandToLongBranch(MBBInfo &I) { BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::LW), Mips::RA) .addReg(Mips::SP).addImm(0); - 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) - .addReg(Mips::SP).addImm(8)); - } else { - // In NaCl, modifying the sp is not allowed in branch delay slot. + // In NaCl, modifying the sp is not allowed in branch delay slot. + if (Subtarget.isTargetNaCl()) BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::ADDiu), Mips::SP) .addReg(Mips::SP).addImm(8); - MIBundleBuilder(*BalTgtMBB, Pos) - .append(BuildMI(*MF, DL, TII->get(Mips::JR)).addReg(Mips::AT)) - .append(BuildMI(*MF, DL, TII->get(Mips::NOP))); + if (Subtarget.hasMips32r6()) + BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::JALR)) + .addReg(Mips::ZERO).addReg(Mips::AT); + else + BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::JR)).addReg(Mips::AT); + if (Subtarget.isTargetNaCl()) { + BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::NOP)); // Bundle-align the target of indirect branch JR. TgtMBB->setAlignment(MIPS_NACL_BUNDLE_ALIGN); - } + } else + BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::ADDiu), Mips::SP) + .addReg(Mips::SP).addImm(8); + + BalTgtMBB->rbegin()->bundleWithPred(); } else { // $longbr: // daddiu $sp, $sp, -16 @@ -404,10 +410,15 @@ void MipsLongBranch::expandToLongBranch(MBBInfo &I) { BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::LD), Mips::RA_64) .addReg(Mips::SP_64).addImm(0); - MIBundleBuilder(*BalTgtMBB, Pos) - .append(BuildMI(*MF, DL, TII->get(Mips::JR64)).addReg(Mips::AT_64)) - .append(BuildMI(*MF, DL, TII->get(Mips::DADDiu), Mips::SP_64) - .addReg(Mips::SP_64).addImm(16)); + if (Subtarget.hasMips64r6()) + BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::JALR64)) + .addReg(Mips::ZERO_64).addReg(Mips::AT_64); + else + BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::JR64)).addReg(Mips::AT_64); + + BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::DADDiu), Mips::SP_64) + .addReg(Mips::SP_64).addImm(16); + BalTgtMBB->rbegin()->bundleWithPred(); } assert(LongBrMBB->size() + BalTgtMBB->size() == LongBranchSeqSize); @@ -457,8 +468,7 @@ bool MipsLongBranch::runOnMachineFunction(MachineFunction &F) { if (STI.inMips16Mode() || !STI.enableLongBranchPass()) return false; - if ((TM.getRelocationModel() == Reloc::PIC_) && - static_cast<const MipsTargetMachine &>(TM).getABI().IsO32() && + if (IsPIC && static_cast<const MipsTargetMachine &>(TM).getABI().IsO32() && F.getInfo<MipsFunctionInfo>()->globalBaseRegSet()) emitGPDisp(F, TII); @@ -506,7 +516,7 @@ bool MipsLongBranch::runOnMachineFunction(MachineFunction &F) { return true; // Compute basic block addresses. - if (TM.getRelocationModel() == Reloc::PIC_) { + if (IsPIC) { uint64_t Address = 0; for (I = MBBInfos.begin(); I != E; Address += I->Size, ++I) diff --git a/lib/Target/Mips/MipsMCInstLower.cpp b/lib/Target/Mips/MipsMCInstLower.cpp index 80d9b75b85b7d..d5bc4e537c37c 100644 --- a/lib/Target/Mips/MipsMCInstLower.cpp +++ b/lib/Target/Mips/MipsMCInstLower.cpp @@ -36,36 +36,87 @@ void MipsMCInstLower::Initialize(MCContext *C) { MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO, MachineOperandType MOTy, unsigned Offset) const { - MCSymbolRefExpr::VariantKind Kind; + MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None; + MipsMCExpr::MipsExprKind TargetKind = MipsMCExpr::MEK_None; + bool IsGpOff = false; const MCSymbol *Symbol; switch(MO.getTargetFlags()) { - default: llvm_unreachable("Invalid target flag!"); - case MipsII::MO_NO_FLAG: Kind = MCSymbolRefExpr::VK_None; break; - case MipsII::MO_GPREL: Kind = MCSymbolRefExpr::VK_Mips_GPREL; break; - case MipsII::MO_GOT_CALL: Kind = MCSymbolRefExpr::VK_Mips_GOT_CALL; break; - case MipsII::MO_GOT16: Kind = MCSymbolRefExpr::VK_Mips_GOT16; break; - case MipsII::MO_GOT: Kind = MCSymbolRefExpr::VK_Mips_GOT; break; - case MipsII::MO_ABS_HI: Kind = MCSymbolRefExpr::VK_Mips_ABS_HI; break; - case MipsII::MO_ABS_LO: Kind = MCSymbolRefExpr::VK_Mips_ABS_LO; break; - case MipsII::MO_TLSGD: Kind = MCSymbolRefExpr::VK_Mips_TLSGD; break; - case MipsII::MO_TLSLDM: Kind = MCSymbolRefExpr::VK_Mips_TLSLDM; break; - case MipsII::MO_DTPREL_HI: Kind = MCSymbolRefExpr::VK_Mips_DTPREL_HI; break; - case MipsII::MO_DTPREL_LO: Kind = MCSymbolRefExpr::VK_Mips_DTPREL_LO; break; - case MipsII::MO_GOTTPREL: Kind = MCSymbolRefExpr::VK_Mips_GOTTPREL; break; - case MipsII::MO_TPREL_HI: Kind = MCSymbolRefExpr::VK_Mips_TPREL_HI; break; - case MipsII::MO_TPREL_LO: Kind = MCSymbolRefExpr::VK_Mips_TPREL_LO; break; - case MipsII::MO_GPOFF_HI: Kind = MCSymbolRefExpr::VK_Mips_GPOFF_HI; break; - case MipsII::MO_GPOFF_LO: Kind = MCSymbolRefExpr::VK_Mips_GPOFF_LO; break; - case MipsII::MO_GOT_DISP: Kind = MCSymbolRefExpr::VK_Mips_GOT_DISP; break; - case MipsII::MO_GOT_PAGE: Kind = MCSymbolRefExpr::VK_Mips_GOT_PAGE; break; - case MipsII::MO_GOT_OFST: Kind = MCSymbolRefExpr::VK_Mips_GOT_OFST; break; - case MipsII::MO_HIGHER: Kind = MCSymbolRefExpr::VK_Mips_HIGHER; break; - case MipsII::MO_HIGHEST: Kind = MCSymbolRefExpr::VK_Mips_HIGHEST; break; - case MipsII::MO_GOT_HI16: Kind = MCSymbolRefExpr::VK_Mips_GOT_HI16; break; - case MipsII::MO_GOT_LO16: Kind = MCSymbolRefExpr::VK_Mips_GOT_LO16; break; - case MipsII::MO_CALL_HI16: Kind = MCSymbolRefExpr::VK_Mips_CALL_HI16; break; - case MipsII::MO_CALL_LO16: Kind = MCSymbolRefExpr::VK_Mips_CALL_LO16; break; + default: + llvm_unreachable("Invalid target flag!"); + case MipsII::MO_NO_FLAG: + break; + case MipsII::MO_GPREL: + TargetKind = MipsMCExpr::MEK_GPREL; + break; + case MipsII::MO_GOT_CALL: + TargetKind = MipsMCExpr::MEK_GOT_CALL; + break; + case MipsII::MO_GOT: + TargetKind = MipsMCExpr::MEK_GOT; + break; + case MipsII::MO_ABS_HI: + TargetKind = MipsMCExpr::MEK_HI; + break; + case MipsII::MO_ABS_LO: + TargetKind = MipsMCExpr::MEK_LO; + break; + case MipsII::MO_TLSGD: + TargetKind = MipsMCExpr::MEK_TLSGD; + break; + case MipsII::MO_TLSLDM: + TargetKind = MipsMCExpr::MEK_TLSLDM; + break; + case MipsII::MO_DTPREL_HI: + TargetKind = MipsMCExpr::MEK_DTPREL_HI; + break; + case MipsII::MO_DTPREL_LO: + TargetKind = MipsMCExpr::MEK_DTPREL_LO; + break; + case MipsII::MO_GOTTPREL: + TargetKind = MipsMCExpr::MEK_GOTTPREL; + break; + case MipsII::MO_TPREL_HI: + TargetKind = MipsMCExpr::MEK_TPREL_HI; + break; + case MipsII::MO_TPREL_LO: + TargetKind = MipsMCExpr::MEK_TPREL_LO; + break; + case MipsII::MO_GPOFF_HI: + TargetKind = MipsMCExpr::MEK_HI; + IsGpOff = true; + break; + case MipsII::MO_GPOFF_LO: + TargetKind = MipsMCExpr::MEK_LO; + IsGpOff = true; + break; + case MipsII::MO_GOT_DISP: + TargetKind = MipsMCExpr::MEK_GOT_DISP; + break; + case MipsII::MO_GOT_HI16: + TargetKind = MipsMCExpr::MEK_GOT_HI16; + break; + case MipsII::MO_GOT_LO16: + TargetKind = MipsMCExpr::MEK_GOT_LO16; + break; + case MipsII::MO_GOT_PAGE: + TargetKind = MipsMCExpr::MEK_GOT_PAGE; + break; + case MipsII::MO_GOT_OFST: + TargetKind = MipsMCExpr::MEK_GOT_OFST; + break; + case MipsII::MO_HIGHER: + TargetKind = MipsMCExpr::MEK_HIGHER; + break; + case MipsII::MO_HIGHEST: + TargetKind = MipsMCExpr::MEK_HIGHEST; + break; + case MipsII::MO_CALL_HI16: + TargetKind = MipsMCExpr::MEK_CALL_HI16; + break; + case MipsII::MO_CALL_LO16: + TargetKind = MipsMCExpr::MEK_CALL_LO16; + break; } switch (MOTy) { @@ -106,30 +157,23 @@ MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO, llvm_unreachable("<unknown operand type>"); } - const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::create(Symbol, Kind, *Ctx); + const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, Kind, *Ctx); - if (!Offset) - return MCOperand::createExpr(MCSym); + if (Offset) { + // Assume offset is never negative. + assert(Offset > 0); - // Assume offset is never negative. - assert(Offset > 0); + Expr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Offset, *Ctx), + *Ctx); + } - const MCConstantExpr *OffsetExpr = MCConstantExpr::create(Offset, *Ctx); - const MCBinaryExpr *Add = MCBinaryExpr::createAdd(MCSym, OffsetExpr, *Ctx); - return MCOperand::createExpr(Add); -} + if (IsGpOff) + Expr = MipsMCExpr::createGpOff(TargetKind, Expr, *Ctx); + else if (TargetKind != MipsMCExpr::MEK_None) + Expr = MipsMCExpr::create(TargetKind, Expr, *Ctx); -/* -static void CreateMCInst(MCInst& Inst, unsigned Opc, const MCOperand &Opnd0, - const MCOperand &Opnd1, - const MCOperand &Opnd2 = MCOperand()) { - Inst.setOpcode(Opc); - Inst.addOperand(Opnd0); - Inst.addOperand(Opnd1); - if (Opnd2.isValid()) - Inst.addOperand(Opnd2); + return MCOperand::createExpr(Expr); } -*/ MCOperand MipsMCInstLower::LowerOperand(const MachineOperand &MO, unsigned offset) const { @@ -160,7 +204,7 @@ MCOperand MipsMCInstLower::LowerOperand(const MachineOperand &MO, MCOperand MipsMCInstLower::createSub(MachineBasicBlock *BB1, MachineBasicBlock *BB2, - MCSymbolRefExpr::VariantKind Kind) const { + MipsMCExpr::MipsExprKind 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); @@ -178,12 +222,12 @@ lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const { // Create %hi($tgt-$baltgt). OutMI.addOperand(createSub(MI->getOperand(1).getMBB(), MI->getOperand(2).getMBB(), - MCSymbolRefExpr::VK_Mips_ABS_HI)); + MipsMCExpr::MEK_HI)); } -void MipsMCInstLower:: -lowerLongBranchADDiu(const MachineInstr *MI, MCInst &OutMI, int Opcode, - MCSymbolRefExpr::VariantKind Kind) const { +void MipsMCInstLower::lowerLongBranchADDiu( + const MachineInstr *MI, MCInst &OutMI, int Opcode, + MipsMCExpr::MipsExprKind Kind) const { OutMI.setOpcode(Opcode); // Lower two register operands. @@ -206,17 +250,14 @@ bool MipsMCInstLower::lowerLongBranch(const MachineInstr *MI, lowerLongBranchLUi(MI, OutMI); return true; case Mips::LONG_BRANCH_ADDiu: - lowerLongBranchADDiu(MI, OutMI, Mips::ADDiu, - MCSymbolRefExpr::VK_Mips_ABS_LO); + lowerLongBranchADDiu(MI, OutMI, Mips::ADDiu, MipsMCExpr::MEK_LO); return true; case Mips::LONG_BRANCH_DADDiu: unsigned TargetFlags = MI->getOperand(2).getTargetFlags(); if (TargetFlags == MipsII::MO_ABS_HI) - lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu, - MCSymbolRefExpr::VK_Mips_ABS_HI); + lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu, MipsMCExpr::MEK_HI); else if (TargetFlags == MipsII::MO_ABS_LO) - lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu, - MCSymbolRefExpr::VK_Mips_ABS_LO); + lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu, MipsMCExpr::MEK_LO); else report_fatal_error("Unexpected flags for LONG_BRANCH_DADDiu"); return true; diff --git a/lib/Target/Mips/MipsMCInstLower.h b/lib/Target/Mips/MipsMCInstLower.h index 1ce27e4018503..c25f900054809 100644 --- a/lib/Target/Mips/MipsMCInstLower.h +++ b/lib/Target/Mips/MipsMCInstLower.h @@ -10,7 +10,6 @@ #ifndef LLVM_LIB_TARGET_MIPS_MIPSMCINSTLOWER_H #define LLVM_LIB_TARGET_MIPS_MIPSMCINSTLOWER_H #include "MCTargetDesc/MipsMCExpr.h" -#include "llvm/ADT/SmallVector.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/Support/Compiler.h" @@ -38,11 +37,10 @@ private: MCOperand LowerSymbolOperand(const MachineOperand &MO, MachineOperandType MOTy, unsigned Offset) const; MCOperand createSub(MachineBasicBlock *BB1, MachineBasicBlock *BB2, - MCSymbolRefExpr::VariantKind Kind) const; + MipsMCExpr::MipsExprKind Kind) const; void lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const; - void lowerLongBranchADDiu(const MachineInstr *MI, MCInst &OutMI, - int Opcode, - MCSymbolRefExpr::VariantKind Kind) const; + void lowerLongBranchADDiu(const MachineInstr *MI, MCInst &OutMI, int Opcode, + MipsMCExpr::MipsExprKind Kind) const; bool lowerLongBranch(const MachineInstr *MI, MCInst &OutMI) const; }; } diff --git a/lib/Target/Mips/MipsMSAInstrInfo.td b/lib/Target/Mips/MipsMSAInstrInfo.td index eacfcec78bc7d..deb4345e26628 100644 --- a/lib/Target/Mips/MipsMSAInstrInfo.td +++ b/lib/Target/Mips/MipsMSAInstrInfo.td @@ -65,53 +65,11 @@ def MipsVExtractZExt : SDNode<"MipsISD::VEXTRACT_ZEXT_ELT", def immZExt1Ptr : ImmLeaf<iPTR, [{return isUInt<1>(Imm);}]>; def immZExt2Ptr : ImmLeaf<iPTR, [{return isUInt<2>(Imm);}]>; +def immZExt3Ptr : ImmLeaf<iPTR, [{return isUInt<3>(Imm);}]>; def immZExt4Ptr : ImmLeaf<iPTR, [{return isUInt<4>(Imm);}]>; -def immZExt6Ptr : ImmLeaf<iPTR, [{return isUInt<6>(Imm);}]>; // Operands -def uimm4_ptr : Operand<iPTR> { - let PrintMethod = "printUnsignedImm8"; -} - -def uimm6_ptr : Operand<iPTR> { - let PrintMethod = "printUnsignedImm8"; -} - -def simm5 : Operand<i32>; - -def vsplat_uimm1 : Operand<vAny> { - let PrintMethod = "printUnsignedImm8"; -} - -def vsplat_uimm2 : Operand<vAny> { - let PrintMethod = "printUnsignedImm8"; -} - -def vsplat_uimm3 : Operand<vAny> { - let PrintMethod = "printUnsignedImm8"; -} - -def vsplat_uimm4 : Operand<vAny> { - let PrintMethod = "printUnsignedImm8"; -} - -def vsplat_uimm5 : Operand<vAny> { - let PrintMethod = "printUnsignedImm8"; -} - -def vsplat_uimm6 : Operand<vAny> { - let PrintMethod = "printUnsignedImm8"; -} - -def vsplat_uimm8 : Operand<vAny> { - let PrintMethod = "printUnsignedImm8"; -} - -def vsplat_simm5 : Operand<vAny>; - -def vsplat_simm10 : Operand<vAny>; - def immZExt2Lsa : ImmLeaf<i32, [{return isUInt<2>(Imm - 1);}]>; // Pattern fragments @@ -336,15 +294,33 @@ def vsplat_uimm_inv_pow2 : ComplexPattern<vAny, 1, "selectVSplatUimmInvPow2", // Any build_vector that is a constant splat with only a consecutive sequence // of left-most bits set. -def vsplat_maskl_bits : SplatComplexPattern<vsplat_uimm8, vAny, 1, - "selectVSplatMaskL", - [build_vector, bitconvert]>; +def vsplat_maskl_bits_uimm3 + : SplatComplexPattern<vsplat_uimm3, vAny, 1, "selectVSplatMaskL", + [build_vector, bitconvert]>; +def vsplat_maskl_bits_uimm4 + : SplatComplexPattern<vsplat_uimm4, vAny, 1, "selectVSplatMaskL", + [build_vector, bitconvert]>; +def vsplat_maskl_bits_uimm5 + : SplatComplexPattern<vsplat_uimm5, vAny, 1, "selectVSplatMaskL", + [build_vector, bitconvert]>; +def vsplat_maskl_bits_uimm6 + : SplatComplexPattern<vsplat_uimm6, vAny, 1, "selectVSplatMaskL", + [build_vector, bitconvert]>; // Any build_vector that is a constant splat with only a consecutive sequence // of right-most bits set. -def vsplat_maskr_bits : SplatComplexPattern<vsplat_uimm8, vAny, 1, - "selectVSplatMaskR", - [build_vector, bitconvert]>; +def vsplat_maskr_bits_uimm3 + : SplatComplexPattern<vsplat_uimm3, vAny, 1, "selectVSplatMaskR", + [build_vector, bitconvert]>; +def vsplat_maskr_bits_uimm4 + : SplatComplexPattern<vsplat_uimm4, vAny, 1, "selectVSplatMaskR", + [build_vector, bitconvert]>; +def vsplat_maskr_bits_uimm5 + : SplatComplexPattern<vsplat_uimm5, vAny, 1, "selectVSplatMaskR", + [build_vector, bitconvert]>; +def vsplat_maskr_bits_uimm6 + : SplatComplexPattern<vsplat_uimm6, vAny, 1, "selectVSplatMaskR", + [build_vector, bitconvert]>; // Any build_vector that is a constant splat with a value that equals 1 // FIXME: These should be a ComplexPattern but we can't use them because the @@ -1185,11 +1161,11 @@ class MSA_BIT_X_DESC_BASE<string instr_asm, SDPatternOperator OpNode, } class MSA_BIT_BINSXI_DESC_BASE<string instr_asm, ValueType Ty, - ComplexPattern Mask, RegisterOperand ROWD, + SplatComplexPattern Mask, RegisterOperand ROWD, RegisterOperand ROWS = ROWD, InstrItinClass itin = NoItinerary> { dag OutOperandList = (outs ROWD:$wd); - dag InOperandList = (ins ROWD:$wd_in, ROWS:$ws, vsplat_uimm8:$m); + dag InOperandList = (ins ROWD:$wd_in, ROWS:$ws, Mask.OpClass:$m); string AsmString = !strconcat(instr_asm, "\t$wd, $ws, $m"); // Note that binsxi and vselect treat the condition operand the opposite // way to each other. @@ -1202,16 +1178,16 @@ class MSA_BIT_BINSXI_DESC_BASE<string instr_asm, ValueType Ty, } class MSA_BIT_BINSLI_DESC_BASE<string instr_asm, ValueType Ty, - RegisterOperand ROWD, + SplatComplexPattern ImmOp, RegisterOperand ROWD, RegisterOperand ROWS = ROWD, InstrItinClass itin = NoItinerary> : - MSA_BIT_BINSXI_DESC_BASE<instr_asm, Ty, vsplat_maskl_bits, ROWD, ROWS, itin>; + MSA_BIT_BINSXI_DESC_BASE<instr_asm, Ty, ImmOp, ROWD, ROWS, itin>; class MSA_BIT_BINSRI_DESC_BASE<string instr_asm, ValueType Ty, - RegisterOperand ROWD, + SplatComplexPattern ImmOp, RegisterOperand ROWD, RegisterOperand ROWS = ROWD, InstrItinClass itin = NoItinerary> : - MSA_BIT_BINSXI_DESC_BASE<instr_asm, Ty, vsplat_maskr_bits, ROWD, ROWS, itin>; + MSA_BIT_BINSXI_DESC_BASE<instr_asm, Ty, ImmOp, ROWD, ROWS, itin>; class MSA_BIT_SPLAT_DESC_BASE<string instr_asm, SDPatternOperator OpNode, SplatComplexPattern SplatImm, @@ -1225,13 +1201,13 @@ class MSA_BIT_SPLAT_DESC_BASE<string instr_asm, SDPatternOperator OpNode, } class MSA_COPY_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - ValueType VecTy, RegisterOperand ROD, - RegisterOperand ROWS, + ValueType VecTy, Operand ImmOp, ImmLeaf Imm, + RegisterOperand ROD, RegisterOperand ROWS, InstrItinClass itin = NoItinerary> { dag OutOperandList = (outs ROD:$rd); - dag InOperandList = (ins ROWS:$ws, uimm4_ptr:$n); + dag InOperandList = (ins ROWS:$ws, ImmOp:$n); string AsmString = !strconcat(instr_asm, "\t$rd, $ws[$n]"); - list<dag> Pattern = [(set ROD:$rd, (OpNode (VecTy ROWS:$ws), immZExt4Ptr:$n))]; + list<dag> Pattern = [(set ROD:$rd, (OpNode (VecTy ROWS:$ws), Imm:$n))]; InstrItinClass Itinerary = itin; } @@ -1249,9 +1225,10 @@ 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_ptr:$n), - [(set RCD:$wd, (OpNode (VecTy RCWS:$ws), immZExt4Ptr:$n))]> { + Operand ImmOp, ImmLeaf Imm, RegisterClass RCD, + RegisterClass RCWS> : + MSAPseudo<(outs RCD:$wd), (ins RCWS:$ws, ImmOp:$n), + [(set RCD:$wd, (OpNode (VecTy RCWS:$ws), Imm:$n))]> { bit usesCustomInserter = 1; } @@ -1433,23 +1410,22 @@ class MSA_CBRANCH_DESC_BASE<string instr_asm, RegisterOperand ROWD> { } class MSA_INSERT_DESC_BASE<string instr_asm, SDPatternOperator OpNode, - RegisterOperand ROWD, RegisterOperand ROS, + Operand ImmOp, ImmLeaf Imm, RegisterOperand ROWD, + RegisterOperand ROS, InstrItinClass itin = NoItinerary> { dag OutOperandList = (outs ROWD:$wd); - dag InOperandList = (ins ROWD:$wd_in, ROS:$rs, uimm6_ptr:$n); + dag InOperandList = (ins ROWD:$wd_in, ROS:$rs, ImmOp:$n); string AsmString = !strconcat(instr_asm, "\t$wd[$n], $rs"); - list<dag> Pattern = [(set ROWD:$wd, (OpNode ROWD:$wd_in, - ROS:$rs, - immZExt6Ptr:$n))]; + list<dag> Pattern = [(set ROWD:$wd, (OpNode ROWD:$wd_in, ROS:$rs, Imm:$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_ptr:$n, ROFS:$fs), - [(set ROWD:$wd, (OpNode (Ty ROWD:$wd_in), ROFS:$fs, - immZExt6Ptr:$n))]> { + Operand ImmOp, ImmLeaf Imm, RegisterOperand ROWD, + RegisterOperand ROFS> : + MSAPseudo<(outs ROWD:$wd), (ins ROWD:$wd_in, ImmOp:$n, ROFS:$fs), + [(set ROWD:$wd, (OpNode (Ty ROWD:$wd_in), ROFS:$fs, Imm:$n))]> { bit usesCustomInserter = 1; string Constraints = "$wd = $wd_in"; } @@ -1643,10 +1619,10 @@ class BINSL_W_DESC : MSA_3R_BINSX_DESC_BASE<"binsl.w", int_mips_binsl_w, class BINSL_D_DESC : MSA_3R_BINSX_DESC_BASE<"binsl.d", int_mips_binsl_d, MSA128DOpnd>; -class BINSLI_B_DESC : MSA_BIT_BINSLI_DESC_BASE<"binsli.b", v16i8, MSA128BOpnd>; -class BINSLI_H_DESC : MSA_BIT_BINSLI_DESC_BASE<"binsli.h", v8i16, MSA128HOpnd>; -class BINSLI_W_DESC : MSA_BIT_BINSLI_DESC_BASE<"binsli.w", v4i32, MSA128WOpnd>; -class BINSLI_D_DESC : MSA_BIT_BINSLI_DESC_BASE<"binsli.d", v2i64, MSA128DOpnd>; +class BINSLI_B_DESC : MSA_BIT_BINSLI_DESC_BASE<"binsli.b", v16i8, vsplat_maskl_bits_uimm3, MSA128BOpnd>; +class BINSLI_H_DESC : MSA_BIT_BINSLI_DESC_BASE<"binsli.h", v8i16, vsplat_maskl_bits_uimm4, MSA128HOpnd>; +class BINSLI_W_DESC : MSA_BIT_BINSLI_DESC_BASE<"binsli.w", v4i32, vsplat_maskl_bits_uimm5, MSA128WOpnd>; +class BINSLI_D_DESC : MSA_BIT_BINSLI_DESC_BASE<"binsli.d", v2i64, vsplat_maskl_bits_uimm6, MSA128DOpnd>; class BINSR_B_DESC : MSA_3R_BINSX_DESC_BASE<"binsr.b", int_mips_binsr_b, MSA128BOpnd>; @@ -1657,10 +1633,18 @@ class BINSR_W_DESC : MSA_3R_BINSX_DESC_BASE<"binsr.w", int_mips_binsr_w, class BINSR_D_DESC : MSA_3R_BINSX_DESC_BASE<"binsr.d", int_mips_binsr_d, MSA128DOpnd>; -class BINSRI_B_DESC : MSA_BIT_BINSRI_DESC_BASE<"binsri.b", v16i8, MSA128BOpnd>; -class BINSRI_H_DESC : MSA_BIT_BINSRI_DESC_BASE<"binsri.h", v8i16, MSA128HOpnd>; -class BINSRI_W_DESC : MSA_BIT_BINSRI_DESC_BASE<"binsri.w", v4i32, MSA128WOpnd>; -class BINSRI_D_DESC : MSA_BIT_BINSRI_DESC_BASE<"binsri.d", v2i64, MSA128DOpnd>; +class BINSRI_B_DESC + : MSA_BIT_BINSRI_DESC_BASE<"binsri.b", v16i8, vsplat_maskr_bits_uimm3, + MSA128BOpnd>; +class BINSRI_H_DESC + : MSA_BIT_BINSRI_DESC_BASE<"binsri.h", v8i16, vsplat_maskr_bits_uimm4, + MSA128HOpnd>; +class BINSRI_W_DESC + : MSA_BIT_BINSRI_DESC_BASE<"binsri.w", v4i32, vsplat_maskr_bits_uimm5, + MSA128WOpnd>; +class BINSRI_D_DESC + : MSA_BIT_BINSRI_DESC_BASE<"binsri.d", v2i64, vsplat_maskr_bits_uimm6, + MSA128DOpnd>; class BMNZ_V_DESC { dag OutOperandList = (outs MSA128BOpnd:$wd); @@ -1867,24 +1851,33 @@ class CLTI_U_D_DESC : MSA_I5_DESC_BASE<"clti_u.d", vsetult_v2i64, vsplati64_uimm5, MSA128DOpnd>; class COPY_S_B_DESC : MSA_COPY_DESC_BASE<"copy_s.b", vextract_sext_i8, v16i8, - GPR32Opnd, MSA128BOpnd>; + uimm4_ptr, immZExt4Ptr, GPR32Opnd, + MSA128BOpnd>; class COPY_S_H_DESC : MSA_COPY_DESC_BASE<"copy_s.h", vextract_sext_i16, v8i16, - GPR32Opnd, MSA128HOpnd>; + uimm3_ptr, immZExt3Ptr, GPR32Opnd, + MSA128HOpnd>; class COPY_S_W_DESC : MSA_COPY_DESC_BASE<"copy_s.w", vextract_sext_i32, v4i32, - GPR32Opnd, MSA128WOpnd>; + uimm2_ptr, immZExt2Ptr, GPR32Opnd, + MSA128WOpnd>; class COPY_S_D_DESC : MSA_COPY_DESC_BASE<"copy_s.d", vextract_sext_i64, v2i64, - GPR64Opnd, MSA128DOpnd>; + uimm1_ptr, immZExt1Ptr, GPR64Opnd, + MSA128DOpnd>; class COPY_U_B_DESC : MSA_COPY_DESC_BASE<"copy_u.b", vextract_zext_i8, v16i8, - GPR32Opnd, MSA128BOpnd>; + uimm4_ptr, immZExt4Ptr, GPR32Opnd, + MSA128BOpnd>; class COPY_U_H_DESC : MSA_COPY_DESC_BASE<"copy_u.h", vextract_zext_i16, v8i16, - GPR32Opnd, MSA128HOpnd>; + uimm3_ptr, immZExt3Ptr, GPR32Opnd, + MSA128HOpnd>; class COPY_U_W_DESC : MSA_COPY_DESC_BASE<"copy_u.w", vextract_zext_i32, v4i32, - GPR32Opnd, MSA128WOpnd>; + uimm2_ptr, immZExt2Ptr, GPR32Opnd, + MSA128WOpnd>; -class COPY_FW_PSEUDO_DESC : MSA_COPY_PSEUDO_BASE<vector_extract, v4f32, FGR32, +class COPY_FW_PSEUDO_DESC : MSA_COPY_PSEUDO_BASE<vector_extract, v4f32, + uimm2_ptr, immZExt2Ptr, FGR32, MSA128W>; -class COPY_FD_PSEUDO_DESC : MSA_COPY_PSEUDO_BASE<vector_extract, v2f64, FGR64, +class COPY_FD_PSEUDO_DESC : MSA_COPY_PSEUDO_BASE<vector_extract, v2f64, + uimm1_ptr, immZExt1Ptr, FGR64, MSA128D>; class CTCMSA_DESC { @@ -2249,14 +2242,14 @@ class ILVR_H_DESC : MSA_3R_DESC_BASE<"ilvr.h", MipsILVR, MSA128HOpnd>; class ILVR_W_DESC : MSA_3R_DESC_BASE<"ilvr.w", MipsILVR, MSA128WOpnd>; class ILVR_D_DESC : MSA_3R_DESC_BASE<"ilvr.d", MipsILVR, MSA128DOpnd>; -class INSERT_B_DESC : MSA_INSERT_DESC_BASE<"insert.b", vinsert_v16i8, - MSA128BOpnd, GPR32Opnd>; -class INSERT_H_DESC : MSA_INSERT_DESC_BASE<"insert.h", vinsert_v8i16, - MSA128HOpnd, GPR32Opnd>; -class INSERT_W_DESC : MSA_INSERT_DESC_BASE<"insert.w", vinsert_v4i32, - MSA128WOpnd, GPR32Opnd>; -class INSERT_D_DESC : MSA_INSERT_DESC_BASE<"insert.d", vinsert_v2i64, - MSA128DOpnd, GPR64Opnd>; +class INSERT_B_DESC : MSA_INSERT_DESC_BASE<"insert.b", vinsert_v16i8, uimm4, + immZExt4Ptr, MSA128BOpnd, GPR32Opnd>; +class INSERT_H_DESC : MSA_INSERT_DESC_BASE<"insert.h", vinsert_v8i16, uimm3, + immZExt3Ptr, MSA128HOpnd, GPR32Opnd>; +class INSERT_W_DESC : MSA_INSERT_DESC_BASE<"insert.w", vinsert_v4i32, uimm2, + immZExt2Ptr, MSA128WOpnd, GPR32Opnd>; +class INSERT_D_DESC : MSA_INSERT_DESC_BASE<"insert.d", vinsert_v2i64, uimm1, + immZExt1Ptr, MSA128DOpnd, GPR64Opnd>; class INSERT_B_VIDX_PSEUDO_DESC : MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v16i8, MSA128BOpnd, GPR32Opnd, GPR32Opnd>; @@ -2268,8 +2261,10 @@ class INSERT_D_VIDX_PSEUDO_DESC : MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v2i64, MSA128DOpnd, GPR64Opnd, GPR32Opnd>; class INSERT_FW_PSEUDO_DESC : MSA_INSERT_PSEUDO_BASE<vector_insert, v4f32, + uimm2, immZExt2Ptr, MSA128WOpnd, FGR32Opnd>; class INSERT_FD_PSEUDO_DESC : MSA_INSERT_PSEUDO_BASE<vector_insert, v2f64, + uimm1, immZExt1Ptr, MSA128DOpnd, FGR64Opnd>; class INSERT_FW_VIDX_PSEUDO_DESC : @@ -2302,7 +2297,7 @@ class INSVE_D_DESC : MSA_INSVE_DESC_BASE<"insve.d", insve_v2i64, uimm1, immZExt1 class LD_DESC_BASE<string instr_asm, SDPatternOperator OpNode, ValueType TyNode, RegisterOperand ROWD, - Operand MemOpnd = mem_msa, ComplexPattern Addr = addrimm10, + Operand MemOpnd, ComplexPattern Addr = addrimm10, InstrItinClass itin = NoItinerary> { dag OutOperandList = (outs ROWD:$wd); dag InOperandList = (ins MemOpnd:$addr); @@ -2312,10 +2307,10 @@ class LD_DESC_BASE<string instr_asm, SDPatternOperator OpNode, string DecoderMethod = "DecodeMSA128Mem"; } -class LD_B_DESC : LD_DESC_BASE<"ld.b", load, v16i8, MSA128BOpnd>; -class LD_H_DESC : LD_DESC_BASE<"ld.h", load, v8i16, MSA128HOpnd>; -class LD_W_DESC : LD_DESC_BASE<"ld.w", load, v4i32, MSA128WOpnd>; -class LD_D_DESC : LD_DESC_BASE<"ld.d", load, v2i64, MSA128DOpnd>; +class LD_B_DESC : LD_DESC_BASE<"ld.b", load, v16i8, MSA128BOpnd, mem_simm10>; +class LD_H_DESC : LD_DESC_BASE<"ld.h", load, v8i16, MSA128HOpnd, mem_simm10_lsl1>; +class LD_W_DESC : LD_DESC_BASE<"ld.w", load, v4i32, MSA128WOpnd, mem_simm10_lsl2>; +class LD_D_DESC : LD_DESC_BASE<"ld.d", load, v2i64, MSA128DOpnd, mem_simm10_lsl3>; class LDI_B_DESC : MSA_I10_LDI_DESC_BASE<"ldi.b", MSA128BOpnd>; class LDI_H_DESC : MSA_I10_LDI_DESC_BASE<"ldi.h", MSA128HOpnd>; @@ -2323,19 +2318,18 @@ class LDI_W_DESC : MSA_I10_LDI_DESC_BASE<"ldi.w", MSA128WOpnd>; class LDI_D_DESC : MSA_I10_LDI_DESC_BASE<"ldi.d", MSA128DOpnd>; class LSA_DESC_BASE<string instr_asm, RegisterOperand RORD, - RegisterOperand RORS = RORD, RegisterOperand RORT = RORD, - InstrItinClass itin = NoItinerary > { + InstrItinClass itin = NoItinerary> { dag OutOperandList = (outs RORD:$rd); - dag InOperandList = (ins RORS:$rs, RORT:$rt, uimm2_plus1:$sa); + dag InOperandList = (ins RORD:$rs, RORD:$rt, uimm2_plus1:$sa); string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt, $sa"); - list<dag> Pattern = [(set RORD:$rd, (add RORT:$rt, - (shl RORS:$rs, + list<dag> Pattern = [(set RORD:$rd, (add RORD:$rt, + (shl RORD:$rs, immZExt2Lsa:$sa)))]; InstrItinClass Itinerary = itin; } -class LSA_DESC : LSA_DESC_BASE<"lsa", GPR32Opnd>; -class DLSA_DESC : LSA_DESC_BASE<"dlsa", GPR64Opnd>; +class LSA_DESC : LSA_DESC_BASE<"lsa", GPR32Opnd, II_LSA>; +class DLSA_DESC : LSA_DESC_BASE<"dlsa", GPR64Opnd, II_DLSA>; class MADD_Q_H_DESC : MSA_3RF_4RF_DESC_BASE<"madd_q.h", int_mips_madd_q_h, MSA128HOpnd>; @@ -2636,7 +2630,7 @@ class SRLRI_D_DESC : MSA_BIT_X_DESC_BASE<"srlri.d", int_mips_srlri_d, uimm6, class ST_DESC_BASE<string instr_asm, SDPatternOperator OpNode, ValueType TyNode, RegisterOperand ROWD, - Operand MemOpnd = mem_msa, ComplexPattern Addr = addrimm10, + Operand MemOpnd, ComplexPattern Addr = addrimm10, InstrItinClass itin = NoItinerary> { dag OutOperandList = (outs); dag InOperandList = (ins ROWD:$wd, MemOpnd:$addr); @@ -2646,10 +2640,10 @@ class ST_DESC_BASE<string instr_asm, SDPatternOperator OpNode, string DecoderMethod = "DecodeMSA128Mem"; } -class ST_B_DESC : ST_DESC_BASE<"st.b", store, v16i8, MSA128BOpnd>; -class ST_H_DESC : ST_DESC_BASE<"st.h", store, v8i16, MSA128HOpnd>; -class ST_W_DESC : ST_DESC_BASE<"st.w", store, v4i32, MSA128WOpnd>; -class ST_D_DESC : ST_DESC_BASE<"st.d", store, v2i64, MSA128DOpnd>; +class ST_B_DESC : ST_DESC_BASE<"st.b", store, v16i8, MSA128BOpnd, mem_simm10>; +class ST_H_DESC : ST_DESC_BASE<"st.h", store, v8i16, MSA128HOpnd, mem_simm10_lsl1>; +class ST_W_DESC : ST_DESC_BASE<"st.w", store, v4i32, MSA128WOpnd, mem_simm10_lsl2>; +class ST_D_DESC : ST_DESC_BASE<"st.d", store, v2i64, MSA128DOpnd, mem_simm10_lsl3>; class SUBS_S_B_DESC : MSA_3R_DESC_BASE<"subs_s.b", int_mips_subs_s_b, MSA128BOpnd>; diff --git a/lib/Target/Mips/MipsMachineFunction.cpp b/lib/Target/Mips/MipsMachineFunction.cpp index c7d2738af1d4a..f81e64e06f433 100644 --- a/lib/Target/Mips/MipsMachineFunction.cpp +++ b/lib/Target/Mips/MipsMachineFunction.cpp @@ -42,7 +42,9 @@ unsigned MipsFunctionInfo::getGlobalBaseReg() { STI.inMips16Mode() ? &Mips::CPU16RegsRegClass : STI.inMicroMipsMode() - ? &Mips::GPRMM16RegClass + ? STI.hasMips64() + ? &Mips::GPRMM16_64RegClass + : &Mips::GPRMM16RegClass : static_cast<const MipsTargetMachine &>(MF.getTarget()) .getABI() .IsN64() @@ -51,18 +53,6 @@ unsigned MipsFunctionInfo::getGlobalBaseReg() { return GlobalBaseReg = MF.getRegInfo().createVirtualRegister(RC); } -bool MipsFunctionInfo::mips16SPAliasRegSet() const { - return Mips16SPAliasReg; -} -unsigned MipsFunctionInfo::getMips16SPAliasReg() { - // Return if it has already been initialized. - if (Mips16SPAliasReg) - return Mips16SPAliasReg; - - const TargetRegisterClass *RC = &Mips::CPU16RegsRegClass; - return Mips16SPAliasReg = MF.getRegInfo().createVirtualRegister(RC); -} - void MipsFunctionInfo::createEhDataRegsFI() { for (int I = 0; I < 4; ++I) { const TargetRegisterClass *RC = diff --git a/lib/Target/Mips/MipsMachineFunction.h b/lib/Target/Mips/MipsMachineFunction.h index a2f6ee03604fc..c9e5fddc19325 100644 --- a/lib/Target/Mips/MipsMachineFunction.h +++ b/lib/Target/Mips/MipsMachineFunction.h @@ -19,12 +19,9 @@ #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/PseudoSourceValue.h" -#include "llvm/IR/ValueMap.h" #include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetMachine.h" #include <map> -#include <string> -#include <utility> namespace llvm { @@ -33,8 +30,8 @@ namespace llvm { class MipsFunctionInfo : public MachineFunctionInfo { public: MipsFunctionInfo(MachineFunction &MF) - : MF(MF), SRetReturnReg(0), GlobalBaseReg(0), Mips16SPAliasReg(0), - VarArgsFrameIndex(0), CallsEhReturn(false), IsISR(false), SaveS2(false), + : MF(MF), SRetReturnReg(0), GlobalBaseReg(0), VarArgsFrameIndex(0), + CallsEhReturn(false), IsISR(false), SaveS2(false), MoveF64ViaSpillFI(-1) {} ~MipsFunctionInfo(); @@ -45,9 +42,6 @@ public: bool globalBaseRegSet() const; unsigned getGlobalBaseReg(); - bool mips16SPAliasRegSet() const; - unsigned getMips16SPAliasReg(); - int getVarArgsFrameIndex() const { return VarArgsFrameIndex; } void setVarArgsFrameIndex(int Index) { VarArgsFrameIndex = Index; } @@ -104,11 +98,6 @@ private: /// relocation models. unsigned GlobalBaseReg; - /// Mips16SPAliasReg - keeps track of the virtual register initialized for - /// use as an alias for SP for use in load/store of halfword/byte from/to - /// the stack - unsigned Mips16SPAliasReg; - /// VarArgsFrameIndex - FrameIndex for start of varargs area. int VarArgsFrameIndex; diff --git a/lib/Target/Mips/MipsOs16.cpp b/lib/Target/Mips/MipsOs16.cpp index b6cd79193cfcd..8136907de4d7e 100644 --- a/lib/Target/Mips/MipsOs16.cpp +++ b/lib/Target/Mips/MipsOs16.cpp @@ -111,22 +111,27 @@ static bool needsFP(Function &F) { bool MipsOs16::runOnModule(Module &M) { bool usingMask = Mips32FunctionMask.length() > 0; bool doneUsingMask = false; // this will make it stop repeating + DEBUG(dbgs() << "Run on Module MipsOs16 \n" << Mips32FunctionMask << "\n"); if (usingMask) DEBUG(dbgs() << "using mask \n" << Mips32FunctionMask << "\n"); + unsigned int functionIndex = 0; bool modified = false; - for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { - if (F->isDeclaration()) continue; - DEBUG(dbgs() << "Working on " << F->getName() << "\n"); + + for (auto &F : M) { + if (F.isDeclaration()) + continue; + + DEBUG(dbgs() << "Working on " << F.getName() << "\n"); if (usingMask) { if (!doneUsingMask) { if (functionIndex == Mips32FunctionMask.length()) functionIndex = 0; switch (Mips32FunctionMask[functionIndex]) { case '1': - DEBUG(dbgs() << "mask forced mips32: " << F->getName() << "\n"); - F->addFnAttr("nomips16"); + DEBUG(dbgs() << "mask forced mips32: " << F.getName() << "\n"); + F.addFnAttr("nomips16"); break; case '.': doneUsingMask = true; @@ -138,16 +143,17 @@ bool MipsOs16::runOnModule(Module &M) { } } else { - if (needsFP(*F)) { - DEBUG(dbgs() << "os16 forced mips32: " << F->getName() << "\n"); - F->addFnAttr("nomips16"); + if (needsFP(F)) { + DEBUG(dbgs() << "os16 forced mips32: " << F.getName() << "\n"); + F.addFnAttr("nomips16"); } else { - DEBUG(dbgs() << "os16 forced mips16: " << F->getName() << "\n"); - F->addFnAttr("mips16"); + DEBUG(dbgs() << "os16 forced mips16: " << F.getName() << "\n"); + F.addFnAttr("mips16"); } } } + return modified; } diff --git a/lib/Target/Mips/MipsRegisterInfo.cpp b/lib/Target/Mips/MipsRegisterInfo.cpp index 28e5a425849fa..860cf9cfd138c 100644 --- a/lib/Target/Mips/MipsRegisterInfo.cpp +++ b/lib/Target/Mips/MipsRegisterInfo.cpp @@ -13,7 +13,6 @@ #include "MipsRegisterInfo.h" #include "Mips.h" -#include "MipsAnalyzeImmediate.h" #include "MipsInstrInfo.h" #include "MipsMachineFunction.h" #include "MipsSubtarget.h" @@ -21,14 +20,13 @@ #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/CodeGen/MachineRegisterInfo.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DebugInfo.h" #include "llvm/IR/Function.h" #include "llvm/IR/Type.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -52,7 +50,21 @@ const TargetRegisterClass * MipsRegisterInfo::getPointerRegClass(const MachineFunction &MF, unsigned Kind) const { MipsABIInfo ABI = MF.getSubtarget<MipsSubtarget>().getABI(); - return ABI.ArePtrs64bit() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; + MipsPtrClass PtrClassKind = static_cast<MipsPtrClass>(Kind); + + switch (PtrClassKind) { + case MipsPtrClass::Default: + return ABI.ArePtrs64bit() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; + case MipsPtrClass::GPR16MM: + return ABI.ArePtrs64bit() ? &Mips::GPRMM16_64RegClass + : &Mips::GPRMM16RegClass; + case MipsPtrClass::StackPointer: + return ABI.ArePtrs64bit() ? &Mips::SP64RegClass : &Mips::SP32RegClass; + case MipsPtrClass::GlobalPointer: + return ABI.ArePtrs64bit() ? &Mips::GP64RegClass : &Mips::GP32RegClass; + } + + llvm_unreachable("Unknown pointer kind"); } unsigned diff --git a/lib/Target/Mips/MipsRegisterInfo.h b/lib/Target/Mips/MipsRegisterInfo.h index 5de68a21b73ea..32f835e83108a 100644 --- a/lib/Target/Mips/MipsRegisterInfo.h +++ b/lib/Target/Mips/MipsRegisterInfo.h @@ -23,18 +23,23 @@ namespace llvm { class MipsRegisterInfo : public MipsGenRegisterInfo { public: - MipsRegisterInfo(); + enum class MipsPtrClass { + /// The default register class for integer values. + Default = 0, + /// The subset of registers permitted in certain microMIPS instructions + /// such as lw16. + GPR16MM = 1, + /// The stack pointer only. + StackPointer = 2, + /// The global pointer only. + GlobalPointer = 3, + }; - /// getRegisterNumbering - Given the enum value for some register, e.g. - /// Mips::RA, return the number that it corresponds to (e.g. 31). - static unsigned getRegisterNumbering(unsigned RegEnum); + MipsRegisterInfo(); /// Get PIC indirect call register static unsigned getPICCallReg(); - /// Adjust the Mips stack frame. - void adjustMipsStackFrame(MachineFunction &MF) const; - /// Code Generation virtual methods... const TargetRegisterClass *getPointerRegClass(const MachineFunction &MF, unsigned Kind) const override; @@ -57,9 +62,6 @@ public: int SPAdj, unsigned FIOperandNum, RegScavenger *RS = nullptr) const override; - void processFunctionBeforeFrameFinalized(MachineFunction &MF, - RegScavenger *RS = nullptr) const; - // Stack realignment queries. bool canRealignStack(const MachineFunction &MF) const override; diff --git a/lib/Target/Mips/MipsRegisterInfo.td b/lib/Target/Mips/MipsRegisterInfo.td index 02bcac5a3ddb3..cfce7c8e65337 100644 --- a/lib/Target/Mips/MipsRegisterInfo.td +++ b/lib/Target/Mips/MipsRegisterInfo.td @@ -330,6 +330,12 @@ def GPR64 : RegisterClass<"Mips", [i64], 64, (add // Reserved K0_64, K1_64, GP_64, SP_64, FP_64, RA_64)>; +def GPRMM16_64 : RegisterClass<"Mips", [i64], 64, (add + // Callee save + S0_64, S1_64, + // Return Values and Arguments + V0_64, V1_64, A0_64, A1_64, A2_64, A3_64)>; + def CPU16Regs : RegisterClass<"Mips", [i32], 32, (add // Return Values and Arguments V0, V1, A0, A1, A2, A3, @@ -447,6 +453,13 @@ def COP2 : RegisterClass<"Mips", [i32], 32, (sequence "COP2%u", 0, 31)>, def COP3 : RegisterClass<"Mips", [i32], 32, (sequence "COP3%u", 0, 31)>, Unallocatable; +// Stack pointer and global pointer classes for instructions that are limited +// to a single register such as lwgp/lwsp in microMIPS. +def SP32 : RegisterClass<"Mips", [i32], 32, (add SP)>, Unallocatable; +def SP64 : RegisterClass<"Mips", [i64], 64, (add SP_64)>, Unallocatable; +def GP32 : RegisterClass<"Mips", [i32], 32, (add GP)>, Unallocatable; +def GP64 : RegisterClass<"Mips", [i64], 64, (add GP_64)>, Unallocatable; + // Octeon multiplier and product registers def OCTEON_MPL : RegisterClass<"Mips", [i64], 64, (add MPL0, MPL1, MPL2)>, Unallocatable; diff --git a/lib/Target/Mips/MipsSEFrameLowering.cpp b/lib/Target/Mips/MipsSEFrameLowering.cpp index a4abd62ee607f..a7ddd7752736b 100644 --- a/lib/Target/Mips/MipsSEFrameLowering.cpp +++ b/lib/Target/Mips/MipsSEFrameLowering.cpp @@ -13,7 +13,6 @@ #include "MipsSEFrameLowering.h" #include "MCTargetDesc/MipsBaseInfo.h" -#include "MipsAnalyzeImmediate.h" #include "MipsMachineFunction.h" #include "MipsSEInstrInfo.h" #include "MipsSubtarget.h" @@ -26,7 +25,6 @@ #include "llvm/CodeGen/RegisterScavenging.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/Function.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Target/TargetOptions.h" using namespace llvm; @@ -87,10 +85,10 @@ ExpandPseudo::ExpandPseudo(MachineFunction &MF_) bool ExpandPseudo::expand() { bool Expanded = false; - for (MachineFunction::iterator BB = MF.begin(), BBEnd = MF.end(); - BB != BBEnd; ++BB) - for (Iter I = BB->begin(), End = BB->end(); I != End;) - Expanded |= expandInstr(*BB, I++); + for (auto &MBB : MF) { + for (Iter I = MBB.begin(), End = MBB.end(); I != End;) + Expanded |= expandInstr(MBB, I++); + } return Expanded; } @@ -518,7 +516,7 @@ void MipsSEFrameLowering::emitPrologue(MachineFunction &MF, unsigned VR = MF.getRegInfo().createVirtualRegister(RC); assert(isInt<16>(MFI->getMaxAlignment()) && "Function's alignment size requirement is not supported."); - int MaxAlign = - (signed) MFI->getMaxAlignment(); + int MaxAlign = -(int)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); diff --git a/lib/Target/Mips/MipsSEISelDAGToDAG.cpp b/lib/Target/Mips/MipsSEISelDAGToDAG.cpp index 6f001ea74b304..d9528da5a96de 100644 --- a/lib/Target/Mips/MipsSEISelDAGToDAG.cpp +++ b/lib/Target/Mips/MipsSEISelDAGToDAG.cpp @@ -47,7 +47,8 @@ void MipsSEDAGToDAGISel::addDSPCtrlRegOperands(bool IsDef, MachineInstr &MI, MachineFunction &MF) { MachineInstrBuilder MIB(MF, &MI); unsigned Mask = MI.getOperand(1).getImm(); - unsigned Flag = IsDef ? RegState::ImplicitDefine : RegState::Implicit; + unsigned Flag = + IsDef ? RegState::ImplicitDefine : RegState::Implicit | RegState::Undef; if (Mask & 1) MIB.addReg(Mips::DSPPos, Flag); @@ -162,7 +163,7 @@ void MipsSEDAGToDAGISel::initGlobalBaseReg(MachineFunction &MF) { return; } - if (MF.getTarget().getRelocationModel() == Reloc::Static) { + if (!MF.getTarget().isPositionIndependent()) { // Set global register to __gnu_local_gp. // // lui $v0, %hi(__gnu_local_gp) @@ -220,21 +221,25 @@ void MipsSEDAGToDAGISel::processFunctionAfterISel(MachineFunction &MF) { MachineRegisterInfo *MRI = &MF.getRegInfo(); - for (MachineFunction::iterator MFI = MF.begin(), MFE = MF.end(); MFI != MFE; - ++MFI) - for (MachineBasicBlock::iterator I = MFI->begin(); I != MFI->end(); ++I) { - if (I->getOpcode() == Mips::RDDSP) - addDSPCtrlRegOperands(false, *I, MF); - else if (I->getOpcode() == Mips::WRDSP) - addDSPCtrlRegOperands(true, *I, MF); - else - replaceUsesWithZeroReg(MRI, *I); + for (auto &MBB: MF) { + for (auto &MI: MBB) { + switch (MI.getOpcode()) { + case Mips::RDDSP: + addDSPCtrlRegOperands(false, MI, MF); + break; + case Mips::WRDSP: + addDSPCtrlRegOperands(true, MI, MF); + break; + default: + replaceUsesWithZeroReg(MRI, MI); + } } + } } -SDNode *MipsSEDAGToDAGISel::selectAddESubE(unsigned MOp, SDValue InFlag, - SDValue CmpLHS, SDLoc DL, - SDNode *Node) const { +void MipsSEDAGToDAGISel::selectAddESubE(unsigned MOp, SDValue InFlag, + SDValue CmpLHS, const SDLoc &DL, + SDNode *Node) const { unsigned Opc = InFlag.getOpcode(); (void)Opc; assert(((Opc == ISD::ADDC || Opc == ISD::ADDE) || @@ -271,8 +276,7 @@ SDNode *MipsSEDAGToDAGISel::selectAddESubE(unsigned MOp, SDValue InFlag, if (!C || C->getZExtValue()) AddCarry = CurDAG->getMachineNode(ADDuOp, DL, VT, SDValue(Carry, 0), RHS); - return CurDAG->SelectNodeTo(Node, MOp, VT, MVT::Glue, LHS, - SDValue(AddCarry, 0)); + CurDAG->SelectNodeTo(Node, MOp, VT, MVT::Glue, LHS, SDValue(AddCarry, 0)); } /// Match frameindex @@ -327,7 +331,7 @@ bool MipsSEDAGToDAGISel::selectAddrRegImm(SDValue Addr, SDValue &Base, return true; } - if (TM.getRelocationModel() != Reloc::PIC_) { + if (!TM.isPositionIndependent()) { if ((Addr.getOpcode() == ISD::TargetExternalSymbol || Addr.getOpcode() == ISD::TargetGlobalAddress)) return false; @@ -364,18 +368,6 @@ bool MipsSEDAGToDAGISel::selectAddrRegImm(SDValue Addr, SDValue &Base, /// ComplexPattern used on MipsInstrInfo /// Used on Mips Load/Store instructions -bool MipsSEDAGToDAGISel::selectAddrRegReg(SDValue Addr, SDValue &Base, - SDValue &Offset) const { - // Operand is a result from an ADD. - if (Addr.getOpcode() == ISD::ADD) { - Base = Addr.getOperand(0); - Offset = Addr.getOperand(1); - return true; - } - - return false; -} - bool MipsSEDAGToDAGISel::selectAddrDefault(SDValue Addr, SDValue &Base, SDValue &Offset) const { Base = Addr; @@ -411,6 +403,18 @@ bool MipsSEDAGToDAGISel::selectAddrRegImm10(SDValue Addr, SDValue &Base, return false; } +/// Used on microMIPS LWC2, LDC2, SWC2 and SDC2 instructions (11-bit offset) +bool MipsSEDAGToDAGISel::selectAddrRegImm11(SDValue Addr, SDValue &Base, + SDValue &Offset) const { + if (selectAddrFrameIndex(Addr, Base, Offset)) + return true; + + if (selectAddrFrameIndexOffset(Addr, Base, Offset, 11)) + return true; + + return false; +} + /// Used on microMIPS Load/Store unaligned instructions (12-bit offset) bool MipsSEDAGToDAGISel::selectAddrRegImm12(SDValue Addr, SDValue &Base, SDValue &Offset) const { @@ -434,12 +438,24 @@ bool MipsSEDAGToDAGISel::selectAddrRegImm16(SDValue Addr, SDValue &Base, return false; } -bool MipsSEDAGToDAGISel::selectIntAddrMM(SDValue Addr, SDValue &Base, +bool MipsSEDAGToDAGISel::selectIntAddr11MM(SDValue Addr, SDValue &Base, + SDValue &Offset) const { + return selectAddrRegImm11(Addr, Base, Offset) || + selectAddrDefault(Addr, Base, Offset); +} + +bool MipsSEDAGToDAGISel::selectIntAddr12MM(SDValue Addr, SDValue &Base, SDValue &Offset) const { return selectAddrRegImm12(Addr, Base, Offset) || selectAddrDefault(Addr, Base, Offset); } +bool MipsSEDAGToDAGISel::selectIntAddr16MM(SDValue Addr, SDValue &Base, + SDValue &Offset) const { + return selectAddrRegImm16(Addr, Base, Offset) || + selectAddrDefault(Addr, Base, Offset); +} + bool MipsSEDAGToDAGISel::selectIntAddrLSL2MM(SDValue Addr, SDValue &Base, SDValue &Offset) const { if (selectAddrFrameIndexOffset(Addr, Base, Offset, 7)) { @@ -702,7 +718,7 @@ bool MipsSEDAGToDAGISel::selectVSplatUimmInvPow2(SDValue N, return false; } -std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) { +bool MipsSEDAGToDAGISel::trySelect(SDNode *Node) { unsigned Opcode = Node->getOpcode(); SDLoc DL(Node); @@ -710,16 +726,14 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) { // Instruction Selection not handled by the auto-generated // tablegen selection should be handled here. /// - SDNode *Result; - switch(Opcode) { default: break; case ISD::SUBE: { SDValue InFlag = Node->getOperand(2); unsigned Opc = Subtarget->isGP64bit() ? Mips::DSUBu : Mips::SUBu; - Result = selectAddESubE(Opc, InFlag, InFlag.getOperand(0), DL, Node); - return std::make_pair(true, Result); + selectAddESubE(Opc, InFlag, InFlag.getOperand(0), DL, Node); + return true; } case ISD::ADDE: { @@ -727,8 +741,8 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) { break; SDValue InFlag = Node->getOperand(2); unsigned Opc = Subtarget->isGP64bit() ? Mips::DADDu : Mips::ADDu; - Result = selectAddESubE(Opc, InFlag, InFlag.getValue(0), DL, Node); - return std::make_pair(true, Result); + selectAddESubE(Opc, InFlag, InFlag.getValue(0), DL, Node); + return true; } case ISD::ConstantFP: { @@ -737,20 +751,20 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) { if (Subtarget->isGP64bit()) { SDValue Zero = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, Mips::ZERO_64, MVT::i64); - Result = CurDAG->getMachineNode(Mips::DMTC1, DL, MVT::f64, Zero); + ReplaceNode(Node, + CurDAG->getMachineNode(Mips::DMTC1, DL, MVT::f64, Zero)); } else if (Subtarget->isFP64bit()) { SDValue Zero = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, Mips::ZERO, MVT::i32); - Result = CurDAG->getMachineNode(Mips::BuildPairF64_64, DL, MVT::f64, - Zero, Zero); + ReplaceNode(Node, CurDAG->getMachineNode(Mips::BuildPairF64_64, DL, + MVT::f64, Zero, Zero)); } else { SDValue Zero = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL, Mips::ZERO, MVT::i32); - Result = CurDAG->getMachineNode(Mips::BuildPairF64, DL, MVT::f64, Zero, - Zero); + ReplaceNode(Node, CurDAG->getMachineNode(Mips::BuildPairF64, DL, + MVT::f64, Zero, Zero)); } - - return std::make_pair(true, Result); + return true; } break; } @@ -793,7 +807,8 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) { SDValue(RegOpnd, 0), ImmOpnd); } - return std::make_pair(true, RegOpnd); + ReplaceNode(Node, RegOpnd); + return true; } case ISD::INTRINSIC_W_CHAIN: { @@ -806,7 +821,8 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) { SDValue RegIdx = Node->getOperand(2); SDValue Reg = CurDAG->getCopyFromReg(ChainIn, DL, getMSACtrlReg(RegIdx), MVT::i32); - return std::make_pair(true, Reg.getNode()); + ReplaceNode(Node, Reg.getNode()); + return true; } } break; @@ -820,10 +836,10 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) { case Intrinsic::mips_move_v: // Like an assignment but will always produce a move.v even if // unnecessary. - return std::make_pair(true, - CurDAG->getMachineNode(Mips::MOVE_V, DL, - Node->getValueType(0), - Node->getOperand(1))); + ReplaceNode(Node, CurDAG->getMachineNode(Mips::MOVE_V, DL, + Node->getValueType(0), + Node->getOperand(1))); + return true; } break; } @@ -839,7 +855,8 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) { SDValue Value = Node->getOperand(3); SDValue ChainOut = CurDAG->getCopyToReg(ChainIn, DL, getMSACtrlReg(RegIdx), Value); - return std::make_pair(true, ChainOut.getNode()); + ReplaceNode(Node, ChainOut.getNode()); + return true; } } break; @@ -864,8 +881,8 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) { SDValue Chain = CurDAG->getCopyToReg(CurDAG->getEntryNode(), DL, DestReg, SDValue(Rdhwr, 0)); SDValue ResNode = CurDAG->getCopyFromReg(Chain, DL, DestReg, PtrVT); - ReplaceUses(SDValue(Node, 0), ResNode); - return std::make_pair(true, ResNode.getNode()); + ReplaceNode(Node, ResNode.getNode()); + return true; } case ISD::BUILD_VECTOR: { @@ -890,16 +907,16 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) { EVT ViaVecTy; if (!Subtarget->hasMSA() || !BVN->getValueType(0).is128BitVector()) - return std::make_pair(false, nullptr); + return false; if (!BVN->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs, 8, !Subtarget->isLittle())) - return std::make_pair(false, nullptr); + return false; switch (SplatBitSize) { default: - return std::make_pair(false, nullptr); + return false; case 8: LdiOp = Mips::LDI_B; ViaVecTy = MVT::v16i8; @@ -919,7 +936,7 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) { } if (!SplatValue.isSignedIntN(10)) - return std::make_pair(false, nullptr); + return false; SDValue Imm = CurDAG->getTargetConstant(SplatValue, DL, ViaVecTy.getVectorElementType()); @@ -940,12 +957,13 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) { MVT::i32)); } - return std::make_pair(true, Res); + ReplaceNode(Node, Res); + return true; } } - return std::make_pair(false, nullptr); + return false; } bool MipsSEDAGToDAGISel:: @@ -1015,6 +1033,7 @@ SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, return true; } -FunctionPass *llvm::createMipsSEISelDag(MipsTargetMachine &TM) { - return new MipsSEDAGToDAGISel(TM); +FunctionPass *llvm::createMipsSEISelDag(MipsTargetMachine &TM, + CodeGenOpt::Level OptLevel) { + return new MipsSEDAGToDAGISel(TM, OptLevel); } diff --git a/lib/Target/Mips/MipsSEISelDAGToDAG.h b/lib/Target/Mips/MipsSEISelDAGToDAG.h index a894034020e99..0f08b72a334e3 100644 --- a/lib/Target/Mips/MipsSEISelDAGToDAG.h +++ b/lib/Target/Mips/MipsSEISelDAGToDAG.h @@ -21,7 +21,8 @@ namespace llvm { class MipsSEDAGToDAGISel : public MipsDAGToDAGISel { public: - explicit MipsSEDAGToDAGISel(MipsTargetMachine &TM) : MipsDAGToDAGISel(TM) {} + explicit MipsSEDAGToDAGISel(MipsTargetMachine &TM, CodeGenOpt::Level OL) + : MipsDAGToDAGISel(TM, OL) {} private: @@ -34,11 +35,12 @@ private: bool replaceUsesWithZeroReg(MachineRegisterInfo *MRI, const MachineInstr&); - std::pair<SDNode*, SDNode*> selectMULT(SDNode *N, unsigned Opc, SDLoc dl, - EVT Ty, bool HasLo, bool HasHi); + std::pair<SDNode *, SDNode *> selectMULT(SDNode *N, unsigned Opc, + const SDLoc &dl, EVT Ty, bool HasLo, + bool HasHi); - SDNode *selectAddESubE(unsigned MOp, SDValue InFlag, SDValue CmpLHS, - SDLoc DL, SDNode *Node) const; + void selectAddESubE(unsigned MOp, SDValue InFlag, SDValue CmpLHS, + const SDLoc &DL, SDNode *Node) const; bool selectAddrFrameIndex(SDValue Addr, SDValue &Base, SDValue &Offset) const; bool selectAddrFrameIndexOffset(SDValue Addr, SDValue &Base, SDValue &Offset, @@ -47,9 +49,6 @@ private: bool selectAddrRegImm(SDValue Addr, SDValue &Base, SDValue &Offset) const override; - bool selectAddrRegReg(SDValue Addr, SDValue &Base, - SDValue &Offset) const override; - bool selectAddrDefault(SDValue Addr, SDValue &Base, SDValue &Offset) const override; @@ -62,14 +61,23 @@ private: bool selectAddrRegImm10(SDValue Addr, SDValue &Base, SDValue &Offset) const; + bool selectAddrRegImm11(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 selectIntAddr11MM(SDValue Addr, SDValue &Base, + SDValue &Offset) const override; + + bool selectIntAddr12MM(SDValue Addr, SDValue &Base, + SDValue &Offset) const override; + + bool selectIntAddr16MM(SDValue Addr, SDValue &Base, + SDValue &Offset) const override; bool selectIntAddrLSL2MM(SDValue Addr, SDValue &Base, SDValue &Offset) const override; @@ -111,7 +119,7 @@ private: /// starting at bit zero. bool selectVSplatMaskR(SDValue N, SDValue &Imm) const override; - std::pair<bool, SDNode*> selectNode(SDNode *Node) override; + bool trySelect(SDNode *Node) override; void processFunctionAfterISel(MachineFunction &MF) override; @@ -124,8 +132,8 @@ private: std::vector<SDValue> &OutOps) override; }; -FunctionPass *createMipsSEISelDag(MipsTargetMachine &TM); - +FunctionPass *createMipsSEISelDag(MipsTargetMachine &TM, + CodeGenOpt::Level OptLevel); } #endif diff --git a/lib/Target/Mips/MipsSEISelLowering.cpp b/lib/Target/Mips/MipsSEISelLowering.cpp index efe22fba98cee..80c000d5746d7 100644 --- a/lib/Target/Mips/MipsSEISelLowering.cpp +++ b/lib/Target/Mips/MipsSEISelLowering.cpp @@ -793,7 +793,7 @@ static SDValue performSUBECombine(SDNode *N, SelectionDAG &DAG, return SDValue(); } -static SDValue genConstMult(SDValue X, uint64_t C, SDLoc DL, EVT VT, +static SDValue genConstMult(SDValue X, uint64_t C, const SDLoc &DL, EVT VT, EVT ShiftTy, SelectionDAG &DAG) { // Clear the upper (64 - VT.sizeInBits) bits. C &= ((uint64_t)-1) >> (64 - VT.getSizeInBits()); @@ -1111,9 +1111,9 @@ MipsSETargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { } MachineBasicBlock * -MipsSETargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, +MipsSETargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *BB) const { - switch (MI->getOpcode()) { + switch (MI.getOpcode()) { default: return MipsTargetLowering::EmitInstrWithCustomInserter(MI, BB); case Mips::BPOSGE32_PSEUDO: @@ -1218,17 +1218,14 @@ SDValue MipsSETargetLowering::lowerLOAD(SDValue Op, SelectionDAG &DAG) const { EVT PtrVT = Ptr.getValueType(); // i32 load from lower address. - SDValue Lo = DAG.getLoad(MVT::i32, DL, Chain, Ptr, - MachinePointerInfo(), Nd.isVolatile(), - Nd.isNonTemporal(), Nd.isInvariant(), - Nd.getAlignment()); + SDValue Lo = DAG.getLoad(MVT::i32, DL, Chain, Ptr, MachinePointerInfo(), + Nd.getAlignment(), Nd.getMemOperand()->getFlags()); // i32 load from higher address. 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(), - std::min(Nd.getAlignment(), 4U)); + SDValue Hi = DAG.getLoad( + MVT::i32, DL, Lo.getValue(1), Ptr, MachinePointerInfo(), + std::min(Nd.getAlignment(), 4U), Nd.getMemOperand()->getFlags()); if (!Subtarget.isLittle()) std::swap(Lo, Hi); @@ -1257,15 +1254,15 @@ SDValue MipsSETargetLowering::lowerSTORE(SDValue Op, SelectionDAG &DAG) const { std::swap(Lo, Hi); // i32 store to lower address. - Chain = DAG.getStore(Chain, DL, Lo, Ptr, MachinePointerInfo(), - Nd.isVolatile(), Nd.isNonTemporal(), Nd.getAlignment(), - Nd.getAAInfo()); + Chain = + DAG.getStore(Chain, DL, Lo, Ptr, MachinePointerInfo(), Nd.getAlignment(), + Nd.getMemOperand()->getFlags(), Nd.getAAInfo()); // i32 store to higher address. 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()); + std::min(Nd.getAlignment(), 4U), + Nd.getMemOperand()->getFlags(), Nd.getAAInfo()); } SDValue MipsSETargetLowering::lowerMulDiv(SDValue Op, unsigned NewOpc, @@ -1292,8 +1289,7 @@ SDValue MipsSETargetLowering::lowerMulDiv(SDValue Op, unsigned NewOpc, return DAG.getMergeValues(Vals, DL); } - -static SDValue initAccumulator(SDValue In, SDLoc DL, SelectionDAG &DAG) { +static SDValue initAccumulator(SDValue In, const SDLoc &DL, SelectionDAG &DAG) { SDValue InLo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, In, DAG.getConstant(0, DL, MVT::i32)); SDValue InHi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, In, @@ -1301,7 +1297,7 @@ static SDValue initAccumulator(SDValue In, SDLoc DL, SelectionDAG &DAG) { return DAG.getNode(MipsISD::MTLOHI, DL, MVT::Untyped, InLo, InHi); } -static SDValue extractLOHI(SDValue Op, SDLoc DL, SelectionDAG &DAG) { +static SDValue extractLOHI(SDValue Op, const SDLoc &DL, SelectionDAG &DAG) { SDValue Lo = DAG.getNode(MipsISD::MFLO, DL, MVT::i32, Op); SDValue Hi = DAG.getNode(MipsISD::MFHI, DL, MVT::i32, Op); return DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, Lo, Hi); @@ -1401,8 +1397,8 @@ static SDValue lowerMSASplatZExt(SDValue Op, unsigned OpNr, SelectionDAG &DAG) { SDValue Ops[16] = { LaneA, LaneB, LaneA, LaneB, LaneA, LaneB, LaneA, LaneB, LaneA, LaneB, LaneA, LaneB, LaneA, LaneB, LaneA, LaneB }; - SDValue Result = DAG.getNode(ISD::BUILD_VECTOR, DL, ViaVecTy, - makeArrayRef(Ops, ViaVecTy.getVectorNumElements())); + SDValue Result = DAG.getBuildVector( + ViaVecTy, DL, makeArrayRef(Ops, ViaVecTy.getVectorNumElements())); if (ViaVecTy != ResVecTy) Result = DAG.getNode(ISD::BITCAST, DL, ResVecTy, Result); @@ -1442,8 +1438,8 @@ static SDValue getBuildVectorSplat(EVT VecTy, SDValue SplatValue, SplatValueA, SplatValueB, SplatValueA, SplatValueB, SplatValueA, SplatValueB, SplatValueA, SplatValueB }; - SDValue Result = DAG.getNode(ISD::BUILD_VECTOR, DL, ViaVecTy, - makeArrayRef(Ops, ViaVecTy.getVectorNumElements())); + SDValue Result = DAG.getBuildVector( + ViaVecTy, DL, makeArrayRef(Ops, ViaVecTy.getVectorNumElements())); if (VecTy != ViaVecTy) Result = DAG.getNode(ISD::BITCAST, DL, VecTy, Result); @@ -1471,10 +1467,10 @@ static SDValue lowerMSABinaryBitImmIntr(SDValue Op, SelectionDAG &DAG, if (BigEndian) std::swap(BitImmLoOp, BitImmHiOp); - Exp2Imm = - DAG.getNode(ISD::BITCAST, DL, MVT::v2i64, - DAG.getNode(ISD::BUILD_VECTOR, DL, MVT::v4i32, BitImmLoOp, - BitImmHiOp, BitImmLoOp, BitImmHiOp)); + Exp2Imm = DAG.getNode( + ISD::BITCAST, DL, MVT::v2i64, + DAG.getBuildVector(MVT::v4i32, DL, + {BitImmLoOp, BitImmHiOp, BitImmLoOp, BitImmHiOp})); } } @@ -1860,7 +1856,7 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op, // If ResTy is v2i64 then the type legalizer will break this node down into // an equivalent v4i32. - return DAG.getNode(ISD::BUILD_VECTOR, DL, ResTy, Ops); + return DAG.getBuildVector(ResTy, DL, Ops); } case Intrinsic::mips_fexp2_w: case Intrinsic::mips_fexp2_d: { @@ -2166,6 +2162,10 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op, case Intrinsic::mips_xori_b: return DAG.getNode(ISD::XOR, DL, Op->getValueType(0), Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG)); + case Intrinsic::thread_pointer: { + EVT PtrVT = getPointerTy(DAG.getDataLayout()); + return DAG.getNode(MipsISD::ThreadPointer, DL, PtrVT); + } } } @@ -2178,9 +2178,8 @@ static SDValue lowerMSALoadIntr(SDValue Op, SelectionDAG &DAG, unsigned Intr) { EVT PtrTy = Address->getValueType(0); Address = DAG.getNode(ISD::ADD, DL, PtrTy, Address, Offset); - - return DAG.getLoad(ResTy, DL, ChainIn, Address, MachinePointerInfo(), false, - false, false, 16); + return DAG.getLoad(ResTy, DL, ChainIn, Address, MachinePointerInfo(), + /* Alignment = */ 16); } SDValue MipsSETargetLowering::lowerINTRINSIC_W_CHAIN(SDValue Op, @@ -2247,8 +2246,8 @@ static SDValue lowerMSAStoreIntr(SDValue Op, SelectionDAG &DAG, unsigned Intr) { Address = DAG.getNode(ISD::ADD, DL, PtrTy, Address, Offset); - return DAG.getStore(ChainIn, DL, Value, Address, MachinePointerInfo(), false, - false, 16); + return DAG.getStore(ChainIn, DL, Value, Address, MachinePointerInfo(), + /* Alignment = */ 16); } SDValue MipsSETargetLowering::lowerINTRINSIC_VOID(SDValue Op, @@ -2311,7 +2310,7 @@ lowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const { } static bool isConstantOrUndef(const SDValue Op) { - if (Op->getOpcode() == ISD::UNDEF) + if (Op->isUndef()) return true; if (isa<ConstantSDNode>(Op)) return true; @@ -2841,7 +2840,7 @@ static SDValue lowerVECTOR_SHUFFLE_VSHF(SDValue Op, EVT ResTy, ++I) Ops.push_back(DAG.getTargetConstant(*I, DL, MaskEltTy)); - SDValue MaskVec = DAG.getNode(ISD::BUILD_VECTOR, DL, MaskVecTy, Ops); + SDValue MaskVec = DAG.getBuildVector(MaskVecTy, DL, Ops); if (Using1stVec && Using2ndVec) { Op0 = Op->getOperand(0); @@ -2883,32 +2882,27 @@ SDValue MipsSETargetLowering::lowerVECTOR_SHUFFLE(SDValue Op, // 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()) + SDValue Result; + if ((Result = lowerVECTOR_SHUFFLE_ILVEV(Op, ResTy, Indices, DAG))) return Result; - Result = lowerVECTOR_SHUFFLE_ILVOD(Op, ResTy, Indices, DAG); - if (Result.getNode()) + if ((Result = lowerVECTOR_SHUFFLE_ILVOD(Op, ResTy, Indices, DAG))) return Result; - Result = lowerVECTOR_SHUFFLE_ILVL(Op, ResTy, Indices, DAG); - if (Result.getNode()) + if ((Result = lowerVECTOR_SHUFFLE_ILVL(Op, ResTy, Indices, DAG))) return Result; - Result = lowerVECTOR_SHUFFLE_ILVR(Op, ResTy, Indices, DAG); - if (Result.getNode()) + if ((Result = lowerVECTOR_SHUFFLE_ILVR(Op, ResTy, Indices, DAG))) return Result; - Result = lowerVECTOR_SHUFFLE_PCKEV(Op, ResTy, Indices, DAG); - if (Result.getNode()) + if ((Result = lowerVECTOR_SHUFFLE_PCKEV(Op, ResTy, Indices, DAG))) return Result; - Result = lowerVECTOR_SHUFFLE_PCKOD(Op, ResTy, Indices, DAG); - if (Result.getNode()) + if ((Result = lowerVECTOR_SHUFFLE_PCKOD(Op, ResTy, Indices, DAG))) return Result; - Result = lowerVECTOR_SHUFFLE_SHF(Op, ResTy, Indices, DAG); - if (Result.getNode()) + if ((Result = lowerVECTOR_SHUFFLE_SHF(Op, ResTy, Indices, DAG))) return Result; return lowerVECTOR_SHUFFLE_VSHF(Op, ResTy, Indices, DAG); } -MachineBasicBlock * MipsSETargetLowering:: -emitBPOSGE32(MachineInstr *MI, MachineBasicBlock *BB) const{ +MachineBasicBlock * +MipsSETargetLowering::emitBPOSGE32(MachineInstr &MI, + MachineBasicBlock *BB) const { // $bb: // bposge32_pseudo $vr0 // => @@ -2925,7 +2919,7 @@ emitBPOSGE32(MachineInstr *MI, MachineBasicBlock *BB) const{ MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); const TargetInstrInfo *TII = Subtarget.getInstrInfo(); const TargetRegisterClass *RC = &Mips::GPR32RegClass; - DebugLoc DL = MI->getDebugLoc(); + DebugLoc DL = MI.getDebugLoc(); const BasicBlock *LLVM_BB = BB->getBasicBlock(); MachineFunction::iterator It = std::next(MachineFunction::iterator(BB)); MachineFunction *F = BB->getParent(); @@ -2949,6 +2943,8 @@ emitBPOSGE32(MachineInstr *MI, MachineBasicBlock *BB) const{ // Insert the real bposge32 instruction to $BB. BuildMI(BB, DL, TII->get(Mips::BPOSGE32)).addMBB(TBB); + // Insert the real bposge32c instruction to $BB. + BuildMI(BB, DL, TII->get(Mips::BPOSGE32C_MMR3)).addMBB(TBB); // Fill $FBB. unsigned VR2 = RegInfo.createVirtualRegister(RC); @@ -2963,16 +2959,18 @@ emitBPOSGE32(MachineInstr *MI, MachineBasicBlock *BB) const{ // Insert phi function to $Sink. BuildMI(*Sink, Sink->begin(), DL, TII->get(Mips::PHI), - MI->getOperand(0).getReg()) - .addReg(VR2).addMBB(FBB).addReg(VR1).addMBB(TBB); + MI.getOperand(0).getReg()) + .addReg(VR2) + .addMBB(FBB) + .addReg(VR1) + .addMBB(TBB); - MI->eraseFromParent(); // The pseudo instruction is gone now. + MI.eraseFromParent(); // The pseudo instruction is gone now. return Sink; } -MachineBasicBlock * MipsSETargetLowering:: -emitMSACBranchPseudo(MachineInstr *MI, MachineBasicBlock *BB, - unsigned BranchOp) const{ +MachineBasicBlock *MipsSETargetLowering::emitMSACBranchPseudo( + MachineInstr &MI, MachineBasicBlock *BB, unsigned BranchOp) const { // $bb: // vany_nonzero $rd, $ws // => @@ -2990,7 +2988,7 @@ emitMSACBranchPseudo(MachineInstr *MI, MachineBasicBlock *BB, MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); const TargetInstrInfo *TII = Subtarget.getInstrInfo(); const TargetRegisterClass *RC = &Mips::GPR32RegClass; - DebugLoc DL = MI->getDebugLoc(); + DebugLoc DL = MI.getDebugLoc(); const BasicBlock *LLVM_BB = BB->getBasicBlock(); MachineFunction::iterator It = std::next(MachineFunction::iterator(BB)); MachineFunction *F = BB->getParent(); @@ -3014,8 +3012,8 @@ emitMSACBranchPseudo(MachineInstr *MI, MachineBasicBlock *BB, // Insert the real bnz.b instruction to $BB. BuildMI(BB, DL, TII->get(BranchOp)) - .addReg(MI->getOperand(1).getReg()) - .addMBB(TBB); + .addReg(MI.getOperand(1).getReg()) + .addMBB(TBB); // Fill $FBB. unsigned RD1 = RegInfo.createVirtualRegister(RC); @@ -3030,10 +3028,13 @@ emitMSACBranchPseudo(MachineInstr *MI, MachineBasicBlock *BB, // Insert phi function to $Sink. BuildMI(*Sink, Sink->begin(), DL, TII->get(Mips::PHI), - MI->getOperand(0).getReg()) - .addReg(RD1).addMBB(FBB).addReg(RD2).addMBB(TBB); + MI.getOperand(0).getReg()) + .addReg(RD1) + .addMBB(FBB) + .addReg(RD2) + .addMBB(TBB); - MI->eraseFromParent(); // The pseudo instruction is gone now. + MI.eraseFromParent(); // The pseudo instruction is gone now. return Sink; } @@ -3047,14 +3048,15 @@ emitMSACBranchPseudo(MachineInstr *MI, MachineBasicBlock *BB, // When n is zero, the equivalent operation can be performed with (potentially) // zero instructions due to register overlaps. This optimization is never valid // 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{ +MachineBasicBlock * +MipsSETargetLowering::emitCOPY_FW(MachineInstr &MI, + MachineBasicBlock *BB) const { const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); - DebugLoc DL = MI->getDebugLoc(); - unsigned Fd = MI->getOperand(0).getReg(); - unsigned Ws = MI->getOperand(1).getReg(); - unsigned Lane = MI->getOperand(2).getImm(); + DebugLoc DL = MI.getDebugLoc(); + unsigned Fd = MI.getOperand(0).getReg(); + unsigned Ws = MI.getOperand(1).getReg(); + unsigned Lane = MI.getOperand(2).getImm(); if (Lane == 0) { unsigned Wt = Ws; @@ -3076,7 +3078,7 @@ emitCOPY_FW(MachineInstr *MI, MachineBasicBlock *BB) const{ BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Fd).addReg(Wt, 0, Mips::sub_lo); } - MI->eraseFromParent(); // The pseudo instruction is gone now. + MI.eraseFromParent(); // The pseudo instruction is gone now. return BB; } @@ -3090,16 +3092,17 @@ emitCOPY_FW(MachineInstr *MI, MachineBasicBlock *BB) const{ // When n is zero, the equivalent operation can be performed with (potentially) // zero instructions due to register overlaps. This optimization is always // valid because FR=1 mode which is the only supported mode in MSA. -MachineBasicBlock * MipsSETargetLowering:: -emitCOPY_FD(MachineInstr *MI, MachineBasicBlock *BB) const{ +MachineBasicBlock * +MipsSETargetLowering::emitCOPY_FD(MachineInstr &MI, + MachineBasicBlock *BB) const { assert(Subtarget.isFP64bit()); const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); - unsigned Fd = MI->getOperand(0).getReg(); - unsigned Ws = MI->getOperand(1).getReg(); - unsigned Lane = MI->getOperand(2).getImm() * 2; - DebugLoc DL = MI->getDebugLoc(); + unsigned Fd = MI.getOperand(0).getReg(); + unsigned Ws = MI.getOperand(1).getReg(); + unsigned Lane = MI.getOperand(2).getImm() * 2; + DebugLoc DL = MI.getDebugLoc(); if (Lane == 0) BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Fd).addReg(Ws, 0, Mips::sub_64); @@ -3110,7 +3113,7 @@ emitCOPY_FD(MachineInstr *MI, MachineBasicBlock *BB) const{ BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Fd).addReg(Wt, 0, Mips::sub_64); } - MI->eraseFromParent(); // The pseudo instruction is gone now. + MI.eraseFromParent(); // The pseudo instruction is gone now. return BB; } @@ -3121,15 +3124,15 @@ emitCOPY_FD(MachineInstr *MI, MachineBasicBlock *BB) const{ // subreg_to_reg $wt:sub_lo, $fs // insve_w $wd[$n], $wd_in, $wt[0] MachineBasicBlock * -MipsSETargetLowering::emitINSERT_FW(MachineInstr *MI, +MipsSETargetLowering::emitINSERT_FW(MachineInstr &MI, MachineBasicBlock *BB) const { const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); - DebugLoc DL = MI->getDebugLoc(); - unsigned Wd = MI->getOperand(0).getReg(); - unsigned Wd_in = MI->getOperand(1).getReg(); - unsigned Lane = MI->getOperand(2).getImm(); - unsigned Fs = MI->getOperand(3).getReg(); + DebugLoc DL = MI.getDebugLoc(); + unsigned Wd = MI.getOperand(0).getReg(); + unsigned Wd_in = MI.getOperand(1).getReg(); + unsigned Lane = MI.getOperand(2).getImm(); + unsigned Fs = MI.getOperand(3).getReg(); unsigned Wt = RegInfo.createVirtualRegister( Subtarget.useOddSPReg() ? &Mips::MSA128WRegClass : &Mips::MSA128WEvensRegClass); @@ -3144,7 +3147,7 @@ MipsSETargetLowering::emitINSERT_FW(MachineInstr *MI, .addReg(Wt) .addImm(0); - MI->eraseFromParent(); // The pseudo instruction is gone now. + MI.eraseFromParent(); // The pseudo instruction is gone now. return BB; } @@ -3155,17 +3158,17 @@ MipsSETargetLowering::emitINSERT_FW(MachineInstr *MI, // subreg_to_reg $wt:sub_64, $fs // insve_d $wd[$n], $wd_in, $wt[0] MachineBasicBlock * -MipsSETargetLowering::emitINSERT_FD(MachineInstr *MI, +MipsSETargetLowering::emitINSERT_FD(MachineInstr &MI, MachineBasicBlock *BB) const { assert(Subtarget.isFP64bit()); const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); - DebugLoc DL = MI->getDebugLoc(); - unsigned Wd = MI->getOperand(0).getReg(); - unsigned Wd_in = MI->getOperand(1).getReg(); - unsigned Lane = MI->getOperand(2).getImm(); - unsigned Fs = MI->getOperand(3).getReg(); + DebugLoc DL = MI.getDebugLoc(); + unsigned Wd = MI.getOperand(0).getReg(); + unsigned Wd_in = MI.getOperand(1).getReg(); + unsigned Lane = MI.getOperand(2).getImm(); + unsigned Fs = MI.getOperand(3).getReg(); unsigned Wt = RegInfo.createVirtualRegister(&Mips::MSA128DRegClass); BuildMI(*BB, MI, DL, TII->get(Mips::SUBREG_TO_REG), Wt) @@ -3178,7 +3181,7 @@ MipsSETargetLowering::emitINSERT_FD(MachineInstr *MI, .addReg(Wt) .addImm(0); - MI->eraseFromParent(); // The pseudo instruction is gone now. + MI.eraseFromParent(); // The pseudo instruction is gone now. return BB; } @@ -3202,22 +3205,23 @@ MipsSETargetLowering::emitINSERT_FD(MachineInstr *MI, // (INSVE_[WD], $wdtmp2, 0, $wdtmp1, 0) // (NEG $lanetmp2, $lanetmp1) // (SLD_B $wd, $wdtmp2, $wdtmp2, $lanetmp2) -MachineBasicBlock * -MipsSETargetLowering::emitINSERT_DF_VIDX(MachineInstr *MI, - MachineBasicBlock *BB, - unsigned EltSizeInBytes, - bool IsFP) const { +MachineBasicBlock *MipsSETargetLowering::emitINSERT_DF_VIDX( + MachineInstr &MI, MachineBasicBlock *BB, unsigned EltSizeInBytes, + bool IsFP) const { const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); - DebugLoc DL = MI->getDebugLoc(); - unsigned Wd = MI->getOperand(0).getReg(); - unsigned SrcVecReg = MI->getOperand(1).getReg(); - unsigned LaneReg = MI->getOperand(2).getReg(); - unsigned SrcValReg = MI->getOperand(3).getReg(); + DebugLoc DL = MI.getDebugLoc(); + unsigned Wd = MI.getOperand(0).getReg(); + unsigned SrcVecReg = MI.getOperand(1).getReg(); + unsigned LaneReg = MI.getOperand(2).getReg(); + unsigned SrcValReg = MI.getOperand(3).getReg(); const TargetRegisterClass *VecRC = nullptr; + // FIXME: This should be true for N32 too. const TargetRegisterClass *GPRRC = Subtarget.isABI_N64() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass; + unsigned SubRegIdx = Subtarget.isABI_N64() ? Mips::sub_32 : 0; + unsigned ShiftOp = Subtarget.isABI_N64() ? Mips::DSLL : Mips::SLL; unsigned EltLog2Size; unsigned InsertOp = 0; unsigned InsveOp = 0; @@ -3262,7 +3266,7 @@ MipsSETargetLowering::emitINSERT_DF_VIDX(MachineInstr *MI, // Convert the lane index into a byte index if (EltSizeInBytes != 1) { unsigned LaneTmp1 = RegInfo.createVirtualRegister(GPRRC); - BuildMI(*BB, MI, DL, TII->get(Mips::SLL), LaneTmp1) + BuildMI(*BB, MI, DL, TII->get(ShiftOp), LaneTmp1) .addReg(LaneReg) .addImm(EltLog2Size); LaneReg = LaneTmp1; @@ -3273,7 +3277,7 @@ MipsSETargetLowering::emitINSERT_DF_VIDX(MachineInstr *MI, BuildMI(*BB, MI, DL, TII->get(Mips::SLD_B), WdTmp1) .addReg(SrcVecReg) .addReg(SrcVecReg) - .addReg(LaneReg); + .addReg(LaneReg, 0, SubRegIdx); unsigned WdTmp2 = RegInfo.createVirtualRegister(VecRC); if (IsFP) { @@ -3302,9 +3306,9 @@ MipsSETargetLowering::emitINSERT_DF_VIDX(MachineInstr *MI, BuildMI(*BB, MI, DL, TII->get(Mips::SLD_B), Wd) .addReg(WdTmp2) .addReg(WdTmp2) - .addReg(LaneTmp2); + .addReg(LaneTmp2, 0, SubRegIdx); - MI->eraseFromParent(); // The pseudo instruction is gone now. + MI.eraseFromParent(); // The pseudo instruction is gone now. return BB; } @@ -3316,13 +3320,13 @@ MipsSETargetLowering::emitINSERT_DF_VIDX(MachineInstr *MI, // insert_subreg $wt2:subreg_lo, $wt1, $fs // splati.w $wd, $wt2[0] MachineBasicBlock * -MipsSETargetLowering::emitFILL_FW(MachineInstr *MI, +MipsSETargetLowering::emitFILL_FW(MachineInstr &MI, MachineBasicBlock *BB) const { const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); - DebugLoc DL = MI->getDebugLoc(); - unsigned Wd = MI->getOperand(0).getReg(); - unsigned Fs = MI->getOperand(1).getReg(); + DebugLoc DL = MI.getDebugLoc(); + unsigned Wd = MI.getOperand(0).getReg(); + unsigned Fs = MI.getOperand(1).getReg(); unsigned Wt1 = RegInfo.createVirtualRegister(&Mips::MSA128WRegClass); unsigned Wt2 = RegInfo.createVirtualRegister(&Mips::MSA128WRegClass); @@ -3333,7 +3337,7 @@ MipsSETargetLowering::emitFILL_FW(MachineInstr *MI, .addImm(Mips::sub_lo); BuildMI(*BB, MI, DL, TII->get(Mips::SPLATI_W), Wd).addReg(Wt2).addImm(0); - MI->eraseFromParent(); // The pseudo instruction is gone now. + MI.eraseFromParent(); // The pseudo instruction is gone now. return BB; } @@ -3345,15 +3349,15 @@ MipsSETargetLowering::emitFILL_FW(MachineInstr *MI, // insert_subreg $wt2:subreg_64, $wt1, $fs // splati.d $wd, $wt2[0] MachineBasicBlock * -MipsSETargetLowering::emitFILL_FD(MachineInstr *MI, +MipsSETargetLowering::emitFILL_FD(MachineInstr &MI, MachineBasicBlock *BB) const { assert(Subtarget.isFP64bit()); const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); - DebugLoc DL = MI->getDebugLoc(); - unsigned Wd = MI->getOperand(0).getReg(); - unsigned Fs = MI->getOperand(1).getReg(); + DebugLoc DL = MI.getDebugLoc(); + unsigned Wd = MI.getOperand(0).getReg(); + unsigned Fs = MI.getOperand(1).getReg(); unsigned Wt1 = RegInfo.createVirtualRegister(&Mips::MSA128DRegClass); unsigned Wt2 = RegInfo.createVirtualRegister(&Mips::MSA128DRegClass); @@ -3364,7 +3368,7 @@ MipsSETargetLowering::emitFILL_FD(MachineInstr *MI, .addImm(Mips::sub_64); BuildMI(*BB, MI, DL, TII->get(Mips::SPLATI_D), Wd).addReg(Wt2).addImm(0); - MI->eraseFromParent(); // The pseudo instruction is gone now. + MI.eraseFromParent(); // The pseudo instruction is gone now. return BB; } @@ -3375,25 +3379,25 @@ MipsSETargetLowering::emitFILL_FD(MachineInstr *MI, // ldi.w $ws, 1 // fexp2.w $wd, $ws, $wt MachineBasicBlock * -MipsSETargetLowering::emitFEXP2_W_1(MachineInstr *MI, +MipsSETargetLowering::emitFEXP2_W_1(MachineInstr &MI, MachineBasicBlock *BB) const { const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); const TargetRegisterClass *RC = &Mips::MSA128WRegClass; unsigned Ws1 = RegInfo.createVirtualRegister(RC); unsigned Ws2 = RegInfo.createVirtualRegister(RC); - DebugLoc DL = MI->getDebugLoc(); + DebugLoc DL = MI.getDebugLoc(); // Splat 1.0 into a vector BuildMI(*BB, MI, DL, TII->get(Mips::LDI_W), Ws1).addImm(1); BuildMI(*BB, MI, DL, TII->get(Mips::FFINT_U_W), Ws2).addReg(Ws1); // Emit 1.0 * fexp2(Wt) - BuildMI(*BB, MI, DL, TII->get(Mips::FEXP2_W), MI->getOperand(0).getReg()) + BuildMI(*BB, MI, DL, TII->get(Mips::FEXP2_W), MI.getOperand(0).getReg()) .addReg(Ws2) - .addReg(MI->getOperand(1).getReg()); + .addReg(MI.getOperand(1).getReg()); - MI->eraseFromParent(); // The pseudo instruction is gone now. + MI.eraseFromParent(); // The pseudo instruction is gone now. return BB; } @@ -3404,24 +3408,24 @@ MipsSETargetLowering::emitFEXP2_W_1(MachineInstr *MI, // ldi.d $ws, 1 // fexp2.d $wd, $ws, $wt MachineBasicBlock * -MipsSETargetLowering::emitFEXP2_D_1(MachineInstr *MI, +MipsSETargetLowering::emitFEXP2_D_1(MachineInstr &MI, MachineBasicBlock *BB) const { const TargetInstrInfo *TII = Subtarget.getInstrInfo(); MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo(); const TargetRegisterClass *RC = &Mips::MSA128DRegClass; unsigned Ws1 = RegInfo.createVirtualRegister(RC); unsigned Ws2 = RegInfo.createVirtualRegister(RC); - DebugLoc DL = MI->getDebugLoc(); + DebugLoc DL = MI.getDebugLoc(); // Splat 1.0 into a vector BuildMI(*BB, MI, DL, TII->get(Mips::LDI_D), Ws1).addImm(1); BuildMI(*BB, MI, DL, TII->get(Mips::FFINT_U_D), Ws2).addReg(Ws1); // Emit 1.0 * fexp2(Wt) - BuildMI(*BB, MI, DL, TII->get(Mips::FEXP2_D), MI->getOperand(0).getReg()) + BuildMI(*BB, MI, DL, TII->get(Mips::FEXP2_D), MI.getOperand(0).getReg()) .addReg(Ws2) - .addReg(MI->getOperand(1).getReg()); + .addReg(MI.getOperand(1).getReg()); - MI->eraseFromParent(); // The pseudo instruction is gone now. + MI.eraseFromParent(); // The pseudo instruction is gone now. return BB; } diff --git a/lib/Target/Mips/MipsSEISelLowering.h b/lib/Target/Mips/MipsSEISelLowering.h index d44f8d82ec3ea..54154662f2614 100644 --- a/lib/Target/Mips/MipsSEISelLowering.h +++ b/lib/Target/Mips/MipsSEISelLowering.h @@ -40,7 +40,7 @@ namespace llvm { SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override; MachineBasicBlock * - EmitInstrWithCustomInserter(MachineInstr *MI, + EmitInstrWithCustomInserter(MachineInstr &MI, MachineBasicBlock *MBB) const override; bool isShuffleMaskLegal(const SmallVectorImpl<int> &Mask, @@ -77,39 +77,39 @@ namespace llvm { /// depending on the indices in the shuffle. SDValue lowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const; - MachineBasicBlock *emitBPOSGE32(MachineInstr *MI, + MachineBasicBlock *emitBPOSGE32(MachineInstr &MI, MachineBasicBlock *BB) const; - MachineBasicBlock *emitMSACBranchPseudo(MachineInstr *MI, + MachineBasicBlock *emitMSACBranchPseudo(MachineInstr &MI, MachineBasicBlock *BB, unsigned BranchOp) const; /// \brief Emit the COPY_FW pseudo instruction - MachineBasicBlock *emitCOPY_FW(MachineInstr *MI, + MachineBasicBlock *emitCOPY_FW(MachineInstr &MI, MachineBasicBlock *BB) const; /// \brief Emit the COPY_FD pseudo instruction - MachineBasicBlock *emitCOPY_FD(MachineInstr *MI, + MachineBasicBlock *emitCOPY_FD(MachineInstr &MI, MachineBasicBlock *BB) const; /// \brief Emit the INSERT_FW pseudo instruction - MachineBasicBlock *emitINSERT_FW(MachineInstr *MI, + MachineBasicBlock *emitINSERT_FW(MachineInstr &MI, MachineBasicBlock *BB) const; /// \brief Emit the INSERT_FD pseudo instruction - MachineBasicBlock *emitINSERT_FD(MachineInstr *MI, + MachineBasicBlock *emitINSERT_FD(MachineInstr &MI, MachineBasicBlock *BB) const; /// \brief Emit the INSERT_([BHWD]|F[WD])_VIDX pseudo instruction - MachineBasicBlock *emitINSERT_DF_VIDX(MachineInstr *MI, + MachineBasicBlock *emitINSERT_DF_VIDX(MachineInstr &MI, MachineBasicBlock *BB, unsigned EltSizeInBytes, bool IsFP) const; /// \brief Emit the FILL_FW pseudo instruction - MachineBasicBlock *emitFILL_FW(MachineInstr *MI, + MachineBasicBlock *emitFILL_FW(MachineInstr &MI, MachineBasicBlock *BB) const; /// \brief Emit the FILL_FD pseudo instruction - MachineBasicBlock *emitFILL_FD(MachineInstr *MI, + MachineBasicBlock *emitFILL_FD(MachineInstr &MI, MachineBasicBlock *BB) const; /// \brief Emit the FEXP2_W_1 pseudo instructions. - MachineBasicBlock *emitFEXP2_W_1(MachineInstr *MI, + MachineBasicBlock *emitFEXP2_W_1(MachineInstr &MI, MachineBasicBlock *BB) const; /// \brief Emit the FEXP2_D_1 pseudo instructions. - MachineBasicBlock *emitFEXP2_D_1(MachineInstr *MI, + MachineBasicBlock *emitFEXP2_D_1(MachineInstr &MI, MachineBasicBlock *BB) const; }; } diff --git a/lib/Target/Mips/MipsSEInstrInfo.cpp b/lib/Target/Mips/MipsSEInstrInfo.cpp index d4aeaf9286552..29107b2c1aa5e 100644 --- a/lib/Target/Mips/MipsSEInstrInfo.cpp +++ b/lib/Target/Mips/MipsSEInstrInfo.cpp @@ -13,20 +13,20 @@ #include "MipsSEInstrInfo.h" #include "InstPrinter/MipsInstPrinter.h" +#include "MipsAnalyzeImmediate.h" #include "MipsMachineFunction.h" #include "MipsTargetMachine.h" #include "llvm/ADT/STLExtras.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MathExtras.h" #include "llvm/Support/TargetRegistry.h" using namespace llvm; MipsSEInstrInfo::MipsSEInstrInfo(const MipsSubtarget &STI) - : MipsInstrInfo(STI, STI.getRelocationModel() == Reloc::PIC_ ? Mips::B - : Mips::J), + : MipsInstrInfo(STI, STI.isPositionIndependent() ? Mips::B : Mips::J), RI() {} const MipsRegisterInfo &MipsSEInstrInfo::getRegisterInfo() const { @@ -38,17 +38,17 @@ const MipsRegisterInfo &MipsSEInstrInfo::getRegisterInfo() const { /// the destination along with the FrameIndex of the loaded stack slot. If /// not, return 0. This predicate must return 0 if the instruction has /// any side effects other than loading from the stack slot. -unsigned MipsSEInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, +unsigned MipsSEInstrInfo::isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const { - unsigned Opc = MI->getOpcode(); + unsigned Opc = MI.getOpcode(); if ((Opc == Mips::LW) || (Opc == Mips::LD) || (Opc == Mips::LWC1) || (Opc == Mips::LDC1) || (Opc == Mips::LDC164)) { - if ((MI->getOperand(1).isFI()) && // is a stack slot - (MI->getOperand(2).isImm()) && // the imm is zero - (isZeroImm(MI->getOperand(2)))) { - FrameIndex = MI->getOperand(1).getIndex(); - return MI->getOperand(0).getReg(); + if ((MI.getOperand(1).isFI()) && // is a stack slot + (MI.getOperand(2).isImm()) && // the imm is zero + (isZeroImm(MI.getOperand(2)))) { + FrameIndex = MI.getOperand(1).getIndex(); + return MI.getOperand(0).getReg(); } } @@ -60,26 +60,26 @@ unsigned MipsSEInstrInfo::isLoadFromStackSlot(const MachineInstr *MI, /// the source reg along with the FrameIndex of the loaded stack slot. If /// not, return 0. This predicate must return 0 if the instruction has /// any side effects other than storing to the stack slot. -unsigned MipsSEInstrInfo::isStoreToStackSlot(const MachineInstr *MI, +unsigned MipsSEInstrInfo::isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const { - unsigned Opc = MI->getOpcode(); + unsigned Opc = MI.getOpcode(); if ((Opc == Mips::SW) || (Opc == Mips::SD) || (Opc == Mips::SWC1) || (Opc == Mips::SDC1) || (Opc == Mips::SDC164)) { - if ((MI->getOperand(1).isFI()) && // is a stack slot - (MI->getOperand(2).isImm()) && // the imm is zero - (isZeroImm(MI->getOperand(2)))) { - FrameIndex = MI->getOperand(1).getIndex(); - return MI->getOperand(0).getReg(); + if ((MI.getOperand(1).isFI()) && // is a stack slot + (MI.getOperand(2).isImm()) && // the imm is zero + (isZeroImm(MI.getOperand(2)))) { + FrameIndex = MI.getOperand(1).getIndex(); + return MI.getOperand(0).getReg(); } } return 0; } void MipsSEInstrInfo::copyPhysReg(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, DebugLoc DL, - unsigned DestReg, unsigned SrcReg, - bool KillSrc) const { + MachineBasicBlock::iterator I, + const DebugLoc &DL, unsigned DestReg, + unsigned SrcReg, bool KillSrc) const { unsigned Opc = 0, ZeroReg = 0; bool isMicroMips = Subtarget.inMicroMipsMode(); @@ -129,9 +129,12 @@ void MipsSEInstrInfo::copyPhysReg(MachineBasicBlock &MBB, .addReg(SrcReg, getKillRegState(KillSrc)).addImm(1 << 4) .addReg(DestReg, RegState::ImplicitDefine); return; + } else if (Mips::MSACtrlRegClass.contains(DestReg)) { + BuildMI(MBB, I, DL, get(Mips::CTCMSA)) + .addReg(DestReg) + .addReg(SrcReg, getKillRegState(KillSrc)); + return; } - else if (Mips::MSACtrlRegClass.contains(DestReg)) - Opc = Mips::CTCMSA; } else if (Mips::FGR32RegClass.contains(DestReg, SrcReg)) Opc = Mips::FMOV_S; @@ -325,12 +328,12 @@ loadRegFromStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, } } -bool MipsSEInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const { - MachineBasicBlock &MBB = *MI->getParent(); +bool MipsSEInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { + MachineBasicBlock &MBB = *MI.getParent(); bool isMicroMips = Subtarget.inMicroMipsMode(); unsigned Opc; - switch(MI->getDesc().getOpcode()) { + switch (MI.getDesc().getOpcode()) { default: return false; case Mips::RetRA: @@ -420,6 +423,14 @@ unsigned MipsSEInstrInfo::getOppositeBranchOpc(unsigned Opc) const { case Mips::BC1F: return Mips::BC1T; case Mips::BEQZC_MM: return Mips::BNEZC_MM; case Mips::BNEZC_MM: return Mips::BEQZC_MM; + case Mips::BEQZC: return Mips::BNEZC; + case Mips::BNEZC: return Mips::BEQZC; + case Mips::BEQC: return Mips::BNEC; + case Mips::BNEC: return Mips::BEQC; + case Mips::BGTZC: return Mips::BLEZC; + case Mips::BGEZC: return Mips::BLTZC; + case Mips::BLTZC: return Mips::BGEZC; + case Mips::BLEZC: return Mips::BGTZC; } } @@ -429,26 +440,33 @@ void MipsSEInstrInfo::adjustStackPtr(unsigned SP, int64_t Amount, MachineBasicBlock::iterator I) const { MipsABIInfo ABI = Subtarget.getABI(); DebugLoc DL; - unsigned ADDu = ABI.GetPtrAdduOp(); unsigned ADDiu = ABI.GetPtrAddiuOp(); if (Amount == 0) return; - if (isInt<16>(Amount))// addi sp, sp, amount + if (isInt<16>(Amount)) { + // addi sp, sp, amount BuildMI(MBB, I, DL, get(ADDiu), SP).addReg(SP).addImm(Amount); - else { // Expand immediate that doesn't fit in 16-bit. + } else { + // For numbers which are not 16bit integers we synthesize Amount inline + // then add or subtract it from sp. + unsigned Opc = ABI.GetPtrAdduOp(); + if (Amount < 0) { + Opc = ABI.GetPtrSubuOp(); + Amount = -Amount; + } unsigned Reg = loadImmediate(Amount, MBB, I, DL, nullptr); - BuildMI(MBB, I, DL, get(ADDu), SP).addReg(SP).addReg(Reg, RegState::Kill); + BuildMI(MBB, I, DL, get(Opc), SP).addReg(SP).addReg(Reg, RegState::Kill); } } /// This function generates the sequence of instructions needed to get the /// result of adding register REG and immediate IMM. -unsigned -MipsSEInstrInfo::loadImmediate(int64_t Imm, MachineBasicBlock &MBB, - MachineBasicBlock::iterator II, DebugLoc DL, - unsigned *NewImm) const { +unsigned MipsSEInstrInfo::loadImmediate(int64_t Imm, MachineBasicBlock &MBB, + MachineBasicBlock::iterator II, + const DebugLoc &DL, + unsigned *NewImm) const { MipsAnalyzeImmediate AnalyzeImm; const MipsSubtarget &STI = Subtarget; MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo(); @@ -493,8 +511,12 @@ unsigned MipsSEInstrInfo::getAnalyzableBrOpc(unsigned Opc) const { Opc == Mips::BEQ64 || Opc == Mips::BNE64 || Opc == Mips::BGTZ64 || Opc == Mips::BGEZ64 || Opc == Mips::BLTZ64 || Opc == Mips::BLEZ64 || Opc == Mips::BC1T || Opc == Mips::BC1F || Opc == Mips::B || - Opc == Mips::J || Opc == Mips::BEQZC_MM || Opc == Mips::BNEZC_MM) ? - Opc : 0; + Opc == Mips::J || Opc == Mips::BEQZC_MM || Opc == Mips::BNEZC_MM || + Opc == Mips::BEQC || Opc == Mips::BNEC || Opc == Mips::BLTC || + Opc == Mips::BGEC || Opc == Mips::BLTUC || Opc == Mips::BGEUC || + Opc == Mips::BGTZC || Opc == Mips::BLEZC || Opc == Mips::BGEZC || + Opc == Mips::BLTZC || Opc == Mips::BEQZC || Opc == Mips::BNEZC || + Opc == Mips::BC) ? Opc : 0; } void MipsSEInstrInfo::expandRetRA(MachineBasicBlock &MBB, @@ -697,7 +719,7 @@ void MipsSEInstrInfo::expandEhReturn(MachineBasicBlock &MBB, // addu $sp, $sp, $v1 // jr $ra (via RetRA) const TargetMachine &TM = MBB.getParent()->getTarget(); - if (TM.getRelocationModel() == Reloc::PIC_) + if (TM.isPositionIndependent()) BuildMI(MBB, I, I->getDebugLoc(), get(ADDU), T9) .addReg(TargetReg) .addReg(ZERO); diff --git a/lib/Target/Mips/MipsSEInstrInfo.h b/lib/Target/Mips/MipsSEInstrInfo.h index 5d73545ef6b9b..b356909bf1cf9 100644 --- a/lib/Target/Mips/MipsSEInstrInfo.h +++ b/lib/Target/Mips/MipsSEInstrInfo.h @@ -32,7 +32,7 @@ public: /// the destination along with the FrameIndex of the loaded stack slot. If /// not, return 0. This predicate must return 0 if the instruction has /// any side effects other than loading from the stack slot. - unsigned isLoadFromStackSlot(const MachineInstr *MI, + unsigned isLoadFromStackSlot(const MachineInstr &MI, int &FrameIndex) const override; /// isStoreToStackSlot - If the specified machine instruction is a direct @@ -40,12 +40,11 @@ public: /// the source reg along with the FrameIndex of the loaded stack slot. If /// not, return 0. This predicate must return 0 if the instruction has /// any side effects other than storing to the stack slot. - unsigned isStoreToStackSlot(const MachineInstr *MI, + unsigned isStoreToStackSlot(const MachineInstr &MI, int &FrameIndex) const override; - void copyPhysReg(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI, DebugLoc DL, - unsigned DestReg, unsigned SrcReg, + void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, + const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, bool KillSrc) const override; void storeRegToStack(MachineBasicBlock &MBB, @@ -62,7 +61,7 @@ public: const TargetRegisterInfo *TRI, int64_t Offset) const override; - bool expandPostRAPseudo(MachineBasicBlock::iterator MI) const override; + bool expandPostRAPseudo(MachineInstr &MI) const override; unsigned getOppositeBranchOpc(unsigned Opc) const override; @@ -74,7 +73,7 @@ public: /// non-NULL parameter, the last instruction is not emitted, but instead /// its immediate operand is returned in NewImm. unsigned loadImmediate(int64_t Imm, MachineBasicBlock &MBB, - MachineBasicBlock::iterator II, DebugLoc DL, + MachineBasicBlock::iterator II, const DebugLoc &DL, unsigned *NewImm) const; private: diff --git a/lib/Target/Mips/MipsSERegisterInfo.cpp b/lib/Target/Mips/MipsSERegisterInfo.cpp index b1e2885f5ba31..e3431cd118ab1 100644 --- a/lib/Target/Mips/MipsSERegisterInfo.cpp +++ b/lib/Target/Mips/MipsSERegisterInfo.cpp @@ -14,12 +14,10 @@ #include "MipsSERegisterInfo.h" #include "Mips.h" -#include "MipsAnalyzeImmediate.h" #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" #include "llvm/CodeGen/MachineFunction.h" @@ -29,7 +27,6 @@ #include "llvm/IR/DebugInfo.h" #include "llvm/IR/Function.h" #include "llvm/IR/Type.h" -#include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" @@ -63,10 +60,11 @@ MipsSERegisterInfo::intRegClass(unsigned Size) const { return &Mips::GPR64RegClass; } -/// Get the size of the offset supported by the given load/store. +/// Get the size of the offset supported by the given load/store/inline asm. /// The result includes the effects of any scale factors applied to the /// instruction immediate. -static inline unsigned getLoadStoreOffsetSizeInBits(const unsigned Opcode) { +static inline unsigned getLoadStoreOffsetSizeInBits(const unsigned Opcode, + MachineOperand MO) { switch (Opcode) { case Mips::LD_B: case Mips::ST_B: @@ -80,6 +78,49 @@ static inline unsigned getLoadStoreOffsetSizeInBits(const unsigned Opcode) { case Mips::LD_D: case Mips::ST_D: return 10 + 3 /* scale factor */; + case Mips::LL: + case Mips::LL64: + case Mips::LLD: + case Mips::LLE: + case Mips::SC: + case Mips::SC64: + case Mips::SCD: + case Mips::SCE: + return 16; + case Mips::LLE_MM: + case Mips::LLE_MMR6: + case Mips::LL_MM: + case Mips::SCE_MM: + case Mips::SCE_MMR6: + case Mips::SC_MM: + return 12; + case Mips::LL64_R6: + case Mips::LL_R6: + case Mips::LLD_R6: + case Mips::SC64_R6: + case Mips::SCD_R6: + case Mips::SC_R6: + return 9; + case Mips::INLINEASM: { + unsigned ConstraintID = InlineAsm::getMemoryConstraintID(MO.getImm()); + switch (ConstraintID) { + case InlineAsm::Constraint_ZC: { + const MipsSubtarget &Subtarget = MO.getParent() + ->getParent() + ->getParent() + ->getSubtarget<MipsSubtarget>(); + if (Subtarget.inMicroMipsMode()) + return 12; + + if (Subtarget.hasMips32r6()) + return 9; + + return 16; + } + default: + return 16; + } + } default: return 16; } @@ -169,7 +210,8 @@ void MipsSERegisterInfo::eliminateFI(MachineBasicBlock::iterator II, // Make sure Offset fits within the field available. // For MSA instructions, this is a 10-bit signed immediate (scaled by // element size), otherwise it is a 16-bit signed immediate. - unsigned OffsetBitSize = getLoadStoreOffsetSizeInBits(MI.getOpcode()); + unsigned OffsetBitSize = + getLoadStoreOffsetSizeInBits(MI.getOpcode(), MI.getOperand(OpNo - 1)); unsigned OffsetAlign = getLoadStoreOffsetAlign(MI.getOpcode()); if (OffsetBitSize < 16 && isInt<16>(Offset) && diff --git a/lib/Target/Mips/MipsSchedule.td b/lib/Target/Mips/MipsSchedule.td index 37f9e491d546e..738b6c46407a7 100644 --- a/lib/Target/Mips/MipsSchedule.td +++ b/lib/Target/Mips/MipsSchedule.td @@ -23,24 +23,34 @@ def IIPseudo : InstrItinClass; def II_ABS : InstrItinClass; def II_ADDI : InstrItinClass; def II_ADDIU : InstrItinClass; +def II_ADDIUPC : InstrItinClass; +def II_ADD : InstrItinClass; def II_ADDU : InstrItinClass; def II_ADD_D : InstrItinClass; def II_ADD_S : InstrItinClass; +def II_ALIGN : InstrItinClass; def II_AND : InstrItinClass; def II_ANDI : InstrItinClass; +def II_ALUIPC : InstrItinClass; +def II_AUI : InstrItinClass; +def II_AUIPC : InstrItinClass; def II_B : InstrItinClass; def II_BADDU : InstrItinClass; def II_BBIT : InstrItinClass; // bbit[01], bbit[01]32 +def II_BALC : InstrItinClass; def II_BC : InstrItinClass; def II_BC1F : InstrItinClass; def II_BC1FL : InstrItinClass; def II_BC1T : InstrItinClass; def II_BC1TL : InstrItinClass; +def II_BC1CCZ : InstrItinClass; def II_BCC : InstrItinClass; // beq and bne def II_BCCZ : InstrItinClass; // b[gl][et]z +def II_BCCC : InstrItinClass; // b<cc>c def II_BCCZAL : InstrItinClass; // bgezal and bltzal def II_BCCZALS : InstrItinClass; // bgezals and bltzals def II_BCCZC : InstrItinClass; // beqzc, bnezc +def II_BITSWAP : InstrItinClass; def II_CEIL : InstrItinClass; def II_CFC1 : InstrItinClass; def II_CLO : InstrItinClass; @@ -51,16 +61,33 @@ def II_C_CC_D : InstrItinClass; // Any c.<cc>.d instruction def II_C_CC_S : InstrItinClass; // Any c.<cc>.s instruction def II_DADDIU : InstrItinClass; def II_DADDU : InstrItinClass; +def II_DADDI : InstrItinClass; def II_DADD : InstrItinClass; +def II_DAHI : InstrItinClass; +def II_DATI : InstrItinClass; +def II_DAUI : InstrItinClass; +def II_DALIGN : InstrItinClass; +def II_DBITSWAP : InstrItinClass; +def II_DCLO : InstrItinClass; +def II_DCLZ : InstrItinClass; def II_DDIV : InstrItinClass; def II_DDIVU : InstrItinClass; def II_DIV : InstrItinClass; def II_DIVU : InstrItinClass; def II_DIV_D : InstrItinClass; def II_DIV_S : InstrItinClass; +def II_DMFC0 : InstrItinClass; +def II_DMTC0 : InstrItinClass; def II_DMFC1 : InstrItinClass; def II_DMTC1 : InstrItinClass; +def II_DMOD : InstrItinClass; +def II_DMODU : InstrItinClass; +def II_DMUH : InstrItinClass; +def II_DMUHU : InstrItinClass; +def II_DMFC2 : InstrItinClass; +def II_DMTC2 : InstrItinClass; def II_DMUL : InstrItinClass; +def II_DMULU : InstrItinClass; def II_DMULT : InstrItinClass; def II_DMULTU : InstrItinClass; def II_DROTR : InstrItinClass; @@ -75,6 +102,8 @@ def II_DSRAV : InstrItinClass; def II_DSRL : InstrItinClass; def II_DSRL32 : InstrItinClass; def II_DSRLV : InstrItinClass; +def II_DSBH : InstrItinClass; +def II_DSHD : InstrItinClass; def II_DSUBU : InstrItinClass; def II_DSUB : InstrItinClass; def II_EXT : InstrItinClass; // Any EXT instruction @@ -84,44 +113,96 @@ def II_IndirectBranchPseudo : InstrItinClass; // Indirect branch pseudo. def II_J : InstrItinClass; def II_JAL : InstrItinClass; def II_JALR : InstrItinClass; +def II_JALR_HB : InstrItinClass; def II_JALRC : InstrItinClass; def II_JALRS : InstrItinClass; def II_JALS : InstrItinClass; +def II_JIC : InstrItinClass; +def II_JIALC : InstrItinClass; def II_JR : InstrItinClass; +def II_JR_HB : InstrItinClass; def II_JRADDIUSP : InstrItinClass; def II_JRC : InstrItinClass; def II_ReturnPseudo : InstrItinClass; // Return pseudo. +def II_ERET : InstrItinClass; +def II_DERET : InstrItinClass; +def II_ERETNC : InstrItinClass; +def II_EHB : InstrItinClass; +def II_SDBBP : InstrItinClass; +def II_SSNOP : InstrItinClass; +def II_SYSCALL : InstrItinClass; +def II_PAUSE : InstrItinClass; +def II_WAIT : InstrItinClass; +def II_EI : InstrItinClass; +def II_DI : InstrItinClass; +def II_TEQ : InstrItinClass; +def II_TEQI : InstrItinClass; +def II_TGE : InstrItinClass; +def II_TGEI : InstrItinClass; +def II_TGEIU : InstrItinClass; +def II_TGEU : InstrItinClass; +def II_TNE : InstrItinClass; +def II_TNEI : InstrItinClass; +def II_TLT : InstrItinClass; +def II_TLTI : InstrItinClass; +def II_TLTU : InstrItinClass; +def II_TTLTIU : InstrItinClass; +def II_TLBP : InstrItinClass; +def II_TLBR : InstrItinClass; +def II_TLBWI : InstrItinClass; +def II_TLBWR : InstrItinClass; +def II_TRAP : InstrItinClass; +def II_BREAK : InstrItinClass; +def II_SYNC : InstrItinClass; +def II_SYNCI : InstrItinClass; def II_LB : InstrItinClass; def II_LBE : InstrItinClass; def II_LBU : InstrItinClass; def II_LBUE : InstrItinClass; def II_LD : InstrItinClass; def II_LDC1 : InstrItinClass; +def II_LDC2 : InstrItinClass; +def II_LDC3 : InstrItinClass; def II_LDL : InstrItinClass; def II_LDR : InstrItinClass; +def II_LDPC : InstrItinClass; def II_LDXC1 : InstrItinClass; def II_LH : InstrItinClass; def II_LHE : InstrItinClass; def II_LHU : InstrItinClass; def II_LHUE : InstrItinClass; +def II_LL : InstrItinClass; +def II_LLD : InstrItinClass; def II_LUI : InstrItinClass; def II_LUXC1 : InstrItinClass; def II_LW : InstrItinClass; def II_LWE : InstrItinClass; def II_LWC1 : InstrItinClass; +def II_LWC2 : InstrItinClass; +def II_LWC3 : InstrItinClass; def II_LWL : InstrItinClass; def II_LWLE : InstrItinClass; +def II_LWPC : InstrItinClass; def II_LWR : InstrItinClass; def II_LWRE : InstrItinClass; def II_LWU : InstrItinClass; +def II_LWUPC : InstrItinClass; def II_LWXC1 : InstrItinClass; +def II_LSA : InstrItinClass; +def II_DLSA : InstrItinClass; def II_MADD : InstrItinClass; def II_MADDU : InstrItinClass; def II_MADD_D : InstrItinClass; def II_MADD_S : InstrItinClass; +def II_MADDF_D : InstrItinClass; +def II_MADDF_S : InstrItinClass; +def II_MFC0 : InstrItinClass; def II_MFC1 : InstrItinClass; def II_MFHC1 : InstrItinClass; +def II_MFC2 : InstrItinClass; def II_MFHI_MFLO : InstrItinClass; // mfhi and mflo +def II_MOD : InstrItinClass; +def II_MODU : InstrItinClass; def II_MOVF : InstrItinClass; def II_MOVF_D : InstrItinClass; def II_MOVF_S : InstrItinClass; @@ -140,10 +221,17 @@ def II_MSUB : InstrItinClass; def II_MSUBU : InstrItinClass; def II_MSUB_D : InstrItinClass; def II_MSUB_S : InstrItinClass; +def II_MSUBF_D : InstrItinClass; +def II_MSUBF_S : InstrItinClass; +def II_MTC0 : InstrItinClass; def II_MTC1 : InstrItinClass; def II_MTHC1 : InstrItinClass; +def II_MTC2 : InstrItinClass; def II_MTHI_MTLO : InstrItinClass; // mthi and mtlo def II_MUL : InstrItinClass; +def II_MUH : InstrItinClass; +def II_MUHU : InstrItinClass; +def II_MULU : InstrItinClass; def II_MULT : InstrItinClass; def II_MULTU : InstrItinClass; def II_MUL_D : InstrItinClass; @@ -163,15 +251,20 @@ def II_ROTR : InstrItinClass; def II_ROTRV : InstrItinClass; def II_ROUND : InstrItinClass; def II_SAVE : InstrItinClass; +def II_SC : InstrItinClass; +def II_SCD : InstrItinClass; def II_SB : InstrItinClass; def II_SBE : InstrItinClass; def II_SD : InstrItinClass; def II_SDC1 : InstrItinClass; +def II_SDC2 : InstrItinClass; +def II_SDC3 : InstrItinClass; def II_SDL : InstrItinClass; def II_SDR : InstrItinClass; def II_SDXC1 : InstrItinClass; def II_SEB : InstrItinClass; def II_SEH : InstrItinClass; +def II_SELCCZ : InstrItinClass; def II_SEQ_SNE : InstrItinClass; // seq and sne def II_SEQI_SNEI : InstrItinClass; // seqi and snei def II_SH : InstrItinClass; @@ -186,6 +279,7 @@ def II_SRA : InstrItinClass; def II_SRAV : InstrItinClass; def II_SRL : InstrItinClass; def II_SRLV : InstrItinClass; +def II_SUB : InstrItinClass; def II_SUBU : InstrItinClass; def II_SUB_D : InstrItinClass; def II_SUB_S : InstrItinClass; @@ -193,6 +287,8 @@ def II_SUXC1 : InstrItinClass; def II_SW : InstrItinClass; def II_SWE : InstrItinClass; def II_SWC1 : InstrItinClass; +def II_SWC2 : InstrItinClass; +def II_SWC3 : InstrItinClass; def II_SWL : InstrItinClass; def II_SWLE : InstrItinClass; def II_SWR : InstrItinClass; @@ -202,6 +298,14 @@ def II_TRUNC : InstrItinClass; def II_WSBH : InstrItinClass; def II_XOR : InstrItinClass; def II_XORI : InstrItinClass; +def II_CACHE : InstrItinClass; +def II_PREF : InstrItinClass; +def II_CACHEE : InstrItinClass; +def II_PREFE : InstrItinClass; +def II_LLE : InstrItinClass; +def II_SCE : InstrItinClass; +def II_TLBINV : InstrItinClass; +def II_TLBINVF : InstrItinClass; //===----------------------------------------------------------------------===// // Mips Generic instruction itineraries. @@ -210,9 +314,16 @@ def MipsGenericItineraries : ProcessorItineraries<[ALU, IMULDIV], [], [ InstrItinData<IIM16Alu , [InstrStage<1, [ALU]>]>, InstrItinData<II_ADDI , [InstrStage<1, [ALU]>]>, InstrItinData<II_ADDIU , [InstrStage<1, [ALU]>]>, + InstrItinData<II_ADDIUPC , [InstrStage<1, [ALU]>]>, + InstrItinData<II_ADD , [InstrStage<1, [ALU]>]>, InstrItinData<II_ADDU , [InstrStage<1, [ALU]>]>, + InstrItinData<II_AUI , [InstrStage<1, [ALU]>]>, InstrItinData<II_AND , [InstrStage<1, [ALU]>]>, + InstrItinData<II_ALUIPC , [InstrStage<1, [ALU]>]>, + InstrItinData<II_AUIPC , [InstrStage<1, [ALU]>]>, + InstrItinData<II_ALIGN , [InstrStage<1, [ALU]>]>, InstrItinData<II_BADDU , [InstrStage<1, [ALU]>]>, + InstrItinData<II_BITSWAP , [InstrStage<1, [ALU]>]>, InstrItinData<II_SLL , [InstrStage<1, [ALU]>]>, InstrItinData<II_SRA , [InstrStage<1, [ALU]>]>, InstrItinData<II_SRL , [InstrStage<1, [ALU]>]>, @@ -225,17 +336,35 @@ def MipsGenericItineraries : ProcessorItineraries<[ALU, IMULDIV], [], [ InstrItinData<II_CLZ , [InstrStage<1, [ALU]>]>, InstrItinData<II_DADDIU , [InstrStage<1, [ALU]>]>, InstrItinData<II_DADDU , [InstrStage<1, [ALU]>]>, + InstrItinData<II_DADDI , [InstrStage<1, [ALU]>]>, InstrItinData<II_DADD , [InstrStage<1, [ALU]>]>, + InstrItinData<II_DALIGN , [InstrStage<1, [ALU]>]>, + InstrItinData<II_DAHI , [InstrStage<1, [ALU]>]>, + InstrItinData<II_DATI , [InstrStage<1, [ALU]>]>, + InstrItinData<II_DAUI , [InstrStage<1, [ALU]>]>, + InstrItinData<II_DBITSWAP , [InstrStage<1, [ALU]>]>, + InstrItinData<II_DCLO , [InstrStage<1, [ALU]>]>, + InstrItinData<II_DCLZ , [InstrStage<1, [ALU]>]>, + InstrItinData<II_DMOD , [InstrStage<17, [IMULDIV]>]>, + InstrItinData<II_DMODU , [InstrStage<17, [IMULDIV]>]>, InstrItinData<II_DSLL , [InstrStage<1, [ALU]>]>, + InstrItinData<II_DSLL32 , [InstrStage<1, [ALU]>]>, InstrItinData<II_DSRL , [InstrStage<1, [ALU]>]>, + InstrItinData<II_DSRL32 , [InstrStage<1, [ALU]>]>, InstrItinData<II_DSRA , [InstrStage<1, [ALU]>]>, + InstrItinData<II_DSRA32 , [InstrStage<1, [ALU]>]>, InstrItinData<II_DSLLV , [InstrStage<1, [ALU]>]>, InstrItinData<II_DSRLV , [InstrStage<1, [ALU]>]>, InstrItinData<II_DSRAV , [InstrStage<1, [ALU]>]>, InstrItinData<II_DSUBU , [InstrStage<1, [ALU]>]>, InstrItinData<II_DSUB , [InstrStage<1, [ALU]>]>, InstrItinData<II_DROTR , [InstrStage<1, [ALU]>]>, + InstrItinData<II_DROTR32 , [InstrStage<1, [ALU]>]>, InstrItinData<II_DROTRV , [InstrStage<1, [ALU]>]>, + InstrItinData<II_DSBH , [InstrStage<1, [ALU]>]>, + InstrItinData<II_DSHD , [InstrStage<1, [ALU]>]>, + InstrItinData<II_DCLO , [InstrStage<1, [ALU]>]>, + InstrItinData<II_DCLZ , [InstrStage<1, [ALU]>]>, InstrItinData<II_EXT , [InstrStage<1, [ALU]>]>, InstrItinData<II_INS , [InstrStage<1, [ALU]>]>, InstrItinData<II_LUI , [InstrStage<1, [ALU]>]>, @@ -249,41 +378,61 @@ def MipsGenericItineraries : ProcessorItineraries<[ALU, IMULDIV], [], [ InstrItinData<II_OR , [InstrStage<1, [ALU]>]>, InstrItinData<II_POP , [InstrStage<1, [ALU]>]>, InstrItinData<II_RDHWR , [InstrStage<1, [ALU]>]>, + InstrItinData<II_SUB , [InstrStage<1, [ALU]>]>, InstrItinData<II_SUBU , [InstrStage<1, [ALU]>]>, InstrItinData<II_XOR , [InstrStage<1, [ALU]>]>, InstrItinData<II_ANDI , [InstrStage<1, [ALU]>]>, InstrItinData<II_ORI , [InstrStage<1, [ALU]>]>, InstrItinData<II_XORI , [InstrStage<1, [ALU]>]>, InstrItinData<II_LB , [InstrStage<3, [ALU]>]>, + InstrItinData<II_LBE , [InstrStage<3, [ALU]>]>, InstrItinData<II_LBU , [InstrStage<3, [ALU]>]>, + InstrItinData<II_LBUE , [InstrStage<3, [ALU]>]>, InstrItinData<II_LH , [InstrStage<3, [ALU]>]>, InstrItinData<II_LHU , [InstrStage<3, [ALU]>]>, + InstrItinData<II_LHUE , [InstrStage<3, [ALU]>]>, InstrItinData<II_LW , [InstrStage<3, [ALU]>]>, + InstrItinData<II_LWPC , [InstrStage<3, [ALU]>]>, InstrItinData<II_LWL , [InstrStage<3, [ALU]>]>, + InstrItinData<II_LWLE , [InstrStage<3, [ALU]>]>, InstrItinData<II_LWR , [InstrStage<3, [ALU]>]>, + InstrItinData<II_LWRE , [InstrStage<3, [ALU]>]>, + InstrItinData<II_LWUPC , [InstrStage<3, [ALU]>]>, InstrItinData<II_LD , [InstrStage<3, [ALU]>]>, InstrItinData<II_LDL , [InstrStage<3, [ALU]>]>, InstrItinData<II_LDR , [InstrStage<3, [ALU]>]>, + InstrItinData<II_LDPC , [InstrStage<3, [ALU]>]>, + InstrItinData<II_LL , [InstrStage<3, [ALU]>]>, + InstrItinData<II_LLD , [InstrStage<3, [ALU]>]>, InstrItinData<II_RESTORE , [InstrStage<3, [ALU]>]>, InstrItinData<II_SB , [InstrStage<1, [ALU]>]>, InstrItinData<II_SH , [InstrStage<1, [ALU]>]>, + InstrItinData<II_SHE , [InstrStage<1, [ALU]>]>, InstrItinData<II_SW , [InstrStage<1, [ALU]>]>, InstrItinData<II_SWL , [InstrStage<1, [ALU]>]>, InstrItinData<II_SWR , [InstrStage<1, [ALU]>]>, InstrItinData<II_SDL , [InstrStage<1, [ALU]>]>, InstrItinData<II_SDR , [InstrStage<1, [ALU]>]>, InstrItinData<II_SD , [InstrStage<1, [ALU]>]>, + InstrItinData<II_SC , [InstrStage<1, [ALU]>]>, + InstrItinData<II_SCD , [InstrStage<1, [ALU]>]>, InstrItinData<II_SAVE , [InstrStage<1, [ALU]>]>, + InstrItinData<II_SELCCZ , [InstrStage<1, [ALU]>]>, InstrItinData<II_SEQ_SNE , [InstrStage<1, [ALU]>]>, InstrItinData<II_SEQI_SNEI , [InstrStage<1, [ALU]>]>, + InstrItinData<II_SLTI_SLTIU , [InstrStage<1, [ALU]>]>, + InstrItinData<II_SLT_SLTU , [InstrStage<1, [ALU]>]>, InstrItinData<II_B , [InstrStage<1, [ALU]>]>, + InstrItinData<II_BALC , [InstrStage<1, [ALU]>]>, InstrItinData<II_BBIT , [InstrStage<1, [ALU]>]>, InstrItinData<II_BC , [InstrStage<1, [ALU]>]>, InstrItinData<II_BC1F , [InstrStage<1, [ALU]>]>, InstrItinData<II_BC1FL , [InstrStage<1, [ALU]>]>, InstrItinData<II_BC1T , [InstrStage<1, [ALU]>]>, InstrItinData<II_BC1TL , [InstrStage<1, [ALU]>]>, + InstrItinData<II_BC1CCZ , [InstrStage<1, [ALU]>]>, InstrItinData<II_BCC , [InstrStage<1, [ALU]>]>, + InstrItinData<II_BCCC , [InstrStage<1, [ALU]>]>, InstrItinData<II_BCCZ , [InstrStage<1, [ALU]>]>, InstrItinData<II_BCCZAL , [InstrStage<1, [ALU]>]>, InstrItinData<II_BCCZALS , [InstrStage<1, [ALU]>]>, @@ -292,25 +441,69 @@ def MipsGenericItineraries : ProcessorItineraries<[ALU, IMULDIV], [], [ InstrItinData<II_J , [InstrStage<1, [ALU]>]>, InstrItinData<II_JAL , [InstrStage<1, [ALU]>]>, InstrItinData<II_JALR , [InstrStage<1, [ALU]>]>, + InstrItinData<II_JALR_HB , [InstrStage<1, [ALU]>]>, InstrItinData<II_JALRC , [InstrStage<1, [ALU]>]>, InstrItinData<II_JALRS , [InstrStage<1, [ALU]>]>, InstrItinData<II_JALS , [InstrStage<1, [ALU]>]>, + InstrItinData<II_JIC , [InstrStage<1, [ALU]>]>, + InstrItinData<II_JIALC , [InstrStage<1, [ALU]>]>, InstrItinData<II_JR , [InstrStage<1, [ALU]>]>, + InstrItinData<II_JR_HB , [InstrStage<1, [ALU]>]>, InstrItinData<II_JRADDIUSP , [InstrStage<1, [ALU]>]>, InstrItinData<II_JRC , [InstrStage<1, [ALU]>]>, InstrItinData<II_ReturnPseudo , [InstrStage<1, [ALU]>]>, + InstrItinData<IIPseudo , [InstrStage<1, [ALU]>]>, + InstrItinData<II_DMUH , [InstrStage<17, [IMULDIV]>]>, + InstrItinData<II_DMUHU , [InstrStage<17, [IMULDIV]>]>, + InstrItinData<II_ERET , [InstrStage<1, [ALU]>]>, + InstrItinData<II_DERET , [InstrStage<1, [ALU]>]>, + InstrItinData<II_ERETNC , [InstrStage<1, [ALU]>]>, + InstrItinData<II_EHB , [InstrStage<1, [ALU]>]>, + InstrItinData<II_SDBBP , [InstrStage<1, [ALU]>]>, + InstrItinData<II_SSNOP , [InstrStage<1, [ALU]>]>, + InstrItinData<II_SYSCALL , [InstrStage<1, [ALU]>]>, + InstrItinData<II_PAUSE , [InstrStage<1, [ALU]>]>, + InstrItinData<II_WAIT , [InstrStage<1, [ALU]>]>, + InstrItinData<II_EI , [InstrStage<1, [ALU]>]>, + InstrItinData<II_DI , [InstrStage<1, [ALU]>]>, + InstrItinData<II_TEQ , [InstrStage<1, [ALU]>]>, + InstrItinData<II_TEQI , [InstrStage<1, [ALU]>]>, + InstrItinData<II_TGE , [InstrStage<1, [ALU]>]>, + InstrItinData<II_TGEI , [InstrStage<1, [ALU]>]>, + InstrItinData<II_TGEIU , [InstrStage<1, [ALU]>]>, + InstrItinData<II_TGEU , [InstrStage<1, [ALU]>]>, + InstrItinData<II_TNE , [InstrStage<1, [ALU]>]>, + InstrItinData<II_TNEI , [InstrStage<1, [ALU]>]>, + InstrItinData<II_TLT , [InstrStage<1, [ALU]>]>, + InstrItinData<II_TLTI , [InstrStage<1, [ALU]>]>, + InstrItinData<II_TLTU , [InstrStage<1, [ALU]>]>, + InstrItinData<II_TTLTIU , [InstrStage<1, [ALU]>]>, + InstrItinData<II_TLBP , [InstrStage<1, [ALU]>]>, + InstrItinData<II_TLBR , [InstrStage<1, [ALU]>]>, + InstrItinData<II_TLBWI , [InstrStage<1, [ALU]>]>, + InstrItinData<II_TLBWR , [InstrStage<1, [ALU]>]>, + InstrItinData<II_TRAP , [InstrStage<1, [ALU]>]>, + InstrItinData<II_BREAK , [InstrStage<1, [ALU]>]>, + InstrItinData<II_SYNC , [InstrStage<1, [ALU]>]>, + InstrItinData<II_SYNCI , [InstrStage<1, [ALU]>]>, InstrItinData<II_DMUL , [InstrStage<17, [IMULDIV]>]>, InstrItinData<II_DMULT , [InstrStage<17, [IMULDIV]>]>, InstrItinData<II_DMULTU , [InstrStage<17, [IMULDIV]>]>, + InstrItinData<II_DMULU , [InstrStage<17, [IMULDIV]>]>, InstrItinData<II_MADD , [InstrStage<17, [IMULDIV]>]>, InstrItinData<II_MADDU , [InstrStage<17, [IMULDIV]>]>, InstrItinData<II_MFHI_MFLO , [InstrStage<1, [IMULDIV]>]>, + InstrItinData<II_MOD , [InstrStage<38, [IMULDIV]>]>, + InstrItinData<II_MODU , [InstrStage<38, [IMULDIV]>]>, InstrItinData<II_MSUB , [InstrStage<17, [IMULDIV]>]>, InstrItinData<II_MSUBU , [InstrStage<17, [IMULDIV]>]>, InstrItinData<II_MTHI_MTLO , [InstrStage<1, [IMULDIV]>]>, + InstrItinData<II_MUH , [InstrStage<17, [IMULDIV]>]>, + InstrItinData<II_MUHU , [InstrStage<17, [IMULDIV]>]>, InstrItinData<II_MUL , [InstrStage<17, [IMULDIV]>]>, InstrItinData<II_MULT , [InstrStage<17, [IMULDIV]>]>, InstrItinData<II_MULTU , [InstrStage<17, [IMULDIV]>]>, + InstrItinData<II_MULU , [InstrStage<17, [IMULDIV]>]>, InstrItinData<II_MSUB , [InstrStage<17, [IMULDIV]>]>, InstrItinData<II_MSUBU , [InstrStage<17, [IMULDIV]>]>, InstrItinData<II_DIV , [InstrStage<38, [IMULDIV]>]>, @@ -342,34 +535,65 @@ def MipsGenericItineraries : ProcessorItineraries<[ALU, IMULDIV], [], [ InstrItinData<II_SUB_S , [InstrStage<4, [ALU]>]>, InstrItinData<II_MUL_S , [InstrStage<7, [ALU]>]>, InstrItinData<II_MADD_S , [InstrStage<7, [ALU]>]>, + InstrItinData<II_MADDF_S , [InstrStage<7, [ALU]>]>, InstrItinData<II_MSUB_S , [InstrStage<7, [ALU]>]>, + InstrItinData<II_MSUBF_S , [InstrStage<7, [ALU]>]>, InstrItinData<II_NMADD_S , [InstrStage<7, [ALU]>]>, InstrItinData<II_NMSUB_S , [InstrStage<7, [ALU]>]>, InstrItinData<II_MUL_D , [InstrStage<8, [ALU]>]>, InstrItinData<II_MADD_D , [InstrStage<8, [ALU]>]>, + InstrItinData<II_MADDF_D , [InstrStage<8, [ALU]>]>, InstrItinData<II_MSUB_D , [InstrStage<8, [ALU]>]>, + InstrItinData<II_MSUBF_D , [InstrStage<8, [ALU]>]>, InstrItinData<II_NMADD_D , [InstrStage<8, [ALU]>]>, InstrItinData<II_NMSUB_D , [InstrStage<8, [ALU]>]>, InstrItinData<II_DIV_S , [InstrStage<23, [ALU]>]>, InstrItinData<II_DIV_D , [InstrStage<36, [ALU]>]>, InstrItinData<II_SQRT_S , [InstrStage<54, [ALU]>]>, InstrItinData<II_SQRT_D , [InstrStage<12, [ALU]>]>, + InstrItinData<II_WSBH , [InstrStage<1, [ALU]>]>, + InstrItinData<II_LSA , [InstrStage<1, [ALU]>]>, + InstrItinData<II_DLSA , [InstrStage<1, [ALU]>]>, InstrItinData<II_LDC1 , [InstrStage<3, [ALU]>]>, + InstrItinData<II_LDC2 , [InstrStage<3, [ALU]>]>, + InstrItinData<II_LDC3 , [InstrStage<3, [ALU]>]>, InstrItinData<II_LWC1 , [InstrStage<3, [ALU]>]>, + InstrItinData<II_LWC2 , [InstrStage<3, [ALU]>]>, + InstrItinData<II_LWC3 , [InstrStage<3, [ALU]>]>, InstrItinData<II_LDXC1 , [InstrStage<3, [ALU]>]>, InstrItinData<II_LWXC1 , [InstrStage<3, [ALU]>]>, InstrItinData<II_LUXC1 , [InstrStage<3, [ALU]>]>, InstrItinData<II_SDC1 , [InstrStage<1, [ALU]>]>, + InstrItinData<II_SDC2 , [InstrStage<1, [ALU]>]>, + InstrItinData<II_SDC3 , [InstrStage<1, [ALU]>]>, InstrItinData<II_SWC1 , [InstrStage<1, [ALU]>]>, + InstrItinData<II_SWC2 , [InstrStage<1, [ALU]>]>, + InstrItinData<II_SWC3 , [InstrStage<1, [ALU]>]>, InstrItinData<II_SDXC1 , [InstrStage<1, [ALU]>]>, InstrItinData<II_SWXC1 , [InstrStage<1, [ALU]>]>, InstrItinData<II_SUXC1 , [InstrStage<1, [ALU]>]>, + InstrItinData<II_DMFC0 , [InstrStage<2, [ALU]>]>, InstrItinData<II_DMFC1 , [InstrStage<2, [ALU]>]>, + InstrItinData<II_DMFC2 , [InstrStage<2, [ALU]>]>, + InstrItinData<II_DMTC0 , [InstrStage<2, [ALU]>]>, InstrItinData<II_DMTC1 , [InstrStage<2, [ALU]>]>, + InstrItinData<II_DMTC2 , [InstrStage<2, [ALU]>]>, + InstrItinData<II_MFC0 , [InstrStage<2, [ALU]>]>, InstrItinData<II_MFC1 , [InstrStage<2, [ALU]>]>, + InstrItinData<II_MFC2 , [InstrStage<2, [ALU]>]>, + InstrItinData<II_MTC0 , [InstrStage<2, [ALU]>]>, InstrItinData<II_MTC1 , [InstrStage<2, [ALU]>]>, + InstrItinData<II_MTC2 , [InstrStage<2, [ALU]>]>, InstrItinData<II_MFHC1 , [InstrStage<2, [ALU]>]>, - InstrItinData<II_MTHC1 , [InstrStage<2, [ALU]>]> + InstrItinData<II_MTHC1 , [InstrStage<2, [ALU]>]>, + InstrItinData<II_CACHE , [InstrStage<1, [ALU]>]>, + InstrItinData<II_PREF , [InstrStage<1, [ALU]>]>, + InstrItinData<II_CACHEE , [InstrStage<1, [ALU]>]>, + InstrItinData<II_PREFE , [InstrStage<1, [ALU]>]>, + InstrItinData<II_TLBINV , [InstrStage<1, [ALU]>]>, + InstrItinData<II_TLBINVF , [InstrStage<1, [ALU]>]>, + InstrItinData<II_LLE , [InstrStage<3, [ALU]>]>, + InstrItinData<II_SCE , [InstrStage<1, [ALU]>]> ]>; include "MipsScheduleP5600.td" diff --git a/lib/Target/Mips/MipsScheduleP5600.td b/lib/Target/Mips/MipsScheduleP5600.td index d32ae4f55eaf1..cee42873c6e8c 100644 --- a/lib/Target/Mips/MipsScheduleP5600.td +++ b/lib/Target/Mips/MipsScheduleP5600.td @@ -13,7 +13,7 @@ def MipsP5600Model : SchedMachineModel { int LoadLatency = 4; int MispredictPenalty = 8; // TODO: Estimated - let CompleteModel = 1; + let CompleteModel = 0; } let SchedModel = MipsP5600Model in { diff --git a/lib/Target/Mips/MipsSubtarget.cpp b/lib/Target/Mips/MipsSubtarget.cpp index 8a18b517d16be..3e7570ff46ed3 100644 --- a/lib/Target/Mips/MipsSubtarget.cpp +++ b/lib/Target/Mips/MipsSubtarget.cpp @@ -90,7 +90,7 @@ MipsSubtarget::MipsSubtarget(const Triple &TT, const std::string &CPU, report_fatal_error("Code generation for MIPS-V is not implemented", false); // Check if Architecture and ABI are compatible. - assert(((!isGP64bit() && (isABI_O32() || isABI_EABI())) || + assert(((!isGP64bit() && isABI_O32()) || (isGP64bit() && (isABI_N32() || isABI_N64()))) && "Invalid Arch & ABI pair."); @@ -114,7 +114,7 @@ MipsSubtarget::MipsSubtarget(const Triple &TT, const std::string &CPU, report_fatal_error(ISA + " is not compatible with the DSP ASE", false); } - if (NoABICalls && TM.getRelocationModel() == Reloc::PIC_) + if (NoABICalls && TM.isPositionIndependent()) report_fatal_error("position-independent code requires '-mabicalls'"); // Set UseSmallSection. @@ -126,6 +126,10 @@ MipsSubtarget::MipsSubtarget(const Triple &TT, const std::string &CPU, } } +bool MipsSubtarget::isPositionIndependent() const { + return TM.isPositionIndependent(); +} + /// This overrides the PostRAScheduler bit in the SchedModel for any CPU. bool MipsSubtarget::enablePostRAScheduler() const { return true; } @@ -164,7 +168,6 @@ 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(); } diff --git a/lib/Target/Mips/MipsSubtarget.h b/lib/Target/Mips/MipsSubtarget.h index fbb01fe770294..38d3cee704777 100644 --- a/lib/Target/Mips/MipsSubtarget.h +++ b/lib/Target/Mips/MipsSubtarget.h @@ -18,10 +18,10 @@ #include "MipsFrameLowering.h" #include "MipsISelLowering.h" #include "MipsInstrInfo.h" +#include "llvm/CodeGen/SelectionDAGTargetInfo.h" #include "llvm/IR/DataLayout.h" #include "llvm/MC/MCInstrItineraries.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Target/TargetSelectionDAGInfo.h" #include "llvm/Target/TargetSubtargetInfo.h" #include <string> @@ -81,6 +81,9 @@ class MipsSubtarget : public MipsGenSubtargetInfo { // IsFP64bit - General-purpose registers are 64 bits wide bool IsGP64bit; + // IsPTR64bit - Pointers are 64 bit wide + bool IsPTR64bit; + // HasVFPU - Processor has a vector floating point unit. bool HasVFPU; @@ -152,19 +155,18 @@ class MipsSubtarget : public MipsGenSubtargetInfo { Triple TargetTriple; - const TargetSelectionDAGInfo TSInfo; + const SelectionDAGTargetInfo TSInfo; std::unique_ptr<const MipsInstrInfo> InstrInfo; std::unique_ptr<const MipsFrameLowering> FrameLowering; std::unique_ptr<const MipsTargetLowering> TLInfo; public: + bool isPositionIndependent() const; /// This overrides the PostRAScheduler bit in the SchedModel for each CPU. bool enablePostRAScheduler() const override; void getCriticalPathRCs(RegClassVector &CriticalPathRCs) const override; CodeGenOpt::Level getOptLevelToEnablePostRAScheduler() const override; - /// Only O32 and EABI supported right now. - bool isABI_EABI() const; bool isABI_N64() const; bool isABI_N32() const; bool isABI_O32() const; @@ -225,6 +227,8 @@ public: bool isGP64bit() const { return IsGP64bit; } bool isGP32bit() const { return !IsGP64bit; } unsigned getGPRSizeInBytes() const { return isGP64bit() ? 8 : 4; } + bool isPTR64bit() const { return IsPTR64bit; } + bool isPTR32bit() const { return !IsPTR64bit; } bool isSingleFloat() const { return IsSingleFloat; } bool hasVFPU() const { return HasVFPU; } bool inMips16Mode() const { return InMips16Mode; } @@ -290,7 +294,7 @@ public: void setHelperClassesMips16(); void setHelperClassesMipsSE(); - const TargetSelectionDAGInfo *getSelectionDAGInfo() const override { + const SelectionDAGTargetInfo *getSelectionDAGInfo() const override { return &TSInfo; } const MipsInstrInfo *getInstrInfo() const override { return InstrInfo.get(); } diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp index 3e638720e8392..c248c3a50ac8d 100644 --- a/lib/Target/Mips/MipsTargetMachine.cpp +++ b/lib/Target/Mips/MipsTargetMachine.cpp @@ -26,6 +26,7 @@ #include "MipsTargetObjectFile.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/TargetPassConfig.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/Support/Debug.h" #include "llvm/Support/TargetRegistry.h" @@ -77,6 +78,13 @@ static std::string computeDataLayout(const Triple &TT, StringRef CPU, return Ret; } +static Reloc::Model getEffectiveRelocModel(CodeModel::Model CM, + Optional<Reloc::Model> RM) { + if (!RM.hasValue() || CM == CodeModel::JITDefault) + return Reloc::Static; + return *RM; +} + // 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 @@ -85,10 +93,12 @@ static std::string computeDataLayout(const Triple &TT, StringRef CPU, MipsTargetMachine::MipsTargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, - Reloc::Model RM, CodeModel::Model CM, - CodeGenOpt::Level OL, bool isLittle) + Optional<Reloc::Model> RM, + CodeModel::Model CM, CodeGenOpt::Level OL, + bool isLittle) : LLVMTargetMachine(T, computeDataLayout(TT, CPU, Options, isLittle), TT, - CPU, FS, Options, RM, CM, OL), + CPU, FS, Options, getEffectiveRelocModel(CM, RM), CM, + OL), isLittle(isLittle), TLOF(make_unique<MipsTargetObjectFile>()), ABI(MipsABIInfo::computeTargetABI(TT, CPU, Options.MCOptions)), Subtarget(nullptr), DefaultSubtarget(TT, CPU, FS, isLittle, *this), @@ -107,7 +117,8 @@ void MipsebTargetMachine::anchor() { } MipsebTargetMachine::MipsebTargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, - Reloc::Model RM, CodeModel::Model CM, + Optional<Reloc::Model> RM, + CodeModel::Model CM, CodeGenOpt::Level OL) : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {} @@ -116,7 +127,8 @@ void MipselTargetMachine::anchor() { } MipselTargetMachine::MipselTargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, - Reloc::Model RM, CodeModel::Model CM, + Optional<Reloc::Model> RM, + CodeModel::Model CM, CodeGenOpt::Level OL) : MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {} @@ -217,8 +229,8 @@ void MipsPassConfig::addIRPasses() { // the ISelDag to gen Mips code. bool MipsPassConfig::addInstSelector() { addPass(createMipsModuleISelDagPass(getMipsTargetMachine())); - addPass(createMips16ISelDag(getMipsTargetMachine())); - addPass(createMipsSEISelDag(getMipsTargetMachine())); + addPass(createMips16ISelDag(getMipsTargetMachine(), getOptLevel())); + addPass(createMipsSEISelDag(getMipsTargetMachine(), getOptLevel())); return false; } @@ -250,7 +262,13 @@ TargetIRAnalysis MipsTargetMachine::getTargetIRAnalysis() { // print out the code after the passes. void MipsPassConfig::addPreEmitPass() { MipsTargetMachine &TM = getMipsTargetMachine(); + + // The delay slot filler pass can potientially create forbidden slot (FS) + // hazards for MIPSR6 which the hazard schedule pass (HSP) will fix. Any + // (new) pass that creates compact branches after the HSP must handle FS + // hazards itself or be pipelined before the HSP. addPass(createMipsDelaySlotFillerPass(TM)); + addPass(createMipsHazardSchedule()); addPass(createMipsLongBranchPass(TM)); - addPass(createMipsConstantIslandPass(TM)); + addPass(createMipsConstantIslandPass()); } diff --git a/lib/Target/Mips/MipsTargetMachine.h b/lib/Target/Mips/MipsTargetMachine.h index 38b2ecff7d7f1..e4cf17e2abd85 100644 --- a/lib/Target/Mips/MipsTargetMachine.h +++ b/lib/Target/Mips/MipsTargetMachine.h @@ -40,8 +40,9 @@ class MipsTargetMachine : public LLVMTargetMachine { public: MipsTargetMachine(const Target &T, const Triple &TT, StringRef CPU, - StringRef FS, const TargetOptions &Options, Reloc::Model RM, - CodeModel::Model CM, CodeGenOpt::Level OL, bool isLittle); + StringRef FS, const TargetOptions &Options, + Optional<Reloc::Model> RM, CodeModel::Model CM, + CodeGenOpt::Level OL, bool isLittle); ~MipsTargetMachine() override; TargetIRAnalysis getTargetIRAnalysis() override; @@ -68,25 +69,25 @@ public: const MipsABIInfo &getABI() const { return ABI; } }; -/// MipsebTargetMachine - Mips32/64 big endian target machine. +/// Mips32/64 big endian target machine. /// class MipsebTargetMachine : public MipsTargetMachine { virtual void anchor(); public: MipsebTargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, - Reloc::Model RM, CodeModel::Model CM, + Optional<Reloc::Model> RM, CodeModel::Model CM, CodeGenOpt::Level OL); }; -/// MipselTargetMachine - Mips32/64 little endian target machine. +/// Mips32/64 little endian target machine. /// class MipselTargetMachine : public MipsTargetMachine { virtual void anchor(); public: MipselTargetMachine(const Target &T, const Triple &TT, StringRef CPU, StringRef FS, const TargetOptions &Options, - Reloc::Model RM, CodeModel::Model CM, + Optional<Reloc::Model> RM, CodeModel::Model CM, CodeGenOpt::Level OL); }; diff --git a/lib/Target/Mips/MipsTargetObjectFile.cpp b/lib/Target/Mips/MipsTargetObjectFile.cpp index 146f33bda249f..3bd4567e37922 100644 --- a/lib/Target/Mips/MipsTargetObjectFile.cpp +++ b/lib/Target/Mips/MipsTargetObjectFile.cpp @@ -41,10 +41,12 @@ void MipsTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM){ InitializeELF(TM.Options.UseInitArray); SmallDataSection = getContext().getELFSection( - ".sdata", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC); + ".sdata", ELF::SHT_PROGBITS, + ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL); SmallBSSSection = getContext().getELFSection(".sbss", ELF::SHT_NOBITS, - ELF::SHF_WRITE | ELF::SHF_ALLOC); + ELF::SHF_WRITE | ELF::SHF_ALLOC | + ELF::SHF_MIPS_GPREL); this->TM = &static_cast<const MipsTargetMachine &>(TM); } @@ -106,7 +108,7 @@ IsGlobalInSmallSectionImpl(const GlobalValue *GV, GV->hasCommonLinkage())) return false; - Type *Ty = GV->getType()->getElementType(); + Type *Ty = GV->getValueType(); return IsInSmallSection( GV->getParent()->getDataLayout().getTypeAllocSize(Ty)); } @@ -138,11 +140,13 @@ bool MipsTargetObjectFile::IsConstantInSmallSection( } /// Return true if this constant should be placed into small data section. -MCSection *MipsTargetObjectFile::getSectionForConstant( - const DataLayout &DL, SectionKind Kind, const Constant *C) const { +MCSection *MipsTargetObjectFile::getSectionForConstant(const DataLayout &DL, + SectionKind Kind, + const Constant *C, + unsigned &Align) const { if (IsConstantInSmallSection(DL, C, *TM)) return SmallDataSection; // Otherwise, we work the same as ELF. - return TargetLoweringObjectFileELF::getSectionForConstant(DL, Kind, C); + return TargetLoweringObjectFileELF::getSectionForConstant(DL, Kind, C, Align); } diff --git a/lib/Target/Mips/MipsTargetObjectFile.h b/lib/Target/Mips/MipsTargetObjectFile.h index ba04343bad87a..9840769aff695 100644 --- a/lib/Target/Mips/MipsTargetObjectFile.h +++ b/lib/Target/Mips/MipsTargetObjectFile.h @@ -40,7 +40,8 @@ class MipsTargetMachine; const TargetMachine &TM) const; MCSection *getSectionForConstant(const DataLayout &DL, SectionKind Kind, - const Constant *C) const override; + const Constant *C, + unsigned &Align) const override; }; } // end namespace llvm diff --git a/lib/Target/Mips/MipsTargetStreamer.h b/lib/Target/Mips/MipsTargetStreamer.h index b3222f5d89ef0..41ebe411b98d9 100644 --- a/lib/Target/Mips/MipsTargetStreamer.h +++ b/lib/Target/Mips/MipsTargetStreamer.h @@ -13,6 +13,7 @@ #include "MCTargetDesc/MipsABIFlagsSection.h" #include "MCTargetDesc/MipsABIInfo.h" #include "llvm/ADT/Optional.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/MC/MCELFStreamer.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCStreamer.h" @@ -24,8 +25,12 @@ struct MipsABIFlagsSection; class MipsTargetStreamer : public MCTargetStreamer { public: MipsTargetStreamer(MCStreamer &S); + + virtual void setPic(bool Value) {} + virtual void emitDirectiveSetMicroMips(); virtual void emitDirectiveSetNoMicroMips(); + virtual void setUsesMicroMips(); virtual void emitDirectiveSetMips16(); virtual void emitDirectiveSetNoMips16(); @@ -78,8 +83,9 @@ public: // PIC support virtual void emitDirectiveCpLoad(unsigned RegNo); - virtual void emitDirectiveCpRestore(SmallVector<MCInst, 3> &StoreInsts, - int Offset); + virtual bool emitDirectiveCpRestore(int Offset, + function_ref<unsigned()> GetATReg, + SMLoc IDLoc, const MCSubtargetInfo *STI); virtual void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, const MCSymbol &Sym, bool IsReg); virtual void emitDirectiveCpreturn(unsigned SaveLocation, @@ -94,6 +100,54 @@ public: virtual void emitDirectiveSetOddSPReg(); virtual void emitDirectiveSetNoOddSPReg(); + void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc, + const MCSubtargetInfo *STI); + void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc, + const MCSubtargetInfo *STI); + void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc, + const MCSubtargetInfo *STI); + void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc, + const MCSubtargetInfo *STI); + void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc, + const MCSubtargetInfo *STI); + void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2, + SMLoc IDLoc, const MCSubtargetInfo *STI); + void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2, + SMLoc IDLoc, const MCSubtargetInfo *STI); + void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm, + SMLoc IDLoc, const MCSubtargetInfo *STI); + void emitAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg, bool Is64Bit, + const MCSubtargetInfo *STI); + void emitDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount, + SMLoc IDLoc, const MCSubtargetInfo *STI); + void emitEmptyDelaySlot(bool hasShortDelaySlot, SMLoc IDLoc, + const MCSubtargetInfo *STI); + void emitNop(SMLoc IDLoc, const MCSubtargetInfo *STI); + + /// Emit a store instruction with an offset. If the offset is out of range + /// then it will be synthesized using the assembler temporary. + /// + /// GetATReg() is a callback that can be used to obtain the current assembler + /// temporary and is only called when the assembler temporary is required. It + /// must handle the case where no assembler temporary is available (typically + /// by reporting an error). + void emitStoreWithImmOffset(unsigned Opcode, unsigned SrcReg, + unsigned BaseReg, int64_t Offset, + function_ref<unsigned()> GetATReg, SMLoc IDLoc, + const MCSubtargetInfo *STI); + void emitStoreWithSymOffset(unsigned Opcode, unsigned SrcReg, + unsigned BaseReg, MCOperand &HiOperand, + MCOperand &LoOperand, unsigned ATReg, SMLoc IDLoc, + const MCSubtargetInfo *STI); + void emitLoadWithImmOffset(unsigned Opcode, unsigned DstReg, unsigned BaseReg, + int64_t Offset, unsigned TmpReg, SMLoc IDLoc, + const MCSubtargetInfo *STI); + void emitLoadWithSymOffset(unsigned Opcode, unsigned DstReg, unsigned BaseReg, + MCOperand &HiOperand, MCOperand &LoOperand, + unsigned ATReg, SMLoc IDLoc, + const MCSubtargetInfo *STI); + void emitGPRestore(int Offset, SMLoc IDLoc, const MCSubtargetInfo *STI); + void forbidModuleDirective() { ModuleDirectiveAllowed = false; } void reallowModuleDirective() { ModuleDirectiveAllowed = true; } bool isModuleDirectiveAllowed() { return ModuleDirectiveAllowed; } @@ -193,8 +247,16 @@ public: // PIC support void emitDirectiveCpLoad(unsigned RegNo) override; - void emitDirectiveCpRestore(SmallVector<MCInst, 3> &StoreInsts, - int Offset) override; + + /// Emit a .cprestore directive. If the offset is out of range then it will + /// be synthesized using the assembler temporary. + /// + /// GetATReg() is a callback that can be used to obtain the current assembler + /// temporary and is only called when the assembler temporary is required. It + /// must handle the case where no assembler temporary is available (typically + /// by reporting an error). + bool emitDirectiveCpRestore(int Offset, function_ref<unsigned()> GetATReg, + SMLoc IDLoc, const MCSubtargetInfo *STI) override; void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, const MCSymbol &Sym, bool IsReg) override; void emitDirectiveCpreturn(unsigned SaveLocation, @@ -221,12 +283,15 @@ public: MCELFStreamer &getStreamer(); MipsTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI); + void setPic(bool Value) override { Pic = Value; } + void emitLabel(MCSymbol *Symbol) override; void emitAssignment(MCSymbol *Symbol, const MCExpr *Value) override; void finish() override; void emitDirectiveSetMicroMips() override; void emitDirectiveSetNoMicroMips() override; + void setUsesMicroMips() override; void emitDirectiveSetMips16() override; void emitDirectiveSetNoReorder() override; @@ -246,8 +311,8 @@ public: // PIC support void emitDirectiveCpLoad(unsigned RegNo) override; - void emitDirectiveCpRestore(SmallVector<MCInst, 3> &StoreInsts, - int Offset) override; + bool emitDirectiveCpRestore(int Offset, function_ref<unsigned()> GetATReg, + SMLoc IDLoc, const MCSubtargetInfo *STI) override; void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset, const MCSymbol &Sym, bool IsReg) override; void emitDirectiveCpreturn(unsigned SaveLocation, diff --git a/lib/Target/Mips/TargetInfo/Makefile b/lib/Target/Mips/TargetInfo/Makefile deleted file mode 100644 index 32f4e1695b1d7..0000000000000 --- a/lib/Target/Mips/TargetInfo/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -##===- lib/Target/Mips/TargetInfo/Makefile -----------------*- Makefile -*-===## -# -# The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -# -##===----------------------------------------------------------------------===## -LEVEL = ../../../.. -LIBRARYNAME = LLVMMipsInfo - -# Hack: we need to include 'main' target directory to grab private headers -CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/.. - -include $(LEVEL)/Makefile.common |