summaryrefslogtreecommitdiff
path: root/lib/Target/Mips
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/Mips')
-rw-r--r--lib/Target/Mips/AsmParser/MipsAsmParser.cpp814
-rw-r--r--lib/Target/Mips/CMakeLists.txt32
-rw-r--r--lib/Target/Mips/Disassembler/MipsDisassembler.cpp115
-rw-r--r--lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp5
-rw-r--r--lib/Target/Mips/InstPrinter/MipsInstPrinter.h1
-rw-r--r--lib/Target/Mips/LLVMBuild.txt1
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h6
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp2
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp128
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h19
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp61
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsELFStreamer.cpp16
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsELFStreamer.h10
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h10
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp14
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp37
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h4
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h2
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp11
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.h10
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp12
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp66
-rw-r--r--lib/Target/Mips/MicroMips32r6InstrFormats.td164
-rw-r--r--lib/Target/Mips/MicroMips32r6InstrInfo.td392
-rw-r--r--lib/Target/Mips/MicroMipsDSPInstrFormats.td8
-rw-r--r--lib/Target/Mips/MicroMipsDSPInstrInfo.td13
-rw-r--r--lib/Target/Mips/MicroMipsInstrFPU.td350
-rw-r--r--lib/Target/Mips/MicroMipsInstrFormats.td75
-rw-r--r--lib/Target/Mips/MicroMipsInstrInfo.td947
-rw-r--r--lib/Target/Mips/MicroMipsSizeReduction.cpp297
-rw-r--r--lib/Target/Mips/Mips.h19
-rw-r--r--lib/Target/Mips/Mips.td19
-rw-r--r--lib/Target/Mips/Mips16FrameLowering.cpp8
-rw-r--r--lib/Target/Mips/Mips16HardFloat.cpp6
-rw-r--r--lib/Target/Mips/Mips16ISelDAGToDAG.cpp35
-rw-r--r--lib/Target/Mips/Mips16InstrInfo.cpp11
-rw-r--r--lib/Target/Mips/Mips16InstrInfo.h3
-rw-r--r--lib/Target/Mips/Mips16InstrInfo.td25
-rw-r--r--lib/Target/Mips/Mips16RegisterInfo.cpp4
-rw-r--r--lib/Target/Mips/Mips32r6InstrFormats.td30
-rw-r--r--lib/Target/Mips/Mips32r6InstrInfo.td101
-rw-r--r--lib/Target/Mips/Mips64InstrInfo.td458
-rw-r--r--lib/Target/Mips/Mips64r6InstrInfo.td57
-rw-r--r--lib/Target/Mips/MipsAsmPrinter.cpp31
-rw-r--r--lib/Target/Mips/MipsBranchExpansion.cpp (renamed from lib/Target/Mips/MipsLongBranch.cpp)483
-rw-r--r--lib/Target/Mips/MipsCallLowering.cpp441
-rw-r--r--lib/Target/Mips/MipsCallLowering.h86
-rw-r--r--lib/Target/Mips/MipsCondMov.td287
-rw-r--r--lib/Target/Mips/MipsConstantIslandPass.cpp99
-rw-r--r--lib/Target/Mips/MipsDSPInstrFormats.td14
-rw-r--r--lib/Target/Mips/MipsDSPInstrInfo.td6
-rw-r--r--lib/Target/Mips/MipsDelaySlotFiller.cpp76
-rw-r--r--lib/Target/Mips/MipsEVAInstrFormats.td2
-rw-r--r--lib/Target/Mips/MipsEVAInstrInfo.td79
-rw-r--r--lib/Target/Mips/MipsExpandPseudo.cpp702
-rw-r--r--lib/Target/Mips/MipsFastISel.cpp85
-rw-r--r--lib/Target/Mips/MipsFrameLowering.h4
-rw-r--r--lib/Target/Mips/MipsHazardSchedule.cpp163
-rw-r--r--lib/Target/Mips/MipsISelDAGToDAG.cpp13
-rw-r--r--lib/Target/Mips/MipsISelDAGToDAG.h28
-rw-r--r--lib/Target/Mips/MipsISelLowering.cpp730
-rw-r--r--lib/Target/Mips/MipsISelLowering.h38
-rw-r--r--lib/Target/Mips/MipsInstrFPU.td323
-rw-r--r--lib/Target/Mips/MipsInstrFormats.td35
-rw-r--r--lib/Target/Mips/MipsInstrInfo.cpp186
-rw-r--r--lib/Target/Mips/MipsInstrInfo.h4
-rw-r--r--lib/Target/Mips/MipsInstrInfo.td1101
-rw-r--r--lib/Target/Mips/MipsInstructionSelector.cpp184
-rw-r--r--lib/Target/Mips/MipsLegalizerInfo.cpp41
-rw-r--r--lib/Target/Mips/MipsLegalizerInfo.h29
-rw-r--r--lib/Target/Mips/MipsMCInstLower.cpp81
-rw-r--r--lib/Target/Mips/MipsMCInstLower.h4
-rw-r--r--lib/Target/Mips/MipsMSAInstrFormats.td5
-rw-r--r--lib/Target/Mips/MipsMSAInstrInfo.td136
-rw-r--r--lib/Target/Mips/MipsMTInstrFormats.td3
-rw-r--r--lib/Target/Mips/MipsMachineFunction.cpp38
-rw-r--r--lib/Target/Mips/MipsModuleISelDAGToDAG.cpp4
-rw-r--r--lib/Target/Mips/MipsOptimizePICCall.cpp12
-rw-r--r--lib/Target/Mips/MipsOs16.cpp16
-rw-r--r--lib/Target/Mips/MipsRegisterBankInfo.cpp100
-rw-r--r--lib/Target/Mips/MipsRegisterBankInfo.h43
-rw-r--r--lib/Target/Mips/MipsRegisterBanks.td13
-rw-r--r--lib/Target/Mips/MipsRegisterInfo.cpp16
-rw-r--r--lib/Target/Mips/MipsRegisterInfo.h4
-rw-r--r--lib/Target/Mips/MipsSEFrameLowering.cpp17
-rw-r--r--lib/Target/Mips/MipsSEFrameLowering.h1
-rw-r--r--lib/Target/Mips/MipsSEISelDAGToDAG.cpp8
-rw-r--r--lib/Target/Mips/MipsSEISelDAGToDAG.h28
-rw-r--r--lib/Target/Mips/MipsSEISelLowering.cpp174
-rw-r--r--lib/Target/Mips/MipsSEISelLowering.h34
-rw-r--r--lib/Target/Mips/MipsSEInstrInfo.cpp148
-rw-r--r--lib/Target/Mips/MipsSEInstrInfo.h9
-rw-r--r--lib/Target/Mips/MipsSERegisterInfo.cpp7
-rw-r--r--lib/Target/Mips/MipsSchedule.td48
-rw-r--r--lib/Target/Mips/MipsScheduleGeneric.td9
-rw-r--r--lib/Target/Mips/MipsScheduleP5600.td178
-rw-r--r--lib/Target/Mips/MipsSubtarget.cpp102
-rw-r--r--lib/Target/Mips/MipsSubtarget.h51
-rw-r--r--lib/Target/Mips/MipsTargetMachine.cpp69
-rw-r--r--lib/Target/Mips/MipsTargetMachine.h2
-rw-r--r--lib/Target/Mips/MipsTargetObjectFile.cpp7
-rw-r--r--lib/Target/Mips/MipsTargetStreamer.h24
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;