diff options
Diffstat (limited to 'lib/Target/Mips')
102 files changed, 7492 insertions, 3567 deletions
diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index 345b081500a4..2acf701b43cb 100644 --- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -146,10 +146,15 @@ class MipsAsmParser : public MCTargetAsmParser { /// If true, then CpSaveLocation is a register, otherwise it's an offset. bool CpSaveLocationIsRegister; + // Map of register aliases created via the .set directive. + StringMap<AsmToken> RegisterSets; + // Print a warning along with its fix-it message at the given range. void printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg, SMRange Range, bool ShowColors = true); + void ConvertXWPOperands(MCInst &Inst, const OperandVector &Operands); + #define GET_ASSEMBLER_HEADER #include "MipsGenAsmMatcher.inc" @@ -182,12 +187,14 @@ class MipsAsmParser : public MCTargetAsmParser { matchAnyRegisterNameWithoutDollar(OperandVector &Operands, StringRef Identifier, SMLoc S); OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands, + const AsmToken &Token, + SMLoc S); + OperandMatchResultTy matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S); OperandMatchResultTy parseAnyRegister(OperandVector &Operands); OperandMatchResultTy parseImm(OperandVector &Operands); OperandMatchResultTy parseJumpTarget(OperandVector &Operands); OperandMatchResultTy parseInvNum(OperandVector &Operands); - OperandMatchResultTy parseRegisterPair(OperandVector &Operands); OperandMatchResultTy parseMovePRegPair(OperandVector &Operands); OperandMatchResultTy parseRegisterList(OperandVector &Operands); @@ -235,13 +242,7 @@ class MipsAsmParser : public MCTargetAsmParser { const MCSubtargetInfo *STI); void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI, bool IsLoad, bool IsImmOpnd); - - void expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI, bool IsImmOpnd); - - void expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI, bool IsImmOpnd); + const MCSubtargetInfo *STI, bool IsLoad); bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI); @@ -255,9 +256,9 @@ class MipsAsmParser : public MCTargetAsmParser { bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI); - bool expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI, const bool IsMips64, - const bool Signed); + bool expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI, const bool IsMips64, + const bool Signed); bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc, MCStreamer &Out, const MCSubtargetInfo *STI); @@ -348,10 +349,12 @@ class MipsAsmParser : public MCTargetAsmParser { bool parseSetHardFloatDirective(); bool parseSetMtDirective(); bool parseSetNoMtDirective(); + bool parseSetNoCRCDirective(); + bool parseSetNoVirtDirective(); + bool parseSetNoGINVDirective(); bool parseSetAssignment(); - bool parseDataDirective(unsigned Size, SMLoc L); bool parseDirectiveGpWord(); bool parseDirectiveGpDWord(); bool parseDirectiveDtpRelWord(); @@ -466,6 +469,7 @@ public: Match_RequiresSameSrcAndDst, Match_NoFCCRegisterForCurrentISA, Match_NonZeroOperandForSync, + Match_NonZeroOperandForMTCX, Match_RequiresPosSizeRange0_32, Match_RequiresPosSizeRange33_64, Match_RequiresPosSizeUImm6, @@ -482,6 +486,9 @@ public: MCAsmParserExtension::Initialize(parser); parser.addAliasForDirective(".asciiz", ".asciz"); + parser.addAliasForDirective(".hword", ".2byte"); + parser.addAliasForDirective(".word", ".4byte"); + parser.addAliasForDirective(".dword", ".8byte"); // Initialize the set of available features. setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits())); @@ -507,14 +514,13 @@ public: CpRestoreOffset = -1; const Triple &TheTriple = sti.getTargetTriple(); - if ((TheTriple.getArch() == Triple::mips) || - (TheTriple.getArch() == Triple::mips64)) - IsLittleEndian = false; - else - IsLittleEndian = true; + IsLittleEndian = TheTriple.isLittleEndian(); if (getSTI().getCPU() == "mips64r6" && inMicroMipsMode()) report_fatal_error("microMIPS64R6 is not supported", false); + + if (!isABI_O32() && inMicroMipsMode()) + report_fatal_error("microMIPS64 is not supported", false); } /// True if all of $fcc0 - $fcc7 exist for the current ISA. @@ -643,6 +649,18 @@ public: return getSTI().getFeatureBits()[Mips::FeatureMT]; } + bool hasCRC() const { + return getSTI().getFeatureBits()[Mips::FeatureCRC]; + } + + bool hasVirt() const { + return getSTI().getFeatureBits()[Mips::FeatureVirt]; + } + + bool hasGINV() const { + return getSTI().getFeatureBits()[Mips::FeatureGINV]; + } + /// Warn if RegIndex is the same as the current AT. void warnIfRegIndexIsAT(unsigned RegIndex, SMLoc Loc); @@ -1297,6 +1315,20 @@ public: return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant()); } + bool isMemWithPtrSizeOffset() const { + if (!isMem()) + return false; + if (!getMemBase()->isGPRAsmReg()) + return false; + const unsigned PtrBits = AsmParser.getABI().ArePtrs64bit() ? 64 : 32; + if (isa<MCTargetExpr>(getMemOff()) || + (isConstantMemOff() && isIntN(PtrBits, getConstantMemOff()))) + return true; + MCValue Res; + bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr); + return IsReloc && isIntN(PtrBits, Res.getConstant()); + } + bool isMemWithGRPMM16Base() const { return isMem() && getMemBase()->isMM16AsmReg(); } @@ -1326,9 +1358,11 @@ public: template <unsigned Bits, unsigned ShiftLeftAmount> bool isScaledSImm() const { - if (isConstantImm() && isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm())) + if (isConstantImm() && + isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm())) return true; - // Operand can also be a symbol or symbol plus offset in case of relocations. + // Operand can also be a symbol or symbol plus + // offset in case of relocations. if (Kind != k_Immediate) return false; MCValue Res; @@ -1405,10 +1439,6 @@ public: return StringRef(Tok.Data, Tok.Length); } - 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, accept // $0/$zero here so that MCK_ZERO works correctly. @@ -1471,7 +1501,7 @@ public: static std::unique_ptr<MipsOperand> createNumericReg(unsigned Index, StringRef Str, const MCRegisterInfo *RegInfo, SMLoc S, SMLoc E, MipsAsmParser &Parser) { - DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n"); + LLVM_DEBUG(dbgs() << "createNumericReg(" << Index << ", ...)\n"); return CreateReg(Index, Str, RegKind_Numeric, RegInfo, S, E, Parser); } @@ -2034,7 +2064,8 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, // FIXME: Add support for forward-declared local symbols. // FIXME: Add expansion for when the LargeGOT option is enabled. if (JalSym->isInSection() || JalSym->isTemporary() || - (JalSym->isELF() && cast<MCSymbolELF>(JalSym)->getBinding() == ELF::STB_LOCAL)) { + (JalSym->isELF() && + cast<MCSymbolELF>(JalSym)->getBinding() == ELF::STB_LOCAL)) { if (isABI_O32()) { // If it's a local symbol and the O32 ABI is being used, we expand to: // lw $25, 0($gp) @@ -2102,10 +2133,10 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) { MCOperand &Op = Inst.getOperand(i); if (Op.isImm()) { - int MemOffset = Op.getImm(); + int64_t MemOffset = Op.getImm(); if (MemOffset < -32768 || MemOffset > 32767) { // Offset can't exceed 16bit value. - expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true); + expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad()); return getParser().hasPendingError(); } } else if (Op.isExpr()) { @@ -2115,11 +2146,11 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, static_cast<const MCSymbolRefExpr *>(Expr); if (SR->getKind() == MCSymbolRefExpr::VK_None) { // Expand symbol. - expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false); + expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad()); return getParser().hasPendingError(); } } else if (!isEvaluated(Expr)) { - expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false); + expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad()); return getParser().hasPendingError(); } } @@ -2128,7 +2159,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, } // if load/store if (inMicroMipsMode()) { - if (MCID.mayLoad()) { + if (MCID.mayLoad() && Inst.getOpcode() != Mips::LWP_MM) { // Try to create 16-bit GP relative load instruction. for (unsigned i = 0; i < MCID.getNumOperands(); i++) { const MCOperandInfo &OpInfo = MCID.OpInfo[i]; @@ -2245,13 +2276,18 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, return Error(IDLoc, "immediate operand value out of range"); break; case Mips::ADDIUPC_MM: - MCOperand Opnd = Inst.getOperand(1); + Opnd = Inst.getOperand(1); if (!Opnd.isImm()) return Error(IDLoc, "expected immediate operand kind"); - int Imm = Opnd.getImm(); + Imm = Opnd.getImm(); if ((Imm % 4 != 0) || !isInt<25>(Imm)) return Error(IDLoc, "immediate operand value out of range"); break; + case Mips::LWP_MM: + case Mips::SWP_MM: + if (Inst.getOperand(0).getReg() == Mips::RA) + return Error(IDLoc, "invalid operand for instruction"); + break; } } @@ -2392,20 +2428,28 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success; case Mips::SDivMacro: case Mips::SDivIMacro: - return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail - : MER_Success; + case Mips::SRemMacro: + case Mips::SRemIMacro: + return expandDivRem(Inst, IDLoc, Out, STI, false, true) ? MER_Fail + : MER_Success; case Mips::DSDivMacro: case Mips::DSDivIMacro: - return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail - : MER_Success; + case Mips::DSRemMacro: + case Mips::DSRemIMacro: + return expandDivRem(Inst, IDLoc, Out, STI, true, true) ? MER_Fail + : MER_Success; case Mips::UDivMacro: case Mips::UDivIMacro: - return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail - : MER_Success; + case Mips::URemMacro: + case Mips::URemIMacro: + return expandDivRem(Inst, IDLoc, Out, STI, false, false) ? MER_Fail + : MER_Success; case Mips::DUDivMacro: case Mips::DUDivIMacro: - return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail - : MER_Success; + case Mips::DURemMacro: + case Mips::DURemIMacro: + return expandDivRem(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; @@ -3522,21 +3566,17 @@ bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, } 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); -} + const MCSubtargetInfo *STI, bool IsLoad) { + const MCOperand &DstRegOp = Inst.getOperand(0); + assert(DstRegOp.isReg() && "expected register operand kind"); + const MCOperand &BaseRegOp = Inst.getOperand(1); + assert(BaseRegOp.isReg() && "expected register operand kind"); + const MCOperand &OffsetOp = Inst.getOperand(2); -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(); + unsigned DstReg = DstRegOp.getReg(); + unsigned BaseReg = BaseRegOp.getReg(); + unsigned TmpReg = DstReg; const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode()); int16_t DstRegClass = Desc.OpInfo[0].RegClass; @@ -3545,75 +3585,51 @@ void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, 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. - unsigned ATReg = getATReg(IDLoc); - if (!ATReg) + if (!IsLoad || !IsGPR || (BaseReg == DstReg)) { + // At this point we need AT to perform the expansions + // and we exit if it is not available. + TmpReg = getATReg(IDLoc); + if (!TmpReg) return; - - TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg, - Inst.getOperand(2).getImm(), ATReg, IDLoc, STI); - 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())); + if (OffsetOp.isImm()) { + int64_t LoOffset = OffsetOp.getImm() & 0xffff; + int64_t HiOffset = OffsetOp.getImm() & ~0xffff; - // Try to use DstReg as the temporary. - if (IsGPR && (BaseReg != DstReg)) { - TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand, - LoOperand, DstReg, IDLoc, STI); - return; - } + // 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 += 0x10000; - // 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; + bool IsLargeOffset = HiOffset != 0; - TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand, - LoOperand, ATReg, IDLoc, STI); -} - -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 (IsLargeOffset) { + bool Is32BitImm = (HiOffset >> 32) == 0; + if (loadImmediate(HiOffset, TmpReg, Mips::NoRegister, Is32BitImm, true, + IDLoc, Out, STI)) + return; + } - if (IsImmOpnd) { - TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg, - Inst.getOperand(2).getImm(), - [&]() { return getATReg(IDLoc); }, IDLoc, STI); - return; + if (BaseReg != Mips::ZERO && BaseReg != Mips::ZERO_64) + TOut.emitRRR(isGP64bit() ? Mips::DADDu : Mips::ADDu, TmpReg, TmpReg, + BaseReg, IDLoc, STI); + TOut.emitRRI(Inst.getOpcode(), DstReg, TmpReg, LoOffset, IDLoc, STI); + } else { + assert(OffsetOp.isExpr() && "expected expression operand kind"); + const MCExpr *ExprOffset = OffsetOp.getExpr(); + MCOperand LoOperand = MCOperand::createExpr( + MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext())); + MCOperand HiOperand = MCOperand::createExpr( + MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext())); + + if (IsLoad) + TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand, + LoOperand, TmpReg, IDLoc, STI); + else + TOut.emitStoreWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand, + LoOperand, TmpReg, IDLoc, STI); } - - 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, @@ -3734,7 +3750,8 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc, case Mips::BLTUL: AcceptsEquality = false; ReverseOrderSLT = false; - IsUnsigned = ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL)); + IsUnsigned = + ((PseudoOpcode == Mips::BLTU) || (PseudoOpcode == Mips::BLTUL)); IsLikely = ((PseudoOpcode == Mips::BLTL) || (PseudoOpcode == Mips::BLTUL)); ZeroSrcOpcode = Mips::BGTZ; ZeroTrgOpcode = Mips::BLTZ; @@ -3745,7 +3762,8 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc, case Mips::BLEUL: AcceptsEquality = true; ReverseOrderSLT = true; - IsUnsigned = ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL)); + IsUnsigned = + ((PseudoOpcode == Mips::BLEU) || (PseudoOpcode == Mips::BLEUL)); IsLikely = ((PseudoOpcode == Mips::BLEL) || (PseudoOpcode == Mips::BLEUL)); ZeroSrcOpcode = Mips::BGEZ; ZeroTrgOpcode = Mips::BLEZ; @@ -3756,7 +3774,8 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc, case Mips::BGEUL: AcceptsEquality = true; ReverseOrderSLT = false; - IsUnsigned = ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL)); + IsUnsigned = + ((PseudoOpcode == Mips::BGEU) || (PseudoOpcode == Mips::BGEUL)); IsLikely = ((PseudoOpcode == Mips::BGEL) || (PseudoOpcode == Mips::BGEUL)); ZeroSrcOpcode = Mips::BLEZ; ZeroTrgOpcode = Mips::BGEZ; @@ -3767,7 +3786,8 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc, case Mips::BGTUL: AcceptsEquality = false; ReverseOrderSLT = true; - IsUnsigned = ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL)); + IsUnsigned = + ((PseudoOpcode == Mips::BGTU) || (PseudoOpcode == Mips::BGTUL)); IsLikely = ((PseudoOpcode == Mips::BGTL) || (PseudoOpcode == Mips::BGTUL)); ZeroSrcOpcode = Mips::BLTZ; ZeroTrgOpcode = Mips::BGTZ; @@ -3885,7 +3905,7 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc, // This is accomplished by using a BNEZ with the result of the SLT. // // The other 2 pseudo-branches are opposites of the above 2 (BGE with BLT - // and BLE with BGT), so we change the BNEZ into a a BEQZ. + // and BLE with BGT), so we change the BNEZ into a BEQZ. // Because only BGE and BLE branch on equality, we can use the // AcceptsEquality variable to decide when to emit the BEQZ. // Note that the order of the SLT arguments doesn't change between @@ -3912,9 +3932,9 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc, // The destination register can only be $zero when expanding (S)DivIMacro or // D(S)DivMacro. -bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, - const MCSubtargetInfo *STI, const bool IsMips64, - const bool Signed) { +bool MipsAsmParser::expandDivRem(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, + const MCSubtargetInfo *STI, const bool IsMips64, + const bool Signed) { MipsTargetStreamer &TOut = getTargetStreamer(); warnIfNoMacro(IDLoc); @@ -3954,6 +3974,17 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, bool UseTraps = useTraps(); + unsigned Opcode = Inst.getOpcode(); + bool isDiv = Opcode == Mips::SDivMacro || Opcode == Mips::SDivIMacro || + Opcode == Mips::UDivMacro || Opcode == Mips::UDivIMacro || + Opcode == Mips::DSDivMacro || Opcode == Mips::DSDivIMacro || + Opcode == Mips::DUDivMacro || Opcode == Mips::DUDivIMacro; + + bool isRem = Opcode == Mips::SRemMacro || Opcode == Mips::SRemIMacro || + Opcode == Mips::URemMacro || Opcode == Mips::URemIMacro || + Opcode == Mips::DSRemMacro || Opcode == Mips::DSRemIMacro || + Opcode == Mips::DURemMacro || Opcode == Mips::DURemIMacro; + if (RtOp.isImm()) { unsigned ATReg = getATReg(IDLoc); if (!ATReg) @@ -3967,10 +3998,13 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, return false; } - if (ImmValue == 1) { + if (isRem && (ImmValue == 1 || (Signed && (ImmValue == -1)))) { + TOut.emitRRR(Mips::OR, RdReg, ZeroReg, ZeroReg, IDLoc, STI); + return false; + } else if (isDiv && ImmValue == 1) { TOut.emitRRR(Mips::OR, RdReg, RsReg, Mips::ZERO, IDLoc, STI); return false; - } else if (Signed && ImmValue == -1) { + } else if (isDiv && Signed && ImmValue == -1) { TOut.emitRRR(SubOp, RdReg, ZeroReg, RsReg, IDLoc, STI); return false; } else { @@ -3978,16 +4012,16 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, false, Inst.getLoc(), Out, STI)) return true; TOut.emitRR(DivOp, RsReg, ATReg, IDLoc, STI); - TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI); + TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI); return false; } return true; } - // If the macro expansion of (d)div(u) would always trap or break, insert - // the trap/break and exit. This gives a different result to GAS. GAS has - // an inconsistency/missed optimization in that not all cases are handled - // equivalently. As the observed behaviour is the same, we're ok. + // If the macro expansion of (d)div(u) or (d)rem(u) would always trap or + // break, insert the trap/break and exit. This gives a different result to + // GAS. GAS has an inconsistency/missed optimization in that not all cases + // are handled equivalently. As the observed behaviour is the same, we're ok. if (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64) { if (UseTraps) { TOut.emitRRI(Mips::TEQ, ZeroReg, ZeroReg, 0x7, IDLoc, STI); @@ -3997,6 +4031,13 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, return false; } + // (d)rem(u) $0, $X, $Y is a special case. Like div $zero, $X, $Y, it does + // not expand to macro sequence. + if (isRem && (RdReg == Mips::ZERO || RdReg == Mips::ZERO_64)) { + TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI); + return false; + } + // Temporary label for first branch traget MCContext &Context = TOut.getStreamer().getContext(); MCSymbol *BrTarget; @@ -4020,7 +4061,7 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, if (!UseTraps) TOut.getStreamer().EmitLabel(BrTarget); - TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI); + TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI); return false; } @@ -4043,7 +4084,7 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, if (IsMips64) { TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI); - TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI); + TOut.emitDSLL(ATReg, ATReg, 63, IDLoc, STI); } else { TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI); } @@ -4053,12 +4094,12 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, else { // Branch to the mflo instruction. TOut.emitRRX(Mips::BNE, RsReg, ATReg, LabelOpEnd, IDLoc, STI); - TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI); + TOut.emitNop(IDLoc, STI); TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI); } TOut.getStreamer().EmitLabel(BrTargetEnd); - TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI); + TOut.emitR(isDiv ? Mips::MFLO : Mips::MFHI, RdReg, IDLoc, STI); return false; } @@ -4287,7 +4328,8 @@ bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, DstReg = ATReg; } - if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) { + if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, + Inst.getLoc(), Out, STI)) { switch (FinalOpcode) { default: llvm_unreachable("unimplemented expansion"); @@ -4675,7 +4717,8 @@ bool MipsAsmParser::expandMulImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out, if (!ATReg) return true; - loadImmediate(ImmValue, ATReg, Mips::NoRegister, true, false, IDLoc, Out, STI); + loadImmediate(ImmValue, ATReg, Mips::NoRegister, true, false, IDLoc, Out, + STI); TOut.emitRR(Inst.getOpcode() == Mips::MULImmMacro ? Mips::MULT : Mips::DMULT, SrcReg, ATReg, IDLoc, STI); @@ -5136,13 +5179,13 @@ unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) { // 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::JALR_HB64: 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; @@ -5150,6 +5193,13 @@ unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) { if (Inst.getOperand(0).getImm() != 0 && !hasMips32()) return Match_NonZeroOperandForSync; return Match_Success; + case Mips::MFC0: + case Mips::MTC0: + case Mips::MTC2: + case Mips::MFC2: + if (Inst.getOperand(2).getImm() != 0 && !hasMips32()) + return Match_NonZeroOperandForMTCX; + return Match_Success; // As described the MIPSR6 spec, the compact branches that compare registers // must: // a) Not use the zero register. @@ -5237,6 +5287,13 @@ unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) { return Match_RequiresPosSizeRange33_64; return Match_Success; } + case Mips::CRC32B: case Mips::CRC32CB: + case Mips::CRC32H: case Mips::CRC32CH: + case Mips::CRC32W: case Mips::CRC32CW: + case Mips::CRC32D: case Mips::CRC32CD: + if (Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg()) + return Match_RequiresSameSrcAndDst; + return Match_Success; } uint64_t TSFlags = getInstDesc(Inst.getOpcode()).TSFlags; @@ -5290,7 +5347,10 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, return Error(ErrorLoc, "invalid operand for instruction"); } case Match_NonZeroOperandForSync: - return Error(IDLoc, "s-type must be zero or unspecified for pre-MIPS32 ISAs"); + return Error(IDLoc, + "s-type must be zero or unspecified for pre-MIPS32 ISAs"); + case Match_NonZeroOperandForMTCX: + return Error(IDLoc, "selector must be zero for pre-MIPS32 ISAs"); case Match_MnemonicFail: return Error(IDLoc, "invalid instruction"); case Match_RequiresDifferentSrcAndDst: @@ -5429,6 +5489,9 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, case Match_MemSImm16: return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected memory with 16-bit signed offset"); + case Match_MemSImmPtr: + return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), + "expected memory with 32-bit signed offset"); case Match_RequiresPosSizeRange0_32: { SMLoc ErrorStart = Operands[3]->getStartLoc(); SMLoc ErrorEnd = Operands[4]->getEndLoc(); @@ -5463,6 +5526,17 @@ void MipsAsmParser::warnIfNoMacro(SMLoc Loc) { Warning(Loc, "macro instruction expanded into multiple instructions"); } +void MipsAsmParser::ConvertXWPOperands(MCInst &Inst, + const OperandVector &Operands) { + assert( + (Inst.getOpcode() == Mips::LWP_MM || Inst.getOpcode() == Mips::SWP_MM) && + "Unexpected instruction!"); + ((MipsOperand &)*Operands[1]).addGPR32ZeroAsmRegOperands(Inst, 1); + int NextReg = nextReg(((MipsOperand &)*Operands[1]).getGPR32Reg()); + Inst.addOperand(MCOperand::createReg(NextReg)); + ((MipsOperand &)*Operands[2]).addMemOperands(Inst, 2); +} + void MipsAsmParser::printWarningWithFixIt(const Twine &Msg, const Twine &FixMsg, SMRange Range, bool ShowColors) { @@ -5653,7 +5727,7 @@ unsigned MipsAsmParser::getReg(int RC, int RegNo) { bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { MCAsmParser &Parser = getParser(); - DEBUG(dbgs() << "parseOperand\n"); + LLVM_DEBUG(dbgs() << "parseOperand\n"); // Check if the current operand has a custom associated parser, if so, try to // custom parse the operand, or fallback to the general approach. @@ -5666,7 +5740,7 @@ bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { if (ResTy == MatchOperand_ParseFail) return true; - DEBUG(dbgs() << ".. Generic Parser\n"); + LLVM_DEBUG(dbgs() << ".. Generic Parser\n"); switch (getLexer().getKind()) { case AsmToken::Dollar: { @@ -5696,7 +5770,7 @@ bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) { return false; } default: { - DEBUG(dbgs() << ".. generic integer expression\n"); + LLVM_DEBUG(dbgs() << ".. generic integer expression\n"); const MCExpr *Expr; SMLoc S = Parser.getTok().getLoc(); // Start location of the operand. @@ -5769,7 +5843,7 @@ bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) { OperandMatchResultTy MipsAsmParser::parseMemOperand(OperandVector &Operands) { MCAsmParser &Parser = getParser(); - DEBUG(dbgs() << "parseMemOperand\n"); + LLVM_DEBUG(dbgs() << "parseMemOperand\n"); const MCExpr *IdVal = nullptr; SMLoc S; bool isParenExpr = false; @@ -5905,13 +5979,12 @@ MipsAsmParser::parseMemOperand(OperandVector &Operands) { bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) { MCAsmParser &Parser = getParser(); MCSymbol *Sym = getContext().lookupSymbol(Parser.getTok().getIdentifier()); - if (Sym) { - SMLoc S = Parser.getTok().getLoc(); - const MCExpr *Expr; - if (Sym->isVariable()) - Expr = Sym->getVariableValue(); - else - return false; + if (!Sym) + return false; + + SMLoc S = Parser.getTok().getLoc(); + if (Sym->isVariable()) { + const MCExpr *Expr = Sym->getVariableValue(); if (Expr->getKind() == MCExpr::SymbolRef) { const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr *>(Expr); StringRef DefSymbol = Ref->getSymbol().getName(); @@ -5921,12 +5994,26 @@ bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) { if (ResTy == MatchOperand_Success) { Parser.Lex(); return true; - } else if (ResTy == MatchOperand_ParseFail) + } + if (ResTy == MatchOperand_ParseFail) llvm_unreachable("Should never ParseFail"); - return false; + } + } + } else if (Sym->isUnset()) { + // If symbol is unset, it might be created in the `parseSetAssignment` + // routine as an alias for a numeric register name. + // Lookup in the aliases list. + auto Entry = RegisterSets.find(Sym->getName()); + if (Entry != RegisterSets.end()) { + OperandMatchResultTy ResTy = + matchAnyRegisterWithoutDollar(Operands, Entry->getValue(), S); + if (ResTy == MatchOperand_Success) { + Parser.Lex(); + return true; } } } + return false; } @@ -5994,48 +6081,59 @@ MipsAsmParser::matchAnyRegisterNameWithoutDollar(OperandVector &Operands, } OperandMatchResultTy -MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) { - MCAsmParser &Parser = getParser(); - auto Token = Parser.getLexer().peekTok(false); - +MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, + const AsmToken &Token, SMLoc S) { if (Token.is(AsmToken::Identifier)) { - DEBUG(dbgs() << ".. identifier\n"); + LLVM_DEBUG(dbgs() << ".. identifier\n"); StringRef Identifier = Token.getIdentifier(); OperandMatchResultTy ResTy = matchAnyRegisterNameWithoutDollar(Operands, Identifier, S); return ResTy; } else if (Token.is(AsmToken::Integer)) { - DEBUG(dbgs() << ".. integer\n"); + LLVM_DEBUG(dbgs() << ".. integer\n"); + int64_t RegNum = Token.getIntVal(); + if (RegNum < 0 || RegNum > 31) { + // Show the error, but treat invalid register + // number as a normal one to continue parsing + // and catch other possible errors. + Error(getLexer().getLoc(), "invalid register number"); + } Operands.push_back(MipsOperand::createNumericReg( - Token.getIntVal(), Token.getString(), getContext().getRegisterInfo(), S, + RegNum, Token.getString(), getContext().getRegisterInfo(), S, Token.getLoc(), *this)); return MatchOperand_Success; } - DEBUG(dbgs() << Parser.getTok().getKind() << "\n"); + LLVM_DEBUG(dbgs() << Token.getKind() << "\n"); return MatchOperand_NoMatch; } OperandMatchResultTy +MipsAsmParser::matchAnyRegisterWithoutDollar(OperandVector &Operands, SMLoc S) { + auto Token = getLexer().peekTok(false); + return matchAnyRegisterWithoutDollar(Operands, Token, S); +} + +OperandMatchResultTy MipsAsmParser::parseAnyRegister(OperandVector &Operands) { MCAsmParser &Parser = getParser(); - DEBUG(dbgs() << "parseAnyRegister\n"); + LLVM_DEBUG(dbgs() << "parseAnyRegister\n"); auto Token = Parser.getTok(); SMLoc S = Token.getLoc(); if (Token.isNot(AsmToken::Dollar)) { - DEBUG(dbgs() << ".. !$ -> try sym aliasing\n"); + LLVM_DEBUG(dbgs() << ".. !$ -> try sym aliasing\n"); if (Token.is(AsmToken::Identifier)) { if (searchSymbolAlias(Operands)) return MatchOperand_Success; } - DEBUG(dbgs() << ".. !symalias -> NoMatch\n"); + LLVM_DEBUG(dbgs() << ".. !symalias -> NoMatch\n"); return MatchOperand_NoMatch; } - DEBUG(dbgs() << ".. $\n"); + LLVM_DEBUG(dbgs() << ".. $\n"); OperandMatchResultTy ResTy = matchAnyRegisterWithoutDollar(Operands, S); if (ResTy == MatchOperand_Success) { @@ -6048,7 +6146,7 @@ MipsAsmParser::parseAnyRegister(OperandVector &Operands) { OperandMatchResultTy MipsAsmParser::parseJumpTarget(OperandVector &Operands) { MCAsmParser &Parser = getParser(); - DEBUG(dbgs() << "parseJumpTarget\n"); + LLVM_DEBUG(dbgs() << "parseJumpTarget\n"); SMLoc S = getLexer().getLoc(); @@ -6181,22 +6279,6 @@ MipsAsmParser::parseRegisterList(OperandVector &Operands) { } OperandMatchResultTy -MipsAsmParser::parseRegisterPair(OperandVector &Operands) { - MCAsmParser &Parser = getParser(); - - SMLoc S = Parser.getTok().getLoc(); - if (parseAnyRegister(Operands) != MatchOperand_Success) - return MatchOperand_ParseFail; - - SMLoc E = Parser.getTok().getLoc(); - MipsOperand Op = static_cast<MipsOperand &>(*Operands.back()); - - Operands.pop_back(); - Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this)); - return MatchOperand_Success; -} - -OperandMatchResultTy MipsAsmParser::parseMovePRegPair(OperandVector &Operands) { MCAsmParser &Parser = getParser(); SmallVector<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands; @@ -6292,7 +6374,7 @@ bool MipsAsmParser::parseBracketSuffix(StringRef Name, bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc, OperandVector &Operands) { MCAsmParser &Parser = getParser(); - DEBUG(dbgs() << "ParseInstruction\n"); + LLVM_DEBUG(dbgs() << "ParseInstruction\n"); // We have reached first instruction, module directive are now forbidden. getTargetStreamer().forbidModuleDirective(); @@ -6654,6 +6736,57 @@ bool MipsAsmParser::parseSetNoMtDirective() { return false; } +bool MipsAsmParser::parseSetNoCRCDirective() { + MCAsmParser &Parser = getParser(); + Parser.Lex(); // Eat "nocrc". + + // 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; + } + + clearFeatureBits(Mips::FeatureCRC, "crc"); + + getTargetStreamer().emitDirectiveSetNoCRC(); + Parser.Lex(); // Consume the EndOfStatement. + return false; +} + +bool MipsAsmParser::parseSetNoVirtDirective() { + MCAsmParser &Parser = getParser(); + Parser.Lex(); // Eat "novirt". + + // 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; + } + + clearFeatureBits(Mips::FeatureVirt, "virt"); + + getTargetStreamer().emitDirectiveSetNoVirt(); + Parser.Lex(); // Consume the EndOfStatement. + return false; +} + +bool MipsAsmParser::parseSetNoGINVDirective() { + MCAsmParser &Parser = getParser(); + Parser.Lex(); // Eat "noginv". + + // 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; + } + + clearFeatureBits(Mips::FeatureGINV, "ginv"); + + getTargetStreamer().emitDirectiveSetNoGINV(); + Parser.Lex(); // Consume the EndOfStatement. + return false; +} + bool MipsAsmParser::parseSetPopDirective() { MCAsmParser &Parser = getParser(); SMLoc Loc = getLexer().getLoc(); @@ -6719,17 +6852,30 @@ bool MipsAsmParser::parseSetAssignment() { MCAsmParser &Parser = getParser(); if (Parser.parseIdentifier(Name)) - reportParseError("expected identifier after .set"); + return reportParseError("expected identifier after .set"); if (getLexer().isNot(AsmToken::Comma)) return reportParseError("unexpected token, expected comma"); Lex(); // Eat comma - if (Parser.parseExpression(Value)) + if (getLexer().is(AsmToken::Dollar) && + getLexer().peekTok().is(AsmToken::Integer)) { + // Parse assignment of a numeric register: + // .set r1,$1 + Parser.Lex(); // Eat $. + RegisterSets[Name] = Parser.getTok(); + Parser.Lex(); // Eat identifier. + getContext().getOrCreateSymbol(Name); + } else if (!Parser.parseExpression(Value)) { + // Parse assignment of an expression including + // symbolic registers: + // .set $tmp, $BB0-$BB1 + // .set r2, $f2 + MCSymbol *Sym = getContext().getOrCreateSymbol(Name); + Sym->setVariableValue(Value); + } else { return reportParseError("expected valid expression after comma"); - - MCSymbol *Sym = getContext().getOrCreateSymbol(Name); - Sym->setVariableValue(Value); + } return false; } @@ -6875,6 +7021,18 @@ bool MipsAsmParser::parseSetFeature(uint64_t Feature) { selectArch("mips64r6"); getTargetStreamer().emitDirectiveSetMips64R6(); break; + case Mips::FeatureCRC: + setFeatureBits(Mips::FeatureCRC, "crc"); + getTargetStreamer().emitDirectiveSetCRC(); + break; + case Mips::FeatureVirt: + setFeatureBits(Mips::FeatureVirt, "virt"); + getTargetStreamer().emitDirectiveSetVirt(); + break; + case Mips::FeatureGINV: + setFeatureBits(Mips::FeatureGINV, "ginv"); + getTargetStreamer().emitDirectiveSetGINV(); + break; } return false; } @@ -7074,143 +7232,131 @@ bool MipsAsmParser::parseDirectiveNaN() { } bool MipsAsmParser::parseDirectiveSet() { - MCAsmParser &Parser = getParser(); - // Get the next token. - const AsmToken &Tok = Parser.getTok(); + const AsmToken &Tok = getParser().getTok(); + StringRef IdVal = Tok.getString(); + SMLoc Loc = Tok.getLoc(); - if (Tok.getString() == "noat") { + if (IdVal == "noat") return parseSetNoAtDirective(); - } else if (Tok.getString() == "at") { + if (IdVal == "at") return parseSetAtDirective(); - } else if (Tok.getString() == "arch") { + if (IdVal == "arch") return parseSetArchDirective(); - } else if (Tok.getString() == "bopt") { - Warning(Tok.getLoc(), "'bopt' feature is unsupported"); + if (IdVal == "bopt") { + Warning(Loc, "'bopt' feature is unsupported"); getParser().Lex(); return false; - } else if (Tok.getString() == "nobopt") { + } + if (IdVal == "nobopt") { // We're already running in nobopt mode, so nothing to do. getParser().Lex(); return false; - } else if (Tok.getString() == "fp") { + } + if (IdVal == "fp") return parseSetFpDirective(); - } else if (Tok.getString() == "oddspreg") { + if (IdVal == "oddspreg") return parseSetOddSPRegDirective(); - } else if (Tok.getString() == "nooddspreg") { + if (IdVal == "nooddspreg") return parseSetNoOddSPRegDirective(); - } else if (Tok.getString() == "pop") { + if (IdVal == "pop") return parseSetPopDirective(); - } else if (Tok.getString() == "push") { + if (IdVal == "push") return parseSetPushDirective(); - } else if (Tok.getString() == "reorder") { + if (IdVal == "reorder") return parseSetReorderDirective(); - } else if (Tok.getString() == "noreorder") { + if (IdVal == "noreorder") return parseSetNoReorderDirective(); - } else if (Tok.getString() == "macro") { + if (IdVal == "macro") return parseSetMacroDirective(); - } else if (Tok.getString() == "nomacro") { + if (IdVal == "nomacro") return parseSetNoMacroDirective(); - } else if (Tok.getString() == "mips16") { + if (IdVal == "mips16") return parseSetMips16Directive(); - } else if (Tok.getString() == "nomips16") { + if (IdVal == "nomips16") return parseSetNoMips16Directive(); - } else if (Tok.getString() == "nomicromips") { + if (IdVal == "nomicromips") { clearFeatureBits(Mips::FeatureMicroMips, "micromips"); getTargetStreamer().emitDirectiveSetNoMicroMips(); - Parser.eatToEndOfStatement(); + getParser().eatToEndOfStatement(); return false; - } else if (Tok.getString() == "micromips") { + } + if (IdVal == "micromips") { if (hasMips64r6()) { - Error(Tok.getLoc(), ".set micromips directive is not supported with MIPS64R6"); + Error(Loc, ".set micromips directive is not supported with MIPS64R6"); return false; } return parseSetFeature(Mips::FeatureMicroMips); - } else if (Tok.getString() == "mips0") { + } + if (IdVal == "mips0") return parseSetMips0Directive(); - } else if (Tok.getString() == "mips1") { + if (IdVal == "mips1") return parseSetFeature(Mips::FeatureMips1); - } else if (Tok.getString() == "mips2") { + if (IdVal == "mips2") return parseSetFeature(Mips::FeatureMips2); - } else if (Tok.getString() == "mips3") { + if (IdVal == "mips3") return parseSetFeature(Mips::FeatureMips3); - } else if (Tok.getString() == "mips4") { + if (IdVal == "mips4") return parseSetFeature(Mips::FeatureMips4); - } else if (Tok.getString() == "mips5") { + if (IdVal == "mips5") return parseSetFeature(Mips::FeatureMips5); - } else if (Tok.getString() == "mips32") { + if (IdVal == "mips32") return parseSetFeature(Mips::FeatureMips32); - } else if (Tok.getString() == "mips32r2") { + if (IdVal == "mips32r2") return parseSetFeature(Mips::FeatureMips32r2); - } else if (Tok.getString() == "mips32r3") { + if (IdVal == "mips32r3") return parseSetFeature(Mips::FeatureMips32r3); - } else if (Tok.getString() == "mips32r5") { + if (IdVal == "mips32r5") return parseSetFeature(Mips::FeatureMips32r5); - } else if (Tok.getString() == "mips32r6") { + if (IdVal == "mips32r6") return parseSetFeature(Mips::FeatureMips32r6); - } else if (Tok.getString() == "mips64") { + if (IdVal == "mips64") return parseSetFeature(Mips::FeatureMips64); - } else if (Tok.getString() == "mips64r2") { + if (IdVal == "mips64r2") return parseSetFeature(Mips::FeatureMips64r2); - } else if (Tok.getString() == "mips64r3") { + if (IdVal == "mips64r3") return parseSetFeature(Mips::FeatureMips64r3); - } else if (Tok.getString() == "mips64r5") { + if (IdVal == "mips64r5") return parseSetFeature(Mips::FeatureMips64r5); - } else if (Tok.getString() == "mips64r6") { + if (IdVal == "mips64r6") { if (inMicroMipsMode()) { - Error(Tok.getLoc(), "MIPS64R6 is not supported with microMIPS"); + Error(Loc, "MIPS64R6 is not supported with microMIPS"); return false; } return parseSetFeature(Mips::FeatureMips64r6); - } else if (Tok.getString() == "dsp") { + } + if (IdVal == "dsp") return parseSetFeature(Mips::FeatureDSP); - } else if (Tok.getString() == "dspr2") { + if (IdVal == "dspr2") return parseSetFeature(Mips::FeatureDSPR2); - } else if (Tok.getString() == "nodsp") { + if (IdVal == "nodsp") return parseSetNoDspDirective(); - } else if (Tok.getString() == "msa") { + if (IdVal == "msa") return parseSetMsaDirective(); - } else if (Tok.getString() == "nomsa") { + if (IdVal == "nomsa") return parseSetNoMsaDirective(); - } else if (Tok.getString() == "mt") { + if (IdVal == "mt") return parseSetMtDirective(); - } else if (Tok.getString() == "nomt") { + if (IdVal == "nomt") return parseSetNoMtDirective(); - } else if (Tok.getString() == "softfloat") { + if (IdVal == "softfloat") return parseSetSoftFloatDirective(); - } else if (Tok.getString() == "hardfloat") { + if (IdVal == "hardfloat") return parseSetHardFloatDirective(); - } else { - // It is just an identifier, look for an assignment. - parseSetAssignment(); - return false; - } - - return true; -} - -/// parseDataDirective -/// ::= .word [ expression (, expression)* ] -bool MipsAsmParser::parseDataDirective(unsigned Size, SMLoc L) { - MCAsmParser &Parser = getParser(); - if (getLexer().isNot(AsmToken::EndOfStatement)) { - while (true) { - const MCExpr *Value; - if (getParser().parseExpression(Value)) - return true; - - getParser().getStreamer().EmitValue(Value, Size); - - if (getLexer().is(AsmToken::EndOfStatement)) - break; - - if (getLexer().isNot(AsmToken::Comma)) - return Error(L, "unexpected token, expected comma"); - Parser.Lex(); - } - } - - Parser.Lex(); - return false; + if (IdVal == "crc") + return parseSetFeature(Mips::FeatureCRC); + if (IdVal == "nocrc") + return parseSetNoCRCDirective(); + if (IdVal == "virt") + return parseSetFeature(Mips::FeatureVirt); + if (IdVal == "novirt") + return parseSetNoVirtDirective(); + if (IdVal == "ginv") + return parseSetFeature(Mips::FeatureGINV); + if (IdVal == "noginv") + return parseSetNoGINVDirective(); + + // It is just an identifier, look for an assignment. + return parseSetAssignment(); } /// parseDirectiveGpWord @@ -7425,6 +7571,12 @@ bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) { /// ::= .module softfloat /// ::= .module hardfloat /// ::= .module mt +/// ::= .module crc +/// ::= .module nocrc +/// ::= .module virt +/// ::= .module novirt +/// ::= .module ginv +/// ::= .module noginv bool MipsAsmParser::parseDirectiveModule() { MCAsmParser &Parser = getParser(); MCAsmLexer &Lexer = getLexer(); @@ -7543,6 +7695,120 @@ bool MipsAsmParser::parseDirectiveModule() { } return false; // parseDirectiveModule has finished successfully. + } else if (Option == "crc") { + setModuleFeatureBits(Mips::FeatureCRC, "crc"); + + // Synchronize the ABI Flags information with the FeatureBits information we + // updated above. + getTargetStreamer().updateABIInfo(*this); + + // If printing assembly, use the recently updated ABI Flags information. + // If generating ELF, don't do anything (the .MIPS.abiflags section gets + // emitted later). + getTargetStreamer().emitDirectiveModuleCRC(); + + // 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; + } + + return false; // parseDirectiveModule has finished successfully. + } else if (Option == "nocrc") { + clearModuleFeatureBits(Mips::FeatureCRC, "crc"); + + // Synchronize the ABI Flags information with the FeatureBits information we + // updated above. + getTargetStreamer().updateABIInfo(*this); + + // If printing assembly, use the recently updated ABI Flags information. + // If generating ELF, don't do anything (the .MIPS.abiflags section gets + // emitted later). + getTargetStreamer().emitDirectiveModuleNoCRC(); + + // 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; + } + + return false; // parseDirectiveModule has finished successfully. + } else if (Option == "virt") { + setModuleFeatureBits(Mips::FeatureVirt, "virt"); + + // Synchronize the ABI Flags information with the FeatureBits information we + // updated above. + getTargetStreamer().updateABIInfo(*this); + + // If printing assembly, use the recently updated ABI Flags information. + // If generating ELF, don't do anything (the .MIPS.abiflags section gets + // emitted later). + getTargetStreamer().emitDirectiveModuleVirt(); + + // 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; + } + + return false; // parseDirectiveModule has finished successfully. + } else if (Option == "novirt") { + clearModuleFeatureBits(Mips::FeatureVirt, "virt"); + + // Synchronize the ABI Flags information with the FeatureBits information we + // updated above. + getTargetStreamer().updateABIInfo(*this); + + // If printing assembly, use the recently updated ABI Flags information. + // If generating ELF, don't do anything (the .MIPS.abiflags section gets + // emitted later). + getTargetStreamer().emitDirectiveModuleNoVirt(); + + // 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; + } + + return false; // parseDirectiveModule has finished successfully. + } else if (Option == "ginv") { + setModuleFeatureBits(Mips::FeatureGINV, "ginv"); + + // Synchronize the ABI Flags information with the FeatureBits information we + // updated above. + getTargetStreamer().updateABIInfo(*this); + + // If printing assembly, use the recently updated ABI Flags information. + // If generating ELF, don't do anything (the .MIPS.abiflags section gets + // emitted later). + getTargetStreamer().emitDirectiveModuleGINV(); + + // 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; + } + + return false; // parseDirectiveModule has finished successfully. + } else if (Option == "noginv") { + clearModuleFeatureBits(Mips::FeatureGINV, "ginv"); + + // Synchronize the ABI Flags information with the FeatureBits information we + // updated above. + getTargetStreamer().updateABIInfo(*this); + + // If printing assembly, use the recently updated ABI Flags information. + // If generating ELF, don't do anything (the .MIPS.abiflags section gets + // emitted later). + getTargetStreamer().emitDirectiveModuleNoGINV(); + + // 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; + } + + return false; // parseDirectiveModule has finished successfully. } else { return Error(L, "'" + Twine(Option) + "' is not a valid .module option."); } @@ -7672,10 +7938,6 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) { parseDirectiveCpRestore(DirectiveID.getLoc()); return false; } - if (IDVal == ".dword") { - parseDataDirective(8, DirectiveID.getLoc()); - return false; - } if (IDVal == ".ent") { StringRef SymbolName; @@ -7923,16 +8185,6 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) { return false; } - if (IDVal == ".word") { - parseDataDirective(4, DirectiveID.getLoc()); - return false; - } - - if (IDVal == ".hword") { - parseDataDirective(2, DirectiveID.getLoc()); - return false; - } - if (IDVal == ".option") { parseDirectiveOption(); return false; diff --git a/lib/Target/Mips/CMakeLists.txt b/lib/Target/Mips/CMakeLists.txt index 40e337eb97ca..2cacc0a0870c 100644 --- a/lib/Target/Mips/CMakeLists.txt +++ b/lib/Target/Mips/CMakeLists.txt @@ -1,16 +1,19 @@ set(LLVM_TARGET_DEFINITIONS Mips.td) -tablegen(LLVM MipsGenRegisterInfo.inc -gen-register-info) -tablegen(LLVM MipsGenInstrInfo.inc -gen-instr-info) -tablegen(LLVM MipsGenDisassemblerTables.inc -gen-disassembler) -tablegen(LLVM MipsGenMCCodeEmitter.inc -gen-emitter) +tablegen(LLVM MipsGenAsmMatcher.inc -gen-asm-matcher) tablegen(LLVM MipsGenAsmWriter.inc -gen-asm-writer) +tablegen(LLVM MipsGenCallingConv.inc -gen-callingconv) tablegen(LLVM MipsGenDAGISel.inc -gen-dag-isel) +tablegen(LLVM MipsGenDisassemblerTables.inc -gen-disassembler) tablegen(LLVM MipsGenFastISel.inc -gen-fast-isel) -tablegen(LLVM MipsGenCallingConv.inc -gen-callingconv) -tablegen(LLVM MipsGenSubtargetInfo.inc -gen-subtarget) -tablegen(LLVM MipsGenAsmMatcher.inc -gen-asm-matcher) +tablegen(LLVM MipsGenGlobalISel.inc -gen-global-isel) +tablegen(LLVM MipsGenInstrInfo.inc -gen-instr-info) +tablegen(LLVM MipsGenMCCodeEmitter.inc -gen-emitter) tablegen(LLVM MipsGenMCPseudoLowering.inc -gen-pseudo-lowering) +tablegen(LLVM MipsGenRegisterBank.inc -gen-register-bank) +tablegen(LLVM MipsGenRegisterInfo.inc -gen-register-info) +tablegen(LLVM MipsGenSubtargetInfo.inc -gen-subtarget) + add_public_tablegen_target(MipsCommonTableGen) add_llvm_target(MipsCodeGen @@ -23,21 +26,25 @@ add_llvm_target(MipsCodeGen Mips16RegisterInfo.cpp MipsAnalyzeImmediate.cpp MipsAsmPrinter.cpp + MipsCallLowering.cpp MipsCCState.cpp MipsConstantIslandPass.cpp MipsDelaySlotFiller.cpp + MipsExpandPseudo.cpp MipsFastISel.cpp - MipsHazardSchedule.cpp MipsInstrInfo.cpp + MipsInstructionSelector.cpp MipsISelDAGToDAG.cpp MipsISelLowering.cpp MipsFrameLowering.cpp - MipsLongBranch.cpp + MipsLegalizerInfo.cpp + MipsBranchExpansion.cpp MipsMCInstLower.cpp MipsMachineFunction.cpp MipsModuleISelDAGToDAG.cpp MipsOptimizePICCall.cpp MipsOs16.cpp + MipsRegisterBankInfo.cpp MipsRegisterInfo.cpp MipsSEFrameLowering.cpp MipsSEInstrInfo.cpp @@ -50,9 +57,8 @@ add_llvm_target(MipsCodeGen MicroMipsSizeReduction.cpp ) -add_subdirectory(InstPrinter) +add_subdirectory(AsmParser) add_subdirectory(Disassembler) -add_subdirectory(TargetInfo) +add_subdirectory(InstPrinter) add_subdirectory(MCTargetDesc) -add_subdirectory(AsmParser) - +add_subdirectory(TargetInfo) diff --git a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp index ef0f08b49850..b94afb9520e3 100644 --- a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -277,11 +277,6 @@ static DecodeStatus DecodeMemEVA(MCInst &Inst, uint64_t Address, const void *Decoder); -static DecodeStatus DecodeLoadByte9(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder); - static DecodeStatus DecodeLoadByte15(MCInst &Inst, unsigned Insn, uint64_t Address, @@ -300,11 +295,6 @@ static DecodeStatus DecodeCacheOpMM(MCInst &Inst, uint64_t Address, const void *Decoder); -static DecodeStatus DecodeStoreEvaOpMM(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder); - static DecodeStatus DecodePrefeOpMM(MCInst &Inst, unsigned Insn, uint64_t Address, @@ -315,6 +305,11 @@ static DecodeStatus DecodeSyncI(MCInst &Inst, uint64_t Address, const void *Decoder); +static DecodeStatus DecodeSyncI_MM(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder); + static DecodeStatus DecodeSynciR6(MCInst &Inst, unsigned Insn, uint64_t Address, @@ -527,6 +522,10 @@ template <typename InsnType> static DecodeStatus DecodeDEXT(MCInst &MI, InsnType Insn, uint64_t Address, const void *Decoder); +template <typename InsnType> +static DecodeStatus DecodeCRC(MCInst &MI, InsnType Insn, uint64_t Address, + const void *Decoder); + static DecodeStatus DecodeRegListOperand(MCInst &Inst, unsigned Insn, uint64_t Address, const void *Decoder); @@ -1139,6 +1138,22 @@ static DecodeStatus DecodeDINS(MCInst &MI, InsnType Insn, uint64_t Address, return MCDisassembler::Success; } + +// Auto-generated decoder wouldn't add the third operand for CRC32*. +template <typename InsnType> +static DecodeStatus DecodeCRC(MCInst &MI, InsnType Insn, uint64_t Address, + const void *Decoder) { + InsnType Rs = fieldFromInstruction(Insn, 21, 5); + InsnType Rt = fieldFromInstruction(Insn, 16, 5); + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, + Rt))); + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, + Rs))); + MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, + Rt))); + return MCDisassembler::Success; +} + /// Read two bytes from the ArrayRef and return 16 bit halfword sorted /// according to the given endianness. static DecodeStatus readInstruction16(ArrayRef<uint8_t> Bytes, uint64_t Address, @@ -1210,7 +1225,8 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, return MCDisassembler::Fail; if (hasMips32r6()) { - DEBUG(dbgs() << "Trying MicroMipsR616 table (16-bit instructions):\n"); + LLVM_DEBUG( + dbgs() << "Trying MicroMipsR616 table (16-bit instructions):\n"); // Calling the auto-generated decoder function for microMIPS32R6 // 16-bit instructions. Result = decodeInstruction(DecoderTableMicroMipsR616, Instr, Insn, @@ -1221,7 +1237,7 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, } } - DEBUG(dbgs() << "Trying MicroMips16 table (16-bit instructions):\n"); + LLVM_DEBUG(dbgs() << "Trying MicroMips16 table (16-bit instructions):\n"); // Calling the auto-generated decoder function for microMIPS 16-bit // instructions. Result = decodeInstruction(DecoderTableMicroMips16, Instr, Insn, Address, @@ -1236,7 +1252,8 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, return MCDisassembler::Fail; if (hasMips32r6()) { - DEBUG(dbgs() << "Trying MicroMips32r632 table (32-bit instructions):\n"); + LLVM_DEBUG( + dbgs() << "Trying MicroMips32r632 table (32-bit instructions):\n"); // Calling the auto-generated decoder function. Result = decodeInstruction(DecoderTableMicroMipsR632, Instr, Insn, Address, this, STI); @@ -1246,7 +1263,7 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, } } - DEBUG(dbgs() << "Trying MicroMips32 table (32-bit instructions):\n"); + LLVM_DEBUG(dbgs() << "Trying MicroMips32 table (32-bit instructions):\n"); // Calling the auto-generated decoder function. Result = decodeInstruction(DecoderTableMicroMips32, Instr, Insn, Address, this, STI); @@ -1256,7 +1273,7 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, } if (isFP64()) { - DEBUG(dbgs() << "Trying MicroMipsFP64 table (32-bit opcodes):\n"); + LLVM_DEBUG(dbgs() << "Trying MicroMipsFP64 table (32-bit opcodes):\n"); Result = decodeInstruction(DecoderTableMicroMipsFP6432, Instr, Insn, Address, this, STI); if (Result != MCDisassembler::Fail) { @@ -1285,7 +1302,7 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, Size = 4; if (hasCOP3()) { - DEBUG(dbgs() << "Trying COP3_ table (32-bit opcodes):\n"); + LLVM_DEBUG(dbgs() << "Trying COP3_ table (32-bit opcodes):\n"); Result = decodeInstruction(DecoderTableCOP3_32, Instr, Insn, Address, this, STI); if (Result != MCDisassembler::Fail) @@ -1293,7 +1310,8 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, } if (hasMips32r6() && isGP64()) { - DEBUG(dbgs() << "Trying Mips32r6_64r6 (GPR64) table (32-bit opcodes):\n"); + LLVM_DEBUG( + dbgs() << "Trying Mips32r6_64r6 (GPR64) table (32-bit opcodes):\n"); Result = decodeInstruction(DecoderTableMips32r6_64r6_GP6432, Instr, Insn, Address, this, STI); if (Result != MCDisassembler::Fail) @@ -1301,7 +1319,8 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, } if (hasMips32r6() && isPTR64()) { - DEBUG(dbgs() << "Trying Mips32r6_64r6 (PTR64) table (32-bit opcodes):\n"); + LLVM_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) @@ -1309,7 +1328,7 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, } if (hasMips32r6()) { - DEBUG(dbgs() << "Trying Mips32r6_64r6 table (32-bit opcodes):\n"); + LLVM_DEBUG(dbgs() << "Trying Mips32r6_64r6 table (32-bit opcodes):\n"); Result = decodeInstruction(DecoderTableMips32r6_64r632, Instr, Insn, Address, this, STI); if (Result != MCDisassembler::Fail) @@ -1317,7 +1336,8 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, } if (hasMips2() && isPTR64()) { - DEBUG(dbgs() << "Trying Mips32r6_64r6 (PTR64) table (32-bit opcodes):\n"); + LLVM_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) @@ -1325,7 +1345,7 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, } if (hasCnMips()) { - DEBUG(dbgs() << "Trying CnMips table (32-bit opcodes):\n"); + LLVM_DEBUG(dbgs() << "Trying CnMips table (32-bit opcodes):\n"); Result = decodeInstruction(DecoderTableCnMips32, Instr, Insn, Address, this, STI); if (Result != MCDisassembler::Fail) @@ -1333,7 +1353,7 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, } if (isGP64()) { - DEBUG(dbgs() << "Trying Mips64 (GPR64) table (32-bit opcodes):\n"); + LLVM_DEBUG(dbgs() << "Trying Mips64 (GPR64) table (32-bit opcodes):\n"); Result = decodeInstruction(DecoderTableMips6432, Instr, Insn, Address, this, STI); if (Result != MCDisassembler::Fail) @@ -1341,14 +1361,15 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size, } if (isFP64()) { - DEBUG(dbgs() << "Trying MipsFP64 (64 bit FPU) table (32-bit opcodes):\n"); + LLVM_DEBUG( + dbgs() << "Trying MipsFP64 (64 bit FPU) table (32-bit opcodes):\n"); Result = decodeInstruction(DecoderTableMipsFP6432, Instr, Insn, Address, this, STI); if (Result != MCDisassembler::Fail) return Result; } - DEBUG(dbgs() << "Trying Mips table (32-bit opcodes):\n"); + LLVM_DEBUG(dbgs() << "Trying Mips table (32-bit opcodes):\n"); // Calling the auto-generated decoder function. Result = decodeInstruction(DecoderTableMips32, Instr, Insn, Address, this, STI); @@ -1538,24 +1559,6 @@ static DecodeStatus DecodeMemEVA(MCInst &Inst, return MCDisassembler::Success; } -static DecodeStatus DecodeLoadByte9(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder) { - int Offset = SignExtend32<9>(Insn & 0x1ff); - unsigned Base = fieldFromInstruction(Insn, 16, 5); - unsigned Reg = fieldFromInstruction(Insn, 21, 5); - - Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - Reg = getReg(Decoder, Mips::GPR32RegClassID, Reg); - - Inst.addOperand(MCOperand::createReg(Reg)); - Inst.addOperand(MCOperand::createReg(Base)); - Inst.addOperand(MCOperand::createImm(Offset)); - - return MCDisassembler::Success; -} - static DecodeStatus DecodeLoadByte15(MCInst &Inst, unsigned Insn, uint64_t Address, @@ -1642,30 +1645,25 @@ static DecodeStatus DecodeCacheeOp_CacheOpR6(MCInst &Inst, return MCDisassembler::Success; } -static DecodeStatus DecodeStoreEvaOpMM(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder) { - int Offset = SignExtend32<9>(Insn & 0x1ff); - unsigned Reg = fieldFromInstruction(Insn, 21, 5); - unsigned Base = fieldFromInstruction(Insn, 16, 5); +static DecodeStatus DecodeSyncI(MCInst &Inst, + unsigned Insn, + uint64_t Address, + const void *Decoder) { + int Offset = SignExtend32<16>(Insn & 0xffff); + unsigned Base = fieldFromInstruction(Insn, 21, 5); - Reg = getReg(Decoder, Mips::GPR32RegClassID, Reg); Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - Inst.addOperand(MCOperand::createReg(Reg)); Inst.addOperand(MCOperand::createReg(Base)); Inst.addOperand(MCOperand::createImm(Offset)); return MCDisassembler::Success; } -static DecodeStatus DecodeSyncI(MCInst &Inst, - unsigned Insn, - uint64_t Address, - const void *Decoder) { +static DecodeStatus DecodeSyncI_MM(MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder) { int Offset = SignExtend32<16>(Insn & 0xffff); - unsigned Base = fieldFromInstruction(Insn, 21, 5); + unsigned Base = fieldFromInstruction(Insn, 16, 5); Base = getReg(Decoder, Mips::GPR32RegClassID, Base); @@ -1862,7 +1860,7 @@ static DecodeStatus DecodeMemMMImm9(MCInst &Inst, Reg = getReg(Decoder, Mips::GPR32RegClassID, Reg); Base = getReg(Decoder, Mips::GPR32RegClassID, Base); - if (Inst.getOpcode() == Mips::SCE_MM) + if (Inst.getOpcode() == Mips::SCE_MM || Inst.getOpcode() == Mips::SC_MMR6) Inst.addOperand(MCOperand::createReg(Reg)); Inst.addOperand(MCOperand::createReg(Reg)); @@ -1897,8 +1895,7 @@ static DecodeStatus DecodeMemMMImm12(MCInst &Inst, LLVM_FALLTHROUGH; default: Inst.addOperand(MCOperand::createReg(Reg)); - if (Inst.getOpcode() == Mips::LWP_MM || Inst.getOpcode() == Mips::SWP_MM || - Inst.getOpcode() == Mips::LWP_MMR6 || Inst.getOpcode() == Mips::SWP_MMR6) + if (Inst.getOpcode() == Mips::LWP_MM || Inst.getOpcode() == Mips::SWP_MM) Inst.addOperand(MCOperand::createReg(Reg+1)); Inst.addOperand(MCOperand::createReg(Base)); diff --git a/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp b/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp index 1d125d0dbae6..73732a40bb8a 100644 --- a/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp +++ b/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp @@ -197,11 +197,6 @@ printFCCOperand(const MCInst *MI, int opNum, raw_ostream &O) { } void MipsInstPrinter:: -printRegisterPair(const MCInst *MI, int opNum, raw_ostream &O) { - printRegName(O, MI->getOperand(opNum).getReg()); -} - -void MipsInstPrinter:: printSHFMask(const MCInst *MI, int opNum, raw_ostream &O) { llvm_unreachable("TODO"); } diff --git a/lib/Target/Mips/InstPrinter/MipsInstPrinter.h b/lib/Target/Mips/InstPrinter/MipsInstPrinter.h index 4a76b5acac79..f02443ee21d3 100644 --- a/lib/Target/Mips/InstPrinter/MipsInstPrinter.h +++ b/lib/Target/Mips/InstPrinter/MipsInstPrinter.h @@ -98,7 +98,6 @@ private: 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); - void printRegisterPair(const MCInst *MI, int opNum, raw_ostream &O); void printSHFMask(const MCInst *MI, int opNum, raw_ostream &O); bool printAlias(const char *Str, const MCInst &MI, unsigned OpNo, diff --git a/lib/Target/Mips/LLVMBuild.txt b/lib/Target/Mips/LLVMBuild.txt index 06af8a10a4d2..4b6851f7af69 100644 --- a/lib/Target/Mips/LLVMBuild.txt +++ b/lib/Target/Mips/LLVMBuild.txt @@ -43,4 +43,5 @@ required_libraries = SelectionDAG Support Target + GlobalISel add_to_library_groups = Mips diff --git a/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h b/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h index 9abd4f1d6b08..68bf3829aab5 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h +++ b/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h @@ -161,6 +161,12 @@ public: ASESet |= Mips::AFL_ASE_MIPS16; if (P.hasMT()) ASESet |= Mips::AFL_ASE_MT; + if (P.hasCRC()) + ASESet |= Mips::AFL_ASE_CRC; + if (P.hasVirt()) + ASESet |= Mips::AFL_ASE_VIRT; + if (P.hasGINV()) + ASESet |= Mips::AFL_ASE_GINV; } template <class PredicateLibrary> diff --git a/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp b/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp index 498ea6fda4b3..bf1390880281 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp @@ -57,7 +57,7 @@ MipsABIInfo MipsABIInfo::computeTargetABI(const Triple &TT, StringRef CPU, return MipsABIInfo::N64(); assert(Options.getABIName().empty() && "Unknown ABI option for MIPS"); - if (TT.getArch() == Triple::mips64 || TT.getArch() == Triple::mips64el) + if (TT.isMIPS64()) return MipsABIInfo::N64(); return MipsABIInfo::O32(); } diff --git a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp index 1ad524c06969..4397c971d080 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp @@ -16,6 +16,7 @@ #include "MCTargetDesc/MipsFixupKinds.h" #include "MCTargetDesc/MipsMCExpr.h" #include "MCTargetDesc/MipsMCTargetDesc.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCContext.h" @@ -53,6 +54,8 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, case Mips::fixup_Mips_GOT_DISP: case Mips::fixup_Mips_GOT_LO16: case Mips::fixup_Mips_CALL_LO16: + case Mips::fixup_MICROMIPS_GPOFF_HI: + case Mips::fixup_MICROMIPS_GPOFF_LO: case Mips::fixup_MICROMIPS_LO16: case Mips::fixup_MICROMIPS_GOT_PAGE: case Mips::fixup_MICROMIPS_GOT_OFST: @@ -107,10 +110,12 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, Value = ((Value + 0x8000) >> 16) & 0xffff; break; case Mips::fixup_Mips_HIGHER: + case Mips::fixup_MICROMIPS_HIGHER: // Get the 3rd 16-bits. Value = ((Value + 0x80008000LL) >> 32) & 0xffff; break; case Mips::fixup_Mips_HIGHEST: + case Mips::fixup_MICROMIPS_HIGHEST: // Get the 4th 16-bits. Value = ((Value + 0x800080008000LL) >> 48) & 0xffff; break; @@ -210,9 +215,9 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value, return Value; } -std::unique_ptr<MCObjectWriter> -MipsAsmBackend::createObjectWriter(raw_pwrite_stream &OS) const { - return createMipsELFObjectWriter(OS, TheTriple, IsN32); +std::unique_ptr<MCObjectTargetWriter> +MipsAsmBackend::createObjectTargetWriter() const { + return createMipsELFObjectWriter(TheTriple, IsN32); } // Little-endian fixup data byte ordering: @@ -238,7 +243,8 @@ static unsigned calculateMMLEIndex(unsigned i) { void MipsAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef<char> Data, uint64_t Value, - bool IsResolved) const { + bool IsResolved, + const MCSubtargetInfo *STI) const { MCFixupKind Kind = Fixup.getKind(); MCContext &Ctx = Asm.getContext(); Value = adjustFixupValue(Fixup, Value, Ctx); @@ -275,9 +281,9 @@ void MipsAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, bool microMipsLEByteOrder = needsMMLEByteOrder((unsigned) Kind); for (unsigned i = 0; i != NumBytes; ++i) { - unsigned Idx = IsLittle ? (microMipsLEByteOrder ? calculateMMLEIndex(i) - : i) - : (FullSize - 1 - i); + unsigned Idx = Endian == support::little + ? (microMipsLEByteOrder ? calculateMMLEIndex(i) : i) + : (FullSize - 1 - i); CurVal |= (uint64_t)((uint8_t)Data[Offset + Idx]) << (i*8); } @@ -287,9 +293,9 @@ void MipsAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, // Write out the fixed up bytes back to the code/data bits. for (unsigned i = 0; i != NumBytes; ++i) { - unsigned Idx = IsLittle ? (microMipsLEByteOrder ? calculateMMLEIndex(i) - : i) - : (FullSize - 1 - i); + unsigned Idx = Endian == support::little + ? (microMipsLEByteOrder ? calculateMMLEIndex(i) : i) + : (FullSize - 1 - i); Data[Offset + Idx] = (uint8_t)((CurVal >> (i*8)) & 0xff); } } @@ -298,12 +304,46 @@ 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) + .Case("R_MIPS_GOT_PAGE", (MCFixupKind)Mips::fixup_Mips_GOT_PAGE) + .Case("R_MIPS_CALL_HI16", (MCFixupKind)Mips::fixup_Mips_CALL_HI16) + .Case("R_MIPS_CALL_LO16", (MCFixupKind)Mips::fixup_Mips_CALL_LO16) + .Case("R_MIPS_CALL16", (MCFixupKind)Mips::fixup_Mips_CALL16) + .Case("R_MIPS_GOT16", (MCFixupKind)Mips::fixup_Mips_GOT) + .Case("R_MIPS_GOT_PAGE", (MCFixupKind)Mips::fixup_Mips_GOT_PAGE) + .Case("R_MIPS_GOT_OFST", (MCFixupKind)Mips::fixup_Mips_GOT_OFST) + .Case("R_MIPS_GOT_DISP", (MCFixupKind)Mips::fixup_Mips_GOT_DISP) + .Case("R_MIPS_GOT_HI16", (MCFixupKind)Mips::fixup_Mips_GOT_HI16) + .Case("R_MIPS_GOT_LO16", (MCFixupKind)Mips::fixup_Mips_GOT_LO16) + .Case("R_MIPS_TLS_GOTTPREL", (MCFixupKind)Mips::fixup_Mips_GOTTPREL) + .Case("R_MIPS_TLS_DTPREL_HI16", (MCFixupKind)Mips::fixup_Mips_DTPREL_HI) + .Case("R_MIPS_TLS_DTPREL_LO16", (MCFixupKind)Mips::fixup_Mips_DTPREL_LO) + .Case("R_MIPS_TLS_GD", (MCFixupKind)Mips::fixup_Mips_TLSGD) + .Case("R_MIPS_TLS_LDM", (MCFixupKind)Mips::fixup_Mips_TLSLDM) + .Case("R_MIPS_TLS_TPREL_HI16", (MCFixupKind)Mips::fixup_Mips_TPREL_HI) + .Case("R_MIPS_TLS_TPREL_LO16", (MCFixupKind)Mips::fixup_Mips_TPREL_LO) + .Case("R_MICROMIPS_CALL16", (MCFixupKind)Mips::fixup_MICROMIPS_CALL16) + .Case("R_MICROMIPS_GOT_DISP", (MCFixupKind)Mips::fixup_MICROMIPS_GOT_DISP) + .Case("R_MICROMIPS_GOT_PAGE", (MCFixupKind)Mips::fixup_MICROMIPS_GOT_PAGE) + .Case("R_MICROMIPS_GOT_OFST", (MCFixupKind)Mips::fixup_MICROMIPS_GOT_OFST) + .Case("R_MICROMIPS_GOT16", (MCFixupKind)Mips::fixup_MICROMIPS_GOT16) + .Case("R_MICROMIPS_TLS_GOTTPREL", + (MCFixupKind)Mips::fixup_MICROMIPS_GOTTPREL) + .Case("R_MICROMIPS_TLS_DTPREL_HI16", + (MCFixupKind)Mips::fixup_MICROMIPS_TLS_DTPREL_HI16) + .Case("R_MICROMIPS_TLS_DTPREL_LO16", + (MCFixupKind)Mips::fixup_MICROMIPS_TLS_DTPREL_LO16) + .Case("R_MICROMIPS_TLS_GD", (MCFixupKind)Mips::fixup_MICROMIPS_TLS_GD) + .Case("R_MICROMIPS_TLS_LDM", (MCFixupKind)Mips::fixup_MICROMIPS_TLS_LDM) + .Case("R_MICROMIPS_TLS_TPREL_HI16", + (MCFixupKind)Mips::fixup_MICROMIPS_TLS_TPREL_HI16) + .Case("R_MICROMIPS_TLS_TPREL_LO16", + (MCFixupKind)Mips::fixup_MICROMIPS_TLS_TPREL_LO16) .Default(MCAsmBackend::getFixupKind(Name)); } const MCFixupKindInfo &MipsAsmBackend:: getFixupKindInfo(MCFixupKind Kind) const { - const static MCFixupKindInfo LittleEndianInfos[Mips::NumTargetFixupKinds] = { + const static MCFixupKindInfo LittleEndianInfos[] = { // This table *must* be in same the order of fixup_* kinds in // MipsFixupKinds.h. // @@ -333,12 +373,16 @@ getFixupKindInfo(MCFixupKind Kind) const { { "fixup_Mips_DTPREL_LO", 0, 16, 0 }, { "fixup_Mips_Branch_PCRel", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_Mips_GPOFF_HI", 0, 16, 0 }, + { "fixup_MICROMIPS_GPOFF_HI",0, 16, 0 }, { "fixup_Mips_GPOFF_LO", 0, 16, 0 }, + { "fixup_MICROMIPS_GPOFF_LO",0, 16, 0 }, { "fixup_Mips_GOT_PAGE", 0, 16, 0 }, { "fixup_Mips_GOT_OFST", 0, 16, 0 }, { "fixup_Mips_GOT_DISP", 0, 16, 0 }, { "fixup_Mips_HIGHER", 0, 16, 0 }, + { "fixup_MICROMIPS_HIGHER", 0, 16, 0 }, { "fixup_Mips_HIGHEST", 0, 16, 0 }, + { "fixup_MICROMIPS_HIGHEST", 0, 16, 0 }, { "fixup_Mips_GOT_HI16", 0, 16, 0 }, { "fixup_Mips_GOT_LO16", 0, 16, 0 }, { "fixup_Mips_CALL_HI16", 0, 16, 0 }, @@ -374,8 +418,10 @@ getFixupKindInfo(MCFixupKind Kind) const { { "fixup_Mips_SUB", 0, 64, 0 }, { "fixup_MICROMIPS_SUB", 0, 64, 0 } }; + static_assert(array_lengthof(LittleEndianInfos) == Mips::NumTargetFixupKinds, + "Not all MIPS little endian fixup kinds added!"); - const static MCFixupKindInfo BigEndianInfos[Mips::NumTargetFixupKinds] = { + const static MCFixupKindInfo BigEndianInfos[] = { // This table *must* be in same the order of fixup_* kinds in // MipsFixupKinds.h. // @@ -405,12 +451,16 @@ getFixupKindInfo(MCFixupKind Kind) const { { "fixup_Mips_DTPREL_LO", 16, 16, 0 }, { "fixup_Mips_Branch_PCRel",16, 16, MCFixupKindInfo::FKF_IsPCRel }, { "fixup_Mips_GPOFF_HI", 16, 16, 0 }, + { "fixup_MICROMIPS_GPOFF_HI", 16, 16, 0 }, { "fixup_Mips_GPOFF_LO", 16, 16, 0 }, + { "fixup_MICROMIPS_GPOFF_LO", 16, 16, 0 }, { "fixup_Mips_GOT_PAGE", 16, 16, 0 }, { "fixup_Mips_GOT_OFST", 16, 16, 0 }, { "fixup_Mips_GOT_DISP", 16, 16, 0 }, { "fixup_Mips_HIGHER", 16, 16, 0 }, + { "fixup_MICROMIPS_HIGHER", 16, 16, 0 }, { "fixup_Mips_HIGHEST", 16, 16, 0 }, + { "fixup_MICROMIPS_HIGHEST",16, 16, 0 }, { "fixup_Mips_GOT_HI16", 16, 16, 0 }, { "fixup_Mips_GOT_LO16", 16, 16, 0 }, { "fixup_Mips_CALL_HI16", 16, 16, 0 }, @@ -446,6 +496,8 @@ getFixupKindInfo(MCFixupKind Kind) const { { "fixup_Mips_SUB", 0, 64, 0 }, { "fixup_MICROMIPS_SUB", 0, 64, 0 } }; + static_assert(array_lengthof(BigEndianInfos) == Mips::NumTargetFixupKinds, + "Not all MIPS big endian fixup kinds added!"); if (Kind < FirstTargetFixupKind) return MCAsmBackend::getFixupKindInfo(Kind); @@ -453,7 +505,7 @@ getFixupKindInfo(MCFixupKind Kind) const { assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && "Invalid kind!"); - if (IsLittle) + if (Endian == support::little) return LittleEndianInfos[Kind - FirstTargetFixupKind]; return BigEndianInfos[Kind - FirstTargetFixupKind]; } @@ -463,7 +515,7 @@ getFixupKindInfo(MCFixupKind Kind) const { /// it should return an error. /// /// \return - True on success. -bool MipsAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { +bool MipsAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const { // Check for a less than instruction size number of bytes // FIXME: 16 bit instructions are not handled yet here. // We shouldn't be using a hard coded number for instruction size. @@ -471,13 +523,55 @@ bool MipsAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const { // If the count is not 4-byte aligned, we must be writing data into the text // section (otherwise we have unaligned instructions, and thus have far // bigger problems), so just write zeros instead. - OW->WriteZeros(Count); + OS.write_zeros(Count); return true; } +bool MipsAsmBackend::shouldForceRelocation(const MCAssembler &Asm, + const MCFixup &Fixup, + const MCValue &Target) { + const unsigned FixupKind = Fixup.getKind(); + switch (FixupKind) { + default: + return false; + // All these relocations require special processing + // at linking time. Delegate this work to a linker. + case Mips::fixup_Mips_CALL_HI16: + case Mips::fixup_Mips_CALL_LO16: + case Mips::fixup_Mips_CALL16: + case Mips::fixup_Mips_GOT: + case Mips::fixup_Mips_GOT_PAGE: + case Mips::fixup_Mips_GOT_OFST: + case Mips::fixup_Mips_GOT_DISP: + case Mips::fixup_Mips_GOT_HI16: + case Mips::fixup_Mips_GOT_LO16: + case Mips::fixup_Mips_GOTTPREL: + case Mips::fixup_Mips_DTPREL_HI: + case Mips::fixup_Mips_DTPREL_LO: + case Mips::fixup_Mips_TLSGD: + case Mips::fixup_Mips_TLSLDM: + case Mips::fixup_Mips_TPREL_HI: + case Mips::fixup_Mips_TPREL_LO: + case Mips::fixup_MICROMIPS_CALL16: + case Mips::fixup_MICROMIPS_GOT_DISP: + case Mips::fixup_MICROMIPS_GOT_PAGE: + case Mips::fixup_MICROMIPS_GOT_OFST: + case Mips::fixup_MICROMIPS_GOT16: + case Mips::fixup_MICROMIPS_GOTTPREL: + case Mips::fixup_MICROMIPS_TLS_DTPREL_HI16: + case Mips::fixup_MICROMIPS_TLS_DTPREL_LO16: + case Mips::fixup_MICROMIPS_TLS_GD: + case Mips::fixup_MICROMIPS_TLS_LDM: + case Mips::fixup_MICROMIPS_TLS_TPREL_HI16: + case Mips::fixup_MICROMIPS_TLS_TPREL_LO16: + return true; + } +} + MCAsmBackend *llvm::createMipsAsmBackend(const Target &T, + const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, - const Triple &TT, StringRef CPU, const MCTargetOptions &Options) { - return new MipsAsmBackend(T, MRI, TT, CPU, Options.ABIName == "n32"); + return new MipsAsmBackend(T, MRI, STI.getTargetTriple(), STI.getCPU(), + Options.ABIName == "n32"); } diff --git a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h index 406b820edae5..3d5e16fcf9b4 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h +++ b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h @@ -29,20 +29,21 @@ class Target; class MipsAsmBackend : public MCAsmBackend { Triple TheTriple; - bool IsLittle; // Big or little endian bool IsN32; public: MipsAsmBackend(const Target &T, const MCRegisterInfo &MRI, const Triple &TT, StringRef CPU, bool N32) - : TheTriple(TT), IsLittle(TT.isLittleEndian()), IsN32(N32) {} + : MCAsmBackend(TT.isLittleEndian() ? support::little : support::big), + TheTriple(TT), IsN32(N32) {} - std::unique_ptr<MCObjectWriter> - createObjectWriter(raw_pwrite_stream &OS) const override; + std::unique_ptr<MCObjectTargetWriter> + createObjectTargetWriter() const override; void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef<char> Data, - uint64_t Value, bool IsResolved) const override; + uint64_t Value, bool IsResolved, + const MCSubtargetInfo *STI) const override; Optional<MCFixupKind> getFixupKind(StringRef Name) const override; const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override; @@ -58,7 +59,8 @@ public: /// relaxation. /// /// \param Inst - The instruction to test. - bool mayNeedRelaxation(const MCInst &Inst) const override { + bool mayNeedRelaxation(const MCInst &Inst, + const MCSubtargetInfo &STI) const override { return false; } @@ -83,7 +85,10 @@ public: /// @} - bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override; + bool writeNopData(raw_ostream &OS, uint64_t Count) const override; + + bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup, + const MCValue &Target) override; }; // class MipsAsmBackend diff --git a/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp b/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp index 6d2f098a6b32..3dc753772e5f 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp @@ -56,8 +56,7 @@ raw_ostream &operator<<(raw_ostream &OS, const MipsRelocationEntry &RHS) { class MipsELFObjectWriter : public MCELFObjectTargetWriter { public: - MipsELFObjectWriter(uint8_t OSABI, bool HasRelocationAddend, bool Is64, - bool IsLittleEndian); + MipsELFObjectWriter(uint8_t OSABI, bool HasRelocationAddend, bool Is64); ~MipsELFObjectWriter() override = default; @@ -116,15 +115,15 @@ static InputIt find_best(InputIt First, InputIt Last, UnaryPredicate Predicate, 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"); + LLVM_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"); + LLVM_DEBUG(dbgs() << ".. and it beats the last one\n"); Best = I; } } if (Matched == FindBest_PerfectMatch) { - DEBUG(dbgs() << ".. and it is unbeatable\n"); + LLVM_DEBUG(dbgs() << ".. and it is unbeatable\n"); break; } } @@ -148,7 +147,8 @@ static unsigned getMatchingLoType(const ELFRelocationEntry &Reloc) { if (Type == ELF::R_MIPS16_HI16) return ELF::R_MIPS16_LO16; - if (Reloc.OriginalSymbol->getBinding() != ELF::STB_LOCAL) + if (Reloc.OriginalSymbol && + Reloc.OriginalSymbol->getBinding() != ELF::STB_LOCAL) return ELF::R_MIPS_NONE; if (Type == ELF::R_MIPS_GOT16) @@ -211,8 +211,7 @@ static void dumpRelocs(const char *Prefix, const Container &Relocs) { #endif MipsELFObjectWriter::MipsELFObjectWriter(uint8_t OSABI, - bool HasRelocationAddend, bool Is64, - bool IsLittleEndian) + bool HasRelocationAddend, bool Is64) : MCELFObjectTargetWriter(Is64, OSABI, ELF::EM_MIPS, HasRelocationAddend) {} unsigned MipsELFObjectWriter::getRelocType(MCContext &Ctx, @@ -225,6 +224,8 @@ unsigned MipsELFObjectWriter::getRelocType(MCContext &Ctx, switch (Kind) { case Mips::fixup_Mips_NONE: return ELF::R_MIPS_NONE; + case FK_Data_1: + report_fatal_error("MIPS does not support one byte relocations"); case Mips::fixup_Mips_16: case FK_Data_2: return IsPCRel ? ELF::R_MIPS_PC16 : ELF::R_MIPS_16; @@ -329,6 +330,13 @@ unsigned MipsELFObjectWriter::getRelocType(MCContext &Ctx, Type = setRType3((unsigned)ELF::R_MIPS_HI16, Type); return Type; } + case Mips::fixup_MICROMIPS_GPOFF_HI: { + unsigned Type = (unsigned)ELF::R_MIPS_NONE; + Type = setRType((unsigned)ELF::R_MICROMIPS_GPREL16, Type); + Type = setRType2((unsigned)ELF::R_MICROMIPS_SUB, Type); + Type = setRType3((unsigned)ELF::R_MICROMIPS_HI16, Type); + return Type; + } case Mips::fixup_Mips_GPOFF_LO: { unsigned Type = (unsigned)ELF::R_MIPS_NONE; Type = setRType((unsigned)ELF::R_MIPS_GPREL16, Type); @@ -336,6 +344,13 @@ unsigned MipsELFObjectWriter::getRelocType(MCContext &Ctx, Type = setRType3((unsigned)ELF::R_MIPS_LO16, Type); return Type; } + case Mips::fixup_MICROMIPS_GPOFF_LO: { + unsigned Type = (unsigned)ELF::R_MIPS_NONE; + Type = setRType((unsigned)ELF::R_MICROMIPS_GPREL16, Type); + Type = setRType2((unsigned)ELF::R_MICROMIPS_SUB, Type); + Type = setRType3((unsigned)ELF::R_MICROMIPS_LO16, Type); + return Type; + } case Mips::fixup_Mips_HIGHER: return ELF::R_MIPS_HIGHER; case Mips::fixup_Mips_HIGHEST: @@ -382,6 +397,10 @@ unsigned MipsELFObjectWriter::getRelocType(MCContext &Ctx, return ELF::R_MICROMIPS_TLS_TPREL_LO16; case Mips::fixup_MICROMIPS_SUB: return ELF::R_MICROMIPS_SUB; + case Mips::fixup_MICROMIPS_HIGHER: + return ELF::R_MICROMIPS_HIGHER; + case Mips::fixup_MICROMIPS_HIGHEST: + return ELF::R_MICROMIPS_HIGHEST; } llvm_unreachable("invalid fixup kind!"); @@ -434,15 +453,15 @@ void MipsELFObjectWriter::sortRelocs(const MCAssembler &Asm, return; // 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; - }); + llvm::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)); + LLVM_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 @@ -453,7 +472,7 @@ void MipsELFObjectWriter::sortRelocs(const MCAssembler &Asm, }); for (auto &R : Remainder) { - DEBUG(dbgs() << "Matching: " << R << "\n"); + LLVM_DEBUG(dbgs() << "Matching: " << R << "\n"); unsigned MatchingType = getMatchingLoType(R); assert(MatchingType != ELF::R_MIPS_NONE && @@ -488,7 +507,7 @@ void MipsELFObjectWriter::sortRelocs(const MCAssembler &Asm, Sorted.insert(InsertionPoint, R)->Matched = true; } - DEBUG(dumpRelocs("S: ", Sorted)); + LLVM_DEBUG(dumpRelocs("S: ", Sorted)); assert(Relocs.size() == Sorted.size() && "Some relocs were not consumed"); @@ -656,13 +675,11 @@ bool MipsELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym, } } -std::unique_ptr<MCObjectWriter> -llvm::createMipsELFObjectWriter(raw_pwrite_stream &OS, const Triple &TT, - bool IsN32) { +std::unique_ptr<MCObjectTargetWriter> +llvm::createMipsELFObjectWriter(const Triple &TT, bool IsN32) { uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS()); bool IsN64 = TT.isArch64Bit() && !IsN32; bool HasRelocationAddend = TT.isArch64Bit(); - auto MOTW = llvm::make_unique<MipsELFObjectWriter>( - OSABI, HasRelocationAddend, IsN64, TT.isLittleEndian()); - return createELFObjectWriter(std::move(MOTW), OS, TT.isLittleEndian()); + return llvm::make_unique<MipsELFObjectWriter>(OSABI, HasRelocationAddend, + IsN64); } diff --git a/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp b/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp index 4b8f9c7a680c..7b9a02503ce2 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp @@ -16,6 +16,7 @@ #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSymbolELF.h" #include "llvm/Support/Casting.h" @@ -23,9 +24,10 @@ using namespace llvm; MipsELFStreamer::MipsELFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> MAB, - raw_pwrite_stream &OS, + std::unique_ptr<MCObjectWriter> OW, std::unique_ptr<MCCodeEmitter> Emitter) - : MCELFStreamer(Context, std::move(MAB), OS, std::move(Emitter)) { + : MCELFStreamer(Context, std::move(MAB), std::move(OW), + std::move(Emitter)) { RegInfoRecord = new MipsRegInfoRecord(this, Context); MipsOptionRecords.push_back( std::unique_ptr<MipsRegInfoRecord>(RegInfoRecord)); @@ -84,6 +86,11 @@ void MipsELFStreamer::EmitValueImpl(const MCExpr *Value, unsigned Size, Labels.clear(); } +void MipsELFStreamer::EmitIntValue(uint64_t Value, unsigned Size) { + MCELFStreamer::EmitIntValue(Value, Size); + Labels.clear(); +} + void MipsELFStreamer::EmitMipsOptionRecords() { for (const auto &I : MipsOptionRecords) I->EmitMipsOptionRecord(); @@ -91,7 +98,8 @@ void MipsELFStreamer::EmitMipsOptionRecords() { MCELFStreamer *llvm::createMipsELFStreamer( MCContext &Context, std::unique_ptr<MCAsmBackend> MAB, - raw_pwrite_stream &OS, std::unique_ptr<MCCodeEmitter> Emitter, + std::unique_ptr<MCObjectWriter> OW, std::unique_ptr<MCCodeEmitter> Emitter, bool RelaxAll) { - return new MipsELFStreamer(Context, std::move(MAB), OS, std::move(Emitter)); + return new MipsELFStreamer(Context, std::move(MAB), std::move(OW), + std::move(Emitter)); } diff --git a/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h b/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h index 2fe9b08b645a..d141f5d77c61 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h +++ b/lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h @@ -34,7 +34,7 @@ class MipsELFStreamer : public MCELFStreamer { public: MipsELFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> MAB, - raw_pwrite_stream &OS, + std::unique_ptr<MCObjectWriter> OW, std::unique_ptr<MCCodeEmitter> Emitter); /// Overriding this function allows us to add arbitrary behaviour before the @@ -54,9 +54,11 @@ public: void SwitchSection(MCSection *Section, const MCExpr *Subsection = nullptr) override; - /// Overriding this function allows us to dismiss all labels that are - /// candidates for marking as microMIPS when .word directive is emitted. + /// Overriding these functions allows us to dismiss all labels that are + /// candidates for marking as microMIPS when .word/.long/.4byte etc + /// directives are emitted. void EmitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) override; + void EmitIntValue(uint64_t Value, unsigned Size) override; /// Emits all the option records stored up until the point it's called. void EmitMipsOptionRecords(); @@ -67,7 +69,7 @@ public: MCELFStreamer *createMipsELFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> MAB, - raw_pwrite_stream &OS, + std::unique_ptr<MCObjectWriter> OW, std::unique_ptr<MCCodeEmitter> Emitter, bool RelaxAll); } // end namespace llvm diff --git a/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h b/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h index 6148a1b622c8..fdb560f3c72f 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h +++ b/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h @@ -96,10 +96,14 @@ namespace Mips { fixup_Mips_Branch_PCRel, // resulting in - R_MIPS_GPREL16/R_MIPS_SUB/R_MIPS_HI16 + // R_MICROMIPS_GPREL16/R_MICROMIPS_SUB/R_MICROMIPS_HI16 fixup_Mips_GPOFF_HI, + fixup_MICROMIPS_GPOFF_HI, // resulting in - R_MIPS_GPREL16/R_MIPS_SUB/R_MIPS_LO16 + // R_MICROMIPS_GPREL16/R_MICROMIPS_SUB/R_MICROMIPS_LO16 fixup_Mips_GPOFF_LO, + fixup_MICROMIPS_GPOFF_LO, // resulting in - R_MIPS_PAGE fixup_Mips_GOT_PAGE, @@ -110,11 +114,13 @@ namespace Mips { // resulting in - R_MIPS_GOT_DISP fixup_Mips_GOT_DISP, - // resulting in - R_MIPS_GOT_HIGHER + // resulting in - R_MIPS_HIGHER/R_MICROMIPS_HIGHER fixup_Mips_HIGHER, + fixup_MICROMIPS_HIGHER, - // resulting in - R_MIPS_HIGHEST + // resulting in - R_MIPS_HIGHEST/R_MICROMIPS_HIGHEST fixup_Mips_HIGHEST, + fixup_MICROMIPS_HIGHEST, // resulting in - R_MIPS_GOT_HI16 fixup_Mips_GOT_HI16, diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp index e63304220ae5..f498d830c8f0 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp @@ -21,16 +21,14 @@ void MipsMCAsmInfo::anchor() { } MipsMCAsmInfo::MipsMCAsmInfo(const Triple &TheTriple) { IsLittleEndian = TheTriple.isLittleEndian(); - if ((TheTriple.getArch() == Triple::mips64el) || - (TheTriple.getArch() == Triple::mips64)) { + if (TheTriple.isMIPS64()) { CodePointerSize = CalleeSaveStackSlotSize = 8; } // FIXME: This condition isn't quite right but it's the best we can do until // this object can identify the ABI. It will misbehave when using O32 // on a mips64*-* triple. - if ((TheTriple.getArch() == Triple::mipsel) || - (TheTriple.getArch() == Triple::mips)) { + if (TheTriple.isMIPS32()) { PrivateGlobalPrefix = "$"; PrivateLabelPrefix = "$"; } @@ -54,8 +52,7 @@ MipsMCAsmInfo::MipsMCAsmInfo(const Triple &TheTriple) { HasMipsExpressions = true; // Enable IAS by default for O32. - if (TheTriple.getArch() == Triple::mips || - TheTriple.getArch() == Triple::mipsel) + if (TheTriple.isMIPS32()) UseIntegratedAssembler = true; // Enable IAS by default for Debian mips64/mips64el. @@ -65,4 +62,9 @@ MipsMCAsmInfo::MipsMCAsmInfo(const Triple &TheTriple) { // Enable IAS by default for Android mips64el that uses N64 ABI. if (TheTriple.getArch() == Triple::mips64el && TheTriple.isAndroid()) UseIntegratedAssembler = true; + + // Enable IAS by default for FreeBSD / OpenBSD mips64/mips64el. + if (TheTriple.isOSFreeBSD() || + TheTriple.isOSOpenBSD()) + UseIntegratedAssembler = true; } diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp index 2f6dd0035de3..cd34b0ab70b4 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -656,27 +656,29 @@ getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups, break; 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; + if (MipsExpr->isGpOff()) + FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GPOFF_LO + : Mips::fixup_Mips_GPOFF_LO; + else + FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16 + : Mips::fixup_Mips_LO16; break; case MipsMCExpr::MEK_HIGHEST: - FixupKind = Mips::fixup_Mips_HIGHEST; + FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HIGHEST + : Mips::fixup_Mips_HIGHEST; break; case MipsMCExpr::MEK_HIGHER: - FixupKind = Mips::fixup_Mips_HIGHER; + FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HIGHER + : Mips::fixup_Mips_HIGHER; break; 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; + if (MipsExpr->isGpOff()) + FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GPOFF_HI + : Mips::fixup_Mips_GPOFF_HI; + else + FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HI16 + : Mips::fixup_Mips_HI16; break; case MipsMCExpr::MEK_PCREL_HI16: FixupKind = Mips::fixup_MIPS_PCHI16; @@ -1058,13 +1060,6 @@ MipsMCCodeEmitter::getRegisterListOpValue16(const MCInst &MI, unsigned OpNo, } unsigned -MipsMCCodeEmitter::getRegisterPairOpValue(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const { - return getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI); -} - -unsigned MipsMCCodeEmitter::getMovePRegPairOpValue(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const { diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h index 1e840114b2b3..09d50d4776ba 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h +++ b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h @@ -245,10 +245,6 @@ public: SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; - unsigned getRegisterPairOpValue(const MCInst &MI, unsigned OpNo, - SmallVectorImpl<MCFixup> &Fixups, - const MCSubtargetInfo &STI) const; - unsigned getMovePRegPairOpValue(const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups, const MCSubtargetInfo &STI) const; diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h b/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h index dfacf4354516..988629ed1bca 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h +++ b/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h @@ -24,7 +24,7 @@ bool baseRegNeedsLoadStoreMask(unsigned Reg); // This function creates an MCELFStreamer for Mips NaCl. MCELFStreamer *createMipsNaClELFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB, - raw_pwrite_stream &OS, + std::unique_ptr<MCObjectWriter> OW, std::unique_ptr<MCCodeEmitter> Emitter, bool RelaxAll); } diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp index 8fcd8aa4c19b..ce208b7f98bc 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp @@ -23,6 +23,7 @@ #include "llvm/MC/MCELFStreamer.h" #include "llvm/MC/MCInstrAnalysis.h" #include "llvm/MC/MCInstrInfo.h" +#include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbol.h" @@ -46,7 +47,7 @@ using namespace llvm; /// FIXME: Merge with the copy in MipsSubtarget.cpp StringRef MIPS_MC::selectMipsCPU(const Triple &TT, StringRef CPU) { if (CPU.empty() || CPU == "generic") { - if (TT.getArch() == Triple::mips || TT.getArch() == Triple::mipsel) + if (TT.isMIPS32()) CPU = "mips32"; else CPU = "mips64"; @@ -93,15 +94,15 @@ static MCInstPrinter *createMipsMCInstPrinter(const Triple &T, static MCStreamer *createMCStreamer(const Triple &T, MCContext &Context, std::unique_ptr<MCAsmBackend> &&MAB, - raw_pwrite_stream &OS, + std::unique_ptr<MCObjectWriter> &&OW, std::unique_ptr<MCCodeEmitter> &&Emitter, bool RelaxAll) { MCStreamer *S; if (!T.isOSNaCl()) - S = createMipsELFStreamer(Context, std::move(MAB), OS, std::move(Emitter), - RelaxAll); + S = createMipsELFStreamer(Context, std::move(MAB), std::move(OW), + std::move(Emitter), RelaxAll); else - S = createMipsNaClELFStreamer(Context, std::move(MAB), OS, + S = createMipsNaClELFStreamer(Context, std::move(MAB), std::move(OW), std::move(Emitter), RelaxAll); return S; } diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h index abbf08ed212f..4fc174ab5871 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h +++ b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h @@ -23,7 +23,7 @@ class MCAsmBackend; class MCCodeEmitter; class MCContext; class MCInstrInfo; -class MCObjectWriter; +class MCObjectTargetWriter; class MCRegisterInfo; class MCSubtargetInfo; class MCTargetOptions; @@ -45,12 +45,12 @@ MCCodeEmitter *createMipsMCCodeEmitterEL(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, MCContext &Ctx); -MCAsmBackend *createMipsAsmBackend(const Target &T, const MCRegisterInfo &MRI, - const Triple &TT, StringRef CPU, +MCAsmBackend *createMipsAsmBackend(const Target &T, const MCSubtargetInfo &STI, + const MCRegisterInfo &MRI, const MCTargetOptions &Options); -std::unique_ptr<MCObjectWriter> -createMipsELFObjectWriter(raw_pwrite_stream &OS, const Triple &TT, bool IsN32); +std::unique_ptr<MCObjectTargetWriter> +createMipsELFObjectWriter(const Triple &TT, bool IsN32); namespace MIPS_MC { StringRef selectMipsCPU(const Triple &TT, StringRef CPU); diff --git a/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp b/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp index d878cf82e26d..6bf62ea618b4 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp @@ -25,6 +25,7 @@ #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCELFStreamer.h" #include "llvm/MC/MCInst.h" +#include "llvm/MC/MCObjectWriter.h" #include "llvm/Support/ErrorHandling.h" #include <cassert> @@ -43,9 +44,10 @@ const unsigned LoadStoreStackMaskReg = Mips::T7; class MipsNaClELFStreamer : public MipsELFStreamer { public: MipsNaClELFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB, - raw_pwrite_stream &OS, + std::unique_ptr<MCObjectWriter> OW, std::unique_ptr<MCCodeEmitter> Emitter) - : MipsELFStreamer(Context, std::move(TAB), OS, std::move(Emitter)) {} + : MipsELFStreamer(Context, std::move(TAB), std::move(OW), + std::move(Emitter)) {} ~MipsNaClELFStreamer() override = default; @@ -260,11 +262,11 @@ bool baseRegNeedsLoadStoreMask(unsigned Reg) { MCELFStreamer *createMipsNaClELFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> TAB, - raw_pwrite_stream &OS, + std::unique_ptr<MCObjectWriter> OW, std::unique_ptr<MCCodeEmitter> Emitter, bool RelaxAll) { - MipsNaClELFStreamer *S = - new MipsNaClELFStreamer(Context, std::move(TAB), OS, std::move(Emitter)); + MipsNaClELFStreamer *S = new MipsNaClELFStreamer( + Context, std::move(TAB), std::move(OW), std::move(Emitter)); if (RelaxAll) S->getAssembler().setRelaxAll(true); diff --git a/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp b/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp index fb4e1ba0ded9..1eb21b6cc826 100644 --- a/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp +++ b/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp @@ -52,6 +52,12 @@ void MipsTargetStreamer::emitDirectiveSetMsa() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetNoMsa() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetMt() {} void MipsTargetStreamer::emitDirectiveSetNoMt() { forbidModuleDirective(); } +void MipsTargetStreamer::emitDirectiveSetCRC() {} +void MipsTargetStreamer::emitDirectiveSetNoCRC() {} +void MipsTargetStreamer::emitDirectiveSetVirt() {} +void MipsTargetStreamer::emitDirectiveSetNoVirt() {} +void MipsTargetStreamer::emitDirectiveSetGINV() {} +void MipsTargetStreamer::emitDirectiveSetNoGINV() {} void MipsTargetStreamer::emitDirectiveSetAt() { forbidModuleDirective(); } void MipsTargetStreamer::emitDirectiveSetAtWithArg(unsigned RegNo) { forbidModuleDirective(); @@ -122,6 +128,12 @@ void MipsTargetStreamer::emitDirectiveModuleOddSPReg() { void MipsTargetStreamer::emitDirectiveModuleSoftFloat() {} void MipsTargetStreamer::emitDirectiveModuleHardFloat() {} void MipsTargetStreamer::emitDirectiveModuleMT() {} +void MipsTargetStreamer::emitDirectiveModuleCRC() {} +void MipsTargetStreamer::emitDirectiveModuleNoCRC() {} +void MipsTargetStreamer::emitDirectiveModuleVirt() {} +void MipsTargetStreamer::emitDirectiveModuleNoVirt() {} +void MipsTargetStreamer::emitDirectiveModuleGINV() {} +void MipsTargetStreamer::emitDirectiveModuleNoGINV() {} void MipsTargetStreamer::emitDirectiveSetFp( MipsABIFlagsSection::FpABIKind Value) { forbidModuleDirective(); @@ -421,6 +433,36 @@ void MipsTargetAsmStreamer::emitDirectiveSetNoMt() { MipsTargetStreamer::emitDirectiveSetNoMt(); } +void MipsTargetAsmStreamer::emitDirectiveSetCRC() { + OS << "\t.set\tcrc\n"; + MipsTargetStreamer::emitDirectiveSetCRC(); +} + +void MipsTargetAsmStreamer::emitDirectiveSetNoCRC() { + OS << "\t.set\tnocrc\n"; + MipsTargetStreamer::emitDirectiveSetNoCRC(); +} + +void MipsTargetAsmStreamer::emitDirectiveSetVirt() { + OS << "\t.set\tvirt\n"; + MipsTargetStreamer::emitDirectiveSetVirt(); +} + +void MipsTargetAsmStreamer::emitDirectiveSetNoVirt() { + OS << "\t.set\tnovirt\n"; + MipsTargetStreamer::emitDirectiveSetNoVirt(); +} + +void MipsTargetAsmStreamer::emitDirectiveSetGINV() { + OS << "\t.set\tginv\n"; + MipsTargetStreamer::emitDirectiveSetGINV(); +} + +void MipsTargetAsmStreamer::emitDirectiveSetNoGINV() { + OS << "\t.set\tnoginv\n"; + MipsTargetStreamer::emitDirectiveSetNoGINV(); +} + void MipsTargetAsmStreamer::emitDirectiveSetAt() { OS << "\t.set\tat\n"; MipsTargetStreamer::emitDirectiveSetAt(); @@ -694,6 +736,30 @@ void MipsTargetAsmStreamer::emitDirectiveModuleMT() { OS << "\t.module\tmt\n"; } +void MipsTargetAsmStreamer::emitDirectiveModuleCRC() { + OS << "\t.module\tcrc\n"; +} + +void MipsTargetAsmStreamer::emitDirectiveModuleNoCRC() { + OS << "\t.module\tnocrc\n"; +} + +void MipsTargetAsmStreamer::emitDirectiveModuleVirt() { + OS << "\t.module\tvirt\n"; +} + +void MipsTargetAsmStreamer::emitDirectiveModuleNoVirt() { + OS << "\t.module\tnovirt\n"; +} + +void MipsTargetAsmStreamer::emitDirectiveModuleGINV() { + OS << "\t.module\tginv\n"; +} + +void MipsTargetAsmStreamer::emitDirectiveModuleNoGINV() { + OS << "\t.module\tnoginv\n"; +} + // This part is for ELF object output. MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI) diff --git a/lib/Target/Mips/MicroMips32r6InstrFormats.td b/lib/Target/Mips/MicroMips32r6InstrFormats.td index 25048293714d..ed5b8dd71a51 100644 --- a/lib/Target/Mips/MicroMips32r6InstrFormats.td +++ b/lib/Target/Mips/MicroMips32r6InstrFormats.td @@ -17,12 +17,6 @@ class MMR6Arch<string opstr> { string DecoderNamespace = "MicroMipsR6"; } -// Class used for microMIPS32r6 instructions. -class MicroMipsR6Inst16 : PredicateControl { - string DecoderNamespace = "MicroMipsR6"; - let InsnPredicates = [HasMicroMips32r6]; -} - //===----------------------------------------------------------------------===// // // Disambiguators @@ -50,7 +44,7 @@ class BC16_FM_MM16R6 { let Inst{9-0} = offset; } -class BEQZC_BNEZC_FM_MM16R6<bits<6> op> : MicroMipsR6Inst16 { +class BEQZC_BNEZC_FM_MM16R6<bits<6> op> { bits<3> rs; bits<7> offset; @@ -174,22 +168,6 @@ class ADDI_FM_MMR6<string instr_asm, bits<6> op> : MMR6Arch<instr_asm> { let Inst{15-0} = imm16; } -class POOL32C_ST_EVA_FM_MMR6<bits<6> op, bits<3> funct> : MipsR6Inst { - bits<21> addr; - bits<5> hint; - bits<5> base = addr{20-16}; - bits<9> offset = addr{8-0}; - - bits<32> Inst; - - let Inst{31-26} = op; - let Inst{25-21} = hint; - let Inst{20-16} = base; - let Inst{15-12} = 0b1010; - let Inst{11-9} = funct; - let Inst{8-0} = offset; -} - class LB32_FM_MMR6 : MipsR6Inst { bits<21> addr; bits<5> rt; @@ -218,34 +196,6 @@ class LBU32_FM_MMR6 : MipsR6Inst { let Inst{15-0} = offset; } -class POOL32C_LB_LBU_FM_MMR6<bits<3> funct> : MipsR6Inst { - bits<21> addr; - bits<5> rt; - - bits<32> Inst; - - let Inst{31-26} = 0b011000; - let Inst{25-21} = rt; - let Inst{20-16} = addr{20-16}; - let Inst{15-12} = 0b0110; - let Inst{11-9} = funct; - let Inst{8-0} = addr{8-0}; -} - -class SIGN_EXTEND_FM_MMR6<string instr_asm, bits<10> funct> - : MMR6Arch<instr_asm> { - bits<5> rd; - bits<5> rt; - - bits<32> Inst; - - let Inst{31-26} = 0b000000; - let Inst{25-21} = rd; - let Inst{20-16} = rt; - let Inst{15-6} = funct; - let Inst{5-0} = 0b111100; -} - class PCREL19_FM_MMR6<bits<2> funct> : MipsR6Inst { bits<5> rt; bits<19> imm; @@ -436,38 +386,6 @@ class SB32_SH32_STORE_FM_MMR6<bits<6> op> { let Inst{15-0} = offset; } -class POOL32C_STORE_EVA_FM_MMR6<bits<3> funct> { - bits<5> rt; - bits<21> addr; - bits<5> base = addr{20-16}; - bits<9> offset = addr{8-0}; - - bits<32> Inst; - - let Inst{31-26} = 0b011000; - let Inst{25-21} = rt; - let Inst{20-16} = base; - let Inst{15-12} = 0b1010; - let Inst{11-9} = funct; - let Inst{8-0} = offset; -} - -class LOAD_WORD_EVA_FM_MMR6<bits<3> funct> { - bits<5> rt; - bits<21> addr; - bits<5> base = addr{20-16}; - bits<9> offset = addr{8-0}; - - bits<32> Inst; - - let Inst{31-26} = 0b011000; - let Inst{25-21} = rt; - let Inst{20-16} = base; - let Inst{15-12} = 0b0110; - let Inst{11-9} = funct; - let Inst{8-0} = offset; -} - class LOAD_WORD_FM_MMR6 { bits<5> rt; bits<21> addr; @@ -631,23 +549,6 @@ class SW32_FM_MMR6<string instr_asm, bits<6> op> : MMR6Arch<instr_asm> { let Inst{15-0} = addr{15-0}; } -class POOL32C_SWE_FM_MMR6<string instr_asm, bits<6> op, bits<4> fmt, - bits<3> funct> : MMR6Arch<instr_asm> { - bits<5> rt; - bits<21> addr; - bits<5> base = addr{20-16}; - bits<9> offset = addr{8-0}; - - bits<32> Inst; - - let Inst{31-26} = op; - let Inst{25-21} = rt; - let Inst{20-16} = base; - let Inst{15-12} = fmt; - let Inst{11-9} = funct; - let Inst{8-0} = offset; -} - class POOL32F_ARITH_FM_MMR6<string instr_asm, bits<2> fmt, bits<8> funct> : MMR6Arch<instr_asm>, MipsR6Inst { bits<5> ft; @@ -791,7 +692,7 @@ class POOL32F_MATH_FM_MMR6<string instr_asm, bits<1> fmt, bits<8> funct> let Inst{5-0} = 0b111011; } -class POOL16A_ADDU16_FM_MMR6 : MicroMipsR6Inst16 { +class POOL16A_ADDU16_FM_MMR6 { bits<3> rs; bits<3> rt; bits<3> rd; @@ -805,7 +706,7 @@ class POOL16A_ADDU16_FM_MMR6 : MicroMipsR6Inst16 { let Inst{0} = 0; } -class POOL16C_AND16_FM_MMR6 : MicroMipsR6Inst16 { +class POOL16C_AND16_FM_MMR6 { bits<3> rt; bits<3> rs; @@ -817,7 +718,7 @@ class POOL16C_AND16_FM_MMR6 : MicroMipsR6Inst16 { let Inst{3-0} = 0b0001; } -class POOL16C_NOT16_FM_MMR6 : MicroMipsR6Inst16 { +class POOL16C_NOT16_FM_MMR6 { bits<3> rt; bits<3> rs; @@ -829,7 +730,7 @@ class POOL16C_NOT16_FM_MMR6 : MicroMipsR6Inst16 { let Inst{3-0} = 0b0000; } -class POOL16C_MOVEP16_FM_MMR6 : MicroMipsR6Inst16 { +class POOL16C_MOVEP16_FM_MMR6 { bits<3> dst_regs; bits<3> rt; bits<3> rs; @@ -844,7 +745,7 @@ class POOL16C_MOVEP16_FM_MMR6 : MicroMipsR6Inst16 { let Inst{1-0} = rs{1-0}; } -class POOL16C_OR16_XOR16_FM_MMR6<bits<4> op> : MicroMipsR6Inst16 { +class POOL16C_OR16_XOR16_FM_MMR6<bits<4> op> { bits<3> rt; bits<3> rs; @@ -879,7 +780,8 @@ class POOL16A_SUBU16_FM_MMR6 { let Inst{0} = 0b1; } -class POOL32A_WRPGPR_WSBH_FM_MMR6<bits<10> funct> : MipsR6Inst { +class POOL32A_WRPGPR_WSBH_FM_MMR6<string instr_asm, bits<10> funct> + : MMR6Arch<instr_asm>, MipsR6Inst { bits<5> rt; bits<5> rs; @@ -981,6 +883,23 @@ class POOL32A_MFTC0_FM_MMR6<string instr_asm, bits<5> funct, bits<6> opcode> let Inst{5-0} = opcode; } +class POOL32A_GINV_FM_MMR6<string instr_asm, bits<2> ginv> + : MMR6Arch<instr_asm>, MipsR6Inst { + bits<5> rs; + bits<2> type; + + bits<32> Inst; + + let Inst{31-26} = 0x0; + let Inst{25-21} = 0x0; + let Inst{20-16} = rs; + let Inst{15-13} = 0b011; + let Inst{12-11} = ginv; + let Inst{10-9} = type; + let Inst{8-6} = 0b101; + let Inst{5-0} = 0b111100; +} + class POOL32F_MFTC1_FM_MMR6<string instr_asm, bits<8> funct> : MMR6Arch<instr_asm> { bits<5> rt; @@ -1037,21 +956,6 @@ class POOL32A_DVPEVP_FM_MMR6<string instr_asm, bits<10> 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; @@ -1107,3 +1011,21 @@ class POOL32B_LDWC2_SDWC2_FM_MMR6<string instr_asm, bits<4> funct> let Inst{11} = 0; let Inst{10-0} = offset; } + +class POOL32C_LL_E_SC_E_FM_MMR6<string instr_asm, bits<4> majorFunc, + bits<3> minorFunc> + : MMR6Arch<instr_asm>, MipsR6Inst { + bits<5> rt; + bits<21> addr; + bits<5> base = addr{20-16}; + bits<9> offset = addr{8-0}; + + bits<32> Inst; + + let Inst{31-26} = 0b011000; + let Inst{25-21} = rt; + let Inst{20-16} = base; + let Inst{15-12} = majorFunc; + let Inst{11-9} = minorFunc; + let Inst{8-0} = offset; +} diff --git a/lib/Target/Mips/MicroMips32r6InstrInfo.td b/lib/Target/Mips/MicroMips32r6InstrInfo.td index 3ff3f07654d9..f795112ae2b7 100644 --- a/lib/Target/Mips/MicroMips32r6InstrInfo.td +++ b/lib/Target/Mips/MicroMips32r6InstrInfo.td @@ -106,20 +106,20 @@ class DI_MMR6_ENC : POOL32A_EIDI_MMR6_ENC<"di", 0b0100011101>; class ERET_MMR6_ENC : POOL32A_ERET_FM_MMR6<"eret", 0x3cd>; class DERET_MMR6_ENC : POOL32A_ERET_FM_MMR6<"eret", 0b1110001101>; class ERETNC_MMR6_ENC : ERETNC_FM_MMR6<"eretnc">; +class GINVI_MMR6_ENC : POOL32A_GINV_FM_MMR6<"ginvi", 0b00>; +class GINVT_MMR6_ENC : POOL32A_GINV_FM_MMR6<"ginvt", 0b10>; class JALRC16_MMR6_ENC : POOL16C_JALRC_FM_MM16R6<0xb>; class JIALC_MMR6_ENC : JMP_IDX_COMPACT_FM<0b100000>; 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>; @@ -131,15 +131,12 @@ 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>; class PREF_MMR6_ENC : CACHE_PREF_FM_MMR6<0b011000, 0b0010>; class SB16_MMR6_ENC : LOAD_STORE_FM_MM16<0x22>; -class SEB_MMR6_ENC : SIGN_EXTEND_FM_MMR6<"seb", 0b0010101100>; -class SEH_MMR6_ENC : SIGN_EXTEND_FM_MMR6<"seh", 0b0011101100>; class SELEQZ_MMR6_ENC : POOL32A_FM_MMR6<0b0101000000>; class SELNEZ_MMR6_ENC : POOL32A_FM_MMR6<0b0110000000>; class SH16_MMR6_ENC : LOAD_STORE_FM_MM16<0x2a>; @@ -147,19 +144,13 @@ class SLL_MMR6_ENC : SHIFT_MMR6_ENC<"sll", 0x00, 0b0>; class SUB_MMR6_ENC : ARITH_FM_MMR6<"sub", 0x190>; class SUBU_MMR6_ENC : ARITH_FM_MMR6<"subu", 0x1d0>; class SW_MMR6_ENC : SW32_FM_MMR6<"sw", 0x3e>; -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>; -class WSBH_MMR6_ENC : POOL32A_WRPGPR_WSBH_FM_MMR6<0x1ec>; +class WRPGPR_MMR6_ENC : POOL32A_WRPGPR_WSBH_FM_MMR6<"wrpgpr", 0x3c5>; +class WSBH_MMR6_ENC : POOL32A_WRPGPR_WSBH_FM_MMR6<"wsbh", 0x1ec>; class LB_MMR6_ENC : LB32_FM_MMR6; class LBU_MMR6_ENC : LBU32_FM_MMR6; -class LBE_MMR6_ENC : POOL32C_LB_LBU_FM_MMR6<0b100>; -class LBUE_MMR6_ENC : POOL32C_LB_LBU_FM_MMR6<0b000>; class PAUSE_MMR6_ENC : POOL32A_PAUSE_FM_MMR6<"pause", 0b00101>; class RDHWR_MMR6_ENC : POOL32A_RDHWR_FM_MMR6; class WAIT_MMR6_ENC : WAIT_FM_MM, MMR6Arch<"wait">; @@ -184,15 +175,8 @@ class TRUNC_L_S_MMR6_ENC : POOL32F_MATH_FM_MMR6<"trunc.l.s", 0, 0b10001100>; class TRUNC_L_D_MMR6_ENC : POOL32F_MATH_FM_MMR6<"trunc.l.d", 1, 0b10001100>; class TRUNC_W_S_MMR6_ENC : POOL32F_MATH_FM_MMR6<"trunc.w.s", 0, 0b10101100>; class TRUNC_W_D_MMR6_ENC : POOL32F_MATH_FM_MMR6<"trunc.w.d", 1, 0b10101100>; -class SQRT_S_MMR6_ENC : POOL32F_MATH_FM_MMR6<"sqrt.s", 0, 0b00101000>; -class SQRT_D_MMR6_ENC : POOL32F_MATH_FM_MMR6<"sqrt.d", 1, 0b00101000>; class SB_MMR6_ENC : SB32_SH32_STORE_FM_MMR6<0b000110>; -class SBE_MMR6_ENC : POOL32C_STORE_EVA_FM_MMR6<0b100>; -class SCE_MMR6_ENC : POOL32C_STORE_EVA_FM_MMR6<0b110>; class SH_MMR6_ENC : SB32_SH32_STORE_FM_MMR6<0b001110>; -class SHE_MMR6_ENC : POOL32C_STORE_EVA_FM_MMR6<0b101>; -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>; @@ -221,11 +205,11 @@ 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; +class ANDI16_MMR6_ENC : ANDI_FM_MM16<0b001011>; class NOT16_MMR6_ENC : POOL16C_NOT16_FM_MMR6; class OR16_MMR6_ENC : POOL16C_OR16_XOR16_FM_MMR6<0b1001>; -class SLL16_MMR6_ENC : SHIFT_FM_MM16<0>, MicroMipsR6Inst16; -class SRL16_MMR6_ENC : SHIFT_FM_MM16<1>, MicroMipsR6Inst16; +class SLL16_MMR6_ENC : SHIFT_FM_MM16<0>; +class SRL16_MMR6_ENC : SHIFT_FM_MM16<1>; class BREAK16_MMR6_ENC : POOL16C_BREAKPOINT_FM_MMR6<0b011011>; class LI16_MMR6_ENC : LI_FM_MM16; class MOVE16_MMR6_ENC : MOVE_FM_MM16<0b000011>; @@ -248,23 +232,20 @@ 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 LL_MMR6_ENC : POOL32C_LL_E_SC_E_FM_MMR6<"ll", 0b0011, 0b000>; +class SC_MMR6_ENC : POOL32C_LL_E_SC_E_FM_MMR6<"sc", 0b1011, 0b000>; + /// 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>; class FSUB_S_MMR6_ENC : POOL32F_ARITH_FM_MMR6<"sub.s", 0, 0b01110000>; -class FSUB_D_MMR6_ENC : POOL32F_ARITH_FM_MMR6<"sub.d", 1, 0b01110000>; class FMUL_S_MMR6_ENC : POOL32F_ARITH_FM_MMR6<"mul.s", 0, 0b10110000>; -class FMUL_D_MMR6_ENC : POOL32F_ARITH_FM_MMR6<"mul.d", 1, 0b10110000>; class FDIV_S_MMR6_ENC : POOL32F_ARITH_FM_MMR6<"div.s", 0, 0b11110000>; -class FDIV_D_MMR6_ENC : POOL32F_ARITH_FM_MMR6<"div.d", 1, 0b11110000>; class MADDF_S_MMR6_ENC : POOL32F_ARITHF_FM_MMR6<"maddf.s", 0, 0b110111000>; class MADDF_D_MMR6_ENC : POOL32F_ARITHF_FM_MMR6<"maddf.d", 1, 0b110111000>; class MSUBF_S_MMR6_ENC : POOL32F_ARITHF_FM_MMR6<"msubf.s", 0, 0b111111000>; class MSUBF_D_MMR6_ENC : POOL32F_ARITHF_FM_MMR6<"msubf.d", 1, 0b111111000>; class FMOV_S_MMR6_ENC : POOL32F_MOV_NEG_FM_MMR6<"mov.s", 0, 0b0000001>; -class FMOV_D_MMR6_ENC : POOL32F_MOV_NEG_FM_MMR6<"mov.d", 1, 0b0000001>; class FNEG_S_MMR6_ENC : POOL32F_MOV_NEG_FM_MMR6<"neg.s", 0, 0b0101101>; -class FNEG_D_MMR6_ENC : POOL32F_MOV_NEG_FM_MMR6<"neg.d", 1, 0b0101101>; class MAX_S_MMR6_ENC : POOL32F_MINMAX_FM<"max.s", 0, 0b000001011>; class MAX_D_MMR6_ENC : POOL32F_MINMAX_FM<"max.d", 1, 0b000001011>; class MAXA_S_MMR6_ENC : POOL32F_MINMAX_FM<"maxa.s", 0, 0b000101011>; @@ -277,11 +258,7 @@ class MINA_D_MMR6_ENC : POOL32F_MINMAX_FM<"mina.d", 1, 0b000100011>; class CVT_L_S_MMR6_ENC : POOL32F_CVT_LW_FM<"cvt.l.s", 0, 0b00000100>; class CVT_L_D_MMR6_ENC : POOL32F_CVT_LW_FM<"cvt.l.d", 1, 0b00000100>; class CVT_W_S_MMR6_ENC : POOL32F_CVT_LW_FM<"cvt.w.s", 0, 0b00100100>; -class CVT_W_D_MMR6_ENC : POOL32F_CVT_LW_FM<"cvt.w.d", 1, 0b00100100>; -class CVT_D_S_MMR6_ENC : POOL32F_CVT_DS_FM<"cvt.d.s", 0, 0b1001101>; -class CVT_D_W_MMR6_ENC : POOL32F_CVT_DS_FM<"cvt.d.w", 1, 0b1001101>; class CVT_D_L_MMR6_ENC : POOL32F_CVT_DS_FM<"cvt.d.l", 2, 0b1001101>; -class CVT_S_D_MMR6_ENC : POOL32F_CVT_DS_FM<"cvt.s.d", 0, 0b1101101>; class CVT_S_W_MMR6_ENC : POOL32F_CVT_DS_FM<"cvt.s.w", 1, 0b1101101>; class CVT_S_L_MMR6_ENC : POOL32F_CVT_DS_FM<"cvt.s.l", 2, 0b1101101>; @@ -390,7 +367,7 @@ class BC_MMR6_DESC : BC_MMR6_DESC_BASE<"bc", brtarget26_mm, II_BC> { class BC16_MMR6_DESC : MicroMipsInst16<(outs), (ins brtarget10_mm:$offset), !strconcat("bc16", "\t$offset"), [], II_BC, FrmI>, - MMR6Arch<"bc16">, MicroMipsR6Inst16 { + MMR6Arch<"bc16"> { let isBranch = 1; let isTerminator = 1; let isBarrier = 1; @@ -400,7 +377,8 @@ class BC16_MMR6_DESC : MicroMipsInst16<(outs), (ins brtarget10_mm:$offset), } class BEQZC_BNEZC_MM16R6_DESC_BASE<string instr_asm> - : CBranchZeroMM<instr_asm, brtarget7_mm, GPRMM16Opnd>, MMR6Arch<instr_asm> { + : CBranchZeroMM<instr_asm, brtarget7_mm, GPRMM16Opnd>, + MMR6Arch<instr_asm> { let isBranch = 1; let isTerminator = 1; let hasDelaySlot = 0; @@ -441,17 +419,6 @@ class CACHE_MMR6_DESC : CACHE_HINT_MMR6_DESC<"cache", mem_mm_12, GPR32Opnd, class PREF_MMR6_DESC : CACHE_HINT_MMR6_DESC<"pref", mem_mm_12, GPR32Opnd, II_PREF>; -class PREFE_CACHEE_MMR6_DESC_BASE<string instr_asm, Operand MemOpnd, - RegisterOperand GPROpnd, InstrItinClass Itin> - : CACHE_HINT_MMR6_DESC<instr_asm, MemOpnd, GPROpnd, Itin> { - string DecoderMethod = "DecodePrefeOpMM"; -} - -class PREFE_MMR6_DESC : PREFE_CACHEE_MMR6_DESC_BASE<"prefe", mem_mm_9, - GPR32Opnd, II_PREFE>; -class CACHEE_MMR6_DESC : PREFE_CACHEE_MMR6_DESC_BASE<"cachee", mem_mm_9, - GPR32Opnd, II_CACHEE>; - class LB_LBU_MMR6_DESC_BASE<string instr_asm, Operand MemOpnd, RegisterOperand GPROpnd, InstrItinClass Itin> : MMR6Arch<instr_asm> { @@ -466,16 +433,6 @@ class LB_MMR6_DESC : LB_LBU_MMR6_DESC_BASE<"lb", mem_mm_16, GPR32Opnd, II_LB>; class LBU_MMR6_DESC : LB_LBU_MMR6_DESC_BASE<"lbu", mem_mm_16, GPR32Opnd, II_LBU>; -class LBE_LBUE_MMR6_DESC_BASE<string instr_asm, Operand MemOpnd, - RegisterOperand GPROpnd, InstrItinClass Itin> - : LB_LBU_MMR6_DESC_BASE<instr_asm, MemOpnd, GPROpnd, Itin> { - let DecoderMethod = "DecodeLoadByte9"; -} -class LBE_MMR6_DESC : LBE_LBUE_MMR6_DESC_BASE<"lbe", mem_mm_9, GPR32Opnd, - II_LBE>; -class LBUE_MMR6_DESC : LBE_LBUE_MMR6_DESC_BASE<"lbue", mem_mm_9, GPR32Opnd, - II_LBUE>; - class CLO_CLZ_MMR6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, InstrItinClass Itin> : MMR6Arch<instr_asm> { dag OutOperandList = (outs GPROpnd:$rt); @@ -498,7 +455,7 @@ class ERETNC_MMR6_DESC : ER_FT<"eretnc", II_ERETNC>; class JALRC16_MMR6_DESC_BASE<string opstr, RegisterOperand RO> : MicroMipsInst16<(outs), (ins RO:$rs), !strconcat(opstr, "\t$rs"), [(MipsJmpLink RO:$rs)], II_JALR, FrmR>, - MMR6Arch<opstr>, MicroMipsR6Inst16 { + MMR6Arch<opstr> { let isCall = 1; let hasDelaySlot = 0; let Defs = [RA]; @@ -532,7 +489,7 @@ class JIC_MMR6_DESC : JMP_MMR6_IDX_COMPACT_DESC_BASE<"jic", jmpoffset16, class JRC16_MMR6_DESC_BASE<string opstr, RegisterOperand RO> : MicroMipsInst16<(outs), (ins RO:$rs), !strconcat(opstr, "\t$rs"), [], II_JR, FrmR>, - MMR6Arch<opstr>, MicroMipsR6Inst16 { + MMR6Arch<opstr> { let hasDelaySlot = 0; let isBranch = 1; let isIndirectBranch = 1; @@ -542,7 +499,7 @@ class JRC16_MMR6_DESC : JRC16_MMR6_DESC_BASE<"jrc16", GPR32Opnd>; class JRCADDIUSP_MMR6_DESC : MicroMipsInst16<(outs), (ins uimm5_lsl2:$imm), "jrcaddiusp\t$imm", [], II_JRADDIUSP, FrmR>, - MMR6Arch<"jrcaddiusp">, MicroMipsR6Inst16 { + MMR6Arch<"jrcaddiusp"> { let hasDelaySlot = 0; let isTerminator = 1; let isBarrier = 1; @@ -574,8 +531,6 @@ class AUI_MMR6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, class AUI_MMR6_DESC : AUI_MMR6_DESC_BASE<"aui", GPR32Opnd, II_AUI>; -class SEB_MMR6_DESC : SignExtInReg<"seb", i8, GPR32Opnd, II_SEB>; -class SEH_MMR6_DESC : SignExtInReg<"seh", i16, GPR32Opnd, II_SEH>; class ALUIPC_MMR6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, InstrItinClass Itin> : MMR6Arch<instr_asm> { dag OutOperandList = (outs GPROpnd:$rt); @@ -615,32 +570,6 @@ class ADDIUPC_MMR6_DESC : PCREL_MMR6_DESC_BASE<"addiupc", GPR32Opnd, class LWPC_MMR6_DESC: PCREL_MMR6_DESC_BASE<"lwpc", GPR32Opnd, simm19_lsl2, II_LWPC>; -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 Itinerary = II_LWP; - 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 Itinerary = II_SWP; - 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, InstrItinClass Itin> : MMR6Arch<instr_asm> { dag OutOperandList = (outs GPROpnd:$rd); @@ -704,23 +633,11 @@ class ORI_MMR6_DESC : ArithLogicI<"ori", uimm16, GPR32Opnd, II_ORI, immZExt16, 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, - InstrItinClass Itin = NoItinerary, - SDPatternOperator OpNode = null_frag, - ComplexPattern Addr = addr> : - InstSE<(outs), (ins RO:$rt, MO:$addr), !strconcat(opstr, "\t$rt, $addr"), - [(OpNode RO:$rt, Addr:$addr)], Itin, FrmI, opstr> { - let DecoderMethod = "DecodeMem"; - let mayStore = 1; -} class SW_MMR6_DESC : Store<"sw", GPR32Opnd> { InstrItinClass Itinerary = II_SW; } -class SWE_MMR6_DESC : SWE_MMR6_DESC_BASE<"swe", GPR32Opnd, mem_simm9, II_SWE>; - class WRPGPR_WSBH_MMR6_DESC_BASE<string instr_asm, RegisterOperand RO, - InstrItinClass Itin> : MMR6Arch<instr_asm> { + InstrItinClass Itin> { dag InOperandList = (ins RO:$rs); dag OutOperandList = (outs RO:$rt); string AsmString = !strconcat(instr_asm, "\t$rt, $rs"); @@ -789,12 +706,6 @@ class MTC2_MMR6_DESC : MTC2_MMR6_DESC_BASE<"mtc2", COP2Opnd, GPR32Opnd, II_MTC2>; class MTHC0_MMR6_DESC : MTC0_MMR6_DESC_BASE<"mthc0", COP0Opnd, GPR32Opnd, II_MTHC0>; -class MTHC1_D32_MMR6_DESC : MTC1_64_MMR6_DESC_BASE<"mthc1", AFGR64Opnd, - GPR32Opnd, II_MTC1>, - HARDFLOAT, FGR_32; -class MTHC1_D64_MMR6_DESC : MTC1_64_MMR6_DESC_BASE<"mthc1", FGR64Opnd, - GPR32Opnd, II_MTC1>, - HARDFLOAT, FGR_64; class MTHC2_MMR6_DESC : MTC2_MMR6_DESC_BASE<"mthc2", COP2Opnd, GPR32Opnd, II_MTC2>; @@ -838,10 +749,6 @@ class MFC2_MMR6_DESC : MFC2_MMR6_DESC_BASE<"mfc2", GPR32Opnd, COP2Opnd, II_MFC2>; class MFHC0_MMR6_DESC : MFC0_MMR6_DESC_BASE<"mfhc0", GPR32Opnd, COP0Opnd, II_MFHC0>; -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, II_MFC2>; @@ -897,6 +804,49 @@ class SDC2_SWC2_MMR6_DESC_BASE<string opstr, InstrItinClass itin> { class SDC2_MMR6_DESC : SDC2_SWC2_MMR6_DESC_BASE<"sdc2", II_SDC2>; class SWC2_MMR6_DESC : SDC2_SWC2_MMR6_DESC_BASE<"swc2", II_SWC2>; +class GINV_MMR6_DESC_BASE<string opstr, + RegisterOperand SrcRC, InstrItinClass Itin> { + dag InOperandList = (ins SrcRC:$rs, uimm2:$type); + dag OutOperandList = (outs); + string AsmString = !strconcat(opstr, "\t$rs, $type"); + list<dag> Pattern = []; + Format f = FrmFR; + string BaseOpcode = opstr; + InstrItinClass Itinerary = Itin; +} + +class GINVI_MMR6_DESC : GINV_MMR6_DESC_BASE<"ginvi", GPR32Opnd, + II_GINVI> { + dag InOperandList = (ins GPR32Opnd:$rs); + string AsmString = "ginvi\t$rs"; +} +class GINVT_MMR6_DESC : GINV_MMR6_DESC_BASE<"ginvt", GPR32Opnd, + II_GINVT>; + +class SC_MMR6_DESC_BASE<string opstr, InstrItinClass itin> { + dag OutOperandList = (outs GPR32Opnd:$dst); + dag InOperandList = (ins GPR32Opnd:$rt, mem_mm_9:$addr); + string AsmString = !strconcat(opstr, "\t$rt, $addr"); + InstrItinClass Itinerary = itin; + string BaseOpcode = opstr; + bit mayStore = 1; + string Constraints = "$rt = $dst"; + string DecoderMethod = "DecodeMemMMImm9"; +} + +class LL_MMR6_DESC_BASE<string opstr, InstrItinClass itin> { + dag OutOperandList = (outs GPR32Opnd:$rt); + dag InOperandList = (ins mem_mm_9:$addr); + string AsmString = !strconcat(opstr, "\t$rt, $addr"); + InstrItinClass Itinerary = itin; + string BaseOpcode = opstr; + bit mayLoad = 1; + string DecoderMethod = "DecodeMemMMImm9"; +} + +class SC_MMR6_DESC : SC_MMR6_DESC_BASE<"sc", II_SC>; +class LL_MMR6_DESC : LL_MMR6_DESC_BASE<"ll", II_LL>; + /// Floating Point Instructions class FARITH_MMR6_DESC_BASE<string instr_asm, RegisterOperand RC, InstrItinClass Itin, bit isComm, @@ -910,20 +860,12 @@ class FARITH_MMR6_DESC_BASE<string instr_asm, RegisterOperand RC, } class FADD_S_MMR6_DESC : FARITH_MMR6_DESC_BASE<"add.s", FGR32Opnd, II_ADD_S, 1, fadd>; -class FADD_D_MMR6_DESC - : FARITH_MMR6_DESC_BASE<"add.d", AFGR64Opnd, II_ADD_D, 1, fadd>; class FSUB_S_MMR6_DESC : FARITH_MMR6_DESC_BASE<"sub.s", FGR32Opnd, II_SUB_S, 0, fsub>; -class FSUB_D_MMR6_DESC - : FARITH_MMR6_DESC_BASE<"sub.d", AFGR64Opnd, II_SUB_D, 0, fsub>; class FMUL_S_MMR6_DESC : FARITH_MMR6_DESC_BASE<"mul.s", FGR32Opnd, II_MUL_S, 1, fmul>; -class FMUL_D_MMR6_DESC - : FARITH_MMR6_DESC_BASE<"mul.d", AFGR64Opnd, II_MUL_D, 1, fmul>; class FDIV_S_MMR6_DESC : FARITH_MMR6_DESC_BASE<"div.s", FGR32Opnd, II_DIV_S, 0, fdiv>; -class FDIV_D_MMR6_DESC - : FARITH_MMR6_DESC_BASE<"div.d", AFGR64Opnd, II_DIV_D, 0, fdiv>; class MADDF_S_MMR6_DESC : COP1_4R_DESC_BASE<"maddf.s", FGR32Opnd, II_MADDF_S>, HARDFLOAT; class MADDF_D_MMR6_DESC : COP1_4R_DESC_BASE<"maddf.d", FGR64Opnd, @@ -946,12 +888,8 @@ class FMOV_FNEG_MMR6_DESC_BASE<string instr_asm, RegisterOperand DstRC, } class FMOV_S_MMR6_DESC : FMOV_FNEG_MMR6_DESC_BASE<"mov.s", FGR32Opnd, FGR32Opnd, II_MOV_S>; -class FMOV_D_MMR6_DESC - : FMOV_FNEG_MMR6_DESC_BASE<"mov.d", AFGR64Opnd, AFGR64Opnd, II_MOV_D>; class FNEG_S_MMR6_DESC : FMOV_FNEG_MMR6_DESC_BASE<"neg.s", FGR32Opnd, FGR32Opnd, II_NEG, fneg>; -class FNEG_D_MMR6_DESC - : FMOV_FNEG_MMR6_DESC_BASE<"neg.d", AFGR64Opnd, AFGR64Opnd, II_NEG, fneg>; class MAX_S_MMR6_DESC : MAX_MIN_DESC_BASE<"max.s", FGR32Opnd, II_MAX_S>, HARDFLOAT; @@ -989,16 +927,8 @@ class CVT_L_D_MMR6_DESC : CVT_MMR6_DESC_BASE<"cvt.l.d", FGR64Opnd, FGR64Opnd, II_CVT>; class CVT_W_S_MMR6_DESC : CVT_MMR6_DESC_BASE<"cvt.w.s", FGR32Opnd, FGR32Opnd, II_CVT>; -class CVT_W_D_MMR6_DESC : CVT_MMR6_DESC_BASE<"cvt.w.d", FGR32Opnd, AFGR64Opnd, - II_CVT>; -class CVT_D_S_MMR6_DESC : CVT_MMR6_DESC_BASE<"cvt.d.s", FGR32Opnd, AFGR64Opnd, - II_CVT>; -class CVT_D_W_MMR6_DESC : CVT_MMR6_DESC_BASE<"cvt.d.w", FGR32Opnd, AFGR64Opnd, - II_CVT>; class CVT_D_L_MMR6_DESC : CVT_MMR6_DESC_BASE<"cvt.d.l", FGR64Opnd, FGR64Opnd, II_CVT>, FGR_64; -class CVT_S_D_MMR6_DESC : CVT_MMR6_DESC_BASE<"cvt.s.d", AFGR64Opnd, FGR32Opnd, - II_CVT>; class CVT_S_W_MMR6_DESC : CVT_MMR6_DESC_BASE<"cvt.s.w", FGR32Opnd, FGR32Opnd, II_CVT>; class CVT_S_L_MMR6_DESC : CVT_MMR6_DESC_BASE<"cvt.s.l", FGR64Opnd, FGR32Opnd, @@ -1085,10 +1015,6 @@ class ABSS_FT_MMR6_DESC_BASE<string instr_asm, RegisterOperand DstRC, list<Predicate> EncodingPredicates = [HasStdEnc]; } -class ABS_S_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"abs.s", FGR32Opnd, FGR32Opnd, - II_ABS, fabs>; -class ABS_D_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"abs.d", AFGR64Opnd, AFGR64Opnd, - II_ABS, fabs>; class FLOOR_L_S_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"floor.l.s", FGR64Opnd, FGR32Opnd, II_FLOOR>; class FLOOR_L_D_MMR6_DESC : ABSS_FT_MMR6_DESC_BASE<"floor.l.d", FGR64Opnd, @@ -1154,70 +1080,35 @@ class STORE_MMR6_DESC_BASE<string opstr, DAGOperand RO, } class SB_MMR6_DESC : STORE_MMR6_DESC_BASE<"sb", GPR32Opnd, II_SB>; -class STORE_EVA_MMR6_DESC_BASE<string instr_asm, RegisterOperand RO, - InstrItinClass Itin> - : MMR6Arch<instr_asm>, MipsR6Inst { - dag OutOperandList = (outs); - dag InOperandList = (ins RO:$rt, mem_simm9:$addr); - string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); - string DecoderMethod = "DecodeStoreEvaOpMM"; - bit mayStore = 1; - InstrItinClass Itinerary = Itin; -} -class SBE_MMR6_DESC : STORE_EVA_MMR6_DESC_BASE<"sbe", GPR32Opnd, II_SBE>; -class SCE_MMR6_DESC : STORE_EVA_MMR6_DESC_BASE<"sce", GPR32Opnd, II_SCE>; class SH_MMR6_DESC : STORE_MMR6_DESC_BASE<"sh", GPR32Opnd, II_SH>; -class SHE_MMR6_DESC : STORE_EVA_MMR6_DESC_BASE<"she", GPR32Opnd, II_SHE>; -class LOAD_WORD_EVA_MMR6_DESC_BASE<string instr_asm, RegisterOperand RO, - InstrItinClass Itin> - : MMR6Arch<instr_asm>, MipsR6Inst { - dag OutOperandList = (outs RO:$rt); - dag InOperandList = (ins mem_simm9:$addr); - string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); - string DecoderMethod = "DecodeMemMMImm9"; - bit mayLoad = 1; - InstrItinClass Itinerary = Itin; -} -class LLE_MMR6_DESC : LOAD_WORD_EVA_MMR6_DESC_BASE<"lle", GPR32Opnd, II_LLE>; -class LWE_MMR6_DESC : LOAD_WORD_EVA_MMR6_DESC_BASE<"lwe", GPR32Opnd, II_LWE>; class ADDU16_MMR6_DESC : ArithRMM16<"addu16", GPRMM16Opnd, 1, II_ADDU, add>, MMR6Arch<"addu16"> { int AddedComplexity = 1; } -class AND16_MMR6_DESC : LogicRMM16<"and16", GPRMM16Opnd, II_AND, and>, - MMR6Arch<"and16"> { - int AddedComplexity = 1; -} +class AND16_MMR6_DESC : LogicRMM16<"and16", GPRMM16Opnd, II_AND>, + MMR6Arch<"and16">; class ANDI16_MMR6_DESC : AndImmMM16<"andi16", GPRMM16Opnd, II_AND>, MMR6Arch<"andi16">; class NOT16_MMR6_DESC : NotMM16<"not16", GPRMM16Opnd>, MMR6Arch<"not16"> { int AddedComplexity = 1; } -class OR16_MMR6_DESC : LogicRMM16<"or16", GPRMM16Opnd, II_OR, or>, - MMR6Arch<"or16"> { - int AddedComplexity = 1; -} +class OR16_MMR6_DESC : LogicRMM16<"or16", GPRMM16Opnd, II_OR>, MMR6Arch<"or16">; 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", II_BREAK>, MMR6Arch<"break16">, - MicroMipsR6Inst16; +class BREAK16_MMR6_DESC : BrkSdbbp16MM<"break16", II_BREAK>, MMR6Arch<"break16">; class LI16_MMR6_DESC : LoadImmMM16<"li16", li16_imm, GPRMM16Opnd>, - MMR6Arch<"li16">, MicroMipsR6Inst16, IsAsCheapAsAMove; -class MOVE16_MMR6_DESC : MoveMM16<"move16", GPR32Opnd>, MMR6Arch<"move16">, - MicroMipsR6Inst16; + MMR6Arch<"li16">, IsAsCheapAsAMove; +class MOVE16_MMR6_DESC : MoveMM16<"move16", GPR32Opnd>, MMR6Arch<"move16">; class MOVEP_MMR6_DESC : MovePMM16<"movep", GPRMM16OpndMoveP>, MMR6Arch<"movep">; -class SDBBP16_MMR6_DESC : BrkSdbbp16MM<"sdbbp16", II_SDBBP>, MMR6Arch<"sdbbp16">, - MicroMipsR6Inst16; +class SDBBP16_MMR6_DESC : BrkSdbbp16MM<"sdbbp16", II_SDBBP>, MMR6Arch<"sdbbp16">; class SUBU16_MMR6_DESC : ArithRMM16<"subu16", GPRMM16Opnd, 0, II_SUBU, sub>, - MMR6Arch<"subu16">, MicroMipsR6Inst16 { - int AddedComplexity = 1; -} -class XOR16_MMR6_DESC : LogicRMM16<"xor16", GPRMM16Opnd, II_XOR, xor>, - MMR6Arch<"xor16"> { + MMR6Arch<"subu16"> { int AddedComplexity = 1; } +class XOR16_MMR6_DESC : LogicRMM16<"xor16", GPRMM16Opnd, II_XOR>, + MMR6Arch<"xor16">; class LW_MMR6_DESC : MMR6Arch<"lw">, MipsR6Inst { dag OutOperandList = (outs GPR32Opnd:$rt); @@ -1250,7 +1141,7 @@ class SYNC_MMR6_DESC : MMR6Arch<"sync">, MipsR6Inst { bit HasSideEffects = 1; } -class SYNCI_MMR6_DESC : SYNCI_FT<"synci"> { +class SYNCI_MMR6_DESC : SYNCI_FT<"synci", mem_mm_16> { let DecoderMethod = "DecodeSynciR6"; } @@ -1273,7 +1164,7 @@ class LWM16_MMR6_DESC : MicroMipsInst16<(outs reglist16:$rt), (ins mem_mm_4sp:$addr), !strconcat("lwm16", "\t$rt, $addr"), [], II_LWM, FrmI>, - MMR6Arch<"lwm16">, MicroMipsR6Inst16 { + MMR6Arch<"lwm16"> { let DecoderMethod = "DecodeMemMMReglistImm4Lsl2"; let mayLoad = 1; ComplexPattern Addr = addr; @@ -1283,7 +1174,7 @@ class SWM16_MMR6_DESC : MicroMipsInst16<(outs), (ins reglist16:$rt, mem_mm_4sp:$addr), !strconcat("swm16", "\t$rt, $addr"), [], II_SWM, FrmI>, - MMR6Arch<"swm16">, MicroMipsR6Inst16 { + MMR6Arch<"swm16"> { let DecoderMethod = "DecodeMemMMReglistImm4Lsl2"; let mayStore = 1; ComplexPattern Addr = addr; @@ -1294,7 +1185,7 @@ class SB16_MMR6_DESC_BASE<string opstr, DAGOperand RTOpnd, DAGOperand RO, Operand MemOpnd> : MicroMipsInst16<(outs), (ins RTOpnd:$rt, MemOpnd:$addr), !strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI>, - MMR6Arch<opstr>, MicroMipsR6Inst16 { + MMR6Arch<opstr> { let DecoderMethod = "DecodeMemMMImm4"; let mayStore = 1; } @@ -1308,7 +1199,7 @@ class SW16_MMR6_DESC : SB16_MMR6_DESC_BASE<"sw16", GPRMM16OpndZero, GPRMM16Opnd, class SWSP_MMR6_DESC : MicroMipsInst16<(outs), (ins GPR32Opnd:$rt, mem_mm_sp_imm5_lsl2:$offset), !strconcat("sw", "\t$rt, $offset"), [], II_SW, FrmI>, - MMR6Arch<"sw">, MicroMipsR6Inst16 { + MMR6Arch<"sw"> { let DecoderMethod = "DecodeMemMMSPImm5Lsl2"; let mayStore = 1; } @@ -1473,6 +1364,11 @@ def ERET_MMR6 : StdMMR6Rel, ERET_MMR6_DESC, ERET_MMR6_ENC, ISA_MICROMIPS32R6; def DERET_MMR6 : StdMMR6Rel, DERET_MMR6_DESC, DERET_MMR6_ENC, ISA_MICROMIPS32R6; def ERETNC_MMR6 : R6MMR6Rel, ERETNC_MMR6_DESC, ERETNC_MMR6_ENC, ISA_MICROMIPS32R6; +def GINVI_MMR6 : R6MMR6Rel, GINVI_MMR6_ENC, GINVI_MMR6_DESC, + ISA_MICROMIPS32R6, ASE_GINV; +def GINVT_MMR6 : R6MMR6Rel, GINVT_MMR6_ENC, GINVT_MMR6_DESC, + ISA_MICROMIPS32R6, ASE_GINV; +let FastISelShouldIgnore = 1 in def JALRC16_MMR6 : R6MMR6Rel, JALRC16_MMR6_DESC, JALRC16_MMR6_ENC, ISA_MICROMIPS32R6; def JIALC_MMR6 : R6MMR6Rel, JIALC_MMR6_ENC, JIALC_MMR6_DESC, ISA_MICROMIPS32R6; @@ -1481,29 +1377,17 @@ 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 = "MicroMipsFP64" 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 = "MicroMipsFP64" 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; @@ -1516,8 +1400,6 @@ def OR_MMR6 : StdMMR6Rel, OR_MMR6_DESC, OR_MMR6_ENC, ISA_MICROMIPS32R6; def ORI_MMR6 : StdMMR6Rel, ORI_MMR6_DESC, ORI_MMR6_ENC, ISA_MICROMIPS32R6; def PREF_MMR6 : R6MMR6Rel, PREF_MMR6_ENC, PREF_MMR6_DESC, ISA_MICROMIPS32R6; def SB16_MMR6 : StdMMR6Rel, SB16_MMR6_DESC, SB16_MMR6_ENC, ISA_MICROMIPS32R6; -def SEB_MMR6 : StdMMR6Rel, SEB_MMR6_DESC, SEB_MMR6_ENC, ISA_MICROMIPS32R6; -def SEH_MMR6 : StdMMR6Rel, SEH_MMR6_DESC, SEH_MMR6_ENC, ISA_MICROMIPS32R6; def SELEQZ_MMR6 : R6MMR6Rel, SELEQZ_MMR6_ENC, SELEQZ_MMR6_DESC, ISA_MICROMIPS32R6; def SELNEZ_MMR6 : R6MMR6Rel, SELNEZ_MMR6_ENC, SELNEZ_MMR6_DESC, @@ -1529,17 +1411,11 @@ 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; def WRPGPR_MMR6 : StdMMR6Rel, WRPGPR_MMR6_ENC, WRPGPR_MMR6_DESC, ISA_MICROMIPS32R6; def WSBH_MMR6 : StdMMR6Rel, WSBH_MMR6_ENC, WSBH_MMR6_DESC, ISA_MICROMIPS32R6; def LB_MMR6 : R6MMR6Rel, LB_MMR6_ENC, LB_MMR6_DESC, ISA_MICROMIPS32R6; def LBU_MMR6 : R6MMR6Rel, LBU_MMR6_ENC, LBU_MMR6_DESC, ISA_MICROMIPS32R6; -def LBE_MMR6 : R6MMR6Rel, LBE_MMR6_ENC, LBE_MMR6_DESC, ISA_MICROMIPS32R6; -def LBUE_MMR6 : R6MMR6Rel, LBUE_MMR6_ENC, LBUE_MMR6_DESC, ISA_MICROMIPS32R6; def PAUSE_MMR6 : StdMMR6Rel, PAUSE_MMR6_DESC, PAUSE_MMR6_ENC, ISA_MICROMIPS32R6; def RDHWR_MMR6 : R6MMR6Rel, RDHWR_MMR6_DESC, RDHWR_MMR6_ENC, ISA_MICROMIPS32R6; def WAIT_MMR6 : StdMMR6Rel, WAIT_MMR6_DESC, WAIT_MMR6_ENC, ISA_MICROMIPS32R6; @@ -1554,26 +1430,15 @@ def XORI_MMR6 : StdMMR6Rel, XORI_MMR6_DESC, XORI_MMR6_ENC, ISA_MICROMIPS32R6; let DecoderMethod = "DecodeMemMMImm16" in { def SW_MMR6 : StdMMR6Rel, SW_MMR6_DESC, SW_MMR6_ENC, ISA_MICROMIPS32R6; } -let DecoderMethod = "DecodeMemMMImm9" in { - def SWE_MMR6 : StdMMR6Rel, SWE_MMR6_DESC, SWE_MMR6_ENC, ISA_MICROMIPS32R6; -} /// Floating Point Instructions def FADD_S_MMR6 : StdMMR6Rel, FADD_S_MMR6_ENC, FADD_S_MMR6_DESC, ISA_MICROMIPS32R6; -def FADD_D_MMR6 : StdMMR6Rel, FADD_D_MMR6_ENC, FADD_D_MMR6_DESC, - ISA_MICROMIPS32R6; def FSUB_S_MMR6 : StdMMR6Rel, FSUB_S_MMR6_ENC, FSUB_S_MMR6_DESC, ISA_MICROMIPS32R6; -def FSUB_D_MMR6 : StdMMR6Rel, FSUB_D_MMR6_ENC, FSUB_D_MMR6_DESC, - ISA_MICROMIPS32R6; def FMUL_S_MMR6 : StdMMR6Rel, FMUL_S_MMR6_ENC, FMUL_S_MMR6_DESC, ISA_MICROMIPS32R6; -def FMUL_D_MMR6 : StdMMR6Rel, FMUL_D_MMR6_ENC, FMUL_D_MMR6_DESC, - ISA_MICROMIPS32R6; def FDIV_S_MMR6 : StdMMR6Rel, FDIV_S_MMR6_ENC, FDIV_S_MMR6_DESC, ISA_MICROMIPS32R6; -def FDIV_D_MMR6 : StdMMR6Rel, FDIV_D_MMR6_ENC, FDIV_D_MMR6_DESC, - ISA_MICROMIPS32R6; def MADDF_S_MMR6 : R6MMR6Rel, MADDF_S_MMR6_ENC, MADDF_S_MMR6_DESC, ISA_MICROMIPS32R6; def MADDF_D_MMR6 : R6MMR6Rel, MADDF_D_MMR6_ENC, MADDF_D_MMR6_DESC, @@ -1584,12 +1449,8 @@ def MSUBF_D_MMR6 : R6MMR6Rel, MSUBF_D_MMR6_ENC, MSUBF_D_MMR6_DESC, ISA_MICROMIPS32R6; def FMOV_S_MMR6 : StdMMR6Rel, FMOV_S_MMR6_ENC, FMOV_S_MMR6_DESC, ISA_MICROMIPS32R6; -def FMOV_D_MMR6 : StdMMR6Rel, FMOV_D_MMR6_ENC, FMOV_D_MMR6_DESC, - ISA_MICROMIPS32R6; def FNEG_S_MMR6 : StdMMR6Rel, FNEG_S_MMR6_ENC, FNEG_S_MMR6_DESC, ISA_MICROMIPS32R6; -def FNEG_D_MMR6 : StdMMR6Rel, FNEG_D_MMR6_ENC, FNEG_D_MMR6_DESC, - ISA_MICROMIPS32R6; def MAX_S_MMR6 : R6MMR6Rel, MAX_S_MMR6_ENC, MAX_S_MMR6_DESC, ISA_MICROMIPS32R6; def MAX_D_MMR6 : R6MMR6Rel, MAX_D_MMR6_ENC, MAX_D_MMR6_DESC, ISA_MICROMIPS32R6; def MIN_S_MMR6 : R6MMR6Rel, MIN_S_MMR6_ENC, MIN_S_MMR6_DESC, ISA_MICROMIPS32R6; @@ -1608,24 +1469,14 @@ def CVT_L_D_MMR6 : StdMMR6Rel, CVT_L_D_MMR6_ENC, CVT_L_D_MMR6_DESC, ISA_MICROMIPS32R6; def CVT_W_S_MMR6 : StdMMR6Rel, CVT_W_S_MMR6_ENC, CVT_W_S_MMR6_DESC, ISA_MICROMIPS32R6; -def CVT_W_D_MMR6 : StdMMR6Rel, CVT_W_D_MMR6_ENC, CVT_W_D_MMR6_DESC, - ISA_MICROMIPS32R6; -def CVT_D_S_MMR6 : StdMMR6Rel, CVT_D_S_MMR6_ENC, CVT_D_S_MMR6_DESC, - ISA_MICROMIPS32R6; -def CVT_D_W_MMR6 : StdMMR6Rel, CVT_D_W_MMR6_ENC, CVT_D_W_MMR6_DESC, - ISA_MICROMIPS32R6; def CVT_D_L_MMR6 : StdMMR6Rel, CVT_D_L_MMR6_ENC, CVT_D_L_MMR6_DESC, ISA_MICROMIPS32R6; -def CVT_S_D_MMR6 : StdMMR6Rel, CVT_S_D_MMR6_ENC, CVT_S_D_MMR6_DESC, - ISA_MICROMIPS32R6; def CVT_S_W_MMR6 : StdMMR6Rel, CVT_S_W_MMR6_ENC, CVT_S_W_MMR6_DESC, ISA_MICROMIPS32R6; def CVT_S_L_MMR6 : StdMMR6Rel, CVT_S_L_MMR6_ENC, CVT_S_L_MMR6_DESC, ISA_MICROMIPS32R6; defm S_MMR6 : CMP_CC_MMR6<0b000101, "s", FGR32Opnd, II_CMP_CC_S>; defm D_MMR6 : CMP_CC_MMR6<0b010101, "d", FGR64Opnd, II_CMP_CC_D>; -def ABS_S_MMR6 : StdMMR6Rel, ABS_S_MMR6_ENC, ABS_S_MMR6_DESC, ISA_MICROMIPS32R6; -def ABS_D_MMR6 : StdMMR6Rel, ABS_D_MMR6_ENC, ABS_D_MMR6_DESC, ISA_MICROMIPS32R6; def FLOOR_L_S_MMR6 : StdMMR6Rel, FLOOR_L_S_MMR6_ENC, FLOOR_L_S_MMR6_DESC, ISA_MICROMIPS32R6; def FLOOR_L_D_MMR6 : StdMMR6Rel, FLOOR_L_D_MMR6_ENC, FLOOR_L_D_MMR6_DESC, @@ -1650,17 +1501,8 @@ def TRUNC_W_S_MMR6 : StdMMR6Rel, TRUNC_W_S_MMR6_ENC, TRUNC_W_S_MMR6_DESC, ISA_MICROMIPS32R6; def TRUNC_W_D_MMR6 : StdMMR6Rel, TRUNC_W_D_MMR6_ENC, TRUNC_W_D_MMR6_DESC, ISA_MICROMIPS32R6; -def SQRT_S_MMR6 : StdMMR6Rel, SQRT_S_MMR6_ENC, SQRT_S_MMR6_DESC, - ISA_MICROMIPS32R6; -def SQRT_D_MMR6 : StdMMR6Rel, SQRT_D_MMR6_ENC, SQRT_D_MMR6_DESC, - ISA_MICROMIPS32R6; def SB_MMR6 : StdMMR6Rel, SB_MMR6_DESC, SB_MMR6_ENC, ISA_MICROMIPS32R6; -def SBE_MMR6 : StdMMR6Rel, SBE_MMR6_DESC, SBE_MMR6_ENC, ISA_MICROMIPS32R6; -def SCE_MMR6 : StdMMR6Rel, SCE_MMR6_DESC, SCE_MMR6_ENC, ISA_MICROMIPS32R6; def SH_MMR6 : StdMMR6Rel, SH_MMR6_DESC, SH_MMR6_ENC, ISA_MICROMIPS32R6; -def SHE_MMR6 : StdMMR6Rel, SHE_MMR6_DESC, SHE_MMR6_ENC, ISA_MICROMIPS32R6; -def LLE_MMR6 : StdMMR6Rel, LLE_MMR6_DESC, LLE_MMR6_ENC, ISA_MICROMIPS32R6; -def LWE_MMR6 : StdMMR6Rel, LWE_MMR6_DESC, LWE_MMR6_ENC, ISA_MICROMIPS32R6; def LW_MMR6 : StdMMR6Rel, LW_MMR6_DESC, LW_MMR6_ENC, ISA_MICROMIPS32R6; def LUI_MMR6 : R6MMR6Rel, LUI_MMR6_DESC, LUI_MMR6_ENC, ISA_MICROMIPS32R6; def ADDU16_MMR6 : StdMMR6Rel, ADDU16_MMR6_DESC, ADDU16_MMR6_ENC, @@ -1747,6 +1589,8 @@ 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 LL_MMR6 : R6MMR6Rel, LL_MMR6_ENC, LL_MMR6_DESC, ISA_MICROMIPS32R6; +def SC_MMR6 : R6MMR6Rel, SC_MMR6_ENC, SC_MMR6_DESC, ISA_MICROMIPS32R6; } def BOVC_MMR6 : R6MMR6Rel, BOVC_MMR6_ENC, BOVC_MMR6_DESC, ISA_MICROMIPS32R6, @@ -1806,6 +1650,8 @@ def : MipsInstAlias<"mfhc0 $rt, $rs", ISA_MICROMIPS32R6; def : MipsInstAlias<"jalrc.hb $rs", (JALRC_HB_MMR6 RA, GPR32Opnd:$rs), 1>, ISA_MICROMIPS32R6; +def : MipsInstAlias<"jal $offset", (BALC_MMR6 brtarget26_mm:$offset), 0>, + 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>, @@ -1831,13 +1677,32 @@ def : MipsInstAlias<"xor $rs, $imm", def : MipsInstAlias<"not $rt, $rs", (NOR_MMR6 GPR32Opnd:$rt, GPR32Opnd:$rs, ZERO), 0>, ISA_MICROMIPS32R6; -def : MipsInstAlias<"seh $rd", (SEH_MMR6 GPR32Opnd:$rd, GPR32Opnd:$rd), 0>, - ISA_MICROMIPS32R6; -def : MipsInstAlias<"seb $rd", (SEB_MMR6 GPR32Opnd:$rd, GPR32Opnd:$rd), 0>, +def : MipsInstAlias<"not $rt", + (NOR_MMR6 GPR32Opnd:$rt, GPR32Opnd:$rt, ZERO), 0>, ISA_MICROMIPS32R6; def : MipsInstAlias<"lapc $rd, $imm", (ADDIUPC_MMR6 GPR32Opnd:$rd, simm19_lsl2:$imm)>, ISA_MICROMIPS32R6; +def : MipsInstAlias<"neg $rt, $rs", + (SUB_MMR6 GPR32Opnd:$rt, ZERO, GPR32Opnd:$rs), 1>, + ISA_MICROMIPS32R6; +def : MipsInstAlias<"neg $rt", + (SUB_MMR6 GPR32Opnd:$rt, ZERO, GPR32Opnd:$rt), 1>, + ISA_MICROMIPS32R6; +def : MipsInstAlias<"negu $rt, $rs", + (SUBU_MMR6 GPR32Opnd:$rt, ZERO, GPR32Opnd:$rs), 1>, + ISA_MICROMIPS32R6; +def : MipsInstAlias<"negu $rt", + (SUBU_MMR6 GPR32Opnd:$rt, ZERO, GPR32Opnd:$rt), 1>, + ISA_MICROMIPS32R6; +def : MipsInstAlias<"beqz16 $rs, $offset", (BEQZC16_MMR6 GPRMM16Opnd:$rs, + brtarget7_mm:$offset), + 0>, ISA_MICROMIPS32R6; +def : MipsInstAlias<"bnez16 $rs, $offset", (BNEZC16_MMR6 GPRMM16Opnd:$rs, + brtarget7_mm:$offset), + 0>, ISA_MICROMIPS32R6; +def : MipsInstAlias<"b16 $offset", (BC16_MMR6 brtarget10_mm:$offset), 0>, + ISA_MICROMIPS32R6; //===----------------------------------------------------------------------===// // @@ -1867,6 +1732,11 @@ defm : SelectInt_Pats<i32, OR_MM, XORI_MMR6, SLTi_MM, SLTiu_MM, SELEQZ_MMR6, defm S_MMR6 : Cmp_Pats<f32, NOR_MMR6, ZERO>, ISA_MICROMIPS32R6; defm D_MMR6 : Cmp_Pats<f64, NOR_MMR6, ZERO>, ISA_MICROMIPS32R6; +def : MipsPat<(f32 fpimm0), (MTC1_MMR6 ZERO)>, ISA_MICROMIPS32R6; +def : MipsPat<(f32 fpimm0neg), (FNEG_S_MMR6 (MTC1 ZERO))>, ISA_MICROMIPS32R6; +def : MipsPat<(MipsTruncIntFP FGR64Opnd:$src), + (TRUNC_W_D_MMR6 FGR64Opnd:$src)>, ISA_MICROMIPS32R6; + def : MipsPat<(and GPRMM16:$src, immZExtAndi16:$imm), (ANDI16_MMR6 GPRMM16:$src, immZExtAndi16:$imm)>, ISA_MICROMIPS32R6; @@ -1886,9 +1756,49 @@ let AddedComplexity = 41 in { def TAILCALL_MMR6 : TailCall<BC_MMR6, brtarget26_mm>, ISA_MICROMIPS32R6; +def TAILCALLREG_MMR6 : TailCallReg<JRC16_MM, GPR32Opnd>, ISA_MICROMIPS32R6; + +def PseudoIndirectBranch_MMR6 : PseudoIndirectBranchBase<JRC16_MMR6, + GPR32Opnd>, + ISA_MICROMIPS32R6; + def : MipsPat<(MipsTailCall (iPTR tglobaladdr:$dst)), (TAILCALL_MMR6 tglobaladdr:$dst)>, ISA_MICROMIPS32R6; def : MipsPat<(MipsTailCall (iPTR texternalsym:$dst)), (TAILCALL_MMR6 texternalsym:$dst)>, ISA_MICROMIPS32R6; + +def : MipsPat<(brcond (i32 (setne GPR32:$lhs, 0)), bb:$dst), + (BNEZC_MMR6 GPR32:$lhs, bb:$dst)>, ISA_MICROMIPS32R6; +def : MipsPat<(brcond (i32 (seteq GPR32:$lhs, 0)), bb:$dst), + (BEQZC_MMR6 GPR32:$lhs, bb:$dst)>, ISA_MICROMIPS32R6; + +def : MipsPat<(brcond (i32 (setge GPR32:$lhs, GPR32:$rhs)), bb:$dst), + (BEQZC_MMR6 (SLT_MM GPR32:$lhs, GPR32:$rhs), bb:$dst)>, + ISA_MICROMIPS32R6; +def : MipsPat<(brcond (i32 (setuge GPR32:$lhs, GPR32:$rhs)), bb:$dst), + (BEQZC_MMR6 (SLTu_MM GPR32:$lhs, GPR32:$rhs), bb:$dst)>, + ISA_MICROMIPS32R6; +def : MipsPat<(brcond (i32 (setge GPR32:$lhs, immSExt16:$rhs)), bb:$dst), + (BEQZC_MMR6 (SLTi_MM GPR32:$lhs, immSExt16:$rhs), bb:$dst)>, + ISA_MICROMIPS32R6; +def : MipsPat<(brcond (i32 (setuge GPR32:$lhs, immSExt16:$rhs)), bb:$dst), + (BEQZC_MMR6 (SLTiu_MM GPR32:$lhs, immSExt16:$rhs), bb:$dst)>, + ISA_MICROMIPS32R6; +def : MipsPat<(brcond (i32 (setgt GPR32:$lhs, immSExt16Plus1:$rhs)), bb:$dst), + (BEQZC_MMR6 (SLTi_MM GPR32:$lhs, (Plus1 imm:$rhs)), bb:$dst)>, + ISA_MICROMIPS32R6; +def : MipsPat<(brcond (i32 (setugt GPR32:$lhs, immSExt16Plus1:$rhs)), bb:$dst), + (BEQZC_MMR6 (SLTiu_MM GPR32:$lhs, (Plus1 imm:$rhs)), bb:$dst)>, + ISA_MICROMIPS32R6; + +def : MipsPat<(brcond (i32 (setle GPR32:$lhs, GPR32:$rhs)), bb:$dst), + (BEQZC_MMR6 (SLT_MM GPR32:$rhs, GPR32:$lhs), bb:$dst)>, + ISA_MICROMIPS32R6; +def : MipsPat<(brcond (i32 (setule GPR32:$lhs, GPR32:$rhs)), bb:$dst), + (BEQZC_MMR6 (SLTu_MM GPR32:$rhs, GPR32:$lhs), bb:$dst)>, + ISA_MICROMIPS32R6; + +def : MipsPat<(brcond GPR32:$cond, bb:$dst), + (BNEZC_MMR6 GPR32:$cond, bb:$dst)>, ISA_MICROMIPS32R6; diff --git a/lib/Target/Mips/MicroMipsDSPInstrFormats.td b/lib/Target/Mips/MicroMipsDSPInstrFormats.td index af6473c468d9..0d444dfc9fad 100644 --- a/lib/Target/Mips/MicroMipsDSPInstrFormats.td +++ b/lib/Target/Mips/MicroMipsDSPInstrFormats.td @@ -8,9 +8,9 @@ //===----------------------------------------------------------------------===// class MMDSPInst<string opstr = ""> - : MipsInst<(outs), (ins), "", [], NoItinerary, FrmOther>, PredicateControl { - let InsnPredicates = [HasDSP]; - let AdditionalPredicates = [InMicroMips]; + : MipsInst<(outs), (ins), "", [], NoItinerary, FrmOther> { + let ASEPredicate = [HasDSP]; + let EncodingPredicates = [InMicroMips]; string BaseOpcode = opstr; string Arch = "mmdsp"; let DecoderNamespace = "MicroMips"; @@ -18,7 +18,7 @@ class MMDSPInst<string opstr = ""> class MMDSPInstAlias<string Asm, dag Result, bit Emit = 0b1> : InstAlias<Asm, Result, Emit>, PredicateControl { - let InsnPredicates = [HasDSP]; + let ASEPredicate = [HasDSP]; let AdditionalPredicates = [InMicroMips]; } diff --git a/lib/Target/Mips/MicroMipsDSPInstrInfo.td b/lib/Target/Mips/MicroMipsDSPInstrInfo.td index 20c1ab5a9998..132de6be750d 100644 --- a/lib/Target/Mips/MicroMipsDSPInstrInfo.td +++ b/lib/Target/Mips/MicroMipsDSPInstrInfo.td @@ -386,6 +386,7 @@ class WRDSP_MM_DESC { string AsmString = !strconcat("wrdsp", "\t$rt, $mask"); list<dag> Pattern = [(int_mips_wrdsp GPR32Opnd:$rt, immZExt7:$mask)]; InstrItinClass Itinerary = NoItinerary; + bit isMoveReg = 1; } class BPOSGE32C_MMR3_DESC { @@ -416,11 +417,11 @@ class BPOSGE32_MM_DESC : BPOSGE32_DESC_BASE<"bposge32", brtarget_mm, NoItinerary>; let DecoderNamespace = "MicroMipsDSP", Arch = "mmdsp", - AdditionalPredicates = [HasDSP, InMicroMips] in { - def LWDSP_MM : Load<"lw", DSPROpnd, null_frag, II_LW>, DspMMRel, - LW_FM_MM<0x3f>; - def SWDSP_MM : Store<"sw", DSPROpnd, null_frag, II_SW>, DspMMRel, - LW_FM_MM<0x3e>; + EncodingPredicates = [InMicroMips], ASEPredicate = [HasDSP] in { + def LWDSP_MM : Load<"lw", DSPROpnd, null_frag, II_LW>, DspMMRel, + LW_FM_MM<0x3f>; + def SWDSP_MM : Store<"sw", DSPROpnd, null_frag, II_SW>, DspMMRel, + LW_FM_MM<0x3e>; } // Instruction defs. // microMIPS DSP Rev 1 @@ -530,7 +531,7 @@ 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; + ISA_MICROMIPS32_NOT_MIPS32R6; 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; diff --git a/lib/Target/Mips/MicroMipsInstrFPU.td b/lib/Target/Mips/MicroMipsInstrFPU.td index 49025cc1570a..84ae0eddf980 100644 --- a/lib/Target/Mips/MicroMipsInstrFPU.td +++ b/lib/Target/Mips/MicroMipsInstrFPU.td @@ -11,7 +11,18 @@ // //===----------------------------------------------------------------------===// -let isCodeGenOnly = 1 in { +multiclass ADDS_MMM<string opstr, InstrItinClass Itin, bit IsComm, + SDPatternOperator OpNode = null_frag> { + def _D32_MM : MMRel, ADDS_FT<opstr, AFGR64Opnd, Itin, IsComm, OpNode>, + FGR_32 { + string DecoderNamespace = "MicroMips"; + } + // FIXME: This needs to be part of the instruction mapping tables. + def _D64_MM : ADDS_FT<opstr, FGR64Opnd, Itin, IsComm, OpNode>, FGR_64 { + string DecoderNamespace = "MicroMipsFP64"; + } +} + def FADD_S_MM : MMRel, ADDS_FT<"add.s", FGR32Opnd, II_ADD_S, 1, fadd>, ADDS_FM_MM<0, 0x30>, ISA_MICROMIPS; def FDIV_S_MM : MMRel, ADDS_FT<"div.s", FGR32Opnd, II_DIV_S, 0, fdiv>, @@ -21,27 +32,27 @@ def FMUL_S_MM : MMRel, ADDS_FT<"mul.s", FGR32Opnd, II_MUL_S, 1, fmul>, def FSUB_S_MM : MMRel, ADDS_FT<"sub.s", FGR32Opnd, II_SUB_S, 0, fsub>, ADDS_FM_MM<0, 0x70>, ISA_MICROMIPS; -def FADD_MM : MMRel, ADDS_FT<"add.d", AFGR64Opnd, II_ADD_D, 1, fadd>, - ADDS_FM_MM<1, 0x30>, ISA_MICROMIPS; -def FDIV_MM : MMRel, ADDS_FT<"div.d", AFGR64Opnd, II_DIV_D, 0, fdiv>, - ADDS_FM_MM<1, 0xf0>, ISA_MICROMIPS; -def FMUL_MM : MMRel, ADDS_FT<"mul.d", AFGR64Opnd, II_MUL_D, 1, fmul>, - ADDS_FM_MM<1, 0xb0>, ISA_MICROMIPS; -def FSUB_MM : MMRel, ADDS_FT<"sub.d", AFGR64Opnd, II_SUB_D, 0, fsub>, - ADDS_FM_MM<1, 0x70>, ISA_MICROMIPS; - -def LWXC1_MM : MMRel, LWXC1_FT<"lwxc1", FGR32Opnd, II_LWXC1, load>, - LWXC1_FM_MM<0x48>, ISA_MICROMIPS32_NOT_MIPS32R6; -def SWXC1_MM : MMRel, SWXC1_FT<"swxc1", FGR32Opnd, II_SWXC1, store>, - SWXC1_FM_MM<0x88>, ISA_MICROMIPS32_NOT_MIPS32R6; - -// FIXME: These instruction definitions are incorrect. They should be 64-bit -// FPU only. -def LUXC1_MM : MMRel, LWXC1_FT<"luxc1", AFGR64Opnd, II_LUXC1>, - LWXC1_FM_MM<0x148>, ISA_MICROMIPS32_NOT_MIPS32R6; -def SUXC1_MM : MMRel, SWXC1_FT<"suxc1", AFGR64Opnd, II_SUXC1>, - SWXC1_FM_MM<0x188>, ISA_MICROMIPS32_NOT_MIPS32R6; +defm FADD : ADDS_MMM<"add.d", II_ADD_D, 1, fadd>, + ADDS_FM_MM<1, 0x30>, ISA_MICROMIPS; +defm FDIV : ADDS_MMM<"div.d", II_DIV_D, 0, fdiv>, + ADDS_FM_MM<1, 0xf0>, ISA_MICROMIPS; +defm FMUL : ADDS_MMM<"mul.d", II_MUL_D, 1, fmul>, + ADDS_FM_MM<1, 0xb0>, ISA_MICROMIPS; +defm FSUB : ADDS_MMM<"sub.d", II_SUB_D, 0, fsub>, + ADDS_FM_MM<1, 0x70>, ISA_MICROMIPS; +let DecoderNamespace = "MicroMips" in { + def LWXC1_MM : MMRel, LWXC1_FT<"lwxc1", FGR32Opnd, II_LWXC1, load>, + LWXC1_FM_MM<0x48>, ISA_MICROMIPS32_NOT_MIPS32R6; + def SWXC1_MM : MMRel, SWXC1_FT<"swxc1", FGR32Opnd, II_SWXC1, store>, + SWXC1_FM_MM<0x88>, ISA_MICROMIPS32_NOT_MIPS32R6; + + def LUXC1_MM : MMRel, LWXC1_FT<"luxc1", FGR64Opnd, II_LUXC1>, + LWXC1_FM_MM<0x148>, FGR_64, ISA_MICROMIPS32_NOT_MIPS32R6; + def SUXC1_MM : MMRel, SWXC1_FT<"suxc1", FGR64Opnd, II_SUXC1>, + SWXC1_FM_MM<0x188>, FGR_64, ISA_MICROMIPS32_NOT_MIPS32R6; +} +let isCodeGenOnly = 1 in { def FCMP_S32_MM : MMRel, CEQS_FT<"s", FGR32, II_C_CC_S, MipsFPCmp>, CEQS_FM_MM<0>, ISA_MICROMIPS32_NOT_MIPS32R6 { // FIXME: This is a required to work around the fact that these instructions @@ -65,130 +76,174 @@ let DecoderNamespace = "MicroMips" in { BC1F_FM_MM<0x1c>, ISA_MICROMIPS32_NOT_MIPS32R6; def BC1T_MM : MMRel, BC1F_FT<"bc1t", brtarget_mm, II_BC1T, MIPS_BRANCH_T>, BC1F_FM_MM<0x1d>, ISA_MICROMIPS32_NOT_MIPS32R6; + def CVT_W_S_MM : MMRel, ABSS_FT<"cvt.w.s", FGR32Opnd, FGR32Opnd, II_CVT>, + ROUND_W_FM_MM<0, 0x24>, ISA_MICROMIPS; } -let isCodeGenOnly = 1 in { -def CVT_W_S_MM : MMRel, ABSS_FT<"cvt.w.s", FGR32Opnd, FGR32Opnd, II_CVT>, - ROUND_W_FM_MM<0, 0x24>, ISA_MICROMIPS; -def ROUND_W_S_MM : MMRel, StdMMR6Rel, ABSS_FT<"round.w.s", FGR32Opnd, FGR32Opnd, - II_ROUND>, ROUND_W_FM_MM<0, 0xec>, - ISA_MICROMIPS; - -def CEIL_W_MM : MMRel, ABSS_FT<"ceil.w.d", FGR32Opnd, AFGR64Opnd, II_CEIL>, - ROUND_W_FM_MM<1, 0x6c>, ISA_MICROMIPS, FGR_32; -def CVT_W_MM : MMRel, ABSS_FT<"cvt.w.d", FGR32Opnd, AFGR64Opnd, II_CVT>, - ROUND_W_FM_MM<1, 0x24>, ISA_MICROMIPS, FGR_32; -def FLOOR_W_MM : MMRel, ABSS_FT<"floor.w.d", FGR32Opnd, AFGR64Opnd, II_FLOOR>, - ROUND_W_FM_MM<1, 0x2c>, ISA_MICROMIPS, FGR_32; -def ROUND_W_MM : MMRel, StdMMR6Rel, ABSS_FT<"round.w.d", FGR32Opnd, AFGR64Opnd, - II_ROUND>, ROUND_W_FM_MM<1, 0xec>, - ISA_MICROMIPS, FGR_32; -def TRUNC_W_MM : MMRel, ABSS_FT<"trunc.w.d", FGR32Opnd, AFGR64Opnd, II_TRUNC>, - ROUND_W_FM_MM<1, 0xac>, ISA_MICROMIPS, FGR_32; - -def FSQRT_MM : MMRel, ABSS_FT<"sqrt.d", AFGR64Opnd, AFGR64Opnd, II_SQRT_D, - fsqrt>, ROUND_W_FM_MM<1, 0x28>, - ISA_MICROMIPS, FGR_32; - -def CVT_L_S_MM : MMRel, ABSS_FT<"cvt.l.s", FGR64Opnd, FGR32Opnd, II_CVT>, - ROUND_W_FM_MM<0, 0x4>, ISA_MICROMIPS, FGR_64; -def CVT_L_D64_MM : MMRel, ABSS_FT<"cvt.l.d", FGR64Opnd, FGR64Opnd, II_CVT>, - ROUND_W_FM_MM<1, 0x4>, ISA_MICROMIPS, FGR_64; +let DecoderNamespace = "MicroMips" in { + def ROUND_W_S_MM : MMRel, StdMMR6Rel, ABSS_FT<"round.w.s", FGR32Opnd, + FGR32Opnd, II_ROUND>, + ROUND_W_FM_MM<0, 0xec>, ISA_MICROMIPS; + + def CEIL_W_MM : MMRel, ABSS_FT<"ceil.w.d", FGR32Opnd, AFGR64Opnd, II_CEIL>, + ROUND_W_FM_MM<1, 0x6c>, ISA_MICROMIPS, FGR_32; + def FLOOR_W_MM : MMRel, ABSS_FT<"floor.w.d", FGR32Opnd, AFGR64Opnd, II_FLOOR>, + ROUND_W_FM_MM<1, 0x2c>, ISA_MICROMIPS, FGR_32; + def ROUND_W_MM : MMRel, StdMMR6Rel, ABSS_FT<"round.w.d", FGR32Opnd, + AFGR64Opnd, II_ROUND>, + ROUND_W_FM_MM<1, 0xec>, ISA_MICROMIPS, FGR_32; + def TRUNC_W_MM : MMRel, ABSS_FT<"trunc.w.d", FGR32Opnd, AFGR64Opnd, II_TRUNC>, + ROUND_W_FM_MM<1, 0xac>, ISA_MICROMIPS, FGR_32; + + def CVT_L_S_MM : MMRel, ABSS_FT<"cvt.l.s", FGR64Opnd, FGR32Opnd, II_CVT>, + ROUND_W_FM_MM<0, 0x4>, ISA_MICROMIPS, FGR_64; + def CVT_L_D64_MM : MMRel, ABSS_FT<"cvt.l.d", FGR64Opnd, FGR64Opnd, II_CVT>, + ROUND_W_FM_MM<1, 0x4>, ISA_MICROMIPS, FGR_64; + + def CVT_W_D32_MM : MMRel, ABSS_FT<"cvt.w.d", FGR32Opnd, AFGR64Opnd, II_CVT>, + ROUND_W_FM_MM<1, 0x24>, ISA_MICROMIPS, FGR_32; +} +let DecoderNamespace = "MicroMipsFP64" in { + def CVT_W_D64_MM : ABSS_FT<"cvt.w.d", FGR32Opnd, FGR64Opnd, II_CVT>, + ROUND_W_FM_MM<1, 0x24>, ISA_MICROMIPS, FGR_64; +} +multiclass ABSS_MMM<string opstr, InstrItinClass Itin, + SDPatternOperator OpNode = null_frag> { + def _D32_MM : MMRel, ABSS_FT<opstr, AFGR64Opnd, AFGR64Opnd, Itin, OpNode>, + ISA_MICROMIPS, FGR_32 { + string DecoderNamespace = "MicroMips"; + } + // FIXME: This needs to be part of the instruction mapping tables. + def _D64_MM : ABSS_FT<opstr, FGR64Opnd, FGR64Opnd, Itin, OpNode>, + ISA_MICROMIPS, FGR_64 { + string DecoderNamespace = "MicroMipsFP64"; + } } +defm FSQRT : ABSS_MMM<"sqrt.d", II_SQRT_D, fsqrt>, ROUND_W_FM_MM<1, 0x28>; +defm FABS : ABSS_MMM<"abs.d", II_SQRT_D, fabs>, ABS_FM_MM<1, 0xd>; + let DecoderNamespace = "MicroMips" in { def FABS_S_MM : MMRel, ABSS_FT<"abs.s", FGR32Opnd, FGR32Opnd, II_ABS, fabs>, ABS_FM_MM<0, 0xd>, ISA_MICROMIPS; - def FABS_MM : MMRel, ABSS_FT<"abs.d", AFGR64Opnd, AFGR64Opnd, II_ABS, fabs>, - ABS_FM_MM<1, 0xd>, ISA_MICROMIPS, FGR_32; } -let isCodeGenOnly = 1 in { def FMOV_S_MM : MMRel, ABSS_FT<"mov.s", FGR32Opnd, FGR32Opnd, II_MOV_S>, - ABS_FM_MM<0, 0x1>, ISA_MICROMIPS; + ABS_FM_MM<0, 0x1>, ISA_MICROMIPS { + let isMoveReg = 1; +} def FNEG_S_MM : MMRel, ABSS_FT<"neg.s", FGR32Opnd, FGR32Opnd, II_NEG, fneg>, ABS_FM_MM<0, 0x2d>, ISA_MICROMIPS; -def CVT_D_S_MM : MMRel, ABSS_FT<"cvt.d.s", AFGR64Opnd, FGR32Opnd, II_CVT>, - ABS_FM_MM<0, 0x4d>, ISA_MICROMIPS, FGR_32; -def CVT_D32_W_MM : MMRel, ABSS_FT<"cvt.d.w", AFGR64Opnd, FGR32Opnd, II_CVT>, - ABS_FM_MM<1, 0x4d>, ISA_MICROMIPS, FGR_32; -def CVT_S_D32_MM : MMRel, ABSS_FT<"cvt.s.d", FGR32Opnd, AFGR64Opnd, II_CVT>, - ABS_FM_MM<0, 0x6d>, ISA_MICROMIPS, FGR_32; -def CVT_S_W_MM : MMRel, ABSS_FT<"cvt.s.w", FGR32Opnd, FGR32Opnd, II_CVT>, - ABS_FM_MM<1, 0x6d>, ISA_MICROMIPS; - -def FNEG_MM : MMRel, ABSS_FT<"neg.d", AFGR64Opnd, AFGR64Opnd, II_NEG, fneg>, - ABS_FM_MM<1, 0x2d>, ISA_MICROMIPS, FGR_32; - -def FMOV_D32_MM : MMRel, ABSS_FT<"mov.d", AFGR64Opnd, AFGR64Opnd, II_MOV_D>, - ABS_FM_MM<1, 0x1>, ISA_MICROMIPS, FGR_32; - -def MOVZ_I_S_MM : MMRel, CMov_I_F_FT<"movz.s", GPR32Opnd, FGR32Opnd, - II_MOVZ_S>, CMov_I_F_FM_MM<0x78, 0>, - ISA_MICROMIPS32_NOT_MIPS32R6; -def MOVN_I_S_MM : MMRel, CMov_I_F_FT<"movn.s", GPR32Opnd, FGR32Opnd, + +let DecoderNamespace = "MicroMips" in { + def CVT_D32_S_MM : MMRel, ABSS_FT<"cvt.d.s", AFGR64Opnd, FGR32Opnd, II_CVT>, + ABS_FM_MM<0, 0x4d>, ISA_MICROMIPS, FGR_32; + def CVT_D32_W_MM : MMRel, ABSS_FT<"cvt.d.w", AFGR64Opnd, FGR32Opnd, II_CVT>, + ABS_FM_MM<1, 0x4d>, ISA_MICROMIPS, FGR_32; +} + +let DecoderNamespace = "MicroMipsFP64" in { + def CVT_D64_S_MM : ABSS_FT<"cvt.d.s", FGR64Opnd, FGR32Opnd, II_CVT>, + ABS_FM_MM<0, 0x4d>, ISA_MICROMIPS, FGR_64; + def CVT_D64_W_MM : ABSS_FT<"cvt.d.w", FGR64Opnd, FGR32Opnd, II_CVT>, + ABS_FM_MM<1, 0x4d>, ISA_MICROMIPS, FGR_64; + def CVT_S_D64_MM : ABSS_FT<"cvt.s.d", FGR32Opnd, FGR64Opnd, II_CVT>, + ABS_FM_MM<0, 0x6d>, ISA_MICROMIPS, FGR_64; +} + +let DecoderNamespace = "MicroMips" in { + def CVT_S_D32_MM : MMRel, ABSS_FT<"cvt.s.d", FGR32Opnd, AFGR64Opnd, II_CVT>, + ABS_FM_MM<0, 0x6d>, ISA_MICROMIPS, FGR_32; + def CVT_S_W_MM : MMRel, ABSS_FT<"cvt.s.w", FGR32Opnd, FGR32Opnd, II_CVT>, + ABS_FM_MM<1, 0x6d>, ISA_MICROMIPS; +} + + +defm FNEG : ABSS_MMM<"neg.d", II_NEG, fneg>, ABS_FM_MM<1, 0x2d>; +defm FMOV : ABSS_MMM<"mov.d", II_MOV_D>, ABS_FM_MM<1, 0x1>; + +let DecoderNamespace = "MicroMips" in { + def MOVZ_I_S_MM : MMRel, CMov_I_F_FT<"movz.s", GPR32Opnd, FGR32Opnd, + II_MOVZ_S>, CMov_I_F_FM_MM<0x78, 0>, + ISA_MICROMIPS32_NOT_MIPS32R6; + def MOVN_I_S_MM : MMRel, CMov_I_F_FT<"movn.s", GPR32Opnd, FGR32Opnd, II_MOVN_S>, CMov_I_F_FM_MM<0x38, 0>, + ISA_MICROMIPS32_NOT_MIPS32R6; + def MOVZ_I_D32_MM : MMRel, CMov_I_F_FT<"movz.d", GPR32Opnd, AFGR64Opnd, + II_MOVZ_D>, CMov_I_F_FM_MM<0x78, 1>, + ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32; + def MOVN_I_D32_MM : MMRel, CMov_I_F_FT<"movn.d", GPR32Opnd, AFGR64Opnd, + II_MOVN_D>, CMov_I_F_FM_MM<0x38, 1>, + ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32; + + def MOVT_S_MM : MMRel, CMov_F_F_FT<"movt.s", FGR32Opnd, II_MOVT_S, + MipsCMovFP_T>, CMov_F_F_FM_MM<0x60, 0>, ISA_MICROMIPS32_NOT_MIPS32R6; -def MOVZ_I_D32_MM : MMRel, CMov_I_F_FT<"movz.d", GPR32Opnd, AFGR64Opnd, - II_MOVZ_D>, CMov_I_F_FM_MM<0x78, 1>, - ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32; -def MOVN_I_D32_MM : MMRel, CMov_I_F_FT<"movn.d", GPR32Opnd, AFGR64Opnd, - II_MOVN_D>, CMov_I_F_FM_MM<0x38, 1>, - ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32; - -def MOVT_S_MM : MMRel, CMov_F_F_FT<"movt.s", FGR32Opnd, II_MOVT_S, - MipsCMovFP_T>, CMov_F_F_FM_MM<0x60, 0>, - ISA_MICROMIPS32_NOT_MIPS32R6; -def MOVF_S_MM : MMRel, CMov_F_F_FT<"movf.s", FGR32Opnd, II_MOVF_S, - MipsCMovFP_F>, CMov_F_F_FM_MM<0x20, 0>, - ISA_MICROMIPS32_NOT_MIPS32R6; -def MOVT_D32_MM : MMRel, CMov_F_F_FT<"movt.d", AFGR64Opnd, II_MOVT_D, + def MOVF_S_MM : MMRel, CMov_F_F_FT<"movf.s", FGR32Opnd, II_MOVF_S, + MipsCMovFP_F>, CMov_F_F_FM_MM<0x20, 0>, + ISA_MICROMIPS32_NOT_MIPS32R6; + def MOVT_D32_MM : MMRel, CMov_F_F_FT<"movt.d", AFGR64Opnd, II_MOVT_D, MipsCMovFP_T>, CMov_F_F_FM_MM<0x60, 1>, - ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32; -def MOVF_D32_MM : MMRel, CMov_F_F_FT<"movf.d", AFGR64Opnd, II_MOVF_D, - MipsCMovFP_F>, CMov_F_F_FM_MM<0x20, 1>, ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32; -def MFC1_MM : MMRel, MFC1_FT<"mfc1", GPR32Opnd, FGR32Opnd, - II_MFC1, bitconvert>, MFC1_FM_MM<0x80>, - ISA_MICROMIPS; -def MTC1_MM : MMRel, MTC1_FT<"mtc1", FGR32Opnd, GPR32Opnd, - II_MTC1, bitconvert>, MFC1_FM_MM<0xa0>, - ISA_MICROMIPS; - -def MADD_S_MM : MMRel, MADDS_FT<"madd.s", FGR32Opnd, II_MADD_S, fadd>, - MADDS_FM_MM<0x1>, ISA_MICROMIPS32_NOT_MIPS32R6; -def MSUB_S_MM : MMRel, MADDS_FT<"msub.s", FGR32Opnd, II_MSUB_S, fsub>, - MADDS_FM_MM<0x21>, ISA_MICROMIPS32_NOT_MIPS32R6; -def NMADD_S_MM : MMRel, NMADDS_FT<"nmadd.s", FGR32Opnd, II_NMADD_S, fadd>, - MADDS_FM_MM<0x2>, ISA_MICROMIPS32_NOT_MIPS32R6; -def NMSUB_S_MM : MMRel, NMADDS_FT<"nmsub.s", FGR32Opnd, II_NMSUB_S, fsub>, - MADDS_FM_MM<0x22>, ISA_MICROMIPS32_NOT_MIPS32R6; - -def MADD_D32_MM : MMRel, MADDS_FT<"madd.d", AFGR64Opnd, II_MADD_D, fadd>, - MADDS_FM_MM<0x9>, ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32; -def MSUB_D32_MM : MMRel, MADDS_FT<"msub.d", AFGR64Opnd, II_MSUB_D, fsub>, - MADDS_FM_MM<0x29>, ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32; -def NMADD_D32_MM : MMRel, NMADDS_FT<"nmadd.d", AFGR64Opnd, II_NMADD_D, fadd>, - MADDS_FM_MM<0xa>, ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32; -def NMSUB_D32_MM : MMRel, NMADDS_FT<"nmsub.d", AFGR64Opnd, II_NMSUB_D, fsub>, - MADDS_FM_MM<0x2a>, ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32; + def MOVF_D32_MM : MMRel, CMov_F_F_FT<"movf.d", AFGR64Opnd, II_MOVF_D, + MipsCMovFP_F>, CMov_F_F_FM_MM<0x20, 1>, + ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32; + + def MFC1_MM : MMRel, MFC1_FT<"mfc1", GPR32Opnd, FGR32Opnd, + II_MFC1, bitconvert>, MFC1_FM_MM<0x80>, + ISA_MICROMIPS; + def MTC1_MM : MMRel, MTC1_FT<"mtc1", FGR32Opnd, GPR32Opnd, + II_MTC1, bitconvert>, MFC1_FM_MM<0xa0>, + ISA_MICROMIPS; + + def MADD_S_MM : MMRel, MADDS_FT<"madd.s", FGR32Opnd, II_MADD_S>, + MADDS_FM_MM<0x1>, ISA_MICROMIPS32_NOT_MIPS32R6, MADD4; + def MSUB_S_MM : MMRel, MADDS_FT<"msub.s", FGR32Opnd, II_MSUB_S>, + MADDS_FM_MM<0x21>, ISA_MICROMIPS32_NOT_MIPS32R6, MADD4; + let AdditionalPredicates = [NoNaNsFPMath, HasMadd4] in { + def NMADD_S_MM : MMRel, NMADDS_FT<"nmadd.s", FGR32Opnd, II_NMADD_S>, + MADDS_FM_MM<0x2>, ISA_MICROMIPS32_NOT_MIPS32R6; + def NMSUB_S_MM : MMRel, NMADDS_FT<"nmsub.s", FGR32Opnd, II_NMSUB_S>, + MADDS_FM_MM<0x22>, ISA_MICROMIPS32_NOT_MIPS32R6; + } + def MADD_D32_MM : MMRel, MADDS_FT<"madd.d", AFGR64Opnd, II_MADD_D>, + MADDS_FM_MM<0x9>, ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32, + MADD4; + def MSUB_D32_MM : MMRel, MADDS_FT<"msub.d", AFGR64Opnd, II_MSUB_D>, + MADDS_FM_MM<0x29>, ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32, + MADD4; + let AdditionalPredicates = [NoNaNsFPMath, HasMadd4] in { + def NMADD_D32_MM : MMRel, NMADDS_FT<"nmadd.d", AFGR64Opnd, II_NMADD_D>, + MADDS_FM_MM<0xa>, ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32; + def NMSUB_D32_MM : MMRel, NMADDS_FT<"nmsub.d", AFGR64Opnd, II_NMSUB_D>, + MADDS_FM_MM<0x2a>, ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32; + } + + def FLOOR_W_S_MM : MMRel, ABSS_FT<"floor.w.s", FGR32Opnd, FGR32Opnd, + II_FLOOR>, ROUND_W_FM_MM<0, 0x2c>, + ISA_MICROMIPS; + def TRUNC_W_S_MM : MMRel, StdMMR6Rel, ABSS_FT<"trunc.w.s", FGR32Opnd, + FGR32Opnd, II_TRUNC>, + ROUND_W_FM_MM<0, 0xac>, ISA_MICROMIPS; + def CEIL_W_S_MM : MMRel, ABSS_FT<"ceil.w.s", FGR32Opnd, FGR32Opnd, II_CEIL>, + ROUND_W_FM_MM<0, 0x6c>, ISA_MICROMIPS; + + def FSQRT_S_MM : MMRel, ABSS_FT<"sqrt.s", FGR32Opnd, FGR32Opnd, II_SQRT_S, + fsqrt>, ROUND_W_FM_MM<0, 0x28>, ISA_MICROMIPS; + + def MTHC1_D32_MM : MMRel, MTC1_64_FT<"mthc1", AFGR64Opnd, GPR32Opnd, II_MTHC1>, + MFC1_FM_MM<0xe0>, ISA_MICROMIPS, FGR_32; + def MFHC1_D32_MM : MMRel, MFC1_FT<"mfhc1", GPR32Opnd, AFGR64Opnd, II_MFHC1>, + MFC1_FM_MM<0xc0>, ISA_MICROMIPS, FGR_32; } -def FLOOR_W_S_MM : MMRel, ABSS_FT<"floor.w.s", FGR32Opnd, FGR32Opnd, - II_FLOOR>, ROUND_W_FM_MM<0, 0x2c>, - ISA_MICROMIPS; -def TRUNC_W_S_MM : MMRel, StdMMR6Rel, ABSS_FT<"trunc.w.s", FGR32Opnd, - FGR32Opnd, II_TRUNC>, - ROUND_W_FM_MM<0, 0xac>, ISA_MICROMIPS; -def CEIL_W_S_MM : MMRel, ABSS_FT<"ceil.w.s", FGR32Opnd, FGR32Opnd, II_CEIL>, - ROUND_W_FM_MM<0, 0x6c>, ISA_MICROMIPS; -def FSQRT_S_MM : MMRel, ABSS_FT<"sqrt.s", FGR32Opnd, FGR32Opnd, II_SQRT_S, - fsqrt>, ROUND_W_FM_MM<0, 0x28>, ISA_MICROMIPS; -def MTHC1_MM : MMRel, MTC1_64_FT<"mthc1", AFGR64Opnd, GPR32Opnd, II_MTHC1>, - MFC1_FM_MM<0xe0>, ISA_MICROMIPS, FGR_32; -def MFHC1_MM : MMRel, MFC1_FT<"mfhc1", GPR32Opnd, AFGR64Opnd, II_MFHC1>, - MFC1_FM_MM<0xc0>, ISA_MICROMIPS, FGR_32; +let DecoderNamespace = "MicroMipsFP64" in { + def MTHC1_D64_MM : MTC1_64_FT<"mthc1", FGR64Opnd, GPR32Opnd, II_MTHC1>, + MFC1_FM_MM<0xe0>, ISA_MICROMIPS, FGR_64; + def MFHC1_D64_MM : MFC1_FT<"mfhc1", GPR32Opnd, FGR64Opnd, II_MFHC1>, + MFC1_FM_MM<0xc0>, ISA_MICROMIPS, FGR_64; +} let DecoderNamespace = "MicroMips" in { def CFC1_MM : MMRel, MFC1_FT<"cfc1", GPR32Opnd, CCROpnd, II_CFC1>, @@ -307,11 +362,13 @@ multiclass C_COND_MM<string TypeStr, RegisterOperand RC, bits<2> fmt, let BaseOpcode = "c.ngt."#NAME; } } +let DecoderNamespace = "MicroMips" in { + defm S : C_COND_MM<"s", FGR32Opnd, 0b00, II_C_CC_S>, + ISA_MICROMIPS32_NOT_MIPS32R6; + defm D32 : C_COND_MM<"d", AFGR64Opnd, 0b01, II_C_CC_D>, + ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32; +} -defm S : C_COND_MM<"s", FGR32Opnd, 0b00, II_C_CC_S>, - ISA_MICROMIPS32_NOT_MIPS32R6; -defm D32 : C_COND_MM<"d", AFGR64Opnd, 0b01, II_C_CC_D>, - ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32; let DecoderNamespace = "Mips64" in defm D64 : C_COND_MM<"d", FGR64Opnd, 0b01, II_C_CC_D>, ISA_MICROMIPS32_NOT_MIPS32R6, FGR_64; @@ -347,3 +404,36 @@ let AddedComplexity = 40 in { def : LoadRegImmPat<LWC1_MM, f32, load>, ISA_MICROMIPS; def : StoreRegImmPat<SWC1_MM, f32>, ISA_MICROMIPS; } + +def : MipsPat<(f32 fpimm0), (MTC1_MM ZERO)>, ISA_MICROMIPS32_NOT_MIPS32R6; +def : MipsPat<(f32 fpimm0neg), (FNEG_S_MM (MTC1_MM ZERO))>, + ISA_MICROMIPS32_NOT_MIPS32R6; + +def : MipsPat<(f32 (fpround FGR64Opnd:$src)), + (CVT_S_D64_MM FGR64Opnd:$src)>, ISA_MICROMIPS, FGR_64; +def : MipsPat<(f64 (fpextend FGR32Opnd:$src)), + (CVT_D64_S_MM FGR32Opnd:$src)>, ISA_MICROMIPS, FGR_64; +def : MipsPat<(f32 (fpround AFGR64Opnd:$src)), + (CVT_S_D32_MM AFGR64Opnd:$src)>, ISA_MICROMIPS, FGR_32; +def : MipsPat<(f64 (fpextend FGR32Opnd:$src)), + (CVT_D32_S_MM FGR32Opnd:$src)>, ISA_MICROMIPS, FGR_32; +def : MipsPat<(MipsTruncIntFP AFGR64Opnd:$src), + (TRUNC_W_MM AFGR64Opnd:$src)>, ISA_MICROMIPS32_NOT_MIPS32R6, + FGR_32; + +// Selects +defm : MovzPats0<GPR32, FGR32, MOVZ_I_S_MM, SLT_MM, SLTu_MM, SLTi_MM, SLTiu_MM>, + ISA_MICROMIPS32_NOT_MIPS32R6; +defm : MovzPats1<GPR32, FGR32, MOVZ_I_S_MM, XOR_MM>, + ISA_MICROMIPS32_NOT_MIPS32R6; + +defm : MovnPats<GPR32, FGR32, MOVN_I_S_MM, XOR_MM>, + ISA_MICROMIPS32_NOT_MIPS32R6; + +defm : MovzPats0<GPR32, AFGR64, MOVZ_I_D32_MM, SLT_MM, SLTu_MM, SLTi_MM, + SLTiu_MM>, + ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32; +defm : MovzPats1<GPR32, AFGR64, MOVZ_I_D32_MM, XOR_MM>, + ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32; +defm : MovnPats<GPR32, AFGR64, MOVN_I_D32_MM, XOR_MM>, + ISA_MICROMIPS32_NOT_MIPS32R6, FGR_32; diff --git a/lib/Target/Mips/MicroMipsInstrFormats.td b/lib/Target/Mips/MicroMipsInstrFormats.td index bc0045dad21e..a9c53e08b810 100644 --- a/lib/Target/Mips/MicroMipsInstrFormats.td +++ b/lib/Target/Mips/MicroMipsInstrFormats.td @@ -1,3 +1,16 @@ +//===-- MicroMipsInstrFormats.td - microMIPS Inst Formats -*- tablegen -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This files descributes the formats of the microMIPS instruction set. +// +//===----------------------------------------------------------------------===// + //===----------------------------------------------------------------------===// // MicroMIPS Base Classes //===----------------------------------------------------------------------===// @@ -7,8 +20,8 @@ // This class does not depend on the instruction size. // class MicroMipsInstBase<dag outs, dag ins, string asmstr, list<dag> pattern, - InstrItinClass itin, Format f> : Instruction -{ + InstrItinClass itin, Format f> : Instruction, + PredicateControl { let Namespace = "Mips"; let DecoderNamespace = "MicroMips"; @@ -19,7 +32,7 @@ class MicroMipsInstBase<dag outs, dag ins, string asmstr, list<dag> pattern, let Pattern = pattern; let Itinerary = itin; - let Predicates = [InMicroMips]; + let EncodingPredicates = [InMicroMips]; Format Form = f; } @@ -406,7 +419,7 @@ class POOL32C_LHUE_FM_MM<bits<6> op, bits<4> fmt, bits<3> funct> : MMArch { let Inst{8-0} = offset; } -class LWL_FM_MM<bits<4> funct> { +class LWL_FM_MM<bits<4> funct> : MMArch { bits<5> rt; bits<21> addr; @@ -419,7 +432,7 @@ class LWL_FM_MM<bits<4> funct> { let Inst{11-0} = addr{11-0}; } -class POOL32C_STEVA_LDEVA_FM_MM<bits<4> type, bits<3> funct> { +class POOL32C_STEVA_LDEVA_FM_MM<bits<4> type, bits<3> funct> : MMArch { bits<5> rt; bits<21> addr; bits<5> base = addr{20-16}; @@ -600,8 +613,9 @@ class SYNC_FM_MM : MMArch { } class SYNCI_FM_MM : MMArch { - bits<5> rs; - bits<16> offset; + bits<21> addr; + bits<5> rs = addr{20-16}; + bits<16> offset = addr{15-0}; bits<32> Inst; let Inst{31-26} = 0b010000; @@ -629,7 +643,7 @@ class SYS_FM_MM : MMArch { let Inst{5-0} = 0x3c; } -class WAIT_FM_MM { +class WAIT_FM_MM : MMArch { bits<10> code_; bits<32> Inst; @@ -699,7 +713,7 @@ class LL_FM_MM<bits<4> funct> : MMArch { let Inst{11-0} = addr{11-0}; } -class LLE_FM_MM<bits<4> funct> { +class LLE_FM_MM<bits<4> funct> : MMArch { bits<5> rt; bits<21> addr; bits<5> base = addr{20-16}; @@ -730,7 +744,6 @@ class ADDS_FM_MM<bits<2> fmt, bits<8> funct> : MMArch { let Inst{9-8} = fmt; let Inst{7-0} = funct; - list<dag> Pattern = []; } class LWXC1_FM_MM<bits<9> funct> : MMArch { @@ -831,13 +844,13 @@ class ABS_FM_MM<bits<2> fmt, bits<7> funct> : MMArch { class CMov_F_F_FM_MM<bits<9> func, bits<2> fmt> : MMArch { bits<5> fd; bits<5> fs; - + bits<3> fcc; bits<32> Inst; let Inst{31-26} = 0x15; let Inst{25-21} = fd; let Inst{20-16} = fs; - let Inst{15-13} = 0x0; //cc + let Inst{15-13} = fcc; //cc let Inst{12-11} = 0x0; let Inst{10-9} = fmt; let Inst{8-0} = func; @@ -961,7 +974,7 @@ class LWM_FM_MM<bits<4> funct> : MMArch { let Inst{11-0} = addr{11-0}; } -class LWM_FM_MM16<bits<4> funct> : MMArch, PredicateControl { +class LWM_FM_MM16<bits<4> funct> : MMArch { bits<2> rt; bits<4> addr; @@ -1053,3 +1066,39 @@ class POOL32A_CFTC2_FM_MM<bits<10> funct> : MMArch { let Inst{15-6} = funct; let Inst{5-0} = 0b111100; } + +class POOL32A_TLBINV_FM_MM<bits<10> funct> : MMArch { + 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_MM<bits<5> funct, bits<6> opcode> : MMArch { + 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 POOL32A_HYPCALL_FM_MM : MMArch { + bits<32> Inst; + + bits<10> code_; + + let Inst{31-26} = 0x0; + let Inst{25-16} = code_; + let Inst{15-6} = 0b1100001101; + let Inst{5-0} = 0b111100; +} diff --git a/lib/Target/Mips/MicroMipsInstrInfo.td b/lib/Target/Mips/MicroMipsInstrInfo.td index 64fe55e9776b..ebadb59a0432 100644 --- a/lib/Target/Mips/MicroMipsInstrInfo.td +++ b/lib/Target/Mips/MicroMipsInstrInfo.td @@ -1,3 +1,16 @@ +//===--- MicroMipsInstrFormats.td - microMIPS Inst Defs -*- tablegen -*----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This files describes the defintions of the microMIPSr3 instructions. +// +//===----------------------------------------------------------------------===// + def addrimm11 : ComplexPattern<iPTR, 2, "selectIntAddr11MM", [frameindex]>; def addrimm12 : ComplexPattern<iPTR, 2, "selectIntAddr12MM", [frameindex]>; def addrimm16 : ComplexPattern<iPTR, 2, "selectIntAddr16MM", [frameindex]>; @@ -128,6 +141,7 @@ def mem_mm_16 : Operand<i32> { let PrintMethod = "printMemOperand"; let MIOperandInfo = (ops ptr_rc, simm16); let EncoderMethod = "getMemEncodingMMImm16"; + let DecoderMethod = "DecodeMemMMImm16"; let ParserMatchClass = MipsMemSimm16AsmOperand; let OperandType = "OPERAND_MEMORY"; } @@ -201,6 +215,9 @@ class LoadLeftRightMM<string opstr, SDNode OpNode, RegisterOperand RO, Itin, FrmI> { let DecoderMethod = "DecodeMemMMImm12"; string Constraints = "$src = $rt"; + let BaseOpcode = opstr; + bit mayLoad = 1; + bit mayStore = 0; } class StoreLeftRightMM<string opstr, SDNode OpNode, RegisterOperand RO, @@ -209,6 +226,9 @@ class StoreLeftRightMM<string opstr, SDNode OpNode, RegisterOperand RO, !strconcat(opstr, "\t$rt, $addr"), [(OpNode RO:$rt, addrimm12:$addr)], Itin, FrmI> { let DecoderMethod = "DecodeMemMMImm12"; + let BaseOpcode = opstr; + bit mayLoad = 0; + bit mayStore = 1; } /// A register pair used by movep instruction. @@ -231,35 +251,23 @@ MicroMipsInst16<(outs movep_regpair:$dst_regs), (ins RO:$rs, RO:$rt), !strconcat(opstr, "\t$dst_regs, $rs, $rt"), [], NoItinerary, FrmR> { let isReMaterializable = 1; -} - -/// A register pair used by load/store pair instructions. -def RegPairAsmOperand : AsmOperandClass { - let Name = "RegPair"; - let ParserMethod = "parseRegisterPair"; - let PredicateMethod = "isRegPair"; -} - -def regpair : Operand<i32> { - let EncoderMethod = "getRegisterPairOpValue"; - let ParserMatchClass = RegPairAsmOperand; - let PrintMethod = "printRegisterPair"; - let DecoderMethod = "DecodeRegPairOperand"; - let MIOperandInfo = (ops ptr_rc, ptr_rc); + let isMoveReg = 1; } class StorePairMM<string opstr, ComplexPattern Addr = addr> - : InstSE<(outs), (ins regpair:$rt, mem_simm12:$addr), + : InstSE<(outs), (ins GPR32Opnd:$rt, GPR32Opnd:$rt2, mem_simm12:$addr), !strconcat(opstr, "\t$rt, $addr"), [], II_SWP, FrmI, opstr> { let DecoderMethod = "DecodeMemMMImm12"; let mayStore = 1; + let AsmMatchConverter = "ConvertXWPOperands"; } class LoadPairMM<string opstr, ComplexPattern Addr = addr> - : InstSE<(outs regpair:$rt), (ins mem_simm12:$addr), + : InstSE<(outs GPR32Opnd:$rt, GPR32Opnd:$rt2), (ins mem_simm12:$addr), !strconcat(opstr, "\t$rt, $addr"), [], II_LWP, FrmI, opstr> { let DecoderMethod = "DecodeMemMMImm12"; let mayLoad = 1; + let AsmMatchConverter = "ConvertXWPOperands"; } class LLBaseMM<string opstr, RegisterOperand RO> : @@ -273,6 +281,7 @@ class LLEBaseMM<string opstr, RegisterOperand RO> : InstSE<(outs RO:$rt), (ins mem_simm9:$addr), !strconcat(opstr, "\t$rt, $addr"), [], II_LLE, FrmI> { let DecoderMethod = "DecodeMemMMImm9"; + string BaseOpcode = opstr; let mayLoad = 1; } @@ -288,6 +297,7 @@ class SCEBaseMM<string opstr, RegisterOperand RO> : InstSE<(outs RO:$dst), (ins RO:$rt, mem_simm9:$addr), !strconcat(opstr, "\t$rt, $addr"), [], II_SCE, FrmI> { let DecoderMethod = "DecodeMemMMImm9"; + string BaseOpcode = opstr; let mayStore = 1; let Constraints = "$rt = $dst"; } @@ -406,12 +416,14 @@ class MoveFromHILOMM<string opstr, RegisterOperand RO, Register UseReg> : [], II_MFHI_MFLO, FrmR> { let Uses = [UseReg]; let hasSideEffects = 0; + let isMoveReg = 1; } class MoveMM16<string opstr, RegisterOperand RO> : MicroMipsInst16<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"), [], II_MOVE, FrmR> { let isReMaterializable = 1; + let isMoveReg = 1; } class LoadImmMM16<string opstr, Operand Od, RegisterOperand RO> : @@ -423,7 +435,7 @@ class LoadImmMM16<string opstr, Operand Od, RegisterOperand RO> : // 16-bit Jump and Link (Call) class JumpLinkRegMM16<string opstr, RegisterOperand RO> : MicroMipsInst16<(outs), (ins RO:$rs), !strconcat(opstr, "\t$rs"), - [(MipsJmpLink RO:$rs)], II_JALR, FrmR>, PredicateControl { + [(MipsJmpLink RO:$rs)], II_JALR, FrmR> { let isCall = 1; let hasDelaySlot = 1; let Defs = [RA]; @@ -586,70 +598,113 @@ class UncondBranchMM16<string opstr> : let Defs = [AT]; } -def ADDU16_MM : ArithRMM16<"addu16", GPRMM16Opnd, 1, II_ADDU, add>, - ARITH_FM_MM16<0>, ISA_MICROMIPS_NOT_32R6; -def AND16_MM : LogicRMM16<"and16", GPRMM16Opnd, II_AND, and>, - LOGIC_FM_MM16<0x2>, ISA_MICROMIPS_NOT_32R6; +class HypcallMM<string opstr> : + InstSE<(outs), (ins uimm10:$code_), + !strconcat(opstr, "\t$code_"), [], II_HYPCALL, FrmOther> { + let BaseOpcode = opstr; +} + +class TLBINVMM<string opstr, InstrItinClass Itin> : + InstSE<(outs), (ins), opstr, [], Itin, FrmOther> { + let BaseOpcode = opstr; +} + +class MfCop0MM<string opstr, RegisterOperand DstRC, + RegisterOperand SrcRC, InstrItinClass Itin> : + InstSE<(outs DstRC:$rt), (ins SrcRC:$rs, uimm3:$sel), + !strconcat(opstr, "\t$rt, $rs, $sel"), [], Itin, FrmR> { + let BaseOpcode = opstr; +} + +class MtCop0MM<string opstr, RegisterOperand DstRC, + RegisterOperand SrcRC, InstrItinClass Itin> : + InstSE<(outs DstRC:$rs), (ins SrcRC:$rt, uimm3:$sel), + !strconcat(opstr, "\t$rt, $rs, $sel"), [], Itin, FrmR> { + let BaseOpcode = opstr; +} + +let FastISelShouldIgnore = 1 in { + def ADDU16_MM : ArithRMM16<"addu16", GPRMM16Opnd, 1, II_ADDU, add>, + ARITH_FM_MM16<0>, ISA_MICROMIPS32_NOT_MIPS32R6; + def AND16_MM : LogicRMM16<"and16", GPRMM16Opnd, II_AND, and>, + LOGIC_FM_MM16<0x2>, ISA_MICROMIPS32_NOT_MIPS32R6; +} + def ANDI16_MM : AndImmMM16<"andi16", GPRMM16Opnd, II_AND>, ANDI_FM_MM16<0x0b>, - ISA_MICROMIPS_NOT_32R6; + ISA_MICROMIPS32_NOT_MIPS32R6; def NOT16_MM : NotMM16<"not16", GPRMM16Opnd>, LOGIC_FM_MM16<0x0>, - ISA_MICROMIPS_NOT_32R6; -def OR16_MM : LogicRMM16<"or16", GPRMM16Opnd, II_OR, or>, LOGIC_FM_MM16<0x3>, - ISA_MICROMIPS_NOT_32R6; + ISA_MICROMIPS32_NOT_MIPS32R6; +let FastISelShouldIgnore = 1 in + def OR16_MM : LogicRMM16<"or16", GPRMM16Opnd, II_OR, or>, LOGIC_FM_MM16<0x3>, + ISA_MICROMIPS32_NOT_MIPS32R6; def SLL16_MM : ShiftIMM16<"sll16", uimm3_shift, GPRMM16Opnd, II_SLL>, - SHIFT_FM_MM16<0>, ISA_MICROMIPS_NOT_32R6; + SHIFT_FM_MM16<0>, ISA_MICROMIPS32_NOT_MIPS32R6; def SRL16_MM : ShiftIMM16<"srl16", uimm3_shift, GPRMM16Opnd, II_SRL>, - SHIFT_FM_MM16<1>, ISA_MICROMIPS_NOT_32R6; + SHIFT_FM_MM16<1>, ISA_MICROMIPS32_NOT_MIPS32R6; -def SUBU16_MM : ArithRMM16<"subu16", GPRMM16Opnd, 0, II_SUBU, sub>, - ARITH_FM_MM16<1>, ISA_MICROMIPS_NOT_32R6; -def XOR16_MM : LogicRMM16<"xor16", GPRMM16Opnd, II_XOR, xor>, - LOGIC_FM_MM16<0x1>, ISA_MICROMIPS_NOT_32R6; +let FastISelShouldIgnore = 1 in { + def SUBU16_MM : ArithRMM16<"subu16", GPRMM16Opnd, 0, II_SUBU, sub>, + ARITH_FM_MM16<1>, ISA_MICROMIPS32_NOT_MIPS32R6; + def XOR16_MM : LogicRMM16<"xor16", GPRMM16Opnd, II_XOR, xor>, + LOGIC_FM_MM16<0x1>, ISA_MICROMIPS32_NOT_MIPS32R6; +} def LBU16_MM : LoadMM16<"lbu16", GPRMM16Opnd, zextloadi8, II_LBU, - mem_mm_4>, LOAD_STORE_FM_MM16<0x02>; + mem_mm_4>, LOAD_STORE_FM_MM16<0x02>, ISA_MICROMIPS; def LHU16_MM : LoadMM16<"lhu16", GPRMM16Opnd, zextloadi16, II_LHU, - mem_mm_4_lsl1>, LOAD_STORE_FM_MM16<0x0a>; + mem_mm_4_lsl1>, LOAD_STORE_FM_MM16<0x0a>, ISA_MICROMIPS; def LW16_MM : LoadMM16<"lw16", GPRMM16Opnd, load, II_LW, mem_mm_4_lsl2>, - LOAD_STORE_FM_MM16<0x1a>; + LOAD_STORE_FM_MM16<0x1a>, ISA_MICROMIPS; def SB16_MM : StoreMM16<"sb16", GPRMM16OpndZero, GPRMM16Opnd, truncstorei8, - II_SB, mem_mm_4>, LOAD_STORE_FM_MM16<0x22>; + II_SB, mem_mm_4>, LOAD_STORE_FM_MM16<0x22>, + ISA_MICROMIPS32_NOT_MIPS32R6; def SH16_MM : StoreMM16<"sh16", GPRMM16OpndZero, GPRMM16Opnd, truncstorei16, II_SH, mem_mm_4_lsl1>, - LOAD_STORE_FM_MM16<0x2a>; + LOAD_STORE_FM_MM16<0x2a>, ISA_MICROMIPS32_NOT_MIPS32R6; def SW16_MM : StoreMM16<"sw16", GPRMM16OpndZero, GPRMM16Opnd, store, II_SW, - mem_mm_4_lsl2>, LOAD_STORE_FM_MM16<0x3a>; + mem_mm_4_lsl2>, LOAD_STORE_FM_MM16<0x3a>, + ISA_MICROMIPS32_NOT_MIPS32R6; def LWGP_MM : LoadGPMM16<"lw", GPRMM16Opnd, II_LW, mem_mm_gp_simm7_lsl2>, - LOAD_GP_FM_MM16<0x19>; + LOAD_GP_FM_MM16<0x19>, ISA_MICROMIPS; def LWSP_MM : LoadSPMM16<"lw", GPR32Opnd, II_LW, mem_mm_sp_imm5_lsl2>, - LOAD_STORE_SP_FM_MM16<0x12>; + LOAD_STORE_SP_FM_MM16<0x12>, ISA_MICROMIPS; def SWSP_MM : StoreSPMM16<"sw", GPR32Opnd, II_SW, mem_mm_sp_imm5_lsl2>, - LOAD_STORE_SP_FM_MM16<0x32>; -def ADDIUR1SP_MM : AddImmUR1SP<"addiur1sp", GPRMM16Opnd>, ADDIUR1SP_FM_MM16; -def ADDIUR2_MM : AddImmUR2<"addiur2", GPRMM16Opnd>, ADDIUR2_FM_MM16; -def ADDIUS5_MM : AddImmUS5<"addius5", GPR32Opnd>, ADDIUS5_FM_MM16; -def ADDIUSP_MM : AddImmUSP<"addiusp">, ADDIUSP_FM_MM16; -def MFHI16_MM : MoveFromHILOMM<"mfhi", GPR32Opnd, AC0>, MFHILO_FM_MM16<0x10>; -def MFLO16_MM : MoveFromHILOMM<"mflo", GPR32Opnd, AC0>, MFHILO_FM_MM16<0x12>; -def MOVE16_MM : MoveMM16<"move", GPR32Opnd>, MOVE_FM_MM16<0x03>; + LOAD_STORE_SP_FM_MM16<0x32>, ISA_MICROMIPS32_NOT_MIPS32R6; +def ADDIUR1SP_MM : AddImmUR1SP<"addiur1sp", GPRMM16Opnd>, ADDIUR1SP_FM_MM16, + ISA_MICROMIPS; +def ADDIUR2_MM : AddImmUR2<"addiur2", GPRMM16Opnd>, ADDIUR2_FM_MM16, + ISA_MICROMIPS; +def ADDIUS5_MM : AddImmUS5<"addius5", GPR32Opnd>, ADDIUS5_FM_MM16, + ISA_MICROMIPS; +def ADDIUSP_MM : AddImmUSP<"addiusp">, ADDIUSP_FM_MM16, ISA_MICROMIPS; +def MFHI16_MM : MoveFromHILOMM<"mfhi16", GPR32Opnd, AC0>, + MFHILO_FM_MM16<0x10>, ISA_MICROMIPS32_NOT_MIPS32R6; +def MFLO16_MM : MoveFromHILOMM<"mflo16", GPR32Opnd, AC0>, + MFHILO_FM_MM16<0x12>, ISA_MICROMIPS32_NOT_MIPS32R6; +def MOVE16_MM : MoveMM16<"move", GPR32Opnd>, MOVE_FM_MM16<0x03>, + ISA_MICROMIPS32_NOT_MIPS32R6; def MOVEP_MM : MovePMM16<"movep", GPRMM16OpndMoveP>, MOVEP_FM_MM16, - ISA_MICROMIPS_NOT_32R6; + ISA_MICROMIPS32_NOT_MIPS32R6; def LI16_MM : LoadImmMM16<"li16", li16_imm, GPRMM16Opnd>, LI_FM_MM16, - IsAsCheapAsAMove; + IsAsCheapAsAMove, ISA_MICROMIPS32_NOT_MIPS32R6; def JALR16_MM : JumpLinkRegMM16<"jalr", GPR32Opnd>, JALR_FM_MM16<0x0e>, ISA_MICROMIPS32_NOT_MIPS32R6; -def JALRS16_MM : JumpLinkRegSMM16<"jalrs16", GPR32Opnd>, JALR_FM_MM16<0x0f>; -def JRC16_MM : JumpRegCMM16<"jrc", GPR32Opnd>, JALR_FM_MM16<0x0d>; -def JRADDIUSP : JumpRAddiuStackMM16, JRADDIUSP_FM_MM16<0x18>; -def JR16_MM : JumpRegMM16<"jr16", GPR32Opnd>, JALR_FM_MM16<0x0c>; +def JALRS16_MM : JumpLinkRegSMM16<"jalrs16", GPR32Opnd>, JALR_FM_MM16<0x0f>, + ISA_MICROMIPS32_NOT_MIPS32R6; +def JRC16_MM : JumpRegCMM16<"jrc", GPR32Opnd>, JALR_FM_MM16<0x0d>, + ISA_MICROMIPS32_NOT_MIPS32R6; +def JRADDIUSP : JumpRAddiuStackMM16, JRADDIUSP_FM_MM16<0x18>, + ISA_MICROMIPS32_NOT_MIPS32R6; +def JR16_MM : JumpRegMM16<"jr16", GPR32Opnd>, JALR_FM_MM16<0x0c>, + ISA_MICROMIPS32_NOT_MIPS32R6; def BEQZ16_MM : CBranchZeroMM<"beqz16", brtarget7_mm, GPRMM16Opnd>, - BEQNEZ_FM_MM16<0x23>; + BEQNEZ_FM_MM16<0x23>, ISA_MICROMIPS32_NOT_MIPS32R6; def BNEZ16_MM : CBranchZeroMM<"bnez16", brtarget7_mm, GPRMM16Opnd>, - BEQNEZ_FM_MM16<0x2b>; -def B16_MM : UncondBranchMM16<"b16">, B16_FM; + BEQNEZ_FM_MM16<0x2b>, ISA_MICROMIPS32_NOT_MIPS32R6; +def B16_MM : UncondBranchMM16<"b16">, B16_FM, ISA_MICROMIPS32_NOT_MIPS32R6; def BREAK16_MM : BrkSdbbp16MM<"break16", II_BREAK>, BRKSDBBP16_FM_MM<0x28>, - ISA_MICROMIPS_NOT_32R6; + ISA_MICROMIPS32_NOT_MIPS32R6; def SDBBP16_MM : BrkSdbbp16MM<"sdbbp16", II_SDBBP>, BRKSDBBP16_FM_MM<0x2C>, - ISA_MICROMIPS_NOT_32R6; + ISA_MICROMIPS32_NOT_MIPS32R6; let DecoderNamespace = "MicroMips" in { /// Load and Store Instructions - multiple @@ -657,175 +712,196 @@ let DecoderNamespace = "MicroMips" in { ISA_MICROMIPS32_NOT_MIPS32R6; def LWM16_MM : LoadMultMM16<"lwm16", II_LWM>, LWM_FM_MM16<0x4>, ISA_MICROMIPS32_NOT_MIPS32R6; - let AdditionalPredicates = [InMicroMips] in { - def CFC2_MM : InstSE<(outs GPR32Opnd:$rt), (ins COP2Opnd:$impl), - "cfc2\t$rt, $impl", [], II_CFC2, FrmFR, "cfc2">, - POOL32A_CFTC2_FM_MM<0b1100110100>; - def CTC2_MM : InstSE<(outs COP2Opnd:$impl), (ins GPR32Opnd:$rt), - "ctc2\t$rt, $impl", [], II_CTC2, FrmFR, "ctc2">, - POOL32A_CFTC2_FM_MM<0b1101110100>; - } + def CFC2_MM : InstSE<(outs GPR32Opnd:$rt), (ins COP2Opnd:$impl), + "cfc2\t$rt, $impl", [], II_CFC2, FrmFR, "cfc2">, + POOL32A_CFTC2_FM_MM<0b1100110100>, ISA_MICROMIPS; + def CTC2_MM : InstSE<(outs COP2Opnd:$impl), (ins GPR32Opnd:$rt), + "ctc2\t$rt, $impl", [], II_CTC2, FrmFR, "ctc2">, + POOL32A_CFTC2_FM_MM<0b1101110100>, ISA_MICROMIPS; } class WaitMM<string opstr> : InstSE<(outs), (ins uimm10:$code_), !strconcat(opstr, "\t$code_"), [], II_WAIT, FrmOther, opstr>; -let DecoderNamespace = "MicroMips", Predicates = [InMicroMips, NotMips32r6, - NotMips64r6] in { +let DecoderNamespace = "MicroMips" in { /// Compact Branch Instructions def BEQZC_MM : CompactBranchMM<"beqzc", brtarget_mm, seteq, GPR32Opnd>, - COMPACT_BRANCH_FM_MM<0x7>; + COMPACT_BRANCH_FM_MM<0x7>, ISA_MICROMIPS32_NOT_MIPS32R6; def BNEZC_MM : CompactBranchMM<"bnezc", brtarget_mm, setne, GPR32Opnd>, - COMPACT_BRANCH_FM_MM<0x5>; -} -let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in { + COMPACT_BRANCH_FM_MM<0x5>, ISA_MICROMIPS32_NOT_MIPS32R6; + /// Arithmetic Instructions (ALU Immediate) def ADDiu_MM : MMRel, ArithLogicI<"addiu", simm16, GPR32Opnd, II_ADDIU>, - ADDI_FM_MM<0xc>; + ADDI_FM_MM<0xc>, ISA_MICROMIPS32_NOT_MIPS32R6; def ADDi_MM : MMRel, ArithLogicI<"addi", simm16, GPR32Opnd, II_ADDI>, - ADDI_FM_MM<0x4>; + ADDI_FM_MM<0x4>, ISA_MICROMIPS32_NOT_MIPS32R6; def SLTi_MM : MMRel, SetCC_I<"slti", setlt, simm16, immSExt16, GPR32Opnd>, - SLTI_FM_MM<0x24>; + SLTI_FM_MM<0x24>, ISA_MICROMIPS; def SLTiu_MM : MMRel, SetCC_I<"sltiu", setult, simm16, immSExt16, GPR32Opnd>, - SLTI_FM_MM<0x2c>; + SLTI_FM_MM<0x2c>, ISA_MICROMIPS; def ANDi_MM : MMRel, ArithLogicI<"andi", uimm16, GPR32Opnd, II_ANDI>, - ADDI_FM_MM<0x34>; + ADDI_FM_MM<0x34>, ISA_MICROMIPS32_NOT_MIPS32R6; def ORi_MM : MMRel, ArithLogicI<"ori", uimm16, GPR32Opnd, II_ORI, immZExt16, - or>, ADDI_FM_MM<0x14>; + or>, ADDI_FM_MM<0x14>, + ISA_MICROMIPS32_NOT_MIPS32R6; 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; + immZExt16, xor>, ADDI_FM_MM<0x1c>, + ISA_MICROMIPS32_NOT_MIPS32R6; + def LUi_MM : MMRel, LoadUpper<"lui", GPR32Opnd, uimm16_relaxed>, LUI_FM_MM, + ISA_MICROMIPS32_NOT_MIPS32R6; def LEA_ADDiu_MM : MMRel, EffectiveAddress<"addiu", GPR32Opnd>, - LW_FM_MM<0xc>; + LW_FM_MM<0xc>, ISA_MICROMIPS; /// Arithmetic Instructions (3-Operand, R-Type) def ADDu_MM : MMRel, ArithLogicR<"addu", GPR32Opnd, 1, II_ADDU, add>, - ADD_FM_MM<0, 0x150>; + ADD_FM_MM<0, 0x150>, ISA_MICROMIPS32_NOT_MIPS32R6; def SUBu_MM : MMRel, ArithLogicR<"subu", GPR32Opnd, 0, II_SUBU, sub>, - ADD_FM_MM<0, 0x1d0>; - def MUL_MM : MMRel, ArithLogicR<"mul", GPR32Opnd, 1, II_MUL>, - ADD_FM_MM<0, 0x210>; + ADD_FM_MM<0, 0x1d0>, ISA_MICROMIPS32_NOT_MIPS32R6; + let Defs = [HI0, LO0] in + def MUL_MM : MMRel, ArithLogicR<"mul", GPR32Opnd, 1, II_MUL, mul>, + ADD_FM_MM<0, 0x210>, ISA_MICROMIPS32_NOT_MIPS32R6; def ADD_MM : MMRel, ArithLogicR<"add", GPR32Opnd, 1, II_ADD>, - ADD_FM_MM<0, 0x110>; + ADD_FM_MM<0, 0x110>, ISA_MICROMIPS32_NOT_MIPS32R6; def SUB_MM : MMRel, ArithLogicR<"sub", GPR32Opnd, 0, II_SUB>, - ADD_FM_MM<0, 0x190>; - def SLT_MM : MMRel, SetCC_R<"slt", setlt, GPR32Opnd>, ADD_FM_MM<0, 0x350>; + ADD_FM_MM<0, 0x190>, ISA_MICROMIPS32_NOT_MIPS32R6; + def SLT_MM : MMRel, SetCC_R<"slt", setlt, GPR32Opnd>, ADD_FM_MM<0, 0x350>, + ISA_MICROMIPS; def SLTu_MM : MMRel, SetCC_R<"sltu", setult, GPR32Opnd>, - ADD_FM_MM<0, 0x390>; + ADD_FM_MM<0, 0x390>, ISA_MICROMIPS; def AND_MM : MMRel, ArithLogicR<"and", GPR32Opnd, 1, II_AND, and>, - ADD_FM_MM<0, 0x250>; + ADD_FM_MM<0, 0x250>, ISA_MICROMIPS32_NOT_MIPS32R6; def OR_MM : MMRel, ArithLogicR<"or", GPR32Opnd, 1, II_OR, or>, - ADD_FM_MM<0, 0x290>; + ADD_FM_MM<0, 0x290>, ISA_MICROMIPS32_NOT_MIPS32R6; def XOR_MM : MMRel, ArithLogicR<"xor", GPR32Opnd, 1, II_XOR, xor>, - ADD_FM_MM<0, 0x310>; - def NOR_MM : MMRel, LogicNOR<"nor", GPR32Opnd>, ADD_FM_MM<0, 0x2d0>; + ADD_FM_MM<0, 0x310>, ISA_MICROMIPS32_NOT_MIPS32R6; + def NOR_MM : MMRel, LogicNOR<"nor", GPR32Opnd>, ADD_FM_MM<0, 0x2d0>, + ISA_MICROMIPS32_NOT_MIPS32R6; def MULT_MM : MMRel, Mult<"mult", II_MULT, GPR32Opnd, [HI0, LO0]>, - MULT_FM_MM<0x22c>; + MULT_FM_MM<0x22c>, ISA_MICROMIPS32_NOT_MIPS32R6; def MULTu_MM : MMRel, Mult<"multu", II_MULTU, GPR32Opnd, [HI0, LO0]>, - MULT_FM_MM<0x26c>; + MULT_FM_MM<0x26c>, ISA_MICROMIPS32_NOT_MIPS32R6; def SDIV_MM : MMRel, Div<"div", II_DIV, GPR32Opnd, [HI0, LO0]>, - MULT_FM_MM<0x2ac>, ISA_MIPS1_NOT_32R6_64R6; + MULT_FM_MM<0x2ac>, ISA_MICROMIPS32_NOT_MIPS32R6; def UDIV_MM : MMRel, Div<"divu", II_DIVU, GPR32Opnd, [HI0, LO0]>, - MULT_FM_MM<0x2ec>, ISA_MIPS1_NOT_32R6_64R6; + MULT_FM_MM<0x2ec>, ISA_MICROMIPS32_NOT_MIPS32R6; /// Arithmetic Instructions with PC and Immediate - def ADDIUPC_MM : AddImmUPC<"addiupc", GPRMM16Opnd>, ADDIUPC_FM_MM; + def ADDIUPC_MM : AddImmUPC<"addiupc", GPRMM16Opnd>, ADDIUPC_FM_MM, + ISA_MICROMIPS32_NOT_MIPS32R6; /// Shift Instructions def SLL_MM : MMRel, shift_rotate_imm<"sll", uimm5, GPR32Opnd, II_SLL>, - SRA_FM_MM<0, 0>; + SRA_FM_MM<0, 0>, ISA_MICROMIPS; def SRL_MM : MMRel, shift_rotate_imm<"srl", uimm5, GPR32Opnd, II_SRL>, - SRA_FM_MM<0x40, 0>; + SRA_FM_MM<0x40, 0>, ISA_MICROMIPS; def SRA_MM : MMRel, shift_rotate_imm<"sra", uimm5, GPR32Opnd, II_SRA>, - SRA_FM_MM<0x80, 0>; + SRA_FM_MM<0x80, 0>, ISA_MICROMIPS; def SLLV_MM : MMRel, shift_rotate_reg<"sllv", GPR32Opnd, II_SLLV>, - SRLV_FM_MM<0x10, 0>; + SRLV_FM_MM<0x10, 0>, ISA_MICROMIPS; def SRLV_MM : MMRel, shift_rotate_reg<"srlv", GPR32Opnd, II_SRLV>, - SRLV_FM_MM<0x50, 0>; + SRLV_FM_MM<0x50, 0>, ISA_MICROMIPS; def SRAV_MM : MMRel, shift_rotate_reg<"srav", GPR32Opnd, II_SRAV>, - SRLV_FM_MM<0x90, 0>; + SRLV_FM_MM<0x90, 0>, ISA_MICROMIPS; def ROTR_MM : MMRel, shift_rotate_imm<"rotr", uimm5, GPR32Opnd, II_ROTR>, - SRA_FM_MM<0xc0, 0> { + SRA_FM_MM<0xc0, 0>, ISA_MICROMIPS { 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>, ISA_MICROMIPS { list<dag> Pattern = [(set GPR32Opnd:$rd, (rotr GPR32Opnd:$rt, GPR32Opnd:$rs))]; } /// Load and Store Instructions - aligned let DecoderMethod = "DecodeMemMMImm16" in { - def LB_MM : LoadMemory<"lb", GPR32Opnd, mem_mm_16, null_frag, II_LB>, - MMRel, LW_FM_MM<0x7>; - def LBu_MM : LoadMemory<"lbu", GPR32Opnd, mem_mm_16, null_frag, II_LBU>, - 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, null_frag, II_LW>, MMRel, LW_FM_MM<0x3f>; - def SB_MM : Store<"sb", GPR32Opnd, null_frag, II_SB>, MMRel, - LW_FM_MM<0x6>; - def SH_MM : Store<"sh", GPR32Opnd, null_frag, II_SH>, MMRel, - LW_FM_MM<0xe>; + def LB_MM : LoadMemory<"lb", GPR32Opnd, mem_mm_16, sextloadi8, II_LB>, + MMRel, LW_FM_MM<0x7>, ISA_MICROMIPS; + def LBu_MM : LoadMemory<"lbu", GPR32Opnd, mem_mm_16, zextloadi8, II_LBU>, + MMRel, LW_FM_MM<0x5>, ISA_MICROMIPS; + def LH_MM : LoadMemory<"lh", GPR32Opnd, mem_simmptr, sextloadi16, II_LH, + addrDefault>, MMRel, LW_FM_MM<0xf>, ISA_MICROMIPS; + def LHu_MM : LoadMemory<"lhu", GPR32Opnd, mem_simmptr, zextloadi16, II_LHU>, + MMRel, LW_FM_MM<0xd>, ISA_MICROMIPS; + def LW_MM : Load<"lw", GPR32Opnd, null_frag, II_LW>, MMRel, LW_FM_MM<0x3f>, + ISA_MICROMIPS; + def SB_MM : Store<"sb", GPR32Opnd, truncstorei8, II_SB>, MMRel, + LW_FM_MM<0x6>, ISA_MICROMIPS; + def SH_MM : Store<"sh", GPR32Opnd, truncstorei16, II_SH>, MMRel, + LW_FM_MM<0xe>, ISA_MICROMIPS; def SW_MM : Store<"sw", GPR32Opnd, null_frag, II_SW>, MMRel, - LW_FM_MM<0x3e>; + LW_FM_MM<0x3e>, ISA_MICROMIPS; } - +} +let DecoderNamespace = "MicroMips" in { let DecoderMethod = "DecodeMemMMImm9" in { - def LBE_MM : Load<"lbe", GPR32Opnd, null_frag, II_LBE>, - POOL32C_LHUE_FM_MM<0x18, 0x6, 0x4>; - def LBuE_MM : Load<"lbue", GPR32Opnd, null_frag, II_LBUE>, - POOL32C_LHUE_FM_MM<0x18, 0x6, 0x0>; - def LHE_MM : LoadMemory<"lhe", GPR32Opnd, mem_simm9, null_frag, II_LHE>, - POOL32C_LHUE_FM_MM<0x18, 0x6, 0x5>; - def LHuE_MM : LoadMemory<"lhue", GPR32Opnd, mem_simm9, null_frag, II_LHUE>, - POOL32C_LHUE_FM_MM<0x18, 0x6, 0x1>; - def LWE_MM : LoadMemory<"lwe", GPR32Opnd, mem_simm9, null_frag, II_LWE>, - POOL32C_LHUE_FM_MM<0x18, 0x6, 0x7>; - def SBE_MM : StoreMemory<"sbe", GPR32Opnd, mem_simm9, null_frag, II_SBE>, - POOL32C_LHUE_FM_MM<0x18, 0xa, 0x4>; - def SHE_MM : StoreMemory<"she", GPR32Opnd, mem_simm9, null_frag, II_SHE>, - POOL32C_LHUE_FM_MM<0x18, 0xa, 0x5>; - def SWE_MM : StoreMemory<"swe", GPR32Opnd, mem_simm9, null_frag, II_SWE>, - POOL32C_LHUE_FM_MM<0x18, 0xa, 0x7>; + def LBE_MM : MMRel, Load<"lbe", GPR32Opnd, null_frag, II_LBE>, + POOL32C_LHUE_FM_MM<0x18, 0x6, 0x4>, ISA_MICROMIPS, ASE_EVA; + def LBuE_MM : MMRel, Load<"lbue", GPR32Opnd, null_frag, II_LBUE>, + POOL32C_LHUE_FM_MM<0x18, 0x6, 0x0>, ISA_MICROMIPS, ASE_EVA; + def LHE_MM : MMRel, LoadMemory<"lhe", GPR32Opnd, mem_simm9, null_frag, + II_LHE>, + POOL32C_LHUE_FM_MM<0x18, 0x6, 0x5>, ISA_MICROMIPS, ASE_EVA; + def LHuE_MM : MMRel, LoadMemory<"lhue", GPR32Opnd, mem_simm9, null_frag, + II_LHUE>, + POOL32C_LHUE_FM_MM<0x18, 0x6, 0x1>, ISA_MICROMIPS, ASE_EVA; + def LWE_MM : MMRel, LoadMemory<"lwe", GPR32Opnd, mem_simm9, null_frag, + II_LWE>, + POOL32C_LHUE_FM_MM<0x18, 0x6, 0x7>, ISA_MICROMIPS, ASE_EVA; + def SBE_MM : MMRel, StoreMemory<"sbe", GPR32Opnd, mem_simm9, null_frag, + II_SBE>, + POOL32C_LHUE_FM_MM<0x18, 0xa, 0x4>, ISA_MICROMIPS, ASE_EVA; + def SHE_MM : MMRel, StoreMemory<"she", GPR32Opnd, mem_simm9, null_frag, + II_SHE>, + POOL32C_LHUE_FM_MM<0x18, 0xa, 0x5>, ISA_MICROMIPS, ASE_EVA; + def SWE_MM : MMRel, StoreMemory<"swe", GPR32Opnd, mem_simm9, null_frag, + II_SWE>, + POOL32C_LHUE_FM_MM<0x18, 0xa, 0x7>, ISA_MICROMIPS, ASE_EVA; + def LWLE_MM : MMRel, LoadLeftRightMM<"lwle", MipsLWL, GPR32Opnd, mem_mm_9, + II_LWLE>, + POOL32C_STEVA_LDEVA_FM_MM<0x6, 0x2>, + ISA_MICROMIPS32_NOT_MIPS32R6, ASE_EVA; + def LWRE_MM : MMRel, LoadLeftRightMM<"lwre", MipsLWR, GPR32Opnd, mem_mm_9, + II_LWRE>, + POOL32C_STEVA_LDEVA_FM_MM<0x6, 0x3>, + ISA_MICROMIPS32_NOT_MIPS32R6, ASE_EVA; + def SWLE_MM : MMRel, StoreLeftRightMM<"swle", MipsSWL, GPR32Opnd, mem_mm_9, + II_SWLE>, + POOL32C_STEVA_LDEVA_FM_MM<0xa, 0x0>, + ISA_MICROMIPS32_NOT_MIPS32R6, ASE_EVA; + def SWRE_MM : MMRel, StoreLeftRightMM<"swre", MipsSWR, GPR32Opnd, mem_mm_9, + II_SWRE>, + POOL32C_STEVA_LDEVA_FM_MM<0xa, 0x1>, + ISA_MICROMIPS32_NOT_MIPS32R6, ASE_EVA; } - def LWXS_MM : LoadWordIndexedScaledMM<"lwxs", GPR32Opnd>, LWXS_FM_MM<0x118>; + def LWXS_MM : LoadWordIndexedScaledMM<"lwxs", GPR32Opnd>, LWXS_FM_MM<0x118>, + ISA_MICROMIPS; /// Load and Store Instructions - unaligned - def LWL_MM : LoadLeftRightMM<"lwl", MipsLWL, GPR32Opnd, mem_mm_12, II_LWL>, - LWL_FM_MM<0x0>; - def LWR_MM : LoadLeftRightMM<"lwr", MipsLWR, GPR32Opnd, mem_mm_12, II_LWR>, - LWL_FM_MM<0x1>; - def SWL_MM : StoreLeftRightMM<"swl", MipsSWL, GPR32Opnd, mem_mm_12, II_SWL>, - LWL_FM_MM<0x8>; - def SWR_MM : StoreLeftRightMM<"swr", MipsSWR, GPR32Opnd, mem_mm_12, II_SWR>, - LWL_FM_MM<0x9>; - let DecoderMethod = "DecodeMemMMImm9" in { - def LWLE_MM : LoadLeftRightMM<"lwle", MipsLWL, GPR32Opnd, mem_mm_9, - II_LWLE>, POOL32C_STEVA_LDEVA_FM_MM<0x6, 0x2>; - def LWRE_MM : LoadLeftRightMM<"lwre", MipsLWR, GPR32Opnd, mem_mm_9, - II_LWRE>, POOL32C_STEVA_LDEVA_FM_MM<0x6, 0x3>; - def SWLE_MM : StoreLeftRightMM<"swle", MipsSWL, GPR32Opnd, mem_mm_9, - II_SWLE>, - POOL32C_STEVA_LDEVA_FM_MM<0xa, 0x0>; - def SWRE_MM : StoreLeftRightMM<"swre", MipsSWR, GPR32Opnd, mem_mm_9, - II_SWRE>, - POOL32C_STEVA_LDEVA_FM_MM<0xa, 0x1>, ISA_MIPS1_NOT_32R6_64R6; - } - + def LWL_MM : MMRel, LoadLeftRightMM<"lwl", MipsLWL, GPR32Opnd, mem_mm_12, + II_LWL>, LWL_FM_MM<0x0>, + ISA_MICROMIPS32_NOT_MIPS32R6; + def LWR_MM : MMRel, LoadLeftRightMM<"lwr", MipsLWR, GPR32Opnd, mem_mm_12, + II_LWR>, LWL_FM_MM<0x1>, + ISA_MICROMIPS32_NOT_MIPS32R6; + def SWL_MM : MMRel, StoreLeftRightMM<"swl", MipsSWL, GPR32Opnd, mem_mm_12, + II_SWL>, LWL_FM_MM<0x8>, + ISA_MICROMIPS32_NOT_MIPS32R6; + def SWR_MM : MMRel, StoreLeftRightMM<"swr", MipsSWR, GPR32Opnd, mem_mm_12, + II_SWR>, LWL_FM_MM<0x9>, + ISA_MICROMIPS32_NOT_MIPS32R6; +} +let DecoderNamespace = "MicroMips" in { /// Load and Store Instructions - multiple - def SWM32_MM : StoreMultMM<"swm32", II_SWM>, LWM_FM_MM<0xd>; - def LWM32_MM : LoadMultMM<"lwm32", II_LWM>, LWM_FM_MM<0x5>; + def SWM32_MM : StoreMultMM<"swm32", II_SWM>, LWM_FM_MM<0xd>, ISA_MICROMIPS; + def LWM32_MM : LoadMultMM<"lwm32", II_LWM>, LWM_FM_MM<0x5>, ISA_MICROMIPS; /// Load and Store Pair Instructions - def SWP_MM : StorePairMM<"swp">, LWM_FM_MM<0x9>; - def LWP_MM : LoadPairMM<"lwp">, LWM_FM_MM<0x1>; + def SWP_MM : StorePairMM<"swp">, LWM_FM_MM<0x9>, ISA_MICROMIPS; + def LWP_MM : LoadPairMM<"lwp">, LWM_FM_MM<0x1>, ISA_MICROMIPS; /// Load and Store multiple pseudo Instructions class LoadWordMultMM<string instr_asm > : @@ -837,172 +913,217 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in { !strconcat(instr_asm, "\t$rt, $addr")> ; - def SWM_MM : StoreWordMultMM<"swm">; - def LWM_MM : LoadWordMultMM<"lwm">; + def SWM_MM : StoreWordMultMM<"swm">, ISA_MICROMIPS; + def LWM_MM : LoadWordMultMM<"lwm">, ISA_MICROMIPS; /// Move Conditional def MOVZ_I_MM : MMRel, CMov_I_I_FT<"movz", GPR32Opnd, GPR32Opnd, - NoItinerary>, ADD_FM_MM<0, 0x58>; + II_MOVZ>, ADD_FM_MM<0, 0x58>, + ISA_MICROMIPS32_NOT_MIPS32R6; def MOVN_I_MM : MMRel, CMov_I_I_FT<"movn", GPR32Opnd, GPR32Opnd, - NoItinerary>, ADD_FM_MM<0, 0x18>; - def MOVT_I_MM : MMRel, CMov_F_I_FT<"movt", GPR32Opnd, II_MOVT>, - CMov_F_I_FM_MM<0x25>; - def MOVF_I_MM : MMRel, CMov_F_I_FT<"movf", GPR32Opnd, II_MOVF>, - CMov_F_I_FM_MM<0x5>; - + II_MOVN>, ADD_FM_MM<0, 0x18>, + ISA_MICROMIPS32_NOT_MIPS32R6; + def MOVT_I_MM : MMRel, CMov_F_I_FT<"movt", GPR32Opnd, II_MOVT, MipsCMovFP_T>, + CMov_F_I_FM_MM<0x25>, ISA_MICROMIPS32_NOT_MIPS32R6; + def MOVF_I_MM : MMRel, CMov_F_I_FT<"movf", GPR32Opnd, II_MOVF, MipsCMovFP_F>, + CMov_F_I_FM_MM<0x5>, ISA_MICROMIPS32_NOT_MIPS32R6; /// Move to/from HI/LO def MTHI_MM : MMRel, MoveToLOHI<"mthi", GPR32Opnd, [HI0]>, - MTLO_FM_MM<0x0b5>; + MTLO_FM_MM<0x0b5>, ISA_MICROMIPS32_NOT_MIPS32R6; def MTLO_MM : MMRel, MoveToLOHI<"mtlo", GPR32Opnd, [LO0]>, - MTLO_FM_MM<0x0f5>; + MTLO_FM_MM<0x0f5>, ISA_MICROMIPS32_NOT_MIPS32R6; def MFHI_MM : MMRel, MoveFromLOHI<"mfhi", GPR32Opnd, AC0>, - MFLO_FM_MM<0x035>; + MFLO_FM_MM<0x035>, ISA_MICROMIPS32_NOT_MIPS32R6; def MFLO_MM : MMRel, MoveFromLOHI<"mflo", GPR32Opnd, AC0>, - MFLO_FM_MM<0x075>; + MFLO_FM_MM<0x075>, ISA_MICROMIPS32_NOT_MIPS32R6; /// Multiply Add/Sub Instructions - def MADD_MM : MMRel, MArithR<"madd", II_MADD, 1>, MULT_FM_MM<0x32c>; - def MADDU_MM : MMRel, MArithR<"maddu", II_MADDU, 1>, MULT_FM_MM<0x36c>; - def MSUB_MM : MMRel, MArithR<"msub", II_MSUB>, MULT_FM_MM<0x3ac>; - def MSUBU_MM : MMRel, MArithR<"msubu", II_MSUBU>, MULT_FM_MM<0x3ec>; + def MADD_MM : MMRel, MArithR<"madd", II_MADD, 1>, MULT_FM_MM<0x32c>, + ISA_MICROMIPS32_NOT_MIPS32R6; + def MADDU_MM : MMRel, MArithR<"maddu", II_MADDU, 1>, MULT_FM_MM<0x36c>, + ISA_MICROMIPS32_NOT_MIPS32R6; + def MSUB_MM : MMRel, MArithR<"msub", II_MSUB>, MULT_FM_MM<0x3ac>, + ISA_MICROMIPS32_NOT_MIPS32R6; + def MSUBU_MM : MMRel, MArithR<"msubu", II_MSUBU>, MULT_FM_MM<0x3ec>, + ISA_MICROMIPS32_NOT_MIPS32R6; /// Count Leading def CLZ_MM : MMRel, CountLeading0<"clz", GPR32Opnd, II_CLZ>, CLO_FM_MM<0x16c>, - ISA_MIPS32; + ISA_MICROMIPS; def CLO_MM : MMRel, CountLeading1<"clo", GPR32Opnd, II_CLO>, CLO_FM_MM<0x12c>, - ISA_MIPS32; + ISA_MICROMIPS; /// Sign Ext In Register Instructions. def SEB_MM : MMRel, SignExtInReg<"seb", i8, GPR32Opnd, II_SEB>, - SEB_FM_MM<0x0ac>, ISA_MIPS32R2; + SEB_FM_MM<0x0ac>, ISA_MICROMIPS; def SEH_MM : MMRel, SignExtInReg<"seh", i16, GPR32Opnd, II_SEH>, - SEB_FM_MM<0x0ec>, ISA_MIPS32R2; + SEB_FM_MM<0x0ec>, ISA_MICROMIPS; /// Word Swap Bytes Within Halfwords def WSBH_MM : MMRel, SubwordSwap<"wsbh", GPR32Opnd, II_WSBH>, - SEB_FM_MM<0x1ec>, ISA_MIPS32R2; + SEB_FM_MM<0x1ec>, ISA_MICROMIPS; // TODO: Add '0 < pos+size <= 32' constraint check to ext instruction def EXT_MM : MMRel, ExtBase<"ext", GPR32Opnd, uimm5, uimm5_plus1, immZExt5, - immZExt5Plus1, MipsExt>, EXT_FM_MM<0x2c>; + immZExt5Plus1, MipsExt>, EXT_FM_MM<0x2c>, + ISA_MICROMIPS32_NOT_MIPS32R6; def INS_MM : MMRel, InsBase<"ins", GPR32Opnd, uimm5, uimm5_inssize_plus1, immZExt5, immZExt5Plus1>, - EXT_FM_MM<0x0c>; + EXT_FM_MM<0x0c>, ISA_MICROMIPS32_NOT_MIPS32R6; /// Jump Instructions -} -let DecoderNamespace = "MicroMips", DecoderMethod = "DecodeJumpTargetMM" in - def J_MM : MMRel, JumpFJ<jmptarget_mm, "j", br, bb, "j">, - J_FM_MM<0x35>, AdditionalRequires<[RelocNotPIC]>, - IsBranch, ISA_MICROMIPS32_NOT_MIPS32R6; + let DecoderMethod = "DecodeJumpTargetMM" in + def J_MM : MMRel, JumpFJ<jmptarget_mm, "j", br, bb, "j">, + J_FM_MM<0x35>, AdditionalRequires<[RelocNotPIC]>, + IsBranch, ISA_MICROMIPS32_NOT_MIPS32R6; -let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in { let DecoderMethod = "DecodeJumpTargetMM" 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 JAL_MM : MMRel, JumpLink<"jal", calltarget_mm>, J_FM_MM<0x3d>, + ISA_MICROMIPS32_NOT_MIPS32R6; + def JALX_MM : MMRel, JumpLink<"jalx", calltarget>, J_FM_MM<0x3c>, + ISA_MICROMIPS32_NOT_MIPS32R6; } 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>; + def JALR_MM : JumpLinkReg<"jalr", GPR32Opnd>, JALR_FM_MM<0x03c>, + ISA_MICROMIPS32_NOT_MIPS32R6; /// Jump Instructions - Short Delay Slot - def JALS_MM : JumpLinkMM<"jals", calltarget_mm>, J_FM_MM<0x1d>; - def JALRS_MM : JumpLinkRegMM<"jalrs", GPR32Opnd>, JALR_FM_MM<0x13c>; + def JALS_MM : JumpLinkMM<"jals", calltarget_mm>, J_FM_MM<0x1d>, + ISA_MICROMIPS32_NOT_MIPS32R6; + def JALRS_MM : JumpLinkRegMM<"jalrs", GPR32Opnd>, JALR_FM_MM<0x13c>, + ISA_MICROMIPS32_NOT_MIPS32R6; /// Branch Instructions def BEQ_MM : MMRel, CBranch<"beq", brtarget_mm, seteq, GPR32Opnd>, - BEQ_FM_MM<0x25>; + BEQ_FM_MM<0x25>, ISA_MICROMIPS32_NOT_MIPS32R6; def BNE_MM : MMRel, CBranch<"bne", brtarget_mm, setne, GPR32Opnd>, - BEQ_FM_MM<0x2d>; + BEQ_FM_MM<0x2d>, ISA_MICROMIPS32_NOT_MIPS32R6; def BGEZ_MM : MMRel, CBranchZero<"bgez", brtarget_mm, setge, GPR32Opnd>, - BGEZ_FM_MM<0x2>; + BGEZ_FM_MM<0x2>, ISA_MICROMIPS32_NOT_MIPS32R6; def BGTZ_MM : MMRel, CBranchZero<"bgtz", brtarget_mm, setgt, GPR32Opnd>, - BGEZ_FM_MM<0x6>; + BGEZ_FM_MM<0x6>, ISA_MICROMIPS32_NOT_MIPS32R6; def BLEZ_MM : MMRel, CBranchZero<"blez", brtarget_mm, setle, GPR32Opnd>, - BGEZ_FM_MM<0x4>; + BGEZ_FM_MM<0x4>, ISA_MICROMIPS32_NOT_MIPS32R6; def BLTZ_MM : MMRel, CBranchZero<"bltz", brtarget_mm, setlt, GPR32Opnd>, - BGEZ_FM_MM<0x0>; + BGEZ_FM_MM<0x0>, ISA_MICROMIPS32_NOT_MIPS32R6; def BGEZAL_MM : MMRel, BGEZAL_FT<"bgezal", brtarget_mm, GPR32Opnd>, - BGEZAL_FM_MM<0x03>; + BGEZAL_FM_MM<0x03>, ISA_MICROMIPS32_NOT_MIPS32R6; def BLTZAL_MM : MMRel, BGEZAL_FT<"bltzal", brtarget_mm, GPR32Opnd>, - BGEZAL_FM_MM<0x01>; + BGEZAL_FM_MM<0x01>, ISA_MICROMIPS32_NOT_MIPS32R6; + def BAL_BR_MM : BAL_BR_Pseudo<BGEZAL_MM, brtarget_mm>, + ISA_MICROMIPS32_NOT_MIPS32R6; /// Branch Instructions - Short Delay Slot def BGEZALS_MM : BranchCompareToZeroLinkMM<"bgezals", brtarget_mm, - GPR32Opnd>, BGEZAL_FM_MM<0x13>; + GPR32Opnd>, BGEZAL_FM_MM<0x13>, + ISA_MICROMIPS32_NOT_MIPS32R6; def BLTZALS_MM : BranchCompareToZeroLinkMM<"bltzals", brtarget_mm, - GPR32Opnd>, BGEZAL_FM_MM<0x11>; -} -def B_MM : UncondBranch<BEQ_MM, brtarget_mm>, IsBranch, ISA_MICROMIPS; -let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in { + GPR32Opnd>, BGEZAL_FM_MM<0x11>, + ISA_MICROMIPS32_NOT_MIPS32R6; + def B_MM : UncondBranch<BEQ_MM, brtarget_mm>, IsBranch, + ISA_MICROMIPS32_NOT_MIPS32R6; /// Control Instructions - def SYNC_MM : MMRel, SYNC_FT<"sync">, SYNC_FM_MM; - def SYNCI_MM : MMRel, SYNCI_FT<"synci">, SYNCI_FM_MM; - def BREAK_MM : MMRel, BRK_FT<"break">, BRK_FM_MM; - def SYSCALL_MM : MMRel, SYS_FT<"syscall", uimm10, II_SYSCALL>, SYS_FM_MM; - def WAIT_MM : WaitMM<"wait">, WAIT_FM_MM; - def ERET_MM : MMRel, ER_FT<"eret", II_ERET>, ER_FM_MM<0x3cd>; - def DERET_MM : MMRel, ER_FT<"deret", II_DERET>, ER_FM_MM<0x38d>; + def SYNC_MM : MMRel, SYNC_FT<"sync">, SYNC_FM_MM, ISA_MICROMIPS; + let DecoderMethod = "DecodeSyncI_MM" in + def SYNCI_MM : MMRel, SYNCI_FT<"synci", mem_mm_16>, SYNCI_FM_MM, + ISA_MICROMIPS32_NOT_MIPS32R6; + def BREAK_MM : MMRel, BRK_FT<"break">, BRK_FM_MM, ISA_MICROMIPS; + def SYSCALL_MM : MMRel, SYS_FT<"syscall", uimm10, II_SYSCALL>, SYS_FM_MM, + ISA_MICROMIPS; + def WAIT_MM : MMRel, WaitMM<"wait">, WAIT_FM_MM, ISA_MICROMIPS; + def ERET_MM : MMRel, ER_FT<"eret", II_ERET>, ER_FM_MM<0x3cd>, + ISA_MICROMIPS; + def DERET_MM : MMRel, ER_FT<"deret", II_DERET>, ER_FM_MM<0x38d>, + ISA_MICROMIPS; def EI_MM : MMRel, DEI_FT<"ei", GPR32Opnd, II_EI>, EI_FM_MM<0x15d>, - ISA_MIPS32R2; + ISA_MICROMIPS; def DI_MM : MMRel, DEI_FT<"di", GPR32Opnd, II_DI>, EI_FM_MM<0x11d>, - ISA_MIPS32R2; + ISA_MICROMIPS; + def TRAP_MM : TrapBase<BREAK_MM>, ISA_MICROMIPS; /// Trap Instructions - def TEQ_MM : MMRel, TEQ_FT<"teq", GPR32Opnd, uimm4, II_TEQ>, TEQ_FM_MM<0x0>; - def TGE_MM : MMRel, TEQ_FT<"tge", GPR32Opnd, uimm4, II_TGE>, TEQ_FM_MM<0x08>; + def TEQ_MM : MMRel, TEQ_FT<"teq", GPR32Opnd, uimm4, II_TEQ>, TEQ_FM_MM<0x0>, + ISA_MICROMIPS; + def TGE_MM : MMRel, TEQ_FT<"tge", GPR32Opnd, uimm4, II_TGE>, TEQ_FM_MM<0x08>, + ISA_MICROMIPS; def TGEU_MM : MMRel, TEQ_FT<"tgeu", GPR32Opnd, uimm4, II_TGEU>, - TEQ_FM_MM<0x10>; - def TLT_MM : MMRel, TEQ_FT<"tlt", GPR32Opnd, uimm4, II_TLT>, TEQ_FM_MM<0x20>; + TEQ_FM_MM<0x10>, ISA_MICROMIPS; + def TLT_MM : MMRel, TEQ_FT<"tlt", GPR32Opnd, uimm4, II_TLT>, TEQ_FM_MM<0x20>, + ISA_MICROMIPS; def TLTU_MM : MMRel, TEQ_FT<"tltu", GPR32Opnd, uimm4, II_TLTU>, - TEQ_FM_MM<0x28>; - def TNE_MM : MMRel, TEQ_FT<"tne", GPR32Opnd, uimm4, II_TNE>, TEQ_FM_MM<0x30>; + TEQ_FM_MM<0x28>, ISA_MICROMIPS; + def TNE_MM : MMRel, TEQ_FT<"tne", GPR32Opnd, uimm4, II_TNE>, TEQ_FM_MM<0x30>, + ISA_MICROMIPS; - def TEQI_MM : MMRel, TEQI_FT<"teqi", GPR32Opnd, II_TEQI>, TEQI_FM_MM<0x0e>; - def TGEI_MM : MMRel, TEQI_FT<"tgei", GPR32Opnd, II_TGEI>, TEQI_FM_MM<0x09>; + def TEQI_MM : MMRel, TEQI_FT<"teqi", GPR32Opnd, II_TEQI>, TEQI_FM_MM<0x0e>, + ISA_MICROMIPS32_NOT_MIPS32R6; + def TGEI_MM : MMRel, TEQI_FT<"tgei", GPR32Opnd, II_TGEI>, TEQI_FM_MM<0x09>, + ISA_MICROMIPS32_NOT_MIPS32R6; def TGEIU_MM : MMRel, TEQI_FT<"tgeiu", GPR32Opnd, II_TGEIU>, - TEQI_FM_MM<0x0b>; - def TLTI_MM : MMRel, TEQI_FT<"tlti", GPR32Opnd, II_TLTI>, TEQI_FM_MM<0x08>; + TEQI_FM_MM<0x0b>, ISA_MICROMIPS32_NOT_MIPS32R6; + def TLTI_MM : MMRel, TEQI_FT<"tlti", GPR32Opnd, II_TLTI>, TEQI_FM_MM<0x08>, + ISA_MICROMIPS32_NOT_MIPS32R6; def TLTIU_MM : MMRel, TEQI_FT<"tltiu", GPR32Opnd, II_TTLTIU>, - TEQI_FM_MM<0x0a>; - def TNEI_MM : MMRel, TEQI_FT<"tnei", GPR32Opnd, II_TNEI>, TEQI_FM_MM<0x0c>; + TEQI_FM_MM<0x0a>, ISA_MICROMIPS32_NOT_MIPS32R6; + def TNEI_MM : MMRel, TEQI_FT<"tnei", GPR32Opnd, II_TNEI>, TEQI_FM_MM<0x0c>, + ISA_MICROMIPS32_NOT_MIPS32R6; /// Load-linked, Store-conditional - def LL_MM : LLBaseMM<"ll", GPR32Opnd>, LL_FM_MM<0x3>; - def SC_MM : SCBaseMM<"sc", GPR32Opnd>, LL_FM_MM<0xb>; + def LL_MM : LLBaseMM<"ll", GPR32Opnd>, LL_FM_MM<0x3>, + ISA_MICROMIPS32_NOT_MIPS32R6; + def SC_MM : SCBaseMM<"sc", GPR32Opnd>, LL_FM_MM<0xb>, + ISA_MICROMIPS32_NOT_MIPS32R6; - def LLE_MM : LLEBaseMM<"lle", GPR32Opnd>, LLE_FM_MM<0x6>; - def SCE_MM : SCEBaseMM<"sce", GPR32Opnd>, LLE_FM_MM<0xA>; + def LLE_MM : MMRel, LLEBaseMM<"lle", GPR32Opnd>, LLE_FM_MM<0x6>, + ISA_MICROMIPS, ASE_EVA; + def SCE_MM : MMRel, SCEBaseMM<"sce", GPR32Opnd>, LLE_FM_MM<0xA>, + ISA_MICROMIPS, ASE_EVA; let DecoderMethod = "DecodeCacheOpMM" in { - def CACHE_MM : MMRel, CacheOp<"cache", mem_mm_12, II_CACHE>, - CACHE_PREF_FM_MM<0x08, 0x6>; - def PREF_MM : MMRel, CacheOp<"pref", mem_mm_12, II_PREF>, - CACHE_PREF_FM_MM<0x18, 0x2>; + def CACHE_MM : MMRel, CacheOp<"cache", mem_mm_12, II_CACHE>, + CACHE_PREF_FM_MM<0x08, 0x6>, ISA_MICROMIPS32_NOT_MIPS32R6; + def PREF_MM : MMRel, CacheOp<"pref", mem_mm_12, II_PREF>, + CACHE_PREF_FM_MM<0x18, 0x2>, ISA_MICROMIPS32_NOT_MIPS32R6; } let DecoderMethod = "DecodePrefeOpMM" in { def PREFE_MM : MMRel, CacheOp<"prefe", mem_mm_9, II_PREFE>, - CACHE_PREFE_FM_MM<0x18, 0x2>; + CACHE_PREFE_FM_MM<0x18, 0x2>, ISA_MICROMIPS, ASE_EVA; def CACHEE_MM : MMRel, CacheOp<"cachee", mem_mm_9, II_CACHEE>, - CACHE_PREFE_FM_MM<0x18, 0x3>; + CACHE_PREFE_FM_MM<0x18, 0x3>, ISA_MICROMIPS, ASE_EVA; } - def SSNOP_MM : MMRel, Barrier<"ssnop", II_SSNOP>, BARRIER_FM_MM<0x1>; - def EHB_MM : MMRel, Barrier<"ehb", II_EHB>, BARRIER_FM_MM<0x3>; - def PAUSE_MM : MMRel, Barrier<"pause", II_PAUSE>, BARRIER_FM_MM<0x5>; - - def TLBP_MM : MMRel, TLB<"tlbp", II_TLBP>, COP0_TLB_FM_MM<0x0d>; - def TLBR_MM : MMRel, TLB<"tlbr", II_TLBR>, COP0_TLB_FM_MM<0x4d>; - def TLBWI_MM : MMRel, TLB<"tlbwi", II_TLBWI>, COP0_TLB_FM_MM<0x8d>; - def TLBWR_MM : MMRel, TLB<"tlbwr", II_TLBWR>, COP0_TLB_FM_MM<0xcd>; - - def SDBBP_MM : MMRel, SYS_FT<"sdbbp", uimm10, II_SDBBP>, SDBBP_FM_MM; - - def PREFX_MM : PrefetchIndexed<"prefx">, POOL32F_PREFX_FM_MM<0x15, 0x1A0>; + def SSNOP_MM : MMRel, Barrier<"ssnop", II_SSNOP>, BARRIER_FM_MM<0x1>, + ISA_MICROMIPS; + def EHB_MM : MMRel, Barrier<"ehb", II_EHB>, BARRIER_FM_MM<0x3>, + ISA_MICROMIPS; + def PAUSE_MM : MMRel, Barrier<"pause", II_PAUSE>, BARRIER_FM_MM<0x5>, + ISA_MICROMIPS; + + def TLBP_MM : MMRel, TLB<"tlbp", II_TLBP>, COP0_TLB_FM_MM<0x0d>, + ISA_MICROMIPS; + def TLBR_MM : MMRel, TLB<"tlbr", II_TLBR>, COP0_TLB_FM_MM<0x4d>, + ISA_MICROMIPS; + def TLBWI_MM : MMRel, TLB<"tlbwi", II_TLBWI>, COP0_TLB_FM_MM<0x8d>, + ISA_MICROMIPS; + def TLBWR_MM : MMRel, TLB<"tlbwr", II_TLBWR>, COP0_TLB_FM_MM<0xcd>, + ISA_MICROMIPS; + + def SDBBP_MM : MMRel, SYS_FT<"sdbbp", uimm10, II_SDBBP>, SDBBP_FM_MM, + ISA_MICROMIPS; + + def PREFX_MM : PrefetchIndexed<"prefx">, POOL32F_PREFX_FM_MM<0x15, 0x1A0>, + ISA_MICROMIPS32_NOT_MIPS32R6; } def TAILCALL_MM : TailCall<J_MM, jmptarget_mm>, ISA_MIPS1_NOT_32R6_64R6; +def TAILCALLREG_MM : TailCallReg<JRC16_MM, GPR32Opnd>, + ISA_MICROMIPS32_NOT_MIPS32R6; + +def PseudoIndirectBranch_MM : PseudoIndirectBranchBase<JR_MM, GPR32Opnd>, + ISA_MICROMIPS32_NOT_MIPS32R6; + let DecoderNamespace = "MicroMips" in { def RDHWR_MM : MMRel, R6MMR6Rel, ReadHardware<GPR32Opnd, HWRegsOpnd>, RDHWR_FM_MM, ISA_MICROMIPS32_NOT_MIPS32R6; @@ -1011,89 +1132,177 @@ let DecoderNamespace = "MicroMips" in { ISA_MICROMIPS32_NOT_MIPS32R6; } +let DecoderNamespace = "MicroMips" in { + def MFGC0_MM : MMRel, MfCop0MM<"mfgc0", GPR32Opnd, COP0Opnd, II_MFGC0>, + POOL32A_MFTC0_FM_MM<0b10011, 0b111100>, + ISA_MICROMIPS32R5, ASE_VIRT; + def MFHGC0_MM : MMRel, MfCop0MM<"mfhgc0", GPR32Opnd, COP0Opnd, II_MFHGC0>, + POOL32A_MFTC0_FM_MM<0b10011, 0b110100>, + ISA_MICROMIPS32R5, ASE_VIRT; + def MTGC0_MM : MMRel, MtCop0MM<"mtgc0", COP0Opnd, GPR32Opnd, II_MTGC0>, + POOL32A_MFTC0_FM_MM<0b11011, 0b111100>, + ISA_MICROMIPS32R5, ASE_VIRT; + def MTHGC0_MM : MMRel, MtCop0MM<"mthgc0", COP0Opnd, GPR32Opnd, II_MTHGC0>, + POOL32A_MFTC0_FM_MM<0b11011, 0b110100>, + ISA_MICROMIPS32R5, ASE_VIRT; + def HYPCALL_MM : MMRel, HypcallMM<"hypcall">, POOL32A_HYPCALL_FM_MM, + ISA_MICROMIPS32R5, ASE_VIRT; + def TLBGINV_MM : MMRel, TLBINVMM<"tlbginv", II_TLBGINV>, + POOL32A_TLBINV_FM_MM<0x105>, ISA_MICROMIPS32R5, ASE_VIRT; + def TLBGINVF_MM : MMRel, TLBINVMM<"tlbginvf", II_TLBGINVF>, + POOL32A_TLBINV_FM_MM<0x145>, ISA_MICROMIPS32R5, ASE_VIRT; + def TLBGP_MM : MMRel, TLBINVMM<"tlbgp", II_TLBGP>, + POOL32A_TLBINV_FM_MM<0x5>, ISA_MICROMIPS32R5, ASE_VIRT; + def TLBGR_MM : MMRel, TLBINVMM<"tlbgr", II_TLBGR>, + POOL32A_TLBINV_FM_MM<0x45>, ISA_MICROMIPS32R5, ASE_VIRT; + def TLBGWI_MM : MMRel, TLBINVMM<"tlbgwi", II_TLBGWI>, + POOL32A_TLBINV_FM_MM<0x85>, ISA_MICROMIPS32R5, ASE_VIRT; + def TLBGWR_MM : MMRel, TLBINVMM<"tlbgwr", II_TLBGWR>, + POOL32A_TLBINV_FM_MM<0xc5>, ISA_MICROMIPS32R5, ASE_VIRT; +} + //===----------------------------------------------------------------------===// // MicroMips arbitrary patterns that map to one or more instructions //===----------------------------------------------------------------------===// -let AdditionalPredicates = [InMicroMips] in { - def : MipsPat<(i32 immLi16:$imm), - (LI16_MM immLi16:$imm)>; - - defm : MaterializeImms<i32, ZERO, ADDiu_MM, LUi_MM, ORi_MM>; -} - -let Predicates = [InMicroMips] in { - 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)>; -} +defm : MipsHiLoRelocs<LUi_MM, ADDiu_MM, ZERO, GPR32Opnd>, ISA_MICROMIPS; + +def : MipsPat<(MipsGotHi tglobaladdr:$in), (LUi_MM tglobaladdr:$in)>, + ISA_MICROMIPS; +def : MipsPat<(MipsGotHi texternalsym:$in), (LUi_MM texternalsym:$in)>, + ISA_MICROMIPS; + +def : MipsPat<(MipsTlsHi tglobaltlsaddr:$in), (LUi_MM tglobaltlsaddr:$in)>, + ISA_MICROMIPS; + +// gp_rel relocs +def : MipsPat<(add GPR32:$gp, (MipsGPRel tglobaladdr:$in)), + (ADDiu_MM GPR32:$gp, tglobaladdr:$in)>, ISA_MICROMIPS; +def : MipsPat<(add GPR32:$gp, (MipsGPRel tconstpool:$in)), + (ADDiu_MM GPR32:$gp, tconstpool:$in)>, ISA_MICROMIPS; + +def : WrapperPat<tglobaladdr, ADDiu_MM, GPR32>, ISA_MICROMIPS; +def : WrapperPat<tconstpool, ADDiu_MM, GPR32>, ISA_MICROMIPS; +def : WrapperPat<texternalsym, ADDiu_MM, GPR32>, ISA_MICROMIPS; +def : WrapperPat<tblockaddress, ADDiu_MM, GPR32>, ISA_MICROMIPS; +def : WrapperPat<tjumptable, ADDiu_MM, GPR32>, ISA_MICROMIPS; +def : WrapperPat<tglobaltlsaddr, ADDiu_MM, GPR32>, ISA_MICROMIPS; + +def : MipsPat<(atomic_load_8 addr:$a), (LB_MM addr:$a)>, ISA_MICROMIPS; +def : MipsPat<(atomic_load_16 addr:$a), (LH_MM addr:$a)>, ISA_MICROMIPS; +def : MipsPat<(atomic_load_32 addr:$a), (LW_MM addr:$a)>, ISA_MICROMIPS; + +def : MipsPat<(i32 immLi16:$imm), + (LI16_MM immLi16:$imm)>, ISA_MICROMIPS; + +defm : MaterializeImms<i32, ZERO, ADDiu_MM, LUi_MM, ORi_MM>, ISA_MICROMIPS; + +def : MipsPat<(not GPRMM16:$in), + (NOT16_MM GPRMM16:$in)>, ISA_MICROMIPS; +def : MipsPat<(not GPR32:$in), + (NOR_MM GPR32Opnd:$in, ZERO)>, ISA_MICROMIPS; + +def : MipsPat<(add GPRMM16:$src, immSExtAddiur2:$imm), + (ADDIUR2_MM GPRMM16:$src, immSExtAddiur2:$imm)>, ISA_MICROMIPS; +def : MipsPat<(add GPR32:$src, immSExtAddius5:$imm), + (ADDIUS5_MM GPR32:$src, immSExtAddius5:$imm)>, ISA_MICROMIPS; +def : MipsPat<(add GPR32:$src, immSExt16:$imm), + (ADDiu_MM GPR32:$src, immSExt16:$imm)>, ISA_MICROMIPS; + +def : MipsPat<(and GPRMM16:$src, immZExtAndi16:$imm), + (ANDI16_MM GPRMM16:$src, immZExtAndi16:$imm)>, ISA_MICROMIPS; +def : MipsPat<(and GPR32:$src, immZExt16:$imm), + (ANDi_MM GPR32:$src, immZExt16:$imm)>, ISA_MICROMIPS; + +def : MipsPat<(shl GPRMM16:$src, immZExt2Shift:$imm), + (SLL16_MM GPRMM16:$src, immZExt2Shift:$imm)>, ISA_MICROMIPS; +def : MipsPat<(shl GPR32:$src, immZExt5:$imm), + (SLL_MM GPR32:$src, immZExt5:$imm)>, ISA_MICROMIPS; +def : MipsPat<(shl GPR32:$lhs, GPR32:$rhs), + (SLLV_MM GPR32:$lhs, GPR32:$rhs)>, ISA_MICROMIPS; + +def : MipsPat<(srl GPRMM16:$src, immZExt2Shift:$imm), + (SRL16_MM GPRMM16:$src, immZExt2Shift:$imm)>, ISA_MICROMIPS; +def : MipsPat<(srl GPR32:$src, immZExt5:$imm), + (SRL_MM GPR32:$src, immZExt5:$imm)>, ISA_MICROMIPS; +def : MipsPat<(srl GPR32:$lhs, GPR32:$rhs), + (SRLV_MM GPR32:$lhs, GPR32:$rhs)>, ISA_MICROMIPS; + +def : MipsPat<(sra GPR32:$src, immZExt5:$imm), + (SRA_MM GPR32:$src, immZExt5:$imm)>, ISA_MICROMIPS; +def : MipsPat<(sra GPR32:$lhs, GPR32:$rhs), + (SRAV_MM GPR32:$lhs, GPR32:$rhs)>, ISA_MICROMIPS; + +def : MipsPat<(store GPRMM16:$src, addrimm4lsl2:$addr), + (SW16_MM GPRMM16:$src, addrimm4lsl2:$addr)>, ISA_MICROMIPS; +def : MipsPat<(store GPR32:$src, addr:$addr), + (SW_MM GPR32:$src, addr:$addr)>, ISA_MICROMIPS; + +def : MipsPat<(load addrimm4lsl2:$addr), + (LW16_MM addrimm4lsl2:$addr)>, ISA_MICROMIPS; +def : MipsPat<(load addr:$addr), + (LW_MM addr:$addr)>, ISA_MICROMIPS; +def : MipsPat<(subc GPR32:$lhs, GPR32:$rhs), + (SUBu_MM GPR32:$lhs, GPR32:$rhs)>, ISA_MICROMIPS; + +def : MipsPat<(i32 (extloadi1 addr:$src)), (LBu_MM addr:$src)>, + ISA_MICROMIPS; + +def : MipsPat<(i32 (extloadi8 addr:$src)), (LBu_MM addr:$src)>, + ISA_MICROMIPS; + +def : MipsPat<(i32 (extloadi16 addr:$src)), (LHu_MM addr:$src)>, + ISA_MICROMIPS; + +let AddedComplexity = 40 in + def : MipsPat<(i32 (sextloadi16 addrRegImm:$a)), + (LH_MM addrRegImm:$a)>, ISA_MICROMIPS; + + +def : MipsPat<(bswap GPR32:$rt), (ROTR_MM (WSBH_MM GPR32:$rt), 16)>, + ISA_MICROMIPS; def : MipsPat<(MipsTailCall (iPTR tglobaladdr:$dst)), (TAILCALL_MM tglobaladdr:$dst)>, ISA_MICROMIPS32_NOT_MIPS32R6; def : MipsPat<(MipsTailCall (iPTR texternalsym:$dst)), (TAILCALL_MM texternalsym:$dst)>, ISA_MICROMIPS32_NOT_MIPS32R6; -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)>; - defm : BrcondPats<GPR32, BEQ_MM, BEQ_MM, BNE_MM, SLT_MM, SLTu_MM, SLTi_MM, - SLTiu_MM, ZERO>; + SLTiu_MM, ZERO>, ISA_MICROMIPS32_NOT_MIPS32R6; + +def : MipsPat<(brcond (i32 (setlt i32:$lhs, 1)), bb:$dst), + (BLEZ_MM i32:$lhs, bb:$dst)>, ISA_MICROMIPS32_NOT_MIPS32R6; +def : MipsPat<(brcond (i32 (setgt i32:$lhs, -1)), bb:$dst), + (BGEZ_MM i32:$lhs, bb:$dst)>, ISA_MICROMIPS32_NOT_MIPS32R6; + +defm : SeteqPats<GPR32, SLTiu_MM, XOR_MM, SLTu_MM, ZERO>, ISA_MICROMIPS; +defm : SetlePats<GPR32, XORi_MM, SLT_MM, SLTu_MM>, ISA_MICROMIPS; +defm : SetgtPats<GPR32, SLT_MM, SLTu_MM>, ISA_MICROMIPS; +defm : SetgePats<GPR32, XORi_MM, SLT_MM, SLTu_MM>, ISA_MICROMIPS; +defm : SetgeImmPats<GPR32, XORi_MM, SLTi_MM, SLTiu_MM>, ISA_MICROMIPS; + +// Select patterns + +// Instantiation of conditional move patterns. +defm : MovzPats0<GPR32, GPR32, MOVZ_I_MM, SLT_MM, SLTu_MM, SLTi_MM, SLTiu_MM>, + ISA_MICROMIPS32_NOT_MIPS32R6; +defm : MovzPats1<GPR32, GPR32, MOVZ_I_MM, XOR_MM>, + ISA_MICROMIPS32_NOT_MIPS32R6; +defm : MovzPats2<GPR32, GPR32, MOVZ_I_MM, XORi_MM>, + ISA_MICROMIPS32_NOT_MIPS32R6; -defm : SeteqPats<GPR32, SLTiu_MM, XOR_MM, SLTu_MM, ZERO>; -defm : SetlePats<GPR32, XORi_MM, SLT_MM, SLTu_MM>; -defm : SetgtPats<GPR32, SLT_MM, SLTu_MM>; -defm : SetgePats<GPR32, XORi_MM, SLT_MM, SLTu_MM>; -defm : SetgeImmPats<GPR32, XORi_MM, SLTi_MM, SLTiu_MM>; + +defm : MovnPats<GPR32, GPR32, MOVN_I_MM, XOR_MM>, INSN_MIPS4_32_NOT_32R6_64R6; + +// Instantiation of conditional move patterns. +defm : MovzPats0<GPR32, GPR32, MOVZ_I_MM, SLT_MM, SLTu_MM, SLTi_MM, SLTiu_MM>, + ISA_MICROMIPS32_NOT_MIPS32R6; +defm : MovzPats1<GPR32, GPR32, MOVZ_I_MM, XOR_MM>, + ISA_MICROMIPS32_NOT_MIPS32R6; +defm : MovzPats2<GPR32, GPR32, MOVZ_I_MM, XORi_MM>, + ISA_MICROMIPS32_NOT_MIPS32R6; + +defm : MovnPats<GPR32, GPR32, MOVN_I_MM, XOR_MM>, ISA_MICROMIPS32_NOT_MIPS32R6; //===----------------------------------------------------------------------===// // MicroMips instruction aliases @@ -1105,17 +1314,29 @@ class UncondBranchMMPseudo<string opstr> : def B_MM_Pseudo : UncondBranchMMPseudo<"b">, ISA_MICROMIPS; -let Predicates = [InMicroMips] in { +let EncodingPredicates = [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>; - def : MipsInstAlias<"ei", (EI_MM ZERO), 1>, ISA_MIPS32R2; - def : MipsInstAlias<"di", (DI_MM ZERO), 1>, ISA_MIPS32R2; + def : MipsInstAlias<"wait", (WAIT_MM 0x0), 1>, ISA_MICROMIPS; + def : MipsInstAlias<"nop", (SLL_MM ZERO, ZERO, 0), 1>, ISA_MICROMIPS; + def : MipsInstAlias<"nop", (MOVE16_MM ZERO, ZERO), 1>, ISA_MICROMIPS; + def : MipsInstAlias<"ei", (EI_MM ZERO), 1>, ISA_MICROMIPS; + def : MipsInstAlias<"di", (DI_MM ZERO), 1>, ISA_MICROMIPS; + def : MipsInstAlias<"neg $rt, $rs", + (SUB_MM GPR32Opnd:$rt, ZERO, GPR32Opnd:$rs), 1>, + ISA_MICROMIPS32_NOT_MIPS32R6; + def : MipsInstAlias<"neg $rt", + (SUB_MM GPR32Opnd:$rt, ZERO, GPR32Opnd:$rt), 1>, + ISA_MICROMIPS32_NOT_MIPS32R6; + def : MipsInstAlias<"negu $rt, $rs", + (SUBu_MM GPR32Opnd:$rt, ZERO, GPR32Opnd:$rs), 1>, + ISA_MICROMIPS32_NOT_MIPS32R6; + def : MipsInstAlias<"negu $rt", + (SUBu_MM GPR32Opnd:$rt, ZERO, GPR32Opnd:$rt), 1>, + ISA_MICROMIPS32_NOT_MIPS32R6; def : MipsInstAlias<"teq $rs, $rt", (TEQ_MM GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>; def : MipsInstAlias<"tge $rs, $rt", @@ -1160,32 +1381,64 @@ let Predicates = [InMicroMips] in { (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<"syscall", (SYSCALL_MM 0), 1>, ISA_MICROMIPS; - defm : OneOrTwoOperandMacroImmediateAlias<"add", ADDi_MM>; + def : MipsInstAlias<"sync", (SYNC_MM 0), 1>, ISA_MICROMIPS; - defm : OneOrTwoOperandMacroImmediateAlias<"addu", ADDiu_MM>; + defm : OneOrTwoOperandMacroImmediateAlias<"add", ADDi_MM>, ISA_MICROMIPS; - defm : OneOrTwoOperandMacroImmediateAlias<"and", ANDi_MM>; + defm : OneOrTwoOperandMacroImmediateAlias<"addu", ADDiu_MM>, ISA_MICROMIPS; - defm : OneOrTwoOperandMacroImmediateAlias<"or", ORi_MM>; + defm : OneOrTwoOperandMacroImmediateAlias<"and", ANDi_MM>, ISA_MICROMIPS; - defm : OneOrTwoOperandMacroImmediateAlias<"xor", XORi_MM>; + defm : OneOrTwoOperandMacroImmediateAlias<"or", ORi_MM>, ISA_MICROMIPS; - defm : OneOrTwoOperandMacroImmediateAlias<"slt", SLTi_MM>; + defm : OneOrTwoOperandMacroImmediateAlias<"xor", XORi_MM>, ISA_MICROMIPS; - defm : OneOrTwoOperandMacroImmediateAlias<"sltu", SLTiu_MM>; + defm : OneOrTwoOperandMacroImmediateAlias<"slt", SLTi_MM>, ISA_MICROMIPS; + + defm : OneOrTwoOperandMacroImmediateAlias<"sltu", SLTiu_MM>, ISA_MICROMIPS; def : MipsInstAlias<"not $rt, $rs", - (NOR_MM GPR32Opnd:$rt, GPR32Opnd:$rs, ZERO), 0>; + (NOR_MM GPR32Opnd:$rt, GPR32Opnd:$rs, ZERO), 0>, + ISA_MICROMIPS32_NOT_MIPS32R6; def : MipsInstAlias<"not $rt", - (NOR_MM GPR32Opnd:$rt, GPR32Opnd:$rt, ZERO), 0>; + (NOR_MM GPR32Opnd:$rt, GPR32Opnd:$rt, ZERO), 0>, + ISA_MICROMIPS32_NOT_MIPS32R6; def : MipsInstAlias<"bnez $rs,$offset", - (BNE_MM GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>; + (BNE_MM GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>, + ISA_MICROMIPS; def : MipsInstAlias<"beqz $rs,$offset", - (BEQ_MM GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>; + (BEQ_MM GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>, + ISA_MICROMIPS; def : MipsInstAlias<"seh $rd", (SEH_MM GPR32Opnd:$rd, GPR32Opnd:$rd), 0>, - ISA_MIPS32R2_NOT_32R6_64R6; + ISA_MICROMIPS; def : MipsInstAlias<"seb $rd", (SEB_MM GPR32Opnd:$rd, GPR32Opnd:$rd), 0>, - ISA_MIPS32R2_NOT_32R6_64R6; -} + ISA_MICROMIPS; + def : MipsInstAlias<"break", (BREAK_MM 0, 0), 1>, ISA_MICROMIPS; + def : MipsInstAlias<"break $imm", (BREAK_MM uimm10:$imm, 0), 1>, + ISA_MICROMIPS; + def : MipsInstAlias<"bal $offset", (BGEZAL_MM ZERO, brtarget_mm:$offset), 1>, + ISA_MICROMIPS32_NOT_MIPS32R6; + + def : MipsInstAlias<"j $rs", (JR_MM GPR32Opnd:$rs), 0>, + ISA_MICROMIPS32_NOT_MIPS32R6; +} +def : MipsInstAlias<"rdhwr $rt, $rs", + (RDHWR_MM GPR32Opnd:$rt, HWRegsOpnd:$rs, 0), 1>, + ISA_MICROMIPS32_NOT_MIPS32R6; + +def : MipsInstAlias<"hypcall", (HYPCALL_MM 0), 1>, + ISA_MICROMIPS32R5, ASE_VIRT; +def : MipsInstAlias<"mfgc0 $rt, $rs", + (MFGC0_MM GPR32Opnd:$rt, COP0Opnd:$rs, 0), 0>, + ISA_MICROMIPS32R5, ASE_VIRT; +def : MipsInstAlias<"mfhgc0 $rt, $rs", + (MFHGC0_MM GPR32Opnd:$rt, COP0Opnd:$rs, 0), 0>, + ISA_MICROMIPS32R5, ASE_VIRT; +def : MipsInstAlias<"mtgc0 $rt, $rs", + (MTGC0_MM COP0Opnd:$rs, GPR32Opnd:$rt, 0), 0>, + ISA_MICROMIPS32R5, ASE_VIRT; +def : MipsInstAlias<"mthgc0 $rt, $rs", + (MTHGC0_MM COP0Opnd:$rs, GPR32Opnd:$rt, 0), 0>, + ISA_MICROMIPS32R5, ASE_VIRT; diff --git a/lib/Target/Mips/MicroMipsSizeReduction.cpp b/lib/Target/Mips/MicroMipsSizeReduction.cpp index f2e014084e46..568cdfb5b110 100644 --- a/lib/Target/Mips/MicroMipsSizeReduction.cpp +++ b/lib/Target/Mips/MicroMipsSizeReduction.cpp @@ -10,7 +10,6 @@ /// This pass is used to reduce the size of instructions where applicable. /// /// TODO: Implement microMIPS64 support. -/// TODO: Implement support for reducing into lwp/swp instruction. //===----------------------------------------------------------------------===// #include "Mips.h" #include "MipsInstrInfo.h" @@ -22,8 +21,10 @@ using namespace llvm; #define DEBUG_TYPE "micromips-reduce-size" +#define MICROMIPS_SIZE_REDUCE_NAME "MicroMips instruction size reduce pass" -STATISTIC(NumReduced, "Number of 32-bit instructions reduced to 16-bit ones"); +STATISTIC(NumReduced, "Number of instructions reduced (32-bit to 16-bit ones, " + "or two instructions into one"); namespace { @@ -35,12 +36,15 @@ enum OperandTransfer { OT_Operands02, ///< Transfer operands 0 and 2 OT_Operand2, ///< Transfer just operand 2 OT_OperandsXOR, ///< Transfer operands for XOR16 + OT_OperandsLwp, ///< Transfer operands for LWP + OT_OperandsSwp, ///< Transfer operands for SWP }; /// Reduction type // TODO: Will be extended when additional optimizations are added enum ReduceType { - RT_OneInstr ///< Reduce one instruction into a smaller instruction + RT_TwoInstr, ///< Reduce two instructions into one instruction + RT_OneInstr ///< Reduce one instruction into a smaller instruction }; // Information about immediate field restrictions @@ -76,21 +80,22 @@ struct OpCodes { unsigned NarrowOpc; ///< Narrow opcode }; +typedef struct ReduceEntryFunArgs ReduceEntryFunArgs; + /// ReduceTable - A static table with information on mapping from wide /// opcodes to narrow struct ReduceEntry { enum ReduceType eRType; ///< Reduction type bool (*ReduceFunction)( - MachineInstr *MI, - const ReduceEntry &Entry); ///< Pointer to reduce function - struct OpCodes Ops; ///< All relevant OpCodes - struct OpInfo OpInf; ///< Characteristics of operands - struct ImmField Imm; ///< Characteristics of immediate field + ReduceEntryFunArgs *Arguments); ///< Pointer to reduce function + struct OpCodes Ops; ///< All relevant OpCodes + struct OpInfo OpInf; ///< Characteristics of operands + struct ImmField Imm; ///< Characteristics of immediate field ReduceEntry(enum ReduceType RType, struct OpCodes Op, - bool (*F)(MachineInstr *MI, const ReduceEntry &Entry), - struct OpInfo OpInf, struct ImmField Imm) + bool (*F)(ReduceEntryFunArgs *Arguments), struct OpInfo OpInf, + struct ImmField Imm) : eRType(RType), ReduceFunction(F), Ops(Op), OpInf(OpInf), Imm(Imm) {} unsigned NarrowOpc() const { return Ops.NarrowOpc; } @@ -113,6 +118,20 @@ struct ReduceEntry { } }; +// Function arguments for ReduceFunction +struct ReduceEntryFunArgs { + MachineInstr *MI; // Instruction + const ReduceEntry &Entry; // Entry field + MachineBasicBlock::instr_iterator + &NextMII; // Iterator to next instruction in block + + ReduceEntryFunArgs(MachineInstr *argMI, const ReduceEntry &argEntry, + MachineBasicBlock::instr_iterator &argNextMII) + : MI(argMI), Entry(argEntry), NextMII(argNextMII) {} +}; + +typedef llvm::SmallVector<ReduceEntry, 32> ReduceEntryVector; + class MicroMipsSizeReduce : public MachineFunctionPass { public: static char ID; @@ -132,42 +151,50 @@ private: bool ReduceMBB(MachineBasicBlock &MBB); /// Attempts to reduce MI, returns true on success. - bool ReduceMI(const MachineBasicBlock::instr_iterator &MII); + bool ReduceMI(const MachineBasicBlock::instr_iterator &MII, + MachineBasicBlock::instr_iterator &NextMII); // Attempts to reduce LW/SW instruction into LWSP/SWSP, // returns true on success. - static bool ReduceXWtoXWSP(MachineInstr *MI, const ReduceEntry &Entry); + static bool ReduceXWtoXWSP(ReduceEntryFunArgs *Arguments); + + // Attempts to reduce two LW/SW instructions into LWP/SWP instruction, + // returns true on success. + static bool ReduceXWtoXWP(ReduceEntryFunArgs *Arguments); // Attempts to reduce LBU/LHU instruction into LBU16/LHU16, // returns true on success. - static bool ReduceLXUtoLXU16(MachineInstr *MI, const ReduceEntry &Entry); + static bool ReduceLXUtoLXU16(ReduceEntryFunArgs *Arguments); // Attempts to reduce SB/SH instruction into SB16/SH16, // returns true on success. - static bool ReduceSXtoSX16(MachineInstr *MI, const ReduceEntry &Entry); + static bool ReduceSXtoSX16(ReduceEntryFunArgs *Arguments); // Attempts to reduce arithmetic instructions, returns true on success. - static bool ReduceArithmeticInstructions(MachineInstr *MI, - const ReduceEntry &Entry); + static bool ReduceArithmeticInstructions(ReduceEntryFunArgs *Arguments); // Attempts to reduce ADDIU into ADDIUSP instruction, // returns true on success. - static bool ReduceADDIUToADDIUSP(MachineInstr *MI, const ReduceEntry &Entry); + static bool ReduceADDIUToADDIUSP(ReduceEntryFunArgs *Arguments); // Attempts to reduce ADDIU into ADDIUR1SP instruction, // returns true on success. - static bool ReduceADDIUToADDIUR1SP(MachineInstr *MI, - const ReduceEntry &Entry); + static bool ReduceADDIUToADDIUR1SP(ReduceEntryFunArgs *Arguments); // Attempts to reduce XOR into XOR16 instruction, // returns true on success. - static bool ReduceXORtoXOR16(MachineInstr *MI, const ReduceEntry &Entry); + static bool ReduceXORtoXOR16(ReduceEntryFunArgs *Arguments); - // Changes opcode of an instruction. - static bool ReplaceInstruction(MachineInstr *MI, const ReduceEntry &Entry); + // Changes opcode of an instruction, replaces an instruction with a + // new one, or replaces two instructions with a new instruction + // depending on their order i.e. if these are consecutive forward + // or consecutive backward + static bool ReplaceInstruction(MachineInstr *MI, const ReduceEntry &Entry, + MachineInstr *MI2 = nullptr, + bool ConsecutiveForward = true); // Table with transformation rules for each instruction. - static llvm::SmallVector<ReduceEntry, 16> ReduceTable; + static ReduceEntryVector ReduceTable; }; char MicroMipsSizeReduce::ID = 0; @@ -175,7 +202,7 @@ const MipsInstrInfo *MicroMipsSizeReduce::MipsII; // This table must be sorted by WideOpc as a main criterion and // ReduceType as a sub-criterion (when wide opcodes are the same). -llvm::SmallVector<ReduceEntry, 16> MicroMipsSizeReduce::ReduceTable = { +ReduceEntryVector MicroMipsSizeReduce::ReduceTable = { // ReduceType, OpCodes, ReduceFunction, // OpInfo(TransferOperands), @@ -200,12 +227,20 @@ llvm::SmallVector<ReduceEntry, 16> MicroMipsSizeReduce::ReduceTable = { OpInfo(OT_OperandsAll), ImmField(0, -1, 15, 2)}, {RT_OneInstr, OpCodes(Mips::LEA_ADDiu, Mips::ADDIUR1SP_MM), ReduceADDIUToADDIUR1SP, OpInfo(OT_Operands02), ImmField(2, 0, 64, 2)}, + {RT_OneInstr, OpCodes(Mips::LEA_ADDiu_MM, Mips::ADDIUR1SP_MM), + ReduceADDIUToADDIUR1SP, OpInfo(OT_Operands02), ImmField(2, 0, 64, 2)}, {RT_OneInstr, OpCodes(Mips::LHu, Mips::LHU16_MM), ReduceLXUtoLXU16, OpInfo(OT_OperandsAll), ImmField(1, 0, 16, 2)}, {RT_OneInstr, OpCodes(Mips::LHu_MM, Mips::LHU16_MM), ReduceLXUtoLXU16, OpInfo(OT_OperandsAll), ImmField(1, 0, 16, 2)}, + {RT_TwoInstr, OpCodes(Mips::LW, Mips::LWP_MM), ReduceXWtoXWP, + OpInfo(OT_OperandsLwp), ImmField(0, -2048, 2048, 2)}, {RT_OneInstr, OpCodes(Mips::LW, Mips::LWSP_MM), ReduceXWtoXWSP, OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)}, + {RT_TwoInstr, OpCodes(Mips::LW16_MM, Mips::LWP_MM), ReduceXWtoXWP, + OpInfo(OT_OperandsLwp), ImmField(0, -2048, 2048, 2)}, + {RT_TwoInstr, OpCodes(Mips::LW_MM, Mips::LWP_MM), ReduceXWtoXWP, + OpInfo(OT_OperandsLwp), ImmField(0, -2048, 2048, 2)}, {RT_OneInstr, OpCodes(Mips::LW_MM, Mips::LWSP_MM), ReduceXWtoXWSP, OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)}, {RT_OneInstr, OpCodes(Mips::SB, Mips::SB16_MM), ReduceSXtoSX16, @@ -222,15 +257,24 @@ llvm::SmallVector<ReduceEntry, 16> MicroMipsSizeReduce::ReduceTable = { {RT_OneInstr, OpCodes(Mips::SUBu_MM, Mips::SUBU16_MM), ReduceArithmeticInstructions, OpInfo(OT_OperandsAll), ImmField(0, 0, 0, -1)}, + {RT_TwoInstr, OpCodes(Mips::SW, Mips::SWP_MM), ReduceXWtoXWP, + OpInfo(OT_OperandsSwp), ImmField(0, -2048, 2048, 2)}, {RT_OneInstr, OpCodes(Mips::SW, Mips::SWSP_MM), ReduceXWtoXWSP, OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)}, + {RT_TwoInstr, OpCodes(Mips::SW16_MM, Mips::SWP_MM), ReduceXWtoXWP, + OpInfo(OT_OperandsSwp), ImmField(0, -2048, 2048, 2)}, + {RT_TwoInstr, OpCodes(Mips::SW_MM, Mips::SWP_MM), ReduceXWtoXWP, + OpInfo(OT_OperandsSwp), ImmField(0, -2048, 2048, 2)}, {RT_OneInstr, OpCodes(Mips::SW_MM, Mips::SWSP_MM), ReduceXWtoXWSP, OpInfo(OT_OperandsAll), ImmField(2, 0, 32, 2)}, {RT_OneInstr, OpCodes(Mips::XOR, Mips::XOR16_MM), ReduceXORtoXOR16, OpInfo(OT_OperandsXOR), ImmField(0, 0, 0, -1)}, {RT_OneInstr, OpCodes(Mips::XOR_MM, Mips::XOR16_MM), ReduceXORtoXOR16, OpInfo(OT_OperandsXOR), ImmField(0, 0, 0, -1)}}; -} // namespace +} // end anonymous namespace + +INITIALIZE_PASS(MicroMipsSizeReduce, DEBUG_TYPE, MICROMIPS_SIZE_REDUCE_NAME, + false, false) // Returns true if the machine operand MO is register SP. static bool IsSP(const MachineOperand &MO) { @@ -297,37 +341,100 @@ static bool ImmInRange(MachineInstr *MI, const ReduceEntry &Entry) { return true; } +// Returns true if MI can be reduced to lwp/swp instruction +static bool CheckXWPInstr(MachineInstr *MI, bool ReduceToLwp, + const ReduceEntry &Entry) { + + if (ReduceToLwp && + !(MI->getOpcode() == Mips::LW || MI->getOpcode() == Mips::LW_MM || + MI->getOpcode() == Mips::LW16_MM)) + return false; + + if (!ReduceToLwp && + !(MI->getOpcode() == Mips::SW || MI->getOpcode() == Mips::SW_MM || + MI->getOpcode() == Mips::SW16_MM)) + return false; + + unsigned reg = MI->getOperand(0).getReg(); + if (reg == Mips::RA) + return false; + + if (!ImmInRange(MI, Entry)) + return false; + + if (ReduceToLwp && (MI->getOperand(0).getReg() == MI->getOperand(1).getReg())) + return false; + + return true; +} + +// Returns true if the registers Reg1 and Reg2 are consecutive +static bool ConsecutiveRegisters(unsigned Reg1, unsigned Reg2) { + static SmallVector<unsigned, 31> Registers = { + Mips::AT, Mips::V0, Mips::V1, Mips::A0, Mips::A1, Mips::A2, Mips::A3, + Mips::T0, Mips::T1, Mips::T2, Mips::T3, Mips::T4, Mips::T5, Mips::T6, + Mips::T7, Mips::S0, Mips::S1, Mips::S2, Mips::S3, Mips::S4, Mips::S5, + Mips::S6, Mips::S7, Mips::T8, Mips::T9, Mips::K0, Mips::K1, Mips::GP, + Mips::SP, Mips::FP, Mips::RA}; + + for (uint8_t i = 0; i < Registers.size() - 1; i++) { + if (Registers[i] == Reg1) { + if (Registers[i + 1] == Reg2) + return true; + else + return false; + } + } + return false; +} + +// Returns true if registers and offsets are consecutive +static bool ConsecutiveInstr(MachineInstr *MI1, MachineInstr *MI2) { + + int64_t Offset1, Offset2; + if (!GetImm(MI1, 2, Offset1)) + return false; + if (!GetImm(MI2, 2, Offset2)) + return false; + + unsigned Reg1 = MI1->getOperand(0).getReg(); + unsigned Reg2 = MI2->getOperand(0).getReg(); + + return ((Offset1 == (Offset2 - 4)) && (ConsecutiveRegisters(Reg1, Reg2))); +} + MicroMipsSizeReduce::MicroMipsSizeReduce() : MachineFunctionPass(ID) {} -bool MicroMipsSizeReduce::ReduceMI( - const MachineBasicBlock::instr_iterator &MII) { +bool MicroMipsSizeReduce::ReduceMI(const MachineBasicBlock::instr_iterator &MII, + MachineBasicBlock::instr_iterator &NextMII) { MachineInstr *MI = &*MII; unsigned Opcode = MI->getOpcode(); // Search the table. - llvm::SmallVector<ReduceEntry, 16>::const_iterator Start = - std::begin(ReduceTable); - llvm::SmallVector<ReduceEntry, 16>::const_iterator End = - std::end(ReduceTable); + ReduceEntryVector::const_iterator Start = std::begin(ReduceTable); + ReduceEntryVector::const_iterator End = std::end(ReduceTable); - std::pair<llvm::SmallVector<ReduceEntry, 16>::const_iterator, - llvm::SmallVector<ReduceEntry, 16>::const_iterator> + std::pair<ReduceEntryVector::const_iterator, + ReduceEntryVector::const_iterator> Range = std::equal_range(Start, End, Opcode); if (Range.first == Range.second) return false; - for (llvm::SmallVector<ReduceEntry, 16>::const_iterator Entry = Range.first; - Entry != Range.second; ++Entry) - if (((*Entry).ReduceFunction)(&(*MII), *Entry)) + for (ReduceEntryVector::const_iterator Entry = Range.first; + Entry != Range.second; ++Entry) { + ReduceEntryFunArgs Arguments(&(*MII), *Entry, NextMII); + if (((*Entry).ReduceFunction)(&Arguments)) return true; - + } return false; } -bool MicroMipsSizeReduce::ReduceXWtoXWSP(MachineInstr *MI, - const ReduceEntry &Entry) { +bool MicroMipsSizeReduce::ReduceXWtoXWSP(ReduceEntryFunArgs *Arguments) { + + MachineInstr *MI = Arguments->MI; + const ReduceEntry &Entry = Arguments->Entry; if (!ImmInRange(MI, Entry)) return false; @@ -338,8 +445,51 @@ bool MicroMipsSizeReduce::ReduceXWtoXWSP(MachineInstr *MI, return ReplaceInstruction(MI, Entry); } +bool MicroMipsSizeReduce::ReduceXWtoXWP(ReduceEntryFunArgs *Arguments) { + + const ReduceEntry &Entry = Arguments->Entry; + MachineBasicBlock::instr_iterator &NextMII = Arguments->NextMII; + const MachineBasicBlock::instr_iterator &E = + Arguments->MI->getParent()->instr_end(); + + if (NextMII == E) + return false; + + MachineInstr *MI1 = Arguments->MI; + MachineInstr *MI2 = &*NextMII; + + // ReduceToLwp = true/false - reduce to LWP/SWP instruction + bool ReduceToLwp = (MI1->getOpcode() == Mips::LW) || + (MI1->getOpcode() == Mips::LW_MM) || + (MI1->getOpcode() == Mips::LW16_MM); + + if (!CheckXWPInstr(MI1, ReduceToLwp, Entry)) + return false; + + if (!CheckXWPInstr(MI2, ReduceToLwp, Entry)) + return false; + + unsigned Reg1 = MI1->getOperand(1).getReg(); + unsigned Reg2 = MI2->getOperand(1).getReg(); + + if (Reg1 != Reg2) + return false; + + bool ConsecutiveForward = ConsecutiveInstr(MI1, MI2); + bool ConsecutiveBackward = ConsecutiveInstr(MI2, MI1); + + if (!(ConsecutiveForward || ConsecutiveBackward)) + return false; + + NextMII = std::next(NextMII); + return ReplaceInstruction(MI1, Entry, MI2, ConsecutiveForward); +} + bool MicroMipsSizeReduce::ReduceArithmeticInstructions( - MachineInstr *MI, const ReduceEntry &Entry) { + ReduceEntryFunArgs *Arguments) { + + MachineInstr *MI = Arguments->MI; + const ReduceEntry &Entry = Arguments->Entry; if (!isMMThreeBitGPRegister(MI->getOperand(0)) || !isMMThreeBitGPRegister(MI->getOperand(1)) || @@ -349,8 +499,11 @@ bool MicroMipsSizeReduce::ReduceArithmeticInstructions( return ReplaceInstruction(MI, Entry); } -bool MicroMipsSizeReduce::ReduceADDIUToADDIUR1SP(MachineInstr *MI, - const ReduceEntry &Entry) { +bool MicroMipsSizeReduce::ReduceADDIUToADDIUR1SP( + ReduceEntryFunArgs *Arguments) { + + MachineInstr *MI = Arguments->MI; + const ReduceEntry &Entry = Arguments->Entry; if (!ImmInRange(MI, Entry)) return false; @@ -361,8 +514,10 @@ bool MicroMipsSizeReduce::ReduceADDIUToADDIUR1SP(MachineInstr *MI, return ReplaceInstruction(MI, Entry); } -bool MicroMipsSizeReduce::ReduceADDIUToADDIUSP(MachineInstr *MI, - const ReduceEntry &Entry) { +bool MicroMipsSizeReduce::ReduceADDIUToADDIUSP(ReduceEntryFunArgs *Arguments) { + + MachineInstr *MI = Arguments->MI; + const ReduceEntry &Entry = Arguments->Entry; int64_t ImmValue; if (!GetImm(MI, Entry.ImmField(), ImmValue)) @@ -377,8 +532,10 @@ bool MicroMipsSizeReduce::ReduceADDIUToADDIUSP(MachineInstr *MI, return ReplaceInstruction(MI, Entry); } -bool MicroMipsSizeReduce::ReduceLXUtoLXU16(MachineInstr *MI, - const ReduceEntry &Entry) { +bool MicroMipsSizeReduce::ReduceLXUtoLXU16(ReduceEntryFunArgs *Arguments) { + + MachineInstr *MI = Arguments->MI; + const ReduceEntry &Entry = Arguments->Entry; if (!ImmInRange(MI, Entry)) return false; @@ -390,8 +547,10 @@ bool MicroMipsSizeReduce::ReduceLXUtoLXU16(MachineInstr *MI, return ReplaceInstruction(MI, Entry); } -bool MicroMipsSizeReduce::ReduceSXtoSX16(MachineInstr *MI, - const ReduceEntry &Entry) { +bool MicroMipsSizeReduce::ReduceSXtoSX16(ReduceEntryFunArgs *Arguments) { + + MachineInstr *MI = Arguments->MI; + const ReduceEntry &Entry = Arguments->Entry; if (!ImmInRange(MI, Entry)) return false; @@ -403,8 +562,11 @@ bool MicroMipsSizeReduce::ReduceSXtoSX16(MachineInstr *MI, return ReplaceInstruction(MI, Entry); } -bool MicroMipsSizeReduce::ReduceXORtoXOR16(MachineInstr *MI, - const ReduceEntry &Entry) { +bool MicroMipsSizeReduce::ReduceXORtoXOR16(ReduceEntryFunArgs *Arguments) { + + MachineInstr *MI = Arguments->MI; + const ReduceEntry &Entry = Arguments->Entry; + if (!isMMThreeBitGPRegister(MI->getOperand(0)) || !isMMThreeBitGPRegister(MI->getOperand(1)) || !isMMThreeBitGPRegister(MI->getOperand(2))) @@ -433,23 +595,25 @@ bool MicroMipsSizeReduce::ReduceMBB(MachineBasicBlock &MBB) { continue; // Try to reduce 32-bit instruction into 16-bit instruction - Modified |= ReduceMI(MII); + Modified |= ReduceMI(MII, NextMII); } return Modified; } bool MicroMipsSizeReduce::ReplaceInstruction(MachineInstr *MI, - const ReduceEntry &Entry) { + const ReduceEntry &Entry, + MachineInstr *MI2, + bool ConsecutiveForward) { enum OperandTransfer OpTransfer = Entry.TransferOperands(); - DEBUG(dbgs() << "Converting 32-bit: " << *MI); + LLVM_DEBUG(dbgs() << "Converting 32-bit: " << *MI); ++NumReduced; if (OpTransfer == OT_OperandsAll) { MI->setDesc(MipsII->get(Entry.NarrowOpc())); - DEBUG(dbgs() << " to 16-bit: " << *MI); + LLVM_DEBUG(dbgs() << " to 16-bit: " << *MI); return true; } else { MachineBasicBlock &MBB = *MI->getParent(); @@ -477,6 +641,27 @@ bool MicroMipsSizeReduce::ReplaceInstruction(MachineInstr *MI, } break; } + case OT_OperandsLwp: + case OT_OperandsSwp: { + if (ConsecutiveForward) { + MIB.add(MI->getOperand(0)); + MIB.add(MI2->getOperand(0)); + MIB.add(MI->getOperand(1)); + MIB.add(MI->getOperand(2)); + } else { // consecutive backward + MIB.add(MI2->getOperand(0)); + MIB.add(MI->getOperand(0)); + MIB.add(MI2->getOperand(1)); + MIB.add(MI2->getOperand(2)); + } + + LLVM_DEBUG(dbgs() << "and converting 32-bit: " << *MI2 + << " to: " << *MIB); + + MBB.erase_instr(MI); + MBB.erase_instr(MI2); + return true; + } default: llvm_unreachable("Unknown operand transfer!"); } @@ -484,7 +669,7 @@ bool MicroMipsSizeReduce::ReplaceInstruction(MachineInstr *MI, // Transfer MI flags. MIB.setMIFlags(MI->getFlags()); - DEBUG(dbgs() << " to 16-bit: " << *MIB); + LLVM_DEBUG(dbgs() << " to 16-bit: " << *MIB); MBB.erase_instr(MI); return true; } @@ -511,6 +696,6 @@ bool MicroMipsSizeReduce::runOnMachineFunction(MachineFunction &MF) { } /// Returns an instance of the MicroMips size reduction pass. -FunctionPass *llvm::createMicroMipsSizeReductionPass() { +FunctionPass *llvm::createMicroMipsSizeReducePass() { return new MicroMipsSizeReduce(); } diff --git a/lib/Target/Mips/Mips.h b/lib/Target/Mips/Mips.h index 008b9505ee26..ef3a807c7648 100644 --- a/lib/Target/Mips/Mips.h +++ b/lib/Target/Mips/Mips.h @@ -22,6 +22,11 @@ namespace llvm { class MipsTargetMachine; class ModulePass; class FunctionPass; + class MipsRegisterBankInfo; + class MipsSubtarget; + class MipsTargetMachine; + class InstructionSelector; + class PassRegistry; ModulePass *createMipsOs16Pass(); ModulePass *createMips16HardFloatPass(); @@ -29,10 +34,18 @@ namespace llvm { FunctionPass *createMipsModuleISelDagPass(); FunctionPass *createMipsOptimizePICCallPass(); FunctionPass *createMipsDelaySlotFillerPass(); - FunctionPass *createMipsHazardSchedule(); - FunctionPass *createMipsLongBranchPass(); + FunctionPass *createMipsBranchExpansion(); FunctionPass *createMipsConstantIslandPass(); - FunctionPass *createMicroMipsSizeReductionPass(); + FunctionPass *createMicroMipsSizeReducePass(); + FunctionPass *createMipsExpandPseudoPass(); + + InstructionSelector *createMipsInstructionSelector(const MipsTargetMachine &, + MipsSubtarget &, + MipsRegisterBankInfo &); + + void initializeMipsDelaySlotFillerPass(PassRegistry &); + void initializeMipsBranchExpansionPass(PassRegistry &); + void initializeMicroMipsSizeReducePass(PassRegistry &); } // end namespace llvm; #endif diff --git a/lib/Target/Mips/Mips.td b/lib/Target/Mips/Mips.td index 6ceb05577538..2f3a1c399d3e 100644 --- a/lib/Target/Mips/Mips.td +++ b/lib/Target/Mips/Mips.td @@ -28,8 +28,10 @@ class PredicateControl { 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 + // Predicates for the instruction group membership such as ISA's. list<Predicate> InsnPredicates = []; + // Predicate for the ASE that an instruction belongs to. + list<Predicate> ASEPredicate = []; // Predicate for marking the instruction as usable in hard-float mode only. list<Predicate> HardFloatPredicate = []; // Predicates for anything else @@ -40,6 +42,7 @@ class PredicateControl { FGRPredicates, InsnPredicates, HardFloatPredicate, + ASEPredicate, AdditionalPredicates); } @@ -56,6 +59,7 @@ include "MipsRegisterInfo.td" include "MipsSchedule.td" include "MipsInstrInfo.td" include "MipsCallingConv.td" +include "MipsRegisterBanks.td" // Avoid forward declaration issues. include "MipsScheduleP5600.td" @@ -173,6 +177,14 @@ def FeatureMSA : SubtargetFeature<"msa", "HasMSA", "true", "Mips MSA ASE">; def FeatureEVA : SubtargetFeature<"eva", "HasEVA", "true", "Mips EVA ASE">; +def FeatureCRC : SubtargetFeature<"crc", "HasCRC", "true", "Mips R6 CRC ASE">; + +def FeatureVirt : SubtargetFeature<"virt", "HasVirt", "true", + "Mips Virtualization ASE">; + +def FeatureGINV : SubtargetFeature<"ginv", "HasGINV", "true", + "Mips Global Invalidate ASE">; + def FeatureMicroMips : SubtargetFeature<"micromips", "InMicroMipsMode", "true", "microMips mode">; @@ -193,6 +205,10 @@ def FeatureMT : SubtargetFeature<"mt", "HasMT", "true", "Mips MT ASE">; def FeatureLongCalls : SubtargetFeature<"long-calls", "UseLongCalls", "true", "Disable use of the jal instruction">; +def FeatureUseIndirectJumpsHazard : SubtargetFeature<"use-indirect-jump-hazard", + "UseIndirectJumpsHazard", + "true", "Use indirect jump" + " guards to prevent certain speculation based attacks">; //===----------------------------------------------------------------------===// // Mips processors supported. //===----------------------------------------------------------------------===// @@ -238,4 +254,5 @@ def Mips : Target { let InstructionSet = MipsInstrInfo; let AssemblyParsers = [MipsAsmParser]; let AssemblyParserVariants = [MipsAsmParserVariant]; + let AllowRegisterRenaming = 1; } diff --git a/lib/Target/Mips/Mips16FrameLowering.cpp b/lib/Target/Mips/Mips16FrameLowering.cpp index cb59e2ddb1c6..122c1f5377b6 100644 --- a/lib/Target/Mips/Mips16FrameLowering.cpp +++ b/lib/Target/Mips/Mips16FrameLowering.cpp @@ -42,7 +42,6 @@ Mips16FrameLowering::Mips16FrameLowering(const MipsSubtarget &STI) void Mips16FrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const { - assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported"); MachineFrameInfo &MFI = MF.getFrameInfo(); const Mips16InstrInfo &TII = *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo()); @@ -92,11 +91,11 @@ void Mips16FrameLowering::emitPrologue(MachineFunction &MF, void Mips16FrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { - MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); + MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator(); MachineFrameInfo &MFI = MF.getFrameInfo(); const Mips16InstrInfo &TII = *static_cast<const Mips16InstrInfo *>(STI.getInstrInfo()); - DebugLoc dl = MBBI->getDebugLoc(); + DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); uint64_t StackSize = MFI.getStackSize(); if (!StackSize) @@ -117,7 +116,6 @@ spillCalleeSavedRegisters(MachineBasicBlock &MBB, const std::vector<CalleeSavedInfo> &CSI, const TargetRegisterInfo *TRI) const { MachineFunction *MF = MBB.getParent(); - MachineBasicBlock *EntryBlock = &MF->front(); // // Registers RA, S0,S1 are the callee saved registers and they @@ -134,7 +132,7 @@ spillCalleeSavedRegisters(MachineBasicBlock &MBB, bool IsRAAndRetAddrIsTaken = (Reg == Mips::RA) && MF->getFrameInfo().isReturnAddressTaken(); if (!IsRAAndRetAddrIsTaken) - EntryBlock->addLiveIn(Reg); + MBB.addLiveIn(Reg); } return true; diff --git a/lib/Target/Mips/Mips16HardFloat.cpp b/lib/Target/Mips/Mips16HardFloat.cpp index 682ea5c4ed7f..c310d9491af8 100644 --- a/lib/Target/Mips/Mips16HardFloat.cpp +++ b/lib/Target/Mips/Mips16HardFloat.cpp @@ -482,11 +482,11 @@ static void createFPFnStub(Function *F, Module *M, FPParamVariant PV, // remove the use-soft-float attribute static void removeUseSoftFloat(Function &F) { AttrBuilder B; - DEBUG(errs() << "removing -use-soft-float\n"); + LLVM_DEBUG(errs() << "removing -use-soft-float\n"); B.addAttribute("use-soft-float", "false"); F.removeAttributes(AttributeList::FunctionIndex, B); if (F.hasFnAttribute("use-soft-float")) { - DEBUG(errs() << "still has -use-soft-float\n"); + LLVM_DEBUG(errs() << "still has -use-soft-float\n"); } F.addAttributes(AttributeList::FunctionIndex, B); } @@ -510,7 +510,7 @@ static void removeUseSoftFloat(Function &F) { bool Mips16HardFloat::runOnModule(Module &M) { auto &TM = static_cast<const MipsTargetMachine &>( getAnalysis<TargetPassConfig>().getTM<TargetMachine>()); - DEBUG(errs() << "Run on Module Mips16HardFloat\n"); + LLVM_DEBUG(errs() << "Run on Module Mips16HardFloat\n"); bool Modified = false; for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) { if (F->hasFnAttribute("nomips16") && diff --git a/lib/Target/Mips/Mips16ISelDAGToDAG.cpp b/lib/Target/Mips/Mips16ISelDAGToDAG.cpp index ce193b1734f3..a0d5bd9ef305 100644 --- a/lib/Target/Mips/Mips16ISelDAGToDAG.cpp +++ b/lib/Target/Mips/Mips16ISelDAGToDAG.cpp @@ -192,41 +192,6 @@ bool Mips16DAGToDAGISel::trySelect(SDNode *Node) { default: break; - case ISD::SUBE: - case ISD::ADDE: { - SDValue InFlag = Node->getOperand(2), CmpLHS; - 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"); - - unsigned MOp; - if (Opcode == ISD::ADDE) { - CmpLHS = InFlag.getValue(0); - MOp = Mips::AdduRxRyRz16; - } else { - CmpLHS = InFlag.getOperand(0); - MOp = Mips::SubuRxRyRz16; - } - - SDValue Ops[] = {CmpLHS, InFlag.getOperand(1)}; - - SDValue LHS = Node->getOperand(0); - SDValue RHS = Node->getOperand(1); - - EVT VT = LHS.getValueType(); - - 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); - - 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: { diff --git a/lib/Target/Mips/Mips16InstrInfo.cpp b/lib/Target/Mips/Mips16InstrInfo.cpp index e11023b4d272..219f1ad33586 100644 --- a/lib/Target/Mips/Mips16InstrInfo.cpp +++ b/lib/Target/Mips/Mips16InstrInfo.cpp @@ -97,6 +97,17 @@ void Mips16InstrInfo::copyPhysReg(MachineBasicBlock &MBB, MIB.addReg(SrcReg, getKillRegState(KillSrc)); } +bool Mips16InstrInfo::isCopyInstr(const MachineInstr &MI, + const MachineOperand *&Src, + const MachineOperand *&Dest) const { + if (MI.isMoveReg()) { + Dest = &MI.getOperand(0); + Src = &MI.getOperand(1); + return true; + } + return false; +} + void Mips16InstrInfo::storeRegToStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned SrcReg, bool isKill, int FI, diff --git a/lib/Target/Mips/Mips16InstrInfo.h b/lib/Target/Mips/Mips16InstrInfo.h index ffdd4728c8cb..8190be6187ea 100644 --- a/lib/Target/Mips/Mips16InstrInfo.h +++ b/lib/Target/Mips/Mips16InstrInfo.h @@ -53,6 +53,9 @@ public: const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, bool KillSrc) const override; + bool isCopyInstr(const MachineInstr &MI, const MachineOperand *&Src, + const MachineOperand *&Dest) const override; + void storeRegToStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, unsigned SrcReg, bool isKill, int FrameIndex, diff --git a/lib/Target/Mips/Mips16InstrInfo.td b/lib/Target/Mips/Mips16InstrInfo.td index b91c94288582..b7a1b9ce41bf 100644 --- a/lib/Target/Mips/Mips16InstrInfo.td +++ b/lib/Target/Mips/Mips16InstrInfo.td @@ -869,7 +869,9 @@ def Move32R16: FI8_MOV32R16_ins<"move", IIM16Alu>; //Purpose: Move // To move the contents of a GPR to a GPR. // -def MoveR3216: FI8_MOVR3216_ins<"move", IIM16Alu>; +def MoveR3216: FI8_MOVR3216_ins<"move", IIM16Alu> { + let isMoveReg = 1; +} // // Format: MFHI rx MIPS16e @@ -879,6 +881,7 @@ def MoveR3216: FI8_MOVR3216_ins<"move", IIM16Alu>; def Mfhi16: FRR16_M_ins<0b10000, "mfhi", IIM16Alu> { let Uses = [HI0]; let hasSideEffects = 0; + let isMoveReg = 1; } // @@ -889,6 +892,7 @@ def Mfhi16: FRR16_M_ins<0b10000, "mfhi", IIM16Alu> { def Mflo16: FRR16_M_ins<0b10010, "mflo", IIM16Alu> { let Uses = [LO0]; let hasSideEffects = 0; + let isMoveReg = 0; } // @@ -1403,14 +1407,6 @@ def: Mips16Pat<(i32 addr16sp:$addr), (AddiuRxRyOffMemX16 addr16sp:$addr)>; // Large (>16 bit) immediate loads def : Mips16Pat<(i32 imm:$imm), (LwConstant32 imm:$imm, -1)>; -// Carry MipsPatterns -def : Mips16Pat<(subc CPU16Regs:$lhs, CPU16Regs:$rhs), - (SubuRxRyRz16 CPU16Regs:$lhs, CPU16Regs:$rhs)>; -def : Mips16Pat<(addc CPU16Regs:$lhs, CPU16Regs:$rhs), - (AdduRxRyRz16 CPU16Regs:$lhs, CPU16Regs:$rhs)>; -def : Mips16Pat<(addc CPU16Regs:$src, immSExt16:$imm), - (AddiuRxRxImmX16 CPU16Regs:$src, imm:$imm)>; - // // Some branch conditional patterns are not generated by llvm at this time. // Some are for seemingly arbitrary reasons not used: i.e. with signed number @@ -1424,7 +1420,7 @@ def : Mips16Pat<(addc CPU16Regs:$src, immSExt16:$imm), // setcc instead and earlier I had implemented setcc first so may have masked // the problem. The setcc variants are suboptimal for mips16 so I may wantto // figure out how to enable the brcond patterns or else possibly new -// combinations of of brcond and setcc. +// combinations of brcond and setcc. // // // bcond-seteq @@ -1862,11 +1858,12 @@ def : Mips16Pat<(MipsHi tglobaladdr:$in), (SllX16 (LiRxImmX16 tglobaladdr:$in), 16)>; def : Mips16Pat<(MipsHi tjumptable:$in), (SllX16 (LiRxImmX16 tjumptable:$in), 16)>; -def : Mips16Pat<(MipsHi tglobaltlsaddr:$in), - (SllX16 (LiRxImmX16 tglobaltlsaddr:$in), 16)>; def : Mips16Pat<(MipsLo tblockaddress:$in), (LiRxImmX16 tblockaddress:$in)>; +def : Mips16Pat<(MipsTlsHi tglobaltlsaddr:$in), + (SllX16 (LiRxImmX16 tglobaltlsaddr:$in), 16)>; + // wrapper_pic class Wrapper16Pat<SDNode node, Instruction ADDiuOp, RegisterClass RC>: Mips16Pat<(MipsWrapper RC:$gp, node:$in), @@ -1910,3 +1907,7 @@ def CONSTPOOL_ENTRY : MipsPseudo16<(outs), (ins cpinst_operand:$instid, cpinst_operand:$cpidx, i32imm:$size), "foo", []>; +// Instruction Aliases + +let EncodingPredicates = [InMips16Mode] in +def : MipsInstAlias<"nop", (Move32R16 ZERO, S0)>; diff --git a/lib/Target/Mips/Mips16RegisterInfo.cpp b/lib/Target/Mips/Mips16RegisterInfo.cpp index ff95f3c72282..751afd5ed369 100644 --- a/lib/Target/Mips/Mips16RegisterInfo.cpp +++ b/lib/Target/Mips/Mips16RegisterInfo.cpp @@ -127,8 +127,8 @@ void Mips16RegisterInfo::eliminateFI(MachineBasicBlock::iterator II, Offset = SPOffset + (int64_t)StackSize; Offset += MI.getOperand(OpNo + 1).getImm(); - - DEBUG(errs() << "Offset : " << Offset << "\n" << "<--------->\n"); + LLVM_DEBUG(errs() << "Offset : " << Offset << "\n" + << "<--------->\n"); if (!MI.isDebugValue() && !Mips16InstrInfo::validImmediate(MI.getOpcode(), FrameReg, Offset)) { diff --git a/lib/Target/Mips/Mips32r6InstrFormats.td b/lib/Target/Mips/Mips32r6InstrFormats.td index 516caa34fbf2..e1d08cad88b7 100644 --- a/lib/Target/Mips/Mips32r6InstrFormats.td +++ b/lib/Target/Mips/Mips32r6InstrFormats.td @@ -30,8 +30,7 @@ class MipsR6Arch<string opstr> { string BaseOpcode = opstr; } -class MipsR6Inst : MipsInst<(outs), (ins), "", [], NoItinerary, FrmOther>, - PredicateControl { +class MipsR6Inst : MipsInst<(outs), (ins), "", [], NoItinerary, FrmOther> { let DecoderNamespace = "Mips32r6_64r6"; let EncodingPredicates = [HasStdEnc]; } @@ -576,3 +575,30 @@ class COP2LDST_FM<OPCODE5 Operation> : MipsR6Inst { let Inst{15-11} = base; let Inst{10-0} = offset; } + +class SPECIAL3_2R_SZ_CRC<bits<2> sz, bits<3> direction> : MipsR6Inst { + bits<5> rs; + bits<5> rt; + + let Inst{31-26} = OPGROUP_SPECIAL3.Value; + let Inst{25-21} = rs; + let Inst{20-16} = rt; + let Inst{15-11} = 0b00000; + let Inst{10-8} = direction; + let Inst{7-6} = sz; + let Inst{5-0} = 0b001111; + + string DecoderMethod = "DecodeCRC"; +} + +class SPECIAL3_GINV<bits<2> ginv> : MipsR6Inst { + bits<5> rs; + bits<2> type_; + + let Inst{31-26} = OPGROUP_SPECIAL3.Value; + let Inst{25-21} = rs; + let Inst{20-10} = 0x0; + let Inst{9-8} = type_; + let Inst{7-6} = ginv; + let Inst{5-0} = 0b111101; +} diff --git a/lib/Target/Mips/Mips32r6InstrInfo.td b/lib/Target/Mips/Mips32r6InstrInfo.td index 62f045e77fdb..d86fc3f658ae 100644 --- a/lib/Target/Mips/Mips32r6InstrInfo.td +++ b/lib/Target/Mips/Mips32r6InstrInfo.td @@ -190,6 +190,16 @@ class CLZ_R6_ENC : SPECIAL_2R_FM<OPCODE6_CLZ>; class SDBBP_R6_ENC : SPECIAL_SDBBP_FM; +class CRC32B_ENC : SPECIAL3_2R_SZ_CRC<0,0>; +class CRC32H_ENC : SPECIAL3_2R_SZ_CRC<1,0>; +class CRC32W_ENC : SPECIAL3_2R_SZ_CRC<2,0>; +class CRC32CB_ENC : SPECIAL3_2R_SZ_CRC<0,1>; +class CRC32CH_ENC : SPECIAL3_2R_SZ_CRC<1,1>; +class CRC32CW_ENC : SPECIAL3_2R_SZ_CRC<2,1>; + +class GINVI_ENC : SPECIAL3_GINV<0>; +class GINVT_ENC : SPECIAL3_GINV<2>; + //===----------------------------------------------------------------------===// // // Instruction Multiclasses @@ -804,6 +814,38 @@ class SDBBP_R6_DESC { InstrItinClass Itinerary = II_SDBBP; } +class CRC_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, + InstrItinClass itin> : 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 = []; + InstrItinClass Itinerary = itin; +} + +class CRC32B_DESC : CRC_DESC_BASE<"crc32b", GPR32Opnd, II_CRC32B>; +class CRC32H_DESC : CRC_DESC_BASE<"crc32h", GPR32Opnd, II_CRC32H>; +class CRC32W_DESC : CRC_DESC_BASE<"crc32w", GPR32Opnd, II_CRC32W>; +class CRC32CB_DESC : CRC_DESC_BASE<"crc32cb", GPR32Opnd, II_CRC32CB>; +class CRC32CH_DESC : CRC_DESC_BASE<"crc32ch", GPR32Opnd, II_CRC32CH>; +class CRC32CW_DESC : CRC_DESC_BASE<"crc32cw", GPR32Opnd, II_CRC32CW>; + +class GINV_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, + InstrItinClass itin> : MipsR6Arch<instr_asm> { + dag OutOperandList = (outs); + dag InOperandList = (ins GPROpnd:$rs, uimm2:$type_); + string AsmString = !strconcat(instr_asm, "\t$rs, $type_"); + list<dag> Pattern = []; + InstrItinClass Itinerary = itin; + bit hasSideEffects = 1; +} + +class GINVI_DESC : GINV_DESC_BASE<"ginvi", GPR32Opnd, II_GINVI> { + dag InOperandList = (ins GPR32Opnd:$rs); + string AsmString = "ginvi\t$rs"; +} +class GINVT_DESC : GINV_DESC_BASE<"ginvt", GPR32Opnd, II_GINVT>; + //===----------------------------------------------------------------------===// // // Instruction Definitions @@ -846,9 +888,7 @@ let AdditionalPredicates = [NotInMicroMips] in { def BNEZC : R6MMR6Rel, BNEZC_ENC, BNEZC_DESC, ISA_MIPS32R6; 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 CACHE_R6 : R6MMR6Rel, CACHE_ENC, CACHE_DESC, ISA_MIPS32R6; def CLASS_D : CLASS_D_ENC, CLASS_D_DESC, ISA_MIPS32R6, HARDFLOAT; def CLASS_S : CLASS_S_ENC, CLASS_S_DESC, ISA_MIPS32R6, HARDFLOAT; } @@ -901,8 +941,8 @@ let AdditionalPredicates = [NotInMicroMips] in { 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 PREF_R6 : R6MMR6Rel, PREF_ENC, PREF_DESC, ISA_MIPS32R6; def RINT_D : RINT_D_ENC, RINT_D_DESC, ISA_MIPS32R6, HARDFLOAT; def RINT_S : RINT_S_ENC, RINT_S_DESC, ISA_MIPS32R6, HARDFLOAT; def SC_R6 : SC_R6_ENC, SC_R6_DESC, PTR_32, ISA_MIPS32R6; @@ -923,6 +963,20 @@ let AdditionalPredicates = [NotInMicroMips] in { def SWC2_R6 : SWC2_R6_ENC, SWC2_R6_DESC, ISA_MIPS32R6; } +let AdditionalPredicates = [NotInMicroMips] in { + def CRC32B : R6MMR6Rel, CRC32B_ENC, CRC32B_DESC, ISA_MIPS32R6, ASE_CRC; + def CRC32H : R6MMR6Rel, CRC32H_ENC, CRC32H_DESC, ISA_MIPS32R6, ASE_CRC; + def CRC32W : R6MMR6Rel, CRC32W_ENC, CRC32W_DESC, ISA_MIPS32R6, ASE_CRC; + def CRC32CB : R6MMR6Rel, CRC32CB_ENC, CRC32CB_DESC, ISA_MIPS32R6, ASE_CRC; + def CRC32CH : R6MMR6Rel, CRC32CH_ENC, CRC32CH_DESC, ISA_MIPS32R6, ASE_CRC; + def CRC32CW : R6MMR6Rel, CRC32CW_ENC, CRC32CW_DESC, ISA_MIPS32R6, ASE_CRC; +} + +let AdditionalPredicates = [NotInMicroMips] in { + def GINVI : R6MMR6Rel, GINVI_ENC, GINVI_DESC, ISA_MIPS32R6, ASE_GINV; + def GINVT : R6MMR6Rel, GINVT_ENC, GINVT_DESC, ISA_MIPS32R6, ASE_GINV; +} + //===----------------------------------------------------------------------===// // // Instruction Aliases @@ -1036,3 +1090,42 @@ def : MipsPat<(select i32:$cond, immz, i32:$f), (SELEQZ i32:$f, i32:$cond)>, ISA_MIPS32R6; } + +// Pseudo instructions +let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, hasDelaySlot = 1, + hasExtraSrcRegAllocReq = 1, isCTI = 1, Defs = [AT] in { + class TailCallRegR6<Instruction JumpInst, Register RT, RegisterOperand RO> : + PseudoSE<(outs), (ins RO:$rs), [(MipsTailCall RO:$rs)], II_JR>, + PseudoInstExpansion<(JumpInst RT:$rt, RO:$rs)>; +} + +class PseudoIndirectBranchBaseR6<Instruction JumpInst, Register RT, + RegisterOperand RO> : + MipsPseudo<(outs), (ins RO:$rs), [(brind RO:$rs)], + II_IndirectBranchPseudo>, + PseudoInstExpansion<(JumpInst RT:$rt, RO:$rs)> { + let isTerminator=1; + let isBarrier=1; + let hasDelaySlot = 1; + let isBranch = 1; + let isIndirectBranch = 1; + bit isCTI = 1; +} + + +let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips, + NoIndirectJumpGuards] in { + def TAILCALLR6REG : TailCallRegR6<JALR, ZERO, GPR32Opnd>, ISA_MIPS32R6; + def PseudoIndirectBranchR6 : PseudoIndirectBranchBaseR6<JALR, ZERO, + GPR32Opnd>, + ISA_MIPS32R6; +} + +let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips, + UseIndirectJumpsHazard] in { + def TAILCALLHBR6REG : TailCallReg<JR_HB_R6, GPR32Opnd>, ISA_MIPS32R6; + def PseudoIndrectHazardBranchR6 : PseudoIndirectBranchBase<JR_HB_R6, + GPR32Opnd>, + ISA_MIPS32R6; +} + diff --git a/lib/Target/Mips/Mips64InstrInfo.td b/lib/Target/Mips/Mips64InstrInfo.td index e008aeafaa2b..878ec29b188d 100644 --- a/lib/Target/Mips/Mips64InstrInfo.td +++ b/lib/Target/Mips/Mips64InstrInfo.td @@ -85,6 +85,17 @@ let usesCustomInserter = 1 in { def ATOMIC_CMP_SWAP_I64 : AtomicCmpSwap<atomic_cmp_swap_64, GPR64>; } +def ATOMIC_LOAD_ADD_I64_POSTRA : Atomic2OpsPostRA<GPR64>; +def ATOMIC_LOAD_SUB_I64_POSTRA : Atomic2OpsPostRA<GPR64>; +def ATOMIC_LOAD_AND_I64_POSTRA : Atomic2OpsPostRA<GPR64>; +def ATOMIC_LOAD_OR_I64_POSTRA : Atomic2OpsPostRA<GPR64>; +def ATOMIC_LOAD_XOR_I64_POSTRA : Atomic2OpsPostRA<GPR64>; +def ATOMIC_LOAD_NAND_I64_POSTRA : Atomic2OpsPostRA<GPR64>; + +def ATOMIC_SWAP_I64_POSTRA : Atomic2OpsPostRA<GPR64>; + +def ATOMIC_CMP_SWAP_I64_POSTRA : AtomicCmpSwapPostRA<GPR64>; + /// Pseudo instructions for loading and storing accumulator registers. let isPseudo = 1, isCodeGenOnly = 1, hasNoSchedulingInfo = 1 in { def LOAD_ACC128 : Load<"", ACC128>; @@ -106,16 +117,16 @@ let AdditionalPredicates = [NotInMicroMips] in { let isCodeGenOnly = 1 in { def SLTi64 : SetCC_I<"slti", setlt, simm16_64, immSExt16, GPR64Opnd>, - SLTI_FM<0xa>; + SLTI_FM<0xa>, GPR_64; def SLTiu64 : SetCC_I<"sltiu", setult, simm16_64, immSExt16, GPR64Opnd>, - SLTI_FM<0xb>; + SLTI_FM<0xb>, GPR_64; def ANDi64 : ArithLogicI<"andi", uimm16_64, GPR64Opnd, II_AND, immZExt16, and>, - ADDI_FM<0xc>; + ADDI_FM<0xc>, GPR_64; def ORi64 : ArithLogicI<"ori", uimm16_64, GPR64Opnd, II_OR, immZExt16, or>, - ADDI_FM<0xd>; + ADDI_FM<0xd>, GPR_64; def XORi64 : ArithLogicI<"xori", uimm16_64, GPR64Opnd, II_XOR, immZExt16, xor>, - ADDI_FM<0xe>; -def LUi64 : LoadUpper<"lui", GPR64Opnd, uimm16_64_relaxed>, LUI_FM; + ADDI_FM<0xe>, GPR_64; +def LUi64 : LoadUpper<"lui", GPR64Opnd, uimm16_64_relaxed>, LUI_FM, GPR_64; } /// Arithmetic Instructions (3-Operand, R-Type) @@ -131,12 +142,15 @@ let AdditionalPredicates = [NotInMicroMips] in { } let isCodeGenOnly = 1 in { -def SLT64 : SetCC_R<"slt", setlt, GPR64Opnd>, ADD_FM<0, 0x2a>; -def SLTu64 : SetCC_R<"sltu", setult, GPR64Opnd>, ADD_FM<0, 0x2b>; -def AND64 : ArithLogicR<"and", GPR64Opnd, 1, II_AND, and>, ADD_FM<0, 0x24>; -def OR64 : ArithLogicR<"or", GPR64Opnd, 1, II_OR, or>, ADD_FM<0, 0x25>; -def XOR64 : ArithLogicR<"xor", GPR64Opnd, 1, II_XOR, xor>, ADD_FM<0, 0x26>; -def NOR64 : LogicNOR<"nor", GPR64Opnd>, ADD_FM<0, 0x27>; +def SLT64 : SetCC_R<"slt", setlt, GPR64Opnd>, ADD_FM<0, 0x2a>, GPR_64; +def SLTu64 : SetCC_R<"sltu", setult, GPR64Opnd>, ADD_FM<0, 0x2b>, GPR_64; +def AND64 : ArithLogicR<"and", GPR64Opnd, 1, II_AND, and>, ADD_FM<0, 0x24>, + GPR_64; +def OR64 : ArithLogicR<"or", GPR64Opnd, 1, II_OR, or>, ADD_FM<0, 0x25>, + GPR_64; +def XOR64 : ArithLogicR<"xor", GPR64Opnd, 1, II_XOR, xor>, ADD_FM<0, 0x26>, + GPR_64; +def NOR64 : LogicNOR<"nor", GPR64Opnd>, ADD_FM<0, 0x27>, GPR_64; } /// Shift Instructions @@ -176,22 +190,24 @@ let AdditionalPredicates = [NotInMicroMips] in { /// Load and Store Instructions /// aligned let isCodeGenOnly = 1 in { -def LB64 : Load<"lb", GPR64Opnd, sextloadi8, II_LB>, LW_FM<0x20>; -def LBu64 : Load<"lbu", GPR64Opnd, zextloadi8, II_LBU>, LW_FM<0x24>; -def LH64 : Load<"lh", GPR64Opnd, sextloadi16, II_LH>, LW_FM<0x21>; -def LHu64 : Load<"lhu", GPR64Opnd, zextloadi16, II_LHU>, LW_FM<0x25>; -def LW64 : Load<"lw", GPR64Opnd, sextloadi32, II_LW>, LW_FM<0x23>; -def SB64 : Store<"sb", GPR64Opnd, truncstorei8, II_SB>, LW_FM<0x28>; -def SH64 : Store<"sh", GPR64Opnd, truncstorei16, II_SH>, LW_FM<0x29>; -def SW64 : Store<"sw", GPR64Opnd, truncstorei32, II_SW>, LW_FM<0x2b>; +def LB64 : Load<"lb", GPR64Opnd, sextloadi8, II_LB>, LW_FM<0x20>, GPR_64; +def LBu64 : Load<"lbu", GPR64Opnd, zextloadi8, II_LBU>, LW_FM<0x24>, GPR_64; +def LH64 : Load<"lh", GPR64Opnd, sextloadi16, II_LH>, LW_FM<0x21>, GPR_64; +def LHu64 : Load<"lhu", GPR64Opnd, zextloadi16, II_LHU>, LW_FM<0x25>, GPR_64; +def LW64 : Load<"lw", GPR64Opnd, sextloadi32, II_LW>, LW_FM<0x23>, GPR_64; +def SB64 : Store<"sb", GPR64Opnd, truncstorei8, II_SB>, LW_FM<0x28>, GPR_64; +def SH64 : Store<"sh", GPR64Opnd, truncstorei16, II_SH>, LW_FM<0x29>, + GPR_64; +def SW64 : Store<"sw", GPR64Opnd, truncstorei32, II_SW>, LW_FM<0x2b>, + GPR_64; } let AdditionalPredicates = [NotInMicroMips] in { def LWu : MMRel, Load<"lwu", GPR64Opnd, zextloadi32, II_LWU>, LW_FM<0x27>, ISA_MIPS3; - def LD : LoadMemory<"ld", GPR64Opnd, mem_simm16, load, II_LD>, + def LD : LoadMemory<"ld", GPR64Opnd, mem_simmptr, load, II_LD>, LW_FM<0x37>, ISA_MIPS3; - def SD : StoreMemory<"sd", GPR64Opnd, mem_simm16, store, II_SD>, + def SD : StoreMemory<"sd", GPR64Opnd, mem_simmptr, store, II_SD>, LW_FM<0x3f>, ISA_MIPS3; } @@ -199,10 +215,14 @@ let AdditionalPredicates = [NotInMicroMips] in { /// load/store left/right let isCodeGenOnly = 1 in { -def LWL64 : LoadLeftRight<"lwl", MipsLWL, GPR64Opnd, II_LWL>, LW_FM<0x22>; -def LWR64 : LoadLeftRight<"lwr", MipsLWR, GPR64Opnd, II_LWR>, LW_FM<0x26>; -def SWL64 : StoreLeftRight<"swl", MipsSWL, GPR64Opnd, II_SWL>, LW_FM<0x2a>; -def SWR64 : StoreLeftRight<"swr", MipsSWR, GPR64Opnd, II_SWR>, LW_FM<0x2e>; +def LWL64 : LoadLeftRight<"lwl", MipsLWL, GPR64Opnd, II_LWL>, LW_FM<0x22>, + GPR_64; +def LWR64 : LoadLeftRight<"lwr", MipsLWR, GPR64Opnd, II_LWR>, LW_FM<0x26>, + GPR_64; +def SWL64 : StoreLeftRight<"swl", MipsSWL, GPR64Opnd, II_SWL>, LW_FM<0x2a>, + GPR_64; +def SWR64 : StoreLeftRight<"swr", MipsSWR, GPR64Opnd, II_SWR>, LW_FM<0x2e>, + GPR_64; } def LDL : LoadLeftRight<"ldl", MipsLDL, GPR64Opnd, II_LDL>, LW_FM<0x1a>, @@ -216,7 +236,7 @@ def SDR : StoreLeftRight<"sdr", MipsSDR, GPR64Opnd, II_SDR>, LW_FM<0x2d>, /// Load-linked, Store-conditional let AdditionalPredicates = [NotInMicroMips] in { - def LLD : LLBase<"lld", GPR64Opnd, mem_simm16>, LW_FM<0x34>, + def LLD : LLBase<"lld", GPR64Opnd, mem_simmptr>, LW_FM<0x34>, ISA_MIPS3_NOT_32R6_64R6; } def SCD : SCBase<"scd", GPR64Opnd>, LW_FM<0x3c>, ISA_MIPS3_NOT_32R6_64R6; @@ -234,19 +254,44 @@ def JALR64 : JumpLinkReg<"jalr", GPR64Opnd>, JALR_FM; /// Jump and Branch Instructions let isCodeGenOnly = 1 in { - def BEQ64 : CBranch<"beq", brtarget, seteq, GPR64Opnd>, BEQ_FM<4>; - def BNE64 : CBranch<"bne", brtarget, setne, GPR64Opnd>, BEQ_FM<5>; - def BGEZ64 : CBranchZero<"bgez", brtarget, setge, GPR64Opnd>, BGEZ_FM<1, 1>; - def BGTZ64 : CBranchZero<"bgtz", brtarget, setgt, GPR64Opnd>, BGEZ_FM<7, 0>; - def BLEZ64 : CBranchZero<"blez", brtarget, setle, GPR64Opnd>, BGEZ_FM<6, 0>; - def BLTZ64 : CBranchZero<"bltz", brtarget, setlt, GPR64Opnd>, BGEZ_FM<1, 0>; - def JALR64Pseudo : JumpLinkRegPseudo<GPR64Opnd, JALR, RA, GPR32Opnd>; + def BEQ64 : CBranch<"beq", brtarget, seteq, GPR64Opnd>, BEQ_FM<4>, + GPR_64; + def BNE64 : CBranch<"bne", brtarget, setne, GPR64Opnd>, BEQ_FM<5>, + GPR_64; + def BGEZ64 : CBranchZero<"bgez", brtarget, setge, GPR64Opnd>, BGEZ_FM<1, 1>, + GPR_64; + def BGTZ64 : CBranchZero<"bgtz", brtarget, setgt, GPR64Opnd>, BGEZ_FM<7, 0>, + GPR_64; + def BLEZ64 : CBranchZero<"blez", brtarget, setle, GPR64Opnd>, BGEZ_FM<6, 0>, + GPR_64; + def BLTZ64 : CBranchZero<"bltz", brtarget, setlt, GPR64Opnd>, BGEZ_FM<1, 0>, + GPR_64; + let AdditionalPredicates = [NoIndirectJumpGuards] in + def JALR64Pseudo : JumpLinkRegPseudo<GPR64Opnd, JALR, RA, GPR32Opnd>; +} +let AdditionalPredicates = [NotInMicroMips], + DecoderNamespace = "Mips64" in { + def JR_HB64 : JR_HB_DESC<GPR64Opnd>, JR_HB_ENC, ISA_MIPS32_NOT_32R6_64R6; + def JALR_HB64 : JALR_HB_DESC<GPR64Opnd>, JALR_HB_ENC, ISA_MIPS32R2; } +def PseudoReturn64 : PseudoReturnBase<GPR64Opnd>; -def TAILCALLREG64 : TailCallReg<GPR64Opnd>; +let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips, + NoIndirectJumpGuards] in { + def TAILCALLREG64 : TailCallReg<JR64, GPR64Opnd>, ISA_MIPS3_NOT_32R6_64R6, + PTR_64; + def PseudoIndirectBranch64 : PseudoIndirectBranchBase<JR64, GPR64Opnd>, + ISA_MIPS3_NOT_32R6_64R6; +} -def PseudoReturn64 : PseudoReturnBase<GPR64Opnd>; -def PseudoIndirectBranch64 : PseudoIndirectBranchBase<GPR64Opnd>; +let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips, + UseIndirectJumpsHazard] in { + def TAILCALLREGHB64 : TailCallReg<JR_HB64, GPR64Opnd>, + ISA_MIPS32R2_NOT_32R6_64R6, PTR_64; + def PseudoIndirectHazardBranch64 : PseudoIndirectBranchBase<JR_HB64, + GPR64Opnd>, + ISA_MIPS32R2_NOT_32R6_64R6; +} /// Multiply and Divide Instructions. let AdditionalPredicates = [NotInMicroMips] in { @@ -304,12 +349,13 @@ let AdditionalPredicates = [NotInMicroMips] in { ISA_MIPS64R2; def DSHD : SubwordSwap<"dshd", GPR64Opnd, II_DSHD>, SEB_FM<5, 0x24>, ISA_MIPS64R2; -} -def LEA_ADDiu64 : EffectiveAddress<"daddiu", GPR64Opnd>, LW_FM<0x19>; + def LEA_ADDiu64 : EffectiveAddress<"daddiu", GPR64Opnd>, LW_FM<0x19>, + GPR_64; +} let isCodeGenOnly = 1 in -def RDHWR64 : ReadHardware<GPR64Opnd, HWRegsOpnd>, RDHWR_FM; +def RDHWR64 : ReadHardware<GPR64Opnd, HWRegsOpnd>, RDHWR_FM, GPR_64; let AdditionalPredicates = [NotInMicroMips] in { // The 'pos + size' constraints for code generation are enforced by the @@ -357,11 +403,13 @@ let isCodeGenOnly = 1, AdditionalPredicates = [NotInMicroMips] in { 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>; - def SLL64_32 : FR<0x0, 0x00, (outs GPR64:$rd), (ins GPR32:$rt), - "sll\t$rd, $rt, 0", [], II_SLL>; - def SLL64_64 : FR<0x0, 0x00, (outs GPR64:$rd), (ins GPR64:$rt), - "sll\t$rd, $rt, 0", [], II_SLL>; + "dsll\t$rd, $rt, 32", [], II_DSLL>, GPR_64; + let isMoveReg = 1 in { + def SLL64_32 : FR<0x0, 0x00, (outs GPR64:$rd), (ins GPR32:$rt), + "sll\t$rd, $rt, 0", [], II_SLL>, GPR_64; + def SLL64_64 : FR<0x0, 0x00, (outs GPR64:$rd), (ins GPR64:$rt), + "sll\t$rd, $rt, 0", [], II_SLL>, GPR_64; + } } // We need the following pseudo instruction to avoid offset calculation for @@ -372,7 +420,7 @@ let isCodeGenOnly = 1, rs = 0, shamt = 0 in { // where %PART may be %hi or %lo, depending on the relocation kind // that $tgt is annotated with. def LONG_BRANCH_DADDiu : PseudoSE<(outs GPR64Opnd:$dst), - (ins GPR64Opnd:$src, brtarget:$tgt, brtarget:$baltgt), []>; + (ins GPR64Opnd:$src, brtarget:$tgt, brtarget:$baltgt), []>, GPR_64; // Cavium Octeon cnMIPS instructions let DecoderNamespace = "CnMips", @@ -526,139 +574,156 @@ def DMTC2_OCTEON : MFC2OP<"dmtc2", GPR64Opnd, II_DMTC2>, MFC2OP_FM<0x12, 5>, /// Move between CPU and coprocessor registers let DecoderNamespace = "Mips64", Predicates = [HasMips64] in { -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; +def DMFC0 : MFC3OP<"dmfc0", GPR64Opnd, COP0Opnd, II_DMFC0>, + MFC3OP_FM<0x10, 1, 0>, ISA_MIPS3; +def DMTC0 : MTC3OP<"dmtc0", COP0Opnd, GPR64Opnd, II_DMTC0>, + MFC3OP_FM<0x10, 5, 0>, ISA_MIPS3; +def DMFC2 : MFC3OP<"dmfc2", GPR64Opnd, COP2Opnd, II_DMFC2>, + MFC3OP_FM<0x12, 1, 0>, ISA_MIPS3; +def DMTC2 : MTC3OP<"dmtc2", COP2Opnd, GPR64Opnd, II_DMTC2>, + MFC3OP_FM<0x12, 5, 0>, ISA_MIPS3; } +/// Move between CPU and guest coprocessor registers (Virtualization ASE) +let DecoderNamespace = "Mips64" in { + def DMFGC0 : MFC3OP<"dmfgc0", GPR64Opnd, COP0Opnd, II_DMFGC0>, + MFC3OP_FM<0x10, 3, 1>, ISA_MIPS64R5, ASE_VIRT; + def DMTGC0 : MTC3OP<"dmtgc0", COP0Opnd, GPR64Opnd, II_DMTGC0>, + MFC3OP_FM<0x10, 3, 3>, ISA_MIPS64R5, ASE_VIRT; +} + +let AdditionalPredicates = [UseIndirectJumpsHazard] in + def JALRHB64Pseudo : JumpLinkRegPseudo<GPR64Opnd, JALR_HB64, RA_64>; + //===----------------------------------------------------------------------===// // Arbitrary patterns that map to one or more instructions //===----------------------------------------------------------------------===// // Materialize i64 constants. -defm : MaterializeImms<i64, ZERO_64, DADDiu, LUi64, ORi64>; +defm : MaterializeImms<i64, ZERO_64, DADDiu, LUi64, ORi64>, ISA_MIPS3, GPR_64; def : MipsPat<(i64 immZExt32Low16Zero:$imm), - (DSLL (ORi64 ZERO_64, (HI16 imm:$imm)), 16)>; + (DSLL (ORi64 ZERO_64, (HI16 imm:$imm)), 16)>, ISA_MIPS3, GPR_64; def : MipsPat<(i64 immZExt32:$imm), (ORi64 (DSLL (ORi64 ZERO_64, (HI16 imm:$imm)), 16), - (LO16 imm:$imm))>; + (LO16 imm:$imm))>, ISA_MIPS3, GPR_64; // extended loads -def : MipsPat<(i64 (extloadi1 addr:$src)), (LB64 addr:$src)>; -def : MipsPat<(i64 (extloadi8 addr:$src)), (LB64 addr:$src)>; -def : MipsPat<(i64 (extloadi16 addr:$src)), (LH64 addr:$src)>; -def : MipsPat<(i64 (extloadi32 addr:$src)), (LW64 addr:$src)>; +def : MipsPat<(i64 (extloadi1 addr:$src)), (LB64 addr:$src)>, ISA_MIPS3, + GPR_64; +def : MipsPat<(i64 (extloadi8 addr:$src)), (LB64 addr:$src)>, ISA_MIPS3, + GPR_64; +def : MipsPat<(i64 (extloadi16 addr:$src)), (LH64 addr:$src)>, ISA_MIPS3, + GPR_64; +def : MipsPat<(i64 (extloadi32 addr:$src)), (LW64 addr:$src)>, ISA_MIPS3, + GPR_64; // hi/lo relocs let AdditionalPredicates = [NotInMicroMips] in -defm : MipsHiLoRelocs<LUi64, DADDiu, ZERO_64, GPR64Opnd>, SYM_32; +defm : MipsHiLoRelocs<LUi64, DADDiu, ZERO_64, GPR64Opnd>, ISA_MIPS3, GPR_64, + SYM_32; -def : MipsPat<(MipsGotHi tglobaladdr:$in), (LUi64 tglobaladdr:$in)>; -def : MipsPat<(MipsGotHi texternalsym:$in), (LUi64 texternalsym:$in)>; +def : MipsPat<(MipsGotHi tglobaladdr:$in), (LUi64 tglobaladdr:$in)>, ISA_MIPS3, + GPR_64; +def : MipsPat<(MipsGotHi texternalsym:$in), (LUi64 texternalsym:$in)>, + ISA_MIPS3, GPR_64; + +def : MipsPat<(MipsTlsHi tglobaltlsaddr:$in), (LUi64 tglobaltlsaddr:$in)>, + ISA_MIPS3, GPR_64; // highest/higher/hi/lo relocs let AdditionalPredicates = [NotInMicroMips] in { def : MipsPat<(MipsJmpLink (i64 texternalsym:$dst)), - (JAL texternalsym:$dst)>, SYM_64; + (JAL texternalsym:$dst)>, ISA_MIPS3, GPR_64, SYM_64; def : MipsPat<(MipsHighest (i64 tglobaladdr:$in)), - (LUi64 tglobaladdr:$in)>, SYM_64; + (LUi64 tglobaladdr:$in)>, ISA_MIPS3, GPR_64, SYM_64; def : MipsPat<(MipsHighest (i64 tblockaddress:$in)), - (LUi64 tblockaddress:$in)>, SYM_64; + (LUi64 tblockaddress:$in)>, ISA_MIPS3, GPR_64, SYM_64; def : MipsPat<(MipsHighest (i64 tjumptable:$in)), - (LUi64 tjumptable:$in)>, SYM_64; + (LUi64 tjumptable:$in)>, ISA_MIPS3, GPR_64, SYM_64; def : MipsPat<(MipsHighest (i64 tconstpool:$in)), - (LUi64 tconstpool:$in)>, SYM_64; - def : MipsPat<(MipsHighest (i64 tglobaltlsaddr:$in)), - (LUi64 tglobaltlsaddr:$in)>, SYM_64; + (LUi64 tconstpool:$in)>, ISA_MIPS3, GPR_64, SYM_64; def : MipsPat<(MipsHighest (i64 texternalsym:$in)), - (LUi64 texternalsym:$in)>, SYM_64; + (LUi64 texternalsym:$in)>, ISA_MIPS3, GPR_64, SYM_64; def : MipsPat<(MipsHigher (i64 tglobaladdr:$in)), - (DADDiu ZERO_64, tglobaladdr:$in)>, SYM_64; + (DADDiu ZERO_64, tglobaladdr:$in)>, ISA_MIPS3, GPR_64, SYM_64; def : MipsPat<(MipsHigher (i64 tblockaddress:$in)), - (DADDiu ZERO_64, tblockaddress:$in)>, SYM_64; + (DADDiu ZERO_64, tblockaddress:$in)>, ISA_MIPS3, GPR_64, SYM_64; def : MipsPat<(MipsHigher (i64 tjumptable:$in)), - (DADDiu ZERO_64, tjumptable:$in)>, SYM_64; + (DADDiu ZERO_64, tjumptable:$in)>, ISA_MIPS3, GPR_64, SYM_64; def : MipsPat<(MipsHigher (i64 tconstpool:$in)), - (DADDiu ZERO_64, tconstpool:$in)>, SYM_64; - def : MipsPat<(MipsHigher (i64 tglobaltlsaddr:$in)), - (DADDiu ZERO_64, tglobaltlsaddr:$in)>, SYM_64; + (DADDiu ZERO_64, tconstpool:$in)>, ISA_MIPS3, GPR_64, SYM_64; def : MipsPat<(MipsHigher (i64 texternalsym:$in)), - (DADDiu ZERO_64, texternalsym:$in)>, SYM_64; + (DADDiu ZERO_64, texternalsym:$in)>, ISA_MIPS3, GPR_64, SYM_64; def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 tglobaladdr:$lo))), - (DADDiu GPR64:$hi, tglobaladdr:$lo)>, SYM_64; + (DADDiu GPR64:$hi, tglobaladdr:$lo)>, ISA_MIPS3, GPR_64, SYM_64; def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 tblockaddress:$lo))), - (DADDiu GPR64:$hi, tblockaddress:$lo)>, SYM_64; + (DADDiu GPR64:$hi, tblockaddress:$lo)>, ISA_MIPS3, GPR_64, + SYM_64; def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 tjumptable:$lo))), - (DADDiu GPR64:$hi, tjumptable:$lo)>, SYM_64; + (DADDiu GPR64:$hi, tjumptable:$lo)>, ISA_MIPS3, GPR_64, SYM_64; def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 tconstpool:$lo))), - (DADDiu GPR64:$hi, tconstpool:$lo)>, SYM_64; - def : MipsPat<(add GPR64:$hi, (MipsHigher (i64 tglobaltlsaddr:$lo))), - (DADDiu GPR64:$hi, tglobaltlsaddr:$lo)>, SYM_64; + (DADDiu GPR64:$hi, tconstpool:$lo)>, ISA_MIPS3, GPR_64, SYM_64; def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tglobaladdr:$lo))), - (DADDiu GPR64:$hi, tglobaladdr:$lo)>, SYM_64; + (DADDiu GPR64:$hi, tglobaladdr:$lo)>, ISA_MIPS3, GPR_64, SYM_64; def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tblockaddress:$lo))), - (DADDiu GPR64:$hi, tblockaddress:$lo)>, SYM_64; + (DADDiu GPR64:$hi, tblockaddress:$lo)>, ISA_MIPS3, GPR_64, + SYM_64; def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tjumptable:$lo))), - (DADDiu GPR64:$hi, tjumptable:$lo)>, SYM_64; + (DADDiu GPR64:$hi, tjumptable:$lo)>, ISA_MIPS3, GPR_64, SYM_64; def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tconstpool:$lo))), - (DADDiu GPR64:$hi, tconstpool:$lo)>, SYM_64; - def : MipsPat<(add GPR64:$hi, (MipsHi (i64 tglobaltlsaddr:$lo))), - (DADDiu GPR64:$hi, tglobaltlsaddr:$lo)>, SYM_64; + (DADDiu GPR64:$hi, tconstpool:$lo)>, ISA_MIPS3, GPR_64, SYM_64; def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tglobaladdr:$lo))), - (DADDiu GPR64:$hi, tglobaladdr:$lo)>, SYM_64; + (DADDiu GPR64:$hi, tglobaladdr:$lo)>, ISA_MIPS3, GPR_64, SYM_64; def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tblockaddress:$lo))), - (DADDiu GPR64:$hi, tblockaddress:$lo)>, SYM_64; + (DADDiu GPR64:$hi, tblockaddress:$lo)>, ISA_MIPS3, GPR_64, + SYM_64; def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tjumptable:$lo))), - (DADDiu GPR64:$hi, tjumptable:$lo)>, SYM_64; + (DADDiu GPR64:$hi, tjumptable:$lo)>, ISA_MIPS3, GPR_64, SYM_64; def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tconstpool:$lo))), - (DADDiu GPR64:$hi, tconstpool:$lo)>, SYM_64; + (DADDiu GPR64:$hi, tconstpool:$lo)>, ISA_MIPS3, GPR_64, SYM_64; def : MipsPat<(add GPR64:$hi, (MipsLo (i64 tglobaltlsaddr:$lo))), - (DADDiu GPR64:$hi, tglobaltlsaddr:$lo)>, SYM_64; + (DADDiu GPR64:$hi, tglobaltlsaddr:$lo)>, ISA_MIPS3, GPR_64, + SYM_64; } // gp_rel relocs def : MipsPat<(add GPR64:$gp, (MipsGPRel tglobaladdr:$in)), - (DADDiu GPR64:$gp, tglobaladdr:$in)>, ABI_N64; + (DADDiu GPR64:$gp, tglobaladdr:$in)>, ISA_MIPS3, ABI_N64; def : MipsPat<(add GPR64:$gp, (MipsGPRel tconstpool:$in)), - (DADDiu GPR64:$gp, tconstpool:$in)>, ABI_N64; + (DADDiu GPR64:$gp, tconstpool:$in)>, ISA_MIPS3, ABI_N64; -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>; +def : WrapperPat<tglobaladdr, DADDiu, GPR64>, ISA_MIPS3, GPR_64; +def : WrapperPat<tconstpool, DADDiu, GPR64>, ISA_MIPS3, GPR_64; +def : WrapperPat<texternalsym, DADDiu, GPR64>, ISA_MIPS3, GPR_64; +def : WrapperPat<tblockaddress, DADDiu, GPR64>, ISA_MIPS3, GPR_64; +def : WrapperPat<tjumptable, DADDiu, GPR64>, ISA_MIPS3, GPR_64; +def : WrapperPat<tglobaltlsaddr, DADDiu, GPR64>, ISA_MIPS3, GPR_64; defm : BrcondPats<GPR64, BEQ64, BEQ, BNE64, SLT64, SLTu64, SLTi64, SLTiu64, - ZERO_64>; + ZERO_64>, ISA_MIPS3, GPR_64; def : MipsPat<(brcond (i32 (setlt i64:$lhs, 1)), bb:$dst), - (BLEZ64 i64:$lhs, bb:$dst)>; + (BLEZ64 i64:$lhs, bb:$dst)>, ISA_MIPS3, GPR_64; def : MipsPat<(brcond (i32 (setgt i64:$lhs, -1)), bb:$dst), - (BGEZ64 i64:$lhs, bb:$dst)>; + (BGEZ64 i64:$lhs, bb:$dst)>, ISA_MIPS3, GPR_64; // setcc patterns let AdditionalPredicates = [NotInMicroMips] in { - defm : SeteqPats<GPR64, SLTiu64, XOR64, SLTu64, ZERO_64>; - defm : SetlePats<GPR64, XORi, SLT64, SLTu64>; - defm : SetgtPats<GPR64, SLT64, SLTu64>; - defm : SetgePats<GPR64, XORi, SLT64, SLTu64>; - defm : SetgeImmPats<GPR64, XORi, SLTi64, SLTiu64>; + defm : SeteqPats<GPR64, SLTiu64, XOR64, SLTu64, ZERO_64>, ISA_MIPS3, GPR_64; + defm : SetlePats<GPR64, XORi, SLT64, SLTu64>, ISA_MIPS3, GPR_64; + defm : SetgtPats<GPR64, SLT64, SLTu64>, ISA_MIPS3, GPR_64; + defm : SetgePats<GPR64, XORi, SLT64, SLTu64>, ISA_MIPS3, GPR_64; + defm : SetgeImmPats<GPR64, XORi, SLTi64, SLTiu64>, ISA_MIPS3, GPR_64; } // truncate def : MipsPat<(trunc (assertsext GPR64:$src)), - (EXTRACT_SUBREG GPR64:$src, sub_32)>; + (EXTRACT_SUBREG GPR64:$src, sub_32)>, ISA_MIPS3, GPR_64; // 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 @@ -670,80 +735,134 @@ def : MipsPat<(trunc (assertsext GPR64:$src)), // 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)>; + (EXTRACT_SUBREG GPR64:$src, sub_32)>, ISA_MIPS3, GPR_64; def : MipsPat<(i32 (trunc GPR64:$src)), - (SLL (EXTRACT_SUBREG GPR64:$src, sub_32), 0)>; + (SLL (EXTRACT_SUBREG GPR64:$src, sub_32), 0)>, ISA_MIPS3, GPR_64; // variable shift instructions patterns def : MipsPat<(shl GPR64:$rt, (i32 (trunc GPR64:$rs))), - (DSLLV GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>; + (DSLLV GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>, + ISA_MIPS3, GPR_64; def : MipsPat<(srl GPR64:$rt, (i32 (trunc GPR64:$rs))), - (DSRLV GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>; + (DSRLV GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>, + ISA_MIPS3, GPR_64; def : MipsPat<(sra GPR64:$rt, (i32 (trunc GPR64:$rs))), - (DSRAV 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))>; -} + (DSRAV GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>, + ISA_MIPS3, GPR_64; +def : MipsPat<(rotr GPR64:$rt, (i32 (trunc GPR64:$rs))), + (DROTRV GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>, + ISA_MIPS3, GPR_64; // 32-to-64-bit extension 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)>; + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GPR32:$src, sub_32)>, + ISA_MIPS3, GPR_64; +def : MipsPat<(i64 (zext GPR32:$src)), (DSRL (DSLL64_32 GPR32:$src), 32)>, + ISA_MIPS3, GPR_64; +def : MipsPat<(i64 (sext GPR32:$src)), (SLL64_32 GPR32:$src)>, ISA_MIPS3, + GPR_64; let AdditionalPredicates = [NotInMicroMips] in { def : MipsPat<(i64 (zext GPR32:$src)), (DEXT64_32 GPR32:$src, 0, 32)>, - ISA_MIPS64R2; + ISA_MIPS64R2, GPR_64; def : MipsPat<(i64 (zext (i32 (shl GPR32:$rt, immZExt5:$imm)))), (CINS64_32 GPR32:$rt, imm:$imm, (immZExt5To31 imm:$imm))>, - ASE_MIPS64_CNMIPS; + ISA_MIPS64R2, GPR_64, ASE_MIPS64_CNMIPS; } // Sign extend in register def : MipsPat<(i64 (sext_inreg GPR64:$src, i32)), - (SLL64_64 GPR64:$src)>; + (SLL64_64 GPR64:$src)>, ISA_MIPS3, GPR_64; // bswap MipsPattern -def : MipsPat<(bswap GPR64:$rt), (DSHD (DSBH GPR64:$rt))>; +def : MipsPat<(bswap GPR64:$rt), (DSHD (DSBH GPR64:$rt))>, ISA_MIPS64R2; // Carry pattern let AdditionalPredicates = [NotInMicroMips] in { def : MipsPat<(subc GPR64:$lhs, GPR64:$rhs), - (DSUBu GPR64:$lhs, GPR64:$rhs)>; + (DSUBu GPR64:$lhs, GPR64:$rhs)>, ISA_MIPS3, GPR_64; def : MipsPat<(addc GPR64:$lhs, GPR64:$rhs), - (DADDu GPR64:$lhs, GPR64:$rhs)>, ASE_NOT_DSP; + (DADDu GPR64:$lhs, GPR64:$rhs)>, ISA_MIPS3, ASE_NOT_DSP, GPR_64; def : MipsPat<(addc GPR64:$lhs, immSExt16:$imm), - (DADDiu GPR64:$lhs, imm:$imm)>, ASE_NOT_DSP; + (DADDiu GPR64:$lhs, imm:$imm)>, ISA_MIPS3, ASE_NOT_DSP, GPR_64; } // Octeon bbit0/bbit1 MipsPattern def : MipsPat<(brcond (i32 (seteq (and i64:$lhs, PowerOf2LO:$mask), 0)), bb:$dst), - (BBIT0 i64:$lhs, (Log2LO PowerOf2LO:$mask), bb:$dst)>, ASE_MIPS64_CNMIPS; + (BBIT0 i64:$lhs, (Log2LO PowerOf2LO:$mask), bb:$dst)>, + ISA_MIPS64R2, ASE_MIPS64_CNMIPS; def : MipsPat<(brcond (i32 (seteq (and i64:$lhs, PowerOf2HI:$mask), 0)), bb:$dst), - (BBIT032 i64:$lhs, (Log2HI PowerOf2HI:$mask), bb:$dst)>, ASE_MIPS64_CNMIPS; + (BBIT032 i64:$lhs, (Log2HI PowerOf2HI:$mask), bb:$dst)>, + ISA_MIPS64R2, ASE_MIPS64_CNMIPS; def : MipsPat<(brcond (i32 (setne (and i64:$lhs, PowerOf2LO:$mask), 0)), bb:$dst), - (BBIT1 i64:$lhs, (Log2LO PowerOf2LO:$mask), bb:$dst)>, ASE_MIPS64_CNMIPS; + (BBIT1 i64:$lhs, (Log2LO PowerOf2LO:$mask), bb:$dst)>, + ISA_MIPS64R2, ASE_MIPS64_CNMIPS; def : MipsPat<(brcond (i32 (setne (and i64:$lhs, PowerOf2HI:$mask), 0)), bb:$dst), - (BBIT132 i64:$lhs, (Log2HI PowerOf2HI:$mask), bb:$dst)>, ASE_MIPS64_CNMIPS; + (BBIT132 i64:$lhs, (Log2HI PowerOf2HI:$mask), bb:$dst)>, + ISA_MIPS64R2, ASE_MIPS64_CNMIPS; def : MipsPat<(brcond (i32 (seteq (and i32:$lhs, PowerOf2LO_i32:$mask), 0)), bb:$dst), (BBIT0 (INSERT_SUBREG (i64 (IMPLICIT_DEF)), i32:$lhs, sub_32), - (Log2LO PowerOf2LO_i32:$mask), bb:$dst)>, ASE_MIPS64_CNMIPS; + (Log2LO PowerOf2LO_i32:$mask), bb:$dst)>, ISA_MIPS64R2, + ASE_MIPS64_CNMIPS; def : MipsPat<(brcond (i32 (setne (and i32:$lhs, PowerOf2LO_i32:$mask), 0)), bb:$dst), (BBIT1 (INSERT_SUBREG (i64 (IMPLICIT_DEF)), i32:$lhs, sub_32), - (Log2LO PowerOf2LO_i32:$mask), bb:$dst)>, ASE_MIPS64_CNMIPS; + (Log2LO PowerOf2LO_i32:$mask), bb:$dst)>, ISA_MIPS64R2, + ASE_MIPS64_CNMIPS; // Atomic load patterns. -def : MipsPat<(atomic_load_8 addr:$a), (LB64 addr:$a)>; -def : MipsPat<(atomic_load_16 addr:$a), (LH64 addr:$a)>; -def : MipsPat<(atomic_load_32 addr:$a), (LW64 addr:$a)>; -def : MipsPat<(atomic_load_64 addr:$a), (LD addr:$a)>; +def : MipsPat<(atomic_load_8 addr:$a), (LB64 addr:$a)>, ISA_MIPS3, GPR_64; +def : MipsPat<(atomic_load_16 addr:$a), (LH64 addr:$a)>, ISA_MIPS3, GPR_64; +def : MipsPat<(atomic_load_32 addr:$a), (LW64 addr:$a)>, ISA_MIPS3, GPR_64; +def : MipsPat<(atomic_load_64 addr:$a), (LD addr:$a)>, ISA_MIPS3, GPR_64; // Atomic store patterns. -def : MipsPat<(atomic_store_8 addr:$a, GPR64:$v), (SB64 GPR64:$v, addr:$a)>; -def : MipsPat<(atomic_store_16 addr:$a, GPR64:$v), (SH64 GPR64:$v, addr:$a)>; -def : MipsPat<(atomic_store_32 addr:$a, GPR64:$v), (SW64 GPR64:$v, addr:$a)>; -def : MipsPat<(atomic_store_64 addr:$a, GPR64:$v), (SD GPR64:$v, addr:$a)>; +def : MipsPat<(atomic_store_8 addr:$a, GPR64:$v), (SB64 GPR64:$v, addr:$a)>, + ISA_MIPS3, GPR_64; +def : MipsPat<(atomic_store_16 addr:$a, GPR64:$v), (SH64 GPR64:$v, addr:$a)>, + ISA_MIPS3, GPR_64; +def : MipsPat<(atomic_store_32 addr:$a, GPR64:$v), (SW64 GPR64:$v, addr:$a)>, + ISA_MIPS3, GPR_64; +def : MipsPat<(atomic_store_64 addr:$a, GPR64:$v), (SD GPR64:$v, addr:$a)>, + ISA_MIPS3, GPR_64; + +// Patterns used for matching away redundant sign extensions. +// MIPS32 arithmetic instructions sign extend their result implicitly. +def : MipsPat<(i64 (sext (i32 (add GPR32:$src, immSExt16:$imm16)))), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (ADDiu GPR32:$src, immSExt16:$imm16), sub_32)>; +def : MipsPat<(i64 (sext (i32 (add GPR32:$src, GPR32:$src2)))), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (ADDu GPR32:$src, GPR32:$src2), sub_32)>; +def : MipsPat<(i64 (sext (i32 (sub GPR32:$src, GPR32:$src2)))), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (SUBu GPR32:$src, GPR32:$src2), sub_32)>; +def : MipsPat<(i64 (sext (i32 (mul GPR32:$src, GPR32:$src2)))), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (MUL GPR32:$src, GPR32:$src2), sub_32)>; +def : MipsPat<(i64 (sext (i32 (MipsMFHI ACC64:$src)))), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (PseudoMFHI ACC64:$src), sub_32)>; +def : MipsPat<(i64 (sext (i32 (MipsMFLO ACC64:$src)))), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (PseudoMFLO ACC64:$src), sub_32)>; +def : MipsPat<(i64 (sext (i32 (shl GPR32:$src, immZExt5:$imm5)))), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (SLL GPR32:$src, immZExt5:$imm5), sub_32)>; +def : MipsPat<(i64 (sext (i32 (shl GPR32:$src, GPR32:$src2)))), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (SLLV GPR32:$src, GPR32:$src2), sub_32)>; +def : MipsPat<(i64 (sext (i32 (srl GPR32:$src, immZExt5:$imm5)))), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (SRL GPR32:$src, immZExt5:$imm5), sub_32)>; +def : MipsPat<(i64 (sext (i32 (srl GPR32:$src, GPR32:$src2)))), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (SRLV GPR32:$src, GPR32:$src2), sub_32)>; +def : MipsPat<(i64 (sext (i32 (sra GPR32:$src, immZExt5:$imm5)))), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (SRA GPR32:$src, immZExt5:$imm5), sub_32)>; +def : MipsPat<(i64 (sext (i32 (sra GPR32:$src, GPR32:$src2)))), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (SRAV GPR32:$src, GPR32:$src2), sub_32)>; //===----------------------------------------------------------------------===// // Instruction aliases @@ -769,13 +888,13 @@ let AdditionalPredicates = [NotInMicroMips] in { 0>, ISA_MIPS3; defm : OneOrTwoOperandMacroImmediateAlias<"and", ANDi64, GPR64Opnd, imm64>, - GPR_64; + ISA_MIPS3, GPR_64; defm : OneOrTwoOperandMacroImmediateAlias<"or", ORi64, GPR64Opnd, imm64>, - GPR_64; + ISA_MIPS3, GPR_64; defm : OneOrTwoOperandMacroImmediateAlias<"xor", XORi64, GPR64Opnd, imm64>, - GPR_64; + ISA_MIPS3, GPR_64; } let AdditionalPredicates = [NotInMicroMips] in { def : MipsInstAlias<"dneg $rt, $rs", @@ -843,12 +962,19 @@ let AdditionalPredicates = [NotInMicroMips] in { def : MipsInstAlias<"dext $rt, $rs, $pos, $size", (DEXTU GPR64Opnd:$rt, GPR64Opnd:$rs, uimm5_plus32:$pos, uimm5_plus1:$size), 0>, ISA_MIPS64R2; - + def : MipsInstAlias<"jalr.hb $rs", (JALR_HB64 RA_64, GPR64Opnd:$rs), 1>, + ISA_MIPS64; // Two operand (implicit 0 selector) versions: 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<"dmfgc0 $rt, $rd", + (DMFGC0 GPR64Opnd:$rt, COP0Opnd:$rd, 0), 0>, + ISA_MIPS64R5, ASE_VIRT; + def : MipsInstAlias<"dmtgc0 $rt, $rd", + (DMTGC0 COP0Opnd:$rd, GPR64Opnd:$rt, 0), 0>, + ISA_MIPS64R5, ASE_VIRT; } def : MipsInstAlias<"dmfc2 $rt, $rd", (DMFC2 GPR64Opnd:$rt, COP2Opnd:$rd, 0), 0>; def : MipsInstAlias<"dmtc2 $rt, $rd", (DMTC2 COP2Opnd:$rd, GPR64Opnd:$rt, 0), 0>; @@ -966,6 +1092,38 @@ let AdditionalPredicates = [NotInMicroMips] in { GPR64Opnd:$rd, imm64:$imm), 0>, ISA_MIPS3_NOT_32R6_64R6; + def DSRemMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), + (ins GPR64Opnd:$rs, GPR64Opnd:$rt), + "drem\t$rd, $rs, $rt">, + ISA_MIPS3_NOT_32R6_64R6; + def DSRemIMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), + (ins GPR64Opnd:$rs, simm32_relaxed:$imm), + "drem\t$rd, $rs, $imm">, + ISA_MIPS3_NOT_32R6_64R6; + def DURemMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), + (ins GPR64Opnd:$rs, GPR64Opnd:$rt), + "dremu\t$rd, $rs, $rt">, + ISA_MIPS3_NOT_32R6_64R6; + def DURemIMacro : MipsAsmPseudoInst<(outs GPR64Opnd:$rd), + (ins GPR64Opnd:$rs, simm32_relaxed:$imm), + "dremu\t$rd, $rs, $imm">, + ISA_MIPS3_NOT_32R6_64R6; + def : MipsInstAlias<"drem $rt, $rs", (DSRemMacro GPR64Opnd:$rt, + GPR64Opnd:$rt, + GPR64Opnd:$rs), 0>, + ISA_MIPS3_NOT_32R6_64R6; + def : MipsInstAlias<"drem $rd, $imm", (DSRemIMacro GPR64Opnd:$rd, + GPR64Opnd:$rd, + simm32_relaxed:$imm), 0>, + ISA_MIPS3_NOT_32R6_64R6; + def : MipsInstAlias<"dremu $rt, $rs", (DURemMacro GPR64Opnd:$rt, + GPR64Opnd:$rt, + GPR64Opnd:$rs), 0>, + ISA_MIPS3_NOT_32R6_64R6; + def : MipsInstAlias<"dremu $rd, $imm", (DURemIMacro GPR64Opnd:$rd, + GPR64Opnd:$rd, + simm32_relaxed:$imm), 0>, + ISA_MIPS3_NOT_32R6_64R6; } def NORImm64 : NORIMM_DESC_BASE<GPR64Opnd, imm64>, GPR_64; diff --git a/lib/Target/Mips/Mips64r6InstrInfo.td b/lib/Target/Mips/Mips64r6InstrInfo.td index 1cd43ee6f1c3..9df802cc30b9 100644 --- a/lib/Target/Mips/Mips64r6InstrInfo.td +++ b/lib/Target/Mips/Mips64r6InstrInfo.td @@ -39,6 +39,8 @@ class DMULU_ENC : SPECIAL_3R_FM<0b00010, 0b011101>; class LDPC_ENC : PCREL18_FM<OPCODE3_LDPC>; class LLD_R6_ENC : SPECIAL3_LL_SC_FM<OPCODE6_LLD>; class SCD_R6_ENC : SPECIAL3_LL_SC_FM<OPCODE6_SCD>; +class CRC32D_ENC : SPECIAL3_2R_SZ_CRC<3,0>; +class CRC32CD_ENC : SPECIAL3_2R_SZ_CRC<3,1>; //===----------------------------------------------------------------------===// // @@ -71,7 +73,7 @@ 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 LLD_R6_DESC : LL_R6_DESC_BASE<"lld", GPR64Opnd, mem_simmptr, 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>; @@ -104,6 +106,20 @@ class JIC64_DESC : JMP_IDX_COMPACT_DESC_BASE<"jic", jmpoffset16, GPR64Opnd, 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>; + +class JR_HB64_R6_DESC : JR_HB_DESC_BASE<"jr.hb", GPR64Opnd> { + bit isBranch = 1; + bit isIndirectBranch = 1; + bit hasDelaySlot = 1; + bit isTerminator=1; + bit isBarrier=1; + bit isCTI = 1; + InstrItinClass Itinerary = II_JR_HB; +} + +class CRC32D_DESC : CRC_DESC_BASE<"crc32d", GPR32Opnd, II_CRC32D>; +class CRC32CD_DESC : CRC_DESC_BASE<"crc32cd", GPR32Opnd, II_CRC32CD>; + //===----------------------------------------------------------------------===// // // Instruction Definitions @@ -136,6 +152,7 @@ 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; + def JR_HB64_R6 : JR_HB_R6_ENC, JR_HB64_R6_DESC, ISA_MIPS32R6; } let AdditionalPredicates = [NotInMicroMips], DecoderNamespace = "Mips32r6_64r6_PTR64" in { @@ -163,6 +180,10 @@ let DecoderNamespace = "Mips32r6_64r6_BranchZero" in { def BLTZC64 : BLTZC_ENC, BLTZC64_DESC, ISA_MIPS64R6, GPR_64; def BGEZC64 : BGEZC_ENC, BGEZC64_DESC, ISA_MIPS64R6, GPR_64; } +let AdditionalPredicates = [NotInMicroMips] in { + def CRC32D : R6MMR6Rel, CRC32D_ENC, CRC32D_DESC, ISA_MIPS64R6, ASE_CRC; + def CRC32CD : R6MMR6Rel, CRC32CD_ENC, CRC32CD_DESC, ISA_MIPS64R6, ASE_CRC; +} //===----------------------------------------------------------------------===// // @@ -277,3 +298,37 @@ def : MipsPat<(select (i32 (setne i32:$cond, immz)), immz, i64:$f), def : MipsPat<(select (i32 (seteq i32:$cond, immz)), immz, i64:$f), (SELNEZ64 i64:$f, (SLL64_32 i32:$cond))>, ISA_MIPS64R6; + +// Patterns used for matching away redundant sign extensions. +// MIPS32 arithmetic instructions sign extend their result implicitly. +def : MipsPat<(i64 (sext (i32 (sdiv GPR32:$src, GPR32:$src2)))), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (DIV GPR32:$src, GPR32:$src2), sub_32)>, ISA_MIPS64R6; +def : MipsPat<(i64 (sext (i32 (udiv GPR32:$src, GPR32:$src2)))), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (DIVU GPR32:$src, GPR32:$src2), sub_32)>, ISA_MIPS64R6; +def : MipsPat<(i64 (sext (i32 (srem GPR32:$src, GPR32:$src2)))), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (MOD GPR32:$src, GPR32:$src2), sub_32)>, ISA_MIPS64R6; +def : MipsPat<(i64 (sext (i32 (urem GPR32:$src, GPR32:$src2)))), + (INSERT_SUBREG (i64 (IMPLICIT_DEF)), + (MODU GPR32:$src, GPR32:$src2), sub_32)>, ISA_MIPS64R6; + +// Pseudo instructions + +let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips, + NoIndirectJumpGuards] in { + def TAILCALL64R6REG : TailCallRegR6<JALR64, ZERO_64, GPR64Opnd>, ISA_MIPS64R6; + def PseudoIndirectBranch64R6 : PseudoIndirectBranchBaseR6<JALR64, ZERO_64, + GPR64Opnd>, + ISA_MIPS64R6; +} + +let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips, + UseIndirectJumpsHazard] in { + def TAILCALLHB64R6REG : TailCallReg<JR_HB64_R6, GPR64Opnd>, + ISA_MIPS64R6; + def PseudoIndrectHazardBranch64R6 : PseudoIndirectBranchBase<JR_HB64_R6, + GPR64Opnd>, + ISA_MIPS64R6; +} diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp index f9de78dc281f..8ffc0731abcb 100644 --- a/lib/Target/Mips/MipsAsmPrinter.cpp +++ b/lib/Target/Mips/MipsAsmPrinter.cpp @@ -160,6 +160,8 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) { PrintDebugValueComment(MI, OS); return; } + if (MI->isDebugLabel()) + return; // If we just ended a constant pool, mark it as such. if (InConstantPool && Opc != Mips::CONSTPOOL_ENTRY) { @@ -499,6 +501,13 @@ bool MipsAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, return true; O << MO.getImm() - 1; return false; + case 'y': // exact log2 + if ((MO.getType()) != MachineOperand::MO_Immediate) + return true; + if (!isPowerOf2_64(MO.getImm())) + return true; + O << Log2_64(MO.getImm()); + return false; case 'z': // $0 if zero, regular printing otherwise if (MO.getType() == MachineOperand::MO_Immediate && MO.getImm() == 0) { @@ -576,17 +585,27 @@ bool MipsAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, assert(OffsetMO.isImm() && "Unexpected offset for inline asm memory operand."); int Offset = OffsetMO.getImm(); - // Currently we are expecting either no ExtraCode or 'D' + // Currently we are expecting either no ExtraCode or 'D','M','L'. if (ExtraCode) { - if (ExtraCode[0] == 'D') + switch (ExtraCode[0]) { + case 'D': Offset += 4; - else + break; + case 'M': + if (Subtarget->isLittle()) + Offset += 4; + break; + case 'L': + if (!Subtarget->isLittle()) + Offset += 4; + break; + default: return true; // Unknown modifier. - // FIXME: M = high order bits - // FIXME: L = low order bits + } } - O << Offset << "($" << MipsInstPrinter::getRegisterName(BaseMO.getReg()) << ")"; + O << Offset << "($" << MipsInstPrinter::getRegisterName(BaseMO.getReg()) + << ")"; return false; } diff --git a/lib/Target/Mips/MipsLongBranch.cpp b/lib/Target/Mips/MipsBranchExpansion.cpp index bbf2050ce1eb..af936e6fc96b 100644 --- a/lib/Target/Mips/MipsLongBranch.cpp +++ b/lib/Target/Mips/MipsBranchExpansion.cpp @@ -1,4 +1,4 @@ -//===- MipsLongBranch.cpp - Emit long branches ----------------------------===// +//===----------------------- MipsBranchExpansion.cpp ----------------------===// // // The LLVM Compiler Infrastructure // @@ -6,11 +6,70 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This pass expands a branch or jump instruction into a long branch if its -// offset is too large to fit into its immediate field. -// -// FIXME: Fix pc-region jump instructions which cross 256MB segment boundaries. +/// \file +/// +/// This pass do two things: +/// - it expands a branch or jump instruction into a long branch if its offset +/// is too large to fit into its immediate field, +/// - it inserts nops to prevent forbidden slot hazards. +/// +/// The reason why this pass combines these two tasks is that one of these two +/// tasks can break the result of the previous one. +/// +/// Example of that is a situation where at first, no branch should be expanded, +/// but after adding at least one nop somewhere in the code to prevent a +/// forbidden slot hazard, offset of some branches may go out of range. In that +/// case it is necessary to check again if there is some branch that needs +/// expansion. On the other hand, expanding some branch may cause a control +/// transfer instruction to appear in the forbidden slot, which is a hazard that +/// should be fixed. This pass alternates between this two tasks untill no +/// changes are made. Only then we can be sure that all branches are expanded +/// properly, and no hazard situations exist. +/// +/// Regarding branch expanding: +/// +/// When branch instruction like beqzc or bnezc has offset that is too large +/// to fit into its immediate field, it has to be expanded to another +/// instruction or series of instructions. +/// +/// FIXME: Fix pc-region jump instructions which cross 256MB segment boundaries. +/// TODO: Handle out of range bc, b (pseudo) instructions. +/// +/// Regarding compact branch hazard prevention: +/// +/// 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 insufficient, as +/// backwards delay slot fillling can also produce hazards in previously +/// processed instuctions. +/// +/// In future this pass can be extended (or new pass can be created) to handle +/// 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 such as compact branch hazard, hence the existing hazard +/// recognizer is not suitable. +/// //===----------------------------------------------------------------------===// #include "MCTargetDesc/MipsABIInfo.h" @@ -30,6 +89,7 @@ #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineInstrBuilder.h" +#include "llvm/CodeGen/MachineModuleInfo.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" #include "llvm/IR/DebugLoc.h" @@ -37,76 +97,126 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MathExtras.h" #include "llvm/Target/TargetMachine.h" +#include <algorithm> #include <cassert> #include <cstdint> #include <iterator> +#include <utility> using namespace llvm; -#define DEBUG_TYPE "mips-long-branch" +#define DEBUG_TYPE "mips-branch-expansion" +STATISTIC(NumInsertedNops, "Number of nops inserted"); STATISTIC(LongBranches, "Number of long branches."); -static cl::opt<bool> SkipLongBranch( - "skip-mips-long-branch", - cl::init(false), - cl::desc("MIPS: Skip long branch pass."), - cl::Hidden); +static cl::opt<bool> + SkipLongBranch("skip-mips-long-branch", cl::init(false), + cl::desc("MIPS: Skip branch expansion pass."), cl::Hidden); -static cl::opt<bool> ForceLongBranch( - "force-mips-long-branch", - cl::init(false), - cl::desc("MIPS: Expand all branches to long format."), - cl::Hidden); +static cl::opt<bool> + ForceLongBranch("force-mips-long-branch", cl::init(false), + cl::desc("MIPS: Expand all branches to long format."), + cl::Hidden); namespace { - using Iter = MachineBasicBlock::iterator; - using ReverseIter = MachineBasicBlock::reverse_iterator; +using Iter = MachineBasicBlock::iterator; +using ReverseIter = MachineBasicBlock::reverse_iterator; - struct MBBInfo { - uint64_t Size = 0; - uint64_t Address; - bool HasLongBranch = false; - MachineInstr *Br = nullptr; +struct MBBInfo { + uint64_t Size = 0; + bool HasLongBranch = false; + MachineInstr *Br = nullptr; + MBBInfo() = default; +}; - MBBInfo() = default; - }; +class MipsBranchExpansion : public MachineFunctionPass { +public: + static char ID; - class MipsLongBranch : public MachineFunctionPass { - public: - static char ID; + MipsBranchExpansion() : MachineFunctionPass(ID), ABI(MipsABIInfo::Unknown()) { + initializeMipsBranchExpansionPass(*PassRegistry::getPassRegistry()); + } - MipsLongBranch() - : MachineFunctionPass(ID), ABI(MipsABIInfo::Unknown()) {} + StringRef getPassName() const override { + return "Mips Branch Expansion Pass"; + } - StringRef getPassName() const override { return "Mips Long Branch"; } + bool runOnMachineFunction(MachineFunction &F) override; - bool runOnMachineFunction(MachineFunction &F) override; + MachineFunctionProperties getRequiredProperties() const override { + return MachineFunctionProperties().set( + MachineFunctionProperties::Property::NoVRegs); + } - MachineFunctionProperties getRequiredProperties() const override { - return MachineFunctionProperties().set( - MachineFunctionProperties::Property::NoVRegs); - } +private: + void splitMBB(MachineBasicBlock *MBB); + void initMBBInfo(); + int64_t computeOffset(const MachineInstr *Br); + void replaceBranch(MachineBasicBlock &MBB, Iter Br, const DebugLoc &DL, + MachineBasicBlock *MBBOpnd); + void expandToLongBranch(MBBInfo &Info); + bool handleForbiddenSlot(); + bool handlePossibleLongBranch(); + + const MipsSubtarget *STI; + const MipsInstrInfo *TII; + + MachineFunction *MFp; + SmallVector<MBBInfo, 16> MBBInfos; + bool IsPIC; + MipsABIInfo ABI; + unsigned LongBranchSeqSize; + bool ForceLongBranchFirstPass = false; +}; + +} // end of anonymous namespace + +char MipsBranchExpansion::ID = 0; + +INITIALIZE_PASS(MipsBranchExpansion, DEBUG_TYPE, + "Expand out of range branch instructions and prevent forbidden" + " slot hazards", + false, false) + +/// Returns a pass that clears pipeline hazards. +FunctionPass *llvm::createMipsBranchExpansion() { + return new MipsBranchExpansion(); +} - private: - void splitMBB(MachineBasicBlock *MBB); - void initMBBInfo(); - int64_t computeOffset(const MachineInstr *Br); - void replaceBranch(MachineBasicBlock &MBB, Iter Br, const DebugLoc &DL, - MachineBasicBlock *MBBOpnd); - void expandToLongBranch(MBBInfo &Info); +// Find the next real instruction from the current position in current basic +// block. +static Iter getNextMachineInstrInBB(Iter Position) { + Iter I = Position, E = Position->getParent()->end(); + I = std::find_if_not(I, E, + [](const Iter &Insn) { return Insn->isTransient(); }); - MachineFunction *MF; - SmallVector<MBBInfo, 16> MBBInfos; - bool IsPIC; - MipsABIInfo ABI; - unsigned LongBranchSeqSize; - }; + return I; +} -} // end anonymous namespace +// Find the next real instruction from the current position, looking through +// basic block boundaries. +static std::pair<Iter, bool> getNextMachineInstr(Iter Position, + MachineBasicBlock *Parent) { + if (Position == Parent->end()) { + do { + MachineBasicBlock *Succ = Parent->getNextNode(); + if (Succ != nullptr && Parent->isSuccessor(Succ)) { + Position = Succ->begin(); + Parent = Succ; + } else { + return std::make_pair(Position, true); + } + } while (Parent->empty()); + } -char MipsLongBranch::ID = 0; + Iter Instr = getNextMachineInstrInBB(Position); + if (Instr == Parent->end()) { + return getNextMachineInstr(Instr, Parent); + } + return std::make_pair(Instr, false); +} /// Iterate over list of Br's operands and search for a MachineBasicBlock /// operand. @@ -125,14 +235,14 @@ static MachineBasicBlock *getTargetMBB(const MachineInstr &Br) { // found or it reaches E. static ReverseIter getNonDebugInstr(ReverseIter B, const ReverseIter &E) { for (; B != E; ++B) - if (!B->isDebugValue()) + if (!B->isDebugInstr()) return B; return E; } // Split MBB if it has two direct jumps/branches. -void MipsLongBranch::splitMBB(MachineBasicBlock *MBB) { +void MipsBranchExpansion::splitMBB(MachineBasicBlock *MBB) { ReverseIter End = MBB->rend(); ReverseIter LastBr = getNonDebugInstr(MBB->rbegin(), End); @@ -153,7 +263,7 @@ void MipsLongBranch::splitMBB(MachineBasicBlock *MBB) { // Create a new MBB. Move instructions in MBB to the newly created MBB. MachineBasicBlock *NewMBB = - MF->CreateMachineBasicBlock(MBB->getBasicBlock()); + MFp->CreateMachineBasicBlock(MBB->getBasicBlock()); // Insert NewMBB and fix control flow. MachineBasicBlock *Tgt = getTargetMBB(*FirstBr); @@ -161,26 +271,24 @@ void MipsLongBranch::splitMBB(MachineBasicBlock *MBB) { NewMBB->removeSuccessor(Tgt, true); MBB->addSuccessor(NewMBB); MBB->addSuccessor(Tgt); - MF->insert(std::next(MachineFunction::iterator(MBB)), NewMBB); + MFp->insert(std::next(MachineFunction::iterator(MBB)), NewMBB); NewMBB->splice(NewMBB->end(), MBB, LastBr.getReverse(), MBB->end()); } // Fill MBBInfos. -void MipsLongBranch::initMBBInfo() { +void MipsBranchExpansion::initMBBInfo() { // Split the MBBs if they have two branches. Each basic block should have at // most one branch after this loop is executed. - for (auto &MBB : *MF) + for (auto &MBB : *MFp) splitMBB(&MBB); - MF->RenumberBlocks(); + MFp->RenumberBlocks(); MBBInfos.clear(); - MBBInfos.resize(MF->size()); + MBBInfos.resize(MFp->size()); - const MipsInstrInfo *TII = - static_cast<const MipsInstrInfo *>(MF->getSubtarget().getInstrInfo()); for (unsigned I = 0, E = MBBInfos.size(); I < E; ++I) { - MachineBasicBlock *MBB = MF->getBlockNumbered(I); + MachineBasicBlock *MBB = MFp->getBlockNumbered(I); // Compute size of MBB. for (MachineBasicBlock::instr_iterator MI = MBB->instr_begin(); @@ -198,7 +306,7 @@ void MipsLongBranch::initMBBInfo() { } // Compute offset of branch in number of bytes. -int64_t MipsLongBranch::computeOffset(const MachineInstr *Br) { +int64_t MipsBranchExpansion::computeOffset(const MachineInstr *Br) { int64_t Offset = 0; int ThisMBB = Br->getParent()->getNumber(); int TargetMBB = getTargetMBB(*Br)->getNumber(); @@ -220,11 +328,9 @@ 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, - const DebugLoc &DL, - MachineBasicBlock *MBBOpnd) { - const MipsInstrInfo *TII = static_cast<const MipsInstrInfo *>( - MBB.getParent()->getSubtarget().getInstrInfo()); +void MipsBranchExpansion::replaceBranch(MachineBasicBlock &MBB, Iter Br, + const DebugLoc &DL, + MachineBasicBlock *MBBOpnd) { unsigned NewOpc = TII->getOppositeBranchOpc(Br->getOpcode()); const MCInstrDesc &NewDesc = TII->get(NewOpc); @@ -258,24 +364,20 @@ void MipsLongBranch::replaceBranch(MachineBasicBlock &MBB, Iter Br, // currently assumes that all branches have 16-bit offsets, and will produce // wrong code if branches whose allowed offsets are [-128, -126, ..., 126] // are present. -void MipsLongBranch::expandToLongBranch(MBBInfo &I) { +void MipsBranchExpansion::expandToLongBranch(MBBInfo &I) { MachineBasicBlock::iterator Pos; MachineBasicBlock *MBB = I.Br->getParent(), *TgtMBB = getTargetMBB(*I.Br); DebugLoc DL = I.Br->getDebugLoc(); const BasicBlock *BB = MBB->getBasicBlock(); MachineFunction::iterator FallThroughMBB = ++MachineFunction::iterator(MBB); - MachineBasicBlock *LongBrMBB = MF->CreateMachineBasicBlock(BB); - const MipsSubtarget &Subtarget = - static_cast<const MipsSubtarget &>(MF->getSubtarget()); - const MipsInstrInfo *TII = - static_cast<const MipsInstrInfo *>(Subtarget.getInstrInfo()); + MachineBasicBlock *LongBrMBB = MFp->CreateMachineBasicBlock(BB); - MF->insert(FallThroughMBB, LongBrMBB); + MFp->insert(FallThroughMBB, LongBrMBB); MBB->replaceSuccessor(TgtMBB, LongBrMBB); if (IsPIC) { - MachineBasicBlock *BalTgtMBB = MF->CreateMachineBasicBlock(BB); - MF->insert(FallThroughMBB, BalTgtMBB); + MachineBasicBlock *BalTgtMBB = MFp->CreateMachineBasicBlock(BB); + MFp->insert(FallThroughMBB, BalTgtMBB); LongBrMBB->addSuccessor(BalTgtMBB); BalTgtMBB->addSuccessor(TgtMBB); @@ -283,9 +385,9 @@ void MipsLongBranch::expandToLongBranch(MBBInfo &I) { // instruction) and the pre-MIPS32r6/MIPS64r6 definition (which is an // pseudo-instruction wrapping BGEZAL). const unsigned BalOp = - Subtarget.hasMips32r6() - ? Subtarget.inMicroMipsMode() ? Mips::BALC_MMR6 : Mips::BALC - : Mips::BAL_BR; + STI->hasMips32r6() + ? STI->inMicroMipsMode() ? Mips::BALC_MMR6 : Mips::BALC + : STI->inMicroMipsMode() ? Mips::BAL_BR_MM : Mips::BAL_BR; if (!ABI.IsN64()) { // Pre R6: @@ -320,9 +422,12 @@ void MipsLongBranch::expandToLongBranch(MBBInfo &I) { Pos = LongBrMBB->begin(); BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::ADDiu), Mips::SP) - .addReg(Mips::SP).addImm(-8); - BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::SW)).addReg(Mips::RA) - .addReg(Mips::SP).addImm(0); + .addReg(Mips::SP) + .addImm(-8); + BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::SW)) + .addReg(Mips::RA) + .addReg(Mips::SP) + .addImm(0); // LUi and ADDiu instructions create 32-bit offset of the target basic // block from the target of BAL(C) instruction. We cannot use immediate @@ -341,16 +446,17 @@ void MipsLongBranch::expandToLongBranch(MBBInfo &I) { // operands to lowered instructions. BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::LONG_BRANCH_LUi), Mips::AT) - .addMBB(TgtMBB).addMBB(BalTgtMBB); + .addMBB(TgtMBB, MipsII::MO_ABS_HI) + .addMBB(BalTgtMBB); MachineInstrBuilder BalInstr = - BuildMI(*MF, DL, TII->get(BalOp)).addMBB(BalTgtMBB); + BuildMI(*MFp, DL, TII->get(BalOp)).addMBB(BalTgtMBB); MachineInstrBuilder ADDiuInstr = - BuildMI(*MF, DL, TII->get(Mips::LONG_BRANCH_ADDiu), Mips::AT) + BuildMI(*MFp, DL, TII->get(Mips::LONG_BRANCH_ADDiu), Mips::AT) .addReg(Mips::AT) - .addMBB(TgtMBB) + .addMBB(TgtMBB, MipsII::MO_ABS_LO) .addMBB(BalTgtMBB); - if (Subtarget.hasMips32r6()) { + if (STI->hasMips32r6()) { LongBrMBB->insert(Pos, ADDiuInstr); LongBrMBB->insert(Pos, BalInstr); } else { @@ -362,30 +468,38 @@ void MipsLongBranch::expandToLongBranch(MBBInfo &I) { Pos = BalTgtMBB->begin(); BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::ADDu), Mips::AT) - .addReg(Mips::RA).addReg(Mips::AT); + .addReg(Mips::RA) + .addReg(Mips::AT); BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::LW), Mips::RA) - .addReg(Mips::SP).addImm(0); - if (Subtarget.isTargetNaCl()) + .addReg(Mips::SP) + .addImm(0); + if (STI->isTargetNaCl()) // Bundle-align the target of indirect branch JR. TgtMBB->setAlignment(MIPS_NACL_BUNDLE_ALIGN); // In NaCl, modifying the sp is not allowed in branch delay slot. // For MIPS32R6, we can skip using a delay slot branch. - if (Subtarget.isTargetNaCl() || Subtarget.hasMips32r6()) + if (STI->isTargetNaCl() || + (STI->hasMips32r6() && !STI->useIndirectJumpsHazard())) BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::ADDiu), Mips::SP) - .addReg(Mips::SP).addImm(8); + .addReg(Mips::SP) + .addImm(8); - if (Subtarget.hasMips32r6()) { + if (STI->hasMips32r6() && !STI->useIndirectJumpsHazard()) { const unsigned JICOp = - Subtarget.inMicroMipsMode() ? Mips::JIC_MMR6 : Mips::JIC; + STI->inMicroMipsMode() ? Mips::JIC_MMR6 : Mips::JIC; BuildMI(*BalTgtMBB, Pos, DL, TII->get(JICOp)) .addReg(Mips::AT) .addImm(0); } else { - BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::JR)).addReg(Mips::AT); + unsigned JROp = + STI->useIndirectJumpsHazard() + ? (STI->hasMips32r6() ? Mips::JR_HB_R6 : Mips::JR_HB) + : Mips::JR; + BuildMI(*BalTgtMBB, Pos, DL, TII->get(JROp)).addReg(Mips::AT); - if (Subtarget.isTargetNaCl()) { + if (STI->isTargetNaCl()) { BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::NOP)); } else BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::ADDiu), Mips::SP) @@ -443,23 +557,29 @@ void MipsLongBranch::expandToLongBranch(MBBInfo &I) { Pos = LongBrMBB->begin(); BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::DADDiu), Mips::SP_64) - .addReg(Mips::SP_64).addImm(-16); - BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::SD)).addReg(Mips::RA_64) - .addReg(Mips::SP_64).addImm(0); + .addReg(Mips::SP_64) + .addImm(-16); + BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::SD)) + .addReg(Mips::RA_64) + .addReg(Mips::SP_64) + .addImm(0); BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::LONG_BRANCH_DADDiu), - Mips::AT_64).addReg(Mips::ZERO_64) - .addMBB(TgtMBB, MipsII::MO_ABS_HI).addMBB(BalTgtMBB); + Mips::AT_64) + .addReg(Mips::ZERO_64) + .addMBB(TgtMBB, MipsII::MO_ABS_HI) + .addMBB(BalTgtMBB); BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::DSLL), Mips::AT_64) - .addReg(Mips::AT_64).addImm(16); + .addReg(Mips::AT_64) + .addImm(16); MachineInstrBuilder BalInstr = - BuildMI(*MF, DL, TII->get(BalOp)).addMBB(BalTgtMBB); + BuildMI(*MFp, DL, TII->get(BalOp)).addMBB(BalTgtMBB); MachineInstrBuilder DADDiuInstr = - BuildMI(*MF, DL, TII->get(Mips::LONG_BRANCH_DADDiu), Mips::AT_64) + BuildMI(*MFp, DL, TII->get(Mips::LONG_BRANCH_DADDiu), Mips::AT_64) .addReg(Mips::AT_64) .addMBB(TgtMBB, MipsII::MO_ABS_LO) .addMBB(BalTgtMBB); - if (Subtarget.hasMips32r6()) { + if (STI->hasMips32r6()) { LongBrMBB->insert(Pos, DADDiuInstr); LongBrMBB->insert(Pos, BalInstr); } else { @@ -471,11 +591,13 @@ void MipsLongBranch::expandToLongBranch(MBBInfo &I) { Pos = BalTgtMBB->begin(); BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::DADDu), Mips::AT_64) - .addReg(Mips::RA_64).addReg(Mips::AT_64); + .addReg(Mips::RA_64) + .addReg(Mips::AT_64); BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::LD), Mips::RA_64) - .addReg(Mips::SP_64).addImm(0); + .addReg(Mips::SP_64) + .addImm(0); - if (Subtarget.hasMips64r6()) { + if (STI->hasMips64r6() && !STI->useIndirectJumpsHazard()) { BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::DADDiu), Mips::SP_64) .addReg(Mips::SP_64) .addImm(16); @@ -483,7 +605,11 @@ void MipsLongBranch::expandToLongBranch(MBBInfo &I) { .addReg(Mips::AT_64) .addImm(0); } else { - BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::JR64)).addReg(Mips::AT_64); + unsigned JROp = + STI->useIndirectJumpsHazard() + ? (STI->hasMips32r6() ? Mips::JR_HB64_R6 : Mips::JR_HB64) + : Mips::JR64; + BuildMI(*BalTgtMBB, Pos, DL, TII->get(JROp)).addReg(Mips::AT_64); BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::DADDiu), Mips::SP_64) .addReg(Mips::SP_64) .addImm(16); @@ -501,14 +627,14 @@ void MipsLongBranch::expandToLongBranch(MBBInfo &I) { // Pos = LongBrMBB->begin(); LongBrMBB->addSuccessor(TgtMBB); - if (Subtarget.hasMips32r6()) + if (STI->hasMips32r6()) BuildMI(*LongBrMBB, Pos, DL, - TII->get(Subtarget.inMicroMipsMode() ? Mips::BC_MMR6 : Mips::BC)) + TII->get(STI->inMicroMipsMode() ? Mips::BC_MMR6 : Mips::BC)) .addMBB(TgtMBB); else MIBundleBuilder(*LongBrMBB, Pos) - .append(BuildMI(*MF, DL, TII->get(Mips::J)).addMBB(TgtMBB)) - .append(BuildMI(*MF, DL, TII->get(Mips::NOP))); + .append(BuildMI(*MFp, DL, TII->get(Mips::J)).addMBB(TgtMBB)) + .append(BuildMI(*MFp, DL, TII->get(Mips::NOP))); assert(LongBrMBB->size() == LongBranchSeqSize); } @@ -528,35 +654,66 @@ static void emitGPDisp(MachineFunction &F, const MipsInstrInfo *TII) { MachineBasicBlock::iterator I = MBB.begin(); DebugLoc DL = MBB.findDebugLoc(MBB.begin()); BuildMI(MBB, I, DL, TII->get(Mips::LUi), Mips::V0) - .addExternalSymbol("_gp_disp", MipsII::MO_ABS_HI); + .addExternalSymbol("_gp_disp", MipsII::MO_ABS_HI); BuildMI(MBB, I, DL, TII->get(Mips::ADDiu), Mips::V0) - .addReg(Mips::V0).addExternalSymbol("_gp_disp", MipsII::MO_ABS_LO); + .addReg(Mips::V0) + .addExternalSymbol("_gp_disp", MipsII::MO_ABS_LO); MBB.removeLiveIn(Mips::V0); } -bool MipsLongBranch::runOnMachineFunction(MachineFunction &F) { - const MipsSubtarget &STI = - static_cast<const MipsSubtarget &>(F.getSubtarget()); - const MipsInstrInfo *TII = - static_cast<const MipsInstrInfo *>(STI.getInstrInfo()); +bool MipsBranchExpansion::handleForbiddenSlot() { + // Forbidden slot hazards are only defined for MIPSR6 but not microMIPSR6. + if (!STI->hasMips32r6() || STI->inMicroMipsMode()) + return false; - const TargetMachine& TM = F.getTarget(); - IsPIC = TM.isPositionIndependent(); - ABI = static_cast<const MipsTargetMachine &>(TM).getABI(); + const MipsInstrInfo *TII = STI->getInstrInfo(); + + bool Changed = false; + + for (MachineFunction::iterator FI = MFp->begin(); FI != MFp->end(); ++FI) { + for (Iter I = FI->begin(); I != FI->end(); ++I) { + + // Forbidden slot hazard handling. Use lookahead over state. + if (!TII->HasForbiddenSlot(*I)) + continue; + + Iter Inst; + bool LastInstInFunction = + std::next(I) == FI->end() && std::next(FI) == MFp->end(); + if (!LastInstInFunction) { + std::pair<Iter, bool> Res = getNextMachineInstr(std::next(I), &*FI); + LastInstInFunction |= Res.second; + Inst = Res.first; + } + + if (LastInstInFunction || !TII->SafeInForbiddenSlot(*Inst)) { + + MachineBasicBlock::instr_iterator Iit = I->getIterator(); + if (std::next(Iit) == FI->end() || + std::next(Iit)->getOpcode() != Mips::NOP) { + Changed = true; + MIBundleBuilder(&*I).append( + BuildMI(*MFp, I->getDebugLoc(), TII->get(Mips::NOP))); + NumInsertedNops++; + } + } + } + } - LongBranchSeqSize = IsPIC ? ((ABI.IsN64() || STI.isTargetNaCl()) ? 10 : 9) - : (STI.hasMips32r6() ? 1 : 2); + return Changed; +} - if (STI.inMips16Mode() || !STI.enableLongBranchPass()) +bool MipsBranchExpansion::handlePossibleLongBranch() { + + LongBranchSeqSize = IsPIC ? ((ABI.IsN64() || STI->isTargetNaCl()) ? 10 : 9) + : (STI->hasMips32r6() ? 1 : 2); + + if (STI->inMips16Mode() || !STI->enableLongBranchPass()) return false; - if (IsPIC && static_cast<const MipsTargetMachine &>(TM).getABI().IsO32() && - F.getInfo<MipsFunctionInfo>()->globalBaseRegSet()) - emitGPDisp(F, TII); if (SkipLongBranch) - return true; + return false; - MF = &F; initMBBInfo(); SmallVectorImpl<MBBInfo>::iterator I, E = MBBInfos.end(); @@ -571,10 +728,9 @@ bool MipsLongBranch::runOnMachineFunction(MachineFunction &F) { if (!I->Br || I->HasLongBranch) continue; - int ShVal = STI.inMicroMipsMode() ? 2 : 4; - int64_t Offset = computeOffset(I->Br) / ShVal; + int64_t Offset = computeOffset(I->Br); - if (STI.isTargetNaCl()) { + if (STI->isTargetNaCl()) { // The offset calculation does not include sandboxing instructions // that will be added later in the MC layer. Since at this point we // don't know the exact amount of code that "sandboxing" will add, we @@ -582,8 +738,9 @@ bool MipsLongBranch::runOnMachineFunction(MachineFunction &F) { Offset *= 2; } - // Check if offset fits into 16-bit immediate field of branches. - if (!ForceLongBranch && isInt<16>(Offset)) + // Check if offset fits into the immediate field of the branch. + if (!ForceLongBranchFirstPass && + TII->isBranchOffsetInRange(I->Br->getOpcode(), Offset)) continue; I->HasLongBranch = true; @@ -593,27 +750,49 @@ bool MipsLongBranch::runOnMachineFunction(MachineFunction &F) { } } - if (!EverMadeChange) - return true; - - // Compute basic block addresses. - if (IsPIC) { - uint64_t Address = 0; + ForceLongBranchFirstPass = false; - for (I = MBBInfos.begin(); I != E; Address += I->Size, ++I) - I->Address = Address; - } + if (!EverMadeChange) + return false; // Do the expansion. for (I = MBBInfos.begin(); I != E; ++I) - if (I->HasLongBranch) + if (I->HasLongBranch) { expandToLongBranch(*I); + } - MF->RenumberBlocks(); + MFp->RenumberBlocks(); return true; } -/// createMipsLongBranchPass - Returns a pass that converts branches to long -/// branches. -FunctionPass *llvm::createMipsLongBranchPass() { return new MipsLongBranch(); } +bool MipsBranchExpansion::runOnMachineFunction(MachineFunction &MF) { + const TargetMachine &TM = MF.getTarget(); + IsPIC = TM.isPositionIndependent(); + ABI = static_cast<const MipsTargetMachine &>(TM).getABI(); + STI = &static_cast<const MipsSubtarget &>(MF.getSubtarget()); + TII = static_cast<const MipsInstrInfo *>(STI->getInstrInfo()); + + if (IsPIC && ABI.IsO32() && + MF.getInfo<MipsFunctionInfo>()->globalBaseRegSet()) + emitGPDisp(MF, TII); + + MFp = &MF; + + ForceLongBranchFirstPass = ForceLongBranch; + // Run these two at least once + bool longBranchChanged = handlePossibleLongBranch(); + bool forbiddenSlotChanged = handleForbiddenSlot(); + + bool Changed = longBranchChanged || forbiddenSlotChanged; + + // Then run them alternatively while there are changes + while (forbiddenSlotChanged) { + longBranchChanged = handlePossibleLongBranch(); + if (!longBranchChanged) + break; + forbiddenSlotChanged = handleForbiddenSlot(); + } + + return Changed; +} diff --git a/lib/Target/Mips/MipsCallLowering.cpp b/lib/Target/Mips/MipsCallLowering.cpp new file mode 100644 index 000000000000..e82f62260b3f --- /dev/null +++ b/lib/Target/Mips/MipsCallLowering.cpp @@ -0,0 +1,441 @@ +//===- MipsCallLowering.cpp -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// \file +/// This file implements the lowering of LLVM calls to machine code calls for +/// GlobalISel. +// +//===----------------------------------------------------------------------===// + +#include "MipsCallLowering.h" +#include "MipsCCState.h" +#include "MipsTargetMachine.h" +#include "llvm/CodeGen/GlobalISel/MachineIRBuilder.h" + +using namespace llvm; + +MipsCallLowering::MipsCallLowering(const MipsTargetLowering &TLI) + : CallLowering(&TLI) {} + +bool MipsCallLowering::MipsHandler::assign(const CCValAssign &VA, + unsigned vreg) { + if (VA.isRegLoc()) { + assignValueToReg(vreg, VA.getLocReg()); + } else if (VA.isMemLoc()) { + unsigned Size = alignTo(VA.getValVT().getSizeInBits(), 8) / 8; + unsigned Offset = VA.getLocMemOffset(); + MachinePointerInfo MPO; + unsigned StackAddr = getStackAddress(Size, Offset, MPO); + assignValueToAddress(vreg, StackAddr, Size, MPO); + } else { + return false; + } + return true; +} + +namespace { +class IncomingValueHandler : public MipsCallLowering::MipsHandler { +public: + IncomingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI) + : MipsHandler(MIRBuilder, MRI) {} + + bool handle(ArrayRef<CCValAssign> ArgLocs, + ArrayRef<CallLowering::ArgInfo> Args); + +private: + void assignValueToReg(unsigned ValVReg, unsigned PhysReg) override; + + unsigned getStackAddress(uint64_t Size, int64_t Offset, + MachinePointerInfo &MPO) override; + + void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size, + MachinePointerInfo &MPO) override; + + virtual void markPhysRegUsed(unsigned PhysReg) { + MIRBuilder.getMBB().addLiveIn(PhysReg); + } + + void buildLoad(unsigned Val, unsigned Addr, uint64_t Size, unsigned Alignment, + MachinePointerInfo &MPO) { + MachineMemOperand *MMO = MIRBuilder.getMF().getMachineMemOperand( + MPO, MachineMemOperand::MOLoad, Size, Alignment); + MIRBuilder.buildLoad(Val, Addr, *MMO); + } +}; + +class CallReturnHandler : public IncomingValueHandler { +public: + CallReturnHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, + MachineInstrBuilder &MIB) + : IncomingValueHandler(MIRBuilder, MRI), MIB(MIB) {} + +private: + void markPhysRegUsed(unsigned PhysReg) override { + MIB.addDef(PhysReg, RegState::Implicit); + } + + MachineInstrBuilder &MIB; +}; + +} // end anonymous namespace + +void IncomingValueHandler::assignValueToReg(unsigned ValVReg, + unsigned PhysReg) { + MIRBuilder.buildCopy(ValVReg, PhysReg); + markPhysRegUsed(PhysReg); +} + +unsigned IncomingValueHandler::getStackAddress(uint64_t Size, int64_t Offset, + MachinePointerInfo &MPO) { + MachineFrameInfo &MFI = MIRBuilder.getMF().getFrameInfo(); + + int FI = MFI.CreateFixedObject(Size, Offset, true); + MPO = MachinePointerInfo::getFixedStack(MIRBuilder.getMF(), FI); + + unsigned AddrReg = MRI.createGenericVirtualRegister(LLT::pointer(0, 32)); + MIRBuilder.buildFrameIndex(AddrReg, FI); + + return AddrReg; +} + +void IncomingValueHandler::assignValueToAddress(unsigned ValVReg, unsigned Addr, + uint64_t Size, + MachinePointerInfo &MPO) { + // If the value is not extended, a simple load will suffice. + buildLoad(ValVReg, Addr, Size, /* Alignment */ 0, MPO); +} + +bool IncomingValueHandler::handle(ArrayRef<CCValAssign> ArgLocs, + ArrayRef<CallLowering::ArgInfo> Args) { + for (unsigned i = 0, ArgsSize = Args.size(); i < ArgsSize; ++i) { + if (!assign(ArgLocs[i], Args[i].Reg)) + return false; + } + return true; +} + +namespace { +class OutgoingValueHandler : public MipsCallLowering::MipsHandler { +public: + OutgoingValueHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI, + MachineInstrBuilder &MIB) + : MipsHandler(MIRBuilder, MRI), MIB(MIB) {} + + bool handle(ArrayRef<CCValAssign> ArgLocs, + ArrayRef<CallLowering::ArgInfo> Args); + +private: + void assignValueToReg(unsigned ValVReg, unsigned PhysReg) override; + + unsigned getStackAddress(uint64_t Size, int64_t Offset, + MachinePointerInfo &MPO) override; + + void assignValueToAddress(unsigned ValVReg, unsigned Addr, uint64_t Size, + MachinePointerInfo &MPO) override; + + MachineInstrBuilder &MIB; +}; +} // end anonymous namespace + +void OutgoingValueHandler::assignValueToReg(unsigned ValVReg, + unsigned PhysReg) { + MIRBuilder.buildCopy(PhysReg, ValVReg); + MIB.addUse(PhysReg, RegState::Implicit); +} + +unsigned OutgoingValueHandler::getStackAddress(uint64_t Size, int64_t Offset, + MachinePointerInfo &MPO) { + LLT p0 = LLT::pointer(0, 32); + LLT s32 = LLT::scalar(32); + unsigned SPReg = MRI.createGenericVirtualRegister(p0); + MIRBuilder.buildCopy(SPReg, Mips::SP); + + unsigned OffsetReg = MRI.createGenericVirtualRegister(s32); + MIRBuilder.buildConstant(OffsetReg, Offset); + + unsigned AddrReg = MRI.createGenericVirtualRegister(p0); + MIRBuilder.buildGEP(AddrReg, SPReg, OffsetReg); + + MPO = MachinePointerInfo::getStack(MIRBuilder.getMF(), Offset); + return AddrReg; +} + +void OutgoingValueHandler::assignValueToAddress(unsigned ValVReg, unsigned Addr, + uint64_t Size, + MachinePointerInfo &MPO) { + MachineMemOperand *MMO = MIRBuilder.getMF().getMachineMemOperand( + MPO, MachineMemOperand::MOStore, Size, /* Alignment */ 0); + MIRBuilder.buildStore(ValVReg, Addr, *MMO); +} + +bool OutgoingValueHandler::handle(ArrayRef<CCValAssign> ArgLocs, + ArrayRef<CallLowering::ArgInfo> Args) { + for (unsigned i = 0; i < Args.size(); ++i) { + if (!assign(ArgLocs[i], Args[i].Reg)) + return false; + } + return true; +} + +static bool isSupportedType(Type *T) { + if (T->isIntegerTy() && T->getScalarSizeInBits() == 32) + return true; + if (T->isPointerTy()) + return true; + return false; +} + +bool MipsCallLowering::lowerReturn(MachineIRBuilder &MIRBuilder, + const Value *Val, unsigned VReg) const { + + MachineInstrBuilder Ret = MIRBuilder.buildInstrNoInsert(Mips::RetRA); + + if (Val != nullptr) { + if (!isSupportedType(Val->getType())) + return false; + + MachineFunction &MF = MIRBuilder.getMF(); + const Function &F = MF.getFunction(); + const DataLayout &DL = MF.getDataLayout(); + const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); + + SmallVector<ArgInfo, 8> RetInfos; + SmallVector<unsigned, 8> OrigArgIndices; + + ArgInfo ArgRetInfo(VReg, Val->getType()); + setArgFlags(ArgRetInfo, AttributeList::ReturnIndex, DL, F); + splitToValueTypes(ArgRetInfo, 0, RetInfos, OrigArgIndices); + + SmallVector<ISD::OutputArg, 8> Outs; + subTargetRegTypeForCallingConv( + MIRBuilder, RetInfos, OrigArgIndices, + [&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used, + unsigned origIdx, unsigned partOffs) { + Outs.emplace_back(flags, vt, argvt, used, origIdx, partOffs); + }); + + SmallVector<CCValAssign, 16> ArgLocs; + MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, + F.getContext()); + CCInfo.AnalyzeReturn(Outs, TLI.CCAssignFnForReturn()); + + OutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), Ret); + if (!RetHandler.handle(ArgLocs, RetInfos)) { + return false; + } + } + MIRBuilder.insertInstr(Ret); + return true; +} + +bool MipsCallLowering::lowerFormalArguments(MachineIRBuilder &MIRBuilder, + const Function &F, + ArrayRef<unsigned> VRegs) const { + + // Quick exit if there aren't any args. + if (F.arg_empty()) + return true; + + if (F.isVarArg()) { + return false; + } + + for (auto &Arg : F.args()) { + if (!isSupportedType(Arg.getType())) + return false; + } + + MachineFunction &MF = MIRBuilder.getMF(); + const DataLayout &DL = MF.getDataLayout(); + const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); + + SmallVector<ArgInfo, 8> ArgInfos; + SmallVector<unsigned, 8> OrigArgIndices; + unsigned i = 0; + for (auto &Arg : F.args()) { + ArgInfo AInfo(VRegs[i], Arg.getType()); + setArgFlags(AInfo, i + AttributeList::FirstArgIndex, DL, F); + splitToValueTypes(AInfo, i, ArgInfos, OrigArgIndices); + ++i; + } + + SmallVector<ISD::InputArg, 8> Ins; + subTargetRegTypeForCallingConv( + MIRBuilder, ArgInfos, OrigArgIndices, + [&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used, unsigned origIdx, + unsigned partOffs) { + Ins.emplace_back(flags, vt, argvt, used, origIdx, partOffs); + }); + + SmallVector<CCValAssign, 16> ArgLocs; + MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, + F.getContext()); + + const MipsTargetMachine &TM = + static_cast<const MipsTargetMachine &>(MF.getTarget()); + const MipsABIInfo &ABI = TM.getABI(); + CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(F.getCallingConv()), + 1); + CCInfo.AnalyzeFormalArguments(Ins, TLI.CCAssignFnForCall()); + + IncomingValueHandler Handler(MIRBuilder, MF.getRegInfo()); + if (!Handler.handle(ArgLocs, ArgInfos)) + return false; + + return true; +} + +bool MipsCallLowering::lowerCall(MachineIRBuilder &MIRBuilder, + CallingConv::ID CallConv, + const MachineOperand &Callee, + const ArgInfo &OrigRet, + ArrayRef<ArgInfo> OrigArgs) const { + + if (CallConv != CallingConv::C) + return false; + + for (auto &Arg : OrigArgs) { + if (!isSupportedType(Arg.Ty)) + return false; + if (Arg.Flags.isByVal() || Arg.Flags.isSRet()) + return false; + } + if (OrigRet.Reg && !isSupportedType(OrigRet.Ty)) + return false; + + MachineFunction &MF = MIRBuilder.getMF(); + const Function &F = MF.getFunction(); + const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); + const MipsTargetMachine &TM = + static_cast<const MipsTargetMachine &>(MF.getTarget()); + const MipsABIInfo &ABI = TM.getABI(); + + MachineInstrBuilder CallSeqStart = + MIRBuilder.buildInstr(Mips::ADJCALLSTACKDOWN); + + // FIXME: Add support for pic calling sequences, long call sequences for O32, + // N32 and N64. First handle the case when Callee.isReg(). + if (Callee.isReg()) + return false; + + MachineInstrBuilder MIB = MIRBuilder.buildInstrNoInsert(Mips::JAL); + MIB.addDef(Mips::SP, RegState::Implicit); + MIB.add(Callee); + const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); + MIB.addRegMask(TRI->getCallPreservedMask(MF, F.getCallingConv())); + + TargetLowering::ArgListTy FuncOrigArgs; + FuncOrigArgs.reserve(OrigArgs.size()); + + SmallVector<ArgInfo, 8> ArgInfos; + SmallVector<unsigned, 8> OrigArgIndices; + unsigned i = 0; + for (auto &Arg : OrigArgs) { + + TargetLowering::ArgListEntry Entry; + Entry.Ty = Arg.Ty; + FuncOrigArgs.push_back(Entry); + + splitToValueTypes(Arg, i, ArgInfos, OrigArgIndices); + ++i; + } + + SmallVector<ISD::OutputArg, 8> Outs; + subTargetRegTypeForCallingConv( + MIRBuilder, ArgInfos, OrigArgIndices, + [&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used, unsigned origIdx, + unsigned partOffs) { + Outs.emplace_back(flags, vt, argvt, used, origIdx, partOffs); + }); + + SmallVector<CCValAssign, 8> ArgLocs; + MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, + F.getContext()); + + CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(CallConv), 1); + const char *Call = Callee.isSymbol() ? Callee.getSymbolName() : nullptr; + CCInfo.AnalyzeCallOperands(Outs, TLI.CCAssignFnForCall(), FuncOrigArgs, Call); + + OutgoingValueHandler RetHandler(MIRBuilder, MF.getRegInfo(), MIB); + if (!RetHandler.handle(ArgLocs, ArgInfos)) { + return false; + } + + unsigned NextStackOffset = CCInfo.getNextStackOffset(); + const TargetFrameLowering *TFL = MF.getSubtarget().getFrameLowering(); + unsigned StackAlignment = TFL->getStackAlignment(); + NextStackOffset = alignTo(NextStackOffset, StackAlignment); + CallSeqStart.addImm(NextStackOffset).addImm(0); + + MIRBuilder.insertInstr(MIB); + + if (OrigRet.Reg) { + + ArgInfos.clear(); + SmallVector<unsigned, 8> OrigRetIndices; + + splitToValueTypes(OrigRet, 0, ArgInfos, OrigRetIndices); + + SmallVector<ISD::InputArg, 8> Ins; + subTargetRegTypeForCallingConv( + MIRBuilder, ArgInfos, OrigRetIndices, + [&](ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used, + unsigned origIdx, unsigned partOffs) { + Ins.emplace_back(flags, vt, argvt, used, origIdx, partOffs); + }); + + SmallVector<CCValAssign, 8> ArgLocs; + MipsCCState CCInfo(F.getCallingConv(), F.isVarArg(), MF, ArgLocs, + F.getContext()); + + CCInfo.AnalyzeCallResult(Ins, TLI.CCAssignFnForReturn(), OrigRet.Ty, Call); + + CallReturnHandler Handler(MIRBuilder, MF.getRegInfo(), MIB); + if (!Handler.handle(ArgLocs, ArgInfos)) + return false; + } + + MIRBuilder.buildInstr(Mips::ADJCALLSTACKUP).addImm(NextStackOffset).addImm(0); + + return true; +} + +void MipsCallLowering::subTargetRegTypeForCallingConv( + MachineIRBuilder &MIRBuilder, ArrayRef<ArgInfo> Args, + ArrayRef<unsigned> OrigArgIndices, const FunTy &PushBack) const { + MachineFunction &MF = MIRBuilder.getMF(); + const Function &F = MF.getFunction(); + const DataLayout &DL = F.getParent()->getDataLayout(); + const MipsTargetLowering &TLI = *getTLI<MipsTargetLowering>(); + + unsigned ArgNo = 0; + for (auto &Arg : Args) { + + EVT VT = TLI.getValueType(DL, Arg.Ty); + MVT RegisterVT = TLI.getRegisterTypeForCallingConv(F.getContext(), VT); + + ISD::ArgFlagsTy Flags = Arg.Flags; + Flags.setOrigAlign(TLI.getABIAlignmentForCallingConv(Arg.Ty, DL)); + + PushBack(Flags, RegisterVT, VT, true, OrigArgIndices[ArgNo], 0); + + ++ArgNo; + } +} + +void MipsCallLowering::splitToValueTypes( + const ArgInfo &OrigArg, unsigned OriginalIndex, + SmallVectorImpl<ArgInfo> &SplitArgs, + SmallVectorImpl<unsigned> &SplitArgsOrigIndices) const { + + // TODO : perform structure and array split. For now we only deal with + // types that pass isSupportedType check. + SplitArgs.push_back(OrigArg); + SplitArgsOrigIndices.push_back(OriginalIndex); +} diff --git a/lib/Target/Mips/MipsCallLowering.h b/lib/Target/Mips/MipsCallLowering.h new file mode 100644 index 000000000000..e23c10cec563 --- /dev/null +++ b/lib/Target/Mips/MipsCallLowering.h @@ -0,0 +1,86 @@ +//===- MipsCallLowering.h ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// \file +/// This file describes how to lower LLVM calls to machine code calls. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_MIPS_MIPSCALLLOWERING_H +#define LLVM_LIB_TARGET_MIPS_MIPSCALLLOWERING_H + +#include "llvm/CodeGen/GlobalISel/CallLowering.h" + +namespace llvm { + +class MipsTargetLowering; + +class MipsCallLowering : public CallLowering { + +public: + class MipsHandler { + public: + MipsHandler(MachineIRBuilder &MIRBuilder, MachineRegisterInfo &MRI) + : MIRBuilder(MIRBuilder), MRI(MRI) {} + + virtual ~MipsHandler() = default; + + protected: + bool assign(const CCValAssign &VA, unsigned vreg); + + MachineIRBuilder &MIRBuilder; + MachineRegisterInfo &MRI; + + private: + virtual unsigned getStackAddress(uint64_t Size, int64_t Offset, + MachinePointerInfo &MPO) = 0; + + virtual void assignValueToReg(unsigned ValVReg, unsigned PhysReg) = 0; + + virtual void assignValueToAddress(unsigned ValVReg, unsigned Addr, + uint64_t Size, + MachinePointerInfo &MPO) = 0; + }; + + MipsCallLowering(const MipsTargetLowering &TLI); + + bool lowerReturn(MachineIRBuilder &MIRBuiler, const Value *Val, + unsigned VReg) const override; + + bool lowerFormalArguments(MachineIRBuilder &MIRBuilder, const Function &F, + ArrayRef<unsigned> VRegs) const override; + + bool lowerCall(MachineIRBuilder &MIRBuilder, CallingConv::ID CallConv, + const MachineOperand &Callee, const ArgInfo &OrigRet, + ArrayRef<ArgInfo> OrigArgs) const override; + +private: + using FunTy = + std::function<void(ISD::ArgFlagsTy flags, EVT vt, EVT argvt, bool used, + unsigned origIdx, unsigned partOffs)>; + + /// Based on registers available on target machine split or extend + /// type if needed, also change pointer type to appropriate integer + /// type. Lambda will fill some info so we can tell MipsCCState to + /// assign physical registers. + void subTargetRegTypeForCallingConv(MachineIRBuilder &MIRBuilder, + ArrayRef<ArgInfo> Args, + ArrayRef<unsigned> OrigArgIndices, + const FunTy &PushBack) const; + + /// Split structures and arrays, save original argument indices since + /// Mips calling conv needs info about original argument type. + void splitToValueTypes(const ArgInfo &OrigArg, unsigned OriginalIndex, + SmallVectorImpl<ArgInfo> &SplitArgs, + SmallVectorImpl<unsigned> &SplitArgsOrigIndices) const; +}; + +} // end namespace llvm + +#endif // LLVM_LIB_TARGET_MIPS_MIPSCALLLOWERING_H diff --git a/lib/Target/Mips/MipsCondMov.td b/lib/Target/Mips/MipsCondMov.td index a0039d159248..39dc2654aa6a 100644 --- a/lib/Target/Mips/MipsCondMov.td +++ b/lib/Target/Mips/MipsCondMov.td @@ -104,163 +104,162 @@ multiclass MovnPats<RegisterClass CRC, RegisterClass DRC, Instruction MOVNInst, } // Instantiation of instructions. -def MOVZ_I_I : MMRel, CMov_I_I_FT<"movz", GPR32Opnd, GPR32Opnd, II_MOVZ>, - ADD_FM<0, 0xa>, INSN_MIPS4_32_NOT_32R6_64R6; - -let isCodeGenOnly = 1 in { - def MOVZ_I_I64 : CMov_I_I_FT<"movz", GPR32Opnd, GPR64Opnd, II_MOVZ>, - ADD_FM<0, 0xa>, INSN_MIPS4_32_NOT_32R6_64R6; - def MOVZ_I64_I : CMov_I_I_FT<"movz", GPR64Opnd, GPR32Opnd, II_MOVZ>, - ADD_FM<0, 0xa>, INSN_MIPS4_32_NOT_32R6_64R6; - def MOVZ_I64_I64 : CMov_I_I_FT<"movz", GPR64Opnd, GPR64Opnd, II_MOVZ>, - ADD_FM<0, 0xa>, INSN_MIPS4_32_NOT_32R6_64R6; -} +let AdditionalPredicates = [NotInMicroMips] in { + def MOVZ_I_I : MMRel, CMov_I_I_FT<"movz", GPR32Opnd, GPR32Opnd, II_MOVZ>, + ADD_FM<0, 0xa>, INSN_MIPS4_32_NOT_32R6_64R6; + + let isCodeGenOnly = 1 in { + def MOVZ_I_I64 : CMov_I_I_FT<"movz", GPR32Opnd, GPR64Opnd, II_MOVZ>, + ADD_FM<0, 0xa>, INSN_MIPS4_32_NOT_32R6_64R6; + def MOVZ_I64_I : CMov_I_I_FT<"movz", GPR64Opnd, GPR32Opnd, II_MOVZ>, + ADD_FM<0, 0xa>, INSN_MIPS4_32_NOT_32R6_64R6; + def MOVZ_I64_I64 : CMov_I_I_FT<"movz", GPR64Opnd, GPR64Opnd, II_MOVZ>, + ADD_FM<0, 0xa>, INSN_MIPS4_32_NOT_32R6_64R6; + } -def MOVN_I_I : MMRel, CMov_I_I_FT<"movn", GPR32Opnd, GPR32Opnd, II_MOVN>, - ADD_FM<0, 0xb>, INSN_MIPS4_32_NOT_32R6_64R6; + def MOVN_I_I : MMRel, CMov_I_I_FT<"movn", GPR32Opnd, GPR32Opnd, II_MOVN>, + ADD_FM<0, 0xb>, INSN_MIPS4_32_NOT_32R6_64R6; -let isCodeGenOnly = 1 in { - def MOVN_I_I64 : CMov_I_I_FT<"movn", GPR32Opnd, GPR64Opnd, II_MOVN>, - ADD_FM<0, 0xb>, INSN_MIPS4_32_NOT_32R6_64R6; - def MOVN_I64_I : CMov_I_I_FT<"movn", GPR64Opnd, GPR32Opnd, II_MOVN>, - ADD_FM<0, 0xb>, INSN_MIPS4_32_NOT_32R6_64R6; - def MOVN_I64_I64 : CMov_I_I_FT<"movn", GPR64Opnd, GPR64Opnd, II_MOVN>, - ADD_FM<0, 0xb>, INSN_MIPS4_32_NOT_32R6_64R6; -} + let isCodeGenOnly = 1 in { + def MOVN_I_I64 : CMov_I_I_FT<"movn", GPR32Opnd, GPR64Opnd, II_MOVN>, + ADD_FM<0, 0xb>, INSN_MIPS4_32_NOT_32R6_64R6; + def MOVN_I64_I : CMov_I_I_FT<"movn", GPR64Opnd, GPR32Opnd, II_MOVN>, + ADD_FM<0, 0xb>, INSN_MIPS4_32_NOT_32R6_64R6; + def MOVN_I64_I64 : CMov_I_I_FT<"movn", GPR64Opnd, GPR64Opnd, II_MOVN>, + ADD_FM<0, 0xb>, INSN_MIPS4_32_NOT_32R6_64R6; + } + def MOVZ_I_S : MMRel, CMov_I_F_FT<"movz.s", GPR32Opnd, FGR32Opnd, II_MOVZ_S>, + CMov_I_F_FM<18, 16>, INSN_MIPS4_32_NOT_32R6_64R6; + + 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, 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, GPR_64; + + def MOVZ_I_D32 : MMRel, CMov_I_F_FT<"movz.d", GPR32Opnd, AFGR64Opnd, + II_MOVZ_D>, CMov_I_F_FM<18, 17>, + INSN_MIPS4_32_NOT_32R6_64R6, FGR_32; + def MOVN_I_D32 : MMRel, CMov_I_F_FT<"movn.d", GPR32Opnd, AFGR64Opnd, + II_MOVN_D>, CMov_I_F_FM<19, 17>, + INSN_MIPS4_32_NOT_32R6_64R6, FGR_32; + + let DecoderNamespace = "MipsFP64" in { + def MOVZ_I_D64 : CMov_I_F_FT<"movz.d", GPR32Opnd, FGR64Opnd, II_MOVZ_D>, + CMov_I_F_FM<18, 17>, INSN_MIPS4_32_NOT_32R6_64R6, FGR_64; + def MOVN_I_D64 : CMov_I_F_FT<"movn.d", GPR32Opnd, FGR64Opnd, II_MOVN_D>, + CMov_I_F_FM<19, 17>, INSN_MIPS4_32_NOT_32R6_64R6, FGR_64; + let isCodeGenOnly = 1 in { + def MOVZ_I64_D64 : CMov_I_F_FT<"movz.d", GPR64Opnd, FGR64Opnd, II_MOVZ_D>, + CMov_I_F_FM<18, 17>, INSN_MIPS4_32_NOT_32R6_64R6, FGR_64; + def MOVN_I64_D64 : CMov_I_F_FT<"movn.d", GPR64Opnd, FGR64Opnd, II_MOVN_D>, + CMov_I_F_FM<19, 17>, INSN_MIPS4_32_NOT_32R6_64R6, FGR_64; + } + } -def MOVZ_I_S : MMRel, CMov_I_F_FT<"movz.s", GPR32Opnd, FGR32Opnd, II_MOVZ_S>, - CMov_I_F_FM<18, 16>, INSN_MIPS4_32_NOT_32R6_64R6; + def MOVT_I : MMRel, CMov_F_I_FT<"movt", GPR32Opnd, II_MOVT, MipsCMovFP_T>, + CMov_F_I_FM<1>, INSN_MIPS4_32_NOT_32R6_64R6; -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, GPR_64; + 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, 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; + 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 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, GPR_64; + 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, 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; + def MOVF_S : MMRel, CMov_F_F_FT<"movf.s", FGR32Opnd, II_MOVF_S, MipsCMovFP_F>, + CMov_F_F_FM<16, 0>, INSN_MIPS4_32_NOT_32R6_64R6; -def MOVZ_I_D32 : MMRel, CMov_I_F_FT<"movz.d", GPR32Opnd, AFGR64Opnd, - II_MOVZ_D>, CMov_I_F_FM<18, 17>, + def MOVT_D32 : MMRel, CMov_F_F_FT<"movt.d", AFGR64Opnd, II_MOVT_D, + MipsCMovFP_T>, CMov_F_F_FM<17, 1>, INSN_MIPS4_32_NOT_32R6_64R6, FGR_32; -def MOVN_I_D32 : MMRel, CMov_I_F_FT<"movn.d", GPR32Opnd, AFGR64Opnd, - II_MOVN_D>, CMov_I_F_FM<19, 17>, + def MOVF_D32 : MMRel, CMov_F_F_FT<"movf.d", AFGR64Opnd, II_MOVF_D, + MipsCMovFP_F>, CMov_F_F_FM<17, 0>, INSN_MIPS4_32_NOT_32R6_64R6, FGR_32; -let DecoderNamespace = "MipsFP64" in { - def MOVZ_I_D64 : CMov_I_F_FT<"movz.d", GPR32Opnd, FGR64Opnd, II_MOVZ_D>, - CMov_I_F_FM<18, 17>, INSN_MIPS4_32_NOT_32R6_64R6, FGR_64; - def MOVN_I_D64 : CMov_I_F_FT<"movn.d", GPR32Opnd, FGR64Opnd, II_MOVN_D>, - CMov_I_F_FM<19, 17>, INSN_MIPS4_32_NOT_32R6_64R6, FGR_64; - let isCodeGenOnly = 1 in { - def MOVZ_I64_D64 : CMov_I_F_FT<"movz.d", GPR64Opnd, FGR64Opnd, II_MOVZ_D>, - CMov_I_F_FM<18, 17>, INSN_MIPS4_32_NOT_32R6_64R6, FGR_64; - def MOVN_I64_D64 : CMov_I_F_FT<"movn.d", GPR64Opnd, FGR64Opnd, II_MOVN_D>, - CMov_I_F_FM<19, 17>, INSN_MIPS4_32_NOT_32R6_64R6, FGR_64; + let DecoderNamespace = "MipsFP64" in { + def MOVT_D64 : CMov_F_F_FT<"movt.d", FGR64Opnd, II_MOVT_D, MipsCMovFP_T>, + CMov_F_F_FM<17, 1>, INSN_MIPS4_32_NOT_32R6_64R6, FGR_64; + def MOVF_D64 : CMov_F_F_FT<"movf.d", FGR64Opnd, II_MOVF_D, MipsCMovFP_F>, + CMov_F_F_FM<17, 0>, INSN_MIPS4_32_NOT_32R6_64R6, FGR_64; } -} -def MOVT_I : MMRel, CMov_F_I_FT<"movt", GPR32Opnd, II_MOVT, MipsCMovFP_T>, - CMov_F_I_FM<1>, INSN_MIPS4_32_NOT_32R6_64R6; - -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, 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, 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; -def MOVF_S : MMRel, CMov_F_F_FT<"movf.s", FGR32Opnd, II_MOVF_S, MipsCMovFP_F>, - CMov_F_F_FM<16, 0>, INSN_MIPS4_32_NOT_32R6_64R6; - -def MOVT_D32 : MMRel, CMov_F_F_FT<"movt.d", AFGR64Opnd, II_MOVT_D, - MipsCMovFP_T>, CMov_F_F_FM<17, 1>, - INSN_MIPS4_32_NOT_32R6_64R6, FGR_32; -def MOVF_D32 : MMRel, CMov_F_F_FT<"movf.d", AFGR64Opnd, II_MOVF_D, - MipsCMovFP_F>, CMov_F_F_FM<17, 0>, - INSN_MIPS4_32_NOT_32R6_64R6, FGR_32; - -let DecoderNamespace = "MipsFP64" in { - def MOVT_D64 : CMov_F_F_FT<"movt.d", FGR64Opnd, II_MOVT_D, MipsCMovFP_T>, - CMov_F_F_FM<17, 1>, INSN_MIPS4_32_NOT_32R6_64R6, FGR_64; - def MOVF_D64 : CMov_F_F_FT<"movf.d", FGR64Opnd, II_MOVF_D, MipsCMovFP_F>, - CMov_F_F_FM<17, 0>, INSN_MIPS4_32_NOT_32R6_64R6, FGR_64; + // Instantiation of conditional move patterns. + defm : MovzPats0<GPR32, GPR32, MOVZ_I_I, SLT, SLTu, SLTi, SLTiu>, + INSN_MIPS4_32_NOT_32R6_64R6; + defm : MovzPats1<GPR32, GPR32, MOVZ_I_I, XOR>, INSN_MIPS4_32_NOT_32R6_64R6; + defm : MovzPats2<GPR32, GPR32, MOVZ_I_I, XORi>, INSN_MIPS4_32_NOT_32R6_64R6; + + defm : MovzPats0<GPR32, GPR64, MOVZ_I_I64, SLT, SLTu, SLTi, SLTiu>, + INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; + defm : MovzPats0<GPR64, GPR32, MOVZ_I_I, SLT64, SLTu64, SLTi64, SLTiu64>, + INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; + defm : MovzPats0<GPR64, GPR64, MOVZ_I_I64, SLT64, SLTu64, SLTi64, SLTiu64>, + INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; + defm : MovzPats1<GPR32, GPR64, MOVZ_I_I64, XOR>, + INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; + defm : MovzPats1<GPR64, GPR32, MOVZ_I64_I, XOR64>, + INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; + defm : MovzPats1<GPR64, GPR64, MOVZ_I64_I64, XOR64>, + INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; + defm : MovzPats2<GPR32, GPR64, MOVZ_I_I64, XORi>, + INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; + defm : MovzPats2<GPR64, GPR32, MOVZ_I64_I, XORi64>, + INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; + defm : MovzPats2<GPR64, GPR64, MOVZ_I64_I64, XORi64>, + INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; + + defm : MovnPats<GPR32, GPR32, MOVN_I_I, XOR>, INSN_MIPS4_32_NOT_32R6_64R6; + + defm : MovnPats<GPR32, GPR64, MOVN_I_I64, XOR>, INSN_MIPS4_32_NOT_32R6_64R6, + GPR_64; + defm : MovnPats<GPR64, GPR32, MOVN_I64_I, XOR64>, INSN_MIPS4_32_NOT_32R6_64R6, + GPR_64; + defm : MovnPats<GPR64, GPR64, MOVN_I64_I64, XOR64>, INSN_MIPS4_32_NOT_32R6_64R6, + GPR_64; + + defm : MovzPats0<GPR32, FGR32, MOVZ_I_S, SLT, SLTu, SLTi, SLTiu>, + INSN_MIPS4_32_NOT_32R6_64R6; + defm : MovzPats1<GPR32, FGR32, MOVZ_I_S, XOR>, INSN_MIPS4_32_NOT_32R6_64R6; + defm : MovnPats<GPR32, FGR32, MOVN_I_S, XOR>, INSN_MIPS4_32_NOT_32R6_64R6; + + defm : MovzPats0<GPR64, FGR32, MOVZ_I_S, SLT64, SLTu64, SLTi64, SLTiu64>, + INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; + defm : MovzPats1<GPR64, FGR32, MOVZ_I64_S, XOR64>, INSN_MIPS4_32_NOT_32R6_64R6, + GPR_64; + defm : MovnPats<GPR64, FGR32, MOVN_I64_S, XOR64>, INSN_MIPS4_32_NOT_32R6_64R6, + GPR_64; + + defm : MovzPats0<GPR32, AFGR64, MOVZ_I_D32, SLT, SLTu, SLTi, SLTiu>, + INSN_MIPS4_32_NOT_32R6_64R6, FGR_32; + defm : MovzPats1<GPR32, AFGR64, MOVZ_I_D32, XOR>, INSN_MIPS4_32_NOT_32R6_64R6, + FGR_32; + defm : MovnPats<GPR32, AFGR64, MOVN_I_D32, XOR>, INSN_MIPS4_32_NOT_32R6_64R6, + FGR_32; + + defm : MovzPats0<GPR32, FGR64, MOVZ_I_D64, SLT, SLTu, SLTi, SLTiu>, + INSN_MIPS4_32_NOT_32R6_64R6, FGR_64; + defm : MovzPats0<GPR64, FGR64, MOVZ_I_D64, SLT64, SLTu64, SLTi64, SLTiu64>, + INSN_MIPS4_32_NOT_32R6_64R6, FGR_64; + defm : MovzPats1<GPR32, FGR64, MOVZ_I_D64, XOR>, INSN_MIPS4_32_NOT_32R6_64R6, + FGR_64; + defm : MovzPats1<GPR64, FGR64, MOVZ_I64_D64, XOR64>, + INSN_MIPS4_32_NOT_32R6_64R6, FGR_64; + defm : MovnPats<GPR32, FGR64, MOVN_I_D64, XOR>, INSN_MIPS4_32_NOT_32R6_64R6, + FGR_64; + defm : MovnPats<GPR64, FGR64, MOVN_I64_D64, XOR64>, INSN_MIPS4_32_NOT_32R6_64R6, + FGR_64; } - -// Instantiation of conditional move patterns. -defm : MovzPats0<GPR32, GPR32, MOVZ_I_I, SLT, SLTu, SLTi, SLTiu>, - INSN_MIPS4_32_NOT_32R6_64R6; -defm : MovzPats1<GPR32, GPR32, MOVZ_I_I, XOR>, INSN_MIPS4_32_NOT_32R6_64R6; -defm : MovzPats2<GPR32, GPR32, MOVZ_I_I, XORi>, INSN_MIPS4_32_NOT_32R6_64R6; - -defm : MovzPats0<GPR32, GPR64, MOVZ_I_I64, SLT, SLTu, SLTi, SLTiu>, - INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; -defm : MovzPats0<GPR64, GPR32, MOVZ_I_I, SLT64, SLTu64, SLTi64, SLTiu64>, - INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; -defm : MovzPats0<GPR64, GPR64, MOVZ_I_I64, SLT64, SLTu64, SLTi64, SLTiu64>, - INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; -defm : MovzPats1<GPR32, GPR64, MOVZ_I_I64, XOR>, - INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; -defm : MovzPats1<GPR64, GPR32, MOVZ_I64_I, XOR64>, - INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; -defm : MovzPats1<GPR64, GPR64, MOVZ_I64_I64, XOR64>, - INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; -defm : MovzPats2<GPR32, GPR64, MOVZ_I_I64, XORi>, - INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; -defm : MovzPats2<GPR64, GPR32, MOVZ_I64_I, XORi64>, - INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; -defm : MovzPats2<GPR64, GPR64, MOVZ_I64_I64, XORi64>, - INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; - -defm : MovnPats<GPR32, GPR32, MOVN_I_I, XOR>, INSN_MIPS4_32_NOT_32R6_64R6; - -defm : MovnPats<GPR32, GPR64, MOVN_I_I64, XOR>, INSN_MIPS4_32_NOT_32R6_64R6, - GPR_64; -defm : MovnPats<GPR64, GPR32, MOVN_I64_I, XOR64>, INSN_MIPS4_32_NOT_32R6_64R6, - GPR_64; -defm : MovnPats<GPR64, GPR64, MOVN_I64_I64, XOR64>, INSN_MIPS4_32_NOT_32R6_64R6, - GPR_64; - -defm : MovzPats0<GPR32, FGR32, MOVZ_I_S, SLT, SLTu, SLTi, SLTiu>, - INSN_MIPS4_32_NOT_32R6_64R6; -defm : MovzPats1<GPR32, FGR32, MOVZ_I_S, XOR>, INSN_MIPS4_32_NOT_32R6_64R6; -defm : MovnPats<GPR32, FGR32, MOVN_I_S, XOR>, INSN_MIPS4_32_NOT_32R6_64R6; - -defm : MovzPats0<GPR64, FGR32, MOVZ_I_S, SLT64, SLTu64, SLTi64, SLTiu64>, - INSN_MIPS4_32_NOT_32R6_64R6, GPR_64; -defm : MovzPats1<GPR64, FGR32, MOVZ_I64_S, XOR64>, INSN_MIPS4_32_NOT_32R6_64R6, - GPR_64; -defm : MovnPats<GPR64, FGR32, MOVN_I64_S, XOR64>, INSN_MIPS4_32_NOT_32R6_64R6, - GPR_64; - -defm : MovzPats0<GPR32, AFGR64, MOVZ_I_D32, SLT, SLTu, SLTi, SLTiu>, - INSN_MIPS4_32_NOT_32R6_64R6, FGR_32; -defm : MovzPats1<GPR32, AFGR64, MOVZ_I_D32, XOR>, INSN_MIPS4_32_NOT_32R6_64R6, - FGR_32; -defm : MovnPats<GPR32, AFGR64, MOVN_I_D32, XOR>, INSN_MIPS4_32_NOT_32R6_64R6, - FGR_32; - -defm : MovzPats0<GPR32, FGR64, MOVZ_I_D64, SLT, SLTu, SLTi, SLTiu>, - INSN_MIPS4_32_NOT_32R6_64R6, FGR_64; -defm : MovzPats0<GPR64, FGR64, MOVZ_I_D64, SLT64, SLTu64, SLTi64, SLTiu64>, - INSN_MIPS4_32_NOT_32R6_64R6, FGR_64; -defm : MovzPats1<GPR32, FGR64, MOVZ_I_D64, XOR>, INSN_MIPS4_32_NOT_32R6_64R6, - FGR_64; -defm : MovzPats1<GPR64, FGR64, MOVZ_I64_D64, XOR64>, - INSN_MIPS4_32_NOT_32R6_64R6, FGR_64; -defm : MovnPats<GPR32, FGR64, MOVN_I_D64, XOR>, INSN_MIPS4_32_NOT_32R6_64R6, - FGR_64; -defm : MovnPats<GPR64, FGR64, MOVN_I64_D64, XOR64>, INSN_MIPS4_32_NOT_32R6_64R6, - FGR_64; - // For targets that don't have conditional-move instructions // we have to match SELECT nodes with pseudo instructions. let usesCustomInserter = 1 in { diff --git a/lib/Target/Mips/MipsConstantIslandPass.cpp b/lib/Target/Mips/MipsConstantIslandPass.cpp index a9abc171b423..9eb13a68e561 100644 --- a/lib/Target/Mips/MipsConstantIslandPass.cpp +++ b/lib/Target/Mips/MipsConstantIslandPass.cpp @@ -37,6 +37,7 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" +#include "llvm/Config/llvm-config.h" #include "llvm/IR/Constants.h" #include "llvm/IR/DataLayout.h" #include "llvm/IR/DebugLoc.h" @@ -442,13 +443,15 @@ bool MipsConstantIslands::runOnMachineFunction(MachineFunction &mf) { MF = &mf; MCP = mf.getConstantPool(); STI = &static_cast<const MipsSubtarget &>(mf.getSubtarget()); - DEBUG(dbgs() << "constant island machine function " << "\n"); + LLVM_DEBUG(dbgs() << "constant island machine function " + << "\n"); if (!STI->inMips16Mode() || !MipsSubtarget::useConstantIslands()) { return false; } TII = (const Mips16InstrInfo *)STI->getInstrInfo(); MFI = MF->getInfo<MipsFunctionInfo>(); - DEBUG(dbgs() << "constant island processing " << "\n"); + LLVM_DEBUG(dbgs() << "constant island processing " + << "\n"); // // will need to make predermination if there is any constants we need to // put in constant islands. TBD. @@ -479,7 +482,7 @@ bool MipsConstantIslands::runOnMachineFunction(MachineFunction &mf) { // constant pool users. initializeFunctionInfo(CPEMIs); CPEMIs.clear(); - DEBUG(dumpBBs()); + LLVM_DEBUG(dumpBBs()); /// Remove dead constant pool entries. MadeChange |= removeUnusedCPEntries(); @@ -489,31 +492,31 @@ bool MipsConstantIslands::runOnMachineFunction(MachineFunction &mf) { unsigned NoCPIters = 0, NoBRIters = 0; (void)NoBRIters; while (true) { - DEBUG(dbgs() << "Beginning CP iteration #" << NoCPIters << '\n'); + LLVM_DEBUG(dbgs() << "Beginning CP iteration #" << NoCPIters << '\n'); bool CPChange = false; for (unsigned i = 0, e = CPUsers.size(); i != e; ++i) CPChange |= handleConstantPoolUser(i); if (CPChange && ++NoCPIters > 30) report_fatal_error("Constant Island pass failed to converge!"); - DEBUG(dumpBBs()); + LLVM_DEBUG(dumpBBs()); // Clear NewWaterList now. If we split a block for branches, it should // appear as "new water" for the next iteration of constant pool placement. NewWaterList.clear(); - DEBUG(dbgs() << "Beginning BR iteration #" << NoBRIters << '\n'); + LLVM_DEBUG(dbgs() << "Beginning BR iteration #" << NoBRIters << '\n'); bool BRChange = false; for (unsigned i = 0, e = ImmBranches.size(); i != e; ++i) BRChange |= fixupImmediateBr(ImmBranches[i]); if (BRChange && ++NoBRIters > 30) report_fatal_error("Branch Fix Up pass failed to converge!"); - DEBUG(dumpBBs()); + LLVM_DEBUG(dumpBBs()); if (!CPChange && !BRChange) break; MadeChange = true; } - DEBUG(dbgs() << '\n'; dumpBBs()); + LLVM_DEBUG(dbgs() << '\n'; dumpBBs()); BBInfo.clear(); WaterList.clear(); @@ -580,10 +583,10 @@ MipsConstantIslands::doInitialPlacement(std::vector<MachineInstr*> &CPEMIs) { // Add a new CPEntry, but no corresponding CPUser yet. CPEntries.emplace_back(1, CPEntry(CPEMI, i)); ++NumCPEs; - DEBUG(dbgs() << "Moved CPI#" << i << " to end of function, size = " - << Size << ", align = " << Align <<'\n'); + LLVM_DEBUG(dbgs() << "Moved CPI#" << i << " to end of function, size = " + << Size << ", align = " << Align << '\n'); } - DEBUG(BB->dump()); + LLVM_DEBUG(BB->dump()); } /// BBHasFallthrough - Return true if the specified basic block can fallthrough @@ -660,7 +663,7 @@ initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) { if (!BBHasFallthrough(&MBB)) WaterList.push_back(&MBB); for (MachineInstr &MI : MBB) { - if (MI.isDebugValue()) + if (MI.isDebugInstr()) continue; int Opc = MI.getOpcode(); @@ -986,7 +989,7 @@ bool MipsConstantIslands::isCPEntryInRange unsigned CPEOffset = getOffsetOf(CPEMI); if (DoDump) { - DEBUG({ + LLVM_DEBUG({ unsigned Block = MI->getParent()->getNumber(); const BasicBlockInfo &BBI = BBInfo[Block]; dbgs() << "User of CPE#" << CPEMI->getOperand(0).getImm() @@ -1059,7 +1062,7 @@ int MipsConstantIslands::findInRangeCPEntry(CPUser& U, unsigned UserOffset) // Check to see if the CPE is already in-range. if (isCPEntryInRange(UserMI, UserOffset, CPEMI, U.getMaxDisp(), U.NegOk, true)) { - DEBUG(dbgs() << "In range\n"); + LLVM_DEBUG(dbgs() << "In range\n"); return 1; } @@ -1075,8 +1078,8 @@ int MipsConstantIslands::findInRangeCPEntry(CPUser& U, unsigned UserOffset) continue; if (isCPEntryInRange(UserMI, UserOffset, CPEs[i].CPEMI, U.getMaxDisp(), U.NegOk)) { - DEBUG(dbgs() << "Replacing CPE#" << CPI << " with CPE#" - << CPEs[i].CPI << "\n"); + LLVM_DEBUG(dbgs() << "Replacing CPE#" << CPI << " with CPE#" + << CPEs[i].CPI << "\n"); // Point the CPUser node to the replacement U.CPEMI = CPEs[i].CPEMI; // Change the CPI in the instruction operand to refer to the clone. @@ -1113,7 +1116,7 @@ int MipsConstantIslands::findLongFormInRangeCPEntry if (isCPEntryInRange(UserMI, UserOffset, CPEMI, U.getLongFormMaxDisp(), U.NegOk, true)) { - DEBUG(dbgs() << "In range\n"); + LLVM_DEBUG(dbgs() << "In range\n"); UserMI->setDesc(TII->get(U.getLongFormOpcode())); U.setMaxDisp(U.getLongFormMaxDisp()); return 2; // instruction is longer length now @@ -1131,8 +1134,8 @@ int MipsConstantIslands::findLongFormInRangeCPEntry continue; if (isCPEntryInRange(UserMI, UserOffset, CPEs[i].CPEMI, U.getLongFormMaxDisp(), U.NegOk)) { - DEBUG(dbgs() << "Replacing CPE#" << CPI << " with CPE#" - << CPEs[i].CPI << "\n"); + LLVM_DEBUG(dbgs() << "Replacing CPE#" << CPI << " with CPE#" + << CPEs[i].CPI << "\n"); // Point the CPUser node to the replacement U.CPEMI = CPEs[i].CPEMI; // Change the CPI in the instruction operand to refer to the clone. @@ -1197,8 +1200,8 @@ bool MipsConstantIslands::findAvailableWater(CPUser &U, unsigned UserOffset, // This is the least amount of required padding seen so far. BestGrowth = Growth; WaterIter = IP; - DEBUG(dbgs() << "Found water after " << printMBBReference(*WaterBB) - << " Growth=" << Growth << '\n'); + LLVM_DEBUG(dbgs() << "Found water after " << printMBBReference(*WaterBB) + << " Growth=" << Growth << '\n'); // Keep looking unless it is perfect. if (BestGrowth == 0) @@ -1236,8 +1239,8 @@ void MipsConstantIslands::createNewWater(unsigned CPUserIndex, unsigned CPEOffset = UserBBI.postOffset(CPELogAlign) + Delta; if (isOffsetInRange(UserOffset, CPEOffset, U)) { - DEBUG(dbgs() << "Split at end of " << printMBBReference(*UserMBB) - << format(", expected CPE offset %#x\n", CPEOffset)); + LLVM_DEBUG(dbgs() << "Split at end of " << printMBBReference(*UserMBB) + << format(", expected CPE offset %#x\n", CPEOffset)); NewMBB = &*++UserMBB->getIterator(); // Add an unconditional branch from UserMBB to fallthrough block. Record // it for branch lengthening; this new branch will not get out of range, @@ -1263,16 +1266,16 @@ void MipsConstantIslands::createNewWater(unsigned CPUserIndex, unsigned LogAlign = MF->getAlignment(); assert(LogAlign >= CPELogAlign && "Over-aligned constant pool entry"); unsigned BaseInsertOffset = UserOffset + U.getMaxDisp(); - DEBUG(dbgs() << format("Split in middle of big block before %#x", - BaseInsertOffset)); + LLVM_DEBUG(dbgs() << format("Split in middle of big block before %#x", + BaseInsertOffset)); // The 4 in the following is for the unconditional branch we'll be inserting // Alignment of the island is handled // inside isOffsetInRange. BaseInsertOffset -= 4; - DEBUG(dbgs() << format(", adjusted to %#x", BaseInsertOffset) - << " la=" << LogAlign << '\n'); + LLVM_DEBUG(dbgs() << format(", adjusted to %#x", BaseInsertOffset) + << " la=" << LogAlign << '\n'); // This could point off the end of the block if we've already got constant // pool entries following this block; only the last one is in the water list. @@ -1280,7 +1283,7 @@ void MipsConstantIslands::createNewWater(unsigned CPUserIndex, // long unconditional). if (BaseInsertOffset + 8 >= UserBBI.postOffset()) { BaseInsertOffset = UserBBI.postOffset() - 8; - DEBUG(dbgs() << format("Move inside block: %#x\n", BaseInsertOffset)); + LLVM_DEBUG(dbgs() << format("Move inside block: %#x\n", BaseInsertOffset)); } unsigned EndInsertOffset = BaseInsertOffset + 4 + CPEMI->getOperand(2).getImm(); @@ -1336,7 +1339,7 @@ bool MipsConstantIslands::handleConstantPoolUser(unsigned CPUserIndex) { MachineBasicBlock *NewMBB; water_iterator IP; if (findAvailableWater(U, UserOffset, IP)) { - DEBUG(dbgs() << "Found water in range\n"); + LLVM_DEBUG(dbgs() << "Found water in range\n"); MachineBasicBlock *WaterBB = *IP; // If the original WaterList entry was "new water" on this iteration, @@ -1355,7 +1358,7 @@ bool MipsConstantIslands::handleConstantPoolUser(unsigned CPUserIndex) { result = findLongFormInRangeCPEntry(U, UserOffset); if (result != 0) return true; } - DEBUG(dbgs() << "No water found\n"); + LLVM_DEBUG(dbgs() << "No water found\n"); createNewWater(CPUserIndex, UserOffset, NewMBB); // splitBlockBeforeInstr adds to WaterList, which is important when it is @@ -1414,8 +1417,9 @@ bool MipsConstantIslands::handleConstantPoolUser(unsigned CPUserIndex) { break; } - DEBUG(dbgs() << " Moved CPE to #" << ID << " CPI=" << CPI - << format(" offset=%#x\n", BBInfo[NewIsland->getNumber()].Offset)); + LLVM_DEBUG( + dbgs() << " Moved CPE to #" << ID << " CPI=" << CPI + << format(" offset=%#x\n", BBInfo[NewIsland->getNumber()].Offset)); return true; } @@ -1470,11 +1474,11 @@ bool MipsConstantIslands::isBBInRange unsigned BrOffset = getOffsetOf(MI) + PCAdj; unsigned DestOffset = BBInfo[DestBB->getNumber()].Offset; - DEBUG(dbgs() << "Branch of destination " << printMBBReference(*DestBB) - << " from " << printMBBReference(*MI->getParent()) - << " max delta=" << MaxDisp << " from " << getOffsetOf(MI) - << " to " << DestOffset << " offset " - << int(DestOffset - BrOffset) << "\t" << *MI); + LLVM_DEBUG(dbgs() << "Branch of destination " << printMBBReference(*DestBB) + << " from " << printMBBReference(*MI->getParent()) + << " max delta=" << MaxDisp << " from " << getOffsetOf(MI) + << " to " << DestOffset << " offset " + << int(DestOffset - BrOffset) << "\t" << *MI); if (BrOffset <= DestOffset) { // Branch before the Dest. @@ -1539,7 +1543,7 @@ MipsConstantIslands::fixupUnconditionalBr(ImmBranch &Br) { HasFarJump = true; ++NumUBrFixed; - DEBUG(dbgs() << " Changed B to long jump " << *MI); + LLVM_DEBUG(dbgs() << " Changed B to long jump " << *MI); return true; } @@ -1594,8 +1598,9 @@ MipsConstantIslands::fixupConditionalBr(ImmBranch &Br) { MachineBasicBlock *NewDest = BMI->getOperand(BMITargetOperand).getMBB(); if (isBBInRange(MI, NewDest, Br.MaxDisp)) { - DEBUG(dbgs() << " Invert Bcc condition and swap its destination with " - << *BMI); + LLVM_DEBUG( + dbgs() << " Invert Bcc condition and swap its destination with " + << *BMI); MI->setDesc(TII->get(OppositeBranchOpcode)); BMI->getOperand(BMITargetOperand).setMBB(DestBB); MI->getOperand(TargetOperand).setMBB(NewDest); @@ -1615,9 +1620,9 @@ MipsConstantIslands::fixupConditionalBr(ImmBranch &Br) { } MachineBasicBlock *NextBB = &*++MBB->getIterator(); - DEBUG(dbgs() << " Insert B to " << printMBBReference(*DestBB) - << " also invert condition and change dest. to " - << printMBBReference(*NextBB) << "\n"); + LLVM_DEBUG(dbgs() << " Insert B to " << printMBBReference(*DestBB) + << " also invert condition and change dest. to " + << printMBBReference(*NextBB) << "\n"); // Insert a new conditional branch and a new unconditional branch. // Also update the ImmBranch as well as adding a new entry for the new branch. @@ -1653,19 +1658,19 @@ void MipsConstantIslands::prescanForConstants() { switch(I->getDesc().getOpcode()) { case Mips::LwConstant32: { PrescannedForConstants = true; - DEBUG(dbgs() << "constant island constant " << *I << "\n"); + LLVM_DEBUG(dbgs() << "constant island constant " << *I << "\n"); J = I->getNumOperands(); - DEBUG(dbgs() << "num operands " << J << "\n"); + LLVM_DEBUG(dbgs() << "num operands " << J << "\n"); MachineOperand& Literal = I->getOperand(1); if (Literal.isImm()) { int64_t V = Literal.getImm(); - DEBUG(dbgs() << "literal " << V << "\n"); + LLVM_DEBUG(dbgs() << "literal " << V << "\n"); Type *Int32Ty = Type::getInt32Ty(MF->getFunction().getContext()); const Constant *C = ConstantInt::get(Int32Ty, V); unsigned index = MCP->getConstantPoolIndex(C, 4); I->getOperand(2).ChangeToImmediate(index); - DEBUG(dbgs() << "constant island constant " << *I << "\n"); + LLVM_DEBUG(dbgs() << "constant island constant " << *I << "\n"); I->setDesc(TII->get(Mips::LwRxPcTcp16)); I->RemoveOperand(1); I->RemoveOperand(1); diff --git a/lib/Target/Mips/MipsDSPInstrFormats.td b/lib/Target/Mips/MipsDSPInstrFormats.td index 0ceb1858fb09..5f0763f5ea46 100644 --- a/lib/Target/Mips/MipsDSPInstrFormats.td +++ b/lib/Target/Mips/MipsDSPInstrFormats.td @@ -29,11 +29,11 @@ def HasDSPR3 : Predicate<"Subtarget->hasDSPR3()">, AssemblerPredicate<"FeatureDSPR3">; class ISA_DSPR2 { - list<Predicate> InsnPredicates = [HasDSPR2]; + list<Predicate> ASEPredicate = [HasDSPR2]; } class ISA_DSPR3 { - list<Predicate> InsnPredicates = [HasDSPR3]; + list<Predicate> ASEPredicate = [HasDSPR3]; } // Fields. @@ -45,21 +45,21 @@ def SPECIAL3_OPCODE : Field6<0b011111>; def REGIMM_OPCODE : Field6<0b000001>; class DSPInst<string opstr = ""> - : MipsInst<(outs), (ins), "", [], NoItinerary, FrmOther>, PredicateControl { - let InsnPredicates = [HasDSP]; + : MipsInst<(outs), (ins), "", [], NoItinerary, FrmOther> { + let ASEPredicate = [HasDSP]; string BaseOpcode = opstr; string Arch = "dsp"; } class PseudoDSP<dag outs, dag ins, list<dag> pattern, InstrItinClass itin = IIPseudo> - : MipsPseudo<outs, ins, pattern, itin>, PredicateControl { - let InsnPredicates = [HasDSP]; + : MipsPseudo<outs, ins, pattern, itin> { + let ASEPredicate = [HasDSP]; } class DSPInstAlias<string Asm, dag Result, bit Emit = 0b1> : InstAlias<Asm, Result, Emit>, PredicateControl { - let InsnPredicates = [HasDSP]; + let ASEPredicate = [HasDSP]; } // ADDU.QB sub-class format. diff --git a/lib/Target/Mips/MipsDSPInstrInfo.td b/lib/Target/Mips/MipsDSPInstrInfo.td index 871135e3a22b..b9824220b558 100644 --- a/lib/Target/Mips/MipsDSPInstrInfo.td +++ b/lib/Target/Mips/MipsDSPInstrInfo.td @@ -447,6 +447,7 @@ class RDDSP_DESC_BASE<string instr_asm, SDPatternOperator OpNode, list<dag> Pattern = [(set GPR32Opnd:$rd, (OpNode immZExt10:$mask))]; InstrItinClass Itinerary = itin; string BaseOpcode = instr_asm; + bit isMoveReg = 1; } class WRDSP_DESC_BASE<string instr_asm, SDPatternOperator OpNode, @@ -457,6 +458,7 @@ class WRDSP_DESC_BASE<string instr_asm, SDPatternOperator OpNode, list<dag> Pattern = [(OpNode GPR32Opnd:$rs, immZExt10:$mask)]; InstrItinClass Itinerary = itin; string BaseOpcode = instr_asm; + bit isMoveReg = 1; } class DPA_W_PH_DESC_BASE<string instr_asm, SDPatternOperator OpNode> { @@ -500,6 +502,7 @@ class MFHI_DESC_BASE<string instr_asm, RegisterOperand RO, SDNode OpNode, list<dag> Pattern = [(set GPR32Opnd:$rd, (OpNode RO:$ac))]; InstrItinClass Itinerary = itin; string BaseOpcode = instr_asm; + bit isMoveReg = 1; } class MTHI_DESC_BASE<string instr_asm, RegisterOperand RO, InstrItinClass itin> { @@ -508,6 +511,7 @@ class MTHI_DESC_BASE<string instr_asm, RegisterOperand RO, InstrItinClass itin> string AsmString = !strconcat(instr_asm, "\t$rs, $ac"); InstrItinClass Itinerary = itin; string BaseOpcode = instr_asm; + bit isMoveReg = 1; } class BPOSGE32_PSEUDO_DESC_BASE<SDPatternOperator OpNode, InstrItinClass itin> : @@ -1285,7 +1289,7 @@ let isPseudo = 1, isCodeGenOnly = 1, hasNoSchedulingInfo = 1 in { } let DecoderNamespace = "MipsDSP", Arch = "dsp", - AdditionalPredicates = [HasDSP] in { + ASEPredicate = [HasDSP] in { def LWDSP : Load<"lw", DSPROpnd, null_frag, II_LW>, DspMMRel, LW_FM<0x23>; def SWDSP : Store<"sw", DSPROpnd, null_frag, II_SW>, DspMMRel, LW_FM<0x2b>; } diff --git a/lib/Target/Mips/MipsDelaySlotFiller.cpp b/lib/Target/Mips/MipsDelaySlotFiller.cpp index e06b57e41834..33f03b954a8c 100644 --- a/lib/Target/Mips/MipsDelaySlotFiller.cpp +++ b/lib/Target/Mips/MipsDelaySlotFiller.cpp @@ -51,7 +51,7 @@ using namespace llvm; -#define DEBUG_TYPE "delay-slot-filler" +#define DEBUG_TYPE "mips-delay-slot-filler" STATISTIC(FilledSlots, "Number of delay slots filled"); STATISTIC(UsefulSlots, "Number of delay slots filled with instructions that" @@ -210,9 +210,11 @@ namespace { bool SeenNoObjStore = false; }; - class Filler : public MachineFunctionPass { + class MipsDelaySlotFiller : public MachineFunctionPass { public: - Filler() : MachineFunctionPass(ID) {} + MipsDelaySlotFiller() : MachineFunctionPass(ID) { + initializeMipsDelaySlotFillerPass(*PassRegistry::getPassRegistry()); + } StringRef getPassName() const override { return "Mips Delay Slot Filler"; } @@ -242,6 +244,8 @@ namespace { MachineFunctionPass::getAnalysisUsage(AU); } + static char ID; + private: bool runOnMachineBasicBlock(MachineBasicBlock &MBB); @@ -292,18 +296,19 @@ namespace { bool terminateSearch(const MachineInstr &Candidate) const; const TargetMachine *TM = nullptr; - - static char ID; }; } // end anonymous namespace -char Filler::ID = 0; +char MipsDelaySlotFiller::ID = 0; static bool hasUnoccupiedSlot(const MachineInstr *MI) { return MI->hasDelaySlot() && !MI->isBundledWithSucc(); } +INITIALIZE_PASS(MipsDelaySlotFiller, DEBUG_TYPE, + "Fill delay slot for MIPS", false, false) + /// This function inserts clones of Filler into predecessor blocks. static void insertDelayFiller(Iter Filler, const BB2BrMap &BrMap) { MachineFunction *MF = Filler->getParent()->getParent(); @@ -551,8 +556,9 @@ getUnderlyingObjects(const MachineInstr &MI, } // Replace Branch with the compact branch instruction. -Iter Filler::replaceWithCompactBranch(MachineBasicBlock &MBB, Iter Branch, - const DebugLoc &DL) { +Iter MipsDelaySlotFiller::replaceWithCompactBranch(MachineBasicBlock &MBB, + Iter Branch, + const DebugLoc &DL) { const MipsSubtarget &STI = MBB.getParent()->getSubtarget<MipsSubtarget>(); const MipsInstrInfo *TII = STI.getInstrInfo(); @@ -575,6 +581,7 @@ static int getEquivalentCallShort(int Opcode) { case Mips::BLTZAL: return Mips::BLTZALS_MM; case Mips::JAL: + case Mips::JAL_MM: return Mips::JALS_MM; case Mips::JALR: return Mips::JALRS_MM; @@ -591,7 +598,7 @@ static int getEquivalentCallShort(int Opcode) { /// runOnMachineBasicBlock - Fill in delay slots for the given basic block. /// We assume there is only one delay slot per delayed instruction. -bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) { +bool MipsDelaySlotFiller::runOnMachineBasicBlock(MachineBasicBlock &MBB) { bool Changed = false; const MipsSubtarget &STI = MBB.getParent()->getSubtarget<MipsSubtarget>(); bool InMicroMipsMode = STI.inMicroMipsMode(); @@ -632,7 +639,7 @@ bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) { // TODO: Implement an instruction mapping table of 16bit opcodes to // 32bit opcodes so that an instruction can be expanded. This would // save 16 bits as a TAILCALL_MM pseudo requires a fullsized nop. - // TODO: Permit b16 when branching backwards to the the same function + // TODO: Permit b16 when branching backwards to the same function // if it is in range. DSI->setDesc(TII->get(getEquivalentCallShort(DSI->getOpcode()))); } @@ -669,16 +676,17 @@ bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) { return Changed; } -template<typename IterTy> -bool Filler::searchRange(MachineBasicBlock &MBB, IterTy Begin, IterTy End, - RegDefsUses &RegDU, InspectMemInstr& IM, Iter Slot, - IterTy &Filler) const { +template <typename IterTy> +bool MipsDelaySlotFiller::searchRange(MachineBasicBlock &MBB, IterTy Begin, + IterTy End, RegDefsUses &RegDU, + InspectMemInstr &IM, Iter Slot, + IterTy &Filler) const { for (IterTy I = Begin; I != End;) { IterTy CurrI = I; ++I; // skip debug value - if (CurrI->isDebugValue()) + if (CurrI->isDebugInstr()) continue; if (terminateSearch(*CurrI)) @@ -720,6 +728,10 @@ bool Filler::searchRange(MachineBasicBlock &MBB, IterTy Begin, IterTy End, (Opcode == Mips::JR || Opcode == Mips::PseudoIndirectBranch || Opcode == Mips::PseudoReturn || Opcode == Mips::TAILCALL)) continue; + // Instructions LWP/SWP should not be in a delay slot as that + // results in unpredictable behaviour + if (InMicroMipsMode && (Opcode == Mips::LWP_MM || Opcode == Mips::SWP_MM)) + continue; Filler = CurrI; return true; @@ -728,7 +740,8 @@ bool Filler::searchRange(MachineBasicBlock &MBB, IterTy Begin, IterTy End, return false; } -bool Filler::searchBackward(MachineBasicBlock &MBB, MachineInstr &Slot) const { +bool MipsDelaySlotFiller::searchBackward(MachineBasicBlock &MBB, + MachineInstr &Slot) const { if (DisableBackwardSearch) return false; @@ -750,7 +763,8 @@ bool Filler::searchBackward(MachineBasicBlock &MBB, MachineInstr &Slot) const { return true; } -bool Filler::searchForward(MachineBasicBlock &MBB, Iter Slot) const { +bool MipsDelaySlotFiller::searchForward(MachineBasicBlock &MBB, + Iter Slot) const { // Can handle only calls. if (DisableForwardSearch || !Slot->isCall()) return false; @@ -770,7 +784,8 @@ bool Filler::searchForward(MachineBasicBlock &MBB, Iter Slot) const { return true; } -bool Filler::searchSuccBBs(MachineBasicBlock &MBB, Iter Slot) const { +bool MipsDelaySlotFiller::searchSuccBBs(MachineBasicBlock &MBB, + Iter Slot) const { if (DisableSuccBBSearch) return false; @@ -816,7 +831,8 @@ bool Filler::searchSuccBBs(MachineBasicBlock &MBB, Iter Slot) const { return true; } -MachineBasicBlock *Filler::selectSuccBB(MachineBasicBlock &B) const { +MachineBasicBlock * +MipsDelaySlotFiller::selectSuccBB(MachineBasicBlock &B) const { if (B.succ_empty()) return nullptr; @@ -832,7 +848,8 @@ MachineBasicBlock *Filler::selectSuccBB(MachineBasicBlock &B) const { } std::pair<MipsInstrInfo::BranchType, MachineInstr *> -Filler::getBranch(MachineBasicBlock &MBB, const MachineBasicBlock &Dst) const { +MipsDelaySlotFiller::getBranch(MachineBasicBlock &MBB, + const MachineBasicBlock &Dst) const { const MipsInstrInfo *TII = MBB.getParent()->getSubtarget<MipsSubtarget>().getInstrInfo(); MachineBasicBlock *TrueBB = nullptr, *FalseBB = nullptr; @@ -867,11 +884,13 @@ Filler::getBranch(MachineBasicBlock &MBB, const MachineBasicBlock &Dst) const { return std::make_pair(MipsInstrInfo::BT_None, nullptr); } -bool Filler::examinePred(MachineBasicBlock &Pred, const MachineBasicBlock &Succ, - RegDefsUses &RegDU, bool &HasMultipleSuccs, - BB2BrMap &BrMap) const { +bool MipsDelaySlotFiller::examinePred(MachineBasicBlock &Pred, + const MachineBasicBlock &Succ, + RegDefsUses &RegDU, + bool &HasMultipleSuccs, + BB2BrMap &BrMap) const { std::pair<MipsInstrInfo::BranchType, MachineInstr *> P = - getBranch(Pred, Succ); + getBranch(Pred, Succ); // Return if either getBranch wasn't able to analyze the branches or there // were no branches with unoccupied slots. @@ -888,8 +907,9 @@ bool Filler::examinePred(MachineBasicBlock &Pred, const MachineBasicBlock &Succ, return true; } -bool Filler::delayHasHazard(const MachineInstr &Candidate, RegDefsUses &RegDU, - InspectMemInstr &IM) const { +bool MipsDelaySlotFiller::delayHasHazard(const MachineInstr &Candidate, + RegDefsUses &RegDU, + InspectMemInstr &IM) const { assert(!Candidate.isKill() && "KILL instructions should have been eliminated at this point."); @@ -901,7 +921,7 @@ bool Filler::delayHasHazard(const MachineInstr &Candidate, RegDefsUses &RegDU, return HasHazard; } -bool Filler::terminateSearch(const MachineInstr &Candidate) const { +bool MipsDelaySlotFiller::terminateSearch(const MachineInstr &Candidate) const { return (Candidate.isTerminator() || Candidate.isCall() || Candidate.isPosition() || Candidate.isInlineAsm() || Candidate.hasUnmodeledSideEffects()); @@ -909,4 +929,4 @@ bool Filler::terminateSearch(const MachineInstr &Candidate) const { /// createMipsDelaySlotFillerPass - Returns a pass that fills in delay /// slots in Mips MachineFunctions -FunctionPass *llvm::createMipsDelaySlotFillerPass() { return new Filler(); } +FunctionPass *llvm::createMipsDelaySlotFillerPass() { return new MipsDelaySlotFiller(); } diff --git a/lib/Target/Mips/MipsEVAInstrFormats.td b/lib/Target/Mips/MipsEVAInstrFormats.td index 8c3024810d27..61785d0e891a 100644 --- a/lib/Target/Mips/MipsEVAInstrFormats.td +++ b/lib/Target/Mips/MipsEVAInstrFormats.td @@ -12,7 +12,7 @@ //===----------------------------------------------------------------------===// class MipsEVAInst : MipsInst<(outs), (ins), "", [], NoItinerary, FrmOther>, - PredicateControl, StdArch { + StdArch { let DecoderNamespace = "Mips"; let EncodingPredicates = [HasStdEnc]; } diff --git a/lib/Target/Mips/MipsEVAInstrInfo.td b/lib/Target/Mips/MipsEVAInstrInfo.td index 26df263d228b..ff54b1f17877 100644 --- a/lib/Target/Mips/MipsEVAInstrInfo.td +++ b/lib/Target/Mips/MipsEVAInstrInfo.td @@ -59,6 +59,7 @@ class LOAD_EVA_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, list<dag> Pattern = []; string DecoderMethod = "DecodeMemEVA"; bit canFoldAsLoad = 1; + string BaseOpcode = instr_asm; bit mayLoad = 1; InstrItinClass Itinerary = itin; } @@ -77,6 +78,7 @@ class STORE_EVA_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); list<dag> Pattern = []; string DecoderMethod = "DecodeMemEVA"; + string BaseOpcode = instr_asm; bit mayStore = 1; InstrItinClass Itinerary = itin; } @@ -93,13 +95,16 @@ class LOAD_LEFT_RIGHT_EVA_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); list<dag> Pattern = []; string DecoderMethod = "DecodeMemEVA"; + string BaseOpcode = instr_asm; string Constraints = "$src = $rt"; bit canFoldAsLoad = 1; InstrItinClass Itinerary = itin; + bit mayLoad = 1; + bit mayStore = 0; } -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 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, InstrItinClass itin = NoItinerary> { @@ -108,11 +113,14 @@ class STORE_LEFT_RIGHT_EVA_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); list<dag> Pattern = []; string DecoderMethod = "DecodeMemEVA"; + string BaseOpcode = instr_asm; InstrItinClass Itinerary = itin; + bit mayLoad = 0; + bit mayStore = 1; } -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>; +class SWLE_DESC : STORE_LEFT_RIGHT_EVA_DESC_BASE<"swle", GPR32Opnd, II_SWLE>; +class SWRE_DESC : STORE_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, @@ -121,6 +129,7 @@ class LLE_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, dag InOperandList = (ins mem_simm9:$addr); string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); list<dag> Pattern = []; + string BaseOpcode = instr_asm; bit mayLoad = 1; string DecoderMethod = "DecodeMemEVA"; InstrItinClass Itinerary = itin; @@ -134,6 +143,7 @@ class SCE_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, dag InOperandList = (ins GPROpnd:$rt, mem_simm9:$addr); string AsmString = !strconcat(instr_asm, "\t$rt, $addr"); list<dag> Pattern = []; + string BaseOpcode = instr_asm; bit mayStore = 1; string Constraints = "$rt = $dst"; string DecoderMethod = "DecodeMemEVA"; @@ -159,6 +169,7 @@ class CACHEE_DESC_BASE<string instr_asm, Operand MemOpnd, dag InOperandList = (ins MemOpnd:$addr, uimm5:$hint); string AsmString = !strconcat(instr_asm, "\t$hint, $addr"); list<dag> Pattern = []; + string BaseOpcode = instr_asm; string DecoderMethod = "DecodeCacheeOp_CacheOpR6"; InstrItinClass Itinerary = itin; } @@ -172,38 +183,32 @@ class PREFE_DESC : CACHEE_DESC_BASE<"prefe", mem_simm9, II_PREFE>; // //===----------------------------------------------------------------------===// -/// Load and Store EVA Instructions -def LBE : LBE_ENC, LBE_DESC, INSN_EVA; -def LBuE : LBuE_ENC, LBuE_DESC, INSN_EVA; -def LHE : LHE_ENC, LHE_DESC, INSN_EVA; -def LHuE : LHuE_ENC, LHuE_DESC, INSN_EVA; -let AdditionalPredicates = [NotInMicroMips] in { -def LWE : LWE_ENC, LWE_DESC, INSN_EVA; -} -def SBE : SBE_ENC, SBE_DESC, INSN_EVA; -def SHE : SHE_ENC, SHE_DESC, INSN_EVA; -let AdditionalPredicates = [NotInMicroMips] in { -def SWE : SWE_ENC, SWE_DESC, INSN_EVA; -} - -/// load/store left/right EVA let AdditionalPredicates = [NotInMicroMips] in { -def LWLE : LWLE_ENC, LWLE_DESC, INSN_EVA_NOT_32R6_64R6; -def LWRE : LWRE_ENC, LWRE_DESC, INSN_EVA_NOT_32R6_64R6; -def SWLE : SWLE_ENC, SWLE_DESC, INSN_EVA_NOT_32R6_64R6; -def SWRE : SWRE_ENC, SWRE_DESC, INSN_EVA_NOT_32R6_64R6; + /// Load and Store EVA Instructions + def LBE : MMRel, LBE_ENC, LBE_DESC, ISA_MIPS32R2, ASE_EVA; + def LBuE : MMRel, LBuE_ENC, LBuE_DESC, ISA_MIPS32R2, ASE_EVA; + def LHE : MMRel, LHE_ENC, LHE_DESC, ISA_MIPS32R2, ASE_EVA; + def LHuE : MMRel, LHuE_ENC, LHuE_DESC, ISA_MIPS32R2, ASE_EVA; + def LWE : MMRel, LWE_ENC, LWE_DESC, ISA_MIPS32R2, ASE_EVA; + def SBE : MMRel, SBE_ENC, SBE_DESC, ISA_MIPS32R2, ASE_EVA; + def SHE : MMRel, SHE_ENC, SHE_DESC, ISA_MIPS32R2, ASE_EVA; + def SWE : MMRel, SWE_ENC, SWE_DESC, ISA_MIPS32R2, ASE_EVA; + + /// load/store left/right EVA + def LWLE : MMRel, LWLE_ENC, LWLE_DESC, ISA_MIPS32R2_NOT_32R6_64R6, ASE_EVA; + def LWRE : MMRel, LWRE_ENC, LWRE_DESC, ISA_MIPS32R2_NOT_32R6_64R6, ASE_EVA; + def SWLE : MMRel, SWLE_ENC, SWLE_DESC, ISA_MIPS32R2_NOT_32R6_64R6, ASE_EVA; + def SWRE : MMRel, SWRE_ENC, SWRE_DESC, ISA_MIPS32R2_NOT_32R6_64R6, ASE_EVA; + + /// Load-linked EVA, Store-conditional EVA + def LLE : MMRel, LLE_ENC, LLE_DESC, ISA_MIPS32R2, ASE_EVA; + def SCE : MMRel, SCE_ENC, SCE_DESC, ISA_MIPS32R2, ASE_EVA; + + /// TLB invalidate instructions + def TLBINV : TLBINV_ENC, TLBINV_DESC, ISA_MIPS32R2, ASE_EVA; + def TLBINVF : TLBINVF_ENC, TLBINVF_DESC, ISA_MIPS32R2, ASE_EVA; + + /// EVA versions of cache and pref + def CACHEE : MMRel, CACHEE_ENC, CACHEE_DESC, ISA_MIPS32R2, ASE_EVA; + def PREFE : MMRel, PREFE_ENC, PREFE_DESC, ISA_MIPS32R2, ASE_EVA; } - -/// Load-linked EVA, Store-conditional EVA -let AdditionalPredicates = [NotInMicroMips] in { -def LLE : LLE_ENC, LLE_DESC, INSN_EVA; -def SCE : SCE_ENC, SCE_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/MipsExpandPseudo.cpp b/lib/Target/Mips/MipsExpandPseudo.cpp new file mode 100644 index 000000000000..acf66d1fb1b2 --- /dev/null +++ b/lib/Target/Mips/MipsExpandPseudo.cpp @@ -0,0 +1,702 @@ +//===-- MipsExpandPseudoInsts.cpp - Expand pseudo instructions ------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a pass that expands pseudo instructions into target +// instructions to allow proper scheduling, if-conversion, and other late +// optimizations. This pass should be run after register allocation but before +// the post-regalloc scheduling pass. +// +// This is currently only used for expanding atomic pseudos after register +// allocation. We do this to avoid the fast register allocator introducing +// spills between ll and sc. These stores cause some MIPS implementations to +// abort the atomic RMW sequence. +// +//===----------------------------------------------------------------------===// + +#include "Mips.h" +#include "MipsInstrInfo.h" +#include "MipsSubtarget.h" +#include "llvm/CodeGen/LivePhysRegs.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstrBuilder.h" + +using namespace llvm; + +#define DEBUG_TYPE "mips-pseudo" + +namespace { + class MipsExpandPseudo : public MachineFunctionPass { + public: + static char ID; + MipsExpandPseudo() : MachineFunctionPass(ID) {} + + const MipsInstrInfo *TII; + const MipsSubtarget *STI; + + bool runOnMachineFunction(MachineFunction &Fn) override; + + MachineFunctionProperties getRequiredProperties() const override { + return MachineFunctionProperties().set( + MachineFunctionProperties::Property::NoVRegs); + } + + StringRef getPassName() const override { + return "Mips pseudo instruction expansion pass"; + } + + private: + bool expandAtomicCmpSwap(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + MachineBasicBlock::iterator &NextMBBI); + bool expandAtomicCmpSwapSubword(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + MachineBasicBlock::iterator &NextMBBI); + + bool expandAtomicBinOp(MachineBasicBlock &BB, + MachineBasicBlock::iterator I, + MachineBasicBlock::iterator &NMBBI, unsigned Size); + bool expandAtomicBinOpSubword(MachineBasicBlock &BB, + MachineBasicBlock::iterator I, + MachineBasicBlock::iterator &NMBBI); + + bool expandMI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, + MachineBasicBlock::iterator &NMBB); + bool expandMBB(MachineBasicBlock &MBB); + }; + char MipsExpandPseudo::ID = 0; +} + +bool MipsExpandPseudo::expandAtomicCmpSwapSubword( + MachineBasicBlock &BB, MachineBasicBlock::iterator I, + MachineBasicBlock::iterator &NMBBI) { + + MachineFunction *MF = BB.getParent(); + + const bool ArePtrs64bit = STI->getABI().ArePtrs64bit(); + DebugLoc DL = I->getDebugLoc(); + unsigned LL, SC; + + unsigned ZERO = Mips::ZERO; + unsigned BNE = Mips::BNE; + unsigned BEQ = Mips::BEQ; + unsigned SEOp = + I->getOpcode() == Mips::ATOMIC_CMP_SWAP_I8_POSTRA ? Mips::SEB : Mips::SEH; + + if (STI->inMicroMipsMode()) { + LL = STI->hasMips32r6() ? Mips::LL_MMR6 : Mips::LL_MM; + SC = STI->hasMips32r6() ? Mips::SC_MMR6 : Mips::SC_MM; + BNE = STI->hasMips32r6() ? Mips::BNEC_MMR6 : Mips::BNE_MM; + BEQ = STI->hasMips32r6() ? Mips::BEQC_MMR6 : Mips::BEQ_MM; + } else { + LL = STI->hasMips32r6() ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6) + : (ArePtrs64bit ? Mips::LL64 : Mips::LL); + SC = STI->hasMips32r6() ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6) + : (ArePtrs64bit ? Mips::SC64 : Mips::SC); + } + + unsigned Dest = I->getOperand(0).getReg(); + unsigned Ptr = I->getOperand(1).getReg(); + unsigned Mask = I->getOperand(2).getReg(); + unsigned ShiftCmpVal = I->getOperand(3).getReg(); + unsigned Mask2 = I->getOperand(4).getReg(); + unsigned ShiftNewVal = I->getOperand(5).getReg(); + unsigned ShiftAmnt = I->getOperand(6).getReg(); + unsigned Scratch = I->getOperand(7).getReg(); + unsigned Scratch2 = I->getOperand(8).getReg(); + + // insert new blocks after the current block + const BasicBlock *LLVM_BB = BB.getBasicBlock(); + MachineBasicBlock *loop1MBB = MF->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *loop2MBB = MF->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); + MachineFunction::iterator It = ++BB.getIterator(); + MF->insert(It, loop1MBB); + MF->insert(It, loop2MBB); + MF->insert(It, sinkMBB); + MF->insert(It, exitMBB); + + // Transfer the remainder of BB and its successor edges to exitMBB. + exitMBB->splice(exitMBB->begin(), &BB, + std::next(MachineBasicBlock::iterator(I)), BB.end()); + exitMBB->transferSuccessorsAndUpdatePHIs(&BB); + + // thisMBB: + // ... + // fallthrough --> loop1MBB + BB.addSuccessor(loop1MBB, BranchProbability::getOne()); + loop1MBB->addSuccessor(sinkMBB); + loop1MBB->addSuccessor(loop2MBB); + loop1MBB->normalizeSuccProbs(); + loop2MBB->addSuccessor(loop1MBB); + loop2MBB->addSuccessor(sinkMBB); + loop2MBB->normalizeSuccProbs(); + sinkMBB->addSuccessor(exitMBB, BranchProbability::getOne()); + + // loop1MBB: + // ll dest, 0(ptr) + // and Mask', dest, Mask + // bne Mask', ShiftCmpVal, exitMBB + BuildMI(loop1MBB, DL, TII->get(LL), Scratch).addReg(Ptr).addImm(0); + BuildMI(loop1MBB, DL, TII->get(Mips::AND), Scratch2) + .addReg(Scratch) + .addReg(Mask); + BuildMI(loop1MBB, DL, TII->get(BNE)) + .addReg(Scratch2).addReg(ShiftCmpVal).addMBB(sinkMBB); + + // loop2MBB: + // and dest, dest, mask2 + // or dest, dest, ShiftNewVal + // sc dest, dest, 0(ptr) + // beq dest, $0, loop1MBB + BuildMI(loop2MBB, DL, TII->get(Mips::AND), Scratch) + .addReg(Scratch, RegState::Kill) + .addReg(Mask2); + BuildMI(loop2MBB, DL, TII->get(Mips::OR), Scratch) + .addReg(Scratch, RegState::Kill) + .addReg(ShiftNewVal); + BuildMI(loop2MBB, DL, TII->get(SC), Scratch) + .addReg(Scratch, RegState::Kill) + .addReg(Ptr) + .addImm(0); + BuildMI(loop2MBB, DL, TII->get(BEQ)) + .addReg(Scratch, RegState::Kill) + .addReg(ZERO) + .addMBB(loop1MBB); + + // sinkMBB: + // srl srlres, Mask', shiftamt + // sign_extend dest,srlres + BuildMI(sinkMBB, DL, TII->get(Mips::SRLV), Dest) + .addReg(Scratch2) + .addReg(ShiftAmnt); + if (STI->hasMips32r2()) { + BuildMI(sinkMBB, DL, TII->get(SEOp), Dest).addReg(Dest); + } else { + const unsigned ShiftImm = + I->getOpcode() == Mips::ATOMIC_CMP_SWAP_I16_POSTRA ? 16 : 24; + BuildMI(sinkMBB, DL, TII->get(Mips::SLL), Dest) + .addReg(Dest, RegState::Kill) + .addImm(ShiftImm); + BuildMI(sinkMBB, DL, TII->get(Mips::SRA), Dest) + .addReg(Dest, RegState::Kill) + .addImm(ShiftImm); + } + + LivePhysRegs LiveRegs; + computeAndAddLiveIns(LiveRegs, *loop1MBB); + computeAndAddLiveIns(LiveRegs, *loop2MBB); + computeAndAddLiveIns(LiveRegs, *sinkMBB); + computeAndAddLiveIns(LiveRegs, *exitMBB); + + NMBBI = BB.end(); + I->eraseFromParent(); + return true; +} + +bool MipsExpandPseudo::expandAtomicCmpSwap(MachineBasicBlock &BB, + MachineBasicBlock::iterator I, + MachineBasicBlock::iterator &NMBBI) { + + const unsigned Size = + I->getOpcode() == Mips::ATOMIC_CMP_SWAP_I32_POSTRA ? 4 : 8; + MachineFunction *MF = BB.getParent(); + + const bool ArePtrs64bit = STI->getABI().ArePtrs64bit(); + DebugLoc DL = I->getDebugLoc(); + + unsigned LL, SC, ZERO, BNE, BEQ, MOVE; + + if (Size == 4) { + if (STI->inMicroMipsMode()) { + LL = STI->hasMips32r6() ? Mips::LL_MMR6 : Mips::LL_MM; + SC = STI->hasMips32r6() ? Mips::SC_MMR6 : Mips::SC_MM; + BNE = STI->hasMips32r6() ? Mips::BNEC_MMR6 : Mips::BNE_MM; + BEQ = STI->hasMips32r6() ? Mips::BEQC_MMR6 : Mips::BEQ_MM; + } else { + LL = STI->hasMips32r6() + ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6) + : (ArePtrs64bit ? Mips::LL64 : Mips::LL); + SC = STI->hasMips32r6() + ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6) + : (ArePtrs64bit ? Mips::SC64 : Mips::SC); + BNE = Mips::BNE; + BEQ = Mips::BEQ; + } + + ZERO = Mips::ZERO; + MOVE = Mips::OR; + } else { + LL = STI->hasMips64r6() ? Mips::LLD_R6 : Mips::LLD; + SC = STI->hasMips64r6() ? Mips::SCD_R6 : Mips::SCD; + ZERO = Mips::ZERO_64; + BNE = Mips::BNE64; + BEQ = Mips::BEQ64; + MOVE = Mips::OR64; + } + + unsigned Dest = I->getOperand(0).getReg(); + unsigned Ptr = I->getOperand(1).getReg(); + unsigned OldVal = I->getOperand(2).getReg(); + unsigned NewVal = I->getOperand(3).getReg(); + unsigned Scratch = I->getOperand(4).getReg(); + + // insert new blocks after the current block + const BasicBlock *LLVM_BB = BB.getBasicBlock(); + MachineBasicBlock *loop1MBB = MF->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *loop2MBB = MF->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); + MachineFunction::iterator It = ++BB.getIterator(); + MF->insert(It, loop1MBB); + MF->insert(It, loop2MBB); + MF->insert(It, exitMBB); + + // Transfer the remainder of BB and its successor edges to exitMBB. + exitMBB->splice(exitMBB->begin(), &BB, + std::next(MachineBasicBlock::iterator(I)), BB.end()); + exitMBB->transferSuccessorsAndUpdatePHIs(&BB); + + // thisMBB: + // ... + // fallthrough --> loop1MBB + BB.addSuccessor(loop1MBB, BranchProbability::getOne()); + loop1MBB->addSuccessor(exitMBB); + loop1MBB->addSuccessor(loop2MBB); + loop1MBB->normalizeSuccProbs(); + loop2MBB->addSuccessor(loop1MBB); + loop2MBB->addSuccessor(exitMBB); + loop2MBB->normalizeSuccProbs(); + + // loop1MBB: + // ll dest, 0(ptr) + // bne dest, oldval, exitMBB + BuildMI(loop1MBB, DL, TII->get(LL), Dest).addReg(Ptr).addImm(0); + BuildMI(loop1MBB, DL, TII->get(BNE)) + .addReg(Dest, RegState::Kill).addReg(OldVal).addMBB(exitMBB); + + // loop2MBB: + // move scratch, NewVal + // sc Scratch, Scratch, 0(ptr) + // beq Scratch, $0, loop1MBB + BuildMI(loop2MBB, DL, TII->get(MOVE), Scratch).addReg(NewVal).addReg(ZERO); + BuildMI(loop2MBB, DL, TII->get(SC), Scratch) + .addReg(Scratch).addReg(Ptr).addImm(0); + BuildMI(loop2MBB, DL, TII->get(BEQ)) + .addReg(Scratch, RegState::Kill).addReg(ZERO).addMBB(loop1MBB); + + LivePhysRegs LiveRegs; + computeAndAddLiveIns(LiveRegs, *loop1MBB); + computeAndAddLiveIns(LiveRegs, *loop2MBB); + computeAndAddLiveIns(LiveRegs, *exitMBB); + + NMBBI = BB.end(); + I->eraseFromParent(); + return true; +} + +bool MipsExpandPseudo::expandAtomicBinOpSubword( + MachineBasicBlock &BB, MachineBasicBlock::iterator I, + MachineBasicBlock::iterator &NMBBI) { + + MachineFunction *MF = BB.getParent(); + + const bool ArePtrs64bit = STI->getABI().ArePtrs64bit(); + DebugLoc DL = I->getDebugLoc(); + + unsigned LL, SC; + unsigned BEQ = Mips::BEQ; + unsigned SEOp = Mips::SEH; + + if (STI->inMicroMipsMode()) { + LL = STI->hasMips32r6() ? Mips::LL_MMR6 : Mips::LL_MM; + SC = STI->hasMips32r6() ? Mips::SC_MMR6 : Mips::SC_MM; + BEQ = STI->hasMips32r6() ? Mips::BEQC_MMR6 : Mips::BEQ_MM; + } else { + LL = STI->hasMips32r6() ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6) + : (ArePtrs64bit ? Mips::LL64 : Mips::LL); + SC = STI->hasMips32r6() ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6) + : (ArePtrs64bit ? Mips::SC64 : Mips::SC); + } + + bool IsSwap = false; + bool IsNand = false; + + unsigned Opcode = 0; + switch (I->getOpcode()) { + case Mips::ATOMIC_LOAD_NAND_I8_POSTRA: + SEOp = Mips::SEB; + LLVM_FALLTHROUGH; + case Mips::ATOMIC_LOAD_NAND_I16_POSTRA: + IsNand = true; + break; + case Mips::ATOMIC_SWAP_I8_POSTRA: + SEOp = Mips::SEB; + LLVM_FALLTHROUGH; + case Mips::ATOMIC_SWAP_I16_POSTRA: + IsSwap = true; + break; + case Mips::ATOMIC_LOAD_ADD_I8_POSTRA: + SEOp = Mips::SEB; + LLVM_FALLTHROUGH; + case Mips::ATOMIC_LOAD_ADD_I16_POSTRA: + Opcode = Mips::ADDu; + break; + case Mips::ATOMIC_LOAD_SUB_I8_POSTRA: + SEOp = Mips::SEB; + LLVM_FALLTHROUGH; + case Mips::ATOMIC_LOAD_SUB_I16_POSTRA: + Opcode = Mips::SUBu; + break; + case Mips::ATOMIC_LOAD_AND_I8_POSTRA: + SEOp = Mips::SEB; + LLVM_FALLTHROUGH; + case Mips::ATOMIC_LOAD_AND_I16_POSTRA: + Opcode = Mips::AND; + break; + case Mips::ATOMIC_LOAD_OR_I8_POSTRA: + SEOp = Mips::SEB; + LLVM_FALLTHROUGH; + case Mips::ATOMIC_LOAD_OR_I16_POSTRA: + Opcode = Mips::OR; + break; + case Mips::ATOMIC_LOAD_XOR_I8_POSTRA: + SEOp = Mips::SEB; + LLVM_FALLTHROUGH; + case Mips::ATOMIC_LOAD_XOR_I16_POSTRA: + Opcode = Mips::XOR; + break; + default: + llvm_unreachable("Unknown subword atomic pseudo for expansion!"); + } + + unsigned Dest = I->getOperand(0).getReg(); + unsigned Ptr = I->getOperand(1).getReg(); + unsigned Incr = I->getOperand(2).getReg(); + unsigned Mask = I->getOperand(3).getReg(); + unsigned Mask2 = I->getOperand(4).getReg(); + unsigned ShiftAmnt = I->getOperand(5).getReg(); + unsigned OldVal = I->getOperand(6).getReg(); + unsigned BinOpRes = I->getOperand(7).getReg(); + unsigned StoreVal = I->getOperand(8).getReg(); + + const BasicBlock *LLVM_BB = BB.getBasicBlock(); + MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); + MachineFunction::iterator It = ++BB.getIterator(); + MF->insert(It, loopMBB); + MF->insert(It, sinkMBB); + MF->insert(It, exitMBB); + + exitMBB->splice(exitMBB->begin(), &BB, std::next(I), BB.end()); + exitMBB->transferSuccessorsAndUpdatePHIs(&BB); + + BB.addSuccessor(loopMBB, BranchProbability::getOne()); + loopMBB->addSuccessor(sinkMBB); + loopMBB->addSuccessor(loopMBB); + loopMBB->normalizeSuccProbs(); + + BuildMI(loopMBB, DL, TII->get(LL), OldVal).addReg(Ptr).addImm(0); + if (IsNand) { + // and andres, oldval, incr2 + // nor binopres, $0, andres + // and newval, binopres, mask + BuildMI(loopMBB, DL, TII->get(Mips::AND), BinOpRes) + .addReg(OldVal) + .addReg(Incr); + BuildMI(loopMBB, DL, TII->get(Mips::NOR), BinOpRes) + .addReg(Mips::ZERO) + .addReg(BinOpRes); + BuildMI(loopMBB, DL, TII->get(Mips::AND), BinOpRes) + .addReg(BinOpRes) + .addReg(Mask); + } else if (!IsSwap) { + // <binop> binopres, oldval, incr2 + // and newval, binopres, mask + BuildMI(loopMBB, DL, TII->get(Opcode), BinOpRes) + .addReg(OldVal) + .addReg(Incr); + BuildMI(loopMBB, DL, TII->get(Mips::AND), BinOpRes) + .addReg(BinOpRes) + .addReg(Mask); + } else { // atomic.swap + // and newval, incr2, mask + BuildMI(loopMBB, DL, TII->get(Mips::AND), BinOpRes) + .addReg(Incr) + .addReg(Mask); + } + + // and StoreVal, OlddVal, Mask2 + // or StoreVal, StoreVal, BinOpRes + // StoreVal<tied1> = sc StoreVal, 0(Ptr) + // beq StoreVal, zero, loopMBB + BuildMI(loopMBB, DL, TII->get(Mips::AND), StoreVal) + .addReg(OldVal).addReg(Mask2); + BuildMI(loopMBB, DL, TII->get(Mips::OR), StoreVal) + .addReg(StoreVal).addReg(BinOpRes); + BuildMI(loopMBB, DL, TII->get(SC), StoreVal) + .addReg(StoreVal).addReg(Ptr).addImm(0); + BuildMI(loopMBB, DL, TII->get(BEQ)) + .addReg(StoreVal).addReg(Mips::ZERO).addMBB(loopMBB); + + // sinkMBB: + // and maskedoldval1,oldval,mask + // srl srlres,maskedoldval1,shiftamt + // sign_extend dest,srlres + + sinkMBB->addSuccessor(exitMBB, BranchProbability::getOne()); + + BuildMI(sinkMBB, DL, TII->get(Mips::AND), Dest) + .addReg(OldVal).addReg(Mask); + BuildMI(sinkMBB, DL, TII->get(Mips::SRLV), Dest) + .addReg(Dest).addReg(ShiftAmnt); + + if (STI->hasMips32r2()) { + BuildMI(sinkMBB, DL, TII->get(SEOp), Dest).addReg(Dest); + } else { + const unsigned ShiftImm = SEOp == Mips::SEH ? 16 : 24; + BuildMI(sinkMBB, DL, TII->get(Mips::SLL), Dest) + .addReg(Dest, RegState::Kill) + .addImm(ShiftImm); + BuildMI(sinkMBB, DL, TII->get(Mips::SRA), Dest) + .addReg(Dest, RegState::Kill) + .addImm(ShiftImm); + } + + LivePhysRegs LiveRegs; + computeAndAddLiveIns(LiveRegs, *loopMBB); + computeAndAddLiveIns(LiveRegs, *sinkMBB); + computeAndAddLiveIns(LiveRegs, *exitMBB); + + NMBBI = BB.end(); + I->eraseFromParent(); + + return true; +} + +bool MipsExpandPseudo::expandAtomicBinOp(MachineBasicBlock &BB, + MachineBasicBlock::iterator I, + MachineBasicBlock::iterator &NMBBI, + unsigned Size) { + MachineFunction *MF = BB.getParent(); + + const bool ArePtrs64bit = STI->getABI().ArePtrs64bit(); + DebugLoc DL = I->getDebugLoc(); + + unsigned LL, SC, ZERO, BEQ; + + if (Size == 4) { + if (STI->inMicroMipsMode()) { + LL = STI->hasMips32r6() ? Mips::LL_MMR6 : Mips::LL_MM; + SC = STI->hasMips32r6() ? Mips::SC_MMR6 : Mips::SC_MM; + BEQ = STI->hasMips32r6() ? Mips::BEQC_MMR6 : Mips::BEQ_MM; + } else { + LL = STI->hasMips32r6() + ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6) + : (ArePtrs64bit ? Mips::LL64 : Mips::LL); + SC = STI->hasMips32r6() + ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6) + : (ArePtrs64bit ? Mips::SC64 : Mips::SC); + BEQ = Mips::BEQ; + } + + ZERO = Mips::ZERO; + } else { + LL = STI->hasMips64r6() ? Mips::LLD_R6 : Mips::LLD; + SC = STI->hasMips64r6() ? Mips::SCD_R6 : Mips::SCD; + ZERO = Mips::ZERO_64; + BEQ = Mips::BEQ64; + } + + unsigned OldVal = I->getOperand(0).getReg(); + unsigned Ptr = I->getOperand(1).getReg(); + unsigned Incr = I->getOperand(2).getReg(); + unsigned Scratch = I->getOperand(3).getReg(); + + unsigned Opcode = 0; + unsigned OR = 0; + unsigned AND = 0; + unsigned NOR = 0; + bool IsNand = false; + switch (I->getOpcode()) { + case Mips::ATOMIC_LOAD_ADD_I32_POSTRA: + Opcode = Mips::ADDu; + break; + case Mips::ATOMIC_LOAD_SUB_I32_POSTRA: + Opcode = Mips::SUBu; + break; + case Mips::ATOMIC_LOAD_AND_I32_POSTRA: + Opcode = Mips::AND; + break; + case Mips::ATOMIC_LOAD_OR_I32_POSTRA: + Opcode = Mips::OR; + break; + case Mips::ATOMIC_LOAD_XOR_I32_POSTRA: + Opcode = Mips::XOR; + break; + case Mips::ATOMIC_LOAD_NAND_I32_POSTRA: + IsNand = true; + AND = Mips::AND; + NOR = Mips::NOR; + break; + case Mips::ATOMIC_SWAP_I32_POSTRA: + OR = Mips::OR; + break; + case Mips::ATOMIC_LOAD_ADD_I64_POSTRA: + Opcode = Mips::DADDu; + break; + case Mips::ATOMIC_LOAD_SUB_I64_POSTRA: + Opcode = Mips::DSUBu; + break; + case Mips::ATOMIC_LOAD_AND_I64_POSTRA: + Opcode = Mips::AND64; + break; + case Mips::ATOMIC_LOAD_OR_I64_POSTRA: + Opcode = Mips::OR64; + break; + case Mips::ATOMIC_LOAD_XOR_I64_POSTRA: + Opcode = Mips::XOR64; + break; + case Mips::ATOMIC_LOAD_NAND_I64_POSTRA: + IsNand = true; + AND = Mips::AND64; + NOR = Mips::NOR64; + break; + case Mips::ATOMIC_SWAP_I64_POSTRA: + OR = Mips::OR64; + break; + default: + llvm_unreachable("Unknown pseudo atomic!"); + } + + const BasicBlock *LLVM_BB = BB.getBasicBlock(); + MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(LLVM_BB); + MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); + MachineFunction::iterator It = ++BB.getIterator(); + MF->insert(It, loopMBB); + MF->insert(It, exitMBB); + + exitMBB->splice(exitMBB->begin(), &BB, std::next(I), BB.end()); + exitMBB->transferSuccessorsAndUpdatePHIs(&BB); + + BB.addSuccessor(loopMBB, BranchProbability::getOne()); + loopMBB->addSuccessor(exitMBB); + loopMBB->addSuccessor(loopMBB); + loopMBB->normalizeSuccProbs(); + + BuildMI(loopMBB, DL, TII->get(LL), OldVal).addReg(Ptr).addImm(0); + assert((OldVal != Ptr) && "Clobbered the wrong ptr reg!"); + assert((OldVal != Incr) && "Clobbered the wrong reg!"); + if (Opcode) { + BuildMI(loopMBB, DL, TII->get(Opcode), Scratch).addReg(OldVal).addReg(Incr); + } else if (IsNand) { + assert(AND && NOR && + "Unknown nand instruction for atomic pseudo expansion"); + BuildMI(loopMBB, DL, TII->get(AND), Scratch).addReg(OldVal).addReg(Incr); + BuildMI(loopMBB, DL, TII->get(NOR), Scratch).addReg(ZERO).addReg(Scratch); + } else { + assert(OR && "Unknown instruction for atomic pseudo expansion!"); + BuildMI(loopMBB, DL, TII->get(OR), Scratch).addReg(Incr).addReg(ZERO); + } + + BuildMI(loopMBB, DL, TII->get(SC), Scratch).addReg(Scratch).addReg(Ptr).addImm(0); + BuildMI(loopMBB, DL, TII->get(BEQ)).addReg(Scratch).addReg(ZERO).addMBB(loopMBB); + + NMBBI = BB.end(); + I->eraseFromParent(); + + LivePhysRegs LiveRegs; + computeAndAddLiveIns(LiveRegs, *loopMBB); + computeAndAddLiveIns(LiveRegs, *exitMBB); + + return true; +} + +bool MipsExpandPseudo::expandMI(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + MachineBasicBlock::iterator &NMBB) { + + bool Modified = false; + + switch (MBBI->getOpcode()) { + case Mips::ATOMIC_CMP_SWAP_I32_POSTRA: + case Mips::ATOMIC_CMP_SWAP_I64_POSTRA: + return expandAtomicCmpSwap(MBB, MBBI, NMBB); + case Mips::ATOMIC_CMP_SWAP_I8_POSTRA: + case Mips::ATOMIC_CMP_SWAP_I16_POSTRA: + return expandAtomicCmpSwapSubword(MBB, MBBI, NMBB); + case Mips::ATOMIC_SWAP_I8_POSTRA: + case Mips::ATOMIC_SWAP_I16_POSTRA: + case Mips::ATOMIC_LOAD_NAND_I8_POSTRA: + case Mips::ATOMIC_LOAD_NAND_I16_POSTRA: + case Mips::ATOMIC_LOAD_ADD_I8_POSTRA: + case Mips::ATOMIC_LOAD_ADD_I16_POSTRA: + case Mips::ATOMIC_LOAD_SUB_I8_POSTRA: + case Mips::ATOMIC_LOAD_SUB_I16_POSTRA: + case Mips::ATOMIC_LOAD_AND_I8_POSTRA: + case Mips::ATOMIC_LOAD_AND_I16_POSTRA: + case Mips::ATOMIC_LOAD_OR_I8_POSTRA: + case Mips::ATOMIC_LOAD_OR_I16_POSTRA: + case Mips::ATOMIC_LOAD_XOR_I8_POSTRA: + case Mips::ATOMIC_LOAD_XOR_I16_POSTRA: + return expandAtomicBinOpSubword(MBB, MBBI, NMBB); + case Mips::ATOMIC_LOAD_ADD_I32_POSTRA: + case Mips::ATOMIC_LOAD_SUB_I32_POSTRA: + case Mips::ATOMIC_LOAD_AND_I32_POSTRA: + case Mips::ATOMIC_LOAD_OR_I32_POSTRA: + case Mips::ATOMIC_LOAD_XOR_I32_POSTRA: + case Mips::ATOMIC_LOAD_NAND_I32_POSTRA: + case Mips::ATOMIC_SWAP_I32_POSTRA: + return expandAtomicBinOp(MBB, MBBI, NMBB, 4); + case Mips::ATOMIC_LOAD_ADD_I64_POSTRA: + case Mips::ATOMIC_LOAD_SUB_I64_POSTRA: + case Mips::ATOMIC_LOAD_AND_I64_POSTRA: + case Mips::ATOMIC_LOAD_OR_I64_POSTRA: + case Mips::ATOMIC_LOAD_XOR_I64_POSTRA: + case Mips::ATOMIC_LOAD_NAND_I64_POSTRA: + case Mips::ATOMIC_SWAP_I64_POSTRA: + return expandAtomicBinOp(MBB, MBBI, NMBB, 8); + default: + return Modified; + } +} + +bool MipsExpandPseudo::expandMBB(MachineBasicBlock &MBB) { + bool Modified = false; + + MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); + while (MBBI != E) { + MachineBasicBlock::iterator NMBBI = std::next(MBBI); + Modified |= expandMI(MBB, MBBI, NMBBI); + MBBI = NMBBI; + } + + return Modified; +} + +bool MipsExpandPseudo::runOnMachineFunction(MachineFunction &MF) { + STI = &static_cast<const MipsSubtarget &>(MF.getSubtarget()); + TII = STI->getInstrInfo(); + + bool Modified = false; + for (MachineFunction::iterator MFI = MF.begin(), E = MF.end(); MFI != E; + ++MFI) + Modified |= expandMBB(*MFI); + + if (Modified) + MF.RenumberBlocks(); + + return Modified; +} + +/// createMipsExpandPseudoPass - returns an instance of the pseudo instruction +/// expansion pass. +FunctionPass *llvm::createMipsExpandPseudoPass() { + return new MipsExpandPseudo(); +} diff --git a/lib/Target/Mips/MipsFastISel.cpp b/lib/Target/Mips/MipsFastISel.cpp index 8bbac3ed7cfb..7b39507812ed 100644 --- a/lib/Target/Mips/MipsFastISel.cpp +++ b/lib/Target/Mips/MipsFastISel.cpp @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief This file defines the MIPS-specific support for the FastISel class. +/// 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. /// @@ -36,7 +36,6 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/MachineValueType.h" #include "llvm/CodeGen/TargetInstrInfo.h" #include "llvm/CodeGen/TargetLowering.h" #include "llvm/CodeGen/ValueTypes.h" @@ -64,9 +63,11 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MachineValueType.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> +#include <array> #include <cassert> #include <cstdint> @@ -950,12 +951,9 @@ bool MipsFastISel::selectBranch(const Instruction *I) { // MachineBasicBlock *TBB = FuncInfo.MBBMap[BI->getSuccessor(0)]; MachineBasicBlock *FBB = FuncInfo.MBBMap[BI->getSuccessor(1)]; - BI->getCondition(); // For now, just try the simplest case where it's fed by a compare. if (const CmpInst *CI = dyn_cast<CmpInst>(BI->getCondition())) { - unsigned CondReg = createResultReg(&Mips::GPR32RegClass); - if (!emitCmp(CondReg, CI)) - return false; + unsigned CondReg = getRegForValue(CI); BuildMI(*BrBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::BGTZ)) .addReg(CondReg) .addMBB(TBB); @@ -1000,11 +998,12 @@ bool MipsFastISel::selectFPExt(const Instruction *I) { bool MipsFastISel::selectSelect(const Instruction *I) { assert(isa<SelectInst>(I) && "Expected a select instruction."); - DEBUG(dbgs() << "selectSelect\n"); + LLVM_DEBUG(dbgs() << "selectSelect\n"); MVT VT; if (!isTypeSupported(I->getType(), VT) || UnsupportedFPMode) { - DEBUG(dbgs() << ".. .. gave up (!isTypeSupported || UnsupportedFPMode)\n"); + LLVM_DEBUG( + dbgs() << ".. .. gave up (!isTypeSupported || UnsupportedFPMode)\n"); return false; } @@ -1287,32 +1286,32 @@ bool MipsFastISel::finishCall(CallLoweringInfo &CLI, MVT RetVT, } bool MipsFastISel::fastLowerArguments() { - DEBUG(dbgs() << "fastLowerArguments\n"); + LLVM_DEBUG(dbgs() << "fastLowerArguments\n"); if (!FuncInfo.CanLowerReturn) { - DEBUG(dbgs() << ".. gave up (!CanLowerReturn)\n"); + LLVM_DEBUG(dbgs() << ".. gave up (!CanLowerReturn)\n"); return false; } const Function *F = FuncInfo.Fn; if (F->isVarArg()) { - DEBUG(dbgs() << ".. gave up (varargs)\n"); + LLVM_DEBUG(dbgs() << ".. gave up (varargs)\n"); return false; } CallingConv::ID CC = F->getCallingConv(); if (CC != CallingConv::C) { - DEBUG(dbgs() << ".. gave up (calling convention is not C)\n"); + LLVM_DEBUG(dbgs() << ".. gave up (calling convention is not C)\n"); return false; } - const ArrayRef<MCPhysReg> GPR32ArgRegs = {Mips::A0, Mips::A1, Mips::A2, - Mips::A3}; - const ArrayRef<MCPhysReg> FGR32ArgRegs = {Mips::F12, Mips::F14}; - const ArrayRef<MCPhysReg> AFGR64ArgRegs = {Mips::D6, Mips::D7}; - ArrayRef<MCPhysReg>::iterator NextGPR32 = GPR32ArgRegs.begin(); - ArrayRef<MCPhysReg>::iterator NextFGR32 = FGR32ArgRegs.begin(); - ArrayRef<MCPhysReg>::iterator NextAFGR64 = AFGR64ArgRegs.begin(); + std::array<MCPhysReg, 4> GPR32ArgRegs = {{Mips::A0, Mips::A1, Mips::A2, + Mips::A3}}; + std::array<MCPhysReg, 2> FGR32ArgRegs = {{Mips::F12, Mips::F14}}; + std::array<MCPhysReg, 2> AFGR64ArgRegs = {{Mips::D6, Mips::D7}}; + auto NextGPR32 = GPR32ArgRegs.begin(); + auto NextFGR32 = FGR32ArgRegs.begin(); + auto NextAFGR64 = AFGR64ArgRegs.begin(); struct AllocatedReg { const TargetRegisterClass *RC; @@ -1328,21 +1327,21 @@ bool MipsFastISel::fastLowerArguments() { if (FormalArg.hasAttribute(Attribute::InReg) || FormalArg.hasAttribute(Attribute::StructRet) || FormalArg.hasAttribute(Attribute::ByVal)) { - DEBUG(dbgs() << ".. gave up (inreg, structret, byval)\n"); + LLVM_DEBUG(dbgs() << ".. gave up (inreg, structret, byval)\n"); return false; } Type *ArgTy = FormalArg.getType(); if (ArgTy->isStructTy() || ArgTy->isArrayTy() || ArgTy->isVectorTy()) { - DEBUG(dbgs() << ".. gave up (struct, array, or vector)\n"); + LLVM_DEBUG(dbgs() << ".. gave up (struct, array, or vector)\n"); return false; } EVT ArgVT = TLI.getValueType(DL, ArgTy); - DEBUG(dbgs() << ".. " << FormalArg.getArgNo() << ": " - << ArgVT.getEVTString() << "\n"); + LLVM_DEBUG(dbgs() << ".. " << FormalArg.getArgNo() << ": " + << ArgVT.getEVTString() << "\n"); if (!ArgVT.isSimple()) { - DEBUG(dbgs() << ".. .. gave up (not a simple type)\n"); + LLVM_DEBUG(dbgs() << ".. .. gave up (not a simple type)\n"); return false; } @@ -1354,16 +1353,16 @@ bool MipsFastISel::fastLowerArguments() { !FormalArg.hasAttribute(Attribute::ZExt)) { // It must be any extend, this shouldn't happen for clang-generated IR // so just fall back on SelectionDAG. - DEBUG(dbgs() << ".. .. gave up (i8/i16 arg is not extended)\n"); + LLVM_DEBUG(dbgs() << ".. .. gave up (i8/i16 arg is not extended)\n"); return false; } if (NextGPR32 == GPR32ArgRegs.end()) { - DEBUG(dbgs() << ".. .. gave up (ran out of GPR32 arguments)\n"); + LLVM_DEBUG(dbgs() << ".. .. gave up (ran out of GPR32 arguments)\n"); return false; } - DEBUG(dbgs() << ".. .. GPR32(" << *NextGPR32 << ")\n"); + LLVM_DEBUG(dbgs() << ".. .. GPR32(" << *NextGPR32 << ")\n"); Allocation.emplace_back(&Mips::GPR32RegClass, *NextGPR32++); // Allocating any GPR32 prohibits further use of floating point arguments. @@ -1374,16 +1373,16 @@ bool MipsFastISel::fastLowerArguments() { case MVT::i32: if (FormalArg.hasAttribute(Attribute::ZExt)) { // The O32 ABI does not permit a zero-extended i32. - DEBUG(dbgs() << ".. .. gave up (i32 arg is zero extended)\n"); + LLVM_DEBUG(dbgs() << ".. .. gave up (i32 arg is zero extended)\n"); return false; } if (NextGPR32 == GPR32ArgRegs.end()) { - DEBUG(dbgs() << ".. .. gave up (ran out of GPR32 arguments)\n"); + LLVM_DEBUG(dbgs() << ".. .. gave up (ran out of GPR32 arguments)\n"); return false; } - DEBUG(dbgs() << ".. .. GPR32(" << *NextGPR32 << ")\n"); + LLVM_DEBUG(dbgs() << ".. .. GPR32(" << *NextGPR32 << ")\n"); Allocation.emplace_back(&Mips::GPR32RegClass, *NextGPR32++); // Allocating any GPR32 prohibits further use of floating point arguments. @@ -1393,14 +1392,14 @@ bool MipsFastISel::fastLowerArguments() { case MVT::f32: if (UnsupportedFPMode) { - DEBUG(dbgs() << ".. .. gave up (UnsupportedFPMode)\n"); + LLVM_DEBUG(dbgs() << ".. .. gave up (UnsupportedFPMode)\n"); return false; } if (NextFGR32 == FGR32ArgRegs.end()) { - DEBUG(dbgs() << ".. .. gave up (ran out of FGR32 arguments)\n"); + LLVM_DEBUG(dbgs() << ".. .. gave up (ran out of FGR32 arguments)\n"); return false; } - DEBUG(dbgs() << ".. .. FGR32(" << *NextFGR32 << ")\n"); + LLVM_DEBUG(dbgs() << ".. .. FGR32(" << *NextFGR32 << ")\n"); Allocation.emplace_back(&Mips::FGR32RegClass, *NextFGR32++); // Allocating an FGR32 also allocates the super-register AFGR64, and // ABI rules require us to skip the corresponding GPR32. @@ -1412,14 +1411,14 @@ bool MipsFastISel::fastLowerArguments() { case MVT::f64: if (UnsupportedFPMode) { - DEBUG(dbgs() << ".. .. gave up (UnsupportedFPMode)\n"); + LLVM_DEBUG(dbgs() << ".. .. gave up (UnsupportedFPMode)\n"); return false; } if (NextAFGR64 == AFGR64ArgRegs.end()) { - DEBUG(dbgs() << ".. .. gave up (ran out of AFGR64 arguments)\n"); + LLVM_DEBUG(dbgs() << ".. .. gave up (ran out of AFGR64 arguments)\n"); return false; } - DEBUG(dbgs() << ".. .. AFGR64(" << *NextAFGR64 << ")\n"); + LLVM_DEBUG(dbgs() << ".. .. AFGR64(" << *NextAFGR64 << ")\n"); Allocation.emplace_back(&Mips::AFGR64RegClass, *NextAFGR64++); // Allocating an FGR32 also allocates the super-register AFGR64, and // ABI rules require us to skip the corresponding GPR32 pair. @@ -1432,7 +1431,7 @@ bool MipsFastISel::fastLowerArguments() { break; default: - DEBUG(dbgs() << ".. .. gave up (unknown type)\n"); + LLVM_DEBUG(dbgs() << ".. .. gave up (unknown type)\n"); return false; } } @@ -1628,7 +1627,7 @@ bool MipsFastISel::fastLowerIntrinsicCall(const IntrinsicInst *II) { if (!MTI->getLength()->getType()->isIntegerTy(32)) return false; const char *IntrMemName = isa<MemCpyInst>(II) ? "memcpy" : "memmove"; - return lowerCallTo(II, IntrMemName, II->getNumArgOperands() - 2); + return lowerCallTo(II, IntrMemName, II->getNumArgOperands() - 1); } case Intrinsic::memset: { const MemSetInst *MSI = cast<MemSetInst>(II); @@ -1637,7 +1636,7 @@ bool MipsFastISel::fastLowerIntrinsicCall(const IntrinsicInst *II) { return false; if (!MSI->getLength()->getType()->isIntegerTy(32)) return false; - return lowerCallTo(II, "memset", II->getNumArgOperands() - 2); + return lowerCallTo(II, "memset", II->getNumArgOperands() - 1); } } return false; @@ -1647,7 +1646,7 @@ bool MipsFastISel::selectRet(const Instruction *I) { const Function &F = *I->getParent()->getParent(); const ReturnInst *Ret = cast<ReturnInst>(I); - DEBUG(dbgs() << "selectRet\n"); + LLVM_DEBUG(dbgs() << "selectRet\n"); if (!FuncInfo.CanLowerReturn) return false; @@ -1711,7 +1710,7 @@ bool MipsFastISel::selectRet(const Instruction *I) { // Do not handle FGR64 returns for now. if (RVVT == MVT::f64 && UnsupportedFPMode) { - DEBUG(dbgs() << ".. .. gave up (UnsupportedFPMode\n"); + LLVM_DEBUG(dbgs() << ".. .. gave up (UnsupportedFPMode\n"); return false; } @@ -2063,6 +2062,10 @@ unsigned MipsFastISel::getRegEnsuringSimpleIntegerWidening(const Value *V, if (VReg == 0) return 0; MVT VMVT = TLI.getValueType(DL, V->getType(), true).getSimpleVT(); + + if (VMVT == MVT::i1) + return 0; + if ((VMVT == MVT::i8) || (VMVT == MVT::i16)) { unsigned TempReg = createResultReg(&Mips::GPR32RegClass); if (!emitIntExt(VMVT, VReg, MVT::i32, TempReg, IsUnsigned)) diff --git a/lib/Target/Mips/MipsFrameLowering.h b/lib/Target/Mips/MipsFrameLowering.h index 883c3267d51a..0ead56eddd2f 100644 --- a/lib/Target/Mips/MipsFrameLowering.h +++ b/lib/Target/Mips/MipsFrameLowering.h @@ -36,6 +36,10 @@ public: bool isFPCloseToIncomingSP() const override { return false; } + bool enableShrinkWrapping(const MachineFunction &MF) const override { + return true; + } + MachineBasicBlock::iterator eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, diff --git a/lib/Target/Mips/MipsHazardSchedule.cpp b/lib/Target/Mips/MipsHazardSchedule.cpp deleted file mode 100644 index da67c1bcea99..000000000000 --- a/lib/Target/Mips/MipsHazardSchedule.cpp +++ /dev/null @@ -1,163 +0,0 @@ -//===- 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 insufficient, as -/// backwards delay slot fillling can also produce hazards in previously -/// processed instuctions. -/// -//===----------------------------------------------------------------------===// - -#include "Mips.h" -#include "MipsInstrInfo.h" -#include "MipsSubtarget.h" -#include "llvm/ADT/Statistic.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineFunctionPass.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include <algorithm> -#include <iterator> -#include <utility> - -using namespace llvm; - -#define DEBUG_TYPE "mips-hazard-schedule" - -STATISTIC(NumInsertedNops, "Number of nops inserted"); - -namespace { - -using Iter = MachineBasicBlock::iterator; -using ReverseIter = MachineBasicBlock::reverse_iterator; - -class MipsHazardSchedule : public MachineFunctionPass { -public: - MipsHazardSchedule() : MachineFunctionPass(ID) {} - - StringRef getPassName() const override { return "Mips Hazard Schedule"; } - - bool runOnMachineFunction(MachineFunction &F) override; - - MachineFunctionProperties getRequiredProperties() const override { - return MachineFunctionProperties().set( - MachineFunctionProperties::Property::NoVRegs); - } - -private: - static char ID; -}; - -} // end of anonymous namespace - -char MipsHazardSchedule::ID = 0; - -/// Returns a pass that clears pipeline hazards. -FunctionPass *llvm::createMipsHazardSchedule() { - return new MipsHazardSchedule(); -} - -// Find the next real instruction from the current position in current basic -// block. -static Iter getNextMachineInstrInBB(Iter Position) { - Iter I = Position, E = Position->getParent()->end(); - I = std::find_if_not(I, E, - [](const Iter &Insn) { return Insn->isTransient(); }); - - return I; -} - -// Find the next real instruction from the current position, looking through -// basic block boundaries. -static std::pair<Iter, bool> getNextMachineInstr(Iter Position, MachineBasicBlock * Parent) { - if (Position == Parent->end()) { - do { - MachineBasicBlock *Succ = Parent->getNextNode(); - if (Succ != nullptr && Parent->isSuccessor(Succ)) { - Position = Succ->begin(); - Parent = Succ; - } else { - return std::make_pair(Position, true); - } - } while (Parent->empty()); - } - - Iter Instr = getNextMachineInstrInBB(Position); - if (Instr == Parent->end()) { - return getNextMachineInstr(Instr, Parent); - } - return std::make_pair(Instr, false); -} - -bool MipsHazardSchedule::runOnMachineFunction(MachineFunction &MF) { - - const MipsSubtarget *STI = - &static_cast<const MipsSubtarget &>(MF.getSubtarget()); - - // Forbidden slot hazards are only defined for MIPSR6 but not microMIPSR6. - 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; - - Iter Inst; - bool LastInstInFunction = - std::next(I) == FI->end() && std::next(FI) == MF.end(); - if (!LastInstInFunction) { - std::pair<Iter, bool> Res = getNextMachineInstr(std::next(I), &*FI); - LastInstInFunction |= Res.second; - Inst = Res.first; - } - - if (LastInstInFunction || !TII->SafeInForbiddenSlot(*Inst)) { - 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 0e1173f1c617..f99f3a1b3e0a 100644 --- a/lib/Target/Mips/MipsISelDAGToDAG.cpp +++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp @@ -24,6 +24,7 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/SelectionDAGNodes.h" +#include "llvm/CodeGen/StackProtector.h" #include "llvm/IR/CFG.h" #include "llvm/IR/GlobalValue.h" #include "llvm/IR/Instructions.h" @@ -46,6 +47,13 @@ using namespace llvm; // instructions for SelectionDAG operations. //===----------------------------------------------------------------------===// +void MipsDAGToDAGISel::getAnalysisUsage(AnalysisUsage &AU) const { + // There are multiple MipsDAGToDAGISel instances added to the pass pipeline. + // We need to preserve StackProtector for the next one. + AU.addPreserved<StackProtector>(); + SelectionDAGISel::getAnalysisUsage(AU); +} + bool MipsDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { Subtarget = &static_cast<const MipsSubtarget &>(MF.getSubtarget()); bool Ret = SelectionDAGISel::runOnMachineFunction(MF); @@ -215,12 +223,9 @@ bool MipsDAGToDAGISel::selectVSplatMaskR(SDValue N, SDValue &Imm) const { void MipsDAGToDAGISel::Select(SDNode *Node) { unsigned Opcode = Node->getOpcode(); - // Dump information about the Node being selected - DEBUG(errs() << "Selecting: "; Node->dump(CurDAG); errs() << "\n"); - // If we have a custom node, we already have selected! if (Node->isMachineOpcode()) { - DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n"); + LLVM_DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n"); Node->setNodeId(-1); return; } diff --git a/lib/Target/Mips/MipsISelDAGToDAG.h b/lib/Target/Mips/MipsISelDAGToDAG.h index 20bdd4aa8f5f..09003459d180 100644 --- a/lib/Target/Mips/MipsISelDAGToDAG.h +++ b/lib/Target/Mips/MipsISelDAGToDAG.h @@ -41,6 +41,8 @@ public: bool runOnMachineFunction(MachineFunction &MF) override; + void getAnalysisUsage(AnalysisUsage &AU) const override; + protected: SDNode *getGlobalBaseReg(); @@ -93,34 +95,34 @@ private: virtual bool selectAddr16(SDValue Addr, SDValue &Base, SDValue &Offset); virtual bool selectAddr16SP(SDValue Addr, SDValue &Base, SDValue &Offset); - /// \brief Select constant vector splats. + /// Select constant vector splats. virtual bool selectVSplat(SDNode *N, APInt &Imm, unsigned MinSizeInBits) const; - /// \brief Select constant vector splats whose value fits in a uimm1. + /// Select constant vector splats whose value fits in a uimm1. virtual bool selectVSplatUimm1(SDValue N, SDValue &Imm) const; - /// \brief Select constant vector splats whose value fits in a uimm2. + /// Select constant vector splats whose value fits in a uimm2. virtual bool selectVSplatUimm2(SDValue N, SDValue &Imm) const; - /// \brief Select constant vector splats whose value fits in a uimm3. + /// Select constant vector splats whose value fits in a uimm3. virtual bool selectVSplatUimm3(SDValue N, SDValue &Imm) const; - /// \brief Select constant vector splats whose value fits in a uimm4. + /// Select constant vector splats whose value fits in a uimm4. virtual bool selectVSplatUimm4(SDValue N, SDValue &Imm) const; - /// \brief Select constant vector splats whose value fits in a uimm5. + /// Select constant vector splats whose value fits in a uimm5. virtual bool selectVSplatUimm5(SDValue N, SDValue &Imm) const; - /// \brief Select constant vector splats whose value fits in a uimm6. + /// Select constant vector splats whose value fits in a uimm6. virtual bool selectVSplatUimm6(SDValue N, SDValue &Imm) const; - /// \brief Select constant vector splats whose value fits in a uimm8. + /// Select constant vector splats whose value fits in a uimm8. virtual bool selectVSplatUimm8(SDValue N, SDValue &Imm) const; - /// \brief Select constant vector splats whose value fits in a simm5. + /// Select constant vector splats whose value fits in a simm5. virtual bool selectVSplatSimm5(SDValue N, SDValue &Imm) const; - /// \brief Select constant vector splats whose value is a power of 2. + /// Select constant vector splats whose value is a power of 2. virtual bool selectVSplatUimmPow2(SDValue N, SDValue &Imm) const; - /// \brief Select constant vector splats whose value is the inverse of a + /// Select constant vector splats whose value is the inverse of a /// power of 2. virtual bool selectVSplatUimmInvPow2(SDValue N, SDValue &Imm) const; - /// \brief Select constant vector splats whose value is a run of set bits + /// Select constant vector splats whose value is a run of set bits /// ending at the most significant bit virtual bool selectVSplatMaskL(SDValue N, SDValue &Imm) const; - /// \brief Select constant vector splats whose value is a run of set bits + /// Select constant vector splats whose value is a run of set bits /// starting at bit zero. virtual bool selectVSplatMaskR(SDValue N, SDValue &Imm) const; diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index 6448fd917560..9ffc38356b76 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -41,7 +41,6 @@ #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/MachineValueType.h" #include "llvm/CodeGen/RuntimeLibcalls.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/SelectionDAGNodes.h" @@ -64,6 +63,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MachineValueType.h" #include "llvm/Support/MathExtras.h" #include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetOptions.h" @@ -110,12 +110,6 @@ static bool isShiftedMask(uint64_t I, uint64_t &Pos, uint64_t &Size) { // The MIPS MSA ABI passes vector arguments in the integer register set. // The number of integer registers used is dependant on the ABI used. -MVT MipsTargetLowering::getRegisterTypeForCallingConv(MVT VT) const { - if (VT.isVector() && Subtarget.hasMSA()) - return Subtarget.isABI_O32() ? MVT::i32 : MVT::i64; - return MipsTargetLowering::getRegisterType(VT); -} - MVT MipsTargetLowering::getRegisterTypeForCallingConv(LLVMContext &Context, EVT VT) const { if (VT.isVector()) { @@ -195,11 +189,13 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { case MipsISD::Hi: return "MipsISD::Hi"; case MipsISD::Lo: return "MipsISD::Lo"; case MipsISD::GotHi: return "MipsISD::GotHi"; + case MipsISD::TlsHi: return "MipsISD::TlsHi"; case MipsISD::GPRel: return "MipsISD::GPRel"; case MipsISD::ThreadPointer: return "MipsISD::ThreadPointer"; case MipsISD::Ret: return "MipsISD::Ret"; case MipsISD::ERet: return "MipsISD::ERet"; case MipsISD::EH_RETURN: return "MipsISD::EH_RETURN"; + case MipsISD::FMS: return "MipsISD::FMS"; case MipsISD::FPBrcond: return "MipsISD::FPBrcond"; case MipsISD::FPCmp: return "MipsISD::FPCmp"; case MipsISD::FSELECT: return "MipsISD::FSELECT"; @@ -286,10 +282,6 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const { case MipsISD::VCLE_U: return "MipsISD::VCLE_U"; case MipsISD::VCLT_S: return "MipsISD::VCLT_S"; case MipsISD::VCLT_U: return "MipsISD::VCLT_U"; - case MipsISD::VSMAX: return "MipsISD::VSMAX"; - case MipsISD::VSMIN: return "MipsISD::VSMIN"; - case MipsISD::VUMAX: return "MipsISD::VUMAX"; - case MipsISD::VUMIN: return "MipsISD::VUMIN"; case MipsISD::VEXTRACT_SEXT_ELT: return "MipsISD::VEXTRACT_SEXT_ELT"; case MipsISD::VEXTRACT_ZEXT_ELT: return "MipsISD::VEXTRACT_ZEXT_ELT"; case MipsISD::VNOR: return "MipsISD::VNOR"; @@ -402,18 +394,6 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM, setOperationAction(ISD::UDIV, MVT::i64, Expand); setOperationAction(ISD::UREM, MVT::i64, Expand); - if (!(Subtarget.hasDSP() && Subtarget.hasMips32r2())) { - setOperationAction(ISD::ADDC, MVT::i32, Expand); - setOperationAction(ISD::ADDE, MVT::i32, Expand); - } - - setOperationAction(ISD::ADDC, MVT::i64, Expand); - setOperationAction(ISD::ADDE, MVT::i64, Expand); - setOperationAction(ISD::SUBC, MVT::i32, Expand); - setOperationAction(ISD::SUBE, MVT::i32, Expand); - setOperationAction(ISD::SUBC, MVT::i64, Expand); - setOperationAction(ISD::SUBE, MVT::i64, Expand); - // Operations not directly supported by Mips. setOperationAction(ISD::BR_CC, MVT::f32, Expand); setOperationAction(ISD::BR_CC, MVT::f64, Expand); @@ -761,7 +741,7 @@ static SDValue performSELECTCombine(SDNode *N, SelectionDAG &DAG, return DAG.getNode(ISD::ADD, DL, SetCC.getValueType(), SetCC, True); } - // Couldn't optimize. + // Could not optimize. return SDValue(); } @@ -1301,76 +1281,76 @@ MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, default: llvm_unreachable("Unexpected instr type to insert"); case Mips::ATOMIC_LOAD_ADD_I8: - return emitAtomicBinaryPartword(MI, BB, 1, Mips::ADDu); + return emitAtomicBinaryPartword(MI, BB, 1); case Mips::ATOMIC_LOAD_ADD_I16: - return emitAtomicBinaryPartword(MI, BB, 2, Mips::ADDu); + return emitAtomicBinaryPartword(MI, BB, 2); case Mips::ATOMIC_LOAD_ADD_I32: - return emitAtomicBinary(MI, BB, 4, Mips::ADDu); + return emitAtomicBinary(MI, BB); case Mips::ATOMIC_LOAD_ADD_I64: - return emitAtomicBinary(MI, BB, 8, Mips::DADDu); + return emitAtomicBinary(MI, BB); case Mips::ATOMIC_LOAD_AND_I8: - return emitAtomicBinaryPartword(MI, BB, 1, Mips::AND); + return emitAtomicBinaryPartword(MI, BB, 1); case Mips::ATOMIC_LOAD_AND_I16: - return emitAtomicBinaryPartword(MI, BB, 2, Mips::AND); + return emitAtomicBinaryPartword(MI, BB, 2); case Mips::ATOMIC_LOAD_AND_I32: - return emitAtomicBinary(MI, BB, 4, Mips::AND); + return emitAtomicBinary(MI, BB); case Mips::ATOMIC_LOAD_AND_I64: - return emitAtomicBinary(MI, BB, 8, Mips::AND64); + return emitAtomicBinary(MI, BB); case Mips::ATOMIC_LOAD_OR_I8: - return emitAtomicBinaryPartword(MI, BB, 1, Mips::OR); + return emitAtomicBinaryPartword(MI, BB, 1); case Mips::ATOMIC_LOAD_OR_I16: - return emitAtomicBinaryPartword(MI, BB, 2, Mips::OR); + return emitAtomicBinaryPartword(MI, BB, 2); case Mips::ATOMIC_LOAD_OR_I32: - return emitAtomicBinary(MI, BB, 4, Mips::OR); + return emitAtomicBinary(MI, BB); case Mips::ATOMIC_LOAD_OR_I64: - return emitAtomicBinary(MI, BB, 8, Mips::OR64); + return emitAtomicBinary(MI, BB); case Mips::ATOMIC_LOAD_XOR_I8: - return emitAtomicBinaryPartword(MI, BB, 1, Mips::XOR); + return emitAtomicBinaryPartword(MI, BB, 1); case Mips::ATOMIC_LOAD_XOR_I16: - return emitAtomicBinaryPartword(MI, BB, 2, Mips::XOR); + return emitAtomicBinaryPartword(MI, BB, 2); case Mips::ATOMIC_LOAD_XOR_I32: - return emitAtomicBinary(MI, BB, 4, Mips::XOR); + return emitAtomicBinary(MI, BB); case Mips::ATOMIC_LOAD_XOR_I64: - return emitAtomicBinary(MI, BB, 8, Mips::XOR64); + return emitAtomicBinary(MI, BB); case Mips::ATOMIC_LOAD_NAND_I8: - return emitAtomicBinaryPartword(MI, BB, 1, 0, true); + return emitAtomicBinaryPartword(MI, BB, 1); case Mips::ATOMIC_LOAD_NAND_I16: - return emitAtomicBinaryPartword(MI, BB, 2, 0, true); + return emitAtomicBinaryPartword(MI, BB, 2); case Mips::ATOMIC_LOAD_NAND_I32: - return emitAtomicBinary(MI, BB, 4, 0, true); + return emitAtomicBinary(MI, BB); case Mips::ATOMIC_LOAD_NAND_I64: - return emitAtomicBinary(MI, BB, 8, 0, true); + return emitAtomicBinary(MI, BB); case Mips::ATOMIC_LOAD_SUB_I8: - return emitAtomicBinaryPartword(MI, BB, 1, Mips::SUBu); + return emitAtomicBinaryPartword(MI, BB, 1); case Mips::ATOMIC_LOAD_SUB_I16: - return emitAtomicBinaryPartword(MI, BB, 2, Mips::SUBu); + return emitAtomicBinaryPartword(MI, BB, 2); case Mips::ATOMIC_LOAD_SUB_I32: - return emitAtomicBinary(MI, BB, 4, Mips::SUBu); + return emitAtomicBinary(MI, BB); case Mips::ATOMIC_LOAD_SUB_I64: - return emitAtomicBinary(MI, BB, 8, Mips::DSUBu); + return emitAtomicBinary(MI, BB); case Mips::ATOMIC_SWAP_I8: - return emitAtomicBinaryPartword(MI, BB, 1, 0); + return emitAtomicBinaryPartword(MI, BB, 1); case Mips::ATOMIC_SWAP_I16: - return emitAtomicBinaryPartword(MI, BB, 2, 0); + return emitAtomicBinaryPartword(MI, BB, 2); case Mips::ATOMIC_SWAP_I32: - return emitAtomicBinary(MI, BB, 4, 0); + return emitAtomicBinary(MI, BB); case Mips::ATOMIC_SWAP_I64: - return emitAtomicBinary(MI, BB, 8, 0); + return emitAtomicBinary(MI, BB); case Mips::ATOMIC_CMP_SWAP_I8: return emitAtomicCmpSwapPartword(MI, BB, 1); case Mips::ATOMIC_CMP_SWAP_I16: return emitAtomicCmpSwapPartword(MI, BB, 2); case Mips::ATOMIC_CMP_SWAP_I32: - return emitAtomicCmpSwap(MI, BB, 4); + return emitAtomicCmpSwap(MI, BB); case Mips::ATOMIC_CMP_SWAP_I64: - return emitAtomicCmpSwap(MI, BB, 8); + return emitAtomicCmpSwap(MI, BB); case Mips::PseudoSDIV: case Mips::PseudoUDIV: case Mips::DIV: @@ -1419,99 +1399,121 @@ 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 { - assert((Size == 4 || Size == 8) && "Unsupported size for EmitAtomicBinary."); +MachineBasicBlock * +MipsTargetLowering::emitAtomicBinary(MachineInstr &MI, + MachineBasicBlock *BB) const { MachineFunction *MF = BB->getParent(); MachineRegisterInfo &RegInfo = MF->getRegInfo(); - const TargetRegisterClass *RC = getRegClassFor(MVT::getIntegerVT(Size * 8)); const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - const bool ArePtrs64bit = ABI.ArePtrs64bit(); DebugLoc DL = MI.getDebugLoc(); - unsigned LL, SC, AND, NOR, ZERO, BEQ; - - 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); - } - AND = Mips::AND; - NOR = Mips::NOR; - ZERO = Mips::ZERO; - BEQ = Mips::BEQ; - } else { - LL = Subtarget.hasMips64r6() ? Mips::LLD_R6 : Mips::LLD; - SC = Subtarget.hasMips64r6() ? Mips::SCD_R6 : Mips::SCD; - AND = Mips::AND64; - NOR = Mips::NOR64; - ZERO = Mips::ZERO_64; - BEQ = Mips::BEQ64; + unsigned AtomicOp; + switch (MI.getOpcode()) { + case Mips::ATOMIC_LOAD_ADD_I32: + AtomicOp = Mips::ATOMIC_LOAD_ADD_I32_POSTRA; + break; + case Mips::ATOMIC_LOAD_SUB_I32: + AtomicOp = Mips::ATOMIC_LOAD_SUB_I32_POSTRA; + break; + case Mips::ATOMIC_LOAD_AND_I32: + AtomicOp = Mips::ATOMIC_LOAD_AND_I32_POSTRA; + break; + case Mips::ATOMIC_LOAD_OR_I32: + AtomicOp = Mips::ATOMIC_LOAD_OR_I32_POSTRA; + break; + case Mips::ATOMIC_LOAD_XOR_I32: + AtomicOp = Mips::ATOMIC_LOAD_XOR_I32_POSTRA; + break; + case Mips::ATOMIC_LOAD_NAND_I32: + AtomicOp = Mips::ATOMIC_LOAD_NAND_I32_POSTRA; + break; + case Mips::ATOMIC_SWAP_I32: + AtomicOp = Mips::ATOMIC_SWAP_I32_POSTRA; + break; + case Mips::ATOMIC_LOAD_ADD_I64: + AtomicOp = Mips::ATOMIC_LOAD_ADD_I64_POSTRA; + break; + case Mips::ATOMIC_LOAD_SUB_I64: + AtomicOp = Mips::ATOMIC_LOAD_SUB_I64_POSTRA; + break; + case Mips::ATOMIC_LOAD_AND_I64: + AtomicOp = Mips::ATOMIC_LOAD_AND_I64_POSTRA; + break; + case Mips::ATOMIC_LOAD_OR_I64: + AtomicOp = Mips::ATOMIC_LOAD_OR_I64_POSTRA; + break; + case Mips::ATOMIC_LOAD_XOR_I64: + AtomicOp = Mips::ATOMIC_LOAD_XOR_I64_POSTRA; + break; + case Mips::ATOMIC_LOAD_NAND_I64: + AtomicOp = Mips::ATOMIC_LOAD_NAND_I64_POSTRA; + break; + case Mips::ATOMIC_SWAP_I64: + AtomicOp = Mips::ATOMIC_SWAP_I64_POSTRA; + break; + default: + llvm_unreachable("Unknown pseudo atomic for replacement!"); } unsigned OldVal = MI.getOperand(0).getReg(); unsigned Ptr = MI.getOperand(1).getReg(); unsigned Incr = MI.getOperand(2).getReg(); + unsigned Scratch = RegInfo.createVirtualRegister(RegInfo.getRegClass(OldVal)); + + MachineBasicBlock::iterator II(MI); + + // The scratch registers here with the EarlyClobber | Define | Implicit + // flags is used to persuade the register allocator and the machine + // verifier to accept the usage of this register. This has to be a real + // register which has an UNDEF value but is dead after the instruction which + // is unique among the registers chosen for the instruction. + + // The EarlyClobber flag has the semantic properties that the operand it is + // attached to is clobbered before the rest of the inputs are read. Hence it + // must be unique among the operands to the instruction. + // The Define flag is needed to coerce the machine verifier that an Undef + // value isn't a problem. + // The Dead flag is needed as the value in scratch isn't used by any other + // instruction. Kill isn't used as Dead is more precise. + // The implicit flag is here due to the interaction between the other flags + // and the machine verifier. + + // For correctness purpose, a new pseudo is introduced here. We need this + // new pseudo, so that FastRegisterAllocator does not see an ll/sc sequence + // that is spread over >1 basic blocks. A register allocator which + // introduces (or any codegen infact) a store, can violate the expectations + // of the hardware. + // + // An atomic read-modify-write sequence starts with a linked load + // instruction and ends with a store conditional instruction. The atomic + // read-modify-write sequence fails if any of the following conditions + // occur between the execution of ll and sc: + // * A coherent store is completed by another process or coherent I/O + // module into the block of synchronizable physical memory containing + // the word. The size and alignment of the block is + // implementation-dependent. + // * A coherent store is executed between an LL and SC sequence on the + // same processor to the block of synchornizable physical memory + // containing the word. + // - unsigned StoreVal = RegInfo.createVirtualRegister(RC); - unsigned AndRes = RegInfo.createVirtualRegister(RC); - unsigned Success = RegInfo.createVirtualRegister(RC); + unsigned PtrCopy = RegInfo.createVirtualRegister(RegInfo.getRegClass(Ptr)); + unsigned IncrCopy = RegInfo.createVirtualRegister(RegInfo.getRegClass(Incr)); - // insert new blocks after the current block - const BasicBlock *LLVM_BB = BB->getBasicBlock(); - MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); - MachineFunction::iterator It = ++BB->getIterator(); - MF->insert(It, loopMBB); - MF->insert(It, exitMBB); + BuildMI(*BB, II, DL, TII->get(Mips::COPY), IncrCopy).addReg(Incr); + BuildMI(*BB, II, DL, TII->get(Mips::COPY), PtrCopy).addReg(Ptr); - // Transfer the remainder of BB and its successor edges to exitMBB. - exitMBB->splice(exitMBB->begin(), BB, - std::next(MachineBasicBlock::iterator(MI)), BB->end()); - exitMBB->transferSuccessorsAndUpdatePHIs(BB); - - // thisMBB: - // ... - // fallthrough --> loopMBB - BB->addSuccessor(loopMBB); - loopMBB->addSuccessor(loopMBB); - loopMBB->addSuccessor(exitMBB); - - // loopMBB: - // ll oldval, 0(ptr) - // <binop> storeval, oldval, incr - // sc success, storeval, 0(ptr) - // beq success, $0, loopMBB - BB = loopMBB; - BuildMI(BB, DL, TII->get(LL), OldVal).addReg(Ptr).addImm(0); - if (Nand) { - // and andres, oldval, incr - // nor storeval, $0, andres - BuildMI(BB, DL, TII->get(AND), AndRes).addReg(OldVal).addReg(Incr); - BuildMI(BB, DL, TII->get(NOR), StoreVal).addReg(ZERO).addReg(AndRes); - } else if (BinOpcode) { - // <binop> storeval, oldval, incr - BuildMI(BB, DL, TII->get(BinOpcode), StoreVal).addReg(OldVal).addReg(Incr); - } else { - StoreVal = Incr; - } - 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); + BuildMI(*BB, II, DL, TII->get(AtomicOp)) + .addReg(OldVal, RegState::Define | RegState::EarlyClobber) + .addReg(PtrCopy) + .addReg(IncrCopy) + .addReg(Scratch, RegState::Define | RegState::EarlyClobber | + RegState::Implicit | RegState::Dead); - MI.eraseFromParent(); // The instruction is gone now. + MI.eraseFromParent(); - return exitMBB; + return BB; } MachineBasicBlock *MipsTargetLowering::emitSignExtendToI32InReg( @@ -1545,8 +1547,7 @@ MachineBasicBlock *MipsTargetLowering::emitSignExtendToI32InReg( } MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword( - MachineInstr &MI, MachineBasicBlock *BB, unsigned Size, unsigned BinOpcode, - bool Nand) const { + MachineInstr &MI, MachineBasicBlock *BB, unsigned Size) const { assert((Size == 1 || Size == 2) && "Unsupported size for EmitAtomicBinaryPartial."); @@ -1567,39 +1568,66 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword( 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(RCp); unsigned PtrLSB2 = RegInfo.createVirtualRegister(RC); unsigned MaskUpper = RegInfo.createVirtualRegister(RC); - unsigned AndRes = RegInfo.createVirtualRegister(RC); - unsigned BinOpRes = RegInfo.createVirtualRegister(RC); - unsigned MaskedOldVal0 = RegInfo.createVirtualRegister(RC); - unsigned StoreVal = RegInfo.createVirtualRegister(RC); - unsigned MaskedOldVal1 = 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); + unsigned Scratch = RegInfo.createVirtualRegister(RC); + unsigned Scratch2 = RegInfo.createVirtualRegister(RC); + unsigned Scratch3 = RegInfo.createVirtualRegister(RC); + + unsigned AtomicOp = 0; + switch (MI.getOpcode()) { + case Mips::ATOMIC_LOAD_NAND_I8: + AtomicOp = Mips::ATOMIC_LOAD_NAND_I8_POSTRA; + break; + case Mips::ATOMIC_LOAD_NAND_I16: + AtomicOp = Mips::ATOMIC_LOAD_NAND_I16_POSTRA; + break; + case Mips::ATOMIC_SWAP_I8: + AtomicOp = Mips::ATOMIC_SWAP_I8_POSTRA; + break; + case Mips::ATOMIC_SWAP_I16: + AtomicOp = Mips::ATOMIC_SWAP_I16_POSTRA; + break; + case Mips::ATOMIC_LOAD_ADD_I8: + AtomicOp = Mips::ATOMIC_LOAD_ADD_I8_POSTRA; + break; + case Mips::ATOMIC_LOAD_ADD_I16: + AtomicOp = Mips::ATOMIC_LOAD_ADD_I16_POSTRA; + break; + case Mips::ATOMIC_LOAD_SUB_I8: + AtomicOp = Mips::ATOMIC_LOAD_SUB_I8_POSTRA; + break; + case Mips::ATOMIC_LOAD_SUB_I16: + AtomicOp = Mips::ATOMIC_LOAD_SUB_I16_POSTRA; + break; + case Mips::ATOMIC_LOAD_AND_I8: + AtomicOp = Mips::ATOMIC_LOAD_AND_I8_POSTRA; + break; + case Mips::ATOMIC_LOAD_AND_I16: + AtomicOp = Mips::ATOMIC_LOAD_AND_I16_POSTRA; + break; + case Mips::ATOMIC_LOAD_OR_I8: + AtomicOp = Mips::ATOMIC_LOAD_OR_I8_POSTRA; + break; + case Mips::ATOMIC_LOAD_OR_I16: + AtomicOp = Mips::ATOMIC_LOAD_OR_I16_POSTRA; + break; + case Mips::ATOMIC_LOAD_XOR_I8: + AtomicOp = Mips::ATOMIC_LOAD_XOR_I8_POSTRA; + break; + case Mips::ATOMIC_LOAD_XOR_I16: + AtomicOp = Mips::ATOMIC_LOAD_XOR_I16_POSTRA; + break; + default: + llvm_unreachable("Unknown subword atomic pseudo for expansion!"); } // insert new blocks after the current block const BasicBlock *LLVM_BB = BB->getBasicBlock(); - MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(LLVM_BB); MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); MachineFunction::iterator It = ++BB->getIterator(); - MF->insert(It, loopMBB); - MF->insert(It, sinkMBB); MF->insert(It, exitMBB); // Transfer the remainder of BB and its successor edges to exitMBB. @@ -1607,10 +1635,7 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword( std::next(MachineBasicBlock::iterator(MI)), BB->end()); exitMBB->transferSuccessorsAndUpdatePHIs(BB); - BB->addSuccessor(loopMBB); - loopMBB->addSuccessor(loopMBB); - loopMBB->addSuccessor(sinkMBB); - sinkMBB->addSuccessor(exitMBB); + BB->addSuccessor(exitMBB, BranchProbability::getOne()); // thisMBB: // addiu masklsb2,$0,-4 # 0xfffffffc @@ -1644,159 +1669,92 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword( BuildMI(BB, DL, TII->get(Mips::NOR), Mask2).addReg(Mips::ZERO).addReg(Mask); BuildMI(BB, DL, TII->get(Mips::SLLV), Incr2).addReg(Incr).addReg(ShiftAmt); - // atomic.load.binop - // loopMBB: - // ll oldval,0(alignedaddr) - // binop binopres,oldval,incr2 - // and newval,binopres,mask - // and maskedoldval0,oldval,mask2 - // or storeval,maskedoldval0,newval - // sc success,storeval,0(alignedaddr) - // beq success,$0,loopMBB - - // atomic.swap - // loopMBB: - // ll oldval,0(alignedaddr) - // and newval,incr2,mask - // and maskedoldval0,oldval,mask2 - // or storeval,maskedoldval0,newval - // sc success,storeval,0(alignedaddr) - // beq success,$0,loopMBB - - BB = loopMBB; - BuildMI(BB, DL, TII->get(LL), OldVal).addReg(AlignedAddr).addImm(0); - if (Nand) { - // and andres, oldval, incr2 - // nor binopres, $0, andres - // and newval, binopres, mask - BuildMI(BB, DL, TII->get(Mips::AND), AndRes).addReg(OldVal).addReg(Incr2); - BuildMI(BB, DL, TII->get(Mips::NOR), BinOpRes) - .addReg(Mips::ZERO).addReg(AndRes); - BuildMI(BB, DL, TII->get(Mips::AND), NewVal).addReg(BinOpRes).addReg(Mask); - } else if (BinOpcode) { - // <binop> binopres, oldval, incr2 - // and newval, binopres, mask - BuildMI(BB, DL, TII->get(BinOpcode), BinOpRes).addReg(OldVal).addReg(Incr2); - BuildMI(BB, DL, TII->get(Mips::AND), NewVal).addReg(BinOpRes).addReg(Mask); - } else { // atomic.swap - // and newval, incr2, mask - BuildMI(BB, DL, TII->get(Mips::AND), NewVal).addReg(Incr2).addReg(Mask); - } - - BuildMI(BB, DL, TII->get(Mips::AND), MaskedOldVal0) - .addReg(OldVal).addReg(Mask2); - BuildMI(BB, DL, TII->get(Mips::OR), StoreVal) - .addReg(MaskedOldVal0).addReg(NewVal); - BuildMI(BB, DL, TII->get(SC), Success) - .addReg(StoreVal).addReg(AlignedAddr).addImm(0); - BuildMI(BB, DL, TII->get(Mips::BEQ)) - .addReg(Success).addReg(Mips::ZERO).addMBB(loopMBB); - // sinkMBB: - // and maskedoldval1,oldval,mask - // srl srlres,maskedoldval1,shiftamt - // sign_extend dest,srlres - BB = sinkMBB; - - BuildMI(BB, DL, TII->get(Mips::AND), MaskedOldVal1) - .addReg(OldVal).addReg(Mask); - BuildMI(BB, DL, TII->get(Mips::SRLV), SrlRes) - .addReg(MaskedOldVal1).addReg(ShiftAmt); - BB = emitSignExtendToI32InReg(MI, BB, Size, Dest, SrlRes); + // The purposes of the flags on the scratch registers is explained in + // emitAtomicBinary. In summary, we need a scratch register which is going to + // be undef, that is unique among registers chosen for the instruction. + + BuildMI(BB, DL, TII->get(AtomicOp)) + .addReg(Dest, RegState::Define | RegState::EarlyClobber) + .addReg(AlignedAddr) + .addReg(Incr2) + .addReg(Mask) + .addReg(Mask2) + .addReg(ShiftAmt) + .addReg(Scratch, RegState::EarlyClobber | RegState::Define | + RegState::Dead | RegState::Implicit) + .addReg(Scratch2, RegState::EarlyClobber | RegState::Define | + RegState::Dead | RegState::Implicit) + .addReg(Scratch3, RegState::EarlyClobber | RegState::Define | + RegState::Dead | RegState::Implicit); MI.eraseFromParent(); // The instruction is gone now. return exitMBB; } -MachineBasicBlock *MipsTargetLowering::emitAtomicCmpSwap(MachineInstr &MI, - MachineBasicBlock *BB, - unsigned Size) const { - assert((Size == 4 || Size == 8) && "Unsupported size for EmitAtomicCmpSwap."); +// Lower atomic compare and swap to a pseudo instruction, taking care to +// define a scratch register for the pseudo instruction's expansion. The +// instruction is expanded after the register allocator as to prevent +// the insertion of stores between the linked load and the store conditional. + +MachineBasicBlock * +MipsTargetLowering::emitAtomicCmpSwap(MachineInstr &MI, + MachineBasicBlock *BB) const { + + assert((MI.getOpcode() == Mips::ATOMIC_CMP_SWAP_I32 || + MI.getOpcode() == Mips::ATOMIC_CMP_SWAP_I64) && + "Unsupported atomic psseudo for EmitAtomicCmpSwap."); + + const unsigned Size = MI.getOpcode() == Mips::ATOMIC_CMP_SWAP_I32 ? 4 : 8; MachineFunction *MF = BB->getParent(); - MachineRegisterInfo &RegInfo = MF->getRegInfo(); + MachineRegisterInfo &MRI = MF->getRegInfo(); const TargetRegisterClass *RC = getRegClassFor(MVT::getIntegerVT(Size * 8)); const TargetInstrInfo *TII = Subtarget.getInstrInfo(); - 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() - ? (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; - } else { - LL = Subtarget.hasMips64r6() ? Mips::LLD_R6 : Mips::LLD; - SC = Subtarget.hasMips64r6() ? Mips::SCD_R6 : Mips::SCD; - ZERO = Mips::ZERO_64; - BNE = Mips::BNE64; - BEQ = Mips::BEQ64; - } + unsigned AtomicOp = MI.getOpcode() == Mips::ATOMIC_CMP_SWAP_I32 + ? Mips::ATOMIC_CMP_SWAP_I32_POSTRA + : Mips::ATOMIC_CMP_SWAP_I64_POSTRA; 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); + unsigned Scratch = MRI.createVirtualRegister(RC); + MachineBasicBlock::iterator II(MI); - // insert new blocks after the current block - const BasicBlock *LLVM_BB = BB->getBasicBlock(); - MachineBasicBlock *loop1MBB = MF->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *loop2MBB = MF->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); - MachineFunction::iterator It = ++BB->getIterator(); - MF->insert(It, loop1MBB); - MF->insert(It, loop2MBB); - MF->insert(It, exitMBB); + // We need to create copies of the various registers and kill them at the + // atomic pseudo. If the copies are not made, when the atomic is expanded + // after fast register allocation, the spills will end up outside of the + // blocks that their values are defined in, causing livein errors. - // Transfer the remainder of BB and its successor edges to exitMBB. - exitMBB->splice(exitMBB->begin(), BB, - std::next(MachineBasicBlock::iterator(MI)), BB->end()); - exitMBB->transferSuccessorsAndUpdatePHIs(BB); + unsigned DestCopy = MRI.createVirtualRegister(MRI.getRegClass(Dest)); + unsigned PtrCopy = MRI.createVirtualRegister(MRI.getRegClass(Ptr)); + unsigned OldValCopy = MRI.createVirtualRegister(MRI.getRegClass(OldVal)); + unsigned NewValCopy = MRI.createVirtualRegister(MRI.getRegClass(NewVal)); - // thisMBB: - // ... - // fallthrough --> loop1MBB - BB->addSuccessor(loop1MBB); - loop1MBB->addSuccessor(exitMBB); - loop1MBB->addSuccessor(loop2MBB); - loop2MBB->addSuccessor(loop1MBB); - loop2MBB->addSuccessor(exitMBB); - - // loop1MBB: - // ll dest, 0(ptr) - // bne dest, oldval, exitMBB - BB = loop1MBB; - BuildMI(BB, DL, TII->get(LL), Dest).addReg(Ptr).addImm(0); - BuildMI(BB, DL, TII->get(BNE)) - .addReg(Dest).addReg(OldVal).addMBB(exitMBB); - - // loop2MBB: - // sc success, newval, 0(ptr) - // beq success, $0, loop1MBB - BB = loop2MBB; - BuildMI(BB, DL, TII->get(SC), Success) - .addReg(NewVal).addReg(Ptr).addImm(0); - BuildMI(BB, DL, TII->get(BEQ)) - .addReg(Success).addReg(ZERO).addMBB(loop1MBB); + BuildMI(*BB, II, DL, TII->get(Mips::COPY), DestCopy).addReg(Dest); + BuildMI(*BB, II, DL, TII->get(Mips::COPY), PtrCopy).addReg(Ptr); + BuildMI(*BB, II, DL, TII->get(Mips::COPY), OldValCopy).addReg(OldVal); + BuildMI(*BB, II, DL, TII->get(Mips::COPY), NewValCopy).addReg(NewVal); + + // The purposes of the flags on the scratch registers is explained in + // emitAtomicBinary. In summary, we need a scratch register which is going to + // be undef, that is unique among registers chosen for the instruction. + + BuildMI(*BB, II, DL, TII->get(AtomicOp)) + .addReg(Dest, RegState::Define | RegState::EarlyClobber) + .addReg(PtrCopy, RegState::Kill) + .addReg(OldValCopy, RegState::Kill) + .addReg(NewValCopy, RegState::Kill) + .addReg(Scratch, RegState::EarlyClobber | RegState::Define | + RegState::Dead | RegState::Implicit); MI.eraseFromParent(); // The instruction is gone now. - return exitMBB; + return BB; } MachineBasicBlock *MipsTargetLowering::emitAtomicCmpSwapPartword( @@ -1823,40 +1781,33 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicCmpSwapPartword( unsigned Mask = RegInfo.createVirtualRegister(RC); unsigned Mask2 = RegInfo.createVirtualRegister(RC); unsigned ShiftedCmpVal = RegInfo.createVirtualRegister(RC); - unsigned OldVal = RegInfo.createVirtualRegister(RC); - unsigned MaskedOldVal0 = RegInfo.createVirtualRegister(RC); unsigned ShiftedNewVal = RegInfo.createVirtualRegister(RC); unsigned MaskLSB2 = RegInfo.createVirtualRegister(RCp); unsigned PtrLSB2 = RegInfo.createVirtualRegister(RC); unsigned MaskUpper = RegInfo.createVirtualRegister(RC); unsigned MaskedCmpVal = RegInfo.createVirtualRegister(RC); unsigned MaskedNewVal = RegInfo.createVirtualRegister(RC); - unsigned MaskedOldVal1 = RegInfo.createVirtualRegister(RC); - 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); - } + unsigned AtomicOp = MI.getOpcode() == Mips::ATOMIC_CMP_SWAP_I8 + ? Mips::ATOMIC_CMP_SWAP_I8_POSTRA + : Mips::ATOMIC_CMP_SWAP_I16_POSTRA; + + // The scratch registers here with the EarlyClobber | Define | Dead | Implicit + // flags are used to coerce the register allocator and the machine verifier to + // accept the usage of these registers. + // The EarlyClobber flag has the semantic properties that the operand it is + // attached to is clobbered before the rest of the inputs are read. Hence it + // must be unique among the operands to the instruction. + // The Define flag is needed to coerce the machine verifier that an Undef + // value isn't a problem. + // The Dead flag is needed as the value in scratch isn't used by any other + // instruction. Kill isn't used as Dead is more precise. + unsigned Scratch = RegInfo.createVirtualRegister(RC); + unsigned Scratch2 = RegInfo.createVirtualRegister(RC); // insert new blocks after the current block const BasicBlock *LLVM_BB = BB->getBasicBlock(); - MachineBasicBlock *loop1MBB = MF->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *loop2MBB = MF->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *sinkMBB = MF->CreateMachineBasicBlock(LLVM_BB); MachineBasicBlock *exitMBB = MF->CreateMachineBasicBlock(LLVM_BB); MachineFunction::iterator It = ++BB->getIterator(); - MF->insert(It, loop1MBB); - MF->insert(It, loop2MBB); - MF->insert(It, sinkMBB); MF->insert(It, exitMBB); // Transfer the remainder of BB and its successor edges to exitMBB. @@ -1864,14 +1815,8 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicCmpSwapPartword( std::next(MachineBasicBlock::iterator(MI)), BB->end()); exitMBB->transferSuccessorsAndUpdatePHIs(BB); - BB->addSuccessor(loop1MBB); - loop1MBB->addSuccessor(sinkMBB); - loop1MBB->addSuccessor(loop2MBB); - loop2MBB->addSuccessor(loop1MBB); - loop2MBB->addSuccessor(sinkMBB); - sinkMBB->addSuccessor(exitMBB); + BB->addSuccessor(exitMBB, BranchProbability::getOne()); - // FIXME: computation of newval2 can be moved to loop2MBB. // thisMBB: // addiu masklsb2,$0,-4 # 0xfffffffc // and alignedaddr,ptr,masklsb2 @@ -1914,40 +1859,22 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicCmpSwapPartword( BuildMI(BB, DL, TII->get(Mips::SLLV), ShiftedNewVal) .addReg(MaskedNewVal).addReg(ShiftAmt); - // loop1MBB: - // ll oldval,0(alginedaddr) - // and maskedoldval0,oldval,mask - // bne maskedoldval0,shiftedcmpval,sinkMBB - BB = loop1MBB; - BuildMI(BB, DL, TII->get(LL), OldVal).addReg(AlignedAddr).addImm(0); - BuildMI(BB, DL, TII->get(Mips::AND), MaskedOldVal0) - .addReg(OldVal).addReg(Mask); - BuildMI(BB, DL, TII->get(Mips::BNE)) - .addReg(MaskedOldVal0).addReg(ShiftedCmpVal).addMBB(sinkMBB); - - // loop2MBB: - // and maskedoldval1,oldval,mask2 - // or storeval,maskedoldval1,shiftednewval - // sc success,storeval,0(alignedaddr) - // beq success,$0,loop1MBB - BB = loop2MBB; - BuildMI(BB, DL, TII->get(Mips::AND), MaskedOldVal1) - .addReg(OldVal).addReg(Mask2); - BuildMI(BB, DL, TII->get(Mips::OR), StoreVal) - .addReg(MaskedOldVal1).addReg(ShiftedNewVal); - BuildMI(BB, DL, TII->get(SC), Success) - .addReg(StoreVal).addReg(AlignedAddr).addImm(0); - BuildMI(BB, DL, TII->get(Mips::BEQ)) - .addReg(Success).addReg(Mips::ZERO).addMBB(loop1MBB); - - // sinkMBB: - // srl srlres,maskedoldval0,shiftamt - // sign_extend dest,srlres - BB = sinkMBB; - - BuildMI(BB, DL, TII->get(Mips::SRLV), SrlRes) - .addReg(MaskedOldVal0).addReg(ShiftAmt); - BB = emitSignExtendToI32InReg(MI, BB, Size, Dest, SrlRes); + // The purposes of the flags on the scratch registers are explained in + // emitAtomicBinary. In summary, we need a scratch register which is going to + // be undef, that is unique among the register chosen for the instruction. + + BuildMI(BB, DL, TII->get(AtomicOp)) + .addReg(Dest, RegState::Define | RegState::EarlyClobber) + .addReg(AlignedAddr) + .addReg(Mask) + .addReg(ShiftedCmpVal) + .addReg(Mask2) + .addReg(ShiftedNewVal) + .addReg(ShiftAmt) + .addReg(Scratch, RegState::EarlyClobber | RegState::Define | + RegState::Dead | RegState::Implicit) + .addReg(Scratch2, RegState::EarlyClobber | RegState::Define | + RegState::Dead | RegState::Implicit); MI.eraseFromParent(); // The instruction is gone now. @@ -2073,7 +2000,7 @@ lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const // Local Exec TLS Model. GlobalAddressSDNode *GA = cast<GlobalAddressSDNode>(Op); - if (DAG.getTarget().Options.EmulatedTLS) + if (DAG.getTarget().useEmulatedTLS()) return LowerToTLSEmulatedModel(GA, DAG); SDLoc DL(GA); @@ -2114,7 +2041,7 @@ lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const SDValue TGAHi = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, MipsII::MO_DTPREL_HI); - SDValue Hi = DAG.getNode(MipsISD::Hi, DL, PtrVT, TGAHi); + SDValue Hi = DAG.getNode(MipsISD::TlsHi, DL, PtrVT, TGAHi); SDValue TGALo = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, MipsII::MO_DTPREL_LO); SDValue Lo = DAG.getNode(MipsISD::Lo, DL, PtrVT, TGALo); @@ -2138,7 +2065,7 @@ lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const MipsII::MO_TPREL_HI); SDValue TGALo = DAG.getTargetGlobalAddress(GV, DL, PtrVT, 0, MipsII::MO_TPREL_LO); - SDValue Hi = DAG.getNode(MipsISD::Hi, DL, PtrVT, TGAHi); + SDValue Hi = DAG.getNode(MipsISD::TlsHi, DL, PtrVT, TGAHi); SDValue Lo = DAG.getNode(MipsISD::Lo, DL, PtrVT, TGALo); Offset = DAG.getNode(ISD::ADD, DL, PtrVT, Hi, Lo); } @@ -2837,6 +2764,13 @@ static bool CC_MipsO32(unsigned ValNo, MVT ValVT, MVT LocVT, #include "MipsGenCallingConv.inc" + CCAssignFn *MipsTargetLowering::CCAssignFnForCall() const{ + return CC_Mips; + } + + CCAssignFn *MipsTargetLowering::CCAssignFnForReturn() const{ + return RetCC_Mips; + } //===----------------------------------------------------------------------===// // Call Calling Convention Implementation //===----------------------------------------------------------------------===// @@ -2953,12 +2887,44 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, CallConv, IsVarArg, DAG.getMachineFunction(), ArgLocs, *DAG.getContext(), MipsCCState::getSpecialCallingConvForCallee(Callee.getNode(), Subtarget)); + const ExternalSymbolSDNode *ES = + dyn_cast_or_null<const ExternalSymbolSDNode>(Callee.getNode()); + + // There is one case where CALLSEQ_START..CALLSEQ_END can be nested, which + // is during the lowering of a call with a byval argument which produces + // a call to memcpy. For the O32 case, this causes the caller to allocate + // stack space for the reserved argument area for the callee, then recursively + // again for the memcpy call. In the NEWABI case, this doesn't occur as those + // ABIs mandate that the callee allocates the reserved argument area. We do + // still produce nested CALLSEQ_START..CALLSEQ_END with zero space though. + // + // If the callee has a byval argument and memcpy is used, we are mandated + // to already have produced a reserved argument area for the callee for O32. + // Therefore, the reserved argument area can be reused for both calls. + // + // Other cases of calling memcpy cannot have a chain with a CALLSEQ_START + // present, as we have yet to hook that node onto the chain. + // + // Hence, the CALLSEQ_START and CALLSEQ_END nodes can be eliminated in this + // case. GCC does a similar trick, in that wherever possible, it calculates + // the maximum out going argument area (including the reserved area), and + // preallocates the stack space on entrance to the caller. + // + // FIXME: We should do the same for efficency and space. + + // Note: The check on the calling convention below must match + // MipsABIInfo::GetCalleeAllocdArgSizeInBytes(). + bool MemcpyInByVal = ES && + StringRef(ES->getSymbol()) == StringRef("memcpy") && + CallConv != CallingConv::Fast && + Chain.getOpcode() == ISD::CALLSEQ_START; + // Allocate the reserved argument area. It seems strange to do this from the // caller side but removing it breaks the frame size calculation. - CCInfo.AllocateStack(ABI.GetCalleeAllocdArgSizeInBytes(CallConv), 1); + unsigned ReservedArgArea = + MemcpyInByVal ? 0 : ABI.GetCalleeAllocdArgSizeInBytes(CallConv); + CCInfo.AllocateStack(ReservedArgArea, 1); - const ExternalSymbolSDNode *ES = - dyn_cast_or_null<const ExternalSymbolSDNode>(Callee.getNode()); CCInfo.AnalyzeCallOperands(Outs, CC_Mips, CLI.getArgs(), ES ? ES->getSymbol() : nullptr); @@ -2993,7 +2959,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, NextStackOffset = alignTo(NextStackOffset, StackAlignment); SDValue NextStackOffsetVal = DAG.getIntPtrConstant(NextStackOffset, DL, true); - if (!IsTailCall) + if (!(IsTailCall || MemcpyInByVal)) Chain = DAG.getCALLSEQ_START(Chain, NextStackOffset, 0, DL); SDValue StackPtr = @@ -3201,10 +3167,13 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, Chain = DAG.getNode(MipsISD::JmpLink, DL, NodeTys, Ops); SDValue InFlag = Chain.getValue(1); - // Create the CALLSEQ_END node. - Chain = DAG.getCALLSEQ_END(Chain, NextStackOffsetVal, - DAG.getIntPtrConstant(0, DL, true), InFlag, DL); - InFlag = Chain.getValue(1); + // Create the CALLSEQ_END node in the case of where it is not a call to + // memcpy. + if (!(MemcpyInByVal)) { + Chain = DAG.getCALLSEQ_END(Chain, NextStackOffsetVal, + DAG.getIntPtrConstant(0, DL, true), InFlag, DL); + InFlag = Chain.getValue(1); + } // Handle result values, copying them out of physregs into vregs that we // return. @@ -3507,10 +3476,9 @@ MipsTargetLowering::CanLowerReturn(CallingConv::ID CallConv, bool MipsTargetLowering::shouldSignExtendTypeInLibCall(EVT Type, bool IsSigned) const { - if (Subtarget.hasMips3() && Subtarget.useSoftFloat()) { - if (Type == MVT::i32) + if ((ABI.IsN32() || ABI.IsN64()) && Type == MVT::i32) return true; - } + return IsSigned; } @@ -3746,6 +3714,13 @@ static std::pair<bool, bool> parsePhysicalReg(StringRef C, StringRef &Prefix, true); } +EVT MipsTargetLowering::getTypeForExtReturn(LLVMContext &Context, EVT VT, + ISD::NodeType) const { + bool Cond = !Subtarget.isABI_O32() && VT.getSizeInBits() == 32; + EVT MinVT = getRegisterType(Context, Cond ? MVT::i64 : MVT::i32); + return VT.bitsLT(MinVT) ? MinVT : VT; +} + std::pair<unsigned, const TargetRegisterClass *> MipsTargetLowering:: parseRegForInlineAsmConstraint(StringRef C, MVT VT) const { const TargetRegisterInfo *TRI = @@ -3863,13 +3838,17 @@ MipsTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, case 'c': // register suitable for indirect jump if (VT == MVT::i32) return std::make_pair((unsigned)Mips::T9, &Mips::GPR32RegClass); - assert(VT == MVT::i64 && "Unexpected type."); - return std::make_pair((unsigned)Mips::T9_64, &Mips::GPR64RegClass); - case 'l': // register suitable for indirect jump - if (VT == MVT::i32) + if (VT == MVT::i64) + return std::make_pair((unsigned)Mips::T9_64, &Mips::GPR64RegClass); + // This will generate an error message + return std::make_pair(0U, nullptr); + case 'l': // use the `lo` register to store values + // that are no bigger than a word + if (VT == MVT::i32 || VT == MVT::i16 || VT == MVT::i8) return std::make_pair((unsigned)Mips::LO0, &Mips::LO32RegClass); return std::make_pair((unsigned)Mips::LO0_64, &Mips::LO64RegClass); - case 'x': // register suitable for indirect jump + case 'x': // use the concatenated `hi` and `lo` registers + // to store doubleword values // Fixme: Not triggering the use of both hi and low // This will generate an error message return std::make_pair(0U, nullptr); @@ -4064,7 +4043,12 @@ void MipsTargetLowering::copyByValRegs( // Create frame object. EVT PtrTy = getPointerTy(DAG.getDataLayout()); - int FI = MFI.CreateFixedObject(FrameObjSize, FrameObjOffset, true); + // Make the fixed object stored to mutable so that the load instructions + // referencing it have their memory dependencies added. + // Set the frame object as isAliased which clears the underlying objects + // vector in ScheduleDAGInstrs::buildSchedGraph() resulting in addition of all + // stores as dependencies for loads referencing this fixed object. + int FI = MFI.CreateFixedObject(FrameObjSize, FrameObjOffset, false, true); SDValue FIN = DAG.getFrameIndex(FI, PtrTy); InVals.push_back(FIN); diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h index ce4f0376ca9b..b58d92c370d8 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -19,9 +19,9 @@ #include "MCTargetDesc/MipsBaseInfo.h" #include "MCTargetDesc/MipsMCTargetDesc.h" #include "Mips.h" +#include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/ISDOpcodes.h" #include "llvm/CodeGen/MachineMemOperand.h" -#include "llvm/CodeGen/MachineValueType.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/CodeGen/TargetLowering.h" @@ -29,6 +29,7 @@ #include "llvm/IR/CallingConv.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/Type.h" +#include "llvm/Support/MachineValueType.h" #include "llvm/Target/TargetMachine.h" #include <algorithm> #include <cassert> @@ -83,12 +84,18 @@ class TargetRegisterClass; // Get the High 16 bits from a 32 bit immediate for accessing the GOT. GotHi, + // Get the High 16 bits from a 32-bit immediate for accessing TLS. + TlsHi, + // Handle gp_rel (small data/bss sections) relocation. GPRel, // Thread Pointer ThreadPointer, + // Vector Floating Point Multiply and Subtract + FMS, + // Floating Point Branch Conditional FPBrcond, @@ -217,12 +224,6 @@ class TargetRegisterClass; VCLT_S, VCLT_U, - // Element-wise vector max/min. - VSMAX, - VSMIN, - VUMAX, - VUMIN, - // Vector Shuffle with mask as an operand VSHF, // Generic shuffle SHF, // 4-element set shuffle. @@ -279,15 +280,14 @@ class TargetRegisterClass; return MVT::i32; } + EVT getTypeForExtReturn(LLVMContext &Context, EVT VT, + ISD::NodeType) const override; + bool isCheapToSpeculateCttz() const override; bool isCheapToSpeculateCtlz() const override; /// Return the register type for a given MVT, ensuring vectors are treated /// as a series of gpr sized integers. - MVT getRegisterTypeForCallingConv(MVT VT) const override; - - /// Return the register type for a given MVT, ensuring vectors are treated - /// as a series of gpr sized integers. MVT getRegisterTypeForCallingConv(LLVMContext &Context, EVT VT) const override; @@ -371,6 +371,10 @@ class TargetRegisterClass; return getTargetMachine().isPositionIndependent(); } + CCAssignFn *CCAssignFnForCall() const; + + CCAssignFn *CCAssignFnForReturn() const; + protected: SDValue getGlobalReg(SelectionDAG &DAG, EVT Ty) const; @@ -681,17 +685,13 @@ class TargetRegisterClass; unsigned Size, unsigned DstReg, unsigned SrcRec) const; - MachineBasicBlock *emitAtomicBinary(MachineInstr &MI, MachineBasicBlock *BB, - unsigned Size, unsigned BinOpcode, - bool Nand = false) const; + MachineBasicBlock *emitAtomicBinary(MachineInstr &MI, + MachineBasicBlock *BB) const; MachineBasicBlock *emitAtomicBinaryPartword(MachineInstr &MI, MachineBasicBlock *BB, - unsigned Size, - unsigned BinOpcode, - bool Nand = false) const; + unsigned Size) const; MachineBasicBlock *emitAtomicCmpSwap(MachineInstr &MI, - MachineBasicBlock *BB, - unsigned Size) const; + MachineBasicBlock *BB) const; MachineBasicBlock *emitAtomicCmpSwapPartword(MachineInstr &MI, MachineBasicBlock *BB, unsigned Size) const; diff --git a/lib/Target/Mips/MipsInstrFPU.td b/lib/Target/Mips/MipsInstrFPU.td index c81739115373..dd30e20a743c 100644 --- a/lib/Target/Mips/MipsInstrFPU.td +++ b/lib/Target/Mips/MipsInstrFPU.td @@ -149,12 +149,16 @@ multiclass ROUND_M<string opstr, InstrItinClass Itin> { class MFC1_FT<string opstr, RegisterOperand DstRC, RegisterOperand SrcRC, InstrItinClass Itin, SDPatternOperator OpNode= null_frag> : InstSE<(outs DstRC:$rt), (ins SrcRC:$fs), !strconcat(opstr, "\t$rt, $fs"), - [(set DstRC:$rt, (OpNode SrcRC:$fs))], Itin, FrmFR, opstr>, HARDFLOAT; + [(set DstRC:$rt, (OpNode SrcRC:$fs))], Itin, FrmFR, opstr>, HARDFLOAT { + let isMoveReg = 1; +} class MTC1_FT<string opstr, RegisterOperand DstRC, RegisterOperand SrcRC, InstrItinClass Itin, SDPatternOperator OpNode= null_frag> : InstSE<(outs DstRC:$fs), (ins SrcRC:$rt), !strconcat(opstr, "\t$rt, $fs"), - [(set DstRC:$fs, (OpNode SrcRC:$rt))], Itin, FrmFR, opstr>, HARDFLOAT; + [(set DstRC:$fs, (OpNode SrcRC:$rt))], Itin, FrmFR, opstr>, HARDFLOAT { + let isMoveReg = 1; +} class MTC1_64_FT<string opstr, RegisterOperand DstRC, RegisterOperand SrcRC, InstrItinClass Itin> : @@ -349,22 +353,24 @@ defm D64 : C_COND_M<"d", FGR64Opnd, 17, II_C_CC_D>, ISA_MIPS1_NOT_32R6_64R6, //===----------------------------------------------------------------------===// // Floating Point Instructions //===----------------------------------------------------------------------===// -def ROUND_W_S : MMRel, StdMMR6Rel, ABSS_FT<"round.w.s", FGR32Opnd, FGR32Opnd, II_ROUND>, - ABSS_FM<0xc, 16>, ISA_MIPS2; -defm ROUND_W : ROUND_M<"round.w.d", II_ROUND>, ABSS_FM<0xc, 17>, ISA_MIPS2; -def TRUNC_W_S : MMRel, StdMMR6Rel, ABSS_FT<"trunc.w.s", FGR32Opnd, FGR32Opnd, II_TRUNC>, - ABSS_FM<0xd, 16>, ISA_MIPS2; -def CEIL_W_S : MMRel, StdMMR6Rel, ABSS_FT<"ceil.w.s", FGR32Opnd, FGR32Opnd, II_CEIL>, - ABSS_FM<0xe, 16>, ISA_MIPS2; -def FLOOR_W_S : MMRel, StdMMR6Rel, ABSS_FT<"floor.w.s", FGR32Opnd, FGR32Opnd, II_FLOOR>, - ABSS_FM<0xf, 16>, ISA_MIPS2; -def CVT_W_S : MMRel, ABSS_FT<"cvt.w.s", FGR32Opnd, FGR32Opnd, II_CVT>, - ABSS_FM<0x24, 16>; - -defm TRUNC_W : ROUND_M<"trunc.w.d", II_TRUNC>, ABSS_FM<0xd, 17>, ISA_MIPS2; -defm CEIL_W : ROUND_M<"ceil.w.d", II_CEIL>, ABSS_FM<0xe, 17>, ISA_MIPS2; -defm FLOOR_W : ROUND_M<"floor.w.d", II_FLOOR>, ABSS_FM<0xf, 17>, ISA_MIPS2; -defm CVT_W : ROUND_M<"cvt.w.d", II_CVT>, ABSS_FM<0x24, 17>; +let AdditionalPredicates = [NotInMicroMips] in { + def ROUND_W_S : MMRel, StdMMR6Rel, ABSS_FT<"round.w.s", FGR32Opnd, FGR32Opnd, II_ROUND>, + ABSS_FM<0xc, 16>, ISA_MIPS2; + defm ROUND_W : ROUND_M<"round.w.d", II_ROUND>, ABSS_FM<0xc, 17>, ISA_MIPS2; + def TRUNC_W_S : MMRel, StdMMR6Rel, ABSS_FT<"trunc.w.s", FGR32Opnd, FGR32Opnd, II_TRUNC>, + ABSS_FM<0xd, 16>, ISA_MIPS2; + def CEIL_W_S : MMRel, StdMMR6Rel, ABSS_FT<"ceil.w.s", FGR32Opnd, FGR32Opnd, II_CEIL>, + ABSS_FM<0xe, 16>, ISA_MIPS2; + def FLOOR_W_S : MMRel, StdMMR6Rel, ABSS_FT<"floor.w.s", FGR32Opnd, FGR32Opnd, II_FLOOR>, + ABSS_FM<0xf, 16>, ISA_MIPS2; + def CVT_W_S : MMRel, ABSS_FT<"cvt.w.s", FGR32Opnd, FGR32Opnd, II_CVT>, + ABSS_FM<0x24, 16>, ISA_MIPS1; + + defm TRUNC_W : ROUND_M<"trunc.w.d", II_TRUNC>, ABSS_FM<0xd, 17>, ISA_MIPS2; + defm CEIL_W : ROUND_M<"ceil.w.d", II_CEIL>, ABSS_FM<0xe, 17>, ISA_MIPS2; + defm FLOOR_W : ROUND_M<"floor.w.d", II_FLOOR>, ABSS_FM<0xf, 17>, ISA_MIPS2; + defm CVT_W : ROUND_M<"cvt.w.d", II_CVT>, ABSS_FM<0x24, 17>, ISA_MIPS1; +} let AdditionalPredicates = [NotInMicroMips] in { def RECIP_S : MMRel, ABSS_FT<"recip.s", FGR32Opnd, FGR32Opnd, II_RECIP_S>, @@ -391,53 +397,54 @@ let AdditionalPredicates = [NotInMicroMips] in { let DecoderNamespace = "MipsFP64" in { let AdditionalPredicates = [NotInMicroMips] in { def ROUND_L_S : ABSS_FT<"round.l.s", FGR64Opnd, FGR32Opnd, II_ROUND>, - ABSS_FM<0x8, 16>, FGR_64; + ABSS_FM<0x8, 16>, ISA_MIPS2, FGR_64; def ROUND_L_D64 : ABSS_FT<"round.l.d", FGR64Opnd, FGR64Opnd, II_ROUND>, - ABSS_FM<0x8, 17>, FGR_64; + ABSS_FM<0x8, 17>, INSN_MIPS3_32, FGR_64; def TRUNC_L_S : ABSS_FT<"trunc.l.s", FGR64Opnd, FGR32Opnd, II_TRUNC>, - ABSS_FM<0x9, 16>, FGR_64; + ABSS_FM<0x9, 16>, ISA_MIPS2, FGR_64; def TRUNC_L_D64 : ABSS_FT<"trunc.l.d", FGR64Opnd, FGR64Opnd, II_TRUNC>, - ABSS_FM<0x9, 17>, FGR_64; + ABSS_FM<0x9, 17>, INSN_MIPS3_32, FGR_64; def CEIL_L_S : ABSS_FT<"ceil.l.s", FGR64Opnd, FGR32Opnd, II_CEIL>, - ABSS_FM<0xa, 16>, FGR_64; + ABSS_FM<0xa, 16>, ISA_MIPS2, FGR_64; def CEIL_L_D64 : ABSS_FT<"ceil.l.d", FGR64Opnd, FGR64Opnd, II_CEIL>, - ABSS_FM<0xa, 17>, FGR_64; + ABSS_FM<0xa, 17>, INSN_MIPS3_32, FGR_64; def FLOOR_L_S : ABSS_FT<"floor.l.s", FGR64Opnd, FGR32Opnd, II_FLOOR>, - ABSS_FM<0xb, 16>, FGR_64; + ABSS_FM<0xb, 16>, ISA_MIPS2, FGR_64; def FLOOR_L_D64 : ABSS_FT<"floor.l.d", FGR64Opnd, FGR64Opnd, II_FLOOR>, - ABSS_FM<0xb, 17>, FGR_64; + ABSS_FM<0xb, 17>, INSN_MIPS3_32, FGR_64; } } -def CVT_S_W : MMRel, ABSS_FT<"cvt.s.w", FGR32Opnd, FGR32Opnd, II_CVT>, - ABSS_FM<0x20, 20>; let AdditionalPredicates = [NotInMicroMips] in{ + def CVT_S_W : MMRel, ABSS_FT<"cvt.s.w", FGR32Opnd, FGR32Opnd, II_CVT>, + ABSS_FM<0x20, 20>, ISA_MIPS1; def CVT_L_S : MMRel, ABSS_FT<"cvt.l.s", FGR64Opnd, FGR32Opnd, II_CVT>, ABSS_FM<0x25, 16>, INSN_MIPS3_32R2; def CVT_L_D64: MMRel, ABSS_FT<"cvt.l.d", FGR64Opnd, FGR64Opnd, II_CVT>, ABSS_FM<0x25, 17>, INSN_MIPS3_32R2; } -def CVT_S_D32 : MMRel, ABSS_FT<"cvt.s.d", FGR32Opnd, AFGR64Opnd, II_CVT>, - ABSS_FM<0x20, 17>, FGR_32; -def CVT_D32_W : MMRel, ABSS_FT<"cvt.d.w", AFGR64Opnd, FGR32Opnd, II_CVT>, - ABSS_FM<0x21, 20>, FGR_32; -def CVT_D32_S : MMRel, ABSS_FT<"cvt.d.s", AFGR64Opnd, FGR32Opnd, II_CVT>, - ABSS_FM<0x21, 16>, FGR_32; - +let AdditionalPredicates = [NotInMicroMips] in { + def CVT_S_D32 : MMRel, ABSS_FT<"cvt.s.d", FGR32Opnd, AFGR64Opnd, II_CVT>, + ABSS_FM<0x20, 17>, ISA_MIPS1, FGR_32; + def CVT_D32_S : MMRel, ABSS_FT<"cvt.d.s", AFGR64Opnd, FGR32Opnd, II_CVT>, + ABSS_FM<0x21, 16>, ISA_MIPS1, FGR_32; + def CVT_D32_W : MMRel, ABSS_FT<"cvt.d.w", AFGR64Opnd, FGR32Opnd, II_CVT>, + ABSS_FM<0x21, 20>, ISA_MIPS1, FGR_32; +} let DecoderNamespace = "MipsFP64" in { - def CVT_S_D64 : ABSS_FT<"cvt.s.d", FGR32Opnd, FGR64Opnd, II_CVT>, - ABSS_FM<0x20, 17>, FGR_64; - let AdditionalPredicates = [NotInMicroMips] in{ + let AdditionalPredicates = [NotInMicroMips] in { def CVT_S_L : ABSS_FT<"cvt.s.l", FGR32Opnd, FGR64Opnd, II_CVT>, - ABSS_FM<0x20, 21>, FGR_64; + ABSS_FM<0x20, 21>, INSN_MIPS3_32R2, FGR_64; + def CVT_S_D64 : ABSS_FT<"cvt.s.d", FGR32Opnd, FGR64Opnd, II_CVT>, + ABSS_FM<0x20, 17>, ISA_MIPS1, FGR_64; + def CVT_D64_W : ABSS_FT<"cvt.d.w", FGR64Opnd, FGR32Opnd, II_CVT>, + ABSS_FM<0x21, 20>, ISA_MIPS1, FGR_64; + def CVT_D64_S : ABSS_FT<"cvt.d.s", FGR64Opnd, FGR32Opnd, II_CVT>, + ABSS_FM<0x21, 16>, ISA_MIPS1, FGR_64; + def CVT_D64_L : ABSS_FT<"cvt.d.l", FGR64Opnd, FGR64Opnd, II_CVT>, + ABSS_FM<0x21, 21>, INSN_MIPS3_32R2, FGR_64; } - def CVT_D64_W : ABSS_FT<"cvt.d.w", FGR64Opnd, FGR32Opnd, II_CVT>, - ABSS_FM<0x21, 20>, FGR_64; - def CVT_D64_S : ABSS_FT<"cvt.d.s", FGR64Opnd, FGR32Opnd, II_CVT>, - ABSS_FM<0x21, 16>, FGR_64; - def CVT_D64_L : ABSS_FT<"cvt.d.l", FGR64Opnd, FGR64Opnd, II_CVT>, - ABSS_FM<0x21, 21>, FGR_64; } let isPseudo = 1, isCodeGenOnly = 1 in { @@ -450,17 +457,21 @@ let isPseudo = 1, isCodeGenOnly = 1 in { let AdditionalPredicates = [NotInMicroMips] in { def FABS_S : MMRel, ABSS_FT<"abs.s", FGR32Opnd, FGR32Opnd, II_ABS, fabs>, - ABSS_FM<0x5, 16>; - defm FABS : ABSS_M<"abs.d", II_ABS, fabs>, ABSS_FM<0x5, 17>; + ABSS_FM<0x5, 16>, ISA_MIPS1; + defm FABS : ABSS_M<"abs.d", II_ABS, fabs>, ABSS_FM<0x5, 17>, ISA_MIPS1; } def FNEG_S : MMRel, ABSS_FT<"neg.s", FGR32Opnd, FGR32Opnd, II_NEG, fneg>, - ABSS_FM<0x7, 16>; -defm FNEG : ABSS_M<"neg.d", II_NEG, fneg>, ABSS_FM<0x7, 17>; + ABSS_FM<0x7, 16>, ISA_MIPS1; +let AdditionalPredicates = [NotInMicroMips] in { + defm FNEG : ABSS_M<"neg.d", II_NEG, fneg>, ABSS_FM<0x7, 17>, ISA_MIPS1; +} -def FSQRT_S : MMRel, StdMMR6Rel, ABSS_FT<"sqrt.s", FGR32Opnd, FGR32Opnd, - II_SQRT_S, fsqrt>, ABSS_FM<0x4, 16>, ISA_MIPS2; -defm FSQRT : ABSS_M<"sqrt.d", II_SQRT_D, fsqrt>, ABSS_FM<0x4, 17>, ISA_MIPS2; +let AdditionalPredicates = [NotInMicroMips] in { + def FSQRT_S : MMRel, StdMMR6Rel, ABSS_FT<"sqrt.s", FGR32Opnd, FGR32Opnd, + II_SQRT_S, fsqrt>, ABSS_FM<0x4, 16>, ISA_MIPS2; + defm FSQRT : ABSS_M<"sqrt.d", II_SQRT_D, fsqrt>, ABSS_FM<0x4, 17>, ISA_MIPS2; +} // The odd-numbered registers are only referenced when doing loads, // stores, and moves between floating-point and integer registers. @@ -469,60 +480,60 @@ defm FSQRT : ABSS_M<"sqrt.d", II_SQRT_D, fsqrt>, ABSS_FM<0x4, 17>, ISA_MIPS2; /// Move Control Registers From/To CPU Registers let AdditionalPredicates = [NotInMicroMips] in { - def CFC1 : MMRel, MFC1_FT<"cfc1", GPR32Opnd, CCROpnd, II_CFC1>, MFC1_FM<2>; - def CTC1 : MMRel, MTC1_FT<"ctc1", CCROpnd, GPR32Opnd, II_CTC1>, MFC1_FM<6>; -} -def MFC1 : MMRel, MFC1_FT<"mfc1", GPR32Opnd, FGR32Opnd, II_MFC1, - bitconvert>, MFC1_FM<0>; -def MFC1_D64 : MFC1_FT<"mfc1", GPR32Opnd, FGR64Opnd, II_MFC1>, MFC1_FM<0>, - FGR_64 { - let DecoderNamespace = "MipsFP64"; -} -def MTC1 : MMRel, MTC1_FT<"mtc1", FGR32Opnd, GPR32Opnd, II_MTC1, - bitconvert>, MFC1_FM<4>; -def MTC1_D64 : MTC1_FT<"mtc1", FGR64Opnd, GPR32Opnd, II_MTC1>, MFC1_FM<4>, - FGR_64 { - let DecoderNamespace = "MipsFP64"; -} + def CFC1 : MMRel, MFC1_FT<"cfc1", GPR32Opnd, CCROpnd, II_CFC1>, MFC1_FM<2>, + ISA_MIPS1; + def CTC1 : MMRel, MTC1_FT<"ctc1", CCROpnd, GPR32Opnd, II_CTC1>, MFC1_FM<6>, + ISA_MIPS1; + + def MFC1 : MMRel, MFC1_FT<"mfc1", GPR32Opnd, FGR32Opnd, II_MFC1, + bitconvert>, MFC1_FM<0>, ISA_MIPS1; + def MFC1_D64 : MFC1_FT<"mfc1", GPR32Opnd, FGR64Opnd, II_MFC1>, MFC1_FM<0>, + ISA_MIPS1, FGR_64 { + let DecoderNamespace = "MipsFP64"; + } + def MTC1 : MMRel, MTC1_FT<"mtc1", FGR32Opnd, GPR32Opnd, II_MTC1, + bitconvert>, MFC1_FM<4>, ISA_MIPS1; + def MTC1_D64 : MTC1_FT<"mtc1", FGR64Opnd, GPR32Opnd, II_MTC1>, MFC1_FM<4>, + ISA_MIPS1, FGR_64 { + let DecoderNamespace = "MipsFP64"; + } -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 = "MipsFP64"; } -} -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 = "MipsFP64"; } -} -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>; -def FMOV_D32 : MMRel, ABSS_FT<"mov.d", AFGR64Opnd, AFGR64Opnd, II_MOV_D>, - ABSS_FM<0x6, 17>, FGR_32; -def FMOV_D64 : ABSS_FT<"mov.d", FGR64Opnd, FGR64Opnd, II_MOV_D>, - ABSS_FM<0x6, 17>, FGR_64 { - let DecoderNamespace = "MipsFP64"; + let isMoveReg = 1 in { + def FMOV_S : MMRel, ABSS_FT<"mov.s", FGR32Opnd, FGR32Opnd, II_MOV_S>, + ABSS_FM<0x6, 16>, ISA_MIPS1; + def FMOV_D32 : MMRel, ABSS_FT<"mov.d", AFGR64Opnd, AFGR64Opnd, II_MOV_D>, + ABSS_FM<0x6, 17>, ISA_MIPS1, FGR_32; + def FMOV_D64 : ABSS_FT<"mov.d", FGR64Opnd, FGR64Opnd, II_MOV_D>, + ABSS_FM<0x6, 17>, ISA_MIPS1, FGR_64 { + let DecoderNamespace = "MipsFP64"; + } + } // isMoveReg } /// Floating Point Memory Instructions let AdditionalPredicates = [NotInMicroMips] in { def LWC1 : MMRel, LW_FT<"lwc1", FGR32Opnd, mem_simm16, II_LWC1, load>, - LW_FM<0x31>; + LW_FM<0x31>, ISA_MIPS1; def SWC1 : MMRel, SW_FT<"swc1", FGR32Opnd, mem_simm16, II_SWC1, store>, - LW_FM<0x39>; + LW_FM<0x39>, ISA_MIPS1; } let DecoderNamespace = "MipsFP64", AdditionalPredicates = [NotInMicroMips] in { @@ -569,14 +580,15 @@ let DecoderNamespace="MipsFP64" in { // Load/store doubleword indexed unaligned. // FIXME: This instruction should not be defined for FGR_32. -let AdditionalPredicates = [IsNotNaCl] in { +let AdditionalPredicates = [IsNotNaCl, NotInMicroMips] in { def LUXC1 : MMRel, LWXC1_FT<"luxc1", AFGR64Opnd, II_LUXC1>, LWXC1_FM<0x5>, INSN_MIPS5_32R2_NOT_32R6_64R6, FGR_32; def SUXC1 : MMRel, SWXC1_FT<"suxc1", AFGR64Opnd, II_SUXC1>, SWXC1_FM<0xd>, INSN_MIPS5_32R2_NOT_32R6_64R6, FGR_32; } -let DecoderNamespace="MipsFP64" in { +let AdditionalPredicates = [IsNotNaCl, NotInMicroMips], + DecoderNamespace="MipsFP64" in { def LUXC164 : LWXC1_FT<"luxc1", FGR64Opnd, II_LUXC1>, LWXC1_FM<0x5>, INSN_MIPS5_32R2_NOT_32R6_64R6, FGR_64; def SUXC164 : SWXC1_FT<"suxc1", FGR64Opnd, II_SUXC1>, SWXC1_FM<0xd>, @@ -584,58 +596,62 @@ let DecoderNamespace="MipsFP64" in { } /// Floating-point Aritmetic -def FADD_S : MMRel, ADDS_FT<"add.s", FGR32Opnd, II_ADD_S, 1, fadd>, - ADDS_FM<0x00, 16>; -defm FADD : ADDS_M<"add.d", II_ADD_D, 1, fadd>, ADDS_FM<0x00, 17>; -def FDIV_S : MMRel, ADDS_FT<"div.s", FGR32Opnd, II_DIV_S, 0, fdiv>, - ADDS_FM<0x03, 16>; -defm FDIV : ADDS_M<"div.d", II_DIV_D, 0, fdiv>, ADDS_FM<0x03, 17>; -def FMUL_S : MMRel, ADDS_FT<"mul.s", FGR32Opnd, II_MUL_S, 1, fmul>, - ADDS_FM<0x02, 16>; -defm FMUL : ADDS_M<"mul.d", II_MUL_D, 1, fmul>, ADDS_FM<0x02, 17>; -def FSUB_S : MMRel, ADDS_FT<"sub.s", FGR32Opnd, II_SUB_S, 0, fsub>, - ADDS_FM<0x01, 16>; -defm FSUB : ADDS_M<"sub.d", II_SUB_D, 0, fsub>, ADDS_FM<0x01, 17>; - -def MADD_S : MMRel, MADDS_FT<"madd.s", FGR32Opnd, II_MADD_S, fadd>, - MADDS_FM<4, 0>, INSN_MIPS4_32R2_NOT_32R6_64R6, MADD4; -def MSUB_S : MMRel, MADDS_FT<"msub.s", FGR32Opnd, II_MSUB_S, fsub>, - MADDS_FM<5, 0>, INSN_MIPS4_32R2_NOT_32R6_64R6, MADD4; - -let AdditionalPredicates = [NoNaNsFPMath, HasMadd4] in { +let AdditionalPredicates = [NotInMicroMips] in { + def FADD_S : MMRel, ADDS_FT<"add.s", FGR32Opnd, II_ADD_S, 1, fadd>, + ADDS_FM<0x00, 16>, ISA_MIPS1; + defm FADD : ADDS_M<"add.d", II_ADD_D, 1, fadd>, ADDS_FM<0x00, 17>, + ISA_MIPS1; + def FDIV_S : MMRel, ADDS_FT<"div.s", FGR32Opnd, II_DIV_S, 0, fdiv>, + ADDS_FM<0x03, 16>, ISA_MIPS1; + defm FDIV : ADDS_M<"div.d", II_DIV_D, 0, fdiv>, ADDS_FM<0x03, 17>, + ISA_MIPS1; + def FMUL_S : MMRel, ADDS_FT<"mul.s", FGR32Opnd, II_MUL_S, 1, fmul>, + ADDS_FM<0x02, 16>, ISA_MIPS1; + defm FMUL : ADDS_M<"mul.d", II_MUL_D, 1, fmul>, ADDS_FM<0x02, 17>, + ISA_MIPS1; + def FSUB_S : MMRel, ADDS_FT<"sub.s", FGR32Opnd, II_SUB_S, 0, fsub>, + ADDS_FM<0x01, 16>, ISA_MIPS1; + defm FSUB : ADDS_M<"sub.d", II_SUB_D, 0, fsub>, ADDS_FM<0x01, 17>, + ISA_MIPS1; +} + +let AdditionalPredicates = [NotInMicroMips, HasMadd4] in { + def MADD_S : MMRel, MADDS_FT<"madd.s", FGR32Opnd, II_MADD_S, fadd>, + MADDS_FM<4, 0>, INSN_MIPS4_32R2_NOT_32R6_64R6; + def MSUB_S : MMRel, MADDS_FT<"msub.s", FGR32Opnd, II_MSUB_S, fsub>, + MADDS_FM<5, 0>, INSN_MIPS4_32R2_NOT_32R6_64R6; + + def MADD_D32 : MMRel, MADDS_FT<"madd.d", AFGR64Opnd, II_MADD_D, fadd>, + MADDS_FM<4, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_32; + def MSUB_D32 : MMRel, MADDS_FT<"msub.d", AFGR64Opnd, II_MSUB_D, fsub>, + MADDS_FM<5, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_32; + + let DecoderNamespace = "MipsFP64" in { + def MADD_D64 : MADDS_FT<"madd.d", FGR64Opnd, II_MADD_D, fadd>, + MADDS_FM<4, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_64; + def MSUB_D64 : MADDS_FT<"msub.d", FGR64Opnd, II_MSUB_D, fsub>, + MADDS_FM<5, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_64; + } +} + +let AdditionalPredicates = [NoNaNsFPMath, HasMadd4, NotInMicroMips] in { def NMADD_S : MMRel, NMADDS_FT<"nmadd.s", FGR32Opnd, II_NMADD_S, fadd>, MADDS_FM<6, 0>, INSN_MIPS4_32R2_NOT_32R6_64R6; def NMSUB_S : MMRel, NMADDS_FT<"nmsub.s", FGR32Opnd, II_NMSUB_S, fsub>, MADDS_FM<7, 0>, INSN_MIPS4_32R2_NOT_32R6_64R6; -} -def MADD_D32 : MMRel, MADDS_FT<"madd.d", AFGR64Opnd, II_MADD_D, fadd>, - MADDS_FM<4, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_32, MADD4; -def MSUB_D32 : MMRel, MADDS_FT<"msub.d", AFGR64Opnd, II_MSUB_D, fsub>, - MADDS_FM<5, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_32, MADD4; - -let AdditionalPredicates = [NoNaNsFPMath, HasMadd4] in { def NMADD_D32 : MMRel, NMADDS_FT<"nmadd.d", AFGR64Opnd, II_NMADD_D, fadd>, MADDS_FM<6, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_32; def NMSUB_D32 : MMRel, NMADDS_FT<"nmsub.d", AFGR64Opnd, II_NMSUB_D, fsub>, MADDS_FM<7, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_32; -} - -let DecoderNamespace = "MipsFP64" in { - def MADD_D64 : MADDS_FT<"madd.d", FGR64Opnd, II_MADD_D, fadd>, - MADDS_FM<4, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_64, MADD4; - def MSUB_D64 : MADDS_FT<"msub.d", FGR64Opnd, II_MSUB_D, fsub>, - MADDS_FM<5, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_64, MADD4; -} -let AdditionalPredicates = [NoNaNsFPMath, HasMadd4], - DecoderNamespace = "MipsFP64" in { - def NMADD_D64 : NMADDS_FT<"nmadd.d", FGR64Opnd, II_NMADD_D, fadd>, - MADDS_FM<6, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_64; - def NMSUB_D64 : NMADDS_FT<"nmsub.d", FGR64Opnd, II_NMSUB_D, fsub>, - MADDS_FM<7, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_64; + let DecoderNamespace = "MipsFP64" in { + def NMADD_D64 : NMADDS_FT<"nmadd.d", FGR64Opnd, II_NMADD_D, fadd>, + MADDS_FM<6, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_64; + def NMSUB_D64 : NMADDS_FT<"nmsub.d", FGR64Opnd, II_NMSUB_D, fsub>, + MADDS_FM<7, 1>, INSN_MIPS4_32R2_NOT_32R6_64R6, FGR_64; + } } - //===----------------------------------------------------------------------===// // Floating Point Branch Codes //===----------------------------------------------------------------------===// @@ -844,28 +860,31 @@ let AdditionalPredicates = [NotInMicroMips] in { //===----------------------------------------------------------------------===// // Floating Point Patterns //===----------------------------------------------------------------------===// -def : MipsPat<(f32 fpimm0), (MTC1 ZERO)>; -def : MipsPat<(f32 fpimm0neg), (FNEG_S (MTC1 ZERO))>; +def : MipsPat<(f32 fpimm0), (MTC1 ZERO)>, ISA_MIPS1; +def : MipsPat<(f32 fpimm0neg), (FNEG_S (MTC1 ZERO))>, ISA_MIPS1; def : MipsPat<(f32 (sint_to_fp GPR32Opnd:$src)), (PseudoCVT_S_W GPR32Opnd:$src)>; def : MipsPat<(MipsTruncIntFP FGR32Opnd:$src), - (TRUNC_W_S FGR32Opnd:$src)>; + (TRUNC_W_S FGR32Opnd:$src)>, ISA_MIPS1; def : MipsPat<(MipsMTC1_D64 GPR32Opnd:$src), - (MTC1_D64 GPR32Opnd:$src)>, FGR_64; + (MTC1_D64 GPR32Opnd:$src)>, ISA_MIPS1, FGR_64; def : MipsPat<(f64 (sint_to_fp GPR32Opnd:$src)), (PseudoCVT_D32_W GPR32Opnd:$src)>, FGR_32; -def : MipsPat<(MipsTruncIntFP AFGR64Opnd:$src), - (TRUNC_W_D32 AFGR64Opnd:$src)>, FGR_32; -def : MipsPat<(f32 (fpround AFGR64Opnd:$src)), - (CVT_S_D32 AFGR64Opnd:$src)>, FGR_32; -def : MipsPat<(f64 (fpextend FGR32Opnd:$src)), - (CVT_D32_S FGR32Opnd:$src)>, FGR_32; +let AdditionalPredicates = [NotInMicroMips] in { + def : MipsPat<(MipsTruncIntFP AFGR64Opnd:$src), + (TRUNC_W_D32 AFGR64Opnd:$src)>, ISA_MIPS2, FGR_32; + def : MipsPat<(f32 (fpround AFGR64Opnd:$src)), + (CVT_S_D32 AFGR64Opnd:$src)>, ISA_MIPS1, FGR_32; + def : MipsPat<(f64 (fpextend FGR32Opnd:$src)), + (CVT_D32_S FGR32Opnd:$src)>, ISA_MIPS1, FGR_32; +} -def : MipsPat<(f64 fpimm0), (DMTC1 ZERO_64)>, FGR_64; -def : MipsPat<(f64 fpimm0neg), (FNEG_D64 (DMTC1 ZERO_64))>, FGR_64; +def : MipsPat<(f64 fpimm0), (DMTC1 ZERO_64)>, ISA_MIPS3, GPR_64, FGR_64; +def : MipsPat<(f64 fpimm0neg), (FNEG_D64 (DMTC1 ZERO_64))>, ISA_MIPS3, GPR_64, + FGR_64; def : MipsPat<(f64 (sint_to_fp GPR32Opnd:$src)), (PseudoCVT_D64_W GPR32Opnd:$src)>, FGR_64; @@ -875,16 +894,18 @@ def : MipsPat<(f64 (sint_to_fp GPR64Opnd:$src)), (PseudoCVT_D64_L GPR64Opnd:$src)>, FGR_64; def : MipsPat<(MipsTruncIntFP FGR64Opnd:$src), - (TRUNC_W_D64 FGR64Opnd:$src)>, FGR_64; + (TRUNC_W_D64 FGR64Opnd:$src)>, ISA_MIPS2, FGR_64; def : MipsPat<(MipsTruncIntFP FGR32Opnd:$src), - (TRUNC_L_S FGR32Opnd:$src)>, FGR_64; + (TRUNC_L_S FGR32Opnd:$src)>, ISA_MIPS2, FGR_64; def : MipsPat<(MipsTruncIntFP FGR64Opnd:$src), - (TRUNC_L_D64 FGR64Opnd:$src)>, FGR_64; + (TRUNC_L_D64 FGR64Opnd:$src)>, ISA_MIPS2, FGR_64; -def : MipsPat<(f32 (fpround FGR64Opnd:$src)), - (CVT_S_D64 FGR64Opnd:$src)>, FGR_64; -def : MipsPat<(f64 (fpextend FGR32Opnd:$src)), - (CVT_D64_S FGR32Opnd:$src)>, FGR_64; +let AdditionalPredicates = [NotInMicroMips] in { + def : MipsPat<(f32 (fpround FGR64Opnd:$src)), + (CVT_S_D64 FGR64Opnd:$src)>, ISA_MIPS1, FGR_64; + def : MipsPat<(f64 (fpextend FGR32Opnd:$src)), + (CVT_D64_S FGR32Opnd:$src)>, ISA_MIPS1, FGR_64; +} // To generate NMADD and NMSUB instructions when fneg node is present multiclass NMADD_NMSUB<Instruction Nmadd, Instruction Nmsub, RegisterOperand RC> { @@ -903,13 +924,13 @@ let AdditionalPredicates = [NoNaNsFPMath, HasMadd4, NotInMicroMips] in { // Patterns for loads/stores with a reg+imm operand. let AdditionalPredicates = [NotInMicroMips] in { let AddedComplexity = 40 in { - def : LoadRegImmPat<LWC1, f32, load>; - def : StoreRegImmPat<SWC1, f32>; + def : LoadRegImmPat<LWC1, f32, load>, ISA_MIPS1; + def : StoreRegImmPat<SWC1, f32>, ISA_MIPS1; - def : LoadRegImmPat<LDC164, f64, load>, FGR_64; - def : StoreRegImmPat<SDC164, f64>, FGR_64; + def : LoadRegImmPat<LDC164, f64, load>, ISA_MIPS1, FGR_64; + def : StoreRegImmPat<SDC164, f64>, ISA_MIPS1, FGR_64; - def : LoadRegImmPat<LDC1, f64, load>, FGR_32; - def : StoreRegImmPat<SDC1, f64>, FGR_32; + def : LoadRegImmPat<LDC1, f64, load>, ISA_MIPS1, FGR_32; + def : StoreRegImmPat<SDC1, f64>, ISA_MIPS1, FGR_32; } } diff --git a/lib/Target/Mips/MipsInstrFormats.td b/lib/Target/Mips/MipsInstrFormats.td index 817d9b44b9c2..ebbdcdf0df89 100644 --- a/lib/Target/Mips/MipsInstrFormats.td +++ b/lib/Target/Mips/MipsInstrFormats.td @@ -70,7 +70,7 @@ class StdArch { // Generic Mips Format class MipsInst<dag outs, dag ins, string asmstr, list<dag> pattern, - InstrItinClass itin, Format f>: Instruction + InstrItinClass itin, Format f>: Instruction, PredicateControl { field bits<32> Inst; Format Form = f; @@ -119,8 +119,8 @@ class MipsInst<dag outs, dag ins, string asmstr, list<dag> pattern, // Mips32/64 Instruction Format class InstSE<dag outs, dag ins, string asmstr, list<dag> pattern, InstrItinClass itin, Format f, string opstr = ""> : - MipsInst<outs, ins, asmstr, pattern, itin, f>, PredicateControl { - let EncodingPredicates = [HasStdEnc]; + MipsInst<outs, ins, asmstr, pattern, itin, f> { + let EncodingPredicates = [NotInMips16Mode]; string BaseOpcode = opstr; string Arch; } @@ -136,15 +136,15 @@ class MipsPseudo<dag outs, dag ins, list<dag> pattern, // Mips32/64 Pseudo Instruction Format class PseudoSE<dag outs, dag ins, list<dag> pattern, InstrItinClass itin = IIPseudo> : - MipsPseudo<outs, ins, pattern, itin>, PredicateControl { - let EncodingPredicates = [HasStdEnc]; + MipsPseudo<outs, ins, pattern, itin> { + let EncodingPredicates = [NotInMips16Mode]; } // Pseudo-instructions for alternate assembly syntax (never used by codegen). // These are aliases that require C++ handling to convert to the target // instruction, while InstAliases can be handled directly by tblgen. class MipsAsmPseudoInst<dag outs, dag ins, string asmstr>: - MipsInst<outs, ins, asmstr, [], IIPseudo, Pseudo>, PredicateControl { + MipsInst<outs, ins, asmstr, [], IIPseudo, Pseudo> { let isPseudo = 1; let Pattern = []; } @@ -220,10 +220,9 @@ class FJ<bits<6> op> : StdArch } //===----------------------------------------------------------------------===// -// MFC instruction class in Mips : <|op|mf|rt|rd|0000000|sel|> +// MFC instruction class in Mips : <|op|mf|rt|rd|gst|0000|sel|> //===----------------------------------------------------------------------===// -class MFC3OP_FM<bits<6> op, bits<5> mfmt> -{ +class MFC3OP_FM<bits<6> op, bits<5> mfmt, bits<3> guest> : StdArch { bits<5> rt; bits<5> rd; bits<3> sel; @@ -234,7 +233,8 @@ class MFC3OP_FM<bits<6> op, bits<5> mfmt> let Inst{25-21} = mfmt; let Inst{20-16} = rt; let Inst{15-11} = rd; - let Inst{10-3} = 0; + let Inst{10-8} = guest; + let Inst{7-3} = 0; let Inst{2-0} = sel; } @@ -508,6 +508,7 @@ class EXT_FM<bits<6> funct> : StdArch { class RDHWR_FM : StdArch { bits<5> rt; bits<5> rd; + bits<3> sel; bits<32> Inst; @@ -515,7 +516,8 @@ class RDHWR_FM : StdArch { let Inst{25-21} = 0; let Inst{20-16} = rt; let Inst{15-11} = rd; - let Inst{10-6} = 0; + let Inst{10-9} = 0b00; + let Inst{8-6} = sel; let Inst{5-0} = 0x3b; } @@ -970,3 +972,14 @@ class CACHEOP_FM<bits<6> op> : StdArch { let Inst{20-16} = hint; let Inst{15-0} = offset; } + +class HYPCALL_FM<bits<6> op> : StdArch { + bits<10> code_; + + bits<32> Inst; + + let Inst{31-26} = 0b010000; + let Inst{25} = 1; + let Inst{20-11} = code_; + let Inst{5-0} = op; +} diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp index 51ddc0d44c00..0e0e712dba19 100644 --- a/lib/Target/Mips/MipsInstrInfo.cpp +++ b/lib/Target/Mips/MipsInstrInfo.cpp @@ -163,7 +163,7 @@ unsigned MipsInstrInfo::removeBranch(MachineBasicBlock &MBB, // Note that indirect branches are not removed. while (I != REnd && removed < 2) { // Skip past debug instructions. - if (I->isDebugValue()) { + if (I->isDebugInstr()) { ++I; continue; } @@ -195,7 +195,7 @@ MipsInstrInfo::BranchType MipsInstrInfo::analyzeBranch( MachineBasicBlock::reverse_iterator I = MBB.rbegin(), REnd = MBB.rend(); // Skip all the debug instructions. - while (I != REnd && I->isDebugValue()) + while (I != REnd && I->isDebugInstr()) ++I; if (I == REnd || !isUnpredicatedTerminator(*I)) { @@ -220,7 +220,7 @@ MipsInstrInfo::BranchType MipsInstrInfo::analyzeBranch( // Skip past any debug instruction to see if the second last actual // is a branch. ++I; - while (I != REnd && I->isDebugValue()) + while (I != REnd && I->isDebugInstr()) ++I; if (I != REnd) { @@ -276,6 +276,163 @@ MipsInstrInfo::BranchType MipsInstrInfo::analyzeBranch( return BT_CondUncond; } +bool MipsInstrInfo::isBranchOffsetInRange(unsigned BranchOpc, int64_t BrOffset) const { + switch (BranchOpc) { + case Mips::B: + case Mips::BAL: + case Mips::BC1F: + case Mips::BC1FL: + case Mips::BC1T: + case Mips::BC1TL: + case Mips::BEQ: case Mips::BEQ64: + case Mips::BEQL: + case Mips::BGEZ: case Mips::BGEZ64: + case Mips::BGEZL: + case Mips::BGEZAL: + case Mips::BGEZALL: + case Mips::BGTZ: case Mips::BGTZ64: + case Mips::BGTZL: + case Mips::BLEZ: case Mips::BLEZ64: + case Mips::BLEZL: + case Mips::BLTZ: case Mips::BLTZ64: + case Mips::BLTZL: + case Mips::BLTZAL: + case Mips::BLTZALL: + case Mips::BNE: case Mips::BNE64: + case Mips::BNEL: + return isInt<18>(BrOffset); + + // microMIPSr3 branches + case Mips::B_MM: + case Mips::BC1F_MM: + case Mips::BC1T_MM: + case Mips::BEQ_MM: + case Mips::BGEZ_MM: + case Mips::BGEZAL_MM: + case Mips::BGTZ_MM: + case Mips::BLEZ_MM: + case Mips::BLTZ_MM: + case Mips::BLTZAL_MM: + case Mips::BNE_MM: + case Mips::BEQZC_MM: + case Mips::BNEZC_MM: + return isInt<17>(BrOffset); + + // microMIPSR3 short branches. + case Mips::B16_MM: + return isInt<11>(BrOffset); + + case Mips::BEQZ16_MM: + case Mips::BNEZ16_MM: + return isInt<8>(BrOffset); + + // MIPSR6 branches. + case Mips::BALC: + case Mips::BC: + return isInt<28>(BrOffset); + + case Mips::BC1EQZ: + case Mips::BC1NEZ: + case Mips::BC2EQZ: + case Mips::BC2NEZ: + case Mips::BEQC: case Mips::BEQC64: + case Mips::BNEC: case Mips::BNEC64: + case Mips::BGEC: case Mips::BGEC64: + case Mips::BGEUC: case Mips::BGEUC64: + case Mips::BGEZC: case Mips::BGEZC64: + case Mips::BGTZC: case Mips::BGTZC64: + case Mips::BLEZC: case Mips::BLEZC64: + case Mips::BLTC: case Mips::BLTC64: + case Mips::BLTUC: case Mips::BLTUC64: + case Mips::BLTZC: case Mips::BLTZC64: + case Mips::BNVC: + case Mips::BOVC: + case Mips::BGEZALC: + case Mips::BEQZALC: + case Mips::BGTZALC: + case Mips::BLEZALC: + case Mips::BLTZALC: + case Mips::BNEZALC: + return isInt<18>(BrOffset); + + case Mips::BEQZC: case Mips::BEQZC64: + case Mips::BNEZC: case Mips::BNEZC64: + return isInt<23>(BrOffset); + + // microMIPSR6 branches + case Mips::BC16_MMR6: + return isInt<11>(BrOffset); + + case Mips::BEQZC16_MMR6: + case Mips::BNEZC16_MMR6: + return isInt<8>(BrOffset); + + case Mips::BALC_MMR6: + case Mips::BC_MMR6: + return isInt<27>(BrOffset); + + case Mips::BC1EQZC_MMR6: + case Mips::BC1NEZC_MMR6: + case Mips::BC2EQZC_MMR6: + case Mips::BC2NEZC_MMR6: + case Mips::BGEZALC_MMR6: + case Mips::BEQZALC_MMR6: + case Mips::BGTZALC_MMR6: + case Mips::BLEZALC_MMR6: + case Mips::BLTZALC_MMR6: + case Mips::BNEZALC_MMR6: + case Mips::BNVC_MMR6: + case Mips::BOVC_MMR6: + return isInt<17>(BrOffset); + + case Mips::BEQC_MMR6: + case Mips::BNEC_MMR6: + case Mips::BGEC_MMR6: + case Mips::BGEUC_MMR6: + case Mips::BGEZC_MMR6: + case Mips::BGTZC_MMR6: + case Mips::BLEZC_MMR6: + case Mips::BLTC_MMR6: + case Mips::BLTUC_MMR6: + case Mips::BLTZC_MMR6: + return isInt<18>(BrOffset); + + case Mips::BEQZC_MMR6: + case Mips::BNEZC_MMR6: + return isInt<23>(BrOffset); + + // DSP branches. + case Mips::BPOSGE32: + return isInt<18>(BrOffset); + case Mips::BPOSGE32_MM: + case Mips::BPOSGE32C_MMR3: + return isInt<17>(BrOffset); + + // cnMIPS branches. + case Mips::BBIT0: + case Mips::BBIT032: + case Mips::BBIT1: + case Mips::BBIT132: + return isInt<18>(BrOffset); + + // MSA branches. + case Mips::BZ_B: + case Mips::BZ_H: + case Mips::BZ_W: + case Mips::BZ_D: + case Mips::BZ_V: + case Mips::BNZ_B: + case Mips::BNZ_H: + case Mips::BNZ_W: + case Mips::BNZ_D: + case Mips::BNZ_V: + return isInt<18>(BrOffset); + } + + llvm_unreachable("Unknown branch instruction!"); +} + + /// Return the corresponding compact (no delay slot) form of a branch. unsigned MipsInstrInfo::getEquivalentCompactForm( const MachineBasicBlock::iterator I) const { @@ -298,7 +455,6 @@ unsigned MipsInstrInfo::getEquivalentCompactForm( case Mips::JR: case Mips::PseudoReturn: case Mips::PseudoIndirectBranch: - case Mips::TAILCALLREG: canUseShortMicroMipsCTI = true; break; } @@ -377,18 +533,18 @@ unsigned MipsInstrInfo::getEquivalentCompactForm( // 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::PseudoIndirectBranchR6: case Mips::PseudoReturn: - case Mips::PseudoIndirectBranch: - case Mips::TAILCALLREG: + case Mips::TAILCALLR6REG: if (canUseShortMicroMipsCTI) return Mips::JRC16_MM; return Mips::JIC; case Mips::JALRPseudo: return Mips::JIALC; case Mips::JR64: + case Mips::PseudoIndirectBranch64R6: case Mips::PseudoReturn64: - case Mips::PseudoIndirectBranch64: - case Mips::TAILCALLREG64: + case Mips::TAILCALL64R6REG: return Mips::JIC64; case Mips::JALR64Pseudo: return Mips::JIALC64; @@ -599,7 +755,7 @@ bool MipsInstrInfo::verifyInstruction(const MachineInstr &MI, case Mips::DINS: return verifyInsExtInstruction(MI, ErrInfo, 0, 32, 0, 32, 0, 32); case Mips::DINSM: - // The ISA spec has a subtle difference difference between dinsm and dextm + // The ISA spec has a subtle difference between dinsm and dextm // in that it says: // 2 <= size <= 64 for 'dinsm' but 'dextm' has 32 < size <= 64. // To make the bounds checks similar, the range 1 < size <= 64 is checked @@ -617,6 +773,18 @@ bool MipsInstrInfo::verifyInstruction(const MachineInstr &MI, return verifyInsExtInstruction(MI, ErrInfo, 0, 32, 32, 64, 32, 64); case Mips::DEXTU: return verifyInsExtInstruction(MI, ErrInfo, 32, 64, 0, 32, 32, 64); + case Mips::TAILCALLREG: + case Mips::PseudoIndirectBranch: + case Mips::JR: + case Mips::JR64: + case Mips::JALR: + case Mips::JALR64: + case Mips::JALRPseudo: + if (!Subtarget.useIndirectJumpsHazard()) + return true; + + ErrInfo = "invalid instruction when using jump guards!"; + return false; default: return true; } diff --git a/lib/Target/Mips/MipsInstrInfo.h b/lib/Target/Mips/MipsInstrInfo.h index c18e395f9013..9d27b8f66211 100644 --- a/lib/Target/Mips/MipsInstrInfo.h +++ b/lib/Target/Mips/MipsInstrInfo.h @@ -86,6 +86,10 @@ public: /// Determine the opcode of a non-delay slot form for a branch if one exists. unsigned getEquivalentCompactForm(const MachineBasicBlock::iterator I) const; + /// Determine if the branch target is in range. + bool isBranchOffsetInRange(unsigned BranchOpc, + int64_t BrOffset) const override; + /// Predicate to determine if an instruction can go in a forbidden slot. bool SafeInForbiddenSlot(const MachineInstr &MI) const; diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td index e0d818b749df..0faa13d4d63f 100644 --- a/lib/Target/Mips/MipsInstrInfo.td +++ b/lib/Target/Mips/MipsInstrInfo.td @@ -73,12 +73,8 @@ def MipsGPRel : SDNode<"MipsISD::GPRel", SDTIntUnaryOp>; // Hi node for accessing the GOT. def MipsGotHi : SDNode<"MipsISD::GotHi", SDTIntUnaryOp>; -// TlsGd node is used to handle General Dynamic TLS -def MipsTlsGd : SDNode<"MipsISD::TlsGd", SDTIntUnaryOp>; - -// TprelHi and TprelLo nodes are used to handle Local Exec TLS -def MipsTprelHi : SDNode<"MipsISD::TprelHi", SDTIntUnaryOp>; -def MipsTprelLo : SDNode<"MipsISD::TprelLo", SDTIntUnaryOp>; +// Hi node for handling TLS offsets +def MipsTlsHi : SDNode<"MipsISD::TlsHi", SDTIntUnaryOp>; // Thread pointer def MipsThreadPointer: SDNode<"MipsISD::ThreadPointer", SDT_MipsThreadPointer>; @@ -202,12 +198,12 @@ def NotMips64 : Predicate<"!Subtarget->hasMips64()">, AssemblerPredicate<"!FeatureMips64">; def HasMips64r2 : Predicate<"Subtarget->hasMips64r2()">, AssemblerPredicate<"FeatureMips64r2">; +def HasMips64r5 : Predicate<"Subtarget->hasMips64r5()">, + AssemblerPredicate<"FeatureMips64r5">; def HasMips64r6 : Predicate<"Subtarget->hasMips64r6()">, AssemblerPredicate<"FeatureMips64r6">; def NotMips64r6 : Predicate<"!Subtarget->hasMips64r6()">, AssemblerPredicate<"!FeatureMips64r6">; -def HasMicroMips32r6 : Predicate<"Subtarget->inMicroMips32r6Mode()">, - AssemblerPredicate<"FeatureMicroMips,FeatureMips32r6">; def InMips16Mode : Predicate<"Subtarget->inMips16Mode()">, AssemblerPredicate<"FeatureMips16">; def NotInMips16Mode : Predicate<"!Subtarget->inMips16Mode()">, @@ -237,14 +233,26 @@ def IsBE : Predicate<"!Subtarget->isLittle()">; def IsNotNaCl : Predicate<"!Subtarget->isTargetNaCl()">; def UseTCCInDIV : AssemblerPredicate<"FeatureUseTCCInDIV">; def HasEVA : Predicate<"Subtarget->hasEVA()">, - AssemblerPredicate<"FeatureEVA,FeatureMips32r2">; + AssemblerPredicate<"FeatureEVA">; def HasMSA : Predicate<"Subtarget->hasMSA()">, AssemblerPredicate<"FeatureMSA">; def HasMadd4 : Predicate<"!Subtarget->disableMadd4()">, AssemblerPredicate<"!FeatureMadd4">; def HasMT : Predicate<"Subtarget->hasMT()">, AssemblerPredicate<"FeatureMT">; - +def UseIndirectJumpsHazard : Predicate<"Subtarget->useIndirectJumpsHazard()">, + AssemblerPredicate<"FeatureUseIndirectJumpsHazard">; +def NoIndirectJumpGuards : Predicate<"!Subtarget->useIndirectJumpsHazard()">, + AssemblerPredicate<"!FeatureUseIndirectJumpsHazard">; +def HasCRC : Predicate<"Subtarget->hasCRC()">, + AssemblerPredicate<"FeatureCRC">; +def HasVirt : Predicate<"Subtarget->hasVirt()">, + AssemblerPredicate<"FeatureVirt">; +def HasGINV : Predicate<"Subtarget->hasGINV()">, + AssemblerPredicate<"FeatureGINV">; +// TODO: Add support for FPOpFusion::Standard +def AllowFPOpFusion : Predicate<"TM.Options.AllowFPOpFusion ==" + " FPOpFusion::Fast">; //===----------------------------------------------------------------------===// // Mips GPR size adjectives. // They are mutually exclusive. @@ -274,126 +282,203 @@ class SYM_64 { list<Predicate> SYMPredicates = [IsSym64]; } // subtractive predicate will hopefully keep us under the 32 predicate // limit long enough to develop an alternative way to handle P1||P2 // predicates. +class ISA_MIPS1 { + list<Predicate> EncodingPredicates = [HasStdEnc]; +} class ISA_MIPS1_NOT_MIPS3 { list<Predicate> InsnPredicates = [NotMips3]; + list<Predicate> EncodingPredicates = [HasStdEnc]; } class ISA_MIPS1_NOT_4_32 { list<Predicate> InsnPredicates = [NotMips4_32]; + list<Predicate> EncodingPredicates = [HasStdEnc]; } class ISA_MIPS1_NOT_32R6_64R6 { list<Predicate> InsnPredicates = [NotMips32r6, NotMips64r6]; + list<Predicate> EncodingPredicates = [HasStdEnc]; +} +class ISA_MIPS2 { + list<Predicate> InsnPredicates = [HasMips2]; + list<Predicate> EncodingPredicates = [HasStdEnc]; } -class ISA_MIPS2 { list<Predicate> InsnPredicates = [HasMips2]; } class ISA_MIPS2_NOT_32R6_64R6 { list<Predicate> InsnPredicates = [HasMips2, NotMips32r6, NotMips64r6]; + list<Predicate> EncodingPredicates = [HasStdEnc]; +} +class ISA_MIPS3 { + list<Predicate> InsnPredicates = [HasMips3]; + list<Predicate> EncodingPredicates = [HasStdEnc]; } -class ISA_MIPS3 { list<Predicate> InsnPredicates = [HasMips3]; } class ISA_MIPS3_NOT_32R6_64R6 { list<Predicate> InsnPredicates = [HasMips3, NotMips32r6, NotMips64r6]; + list<Predicate> EncodingPredicates = [HasStdEnc]; +} +class ISA_MIPS32 { + list<Predicate> InsnPredicates = [HasMips32]; + list<Predicate> EncodingPredicates = [HasStdEnc]; } -class ISA_MIPS32 { list<Predicate> InsnPredicates = [HasMips32]; } class ISA_MIPS32_NOT_32R6_64R6 { list<Predicate> InsnPredicates = [HasMips32, NotMips32r6, NotMips64r6]; + list<Predicate> EncodingPredicates = [HasStdEnc]; +} +class ISA_MIPS32R2 { + list<Predicate> InsnPredicates = [HasMips32r2]; + list<Predicate> EncodingPredicates = [HasStdEnc]; } -class ISA_MIPS32R2 { list<Predicate> InsnPredicates = [HasMips32r2]; } class ISA_MIPS32R2_NOT_32R6_64R6 { list<Predicate> InsnPredicates = [HasMips32r2, NotMips32r6, NotMips64r6]; + list<Predicate> EncodingPredicates = [HasStdEnc]; +} +class ISA_MIPS32R5 { + list<Predicate> InsnPredicates = [HasMips32r5]; + list<Predicate> EncodingPredicates = [HasStdEnc]; +} +class ISA_MIPS64 { + list<Predicate> InsnPredicates = [HasMips64]; + list<Predicate> EncodingPredicates = [HasStdEnc]; } -class ISA_MIPS32R5 { list<Predicate> InsnPredicates = [HasMips32r5]; } -class ISA_MIPS64 { list<Predicate> InsnPredicates = [HasMips64]; } class ISA_MIPS64_NOT_64R6 { list<Predicate> InsnPredicates = [HasMips64, NotMips64r6]; + list<Predicate> EncodingPredicates = [HasStdEnc]; +} +class ISA_MIPS64R2 { + list<Predicate> InsnPredicates = [HasMips64r2]; + list<Predicate> EncodingPredicates = [HasStdEnc]; +} +class ISA_MIPS64R5 { + list<Predicate> InsnPredicates = [HasMips64r5]; + list<Predicate> EncodingPredicates = [HasStdEnc]; +} +class ISA_MIPS32R6 { + list<Predicate> InsnPredicates = [HasMips32r6]; + list<Predicate> EncodingPredicates = [HasStdEnc]; +} +class ISA_MIPS64R6 { + list<Predicate> InsnPredicates = [HasMips64r6]; + list<Predicate> EncodingPredicates = [HasStdEnc]; +} +class ISA_MICROMIPS { + list<Predicate> EncodingPredicates = [InMicroMips]; +} +class ISA_MICROMIPS32R5 { + list<Predicate> InsnPredicates = [HasMips32r5]; + list<Predicate> EncodingPredicates = [InMicroMips]; } -class ISA_MIPS64R2 { list<Predicate> InsnPredicates = [HasMips64r2]; } -class ISA_MIPS32R6 { list<Predicate> InsnPredicates = [HasMips32r6]; } -class ISA_MIPS64R6 { list<Predicate> InsnPredicates = [HasMips64r6]; } -class ISA_MICROMIPS { list<Predicate> InsnPredicates = [InMicroMips]; } class ISA_MICROMIPS32R6 { - list<Predicate> InsnPredicates = [HasMicroMips32r6]; + list<Predicate> InsnPredicates = [HasMips32r6]; + list<Predicate> EncodingPredicates = [InMicroMips]; } -class ISA_MICROMIPS32_NOT_MIPS32R6 { - list<Predicate> InsnPredicates = [InMicroMips, NotMips32r6]; +class ISA_MICROMIPS64R6 { + list<Predicate> InsnPredicates = [HasMips64r6]; + list<Predicate> EncodingPredicates = [InMicroMips]; } - -class INSN_EVA { list<Predicate> InsnPredicates = [HasEVA]; } -class INSN_EVA_NOT_32R6_64R6 { - list<Predicate> InsnPredicates = [NotMips32r6, NotMips64r6, HasEVA]; +class ISA_MICROMIPS32_NOT_MIPS32R6 { + list<Predicate> InsnPredicates = [NotMips32r6]; + list<Predicate> EncodingPredicates = [InMicroMips]; } +class ASE_EVA { list<Predicate> ASEPredicate = [HasEVA]; } // The portions of MIPS-III that were also added to MIPS32 -class INSN_MIPS3_32 { list<Predicate> InsnPredicates = [HasMips3_32]; } +class INSN_MIPS3_32 { + list<Predicate> InsnPredicates = [HasMips3_32]; + list<Predicate> EncodingPredicates = [HasStdEnc]; +} // The portions of MIPS-III that were also added to MIPS32 but were removed in // MIPS32r6 and MIPS64r6. class INSN_MIPS3_32_NOT_32R6_64R6 { list<Predicate> InsnPredicates = [HasMips3_32, NotMips32r6, NotMips64r6]; + list<Predicate> EncodingPredicates = [HasStdEnc]; } // The portions of MIPS-III that were also added to MIPS32 -class INSN_MIPS3_32R2 { list<Predicate> InsnPredicates = [HasMips3_32r2]; } +class INSN_MIPS3_32R2 { + list<Predicate> InsnPredicates = [HasMips3_32r2]; + list<Predicate> EncodingPredicates = [HasStdEnc]; +} // The portions of MIPS-IV that were also added to MIPS32. -class INSN_MIPS4_32 { list <Predicate> InsnPredicates = [HasMips4_32]; } +class INSN_MIPS4_32 { + list <Predicate> InsnPredicates = [HasMips4_32]; + list<Predicate> EncodingPredicates = [HasStdEnc]; +} // The portions of MIPS-IV that were also added to MIPS32 but were removed in // MIPS32r6 and MIPS64r6. class INSN_MIPS4_32_NOT_32R6_64R6 { list<Predicate> InsnPredicates = [HasMips4_32, NotMips32r6, NotMips64r6]; + list<Predicate> EncodingPredicates = [HasStdEnc]; } // The portions of MIPS-IV that were also added to MIPS32r2 but were removed in // MIPS32r6 and MIPS64r6. class INSN_MIPS4_32R2_NOT_32R6_64R6 { list<Predicate> InsnPredicates = [HasMips4_32r2, NotMips32r6, NotMips64r6]; + list<Predicate> EncodingPredicates = [HasStdEnc]; } // The portions of MIPS-IV that were also added to MIPS32r2. class INSN_MIPS4_32R2 { list<Predicate> InsnPredicates = [HasMips4_32r2]; + list<Predicate> EncodingPredicates = [HasStdEnc]; } // The portions of MIPS-V that were also added to MIPS32r2 but were removed in // MIPS32r6 and MIPS64r6. class INSN_MIPS5_32R2_NOT_32R6_64R6 { list<Predicate> InsnPredicates = [HasMips5_32r2, NotMips32r6, NotMips64r6]; + list<Predicate> EncodingPredicates = [HasStdEnc]; } class ASE_CNMIPS { - list<Predicate> InsnPredicates = [HasCnMips]; + list<Predicate> ASEPredicate = [HasCnMips]; } class NOT_ASE_CNMIPS { - list<Predicate> InsnPredicates = [NotCnMips]; + list<Predicate> ASEPredicate = [NotCnMips]; } class ASE_MIPS64_CNMIPS { - list<Predicate> InsnPredicates = [HasMips64, HasCnMips]; + list<Predicate> ASEPredicate = [HasMips64, HasCnMips]; } class ASE_MSA { - list<Predicate> InsnPredicates = [HasMSA]; + list<Predicate> ASEPredicate = [HasMSA]; } class ASE_MSA_NOT_MSA64 { - list<Predicate> InsnPredicates = [HasMSA, NotMips64]; + list<Predicate> ASEPredicate = [HasMSA, NotMips64]; } class ASE_MSA64 { - list<Predicate> InsnPredicates = [HasMSA, HasMips64]; + list<Predicate> ASEPredicate = [HasMSA, HasMips64]; } class ASE_MT { - list <Predicate> InsnPredicates = [HasMT]; + list <Predicate> ASEPredicate = [HasMT]; +} + +class ASE_CRC { + list <Predicate> ASEPredicate = [HasCRC]; +} + +class ASE_VIRT { + list <Predicate> ASEPredicate = [HasVirt]; +} + +class ASE_GINV { + list <Predicate> ASEPredicate = [HasGINV]; } // Class used for separating microMIPSr6 and microMIPS (r3) instruction. // It can be used only on instructions that doesn't inherit PredicateControl. class ISA_MICROMIPS_NOT_32R6 : PredicateControl { - let InsnPredicates = [InMicroMips, NotMips32r6]; + let InsnPredicates = [NotMips32r6]; + let EncodingPredicates = [InMicroMips]; } class ASE_NOT_DSP { - list<Predicate> InsnPredicates = [NotDSP]; + list<Predicate> ASEPredicate = [NotDSP]; } class MADD4 { @@ -410,11 +495,13 @@ class ABI_NOT_N64 { list<Predicate> AdditionalPredicates = [IsNotN64]; } +class FPOP_FUSION_FAST { + list <Predicate> AdditionalPredicates = [AllowFPOpFusion]; +} + //===----------------------------------------------------------------------===// -class MipsPat<dag pattern, dag result> : Pat<pattern, result>, PredicateControl { - let EncodingPredicates = [HasStdEnc]; -} +class MipsPat<dag pattern, dag result> : Pat<pattern, result>, PredicateControl; class MipsInstAlias<string Asm, dag Result, bit Emit = 0b1> : InstAlias<Asm, Result, Emit>, PredicateControl; @@ -1044,6 +1131,15 @@ def MipsMemSimm16AsmOperand : AsmOperandClass { let DiagnosticType = "MemSImm16"; } +def MipsMemSimmPtrAsmOperand : AsmOperandClass { + let Name = "MemOffsetSimmPtr"; + let SuperClasses = [MipsMemAsmOperand]; + let RenderMethod = "addMemOperands"; + let ParserMethod = "parseMemOperand"; + let PredicateMethod = "isMemWithPtrSizeOffset"; + let DiagnosticType = "MemSImmPtr"; +} + def MipsInvertedImmoperand : AsmOperandClass { let Name = "InvNum"; let RenderMethod = "addImmOperands"; @@ -1117,6 +1213,10 @@ def mem_simm16 : mem_generic { let ParserMatchClass = MipsMemSimm16AsmOperand; } +def mem_simmptr : mem_generic { + let ParserMatchClass = MipsMemSimmPtrAsmOperand; +} + def mem_ea : Operand<iPTR> { let PrintMethod = "printMemOperandEA"; let MIOperandInfo = (ops ptr_rc, simm16); @@ -1333,6 +1433,7 @@ class LoadMemory<string opstr, DAGOperand RO, DAGOperand MO, [(set RO:$rt, (OpNode Addr:$addr))], Itin, FrmI, opstr> { let DecoderMethod = "DecodeMem"; let canFoldAsLoad = 1; + string BaseOpcode = opstr; let mayLoad = 1; } @@ -1346,6 +1447,7 @@ class StoreMemory<string opstr, DAGOperand RO, DAGOperand MO, InstSE<(outs), (ins RO:$rt, MO:$addr), !strconcat(opstr, "\t$rt, $addr"), [(OpNode RO:$rt, Addr:$addr)], Itin, FrmI, opstr> { let DecoderMethod = "DecodeMem"; + string BaseOpcode = opstr; let mayStore = 1; } @@ -1363,6 +1465,7 @@ class LoadLeftRight<string opstr, SDNode OpNode, RegisterOperand RO, [(set RO:$rt, (OpNode addr:$addr, RO:$src))], Itin, FrmI> { let DecoderMethod = "DecodeMem"; string Constraints = "$src = $rt"; + let BaseOpcode = opstr; } class StoreLeftRight<string opstr, SDNode OpNode, RegisterOperand RO, @@ -1370,6 +1473,7 @@ class StoreLeftRight<string opstr, SDNode OpNode, RegisterOperand RO, InstSE<(outs), (ins RO:$rt, mem:$addr), !strconcat(opstr, "\t$rt, $addr"), [(OpNode RO:$rt, addr:$addr)], Itin, FrmI> { let DecoderMethod = "DecodeMem"; + let BaseOpcode = opstr; } // COP2 Load/Store @@ -1540,13 +1644,14 @@ let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, hasDelaySlot = 1, PseudoSE<(outs), (ins calltarget:$target), [], II_J>, PseudoInstExpansion<(JumpInst Opnd:$target)>; - class TailCallReg<RegisterOperand RO> : - PseudoSE<(outs), (ins RO:$rs), [(MipsTailCall RO:$rs)], II_JR>; + class TailCallReg<Instruction JumpInst, RegisterOperand RO> : + PseudoSE<(outs), (ins RO:$rs), [(MipsTailCall RO:$rs)], II_JR>, + PseudoInstExpansion<(JumpInst RO:$rs)>; } -class BAL_BR_Pseudo<Instruction RealInst> : - PseudoSE<(outs), (ins brtarget:$offset), [], II_BCCZAL>, - PseudoInstExpansion<(RealInst ZERO, brtarget:$offset)> { +class BAL_BR_Pseudo<Instruction RealInst, DAGOperand opnd> : + PseudoSE<(outs), (ins opnd:$offset), [], II_BCCZAL>, + PseudoInstExpansion<(RealInst ZERO, opnd:$offset)> { let isBranch = 1; let isTerminator = 1; let isBarrier = 1; @@ -1588,8 +1693,8 @@ class SYNC_FT<string 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"), [], +class SYNCI_FT<string opstr, DAGOperand MO> : + InstSE<(outs), (ins MO:$addr), !strconcat(opstr, "\t$addr"), [], II_SYNCI, FrmOther, opstr> { let hasSideEffects = 1; let DecoderMethod = "DecodeSyncI"; @@ -1661,6 +1766,7 @@ class MoveFromLOHI<string opstr, RegisterOperand RO, Register UseReg>: FrmR, opstr> { let Uses = [UseReg]; let hasSideEffects = 0; + let isMoveReg = 1; } class PseudoMTLOHI<RegisterClass DstRC, RegisterClass SrcRC> @@ -1673,6 +1779,7 @@ class MoveToLOHI<string opstr, RegisterOperand RO, list<Register> DefRegs>: FrmR, opstr> { let Defs = DefRegs; let hasSideEffects = 0; + let isMoveReg = 1; } class EffectiveAddress<string opstr, RegisterOperand RO> : @@ -1711,8 +1818,8 @@ class SubwordSwap<string opstr, RegisterOperand RO, // Read Hardware class ReadHardware<RegisterOperand CPURegOperand, RegisterOperand RO> : - InstSE<(outs CPURegOperand:$rt), (ins RO:$rd), "rdhwr\t$rt, $rd", [], - II_RDHWR, FrmR, "rdhwr">; + InstSE<(outs CPURegOperand:$rt), (ins RO:$rd, uimm8:$sel), + "rdhwr\t$rt, $rd, $sel", [], II_RDHWR, FrmR, "rdhwr">; // Ext and Ins class ExtBase<string opstr, RegisterOperand RO, Operand PosOpnd, @@ -1721,7 +1828,7 @@ class ExtBase<string opstr, RegisterOperand RO, Operand PosOpnd, InstSE<(outs RO:$rt), (ins RO:$rs, PosOpnd:$pos, SizeOpnd:$size), !strconcat(opstr, "\t$rt, $rs, $pos, $size"), [(set RO:$rt, (Op RO:$rs, PosImm:$pos, SizeImm:$size))], II_EXT, - FrmR, opstr>, ISA_MIPS32R2; + FrmR, opstr>; // 'ins' and its' 64 bit variants are matched by C++ code. class InsBase<string opstr, RegisterOperand RO, Operand PosOpnd, @@ -1730,7 +1837,7 @@ class InsBase<string opstr, RegisterOperand RO, Operand PosOpnd, !strconcat(opstr, "\t$rt, $rs, $pos, $size"), [(set RO:$rt, (null_frag RO:$rs, PosImm:$pos, SizeImm:$size, RO:$src))], - II_INS, FrmR, opstr>, ISA_MIPS32R2 { + II_INS, FrmR, opstr> { let Constraints = "$src = $rt"; } @@ -1739,11 +1846,37 @@ class Atomic2Ops<PatFrag Op, RegisterClass DRC> : PseudoSE<(outs DRC:$dst), (ins PtrRC:$ptr, DRC:$incr), [(set DRC:$dst, (Op iPTR:$ptr, DRC:$incr))]>; +class Atomic2OpsPostRA<RegisterClass RC> : + PseudoSE<(outs RC:$dst), (ins PtrRC:$ptr, RC:$incr), []> { + let mayLoad = 1; + let mayStore = 1; +} + +class Atomic2OpsSubwordPostRA<RegisterClass RC> : + PseudoSE<(outs RC:$dst), (ins PtrRC:$ptr, RC:$incr, RC:$mask, RC:$mask2, + RC:$shiftamnt), []>; + // Atomic Compare & Swap. +// Atomic compare and swap is lowered into two stages. The first stage happens +// during ISelLowering, which produces the PostRA version of this instruction. 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 AtomicCmpSwapPostRA<RegisterClass RC> : + PseudoSE<(outs RC:$dst), (ins PtrRC:$ptr, RC:$cmp, RC:$swap), []> { + let mayLoad = 1; + let mayStore = 1; +} + +class AtomicCmpSwapSubwordPostRA<RegisterClass RC> : + PseudoSE<(outs RC:$dst), (ins PtrRC:$ptr, RC:$mask, RC:$ShiftCmpVal, + RC:$mask2, RC:$ShiftNewVal, RC:$ShiftAmt), []> { + let mayLoad = 1; + let mayStore = 1; +} + + 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> { @@ -1762,12 +1895,16 @@ class SCBase<string opstr, RegisterOperand RO> : 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>; + !strconcat(asmstr, "\t$rt, $rd, $sel"), [], itin, FrmFR> { + let BaseOpcode = asmstr; +} 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>; + !strconcat(asmstr, "\t$rt, $rd, $sel"), [], itin, FrmFR> { + let BaseOpcode = asmstr; +} class TrapBase<Instruction RealInst> : PseudoSE<(outs), (ins), [(trap)], II_TRAP>, @@ -1825,8 +1962,36 @@ let usesCustomInserter = 1 in { def ATOMIC_CMP_SWAP_I8 : AtomicCmpSwap<atomic_cmp_swap_8, GPR32>; def ATOMIC_CMP_SWAP_I16 : AtomicCmpSwap<atomic_cmp_swap_16, GPR32>; def ATOMIC_CMP_SWAP_I32 : AtomicCmpSwap<atomic_cmp_swap_32, GPR32>; + } +def ATOMIC_LOAD_ADD_I8_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; +def ATOMIC_LOAD_ADD_I16_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; +def ATOMIC_LOAD_ADD_I32_POSTRA : Atomic2OpsPostRA<GPR32>; +def ATOMIC_LOAD_SUB_I8_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; +def ATOMIC_LOAD_SUB_I16_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; +def ATOMIC_LOAD_SUB_I32_POSTRA : Atomic2OpsPostRA<GPR32>; +def ATOMIC_LOAD_AND_I8_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; +def ATOMIC_LOAD_AND_I16_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; +def ATOMIC_LOAD_AND_I32_POSTRA : Atomic2OpsPostRA<GPR32>; +def ATOMIC_LOAD_OR_I8_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; +def ATOMIC_LOAD_OR_I16_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; +def ATOMIC_LOAD_OR_I32_POSTRA : Atomic2OpsPostRA<GPR32>; +def ATOMIC_LOAD_XOR_I8_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; +def ATOMIC_LOAD_XOR_I16_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; +def ATOMIC_LOAD_XOR_I32_POSTRA : Atomic2OpsPostRA<GPR32>; +def ATOMIC_LOAD_NAND_I8_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; +def ATOMIC_LOAD_NAND_I16_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; +def ATOMIC_LOAD_NAND_I32_POSTRA : Atomic2OpsPostRA<GPR32>; + +def ATOMIC_SWAP_I8_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; +def ATOMIC_SWAP_I16_POSTRA : Atomic2OpsSubwordPostRA<GPR32>; +def ATOMIC_SWAP_I32_POSTRA : Atomic2OpsPostRA<GPR32>; + +def ATOMIC_CMP_SWAP_I8_POSTRA : AtomicCmpSwapSubwordPostRA<GPR32>; +def ATOMIC_CMP_SWAP_I16_POSTRA : AtomicCmpSwapSubwordPostRA<GPR32>; +def ATOMIC_CMP_SWAP_I32_POSTRA : AtomicCmpSwapPostRA<GPR32>; + /// Pseudo instructions for loading and storing accumulator registers. let isPseudo = 1, isCodeGenOnly = 1, hasNoSchedulingInfo = 1 in { def LOAD_ACC64 : Load<"", ACC64>; @@ -1856,69 +2021,72 @@ def LONG_BRANCH_ADDiu : PseudoSE<(outs GPR32Opnd:$dst), let AdditionalPredicates = [NotInMicroMips] in { def ADDiu : MMRel, StdMMR6Rel, ArithLogicI<"addiu", simm16_relaxed, GPR32Opnd, II_ADDIU, immSExt16, add>, - ADDI_FM<0x9>, IsAsCheapAsAMove; + ADDI_FM<0x9>, IsAsCheapAsAMove, ISA_MIPS1; def ANDi : MMRel, StdMMR6Rel, ArithLogicI<"andi", uimm16, GPR32Opnd, II_ANDI, immZExt16, and>, - ADDI_FM<0xc>; + ADDI_FM<0xc>, ISA_MIPS1; def ORi : MMRel, StdMMR6Rel, ArithLogicI<"ori", uimm16, GPR32Opnd, II_ORI, immZExt16, or>, - ADDI_FM<0xd>; + ADDI_FM<0xd>, ISA_MIPS1; 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; -let AdditionalPredicates = [NotInMicroMips] in { + ADDI_FM<0xe>, ISA_MIPS1; + 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>; + SLTI_FM<0xa>, ISA_MIPS1; def SLTiu : MMRel, SetCC_I<"sltiu", setult, simm16, immSExt16, GPR32Opnd>, - SLTI_FM<0xb>; -} -def LUi : MMRel, LoadUpper<"lui", GPR32Opnd, uimm16_relaxed>, LUI_FM; -let AdditionalPredicates = [NotInMicroMips] in { + SLTI_FM<0xb>, ISA_MIPS1; + + def LUi : MMRel, LoadUpper<"lui", GPR32Opnd, uimm16_relaxed>, LUI_FM, + ISA_MIPS1; + /// Arithmetic Instructions (3-Operand, R-Type) def ADDu : MMRel, StdMMR6Rel, ArithLogicR<"addu", GPR32Opnd, 1, II_ADDU, add>, - ADD_FM<0, 0x21>; + ADD_FM<0, 0x21>, ISA_MIPS1; 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, 1, II_ADD>, ADD_FM<0, 0x20>; -def SUB : MMRel, StdMMR6Rel, ArithLogicR<"sub", GPR32Opnd, 0, II_SUB>, ADD_FM<0, 0x22>; -let AdditionalPredicates = [NotInMicroMips] in { - def SLT : MMRel, SetCC_R<"slt", setlt, GPR32Opnd>, ADD_FM<0, 0x2a>; - def SLTu : MMRel, SetCC_R<"sltu", setult, GPR32Opnd>, ADD_FM<0, 0x2b>; + ADD_FM<0, 0x23>, ISA_MIPS1; + + 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, 1, II_ADD>, + ADD_FM<0, 0x20>, ISA_MIPS1; + def SUB : MMRel, StdMMR6Rel, ArithLogicR<"sub", GPR32Opnd, 0, II_SUB>, + ADD_FM<0, 0x22>, ISA_MIPS1; + + def SLT : MMRel, SetCC_R<"slt", setlt, GPR32Opnd>, ADD_FM<0, 0x2a>, + ISA_MIPS1; + def SLTu : MMRel, SetCC_R<"sltu", setult, GPR32Opnd>, ADD_FM<0, 0x2b>, + ISA_MIPS1; def AND : MMRel, StdMMR6Rel, ArithLogicR<"and", GPR32Opnd, 1, II_AND, and>, - ADD_FM<0, 0x24>; + ADD_FM<0, 0x24>, ISA_MIPS1; def OR : MMRel, StdMMR6Rel, ArithLogicR<"or", GPR32Opnd, 1, II_OR, or>, - ADD_FM<0, 0x25>; + ADD_FM<0, 0x25>, ISA_MIPS1; 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>; + ADD_FM<0, 0x26>, ISA_MIPS1; + def NOR : MMRel, StdMMR6Rel, LogicNOR<"nor", GPR32Opnd>, ADD_FM<0, 0x27>, + ISA_MIPS1; } -/// Shift Instructions -let AdditionalPredicates = [NotInMicroMips] in { -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>, - SRLV_FM<4, 0>; -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 let AdditionalPredicates = [NotInMicroMips] in { + /// Shift Instructions + def SLL : MMRel, shift_rotate_imm<"sll", uimm5, GPR32Opnd, II_SLL, shl, + immZExt5>, SRA_FM<0, 0>, ISA_MIPS1; + def SRL : MMRel, shift_rotate_imm<"srl", uimm5, GPR32Opnd, II_SRL, srl, + immZExt5>, SRA_FM<2, 0>, ISA_MIPS1; + def SRA : MMRel, shift_rotate_imm<"sra", uimm5, GPR32Opnd, II_SRA, sra, + immZExt5>, SRA_FM<3, 0>, ISA_MIPS1; + def SLLV : MMRel, shift_rotate_reg<"sllv", GPR32Opnd, II_SLLV, shl>, + SRLV_FM<4, 0>, ISA_MIPS1; + def SRLV : MMRel, shift_rotate_reg<"srlv", GPR32Opnd, II_SRLV, srl>, + SRLV_FM<6, 0>, ISA_MIPS1; + def SRAV : MMRel, shift_rotate_reg<"srav", GPR32Opnd, II_SRAV, sra>, + SRLV_FM<7, 0>, ISA_MIPS1; + + // Rotate Instructions def ROTR : MMRel, shift_rotate_imm<"rotr", uimm5, GPR32Opnd, II_ROTR, rotr, immZExt5>, SRA_FM<2, 1>, ISA_MIPS32R2; @@ -1928,39 +2096,35 @@ let AdditionalPredicates = [NotInMicroMips] in { /// Load and Store Instructions /// aligned -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 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 LB : LoadMemory<"lb", GPR32Opnd, mem_simmptr, sextloadi8, II_LB>, MMRel, + LW_FM<0x20>, ISA_MIPS1; + def LBu : LoadMemory<"lbu", GPR32Opnd, mem_simmptr, zextloadi8, II_LBU, + addrDefault>, MMRel, LW_FM<0x24>, ISA_MIPS1; + def LH : LoadMemory<"lh", GPR32Opnd, mem_simmptr, sextloadi16, II_LH, + addrDefault>, MMRel, LW_FM<0x21>, ISA_MIPS1; + def LHu : LoadMemory<"lhu", GPR32Opnd, mem_simmptr, zextloadi16, II_LHU>, + MMRel, LW_FM<0x25>, ISA_MIPS1; 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>; -def SH : Store<"sh", GPR32Opnd, truncstorei16, II_SH>, MMRel, LW_FM<0x29>; -let AdditionalPredicates = [NotInMicroMips] in { -def SW : Store<"sw", GPR32Opnd, store, II_SW>, MMRel, LW_FM<0x2b>; + LW_FM<0x23>, ISA_MIPS1; + def SB : StdMMR6Rel, Store<"sb", GPR32Opnd, truncstorei8, II_SB>, MMRel, + LW_FM<0x28>, ISA_MIPS1; + def SH : Store<"sh", GPR32Opnd, truncstorei16, II_SH>, MMRel, LW_FM<0x29>, + ISA_MIPS1; + def SW : Store<"sw", GPR32Opnd, store, II_SW>, MMRel, LW_FM<0x2b>, ISA_MIPS1; } /// load/store left/right -let EncodingPredicates = []<Predicate>, // FIXME: Lack of HasStdEnc is probably a bug - AdditionalPredicates = [NotInMicroMips] in { -def LWL : LoadLeftRight<"lwl", MipsLWL, GPR32Opnd, II_LWL>, LW_FM<0x22>, +let AdditionalPredicates = [NotInMicroMips] in { +def LWL : MMRel, LoadLeftRight<"lwl", MipsLWL, GPR32Opnd, II_LWL>, LW_FM<0x22>, ISA_MIPS1_NOT_32R6_64R6; -def LWR : LoadLeftRight<"lwr", MipsLWR, GPR32Opnd, II_LWR>, LW_FM<0x26>, +def LWR : MMRel, LoadLeftRight<"lwr", MipsLWR, GPR32Opnd, II_LWR>, LW_FM<0x26>, ISA_MIPS1_NOT_32R6_64R6; -def SWL : StoreLeftRight<"swl", MipsSWL, GPR32Opnd, II_SWL>, LW_FM<0x2a>, +def SWL : MMRel, StoreLeftRight<"swl", MipsSWL, GPR32Opnd, II_SWL>, LW_FM<0x2a>, ISA_MIPS1_NOT_32R6_64R6; -def SWR : StoreLeftRight<"swr", MipsSWR, GPR32Opnd, II_SWR>, LW_FM<0x2e>, +def SWR : MMRel, StoreLeftRight<"swr", MipsSWR, GPR32Opnd, II_SWR>, LW_FM<0x2e>, ISA_MIPS1_NOT_32R6_64R6; -} -let AdditionalPredicates = [NotInMicroMips] in { // COP2 Memory Instructions def LWC2 : StdMMR6Rel, LW_FT2<"lwc2", COP2Opnd, II_LWC2, load>, LW_FM<0x32>, ISA_MIPS1_NOT_32R6_64R6; @@ -1973,63 +2137,68 @@ def SDC2 : StdMMR6Rel, SW_FT2<"sdc2", COP2Opnd, II_SDC2, store>, // COP3 Memory Instructions let DecoderNamespace = "COP3_" in { - 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 LWC3 : LW_FT3<"lwc3", COP3Opnd, II_LWC3, load>, LW_FM<0x33>, + ISA_MIPS1_NOT_32R6_64R6, NOT_ASE_CNMIPS; + def SWC3 : SW_FT3<"swc3", COP3Opnd, II_SWC3, store>, LW_FM<0x3b>, + ISA_MIPS1_NOT_32R6_64R6, NOT_ASE_CNMIPS; def LDC3 : LW_FT3<"ldc3", COP3Opnd, II_LDC3, load>, LW_FM<0x37>, - ISA_MIPS2; + ISA_MIPS2, NOT_ASE_CNMIPS; def SDC3 : SW_FT3<"sdc3", COP3Opnd, II_SDC3, store>, LW_FM<0x3f>, - ISA_MIPS2; + ISA_MIPS2, NOT_ASE_CNMIPS; } def SYNC : MMRel, StdMMR6Rel, SYNC_FT<"sync">, SYNC_FM, ISA_MIPS2; - def SYNCI : MMRel, StdMMR6Rel, SYNCI_FT<"synci">, SYNCI_FM, ISA_MIPS32R2; + def SYNCI : MMRel, StdMMR6Rel, SYNCI_FT<"synci", mem_simm16>, SYNCI_FM, + ISA_MIPS32R2; } let AdditionalPredicates = [NotInMicroMips] in { - 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 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, II_TEQI>, TEQI_FM<0xc>, + ISA_MIPS2_NOT_32R6_64R6; + def TGEI : MMRel, TEQI_FT<"tgei", GPR32Opnd, II_TGEI>, TEQI_FM<0x8>, + ISA_MIPS2_NOT_32R6_64R6; + def TGEIU : MMRel, TEQI_FT<"tgeiu", GPR32Opnd, II_TGEIU>, TEQI_FM<0x9>, + ISA_MIPS2_NOT_32R6_64R6; + def TLTI : MMRel, TEQI_FT<"tlti", GPR32Opnd, II_TLTI>, TEQI_FM<0xa>, + ISA_MIPS2_NOT_32R6_64R6; + def TTLTIU : MMRel, TEQI_FT<"tltiu", GPR32Opnd, II_TTLTIU>, TEQI_FM<0xb>, + ISA_MIPS2_NOT_32R6_64R6; + def TNEI : MMRel, TEQI_FT<"tnei", GPR32Opnd, II_TNEI>, TEQI_FM<0xe>, + ISA_MIPS2_NOT_32R6_64R6; } -def TEQI : MMRel, TEQI_FT<"teqi", GPR32Opnd, II_TEQI>, TEQI_FM<0xc>, - ISA_MIPS2_NOT_32R6_64R6; -def TGEI : MMRel, TEQI_FT<"tgei", GPR32Opnd, II_TGEI>, TEQI_FM<0x8>, - ISA_MIPS2_NOT_32R6_64R6; -def TGEIU : MMRel, TEQI_FT<"tgeiu", GPR32Opnd, II_TGEIU>, TEQI_FM<0x9>, - ISA_MIPS2_NOT_32R6_64R6; -def TLTI : MMRel, TEQI_FT<"tlti", GPR32Opnd, II_TLTI>, TEQI_FM<0xa>, - ISA_MIPS2_NOT_32R6_64R6; -def TTLTIU : MMRel, TEQI_FT<"tltiu", GPR32Opnd, II_TTLTIU>, TEQI_FM<0xb>, - ISA_MIPS2_NOT_32R6_64R6; -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 TRAP : TrapBase<BREAK>; -let AdditionalPredicates = [NotInMicroMips] in { -def SDBBP : MMRel, SYS_FT<"sdbbp", uimm20, II_SDBBP>, SDBBP_FM, ISA_MIPS32_NOT_32R6_64R6; -} + def BREAK : MMRel, StdMMR6Rel, BRK_FT<"break">, BRK_FM<0xd>, ISA_MIPS1; + def SYSCALL : MMRel, SYS_FT<"syscall", uimm20, II_SYSCALL>, SYS_FM<0xc>, + ISA_MIPS1; + def TRAP : TrapBase<BREAK>, ISA_MIPS1; + 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", II_ERET>, ER_FM<0x18, 0x0>, INSN_MIPS3_32; - def ERETNC : MMRel, ER_FT<"eretnc", II_ERETNC>, ER_FM<0x18, 0x1>, ISA_MIPS32R5; + 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, II_EI>, EI_FM<1>, ISA_MIPS32R2; - def DI : MMRel, StdMMR6Rel, DEI_FT<"di", GPR32Opnd, II_DI>, 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; + def WAIT : MMRel, StdMMR6Rel, WAIT_FT<"wait">, WAIT_FM, INSN_MIPS3_32; } let AdditionalPredicates = [NotInMicroMips] in { @@ -2037,75 +2206,86 @@ let AdditionalPredicates = [NotInMicroMips] in { 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 +let AdditionalPredicates = [NotInMicroMips, RelocNotPIC] in def J : MMRel, JumpFJ<jmptarget, "j", br, bb, "j">, FJ<2>, - AdditionalRequires<[RelocNotPIC, NotInMicroMips]>, 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>; + IsBranch, ISA_MIPS1; + +let AdditionalPredicates = [NotInMicroMips] in { +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>, + ISA_MIPS1; def BEQL : MMRel, CBranchLikely<"beql", brtarget, GPR32Opnd>, BEQ_FM<20>, ISA_MIPS2_NOT_32R6_64R6; -def BNE : MMRel, CBranch<"bne", brtarget, setne, GPR32Opnd>, BEQ_FM<5>; +def BNE : MMRel, CBranch<"bne", brtarget, setne, GPR32Opnd>, BEQ_FM<5>, + ISA_MIPS1; def BNEL : MMRel, CBranchLikely<"bnel", brtarget, GPR32Opnd>, BEQ_FM<21>, ISA_MIPS2_NOT_32R6_64R6; def BGEZ : MMRel, CBranchZero<"bgez", brtarget, setge, GPR32Opnd>, - BGEZ_FM<1, 1>; + BGEZ_FM<1, 1>, ISA_MIPS1; def BGEZL : MMRel, CBranchZeroLikely<"bgezl", brtarget, GPR32Opnd>, BGEZ_FM<1, 3>, ISA_MIPS2_NOT_32R6_64R6; def BGTZ : MMRel, CBranchZero<"bgtz", brtarget, setgt, GPR32Opnd>, - BGEZ_FM<7, 0>; + BGEZ_FM<7, 0>, ISA_MIPS1; def BGTZL : MMRel, CBranchZeroLikely<"bgtzl", brtarget, GPR32Opnd>, BGEZ_FM<23, 0>, ISA_MIPS2_NOT_32R6_64R6; def BLEZ : MMRel, CBranchZero<"blez", brtarget, setle, GPR32Opnd>, - BGEZ_FM<6, 0>; + BGEZ_FM<6, 0>, ISA_MIPS1; def BLEZL : MMRel, CBranchZeroLikely<"blezl", brtarget, GPR32Opnd>, BGEZ_FM<22, 0>, ISA_MIPS2_NOT_32R6_64R6; def BLTZ : MMRel, CBranchZero<"bltz", brtarget, setlt, GPR32Opnd>, - BGEZ_FM<1, 0>; + BGEZ_FM<1, 0>, ISA_MIPS1; def BLTZL : MMRel, CBranchZeroLikely<"bltzl", brtarget, GPR32Opnd>, BGEZ_FM<1, 2>, ISA_MIPS2_NOT_32R6_64R6; -def B : UncondBranch<BEQ, brtarget>, - AdditionalRequires<[NotInMicroMips]>; +def B : UncondBranch<BEQ, brtarget>, ISA_MIPS1; + +def JAL : MMRel, JumpLink<"jal", calltarget>, FJ<3>, ISA_MIPS1; -def JAL : MMRel, JumpLink<"jal", calltarget>, FJ<3>; -let AdditionalPredicates = [NotInMicroMips] in { - def JALR : JumpLinkReg<"jalr", GPR32Opnd>, JALR_FM; - def JALRPseudo : JumpLinkRegPseudo<GPR32Opnd, JALR, RA>; } -def JALX : MMRel, JumpLink<"jalx", calltarget>, FJ<0x1D>, - ISA_MIPS32_NOT_32R6_64R6; -def BGEZAL : MMRel, BGEZAL_FT<"bgezal", brtarget, GPR32Opnd>, BGEZAL_FM<0x11>, - ISA_MIPS1_NOT_32R6_64R6; -def BGEZALL : MMRel, BGEZAL_FT<"bgezall", brtarget, GPR32Opnd>, - BGEZAL_FM<0x13>, ISA_MIPS2_NOT_32R6_64R6; -def BLTZAL : MMRel, BGEZAL_FT<"bltzal", brtarget, GPR32Opnd>, BGEZAL_FM<0x10>, - ISA_MIPS1_NOT_32R6_64R6; -def BLTZALL : MMRel, BGEZAL_FT<"bltzall", brtarget, GPR32Opnd>, - BGEZAL_FM<0x12>, ISA_MIPS2_NOT_32R6_64R6; -def BAL_BR : BAL_BR_Pseudo<BGEZAL>; +let AdditionalPredicates = [NotInMicroMips, NoIndirectJumpGuards] in { + def JALR : JumpLinkReg<"jalr", GPR32Opnd>, JALR_FM, ISA_MIPS1; + def JALRPseudo : JumpLinkRegPseudo<GPR32Opnd, JALR, RA>, ISA_MIPS1; +} +let AdditionalPredicates = [NotInMicroMips] in { + def JALX : MMRel, JumpLink<"jalx", calltarget>, FJ<0x1D>, + ISA_MIPS32_NOT_32R6_64R6; + def BGEZAL : MMRel, BGEZAL_FT<"bgezal", brtarget, GPR32Opnd>, BGEZAL_FM<0x11>, + ISA_MIPS1_NOT_32R6_64R6; + def BGEZALL : MMRel, BGEZAL_FT<"bgezall", brtarget, GPR32Opnd>, + BGEZAL_FM<0x13>, ISA_MIPS2_NOT_32R6_64R6; + def BLTZAL : MMRel, BGEZAL_FT<"bltzal", brtarget, GPR32Opnd>, BGEZAL_FM<0x10>, + ISA_MIPS1_NOT_32R6_64R6; + def BLTZALL : MMRel, BGEZAL_FT<"bltzall", brtarget, GPR32Opnd>, + BGEZAL_FM<0x12>, ISA_MIPS2_NOT_32R6_64R6; + def BAL_BR : BAL_BR_Pseudo<BGEZAL, brtarget>, ISA_MIPS1; +} let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips] in { - def TAILCALL : TailCall<J, jmptarget>; + def TAILCALL : TailCall<J, jmptarget>, ISA_MIPS1; } - -def TAILCALLREG : TailCallReg<GPR32Opnd>; +let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips, + NoIndirectJumpGuards] in + def TAILCALLREG : TailCallReg<JR, GPR32Opnd>, ISA_MIPS1_NOT_32R6_64R6; // Indirect branches are matched as PseudoIndirectBranch/PseudoIndirectBranch64 // then are expanded to JR, JR64, JALR, or JALR64 depending on the ISA. -class PseudoIndirectBranchBase<RegisterOperand RO> : +class PseudoIndirectBranchBase<Instruction JumpInst, RegisterOperand RO> : MipsPseudo<(outs), (ins RO:$rs), [(brind RO:$rs)], - II_IndirectBranchPseudo> { + II_IndirectBranchPseudo>, + PseudoInstExpansion<(JumpInst RO:$rs)> { let isTerminator=1; let isBarrier=1; let hasDelaySlot = 1; let isBranch = 1; let isIndirectBranch = 1; bit isCTI = 1; - let Predicates = [NotInMips16Mode]; } -def PseudoIndirectBranch : PseudoIndirectBranchBase<GPR32Opnd>; +let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips, + NoIndirectJumpGuards] in + def PseudoIndirectBranch : PseudoIndirectBranchBase<JR, GPR32Opnd>, + ISA_MIPS1_NOT_32R6_64R6; // Return instructions are matched as a RetRA instruction, then are expanded // into PseudoReturn/PseudoReturn64 after register allocation. Finally, @@ -2147,64 +2327,61 @@ let Uses = [V0, V1], isTerminator = 1, isReturn = 1, isBarrier = 1, isCTI = 1 in } /// Multiply and Divide Instructions. -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; let AdditionalPredicates = [NotInMicroMips] in { + 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; -} -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>, - ISA_MIPS1_NOT_32R6_64R6; -let EncodingPredicates = []<Predicate>, // FIXME: Lack of HasStdEnc is probably a bug - AdditionalPredicates = [NotInMicroMips] in { -def MFHI : MMRel, MoveFromLOHI<"mfhi", GPR32Opnd, AC0>, MFLO_FM<0x10>, - ISA_MIPS1_NOT_32R6_64R6; -def MFLO : MMRel, MoveFromLOHI<"mflo", GPR32Opnd, AC0>, MFLO_FM<0x12>, - 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>, + ISA_MIPS1_NOT_32R6_64R6; + def MFHI : MMRel, MoveFromLOHI<"mfhi", GPR32Opnd, AC0>, MFLO_FM<0x10>, + ISA_MIPS1_NOT_32R6_64R6; + def MFLO : MMRel, MoveFromLOHI<"mflo", GPR32Opnd, AC0>, MFLO_FM<0x12>, + ISA_MIPS1_NOT_32R6_64R6; -/// Sign Ext In Register Instructions. -def SEB : MMRel, StdMMR6Rel, SignExtInReg<"seb", i8, GPR32Opnd, II_SEB>, - SEB_FM<0x10, 0x20>, ISA_MIPS32R2; -def SEH : MMRel, StdMMR6Rel, SignExtInReg<"seh", i16, GPR32Opnd, II_SEH>, - SEB_FM<0x18, 0x20>, ISA_MIPS32R2; + /// Sign Ext In Register Instructions. + def SEB : MMRel, StdMMR6Rel, SignExtInReg<"seb", i8, GPR32Opnd, II_SEB>, + SEB_FM<0x10, 0x20>, ISA_MIPS32R2; + def SEH : MMRel, StdMMR6Rel, SignExtInReg<"seh", i16, GPR32Opnd, II_SEH>, + SEB_FM<0x18, 0x20>, ISA_MIPS32R2; -/// Count Leading -def CLZ : MMRel, CountLeading0<"clz", GPR32Opnd, II_CLZ>, CLO_FM<0x20>, - ISA_MIPS32_NOT_32R6_64R6; -def CLO : MMRel, CountLeading1<"clo", GPR32Opnd, II_CLO>, CLO_FM<0x21>, - ISA_MIPS32_NOT_32R6_64R6; + /// Count Leading + def CLZ : MMRel, CountLeading0<"clz", GPR32Opnd, II_CLZ>, CLO_FM<0x20>, + ISA_MIPS32_NOT_32R6_64R6; + def CLO : MMRel, CountLeading1<"clo", GPR32Opnd, II_CLO>, CLO_FM<0x21>, + ISA_MIPS32_NOT_32R6_64R6; -let AdditionalPredicates = [NotInMicroMips] in { /// Word Swap Bytes Within Halfwords def WSBH : MMRel, SubwordSwap<"wsbh", GPR32Opnd, II_WSBH>, SEB_FM<2, 0x20>, ISA_MIPS32R2; -} -/// No operation. -def NOP : PseudoSE<(outs), (ins), []>, PseudoInstExpansion<(SLL ZERO, ZERO, 0)>; + /// No operation. + def NOP : PseudoSE<(outs), (ins), []>, + PseudoInstExpansion<(SLL ZERO, ZERO, 0)>, ISA_MIPS1; -// FrameIndexes are legalized when they are operands from load/store -// instructions. The same not happens for stack address copies, so an -// add op with mem ComplexPattern is used and the stack address copy -// can be matched. It's similar to Sparc LEA_ADDRi -def LEA_ADDiu : MMRel, EffectiveAddress<"addiu", GPR32Opnd>, LW_FM<9>; + // FrameIndexes are legalized when they are operands from load/store + // instructions. The same not happens for stack address copies, so an + // add op with mem ComplexPattern is used and the stack address copy + // can be matched. It's similar to Sparc LEA_ADDRi + let AdditionalPredicates = [NotInMicroMips] in + def LEA_ADDiu : MMRel, EffectiveAddress<"addiu", GPR32Opnd>, LW_FM<9>, ISA_MIPS1; -// MADD*/MSUB* -def MADD : MMRel, MArithR<"madd", II_MADD, 1>, MULT_FM<0x1c, 0>, - ISA_MIPS32_NOT_32R6_64R6; -def MADDU : MMRel, MArithR<"maddu", II_MADDU, 1>, MULT_FM<0x1c, 1>, - ISA_MIPS32_NOT_32R6_64R6; -def MSUB : MMRel, MArithR<"msub", II_MSUB>, MULT_FM<0x1c, 4>, - ISA_MIPS32_NOT_32R6_64R6; -def MSUBU : MMRel, MArithR<"msubu", II_MSUBU>, MULT_FM<0x1c, 5>, - ISA_MIPS32_NOT_32R6_64R6; + // MADD*/MSUB* + def MADD : MMRel, MArithR<"madd", II_MADD, 1>, MULT_FM<0x1c, 0>, + ISA_MIPS32_NOT_32R6_64R6; + def MADDU : MMRel, MArithR<"maddu", II_MADDU, 1>, MULT_FM<0x1c, 1>, + ISA_MIPS32_NOT_32R6_64R6; + def MSUB : MMRel, MArithR<"msub", II_MSUB>, MULT_FM<0x1c, 4>, + ISA_MIPS32_NOT_32R6_64R6; + def MSUBU : MMRel, MArithR<"msubu", II_MSUBU>, MULT_FM<0x1c, 5>, + ISA_MIPS32_NOT_32R6_64R6; +} let AdditionalPredicates = [NotDSP] in { def PseudoMULT : MultDivPseudo<MULT, ACC64, GPR32Opnd, MipsMult, II_MULT>, @@ -2229,35 +2406,39 @@ let AdditionalPredicates = [NotInMicroMips] in { 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; + def RDHWR : MMRel, ReadHardware<GPR32Opnd, HWRegsOpnd>, RDHWR_FM, ISA_MIPS1; // 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>; + EXT_FM<0>, ISA_MIPS32R2; def INS : MMRel, StdMMR6Rel, InsBase<"ins", GPR32Opnd, uimm5, uimm5_inssize_plus1, immZExt5, immZExt5Plus1>, - EXT_FM<4>; + EXT_FM<4>, ISA_MIPS32R2; } /// Move Control Registers From/To CPU Registers 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 MTC0 : MTC3OP<"mtc0", COP0Opnd, GPR32Opnd, II_MTC0>, + MFC3OP_FM<0x10, 4, 0>, ISA_MIPS1; + def MFC0 : MFC3OP<"mfc0", GPR32Opnd, COP0Opnd, II_MFC0>, + MFC3OP_FM<0x10, 0, 0>, ISA_MIPS1; + def MFC2 : MFC3OP<"mfc2", GPR32Opnd, COP2Opnd, II_MFC2>, + MFC3OP_FM<0x12, 0, 0>, ISA_MIPS1; + def MTC2 : MTC3OP<"mtc2", COP2Opnd, GPR32Opnd, II_MTC2>, + MFC3OP_FM<0x12, 4, 0>, ISA_MIPS1; } -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>; +let AdditionalPredicates = [NotInMicroMips] in { + def SSNOP : MMRel, StdMMR6Rel, Barrier<"ssnop", II_SSNOP>, BARRIER_FM<1>, + ISA_MIPS1; + def EHB : MMRel, Barrier<"ehb", II_EHB>, BARRIER_FM<3>, ISA_MIPS1; -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; + 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 @@ -2278,8 +2459,8 @@ class JALR_HB_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> { list<dag> Pattern = []; } -class JR_HB_DESC : InstSE<(outs), (ins), "", [], II_JR_HB, FrmJ>, - JR_HB_DESC_BASE<"jr.hb", GPR32Opnd> { +class JR_HB_DESC<RegisterOperand RO> : + InstSE<(outs), (ins), "", [], II_JR_HB, FrmJ>, JR_HB_DESC_BASE<"jr.hb", RO> { let isBranch=1; let isIndirectBranch=1; let hasDelaySlot=1; @@ -2288,8 +2469,9 @@ class JR_HB_DESC : InstSE<(outs), (ins), "", [], II_JR_HB, FrmJ>, bit isCTI = 1; } -class JALR_HB_DESC : InstSE<(outs), (ins), "", [], II_JALR_HB, FrmJ>, - JALR_HB_DESC_BASE<"jalr.hb", GPR32Opnd> { +class JALR_HB_DESC<RegisterOperand RO> : + InstSE<(outs), (ins), "", [], II_JALR_HB, FrmJ>, JALR_HB_DESC_BASE<"jalr.hb", + RO> { let isIndirectBranch=1; let hasDelaySlot=1; bit isCTI = 1; @@ -2298,16 +2480,27 @@ class JALR_HB_DESC : InstSE<(outs), (ins), "", [], II_JALR_HB, FrmJ>, class JR_HB_ENC : JR_HB_FM<8>; 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; +def JR_HB : JR_HB_DESC<GPR32Opnd>, JR_HB_ENC, ISA_MIPS32R2_NOT_32R6_64R6; +def JALR_HB : JALR_HB_DESC<GPR32Opnd>, JALR_HB_ENC, ISA_MIPS32; + +let AdditionalPredicates = [NotInMicroMips, UseIndirectJumpsHazard] in + def JALRHBPseudo : JumpLinkRegPseudo<GPR32Opnd, JALR_HB, RA>; + + +let AdditionalPredicates = [NotInMips16Mode, NotInMicroMips, + UseIndirectJumpsHazard] in { + def TAILCALLREGHB : TailCallReg<JR_HB, GPR32Opnd>, ISA_MIPS32_NOT_32R6_64R6; + def PseudoIndirectHazardBranch : PseudoIndirectBranchBase<JR_HB, GPR32Opnd>, + ISA_MIPS32R2_NOT_32R6_64R6; +} 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>; + def TLBP : MMRel, TLB<"tlbp", II_TLBP>, COP0_TLB_FM<0x08>, ISA_MIPS1; + def TLBR : MMRel, TLB<"tlbr", II_TLBR>, COP0_TLB_FM<0x01>, ISA_MIPS1; + def TLBWI : MMRel, TLB<"tlbwi", II_TLBWI>, COP0_TLB_FM<0x02>, ISA_MIPS1; + def TLBWR : MMRel, TLB<"tlbwr", II_TLBWR>, COP0_TLB_FM<0x06>, ISA_MIPS1; } class CacheOp<string instr_asm, Operand MemOpnd, InstrItinClass itin = NoItinerary> : @@ -2317,11 +2510,13 @@ class CacheOp<string instr_asm, Operand MemOpnd, let DecoderMethod = "DecodeCacheOp"; } -def CACHE : MMRel, CacheOp<"cache", mem, II_CACHE>, CACHEOP_FM<0b101111>, - INSN_MIPS3_32_NOT_32R6_64R6; -def PREF : MMRel, CacheOp<"pref", mem, II_PREF>, CACHEOP_FM<0b110011>, - INSN_MIPS3_32_NOT_32R6_64R6; - +let AdditionalPredicates = [NotInMicroMips] in { + def CACHE : MMRel, CacheOp<"cache", mem, II_CACHE>, CACHEOP_FM<0b101111>, + INSN_MIPS3_32_NOT_32R6_64R6; + def PREF : MMRel, CacheOp<"pref", mem, II_PREF>, CACHEOP_FM<0b110011>, + INSN_MIPS3_32_NOT_32R6_64R6; +} +// FIXME: We are missing the prefx instruction. def ROL : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt, GPR32Opnd:$rd), "rol\t$rs, $rt, $rd">; @@ -2398,6 +2593,38 @@ def MULOUMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rd, GPR32Opnd:$rs, "mulou\t$rd, $rs, $rt">, ISA_MIPS1_NOT_32R6_64R6; +// Virtualization ASE +class HYPCALL_FT<string opstr> : + InstSE<(outs), (ins uimm10:$code_), + !strconcat(opstr, "\t$code_"), [], II_HYPCALL, FrmOther, opstr> { + let BaseOpcode = opstr; +} + +let AdditionalPredicates = [NotInMicroMips] in { + def MFGC0 : MMRel, MFC3OP<"mfgc0", GPR32Opnd, COP0Opnd, II_MFGC0>, + MFC3OP_FM<0x10, 3, 0>, ISA_MIPS32R5, ASE_VIRT; + def MTGC0 : MMRel, MTC3OP<"mtgc0", COP0Opnd, GPR32Opnd, II_MTGC0>, + MFC3OP_FM<0x10, 3, 2>, ISA_MIPS32R5, ASE_VIRT; + def MFHGC0 : MMRel, MFC3OP<"mfhgc0", GPR32Opnd, COP0Opnd, II_MFHGC0>, + MFC3OP_FM<0x10, 3, 4>, ISA_MIPS32R5, ASE_VIRT; + def MTHGC0 : MMRel, MTC3OP<"mthgc0", COP0Opnd, GPR32Opnd, II_MTHGC0>, + MFC3OP_FM<0x10, 3, 6>, ISA_MIPS32R5, ASE_VIRT; + def TLBGINV : MMRel, TLB<"tlbginv", II_TLBGINV>, COP0_TLB_FM<0b001011>, + ISA_MIPS32R5, ASE_VIRT; + def TLBGINVF : MMRel, TLB<"tlbginvf", II_TLBGINVF>, COP0_TLB_FM<0b001100>, + ISA_MIPS32R5, ASE_VIRT; + def TLBGP : MMRel, TLB<"tlbgp", II_TLBGP>, COP0_TLB_FM<0b010000>, + ISA_MIPS32R5, ASE_VIRT; + def TLBGR : MMRel, TLB<"tlbgr", II_TLBGR>, COP0_TLB_FM<0b001001>, + ISA_MIPS32R5, ASE_VIRT; + def TLBGWI : MMRel, TLB<"tlbgwi", II_TLBGWI>, COP0_TLB_FM<0b001010>, + ISA_MIPS32R5, ASE_VIRT; + def TLBGWR : MMRel, TLB<"tlbgwr", II_TLBGWR>, COP0_TLB_FM<0b001110>, + ISA_MIPS32R5, ASE_VIRT; + def HYPCALL : MMRel, HYPCALL_FT<"hypcall">, + HYPCALL_FM<0b101000>, ISA_MIPS32R5, ASE_VIRT; +} + //===----------------------------------------------------------------------===// // Instruction aliases //===----------------------------------------------------------------------===// @@ -2416,93 +2643,111 @@ multiclass OneOrTwoOperandMacroImmediateAlias<string Memnomic, Imm:$imm), 0>; } -def : MipsInstAlias<"move $dst, $src", - (OR GPR32Opnd:$dst, GPR32Opnd:$src, ZERO), 1>, - GPR_32 { - let AdditionalPredicates = [NotInMicroMips]; -} -def : MipsInstAlias<"move $dst, $src", - (ADDu GPR32Opnd:$dst, GPR32Opnd:$src, ZERO), 1>, - GPR_32 { - let AdditionalPredicates = [NotInMicroMips]; -} -def : MipsInstAlias<"bal $offset", (BGEZAL ZERO, brtarget:$offset), 0>, - ISA_MIPS1_NOT_32R6_64R6; - -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<"neg $rt, $rs", - (SUB GPR32Opnd:$rt, ZERO, GPR32Opnd:$rs), 1>; -def : MipsInstAlias<"neg $rt", - (SUB GPR32Opnd:$rt, ZERO, GPR32Opnd:$rt), 1>; -def : MipsInstAlias<"negu $rt, $rs", - (SUBu GPR32Opnd:$rt, ZERO, GPR32Opnd:$rs), 1>; -def : MipsInstAlias<"negu $rt", - (SUBu GPR32Opnd:$rt, ZERO, GPR32Opnd:$rt), 1>; let AdditionalPredicates = [NotInMicroMips] in { + def : MipsInstAlias<"move $dst, $src", + (OR GPR32Opnd:$dst, GPR32Opnd:$src, ZERO), 1>, + GPR_32, ISA_MIPS1; + def : MipsInstAlias<"move $dst, $src", + (ADDu GPR32Opnd:$dst, GPR32Opnd:$src, ZERO), 1>, + GPR_32, ISA_MIPS1; + + def : MipsInstAlias<"bal $offset", (BGEZAL ZERO, brtarget:$offset), 1>, + ISA_MIPS1_NOT_32R6_64R6; + + def : MipsInstAlias<"j $rs", (JR GPR32Opnd:$rs), 0>, ISA_MIPS1; + + def : MipsInstAlias<"jalr $rs", (JALR RA, GPR32Opnd:$rs), 0>; + + def : MipsInstAlias<"jalr.hb $rs", (JALR_HB RA, GPR32Opnd:$rs), 1>, + ISA_MIPS32; + + def : MipsInstAlias<"neg $rt, $rs", + (SUB GPR32Opnd:$rt, ZERO, GPR32Opnd:$rs), 1>, ISA_MIPS1; + def : MipsInstAlias<"neg $rt", + (SUB GPR32Opnd:$rt, ZERO, GPR32Opnd:$rt), 1>, ISA_MIPS1; + def : MipsInstAlias<"negu $rt, $rs", + (SUBu GPR32Opnd:$rt, ZERO, GPR32Opnd:$rs), 1>, ISA_MIPS1; + def : MipsInstAlias<"negu $rt", + (SUBu GPR32Opnd:$rt, ZERO, GPR32Opnd:$rt), 1>, ISA_MIPS1; def : MipsInstAlias< "sgt $rd, $rs, $rt", - (SLT GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>; + (SLT GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>, ISA_MIPS1; def : MipsInstAlias< "sgt $rs, $rt", - (SLT GPR32Opnd:$rs, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>; + (SLT GPR32Opnd:$rs, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>, ISA_MIPS1; def : MipsInstAlias< "sgtu $rd, $rs, $rt", - (SLTu GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>; + (SLTu GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>, ISA_MIPS1; def : MipsInstAlias< "sgtu $$rs, $rt", - (SLTu GPR32Opnd:$rs, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>; + (SLTu GPR32Opnd:$rs, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>, ISA_MIPS1; def : MipsInstAlias< "not $rt, $rs", - (NOR GPR32Opnd:$rt, GPR32Opnd:$rs, ZERO), 0>; + (NOR GPR32Opnd:$rt, GPR32Opnd:$rs, ZERO), 0>, ISA_MIPS1; def : MipsInstAlias< "not $rt", - (NOR GPR32Opnd:$rt, GPR32Opnd:$rt, ZERO), 0>; - def : MipsInstAlias<"nop", (SLL ZERO, ZERO, 0), 1>; - - defm : OneOrTwoOperandMacroImmediateAlias<"add", ADDi>, ISA_MIPS1_NOT_32R6_64R6; - - defm : OneOrTwoOperandMacroImmediateAlias<"addu", ADDiu>; - - defm : OneOrTwoOperandMacroImmediateAlias<"and", ANDi>, GPR_32; + (NOR GPR32Opnd:$rt, GPR32Opnd:$rt, ZERO), 0>, ISA_MIPS1; - defm : OneOrTwoOperandMacroImmediateAlias<"or", ORi>, GPR_32; + def : MipsInstAlias<"nop", (SLL ZERO, ZERO, 0), 1>, ISA_MIPS1; - defm : OneOrTwoOperandMacroImmediateAlias<"xor", XORi>, GPR_32; - - defm : OneOrTwoOperandMacroImmediateAlias<"slt", SLTi>, GPR_32; - - defm : OneOrTwoOperandMacroImmediateAlias<"sltu", SLTiu>, GPR_32; -} -def : MipsInstAlias<"mfc0 $rt, $rd", (MFC0 GPR32Opnd:$rt, COP0Opnd:$rd, 0), 0>; -def : MipsInstAlias<"mtc0 $rt, $rd", (MTC0 COP0Opnd:$rd, GPR32Opnd:$rt, 0), 0>; -def : MipsInstAlias<"mfc2 $rt, $rd", (MFC2 GPR32Opnd:$rt, COP2Opnd:$rd, 0), 0>; -def : MipsInstAlias<"mtc2 $rt, $rd", (MTC2 COP2Opnd:$rd, GPR32Opnd:$rt, 0), 0>; -let AdditionalPredicates = [NotInMicroMips] in { -def : MipsInstAlias<"b $offset", (BEQ ZERO, ZERO, brtarget:$offset), 0>; -} -def : MipsInstAlias<"bnez $rs,$offset", - (BNE GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>; -def : MipsInstAlias<"bnezl $rs,$offset", - (BNEL GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>; -def : MipsInstAlias<"beqz $rs,$offset", - (BEQ GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>; -def : MipsInstAlias<"beqzl $rs,$offset", - (BEQL GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>; -let AdditionalPredicates = [NotInMicroMips] in { - def : MipsInstAlias<"syscall", (SYSCALL 0), 1>; -} + defm : OneOrTwoOperandMacroImmediateAlias<"add", ADDi>, ISA_MIPS1_NOT_32R6_64R6; -def : MipsInstAlias<"break", (BREAK 0, 0), 1>; -def : MipsInstAlias<"break $imm", (BREAK uimm10:$imm, 0), 1>; -let AdditionalPredicates = [NotInMicroMips] in { + defm : OneOrTwoOperandMacroImmediateAlias<"addu", ADDiu>, ISA_MIPS1; + + defm : OneOrTwoOperandMacroImmediateAlias<"and", ANDi>, ISA_MIPS1, GPR_32; + + defm : OneOrTwoOperandMacroImmediateAlias<"or", ORi>, ISA_MIPS1, GPR_32; + + defm : OneOrTwoOperandMacroImmediateAlias<"xor", XORi>, ISA_MIPS1, GPR_32; + + defm : OneOrTwoOperandMacroImmediateAlias<"slt", SLTi>, ISA_MIPS1, GPR_32; + + defm : OneOrTwoOperandMacroImmediateAlias<"sltu", SLTiu>, ISA_MIPS1, GPR_32; + + def : MipsInstAlias<"mfgc0 $rt, $rd", + (MFGC0 GPR32Opnd:$rt, COP0Opnd:$rd, 0), 0>, + ISA_MIPS32R5, ASE_VIRT; + def : MipsInstAlias<"mtgc0 $rt, $rd", + (MTGC0 COP0Opnd:$rd, GPR32Opnd:$rt, 0), 0>, + ISA_MIPS32R5, ASE_VIRT; + def : MipsInstAlias<"mfhgc0 $rt, $rd", + (MFHGC0 GPR32Opnd:$rt, COP0Opnd:$rd, 0), 0>, + ISA_MIPS32R5, ASE_VIRT; + def : MipsInstAlias<"mthgc0 $rt, $rd", + (MTHGC0 COP0Opnd:$rd, GPR32Opnd:$rt, 0), 0>, + ISA_MIPS32R5, ASE_VIRT; + def : MipsInstAlias<"mfc0 $rt, $rd", (MFC0 GPR32Opnd:$rt, COP0Opnd:$rd, 0), 0>, + ISA_MIPS1; + def : MipsInstAlias<"mtc0 $rt, $rd", (MTC0 COP0Opnd:$rd, GPR32Opnd:$rt, 0), 0>, + ISA_MIPS1; + def : MipsInstAlias<"mfc2 $rt, $rd", (MFC2 GPR32Opnd:$rt, COP2Opnd:$rd, 0), 0>, + ISA_MIPS1; + def : MipsInstAlias<"mtc2 $rt, $rd", (MTC2 COP2Opnd:$rd, GPR32Opnd:$rt, 0), 0>, + ISA_MIPS1; + + def : MipsInstAlias<"b $offset", (BEQ ZERO, ZERO, brtarget:$offset), 0>, + ISA_MIPS1; + + def : MipsInstAlias<"bnez $rs,$offset", + (BNE GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>, + ISA_MIPS1; + def : MipsInstAlias<"bnezl $rs,$offset", + (BNEL GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>, + ISA_MIPS2; + def : MipsInstAlias<"beqz $rs,$offset", + (BEQ GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>, + ISA_MIPS1; + def : MipsInstAlias<"beqzl $rs,$offset", + (BEQL GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>, + ISA_MIPS2; + + def : MipsInstAlias<"syscall", (SYSCALL 0), 1>, ISA_MIPS1; + + def : MipsInstAlias<"break", (BREAK 0, 0), 1>, ISA_MIPS1; + def : MipsInstAlias<"break $imm", (BREAK uimm10:$imm, 0), 1>, ISA_MIPS1; def : MipsInstAlias<"ei", (EI ZERO), 1>, ISA_MIPS32R2; def : MipsInstAlias<"di", (DI ZERO), 1>, ISA_MIPS32R2; -} -let AdditionalPredicates = [NotInMicroMips] in { + def : MipsInstAlias<"teq $rs, $rt", (TEQ GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>, ISA_MIPS2; def : MipsInstAlias<"tge $rs, $rt", @@ -2515,6 +2760,9 @@ let AdditionalPredicates = [NotInMicroMips] in { (TLTU GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>, ISA_MIPS2; def : MipsInstAlias<"tne $rs, $rt", (TNE GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>, ISA_MIPS2; + def : MipsInstAlias<"rdhwr $rt, $rs", + (RDHWR GPR32Opnd:$rt, HWRegsOpnd:$rs, 0), 1>, ISA_MIPS1; + } def : MipsInstAlias<"sub, $rd, $rs, $imm", (ADDi GPR32Opnd:$rd, GPR32Opnd:$rs, @@ -2546,8 +2794,8 @@ let AdditionalPredicates = [NotInMicroMips] in { ISA_MIPS32R2; } def : MipsInstAlias<"sdbbp", (SDBBP 0)>, ISA_MIPS32_NOT_32R6_64R6; -def : MipsInstAlias<"sync", - (SYNC 0), 1>, ISA_MIPS2; +let AdditionalPredicates = [NotInMicroMips] in + def : MipsInstAlias<"sync", (SYNC 0), 1>, ISA_MIPS2; def : MipsInstAlias<"mulo $rs, $rt", (MULOMacro GPR32Opnd:$rs, GPR32Opnd:$rs, GPR32Opnd:$rt), 0>, @@ -2556,6 +2804,9 @@ def : MipsInstAlias<"mulou $rs, $rt", (MULOUMacro GPR32Opnd:$rs, GPR32Opnd:$rs, GPR32Opnd:$rt), 0>, ISA_MIPS1_NOT_32R6_64R6; +let AdditionalPredicates = [NotInMicroMips] in + def : MipsInstAlias<"hypcall", (HYPCALL 0), 1>, ISA_MIPS32R5, ASE_VIRT; + //===----------------------------------------------------------------------===// // Assembler Pseudo Instructions //===----------------------------------------------------------------------===// @@ -2693,6 +2944,36 @@ def : MipsInstAlias<"divu $rd, $imm", (UDivIMacro GPR32Opnd:$rd, GPR32Opnd:$rd, simm32:$imm), 0>, ISA_MIPS1_NOT_32R6_64R6; +def SRemMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), + (ins GPR32Opnd:$rs, GPR32Opnd:$rt), + "rem\t$rd, $rs, $rt">, + ISA_MIPS1_NOT_32R6_64R6; +def SRemIMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), + (ins GPR32Opnd:$rs, simm32_relaxed:$imm), + "rem\t$rd, $rs, $imm">, + ISA_MIPS1_NOT_32R6_64R6; +def URemMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), + (ins GPR32Opnd:$rs, GPR32Opnd:$rt), + "remu\t$rd, $rs, $rt">, + ISA_MIPS1_NOT_32R6_64R6; +def URemIMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), + (ins GPR32Opnd:$rs, simm32_relaxed:$imm), + "remu\t$rd, $rs, $imm">, + ISA_MIPS1_NOT_32R6_64R6; + +def : MipsInstAlias<"rem $rt, $rs", (SRemMacro GPR32Opnd:$rt, GPR32Opnd:$rt, + GPR32Opnd:$rs), 0>, + ISA_MIPS1_NOT_32R6_64R6; +def : MipsInstAlias<"rem $rd, $imm", (SRemIMacro GPR32Opnd:$rd, GPR32Opnd:$rd, + simm32_relaxed:$imm), 0>, + ISA_MIPS1_NOT_32R6_64R6; +def : MipsInstAlias<"remu $rt, $rs", (URemMacro GPR32Opnd:$rt, GPR32Opnd:$rt, + GPR32Opnd:$rs), 0>, + ISA_MIPS1_NOT_32R6_64R6; +def : MipsInstAlias<"remu $rd, $imm", (URemIMacro GPR32Opnd:$rd, GPR32Opnd:$rd, + simm32_relaxed:$imm), 0>, + ISA_MIPS1_NOT_32R6_64R6; + def Ulh : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins mem:$addr), "ulh\t$rt, $addr">; //, ISA_MIPS1_NOT_32R6_64R6; @@ -2747,17 +3028,17 @@ def : MipsPat<(VT immSExt16:$imm), (ADDiuOp ZEROReg, imm:$imm)>; } let AdditionalPredicates = [NotInMicroMips] in - defm : MaterializeImms<i32, ZERO, ADDiu, LUi, ORi>; + defm : MaterializeImms<i32, ZERO, ADDiu, LUi, ORi>, ISA_MIPS1; // Carry MipsPatterns let AdditionalPredicates = [NotInMicroMips] in { def : MipsPat<(subc GPR32:$lhs, GPR32:$rhs), - (SUBu GPR32:$lhs, GPR32:$rhs)>; + (SUBu GPR32:$lhs, GPR32:$rhs)>, ISA_MIPS1; } def : MipsPat<(addc GPR32:$lhs, GPR32:$rhs), - (ADDu GPR32:$lhs, GPR32:$rhs)>, ASE_NOT_DSP; + (ADDu GPR32:$lhs, GPR32:$rhs)>, ISA_MIPS1, ASE_NOT_DSP; def : MipsPat<(addc GPR32:$src, immSExt16:$imm), - (ADDiu GPR32:$src, imm:$imm)>, ASE_NOT_DSP; + (ADDiu GPR32:$src, imm:$imm)>, ISA_MIPS1, ASE_NOT_DSP; // Support multiplication for pre-Mips32 targets that don't have // the MUL instruction. @@ -2771,16 +3052,16 @@ def : MipsPat<(MipsSync (i32 immz)), // Call def : MipsPat<(MipsJmpLink (i32 texternalsym:$dst)), - (JAL texternalsym:$dst)>; + (JAL texternalsym:$dst)>, ISA_MIPS1; //def : MipsPat<(MipsJmpLink GPR32:$dst), // (JALR GPR32:$dst)>; // Tail call let AdditionalPredicates = [NotInMicroMips] in { def : MipsPat<(MipsTailCall (iPTR tglobaladdr:$dst)), - (TAILCALL tglobaladdr:$dst)>; + (TAILCALL tglobaladdr:$dst)>, ISA_MIPS1; def : MipsPat<(MipsTailCall (iPTR texternalsym:$dst)), - (TAILCALL texternalsym:$dst)>; + (TAILCALL texternalsym:$dst)>, ISA_MIPS1; } // hi/lo relocs multiclass MipsHiLoRelocs<Instruction Lui, Instruction Addiu, @@ -2789,7 +3070,6 @@ multiclass MipsHiLoRelocs<Instruction Lui, Instruction Addiu, def : MipsPat<(MipsHi tblockaddress:$in), (Lui tblockaddress:$in)>; def : MipsPat<(MipsHi tjumptable:$in), (Lui tjumptable:$in)>; def : MipsPat<(MipsHi tconstpool:$in), (Lui tconstpool:$in)>; - def : MipsPat<(MipsHi tglobaltlsaddr:$in), (Lui tglobaltlsaddr:$in)>; def : MipsPat<(MipsHi texternalsym:$in), (Lui texternalsym:$in)>; def : MipsPat<(MipsLo tglobaladdr:$in), (Addiu ZeroReg, tglobaladdr:$in)>; @@ -2813,44 +3093,47 @@ multiclass MipsHiLoRelocs<Instruction Lui, Instruction Addiu, (Addiu GPROpnd:$hi, tglobaltlsaddr:$lo)>; } -defm : MipsHiLoRelocs<LUi, ADDiu, ZERO, GPR32Opnd>; +// wrapper_pic +class WrapperPat<SDNode node, Instruction ADDiuOp, RegisterClass RC>: + MipsPat<(MipsWrapper RC:$gp, node:$in), (ADDiuOp RC:$gp, node:$in)>; -def : MipsPat<(MipsGotHi tglobaladdr:$in), (LUi tglobaladdr:$in)>; -def : MipsPat<(MipsGotHi texternalsym:$in), (LUi texternalsym:$in)>; +let AdditionalPredicates = [NotInMicroMips] in { + defm : MipsHiLoRelocs<LUi, ADDiu, ZERO, GPR32Opnd>, ISA_MIPS1; -// gp_rel relocs -def : MipsPat<(add GPR32:$gp, (MipsGPRel tglobaladdr:$in)), - (ADDiu GPR32:$gp, tglobaladdr:$in)>, ABI_NOT_N64; -def : MipsPat<(add GPR32:$gp, (MipsGPRel tconstpool:$in)), - (ADDiu GPR32:$gp, tconstpool:$in)>, ABI_NOT_N64; + def : MipsPat<(MipsGotHi tglobaladdr:$in), (LUi tglobaladdr:$in)>, ISA_MIPS1; + def : MipsPat<(MipsGotHi texternalsym:$in), (LUi texternalsym:$in)>, + ISA_MIPS1; -// wrapper_pic -class WrapperPat<SDNode node, Instruction ADDiuOp, RegisterClass RC>: - MipsPat<(MipsWrapper RC:$gp, node:$in), - (ADDiuOp RC:$gp, node:$in)>; + def : MipsPat<(MipsTlsHi tglobaltlsaddr:$in), (LUi tglobaltlsaddr:$in)>, + ISA_MIPS1; -def : WrapperPat<tglobaladdr, ADDiu, GPR32>; -def : WrapperPat<tconstpool, ADDiu, GPR32>; -def : WrapperPat<texternalsym, ADDiu, GPR32>; -def : WrapperPat<tblockaddress, ADDiu, GPR32>; -def : WrapperPat<tjumptable, ADDiu, GPR32>; -def : WrapperPat<tglobaltlsaddr, ADDiu, GPR32>; + // gp_rel relocs + def : MipsPat<(add GPR32:$gp, (MipsGPRel tglobaladdr:$in)), + (ADDiu GPR32:$gp, tglobaladdr:$in)>, ISA_MIPS1, ABI_NOT_N64; + def : MipsPat<(add GPR32:$gp, (MipsGPRel tconstpool:$in)), + (ADDiu GPR32:$gp, tconstpool:$in)>, ISA_MIPS1, ABI_NOT_N64; -let AdditionalPredicates = [NotInMicroMips] in { -// Mips does not have "not", so we expand our way -def : MipsPat<(not GPR32:$in), - (NOR GPR32Opnd:$in, ZERO)>; + def : WrapperPat<tglobaladdr, ADDiu, GPR32>, ISA_MIPS1; + def : WrapperPat<tconstpool, ADDiu, GPR32>, ISA_MIPS1; + def : WrapperPat<texternalsym, ADDiu, GPR32>, ISA_MIPS1; + def : WrapperPat<tblockaddress, ADDiu, GPR32>, ISA_MIPS1; + def : WrapperPat<tjumptable, ADDiu, GPR32>, ISA_MIPS1; + def : WrapperPat<tglobaltlsaddr, ADDiu, GPR32>, ISA_MIPS1; + + // Mips does not have "not", so we expand our way + def : MipsPat<(not GPR32:$in), + (NOR GPR32Opnd:$in, ZERO)>, ISA_MIPS1; } // extended loads -def : MipsPat<(i32 (extloadi1 addr:$src)), (LBu addr:$src)>; -def : MipsPat<(i32 (extloadi8 addr:$src)), (LBu addr:$src)>; let AdditionalPredicates = [NotInMicroMips] in { - def : MipsPat<(i32 (extloadi16 addr:$src)), (LHu addr:$src)>; -} + def : MipsPat<(i32 (extloadi1 addr:$src)), (LBu addr:$src)>, ISA_MIPS1; + def : MipsPat<(i32 (extloadi8 addr:$src)), (LBu addr:$src)>, ISA_MIPS1; + def : MipsPat<(i32 (extloadi16 addr:$src)), (LHu addr:$src)>, ISA_MIPS1; -// peepholes -def : MipsPat<(store (i32 0), addr:$dst), (SW ZERO, addr:$dst)>; + // peepholes + def : MipsPat<(store (i32 0), addr:$dst), (SW ZERO, addr:$dst)>, ISA_MIPS1; +} // brcond patterns multiclass BrcondPats<RegisterClass RC, Instruction BEQOp, Instruction BEQOp1, @@ -2884,12 +3167,13 @@ def : MipsPat<(brcond RC:$cond, bb:$dst), (BNEOp RC:$cond, ZEROReg, bb:$dst)>; } let AdditionalPredicates = [NotInMicroMips] in { - defm : BrcondPats<GPR32, BEQ, BEQ, BNE, SLT, SLTu, SLTi, SLTiu, ZERO>; + defm : BrcondPats<GPR32, BEQ, BEQ, BNE, SLT, SLTu, SLTi, SLTiu, ZERO>, + ISA_MIPS1; + def : MipsPat<(brcond (i32 (setlt i32:$lhs, 1)), bb:$dst), + (BLEZ i32:$lhs, bb:$dst)>, ISA_MIPS1; + def : MipsPat<(brcond (i32 (setgt i32:$lhs, -1)), bb:$dst), + (BGEZ i32:$lhs, bb:$dst)>, ISA_MIPS1; } -def : MipsPat<(brcond (i32 (setlt i32:$lhs, 1)), bb:$dst), - (BLEZ i32:$lhs, bb:$dst)>; -def : MipsPat<(brcond (i32 (setgt i32:$lhs, -1)), bb:$dst), - (BGEZ i32:$lhs, bb:$dst)>; // setcc patterns multiclass SeteqPats<RegisterClass RC, Instruction SLTiuOp, Instruction XOROp, @@ -2936,36 +3220,39 @@ multiclass SetgeImmPats<RegisterClass RC, Instruction XORiOp, } let AdditionalPredicates = [NotInMicroMips] in { - defm : SeteqPats<GPR32, SLTiu, XOR, SLTu, ZERO>; - defm : SetlePats<GPR32, XORi, SLT, SLTu>; - defm : SetgtPats<GPR32, SLT, SLTu>; - defm : SetgePats<GPR32, XORi, SLT, SLTu>; - defm : SetgeImmPats<GPR32, XORi, SLTi, SLTiu>; -} + defm : SeteqPats<GPR32, SLTiu, XOR, SLTu, ZERO>, ISA_MIPS1; + defm : SetlePats<GPR32, XORi, SLT, SLTu>, ISA_MIPS1; + defm : SetgtPats<GPR32, SLT, SLTu>, ISA_MIPS1; + defm : SetgePats<GPR32, XORi, SLT, SLTu>, ISA_MIPS1; + defm : SetgeImmPats<GPR32, XORi, SLTi, SLTiu>, ISA_MIPS1; -// bswap pattern -def : MipsPat<(bswap GPR32:$rt), (ROTR (WSBH GPR32:$rt), 16)>; + // bswap pattern + def : MipsPat<(bswap GPR32:$rt), (ROTR (WSBH GPR32:$rt), 16)>, ISA_MIPS32R2; +} // Load halfword/word patterns. -let AddedComplexity = 40 in { - def : LoadRegImmPat<LBu, i32, zextloadi8>; - let AdditionalPredicates = [NotInMicroMips] in { - def : LoadRegImmPat<LH, i32, sextloadi16>; - def : LoadRegImmPat<LW, i32, load>; +let AdditionalPredicates = [NotInMicroMips] in { + let AddedComplexity = 40 in { + def : LoadRegImmPat<LBu, i32, zextloadi8>, ISA_MIPS1; + def : LoadRegImmPat<LHu, i32, zextloadi16>, ISA_MIPS1; + def : LoadRegImmPat<LB, i32, sextloadi8>, ISA_MIPS1; + def : LoadRegImmPat<LH, i32, sextloadi16>, ISA_MIPS1; + def : LoadRegImmPat<LW, i32, load>, ISA_MIPS1; } -} -// Atomic load patterns. -def : MipsPat<(atomic_load_8 addr:$a), (LB 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 load patterns. + def : MipsPat<(atomic_load_8 addr:$a), (LB addr:$a)>, ISA_MIPS1; + def : MipsPat<(atomic_load_16 addr:$a), (LH addr:$a)>, ISA_MIPS1; + def : MipsPat<(atomic_load_32 addr:$a), (LW addr:$a)>, ISA_MIPS1; -// Atomic store patterns. -def : MipsPat<(atomic_store_8 addr:$a, GPR32:$v), (SB GPR32:$v, addr:$a)>; -def : MipsPat<(atomic_store_16 addr:$a, GPR32:$v), (SH GPR32:$v, addr:$a)>; -def : MipsPat<(atomic_store_32 addr:$a, GPR32:$v), (SW GPR32:$v, addr:$a)>; + // Atomic store patterns. + def : MipsPat<(atomic_store_8 addr:$a, GPR32:$v), (SB GPR32:$v, addr:$a)>, + ISA_MIPS1; + def : MipsPat<(atomic_store_16 addr:$a, GPR32:$v), (SH GPR32:$v, addr:$a)>, + ISA_MIPS1; + def : MipsPat<(atomic_store_32 addr:$a, GPR32:$v), (SW GPR32:$v, addr:$a)>, + ISA_MIPS1; +} //===----------------------------------------------------------------------===// // Floating Point Support diff --git a/lib/Target/Mips/MipsInstructionSelector.cpp b/lib/Target/Mips/MipsInstructionSelector.cpp new file mode 100644 index 000000000000..af0ac006bc9e --- /dev/null +++ b/lib/Target/Mips/MipsInstructionSelector.cpp @@ -0,0 +1,184 @@ +//===- MipsInstructionSelector.cpp ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// This file implements the targeting of the InstructionSelector class for +/// Mips. +/// \todo This should be generated by TableGen. +//===----------------------------------------------------------------------===// + +#include "MipsRegisterBankInfo.h" +#include "MipsTargetMachine.h" +#include "llvm/CodeGen/GlobalISel/InstructionSelectorImpl.h" + +#define DEBUG_TYPE "mips-isel" + +using namespace llvm; + +namespace { + +#define GET_GLOBALISEL_PREDICATE_BITSET +#include "MipsGenGlobalISel.inc" +#undef GET_GLOBALISEL_PREDICATE_BITSET + +class MipsInstructionSelector : public InstructionSelector { +public: + MipsInstructionSelector(const MipsTargetMachine &TM, const MipsSubtarget &STI, + const MipsRegisterBankInfo &RBI); + + bool select(MachineInstr &I, CodeGenCoverage &CoverageInfo) const override; + static const char *getName() { return DEBUG_TYPE; } + +private: + bool selectImpl(MachineInstr &I, CodeGenCoverage &CoverageInfo) const; + + const MipsTargetMachine &TM; + const MipsSubtarget &STI; + const MipsInstrInfo &TII; + const MipsRegisterInfo &TRI; + const MipsRegisterBankInfo &RBI; + +#define GET_GLOBALISEL_PREDICATES_DECL +#include "MipsGenGlobalISel.inc" +#undef GET_GLOBALISEL_PREDICATES_DECL + +#define GET_GLOBALISEL_TEMPORARIES_DECL +#include "MipsGenGlobalISel.inc" +#undef GET_GLOBALISEL_TEMPORARIES_DECL +}; + +} // end anonymous namespace + +#define GET_GLOBALISEL_IMPL +#include "MipsGenGlobalISel.inc" +#undef GET_GLOBALISEL_IMPL + +MipsInstructionSelector::MipsInstructionSelector( + const MipsTargetMachine &TM, const MipsSubtarget &STI, + const MipsRegisterBankInfo &RBI) + : InstructionSelector(), TM(TM), STI(STI), TII(*STI.getInstrInfo()), + TRI(*STI.getRegisterInfo()), RBI(RBI), + +#define GET_GLOBALISEL_PREDICATES_INIT +#include "MipsGenGlobalISel.inc" +#undef GET_GLOBALISEL_PREDICATES_INIT +#define GET_GLOBALISEL_TEMPORARIES_INIT +#include "MipsGenGlobalISel.inc" +#undef GET_GLOBALISEL_TEMPORARIES_INIT +{ +} + +static bool selectCopy(MachineInstr &I, const TargetInstrInfo &TII, + MachineRegisterInfo &MRI, const TargetRegisterInfo &TRI, + const RegisterBankInfo &RBI) { + unsigned DstReg = I.getOperand(0).getReg(); + if (TargetRegisterInfo::isPhysicalRegister(DstReg)) + return true; + + const TargetRegisterClass *RC = &Mips::GPR32RegClass; + + if (!RBI.constrainGenericRegister(DstReg, *RC, MRI)) { + LLVM_DEBUG(dbgs() << "Failed to constrain " << TII.getName(I.getOpcode()) + << " operand\n"); + return false; + } + return true; +} + +bool MipsInstructionSelector::select(MachineInstr &I, + CodeGenCoverage &CoverageInfo) const { + + MachineBasicBlock &MBB = *I.getParent(); + MachineFunction &MF = *MBB.getParent(); + MachineRegisterInfo &MRI = MF.getRegInfo(); + + if (!isPreISelGenericOpcode(I.getOpcode())) { + if (I.isCopy()) + return selectCopy(I, TII, MRI, TRI, RBI); + + return true; + } + + if (selectImpl(I, CoverageInfo)) { + return true; + } + + MachineInstr *MI = nullptr; + using namespace TargetOpcode; + + switch (I.getOpcode()) { + case G_GEP: { + MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDu)) + .add(I.getOperand(0)) + .add(I.getOperand(1)) + .add(I.getOperand(2)); + break; + } + case G_FRAME_INDEX: { + MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ADDiu)) + .add(I.getOperand(0)) + .add(I.getOperand(1)) + .addImm(0); + break; + } + case G_STORE: + case G_LOAD: { + const unsigned DestReg = I.getOperand(0).getReg(); + const unsigned DestRegBank = RBI.getRegBank(DestReg, MRI, TRI)->getID(); + const unsigned OpSize = MRI.getType(DestReg).getSizeInBits(); + + if (DestRegBank != Mips::GPRBRegBankID || OpSize != 32) + return false; + + const unsigned NewOpc = I.getOpcode() == G_STORE ? Mips::SW : Mips::LW; + + MI = BuildMI(MBB, I, I.getDebugLoc(), TII.get(NewOpc)) + .add(I.getOperand(0)) + .add(I.getOperand(1)) + .addImm(0) + .addMemOperand(*I.memoperands_begin()); + break; + } + case G_CONSTANT: { + int Imm = I.getOperand(1).getCImm()->getValue().getLimitedValue(); + unsigned LUiReg = MRI.createVirtualRegister(&Mips::GPR32RegClass); + MachineInstr *LUi, *ORi; + + LUi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::LUi)) + .addDef(LUiReg) + .addImm(Imm >> 16); + + ORi = BuildMI(MBB, I, I.getDebugLoc(), TII.get(Mips::ORi)) + .addDef(I.getOperand(0).getReg()) + .addUse(LUiReg) + .addImm(Imm & 0xFFFF); + + if (!constrainSelectedInstRegOperands(*LUi, TII, TRI, RBI)) + return false; + if (!constrainSelectedInstRegOperands(*ORi, TII, TRI, RBI)) + return false; + + I.eraseFromParent(); + return true; + } + + default: + return false; + } + + I.eraseFromParent(); + return constrainSelectedInstRegOperands(*MI, TII, TRI, RBI); +} + +namespace llvm { +InstructionSelector *createMipsInstructionSelector(const MipsTargetMachine &TM, + MipsSubtarget &Subtarget, + MipsRegisterBankInfo &RBI) { + return new MipsInstructionSelector(TM, Subtarget, RBI); +} +} // end namespace llvm diff --git a/lib/Target/Mips/MipsLegalizerInfo.cpp b/lib/Target/Mips/MipsLegalizerInfo.cpp new file mode 100644 index 000000000000..da6f9dabdaaf --- /dev/null +++ b/lib/Target/Mips/MipsLegalizerInfo.cpp @@ -0,0 +1,41 @@ +//===- MipsLegalizerInfo.cpp ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// This file implements the targeting of the Machinelegalizer class for Mips. +/// \todo This should be generated by TableGen. +//===----------------------------------------------------------------------===// + +#include "MipsLegalizerInfo.h" +#include "MipsTargetMachine.h" + +using namespace llvm; + +MipsLegalizerInfo::MipsLegalizerInfo(const MipsSubtarget &ST) { + using namespace TargetOpcode; + + const LLT s32 = LLT::scalar(32); + const LLT p0 = LLT::pointer(0, 32); + + getActionDefinitionsBuilder(G_ADD).legalFor({s32}); + + getActionDefinitionsBuilder({G_LOAD, G_STORE}) + .legalForCartesianProduct({p0, s32}, {p0}); + + getActionDefinitionsBuilder(G_CONSTANT) + .legalFor({s32}); + + getActionDefinitionsBuilder(G_GEP) + .legalFor({{p0, s32}}); + + getActionDefinitionsBuilder(G_FRAME_INDEX) + .legalFor({p0}); + + computeTables(); + verify(*ST.getInstrInfo()); +} diff --git a/lib/Target/Mips/MipsLegalizerInfo.h b/lib/Target/Mips/MipsLegalizerInfo.h new file mode 100644 index 000000000000..36dd39c8c1c1 --- /dev/null +++ b/lib/Target/Mips/MipsLegalizerInfo.h @@ -0,0 +1,29 @@ +//===- MipsLegalizerInfo ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// This file declares the targeting of the Machinelegalizer class for Mips. +/// \todo This should be generated by TableGen. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_MIPS_MIPSMACHINELEGALIZER_H +#define LLVM_LIB_TARGET_MIPS_MIPSMACHINELEGALIZER_H + +#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" + +namespace llvm { + +class MipsSubtarget; + +/// This class provides legalization strategies. +class MipsLegalizerInfo : public LegalizerInfo { +public: + MipsLegalizerInfo(const MipsSubtarget &ST); +}; +} // end namespace llvm +#endif diff --git a/lib/Target/Mips/MipsMCInstLower.cpp b/lib/Target/Mips/MipsMCInstLower.cpp index a4ab7d3a5780..2b7f64099923 100644 --- a/lib/Target/Mips/MipsMCInstLower.cpp +++ b/lib/Target/Mips/MipsMCInstLower.cpp @@ -219,26 +219,77 @@ lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const { // Lower register operand. OutMI.addOperand(LowerOperand(MI->getOperand(0))); - // Create %hi($tgt-$baltgt). - OutMI.addOperand(createSub(MI->getOperand(1).getMBB(), - MI->getOperand(2).getMBB(), - MipsMCExpr::MEK_HI)); + MipsMCExpr::MipsExprKind Kind; + unsigned TargetFlags = MI->getOperand(1).getTargetFlags(); + switch (TargetFlags) { + case MipsII::MO_HIGHEST: + Kind = MipsMCExpr::MEK_HIGHEST; + break; + case MipsII::MO_HIGHER: + Kind = MipsMCExpr::MEK_HIGHER; + break; + case MipsII::MO_ABS_HI: + Kind = MipsMCExpr::MEK_HI; + break; + case MipsII::MO_ABS_LO: + Kind = MipsMCExpr::MEK_LO; + break; + default: + report_fatal_error("Unexpected flags for lowerLongBranchLUi"); + } + + if (MI->getNumOperands() == 2) { + const MCExpr *Expr = + MCSymbolRefExpr::create(MI->getOperand(1).getMBB()->getSymbol(), *Ctx); + const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, *Ctx); + OutMI.addOperand(MCOperand::createExpr(MipsExpr)); + } else if (MI->getNumOperands() == 3) { + // Create %hi($tgt-$baltgt). + OutMI.addOperand(createSub(MI->getOperand(1).getMBB(), + MI->getOperand(2).getMBB(), Kind)); + } } -void MipsMCInstLower::lowerLongBranchADDiu( - const MachineInstr *MI, MCInst &OutMI, int Opcode, - MipsMCExpr::MipsExprKind Kind) const { +void MipsMCInstLower::lowerLongBranchADDiu(const MachineInstr *MI, + MCInst &OutMI, int Opcode) const { OutMI.setOpcode(Opcode); + MipsMCExpr::MipsExprKind Kind; + unsigned TargetFlags = MI->getOperand(2).getTargetFlags(); + switch (TargetFlags) { + case MipsII::MO_HIGHEST: + Kind = MipsMCExpr::MEK_HIGHEST; + break; + case MipsII::MO_HIGHER: + Kind = MipsMCExpr::MEK_HIGHER; + break; + case MipsII::MO_ABS_HI: + Kind = MipsMCExpr::MEK_HI; + break; + case MipsII::MO_ABS_LO: + Kind = MipsMCExpr::MEK_LO; + break; + default: + report_fatal_error("Unexpected flags for lowerLongBranchADDiu"); + } + // Lower two register operands. for (unsigned I = 0, E = 2; I != E; ++I) { const MachineOperand &MO = MI->getOperand(I); OutMI.addOperand(LowerOperand(MO)); } - // Create %lo($tgt-$baltgt) or %hi($tgt-$baltgt). - OutMI.addOperand(createSub(MI->getOperand(2).getMBB(), - MI->getOperand(3).getMBB(), Kind)); + if (MI->getNumOperands() == 3) { + // Lower register operand. + const MCExpr *Expr = + MCSymbolRefExpr::create(MI->getOperand(2).getMBB()->getSymbol(), *Ctx); + const MipsMCExpr *MipsExpr = MipsMCExpr::create(Kind, Expr, *Ctx); + OutMI.addOperand(MCOperand::createExpr(MipsExpr)); + } else if (MI->getNumOperands() == 4) { + // Create %lo($tgt-$baltgt) or %hi($tgt-$baltgt). + OutMI.addOperand(createSub(MI->getOperand(2).getMBB(), + MI->getOperand(3).getMBB(), Kind)); + } } bool MipsMCInstLower::lowerLongBranch(const MachineInstr *MI, @@ -250,16 +301,10 @@ bool MipsMCInstLower::lowerLongBranch(const MachineInstr *MI, lowerLongBranchLUi(MI, OutMI); return true; case Mips::LONG_BRANCH_ADDiu: - lowerLongBranchADDiu(MI, OutMI, Mips::ADDiu, MipsMCExpr::MEK_LO); + lowerLongBranchADDiu(MI, OutMI, Mips::ADDiu); return true; case Mips::LONG_BRANCH_DADDiu: - unsigned TargetFlags = MI->getOperand(2).getTargetFlags(); - if (TargetFlags == MipsII::MO_ABS_HI) - lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu, MipsMCExpr::MEK_HI); - else if (TargetFlags == MipsII::MO_ABS_LO) - lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu, MipsMCExpr::MEK_LO); - else - report_fatal_error("Unexpected flags for LONG_BRANCH_DADDiu"); + lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu); return true; } } diff --git a/lib/Target/Mips/MipsMCInstLower.h b/lib/Target/Mips/MipsMCInstLower.h index fb5079643827..e19f21c98839 100644 --- a/lib/Target/Mips/MipsMCInstLower.h +++ b/lib/Target/Mips/MipsMCInstLower.h @@ -44,8 +44,8 @@ private: MCOperand createSub(MachineBasicBlock *BB1, MachineBasicBlock *BB2, MipsMCExpr::MipsExprKind Kind) const; void lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const; - void lowerLongBranchADDiu(const MachineInstr *MI, MCInst &OutMI, int Opcode, - MipsMCExpr::MipsExprKind Kind) const; + void lowerLongBranchADDiu(const MachineInstr *MI, MCInst &OutMI, + int Opcode) const; bool lowerLongBranch(const MachineInstr *MI, MCInst &OutMI) const; }; diff --git a/lib/Target/Mips/MipsMSAInstrFormats.td b/lib/Target/Mips/MipsMSAInstrFormats.td index 7d25ea56e3d5..d4e225678184 100644 --- a/lib/Target/Mips/MipsMSAInstrFormats.td +++ b/lib/Target/Mips/MipsMSAInstrFormats.td @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// class MSAInst : MipsInst<(outs), (ins), "", [], NoItinerary, FrmOther>, - PredicateControl, ASE_MSA { + ASE_MSA { let EncodingPredicates = [HasStdEnc]; let Inst{31-26} = 0b011110; } @@ -24,7 +24,8 @@ class MSASpecial : MSAInst { class MSAPseudo<dag outs, dag ins, list<dag> pattern, InstrItinClass itin = IIPseudo>: MipsPseudo<outs, ins, pattern, itin> { - let Predicates = [HasMSA]; + let EncodingPredicates = [HasStdEnc]; + let ASEPredicate = [HasMSA]; } class MSA_BIT_B_FMT<bits<3> major, bits<6> minor>: MSAInst { diff --git a/lib/Target/Mips/MipsMSAInstrInfo.td b/lib/Target/Mips/MipsMSAInstrInfo.td index bf79f0f2ff82..d83f75ffa1c1 100644 --- a/lib/Target/Mips/MipsMSAInstrInfo.td +++ b/lib/Target/Mips/MipsMSAInstrInfo.td @@ -35,14 +35,6 @@ def MipsVAllNonZero : SDNode<"MipsISD::VALL_NONZERO", SDT_MipsVecCond>; def MipsVAnyNonZero : SDNode<"MipsISD::VANY_NONZERO", SDT_MipsVecCond>; def MipsVAllZero : SDNode<"MipsISD::VALL_ZERO", SDT_MipsVecCond>; def MipsVAnyZero : SDNode<"MipsISD::VANY_ZERO", SDT_MipsVecCond>; -def MipsVSMax : SDNode<"MipsISD::VSMAX", SDTIntBinOp, - [SDNPCommutative, SDNPAssociative]>; -def MipsVSMin : SDNode<"MipsISD::VSMIN", SDTIntBinOp, - [SDNPCommutative, SDNPAssociative]>; -def MipsVUMax : SDNode<"MipsISD::VUMAX", SDTIntBinOp, - [SDNPCommutative, SDNPAssociative]>; -def MipsVUMin : SDNode<"MipsISD::VUMIN", SDTIntBinOp, - [SDNPCommutative, SDNPAssociative]>; def MipsVNOR : SDNode<"MipsISD::VNOR", SDTIntBinOp, [SDNPCommutative, SDNPAssociative]>; def MipsVSHF : SDNode<"MipsISD::VSHF", SDT_VSHF>; @@ -54,6 +46,7 @@ def MipsILVR : SDNode<"MipsISD::ILVR", SDT_ILV>; def MipsPCKEV : SDNode<"MipsISD::PCKEV", SDT_ILV>; def MipsPCKOD : SDNode<"MipsISD::PCKOD", SDT_ILV>; def MipsINSVE : SDNode<"MipsISD::INSVE", SDT_INSVE>; +def MipsFMS : SDNode<"MipsISD::FMS", SDTFPTernaryOp>; def vsetcc : SDNode<"ISD::SETCC", SDT_VSetCC>; def vfsetcc : SDNode<"ISD::SETCC", SDT_VFSetCC>; @@ -188,8 +181,28 @@ def vsplati16 : PatFrag<(ops node:$e0), def vsplati32 : PatFrag<(ops node:$e0), (v4i32 (build_vector node:$e0, node:$e0, node:$e0, node:$e0))>; + +def vsplati64_imm_eq_1 : PatLeaf<(bitconvert (v4i32 (build_vector))), [{ + APInt Imm; + SDNode *BV = N->getOperand(0).getNode(); + EVT EltTy = N->getValueType(0).getVectorElementType(); + + return selectVSplat(BV, Imm, EltTy.getSizeInBits()) && + Imm.getBitWidth() == EltTy.getSizeInBits() && Imm == 1; +}]>; + def vsplati64 : PatFrag<(ops node:$e0), (v2i64 (build_vector node:$e0, node:$e0))>; + +def vsplati64_splat_d : PatFrag<(ops node:$e0), + (v2i64 (bitconvert + (v4i32 (and + (v4i32 (build_vector node:$e0, + node:$e0, + node:$e0, + node:$e0)), + vsplati64_imm_eq_1))))>; + def vsplatf32 : PatFrag<(ops node:$e0), (v4f32 (build_vector node:$e0, node:$e0, node:$e0, node:$e0))>; @@ -203,7 +216,8 @@ def vsplati16_elt : PatFrag<(ops node:$v, node:$i), def vsplati32_elt : PatFrag<(ops node:$v, node:$i), (MipsVSHF (vsplati32 node:$i), node:$v, node:$v)>; def vsplati64_elt : PatFrag<(ops node:$v, node:$i), - (MipsVSHF (vsplati64 node:$i), node:$v, node:$v)>; + (MipsVSHF (vsplati64_splat_d node:$i), + node:$v, node:$v)>; class SplatPatLeaf<Operand opclass, dag frag, code pred = [{}], SDNodeXForm xform = NOOP_SDNodeXForm> @@ -334,15 +348,6 @@ def vsplat_imm_eq_1 : PatLeaf<(build_vector), [{ Imm.getBitWidth() == EltTy.getSizeInBits() && Imm == 1; }]>; -def vsplati64_imm_eq_1 : PatLeaf<(bitconvert (v4i32 (build_vector))), [{ - APInt Imm; - SDNode *BV = N->getOperand(0).getNode(); - EVT EltTy = N->getValueType(0).getVectorElementType(); - - return selectVSplat(BV, Imm, EltTy.getSizeInBits()) && - Imm.getBitWidth() == EltTy.getSizeInBits() && Imm == 1; -}]>; - def vbclr_b : PatFrag<(ops node:$ws, node:$wt), (and node:$ws, (xor (shl vsplat_imm_eq_1, node:$wt), immAllOnesV))>; @@ -377,9 +382,6 @@ def vbset_d : PatFrag<(ops node:$ws, node:$wt), (or node:$ws, (shl (v2i64 vsplati64_imm_eq_1), node:$wt))>; -def fms : PatFrag<(ops node:$wd, node:$ws, node:$wt), - (fsub node:$wd, (fmul node:$ws, node:$wt))>; - def muladd : PatFrag<(ops node:$wd, node:$ws, node:$wt), (add node:$wd, (mul node:$ws, node:$wt))>; @@ -1788,6 +1790,7 @@ class CFCMSA_DESC { string AsmString = "cfcmsa\t$rd, $cs"; InstrItinClass Itinerary = NoItinerary; bit hasSideEffects = 1; + bit isMoveReg = 1; } class CLE_S_B_DESC : MSA_3R_DESC_BASE<"cle_s.b", vsetle_v16i8, MSA128BOpnd>; @@ -1882,6 +1885,7 @@ class CTCMSA_DESC { string AsmString = "ctcmsa\t$cd, $rs"; InstrItinClass Itinerary = NoItinerary; bit hasSideEffects = 1; + bit isMoveReg = 1; } class DIV_S_B_DESC : MSA_3R_DESC_BASE<"div_s.b", sdiv, MSA128BOpnd>; @@ -2099,8 +2103,8 @@ class FMIN_A_W_DESC : MSA_3RF_DESC_BASE<"fmin_a.w", int_mips_fmin_a_w, class FMIN_A_D_DESC : MSA_3RF_DESC_BASE<"fmin_a.d", int_mips_fmin_a_d, MSA128DOpnd>; -class FMSUB_W_DESC : MSA_3RF_4RF_DESC_BASE<"fmsub.w", fms, MSA128WOpnd>; -class FMSUB_D_DESC : MSA_3RF_4RF_DESC_BASE<"fmsub.d", fms, MSA128DOpnd>; +class FMSUB_W_DESC : MSA_3RF_4RF_DESC_BASE<"fmsub.w", MipsFMS, MSA128WOpnd>; +class FMSUB_D_DESC : MSA_3RF_4RF_DESC_BASE<"fmsub.d", MipsFMS, MSA128DOpnd>; class FMUL_W_DESC : MSA_3RF_DESC_BASE<"fmul.w", fmul, MSA128WOpnd>; class FMUL_D_DESC : MSA_3RF_DESC_BASE<"fmul.d", fmul, MSA128DOpnd>; @@ -2350,32 +2354,32 @@ class MAX_A_H_DESC : MSA_3R_DESC_BASE<"max_a.h", int_mips_max_a_h, MSA128HOpnd>; class MAX_A_W_DESC : MSA_3R_DESC_BASE<"max_a.w", int_mips_max_a_w, MSA128WOpnd>; class MAX_A_D_DESC : MSA_3R_DESC_BASE<"max_a.d", int_mips_max_a_d, MSA128DOpnd>; -class MAX_S_B_DESC : MSA_3R_DESC_BASE<"max_s.b", MipsVSMax, MSA128BOpnd>; -class MAX_S_H_DESC : MSA_3R_DESC_BASE<"max_s.h", MipsVSMax, MSA128HOpnd>; -class MAX_S_W_DESC : MSA_3R_DESC_BASE<"max_s.w", MipsVSMax, MSA128WOpnd>; -class MAX_S_D_DESC : MSA_3R_DESC_BASE<"max_s.d", MipsVSMax, MSA128DOpnd>; +class MAX_S_B_DESC : MSA_3R_DESC_BASE<"max_s.b", smax, MSA128BOpnd>; +class MAX_S_H_DESC : MSA_3R_DESC_BASE<"max_s.h", smax, MSA128HOpnd>; +class MAX_S_W_DESC : MSA_3R_DESC_BASE<"max_s.w", smax, MSA128WOpnd>; +class MAX_S_D_DESC : MSA_3R_DESC_BASE<"max_s.d", smax, MSA128DOpnd>; -class MAX_U_B_DESC : MSA_3R_DESC_BASE<"max_u.b", MipsVUMax, MSA128BOpnd>; -class MAX_U_H_DESC : MSA_3R_DESC_BASE<"max_u.h", MipsVUMax, MSA128HOpnd>; -class MAX_U_W_DESC : MSA_3R_DESC_BASE<"max_u.w", MipsVUMax, MSA128WOpnd>; -class MAX_U_D_DESC : MSA_3R_DESC_BASE<"max_u.d", MipsVUMax, MSA128DOpnd>; +class MAX_U_B_DESC : MSA_3R_DESC_BASE<"max_u.b", umax, MSA128BOpnd>; +class MAX_U_H_DESC : MSA_3R_DESC_BASE<"max_u.h", umax, MSA128HOpnd>; +class MAX_U_W_DESC : MSA_3R_DESC_BASE<"max_u.w", umax, MSA128WOpnd>; +class MAX_U_D_DESC : MSA_3R_DESC_BASE<"max_u.d", umax, MSA128DOpnd>; -class MAXI_S_B_DESC : MSA_I5_DESC_BASE<"maxi_s.b", MipsVSMax, vsplati8_simm5, +class MAXI_S_B_DESC : MSA_I5_DESC_BASE<"maxi_s.b", smax, vsplati8_simm5, MSA128BOpnd>; -class MAXI_S_H_DESC : MSA_I5_DESC_BASE<"maxi_s.h", MipsVSMax, vsplati16_simm5, +class MAXI_S_H_DESC : MSA_I5_DESC_BASE<"maxi_s.h", smax, vsplati16_simm5, MSA128HOpnd>; -class MAXI_S_W_DESC : MSA_I5_DESC_BASE<"maxi_s.w", MipsVSMax, vsplati32_simm5, +class MAXI_S_W_DESC : MSA_I5_DESC_BASE<"maxi_s.w", smax, vsplati32_simm5, MSA128WOpnd>; -class MAXI_S_D_DESC : MSA_I5_DESC_BASE<"maxi_s.d", MipsVSMax, vsplati64_simm5, +class MAXI_S_D_DESC : MSA_I5_DESC_BASE<"maxi_s.d", smax, vsplati64_simm5, MSA128DOpnd>; -class MAXI_U_B_DESC : MSA_I5_DESC_BASE<"maxi_u.b", MipsVUMax, vsplati8_uimm5, +class MAXI_U_B_DESC : MSA_I5_DESC_BASE<"maxi_u.b", umax, vsplati8_uimm5, MSA128BOpnd>; -class MAXI_U_H_DESC : MSA_I5_DESC_BASE<"maxi_u.h", MipsVUMax, vsplati16_uimm5, +class MAXI_U_H_DESC : MSA_I5_DESC_BASE<"maxi_u.h", umax, vsplati16_uimm5, MSA128HOpnd>; -class MAXI_U_W_DESC : MSA_I5_DESC_BASE<"maxi_u.w", MipsVUMax, vsplati32_uimm5, +class MAXI_U_W_DESC : MSA_I5_DESC_BASE<"maxi_u.w", umax, vsplati32_uimm5, MSA128WOpnd>; -class MAXI_U_D_DESC : MSA_I5_DESC_BASE<"maxi_u.d", MipsVUMax, vsplati64_uimm5, +class MAXI_U_D_DESC : MSA_I5_DESC_BASE<"maxi_u.d", umax, vsplati64_uimm5, MSA128DOpnd>; class MIN_A_B_DESC : MSA_3R_DESC_BASE<"min_a.b", int_mips_min_a_b, MSA128BOpnd>; @@ -2383,32 +2387,32 @@ class MIN_A_H_DESC : MSA_3R_DESC_BASE<"min_a.h", int_mips_min_a_h, MSA128HOpnd>; class MIN_A_W_DESC : MSA_3R_DESC_BASE<"min_a.w", int_mips_min_a_w, MSA128WOpnd>; class MIN_A_D_DESC : MSA_3R_DESC_BASE<"min_a.d", int_mips_min_a_d, MSA128DOpnd>; -class MIN_S_B_DESC : MSA_3R_DESC_BASE<"min_s.b", MipsVSMin, MSA128BOpnd>; -class MIN_S_H_DESC : MSA_3R_DESC_BASE<"min_s.h", MipsVSMin, MSA128HOpnd>; -class MIN_S_W_DESC : MSA_3R_DESC_BASE<"min_s.w", MipsVSMin, MSA128WOpnd>; -class MIN_S_D_DESC : MSA_3R_DESC_BASE<"min_s.d", MipsVSMin, MSA128DOpnd>; +class MIN_S_B_DESC : MSA_3R_DESC_BASE<"min_s.b", smin, MSA128BOpnd>; +class MIN_S_H_DESC : MSA_3R_DESC_BASE<"min_s.h", smin, MSA128HOpnd>; +class MIN_S_W_DESC : MSA_3R_DESC_BASE<"min_s.w", smin, MSA128WOpnd>; +class MIN_S_D_DESC : MSA_3R_DESC_BASE<"min_s.d", smin, MSA128DOpnd>; -class MIN_U_B_DESC : MSA_3R_DESC_BASE<"min_u.b", MipsVUMin, MSA128BOpnd>; -class MIN_U_H_DESC : MSA_3R_DESC_BASE<"min_u.h", MipsVUMin, MSA128HOpnd>; -class MIN_U_W_DESC : MSA_3R_DESC_BASE<"min_u.w", MipsVUMin, MSA128WOpnd>; -class MIN_U_D_DESC : MSA_3R_DESC_BASE<"min_u.d", MipsVUMin, MSA128DOpnd>; +class MIN_U_B_DESC : MSA_3R_DESC_BASE<"min_u.b", umin, MSA128BOpnd>; +class MIN_U_H_DESC : MSA_3R_DESC_BASE<"min_u.h", umin, MSA128HOpnd>; +class MIN_U_W_DESC : MSA_3R_DESC_BASE<"min_u.w", umin, MSA128WOpnd>; +class MIN_U_D_DESC : MSA_3R_DESC_BASE<"min_u.d", umin, MSA128DOpnd>; -class MINI_S_B_DESC : MSA_I5_DESC_BASE<"mini_s.b", MipsVSMin, vsplati8_simm5, +class MINI_S_B_DESC : MSA_I5_DESC_BASE<"mini_s.b", smin, vsplati8_simm5, MSA128BOpnd>; -class MINI_S_H_DESC : MSA_I5_DESC_BASE<"mini_s.h", MipsVSMin, vsplati16_simm5, +class MINI_S_H_DESC : MSA_I5_DESC_BASE<"mini_s.h", smin, vsplati16_simm5, MSA128HOpnd>; -class MINI_S_W_DESC : MSA_I5_DESC_BASE<"mini_s.w", MipsVSMin, vsplati32_simm5, +class MINI_S_W_DESC : MSA_I5_DESC_BASE<"mini_s.w", smin, vsplati32_simm5, MSA128WOpnd>; -class MINI_S_D_DESC : MSA_I5_DESC_BASE<"mini_s.d", MipsVSMin, vsplati64_simm5, +class MINI_S_D_DESC : MSA_I5_DESC_BASE<"mini_s.d", smin, vsplati64_simm5, MSA128DOpnd>; -class MINI_U_B_DESC : MSA_I5_DESC_BASE<"mini_u.b", MipsVUMin, vsplati8_uimm5, +class MINI_U_B_DESC : MSA_I5_DESC_BASE<"mini_u.b", umin, vsplati8_uimm5, MSA128BOpnd>; -class MINI_U_H_DESC : MSA_I5_DESC_BASE<"mini_u.h", MipsVUMin, vsplati16_uimm5, +class MINI_U_H_DESC : MSA_I5_DESC_BASE<"mini_u.h", umin, vsplati16_uimm5, MSA128HOpnd>; -class MINI_U_W_DESC : MSA_I5_DESC_BASE<"mini_u.w", MipsVUMin, vsplati32_uimm5, +class MINI_U_W_DESC : MSA_I5_DESC_BASE<"mini_u.w", umin, vsplati32_uimm5, MSA128WOpnd>; -class MINI_U_D_DESC : MSA_I5_DESC_BASE<"mini_u.d", MipsVUMin, vsplati64_uimm5, +class MINI_U_D_DESC : MSA_I5_DESC_BASE<"mini_u.d", umin, vsplati64_uimm5, MSA128DOpnd>; class MOD_S_B_DESC : MSA_3R_DESC_BASE<"mod_s.b", srem, MSA128BOpnd>; @@ -2427,6 +2431,7 @@ class MOVE_V_DESC { string AsmString = "move.v\t$wd, $ws"; list<dag> Pattern = []; InstrItinClass Itinerary = NoItinerary; + bit isMoveReg = 1; } class MSUB_Q_H_DESC : MSA_3RF_4RF_DESC_BASE<"msub_q.h", int_mips_msub_q_h, @@ -3143,6 +3148,20 @@ def FTRUNC_S_D : FTRUNC_S_D_ENC, FTRUNC_S_D_DESC; def FTRUNC_U_W : FTRUNC_U_W_ENC, FTRUNC_U_W_DESC; def FTRUNC_U_D : FTRUNC_U_D_ENC, FTRUNC_U_D_DESC; +def : MipsPat<(fsub MSA128WOpnd:$wd, (fmul MSA128WOpnd:$ws, MSA128WOpnd:$wt)), + (FMSUB_W MSA128WOpnd:$wd, MSA128WOpnd:$ws, MSA128WOpnd:$wt)>, + ISA_MIPS1, ASE_MSA, FPOP_FUSION_FAST; +def : MipsPat<(fsub MSA128DOpnd:$wd, (fmul MSA128DOpnd:$ws, MSA128DOpnd:$wt)), + (FMSUB_D MSA128DOpnd:$wd, MSA128DOpnd:$ws, MSA128DOpnd:$wt)>, + ISA_MIPS1, ASE_MSA, FPOP_FUSION_FAST; + +def : MipsPat<(fadd MSA128WOpnd:$wd, (fmul MSA128WOpnd:$ws, MSA128WOpnd:$wt)), + (FMADD_W MSA128WOpnd:$wd, MSA128WOpnd:$ws, MSA128WOpnd:$wt)>, + ISA_MIPS1, ASE_MSA, FPOP_FUSION_FAST; +def : MipsPat<(fadd MSA128DOpnd:$wd, (fmul MSA128DOpnd:$ws, MSA128DOpnd:$wt)), + (FMADD_D MSA128DOpnd:$wd, MSA128DOpnd:$ws, MSA128DOpnd:$wt)>, + ISA_MIPS1, ASE_MSA, FPOP_FUSION_FAST; + def HADD_S_H : HADD_S_H_ENC, HADD_S_H_DESC; def HADD_S_W : HADD_S_W_ENC, HADD_S_W_DESC; def HADD_S_D : HADD_S_D_ENC, HADD_S_D_DESC; @@ -3733,7 +3752,7 @@ def SZ_V_PSEUDO : MSA_CBRANCH_PSEUDO_DESC_BASE<MipsVAnyZero, v16i8, // Pseudoes used to implement transparent fp16 support. -let Predicates = [HasMSA] in { +let ASEPredicate = [HasMSA] in { def ST_F16 : MipsPseudo<(outs), (ins MSA128F16:$ws, mem_simm10:$addr), [(store (f16 MSA128F16:$ws), (addrimm10:$addr))]> { let usesCustomInserter = 1; @@ -3773,12 +3792,13 @@ let Predicates = [HasMSA] in { } def : MipsPat<(MipsTruncIntFP MSA128F16:$ws), - (TRUNC_W_D64 (MSA_FP_EXTEND_D_PSEUDO MSA128F16:$ws))>; + (TRUNC_W_D64 (MSA_FP_EXTEND_D_PSEUDO MSA128F16:$ws))>, ISA_MIPS1, + ASE_MSA; def : MipsPat<(MipsFPCmp MSA128F16:$ws, MSA128F16:$wt, imm:$cond), (FCMP_S32 (MSA_FP_EXTEND_W_PSEUDO MSA128F16:$ws), (MSA_FP_EXTEND_W_PSEUDO MSA128F16:$wt), imm:$cond)>, - ISA_MIPS1_NOT_32R6_64R6; + ISA_MIPS1_NOT_32R6_64R6, ASE_MSA; } def vsplati64_imm_eq_63 : PatLeaf<(bitconvert (v4i32 (build_vector))), [{ diff --git a/lib/Target/Mips/MipsMTInstrFormats.td b/lib/Target/Mips/MipsMTInstrFormats.td index edc0981e6278..c2c22e2ad61c 100644 --- a/lib/Target/Mips/MipsMTInstrFormats.td +++ b/lib/Target/Mips/MipsMTInstrFormats.td @@ -15,8 +15,7 @@ // //===----------------------------------------------------------------------===// -class MipsMTInst : MipsInst<(outs), (ins), "", [], NoItinerary, FrmOther>, - PredicateControl { +class MipsMTInst : MipsInst<(outs), (ins), "", [], NoItinerary, FrmOther> { let DecoderNamespace = "Mips"; let EncodingPredicates = [HasStdEnc]; } diff --git a/lib/Target/Mips/MipsMachineFunction.cpp b/lib/Target/Mips/MipsMachineFunction.cpp index 1ee56d830090..81b4352670c0 100644 --- a/lib/Target/Mips/MipsMachineFunction.cpp +++ b/lib/Target/Mips/MipsMachineFunction.cpp @@ -29,25 +29,27 @@ bool MipsFunctionInfo::globalBaseRegSet() const { return GlobalBaseReg; } +static const TargetRegisterClass &getGlobalBaseRegClass(MachineFunction &MF) { + auto &STI = static_cast<const MipsSubtarget &>(MF.getSubtarget()); + auto &TM = static_cast<const MipsTargetMachine &>(MF.getTarget()); + + if (STI.inMips16Mode()) + return Mips::CPU16RegsRegClass; + + if (STI.inMicroMipsMode()) + return Mips::GPRMM16RegClass; + + if (TM.getABI().IsN64()) + return Mips::GPR64RegClass; + + return Mips::GPR32RegClass; +} + unsigned MipsFunctionInfo::getGlobalBaseReg() { - // Return if it has already been initialized. - if (GlobalBaseReg) - return GlobalBaseReg; - - MipsSubtarget const &STI = - static_cast<const MipsSubtarget &>(MF.getSubtarget()); - - const TargetRegisterClass *RC = - STI.inMips16Mode() - ? &Mips::CPU16RegsRegClass - : STI.inMicroMipsMode() - ? &Mips::GPRMM16RegClass - : static_cast<const MipsTargetMachine &>(MF.getTarget()) - .getABI() - .IsN64() - ? &Mips::GPR64RegClass - : &Mips::GPR32RegClass; - return GlobalBaseReg = MF.getRegInfo().createVirtualRegister(RC); + if (!GlobalBaseReg) + GlobalBaseReg = + MF.getRegInfo().createVirtualRegister(&getGlobalBaseRegClass(MF)); + return GlobalBaseReg; } void MipsFunctionInfo::createEhDataRegsFI() { diff --git a/lib/Target/Mips/MipsModuleISelDAGToDAG.cpp b/lib/Target/Mips/MipsModuleISelDAGToDAG.cpp index ceacaa498389..a2b55e8bddcd 100644 --- a/lib/Target/Mips/MipsModuleISelDAGToDAG.cpp +++ b/lib/Target/Mips/MipsModuleISelDAGToDAG.cpp @@ -11,6 +11,7 @@ #include "Mips.h" #include "MipsTargetMachine.h" #include "llvm/CodeGen/TargetPassConfig.h" +#include "llvm/CodeGen/StackProtector.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" @@ -32,6 +33,7 @@ namespace { void getAnalysisUsage(AnalysisUsage &AU) const override { AU.addRequired<TargetPassConfig>(); + AU.addPreserved<StackProtector>(); MachineFunctionPass::getAnalysisUsage(AU); } @@ -42,7 +44,7 @@ namespace { } bool MipsModuleDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) { - DEBUG(errs() << "In MipsModuleDAGToDAGISel::runMachineFunction\n"); + LLVM_DEBUG(errs() << "In MipsModuleDAGToDAGISel::runMachineFunction\n"); auto &TPC = getAnalysis<TargetPassConfig>(); auto &TM = TPC.getTM<MipsTargetMachine>(); TM.resetSubtarget(&MF); diff --git a/lib/Target/Mips/MipsOptimizePICCall.cpp b/lib/Target/Mips/MipsOptimizePICCall.cpp index a9ca31a6d09f..27bc4843f410 100644 --- a/lib/Target/Mips/MipsOptimizePICCall.cpp +++ b/lib/Target/Mips/MipsOptimizePICCall.cpp @@ -27,7 +27,6 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/MachineValueType.h" #include "llvm/CodeGen/TargetInstrInfo.h" #include "llvm/CodeGen/TargetOpcodes.h" #include "llvm/CodeGen/TargetRegisterInfo.h" @@ -35,6 +34,7 @@ #include "llvm/Support/Allocator.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MachineValueType.h" #include "llvm/Support/RecyclingAllocator.h" #include <cassert> #include <utility> @@ -90,10 +90,10 @@ public: } private: - /// \brief Visit MBB. + /// Visit MBB. bool visitNode(MBBInfo &MBBI); - /// \brief Test if MI jumps to a function via a register. + /// Test if MI jumps to a function via a register. /// /// Also, return the virtual register containing the target function's address /// and the underlying object in Reg and Val respectively, if the function's @@ -101,15 +101,15 @@ private: bool isCallViaRegister(MachineInstr &MI, unsigned &Reg, ValueType &Val) const; - /// \brief Return the number of instructions that dominate the current + /// Return the number of instructions that dominate the current /// instruction and load the function address from object Entry. unsigned getCount(ValueType Entry); - /// \brief Return the destination virtual register of the last instruction + /// Return the destination virtual register of the last instruction /// that loads from object Entry. unsigned getReg(ValueType Entry); - /// \brief Update ScopedHT. + /// Update ScopedHT. void incCntAndSetReg(ValueType Entry, unsigned Reg); ScopedHTType ScopedHT; diff --git a/lib/Target/Mips/MipsOs16.cpp b/lib/Target/Mips/MipsOs16.cpp index 7ee45c28a7d0..4edcb3132ada 100644 --- a/lib/Target/Mips/MipsOs16.cpp +++ b/lib/Target/Mips/MipsOs16.cpp @@ -96,7 +96,8 @@ static bool needsFP(Function &F) { ; } if (const CallInst *CI = dyn_cast<CallInst>(I)) { - DEBUG(dbgs() << "Working on call" << "\n"); + LLVM_DEBUG(dbgs() << "Working on call" + << "\n"); Function &F_ = *CI->getCalledFunction(); if (needsFPFromSig(F_)) return true; @@ -110,9 +111,10 @@ 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"); + LLVM_DEBUG(dbgs() << "Run on Module MipsOs16 \n" + << Mips32FunctionMask << "\n"); if (usingMask) - DEBUG(dbgs() << "using mask \n" << Mips32FunctionMask << "\n"); + LLVM_DEBUG(dbgs() << "using mask \n" << Mips32FunctionMask << "\n"); unsigned int functionIndex = 0; bool modified = false; @@ -121,14 +123,14 @@ bool MipsOs16::runOnModule(Module &M) { if (F.isDeclaration()) continue; - DEBUG(dbgs() << "Working on " << F.getName() << "\n"); + LLVM_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"); + LLVM_DEBUG(dbgs() << "mask forced mips32: " << F.getName() << "\n"); F.addFnAttr("nomips16"); break; case '.': @@ -142,11 +144,11 @@ bool MipsOs16::runOnModule(Module &M) { } else { if (needsFP(F)) { - DEBUG(dbgs() << "os16 forced mips32: " << F.getName() << "\n"); + LLVM_DEBUG(dbgs() << "os16 forced mips32: " << F.getName() << "\n"); F.addFnAttr("nomips16"); } else { - DEBUG(dbgs() << "os16 forced mips16: " << F.getName() << "\n"); + LLVM_DEBUG(dbgs() << "os16 forced mips16: " << F.getName() << "\n"); F.addFnAttr("mips16"); } } diff --git a/lib/Target/Mips/MipsRegisterBankInfo.cpp b/lib/Target/Mips/MipsRegisterBankInfo.cpp new file mode 100644 index 000000000000..cef21f447205 --- /dev/null +++ b/lib/Target/Mips/MipsRegisterBankInfo.cpp @@ -0,0 +1,100 @@ +//===- MipsRegisterBankInfo.cpp ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// This file implements the targeting of the RegisterBankInfo class for Mips. +/// \todo This should be generated by TableGen. +//===----------------------------------------------------------------------===// + +#include "MipsInstrInfo.h" +#include "MipsRegisterBankInfo.h" +#include "llvm/CodeGen/MachineRegisterInfo.h" + +#define GET_TARGET_REGBANK_IMPL + +#define DEBUG_TYPE "registerbankinfo" + +#include "MipsGenRegisterBank.inc" + +namespace llvm { +namespace Mips { +enum PartialMappingIdx { + PMI_GPR, + PMI_Min = PMI_GPR, +}; + +RegisterBankInfo::PartialMapping PartMappings[]{ + {0, 32, GPRBRegBank} +}; + +enum ValueMappingIdx { InvalidIdx = 0, GPRIdx = 1 }; + +RegisterBankInfo::ValueMapping ValueMappings[] = { + // invalid + {nullptr, 0}, + // 3 operands in GPRs + {&PartMappings[PMI_GPR - PMI_Min], 1}, + {&PartMappings[PMI_GPR - PMI_Min], 1}, + {&PartMappings[PMI_GPR - PMI_Min], 1}}; + +} // end namespace Mips +} // end namespace llvm + +using namespace llvm; + +MipsRegisterBankInfo::MipsRegisterBankInfo(const TargetRegisterInfo &TRI) + : MipsGenRegisterBankInfo() {} + +const RegisterBank &MipsRegisterBankInfo::getRegBankFromRegClass( + const TargetRegisterClass &RC) const { + using namespace Mips; + + switch (RC.getID()) { + case Mips::GPR32RegClassID: + case Mips::CPU16Regs_and_GPRMM16ZeroRegClassID: + case Mips::GPRMM16MoveP_and_CPU16Regs_and_GPRMM16ZeroRegClassID: + case Mips::SP32RegClassID: + return getRegBank(Mips::GPRBRegBankID); + default: + llvm_unreachable("Register class not supported"); + } +} + +const RegisterBankInfo::InstructionMapping & +MipsRegisterBankInfo::getInstrMapping(const MachineInstr &MI) const { + + unsigned Opc = MI.getOpcode(); + + const RegisterBankInfo::InstructionMapping &Mapping = getInstrMappingImpl(MI); + if (Mapping.isValid()) + return Mapping; + + using namespace TargetOpcode; + + unsigned NumOperands = MI.getNumOperands(); + const ValueMapping *OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx]; + + switch (Opc) { + case G_ADD: + case G_LOAD: + case G_STORE: + case G_GEP: + OperandsMapping = &Mips::ValueMappings[Mips::GPRIdx]; + break; + case G_CONSTANT: + case G_FRAME_INDEX: + OperandsMapping = + getOperandsMapping({&Mips::ValueMappings[Mips::GPRIdx], nullptr}); + break; + default: + return getInvalidInstructionMapping(); + } + + return getInstructionMapping(DefaultMappingID, /*Cost=*/1, OperandsMapping, + NumOperands); +} diff --git a/lib/Target/Mips/MipsRegisterBankInfo.h b/lib/Target/Mips/MipsRegisterBankInfo.h new file mode 100644 index 000000000000..64a79abaa74d --- /dev/null +++ b/lib/Target/Mips/MipsRegisterBankInfo.h @@ -0,0 +1,43 @@ +//===- MipsRegisterBankInfo.h -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// This file declares the targeting of the RegisterBankInfo class for Mips. +/// \todo This should be generated by TableGen. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LIB_TARGET_MIPS_MIPSREGISTERBANKINFO_H +#define LLVM_LIB_TARGET_MIPS_MIPSREGISTERBANKINFO_H + +#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h" + +#define GET_REGBANK_DECLARATIONS +#include "MipsGenRegisterBank.inc" + +namespace llvm { + +class TargetRegisterInfo; + +class MipsGenRegisterBankInfo : public RegisterBankInfo { +#define GET_TARGET_REGBANK_CLASS +#include "MipsGenRegisterBank.inc" +}; + +/// This class provides the information for the target register banks. +class MipsRegisterBankInfo final : public MipsGenRegisterBankInfo { +public: + MipsRegisterBankInfo(const TargetRegisterInfo &TRI); + + const RegisterBank & + getRegBankFromRegClass(const TargetRegisterClass &RC) const override; + + const InstructionMapping & + getInstrMapping(const MachineInstr &MI) const override; +}; +} // end namespace llvm +#endif diff --git a/lib/Target/Mips/MipsRegisterBanks.td b/lib/Target/Mips/MipsRegisterBanks.td new file mode 100644 index 000000000000..5f1687048fac --- /dev/null +++ b/lib/Target/Mips/MipsRegisterBanks.td @@ -0,0 +1,13 @@ +//===- MipsRegisterBank.td ---------------------------------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +//===----------------------------------------------------------------------===// + +def GPRBRegBank : RegisterBank<"GPRB", [GPR32]>; diff --git a/lib/Target/Mips/MipsRegisterInfo.cpp b/lib/Target/Mips/MipsRegisterInfo.cpp index 0e0d82270c89..3c108c2ba9b7 100644 --- a/lib/Target/Mips/MipsRegisterInfo.cpp +++ b/lib/Target/Mips/MipsRegisterInfo.cpp @@ -275,18 +275,20 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj, MachineInstr &MI = *II; MachineFunction &MF = *MI.getParent()->getParent(); - DEBUG(errs() << "\nFunction : " << MF.getName() << "\n"; - errs() << "<--------->\n" << MI); + LLVM_DEBUG(errs() << "\nFunction : " << MF.getName() << "\n"; + errs() << "<--------->\n" + << MI); int FrameIndex = MI.getOperand(FIOperandNum).getIndex(); uint64_t stackSize = MF.getFrameInfo().getStackSize(); int64_t spOffset = MF.getFrameInfo().getObjectOffset(FrameIndex); - DEBUG(errs() << "FrameIndex : " << FrameIndex << "\n" - << "spOffset : " << spOffset << "\n" - << "stackSize : " << stackSize << "\n" - << "alignment : " - << MF.getFrameInfo().getObjectAlignment(FrameIndex) << "\n"); + LLVM_DEBUG(errs() << "FrameIndex : " << FrameIndex << "\n" + << "spOffset : " << spOffset << "\n" + << "stackSize : " << stackSize << "\n" + << "alignment : " + << MF.getFrameInfo().getObjectAlignment(FrameIndex) + << "\n"); eliminateFI(MI, FIOperandNum, FrameIndex, stackSize, spOffset); } diff --git a/lib/Target/Mips/MipsRegisterInfo.h b/lib/Target/Mips/MipsRegisterInfo.h index fe8d7953ec8f..4cc50fb981ba 100644 --- a/lib/Target/Mips/MipsRegisterInfo.h +++ b/lib/Target/Mips/MipsRegisterInfo.h @@ -57,6 +57,8 @@ public: BitVector getReservedRegs(const MachineFunction &MF) const override; + bool enableMultipleCopyHints() const override { return true; } + bool requiresRegisterScavenging(const MachineFunction &MF) const override; bool trackLivenessAfterRegAlloc(const MachineFunction &MF) const override; @@ -72,7 +74,7 @@ public: /// Debug information queries. unsigned getFrameRegister(const MachineFunction &MF) const override; - /// \brief Return GPR register class. + /// Return GPR register class. virtual const TargetRegisterClass *intRegClass(unsigned Size) const = 0; private: diff --git a/lib/Target/Mips/MipsSEFrameLowering.cpp b/lib/Target/Mips/MipsSEFrameLowering.cpp index eb1eea7925c0..687c9f676b34 100644 --- a/lib/Target/Mips/MipsSEFrameLowering.cpp +++ b/lib/Target/Mips/MipsSEFrameLowering.cpp @@ -394,7 +394,6 @@ MipsSEFrameLowering::MipsSEFrameLowering(const MipsSubtarget &STI) void MipsSEFrameLowering::emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const { - assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported"); MachineFrameInfo &MFI = MF.getFrameInfo(); MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); @@ -682,7 +681,7 @@ void MipsSEFrameLowering::emitInterruptPrologueStub( void MipsSEFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { - MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); + MachineBasicBlock::iterator MBBI = MBB.getFirstTerminator(); MachineFrameInfo &MFI = MF.getFrameInfo(); MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>(); @@ -691,7 +690,7 @@ void MipsSEFrameLowering::emitEpilogue(MachineFunction &MF, const MipsRegisterInfo &RegInfo = *static_cast<const MipsRegisterInfo *>(STI.getRegisterInfo()); - DebugLoc DL = MBBI->getDebugLoc(); + DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); MipsABIInfo ABI = STI.getABI(); unsigned SP = ABI.GetStackPtr(); unsigned FP = ABI.GetFramePtr(); @@ -790,7 +789,6 @@ spillCalleeSavedRegisters(MachineBasicBlock &MBB, const std::vector<CalleeSavedInfo> &CSI, const TargetRegisterInfo *TRI) const { MachineFunction *MF = MBB.getParent(); - MachineBasicBlock *EntryBlock = &MF->front(); const TargetInstrInfo &TII = *STI.getInstrInfo(); for (unsigned i = 0, e = CSI.size(); i != e; ++i) { @@ -803,7 +801,7 @@ spillCalleeSavedRegisters(MachineBasicBlock &MBB, bool IsRAAndRetAddrIsTaken = (Reg == Mips::RA || Reg == Mips::RA_64) && MF->getFrameInfo().isReturnAddressTaken(); if (!IsRAAndRetAddrIsTaken) - EntryBlock->addLiveIn(Reg); + MBB.addLiveIn(Reg); // ISRs require HI/LO to be spilled into kernel registers to be then // spilled to the stack frame. @@ -828,7 +826,7 @@ spillCalleeSavedRegisters(MachineBasicBlock &MBB, // Insert the spill to the stack frame. bool IsKill = !IsRAAndRetAddrIsTaken; const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg); - TII.storeRegToStackSlot(*EntryBlock, MI, Reg, IsKill, + TII.storeRegToStackSlot(MBB, MI, Reg, IsKill, CSI[i].getFrameIdx(), RC, TRI); } @@ -882,9 +880,10 @@ void MipsSEFrameLowering::determineCalleeSaves(MachineFunction &MF, // Expand pseudo instructions which load, store or copy accumulators. // Add an emergency spill slot if a pseudo was expanded. if (ExpandPseudo(MF).expand()) { - // The spill slot should be half the size of the accumulator. If target is - // mips64, it should be 64-bit, otherwise it should be 32-bt. - const TargetRegisterClass &RC = STI.hasMips64() ? + // The spill slot should be half the size of the accumulator. If target have + // general-purpose registers 64 bits wide, it should be 64-bit, otherwise + // it should be 32-bit. + const TargetRegisterClass &RC = STI.isGP64bit() ? Mips::GPR64RegClass : Mips::GPR32RegClass; int FI = MF.getFrameInfo().CreateStackObject(TRI->getSpillSize(RC), TRI->getSpillAlignment(RC), diff --git a/lib/Target/Mips/MipsSEFrameLowering.h b/lib/Target/Mips/MipsSEFrameLowering.h index de8e6eed31d7..cb2119d6880b 100644 --- a/lib/Target/Mips/MipsSEFrameLowering.h +++ b/lib/Target/Mips/MipsSEFrameLowering.h @@ -40,7 +40,6 @@ public: void determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, RegScavenger *RS) const override; - unsigned ehDataReg(unsigned I) const; private: void emitInterruptEpilogueStub(MachineFunction &MF, diff --git a/lib/Target/Mips/MipsSEISelDAGToDAG.cpp b/lib/Target/Mips/MipsSEISelDAGToDAG.cpp index 893cae93e58f..599c1e913acf 100644 --- a/lib/Target/Mips/MipsSEISelDAGToDAG.cpp +++ b/lib/Target/Mips/MipsSEISelDAGToDAG.cpp @@ -288,7 +288,7 @@ void MipsSEDAGToDAGISel::selectAddE(SDNode *Node, const SDLoc &DL) const { SDValue(Carry, 0)}; SDNode *DSPCFWithCarry = CurDAG->getMachineNode(Mips::INS, DL, MVT::i32, Ops); - // My reading of the the MIPS DSP 3.01 specification isn't as clear as I + // My reading of the MIPS DSP 3.01 specification isn't as clear as I // would like about whether bit 20 always gets overwritten by addwc. // Hence take an extremely conservative view and presume it's sticky. We // therefore need to clear it. @@ -976,9 +976,9 @@ bool MipsSEDAGToDAGISel::trySelect(SDNode *Node) { } SDNode *Rdhwr = - CurDAG->getMachineNode(RdhwrOpc, DL, - Node->getValueType(0), - CurDAG->getRegister(Mips::HWR29, MVT::i32)); + CurDAG->getMachineNode(RdhwrOpc, DL, Node->getValueType(0), + CurDAG->getRegister(Mips::HWR29, MVT::i32), + CurDAG->getTargetConstant(0, DL, MVT::i32)); SDValue Chain = CurDAG->getCopyToReg(CurDAG->getEntryNode(), DL, DestReg, SDValue(Rdhwr, 0)); SDValue ResNode = CurDAG->getCopyFromReg(Chain, DL, DestReg, PtrVT); diff --git a/lib/Target/Mips/MipsSEISelDAGToDAG.h b/lib/Target/Mips/MipsSEISelDAGToDAG.h index 6f38289c5a45..eb3657aae050 100644 --- a/lib/Target/Mips/MipsSEISelDAGToDAG.h +++ b/lib/Target/Mips/MipsSEISelDAGToDAG.h @@ -93,37 +93,37 @@ private: bool selectIntAddrSImm10Lsl3(SDValue Addr, SDValue &Base, SDValue &Offset) const override; - /// \brief Select constant vector splats. + /// Select constant vector splats. bool selectVSplat(SDNode *N, APInt &Imm, unsigned MinSizeInBits) const override; - /// \brief Select constant vector splats whose value fits in a given integer. + /// Select constant vector splats whose value fits in a given integer. bool selectVSplatCommon(SDValue N, SDValue &Imm, bool Signed, unsigned ImmBitSize) const; - /// \brief Select constant vector splats whose value fits in a uimm1. + /// Select constant vector splats whose value fits in a uimm1. bool selectVSplatUimm1(SDValue N, SDValue &Imm) const override; - /// \brief Select constant vector splats whose value fits in a uimm2. + /// Select constant vector splats whose value fits in a uimm2. bool selectVSplatUimm2(SDValue N, SDValue &Imm) const override; - /// \brief Select constant vector splats whose value fits in a uimm3. + /// Select constant vector splats whose value fits in a uimm3. bool selectVSplatUimm3(SDValue N, SDValue &Imm) const override; - /// \brief Select constant vector splats whose value fits in a uimm4. + /// Select constant vector splats whose value fits in a uimm4. bool selectVSplatUimm4(SDValue N, SDValue &Imm) const override; - /// \brief Select constant vector splats whose value fits in a uimm5. + /// Select constant vector splats whose value fits in a uimm5. bool selectVSplatUimm5(SDValue N, SDValue &Imm) const override; - /// \brief Select constant vector splats whose value fits in a uimm6. + /// Select constant vector splats whose value fits in a uimm6. bool selectVSplatUimm6(SDValue N, SDValue &Imm) const override; - /// \brief Select constant vector splats whose value fits in a uimm8. + /// Select constant vector splats whose value fits in a uimm8. bool selectVSplatUimm8(SDValue N, SDValue &Imm) const override; - /// \brief Select constant vector splats whose value fits in a simm5. + /// Select constant vector splats whose value fits in a simm5. bool selectVSplatSimm5(SDValue N, SDValue &Imm) const override; - /// \brief Select constant vector splats whose value is a power of 2. + /// Select constant vector splats whose value is a power of 2. bool selectVSplatUimmPow2(SDValue N, SDValue &Imm) const override; - /// \brief Select constant vector splats whose value is the inverse of a + /// Select constant vector splats whose value is the inverse of a /// power of 2. bool selectVSplatUimmInvPow2(SDValue N, SDValue &Imm) const override; - /// \brief Select constant vector splats whose value is a run of set bits + /// Select constant vector splats whose value is a run of set bits /// ending at the most significant bit bool selectVSplatMaskL(SDValue N, SDValue &Imm) const override; - /// \brief Select constant vector splats whose value is a run of set bits + /// Select constant vector splats whose value is a run of set bits /// starting at bit zero. bool selectVSplatMaskR(SDValue N, SDValue &Imm) const override; diff --git a/lib/Target/Mips/MipsSEISelLowering.cpp b/lib/Target/Mips/MipsSEISelLowering.cpp index f7d7e2af85e4..f625a2903bd7 100644 --- a/lib/Target/Mips/MipsSEISelLowering.cpp +++ b/lib/Target/Mips/MipsSEISelLowering.cpp @@ -28,7 +28,6 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineMemOperand.h" #include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/MachineValueType.h" #include "llvm/CodeGen/SelectionDAG.h" #include "llvm/CodeGen/SelectionDAGNodes.h" #include "llvm/CodeGen/TargetInstrInfo.h" @@ -40,6 +39,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MachineValueType.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> @@ -104,6 +104,11 @@ MipsSETargetLowering::MipsSETargetLowering(const MipsTargetMachine &TM, setTargetDAGCombine(ISD::SRL); setTargetDAGCombine(ISD::SETCC); setTargetDAGCombine(ISD::VSELECT); + + if (Subtarget.hasMips32r2()) { + setOperationAction(ISD::ADDC, MVT::i32, Legal); + setOperationAction(ISD::ADDE, MVT::i32, Legal); + } } if (Subtarget.hasDSPR2()) @@ -331,8 +336,12 @@ addMSAIntType(MVT::SimpleValueType Ty, const TargetRegisterClass *RC) { setOperationAction(ISD::SRA, Ty, Legal); setOperationAction(ISD::SRL, Ty, Legal); setOperationAction(ISD::SUB, Ty, Legal); + setOperationAction(ISD::SMAX, Ty, Legal); + setOperationAction(ISD::SMIN, Ty, Legal); setOperationAction(ISD::UDIV, Ty, Legal); setOperationAction(ISD::UREM, Ty, Legal); + setOperationAction(ISD::UMAX, Ty, Legal); + setOperationAction(ISD::UMIN, Ty, Legal); setOperationAction(ISD::VECTOR_SHUFFLE, Ty, Custom); setOperationAction(ISD::VSELECT, Ty, Legal); setOperationAction(ISD::XOR, Ty, Legal); @@ -701,6 +710,77 @@ static SDValue performORCombine(SDNode *N, SelectionDAG &DAG, return SDValue(); } +static bool shouldTransformMulToShiftsAddsSubs(APInt C, EVT VT, + SelectionDAG &DAG, + const MipsSubtarget &Subtarget) { + // Estimate the number of operations the below transform will turn a + // constant multiply into. The number is approximately how many powers + // of two summed together that the constant can be broken down into. + + SmallVector<APInt, 16> WorkStack(1, C); + unsigned Steps = 0; + unsigned BitWidth = C.getBitWidth(); + + while (!WorkStack.empty()) { + APInt Val = WorkStack.pop_back_val(); + + if (Val == 0 || Val == 1) + continue; + + if (Val.isPowerOf2()) { + ++Steps; + continue; + } + + APInt Floor = APInt(BitWidth, 1) << Val.logBase2(); + APInt Ceil = Val.isNegative() ? APInt(BitWidth, 0) + : APInt(BitWidth, 1) << C.ceilLogBase2(); + + if ((Val - Floor).ule(Ceil - Val)) { + WorkStack.push_back(Floor); + WorkStack.push_back(Val - Floor); + ++Steps; + continue; + } + + WorkStack.push_back(Ceil); + WorkStack.push_back(Ceil - Val); + ++Steps; + + // If we have taken more than 12[1] / 8[2] steps to attempt the + // optimization for a native sized value, it is more than likely that this + // optimization will make things worse. + // + // [1] MIPS64 requires 6 instructions at most to materialize any constant, + // multiplication requires at least 4 cycles, but another cycle (or two) + // to retrieve the result from the HI/LO registers. + // + // [2] For MIPS32, more than 8 steps is expensive as the constant could be + // materialized in 2 instructions, multiplication requires at least 4 + // cycles, but another cycle (or two) to retrieve the result from the + // HI/LO registers. + + if (Steps > 12 && (Subtarget.isABI_N32() || Subtarget.isABI_N64())) + return false; + + if (Steps > 8 && Subtarget.isABI_O32()) + return false; + } + + // If the value being multiplied is not supported natively, we have to pay + // an additional legalization cost, conservatively assume an increase in the + // cost of 3 instructions per step. This values for this heuristic were + // determined experimentally. + unsigned RegisterSize = DAG.getTargetLoweringInfo() + .getRegisterType(*DAG.getContext(), VT) + .getSizeInBits(); + Steps *= (VT.getSizeInBits() != RegisterSize) * 3; + if (Steps > 27) + return false; + + return true; +} + static SDValue genConstMult(SDValue X, APInt C, const SDLoc &DL, EVT VT, EVT ShiftTy, SelectionDAG &DAG) { // Return 0. @@ -739,11 +819,13 @@ static SDValue genConstMult(SDValue X, APInt C, const SDLoc &DL, EVT VT, static SDValue performMULCombine(SDNode *N, SelectionDAG &DAG, const TargetLowering::DAGCombinerInfo &DCI, - const MipsSETargetLowering *TL) { + const MipsSETargetLowering *TL, + const MipsSubtarget &Subtarget) { EVT VT = N->getValueType(0); if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(N->getOperand(1))) - if (!VT.isVector()) + if (!VT.isVector() && shouldTransformMulToShiftsAddsSubs( + C->getAPIntValue(), VT, DAG, Subtarget)) return genConstMult(N->getOperand(0), C->getAPIntValue(), SDLoc(N), VT, TL->getScalarShiftAmountTy(DAG.getDataLayout(), VT), DAG); @@ -890,46 +972,7 @@ static SDValue performSETCCCombine(SDNode *N, SelectionDAG &DAG) { static SDValue performVSELECTCombine(SDNode *N, SelectionDAG &DAG) { EVT Ty = N->getValueType(0); - if (Ty.is128BitVector() && Ty.isInteger()) { - // Try the following combines: - // (vselect (setcc $a, $b, SETLT), $b, $a)) -> (vsmax $a, $b) - // (vselect (setcc $a, $b, SETLE), $b, $a)) -> (vsmax $a, $b) - // (vselect (setcc $a, $b, SETLT), $a, $b)) -> (vsmin $a, $b) - // (vselect (setcc $a, $b, SETLE), $a, $b)) -> (vsmin $a, $b) - // (vselect (setcc $a, $b, SETULT), $b, $a)) -> (vumax $a, $b) - // (vselect (setcc $a, $b, SETULE), $b, $a)) -> (vumax $a, $b) - // (vselect (setcc $a, $b, SETULT), $a, $b)) -> (vumin $a, $b) - // (vselect (setcc $a, $b, SETULE), $a, $b)) -> (vumin $a, $b) - // SETGT/SETGE/SETUGT/SETUGE variants of these will show up initially but - // will be expanded to equivalent SETLT/SETLE/SETULT/SETULE versions by the - // legalizer. - SDValue Op0 = N->getOperand(0); - - if (Op0->getOpcode() != ISD::SETCC) - return SDValue(); - - ISD::CondCode CondCode = cast<CondCodeSDNode>(Op0->getOperand(2))->get(); - bool Signed; - - if (CondCode == ISD::SETLT || CondCode == ISD::SETLE) - Signed = true; - else if (CondCode == ISD::SETULT || CondCode == ISD::SETULE) - Signed = false; - else - return SDValue(); - - SDValue Op1 = N->getOperand(1); - SDValue Op2 = N->getOperand(2); - SDValue Op0Op0 = Op0->getOperand(0); - SDValue Op0Op1 = Op0->getOperand(1); - - if (Op1 == Op0Op0 && Op2 == Op0Op1) - return DAG.getNode(Signed ? MipsISD::VSMIN : MipsISD::VUMIN, SDLoc(N), - Ty, Op1, Op2); - else if (Op1 == Op0Op1 && Op2 == Op0Op0) - return DAG.getNode(Signed ? MipsISD::VSMAX : MipsISD::VUMAX, SDLoc(N), - Ty, Op1, Op2); - } else if ((Ty == MVT::v2i16) || (Ty == MVT::v4i8)) { + if (Ty == MVT::v2i16 || Ty == MVT::v4i8) { SDValue SetCC = N->getOperand(0); if (SetCC.getOpcode() != MipsISD::SETCC_DSP) @@ -983,7 +1026,7 @@ MipsSETargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { Val = performORCombine(N, DAG, DCI, Subtarget); break; case ISD::MUL: - return performMULCombine(N, DAG, DCI, this); + return performMULCombine(N, DAG, DCI, this, Subtarget); case ISD::SHL: Val = performSHLCombine(N, DAG, DCI, Subtarget); break; @@ -1002,11 +1045,9 @@ MipsSETargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const { } if (Val.getNode()) { - DEBUG(dbgs() << "\nMipsSE DAG Combine:\n"; - N->printrWithDepth(dbgs(), &DAG); - dbgs() << "\n=> \n"; - Val.getNode()->printrWithDepth(dbgs(), &DAG); - dbgs() << "\n"); + LLVM_DEBUG(dbgs() << "\nMipsSE DAG Combine:\n"; + N->printrWithDepth(dbgs(), &DAG); dbgs() << "\n=> \n"; + Val.getNode()->printrWithDepth(dbgs(), &DAG); dbgs() << "\n"); return Val; } @@ -1305,7 +1346,16 @@ static SDValue lowerMSASplatZExt(SDValue Op, unsigned OpNr, SelectionDAG &DAG) { SDValue LaneB; if (ResVecTy == MVT::v2i64) { - LaneB = DAG.getConstant(0, DL, MVT::i32); + // In case of the index being passed as an immediate value, set the upper + // lane to 0 so that the splati.d instruction can be matched. + if (isa<ConstantSDNode>(LaneA)) + LaneB = DAG.getConstant(0, DL, MVT::i32); + // Having the index passed in a register, set the upper lane to the same + // value as the lower - this results in the BUILD_VECTOR node not being + // expanded through stack. This way we are able to pattern match the set of + // nodes created here to splat.d. + else + LaneB = LaneA; ViaVecTy = MVT::v4i32; if(BigEndian) std::swap(LaneA, LaneB); @@ -1820,10 +1870,8 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op, case Intrinsic::mips_fmsub_w: case Intrinsic::mips_fmsub_d: { // TODO: If intrinsics have fast-math-flags, propagate them. - EVT ResTy = Op->getValueType(0); - return DAG.getNode(ISD::FSUB, SDLoc(Op), ResTy, Op->getOperand(1), - DAG.getNode(ISD::FMUL, SDLoc(Op), ResTy, - Op->getOperand(2), Op->getOperand(3))); + return DAG.getNode(MipsISD::FMS, SDLoc(Op), Op->getValueType(0), + Op->getOperand(1), Op->getOperand(2), Op->getOperand(3)); } case Intrinsic::mips_frint_w: case Intrinsic::mips_frint_d: @@ -1919,49 +1967,49 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op, case Intrinsic::mips_max_s_h: case Intrinsic::mips_max_s_w: case Intrinsic::mips_max_s_d: - return DAG.getNode(MipsISD::VSMAX, DL, Op->getValueType(0), + return DAG.getNode(ISD::SMAX, DL, Op->getValueType(0), Op->getOperand(1), Op->getOperand(2)); case Intrinsic::mips_max_u_b: case Intrinsic::mips_max_u_h: case Intrinsic::mips_max_u_w: case Intrinsic::mips_max_u_d: - return DAG.getNode(MipsISD::VUMAX, DL, Op->getValueType(0), + return DAG.getNode(ISD::UMAX, DL, Op->getValueType(0), Op->getOperand(1), Op->getOperand(2)); case Intrinsic::mips_maxi_s_b: case Intrinsic::mips_maxi_s_h: case Intrinsic::mips_maxi_s_w: case Intrinsic::mips_maxi_s_d: - return DAG.getNode(MipsISD::VSMAX, DL, Op->getValueType(0), + return DAG.getNode(ISD::SMAX, DL, Op->getValueType(0), Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG, true)); case Intrinsic::mips_maxi_u_b: case Intrinsic::mips_maxi_u_h: case Intrinsic::mips_maxi_u_w: case Intrinsic::mips_maxi_u_d: - return DAG.getNode(MipsISD::VUMAX, DL, Op->getValueType(0), + return DAG.getNode(ISD::UMAX, DL, Op->getValueType(0), Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG)); case Intrinsic::mips_min_s_b: case Intrinsic::mips_min_s_h: case Intrinsic::mips_min_s_w: case Intrinsic::mips_min_s_d: - return DAG.getNode(MipsISD::VSMIN, DL, Op->getValueType(0), + return DAG.getNode(ISD::SMIN, DL, Op->getValueType(0), Op->getOperand(1), Op->getOperand(2)); case Intrinsic::mips_min_u_b: case Intrinsic::mips_min_u_h: case Intrinsic::mips_min_u_w: case Intrinsic::mips_min_u_d: - return DAG.getNode(MipsISD::VUMIN, DL, Op->getValueType(0), + return DAG.getNode(ISD::UMIN, DL, Op->getValueType(0), Op->getOperand(1), Op->getOperand(2)); case Intrinsic::mips_mini_s_b: case Intrinsic::mips_mini_s_h: case Intrinsic::mips_mini_s_w: case Intrinsic::mips_mini_s_d: - return DAG.getNode(MipsISD::VSMIN, DL, Op->getValueType(0), + return DAG.getNode(ISD::SMIN, DL, Op->getValueType(0), Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG, true)); case Intrinsic::mips_mini_u_b: case Intrinsic::mips_mini_u_h: case Intrinsic::mips_mini_u_w: case Intrinsic::mips_mini_u_d: - return DAG.getNode(MipsISD::VUMIN, DL, Op->getValueType(0), + return DAG.getNode(ISD::UMIN, DL, Op->getValueType(0), Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG)); case Intrinsic::mips_mod_s_b: case Intrinsic::mips_mod_s_h: @@ -2312,7 +2360,7 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_VOID(SDValue Op, } } -/// \brief Check if the given BuildVectorSDNode is a splat. +/// Check if the given BuildVectorSDNode is a splat. /// This method currently relies on DAG nodes being reused when equivalent, /// so it's possible for this to return false even when isConstantSplat returns /// true. diff --git a/lib/Target/Mips/MipsSEISelLowering.h b/lib/Target/Mips/MipsSEISelLowering.h index 5976ecbcfc61..761ff3b1fa4d 100644 --- a/lib/Target/Mips/MipsSEISelLowering.h +++ b/lib/Target/Mips/MipsSEISelLowering.h @@ -15,8 +15,8 @@ #define LLVM_LIB_TARGET_MIPS_MIPSSEISELLOWERING_H #include "MipsISelLowering.h" -#include "llvm/CodeGen/MachineValueType.h" #include "llvm/CodeGen/SelectionDAGNodes.h" +#include "llvm/Support/MachineValueType.h" namespace llvm { @@ -32,11 +32,11 @@ class TargetRegisterClass; explicit MipsSETargetLowering(const MipsTargetMachine &TM, const MipsSubtarget &STI); - /// \brief Enable MSA support for the given integer type and Register + /// Enable MSA support for the given integer type and Register /// class. void addMSAIntType(MVT::SimpleValueType Ty, const TargetRegisterClass *RC); - /// \brief Enable MSA support for the given floating-point type and + /// Enable MSA support for the given floating-point type and /// Register class. void addMSAFloatType(MVT::SimpleValueType Ty, const TargetRegisterClass *RC); @@ -82,7 +82,7 @@ class TargetRegisterClass; SDValue lowerINTRINSIC_VOID(SDValue Op, SelectionDAG &DAG) const; SDValue lowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const; SDValue lowerBUILD_VECTOR(SDValue Op, SelectionDAG &DAG) const; - /// \brief Lower VECTOR_SHUFFLE into one of a number of instructions + /// Lower VECTOR_SHUFFLE into one of a number of instructions /// depending on the indices in the shuffle. SDValue lowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const; SDValue lowerSELECT(SDValue Op, SelectionDAG &DAG) const; @@ -92,46 +92,46 @@ class TargetRegisterClass; MachineBasicBlock *emitMSACBranchPseudo(MachineInstr &MI, MachineBasicBlock *BB, unsigned BranchOp) const; - /// \brief Emit the COPY_FW pseudo instruction + /// Emit the COPY_FW pseudo instruction MachineBasicBlock *emitCOPY_FW(MachineInstr &MI, MachineBasicBlock *BB) const; - /// \brief Emit the COPY_FD pseudo instruction + /// Emit the COPY_FD pseudo instruction MachineBasicBlock *emitCOPY_FD(MachineInstr &MI, MachineBasicBlock *BB) const; - /// \brief Emit the INSERT_FW pseudo instruction + /// Emit the INSERT_FW pseudo instruction MachineBasicBlock *emitINSERT_FW(MachineInstr &MI, MachineBasicBlock *BB) const; - /// \brief Emit the INSERT_FD pseudo instruction + /// Emit the INSERT_FD pseudo instruction MachineBasicBlock *emitINSERT_FD(MachineInstr &MI, MachineBasicBlock *BB) const; - /// \brief Emit the INSERT_([BHWD]|F[WD])_VIDX pseudo instruction + /// Emit the INSERT_([BHWD]|F[WD])_VIDX pseudo instruction MachineBasicBlock *emitINSERT_DF_VIDX(MachineInstr &MI, MachineBasicBlock *BB, unsigned EltSizeInBytes, bool IsFP) const; - /// \brief Emit the FILL_FW pseudo instruction + /// Emit the FILL_FW pseudo instruction MachineBasicBlock *emitFILL_FW(MachineInstr &MI, MachineBasicBlock *BB) const; - /// \brief Emit the FILL_FD pseudo instruction + /// Emit the FILL_FD pseudo instruction MachineBasicBlock *emitFILL_FD(MachineInstr &MI, MachineBasicBlock *BB) const; - /// \brief Emit the FEXP2_W_1 pseudo instructions. + /// Emit the FEXP2_W_1 pseudo instructions. MachineBasicBlock *emitFEXP2_W_1(MachineInstr &MI, MachineBasicBlock *BB) const; - /// \brief Emit the FEXP2_D_1 pseudo instructions. + /// Emit the FEXP2_D_1 pseudo instructions. MachineBasicBlock *emitFEXP2_D_1(MachineInstr &MI, MachineBasicBlock *BB) const; - /// \brief Emit the FILL_FW pseudo instruction + /// Emit the FILL_FW pseudo instruction MachineBasicBlock *emitLD_F16_PSEUDO(MachineInstr &MI, MachineBasicBlock *BB) const; - /// \brief Emit the FILL_FD pseudo instruction + /// Emit the FILL_FD pseudo instruction MachineBasicBlock *emitST_F16_PSEUDO(MachineInstr &MI, MachineBasicBlock *BB) const; - /// \brief Emit the FEXP2_W_1 pseudo instructions. + /// Emit the FEXP2_W_1 pseudo instructions. MachineBasicBlock *emitFPEXTEND_PSEUDO(MachineInstr &MI, MachineBasicBlock *BB, bool IsFGR64) const; - /// \brief Emit the FEXP2_D_1 pseudo instructions. + /// Emit the FEXP2_D_1 pseudo instructions. MachineBasicBlock *emitFPROUND_PSEUDO(MachineInstr &MI, MachineBasicBlock *BBi, bool IsFGR64) const; diff --git a/lib/Target/Mips/MipsSEInstrInfo.cpp b/lib/Target/Mips/MipsSEInstrInfo.cpp index 59b7679971cd..7ffe4aff474d 100644 --- a/lib/Target/Mips/MipsSEInstrInfo.cpp +++ b/lib/Target/Mips/MipsSEInstrInfo.cpp @@ -179,6 +179,69 @@ void MipsSEInstrInfo::copyPhysReg(MachineBasicBlock &MBB, MIB.addReg(ZeroReg); } +static bool isORCopyInst(const MachineInstr &MI) { + switch (MI.getOpcode()) { + default: + break; + case Mips::OR_MM: + case Mips::OR: + if (MI.getOperand(2).getReg() == Mips::ZERO) + return true; + break; + case Mips::OR64: + if (MI.getOperand(2).getReg() == Mips::ZERO_64) + return true; + break; + } + return false; +} + +/// If @MI is WRDSP/RRDSP instruction return true with @isWrite set to true +/// if it is WRDSP instruction. +static bool isReadOrWriteToDSPReg(const MachineInstr &MI, bool &isWrite) { + switch (MI.getOpcode()) { + default: + return false; + case Mips::WRDSP: + case Mips::WRDSP_MM: + isWrite = true; + break; + case Mips::RDDSP: + case Mips::RDDSP_MM: + isWrite = false; + break; + } + return true; +} + +/// We check for the common case of 'or', as it's MIPS' preferred instruction +/// for GPRs but we have to check the operands to ensure that is the case. +/// Other move instructions for MIPS are directly identifiable. +bool MipsSEInstrInfo::isCopyInstr(const MachineInstr &MI, + const MachineOperand *&Src, + const MachineOperand *&Dest) const { + bool isDSPControlWrite = false; + // Condition is made to match the creation of WRDSP/RDDSP copy instruction + // from copyPhysReg function. + if (isReadOrWriteToDSPReg(MI, isDSPControlWrite)) { + if (!MI.getOperand(1).isImm() || MI.getOperand(1).getImm() != (1<<4)) + return false; + else if (isDSPControlWrite) { + Src = &MI.getOperand(0); + Dest = &MI.getOperand(2); + } else { + Dest = &MI.getOperand(0); + Src = &MI.getOperand(2); + } + return true; + } else if (MI.isMoveReg() || isORCopyInst(MI)) { + Dest = &MI.getOperand(0); + Src = &MI.getOperand(1); + return true; + } + return false; +} + void MipsSEInstrInfo:: storeRegToStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned SrcReg, bool isKill, int FI, @@ -379,28 +442,30 @@ bool MipsSEInstrInfo::expandPostRAPseudo(MachineInstr &MI) const { expandCvtFPInt(MBB, MI, Mips::CVT_S_W, Mips::MTC1, false); break; case Mips::PseudoCVT_D32_W: - expandCvtFPInt(MBB, MI, Mips::CVT_D32_W, Mips::MTC1, false); + Opc = isMicroMips ? Mips::CVT_D32_W_MM : Mips::CVT_D32_W; + expandCvtFPInt(MBB, MI, Opc, Mips::MTC1, false); break; case Mips::PseudoCVT_S_L: expandCvtFPInt(MBB, MI, Mips::CVT_S_L, Mips::DMTC1, true); break; case Mips::PseudoCVT_D64_W: - expandCvtFPInt(MBB, MI, Mips::CVT_D64_W, Mips::MTC1, true); + Opc = isMicroMips ? Mips::CVT_D64_W_MM : Mips::CVT_D64_W; + expandCvtFPInt(MBB, MI, Opc, Mips::MTC1, true); break; case Mips::PseudoCVT_D64_L: expandCvtFPInt(MBB, MI, Mips::CVT_D64_L, Mips::DMTC1, true); break; case Mips::BuildPairF64: - expandBuildPairF64(MBB, MI, false); + expandBuildPairF64(MBB, MI, isMicroMips, false); break; case Mips::BuildPairF64_64: - expandBuildPairF64(MBB, MI, true); + expandBuildPairF64(MBB, MI, isMicroMips, true); break; case Mips::ExtractElementF64: - expandExtractElementF64(MBB, MI, false); + expandExtractElementF64(MBB, MI, isMicroMips, false); break; case Mips::ExtractElementF64_64: - expandExtractElementF64(MBB, MI, true); + expandExtractElementF64(MBB, MI, isMicroMips, true); break; case Mips::MIPSeh_return32: case Mips::MIPSeh_return64: @@ -425,6 +490,10 @@ unsigned MipsSEInstrInfo::getOppositeBranchOpc(unsigned Opc) const { case Mips::BGEZ: return Mips::BLTZ; case Mips::BLTZ: return Mips::BGEZ; case Mips::BLEZ: return Mips::BGTZ; + case Mips::BGTZ_MM: return Mips::BLEZ_MM; + case Mips::BGEZ_MM: return Mips::BLTZ_MM; + case Mips::BLTZ_MM: return Mips::BGEZ_MM; + case Mips::BLEZ_MM: return Mips::BGTZ_MM; case Mips::BEQ64: return Mips::BNE64; case Mips::BNE64: return Mips::BEQ64; case Mips::BGTZ64: return Mips::BLEZ64; @@ -433,16 +502,40 @@ unsigned MipsSEInstrInfo::getOppositeBranchOpc(unsigned Opc) const { case Mips::BLEZ64: return Mips::BGTZ64; case Mips::BC1T: return Mips::BC1F; case Mips::BC1F: return Mips::BC1T; - case Mips::BEQZC_MM: return Mips::BNEZC_MM; - case Mips::BNEZC_MM: return Mips::BEQZC_MM; + case Mips::BC1T_MM: return Mips::BC1F_MM; + case Mips::BC1F_MM: return Mips::BC1T_MM; + case Mips::BEQZ16_MM: return Mips::BNEZ16_MM; + case Mips::BNEZ16_MM: return Mips::BEQZ16_MM; + 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::BLEZC: return Mips::BGTZC; case Mips::BGEZC: return Mips::BLTZC; + case Mips::BGEC: return Mips::BLTC; + case Mips::BGTZC: return Mips::BLEZC; case Mips::BLTZC: return Mips::BGEZC; - case Mips::BLEZC: return Mips::BGTZC; + case Mips::BLTC: return Mips::BGEC; + case Mips::BGEUC: return Mips::BLTUC; + case Mips::BLTUC: return Mips::BGEUC; + case Mips::BEQC: return Mips::BNEC; + case Mips::BNEC: return Mips::BEQC; + case Mips::BC1EQZ: return Mips::BC1NEZ; + case Mips::BC1NEZ: return Mips::BC1EQZ; + case Mips::BEQZC_MMR6: return Mips::BNEZC_MMR6; + case Mips::BNEZC_MMR6: return Mips::BEQZC_MMR6; + case Mips::BLEZC_MMR6: return Mips::BGTZC_MMR6; + case Mips::BGEZC_MMR6: return Mips::BLTZC_MMR6; + case Mips::BGEC_MMR6: return Mips::BLTC_MMR6; + case Mips::BGTZC_MMR6: return Mips::BLEZC_MMR6; + case Mips::BLTZC_MMR6: return Mips::BGEZC_MMR6; + case Mips::BLTC_MMR6: return Mips::BGEC_MMR6; + case Mips::BGEUC_MMR6: return Mips::BLTUC_MMR6; + case Mips::BLTUC_MMR6: return Mips::BGEUC_MMR6; + case Mips::BEQC_MMR6: return Mips::BNEC_MMR6; + case Mips::BNEC_MMR6: return Mips::BEQC_MMR6; + case Mips::BC1EQZC_MMR6: return Mips::BC1NEZC_MMR6; + case Mips::BC1NEZC_MMR6: return Mips::BC1EQZC_MMR6; case Mips::BEQZC64: return Mips::BNEZC64; case Mips::BNEZC64: return Mips::BEQZC64; case Mips::BEQC64: return Mips::BNEC64; @@ -459,6 +552,16 @@ unsigned MipsSEInstrInfo::getOppositeBranchOpc(unsigned Opc) const { case Mips::BBIT1: return Mips::BBIT0; case Mips::BBIT032: return Mips::BBIT132; case Mips::BBIT132: return Mips::BBIT032; + case Mips::BZ_B: return Mips::BNZ_B; + case Mips::BZ_H: return Mips::BNZ_H; + case Mips::BZ_W: return Mips::BNZ_W; + case Mips::BZ_D: return Mips::BNZ_D; + case Mips::BZ_V: return Mips::BNZ_V; + case Mips::BNZ_B: return Mips::BZ_B; + case Mips::BNZ_H: return Mips::BZ_H; + case Mips::BNZ_W: return Mips::BZ_W; + case Mips::BNZ_D: return Mips::BZ_D; + case Mips::BNZ_V: return Mips::BZ_V; } } @@ -551,7 +654,13 @@ unsigned MipsSEInstrInfo::getAnalyzableBrOpc(unsigned Opc) const { Opc == Mips::BGTZC64 || Opc == Mips::BGEZC64 || Opc == Mips::BLTZC64 || Opc == Mips::BLEZC64 || Opc == Mips::BC || Opc == Mips::BBIT0 || Opc == Mips::BBIT1 || Opc == Mips::BBIT032 || - Opc == Mips::BBIT132) ? Opc : 0; + Opc == Mips::BBIT132 || Opc == Mips::BC_MMR6 || + Opc == Mips::BEQC_MMR6 || Opc == Mips::BNEC_MMR6 || + Opc == Mips::BLTC_MMR6 || Opc == Mips::BGEC_MMR6 || + Opc == Mips::BLTUC_MMR6 || Opc == Mips::BGEUC_MMR6 || + Opc == Mips::BGTZC_MMR6 || Opc == Mips::BLEZC_MMR6 || + Opc == Mips::BGEZC_MMR6 || Opc == Mips::BLTZC_MMR6 || + Opc == Mips::BEQZC_MMR6 || Opc == Mips::BNEZC_MMR6) ? Opc : 0; } void MipsSEInstrInfo::expandRetRA(MachineBasicBlock &MBB, @@ -651,6 +760,7 @@ void MipsSEInstrInfo::expandCvtFPInt(MachineBasicBlock &MBB, void MipsSEInstrInfo::expandExtractElementF64(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + bool isMicroMips, bool FP64) const { unsigned DstReg = I->getOperand(0).getReg(); unsigned SrcReg = I->getOperand(1).getReg(); @@ -682,7 +792,10 @@ void MipsSEInstrInfo::expandExtractElementF64(MachineBasicBlock &MBB, // We therefore pretend that it reads the bottom 32-bits to // artificially create a dependency and prevent the scheduler // changing the behaviour of the code. - BuildMI(MBB, I, dl, get(FP64 ? Mips::MFHC1_D64 : Mips::MFHC1_D32), DstReg) + BuildMI(MBB, I, dl, + get(isMicroMips ? (FP64 ? Mips::MFHC1_D64_MM : Mips::MFHC1_D32_MM) + : (FP64 ? Mips::MFHC1_D64 : Mips::MFHC1_D32)), + DstReg) .addReg(SrcReg); } else BuildMI(MBB, I, dl, get(Mips::MFC1), DstReg).addReg(SubReg); @@ -690,7 +803,7 @@ void MipsSEInstrInfo::expandExtractElementF64(MachineBasicBlock &MBB, void MipsSEInstrInfo::expandBuildPairF64(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, - bool FP64) const { + bool isMicroMips, bool FP64) const { unsigned DstReg = I->getOperand(0).getReg(); unsigned LoReg = I->getOperand(1).getReg(), HiReg = I->getOperand(2).getReg(); const MCInstrDesc& Mtc1Tdd = get(Mips::MTC1); @@ -735,7 +848,10 @@ void MipsSEInstrInfo::expandBuildPairF64(MachineBasicBlock &MBB, // We therefore pretend that it reads the bottom 32-bits to // artificially create a dependency and prevent the scheduler // changing the behaviour of the code. - BuildMI(MBB, I, dl, get(FP64 ? Mips::MTHC1_D64 : Mips::MTHC1_D32), DstReg) + BuildMI(MBB, I, dl, + get(isMicroMips ? (FP64 ? Mips::MTHC1_D64_MM : Mips::MTHC1_D32_MM) + : (FP64 ? Mips::MTHC1_D64 : Mips::MTHC1_D32)), + DstReg) .addReg(DstReg) .addReg(HiReg); } else if (Subtarget.isABI_FPXX()) diff --git a/lib/Target/Mips/MipsSEInstrInfo.h b/lib/Target/Mips/MipsSEInstrInfo.h index b356909bf1cf..fc55716d598a 100644 --- a/lib/Target/Mips/MipsSEInstrInfo.h +++ b/lib/Target/Mips/MipsSEInstrInfo.h @@ -47,6 +47,9 @@ public: const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, bool KillSrc) const override; + bool isCopyInstr(const MachineInstr &MI, const MachineOperand *&Src, + const MachineOperand *&Dest) const override; + void storeRegToStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned SrcReg, bool isKill, int FrameIndex, @@ -107,9 +110,11 @@ private: unsigned CvtOpc, unsigned MovOpc, bool IsI64) const; void expandExtractElementF64(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, bool FP64) const; + MachineBasicBlock::iterator I, bool isMicroMips, + bool FP64) const; void expandBuildPairF64(MachineBasicBlock &MBB, - MachineBasicBlock::iterator I, bool FP64) const; + MachineBasicBlock::iterator I, bool isMicroMips, + bool FP64) const; void expandEhReturn(MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const; }; diff --git a/lib/Target/Mips/MipsSERegisterInfo.cpp b/lib/Target/Mips/MipsSERegisterInfo.cpp index 2ff6b99e78ff..e7d720a4b769 100644 --- a/lib/Target/Mips/MipsSERegisterInfo.cpp +++ b/lib/Target/Mips/MipsSERegisterInfo.cpp @@ -88,10 +88,8 @@ static inline unsigned getLoadStoreOffsetSizeInBits(const unsigned Opcode, 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: @@ -100,6 +98,8 @@ static inline unsigned getLoadStoreOffsetSizeInBits(const unsigned Opcode, case Mips::SC64_R6: case Mips::SCD_R6: case Mips::SC_R6: + case Mips::LL_MMR6: + case Mips::SC_MMR6: return 9; case Mips::INLINEASM: { unsigned ConstraintID = InlineAsm::getMemoryConstraintID(MO.getImm()); @@ -204,7 +204,8 @@ void MipsSERegisterInfo::eliminateFI(MachineBasicBlock::iterator II, Offset = SPOffset + (int64_t)StackSize; Offset += MI.getOperand(OpNo + 1).getImm(); - DEBUG(errs() << "Offset : " << Offset << "\n" << "<--------->\n"); + LLVM_DEBUG(errs() << "Offset : " << Offset << "\n" + << "<--------->\n"); if (!MI.isDebugValue()) { // Make sure Offset fits within the field available. diff --git a/lib/Target/Mips/MipsSchedule.td b/lib/Target/Mips/MipsSchedule.td index 8ec55ab6284d..64db815a0f4c 100644 --- a/lib/Target/Mips/MipsSchedule.td +++ b/lib/Target/Mips/MipsSchedule.td @@ -57,6 +57,14 @@ def II_CFC1 : InstrItinClass; def II_CFC2 : InstrItinClass; def II_CLO : InstrItinClass; def II_CLZ : InstrItinClass; +def II_CRC32B : InstrItinClass; +def II_CRC32CB : InstrItinClass; +def II_CRC32CD : InstrItinClass; +def II_CRC32CH : InstrItinClass; +def II_CRC32CW : InstrItinClass; +def II_CRC32D : InstrItinClass; +def II_CRC32H : InstrItinClass; +def II_CRC32W : InstrItinClass; def II_CTC1 : InstrItinClass; def II_CTC2 : InstrItinClass; def II_CVT : InstrItinClass; @@ -84,8 +92,10 @@ def II_DIVU : InstrItinClass; def II_DIV_D : InstrItinClass; def II_DIV_S : InstrItinClass; def II_DMFC0 : InstrItinClass; +def II_DMFGC0 : InstrItinClass; def II_DMT : InstrItinClass; def II_DMTC0 : InstrItinClass; +def II_DMTGC0 : InstrItinClass; def II_DMFC1 : InstrItinClass; def II_DMTC1 : InstrItinClass; def II_DMOD : InstrItinClass; @@ -120,6 +130,9 @@ def II_EVPE : InstrItinClass; def II_EXT : InstrItinClass; // Any EXT instruction def II_FLOOR : InstrItinClass; def II_FORK : InstrItinClass; +def II_GINVI : InstrItinClass; +def II_GINVT : InstrItinClass; +def II_HYPCALL : InstrItinClass; def II_INS : InstrItinClass; // Any INS instruction def II_IndirectBranchPseudo : InstrItinClass; // Indirect branch pseudo. def II_J : InstrItinClass; @@ -225,6 +238,8 @@ def II_MFHC0 : InstrItinClass; def II_MFC1 : InstrItinClass; def II_MFHC1 : InstrItinClass; def II_MFC2 : InstrItinClass; +def II_MFGC0 : InstrItinClass; +def II_MFHGC0 : InstrItinClass; def II_MFHI_MFLO : InstrItinClass; // mfhi and mflo def II_MFTR : InstrItinClass; def II_MOD : InstrItinClass; @@ -255,6 +270,8 @@ def II_MTHC0 : InstrItinClass; def II_MTC1 : InstrItinClass; def II_MTHC1 : InstrItinClass; def II_MTC2 : InstrItinClass; +def II_MTGC0 : InstrItinClass; +def II_MTHGC0 : InstrItinClass; def II_MTHI_MTLO : InstrItinClass; // mthi and mtlo def II_MTTR : InstrItinClass; def II_MUL : InstrItinClass; @@ -346,6 +363,12 @@ def II_CACHEE : InstrItinClass; def II_PREFE : InstrItinClass; def II_LLE : InstrItinClass; def II_SCE : InstrItinClass; +def II_TLBGINV : InstrItinClass; +def II_TLBGINVF : InstrItinClass; +def II_TLBGP : InstrItinClass; +def II_TLBGR : InstrItinClass; +def II_TLBGWI : InstrItinClass; +def II_TLBGWR : InstrItinClass; def II_TLBINV : InstrItinClass; def II_TLBINVF : InstrItinClass; def II_WRPGPR : InstrItinClass; @@ -686,5 +709,28 @@ def MipsGenericItineraries : ProcessorItineraries<[ALU, IMULDIV], [], [ InstrItinData<II_RDPGPR , [InstrStage<1, [ALU]>]>, InstrItinData<II_DVP , [InstrStage<1, [ALU]>]>, InstrItinData<II_EVP , [InstrStage<1, [ALU]>]>, - InstrItinData<II_YIELD , [InstrStage<5, [ALU]>]> + InstrItinData<II_YIELD , [InstrStage<5, [ALU]>]>, + InstrItinData<II_CRC32B , [InstrStage<1, [ALU]>]>, + InstrItinData<II_CRC32H , [InstrStage<1, [ALU]>]>, + InstrItinData<II_CRC32W , [InstrStage<1, [ALU]>]>, + InstrItinData<II_CRC32D , [InstrStage<1, [ALU]>]>, + InstrItinData<II_CRC32CB , [InstrStage<1, [ALU]>]>, + InstrItinData<II_CRC32CH , [InstrStage<1, [ALU]>]>, + InstrItinData<II_CRC32CW , [InstrStage<1, [ALU]>]>, + InstrItinData<II_CRC32CD , [InstrStage<1, [ALU]>]>, + InstrItinData<II_MFGC0 , [InstrStage<2, [ALU]>]>, + InstrItinData<II_MTGC0 , [InstrStage<2, [ALU]>]>, + InstrItinData<II_MFHGC0 , [InstrStage<2, [ALU]>]>, + InstrItinData<II_MTHGC0 , [InstrStage<2, [ALU]>]>, + InstrItinData<II_HYPCALL , [InstrStage<2, [ALU]>]>, + InstrItinData<II_TLBGINV , [InstrStage<2, [ALU]>]>, + InstrItinData<II_TLBGINVF , [InstrStage<2, [ALU]>]>, + InstrItinData<II_TLBGP , [InstrStage<2, [ALU]>]>, + InstrItinData<II_TLBGR , [InstrStage<2, [ALU]>]>, + InstrItinData<II_TLBWI , [InstrStage<2, [ALU]>]>, + InstrItinData<II_TLBWR , [InstrStage<2, [ALU]>]>, + InstrItinData<II_DMFGC0 , [InstrStage<2, [ALU]>]>, + InstrItinData<II_DMTGC0 , [InstrStage<2, [ALU]>]>, + InstrItinData<II_GINVI , [InstrStage<1, [ALU]>]>, + InstrItinData<II_GINVT , [InstrStage<1, [ALU]>]> ]>; diff --git a/lib/Target/Mips/MipsScheduleGeneric.td b/lib/Target/Mips/MipsScheduleGeneric.td index 744392c320ef..79c55dbb9e03 100644 --- a/lib/Target/Mips/MipsScheduleGeneric.td +++ b/lib/Target/Mips/MipsScheduleGeneric.td @@ -25,8 +25,11 @@ def MipsGenericModel : SchedMachineModel { int HighLatency = 37; list<Predicate> UnsupportedFeatures = []; - let CompleteModel = 1; + let CompleteModel = 0; let PostRAScheduler = 1; + + // FIXME: Remove when all errors have been fixed. + let FullInstRWOverlapCheck = 0; } let SchedModel = MipsGenericModel in { @@ -71,12 +74,12 @@ def : ItinRW<[GenericWriteMDUtoGPR], [II_MUL]>; def GenericWriteDIV : SchedWriteRes<[GenericIssueDIV]> { // Estimated worst case let Latency = 33; - let ResourceCycles = [1, 33]; + let ResourceCycles = [33]; } def GenericWriteDIVU : SchedWriteRes<[GenericIssueDIV]> { // Estimated worst case let Latency = 31; - let ResourceCycles = [1, 31]; + let ResourceCycles = [31]; } def : ItinRW<[GenericWriteDIV], [II_DIV]>; diff --git a/lib/Target/Mips/MipsScheduleP5600.td b/lib/Target/Mips/MipsScheduleP5600.td index 440f93d5b7eb..846fa11494c7 100644 --- a/lib/Target/Mips/MipsScheduleP5600.td +++ b/lib/Target/Mips/MipsScheduleP5600.td @@ -13,14 +13,13 @@ def MipsP5600Model : SchedMachineModel { int LoadLatency = 4; int MispredictPenalty = 8; // TODO: Estimated - let CompleteModel = 1; + let CompleteModel = 0; + let FullInstRWOverlapCheck = 1; list<Predicate> UnsupportedFeatures = [HasMips32r6, HasMips64r6, - HasMips64, HasMips64r2, HasCnMips, + HasMips3, HasMips64r2, HasCnMips, InMicroMips, InMips16Mode, - HasMicroMips32r6, HasDSP, - HasDSPR2, HasMT]; - + HasDSP, HasDSPR2, HasMT, HasCRC]; } let SchedModel = MipsP5600Model in { @@ -37,9 +36,8 @@ def P5600IssueALU : ProcResource<1> { let Super = P5600ALQ; } def P5600WriteALU : SchedWriteRes<[P5600IssueALU]>; // and, lui, nor, or, slti, sltiu, sub, subu, xor -def : ItinRW<[P5600WriteALU], - [II_AND, II_LUI, II_NOR, II_OR, II_SLTI_SLTIU, II_SUB, II_SUBU, - II_XOR]>; +def : InstRW<[P5600WriteALU], (instrs AND, LUi, NOR, OR, SLTi, SLTiu, SUB, + SUBu, XOR)>; // AGQ Pipelines // ============= @@ -63,20 +61,35 @@ def P5600WriteJumpAndLink : SchedWriteRes<[P5600IssueCTISTD, P5600CTISTD]> { // b, beq, beql, bg[et]z, bl[et]z, bne, bnel, j, syscall, jal, bltzal, // jalr, jr.hb, jr -def : ItinRW<[P5600WriteJump], [II_B, II_BCC, II_BCCZ, II_BCCZAL, II_J, II_JR, - II_JR_HB, II_DERET, II_ERET, II_ERETNC, - II_SYSCALL, II_BREAK, II_SDBBP, II_SSNOP, - II_TEQ, II_TEQI, II_TGE, II_TGEI, II_TGEIU, - II_TGEU, II_TLT, II_TLTI, II_TLTU, II_TNE, - II_TNEI, II_TRAP, II_TTLTIU, II_WAIT, - II_PAUSE]>; - -def : ItinRW<[P5600WriteJumpAndLink], [II_JAL, II_JALR, II_JALR_HB]>; +def : InstRW<[P5600WriteJump], (instrs B, BAL, BAL_BR, BEQ, BEQL, BGEZ, BGEZAL, + BGEZALL, BGEZL, BGTZ, BGTZL, BLEZ, BLEZL, BLTZ, + BLTZAL, BLTZALL, BLTZL, BNE, BNEL, BREAK, + DERET, ERET, ERETNC, J, JR, JR_HB, + PseudoIndirectBranch, + PseudoIndirectHazardBranch, PseudoReturn, + SDBBP, SSNOP, SYSCALL, TAILCALL, TAILCALLREG, + TAILCALLREGHB, TEQ, TEQI, TGE, TGEI, TGEIU, + TGEU, TLT, TLTI, TLTU, TNE, TNEI, TRAP, + TTLTIU, WAIT, PAUSE)>; + +def : InstRW<[P5600WriteJumpAndLink], (instrs JAL, JALR, JALRHBPseudo, + JALRPseudo, JALR_HB)>; + +def : InstRW<[P5600WriteJumpAndLink], (instrs JALX)> { + let Unsupported = 1; +} def P5600COP0 : SchedWriteRes<[P5600IssueCTISTD, P5600CTISTD]>; -def : ItinRW<[P5600COP0], [II_TLBINV, II_TLBINVF, II_TLBP, II_TLBR, II_TLBWI, - II_TLBWR, II_MFC0, II_MTC0]>; +def : InstRW<[P5600COP0], (instrs TLBINV, TLBINVF, TLBP, TLBR, TLBWI, TLBWR, + MFC0, MTC0)>; + +def P5600COP2 : SchedWriteRes<[P5600IssueCTISTD, P5600CTISTD]>; + +def : InstRW<[P5600COP2], (instrs MFC2, MTC2)> { + let Unsupported = 1; +} + // LDST Pipeline // ------------- @@ -106,21 +119,20 @@ def P5600WriteLoadToOtherUnits : SchedWriteRes<[P5600IssueLDST]> { } // l[bhw], l[bh]u, ll -def : ItinRW<[P5600WriteLoad], [II_LB, II_LBE, II_LBU, II_LBUE, II_LH, II_LHE, - II_LHU, II_LHUE, II_LW, II_LWE, II_LL, II_LLE, - II_LWPC]>; +def : InstRW<[P5600WriteLoad], (instrs LB, LBu, LH, LHu, LW, LL, LWC2, LWC3, + LDC2, LDC3, LBE, LBuE, LHE, LHuE, LWE, LLE, + LWPC)>; // lw[lr] -def : ItinRW<[P5600WriteLoadShifted], [II_LWL, II_LWLE, II_LWR, II_LWRE]>; +def : InstRW<[P5600WriteLoadShifted], (instrs LWL, LWR, LWLE, LWRE)>; // s[bhw], sw[lr] -def : ItinRW<[P5600WriteStore], [II_SB, II_SBE, II_SH, II_SHE, II_SW, II_SWE, - II_SWL, II_SWLE, II_SWR, II_SWRE, II_SC, - II_SCE]>; +def : InstRW<[P5600WriteStore], (instrs SB, SH, SW, SWC2, SWC3, SDC2, SDC3, SC, + SBE, SHE, SWE, SCE, SWL, SWR, SWLE, SWRE)>; // pref, cache, sync, synci -def : ItinRW<[P5600WriteCache], [II_PREF, II_PREFE, II_CACHE, II_CACHEE, - II_SYNC, II_SYNCI]>; +def : InstRW<[P5600WriteCache], (instrs PREF, PREFE, CACHE, CACHEE, SYNC, + SYNCI)>; // LDST is also used in moves from general purpose registers to floating point // and MSA. @@ -154,28 +166,31 @@ def P5600WriteAL2MAdd: SchedWriteRes<[P5600IssueAL2, P5600CTISTD]> { } // clo, clz, di, ei, mfhi, mflo -def : ItinRW<[P5600WriteAL2], [II_CLO, II_CLZ, II_DI, II_EI, II_MFHI_MFLO]>; +def : InstRW<[P5600WriteAL2], (instrs CLO, CLZ, DI, EI, MFHI, MFLO, + PseudoMFHI, PseudoMFLO)>; // ehb, rdhwr, rdpgpr, wrpgpr, wsbh -def : ItinRW<[P5600WriteAL2ShadowMov], [II_EHB, II_RDHWR, II_WSBH]>; +def : InstRW<[P5600WriteAL2ShadowMov], (instrs EHB, RDHWR, WSBH)>; // mov[nz] -def : ItinRW<[P5600WriteAL2CondMov], [II_MOVN, II_MOVZ]>; +def : InstRW<[P5600WriteAL2CondMov], (instrs MOVN_I_I, MOVZ_I_I)>; // divu? -def : ItinRW<[P5600WriteAL2Div], [II_DIV]>; -def : ItinRW<[P5600WriteAL2DivU], [II_DIVU]>; +def : InstRW<[P5600WriteAL2Div], (instrs DIV, PseudoSDIV, SDIV)>; +def : InstRW<[P5600WriteAL2DivU], (instrs DIVU, PseudoUDIV, UDIV)>; // mul -def : ItinRW<[P5600WriteAL2Mul], [II_MUL]>; +def : InstRW<[P5600WriteAL2Mul], (instrs MUL)>; // multu?, multu? -def : ItinRW<[P5600WriteAL2Mult], [II_MULT, II_MULTU]>; +def : InstRW<[P5600WriteAL2Mult], (instrs MULT, MULTu, PseudoMULT, + PseudoMULTu)>; // maddu?, msubu?, mthi, mtlo -def : ItinRW<[P5600WriteAL2MAdd], - [II_MADD, II_MADDU, II_MSUB, II_MSUBU, II_MTHI_MTLO]>; +def : InstRW<[P5600WriteAL2MAdd], (instrs MADD, MADDU, MSUB, MSUBU, + MTHI, MTLO, PseudoMADD, PseudoMADDU, + PseudoMSUB, PseudoMSUBU, PseudoMTLOHI)>; // ext, ins -def : ItinRW<[P5600WriteAL2BitExt], [II_EXT, II_INS]>; +def : InstRW<[P5600WriteAL2BitExt], (instrs EXT, INS)>; // Either ALU or AL2 Pipelines // --------------------------- @@ -193,11 +208,9 @@ def P5600WriteEitherALU : SchedWriteVariant< // add, addi, addiu, addu, andi, ori, rotr, se[bh], sllv?, sr[al]v?, slt, sltu, // xori -def : ItinRW<[P5600WriteEitherALU], - [II_ADD, II_ADDI, II_ADDIU, II_ANDI, II_ORI, II_ROTR, II_SEB, II_SEH, - II_SLT_SLTU, II_SLL, II_SRA, II_SRL, II_XORI, II_ADDU, II_SLLV, - II_SRAV, II_SRLV, II_LSA]>; -def : InstRW<[], (instrs COPY)>; +def : InstRW<[P5600WriteEitherALU], (instrs ADD, ADDi, ADDiu, ANDi, ORi, ROTR, + SEB, SEH, SLT, SLTu, SLL, SRA, SRL, XORi, + ADDu, SLLV, SRAV, SRLV, LSA, COPY)>; // FPU Pipelines // ============= @@ -300,8 +313,10 @@ def P5600WriteMoveFPULToOtherUnits : SchedWriteRes<[P5600IssueFPUL]>; // abs.[ds], abs.ps, bc1[tf]l?, mov[tf].[ds], mov[tf], mov.[ds], [cm][ft]c1, // m[ft]hc1, neg.[ds], neg.ps, nor.v, nori.b, or.v, ori.b, xor.v, xori.b, // sdxc1, sdc1, st.[bhwd], swc1, swxc1 -def : ItinRW<[P5600WriteFPUS], [II_ABS, II_MOVF_D, II_MOVF_S, II_MOVT_D, - II_MOVT_S, II_MOV_D, II_MOV_S, II_NEG]>; +def : InstRW<[P5600WriteFPUS], (instrs FABS_S, FABS_D32, FABS_D64, MOVF_D32, + MOVF_D64, MOVF_S, MOVT_D32, MOVT_D64, + MOVT_S, FMOV_D32, FMOV_D64, FMOV_S, FNEG_S, + FNEG_D32, FNEG_D64)>; // adds_a.[bhwd], adds_[asu].[bhwd], addvi?.[bhwd], asub_[us].[bhwd], // aver?_[us].[bhwd], shf.[bhw], fill[bhwd], splat?.[bhwd] @@ -321,23 +336,6 @@ def : InstRW<[P5600WriteMSAShortLogic], (instregex "^LDI_[BHWD]$")>; def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(AND|OR|[XN]OR)_V$")>; def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(AND|OR|[XN]OR)I_B$")>; -// vshf.[bhwd], binsl.[bhwd], binsr.[bhwd], insert.[bhwd], sld?.[bhwd], -// bset.[bhwd], bclr.[bhwd], bneg.[bhwd], bsel_v, bseli_b -def : InstRW<[P5600WriteMSAShortInt], (instregex "^VSHF_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortInt], (instregex "^(BINSL|BINSLI)_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortInt], (instregex "^(BINSR|BINSRI)_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortInt], (instregex "^INSERT_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortInt], (instregex "^(SLD|SLDI)_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortInt], (instregex "^(BSET|BSETI)_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortInt], (instregex "^(BCLR|BCLRI)_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortInt], (instregex "^(BNEG|BNEGI)_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortInt], (instregex "^(BSEL_V|BSELI_B)$")>; -def : InstRW<[P5600WriteMSAShortInt], (instregex "^BMN*Z.*$")>; - -// pcnt.[bhwd], sat_s.[bhwd], sat_u.bhwd] -def : InstRW<[P5600WriteMSAOther3], (instregex "^PCNT_[BHWD]$")>; -def : InstRW<[P5600WriteMSAOther3], (instregex "^SAT_(S|U)_[BHWD]$")>; - // fexp2_w, fexp2_d def : InstRW<[P5600WriteFPUS], (instregex "^FEXP2_(W|D)$")>; @@ -424,7 +422,6 @@ def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(SRLR|SRLRI)_[BHWD]$")>; def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(SLL|SLLI)_[BHWD]$")>; def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(PCKEV|PCKOD)_[BHWD]$")>; def : InstRW<[P5600WriteMSAShortLogic], (instregex "^(NLOC|NLZC)_[BHWD]$")>; -def : InstRW<[P5600WriteMSAShortLogic], (instregex "^INSVE_[BHWD]$")>; // Long Pipe // ---------- @@ -432,24 +429,31 @@ def : InstRW<[P5600WriteMSAShortLogic], (instregex "^INSVE_[BHWD]$")>; // add.[ds], add.ps, cvt.d.[sw], cvt.s.[dw], cvt.w.[sd], cvt.[sw].ps, // cvt.ps.[sw], c.<cc>.[ds], c.<cc>.ps, mul.[ds], mul.ps, sub.[ds], sub.ps, // trunc.w.[ds], trunc.w.ps -def : ItinRW<[P5600WriteFPUL], - [II_ADD_D, II_ADD_S, II_CVT, II_C_CC_D, II_C_CC_S, II_MUL_D, - II_MUL_S, II_SUB_D, II_SUB_S, II_TRUNC]>; +def : InstRW<[P5600WriteFPUL], + (instrs FADD_D32, FADD_D64, FADD_S, FMUL_D32, FMUL_D64, FMUL_S, + FSUB_D32, FSUB_D64, FSUB_S)>; +def : InstRW<[P5600WriteFPUL], (instregex "^TRUNC_(L|W)_(S|D32|D64)$")>; +def : InstRW<[P5600WriteFPUL], + (instregex "^CVT_(S|D32|D64|L|W)_(S|D32|D64|L|W)$")>; +def : InstRW<[P5600WriteFPUL], (instregex "^C_[A-Z]+_(S|D32|D64)$")>; +def : InstRW<[P5600WriteFPUL], (instregex "^FCMP_(S32|D32|D64)$")>; +def : InstRW<[P5600WriteFPUL], (instregex "^PseudoCVT_(S|D32|D64)_(L|W)$")>; // div.[ds], div.ps -def : ItinRW<[P5600WriteFPUDivS], [II_DIV_S]>; -def : ItinRW<[P5600WriteFPUDivD], [II_DIV_D]>; +def : InstRW<[P5600WriteFPUDivS], (instrs FDIV_S)>; +def : InstRW<[P5600WriteFPUDivD], (instrs FDIV_D32, FDIV_D64)>; // sqrt.[ds], sqrt.ps -def : ItinRW<[P5600WriteFPUSqrtS], [II_SQRT_S]>; -def : ItinRW<[P5600WriteFPUSqrtD], [II_SQRT_D]>; +def : InstRW<[P5600WriteFPUSqrtS], (instrs FSQRT_S)>; +def : InstRW<[P5600WriteFPUSqrtD], (instrs FSQRT_D32, FSQRT_D64)>; // frcp.[wd], frsqrt.[wd] def : InstRW<[P5600WriteFPURsqrtD], (instregex "^FRCP_(W|D)$")>; def : InstRW<[P5600WriteFPURsqrtD], (instregex "^FRSQRT_(W|D)$")>; -def : ItinRW<[P5600WriteFPURsqrtD], [II_RECIP_D, II_RSQRT_D]>; -def : ItinRW<[P5600WriteFPURsqrtS], [II_RECIP_S, II_RSQRT_S]>; +def : InstRW<[P5600WriteFPURsqrtD], (instrs RECIP_D32, RECIP_D64, RSQRT_D32, + RSQRT_D64)>; +def : InstRW<[P5600WriteFPURsqrtS], (instrs RECIP_S, RSQRT_S)>; // fmadd.[wd], fmsubb.[wd], fdiv.[wd], fsqrt.[wd], fmul.[wd], fadd.[wd], // fsub.[wd] @@ -481,9 +485,9 @@ def : InstRW<[P5600WriteMSALongInt], (instregex "^MUL_Q_[HW]$")>; // madd.[ds], msub.[ds], nmadd.[ds], nmsub.[ds], // Operand 0 is read on cycle 5. All other operands are read on operand 0. -def : ItinRW<[SchedReadAdvance<5>, P5600WriteFPUL_MADDSUB], - [II_MADD_D, II_MADD_S, II_MSUB_D, II_MSUB_S, II_NMADD_D, - II_NMADD_S, II_NMSUB_D, II_NMSUB_S]>; +def : InstRW<[SchedReadAdvance<5>, P5600WriteFPUL_MADDSUB], + (instrs MADD_D32, MADD_D64, MADD_S, MSUB_D32, MSUB_D64, MSUB_S, + NMADD_D32, NMADD_D64, NMADD_S, NMSUB_D32, NMSUB_D64, NMSUB_S)>; // madd.ps, msub.ps, nmadd.ps, nmsub.ps // Operand 0 and 1 are read on cycle 5. All others are read on operand 0. @@ -536,26 +540,30 @@ def P5600WriteLoadFPU : WriteSequence<[P5600WriteLoadToOtherUnits, P5600WriteLoadOtherUnitsToFPU]>; // ctc1, mtc1, mthc1 -def : ItinRW<[P5600WriteMoveGPRToFPU], [II_CTC1, II_MTC1, II_MTHC1]>; +def : InstRW<[P5600WriteMoveGPRToFPU], (instrs CTC1, MTC1, MTC1_D64, MTHC1_D32, + MTHC1_D64, BuildPairF64, + BuildPairF64_64)>; // copy.[su]_[bhwd] def : InstRW<[P5600WriteMoveFPUToGPR], (instregex "^COPY_U_[BHW]$")>; def : InstRW<[P5600WriteMoveFPUToGPR], (instregex "^COPY_S_[BHWD]$")>; // bc1[ft], cfc1, mfc1, mfhc1, movf, movt -def : ItinRW<[P5600WriteMoveFPUToGPR], - [II_BC1F, II_BC1FL, II_BC1T, II_BC1TL, II_CFC1, II_MFC1, II_MFHC1, II_MOVF, II_MOVT]>; +def : InstRW<[P5600WriteMoveFPUToGPR], (instrs BC1F, BC1FL, BC1T, BC1TL, CFC1, + MFC1, MFC1_D64, MFHC1_D32, MFHC1_D64, + MOVF_I, MOVT_I, ExtractElementF64, + ExtractElementF64_64)>; // swc1, swxc1, st.[bhwd] -def : ItinRW<[P5600WriteStoreFPUS], [II_SDC1, II_SDXC1, II_SUXC1, II_SWC1, - II_SWXC1]>; +def : InstRW<[P5600WriteStoreFPUS], (instrs SDC1, SDXC1, SUXC1, SWC1, SWXC1)>; def : InstRW<[P5600WriteStoreFPUS], (instregex "^ST_[BHWD]$")>; // movn.[ds], movz.[ds] -def : ItinRW<[P5600WriteStoreFPUL], [II_MOVN_D, II_MOVN_S, II_MOVZ_D, II_MOVZ_S]>; +def : InstRW<[P5600WriteStoreFPUL], (instrs MOVN_I_D32, MOVN_I_D64, MOVN_I_S, + MOVZ_I_D32, MOVZ_I_D64, MOVZ_I_S)>; // l[dw]x?c1, ld.[bhwd] -def : ItinRW<[P5600WriteLoadFPU], [II_LDC1, II_LDXC1, II_LWC1, II_LWXC1, II_LUXC1]>; +def : InstRW<[P5600WriteLoadFPU], (instrs LDC1, LDXC1, LWC1, LWXC1, LUXC1)>; def : InstRW<[P5600WriteLoadFPU], (instregex "LD_[BHWD]")>; // Unsupported Instructions @@ -577,10 +585,12 @@ def : InstRW<[P5600WriteLoadFPU], (instregex "LD_[BHWD]")>; // ceil.[lw].[ds], floor.[lw].[ds] // Reason behind guess: trunc.[lw].ds and the various cvt's are in FPUL -def : ItinRW<[P5600WriteFPUL], [II_CEIL, II_FLOOR, II_ROUND]>; +def : InstRW<[P5600WriteFPUL], (instregex "^CEIL_(L|W)_(S|D32|D64)$")>; +def : InstRW<[P5600WriteFPUL], (instregex "^FLOOR_(L|W)_(S|D32|D64)$")>; +def : InstRW<[P5600WriteFPUL], (instregex "^ROUND_(L|W)_(S|D32|D64)$")>; // rotrv // Reason behind guess: rotr is in the same category and the two register forms // generally follow the immediate forms in this category -def : ItinRW<[P5600WriteEitherALU], [II_ROTRV]>; +def : InstRW<[P5600WriteEitherALU], (instrs ROTRV)>; } diff --git a/lib/Target/Mips/MipsSubtarget.cpp b/lib/Target/Mips/MipsSubtarget.cpp index f6af7e22e351..0c39a45467c4 100644 --- a/lib/Target/Mips/MipsSubtarget.cpp +++ b/lib/Target/Mips/MipsSubtarget.cpp @@ -16,6 +16,9 @@ #include "MipsMachineFunction.h" #include "MipsRegisterInfo.h" #include "MipsTargetMachine.h" +#include "MipsCallLowering.h" +#include "MipsLegalizerInfo.h" +#include "MipsRegisterBankInfo.h" #include "llvm/IR/Attributes.h" #include "llvm/IR/Function.h" #include "llvm/Support/CommandLine.h" @@ -57,6 +60,12 @@ static cl::opt<bool> GPOpt("mgpopt", cl::Hidden, cl::desc("Enable gp-relative addressing of mips small data items")); +bool MipsSubtarget::DspWarningPrinted = false; +bool MipsSubtarget::MSAWarningPrinted = false; +bool MipsSubtarget::VirtWarningPrinted = false; +bool MipsSubtarget::CRCWarningPrinted = false; +bool MipsSubtarget::GINVWarningPrinted = false; + void MipsSubtarget::anchor() {} MipsSubtarget::MipsSubtarget(const Triple &TT, StringRef CPU, StringRef FS, @@ -71,10 +80,12 @@ MipsSubtarget::MipsSubtarget(const Triple &TT, StringRef CPU, StringRef FS, InMips16HardFloat(Mips16HardFloat), InMicroMipsMode(false), HasDSP(false), HasDSPR2(false), HasDSPR3(false), AllowMixed16_32(Mixed16_32 | Mips_Os16), Os16(Mips_Os16), HasMSA(false), UseTCCInDIV(false), HasSym32(false), - HasEVA(false), DisableMadd4(false), HasMT(false), - StackAlignOverride(StackAlignOverride), TM(TM), TargetTriple(TT), - TSInfo(), InstrInfo(MipsInstrInfo::create( - initializeSubtargetDependencies(CPU, FS, TM))), + HasEVA(false), DisableMadd4(false), HasMT(false), HasCRC(false), + HasVirt(false), HasGINV(false), UseIndirectJumpsHazard(false), + StackAlignOverride(StackAlignOverride), + TM(TM), TargetTriple(TT), TSInfo(), + InstrInfo( + MipsInstrInfo::create(initializeSubtargetDependencies(CPU, FS, TM))), FrameLowering(MipsFrameLowering::create(*this)), TLInfo(MipsTargetLowering::create(TM, *this)) { @@ -107,6 +118,17 @@ MipsSubtarget::MipsSubtarget(const Triple &TT, StringRef CPU, StringRef FS, if (hasMips64r6() && InMicroMipsMode) report_fatal_error("microMIPS64R6 is not supported", false); + if (!isABI_O32() && InMicroMipsMode) + report_fatal_error("microMIPS64 is not supported.", false); + + if (UseIndirectJumpsHazard) { + if (InMicroMipsMode) + report_fatal_error( + "cannot combine indirect jumps with hazard barriers and microMIPS"); + if (!hasMips32r2()) + report_fatal_error( + "indirect jumps with hazard barriers requires MIPS32R2 or later"); + } if (hasMips32r6()) { StringRef ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6"; @@ -129,6 +151,59 @@ MipsSubtarget::MipsSubtarget(const Triple &TT, StringRef CPU, StringRef FS, << "\n"; UseSmallSection = false; } + + if (hasDSPR2() && !DspWarningPrinted) { + if (hasMips64() && !hasMips64r2()) { + errs() << "warning: the 'dspr2' ASE requires MIPS64 revision 2 or " + << "greater\n"; + DspWarningPrinted = true; + } else if (hasMips32() && !hasMips32r2()) { + errs() << "warning: the 'dspr2' ASE requires MIPS32 revision 2 or " + << "greater\n"; + DspWarningPrinted = true; + } + } else if (hasDSP() && !DspWarningPrinted) { + if (hasMips64() && !hasMips64r2()) { + errs() << "warning: the 'dsp' ASE requires MIPS64 revision 2 or " + << "greater\n"; + DspWarningPrinted = true; + } else if (hasMips32() && !hasMips32r2()) { + errs() << "warning: the 'dsp' ASE requires MIPS32 revision 2 or " + << "greater\n"; + DspWarningPrinted = true; + } + } + + StringRef ArchName = hasMips64() ? "MIPS64" : "MIPS32"; + + if (!hasMips32r5() && hasMSA() && !MSAWarningPrinted) { + errs() << "warning: the 'msa' ASE requires " << ArchName + << " revision 5 or greater\n"; + MSAWarningPrinted = true; + } + if (!hasMips32r5() && hasVirt() && !VirtWarningPrinted) { + errs() << "warning: the 'virt' ASE requires " << ArchName + << " revision 5 or greater\n"; + VirtWarningPrinted = true; + } + if (!hasMips32r6() && hasCRC() && !CRCWarningPrinted) { + errs() << "warning: the 'crc' ASE requires " << ArchName + << " revision 6 or greater\n"; + CRCWarningPrinted = true; + } + if (!hasMips32r6() && hasGINV() && !GINVWarningPrinted) { + errs() << "warning: the 'ginv' ASE requires " << ArchName + << " revision 6 or greater\n"; + GINVWarningPrinted = true; + } + + CallLoweringInfo.reset(new MipsCallLowering(*getTargetLowering())); + Legalizer.reset(new MipsLegalizerInfo(*this)); + + auto *RBI = new MipsRegisterBankInfo(*getRegisterInfo()); + RegBankInfo.reset(RBI); + InstSelector.reset(createMipsInstructionSelector( + *static_cast<const MipsTargetMachine *>(&TM), *this, *RBI)); } bool MipsSubtarget::isPositionIndependent() const { @@ -174,7 +249,8 @@ MipsSubtarget::initializeSubtargetDependencies(StringRef CPU, StringRef FS, } bool MipsSubtarget::useConstantIslands() { - DEBUG(dbgs() << "use constant islands " << Mips16ConstantIslands << "\n"); + LLVM_DEBUG(dbgs() << "use constant islands " << Mips16ConstantIslands + << "\n"); return Mips16ConstantIslands; } @@ -186,3 +262,19 @@ bool MipsSubtarget::isABI_N64() const { return getABI().IsN64(); } bool MipsSubtarget::isABI_N32() const { return getABI().IsN32(); } bool MipsSubtarget::isABI_O32() const { return getABI().IsO32(); } const MipsABIInfo &MipsSubtarget::getABI() const { return TM.getABI(); } + +const CallLowering *MipsSubtarget::getCallLowering() const { + return CallLoweringInfo.get(); +} + +const LegalizerInfo *MipsSubtarget::getLegalizerInfo() const { + return Legalizer.get(); +} + +const RegisterBankInfo *MipsSubtarget::getRegBankInfo() const { + return RegBankInfo.get(); +} + +const InstructionSelector *MipsSubtarget::getInstructionSelector() const { + return InstSelector.get(); +} diff --git a/lib/Target/Mips/MipsSubtarget.h b/lib/Target/Mips/MipsSubtarget.h index 8b10b0596e0e..676d702ba63e 100644 --- a/lib/Target/Mips/MipsSubtarget.h +++ b/lib/Target/Mips/MipsSubtarget.h @@ -20,6 +20,10 @@ #include "MipsInstrInfo.h" #include "llvm/CodeGen/SelectionDAGTargetInfo.h" #include "llvm/CodeGen/TargetSubtargetInfo.h" +#include "llvm/CodeGen/GlobalISel/CallLowering.h" +#include "llvm/CodeGen/GlobalISel/LegalizerInfo.h" +#include "llvm/CodeGen/GlobalISel/RegisterBankInfo.h" +#include "llvm/CodeGen/GlobalISel/InstructionSelector.h" #include "llvm/IR/DataLayout.h" #include "llvm/MC/MCInstrItineraries.h" #include "llvm/Support/ErrorHandling.h" @@ -44,6 +48,21 @@ class MipsSubtarget : public MipsGenSubtargetInfo { enum class CPU { P5600 }; + // Used to avoid printing dsp warnings multiple times. + static bool DspWarningPrinted; + + // Used to avoid printing msa warnings multiple times. + static bool MSAWarningPrinted; + + // Used to avoid printing crc warnings multiple times. + static bool CRCWarningPrinted; + + // Used to avoid printing ginv warnings multiple times. + static bool GINVWarningPrinted; + + // Used to avoid printing virt warnings multiple times. + static bool VirtWarningPrinted; + // Mips architecture version MipsArchEnum MipsArchVersion; @@ -152,6 +171,19 @@ class MipsSubtarget : public MipsGenSubtargetInfo { // HasMT -- support MT ASE. bool HasMT; + // HasCRC -- supports R6 CRC ASE + bool HasCRC; + + // HasVirt -- supports Virtualization ASE + bool HasVirt; + + // HasGINV -- supports R6 Global INValidate ASE + bool HasGINV; + + // Use hazard variants of the jump register instructions for indirect + // function calls and jump tables. + bool UseIndirectJumpsHazard; + // Disable use of the `jal` instruction. bool UseLongCalls = false; @@ -272,6 +304,12 @@ public: bool disableMadd4() const { return DisableMadd4; } bool hasEVA() const { return HasEVA; } bool hasMT() const { return HasMT; } + bool hasCRC() const { return HasCRC; } + bool hasVirt() const { return HasVirt; } + bool hasGINV() const { return HasGINV; } + bool useIndirectJumpsHazard() const { + return UseIndirectJumpsHazard && hasMips32r2(); + } bool useSmallSection() const { return UseSmallSection; } bool hasStandardEncoding() const { return !inMips16Mode(); } @@ -336,6 +374,19 @@ public: const InstrItineraryData *getInstrItineraryData() const override { return &InstrItins; } + +protected: + // GlobalISel related APIs. + std::unique_ptr<CallLowering> CallLoweringInfo; + std::unique_ptr<LegalizerInfo> Legalizer; + std::unique_ptr<RegisterBankInfo> RegBankInfo; + std::unique_ptr<InstructionSelector> InstSelector; + +public: + const CallLowering *getCallLowering() const override; + const LegalizerInfo *getLegalizerInfo() const override; + const RegisterBankInfo *getRegBankInfo() const override; + const InstructionSelector *getInstructionSelector() const override; }; } // End llvm namespace diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp index fb79a4bf40c5..1e6fe2b9f7e7 100644 --- a/lib/Target/Mips/MipsTargetMachine.cpp +++ b/lib/Target/Mips/MipsTargetMachine.cpp @@ -23,6 +23,10 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/Analysis/TargetTransformInfo.h" +#include "llvm/CodeGen/GlobalISel/IRTranslator.h" +#include "llvm/CodeGen/GlobalISel/Legalizer.h" +#include "llvm/CodeGen/GlobalISel/RegBankSelect.h" +#include "llvm/CodeGen/GlobalISel/InstructionSelect.h" #include "llvm/CodeGen/BasicTTIImpl.h" #include "llvm/CodeGen/MachineFunction.h" #include "llvm/CodeGen/Passes.h" @@ -46,6 +50,12 @@ extern "C" void LLVMInitializeMipsTarget() { RegisterTargetMachine<MipselTargetMachine> Y(getTheMipselTarget()); RegisterTargetMachine<MipsebTargetMachine> A(getTheMips64Target()); RegisterTargetMachine<MipselTargetMachine> B(getTheMips64elTarget()); + + PassRegistry *PR = PassRegistry::getPassRegistry(); + initializeGlobalISel(*PR); + initializeMipsDelaySlotFillerPass(*PR); + initializeMipsBranchExpansionPass(*PR); + initializeMicroMipsSizeReducePass(*PR); } static std::string computeDataLayout(const Triple &TT, StringRef CPU, @@ -198,7 +208,7 @@ MipsTargetMachine::getSubtargetImpl(const Function &F) const { } void MipsTargetMachine::resetSubtarget(MachineFunction *MF) { - DEBUG(dbgs() << "resetSubtarget\n"); + LLVM_DEBUG(dbgs() << "resetSubtarget\n"); Subtarget = const_cast<MipsSubtarget *>(getSubtargetImpl(MF->getFunction())); MF->setSubtarget(Subtarget); @@ -230,6 +240,11 @@ public: bool addInstSelector() override; void addPreEmitPass() override; void addPreRegAlloc() override; + void addPreEmit2() ; + bool addIRTranslator() override; + bool addLegalizeMachineIR() override; + bool addRegBankSelect() override; + bool addGlobalInstructionSelect() override; }; } // end anonymous namespace @@ -262,26 +277,62 @@ void MipsPassConfig::addPreRegAlloc() { TargetTransformInfo MipsTargetMachine::getTargetTransformInfo(const Function &F) { if (Subtarget->allowMixed16_32()) { - DEBUG(errs() << "No Target Transform Info Pass Added\n"); + LLVM_DEBUG(errs() << "No Target Transform Info Pass Added\n"); // FIXME: This is no longer necessary as the TTI returned is per-function. return TargetTransformInfo(F.getParent()->getDataLayout()); } - DEBUG(errs() << "Target Transform Info Pass Added\n"); + LLVM_DEBUG(errs() << "Target Transform Info Pass Added\n"); return TargetTransformInfo(BasicTTIImpl(this, F)); } +void MipsPassConfig::addPreEmit2() { +} + // Implemented by targets that want to run passes immediately before // machine code is emitted. return true if -print-machineinstrs should // print out the code after the passes. void MipsPassConfig::addPreEmitPass() { - addPass(createMicroMipsSizeReductionPass()); + // Expand pseudo instructions that are sensitive to register allocation. + addPass(createMipsExpandPseudoPass()); - // The delay slot filler and the long branch passes can potientially create - // forbidden slot/ hazards for MIPSR6 which the hazard schedule pass will - // fix. Any new pass must come before the hazard schedule pass. + // The microMIPS size reduction pass performs instruction reselection for + // instructions which can be remapped to a 16 bit instruction. + addPass(createMicroMipsSizeReducePass()); + + // The delay slot filler pass can potientially create forbidden slot hazards + // for MIPSR6 and therefore it should go before MipsBranchExpansion pass. addPass(createMipsDelaySlotFillerPass()); - addPass(createMipsLongBranchPass()); - addPass(createMipsHazardSchedule()); + + // This pass expands branches and takes care about the forbidden slot hazards. + // Expanding branches may potentially create forbidden slot hazards for + // MIPSR6, and fixing such hazard may potentially break a branch by extending + // its offset out of range. That's why this pass combine these two tasks, and + // runs them alternately until one of them finishes without any changes. Only + // then we can be sure that all branches are expanded properly and no hazards + // exists. + // Any new pass should go before this pass. + addPass(createMipsBranchExpansion()); + addPass(createMipsConstantIslandPass()); } + +bool MipsPassConfig::addIRTranslator() { + addPass(new IRTranslator()); + return false; +} + +bool MipsPassConfig::addLegalizeMachineIR() { + addPass(new Legalizer()); + return false; +} + +bool MipsPassConfig::addRegBankSelect() { + addPass(new RegBankSelect()); + return false; +} + +bool MipsPassConfig::addGlobalInstructionSelect() { + addPass(new InstructionSelect()); + return false; +} diff --git a/lib/Target/Mips/MipsTargetMachine.h b/lib/Target/Mips/MipsTargetMachine.h index 56e6e5d8daa2..d9b73d151119 100644 --- a/lib/Target/Mips/MipsTargetMachine.h +++ b/lib/Target/Mips/MipsTargetMachine.h @@ -54,7 +54,7 @@ public: const MipsSubtarget *getSubtargetImpl(const Function &F) const override; - /// \brief Reset the subtarget for the Mips target. + /// Reset the subtarget for the Mips target. void resetSubtarget(MachineFunction *MF); // Pass Pipeline Configuration diff --git a/lib/Target/Mips/MipsTargetObjectFile.cpp b/lib/Target/Mips/MipsTargetObjectFile.cpp index 9db6b7b1bcd6..f767c8321988 100644 --- a/lib/Target/Mips/MipsTargetObjectFile.cpp +++ b/lib/Target/Mips/MipsTargetObjectFile.cpp @@ -136,6 +136,13 @@ IsGlobalInSmallSectionImpl(const GlobalObject *GO, return false; Type *Ty = GVA->getValueType(); + + // It is possible that the type of the global is unsized, i.e. a declaration + // of a extern struct. In this case don't presume it is in the small data + // section. This happens e.g. when building the FreeBSD kernel. + if (!Ty->isSized()) + return false; + return IsInSmallSection( GVA->getParent()->getDataLayout().getTypeAllocSize(Ty)); } diff --git a/lib/Target/Mips/MipsTargetStreamer.h b/lib/Target/Mips/MipsTargetStreamer.h index 42473aac7288..a282366f6d40 100644 --- a/lib/Target/Mips/MipsTargetStreamer.h +++ b/lib/Target/Mips/MipsTargetStreamer.h @@ -42,6 +42,12 @@ public: virtual void emitDirectiveSetNoMsa(); virtual void emitDirectiveSetMt(); virtual void emitDirectiveSetNoMt(); + virtual void emitDirectiveSetCRC(); + virtual void emitDirectiveSetNoCRC(); + virtual void emitDirectiveSetVirt(); + virtual void emitDirectiveSetNoVirt(); + virtual void emitDirectiveSetGINV(); + virtual void emitDirectiveSetNoGINV(); virtual void emitDirectiveSetAt(); virtual void emitDirectiveSetAtWithArg(unsigned RegNo); virtual void emitDirectiveSetNoAt(); @@ -103,6 +109,12 @@ public: virtual void emitDirectiveSetFp(MipsABIFlagsSection::FpABIKind Value); virtual void emitDirectiveSetOddSPReg(); virtual void emitDirectiveSetNoOddSPReg(); + virtual void emitDirectiveModuleCRC(); + virtual void emitDirectiveModuleNoCRC(); + virtual void emitDirectiveModuleVirt(); + virtual void emitDirectiveModuleNoVirt(); + virtual void emitDirectiveModuleGINV(); + virtual void emitDirectiveModuleNoGINV(); void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc, const MCSubtargetInfo *STI); @@ -213,6 +225,12 @@ public: void emitDirectiveSetNoMsa() override; void emitDirectiveSetMt() override; void emitDirectiveSetNoMt() override; + void emitDirectiveSetCRC() override; + void emitDirectiveSetNoCRC() override; + void emitDirectiveSetVirt() override; + void emitDirectiveSetNoVirt() override; + void emitDirectiveSetGINV() override; + void emitDirectiveSetNoGINV() override; void emitDirectiveSetAt() override; void emitDirectiveSetAtWithArg(unsigned RegNo) override; void emitDirectiveSetNoAt() override; @@ -278,6 +296,12 @@ public: void emitDirectiveModuleSoftFloat() override; void emitDirectiveModuleHardFloat() override; void emitDirectiveModuleMT() override; + void emitDirectiveModuleCRC() override; + void emitDirectiveModuleNoCRC() override; + void emitDirectiveModuleVirt() override; + void emitDirectiveModuleNoVirt() override; + void emitDirectiveModuleGINV() override; + void emitDirectiveModuleNoGINV() override; void emitDirectiveSetFp(MipsABIFlagsSection::FpABIKind Value) override; void emitDirectiveSetOddSPReg() override; void emitDirectiveSetNoOddSPReg() override; |