summaryrefslogtreecommitdiff
path: root/lib/Target/Mips
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/Mips')
-rw-r--r--lib/Target/Mips/AsmParser/Makefile15
-rw-r--r--lib/Target/Mips/AsmParser/MipsAsmParser.cpp1724
-rw-r--r--lib/Target/Mips/CMakeLists.txt1
-rw-r--r--lib/Target/Mips/Disassembler/Makefile16
-rw-r--r--lib/Target/Mips/Disassembler/MipsDisassembler.cpp376
-rw-r--r--lib/Target/Mips/InstPrinter/Makefile16
-rw-r--r--lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp96
-rw-r--r--lib/Target/Mips/InstPrinter/MipsInstPrinter.h4
-rw-r--r--lib/Target/Mips/MCTargetDesc/Makefile17
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp22
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h17
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp47
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsABIInfo.h9
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp77
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h5
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h10
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp614
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h19
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp5
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp415
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h27
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp295
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsMCExpr.h66
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp55
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp378
-rw-r--r--lib/Target/Mips/Makefile25
-rw-r--r--lib/Target/Mips/MicroMips32r6InstrFormats.td238
-rw-r--r--lib/Target/Mips/MicroMips32r6InstrInfo.td717
-rw-r--r--lib/Target/Mips/MicroMips64r6InstrFormats.td141
-rw-r--r--lib/Target/Mips/MicroMips64r6InstrInfo.td404
-rw-r--r--lib/Target/Mips/MicroMipsDSPInstrFormats.td58
-rw-r--r--lib/Target/Mips/MicroMipsDSPInstrInfo.td79
-rw-r--r--lib/Target/Mips/MicroMipsInstrFPU.td39
-rw-r--r--lib/Target/Mips/MicroMipsInstrFormats.td9
-rw-r--r--lib/Target/Mips/MicroMipsInstrInfo.td360
-rw-r--r--lib/Target/Mips/Mips.h3
-rw-r--r--lib/Target/Mips/Mips.td5
-rw-r--r--lib/Target/Mips/Mips16FrameLowering.cpp1
-rw-r--r--lib/Target/Mips/Mips16HardFloat.cpp28
-rw-r--r--lib/Target/Mips/Mips16ISelDAGToDAG.cpp182
-rw-r--r--lib/Target/Mips/Mips16ISelDAGToDAG.h26
-rw-r--r--lib/Target/Mips/Mips16ISelLowering.cpp137
-rw-r--r--lib/Target/Mips/Mips16ISelLowering.h28
-rw-r--r--lib/Target/Mips/Mips16InstrInfo.cpp25
-rw-r--r--lib/Target/Mips/Mips16InstrInfo.h16
-rw-r--r--lib/Target/Mips/Mips16InstrInfo.td85
-rw-r--r--lib/Target/Mips/Mips16RegisterInfo.cpp3
-rw-r--r--lib/Target/Mips/Mips32r6InstrFormats.td2
-rw-r--r--lib/Target/Mips/Mips32r6InstrInfo.td343
-rw-r--r--lib/Target/Mips/Mips64InstrInfo.td475
-rw-r--r--lib/Target/Mips/Mips64r6InstrInfo.td98
-rw-r--r--lib/Target/Mips/MipsAsmPrinter.cpp65
-rw-r--r--lib/Target/Mips/MipsAsmPrinter.h2
-rw-r--r--lib/Target/Mips/MipsCCState.cpp4
-rw-r--r--lib/Target/Mips/MipsCallingConv.td48
-rw-r--r--lib/Target/Mips/MipsCondMov.td12
-rw-r--r--lib/Target/Mips/MipsConstantIslandPass.cpp114
-rw-r--r--lib/Target/Mips/MipsDSPInstrFormats.td4
-rw-r--r--lib/Target/Mips/MipsDSPInstrInfo.td69
-rw-r--r--lib/Target/Mips/MipsDelaySlotFiller.cpp144
-rw-r--r--lib/Target/Mips/MipsEVAInstrInfo.td73
-rw-r--r--lib/Target/Mips/MipsFastISel.cpp39
-rw-r--r--lib/Target/Mips/MipsFrameLowering.cpp16
-rw-r--r--lib/Target/Mips/MipsFrameLowering.h2
-rw-r--r--lib/Target/Mips/MipsHazardSchedule.cpp147
-rw-r--r--lib/Target/Mips/MipsISelDAGToDAG.cpp53
-rw-r--r--lib/Target/Mips/MipsISelDAGToDAG.h25
-rw-r--r--lib/Target/Mips/MipsISelLowering.cpp419
-rw-r--r--lib/Target/Mips/MipsISelLowering.h96
-rw-r--r--lib/Target/Mips/MipsInstrFPU.td130
-rw-r--r--lib/Target/Mips/MipsInstrFormats.td7
-rw-r--r--lib/Target/Mips/MipsInstrInfo.cpp236
-rw-r--r--lib/Target/Mips/MipsInstrInfo.h26
-rw-r--r--lib/Target/Mips/MipsInstrInfo.td1036
-rw-r--r--lib/Target/Mips/MipsLongBranch.cpp72
-rw-r--r--lib/Target/Mips/MipsMCInstLower.cpp155
-rw-r--r--lib/Target/Mips/MipsMCInstLower.h8
-rw-r--r--lib/Target/Mips/MipsMSAInstrInfo.td220
-rw-r--r--lib/Target/Mips/MipsMachineFunction.cpp16
-rw-r--r--lib/Target/Mips/MipsMachineFunction.h15
-rw-r--r--lib/Target/Mips/MipsOs16.cpp26
-rw-r--r--lib/Target/Mips/MipsRegisterInfo.cpp20
-rw-r--r--lib/Target/Mips/MipsRegisterInfo.h22
-rw-r--r--lib/Target/Mips/MipsRegisterInfo.td13
-rw-r--r--lib/Target/Mips/MipsSEFrameLowering.cpp12
-rw-r--r--lib/Target/Mips/MipsSEISelDAGToDAG.cpp141
-rw-r--r--lib/Target/Mips/MipsSEISelDAGToDAG.h34
-rw-r--r--lib/Target/Mips/MipsSEISelLowering.cpp256
-rw-r--r--lib/Target/Mips/MipsSEISelLowering.h24
-rw-r--r--lib/Target/Mips/MipsSEInstrInfo.cpp94
-rw-r--r--lib/Target/Mips/MipsSEInstrInfo.h13
-rw-r--r--lib/Target/Mips/MipsSERegisterInfo.cpp54
-rw-r--r--lib/Target/Mips/MipsSchedule.td226
-rw-r--r--lib/Target/Mips/MipsScheduleP5600.td2
-rw-r--r--lib/Target/Mips/MipsSubtarget.cpp9
-rw-r--r--lib/Target/Mips/MipsSubtarget.h14
-rw-r--r--lib/Target/Mips/MipsTargetMachine.cpp34
-rw-r--r--lib/Target/Mips/MipsTargetMachine.h13
-rw-r--r--lib/Target/Mips/MipsTargetObjectFile.cpp16
-rw-r--r--lib/Target/Mips/MipsTargetObjectFile.h3
-rw-r--r--lib/Target/Mips/MipsTargetStreamer.h77
-rw-r--r--lib/Target/Mips/TargetInfo/Makefile15
102 files changed, 8171 insertions, 4053 deletions
diff --git a/lib/Target/Mips/AsmParser/Makefile b/lib/Target/Mips/AsmParser/Makefile
deleted file mode 100644
index 679acee9fe724..0000000000000
--- a/lib/Target/Mips/AsmParser/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-##===- lib/Target/Mips/AsmParser/Makefile ------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-LEVEL = ../../../..
-LIBRARYNAME = LLVMMipsAsmParser
-
-# Hack: we need to include 'main' mips target directory to grab private headers
-CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
-
-include $(LEVEL)/Makefile.common
diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
index d4e061f00d3ac..b51d0200b0b1a 100644
--- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -13,7 +13,6 @@
#include "MipsRegisterInfo.h"
#include "MipsTargetObjectFile.h"
#include "MipsTargetStreamer.h"
-#include "llvm/ADT/APInt.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/MC/MCContext.h"
@@ -22,11 +21,13 @@
#include "llvm/MC/MCInstBuilder.h"
#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
+#include "llvm/MC/MCParser/MCTargetAsmParser.h"
+#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbol.h"
-#include "llvm/MC/MCTargetAsmParser.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/ELF.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/TargetRegistry.h"
@@ -157,7 +158,6 @@ class MipsAsmParser : public MCTargetAsmParser {
OperandMatchResultTy parseImm(OperandVector &Operands);
OperandMatchResultTy parseJumpTarget(OperandVector &Operands);
OperandMatchResultTy parseInvNum(OperandVector &Operands);
- OperandMatchResultTy parseLSAImm(OperandVector &Operands);
OperandMatchResultTy parseRegisterPair(OperandVector &Operands);
OperandMatchResultTy parseMovePRegPair(OperandVector &Operands);
OperandMatchResultTy parseRegisterList(OperandVector &Operands);
@@ -173,74 +173,77 @@ class MipsAsmParser : public MCTargetAsmParser {
};
// Expands assembly pseudo instructions.
- MacroExpanderResultTy
- tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
+ MacroExpanderResultTy tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
+ MCStreamer &Out,
+ const MCSubtargetInfo *STI);
- bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
+ bool expandJalWithRegs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI);
bool loadImmediate(int64_t ImmValue, unsigned DstReg, unsigned SrcReg,
bool Is32BitImm, bool IsAddress, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
+ MCStreamer &Out, const MCSubtargetInfo *STI);
bool loadAndAddSymbolAddress(const MCExpr *SymExpr, unsigned DstReg,
unsigned SrcReg, bool Is32BitSym, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
+ MCStreamer &Out, const MCSubtargetInfo *STI);
bool expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
+ MCStreamer &Out, const MCSubtargetInfo *STI);
bool expandLoadAddress(unsigned DstReg, unsigned BaseReg,
const MCOperand &Offset, bool Is32BitAddress,
- SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions);
+ SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI);
- bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
+ bool expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI);
- void expandMemInst(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions, bool isLoad,
- bool isImmOpnd);
+ void expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI, bool IsLoad, bool IsImmOpnd);
- bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
+ void expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI, bool IsImmOpnd);
- bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
+ void expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI, bool IsImmOpnd);
- bool expandBranchImm(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
+ bool expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI);
- bool expandCondBranches(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
+ bool expandAliasImmediate(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI);
- bool expandDiv(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions, const bool IsMips64,
- const bool Signed);
+ bool expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI);
- bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
+ bool expandCondBranches(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI);
- bool expandUlw(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
+ bool expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI, const bool IsMips64,
+ const bool Signed);
- bool expandRotation(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
- bool expandRotationImm(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
- bool expandDRotation(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
- bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
+ bool expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU, SMLoc IDLoc,
+ MCStreamer &Out, const MCSubtargetInfo *STI);
- void createNop(bool hasShortDelaySlot, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
+ bool expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI);
- void createAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg,
- bool Is64Bit, SmallVectorImpl<MCInst> &Instructions);
+ bool expandUlw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI);
- void createCpRestoreMemOp(bool IsLoad, int StackOffset, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
+ bool expandRotation(MCInst &Inst, SMLoc IDLoc,
+ MCStreamer &Out, const MCSubtargetInfo *STI);
+ bool expandRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI);
+ bool expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI);
+ bool expandDRotationImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI);
+
+ bool expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI);
bool reportParseError(Twine ErrorMsg);
bool reportParseError(SMLoc Loc, Twine ErrorMsg);
@@ -263,6 +266,7 @@ class MipsAsmParser : public MCTargetAsmParser {
bool parseDirectiveSet();
bool parseDirectiveOption();
bool parseInsnDirective();
+ bool parseSSectionDirective(StringRef Section, unsigned Type);
bool parseSetAtDirective();
bool parseSetNoAtDirective();
@@ -295,16 +299,12 @@ class MipsAsmParser : public MCTargetAsmParser {
bool parseInternalDirectiveReallowModule();
- MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
-
bool eatComma(StringRef ErrorStr);
int matchCPURegisterName(StringRef Symbol);
int matchHWRegsRegisterName(StringRef Symbol);
- int matchRegisterByNumber(unsigned RegNum, unsigned RegClass);
-
int matchFPURegisterName(StringRef Name);
int matchFCCRegisterName(StringRef Name);
@@ -317,15 +317,13 @@ class MipsAsmParser : public MCTargetAsmParser {
unsigned getReg(int RC, int RegNo);
- unsigned getGPR(int RegNo);
-
/// Returns the internal register number for the current AT. Also checks if
/// the current AT is unavailable (set to $0) and gives an error if it is.
/// This should be used in pseudo-instruction expansions which need AT.
unsigned getATReg(SMLoc Loc);
- bool processInstruction(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions);
+ bool processInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI);
// Helper function that checks if the value of a vector index is within the
// boundaries of accepted values for each RegisterKind
@@ -395,6 +393,8 @@ class MipsAsmParser : public MCTargetAsmParser {
public:
enum MipsMatchResultTy {
Match_RequiresDifferentSrcAndDst = FIRST_TARGET_MATCH_RESULT_TY,
+ Match_RequiresDifferentOperands,
+ Match_RequiresNoZeroRegister,
#define GET_OPERAND_DIAGNOSTIC_TYPES
#include "MipsGenAsmMatcher.inc"
#undef GET_OPERAND_DIAGNOSTIC_TYPES
@@ -427,13 +427,12 @@ public:
CurrentFn = nullptr;
- IsPicEnabled =
- (getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_);
+ IsPicEnabled = getContext().getObjectFileInfo()->isPositionIndependent();
IsCpRestoreSet = false;
CpRestoreOffset = -1;
- Triple TheTriple(sti.getTargetTriple());
+ const Triple &TheTriple = sti.getTargetTriple();
if ((TheTriple.getArch() == Triple::mips) ||
(TheTriple.getArch() == Triple::mips64))
IsLittleEndian = false;
@@ -584,7 +583,6 @@ private:
enum KindTy {
k_Immediate, /// An immediate (possibly involving symbol references)
k_Memory, /// Base + Offset Memory Address
- k_PhysRegister, /// A physical register from the Mips namespace
k_RegisterIndex, /// A register index in one or more RegKind.
k_Token, /// A simple token
k_RegList, /// A physical register list
@@ -604,10 +602,6 @@ private:
unsigned Length;
};
- struct PhysRegOp {
- unsigned Num; /// Register Number
- };
-
struct RegIdxOp {
unsigned Index; /// Index into the register class
RegKind Kind; /// Bitfield of the kinds it could possibly be
@@ -629,7 +623,6 @@ private:
union {
struct Token Tok;
- struct PhysRegOp PhysReg;
struct RegIdxOp RegIdx;
struct ImmOp Imm;
struct MemOp Mem;
@@ -938,6 +931,34 @@ public:
Inst.addOperand(MCOperand::createImm(Imm));
}
+ template <unsigned Bits>
+ void addSImmOperands(MCInst &Inst, unsigned N) const {
+ if (isImm() && !isConstantImm()) {
+ addExpr(Inst, getImm());
+ return;
+ }
+ addConstantSImmOperands<Bits, 0, 0>(Inst, N);
+ }
+
+ template <unsigned Bits>
+ void addUImmOperands(MCInst &Inst, unsigned N) const {
+ if (isImm() && !isConstantImm()) {
+ addExpr(Inst, getImm());
+ return;
+ }
+ addConstantUImmOperands<Bits, 0, 0>(Inst, N);
+ }
+
+ template <unsigned Bits, int Offset = 0, int AdjustOffset = 0>
+ void addConstantSImmOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ int64_t Imm = getConstantImm() - Offset;
+ Imm = SignExtend64<Bits>(Imm);
+ Imm += Offset;
+ Imm += AdjustOffset;
+ Inst.addOperand(MCOperand::createImm(Imm));
+ }
+
void addImmOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
const MCExpr *Expr = getImm();
@@ -973,9 +994,19 @@ public:
void addRegPairOperands(MCInst &Inst, unsigned N) const {
assert(N == 2 && "Invalid number of operands!");
+ assert((RegIdx.Kind & RegKind_GPR) && "Invalid access!");
unsigned RegNo = getRegPair();
- Inst.addOperand(MCOperand::createReg(RegNo++));
- Inst.addOperand(MCOperand::createReg(RegNo));
+ AsmParser.warnIfRegIndexIsAT(RegNo, StartLoc);
+ Inst.addOperand(MCOperand::createReg(
+ RegIdx.RegInfo->getRegClass(
+ AsmParser.getABI().AreGprs64bit()
+ ? Mips::GPR64RegClassID
+ : Mips::GPR32RegClassID).getRegister(RegNo++)));
+ Inst.addOperand(MCOperand::createReg(
+ RegIdx.RegInfo->getRegClass(
+ AsmParser.getABI().AreGprs64bit()
+ ? Mips::GPR64RegClassID
+ : Mips::GPR32RegClassID).getRegister(RegNo)));
}
void addMovePRegPairOperands(MCInst &Inst, unsigned N) const {
@@ -985,12 +1016,9 @@ public:
}
bool isReg() const override {
- // As a special case until we sort out the definition of div/divu, pretend
- // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
- if (isGPRAsmReg() && RegIdx.Index == 0)
- return true;
-
- return Kind == k_PhysRegister;
+ // As a special case until we sort out the definition of div/divu, accept
+ // $0/$zero here so that MCK_ZERO works correctly.
+ return isGPRAsmReg() && RegIdx.Index == 0;
}
bool isRegIdx() const { return Kind == k_RegisterIndex; }
bool isImm() const override { return Kind == k_Immediate; }
@@ -1003,8 +1031,23 @@ public:
template <unsigned Bits, int Offset = 0> bool isConstantUImm() const {
return isConstantImm() && isUInt<Bits>(getConstantImm() - Offset);
}
- template <unsigned Bits> bool isConstantSImm() const {
- return isConstantImm() && isInt<Bits>(getConstantImm());
+ template <unsigned Bits> bool isSImm() const {
+ return isConstantImm() ? isInt<Bits>(getConstantImm()) : isImm();
+ }
+ template <unsigned Bits> bool isUImm() const {
+ return isConstantImm() ? isUInt<Bits>(getConstantImm()) : isImm();
+ }
+ template <unsigned Bits> bool isAnyImm() const {
+ return isConstantImm() ? (isInt<Bits>(getConstantImm()) ||
+ isUInt<Bits>(getConstantImm()))
+ : isImm();
+ }
+ template <unsigned Bits, int Offset = 0> bool isConstantSImm() const {
+ return isConstantImm() && isInt<Bits>(getConstantImm() - Offset);
+ }
+ template <unsigned Bottom, unsigned Top> bool isConstantUImmRange() const {
+ return isConstantImm() && getConstantImm() >= Bottom &&
+ getConstantImm() <= Top;
}
bool isToken() const override {
// Note: It's not possible to pretend that other operand kinds are tokens.
@@ -1015,13 +1058,22 @@ public:
bool isConstantMemOff() const {
return isMem() && isa<MCConstantExpr>(getMemOff());
}
- template <unsigned Bits> bool isMemWithSimmOffset() const {
- return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
- && getMemBase()->isGPRAsmReg();
- }
- template <unsigned Bits> bool isMemWithSimmOffsetGPR() const {
- return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff()) &&
- getMemBase()->isGPRAsmReg();
+ // Allow relocation operators.
+ // FIXME: This predicate and others need to look through binary expressions
+ // and determine whether a Value is a constant or not.
+ template <unsigned Bits, unsigned ShiftAmount = 0>
+ bool isMemWithSimmOffset() const {
+ if (!isMem())
+ return false;
+ if (!getMemBase()->isGPRAsmReg())
+ return false;
+ if (isa<MCTargetExpr>(getMemOff()) ||
+ (isConstantMemOff() &&
+ isShiftedInt<Bits, ShiftAmount>(getConstantMemOff())))
+ return true;
+ MCValue Res;
+ bool IsReloc = getMemOff()->evaluateAsRelocatable(Res, nullptr, nullptr);
+ return IsReloc && isShiftedInt<Bits, ShiftAmount>(Res.getConstant());
}
bool isMemWithGRPMM16Base() const {
return isMem() && getMemBase()->isMM16AsmReg();
@@ -1035,11 +1087,21 @@ public:
&& (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
&& (getMemBase()->getGPR32Reg() == Mips::SP);
}
+ template <unsigned Bits> bool isMemWithSimmWordAlignedOffsetGP() const {
+ return isMem() && isConstantMemOff() && isInt<Bits>(getConstantMemOff())
+ && (getConstantMemOff() % 4 == 0) && getMemBase()->isRegIdx()
+ && (getMemBase()->getGPR32Reg() == Mips::GP);
+ }
template <unsigned Bits, unsigned ShiftLeftAmount>
bool isScaledUImm() const {
return isConstantImm() &&
isShiftedUInt<Bits, ShiftLeftAmount>(getConstantImm());
}
+ template <unsigned Bits, unsigned ShiftLeftAmount>
+ bool isScaledSImm() const {
+ return isConstantImm() &&
+ isShiftedInt<Bits, ShiftLeftAmount>(getConstantImm());
+ }
bool isRegList16() const {
if (!isRegList())
return false;
@@ -1086,7 +1148,15 @@ public:
(R0 == Mips::A0 && R1 == Mips::S6) ||
(R0 == Mips::A0 && R1 == Mips::A1) ||
(R0 == Mips::A0 && R1 == Mips::A2) ||
- (R0 == Mips::A0 && R1 == Mips::A3))
+ (R0 == Mips::A0 && R1 == Mips::A3) ||
+ (R0 == Mips::A1_64 && R1 == Mips::A2_64) ||
+ (R0 == Mips::A1_64 && R1 == Mips::A3_64) ||
+ (R0 == Mips::A2_64 && R1 == Mips::A3_64) ||
+ (R0 == Mips::A0_64 && R1 == Mips::S5_64) ||
+ (R0 == Mips::A0_64 && R1 == Mips::S6_64) ||
+ (R0 == Mips::A0_64 && R1 == Mips::A1_64) ||
+ (R0 == Mips::A0_64 && R1 == Mips::A2_64) ||
+ (R0 == Mips::A0_64 && R1 == Mips::A3_64))
return true;
return false;
@@ -1096,17 +1166,19 @@ public:
assert(Kind == k_Token && "Invalid access!");
return StringRef(Tok.Data, Tok.Length);
}
- bool isRegPair() const { return Kind == k_RegPair; }
+ bool isRegPair() const {
+ return Kind == k_RegPair && RegIdx.Index <= 30;
+ }
unsigned getReg() const override {
- // As a special case until we sort out the definition of div/divu, pretend
- // that $0/$zero are k_PhysRegister so that MCK_ZERO works correctly.
+ // As a special case until we sort out the definition of div/divu, accept
+ // $0/$zero here so that MCK_ZERO works correctly.
if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
RegIdx.Kind & RegKind_GPR)
return getGPR32Reg(); // FIXME: GPR64 too
- assert(Kind == k_PhysRegister && "Invalid access!");
- return PhysReg.Num;
+ llvm_unreachable("Invalid access!");
+ return 0;
}
const MCExpr *getImm() const {
@@ -1250,10 +1322,13 @@ public:
return Op;
}
- static std::unique_ptr<MipsOperand>
- CreateRegPair(unsigned RegNo, SMLoc S, SMLoc E, MipsAsmParser &Parser) {
+ static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
+ SMLoc S, SMLoc E,
+ MipsAsmParser &Parser) {
auto Op = make_unique<MipsOperand>(k_RegPair, Parser);
- Op->RegIdx.Index = RegNo;
+ Op->RegIdx.Index = MOP.RegIdx.Index;
+ Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo;
+ Op->RegIdx.Kind = MOP.RegIdx.Kind;
Op->StartLoc = S;
Op->EndLoc = E;
return Op;
@@ -1331,7 +1406,6 @@ public:
break;
case k_RegList:
delete RegList.List;
- case k_PhysRegister:
case k_RegisterIndex:
case k_Token:
case k_RegPair:
@@ -1353,9 +1427,6 @@ public:
OS << *Mem.Off;
OS << ">";
break;
- case k_PhysRegister:
- OS << "PhysReg<" << PhysReg.Num << ">";
- break;
case k_RegisterIndex:
OS << "RegIdx<" << RegIdx.Index << ":" << RegIdx.Kind << ">";
break;
@@ -1434,83 +1505,10 @@ static unsigned countMCSymbolRefExpr(const MCExpr *Expr) {
return 0;
}
-namespace {
-void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
- MCInst tmpInst;
- tmpInst.setOpcode(Opcode);
- tmpInst.addOperand(MCOperand::createReg(Reg0));
- tmpInst.addOperand(Op1);
- tmpInst.setLoc(IDLoc);
- Instructions.push_back(tmpInst);
-}
-
-void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
- emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, Instructions);
-}
-
-void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
- emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, Instructions);
-}
-
-void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
- MCInst tmpInst;
- tmpInst.setOpcode(Opcode);
- tmpInst.addOperand(MCOperand::createImm(Imm1));
- tmpInst.addOperand(MCOperand::createImm(Imm2));
- tmpInst.setLoc(IDLoc);
- Instructions.push_back(tmpInst);
-}
-
-void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
- MCInst tmpInst;
- tmpInst.setOpcode(Opcode);
- tmpInst.addOperand(MCOperand::createReg(Reg0));
- tmpInst.setLoc(IDLoc);
- Instructions.push_back(tmpInst);
-}
-
-void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
- SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
- MCInst tmpInst;
- tmpInst.setOpcode(Opcode);
- tmpInst.addOperand(MCOperand::createReg(Reg0));
- tmpInst.addOperand(MCOperand::createReg(Reg1));
- tmpInst.addOperand(Op2);
- tmpInst.setLoc(IDLoc);
- Instructions.push_back(tmpInst);
-}
-
-void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
- SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
- emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc,
- Instructions);
-}
-
-void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
- SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
- emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc,
- Instructions);
-}
-
-void emitAppropriateDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
- SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
- if (ShiftAmount >= 32) {
- emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc,
- Instructions);
- return;
- }
-
- emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, Instructions);
-}
-} // end anonymous namespace.
-
bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
+ MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
bool ExpandedJalSym = false;
@@ -1560,6 +1558,10 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
case Mips::BLTZAL_MM:
case Mips::BC1F_MM:
case Mips::BC1T_MM:
+ case Mips::BC1EQZC_MMR6:
+ case Mips::BC1NEZC_MMR6:
+ case Mips::BC2EQZC_MMR6:
+ case Mips::BC2NEZC_MMR6:
assert(MCID.getNumOperands() == 2 && "unexpected number of operands");
Offset = Inst.getOperand(1);
if (!Offset.isImm())
@@ -1650,9 +1652,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
return Error(IDLoc, "jal doesn't support multiple symbols in PIC mode");
// FIXME: This is checking the expression can be handled by the later stages
- // of the assembler. We ought to leave it to those later stages but
- // we can't do that until we stop evaluateRelocExpr() rewriting the
- // expressions into non-equivalent forms.
+ // of the assembler. We ought to leave it to those later stages.
const MCSymbol *JalSym = getSingleMCSymbol(JalExpr);
// FIXME: Add support for label+offset operands (currently causes an error).
@@ -1666,33 +1666,38 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
// addiu $25, $25, 0
// R_(MICRO)MIPS_LO16 label
// jalr $25
- const MCExpr *Got16RelocExpr = evaluateRelocExpr(JalExpr, "got");
- const MCExpr *Lo16RelocExpr = evaluateRelocExpr(JalExpr, "lo");
-
- emitRRX(Mips::LW, Mips::T9, Mips::GP,
- MCOperand::createExpr(Got16RelocExpr), IDLoc, Instructions);
- emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
- MCOperand::createExpr(Lo16RelocExpr), IDLoc, Instructions);
+ const MCExpr *Got16RelocExpr =
+ MipsMCExpr::create(MipsMCExpr::MEK_GOT, JalExpr, getContext());
+ const MCExpr *Lo16RelocExpr =
+ MipsMCExpr::create(MipsMCExpr::MEK_LO, JalExpr, getContext());
+
+ TOut.emitRRX(Mips::LW, Mips::T9, Mips::GP,
+ MCOperand::createExpr(Got16RelocExpr), IDLoc, STI);
+ TOut.emitRRX(Mips::ADDiu, Mips::T9, Mips::T9,
+ MCOperand::createExpr(Lo16RelocExpr), IDLoc, STI);
} else if (isABI_N32() || isABI_N64()) {
// If it's a local symbol and the N32/N64 ABIs are being used,
// we expand to:
// lw/ld $25, 0($gp)
// R_(MICRO)MIPS_GOT_DISP label
// jalr $25
- const MCExpr *GotDispRelocExpr = evaluateRelocExpr(JalExpr, "got_disp");
+ const MCExpr *GotDispRelocExpr =
+ MipsMCExpr::create(MipsMCExpr::MEK_GOT_DISP, JalExpr, getContext());
- emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
- MCOperand::createExpr(GotDispRelocExpr), IDLoc, Instructions);
+ TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9,
+ Mips::GP, MCOperand::createExpr(GotDispRelocExpr), IDLoc,
+ STI);
}
} else {
// If it's an external/weak symbol, we expand to:
// lw/ld $25, 0($gp)
// R_(MICRO)MIPS_CALL16 label
// jalr $25
- const MCExpr *Call16RelocExpr = evaluateRelocExpr(JalExpr, "call16");
+ const MCExpr *Call16RelocExpr =
+ MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, JalExpr, getContext());
- emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
- MCOperand::createExpr(Call16RelocExpr), IDLoc, Instructions);
+ TOut.emitRRX(ABI.ArePtrs64bit() ? Mips::LD : Mips::LW, Mips::T9, Mips::GP,
+ MCOperand::createExpr(Call16RelocExpr), IDLoc, STI);
}
MCInst JalrInst;
@@ -1723,7 +1728,7 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
int MemOffset = Op.getImm();
if (MemOffset < -32768 || MemOffset > 32767) {
// Offset can't exceed 16bit value.
- expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
+ expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), true);
return false;
}
} else if (Op.isExpr()) {
@@ -1733,11 +1738,11 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
static_cast<const MCSymbolRefExpr *>(Expr);
if (SR->getKind() == MCSymbolRefExpr::VK_None) {
// Expand symbol.
- expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
+ expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
return false;
}
} else if (!isEvaluated(Expr)) {
- expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
+ expandMemInst(Inst, IDLoc, Out, STI, MCID.mayLoad(), false);
return false;
}
}
@@ -1763,8 +1768,8 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
(BaseReg.getReg() == Mips::GP ||
BaseReg.getReg() == Mips::GP_64)) {
- emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
- IDLoc, Instructions);
+ TOut.emitRRI(Mips::LWGP_MM, DstReg.getReg(), Mips::GP, MemOffset,
+ IDLoc, STI);
return false;
}
}
@@ -1780,14 +1785,6 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
switch (Inst.getOpcode()) {
default:
break;
- case Mips::ADDIUS5_MM:
- Opnd = Inst.getOperand(2);
- if (!Opnd.isImm())
- return Error(IDLoc, "expected immediate operand kind");
- Imm = Opnd.getImm();
- if (Imm < -8 || Imm > 7)
- return Error(IDLoc, "immediate operand value out of range");
- break;
case Mips::ADDIUSP_MM:
Opnd = Inst.getOperand(0);
if (!Opnd.isImm())
@@ -1823,16 +1820,6 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
((Imm % 4 == 0) && Imm < 28 && Imm > 0)))
return Error(IDLoc, "immediate operand value out of range");
break;
- case Mips::ADDIUR1SP_MM:
- Opnd = Inst.getOperand(1);
- if (!Opnd.isImm())
- return Error(IDLoc, "expected immediate operand kind");
- Imm = Opnd.getImm();
- if (OffsetToAlignment(Imm, 4LL))
- return Error(IDLoc, "misaligned immediate operand value");
- if (Imm < 0 || Imm > 255)
- return Error(IDLoc, "immediate operand value out of range");
- break;
case Mips::ANDI16_MM:
Opnd = Inst.getOperand(2);
if (!Opnd.isImm())
@@ -1851,12 +1838,6 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
if (Imm < -1 || Imm > 14)
return Error(IDLoc, "immediate operand value out of range");
break;
- case Mips::TEQ_MM:
- case Mips::TGE_MM:
- case Mips::TGEU_MM:
- case Mips::TLT_MM:
- case Mips::TLTU_MM:
- case Mips::TNE_MM:
case Mips::SB16_MM:
case Mips::SB16_MMR6:
Opnd = Inst.getOperand(2);
@@ -1897,11 +1878,16 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
}
}
+ bool FillDelaySlot =
+ MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder();
+ if (FillDelaySlot)
+ TOut.emitDirectiveSetNoReorder();
+
MacroExpanderResultTy ExpandResult =
- tryExpandInstruction(Inst, IDLoc, Instructions);
+ tryExpandInstruction(Inst, IDLoc, Out, STI);
switch (ExpandResult) {
case MER_NotAMacro:
- Instructions.push_back(Inst);
+ Out.EmitInstruction(Inst, *STI);
break;
case MER_Success:
break;
@@ -1909,10 +1895,17 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
return true;
}
+ // We know we emitted an instruction on the MER_NotAMacro or MER_Success path.
+ // If we're in microMIPS mode then we must also set EF_MIPS_MICROMIPS.
+ if (inMicroMipsMode())
+ TOut.setUsesMicroMips();
+
// If this instruction has a delay slot and .set reorder is active,
// emit a NOP after it.
- if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
- createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
+ if (FillDelaySlot) {
+ TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc, STI);
+ TOut.emitDirectiveSetReorder();
+ }
if ((Inst.getOpcode() == Mips::JalOneReg ||
Inst.getOpcode() == Mips::JalTwoReg || ExpandedJalSym) &&
@@ -1922,16 +1915,11 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
// If .set reorder has been used, we've already emitted a NOP.
// If .set noreorder has been used, we need to emit a NOP at this point.
if (!AssemblerOptions.back()->isReorder())
- createNop(hasShortDelaySlot(Inst.getOpcode()), IDLoc, Instructions);
+ TOut.emitEmptyDelaySlot(hasShortDelaySlot(Inst.getOpcode()), IDLoc,
+ STI);
// Load the $gp from the stack.
- SmallVector<MCInst, 3> LoadInsts;
- createCpRestoreMemOp(true /*IsLoad*/, CpRestoreOffset /*StackOffset*/,
- IDLoc, LoadInsts);
-
- for (const MCInst &Inst : LoadInsts)
- Instructions.push_back(Inst);
-
+ TOut.emitGPRestore(CpRestoreOffset, IDLoc, STI);
} else
Warning(IDLoc, "no .cprestore used in PIC mode");
}
@@ -1940,17 +1928,15 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
}
MipsAsmParser::MacroExpanderResultTy
-MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
+MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
switch (Inst.getOpcode()) {
default:
return MER_NotAMacro;
case Mips::LoadImm32:
- return expandLoadImm(Inst, true, IDLoc, Instructions) ? MER_Fail
- : MER_Success;
+ return expandLoadImm(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::LoadImm64:
- return expandLoadImm(Inst, false, IDLoc, Instructions) ? MER_Fail
- : MER_Success;
+ return expandLoadImm(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::LoadAddrImm32:
case Mips::LoadAddrImm64:
assert(Inst.getOperand(0).isReg() && "expected register operand kind");
@@ -1960,7 +1946,7 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
return expandLoadAddress(Inst.getOperand(0).getReg(), Mips::NoRegister,
Inst.getOperand(1),
Inst.getOpcode() == Mips::LoadAddrImm32, IDLoc,
- Instructions)
+ Out, STI)
? MER_Fail
: MER_Success;
case Mips::LoadAddrReg32:
@@ -1973,24 +1959,23 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
return expandLoadAddress(Inst.getOperand(0).getReg(),
Inst.getOperand(1).getReg(), Inst.getOperand(2),
Inst.getOpcode() == Mips::LoadAddrReg32, IDLoc,
- Instructions)
+ Out, STI)
? MER_Fail
: MER_Success;
case Mips::B_MM_Pseudo:
case Mips::B_MMR6_Pseudo:
- return expandUncondBranchMMPseudo(Inst, IDLoc, Instructions) ? MER_Fail
- : MER_Success;
+ return expandUncondBranchMMPseudo(Inst, IDLoc, Out, STI) ? MER_Fail
+ : MER_Success;
case Mips::SWM_MM:
case Mips::LWM_MM:
- return expandLoadStoreMultiple(Inst, IDLoc, Instructions) ? MER_Fail
- : MER_Success;
+ return expandLoadStoreMultiple(Inst, IDLoc, Out, STI) ? MER_Fail
+ : MER_Success;
case Mips::JalOneReg:
case Mips::JalTwoReg:
- return expandJalWithRegs(Inst, IDLoc, Instructions) ? MER_Fail
- : MER_Success;
+ return expandJalWithRegs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::BneImm:
case Mips::BeqImm:
- return expandBranchImm(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
+ return expandBranchImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::BLT:
case Mips::BLE:
case Mips::BGE:
@@ -2023,29 +2008,36 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
case Mips::BLEULImmMacro:
case Mips::BGEULImmMacro:
case Mips::BGTULImmMacro:
- return expandCondBranches(Inst, IDLoc, Instructions) ? MER_Fail
- : MER_Success;
+ return expandCondBranches(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::SDivMacro:
- return expandDiv(Inst, IDLoc, Instructions, false, true) ? MER_Fail
- : MER_Success;
+ return expandDiv(Inst, IDLoc, Out, STI, false, true) ? MER_Fail
+ : MER_Success;
case Mips::DSDivMacro:
- return expandDiv(Inst, IDLoc, Instructions, true, true) ? MER_Fail
- : MER_Success;
+ return expandDiv(Inst, IDLoc, Out, STI, true, true) ? MER_Fail
+ : MER_Success;
case Mips::UDivMacro:
- return expandDiv(Inst, IDLoc, Instructions, false, false) ? MER_Fail
- : MER_Success;
+ return expandDiv(Inst, IDLoc, Out, STI, false, false) ? MER_Fail
+ : MER_Success;
case Mips::DUDivMacro:
- return expandDiv(Inst, IDLoc, Instructions, true, false) ? MER_Fail
- : MER_Success;
+ return expandDiv(Inst, IDLoc, Out, STI, true, false) ? MER_Fail
+ : MER_Success;
+ case Mips::PseudoTRUNC_W_S:
+ return expandTrunc(Inst, false, false, IDLoc, Out, STI) ? MER_Fail
+ : MER_Success;
+ case Mips::PseudoTRUNC_W_D32:
+ return expandTrunc(Inst, true, false, IDLoc, Out, STI) ? MER_Fail
+ : MER_Success;
+ case Mips::PseudoTRUNC_W_D:
+ return expandTrunc(Inst, true, true, IDLoc, Out, STI) ? MER_Fail
+ : MER_Success;
case Mips::Ulh:
- return expandUlh(Inst, true, IDLoc, Instructions) ? MER_Fail : MER_Success;
+ return expandUlh(Inst, true, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::Ulhu:
- return expandUlh(Inst, false, IDLoc, Instructions) ? MER_Fail : MER_Success;
+ return expandUlh(Inst, false, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::Ulw:
- return expandUlw(Inst, IDLoc, Instructions) ? MER_Fail : MER_Success;
+ return expandUlw(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::NORImm:
- return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
- : MER_Success;
+ return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::ADDi:
case Mips::ADDiu:
case Mips::SLTi:
@@ -2055,8 +2047,8 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
int64_t ImmValue = Inst.getOperand(2).getImm();
if (isInt<16>(ImmValue))
return MER_NotAMacro;
- return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
- : MER_Success;
+ return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
+ : MER_Success;
}
return MER_NotAMacro;
case Mips::ANDi:
@@ -2067,31 +2059,32 @@ MipsAsmParser::tryExpandInstruction(MCInst &Inst, SMLoc IDLoc,
int64_t ImmValue = Inst.getOperand(2).getImm();
if (isUInt<16>(ImmValue))
return MER_NotAMacro;
- return expandAliasImmediate(Inst, IDLoc, Instructions) ? MER_Fail
- : MER_Success;
+ return expandAliasImmediate(Inst, IDLoc, Out, STI) ? MER_Fail
+ : MER_Success;
}
return MER_NotAMacro;
case Mips::ROL:
case Mips::ROR:
- return expandRotation(Inst, IDLoc, Instructions) ? MER_Fail
- : MER_Success;
+ return expandRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::ROLImm:
case Mips::RORImm:
- return expandRotationImm(Inst, IDLoc, Instructions) ? MER_Fail
- : MER_Success;
+ return expandRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::DROL:
case Mips::DROR:
- return expandDRotation(Inst, IDLoc, Instructions) ? MER_Fail
- : MER_Success;
+ return expandDRotation(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
case Mips::DROLImm:
case Mips::DRORImm:
- return expandDRotationImm(Inst, IDLoc, Instructions) ? MER_Fail
- : MER_Success;
+ return expandDRotationImm(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
+ case Mips::ABSMacro:
+ return expandAbs(Inst, IDLoc, Out, STI) ? MER_Fail : MER_Success;
}
}
bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
+ MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
+
// Create a JALR instruction which is going to replace the pseudo-JAL.
MCInst JalrInst;
JalrInst.setLoc(IDLoc);
@@ -2121,14 +2114,14 @@ bool MipsAsmParser::expandJalWithRegs(MCInst &Inst, SMLoc IDLoc,
const MCOperand SecondRegOp = Inst.getOperand(1);
JalrInst.addOperand(SecondRegOp);
}
- Instructions.push_back(JalrInst);
+ Out.EmitInstruction(JalrInst, *STI);
// If .set reorder is active and branch instruction has a delay slot,
// emit a NOP after it.
const MCInstrDesc &MCID = getInstDesc(JalrInst.getOpcode());
- if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder()) {
- createNop(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc, Instructions);
- }
+ if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
+ TOut.emitEmptyDelaySlot(hasShortDelaySlot(JalrInst.getOpcode()), IDLoc,
+ STI);
return false;
}
@@ -2150,11 +2143,12 @@ template <unsigned N> static bool isShiftedUIntAtAnyPosition(uint64_t x) {
/// @param IsAddress True if the immediate represents an address. False if it
/// is an integer.
/// @param IDLoc Location of the immediate in the source file.
-/// @param Instructions The instructions emitted by this expansion.
bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
unsigned SrcReg, bool Is32BitImm,
- bool IsAddress, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
+ bool IsAddress, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
+
if (!Is32BitImm && !isGP64bit()) {
Error(IDLoc, "instruction requires a 64-bit architecture");
return true;
@@ -2180,7 +2174,8 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
UseSrcReg = true;
unsigned TmpReg = DstReg;
- if (UseSrcReg && (DstReg == SrcReg)) {
+ if (UseSrcReg &&
+ getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
// At this point we need AT to perform the expansions and we exit if it is
// not available.
unsigned ATReg = getATReg(IDLoc);
@@ -2197,11 +2192,11 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
// traditional assembler behaviour. N32 would normally use addiu for both
// integers and addresses.
if (IsAddress && !Is32BitImm) {
- emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
+ TOut.emitRRI(Mips::DADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
return false;
}
- emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, Instructions);
+ TOut.emitRRI(Mips::ADDiu, DstReg, SrcReg, ImmValue, IDLoc, STI);
return false;
}
@@ -2213,9 +2208,9 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
return true;
}
- emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, Instructions);
+ TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, ImmValue, IDLoc, STI);
if (UseSrcReg)
- emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, Instructions);
+ TOut.emitRRR(ABI.GetPtrAdduOp(), DstReg, TmpReg, SrcReg, IDLoc, STI);
return false;
}
@@ -2229,29 +2224,29 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
// Traditional behaviour seems to special case this particular value. It's
// not clear why other masks are handled differently.
if (ImmValue == 0xffffffff) {
- emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, Instructions);
- emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, Instructions);
+ TOut.emitRI(Mips::LUi, TmpReg, 0xffff, IDLoc, STI);
+ TOut.emitRRI(Mips::DSRL32, TmpReg, TmpReg, 0, IDLoc, STI);
if (UseSrcReg)
- emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
+ TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
return false;
}
// Expand to an ORi instead of a LUi to avoid sign-extending into the
// upper 32 bits.
- emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, Instructions);
- emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, Instructions);
+ TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits31To16, IDLoc, STI);
+ TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, 16, IDLoc, STI);
if (Bits15To0)
- emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
+ TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
if (UseSrcReg)
- emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
+ TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
return false;
}
- emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, Instructions);
+ TOut.emitRI(Mips::LUi, TmpReg, Bits31To16, IDLoc, STI);
if (Bits15To0)
- emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, Instructions);
+ TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, Bits15To0, IDLoc, STI);
if (UseSrcReg)
- emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
+ TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
return false;
}
@@ -2267,11 +2262,11 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
unsigned LastSet = findLastSet((uint64_t)ImmValue);
unsigned ShiftAmount = FirstSet - (15 - (LastSet - FirstSet));
uint16_t Bits = (ImmValue >> ShiftAmount) & 0xffff;
- emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, Instructions);
- emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, Instructions);
+ TOut.emitRRI(Mips::ORi, TmpReg, ZeroReg, Bits, IDLoc, STI);
+ TOut.emitRRI(Mips::DSLL, TmpReg, TmpReg, ShiftAmount, IDLoc, STI);
if (UseSrcReg)
- emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
+ TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
return false;
}
@@ -2284,7 +2279,7 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
// Load bits 32-63 of ImmValue into bits 0-31 of the temporary register.
if (loadImmediate(ImmValue >> 32, TmpReg, Mips::NoRegister, true, false,
- IDLoc, Instructions))
+ IDLoc, Out, STI))
return false;
// Shift and accumulate into the register. If a 16-bit chunk is zero, then
@@ -2294,9 +2289,8 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
uint16_t ImmChunk = (ImmValue >> BitNum) & 0xffff;
if (ImmChunk != 0) {
- emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
- Instructions);
- emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, Instructions);
+ TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
+ TOut.emitRRI(Mips::ORi, TmpReg, TmpReg, ImmChunk, IDLoc, STI);
ShiftCarriedForwards = 0;
}
@@ -2306,24 +2300,23 @@ bool MipsAsmParser::loadImmediate(int64_t ImmValue, unsigned DstReg,
// Finish any remaining shifts left by trailing zeros.
if (ShiftCarriedForwards)
- emitAppropriateDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc,
- Instructions);
+ TOut.emitDSLL(TmpReg, TmpReg, ShiftCarriedForwards, IDLoc, STI);
if (UseSrcReg)
- emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
+ TOut.emitRRR(AdduOp, DstReg, TmpReg, SrcReg, IDLoc, STI);
return false;
}
bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
+ MCStreamer &Out, const MCSubtargetInfo *STI) {
const MCOperand &ImmOp = Inst.getOperand(1);
assert(ImmOp.isImm() && "expected immediate operand kind");
const MCOperand &DstRegOp = Inst.getOperand(0);
assert(DstRegOp.isReg() && "expected register operand kind");
if (loadImmediate(ImmOp.getImm(), DstRegOp.getReg(), Mips::NoRegister,
- Is32BitImm, false, IDLoc, Instructions))
+ Is32BitImm, false, IDLoc, Out, STI))
return true;
return false;
@@ -2332,7 +2325,8 @@ bool MipsAsmParser::expandLoadImm(MCInst &Inst, bool Is32BitImm, SMLoc IDLoc,
bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
const MCOperand &Offset,
bool Is32BitAddress, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
+ MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
// la can't produce a usable address when addresses are 64-bit.
if (Is32BitAddress && ABI.ArePtrs64bit()) {
// FIXME: Demote this to a warning and continue as if we had 'dla' instead.
@@ -2344,31 +2338,109 @@ bool MipsAsmParser::expandLoadAddress(unsigned DstReg, unsigned BaseReg,
}
// dla requires 64-bit addresses.
- if (!Is32BitAddress && !ABI.ArePtrs64bit()) {
+ if (!Is32BitAddress && !hasMips3()) {
Error(IDLoc, "instruction requires a 64-bit architecture");
return true;
}
if (!Offset.isImm())
return loadAndAddSymbolAddress(Offset.getExpr(), DstReg, BaseReg,
- Is32BitAddress, IDLoc, Instructions);
+ Is32BitAddress, IDLoc, Out, STI);
+
+ if (!ABI.ArePtrs64bit()) {
+ // Continue as if we had 'la' whether we had 'la' or 'dla'.
+ Is32BitAddress = true;
+ }
return loadImmediate(Offset.getImm(), DstReg, BaseReg, Is32BitAddress, true,
- IDLoc, Instructions);
+ IDLoc, Out, STI);
}
-bool MipsAsmParser::loadAndAddSymbolAddress(
- const MCExpr *SymExpr, unsigned DstReg, unsigned SrcReg, bool Is32BitSym,
- SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
+bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
+ unsigned DstReg, unsigned SrcReg,
+ bool Is32BitSym, SMLoc IDLoc,
+ MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
+ bool UseSrcReg = SrcReg != Mips::NoRegister;
warnIfNoMacro(IDLoc);
- const MCExpr *Symbol = cast<MCExpr>(SymExpr);
- const MipsMCExpr *HiExpr = MipsMCExpr::create(
- MCSymbolRefExpr::VK_Mips_ABS_HI, Symbol, getContext());
- const MipsMCExpr *LoExpr = MipsMCExpr::create(
- MCSymbolRefExpr::VK_Mips_ABS_LO, Symbol, getContext());
+ if (inPicMode() && ABI.IsO32()) {
+ MCValue Res;
+ if (!SymExpr->evaluateAsRelocatable(Res, nullptr, nullptr)) {
+ Error(IDLoc, "expected relocatable expression");
+ return true;
+ }
+ if (Res.getSymB() != nullptr) {
+ Error(IDLoc, "expected relocatable expression with only one symbol");
+ return true;
+ }
+
+ // The case where the result register is $25 is somewhat special. If the
+ // symbol in the final relocation is external and not modified with a
+ // constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
+ if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
+ Res.getConstant() == 0 && !Res.getSymA()->getSymbol().isInSection() &&
+ !Res.getSymA()->getSymbol().isTemporary()) {
+ const MCExpr *CallExpr =
+ MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
+ TOut.emitRRX(Mips::LW, DstReg, ABI.GetGlobalPtr(),
+ MCOperand::createExpr(CallExpr), IDLoc, STI);
+ return false;
+ }
- bool UseSrcReg = SrcReg != Mips::NoRegister;
+ // The remaining cases are:
+ // External GOT: lw $tmp, %got(symbol+offset)($gp)
+ // >addiu $tmp, $tmp, %lo(offset)
+ // >addiu $rd, $tmp, $rs
+ // Local GOT: lw $tmp, %got(symbol+offset)($gp)
+ // addiu $tmp, $tmp, %lo(symbol+offset)($gp)
+ // >addiu $rd, $tmp, $rs
+ // The addiu's marked with a '>' may be omitted if they are redundant. If
+ // this happens then the last instruction must use $rd as the result
+ // register.
+ const MipsMCExpr *GotExpr =
+ MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
+ const MCExpr *LoExpr = nullptr;
+ if (Res.getSymA()->getSymbol().isInSection() ||
+ Res.getSymA()->getSymbol().isTemporary())
+ LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
+ else if (Res.getConstant() != 0) {
+ // External symbols fully resolve the symbol with just the %got(symbol)
+ // but we must still account for any offset to the symbol for expressions
+ // like symbol+8.
+ LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
+ }
+
+ unsigned TmpReg = DstReg;
+ if (UseSrcReg &&
+ getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
+ SrcReg)) {
+ // If $rs is the same as $rd, we need to use AT.
+ // If it is not available we exit.
+ unsigned ATReg = getATReg(IDLoc);
+ if (!ATReg)
+ return true;
+ TmpReg = ATReg;
+ }
+
+ TOut.emitRRX(Mips::LW, TmpReg, ABI.GetGlobalPtr(),
+ MCOperand::createExpr(GotExpr), IDLoc, STI);
+
+ if (LoExpr)
+ TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
+ IDLoc, STI);
+
+ if (UseSrcReg)
+ TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
+
+ return false;
+ }
+
+ const MipsMCExpr *HiExpr =
+ MipsMCExpr::create(MipsMCExpr::MEK_HI, SymExpr, getContext());
+ const MipsMCExpr *LoExpr =
+ MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
// This is the 64-bit symbol address expansion.
if (ABI.ArePtrs64bit() && isGP64bit()) {
@@ -2378,12 +2450,14 @@ bool MipsAsmParser::loadAndAddSymbolAddress(
if (!ATReg)
return true;
- const MipsMCExpr *HighestExpr = MipsMCExpr::create(
- MCSymbolRefExpr::VK_Mips_HIGHEST, Symbol, getContext());
- const MipsMCExpr *HigherExpr = MipsMCExpr::create(
- MCSymbolRefExpr::VK_Mips_HIGHER, Symbol, getContext());
+ const MipsMCExpr *HighestExpr =
+ MipsMCExpr::create(MipsMCExpr::MEK_HIGHEST, SymExpr, getContext());
+ const MipsMCExpr *HigherExpr =
+ MipsMCExpr::create(MipsMCExpr::MEK_HIGHER, SymExpr, getContext());
- if (UseSrcReg && (DstReg == SrcReg)) {
+ if (UseSrcReg &&
+ getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg,
+ SrcReg)) {
// If $rs is the same as $rd:
// (d)la $rd, sym($rd) => lui $at, %highest(sym)
// daddiu $at, $at, %higher(sym)
@@ -2392,17 +2466,17 @@ bool MipsAsmParser::loadAndAddSymbolAddress(
// dsll $at, $at, 16
// daddiu $at, $at, %lo(sym)
// daddu $rd, $at, $rd
- emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
- Instructions);
- emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HigherExpr),
- IDLoc, Instructions);
- emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
- emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
- Instructions);
- emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, Instructions);
- emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
- Instructions);
- emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, Instructions);
+ TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HighestExpr), IDLoc,
+ STI);
+ TOut.emitRRX(Mips::DADDiu, ATReg, ATReg,
+ MCOperand::createExpr(HigherExpr), IDLoc, STI);
+ TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
+ TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(HiExpr),
+ IDLoc, STI);
+ TOut.emitRRI(Mips::DSLL, ATReg, ATReg, 16, IDLoc, STI);
+ TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
+ IDLoc, STI);
+ TOut.emitRRR(Mips::DADDu, DstReg, ATReg, SrcReg, IDLoc, STI);
return false;
}
@@ -2415,18 +2489,17 @@ bool MipsAsmParser::loadAndAddSymbolAddress(
// dsll32 $rd, $rd, 0
// daddu $rd, $rd, $at
// (daddu $rd, $rd, $rs)
- emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
- Instructions);
- emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc,
- Instructions);
- emitRRX(Mips::DADDiu, DstReg, DstReg, MCOperand::createExpr(HigherExpr),
- IDLoc, Instructions);
- emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr), IDLoc,
- Instructions);
- emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, Instructions);
- emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, Instructions);
+ TOut.emitRX(Mips::LUi, DstReg, MCOperand::createExpr(HighestExpr), IDLoc,
+ STI);
+ TOut.emitRX(Mips::LUi, ATReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
+ TOut.emitRRX(Mips::DADDiu, DstReg, DstReg,
+ MCOperand::createExpr(HigherExpr), IDLoc, STI);
+ TOut.emitRRX(Mips::DADDiu, ATReg, ATReg, MCOperand::createExpr(LoExpr),
+ IDLoc, STI);
+ TOut.emitRRI(Mips::DSLL32, DstReg, DstReg, 0, IDLoc, STI);
+ TOut.emitRRR(Mips::DADDu, DstReg, DstReg, ATReg, IDLoc, STI);
if (UseSrcReg)
- emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, Instructions);
+ TOut.emitRRR(Mips::DADDu, DstReg, DstReg, SrcReg, IDLoc, STI);
return false;
}
@@ -2441,7 +2514,8 @@ bool MipsAsmParser::loadAndAddSymbolAddress(
// ori $rd, $rd, %lo(sym)
// (addu $rd, $rd, $rs)
unsigned TmpReg = DstReg;
- if (UseSrcReg && (DstReg == SrcReg)) {
+ if (UseSrcReg &&
+ getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, SrcReg)) {
// If $rs is the same as $rd, we need to use AT.
// If it is not available we exit.
unsigned ATReg = getATReg(IDLoc);
@@ -2450,20 +2524,24 @@ bool MipsAsmParser::loadAndAddSymbolAddress(
TmpReg = ATReg;
}
- emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, Instructions);
- emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr), IDLoc,
- Instructions);
+ TOut.emitRX(Mips::LUi, TmpReg, MCOperand::createExpr(HiExpr), IDLoc, STI);
+ TOut.emitRRX(Mips::ADDiu, TmpReg, TmpReg, MCOperand::createExpr(LoExpr),
+ IDLoc, STI);
if (UseSrcReg)
- emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, Instructions);
+ TOut.emitRRR(Mips::ADDu, DstReg, TmpReg, SrcReg, IDLoc, STI);
else
- assert(DstReg == TmpReg);
+ assert(
+ getContext().getRegisterInfo()->isSuperOrSubRegisterEq(DstReg, TmpReg));
return false;
}
-bool MipsAsmParser::expandUncondBranchMMPseudo(
- MCInst &Inst, SMLoc IDLoc, SmallVectorImpl<MCInst> &Instructions) {
+bool MipsAsmParser::expandUncondBranchMMPseudo(MCInst &Inst, SMLoc IDLoc,
+ MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
+
assert(getInstDesc(Inst.getOpcode()).getNumOperands() == 1 &&
"unexpected number of operands");
@@ -2493,19 +2571,20 @@ bool MipsAsmParser::expandUncondBranchMMPseudo(
Inst.addOperand(MCOperand::createImm(Offset.getImm()));
}
}
- Instructions.push_back(Inst);
+ Out.EmitInstruction(Inst, *STI);
// If .set reorder is active and branch instruction has a delay slot,
// emit a NOP after it.
const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
if (MCID.hasDelaySlot() && AssemblerOptions.back()->isReorder())
- createNop(true, IDLoc, Instructions);
+ TOut.emitEmptyDelaySlot(true, IDLoc, STI);
return false;
}
-bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
+bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
const MCOperand &DstRegOp = Inst.getOperand(0);
assert(DstRegOp.isReg() && "expected register operand kind");
@@ -2513,7 +2592,8 @@ bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
assert(ImmOp.isImm() && "expected immediate operand kind");
const MCOperand &MemOffsetOp = Inst.getOperand(2);
- assert(MemOffsetOp.isImm() && "expected immediate operand kind");
+ assert((MemOffsetOp.isImm() || MemOffsetOp.isExpr()) &&
+ "expected immediate or expression operand");
unsigned OpCode = 0;
switch(Inst.getOpcode()) {
@@ -2530,8 +2610,8 @@ bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
int64_t ImmValue = ImmOp.getImm();
if (ImmValue == 0)
- emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
- Instructions);
+ TOut.emitRRX(OpCode, DstRegOp.getReg(), Mips::ZERO, MemOffsetOp, IDLoc,
+ STI);
else {
warnIfNoMacro(IDLoc);
@@ -2540,94 +2620,112 @@ bool MipsAsmParser::expandBranchImm(MCInst &Inst, SMLoc IDLoc,
return true;
if (loadImmediate(ImmValue, ATReg, Mips::NoRegister, !isGP64bit(), true,
- IDLoc, Instructions))
+ IDLoc, Out, STI))
return true;
- emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, Instructions);
+ TOut.emitRRX(OpCode, DstRegOp.getReg(), ATReg, MemOffsetOp, IDLoc, STI);
}
return false;
}
-void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions,
- bool isLoad, bool isImmOpnd) {
- unsigned ImmOffset, HiOffset, LoOffset;
- const MCExpr *ExprOffset;
- unsigned TmpRegNum;
- // 1st operand is either the source or destination register.
- assert(Inst.getOperand(0).isReg() && "expected register operand kind");
- unsigned RegOpNum = Inst.getOperand(0).getReg();
- // 2nd operand is the base register.
- assert(Inst.getOperand(1).isReg() && "expected register operand kind");
- unsigned BaseRegNum = Inst.getOperand(1).getReg();
- // 3rd operand is either an immediate or expression.
- if (isImmOpnd) {
- assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
- ImmOffset = Inst.getOperand(2).getImm();
- LoOffset = ImmOffset & 0x0000ffff;
- HiOffset = (ImmOffset & 0xffff0000) >> 16;
- // If msb of LoOffset is 1(negative number) we must increment HiOffset.
- if (LoOffset & 0x8000)
- HiOffset++;
- } else
- ExprOffset = Inst.getOperand(2).getExpr();
- // These are some of the types of expansions we perform here:
- // 1) lw $8, sym => lui $8, %hi(sym)
- // lw $8, %lo(sym)($8)
- // 2) lw $8, offset($9) => lui $8, %hi(offset)
- // add $8, $8, $9
- // lw $8, %lo(offset)($9)
- // 3) lw $8, offset($8) => lui $at, %hi(offset)
- // add $at, $at, $8
- // lw $8, %lo(offset)($at)
- // 4) sw $8, sym => lui $at, %hi(sym)
- // sw $8, %lo(sym)($at)
- // 5) sw $8, offset($8) => lui $at, %hi(offset)
- // add $at, $at, $8
- // sw $8, %lo(offset)($at)
- // 6) ldc1 $f0, sym => lui $at, %hi(sym)
- // ldc1 $f0, %lo(sym)($at)
- //
- // For load instructions we can use the destination register as a temporary
- // if base and dst are different (examples 1 and 2) and if the base register
- // is general purpose otherwise we must use $at (example 6) and error if it's
- // not available. For stores we must use $at (examples 4 and 5) because we
- // must not clobber the source register setting up the offset.
+void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI, bool IsLoad,
+ bool IsImmOpnd) {
+ if (IsLoad) {
+ expandLoadInst(Inst, IDLoc, Out, STI, IsImmOpnd);
+ return;
+ }
+ expandStoreInst(Inst, IDLoc, Out, STI, IsImmOpnd);
+}
+
+void MipsAsmParser::expandLoadInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI, bool IsImmOpnd) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
+
+ unsigned DstReg = Inst.getOperand(0).getReg();
+ unsigned BaseReg = Inst.getOperand(1).getReg();
+
const MCInstrDesc &Desc = getInstDesc(Inst.getOpcode());
- int16_t RegClassOp0 = Desc.OpInfo[0].RegClass;
- unsigned RegClassIDOp0 =
- getContext().getRegisterInfo()->getRegClass(RegClassOp0).getID();
- bool IsGPR = (RegClassIDOp0 == Mips::GPR32RegClassID) ||
- (RegClassIDOp0 == Mips::GPR64RegClassID);
- if (isLoad && IsGPR && (BaseRegNum != RegOpNum))
- TmpRegNum = RegOpNum;
- else {
+ int16_t DstRegClass = Desc.OpInfo[0].RegClass;
+ unsigned DstRegClassID =
+ getContext().getRegisterInfo()->getRegClass(DstRegClass).getID();
+ bool IsGPR = (DstRegClassID == Mips::GPR32RegClassID) ||
+ (DstRegClassID == Mips::GPR64RegClassID);
+
+ if (IsImmOpnd) {
+ // Try to use DstReg as the temporary.
+ if (IsGPR && (BaseReg != DstReg)) {
+ TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
+ Inst.getOperand(2).getImm(), DstReg, IDLoc,
+ STI);
+ return;
+ }
+
// At this point we need AT to perform the expansions and we exit if it is
// not available.
- TmpRegNum = getATReg(IDLoc);
- if (!TmpRegNum)
+ unsigned ATReg = getATReg(IDLoc);
+ if (!ATReg)
return;
+
+ TOut.emitLoadWithImmOffset(Inst.getOpcode(), DstReg, BaseReg,
+ Inst.getOperand(2).getImm(), ATReg, IDLoc, STI);
+ return;
}
- emitRX(Mips::LUi, TmpRegNum,
- isImmOpnd ? MCOperand::createImm(HiOffset)
- : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "hi")),
- IDLoc, Instructions);
- // Add temp register to base.
- if (BaseRegNum != Mips::ZERO)
- emitRRR(Mips::ADDu, TmpRegNum, TmpRegNum, BaseRegNum, IDLoc, Instructions);
- // And finally, create original instruction with low part
- // of offset and new base.
- emitRRX(Inst.getOpcode(), RegOpNum, TmpRegNum,
- isImmOpnd
- ? MCOperand::createImm(LoOffset)
- : MCOperand::createExpr(evaluateRelocExpr(ExprOffset, "lo")),
- IDLoc, Instructions);
+ const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
+ MCOperand LoOperand = MCOperand::createExpr(
+ MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
+ MCOperand HiOperand = MCOperand::createExpr(
+ MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
+
+ // Try to use DstReg as the temporary.
+ if (IsGPR && (BaseReg != DstReg)) {
+ TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
+ LoOperand, DstReg, IDLoc, STI);
+ return;
+ }
+
+ // At this point we need AT to perform the expansions and we exit if it is
+ // not available.
+ unsigned ATReg = getATReg(IDLoc);
+ if (!ATReg)
+ return;
+
+ TOut.emitLoadWithSymOffset(Inst.getOpcode(), DstReg, BaseReg, HiOperand,
+ LoOperand, ATReg, IDLoc, STI);
}
-bool
-MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
+void MipsAsmParser::expandStoreInst(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI,
+ bool IsImmOpnd) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
+
+ unsigned SrcReg = Inst.getOperand(0).getReg();
+ unsigned BaseReg = Inst.getOperand(1).getReg();
+
+ if (IsImmOpnd) {
+ TOut.emitStoreWithImmOffset(Inst.getOpcode(), SrcReg, BaseReg,
+ Inst.getOperand(2).getImm(),
+ [&]() { return getATReg(IDLoc); }, IDLoc, STI);
+ return;
+ }
+
+ unsigned ATReg = getATReg(IDLoc);
+ if (!ATReg)
+ return;
+
+ const MCExpr *ExprOffset = Inst.getOperand(2).getExpr();
+ MCOperand LoOperand = MCOperand::createExpr(
+ MipsMCExpr::create(MipsMCExpr::MEK_LO, ExprOffset, getContext()));
+ MCOperand HiOperand = MCOperand::createExpr(
+ MipsMCExpr::create(MipsMCExpr::MEK_HI, ExprOffset, getContext()));
+ TOut.emitStoreWithSymOffset(Inst.getOpcode(), SrcReg, BaseReg, HiOperand,
+ LoOperand, ATReg, IDLoc, STI);
+}
+
+bool MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
+ MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
unsigned OpNum = Inst.getNumOperands();
unsigned Opcode = Inst.getOpcode();
unsigned NewOpcode = Opcode == Mips::SWM_MM ? Mips::SWM32_MM : Mips::LWM32_MM;
@@ -2650,12 +2748,14 @@ MipsAsmParser::expandLoadStoreMultiple(MCInst &Inst, SMLoc IDLoc,
}
Inst.setOpcode(NewOpcode);
- Instructions.push_back(Inst);
+ Out.EmitInstruction(Inst, *STI);
return false;
}
bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
+ MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
bool EmittedNoMacroWarning = false;
unsigned PseudoOpcode = Inst.getOpcode();
unsigned SrcReg = Inst.getOperand(0).getReg();
@@ -2730,7 +2830,7 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
}
if (loadImmediate(TrgOp.getImm(), TrgReg, Mips::NoRegister, !isGP64bit(),
- false, IDLoc, Instructions))
+ false, IDLoc, Out, STI))
return true;
}
@@ -2790,37 +2890,37 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
// with GAS' behaviour. However, they may not generate the most efficient
// code in some circumstances.
if (PseudoOpcode == Mips::BLT) {
- emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
- Instructions);
+ TOut.emitRX(Mips::BLTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
+ IDLoc, STI);
return false;
}
if (PseudoOpcode == Mips::BLE) {
- emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
- Instructions);
+ TOut.emitRX(Mips::BLEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
+ IDLoc, STI);
Warning(IDLoc, "branch is always taken");
return false;
}
if (PseudoOpcode == Mips::BGE) {
- emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
- Instructions);
+ TOut.emitRX(Mips::BGEZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
+ IDLoc, STI);
Warning(IDLoc, "branch is always taken");
return false;
}
if (PseudoOpcode == Mips::BGT) {
- emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
- Instructions);
+ TOut.emitRX(Mips::BGTZ, Mips::ZERO, MCOperand::createExpr(OffsetExpr),
+ IDLoc, STI);
return false;
}
if (PseudoOpcode == Mips::BGTU) {
- emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
- MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
+ TOut.emitRRX(Mips::BNE, Mips::ZERO, Mips::ZERO,
+ MCOperand::createExpr(OffsetExpr), IDLoc, STI);
return false;
}
if (AcceptsEquality) {
// If both registers are $0 and the pseudo-branch accepts equality, it
// will always be taken, so we emit an unconditional branch.
- emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
- MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
+ TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
+ MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Warning(IDLoc, "branch is always taken");
return false;
}
@@ -2844,8 +2944,8 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
// the pseudo-branch will always be taken, so we emit an unconditional
// branch.
// This only applies to unsigned pseudo-branches.
- emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
- MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
+ TOut.emitRRX(Mips::BEQ, Mips::ZERO, Mips::ZERO,
+ MCOperand::createExpr(OffsetExpr), IDLoc, STI);
Warning(IDLoc, "branch is always taken");
return false;
}
@@ -2862,17 +2962,17 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
//
// Because only BLEU and BGEU branch on equality, we can use the
// AcceptsEquality variable to decide when to emit the BEQZ.
- emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
- IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
- MCOperand::createExpr(OffsetExpr), IDLoc, Instructions);
+ TOut.emitRRX(AcceptsEquality ? Mips::BEQ : Mips::BNE,
+ IsSrcRegZero ? TrgReg : SrcReg, Mips::ZERO,
+ MCOperand::createExpr(OffsetExpr), IDLoc, STI);
return false;
}
// If we have a signed pseudo-branch and one of the registers is $0,
// we can use an appropriate compare-to-zero branch. We select which one
// to use in the switch statement above.
- emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
- IsSrcRegZero ? TrgReg : SrcReg, MCOperand::createExpr(OffsetExpr),
- IDLoc, Instructions);
+ TOut.emitRX(IsSrcRegZero ? ZeroSrcOpcode : ZeroTrgOpcode,
+ IsSrcRegZero ? TrgReg : SrcReg,
+ MCOperand::createExpr(OffsetExpr), IDLoc, STI);
return false;
}
@@ -2900,32 +3000,33 @@ bool MipsAsmParser::expandCondBranches(MCInst &Inst, SMLoc IDLoc,
//
// The same applies to the unsigned variants, except that SLTu is used
// instead of SLT.
- emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
- ReverseOrderSLT ? TrgReg : SrcReg, ReverseOrderSLT ? SrcReg : TrgReg,
- IDLoc, Instructions);
-
- emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
- : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
- ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
- Instructions);
+ TOut.emitRRR(IsUnsigned ? Mips::SLTu : Mips::SLT, ATRegNum,
+ ReverseOrderSLT ? TrgReg : SrcReg,
+ ReverseOrderSLT ? SrcReg : TrgReg, IDLoc, STI);
+
+ TOut.emitRRX(IsLikely ? (AcceptsEquality ? Mips::BEQL : Mips::BNEL)
+ : (AcceptsEquality ? Mips::BEQ : Mips::BNE),
+ ATRegNum, Mips::ZERO, MCOperand::createExpr(OffsetExpr), IDLoc,
+ STI);
return false;
}
-bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions,
- const bool IsMips64, const bool Signed) {
- if (hasMips32r6()) {
- Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
- return false;
- }
+bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI, const bool IsMips64,
+ const bool Signed) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
warnIfNoMacro(IDLoc);
- const MCOperand &RsRegOp = Inst.getOperand(0);
+ const MCOperand &RdRegOp = Inst.getOperand(0);
+ assert(RdRegOp.isReg() && "expected register operand kind");
+ unsigned RdReg = RdRegOp.getReg();
+
+ const MCOperand &RsRegOp = Inst.getOperand(1);
assert(RsRegOp.isReg() && "expected register operand kind");
unsigned RsReg = RsRegOp.getReg();
- const MCOperand &RtRegOp = Inst.getOperand(1);
+ const MCOperand &RtRegOp = Inst.getOperand(2);
assert(RtRegOp.isReg() && "expected register operand kind");
unsigned RtReg = RtRegOp.getReg();
unsigned DivOp;
@@ -2947,15 +3048,15 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
if (IsMips64) {
if (Signed && (RtReg == Mips::ZERO || RtReg == Mips::ZERO_64)) {
if (UseTraps) {
- emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
+ TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
return false;
}
- emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
+ TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
return false;
}
} else {
- emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
+ TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
return false;
}
}
@@ -2964,11 +3065,11 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
Warning(IDLoc, "division by zero");
if (Signed) {
if (UseTraps) {
- emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
+ TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
return false;
}
- emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
+ TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
return false;
}
}
@@ -2980,22 +3081,21 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
if (UseTraps) {
BranchTarget = IsMips64 ? 12 : 8;
- emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, Instructions);
+ TOut.emitRRI(Mips::TEQ, RtReg, ZeroReg, 0x7, IDLoc, STI);
} else {
BranchTarget = IsMips64 ? 20 : 16;
BranchTargetNoTraps = 8;
// Branch to the li instruction.
- emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc,
- Instructions);
+ TOut.emitRRI(Mips::BNE, RtReg, ZeroReg, BranchTargetNoTraps, IDLoc, STI);
}
- emitRR(DivOp, RsReg, RtReg, IDLoc, Instructions);
+ TOut.emitRR(DivOp, RsReg, RtReg, IDLoc, STI);
if (!UseTraps)
- emitII(Mips::BREAK, 0x7, 0, IDLoc, Instructions);
+ TOut.emitII(Mips::BREAK, 0x7, 0, IDLoc, STI);
if (!Signed) {
- emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
+ TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
return false;
}
@@ -3003,32 +3103,73 @@ bool MipsAsmParser::expandDiv(MCInst &Inst, SMLoc IDLoc,
if (!ATReg)
return true;
- emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, Instructions);
+ TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, -1, IDLoc, STI);
if (IsMips64) {
// Branch to the mflo instruction.
- emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
- emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, Instructions);
- emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, Instructions);
+ TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
+ TOut.emitRRI(Mips::ADDiu, ATReg, ZeroReg, 1, IDLoc, STI);
+ TOut.emitRRI(Mips::DSLL32, ATReg, ATReg, 0x1f, IDLoc, STI);
} else {
// Branch to the mflo instruction.
- emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, Instructions);
- emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, Instructions);
+ TOut.emitRRI(Mips::BNE, RtReg, ATReg, BranchTarget, IDLoc, STI);
+ TOut.emitRI(Mips::LUi, ATReg, (uint16_t)0x8000, IDLoc, STI);
}
if (UseTraps)
- emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, Instructions);
+ TOut.emitRRI(Mips::TEQ, RsReg, ATReg, 0x6, IDLoc, STI);
else {
// Branch to the mflo instruction.
- emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, Instructions);
- emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, Instructions);
- emitII(Mips::BREAK, 0x6, 0, IDLoc, Instructions);
+ TOut.emitRRI(Mips::BNE, RsReg, ATReg, BranchTargetNoTraps, IDLoc, STI);
+ TOut.emitRRI(Mips::SLL, ZeroReg, ZeroReg, 0, IDLoc, STI);
+ TOut.emitII(Mips::BREAK, 0x6, 0, IDLoc, STI);
+ }
+ TOut.emitR(Mips::MFLO, RdReg, IDLoc, STI);
+ return false;
+}
+
+bool MipsAsmParser::expandTrunc(MCInst &Inst, bool IsDouble, bool Is64FPU,
+ SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
+
+ assert(Inst.getNumOperands() == 3 && "Invalid operand count");
+ assert(Inst.getOperand(0).isReg() && Inst.getOperand(1).isReg() &&
+ Inst.getOperand(2).isReg() && "Invalid instruction operand.");
+
+ unsigned FirstReg = Inst.getOperand(0).getReg();
+ unsigned SecondReg = Inst.getOperand(1).getReg();
+ unsigned ThirdReg = Inst.getOperand(2).getReg();
+
+ if (hasMips1() && !hasMips2()) {
+ unsigned ATReg = getATReg(IDLoc);
+ if (!ATReg)
+ return true;
+ TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
+ TOut.emitRR(Mips::CFC1, ThirdReg, Mips::RA, IDLoc, STI);
+ TOut.emitNop(IDLoc, STI);
+ TOut.emitRRI(Mips::ORi, ATReg, ThirdReg, 0x3, IDLoc, STI);
+ TOut.emitRRI(Mips::XORi, ATReg, ATReg, 0x2, IDLoc, STI);
+ TOut.emitRR(Mips::CTC1, Mips::RA, ATReg, IDLoc, STI);
+ TOut.emitNop(IDLoc, STI);
+ TOut.emitRR(IsDouble ? (Is64FPU ? Mips::CVT_W_D64 : Mips::CVT_W_D32)
+ : Mips::CVT_W_S,
+ FirstReg, SecondReg, IDLoc, STI);
+ TOut.emitRR(Mips::CTC1, Mips::RA, ThirdReg, IDLoc, STI);
+ TOut.emitNop(IDLoc, STI);
+ return false;
}
- emitR(Mips::MFLO, RsReg, IDLoc, Instructions);
+
+ TOut.emitRR(IsDouble ? (Is64FPU ? Mips::TRUNC_W_D64 : Mips::TRUNC_W_D32)
+ : Mips::TRUNC_W_S,
+ FirstReg, SecondReg, IDLoc, STI);
+
return false;
}
bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
+ MCStreamer &Out, const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
+
if (hasMips32r6() || hasMips64r6()) {
Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
return false;
@@ -3063,7 +3204,7 @@ bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
LoadedOffsetInAT = true;
if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
- true, IDLoc, Instructions))
+ true, IDLoc, Out, STI))
return true;
// NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
@@ -3073,7 +3214,7 @@ bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
// NOTE: If there is no source register specified in the ULHU, the parser
// will interpret it as $0.
if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
- createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
+ TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
}
unsigned FirstLbuDstReg = LoadedOffsetInAT ? DstReg : ATReg;
@@ -3091,21 +3232,23 @@ bool MipsAsmParser::expandUlh(MCInst &Inst, bool Signed, SMLoc IDLoc,
unsigned SllReg = LoadedOffsetInAT ? DstReg : ATReg;
- emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
- FirstLbuOffset, IDLoc, Instructions);
+ TOut.emitRRI(Signed ? Mips::LB : Mips::LBu, FirstLbuDstReg, LbuSrcReg,
+ FirstLbuOffset, IDLoc, STI);
- emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
- Instructions);
+ TOut.emitRRI(Mips::LBu, SecondLbuDstReg, LbuSrcReg, SecondLbuOffset, IDLoc,
+ STI);
- emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, Instructions);
+ TOut.emitRRI(Mips::SLL, SllReg, SllReg, 8, IDLoc, STI);
- emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, Instructions);
+ TOut.emitRRR(Mips::OR, DstReg, DstReg, ATReg, IDLoc, STI);
return false;
}
-bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
+bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
+
if (hasMips32r6() || hasMips64r6()) {
Error(IDLoc, "instruction not supported on mips32r6 or mips64r6");
return false;
@@ -3137,7 +3280,7 @@ bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
warnIfNoMacro(IDLoc);
if (loadImmediate(OffsetValue, ATReg, Mips::NoRegister, !ABI.ArePtrs64bit(),
- true, IDLoc, Instructions))
+ true, IDLoc, Out, STI))
return true;
// NOTE: We do this (D)ADDu here instead of doing it in loadImmediate()
@@ -3147,7 +3290,7 @@ bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
// NOTE: If there is no source register specified in the ULW, the parser
// will interpret it as $0.
if (SrcReg != Mips::ZERO && SrcReg != Mips::ZERO_64)
- createAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), Instructions);
+ TOut.emitAddu(ATReg, ATReg, SrcReg, ABI.ArePtrs64bit(), STI);
}
unsigned FinalSrcReg = LoadedOffsetInAT ? ATReg : SrcReg;
@@ -3160,17 +3303,19 @@ bool MipsAsmParser::expandUlw(MCInst &Inst, SMLoc IDLoc,
RightLoadOffset = LoadedOffsetInAT ? 3 : (OffsetValue + 3);
}
- emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
- Instructions);
+ TOut.emitRRI(Mips::LWL, DstRegOp.getReg(), FinalSrcReg, LeftLoadOffset, IDLoc,
+ STI);
- emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset, IDLoc,
- Instructions);
+ TOut.emitRRI(Mips::LWR, DstRegOp.getReg(), FinalSrcReg, RightLoadOffset,
+ IDLoc, STI);
return false;
}
bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
+ MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
assert (Inst.getNumOperands() == 3 && "Invalid operand count");
assert (Inst.getOperand(0).isReg() &&
@@ -3195,7 +3340,7 @@ bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
DstReg = ATReg;
}
- if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Instructions)) {
+ if (!loadImmediate(ImmValue, DstReg, Mips::NoRegister, Is32Bit, false, Inst.getLoc(), Out, STI)) {
switch (FinalOpcode) {
default:
llvm_unreachable("unimplemented expansion");
@@ -3226,17 +3371,17 @@ bool MipsAsmParser::expandAliasImmediate(MCInst &Inst, SMLoc IDLoc,
}
if (FinalDstReg == Mips::NoRegister)
- emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, Instructions);
+ TOut.emitRRR(FinalOpcode, DstReg, DstReg, SrcReg, IDLoc, STI);
else
- emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc,
- Instructions);
+ TOut.emitRRR(FinalOpcode, FinalDstReg, FinalDstReg, DstReg, IDLoc, STI);
return false;
}
return true;
}
-bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
+bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
unsigned ATReg = Mips::NoRegister;
unsigned DReg = Inst.getOperand(0).getReg();
unsigned SReg = Inst.getOperand(1).getReg();
@@ -3255,13 +3400,13 @@ bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc,
}
if (Inst.getOpcode() == Mips::ROL) {
- emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
- emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions);
+ TOut.emitRRR(Mips::SUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
+ TOut.emitRRR(Mips::ROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
return false;
}
if (Inst.getOpcode() == Mips::ROR) {
- emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions);
+ TOut.emitRRR(Mips::ROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
return false;
}
@@ -3287,10 +3432,10 @@ bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc,
if (!ATReg)
return true;
- emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
- emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions);
- emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions);
- emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
+ TOut.emitRRR(Mips::SUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
+ TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
+ TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
+ TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
return false;
}
@@ -3299,8 +3444,9 @@ bool MipsAsmParser::expandRotation(MCInst &Inst, SMLoc IDLoc,
}
bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
-
+ MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
unsigned ATReg = Mips::NoRegister;
unsigned DReg = Inst.getOperand(0).getReg();
unsigned SReg = Inst.getOperand(1).getReg();
@@ -3316,12 +3462,12 @@ bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
uint64_t ShiftValue = ImmValue;
if (ImmValue != 0)
ShiftValue = MaxShift - ImmValue;
- emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions);
+ TOut.emitRRI(Mips::ROTR, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
return false;
}
if (Inst.getOpcode() == Mips::RORImm) {
- emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), Instructions);
+ TOut.emitRRI(Mips::ROTR, DReg, SReg, ImmValue, Inst.getLoc(), STI);
return false;
}
@@ -3331,7 +3477,7 @@ bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
if (hasMips32()) {
if (ImmValue == 0) {
- emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), Instructions);
+ TOut.emitRRI(Mips::SRL, DReg, SReg, 0, Inst.getLoc(), STI);
return false;
}
@@ -3352,9 +3498,9 @@ bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
if (!ATReg)
return true;
- emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), Instructions);
- emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), Instructions);
- emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
+ TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue, Inst.getLoc(), STI);
+ TOut.emitRRI(SecondShift, DReg, SReg, 32 - ImmValue, Inst.getLoc(), STI);
+ TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
return false;
}
@@ -3362,9 +3508,9 @@ bool MipsAsmParser::expandRotationImm(MCInst &Inst, SMLoc IDLoc,
return true;
}
-bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
-
+bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
unsigned ATReg = Mips::NoRegister;
unsigned DReg = Inst.getOperand(0).getReg();
unsigned SReg = Inst.getOperand(1).getReg();
@@ -3383,13 +3529,13 @@ bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc,
}
if (Inst.getOpcode() == Mips::DROL) {
- emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
- emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), Instructions);
+ TOut.emitRRR(Mips::DSUBu, TmpReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
+ TOut.emitRRR(Mips::DROTRV, DReg, SReg, TmpReg, Inst.getLoc(), STI);
return false;
}
if (Inst.getOpcode() == Mips::DROR) {
- emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), Instructions);
+ TOut.emitRRR(Mips::DROTRV, DReg, SReg, TReg, Inst.getLoc(), STI);
return false;
}
@@ -3415,10 +3561,10 @@ bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc,
if (!ATReg)
return true;
- emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), Instructions);
- emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), Instructions);
- emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), Instructions);
- emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
+ TOut.emitRRR(Mips::DSUBu, ATReg, Mips::ZERO, TReg, Inst.getLoc(), STI);
+ TOut.emitRRR(FirstShift, ATReg, SReg, ATReg, Inst.getLoc(), STI);
+ TOut.emitRRR(SecondShift, DReg, SReg, TReg, Inst.getLoc(), STI);
+ TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
return false;
}
@@ -3427,8 +3573,9 @@ bool MipsAsmParser::expandDRotation(MCInst &Inst, SMLoc IDLoc,
}
bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
-
+ MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
unsigned ATReg = Mips::NoRegister;
unsigned DReg = Inst.getOperand(0).getReg();
unsigned SReg = Inst.getOperand(1).getReg();
@@ -3462,7 +3609,7 @@ bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
if (Inst.getOpcode() == Mips::DROLImm)
ShiftValue = (32 - ImmValue % 32) % 32;
- emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), Instructions);
+ TOut.emitRRI(FinalOpcode, DReg, SReg, ShiftValue, Inst.getLoc(), STI);
return false;
}
@@ -3470,7 +3617,7 @@ bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
if (hasMips64()) {
if (ImmValue == 0) {
- emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), Instructions);
+ TOut.emitRRI(Mips::DSRL, DReg, SReg, 0, Inst.getLoc(), STI);
return false;
}
@@ -3511,9 +3658,10 @@ bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
if (!ATReg)
return true;
- emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), Instructions);
- emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32, Inst.getLoc(), Instructions);
- emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), Instructions);
+ TOut.emitRRI(FirstShift, ATReg, SReg, ImmValue % 32, Inst.getLoc(), STI);
+ TOut.emitRRI(SecondShift, DReg, SReg, (32 - ImmValue % 32) % 32,
+ Inst.getLoc(), STI);
+ TOut.emitRRR(Mips::OR, DReg, DReg, ATReg, Inst.getLoc(), STI);
return false;
}
@@ -3521,49 +3669,76 @@ bool MipsAsmParser::expandDRotationImm(MCInst &Inst, SMLoc IDLoc,
return true;
}
-void MipsAsmParser::createNop(bool hasShortDelaySlot, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
- if (hasShortDelaySlot)
- emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, Instructions);
- else
- emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, Instructions);
-}
+bool MipsAsmParser::expandAbs(MCInst &Inst, SMLoc IDLoc, MCStreamer &Out,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer &TOut = getTargetStreamer();
+ unsigned FirstRegOp = Inst.getOperand(0).getReg();
+ unsigned SecondRegOp = Inst.getOperand(1).getReg();
-void MipsAsmParser::createAddu(unsigned DstReg, unsigned SrcReg,
- unsigned TrgReg, bool Is64Bit,
- SmallVectorImpl<MCInst> &Instructions) {
- emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
- Instructions);
-}
-
-void MipsAsmParser::createCpRestoreMemOp(
- bool IsLoad, int StackOffset, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions) {
- // If the offset can not fit into 16 bits, we need to expand.
- if (!isInt<16>(StackOffset)) {
- MCInst MemInst;
- MemInst.setOpcode(IsLoad ? Mips::LW : Mips::SW);
- MemInst.addOperand(MCOperand::createReg(Mips::GP));
- MemInst.addOperand(MCOperand::createReg(Mips::SP));
- MemInst.addOperand(MCOperand::createImm(StackOffset));
- expandMemInst(MemInst, IDLoc, Instructions, IsLoad, true /*HasImmOpnd*/);
- return;
- }
+ TOut.emitRI(Mips::BGEZ, SecondRegOp, 8, IDLoc, STI);
+ if (FirstRegOp != SecondRegOp)
+ TOut.emitRRR(Mips::ADDu, FirstRegOp, SecondRegOp, Mips::ZERO, IDLoc, STI);
+ else
+ TOut.emitEmptyDelaySlot(false, IDLoc, STI);
+ TOut.emitRRR(Mips::SUB, FirstRegOp, Mips::ZERO, SecondRegOp, IDLoc, STI);
- emitRRI(IsLoad ? Mips::LW : Mips::SW, Mips::GP, Mips::SP, StackOffset, IDLoc,
- Instructions);
+ return false;
}
unsigned MipsAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
+ switch (Inst.getOpcode()) {
// As described by the Mips32r2 spec, the registers Rd and Rs for
// jalr.hb must be different.
- unsigned Opcode = Inst.getOpcode();
-
- if (Opcode == Mips::JALR_HB &&
- (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()))
- return Match_RequiresDifferentSrcAndDst;
-
- return Match_Success;
+ // It also applies for registers Rt and Rs of microMIPSr6 jalrc.hb instruction
+ // and registers Rd and Base for microMIPS lwp instruction
+ case Mips::JALR_HB:
+ case Mips::JALRC_HB_MMR6:
+ case Mips::JALRC_MMR6:
+ if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
+ return Match_RequiresDifferentSrcAndDst;
+ return Match_Success;
+ case Mips::LWP_MM:
+ case Mips::LWP_MMR6:
+ if (Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg())
+ return Match_RequiresDifferentSrcAndDst;
+ return Match_Success;
+ // As described the MIPSR6 spec, the compact branches that compare registers
+ // must:
+ // a) Not use the zero register.
+ // b) Not use the same register twice.
+ // c) rs < rt for bnec, beqc.
+ // NB: For this case, the encoding will swap the operands as their
+ // ordering doesn't matter. GAS performs this transformation too.
+ // Hence, that constraint does not have to be enforced.
+ //
+ // The compact branches that branch iff the signed addition of two registers
+ // would overflow must have rs >= rt. That can be handled like beqc/bnec with
+ // operand swapping. They do not have restriction of using the zero register.
+ case Mips::BLEZC:
+ case Mips::BGEZC:
+ case Mips::BGTZC:
+ case Mips::BLTZC:
+ case Mips::BEQZC:
+ case Mips::BNEZC:
+ if (Inst.getOperand(0).getReg() == Mips::ZERO)
+ return Match_RequiresNoZeroRegister;
+ return Match_Success;
+ case Mips::BGEC:
+ case Mips::BLTC:
+ case Mips::BGEUC:
+ case Mips::BLTUC:
+ case Mips::BEQC:
+ case Mips::BNEC:
+ if (Inst.getOperand(0).getReg() == Mips::ZERO)
+ return Match_RequiresNoZeroRegister;
+ if (Inst.getOperand(1).getReg() == Mips::ZERO)
+ return Match_RequiresNoZeroRegister;
+ if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg())
+ return Match_RequiresDifferentOperands;
+ return Match_Success;
+ default:
+ return Match_Success;
+ }
}
static SMLoc RefineErrorLoc(const SMLoc Loc, const OperandVector &Operands,
@@ -3584,16 +3759,13 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
bool MatchingInlineAsm) {
MCInst Inst;
- SmallVector<MCInst, 8> Instructions;
unsigned MatchResult =
MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm);
switch (MatchResult) {
case Match_Success: {
- if (processInstruction(Inst, IDLoc, Instructions))
+ if (processInstruction(Inst, IDLoc, Out, STI))
return true;
- for (unsigned i = 0; i < Instructions.size(); i++)
- Out.EmitInstruction(Instructions[i], getSTI());
return false;
}
case Match_MissingFeature:
@@ -3616,6 +3788,10 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
return Error(IDLoc, "invalid instruction");
case Match_RequiresDifferentSrcAndDst:
return Error(IDLoc, "source and destination must be different");
+ case Match_RequiresDifferentOperands:
+ return Error(IDLoc, "registers must be different");
+ case Match_RequiresNoZeroRegister:
+ return Error(IDLoc, "invalid operand ($zero) for instruction");
case Match_Immz:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo), "expected '0'");
case Match_UImm1_0:
@@ -3633,9 +3809,15 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_UImm4_0:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected 4-bit unsigned immediate");
+ case Match_SImm4_0:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected 4-bit signed immediate");
case Match_UImm5_0:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected 5-bit unsigned immediate");
+ case Match_SImm5_0:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected 5-bit signed immediate");
case Match_UImm5_1:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected immediate in range 1 .. 32");
@@ -3653,21 +3835,81 @@ bool MipsAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
case Match_UImm5_Lsl2:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected both 7-bit unsigned immediate and multiple of 4");
+ case Match_UImmRange2_64:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected immediate in range 2 .. 64");
case Match_UImm6_0:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected 6-bit unsigned immediate");
- case Match_SImm6:
+ case Match_UImm6_Lsl2:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected both 8-bit unsigned immediate and multiple of 4");
+ case Match_SImm6_0:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected 6-bit signed immediate");
case Match_UImm7_0:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected 7-bit unsigned immediate");
+ case Match_UImm7_N1:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected immediate in range -1 .. 126");
+ case Match_SImm7_Lsl2:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected both 9-bit signed immediate and multiple of 4");
case Match_UImm8_0:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected 8-bit unsigned immediate");
case Match_UImm10_0:
return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
"expected 10-bit unsigned immediate");
+ case Match_SImm10_0:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected 10-bit signed immediate");
+ case Match_SImm11_0:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected 11-bit signed immediate");
+ case Match_UImm16:
+ case Match_UImm16_Relaxed:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected 16-bit unsigned immediate");
+ case Match_SImm16:
+ case Match_SImm16_Relaxed:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected 16-bit signed immediate");
+ case Match_UImm20_0:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected 20-bit unsigned immediate");
+ case Match_UImm26_0:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected 26-bit unsigned immediate");
+ case Match_SImm32:
+ case Match_SImm32_Relaxed:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected 32-bit signed immediate");
+ case Match_MemSImm9:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected memory with 9-bit signed offset");
+ case Match_MemSImm10:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected memory with 10-bit signed offset");
+ case Match_MemSImm10Lsl1:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected memory with 11-bit signed offset and multiple of 2");
+ case Match_MemSImm10Lsl2:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected memory with 12-bit signed offset and multiple of 4");
+ case Match_MemSImm10Lsl3:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected memory with 13-bit signed offset and multiple of 8");
+ case Match_MemSImm11:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected memory with 11-bit signed offset");
+ case Match_MemSImm12:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected memory with 12-bit signed offset");
+ case Match_MemSImm16:
+ return Error(RefineErrorLoc(IDLoc, Operands, ErrorInfo),
+ "expected memory with 16-bit signed offset");
}
llvm_unreachable("Implement any new match types added!");
@@ -3871,19 +4113,6 @@ unsigned MipsAsmParser::getReg(int RC, int RegNo) {
return *(getContext().getRegisterInfo()->getRegClass(RC).begin() + RegNo);
}
-unsigned MipsAsmParser::getGPR(int RegNo) {
- return getReg(isGP64bit() ? Mips::GPR64RegClassID : Mips::GPR32RegClassID,
- RegNo);
-}
-
-int MipsAsmParser::matchRegisterByNumber(unsigned RegNum, unsigned RegClass) {
- if (RegNum >
- getContext().getRegisterInfo()->getRegClass(RegClass).getNumRegs() - 1)
- return -1;
-
- return getReg(RegClass, RegNum);
-}
-
bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
MCAsmParser &Parser = getParser();
DEBUG(dbgs() << "parseOperand\n");
@@ -3960,63 +4189,41 @@ bool MipsAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
const MCExpr *MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
StringRef RelocStr) {
- const MCExpr *Res;
- // Check the type of the expression.
- if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
- // It's a constant, evaluate reloc value.
- int16_t Val;
- switch (getVariantKind(RelocStr)) {
- case MCSymbolRefExpr::VK_Mips_ABS_LO:
- // Get the 1st 16-bits.
- Val = MCE->getValue() & 0xffff;
- break;
- case MCSymbolRefExpr::VK_Mips_ABS_HI:
- // Get the 2nd 16-bits. Also add 1 if bit 15 is 1, to compensate for low
- // 16 bits being negative.
- Val = ((MCE->getValue() + 0x8000) >> 16) & 0xffff;
- break;
- case MCSymbolRefExpr::VK_Mips_HIGHER:
- // Get the 3rd 16-bits.
- Val = ((MCE->getValue() + 0x80008000LL) >> 32) & 0xffff;
- break;
- case MCSymbolRefExpr::VK_Mips_HIGHEST:
- // Get the 4th 16-bits.
- Val = ((MCE->getValue() + 0x800080008000LL) >> 48) & 0xffff;
- break;
- default:
- report_fatal_error("unsupported reloc value");
- }
- return MCConstantExpr::create(Val, getContext());
- }
-
- if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
- // It's a symbol, create a symbolic expression from the symbol.
- const MCSymbol *Symbol = &MSRE->getSymbol();
- MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
- Res = MCSymbolRefExpr::create(Symbol, VK, getContext());
- return Res;
- }
-
- if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
- MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
-
- // Try to create target expression.
- if (MipsMCExpr::isSupportedBinaryExpr(VK, BE))
- return MipsMCExpr::create(VK, Expr, getContext());
-
- const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
- const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
- Res = MCBinaryExpr::create(BE->getOpcode(), LExp, RExp, getContext());
- return Res;
- }
-
- if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
- const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
- Res = MCUnaryExpr::create(UN->getOpcode(), UnExp, getContext());
- return Res;
- }
- // Just return the original expression.
- return Expr;
+ if (RelocStr == "hi(%neg(%gp_rel")
+ return MipsMCExpr::createGpOff(MipsMCExpr::MEK_HI, Expr, getContext());
+ else if (RelocStr == "lo(%neg(%gp_rel")
+ return MipsMCExpr::createGpOff(MipsMCExpr::MEK_LO, Expr, getContext());
+
+ MipsMCExpr::MipsExprKind Kind =
+ StringSwitch<MipsMCExpr::MipsExprKind>(RelocStr)
+ .Case("call16", MipsMCExpr::MEK_GOT_CALL)
+ .Case("call_hi", MipsMCExpr::MEK_CALL_HI16)
+ .Case("call_lo", MipsMCExpr::MEK_CALL_LO16)
+ .Case("dtprel_hi", MipsMCExpr::MEK_DTPREL_HI)
+ .Case("dtprel_lo", MipsMCExpr::MEK_DTPREL_LO)
+ .Case("got", MipsMCExpr::MEK_GOT)
+ .Case("got_disp", MipsMCExpr::MEK_GOT_DISP)
+ .Case("got_hi", MipsMCExpr::MEK_GOT_HI16)
+ .Case("got_lo", MipsMCExpr::MEK_GOT_LO16)
+ .Case("got_ofst", MipsMCExpr::MEK_GOT_OFST)
+ .Case("got_page", MipsMCExpr::MEK_GOT_PAGE)
+ .Case("gottprel", MipsMCExpr::MEK_GOTTPREL)
+ .Case("gp_rel", MipsMCExpr::MEK_GPREL)
+ .Case("hi", MipsMCExpr::MEK_HI)
+ .Case("higher", MipsMCExpr::MEK_HIGHER)
+ .Case("highest", MipsMCExpr::MEK_HIGHEST)
+ .Case("lo", MipsMCExpr::MEK_LO)
+ .Case("neg", MipsMCExpr::MEK_NEG)
+ .Case("pcrel_hi", MipsMCExpr::MEK_PCREL_HI16)
+ .Case("pcrel_lo", MipsMCExpr::MEK_PCREL_LO16)
+ .Case("tlsgd", MipsMCExpr::MEK_TLSGD)
+ .Case("tlsldm", MipsMCExpr::MEK_TLSLDM)
+ .Case("tprel_hi", MipsMCExpr::MEK_TPREL_HI)
+ .Case("tprel_lo", MipsMCExpr::MEK_TPREL_LO)
+ .Default(MipsMCExpr::MEK_None);
+
+ assert(Kind != MipsMCExpr::MEK_None);
+ return MipsMCExpr::create(Kind, Expr, getContext());
}
bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
@@ -4248,12 +4455,6 @@ bool MipsAsmParser::searchSymbolAlias(OperandVector &Operands) {
llvm_unreachable("Should never ParseFail");
return false;
}
- } else if (Expr->getKind() == MCExpr::Constant) {
- Parser.Lex();
- const MCConstantExpr *Const = static_cast<const MCConstantExpr *>(Expr);
- Operands.push_back(
- MipsOperand::CreateImm(Const, S, Parser.getTok().getLoc(), *this));
- return true;
}
}
return false;
@@ -4439,46 +4640,6 @@ MipsAsmParser::parseInvNum(OperandVector &Operands) {
}
MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::parseLSAImm(OperandVector &Operands) {
- MCAsmParser &Parser = getParser();
- switch (getLexer().getKind()) {
- default:
- return MatchOperand_NoMatch;
- case AsmToken::LParen:
- case AsmToken::Plus:
- case AsmToken::Minus:
- case AsmToken::Integer:
- break;
- }
-
- const MCExpr *Expr;
- SMLoc S = Parser.getTok().getLoc();
-
- if (getParser().parseExpression(Expr))
- return MatchOperand_ParseFail;
-
- int64_t Val;
- if (!Expr->evaluateAsAbsolute(Val)) {
- Error(S, "expected immediate value");
- return MatchOperand_ParseFail;
- }
-
- // The LSA instruction allows a 2-bit unsigned immediate. For this reason
- // and because the CPU always adds one to the immediate field, the allowed
- // range becomes 1..4. We'll only check the range here and will deal
- // with the addition/subtraction when actually decoding/encoding
- // the instruction.
- if (Val < 1 || Val > 4) {
- Error(S, "immediate not in range (1..4)");
- return MatchOperand_ParseFail;
- }
-
- Operands.push_back(
- MipsOperand::CreateImm(Expr, S, Parser.getTok().getLoc(), *this));
- return MatchOperand_Success;
-}
-
-MipsAsmParser::OperandMatchResultTy
MipsAsmParser::parseRegisterList(OperandVector &Operands) {
MCAsmParser &Parser = getParser();
SmallVector<unsigned, 10> Regs;
@@ -4573,10 +4734,10 @@ MipsAsmParser::parseRegisterPair(OperandVector &Operands) {
return MatchOperand_ParseFail;
SMLoc E = Parser.getTok().getLoc();
- MipsOperand &Op = static_cast<MipsOperand &>(*Operands.back());
- unsigned Reg = Op.getGPR32Reg();
+ MipsOperand Op = static_cast<MipsOperand &>(*Operands.back());
+
Operands.pop_back();
- Operands.push_back(MipsOperand::CreateRegPair(Reg, S, E, *this));
+ Operands.push_back(MipsOperand::CreateRegPair(Op, S, E, *this));
return MatchOperand_Success;
}
@@ -4619,42 +4780,6 @@ MipsAsmParser::parseMovePRegPair(OperandVector &Operands) {
return MatchOperand_Success;
}
-MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
-
- MCSymbolRefExpr::VariantKind VK =
- StringSwitch<MCSymbolRefExpr::VariantKind>(Symbol)
- .Case("hi", MCSymbolRefExpr::VK_Mips_ABS_HI)
- .Case("lo", MCSymbolRefExpr::VK_Mips_ABS_LO)
- .Case("gp_rel", MCSymbolRefExpr::VK_Mips_GPREL)
- .Case("call16", MCSymbolRefExpr::VK_Mips_GOT_CALL)
- .Case("got", MCSymbolRefExpr::VK_Mips_GOT)
- .Case("tlsgd", MCSymbolRefExpr::VK_Mips_TLSGD)
- .Case("tlsldm", MCSymbolRefExpr::VK_Mips_TLSLDM)
- .Case("dtprel_hi", MCSymbolRefExpr::VK_Mips_DTPREL_HI)
- .Case("dtprel_lo", MCSymbolRefExpr::VK_Mips_DTPREL_LO)
- .Case("gottprel", MCSymbolRefExpr::VK_Mips_GOTTPREL)
- .Case("tprel_hi", MCSymbolRefExpr::VK_Mips_TPREL_HI)
- .Case("tprel_lo", MCSymbolRefExpr::VK_Mips_TPREL_LO)
- .Case("got_disp", MCSymbolRefExpr::VK_Mips_GOT_DISP)
- .Case("got_page", MCSymbolRefExpr::VK_Mips_GOT_PAGE)
- .Case("got_ofst", MCSymbolRefExpr::VK_Mips_GOT_OFST)
- .Case("hi(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_HI)
- .Case("lo(%neg(%gp_rel", MCSymbolRefExpr::VK_Mips_GPOFF_LO)
- .Case("got_hi", MCSymbolRefExpr::VK_Mips_GOT_HI16)
- .Case("got_lo", MCSymbolRefExpr::VK_Mips_GOT_LO16)
- .Case("call_hi", MCSymbolRefExpr::VK_Mips_CALL_HI16)
- .Case("call_lo", MCSymbolRefExpr::VK_Mips_CALL_LO16)
- .Case("higher", MCSymbolRefExpr::VK_Mips_HIGHER)
- .Case("highest", MCSymbolRefExpr::VK_Mips_HIGHEST)
- .Case("pcrel_hi", MCSymbolRefExpr::VK_Mips_PCREL_HI16)
- .Case("pcrel_lo", MCSymbolRefExpr::VK_Mips_PCREL_LO16)
- .Default(MCSymbolRefExpr::VK_None);
-
- assert(VK != MCSymbolRefExpr::VK_None);
-
- return VK;
-}
-
/// Sometimes (i.e. load/stores) the operand may be followed immediately by
/// either this.
/// ::= '(', register, ')'
@@ -4767,6 +4892,8 @@ bool MipsAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
return false;
}
+// FIXME: Given that these have the same name, these should both be
+// consistent on affecting the Parser.
bool MipsAsmParser::reportParseError(Twine ErrorMsg) {
MCAsmParser &Parser = getParser();
SMLoc Loc = getLexer().getLoc();
@@ -5174,7 +5301,7 @@ bool MipsAsmParser::parseSetArchDirective() {
.Case("mips64r3", "mips64r3")
.Case("mips64r5", "mips64r5")
.Case("mips64r6", "mips64r6")
- .Case("cnmips", "cnmips")
+ .Case("octeon", "cnmips")
.Case("r4000", "mips3") // This is an implementation of Mips3.
.Default("");
@@ -5200,6 +5327,7 @@ bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
getTargetStreamer().emitDirectiveSetDsp();
break;
case Mips::FeatureMicroMips:
+ setFeatureBits(Mips::FeatureMicroMips, "micromips");
getTargetStreamer().emitDirectiveSetMicroMips();
break;
case Mips::FeatureMips1:
@@ -5356,12 +5484,9 @@ bool MipsAsmParser::parseDirectiveCpRestore(SMLoc Loc) {
return false;
}
- // Store the $gp on the stack.
- SmallVector<MCInst, 3> StoreInsts;
- createCpRestoreMemOp(false /*IsLoad*/, CpRestoreOffset /*StackOffset*/, Loc,
- StoreInsts);
-
- getTargetStreamer().emitDirectiveCpRestore(StoreInsts, CpRestoreOffset);
+ if (!getTargetStreamer().emitDirectiveCpRestore(
+ CpRestoreOffset, [&]() { return getATReg(Loc); }, Loc, STI))
+ return true;
Parser.Lex(); // Consume the EndOfStatement.
return false;
}
@@ -5376,7 +5501,6 @@ bool MipsAsmParser::parseDirectiveCPSetup() {
OperandMatchResultTy ResTy = parseAnyRegister(TmpReg);
if (ResTy == MatchOperand_NoMatch) {
reportParseError("expected register containing function address");
- Parser.eatToEndOfStatement();
return false;
}
@@ -5502,6 +5626,7 @@ bool MipsAsmParser::parseDirectiveSet() {
} else if (Tok.getString() == "nomips16") {
return parseSetNoMips16Directive();
} else if (Tok.getString() == "nomicromips") {
+ clearFeatureBits(Mips::FeatureMicroMips, "micromips");
getTargetStreamer().emitDirectiveSetNoMicroMips();
Parser.eatToEndOfStatement();
return false;
@@ -5686,6 +5811,24 @@ bool MipsAsmParser::parseInsnDirective() {
return false;
}
+/// parseSSectionDirective
+/// ::= .sbss
+/// ::= .sdata
+bool MipsAsmParser::parseSSectionDirective(StringRef Section, unsigned Type) {
+ // If this is not the end of the statement, report an error.
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ reportParseError("unexpected token, expected end of statement");
+ return false;
+ }
+
+ MCSection *ELFSection = getContext().getELFSection(
+ Section, Type, ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
+ getParser().getStreamer().SwitchSection(ELFSection);
+
+ getParser().Lex(); // Eat EndOfStatement token.
+ return false;
+}
+
/// parseDirectiveModule
/// ::= .module oddspreg
/// ::= .module nooddspreg
@@ -5905,13 +6048,22 @@ bool MipsAsmParser::parseFpABIValue(MipsABIFlagsSection::FpABIKind &FpABI,
}
bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
+ // This returns false if this function recognizes the directive
+ // regardless of whether it is successfully handles or reports an
+ // error. Otherwise it returns true to give the generic parser a
+ // chance at recognizing it.
+
MCAsmParser &Parser = getParser();
StringRef IDVal = DirectiveID.getString();
- if (IDVal == ".cpload")
- return parseDirectiveCpLoad(DirectiveID.getLoc());
- if (IDVal == ".cprestore")
- return parseDirectiveCpRestore(DirectiveID.getLoc());
+ if (IDVal == ".cpload") {
+ parseDirectiveCpLoad(DirectiveID.getLoc());
+ return false;
+ }
+ if (IDVal == ".cprestore") {
+ parseDirectiveCpRestore(DirectiveID.getLoc());
+ return false;
+ }
if (IDVal == ".dword") {
parseDataDirective(8, DirectiveID.getLoc());
return false;
@@ -6068,7 +6220,8 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
}
if (IDVal == ".set") {
- return parseDirectiveSet();
+ parseDirectiveSet();
+ return false;
}
if (IDVal == ".mask" || IDVal == ".fmask") {
@@ -6147,8 +6300,15 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
return false;
}
- if (IDVal == ".option")
- return parseDirectiveOption();
+ if (IDVal == ".hword") {
+ parseDataDirective(2, DirectiveID.getLoc());
+ return false;
+ }
+
+ if (IDVal == ".option") {
+ parseDirectiveOption();
+ return false;
+ }
if (IDVal == ".abicalls") {
getTargetStreamer().emitDirectiveAbiCalls();
@@ -6161,20 +6321,34 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
return false;
}
- if (IDVal == ".cpsetup")
- return parseDirectiveCPSetup();
-
- if (IDVal == ".cpreturn")
- return parseDirectiveCPReturn();
-
- if (IDVal == ".module")
- return parseDirectiveModule();
-
- if (IDVal == ".llvm_internal_mips_reallow_module_directive")
- return parseInternalDirectiveReallowModule();
-
- if (IDVal == ".insn")
- return parseInsnDirective();
+ if (IDVal == ".cpsetup") {
+ parseDirectiveCPSetup();
+ return false;
+ }
+ if (IDVal == ".cpreturn") {
+ parseDirectiveCPReturn();
+ return false;
+ }
+ if (IDVal == ".module") {
+ parseDirectiveModule();
+ return false;
+ }
+ if (IDVal == ".llvm_internal_mips_reallow_module_directive") {
+ parseInternalDirectiveReallowModule();
+ return false;
+ }
+ if (IDVal == ".insn") {
+ parseInsnDirective();
+ return false;
+ }
+ if (IDVal == ".sbss") {
+ parseSSectionDirective(IDVal, ELF::SHT_NOBITS);
+ return false;
+ }
+ if (IDVal == ".sdata") {
+ parseSSectionDirective(IDVal, ELF::SHT_PROGBITS);
+ return false;
+ }
return true;
}
diff --git a/lib/Target/Mips/CMakeLists.txt b/lib/Target/Mips/CMakeLists.txt
index bde843afd3d28..3650cc9fe0728 100644
--- a/lib/Target/Mips/CMakeLists.txt
+++ b/lib/Target/Mips/CMakeLists.txt
@@ -27,6 +27,7 @@ add_llvm_target(MipsCodeGen
MipsConstantIslandPass.cpp
MipsDelaySlotFiller.cpp
MipsFastISel.cpp
+ MipsHazardSchedule.cpp
MipsInstrInfo.cpp
MipsISelDAGToDAG.cpp
MipsISelLowering.cpp
diff --git a/lib/Target/Mips/Disassembler/Makefile b/lib/Target/Mips/Disassembler/Makefile
deleted file mode 100644
index 7900373dd2b21..0000000000000
--- a/lib/Target/Mips/Disassembler/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-##===- lib/Target/Mips/Disassembler/Makefile ---------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LEVEL = ../../../..
-LIBRARYNAME = LLVMMipsDisassembler
-
-# Hack: we need to include 'main' Mips target directory to grab private headers
-CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
-
-include $(LEVEL)/Makefile.common
diff --git a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
index 3c1a771f97e95..aebb4ef419d18 100644
--- a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
+++ b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
@@ -15,7 +15,7 @@
#include "MipsRegisterInfo.h"
#include "MipsSubtarget.h"
#include "llvm/MC/MCContext.h"
-#include "llvm/MC/MCDisassembler.h"
+#include "llvm/MC/MCDisassembler/MCDisassembler.h"
#include "llvm/MC/MCFixedLenDisassembler.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCSubtargetInfo.h"
@@ -39,14 +39,18 @@ public:
IsMicroMips(STI.getFeatureBits()[Mips::FeatureMicroMips]),
IsBigEndian(IsBigEndian) {}
+ bool hasMips2() const { return STI.getFeatureBits()[Mips::FeatureMips2]; }
bool hasMips3() const { return STI.getFeatureBits()[Mips::FeatureMips3]; }
bool hasMips32() const { return STI.getFeatureBits()[Mips::FeatureMips32]; }
bool hasMips32r6() const {
return STI.getFeatureBits()[Mips::FeatureMips32r6];
}
+ bool isFP64() const { return STI.getFeatureBits()[Mips::FeatureFP64Bit]; }
bool isGP64() const { return STI.getFeatureBits()[Mips::FeatureGP64Bit]; }
+ bool isPTR64() const { return STI.getFeatureBits()[Mips::FeaturePTR64Bit]; }
+
bool hasCnMips() const { return STI.getFeatureBits()[Mips::FeatureCnMips]; }
bool hasCOP3() const {
@@ -193,6 +197,11 @@ static DecodeStatus DecodeBranchTarget(MCInst &Inst,
uint64_t Address,
const void *Decoder);
+static DecodeStatus DecodeBranchTarget1SImm16(MCInst &Inst,
+ unsigned Offset,
+ uint64_t Address,
+ const void *Decoder);
+
static DecodeStatus DecodeJumpTarget(MCInst &Inst,
unsigned Insn,
uint64_t Address,
@@ -203,6 +212,11 @@ static DecodeStatus DecodeBranchTarget21(MCInst &Inst,
uint64_t Address,
const void *Decoder);
+static DecodeStatus DecodeBranchTarget21MM(MCInst &Inst,
+ unsigned Offset,
+ uint64_t Address,
+ const void *Decoder);
+
static DecodeStatus DecodeBranchTarget26(MCInst &Inst,
unsigned Offset,
uint64_t Address,
@@ -340,6 +354,10 @@ static DecodeStatus DecodeFMem(MCInst &Inst, unsigned Insn,
uint64_t Address,
const void *Decoder);
+static DecodeStatus DecodeFMemMMR2(MCInst &Inst, unsigned Insn,
+ uint64_t Address,
+ const void *Decoder);
+
static DecodeStatus DecodeFMem2(MCInst &Inst, unsigned Insn,
uint64_t Address,
const void *Decoder);
@@ -352,6 +370,10 @@ static DecodeStatus DecodeFMemCop2R6(MCInst &Inst, unsigned Insn,
uint64_t Address,
const void *Decoder);
+static DecodeStatus DecodeFMemCop2MMR6(MCInst &Inst, unsigned Insn,
+ uint64_t Address,
+ const void *Decoder);
+
static DecodeStatus DecodeSpecial3LlSc(MCInst &Inst,
unsigned Insn,
uint64_t Address,
@@ -362,12 +384,7 @@ static DecodeStatus DecodeAddiur2Simm7(MCInst &Inst,
uint64_t Address,
const void *Decoder);
-static DecodeStatus DecodeUImm6Lsl2(MCInst &Inst,
- unsigned Value,
- uint64_t Address,
- const void *Decoder);
-
-static DecodeStatus DecodeLiSimm7(MCInst &Inst,
+static DecodeStatus DecodeLi16Imm(MCInst &Inst,
unsigned Value,
uint64_t Address,
const void *Decoder);
@@ -377,19 +394,23 @@ static DecodeStatus DecodePOOL16BEncodedField(MCInst &Inst,
uint64_t Address,
const void *Decoder);
-static DecodeStatus DecodeSimm4(MCInst &Inst,
- unsigned Value,
- uint64_t Address,
- const void *Decoder);
-
-static DecodeStatus DecodeSimm16(MCInst &Inst,
- unsigned Insn,
- uint64_t Address,
- const void *Decoder);
+template <unsigned Bits, int Offset, int Scale>
+static DecodeStatus DecodeUImmWithOffsetAndScale(MCInst &Inst, unsigned Value,
+ uint64_t Address,
+ const void *Decoder);
template <unsigned Bits, int Offset>
static DecodeStatus DecodeUImmWithOffset(MCInst &Inst, unsigned Value,
- uint64_t Address, const void *Decoder);
+ uint64_t Address,
+ const void *Decoder) {
+ return DecodeUImmWithOffsetAndScale<Bits, Offset, 1>(Inst, Value, Address,
+ Decoder);
+}
+
+template <unsigned Bits, int Offset = 0, int ScaleBy = 1>
+static DecodeStatus DecodeSImmWithOffsetAndScale(MCInst &Inst, unsigned Value,
+ uint64_t Address,
+ const void *Decoder);
static DecodeStatus DecodeInsSize(MCInst &Inst,
unsigned Insn,
@@ -408,9 +429,6 @@ static DecodeStatus DecodeSimm9SP(MCInst &Inst, unsigned Insn,
static DecodeStatus DecodeANDI16Imm(MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
-static DecodeStatus DecodeUImm5lsl2(MCInst &Inst, unsigned Insn,
- uint64_t Address, const void *Decoder);
-
static DecodeStatus DecodeSimm23Lsl2(MCInst &Inst, unsigned Insn,
uint64_t Address, const void *Decoder);
@@ -427,11 +445,21 @@ DecodeAddiGroupBranch(MCInst &MI, InsnType insn, uint64_t Address,
template <typename InsnType>
static DecodeStatus
+DecodePOP35GroupBranchMMR6(MCInst &MI, InsnType insn, uint64_t Address,
+ const void *Decoder);
+
+template <typename InsnType>
+static DecodeStatus
DecodeDaddiGroupBranch(MCInst &MI, InsnType insn, uint64_t Address,
const void *Decoder);
template <typename InsnType>
static DecodeStatus
+DecodePOP37GroupBranchMMR6(MCInst &MI, InsnType insn, uint64_t Address,
+ const void *Decoder);
+
+template <typename InsnType>
+static DecodeStatus
DecodeBlezlGroupBranch(MCInst &MI, InsnType insn, uint64_t Address,
const void *Decoder);
@@ -450,6 +478,16 @@ static DecodeStatus
DecodeBlezGroupBranch(MCInst &MI, InsnType insn, uint64_t Address,
const void *Decoder);
+template <typename InsnType>
+static DecodeStatus
+DecodeBgtzGroupBranchMMR6(MCInst &MI, InsnType insn, uint64_t Address,
+ const void *Decoder);
+
+template <typename InsnType>
+static DecodeStatus
+DecodeBlezGroupBranchMMR6(MCInst &MI, InsnType insn, uint64_t Address,
+ const void *Decoder);
+
static DecodeStatus DecodeRegListOperand(MCInst &Inst, unsigned Insn,
uint64_t Address,
const void *Decoder);
@@ -563,7 +601,7 @@ static DecodeStatus DecodeAddiGroupBranch(MCInst &MI, InsnType insn,
InsnType Rs = fieldFromInstruction(insn, 21, 5);
InsnType Rt = fieldFromInstruction(insn, 16, 5);
- InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4;
+ int64_t Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4 + 4;
bool HasRs = false;
if (Rs >= Rt) {
@@ -587,6 +625,37 @@ static DecodeStatus DecodeAddiGroupBranch(MCInst &MI, InsnType insn,
}
template <typename InsnType>
+static DecodeStatus DecodePOP35GroupBranchMMR6(MCInst &MI, InsnType insn,
+ uint64_t Address,
+ const void *Decoder) {
+ InsnType Rt = fieldFromInstruction(insn, 21, 5);
+ InsnType Rs = fieldFromInstruction(insn, 16, 5);
+ InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 2;
+
+ if (Rs >= Rt) {
+ MI.setOpcode(Mips::BOVC_MMR6);
+ MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID,
+ Rt)));
+ MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID,
+ Rs)));
+ } else if (Rs != 0 && Rs < Rt) {
+ MI.setOpcode(Mips::BEQC_MMR6);
+ MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID,
+ Rs)));
+ MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID,
+ Rt)));
+ } else {
+ MI.setOpcode(Mips::BEQZALC_MMR6);
+ MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID,
+ Rt)));
+ }
+
+ MI.addOperand(MCOperand::createImm(Imm));
+
+ return MCDisassembler::Success;
+}
+
+template <typename InsnType>
static DecodeStatus DecodeDaddiGroupBranch(MCInst &MI, InsnType insn,
uint64_t Address,
const void *Decoder) {
@@ -602,7 +671,7 @@ static DecodeStatus DecodeDaddiGroupBranch(MCInst &MI, InsnType insn,
InsnType Rs = fieldFromInstruction(insn, 21, 5);
InsnType Rt = fieldFromInstruction(insn, 16, 5);
- InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4;
+ int64_t Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4 + 4;
bool HasRs = false;
if (Rs >= Rt) {
@@ -626,6 +695,37 @@ static DecodeStatus DecodeDaddiGroupBranch(MCInst &MI, InsnType insn,
}
template <typename InsnType>
+static DecodeStatus DecodePOP37GroupBranchMMR6(MCInst &MI, InsnType insn,
+ uint64_t Address,
+ const void *Decoder) {
+ InsnType Rt = fieldFromInstruction(insn, 21, 5);
+ InsnType Rs = fieldFromInstruction(insn, 16, 5);
+ InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 2;
+
+ if (Rs >= Rt) {
+ MI.setOpcode(Mips::BNVC_MMR6);
+ MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID,
+ Rt)));
+ MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID,
+ Rs)));
+ } else if (Rs != 0 && Rs < Rt) {
+ MI.setOpcode(Mips::BNEC_MMR6);
+ MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID,
+ Rs)));
+ MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID,
+ Rt)));
+ } else {
+ MI.setOpcode(Mips::BNEZALC_MMR6);
+ MI.addOperand(MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID,
+ Rt)));
+ }
+
+ MI.addOperand(MCOperand::createImm(Imm));
+
+ return MCDisassembler::Success;
+}
+
+template <typename InsnType>
static DecodeStatus DecodeBlezlGroupBranch(MCInst &MI, InsnType insn,
uint64_t Address,
const void *Decoder) {
@@ -642,7 +742,7 @@ static DecodeStatus DecodeBlezlGroupBranch(MCInst &MI, InsnType insn,
InsnType Rs = fieldFromInstruction(insn, 21, 5);
InsnType Rt = fieldFromInstruction(insn, 16, 5);
- InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4;
+ int64_t Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4 + 4;
bool HasRs = false;
if (Rt == 0)
@@ -687,7 +787,7 @@ static DecodeStatus DecodeBgtzlGroupBranch(MCInst &MI, InsnType insn,
InsnType Rs = fieldFromInstruction(insn, 21, 5);
InsnType Rt = fieldFromInstruction(insn, 16, 5);
- InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4;
+ int64_t Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4 + 4;
if (Rt == 0)
return MCDisassembler::Fail;
@@ -729,7 +829,7 @@ static DecodeStatus DecodeBgtzGroupBranch(MCInst &MI, InsnType insn,
InsnType Rs = fieldFromInstruction(insn, 21, 5);
InsnType Rt = fieldFromInstruction(insn, 16, 5);
- InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4;
+ int64_t Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4 + 4;
bool HasRs = false;
bool HasRt = false;
@@ -778,7 +878,7 @@ static DecodeStatus DecodeBlezGroupBranch(MCInst &MI, InsnType insn,
InsnType Rs = fieldFromInstruction(insn, 21, 5);
InsnType Rt = fieldFromInstruction(insn, 16, 5);
- InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4;
+ int64_t Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 4 + 4;
bool HasRs = false;
if (Rt == 0)
@@ -917,6 +1017,17 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
Size = 4;
return Result;
}
+
+ if (hasMips32r6() && isFP64()) {
+ DEBUG(dbgs() << "Trying MicroMips32r6FP64 table (32-bit opcodes):\n");
+ Result = decodeInstruction(DecoderTableMicroMips32r6FP6432, Instr, Insn,
+ Address, this, STI);
+ if (Result != MCDisassembler::Fail) {
+ Size = 4;
+ return Result;
+ }
+ }
+
// This is an invalid instruction. Let the disassembler move forward by the
// minimum instruction size.
Size = 2;
@@ -949,6 +1060,16 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
}
}
+ if (hasMips32r6() && isPTR64()) {
+ DEBUG(dbgs() << "Trying Mips32r6_64r6 (PTR64) table (32-bit opcodes):\n");
+ Result = decodeInstruction(DecoderTableMips32r6_64r6_PTR6432, Instr, Insn,
+ Address, this, STI);
+ if (Result != MCDisassembler::Fail) {
+ Size = 4;
+ return Result;
+ }
+ }
+
if (hasMips32r6()) {
DEBUG(dbgs() << "Trying Mips32r6_64r6 table (32-bit opcodes):\n");
Result = decodeInstruction(DecoderTableMips32r6_64r632, Instr, Insn,
@@ -959,6 +1080,16 @@ DecodeStatus MipsDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
}
}
+ if (hasMips2() && isPTR64()) {
+ DEBUG(dbgs() << "Trying Mips32r6_64r6 (PTR64) table (32-bit opcodes):\n");
+ Result = decodeInstruction(DecoderTableMips32_64_PTR6432, Instr, Insn,
+ Address, this, STI);
+ if (Result != MCDisassembler::Fail) {
+ Size = 4;
+ return Result;
+ }
+ }
+
if (hasCnMips()) {
DEBUG(dbgs() << "Trying CnMips table (32-bit opcodes):\n");
Result = decodeInstruction(DecoderTableCnMips32, Instr, Insn,
@@ -1534,7 +1665,8 @@ static DecodeStatus DecodeMemMMImm12(MCInst &Inst,
// fallthrough
default:
Inst.addOperand(MCOperand::createReg(Reg));
- if (Inst.getOpcode() == Mips::LWP_MM || Inst.getOpcode() == Mips::SWP_MM)
+ if (Inst.getOpcode() == Mips::LWP_MM || Inst.getOpcode() == Mips::SWP_MM ||
+ Inst.getOpcode() == Mips::LWP_MMR6 || Inst.getOpcode() == Mips::SWP_MMR6)
Inst.addOperand(MCOperand::createReg(Reg+1));
Inst.addOperand(MCOperand::createReg(Base));
@@ -1580,6 +1712,24 @@ static DecodeStatus DecodeFMem(MCInst &Inst,
return MCDisassembler::Success;
}
+static DecodeStatus DecodeFMemMMR2(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ // This function is the same as DecodeFMem but with the Reg and Base fields
+ // swapped according to microMIPS spec.
+ int Offset = SignExtend32<16>(Insn & 0xffff);
+ unsigned Base = fieldFromInstruction(Insn, 16, 5);
+ unsigned Reg = fieldFromInstruction(Insn, 21, 5);
+
+ Reg = getReg(Decoder, Mips::FGR64RegClassID, Reg);
+ Base = getReg(Decoder, Mips::GPR32RegClassID, Base);
+
+ Inst.addOperand(MCOperand::createReg(Reg));
+ Inst.addOperand(MCOperand::createReg(Base));
+ Inst.addOperand(MCOperand::createImm(Offset));
+
+ return MCDisassembler::Success;
+}
+
static DecodeStatus DecodeFMem2(MCInst &Inst,
unsigned Insn,
uint64_t Address,
@@ -1633,6 +1783,23 @@ static DecodeStatus DecodeFMemCop2R6(MCInst &Inst,
return MCDisassembler::Success;
}
+
+static DecodeStatus DecodeFMemCop2MMR6(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ int Offset = SignExtend32<11>(Insn & 0x07ff);
+ unsigned Reg = fieldFromInstruction(Insn, 21, 5);
+ unsigned Base = fieldFromInstruction(Insn, 16, 5);
+
+ Reg = getReg(Decoder, Mips::COP2RegClassID, Reg);
+ Base = getReg(Decoder, Mips::GPR32RegClassID, Base);
+
+ Inst.addOperand(MCOperand::createReg(Reg));
+ Inst.addOperand(MCOperand::createReg(Base));
+ Inst.addOperand(MCOperand::createImm(Offset));
+
+ return MCDisassembler::Success;
+}
+
static DecodeStatus DecodeSpecial3LlSc(MCInst &Inst,
unsigned Insn,
uint64_t Address,
@@ -1808,6 +1975,15 @@ static DecodeStatus DecodeBranchTarget(MCInst &Inst,
return MCDisassembler::Success;
}
+static DecodeStatus DecodeBranchTarget1SImm16(MCInst &Inst,
+ unsigned Offset,
+ uint64_t Address,
+ const void *Decoder) {
+ int32_t BranchOffset = (SignExtend32<16>(Offset) * 2);
+ Inst.addOperand(MCOperand::createImm(BranchOffset));
+ return MCDisassembler::Success;
+}
+
static DecodeStatus DecodeJumpTarget(MCInst &Inst,
unsigned Insn,
uint64_t Address,
@@ -1822,7 +1998,17 @@ static DecodeStatus DecodeBranchTarget21(MCInst &Inst,
unsigned Offset,
uint64_t Address,
const void *Decoder) {
- int32_t BranchOffset = SignExtend32<21>(Offset) * 4;
+ int32_t BranchOffset = SignExtend32<21>(Offset) * 4 + 4;
+
+ Inst.addOperand(MCOperand::createImm(BranchOffset));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeBranchTarget21MM(MCInst &Inst,
+ unsigned Offset,
+ uint64_t Address,
+ const void *Decoder) {
+ int32_t BranchOffset = SignExtend32<21>(Offset) << 1;
Inst.addOperand(MCOperand::createImm(BranchOffset));
return MCDisassembler::Success;
@@ -1832,7 +2018,7 @@ static DecodeStatus DecodeBranchTarget26(MCInst &Inst,
unsigned Offset,
uint64_t Address,
const void *Decoder) {
- int32_t BranchOffset = SignExtend32<26>(Offset) * 4;
+ int32_t BranchOffset = SignExtend32<26>(Offset) * 4 + 4;
Inst.addOperand(MCOperand::createImm(BranchOffset));
return MCDisassembler::Success;
@@ -1897,15 +2083,7 @@ static DecodeStatus DecodeAddiur2Simm7(MCInst &Inst,
return MCDisassembler::Success;
}
-static DecodeStatus DecodeUImm6Lsl2(MCInst &Inst,
- unsigned Value,
- uint64_t Address,
- const void *Decoder) {
- Inst.addOperand(MCOperand::createImm(Value << 2));
- return MCDisassembler::Success;
-}
-
-static DecodeStatus DecodeLiSimm7(MCInst &Inst,
+static DecodeStatus DecodeLi16Imm(MCInst &Inst,
unsigned Value,
uint64_t Address,
const void *Decoder) {
@@ -1924,28 +2102,22 @@ static DecodeStatus DecodePOOL16BEncodedField(MCInst &Inst,
return MCDisassembler::Success;
}
-static DecodeStatus DecodeSimm4(MCInst &Inst,
- unsigned Value,
- uint64_t Address,
- const void *Decoder) {
- Inst.addOperand(MCOperand::createImm(SignExtend32<4>(Value)));
- return MCDisassembler::Success;
-}
-
-static DecodeStatus DecodeSimm16(MCInst &Inst,
- unsigned Insn,
- uint64_t Address,
- const void *Decoder) {
- Inst.addOperand(MCOperand::createImm(SignExtend32<16>(Insn)));
+template <unsigned Bits, int Offset, int Scale>
+static DecodeStatus DecodeUImmWithOffsetAndScale(MCInst &Inst, unsigned Value,
+ uint64_t Address,
+ const void *Decoder) {
+ Value &= ((1 << Bits) - 1);
+ Value *= Scale;
+ Inst.addOperand(MCOperand::createImm(Value + Offset));
return MCDisassembler::Success;
}
-template <unsigned Bits, int Offset>
-static DecodeStatus DecodeUImmWithOffset(MCInst &Inst, unsigned Value,
- uint64_t Address,
- const void *Decoder) {
- Value &= ((1 << Bits) - 1);
- Inst.addOperand(MCOperand::createImm(Value + Offset));
+template <unsigned Bits, int Offset, int ScaleBy>
+static DecodeStatus DecodeSImmWithOffsetAndScale(MCInst &Inst, unsigned Value,
+ uint64_t Address,
+ const void *Decoder) {
+ int32_t Imm = SignExtend32<Bits>(Value) * ScaleBy;
+ Inst.addOperand(MCOperand::createImm(Imm + Offset));
return MCDisassembler::Success;
}
@@ -1996,12 +2168,6 @@ static DecodeStatus DecodeANDI16Imm(MCInst &Inst, unsigned Insn,
return MCDisassembler::Success;
}
-static DecodeStatus DecodeUImm5lsl2(MCInst &Inst, unsigned Insn,
- uint64_t Address, const void *Decoder) {
- Inst.addOperand(MCOperand::createImm(Insn << 2));
- return MCDisassembler::Success;
-}
-
static DecodeStatus DecodeRegListOperand(MCInst &Inst,
unsigned Insn,
uint64_t Address,
@@ -2105,3 +2271,87 @@ static DecodeStatus DecodeSimm23Lsl2(MCInst &Inst, unsigned Insn,
Inst.addOperand(MCOperand::createImm(SignExtend32<25>(Insn << 2)));
return MCDisassembler::Success;
}
+
+template <typename InsnType>
+static DecodeStatus DecodeBgtzGroupBranchMMR6(MCInst &MI, InsnType insn,
+ uint64_t Address,
+ const void *Decoder) {
+ // We have:
+ // 0b000111 ttttt sssss iiiiiiiiiiiiiiii
+ // Invalid if rt == 0
+ // BGTZALC_MMR6 if rs == 0 && rt != 0
+ // BLTZALC_MMR6 if rs != 0 && rs == rt
+ // BLTUC_MMR6 if rs != 0 && rs != rt
+
+ InsnType Rt = fieldFromInstruction(insn, 21, 5);
+ InsnType Rs = fieldFromInstruction(insn, 16, 5);
+ InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 2;
+ bool HasRs = false;
+ bool HasRt = false;
+
+ if (Rt == 0)
+ return MCDisassembler::Fail;
+ else if (Rs == 0) {
+ MI.setOpcode(Mips::BGTZALC_MMR6);
+ HasRt = true;
+ }
+ else if (Rs == Rt) {
+ MI.setOpcode(Mips::BLTZALC_MMR6);
+ HasRs = true;
+ }
+ else {
+ MI.setOpcode(Mips::BLTUC_MMR6);
+ HasRs = true;
+ HasRt = true;
+ }
+
+ if (HasRs)
+ MI.addOperand(
+ MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, Rs)));
+
+ if (HasRt)
+ MI.addOperand(
+ MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, Rt)));
+
+ MI.addOperand(MCOperand::createImm(Imm));
+
+ return MCDisassembler::Success;
+}
+
+template <typename InsnType>
+static DecodeStatus DecodeBlezGroupBranchMMR6(MCInst &MI, InsnType insn,
+ uint64_t Address,
+ const void *Decoder) {
+ // We have:
+ // 0b000110 ttttt sssss iiiiiiiiiiiiiiii
+ // Invalid if rs == 0
+ // BLEZALC_MMR6 if rs == 0 && rt != 0
+ // BGEZALC_MMR6 if rs == rt && rt != 0
+ // BGEUC_MMR6 if rs != rt && rs != 0 && rt != 0
+
+ InsnType Rt = fieldFromInstruction(insn, 21, 5);
+ InsnType Rs = fieldFromInstruction(insn, 16, 5);
+ InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) * 2;
+ bool HasRs = false;
+
+ if (Rt == 0)
+ return MCDisassembler::Fail;
+ else if (Rs == 0)
+ MI.setOpcode(Mips::BLEZALC_MMR6);
+ else if (Rs == Rt)
+ MI.setOpcode(Mips::BGEZALC_MMR6);
+ else {
+ HasRs = true;
+ MI.setOpcode(Mips::BGEUC_MMR6);
+ }
+
+ if (HasRs)
+ MI.addOperand(
+ MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, Rs)));
+ MI.addOperand(
+ MCOperand::createReg(getReg(Decoder, Mips::GPR32RegClassID, Rt)));
+
+ MI.addOperand(MCOperand::createImm(Imm));
+
+ return MCDisassembler::Success;
+}
diff --git a/lib/Target/Mips/InstPrinter/Makefile b/lib/Target/Mips/InstPrinter/Makefile
deleted file mode 100644
index f07f3ed381ee2..0000000000000
--- a/lib/Target/Mips/InstPrinter/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-##===- lib/Target/Mips/AsmPrinter/Makefile -----------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LEVEL = ../../../..
-LIBRARYNAME = LLVMMipsAsmPrinter
-
-# Hack: we need to include 'main' mips target directory to grab private headers
-CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
-
-include $(LEVEL)/Makefile.common
diff --git a/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp b/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp
index a7b7d2e080eeb..0fd593fcfbe16 100644
--- a/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp
+++ b/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp
@@ -122,70 +122,6 @@ void MipsInstPrinter::printInst(const MCInst *MI, raw_ostream &O,
}
}
-static void printExpr(const MCExpr *Expr, const MCAsmInfo *MAI,
- raw_ostream &OS) {
- int Offset = 0;
- const MCSymbolRefExpr *SRE;
-
- if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
- SRE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
- const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(BE->getRHS());
- assert(SRE && CE && "Binary expression must be sym+const.");
- Offset = CE->getValue();
- } else if (const MipsMCExpr *ME = dyn_cast<MipsMCExpr>(Expr)) {
- ME->print(OS, MAI);
- return;
- } else
- SRE = cast<MCSymbolRefExpr>(Expr);
-
- MCSymbolRefExpr::VariantKind Kind = SRE->getKind();
-
- switch (Kind) {
- default: llvm_unreachable("Invalid kind!");
- case MCSymbolRefExpr::VK_None: break;
- case MCSymbolRefExpr::VK_Mips_GPREL: OS << "%gp_rel("; break;
- case MCSymbolRefExpr::VK_Mips_GOT_CALL: OS << "%call16("; break;
- case MCSymbolRefExpr::VK_Mips_GOT16: OS << "%got("; break;
- case MCSymbolRefExpr::VK_Mips_GOT: OS << "%got("; break;
- case MCSymbolRefExpr::VK_Mips_ABS_HI: OS << "%hi("; break;
- case MCSymbolRefExpr::VK_Mips_ABS_LO: OS << "%lo("; break;
- case MCSymbolRefExpr::VK_Mips_TLSGD: OS << "%tlsgd("; break;
- case MCSymbolRefExpr::VK_Mips_TLSLDM: OS << "%tlsldm("; break;
- case MCSymbolRefExpr::VK_Mips_DTPREL_HI: OS << "%dtprel_hi("; break;
- case MCSymbolRefExpr::VK_Mips_DTPREL_LO: OS << "%dtprel_lo("; break;
- case MCSymbolRefExpr::VK_Mips_GOTTPREL: OS << "%gottprel("; break;
- case MCSymbolRefExpr::VK_Mips_TPREL_HI: OS << "%tprel_hi("; break;
- case MCSymbolRefExpr::VK_Mips_TPREL_LO: OS << "%tprel_lo("; break;
- case MCSymbolRefExpr::VK_Mips_GPOFF_HI: OS << "%hi(%neg(%gp_rel("; break;
- case MCSymbolRefExpr::VK_Mips_GPOFF_LO: OS << "%lo(%neg(%gp_rel("; break;
- case MCSymbolRefExpr::VK_Mips_GOT_DISP: OS << "%got_disp("; break;
- case MCSymbolRefExpr::VK_Mips_GOT_PAGE: OS << "%got_page("; break;
- case MCSymbolRefExpr::VK_Mips_GOT_OFST: OS << "%got_ofst("; break;
- case MCSymbolRefExpr::VK_Mips_HIGHER: OS << "%higher("; break;
- case MCSymbolRefExpr::VK_Mips_HIGHEST: OS << "%highest("; break;
- case MCSymbolRefExpr::VK_Mips_GOT_HI16: OS << "%got_hi("; break;
- case MCSymbolRefExpr::VK_Mips_GOT_LO16: OS << "%got_lo("; break;
- case MCSymbolRefExpr::VK_Mips_CALL_HI16: OS << "%call_hi("; break;
- case MCSymbolRefExpr::VK_Mips_CALL_LO16: OS << "%call_lo("; break;
- case MCSymbolRefExpr::VK_Mips_PCREL_HI16: OS << "%pcrel_hi("; break;
- case MCSymbolRefExpr::VK_Mips_PCREL_LO16: OS << "%pcrel_lo("; break;
- }
-
- SRE->getSymbol().print(OS, MAI);
-
- if (Offset) {
- if (Offset > 0)
- OS << '+';
- OS << Offset;
- }
-
- if ((Kind == MCSymbolRefExpr::VK_Mips_GPOFF_HI) ||
- (Kind == MCSymbolRefExpr::VK_Mips_GPOFF_LO))
- OS << ")))";
- else if (Kind != MCSymbolRefExpr::VK_None)
- OS << ')';
-}
-
void MipsInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {
const MCOperand &Op = MI->getOperand(OpNo);
@@ -195,30 +131,27 @@ void MipsInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
}
if (Op.isImm()) {
- O << Op.getImm();
+ O << formatImm(Op.getImm());
return;
}
assert(Op.isExpr() && "unknown operand kind in printOperand");
- printExpr(Op.getExpr(), &MAI, O);
+ Op.getExpr()->print(O, &MAI, true);
}
-void MipsInstPrinter::printUnsignedImm(const MCInst *MI, int opNum,
- raw_ostream &O) {
+template <unsigned Bits, unsigned Offset>
+void MipsInstPrinter::printUImm(const MCInst *MI, int opNum, raw_ostream &O) {
const MCOperand &MO = MI->getOperand(opNum);
- if (MO.isImm())
- O << (unsigned short int)MO.getImm();
- else
- printOperand(MI, opNum, O);
-}
+ if (MO.isImm()) {
+ uint64_t Imm = MO.getImm();
+ Imm -= Offset;
+ Imm &= (1 << Bits) - 1;
+ Imm += Offset;
+ O << formatImm(Imm);
+ return;
+ }
-void MipsInstPrinter::printUnsignedImm8(const MCInst *MI, int opNum,
- raw_ostream &O) {
- const MCOperand &MO = MI->getOperand(opNum);
- if (MO.isImm())
- O << (unsigned short int)(unsigned char)MO.getImm();
- else
- printOperand(MI, opNum, O);
+ printOperand(MI, opNum, O);
}
void MipsInstPrinter::
@@ -325,6 +258,7 @@ bool MipsInstPrinter::printAlias(const MCInst &MI, raw_ostream &OS) {
return isReg<Mips::RA_64>(MI, 0) && printAlias("jalr", MI, 1, OS);
case Mips::NOR:
case Mips::NOR_MM:
+ case Mips::NOR_MMR6:
// nor $r0, $r1, $zero => not $r0, $r1
return isReg<Mips::ZERO>(MI, 2) && printAlias("not", MI, 0, 1, OS);
case Mips::NOR64:
@@ -343,7 +277,7 @@ void MipsInstPrinter::printSaveRestore(const MCInst *MI, raw_ostream &O) {
if (MI->getOperand(i).isReg())
printRegName(O, MI->getOperand(i).getReg());
else
- printUnsignedImm(MI, i, O);
+ printUImm<16>(MI, i, O);
}
}
diff --git a/lib/Target/Mips/InstPrinter/MipsInstPrinter.h b/lib/Target/Mips/InstPrinter/MipsInstPrinter.h
index 0e61ea61899a3..4a76b5acac790 100644
--- a/lib/Target/Mips/InstPrinter/MipsInstPrinter.h
+++ b/lib/Target/Mips/InstPrinter/MipsInstPrinter.h
@@ -93,8 +93,8 @@ public:
private:
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
- void printUnsignedImm(const MCInst *MI, int opNum, raw_ostream &O);
- void printUnsignedImm8(const MCInst *MI, int opNum, raw_ostream &O);
+ template <unsigned Bits, unsigned Offset = 0>
+ void printUImm(const MCInst *MI, int opNum, raw_ostream &O);
void printMemOperand(const MCInst *MI, int opNum, raw_ostream &O);
void printMemOperandEA(const MCInst *MI, int opNum, raw_ostream &O);
void printFCCOperand(const MCInst *MI, int opNum, raw_ostream &O);
diff --git a/lib/Target/Mips/MCTargetDesc/Makefile b/lib/Target/Mips/MCTargetDesc/Makefile
deleted file mode 100644
index 22a27218f28d5..0000000000000
--- a/lib/Target/Mips/MCTargetDesc/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-##===- lib/Target/Mips/TargetDesc/Makefile -----------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LEVEL = ../../../..
-LIBRARYNAME = LLVMMipsDesc
-
-# Hack: we need to include 'main' target directory to grab private headers
-CPP.Flags += -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
-
-include $(LEVEL)/Makefile.common
-
diff --git a/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp b/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp
index 70b9cca8cf6e7..932d38a0b9fe2 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp
+++ b/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.cpp
@@ -53,17 +53,17 @@ uint8_t MipsABIFlagsSection::getCPR1SizeValue() {
namespace llvm {
MCStreamer &operator<<(MCStreamer &OS, MipsABIFlagsSection &ABIFlagsSection) {
// Write out a Elf_Internal_ABIFlags_v0 struct
- OS.EmitIntValue(ABIFlagsSection.getVersionValue(), 2); // version
- OS.EmitIntValue(ABIFlagsSection.getISALevelValue(), 1); // isa_level
- OS.EmitIntValue(ABIFlagsSection.getISARevisionValue(), 1); // isa_rev
- OS.EmitIntValue(ABIFlagsSection.getGPRSizeValue(), 1); // gpr_size
- OS.EmitIntValue(ABIFlagsSection.getCPR1SizeValue(), 1); // cpr1_size
- OS.EmitIntValue(ABIFlagsSection.getCPR2SizeValue(), 1); // cpr2_size
- OS.EmitIntValue(ABIFlagsSection.getFpABIValue(), 1); // fp_abi
- OS.EmitIntValue(ABIFlagsSection.getISAExtensionSetValue(), 4); // isa_ext
- OS.EmitIntValue(ABIFlagsSection.getASESetValue(), 4); // ases
- OS.EmitIntValue(ABIFlagsSection.getFlags1Value(), 4); // flags1
- OS.EmitIntValue(ABIFlagsSection.getFlags2Value(), 4); // flags2
+ OS.EmitIntValue(ABIFlagsSection.getVersionValue(), 2); // version
+ OS.EmitIntValue(ABIFlagsSection.getISALevelValue(), 1); // isa_level
+ OS.EmitIntValue(ABIFlagsSection.getISARevisionValue(), 1); // isa_rev
+ OS.EmitIntValue(ABIFlagsSection.getGPRSizeValue(), 1); // gpr_size
+ OS.EmitIntValue(ABIFlagsSection.getCPR1SizeValue(), 1); // cpr1_size
+ OS.EmitIntValue(ABIFlagsSection.getCPR2SizeValue(), 1); // cpr2_size
+ OS.EmitIntValue(ABIFlagsSection.getFpABIValue(), 1); // fp_abi
+ OS.EmitIntValue(ABIFlagsSection.getISAExtensionValue(), 4); // isa_ext
+ OS.EmitIntValue(ABIFlagsSection.getASESetValue(), 4); // ases
+ OS.EmitIntValue(ABIFlagsSection.getFlags1Value(), 4); // flags1
+ OS.EmitIntValue(ABIFlagsSection.getFlags2Value(), 4); // flags2
return OS;
}
}
diff --git a/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h b/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h
index b078cd30a87bd..3966cae9fe33d 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h
+++ b/lib/Target/Mips/MCTargetDesc/MipsABIFlagsSection.h
@@ -35,7 +35,7 @@ struct MipsABIFlagsSection {
// The size of co-processor 2 registers.
Mips::AFL_REG CPR2Size;
// Processor-specific extension.
- uint32_t ISAExtensionSet;
+ Mips::AFL_EXT ISAExtension;
// Mask of ASEs used.
uint32_t ASESet;
@@ -51,8 +51,8 @@ public:
MipsABIFlagsSection()
: Version(0), ISALevel(0), ISARevision(0), GPRSize(Mips::AFL_REG_NONE),
CPR1Size(Mips::AFL_REG_NONE), CPR2Size(Mips::AFL_REG_NONE),
- ISAExtensionSet(0), ASESet(0), OddSPReg(false), Is32BitABI(false),
- FpABI(FpABIKind::ANY) {}
+ ISAExtension(Mips::AFL_EXT_NONE), ASESet(0), OddSPReg(false),
+ Is32BitABI(false), FpABI(FpABIKind::ANY) {}
uint16_t getVersionValue() { return (uint16_t)Version; }
uint8_t getISALevelValue() { return (uint8_t)ISALevel; }
@@ -61,7 +61,7 @@ public:
uint8_t getCPR1SizeValue();
uint8_t getCPR2SizeValue() { return (uint8_t)CPR2Size; }
uint8_t getFpABIValue();
- uint32_t getISAExtensionSetValue() { return (uint32_t)ISAExtensionSet; }
+ uint32_t getISAExtensionValue() { return (uint32_t)ISAExtension; }
uint32_t getASESetValue() { return (uint32_t)ASESet; }
uint32_t getFlags1Value() {
@@ -141,6 +141,14 @@ public:
}
template <class PredicateLibrary>
+ void setISAExtensionFromPredicates(const PredicateLibrary &P) {
+ if (P.hasCnMips())
+ ISAExtension = Mips::AFL_EXT_OCTEON;
+ else
+ ISAExtension = Mips::AFL_EXT_NONE;
+ }
+
+ template <class PredicateLibrary>
void setASESetFromPredicates(const PredicateLibrary &P) {
ASESet = 0;
if (P.hasDSP())
@@ -179,6 +187,7 @@ public:
setISALevelAndRevisionFromPredicates(P);
setGPRSizeFromPredicates(P);
setCPR1SizeFromPredicates(P);
+ setISAExtensionFromPredicates(P);
setASESetFromPredicates(P);
setFpAbiFromPredicates(P);
OddSPReg = P.useOddSPReg();
diff --git a/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp b/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp
index cdcc3923b81e6..3cf632e789dea 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp
+++ b/lib/Target/Mips/MCTargetDesc/MipsABIInfo.cpp
@@ -42,7 +42,7 @@ ArrayRef<MCPhysReg> MipsABIInfo::GetVarArgRegs() const {
unsigned MipsABIInfo::GetCalleeAllocdArgSizeInBytes(CallingConv::ID CC) const {
if (IsO32())
return CC != CallingConv::Fast ? 16 : 0;
- if (IsN32() || IsN64() || IsEABI())
+ if (IsN32() || IsN64())
return 0;
llvm_unreachable("Unhandled ABI");
}
@@ -55,39 +55,12 @@ MipsABIInfo MipsABIInfo::computeTargetABI(const Triple &TT, StringRef CPU,
return MipsABIInfo::N32();
else if (Options.getABIName().startswith("n64"))
return MipsABIInfo::N64();
- else if (Options.getABIName().startswith("eabi"))
- return MipsABIInfo::EABI();
else if (!Options.getABIName().empty())
llvm_unreachable("Unknown ABI option for MIPS");
- // FIXME: This shares code with the selectMipsCPU routine that's
- // used and not shared in a couple of other places. This needs unifying
- // at some level.
- if (CPU.empty() || CPU == "generic") {
- if (TT.getArch() == Triple::mips || TT.getArch() == Triple::mipsel)
- CPU = "mips32";
- else
- CPU = "mips64";
- }
-
- return StringSwitch<MipsABIInfo>(CPU)
- .Case("mips1", MipsABIInfo::O32())
- .Case("mips2", MipsABIInfo::O32())
- .Case("mips32", MipsABIInfo::O32())
- .Case("mips32r2", MipsABIInfo::O32())
- .Case("mips32r3", MipsABIInfo::O32())
- .Case("mips32r5", MipsABIInfo::O32())
- .Case("mips32r6", MipsABIInfo::O32())
- .Case("mips3", MipsABIInfo::N64())
- .Case("mips4", MipsABIInfo::N64())
- .Case("mips5", MipsABIInfo::N64())
- .Case("mips64", MipsABIInfo::N64())
- .Case("mips64r2", MipsABIInfo::N64())
- .Case("mips64r3", MipsABIInfo::N64())
- .Case("mips64r5", MipsABIInfo::N64())
- .Case("mips64r6", MipsABIInfo::N64())
- .Case("octeon", MipsABIInfo::N64())
- .Default(MipsABIInfo::Unknown());
+ if (TT.getArch() == Triple::mips64 || TT.getArch() == Triple::mips64el)
+ return MipsABIInfo::N64();
+ return MipsABIInfo::O32();
}
unsigned MipsABIInfo::GetStackPtr() const {
@@ -102,6 +75,10 @@ unsigned MipsABIInfo::GetBasePtr() const {
return ArePtrs64bit() ? Mips::S7_64 : Mips::S7;
}
+unsigned MipsABIInfo::GetGlobalPtr() const {
+ return ArePtrs64bit() ? Mips::GP_64 : Mips::GP;
+}
+
unsigned MipsABIInfo::GetNullPtr() const {
return ArePtrs64bit() ? Mips::ZERO_64 : Mips::ZERO;
}
@@ -118,6 +95,14 @@ unsigned MipsABIInfo::GetPtrAddiuOp() const {
return ArePtrs64bit() ? Mips::DADDiu : Mips::ADDiu;
}
+unsigned MipsABIInfo::GetPtrSubuOp() const {
+ return ArePtrs64bit() ? Mips::DSUBu : Mips::SUBu;
+}
+
+unsigned MipsABIInfo::GetPtrAndOp() const {
+ return ArePtrs64bit() ? Mips::AND64 : Mips::AND;
+}
+
unsigned MipsABIInfo::GetGPRMoveOp() const {
return ArePtrs64bit() ? Mips::OR64 : Mips::OR;
}
diff --git a/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h b/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h
index ffa2c765e79bc..9372a3c2bb1f8 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h
+++ b/lib/Target/Mips/MCTargetDesc/MipsABIInfo.h
@@ -10,20 +10,20 @@
#ifndef LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSABIINFO_H
#define LLVM_LIB_TARGET_MIPS_MCTARGETDESC_MIPSABIINFO_H
-#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/MC/MCRegisterInfo.h"
namespace llvm {
+template <typename T> class ArrayRef;
class MCTargetOptions;
class StringRef;
class TargetRegisterClass;
class MipsABIInfo {
public:
- enum class ABI { Unknown, O32, N32, N64, EABI };
+ enum class ABI { Unknown, O32, N32, N64 };
protected:
ABI ThisABI;
@@ -35,7 +35,6 @@ public:
static MipsABIInfo O32() { return MipsABIInfo(ABI::O32); }
static MipsABIInfo N32() { return MipsABIInfo(ABI::N32); }
static MipsABIInfo N64() { return MipsABIInfo(ABI::N64); }
- static MipsABIInfo EABI() { return MipsABIInfo(ABI::EABI); }
static MipsABIInfo computeTargetABI(const Triple &TT, StringRef CPU,
const MCTargetOptions &Options);
@@ -43,7 +42,6 @@ public:
bool IsO32() const { return ThisABI == ABI::O32; }
bool IsN32() const { return ThisABI == ABI::N32; }
bool IsN64() const { return ThisABI == ABI::N64; }
- bool IsEABI() const { return ThisABI == ABI::EABI; }
ABI GetEnumValue() const { return ThisABI; }
/// The registers to use for byval arguments.
@@ -66,10 +64,13 @@ public:
unsigned GetStackPtr() const;
unsigned GetFramePtr() const;
unsigned GetBasePtr() const;
+ unsigned GetGlobalPtr() const;
unsigned GetNullPtr() const;
unsigned GetZeroReg() const;
unsigned GetPtrAdduOp() const;
unsigned GetPtrAddiuOp() const;
+ unsigned GetPtrSubuOp() const;
+ unsigned GetPtrAndOp() const;
unsigned GetGPRMoveOp() const;
inline bool ArePtrs64bit() const { return IsN64(); }
inline bool AreGprs64bit() const { return IsN32() || IsN64(); }
diff --git a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
index e4865e2455ee4..8292d6b4c55aa 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
+++ b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
@@ -14,6 +14,7 @@
#include "MCTargetDesc/MipsFixupKinds.h"
#include "MCTargetDesc/MipsAsmBackend.h"
+#include "MCTargetDesc/MipsMCExpr.h"
#include "MCTargetDesc/MipsMCTargetDesc.h"
#include "llvm/MC/MCAsmBackend.h"
#include "llvm/MC/MCAssembler.h"
@@ -23,7 +24,9 @@
#include "llvm/MC/MCFixupKindInfo.h"
#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSubtargetInfo.h"
+#include "llvm/MC/MCValue.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Format.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
@@ -40,9 +43,6 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
default:
return 0;
case FK_Data_2:
- case FK_GPRel_4:
- case FK_Data_4:
- case FK_Data_8:
case Mips::fixup_Mips_LO16:
case Mips::fixup_Mips_GPREL16:
case Mips::fixup_Mips_GPOFF_HI:
@@ -57,6 +57,11 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
case Mips::fixup_MICROMIPS_GOT_OFST:
case Mips::fixup_MICROMIPS_GOT_DISP:
case Mips::fixup_MIPS_PCLO16:
+ Value &= 0xffff;
+ break;
+ case FK_GPRel_4:
+ case FK_Data_4:
+ case FK_Data_8:
break;
case Mips::fixup_Mips_PC16:
// The displacement is then divided by 4 to give us an 18 bit
@@ -69,6 +74,7 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
}
break;
case Mips::fixup_MIPS_PC19_S2:
+ case Mips::fixup_MICROMIPS_PC19_S2:
// Forcing a signed division because Value can be negative.
Value = (int64_t)Value / 4;
// We now check if Value can be encoded as a 19-bit signed immediate.
@@ -84,7 +90,8 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
Value >>= 2;
break;
case Mips::fixup_Mips_HI16:
- case Mips::fixup_Mips_GOT_Local:
+ case Mips::fixup_Mips_GOT:
+ case Mips::fixup_MICROMIPS_GOT16:
case Mips::fixup_Mips_GOT_HI16:
case Mips::fixup_Mips_CALL_HI16:
case Mips::fixup_MICROMIPS_HI16:
@@ -142,6 +149,19 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
return 0;
}
break;
+ case Mips::fixup_MICROMIPS_PC18_S3:
+ // Check alignment.
+ if ((Value & 7) && Ctx) {
+ Ctx->reportError(Fixup.getLoc(), "out of range PC18 fixup");
+ }
+ // Forcing a signed division because Value can be negative.
+ Value = (int64_t)Value / 8;
+ // We now check if Value can be encoded as a 18-bit signed immediate.
+ if (!isInt<18>(Value) && Ctx) {
+ Ctx->reportError(Fixup.getLoc(), "out of range PC18 fixup");
+ return 0;
+ }
+ break;
case Mips::fixup_MIPS_PC21_S2:
// Forcing a signed division because Value can be negative.
Value = (int64_t) Value / 4;
@@ -160,6 +180,24 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
return 0;
}
break;
+ case Mips::fixup_MICROMIPS_PC26_S1:
+ // Forcing a signed division because Value can be negative.
+ Value = (int64_t)Value / 2;
+ // We now check if Value can be encoded as a 26-bit signed immediate.
+ if (!isInt<26>(Value) && Ctx) {
+ Ctx->reportFatalError(Fixup.getLoc(), "out of range PC26 fixup");
+ return 0;
+ }
+ break;
+ case Mips::fixup_MICROMIPS_PC21_S1:
+ // Forcing a signed division because Value can be negative.
+ Value = (int64_t)Value / 2;
+ // We now check if Value can be encoded as a 21-bit signed immediate.
+ if (!isInt<21>(Value) && Ctx) {
+ Ctx->reportError(Fixup.getLoc(), "out of range PC21 fixup");
+ return 0;
+ }
+ break;
}
return Value;
@@ -248,16 +286,11 @@ void MipsAsmBackend::applyFixup(const MCFixup &Fixup, char *Data,
}
}
-bool MipsAsmBackend::getFixupKind(StringRef Name, MCFixupKind &MappedKind) const {
- if (Name == "R_MIPS_NONE") {
- MappedKind = (MCFixupKind)Mips::fixup_Mips_NONE;
- return true;
- }
- if (Name == "R_MIPS_32") {
- MappedKind = FK_Data_4;
- return true;
- }
- return MCAsmBackend::getFixupKind(Name, MappedKind);
+Optional<MCFixupKind> MipsAsmBackend::getFixupKind(StringRef Name) const {
+ return StringSwitch<Optional<MCFixupKind>>(Name)
+ .Case("R_MIPS_NONE", (MCFixupKind)Mips::fixup_Mips_NONE)
+ .Case("R_MIPS_32", FK_Data_4)
+ .Default(MCAsmBackend::getFixupKind(Name));
}
const MCFixupKindInfo &MipsAsmBackend::
@@ -276,8 +309,7 @@ getFixupKindInfo(MCFixupKind Kind) const {
{ "fixup_Mips_LO16", 0, 16, 0 },
{ "fixup_Mips_GPREL16", 0, 16, 0 },
{ "fixup_Mips_LITERAL", 0, 16, 0 },
- { "fixup_Mips_GOT_Global", 0, 16, 0 },
- { "fixup_Mips_GOT_Local", 0, 16, 0 },
+ { "fixup_Mips_GOT", 0, 16, 0 },
{ "fixup_Mips_PC16", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Mips_CALL16", 0, 16, 0 },
{ "fixup_Mips_GPREL32", 0, 32, 0 },
@@ -316,6 +348,10 @@ getFixupKindInfo(MCFixupKind Kind) const {
{ "fixup_MICROMIPS_PC7_S1", 0, 7, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_MICROMIPS_PC10_S1", 0, 10, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_MICROMIPS_PC16_S1", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_MICROMIPS_PC26_S1", 0, 26, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_MICROMIPS_PC19_S2", 0, 19, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_MICROMIPS_PC18_S3", 0, 18, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_MICROMIPS_PC21_S1", 0, 21, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_MICROMIPS_CALL16", 0, 16, 0 },
{ "fixup_MICROMIPS_GOT_DISP", 0, 16, 0 },
{ "fixup_MICROMIPS_GOT_PAGE", 0, 16, 0 },
@@ -342,8 +378,7 @@ getFixupKindInfo(MCFixupKind Kind) const {
{ "fixup_Mips_LO16", 16, 16, 0 },
{ "fixup_Mips_GPREL16", 16, 16, 0 },
{ "fixup_Mips_LITERAL", 16, 16, 0 },
- { "fixup_Mips_GOT_Global", 16, 16, 0 },
- { "fixup_Mips_GOT_Local", 16, 16, 0 },
+ { "fixup_Mips_GOT", 16, 16, 0 },
{ "fixup_Mips_PC16", 16, 16, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_Mips_CALL16", 16, 16, 0 },
{ "fixup_Mips_GPREL32", 0, 32, 0 },
@@ -382,6 +417,10 @@ getFixupKindInfo(MCFixupKind Kind) const {
{ "fixup_MICROMIPS_PC7_S1", 9, 7, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_MICROMIPS_PC10_S1", 6, 10, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_MICROMIPS_PC16_S1",16, 16, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_MICROMIPS_PC26_S1", 6, 26, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_MICROMIPS_PC19_S2",13, 19, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_MICROMIPS_PC18_S3",14, 18, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_MICROMIPS_PC21_S1",11, 21, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_MICROMIPS_CALL16", 16, 16, 0 },
{ "fixup_MICROMIPS_GOT_DISP", 16, 16, 0 },
{ "fixup_MICROMIPS_GOT_PAGE", 16, 16, 0 },
@@ -435,6 +474,8 @@ void MipsAsmBackend::processFixupValue(const MCAssembler &Asm,
// we are only checking if the fixup can be applied correctly. We have
// access to MCContext from here which allows us to report a fatal error
// with *possibly* a source code location.
+ // The caller will also ignore any changes we make to Value
+ // (recordRelocation() overwrites it with it's own calculation).
(void)adjustFixupValue(Fixup, Value, &Asm.getContext());
}
diff --git a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h
index 1c9af9227ffe5..f260cfa566c90 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h
+++ b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h
@@ -41,7 +41,7 @@ public:
void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
uint64_t Value, bool IsPCRel) const override;
- bool getFixupKind(StringRef Name, MCFixupKind &MappedKind) const override;
+ Optional<MCFixupKind> getFixupKind(StringRef Name) const override;
const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override;
unsigned getNumFixupKinds() const override {
@@ -75,7 +75,8 @@ public:
/// \param Inst - The instruction to relax, which may be the same
/// as the output.
/// \param [out] Res On return, the relaxed instruction.
- void relaxInstruction(const MCInst &Inst, MCInst &Res) const override {}
+ void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
+ MCInst &Res) const override {}
/// @}
diff --git a/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h b/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h
index ff7779ec1e789..2bcff881788c4 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h
+++ b/lib/Target/Mips/MCTargetDesc/MipsBaseInfo.h
@@ -33,9 +33,8 @@ namespace MipsII {
MO_NO_FLAG,
- /// MO_GOT16 - Represents the offset into the global offset table at which
+ /// MO_GOT - Represents the offset into the global offset table at which
/// the address the relocation entry symbol resides during execution.
- MO_GOT16,
MO_GOT,
/// MO_GOT_CALL - Represents the offset into the global offset table at
@@ -117,7 +116,12 @@ namespace MipsII {
/// FrmOther - This form is for instructions that have no specific format.
FrmOther = 6,
- FormMask = 15
+ FormMask = 15,
+ /// IsCTI - Instruction is a Control Transfer Instruction.
+ IsCTI = 1 << 4,
+ /// HasForbiddenSlot - Instruction has a forbidden slot.
+ HasForbiddenSlot = 1 << 5
+
};
}
}
diff --git a/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp b/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp
index 5b9f02b89be5d..cdad7ce1b73a5 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp
+++ b/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp
@@ -7,8 +7,11 @@
//
//===----------------------------------------------------------------------===//
+#include <algorithm>
+#include <list>
#include "MCTargetDesc/MipsBaseInfo.h"
#include "MCTargetDesc/MipsFixupKinds.h"
+#include "MCTargetDesc/MipsMCExpr.h"
#include "MCTargetDesc/MipsMCTargetDesc.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/MC/MCAssembler.h"
@@ -17,42 +20,190 @@
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSymbolELF.h"
#include "llvm/MC/MCValue.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
-#include <list>
+
+#define DEBUG_TYPE "mips-elf-object-writer"
using namespace llvm;
namespace {
-// A helper structure based on ELFRelocationEntry, used for sorting entries in
-// the relocation table.
+/// Holds additional information needed by the relocation ordering algorithm.
struct MipsRelocationEntry {
- MipsRelocationEntry(const ELFRelocationEntry &R)
- : R(R), SortOffset(R.Offset), HasMatchingHi(false) {}
- const ELFRelocationEntry R;
- // SortOffset equals R.Offset except for the *HI16 relocations, for which it
- // will be set based on the R.Offset of the matching *LO16 relocation.
- int64_t SortOffset;
- // True when this is a *LO16 relocation chosen as a match for a *HI16
- // relocation.
- bool HasMatchingHi;
+ const ELFRelocationEntry R; ///< The relocation.
+ bool Matched; ///< Is this relocation part of a match.
+
+ MipsRelocationEntry(const ELFRelocationEntry &R) : R(R), Matched(false) {}
+
+ void print(raw_ostream &Out) const {
+ R.print(Out);
+ Out << ", Matched=" << Matched;
+ }
+};
+
+#ifndef NDEBUG
+raw_ostream &operator<<(raw_ostream &OS, const MipsRelocationEntry &RHS) {
+ RHS.print(OS);
+ return OS;
+}
+#endif
+
+class MipsELFObjectWriter : public MCELFObjectTargetWriter {
+public:
+ MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI, bool _isN64,
+ bool IsLittleEndian);
+
+ ~MipsELFObjectWriter() override;
+
+ unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
+ const MCFixup &Fixup, bool IsPCRel) const override;
+ bool needsRelocateWithSymbol(const MCSymbol &Sym,
+ unsigned Type) const override;
+ virtual void sortRelocs(const MCAssembler &Asm,
+ std::vector<ELFRelocationEntry> &Relocs) override;
+};
+
+/// Copy elements in the range [First, Last) to d1 when the predicate is true or
+/// d2 when the predicate is false. This is essentially both std::copy_if and
+/// std::remove_copy_if combined into a single pass.
+template <class InputIt, class OutputIt1, class OutputIt2, class UnaryPredicate>
+std::pair<OutputIt1, OutputIt2> copy_if_else(InputIt First, InputIt Last,
+ OutputIt1 d1, OutputIt2 d2,
+ UnaryPredicate Predicate) {
+ for (InputIt I = First; I != Last; ++I) {
+ if (Predicate(*I)) {
+ *d1 = *I;
+ d1++;
+ } else {
+ *d2 = *I;
+ d2++;
+ }
+ }
+
+ return std::make_pair(d1, d2);
+}
+
+/// The possible results of the Predicate function used by find_best.
+enum FindBestPredicateResult {
+ FindBest_NoMatch = 0, ///< The current element is not a match.
+ FindBest_Match, ///< The current element is a match but better ones are
+ /// possible.
+ FindBest_PerfectMatch, ///< The current element is an unbeatable match.
};
- class MipsELFObjectWriter : public MCELFObjectTargetWriter {
- public:
- MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI,
- bool _isN64, bool IsLittleEndian);
+/// Find the best match in the range [First, Last).
+///
+/// An element matches when Predicate(X) returns FindBest_Match or
+/// FindBest_PerfectMatch. A value of FindBest_PerfectMatch also terminates
+/// the search. BetterThan(A, B) is a comparator that returns true when A is a
+/// better match than B. The return value is the position of the best match.
+///
+/// This is similar to std::find_if but finds the best of multiple possible
+/// matches.
+template <class InputIt, class UnaryPredicate, class Comparator>
+InputIt find_best(InputIt First, InputIt Last, UnaryPredicate Predicate,
+ Comparator BetterThan) {
+ InputIt Best = Last;
+
+ for (InputIt I = First; I != Last; ++I) {
+ unsigned Matched = Predicate(*I);
+ if (Matched != FindBest_NoMatch) {
+ DEBUG(dbgs() << std::distance(First, I) << " is a match (";
+ I->print(dbgs()); dbgs() << ")\n");
+ if (Best == Last || BetterThan(*I, *Best)) {
+ DEBUG(dbgs() << ".. and it beats the last one\n");
+ Best = I;
+ }
+ }
+ if (Matched == FindBest_PerfectMatch) {
+ DEBUG(dbgs() << ".. and it is unbeatable\n");
+ break;
+ }
+ }
+
+ return Best;
+}
+
+/// Determine the low relocation that matches the given relocation.
+/// If the relocation does not need a low relocation then the return value
+/// is ELF::R_MIPS_NONE.
+///
+/// The relocations that need a matching low part are
+/// R_(MIPS|MICROMIPS|MIPS16)_HI16 for all symbols and
+/// R_(MIPS|MICROMIPS|MIPS16)_GOT16 for local symbols only.
+static unsigned getMatchingLoType(const ELFRelocationEntry &Reloc) {
+ unsigned Type = Reloc.Type;
+ if (Type == ELF::R_MIPS_HI16)
+ return ELF::R_MIPS_LO16;
+ if (Type == ELF::R_MICROMIPS_HI16)
+ return ELF::R_MICROMIPS_LO16;
+ if (Type == ELF::R_MIPS16_HI16)
+ return ELF::R_MIPS16_LO16;
+
+ if (Reloc.OriginalSymbol->getBinding() != ELF::STB_LOCAL)
+ return ELF::R_MIPS_NONE;
+
+ if (Type == ELF::R_MIPS_GOT16)
+ return ELF::R_MIPS_LO16;
+ if (Type == ELF::R_MICROMIPS_GOT16)
+ return ELF::R_MICROMIPS_LO16;
+ if (Type == ELF::R_MIPS16_GOT16)
+ return ELF::R_MIPS16_LO16;
+
+ return ELF::R_MIPS_NONE;
+}
- ~MipsELFObjectWriter() override;
+/// Determine whether a relocation (X) matches the one given in R.
+///
+/// A relocation matches if:
+/// - It's type matches that of a corresponding low part. This is provided in
+/// MatchingType for efficiency.
+/// - It's based on the same symbol.
+/// - It's offset of greater or equal to that of the one given in R.
+/// It should be noted that this rule assumes the programmer does not use
+/// offsets that exceed the alignment of the symbol. The carry-bit will be
+/// incorrect if this is not true.
+///
+/// A matching relocation is unbeatable if:
+/// - It is not already involved in a match.
+/// - It's offset is exactly that of the one given in R.
+static FindBestPredicateResult isMatchingReloc(const MipsRelocationEntry &X,
+ const ELFRelocationEntry &R,
+ unsigned MatchingType) {
+ if (X.R.Type == MatchingType && X.R.OriginalSymbol == R.OriginalSymbol) {
+ if (!X.Matched &&
+ X.R.OriginalAddend == R.OriginalAddend)
+ return FindBest_PerfectMatch;
+ else if (X.R.OriginalAddend >= R.OriginalAddend)
+ return FindBest_Match;
+ }
+ return FindBest_NoMatch;
+}
- unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
- bool IsPCRel) const override;
- bool needsRelocateWithSymbol(const MCSymbol &Sym,
- unsigned Type) const override;
- virtual void sortRelocs(const MCAssembler &Asm,
- std::vector<ELFRelocationEntry> &Relocs) override;
- };
+/// Determine whether Candidate or PreviousBest is the better match.
+/// The return value is true if Candidate is the better match.
+///
+/// A matching relocation is a better match if:
+/// - It has a smaller addend.
+/// - It is not already involved in a match.
+static bool compareMatchingRelocs(const MipsRelocationEntry &Candidate,
+ const MipsRelocationEntry &PreviousBest) {
+ if (Candidate.R.OriginalAddend != PreviousBest.R.OriginalAddend)
+ return Candidate.R.OriginalAddend < PreviousBest.R.OriginalAddend;
+ return PreviousBest.Matched && !Candidate.Matched;
}
+#ifndef NDEBUG
+/// Print all the relocations.
+template <class Container>
+static void dumpRelocs(const char *Prefix, const Container &Relocs) {
+ for (const auto &R : Relocs)
+ dbgs() << Prefix << R << "\n";
+}
+#endif
+
+} // end anonymous namespace
+
MipsELFObjectWriter::MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI,
bool _isN64, bool IsLittleEndian)
: MCELFObjectTargetWriter(_is64Bit, OSABI, ELF::EM_MIPS,
@@ -61,7 +212,8 @@ MipsELFObjectWriter::MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI,
MipsELFObjectWriter::~MipsELFObjectWriter() {}
-unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target,
+unsigned MipsELFObjectWriter::getRelocType(MCContext &Ctx,
+ const MCValue &Target,
const MCFixup &Fixup,
bool IsPCRel) const {
// Determine the type of the relocation.
@@ -89,6 +241,14 @@ unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target,
return ELF::R_MICROMIPS_PC10_S1;
case Mips::fixup_MICROMIPS_PC16_S1:
return ELF::R_MICROMIPS_PC16_S1;
+ case Mips::fixup_MICROMIPS_PC26_S1:
+ return ELF::R_MICROMIPS_PC26_S1;
+ case Mips::fixup_MICROMIPS_PC19_S2:
+ return ELF::R_MICROMIPS_PC19_S2;
+ case Mips::fixup_MICROMIPS_PC18_S3:
+ return ELF::R_MICROMIPS_PC18_S3;
+ case Mips::fixup_MICROMIPS_PC21_S1:
+ return ELF::R_MICROMIPS_PC21_S1;
case Mips::fixup_MIPS_PC19_S2:
return ELF::R_MIPS_PC19_S2;
case Mips::fixup_MIPS_PC18_S3:
@@ -125,8 +285,7 @@ unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target,
return ELF::R_MIPS_26;
case Mips::fixup_Mips_CALL16:
return ELF::R_MIPS_CALL16;
- case Mips::fixup_Mips_GOT_Global:
- case Mips::fixup_Mips_GOT_Local:
+ case Mips::fixup_Mips_GOT:
return ELF::R_MIPS_GOT16;
case Mips::fixup_Mips_HI16:
return ELF::R_MIPS_HI16;
@@ -211,213 +370,266 @@ unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target,
llvm_unreachable("invalid fixup kind!");
}
-// Sort entries by SortOffset in descending order.
-// When there are more *HI16 relocs paired with one *LO16 reloc, the 2nd rule
-// sorts them in ascending order of R.Offset.
-static int cmpRelMips(const MipsRelocationEntry *AP,
- const MipsRelocationEntry *BP) {
- const MipsRelocationEntry &A = *AP;
- const MipsRelocationEntry &B = *BP;
- if (A.SortOffset != B.SortOffset)
- return B.SortOffset - A.SortOffset;
- if (A.R.Offset != B.R.Offset)
- return A.R.Offset - B.R.Offset;
- if (B.R.Type != A.R.Type)
- return B.R.Type - A.R.Type;
- //llvm_unreachable("ELFRelocs might be unstable!");
- return 0;
-}
-
-// For the given Reloc.Type, return the matching relocation type, as in the
-// table below.
-static unsigned getMatchingLoType(const MCAssembler &Asm,
- const ELFRelocationEntry &Reloc) {
- unsigned Type = Reloc.Type;
- if (Type == ELF::R_MIPS_HI16)
- return ELF::R_MIPS_LO16;
- if (Type == ELF::R_MICROMIPS_HI16)
- return ELF::R_MICROMIPS_LO16;
- if (Type == ELF::R_MIPS16_HI16)
- return ELF::R_MIPS16_LO16;
-
- if (Reloc.Symbol->getBinding() != ELF::STB_LOCAL)
- return ELF::R_MIPS_NONE;
-
- if (Type == ELF::R_MIPS_GOT16)
- return ELF::R_MIPS_LO16;
- if (Type == ELF::R_MICROMIPS_GOT16)
- return ELF::R_MICROMIPS_LO16;
- if (Type == ELF::R_MIPS16_GOT16)
- return ELF::R_MIPS16_LO16;
-
- return ELF::R_MIPS_NONE;
-}
-
-// Return true if First needs a matching *LO16, its matching *LO16 type equals
-// Second's type and both relocations are against the same symbol.
-static bool areMatchingHiAndLo(const MCAssembler &Asm,
- const ELFRelocationEntry &First,
- const ELFRelocationEntry &Second) {
- return getMatchingLoType(Asm, First) != ELF::R_MIPS_NONE &&
- getMatchingLoType(Asm, First) == Second.Type &&
- First.Symbol && First.Symbol == Second.Symbol;
-}
-
-// Return true if MipsRelocs[Index] is a *LO16 preceded by a matching *HI16.
-static bool
-isPrecededByMatchingHi(const MCAssembler &Asm, uint32_t Index,
- std::vector<MipsRelocationEntry> &MipsRelocs) {
- return Index < MipsRelocs.size() - 1 &&
- areMatchingHiAndLo(Asm, MipsRelocs[Index + 1].R, MipsRelocs[Index].R);
-}
-
-// Return true if MipsRelocs[Index] is a *LO16 not preceded by a matching *HI16
-// and not chosen by a *HI16 as a match.
-static bool isFreeLo(const MCAssembler &Asm, uint32_t Index,
- std::vector<MipsRelocationEntry> &MipsRelocs) {
- return Index < MipsRelocs.size() && !MipsRelocs[Index].HasMatchingHi &&
- !isPrecededByMatchingHi(Asm, Index, MipsRelocs);
-}
-
-// Lo is chosen as a match for Hi, set their fields accordingly.
-// Mips instructions have fixed length of at least two bytes (two for
-// micromips/mips16, four for mips32/64), so we can set HI's SortOffset to
-// matching LO's Offset minus one to simplify the sorting function.
-static void setMatch(MipsRelocationEntry &Hi, MipsRelocationEntry &Lo) {
- Lo.HasMatchingHi = true;
- Hi.SortOffset = Lo.R.Offset - 1;
-}
-
-// We sort relocation table entries by offset, except for one additional rule
-// required by MIPS ABI: every *HI16 relocation must be immediately followed by
-// the corresponding *LO16 relocation. We also support a GNU extension that
-// allows more *HI16s paired with one *LO16.
-//
-// *HI16 relocations and their matching *LO16 are:
-//
-// +---------------------------------------------+-------------------+
-// | *HI16 | matching *LO16 |
-// |---------------------------------------------+-------------------|
-// | R_MIPS_HI16, local R_MIPS_GOT16 | R_MIPS_LO16 |
-// | R_MICROMIPS_HI16, local R_MICROMIPS_GOT16 | R_MICROMIPS_LO16 |
-// | R_MIPS16_HI16, local R_MIPS16_GOT16 | R_MIPS16_LO16 |
-// +---------------------------------------------+-------------------+
-//
-// (local R_*_GOT16 meaning R_*_GOT16 against the local symbol.)
-//
-// To handle *HI16 and *LO16 relocations, the linker needs a combined addend
-// ("AHL") calculated from both *HI16 ("AHI") and *LO16 ("ALO") relocations:
-// AHL = (AHI << 16) + (short)ALO;
-//
-// We are reusing gnu as sorting algorithm so we are emitting the relocation
-// table sorted the same way as gnu as would sort it, for easier comparison of
-// the generated .o files.
-//
-// The logic is:
-// search the table (starting from the highest offset and going back to zero)
-// for all *HI16 relocations that don't have a matching *LO16.
-// For every such HI, find a matching LO with highest offset that isn't already
-// matched with another HI. If there are no free LOs, match it with the first
-// found (starting from lowest offset).
-// When there are more HIs matched with one LO, sort them in descending order by
-// offset.
-//
-// In other words, when searching for a matching LO:
-// - don't look for a 'better' match for the HIs that are already followed by a
-// matching LO;
-// - prefer LOs without a pair;
-// - prefer LOs with higher offset;
-
-static int cmpRel(const ELFRelocationEntry *AP, const ELFRelocationEntry *BP) {
- const ELFRelocationEntry &A = *AP;
- const ELFRelocationEntry &B = *BP;
- if (A.Offset != B.Offset)
- return B.Offset - A.Offset;
- if (B.Type != A.Type)
- return A.Type - B.Type;
- return 0;
-}
-
+/// Sort relocation table entries by offset except where another order is
+/// required by the MIPS ABI.
+///
+/// MIPS has a few relocations that have an AHL component in the expression used
+/// to evaluate them. This AHL component is an addend with the same number of
+/// bits as a symbol value but not all of our ABI's are able to supply a
+/// sufficiently sized addend in a single relocation.
+///
+/// The O32 ABI for example, uses REL relocations which store the addend in the
+/// section data. All the relocations with AHL components affect 16-bit fields
+/// so the addend for a single relocation is limited to 16-bit. This ABI
+/// resolves the limitation by linking relocations (e.g. R_MIPS_HI16 and
+/// R_MIPS_LO16) and distributing the addend between the linked relocations. The
+/// ABI mandates that such relocations must be next to each other in a
+/// particular order (e.g. R_MIPS_HI16 must be immediately followed by a
+/// matching R_MIPS_LO16) but the rule is less strict in practice.
+///
+/// The de facto standard is lenient in the following ways:
+/// - 'Immediately following' does not refer to the next relocation entry but
+/// the next matching relocation.
+/// - There may be multiple high parts relocations for one low part relocation.
+/// - There may be multiple low part relocations for one high part relocation.
+/// - The AHL addend in each part does not have to be exactly equal as long as
+/// the difference does not affect the carry bit from bit 15 into 16. This is
+/// to allow, for example, the use of %lo(foo) and %lo(foo+4) when loading
+/// both halves of a long long.
+///
+/// See getMatchingLoType() for a description of which high part relocations
+/// match which low part relocations. One particular thing to note is that
+/// R_MIPS_GOT16 and similar only have AHL addends if they refer to local
+/// symbols.
+///
+/// It should also be noted that this function is not affected by whether
+/// the symbol was kept or rewritten into a section-relative equivalent. We
+/// always match using the expressions from the source.
void MipsELFObjectWriter::sortRelocs(const MCAssembler &Asm,
std::vector<ELFRelocationEntry> &Relocs) {
if (Relocs.size() < 2)
return;
- // Sorts entries by Offset in descending order.
- array_pod_sort(Relocs.begin(), Relocs.end(), cmpRel);
-
- // Init MipsRelocs from Relocs.
- std::vector<MipsRelocationEntry> MipsRelocs;
- for (unsigned I = 0, E = Relocs.size(); I != E; ++I)
- MipsRelocs.push_back(MipsRelocationEntry(Relocs[I]));
-
- // Find a matching LO for all HIs that need it.
- for (int32_t I = 0, E = MipsRelocs.size(); I != E; ++I) {
- if (getMatchingLoType(Asm, MipsRelocs[I].R) == ELF::R_MIPS_NONE ||
- (I > 0 && isPrecededByMatchingHi(Asm, I - 1, MipsRelocs)))
- continue;
-
- int32_t MatchedLoIndex = -1;
-
- // Search the list in the ascending order of Offset.
- for (int32_t J = MipsRelocs.size() - 1, N = -1; J != N; --J) {
- // check for a match
- if (areMatchingHiAndLo(Asm, MipsRelocs[I].R, MipsRelocs[J].R) &&
- (MatchedLoIndex == -1 || // first match
- // or we already have a match,
- // but this one is with higher offset and it's free
- (MatchedLoIndex > J && isFreeLo(Asm, J, MipsRelocs))))
- MatchedLoIndex = J;
- }
-
- if (MatchedLoIndex != -1)
- // We have a match.
- setMatch(MipsRelocs[I], MipsRelocs[MatchedLoIndex]);
+ // Sort relocations by the address they are applied to.
+ std::sort(Relocs.begin(), Relocs.end(),
+ [](const ELFRelocationEntry &A, const ELFRelocationEntry &B) {
+ return A.Offset < B.Offset;
+ });
+
+ std::list<MipsRelocationEntry> Sorted;
+ std::list<ELFRelocationEntry> Remainder;
+
+ DEBUG(dumpRelocs("R: ", Relocs));
+
+ // Separate the movable relocations (AHL relocations using the high bits) from
+ // the immobile relocations (everything else). This does not preserve high/low
+ // matches that already existed in the input.
+ copy_if_else(Relocs.begin(), Relocs.end(), std::back_inserter(Remainder),
+ std::back_inserter(Sorted), [](const ELFRelocationEntry &Reloc) {
+ return getMatchingLoType(Reloc) != ELF::R_MIPS_NONE;
+ });
+
+ for (auto &R : Remainder) {
+ DEBUG(dbgs() << "Matching: " << R << "\n");
+
+ unsigned MatchingType = getMatchingLoType(R);
+ assert(MatchingType != ELF::R_MIPS_NONE &&
+ "Wrong list for reloc that doesn't need a match");
+
+ // Find the best matching relocation for the current high part.
+ // See isMatchingReloc for a description of a matching relocation and
+ // compareMatchingRelocs for a description of what 'best' means.
+ auto InsertionPoint =
+ find_best(Sorted.begin(), Sorted.end(),
+ [&R, &MatchingType](const MipsRelocationEntry &X) {
+ return isMatchingReloc(X, R, MatchingType);
+ },
+ compareMatchingRelocs);
+
+ // If we matched then insert the high part in front of the match and mark
+ // both relocations as being involved in a match. We only mark the high
+ // part for cosmetic reasons in the debug output.
+ //
+ // If we failed to find a match then the high part is orphaned. This is not
+ // permitted since the relocation cannot be evaluated without knowing the
+ // carry-in. We can sometimes handle this using a matching low part that is
+ // already used in a match but we already cover that case in
+ // isMatchingReloc and compareMatchingRelocs. For the remaining cases we
+ // should insert the high part at the end of the list. This will cause the
+ // linker to fail but the alternative is to cause the linker to bind the
+ // high part to a semi-matching low part and silently calculate the wrong
+ // value. Unfortunately we have no means to warn the user that we did this
+ // so leave it up to the linker to complain about it.
+ if (InsertionPoint != Sorted.end())
+ InsertionPoint->Matched = true;
+ Sorted.insert(InsertionPoint, R)->Matched = true;
}
- // SortOffsets are calculated, call the sorting function.
- array_pod_sort(MipsRelocs.begin(), MipsRelocs.end(), cmpRelMips);
+ DEBUG(dumpRelocs("S: ", Sorted));
+
+ assert(Relocs.size() == Sorted.size() && "Some relocs were not consumed");
- // Copy sorted MipsRelocs back to Relocs.
- for (unsigned I = 0, E = MipsRelocs.size(); I != E; ++I)
- Relocs[I] = MipsRelocs[I].R;
+ // Overwrite the original vector with the sorted elements. The caller expects
+ // them in reverse order.
+ unsigned CopyTo = 0;
+ for (const auto &R : reverse(Sorted))
+ Relocs[CopyTo++] = R.R;
}
bool MipsELFObjectWriter::needsRelocateWithSymbol(const MCSymbol &Sym,
unsigned Type) const {
- // FIXME: This is extremely conservative. This really needs to use a
- // whitelist with a clear explanation for why each realocation needs to
- // point to the symbol, not to the section.
+ // If it's a compound relocation for N64 then we need the relocation if any
+ // sub-relocation needs it.
+ if (!isUInt<8>(Type))
+ return needsRelocateWithSymbol(Sym, Type & 0xff) ||
+ needsRelocateWithSymbol(Sym, (Type >> 8) & 0xff) ||
+ needsRelocateWithSymbol(Sym, (Type >> 16) & 0xff);
+
switch (Type) {
default:
+ errs() << Type << "\n";
+ llvm_unreachable("Unexpected relocation");
return true;
+ // This relocation doesn't affect the section data.
+ case ELF::R_MIPS_NONE:
+ return false;
+
+ // On REL ABI's (e.g. O32), these relocations form pairs. The pairing is done
+ // by the static linker by matching the symbol and offset.
+ // We only see one relocation at a time but it's still safe to relocate with
+ // the section so long as both relocations make the same decision.
+ //
+ // Some older linkers may require the symbol for particular cases. Such cases
+ // are not supported yet but can be added as required.
case ELF::R_MIPS_GOT16:
case ELF::R_MIPS16_GOT16:
case ELF::R_MICROMIPS_GOT16:
- llvm_unreachable("Should have been handled already");
-
- // These relocations might be paired with another relocation. The pairing is
- // done by the static linker by matching the symbol. Since we only see one
- // relocation at a time, we have to force them to relocate with a symbol to
- // avoid ending up with a pair where one points to a section and another
- // points to a symbol.
case ELF::R_MIPS_HI16:
case ELF::R_MIPS16_HI16:
case ELF::R_MICROMIPS_HI16:
case ELF::R_MIPS_LO16:
case ELF::R_MIPS16_LO16:
case ELF::R_MICROMIPS_LO16:
- return true;
+ // FIXME: It should be safe to return false for the STO_MIPS_MICROMIPS but
+ // we neglect to handle the adjustment to the LSB of the addend that
+ // it causes in applyFixup() and similar.
+ if (cast<MCSymbolELF>(Sym).getOther() & ELF::STO_MIPS_MICROMIPS)
+ return true;
+ return false;
+ case ELF::R_MIPS_16:
case ELF::R_MIPS_32:
+ case ELF::R_MIPS_GPREL32:
if (cast<MCSymbolELF>(Sym).getOther() & ELF::STO_MIPS_MICROMIPS)
return true;
- // falltrough
+ // fallthrough
case ELF::R_MIPS_26:
case ELF::R_MIPS_64:
case ELF::R_MIPS_GPREL16:
+ case ELF::R_MIPS_PC16:
+ case ELF::R_MIPS_SUB:
return false;
+
+ // FIXME: Many of these relocations should probably return false but this
+ // hasn't been confirmed to be safe yet.
+ case ELF::R_MIPS_REL32:
+ case ELF::R_MIPS_LITERAL:
+ case ELF::R_MIPS_CALL16:
+ case ELF::R_MIPS_SHIFT5:
+ case ELF::R_MIPS_SHIFT6:
+ case ELF::R_MIPS_GOT_DISP:
+ case ELF::R_MIPS_GOT_PAGE:
+ case ELF::R_MIPS_GOT_OFST:
+ case ELF::R_MIPS_GOT_HI16:
+ case ELF::R_MIPS_GOT_LO16:
+ case ELF::R_MIPS_INSERT_A:
+ case ELF::R_MIPS_INSERT_B:
+ case ELF::R_MIPS_DELETE:
+ case ELF::R_MIPS_HIGHER:
+ case ELF::R_MIPS_HIGHEST:
+ case ELF::R_MIPS_CALL_HI16:
+ case ELF::R_MIPS_CALL_LO16:
+ case ELF::R_MIPS_SCN_DISP:
+ case ELF::R_MIPS_REL16:
+ case ELF::R_MIPS_ADD_IMMEDIATE:
+ case ELF::R_MIPS_PJUMP:
+ case ELF::R_MIPS_RELGOT:
+ case ELF::R_MIPS_JALR:
+ case ELF::R_MIPS_TLS_DTPMOD32:
+ case ELF::R_MIPS_TLS_DTPREL32:
+ case ELF::R_MIPS_TLS_DTPMOD64:
+ case ELF::R_MIPS_TLS_DTPREL64:
+ case ELF::R_MIPS_TLS_GD:
+ case ELF::R_MIPS_TLS_LDM:
+ case ELF::R_MIPS_TLS_DTPREL_HI16:
+ case ELF::R_MIPS_TLS_DTPREL_LO16:
+ case ELF::R_MIPS_TLS_GOTTPREL:
+ case ELF::R_MIPS_TLS_TPREL32:
+ case ELF::R_MIPS_TLS_TPREL64:
+ case ELF::R_MIPS_TLS_TPREL_HI16:
+ case ELF::R_MIPS_TLS_TPREL_LO16:
+ case ELF::R_MIPS_GLOB_DAT:
+ case ELF::R_MIPS_PC21_S2:
+ case ELF::R_MIPS_PC26_S2:
+ case ELF::R_MIPS_PC18_S3:
+ case ELF::R_MIPS_PC19_S2:
+ case ELF::R_MIPS_PCHI16:
+ case ELF::R_MIPS_PCLO16:
+ case ELF::R_MIPS_COPY:
+ case ELF::R_MIPS_JUMP_SLOT:
+ case ELF::R_MIPS_NUM:
+ case ELF::R_MIPS_PC32:
+ case ELF::R_MIPS_EH:
+ case ELF::R_MICROMIPS_26_S1:
+ case ELF::R_MICROMIPS_GPREL16:
+ case ELF::R_MICROMIPS_LITERAL:
+ case ELF::R_MICROMIPS_PC7_S1:
+ case ELF::R_MICROMIPS_PC10_S1:
+ case ELF::R_MICROMIPS_PC16_S1:
+ case ELF::R_MICROMIPS_CALL16:
+ case ELF::R_MICROMIPS_GOT_DISP:
+ case ELF::R_MICROMIPS_GOT_PAGE:
+ case ELF::R_MICROMIPS_GOT_OFST:
+ case ELF::R_MICROMIPS_GOT_HI16:
+ case ELF::R_MICROMIPS_GOT_LO16:
+ case ELF::R_MICROMIPS_SUB:
+ case ELF::R_MICROMIPS_HIGHER:
+ case ELF::R_MICROMIPS_HIGHEST:
+ case ELF::R_MICROMIPS_CALL_HI16:
+ case ELF::R_MICROMIPS_CALL_LO16:
+ case ELF::R_MICROMIPS_SCN_DISP:
+ case ELF::R_MICROMIPS_JALR:
+ case ELF::R_MICROMIPS_HI0_LO16:
+ case ELF::R_MICROMIPS_TLS_GD:
+ case ELF::R_MICROMIPS_TLS_LDM:
+ case ELF::R_MICROMIPS_TLS_DTPREL_HI16:
+ case ELF::R_MICROMIPS_TLS_DTPREL_LO16:
+ case ELF::R_MICROMIPS_TLS_GOTTPREL:
+ case ELF::R_MICROMIPS_TLS_TPREL_HI16:
+ case ELF::R_MICROMIPS_TLS_TPREL_LO16:
+ case ELF::R_MICROMIPS_GPREL7_S2:
+ case ELF::R_MICROMIPS_PC23_S2:
+ case ELF::R_MICROMIPS_PC21_S1:
+ case ELF::R_MICROMIPS_PC26_S1:
+ case ELF::R_MICROMIPS_PC18_S3:
+ case ELF::R_MICROMIPS_PC19_S2:
+ return true;
+
+ // FIXME: Many of these should probably return false but MIPS16 isn't
+ // supported by the integrated assembler.
+ case ELF::R_MIPS16_26:
+ case ELF::R_MIPS16_GPREL:
+ case ELF::R_MIPS16_CALL16:
+ case ELF::R_MIPS16_TLS_GD:
+ case ELF::R_MIPS16_TLS_LDM:
+ case ELF::R_MIPS16_TLS_DTPREL_HI16:
+ case ELF::R_MIPS16_TLS_DTPREL_LO16:
+ case ELF::R_MIPS16_TLS_GOTTPREL:
+ case ELF::R_MIPS16_TLS_TPREL_HI16:
+ case ELF::R_MIPS16_TLS_TPREL_LO16:
+ llvm_unreachable("Unsupported MIPS16 relocation");
+ return true;
}
}
diff --git a/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h b/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h
index 3652f4bab0d43..b4d8e9494650a 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h
+++ b/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h
@@ -50,11 +50,8 @@ namespace Mips {
// 16 bit literal fixup resulting in - R_MIPS_LITERAL.
fixup_Mips_LITERAL,
- // Global symbol fixup resulting in - R_MIPS_GOT16.
- fixup_Mips_GOT_Global,
-
- // Local symbol fixup resulting in - R_MIPS_GOT16.
- fixup_Mips_GOT_Local,
+ // Symbol fixup resulting in - R_MIPS_GOT16.
+ fixup_Mips_GOT,
// PC relative branch fixup resulting in - R_MIPS_PC16.
fixup_Mips_PC16,
@@ -170,6 +167,18 @@ namespace Mips {
// resulting in - R_MICROMIPS_PC16_S1
fixup_MICROMIPS_PC16_S1,
+ // resulting in - R_MICROMIPS_PC26_S1
+ fixup_MICROMIPS_PC26_S1,
+
+ // resulting in - R_MICROMIPS_PC19_S2
+ fixup_MICROMIPS_PC19_S2,
+
+ // resulting in - R_MICROMIPS_PC18_S3
+ fixup_MICROMIPS_PC18_S3,
+
+ // resulting in - R_MICROMIPS_PC21_S1
+ fixup_MICROMIPS_PC21_S1,
+
// resulting in - R_MICROMIPS_CALL16
fixup_MICROMIPS_CALL16,
diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp
index 4d554583dc782..1622b22126653 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp
+++ b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.cpp
@@ -42,4 +42,9 @@ MipsMCAsmInfo::MipsMCAsmInfo(const Triple &TheTriple) {
SupportsDebugInformation = true;
ExceptionsType = ExceptionHandling::DwarfCFI;
DwarfRegNumForCFI = true;
+
+ // Enable IAS by default for O32.
+ if (TheTriple.getArch() == Triple::mips ||
+ TheTriple.getArch() == Triple::mipsel)
+ UseIntegratedAssembler = true;
}
diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
index 4b030ebfce8c5..401c7d42c4cea 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
+++ b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
@@ -78,19 +78,25 @@ static void LowerLargeShift(MCInst& Inst) {
case Mips::DROTR:
Inst.setOpcode(Mips::DROTR32);
return;
+ case Mips::DSLL_MM64R6:
+ Inst.setOpcode(Mips::DSLL32_MM64R6);
+ return;
+ case Mips::DSRL_MM64R6:
+ Inst.setOpcode(Mips::DSRL32_MM64R6);
+ return;
+ case Mips::DSRA_MM64R6:
+ Inst.setOpcode(Mips::DSRA32_MM64R6);
+ return;
+ case Mips::DROTR_MM64R6:
+ Inst.setOpcode(Mips::DROTR32_MM64R6);
+ return;
}
}
-// Pick a DEXT or DINS instruction variant based on the pos and size operands
-static void LowerDextDins(MCInst& InstIn) {
- int Opcode = InstIn.getOpcode();
-
- if (Opcode == Mips::DEXT)
- assert(InstIn.getNumOperands() == 4 &&
- "Invalid no. of machine operands for DEXT!");
- else // Only DEXT and DINS are possible
- assert(InstIn.getNumOperands() == 5 &&
- "Invalid no. of machine operands for DINS!");
+// Pick a DINS instruction variant based on the pos and size operands
+static void LowerDins(MCInst& InstIn) {
+ assert(InstIn.getNumOperands() == 5 &&
+ "Invalid no. of machine operands for DINS!");
assert(InstIn.getOperand(2).isImm());
int64_t pos = InstIn.getOperand(2).getImm();
@@ -98,20 +104,50 @@ static void LowerDextDins(MCInst& InstIn) {
int64_t size = InstIn.getOperand(3).getImm();
if (size <= 32) {
- if (pos < 32) // DEXT/DINS, do nothing
+ if (pos < 32) // DINS, do nothing
return;
- // DEXTU/DINSU
+ // DINSU
InstIn.getOperand(2).setImm(pos - 32);
- InstIn.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTU : Mips::DINSU);
+ InstIn.setOpcode(Mips::DINSU);
return;
}
- // DEXTM/DINSM
- assert(pos < 32 && "DEXT/DINS cannot have both size and pos > 32");
+ // DINSM
+ assert(pos < 32 && "DINS cannot have both size and pos > 32");
InstIn.getOperand(3).setImm(size - 32);
- InstIn.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTM : Mips::DINSM);
+ InstIn.setOpcode(Mips::DINSM);
return;
}
+// Fix a bad compact branch encoding for beqc/bnec.
+void MipsMCCodeEmitter::LowerCompactBranch(MCInst& Inst) const {
+
+ // Encoding may be illegal !(rs < rt), but this situation is
+ // easily fixed.
+ unsigned RegOp0 = Inst.getOperand(0).getReg();
+ unsigned RegOp1 = Inst.getOperand(1).getReg();
+
+ unsigned Reg0 = Ctx.getRegisterInfo()->getEncodingValue(RegOp0);
+ unsigned Reg1 = Ctx.getRegisterInfo()->getEncodingValue(RegOp1);
+
+ if (Inst.getOpcode() == Mips::BNEC || Inst.getOpcode() == Mips::BEQC) {
+ assert(Reg0 != Reg1 && "Instruction has bad operands ($rs == $rt)!");
+ if (Reg0 < Reg1)
+ return;
+ } else if (Inst.getOpcode() == Mips::BNVC || Inst.getOpcode() == Mips::BOVC) {
+ if (Reg0 >= Reg1)
+ return;
+ } else if (Inst.getOpcode() == Mips::BNVC_MMR6 ||
+ Inst.getOpcode() == Mips::BOVC_MMR6) {
+ if (Reg1 >= Reg0)
+ return;
+ } else
+ llvm_unreachable("Cannot rewrite unknown branch!");
+
+ Inst.getOperand(0).setReg(RegOp1);
+ Inst.getOperand(1).setReg(RegOp0);
+
+}
+
bool MipsMCCodeEmitter::isMicroMips(const MCSubtargetInfo &STI) const {
return STI.getFeatureBits()[Mips::FeatureMicroMips];
}
@@ -161,12 +197,24 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS,
case Mips::DSRL:
case Mips::DSRA:
case Mips::DROTR:
+ case Mips::DSLL_MM64R6:
+ case Mips::DSRL_MM64R6:
+ case Mips::DSRA_MM64R6:
+ case Mips::DROTR_MM64R6:
LowerLargeShift(TmpInst);
break;
// Double extract instruction is chosen by pos and size operands
- case Mips::DEXT:
case Mips::DINS:
- LowerDextDins(TmpInst);
+ LowerDins(TmpInst);
+ break;
+ // Compact branches, enforce encoding restrictions.
+ case Mips::BEQC:
+ case Mips::BNEC:
+ case Mips::BOVC:
+ case Mips::BOVC_MMR6:
+ case Mips::BNVC:
+ case Mips::BNVC_MMR6:
+ LowerCompactBranch(TmpInst);
}
unsigned long N = Fixups.size();
@@ -237,6 +285,53 @@ getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
return 0;
}
+/// getBranchTargetOpValue1SImm16 - Return binary encoding of the branch
+/// target operand. If the machine operand requires relocation,
+/// record the relocation and return zero.
+unsigned MipsMCCodeEmitter::
+getBranchTargetOpValue1SImm16(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+
+ const MCOperand &MO = MI.getOperand(OpNo);
+
+ // If the destination is an immediate, divide by 2.
+ if (MO.isImm()) return MO.getImm() >> 1;
+
+ assert(MO.isExpr() &&
+ "getBranchTargetOpValue expects only expressions or immediates");
+
+ const MCExpr *FixupExpression = MCBinaryExpr::createAdd(
+ MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx);
+ Fixups.push_back(MCFixup::create(0, FixupExpression,
+ MCFixupKind(Mips::fixup_Mips_PC16)));
+ return 0;
+}
+
+/// getBranchTargetOpValueMMR6 - Return binary encoding of the branch
+/// target operand. If the machine operand requires relocation,
+/// record the relocation and return zero.
+unsigned MipsMCCodeEmitter::
+getBranchTargetOpValueMMR6(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+
+ const MCOperand &MO = MI.getOperand(OpNo);
+
+ // If the destination is an immediate, divide by 2.
+ if (MO.isImm())
+ return MO.getImm() >> 1;
+
+ assert(MO.isExpr() &&
+ "getBranchTargetOpValueMMR6 expects only expressions or immediates");
+
+ const MCExpr *FixupExpression = MCBinaryExpr::createAdd(
+ MO.getExpr(), MCConstantExpr::create(-2, Ctx), Ctx);
+ Fixups.push_back(MCFixup::create(0, FixupExpression,
+ MCFixupKind(Mips::fixup_Mips_PC16)));
+ return 0;
+}
+
/// getBranchTarget7OpValueMM - Return binary encoding of the microMIPS branch
/// target operand. If the machine operand requires relocation,
/// record the relocation and return zero.
@@ -327,6 +422,29 @@ getBranchTarget21OpValue(const MCInst &MI, unsigned OpNo,
return 0;
}
+/// getBranchTarget21OpValueMM - Return binary encoding of the branch
+/// target operand for microMIPS. If the machine operand requires
+/// relocation, record the relocation and return zero.
+unsigned MipsMCCodeEmitter::
+getBranchTarget21OpValueMM(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+
+ const MCOperand &MO = MI.getOperand(OpNo);
+
+ // If the destination is an immediate, divide by 2.
+ if (MO.isImm()) return MO.getImm() >> 1;
+
+ assert(MO.isExpr() &&
+ "getBranchTarget21OpValueMM expects only expressions or immediates");
+
+ const MCExpr *FixupExpression = MCBinaryExpr::createAdd(
+ MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx);
+ Fixups.push_back(MCFixup::create(0, FixupExpression,
+ MCFixupKind(Mips::fixup_MICROMIPS_PC21_S1)));
+ return 0;
+}
+
/// getBranchTarget26OpValue - Return binary encoding of the branch
/// target operand. If the machine operand requires relocation,
/// record the relocation and return zero.
@@ -363,7 +481,13 @@ unsigned MipsMCCodeEmitter::getBranchTarget26OpValueMM(
if (MO.isImm())
return MO.getImm() >> 1;
- // TODO: Push 26 PC fixup.
+ assert(MO.isExpr() &&
+ "getBranchTarget26OpValueMM expects only expressions or immediates");
+
+ const MCExpr *FixupExpression = MCBinaryExpr::createAdd(
+ MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx);
+ Fixups.push_back(MCFixup::create(0, FixupExpression,
+ MCFixupKind(Mips::fixup_MICROMIPS_PC26_S1)));
return 0;
}
@@ -510,126 +634,117 @@ getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups,
Mips::Fixups FixupKind = Mips::Fixups(0);
switch (MipsExpr->getKind()) {
- default: llvm_unreachable("Unsupported fixup kind for target expression!");
- case MipsMCExpr::VK_Mips_HIGHEST:
- FixupKind = Mips::fixup_Mips_HIGHEST;
+ case MipsMCExpr::MEK_NEG:
+ case MipsMCExpr::MEK_None:
+ case MipsMCExpr::MEK_Special:
+ llvm_unreachable("Unhandled fixup kind!");
break;
- case MipsMCExpr::VK_Mips_HIGHER:
- FixupKind = Mips::fixup_Mips_HIGHER;
+ case MipsMCExpr::MEK_CALL_HI16:
+ FixupKind = Mips::fixup_Mips_CALL_HI16;
break;
- case MipsMCExpr::VK_Mips_HI:
- FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HI16
- : Mips::fixup_Mips_HI16;
+ case MipsMCExpr::MEK_CALL_LO16:
+ FixupKind = Mips::fixup_Mips_CALL_LO16;
break;
- case MipsMCExpr::VK_Mips_LO:
- FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16
- : Mips::fixup_Mips_LO16;
+ case MipsMCExpr::MEK_DTPREL_HI:
+ FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_HI16
+ : Mips::fixup_Mips_DTPREL_HI;
break;
- }
- Fixups.push_back(MCFixup::create(0, MipsExpr, MCFixupKind(FixupKind)));
- return 0;
- }
-
- if (Kind == MCExpr::SymbolRef) {
- Mips::Fixups FixupKind = Mips::Fixups(0);
-
- switch(cast<MCSymbolRefExpr>(Expr)->getKind()) {
- default: llvm_unreachable("Unknown fixup kind!");
+ case MipsMCExpr::MEK_DTPREL_LO:
+ FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_LO16
+ : Mips::fixup_Mips_DTPREL_LO;
break;
- case MCSymbolRefExpr::VK_None:
- FixupKind = Mips::fixup_Mips_32; // FIXME: This is ok for O32/N32 but not N64.
+ case MipsMCExpr::MEK_GOTTPREL:
+ FixupKind = Mips::fixup_Mips_GOTTPREL;
+ break;
+ case MipsMCExpr::MEK_GOT:
+ FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT16
+ : Mips::fixup_Mips_GOT;
+ break;
+ case MipsMCExpr::MEK_GOT_CALL:
+ FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_CALL16
+ : Mips::fixup_Mips_CALL16;
+ break;
+ case MipsMCExpr::MEK_GOT_DISP:
+ FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_DISP
+ : Mips::fixup_Mips_GOT_DISP;
break;
- case MCSymbolRefExpr::VK_Mips_GPOFF_HI :
- FixupKind = Mips::fixup_Mips_GPOFF_HI;
+ case MipsMCExpr::MEK_GOT_HI16:
+ FixupKind = Mips::fixup_Mips_GOT_HI16;
break;
- case MCSymbolRefExpr::VK_Mips_GPOFF_LO :
- FixupKind = Mips::fixup_Mips_GPOFF_LO;
+ case MipsMCExpr::MEK_GOT_LO16:
+ FixupKind = Mips::fixup_Mips_GOT_LO16;
break;
- case MCSymbolRefExpr::VK_Mips_GOT_PAGE :
+ case MipsMCExpr::MEK_GOT_PAGE:
FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_PAGE
- : Mips::fixup_Mips_GOT_PAGE;
+ : Mips::fixup_Mips_GOT_PAGE;
break;
- case MCSymbolRefExpr::VK_Mips_GOT_OFST :
+ case MipsMCExpr::MEK_GOT_OFST:
FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_OFST
- : Mips::fixup_Mips_GOT_OFST;
+ : Mips::fixup_Mips_GOT_OFST;
break;
- case MCSymbolRefExpr::VK_Mips_GOT_DISP :
- FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_DISP
- : Mips::fixup_Mips_GOT_DISP;
- break;
- case MCSymbolRefExpr::VK_Mips_GPREL:
+ case MipsMCExpr::MEK_GPREL:
FixupKind = Mips::fixup_Mips_GPREL16;
break;
- case MCSymbolRefExpr::VK_Mips_GOT_CALL:
- FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_CALL16
- : Mips::fixup_Mips_CALL16;
+ case MipsMCExpr::MEK_LO: {
+ // Check for %lo(%neg(%gp_rel(X)))
+ if (MipsExpr->isGpOff()) {
+ FixupKind = Mips::fixup_Mips_GPOFF_LO;
+ break;
+ }
+ FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16
+ : Mips::fixup_Mips_LO16;
break;
- case MCSymbolRefExpr::VK_Mips_GOT16:
- FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT16
- : Mips::fixup_Mips_GOT_Global;
+ }
+ case MipsMCExpr::MEK_HIGHEST:
+ FixupKind = Mips::fixup_Mips_HIGHEST;
break;
- case MCSymbolRefExpr::VK_Mips_GOT:
- FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT16
- : Mips::fixup_Mips_GOT_Local;
+ case MipsMCExpr::MEK_HIGHER:
+ FixupKind = Mips::fixup_Mips_HIGHER;
break;
- case MCSymbolRefExpr::VK_Mips_ABS_HI:
+ case MipsMCExpr::MEK_HI:
+ // Check for %hi(%neg(%gp_rel(X)))
+ if (MipsExpr->isGpOff()) {
+ FixupKind = Mips::fixup_Mips_GPOFF_HI;
+ break;
+ }
FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HI16
- : Mips::fixup_Mips_HI16;
+ : Mips::fixup_Mips_HI16;
break;
- case MCSymbolRefExpr::VK_Mips_ABS_LO:
- FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16
- : Mips::fixup_Mips_LO16;
+ case MipsMCExpr::MEK_PCREL_HI16:
+ FixupKind = Mips::fixup_MIPS_PCHI16;
+ break;
+ case MipsMCExpr::MEK_PCREL_LO16:
+ FixupKind = Mips::fixup_MIPS_PCLO16;
break;
- case MCSymbolRefExpr::VK_Mips_TLSGD:
+ case MipsMCExpr::MEK_TLSGD:
FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_GD
- : Mips::fixup_Mips_TLSGD;
+ : Mips::fixup_Mips_TLSGD;
break;
- case MCSymbolRefExpr::VK_Mips_TLSLDM:
+ case MipsMCExpr::MEK_TLSLDM:
FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_LDM
- : Mips::fixup_Mips_TLSLDM;
- break;
- case MCSymbolRefExpr::VK_Mips_DTPREL_HI:
- FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_HI16
- : Mips::fixup_Mips_DTPREL_HI;
- break;
- case MCSymbolRefExpr::VK_Mips_DTPREL_LO:
- FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_LO16
- : Mips::fixup_Mips_DTPREL_LO;
- break;
- case MCSymbolRefExpr::VK_Mips_GOTTPREL:
- FixupKind = Mips::fixup_Mips_GOTTPREL;
+ : Mips::fixup_Mips_TLSLDM;
break;
- case MCSymbolRefExpr::VK_Mips_TPREL_HI:
+ case MipsMCExpr::MEK_TPREL_HI:
FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_HI16
- : Mips::fixup_Mips_TPREL_HI;
+ : Mips::fixup_Mips_TPREL_HI;
break;
- case MCSymbolRefExpr::VK_Mips_TPREL_LO:
+ case MipsMCExpr::MEK_TPREL_LO:
FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_LO16
- : Mips::fixup_Mips_TPREL_LO;
+ : Mips::fixup_Mips_TPREL_LO;
break;
- case MCSymbolRefExpr::VK_Mips_HIGHER:
- FixupKind = Mips::fixup_Mips_HIGHER;
- break;
- case MCSymbolRefExpr::VK_Mips_HIGHEST:
- FixupKind = Mips::fixup_Mips_HIGHEST;
- break;
- case MCSymbolRefExpr::VK_Mips_GOT_HI16:
- FixupKind = Mips::fixup_Mips_GOT_HI16;
- break;
- case MCSymbolRefExpr::VK_Mips_GOT_LO16:
- FixupKind = Mips::fixup_Mips_GOT_LO16;
- break;
- case MCSymbolRefExpr::VK_Mips_CALL_HI16:
- FixupKind = Mips::fixup_Mips_CALL_HI16;
- break;
- case MCSymbolRefExpr::VK_Mips_CALL_LO16:
- FixupKind = Mips::fixup_Mips_CALL_LO16;
- break;
- case MCSymbolRefExpr::VK_Mips_PCREL_HI16:
- FixupKind = Mips::fixup_MIPS_PCHI16;
+ }
+ Fixups.push_back(MCFixup::create(0, MipsExpr, MCFixupKind(FixupKind)));
+ return 0;
+ }
+
+ if (Kind == MCExpr::SymbolRef) {
+ Mips::Fixups FixupKind = Mips::Fixups(0);
+
+ switch(cast<MCSymbolRefExpr>(Expr)->getKind()) {
+ default: llvm_unreachable("Unknown fixup kind!");
break;
- case MCSymbolRefExpr::VK_Mips_PCREL_LO16:
- FixupKind = Mips::fixup_MIPS_PCLO16;
+ case MCSymbolRefExpr::VK_None:
+ FixupKind = Mips::fixup_Mips_32; // FIXME: This is ok for O32/N32 but not N64.
break;
} // switch
@@ -660,61 +775,20 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO,
return getExprOpValue(MO.getExpr(),Fixups, STI);
}
-/// getMSAMemEncoding - Return binary encoding of memory operand for LD/ST
-/// instructions.
-unsigned
-MipsMCCodeEmitter::getMSAMemEncoding(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups,
- const MCSubtargetInfo &STI) const {
- // Base register is encoded in bits 20-16, offset is encoded in bits 15-0.
- assert(MI.getOperand(OpNo).isReg());
- unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups, STI) << 16;
- unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);
-
- // The immediate field of an LD/ST instruction is scaled which means it must
- // be divided (when encoding) by the size (in bytes) of the instructions'
- // data format.
- // .b - 1 byte
- // .h - 2 bytes
- // .w - 4 bytes
- // .d - 8 bytes
- switch(MI.getOpcode())
- {
- default:
- assert (0 && "Unexpected instruction");
- break;
- case Mips::LD_B:
- case Mips::ST_B:
- // We don't need to scale the offset in this case
- break;
- case Mips::LD_H:
- case Mips::ST_H:
- OffBits >>= 1;
- break;
- case Mips::LD_W:
- case Mips::ST_W:
- OffBits >>= 2;
- break;
- case Mips::LD_D:
- case Mips::ST_D:
- OffBits >>= 3;
- break;
- }
-
- return (OffBits & 0xFFFF) | RegBits;
-}
-
-/// getMemEncoding - Return binary encoding of memory related operand.
+/// Return binary encoding of memory related operand.
/// If the offset operand requires relocation, record the relocation.
-unsigned
-MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo,
- SmallVectorImpl<MCFixup> &Fixups,
- const MCSubtargetInfo &STI) const {
+template <unsigned ShiftAmount>
+unsigned MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
// Base register is encoded in bits 20-16, offset is encoded in bits 15-0.
assert(MI.getOperand(OpNo).isReg());
unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups, STI) << 16;
unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);
+ // Apply the scale factor if there is one.
+ OffBits >>= ShiftAmount;
+
return (OffBits & 0xFFFF) | RegBits;
}
@@ -804,6 +878,19 @@ getMemEncodingMMImm9(const MCInst &MI, unsigned OpNo,
}
unsigned MipsMCCodeEmitter::
+getMemEncodingMMImm11(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ // Base register is encoded in bits 20-16, offset is encoded in bits 10-0.
+ assert(MI.getOperand(OpNo).isReg());
+ unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups,
+ STI) << 16;
+ unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);
+
+ return (OffBits & 0x07FF) | RegBits;
+}
+
+unsigned MipsMCCodeEmitter::
getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const {
@@ -906,8 +993,9 @@ MipsMCCodeEmitter::getSimm19Lsl2Encoding(const MCInst &MI, unsigned OpNo,
"getSimm19Lsl2Encoding expects only expressions or an immediate");
const MCExpr *Expr = MO.getExpr();
- Fixups.push_back(MCFixup::create(0, Expr,
- MCFixupKind(Mips::fixup_MIPS_PC19_S2)));
+ Mips::Fixups FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_PC19_S2
+ : Mips::fixup_MIPS_PC19_S2;
+ Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(FixupKind)));
return 0;
}
@@ -927,8 +1015,9 @@ MipsMCCodeEmitter::getSimm18Lsl3Encoding(const MCInst &MI, unsigned OpNo,
"getSimm18Lsl2Encoding expects only expressions or an immediate");
const MCExpr *Expr = MO.getExpr();
- Fixups.push_back(MCFixup::create(0, Expr,
- MCFixupKind(Mips::fixup_MIPS_PC18_S3)));
+ Mips::Fixups FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_PC18_S3
+ : Mips::fixup_MIPS_PC18_S3;
+ Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(FixupKind)));
return 0;
}
diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h
index fdacd172e3a23..0f4dfe1200c0b 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h
+++ b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h
@@ -102,6 +102,20 @@ public:
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
+ // getBranchTargetOpValue1SImm16 - Return binary encoding of the branch
+ // target operand. If the machine operand requires relocation,
+ // record the relocation and return zero.
+ unsigned getBranchTargetOpValue1SImm16(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
+ // getBranchTargetOpValueMMR6 - Return binary encoding of the branch
+ // target operand. If the machine operand requires relocation,
+ // record the relocation and return zero.
+ unsigned getBranchTargetOpValueMMR6(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
// getBranchTarget7OpValue - Return binary encoding of the microMIPS branch
// target operand. If the machine operand requires relocation,
// record the relocation and return zero.
@@ -130,6 +144,13 @@ public:
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
+ // getBranchTarget21OpValueMM - Return binary encoding of the branch
+ // offset operand for microMIPS. If the machine operand requires
+ // relocation,record the relocation and return zero.
+ unsigned getBranchTarget21OpValueMM(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
// getBranchTarget26OpValue - Return binary encoding of the branch
// offset operand. If the machine operand requires relocation,
// record the relocation and return zero.
@@ -161,6 +182,7 @@ public:
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
+ template <unsigned ShiftAmount = 0>
unsigned getMemEncoding(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
@@ -182,6 +204,9 @@ public:
unsigned getMemEncodingMMImm9(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
+ unsigned getMemEncodingMMImm11(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
unsigned getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
@@ -238,6 +263,8 @@ public:
unsigned getRegisterListOpValue16(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
+ private:
+ void LowerCompactBranch(MCInst& Inst) const;
}; // class MipsMCCodeEmitter
} // namespace llvm.
diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp
index c85fc4816b086..082bb87fcb8a1 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp
+++ b/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp
@@ -12,69 +12,110 @@
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCObjectStreamer.h"
+#include "llvm/MC/MCSymbolELF.h"
+#include "llvm/Support/ELF.h"
using namespace llvm;
#define DEBUG_TYPE "mipsmcexpr"
-bool MipsMCExpr::isSupportedBinaryExpr(MCSymbolRefExpr::VariantKind VK,
- const MCBinaryExpr *BE) {
- switch (VK) {
- case MCSymbolRefExpr::VK_Mips_ABS_LO:
- case MCSymbolRefExpr::VK_Mips_ABS_HI:
- case MCSymbolRefExpr::VK_Mips_HIGHER:
- case MCSymbolRefExpr::VK_Mips_HIGHEST:
- break;
- default:
- return false;
- }
+const MipsMCExpr *MipsMCExpr::create(MipsMCExpr::MipsExprKind Kind,
+ const MCExpr *Expr, MCContext &Ctx) {
+ return new (Ctx) MipsMCExpr(Kind, Expr);
+}
- // We support expressions of the form "(sym1 binop1 sym2) binop2 const",
- // where "binop2 const" is optional.
- if (isa<MCBinaryExpr>(BE->getLHS())) {
- if (!isa<MCConstantExpr>(BE->getRHS()))
- return false;
- BE = cast<MCBinaryExpr>(BE->getLHS());
- }
- return (isa<MCSymbolRefExpr>(BE->getLHS())
- && isa<MCSymbolRefExpr>(BE->getRHS()));
+const MipsMCExpr *MipsMCExpr::createGpOff(MipsMCExpr::MipsExprKind Kind,
+ const MCExpr *Expr, MCContext &Ctx) {
+ return create(Kind, create(MEK_NEG, create(MEK_GPREL, Expr, Ctx), Ctx), Ctx);
}
-const MipsMCExpr*
-MipsMCExpr::create(MCSymbolRefExpr::VariantKind VK, const MCExpr *Expr,
- MCContext &Ctx) {
- VariantKind Kind;
- switch (VK) {
- case MCSymbolRefExpr::VK_Mips_ABS_LO:
- Kind = VK_Mips_LO;
+void MipsMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
+ int64_t AbsVal;
+
+ switch (Kind) {
+ case MEK_None:
+ case MEK_Special:
+ llvm_unreachable("MEK_None and MEK_Special are invalid");
break;
- case MCSymbolRefExpr::VK_Mips_ABS_HI:
- Kind = VK_Mips_HI;
+ case MEK_CALL_HI16:
+ OS << "%call_hi";
break;
- case MCSymbolRefExpr::VK_Mips_HIGHER:
- Kind = VK_Mips_HIGHER;
+ case MEK_CALL_LO16:
+ OS << "%call_lo";
break;
- case MCSymbolRefExpr::VK_Mips_HIGHEST:
- Kind = VK_Mips_HIGHEST;
+ case MEK_DTPREL_HI:
+ OS << "%dtprel_hi";
+ break;
+ case MEK_DTPREL_LO:
+ OS << "%dtprel_lo";
+ break;
+ case MEK_GOT:
+ OS << "%got";
+ break;
+ case MEK_GOTTPREL:
+ OS << "%gottprel";
+ break;
+ case MEK_GOT_CALL:
+ OS << "%call16";
+ break;
+ case MEK_GOT_DISP:
+ OS << "%got_disp";
+ break;
+ case MEK_GOT_HI16:
+ OS << "%got_hi";
+ break;
+ case MEK_GOT_LO16:
+ OS << "%got_lo";
+ break;
+ case MEK_GOT_PAGE:
+ OS << "%got_page";
+ break;
+ case MEK_GOT_OFST:
+ OS << "%got_ofst";
+ break;
+ case MEK_GPREL:
+ OS << "%gp_rel";
+ break;
+ case MEK_HI:
+ OS << "%hi";
+ break;
+ case MEK_HIGHER:
+ OS << "%higher";
+ break;
+ case MEK_HIGHEST:
+ OS << "%highest";
+ break;
+ case MEK_LO:
+ OS << "%lo";
+ break;
+ case MEK_NEG:
+ OS << "%neg";
+ break;
+ case MEK_PCREL_HI16:
+ OS << "%pcrel_hi";
+ break;
+ case MEK_PCREL_LO16:
+ OS << "%pcrel_lo";
+ break;
+ case MEK_TLSGD:
+ OS << "%tlsgd";
+ break;
+ case MEK_TLSLDM:
+ OS << "%tlsldm";
+ break;
+ case MEK_TPREL_HI:
+ OS << "%tprel_hi";
+ break;
+ case MEK_TPREL_LO:
+ OS << "%tprel_lo";
break;
- default:
- llvm_unreachable("Invalid kind!");
- }
-
- return new (Ctx) MipsMCExpr(Kind, Expr);
-}
-
-void MipsMCExpr::printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const {
- switch (Kind) {
- default: llvm_unreachable("Invalid kind!");
- case VK_Mips_LO: OS << "%lo"; break;
- case VK_Mips_HI: OS << "%hi"; break;
- case VK_Mips_HIGHER: OS << "%higher"; break;
- case VK_Mips_HIGHEST: OS << "%highest"; break;
}
OS << '(';
- Expr->print(OS, MAI);
+ if (Expr->evaluateAsAbsolute(AbsVal))
+ OS << AbsVal;
+ else
+ Expr->print(OS, MAI, true);
OS << ')';
}
@@ -82,9 +123,165 @@ bool
MipsMCExpr::evaluateAsRelocatableImpl(MCValue &Res,
const MCAsmLayout *Layout,
const MCFixup *Fixup) const {
- return getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup);
+ // Look for the %hi(%neg(%gp_rel(X))) and %lo(%neg(%gp_rel(X))) special cases.
+ if (isGpOff()) {
+ const MCExpr *SubExpr =
+ cast<MipsMCExpr>(cast<MipsMCExpr>(getSubExpr())->getSubExpr())
+ ->getSubExpr();
+ if (!SubExpr->evaluateAsRelocatable(Res, Layout, Fixup))
+ return false;
+
+ Res = MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(),
+ MEK_Special);
+ return true;
+ }
+
+ if (!getSubExpr()->evaluateAsRelocatable(Res, Layout, Fixup))
+ return false;
+
+ if (Res.getRefKind() != MCSymbolRefExpr::VK_None)
+ return false;
+
+ // evaluateAsAbsolute() and evaluateAsValue() require that we evaluate the
+ // %hi/%lo/etc. here. Fixup is a null pointer when either of these is the
+ // caller.
+ if (Res.isAbsolute() && Fixup == nullptr) {
+ int64_t AbsVal = Res.getConstant();
+ switch (Kind) {
+ case MEK_None:
+ case MEK_Special:
+ llvm_unreachable("MEK_None and MEK_Special are invalid");
+ case MEK_DTPREL_HI:
+ case MEK_DTPREL_LO:
+ case MEK_GOT:
+ case MEK_GOTTPREL:
+ case MEK_GOT_CALL:
+ case MEK_GOT_DISP:
+ case MEK_GOT_HI16:
+ case MEK_GOT_LO16:
+ case MEK_GOT_OFST:
+ case MEK_GOT_PAGE:
+ case MEK_GPREL:
+ case MEK_PCREL_HI16:
+ case MEK_PCREL_LO16:
+ case MEK_TLSGD:
+ case MEK_TLSLDM:
+ case MEK_TPREL_HI:
+ case MEK_TPREL_LO:
+ return false;
+ case MEK_LO:
+ case MEK_CALL_LO16:
+ AbsVal = SignExtend64<16>(AbsVal);
+ break;
+ case MEK_CALL_HI16:
+ case MEK_HI:
+ AbsVal = SignExtend64<16>((AbsVal + 0x8000) >> 16);
+ break;
+ case MEK_HIGHER:
+ AbsVal = SignExtend64<16>((AbsVal + 0x80008000LL) >> 32);
+ break;
+ case MEK_HIGHEST:
+ AbsVal = SignExtend64<16>((AbsVal + 0x800080008000LL) >> 48);
+ break;
+ case MEK_NEG:
+ AbsVal = -AbsVal;
+ break;
+ }
+ Res = MCValue::get(AbsVal);
+ return true;
+ }
+
+ // We want to defer it for relocatable expressions since the constant is
+ // applied to the whole symbol value.
+ //
+ // The value of getKind() that is given to MCValue is only intended to aid
+ // debugging when inspecting MCValue objects. It shouldn't be relied upon
+ // for decision making.
+ Res = MCValue::get(Res.getSymA(), Res.getSymB(), Res.getConstant(), getKind());
+
+ return true;
}
void MipsMCExpr::visitUsedExpr(MCStreamer &Streamer) const {
Streamer.visitUsedExpr(*getSubExpr());
}
+
+static void fixELFSymbolsInTLSFixupsImpl(const MCExpr *Expr, MCAssembler &Asm) {
+ switch (Expr->getKind()) {
+ case MCExpr::Target:
+ fixELFSymbolsInTLSFixupsImpl(cast<MipsMCExpr>(Expr)->getSubExpr(), Asm);
+ break;
+ case MCExpr::Constant:
+ break;
+ case MCExpr::Binary: {
+ const MCBinaryExpr *BE = cast<MCBinaryExpr>(Expr);
+ fixELFSymbolsInTLSFixupsImpl(BE->getLHS(), Asm);
+ fixELFSymbolsInTLSFixupsImpl(BE->getRHS(), Asm);
+ break;
+ }
+ case MCExpr::SymbolRef: {
+ // We're known to be under a TLS fixup, so any symbol should be
+ // modified. There should be only one.
+ const MCSymbolRefExpr &SymRef = *cast<MCSymbolRefExpr>(Expr);
+ cast<MCSymbolELF>(SymRef.getSymbol()).setType(ELF::STT_TLS);
+ break;
+ }
+ case MCExpr::Unary:
+ fixELFSymbolsInTLSFixupsImpl(cast<MCUnaryExpr>(Expr)->getSubExpr(), Asm);
+ break;
+ }
+}
+
+void MipsMCExpr::fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {
+ switch (getKind()) {
+ case MEK_None:
+ case MEK_Special:
+ llvm_unreachable("MEK_None and MEK_Special are invalid");
+ break;
+ case MEK_CALL_HI16:
+ case MEK_CALL_LO16:
+ case MEK_DTPREL_HI:
+ case MEK_DTPREL_LO:
+ case MEK_GOT:
+ case MEK_GOT_CALL:
+ case MEK_GOT_DISP:
+ case MEK_GOT_HI16:
+ case MEK_GOT_LO16:
+ case MEK_GOT_OFST:
+ case MEK_GOT_PAGE:
+ case MEK_GPREL:
+ case MEK_HI:
+ case MEK_HIGHER:
+ case MEK_HIGHEST:
+ case MEK_LO:
+ case MEK_NEG:
+ case MEK_PCREL_HI16:
+ case MEK_PCREL_LO16:
+ case MEK_TLSLDM:
+ // If we do have nested target-specific expressions, they will be in
+ // a consecutive chain.
+ if (const MipsMCExpr *E = dyn_cast<const MipsMCExpr>(getSubExpr()))
+ E->fixELFSymbolsInTLSFixups(Asm);
+ break;
+ case MEK_GOTTPREL:
+ case MEK_TLSGD:
+ case MEK_TPREL_HI:
+ case MEK_TPREL_LO:
+ fixELFSymbolsInTLSFixupsImpl(getSubExpr(), Asm);
+ break;
+ }
+}
+
+bool MipsMCExpr::isGpOff(MipsExprKind &Kind) const {
+ if (getKind() == MEK_HI || getKind() == MEK_LO) {
+ if (const MipsMCExpr *S1 = dyn_cast<const MipsMCExpr>(getSubExpr())) {
+ if (const MipsMCExpr *S2 = dyn_cast<const MipsMCExpr>(S1->getSubExpr())) {
+ if (S1->getKind() == MEK_NEG && S2->getKind() == MEK_GPREL) {
+ Kind = getKind();
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h b/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h
index e889972c5c0e8..d1a4334ec640a 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h
+++ b/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h
@@ -18,49 +18,73 @@ namespace llvm {
class MipsMCExpr : public MCTargetExpr {
public:
- enum VariantKind {
- VK_Mips_None,
- VK_Mips_LO,
- VK_Mips_HI,
- VK_Mips_HIGHER,
- VK_Mips_HIGHEST
+ enum MipsExprKind {
+ MEK_None,
+ MEK_CALL_HI16,
+ MEK_CALL_LO16,
+ MEK_DTPREL_HI,
+ MEK_DTPREL_LO,
+ MEK_GOT,
+ MEK_GOTTPREL,
+ MEK_GOT_CALL,
+ MEK_GOT_DISP,
+ MEK_GOT_HI16,
+ MEK_GOT_LO16,
+ MEK_GOT_OFST,
+ MEK_GOT_PAGE,
+ MEK_GPREL,
+ MEK_HI,
+ MEK_HIGHER,
+ MEK_HIGHEST,
+ MEK_LO,
+ MEK_NEG,
+ MEK_PCREL_HI16,
+ MEK_PCREL_LO16,
+ MEK_TLSGD,
+ MEK_TLSLDM,
+ MEK_TPREL_HI,
+ MEK_TPREL_LO,
+ MEK_Special,
};
private:
- const VariantKind Kind;
+ const MipsExprKind Kind;
const MCExpr *Expr;
- explicit MipsMCExpr(VariantKind Kind, const MCExpr *Expr)
- : Kind(Kind), Expr(Expr) {}
+ explicit MipsMCExpr(MipsExprKind Kind, const MCExpr *Expr)
+ : Kind(Kind), Expr(Expr) {}
public:
- static bool isSupportedBinaryExpr(MCSymbolRefExpr::VariantKind VK,
- const MCBinaryExpr *BE);
+ static const MipsMCExpr *create(MipsExprKind Kind, const MCExpr *Expr,
+ MCContext &Ctx);
+ static const MipsMCExpr *createGpOff(MipsExprKind Kind, const MCExpr *Expr,
+ MCContext &Ctx);
- static const MipsMCExpr *create(MCSymbolRefExpr::VariantKind VK,
- const MCExpr *Expr, MCContext &Ctx);
+ /// Get the kind of this expression.
+ MipsExprKind getKind() const { return Kind; }
- /// getOpcode - Get the kind of this expression.
- VariantKind getKind() const { return Kind; }
-
- /// getSubExpr - Get the child of this expression.
+ /// Get the child of this expression.
const MCExpr *getSubExpr() const { return Expr; }
void printImpl(raw_ostream &OS, const MCAsmInfo *MAI) const override;
- bool evaluateAsRelocatableImpl(MCValue &Res,
- const MCAsmLayout *Layout,
+ bool evaluateAsRelocatableImpl(MCValue &Res, const MCAsmLayout *Layout,
const MCFixup *Fixup) const override;
void visitUsedExpr(MCStreamer &Streamer) const override;
MCFragment *findAssociatedFragment() const override {
return getSubExpr()->findAssociatedFragment();
}
- // There are no TLS MipsMCExprs at the moment.
- void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override {}
+ void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override;
static bool classof(const MCExpr *E) {
return E->getKind() == MCExpr::Target;
}
+
+ bool isGpOff(MipsExprKind &Kind) const;
+ bool isGpOff() const {
+ MipsExprKind Kind;
+ return isGpOff(Kind);
+ }
};
} // end namespace llvm
diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
index 949ee1474f96a..a055739509741 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
+++ b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
@@ -11,21 +11,20 @@
//
//===----------------------------------------------------------------------===//
+#include "MipsMCTargetDesc.h"
#include "InstPrinter/MipsInstPrinter.h"
#include "MipsELFStreamer.h"
#include "MipsMCAsmInfo.h"
#include "MipsMCNaCl.h"
-#include "MipsMCTargetDesc.h"
#include "MipsTargetStreamer.h"
#include "llvm/ADT/Triple.h"
-#include "llvm/MC/MCCodeGenInfo.h"
#include "llvm/MC/MCELFStreamer.h"
+#include "llvm/MC/MCInstrAnalysis.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MachineLocation.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/TargetRegistry.h"
@@ -82,18 +81,6 @@ static MCAsmInfo *createMipsMCAsmInfo(const MCRegisterInfo &MRI,
return MAI;
}
-static MCCodeGenInfo *createMipsMCCodeGenInfo(const Triple &TT, Reloc::Model RM,
- CodeModel::Model CM,
- CodeGenOpt::Level OL) {
- MCCodeGenInfo *X = new MCCodeGenInfo();
- if (CM == CodeModel::JITDefault)
- RM = Reloc::Static;
- else if (RM == Reloc::Default)
- RM = Reloc::PIC_;
- X->initMCCodeGenInfo(RM, CM, OL);
- return X;
-}
-
static MCInstPrinter *createMipsMCInstPrinter(const Triple &T,
unsigned SyntaxVariant,
const MCAsmInfo &MAI,
@@ -129,15 +116,44 @@ createMipsObjectTargetStreamer(MCStreamer &S, const MCSubtargetInfo &STI) {
return new MipsTargetELFStreamer(S, STI);
}
+namespace {
+
+class MipsMCInstrAnalysis : public MCInstrAnalysis {
+public:
+ MipsMCInstrAnalysis(const MCInstrInfo *Info) : MCInstrAnalysis(Info) {}
+
+ bool evaluateBranch(const MCInst &Inst, uint64_t Addr, uint64_t Size,
+ uint64_t &Target) const override {
+ unsigned NumOps = Inst.getNumOperands();
+ if (NumOps == 0)
+ return false;
+ switch (Info->get(Inst.getOpcode()).OpInfo[NumOps - 1].OperandType) {
+ case MCOI::OPERAND_UNKNOWN:
+ case MCOI::OPERAND_IMMEDIATE:
+ // jal, bal ...
+ Target = Inst.getOperand(NumOps - 1).getImm();
+ return true;
+ case MCOI::OPERAND_PCREL:
+ // b, j, beq ...
+ Target = Addr + Inst.getOperand(NumOps - 1).getImm();
+ return true;
+ default:
+ return false;
+ }
+ }
+};
+}
+
+static MCInstrAnalysis *createMipsMCInstrAnalysis(const MCInstrInfo *Info) {
+ return new MipsMCInstrAnalysis(Info);
+}
+
extern "C" void LLVMInitializeMipsTargetMC() {
for (Target *T : {&TheMipsTarget, &TheMipselTarget, &TheMips64Target,
&TheMips64elTarget}) {
// Register the MC asm info.
RegisterMCAsmInfoFn X(*T, createMipsMCAsmInfo);
- // Register the MC codegen info.
- TargetRegistry::RegisterMCCodeGenInfo(*T, createMipsMCCodeGenInfo);
-
// Register the MC instruction info.
TargetRegistry::RegisterMCInstrInfo(*T, createMipsMCInstrInfo);
@@ -156,6 +172,9 @@ extern "C" void LLVMInitializeMipsTargetMC() {
// Register the MC subtarget info.
TargetRegistry::RegisterMCSubtargetInfo(*T, createMipsMCSubtargetInfo);
+ // Register the MC instruction analyzer.
+ TargetRegistry::RegisterMCInstrAnalysis(*T, createMipsMCInstrAnalysis);
+
// Register the MCInstPrinter.
TargetRegistry::RegisterMCInstPrinter(*T, createMipsMCInstPrinter);
diff --git a/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp b/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
index e5fa7556053f9..7f79eb400f597 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
+++ b/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
@@ -11,11 +11,12 @@
//
//===----------------------------------------------------------------------===//
+#include "MipsTargetStreamer.h"
#include "InstPrinter/MipsInstPrinter.h"
#include "MipsELFStreamer.h"
+#include "MipsMCExpr.h"
#include "MipsMCTargetDesc.h"
#include "MipsTargetObjectFile.h"
-#include "MipsTargetStreamer.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCSubtargetInfo.h"
@@ -27,12 +28,19 @@
using namespace llvm;
+namespace {
+static cl::opt<bool> RoundSectionSizes(
+ "mips-round-section-sizes", cl::init(false),
+ cl::desc("Round section sizes up to the section alignment"), cl::Hidden);
+} // end anonymous namespace
+
MipsTargetStreamer::MipsTargetStreamer(MCStreamer &S)
: MCTargetStreamer(S), ModuleDirectiveAllowed(true) {
GPRInfoSet = FPRInfoSet = FrameInfoSet = false;
}
void MipsTargetStreamer::emitDirectiveSetMicroMips() {}
void MipsTargetStreamer::emitDirectiveSetNoMicroMips() {}
+void MipsTargetStreamer::setUsesMicroMips() {}
void MipsTargetStreamer::emitDirectiveSetMips16() {}
void MipsTargetStreamer::emitDirectiveSetNoMips16() { forbidModuleDirective(); }
void MipsTargetStreamer::emitDirectiveSetReorder() { forbidModuleDirective(); }
@@ -89,9 +97,11 @@ void MipsTargetStreamer::emitDirectiveSetHardFloat() {
void MipsTargetStreamer::emitDirectiveSetDsp() { forbidModuleDirective(); }
void MipsTargetStreamer::emitDirectiveSetNoDsp() { forbidModuleDirective(); }
void MipsTargetStreamer::emitDirectiveCpLoad(unsigned RegNo) {}
-void MipsTargetStreamer::emitDirectiveCpRestore(
- SmallVector<MCInst, 3> &StoreInsts, int Offset) {
+bool MipsTargetStreamer::emitDirectiveCpRestore(
+ int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc,
+ const MCSubtargetInfo *STI) {
forbidModuleDirective();
+ return true;
}
void MipsTargetStreamer::emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
const MCSymbol &Sym, bool IsReg) {
@@ -116,6 +126,217 @@ void MipsTargetStreamer::emitDirectiveSetNoOddSPReg() {
forbidModuleDirective();
}
+void MipsTargetStreamer::emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
+ const MCSubtargetInfo *STI) {
+ MCInst TmpInst;
+ TmpInst.setOpcode(Opcode);
+ TmpInst.addOperand(MCOperand::createReg(Reg0));
+ TmpInst.setLoc(IDLoc);
+ getStreamer().EmitInstruction(TmpInst, *STI);
+}
+
+void MipsTargetStreamer::emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1,
+ SMLoc IDLoc, const MCSubtargetInfo *STI) {
+ MCInst TmpInst;
+ TmpInst.setOpcode(Opcode);
+ TmpInst.addOperand(MCOperand::createReg(Reg0));
+ TmpInst.addOperand(Op1);
+ TmpInst.setLoc(IDLoc);
+ getStreamer().EmitInstruction(TmpInst, *STI);
+}
+
+void MipsTargetStreamer::emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm,
+ SMLoc IDLoc, const MCSubtargetInfo *STI) {
+ emitRX(Opcode, Reg0, MCOperand::createImm(Imm), IDLoc, STI);
+}
+
+void MipsTargetStreamer::emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1,
+ SMLoc IDLoc, const MCSubtargetInfo *STI) {
+ emitRX(Opcode, Reg0, MCOperand::createReg(Reg1), IDLoc, STI);
+}
+
+void MipsTargetStreamer::emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2,
+ SMLoc IDLoc, const MCSubtargetInfo *STI) {
+ MCInst TmpInst;
+ TmpInst.setOpcode(Opcode);
+ TmpInst.addOperand(MCOperand::createImm(Imm1));
+ TmpInst.addOperand(MCOperand::createImm(Imm2));
+ TmpInst.setLoc(IDLoc);
+ getStreamer().EmitInstruction(TmpInst, *STI);
+}
+
+void MipsTargetStreamer::emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1,
+ MCOperand Op2, SMLoc IDLoc,
+ const MCSubtargetInfo *STI) {
+ MCInst TmpInst;
+ TmpInst.setOpcode(Opcode);
+ TmpInst.addOperand(MCOperand::createReg(Reg0));
+ TmpInst.addOperand(MCOperand::createReg(Reg1));
+ TmpInst.addOperand(Op2);
+ TmpInst.setLoc(IDLoc);
+ getStreamer().EmitInstruction(TmpInst, *STI);
+}
+
+void MipsTargetStreamer::emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1,
+ unsigned Reg2, SMLoc IDLoc,
+ const MCSubtargetInfo *STI) {
+ emitRRX(Opcode, Reg0, Reg1, MCOperand::createReg(Reg2), IDLoc, STI);
+}
+
+void MipsTargetStreamer::emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1,
+ int16_t Imm, SMLoc IDLoc,
+ const MCSubtargetInfo *STI) {
+ emitRRX(Opcode, Reg0, Reg1, MCOperand::createImm(Imm), IDLoc, STI);
+}
+
+void MipsTargetStreamer::emitAddu(unsigned DstReg, unsigned SrcReg,
+ unsigned TrgReg, bool Is64Bit,
+ const MCSubtargetInfo *STI) {
+ emitRRR(Is64Bit ? Mips::DADDu : Mips::ADDu, DstReg, SrcReg, TrgReg, SMLoc(),
+ STI);
+}
+
+void MipsTargetStreamer::emitDSLL(unsigned DstReg, unsigned SrcReg,
+ int16_t ShiftAmount, SMLoc IDLoc,
+ const MCSubtargetInfo *STI) {
+ if (ShiftAmount >= 32) {
+ emitRRI(Mips::DSLL32, DstReg, SrcReg, ShiftAmount - 32, IDLoc, STI);
+ return;
+ }
+
+ emitRRI(Mips::DSLL, DstReg, SrcReg, ShiftAmount, IDLoc, STI);
+}
+
+void MipsTargetStreamer::emitEmptyDelaySlot(bool hasShortDelaySlot, SMLoc IDLoc,
+ const MCSubtargetInfo *STI) {
+ if (hasShortDelaySlot)
+ emitRR(Mips::MOVE16_MM, Mips::ZERO, Mips::ZERO, IDLoc, STI);
+ else
+ emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
+}
+
+void MipsTargetStreamer::emitNop(SMLoc IDLoc, const MCSubtargetInfo *STI) {
+ emitRRI(Mips::SLL, Mips::ZERO, Mips::ZERO, 0, IDLoc, STI);
+}
+
+/// Emit the $gp restore operation for .cprestore.
+void MipsTargetStreamer::emitGPRestore(int Offset, SMLoc IDLoc,
+ const MCSubtargetInfo *STI) {
+ emitLoadWithImmOffset(Mips::LW, Mips::GP, Mips::SP, Offset, Mips::GP, IDLoc,
+ STI);
+}
+
+/// Emit a store instruction with an immediate offset.
+void MipsTargetStreamer::emitStoreWithImmOffset(
+ unsigned Opcode, unsigned SrcReg, unsigned BaseReg, int64_t Offset,
+ function_ref<unsigned()> GetATReg, SMLoc IDLoc,
+ const MCSubtargetInfo *STI) {
+ if (isInt<16>(Offset)) {
+ emitRRI(Opcode, SrcReg, BaseReg, Offset, IDLoc, STI);
+ return;
+ }
+
+ // sw $8, offset($8) => lui $at, %hi(offset)
+ // add $at, $at, $8
+ // sw $8, %lo(offset)($at)
+
+ unsigned ATReg = GetATReg();
+ if (!ATReg)
+ return;
+
+ unsigned LoOffset = Offset & 0x0000ffff;
+ unsigned HiOffset = (Offset & 0xffff0000) >> 16;
+
+ // If msb of LoOffset is 1(negative number) we must increment HiOffset
+ // to account for the sign-extension of the low part.
+ if (LoOffset & 0x8000)
+ HiOffset++;
+
+ // Generate the base address in ATReg.
+ emitRI(Mips::LUi, ATReg, HiOffset, IDLoc, STI);
+ if (BaseReg != Mips::ZERO)
+ emitRRR(Mips::ADDu, ATReg, ATReg, BaseReg, IDLoc, STI);
+ // Emit the store with the adjusted base and offset.
+ emitRRI(Opcode, SrcReg, ATReg, LoOffset, IDLoc, STI);
+}
+
+/// Emit a store instruction with an symbol offset. Symbols are assumed to be
+/// out of range for a simm16 will be expanded to appropriate instructions.
+void MipsTargetStreamer::emitStoreWithSymOffset(
+ unsigned Opcode, unsigned SrcReg, unsigned BaseReg, MCOperand &HiOperand,
+ MCOperand &LoOperand, unsigned ATReg, SMLoc IDLoc,
+ const MCSubtargetInfo *STI) {
+ // sw $8, sym => lui $at, %hi(sym)
+ // sw $8, %lo(sym)($at)
+
+ // Generate the base address in ATReg.
+ emitRX(Mips::LUi, ATReg, HiOperand, IDLoc, STI);
+ if (BaseReg != Mips::ZERO)
+ emitRRR(Mips::ADDu, ATReg, ATReg, BaseReg, IDLoc, STI);
+ // Emit the store with the adjusted base and offset.
+ emitRRX(Opcode, SrcReg, ATReg, LoOperand, IDLoc, STI);
+}
+
+/// Emit a load instruction with an immediate offset. DstReg and TmpReg are
+/// permitted to be the same register iff DstReg is distinct from BaseReg and
+/// DstReg is a GPR. It is the callers responsibility to identify such cases
+/// and pass the appropriate register in TmpReg.
+void MipsTargetStreamer::emitLoadWithImmOffset(unsigned Opcode, unsigned DstReg,
+ unsigned BaseReg, int64_t Offset,
+ unsigned TmpReg, SMLoc IDLoc,
+ const MCSubtargetInfo *STI) {
+ if (isInt<16>(Offset)) {
+ emitRRI(Opcode, DstReg, BaseReg, Offset, IDLoc, STI);
+ return;
+ }
+
+ // 1) lw $8, offset($9) => lui $8, %hi(offset)
+ // add $8, $8, $9
+ // lw $8, %lo(offset)($9)
+ // 2) lw $8, offset($8) => lui $at, %hi(offset)
+ // add $at, $at, $8
+ // lw $8, %lo(offset)($at)
+
+ unsigned LoOffset = Offset & 0x0000ffff;
+ unsigned HiOffset = (Offset & 0xffff0000) >> 16;
+
+ // If msb of LoOffset is 1(negative number) we must increment HiOffset
+ // to account for the sign-extension of the low part.
+ if (LoOffset & 0x8000)
+ HiOffset++;
+
+ // Generate the base address in TmpReg.
+ emitRI(Mips::LUi, TmpReg, HiOffset, IDLoc, STI);
+ if (BaseReg != Mips::ZERO)
+ emitRRR(Mips::ADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI);
+ // Emit the load with the adjusted base and offset.
+ emitRRI(Opcode, DstReg, TmpReg, LoOffset, IDLoc, STI);
+}
+
+/// Emit a load instruction with an symbol offset. Symbols are assumed to be
+/// out of range for a simm16 will be expanded to appropriate instructions.
+/// DstReg and TmpReg are permitted to be the same register iff DstReg is a
+/// GPR. It is the callers responsibility to identify such cases and pass the
+/// appropriate register in TmpReg.
+void MipsTargetStreamer::emitLoadWithSymOffset(unsigned Opcode, unsigned DstReg,
+ unsigned BaseReg,
+ MCOperand &HiOperand,
+ MCOperand &LoOperand,
+ unsigned TmpReg, SMLoc IDLoc,
+ const MCSubtargetInfo *STI) {
+ // 1) lw $8, sym => lui $8, %hi(sym)
+ // lw $8, %lo(sym)($8)
+ // 2) ldc1 $f0, sym => lui $at, %hi(sym)
+ // ldc1 $f0, %lo(sym)($at)
+
+ // Generate the base address in TmpReg.
+ emitRX(Mips::LUi, TmpReg, HiOperand, IDLoc, STI);
+ if (BaseReg != Mips::ZERO)
+ emitRRR(Mips::ADDu, TmpReg, TmpReg, BaseReg, IDLoc, STI);
+ // Emit the load with the adjusted base and offset.
+ emitRRX(Opcode, DstReg, TmpReg, LoOperand, IDLoc, STI);
+}
+
MipsTargetAsmStreamer::MipsTargetAsmStreamer(MCStreamer &S,
formatted_raw_ostream &OS)
: MipsTargetStreamer(S), OS(OS) {}
@@ -364,10 +585,12 @@ void MipsTargetAsmStreamer::emitDirectiveCpLoad(unsigned RegNo) {
forbidModuleDirective();
}
-void MipsTargetAsmStreamer::emitDirectiveCpRestore(
- SmallVector<MCInst, 3> &StoreInsts, int Offset) {
- MipsTargetStreamer::emitDirectiveCpRestore(StoreInsts, Offset);
+bool MipsTargetAsmStreamer::emitDirectiveCpRestore(
+ int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer::emitDirectiveCpRestore(Offset, GetATReg, IDLoc, STI);
OS << "\t.cprestore\t" << Offset << "\n";
+ return true;
}
void MipsTargetAsmStreamer::emitDirectiveCpsetup(unsigned RegNo,
@@ -437,7 +660,15 @@ MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S,
const MCSubtargetInfo &STI)
: MipsTargetStreamer(S), MicroMipsEnabled(false), STI(STI) {
MCAssembler &MCA = getStreamer().getAssembler();
- Pic = MCA.getContext().getObjectFileInfo()->getRelocM() == Reloc::PIC_;
+
+ // It's possible that MCObjectFileInfo isn't fully initialized at this point
+ // due to an initialization order problem where LLVMTargetMachine creates the
+ // target streamer before TargetLoweringObjectFile calls
+ // InitializeMCObjectFileInfo. There doesn't seem to be a single place that
+ // covers all cases so this statement covers most cases and direct object
+ // emission must call setPic() once MCObjectFileInfo has been initialized. The
+ // cases we don't handle here are covered by MipsAsmPrinter.
+ Pic = MCA.getContext().getObjectFileInfo()->isPositionIndependent();
const FeatureBitset &Features = STI.getFeatureBits();
@@ -482,6 +713,10 @@ MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S,
else
EFlags |= ELF::EF_MIPS_ARCH_1;
+ // Machine
+ if (Features[Mips::FeatureCnMips])
+ EFlags |= ELF::EF_MIPS_MACH_OCTEON;
+
// Other options.
if (Features[Mips::FeatureNaN2008])
EFlags |= ELF::EF_MIPS_NAN2008;
@@ -521,6 +756,26 @@ void MipsTargetELFStreamer::finish() {
DataSection.setAlignment(std::max(16u, DataSection.getAlignment()));
BSSSection.setAlignment(std::max(16u, BSSSection.getAlignment()));
+ if (RoundSectionSizes) {
+ // Make sections sizes a multiple of the alignment. This is useful for
+ // verifying the output of IAS against the output of other assemblers but
+ // it's not necessary to produce a correct object and increases section
+ // size.
+ MCStreamer &OS = getStreamer();
+ for (MCSection &S : MCA) {
+ MCSectionELF &Section = static_cast<MCSectionELF &>(S);
+
+ unsigned Alignment = Section.getAlignment();
+ if (Alignment) {
+ OS.SwitchSection(&Section);
+ if (Section.UseCodeAlign())
+ OS.EmitCodeAlignment(Alignment, Alignment);
+ else
+ OS.EmitValueToAlignment(Alignment, 0, 1, Alignment);
+ }
+ }
+ }
+
const FeatureBitset &Features = STI.getFeatureBits();
// Update e_header flags. See the FIXME and comment above in
@@ -576,11 +831,6 @@ MCELFStreamer &MipsTargetELFStreamer::getStreamer() {
void MipsTargetELFStreamer::emitDirectiveSetMicroMips() {
MicroMipsEnabled = true;
-
- MCAssembler &MCA = getStreamer().getAssembler();
- unsigned Flags = MCA.getELFHeaderEFlags();
- Flags |= ELF::EF_MIPS_MICROMIPS;
- MCA.setELFHeaderEFlags(Flags);
forbidModuleDirective();
}
@@ -589,6 +839,13 @@ void MipsTargetELFStreamer::emitDirectiveSetNoMicroMips() {
forbidModuleDirective();
}
+void MipsTargetELFStreamer::setUsesMicroMips() {
+ MCAssembler &MCA = getStreamer().getAssembler();
+ unsigned Flags = MCA.getELFHeaderEFlags();
+ Flags |= ELF::EF_MIPS_MICROMIPS;
+ MCA.setELFHeaderEFlags(Flags);
+}
+
void MipsTargetELFStreamer::emitDirectiveSetMips16() {
MCAssembler &MCA = getStreamer().getAssembler();
unsigned Flags = MCA.getELFHeaderEFlags();
@@ -610,8 +867,7 @@ void MipsTargetELFStreamer::emitDirectiveEnd(StringRef Name) {
MCContext &Context = MCA.getContext();
MCStreamer &OS = getStreamer();
- MCSectionELF *Sec = Context.getELFSection(".pdr", ELF::SHT_PROGBITS,
- ELF::SHF_ALLOC | ELF::SHT_REL);
+ MCSectionELF *Sec = Context.getELFSection(".pdr", ELF::SHT_PROGBITS, 0);
MCSymbol *Sym = Context.getOrCreateSymbol(Name);
const MCSymbolRefExpr *ExprRef =
@@ -760,8 +1016,11 @@ void MipsTargetELFStreamer::emitDirectiveCpLoad(unsigned RegNo) {
MCInst TmpInst;
TmpInst.setOpcode(Mips::LUi);
TmpInst.addOperand(MCOperand::createReg(Mips::GP));
- const MCSymbolRefExpr *HiSym = MCSymbolRefExpr::create(
- "_gp_disp", MCSymbolRefExpr::VK_Mips_ABS_HI, MCA.getContext());
+ const MCExpr *HiSym = MipsMCExpr::create(
+ MipsMCExpr::MEK_HI,
+ MCSymbolRefExpr::create("_gp_disp", MCSymbolRefExpr::VK_None,
+ MCA.getContext()),
+ MCA.getContext());
TmpInst.addOperand(MCOperand::createExpr(HiSym));
getStreamer().EmitInstruction(TmpInst, STI);
@@ -770,8 +1029,11 @@ void MipsTargetELFStreamer::emitDirectiveCpLoad(unsigned RegNo) {
TmpInst.setOpcode(Mips::ADDiu);
TmpInst.addOperand(MCOperand::createReg(Mips::GP));
TmpInst.addOperand(MCOperand::createReg(Mips::GP));
- const MCSymbolRefExpr *LoSym = MCSymbolRefExpr::create(
- "_gp_disp", MCSymbolRefExpr::VK_Mips_ABS_LO, MCA.getContext());
+ const MCExpr *LoSym = MipsMCExpr::create(
+ MipsMCExpr::MEK_LO,
+ MCSymbolRefExpr::create("_gp_disp", MCSymbolRefExpr::VK_None,
+ MCA.getContext()),
+ MCA.getContext());
TmpInst.addOperand(MCOperand::createExpr(LoSym));
getStreamer().EmitInstruction(TmpInst, STI);
@@ -786,9 +1048,10 @@ void MipsTargetELFStreamer::emitDirectiveCpLoad(unsigned RegNo) {
forbidModuleDirective();
}
-void MipsTargetELFStreamer::emitDirectiveCpRestore(
- SmallVector<MCInst, 3> &StoreInsts, int Offset) {
- MipsTargetStreamer::emitDirectiveCpRestore(StoreInsts, Offset);
+bool MipsTargetELFStreamer::emitDirectiveCpRestore(
+ int Offset, function_ref<unsigned()> GetATReg, SMLoc IDLoc,
+ const MCSubtargetInfo *STI) {
+ MipsTargetStreamer::emitDirectiveCpRestore(Offset, GetATReg, IDLoc, STI);
// .cprestore offset
// When PIC mode is enabled and the O32 ABI is used, this directive expands
// to:
@@ -798,10 +1061,12 @@ void MipsTargetELFStreamer::emitDirectiveCpRestore(
// Note that .cprestore is ignored if used with the N32 and N64 ABIs or if it
// is used in non-PIC mode.
if (!Pic || (getABI().IsN32() || getABI().IsN64()))
- return;
+ return true;
- for (const MCInst &Inst : StoreInsts)
- getStreamer().EmitInstruction(Inst, STI);
+ // Store the $gp on the stack.
+ emitStoreWithImmOffset(Mips::SW, Mips::GP, Mips::SP, Offset, GetATReg, IDLoc,
+ STI);
+ return true;
}
void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo,
@@ -812,54 +1077,55 @@ void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo,
if (!Pic || !(getABI().IsN32() || getABI().IsN64()))
return;
+ forbidModuleDirective();
+
MCAssembler &MCA = getStreamer().getAssembler();
MCInst Inst;
// Either store the old $gp in a register or on the stack
if (IsReg) {
// move $save, $gpreg
- Inst.setOpcode(Mips::OR64);
- Inst.addOperand(MCOperand::createReg(RegOrOffset));
- Inst.addOperand(MCOperand::createReg(Mips::GP));
- Inst.addOperand(MCOperand::createReg(Mips::ZERO));
+ emitRRR(Mips::OR64, RegOrOffset, Mips::GP, Mips::ZERO, SMLoc(), &STI);
} else {
// sd $gpreg, offset($sp)
- Inst.setOpcode(Mips::SD);
- Inst.addOperand(MCOperand::createReg(Mips::GP));
- Inst.addOperand(MCOperand::createReg(Mips::SP));
- Inst.addOperand(MCOperand::createImm(RegOrOffset));
+ emitRRI(Mips::SD, Mips::GP, Mips::SP, RegOrOffset, SMLoc(), &STI);
}
- getStreamer().EmitInstruction(Inst, STI);
- Inst.clear();
- const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::create(
- &Sym, MCSymbolRefExpr::VK_Mips_GPOFF_HI, MCA.getContext());
- const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::create(
- &Sym, MCSymbolRefExpr::VK_Mips_GPOFF_LO, MCA.getContext());
+ if (getABI().IsN32()) {
+ MCSymbol *GPSym = MCA.getContext().getOrCreateSymbol("__gnu_local_gp");
+ const MipsMCExpr *HiExpr = MipsMCExpr::create(
+ MipsMCExpr::MEK_HI, MCSymbolRefExpr::create(GPSym, MCA.getContext()),
+ MCA.getContext());
+ const MipsMCExpr *LoExpr = MipsMCExpr::create(
+ MipsMCExpr::MEK_LO, MCSymbolRefExpr::create(GPSym, MCA.getContext()),
+ MCA.getContext());
+
+ // lui $gp, %hi(__gnu_local_gp)
+ emitRX(Mips::LUi, Mips::GP, MCOperand::createExpr(HiExpr), SMLoc(), &STI);
+
+ // addiu $gp, $gp, %lo(__gnu_local_gp)
+ emitRRX(Mips::ADDiu, Mips::GP, Mips::GP, MCOperand::createExpr(LoExpr),
+ SMLoc(), &STI);
+
+ return;
+ }
+
+ const MipsMCExpr *HiExpr = MipsMCExpr::createGpOff(
+ MipsMCExpr::MEK_HI, MCSymbolRefExpr::create(&Sym, MCA.getContext()),
+ MCA.getContext());
+ const MipsMCExpr *LoExpr = MipsMCExpr::createGpOff(
+ MipsMCExpr::MEK_LO, MCSymbolRefExpr::create(&Sym, MCA.getContext()),
+ MCA.getContext());
// lui $gp, %hi(%neg(%gp_rel(funcSym)))
- Inst.setOpcode(Mips::LUi);
- Inst.addOperand(MCOperand::createReg(Mips::GP));
- Inst.addOperand(MCOperand::createExpr(HiExpr));
- getStreamer().EmitInstruction(Inst, STI);
- Inst.clear();
+ emitRX(Mips::LUi, Mips::GP, MCOperand::createExpr(HiExpr), SMLoc(), &STI);
// addiu $gp, $gp, %lo(%neg(%gp_rel(funcSym)))
- Inst.setOpcode(Mips::ADDiu);
- Inst.addOperand(MCOperand::createReg(Mips::GP));
- Inst.addOperand(MCOperand::createReg(Mips::GP));
- Inst.addOperand(MCOperand::createExpr(LoExpr));
- getStreamer().EmitInstruction(Inst, STI);
- Inst.clear();
+ emitRRX(Mips::ADDiu, Mips::GP, Mips::GP, MCOperand::createExpr(LoExpr),
+ SMLoc(), &STI);
// daddu $gp, $gp, $funcreg
- Inst.setOpcode(Mips::DADDu);
- Inst.addOperand(MCOperand::createReg(Mips::GP));
- Inst.addOperand(MCOperand::createReg(Mips::GP));
- Inst.addOperand(MCOperand::createReg(RegNo));
- getStreamer().EmitInstruction(Inst, STI);
-
- forbidModuleDirective();
+ emitRRR(Mips::DADDu, Mips::GP, Mips::GP, RegNo, SMLoc(), &STI);
}
void MipsTargetELFStreamer::emitDirectiveCpreturn(unsigned SaveLocation,
diff --git a/lib/Target/Mips/Makefile b/lib/Target/Mips/Makefile
deleted file mode 100644
index 56db450f6961a..0000000000000
--- a/lib/Target/Mips/Makefile
+++ /dev/null
@@ -1,25 +0,0 @@
-##===- lib/Target/Mips/Makefile ----------------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LEVEL = ../../..
-LIBRARYNAME = LLVMMipsCodeGen
-TARGET = Mips
-
-# Make sure that tblgen is run, first thing.
-BUILT_SOURCES = MipsGenRegisterInfo.inc MipsGenInstrInfo.inc \
- MipsGenAsmWriter.inc MipsGenFastISel.inc \
- MipsGenDAGISel.inc MipsGenCallingConv.inc \
- MipsGenSubtargetInfo.inc MipsGenMCCodeEmitter.inc \
- MipsGenDisassemblerTables.inc \
- MipsGenMCPseudoLowering.inc MipsGenAsmMatcher.inc
-
-DIRS = InstPrinter Disassembler AsmParser TargetInfo MCTargetDesc
-
-include $(LEVEL)/Makefile.common
-
diff --git a/lib/Target/Mips/MicroMips32r6InstrFormats.td b/lib/Target/Mips/MicroMips32r6InstrFormats.td
index 400f6eef3fb0c..2f0933277e81a 100644
--- a/lib/Target/Mips/MicroMips32r6InstrFormats.td
+++ b/lib/Target/Mips/MicroMips32r6InstrFormats.td
@@ -14,6 +14,7 @@
class MMR6Arch<string opstr> {
string Arch = "micromipsr6";
string BaseOpcode = opstr;
+ string DecoderNamespace = "MicroMipsR6";
}
// Class used for microMIPS32r6 and microMIPS64r6 instructions.
@@ -22,6 +23,24 @@ class MicroMipsR6Inst16 : PredicateControl {
let InsnPredicates = [HasMicroMips32r6];
}
+//===----------------------------------------------------------------------===//
+//
+// Disambiguators
+//
+//===----------------------------------------------------------------------===//
+//
+// Some encodings are ambiguous except by comparing field values.
+
+class MMDecodeDisambiguatedBy<string Name> : DecodeDisambiguates<Name> {
+ string DecoderNamespace = "MicroMipsR6_Ambiguous";
+}
+
+//===----------------------------------------------------------------------===//
+//
+// Encoding Formats
+//
+//===----------------------------------------------------------------------===//
+
class BC16_FM_MM16R6 {
bits<10> offset;
@@ -52,6 +71,32 @@ class POOL16C_JALRC_FM_MM16R6<bits<5> op> {
let Inst{4-0} = op;
}
+class POP35_BOVC_FM_MMR6<string instr_asm> : MipsR6Inst, MMR6Arch<instr_asm> {
+ bits<5> rt;
+ bits<5> rs;
+ bits<16> offset;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = 0b011101;
+ let Inst{25-21} = rt;
+ let Inst{20-16} = rs;
+ let Inst{15-0} = offset;
+}
+
+class POP37_BNVC_FM_MMR6<string instr_asm> : MipsR6Inst, MMR6Arch<instr_asm> {
+ bits<5> rt;
+ bits<5> rs;
+ bits<16> offset;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = 0b011111;
+ let Inst{25-21} = rt;
+ let Inst{20-16} = rs;
+ let Inst{15-0} = offset;
+}
+
class POOL16C_JRCADDIUSP_FM_MM16R6<bits<5> op> {
bits<5> imm;
@@ -449,7 +494,8 @@ class LOAD_UPPER_IMM_FM_MMR6 {
let Inst{15-0} = imm16;
}
-class CMP_BRANCH_1R_RT_OFF16_FM_MMR6<bits<6> funct> : MipsR6Inst {
+class CMP_BRANCH_1R_RT_OFF16_FM_MMR6<string instr_asm, bits<6> funct>
+ : MMR6Arch<instr_asm>, MipsR6Inst {
bits<5> rt;
bits<16> offset;
@@ -461,7 +507,8 @@ class CMP_BRANCH_1R_RT_OFF16_FM_MMR6<bits<6> funct> : MipsR6Inst {
let Inst{15-0} = offset;
}
-class CMP_BRANCH_1R_BOTH_OFF16_FM_MMR6<bits<6> funct> : MipsR6Inst {
+class CMP_BRANCH_1R_BOTH_OFF16_FM_MMR6<string instr_asm, bits<6> funct>
+ : MMR6Arch<instr_asm>, MipsR6Inst {
bits<5> rt;
bits<16> offset;
@@ -473,6 +520,37 @@ class CMP_BRANCH_1R_BOTH_OFF16_FM_MMR6<bits<6> funct> : MipsR6Inst {
let Inst{15-0} = offset;
}
+class POOL32A_JALRC_FM_MMR6<string instr_asm, bits<10> funct>
+ : MipsR6Inst, MMR6Arch<instr_asm> {
+ bits<5> rt;
+ bits<5> rs;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = 0;
+ let Inst{25-21} = rt;
+ let Inst{20-16} = rs;
+ let Inst{15-6} = funct;
+ let Inst{5-0} = 0b111100;
+}
+
+class POOL32A_EXT_INS_FM_MMR6<string instr_asm, bits<6> funct>
+ : MMR6Arch<instr_asm>, MipsR6Inst {
+ bits<5> rt;
+ bits<5> rs;
+ bits<5> size;
+ bits<5> pos;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = 0;
+ let Inst{25-21} = rt;
+ let Inst{20-16} = rs;
+ let Inst{15-11} = size;
+ let Inst{10-6} = pos;
+ let Inst{5-0} = funct;
+}
+
class POOL32A_ERET_FM_MMR6<string instr_asm, bits<10> funct>
: MMR6Arch<instr_asm> {
bits<32> Inst;
@@ -751,7 +829,7 @@ class POOL16C_NOT16_FM_MMR6 : MicroMipsR6Inst16 {
let Inst{3-0} = 0b0000;
}
-class POOL16C_OR16_XOR16_FM_MMR6<bits<4> op> {
+class POOL16C_OR16_XOR16_FM_MMR6<bits<4> op> : MicroMipsR6Inst16 {
bits<3> rt;
bits<3> rs;
@@ -860,3 +938,157 @@ class POOL32F_CLASS_FM_MMR6<string instr_asm, bits<2> fmt, bits<9> funct>
let Inst{10-9} = fmt;
let Inst{8-0} = funct;
}
+
+class POOL32A_TLBINV_FM_MMR6<string instr_asm, bits<10> funct>
+ : MMR6Arch<instr_asm>, MipsR6Inst {
+ bits<32> Inst;
+
+ let Inst{31-26} = 0x0;
+ let Inst{25-16} = 0x0;
+ let Inst{15-6} = funct;
+ let Inst{5-0} = 0b111100;
+}
+
+class POOL32A_MFTC0_FM_MMR6<string instr_asm, bits<5> funct, bits<6> opcode>
+ : MMR6Arch<instr_asm>, MipsR6Inst {
+ bits<5> rt;
+ bits<5> rs;
+ bits<3> sel;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = 0b000000;
+ let Inst{25-21} = rt;
+ let Inst{20-16} = rs;
+ let Inst{15-14} = 0;
+ let Inst{13-11} = sel;
+ let Inst{10-6} = funct;
+ let Inst{5-0} = opcode;
+}
+
+class POOL32F_MFTC1_FM_MMR6<string instr_asm, bits<8> funct>
+ : MMR6Arch<instr_asm> {
+ bits<5> rt;
+ bits<5> fs;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = 0b010101;
+ let Inst{25-21} = rt;
+ let Inst{20-16} = fs;
+ let Inst{15-14} = 0;
+ let Inst{13-6} = funct;
+ let Inst{5-0} = 0b111011;
+}
+
+class POOL32A_MFTC2_FM_MMR6<string instr_asm, bits<10> funct>
+ : MMR6Arch<instr_asm>, MipsR6Inst {
+ bits<5> rt;
+ bits<5> impl;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = 0b000000;
+ let Inst{25-21} = rt;
+ let Inst{20-16} = impl;
+ let Inst{15-6} = funct;
+ let Inst{5-0} = 0b111100;
+}
+
+class CMP_BRANCH_2R_OFF16_FM_MMR6<string opstr, bits<6> funct>
+ : MipsR6Inst, MMR6Arch<opstr> {
+ bits<5> rt;
+ bits<5> rs;
+ bits<16> offset;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = funct;
+ let Inst{25-21} = rt;
+ let Inst{20-16} = rs;
+ let Inst{15-0} = offset;
+}
+
+class POOL32A_DVPEVP_FM_MMR6<string instr_asm, bits<10> funct>
+ : MMR6Arch<instr_asm>, MipsR6Inst {
+ bits<5> rs;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = 0b000000;
+ let Inst{25-21} = 0b00000;
+ let Inst{20-16} = rs;
+ let Inst{15-6} = funct;
+ let Inst{5-0} = 0b111100;
+}
+
+class POOL32B_LWP_SWP_FM_MMR6<bits<4> funct> : MipsR6Inst {
+ bits<5> rd;
+ bits<21> addr;
+ bits<5> base = addr{20-16};
+ bits<12> offset = addr{11-0};
+
+ bits<32> Inst;
+
+ let Inst{31-26} = 0x8;
+ let Inst{25-21} = rd;
+ let Inst{20-16} = base;
+ let Inst{15-12} = funct;
+ let Inst{11-0} = offset;
+}
+
+class CMP_BRANCH_OFF21_FM_MMR6<string opstr, bits<6> funct> : MipsR6Inst {
+ bits<5> rs;
+ bits<21> offset;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = funct;
+ let Inst{25-21} = rs;
+ let Inst{20-0} = offset;
+}
+
+class POOL32I_BRANCH_COP_1_2_FM_MMR6<string instr_asm, bits<5> funct>
+ : MMR6Arch<instr_asm> {
+ bits<5> rt;
+ bits<16> offset;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = 0b010000;
+ let Inst{25-21} = funct;
+ let Inst{20-16} = rt;
+ let Inst{15-0} = offset;
+}
+
+class LDWC1_SDWC1_FM_MMR6<string instr_asm, bits<6> funct>
+ : MMR6Arch<instr_asm> {
+ bits<5> ft;
+ bits<21> addr;
+ bits<5> base = addr{20-16};
+ bits<16> offset = addr{15-0};
+
+ bits<32> Inst;
+
+ let Inst{31-26} = funct;
+ let Inst{25-21} = ft;
+ let Inst{20-16} = base;
+ let Inst{15-0} = offset;
+}
+
+class POOL32B_LDWC2_SDWC2_FM_MMR6<string instr_asm, bits<4> funct>
+ : MMR6Arch<instr_asm>, MipsR6Inst {
+ bits<5> rt;
+ bits<21> addr;
+ bits<5> base = addr{20-16};
+ bits<11> offset = addr{10-0};
+
+ bits<32> Inst;
+
+ let Inst{31-26} = 0b001000;
+ let Inst{25-21} = rt;
+ let Inst{20-16} = base;
+ let Inst{15-12} = funct;
+ let Inst{11} = 0;
+ let Inst{10-0} = offset;
+}
diff --git a/lib/Target/Mips/MicroMips32r6InstrInfo.td b/lib/Target/Mips/MicroMips32r6InstrInfo.td
index 31b5db036daa6..2b636cfe3bfe7 100644
--- a/lib/Target/Mips/MicroMips32r6InstrInfo.td
+++ b/lib/Target/Mips/MicroMips32r6InstrInfo.td
@@ -11,6 +11,13 @@
//
//===----------------------------------------------------------------------===//
+def brtarget21_mm : Operand<OtherVT> {
+ let EncoderMethod = "getBranchTarget21OpValueMM";
+ let OperandType = "OPERAND_PCREL";
+ let DecoderMethod = "DecodeBranchTarget21MM";
+ let ParserMatchClass = MipsJumpTargetAsmOperand;
+}
+
def brtarget26_mm : Operand<OtherVT> {
let EncoderMethod = "getBranchTarget26OpValueMM";
let OperandType = "OPERAND_PCREL";
@@ -18,6 +25,13 @@ def brtarget26_mm : Operand<OtherVT> {
let ParserMatchClass = MipsJumpTargetAsmOperand;
}
+def brtargetr6 : Operand<OtherVT> {
+ let EncoderMethod = "getBranchTargetOpValueMMR6";
+ let OperandType = "OPERAND_PCREL";
+ let DecoderMethod = "DecodeBranchTargetMM";
+ let ParserMatchClass = MipsJumpTargetAsmOperand;
+}
+
//===----------------------------------------------------------------------===//
//
// Instruction Encodings
@@ -40,12 +54,26 @@ class BEQZC16_MMR6_ENC : BEQZC_BNEZC_FM_MM16R6<0x23>;
class BNEZC16_MMR6_ENC : BEQZC_BNEZC_FM_MM16R6<0x2b>;
class BITSWAP_MMR6_ENC : POOL32A_BITSWAP_FM_MMR6<0b101100>;
class BRK_MMR6_ENC : BREAK_MMR6_ENC<"break">;
-class BEQZALC_MMR6_ENC : CMP_BRANCH_1R_RT_OFF16_FM_MMR6<0b011101>;
-class BNEZALC_MMR6_ENC : CMP_BRANCH_1R_RT_OFF16_FM_MMR6<0b011111>;
-class BGTZALC_MMR6_ENC : CMP_BRANCH_1R_RT_OFF16_FM_MMR6<0b111000>;
-class BLTZALC_MMR6_ENC : CMP_BRANCH_1R_BOTH_OFF16_FM_MMR6<0b111000>;
-class BGEZALC_MMR6_ENC : CMP_BRANCH_1R_BOTH_OFF16_FM_MMR6<0b110000>;
-class BLEZALC_MMR6_ENC : CMP_BRANCH_1R_RT_OFF16_FM_MMR6<0b110000>;
+class BEQZC_MMR6_ENC : CMP_BRANCH_OFF21_FM_MMR6<"beqzc", 0b100000>;
+class BNEZC_MMR6_ENC : CMP_BRANCH_OFF21_FM_MMR6<"bnezc", 0b101000>;
+class BGEC_MMR6_ENC : CMP_BRANCH_2R_OFF16_FM_MMR6<"bgec", 0b111001>;
+class BGEUC_MMR6_ENC : CMP_BRANCH_2R_OFF16_FM_MMR6<"bgeuc", 0b110000>,
+ DecodeDisambiguates<"BlezGroupBranchMMR6">;
+class BLTC_MMR6_ENC : CMP_BRANCH_2R_OFF16_FM_MMR6<"bltc", 0b110001>;
+class BLTUC_MMR6_ENC : CMP_BRANCH_2R_OFF16_FM_MMR6<"bltuc", 0b111000>,
+ DecodeDisambiguates<"BgtzGroupBranchMMR6">;
+class BEQC_MMR6_ENC : CMP_BRANCH_2R_OFF16_FM_MMR6<"beqc", 0b011101>;
+class BNEC_MMR6_ENC : CMP_BRANCH_2R_OFF16_FM_MMR6<"bnec", 0b011111>;
+class BEQZALC_MMR6_ENC : CMP_BRANCH_1R_RT_OFF16_FM_MMR6<"beqzalc", 0b011101>;
+class BNEZALC_MMR6_ENC : CMP_BRANCH_1R_RT_OFF16_FM_MMR6<"bnezalc", 0b011111>;
+class BGTZALC_MMR6_ENC : CMP_BRANCH_1R_RT_OFF16_FM_MMR6<"bgtzalc", 0b111000>,
+ MMDecodeDisambiguatedBy<"BgtzGroupBranchMMR6">;
+class BLTZALC_MMR6_ENC : CMP_BRANCH_1R_BOTH_OFF16_FM_MMR6<"bltzalc", 0b111000>,
+ MMDecodeDisambiguatedBy<"BgtzGroupBranchMMR6">;
+class BGEZALC_MMR6_ENC : CMP_BRANCH_1R_BOTH_OFF16_FM_MMR6<"bgezalc", 0b110000>,
+ MMDecodeDisambiguatedBy<"BlezGroupBranchMMR6">;
+class BLEZALC_MMR6_ENC : CMP_BRANCH_1R_RT_OFF16_FM_MMR6<"blezalc", 0b110000>,
+ MMDecodeDisambiguatedBy<"BlezGroupBranchMMR6">;
class CACHE_MMR6_ENC : CACHE_PREF_FM_MMR6<0b001000, 0b0110>;
class CLO_MMR6_ENC : POOL32A_2R_FM_MMR6<0b0100101100>;
class CLZ_MMR6_ENC : SPECIAL_2R_FM_MMR6<0b010000>;
@@ -63,14 +91,27 @@ class JIC_MMR6_ENC : JMP_IDX_COMPACT_FM<0b101000>;
class JRC16_MMR6_ENC: POOL16C_JALRC_FM_MM16R6<0x3>;
class JRCADDIUSP_MMR6_ENC : POOL16C_JRCADDIUSP_FM_MM16R6<0x13>;
class LSA_MMR6_ENC : POOL32A_LSA_FM<0b001111>;
+class LWP_MMR6_ENC : POOL32B_LWP_SWP_FM_MMR6<0x1>;
class LWPC_MMR6_ENC : PCREL19_FM_MMR6<0b01>;
class LWM16_MMR6_ENC : POOL16C_LWM_SWM_FM_MM16R6<0x2>;
+class MFC0_MMR6_ENC : POOL32A_MFTC0_FM_MMR6<"mfc0", 0b00011, 0b111100>;
+class MFC1_MMR6_ENC : POOL32F_MFTC1_FM_MMR6<"mfc1", 0b10000000>;
+class MFC2_MMR6_ENC : POOL32A_MFTC2_FM_MMR6<"mfc2", 0b0100110100>;
+class MFHC0_MMR6_ENC : POOL32A_MFTC0_FM_MMR6<"mfhc0", 0b00011, 0b110100>;
+class MFHC1_MMR6_ENC : POOL32F_MFTC1_FM_MMR6<"mfhc1", 0b11000000>;
+class MFHC2_MMR6_ENC : POOL32A_MFTC2_FM_MMR6<"mfhc2", 0b1000110100>;
class MOD_MMR6_ENC : ARITH_FM_MMR6<"mod", 0x158>;
class MODU_MMR6_ENC : ARITH_FM_MMR6<"modu", 0x1d8>;
class MUL_MMR6_ENC : ARITH_FM_MMR6<"mul", 0x18>;
class MUH_MMR6_ENC : ARITH_FM_MMR6<"muh", 0x58>;
class MULU_MMR6_ENC : ARITH_FM_MMR6<"mulu", 0x98>;
class MUHU_MMR6_ENC : ARITH_FM_MMR6<"muhu", 0xd8>;
+class MTC0_MMR6_ENC : POOL32A_MFTC0_FM_MMR6<"mtc0", 0b01011, 0b111100>;
+class MTC1_MMR6_ENC : POOL32F_MFTC1_FM_MMR6<"mtc1", 0b10100000>;
+class MTC2_MMR6_ENC : POOL32A_MFTC2_FM_MMR6<"mtc2", 0b0101110100>;
+class MTHC0_MMR6_ENC : POOL32A_MFTC0_FM_MMR6<"mthc0", 0b01011, 0b110100>;
+class MTHC1_MMR6_ENC : POOL32F_MFTC1_FM_MMR6<"mthc1", 0b11100000>;
+class MTHC2_MMR6_ENC : POOL32A_MFTC2_FM_MMR6<"mthc2", 0b1001110100>;
class NOR_MMR6_ENC : ARITH_FM_MMR6<"nor", 0x2d0>;
class OR_MMR6_ENC : ARITH_FM_MMR6<"or", 0x290>;
class ORI_MMR6_ENC : ADDI_FM_MMR6<"ori", 0x14>;
@@ -89,6 +130,7 @@ class SWE_MMR6_ENC : POOL32C_SWE_FM_MMR6<"swe", 0x18, 0xa, 0x7>;
class SW16_MMR6_ENC : LOAD_STORE_FM_MM16<0x3a>;
class SWM16_MMR6_ENC : POOL16C_LWM_SWM_FM_MM16R6<0xa>;
class SWSP_MMR6_ENC : LOAD_STORE_SP_FM_MM16<0x32>;
+class SWP_MMR6_ENC : POOL32B_LWP_SWP_FM_MMR6<0x9>;
class PREFE_MMR6_ENC : POOL32C_ST_EVA_FM_MMR6<0b011000, 0b010>;
class CACHEE_MMR6_ENC : POOL32C_ST_EVA_FM_MMR6<0b011000, 0b011>;
class WRPGPR_MMR6_ENC : POOL32A_WRPGPR_WSBH_FM_MMR6<0x3c5>;
@@ -134,6 +176,7 @@ class LLE_MMR6_ENC : LOAD_WORD_EVA_FM_MMR6<0b110>;
class LWE_MMR6_ENC : LOAD_WORD_EVA_FM_MMR6<0b111>;
class LW_MMR6_ENC : LOAD_WORD_FM_MMR6;
class LUI_MMR6_ENC : LOAD_UPPER_IMM_FM_MMR6;
+class JALRC_HB_MMR6_ENC : POOL32A_JALRC_FM_MMR6<"jalrc.hb", 0b0001111100>;
class RECIP_S_MMR6_ENC : POOL32F_RECIP_ROUND_FM_MMR6<"recip.s", 0, 0b01001000>;
class RECIP_D_MMR6_ENC : POOL32F_RECIP_ROUND_FM_MMR6<"recip.d", 1, 0b01001000>;
class RINT_S_MMR6_ENC : POOL32F_RINT_FM_MMR6<"rint.s", 0>;
@@ -150,11 +193,15 @@ class SEL_S_MMR6_ENC : POOL32F_SEL_FM_MMR6<"sel.s", 0, 0b010111000>;
class SEL_D_MMR6_ENC : POOL32F_SEL_FM_MMR6<"sel.d", 1, 0b010111000>;
class SELEQZ_S_MMR6_ENC : POOL32F_SEL_FM_MMR6<"seleqz.s", 0, 0b000111000>;
class SELEQZ_D_MMR6_ENC : POOL32F_SEL_FM_MMR6<"seleqz.d", 1, 0b000111000>;
-class SELENZ_S_MMR6_ENC : POOL32F_SEL_FM_MMR6<"selenz.s", 0, 0b001111000>;
-class SELENZ_D_MMR6_ENC : POOL32F_SEL_FM_MMR6<"selenz.d", 1, 0b001111000>;
+class SELNEZ_S_MMR6_ENC : POOL32F_SEL_FM_MMR6<"selnez.s", 0, 0b001111000>;
+class SELNEZ_D_MMR6_ENC : POOL32F_SEL_FM_MMR6<"selnez.d", 1, 0b001111000>;
class CLASS_S_MMR6_ENC : POOL32F_CLASS_FM_MMR6<"class.s", 0, 0b001100000>;
class CLASS_D_MMR6_ENC : POOL32F_CLASS_FM_MMR6<"class.d", 1, 0b001100000>;
-
+class EXT_MMR6_ENC : POOL32A_EXT_INS_FM_MMR6<"ext", 0b101100>;
+class INS_MMR6_ENC : POOL32A_EXT_INS_FM_MMR6<"ins", 0b001100>;
+class JALRC_MMR6_ENC : POOL32A_JALRC_FM_MMR6<"jalrc", 0b0000111100>;
+class BOVC_MMR6_ENC : POP35_BOVC_FM_MMR6<"bovc">;
+class BNVC_MMR6_ENC : POP37_BNVC_FM_MMR6<"bnvc">;
class ADDU16_MMR6_ENC : POOL16A_ADDU16_FM_MMR6;
class AND16_MMR6_ENC : POOL16C_AND16_FM_MMR6;
class ANDI16_MMR6_ENC : ANDI_FM_MM16<0b001011>, MicroMipsR6Inst16;
@@ -168,10 +215,24 @@ class MOVE16_MMR6_ENC : MOVE_FM_MM16<0b000011>;
class SDBBP16_MMR6_ENC : POOL16C_BREAKPOINT_FM_MMR6<0b111011>;
class SUBU16_MMR6_ENC : POOL16A_SUBU16_FM_MMR6;
class XOR16_MMR6_ENC : POOL16C_OR16_XOR16_FM_MMR6<0b1000>;
+class TLBINV_MMR6_ENC : POOL32A_TLBINV_FM_MMR6<"tlbinv", 0x10d>;
+class TLBINVF_MMR6_ENC : POOL32A_TLBINV_FM_MMR6<"tlbinvf", 0x14d>;
+class DVP_MMR6_ENC : POOL32A_DVPEVP_FM_MMR6<"dvp", 0b0001100101>;
+class EVP_MMR6_ENC : POOL32A_DVPEVP_FM_MMR6<"evp", 0b0011100101>;
+class BC1EQZC_MMR6_ENC : POOL32I_BRANCH_COP_1_2_FM_MMR6<"bc1eqzc", 0b01000>;
+class BC1NEZC_MMR6_ENC : POOL32I_BRANCH_COP_1_2_FM_MMR6<"bc1nezc", 0b01001>;
+class BC2EQZC_MMR6_ENC : POOL32I_BRANCH_COP_1_2_FM_MMR6<"bc2eqzc", 0b01010>;
+class BC2NEZC_MMR6_ENC : POOL32I_BRANCH_COP_1_2_FM_MMR6<"bc2nezc", 0b01011>;
+class LDC1_MMR6_ENC : LDWC1_SDWC1_FM_MMR6<"ldc1", 0b101111>;
+class SDC1_MMR6_ENC : LDWC1_SDWC1_FM_MMR6<"sdc1", 0b101110>;
+class LDC2_MMR6_ENC : POOL32B_LDWC2_SDWC2_FM_MMR6<"ldc2", 0b0010>;
+class SDC2_MMR6_ENC : POOL32B_LDWC2_SDWC2_FM_MMR6<"sdc2", 0b1010>;
+class LWC2_MMR6_ENC : POOL32B_LDWC2_SDWC2_FM_MMR6<"lwc2", 0b0000>;
+class SWC2_MMR6_ENC : POOL32B_LDWC2_SDWC2_FM_MMR6<"swc2", 0b1000>;
class CMP_CBR_RT_Z_MMR6_DESC_BASE<string instr_asm, DAGOperand opnd,
RegisterOperand GPROpnd>
- : BRANCH_DESC_BASE, MMR6Arch<instr_asm> {
+ : BRANCH_DESC_BASE {
dag InOperandList = (ins GPROpnd:$rt, opnd:$offset);
dag OutOperandList = (outs);
string AsmString = !strconcat(instr_asm, "\t$rt, $offset");
@@ -208,6 +269,27 @@ class BNEZALC_MMR6_DESC : CMP_CBR_RT_Z_MMR6_DESC_BASE<"bnezalc", brtarget_mm,
list<Register> Defs = [RA];
}
+class CMP_CBR_2R_MMR6_DESC_BASE<string instr_asm, DAGOperand opnd,
+ RegisterOperand GPROpnd> : BRANCH_DESC_BASE {
+ dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt, opnd:$offset);
+ dag OutOperandList = (outs);
+ string AsmString = !strconcat(instr_asm, "\t$rs, $rt, $offset");
+ list<Register> Defs = [AT];
+}
+
+class BGEC_MMR6_DESC : CMP_CBR_2R_MMR6_DESC_BASE<"bgec", brtarget_mm,
+ GPR32Opnd>;
+class BGEUC_MMR6_DESC : CMP_CBR_2R_MMR6_DESC_BASE<"bgeuc", brtarget_mm,
+ GPR32Opnd>;
+class BLTC_MMR6_DESC : CMP_CBR_2R_MMR6_DESC_BASE<"bltc", brtarget_mm,
+ GPR32Opnd>;
+class BLTUC_MMR6_DESC : CMP_CBR_2R_MMR6_DESC_BASE<"bltuc", brtarget_mm,
+ GPR32Opnd>;
+class BEQC_MMR6_DESC : CMP_CBR_2R_MMR6_DESC_BASE<"beqc", brtarget_mm,
+ GPR32Opnd>;
+class BNEC_MMR6_DESC : CMP_CBR_2R_MMR6_DESC_BASE<"bnec", brtarget_mm,
+ GPR32Opnd>;
+
/// Floating Point Instructions
class FADD_S_MMR6_ENC : POOL32F_ARITH_FM_MMR6<"add.s", 0, 0b00110000>;
class FADD_D_MMR6_ENC : POOL32F_ARITH_FM_MMR6<"add.d", 1, 0b00110000>;
@@ -252,12 +334,12 @@ class CVT_S_L_MMR6_ENC : POOL32F_CVT_DS_FM<"cvt.s.l", 2, 0b1101101>;
//===----------------------------------------------------------------------===//
class ADD_MMR6_DESC : ArithLogicR<"add", GPR32Opnd>;
-class ADDIU_MMR6_DESC : ArithLogicI<"addiu", simm16, GPR32Opnd>;
+class ADDIU_MMR6_DESC : ArithLogicI<"addiu", simm16, GPR32Opnd, II_ADDIU, immSExt16, add>;
class ADDU_MMR6_DESC : ArithLogicR<"addu", GPR32Opnd>;
-class MUL_MMR6_DESC : ArithLogicR<"mul", GPR32Opnd>;
-class MUH_MMR6_DESC : ArithLogicR<"muh", GPR32Opnd>;
-class MULU_MMR6_DESC : ArithLogicR<"mulu", GPR32Opnd>;
-class MUHU_MMR6_DESC : ArithLogicR<"muhu", GPR32Opnd>;
+class MUL_MMR6_DESC : ArithLogicR<"mul", GPR32Opnd, 1, II_MUL, mul>;
+class MUH_MMR6_DESC : ArithLogicR<"muh", GPR32Opnd, 1, II_MUH, mulhs>;
+class MULU_MMR6_DESC : ArithLogicR<"mulu", GPR32Opnd, 1, II_MULU>;
+class MUHU_MMR6_DESC : ArithLogicR<"muhu", GPR32Opnd, 1, II_MUHU, mulhu>;
class BC_MMR6_DESC_BASE<string instr_asm, DAGOperand opnd>
: BRANCH_DESC_BASE, MMR6Arch<instr_asm> {
@@ -476,6 +558,32 @@ class PCREL_MMR6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd,
class ADDIUPC_MMR6_DESC : PCREL_MMR6_DESC_BASE<"addiupc", GPR32Opnd, simm19_lsl2>;
class LWPC_MMR6_DESC: PCREL_MMR6_DESC_BASE<"lwpc", GPR32Opnd, simm19_lsl2>;
+class LWP_MMR6_DESC : MMR6Arch<"lwp"> {
+ dag OutOperandList = (outs regpair:$rd);
+ dag InOperandList = (ins mem_simm12:$addr);
+ string AsmString = !strconcat("lwp", "\t$rd, $addr");
+ list<dag> Pattern = [];
+ InstrItinClass Itin = NoItinerary;
+ ComplexPattern Addr = addr;
+ Format f = FrmI;
+ string BaseOpcode = "lwp";
+ string DecoderMethod = "DecodeMemMMImm12";
+ bit mayLoad = 1;
+}
+
+class SWP_MMR6_DESC : MMR6Arch<"swp"> {
+ dag OutOperandList = (outs);
+ dag InOperandList = (ins regpair:$rd, mem_simm12:$addr);
+ string AsmString = !strconcat("swp", "\t$rd, $addr");
+ list<dag> Pattern = [];
+ InstrItinClass Itin = NoItinerary;
+ ComplexPattern Addr = addr;
+ Format f = FrmI;
+ string BaseOpcode = "swp";
+ string DecoderMethod = "DecodeMemMMImm12";
+ bit mayStore = 1;
+}
+
class SELEQNE_Z_MMR6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd>
: MMR6Arch<instr_asm> {
dag OutOperandList = (outs GPROpnd:$rd);
@@ -499,17 +607,38 @@ class RDHWR_MMR6_DESC : MMR6Arch<"rdhwr">, MipsR6Inst {
class WAIT_MMR6_DESC : WaitMM<"wait">;
class SSNOP_MMR6_DESC : Barrier<"ssnop">;
class SLL_MMR6_DESC : shift_rotate_imm<"sll", uimm5, GPR32Opnd, II_SLL>;
-class DIV_MMR6_DESC : ArithLogicR<"div", GPR32Opnd>;
-class DIVU_MMR6_DESC : ArithLogicR<"divu", GPR32Opnd>;
-class MOD_MMR6_DESC : ArithLogicR<"mod", GPR32Opnd>;
-class MODU_MMR6_DESC : ArithLogicR<"modu", GPR32Opnd>;
-class AND_MMR6_DESC : ArithLogicR<"and", GPR32Opnd>;
-class ANDI_MMR6_DESC : ArithLogicI<"andi", simm16, GPR32Opnd>;
-class NOR_MMR6_DESC : ArithLogicR<"nor", GPR32Opnd>;
-class OR_MMR6_DESC : ArithLogicR<"or", GPR32Opnd>;
-class ORI_MMR6_DESC : ArithLogicI<"ori", simm16, GPR32Opnd>;
-class XOR_MMR6_DESC : ArithLogicR<"xor", GPR32Opnd>;
-class XORI_MMR6_DESC : ArithLogicI<"xori", simm16, GPR32Opnd>;
+
+class DIVMOD_MMR6_DESC_BASE<string opstr, RegisterOperand GPROpnd,
+ SDPatternOperator OpNode=null_frag>
+ : MipsR6Inst {
+ dag OutOperandList = (outs GPROpnd:$rd);
+ dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt);
+ string AsmString = !strconcat(opstr, "\t$rd, $rs, $rt");
+ list<dag> Pattern = [(set GPROpnd:$rd, (OpNode GPROpnd:$rs, GPROpnd:$rt))];
+ string BaseOpcode = opstr;
+ Format f = FrmR;
+ let isCommutable = 0;
+ let isReMaterializable = 1;
+
+ // This instruction doesn't trap division by zero itself. We must insert
+ // teq instructions as well.
+ bit usesCustomInserter = 1;
+}
+class DIV_MMR6_DESC : DIVMOD_MMR6_DESC_BASE<"div", GPR32Opnd, sdiv>;
+class DIVU_MMR6_DESC : DIVMOD_MMR6_DESC_BASE<"divu", GPR32Opnd, udiv>;
+class MOD_MMR6_DESC : DIVMOD_MMR6_DESC_BASE<"mod", GPR32Opnd, srem>;
+class MODU_MMR6_DESC : DIVMOD_MMR6_DESC_BASE<"modu", GPR32Opnd, urem>;
+class AND_MMR6_DESC : ArithLogicR<"and", GPR32Opnd, 1, II_AND, and>;
+class ANDI_MMR6_DESC : ArithLogicI<"andi", uimm16, GPR32Opnd, II_ANDI>;
+class NOR_MMR6_DESC : LogicNOR<"nor", GPR32Opnd>;
+class OR_MMR6_DESC : ArithLogicR<"or", GPR32Opnd, 1, II_OR, or>;
+class ORI_MMR6_DESC : ArithLogicI<"ori", uimm16, GPR32Opnd, II_ORI, immZExt16,
+ or> {
+ int AddedComplexity = 1;
+}
+class XOR_MMR6_DESC : ArithLogicR<"xor", GPR32Opnd, 1, II_XOR, xor>;
+class XORI_MMR6_DESC : ArithLogicI<"xori", uimm16, GPR32Opnd, II_XORI,
+ immZExt16, xor>;
class SWE_MMR6_DESC_BASE<string opstr, DAGOperand RO, DAGOperand MO,
SDPatternOperator OpNode = null_frag,
@@ -536,6 +665,155 @@ class WRPGPR_WSBH_MMR6_DESC_BASE<string instr_asm, RegisterOperand RO>
class WRPGPR_MMR6_DESC : WRPGPR_WSBH_MMR6_DESC_BASE<"wrpgpr", GPR32Opnd>;
class WSBH_MMR6_DESC : WRPGPR_WSBH_MMR6_DESC_BASE<"wsbh", GPR32Opnd>;
+class MTC0_MMR6_DESC_BASE<string opstr, RegisterOperand DstRC,
+ RegisterOperand SrcRC> {
+ dag InOperandList = (ins SrcRC:$rt, uimm3:$sel);
+ dag OutOperandList = (outs DstRC:$rs);
+ string AsmString = !strconcat(opstr, "\t$rt, $rs, $sel");
+ list<dag> Pattern = [];
+ Format f = FrmFR;
+ string BaseOpcode = opstr;
+}
+class MTC1_MMR6_DESC_BASE<
+ string opstr, RegisterOperand DstRC, RegisterOperand SrcRC,
+ InstrItinClass Itin = NoItinerary, SDPatternOperator OpNode = null_frag>
+ : MipsR6Inst {
+ dag InOperandList = (ins SrcRC:$rt);
+ dag OutOperandList = (outs DstRC:$fs);
+ string AsmString = !strconcat(opstr, "\t$rt, $fs");
+ list<dag> Pattern = [(set DstRC:$fs, (OpNode SrcRC:$rt))];
+ Format f = FrmFR;
+ InstrItinClass Itinerary = Itin;
+ string BaseOpcode = opstr;
+}
+class MTC1_64_MMR6_DESC_BASE<
+ string opstr, RegisterOperand DstRC, RegisterOperand SrcRC,
+ InstrItinClass Itin = NoItinerary> : MipsR6Inst {
+ dag InOperandList = (ins DstRC:$fs_in, SrcRC:$rt);
+ dag OutOperandList = (outs DstRC:$fs);
+ string AsmString = !strconcat(opstr, "\t$rt, $fs");
+ list<dag> Pattern = [];
+ Format f = FrmFR;
+ InstrItinClass Itinerary = Itin;
+ string BaseOpcode = opstr;
+ // $fs_in is part of a white lie to work around a widespread bug in the FPU
+ // implementation. See expandBuildPairF64 for details.
+ let Constraints = "$fs = $fs_in";
+}
+class MTC2_MMR6_DESC_BASE<string opstr, RegisterOperand DstRC,
+ RegisterOperand SrcRC> {
+ dag InOperandList = (ins SrcRC:$rt);
+ dag OutOperandList = (outs DstRC:$impl);
+ string AsmString = !strconcat(opstr, "\t$rt, $impl");
+ list<dag> Pattern = [];
+ Format f = FrmFR;
+ string BaseOpcode = opstr;
+}
+
+class MTC0_MMR6_DESC : MTC0_MMR6_DESC_BASE<"mtc0", COP0Opnd, GPR32Opnd>;
+class MTC1_MMR6_DESC : MTC1_MMR6_DESC_BASE<"mtc1", FGR32Opnd, GPR32Opnd,
+ II_MTC1, bitconvert>, HARDFLOAT;
+class MTC2_MMR6_DESC : MTC2_MMR6_DESC_BASE<"mtc2", COP2Opnd, GPR32Opnd>;
+class MTHC0_MMR6_DESC : MTC0_MMR6_DESC_BASE<"mthc0", COP0Opnd, GPR32Opnd>;
+class MTHC1_D32_MMR6_DESC : MTC1_64_MMR6_DESC_BASE<"mthc1", AFGR64Opnd, GPR32Opnd>,
+ HARDFLOAT, FGR_32;
+class MTHC1_D64_MMR6_DESC : MTC1_64_MMR6_DESC_BASE<"mthc1", FGR64Opnd, GPR32Opnd>,
+ HARDFLOAT, FGR_64;
+class MTHC2_MMR6_DESC : MTC2_MMR6_DESC_BASE<"mthc2", COP2Opnd, GPR32Opnd>;
+
+class MFC0_MMR6_DESC_BASE<string opstr, RegisterOperand DstRC,
+ RegisterOperand SrcRC> {
+ dag InOperandList = (ins SrcRC:$rs, uimm3:$sel);
+ dag OutOperandList = (outs DstRC:$rt);
+ string AsmString = !strconcat(opstr, "\t$rt, $rs, $sel");
+ list<dag> Pattern = [];
+ Format f = FrmFR;
+ string BaseOpcode = opstr;
+}
+class MFC1_MMR6_DESC_BASE<string opstr, RegisterOperand DstRC,
+ RegisterOperand SrcRC,
+ InstrItinClass Itin = NoItinerary,
+ SDPatternOperator OpNode = null_frag> : MipsR6Inst {
+ dag InOperandList = (ins SrcRC:$fs);
+ dag OutOperandList = (outs DstRC:$rt);
+ string AsmString = !strconcat(opstr, "\t$rt, $fs");
+ list<dag> Pattern = [(set DstRC:$rt, (OpNode SrcRC:$fs))];
+ Format f = FrmFR;
+ InstrItinClass Itinerary = Itin;
+ string BaseOpcode = opstr;
+}
+class MFC2_MMR6_DESC_BASE<string opstr, RegisterOperand DstRC,
+ RegisterOperand SrcRC> {
+ dag InOperandList = (ins SrcRC:$impl);
+ dag OutOperandList = (outs DstRC:$rt);
+ string AsmString = !strconcat(opstr, "\t$rt, $impl");
+ list<dag> Pattern = [];
+ Format f = FrmFR;
+ string BaseOpcode = opstr;
+}
+class MFC0_MMR6_DESC : MFC0_MMR6_DESC_BASE<"mfc0", GPR32Opnd, COP0Opnd>;
+class MFC1_MMR6_DESC : MFC1_MMR6_DESC_BASE<"mfc1", GPR32Opnd, FGR32Opnd,
+ II_MFC1, bitconvert>, HARDFLOAT;
+class MFC2_MMR6_DESC : MFC2_MMR6_DESC_BASE<"mfc2", GPR32Opnd, COP2Opnd>;
+class MFHC0_MMR6_DESC : MFC0_MMR6_DESC_BASE<"mfhc0", GPR32Opnd, COP0Opnd>;
+class MFHC1_D32_MMR6_DESC : MFC1_MMR6_DESC_BASE<"mfhc1", GPR32Opnd, AFGR64Opnd,
+ II_MFHC1>, HARDFLOAT, FGR_32;
+class MFHC1_D64_MMR6_DESC : MFC1_MMR6_DESC_BASE<"mfhc1", GPR32Opnd, FGR64Opnd,
+ II_MFHC1>, HARDFLOAT, FGR_64;
+class MFHC2_MMR6_DESC : MFC2_MMR6_DESC_BASE<"mfhc2", GPR32Opnd, COP2Opnd>;
+
+class LDC1_D64_MMR6_DESC : MipsR6Inst, HARDFLOAT, FGR_64 {
+ dag InOperandList = (ins mem_mm_16:$addr);
+ dag OutOperandList = (outs FGR64Opnd:$ft);
+ string AsmString = !strconcat("ldc1", "\t$ft, $addr");
+ list<dag> Pattern = [(set FGR64Opnd:$ft, (load addrimm16:$addr))];
+ Format f = FrmFI;
+ InstrItinClass Itinerary = II_LDC1;
+ string BaseOpcode = "ldc1";
+ bit mayLoad = 1;
+ let DecoderMethod = "DecodeFMemMMR2";
+}
+
+class SDC1_D64_MMR6_DESC : MipsR6Inst, HARDFLOAT, FGR_64 {
+ dag InOperandList = (ins FGR64Opnd:$ft, mem_mm_16:$addr);
+ dag OutOperandList = (outs);
+ string AsmString = !strconcat("sdc1", "\t$ft, $addr");
+ list<dag> Pattern = [(store FGR64Opnd:$ft, addrimm16:$addr)];
+ Format f = FrmFI;
+ InstrItinClass Itinerary = II_SDC1;
+ string BaseOpcode = "sdc1";
+ bit mayStore = 1;
+ let DecoderMethod = "DecodeFMemMMR2";
+}
+
+class LDC2_LWC2_MMR6_DESC_BASE<string opstr> {
+ dag OutOperandList = (outs COP2Opnd:$rt);
+ dag InOperandList = (ins mem_mm_11:$addr);
+ string AsmString = !strconcat(opstr, "\t$rt, $addr");
+ list<dag> Pattern = [(set COP2Opnd:$rt, (load addrimm11:$addr))];
+ Format f = FrmFI;
+ InstrItinClass Itinerary = NoItinerary;
+ string BaseOpcode = opstr;
+ bit mayLoad = 1;
+ string DecoderMethod = "DecodeFMemCop2MMR6";
+}
+class LDC2_MMR6_DESC : LDC2_LWC2_MMR6_DESC_BASE<"ldc2">;
+class LWC2_MMR6_DESC : LDC2_LWC2_MMR6_DESC_BASE<"lwc2">;
+
+class SDC2_SWC2_MMR6_DESC_BASE<string opstr> {
+ dag OutOperandList = (outs);
+ dag InOperandList = (ins COP2Opnd:$rt, mem_mm_11:$addr);
+ string AsmString = !strconcat(opstr, "\t$rt, $addr");
+ list<dag> Pattern = [(store COP2Opnd:$rt, addrimm11:$addr)];
+ Format f = FrmFI;
+ InstrItinClass Itinerary = NoItinerary;
+ string BaseOpcode = opstr;
+ bit mayStore = 1;
+ string DecoderMethod = "DecodeFMemCop2MMR6";
+}
+class SDC2_MMR6_DESC : SDC2_SWC2_MMR6_DESC_BASE<"sdc2">;
+class SWC2_MMR6_DESC : SDC2_SWC2_MMR6_DESC_BASE<"swc2">;
+
/// Floating Point Instructions
class FARITH_MMR6_DESC_BASE<string instr_asm, RegisterOperand RC,
InstrItinClass Itin, bit isComm,
@@ -633,69 +911,69 @@ class CVT_S_L_MMR6_DESC : CVT_MMR6_DESC_BASE<"cvt.s.l", FGR64Opnd, FGR32Opnd,
multiclass CMP_CC_MMR6<bits<6> format, string Typestr,
RegisterOperand FGROpnd> {
- def CMP_AF_#NAME : POOL32F_CMP_FM<
+ def CMP_AF_#NAME : R6MMR6Rel, POOL32F_CMP_FM<
!strconcat("cmp.af.", Typestr), format, FIELD_CMP_COND_AF>,
- CMP_CONDN_DESC_BASE<"af", Typestr, FGROpnd>, HARDFLOAT, R6MMR6Rel,
+ CMP_CONDN_DESC_BASE<"af", Typestr, FGROpnd>, HARDFLOAT,
ISA_MICROMIPS32R6;
- def CMP_UN_#NAME : POOL32F_CMP_FM<
+ def CMP_UN_#NAME : R6MMR6Rel, POOL32F_CMP_FM<
!strconcat("cmp.un.", Typestr), format, FIELD_CMP_COND_UN>,
- CMP_CONDN_DESC_BASE<"un", Typestr, FGROpnd>, HARDFLOAT, R6MMR6Rel,
+ CMP_CONDN_DESC_BASE<"un", Typestr, FGROpnd, setuo>, HARDFLOAT,
ISA_MICROMIPS32R6;
- def CMP_EQ_#NAME : POOL32F_CMP_FM<
+ def CMP_EQ_#NAME : R6MMR6Rel, POOL32F_CMP_FM<
!strconcat("cmp.eq.", Typestr), format, FIELD_CMP_COND_EQ>,
- CMP_CONDN_DESC_BASE<"eq", Typestr, FGROpnd>, HARDFLOAT, R6MMR6Rel,
+ CMP_CONDN_DESC_BASE<"eq", Typestr, FGROpnd, setoeq>, HARDFLOAT,
ISA_MICROMIPS32R6;
- def CMP_UEQ_#NAME : POOL32F_CMP_FM<
+ def CMP_UEQ_#NAME : R6MMR6Rel, POOL32F_CMP_FM<
!strconcat("cmp.ueq.", Typestr), format, FIELD_CMP_COND_UEQ>,
- CMP_CONDN_DESC_BASE<"ueq", Typestr, FGROpnd>, HARDFLOAT, R6MMR6Rel,
+ CMP_CONDN_DESC_BASE<"ueq", Typestr, FGROpnd, setueq>, HARDFLOAT,
ISA_MICROMIPS32R6;
- def CMP_LT_#NAME : POOL32F_CMP_FM<
+ def CMP_LT_#NAME : R6MMR6Rel, POOL32F_CMP_FM<
!strconcat("cmp.lt.", Typestr), format, FIELD_CMP_COND_LT>,
- CMP_CONDN_DESC_BASE<"lt", Typestr, FGROpnd>, HARDFLOAT, R6MMR6Rel,
+ CMP_CONDN_DESC_BASE<"lt", Typestr, FGROpnd, setolt>, HARDFLOAT,
ISA_MICROMIPS32R6;
- def CMP_ULT_#NAME : POOL32F_CMP_FM<
+ def CMP_ULT_#NAME : R6MMR6Rel, POOL32F_CMP_FM<
!strconcat("cmp.ult.", Typestr), format, FIELD_CMP_COND_ULT>,
- CMP_CONDN_DESC_BASE<"ult", Typestr, FGROpnd>, HARDFLOAT, R6MMR6Rel,
+ CMP_CONDN_DESC_BASE<"ult", Typestr, FGROpnd, setult>, HARDFLOAT,
ISA_MICROMIPS32R6;
- def CMP_LE_#NAME : POOL32F_CMP_FM<
+ def CMP_LE_#NAME : R6MMR6Rel, POOL32F_CMP_FM<
!strconcat("cmp.le.", Typestr), format, FIELD_CMP_COND_LE>,
- CMP_CONDN_DESC_BASE<"le", Typestr, FGROpnd>, HARDFLOAT, R6MMR6Rel,
+ CMP_CONDN_DESC_BASE<"le", Typestr, FGROpnd, setole>, HARDFLOAT,
ISA_MICROMIPS32R6;
- def CMP_ULE_#NAME : POOL32F_CMP_FM<
+ def CMP_ULE_#NAME : R6MMR6Rel, POOL32F_CMP_FM<
!strconcat("cmp.ule.", Typestr), format, FIELD_CMP_COND_ULE>,
- CMP_CONDN_DESC_BASE<"ule", Typestr, FGROpnd>, HARDFLOAT, R6MMR6Rel,
+ CMP_CONDN_DESC_BASE<"ule", Typestr, FGROpnd, setule>, HARDFLOAT,
ISA_MICROMIPS32R6;
- def CMP_SAF_#NAME : POOL32F_CMP_FM<
+ def CMP_SAF_#NAME : R6MMR6Rel, POOL32F_CMP_FM<
!strconcat("cmp.saf.", Typestr), format, FIELD_CMP_COND_SAF>,
- CMP_CONDN_DESC_BASE<"saf", Typestr, FGROpnd>, HARDFLOAT, R6MMR6Rel,
+ CMP_CONDN_DESC_BASE<"saf", Typestr, FGROpnd>, HARDFLOAT,
ISA_MICROMIPS32R6;
- def CMP_SUN_#NAME : POOL32F_CMP_FM<
+ def CMP_SUN_#NAME : R6MMR6Rel, POOL32F_CMP_FM<
!strconcat("cmp.sun.", Typestr), format, FIELD_CMP_COND_SUN>,
- CMP_CONDN_DESC_BASE<"sun", Typestr, FGROpnd>, HARDFLOAT, R6MMR6Rel,
+ CMP_CONDN_DESC_BASE<"sun", Typestr, FGROpnd>, HARDFLOAT,
ISA_MICROMIPS32R6;
- def CMP_SEQ_#NAME : POOL32F_CMP_FM<
+ def CMP_SEQ_#NAME : R6MMR6Rel, POOL32F_CMP_FM<
!strconcat("cmp.seq.", Typestr), format, FIELD_CMP_COND_SEQ>,
- CMP_CONDN_DESC_BASE<"seq", Typestr, FGROpnd>, HARDFLOAT, R6MMR6Rel,
+ CMP_CONDN_DESC_BASE<"seq", Typestr, FGROpnd>, HARDFLOAT,
ISA_MICROMIPS32R6;
- def CMP_SUEQ_#NAME : POOL32F_CMP_FM<
+ def CMP_SUEQ_#NAME : R6MMR6Rel, POOL32F_CMP_FM<
!strconcat("cmp.sueq.", Typestr), format, FIELD_CMP_COND_SUEQ>,
- CMP_CONDN_DESC_BASE<"sueq", Typestr, FGROpnd>, HARDFLOAT, R6MMR6Rel,
+ CMP_CONDN_DESC_BASE<"sueq", Typestr, FGROpnd>, HARDFLOAT,
ISA_MICROMIPS32R6;
- def CMP_SLT_#NAME : POOL32F_CMP_FM<
+ def CMP_SLT_#NAME : R6MMR6Rel, POOL32F_CMP_FM<
!strconcat("cmp.slt.", Typestr), format, FIELD_CMP_COND_SLT>,
- CMP_CONDN_DESC_BASE<"slt", Typestr, FGROpnd>, HARDFLOAT, R6MMR6Rel,
+ CMP_CONDN_DESC_BASE<"slt", Typestr, FGROpnd>, HARDFLOAT,
ISA_MICROMIPS32R6;
- def CMP_SULT_#NAME : POOL32F_CMP_FM<
+ def CMP_SULT_#NAME : R6MMR6Rel, POOL32F_CMP_FM<
!strconcat("cmp.sult.", Typestr), format, FIELD_CMP_COND_SULT>,
- CMP_CONDN_DESC_BASE<"sult", Typestr, FGROpnd>, HARDFLOAT, R6MMR6Rel,
+ CMP_CONDN_DESC_BASE<"sult", Typestr, FGROpnd>, HARDFLOAT,
ISA_MICROMIPS32R6;
- def CMP_SLE_#NAME : POOL32F_CMP_FM<
+ def CMP_SLE_#NAME : R6MMR6Rel, POOL32F_CMP_FM<
!strconcat("cmp.sle.", Typestr), format, FIELD_CMP_COND_SLE>,
- CMP_CONDN_DESC_BASE<"sle", Typestr, FGROpnd>, HARDFLOAT, R6MMR6Rel,
+ CMP_CONDN_DESC_BASE<"sle", Typestr, FGROpnd>, HARDFLOAT,
ISA_MICROMIPS32R6;
- def CMP_SULE_#NAME : POOL32F_CMP_FM<
+ def CMP_SULE_#NAME : R6MMR6Rel, POOL32F_CMP_FM<
!strconcat("cmp.sule.", Typestr), format, FIELD_CMP_COND_SULE>,
- CMP_CONDN_DESC_BASE<"sule", Typestr, FGROpnd>, HARDFLOAT, R6MMR6Rel,
+ CMP_CONDN_DESC_BASE<"sule", Typestr, FGROpnd>, HARDFLOAT,
ISA_MICROMIPS32R6;
}
@@ -769,8 +1047,8 @@ class SEL_D_MMR6_DESC : COP1_SEL_DESC_BASE<"sel.d", FGR64Opnd> {
class SELEQZ_S_MMR6_DESC : SELEQNEZ_DESC_BASE<"seleqz.s", FGR32Opnd>;
class SELEQZ_D_MMR6_DESC : SELEQNEZ_DESC_BASE<"seleqz.d", FGR64Opnd>;
-class SELENZ_S_MMR6_DESC : SELEQNEZ_DESC_BASE<"selnez.s", FGR32Opnd>;
-class SELENZ_D_MMR6_DESC : SELEQNEZ_DESC_BASE<"selnez.d", FGR64Opnd>;
+class SELNEZ_S_MMR6_DESC : SELEQNEZ_DESC_BASE<"selnez.s", FGR32Opnd>;
+class SELNEZ_D_MMR6_DESC : SELEQNEZ_DESC_BASE<"selnez.d", FGR64Opnd>;
class RINT_S_MMR6_DESC : CLASS_RINT_DESC_BASE<"rint.s", FGR32Opnd>;
class RINT_D_MMR6_DESC : CLASS_RINT_DESC_BASE<"rint.d", FGR64Opnd>;
class CLASS_S_MMR6_DESC : CLASS_RINT_DESC_BASE<"class.s", FGR32Opnd>;
@@ -785,7 +1063,7 @@ class SB_MMR6_DESC : STORE_MMR6_DESC_BASE<"sb", GPR32Opnd>;
class STORE_EVA_MMR6_DESC_BASE<string instr_asm, RegisterOperand RO>
: MMR6Arch<instr_asm>, MipsR6Inst {
dag OutOperandList = (outs);
- dag InOperandList = (ins RO:$rt, mem_mm_9:$addr);
+ dag InOperandList = (ins RO:$rt, mem_simm9:$addr);
string AsmString = !strconcat(instr_asm, "\t$rt, $addr");
string DecoderMethod = "DecodeStoreEvaOpMM";
bit mayStore = 1;
@@ -797,7 +1075,7 @@ class SHE_MMR6_DESC : STORE_EVA_MMR6_DESC_BASE<"she", GPR32Opnd>;
class LOAD_WORD_EVA_MMR6_DESC_BASE<string instr_asm, RegisterOperand RO> :
MMR6Arch<instr_asm>, MipsR6Inst {
dag OutOperandList = (outs RO:$rt);
- dag InOperandList = (ins mem_mm_12:$addr);
+ dag InOperandList = (ins mem_simm9:$addr);
string AsmString = !strconcat(instr_asm, "\t$rt, $addr");
string DecoderMethod = "DecodeMemMMImm9";
bit mayLoad = 1;
@@ -805,30 +1083,42 @@ class LOAD_WORD_EVA_MMR6_DESC_BASE<string instr_asm, RegisterOperand RO> :
class LLE_MMR6_DESC : LOAD_WORD_EVA_MMR6_DESC_BASE<"lle", GPR32Opnd>;
class LWE_MMR6_DESC : LOAD_WORD_EVA_MMR6_DESC_BASE<"lwe", GPR32Opnd>;
class ADDU16_MMR6_DESC : ArithRMM16<"addu16", GPRMM16Opnd, 1, II_ADDU, add>,
- MMR6Arch<"addu16">;
+ MMR6Arch<"addu16"> {
+ int AddedComplexity = 1;
+}
class AND16_MMR6_DESC : LogicRMM16<"and16", GPRMM16Opnd, II_AND, and>,
- MMR6Arch<"and16">;
+ MMR6Arch<"and16"> {
+ int AddedComplexity = 1;
+}
class ANDI16_MMR6_DESC : AndImmMM16<"andi16", GPRMM16Opnd, II_AND>,
MMR6Arch<"andi16">;
-class NOT16_MMR6_DESC : NotMM16<"not16", GPRMM16Opnd>, MMR6Arch<"not16">;
+class NOT16_MMR6_DESC : NotMM16<"not16", GPRMM16Opnd>, MMR6Arch<"not16"> {
+ int AddedComplexity = 1;
+}
class OR16_MMR6_DESC : LogicRMM16<"or16", GPRMM16Opnd, II_OR, or>,
- MMR6Arch<"or16">;
+ MMR6Arch<"or16"> {
+ int AddedComplexity = 1;
+}
class SLL16_MMR6_DESC : ShiftIMM16<"sll16", uimm3_shift, GPRMM16Opnd, II_SLL>,
MMR6Arch<"sll16">;
class SRL16_MMR6_DESC : ShiftIMM16<"srl16", uimm3_shift, GPRMM16Opnd, II_SRL>,
MMR6Arch<"srl16">;
-class BREAK16_MMR6_DESC : BrkSdbbp16MM<"break16">, MMR6Arch<"srl16">,
+class BREAK16_MMR6_DESC : BrkSdbbp16MM<"break16">, MMR6Arch<"break16">,
MicroMipsR6Inst16;
-class LI16_MMR6_DESC : LoadImmMM16<"li16", li_simm7, GPRMM16Opnd>,
- MMR6Arch<"srl16">, MicroMipsR6Inst16, IsAsCheapAsAMove;
-class MOVE16_MMR6_DESC : MoveMM16<"move16", GPR32Opnd>, MMR6Arch<"srl16">,
+class LI16_MMR6_DESC : LoadImmMM16<"li16", li16_imm, GPRMM16Opnd>,
+ MMR6Arch<"li16">, MicroMipsR6Inst16, IsAsCheapAsAMove;
+class MOVE16_MMR6_DESC : MoveMM16<"move16", GPR32Opnd>, MMR6Arch<"move16">,
MicroMipsR6Inst16;
class SDBBP16_MMR6_DESC : BrkSdbbp16MM<"sdbbp16">, MMR6Arch<"sdbbp16">,
MicroMipsR6Inst16;
class SUBU16_MMR6_DESC : ArithRMM16<"subu16", GPRMM16Opnd, 0, II_SUBU, sub>,
- MMR6Arch<"sdbbp16">, MicroMipsR6Inst16;
+ MMR6Arch<"subu16">, MicroMipsR6Inst16 {
+ int AddedComplexity = 1;
+}
class XOR16_MMR6_DESC : LogicRMM16<"xor16", GPRMM16Opnd, II_XOR, xor>,
- MMR6Arch<"sdbbp16">, MicroMipsR6Inst16;
+ MMR6Arch<"xor16"> {
+ int AddedComplexity = 1;
+}
class LW_MMR6_DESC : MMR6Arch<"lw">, MipsR6Inst {
dag OutOperandList = (outs GPR32Opnd:$rt);
@@ -854,9 +1144,9 @@ class LUI_MMR6_DESC : IsAsCheapAsAMove, MMR6Arch<"lui">, MipsR6Inst{
class SYNC_MMR6_DESC : MMR6Arch<"sync">, MipsR6Inst {
dag OutOperandList = (outs);
- dag InOperandList = (ins i32imm:$stype);
+ dag InOperandList = (ins uimm5:$stype);
string AsmString = !strconcat("sync", "\t$stype");
- list<dag> Pattern = [(MipsSync imm:$stype)];
+ list<dag> Pattern = [(MipsSync immZExt5:$stype)];
InstrItinClass Itinerary = NoItinerary;
bit HasSideEffects = 1;
}
@@ -924,6 +1214,111 @@ class SWSP_MMR6_DESC
let mayStore = 1;
}
+class JALRC_HB_MMR6_DESC {
+ dag OutOperandList = (outs GPR32Opnd:$rt);
+ dag InOperandList = (ins GPR32Opnd:$rs);
+ string AsmString = !strconcat("jalrc.hb", "\t$rt, $rs");
+ list<dag> Pattern = [];
+ InstrItinClass Itinerary = NoItinerary;
+ Format Form = FrmJ;
+ bit isIndirectBranch = 1;
+ bit hasDelaySlot = 0;
+}
+
+class TLBINV_MMR6_DESC_BASE<string opstr> {
+ dag OutOperandList = (outs);
+ dag InOperandList = (ins);
+ string AsmString = opstr;
+ list<dag> Pattern = [];
+}
+
+class TLBINV_MMR6_DESC : TLBINV_MMR6_DESC_BASE<"tlbinv">;
+class TLBINVF_MMR6_DESC : TLBINV_MMR6_DESC_BASE<"tlbinvf">;
+
+class DVPEVP_MMR6_DESC_BASE<string opstr> {
+ dag OutOperandList = (outs);
+ dag InOperandList = (ins GPR32Opnd:$rs);
+ string AsmString = !strconcat(opstr, "\t$rs");
+ list<dag> Pattern = [];
+}
+
+class DVP_MMR6_DESC : DVPEVP_MMR6_DESC_BASE<"dvp">;
+class EVP_MMR6_DESC : DVPEVP_MMR6_DESC_BASE<"evp">;
+
+class BEQZC_MMR6_DESC
+ : CMP_CBR_EQNE_Z_DESC_BASE<"beqzc", brtarget21_mm, GPR32Opnd>,
+ MMR6Arch<"beqzc">;
+class BNEZC_MMR6_DESC
+ : CMP_CBR_EQNE_Z_DESC_BASE<"bnezc", brtarget21_mm, GPR32Opnd>,
+ MMR6Arch<"bnezc">;
+
+class BRANCH_COP1_MMR6_DESC_BASE<string opstr> :
+ InstSE<(outs), (ins FGR64Opnd:$rt, brtarget_mm:$offset),
+ !strconcat(opstr, "\t$rt, $offset"), [], II_BC1CCZ, FrmI>,
+ HARDFLOAT, BRANCH_DESC_BASE {
+ list<Register> Defs = [AT];
+}
+
+class BC1EQZC_MMR6_DESC : BRANCH_COP1_MMR6_DESC_BASE<"bc1eqzc">;
+class BC1NEZC_MMR6_DESC : BRANCH_COP1_MMR6_DESC_BASE<"bc1nezc">;
+
+class BRANCH_COP2_MMR6_DESC_BASE<string opstr> : BRANCH_DESC_BASE {
+ dag InOperandList = (ins COP2Opnd:$rt, brtarget_mm:$offset);
+ dag OutOperandList = (outs);
+ string AsmString = !strconcat(opstr, "\t$rt, $offset");
+ list<Register> Defs = [AT];
+}
+
+class BC2EQZC_MMR6_DESC : BRANCH_COP2_MMR6_DESC_BASE<"bc2eqzc">;
+class BC2NEZC_MMR6_DESC : BRANCH_COP2_MMR6_DESC_BASE<"bc2nezc">;
+
+class EXT_MMR6_DESC {
+ dag OutOperandList = (outs GPR32Opnd:$rt);
+ dag InOperandList = (ins GPR32Opnd:$rs, uimm5:$pos, uimm5_plus1:$size);
+ string AsmString = !strconcat("ext", "\t$rt, $rs, $pos, $size");
+ list<dag> Pattern = [(set GPR32Opnd:$rt, (MipsExt GPR32Opnd:$rs, imm:$pos,
+ imm:$size))];
+ InstrItinClass Itinerary = II_EXT;
+ Format Form = FrmR;
+ string BaseOpcode = "ext";
+}
+
+class INS_MMR6_DESC {
+ dag OutOperandList = (outs GPR32Opnd:$rt);
+ dag InOperandList = (ins GPR32Opnd:$rs, uimm5:$pos, uimm5_inssize_plus1:$size,
+ GPR32Opnd:$src);
+ string AsmString = !strconcat("ins", "\t$rt, $rs, $pos, $size");
+ list<dag> Pattern = [(set GPR32Opnd:$rt, (MipsIns GPR32Opnd:$rs, imm:$pos,
+ imm:$size, GPR32Opnd:$src))];
+ InstrItinClass Itinerary = II_INS;
+ Format Form = FrmR;
+ string BaseOpcode = "ins";
+ string Constraints = "$src = $rt";
+}
+
+class JALRC_MMR6_DESC {
+ dag OutOperandList = (outs GPR32Opnd:$rt);
+ dag InOperandList = (ins GPR32Opnd:$rs);
+ string AsmString = !strconcat("jalrc", "\t$rt, $rs");
+ list<dag> Pattern = [];
+ InstrItinClass Itinerary = II_JALRC;
+ bit isCall = 1;
+ bit hasDelaySlot = 0;
+ list<Register> Defs = [RA];
+}
+
+class BOVC_BNVC_MMR6_DESC_BASE<string instr_asm, Operand opnd,
+ RegisterOperand GPROpnd>
+ : BRANCH_DESC_BASE {
+ dag InOperandList = (ins GPROpnd:$rt, GPROpnd:$rs, opnd:$offset);
+ dag OutOperandList = (outs);
+ string AsmString = !strconcat(instr_asm, "\t$rt, $rs, $offset");
+ list<Register> Defs = [AT];
+}
+
+class BOVC_MMR6_DESC : BOVC_BNVC_MMR6_DESC_BASE<"bovc", brtargetr6, GPR32Opnd>;
+class BNVC_MMR6_DESC : BOVC_BNVC_MMR6_DESC_BASE<"bnvc", brtargetr6, GPR32Opnd>;
+
//===----------------------------------------------------------------------===//
//
// Instruction Definitions
@@ -946,22 +1341,18 @@ def AUI_MMR6 : R6MMR6Rel, AUI_MMR6_ENC, AUI_MMR6_DESC, ISA_MICROMIPS32R6;
def BALC_MMR6 : R6MMR6Rel, BALC_MMR6_ENC, BALC_MMR6_DESC, ISA_MICROMIPS32R6;
def BC_MMR6 : R6MMR6Rel, BC_MMR6_ENC, BC_MMR6_DESC, ISA_MICROMIPS32R6;
def BC16_MMR6 : StdMMR6Rel, BC16_MMR6_DESC, BC16_MMR6_ENC, ISA_MICROMIPS32R6;
+def BEQZC_MMR6 : R6MMR6Rel, BEQZC_MMR6_ENC, BEQZC_MMR6_DESC,
+ ISA_MICROMIPS32R6;
def BEQZC16_MMR6 : StdMMR6Rel, BEQZC16_MMR6_DESC, BEQZC16_MMR6_ENC,
ISA_MICROMIPS32R6;
+def BNEZC_MMR6 : R6MMR6Rel, BNEZC_MMR6_ENC, BNEZC_MMR6_DESC,
+ ISA_MICROMIPS32R6;
def BNEZC16_MMR6 : StdMMR6Rel, BNEZC16_MMR6_DESC, BNEZC16_MMR6_ENC,
ISA_MICROMIPS32R6;
def BITSWAP_MMR6 : R6MMR6Rel, BITSWAP_MMR6_ENC, BITSWAP_MMR6_DESC,
ISA_MICROMIPS32R6;
def BEQZALC_MMR6 : R6MMR6Rel, BEQZALC_MMR6_ENC, BEQZALC_MMR6_DESC,
ISA_MICROMIPS32R6;
-def BGEZALC_MMR6 : R6MMR6Rel, BGEZALC_MMR6_ENC, BGEZALC_MMR6_DESC,
- ISA_MICROMIPS32R6;
-def BGTZALC_MMR6 : R6MMR6Rel, BGTZALC_MMR6_ENC, BGTZALC_MMR6_DESC,
- ISA_MICROMIPS32R6;
-def BLEZALC_MMR6 : R6MMR6Rel, BLEZALC_MMR6_ENC, BLEZALC_MMR6_DESC,
- ISA_MICROMIPS32R6;
-def BLTZALC_MMR6 : R6MMR6Rel, BLTZALC_MMR6_ENC, BLTZALC_MMR6_DESC,
- ISA_MICROMIPS32R6;
def BNEZALC_MMR6 : R6MMR6Rel, BNEZALC_MMR6_ENC, BNEZALC_MMR6_DESC,
ISA_MICROMIPS32R6;
def BREAK_MMR6 : StdMMR6Rel, BRK_MMR6_DESC, BRK_MMR6_ENC, ISA_MICROMIPS32R6;
@@ -985,8 +1376,30 @@ def JRC16_MMR6 : R6MMR6Rel, JRC16_MMR6_DESC, JRC16_MMR6_ENC, ISA_MICROMIPS32R6;
def JRCADDIUSP_MMR6 : R6MMR6Rel, JRCADDIUSP_MMR6_DESC, JRCADDIUSP_MMR6_ENC,
ISA_MICROMIPS32R6;
def LSA_MMR6 : R6MMR6Rel, LSA_MMR6_ENC, LSA_MMR6_DESC, ISA_MICROMIPS32R6;
+def LWP_MMR6 : StdMMR6Rel, LWP_MMR6_ENC, LWP_MMR6_DESC, ISA_MICROMIPS32R6;
def LWPC_MMR6 : R6MMR6Rel, LWPC_MMR6_ENC, LWPC_MMR6_DESC, ISA_MICROMIPS32R6;
def LWM16_MMR6 : StdMMR6Rel, LWM16_MMR6_DESC, LWM16_MMR6_ENC, ISA_MICROMIPS32R6;
+def MTC0_MMR6 : StdMMR6Rel, MTC0_MMR6_ENC, MTC0_MMR6_DESC, ISA_MICROMIPS32R6;
+def MTC1_MMR6 : StdMMR6Rel, MTC1_MMR6_DESC, MTC1_MMR6_ENC, ISA_MICROMIPS32R6;
+def MTC2_MMR6 : StdMMR6Rel, MTC2_MMR6_ENC, MTC2_MMR6_DESC, ISA_MICROMIPS32R6;
+def MTHC0_MMR6 : R6MMR6Rel, MTHC0_MMR6_ENC, MTHC0_MMR6_DESC, ISA_MICROMIPS32R6;
+def MTHC1_D32_MMR6 : StdMMR6Rel, MTHC1_D32_MMR6_DESC, MTHC1_MMR6_ENC, ISA_MICROMIPS32R6;
+let DecoderNamespace = "MicroMips32r6FP64" in {
+ def MTHC1_D64_MMR6 : R6MMR6Rel, MTHC1_D64_MMR6_DESC, MTHC1_MMR6_ENC,
+ ISA_MICROMIPS32R6;
+}
+def MTHC2_MMR6 : StdMMR6Rel, MTHC2_MMR6_ENC, MTHC2_MMR6_DESC, ISA_MICROMIPS32R6;
+def MFC0_MMR6 : StdMMR6Rel, MFC0_MMR6_ENC, MFC0_MMR6_DESC, ISA_MICROMIPS32R6;
+def MFC1_MMR6 : StdMMR6Rel, MFC1_MMR6_DESC, MFC1_MMR6_ENC, ISA_MICROMIPS32R6;
+def MFC2_MMR6 : StdMMR6Rel, MFC2_MMR6_ENC, MFC2_MMR6_DESC, ISA_MICROMIPS32R6;
+def MFHC0_MMR6 : R6MMR6Rel, MFHC0_MMR6_ENC, MFHC0_MMR6_DESC, ISA_MICROMIPS32R6;
+def MFHC1_D32_MMR6 : StdMMR6Rel, MFHC1_D32_MMR6_DESC, MFHC1_MMR6_ENC,
+ ISA_MICROMIPS32R6;
+let DecoderNamespace = "MicroMips32r6FP64" in {
+ def MFHC1_D64_MMR6 : StdMMR6Rel, MFHC1_D64_MMR6_DESC, MFHC1_MMR6_ENC,
+ ISA_MICROMIPS32R6;
+}
+def MFHC2_MMR6 : StdMMR6Rel, MFHC2_MMR6_ENC, MFHC2_MMR6_DESC, ISA_MICROMIPS32R6;
def MOD_MMR6 : R6MMR6Rel, MOD_MMR6_DESC, MOD_MMR6_ENC, ISA_MICROMIPS32R6;
def MODU_MMR6 : R6MMR6Rel, MODU_MMR6_DESC, MODU_MMR6_ENC, ISA_MICROMIPS32R6;
def MUL_MMR6 : R6MMR6Rel, MUL_MMR6_DESC, MUL_MMR6_ENC, ISA_MICROMIPS32R6;
@@ -1011,6 +1424,7 @@ def SUBU_MMR6 : StdMMR6Rel, SUBU_MMR6_DESC, SUBU_MMR6_ENC, ISA_MICROMIPS32R6;
def SW16_MMR6 : StdMMR6Rel, SW16_MMR6_DESC, SW16_MMR6_ENC, ISA_MICROMIPS32R6;
def SWM16_MMR6 : StdMMR6Rel, SWM16_MMR6_DESC, SWM16_MMR6_ENC, ISA_MICROMIPS32R6;
def SWSP_MMR6 : StdMMR6Rel, SWSP_MMR6_DESC, SWSP_MMR6_ENC, ISA_MICROMIPS32R6;
+def SWP_MMR6 : StdMMR6Rel, SWP_MMR6_ENC, SWP_MMR6_DESC, ISA_MICROMIPS32R6;
def PREFE_MMR6 : StdMMR6Rel, PREFE_MMR6_ENC, PREFE_MMR6_DESC, ISA_MICROMIPS32R6;
def CACHEE_MMR6 : StdMMR6Rel, CACHEE_MMR6_ENC, CACHEE_MMR6_DESC,
ISA_MICROMIPS32R6;
@@ -1174,6 +1588,11 @@ def SUBU16_MMR6 : StdMMR6Rel, SUBU16_MMR6_DESC, SUBU16_MMR6_ENC,
ISA_MICROMIPS32R6;
def XOR16_MMR6 : StdMMR6Rel, XOR16_MMR6_DESC, XOR16_MMR6_ENC,
ISA_MICROMIPS32R6;
+def JALRC_HB_MMR6 : R6MMR6Rel, JALRC_HB_MMR6_ENC, JALRC_HB_MMR6_DESC,
+ ISA_MICROMIPS32R6;
+def EXT_MMR6 : StdMMR6Rel, EXT_MMR6_ENC, EXT_MMR6_DESC, ISA_MICROMIPS32R6;
+def INS_MMR6 : StdMMR6Rel, INS_MMR6_ENC, INS_MMR6_DESC, ISA_MICROMIPS32R6;
+def JALRC_MMR6 : R6MMR6Rel, JALRC_MMR6_ENC, JALRC_MMR6_DESC, ISA_MICROMIPS32R6;
def RECIP_S_MMR6 : StdMMR6Rel, RECIP_S_MMR6_ENC, RECIP_S_MMR6_DESC,
ISA_MICROMIPS32R6;
def RECIP_D_MMR6 : StdMMR6Rel, RECIP_D_MMR6_ENC, RECIP_D_MMR6_DESC, ISA_MICROMIPS32R6;
@@ -1188,22 +1607,69 @@ def ROUND_W_S_MMR6 : StdMMR6Rel, ROUND_W_S_MMR6_ENC, ROUND_W_S_MMR6_DESC,
ISA_MICROMIPS32R6;
def ROUND_W_D_MMR6 : StdMMR6Rel, ROUND_W_D_MMR6_ENC, ROUND_W_D_MMR6_DESC,
ISA_MICROMIPS32R6;
-def SEL_S_MMR6 : StdMMR6Rel, SEL_S_MMR6_ENC, SEL_S_MMR6_DESC, ISA_MICROMIPS32R6;
-def SEL_D_MMR6 : StdMMR6Rel, SEL_D_MMR6_ENC, SEL_D_MMR6_DESC, ISA_MICROMIPS32R6;
-def SELEQZ_S_MMR6 : StdMMR6Rel, SELEQZ_S_MMR6_ENC, SELEQZ_S_MMR6_DESC,
+def SEL_S_MMR6 : R6MMR6Rel, SEL_S_MMR6_ENC, SEL_S_MMR6_DESC, ISA_MICROMIPS32R6;
+def SEL_D_MMR6 : R6MMR6Rel, SEL_D_MMR6_ENC, SEL_D_MMR6_DESC, ISA_MICROMIPS32R6;
+def SELEQZ_S_MMR6 : R6MMR6Rel, SELEQZ_S_MMR6_ENC, SELEQZ_S_MMR6_DESC,
ISA_MICROMIPS32R6;
-def SELEQZ_D_MMR6 : StdMMR6Rel, SELEQZ_D_MMR6_ENC, SELEQZ_D_MMR6_DESC,
+def SELEQZ_D_MMR6 : R6MMR6Rel, SELEQZ_D_MMR6_ENC, SELEQZ_D_MMR6_DESC,
ISA_MICROMIPS32R6;
-def SELENZ_S_MMR6 : StdMMR6Rel, SELENZ_S_MMR6_ENC, SELENZ_S_MMR6_DESC,
+def SELNEZ_S_MMR6 : R6MMR6Rel, SELNEZ_S_MMR6_ENC, SELNEZ_S_MMR6_DESC,
ISA_MICROMIPS32R6;
-def SELENZ_D_MMR6 : StdMMR6Rel, SELENZ_D_MMR6_ENC, SELENZ_D_MMR6_DESC,
+def SELNEZ_D_MMR6 : R6MMR6Rel, SELNEZ_D_MMR6_ENC, SELNEZ_D_MMR6_DESC,
ISA_MICROMIPS32R6;
def CLASS_S_MMR6 : StdMMR6Rel, CLASS_S_MMR6_ENC, CLASS_S_MMR6_DESC,
ISA_MICROMIPS32R6;
def CLASS_D_MMR6 : StdMMR6Rel, CLASS_D_MMR6_ENC, CLASS_D_MMR6_DESC,
ISA_MICROMIPS32R6;
+def TLBINV_MMR6 : StdMMR6Rel, TLBINV_MMR6_ENC, TLBINV_MMR6_DESC,
+ ISA_MICROMIPS32R6;
+def TLBINVF_MMR6 : StdMMR6Rel, TLBINVF_MMR6_ENC, TLBINVF_MMR6_DESC,
+ ISA_MICROMIPS32R6;
+def DVP_MMR6 : R6MMR6Rel, DVP_MMR6_ENC, DVP_MMR6_DESC, ISA_MICROMIPS32R6;
+def EVP_MMR6 : R6MMR6Rel, EVP_MMR6_ENC, EVP_MMR6_DESC, ISA_MICROMIPS32R6;
+def BC1EQZC_MMR6 : R6MMR6Rel, BC1EQZC_MMR6_DESC, BC1EQZC_MMR6_ENC,
+ ISA_MICROMIPS32R6;
+def BC1NEZC_MMR6 : R6MMR6Rel, BC1NEZC_MMR6_DESC, BC1NEZC_MMR6_ENC,
+ ISA_MICROMIPS32R6;
+def BC2EQZC_MMR6 : R6MMR6Rel, MipsR6Inst, BC2EQZC_MMR6_ENC, BC2EQZC_MMR6_DESC,
+ ISA_MICROMIPS32R6;
+def BC2NEZC_MMR6 : R6MMR6Rel, MipsR6Inst, BC2NEZC_MMR6_ENC, BC2NEZC_MMR6_DESC,
+ ISA_MICROMIPS32R6;
+let DecoderNamespace = "MicroMips32r6FP64" in {
+ def LDC1_D64_MMR6 : StdMMR6Rel, LDC1_D64_MMR6_DESC, LDC1_MMR6_ENC,
+ ISA_MICROMIPS32R6 {
+ let BaseOpcode = "LDC164";
+ }
+ def SDC1_D64_MMR6 : StdMMR6Rel, SDC1_D64_MMR6_DESC, SDC1_MMR6_ENC,
+ ISA_MICROMIPS32R6;
+}
+def LDC2_MMR6 : StdMMR6Rel, LDC2_MMR6_ENC, LDC2_MMR6_DESC, ISA_MICROMIPS32R6;
+def SDC2_MMR6 : StdMMR6Rel, SDC2_MMR6_ENC, SDC2_MMR6_DESC, ISA_MICROMIPS32R6;
+def LWC2_MMR6 : StdMMR6Rel, LWC2_MMR6_ENC, LWC2_MMR6_DESC, ISA_MICROMIPS32R6;
+def SWC2_MMR6 : StdMMR6Rel, SWC2_MMR6_ENC, SWC2_MMR6_DESC, ISA_MICROMIPS32R6;
}
+def BOVC_MMR6 : R6MMR6Rel, BOVC_MMR6_ENC, BOVC_MMR6_DESC, ISA_MICROMIPS32R6,
+ MMDecodeDisambiguatedBy<"POP35GroupBranchMMR6">;
+def BNVC_MMR6 : R6MMR6Rel, BNVC_MMR6_ENC, BNVC_MMR6_DESC, ISA_MICROMIPS32R6,
+ MMDecodeDisambiguatedBy<"POP37GroupBranchMMR6">;
+def BGEC_MMR6 : R6MMR6Rel, BGEC_MMR6_ENC, BGEC_MMR6_DESC, ISA_MICROMIPS32R6;
+def BGEUC_MMR6 : R6MMR6Rel, BGEUC_MMR6_ENC, BGEUC_MMR6_DESC, ISA_MICROMIPS32R6;
+def BLTC_MMR6 : R6MMR6Rel, BLTC_MMR6_ENC, BLTC_MMR6_DESC, ISA_MICROMIPS32R6;
+def BLTUC_MMR6 : R6MMR6Rel, BLTUC_MMR6_ENC, BLTUC_MMR6_DESC, ISA_MICROMIPS32R6;
+def BEQC_MMR6 : R6MMR6Rel, BEQC_MMR6_ENC, BEQC_MMR6_DESC, ISA_MICROMIPS32R6,
+ DecodeDisambiguates<"POP35GroupBranchMMR6">;
+def BNEC_MMR6 : R6MMR6Rel, BNEC_MMR6_ENC, BNEC_MMR6_DESC, ISA_MICROMIPS32R6,
+ DecodeDisambiguates<"POP37GroupBranchMMR6">;
+def BGEZALC_MMR6 : R6MMR6Rel, BGEZALC_MMR6_ENC, BGEZALC_MMR6_DESC,
+ ISA_MICROMIPS32R6;
+def BGTZALC_MMR6 : R6MMR6Rel, BGTZALC_MMR6_ENC, BGTZALC_MMR6_DESC,
+ ISA_MICROMIPS32R6;
+def BLEZALC_MMR6 : R6MMR6Rel, BLEZALC_MMR6_ENC, BLEZALC_MMR6_DESC,
+ ISA_MICROMIPS32R6;
+def BLTZALC_MMR6 : R6MMR6Rel, BLTZALC_MMR6_ENC, BLTZALC_MMR6_DESC,
+ ISA_MICROMIPS32R6;
+
//===----------------------------------------------------------------------===//
//
// MicroMips instruction aliases
@@ -1222,6 +1688,45 @@ def : MipsInstAlias<"sdbbp", (SDBBP_MMR6 0), 1>, ISA_MICROMIPS32R6;
def : MipsInstAlias<"rdhwr $rt, $rs",
(RDHWR_MMR6 GPR32Opnd:$rt, HWRegsOpnd:$rs, 0), 1>,
ISA_MICROMIPS32R6;
+def : MipsInstAlias<"mtc0 $rt, $rs",
+ (MTC0_MMR6 COP0Opnd:$rs, GPR32Opnd:$rt, 0), 0>,
+ ISA_MICROMIPS32R6;
+def : MipsInstAlias<"mthc0 $rt, $rs",
+ (MTHC0_MMR6 COP0Opnd:$rs, GPR32Opnd:$rt, 0), 0>,
+ ISA_MICROMIPS32R6;
+def : MipsInstAlias<"mfc0 $rt, $rs",
+ (MFC0_MMR6 GPR32Opnd:$rt, COP0Opnd:$rs, 0), 0>,
+ ISA_MICROMIPS32R6;
+def : MipsInstAlias<"mfhc0 $rt, $rs",
+ (MFHC0_MMR6 GPR32Opnd:$rt, COP0Opnd:$rs, 0), 0>,
+ ISA_MICROMIPS32R6;
+def : MipsInstAlias<"jalrc.hb $rs", (JALRC_HB_MMR6 RA, GPR32Opnd:$rs), 1>,
+ ISA_MICROMIPS32R6;
+def : MipsInstAlias<"dvp", (DVP_MMR6 ZERO), 0>, ISA_MICROMIPS32R6;
+def : MipsInstAlias<"evp", (EVP_MMR6 ZERO), 0>, ISA_MICROMIPS32R6;
+def : MipsInstAlias<"jalrc $rs", (JALRC_MMR6 RA, GPR32Opnd:$rs), 1>,
+ ISA_MICROMIPS32R6;
+def : MipsInstAlias<"and $rs, $rt, $imm",
+ (ANDI_MMR6 GPR32Opnd:$rs, GPR32Opnd:$rt, uimm16:$imm), 0>,
+ ISA_MICROMIPS32R6;
+def : MipsInstAlias<"and $rs, $imm",
+ (ANDI_MMR6 GPR32Opnd:$rs, GPR32Opnd:$rs, uimm16:$imm), 0>,
+ ISA_MICROMIPS32R6;
+def : MipsInstAlias<"or $rs, $rt, $imm",
+ (ORI_MMR6 GPR32Opnd:$rs, GPR32Opnd:$rt, uimm16:$imm), 0>,
+ ISA_MICROMIPS32R6;
+def : MipsInstAlias<"or $rs, $imm",
+ (ORI_MMR6 GPR32Opnd:$rs, GPR32Opnd:$rs, uimm16:$imm), 0>,
+ ISA_MICROMIPS32R6;
+def : MipsInstAlias<"xor $rs, $rt, $imm",
+ (XORI_MMR6 GPR32Opnd:$rs, GPR32Opnd:$rt, uimm16:$imm), 0>,
+ ISA_MICROMIPS32R6;
+def : MipsInstAlias<"xor $rs, $imm",
+ (XORI_MMR6 GPR32Opnd:$rs, GPR32Opnd:$rs, uimm16:$imm), 0>,
+ ISA_MICROMIPS32R6;
+def : MipsInstAlias<"not $rt, $rs",
+ (NOR_MMR6 GPR32Opnd:$rt, GPR32Opnd:$rs, ZERO), 0>,
+ ISA_MICROMIPS32R6;
//===----------------------------------------------------------------------===//
//
@@ -1231,3 +1736,39 @@ def : MipsInstAlias<"rdhwr $rt, $rs",
def : MipsPat<(store GPRMM16:$src, addrimm4lsl2:$addr),
(SW16_MMR6 GPRMM16:$src, addrimm4lsl2:$addr)>, ISA_MICROMIPS32R6;
+def : MipsPat<(subc GPR32:$lhs, GPR32:$rhs),
+ (SUBU_MMR6 GPR32:$lhs, GPR32:$rhs)>, ISA_MICROMIPS32R6;
+
+def : MipsPat<(select i32:$cond, i32:$t, i32:$f),
+ (OR_MM (SELNEZ_MMR6 i32:$t, i32:$cond),
+ (SELEQZ_MMR6 i32:$f, i32:$cond))>,
+ ISA_MICROMIPS32R6;
+def : MipsPat<(select i32:$cond, i32:$t, immz),
+ (SELNEZ_MMR6 i32:$t, i32:$cond)>,
+ ISA_MICROMIPS32R6;
+def : MipsPat<(select i32:$cond, immz, i32:$f),
+ (SELEQZ_MMR6 i32:$f, i32:$cond)>,
+ ISA_MICROMIPS32R6;
+
+defm : SelectInt_Pats<i32, OR_MM, XORI_MMR6, SLTi_MM, SLTiu_MM, SELEQZ_MMR6,
+ SELNEZ_MMR6, immZExt16, i32>, ISA_MICROMIPS32R6;
+
+defm S_MMR6 : Cmp_Pats<f32, NOR_MMR6, ZERO>, ISA_MICROMIPS32R6;
+defm D_MMR6 : Cmp_Pats<f64, NOR_MMR6, ZERO>, ISA_MICROMIPS32R6;
+
+def : MipsPat<(and GPRMM16:$src, immZExtAndi16:$imm),
+ (ANDI16_MMR6 GPRMM16:$src, immZExtAndi16:$imm)>,
+ ISA_MICROMIPS32R6;
+def : MipsPat<(and GPR32:$src, immZExt16:$imm),
+ (ANDI_MMR6 GPR32:$src, immZExt16:$imm)>, ISA_MICROMIPS32R6;
+def : MipsPat<(i32 immZExt16:$imm),
+ (XORI_MMR6 ZERO, immZExt16:$imm)>, ISA_MICROMIPS32R6;
+def : MipsPat<(not GPRMM16:$in),
+ (NOT16_MMR6 GPRMM16:$in)>, ISA_MICROMIPS32R6;
+def : MipsPat<(not GPR32:$in),
+ (NOR_MMR6 GPR32Opnd:$in, ZERO)>, ISA_MICROMIPS32R6;
+// Patterns for load with a reg+imm operand.
+let AddedComplexity = 41 in {
+ def : LoadRegImmPat<LDC1_D64_MMR6, f64, load>, FGR_64, ISA_MICROMIPS32R6;
+ def : StoreRegImmPat<SDC1_D64_MMR6, f64>, FGR_64, ISA_MICROMIPS32R6;
+}
diff --git a/lib/Target/Mips/MicroMips64r6InstrFormats.td b/lib/Target/Mips/MicroMips64r6InstrFormats.td
index da305a2d508aa..4add305522f75 100644
--- a/lib/Target/Mips/MicroMips64r6InstrFormats.td
+++ b/lib/Target/Mips/MicroMips64r6InstrFormats.td
@@ -71,16 +71,151 @@ class POOL32S_DALIGN_FM_MMR6 {
class POOL32A_DIVMOD_FM_MMR6<string instr_asm, bits<9> funct>
: MMR6Arch<instr_asm> {
+ bits<5> rt;
+ bits<5> rs;
bits<5> rd;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = 0b010110;
+ let Inst{25-21} = rt;
+ let Inst{20-16} = rs;
+ let Inst{15-11} = rd;
+ let Inst{10-9} = 0b00;
+ let Inst{8-0} = funct;
+}
+
+class POOL32S_DMFTC0_FM_MMR6<string instr_asm, bits<5> funct>
+ : MMR6Arch<instr_asm>, MipsR6Inst {
+ bits<5> rt;
bits<5> rs;
+ bits<3> sel;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = 0b010110;
+ let Inst{25-21} = rt;
+ let Inst{20-16} = rs;
+ let Inst{15-14} = 0;
+ let Inst{13-11} = sel;
+ let Inst{10-6} = funct;
+ let Inst{5-0} = 0b111100;
+}
+
+class POOL32S_ARITH_FM_MMR6<string opstr, bits<9> funct>
+ : MMR6Arch<opstr> {
bits<5> rt;
+ bits<5> rs;
+ bits<5> rd;
bits<32> Inst;
let Inst{31-26} = 0b010110;
- let Inst{25-21} = rd;
+ let Inst{25-21} = rt;
let Inst{20-16} = rs;
- let Inst{15-11} = rt;
+ let Inst{15-11} = rd;
let Inst{10-9} = 0b00;
- let Inst{8-0} = funct;
+ let Inst{8-0} = funct;
+}
+
+class DADDIU_FM_MMR6<string opstr> : MMR6Arch<opstr> {
+ bits<5> rt;
+ bits<5> rs;
+ bits<16> imm16;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = 0b010111;
+ let Inst{25-21} = rt;
+ let Inst{20-16} = rs;
+ let Inst{15-0} = imm16;
+}
+
+class PCREL18_FM_MMR6<bits<3> funct> : MipsR6Inst {
+ bits<5> rt;
+ bits<18> imm;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = 0b011110;
+ let Inst{25-21} = rt;
+ let Inst{20-18} = funct;
+ let Inst{17-0} = imm;
+}
+
+class POOL32S_2R_FM_MMR6<string instr_asm, bits<10> funct>
+ : MMR6Arch<instr_asm>, MipsR6Inst {
+ bits<5> rt;
+ bits<5> rs;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = 0b010110;
+ let Inst{25-21} = rt;
+ let Inst{20-16} = rs;
+ let Inst{15-6} = funct;
+ let Inst{5-0} = 0b111100;
+}
+
+class POOL32S_2RSA5B0_FM_MMR6<string instr_asm, bits<9> funct>
+ : MMR6Arch<instr_asm>, MipsR6Inst {
+ bits<5> rt;
+ bits<5> rs;
+ bits<5> sa;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = 0b010110;
+ let Inst{25-21} = rt;
+ let Inst{20-16} = rs;
+ let Inst{15-11} = sa;
+ let Inst{10-9} = 0b00;
+ let Inst{8-0} = funct;
+}
+
+class LD_SD_32_2R_OFFSET16_FM_MMR6<string instr_asm, bits<6> op>
+ : MMR6Arch<instr_asm>, MipsR6Inst {
+ bits<5> rt;
+ bits<21> addr;
+ bits<5> base = addr{20-16};
+ bits<16> offset = addr{15-0};
+
+ bits<32> Inst;
+
+ let Inst{31-26} = op;
+ let Inst{25-21} = rt;
+ let Inst{20-16} = base;
+ let Inst{15-0} = offset;
+}
+
+class POOL32C_2R_OFFSET12_FM_MMR6<string instr_asm, bits<4> funct>
+ : MMR6Arch<instr_asm>, MipsR6Inst {
+ bits<5> rt;
+ bits<21> addr;
+ bits<5> base = addr{20-16};
+ bits<12> offset = addr{11-0};
+
+ bits<32> Inst;
+
+ let Inst{31-26} = 0b011000;
+ let Inst{25-21} = rt;
+ let Inst{20-16} = base;
+ let Inst{15-12} = funct;
+ let Inst{11-0} = offset;
+}
+
+class POOL32S_3R_FM_MMR6<string instr_asm, bits<9> funct>
+ : MMR6Arch<instr_asm>, MipsR6Inst {
+ bits<5> rt;
+ bits<5> rs;
+ bits<5> rd;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = 0b010110;
+ let Inst{25-21} = rt;
+ let Inst{20-16} = rs;
+ let Inst{15-11} = rd;
+ let Inst{10-9} = 0b00;
+ let Inst{8-0} = funct;
}
diff --git a/lib/Target/Mips/MicroMips64r6InstrInfo.td b/lib/Target/Mips/MicroMips64r6InstrInfo.td
index ec1aef86a9426..87c41deb85af8 100644
--- a/lib/Target/Mips/MicroMips64r6InstrInfo.td
+++ b/lib/Target/Mips/MicroMips64r6InstrInfo.td
@@ -28,6 +28,45 @@ class DDIV_MM64R6_ENC : POOL32A_DIVMOD_FM_MMR6<"ddiv", 0b100011000>;
class DMOD_MM64R6_ENC : POOL32A_DIVMOD_FM_MMR6<"dmod", 0b101011000>;
class DDIVU_MM64R6_ENC : POOL32A_DIVMOD_FM_MMR6<"ddivu", 0b110011000>;
class DMODU_MM64R6_ENC : POOL32A_DIVMOD_FM_MMR6<"dmodu", 0b111011000>;
+class DINSU_MM64R6_ENC : POOL32S_EXTBITS_FM_MMR6<0b110100>;
+class DINSM_MM64R6_ENC : POOL32S_EXTBITS_FM_MMR6<0b000100>;
+class DINS_MM64R6_ENC : POOL32S_EXTBITS_FM_MMR6<0b001100>;
+class DMTC0_MM64R6_ENC : POOL32S_DMFTC0_FM_MMR6<"dmtc0", 0b01011>;
+class DMTC1_MM64R6_ENC : POOL32F_MFTC1_FM_MMR6<"dmtc1", 0b10110000>;
+class DMTC2_MM64R6_ENC : POOL32A_MFTC2_FM_MMR6<"dmtc2", 0b0111110100>;
+class DMFC0_MM64R6_ENC : POOL32S_DMFTC0_FM_MMR6<"dmfc0", 0b00011>;
+class DMFC1_MM64R6_ENC : POOL32F_MFTC1_FM_MMR6<"dmfc1", 0b10010000>;
+class DMFC2_MM64R6_ENC : POOL32A_MFTC2_FM_MMR6<"dmfc2", 0b0110110100>;
+class DADD_MM64R6_ENC : POOL32S_ARITH_FM_MMR6<"dadd", 0b100010000>;
+class DADDIU_MM64R6_ENC : DADDIU_FM_MMR6<"daddiu">;
+class DADDU_MM64R6_ENC : POOL32S_ARITH_FM_MMR6<"daddu", 0b101010000>;
+class LDPC_MMR646_ENC : PCREL18_FM_MMR6<0b110>;
+class DSUB_MM64R6_ENC : POOL32S_ARITH_FM_MMR6<"dsub", 0b110010000>;
+class DSUBU_MM64R6_ENC : POOL32S_ARITH_FM_MMR6<"dsubu", 0b111010000>;
+class DMUL_MM64R6_ENC : POOL32S_ARITH_FM_MMR6<"dmul", 0b000011000>;
+class DMUH_MM64R6_ENC : POOL32S_ARITH_FM_MMR6<"dmuh", 0b001011000>;
+class DMULU_MM64R6_ENC : POOL32S_ARITH_FM_MMR6<"dmulu", 0b010011000>;
+class DMUHU_MM64R6_ENC : POOL32S_ARITH_FM_MMR6<"dmuhu", 0b011011000>;
+class DSBH_MM64R6_ENC : POOL32S_2R_FM_MMR6<"dsbh", 0b0111101100>;
+class DSHD_MM64R6_ENC : POOL32S_2R_FM_MMR6<"dshd", 0b1111101100>;
+class DSLL_MM64R6_ENC : POOL32S_2RSA5B0_FM_MMR6<"dsll", 0b000000000>;
+class DSLL32_MM64R6_ENC : POOL32S_2RSA5B0_FM_MMR6<"dsll32", 0b000001000>;
+class DSLLV_MM64R6_ENC : POOL32S_3R_FM_MMR6<"dsllv", 0b000010000>;
+class DSRAV_MM64R6_ENC : POOL32S_3R_FM_MMR6<"dsrav", 0b010010000>;
+class DSRA_MM64R6_ENC : POOL32S_2RSA5B0_FM_MMR6<"dsra", 0b010000000>;
+class DSRA32_MM64R6_ENC : POOL32S_2RSA5B0_FM_MMR6<"dsra32", 0b010000100>;
+class DCLO_MM64R6_ENC : POOL32S_2R_FM_MMR6<"dclo", 0b0100101100>;
+class DCLZ_MM64R6_ENC : POOL32S_2R_FM_MMR6<"dclz", 0b0101101100>;
+class DROTR_MM64R6_ENC : POOL32S_2RSA5B0_FM_MMR6<"drotr", 0b011000000>;
+class DROTR32_MM64R6_ENC : POOL32S_2RSA5B0_FM_MMR6<"drotr32", 0b011001000>;
+class DROTRV_MM64R6_ENC : POOL32S_3R_FM_MMR6<"drotrv", 0b011010000>;
+class LD_MM64R6_ENC : LD_SD_32_2R_OFFSET16_FM_MMR6<"ld", 0b110111>;
+class LLD_MM64R6_ENC : POOL32C_2R_OFFSET12_FM_MMR6<"lld", 0b0111>;
+class LWU_MM64R6_ENC : POOL32C_2R_OFFSET12_FM_MMR6<"lwu", 0b1110>;
+class SD_MM64R6_ENC : LD_SD_32_2R_OFFSET16_FM_MMR6<"sd", 0b110110>;
+class DSRL_MM64R6_ENC : POOL32S_2RSA5B0_FM_MMR6<"dsrl", 0b001000000>;
+class DSRL32_MM64R6_ENC : POOL32S_2RSA5B0_FM_MMR6<"dsrl32", 0b001001000>;
+class DSRLV_MM64R6_ENC : POOL32S_3R_FM_MMR6<"dsrlv", 0b001010000>;
//===----------------------------------------------------------------------===//
//
@@ -68,7 +107,7 @@ class EXTBITS_DESC_BASE<string instr_asm, RegisterOperand RO, Operand PosOpnd,
// TODO: Add 'pos + size' constraint check to dext* instructions
// DEXT: 0 < pos + size <= 63
// DEXTM, DEXTU: 32 < pos + size <= 64
-class DEXT_MMR6_DESC : EXTBITS_DESC_BASE<"dext", GPR64Opnd, uimm5,
+class DEXT_MMR6_DESC : EXTBITS_DESC_BASE<"dext", GPR64Opnd, uimm5_report_uimm6,
uimm5_plus1, MipsExt>;
class DEXTM_MMR6_DESC : EXTBITS_DESC_BASE<"dextm", GPR64Opnd, uimm5,
uimm5_plus33, MipsExt>;
@@ -85,10 +124,189 @@ class DALIGN_DESC_BASE<string instr_asm, RegisterOperand GPROpnd,
class DALIGN_MMR6_DESC : DALIGN_DESC_BASE<"dalign", GPR64Opnd, uimm3>;
-class DDIV_MM64R6_DESC : ArithLogicR<"ddiv", GPR32Opnd>;
-class DMOD_MM64R6_DESC : ArithLogicR<"dmod", GPR32Opnd>;
-class DDIVU_MM64R6_DESC : ArithLogicR<"ddivu", GPR32Opnd>;
-class DMODU_MM64R6_DESC : ArithLogicR<"dmodu", GPR32Opnd>;
+class DDIV_MM64R6_DESC : DIVMOD_MMR6_DESC_BASE<"ddiv", GPR64Opnd, sdiv>;
+class DMOD_MM64R6_DESC : DIVMOD_MMR6_DESC_BASE<"dmod", GPR64Opnd, srem>;
+class DDIVU_MM64R6_DESC : DIVMOD_MMR6_DESC_BASE<"ddivu", GPR64Opnd, udiv>;
+class DMODU_MM64R6_DESC : DIVMOD_MMR6_DESC_BASE<"dmodu", GPR64Opnd, urem>;
+
+class DCLO_MM64R6_DESC {
+ dag OutOperandList = (outs GPR64Opnd:$rt);
+ dag InOperandList = (ins GPR64Opnd:$rs);
+ string AsmString = !strconcat("dclo", "\t$rt, $rs");
+ list<dag> Pattern = [(set GPR64Opnd:$rt, (ctlz (not GPR64Opnd:$rs)))];
+ InstrItinClass Itinerary = II_CLO;
+ Format Form = FrmR;
+ string BaseOpcode = "dclo";
+}
+
+class DCLZ_MM64R6_DESC {
+ dag OutOperandList = (outs GPR64Opnd:$rt);
+ dag InOperandList = (ins GPR64Opnd:$rs);
+ string AsmString = !strconcat("dclz", "\t$rt, $rs");
+ list<dag> Pattern = [(set GPR64Opnd:$rt, (ctlz GPR64Opnd:$rs))];
+ InstrItinClass Itinerary = II_CLZ;
+ Format Form = FrmR;
+ string BaseOpcode = "dclz";
+}
+
+class DINSU_MM64R6_DESC : InsBase<"dinsu", GPR64Opnd, uimm5_plus32,
+ uimm5_inssize_plus1, MipsIns>;
+class DINSM_MM64R6_DESC : InsBase<"dinsm", GPR64Opnd, uimm5, uimm_range_2_64>;
+class DINS_MM64R6_DESC : InsBase<"dins", GPR64Opnd, uimm5, uimm5_inssize_plus1,
+ MipsIns>;
+class DMTC0_MM64R6_DESC : MTC0_MMR6_DESC_BASE<"dmtc0", COP0Opnd, GPR64Opnd>;
+class DMTC1_MM64R6_DESC : MTC1_MMR6_DESC_BASE<"dmtc1", FGR64Opnd, GPR64Opnd,
+ II_DMTC1, bitconvert>;
+class DMTC2_MM64R6_DESC : MTC2_MMR6_DESC_BASE<"dmtc2", COP2Opnd, GPR64Opnd>;
+
+class DMFC0_MM64R6_DESC : MFC0_MMR6_DESC_BASE<"dmfc0", GPR64Opnd, COP0Opnd>;
+class DMFC1_MM64R6_DESC : MFC1_MMR6_DESC_BASE<"dmfc1", GPR64Opnd, FGR64Opnd,
+ II_DMFC1, bitconvert>;
+class DMFC2_MM64R6_DESC : MFC2_MMR6_DESC_BASE<"dmfc2", GPR64Opnd, COP2Opnd>;
+
+class DADD_MM64R6_DESC : ArithLogicR<"dadd", GPR64Opnd, 1, II_DADD>;
+class DADDIU_MM64R6_DESC : ArithLogicI<"daddiu", simm16_64, GPR64Opnd,
+ II_DADDIU, immSExt16, add>,
+ IsAsCheapAsAMove;
+class DADDU_MM64R6_DESC : ArithLogicR<"daddu", GPR64Opnd, 1, II_DADDU, add>;
+
+class DSUB_DESC_BASE<string instr_asm, RegisterOperand RO,
+ InstrItinClass Itin = NoItinerary,
+ SDPatternOperator OpNode = null_frag>
+ : MipsR6Inst {
+ dag OutOperandList = (outs RO:$rd);
+ dag InOperandList = (ins RO:$rs, RO:$rt);
+ string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt");
+ list<dag> Pattern = [(set RO:$rd, (OpNode RO:$rs, RO:$rt))];
+ InstrItinClass Itinerary = Itin;
+ Format Form = FrmR;
+ string BaseOpcode = instr_asm;
+ let isCommutable = 0;
+ let isReMaterializable = 1;
+ let TwoOperandAliasConstraint = "$rd = $rs";
+}
+class DSUB_MM64R6_DESC : DSUB_DESC_BASE<"dsub", GPR64Opnd, II_DSUB>;
+class DSUBU_MM64R6_DESC : DSUB_DESC_BASE<"dsubu", GPR64Opnd, II_DSUBU, sub>;
+
+class LDPC_MM64R6_DESC : PCREL_MMR6_DESC_BASE<"ldpc", GPR64Opnd, simm18_lsl3>;
+
+class MUL_MM64R6_DESC_BASE<string opstr, RegisterOperand GPROpnd,
+ InstrItinClass Itin = NoItinerary,
+ SDPatternOperator Op = null_frag> : MipsR6Inst {
+ dag OutOperandList = (outs GPROpnd:$rd);
+ dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt);
+ string AsmString = !strconcat(opstr, "\t$rd, $rs, $rt");
+ InstrItinClass Itinerary = Itin;
+ list<dag> Pattern = [(set GPROpnd:$rd, (Op GPROpnd:$rs, GPROpnd:$rt))];
+}
+
+class DMUL_MM64R6_DESC : MUL_MM64R6_DESC_BASE<"dmul", GPR64Opnd, II_DMUL, mul>;
+class DMUH_MM64R6_DESC : MUL_MM64R6_DESC_BASE<"dmuh", GPR64Opnd, II_DMUH,
+ mulhs>;
+class DMULU_MM64R6_DESC : MUL_MM64R6_DESC_BASE<"dmulu", GPR64Opnd, II_DMULU>;
+class DMUHU_MM64R6_DESC : MUL_MM64R6_DESC_BASE<"dmuhu", GPR64Opnd, II_DMUHU,
+ mulhu>;
+
+class DSBH_DSHD_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> {
+ dag OutOperandList = (outs GPROpnd:$rt);
+ dag InOperandList = (ins GPROpnd:$rs);
+ string AsmString = !strconcat(instr_asm, "\t$rt, $rs");
+ bit hasSideEffects = 0;
+ list<dag> Pattern = [];
+ InstrItinClass Itinerary = NoItinerary;
+ Format Form = FrmR;
+ string BaseOpcode = instr_asm;
+}
+
+class DSBH_MM64R6_DESC : DSBH_DSHD_DESC_BASE<"dsbh", GPR64Opnd>;
+class DSHD_MM64R6_DESC : DSBH_DSHD_DESC_BASE<"dshd", GPR64Opnd>;
+
+class SHIFT_ROTATE_IMM_MM64R6<string instr_asm, Operand ImmOpnd,
+ InstrItinClass itin,
+ SDPatternOperator OpNode = null_frag,
+ SDPatternOperator PO = null_frag> {
+ dag OutOperandList = (outs GPR64Opnd:$rt);
+ dag InOperandList = (ins GPR64Opnd:$rs, ImmOpnd:$sa);
+ string AsmString = !strconcat(instr_asm, "\t$rt, $rs, $sa");
+ list<dag> Pattern = [(set GPR64Opnd:$rt, (OpNode GPR64Opnd:$rs, PO:$sa))];
+ InstrItinClass Itinerary = itin;
+ Format Form = FrmR;
+ string TwoOperandAliasConstraint = "$rs = $rt";
+ string BaseOpcode = instr_asm;
+}
+
+class SHIFT_ROTATE_REG_MM64R6<string instr_asm, InstrItinClass itin,
+ SDPatternOperator OpNode = null_frag> {
+ dag OutOperandList = (outs GPR64Opnd:$rd);
+ dag InOperandList = (ins GPR64Opnd:$rt, GPR32Opnd:$rs);
+ string AsmString = !strconcat(instr_asm, "\t$rd, $rt, $rs");
+ list<dag> Pattern = [(set GPR64Opnd:$rd,
+ (OpNode GPR64Opnd:$rt, GPR32Opnd:$rs))];
+ InstrItinClass Itinerary = itin;
+ Format Form = FrmR;
+ string BaseOpcode = instr_asm;
+}
+
+class DSLL_MM64R6_DESC : SHIFT_ROTATE_IMM_MM64R6<"dsll", uimm6, II_DSLL, shl,
+ immZExt6>;
+class DSLL32_MM64R6_DESC : SHIFT_ROTATE_IMM_MM64R6<"dsll32", uimm5, II_DSLL32>;
+class DSLLV_MM64R6_DESC : SHIFT_ROTATE_REG_MM64R6<"dsllv", II_DSLLV, shl>;
+class DSRAV_MM64R6_DESC : SHIFT_ROTATE_REG_MM64R6<"dsrav", II_DSRAV, sra>;
+class DSRA_MM64R6_DESC : SHIFT_ROTATE_IMM_MM64R6<"dsra", uimm6, II_DSRA, sra,
+ immZExt6>;
+class DSRA32_MM64R6_DESC : SHIFT_ROTATE_IMM_MM64R6<"dsra32", uimm5, II_DSRA32>;
+class DROTR_MM64R6_DESC : SHIFT_ROTATE_IMM_MM64R6<"drotr", uimm6, II_DROTR,
+ rotr, immZExt6>;
+class DROTR32_MM64R6_DESC : SHIFT_ROTATE_IMM_MM64R6<"drotr32", uimm5,
+ II_DROTR32>;
+class DROTRV_MM64R6_DESC : SHIFT_ROTATE_REG_MM64R6<"drotrv", II_DROTRV, rotr>;
+class DSRL_MM64R6_DESC : SHIFT_ROTATE_IMM_MM64R6<"dsrl", uimm6, II_DSRL, srl,
+ immZExt6>;
+class DSRL32_MM64R6_DESC : SHIFT_ROTATE_IMM_MM64R6<"dsrl32", uimm5, II_DSRL32>;
+class DSRLV_MM64R6_DESC : SHIFT_ROTATE_REG_MM64R6<"dsrlv", II_DSRLV, srl>;
+
+class Load_MM64R6<string instr_asm, Operand MemOpnd, InstrItinClass itin,
+ SDPatternOperator OpNode = null_frag> {
+ dag OutOperandList = (outs GPR64Opnd:$rt);
+ dag InOperandList = (ins MemOpnd:$addr);
+ string AsmString = !strconcat(instr_asm, "\t$rt, $addr");
+ list<dag> Pattern = [(set GPR64Opnd:$rt, (OpNode addr:$addr))];
+ InstrItinClass Itinerary = itin;
+ Format Form = FrmI;
+ bit mayLoad = 1;
+ bit canFoldAsLoad = 1;
+ string BaseOpcode = instr_asm;
+}
+
+class LD_MM64R6_DESC : Load_MM64R6<"ld", mem_simm16, II_LD, load> {
+ string DecoderMethod = "DecodeMemMMImm16";
+}
+class LWU_MM64R6_DESC : Load_MM64R6<"lwu", mem_simm12, II_LWU, zextloadi32>{
+ string DecoderMethod = "DecodeMemMMImm12";
+}
+
+class LLD_MM64R6_DESC {
+ dag OutOperandList = (outs GPR64Opnd:$rt);
+ dag InOperandList = (ins mem_simm12:$addr);
+ string AsmString = "lld\t$rt, $addr";
+ list<dag> Pattern = [];
+ bit mayLoad = 1;
+ InstrItinClass Itinerary = II_LLD;
+ string BaseOpcode = "lld";
+ string DecoderMethod = "DecodeMemMMImm12";
+}
+
+class SD_MM64R6_DESC {
+ dag OutOperandList = (outs);
+ dag InOperandList = (ins GPR64Opnd:$rt, mem_simm16:$addr);
+ string AsmString = "sd\t$rt, $addr";
+ list<dag> Pattern = [(store GPR64Opnd:$rt, addr:$addr)];
+ InstrItinClass Itinerary = II_SD;
+ Format Form = FrmI;
+ bit mayStore = 1;
+ string BaseOpcode = "sd";
+ string DecoderMethod = "DecodeMemMMImm16";
+}
//===----------------------------------------------------------------------===//
//
@@ -116,4 +334,180 @@ let DecoderNamespace = "MicroMipsR6" in {
ISA_MICROMIPS64R6;
def DMODU_MM64R6 : R6MMR6Rel, DMODU_MM64R6_DESC, DMODU_MM64R6_ENC,
ISA_MICROMIPS64R6;
+ def DINSU_MM64R6: R6MMR6Rel, DINSU_MM64R6_DESC, DINSU_MM64R6_ENC,
+ ISA_MICROMIPS64R6;
+ def DINSM_MM64R6: R6MMR6Rel, DINSM_MM64R6_DESC, DINSM_MM64R6_ENC,
+ ISA_MICROMIPS64R6;
+ def DINS_MM64R6: R6MMR6Rel, DINS_MM64R6_DESC, DINS_MM64R6_ENC,
+ ISA_MICROMIPS64R6;
+ def DMTC0_MM64R6 : StdMMR6Rel, DMTC0_MM64R6_ENC, DMTC0_MM64R6_DESC,
+ ISA_MICROMIPS64R6;
+ def DMTC1_MM64R6 : StdMMR6Rel, DMTC1_MM64R6_DESC, DMTC1_MM64R6_ENC,
+ ISA_MICROMIPS64R6;
+ def DMTC2_MM64R6 : StdMMR6Rel, DMTC2_MM64R6_ENC, DMTC2_MM64R6_DESC,
+ ISA_MICROMIPS64R6;
+ def DMFC0_MM64R6 : StdMMR6Rel, DMFC0_MM64R6_ENC, DMFC0_MM64R6_DESC,
+ ISA_MICROMIPS64R6;
+ def DMFC1_MM64R6 : StdMMR6Rel, DMFC1_MM64R6_DESC, DMFC1_MM64R6_ENC,
+ ISA_MICROMIPS64R6;
+ def DMFC2_MM64R6 : StdMMR6Rel, DMFC2_MM64R6_ENC, DMFC2_MM64R6_DESC,
+ ISA_MICROMIPS64R6;
+ def DADD_MM64R6: StdMMR6Rel, DADD_MM64R6_DESC, DADD_MM64R6_ENC,
+ ISA_MICROMIPS64R6;
+ def DADDIU_MM64R6: StdMMR6Rel, DADDIU_MM64R6_DESC, DADDIU_MM64R6_ENC,
+ ISA_MICROMIPS64R6;
+ def DADDU_MM64R6: StdMMR6Rel, DADDU_MM64R6_DESC, DADDU_MM64R6_ENC,
+ ISA_MICROMIPS64R6;
+ def LDPC_MM64R6 : R6MMR6Rel, LDPC_MMR646_ENC, LDPC_MM64R6_DESC,
+ ISA_MICROMIPS64R6;
+ def DSUB_MM64R6 : StdMMR6Rel, DSUB_MM64R6_DESC, DSUB_MM64R6_ENC,
+ ISA_MICROMIPS64R6;
+ def DSUBU_MM64R6 : StdMMR6Rel, DSUBU_MM64R6_DESC, DSUBU_MM64R6_ENC,
+ ISA_MICROMIPS64R6;
+ def DMUL_MM64R6 : R6MMR6Rel, DMUL_MM64R6_DESC, DMUL_MM64R6_ENC,
+ ISA_MICROMIPS64R6;
+ def DMUH_MM64R6 : R6MMR6Rel, DMUH_MM64R6_DESC, DMUH_MM64R6_ENC,
+ ISA_MICROMIPS64R6;
+ def DMULU_MM64R6 : R6MMR6Rel, DMULU_MM64R6_DESC, DMULU_MM64R6_ENC,
+ ISA_MICROMIPS64R6;
+ def DMUHU_MM64R6 : R6MMR6Rel, DMUHU_MM64R6_DESC, DMUHU_MM64R6_ENC,
+ ISA_MICROMIPS64R6;
+ def DSBH_MM64R6 : R6MMR6Rel, DSBH_MM64R6_ENC, DSBH_MM64R6_DESC,
+ ISA_MICROMIPS64R6;
+ def DSHD_MM64R6 : R6MMR6Rel, DSHD_MM64R6_ENC, DSHD_MM64R6_DESC,
+ ISA_MICROMIPS64R6;
+ def DSLL_MM64R6 : StdMMR6Rel, DSLL_MM64R6_ENC, DSLL_MM64R6_DESC,
+ ISA_MICROMIPS64R6;
+ def DSLL32_MM64R6 : StdMMR6Rel, DSLL32_MM64R6_ENC, DSLL32_MM64R6_DESC,
+ ISA_MICROMIPS64R6;
+ def DSLLV_MM64R6 : StdMMR6Rel, DSLLV_MM64R6_ENC, DSLLV_MM64R6_DESC,
+ ISA_MICROMIPS64R6;
+ def DSRAV_MM64R6 : StdMMR6Rel, DSRAV_MM64R6_ENC, DSRAV_MM64R6_DESC,
+ ISA_MICROMIPS64R6;
+ def DSRA_MM64R6 : StdMMR6Rel, DSRA_MM64R6_ENC, DSRA_MM64R6_DESC,
+ ISA_MICROMIPS64R6;
+ def DSRA32_MM64R6 : StdMMR6Rel, DSRA32_MM64R6_ENC, DSRA32_MM64R6_DESC,
+ ISA_MICROMIPS64R6;
+ def DCLO_MM64R6 : StdMMR6Rel, R6MMR6Rel, DCLO_MM64R6_ENC, DCLO_MM64R6_DESC,
+ ISA_MICROMIPS64R6;
+ def DCLZ_MM64R6 : StdMMR6Rel, R6MMR6Rel, DCLZ_MM64R6_ENC, DCLZ_MM64R6_DESC,
+ ISA_MICROMIPS64R6;
+ def DROTR_MM64R6 : StdMMR6Rel, DROTR_MM64R6_ENC, DROTR_MM64R6_DESC,
+ ISA_MICROMIPS64R6;
+ def DROTR32_MM64R6 : StdMMR6Rel, DROTR32_MM64R6_ENC, DROTR32_MM64R6_DESC,
+ ISA_MICROMIPS64R6;
+ def DROTRV_MM64R6 : StdMMR6Rel, DROTRV_MM64R6_ENC, DROTRV_MM64R6_DESC,
+ ISA_MICROMIPS64R6;
+ def LD_MM64R6 : StdMMR6Rel, LD_MM64R6_ENC, LD_MM64R6_DESC,
+ ISA_MICROMIPS64R6;
+ def LLD_MM64R6 : StdMMR6Rel, R6MMR6Rel, LLD_MM64R6_ENC, LLD_MM64R6_DESC,
+ ISA_MICROMIPS64R6;
+ def LWU_MM64R6 : StdMMR6Rel, LWU_MM64R6_ENC, LWU_MM64R6_DESC,
+ ISA_MICROMIPS64R6;
+ def SD_MM64R6 : StdMMR6Rel, SD_MM64R6_ENC, SD_MM64R6_DESC,
+ ISA_MICROMIPS64R6;
+ def DSRL_MM64R6 : StdMMR6Rel, DSRL_MM64R6_ENC, DSRL_MM64R6_DESC,
+ ISA_MICROMIPS64R6;
+ def DSRL32_MM64R6 : StdMMR6Rel, DSRL32_MM64R6_ENC, DSRL32_MM64R6_DESC,
+ ISA_MICROMIPS64R6;
+ def DSRLV_MM64R6 : StdMMR6Rel, DSRLV_MM64R6_ENC, DSRLV_MM64R6_DESC,
+ ISA_MICROMIPS64R6;
}
+
+//===----------------------------------------------------------------------===//
+//
+// Arbitrary patterns that map to one or more instructions
+//
+//===----------------------------------------------------------------------===//
+
+def : MipsPat<(MipsLo tglobaladdr:$in),
+ (DADDIU_MM64R6 ZERO_64, tglobaladdr:$in)>, ISA_MICROMIPS64R6;
+def : MipsPat<(MipsLo tblockaddress:$in),
+ (DADDIU_MM64R6 ZERO_64, tblockaddress:$in)>, ISA_MICROMIPS64R6;
+def : MipsPat<(MipsLo tjumptable:$in),
+ (DADDIU_MM64R6 ZERO_64, tjumptable:$in)>, ISA_MICROMIPS64R6;
+def : MipsPat<(MipsLo tconstpool:$in),
+ (DADDIU_MM64R6 ZERO_64, tconstpool:$in)>, ISA_MICROMIPS64R6;
+def : MipsPat<(MipsLo tglobaltlsaddr:$in),
+ (DADDIU_MM64R6 ZERO_64, tglobaltlsaddr:$in)>, ISA_MICROMIPS64R6;
+def : MipsPat<(MipsLo texternalsym:$in),
+ (DADDIU_MM64R6 ZERO_64, texternalsym:$in)>, ISA_MICROMIPS64R6;
+
+def : MipsPat<(add GPR64:$hi, (MipsLo tglobaladdr:$lo)),
+ (DADDIU_MM64R6 GPR64:$hi, tglobaladdr:$lo)>, ISA_MICROMIPS64R6;
+def : MipsPat<(add GPR64:$hi, (MipsLo tblockaddress:$lo)),
+ (DADDIU_MM64R6 GPR64:$hi, tblockaddress:$lo)>, ISA_MICROMIPS64R6;
+def : MipsPat<(add GPR64:$hi, (MipsLo tjumptable:$lo)),
+ (DADDIU_MM64R6 GPR64:$hi, tjumptable:$lo)>, ISA_MICROMIPS64R6;
+def : MipsPat<(add GPR64:$hi, (MipsLo tconstpool:$lo)),
+ (DADDIU_MM64R6 GPR64:$hi, tconstpool:$lo)>, ISA_MICROMIPS64R6;
+def : MipsPat<(add GPR64:$hi, (MipsLo tglobaltlsaddr:$lo)),
+ (DADDIU_MM64R6 GPR64:$hi, tglobaltlsaddr:$lo)>, ISA_MICROMIPS64R6;
+
+def : MipsPat<(addc GPR64:$lhs, GPR64:$rhs),
+ (DADDU_MM64R6 GPR64:$lhs, GPR64:$rhs)>, ISA_MICROMIPS64R6;
+def : MipsPat<(addc GPR64:$lhs, immSExt16:$imm),
+ (DADDIU_MM64R6 GPR64:$lhs, imm:$imm)>, ISA_MICROMIPS64R6;
+
+
+def : MipsPat<(rotr GPR64:$rt, (i32 (trunc GPR64:$rs))),
+ (DROTRV_MM64R6 GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>,
+ ISA_MICROMIPS64R6;
+
+
+def : WrapperPat<tglobaladdr, DADDIU_MM64R6, GPR64>, ISA_MICROMIPS64R6;
+def : WrapperPat<tconstpool, DADDIU_MM64R6, GPR64>, ISA_MICROMIPS64R6;
+def : WrapperPat<texternalsym, DADDIU_MM64R6, GPR64>, ISA_MICROMIPS64R6;
+def : WrapperPat<tblockaddress, DADDIU_MM64R6, GPR64>, ISA_MICROMIPS64R6;
+def : WrapperPat<tjumptable, DADDIU_MM64R6, GPR64>, ISA_MICROMIPS64R6;
+def : WrapperPat<tglobaltlsaddr, DADDIU_MM64R6, GPR64>, ISA_MICROMIPS64R6;
+
+// Carry pattern
+def : MipsPat<(subc GPR64:$lhs, GPR64:$rhs),
+ (DSUBU_MM64R6 GPR64:$lhs, GPR64:$rhs)>, ISA_MICROMIPS64R6;
+
+def : MipsPat<(atomic_load_64 addr:$a), (LD_MM64R6 addr:$a)>, ISA_MICROMIPS64R6;
+
+//===----------------------------------------------------------------------===//
+//
+// Instruction aliases
+//
+//===----------------------------------------------------------------------===//
+
+def : MipsInstAlias<"dmtc0 $rt, $rd",
+ (DMTC0_MM64R6 COP0Opnd:$rd, GPR64Opnd:$rt, 0), 0>;
+def : MipsInstAlias<"dmfc0 $rt, $rd",
+ (DMFC0_MM64R6 GPR64Opnd:$rt, COP0Opnd:$rd, 0), 0>,
+ ISA_MICROMIPS64R6;
+def : MipsInstAlias<"daddu $rs, $rt, $imm",
+ (DADDIU_MM64R6 GPR64Opnd:$rs,
+ GPR64Opnd:$rt,
+ simm16_64:$imm),
+ 0>, ISA_MICROMIPS64R6;
+def : MipsInstAlias<"daddu $rs, $imm",
+ (DADDIU_MM64R6 GPR64Opnd:$rs,
+ GPR64Opnd:$rs,
+ simm16_64:$imm),
+ 0>, ISA_MICROMIPS64R6;
+def : MipsInstAlias<"dsubu $rt, $rs, $imm",
+ (DADDIU_MM64R6 GPR64Opnd:$rt,
+ GPR64Opnd:$rs,
+ InvertedImOperand64:$imm),
+ 0>, ISA_MICROMIPS64R6;
+def : MipsInstAlias<"dsubu $rs, $imm",
+ (DADDIU_MM64R6 GPR64Opnd:$rs,
+ GPR64Opnd:$rs,
+ InvertedImOperand64:$imm),
+ 0>, ISA_MICROMIPS64R6;
+def : MipsInstAlias<"dneg $rt, $rs",
+ (DSUB_MM64R6 GPR64Opnd:$rt, ZERO_64, GPR64Opnd:$rs), 1>,
+ ISA_MICROMIPS64R6;
+def : MipsInstAlias<"dneg $rt",
+ (DSUB_MM64R6 GPR64Opnd:$rt, ZERO_64, GPR64Opnd:$rt), 0>,
+ ISA_MICROMIPS64R6;
+def : MipsInstAlias<"dnegu $rt, $rs",
+ (DSUBU_MM64R6 GPR64Opnd:$rt, ZERO_64, GPR64Opnd:$rs), 1>,
+ ISA_MICROMIPS64R6;
+def : MipsInstAlias<"dnegu $rt",
+ (DSUBU_MM64R6 GPR64Opnd:$rt, ZERO_64, GPR64Opnd:$rt), 0>,
+ ISA_MICROMIPS64R6;
diff --git a/lib/Target/Mips/MicroMipsDSPInstrFormats.td b/lib/Target/Mips/MicroMipsDSPInstrFormats.td
index f11c09abfc367..af6473c468d9b 100644
--- a/lib/Target/Mips/MicroMipsDSPInstrFormats.td
+++ b/lib/Target/Mips/MicroMipsDSPInstrFormats.td
@@ -242,3 +242,61 @@ class POOL32A_5B01RAC_FMT<string opstr, bits<8> op> : MMDSPInst<opstr> {
let Inst{13-6} = op;
let Inst{5-0} = 0b111100;
}
+
+class POOL32I_IMMB0_FMT<string opstr, bits<5> op> : MMDSPInst<opstr> {
+ bits<16> offset;
+
+ let Inst{31-26} = 0b010000;
+ let Inst{25-21} = op;
+ let Inst{20-16} = 0;
+ let Inst{15-0} = offset;
+}
+
+class POOL32A_2RBP_FMT<string opstr> : MMDSPInst<opstr> {
+ bits<5> rt;
+ bits<5> rs;
+ bits<2> bp;
+
+ let Inst{31-26} = 0;
+ let Inst{25-21} = rt;
+ let Inst{20-16} = rs;
+ let Inst{15-14} = bp;
+ let Inst{13-6} = 0b00100010;
+ let Inst{5-0} = 0b111100;
+}
+
+class POOL32A_2RB0_FMT<string opstr, bits<10> op> : MMDSPInst<opstr> {
+ bits<5> rt;
+ bits<5> rs;
+
+ let Inst{31-26} = 0;
+ let Inst{25-21} = rt;
+ let Inst{20-16} = rs;
+ let Inst{15-10} = 0;
+ let Inst{9-0} = op;
+}
+
+class POOL32S_3RB0_FMT<string opstr, bits<10> op> : MMDSPInst<opstr> {
+ bits<5> rt;
+ bits<5> rs;
+ bits<5> rd;
+
+ let Inst{31-26} = 0b010110;
+ let Inst{25-21} = rt;
+ let Inst{20-16} = rs;
+ let Inst{15-11} = rd;
+ let Inst{10} = 0b0;
+ let Inst{9-0} = op;
+}
+
+class POOL32A_2R2B0_FMT<string opstr, bits<10> op> : MMDSPInst<opstr> {
+ bits<5> rt;
+ bits<5> rs;
+
+ let Inst{31-26} = 0;
+ let Inst{25-21} = rt;
+ let Inst{20-16} = rs;
+ let Inst{15-11} = 0;
+ let Inst{10} = 0;
+ let Inst{9-0} = op;
+}
diff --git a/lib/Target/Mips/MicroMipsDSPInstrInfo.td b/lib/Target/Mips/MicroMipsDSPInstrInfo.td
index b342e2371df4c..f82f82fc7e45b 100644
--- a/lib/Target/Mips/MicroMipsDSPInstrInfo.td
+++ b/lib/Target/Mips/MicroMipsDSPInstrInfo.td
@@ -155,6 +155,26 @@ class PICK_QB_MM_ENC : POOL32A_3RB0_FMT<"pick.qb", 0b0111101101>;
class SHILO_MM_ENC : POOL32A_4B0SHIFT6AC4B0_FMT<"shilo", 0b0000011101>;
class SHILOV_MM_ENC : POOL32A_5B01RAC_FMT<"shilov", 0b01001001>;
class WRDSP_MM_ENC : POOL32A_1RMASK7_FMT<"wrdsp", 0b01011001>;
+class APPEND_MMR2_ENC : POOL32A_2RSA5B0_FMT<"append", 0b1000010101>;
+class MODSUB_MM_ENC : POOL32A_3RB0_FMT<"modsub", 0b1010010101>;
+class MULSA_W_PH_MMR2_ENC : POOL32A_2RAC_FMT<"mulsa.w.ph", 0b10110010>;
+class MULSAQ_S_W_PH_MM_ENC : POOL32A_2RAC_FMT<"mulsaq_s.w.ph", 0b11110010>;
+class BPOSGE32C_MMR3_ENC : POOL32I_IMMB0_FMT<"bposge32c", 0b11001>;
+class BITREV_MM_ENC : POOL32A_2R_FMT<"bitrev", 0b0011000100>;
+class BALIGN_MMR2_ENC : POOL32A_2RBP_FMT<"balign">;
+class BPOSGE32_MM_ENC : POOL32I_IMMB0_FMT<"bposge32", 0b11011>;
+class CMP_EQ_PH_MM_ENC : POOL32A_2RB0_FMT<"cmp.eq.ph", 0b0000000101>;
+class CMP_LE_PH_MM_ENC : POOL32A_2RB0_FMT<"cmp.le.ph", 0b0010000101>;
+class CMP_LT_PH_MM_ENC : POOL32A_2RB0_FMT<"cmp.lt.ph", 0b0001000101>;
+class CMPGDU_EQ_QB_MMR2_ENC : POOL32A_3RB0_FMT<"cmpgdu.eq.qb", 0b0110000101>;
+class CMPGDU_LT_QB_MMR2_ENC : POOL32A_3RB0_FMT<"cmpgdu.lt.qb", 0b0111000101>;
+class CMPGDU_LE_QB_MMR2_ENC : POOL32A_3RB0_FMT<"cmpgdu.le.qb", 0b1000000101>;
+class CMPGU_EQ_QB_MM_ENC : POOL32S_3RB0_FMT<"cmpgu.eq.qb", 0b0011000101>;
+class CMPGU_LT_QB_MM_ENC : POOL32S_3RB0_FMT<"cmpgu.lt.qb", 0b0100000101>;
+class CMPGU_LE_QB_MM_ENC : POOL32S_3RB0_FMT<"cmpgu.le.qb", 0b0101000101>;
+class CMPU_EQ_QB_MM_ENC : POOL32A_2R2B0_FMT<"cmpu.eq.qb", 0b1001000101>;
+class CMPU_LT_QB_MM_ENC : POOL32A_2R2B0_FMT<"cmpu.lt.qb", 0b1010000101>;
+class CMPU_LE_QB_MM_ENC : POOL32A_2R2B0_FMT<"cmpu.le.qb", 0b1011000101>;
// Instruction desc.
class ABSQ_S_PH_MM_R2_DESC_BASE<string opstr, SDPatternOperator OpNode,
@@ -339,15 +359,15 @@ class RADDU_W_QB_MM_DESC {
class RDDSP_MM_DESC {
dag OutOperandList = (outs GPR32Opnd:$rt);
- dag InOperandList = (ins uimm16:$mask);
+ dag InOperandList = (ins uimm7:$mask);
string AsmString = !strconcat("rddsp", "\t$rt, $mask");
- list<dag> Pattern = [(set GPR32Opnd:$rt, (int_mips_rddsp immZExt10:$mask))];
+ list<dag> Pattern = [(set GPR32Opnd:$rt, (int_mips_rddsp immZExt7:$mask))];
InstrItinClass Itinerary = NoItinerary;
}
class REPL_QB_MM_DESC {
dag OutOperandList = (outs DSPROpnd:$rt);
- dag InOperandList = (ins uimm16:$imm);
+ dag InOperandList = (ins uimm8:$imm);
string AsmString = !strconcat("repl.qb", "\t$rt, $imm");
list<dag> Pattern = [(set DSPROpnd:$rt, (int_mips_repl_qb immZExt8:$imm))];
InstrItinClass Itinerary = NoItinerary;
@@ -368,6 +388,33 @@ class WRDSP_MM_DESC {
InstrItinClass Itinerary = NoItinerary;
}
+class BPOSGE32C_MMR3_DESC {
+ dag OutOperandList = (outs);
+ dag InOperandList = (ins brtarget1SImm16:$offset);
+ string AsmString = !strconcat("bposge32c", "\t$offset");
+ InstrItinClass Itinerary = NoItinerary;
+ bit isBranch = 1;
+ bit isTerminator = 1;
+ bit hasDelaySlot = 0;
+}
+
+class BALIGN_MMR2_DESC {
+ dag OutOperandList = (outs GPR32Opnd:$rt);
+ dag InOperandList = (ins GPR32Opnd:$rs, uimm2:$bp, GPR32Opnd:$src);
+ string AsmString = !strconcat("balign", "\t$rt, $rs, $bp");
+ list<dag> Pattern = [(set GPR32Opnd:$rt, (int_mips_balign GPR32Opnd:$src,
+ GPR32Opnd:$rs,
+ immZExt2:$bp))];
+ InstrItinClass Itinerary = NoItinerary;
+ string Constraints = "$src = $rt";
+}
+
+class BITREV_MM_DESC : ABSQ_S_PH_MM_R2_DESC_BASE<"bitrev", int_mips_bitrev,
+ NoItinerary, GPR32Opnd>;
+
+class BPOSGE32_MM_DESC : BPOSGE32_DESC_BASE<"bposge32", brtarget_mm,
+ NoItinerary>;
+
// Instruction defs.
// microMIPS DSP Rev 1
def ADDQ_PH_MM : DspMMRel, ADDQ_PH_MM_ENC, ADDQ_PH_DESC;
@@ -472,6 +519,20 @@ def PICK_QB_MM : DspMMRel, PICK_QB_MM_ENC, PICK_QB_DESC;
def SHILO_MM : DspMMRel, SHILO_MM_ENC, SHILO_DESC;
def SHILOV_MM : DspMMRel, SHILOV_MM_ENC, SHILOV_DESC;
def WRDSP_MM : DspMMRel, WRDSP_MM_ENC, WRDSP_MM_DESC;
+def MODSUB_MM : DspMMRel, MODSUB_MM_ENC, MODSUB_DESC;
+def MULSAQ_S_W_PH_MM : DspMMRel, MULSAQ_S_W_PH_MM_ENC, MULSAQ_S_W_PH_DESC;
+def BITREV_MM : DspMMRel, BITREV_MM_ENC, BITREV_MM_DESC;
+def BPOSGE32_MM : DspMMRel, BPOSGE32_MM_ENC, BPOSGE32_MM_DESC,
+ ISA_MIPS1_NOT_32R6_64R6;
+def CMP_EQ_PH_MM : DspMMRel, CMP_EQ_PH_MM_ENC, CMP_EQ_PH_DESC;
+def CMP_LT_PH_MM : DspMMRel, CMP_LT_PH_MM_ENC, CMP_LT_PH_DESC;
+def CMP_LE_PH_MM : DspMMRel, CMP_LE_PH_MM_ENC, CMP_LE_PH_DESC;
+def CMPGU_EQ_QB_MM : DspMMRel, CMPGU_EQ_QB_MM_ENC, CMPGU_EQ_QB_DESC;
+def CMPGU_LT_QB_MM : DspMMRel, CMPGU_LT_QB_MM_ENC, CMPGU_LT_QB_DESC;
+def CMPGU_LE_QB_MM : DspMMRel, CMPGU_LE_QB_MM_ENC, CMPGU_LE_QB_DESC;
+def CMPU_EQ_QB_MM : DspMMRel, CMPU_EQ_QB_MM_ENC, CMPU_EQ_QB_DESC;
+def CMPU_LT_QB_MM : DspMMRel, CMPU_LT_QB_MM_ENC, CMPU_LT_QB_DESC;
+def CMPU_LE_QB_MM : DspMMRel, CMPU_LE_QB_MM_ENC, CMPU_LE_QB_DESC;
// microMIPS DSP Rev 2
def ABSQ_S_QB_MMR2 : DspMMRel, ABSQ_S_QB_MMR2_ENC, ABSQ_S_QB_MMR2_DESC,
ISA_DSPR2;
@@ -495,6 +556,13 @@ def SHRA_R_QB_MMR2 : DspMMRel, SHRA_R_QB_MMR2_ENC, SHRA_R_QB_MMR2_DESC,
def SHRAV_QB_MMR2 : DspMMRel, SHRAV_QB_MMR2_ENC, SHRAV_QB_MMR2_DESC, ISA_DSPR2;
def SHRAV_R_QB_MMR2 : DspMMRel, SHRAV_R_QB_MMR2_ENC, SHRAV_R_QB_MMR2_DESC,
ISA_DSPR2;
+def BALIGN_MMR2 : DspMMRel, BALIGN_MMR2_ENC, BALIGN_MMR2_DESC, ISA_DSPR2;
+def CMPGDU_EQ_QB_MMR2 : DspMMRel, CMPGDU_EQ_QB_MMR2_ENC, CMPGDU_EQ_QB_DESC,
+ ISA_DSPR2;
+def CMPGDU_LT_QB_MMR2 : DspMMRel, CMPGDU_LT_QB_MMR2_ENC, CMPGDU_LT_QB_DESC,
+ ISA_DSPR2;
+def CMPGDU_LE_QB_MMR2 : DspMMRel, CMPGDU_LE_QB_MMR2_ENC, CMPGDU_LE_QB_DESC,
+ ISA_DSPR2;
def SHRL_PH_MMR2 : DspMMRel, SHRL_PH_MMR2_ENC, SHRL_PH_MMR2_DESC, ISA_DSPR2;
def SHRLV_PH_MMR2 : DspMMRel, SHRLV_PH_MMR2_ENC, SHRLV_PH_MMR2_DESC, ISA_DSPR2;
def SUBQH_PH_MMR2 : DspMMRel, SUBQH_PH_MMR2_ENC, SUBQH_PH_DESC, ISA_DSPR2;
@@ -526,3 +594,8 @@ def PREPEND_MMR2 : DspMMRel, PREPEND_MMR2_ENC, PREPEND_DESC, ISA_DSPR2;
// Instruction alias.
def : MMDSPInstAlias<"wrdsp $rt", (WRDSP_MM GPR32Opnd:$rt, 0x1F), 1>;
+def APPEND_MMR2 : DspMMRel, APPEND_MMR2_ENC, APPEND_DESC, ISA_DSPR2;
+def MULSA_W_PH_MMR2 : DspMMRel, MULSA_W_PH_MMR2_ENC, MULSA_W_PH_DESC, ISA_DSPR2;
+// microMIPS DSP Rev 3
+def BPOSGE32C_MMR3 : DspMMRel, BPOSGE32C_MMR3_ENC, BPOSGE32C_MMR3_DESC,
+ ISA_DSPR3;
diff --git a/lib/Target/Mips/MicroMipsInstrFPU.td b/lib/Target/Mips/MicroMipsInstrFPU.td
index 756e6c92c1d11..7b0e00bd1c3c6 100644
--- a/lib/Target/Mips/MicroMipsInstrFPU.td
+++ b/lib/Target/Mips/MicroMipsInstrFPU.td
@@ -17,12 +17,6 @@ def FMUL_MM : MMRel, ADDS_FT<"mul.d", AFGR64Opnd, II_MUL_D, 1, fmul>,
def FSUB_MM : MMRel, ADDS_FT<"sub.d", AFGR64Opnd, II_SUB_D, 0, fsub>,
ADDS_FM_MM<1, 0x70>;
-def LWC1_MM : MMRel, LW_FT<"lwc1", FGR32Opnd, II_LWC1, load>, LW_FM_MM<0x27>;
-def SWC1_MM : MMRel, SW_FT<"swc1", FGR32Opnd, II_SWC1, store>,
- LW_FM_MM<0x26>;
-def LDC1_MM : MMRel, LW_FT<"ldc1", AFGR64Opnd, II_LDC1, load>, LW_FM_MM<0x2f>;
-def SDC1_MM : MMRel, SW_FT<"sdc1", AFGR64Opnd, II_SDC1, store>,
- LW_FM_MM<0x2e>;
def LWXC1_MM : MMRel, LWXC1_FT<"lwxc1", FGR32Opnd, II_LWXC1, load>,
LWXC1_FM_MM<0x48>, INSN_MIPS4_32R2_NOT_32R6_64R6;
def SWXC1_MM : MMRel, SWXC1_FT<"swxc1", FGR32Opnd, II_SWXC1, store>,
@@ -114,10 +108,6 @@ def MFC1_MM : MMRel, MFC1_FT<"mfc1", GPR32Opnd, FGR32Opnd,
II_MFC1, bitconvert>, MFC1_FM_MM<0x80>;
def MTC1_MM : MMRel, MTC1_FT<"mtc1", FGR32Opnd, GPR32Opnd,
II_MTC1, bitconvert>, MFC1_FM_MM<0xa0>;
-def MFHC1_MM : MMRel, MFC1_FT<"mfhc1", GPR32Opnd, AFGR64Opnd, II_MFHC1>,
- MFC1_FM_MM<0xc0>, ISA_MIPS32R2, FGR_32;
-def MTHC1_MM : MMRel, MTC1_64_FT<"mthc1", AFGR64Opnd, GPR32Opnd, II_MTHC1>,
- MFC1_FM_MM<0xe0>, ISA_MIPS32R2, FGR_32;
def MADD_S_MM : MMRel, MADDS_FT<"madd.s", FGR32Opnd, II_MADD_S, fadd>,
MADDS_FM_MM<0x1>;
@@ -147,4 +137,33 @@ let AdditionalPredicates = [InMicroMips] in {
ROUND_W_FM_MM<0, 0x6c>;
def FSQRT_S_MM : MMRel, ABSS_FT<"sqrt.s", FGR32Opnd, FGR32Opnd, II_SQRT_S,
fsqrt>, ROUND_W_FM_MM<0, 0x28>;
+ def MTHC1_MM : MMRel, MTC1_64_FT<"mthc1", AFGR64Opnd, GPR32Opnd, II_MTHC1>,
+ MFC1_FM_MM<0xe0>, ISA_MIPS32R2, FGR_32;
+ def MFHC1_MM : MMRel, MFC1_FT<"mfhc1", GPR32Opnd, AFGR64Opnd, II_MFHC1>,
+ MFC1_FM_MM<0xc0>, ISA_MIPS32R2, FGR_32;
+ let DecoderNamespace = "MicroMips", DecoderMethod = "DecodeFMemMMR2" in {
+ def LDC1_MM : MMRel, LW_FT<"ldc1", AFGR64Opnd, mem_mm_16, II_LDC1, load>,
+ LW_FM_MM<0x2f>, FGR_32 {
+ let BaseOpcode = "LDC132";
+ }
+ def SDC1_MM : MMRel, SW_FT<"sdc1", AFGR64Opnd, mem_mm_16, II_SDC1, store>,
+ LW_FM_MM<0x2e>, FGR_32;
+ def LWC1_MM : MMRel, LW_FT<"lwc1", FGR32Opnd, mem_mm_16, II_LWC1, load>,
+ LW_FM_MM<0x27>;
+ def SWC1_MM : MMRel, SW_FT<"swc1", FGR32Opnd, mem_mm_16, II_SWC1, store>,
+ LW_FM_MM<0x26>;
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Floating Point Patterns
+//===----------------------------------------------------------------------===//
+let AdditionalPredicates = [InMicroMips] in {
+ // Patterns for loads/stores with a reg+imm operand.
+ let AddedComplexity = 40 in {
+ def : LoadRegImmPat<LDC1_MM, f64, load>, FGR_32;
+ def : StoreRegImmPat<SDC1_MM, f64>, FGR_32;
+ def : LoadRegImmPat<LWC1_MM, f32, load>;
+ def : StoreRegImmPat<SWC1_MM, f32>;
+ }
}
diff --git a/lib/Target/Mips/MicroMipsInstrFormats.td b/lib/Target/Mips/MicroMipsInstrFormats.td
index b736367ee5fa5..79ef6482180db 100644
--- a/lib/Target/Mips/MicroMipsInstrFormats.td
+++ b/lib/Target/Mips/MicroMipsInstrFormats.td
@@ -278,7 +278,6 @@ class MOVEP_FM_MM16 {
class MMArch {
string Arch = "micromips";
- list<dag> Pattern = [];
}
class ADD_FM_MM<bits<6> op, bits<10> funct> : MMArch {
@@ -380,13 +379,15 @@ class SRLV_FM_MM<bits<10> funct, bit rotate> : MMArch {
class LW_FM_MM<bits<6> op> : MMArch {
bits<5> rt;
bits<21> addr;
+ bits<5> base = addr{20-16};
+ bits<16> offset = addr{15-0};
bits<32> Inst;
let Inst{31-26} = op;
let Inst{25-21} = rt;
- let Inst{20-16} = addr{20-16};
- let Inst{15-0} = addr{15-0};
+ let Inst{20-16} = base;
+ let Inst{15-0} = offset;
}
class POOL32C_LHUE_FM_MM<bits<6> op, bits<4> fmt, bits<3> funct> : MMArch {
@@ -674,7 +675,7 @@ class TEQI_FM_MM<bits<5> funct> : MMArch {
let Inst{15-0} = imm16;
}
-class LL_FM_MM<bits<4> funct> {
+class LL_FM_MM<bits<4> funct> : MMArch {
bits<5> rt;
bits<21> addr;
diff --git a/lib/Target/Mips/MicroMipsInstrInfo.td b/lib/Target/Mips/MicroMipsInstrInfo.td
index 99f0f446deabe..f27370f57fa00 100644
--- a/lib/Target/Mips/MicroMipsInstrInfo.td
+++ b/lib/Target/Mips/MicroMipsInstrInfo.td
@@ -1,23 +1,8 @@
-def addrimm12 : ComplexPattern<iPTR, 2, "selectIntAddrMM", [frameindex]>;
+def addrimm11 : ComplexPattern<iPTR, 2, "selectIntAddr11MM", [frameindex]>;
+def addrimm12 : ComplexPattern<iPTR, 2, "selectIntAddr12MM", [frameindex]>;
+def addrimm16 : ComplexPattern<iPTR, 2, "selectIntAddr16MM", [frameindex]>;
def addrimm4lsl2 : ComplexPattern<iPTR, 2, "selectIntAddrLSL2MM", [frameindex]>;
-def simm4 : Operand<i32> {
- let DecoderMethod = "DecodeSimm4";
-}
-def simm7 : Operand<i32>;
-def li_simm7 : Operand<i32> {
- let DecoderMethod = "DecodeLiSimm7";
-}
-
-def simm12 : Operand<i32> {
- let DecoderMethod = "DecodeSimm12";
-}
-
-def uimm6_lsl2 : Operand<i32> {
- let EncoderMethod = "getUImm6Lsl2Encoding";
- let DecoderMethod = "DecodeUImm6Lsl2";
-}
-
def simm9_addiusp : Operand<i32> {
let EncoderMethod = "getSImm9AddiuspValue";
let DecoderMethod = "DecodeSimm9SP";
@@ -60,9 +45,15 @@ def MicroMipsMemGPRMM16AsmOperand : AsmOperandClass {
let PredicateMethod = "isMemWithGRPMM16Base";
}
+// Define the classes of pointers used by microMIPS.
+// The numbers must match those in MipsRegisterInfo::MipsPtrClass.
+def ptr_gpr16mm_rc : PointerLikeRegClass<1>;
+def ptr_sp_rc : PointerLikeRegClass<2>;
+def ptr_gp_rc : PointerLikeRegClass<3>;
+
class mem_mm_4_generic : Operand<i32> {
let PrintMethod = "printMemOperand";
- let MIOperandInfo = (ops GPRMM16, simm4);
+ let MIOperandInfo = (ops ptr_gpr16mm_rc, simm4);
let OperandType = "OPERAND_MEMORY";
let ParserMatchClass = MicroMipsMemGPRMM16AsmOperand;
}
@@ -86,32 +77,48 @@ def MicroMipsMemSPAsmOperand : AsmOperandClass {
let PredicateMethod = "isMemWithUimmWordAlignedOffsetSP<7>";
}
+def MicroMipsMemGPAsmOperand : AsmOperandClass {
+ let Name = "MicroMipsMemGP";
+ let RenderMethod = "addMemOperands";
+ let ParserMethod = "parseMemOperand";
+ let PredicateMethod = "isMemWithSimmWordAlignedOffsetGP<9>";
+}
+
def mem_mm_sp_imm5_lsl2 : Operand<i32> {
let PrintMethod = "printMemOperand";
- let MIOperandInfo = (ops GPR32:$base, simm5:$offset);
+ let MIOperandInfo = (ops ptr_sp_rc:$base, simm5:$offset);
let OperandType = "OPERAND_MEMORY";
let ParserMatchClass = MicroMipsMemSPAsmOperand;
let EncoderMethod = "getMemEncodingMMSPImm5Lsl2";
}
-def mem_mm_gp_imm7_lsl2 : Operand<i32> {
+def mem_mm_gp_simm7_lsl2 : Operand<i32> {
let PrintMethod = "printMemOperand";
- let MIOperandInfo = (ops GPRMM16:$base, simm7:$offset);
+ let MIOperandInfo = (ops ptr_gp_rc:$base, simm7_lsl2:$offset);
let OperandType = "OPERAND_MEMORY";
+ let ParserMatchClass = MicroMipsMemGPAsmOperand;
let EncoderMethod = "getMemEncodingMMGPImm7Lsl2";
}
def mem_mm_9 : Operand<i32> {
let PrintMethod = "printMemOperand";
- let MIOperandInfo = (ops GPR32, simm9);
+ let MIOperandInfo = (ops ptr_rc, simm9);
let EncoderMethod = "getMemEncodingMMImm9";
- let ParserMatchClass = MipsMemAsmOperand;
+ let ParserMatchClass = MipsMemSimm9AsmOperand;
+ let OperandType = "OPERAND_MEMORY";
+}
+
+def mem_mm_11 : Operand<i32> {
+ let PrintMethod = "printMemOperand";
+ let MIOperandInfo = (ops GPR32, simm11);
+ let EncoderMethod = "getMemEncodingMMImm11";
+ let ParserMatchClass = MipsMemSimm11AsmOperand;
let OperandType = "OPERAND_MEMORY";
}
def mem_mm_12 : Operand<i32> {
let PrintMethod = "printMemOperand";
- let MIOperandInfo = (ops GPR32, simm12);
+ let MIOperandInfo = (ops ptr_rc, simm12);
let EncoderMethod = "getMemEncodingMMImm12";
let ParserMatchClass = MipsMemAsmOperand;
let OperandType = "OPERAND_MEMORY";
@@ -119,9 +126,9 @@ def mem_mm_12 : Operand<i32> {
def mem_mm_16 : Operand<i32> {
let PrintMethod = "printMemOperand";
- let MIOperandInfo = (ops GPR32, simm16);
+ let MIOperandInfo = (ops ptr_rc, simm16);
let EncoderMethod = "getMemEncodingMMImm16";
- let ParserMatchClass = MipsMemAsmOperand;
+ let ParserMatchClass = MipsMemSimm16AsmOperand;
let OperandType = "OPERAND_MEMORY";
}
@@ -135,7 +142,7 @@ def MipsMemUimm4AsmOperand : AsmOperandClass {
def mem_mm_4sp : Operand<i32> {
let PrintMethod = "printMemOperand";
- let MIOperandInfo = (ops GPR32, uimm8);
+ let MIOperandInfo = (ops ptr_sp_rc, uimm8);
let EncoderMethod = "getMemEncodingMMImm4sp";
let ParserMatchClass = MipsMemUimm4AsmOperand;
let OperandType = "OPERAND_MEMORY";
@@ -216,7 +223,7 @@ def movep_regpair : Operand<i32> {
let ParserMatchClass = MovePRegPairAsmOperand;
let PrintMethod = "printRegisterList";
let DecoderMethod = "DecodeMovePRegPair";
- let MIOperandInfo = (ops GPR32Opnd, GPR32Opnd);
+ let MIOperandInfo = (ops ptr_rc, ptr_rc);
}
class MovePMM16<string opstr, RegisterOperand RO> :
@@ -230,6 +237,7 @@ MicroMipsInst16<(outs movep_regpair:$dst_regs), (ins RO:$rs, RO:$rt),
def RegPairAsmOperand : AsmOperandClass {
let Name = "RegPair";
let ParserMethod = "parseRegisterPair";
+ let PredicateMethod = "isRegPair";
}
def regpair : Operand<i32> {
@@ -237,12 +245,12 @@ def regpair : Operand<i32> {
let ParserMatchClass = RegPairAsmOperand;
let PrintMethod = "printRegisterPair";
let DecoderMethod = "DecodeRegPairOperand";
- let MIOperandInfo = (ops GPR32Opnd, GPR32Opnd);
+ let MIOperandInfo = (ops ptr_rc, ptr_rc);
}
class StorePairMM<string opstr, InstrItinClass Itin = NoItinerary,
ComplexPattern Addr = addr> :
- InstSE<(outs), (ins regpair:$rt, mem_mm_12:$addr),
+ InstSE<(outs), (ins regpair:$rt, mem_simm12:$addr),
!strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI, opstr> {
let DecoderMethod = "DecodeMemMMImm12";
let mayStore = 1;
@@ -250,7 +258,7 @@ class StorePairMM<string opstr, InstrItinClass Itin = NoItinerary,
class LoadPairMM<string opstr, InstrItinClass Itin = NoItinerary,
ComplexPattern Addr = addr> :
- InstSE<(outs regpair:$rt), (ins mem_mm_12:$addr),
+ InstSE<(outs regpair:$rt), (ins mem_simm12:$addr),
!strconcat(opstr, "\t$rt, $addr"), [], Itin, FrmI, opstr> {
let DecoderMethod = "DecodeMemMMImm12";
let mayLoad = 1;
@@ -264,7 +272,7 @@ class LLBaseMM<string opstr, RegisterOperand RO> :
}
class LLEBaseMM<string opstr, RegisterOperand RO> :
- InstSE<(outs RO:$rt), (ins mem_mm_12:$addr),
+ InstSE<(outs RO:$rt), (ins mem_simm9:$addr),
!strconcat(opstr, "\t$rt, $addr"), [], NoItinerary, FrmI> {
let DecoderMethod = "DecodeMemMMImm9";
let mayLoad = 1;
@@ -279,7 +287,7 @@ class SCBaseMM<string opstr, RegisterOperand RO> :
}
class SCEBaseMM<string opstr, RegisterOperand RO> :
- InstSE<(outs RO:$dst), (ins RO:$rt, mem_mm_12:$addr),
+ InstSE<(outs RO:$dst), (ins RO:$rt, mem_simm9:$addr),
!strconcat(opstr, "\t$rt, $addr"), [], NoItinerary, FrmI> {
let DecoderMethod = "DecodeMemMMImm9";
let mayStore = 1;
@@ -287,10 +295,10 @@ class SCEBaseMM<string opstr, RegisterOperand RO> :
}
class LoadMM<string opstr, DAGOperand RO, SDPatternOperator OpNode = null_frag,
- InstrItinClass Itin = NoItinerary> :
- InstSE<(outs RO:$rt), (ins mem_mm_12:$addr),
+ InstrItinClass Itin = NoItinerary, DAGOperand MO = mem_mm_12> :
+ InstSE<(outs RO:$rt), (ins MO:$addr),
!strconcat(opstr, "\t$rt, $addr"),
- [(set RO:$rt, (OpNode addrimm12:$addr))], Itin, FrmI> {
+ [(set RO:$rt, (OpNode addrimm12:$addr))], Itin, FrmI, opstr> {
let DecoderMethod = "DecodeMemMMImm12";
let canFoldAsLoad = 1;
let mayLoad = 1;
@@ -615,7 +623,7 @@ def SH16_MM : StoreMM16<"sh16", GPRMM16OpndZero, GPRMM16Opnd, truncstorei16,
LOAD_STORE_FM_MM16<0x2a>;
def SW16_MM : StoreMM16<"sw16", GPRMM16OpndZero, GPRMM16Opnd, store, II_SW,
mem_mm_4_lsl2>, LOAD_STORE_FM_MM16<0x3a>;
-def LWGP_MM : LoadGPMM16<"lw", GPRMM16Opnd, II_LW, mem_mm_gp_imm7_lsl2>,
+def LWGP_MM : LoadGPMM16<"lw", GPRMM16Opnd, II_LW, mem_mm_gp_simm7_lsl2>,
LOAD_GP_FM_MM16<0x19>;
def LWSP_MM : LoadSPMM16<"lw", GPR32Opnd, II_LW, mem_mm_sp_imm5_lsl2>,
LOAD_STORE_SP_FM_MM16<0x12>;
@@ -629,7 +637,7 @@ def MFHI16_MM : MoveFromHILOMM<"mfhi", GPR32Opnd, AC0>, MFHILO_FM_MM16<0x10>;
def MFLO16_MM : MoveFromHILOMM<"mflo", GPR32Opnd, AC0>, MFHILO_FM_MM16<0x12>;
def MOVE16_MM : MoveMM16<"move", GPR32Opnd>, MOVE_FM_MM16<0x03>;
def MOVEP_MM : MovePMM16<"movep", GPRMM16OpndMoveP>, MOVEP_FM_MM16;
-def LI16_MM : LoadImmMM16<"li16", li_simm7, GPRMM16Opnd>, LI_FM_MM16,
+def LI16_MM : LoadImmMM16<"li16", li16_imm, GPRMM16Opnd>, LI_FM_MM16,
IsAsCheapAsAMove;
def JALR16_MM : JumpLinkRegMM16<"jalr", GPR32Opnd>, JALR_FM_MM16<0x0e>,
ISA_MICROMIPS32_NOT_MIPS32R6;
@@ -677,11 +685,11 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in {
SLTI_FM_MM<0x2c>;
def ANDi_MM : MMRel, ArithLogicI<"andi", uimm16, GPR32Opnd>,
ADDI_FM_MM<0x34>;
- def ORi_MM : MMRel, ArithLogicI<"ori", uimm16, GPR32Opnd>,
- ADDI_FM_MM<0x14>;
- def XORi_MM : MMRel, ArithLogicI<"xori", uimm16, GPR32Opnd>,
- ADDI_FM_MM<0x1c>;
- def LUi_MM : MMRel, LoadUpper<"lui", GPR32Opnd, uimm16>, LUI_FM_MM;
+ def ORi_MM : MMRel, ArithLogicI<"ori", uimm16, GPR32Opnd, II_ORI, immZExt16,
+ or>, ADDI_FM_MM<0x14>;
+ def XORi_MM : MMRel, ArithLogicI<"xori", uimm16, GPR32Opnd, II_XORI,
+ immZExt16, xor>, ADDI_FM_MM<0x1c>;
+ def LUi_MM : MMRel, LoadUpper<"lui", GPR32Opnd, uimm16_relaxed>, LUI_FM_MM;
def LEA_ADDiu_MM : MMRel, EffectiveAddress<"addiu", GPR32Opnd>,
LW_FM_MM<0xc>;
@@ -709,9 +717,9 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in {
def MULTu_MM : MMRel, Mult<"multu", II_MULTU, GPR32Opnd, [HI0, LO0]>,
MULT_FM_MM<0x26c>;
def SDIV_MM : MMRel, Div<"div", II_DIV, GPR32Opnd, [HI0, LO0]>,
- MULT_FM_MM<0x2ac>;
+ MULT_FM_MM<0x2ac>, ISA_MIPS1_NOT_32R6_64R6;
def UDIV_MM : MMRel, Div<"divu", II_DIVU, GPR32Opnd, [HI0, LO0]>,
- MULT_FM_MM<0x2ec>;
+ MULT_FM_MM<0x2ec>, ISA_MIPS1_NOT_32R6_64R6;
/// Arithmetic Instructions with PC and Immediate
def ADDIUPC_MM : AddImmUPC<"addiupc", GPRMM16Opnd>, ADDIUPC_FM_MM;
@@ -730,16 +738,24 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in {
def SRAV_MM : MMRel, shift_rotate_reg<"srav", GPR32Opnd, II_SRAV>,
SRLV_FM_MM<0x90, 0>;
def ROTR_MM : MMRel, shift_rotate_imm<"rotr", uimm5, GPR32Opnd, II_ROTR>,
- SRA_FM_MM<0xc0, 0>;
+ SRA_FM_MM<0xc0, 0> {
+ list<dag> Pattern = [(set GPR32Opnd:$rd,
+ (rotr GPR32Opnd:$rt, immZExt5:$shamt))];
+ }
def ROTRV_MM : MMRel, shift_rotate_reg<"rotrv", GPR32Opnd, II_ROTRV>,
- SRLV_FM_MM<0xd0, 0>;
+ SRLV_FM_MM<0xd0, 0> {
+ list<dag> Pattern = [(set GPR32Opnd:$rd,
+ (rotr GPR32Opnd:$rt, GPR32Opnd:$rs))];
+ }
/// Load and Store Instructions - aligned
let DecoderMethod = "DecodeMemMMImm16" in {
- def LB_MM : Load<"lb", GPR32Opnd>, MMRel, LW_FM_MM<0x7>;
- def LBu_MM : Load<"lbu", GPR32Opnd>, MMRel, LW_FM_MM<0x5>;
- def LH_MM : Load<"lh", GPR32Opnd>, MMRel, LW_FM_MM<0xf>;
- def LHu_MM : Load<"lhu", GPR32Opnd>, MMRel, LW_FM_MM<0xd>;
+ def LB_MM : LoadMemory<"lb", GPR32Opnd, mem_mm_16>, MMRel, LW_FM_MM<0x7>;
+ def LBu_MM : LoadMemory<"lbu", GPR32Opnd, mem_mm_16>, MMRel, LW_FM_MM<0x5>;
+ def LH_MM : LoadMemory<"lh", GPR32Opnd, mem_simm16, sextloadi16, II_LH,
+ addrDefault>, MMRel, LW_FM_MM<0xf>;
+ def LHu_MM : LoadMemory<"lhu", GPR32Opnd, mem_simm16, zextloadi16, II_LHU>,
+ MMRel, LW_FM_MM<0xd>;
def LW_MM : Load<"lw", GPR32Opnd>, MMRel, LW_FM_MM<0x3f>;
def SB_MM : Store<"sb", GPR32Opnd>, MMRel, LW_FM_MM<0x6>;
def SH_MM : Store<"sh", GPR32Opnd>, MMRel, LW_FM_MM<0xe>;
@@ -749,19 +765,22 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in {
let DecoderMethod = "DecodeMemMMImm9" in {
def LBE_MM : Load<"lbe", GPR32Opnd>, POOL32C_LHUE_FM_MM<0x18, 0x6, 0x4>;
def LBuE_MM : Load<"lbue", GPR32Opnd>, POOL32C_LHUE_FM_MM<0x18, 0x6, 0x0>;
- def LHE_MM : Load<"lhe", GPR32Opnd>, POOL32C_LHUE_FM_MM<0x18, 0x6, 0x5>;
- def LHuE_MM : Load<"lhue", GPR32Opnd>, POOL32C_LHUE_FM_MM<0x18, 0x6, 0x1>;
- def LWE_MM : Load<"lwe", GPR32Opnd>, POOL32C_LHUE_FM_MM<0x18, 0x6, 0x7>;
- def SBE_MM : Store<"sbe", GPR32Opnd>, POOL32C_LHUE_FM_MM<0x18, 0xa, 0x4>;
- def SHE_MM : Store<"she", GPR32Opnd>, POOL32C_LHUE_FM_MM<0x18, 0xa, 0x5>;
- def SWE_MM : StoreMemory<"swe", GPR32Opnd, mem_simm9gpr>,
+ def LHE_MM : LoadMemory<"lhe", GPR32Opnd, mem_simm9>,
+ POOL32C_LHUE_FM_MM<0x18, 0x6, 0x5>;
+ def LHuE_MM : LoadMemory<"lhue", GPR32Opnd, mem_simm9>,
+ POOL32C_LHUE_FM_MM<0x18, 0x6, 0x1>;
+ def LWE_MM : LoadMemory<"lwe", GPR32Opnd, mem_simm9>,
+ POOL32C_LHUE_FM_MM<0x18, 0x6, 0x7>;
+ def SBE_MM : StoreMemory<"sbe", GPR32Opnd, mem_simm9>,
+ POOL32C_LHUE_FM_MM<0x18, 0xa, 0x4>;
+ def SHE_MM : StoreMemory<"she", GPR32Opnd, mem_simm9>,
+ POOL32C_LHUE_FM_MM<0x18, 0xa, 0x5>;
+ def SWE_MM : StoreMemory<"swe", GPR32Opnd, mem_simm9>,
POOL32C_LHUE_FM_MM<0x18, 0xa, 0x7>;
}
def LWXS_MM : LoadWordIndexedScaledMM<"lwxs", GPR32Opnd>, LWXS_FM_MM<0x118>;
- def LWU_MM : LoadMM<"lwu", GPR32Opnd, zextloadi32, II_LWU>, LL_FM_MM<0xe>;
-
/// Load and Store Instructions - unaligned
def LWL_MM : LoadLeftRightMM<"lwl", MipsLWL, GPR32Opnd, mem_mm_12>,
LWL_FM_MM<0x0>;
@@ -772,13 +791,13 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in {
def SWR_MM : StoreLeftRightMM<"swr", MipsSWR, GPR32Opnd, mem_mm_12>,
LWL_FM_MM<0x9>;
let DecoderMethod = "DecodeMemMMImm9" in {
- def LWLE_MM : LoadLeftRightMM<"lwle", MipsLWL, GPR32Opnd, mem_mm_12>,
+ def LWLE_MM : LoadLeftRightMM<"lwle", MipsLWL, GPR32Opnd, mem_mm_9>,
POOL32C_STEVA_LDEVA_FM_MM<0x6, 0x2>;
- def LWRE_MM : LoadLeftRightMM<"lwre", MipsLWR, GPR32Opnd, mem_mm_12>,
+ def LWRE_MM : LoadLeftRightMM<"lwre", MipsLWR, GPR32Opnd, mem_mm_9>,
POOL32C_STEVA_LDEVA_FM_MM<0x6, 0x3>;
- def SWLE_MM : StoreLeftRightMM<"swle", MipsSWL, GPR32Opnd, mem_mm_12>,
+ def SWLE_MM : StoreLeftRightMM<"swle", MipsSWL, GPR32Opnd, mem_mm_9>,
POOL32C_STEVA_LDEVA_FM_MM<0xa, 0x0>;
- def SWRE_MM : StoreLeftRightMM<"swre", MipsSWR, GPR32Opnd, mem_mm_12>,
+ def SWRE_MM : StoreLeftRightMM<"swre", MipsSWR, GPR32Opnd, mem_mm_9>,
POOL32C_STEVA_LDEVA_FM_MM<0xa, 0x1>, ISA_MIPS1_NOT_32R6_64R6;
}
@@ -845,10 +864,10 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in {
def WSBH_MM : MMRel, SubwordSwap<"wsbh", GPR32Opnd, II_WSBH>,
SEB_FM_MM<0x1ec>, ISA_MIPS32R2;
// TODO: Add '0 < pos+size <= 32' constraint check to ext instruction
- def EXT_MM : MMRel, ExtBase<"ext", GPR32Opnd, uimm5, uimm5_plus1,
- MipsExt>, EXT_FM_MM<0x2c>;
- def INS_MM : MMRel, InsBase<"ins", GPR32Opnd, uimm5, MipsIns>,
- EXT_FM_MM<0x0c>;
+ def EXT_MM : MMRel, ExtBase<"ext", GPR32Opnd, uimm5, uimm5_plus1, immZExt5,
+ immZExt5Plus1, MipsExt>, EXT_FM_MM<0x2c>;
+ def INS_MM : MMRel, InsBase<"ins", GPR32Opnd, uimm5, uimm5_inssize_plus1,
+ MipsIns>, EXT_FM_MM<0x0c>;
/// Jump Instructions
let DecoderMethod = "DecodeJumpTargetMM" in {
@@ -857,7 +876,8 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in {
def JAL_MM : MMRel, JumpLink<"jal", calltarget_mm>, J_FM_MM<0x3d>;
def JALX_MM : MMRel, JumpLink<"jalx", calltarget>, J_FM_MM<0x3c>;
}
- def JR_MM : MMRel, IndirectBranch<"jr", GPR32Opnd>, JR_FM_MM<0x3c>;
+ def JR_MM : MMRel, IndirectBranch<"jr", GPR32Opnd>, JR_FM_MM<0x3c>,
+ ISA_MICROMIPS32_NOT_MIPS32R6;
def JALR_MM : JumpLinkReg<"jalr", GPR32Opnd>, JALR_FM_MM<0x03c>;
/// Jump Instructions - Short Delay Slot
@@ -891,7 +911,7 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in {
/// Control Instructions
def SYNC_MM : MMRel, SYNC_FT<"sync">, SYNC_FM_MM;
def BREAK_MM : MMRel, BRK_FT<"break">, BRK_FM_MM;
- def SYSCALL_MM : MMRel, SYS_FT<"syscall">, SYS_FM_MM;
+ def SYSCALL_MM : MMRel, SYS_FT<"syscall", uimm10>, SYS_FM_MM;
def WAIT_MM : WaitMM<"wait">, WAIT_FM_MM;
def ERET_MM : MMRel, ER_FT<"eret">, ER_FM_MM<0x3cd>;
def DERET_MM : MMRel, ER_FT<"deret">, ER_FM_MM<0x38d>;
@@ -901,12 +921,12 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in {
ISA_MIPS32R2;
/// Trap Instructions
- def TEQ_MM : MMRel, TEQ_FT<"teq", GPR32Opnd>, TEQ_FM_MM<0x0>;
- def TGE_MM : MMRel, TEQ_FT<"tge", GPR32Opnd>, TEQ_FM_MM<0x08>;
- def TGEU_MM : MMRel, TEQ_FT<"tgeu", GPR32Opnd>, TEQ_FM_MM<0x10>;
- def TLT_MM : MMRel, TEQ_FT<"tlt", GPR32Opnd>, TEQ_FM_MM<0x20>;
- def TLTU_MM : MMRel, TEQ_FT<"tltu", GPR32Opnd>, TEQ_FM_MM<0x28>;
- def TNE_MM : MMRel, TEQ_FT<"tne", GPR32Opnd>, TEQ_FM_MM<0x30>;
+ def TEQ_MM : MMRel, TEQ_FT<"teq", GPR32Opnd, uimm4>, TEQ_FM_MM<0x0>;
+ def TGE_MM : MMRel, TEQ_FT<"tge", GPR32Opnd, uimm4>, TEQ_FM_MM<0x08>;
+ def TGEU_MM : MMRel, TEQ_FT<"tgeu", GPR32Opnd, uimm4>, TEQ_FM_MM<0x10>;
+ def TLT_MM : MMRel, TEQ_FT<"tlt", GPR32Opnd, uimm4>, TEQ_FM_MM<0x20>;
+ def TLTU_MM : MMRel, TEQ_FT<"tltu", GPR32Opnd, uimm4>, TEQ_FM_MM<0x28>;
+ def TNE_MM : MMRel, TEQ_FT<"tne", GPR32Opnd, uimm4>, TEQ_FM_MM<0x30>;
def TEQI_MM : MMRel, TEQI_FT<"teqi", GPR32Opnd>, TEQI_FM_MM<0x0e>;
def TGEI_MM : MMRel, TEQI_FT<"tgei", GPR32Opnd>, TEQI_FM_MM<0x09>;
@@ -931,9 +951,9 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in {
let DecoderMethod = "DecodePrefeOpMM" in {
def PREFE_MM : MMRel, CacheOp<"prefe", mem_mm_9>,
- CACHE_PREFE_FM_MM<0x18, 0x2>;
+ CACHE_PREFE_FM_MM<0x18, 0x2>;
def CACHEE_MM : MMRel, CacheOp<"cachee", mem_mm_9>,
- CACHE_PREFE_FM_MM<0x18, 0x3>;
+ CACHE_PREFE_FM_MM<0x18, 0x3>;
}
def SSNOP_MM : MMRel, Barrier<"ssnop">, BARRIER_FM_MM<0x1>;
def EHB_MM : MMRel, Barrier<"ehb">, BARRIER_FM_MM<0x3>;
@@ -944,7 +964,7 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in {
def TLBWI_MM : MMRel, TLB<"tlbwi">, COP0_TLB_FM_MM<0x8d>;
def TLBWR_MM : MMRel, TLB<"tlbwr">, COP0_TLB_FM_MM<0xcd>;
- def SDBBP_MM : MMRel, SYS_FT<"sdbbp">, SDBBP_FM_MM;
+ def SDBBP_MM : MMRel, SYS_FT<"sdbbp", uimm10>, SDBBP_FM_MM;
def PREFX_MM : PrefetchIndexed<"prefx">, POOL32F_PREFX_FM_MM<0x15, 0x1A0>;
}
@@ -952,54 +972,80 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in {
let DecoderNamespace = "MicroMips" in {
def RDHWR_MM : MMRel, R6MMR6Rel, ReadHardware<GPR32Opnd, HWRegsOpnd>,
RDHWR_FM_MM, ISA_MICROMIPS32_NOT_MIPS32R6;
+ def LWU_MM : MMRel, LoadMM<"lwu", GPR32Opnd, zextloadi32, II_LWU,
+ mem_simm12>, LL_FM_MM<0xe>,
+ ISA_MICROMIPS32_NOT_MIPS32R6;
}
-let Predicates = [InMicroMips] in {
-
//===----------------------------------------------------------------------===//
// MicroMips arbitrary patterns that map to one or more instructions
//===----------------------------------------------------------------------===//
-def : MipsPat<(i32 immLi16:$imm),
- (LI16_MM immLi16:$imm)>;
-def : MipsPat<(i32 immSExt16:$imm),
- (ADDiu_MM ZERO, immSExt16:$imm)>;
-def : MipsPat<(i32 immZExt16:$imm),
- (ORi_MM ZERO, immZExt16:$imm)>;
-def : MipsPat<(not GPR32:$in),
- (NOR_MM GPR32Opnd:$in, ZERO)>;
-
-def : MipsPat<(add GPRMM16:$src, immSExtAddiur2:$imm),
- (ADDIUR2_MM GPRMM16:$src, immSExtAddiur2:$imm)>;
-def : MipsPat<(add GPR32:$src, immSExtAddius5:$imm),
- (ADDIUS5_MM GPR32:$src, immSExtAddius5:$imm)>;
-def : MipsPat<(add GPR32:$src, immSExt16:$imm),
- (ADDiu_MM GPR32:$src, immSExt16:$imm)>;
-
-def : MipsPat<(and GPRMM16:$src, immZExtAndi16:$imm),
- (ANDI16_MM GPRMM16:$src, immZExtAndi16:$imm)>;
-def : MipsPat<(and GPR32:$src, immZExt16:$imm),
- (ANDi_MM GPR32:$src, immZExt16:$imm)>;
-
-def : MipsPat<(shl GPRMM16:$src, immZExt2Shift:$imm),
- (SLL16_MM GPRMM16:$src, immZExt2Shift:$imm)>;
-def : MipsPat<(shl GPR32:$src, immZExt5:$imm),
- (SLL_MM GPR32:$src, immZExt5:$imm)>;
-
-def : MipsPat<(srl GPRMM16:$src, immZExt2Shift:$imm),
- (SRL16_MM GPRMM16:$src, immZExt2Shift:$imm)>;
-def : MipsPat<(srl GPR32:$src, immZExt5:$imm),
- (SRL_MM GPR32:$src, immZExt5:$imm)>;
-
-def : MipsPat<(store GPRMM16:$src, addrimm4lsl2:$addr),
- (SW16_MM GPRMM16:$src, addrimm4lsl2:$addr)>;
-def : MipsPat<(store GPR32:$src, addr:$addr),
- (SW_MM GPR32:$src, addr:$addr)>;
-
-def : MipsPat<(load addrimm4lsl2:$addr),
- (LW16_MM addrimm4lsl2:$addr)>;
-def : MipsPat<(load addr:$addr),
- (LW_MM addr:$addr)>;
+let Predicates = [InMicroMips] in {
+ def : MipsPat<(i32 immLi16:$imm),
+ (LI16_MM immLi16:$imm)>;
+ def : MipsPat<(i32 immSExt16:$imm),
+ (ADDiu_MM ZERO, immSExt16:$imm)>;
+ def : MipsPat<(i32 immZExt16:$imm),
+ (ORi_MM ZERO, immZExt16:$imm)>;
+
+ def : MipsPat<(not GPRMM16:$in),
+ (NOT16_MM GPRMM16:$in)>;
+ def : MipsPat<(not GPR32:$in),
+ (NOR_MM GPR32Opnd:$in, ZERO)>;
+
+ def : MipsPat<(add GPRMM16:$src, immSExtAddiur2:$imm),
+ (ADDIUR2_MM GPRMM16:$src, immSExtAddiur2:$imm)>;
+ def : MipsPat<(add GPR32:$src, immSExtAddius5:$imm),
+ (ADDIUS5_MM GPR32:$src, immSExtAddius5:$imm)>;
+ def : MipsPat<(add GPR32:$src, immSExt16:$imm),
+ (ADDiu_MM GPR32:$src, immSExt16:$imm)>;
+
+ def : MipsPat<(and GPRMM16:$src, immZExtAndi16:$imm),
+ (ANDI16_MM GPRMM16:$src, immZExtAndi16:$imm)>;
+ def : MipsPat<(and GPR32:$src, immZExt16:$imm),
+ (ANDi_MM GPR32:$src, immZExt16:$imm)>;
+
+ def : MipsPat<(shl GPRMM16:$src, immZExt2Shift:$imm),
+ (SLL16_MM GPRMM16:$src, immZExt2Shift:$imm)>;
+ def : MipsPat<(shl GPR32:$src, immZExt5:$imm),
+ (SLL_MM GPR32:$src, immZExt5:$imm)>;
+ def : MipsPat<(shl GPR32:$lhs, GPR32:$rhs),
+ (SLLV_MM GPR32:$lhs, GPR32:$rhs)>;
+
+ def : MipsPat<(srl GPRMM16:$src, immZExt2Shift:$imm),
+ (SRL16_MM GPRMM16:$src, immZExt2Shift:$imm)>;
+ def : MipsPat<(srl GPR32:$src, immZExt5:$imm),
+ (SRL_MM GPR32:$src, immZExt5:$imm)>;
+ def : MipsPat<(srl GPR32:$lhs, GPR32:$rhs),
+ (SRLV_MM GPR32:$lhs, GPR32:$rhs)>;
+
+ def : MipsPat<(sra GPR32:$src, immZExt5:$imm),
+ (SRA_MM GPR32:$src, immZExt5:$imm)>;
+ def : MipsPat<(sra GPR32:$lhs, GPR32:$rhs),
+ (SRAV_MM GPR32:$lhs, GPR32:$rhs)>;
+
+ def : MipsPat<(store GPRMM16:$src, addrimm4lsl2:$addr),
+ (SW16_MM GPRMM16:$src, addrimm4lsl2:$addr)>;
+ def : MipsPat<(store GPR32:$src, addr:$addr),
+ (SW_MM GPR32:$src, addr:$addr)>;
+
+ def : MipsPat<(load addrimm4lsl2:$addr),
+ (LW16_MM addrimm4lsl2:$addr)>;
+ def : MipsPat<(load addr:$addr),
+ (LW_MM addr:$addr)>;
+ def : MipsPat<(subc GPR32:$lhs, GPR32:$rhs),
+ (SUBu_MM GPR32:$lhs, GPR32:$rhs)>;
+}
+
+let AddedComplexity = 40 in {
+ def : MipsPat<(i32 (sextloadi16 addrRegImm:$a)),
+ (LH_MM addrRegImm:$a)>;
+}
+def : MipsPat<(atomic_load_16 addr:$a),
+ (LH_MM addr:$a)>;
+def : MipsPat<(i32 (extloadi16 addr:$src)),
+ (LHu_MM addr:$src)>;
//===----------------------------------------------------------------------===//
// MicroMips instruction aliases
@@ -1011,24 +1057,62 @@ class UncondBranchMMPseudo<string opstr> :
def B_MM_Pseudo : UncondBranchMMPseudo<"b">, ISA_MICROMIPS;
+let Predicates = [InMicroMips] in {
+ def SDIV_MM_Pseudo : MultDivPseudo<SDIV_MM, ACC64, GPR32Opnd, MipsDivRem,
+ II_DIV, 0, 1, 1>, ISA_MIPS1_NOT_32R6_64R6;
+ def UDIV_MM_Pseudo : MultDivPseudo<UDIV_MM, ACC64, GPR32Opnd, MipsDivRemU,
+ II_DIVU, 0, 1, 1>, ISA_MIPS1_NOT_32R6_64R6;
+
def : MipsInstAlias<"wait", (WAIT_MM 0x0), 1>;
def : MipsInstAlias<"nop", (SLL_MM ZERO, ZERO, 0), 1>;
def : MipsInstAlias<"nop", (MOVE16_MM ZERO, ZERO), 1>;
-}
-
-let Predicates = [InMicroMips] in {
-def : MipsInstAlias<"ei", (EI_MM ZERO), 1>, ISA_MIPS32R2;
-def : MipsInstAlias<"di", (DI_MM ZERO), 1>, ISA_MIPS32R2;
-def : MipsInstAlias<"teq $rs, $rt",
- (TEQ_MM GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>;
-def : MipsInstAlias<"tge $rs, $rt",
- (TGE_MM GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>;
-def : MipsInstAlias<"tgeu $rs, $rt",
- (TGEU_MM GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>;
-def : MipsInstAlias<"tlt $rs, $rt",
- (TLT_MM GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>;
-def : MipsInstAlias<"tltu $rs, $rt",
- (TLTU_MM GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>;
-def : MipsInstAlias<"tne $rs, $rt",
- (TNE_MM GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>;
+ def : MipsInstAlias<"ei", (EI_MM ZERO), 1>, ISA_MIPS32R2;
+ def : MipsInstAlias<"di", (DI_MM ZERO), 1>, ISA_MIPS32R2;
+ def : MipsInstAlias<"teq $rs, $rt",
+ (TEQ_MM GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>;
+ def : MipsInstAlias<"tge $rs, $rt",
+ (TGE_MM GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>;
+ def : MipsInstAlias<"tgeu $rs, $rt",
+ (TGEU_MM GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>;
+ def : MipsInstAlias<"tlt $rs, $rt",
+ (TLT_MM GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>;
+ def : MipsInstAlias<"tltu $rs, $rt",
+ (TLTU_MM GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>;
+ def : MipsInstAlias<"tne $rs, $rt",
+ (TNE_MM GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>;
+ def : MipsInstAlias<"sll $rd, $rt, $rs",
+ (SLLV_MM GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>;
+ def : MipsInstAlias<"sra $rd, $rt, $rs",
+ (SRAV_MM GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>;
+ def : MipsInstAlias<"srl $rd, $rt, $rs",
+ (SRLV_MM GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>;
+ def : MipsInstAlias<"sll $rd, $rt",
+ (SLLV_MM GPR32Opnd:$rd, GPR32Opnd:$rd, GPR32Opnd:$rt), 0>;
+ def : MipsInstAlias<"sra $rd, $rt",
+ (SRAV_MM GPR32Opnd:$rd, GPR32Opnd:$rd, GPR32Opnd:$rt), 0>;
+ def : MipsInstAlias<"srl $rd, $rt",
+ (SRLV_MM GPR32Opnd:$rd, GPR32Opnd:$rd, GPR32Opnd:$rt), 0>;
+ def : MipsInstAlias<"sll $rd, $shamt",
+ (SLL_MM GPR32Opnd:$rd, GPR32Opnd:$rd, uimm5:$shamt), 0>;
+ def : MipsInstAlias<"sra $rd, $shamt",
+ (SRA_MM GPR32Opnd:$rd, GPR32Opnd:$rd, uimm5:$shamt), 0>;
+ def : MipsInstAlias<"srl $rd, $shamt",
+ (SRL_MM GPR32Opnd:$rd, GPR32Opnd:$rd, uimm5:$shamt), 0>;
+ def : MipsInstAlias<"rotr $rt, $imm",
+ (ROTR_MM GPR32Opnd:$rt, GPR32Opnd:$rt, uimm5:$imm), 0>;
+ def : MipsInstAlias<"syscall", (SYSCALL_MM 0), 1>;
+ def : MipsInstAlias<"and $rs, $rt, $imm",
+ (ANDi_MM GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>;
+ def : MipsInstAlias<"and $rs, $imm",
+ (ANDi_MM GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm), 0>;
+ def : MipsInstAlias<"or $rs, $rt, $imm",
+ (ORi_MM GPR32Opnd:$rs, GPR32Opnd:$rt, uimm16:$imm), 0>;
+ def : MipsInstAlias<"or $rs, $imm",
+ (ORi_MM GPR32Opnd:$rs, GPR32Opnd:$rs, uimm16:$imm), 0>;
+ def : MipsInstAlias<"xor $rs, $rt, $imm",
+ (XORi_MM GPR32Opnd:$rs, GPR32Opnd:$rt, uimm16:$imm), 0>;
+ def : MipsInstAlias<"xor $rs, $imm",
+ (XORi_MM GPR32Opnd:$rs, GPR32Opnd:$rs, uimm16:$imm), 0>;
+ def : MipsInstAlias<"not $rt, $rs",
+ (NOR_MM GPR32Opnd:$rt, GPR32Opnd:$rs, ZERO), 0>;
}
diff --git a/lib/Target/Mips/Mips.h b/lib/Target/Mips/Mips.h
index 671d7a87cc3d9..d9faf3325cacd 100644
--- a/lib/Target/Mips/Mips.h
+++ b/lib/Target/Mips/Mips.h
@@ -29,8 +29,9 @@ namespace llvm {
FunctionPass *createMipsModuleISelDagPass(MipsTargetMachine &TM);
FunctionPass *createMipsOptimizePICCallPass(MipsTargetMachine &TM);
FunctionPass *createMipsDelaySlotFillerPass(MipsTargetMachine &TM);
+ FunctionPass *createMipsHazardSchedule();
FunctionPass *createMipsLongBranchPass(MipsTargetMachine &TM);
- FunctionPass *createMipsConstantIslandPass(MipsTargetMachine &tm);
+ FunctionPass *createMipsConstantIslandPass();
} // end namespace llvm;
#endif
diff --git a/lib/Target/Mips/Mips.td b/lib/Target/Mips/Mips.td
index 35352b6115c54..ea3fa0a9578e1 100644
--- a/lib/Target/Mips/Mips.td
+++ b/lib/Target/Mips/Mips.td
@@ -24,6 +24,8 @@ class PredicateControl {
list<Predicate> EncodingPredicates = [];
// Predicates for the GPR size such as IsGP64bit
list<Predicate> GPRPredicates = [];
+ // Predicates for the PTR size such as IsPTR64bit
+ list<Predicate> PTRPredicates = [];
// Predicates for the FGR size and layout such as IsFP64bit
list<Predicate> FGRPredicates = [];
// Predicates for the instruction group membership such as ISA's and ASE's
@@ -34,6 +36,7 @@ class PredicateControl {
list<Predicate> AdditionalPredicates = [];
list<Predicate> Predicates = !listconcat(EncodingPredicates,
GPRPredicates,
+ PTRPredicates,
FGRPredicates,
InsnPredicates,
HardFloatPredicate,
@@ -62,6 +65,8 @@ def MipsInstrInfo : InstrInfo;
def FeatureNoABICalls : SubtargetFeature<"noabicalls", "NoABICalls", "true",
"Disable SVR4-style position-independent code">;
+def FeaturePTR64Bit : SubtargetFeature<"ptr64", "IsPTR64bit", "true",
+ "Pointers are 64-bit wide">;
def FeatureGP64Bit : SubtargetFeature<"gp64", "IsGP64bit", "true",
"General Purpose Registers are 64-bit wide">;
def FeatureFP64Bit : SubtargetFeature<"fp64", "IsFP64bit", "true",
diff --git a/lib/Target/Mips/Mips16FrameLowering.cpp b/lib/Target/Mips/Mips16FrameLowering.cpp
index 26426c087164f..e937ffa7a7ab9 100644
--- a/lib/Target/Mips/Mips16FrameLowering.cpp
+++ b/lib/Target/Mips/Mips16FrameLowering.cpp
@@ -24,7 +24,6 @@
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetOptions.h"
using namespace llvm;
diff --git a/lib/Target/Mips/Mips16HardFloat.cpp b/lib/Target/Mips/Mips16HardFloat.cpp
index b2bc7e74c706d..d2d1c65e40d94 100644
--- a/lib/Target/Mips/Mips16HardFloat.cpp
+++ b/lib/Target/Mips/Mips16HardFloat.cpp
@@ -261,7 +261,7 @@ static std::string swapFPIntParams(FPParamVariant PV, Module *M, bool LE,
static void assureFPCallStub(Function &F, Module *M,
const MipsTargetMachine &TM) {
// for now we only need them for static relocation
- if (TM.getRelocationModel() == Reloc::PIC_)
+ if (TM.isPositionIndependent())
return;
LLVMContext &Context = M->getContext();
bool LE = TM.isLittleEndian();
@@ -387,11 +387,9 @@ static bool fixupFPReturnAndCall(Function &F, Module *M,
bool Modified = false;
LLVMContext &C = M->getContext();
Type *MyVoid = Type::getVoidTy(C);
- for (Function::iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
- for (BasicBlock::iterator I = BB->begin(), E = BB->end();
- I != E; ++I) {
- Instruction &Inst = *I;
- if (const ReturnInst *RI = dyn_cast<ReturnInst>(I)) {
+ for (auto &BB: F)
+ for (auto &I: BB) {
+ if (const ReturnInst *RI = dyn_cast<ReturnInst>(&I)) {
Value *RVal = RI->getReturnValue();
if (!RVal) continue;
//
@@ -425,17 +423,11 @@ static bool fixupFPReturnAndCall(Function &F, Module *M,
A = A.addAttribute(C, AttributeSet::FunctionIndex,
Attribute::NoInline);
Value *F = (M->getOrInsertFunction(Name, A, MyVoid, T, nullptr));
- CallInst::Create(F, Params, "", &Inst );
- } else if (const CallInst *CI = dyn_cast<CallInst>(I)) {
- const Value* V = CI->getCalledValue();
- Type* T = nullptr;
- if (V) T = V->getType();
- PointerType *PFT = nullptr;
- if (T) PFT = dyn_cast<PointerType>(T);
- FunctionType *FT = nullptr;
- if (PFT) FT = dyn_cast<FunctionType>(PFT->getElementType());
+ CallInst::Create(F, Params, "", &I);
+ } else if (const CallInst *CI = dyn_cast<CallInst>(&I)) {
+ FunctionType *FT = CI->getFunctionType();
Function *F_ = CI->getCalledFunction();
- if (FT && needsFPReturnHelper(*FT) &&
+ if (needsFPReturnHelper(*FT) &&
!(F_ && isIntrinsicInline(F_))) {
Modified=true;
F.addFnAttr("saveS2");
@@ -447,7 +439,7 @@ static bool fixupFPReturnAndCall(Function &F, Module *M,
Modified=true;
F.addFnAttr("saveS2");
}
- if (TM.getRelocationModel() != Reloc::PIC_ ) {
+ if (!TM.isPositionIndependent()) {
if (needsFPHelperFromSig(*F_)) {
assureFPCallStub(*F_, M, TM);
Modified=true;
@@ -461,7 +453,7 @@ static bool fixupFPReturnAndCall(Function &F, Module *M,
static void createFPFnStub(Function *F, Module *M, FPParamVariant PV,
const MipsTargetMachine &TM) {
- bool PicMode = TM.getRelocationModel() == Reloc::PIC_;
+ bool PicMode = TM.isPositionIndependent();
bool LE = TM.isLittleEndian();
LLVMContext &Context = M->getContext();
std::string Name = F->getName();
diff --git a/lib/Target/Mips/Mips16ISelDAGToDAG.cpp b/lib/Target/Mips/Mips16ISelDAGToDAG.cpp
index 5a1c2c67cc704..0405291431cdb 100644
--- a/lib/Target/Mips/Mips16ISelDAGToDAG.cpp
+++ b/lib/Target/Mips/Mips16ISelDAGToDAG.cpp
@@ -14,7 +14,6 @@
#include "Mips16ISelDAGToDAG.h"
#include "MCTargetDesc/MipsBaseInfo.h"
#include "Mips.h"
-#include "MipsAnalyzeImmediate.h"
#include "MipsMachineFunction.h"
#include "MipsRegisterInfo.h"
#include "llvm/CodeGen/MachineConstantPool.h"
@@ -43,8 +42,8 @@ bool Mips16DAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
return MipsDAGToDAGISel::runOnMachineFunction(MF);
}
/// Select multiply instructions.
-std::pair<SDNode*, SDNode*>
-Mips16DAGToDAGISel::selectMULT(SDNode *N, unsigned Opc, SDLoc DL, EVT Ty,
+std::pair<SDNode *, SDNode *>
+Mips16DAGToDAGISel::selectMULT(SDNode *N, unsigned Opc, const SDLoc &DL, EVT Ty,
bool HasLo, bool HasHi) {
SDNode *Lo = nullptr, *Hi = nullptr;
SDNode *Mul = CurDAG->getMachineNode(Opc, DL, MVT::Glue, N->getOperand(0),
@@ -81,125 +80,60 @@ void Mips16DAGToDAGISel::initGlobalBaseReg(MachineFunction &MF) {
V1 = RegInfo.createVirtualRegister(RC);
V2 = RegInfo.createVirtualRegister(RC);
- BuildMI(MBB, I, DL, TII.get(Mips::GotPrologue16), V0).
- addReg(V1, RegState::Define).
- addExternalSymbol("_gp_disp", MipsII::MO_ABS_HI).
- addExternalSymbol("_gp_disp", MipsII::MO_ABS_LO);
+ BuildMI(MBB, I, DL, TII.get(Mips::GotPrologue16), V0)
+ .addReg(V1, RegState::Define)
+ .addExternalSymbol("_gp_disp", MipsII::MO_ABS_HI)
+ .addExternalSymbol("_gp_disp", MipsII::MO_ABS_LO);
BuildMI(MBB, I, DL, TII.get(Mips::SllX16), V2).addReg(V0).addImm(16);
BuildMI(MBB, I, DL, TII.get(Mips::AdduRxRyRz16), GlobalBaseReg)
- .addReg(V1).addReg(V2);
-}
-
-// Insert instructions to initialize the Mips16 SP Alias register in the
-// first MBB of the function.
-//
-void Mips16DAGToDAGISel::initMips16SPAliasReg(MachineFunction &MF) {
- MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
-
- if (!MipsFI->mips16SPAliasRegSet())
- return;
-
- MachineBasicBlock &MBB = MF.front();
- MachineBasicBlock::iterator I = MBB.begin();
- const TargetInstrInfo &TII = *Subtarget->getInstrInfo();
- DebugLoc DL = I != MBB.end() ? I->getDebugLoc() : DebugLoc();
- unsigned Mips16SPAliasReg = MipsFI->getMips16SPAliasReg();
-
- BuildMI(MBB, I, DL, TII.get(Mips::MoveR3216), Mips16SPAliasReg)
- .addReg(Mips::SP);
+ .addReg(V1)
+ .addReg(V2);
}
void Mips16DAGToDAGISel::processFunctionAfterISel(MachineFunction &MF) {
initGlobalBaseReg(MF);
- initMips16SPAliasReg(MF);
-}
-
-/// getMips16SPAliasReg - Output the instructions required to put the
-/// SP into a Mips16 accessible aliased register.
-SDValue Mips16DAGToDAGISel::getMips16SPAliasReg() {
- unsigned Mips16SPAliasReg =
- MF->getInfo<MipsFunctionInfo>()->getMips16SPAliasReg();
- auto PtrVT = getTargetLowering()->getPointerTy(CurDAG->getDataLayout());
- return CurDAG->getRegister(Mips16SPAliasReg, PtrVT);
}
-void Mips16DAGToDAGISel::getMips16SPRefReg(SDNode *Parent, SDValue &AliasReg) {
- auto PtrVT = getTargetLowering()->getPointerTy(CurDAG->getDataLayout());
- SDValue AliasFPReg = CurDAG->getRegister(Mips::S0, PtrVT);
- if (Parent) {
- switch (Parent->getOpcode()) {
- case ISD::LOAD: {
- LoadSDNode *SD = dyn_cast<LoadSDNode>(Parent);
- switch (SD->getMemoryVT().getSizeInBits()) {
- case 8:
- case 16:
- AliasReg = Subtarget->getFrameLowering()->hasFP(*MF)
- ? AliasFPReg
- : getMips16SPAliasReg();
- return;
- }
- break;
- }
- case ISD::STORE: {
- StoreSDNode *SD = dyn_cast<StoreSDNode>(Parent);
- switch (SD->getMemoryVT().getSizeInBits()) {
- case 8:
- case 16:
- AliasReg = Subtarget->getFrameLowering()->hasFP(*MF)
- ? AliasFPReg
- : getMips16SPAliasReg();
- return;
- }
- break;
- }
- }
- }
- AliasReg = CurDAG->getRegister(Mips::SP, PtrVT);
- return;
-
-}
-
-bool Mips16DAGToDAGISel::selectAddr16(
- SDNode *Parent, SDValue Addr, SDValue &Base, SDValue &Offset,
- SDValue &Alias) {
+bool Mips16DAGToDAGISel::selectAddr(bool SPAllowed, SDValue Addr, SDValue &Base,
+ SDValue &Offset) {
SDLoc DL(Addr);
EVT ValTy = Addr.getValueType();
- Alias = CurDAG->getTargetConstant(0, DL, ValTy);
-
// if Address is FI, get the TargetFrameIndex.
- if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
- Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy);
- Offset = CurDAG->getTargetConstant(0, DL, ValTy);
- getMips16SPRefReg(Parent, Alias);
- return true;
+ if (SPAllowed) {
+ if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>(Addr)) {
+ Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy);
+ Offset = CurDAG->getTargetConstant(0, DL, ValTy);
+ return true;
+ }
}
// on PIC code Load GA
if (Addr.getOpcode() == MipsISD::Wrapper) {
- Base = Addr.getOperand(0);
+ Base = Addr.getOperand(0);
Offset = Addr.getOperand(1);
return true;
}
- if (TM.getRelocationModel() != Reloc::PIC_) {
+ if (!TM.isPositionIndependent()) {
if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
- Addr.getOpcode() == ISD::TargetGlobalAddress))
+ Addr.getOpcode() == ISD::TargetGlobalAddress))
return false;
}
// Addresses of the form FI+const or FI|const
if (CurDAG->isBaseWithConstantOffset(Addr)) {
ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1));
if (isInt<16>(CN->getSExtValue())) {
-
// If the first operand is a FI, get the TargetFI Node
- if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>
- (Addr.getOperand(0))) {
- Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy);
- getMips16SPRefReg(Parent, Alias);
+ if (SPAllowed) {
+ if (FrameIndexSDNode *FIN =
+ dyn_cast<FrameIndexSDNode>(Addr.getOperand(0))) {
+ Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), ValTy);
+ Offset = CurDAG->getTargetConstant(CN->getZExtValue(), DL, ValTy);
+ return true;
+ }
}
- else
- Base = Addr.getOperand(0);
+ Base = Addr.getOperand(0);
Offset = CurDAG->getTargetConstant(CN->getZExtValue(), DL, ValTy);
return true;
}
@@ -224,25 +158,25 @@ bool Mips16DAGToDAGISel::selectAddr16(
return true;
}
}
-
- // If an indexed floating point load/store can be emitted, return false.
- const LSBaseSDNode *LS = dyn_cast<LSBaseSDNode>(Parent);
-
- if (LS) {
- if (LS->getMemoryVT() == MVT::f32 && Subtarget->hasMips4_32r2())
- return false;
- if (LS->getMemoryVT() == MVT::f64 && Subtarget->hasMips4_32r2())
- return false;
- }
}
- Base = Addr;
+ Base = Addr;
Offset = CurDAG->getTargetConstant(0, DL, ValTy);
return true;
}
+bool Mips16DAGToDAGISel::selectAddr16(SDValue Addr, SDValue &Base,
+ SDValue &Offset) {
+ return selectAddr(false, Addr, Base, Offset);
+}
+
+bool Mips16DAGToDAGISel::selectAddr16SP(SDValue Addr, SDValue &Base,
+ SDValue &Offset) {
+ return selectAddr(true, Addr, Base, Offset);
+}
+
/// Select instructions not customized! Used for
/// expanded, promoted and normal instructions
-std::pair<bool, SDNode*> Mips16DAGToDAGISel::selectNode(SDNode *Node) {
+bool Mips16DAGToDAGISel::trySelect(SDNode *Node) {
unsigned Opcode = Node->getOpcode();
SDLoc DL(Node);
@@ -253,13 +187,15 @@ std::pair<bool, SDNode*> Mips16DAGToDAGISel::selectNode(SDNode *Node) {
EVT NodeTy = Node->getValueType(0);
unsigned MultOpc;
- switch(Opcode) {
- default: break;
+ switch (Opcode) {
+ default:
+ break;
case ISD::SUBE:
case ISD::ADDE: {
SDValue InFlag = Node->getOperand(2), CmpLHS;
- unsigned Opc = InFlag.getOpcode(); (void)Opc;
+ unsigned Opc = InFlag.getOpcode();
+ (void)Opc;
assert(((Opc == ISD::ADDC || Opc == ISD::ADDE) ||
(Opc == ISD::SUBC || Opc == ISD::SUBE)) &&
"(ADD|SUB)E flag operand must come from (ADD|SUB)C/E insn");
@@ -273,7 +209,7 @@ std::pair<bool, SDNode*> Mips16DAGToDAGISel::selectNode(SDNode *Node) {
MOp = Mips::SubuRxRyRz16;
}
- SDValue Ops[] = { CmpLHS, InFlag.getOperand(1) };
+ SDValue Ops[] = {CmpLHS, InFlag.getOperand(1)};
SDValue LHS = Node->getOperand(0);
SDValue RHS = Node->getOperand(1);
@@ -283,40 +219,42 @@ std::pair<bool, SDNode*> Mips16DAGToDAGISel::selectNode(SDNode *Node) {
unsigned Sltu_op = Mips::SltuRxRyRz16;
SDNode *Carry = CurDAG->getMachineNode(Sltu_op, DL, VT, Ops);
unsigned Addu_op = Mips::AdduRxRyRz16;
- SDNode *AddCarry = CurDAG->getMachineNode(Addu_op, DL, VT,
- SDValue(Carry,0), RHS);
+ SDNode *AddCarry =
+ CurDAG->getMachineNode(Addu_op, DL, VT, SDValue(Carry, 0), RHS);
- SDNode *Result = CurDAG->SelectNodeTo(Node, MOp, VT, MVT::Glue, LHS,
- SDValue(AddCarry,0));
- return std::make_pair(true, Result);
+ CurDAG->SelectNodeTo(Node, MOp, VT, MVT::Glue, LHS, SDValue(AddCarry, 0));
+ return true;
}
/// Mul with two results
case ISD::SMUL_LOHI:
case ISD::UMUL_LOHI: {
MultOpc = (Opcode == ISD::UMUL_LOHI ? Mips::MultuRxRy16 : Mips::MultRxRy16);
- std::pair<SDNode*, SDNode*> LoHi = selectMULT(Node, MultOpc, DL, NodeTy,
- true, true);
+ std::pair<SDNode *, SDNode *> LoHi =
+ selectMULT(Node, MultOpc, DL, NodeTy, true, true);
if (!SDValue(Node, 0).use_empty())
ReplaceUses(SDValue(Node, 0), SDValue(LoHi.first, 0));
if (!SDValue(Node, 1).use_empty())
ReplaceUses(SDValue(Node, 1), SDValue(LoHi.second, 0));
- return std::make_pair(true, nullptr);
+ CurDAG->RemoveDeadNode(Node);
+ return true;
}
case ISD::MULHS:
case ISD::MULHU: {
MultOpc = (Opcode == ISD::MULHU ? Mips::MultuRxRy16 : Mips::MultRxRy16);
- SDNode *Result = selectMULT(Node, MultOpc, DL, NodeTy, false, true).second;
- return std::make_pair(true, Result);
+ auto LoHi = selectMULT(Node, MultOpc, DL, NodeTy, false, true);
+ ReplaceNode(Node, LoHi.second);
+ return true;
}
}
- return std::make_pair(false, nullptr);
+ return false;
}
-FunctionPass *llvm::createMips16ISelDag(MipsTargetMachine &TM) {
- return new Mips16DAGToDAGISel(TM);
+FunctionPass *llvm::createMips16ISelDag(MipsTargetMachine &TM,
+ CodeGenOpt::Level OptLevel) {
+ return new Mips16DAGToDAGISel(TM, OptLevel);
}
diff --git a/lib/Target/Mips/Mips16ISelDAGToDAG.h b/lib/Target/Mips/Mips16ISelDAGToDAG.h
index ae0e61e19d9d6..bbf8cc36f241a 100644
--- a/lib/Target/Mips/Mips16ISelDAGToDAG.h
+++ b/lib/Target/Mips/Mips16ISelDAGToDAG.h
@@ -20,22 +20,24 @@ namespace llvm {
class Mips16DAGToDAGISel : public MipsDAGToDAGISel {
public:
- explicit Mips16DAGToDAGISel(MipsTargetMachine &TM) : MipsDAGToDAGISel(TM) {}
+ explicit Mips16DAGToDAGISel(MipsTargetMachine &TM, CodeGenOpt::Level OL)
+ : MipsDAGToDAGISel(TM, OL) {}
private:
- std::pair<SDNode*, SDNode*> selectMULT(SDNode *N, unsigned Opc, SDLoc DL,
- EVT Ty, bool HasLo, bool HasHi);
-
- SDValue getMips16SPAliasReg();
+ std::pair<SDNode *, SDNode *> selectMULT(SDNode *N, unsigned Opc,
+ const SDLoc &DL, EVT Ty, bool HasLo,
+ bool HasHi);
bool runOnMachineFunction(MachineFunction &MF) override;
- void getMips16SPRefReg(SDNode *Parent, SDValue &AliasReg);
-
- bool selectAddr16(SDNode *Parent, SDValue N, SDValue &Base,
- SDValue &Offset, SDValue &Alias) override;
+ bool selectAddr(bool SPAllowed, SDValue Addr, SDValue &Base,
+ SDValue &Offset);
+ bool selectAddr16(SDValue Addr, SDValue &Base,
+ SDValue &Offset) override;
+ bool selectAddr16SP(SDValue Addr, SDValue &Base,
+ SDValue &Offset) override;
- std::pair<bool, SDNode*> selectNode(SDNode *Node) override;
+ bool trySelect(SDNode *Node) override;
void processFunctionAfterISel(MachineFunction &MF) override;
@@ -46,8 +48,8 @@ private:
void initMips16SPAliasReg(MachineFunction &MF);
};
-FunctionPass *createMips16ISelDag(MipsTargetMachine &TM);
-
+FunctionPass *createMips16ISelDag(MipsTargetMachine &TM,
+ CodeGenOpt::Level OptLevel);
}
#endif
diff --git a/lib/Target/Mips/Mips16ISelLowering.cpp b/lib/Target/Mips/Mips16ISelLowering.cpp
index e7483253e61d8..bdb9eec4cc5ae 100644
--- a/lib/Target/Mips/Mips16ISelLowering.cpp
+++ b/lib/Target/Mips/Mips16ISelLowering.cpp
@@ -16,11 +16,9 @@
#include "MipsMachineFunction.h"
#include "MipsRegisterInfo.h"
#include "MipsTargetMachine.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetInstrInfo.h"
-#include <string>
using namespace llvm;
@@ -167,9 +165,9 @@ Mips16TargetLowering::allowsMisalignedMemoryAccesses(EVT VT,
}
MachineBasicBlock *
-Mips16TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
+Mips16TargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
MachineBasicBlock *BB) const {
- switch (MI->getOpcode()) {
+ switch (MI.getOpcode()) {
default:
return MipsTargetLowering::EmitInstrWithCustomInserter(MI, BB);
case Mips::SelBeqZ:
@@ -519,12 +517,13 @@ getOpndList(SmallVectorImpl<SDValue> &Ops,
Chain);
}
-MachineBasicBlock *Mips16TargetLowering::
-emitSel16(unsigned Opc, MachineInstr *MI, MachineBasicBlock *BB) const {
+MachineBasicBlock *
+Mips16TargetLowering::emitSel16(unsigned Opc, MachineInstr &MI,
+ MachineBasicBlock *BB) const {
if (DontExpandCondPseudos16)
return BB;
const TargetInstrInfo *TII = Subtarget.getInstrInfo();
- DebugLoc DL = MI->getDebugLoc();
+ DebugLoc DL = MI.getDebugLoc();
// To "insert" a SELECT_CC instruction, we actually have to insert the
// diamond control-flow pattern. The incoming instruction knows the
// destination vreg to set, the condition code register to branch on, the
@@ -554,8 +553,9 @@ emitSel16(unsigned Opc, MachineInstr *MI, MachineBasicBlock *BB) const {
BB->addSuccessor(copy0MBB);
BB->addSuccessor(sinkMBB);
- BuildMI(BB, DL, TII->get(Opc)).addReg(MI->getOperand(3).getReg())
- .addMBB(sinkMBB);
+ BuildMI(BB, DL, TII->get(Opc))
+ .addReg(MI.getOperand(3).getReg())
+ .addMBB(sinkMBB);
// copy0MBB:
// %FalseValue = ...
@@ -570,22 +570,23 @@ emitSel16(unsigned Opc, MachineInstr *MI, MachineBasicBlock *BB) const {
// ...
BB = sinkMBB;
- BuildMI(*BB, BB->begin(), DL,
- TII->get(Mips::PHI), MI->getOperand(0).getReg())
- .addReg(MI->getOperand(1).getReg()).addMBB(thisMBB)
- .addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB);
+ BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(0).getReg())
+ .addReg(MI.getOperand(1).getReg())
+ .addMBB(thisMBB)
+ .addReg(MI.getOperand(2).getReg())
+ .addMBB(copy0MBB);
- MI->eraseFromParent(); // The pseudo instruction is gone now.
+ MI.eraseFromParent(); // The pseudo instruction is gone now.
return BB;
}
MachineBasicBlock *
-Mips16TargetLowering::emitSelT16(unsigned Opc1, unsigned Opc2, MachineInstr *MI,
+Mips16TargetLowering::emitSelT16(unsigned Opc1, unsigned Opc2, MachineInstr &MI,
MachineBasicBlock *BB) const {
if (DontExpandCondPseudos16)
return BB;
const TargetInstrInfo *TII = Subtarget.getInstrInfo();
- DebugLoc DL = MI->getDebugLoc();
+ DebugLoc DL = MI.getDebugLoc();
// To "insert" a SELECT_CC instruction, we actually have to insert the
// diamond control-flow pattern. The incoming instruction knows the
// destination vreg to set, the condition code register to branch on, the
@@ -615,8 +616,9 @@ Mips16TargetLowering::emitSelT16(unsigned Opc1, unsigned Opc2, MachineInstr *MI,
BB->addSuccessor(copy0MBB);
BB->addSuccessor(sinkMBB);
- BuildMI(BB, DL, TII->get(Opc2)).addReg(MI->getOperand(3).getReg())
- .addReg(MI->getOperand(4).getReg());
+ BuildMI(BB, DL, TII->get(Opc2))
+ .addReg(MI.getOperand(3).getReg())
+ .addReg(MI.getOperand(4).getReg());
BuildMI(BB, DL, TII->get(Opc1)).addMBB(sinkMBB);
// copy0MBB:
@@ -632,24 +634,25 @@ Mips16TargetLowering::emitSelT16(unsigned Opc1, unsigned Opc2, MachineInstr *MI,
// ...
BB = sinkMBB;
- BuildMI(*BB, BB->begin(), DL,
- TII->get(Mips::PHI), MI->getOperand(0).getReg())
- .addReg(MI->getOperand(1).getReg()).addMBB(thisMBB)
- .addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB);
+ BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(0).getReg())
+ .addReg(MI.getOperand(1).getReg())
+ .addMBB(thisMBB)
+ .addReg(MI.getOperand(2).getReg())
+ .addMBB(copy0MBB);
- MI->eraseFromParent(); // The pseudo instruction is gone now.
+ MI.eraseFromParent(); // The pseudo instruction is gone now.
return BB;
}
MachineBasicBlock *
Mips16TargetLowering::emitSeliT16(unsigned Opc1, unsigned Opc2,
- MachineInstr *MI,
+ MachineInstr &MI,
MachineBasicBlock *BB) const {
if (DontExpandCondPseudos16)
return BB;
const TargetInstrInfo *TII = Subtarget.getInstrInfo();
- DebugLoc DL = MI->getDebugLoc();
+ DebugLoc DL = MI.getDebugLoc();
// To "insert" a SELECT_CC instruction, we actually have to insert the
// diamond control-flow pattern. The incoming instruction knows the
// destination vreg to set, the condition code register to branch on, the
@@ -679,8 +682,9 @@ Mips16TargetLowering::emitSeliT16(unsigned Opc1, unsigned Opc2,
BB->addSuccessor(copy0MBB);
BB->addSuccessor(sinkMBB);
- BuildMI(BB, DL, TII->get(Opc2)).addReg(MI->getOperand(3).getReg())
- .addImm(MI->getOperand(4).getImm());
+ BuildMI(BB, DL, TII->get(Opc2))
+ .addReg(MI.getOperand(3).getReg())
+ .addImm(MI.getOperand(4).getImm());
BuildMI(BB, DL, TII->get(Opc1)).addMBB(sinkMBB);
// copy0MBB:
@@ -696,42 +700,44 @@ Mips16TargetLowering::emitSeliT16(unsigned Opc1, unsigned Opc2,
// ...
BB = sinkMBB;
- BuildMI(*BB, BB->begin(), DL,
- TII->get(Mips::PHI), MI->getOperand(0).getReg())
- .addReg(MI->getOperand(1).getReg()).addMBB(thisMBB)
- .addReg(MI->getOperand(2).getReg()).addMBB(copy0MBB);
+ BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(0).getReg())
+ .addReg(MI.getOperand(1).getReg())
+ .addMBB(thisMBB)
+ .addReg(MI.getOperand(2).getReg())
+ .addMBB(copy0MBB);
- MI->eraseFromParent(); // The pseudo instruction is gone now.
+ MI.eraseFromParent(); // The pseudo instruction is gone now.
return BB;
}
MachineBasicBlock *
Mips16TargetLowering::emitFEXT_T8I816_ins(unsigned BtOpc, unsigned CmpOpc,
- MachineInstr *MI,
+ MachineInstr &MI,
MachineBasicBlock *BB) const {
if (DontExpandCondPseudos16)
return BB;
const TargetInstrInfo *TII = Subtarget.getInstrInfo();
- unsigned regX = MI->getOperand(0).getReg();
- unsigned regY = MI->getOperand(1).getReg();
- MachineBasicBlock *target = MI->getOperand(2).getMBB();
- BuildMI(*BB, MI, MI->getDebugLoc(), TII->get(CmpOpc)).addReg(regX)
- .addReg(regY);
- BuildMI(*BB, MI, MI->getDebugLoc(), TII->get(BtOpc)).addMBB(target);
- MI->eraseFromParent(); // The pseudo instruction is gone now.
+ unsigned regX = MI.getOperand(0).getReg();
+ unsigned regY = MI.getOperand(1).getReg();
+ MachineBasicBlock *target = MI.getOperand(2).getMBB();
+ BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(CmpOpc))
+ .addReg(regX)
+ .addReg(regY);
+ BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(BtOpc)).addMBB(target);
+ MI.eraseFromParent(); // The pseudo instruction is gone now.
return BB;
}
MachineBasicBlock *Mips16TargetLowering::emitFEXT_T8I8I16_ins(
unsigned BtOpc, unsigned CmpiOpc, unsigned CmpiXOpc, bool ImmSigned,
- MachineInstr *MI, MachineBasicBlock *BB) const {
+ MachineInstr &MI, MachineBasicBlock *BB) const {
if (DontExpandCondPseudos16)
return BB;
const TargetInstrInfo *TII = Subtarget.getInstrInfo();
- unsigned regX = MI->getOperand(0).getReg();
- int64_t imm = MI->getOperand(1).getImm();
- MachineBasicBlock *target = MI->getOperand(2).getMBB();
+ unsigned regX = MI.getOperand(0).getReg();
+ int64_t imm = MI.getOperand(1).getImm();
+ MachineBasicBlock *target = MI.getOperand(2).getMBB();
unsigned CmpOpc;
if (isUInt<8>(imm))
CmpOpc = CmpiOpc;
@@ -740,10 +746,9 @@ MachineBasicBlock *Mips16TargetLowering::emitFEXT_T8I8I16_ins(
CmpOpc = CmpiXOpc;
else
llvm_unreachable("immediate field not usable");
- BuildMI(*BB, MI, MI->getDebugLoc(), TII->get(CmpOpc)).addReg(regX)
- .addImm(imm);
- BuildMI(*BB, MI, MI->getDebugLoc(), TII->get(BtOpc)).addMBB(target);
- MI->eraseFromParent(); // The pseudo instruction is gone now.
+ BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(CmpOpc)).addReg(regX).addImm(imm);
+ BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(BtOpc)).addMBB(target);
+ MI.eraseFromParent(); // The pseudo instruction is gone now.
return BB;
}
@@ -758,38 +763,38 @@ static unsigned Mips16WhichOp8uOr16simm
}
MachineBasicBlock *
-Mips16TargetLowering::emitFEXT_CCRX16_ins(unsigned SltOpc, MachineInstr *MI,
+Mips16TargetLowering::emitFEXT_CCRX16_ins(unsigned SltOpc, MachineInstr &MI,
MachineBasicBlock *BB) const {
if (DontExpandCondPseudos16)
return BB;
const TargetInstrInfo *TII = Subtarget.getInstrInfo();
- unsigned CC = MI->getOperand(0).getReg();
- unsigned regX = MI->getOperand(1).getReg();
- unsigned regY = MI->getOperand(2).getReg();
- BuildMI(*BB, MI, MI->getDebugLoc(), TII->get(SltOpc)).addReg(regX).addReg(
- regY);
- BuildMI(*BB, MI, MI->getDebugLoc(),
- TII->get(Mips::MoveR3216), CC).addReg(Mips::T8);
- MI->eraseFromParent(); // The pseudo instruction is gone now.
+ unsigned CC = MI.getOperand(0).getReg();
+ unsigned regX = MI.getOperand(1).getReg();
+ unsigned regY = MI.getOperand(2).getReg();
+ BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(SltOpc))
+ .addReg(regX)
+ .addReg(regY);
+ BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(Mips::MoveR3216), CC)
+ .addReg(Mips::T8);
+ MI.eraseFromParent(); // The pseudo instruction is gone now.
return BB;
}
MachineBasicBlock *
Mips16TargetLowering::emitFEXT_CCRXI16_ins(unsigned SltiOpc, unsigned SltiXOpc,
- MachineInstr *MI,
+ MachineInstr &MI,
MachineBasicBlock *BB) const {
if (DontExpandCondPseudos16)
return BB;
const TargetInstrInfo *TII = Subtarget.getInstrInfo();
- unsigned CC = MI->getOperand(0).getReg();
- unsigned regX = MI->getOperand(1).getReg();
- int64_t Imm = MI->getOperand(2).getImm();
+ unsigned CC = MI.getOperand(0).getReg();
+ unsigned regX = MI.getOperand(1).getReg();
+ int64_t Imm = MI.getOperand(2).getImm();
unsigned SltOpc = Mips16WhichOp8uOr16simm(SltiOpc, SltiXOpc, Imm);
- BuildMI(*BB, MI, MI->getDebugLoc(),
- TII->get(SltOpc)).addReg(regX).addImm(Imm);
- BuildMI(*BB, MI, MI->getDebugLoc(),
- TII->get(Mips::MoveR3216), CC).addReg(Mips::T8);
- MI->eraseFromParent(); // The pseudo instruction is gone now.
+ BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(SltOpc)).addReg(regX).addImm(Imm);
+ BuildMI(*BB, MI, MI.getDebugLoc(), TII->get(Mips::MoveR3216), CC)
+ .addReg(Mips::T8);
+ MI.eraseFromParent(); // The pseudo instruction is gone now.
return BB;
}
diff --git a/lib/Target/Mips/Mips16ISelLowering.h b/lib/Target/Mips/Mips16ISelLowering.h
index d3b9f750f3471..0ee0b816ef70f 100644
--- a/lib/Target/Mips/Mips16ISelLowering.h
+++ b/lib/Target/Mips/Mips16ISelLowering.h
@@ -27,7 +27,7 @@ namespace llvm {
bool *Fast) const override;
MachineBasicBlock *
- EmitInstrWithCustomInserter(MachineInstr *MI,
+ EmitInstrWithCustomInserter(MachineInstr &MI,
MachineBasicBlock *MBB) const override;
private:
@@ -50,32 +50,32 @@ namespace llvm {
bool IsCallReloc, CallLoweringInfo &CLI, SDValue Callee,
SDValue Chain) const override;
- MachineBasicBlock *emitSel16(unsigned Opc, MachineInstr *MI,
+ MachineBasicBlock *emitSel16(unsigned Opc, MachineInstr &MI,
MachineBasicBlock *BB) const;
MachineBasicBlock *emitSeliT16(unsigned Opc1, unsigned Opc2,
- MachineInstr *MI,
+ MachineInstr &MI,
MachineBasicBlock *BB) const;
MachineBasicBlock *emitSelT16(unsigned Opc1, unsigned Opc2,
- MachineInstr *MI,
+ MachineInstr &MI,
MachineBasicBlock *BB) const;
MachineBasicBlock *emitFEXT_T8I816_ins(unsigned BtOpc, unsigned CmpOpc,
- MachineInstr *MI,
+ MachineInstr &MI,
MachineBasicBlock *BB) const;
- MachineBasicBlock *emitFEXT_T8I8I16_ins(
- unsigned BtOpc, unsigned CmpiOpc, unsigned CmpiXOpc, bool ImmSigned,
- MachineInstr *MI, MachineBasicBlock *BB) const;
+ MachineBasicBlock *emitFEXT_T8I8I16_ins(unsigned BtOpc, unsigned CmpiOpc,
+ unsigned CmpiXOpc, bool ImmSigned,
+ MachineInstr &MI,
+ MachineBasicBlock *BB) const;
- MachineBasicBlock *emitFEXT_CCRX16_ins(
- unsigned SltOpc,
- MachineInstr *MI, MachineBasicBlock *BB) const;
+ MachineBasicBlock *emitFEXT_CCRX16_ins(unsigned SltOpc, MachineInstr &MI,
+ MachineBasicBlock *BB) const;
- MachineBasicBlock *emitFEXT_CCRXI16_ins(
- unsigned SltiOpc, unsigned SltiXOpc,
- MachineInstr *MI, MachineBasicBlock *BB )const;
+ MachineBasicBlock *emitFEXT_CCRXI16_ins(unsigned SltiOpc, unsigned SltiXOpc,
+ MachineInstr &MI,
+ MachineBasicBlock *BB) const;
};
}
diff --git a/lib/Target/Mips/Mips16InstrInfo.cpp b/lib/Target/Mips/Mips16InstrInfo.cpp
index da8ada4e53917..daa1355ffefd0 100644
--- a/lib/Target/Mips/Mips16InstrInfo.cpp
+++ b/lib/Target/Mips/Mips16InstrInfo.cpp
@@ -15,12 +15,10 @@
#include "MipsMachineFunction.h"
#include "MipsTargetMachine.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/MC/MCAsmInfo.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TargetRegistry.h"
@@ -43,7 +41,7 @@ const MipsRegisterInfo &Mips16InstrInfo::getRegisterInfo() const {
/// the destination along with the FrameIndex of the loaded stack slot. If
/// not, return 0. This predicate must return 0 if the instruction has
/// any side effects other than loading from the stack slot.
-unsigned Mips16InstrInfo::isLoadFromStackSlot(const MachineInstr *MI,
+unsigned Mips16InstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
int &FrameIndex) const {
return 0;
}
@@ -53,15 +51,15 @@ unsigned Mips16InstrInfo::isLoadFromStackSlot(const MachineInstr *MI,
/// the source reg along with the FrameIndex of the loaded stack slot. If
/// not, return 0. This predicate must return 0 if the instruction has
/// any side effects other than storing to the stack slot.
-unsigned Mips16InstrInfo::isStoreToStackSlot(const MachineInstr *MI,
+unsigned Mips16InstrInfo::isStoreToStackSlot(const MachineInstr &MI,
int &FrameIndex) const {
return 0;
}
void Mips16InstrInfo::copyPhysReg(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator I, DebugLoc DL,
- unsigned DestReg, unsigned SrcReg,
- bool KillSrc) const {
+ MachineBasicBlock::iterator I,
+ const DebugLoc &DL, unsigned DestReg,
+ unsigned SrcReg, bool KillSrc) const {
unsigned Opc = 0;
if (Mips::CPU16RegsRegClass.contains(DestReg) &&
@@ -126,9 +124,9 @@ void Mips16InstrInfo::loadRegFromStack(MachineBasicBlock &MBB,
.addMemOperand(MMO);
}
-bool Mips16InstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const {
- MachineBasicBlock &MBB = *MI->getParent();
- switch(MI->getDesc().getOpcode()) {
+bool Mips16InstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
+ MachineBasicBlock &MBB = *MI.getParent();
+ switch (MI.getDesc().getOpcode()) {
default:
return false;
case Mips::RetRA16:
@@ -136,7 +134,7 @@ bool Mips16InstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const {
break;
}
- MBB.erase(MI);
+ MBB.erase(MI.getIterator());
return true;
}
@@ -307,7 +305,8 @@ void Mips16InstrInfo::adjustStackPtr(unsigned SP, int64_t Amount,
unsigned Mips16InstrInfo::loadImmediate(unsigned FrameReg, int64_t Imm,
MachineBasicBlock &MBB,
MachineBasicBlock::iterator II,
- DebugLoc DL, unsigned &NewImm) const {
+ const DebugLoc &DL,
+ unsigned &NewImm) const {
//
// given original instruction is:
// Instr rx, T[offset] where offset is too big.
@@ -326,7 +325,7 @@ unsigned Mips16InstrInfo::loadImmediate(unsigned FrameReg, int64_t Imm,
int Reg =0;
int SpReg = 0;
- rs.enterBasicBlock(&MBB);
+ rs.enterBasicBlock(MBB);
rs.forward(II);
//
// We need to know which registers can be used, in the case where there
diff --git a/lib/Target/Mips/Mips16InstrInfo.h b/lib/Target/Mips/Mips16InstrInfo.h
index 6540b40bc9abf..ab559799f00b0 100644
--- a/lib/Target/Mips/Mips16InstrInfo.h
+++ b/lib/Target/Mips/Mips16InstrInfo.h
@@ -32,7 +32,7 @@ public:
/// the destination along with the FrameIndex of the loaded stack slot. If
/// not, return 0. This predicate must return 0 if the instruction has
/// any side effects other than loading from the stack slot.
- unsigned isLoadFromStackSlot(const MachineInstr *MI,
+ unsigned isLoadFromStackSlot(const MachineInstr &MI,
int &FrameIndex) const override;
/// isStoreToStackSlot - If the specified machine instruction is a direct
@@ -40,12 +40,11 @@ public:
/// the source reg along with the FrameIndex of the loaded stack slot. If
/// not, return 0. This predicate must return 0 if the instruction has
/// any side effects other than storing to the stack slot.
- unsigned isStoreToStackSlot(const MachineInstr *MI,
+ unsigned isStoreToStackSlot(const MachineInstr &MI,
int &FrameIndex) const override;
- void copyPhysReg(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI, DebugLoc DL,
- unsigned DestReg, unsigned SrcReg,
+ void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
+ const DebugLoc &DL, unsigned DestReg, unsigned SrcReg,
bool KillSrc) const override;
void storeRegToStack(MachineBasicBlock &MBB,
@@ -62,7 +61,7 @@ public:
const TargetRegisterInfo *TRI,
int64_t Offset) const override;
- bool expandPostRAPseudo(MachineBasicBlock::iterator MI) const override;
+ bool expandPostRAPseudo(MachineInstr &MI) const override;
unsigned getOppositeBranchOpc(unsigned Opc) const override;
@@ -83,9 +82,8 @@ public:
// This is to adjust some FrameReg. We return the new register to be used
// in place of FrameReg and the adjusted immediate field (&NewImm)
//
- unsigned loadImmediate(unsigned FrameReg,
- int64_t Imm, MachineBasicBlock &MBB,
- MachineBasicBlock::iterator II, DebugLoc DL,
+ unsigned loadImmediate(unsigned FrameReg, int64_t Imm, MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator II, const DebugLoc &DL,
unsigned &NewImm) const;
static bool validImmediate(unsigned Opcode, unsigned Reg, int64_t Amount);
diff --git a/lib/Target/Mips/Mips16InstrInfo.td b/lib/Target/Mips/Mips16InstrInfo.td
index dad6ea4c9e981..021fb86786869 100644
--- a/lib/Target/Mips/Mips16InstrInfo.td
+++ b/lib/Target/Mips/Mips16InstrInfo.td
@@ -14,14 +14,26 @@
//
// Mips Address
//
-def addr16 :
- ComplexPattern<iPTR, 3, "selectAddr16", [frameindex], [SDNPWantParent]>;
+def addr16 : ComplexPattern<iPTR, 2, "selectAddr16", [frameindex]>;
+def addr16sp : ComplexPattern<iPTR, 2, "selectAddr16SP", [frameindex]>;
//
// Address operand
def mem16 : Operand<i32> {
let PrintMethod = "printMemOperand";
- let MIOperandInfo = (ops CPU16Regs, simm16, CPU16RegsPlusSP);
+ let MIOperandInfo = (ops CPU16Regs, simm16);
+ let EncoderMethod = "getMemEncoding";
+}
+
+def mem16sp : Operand<i32> {
+ let PrintMethod = "printMemOperand";
+ // This should be CPUSPReg but the MIPS16 subtarget isn't good enough at
+ // keeping the sp-relative load and the other varieties separate at the
+ // moment. This lie fixes the problem sufficiently well to fix the errors
+ // emitted by -verify-machineinstrs and the output ends up correct as long
+ // as we use an external assembler (which is already a requirement for MIPS16
+ // for several other reasons).
+ let MIOperandInfo = (ops CPU16RegsPlusSP, simm16);
let EncoderMethod = "getMemEncoding";
}
@@ -31,6 +43,8 @@ def mem16_ea : Operand<i32> {
let EncoderMethod = "getMemEncoding";
}
+def pcrel16 : Operand<i32>;
+
//
// I-type instruction format
//
@@ -115,7 +129,7 @@ class FEXT_CCRXI16_ins<string asmstr>:
//
class FJAL16_ins<bits<1> _X, string asmstr,
InstrItinClass itin>:
- FJAL16<_X, (outs), (ins simm20:$imm),
+ FJAL16<_X, (outs), (ins uimm26:$imm),
!strconcat(asmstr, "\t$imm\n\tnop"),[],
itin> {
let isCodeGenOnly=1;
@@ -124,7 +138,7 @@ class FJAL16_ins<bits<1> _X, string asmstr,
class FJALB16_ins<bits<1> _X, string asmstr,
InstrItinClass itin>:
- FJAL16<_X, (outs), (ins simm20:$imm),
+ FJAL16<_X, (outs), (ins uimm26:$imm),
!strconcat(asmstr, "\t$imm\t# branch\n\tnop"),[],
itin> {
let isCodeGenOnly=1;
@@ -213,19 +227,6 @@ class FEXT_2RI16_ins<bits<5> _op, string asmstr,
let Constraints = "$rx_ = $rx";
}
-
-// this has an explicit sp argument that we ignore to work around a problem
-// in the compiler
-class FEXT_RI16_SP_explicit_ins<bits<5> _op, string asmstr,
- InstrItinClass itin>:
- FEXT_RI16<_op, (outs CPU16Regs:$rx), (ins CPUSPReg:$ry, simm16:$imm),
- !strconcat(asmstr, "\t$rx, $imm ( $ry ); "), [], itin>;
-
-class FEXT_RI16_SP_Store_explicit_ins<bits<5> _op, string asmstr,
- InstrItinClass itin>:
- FEXT_RI16<_op, (outs), (ins CPU16Regs:$rx, CPUSPReg:$ry, simm16:$imm),
- !strconcat(asmstr, "\t$rx, $imm ( $ry ); "), [], itin>;
-
//
// EXT-RRI instruction format
//
@@ -483,13 +484,11 @@ class SelT<string op1, string op2>:
//
// 32 bit constant
//
-def imm32: Operand<i32>;
-
def Constant32:
- MipsPseudo16<(outs), (ins imm32:$imm), "\t.word $imm", []>;
+ MipsPseudo16<(outs), (ins simm32:$imm), "\t.word $imm", []>;
def LwConstant32:
- MipsPseudo16<(outs CPU16Regs:$rx), (ins imm32:$imm, imm32:$constid),
+ MipsPseudo16<(outs CPU16Regs:$rx), (ins simm32:$imm, simm32:$constid),
"lw\t$rx, 1f\n\tb\t2f\n\t.align\t2\n1: \t.word\t$imm\n2:", []>;
@@ -635,7 +634,7 @@ def BnezRxImmX16: FEXT_RI16_B_ins<0b00101, "bnez", IIM16Alu>, cbranch16;
// Purpose: Breakpoint
// To cause a Breakpoint exception.
-def Break16: FRRBreakNull16_ins<"break 0", NoItinerary>;
+def Break16: FRRBreakNull16_ins<"break 0", IIM16Alu>;
//
// Format: BTEQZ offset MIPS16e
// Purpose: Branch on T Equal to Zero (Extended)
@@ -851,9 +850,7 @@ def LwRxRyOffMemX16: FEXT_RRI16_mem_ins<0b10011, "lw", mem16, II_LW>, MayLoad{
// Purpose: Load Word (SP-Relative, Extended)
// To load an SP-relative word from memory as a signed value.
//
-def LwRxSpImmX16: FEXT_RI16_SP_explicit_ins<0b10010, "lw", II_LW>, MayLoad{
- let Uses = [SP];
-}
+def LwRxSpImmX16: FEXT_RRI16_mem_ins<0b10010, "lw", mem16sp, II_LW>, MayLoad;
def LwRxPcTcp16: FRI16_TCP_ins<0b10110, "lw", II_LW>, MayLoad;
@@ -1277,16 +1274,14 @@ def SubuRxRyRz16: FRRR16_ins<0b11, "subu", IIM16Alu>, ArithLogic16Defs<0>;
// Purpose: Store Word (Extended)
// To store a word to memory.
//
-def SwRxRyOffMemX16:
- FEXT_RRI16_mem2_ins<0b11011, "sw", mem16, II_SW>, MayStore;
+def SwRxRyOffMemX16: FEXT_RRI16_mem2_ins<0b11011, "sw", mem16, II_SW>, MayStore;
//
// Format: SW rx, offset(sp) MIPS16e
// Purpose: Store Word rx (SP-Relative)
// To store an SP-relative word to memory.
//
-def SwRxSpImmX16: FEXT_RI16_SP_Store_explicit_ins
- <0b11010, "sw", II_SW>, MayStore;
+def SwRxSpImmX16: FEXT_RRI16_mem2_ins<0b11010, "sw", mem16sp, II_SW>, MayStore;
//
//
@@ -1340,22 +1335,21 @@ def: shift_rotate_reg16_pat<shl, SllvRxRy16>;
def: shift_rotate_reg16_pat<sra, SravRxRy16>;
def: shift_rotate_reg16_pat<srl, SrlvRxRy16>;
-class LoadM16_pat<PatFrag OpNode, Instruction I> :
- Mips16Pat<(OpNode addr16:$addr), (I addr16:$addr)>;
+class LoadM16_pat<PatFrag OpNode, Instruction I, ComplexPattern Addr> :
+ Mips16Pat<(OpNode Addr:$addr), (I Addr:$addr)>;
-def: LoadM16_pat<sextloadi8, LbRxRyOffMemX16>;
-def: LoadM16_pat<zextloadi8, LbuRxRyOffMemX16>;
-def: LoadM16_pat<sextloadi16, LhRxRyOffMemX16>;
-def: LoadM16_pat<zextloadi16, LhuRxRyOffMemX16>;
-def: LoadM16_pat<load, LwRxRyOffMemX16>;
+def: LoadM16_pat<sextloadi8, LbRxRyOffMemX16, addr16>;
+def: LoadM16_pat<zextloadi8, LbuRxRyOffMemX16, addr16>;
+def: LoadM16_pat<sextloadi16, LhRxRyOffMemX16, addr16>;
+def: LoadM16_pat<zextloadi16, LhuRxRyOffMemX16, addr16>;
+def: LoadM16_pat<load, LwRxSpImmX16, addr16sp>;
-class StoreM16_pat<PatFrag OpNode, Instruction I> :
- Mips16Pat<(OpNode CPU16Regs:$r, addr16:$addr),
- (I CPU16Regs:$r, addr16:$addr)>;
+class StoreM16_pat<PatFrag OpNode, Instruction I, ComplexPattern Addr> :
+ Mips16Pat<(OpNode CPU16Regs:$r, Addr:$addr), (I CPU16Regs:$r, Addr:$addr)>;
-def: StoreM16_pat<truncstorei8, SbRxRyOffMemX16>;
-def: StoreM16_pat<truncstorei16, ShRxRyOffMemX16>;
-def: StoreM16_pat<store, SwRxRyOffMemX16>;
+def: StoreM16_pat<truncstorei8, SbRxRyOffMemX16, addr16>;
+def: StoreM16_pat<truncstorei16, ShRxRyOffMemX16, addr16>;
+def: StoreM16_pat<store, SwRxSpImmX16, addr16sp>;
// Unconditional branch
class UncondBranch16_pat<SDNode OpNode, Instruction I>:
@@ -1401,8 +1395,7 @@ class SetCC_I16<PatFrag cond_op, PatLeaf imm_type, Instruction I>:
(I CPU16Regs:$rx, imm_type:$imm16)>;
-def: Mips16Pat<(i32 addr16:$addr),
- (AddiuRxRyOffMemX16 addr16:$addr)>;
+def: Mips16Pat<(i32 addr16sp:$addr), (AddiuRxRyOffMemX16 addr16sp:$addr)>;
// Large (>16 bit) immediate loads
@@ -1551,7 +1544,7 @@ def: UncondBranch16_pat<br, Bimm16>;
// Small immediates
def: Mips16Pat<(i32 immSExt16:$in),
- (AddiuRxRxImmX16 (Move32R16 ZERO), immSExt16:$in)>;
+ (AddiuRxRxImmX16 (MoveR3216 ZERO), immSExt16:$in)>;
def: Mips16Pat<(i32 immZExt16:$in), (LiRxImmX16 immZExt16:$in)>;
diff --git a/lib/Target/Mips/Mips16RegisterInfo.cpp b/lib/Target/Mips/Mips16RegisterInfo.cpp
index ebd51d7b50728..b034c26640e37 100644
--- a/lib/Target/Mips/Mips16RegisterInfo.cpp
+++ b/lib/Target/Mips/Mips16RegisterInfo.cpp
@@ -14,11 +14,9 @@
#include "Mips16RegisterInfo.h"
#include "Mips.h"
#include "Mips16InstrInfo.h"
-#include "MipsAnalyzeImmediate.h"
#include "MipsInstrInfo.h"
#include "MipsMachineFunction.h"
#include "MipsSubtarget.h"
-#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
@@ -28,7 +26,6 @@
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Type.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
diff --git a/lib/Target/Mips/Mips32r6InstrFormats.td b/lib/Target/Mips/Mips32r6InstrFormats.td
index 13216bebe5b66..a20c683c1e5ec 100644
--- a/lib/Target/Mips/Mips32r6InstrFormats.td
+++ b/lib/Target/Mips/Mips32r6InstrFormats.td
@@ -360,7 +360,7 @@ class SPECIAL_SDBBP_FM : MipsR6Inst {
}
// This class is ambiguous with other branches:
-// BEQC/BNEC require that rs > rt
+// BEQC/BNEC require that rs < rt && rs != 0
class CMP_BRANCH_2R_OFF16_FM<OPGROUP funct> : MipsR6Inst {
bits<5> rs;
bits<5> rt;
diff --git a/lib/Target/Mips/Mips32r6InstrInfo.td b/lib/Target/Mips/Mips32r6InstrInfo.td
index 82d2c8ee99053..f552f8d37afbb 100644
--- a/lib/Target/Mips/Mips32r6InstrInfo.td
+++ b/lib/Target/Mips/Mips32r6InstrInfo.td
@@ -182,58 +182,86 @@ class CMP_CONDN_DESC_BASE<string CondStr, string Typestr,
dag InOperandList = (ins FGROpnd:$fs, FGROpnd:$ft);
string AsmString = !strconcat("cmp.", CondStr, ".", Typestr, "\t$fd, $fs, $ft");
list<dag> Pattern = [(set FGRCCOpnd:$fd, (Op FGROpnd:$fs, FGROpnd:$ft))];
+ bit isCTI = 1;
}
multiclass CMP_CC_M <FIELD_CMP_FORMAT Format, string Typestr,
RegisterOperand FGROpnd>{
let AdditionalPredicates = [NotInMicroMips] in {
- def CMP_F_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_AF>,
+ def CMP_F_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_AF>,
CMP_CONDN_DESC_BASE<"af", Typestr, FGROpnd>,
+ MipsR6Arch<!strconcat("cmp.af.", Typestr)>,
ISA_MIPS32R6, HARDFLOAT;
- def CMP_UN_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_UN>,
+ def CMP_UN_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_UN>,
CMP_CONDN_DESC_BASE<"un", Typestr, FGROpnd, setuo>,
+ MipsR6Arch<!strconcat("cmp.un.", Typestr)>,
ISA_MIPS32R6, HARDFLOAT;
- def CMP_EQ_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_EQ>,
+ def CMP_EQ_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_EQ>,
CMP_CONDN_DESC_BASE<"eq", Typestr, FGROpnd, setoeq>,
+ MipsR6Arch<!strconcat("cmp.eq.", Typestr)>,
ISA_MIPS32R6, HARDFLOAT;
- def CMP_UEQ_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_UEQ>,
+ def CMP_UEQ_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format,
+ FIELD_CMP_COND_UEQ>,
CMP_CONDN_DESC_BASE<"ueq", Typestr, FGROpnd, setueq>,
+ MipsR6Arch<!strconcat("cmp.ueq.", Typestr)>,
ISA_MIPS32R6, HARDFLOAT;
- def CMP_LT_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_LT>,
+ def CMP_LT_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_LT>,
CMP_CONDN_DESC_BASE<"lt", Typestr, FGROpnd, setolt>,
+ MipsR6Arch<!strconcat("cmp.lt.", Typestr)>,
ISA_MIPS32R6, HARDFLOAT;
- def CMP_ULT_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_ULT>,
+ def CMP_ULT_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format,
+ FIELD_CMP_COND_ULT>,
CMP_CONDN_DESC_BASE<"ult", Typestr, FGROpnd, setult>,
+ MipsR6Arch<!strconcat("cmp.ult.", Typestr)>,
ISA_MIPS32R6, HARDFLOAT;
- def CMP_LE_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_LE>,
+ def CMP_LE_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_LE>,
CMP_CONDN_DESC_BASE<"le", Typestr, FGROpnd, setole>,
+ MipsR6Arch<!strconcat("cmp.le.", Typestr)>,
ISA_MIPS32R6, HARDFLOAT;
- def CMP_ULE_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_ULE>,
+ def CMP_ULE_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format,
+ FIELD_CMP_COND_ULE>,
CMP_CONDN_DESC_BASE<"ule", Typestr, FGROpnd, setule>,
+ MipsR6Arch<!strconcat("cmp.ule.", Typestr)>,
ISA_MIPS32R6, HARDFLOAT;
- def CMP_SAF_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_SAF>,
+ def CMP_SAF_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format,
+ FIELD_CMP_COND_SAF>,
CMP_CONDN_DESC_BASE<"saf", Typestr, FGROpnd>,
+ MipsR6Arch<!strconcat("cmp.saf.", Typestr)>,
ISA_MIPS32R6, HARDFLOAT;
- def CMP_SUN_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_SUN>,
+ def CMP_SUN_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format,
+ FIELD_CMP_COND_SUN>,
CMP_CONDN_DESC_BASE<"sun", Typestr, FGROpnd>,
+ MipsR6Arch<!strconcat("cmp.sun.", Typestr)>,
ISA_MIPS32R6, HARDFLOAT;
- def CMP_SEQ_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_SEQ>,
+ def CMP_SEQ_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format,
+ FIELD_CMP_COND_SEQ>,
CMP_CONDN_DESC_BASE<"seq", Typestr, FGROpnd>,
+ MipsR6Arch<!strconcat("cmp.seq.", Typestr)>,
ISA_MIPS32R6, HARDFLOAT;
- def CMP_SUEQ_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_SUEQ>,
+ def CMP_SUEQ_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format,
+ FIELD_CMP_COND_SUEQ>,
CMP_CONDN_DESC_BASE<"sueq", Typestr, FGROpnd>,
+ MipsR6Arch<!strconcat("cmp.sueq.", Typestr)>,
ISA_MIPS32R6, HARDFLOAT;
- def CMP_SLT_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_SLT>,
+ def CMP_SLT_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format,
+ FIELD_CMP_COND_SLT>,
CMP_CONDN_DESC_BASE<"slt", Typestr, FGROpnd>,
+ MipsR6Arch<!strconcat("cmp.slt.", Typestr)>,
ISA_MIPS32R6, HARDFLOAT;
- def CMP_SULT_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_SULT>,
+ def CMP_SULT_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format,
+ FIELD_CMP_COND_SULT>,
CMP_CONDN_DESC_BASE<"sult", Typestr, FGROpnd>,
+ MipsR6Arch<!strconcat("cmp.sult.", Typestr)>,
ISA_MIPS32R6, HARDFLOAT;
- def CMP_SLE_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_SLE>,
+ def CMP_SLE_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format,
+ FIELD_CMP_COND_SLE>,
CMP_CONDN_DESC_BASE<"sle", Typestr, FGROpnd>,
+ MipsR6Arch<!strconcat("cmp.sle.", Typestr)>,
ISA_MIPS32R6, HARDFLOAT;
- def CMP_SULE_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_SULE>,
+ def CMP_SULE_#NAME : R6MMR6Rel, COP1_CMP_CONDN_FM<Format,
+ FIELD_CMP_COND_SULE>,
CMP_CONDN_DESC_BASE<"sule", Typestr, FGROpnd>,
+ MipsR6Arch<!strconcat("cmp.sule.", Typestr)>,
ISA_MIPS32R6, HARDFLOAT;
}
}
@@ -245,52 +273,62 @@ multiclass CMP_CC_M <FIELD_CMP_FORMAT Format, string Typestr,
//===----------------------------------------------------------------------===//
class PCREL_DESC_BASE<string instr_asm, RegisterOperand GPROpnd,
- Operand ImmOpnd> : MipsR6Arch<instr_asm> {
+ Operand ImmOpnd, InstrItinClass itin>
+ : MipsR6Arch<instr_asm> {
dag OutOperandList = (outs GPROpnd:$rs);
dag InOperandList = (ins ImmOpnd:$imm);
string AsmString = !strconcat(instr_asm, "\t$rs, $imm");
list<dag> Pattern = [];
+ InstrItinClass Itinerary = itin;
}
-class ADDIUPC_DESC : PCREL_DESC_BASE<"addiupc", GPR32Opnd, simm19_lsl2>;
-class LWPC_DESC: PCREL_DESC_BASE<"lwpc", GPR32Opnd, simm19_lsl2>;
-class LWUPC_DESC: PCREL_DESC_BASE<"lwupc", GPR32Opnd, simm19_lsl2>;
+class ADDIUPC_DESC : PCREL_DESC_BASE<"addiupc", GPR32Opnd, simm19_lsl2,
+ II_ADDIUPC>;
+class LWPC_DESC: PCREL_DESC_BASE<"lwpc", GPR32Opnd, simm19_lsl2, II_LWPC>;
+class LWUPC_DESC: PCREL_DESC_BASE<"lwupc", GPR32Opnd, simm19_lsl2, II_LWUPC>;
class ALIGN_DESC_BASE<string instr_asm, RegisterOperand GPROpnd,
- Operand ImmOpnd> : MipsR6Arch<instr_asm> {
+ Operand ImmOpnd, InstrItinClass itin>
+ : MipsR6Arch<instr_asm> {
dag OutOperandList = (outs GPROpnd:$rd);
dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt, ImmOpnd:$bp);
string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt, $bp");
list<dag> Pattern = [];
+ InstrItinClass Itinerary = itin;
}
-class ALIGN_DESC : ALIGN_DESC_BASE<"align", GPR32Opnd, uimm2>;
+class ALIGN_DESC : ALIGN_DESC_BASE<"align", GPR32Opnd, uimm2, II_ALIGN>;
-class ALUIPC_DESC_BASE<string instr_asm, RegisterOperand GPROpnd>
- : MipsR6Arch<instr_asm> {
+class ALUIPC_DESC_BASE<string instr_asm, RegisterOperand GPROpnd,
+ InstrItinClass itin = NoItinerary>
+ : MipsR6Arch<instr_asm> {
dag OutOperandList = (outs GPROpnd:$rs);
dag InOperandList = (ins simm16:$imm);
string AsmString = !strconcat(instr_asm, "\t$rs, $imm");
list<dag> Pattern = [];
+ InstrItinClass Itinerary = itin;
}
-class ALUIPC_DESC : ALUIPC_DESC_BASE<"aluipc", GPR32Opnd>;
-class AUIPC_DESC : ALUIPC_DESC_BASE<"auipc", GPR32Opnd>;
+class ALUIPC_DESC : ALUIPC_DESC_BASE<"aluipc", GPR32Opnd, II_ALUIPC>;
+class AUIPC_DESC : ALUIPC_DESC_BASE<"auipc", GPR32Opnd, II_AUIPC>;
-class AUI_DESC_BASE<string instr_asm, RegisterOperand GPROpnd>
- : MipsR6Arch<instr_asm> {
+class AUI_DESC_BASE<string instr_asm, RegisterOperand GPROpnd,
+ InstrItinClass itin = NoItinerary>
+ : MipsR6Arch<instr_asm> {
dag OutOperandList = (outs GPROpnd:$rs);
dag InOperandList = (ins GPROpnd:$rt, simm16:$imm);
string AsmString = !strconcat(instr_asm, "\t$rs, $rt, $imm");
list<dag> Pattern = [];
+ InstrItinClass Itinerary = itin;
}
-class AUI_DESC : AUI_DESC_BASE<"aui", GPR32Opnd>;
+class AUI_DESC : AUI_DESC_BASE<"aui", GPR32Opnd, II_AUI>;
class BRANCH_DESC_BASE {
bit isBranch = 1;
bit isTerminator = 1;
bit hasDelaySlot = 0;
+ bit isCTI = 1;
}
class BC_DESC_BASE<string instr_asm, DAGOperand opnd> : BRANCH_DESC_BASE,
@@ -299,22 +337,32 @@ class BC_DESC_BASE<string instr_asm, DAGOperand opnd> : BRANCH_DESC_BASE,
dag OutOperandList = (outs);
string AsmString = !strconcat(instr_asm, "\t$offset");
bit isBarrier = 1;
+ InstrItinClass Itinerary = II_BC;
+ bit isCTI = 1;
}
class CMP_BC_DESC_BASE<string instr_asm, DAGOperand opnd,
- RegisterOperand GPROpnd> : BRANCH_DESC_BASE {
+ RegisterOperand GPROpnd> : BRANCH_DESC_BASE,
+ MipsR6Arch<instr_asm> {
dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt, opnd:$offset);
dag OutOperandList = (outs);
string AsmString = !strconcat(instr_asm, "\t$rs, $rt, $offset");
list<Register> Defs = [AT];
+ InstrItinClass Itinerary = II_BCCC;
+ bit hasForbiddenSlot = 1;
+ bit isCTI = 1;
}
class CMP_CBR_EQNE_Z_DESC_BASE<string instr_asm, DAGOperand opnd,
- RegisterOperand GPROpnd> : BRANCH_DESC_BASE {
+ RegisterOperand GPROpnd>
+ : BRANCH_DESC_BASE, MipsR6Arch<instr_asm> {
dag InOperandList = (ins GPROpnd:$rs, opnd:$offset);
dag OutOperandList = (outs);
string AsmString = !strconcat(instr_asm, "\t$rs, $offset");
list<Register> Defs = [AT];
+ InstrItinClass Itinerary = II_BCCZC;
+ bit hasForbiddenSlot = 1;
+ bit isCTI = 1;
}
class CMP_CBR_RT_Z_DESC_BASE<string instr_asm, DAGOperand opnd,
@@ -324,17 +372,23 @@ class CMP_CBR_RT_Z_DESC_BASE<string instr_asm, DAGOperand opnd,
dag OutOperandList = (outs);
string AsmString = !strconcat(instr_asm, "\t$rt, $offset");
list<Register> Defs = [AT];
+ InstrItinClass Itinerary = II_BCCZC;
+ bit hasForbiddenSlot = 1;
+ bit isCTI = 1;
}
class BAL_DESC : BC_DESC_BASE<"bal", brtarget> {
bit isCall = 1;
bit hasDelaySlot = 1;
list<Register> Defs = [RA];
+ bit isCTI = 1;
}
class BALC_DESC : BC_DESC_BASE<"balc", brtarget26> {
bit isCall = 1;
list<Register> Defs = [RA];
+ InstrItinClass Itinerary = II_BALC;
+ bit isCTI = 1;
}
class BC_DESC : BC_DESC_BASE<"bc", brtarget26>;
@@ -360,6 +414,7 @@ class COP1_BCCZ_DESC_BASE<string instr_asm> : BRANCH_DESC_BASE {
dag OutOperandList = (outs);
string AsmString = instr_asm;
bit hasDelaySlot = 1;
+ InstrItinClass Itinerary = II_BC1CCZ;
}
class BC1EQZ_DESC : COP1_BCCZ_DESC_BASE<"bc1eqz $ft, $offset">;
@@ -370,6 +425,7 @@ class COP2_BCCZ_DESC_BASE<string instr_asm> : BRANCH_DESC_BASE {
dag OutOperandList = (outs);
string AsmString = instr_asm;
bit hasDelaySlot = 1;
+ bit isCTI = 1;
}
class BC2EQZ_DESC : COP2_BCCZ_DESC_BASE<"bc2eqz $ct, $offset">;
@@ -379,23 +435,29 @@ class BOVC_DESC : CMP_BC_DESC_BASE<"bovc", brtarget, GPR32Opnd>;
class BNVC_DESC : CMP_BC_DESC_BASE<"bnvc", brtarget, GPR32Opnd>;
class JMP_IDX_COMPACT_DESC_BASE<string opstr, DAGOperand opnd,
- RegisterOperand GPROpnd>
+ RegisterOperand GPROpnd,
+ InstrItinClass itin = NoItinerary>
: MipsR6Arch<opstr> {
dag InOperandList = (ins GPROpnd:$rt, opnd:$offset);
string AsmString = !strconcat(opstr, "\t$rt, $offset");
list<dag> Pattern = [];
- bit isTerminator = 1;
bit hasDelaySlot = 0;
+ InstrItinClass Itinerary = itin;
+ bit isCTI = 1;
+ bit isBranch = 1;
+ bit isIndirectBranch = 1;
}
class JIALC_DESC : JMP_IDX_COMPACT_DESC_BASE<"jialc", calloffset16,
- GPR32Opnd> {
+ GPR32Opnd, II_JIALC> {
bit isCall = 1;
list<Register> Defs = [RA];
}
-class JIC_DESC : JMP_IDX_COMPACT_DESC_BASE<"jic", jmpoffset16, GPR32Opnd> {
+class JIC_DESC : JMP_IDX_COMPACT_DESC_BASE<"jic", jmpoffset16,
+ GPR32Opnd, II_JIALC> {
bit isBarrier = 1;
+ bit isTerminator = 1;
list<Register> Defs = [AT];
}
@@ -405,35 +467,39 @@ class JR_HB_R6_DESC : JR_HB_DESC_BASE<"jr.hb", GPR32Opnd> {
bit hasDelaySlot = 1;
bit isTerminator=1;
bit isBarrier=1;
+ bit isCTI = 1;
}
-class BITSWAP_DESC_BASE<string instr_asm, RegisterOperand GPROpnd>
+class BITSWAP_DESC_BASE<string instr_asm, RegisterOperand GPROpnd,
+ InstrItinClass itin>
: MipsR6Arch<instr_asm> {
dag OutOperandList = (outs GPROpnd:$rd);
dag InOperandList = (ins GPROpnd:$rt);
string AsmString = !strconcat(instr_asm, "\t$rd, $rt");
list<dag> Pattern = [];
+ InstrItinClass Itinerary = itin;
}
-class BITSWAP_DESC : BITSWAP_DESC_BASE<"bitswap", GPR32Opnd>;
+class BITSWAP_DESC : BITSWAP_DESC_BASE<"bitswap", GPR32Opnd, II_BITSWAP>;
class DIVMOD_DESC_BASE<string instr_asm, RegisterOperand GPROpnd,
+ InstrItinClass itin,
SDPatternOperator Op=null_frag>
: MipsR6Arch<instr_asm> {
dag OutOperandList = (outs GPROpnd:$rd);
dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt);
string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt");
list<dag> Pattern = [(set GPROpnd:$rd, (Op GPROpnd:$rs, GPROpnd:$rt))];
-
+ InstrItinClass Itinerary = itin;
// This instruction doesn't trap division by zero itself. We must insert
// teq instructions as well.
bit usesCustomInserter = 1;
}
-class DIV_DESC : DIVMOD_DESC_BASE<"div", GPR32Opnd, sdiv>;
-class DIVU_DESC : DIVMOD_DESC_BASE<"divu", GPR32Opnd, udiv>;
-class MOD_DESC : DIVMOD_DESC_BASE<"mod", GPR32Opnd, srem>;
-class MODU_DESC : DIVMOD_DESC_BASE<"modu", GPR32Opnd, urem>;
+class DIV_DESC : DIVMOD_DESC_BASE<"div", GPR32Opnd, II_DIV, sdiv>;
+class DIVU_DESC : DIVMOD_DESC_BASE<"divu", GPR32Opnd, II_DIVU, udiv>;
+class MOD_DESC : DIVMOD_DESC_BASE<"mod", GPR32Opnd, II_MOD, srem>;
+class MODU_DESC : DIVMOD_DESC_BASE<"modu", GPR32Opnd, II_MODU, urem>;
class BEQZALC_DESC : CMP_CBR_RT_Z_DESC_BASE<"beqzalc", brtarget, GPR32Opnd> {
list<Register> Defs = [RA];
@@ -460,17 +526,19 @@ class BNEZALC_DESC : CMP_CBR_RT_Z_DESC_BASE<"bnezalc", brtarget, GPR32Opnd> {
}
class MUL_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd,
+ InstrItinClass itin,
SDPatternOperator Op=null_frag> : MipsR6Arch<instr_asm> {
dag OutOperandList = (outs GPROpnd:$rd);
dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt);
string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt");
list<dag> Pattern = [(set GPROpnd:$rd, (Op GPROpnd:$rs, GPROpnd:$rt))];
+ InstrItinClass Itinerary = itin;
}
-class MUH_DESC : MUL_R6_DESC_BASE<"muh", GPR32Opnd, mulhs>;
-class MUHU_DESC : MUL_R6_DESC_BASE<"muhu", GPR32Opnd, mulhu>;
-class MUL_R6_DESC : MUL_R6_DESC_BASE<"mul", GPR32Opnd, mul>;
-class MULU_DESC : MUL_R6_DESC_BASE<"mulu", GPR32Opnd>;
+class MUH_DESC : MUL_R6_DESC_BASE<"muh", GPR32Opnd, II_MUH, mulhs>;
+class MUHU_DESC : MUL_R6_DESC_BASE<"muhu", GPR32Opnd, II_MUHU, mulhu>;
+class MUL_R6_DESC : MUL_R6_DESC_BASE<"mul", GPR32Opnd, II_MUL, mul>;
+class MULU_DESC : MUL_R6_DESC_BASE<"mulu", GPR32Opnd, II_MULU>;
class COP1_SEL_DESC_BASE<string instr_asm, RegisterOperand FGROpnd> {
dag OutOperandList = (outs FGROpnd:$fd);
@@ -482,11 +550,11 @@ class COP1_SEL_DESC_BASE<string instr_asm, RegisterOperand FGROpnd> {
string Constraints = "$fd_in = $fd";
}
-class SEL_D_DESC : COP1_SEL_DESC_BASE<"sel.d", FGR64Opnd> {
+class SEL_D_DESC : COP1_SEL_DESC_BASE<"sel.d", FGR64Opnd>, MipsR6Arch<"sel.d"> {
// We must insert a SUBREG_TO_REG around $fd_in
bit usesCustomInserter = 1;
}
-class SEL_S_DESC : COP1_SEL_DESC_BASE<"sel.s", FGR32Opnd>;
+class SEL_S_DESC : COP1_SEL_DESC_BASE<"sel.s", FGR32Opnd>, MipsR6Arch<"sel.s">;
class SELEQNE_Z_DESC_BASE<string instr_asm, RegisterOperand GPROpnd>
: MipsR6Arch<instr_asm> {
@@ -494,23 +562,26 @@ class SELEQNE_Z_DESC_BASE<string instr_asm, RegisterOperand GPROpnd>
dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt);
string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt");
list<dag> Pattern = [];
+ InstrItinClass Itinerary = II_SELCCZ;
}
class SELEQZ_DESC : SELEQNE_Z_DESC_BASE<"seleqz", GPR32Opnd>;
class SELNEZ_DESC : SELEQNE_Z_DESC_BASE<"selnez", GPR32Opnd>;
-class COP1_4R_DESC_BASE<string instr_asm, RegisterOperand FGROpnd> {
+class COP1_4R_DESC_BASE<string instr_asm, RegisterOperand FGROpnd,
+ InstrItinClass itin = NoItinerary> {
dag OutOperandList = (outs FGROpnd:$fd);
dag InOperandList = (ins FGROpnd:$fd_in, FGROpnd:$fs, FGROpnd:$ft);
string AsmString = !strconcat(instr_asm, "\t$fd, $fs, $ft");
list<dag> Pattern = [];
string Constraints = "$fd_in = $fd";
+ InstrItinClass Itinerary = itin;
}
-class MADDF_S_DESC : COP1_4R_DESC_BASE<"maddf.s", FGR32Opnd>;
-class MADDF_D_DESC : COP1_4R_DESC_BASE<"maddf.d", FGR64Opnd>;
-class MSUBF_S_DESC : COP1_4R_DESC_BASE<"msubf.s", FGR32Opnd>;
-class MSUBF_D_DESC : COP1_4R_DESC_BASE<"msubf.d", FGR64Opnd>;
+class MADDF_S_DESC : COP1_4R_DESC_BASE<"maddf.s", FGR32Opnd, II_MADDF_S>;
+class MADDF_D_DESC : COP1_4R_DESC_BASE<"maddf.d", FGR64Opnd, II_MADDF_D>;
+class MSUBF_S_DESC : COP1_4R_DESC_BASE<"msubf.s", FGR32Opnd, II_MSUBF_S>;
+class MSUBF_D_DESC : COP1_4R_DESC_BASE<"msubf.d", FGR64Opnd, II_MSUBF_D>;
class MAX_MIN_DESC_BASE<string instr_asm, RegisterOperand FGROpnd> {
dag OutOperandList = (outs FGROpnd:$fd);
@@ -536,10 +607,14 @@ class SELEQNEZ_DESC_BASE<string instr_asm, RegisterOperand FGROpnd> {
list<dag> Pattern = [];
}
-class SELEQZ_S_DESC : SELEQNEZ_DESC_BASE<"seleqz.s", FGR32Opnd>;
-class SELEQZ_D_DESC : SELEQNEZ_DESC_BASE<"seleqz.d", FGR64Opnd>;
-class SELNEZ_S_DESC : SELEQNEZ_DESC_BASE<"selnez.s", FGR32Opnd>;
-class SELNEZ_D_DESC : SELEQNEZ_DESC_BASE<"selnez.d", FGR64Opnd>;
+class SELEQZ_S_DESC : SELEQNEZ_DESC_BASE<"seleqz.s", FGR32Opnd>,
+ MipsR6Arch<"seleqz.s">;
+class SELEQZ_D_DESC : SELEQNEZ_DESC_BASE<"seleqz.d", FGR64Opnd>,
+ MipsR6Arch<"seleqz.d">;
+class SELNEZ_S_DESC : SELEQNEZ_DESC_BASE<"selnez.s", FGR32Opnd>,
+ MipsR6Arch<"selnez.s">;
+class SELNEZ_D_DESC : SELEQNEZ_DESC_BASE<"selnez.d", FGR64Opnd>,
+ MipsR6Arch<"selnez.d">;
class CLASS_RINT_DESC_BASE<string instr_asm, RegisterOperand FGROpnd> {
dag OutOperandList = (outs FGROpnd:$fd);
@@ -590,61 +665,73 @@ class SDC2_R6_DESC : COP2ST_DESC_BASE<"sdc2", COP2Opnd>;
class SWC2_R6_DESC : COP2ST_DESC_BASE<"swc2", COP2Opnd>;
class LSA_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd,
- Operand ImmOpnd> : MipsR6Arch<instr_asm> {
+ Operand ImmOpnd, InstrItinClass itin>
+ : MipsR6Arch<instr_asm> {
dag OutOperandList = (outs GPROpnd:$rd);
dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt, ImmOpnd:$imm2);
string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt, $imm2");
list<dag> Pattern = [];
+ InstrItinClass Itinerary = itin;
}
-class LSA_R6_DESC : LSA_R6_DESC_BASE<"lsa", GPR32Opnd, uimm2_plus1>;
+class LSA_R6_DESC : LSA_R6_DESC_BASE<"lsa", GPR32Opnd, uimm2_plus1, II_LSA>;
-class LL_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> {
+class LL_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd,
+ Operand MemOpnd, InstrItinClass itin>
+ : MipsR6Arch<instr_asm> {
dag OutOperandList = (outs GPROpnd:$rt);
- dag InOperandList = (ins mem_simm9:$addr);
+ dag InOperandList = (ins MemOpnd:$addr);
string AsmString = !strconcat(instr_asm, "\t$rt, $addr");
list<dag> Pattern = [];
bit mayLoad = 1;
+ InstrItinClass Itinerary = itin;
}
-class LL_R6_DESC : LL_R6_DESC_BASE<"ll", GPR32Opnd>;
+class LL_R6_DESC : LL_R6_DESC_BASE<"ll", GPR32Opnd, mem_simm9, II_LL>;
-class SC_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> {
+class SC_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd,
+ InstrItinClass itin> {
dag OutOperandList = (outs GPROpnd:$dst);
dag InOperandList = (ins GPROpnd:$rt, mem_simm9:$addr);
string AsmString = !strconcat(instr_asm, "\t$rt, $addr");
list<dag> Pattern = [];
bit mayStore = 1;
string Constraints = "$rt = $dst";
+ InstrItinClass Itinerary = itin;
}
-class SC_R6_DESC : SC_R6_DESC_BASE<"sc", GPR32Opnd>;
+class SC_R6_DESC : SC_R6_DESC_BASE<"sc", GPR32Opnd, II_SC>;
-class CLO_CLZ_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd>
+class CLO_CLZ_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd,
+ InstrItinClass itin>
: MipsR6Arch<instr_asm> {
dag OutOperandList = (outs GPROpnd:$rd);
dag InOperandList = (ins GPROpnd:$rs);
string AsmString = !strconcat(instr_asm, "\t$rd, $rs");
+ InstrItinClass Itinerary = itin;
}
-class CLO_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> :
- CLO_CLZ_R6_DESC_BASE<instr_asm, GPROpnd> {
+class CLO_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd,
+ InstrItinClass itin> :
+ CLO_CLZ_R6_DESC_BASE<instr_asm, GPROpnd, itin> {
list<dag> Pattern = [(set GPROpnd:$rd, (ctlz (not GPROpnd:$rs)))];
}
-class CLZ_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> :
- CLO_CLZ_R6_DESC_BASE<instr_asm, GPROpnd> {
+class CLZ_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd,
+ InstrItinClass itin> :
+ CLO_CLZ_R6_DESC_BASE<instr_asm, GPROpnd, itin> {
list<dag> Pattern = [(set GPROpnd:$rd, (ctlz GPROpnd:$rs))];
}
-class CLO_R6_DESC : CLO_R6_DESC_BASE<"clo", GPR32Opnd>;
-class CLZ_R6_DESC : CLZ_R6_DESC_BASE<"clz", GPR32Opnd>;
+class CLO_R6_DESC : CLO_R6_DESC_BASE<"clo", GPR32Opnd, II_CLO>;
+class CLZ_R6_DESC : CLZ_R6_DESC_BASE<"clz", GPR32Opnd, II_CLZ>;
class SDBBP_R6_DESC {
dag OutOperandList = (outs);
dag InOperandList = (ins uimm20:$code_);
string AsmString = "sdbbp\t$code_";
list<dag> Pattern = [];
+ bit isCTI = 1;
}
//===----------------------------------------------------------------------===//
@@ -660,16 +747,18 @@ def AUI : R6MMR6Rel, AUI_ENC, AUI_DESC, ISA_MIPS32R6;
def AUIPC : R6MMR6Rel, AUIPC_ENC, AUIPC_DESC, ISA_MIPS32R6;
def BAL : BAL_ENC, BAL_DESC, ISA_MIPS32R6;
def BALC : R6MMR6Rel, BALC_ENC, BALC_DESC, ISA_MIPS32R6;
-def BC1EQZ : BC1EQZ_ENC, BC1EQZ_DESC, ISA_MIPS32R6, HARDFLOAT;
-def BC1NEZ : BC1NEZ_ENC, BC1NEZ_DESC, ISA_MIPS32R6, HARDFLOAT;
-def BC2EQZ : BC2EQZ_ENC, BC2EQZ_DESC, ISA_MIPS32R6;
-def BC2NEZ : BC2NEZ_ENC, BC2NEZ_DESC, ISA_MIPS32R6;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def BC1EQZ : BC1EQZ_ENC, BC1EQZ_DESC, ISA_MIPS32R6, HARDFLOAT;
+ def BC1NEZ : BC1NEZ_ENC, BC1NEZ_DESC, ISA_MIPS32R6, HARDFLOAT;
+ def BC2EQZ : BC2EQZ_ENC, BC2EQZ_DESC, ISA_MIPS32R6;
+ def BC2NEZ : BC2NEZ_ENC, BC2NEZ_DESC, ISA_MIPS32R6;
+}
def BC : R6MMR6Rel, BC_ENC, BC_DESC, ISA_MIPS32R6;
-def BEQC : BEQC_ENC, BEQC_DESC, ISA_MIPS32R6;
+def BEQC : R6MMR6Rel, BEQC_ENC, BEQC_DESC, ISA_MIPS32R6;
def BEQZALC : R6MMR6Rel, BEQZALC_ENC, BEQZALC_DESC, ISA_MIPS32R6;
-def BEQZC : BEQZC_ENC, BEQZC_DESC, ISA_MIPS32R6;
-def BGEC : BGEC_ENC, BGEC_DESC, ISA_MIPS32R6;
-def BGEUC : BGEUC_ENC, BGEUC_DESC, ISA_MIPS32R6;
+def BEQZC : R6MMR6Rel, BEQZC_ENC, BEQZC_DESC, ISA_MIPS32R6;
+def BGEC : R6MMR6Rel, BGEC_ENC, BGEC_DESC, ISA_MIPS32R6;
+def BGEUC : R6MMR6Rel, BGEUC_ENC, BGEUC_DESC, ISA_MIPS32R6;
def BGEZALC : R6MMR6Rel, BGEZALC_ENC, BGEZALC_DESC, ISA_MIPS32R6;
def BGEZC : BGEZC_ENC, BGEZC_DESC, ISA_MIPS32R6;
def BGTZALC : R6MMR6Rel, BGTZALC_ENC, BGTZALC_DESC, ISA_MIPS32R6;
@@ -677,15 +766,17 @@ def BGTZC : BGTZC_ENC, BGTZC_DESC, ISA_MIPS32R6;
def BITSWAP : R6MMR6Rel, BITSWAP_ENC, BITSWAP_DESC, ISA_MIPS32R6;
def BLEZALC : R6MMR6Rel, BLEZALC_ENC, BLEZALC_DESC, ISA_MIPS32R6;
def BLEZC : BLEZC_ENC, BLEZC_DESC, ISA_MIPS32R6;
-def BLTC : BLTC_ENC, BLTC_DESC, ISA_MIPS32R6;
-def BLTUC : BLTUC_ENC, BLTUC_DESC, ISA_MIPS32R6;
+def BLTC : R6MMR6Rel, BLTC_ENC, BLTC_DESC, ISA_MIPS32R6;
+def BLTUC : R6MMR6Rel, BLTUC_ENC, BLTUC_DESC, ISA_MIPS32R6;
def BLTZALC : R6MMR6Rel, BLTZALC_ENC, BLTZALC_DESC, ISA_MIPS32R6;
def BLTZC : BLTZC_ENC, BLTZC_DESC, ISA_MIPS32R6;
-def BNEC : BNEC_ENC, BNEC_DESC, ISA_MIPS32R6;
+def BNEC : R6MMR6Rel, BNEC_ENC, BNEC_DESC, ISA_MIPS32R6;
def BNEZALC : R6MMR6Rel, BNEZALC_ENC, BNEZALC_DESC, ISA_MIPS32R6;
-def BNEZC : BNEZC_ENC, BNEZC_DESC, ISA_MIPS32R6;
-def BNVC : BNVC_ENC, BNVC_DESC, ISA_MIPS32R6;
-def BOVC : BOVC_ENC, BOVC_DESC, ISA_MIPS32R6;
+def BNEZC : R6MMR6Rel, BNEZC_ENC, BNEZC_DESC, ISA_MIPS32R6;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def BNVC : R6MMR6Rel, BNVC_ENC, BNVC_DESC, ISA_MIPS32R6;
+ def BOVC : R6MMR6Rel, BOVC_ENC, BOVC_DESC, ISA_MIPS32R6;
+}
def CACHE_R6 : R6MMR6Rel, CACHE_ENC, CACHE_DESC, ISA_MIPS32R6;
let AdditionalPredicates = [NotInMicroMips] in {
def CLASS_D : CLASS_D_ENC, CLASS_D_DESC, ISA_MIPS32R6, HARDFLOAT;
@@ -695,15 +786,21 @@ def CLO_R6 : R6MMR6Rel, CLO_R6_ENC, CLO_R6_DESC, ISA_MIPS32R6;
def CLZ_R6 : R6MMR6Rel, CLZ_R6_ENC, CLZ_R6_DESC, ISA_MIPS32R6;
defm S : CMP_CC_M<FIELD_CMP_FORMAT_S, "s", FGR32Opnd>;
defm D : CMP_CC_M<FIELD_CMP_FORMAT_D, "d", FGR64Opnd>;
-def DIV : R6MMR6Rel, DIV_ENC, DIV_DESC, ISA_MIPS32R6;
-def DIVU : R6MMR6Rel, DIVU_ENC, DIVU_DESC, ISA_MIPS32R6;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def DIV : R6MMR6Rel, DIV_ENC, DIV_DESC, ISA_MIPS32R6;
+ def DIVU : R6MMR6Rel, DIVU_ENC, DIVU_DESC, ISA_MIPS32R6;
+}
def JIALC : R6MMR6Rel, JIALC_ENC, JIALC_DESC, ISA_MIPS32R6;
def JIC : R6MMR6Rel, JIC_ENC, JIC_DESC, ISA_MIPS32R6;
def JR_HB_R6 : JR_HB_R6_ENC, JR_HB_R6_DESC, ISA_MIPS32R6;
-def LDC2_R6 : LDC2_R6_ENC, LDC2_R6_DESC, ISA_MIPS32R6;
-def LL_R6 : LL_R6_ENC, LL_R6_DESC, ISA_MIPS32R6;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def LDC2_R6 : LDC2_R6_ENC, LDC2_R6_DESC, ISA_MIPS32R6;
+ def LL_R6 : LL_R6_ENC, LL_R6_DESC, PTR_32, ISA_MIPS32R6;
+}
def LSA_R6 : R6MMR6Rel, LSA_R6_ENC, LSA_R6_DESC, ISA_MIPS32R6;
-def LWC2_R6 : LWC2_R6_ENC, LWC2_R6_DESC, ISA_MIPS32R6;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def LWC2_R6 : LWC2_R6_ENC, LWC2_R6_DESC, ISA_MIPS32R6;
+}
def LWPC : R6MMR6Rel, LWPC_ENC, LWPC_DESC, ISA_MIPS32R6;
def LWUPC : LWUPC_ENC, LWUPC_DESC, ISA_MIPS32R6;
let AdditionalPredicates = [NotInMicroMips] in {
@@ -717,41 +814,40 @@ let AdditionalPredicates = [NotInMicroMips] in {
def MINA_S : MINA_S_ENC, MINA_S_DESC, ISA_MIPS32R6, HARDFLOAT;
def MIN_D : MIN_D_ENC, MIN_D_DESC, ISA_MIPS32R6, HARDFLOAT;
def MIN_S : MIN_S_ENC, MIN_S_DESC, ISA_MIPS32R6, HARDFLOAT;
-}
-def MOD : R6MMR6Rel, MOD_ENC, MOD_DESC, ISA_MIPS32R6;
-def MODU : R6MMR6Rel, MODU_ENC, MODU_DESC, ISA_MIPS32R6;
-let AdditionalPredicates = [NotInMicroMips] in {
+
+ def MOD : R6MMR6Rel, MOD_ENC, MOD_DESC, ISA_MIPS32R6;
+ def MODU : R6MMR6Rel, MODU_ENC, MODU_DESC, ISA_MIPS32R6;
+
def MSUBF_S : MSUBF_S_ENC, MSUBF_S_DESC, ISA_MIPS32R6, HARDFLOAT;
def MSUBF_D : MSUBF_D_ENC, MSUBF_D_DESC, ISA_MIPS32R6, HARDFLOAT;
+
+ def MUH : R6MMR6Rel, MUH_ENC, MUH_DESC, ISA_MIPS32R6;
+ def MUHU : R6MMR6Rel, MUHU_ENC, MUHU_DESC, ISA_MIPS32R6;
+ def MUL_R6 : R6MMR6Rel, MUL_R6_ENC, MUL_R6_DESC, ISA_MIPS32R6;
+ def MULU : R6MMR6Rel, MULU_ENC, MULU_DESC, ISA_MIPS32R6;
}
-def MUH : R6MMR6Rel, MUH_ENC, MUH_DESC, ISA_MIPS32R6;
-def MUHU : R6MMR6Rel, MUHU_ENC, MUHU_DESC, ISA_MIPS32R6;
-def MUL_R6 : R6MMR6Rel, MUL_R6_ENC, MUL_R6_DESC, ISA_MIPS32R6;
-def MULU : R6MMR6Rel, MULU_ENC, MULU_DESC, ISA_MIPS32R6;
def NAL; // BAL with rd=0
def PREF_R6 : R6MMR6Rel, PREF_ENC, PREF_DESC, ISA_MIPS32R6;
let AdditionalPredicates = [NotInMicroMips] in {
def RINT_D : RINT_D_ENC, RINT_D_DESC, ISA_MIPS32R6, HARDFLOAT;
def RINT_S : RINT_S_ENC, RINT_S_DESC, ISA_MIPS32R6, HARDFLOAT;
+ def SC_R6 : SC_R6_ENC, SC_R6_DESC, PTR_32, ISA_MIPS32R6;
+ def SDBBP_R6 : SDBBP_R6_ENC, SDBBP_R6_DESC, ISA_MIPS32R6;
+ def SELEQZ : R6MMR6Rel, SELEQZ_ENC, SELEQZ_DESC, ISA_MIPS32R6, GPR_32;
+ def SELNEZ : R6MMR6Rel, SELNEZ_ENC, SELNEZ_DESC, ISA_MIPS32R6, GPR_32;
+ def SELEQZ_D : R6MMR6Rel, SELEQZ_D_ENC, SELEQZ_D_DESC, ISA_MIPS32R6,
+ HARDFLOAT;
+ def SELEQZ_S : R6MMR6Rel, SELEQZ_S_ENC, SELEQZ_S_DESC, ISA_MIPS32R6,
+ HARDFLOAT;
+ def SELNEZ_D : R6MMR6Rel, SELNEZ_D_ENC, SELNEZ_D_DESC, ISA_MIPS32R6,
+ HARDFLOAT;
+ def SELNEZ_S : R6MMR6Rel, SELNEZ_S_ENC, SELNEZ_S_DESC, ISA_MIPS32R6,
+ HARDFLOAT;
+ def SEL_D : R6MMR6Rel, SEL_D_ENC, SEL_D_DESC, ISA_MIPS32R6, HARDFLOAT;
+ def SEL_S : R6MMR6Rel, SEL_S_ENC, SEL_S_DESC, ISA_MIPS32R6, HARDFLOAT;
+ def SDC2_R6 : SDC2_R6_ENC, SDC2_R6_DESC, ISA_MIPS32R6;
+ def SWC2_R6 : SWC2_R6_ENC, SWC2_R6_DESC, ISA_MIPS32R6;
}
-def SC_R6 : SC_R6_ENC, SC_R6_DESC, ISA_MIPS32R6;
-let AdditionalPredicates = [NotInMicroMips] in {
-def SDBBP_R6 : SDBBP_R6_ENC, SDBBP_R6_DESC, ISA_MIPS32R6;
-}
-def SDC2_R6 : SDC2_R6_ENC, SDC2_R6_DESC, ISA_MIPS32R6;
-def SELEQZ : R6MMR6Rel, SELEQZ_ENC, SELEQZ_DESC, ISA_MIPS32R6, GPR_32;
-let AdditionalPredicates = [NotInMicroMips] in {
- def SELEQZ_D : SELEQZ_D_ENC, SELEQZ_D_DESC, ISA_MIPS32R6, HARDFLOAT;
- def SELEQZ_S : SELEQZ_S_ENC, SELEQZ_S_DESC, ISA_MIPS32R6, HARDFLOAT;
-}
-def SELNEZ : R6MMR6Rel, SELNEZ_ENC, SELNEZ_DESC, ISA_MIPS32R6, GPR_32;
-let AdditionalPredicates = [NotInMicroMips] in {
- def SELNEZ_D : SELNEZ_D_ENC, SELNEZ_D_DESC, ISA_MIPS32R6, HARDFLOAT;
- def SELNEZ_S : SELNEZ_S_ENC, SELNEZ_S_DESC, ISA_MIPS32R6, HARDFLOAT;
- def SEL_D : SEL_D_ENC, SEL_D_DESC, ISA_MIPS32R6, HARDFLOAT;
- def SEL_S : SEL_S_ENC, SEL_S_DESC, ISA_MIPS32R6, HARDFLOAT;
-}
-def SWC2_R6 : SWC2_R6_ENC, SWC2_R6_DESC, ISA_MIPS32R6;
//===----------------------------------------------------------------------===//
//
@@ -761,9 +857,14 @@ def SWC2_R6 : SWC2_R6_ENC, SWC2_R6_DESC, ISA_MIPS32R6;
let AdditionalPredicates = [NotInMicroMips] in {
def : MipsInstAlias<"sdbbp", (SDBBP_R6 0)>, ISA_MIPS32R6;
+def : MipsInstAlias<"jr $rs", (JALR ZERO, GPR32Opnd:$rs), 1>, ISA_MIPS32R6, GPR_32;
}
-def : MipsInstAlias<"jr $rs", (JALR ZERO, GPR32Opnd:$rs), 1>, ISA_MIPS32R6;
+def : MipsInstAlias<"jrc $rs", (JIC GPR32Opnd:$rs, 0), 1>, ISA_MIPS32R6, GPR_32;
+
+let AdditionalPredicates = [NotInMicroMips] in {
+def : MipsInstAlias<"jalrc $rs", (JIALC GPR32Opnd:$rs, 0), 1>, ISA_MIPS32R6, GPR_32;
+}
//===----------------------------------------------------------------------===//
//
// Patterns and Pseudo Instructions
@@ -792,8 +893,10 @@ def : MipsPat<(setne VT:$lhs, VT:$rhs),
(NOROp (!cast<Instruction>("CMP_EQ_"#NAME) VT:$lhs, VT:$rhs), ZEROReg)>;
}
-defm S : Cmp_Pats<f32, NOR, ZERO>, ISA_MIPS32R6;
-defm D : Cmp_Pats<f64, NOR, ZERO>, ISA_MIPS32R6;
+let AdditionalPredicates = [NotInMicroMips] in {
+ defm S : Cmp_Pats<f32, NOR, ZERO>, ISA_MIPS32R6;
+ defm D : Cmp_Pats<f64, NOR, ZERO>, ISA_MIPS32R6;
+}
// i32 selects
multiclass SelectInt_Pats<ValueType RC, Instruction OROp, Instruction XORiOp,
@@ -832,6 +935,7 @@ def : MipsPat<(select (Opg (setne RC:$cond, immz)), immz, RC:$f),
(SELEQZOp RC:$f, RC:$cond)>;
}
+let AdditionalPredicates = [NotInMicroMips] in {
defm : SelectInt_Pats<i32, OR, XORi, SLTi, SLTiu, SELEQZ, SELNEZ,
immZExt16, i32>, ISA_MIPS32R6;
@@ -845,3 +949,4 @@ def : MipsPat<(select i32:$cond, i32:$t, immz),
def : MipsPat<(select i32:$cond, immz, i32:$f),
(SELEQZ i32:$f, i32:$cond)>,
ISA_MIPS32R6;
+}
diff --git a/lib/Target/Mips/Mips64InstrInfo.td b/lib/Target/Mips/Mips64InstrInfo.td
index cbdcdd788bec7..88cfec5bc13c1 100644
--- a/lib/Target/Mips/Mips64InstrInfo.td
+++ b/lib/Target/Mips/Mips64InstrInfo.td
@@ -15,14 +15,6 @@
// Mips Operand, Complex Patterns and Transformations Definitions.
//===----------------------------------------------------------------------===//
-// Unsigned Operand
-def uimm16_64 : Operand<i64> {
- let PrintMethod = "printUnsignedImm";
-}
-
-// Signed Operand
-def simm10_64 : Operand<i64>;
-
// Transformation Function - get Imm - 32.
def Subtract32 : SDNodeXForm<imm, [{
return getImm(N, (unsigned)N->getZExtValue() - 32);
@@ -37,7 +29,7 @@ def immSExt10_64 : PatLeaf<(i64 imm),
[{ return isInt<10>(N->getSExtValue()); }]>;
def immZExt16_64 : PatLeaf<(i64 imm),
- [{ return isInt<16>(N->getZExtValue()); }]>;
+ [{ return isUInt<16>(N->getZExtValue()); }]>;
def immZExt5_64 : ImmLeaf<i64, [{ return Imm == (Imm & 0x1f); }]>;
@@ -71,6 +63,10 @@ def PowerOf2HI : PatLeaf<(imm), [{
return false;
}]>;
+def assertzext_lt_i32 : PatFrag<(ops node:$src), (assertzext node:$src), [{
+ return cast<VTSDNode>(N->getOperand(1))->getVT().bitsLT(MVT::i32);
+}]>;
+
//===----------------------------------------------------------------------===//
// Instructions specific format
//===----------------------------------------------------------------------===//
@@ -86,7 +82,7 @@ let usesCustomInserter = 1 in {
}
/// Pseudo instructions for loading and storing accumulator registers.
-let isPseudo = 1, isCodeGenOnly = 1 in {
+let isPseudo = 1, isCodeGenOnly = 1, hasNoSchedulingInfo = 1 in {
def LOAD_ACC128 : Load<"", ACC128>;
def STORE_ACC128 : Store<"", ACC128>;
}
@@ -96,11 +92,13 @@ let isPseudo = 1, isCodeGenOnly = 1 in {
//===----------------------------------------------------------------------===//
let DecoderNamespace = "Mips64" in {
/// Arithmetic Instructions (ALU Immediate)
-def DADDi : ArithLogicI<"daddi", simm16_64, GPR64Opnd>, ADDI_FM<0x18>,
- ISA_MIPS3_NOT_32R6_64R6;
-def DADDiu : ArithLogicI<"daddiu", simm16_64, GPR64Opnd, II_DADDIU,
- immSExt16, add>,
- ADDI_FM<0x19>, IsAsCheapAsAMove, ISA_MIPS3;
+def DADDi : ArithLogicI<"daddi", simm16_64, GPR64Opnd, II_DADDI>,
+ ADDI_FM<0x18>, ISA_MIPS3_NOT_32R6_64R6;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def DADDiu : StdMMR6Rel, ArithLogicI<"daddiu", simm16_64, GPR64Opnd,
+ II_DADDIU, immSExt16, add>,
+ ADDI_FM<0x19>, IsAsCheapAsAMove, ISA_MIPS3;
+}
let isCodeGenOnly = 1 in {
def SLTi64 : SetCC_I<"slti", setlt, simm16_64, immSExt16, GPR64Opnd>,
@@ -113,18 +111,20 @@ def ORi64 : ArithLogicI<"ori", uimm16_64, GPR64Opnd, II_OR, immZExt16, or>,
ADDI_FM<0xd>;
def XORi64 : ArithLogicI<"xori", uimm16_64, GPR64Opnd, II_XOR, immZExt16, xor>,
ADDI_FM<0xe>;
-def LUi64 : LoadUpper<"lui", GPR64Opnd, uimm16_64>, LUI_FM;
+def LUi64 : LoadUpper<"lui", GPR64Opnd, uimm16_64_relaxed>, LUI_FM;
}
/// Arithmetic Instructions (3-Operand, R-Type)
-def DADD : ArithLogicR<"dadd", GPR64Opnd, 1, II_DADD>, ADD_FM<0, 0x2c>,
- ISA_MIPS3;
-def DADDu : ArithLogicR<"daddu", GPR64Opnd, 1, II_DADDU, add>, ADD_FM<0, 0x2d>,
- ISA_MIPS3;
-def DSUBu : ArithLogicR<"dsubu", GPR64Opnd, 0, II_DSUBU, sub>, ADD_FM<0, 0x2f>,
- ISA_MIPS3;
-def DSUB : ArithLogicR<"dsub", GPR64Opnd, 0, II_DSUB>, ADD_FM<0, 0x2e>,
- ISA_MIPS3;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def DADD : StdMMR6Rel, ArithLogicR<"dadd", GPR64Opnd, 1, II_DADD>,
+ ADD_FM<0, 0x2c>, ISA_MIPS3;
+ def DADDu : StdMMR6Rel, ArithLogicR<"daddu", GPR64Opnd, 1, II_DADDU, add>,
+ ADD_FM<0, 0x2d>, ISA_MIPS3;
+ def DSUBu : StdMMR6Rel, ArithLogicR<"dsubu", GPR64Opnd, 0, II_DSUBU, sub>, ADD_FM<0, 0x2f>,
+ ISA_MIPS3;
+ def DSUB : StdMMR6Rel, ArithLogicR<"dsub", GPR64Opnd, 0, II_DSUB>, ADD_FM<0, 0x2e>,
+ ISA_MIPS3;
+}
let isCodeGenOnly = 1 in {
def SLT64 : SetCC_R<"slt", setlt, GPR64Opnd>, ADD_FM<0, 0x2a>;
@@ -136,33 +136,43 @@ def NOR64 : LogicNOR<"nor", GPR64Opnd>, ADD_FM<0, 0x27>;
}
/// Shift Instructions
-def DSLL : shift_rotate_imm<"dsll", uimm6, GPR64Opnd, II_DSLL, shl, immZExt6>,
+let AdditionalPredicates = [NotInMicroMips] in {
+ def DSLL : StdMMR6Rel, shift_rotate_imm<"dsll", uimm6, GPR64Opnd, II_DSLL,
+ shl, immZExt6>,
SRA_FM<0x38, 0>, ISA_MIPS3;
-def DSRL : shift_rotate_imm<"dsrl", uimm6, GPR64Opnd, II_DSRL, srl, immZExt6>,
+ def DSRL : StdMMR6Rel, shift_rotate_imm<"dsrl", uimm6, GPR64Opnd, II_DSRL,
+ srl, immZExt6>,
SRA_FM<0x3a, 0>, ISA_MIPS3;
-def DSRA : shift_rotate_imm<"dsra", uimm6, GPR64Opnd, II_DSRA, sra, immZExt6>,
+ def DSRA : StdMMR6Rel, shift_rotate_imm<"dsra", uimm6, GPR64Opnd, II_DSRA,
+ sra, immZExt6>,
SRA_FM<0x3b, 0>, ISA_MIPS3;
-def DSLLV : shift_rotate_reg<"dsllv", GPR64Opnd, II_DSLLV, shl>,
- SRLV_FM<0x14, 0>, ISA_MIPS3;
-def DSRLV : shift_rotate_reg<"dsrlv", GPR64Opnd, II_DSRLV, srl>,
- SRLV_FM<0x16, 0>, ISA_MIPS3;
-def DSRAV : shift_rotate_reg<"dsrav", GPR64Opnd, II_DSRAV, sra>,
- SRLV_FM<0x17, 0>, ISA_MIPS3;
-def DSLL32 : shift_rotate_imm<"dsll32", uimm5, GPR64Opnd, II_DSLL32>,
- SRA_FM<0x3c, 0>, ISA_MIPS3;
-def DSRL32 : shift_rotate_imm<"dsrl32", uimm5, GPR64Opnd, II_DSRL32>,
- SRA_FM<0x3e, 0>, ISA_MIPS3;
-def DSRA32 : shift_rotate_imm<"dsra32", uimm5, GPR64Opnd, II_DSRA32>,
- SRA_FM<0x3f, 0>, ISA_MIPS3;
+ def DSLLV : StdMMR6Rel, shift_rotate_reg<"dsllv", GPR64Opnd, II_DSLLV, shl>,
+ SRLV_FM<0x14, 0>, ISA_MIPS3;
+ def DSRAV : StdMMR6Rel, shift_rotate_reg<"dsrav", GPR64Opnd, II_DSRAV, sra>,
+ SRLV_FM<0x17, 0>, ISA_MIPS3;
+ def DSRLV : StdMMR6Rel, shift_rotate_reg<"dsrlv", GPR64Opnd, II_DSRLV, srl>,
+ SRLV_FM<0x16, 0>, ISA_MIPS3;
+ def DSLL32 : StdMMR6Rel, shift_rotate_imm<"dsll32", uimm5, GPR64Opnd,
+ II_DSLL32>,
+ SRA_FM<0x3c, 0>, ISA_MIPS3;
+ def DSRL32 : StdMMR6Rel, shift_rotate_imm<"dsrl32", uimm5, GPR64Opnd,
+ II_DSRL32>,
+ SRA_FM<0x3e, 0>, ISA_MIPS3;
+ def DSRA32 : StdMMR6Rel, shift_rotate_imm<"dsra32", uimm5, GPR64Opnd,
+ II_DSRA32>,
+ SRA_FM<0x3f, 0>, ISA_MIPS3;
// Rotate Instructions
-def DROTR : shift_rotate_imm<"drotr", uimm6, GPR64Opnd, II_DROTR, rotr,
- immZExt6>,
- SRA_FM<0x3a, 1>, ISA_MIPS64R2;
-def DROTRV : shift_rotate_reg<"drotrv", GPR64Opnd, II_DROTRV, rotr>,
- SRLV_FM<0x16, 1>, ISA_MIPS64R2;
-def DROTR32 : shift_rotate_imm<"drotr32", uimm5, GPR64Opnd, II_DROTR32>,
- SRA_FM<0x3e, 1>, ISA_MIPS64R2;
+ def DROTR : StdMMR6Rel, shift_rotate_imm<"drotr", uimm6, GPR64Opnd, II_DROTR,
+ rotr, immZExt6>,
+ SRA_FM<0x3a, 1>, ISA_MIPS64R2;
+ def DROTRV : StdMMR6Rel, shift_rotate_reg<"drotrv", GPR64Opnd, II_DROTRV,
+ rotr>,
+ SRLV_FM<0x16, 1>, ISA_MIPS64R2;
+ def DROTR32 : StdMMR6Rel, shift_rotate_imm<"drotr32", uimm5, GPR64Opnd,
+ II_DROTR32>,
+ SRA_FM<0x3e, 1>, ISA_MIPS64R2;
+}
/// Load and Store Instructions
/// aligned
@@ -177,9 +187,16 @@ def SH64 : Store<"sh", GPR64Opnd, truncstorei16, II_SH>, LW_FM<0x29>;
def SW64 : Store<"sw", GPR64Opnd, truncstorei32, II_SW>, LW_FM<0x2b>;
}
-def LWu : Load<"lwu", GPR64Opnd, zextloadi32, II_LWU>, LW_FM<0x27>, ISA_MIPS3;
-def LD : Load<"ld", GPR64Opnd, load, II_LD>, LW_FM<0x37>, ISA_MIPS3;
-def SD : Store<"sd", GPR64Opnd, store, II_SD>, LW_FM<0x3f>, ISA_MIPS3;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def LWu : StdMMR6Rel, MMRel, Load<"lwu", GPR64Opnd, zextloadi32, II_LWU>,
+ LW_FM<0x27>, ISA_MIPS3;
+ def LD : StdMMR6Rel, LoadMemory<"ld", GPR64Opnd, mem_simm16, load, II_LD>,
+ LW_FM<0x37>, ISA_MIPS3;
+ def SD : StdMMR6Rel, StoreMemory<"sd", GPR64Opnd, mem_simm16, store, II_SD>,
+ LW_FM<0x3f>, ISA_MIPS3;
+}
+
+
/// load/store left/right
let isCodeGenOnly = 1 in {
@@ -199,9 +216,20 @@ def SDR : StoreLeftRight<"sdr", MipsSDR, GPR64Opnd, II_SDR>, LW_FM<0x2d>,
ISA_MIPS3_NOT_32R6_64R6;
/// Load-linked, Store-conditional
-def LLD : LLBase<"lld", GPR64Opnd>, LW_FM<0x34>, ISA_MIPS3_NOT_32R6_64R6;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def LLD : StdMMR6Rel, LLBase<"lld", GPR64Opnd, mem_simm16>, LW_FM<0x34>,
+ ISA_MIPS3_NOT_32R6_64R6;
+}
def SCD : SCBase<"scd", GPR64Opnd>, LW_FM<0x3c>, ISA_MIPS3_NOT_32R6_64R6;
+let AdditionalPredicates = [NotInMicroMips],
+ DecoderNamespace = "Mips32_64_PTR64" in {
+def LL64 : LLBase<"ll", GPR32Opnd>, LW_FM<0x30>, PTR_64,
+ ISA_MIPS2_NOT_32R6_64R6;
+def SC64 : SCBase<"sc", GPR32Opnd>, LW_FM<0x38>, PTR_64,
+ ISA_MIPS2_NOT_32R6_64R6;
+}
+
/// Jump and Branch Instructions
let isCodeGenOnly = 1 in {
def JR64 : IndirectBranch<"jr", GPR64Opnd>, MTLO_FM<8>;
@@ -220,18 +248,22 @@ def PseudoReturn64 : PseudoReturnBase<GPR64Opnd>;
def PseudoIndirectBranch64 : PseudoIndirectBranchBase<GPR64Opnd>;
/// Multiply and Divide Instructions.
-def DMULT : Mult<"dmult", II_DMULT, GPR64Opnd, [HI0_64, LO0_64]>,
- MULT_FM<0, 0x1c>, ISA_MIPS3_NOT_32R6_64R6;
-def DMULTu : Mult<"dmultu", II_DMULTU, GPR64Opnd, [HI0_64, LO0_64]>,
- MULT_FM<0, 0x1d>, ISA_MIPS3_NOT_32R6_64R6;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def DMULT : Mult<"dmult", II_DMULT, GPR64Opnd, [HI0_64, LO0_64]>,
+ MULT_FM<0, 0x1c>, ISA_MIPS3_NOT_32R6_64R6;
+ def DMULTu : Mult<"dmultu", II_DMULTU, GPR64Opnd, [HI0_64, LO0_64]>,
+ MULT_FM<0, 0x1d>, ISA_MIPS3_NOT_32R6_64R6;
+}
def PseudoDMULT : MultDivPseudo<DMULT, ACC128, GPR64Opnd, MipsMult,
II_DMULT>, ISA_MIPS3_NOT_32R6_64R6;
def PseudoDMULTu : MultDivPseudo<DMULTu, ACC128, GPR64Opnd, MipsMultu,
II_DMULTU>, ISA_MIPS3_NOT_32R6_64R6;
-def DSDIV : Div<"ddiv", II_DDIV, GPR64Opnd, [HI0_64, LO0_64]>,
- MULT_FM<0, 0x1e>, ISA_MIPS3_NOT_32R6_64R6;
-def DUDIV : Div<"ddivu", II_DDIVU, GPR64Opnd, [HI0_64, LO0_64]>,
- MULT_FM<0, 0x1f>, ISA_MIPS3_NOT_32R6_64R6;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def DSDIV : Div<"ddiv", II_DDIV, GPR64Opnd, [HI0_64, LO0_64]>,
+ MULT_FM<0, 0x1e>, ISA_MIPS3_NOT_32R6_64R6;
+ def DUDIV : Div<"ddivu", II_DDIVU, GPR64Opnd, [HI0_64, LO0_64]>,
+ MULT_FM<0, 0x1f>, ISA_MIPS3_NOT_32R6_64R6;
+}
def PseudoDSDIV : MultDivPseudo<DSDIV, ACC128, GPR64Opnd, MipsDivRem,
II_DDIV, 0, 1, 1>, ISA_MIPS3_NOT_32R6_64R6;
def PseudoDUDIV : MultDivPseudo<DUDIV, ACC128, GPR64Opnd, MipsDivRemU,
@@ -260,12 +292,16 @@ def SEH64 : SignExtInReg<"seh", i16, GPR64Opnd, II_SEH>, SEB_FM<0x18, 0x20>,
}
/// Count Leading
-def DCLZ : CountLeading0<"dclz", GPR64Opnd>, CLO_FM<0x24>, ISA_MIPS64_NOT_64R6;
-def DCLO : CountLeading1<"dclo", GPR64Opnd>, CLO_FM<0x25>, ISA_MIPS64_NOT_64R6;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def DCLZ : StdMMR6Rel, CountLeading0<"dclz", GPR64Opnd>, CLO_FM<0x24>,
+ ISA_MIPS64_NOT_64R6;
+ def DCLO : StdMMR6Rel, CountLeading1<"dclo", GPR64Opnd>, CLO_FM<0x25>,
+ ISA_MIPS64_NOT_64R6;
/// Double Word Swap Bytes/HalfWords
-def DSBH : SubwordSwap<"dsbh", GPR64Opnd>, SEB_FM<2, 0x24>, ISA_MIPS64R2;
-def DSHD : SubwordSwap<"dshd", GPR64Opnd>, SEB_FM<5, 0x24>, ISA_MIPS64R2;
+ def DSBH : SubwordSwap<"dsbh", GPR64Opnd>, SEB_FM<2, 0x24>, ISA_MIPS64R2;
+ def DSHD : SubwordSwap<"dshd", GPR64Opnd>, SEB_FM<5, 0x24>, ISA_MIPS64R2;
+}
def LEA_ADDiu64 : EffectiveAddress<"daddiu", GPR64Opnd>, LW_FM<0x19>;
@@ -273,21 +309,24 @@ let isCodeGenOnly = 1 in
def RDHWR64 : ReadHardware<GPR64Opnd, HWRegsOpnd>, RDHWR_FM;
let AdditionalPredicates = [NotInMicroMips] in {
- // TODO: Add 'pos + size' constraint check to dext* instructions
- // DEXT: 0 < pos + size <= 63
- // DEXTM, DEXTU: 32 < pos + size <= 64
- def DEXT : ExtBase<"dext", GPR64Opnd, uimm5, uimm5_plus1, MipsExt>,
- EXT_FM<3>;
- def DEXTM : ExtBase<"dextm", GPR64Opnd, uimm5, uimm5_plus33, MipsExt>,
- EXT_FM<1>;
+ // The 'pos + size' constraints are enforced by the code that lowers into
+ // MipsISD::Ext.
+ def DEXT : ExtBase<"dext", GPR64Opnd, uimm5_report_uimm6, uimm5_plus1,
+ immZExt5, immZExt5Plus1, MipsExt>, EXT_FM<3>,
+ ISA_MIPS64R2;
+ def DEXTM : ExtBase<"dextm", GPR64Opnd, uimm5, uimm5_plus33, immZExt5,
+ immZExt5Plus33, MipsExt>, EXT_FM<1>, ISA_MIPS64R2;
def DEXTU : ExtBase<"dextu", GPR64Opnd, uimm5_plus32, uimm5_plus1,
- MipsExt>, EXT_FM<2>;
+ immZExt5Plus32, immZExt5Plus1, MipsExt>, EXT_FM<2>,
+ ISA_MIPS64R2;
+ def DINS : InsBase<"dins", GPR64Opnd, uimm6, uimm5_inssize_plus1, MipsIns>,
+ EXT_FM<7>, ISA_MIPS64R2;
+ def DINSU : InsBase<"dinsu", GPR64Opnd, uimm5_plus32, uimm5_inssize_plus1>,
+ EXT_FM<6>, ISA_MIPS64R2;
+ def DINSM : InsBase<"dinsm", GPR64Opnd, uimm5, uimm5_inssize_plus1>,
+ EXT_FM<5>, ISA_MIPS64R2;
}
-def DINS : InsBase<"dins", GPR64Opnd, uimm6, MipsIns>, EXT_FM<7>;
-def DINSU : InsBase<"dinsu", GPR64Opnd, uimm5_plus32>, EXT_FM<6>;
-def DINSM : InsBase<"dinsm", GPR64Opnd, uimm5>, EXT_FM<5>;
-
let isCodeGenOnly = 1, rs = 0, shamt = 0 in {
def DSLL64_32 : FR<0x00, 0x3c, (outs GPR64:$rd), (ins GPR32:$rt),
"dsll\t$rd, $rt, 32", [], II_DSLL>;
@@ -309,8 +348,8 @@ def LONG_BRANCH_DADDiu : PseudoSE<(outs GPR64Opnd:$dst),
// Cavium Octeon cnMIPS instructions
let DecoderNamespace = "CnMips",
- EncodingPredicates = []<Predicate>, // FIXME: The lack of HasStdEnc is probably a bug
- AdditionalPredicates = [HasCnMips] in {
+ // FIXME: The lack of HasStdEnc is probably a bug
+ EncodingPredicates = []<Predicate> in {
class Count1s<string opstr, RegisterOperand RO>:
InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"),
@@ -361,83 +400,94 @@ class MFC2OP<string asmstr, RegisterOperand RO> :
!strconcat(asmstr, "\t$rt, $imm16"), [], NoItinerary, FrmFR>;
// Unsigned Byte Add
-let Pattern = [(set GPR64Opnd:$rd,
- (and (add GPR64Opnd:$rs, GPR64Opnd:$rt), 255))] in
def BADDu : ArithLogicR<"baddu", GPR64Opnd, 1, II_BADDU>,
- ADD_FM<0x1c, 0x28>;
+ ADD_FM<0x1c, 0x28>, ASE_CNMIPS {
+ let Pattern = [(set GPR64Opnd:$rd,
+ (and (add GPR64Opnd:$rs, GPR64Opnd:$rt), 255))];
+}
// Branch on Bit Clear /+32
def BBIT0 : CBranchBitNum<"bbit0", brtarget, seteq, GPR64Opnd,
- uimm5_64_report_uimm6>, BBIT_FM<0x32>;
+ uimm5_64_report_uimm6>, BBIT_FM<0x32>, ASE_CNMIPS;
def BBIT032: CBranchBitNum<"bbit032", brtarget, seteq, GPR64Opnd, uimm5_64,
- 0x100000000>,
- BBIT_FM<0x36>;
+ 0x100000000>, BBIT_FM<0x36>, ASE_CNMIPS;
// Branch on Bit Set /+32
def BBIT1 : CBranchBitNum<"bbit1", brtarget, setne, GPR64Opnd,
- uimm5_64_report_uimm6>, BBIT_FM<0x3a>;
+ uimm5_64_report_uimm6>, BBIT_FM<0x3a>, ASE_CNMIPS;
def BBIT132: CBranchBitNum<"bbit132", brtarget, setne, GPR64Opnd, uimm5_64,
- 0x100000000>, BBIT_FM<0x3e>;
+ 0x100000000>, BBIT_FM<0x3e>, ASE_CNMIPS;
// Multiply Doubleword to GPR
-let Defs = [HI0, LO0, P0, P1, P2] in
def DMUL : ArithLogicR<"dmul", GPR64Opnd, 1, II_DMUL, mul>,
- ADD_FM<0x1c, 0x03>;
+ ADD_FM<0x1c, 0x03>, ASE_CNMIPS {
+ let Defs = [HI0, LO0, P0, P1, P2];
+}
// Extract a signed bit field /+32
-def EXTS : ExtsCins<"exts">, EXTS_FM<0x3a>;
-def EXTS32: ExtsCins<"exts32">, EXTS_FM<0x3b>;
+def EXTS : ExtsCins<"exts">, EXTS_FM<0x3a>, ASE_CNMIPS;
+def EXTS32: ExtsCins<"exts32">, EXTS_FM<0x3b>, ASE_CNMIPS;
// Clear and insert a bit field /+32
-def CINS : ExtsCins<"cins">, EXTS_FM<0x32>;
-def CINS32: ExtsCins<"cins32">, EXTS_FM<0x33>;
+def CINS : ExtsCins<"cins">, EXTS_FM<0x32>, ASE_CNMIPS;
+def CINS32: ExtsCins<"cins32">, EXTS_FM<0x33>, ASE_CNMIPS;
// Move to multiplier/product register
-def MTM0 : MoveToLOHI<"mtm0", GPR64Opnd, [MPL0, P0, P1, P2]>, MTMR_FM<0x08>;
-def MTM1 : MoveToLOHI<"mtm1", GPR64Opnd, [MPL1, P0, P1, P2]>, MTMR_FM<0x0c>;
-def MTM2 : MoveToLOHI<"mtm2", GPR64Opnd, [MPL2, P0, P1, P2]>, MTMR_FM<0x0d>;
-def MTP0 : MoveToLOHI<"mtp0", GPR64Opnd, [P0]>, MTMR_FM<0x09>;
-def MTP1 : MoveToLOHI<"mtp1", GPR64Opnd, [P1]>, MTMR_FM<0x0a>;
-def MTP2 : MoveToLOHI<"mtp2", GPR64Opnd, [P2]>, MTMR_FM<0x0b>;
+def MTM0 : MoveToLOHI<"mtm0", GPR64Opnd, [MPL0, P0, P1, P2]>, MTMR_FM<0x08>,
+ ASE_CNMIPS;
+def MTM1 : MoveToLOHI<"mtm1", GPR64Opnd, [MPL1, P0, P1, P2]>, MTMR_FM<0x0c>,
+ ASE_CNMIPS;
+def MTM2 : MoveToLOHI<"mtm2", GPR64Opnd, [MPL2, P0, P1, P2]>, MTMR_FM<0x0d>,
+ ASE_CNMIPS;
+def MTP0 : MoveToLOHI<"mtp0", GPR64Opnd, [P0]>, MTMR_FM<0x09>, ASE_CNMIPS;
+def MTP1 : MoveToLOHI<"mtp1", GPR64Opnd, [P1]>, MTMR_FM<0x0a>, ASE_CNMIPS;
+def MTP2 : MoveToLOHI<"mtp2", GPR64Opnd, [P2]>, MTMR_FM<0x0b>, ASE_CNMIPS;
// Count Ones in a Word/Doubleword
-def POP : Count1s<"pop", GPR32Opnd>, POP_FM<0x2c>;
-def DPOP : Count1s<"dpop", GPR64Opnd>, POP_FM<0x2d>;
+def POP : Count1s<"pop", GPR32Opnd>, POP_FM<0x2c>, ASE_CNMIPS;
+def DPOP : Count1s<"dpop", GPR64Opnd>, POP_FM<0x2d>, ASE_CNMIPS;
// Set on equal/not equal
-def SEQ : SetCC64_R<"seq", seteq>, SEQ_FM<0x2a>;
-def SEQi : SetCC64_I<"seqi", seteq>, SEQI_FM<0x2e>;
-def SNE : SetCC64_R<"sne", setne>, SEQ_FM<0x2b>;
-def SNEi : SetCC64_I<"snei", setne>, SEQI_FM<0x2f>;
+def SEQ : SetCC64_R<"seq", seteq>, SEQ_FM<0x2a>, ASE_CNMIPS;
+def SEQi : SetCC64_I<"seqi", seteq>, SEQI_FM<0x2e>, ASE_CNMIPS;
+def SNE : SetCC64_R<"sne", setne>, SEQ_FM<0x2b>, ASE_CNMIPS;
+def SNEi : SetCC64_I<"snei", setne>, SEQI_FM<0x2f>, ASE_CNMIPS;
// 192-bit x 64-bit Unsigned Multiply and Add
-let Defs = [P0, P1, P2] in
-def V3MULU: ArithLogicR<"v3mulu", GPR64Opnd, 0, II_DMUL>,
- ADD_FM<0x1c, 0x11>;
+def V3MULU: ArithLogicR<"v3mulu", GPR64Opnd, 0, II_DMUL>, ADD_FM<0x1c, 0x11>,
+ ASE_CNMIPS {
+ let Defs = [P0, P1, P2];
+}
// 64-bit Unsigned Multiply and Add Move
-let Defs = [MPL0, P0, P1, P2] in
-def VMM0 : ArithLogicR<"vmm0", GPR64Opnd, 0, II_DMUL>,
- ADD_FM<0x1c, 0x10>;
+def VMM0 : ArithLogicR<"vmm0", GPR64Opnd, 0, II_DMUL>, ADD_FM<0x1c, 0x10>,
+ ASE_CNMIPS {
+ let Defs = [MPL0, P0, P1, P2];
+}
// 64-bit Unsigned Multiply and Add
-let Defs = [MPL1, MPL2, P0, P1, P2] in
-def VMULU : ArithLogicR<"vmulu", GPR64Opnd, 0, II_DMUL>,
- ADD_FM<0x1c, 0x0f>;
+def VMULU : ArithLogicR<"vmulu", GPR64Opnd, 0, II_DMUL>, ADD_FM<0x1c, 0x0f>,
+ ASE_CNMIPS {
+ let Defs = [MPL1, MPL2, P0, P1, P2];
+}
// Move between CPU and coprocessor registers
-def DMFC2_OCTEON : MFC2OP<"dmfc2", GPR64Opnd>, MFC2OP_FM<0x12, 1>;
-def DMTC2_OCTEON : MFC2OP<"dmtc2", GPR64Opnd>, MFC2OP_FM<0x12, 5>;
+def DMFC2_OCTEON : MFC2OP<"dmfc2", GPR64Opnd>, MFC2OP_FM<0x12, 1>, ASE_CNMIPS;
+def DMTC2_OCTEON : MFC2OP<"dmtc2", GPR64Opnd>, MFC2OP_FM<0x12, 5>, ASE_CNMIPS;
}
}
/// Move between CPU and coprocessor registers
let DecoderNamespace = "Mips64", Predicates = [HasMips64] in {
-def DMFC0 : MFC3OP<"dmfc0", GPR64Opnd, COP0Opnd>, MFC3OP_FM<0x10, 1>, ISA_MIPS3;
-def DMTC0 : MTC3OP<"dmtc0", COP0Opnd, GPR64Opnd>, MFC3OP_FM<0x10, 5>, ISA_MIPS3;
-def DMFC2 : MFC3OP<"dmfc2", GPR64Opnd, COP2Opnd>, MFC3OP_FM<0x12, 1>, ISA_MIPS3;
-def DMTC2 : MTC3OP<"dmtc2", COP2Opnd, GPR64Opnd>, MFC3OP_FM<0x12, 5>, ISA_MIPS3;
+def DMFC0 : MFC3OP<"dmfc0", GPR64Opnd, COP0Opnd, II_DMFC0>, MFC3OP_FM<0x10, 1>,
+ ISA_MIPS3;
+def DMTC0 : MTC3OP<"dmtc0", COP0Opnd, GPR64Opnd, II_DMTC0>, MFC3OP_FM<0x10, 5>,
+ ISA_MIPS3;
+def DMFC2 : MFC3OP<"dmfc2", GPR64Opnd, COP2Opnd, II_DMFC2>, MFC3OP_FM<0x12, 1>,
+ ISA_MIPS3;
+def DMTC2 : MTC3OP<"dmtc2", COP2Opnd, GPR64Opnd, II_DMTC2>, MFC3OP_FM<0x12, 5>,
+ ISA_MIPS3;
}
//===----------------------------------------------------------------------===//
@@ -458,31 +508,34 @@ def : MipsPat<(MipsHi tconstpool:$in), (LUi64 tconstpool:$in)>;
def : MipsPat<(MipsHi tglobaltlsaddr:$in), (LUi64 tglobaltlsaddr:$in)>;
def : MipsPat<(MipsHi texternalsym:$in), (LUi64 texternalsym:$in)>;
-def : MipsPat<(MipsLo tglobaladdr:$in), (DADDiu ZERO_64, tglobaladdr:$in)>;
-def : MipsPat<(MipsLo tblockaddress:$in), (DADDiu ZERO_64, tblockaddress:$in)>;
-def : MipsPat<(MipsLo tjumptable:$in), (DADDiu ZERO_64, tjumptable:$in)>;
-def : MipsPat<(MipsLo tconstpool:$in), (DADDiu ZERO_64, tconstpool:$in)>;
-def : MipsPat<(MipsLo tglobaltlsaddr:$in),
- (DADDiu ZERO_64, tglobaltlsaddr:$in)>;
-def : MipsPat<(MipsLo texternalsym:$in), (DADDiu ZERO_64, texternalsym:$in)>;
-
-def : MipsPat<(add GPR64:$hi, (MipsLo tglobaladdr:$lo)),
- (DADDiu GPR64:$hi, tglobaladdr:$lo)>;
-def : MipsPat<(add GPR64:$hi, (MipsLo tblockaddress:$lo)),
- (DADDiu GPR64:$hi, tblockaddress:$lo)>;
-def : MipsPat<(add GPR64:$hi, (MipsLo tjumptable:$lo)),
- (DADDiu GPR64:$hi, tjumptable:$lo)>;
-def : MipsPat<(add GPR64:$hi, (MipsLo tconstpool:$lo)),
- (DADDiu GPR64:$hi, tconstpool:$lo)>;
-def : MipsPat<(add GPR64:$hi, (MipsLo tglobaltlsaddr:$lo)),
- (DADDiu GPR64:$hi, tglobaltlsaddr:$lo)>;
-
-def : WrapperPat<tglobaladdr, DADDiu, GPR64>;
-def : WrapperPat<tconstpool, DADDiu, GPR64>;
-def : WrapperPat<texternalsym, DADDiu, GPR64>;
-def : WrapperPat<tblockaddress, DADDiu, GPR64>;
-def : WrapperPat<tjumptable, DADDiu, GPR64>;
-def : WrapperPat<tglobaltlsaddr, DADDiu, GPR64>;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def : MipsPat<(MipsLo tglobaladdr:$in), (DADDiu ZERO_64, tglobaladdr:$in)>;
+ def : MipsPat<(MipsLo tblockaddress:$in),
+ (DADDiu ZERO_64, tblockaddress:$in)>;
+ def : MipsPat<(MipsLo tjumptable:$in), (DADDiu ZERO_64, tjumptable:$in)>;
+ def : MipsPat<(MipsLo tconstpool:$in), (DADDiu ZERO_64, tconstpool:$in)>;
+ def : MipsPat<(MipsLo tglobaltlsaddr:$in),
+ (DADDiu ZERO_64, tglobaltlsaddr:$in)>;
+ def : MipsPat<(MipsLo texternalsym:$in), (DADDiu ZERO_64, texternalsym:$in)>;
+
+ def : MipsPat<(add GPR64:$hi, (MipsLo tglobaladdr:$lo)),
+ (DADDiu GPR64:$hi, tglobaladdr:$lo)>;
+ def : MipsPat<(add GPR64:$hi, (MipsLo tblockaddress:$lo)),
+ (DADDiu GPR64:$hi, tblockaddress:$lo)>;
+ def : MipsPat<(add GPR64:$hi, (MipsLo tjumptable:$lo)),
+ (DADDiu GPR64:$hi, tjumptable:$lo)>;
+ def : MipsPat<(add GPR64:$hi, (MipsLo tconstpool:$lo)),
+ (DADDiu GPR64:$hi, tconstpool:$lo)>;
+ def : MipsPat<(add GPR64:$hi, (MipsLo tglobaltlsaddr:$lo)),
+ (DADDiu GPR64:$hi, tglobaltlsaddr:$lo)>;
+
+ def : WrapperPat<tglobaladdr, DADDiu, GPR64>;
+ def : WrapperPat<tconstpool, DADDiu, GPR64>;
+ def : WrapperPat<texternalsym, DADDiu, GPR64>;
+ def : WrapperPat<tblockaddress, DADDiu, GPR64>;
+ def : WrapperPat<tjumptable, DADDiu, GPR64>;
+ def : WrapperPat<tglobaltlsaddr, DADDiu, GPR64>;
+}
defm : BrcondPats<GPR64, BEQ64, BNE64, SLT64, SLTu64, SLTi64, SLTiu64,
ZERO_64>;
@@ -502,7 +555,17 @@ defm : SetgeImmPats<GPR64, SLTi64, SLTiu64>;
// truncate
def : MipsPat<(trunc (assertsext GPR64:$src)),
(EXTRACT_SUBREG GPR64:$src, sub_32)>;
-def : MipsPat<(trunc (assertzext GPR64:$src)),
+// The forward compatibility strategy employed by MIPS requires us to treat
+// values as being sign extended to an infinite number of bits. This allows
+// existing software to run without modification on any future MIPS
+// implementation (e.g. 128-bit, or 1024-bit). Being compatible with this
+// strategy requires that truncation acts as a sign-extension for values being
+// fed into instructions operating on 32-bit values. Such instructions have
+// undefined results if this is not true.
+// For our case, this means that we can't issue an extract_subreg for nodes
+// such as (trunc:i32 (assertzext:i64 X, i32)), because the sign-bit of the
+// lower subreg would not be replicated into the upper half.
+def : MipsPat<(trunc (assertzext_lt_i32 GPR64:$src)),
(EXTRACT_SUBREG GPR64:$src, sub_32)>;
def : MipsPat<(i32 (trunc GPR64:$src)),
(SLL (EXTRACT_SUBREG GPR64:$src, sub_32), 0)>;
@@ -514,11 +577,14 @@ def : MipsPat<(srl GPR64:$rt, (i32 (trunc GPR64:$rs))),
(DSRLV GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>;
def : MipsPat<(sra GPR64:$rt, (i32 (trunc GPR64:$rs))),
(DSRAV GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>;
-def : MipsPat<(rotr GPR64:$rt, (i32 (trunc GPR64:$rs))),
- (DROTRV GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def : MipsPat<(rotr GPR64:$rt, (i32 (trunc GPR64:$rs))),
+ (DROTRV GPR64:$rt, (EXTRACT_SUBREG GPR64:$rs, sub_32))>;
+}
// 32-to-64-bit extension
-def : MipsPat<(i64 (anyext GPR32:$src)), (SLL64_32 GPR32:$src)>;
+def : MipsPat<(i64 (anyext GPR32:$src)),
+ (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GPR32:$src, sub_32)>;
def : MipsPat<(i64 (zext GPR32:$src)), (DSRL (DSLL64_32 GPR32:$src), 32)>;
def : MipsPat<(i64 (sext GPR32:$src)), (SLL64_32 GPR32:$src)>;
@@ -530,26 +596,24 @@ def : MipsPat<(i64 (sext_inreg GPR64:$src, i32)),
def : MipsPat<(bswap GPR64:$rt), (DSHD (DSBH GPR64:$rt))>;
// Carry pattern
-def : MipsPat<(subc GPR64:$lhs, GPR64:$rhs),
- (DSUBu GPR64:$lhs, GPR64:$rhs)>;
-let AdditionalPredicates = [NotDSP] in {
+let AdditionalPredicates = [NotInMicroMips] in {
+ def : MipsPat<(subc GPR64:$lhs, GPR64:$rhs),
+ (DSUBu GPR64:$lhs, GPR64:$rhs)>;
def : MipsPat<(addc GPR64:$lhs, GPR64:$rhs),
- (DADDu GPR64:$lhs, GPR64:$rhs)>;
+ (DADDu GPR64:$lhs, GPR64:$rhs)>, ASE_NOT_DSP;
def : MipsPat<(addc GPR64:$lhs, immSExt16:$imm),
- (DADDiu GPR64:$lhs, imm:$imm)>;
+ (DADDiu GPR64:$lhs, imm:$imm)>, ASE_NOT_DSP;
}
// Octeon bbit0/bbit1 MipsPattern
-let Predicates = [HasMips64, HasCnMips] in {
def : MipsPat<(brcond (i32 (seteq (and i64:$lhs, PowerOf2LO:$mask), 0)), bb:$dst),
- (BBIT0 i64:$lhs, (Log2LO PowerOf2LO:$mask), bb:$dst)>;
+ (BBIT0 i64:$lhs, (Log2LO PowerOf2LO:$mask), bb:$dst)>, ASE_MIPS64_CNMIPS;
def : MipsPat<(brcond (i32 (seteq (and i64:$lhs, PowerOf2HI:$mask), 0)), bb:$dst),
- (BBIT032 i64:$lhs, (Log2HI PowerOf2HI:$mask), bb:$dst)>;
+ (BBIT032 i64:$lhs, (Log2HI PowerOf2HI:$mask), bb:$dst)>, ASE_MIPS64_CNMIPS;
def : MipsPat<(brcond (i32 (setne (and i64:$lhs, PowerOf2LO:$mask), 0)), bb:$dst),
- (BBIT1 i64:$lhs, (Log2LO PowerOf2LO:$mask), bb:$dst)>;
+ (BBIT1 i64:$lhs, (Log2LO PowerOf2LO:$mask), bb:$dst)>, ASE_MIPS64_CNMIPS;
def : MipsPat<(brcond (i32 (setne (and i64:$lhs, PowerOf2HI:$mask), 0)), bb:$dst),
- (BBIT132 i64:$lhs, (Log2HI PowerOf2HI:$mask), bb:$dst)>;
-}
+ (BBIT132 i64:$lhs, (Log2HI PowerOf2HI:$mask), bb:$dst)>, ASE_MIPS64_CNMIPS;
// Atomic load patterns.
def : MipsPat<(atomic_load_8 addr:$a), (LB64 addr:$a)>;
@@ -566,39 +630,40 @@ def : MipsPat<(atomic_store_64 addr:$a, GPR64:$v), (SD GPR64:$v, addr:$a)>;
//===----------------------------------------------------------------------===//
// Instruction aliases
//===----------------------------------------------------------------------===//
-def : MipsInstAlias<"move $dst, $src",
- (OR64 GPR64Opnd:$dst, GPR64Opnd:$src, ZERO_64), 1>,
- GPR_64;
-def : MipsInstAlias<"move $dst, $src",
- (DADDu GPR64Opnd:$dst, GPR64Opnd:$src, ZERO_64), 1>,
- GPR_64;
-def : MipsInstAlias<"daddu $rs, $rt, $imm",
- (DADDiu GPR64Opnd:$rs, GPR64Opnd:$rt, simm16_64:$imm),
- 0>, ISA_MIPS3;
-def : MipsInstAlias<"dadd $rs, $rt, $imm",
- (DADDi GPR64Opnd:$rs, GPR64Opnd:$rt, simm16_64:$imm),
- 0>, ISA_MIPS3_NOT_32R6_64R6;
-def : MipsInstAlias<"daddu $rs, $imm",
- (DADDiu GPR64Opnd:$rs, GPR64Opnd:$rs, simm16_64:$imm),
- 0>, ISA_MIPS3;
-def : MipsInstAlias<"dadd $rs, $imm",
- (DADDi GPR64Opnd:$rs, GPR64Opnd:$rs, simm16_64:$imm),
- 0>, ISA_MIPS3_NOT_32R6_64R6;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def : MipsInstAlias<"move $dst, $src",
+ (OR64 GPR64Opnd:$dst, GPR64Opnd:$src, ZERO_64), 1>,
+ GPR_64;
+ def : MipsInstAlias<"move $dst, $src",
+ (DADDu GPR64Opnd:$dst, GPR64Opnd:$src, ZERO_64), 1>,
+ GPR_64;
+ def : MipsInstAlias<"dadd $rs, $rt, $imm",
+ (DADDi GPR64Opnd:$rs, GPR64Opnd:$rt, simm16_64:$imm),
+ 0>, ISA_MIPS3_NOT_32R6_64R6;
+ def : MipsInstAlias<"dadd $rs, $imm",
+ (DADDi GPR64Opnd:$rs, GPR64Opnd:$rs, simm16_64:$imm),
+ 0>, ISA_MIPS3_NOT_32R6_64R6;
+ def : MipsInstAlias<"daddu $rs, $rt, $imm",
+ (DADDiu GPR64Opnd:$rs, GPR64Opnd:$rt, simm16_64:$imm),
+ 0>, ISA_MIPS3;
+ def : MipsInstAlias<"daddu $rs, $imm",
+ (DADDiu GPR64Opnd:$rs, GPR64Opnd:$rs, simm16_64:$imm),
+ 0>, ISA_MIPS3;
+}
def : MipsInstAlias<"dsll $rd, $rt, $rs",
(DSLLV GPR64Opnd:$rd, GPR64Opnd:$rt, GPR32Opnd:$rs), 0>,
ISA_MIPS3;
-def : MipsInstAlias<"dneg $rt, $rs",
- (DSUB GPR64Opnd:$rt, ZERO_64, GPR64Opnd:$rs), 1>,
- ISA_MIPS3;
-def : MipsInstAlias<"dneg $rt",
- (DSUB GPR64Opnd:$rt, ZERO_64, GPR64Opnd:$rt), 0>,
- ISA_MIPS3;
-def : MipsInstAlias<"dnegu $rt, $rs",
- (DSUBu GPR64Opnd:$rt, ZERO_64, GPR64Opnd:$rs), 1>,
- ISA_MIPS3;
-def : MipsInstAlias<"dsubu $rt, $rs, $imm",
- (DADDiu GPR64Opnd:$rt, GPR64Opnd:$rs,
- InvertedImOperand64:$imm), 0>, ISA_MIPS3;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def : MipsInstAlias<"dneg $rt, $rs",
+ (DSUB GPR64Opnd:$rt, ZERO_64, GPR64Opnd:$rs), 1>,
+ ISA_MIPS3;
+ def : MipsInstAlias<"dneg $rt",
+ (DSUB GPR64Opnd:$rt, ZERO_64, GPR64Opnd:$rt), 0>,
+ ISA_MIPS3;
+ def : MipsInstAlias<"dnegu $rt, $rs",
+ (DSUBu GPR64Opnd:$rt, ZERO_64, GPR64Opnd:$rs), 1>,
+ ISA_MIPS3;
+}
def : MipsInstAlias<"dsubi $rs, $rt, $imm",
(DADDi GPR64Opnd:$rs, GPR64Opnd:$rt,
InvertedImOperand64:$imm),
@@ -615,29 +680,35 @@ def : MipsInstAlias<"dsub $rs, $imm",
(DADDi GPR64Opnd:$rs, GPR64Opnd:$rs,
InvertedImOperand64:$imm),
0>, ISA_MIPS3_NOT_32R6_64R6;
-def : MipsInstAlias<"dsubu $rs, $imm",
- (DADDiu GPR64Opnd:$rs, GPR64Opnd:$rs,
- InvertedImOperand64:$imm),
- 0>, ISA_MIPS3;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def : MipsInstAlias<"dsubu $rt, $rs, $imm",
+ (DADDiu GPR64Opnd:$rt, GPR64Opnd:$rs,
+ InvertedImOperand64:$imm), 0>, ISA_MIPS3;
+ def : MipsInstAlias<"dsubu $rs, $imm",
+ (DADDiu GPR64Opnd:$rs, GPR64Opnd:$rs,
+ InvertedImOperand64:$imm), 0>, ISA_MIPS3;
+}
def : MipsInstAlias<"dsra $rd, $rt, $rs",
(DSRAV GPR64Opnd:$rd, GPR64Opnd:$rt, GPR32Opnd:$rs), 0>,
ISA_MIPS3;
-def : MipsInstAlias<"dsrl $rd, $rt, $rs",
- (DSRLV GPR64Opnd:$rd, GPR64Opnd:$rt, GPR32Opnd:$rs), 0>,
- ISA_MIPS3;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def : MipsInstAlias<"dsrl $rd, $rt, $rs",
+ (DSRLV GPR64Opnd:$rd, GPR64Opnd:$rt, GPR32Opnd:$rs), 0>,
+ ISA_MIPS3;
// Two operand (implicit 0 selector) versions:
-def : MipsInstAlias<"dmfc0 $rt, $rd", (DMFC0 GPR64Opnd:$rt, COP0Opnd:$rd, 0), 0>;
-def : MipsInstAlias<"dmtc0 $rt, $rd", (DMTC0 COP0Opnd:$rd, GPR64Opnd:$rt, 0), 0>;
+ def : MipsInstAlias<"dmtc0 $rt, $rd",
+ (DMTC0 COP0Opnd:$rd, GPR64Opnd:$rt, 0), 0>;
+ def : MipsInstAlias<"dmfc0 $rt, $rd",
+ (DMFC0 GPR64Opnd:$rt, COP0Opnd:$rd, 0), 0>;
+}
def : MipsInstAlias<"dmfc2 $rt, $rd", (DMFC2 GPR64Opnd:$rt, COP2Opnd:$rd, 0), 0>;
def : MipsInstAlias<"dmtc2 $rt, $rd", (DMTC2 COP2Opnd:$rd, GPR64Opnd:$rt, 0), 0>;
-let Predicates = [HasMips64, HasCnMips] in {
-def : MipsInstAlias<"synciobdma", (SYNC 0x2), 0>;
-def : MipsInstAlias<"syncs", (SYNC 0x6), 0>;
-def : MipsInstAlias<"syncw", (SYNC 0x4), 0>;
-def : MipsInstAlias<"syncws", (SYNC 0x5), 0>;
-}
+def : MipsInstAlias<"synciobdma", (SYNC 0x2), 0>, ASE_MIPS64_CNMIPS;
+def : MipsInstAlias<"syncs", (SYNC 0x6), 0>, ASE_MIPS64_CNMIPS;
+def : MipsInstAlias<"syncw", (SYNC 0x4), 0>, ASE_MIPS64_CNMIPS;
+def : MipsInstAlias<"syncws", (SYNC 0x5), 0>, ASE_MIPS64_CNMIPS;
// cnMIPS Aliases.
diff --git a/lib/Target/Mips/Mips64r6InstrInfo.td b/lib/Target/Mips/Mips64r6InstrInfo.td
index 6f34dbe28d305..64effbef8a6a4 100644
--- a/lib/Target/Mips/Mips64r6InstrInfo.td
+++ b/lib/Target/Mips/Mips64r6InstrInfo.td
@@ -46,35 +46,50 @@ class SCD_R6_ENC : SPECIAL3_LL_SC_FM<OPCODE6_SCD>;
//
//===----------------------------------------------------------------------===//
-class AHI_ATI_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> {
+class AHI_ATI_DESC_BASE<string instr_asm, RegisterOperand GPROpnd, InstrItinClass itin> {
dag OutOperandList = (outs GPROpnd:$rs);
- dag InOperandList = (ins GPROpnd:$rt, simm16:$imm);
+ dag InOperandList = (ins GPROpnd:$rt, simm16_relaxed:$imm);
string AsmString = !strconcat(instr_asm, "\t$rt, $imm");
string Constraints = "$rs = $rt";
+ InstrItinClass Itinerary = itin;
}
-class DALIGN_DESC : ALIGN_DESC_BASE<"dalign", GPR64Opnd, uimm3>;
-class DAHI_DESC : AHI_ATI_DESC_BASE<"dahi", GPR64Opnd>;
-class DATI_DESC : AHI_ATI_DESC_BASE<"dati", GPR64Opnd>;
-class DAUI_DESC : AUI_DESC_BASE<"daui", GPR64Opnd>;
-class DBITSWAP_DESC : BITSWAP_DESC_BASE<"dbitswap", GPR64Opnd>;
-class DCLO_R6_DESC : CLO_R6_DESC_BASE<"dclo", GPR64Opnd>;
-class DCLZ_R6_DESC : CLZ_R6_DESC_BASE<"dclz", GPR64Opnd>;
-class DDIV_DESC : DIVMOD_DESC_BASE<"ddiv", GPR64Opnd, sdiv>;
-class DDIVU_DESC : DIVMOD_DESC_BASE<"ddivu", GPR64Opnd, udiv>;
-class DLSA_R6_DESC : LSA_R6_DESC_BASE<"dlsa", GPR64Opnd, uimm2_plus1>;
-class DMOD_DESC : DIVMOD_DESC_BASE<"dmod", GPR64Opnd, srem>;
-class DMODU_DESC : DIVMOD_DESC_BASE<"dmodu", GPR64Opnd, urem>;
-class DMUH_DESC : MUL_R6_DESC_BASE<"dmuh", GPR64Opnd, mulhs>;
-class DMUHU_DESC : MUL_R6_DESC_BASE<"dmuhu", GPR64Opnd, mulhu>;
-class DMUL_R6_DESC : MUL_R6_DESC_BASE<"dmul", GPR64Opnd, mul>;
-class DMULU_DESC : MUL_R6_DESC_BASE<"dmulu", GPR64Opnd>;
-class LDPC_DESC : PCREL_DESC_BASE<"ldpc", GPR64Opnd, simm18_lsl3>;
-class LLD_R6_DESC : LL_R6_DESC_BASE<"lld", GPR64Opnd>;
-class SCD_R6_DESC : SC_R6_DESC_BASE<"scd", GPR64Opnd>;
+class DALIGN_DESC : ALIGN_DESC_BASE<"dalign", GPR64Opnd, uimm3, II_DALIGN>;
+class DAHI_DESC : AHI_ATI_DESC_BASE<"dahi", GPR64Opnd, II_DAHI>;
+class DATI_DESC : AHI_ATI_DESC_BASE<"dati", GPR64Opnd, II_DATI>;
+class DAUI_DESC : AUI_DESC_BASE<"daui", GPR64Opnd, II_DAUI>;
+class DBITSWAP_DESC : BITSWAP_DESC_BASE<"dbitswap", GPR64Opnd, II_DBITSWAP>;
+class DCLO_R6_DESC : CLO_R6_DESC_BASE<"dclo", GPR64Opnd, II_DCLO>;
+class DCLZ_R6_DESC : CLZ_R6_DESC_BASE<"dclz", GPR64Opnd, II_DCLZ>;
+class DDIV_DESC : DIVMOD_DESC_BASE<"ddiv", GPR64Opnd, II_DDIV, sdiv>;
+class DDIVU_DESC : DIVMOD_DESC_BASE<"ddivu", GPR64Opnd, II_DDIVU, udiv>;
+class DLSA_R6_DESC : LSA_R6_DESC_BASE<"dlsa", GPR64Opnd, uimm2_plus1, II_DLSA>;
+class DMOD_DESC : DIVMOD_DESC_BASE<"dmod", GPR64Opnd, II_DMOD, srem>;
+class DMODU_DESC : DIVMOD_DESC_BASE<"dmodu", GPR64Opnd, II_DMODU, urem>;
+class DMUH_DESC : MUL_R6_DESC_BASE<"dmuh", GPR64Opnd, II_DMUH, mulhs>;
+class DMUHU_DESC : MUL_R6_DESC_BASE<"dmuhu", GPR64Opnd, II_DMUHU, mulhu>;
+class DMUL_R6_DESC : MUL_R6_DESC_BASE<"dmul", GPR64Opnd, II_DMUL, mul>;
+class DMULU_DESC : MUL_R6_DESC_BASE<"dmulu", GPR64Opnd, II_DMUL>;
+class LDPC_DESC : PCREL_DESC_BASE<"ldpc", GPR64Opnd, simm18_lsl3, II_LDPC>;
+class LLD_R6_DESC : LL_R6_DESC_BASE<"lld", GPR64Opnd, mem_simm16, II_LLD>;
+class SCD_R6_DESC : SC_R6_DESC_BASE<"scd", GPR64Opnd, II_SCD>;
class SELEQZ64_DESC : SELEQNE_Z_DESC_BASE<"seleqz", GPR64Opnd>;
class SELNEZ64_DESC : SELEQNE_Z_DESC_BASE<"selnez", GPR64Opnd>;
+class JIALC64_DESC : JMP_IDX_COMPACT_DESC_BASE<"jialc", calloffset16,
+ GPR64Opnd> {
+ bit isCall = 1;
+ list<Register> Defs = [RA];
+}
+
+class JIC64_DESC : JMP_IDX_COMPACT_DESC_BASE<"jic", jmpoffset16, GPR64Opnd> {
+ bit isBarrier = 1;
+ bit isTerminator = 1;
+ list<Register> Defs = [AT];
+}
+
+class LL64_R6_DESC : LL_R6_DESC_BASE<"ll", GPR32Opnd, mem_simm9, II_LL>;
+class SC64_R6_DESC : SC_R6_DESC_BASE<"sc", GPR32Opnd, II_SC>;
//===----------------------------------------------------------------------===//
//
// Instruction Definitions
@@ -88,25 +103,37 @@ let AdditionalPredicates = [NotInMicroMips] in {
def DALIGN : DALIGN_ENC, DALIGN_DESC, ISA_MIPS64R6;
}
def DBITSWAP : DBITSWAP_ENC, DBITSWAP_DESC, ISA_MIPS64R6;
-def DCLO_R6 : DCLO_R6_ENC, DCLO_R6_DESC, ISA_MIPS64R6;
-def DCLZ_R6 : DCLZ_R6_ENC, DCLZ_R6_DESC, ISA_MIPS64R6;
-def DDIV : DDIV_ENC, DDIV_DESC, ISA_MIPS64R6;
-def DDIVU : DDIVU_ENC, DDIVU_DESC, ISA_MIPS64R6;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def DCLO_R6 : R6MMR6Rel, DCLO_R6_ENC, DCLO_R6_DESC, ISA_MIPS64R6;
+ def DCLZ_R6 : R6MMR6Rel, DCLZ_R6_ENC, DCLZ_R6_DESC, ISA_MIPS64R6;
+ def DDIV : DDIV_ENC, DDIV_DESC, ISA_MIPS64R6;
+ def DDIVU : DDIVU_ENC, DDIVU_DESC, ISA_MIPS64R6;
+ def DMOD : DMOD_ENC, DMOD_DESC, ISA_MIPS64R6;
+ def DMODU : DMODU_ENC, DMODU_DESC, ISA_MIPS64R6;
+}
def DLSA_R6 : DLSA_R6_ENC, DLSA_R6_DESC, ISA_MIPS64R6;
-def DMOD : DMOD_ENC, DMOD_DESC, ISA_MIPS64R6;
-def DMODU : DMODU_ENC, DMODU_DESC, ISA_MIPS64R6;
-def DMUH: DMUH_ENC, DMUH_DESC, ISA_MIPS64R6;
-def DMUHU: DMUHU_ENC, DMUHU_DESC, ISA_MIPS64R6;
-def DMUL_R6: DMUL_R6_ENC, DMUL_R6_DESC, ISA_MIPS64R6;
-def DMULU: DMULU_ENC, DMULU_DESC, ISA_MIPS64R6;
-def LDPC: LDPC_ENC, LDPC_DESC, ISA_MIPS64R6;
-def LLD_R6 : LLD_R6_ENC, LLD_R6_DESC, ISA_MIPS32R6;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def DMUH: DMUH_ENC, DMUH_DESC, ISA_MIPS64R6;
+ def DMUHU: DMUHU_ENC, DMUHU_DESC, ISA_MIPS64R6;
+ def DMUL_R6: DMUL_R6_ENC, DMUL_R6_DESC, ISA_MIPS64R6;
+ def DMULU: DMULU_ENC, DMULU_DESC, ISA_MIPS64R6;
+ def LLD_R6 : R6MMR6Rel, LLD_R6_ENC, LLD_R6_DESC, ISA_MIPS64R6;
+}
+def LDPC: R6MMR6Rel, LDPC_ENC, LDPC_DESC, ISA_MIPS64R6;
def SCD_R6 : SCD_R6_ENC, SCD_R6_DESC, ISA_MIPS32R6;
let DecoderNamespace = "Mips32r6_64r6_GP64" in {
def SELEQZ64 : SELEQZ_ENC, SELEQZ64_DESC, ISA_MIPS32R6, GPR_64;
def SELNEZ64 : SELNEZ_ENC, SELNEZ64_DESC, ISA_MIPS32R6, GPR_64;
}
-
+let AdditionalPredicates = [NotInMicroMips],
+ DecoderNamespace = "Mips32r6_64r6_PTR64" in {
+ def LL64_R6 : LL_R6_ENC, LL64_R6_DESC, PTR_64, ISA_MIPS64R6;
+ def SC64_R6 : SC_R6_ENC, SC64_R6_DESC, PTR_64, ISA_MIPS64R6;
+}
+let isCodeGenOnly = 1 in {
+def JIALC64 : JIALC_ENC, JIALC64_DESC, ISA_MIPS64R6;
+def JIC64 : JIC_ENC, JIC64_DESC, ISA_MIPS64R6;
+}
//===----------------------------------------------------------------------===//
//
// Instruction Aliases
@@ -115,6 +142,9 @@ let DecoderNamespace = "Mips32r6_64r6_GP64" in {
def : MipsInstAlias<"jr $rs", (JALR64 ZERO_64, GPR64Opnd:$rs), 1>, ISA_MIPS64R6;
+def : MipsInstAlias<"jrc $rs", (JIC64 GPR64Opnd:$rs, 0), 1>, ISA_MIPS64R6;
+
+def : MipsInstAlias<"jalrc $rs", (JIALC64 GPR64Opnd:$rs, 0), 1>, ISA_MIPS64R6;
//===----------------------------------------------------------------------===//
//
// Patterns and Pseudo Instructions
diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp
index 957529376b372..3686c2fe3ec45 100644
--- a/lib/Target/Mips/MipsAsmPrinter.cpp
+++ b/lib/Target/Mips/MipsAsmPrinter.cpp
@@ -313,7 +313,6 @@ const char *MipsAsmPrinter::getCurrentABIString() const {
case MipsABIInfo::ABI::O32: return "abi32";
case MipsABIInfo::ABI::N32: return "abiN32";
case MipsABIInfo::ABI::N64: return "abi64";
- case MipsABIInfo::ABI::EABI: return "eabi32"; // TODO: handle eabi64
default: llvm_unreachable("Unknown Mips ABI");
}
}
@@ -326,9 +325,10 @@ void MipsAsmPrinter::EmitFunctionEntryLabel() {
if (Subtarget->isTargetNaCl())
EmitAlignment(std::max(MF->getAlignment(), MIPS_NACL_BUNDLE_ALIGN));
- if (Subtarget->inMicroMipsMode())
+ if (Subtarget->inMicroMipsMode()) {
TS.emitDirectiveSetMicroMips();
- else
+ TS.setUsesMicroMips();
+ } else
TS.emitDirectiveSetNoMicroMips();
if (Subtarget->inMips16Mode())
@@ -620,24 +620,6 @@ void MipsAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
if (closeP) O << ")";
}
-void MipsAsmPrinter::printUnsignedImm(const MachineInstr *MI, int opNum,
- raw_ostream &O) {
- const MachineOperand &MO = MI->getOperand(opNum);
- if (MO.isImm())
- O << (unsigned short int)MO.getImm();
- else
- printOperand(MI, opNum, O);
-}
-
-void MipsAsmPrinter::printUnsignedImm8(const MachineInstr *MI, int opNum,
- raw_ostream &O) {
- const MachineOperand &MO = MI->getOperand(opNum);
- if (MO.isImm())
- O << (unsigned short int)(unsigned char)MO.getImm();
- else
- printOperand(MI, opNum, O);
-}
-
void MipsAsmPrinter::
printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O) {
// Load/Store memory operands -- imm($reg)
@@ -687,6 +669,12 @@ printRegisterList(const MachineInstr *MI, int opNum, raw_ostream &O) {
}
void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) {
+ MipsTargetStreamer &TS = getTargetStreamer();
+
+ // MipsTargetStreamer has an initialization order problem when emitting an
+ // object file directly (see MipsTargetELFStreamer for full details). Work
+ // around it by re-initializing the PIC state here.
+ TS.setPic(OutContext.getObjectFileInfo()->isPositionIndependent());
// Compute MIPS architecture attributes based on the default subtarget
// that we'd have constructed. Module level directives aren't LTO
@@ -702,14 +690,13 @@ void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) {
bool IsABICalls = STI.isABICalls();
const MipsABIInfo &ABI = MTM.getABI();
if (IsABICalls) {
- getTargetStreamer().emitDirectiveAbiCalls();
- Reloc::Model RM = TM.getRelocationModel();
+ TS.emitDirectiveAbiCalls();
// FIXME: This condition should be a lot more complicated that it is here.
// Ideally it should test for properties of the ABI and not the ABI
// itself.
// For the moment, I'm only correcting enough to make MIPS-IV work.
- if (RM == Reloc::Static && !ABI.IsN64())
- getTargetStreamer().emitDirectiveOptionPic0();
+ if (!isPositionIndependent() && !ABI.IsN64())
+ TS.emitDirectiveOptionPic0();
}
// Tell the assembler which ABI we are using
@@ -720,33 +707,24 @@ void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) {
// NaN: At the moment we only support:
// 1. .nan legacy (default)
// 2. .nan 2008
- STI.isNaN2008() ? getTargetStreamer().emitDirectiveNaN2008()
- : getTargetStreamer().emitDirectiveNaNLegacy();
+ STI.isNaN2008() ? TS.emitDirectiveNaN2008()
+ : TS.emitDirectiveNaNLegacy();
// TODO: handle O64 ABI
- if (ABI.IsEABI()) {
- if (STI.isGP32bit())
- OutStreamer->SwitchSection(OutContext.getELFSection(".gcc_compiled_long32",
- ELF::SHT_PROGBITS, 0));
- else
- OutStreamer->SwitchSection(OutContext.getELFSection(".gcc_compiled_long64",
- ELF::SHT_PROGBITS, 0));
- }
-
- getTargetStreamer().updateABIInfo(STI);
+ TS.updateABIInfo(STI);
// We should always emit a '.module fp=...' but binutils 2.24 does not accept
// it. We therefore emit it when it contradicts the ABI defaults (-mfpxx or
// -mfp64) and omit it otherwise.
if (ABI.IsO32() && (STI.isABI_FPXX() || STI.isFP64bit()))
- getTargetStreamer().emitDirectiveModuleFP();
+ TS.emitDirectiveModuleFP();
// We should always emit a '.module [no]oddspreg' but binutils 2.24 does not
// accept it. We therefore emit it when it contradicts the default or an
// option has changed the default (i.e. FPXX) and omit it otherwise.
if (ABI.IsO32() && (!STI.useOddSPReg() || STI.isABI_FPXX()))
- getTargetStreamer().emitDirectiveModuleOddSPReg();
+ TS.emitDirectiveModuleOddSPReg();
}
void MipsAsmPrinter::emitInlineAsmStart() const {
@@ -990,7 +968,7 @@ void MipsAsmPrinter::EmitFPCallStub(
OutStreamer->EmitLabel(Stub);
// Only handle non-pic for now.
- assert(TM.getRelocationModel() != Reloc::PIC_ &&
+ assert(!isPositionIndependent() &&
"should not be here if we are compiling pic");
TS.emitDirectiveSetReorder();
//
@@ -1071,10 +1049,9 @@ void MipsAsmPrinter::NaClAlignIndirectJumpTargets(MachineFunction &MF) {
}
// If basic block address is taken, block can be target of indirect branch.
- for (MachineFunction::iterator MBB = MF.begin(), E = MF.end();
- MBB != E; ++MBB) {
- if (MBB->hasAddressTaken())
- MBB->setAlignment(MIPS_NACL_BUNDLE_ALIGN);
+ for (auto &MBB : MF) {
+ if (MBB.hasAddressTaken())
+ MBB.setAlignment(MIPS_NACL_BUNDLE_ALIGN);
}
}
diff --git a/lib/Target/Mips/MipsAsmPrinter.h b/lib/Target/Mips/MipsAsmPrinter.h
index a7f3304a3da8a..f30141fc918f3 100644
--- a/lib/Target/Mips/MipsAsmPrinter.h
+++ b/lib/Target/Mips/MipsAsmPrinter.h
@@ -134,8 +134,6 @@ public:
unsigned AsmVariant, const char *ExtraCode,
raw_ostream &O) override;
void printOperand(const MachineInstr *MI, int opNum, raw_ostream &O);
- void printUnsignedImm(const MachineInstr *MI, int opNum, raw_ostream &O);
- void printUnsignedImm8(const MachineInstr *MI, int opNum, raw_ostream &O);
void printMemOperand(const MachineInstr *MI, int opNum, raw_ostream &O);
void printMemOperandEA(const MachineInstr *MI, int opNum, raw_ostream &O);
void printFCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O,
diff --git a/lib/Target/Mips/MipsCCState.cpp b/lib/Target/Mips/MipsCCState.cpp
index d82063e3d2a94..7af988c1f64d9 100644
--- a/lib/Target/Mips/MipsCCState.cpp
+++ b/lib/Target/Mips/MipsCCState.cpp
@@ -26,8 +26,8 @@ static bool isF128SoftLibCall(const char *CallSym) {
"ceill", "copysignl", "cosl", "exp2l",
"expl", "floorl", "fmal", "fmodl",
"log10l", "log2l", "logl", "nearbyintl",
- "powl", "rintl", "sinl", "sqrtl",
- "truncl"};
+ "powl", "rintl", "roundl", "sinl",
+ "sqrtl", "truncl"};
// Check that LibCalls is sorted alphabetically.
auto Comp = [](const char *S1, const char *S2) { return strcmp(S1, S2) < 0; };
diff --git a/lib/Target/Mips/MipsCallingConv.td b/lib/Target/Mips/MipsCallingConv.td
index 0b4b7785af670..a57cb7badc175 100644
--- a/lib/Target/Mips/MipsCallingConv.td
+++ b/lib/Target/Mips/MipsCallingConv.td
@@ -212,48 +212,6 @@ def RetCC_MipsN : CallingConv<[
]>;
//===----------------------------------------------------------------------===//
-// Mips EABI Calling Convention
-//===----------------------------------------------------------------------===//
-
-def CC_MipsEABI : CallingConv<[
- // Promote i8/i16 arguments to i32.
- CCIfType<[i8, i16], CCPromoteToType<i32>>,
-
- // Integer arguments are passed in integer registers.
- CCIfType<[i32], CCAssignToReg<[A0, A1, A2, A3, T0, T1, T2, T3]>>,
-
- // Single fp arguments are passed in pairs within 32-bit mode
- CCIfType<[f32], CCIfSubtarget<"isSingleFloat()",
- CCAssignToReg<[F12, F13, F14, F15, F16, F17, F18, F19]>>>,
-
- CCIfType<[f32], CCIfSubtargetNot<"isSingleFloat()",
- CCAssignToReg<[F12, F14, F16, F18]>>>,
-
- // The first 4 double fp arguments are passed in single fp registers.
- CCIfType<[f64], CCIfSubtargetNot<"isSingleFloat()",
- CCAssignToReg<[D6, D7, D8, D9]>>>,
-
- // Integer values get stored in stack slots that are 4 bytes in
- // size and 4-byte aligned.
- CCIfType<[i32, f32], CCAssignToStack<4, 4>>,
-
- // Integer values get stored in stack slots that are 8 bytes in
- // size and 8-byte aligned.
- CCIfType<[f64], CCIfSubtargetNot<"isSingleFloat()", CCAssignToStack<8, 8>>>
-]>;
-
-def RetCC_MipsEABI : CallingConv<[
- // i32 are returned in registers V0, V1
- CCIfType<[i32], CCAssignToReg<[V0, V1]>>,
-
- // f32 are returned in registers F0, F1
- CCIfType<[f32], CCAssignToReg<[F0, F1]>>,
-
- // f64 are returned in register D0
- CCIfType<[f64], CCIfSubtargetNot<"isSingleFloat()", CCAssignToReg<[D0]>>>
-]>;
-
-//===----------------------------------------------------------------------===//
// Mips FastCC Calling Convention
//===----------------------------------------------------------------------===//
def CC_MipsO32_FastCC : CallingConv<[
@@ -325,7 +283,6 @@ def CC_Mips_FastCC : CallingConv<[
// Stack parameter slots for i32 and f32 are 32-bit words and 4-byte aligned.
CCIfType<[i32, f32], CCAssignToStack<4, 4>>,
- CCIfSubtarget<"isABI_EABI()", CCDelegateTo<CC_MipsEABI>>,
CCIfSubtarget<"isABI_O32()", CCDelegateTo<CC_MipsO32_FastCC>>,
CCDelegateTo<CC_MipsN_FastCC>
]>;
@@ -335,7 +292,6 @@ def CC_Mips_FastCC : CallingConv<[
//===----------------------------------------------------------------------===//
def RetCC_Mips : CallingConv<[
- CCIfSubtarget<"isABI_EABI()", CCDelegateTo<RetCC_MipsEABI>>,
CCIfSubtarget<"isABI_N32()", CCDelegateTo<RetCC_MipsN>>,
CCIfSubtarget<"isABI_N64()", CCDelegateTo<RetCC_MipsN>>,
CCDelegateTo<RetCC_MipsO32>
@@ -377,8 +333,6 @@ def CC_Mips_FixedArg : CallingConv<[
CCIfCC<"CallingConv::Fast", CCDelegateTo<CC_Mips_FastCC>>,
- // FIXME: There wasn't an EABI case in the original code and it seems unlikely
- // that it's the same as CC_MipsN
CCIfSubtarget<"isABI_O32()", CCDelegateTo<CC_MipsO32_FP>>,
CCDelegateTo<CC_MipsN>
]>;
@@ -386,8 +340,6 @@ def CC_Mips_FixedArg : CallingConv<[
def CC_Mips_VarArg : CallingConv<[
CCIfByVal<CCDelegateTo<CC_Mips_ByVal>>,
- // FIXME: There wasn't an EABI case in the original code and it seems unlikely
- // that it's the same as CC_MipsN_VarArg
CCIfSubtarget<"isABI_O32()", CCDelegateTo<CC_MipsO32_FP>>,
CCDelegateTo<CC_MipsN_VarArg>
]>;
diff --git a/lib/Target/Mips/MipsCondMov.td b/lib/Target/Mips/MipsCondMov.td
index 2d96d9b48c0b0..fd4517f253359 100644
--- a/lib/Target/Mips/MipsCondMov.td
+++ b/lib/Target/Mips/MipsCondMov.td
@@ -133,16 +133,14 @@ def MOVZ_I_S : MMRel, CMov_I_F_FT<"movz.s", GPR32Opnd, FGR32Opnd, II_MOVZ_S>,
let isCodeGenOnly = 1 in
def MOVZ_I64_S : CMov_I_F_FT<"movz.s", GPR64Opnd, FGR32Opnd, II_MOVZ_S>,
- CMov_I_F_FM<18, 16>, INSN_MIPS4_32_NOT_32R6_64R6,
- AdditionalRequires<[HasMips64]>;
+ CMov_I_F_FM<18, 16>, INSN_MIPS4_32_NOT_32R6_64R6, GPR_64;
def MOVN_I_S : MMRel, CMov_I_F_FT<"movn.s", GPR32Opnd, FGR32Opnd, II_MOVN_S>,
CMov_I_F_FM<19, 16>, INSN_MIPS4_32_NOT_32R6_64R6;
let isCodeGenOnly = 1 in
def MOVN_I64_S : CMov_I_F_FT<"movn.s", GPR64Opnd, FGR32Opnd, II_MOVN_S>,
- CMov_I_F_FM<19, 16>, INSN_MIPS4_32_NOT_32R6_64R6,
- AdditionalRequires<[IsGP64bit]>;
+ CMov_I_F_FM<19, 16>, INSN_MIPS4_32_NOT_32R6_64R6, GPR_64;
def MOVZ_I_D32 : MMRel, CMov_I_F_FT<"movz.d", GPR32Opnd, AFGR64Opnd,
II_MOVZ_D>, CMov_I_F_FM<18, 17>,
@@ -169,16 +167,14 @@ def MOVT_I : MMRel, CMov_F_I_FT<"movt", GPR32Opnd, II_MOVT, MipsCMovFP_T>,
let isCodeGenOnly = 1 in
def MOVT_I64 : CMov_F_I_FT<"movt", GPR64Opnd, II_MOVT, MipsCMovFP_T>,
- CMov_F_I_FM<1>, INSN_MIPS4_32_NOT_32R6_64R6,
- AdditionalRequires<[IsGP64bit]>;
+ CMov_F_I_FM<1>, INSN_MIPS4_32_NOT_32R6_64R6, GPR_64;
def MOVF_I : MMRel, CMov_F_I_FT<"movf", GPR32Opnd, II_MOVF, MipsCMovFP_F>,
CMov_F_I_FM<0>, INSN_MIPS4_32_NOT_32R6_64R6;
let isCodeGenOnly = 1 in
def MOVF_I64 : CMov_F_I_FT<"movf", GPR64Opnd, II_MOVF, MipsCMovFP_F>,
- CMov_F_I_FM<0>, INSN_MIPS4_32_NOT_32R6_64R6,
- AdditionalRequires<[IsGP64bit]>;
+ CMov_F_I_FM<0>, INSN_MIPS4_32_NOT_32R6_64R6, GPR_64;
def MOVT_S : MMRel, CMov_F_F_FT<"movt.s", FGR32Opnd, II_MOVT_S, MipsCMovFP_T>,
CMov_F_F_FM<16, 1>, INSN_MIPS4_32_NOT_32R6_64R6;
diff --git a/lib/Target/Mips/MipsConstantIslandPass.cpp b/lib/Target/Mips/MipsConstantIslandPass.cpp
index ea8c5871fa0ec..1ea48e0439d4d 100644
--- a/lib/Target/Mips/MipsConstantIslandPass.cpp
+++ b/lib/Target/Mips/MipsConstantIslandPass.cpp
@@ -97,16 +97,6 @@ static unsigned int branchTargetOperand(MachineInstr *MI) {
llvm_unreachable("Unknown branch type");
}
-static bool isUnconditionalBranch(unsigned int Opcode) {
- switch (Opcode) {
- default: return false;
- case Mips::Bimm16:
- case Mips::BimmX16:
- case Mips::JalB16:
- return true;
- }
-}
-
static unsigned int longformBranchOpcode(unsigned int Opcode) {
switch (Opcode) {
case Mips::Bimm16:
@@ -342,8 +332,6 @@ namespace {
/// the branch fix up pass.
bool HasFarJump;
- const TargetMachine &TM;
- bool IsPIC;
const MipsSubtarget *STI;
const Mips16InstrInfo *TII;
MipsFunctionInfo *MFI;
@@ -364,10 +352,9 @@ namespace {
public:
static char ID;
- MipsConstantIslands(TargetMachine &tm)
- : MachineFunctionPass(ID), TM(tm),
- IsPIC(TM.getRelocationModel() == Reloc::PIC_), STI(nullptr),
- MF(nullptr), MCP(nullptr), PrescannedForConstants(false) {}
+ MipsConstantIslands()
+ : MachineFunctionPass(ID), STI(nullptr), MF(nullptr), MCP(nullptr),
+ PrescannedForConstants(false) {}
const char *getPassName() const override {
return "Mips Constant Islands";
@@ -375,9 +362,14 @@ namespace {
bool runOnMachineFunction(MachineFunction &F) override;
+ MachineFunctionProperties getRequiredProperties() const override {
+ return MachineFunctionProperties().set(
+ MachineFunctionProperties::Property::AllVRegsAllocated);
+ }
+
void doInitialPlacement(std::vector<MachineInstr*> &CPEMIs);
CPEntry *findConstPoolEntry(unsigned CPI, const MachineInstr *CPEMI);
- unsigned getCPELogAlign(const MachineInstr *CPEMI);
+ unsigned getCPELogAlign(const MachineInstr &CPEMI);
void initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs);
unsigned getOffsetOf(MachineInstr *MI) const;
unsigned getUserOffset(CPUser&) const;
@@ -389,7 +381,7 @@ namespace {
const CPUser &U);
void computeBlockSize(MachineBasicBlock *MBB);
- MachineBasicBlock *splitBlockBeforeInstr(MachineInstr *MI);
+ MachineBasicBlock *splitBlockBeforeInstr(MachineInstr &MI);
void updateForInsertedWaterBlock(MachineBasicBlock *NewBB);
void adjustBBOffsetsAfter(MachineBasicBlock *BB);
bool decrementCPEReferenceCount(unsigned CPI, MachineInstr* CPEMI);
@@ -437,10 +429,9 @@ void MipsConstantIslands::dumpBBs() {
}
});
}
-/// createMipsLongBranchPass - Returns a pass that converts branches to long
-/// branches.
-FunctionPass *llvm::createMipsConstantIslandPass(MipsTargetMachine &tm) {
- return new MipsConstantIslands(tm);
+/// Returns a pass that converts branches to long branches.
+FunctionPass *llvm::createMipsConstantIslandPass() {
+ return new MipsConstantIslands();
}
bool MipsConstantIslands::runOnMachineFunction(MachineFunction &mf) {
@@ -629,14 +620,14 @@ MipsConstantIslands::CPEntry
/// getCPELogAlign - Returns the required alignment of the constant pool entry
/// represented by CPEMI. Alignment is measured in log2(bytes) units.
-unsigned MipsConstantIslands::getCPELogAlign(const MachineInstr *CPEMI) {
- assert(CPEMI && CPEMI->getOpcode() == Mips::CONSTPOOL_ENTRY);
+unsigned MipsConstantIslands::getCPELogAlign(const MachineInstr &CPEMI) {
+ assert(CPEMI.getOpcode() == Mips::CONSTPOOL_ENTRY);
// Everything is 4-byte aligned unless AlignConstantIslands is set.
if (!AlignConstantIslands)
return 2;
- unsigned CPI = CPEMI->getOperand(1).getIndex();
+ unsigned CPI = CPEMI.getOperand(1).getIndex();
assert(CPI < MCP->getConstants().size() && "Invalid constant pool index.");
unsigned Align = MCP->getConstants()[CPI].getAlignment();
assert(isPowerOf2_32(Align) && "Invalid CPE alignment");
@@ -663,21 +654,17 @@ initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) {
adjustBBOffsetsAfter(&MF->front());
// Now go back through the instructions and build up our data structures.
- for (MachineFunction::iterator MBBI = MF->begin(), E = MF->end();
- MBBI != E; ++MBBI) {
- MachineBasicBlock &MBB = *MBBI;
-
+ for (MachineBasicBlock &MBB : *MF) {
// If this block doesn't fall through into the next MBB, then this is
// 'water' that a constant pool island could be placed.
if (!BBHasFallthrough(&MBB))
WaterList.push_back(&MBB);
- for (MachineBasicBlock::iterator I = MBB.begin(), E = MBB.end();
- I != E; ++I) {
- if (I->isDebugValue())
+ for (MachineInstr &MI : MBB) {
+ if (MI.isDebugValue())
continue;
- int Opc = I->getOpcode();
- if (I->isBranch()) {
+ int Opc = MI.getOpcode();
+ if (MI.isBranch()) {
bool isCond = false;
unsigned Bits = 0;
unsigned Scale = 1;
@@ -746,7 +733,7 @@ initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) {
}
// Record this immediate branch.
unsigned MaxOffs = ((1 << (Bits-1))-1) * Scale;
- ImmBranches.push_back(ImmBranch(I, MaxOffs, isCond, UOpc));
+ ImmBranches.push_back(ImmBranch(&MI, MaxOffs, isCond, UOpc));
}
if (Opc == Mips::CONSTPOOL_ENTRY)
@@ -754,8 +741,8 @@ initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) {
// Scan the instructions for constant pool operands.
- for (unsigned op = 0, e = I->getNumOperands(); op != e; ++op)
- if (I->getOperand(op).isCPI()) {
+ for (unsigned op = 0, e = MI.getNumOperands(); op != e; ++op)
+ if (MI.getOperand(op).isCPI()) {
// We found one. The addressing mode tells us the max displacement
// from the PC that this instruction permits.
@@ -784,12 +771,12 @@ initializeFunctionInfo(const std::vector<MachineInstr*> &CPEMIs) {
break;
}
// Remember that this is a user of a CP entry.
- unsigned CPI = I->getOperand(op).getIndex();
+ unsigned CPI = MI.getOperand(op).getIndex();
MachineInstr *CPEMI = CPEMIs[CPI];
unsigned MaxOffs = ((1 << Bits)-1) * Scale;
unsigned LongFormMaxOffs = ((1 << LongFormBits)-1) * LongFormScale;
- CPUsers.push_back(CPUser(I, CPEMI, MaxOffs, NegOk,
- LongFormMaxOffs, LongFormOpcode));
+ CPUsers.push_back(CPUser(&MI, CPEMI, MaxOffs, NegOk, LongFormMaxOffs,
+ LongFormOpcode));
// Increment corresponding CPEntry reference count.
CPEntry *CPE = findConstPoolEntry(CPI, CPEMI);
@@ -813,10 +800,8 @@ void MipsConstantIslands::computeBlockSize(MachineBasicBlock *MBB) {
BasicBlockInfo &BBI = BBInfo[MBB->getNumber()];
BBI.Size = 0;
- for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E;
- ++I)
- BBI.Size += TII->GetInstSizeInBytes(I);
-
+ for (const MachineInstr &MI : *MBB)
+ BBI.Size += TII->GetInstSizeInBytes(MI);
}
/// getOffsetOf - Return the current offset of the specified machine instruction
@@ -833,7 +818,7 @@ unsigned MipsConstantIslands::getOffsetOf(MachineInstr *MI) const {
// Sum instructions before MI in MBB.
for (MachineBasicBlock::iterator I = MBB->begin(); &*I != MI; ++I) {
assert(I != MBB->end() && "Didn't find MI in its own basic block?");
- Offset += TII->GetInstSizeInBytes(I);
+ Offset += TII->GetInstSizeInBytes(*I);
}
return Offset;
}
@@ -872,9 +857,9 @@ unsigned MipsConstantIslands::getUserOffset(CPUser &U) const {
/// Split the basic block containing MI into two blocks, which are joined by
/// an unconditional branch. Update data structures and renumber blocks to
/// account for this change and returns the newly created block.
-MachineBasicBlock *MipsConstantIslands::splitBlockBeforeInstr
- (MachineInstr *MI) {
- MachineBasicBlock *OrigBB = MI->getParent();
+MachineBasicBlock *
+MipsConstantIslands::splitBlockBeforeInstr(MachineInstr &MI) {
+ MachineBasicBlock *OrigBB = MI.getParent();
// Create a new MBB for the code after the OrigBB.
MachineBasicBlock *NewBB =
@@ -964,7 +949,7 @@ bool MipsConstantIslands::isOffsetInRange(unsigned UserOffset,
bool MipsConstantIslands::isWaterInRange(unsigned UserOffset,
MachineBasicBlock* Water, CPUser &U,
unsigned &Growth) {
- unsigned CPELogAlign = getCPELogAlign(U.CPEMI);
+ unsigned CPELogAlign = getCPELogAlign(*U.CPEMI);
unsigned CPEOffset = BBInfo[Water->getNumber()].postOffset(CPELogAlign);
unsigned NextBlockOffset, NextBlockAlignment;
MachineFunction::const_iterator NextBlock = ++Water->getIterator();
@@ -985,7 +970,7 @@ bool MipsConstantIslands::isWaterInRange(unsigned UserOffset,
Growth = CPEEnd - NextBlockOffset;
// Compute the padding that would go at the end of the CPE to align the next
// block.
- Growth += OffsetToAlignment(CPEEnd, 1u << NextBlockAlignment);
+ Growth += OffsetToAlignment(CPEEnd, 1ULL << NextBlockAlignment);
// If the CPE is to be inserted before the instruction, that will raise
// the offset of the instruction. Also account for unknown alignment padding
@@ -1246,7 +1231,7 @@ void MipsConstantIslands::createNewWater(unsigned CPUserIndex,
CPUser &U = CPUsers[CPUserIndex];
MachineInstr *UserMI = U.MI;
MachineInstr *CPEMI = U.CPEMI;
- unsigned CPELogAlign = getCPELogAlign(CPEMI);
+ unsigned CPELogAlign = getCPELogAlign(*CPEMI);
MachineBasicBlock *UserMBB = UserMI->getParent();
const BasicBlockInfo &UserBBI = BBInfo[UserMBB->getNumber()];
@@ -1312,11 +1297,12 @@ void MipsConstantIslands::createNewWater(unsigned CPUserIndex,
unsigned CPUIndex = CPUserIndex+1;
unsigned NumCPUsers = CPUsers.size();
//MachineInstr *LastIT = 0;
- for (unsigned Offset = UserOffset+TII->GetInstSizeInBytes(UserMI);
+ for (unsigned Offset = UserOffset + TII->GetInstSizeInBytes(*UserMI);
Offset < BaseInsertOffset;
- Offset += TII->GetInstSizeInBytes(MI), MI = std::next(MI)) {
+ Offset += TII->GetInstSizeInBytes(*MI), MI = std::next(MI)) {
assert(MI != UserMBB->end() && "Fell off end of block");
- if (CPUIndex < NumCPUsers && CPUsers[CPUIndex].MI == MI) {
+ if (CPUIndex < NumCPUsers &&
+ CPUsers[CPUIndex].MI == static_cast<MachineInstr *>(MI)) {
CPUser &U = CPUsers[CPUIndex];
if (!isOffsetInRange(Offset, EndInsertOffset, U)) {
// Shift intertion point by one unit of alignment so it is within reach.
@@ -1332,8 +1318,7 @@ void MipsConstantIslands::createNewWater(unsigned CPUserIndex,
}
}
- --MI;
- NewMBB = splitBlockBeforeInstr(MI);
+ NewMBB = splitBlockBeforeInstr(*--MI);
}
/// handleConstantPoolUser - Analyze the specified user, checking to see if it
@@ -1426,7 +1411,7 @@ bool MipsConstantIslands::handleConstantPoolUser(unsigned CPUserIndex) {
++NumCPEs;
// Mark the basic block as aligned as required by the const-pool entry.
- NewIsland->setAlignment(getCPELogAlign(U.CPEMI));
+ NewIsland->setAlignment(getCPELogAlign(*U.CPEMI));
// Increase the size of the island block to account for the new entry.
BBInfo[NewIsland->getNumber()].Size += Size;
@@ -1460,7 +1445,7 @@ void MipsConstantIslands::removeDeadCPEMI(MachineInstr *CPEMI) {
CPEBB->setAlignment(0);
} else
// Entries are sorted by descending alignment, so realign from the front.
- CPEBB->setAlignment(getCPELogAlign(CPEBB->begin()));
+ CPEBB->setAlignment(getCPELogAlign(*CPEBB->begin()));
adjustBBOffsetsAfter(CPEBB);
// An island has only one predecessor BB and one successor BB. Check if
@@ -1610,7 +1595,7 @@ MipsConstantIslands::fixupConditionalBr(ImmBranch &Br) {
++NumCBrFixed;
if (BMI != MI) {
if (std::next(MachineBasicBlock::iterator(MI)) == std::prev(MBB->end()) &&
- isUnconditionalBranch(BMI->getOpcode())) {
+ BMI->isUnconditionalBranch()) {
// Last MI in the BB is an unconditional branch. Can we simply invert the
// condition and swap destinations:
// beqz L1
@@ -1634,10 +1619,10 @@ MipsConstantIslands::fixupConditionalBr(ImmBranch &Br) {
if (NeedSplit) {
- splitBlockBeforeInstr(MI);
+ splitBlockBeforeInstr(*MI);
// No need for the branch to the next block. We're adding an unconditional
// branch to the destination.
- int delta = TII->GetInstSizeInBytes(&MBB->back());
+ int delta = TII->GetInstSizeInBytes(MBB->back());
BBInfo[MBB->getNumber()].Size -= delta;
MBB->back().eraseFromParent();
// BBInfo[SplitBB].Offset is wrong temporarily, fixed below
@@ -1659,14 +1644,14 @@ MipsConstantIslands::fixupConditionalBr(ImmBranch &Br) {
.addMBB(NextBB);
}
Br.MI = &MBB->back();
- BBInfo[MBB->getNumber()].Size += TII->GetInstSizeInBytes(&MBB->back());
+ BBInfo[MBB->getNumber()].Size += TII->GetInstSizeInBytes(MBB->back());
BuildMI(MBB, DebugLoc(), TII->get(Br.UncondBr)).addMBB(DestBB);
- BBInfo[MBB->getNumber()].Size += TII->GetInstSizeInBytes(&MBB->back());
+ BBInfo[MBB->getNumber()].Size += TII->GetInstSizeInBytes(MBB->back());
unsigned MaxDisp = getUnconditionalBrDisp(Br.UncondBr);
ImmBranches.push_back(ImmBranch(&MBB->back(), MaxDisp, false, Br.UncondBr));
// Remove the old conditional branch. It may or may not still be in MBB.
- BBInfo[MI->getParent()->getNumber()].Size -= TII->GetInstSizeInBytes(MI);
+ BBInfo[MI->getParent()->getNumber()].Size -= TII->GetInstSizeInBytes(*MI);
MI->eraseFromParent();
adjustBBOffsetsAfter(MBB);
return true;
@@ -1710,4 +1695,3 @@ void MipsConstantIslands::prescanForConstants() {
}
}
}
-
diff --git a/lib/Target/Mips/MipsDSPInstrFormats.td b/lib/Target/Mips/MipsDSPInstrFormats.td
index f959bd4d8db3f..0ceb1858fb09e 100644
--- a/lib/Target/Mips/MipsDSPInstrFormats.td
+++ b/lib/Target/Mips/MipsDSPInstrFormats.td
@@ -32,6 +32,10 @@ class ISA_DSPR2 {
list<Predicate> InsnPredicates = [HasDSPR2];
}
+class ISA_DSPR3 {
+ list<Predicate> InsnPredicates = [HasDSPR3];
+}
+
// Fields.
class Field6<bits<6> val> {
bits<6> V = val;
diff --git a/lib/Target/Mips/MipsDSPInstrInfo.td b/lib/Target/Mips/MipsDSPInstrInfo.td
index da6f174e2a199..ac9a81b1bb2f7 100644
--- a/lib/Target/Mips/MipsDSPInstrInfo.td
+++ b/lib/Target/Mips/MipsDSPInstrInfo.td
@@ -16,7 +16,6 @@ def immZExt1 : ImmLeaf<i32, [{return isUInt<1>(Imm);}]>;
def immZExt2 : ImmLeaf<i32, [{return isUInt<2>(Imm);}]>;
def immZExt3 : ImmLeaf<i32, [{return isUInt<3>(Imm);}]>;
def immZExt4 : ImmLeaf<i32, [{return isUInt<4>(Imm);}]>;
-def immZExt7 : ImmLeaf<i32, [{return isUInt<7>(Imm);}]>;
def immZExt8 : ImmLeaf<i32, [{return isUInt<8>(Imm);}]>;
def immZExt10 : ImmLeaf<i32, [{return isUInt<10>(Imm);}]>;
def immSExt6 : ImmLeaf<i32, [{return isInt<6>(Imm);}]>;
@@ -287,6 +286,7 @@ class CMP_EQ_QB_R2_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
string AsmString = !strconcat(instr_asm, "\t$rs, $rt");
list<dag> Pattern = [(OpNode ROS:$rs, ROT:$rt)];
InstrItinClass Itinerary = itin;
+ string BaseOpcode = instr_asm;
}
class CMP_EQ_QB_R3_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
@@ -324,9 +324,10 @@ class ABSQ_S_PH_R2_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
}
class REPL_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
- ImmLeaf immPat, InstrItinClass itin, RegisterOperand RO> {
+ Operand ImmOp, ImmLeaf immPat, InstrItinClass itin,
+ RegisterOperand RO> {
dag OutOperandList = (outs RO:$rd);
- dag InOperandList = (ins uimm16:$imm);
+ dag InOperandList = (ins ImmOp:$imm);
string AsmString = !strconcat(instr_asm, "\t$rd, $imm");
list<dag> Pattern = [(set RO:$rd, (OpNode immPat:$imm))];
InstrItinClass Itinerary = itin;
@@ -401,7 +402,7 @@ class EXTR_W_TY1_R2_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
class EXTR_W_TY1_R1_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
InstrItinClass itin> {
dag OutOperandList = (outs GPR32Opnd:$rt);
- dag InOperandList = (ins ACC64DSPOpnd:$ac, uimm16:$shift_rs);
+ dag InOperandList = (ins ACC64DSPOpnd:$ac, uimm5:$shift_rs);
string AsmString = !strconcat(instr_asm, "\t$rt, $ac, $shift_rs");
InstrItinClass Itinerary = itin;
string BaseOpcode = instr_asm;
@@ -440,7 +441,7 @@ class MTHLIP_DESC_BASE<string instr_asm, SDPatternOperator OpNode> {
class RDDSP_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
InstrItinClass itin> {
dag OutOperandList = (outs GPR32Opnd:$rd);
- dag InOperandList = (ins uimm16:$mask);
+ dag InOperandList = (ins uimm10:$mask);
string AsmString = !strconcat(instr_asm, "\t$rd, $mask");
list<dag> Pattern = [(set GPR32Opnd:$rd, (OpNode immZExt10:$mask))];
InstrItinClass Itinerary = itin;
@@ -513,14 +514,16 @@ class BPOSGE32_PSEUDO_DESC_BASE<SDPatternOperator OpNode, InstrItinClass itin> :
bit usesCustomInserter = 1;
}
-class BPOSGE32_DESC_BASE<string instr_asm, InstrItinClass itin> {
+class BPOSGE32_DESC_BASE<string instr_asm, DAGOperand opnd,
+ InstrItinClass itin> {
dag OutOperandList = (outs);
- dag InOperandList = (ins brtarget:$offset);
+ dag InOperandList = (ins opnd:$offset);
string AsmString = !strconcat(instr_asm, "\t$offset");
InstrItinClass Itinerary = itin;
bit isBranch = 1;
bit isTerminator = 1;
bit hasDelaySlot = 1;
+ string BaseOpcode = instr_asm;
}
class INSV_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
@@ -845,11 +848,11 @@ class BITREV_DESC : ABSQ_S_PH_R2_DESC_BASE<"bitrev", int_mips_bitrev,
class PACKRL_PH_DESC : CMP_EQ_QB_R3_DESC_BASE<"packrl.ph", int_mips_packrl_ph,
NoItinerary, DSPROpnd, DSPROpnd>;
-class REPL_QB_DESC : REPL_DESC_BASE<"repl.qb", int_mips_repl_qb, immZExt8,
- NoItinerary, DSPROpnd>;
+class REPL_QB_DESC : REPL_DESC_BASE<"repl.qb", int_mips_repl_qb, uimm8,
+ immZExt8, NoItinerary, DSPROpnd>;
-class REPL_PH_DESC : REPL_DESC_BASE<"repl.ph", int_mips_repl_ph, immZExt10,
- NoItinerary, DSPROpnd>;
+class REPL_PH_DESC : REPL_DESC_BASE<"repl.ph", int_mips_repl_ph, uimm10,
+ immZExt10, NoItinerary, DSPROpnd>;
class REPLV_QB_DESC : ABSQ_S_PH_R2_DESC_BASE<"replv.qb", int_mips_repl_qb,
NoItinerary, DSPROpnd, GPR32Opnd>;
@@ -871,7 +874,7 @@ class LHX_DESC : LX_DESC_BASE<"lhx", int_mips_lhx, NoItinerary>;
class LBUX_DESC : LX_DESC_BASE<"lbux", int_mips_lbux, NoItinerary>;
-class BPOSGE32_DESC : BPOSGE32_DESC_BASE<"bposge32", NoItinerary>;
+class BPOSGE32_DESC : BPOSGE32_DESC_BASE<"bposge32", brtarget, NoItinerary>;
// Extr
class EXTP_DESC : EXTR_W_TY1_R1_DESC_BASE<"extp", MipsEXTP, NoItinerary>,
@@ -1115,7 +1118,7 @@ def ADDQ_S_W : DspMMRel, ADDQ_S_W_ENC, ADDQ_S_W_DESC;
def SUBQ_S_W : DspMMRel, SUBQ_S_W_ENC, SUBQ_S_W_DESC;
def ADDSC : DspMMRel, ADDSC_ENC, ADDSC_DESC;
def ADDWC : DspMMRel, ADDWC_ENC, ADDWC_DESC;
-def MODSUB : MODSUB_ENC, MODSUB_DESC;
+def MODSUB : DspMMRel, MODSUB_ENC, MODSUB_DESC;
def RADDU_W_QB : DspMMRel, RADDU_W_QB_ENC, RADDU_W_QB_DESC;
def ABSQ_S_PH : DspMMRel, ABSQ_S_PH_ENC, ABSQ_S_PH_DESC;
def ABSQ_S_W : DspMMRel, ABSQ_S_W_ENC, ABSQ_S_W_DESC;
@@ -1154,7 +1157,7 @@ def MULEU_S_PH_QBR : DspMMRel, MULEU_S_PH_QBR_ENC, MULEU_S_PH_QBR_DESC;
def MULEQ_S_W_PHL : DspMMRel, MULEQ_S_W_PHL_ENC, MULEQ_S_W_PHL_DESC;
def MULEQ_S_W_PHR : DspMMRel, MULEQ_S_W_PHR_ENC, MULEQ_S_W_PHR_DESC;
def MULQ_RS_PH : DspMMRel, MULQ_RS_PH_ENC, MULQ_RS_PH_DESC;
-def MULSAQ_S_W_PH : MULSAQ_S_W_PH_ENC, MULSAQ_S_W_PH_DESC;
+def MULSAQ_S_W_PH : DspMMRel, MULSAQ_S_W_PH_ENC, MULSAQ_S_W_PH_DESC;
def MAQ_S_W_PHL : DspMMRel, MAQ_S_W_PHL_ENC, MAQ_S_W_PHL_DESC;
def MAQ_S_W_PHR : DspMMRel, MAQ_S_W_PHR_ENC, MAQ_S_W_PHR_DESC;
def MAQ_SA_W_PHL : DspMMRel, MAQ_SA_W_PHL_ENC, MAQ_SA_W_PHL_DESC;
@@ -1177,16 +1180,16 @@ def MADD_DSP : DspMMRel, MADD_DSP_ENC, MADD_DSP_DESC;
def MADDU_DSP : DspMMRel, MADDU_DSP_ENC, MADDU_DSP_DESC;
def MSUB_DSP : DspMMRel, MSUB_DSP_ENC, MSUB_DSP_DESC;
def MSUBU_DSP : DspMMRel, MSUBU_DSP_ENC, MSUBU_DSP_DESC;
-def CMPU_EQ_QB : CMPU_EQ_QB_ENC, CMPU_EQ_QB_DESC;
-def CMPU_LT_QB : CMPU_LT_QB_ENC, CMPU_LT_QB_DESC;
-def CMPU_LE_QB : CMPU_LE_QB_ENC, CMPU_LE_QB_DESC;
-def CMPGU_EQ_QB : CMPGU_EQ_QB_ENC, CMPGU_EQ_QB_DESC;
-def CMPGU_LT_QB : CMPGU_LT_QB_ENC, CMPGU_LT_QB_DESC;
-def CMPGU_LE_QB : CMPGU_LE_QB_ENC, CMPGU_LE_QB_DESC;
-def CMP_EQ_PH : CMP_EQ_PH_ENC, CMP_EQ_PH_DESC;
-def CMP_LT_PH : CMP_LT_PH_ENC, CMP_LT_PH_DESC;
-def CMP_LE_PH : CMP_LE_PH_ENC, CMP_LE_PH_DESC;
-def BITREV : BITREV_ENC, BITREV_DESC;
+def CMPU_EQ_QB : DspMMRel, CMPU_EQ_QB_ENC, CMPU_EQ_QB_DESC;
+def CMPU_LT_QB : DspMMRel, CMPU_LT_QB_ENC, CMPU_LT_QB_DESC;
+def CMPU_LE_QB : DspMMRel, CMPU_LE_QB_ENC, CMPU_LE_QB_DESC;
+def CMPGU_EQ_QB : DspMMRel, CMPGU_EQ_QB_ENC, CMPGU_EQ_QB_DESC;
+def CMPGU_LT_QB : DspMMRel, CMPGU_LT_QB_ENC, CMPGU_LT_QB_DESC;
+def CMPGU_LE_QB : DspMMRel, CMPGU_LE_QB_ENC, CMPGU_LE_QB_DESC;
+def CMP_EQ_PH : DspMMRel, CMP_EQ_PH_ENC, CMP_EQ_PH_DESC;
+def CMP_LT_PH : DspMMRel, CMP_LT_PH_ENC, CMP_LT_PH_DESC;
+def CMP_LE_PH : DspMMRel, CMP_LE_PH_ENC, CMP_LE_PH_DESC;
+def BITREV : DspMMRel, BITREV_ENC, BITREV_DESC;
def PACKRL_PH : DspMMRel, PACKRL_PH_ENC, PACKRL_PH_DESC;
def REPL_QB : DspMMRel, REPL_QB_ENC, REPL_QB_DESC;
def REPL_PH : DspMMRel, REPL_PH_ENC, REPL_PH_DESC;
@@ -1197,7 +1200,9 @@ def PICK_PH : DspMMRel, PICK_PH_ENC, PICK_PH_DESC;
def LWX : DspMMRel, LWX_ENC, LWX_DESC;
def LHX : DspMMRel, LHX_ENC, LHX_DESC;
def LBUX : DspMMRel, LBUX_ENC, LBUX_DESC;
-def BPOSGE32 : BPOSGE32_ENC, BPOSGE32_DESC;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def BPOSGE32 : DspMMRel, BPOSGE32_ENC, BPOSGE32_DESC;
+}
def INSV : DspMMRel, INSV_ENC, INSV_DESC;
def EXTP : DspMMRel, EXTP_ENC, EXTP_DESC;
def EXTPV : DspMMRel, EXTPV_ENC, EXTPV_DESC;
@@ -1224,9 +1229,9 @@ def ADDU_PH : DspMMRel, ADDU_PH_ENC, ADDU_PH_DESC, ISA_DSPR2;
def ADDU_S_PH : DspMMRel, ADDU_S_PH_ENC, ADDU_S_PH_DESC, ISA_DSPR2;
def SUBU_PH : DspMMRel, SUBU_PH_ENC, SUBU_PH_DESC, ISA_DSPR2;
def SUBU_S_PH : DspMMRel, SUBU_S_PH_ENC, SUBU_S_PH_DESC, ISA_DSPR2;
-def CMPGDU_EQ_QB : CMPGDU_EQ_QB_ENC, CMPGDU_EQ_QB_DESC, ISA_DSPR2;
-def CMPGDU_LT_QB : CMPGDU_LT_QB_ENC, CMPGDU_LT_QB_DESC, ISA_DSPR2;
-def CMPGDU_LE_QB : CMPGDU_LE_QB_ENC, CMPGDU_LE_QB_DESC, ISA_DSPR2;
+def CMPGDU_EQ_QB : DspMMRel, CMPGDU_EQ_QB_ENC, CMPGDU_EQ_QB_DESC, ISA_DSPR2;
+def CMPGDU_LT_QB : DspMMRel, CMPGDU_LT_QB_ENC, CMPGDU_LT_QB_DESC, ISA_DSPR2;
+def CMPGDU_LE_QB : DspMMRel, CMPGDU_LE_QB_ENC, CMPGDU_LE_QB_DESC, ISA_DSPR2;
def ABSQ_S_QB : DspMMRel, ABSQ_S_QB_ENC, ABSQ_S_QB_DESC, ISA_DSPR2;
def ADDUH_QB : DspMMRel, ADDUH_QB_ENC, ADDUH_QB_DESC, ISA_DSPR2;
def ADDUH_R_QB : DspMMRel, ADDUH_R_QB_ENC, ADDUH_R_QB_DESC, ISA_DSPR2;
@@ -1253,7 +1258,7 @@ def DPAX_W_PH : DspMMRel, DPAX_W_PH_ENC, DPAX_W_PH_DESC, ISA_DSPR2;
def DPSX_W_PH : DspMMRel, DPSX_W_PH_ENC, DPSX_W_PH_DESC, ISA_DSPR2;
def DPSQX_S_W_PH : DspMMRel, DPSQX_S_W_PH_ENC, DPSQX_S_W_PH_DESC, ISA_DSPR2;
def DPSQX_SA_W_PH : DspMMRel, DPSQX_SA_W_PH_ENC, DPSQX_SA_W_PH_DESC, ISA_DSPR2;
-def MULSA_W_PH : MULSA_W_PH_ENC, MULSA_W_PH_DESC, ISA_DSPR2;
+def MULSA_W_PH : DspMMRel, MULSA_W_PH_ENC, MULSA_W_PH_DESC, ISA_DSPR2;
def PRECR_QB_PH : DspMMRel, PRECR_QB_PH_ENC, PRECR_QB_PH_DESC, ISA_DSPR2;
def PRECR_SRA_PH_W : DspMMRel, PRECR_SRA_PH_W_ENC, PRECR_SRA_PH_W_DESC, ISA_DSPR2;
def PRECR_SRA_R_PH_W : DspMMRel, PRECR_SRA_R_PH_W_ENC, PRECR_SRA_R_PH_W_DESC, ISA_DSPR2;
@@ -1263,12 +1268,12 @@ def SHRA_R_QB : DspMMRel, SHRA_R_QB_ENC, SHRA_R_QB_DESC, ISA_DSPR2;
def SHRAV_R_QB : DspMMRel, SHRAV_R_QB_ENC, SHRAV_R_QB_DESC, ISA_DSPR2;
def SHRL_PH : DspMMRel, SHRL_PH_ENC, SHRL_PH_DESC, ISA_DSPR2;
def SHRLV_PH : DspMMRel, SHRLV_PH_ENC, SHRLV_PH_DESC, ISA_DSPR2;
-def APPEND : APPEND_ENC, APPEND_DESC, ISA_DSPR2;
-def BALIGN : BALIGN_ENC, BALIGN_DESC, ISA_DSPR2;
+def APPEND : DspMMRel, APPEND_ENC, APPEND_DESC, ISA_DSPR2;
+def BALIGN : DspMMRel, BALIGN_ENC, BALIGN_DESC, ISA_DSPR2;
def PREPEND : DspMMRel, PREPEND_ENC, PREPEND_DESC, ISA_DSPR2;
// Pseudos.
-let isPseudo = 1, isCodeGenOnly = 1 in {
+let isPseudo = 1, isCodeGenOnly = 1, hasNoSchedulingInfo = 1 in {
// Pseudo instructions for loading and storing accumulator registers.
def LOAD_ACC64DSP : Load<"", ACC64DSPOpnd>;
def STORE_ACC64DSP : Store<"", ACC64DSPOpnd>;
diff --git a/lib/Target/Mips/MipsDelaySlotFiller.cpp b/lib/Target/Mips/MipsDelaySlotFiller.cpp
index 8313d909df2a9..b5ba770df7bdc 100644
--- a/lib/Target/Mips/MipsDelaySlotFiller.cpp
+++ b/lib/Target/Mips/MipsDelaySlotFiller.cpp
@@ -62,6 +62,28 @@ static cl::opt<bool> DisableBackwardSearch(
cl::desc("Disallow MIPS delay filler to search backward."),
cl::Hidden);
+enum CompactBranchPolicy {
+ CB_Never, ///< The policy 'never' may in some circumstances or for some
+ ///< ISAs not be absolutely adhered to.
+ CB_Optimal, ///< Optimal is the default and will produce compact branches
+ ///< when delay slots cannot be filled.
+ CB_Always ///< 'always' may in some circumstances may not be
+ ///< absolutely adhered to there may not be a corresponding
+ ///< compact form of a branch.
+};
+
+static cl::opt<CompactBranchPolicy> MipsCompactBranchPolicy(
+ "mips-compact-branches",cl::Optional,
+ cl::init(CB_Optimal),
+ cl::desc("MIPS Specific: Compact branch policy."),
+ cl::values(
+ clEnumValN(CB_Never, "never", "Do not use compact branches if possible."),
+ clEnumValN(CB_Optimal, "optimal", "Use compact branches where appropiate (default)."),
+ clEnumValN(CB_Always, "always", "Always use compact branches if possible."),
+ clEnumValEnd
+ )
+);
+
namespace {
typedef MachineBasicBlock::iterator Iter;
typedef MachineBasicBlock::reverse_iterator ReverseIter;
@@ -189,6 +211,11 @@ namespace {
return Changed;
}
+ MachineFunctionProperties getRequiredProperties() const override {
+ return MachineFunctionProperties().set(
+ MachineFunctionProperties::Property::AllVRegsAllocated);
+ }
+
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addRequired<MachineBranchProbabilityInfo>();
MachineFunctionPass::getAnalysisUsage(AU);
@@ -197,11 +224,8 @@ namespace {
private:
bool runOnMachineBasicBlock(MachineBasicBlock &MBB);
- Iter replaceWithCompactBranch(MachineBasicBlock &MBB,
- Iter Branch, DebugLoc DL);
-
- Iter replaceWithCompactJump(MachineBasicBlock &MBB,
- Iter Jump, DebugLoc DL);
+ Iter replaceWithCompactBranch(MachineBasicBlock &MBB, Iter Branch,
+ const DebugLoc &DL);
/// This function checks if it is valid to move Candidate to the delay slot
/// and returns true if it isn't. It also updates memory and register
@@ -505,46 +529,18 @@ getUnderlyingObjects(const MachineInstr &MI,
}
// Replace Branch with the compact branch instruction.
-Iter Filler::replaceWithCompactBranch(MachineBasicBlock &MBB,
- Iter Branch, DebugLoc DL) {
- const MipsInstrInfo *TII =
- MBB.getParent()->getSubtarget<MipsSubtarget>().getInstrInfo();
-
- unsigned NewOpcode =
- (((unsigned) Branch->getOpcode()) == Mips::BEQ) ? Mips::BEQZC_MM
- : Mips::BNEZC_MM;
-
- const MCInstrDesc &NewDesc = TII->get(NewOpcode);
- MachineInstrBuilder MIB = BuildMI(MBB, Branch, DL, NewDesc);
-
- MIB.addReg(Branch->getOperand(0).getReg());
- MIB.addMBB(Branch->getOperand(2).getMBB());
+Iter Filler::replaceWithCompactBranch(MachineBasicBlock &MBB, Iter Branch,
+ const DebugLoc &DL) {
+ const MipsSubtarget &STI = MBB.getParent()->getSubtarget<MipsSubtarget>();
+ const MipsInstrInfo *TII = STI.getInstrInfo();
- Iter tmpIter = Branch;
- Branch = std::prev(Branch);
- MBB.erase(tmpIter);
+ unsigned NewOpcode = TII->getEquivalentCompactForm(Branch);
+ Branch = TII->genInstrWithNewOpc(NewOpcode, Branch);
+ std::next(Branch)->eraseFromParent();
return Branch;
}
-// Replace Jumps with the compact jump instruction.
-Iter Filler::replaceWithCompactJump(MachineBasicBlock &MBB,
- Iter Jump, DebugLoc DL) {
- const MipsInstrInfo *TII =
- MBB.getParent()->getSubtarget<MipsSubtarget>().getInstrInfo();
-
- const MCInstrDesc &NewDesc = TII->get(Mips::JRC16_MM);
- MachineInstrBuilder MIB = BuildMI(MBB, Jump, DL, NewDesc);
-
- MIB.addReg(Jump->getOperand(0).getReg());
-
- Iter tmpIter = Jump;
- Jump = std::prev(Jump);
- MBB.erase(tmpIter);
-
- return Jump;
-}
-
// For given opcode returns opcode of corresponding instruction with short
// delay slot.
static int getEquivalentCallShort(int Opcode) {
@@ -572,6 +568,12 @@ bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
bool InMicroMipsMode = STI.inMicroMipsMode();
const MipsInstrInfo *TII = STI.getInstrInfo();
+ if (InMicroMipsMode && STI.hasMips32r6()) {
+ // This is microMIPS32r6 or microMIPS64r6 processor. Delay slot for
+ // branching instructions is not needed.
+ return Changed;
+ }
+
for (Iter I = MBB.begin(); I != MBB.end(); ++I) {
if (!hasUnoccupiedSlot(&*I))
continue;
@@ -583,55 +585,49 @@ bool Filler::runOnMachineBasicBlock(MachineBasicBlock &MBB) {
if (!DisableDelaySlotFiller && (TM.getOptLevel() != CodeGenOpt::None)) {
bool Filled = false;
- if (searchBackward(MBB, I)) {
- Filled = true;
- } else if (I->isTerminator()) {
- if (searchSuccBBs(MBB, I)) {
+ if (MipsCompactBranchPolicy.getValue() != CB_Always ||
+ !TII->getEquivalentCompactForm(I)) {
+ if (searchBackward(MBB, I)) {
+ Filled = true;
+ } else if (I->isTerminator()) {
+ if (searchSuccBBs(MBB, I)) {
+ Filled = true;
+ }
+ } else if (searchForward(MBB, I)) {
Filled = true;
}
- } else if (searchForward(MBB, I)) {
- Filled = true;
}
if (Filled) {
// Get instruction with delay slot.
- MachineBasicBlock::instr_iterator DSI(I);
+ MachineBasicBlock::instr_iterator DSI = I.getInstrIterator();
- if (InMicroMipsMode && TII->GetInstSizeInBytes(&*std::next(DSI)) == 2 &&
+ if (InMicroMipsMode && TII->GetInstSizeInBytes(*std::next(DSI)) == 2 &&
DSI->isCall()) {
// If instruction in delay slot is 16b change opcode to
// corresponding instruction with short delay slot.
DSI->setDesc(TII->get(getEquivalentCallShort(DSI->getOpcode())));
}
-
continue;
}
}
- // If instruction is BEQ or BNE with one ZERO register, then instead of
- // adding NOP replace this instruction with the corresponding compact
- // branch instruction, i.e. BEQZC or BNEZC.
- unsigned Opcode = I->getOpcode();
- if (InMicroMipsMode) {
- switch (Opcode) {
- case Mips::BEQ:
- case Mips::BNE:
- if (((unsigned) I->getOperand(1).getReg()) == Mips::ZERO) {
- I = replaceWithCompactBranch(MBB, I, I->getDebugLoc());
- continue;
- }
- break;
- case Mips::JR:
- case Mips::PseudoReturn:
- case Mips::PseudoIndirectBranch:
- // For microMIPS the PseudoReturn and PseudoIndirectBranch are allways
- // expanded to JR_MM, so they can be replaced with JRC16_MM.
- I = replaceWithCompactJump(MBB, I, I->getDebugLoc());
- continue;
- default:
- break;
- }
+ // For microMIPS if instruction is BEQ or BNE with one ZERO register, then
+ // instead of adding NOP replace this instruction with the corresponding
+ // compact branch instruction, i.e. BEQZC or BNEZC. Additionally
+ // PseudoReturn and PseudoIndirectBranch are expanded to JR_MM, so they can
+ // be replaced with JRC16_MM.
+
+ // For MIPSR6 attempt to produce the corresponding compact (no delay slot)
+ // form of the CTI. For indirect jumps this will not require inserting a
+ // NOP and for branches will hopefully avoid requiring a NOP.
+ if ((InMicroMipsMode ||
+ (STI.hasMips32r6() && MipsCompactBranchPolicy != CB_Never)) &&
+ TII->getEquivalentCompactForm(I)) {
+ I = replaceWithCompactBranch(MBB, I, I->getDebugLoc());
+ continue;
}
+
// Bundle the NOP to the instruction with the delay slot.
BuildMI(MBB, std::next(I), I->getDebugLoc(), TII->get(Mips::NOP));
MIBundleBuilder(MBB, I, std::next(I, 2));
@@ -696,7 +692,7 @@ bool Filler::searchRange(MachineBasicBlock &MBB, IterTy Begin, IterTy End,
bool InMicroMipsMode = STI.inMicroMipsMode();
const MipsInstrInfo *TII = STI.getInstrInfo();
unsigned Opcode = (*Slot).getOpcode();
- if (InMicroMipsMode && TII->GetInstSizeInBytes(&(*CurrI)) == 2 &&
+ if (InMicroMipsMode && TII->GetInstSizeInBytes(*CurrI) == 2 &&
(Opcode == Mips::JR || Opcode == Mips::PseudoIndirectBranch ||
Opcode == Mips::PseudoReturn))
continue;
@@ -819,7 +815,7 @@ Filler::getBranch(MachineBasicBlock &MBB, const MachineBasicBlock &Dst) const {
SmallVector<MachineOperand, 2> Cond;
MipsInstrInfo::BranchType R =
- TII->AnalyzeBranch(MBB, TrueBB, FalseBB, Cond, false, BranchInstrs);
+ TII->analyzeBranch(MBB, TrueBB, FalseBB, Cond, false, BranchInstrs);
if ((R == MipsInstrInfo::BT_None) || (R == MipsInstrInfo::BT_NoBranch))
return std::make_pair(R, nullptr);
diff --git a/lib/Target/Mips/MipsEVAInstrInfo.td b/lib/Target/Mips/MipsEVAInstrInfo.td
index 36c9694cbaddc..26df263d228b3 100644
--- a/lib/Target/Mips/MipsEVAInstrInfo.td
+++ b/lib/Target/Mips/MipsEVAInstrInfo.td
@@ -51,7 +51,8 @@ class PREFE_ENC : SPECIAL3_EVA_LOAD_STORE_FM<OPCODE6_PREFE>;
//===----------------------------------------------------------------------===//
// Memory Load/Store EVA descriptions
-class LOAD_EVA_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> {
+class LOAD_EVA_DESC_BASE<string instr_asm, RegisterOperand GPROpnd,
+ InstrItinClass itin = NoItinerary> {
dag OutOperandList = (outs GPROpnd:$rt);
dag InOperandList = (ins mem_simm9:$addr);
string AsmString = !strconcat(instr_asm, "\t$rt, $addr");
@@ -59,30 +60,34 @@ class LOAD_EVA_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> {
string DecoderMethod = "DecodeMemEVA";
bit canFoldAsLoad = 1;
bit mayLoad = 1;
+ InstrItinClass Itinerary = itin;
}
-class LBE_DESC : LOAD_EVA_DESC_BASE<"lbe", GPR32Opnd>;
-class LBuE_DESC : LOAD_EVA_DESC_BASE<"lbue", GPR32Opnd>;
-class LHE_DESC : LOAD_EVA_DESC_BASE<"lhe", GPR32Opnd>;
-class LHuE_DESC : LOAD_EVA_DESC_BASE<"lhue", GPR32Opnd>;
-class LWE_DESC : LOAD_EVA_DESC_BASE<"lwe", GPR32Opnd>;
+class LBE_DESC : LOAD_EVA_DESC_BASE<"lbe", GPR32Opnd, II_LBE>;
+class LBuE_DESC : LOAD_EVA_DESC_BASE<"lbue", GPR32Opnd, II_LBUE>;
+class LHE_DESC : LOAD_EVA_DESC_BASE<"lhe", GPR32Opnd, II_LHE>;
+class LHuE_DESC : LOAD_EVA_DESC_BASE<"lhue", GPR32Opnd, II_LHUE>;
+class LWE_DESC : LOAD_EVA_DESC_BASE<"lwe", GPR32Opnd, II_LWE>;
class STORE_EVA_DESC_BASE<string instr_asm, RegisterOperand GPROpnd,
- SDPatternOperator OpNode = null_frag> {
+ SDPatternOperator OpNode = null_frag,
+ InstrItinClass itin = NoItinerary> {
dag OutOperandList = (outs);
dag InOperandList = (ins GPROpnd:$rt, mem_simm9:$addr);
string AsmString = !strconcat(instr_asm, "\t$rt, $addr");
list<dag> Pattern = [];
string DecoderMethod = "DecodeMemEVA";
bit mayStore = 1;
+ InstrItinClass Itinerary = itin;
}
-class SBE_DESC : STORE_EVA_DESC_BASE<"sbe", GPR32Opnd>;
-class SHE_DESC : STORE_EVA_DESC_BASE<"she", GPR32Opnd>;
-class SWE_DESC : STORE_EVA_DESC_BASE<"swe", GPR32Opnd>;
+class SBE_DESC : STORE_EVA_DESC_BASE<"sbe", GPR32Opnd, null_frag, II_SBE>;
+class SHE_DESC : STORE_EVA_DESC_BASE<"she", GPR32Opnd, null_frag, II_SHE>;
+class SWE_DESC : STORE_EVA_DESC_BASE<"swe", GPR32Opnd, null_frag, II_SWE>;
// Load/Store Left/Right EVA descriptions
-class LOAD_LEFT_RIGHT_EVA_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> {
+class LOAD_LEFT_RIGHT_EVA_DESC_BASE<string instr_asm, RegisterOperand GPROpnd,
+ InstrItinClass itin = NoItinerary> {
dag OutOperandList = (outs GPROpnd:$rt);
dag InOperandList = (ins mem_simm9:$addr, GPROpnd:$src);
string AsmString = !strconcat(instr_asm, "\t$rt, $addr");
@@ -90,35 +95,41 @@ class LOAD_LEFT_RIGHT_EVA_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> {
string DecoderMethod = "DecodeMemEVA";
string Constraints = "$src = $rt";
bit canFoldAsLoad = 1;
+ InstrItinClass Itinerary = itin;
}
-class LWLE_DESC : LOAD_LEFT_RIGHT_EVA_DESC_BASE<"lwle", GPR32Opnd>;
-class LWRE_DESC : LOAD_LEFT_RIGHT_EVA_DESC_BASE<"lwre", GPR32Opnd>;
+class LWLE_DESC : LOAD_LEFT_RIGHT_EVA_DESC_BASE<"lwle", GPR32Opnd, II_LWLE>;
+class LWRE_DESC : LOAD_LEFT_RIGHT_EVA_DESC_BASE<"lwre", GPR32Opnd, II_LWRE>;
-class STORE_LEFT_RIGHT_EVA_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> {
+class STORE_LEFT_RIGHT_EVA_DESC_BASE<string instr_asm, RegisterOperand GPROpnd,
+ InstrItinClass itin = NoItinerary> {
dag OutOperandList = (outs);
dag InOperandList = (ins GPROpnd:$rt, mem_simm9:$addr);
string AsmString = !strconcat(instr_asm, "\t$rt, $addr");
list<dag> Pattern = [];
string DecoderMethod = "DecodeMemEVA";
+ InstrItinClass Itinerary = itin;
}
-class SWLE_DESC : LOAD_LEFT_RIGHT_EVA_DESC_BASE<"swle", GPR32Opnd>;
-class SWRE_DESC : LOAD_LEFT_RIGHT_EVA_DESC_BASE<"swre", GPR32Opnd>;
+class SWLE_DESC : LOAD_LEFT_RIGHT_EVA_DESC_BASE<"swle", GPR32Opnd, II_SWLE>;
+class SWRE_DESC : LOAD_LEFT_RIGHT_EVA_DESC_BASE<"swre", GPR32Opnd, II_SWRE>;
// Load-linked EVA, Store-conditional EVA descriptions
-class LLE_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> {
+class LLE_DESC_BASE<string instr_asm, RegisterOperand GPROpnd,
+ InstrItinClass itin = NoItinerary> {
dag OutOperandList = (outs GPROpnd:$rt);
dag InOperandList = (ins mem_simm9:$addr);
string AsmString = !strconcat(instr_asm, "\t$rt, $addr");
list<dag> Pattern = [];
bit mayLoad = 1;
string DecoderMethod = "DecodeMemEVA";
+ InstrItinClass Itinerary = itin;
}
-class LLE_DESC : LLE_DESC_BASE<"lle", GPR32Opnd>;
+class LLE_DESC : LLE_DESC_BASE<"lle", GPR32Opnd, II_LLE>;
-class SCE_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> {
+class SCE_DESC_BASE<string instr_asm, RegisterOperand GPROpnd,
+ InstrItinClass itin = NoItinerary> {
dag OutOperandList = (outs GPROpnd:$dst);
dag InOperandList = (ins GPROpnd:$rt, mem_simm9:$addr);
string AsmString = !strconcat(instr_asm, "\t$rt, $addr");
@@ -126,30 +137,34 @@ class SCE_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> {
bit mayStore = 1;
string Constraints = "$rt = $dst";
string DecoderMethod = "DecodeMemEVA";
+ InstrItinClass Itinerary = itin;
}
-class SCE_DESC : SCE_DESC_BASE<"sce", GPR32Opnd>;
+class SCE_DESC : SCE_DESC_BASE<"sce", GPR32Opnd, II_SCE>;
-class TLB_DESC_BASE<string instr_asm> {
+class TLB_DESC_BASE<string instr_asm, InstrItinClass itin = NoItinerary> {
dag OutOperandList = (outs);
dag InOperandList = (ins);
string AsmString = instr_asm;
list<dag> Pattern = [];
+ InstrItinClass Itinerary = itin;
}
-class TLBINV_DESC : TLB_DESC_BASE<"tlbinv">;
-class TLBINVF_DESC : TLB_DESC_BASE<"tlbinvf">;
+class TLBINV_DESC : TLB_DESC_BASE<"tlbinv", II_TLBINV>;
+class TLBINVF_DESC : TLB_DESC_BASE<"tlbinvf", II_TLBINVF>;
-class CACHEE_DESC_BASE<string instr_asm, Operand MemOpnd> {
+class CACHEE_DESC_BASE<string instr_asm, Operand MemOpnd,
+ InstrItinClass itin = NoItinerary> {
dag OutOperandList = (outs);
dag InOperandList = (ins MemOpnd:$addr, uimm5:$hint);
string AsmString = !strconcat(instr_asm, "\t$hint, $addr");
list<dag> Pattern = [];
string DecoderMethod = "DecodeCacheeOp_CacheOpR6";
+ InstrItinClass Itinerary = itin;
}
-class CACHEE_DESC : CACHEE_DESC_BASE<"cachee", mem>;
-class PREFE_DESC : CACHEE_DESC_BASE<"prefe", mem>;
+class CACHEE_DESC : CACHEE_DESC_BASE<"cachee", mem_simm9, II_CACHEE>;
+class PREFE_DESC : CACHEE_DESC_BASE<"prefe", mem_simm9, II_PREFE>;
//===----------------------------------------------------------------------===//
//
@@ -185,8 +200,10 @@ def LLE : LLE_ENC, LLE_DESC, INSN_EVA;
def SCE : SCE_ENC, SCE_DESC, INSN_EVA;
}
-def TLBINV : TLBINV_ENC, TLBINV_DESC, INSN_EVA;
-def TLBINVF : TLBINVF_ENC, TLBINVF_DESC, INSN_EVA;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def TLBINV : TLBINV_ENC, TLBINV_DESC, INSN_EVA;
+ def TLBINVF : TLBINVF_ENC, TLBINVF_DESC, INSN_EVA;
+}
def CACHEE : CACHEE_ENC, CACHEE_DESC, INSN_EVA;
def PREFE : PREFE_ENC, PREFE_DESC, INSN_EVA;
diff --git a/lib/Target/Mips/MipsFastISel.cpp b/lib/Target/Mips/MipsFastISel.cpp
index e9eaf810637a6..19c201d26b245 100644
--- a/lib/Target/Mips/MipsFastISel.cpp
+++ b/lib/Target/Mips/MipsFastISel.cpp
@@ -1,5 +1,18 @@
-//===-- MipsastISel.cpp - Mips FastISel implementation
-//---------------------===//
+//===-- MipsFastISel.cpp - Mips FastISel implementation --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief This file defines the MIPS-specific support for the FastISel class.
+/// Some of the target-specific code is generated by tablegen in the file
+/// MipsGenFastISel.inc, which is #included here.
+///
+//===----------------------------------------------------------------------===//
#include "MipsCCState.h"
#include "MipsInstrInfo.h"
@@ -192,9 +205,10 @@ public:
TII(*Subtarget->getInstrInfo()), TLI(*Subtarget->getTargetLowering()) {
MFI = funcInfo.MF->getInfo<MipsFunctionInfo>();
Context = &funcInfo.Fn->getContext();
- bool ISASupported = !Subtarget->hasMips32r6() && Subtarget->hasMips32();
+ bool ISASupported = !Subtarget->hasMips32r6() &&
+ !Subtarget->inMicroMipsMode() && Subtarget->hasMips32();
TargetSupported =
- ISASupported && (TM.getRelocationModel() == Reloc::PIC_) &&
+ ISASupported && TM.isPositionIndependent() &&
(static_cast<const MipsTargetMachine &>(TM).getABI().IsO32());
UnsupportedFPMode = Subtarget->isFP64bit();
}
@@ -691,11 +705,10 @@ bool MipsFastISel::emitCmp(unsigned ResultReg, const CmpInst *CI) {
emitInst(Mips::ADDiu, RegWithOne).addReg(Mips::ZERO).addImm(1);
emitInst(Opc).addReg(LeftReg).addReg(RightReg).addReg(
Mips::FCC0, RegState::ImplicitDefine);
- MachineInstrBuilder MI = emitInst(CondMovOpc, ResultReg)
- .addReg(RegWithOne)
- .addReg(Mips::FCC0)
- .addReg(RegWithZero, RegState::Implicit);
- MI->tieOperands(0, 3);
+ emitInst(CondMovOpc, ResultReg)
+ .addReg(RegWithOne)
+ .addReg(Mips::FCC0)
+ .addReg(RegWithZero);
break;
}
}
@@ -802,7 +815,7 @@ bool MipsFastISel::emitStore(MVT VT, unsigned SrcReg, Address &Addr,
unsigned Offset = Addr.getOffset();
MachineFrameInfo &MFI = *MF->getFrameInfo();
MachineMemOperand *MMO = MF->getMachineMemOperand(
- MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOLoad,
+ MachinePointerInfo::getFixedStack(*MF, FI), MachineMemOperand::MOStore,
MFI.getObjectSize(FI), Align);
BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc))
.addReg(SrcReg)
@@ -943,7 +956,7 @@ bool MipsFastISel::selectFPExt(const Instruction *I) {
return false;
unsigned SrcReg =
- getRegForValue(Src); // his must be a 32 bit floating point register class
+ getRegForValue(Src); // this must be a 32bit floating point register class
// maybe we should handle this differently
if (!SrcReg)
return false;
@@ -1180,7 +1193,7 @@ bool MipsFastISel::processCallArgs(CallLoweringInfo &CLI,
// for now (will return false). We need to determine the right alignment
// based on the normal alignment for the underlying machine type.
//
- unsigned ArgSize = RoundUpToAlignment(ArgVT.getSizeInBits(), 4);
+ unsigned ArgSize = alignTo(ArgVT.getSizeInBits(), 4);
unsigned BEAlign = 0;
if (ArgSize < 8 && !Subtarget->isLittle())
@@ -1207,7 +1220,7 @@ bool MipsFastISel::processCallArgs(CallLoweringInfo &CLI,
bool MipsFastISel::finishCall(CallLoweringInfo &CLI, MVT RetVT,
unsigned NumBytes) {
CallingConv::ID CC = CLI.CallConv;
- emitInst(Mips::ADJCALLSTACKUP).addImm(16);
+ emitInst(Mips::ADJCALLSTACKUP).addImm(16).addImm(0);
if (RetVT != MVT::isVoid) {
SmallVector<CCValAssign, 16> RVLocs;
CCState CCInfo(CC, false, *FuncInfo.MF, RVLocs, *Context);
diff --git a/lib/Target/Mips/MipsFrameLowering.cpp b/lib/Target/Mips/MipsFrameLowering.cpp
index a74c8abd2e2db..fe6f332f2bdf9 100644
--- a/lib/Target/Mips/MipsFrameLowering.cpp
+++ b/lib/Target/Mips/MipsFrameLowering.cpp
@@ -13,7 +13,6 @@
#include "MipsFrameLowering.h"
#include "MCTargetDesc/MipsBaseInfo.h"
-#include "MipsAnalyzeImmediate.h"
#include "MipsInstrInfo.h"
#include "MipsMachineFunction.h"
#include "MipsTargetMachine.h"
@@ -24,7 +23,6 @@
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetOptions.h"
using namespace llvm;
@@ -122,7 +120,7 @@ uint64_t MipsFrameLowering::estimateStackSize(const MachineFunction &MF) const {
// Conservatively assume all callee-saved registers will be saved.
for (const MCPhysReg *R = TRI.getCalleeSavedRegs(&MF); *R; ++R) {
unsigned Size = TRI.getMinimalPhysRegClass(*R)->getSize();
- Offset = RoundUpToAlignment(Offset + Size, Size);
+ Offset = alignTo(Offset + Size, Size);
}
unsigned MaxAlign = MFI->getMaxAlignment();
@@ -133,18 +131,18 @@ uint64_t MipsFrameLowering::estimateStackSize(const MachineFunction &MF) const {
// Iterate over other objects.
for (unsigned I = 0, E = MFI->getObjectIndexEnd(); I != E; ++I)
- Offset = RoundUpToAlignment(Offset + MFI->getObjectSize(I), MaxAlign);
+ Offset = alignTo(Offset + MFI->getObjectSize(I), MaxAlign);
// Call frame.
if (MFI->adjustsStack() && hasReservedCallFrame(MF))
- Offset = RoundUpToAlignment(Offset + MFI->getMaxCallFrameSize(),
- std::max(MaxAlign, getStackAlignment()));
+ Offset = alignTo(Offset + MFI->getMaxCallFrameSize(),
+ std::max(MaxAlign, getStackAlignment()));
- return RoundUpToAlignment(Offset, getStackAlignment());
+ return alignTo(Offset, getStackAlignment());
}
// Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions
-void MipsFrameLowering::
+MachineBasicBlock::iterator MipsFrameLowering::
eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const {
unsigned SP = STI.getABI().IsN64() ? Mips::SP_64 : Mips::SP;
@@ -157,5 +155,5 @@ eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
STI.getInstrInfo()->adjustStackPtr(SP, Amount, MBB, I);
}
- MBB.erase(I);
+ return MBB.erase(I);
}
diff --git a/lib/Target/Mips/MipsFrameLowering.h b/lib/Target/Mips/MipsFrameLowering.h
index 5eabd58e8686a..8c4214c4c21d0 100644
--- a/lib/Target/Mips/MipsFrameLowering.h
+++ b/lib/Target/Mips/MipsFrameLowering.h
@@ -36,7 +36,7 @@ public:
bool isFPCloseToIncomingSP() const override { return false; }
- void
+ MachineBasicBlock::iterator
eliminateCallFramePseudoInstr(MachineFunction &MF,
MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const override;
diff --git a/lib/Target/Mips/MipsHazardSchedule.cpp b/lib/Target/Mips/MipsHazardSchedule.cpp
new file mode 100644
index 0000000000000..10022ba60680d
--- /dev/null
+++ b/lib/Target/Mips/MipsHazardSchedule.cpp
@@ -0,0 +1,147 @@
+//===-- MipsHazardSchedule.cpp - Workaround pipeline hazards --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+/// \file
+/// This pass is used to workaround certain pipeline hazards. For now, this covers
+/// compact branch hazards. In future this pass can be extended to other pipeline
+/// hazards, such as various MIPS1 hazards, processor errata that require
+/// instruction reorganization, etc.
+///
+/// This pass has to run after the delay slot filler as that pass can introduce
+/// pipeline hazards, hence the existing hazard recognizer is not suitable.
+///
+/// Hazards handled: forbidden slots for MIPSR6.
+///
+/// A forbidden slot hazard occurs when a compact branch instruction is executed
+/// and the adjacent instruction in memory is a control transfer instruction such
+/// as a branch or jump, ERET, ERETNC, DERET, WAIT and PAUSE.
+///
+/// For example:
+///
+/// 0x8004 bnec a1,v0,<P+0x18>
+/// 0x8008 beqc a1,a2,<P+0x54>
+///
+/// In such cases, the processor is required to signal a Reserved Instruction
+/// exception.
+///
+/// Here, if the instruction at 0x8004 is executed, the processor will raise an
+/// exception as there is a control transfer instruction at 0x8008.
+///
+/// There are two sources of forbidden slot hazards:
+///
+/// A) A previous pass has created a compact branch directly.
+/// B) Transforming a delay slot branch into compact branch. This case can be
+/// difficult to process as lookahead for hazards is insufficent, as
+/// backwards delay slot fillling can also produce hazards in previously
+/// processed instuctions.
+///
+//===----------------------------------------------------------------------===//
+
+#include "Mips.h"
+#include "MipsInstrInfo.h"
+#include "MipsSEInstrInfo.h"
+#include "MipsTargetMachine.h"
+#include "llvm/ADT/Statistic.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/IR/Function.h"
+#include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/Target/TargetMachine.h"
+#include "llvm/Target/TargetRegisterInfo.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "mips-hazard-schedule"
+
+STATISTIC(NumInsertedNops, "Number of nops inserted");
+
+namespace {
+
+typedef MachineBasicBlock::iterator Iter;
+typedef MachineBasicBlock::reverse_iterator ReverseIter;
+
+class MipsHazardSchedule : public MachineFunctionPass {
+
+public:
+ MipsHazardSchedule() : MachineFunctionPass(ID) {}
+
+ const char *getPassName() const override { return "Mips Hazard Schedule"; }
+
+ bool runOnMachineFunction(MachineFunction &F) override;
+
+ MachineFunctionProperties getRequiredProperties() const override {
+ return MachineFunctionProperties().set(
+ MachineFunctionProperties::Property::AllVRegsAllocated);
+ }
+
+private:
+ static char ID;
+};
+
+char MipsHazardSchedule::ID = 0;
+} // end of anonymous namespace
+
+/// Returns a pass that clears pipeline hazards.
+FunctionPass *llvm::createMipsHazardSchedule() {
+ return new MipsHazardSchedule();
+}
+
+// Find the next real instruction from the current position.
+static Iter getNextMachineInstr(Iter Position) {
+ Iter I = Position, E = Position->getParent()->end();
+ I = std::find_if_not(I, E, [](const Iter &Insn) { return Insn->isTransient(); });
+ assert(I != E);
+ return I;
+}
+
+bool MipsHazardSchedule::runOnMachineFunction(MachineFunction &MF) {
+
+ const MipsSubtarget *STI =
+ &static_cast<const MipsSubtarget &>(MF.getSubtarget());
+
+ // Forbidden slot hazards are only defined for MIPSR6.
+ if (!STI->hasMips32r6() || STI->inMicroMipsMode())
+ return false;
+
+ bool Changed = false;
+ const MipsInstrInfo *TII = STI->getInstrInfo();
+
+ for (MachineFunction::iterator FI = MF.begin(); FI != MF.end(); ++FI) {
+ for (Iter I = FI->begin(); I != FI->end(); ++I) {
+
+ // Forbidden slot hazard handling. Use lookahead over state.
+ if (!TII->HasForbiddenSlot(*I))
+ continue;
+
+ bool InsertNop = false;
+ // Next instruction in the basic block.
+ if (std::next(I) != FI->end() &&
+ !TII->SafeInForbiddenSlot(*getNextMachineInstr(std::next(I)))) {
+ InsertNop = true;
+ } else {
+ // Next instruction in the physical successor basic block.
+ for (auto *Succ : FI->successors()) {
+ if (FI->isLayoutSuccessor(Succ) &&
+ getNextMachineInstr(Succ->begin()) != Succ->end() &&
+ !TII->SafeInForbiddenSlot(*getNextMachineInstr(Succ->begin()))) {
+ InsertNop = true;
+ break;
+ }
+ }
+ }
+
+ if (InsertNop) {
+ Changed = true;
+ MIBundleBuilder(&*I).append(
+ BuildMI(MF, I->getDebugLoc(), TII->get(Mips::NOP)));
+ NumInsertedNops++;
+ }
+ }
+ }
+ return Changed;
+}
diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp
index 06502397b6b8c..83763a64ab6ae 100644
--- a/lib/Target/Mips/MipsISelDAGToDAG.cpp
+++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp
@@ -72,12 +72,6 @@ bool MipsDAGToDAGISel::selectAddrRegImm(SDValue Addr, SDValue &Base,
return false;
}
-bool MipsDAGToDAGISel::selectAddrRegReg(SDValue Addr, SDValue &Base,
- SDValue &Offset) const {
- llvm_unreachable("Unimplemented function.");
- return false;
-}
-
bool MipsDAGToDAGISel::selectAddrDefault(SDValue Addr, SDValue &Base,
SDValue &Offset) const {
llvm_unreachable("Unimplemented function.");
@@ -90,7 +84,19 @@ bool MipsDAGToDAGISel::selectIntAddr(SDValue Addr, SDValue &Base,
return false;
}
-bool MipsDAGToDAGISel::selectIntAddrMM(SDValue Addr, SDValue &Base,
+bool MipsDAGToDAGISel::selectIntAddr11MM(SDValue Addr, SDValue &Base,
+ SDValue &Offset) const {
+ llvm_unreachable("Unimplemented function.");
+ return false;
+}
+
+bool MipsDAGToDAGISel::selectIntAddr12MM(SDValue Addr, SDValue &Base,
+ SDValue &Offset) const {
+ llvm_unreachable("Unimplemented function.");
+ return false;
+}
+
+bool MipsDAGToDAGISel::selectIntAddr16MM(SDValue Addr, SDValue &Base,
SDValue &Offset) const {
llvm_unreachable("Unimplemented function.");
return false;
@@ -108,8 +114,14 @@ bool MipsDAGToDAGISel::selectIntAddrMSA(SDValue Addr, SDValue &Base,
return false;
}
-bool MipsDAGToDAGISel::selectAddr16(SDNode *Parent, SDValue N, SDValue &Base,
- SDValue &Offset, SDValue &Alias) {
+bool MipsDAGToDAGISel::selectAddr16(SDValue Addr, SDValue &Base,
+ SDValue &Offset) {
+ llvm_unreachable("Unimplemented function.");
+ return false;
+}
+
+bool MipsDAGToDAGISel::selectAddr16SP(SDValue Addr, SDValue &Base,
+ SDValue &Offset) {
llvm_unreachable("Unimplemented function.");
return false;
}
@@ -182,7 +194,7 @@ bool MipsDAGToDAGISel::selectVSplatMaskR(SDValue N, SDValue &Imm) const {
/// Select instructions not customized! Used for
/// expanded, promoted and normal instructions
-SDNode* MipsDAGToDAGISel::Select(SDNode *Node) {
+void MipsDAGToDAGISel::Select(SDNode *Node) {
unsigned Opcode = Node->getOpcode();
// Dump information about the Node being selected
@@ -192,21 +204,20 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) {
if (Node->isMachineOpcode()) {
DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n");
Node->setNodeId(-1);
- return nullptr;
+ return;
}
// See if subclasses can handle this node.
- std::pair<bool, SDNode*> Ret = selectNode(Node);
-
- if (Ret.first)
- return Ret.second;
+ if (trySelect(Node))
+ return;
switch(Opcode) {
default: break;
// Get target GOT address.
case ISD::GLOBAL_OFFSET_TABLE:
- return getGlobalBaseReg();
+ ReplaceNode(Node, getGlobalBaseReg());
+ return;
#ifndef NDEBUG
case ISD::LOAD:
@@ -220,15 +231,7 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) {
}
// Select the default instruction
- SDNode *ResNode = SelectCode(Node);
-
- DEBUG(errs() << "=> ");
- if (ResNode == nullptr || ResNode == Node)
- DEBUG(Node->dump(CurDAG));
- else
- DEBUG(ResNode->dump(CurDAG));
- DEBUG(errs() << "\n");
- return ResNode;
+ SelectCode(Node);
}
bool MipsDAGToDAGISel::
diff --git a/lib/Target/Mips/MipsISelDAGToDAG.h b/lib/Target/Mips/MipsISelDAGToDAG.h
index 1426d0fbf5161..289832a8064e3 100644
--- a/lib/Target/Mips/MipsISelDAGToDAG.h
+++ b/lib/Target/Mips/MipsISelDAGToDAG.h
@@ -31,8 +31,8 @@ namespace llvm {
class MipsDAGToDAGISel : public SelectionDAGISel {
public:
- explicit MipsDAGToDAGISel(MipsTargetMachine &TM)
- : SelectionDAGISel(TM), Subtarget(nullptr) {}
+ explicit MipsDAGToDAGISel(MipsTargetMachine &TM, CodeGenOpt::Level OL)
+ : SelectionDAGISel(TM, OL), Subtarget(nullptr) {}
// Pass Name
const char *getPassName() const override {
@@ -57,11 +57,6 @@ private:
virtual bool selectAddrRegImm(SDValue Addr, SDValue &Base,
SDValue &Offset) const;
- // Complex Pattern.
- /// (reg + reg).
- virtual bool selectAddrRegReg(SDValue Addr, SDValue &Base,
- SDValue &Offset) const;
-
/// Fall back on this function if all else fails.
virtual bool selectAddrDefault(SDValue Addr, SDValue &Base,
SDValue &Offset) const;
@@ -70,9 +65,15 @@ private:
virtual bool selectIntAddr(SDValue Addr, SDValue &Base,
SDValue &Offset) const;
- virtual bool selectIntAddrMM(SDValue Addr, SDValue &Base,
+ virtual bool selectIntAddr11MM(SDValue Addr, SDValue &Base,
+ SDValue &Offset) const;
+
+ virtual bool selectIntAddr12MM(SDValue Addr, SDValue &Base,
SDValue &Offset) const;
+ virtual bool selectIntAddr16MM(SDValue Addr, SDValue &Base,
+ SDValue &Offset) const;
+
virtual bool selectIntAddrLSL2MM(SDValue Addr, SDValue &Base,
SDValue &Offset) const;
@@ -80,8 +81,8 @@ private:
virtual bool selectIntAddrMSA(SDValue Addr, SDValue &Base,
SDValue &Offset) const;
- virtual bool selectAddr16(SDNode *Parent, SDValue N, SDValue &Base,
- SDValue &Offset, SDValue &Alias);
+ virtual bool selectAddr16(SDValue Addr, SDValue &Base, SDValue &Offset);
+ virtual bool selectAddr16SP(SDValue Addr, SDValue &Base, SDValue &Offset);
/// \brief Select constant vector splats.
virtual bool selectVSplat(SDNode *N, APInt &Imm,
@@ -114,9 +115,9 @@ private:
/// starting at bit zero.
virtual bool selectVSplatMaskR(SDValue N, SDValue &Imm) const;
- SDNode *Select(SDNode *N) override;
+ void Select(SDNode *N) override;
- virtual std::pair<bool, SDNode*> selectNode(SDNode *Node) = 0;
+ virtual bool trySelect(SDNode *Node) = 0;
// getImm - Return a target constant with the specified value.
inline SDValue getImm(const SDNode *Node, uint64_t Imm) {
diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp
index 5680130b91b22..1d62a251cc663 100644
--- a/lib/Target/Mips/MipsISelLowering.cpp
+++ b/lib/Target/Mips/MipsISelLowering.cpp
@@ -341,10 +341,6 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM,
}
setOperationAction(ISD::CTTZ, MVT::i32, Expand);
setOperationAction(ISD::CTTZ, MVT::i64, Expand);
- setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i32, Expand);
- setOperationAction(ISD::CTTZ_ZERO_UNDEF, MVT::i64, Expand);
- setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i32, Expand);
- setOperationAction(ISD::CTLZ_ZERO_UNDEF, MVT::i64, Expand);
setOperationAction(ISD::ROTL, MVT::i32, Expand);
setOperationAction(ISD::ROTL, MVT::i64, Expand);
setOperationAction(ISD::DYNAMIC_STACKALLOC, MVT::i32, Expand);
@@ -396,7 +392,6 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM,
setOperationAction(ISD::ATOMIC_STORE, MVT::i64, Expand);
}
- setInsertFencesForAtomic(true);
if (!Subtarget.hasMips32r2()) {
setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8, Expand);
@@ -429,6 +424,7 @@ MipsTargetLowering::MipsTargetLowering(const MipsTargetMachine &TM,
setTargetDAGCombine(ISD::AND);
setTargetDAGCombine(ISD::OR);
setTargetDAGCombine(ISD::ADD);
+ setTargetDAGCombine(ISD::AssertZext);
setMinFunctionAlignment(Subtarget.isGP64bit() ? 3 : 2);
@@ -568,7 +564,7 @@ static SDValue createFPCmp(SelectionDAG &DAG, const SDValue &Op) {
// Creates and returns a CMovFPT/F node.
static SDValue createCMovFP(SelectionDAG &DAG, SDValue Cond, SDValue True,
- SDValue False, SDLoc DL) {
+ SDValue False, const SDLoc &DL) {
ConstantSDNode *CC = cast<ConstantSDNode>(Cond.getOperand(2));
bool invert = invertFPCondCodeUser((Mips::CondCode)CC->getSExtValue());
SDValue FCC0 = DAG.getRegister(Mips::FCC0, MVT::i32);
@@ -808,6 +804,37 @@ static SDValue performADDCombine(SDNode *N, SelectionDAG &DAG,
return DAG.getNode(ISD::ADD, DL, ValTy, Add1, Lo);
}
+static SDValue performAssertZextCombine(SDNode *N, SelectionDAG &DAG,
+ TargetLowering::DAGCombinerInfo &DCI,
+ const MipsSubtarget &Subtarget) {
+ SDValue N0 = N->getOperand(0);
+ EVT NarrowerVT = cast<VTSDNode>(N->getOperand(1))->getVT();
+
+ if (N0.getOpcode() != ISD::TRUNCATE)
+ return SDValue();
+
+ if (N0.getOperand(0).getOpcode() != ISD::AssertZext)
+ return SDValue();
+
+ // fold (AssertZext (trunc (AssertZext x))) -> (trunc (AssertZext x))
+ // if the type of the extension of the innermost AssertZext node is
+ // smaller from that of the outermost node, eg:
+ // (AssertZext:i32 (trunc:i32 (AssertZext:i64 X, i32)), i8)
+ // -> (trunc:i32 (AssertZext X, i8))
+ SDValue WiderAssertZext = N0.getOperand(0);
+ EVT WiderVT = cast<VTSDNode>(WiderAssertZext->getOperand(1))->getVT();
+
+ if (NarrowerVT.bitsLT(WiderVT)) {
+ SDValue NewAssertZext = DAG.getNode(
+ ISD::AssertZext, SDLoc(N), WiderAssertZext.getValueType(),
+ WiderAssertZext.getOperand(0), DAG.getValueType(NarrowerVT));
+ return DAG.getNode(ISD::TRUNCATE, SDLoc(N), N->getValueType(0),
+ NewAssertZext);
+ }
+
+ return SDValue();
+}
+
SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI)
const {
SelectionDAG &DAG = DCI.DAG;
@@ -829,6 +856,8 @@ SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI)
return performORCombine(N, DAG, DCI, Subtarget);
case ISD::ADD:
return performADDCombine(N, DAG, DCI, Subtarget);
+ case ISD::AssertZext:
+ return performAssertZextCombine(N, DAG, DCI, Subtarget);
}
return SDValue();
@@ -906,20 +935,22 @@ addLiveIn(MachineFunction &MF, unsigned PReg, const TargetRegisterClass *RC)
return VReg;
}
-static MachineBasicBlock *insertDivByZeroTrap(MachineInstr *MI,
+static MachineBasicBlock *insertDivByZeroTrap(MachineInstr &MI,
MachineBasicBlock &MBB,
const TargetInstrInfo &TII,
- bool Is64Bit) {
+ bool Is64Bit, bool IsMicroMips) {
if (NoZeroDivCheck)
return &MBB;
// Insert instruction "teq $divisor_reg, $zero, 7".
MachineBasicBlock::iterator I(MI);
MachineInstrBuilder MIB;
- MachineOperand &Divisor = MI->getOperand(2);
- MIB = BuildMI(MBB, std::next(I), MI->getDebugLoc(), TII.get(Mips::TEQ))
- .addReg(Divisor.getReg(), getKillRegState(Divisor.isKill()))
- .addReg(Mips::ZERO).addImm(7);
+ MachineOperand &Divisor = MI.getOperand(2);
+ MIB = BuildMI(MBB, std::next(I), MI.getDebugLoc(),
+ TII.get(IsMicroMips ? Mips::TEQ_MM : Mips::TEQ))
+ .addReg(Divisor.getReg(), getKillRegState(Divisor.isKill()))
+ .addReg(Mips::ZERO)
+ .addImm(7);
// Use the 32-bit sub-register if this is a 64-bit division.
if (Is64Bit)
@@ -935,9 +966,9 @@ static MachineBasicBlock *insertDivByZeroTrap(MachineInstr *MI,
}
MachineBasicBlock *
-MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
+MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
MachineBasicBlock *BB) const {
- switch (MI->getOpcode()) {
+ switch (MI.getOpcode()) {
default:
llvm_unreachable("Unexpected instr type to insert");
case Mips::ATOMIC_LOAD_ADD_I8:
@@ -1017,15 +1048,31 @@ MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
case Mips::DIVU:
case Mips::MOD:
case Mips::MODU:
- return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), false);
+ return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), false,
+ false);
+ case Mips::SDIV_MM_Pseudo:
+ case Mips::UDIV_MM_Pseudo:
+ case Mips::SDIV_MM:
+ case Mips::UDIV_MM:
+ case Mips::DIV_MMR6:
+ case Mips::DIVU_MMR6:
+ case Mips::MOD_MMR6:
+ case Mips::MODU_MMR6:
+ return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), false, true);
case Mips::PseudoDSDIV:
case Mips::PseudoDUDIV:
case Mips::DDIV:
case Mips::DDIVU:
case Mips::DMOD:
case Mips::DMODU:
- return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), true);
+ return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), true, false);
+ case Mips::DDIV_MM64R6:
+ case Mips::DDIVU_MM64R6:
+ case Mips::DMOD_MM64R6:
+ case Mips::DMODU_MM64R6:
+ return insertDivByZeroTrap(MI, *BB, *Subtarget.getInstrInfo(), true, true);
case Mips::SEL_D:
+ case Mips::SEL_D_MMR6:
return emitSEL_D(MI, BB);
case Mips::PseudoSELECT_I:
@@ -1051,17 +1098,19 @@ MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
// This function also handles Mips::ATOMIC_SWAP_I32 (when BinOpcode == 0), and
// Mips::ATOMIC_LOAD_NAND_I32 (when Nand == true)
-MachineBasicBlock *
-MipsTargetLowering::emitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB,
- unsigned Size, unsigned BinOpcode,
- bool Nand) const {
+MachineBasicBlock *MipsTargetLowering::emitAtomicBinary(MachineInstr &MI,
+ MachineBasicBlock *BB,
+ unsigned Size,
+ unsigned BinOpcode,
+ bool Nand) const {
assert((Size == 4 || Size == 8) && "Unsupported size for EmitAtomicBinary.");
MachineFunction *MF = BB->getParent();
MachineRegisterInfo &RegInfo = MF->getRegInfo();
const TargetRegisterClass *RC = getRegClassFor(MVT::getIntegerVT(Size * 8));
const TargetInstrInfo *TII = Subtarget.getInstrInfo();
- DebugLoc DL = MI->getDebugLoc();
+ const bool ArePtrs64bit = ABI.ArePtrs64bit();
+ DebugLoc DL = MI.getDebugLoc();
unsigned LL, SC, AND, NOR, ZERO, BEQ;
if (Size == 4) {
@@ -1069,9 +1118,14 @@ MipsTargetLowering::emitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB,
LL = Mips::LL_MM;
SC = Mips::SC_MM;
} else {
- LL = Subtarget.hasMips32r6() ? Mips::LL_R6 : Mips::LL;
- SC = Subtarget.hasMips32r6() ? Mips::SC_R6 : Mips::SC;
+ LL = Subtarget.hasMips32r6()
+ ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6)
+ : (ArePtrs64bit ? Mips::LL64 : Mips::LL);
+ SC = Subtarget.hasMips32r6()
+ ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6)
+ : (ArePtrs64bit ? Mips::SC64 : Mips::SC);
}
+
AND = Mips::AND;
NOR = Mips::NOR;
ZERO = Mips::ZERO;
@@ -1085,9 +1139,9 @@ MipsTargetLowering::emitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB,
BEQ = Mips::BEQ64;
}
- unsigned OldVal = MI->getOperand(0).getReg();
- unsigned Ptr = MI->getOperand(1).getReg();
- unsigned Incr = MI->getOperand(2).getReg();
+ unsigned OldVal = MI.getOperand(0).getReg();
+ unsigned Ptr = MI.getOperand(1).getReg();
+ unsigned Incr = MI.getOperand(2).getReg();
unsigned StoreVal = RegInfo.createVirtualRegister(RC);
unsigned AndRes = RegInfo.createVirtualRegister(RC);
@@ -1134,16 +1188,16 @@ MipsTargetLowering::emitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB,
BuildMI(BB, DL, TII->get(SC), Success).addReg(StoreVal).addReg(Ptr).addImm(0);
BuildMI(BB, DL, TII->get(BEQ)).addReg(Success).addReg(ZERO).addMBB(loopMBB);
- MI->eraseFromParent(); // The instruction is gone now.
+ MI.eraseFromParent(); // The instruction is gone now.
return exitMBB;
}
MachineBasicBlock *MipsTargetLowering::emitSignExtendToI32InReg(
- MachineInstr *MI, MachineBasicBlock *BB, unsigned Size, unsigned DstReg,
+ MachineInstr &MI, MachineBasicBlock *BB, unsigned Size, unsigned DstReg,
unsigned SrcReg) const {
const TargetInstrInfo *TII = Subtarget.getInstrInfo();
- DebugLoc DL = MI->getDebugLoc();
+ const DebugLoc &DL = MI.getDebugLoc();
if (Subtarget.hasMips32r2() && Size == 1) {
BuildMI(BB, DL, TII->get(Mips::SEB), DstReg).addReg(SrcReg);
@@ -1170,7 +1224,7 @@ MachineBasicBlock *MipsTargetLowering::emitSignExtendToI32InReg(
}
MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword(
- MachineInstr *MI, MachineBasicBlock *BB, unsigned Size, unsigned BinOpcode,
+ MachineInstr &MI, MachineBasicBlock *BB, unsigned Size, unsigned BinOpcode,
bool Nand) const {
assert((Size == 1 || Size == 2) &&
"Unsupported size for EmitAtomicBinaryPartial.");
@@ -1178,21 +1232,24 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword(
MachineFunction *MF = BB->getParent();
MachineRegisterInfo &RegInfo = MF->getRegInfo();
const TargetRegisterClass *RC = getRegClassFor(MVT::i32);
+ const bool ArePtrs64bit = ABI.ArePtrs64bit();
+ const TargetRegisterClass *RCp =
+ getRegClassFor(ArePtrs64bit ? MVT::i64 : MVT::i32);
const TargetInstrInfo *TII = Subtarget.getInstrInfo();
- DebugLoc DL = MI->getDebugLoc();
+ DebugLoc DL = MI.getDebugLoc();
- unsigned Dest = MI->getOperand(0).getReg();
- unsigned Ptr = MI->getOperand(1).getReg();
- unsigned Incr = MI->getOperand(2).getReg();
+ unsigned Dest = MI.getOperand(0).getReg();
+ unsigned Ptr = MI.getOperand(1).getReg();
+ unsigned Incr = MI.getOperand(2).getReg();
- unsigned AlignedAddr = RegInfo.createVirtualRegister(RC);
+ unsigned AlignedAddr = RegInfo.createVirtualRegister(RCp);
unsigned ShiftAmt = RegInfo.createVirtualRegister(RC);
unsigned Mask = RegInfo.createVirtualRegister(RC);
unsigned Mask2 = RegInfo.createVirtualRegister(RC);
unsigned NewVal = RegInfo.createVirtualRegister(RC);
unsigned OldVal = RegInfo.createVirtualRegister(RC);
unsigned Incr2 = RegInfo.createVirtualRegister(RC);
- unsigned MaskLSB2 = RegInfo.createVirtualRegister(RC);
+ unsigned MaskLSB2 = RegInfo.createVirtualRegister(RCp);
unsigned PtrLSB2 = RegInfo.createVirtualRegister(RC);
unsigned MaskUpper = RegInfo.createVirtualRegister(RC);
unsigned AndRes = RegInfo.createVirtualRegister(RC);
@@ -1203,6 +1260,17 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword(
unsigned SrlRes = RegInfo.createVirtualRegister(RC);
unsigned Success = RegInfo.createVirtualRegister(RC);
+ unsigned LL, SC;
+ if (isMicroMips) {
+ LL = Mips::LL_MM;
+ SC = Mips::SC_MM;
+ } else {
+ LL = Subtarget.hasMips32r6() ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6)
+ : (ArePtrs64bit ? Mips::LL64 : Mips::LL);
+ SC = Subtarget.hasMips32r6() ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6)
+ : (ArePtrs64bit ? Mips::SC64 : Mips::SC);
+ }
+
// insert new blocks after the current block
const BasicBlock *LLVM_BB = BB->getBasicBlock();
MachineBasicBlock *loopMBB = MF->CreateMachineBasicBlock(LLVM_BB);
@@ -1234,11 +1302,12 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword(
// sll incr2,incr,shiftamt
int64_t MaskImm = (Size == 1) ? 255 : 65535;
- BuildMI(BB, DL, TII->get(Mips::ADDiu), MaskLSB2)
- .addReg(Mips::ZERO).addImm(-4);
- BuildMI(BB, DL, TII->get(Mips::AND), AlignedAddr)
+ BuildMI(BB, DL, TII->get(ABI.GetPtrAddiuOp()), MaskLSB2)
+ .addReg(ABI.GetNullPtr()).addImm(-4);
+ BuildMI(BB, DL, TII->get(ABI.GetPtrAndOp()), AlignedAddr)
.addReg(Ptr).addReg(MaskLSB2);
- BuildMI(BB, DL, TII->get(Mips::ANDi), PtrLSB2).addReg(Ptr).addImm(3);
+ BuildMI(BB, DL, TII->get(Mips::ANDi), PtrLSB2)
+ .addReg(Ptr, 0, ArePtrs64bit ? Mips::sub_32 : 0).addImm(3);
if (Subtarget.isLittle()) {
BuildMI(BB, DL, TII->get(Mips::SLL), ShiftAmt).addReg(PtrLSB2).addImm(3);
} else {
@@ -1274,7 +1343,6 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword(
// beq success,$0,loopMBB
BB = loopMBB;
- unsigned LL = isMicroMips ? Mips::LL_MM : Mips::LL;
BuildMI(BB, DL, TII->get(LL), OldVal).addReg(AlignedAddr).addImm(0);
if (Nand) {
// and andres, oldval, incr2
@@ -1298,7 +1366,6 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword(
.addReg(OldVal).addReg(Mask2);
BuildMI(BB, DL, TII->get(Mips::OR), StoreVal)
.addReg(MaskedOldVal0).addReg(NewVal);
- unsigned SC = isMicroMips ? Mips::SC_MM : Mips::SC;
BuildMI(BB, DL, TII->get(SC), Success)
.addReg(StoreVal).addReg(AlignedAddr).addImm(0);
BuildMI(BB, DL, TII->get(Mips::BEQ))
@@ -1316,31 +1383,37 @@ MachineBasicBlock *MipsTargetLowering::emitAtomicBinaryPartword(
.addReg(MaskedOldVal1).addReg(ShiftAmt);
BB = emitSignExtendToI32InReg(MI, BB, Size, Dest, SrlRes);
- MI->eraseFromParent(); // The instruction is gone now.
+ MI.eraseFromParent(); // The instruction is gone now.
return exitMBB;
}
-MachineBasicBlock * MipsTargetLowering::emitAtomicCmpSwap(MachineInstr *MI,
- MachineBasicBlock *BB,
- unsigned Size) const {
+MachineBasicBlock *MipsTargetLowering::emitAtomicCmpSwap(MachineInstr &MI,
+ MachineBasicBlock *BB,
+ unsigned Size) const {
assert((Size == 4 || Size == 8) && "Unsupported size for EmitAtomicCmpSwap.");
MachineFunction *MF = BB->getParent();
MachineRegisterInfo &RegInfo = MF->getRegInfo();
const TargetRegisterClass *RC = getRegClassFor(MVT::getIntegerVT(Size * 8));
const TargetInstrInfo *TII = Subtarget.getInstrInfo();
- DebugLoc DL = MI->getDebugLoc();
+ const bool ArePtrs64bit = ABI.ArePtrs64bit();
+ DebugLoc DL = MI.getDebugLoc();
unsigned LL, SC, ZERO, BNE, BEQ;
- if (Size == 4) {
- if (isMicroMips) {
- LL = Mips::LL_MM;
- SC = Mips::SC_MM;
- } else {
- LL = Subtarget.hasMips32r6() ? Mips::LL_R6 : Mips::LL;
- SC = Subtarget.hasMips32r6() ? Mips::SC_R6 : Mips::SC;
- }
+ if (Size == 4) {
+ if (isMicroMips) {
+ LL = Mips::LL_MM;
+ SC = Mips::SC_MM;
+ } else {
+ LL = Subtarget.hasMips32r6()
+ ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6)
+ : (ArePtrs64bit ? Mips::LL64 : Mips::LL);
+ SC = Subtarget.hasMips32r6()
+ ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6)
+ : (ArePtrs64bit ? Mips::SC64 : Mips::SC);
+ }
+
ZERO = Mips::ZERO;
BNE = Mips::BNE;
BEQ = Mips::BEQ;
@@ -1352,10 +1425,10 @@ MachineBasicBlock * MipsTargetLowering::emitAtomicCmpSwap(MachineInstr *MI,
BEQ = Mips::BEQ64;
}
- unsigned Dest = MI->getOperand(0).getReg();
- unsigned Ptr = MI->getOperand(1).getReg();
- unsigned OldVal = MI->getOperand(2).getReg();
- unsigned NewVal = MI->getOperand(3).getReg();
+ unsigned Dest = MI.getOperand(0).getReg();
+ unsigned Ptr = MI.getOperand(1).getReg();
+ unsigned OldVal = MI.getOperand(2).getReg();
+ unsigned NewVal = MI.getOperand(3).getReg();
unsigned Success = RegInfo.createVirtualRegister(RC);
@@ -1400,30 +1473,31 @@ MachineBasicBlock * MipsTargetLowering::emitAtomicCmpSwap(MachineInstr *MI,
BuildMI(BB, DL, TII->get(BEQ))
.addReg(Success).addReg(ZERO).addMBB(loop1MBB);
- MI->eraseFromParent(); // The instruction is gone now.
+ MI.eraseFromParent(); // The instruction is gone now.
return exitMBB;
}
-MachineBasicBlock *
-MipsTargetLowering::emitAtomicCmpSwapPartword(MachineInstr *MI,
- MachineBasicBlock *BB,
- unsigned Size) const {
+MachineBasicBlock *MipsTargetLowering::emitAtomicCmpSwapPartword(
+ MachineInstr &MI, MachineBasicBlock *BB, unsigned Size) const {
assert((Size == 1 || Size == 2) &&
"Unsupported size for EmitAtomicCmpSwapPartial.");
MachineFunction *MF = BB->getParent();
MachineRegisterInfo &RegInfo = MF->getRegInfo();
const TargetRegisterClass *RC = getRegClassFor(MVT::i32);
+ const bool ArePtrs64bit = ABI.ArePtrs64bit();
+ const TargetRegisterClass *RCp =
+ getRegClassFor(ArePtrs64bit ? MVT::i64 : MVT::i32);
const TargetInstrInfo *TII = Subtarget.getInstrInfo();
- DebugLoc DL = MI->getDebugLoc();
+ DebugLoc DL = MI.getDebugLoc();
- unsigned Dest = MI->getOperand(0).getReg();
- unsigned Ptr = MI->getOperand(1).getReg();
- unsigned CmpVal = MI->getOperand(2).getReg();
- unsigned NewVal = MI->getOperand(3).getReg();
+ unsigned Dest = MI.getOperand(0).getReg();
+ unsigned Ptr = MI.getOperand(1).getReg();
+ unsigned CmpVal = MI.getOperand(2).getReg();
+ unsigned NewVal = MI.getOperand(3).getReg();
- unsigned AlignedAddr = RegInfo.createVirtualRegister(RC);
+ unsigned AlignedAddr = RegInfo.createVirtualRegister(RCp);
unsigned ShiftAmt = RegInfo.createVirtualRegister(RC);
unsigned Mask = RegInfo.createVirtualRegister(RC);
unsigned Mask2 = RegInfo.createVirtualRegister(RC);
@@ -1431,7 +1505,7 @@ MipsTargetLowering::emitAtomicCmpSwapPartword(MachineInstr *MI,
unsigned OldVal = RegInfo.createVirtualRegister(RC);
unsigned MaskedOldVal0 = RegInfo.createVirtualRegister(RC);
unsigned ShiftedNewVal = RegInfo.createVirtualRegister(RC);
- unsigned MaskLSB2 = RegInfo.createVirtualRegister(RC);
+ unsigned MaskLSB2 = RegInfo.createVirtualRegister(RCp);
unsigned PtrLSB2 = RegInfo.createVirtualRegister(RC);
unsigned MaskUpper = RegInfo.createVirtualRegister(RC);
unsigned MaskedCmpVal = RegInfo.createVirtualRegister(RC);
@@ -1440,6 +1514,17 @@ MipsTargetLowering::emitAtomicCmpSwapPartword(MachineInstr *MI,
unsigned StoreVal = RegInfo.createVirtualRegister(RC);
unsigned SrlRes = RegInfo.createVirtualRegister(RC);
unsigned Success = RegInfo.createVirtualRegister(RC);
+ unsigned LL, SC;
+
+ if (isMicroMips) {
+ LL = Mips::LL_MM;
+ SC = Mips::SC_MM;
+ } else {
+ LL = Subtarget.hasMips32r6() ? (ArePtrs64bit ? Mips::LL64_R6 : Mips::LL_R6)
+ : (ArePtrs64bit ? Mips::LL64 : Mips::LL);
+ SC = Subtarget.hasMips32r6() ? (ArePtrs64bit ? Mips::SC64_R6 : Mips::SC_R6)
+ : (ArePtrs64bit ? Mips::SC64 : Mips::SC);
+ }
// insert new blocks after the current block
const BasicBlock *LLVM_BB = BB->getBasicBlock();
@@ -1470,6 +1555,7 @@ MipsTargetLowering::emitAtomicCmpSwapPartword(MachineInstr *MI,
// addiu masklsb2,$0,-4 # 0xfffffffc
// and alignedaddr,ptr,masklsb2
// andi ptrlsb2,ptr,3
+ // xori ptrlsb2,ptrlsb2,3 # Only for BE
// sll shiftamt,ptrlsb2,3
// ori maskupper,$0,255 # 0xff
// sll mask,maskupper,shiftamt
@@ -1479,11 +1565,12 @@ MipsTargetLowering::emitAtomicCmpSwapPartword(MachineInstr *MI,
// andi maskednewval,newval,255
// sll shiftednewval,maskednewval,shiftamt
int64_t MaskImm = (Size == 1) ? 255 : 65535;
- BuildMI(BB, DL, TII->get(Mips::ADDiu), MaskLSB2)
- .addReg(Mips::ZERO).addImm(-4);
- BuildMI(BB, DL, TII->get(Mips::AND), AlignedAddr)
+ BuildMI(BB, DL, TII->get(ArePtrs64bit ? Mips::DADDiu : Mips::ADDiu), MaskLSB2)
+ .addReg(ABI.GetNullPtr()).addImm(-4);
+ BuildMI(BB, DL, TII->get(ArePtrs64bit ? Mips::AND64 : Mips::AND), AlignedAddr)
.addReg(Ptr).addReg(MaskLSB2);
- BuildMI(BB, DL, TII->get(Mips::ANDi), PtrLSB2).addReg(Ptr).addImm(3);
+ BuildMI(BB, DL, TII->get(Mips::ANDi), PtrLSB2)
+ .addReg(Ptr, 0, ArePtrs64bit ? Mips::sub_32 : 0).addImm(3);
if (Subtarget.isLittle()) {
BuildMI(BB, DL, TII->get(Mips::SLL), ShiftAmt).addReg(PtrLSB2).addImm(3);
} else {
@@ -1511,7 +1598,6 @@ MipsTargetLowering::emitAtomicCmpSwapPartword(MachineInstr *MI,
// and maskedoldval0,oldval,mask
// bne maskedoldval0,shiftedcmpval,sinkMBB
BB = loop1MBB;
- unsigned LL = isMicroMips ? Mips::LL_MM : Mips::LL;
BuildMI(BB, DL, TII->get(LL), OldVal).addReg(AlignedAddr).addImm(0);
BuildMI(BB, DL, TII->get(Mips::AND), MaskedOldVal0)
.addReg(OldVal).addReg(Mask);
@@ -1528,7 +1614,6 @@ MipsTargetLowering::emitAtomicCmpSwapPartword(MachineInstr *MI,
.addReg(OldVal).addReg(Mask2);
BuildMI(BB, DL, TII->get(Mips::OR), StoreVal)
.addReg(MaskedOldVal1).addReg(ShiftedNewVal);
- unsigned SC = isMicroMips ? Mips::SC_MM : Mips::SC;
BuildMI(BB, DL, TII->get(SC), Success)
.addReg(StoreVal).addReg(AlignedAddr).addImm(0);
BuildMI(BB, DL, TII->get(Mips::BEQ))
@@ -1543,21 +1628,21 @@ MipsTargetLowering::emitAtomicCmpSwapPartword(MachineInstr *MI,
.addReg(MaskedOldVal0).addReg(ShiftAmt);
BB = emitSignExtendToI32InReg(MI, BB, Size, Dest, SrlRes);
- MI->eraseFromParent(); // The instruction is gone now.
+ MI.eraseFromParent(); // The instruction is gone now.
return exitMBB;
}
-MachineBasicBlock *MipsTargetLowering::emitSEL_D(MachineInstr *MI,
+MachineBasicBlock *MipsTargetLowering::emitSEL_D(MachineInstr &MI,
MachineBasicBlock *BB) const {
MachineFunction *MF = BB->getParent();
const TargetRegisterInfo *TRI = Subtarget.getRegisterInfo();
const TargetInstrInfo *TII = Subtarget.getInstrInfo();
MachineRegisterInfo &RegInfo = MF->getRegInfo();
- DebugLoc DL = MI->getDebugLoc();
+ DebugLoc DL = MI.getDebugLoc();
MachineBasicBlock::iterator II(MI);
- unsigned Fc = MI->getOperand(1).getReg();
+ unsigned Fc = MI.getOperand(1).getReg();
const auto &FGR64RegClass = TRI->getRegClass(Mips::FGR64RegClassID);
unsigned Fc2 = RegInfo.createVirtualRegister(FGR64RegClass);
@@ -1569,7 +1654,7 @@ MachineBasicBlock *MipsTargetLowering::emitSEL_D(MachineInstr *MI,
// We don't erase the original instruction, we just replace the condition
// register with the 64-bit super-register.
- MI->getOperand(1).setReg(Fc2);
+ MI.getOperand(1).setReg(Fc2);
return BB;
}
@@ -1592,13 +1677,12 @@ SDValue MipsTargetLowering::lowerBR_JT(SDValue Op, SelectionDAG &DAG) const {
SDValue Addr = DAG.getNode(ISD::ADD, DL, PTy, Index, Table);
EVT MemVT = EVT::getIntegerVT(*DAG.getContext(), EntrySize * 8);
- Addr =
- DAG.getExtLoad(ISD::SEXTLOAD, DL, PTy, Chain, Addr,
- MachinePointerInfo::getJumpTable(DAG.getMachineFunction()),
- MemVT, false, false, false, 0);
+ Addr = DAG.getExtLoad(
+ ISD::SEXTLOAD, DL, PTy, Chain, Addr,
+ MachinePointerInfo::getJumpTable(DAG.getMachineFunction()), MemVT);
Chain = Addr.getValue(1);
- if ((getTargetMachine().getRelocationModel() == Reloc::PIC_) || ABI.IsN64()) {
+ if (isPositionIndependent() || ABI.IsN64()) {
// For PIC, the sequence is:
// BRIND(load(Jumptable + index) + RelocBase)
// RelocBase can be JumpTable, GOT or some sort of global base.
@@ -1667,7 +1751,7 @@ SDValue MipsTargetLowering::lowerGlobalAddress(SDValue Op,
GlobalAddressSDNode *N = cast<GlobalAddressSDNode>(Op);
const GlobalValue *GV = N->getGlobal();
- if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !ABI.IsN64()) {
+ if (!isPositionIndependent() && !ABI.IsN64()) {
const MipsTargetObjectFile *TLOF =
static_cast<const MipsTargetObjectFile *>(
getTargetMachine().getObjFileLowering());
@@ -1679,7 +1763,18 @@ SDValue MipsTargetLowering::lowerGlobalAddress(SDValue Op,
return getAddrNonPIC(N, SDLoc(N), Ty, DAG);
}
- if (GV->hasInternalLinkage() || (GV->hasLocalLinkage() && !isa<Function>(GV)))
+ // Every other architecture would use shouldAssumeDSOLocal in here, but
+ // mips is special.
+ // * In PIC code mips requires got loads even for local statics!
+ // * To save on got entries, for local statics the got entry contains the
+ // page and an additional add instruction takes care of the low bits.
+ // * It is legal to access a hidden symbol with a non hidden undefined,
+ // so one cannot guarantee that all access to a hidden symbol will know
+ // it is hidden.
+ // * Mips linkers don't support creating a page and a full got entry for
+ // the same symbol.
+ // * Given all that, we have to use a full got entry for hidden symbols :-(
+ if (GV->hasLocalLinkage())
return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64());
if (LargeGOT)
@@ -1690,7 +1785,7 @@ SDValue MipsTargetLowering::lowerGlobalAddress(SDValue Op,
return getAddrGlobal(
N, SDLoc(N), Ty, DAG,
- (ABI.IsN32() || ABI.IsN64()) ? MipsII::MO_GOT_DISP : MipsII::MO_GOT16,
+ (ABI.IsN32() || ABI.IsN64()) ? MipsII::MO_GOT_DISP : MipsII::MO_GOT,
DAG.getEntryNode(), MachinePointerInfo::getGOT(DAG.getMachineFunction()));
}
@@ -1699,7 +1794,7 @@ SDValue MipsTargetLowering::lowerBlockAddress(SDValue Op,
BlockAddressSDNode *N = cast<BlockAddressSDNode>(Op);
EVT Ty = Op.getValueType();
- if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !ABI.IsN64())
+ if (!isPositionIndependent() && !ABI.IsN64())
return getAddrNonPIC(N, SDLoc(N), Ty, DAG);
return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64());
@@ -1743,7 +1838,7 @@ lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const
TargetLowering::CallLoweringInfo CLI(DAG);
CLI.setDebugLoc(DL).setChain(DAG.getEntryNode())
- .setCallee(CallingConv::C, PtrTy, TlsGetAddr, std::move(Args), 0);
+ .setCallee(CallingConv::C, PtrTy, TlsGetAddr, std::move(Args));
std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI);
SDValue Ret = CallResult.first;
@@ -1768,9 +1863,8 @@ lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const
MipsII::MO_GOTTPREL);
TGA = DAG.getNode(MipsISD::Wrapper, DL, PtrVT, getGlobalReg(DAG, PtrVT),
TGA);
- Offset = DAG.getLoad(PtrVT, DL,
- DAG.getEntryNode(), TGA, MachinePointerInfo(),
- false, false, false, 0);
+ Offset =
+ DAG.getLoad(PtrVT, DL, DAG.getEntryNode(), TGA, MachinePointerInfo());
} else {
// Local Exec TLS Model
assert(model == TLSModel::LocalExec);
@@ -1793,7 +1887,7 @@ lowerJumpTable(SDValue Op, SelectionDAG &DAG) const
JumpTableSDNode *N = cast<JumpTableSDNode>(Op);
EVT Ty = Op.getValueType();
- if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !ABI.IsN64())
+ if (!isPositionIndependent() && !ABI.IsN64())
return getAddrNonPIC(N, SDLoc(N), Ty, DAG);
return getAddrLocal(N, SDLoc(N), Ty, DAG, ABI.IsN32() || ABI.IsN64());
@@ -1805,7 +1899,7 @@ lowerConstantPool(SDValue Op, SelectionDAG &DAG) const
ConstantPoolSDNode *N = cast<ConstantPoolSDNode>(Op);
EVT Ty = Op.getValueType();
- if (getTargetMachine().getRelocationModel() != Reloc::PIC_ && !ABI.IsN64()) {
+ if (!isPositionIndependent() && !ABI.IsN64()) {
const MipsTargetObjectFile *TLOF =
static_cast<const MipsTargetObjectFile *>(
getTargetMachine().getObjFileLowering());
@@ -1833,7 +1927,7 @@ SDValue MipsTargetLowering::lowerVASTART(SDValue Op, SelectionDAG &DAG) const {
// memory location argument.
const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
return DAG.getStore(Op.getOperand(0), DL, FI, Op.getOperand(1),
- MachinePointerInfo(SV), false, false, 0);
+ MachinePointerInfo(SV));
}
SDValue MipsTargetLowering::lowerVAARG(SDValue Op, SelectionDAG &DAG) const {
@@ -1846,9 +1940,8 @@ SDValue MipsTargetLowering::lowerVAARG(SDValue Op, SelectionDAG &DAG) const {
SDLoc DL(Node);
unsigned ArgSlotSizeInBytes = (ABI.IsN32() || ABI.IsN64()) ? 8 : 4;
- SDValue VAListLoad =
- DAG.getLoad(getPointerTy(DAG.getDataLayout()), DL, Chain, VAListPtr,
- MachinePointerInfo(SV), false, false, false, 0);
+ SDValue VAListLoad = DAG.getLoad(getPointerTy(DAG.getDataLayout()), DL, Chain,
+ VAListPtr, MachinePointerInfo(SV));
SDValue VAList = VAListLoad;
// Re-align the pointer if necessary.
@@ -1873,13 +1966,13 @@ SDValue MipsTargetLowering::lowerVAARG(SDValue Op, SelectionDAG &DAG) const {
auto &TD = DAG.getDataLayout();
unsigned ArgSizeInBytes =
TD.getTypeAllocSize(VT.getTypeForEVT(*DAG.getContext()));
- SDValue Tmp3 = DAG.getNode(ISD::ADD, DL, VAList.getValueType(), VAList,
- DAG.getConstant(RoundUpToAlignment(ArgSizeInBytes,
- ArgSlotSizeInBytes),
- DL, VAList.getValueType()));
+ SDValue Tmp3 =
+ DAG.getNode(ISD::ADD, DL, VAList.getValueType(), VAList,
+ DAG.getConstant(alignTo(ArgSizeInBytes, ArgSlotSizeInBytes),
+ DL, VAList.getValueType()));
// Store the incremented VAList to the legalized pointer
Chain = DAG.getStore(VAListLoad.getValue(1), DL, Tmp3, VAListPtr,
- MachinePointerInfo(SV), false, false, 0);
+ MachinePointerInfo(SV));
// In big-endian mode we must adjust the pointer when the load size is smaller
// than the argument slot size. We must also reduce the known alignment to
@@ -1892,8 +1985,7 @@ SDValue MipsTargetLowering::lowerVAARG(SDValue Op, SelectionDAG &DAG) const {
DAG.getIntPtrConstant(Adjustment, DL));
}
// Load the actual argument out of the pointer VAList
- return DAG.getLoad(VT, DL, Chain, VAList, MachinePointerInfo(), false, false,
- false, 0);
+ return DAG.getLoad(VT, DL, Chain, VAList, MachinePointerInfo());
}
static SDValue lowerFCOPYSIGN32(SDValue Op, SelectionDAG &DAG,
@@ -2283,10 +2375,9 @@ static SDValue lowerFP_TO_SINT_STORE(StoreSDNode *SD, SelectionDAG &DAG) {
EVT FPTy = EVT::getFloatingPointVT(Val.getValueSizeInBits());
SDValue Tr = DAG.getNode(MipsISD::TruncIntFP, SDLoc(Val), FPTy,
Val.getOperand(0));
-
return DAG.getStore(SD->getChain(), SDLoc(SD), Tr, SD->getBasePtr(),
- SD->getPointerInfo(), SD->isVolatile(),
- SD->isNonTemporal(), SD->getAlignment());
+ SD->getPointerInfo(), SD->getAlignment(),
+ SD->getMemOperand()->getFlags());
}
SDValue MipsTargetLowering::lowerSTORE(SDValue Op, SelectionDAG &DAG) const {
@@ -2472,23 +2563,22 @@ static unsigned getNextIntArgReg(unsigned Reg) {
return (Reg == Mips::A0) ? Mips::A1 : Mips::A3;
}
-SDValue
-MipsTargetLowering::passArgOnStack(SDValue StackPtr, unsigned Offset,
- SDValue Chain, SDValue Arg, SDLoc DL,
- bool IsTailCall, SelectionDAG &DAG) const {
+SDValue MipsTargetLowering::passArgOnStack(SDValue StackPtr, unsigned Offset,
+ SDValue Chain, SDValue Arg,
+ const SDLoc &DL, bool IsTailCall,
+ SelectionDAG &DAG) const {
if (!IsTailCall) {
SDValue PtrOff =
DAG.getNode(ISD::ADD, DL, getPointerTy(DAG.getDataLayout()), StackPtr,
DAG.getIntPtrConstant(Offset, DL));
- return DAG.getStore(Chain, DL, Arg, PtrOff, MachinePointerInfo(), false,
- false, 0);
+ return DAG.getStore(Chain, DL, Arg, PtrOff, MachinePointerInfo());
}
MachineFrameInfo *MFI = DAG.getMachineFunction().getFrameInfo();
int FI = MFI->CreateFixedObject(Arg.getValueSizeInBits() / 8, Offset, false);
SDValue FIN = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));
return DAG.getStore(Chain, DL, Arg, FIN, MachinePointerInfo(),
- /*isVolatile=*/ true, false, 0);
+ /* Alignment = */ 0, MachineMemOperand::MOVolatile);
}
void MipsTargetLowering::
@@ -2571,7 +2661,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
MachineFrameInfo *MFI = MF.getFrameInfo();
const TargetFrameLowering *TFL = Subtarget.getFrameLowering();
MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>();
- bool IsPIC = getTargetMachine().getRelocationModel() == Reloc::PIC_;
+ bool IsPIC = isPositionIndependent();
// Analyze operands of the call, assigning locations to each operand.
SmallVector<CCValAssign, 16> ArgLocs;
@@ -2604,7 +2694,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
// ByValChain is the output chain of the last Memcpy node created for copying
// byval arguments to the stack.
unsigned StackAlignment = TFL->getStackAlignment();
- NextStackOffset = RoundUpToAlignment(NextStackOffset, StackAlignment);
+ NextStackOffset = alignTo(NextStackOffset, StackAlignment);
SDValue NextStackOffsetVal = DAG.getIntPtrConstant(NextStackOffset, DL, true);
if (!IsTailCall)
@@ -2614,7 +2704,6 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
DAG.getCopyFromReg(Chain, DL, ABI.IsN64() ? Mips::SP_64 : Mips::SP,
getPointerTy(DAG.getDataLayout()));
- // With EABI is it possible to have 16 args on registers.
std::deque< std::pair<unsigned, SDValue> > RegsToPass;
SmallVector<SDValue, 8> MemOpChains;
@@ -2802,8 +2891,8 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
/// appropriate copies out of appropriate physical registers.
SDValue MipsTargetLowering::LowerCallResult(
SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, bool IsVarArg,
- const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc DL, SelectionDAG &DAG,
- SmallVectorImpl<SDValue> &InVals,
+ const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
+ SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals,
TargetLowering::CallLoweringInfo &CLI) const {
// Assign locations to each value returned by this call.
SmallVector<CCValAssign, 16> RVLocs;
@@ -2864,7 +2953,8 @@ SDValue MipsTargetLowering::LowerCallResult(
}
static SDValue UnpackFromArgumentSlot(SDValue Val, const CCValAssign &VA,
- EVT ArgVT, SDLoc DL, SelectionDAG &DAG) {
+ EVT ArgVT, const SDLoc &DL,
+ SelectionDAG &DAG) {
MVT LocVT = VA.getLocVT();
EVT ValVT = VA.getValVT();
@@ -2922,14 +3012,10 @@ static SDValue UnpackFromArgumentSlot(SDValue Val, const CCValAssign &VA,
//===----------------------------------------------------------------------===//
/// LowerFormalArguments - transform physical registers into virtual registers
/// and generate load operations for arguments places on the stack.
-SDValue
-MipsTargetLowering::LowerFormalArguments(SDValue Chain,
- CallingConv::ID CallConv,
- bool IsVarArg,
- const SmallVectorImpl<ISD::InputArg> &Ins,
- SDLoc DL, SelectionDAG &DAG,
- SmallVectorImpl<SDValue> &InVals)
- const {
+SDValue MipsTargetLowering::LowerFormalArguments(
+ SDValue Chain, CallingConv::ID CallConv, bool IsVarArg,
+ const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &DL,
+ SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals) const {
MachineFunction &MF = DAG.getMachineFunction();
MachineFrameInfo *MFI = MF.getFrameInfo();
MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
@@ -3037,8 +3123,7 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain,
SDValue FIN = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));
SDValue ArgValue = DAG.getLoad(
LocVT, DL, Chain, FIN,
- MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI),
- false, false, false, 0);
+ MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI));
OutChains.push_back(ArgValue.getValue(1));
ArgValue = UnpackFromArgumentSlot(ArgValue, VA, Ins[i].ArgVT, DL, DAG);
@@ -3102,7 +3187,8 @@ MipsTargetLowering::shouldSignExtendTypeInLibCall(EVT Type, bool IsSigned) const
SDValue
MipsTargetLowering::LowerInterruptReturn(SmallVectorImpl<SDValue> &RetOps,
- SDLoc DL, SelectionDAG &DAG) const {
+ const SDLoc &DL,
+ SelectionDAG &DAG) const {
MachineFunction &MF = DAG.getMachineFunction();
MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
@@ -3117,7 +3203,7 @@ MipsTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv,
bool IsVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<SDValue> &OutVals,
- SDLoc DL, SelectionDAG &DAG) const {
+ const SDLoc &DL, SelectionDAG &DAG) const {
// CCValAssign - represent the assignment of
// the return value to a location
SmallVector<CCValAssign, 16> RVLocs;
@@ -3625,10 +3711,11 @@ bool MipsTargetLowering::useSoftFloat() const {
}
void MipsTargetLowering::copyByValRegs(
- SDValue Chain, SDLoc DL, std::vector<SDValue> &OutChains, SelectionDAG &DAG,
- const ISD::ArgFlagsTy &Flags, SmallVectorImpl<SDValue> &InVals,
- const Argument *FuncArg, unsigned FirstReg, unsigned LastReg,
- const CCValAssign &VA, MipsCCState &State) const {
+ SDValue Chain, const SDLoc &DL, std::vector<SDValue> &OutChains,
+ SelectionDAG &DAG, const ISD::ArgFlagsTy &Flags,
+ SmallVectorImpl<SDValue> &InVals, const Argument *FuncArg,
+ unsigned FirstReg, unsigned LastReg, const CCValAssign &VA,
+ MipsCCState &State) const {
MachineFunction &MF = DAG.getMachineFunction();
MachineFrameInfo *MFI = MF.getFrameInfo();
unsigned GPRSizeInBytes = Subtarget.getGPRSizeInBytes();
@@ -3665,15 +3752,14 @@ void MipsTargetLowering::copyByValRegs(
SDValue StorePtr = DAG.getNode(ISD::ADD, DL, PtrTy, FIN,
DAG.getConstant(Offset, DL, PtrTy));
SDValue Store = DAG.getStore(Chain, DL, DAG.getRegister(VReg, RegTy),
- StorePtr, MachinePointerInfo(FuncArg, Offset),
- false, false, 0);
+ StorePtr, MachinePointerInfo(FuncArg, Offset));
OutChains.push_back(Store);
}
}
// Copy byVal arg to registers and stack.
void MipsTargetLowering::passByValArg(
- SDValue Chain, SDLoc DL,
+ SDValue Chain, const SDLoc &DL,
std::deque<std::pair<unsigned, SDValue>> &RegsToPass,
SmallVectorImpl<SDValue> &MemOpChains, SDValue StackPtr,
MachineFrameInfo *MFI, SelectionDAG &DAG, SDValue Arg, unsigned FirstReg,
@@ -3697,8 +3783,7 @@ void MipsTargetLowering::passByValArg(
SDValue LoadPtr = DAG.getNode(ISD::ADD, DL, PtrTy, Arg,
DAG.getConstant(OffsetInBytes, DL, PtrTy));
SDValue LoadVal = DAG.getLoad(RegTy, DL, Chain, LoadPtr,
- MachinePointerInfo(), false, false, false,
- Alignment);
+ MachinePointerInfo(), Alignment);
MemOpChains.push_back(LoadVal.getValue(1));
unsigned ArgReg = ArgRegs[FirstReg + I];
RegsToPass.push_back(std::make_pair(ArgReg, LoadVal));
@@ -3725,8 +3810,7 @@ void MipsTargetLowering::passByValArg(
PtrTy));
SDValue LoadVal = DAG.getExtLoad(
ISD::ZEXTLOAD, DL, RegTy, Chain, LoadPtr, MachinePointerInfo(),
- MVT::getIntegerVT(LoadSizeInBytes * 8), false, false, false,
- Alignment);
+ MVT::getIntegerVT(LoadSizeInBytes * 8), Alignment);
MemOpChains.push_back(LoadVal.getValue(1));
// Shift the loaded value.
@@ -3771,7 +3855,7 @@ void MipsTargetLowering::passByValArg(
}
void MipsTargetLowering::writeVarArgRegs(std::vector<SDValue> &OutChains,
- SDValue Chain, SDLoc DL,
+ SDValue Chain, const SDLoc &DL,
SelectionDAG &DAG,
CCState &State) const {
ArrayRef<MCPhysReg> ArgRegs = ABI.GetVarArgRegs();
@@ -3787,8 +3871,7 @@ void MipsTargetLowering::writeVarArgRegs(std::vector<SDValue> &OutChains,
int VaArgOffset;
if (ArgRegs.size() == Idx)
- VaArgOffset =
- RoundUpToAlignment(State.getNextStackOffset(), RegSizeInBytes);
+ VaArgOffset = alignTo(State.getNextStackOffset(), RegSizeInBytes);
else {
VaArgOffset =
(int)ABI.GetCalleeAllocdArgSizeInBytes(State.getCallingConv()) -
@@ -3810,8 +3893,8 @@ void MipsTargetLowering::writeVarArgRegs(std::vector<SDValue> &OutChains,
SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, RegTy);
FI = MFI->CreateFixedObject(RegSizeInBytes, VaArgOffset, true);
SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout()));
- SDValue Store = DAG.getStore(Chain, DL, ArgValue, PtrOff,
- MachinePointerInfo(), false, false, 0);
+ SDValue Store =
+ DAG.getStore(Chain, DL, ArgValue, PtrOff, MachinePointerInfo());
cast<StoreSDNode>(Store.getNode())->getMemOperand()->setValue(
(Value *)nullptr);
OutChains.push_back(Store);
@@ -3854,7 +3937,7 @@ void MipsTargetLowering::HandleByVal(CCState *State, unsigned &Size,
}
// Mark the registers allocated.
- Size = RoundUpToAlignment(Size, RegSizeInBytes);
+ Size = alignTo(Size, RegSizeInBytes);
for (unsigned I = FirstReg; Size > 0 && (I < IntArgRegs.size());
Size -= RegSizeInBytes, ++I, ++NumRegs)
State->AllocateReg(IntArgRegs[I], ShadowRegs[I]);
@@ -3863,16 +3946,17 @@ void MipsTargetLowering::HandleByVal(CCState *State, unsigned &Size,
State->addInRegsParamInfo(FirstReg, FirstReg + NumRegs);
}
-MachineBasicBlock *
-MipsTargetLowering::emitPseudoSELECT(MachineInstr *MI, MachineBasicBlock *BB,
- bool isFPCmp, unsigned Opc) const {
+MachineBasicBlock *MipsTargetLowering::emitPseudoSELECT(MachineInstr &MI,
+ MachineBasicBlock *BB,
+ bool isFPCmp,
+ unsigned Opc) const {
assert(!(Subtarget.hasMips4() || Subtarget.hasMips32()) &&
"Subtarget already supports SELECT nodes with the use of"
"conditional-move instructions.");
const TargetInstrInfo *TII =
Subtarget.getInstrInfo();
- DebugLoc DL = MI->getDebugLoc();
+ DebugLoc DL = MI.getDebugLoc();
// To "insert" a SELECT instruction, we actually have to insert the
// diamond control-flow pattern. The incoming instruction knows the
@@ -3906,14 +3990,14 @@ MipsTargetLowering::emitPseudoSELECT(MachineInstr *MI, MachineBasicBlock *BB,
if (isFPCmp) {
// bc1[tf] cc, sinkMBB
BuildMI(BB, DL, TII->get(Opc))
- .addReg(MI->getOperand(1).getReg())
- .addMBB(sinkMBB);
+ .addReg(MI.getOperand(1).getReg())
+ .addMBB(sinkMBB);
} else {
// bne rs, $0, sinkMBB
BuildMI(BB, DL, TII->get(Opc))
- .addReg(MI->getOperand(1).getReg())
- .addReg(Mips::ZERO)
- .addMBB(sinkMBB);
+ .addReg(MI.getOperand(1).getReg())
+ .addReg(Mips::ZERO)
+ .addMBB(sinkMBB);
}
// copy0MBB:
@@ -3929,12 +4013,13 @@ MipsTargetLowering::emitPseudoSELECT(MachineInstr *MI, MachineBasicBlock *BB,
// ...
BB = sinkMBB;
- BuildMI(*BB, BB->begin(), DL,
- TII->get(Mips::PHI), MI->getOperand(0).getReg())
- .addReg(MI->getOperand(2).getReg()).addMBB(thisMBB)
- .addReg(MI->getOperand(3).getReg()).addMBB(copy0MBB);
+ BuildMI(*BB, BB->begin(), DL, TII->get(Mips::PHI), MI.getOperand(0).getReg())
+ .addReg(MI.getOperand(2).getReg())
+ .addMBB(thisMBB)
+ .addReg(MI.getOperand(3).getReg())
+ .addMBB(copy0MBB);
- MI->eraseFromParent(); // The pseudo instruction is gone now.
+ MI.eraseFromParent(); // The pseudo instruction is gone now.
return BB;
}
diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h
index 0dc683e3df27f..182dc9070fc8a 100644
--- a/lib/Target/Mips/MipsISelLowering.h
+++ b/lib/Target/Mips/MipsISelLowering.h
@@ -238,6 +238,10 @@ namespace llvm {
bool isCheapToSpeculateCttz() const override;
bool isCheapToSpeculateCtlz() const override;
+ ISD::NodeType getExtendForAtomicOps() const override {
+ return ISD::SIGN_EXTEND;
+ }
+
void LowerOperationWrapper(SDNode *N,
SmallVectorImpl<SDValue> &Results,
SelectionDAG &DAG) const override;
@@ -262,7 +266,7 @@ namespace llvm {
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override;
MachineBasicBlock *
- EmitInstrWithCustomInserter(MachineInstr *MI,
+ EmitInstrWithCustomInserter(MachineInstr &MI,
MachineBasicBlock *MBB) const override;
void HandleByVal(CCState *, unsigned &, unsigned) const override;
@@ -300,15 +304,14 @@ namespace llvm {
//
// (add (load (wrapper $gp, %got(sym)), %lo(sym))
template <class NodeTy>
- SDValue getAddrLocal(NodeTy *N, SDLoc DL, EVT Ty, SelectionDAG &DAG,
+ SDValue getAddrLocal(NodeTy *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG,
bool IsN32OrN64) const {
unsigned GOTFlag = IsN32OrN64 ? MipsII::MO_GOT_PAGE : MipsII::MO_GOT;
SDValue GOT = DAG.getNode(MipsISD::Wrapper, DL, Ty, getGlobalReg(DAG, Ty),
getTargetNode(N, Ty, DAG, GOTFlag));
SDValue Load =
DAG.getLoad(Ty, DL, DAG.getEntryNode(), GOT,
- MachinePointerInfo::getGOT(DAG.getMachineFunction()),
- false, false, false, 0);
+ MachinePointerInfo::getGOT(DAG.getMachineFunction()));
unsigned LoFlag = IsN32OrN64 ? MipsII::MO_GOT_OFST : MipsII::MO_ABS_LO;
SDValue Lo = DAG.getNode(MipsISD::Lo, DL, Ty,
getTargetNode(N, Ty, DAG, LoFlag));
@@ -320,12 +323,12 @@ namespace llvm {
//
// (load (wrapper $gp, %got(sym)))
template <class NodeTy>
- SDValue getAddrGlobal(NodeTy *N, SDLoc DL, EVT Ty, SelectionDAG &DAG,
+ SDValue getAddrGlobal(NodeTy *N, const SDLoc &DL, EVT Ty, SelectionDAG &DAG,
unsigned Flag, SDValue Chain,
const MachinePointerInfo &PtrInfo) const {
SDValue Tgt = DAG.getNode(MipsISD::Wrapper, DL, Ty, getGlobalReg(DAG, Ty),
getTargetNode(N, Ty, DAG, Flag));
- return DAG.getLoad(Ty, DL, Chain, Tgt, PtrInfo, false, false, false, 0);
+ return DAG.getLoad(Ty, DL, Chain, Tgt, PtrInfo);
}
// This method creates the following nodes, which are necessary for
@@ -333,7 +336,7 @@ namespace llvm {
//
// (load (wrapper (add %hi(sym), $gp), %lo(sym)))
template <class NodeTy>
- SDValue getAddrGlobalLargeGOT(NodeTy *N, SDLoc DL, EVT Ty,
+ SDValue getAddrGlobalLargeGOT(NodeTy *N, const SDLoc &DL, EVT Ty,
SelectionDAG &DAG, unsigned HiFlag,
unsigned LoFlag, SDValue Chain,
const MachinePointerInfo &PtrInfo) const {
@@ -342,8 +345,7 @@ namespace llvm {
Hi = DAG.getNode(ISD::ADD, DL, Ty, Hi, getGlobalReg(DAG, Ty));
SDValue Wrapper = DAG.getNode(MipsISD::Wrapper, DL, Ty, Hi,
getTargetNode(N, Ty, DAG, LoFlag));
- return DAG.getLoad(Ty, DL, Chain, Wrapper, PtrInfo, false, false, false,
- 0);
+ return DAG.getLoad(Ty, DL, Chain, Wrapper, PtrInfo);
}
// This method creates the following nodes, which are necessary for
@@ -351,7 +353,7 @@ namespace llvm {
//
// (add %hi(sym), %lo(sym))
template <class NodeTy>
- SDValue getAddrNonPIC(NodeTy *N, SDLoc DL, EVT Ty,
+ SDValue getAddrNonPIC(NodeTy *N, const SDLoc &DL, EVT Ty,
SelectionDAG &DAG) const {
SDValue Hi = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_HI);
SDValue Lo = getTargetNode(N, Ty, DAG, MipsII::MO_ABS_LO);
@@ -365,7 +367,8 @@ namespace llvm {
//
// (add $gp, %gp_rel(sym))
template <class NodeTy>
- SDValue getAddrGPRel(NodeTy *N, SDLoc DL, EVT Ty, SelectionDAG &DAG) const {
+ SDValue getAddrGPRel(NodeTy *N, const SDLoc &DL, EVT Ty,
+ SelectionDAG &DAG) const {
assert(Ty == MVT::i32);
SDValue GPRel = getTargetNode(N, Ty, DAG, MipsII::MO_GPREL);
return DAG.getNode(ISD::ADD, DL, Ty,
@@ -417,8 +420,9 @@ namespace llvm {
// Lower Operand helpers
SDValue LowerCallResult(SDValue Chain, SDValue InFlag,
CallingConv::ID CallConv, bool isVarArg,
- const SmallVectorImpl<ISD::InputArg> &Ins, SDLoc dl,
- SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ const SDLoc &dl, SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals,
TargetLowering::CallLoweringInfo &CLI) const;
// Lower Operand specifics
@@ -455,15 +459,16 @@ namespace llvm {
/// copyByValArg - Copy argument registers which were used to pass a byval
/// argument to the stack. Create a stack frame object for the byval
/// argument.
- void copyByValRegs(SDValue Chain, SDLoc DL, std::vector<SDValue> &OutChains,
- SelectionDAG &DAG, const ISD::ArgFlagsTy &Flags,
+ void copyByValRegs(SDValue Chain, const SDLoc &DL,
+ std::vector<SDValue> &OutChains, SelectionDAG &DAG,
+ const ISD::ArgFlagsTy &Flags,
SmallVectorImpl<SDValue> &InVals,
const Argument *FuncArg, unsigned FirstReg,
unsigned LastReg, const CCValAssign &VA,
MipsCCState &State) const;
/// passByValArg - Pass a byval argument in registers or on stack.
- void passByValArg(SDValue Chain, SDLoc DL,
+ void passByValArg(SDValue Chain, const SDLoc &DL,
std::deque<std::pair<unsigned, SDValue>> &RegsToPass,
SmallVectorImpl<SDValue> &MemOpChains, SDValue StackPtr,
MachineFrameInfo *MFI, SelectionDAG &DAG, SDValue Arg,
@@ -475,17 +480,17 @@ namespace llvm {
/// to the stack. Also create a stack frame object for the first variable
/// argument.
void writeVarArgRegs(std::vector<SDValue> &OutChains, SDValue Chain,
- SDLoc DL, SelectionDAG &DAG, CCState &State) const;
+ const SDLoc &DL, SelectionDAG &DAG,
+ CCState &State) const;
SDValue
- LowerFormalArguments(SDValue Chain,
- CallingConv::ID CallConv, bool isVarArg,
- const SmallVectorImpl<ISD::InputArg> &Ins,
- SDLoc dl, SelectionDAG &DAG,
- SmallVectorImpl<SDValue> &InVals) const override;
+ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
+ const SmallVectorImpl<ISD::InputArg> &Ins,
+ const SDLoc &dl, SelectionDAG &DAG,
+ SmallVectorImpl<SDValue> &InVals) const override;
SDValue passArgOnStack(SDValue StackPtr, unsigned Offset, SDValue Chain,
- SDValue Arg, SDLoc DL, bool IsTailCall,
+ SDValue Arg, const SDLoc &DL, bool IsTailCall,
SelectionDAG &DAG) const;
SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI,
@@ -496,14 +501,13 @@ namespace llvm {
const SmallVectorImpl<ISD::OutputArg> &Outs,
LLVMContext &Context) const override;
- SDValue LowerReturn(SDValue Chain,
- CallingConv::ID CallConv, bool isVarArg,
+ SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool isVarArg,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<SDValue> &OutVals,
- SDLoc dl, SelectionDAG &DAG) const override;
+ const SDLoc &dl, SelectionDAG &DAG) const override;
- SDValue LowerInterruptReturn(SmallVectorImpl<SDValue> &RetOps, SDLoc DL,
- SelectionDAG &DAG) const;
+ SDValue LowerInterruptReturn(SmallVectorImpl<SDValue> &RetOps,
+ const SDLoc &DL, SelectionDAG &DAG) const;
bool shouldSignExtendTypeInLibCall(EVT Type, bool IsSigned) const override;
@@ -561,25 +565,33 @@ namespace llvm {
unsigned getJumpTableEncoding() const override;
bool useSoftFloat() const override;
+ bool shouldInsertFencesForAtomic(const Instruction *I) const override {
+ return true;
+ }
+
/// Emit a sign-extension using sll/sra, seb, or seh appropriately.
- MachineBasicBlock *emitSignExtendToI32InReg(MachineInstr *MI,
+ MachineBasicBlock *emitSignExtendToI32InReg(MachineInstr &MI,
MachineBasicBlock *BB,
unsigned Size, unsigned DstReg,
unsigned SrcRec) const;
- MachineBasicBlock *emitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB,
- unsigned Size, unsigned BinOpcode, bool Nand = false) const;
- MachineBasicBlock *emitAtomicBinaryPartword(MachineInstr *MI,
- MachineBasicBlock *BB, unsigned Size, unsigned BinOpcode,
- bool Nand = false) const;
- MachineBasicBlock *emitAtomicCmpSwap(MachineInstr *MI,
- MachineBasicBlock *BB, unsigned Size) const;
- MachineBasicBlock *emitAtomicCmpSwapPartword(MachineInstr *MI,
- MachineBasicBlock *BB, unsigned Size) const;
- MachineBasicBlock *emitSEL_D(MachineInstr *MI, MachineBasicBlock *BB) const;
- MachineBasicBlock *emitPseudoSELECT(MachineInstr *MI,
- MachineBasicBlock *BB, bool isFPCmp,
- unsigned Opc) const;
+ MachineBasicBlock *emitAtomicBinary(MachineInstr &MI, MachineBasicBlock *BB,
+ unsigned Size, unsigned BinOpcode,
+ bool Nand = false) const;
+ MachineBasicBlock *emitAtomicBinaryPartword(MachineInstr &MI,
+ MachineBasicBlock *BB,
+ unsigned Size,
+ unsigned BinOpcode,
+ bool Nand = false) const;
+ MachineBasicBlock *emitAtomicCmpSwap(MachineInstr &MI,
+ MachineBasicBlock *BB,
+ unsigned Size) const;
+ MachineBasicBlock *emitAtomicCmpSwapPartword(MachineInstr &MI,
+ MachineBasicBlock *BB,
+ unsigned Size) const;
+ MachineBasicBlock *emitSEL_D(MachineInstr &MI, MachineBasicBlock *BB) const;
+ MachineBasicBlock *emitPseudoSELECT(MachineInstr &MI, MachineBasicBlock *BB,
+ bool isFPCmp, unsigned Opc) const;
};
/// Create MipsTargetLowering objects.
diff --git a/lib/Target/Mips/MipsInstrFPU.td b/lib/Target/Mips/MipsInstrFPU.td
index 377260f89d10e..87b02bdfdfdb2 100644
--- a/lib/Target/Mips/MipsInstrFPU.td
+++ b/lib/Target/Mips/MipsInstrFPU.td
@@ -160,18 +160,18 @@ class MTC1_64_FT<string opstr, RegisterOperand DstRC, RegisterOperand SrcRC,
let Constraints = "$fs = $fs_in";
}
-class LW_FT<string opstr, RegisterOperand RC, InstrItinClass Itin,
- SDPatternOperator OpNode= null_frag> :
- InstSE<(outs RC:$rt), (ins mem:$addr), !strconcat(opstr, "\t$rt, $addr"),
+class LW_FT<string opstr, RegisterOperand RC, DAGOperand MO,
+ InstrItinClass Itin, SDPatternOperator OpNode = null_frag> :
+ InstSE<(outs RC:$rt), (ins MO:$addr), !strconcat(opstr, "\t$rt, $addr"),
[(set RC:$rt, (OpNode addrDefault:$addr))], Itin, FrmFI, opstr>,
HARDFLOAT {
let DecoderMethod = "DecodeFMem";
let mayLoad = 1;
}
-class SW_FT<string opstr, RegisterOperand RC, InstrItinClass Itin,
- SDPatternOperator OpNode= null_frag> :
- InstSE<(outs), (ins RC:$rt, mem:$addr), !strconcat(opstr, "\t$rt, $addr"),
+class SW_FT<string opstr, RegisterOperand RC, DAGOperand MO,
+ InstrItinClass Itin, SDPatternOperator OpNode = null_frag> :
+ InstSE<(outs), (ins RC:$rt, MO:$addr), !strconcat(opstr, "\t$rt, $addr"),
[(OpNode RC:$rt, addrDefault:$addr)], Itin, FrmFI, opstr>, HARDFLOAT {
let DecoderMethod = "DecodeFMem";
let mayStore = 1;
@@ -367,22 +367,28 @@ def MFC1 : MMRel, MFC1_FT<"mfc1", GPR32Opnd, FGR32Opnd, II_MFC1,
bitconvert>, MFC1_FM<0>;
def MTC1 : MMRel, MTC1_FT<"mtc1", FGR32Opnd, GPR32Opnd, II_MTC1,
bitconvert>, MFC1_FM<4>;
-def MFHC1_D32 : MMRel, MFC1_FT<"mfhc1", GPR32Opnd, AFGR64Opnd, II_MFHC1>,
- MFC1_FM<3>, ISA_MIPS32R2, FGR_32;
-def MFHC1_D64 : MFC1_FT<"mfhc1", GPR32Opnd, FGR64Opnd, II_MFHC1>,
- MFC1_FM<3>, ISA_MIPS32R2, FGR_64 {
- let DecoderNamespace = "Mips64";
-}
-def MTHC1_D32 : MMRel, MTC1_64_FT<"mthc1", AFGR64Opnd, GPR32Opnd, II_MTHC1>,
- MFC1_FM<7>, ISA_MIPS32R2, FGR_32;
-def MTHC1_D64 : MTC1_64_FT<"mthc1", FGR64Opnd, GPR32Opnd, II_MTHC1>,
- MFC1_FM<7>, ISA_MIPS32R2, FGR_64 {
- let DecoderNamespace = "Mips64";
-}
-def DMFC1 : MFC1_FT<"dmfc1", GPR64Opnd, FGR64Opnd, II_DMFC1,
- bitconvert>, MFC1_FM<1>, ISA_MIPS3;
-def DMTC1 : MTC1_FT<"dmtc1", FGR64Opnd, GPR64Opnd, II_DMTC1,
- bitconvert>, MFC1_FM<5>, ISA_MIPS3;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def MFHC1_D32 : MMRel, MFC1_FT<"mfhc1", GPR32Opnd, AFGR64Opnd, II_MFHC1>,
+ MFC1_FM<3>, ISA_MIPS32R2, FGR_32;
+ def MFHC1_D64 : MFC1_FT<"mfhc1", GPR32Opnd, FGR64Opnd, II_MFHC1>,
+ MFC1_FM<3>, ISA_MIPS32R2, FGR_64 {
+ let DecoderNamespace = "Mips64";
+ }
+}
+let AdditionalPredicates = [NotInMicroMips] in {
+ def MTHC1_D32 : MMRel, StdMMR6Rel, MTC1_64_FT<"mthc1", AFGR64Opnd, GPR32Opnd, II_MTHC1>,
+ MFC1_FM<7>, ISA_MIPS32R2, FGR_32;
+ def MTHC1_D64 : MTC1_64_FT<"mthc1", FGR64Opnd, GPR32Opnd, II_MTHC1>,
+ MFC1_FM<7>, ISA_MIPS32R2, FGR_64 {
+ let DecoderNamespace = "Mips64";
+ }
+}
+let AdditionalPredicates = [NotInMicroMips] in {
+ def DMTC1 : MTC1_FT<"dmtc1", FGR64Opnd, GPR64Opnd, II_DMTC1,
+ bitconvert>, MFC1_FM<5>, ISA_MIPS3;
+ def DMFC1 : MFC1_FT<"dmfc1", GPR64Opnd, FGR64Opnd, II_DMFC1,
+ bitconvert>, MFC1_FM<1>, ISA_MIPS3;
+}
def FMOV_S : MMRel, ABSS_FT<"mov.s", FGR32Opnd, FGR32Opnd, II_MOV_S>,
ABSS_FM<0x6, 16>;
@@ -394,20 +400,30 @@ def FMOV_D64 : ABSS_FT<"mov.d", FGR64Opnd, FGR64Opnd, II_MOV_D>,
}
/// Floating Point Memory Instructions
-def LWC1 : MMRel, LW_FT<"lwc1", FGR32Opnd, II_LWC1, load>, LW_FM<0x31>;
-def SWC1 : MMRel, SW_FT<"swc1", FGR32Opnd, II_SWC1, store>, LW_FM<0x39>;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def LWC1 : MMRel, LW_FT<"lwc1", FGR32Opnd, mem_simm16, II_LWC1, load>,
+ LW_FM<0x31>;
+ def SWC1 : MMRel, SW_FT<"swc1", FGR32Opnd, mem_simm16, II_SWC1, store>,
+ LW_FM<0x39>;
+}
-let DecoderNamespace = "Mips64" in {
- def LDC164 : LW_FT<"ldc1", FGR64Opnd, II_LDC1, load>, LW_FM<0x35>, ISA_MIPS2,
- FGR_64;
- def SDC164 : SW_FT<"sdc1", FGR64Opnd, II_SDC1, store>, LW_FM<0x3d>, ISA_MIPS2,
- FGR_64;
+let DecoderNamespace = "Mips64", AdditionalPredicates = [NotInMicroMips] in {
+ def LDC164 : StdMMR6Rel, LW_FT<"ldc1", FGR64Opnd, mem_simm16, II_LDC1, load>,
+ LW_FM<0x35>, ISA_MIPS2, FGR_64 {
+ let BaseOpcode = "LDC164";
+ }
+ def SDC164 : StdMMR6Rel, SW_FT<"sdc1", FGR64Opnd, mem_simm16, II_SDC1, store>,
+ LW_FM<0x3d>, ISA_MIPS2, FGR_64;
}
-def LDC1 : MMRel, LW_FT<"ldc1", AFGR64Opnd, II_LDC1, load>, LW_FM<0x35>,
- ISA_MIPS2, FGR_32;
-def SDC1 : MMRel, SW_FT<"sdc1", AFGR64Opnd, II_SDC1, store>, LW_FM<0x3d>,
- ISA_MIPS2, FGR_32;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def LDC1 : MMRel, StdMMR6Rel, LW_FT<"ldc1", AFGR64Opnd, mem_simm16, II_LDC1,
+ load>, LW_FM<0x35>, ISA_MIPS2, FGR_32 {
+ let BaseOpcode = "LDC132";
+ }
+ def SDC1 : MMRel, SW_FT<"sdc1", AFGR64Opnd, mem_simm16, II_SDC1, store>,
+ LW_FM<0x3d>, ISA_MIPS2, FGR_32;
+}
// Indexed loads and stores.
// Base register + offset register addressing mode (indicated by "x" in the
@@ -519,10 +535,12 @@ def BC1TL : MMRel, BC1F_FT<"bc1tl", brtarget, II_BC1TL, MIPS_BRANCH_T, 0>,
BC1F_FM<1, 1>, ISA_MIPS2_NOT_32R6_64R6;
/// Floating Point Compare
-def FCMP_S32 : MMRel, CEQS_FT<"s", FGR32, II_C_CC_S, MipsFPCmp>, CEQS_FM<16>,
- ISA_MIPS1_NOT_32R6_64R6;
-def FCMP_D32 : MMRel, CEQS_FT<"d", AFGR64, II_C_CC_D, MipsFPCmp>, CEQS_FM<17>,
- ISA_MIPS1_NOT_32R6_64R6, FGR_32;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def FCMP_S32 : MMRel, CEQS_FT<"s", FGR32, II_C_CC_S, MipsFPCmp>, CEQS_FM<16>,
+ ISA_MIPS1_NOT_32R6_64R6;
+ def FCMP_D32 : MMRel, CEQS_FT<"d", AFGR64, II_C_CC_D, MipsFPCmp>, CEQS_FM<17>,
+ ISA_MIPS1_NOT_32R6_64R6, FGR_32;
+}
let DecoderNamespace = "Mips64" in
def FCMP_D64 : CEQS_FT<"d", FGR64, II_C_CC_D, MipsFPCmp>, CEQS_FM<17>,
ISA_MIPS1_NOT_32R6_64R6, FGR_64;
@@ -535,7 +553,8 @@ def FCMP_D64 : CEQS_FT<"d", FGR64, II_C_CC_D, MipsFPCmp>, CEQS_FM<17>,
// allocation.
class BuildPairF64Base<RegisterOperand RO> :
PseudoSE<(outs RO:$dst), (ins GPR32Opnd:$lo, GPR32Opnd:$hi),
- [(set RO:$dst, (MipsBuildPairF64 GPR32Opnd:$lo, GPR32Opnd:$hi))]>;
+ [(set RO:$dst, (MipsBuildPairF64 GPR32Opnd:$lo, GPR32Opnd:$hi))],
+ II_MTC1>;
def BuildPairF64 : BuildPairF64Base<AFGR64Opnd>, FGR_32, HARDFLOAT;
def BuildPairF64_64 : BuildPairF64Base<FGR64Opnd>, FGR_64, HARDFLOAT;
@@ -544,13 +563,30 @@ def BuildPairF64_64 : BuildPairF64Base<FGR64Opnd>, FGR_64, HARDFLOAT;
// allocation.
// if n is 0, lower part of src is extracted.
// if n is 1, higher part of src is extracted.
+// This node has associated scheduling information as the pre RA scheduler
+// asserts otherwise.
class ExtractElementF64Base<RegisterOperand RO> :
PseudoSE<(outs GPR32Opnd:$dst), (ins RO:$src, i32imm:$n),
- [(set GPR32Opnd:$dst, (MipsExtractElementF64 RO:$src, imm:$n))]>;
+ [(set GPR32Opnd:$dst, (MipsExtractElementF64 RO:$src, imm:$n))],
+ II_MFC1>;
def ExtractElementF64 : ExtractElementF64Base<AFGR64Opnd>, FGR_32, HARDFLOAT;
def ExtractElementF64_64 : ExtractElementF64Base<FGR64Opnd>, FGR_64, HARDFLOAT;
+def PseudoTRUNC_W_S : MipsAsmPseudoInst<(outs FGR32Opnd:$fd),
+ (ins FGR32Opnd:$fs, GPR32Opnd:$rs),
+ "trunc.w.s\t$fd, $fs, $rs">;
+
+def PseudoTRUNC_W_D32 : MipsAsmPseudoInst<(outs FGR32Opnd:$fd),
+ (ins AFGR64Opnd:$fs, GPR32Opnd:$rs),
+ "trunc.w.d\t$fd, $fs, $rs">,
+ FGR_32, HARDFLOAT;
+
+def PseudoTRUNC_W_D : MipsAsmPseudoInst<(outs FGR32Opnd:$fd),
+ (ins FGR64Opnd:$fs, GPR32Opnd:$rs),
+ "trunc.w.d\t$fd, $fs, $rs">,
+ FGR_64, HARDFLOAT;
+
//===----------------------------------------------------------------------===//
// InstAliases.
//===----------------------------------------------------------------------===//
@@ -606,13 +642,15 @@ def : MipsPat<(f64 (fextend FGR32Opnd:$src)),
(CVT_D64_S FGR32Opnd:$src)>, FGR_64;
// Patterns for loads/stores with a reg+imm operand.
-let AddedComplexity = 40 in {
- def : LoadRegImmPat<LWC1, f32, load>;
- def : StoreRegImmPat<SWC1, f32>;
+let AdditionalPredicates = [NotInMicroMips] in {
+ let AddedComplexity = 40 in {
+ def : LoadRegImmPat<LWC1, f32, load>;
+ def : StoreRegImmPat<SWC1, f32>;
- def : LoadRegImmPat<LDC164, f64, load>, FGR_64;
- def : StoreRegImmPat<SDC164, f64>, FGR_64;
+ def : LoadRegImmPat<LDC164, f64, load>, FGR_64;
+ def : StoreRegImmPat<SDC164, f64>, FGR_64;
- def : LoadRegImmPat<LDC1, f64, load>, FGR_32;
- def : StoreRegImmPat<SDC1, f64>, FGR_32;
+ def : LoadRegImmPat<LDC1, f64, load>, FGR_32;
+ def : StoreRegImmPat<SDC1, f64>, FGR_32;
+ }
}
diff --git a/lib/Target/Mips/MipsInstrFormats.td b/lib/Target/Mips/MipsInstrFormats.td
index 45baf27be518f..0bbb49b6b08ea 100644
--- a/lib/Target/Mips/MipsInstrFormats.td
+++ b/lib/Target/Mips/MipsInstrFormats.td
@@ -94,10 +94,15 @@ class MipsInst<dag outs, dag ins, string asmstr, list<dag> pattern,
//
// Attributes specific to Mips instructions...
//
- bits<4> FormBits = Form.Value;
+ bits<4> FormBits = Form.Value;
+ bit isCTI = 0; // Any form of Control Transfer Instruction.
+ // Required for MIPSR6
+ bit hasForbiddenSlot = 0; // Instruction has a forbidden slot.
// TSFlags layout should be kept in sync with MipsInstrInfo.h.
let TSFlags{3-0} = FormBits;
+ let TSFlags{4} = isCTI;
+ let TSFlags{5} = hasForbiddenSlot;
let DecoderNamespace = "Mips";
diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp
index b1d69506c16f2..800d834e0ab8e 100644
--- a/lib/Target/Mips/MipsInstrInfo.cpp
+++ b/lib/Target/Mips/MipsInstrInfo.cpp
@@ -13,7 +13,6 @@
#include "MipsInstrInfo.h"
#include "InstPrinter/MipsInstPrinter.h"
-#include "MipsAnalyzeImmediate.h"
#include "MipsMachineFunction.h"
#include "MipsSubtarget.h"
#include "llvm/ADT/STLExtras.h"
@@ -47,6 +46,7 @@ bool MipsInstrInfo::isZeroImm(const MachineOperand &op) const {
/// insertNoop - If data hazard condition is found insert the target nop
/// instruction.
+// FIXME: This appears to be dead code.
void MipsInstrInfo::
insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const
{
@@ -54,14 +54,15 @@ insertNoop(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI) const
BuildMI(MBB, MI, DL, get(Mips::NOP));
}
-MachineMemOperand *MipsInstrInfo::GetMemOperand(MachineBasicBlock &MBB, int FI,
- unsigned Flag) const {
+MachineMemOperand *
+MipsInstrInfo::GetMemOperand(MachineBasicBlock &MBB, int FI,
+ MachineMemOperand::Flags Flags) const {
MachineFunction &MF = *MBB.getParent();
MachineFrameInfo &MFI = *MF.getFrameInfo();
unsigned Align = MFI.getObjectAlignment(FI);
return MF.getMachineMemOperand(MachinePointerInfo::getFixedStack(MF, FI),
- Flag, MFI.getObjectSize(FI), Align);
+ Flags, MFI.getObjectSize(FI), Align);
}
//===----------------------------------------------------------------------===//
@@ -83,20 +84,20 @@ void MipsInstrInfo::AnalyzeCondBr(const MachineInstr *Inst, unsigned Opc,
Cond.push_back(Inst->getOperand(i));
}
-bool MipsInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB,
+bool MipsInstrInfo::analyzeBranch(MachineBasicBlock &MBB,
MachineBasicBlock *&TBB,
MachineBasicBlock *&FBB,
SmallVectorImpl<MachineOperand> &Cond,
bool AllowModify) const {
SmallVector<MachineInstr*, 2> BranchInstrs;
- BranchType BT = AnalyzeBranch(MBB, TBB, FBB, Cond, AllowModify, BranchInstrs);
+ BranchType BT = analyzeBranch(MBB, TBB, FBB, Cond, AllowModify, BranchInstrs);
return (BT == BT_None) || (BT == BT_Indirect);
}
-void
-MipsInstrInfo::BuildCondBr(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
- DebugLoc DL, ArrayRef<MachineOperand> Cond) const {
+void MipsInstrInfo::BuildCondBr(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
+ const DebugLoc &DL,
+ ArrayRef<MachineOperand> Cond) const {
unsigned Opc = Cond[0].getImm();
const MCInstrDesc &MCID = get(Opc);
MachineInstrBuilder MIB = BuildMI(&MBB, DL, MCID);
@@ -107,14 +108,16 @@ MipsInstrInfo::BuildCondBr(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
else if (Cond[i].isImm())
MIB.addImm(Cond[i].getImm());
else
- assert(true && "Cannot copy operand");
+ assert(false && "Cannot copy operand");
}
MIB.addMBB(TBB);
}
-unsigned MipsInstrInfo::InsertBranch(
- MachineBasicBlock &MBB, MachineBasicBlock *TBB, MachineBasicBlock *FBB,
- ArrayRef<MachineOperand> Cond, DebugLoc DL) const {
+unsigned MipsInstrInfo::InsertBranch(MachineBasicBlock &MBB,
+ MachineBasicBlock *TBB,
+ MachineBasicBlock *FBB,
+ ArrayRef<MachineOperand> Cond,
+ const DebugLoc &DL) const {
// Shouldn't be a fall through.
assert(TBB && "InsertBranch must not be told to insert a fallthrough");
@@ -174,7 +177,7 @@ bool MipsInstrInfo::ReverseBranchCondition(
return false;
}
-MipsInstrInfo::BranchType MipsInstrInfo::AnalyzeBranch(
+MipsInstrInfo::BranchType MipsInstrInfo::analyzeBranch(
MachineBasicBlock &MBB, MachineBasicBlock *&TBB, MachineBasicBlock *&FBB,
SmallVectorImpl<MachineOperand> &Cond, bool AllowModify,
SmallVectorImpl<MachineInstr *> &BranchInstrs) const {
@@ -185,7 +188,7 @@ MipsInstrInfo::BranchType MipsInstrInfo::AnalyzeBranch(
while (I != REnd && I->isDebugValue())
++I;
- if (I == REnd || !isUnpredicatedTerminator(&*I)) {
+ if (I == REnd || !isUnpredicatedTerminator(*I)) {
// This block ends with no branches (it just falls through to its succ).
// Leave TBB/FBB null.
TBB = FBB = nullptr;
@@ -209,14 +212,14 @@ MipsInstrInfo::BranchType MipsInstrInfo::AnalyzeBranch(
SecondLastOpc = getAnalyzableBrOpc(SecondLastInst->getOpcode());
// Not an analyzable branch (must be an indirect jump).
- if (isUnpredicatedTerminator(SecondLastInst) && !SecondLastOpc)
+ if (isUnpredicatedTerminator(*SecondLastInst) && !SecondLastOpc)
return BT_None;
}
// If there is only one terminator instruction, process it.
if (!SecondLastOpc) {
// Unconditional branch.
- if (LastOpc == UncondBrOpc) {
+ if (LastInst->isUnconditionalBranch()) {
TBB = LastInst->getOperand(0).getMBB();
return BT_Uncond;
}
@@ -228,14 +231,14 @@ MipsInstrInfo::BranchType MipsInstrInfo::AnalyzeBranch(
// If we reached here, there are two branches.
// If there are three terminators, we don't know what sort of block this is.
- if (++I != REnd && isUnpredicatedTerminator(&*I))
+ if (++I != REnd && isUnpredicatedTerminator(*I))
return BT_None;
BranchInstrs.insert(BranchInstrs.begin(), SecondLastInst);
// If second to last instruction is an unconditional branch,
// analyze it and remove the last instruction.
- if (SecondLastOpc == UncondBrOpc) {
+ if (SecondLastInst->isUnconditionalBranch()) {
// Return if the last instruction cannot be removed.
if (!AllowModify)
return BT_None;
@@ -248,7 +251,7 @@ MipsInstrInfo::BranchType MipsInstrInfo::AnalyzeBranch(
// Conditional branch followed by an unconditional branch.
// The last one must be unconditional.
- if (LastOpc != UncondBrOpc)
+ if (!LastInst->isUnconditionalBranch())
return BT_None;
AnalyzeCondBr(SecondLastInst, SecondLastOpc, TBB, Cond);
@@ -257,20 +260,137 @@ MipsInstrInfo::BranchType MipsInstrInfo::AnalyzeBranch(
return BT_CondUncond;
}
+/// Return the corresponding compact (no delay slot) form of a branch.
+unsigned MipsInstrInfo::getEquivalentCompactForm(
+ const MachineBasicBlock::iterator I) const {
+ unsigned Opcode = I->getOpcode();
+ bool canUseShortMicroMipsCTI = false;
+
+ if (Subtarget.inMicroMipsMode()) {
+ switch (Opcode) {
+ case Mips::BNE:
+ case Mips::BEQ:
+ // microMIPS has NE,EQ branches that do not have delay slots provided one
+ // of the operands is zero.
+ if (I->getOperand(1).getReg() == Subtarget.getABI().GetZeroReg())
+ canUseShortMicroMipsCTI = true;
+ break;
+ // For microMIPS the PseudoReturn and PseudoIndirectBranch are always
+ // expanded to JR_MM, so they can be replaced with JRC16_MM.
+ case Mips::JR:
+ case Mips::PseudoReturn:
+ case Mips::PseudoIndirectBranch:
+ canUseShortMicroMipsCTI = true;
+ break;
+ }
+ }
+
+ // MIPSR6 forbids both operands being the zero register.
+ if (Subtarget.hasMips32r6() && (I->getNumOperands() > 1) &&
+ (I->getOperand(0).isReg() &&
+ (I->getOperand(0).getReg() == Mips::ZERO ||
+ I->getOperand(0).getReg() == Mips::ZERO_64)) &&
+ (I->getOperand(1).isReg() &&
+ (I->getOperand(1).getReg() == Mips::ZERO ||
+ I->getOperand(1).getReg() == Mips::ZERO_64)))
+ return 0;
+
+ if (Subtarget.hasMips32r6() || canUseShortMicroMipsCTI) {
+ switch (Opcode) {
+ case Mips::B:
+ return Mips::BC;
+ case Mips::BAL:
+ return Mips::BALC;
+ case Mips::BEQ:
+ if (canUseShortMicroMipsCTI)
+ return Mips::BEQZC_MM;
+ else if (I->getOperand(0).getReg() == I->getOperand(1).getReg())
+ return 0;
+ return Mips::BEQC;
+ case Mips::BNE:
+ if (canUseShortMicroMipsCTI)
+ return Mips::BNEZC_MM;
+ else if (I->getOperand(0).getReg() == I->getOperand(1).getReg())
+ return 0;
+ return Mips::BNEC;
+ case Mips::BGE:
+ if (I->getOperand(0).getReg() == I->getOperand(1).getReg())
+ return 0;
+ return Mips::BGEC;
+ case Mips::BGEU:
+ if (I->getOperand(0).getReg() == I->getOperand(1).getReg())
+ return 0;
+ return Mips::BGEUC;
+ case Mips::BGEZ:
+ return Mips::BGEZC;
+ case Mips::BGTZ:
+ return Mips::BGTZC;
+ case Mips::BLEZ:
+ return Mips::BLEZC;
+ case Mips::BLT:
+ if (I->getOperand(0).getReg() == I->getOperand(1).getReg())
+ return 0;
+ return Mips::BLTC;
+ case Mips::BLTU:
+ if (I->getOperand(0).getReg() == I->getOperand(1).getReg())
+ return 0;
+ return Mips::BLTUC;
+ case Mips::BLTZ:
+ return Mips::BLTZC;
+ // For MIPSR6, the instruction 'jic' can be used for these cases. Some
+ // tools will accept 'jrc reg' as an alias for 'jic 0, $reg'.
+ case Mips::JR:
+ case Mips::PseudoReturn:
+ case Mips::PseudoIndirectBranch:
+ if (canUseShortMicroMipsCTI)
+ return Mips::JRC16_MM;
+ return Mips::JIC;
+ case Mips::JALRPseudo:
+ return Mips::JIALC;
+ case Mips::JR64:
+ case Mips::PseudoReturn64:
+ case Mips::PseudoIndirectBranch64:
+ return Mips::JIC64;
+ case Mips::JALR64Pseudo:
+ return Mips::JIALC64;
+ default:
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+/// Predicate for distingushing between control transfer instructions and all
+/// other instructions for handling forbidden slots. Consider inline assembly
+/// as unsafe as well.
+bool MipsInstrInfo::SafeInForbiddenSlot(const MachineInstr &MI) const {
+ if (MI.isInlineAsm())
+ return false;
+
+ return (MI.getDesc().TSFlags & MipsII::IsCTI) == 0;
+
+}
+
+/// Predicate for distingushing instructions that have forbidden slots.
+bool MipsInstrInfo::HasForbiddenSlot(const MachineInstr &MI) const {
+ return (MI.getDesc().TSFlags & MipsII::HasForbiddenSlot) != 0;
+}
+
/// Return the number of bytes of code the specified instruction may be.
-unsigned MipsInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const {
- switch (MI->getOpcode()) {
+unsigned MipsInstrInfo::GetInstSizeInBytes(const MachineInstr &MI) const {
+ switch (MI.getOpcode()) {
default:
- return MI->getDesc().getSize();
+ return MI.getDesc().getSize();
case TargetOpcode::INLINEASM: { // Inline Asm: Variable size.
- const MachineFunction *MF = MI->getParent()->getParent();
- const char *AsmStr = MI->getOperand(0).getSymbolName();
+ const MachineFunction *MF = MI.getParent()->getParent();
+ const char *AsmStr = MI.getOperand(0).getSymbolName();
return getInlineAsmLength(AsmStr, *MF->getTarget().getMCAsmInfo());
}
case Mips::CONSTPOOL_ENTRY:
// If this machine instr is a constant pool entry, its size is recorded as
// operand #2.
- return MI->getOperand(2).getImm();
+ return MI.getOperand(2).getImm();
}
}
@@ -278,10 +398,70 @@ MachineInstrBuilder
MipsInstrInfo::genInstrWithNewOpc(unsigned NewOpc,
MachineBasicBlock::iterator I) const {
MachineInstrBuilder MIB;
+
+ // Certain branches have two forms: e.g beq $1, $zero, dst vs beqz $1, dest
+ // Pick the zero form of the branch for readable assembly and for greater
+ // branch distance in non-microMIPS mode.
+ // FIXME: Certain atomic sequences on mips64 generate 32bit references to
+ // Mips::ZERO, which is incorrect. This test should be updated to use
+ // Subtarget.getABI().GetZeroReg() when those atomic sequences and others
+ // are fixed.
+ bool BranchWithZeroOperand =
+ (I->isBranch() && !I->isPseudo() && I->getOperand(1).isReg() &&
+ (I->getOperand(1).getReg() == Mips::ZERO ||
+ I->getOperand(1).getReg() == Mips::ZERO_64));
+
+ if (BranchWithZeroOperand) {
+ switch (NewOpc) {
+ case Mips::BEQC:
+ NewOpc = Mips::BEQZC;
+ break;
+ case Mips::BNEC:
+ NewOpc = Mips::BNEZC;
+ break;
+ case Mips::BGEC:
+ NewOpc = Mips::BGEZC;
+ break;
+ case Mips::BLTC:
+ NewOpc = Mips::BLTZC;
+ break;
+ }
+ }
+
MIB = BuildMI(*I->getParent(), I, I->getDebugLoc(), get(NewOpc));
- for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J)
- MIB.addOperand(I->getOperand(J));
+ // For MIPSR6 JI*C requires an immediate 0 as an operand, JIALC(64) an
+ // immediate 0 as an operand and requires the removal of it's %RA<imp-def>
+ // implicit operand as copying the implicit operations of the instructio we're
+ // looking at will give us the correct flags.
+ if (NewOpc == Mips::JIC || NewOpc == Mips::JIALC || NewOpc == Mips::JIC64 ||
+ NewOpc == Mips::JIALC64) {
+
+ if (NewOpc == Mips::JIALC || NewOpc == Mips::JIALC64)
+ MIB->RemoveOperand(0);
+
+ for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J) {
+ MIB.addOperand(I->getOperand(J));
+ }
+
+ MIB.addImm(0);
+
+ } else if (BranchWithZeroOperand) {
+ // For MIPSR6 and microMIPS branches with an explicit zero operand, copy
+ // everything after the zero.
+ MIB.addOperand(I->getOperand(0));
+
+ for (unsigned J = 2, E = I->getDesc().getNumOperands(); J < E; ++J) {
+ MIB.addOperand(I->getOperand(J));
+ }
+ } else {
+ // All other cases copy all other operands.
+ for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J) {
+ MIB.addOperand(I->getOperand(J));
+ }
+ }
+
+ MIB.copyImplicitOps(*I);
MIB.setMemRefs(I->memoperands_begin(), I->memoperands_end());
return MIB;
diff --git a/lib/Target/Mips/MipsInstrInfo.h b/lib/Target/Mips/MipsInstrInfo.h
index 08efc35090466..2e55012eec406 100644
--- a/lib/Target/Mips/MipsInstrInfo.h
+++ b/lib/Target/Mips/MipsInstrInfo.h
@@ -19,7 +19,6 @@
#define LLVM_LIB_TARGET_MIPS_MIPSINSTRINFO_H
#include "Mips.h"
-#include "MipsAnalyzeImmediate.h"
#include "MipsRegisterInfo.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/Support/ErrorHandling.h"
@@ -51,7 +50,7 @@ public:
static const MipsInstrInfo *create(MipsSubtarget &STI);
/// Branch Analysis
- bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
+ bool analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
MachineBasicBlock *&FBB,
SmallVectorImpl<MachineOperand> &Cond,
bool AllowModify) const override;
@@ -60,16 +59,25 @@ public:
unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
MachineBasicBlock *FBB, ArrayRef<MachineOperand> Cond,
- DebugLoc DL) const override;
+ const DebugLoc &DL) const override;
bool
ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override;
- BranchType AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
+ BranchType analyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
MachineBasicBlock *&FBB,
SmallVectorImpl<MachineOperand> &Cond,
bool AllowModify,
- SmallVectorImpl<MachineInstr*> &BranchInstrs) const;
+ SmallVectorImpl<MachineInstr *> &BranchInstrs) const;
+
+ /// Determine the opcode of a non-delay slot form for a branch if one exists.
+ unsigned getEquivalentCompactForm(const MachineBasicBlock::iterator I) const;
+
+ /// Predicate to determine if an instruction can go in a forbidden slot.
+ bool SafeInForbiddenSlot(const MachineInstr &MI) const;
+
+ /// Predicate to determine if an instruction has a forbidden slot.
+ bool HasForbiddenSlot(const MachineInstr &MI) const;
/// Insert nop instruction when hazard condition is found
void insertNoop(MachineBasicBlock &MBB,
@@ -84,7 +92,7 @@ public:
virtual unsigned getOppositeBranchOpc(unsigned Opc) const = 0;
/// Return the number of bytes of code the specified instruction may be.
- unsigned GetInstSizeInBytes(const MachineInstr *MI) const;
+ unsigned GetInstSizeInBytes(const MachineInstr &MI) const;
void storeRegToStackSlot(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MBBI,
@@ -129,7 +137,7 @@ protected:
bool isZeroImm(const MachineOperand &op) const;
MachineMemOperand *GetMemOperand(MachineBasicBlock &MBB, int FI,
- unsigned Flag) const;
+ MachineMemOperand::Flags Flags) const;
private:
virtual unsigned getAnalyzableBrOpc(unsigned Opc) const = 0;
@@ -138,8 +146,8 @@ private:
MachineBasicBlock *&BB,
SmallVectorImpl<MachineOperand> &Cond) const;
- void BuildCondBr(MachineBasicBlock &MBB, MachineBasicBlock *TBB, DebugLoc DL,
- ArrayRef<MachineOperand> Cond) const;
+ void BuildCondBr(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
+ const DebugLoc &DL, ArrayRef<MachineOperand> Cond) const;
};
/// Create MipsInstrInfo objects.
diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td
index ffda491f0c864..296f6e9b08bd0 100644
--- a/lib/Target/Mips/MipsInstrInfo.td
+++ b/lib/Target/Mips/MipsInstrInfo.td
@@ -179,6 +179,10 @@ def IsGP64bit : Predicate<"Subtarget->isGP64bit()">,
AssemblerPredicate<"FeatureGP64Bit">;
def IsGP32bit : Predicate<"!Subtarget->isGP64bit()">,
AssemblerPredicate<"!FeatureGP64Bit">;
+def IsPTR64bit : Predicate<"Subtarget->isABI_N64()">,
+ AssemblerPredicate<"FeaturePTR64Bit">;
+def IsPTR32bit : Predicate<"!Subtarget->isABI_N64()">,
+ AssemblerPredicate<"!FeaturePTR64Bit">;
def HasMips64 : Predicate<"Subtarget->hasMips64()">,
AssemblerPredicate<"FeatureMips64">;
def NotMips64 : Predicate<"!Subtarget->hasMips64()">,
@@ -197,8 +201,8 @@ def InMips16Mode : Predicate<"Subtarget->inMips16Mode()">,
AssemblerPredicate<"FeatureMips16">;
def HasCnMips : Predicate<"Subtarget->hasCnMips()">,
AssemblerPredicate<"FeatureCnMips">;
-def RelocStatic : Predicate<"TM.getRelocationModel() == Reloc::Static">;
-def RelocPIC : Predicate<"TM.getRelocationModel() == Reloc::PIC_">;
+def RelocNotPIC : Predicate<"!TM.isPositionIndependent()">;
+def RelocPIC : Predicate<"TM.isPositionIndependent()">;
def NoNaNsFPMath : Predicate<"TM.Options.NoNaNsFPMath">;
def HasStdEnc : Predicate<"Subtarget->hasStandardEncoding()">,
AssemblerPredicate<"!FeatureMips16">;
@@ -225,6 +229,9 @@ def HasMSA : Predicate<"Subtarget->hasMSA()">,
class GPR_32 { list<Predicate> GPRPredicates = [IsGP32bit]; }
class GPR_64 { list<Predicate> GPRPredicates = [IsGP64bit]; }
+class PTR_32 { list<Predicate> PTRPredicates = [IsPTR32bit]; }
+class PTR_64 { list<Predicate> PTRPredicates = [IsPTR64bit]; }
+
//===----------------------------------------------------------------------===//
// Mips ISA/ASE membership and instruction group membership adjectives.
// They are mutually exclusive.
@@ -315,6 +322,10 @@ class ASE_CNMIPS {
list<Predicate> InsnPredicates = [HasCnMips];
}
+class ASE_MIPS64_CNMIPS {
+ list<Predicate> InsnPredicates = [HasMips64, HasCnMips];
+}
+
class ASE_MSA {
list<Predicate> InsnPredicates = [HasMSA];
}
@@ -333,6 +344,10 @@ class ISA_MICROMIPS_NOT_32R6_64R6 : PredicateControl {
let InsnPredicates = [InMicroMips, NotMips32r6, NotMips64r6];
}
+class ASE_NOT_DSP {
+ list<Predicate> InsnPredicates = [NotDSP];
+}
+
//===----------------------------------------------------------------------===//
class MipsPat<dag pattern, dag result> : Pat<pattern, result>, PredicateControl {
@@ -348,14 +363,17 @@ class IsCommutable {
class IsBranch {
bit isBranch = 1;
+ bit isCTI = 1;
}
class IsReturn {
bit isReturn = 1;
+ bit isCTI = 1;
}
class IsCall {
bit isCall = 1;
+ bit isCTI = 1;
}
class IsTailCall {
@@ -365,6 +383,7 @@ class IsTailCall {
bit isBarrier = 1;
bit hasExtraSrcRegAllocReq = 1;
bit isCodeGenOnly = 1;
+ bit isCTI = 1;
}
class IsAsCheapAsAMove {
@@ -385,13 +404,13 @@ include "MipsInstrFormats.td"
// Mips Operand, Complex Patterns and Transformations Definitions.
//===----------------------------------------------------------------------===//
-class ConstantSImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = []>
- : AsmOperandClass {
- let Name = "ConstantSImm" # Bits;
- let RenderMethod = "addImmOperands";
- let PredicateMethod = "isConstantSImm<" # Bits # ">";
+class ConstantSImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = [],
+ int Offset = 0> : AsmOperandClass {
+ let Name = "ConstantSImm" # Bits # "_" # Offset;
+ let RenderMethod = "addConstantSImmOperands<" # Bits # ", " # Offset # ">";
+ let PredicateMethod = "isConstantSImm<" # Bits # ", " # Offset # ">";
let SuperClasses = Supers;
- let DiagnosticType = "SImm" # Bits;
+ let DiagnosticType = "SImm" # Bits # "_" # Offset;
}
class ConstantUImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = [],
@@ -403,49 +422,181 @@ class ConstantUImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = [],
let DiagnosticType = "UImm" # Bits # "_" # Offset;
}
+class ConstantUImmRangeAsmOperandClass<int Bottom, int Top,
+ list<AsmOperandClass> Supers = []>
+ : AsmOperandClass {
+ let Name = "ConstantUImmRange" # Bottom # "_" # Top;
+ let RenderMethod = "addImmOperands";
+ let PredicateMethod = "isConstantUImmRange<" # Bottom # ", " # Top # ">";
+ let SuperClasses = Supers;
+ let DiagnosticType = "UImmRange" # Bottom # "_" # Top;
+}
+
+class SImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = []>
+ : AsmOperandClass {
+ let Name = "SImm" # Bits;
+ let RenderMethod = "addSImmOperands<" # Bits # ">";
+ let PredicateMethod = "isSImm<" # Bits # ">";
+ let SuperClasses = Supers;
+ let DiagnosticType = "SImm" # Bits;
+}
+
+class UImmAsmOperandClass<int Bits, list<AsmOperandClass> Supers = []>
+ : AsmOperandClass {
+ let Name = "UImm" # Bits;
+ let RenderMethod = "addUImmOperands<" # Bits # ">";
+ let PredicateMethod = "isUImm<" # Bits # ">";
+ let SuperClasses = Supers;
+ let DiagnosticType = "UImm" # Bits;
+}
+
+// AsmOperandClasses require a strict ordering which is difficult to manage
+// as a hierarchy. Instead, we use a linear ordering and impose an order that
+// is in some places arbitrary.
+//
+// Here the rules that are in use:
+// * Wider immediates are a superset of narrower immediates:
+// uimm4 < uimm5 < uimm6
+// * For the same bit-width, unsigned immediates are a superset of signed
+// immediates::
+// simm4 < uimm4 < simm5 < uimm5
+// * For the same upper-bound, signed immediates are a superset of unsigned
+// immediates:
+// uimm3 < simm4 < uimm4 < simm4
+// * Modified immediates are a superset of ordinary immediates:
+// uimm5 < uimm5_plus1 (1..32) < uimm5_plus32 (32..63) < uimm6
+// The term 'superset' starts to break down here since the uimm5_plus* classes
+// are not true supersets of uimm5 (but they are still subsets of uimm6).
+// * 'Relaxed' immediates are supersets of the corresponding unsigned immediate.
+// uimm16 < uimm16_relaxed
+// * The codeGen pattern type is arbitrarily ordered.
+// uimm5 < uimm5_64, and uimm5 < vsplat_uimm5
+// This is entirely arbitrary. We need an ordering and what we pick is
+// unimportant since only one is possible for a given mnemonic.
+def SImm32RelaxedAsmOperandClass
+ : SImmAsmOperandClass<32, []> {
+ let Name = "SImm32_Relaxed";
+ let PredicateMethod = "isAnyImm<32>";
+ let DiagnosticType = "SImm32_Relaxed";
+}
+def SImm32AsmOperandClass
+ : SImmAsmOperandClass<32, [SImm32RelaxedAsmOperandClass]>;
+def ConstantUImm26AsmOperandClass
+ : ConstantUImmAsmOperandClass<26, [SImm32AsmOperandClass]>;
+def ConstantUImm20AsmOperandClass
+ : ConstantUImmAsmOperandClass<20, [ConstantUImm26AsmOperandClass]>;
+def UImm16RelaxedAsmOperandClass
+ : UImmAsmOperandClass<16, [ConstantUImm20AsmOperandClass]> {
+ let Name = "UImm16_Relaxed";
+ let PredicateMethod = "isAnyImm<16>";
+ let DiagnosticType = "UImm16_Relaxed";
+}
+def UImm16AsmOperandClass
+ : UImmAsmOperandClass<16, [UImm16RelaxedAsmOperandClass]>;
+def SImm16RelaxedAsmOperandClass
+ : SImmAsmOperandClass<16, [UImm16RelaxedAsmOperandClass]> {
+ let Name = "SImm16_Relaxed";
+ let PredicateMethod = "isAnyImm<16>";
+ let DiagnosticType = "SImm16_Relaxed";
+}
+def SImm16AsmOperandClass
+ : SImmAsmOperandClass<16, [SImm16RelaxedAsmOperandClass]>;
+def ConstantSImm10Lsl3AsmOperandClass : AsmOperandClass {
+ let Name = "SImm10Lsl3";
+ let RenderMethod = "addImmOperands";
+ let PredicateMethod = "isScaledSImm<10, 3>";
+ let SuperClasses = [SImm16AsmOperandClass];
+ let DiagnosticType = "SImm10_Lsl3";
+}
+def ConstantSImm10Lsl2AsmOperandClass : AsmOperandClass {
+ let Name = "SImm10Lsl2";
+ let RenderMethod = "addImmOperands";
+ let PredicateMethod = "isScaledSImm<10, 2>";
+ let SuperClasses = [ConstantSImm10Lsl3AsmOperandClass];
+ let DiagnosticType = "SImm10_Lsl2";
+}
+def ConstantSImm11AsmOperandClass
+ : ConstantSImmAsmOperandClass<11, [ConstantSImm10Lsl2AsmOperandClass]>;
+def ConstantSImm10Lsl1AsmOperandClass : AsmOperandClass {
+ let Name = "SImm10Lsl1";
+ let RenderMethod = "addImmOperands";
+ let PredicateMethod = "isScaledSImm<10, 1>";
+ let SuperClasses = [ConstantSImm11AsmOperandClass];
+ let DiagnosticType = "SImm10_Lsl1";
+}
def ConstantUImm10AsmOperandClass
- : ConstantUImmAsmOperandClass<10, []>;
+ : ConstantUImmAsmOperandClass<10, [ConstantSImm10Lsl1AsmOperandClass]>;
+def ConstantSImm10AsmOperandClass
+ : ConstantSImmAsmOperandClass<10, [ConstantUImm10AsmOperandClass]>;
+def ConstantSImm9AsmOperandClass
+ : ConstantSImmAsmOperandClass<9, [ConstantSImm10AsmOperandClass]>;
+def ConstantSImm7Lsl2AsmOperandClass : AsmOperandClass {
+ let Name = "SImm7Lsl2";
+ let RenderMethod = "addImmOperands";
+ let PredicateMethod = "isScaledSImm<7, 2>";
+ let SuperClasses = [ConstantSImm9AsmOperandClass];
+ let DiagnosticType = "SImm7_Lsl2";
+}
def ConstantUImm8AsmOperandClass
- : ConstantUImmAsmOperandClass<8, [ConstantUImm10AsmOperandClass]>;
+ : ConstantUImmAsmOperandClass<8, [ConstantSImm7Lsl2AsmOperandClass]>;
+def ConstantUImm7Sub1AsmOperandClass
+ : ConstantUImmAsmOperandClass<7, [ConstantUImm8AsmOperandClass], -1> {
+ // Specify the names since the -1 offset causes invalid identifiers otherwise.
+ let Name = "UImm7_N1";
+ let DiagnosticType = "UImm7_N1";
+}
def ConstantUImm7AsmOperandClass
- : ConstantUImmAsmOperandClass<7, [ConstantUImm8AsmOperandClass]>;
+ : ConstantUImmAsmOperandClass<7, [ConstantUImm7Sub1AsmOperandClass]>;
+def ConstantUImm6Lsl2AsmOperandClass : AsmOperandClass {
+ let Name = "UImm6Lsl2";
+ let RenderMethod = "addImmOperands";
+ let PredicateMethod = "isScaledUImm<6, 2>";
+ let SuperClasses = [ConstantUImm7AsmOperandClass];
+ let DiagnosticType = "UImm6_Lsl2";
+}
def ConstantUImm6AsmOperandClass
- : ConstantUImmAsmOperandClass<6, [ConstantUImm7AsmOperandClass]>;
+ : ConstantUImmAsmOperandClass<6, [ConstantUImm6Lsl2AsmOperandClass]>;
def ConstantSImm6AsmOperandClass
- : ConstantSImmAsmOperandClass<6, [ConstantUImm7AsmOperandClass]>;
-def ConstantUImm5Plus1AsmOperandClass
- : ConstantUImmAsmOperandClass<5, [ConstantUImm6AsmOperandClass], 1>;
-def ConstantUImm5Plus32AsmOperandClass
- : ConstantUImmAsmOperandClass<5, [ConstantUImm6AsmOperandClass], 32>;
-def ConstantUImm5Plus33AsmOperandClass
- : ConstantUImmAsmOperandClass<5, [ConstantUImm6AsmOperandClass], 33>;
-def ConstantUImm5Plus32NormalizeAsmOperandClass
- : ConstantUImmAsmOperandClass<5, [ConstantUImm6AsmOperandClass], 32> {
- let Name = "ConstantUImm5_32_Norm";
- // We must also subtract 32 when we render the operand.
- let RenderMethod = "addConstantUImmOperands<5, 32, -32>";
-}
+ : ConstantSImmAsmOperandClass<6, [ConstantUImm6AsmOperandClass]>;
def ConstantUImm5Lsl2AsmOperandClass : AsmOperandClass {
let Name = "UImm5Lsl2";
let RenderMethod = "addImmOperands";
let PredicateMethod = "isScaledUImm<5, 2>";
- let SuperClasses = [ConstantUImm6AsmOperandClass];
+ let SuperClasses = [ConstantSImm6AsmOperandClass];
let DiagnosticType = "UImm5_Lsl2";
}
+def ConstantUImm5_Range2_64AsmOperandClass
+ : ConstantUImmRangeAsmOperandClass<2, 64, [ConstantUImm5Lsl2AsmOperandClass]>;
+def ConstantUImm5Plus33AsmOperandClass
+ : ConstantUImmAsmOperandClass<5, [ConstantUImm5_Range2_64AsmOperandClass],
+ 33>;
def ConstantUImm5ReportUImm6AsmOperandClass
- : ConstantUImmAsmOperandClass<5, [ConstantUImm6AsmOperandClass]> {
+ : ConstantUImmAsmOperandClass<5, [ConstantUImm5Plus33AsmOperandClass]> {
let Name = "ConstantUImm5_0_Report_UImm6";
let DiagnosticType = "UImm5_0_Report_UImm6";
}
+def ConstantUImm5Plus32AsmOperandClass
+ : ConstantUImmAsmOperandClass<
+ 5, [ConstantUImm5ReportUImm6AsmOperandClass], 32>;
+def ConstantUImm5Plus32NormalizeAsmOperandClass
+ : ConstantUImmAsmOperandClass<5, [ConstantUImm5Plus32AsmOperandClass], 32> {
+ let Name = "ConstantUImm5_32_Norm";
+ // We must also subtract 32 when we render the operand.
+ let RenderMethod = "addConstantUImmOperands<5, 32, -32>";
+}
+def ConstantUImm5Plus1AsmOperandClass
+ : ConstantUImmAsmOperandClass<
+ 5, [ConstantUImm5Plus32NormalizeAsmOperandClass], 1>;
def ConstantUImm5AsmOperandClass
- : ConstantUImmAsmOperandClass<5, [ConstantUImm6AsmOperandClass]>;
+ : ConstantUImmAsmOperandClass<5, [ConstantUImm5Plus1AsmOperandClass]>;
+def ConstantSImm5AsmOperandClass
+ : ConstantSImmAsmOperandClass<5, [ConstantUImm5AsmOperandClass]>;
def ConstantUImm4AsmOperandClass
- : ConstantUImmAsmOperandClass<
- 4, [ConstantUImm5AsmOperandClass,
- ConstantUImm5Plus32AsmOperandClass,
- ConstantUImm5Plus32NormalizeAsmOperandClass]>;
+ : ConstantUImmAsmOperandClass<4, [ConstantSImm5AsmOperandClass]>;
+def ConstantSImm4AsmOperandClass
+ : ConstantSImmAsmOperandClass<4, [ConstantUImm4AsmOperandClass]>;
def ConstantUImm3AsmOperandClass
- : ConstantUImmAsmOperandClass<3, [ConstantUImm4AsmOperandClass]>;
+ : ConstantUImmAsmOperandClass<3, [ConstantSImm4AsmOperandClass]>;
def ConstantUImm2Plus1AsmOperandClass
: ConstantUImmAsmOperandClass<2, [ConstantUImm3AsmOperandClass], 1>;
def ConstantUImm2AsmOperandClass
@@ -478,6 +629,12 @@ def brtarget : Operand<OtherVT> {
let DecoderMethod = "DecodeBranchTarget";
let ParserMatchClass = MipsJumpTargetAsmOperand;
}
+def brtarget1SImm16 : Operand<OtherVT> {
+ let EncoderMethod = "getBranchTargetOpValue1SImm16";
+ let OperandType = "OPERAND_PCREL";
+ let DecoderMethod = "DecodeBranchTarget1SImm16";
+ let ParserMatchClass = MipsJumpTargetAsmOperand;
+}
def calltarget : Operand<iPTR> {
let EncoderMethod = "getJumpTargetOpValue";
let ParserMatchClass = MipsJumpTargetAsmOperand;
@@ -485,18 +642,6 @@ def calltarget : Operand<iPTR> {
def imm64: Operand<i64>;
-def simm6 : Operand<i32> {
- let ParserMatchClass = ConstantSImm6AsmOperandClass;
- let OperandType = "OPERAND_IMMEDIATE";
-}
-def simm9 : Operand<i32>;
-def simm10 : Operand<i32>;
-def simm11 : Operand<i32>;
-
-def simm16 : Operand<i32> {
- let DecoderMethod= "DecodeSimm16";
-}
-
def simm19_lsl2 : Operand<i32> {
let EncoderMethod = "getSimm19Lsl2Encoding";
let DecoderMethod = "DecodeSimm19Lsl2";
@@ -509,91 +654,207 @@ def simm18_lsl3 : Operand<i32> {
let ParserMatchClass = MipsJumpTargetAsmOperand;
}
-def simm20 : Operand<i32>;
-def simm32 : Operand<i32>;
-
-def uimm20 : Operand<i32> {
-}
-
-def simm16_64 : Operand<i64> {
- let DecoderMethod = "DecodeSimm16";
-}
-
// Zero
def uimmz : Operand<i32> {
- let PrintMethod = "printUnsignedImm";
+ let PrintMethod = "printUImm<0>";
let ParserMatchClass = ConstantImmzAsmOperandClass;
}
+// size operand of ins instruction
+def uimm_range_2_64 : Operand<i32> {
+ let PrintMethod = "printUImm<6, 2>";
+ let EncoderMethod = "getSizeInsEncoding";
+ let DecoderMethod = "DecodeInsSize";
+ let ParserMatchClass = ConstantUImm5_Range2_64AsmOperandClass;
+}
+
// Unsigned Operands
-foreach I = {1, 2, 3, 4, 5, 6, 7, 8, 10} in
+foreach I = {1, 2, 3, 4, 5, 6, 7, 8, 10, 20, 26} in
def uimm # I : Operand<i32> {
- let PrintMethod = "printUnsignedImm";
+ let PrintMethod = "printUImm<" # I # ">";
let ParserMatchClass =
!cast<AsmOperandClass>("ConstantUImm" # I # "AsmOperandClass");
}
def uimm2_plus1 : Operand<i32> {
- let PrintMethod = "printUnsignedImm";
+ let PrintMethod = "printUImm<2, 1>";
let EncoderMethod = "getUImmWithOffsetEncoding<2, 1>";
let DecoderMethod = "DecodeUImmWithOffset<2, 1>";
let ParserMatchClass = ConstantUImm2Plus1AsmOperandClass;
}
def uimm5_plus1 : Operand<i32> {
- let PrintMethod = "printUnsignedImm";
+ let PrintMethod = "printUImm<5, 1>";
let EncoderMethod = "getUImmWithOffsetEncoding<5, 1>";
let DecoderMethod = "DecodeUImmWithOffset<5, 1>";
let ParserMatchClass = ConstantUImm5Plus1AsmOperandClass;
}
def uimm5_plus32 : Operand<i32> {
- let PrintMethod = "printUnsignedImm";
+ let PrintMethod = "printUImm<5, 32>";
let ParserMatchClass = ConstantUImm5Plus32AsmOperandClass;
}
def uimm5_plus33 : Operand<i32> {
- let PrintMethod = "printUnsignedImm";
+ let PrintMethod = "printUImm<5, 33>";
let EncoderMethod = "getUImmWithOffsetEncoding<5, 1>";
let DecoderMethod = "DecodeUImmWithOffset<5, 1>";
let ParserMatchClass = ConstantUImm5Plus33AsmOperandClass;
}
+def uimm5_inssize_plus1 : Operand<i32> {
+ let PrintMethod = "printUImm<6>";
+ let ParserMatchClass = ConstantUImm5Plus1AsmOperandClass;
+ let EncoderMethod = "getSizeInsEncoding";
+ let DecoderMethod = "DecodeInsSize";
+}
+
def uimm5_plus32_normalize : Operand<i32> {
- let PrintMethod = "printUnsignedImm";
+ let PrintMethod = "printUImm<5>";
let ParserMatchClass = ConstantUImm5Plus32NormalizeAsmOperandClass;
}
def uimm5_lsl2 : Operand<OtherVT> {
let EncoderMethod = "getUImm5Lsl2Encoding";
- let DecoderMethod = "DecodeUImm5lsl2";
+ let DecoderMethod = "DecodeUImmWithOffsetAndScale<5, 0, 4>";
let ParserMatchClass = ConstantUImm5Lsl2AsmOperandClass;
}
def uimm5_plus32_normalize_64 : Operand<i64> {
- let PrintMethod = "printUnsignedImm";
+ let PrintMethod = "printUImm<5>";
let ParserMatchClass = ConstantUImm5Plus32NormalizeAsmOperandClass;
}
+def uimm6_lsl2 : Operand<OtherVT> {
+ let EncoderMethod = "getUImm6Lsl2Encoding";
+ let DecoderMethod = "DecodeUImmWithOffsetAndScale<6, 0, 4>";
+ let ParserMatchClass = ConstantUImm6Lsl2AsmOperandClass;
+}
+
+foreach I = {16} in
+ def uimm # I : Operand<i32> {
+ let PrintMethod = "printUImm<" # I # ">";
+ let ParserMatchClass =
+ !cast<AsmOperandClass>("UImm" # I # "AsmOperandClass");
+ }
+
+// Like uimm16_64 but coerces simm16 to uimm16.
+def uimm16_relaxed : Operand<i32> {
+ let PrintMethod = "printUImm<16>";
+ let ParserMatchClass =
+ !cast<AsmOperandClass>("UImm16RelaxedAsmOperandClass");
+}
+
foreach I = {5} in
def uimm # I # _64 : Operand<i64> {
- let PrintMethod = "printUnsignedImm";
+ let PrintMethod = "printUImm<" # I # ">";
let ParserMatchClass =
!cast<AsmOperandClass>("ConstantUImm" # I # "AsmOperandClass");
}
+foreach I = {16} in
+ def uimm # I # _64 : Operand<i64> {
+ let PrintMethod = "printUImm<" # I # ">";
+ let ParserMatchClass =
+ !cast<AsmOperandClass>("UImm" # I # "AsmOperandClass");
+ }
+
+// Like uimm16_64 but coerces simm16 to uimm16.
+def uimm16_64_relaxed : Operand<i64> {
+ let PrintMethod = "printUImm<16>";
+ let ParserMatchClass =
+ !cast<AsmOperandClass>("UImm16RelaxedAsmOperandClass");
+}
+
+// Like uimm5 but reports a less confusing error for 32-63 when
+// an instruction alias permits that.
+def uimm5_report_uimm6 : Operand<i32> {
+ let PrintMethod = "printUImm<5>";
+ let ParserMatchClass = ConstantUImm5ReportUImm6AsmOperandClass;
+}
+
// Like uimm5_64 but reports a less confusing error for 32-63 when
// an instruction alias permits that.
def uimm5_64_report_uimm6 : Operand<i64> {
- let PrintMethod = "printUnsignedImm";
+ let PrintMethod = "printUImm<5>";
let ParserMatchClass = ConstantUImm5ReportUImm6AsmOperandClass;
}
-def uimm16 : Operand<i32> {
- let PrintMethod = "printUnsignedImm";
+foreach I = {1, 2, 3, 4} in
+ def uimm # I # _ptr : Operand<iPTR> {
+ let PrintMethod = "printUImm<" # I # ">";
+ let ParserMatchClass =
+ !cast<AsmOperandClass>("ConstantUImm" # I # "AsmOperandClass");
+ }
+
+foreach I = {1, 2, 3, 4, 5, 6, 8} in
+ def vsplat_uimm # I : Operand<vAny> {
+ let PrintMethod = "printUImm<" # I # ">";
+ let ParserMatchClass =
+ !cast<AsmOperandClass>("ConstantUImm" # I # "AsmOperandClass");
+ }
+
+// Signed operands
+foreach I = {4, 5, 6, 9, 10, 11} in
+ def simm # I : Operand<i32> {
+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<" # I # ">";
+ let ParserMatchClass =
+ !cast<AsmOperandClass>("ConstantSImm" # I # "AsmOperandClass");
+ }
+
+foreach I = {1, 2, 3} in
+ def simm10_lsl # I : Operand<i32> {
+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<10, " # I # ">";
+ let ParserMatchClass =
+ !cast<AsmOperandClass>("ConstantSImm10Lsl" # I # "AsmOperandClass");
+ }
+
+foreach I = {10} in
+ def simm # I # _64 : Operand<i64> {
+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<" # I # ">";
+ let ParserMatchClass =
+ !cast<AsmOperandClass>("ConstantSImm" # I # "AsmOperandClass");
+ }
+
+foreach I = {5, 10} in
+ def vsplat_simm # I : Operand<vAny> {
+ let ParserMatchClass =
+ !cast<AsmOperandClass>("ConstantSImm" # I # "AsmOperandClass");
+ }
+
+def simm7_lsl2 : Operand<OtherVT> {
+ let EncoderMethod = "getSImm7Lsl2Encoding";
+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<" # I # ", 0, 4>";
+ let ParserMatchClass = ConstantSImm7Lsl2AsmOperandClass;
+}
+
+foreach I = {16, 32} in
+ def simm # I : Operand<i32> {
+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<" # I # ">";
+ let ParserMatchClass = !cast<AsmOperandClass>("SImm" # I # "AsmOperandClass");
+ }
+
+// Like simm16 but coerces uimm16 to simm16.
+def simm16_relaxed : Operand<i32> {
+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<16>";
+ let ParserMatchClass = !cast<AsmOperandClass>("SImm16RelaxedAsmOperandClass");
+}
+
+def simm16_64 : Operand<i64> {
+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<16>";
+ let ParserMatchClass = !cast<AsmOperandClass>("SImm16AsmOperandClass");
+}
+
+// Like simm32 but coerces uimm32 to simm32.
+def simm32_relaxed : Operand<i32> {
+ let DecoderMethod = "DecodeSImmWithOffsetAndScale<32>";
+ let ParserMatchClass = !cast<AsmOperandClass>("SImm32RelaxedAsmOperandClass");
}
-def pcrel16 : Operand<i32> {
+// This is almost the same as a uimm7 but 0x7f is interpreted as -1.
+def li16_imm : Operand<i32> {
+ let DecoderMethod = "DecodeLi16Imm";
+ let ParserMatchClass = ConstantUImm7Sub1AsmOperandClass;
}
def MipsMemAsmOperand : AsmOperandClass {
@@ -607,22 +868,44 @@ def MipsMemSimm9AsmOperand : AsmOperandClass {
let RenderMethod = "addMemOperands";
let ParserMethod = "parseMemOperand";
let PredicateMethod = "isMemWithSimmOffset<9>";
+ let DiagnosticType = "MemSImm9";
}
-def MipsMemSimm9GPRAsmOperand : AsmOperandClass {
- let Name = "MemOffsetSimm9GPR";
+def MipsMemSimm10AsmOperand : AsmOperandClass {
+ let Name = "MemOffsetSimm10";
let SuperClasses = [MipsMemAsmOperand];
let RenderMethod = "addMemOperands";
let ParserMethod = "parseMemOperand";
- let PredicateMethod = "isMemWithSimmOffsetGPR<9>";
+ let PredicateMethod = "isMemWithSimmOffset<10>";
+ let DiagnosticType = "MemSImm10";
}
+def MipsMemSimm12AsmOperand : AsmOperandClass {
+ let Name = "MemOffsetSimm12";
+ let SuperClasses = [MipsMemAsmOperand];
+ let RenderMethod = "addMemOperands";
+ let ParserMethod = "parseMemOperand";
+ let PredicateMethod = "isMemWithSimmOffset<12>";
+ let DiagnosticType = "MemSImm12";
+}
+
+foreach I = {1, 2, 3} in
+ def MipsMemSimm10Lsl # I # AsmOperand : AsmOperandClass {
+ let Name = "MemOffsetSimm10_" # I;
+ let SuperClasses = [MipsMemAsmOperand];
+ let RenderMethod = "addMemOperands";
+ let ParserMethod = "parseMemOperand";
+ let PredicateMethod = "isMemWithSimmOffset<10, " # I # ">";
+ let DiagnosticType = "MemSImm10Lsl" # I;
+ }
+
def MipsMemSimm11AsmOperand : AsmOperandClass {
let Name = "MemOffsetSimm11";
let SuperClasses = [MipsMemAsmOperand];
let RenderMethod = "addMemOperands";
let ParserMethod = "parseMemOperand";
let PredicateMethod = "isMemWithSimmOffset<11>";
+ let DiagnosticType = "MemSImm11";
}
def MipsMemSimm16AsmOperand : AsmOperandClass {
@@ -631,6 +914,7 @@ def MipsMemSimm16AsmOperand : AsmOperandClass {
let RenderMethod = "addMemOperands";
let ParserMethod = "parseMemOperand";
let PredicateMethod = "isMemWithSimmOffset<16>";
+ let DiagnosticType = "MemSImm16";
}
def MipsInvertedImmoperand : AsmOperandClass {
@@ -664,24 +948,42 @@ def mem_msa : mem_generic {
let EncoderMethod = "getMSAMemEncoding";
}
+def simm12 : Operand<i32> {
+ let DecoderMethod = "DecodeSimm12";
+}
+
def mem_simm9 : mem_generic {
let MIOperandInfo = (ops ptr_rc, simm9);
let EncoderMethod = "getMemEncoding";
let ParserMatchClass = MipsMemSimm9AsmOperand;
}
-def mem_simm9gpr : mem_generic {
- let MIOperandInfo = (ops ptr_rc, simm9);
+def mem_simm10 : mem_generic {
+ let MIOperandInfo = (ops ptr_rc, simm10);
let EncoderMethod = "getMemEncoding";
- let ParserMatchClass = MipsMemSimm9GPRAsmOperand;
+ let ParserMatchClass = MipsMemSimm10AsmOperand;
}
+foreach I = {1, 2, 3} in
+ def mem_simm10_lsl # I : mem_generic {
+ let MIOperandInfo = (ops ptr_rc, !cast<Operand>("simm10_lsl" # I));
+ let EncoderMethod = "getMemEncoding<" # I # ">";
+ let ParserMatchClass =
+ !cast<AsmOperandClass>("MipsMemSimm10Lsl" # I # "AsmOperand");
+ }
+
def mem_simm11 : mem_generic {
let MIOperandInfo = (ops ptr_rc, simm11);
let EncoderMethod = "getMemEncoding";
let ParserMatchClass = MipsMemSimm11AsmOperand;
}
+def mem_simm12 : mem_generic {
+ let MIOperandInfo = (ops ptr_rc, simm12);
+ let EncoderMethod = "getMemEncoding";
+ let ParserMatchClass = MipsMemSimm12AsmOperand;
+}
+
def mem_simm16 : mem_generic {
let MIOperandInfo = (ops ptr_rc, simm16);
let EncoderMethod = "getMemEncoding";
@@ -735,6 +1037,9 @@ def immSExt16 : PatLeaf<(imm), [{ return isInt<16>(N->getSExtValue()); }]>;
// e.g. addi, andi
def immSExt15 : PatLeaf<(imm), [{ return isInt<15>(N->getSExtValue()); }]>;
+// Node immediate fits as 7-bit zero extended on target immediate.
+def immZExt7 : PatLeaf<(imm), [{ return isUInt<7>(N->getZExtValue()); }]>;
+
// Node immediate fits as 16-bit zero extended on target immediate.
// The LO16 param means that only the lower 16 bits of the node
// immediate are caught.
@@ -755,6 +1060,16 @@ def immLow16Zero : PatLeaf<(imm), [{
// shamt field must fit in 5 bits.
def immZExt5 : ImmLeaf<i32, [{return Imm == (Imm & 0x1f);}]>;
+def immZExt5Plus1 : PatLeaf<(imm), [{
+ return isUInt<5>(N->getZExtValue() - 1);
+}]>;
+def immZExt5Plus32 : PatLeaf<(imm), [{
+ return isUInt<5>(N->getZExtValue() - 32);
+}]>;
+def immZExt5Plus33 : PatLeaf<(imm), [{
+ return isUInt<5>(N->getZExtValue() - 33);
+}]>;
+
// True if (N + 1) fits in 16-bit field.
def immSExt16Plus1 : PatLeaf<(imm), [{
return isInt<17>(N->getSExtValue()) && isInt<16>(N->getSExtValue() + 1);
@@ -768,9 +1083,6 @@ def addr :
def addrRegImm :
ComplexPattern<iPTR, 2, "selectAddrRegImm", [frameindex]>;
-def addrRegReg :
- ComplexPattern<iPTR, 2, "selectAddrRegReg", [frameindex]>;
-
def addrDefault :
ComplexPattern<iPTR, 2, "selectAddrDefault", [frameindex]>;
@@ -849,15 +1161,21 @@ class LoadUpper<string opstr, RegisterOperand RO, Operand Imm>:
}
// Memory Load/Store
-class Load<string opstr, DAGOperand RO, SDPatternOperator OpNode = null_frag,
- InstrItinClass Itin = NoItinerary, ComplexPattern Addr = addr> :
- InstSE<(outs RO:$rt), (ins mem:$addr), !strconcat(opstr, "\t$rt, $addr"),
+class LoadMemory<string opstr, DAGOperand RO, DAGOperand MO,
+ SDPatternOperator OpNode = null_frag,
+ InstrItinClass Itin = NoItinerary,
+ ComplexPattern Addr = addr> :
+ InstSE<(outs RO:$rt), (ins MO:$addr), !strconcat(opstr, "\t$rt, $addr"),
[(set RO:$rt, (OpNode Addr:$addr))], Itin, FrmI, opstr> {
let DecoderMethod = "DecodeMem";
let canFoldAsLoad = 1;
let mayLoad = 1;
}
+class Load<string opstr, DAGOperand RO, SDPatternOperator OpNode = null_frag,
+ InstrItinClass Itin = NoItinerary, ComplexPattern Addr = addr> :
+ LoadMemory<opstr, RO, mem, OpNode, Itin, Addr>;
+
class StoreMemory<string opstr, DAGOperand RO, DAGOperand MO,
SDPatternOperator OpNode = null_frag,
InstrItinClass Itin = NoItinerary, ComplexPattern Addr = addr> :
@@ -868,8 +1186,9 @@ class StoreMemory<string opstr, DAGOperand RO, DAGOperand MO,
}
class Store<string opstr, DAGOperand RO, SDPatternOperator OpNode = null_frag,
- InstrItinClass Itin = NoItinerary, ComplexPattern Addr = addr> :
- StoreMemory<opstr, RO, mem, OpNode, Itin, Addr>;
+ InstrItinClass Itin = NoItinerary, ComplexPattern Addr = addr,
+ DAGOperand MO = mem> :
+ StoreMemory<opstr, RO, MO, OpNode, Itin, Addr>;
// Load/Store Left/Right
let canFoldAsLoad = 1 in
@@ -892,7 +1211,8 @@ class StoreLeftRight<string opstr, SDNode OpNode, RegisterOperand RO,
// COP2 Load/Store
class LW_FT2<string opstr, RegisterOperand RC, InstrItinClass Itin,
SDPatternOperator OpNode= null_frag> :
- InstSE<(outs RC:$rt), (ins mem:$addr), !strconcat(opstr, "\t$rt, $addr"),
+ InstSE<(outs RC:$rt), (ins mem_simm16:$addr),
+ !strconcat(opstr, "\t$rt, $addr"),
[(set RC:$rt, (OpNode addrDefault:$addr))], Itin, FrmFI, opstr> {
let DecoderMethod = "DecodeFMem2";
let mayLoad = 1;
@@ -900,7 +1220,8 @@ class LW_FT2<string opstr, RegisterOperand RC, InstrItinClass Itin,
class SW_FT2<string opstr, RegisterOperand RC, InstrItinClass Itin,
SDPatternOperator OpNode= null_frag> :
- InstSE<(outs), (ins RC:$rt, mem:$addr), !strconcat(opstr, "\t$rt, $addr"),
+ InstSE<(outs), (ins RC:$rt, mem_simm16:$addr),
+ !strconcat(opstr, "\t$rt, $addr"),
[(OpNode RC:$rt, addrDefault:$addr)], Itin, FrmFI, opstr> {
let DecoderMethod = "DecodeFMem2";
let mayStore = 1;
@@ -934,6 +1255,7 @@ class CBranch<string opstr, DAGOperand opnd, PatFrag cond_op,
let isTerminator = 1;
let hasDelaySlot = DelaySlot;
let Defs = [AT];
+ bit isCTI = 1;
}
class CBranchZero<string opstr, DAGOperand opnd, PatFrag cond_op,
@@ -946,6 +1268,7 @@ class CBranchZero<string opstr, DAGOperand opnd, PatFrag cond_op,
let isTerminator = 1;
let hasDelaySlot = DelaySlot;
let Defs = [AT];
+ bit isCTI = 1;
}
// SetCC
@@ -972,6 +1295,7 @@ class JumpFJ<DAGOperand opnd, string opstr, SDPatternOperator operator,
let hasDelaySlot = 1;
let DecoderMethod = "DecodeJumpTarget";
let Defs = [AT];
+ bit isCTI = 1;
}
// Unconditional branch
@@ -984,10 +1308,11 @@ class UncondBranch<Instruction BEQInst> :
let hasDelaySlot = 1;
let AdditionalPredicates = [RelocPIC];
let Defs = [AT];
+ bit isCTI = 1;
}
// Base class for indirect branch and return instruction classes.
-let isTerminator=1, isBarrier=1, hasDelaySlot = 1 in
+let isTerminator=1, isBarrier=1, hasDelaySlot = 1, isCTI = 1 in
class JumpFR<string opstr, RegisterOperand RO,
SDPatternOperator operator = null_frag>:
InstSE<(outs), (ins RO:$rs), "jr\t$rs", [(operator RO:$rs)], II_JR,
@@ -1000,7 +1325,7 @@ class IndirectBranch<string opstr, RegisterOperand RO> : JumpFR<opstr, RO> {
}
// Jump and Link (Call)
-let isCall=1, hasDelaySlot=1, Defs = [RA] in {
+let isCall=1, hasDelaySlot=1, isCTI=1, Defs = [RA] in {
class JumpLink<string opstr, DAGOperand opnd> :
InstSE<(outs), (ins opnd:$target), !strconcat(opstr, "\t$target"),
[(MipsJmpLink tglobaladdr:$target)], II_JAL, FrmJ, opstr> {
@@ -1026,7 +1351,7 @@ let isCall=1, hasDelaySlot=1, Defs = [RA] in {
}
let isCall = 1, isTerminator = 1, isReturn = 1, isBarrier = 1, hasDelaySlot = 1,
- hasExtraSrcRegAllocReq = 1, Defs = [AT] in {
+ hasExtraSrcRegAllocReq = 1, isCTI = 1, Defs = [AT] in {
class TailCall<Instruction JumpInst> :
PseudoSE<(outs), (ins calltarget:$target), [], II_J>,
PseudoInstExpansion<(JumpInst jmptarget:$target)>;
@@ -1045,54 +1370,61 @@ class BAL_BR_Pseudo<Instruction RealInst> :
let isBarrier = 1;
let hasDelaySlot = 1;
let Defs = [RA];
+ bit isCTI = 1;
}
+let isCTI = 1 in {
// Syscall
-class SYS_FT<string opstr> :
- InstSE<(outs), (ins uimm20:$code_),
- !strconcat(opstr, "\t$code_"), [], NoItinerary, FrmI, opstr>;
+class SYS_FT<string opstr, Operand ImmOp, InstrItinClass itin = NoItinerary> :
+ InstSE<(outs), (ins ImmOp:$code_),
+ !strconcat(opstr, "\t$code_"), [], itin, FrmI, opstr>;
// Break
class BRK_FT<string opstr> :
InstSE<(outs), (ins uimm10:$code_1, uimm10:$code_2),
- !strconcat(opstr, "\t$code_1, $code_2"), [], NoItinerary,
+ !strconcat(opstr, "\t$code_1, $code_2"), [], II_BREAK,
FrmOther, opstr>;
// (D)Eret
-class ER_FT<string opstr> :
+class ER_FT<string opstr, InstrItinClass itin = NoItinerary> :
InstSE<(outs), (ins),
- opstr, [], NoItinerary, FrmOther, opstr>;
-
-// Interrupts
-class DEI_FT<string opstr, RegisterOperand RO> :
- InstSE<(outs RO:$rt), (ins),
- !strconcat(opstr, "\t$rt"), [], NoItinerary, FrmOther, opstr>;
+ opstr, [], itin, FrmOther, opstr>;
// Wait
class WAIT_FT<string opstr> :
- InstSE<(outs), (ins), opstr, [], NoItinerary, FrmOther, opstr>;
+ InstSE<(outs), (ins), opstr, [], II_WAIT, FrmOther, opstr>;
+}
+
+// Interrupts
+class DEI_FT<string opstr, RegisterOperand RO,
+ InstrItinClass itin = NoItinerary> :
+ InstSE<(outs RO:$rt), (ins),
+ !strconcat(opstr, "\t$rt"), [], itin, FrmOther, opstr>;
// Sync
let hasSideEffects = 1 in
class SYNC_FT<string opstr> :
- InstSE<(outs), (ins i32imm:$stype), "sync $stype", [(MipsSync imm:$stype)],
- NoItinerary, FrmOther, opstr>;
+ InstSE<(outs), (ins uimm5:$stype), "sync $stype",
+ [(MipsSync immZExt5:$stype)], II_SYNC, FrmOther, opstr>;
class SYNCI_FT<string opstr> :
InstSE<(outs), (ins mem_simm16:$addr), !strconcat(opstr, "\t$addr"), [],
- NoItinerary, FrmOther, opstr> {
+ II_SYNCI, FrmOther, opstr> {
let hasSideEffects = 1;
let DecoderMethod = "DecodeSyncI";
}
-let hasSideEffects = 1 in
-class TEQ_FT<string opstr, RegisterOperand RO> :
- InstSE<(outs), (ins RO:$rs, RO:$rt, uimm16:$code_),
- !strconcat(opstr, "\t$rs, $rt, $code_"), [], NoItinerary,
- FrmI, opstr>;
-
-class TEQI_FT<string opstr, RegisterOperand RO> :
- InstSE<(outs), (ins RO:$rs, uimm16:$imm16),
- !strconcat(opstr, "\t$rs, $imm16"), [], NoItinerary, FrmOther, opstr>;
+let hasSideEffects = 1, isCTI = 1 in {
+class TEQ_FT<string opstr, RegisterOperand RO, Operand ImmOp,
+ InstrItinClass itin = NoItinerary> :
+ InstSE<(outs), (ins RO:$rs, RO:$rt, ImmOp:$code_),
+ !strconcat(opstr, "\t$rs, $rt, $code_"), [], itin, FrmI, opstr>;
+
+class TEQI_FT<string opstr, RegisterOperand RO,
+ InstrItinClass itin = NoItinerary> :
+ InstSE<(outs), (ins RO:$rs, simm16:$imm16),
+ !strconcat(opstr, "\t$rs, $imm16"), [], itin, FrmOther, opstr>;
+}
+
// Mul, Div
class Mult<string opstr, InstrItinClass itin, RegisterOperand RO,
list<Register> DefRegs> :
@@ -1163,20 +1495,23 @@ class MoveToLOHI<string opstr, RegisterOperand RO, list<Register> DefRegs>:
class EffectiveAddress<string opstr, RegisterOperand RO> :
InstSE<(outs RO:$rt), (ins mem_ea:$addr), !strconcat(opstr, "\t$rt, $addr"),
- [(set RO:$rt, addr:$addr)], NoItinerary, FrmI,
+ [(set RO:$rt, addr:$addr)], II_ADDIU, FrmI,
!strconcat(opstr, "_lea")> {
let isCodeGenOnly = 1;
+ let hasNoSchedulingInfo = 1;
let DecoderMethod = "DecodeMem";
}
// Count Leading Ones/Zeros in Word
-class CountLeading0<string opstr, RegisterOperand RO>:
+class CountLeading0<string opstr, RegisterOperand RO,
+ InstrItinClass itin = NoItinerary>:
InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"),
- [(set RO:$rd, (ctlz RO:$rs))], II_CLZ, FrmR, opstr>;
+ [(set RO:$rd, (ctlz RO:$rs))], itin, FrmR, opstr>;
-class CountLeading1<string opstr, RegisterOperand RO>:
+class CountLeading1<string opstr, RegisterOperand RO,
+ InstrItinClass itin = NoItinerary>:
InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"),
- [(set RO:$rd, (ctlz (not RO:$rs)))], II_CLO, FrmR, opstr>;
+ [(set RO:$rd, (ctlz (not RO:$rs)))], itin, FrmR, opstr>;
// Sign Extend in Register.
class SignExtInReg<string opstr, ValueType vt, RegisterOperand RO,
@@ -1199,15 +1534,16 @@ class ReadHardware<RegisterOperand CPURegOperand, RegisterOperand RO> :
// Ext and Ins
class ExtBase<string opstr, RegisterOperand RO, Operand PosOpnd,
- Operand SizeOpnd, SDPatternOperator Op = null_frag> :
+ Operand SizeOpnd, PatFrag PosImm, PatFrag SizeImm,
+ SDPatternOperator Op = null_frag> :
InstSE<(outs RO:$rt), (ins RO:$rs, PosOpnd:$pos, SizeOpnd:$size),
!strconcat(opstr, " $rt, $rs, $pos, $size"),
- [(set RO:$rt, (Op RO:$rs, imm:$pos, imm:$size))], II_EXT,
+ [(set RO:$rt, (Op RO:$rs, PosImm:$pos, SizeImm:$size))], II_EXT,
FrmR, opstr>, ISA_MIPS32R2;
class InsBase<string opstr, RegisterOperand RO, Operand PosOpnd,
- SDPatternOperator Op = null_frag>:
- InstSE<(outs RO:$rt), (ins RO:$rs, PosOpnd:$pos, size_ins:$size, RO:$src),
+ Operand SizeOpnd, SDPatternOperator Op = null_frag>:
+ InstSE<(outs RO:$rt), (ins RO:$rs, PosOpnd:$pos, SizeOpnd:$size, RO:$src),
!strconcat(opstr, " $rt, $rs, $pos, $size"),
[(set RO:$rt, (Op RO:$rs, imm:$pos, imm:$size, RO:$src))],
II_INS, FrmR, opstr>, ISA_MIPS32R2 {
@@ -1224,35 +1560,38 @@ class AtomicCmpSwap<PatFrag Op, RegisterClass DRC> :
PseudoSE<(outs DRC:$dst), (ins PtrRC:$ptr, DRC:$cmp, DRC:$swap),
[(set DRC:$dst, (Op iPTR:$ptr, DRC:$cmp, DRC:$swap))]>;
-class LLBase<string opstr, RegisterOperand RO> :
- InstSE<(outs RO:$rt), (ins mem:$addr), !strconcat(opstr, "\t$rt, $addr"),
- [], NoItinerary, FrmI> {
+class LLBase<string opstr, RegisterOperand RO, DAGOperand MO = mem> :
+ InstSE<(outs RO:$rt), (ins MO:$addr), !strconcat(opstr, "\t$rt, $addr"),
+ [], II_LL, FrmI, opstr> {
let DecoderMethod = "DecodeMem";
let mayLoad = 1;
}
class SCBase<string opstr, RegisterOperand RO> :
InstSE<(outs RO:$dst), (ins RO:$rt, mem:$addr),
- !strconcat(opstr, "\t$rt, $addr"), [], NoItinerary, FrmI> {
+ !strconcat(opstr, "\t$rt, $addr"), [], II_SC, FrmI> {
let DecoderMethod = "DecodeMem";
let mayStore = 1;
let Constraints = "$rt = $dst";
}
-class MFC3OP<string asmstr, RegisterOperand RO, RegisterOperand RD> :
- InstSE<(outs RO:$rt), (ins RD:$rd, uimm16:$sel),
- !strconcat(asmstr, "\t$rt, $rd, $sel"), [], NoItinerary, FrmFR>;
+class MFC3OP<string asmstr, RegisterOperand RO, RegisterOperand RD,
+ InstrItinClass itin> :
+ InstSE<(outs RO:$rt), (ins RD:$rd, uimm3:$sel),
+ !strconcat(asmstr, "\t$rt, $rd, $sel"), [], itin, FrmFR>;
-class MTC3OP<string asmstr, RegisterOperand RO, RegisterOperand RD> :
- InstSE<(outs RO:$rd), (ins RD:$rt, uimm16:$sel),
- !strconcat(asmstr, "\t$rt, $rd, $sel"), [], NoItinerary, FrmFR>;
+class MTC3OP<string asmstr, RegisterOperand RO, RegisterOperand RD,
+ InstrItinClass itin> :
+ InstSE<(outs RO:$rd), (ins RD:$rt, uimm3:$sel),
+ !strconcat(asmstr, "\t$rt, $rd, $sel"), [], itin, FrmFR>;
class TrapBase<Instruction RealInst>
- : PseudoSE<(outs), (ins), [(trap)], NoItinerary>,
+ : PseudoSE<(outs), (ins), [(trap)], II_TRAP>,
PseudoInstExpansion<(RealInst 0, 0)> {
let isBarrier = 1;
let isTerminator = 1;
let isCodeGenOnly = 1;
+ let isCTI = 1;
}
//===----------------------------------------------------------------------===//
@@ -1260,11 +1599,13 @@ class TrapBase<Instruction RealInst>
//===----------------------------------------------------------------------===//
// Return RA.
-let isReturn=1, isTerminator=1, hasDelaySlot=1, isBarrier=1, hasCtrlDep=1 in
-def RetRA : PseudoSE<(outs), (ins), [(MipsRet)]>;
+let isReturn=1, isTerminator=1, isBarrier=1, hasCtrlDep=1, isCTI=1 in {
+ let hasDelaySlot=1 in
+ def RetRA : PseudoSE<(outs), (ins), [(MipsRet)]>;
-let isReturn=1, isTerminator=1, isBarrier=1, hasCtrlDep=1, hasSideEffects=1 in
-def ERet : PseudoSE<(outs), (ins), [(MipsERet)]>;
+ let hasSideEffects=1 in
+ def ERet : PseudoSE<(outs), (ins), [(MipsERet)]>;
+}
let Defs = [SP], Uses = [SP], hasSideEffects = 1 in {
def ADJCALLSTACKDOWN : MipsPseudo<(outs), (ins i32imm:$amt),
@@ -1303,7 +1644,7 @@ let usesCustomInserter = 1 in {
}
/// Pseudo instructions for loading and storing accumulator registers.
-let isPseudo = 1, isCodeGenOnly = 1 in {
+let isPseudo = 1, isCodeGenOnly = 1, hasNoSchedulingInfo = 1 in {
def LOAD_ACC64 : Load<"", ACC64>;
def STORE_ACC64 : Store<"", ACC64>;
}
@@ -1329,40 +1670,39 @@ def LONG_BRANCH_ADDiu : PseudoSE<(outs GPR32Opnd:$dst),
/// Arithmetic Instructions (ALU Immediate)
let AdditionalPredicates = [NotInMicroMips] in {
-def ADDiu : MMRel, StdMMR6Rel, ArithLogicI<"addiu", simm16, GPR32Opnd,
- II_ADDIU, immSExt16, add>,
- ADDI_FM<0x9>, IsAsCheapAsAMove;
-}
-def ADDi : MMRel, ArithLogicI<"addi", simm16, GPR32Opnd>, ADDI_FM<0x8>,
+ def ADDiu : MMRel, StdMMR6Rel, ArithLogicI<"addiu", simm16_relaxed, GPR32Opnd,
+ II_ADDIU, immSExt16, add>,
+ ADDI_FM<0x9>, IsAsCheapAsAMove;
+
+ def ANDi : MMRel, StdMMR6Rel,
+ ArithLogicI<"andi", uimm16, GPR32Opnd, II_ANDI, immZExt16, and>,
+ ADDI_FM<0xc>;
+ def ORi : MMRel, StdMMR6Rel,
+ ArithLogicI<"ori", uimm16, GPR32Opnd, II_ORI, immZExt16, or>,
+ ADDI_FM<0xd>;
+ def XORi : MMRel, StdMMR6Rel,
+ ArithLogicI<"xori", uimm16, GPR32Opnd, II_XORI, immZExt16, xor>,
+ ADDI_FM<0xe>;
+}
+def ADDi : MMRel, ArithLogicI<"addi", simm16_relaxed, GPR32Opnd, II_ADDI>, ADDI_FM<0x8>,
ISA_MIPS1_NOT_32R6_64R6;
def SLTi : MMRel, SetCC_I<"slti", setlt, simm16, immSExt16, GPR32Opnd>,
SLTI_FM<0xa>;
def SLTiu : MMRel, SetCC_I<"sltiu", setult, simm16, immSExt16, GPR32Opnd>,
SLTI_FM<0xb>;
-let AdditionalPredicates = [NotInMicroMips] in {
-def ANDi : MMRel, StdMMR6Rel,
- ArithLogicI<"andi", uimm16, GPR32Opnd, II_ANDI, immZExt16, and>,
- ADDI_FM<0xc>;
-}
-def ORi : MMRel, StdMMR6Rel,
- ArithLogicI<"ori", uimm16, GPR32Opnd, II_ORI, immZExt16, or>,
- ADDI_FM<0xd>;
-def XORi : MMRel, StdMMR6Rel,
- ArithLogicI<"xori", uimm16, GPR32Opnd, II_XORI, immZExt16, xor>,
- ADDI_FM<0xe>;
-def LUi : MMRel, LoadUpper<"lui", GPR32Opnd, uimm16>, LUI_FM;
+def LUi : MMRel, LoadUpper<"lui", GPR32Opnd, uimm16_relaxed>, LUI_FM;
let AdditionalPredicates = [NotInMicroMips] in {
/// Arithmetic Instructions (3-Operand, R-Type)
def ADDu : MMRel, StdMMR6Rel, ArithLogicR<"addu", GPR32Opnd, 1, II_ADDU, add>,
ADD_FM<0, 0x21>;
-def SUBu : MMRel, ArithLogicR<"subu", GPR32Opnd, 0, II_SUBU, sub>,
+def SUBu : MMRel, StdMMR6Rel, ArithLogicR<"subu", GPR32Opnd, 0, II_SUBU, sub>,
ADD_FM<0, 0x23>;
}
let Defs = [HI0, LO0] in
def MUL : MMRel, ArithLogicR<"mul", GPR32Opnd, 1, II_MUL, mul>,
ADD_FM<0x1c, 2>, ISA_MIPS32_NOT_32R6_64R6;
-def ADD : MMRel, StdMMR6Rel, ArithLogicR<"add", GPR32Opnd>, ADD_FM<0, 0x20>;
-def SUB : MMRel, ArithLogicR<"sub", GPR32Opnd>, ADD_FM<0, 0x22>;
+def ADD : MMRel, StdMMR6Rel, ArithLogicR<"add", GPR32Opnd, 1, II_ADD>, ADD_FM<0, 0x20>;
+def SUB : MMRel, StdMMR6Rel, ArithLogicR<"sub", GPR32Opnd, 0, II_SUB>, ADD_FM<0, 0x22>;
def SLT : MMRel, SetCC_R<"slt", setlt, GPR32Opnd>, ADD_FM<0, 0x2a>;
def SLTu : MMRel, SetCC_R<"sltu", setult, GPR32Opnd>, ADD_FM<0, 0x2b>;
let AdditionalPredicates = [NotInMicroMips] in {
@@ -1372,8 +1712,8 @@ def OR : MMRel, StdMMR6Rel, ArithLogicR<"or", GPR32Opnd, 1, II_OR, or>,
ADD_FM<0, 0x25>;
def XOR : MMRel, StdMMR6Rel, ArithLogicR<"xor", GPR32Opnd, 1, II_XOR, xor>,
ADD_FM<0, 0x26>;
-}
def NOR : MMRel, StdMMR6Rel, LogicNOR<"nor", GPR32Opnd>, ADD_FM<0, 0x27>;
+}
/// Shift Instructions
let AdditionalPredicates = [NotInMicroMips] in {
@@ -1381,7 +1721,6 @@ def SLL : MMRel, shift_rotate_imm<"sll", uimm5, GPR32Opnd, II_SLL, shl,
immZExt5>, SRA_FM<0, 0>;
def SRL : MMRel, shift_rotate_imm<"srl", uimm5, GPR32Opnd, II_SRL, srl,
immZExt5>, SRA_FM<2, 0>;
-}
def SRA : MMRel, shift_rotate_imm<"sra", uimm5, GPR32Opnd, II_SRA, sra,
immZExt5>, SRA_FM<3, 0>;
def SLLV : MMRel, shift_rotate_reg<"sllv", GPR32Opnd, II_SLLV, shl>,
@@ -1390,25 +1729,30 @@ def SRLV : MMRel, shift_rotate_reg<"srlv", GPR32Opnd, II_SRLV, srl>,
SRLV_FM<6, 0>;
def SRAV : MMRel, shift_rotate_reg<"srav", GPR32Opnd, II_SRAV, sra>,
SRLV_FM<7, 0>;
+}
// Rotate Instructions
-def ROTR : MMRel, shift_rotate_imm<"rotr", uimm5, GPR32Opnd, II_ROTR, rotr,
- immZExt5>,
- SRA_FM<2, 1>, ISA_MIPS32R2;
-def ROTRV : MMRel, shift_rotate_reg<"rotrv", GPR32Opnd, II_ROTRV, rotr>,
- SRLV_FM<6, 1>, ISA_MIPS32R2;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def ROTR : MMRel, shift_rotate_imm<"rotr", uimm5, GPR32Opnd, II_ROTR, rotr,
+ immZExt5>,
+ SRA_FM<2, 1>, ISA_MIPS32R2;
+ def ROTRV : MMRel, shift_rotate_reg<"rotrv", GPR32Opnd, II_ROTRV, rotr>,
+ SRLV_FM<6, 1>, ISA_MIPS32R2;
+}
/// Load and Store Instructions
/// aligned
-def LB : Load<"lb", GPR32Opnd, sextloadi8, II_LB>, MMRel, LW_FM<0x20>;
-def LBu : Load<"lbu", GPR32Opnd, zextloadi8, II_LBU, addrDefault>, MMRel,
- LW_FM<0x24>;
-def LH : Load<"lh", GPR32Opnd, sextloadi16, II_LH, addrDefault>, MMRel,
- LW_FM<0x21>;
-def LHu : Load<"lhu", GPR32Opnd, zextloadi16, II_LHU>, MMRel, LW_FM<0x25>;
+def LB : LoadMemory<"lb", GPR32Opnd, mem_simm16, sextloadi8, II_LB>, MMRel,
+ LW_FM<0x20>;
+def LBu : LoadMemory<"lbu", GPR32Opnd, mem_simm16, zextloadi8, II_LBU,
+ addrDefault>, MMRel, LW_FM<0x24>;
let AdditionalPredicates = [NotInMicroMips] in {
-def LW : StdMMR6Rel, Load<"lw", GPR32Opnd, load, II_LW, addrDefault>, MMRel,
- LW_FM<0x23>;
+ def LH : LoadMemory<"lh", GPR32Opnd, mem_simm16, sextloadi16, II_LH,
+ addrDefault>, MMRel, LW_FM<0x21>;
+ def LHu : LoadMemory<"lhu", GPR32Opnd, mem_simm16, zextloadi16, II_LHU>,
+ MMRel, LW_FM<0x25>;
+ def LW : StdMMR6Rel, Load<"lw", GPR32Opnd, load, II_LW, addrDefault>, MMRel,
+ LW_FM<0x23>;
}
def SB : StdMMR6Rel, Store<"sb", GPR32Opnd, truncstorei8, II_SB>, MMRel,
LW_FM<0x28>;
@@ -1432,82 +1776,87 @@ def SWR : StoreLeftRight<"swr", MipsSWR, GPR32Opnd, II_SWR>, LW_FM<0x2e>,
let AdditionalPredicates = [NotInMicroMips] in {
// COP2 Memory Instructions
-def LWC2 : LW_FT2<"lwc2", COP2Opnd, NoItinerary, load>, LW_FM<0x32>,
+def LWC2 : StdMMR6Rel, LW_FT2<"lwc2", COP2Opnd, II_LWC2, load>, LW_FM<0x32>,
ISA_MIPS1_NOT_32R6_64R6;
-def SWC2 : SW_FT2<"swc2", COP2Opnd, NoItinerary, store>, LW_FM<0x3a>,
- ISA_MIPS1_NOT_32R6_64R6;
-def LDC2 : LW_FT2<"ldc2", COP2Opnd, NoItinerary, load>, LW_FM<0x36>,
- ISA_MIPS2_NOT_32R6_64R6;
-def SDC2 : SW_FT2<"sdc2", COP2Opnd, NoItinerary, store>, LW_FM<0x3e>,
+def SWC2 : StdMMR6Rel, SW_FT2<"swc2", COP2Opnd, II_SWC2, store>,
+ LW_FM<0x3a>, ISA_MIPS1_NOT_32R6_64R6;
+def LDC2 : StdMMR6Rel, LW_FT2<"ldc2", COP2Opnd, II_LDC2, load>, LW_FM<0x36>,
ISA_MIPS2_NOT_32R6_64R6;
+def SDC2 : StdMMR6Rel, SW_FT2<"sdc2", COP2Opnd, II_SDC2, store>,
+ LW_FM<0x3e>, ISA_MIPS2_NOT_32R6_64R6;
// COP3 Memory Instructions
let DecoderNamespace = "COP3_" in {
- def LWC3 : LW_FT3<"lwc3", COP3Opnd, NoItinerary, load>, LW_FM<0x33>;
- def SWC3 : SW_FT3<"swc3", COP3Opnd, NoItinerary, store>, LW_FM<0x3b>;
- def LDC3 : LW_FT3<"ldc3", COP3Opnd, NoItinerary, load>, LW_FM<0x37>,
+ def LWC3 : LW_FT3<"lwc3", COP3Opnd, II_LWC3, load>, LW_FM<0x33>;
+ def SWC3 : SW_FT3<"swc3", COP3Opnd, II_SWC3, store>, LW_FM<0x3b>;
+ def LDC3 : LW_FT3<"ldc3", COP3Opnd, II_LDC3, load>, LW_FM<0x37>,
ISA_MIPS2;
- def SDC3 : SW_FT3<"sdc3", COP3Opnd, NoItinerary, store>, LW_FM<0x3f>,
+ def SDC3 : SW_FT3<"sdc3", COP3Opnd, II_SDC3, store>, LW_FM<0x3f>,
ISA_MIPS2;
}
}
-def SYNC : MMRel, StdMMR6Rel, SYNC_FT<"sync">, SYNC_FM, ISA_MIPS32;
+def SYNC : MMRel, StdMMR6Rel, SYNC_FT<"sync">, SYNC_FM,
+ ISA_MIPS32;
def SYNCI : MMRel, StdMMR6Rel, SYNCI_FT<"synci">, SYNCI_FM, ISA_MIPS32R2;
let AdditionalPredicates = [NotInMicroMips] in {
- def TEQ : MMRel, TEQ_FT<"teq", GPR32Opnd>, TEQ_FM<0x34>, ISA_MIPS2;
- def TGE : MMRel, TEQ_FT<"tge", GPR32Opnd>, TEQ_FM<0x30>, ISA_MIPS2;
- def TGEU : MMRel, TEQ_FT<"tgeu", GPR32Opnd>, TEQ_FM<0x31>, ISA_MIPS2;
- def TLT : MMRel, TEQ_FT<"tlt", GPR32Opnd>, TEQ_FM<0x32>, ISA_MIPS2;
- def TLTU : MMRel, TEQ_FT<"tltu", GPR32Opnd>, TEQ_FM<0x33>, ISA_MIPS2;
- def TNE : MMRel, TEQ_FT<"tne", GPR32Opnd>, TEQ_FM<0x36>, ISA_MIPS2;
+ def TEQ : MMRel, TEQ_FT<"teq", GPR32Opnd, uimm10, II_TEQ>, TEQ_FM<0x34>, ISA_MIPS2;
+ def TGE : MMRel, TEQ_FT<"tge", GPR32Opnd, uimm10, II_TGE>, TEQ_FM<0x30>, ISA_MIPS2;
+ def TGEU : MMRel, TEQ_FT<"tgeu", GPR32Opnd, uimm10, II_TGEU>, TEQ_FM<0x31>, ISA_MIPS2;
+ def TLT : MMRel, TEQ_FT<"tlt", GPR32Opnd, uimm10, II_TLT>, TEQ_FM<0x32>, ISA_MIPS2;
+ def TLTU : MMRel, TEQ_FT<"tltu", GPR32Opnd, uimm10, II_TLTU>, TEQ_FM<0x33>, ISA_MIPS2;
+ def TNE : MMRel, TEQ_FT<"tne", GPR32Opnd, uimm10, II_TNE>, TEQ_FM<0x36>, ISA_MIPS2;
}
-def TEQI : MMRel, TEQI_FT<"teqi", GPR32Opnd>, TEQI_FM<0xc>,
+def TEQI : MMRel, TEQI_FT<"teqi", GPR32Opnd, II_TEQI>, TEQI_FM<0xc>,
ISA_MIPS2_NOT_32R6_64R6;
-def TGEI : MMRel, TEQI_FT<"tgei", GPR32Opnd>, TEQI_FM<0x8>,
+def TGEI : MMRel, TEQI_FT<"tgei", GPR32Opnd, II_TGEI>, TEQI_FM<0x8>,
ISA_MIPS2_NOT_32R6_64R6;
-def TGEIU : MMRel, TEQI_FT<"tgeiu", GPR32Opnd>, TEQI_FM<0x9>,
+def TGEIU : MMRel, TEQI_FT<"tgeiu", GPR32Opnd, II_TGEIU>, TEQI_FM<0x9>,
ISA_MIPS2_NOT_32R6_64R6;
-def TLTI : MMRel, TEQI_FT<"tlti", GPR32Opnd>, TEQI_FM<0xa>,
+def TLTI : MMRel, TEQI_FT<"tlti", GPR32Opnd, II_TLTI>, TEQI_FM<0xa>,
ISA_MIPS2_NOT_32R6_64R6;
-def TTLTIU : MMRel, TEQI_FT<"tltiu", GPR32Opnd>, TEQI_FM<0xb>,
+def TTLTIU : MMRel, TEQI_FT<"tltiu", GPR32Opnd, II_TTLTIU>, TEQI_FM<0xb>,
ISA_MIPS2_NOT_32R6_64R6;
-def TNEI : MMRel, TEQI_FT<"tnei", GPR32Opnd>, TEQI_FM<0xe>,
+def TNEI : MMRel, TEQI_FT<"tnei", GPR32Opnd, II_TNEI>, TEQI_FM<0xe>,
ISA_MIPS2_NOT_32R6_64R6;
let AdditionalPredicates = [NotInMicroMips] in {
def BREAK : MMRel, StdMMR6Rel, BRK_FT<"break">, BRK_FM<0xd>;
+def SYSCALL : MMRel, SYS_FT<"syscall", uimm20, II_SYSCALL>, SYS_FM<0xc>;
}
-def SYSCALL : MMRel, SYS_FT<"syscall">, SYS_FM<0xc>;
def TRAP : TrapBase<BREAK>;
-def SDBBP : MMRel, SYS_FT<"sdbbp">, SDBBP_FM, ISA_MIPS32_NOT_32R6_64R6;
+let AdditionalPredicates = [NotInMicroMips] in {
+def SDBBP : MMRel, SYS_FT<"sdbbp", uimm20, II_SDBBP>, SDBBP_FM, ISA_MIPS32_NOT_32R6_64R6;
+}
let AdditionalPredicates = [NotInMicroMips] in {
- def ERET : MMRel, ER_FT<"eret">, ER_FM<0x18, 0x0>, INSN_MIPS3_32;
- def ERETNC : MMRel, ER_FT<"eretnc">, ER_FM<0x18, 0x1>, ISA_MIPS32R5;
- def DERET : MMRel, ER_FT<"deret">, ER_FM<0x1f, 0x0>, ISA_MIPS32;
+ def ERET : MMRel, ER_FT<"eret", II_ERET>, ER_FM<0x18, 0x0>, INSN_MIPS3_32;
+ def ERETNC : MMRel, ER_FT<"eretnc", II_ERETNC>, ER_FM<0x18, 0x1>, ISA_MIPS32R5;
+ def DERET : MMRel, ER_FT<"deret", II_DERET>, ER_FM<0x1f, 0x0>, ISA_MIPS32;
}
let AdditionalPredicates = [NotInMicroMips] in {
- def EI : MMRel, StdMMR6Rel, DEI_FT<"ei", GPR32Opnd>, EI_FM<1>, ISA_MIPS32R2;
- def DI : MMRel, StdMMR6Rel, DEI_FT<"di", GPR32Opnd>, EI_FM<0>, ISA_MIPS32R2;
+ def EI : MMRel, StdMMR6Rel, DEI_FT<"ei", GPR32Opnd, II_EI>, EI_FM<1>, ISA_MIPS32R2;
+ def DI : MMRel, StdMMR6Rel, DEI_FT<"di", GPR32Opnd, II_DI>, EI_FM<0>, ISA_MIPS32R2;
}
let EncodingPredicates = []<Predicate>, // FIXME: Lack of HasStdEnc is probably a bug
AdditionalPredicates = [NotInMicroMips] in {
def WAIT : WAIT_FT<"wait">, WAIT_FM;
+}
+let AdditionalPredicates = [NotInMicroMips] in {
/// Load-linked, Store-conditional
-def LL : LLBase<"ll", GPR32Opnd>, LW_FM<0x30>, ISA_MIPS2_NOT_32R6_64R6;
-def SC : SCBase<"sc", GPR32Opnd>, LW_FM<0x38>, ISA_MIPS2_NOT_32R6_64R6;
+def LL : LLBase<"ll", GPR32Opnd>, LW_FM<0x30>, PTR_32, ISA_MIPS2_NOT_32R6_64R6;
+def SC : SCBase<"sc", GPR32Opnd>, LW_FM<0x38>, PTR_32, ISA_MIPS2_NOT_32R6_64R6;
}
/// Jump and Branch Instructions
def J : MMRel, JumpFJ<jmptarget, "j", br, bb, "j">, FJ<2>,
- AdditionalRequires<[RelocStatic]>, IsBranch;
-def JR : MMRel, IndirectBranch<"jr", GPR32Opnd>, MTLO_FM<8>;
+ AdditionalRequires<[RelocNotPIC]>, IsBranch;
+def JR : MMRel, IndirectBranch<"jr", GPR32Opnd>, MTLO_FM<8>, ISA_MIPS1_NOT_32R6_64R6;
def BEQ : MMRel, CBranch<"beq", brtarget, seteq, GPR32Opnd>, BEQ_FM<4>;
def BEQL : MMRel, CBranch<"beql", brtarget, seteq, GPR32Opnd, 0>,
BEQ_FM<20>, ISA_MIPS2_NOT_32R6_64R6;
@@ -1562,6 +1911,7 @@ class PseudoIndirectBranchBase<RegisterOperand RO> :
let hasDelaySlot = 1;
let isBranch = 1;
let isIndirectBranch = 1;
+ bit isCTI = 1;
}
def PseudoIndirectBranch : PseudoIndirectBranchBase<GPR32Opnd>;
@@ -1579,6 +1929,7 @@ class PseudoReturnBase<RegisterOperand RO> : MipsPseudo<(outs), (ins RO:$rs),
let isCodeGenOnly = 1;
let hasCtrlDep = 1;
let hasExtraSrcRegAllocReq = 1;
+ bit isCTI = 1;
}
def PseudoReturn : PseudoReturnBase<GPR32Opnd>;
@@ -1596,7 +1947,7 @@ def SDT_MipsEHRET : SDTypeProfile<0, 2, [SDTCisInt<0>, SDTCisPtrTy<1>]>;
def MIPSehret : SDNode<"MipsISD::EH_RETURN", SDT_MipsEHRET,
[SDNPHasChain, SDNPOptInGlue, SDNPVariadic]>;
-let Uses = [V0, V1], isTerminator = 1, isReturn = 1, isBarrier = 1 in {
+let Uses = [V0, V1], isTerminator = 1, isReturn = 1, isBarrier = 1, isCTI = 1 in {
def MIPSeh_return32 : MipsPseudo<(outs), (ins GPR32:$spoff, GPR32:$dst),
[(MIPSehret GPR32:$spoff, GPR32:$dst)]>;
def MIPSeh_return64 : MipsPseudo<(outs), (ins GPR64:$spoff,
@@ -1609,11 +1960,12 @@ def MULT : MMRel, Mult<"mult", II_MULT, GPR32Opnd, [HI0, LO0]>,
MULT_FM<0, 0x18>, ISA_MIPS1_NOT_32R6_64R6;
def MULTu : MMRel, Mult<"multu", II_MULTU, GPR32Opnd, [HI0, LO0]>,
MULT_FM<0, 0x19>, ISA_MIPS1_NOT_32R6_64R6;
-def SDIV : MMRel, Div<"div", II_DIV, GPR32Opnd, [HI0, LO0]>,
- MULT_FM<0, 0x1a>, ISA_MIPS1_NOT_32R6_64R6;
-def UDIV : MMRel, Div<"divu", II_DIVU, GPR32Opnd, [HI0, LO0]>,
- MULT_FM<0, 0x1b>, ISA_MIPS1_NOT_32R6_64R6;
-
+let AdditionalPredicates = [NotInMicroMips] in {
+ def SDIV : MMRel, Div<"div", II_DIV, GPR32Opnd, [HI0, LO0]>,
+ MULT_FM<0, 0x1a>, ISA_MIPS1_NOT_32R6_64R6;
+ def UDIV : MMRel, Div<"divu", II_DIVU, GPR32Opnd, [HI0, LO0]>,
+ MULT_FM<0, 0x1b>, ISA_MIPS1_NOT_32R6_64R6;
+}
def MTHI : MMRel, MoveToLOHI<"mthi", GPR32Opnd, [HI0]>, MTLO_FM<0x11>,
ISA_MIPS1_NOT_32R6_64R6;
def MTLO : MMRel, MoveToLOHI<"mtlo", GPR32Opnd, [LO0]>, MTLO_FM<0x13>,
@@ -1633,9 +1985,9 @@ def SEH : MMRel, StdMMR6Rel, SignExtInReg<"seh", i16, GPR32Opnd, II_SEH>,
SEB_FM<0x18, 0x20>, ISA_MIPS32R2;
/// Count Leading
-def CLZ : MMRel, CountLeading0<"clz", GPR32Opnd>, CLO_FM<0x20>,
+def CLZ : MMRel, CountLeading0<"clz", GPR32Opnd, II_CLZ>, CLO_FM<0x20>,
ISA_MIPS32_NOT_32R6_64R6;
-def CLO : MMRel, CountLeading1<"clo", GPR32Opnd>, CLO_FM<0x21>,
+def CLO : MMRel, CountLeading1<"clo", GPR32Opnd, II_CLO>, CLO_FM<0x21>,
ISA_MIPS32_NOT_32R6_64R6;
let AdditionalPredicates = [NotInMicroMips] in {
@@ -1681,29 +2033,39 @@ def PseudoMSUBU : MAddSubPseudo<MSUBU, MipsMSubu, II_MSUBU>,
ISA_MIPS32_NOT_32R6_64R6;
}
-def PseudoSDIV : MultDivPseudo<SDIV, ACC64, GPR32Opnd, MipsDivRem, II_DIV,
- 0, 1, 1>, ISA_MIPS1_NOT_32R6_64R6;
-def PseudoUDIV : MultDivPseudo<UDIV, ACC64, GPR32Opnd, MipsDivRemU, II_DIVU,
- 0, 1, 1>, ISA_MIPS1_NOT_32R6_64R6;
let AdditionalPredicates = [NotInMicroMips] in {
-def RDHWR : MMRel, ReadHardware<GPR32Opnd, HWRegsOpnd>, RDHWR_FM;
+ def PseudoSDIV : MultDivPseudo<SDIV, ACC64, GPR32Opnd, MipsDivRem, II_DIV,
+ 0, 1, 1>, ISA_MIPS1_NOT_32R6_64R6;
+ def PseudoUDIV : MultDivPseudo<UDIV, ACC64, GPR32Opnd, MipsDivRemU, II_DIVU,
+ 0, 1, 1>, ISA_MIPS1_NOT_32R6_64R6;
+ def RDHWR : MMRel, ReadHardware<GPR32Opnd, HWRegsOpnd>, RDHWR_FM;
+ // TODO: Add '0 < pos+size <= 32' constraint check to ext instruction
+ def EXT : MMRel, StdMMR6Rel, ExtBase<"ext", GPR32Opnd, uimm5, uimm5_plus1,
+ immZExt5, immZExt5Plus1, MipsExt>,
+ EXT_FM<0>;
+ def INS : MMRel, StdMMR6Rel, InsBase<"ins", GPR32Opnd, uimm5,
+ uimm5_inssize_plus1, MipsIns>,
+ EXT_FM<4>;
}
-// TODO: Add '0 < pos+size <= 32' constraint check to ext instruction
-def EXT : MMRel, ExtBase<"ext", GPR32Opnd, uimm5, uimm5_plus1, MipsExt>,
- EXT_FM<0>;
-def INS : MMRel, InsBase<"ins", GPR32Opnd, uimm5, MipsIns>, EXT_FM<4>;
-
/// Move Control Registers From/To CPU Registers
-def MFC0 : MFC3OP<"mfc0", GPR32Opnd, COP0Opnd>, MFC3OP_FM<0x10, 0>, ISA_MIPS32;
-def MTC0 : MTC3OP<"mtc0", COP0Opnd, GPR32Opnd>, MFC3OP_FM<0x10, 4>, ISA_MIPS32;
-def MFC2 : MFC3OP<"mfc2", GPR32Opnd, COP2Opnd>, MFC3OP_FM<0x12, 0>;
-def MTC2 : MTC3OP<"mtc2", COP2Opnd, GPR32Opnd>, MFC3OP_FM<0x12, 4>;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def MTC0 : MTC3OP<"mtc0", COP0Opnd, GPR32Opnd, II_MTC0>, MFC3OP_FM<0x10, 4>,
+ ISA_MIPS32;
+ def MFC0 : MFC3OP<"mfc0", GPR32Opnd, COP0Opnd, II_MFC0>, MFC3OP_FM<0x10, 0>,
+ ISA_MIPS32;
+}
+def MFC2 : MFC3OP<"mfc2", GPR32Opnd, COP2Opnd, II_MFC2>, MFC3OP_FM<0x12, 0>;
+def MTC2 : MTC3OP<"mtc2", COP2Opnd, GPR32Opnd, II_MTC2>, MFC3OP_FM<0x12, 4>;
+
+class Barrier<string asmstr, InstrItinClass itin = NoItinerary> :
+ InstSE<(outs), (ins), asmstr, [], itin, FrmOther, asmstr>;
-class Barrier<string asmstr> : InstSE<(outs), (ins), asmstr, [], NoItinerary,
- FrmOther, asmstr>;
-def SSNOP : MMRel, StdMMR6Rel, Barrier<"ssnop">, BARRIER_FM<1>;
-def EHB : MMRel, Barrier<"ehb">, BARRIER_FM<3>;
-def PAUSE : MMRel, StdMMR6Rel, Barrier<"pause">, BARRIER_FM<5>, ISA_MIPS32R2;
+def SSNOP : MMRel, StdMMR6Rel, Barrier<"ssnop", II_SSNOP>, BARRIER_FM<1>;
+def EHB : MMRel, Barrier<"ehb", II_EHB>, BARRIER_FM<3>;
+
+let isCTI = 1 in
+def PAUSE : MMRel, StdMMR6Rel, Barrier<"pause", II_PAUSE>, BARRIER_FM<5>,
+ ISA_MIPS32R2;
// JR_HB and JALR_HB are defined here using the new style naming
// scheme because some of this code is shared with Mips32r6InstrInfo.td
@@ -1724,19 +2086,21 @@ class JALR_HB_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> {
list<dag> Pattern = [];
}
-class JR_HB_DESC : InstSE<(outs), (ins), "", [], NoItinerary, FrmJ>,
+class JR_HB_DESC : InstSE<(outs), (ins), "", [], II_JR_HB, FrmJ>,
JR_HB_DESC_BASE<"jr.hb", GPR32Opnd> {
let isBranch=1;
let isIndirectBranch=1;
let hasDelaySlot=1;
let isTerminator=1;
let isBarrier=1;
+ bit isCTI = 1;
}
-class JALR_HB_DESC : InstSE<(outs), (ins), "", [], NoItinerary, FrmJ>,
+class JALR_HB_DESC : InstSE<(outs), (ins), "", [], II_JALR_HB, FrmJ>,
JALR_HB_DESC_BASE<"jalr.hb", GPR32Opnd> {
let isIndirectBranch=1;
let hasDelaySlot=1;
+ bit isCTI = 1;
}
class JR_HB_ENC : JR_HB_FM<8>;
@@ -1745,23 +2109,25 @@ class JALR_HB_ENC : JALR_HB_FM<9>;
def JR_HB : JR_HB_DESC, JR_HB_ENC, ISA_MIPS32_NOT_32R6_64R6;
def JALR_HB : JALR_HB_DESC, JALR_HB_ENC, ISA_MIPS32;
-class TLB<string asmstr> : InstSE<(outs), (ins), asmstr, [], NoItinerary,
- FrmOther, asmstr>;
-def TLBP : MMRel, TLB<"tlbp">, COP0_TLB_FM<0x08>;
-def TLBR : MMRel, TLB<"tlbr">, COP0_TLB_FM<0x01>;
-def TLBWI : MMRel, TLB<"tlbwi">, COP0_TLB_FM<0x02>;
-def TLBWR : MMRel, TLB<"tlbwr">, COP0_TLB_FM<0x06>;
-
-class CacheOp<string instr_asm, Operand MemOpnd> :
+class TLB<string asmstr, InstrItinClass itin = NoItinerary> :
+ InstSE<(outs), (ins), asmstr, [], itin, FrmOther, asmstr>;
+let AdditionalPredicates = [NotInMicroMips] in {
+def TLBP : MMRel, TLB<"tlbp", II_TLBP>, COP0_TLB_FM<0x08>;
+def TLBR : MMRel, TLB<"tlbr", II_TLBR>, COP0_TLB_FM<0x01>;
+def TLBWI : MMRel, TLB<"tlbwi", II_TLBWI>, COP0_TLB_FM<0x02>;
+def TLBWR : MMRel, TLB<"tlbwr", II_TLBWR>, COP0_TLB_FM<0x06>;
+}
+class CacheOp<string instr_asm, Operand MemOpnd,
+ InstrItinClass itin = NoItinerary> :
InstSE<(outs), (ins MemOpnd:$addr, uimm5:$hint),
- !strconcat(instr_asm, "\t$hint, $addr"), [], NoItinerary, FrmOther,
+ !strconcat(instr_asm, "\t$hint, $addr"), [], itin, FrmOther,
instr_asm> {
let DecoderMethod = "DecodeCacheOp";
}
-def CACHE : MMRel, CacheOp<"cache", mem>, CACHEOP_FM<0b101111>,
+def CACHE : MMRel, CacheOp<"cache", mem, II_CACHE>, CACHEOP_FM<0b101111>,
INSN_MIPS3_32_NOT_32R6_64R6;
-def PREF : MMRel, CacheOp<"pref", mem>, CACHEOP_FM<0b110011>,
+def PREF : MMRel, CacheOp<"pref", mem, II_PREF>, CACHEOP_FM<0b110011>,
INSN_MIPS3_32_NOT_32R6_64R6;
def ROL : MipsAsmPseudoInst<(outs),
@@ -1808,6 +2174,9 @@ def : MipsInstAlias<"dror $rd, $rs",
def : MipsInstAlias<"dror $rd, $imm",
(DRORImm GPR32Opnd:$rd, GPR32Opnd:$rd, simm16:$imm), 0>, ISA_MIPS64;
+def ABSMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), (ins GPR32Opnd:$rs),
+ "abs\t$rd, $rs">;
+
//===----------------------------------------------------------------------===//
// Instruction aliases
//===----------------------------------------------------------------------===//
@@ -1823,47 +2192,66 @@ def : MipsInstAlias<"move $dst, $src",
}
def : MipsInstAlias<"bal $offset", (BGEZAL ZERO, brtarget:$offset), 0>,
ISA_MIPS1_NOT_32R6_64R6;
-def : MipsInstAlias<"addu $rs, $rt, $imm",
- (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>;
-def : MipsInstAlias<"addu $rs, $imm",
- (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm), 0>;
-def : MipsInstAlias<"add $rs, $rt, $imm",
- (ADDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>,
- ISA_MIPS1_NOT_32R6_64R6;
-def : MipsInstAlias<"add $rs, $imm",
- (ADDi GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm), 0>,
- ISA_MIPS1_NOT_32R6_64R6;
-def : MipsInstAlias<"and $rs, $rt, $imm",
- (ANDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>;
-def : MipsInstAlias<"and $rs, $imm",
- (ANDi GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm), 0>;
+def : MipsInstAlias<
+ "addu $rs, $rt, $imm",
+ (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rt, simm32_relaxed:$imm), 0>;
+def : MipsInstAlias<
+ "addu $rs, $imm",
+ (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rs, simm32_relaxed:$imm), 0>;
+def : MipsInstAlias<
+ "add $rs, $rt, $imm",
+ (ADDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm32_relaxed:$imm), 0>,
+ ISA_MIPS1_NOT_32R6_64R6;
+def : MipsInstAlias<
+ "add $rs, $imm",
+ (ADDi GPR32Opnd:$rs, GPR32Opnd:$rs, simm32_relaxed:$imm), 0>,
+ ISA_MIPS1_NOT_32R6_64R6;
+def : MipsInstAlias<
+ "and $rs, $rt, $imm",
+ (ANDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm32_relaxed:$imm), 0>;
+def : MipsInstAlias<
+ "and $rs, $imm",
+ (ANDi GPR32Opnd:$rs, GPR32Opnd:$rs, simm32_relaxed:$imm), 0>;
def : MipsInstAlias<"j $rs", (JR GPR32Opnd:$rs), 0>;
let Predicates = [NotInMicroMips] in {
def : MipsInstAlias<"jalr $rs", (JALR RA, GPR32Opnd:$rs), 0>;
}
def : MipsInstAlias<"jalr.hb $rs", (JALR_HB RA, GPR32Opnd:$rs), 1>, ISA_MIPS32;
-def : MipsInstAlias<"not $rt, $rs",
- (NOR GPR32Opnd:$rt, GPR32Opnd:$rs, ZERO), 0>;
def : MipsInstAlias<"neg $rt, $rs",
(SUB GPR32Opnd:$rt, ZERO, GPR32Opnd:$rs), 1>;
def : MipsInstAlias<"negu $rt",
(SUBu GPR32Opnd:$rt, ZERO, GPR32Opnd:$rt), 0>;
def : MipsInstAlias<"negu $rt, $rs",
(SUBu GPR32Opnd:$rt, ZERO, GPR32Opnd:$rs), 1>;
-def : MipsInstAlias<"slt $rs, $rt, $imm",
- (SLTi GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>;
-def : MipsInstAlias<"sltu $rt, $rs, $imm",
- (SLTiu GPR32Opnd:$rt, GPR32Opnd:$rs, simm16:$imm), 0>;
-def : MipsInstAlias<"xor $rs, $rt, $imm",
- (XORi GPR32Opnd:$rs, GPR32Opnd:$rt, uimm16:$imm), 0>;
-def : MipsInstAlias<"xor $rs, $imm",
- (XORi GPR32Opnd:$rs, GPR32Opnd:$rs, uimm16:$imm), 0>;
-def : MipsInstAlias<"or $rs, $rt, $imm",
- (ORi GPR32Opnd:$rs, GPR32Opnd:$rt, uimm16:$imm), 0>;
-def : MipsInstAlias<"or $rs, $imm",
- (ORi GPR32Opnd:$rs, GPR32Opnd:$rs, uimm16:$imm), 0>;
+def : MipsInstAlias<
+ "slt $rs, $rt, $imm",
+ (SLTi GPR32Opnd:$rs, GPR32Opnd:$rt, simm32_relaxed:$imm), 0>;
+def : MipsInstAlias<
+ "sltu $rt, $rs, $imm",
+ (SLTiu GPR32Opnd:$rt, GPR32Opnd:$rs, simm32_relaxed:$imm), 0>;
let AdditionalPredicates = [NotInMicroMips] in {
-def : MipsInstAlias<"nop", (SLL ZERO, ZERO, 0), 1>;
+ def : MipsInstAlias<
+ "and $rs, $rt, $imm",
+ (ANDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm32_relaxed:$imm), 0>;
+ def : MipsInstAlias<
+ "and $rs, $imm",
+ (ANDi GPR32Opnd:$rs, GPR32Opnd:$rs, simm32_relaxed:$imm), 0>;
+ def : MipsInstAlias<
+ "xor $rs, $rt, $imm",
+ (XORi GPR32Opnd:$rs, GPR32Opnd:$rt, simm32_relaxed:$imm), 0>;
+ def : MipsInstAlias<
+ "xor $rs, $imm",
+ (XORi GPR32Opnd:$rs, GPR32Opnd:$rs, simm32_relaxed:$imm), 0>;
+ def : MipsInstAlias<
+ "or $rs, $rt, $imm",
+ (ORi GPR32Opnd:$rs, GPR32Opnd:$rt, simm32_relaxed:$imm), 0>;
+ def : MipsInstAlias<
+ "or $rs, $imm",
+ (ORi GPR32Opnd:$rs, GPR32Opnd:$rs, simm32_relaxed:$imm), 0>;
+ def : MipsInstAlias<
+ "not $rt, $rs",
+ (NOR GPR32Opnd:$rt, GPR32Opnd:$rs, ZERO), 0>;
+ def : MipsInstAlias<"nop", (SLL ZERO, ZERO, 0), 1>;
}
def : MipsInstAlias<"mfc0 $rt, $rd", (MFC0 GPR32Opnd:$rt, COP0Opnd:$rd, 0), 0>;
def : MipsInstAlias<"mtc0 $rt, $rd", (MTC0 COP0Opnd:$rd, GPR32Opnd:$rt, 0), 0>;
@@ -1880,7 +2268,9 @@ def : MipsInstAlias<"beqz $rs,$offset",
(BEQ GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>;
def : MipsInstAlias<"beqzl $rs,$offset",
(BEQL GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>;
-def : MipsInstAlias<"syscall", (SYSCALL 0), 1>;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def : MipsInstAlias<"syscall", (SYSCALL 0), 1>;
+}
def : MipsInstAlias<"break", (BREAK 0, 0), 1>;
def : MipsInstAlias<"break $imm", (BREAK uimm10:$imm, 0), 1>;
@@ -1902,8 +2292,6 @@ let AdditionalPredicates = [NotInMicroMips] in {
def : MipsInstAlias<"tne $rs, $rt",
(TNE GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>, ISA_MIPS2;
}
-def : MipsInstAlias<"sll $rd, $rt, $rs",
- (SLLV GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>;
def : MipsInstAlias<"sub, $rd, $rs, $imm",
(ADDi GPR32Opnd:$rd, GPR32Opnd:$rs,
InvertedImOperand:$imm), 0>, ISA_MIPS1_NOT_32R6_64R6;
@@ -1915,10 +2303,14 @@ def : MipsInstAlias<"subu, $rd, $rs, $imm",
InvertedImOperand:$imm), 0>;
def : MipsInstAlias<"subu $rs, $imm", (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rs,
InvertedImOperand:$imm), 0>;
-def : MipsInstAlias<"sra $rd, $rt, $rs",
- (SRAV GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>;
-def : MipsInstAlias<"srl $rd, $rt, $rs",
- (SRLV GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def : MipsInstAlias<"sll $rd, $rt, $rs",
+ (SLLV GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>;
+ def : MipsInstAlias<"sra $rd, $rt, $rs",
+ (SRAV GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>;
+ def : MipsInstAlias<"srl $rd, $rt, $rs",
+ (SRLV GPR32Opnd:$rd, GPR32Opnd:$rt, GPR32Opnd:$rs), 0>;
+}
def : MipsInstAlias<"sdbbp", (SDBBP 0)>, ISA_MIPS32_NOT_32R6_64R6;
def : MipsInstAlias<"sync",
(SYNC 0), 1>, ISA_MIPS2;
@@ -1926,10 +2318,11 @@ def : MipsInstAlias<"sync",
// Assembler Pseudo Instructions
//===----------------------------------------------------------------------===//
+// We use i32imm on li/la to defer range checking to the assembler.
class LoadImmediate32<string instr_asm, Operand Od, RegisterOperand RO> :
MipsAsmPseudoInst<(outs RO:$rt), (ins Od:$imm32),
!strconcat(instr_asm, "\t$rt, $imm32")> ;
-def LoadImm32 : LoadImmediate32<"li", simm32, GPR32Opnd>;
+def LoadImm32 : LoadImmediate32<"li", i32imm, GPR32Opnd>;
class LoadAddressFromReg32<string instr_asm, Operand MemOpnd,
RegisterOperand RO> :
@@ -1940,17 +2333,18 @@ def LoadAddrReg32 : LoadAddressFromReg32<"la", mem, GPR32Opnd>;
class LoadAddressFromImm32<string instr_asm, Operand Od, RegisterOperand RO> :
MipsAsmPseudoInst<(outs RO:$rt), (ins Od:$imm32),
!strconcat(instr_asm, "\t$rt, $imm32")> ;
-def LoadAddrImm32 : LoadAddressFromImm32<"la", simm32, GPR32Opnd>;
+def LoadAddrImm32 : LoadAddressFromImm32<"la", i32imm, GPR32Opnd>;
def JalTwoReg : MipsAsmPseudoInst<(outs GPR32Opnd:$rd), (ins GPR32Opnd:$rs),
"jal\t$rd, $rs"> ;
def JalOneReg : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs),
"jal\t$rs"> ;
-def NORImm : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm),
- "nor\t$rs, $rt, $imm"> ;
+def NORImm : MipsAsmPseudoInst<
+ (outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt, simm32:$imm),
+ "nor\t$rs, $rt, $imm"> ;
-let hasDelaySlot = 1 in {
+let hasDelaySlot = 1, isCTI = 1 in {
def BneImm : MipsAsmPseudoInst<(outs GPR32Opnd:$rt),
(ins imm64:$imm64, brtarget:$offset),
"bne\t$rt, $imm64, $offset">;
@@ -1981,6 +2375,7 @@ def BLEUL: CondBranchPseudo<"bleul">, ISA_MIPS2_NOT_32R6_64R6;
def BGEUL: CondBranchPseudo<"bgeul">, ISA_MIPS2_NOT_32R6_64R6;
def BGTUL: CondBranchPseudo<"bgtul">, ISA_MIPS2_NOT_32R6_64R6;
+let isCTI = 1 in
class CondBranchImmPseudo<string instr_asm> :
MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, imm64:$imm, brtarget:$offset),
!strconcat(instr_asm, "\t$rs, $imm, $offset")>;
@@ -2008,17 +2403,34 @@ def BGTULImmMacro : CondBranchImmPseudo<"bgtul">, ISA_MIPS2_NOT_32R6_64R6;
// Once the tablegen-erated errors are made better, this needs to be fixed and
// predicates needs to be restored.
-def SDivMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt),
- "div\t$rs, $rt">; //, ISA_MIPS1_NOT_32R6_64R6;
-
-def UDivMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt),
- "divu\t$rs, $rt">; //, ISA_MIPS1_NOT_32R6_64R6;
-
-def DSDivMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt),
- "ddiv\t$rs, $rt">; //, ISA_MIPS64_NOT_64R6;
-
-def DUDivMacro : MipsAsmPseudoInst<(outs), (ins GPR32Opnd:$rs, GPR32Opnd:$rt),
- "ddivu\t$rs, $rt">; //, ISA_MIPS64_NOT_64R6;
+def SDivMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd),
+ (ins GPR32Opnd:$rs, GPR32Opnd:$rt),
+ "div\t$rd, $rs, $rt">,
+ ISA_MIPS1_NOT_32R6_64R6;
+def UDivMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd),
+ (ins GPR32Opnd:$rs, GPR32Opnd:$rt),
+ "divu\t$rd, $rs, $rt">,
+ ISA_MIPS1_NOT_32R6_64R6;
+def : MipsInstAlias<"div $rt, $rs", (SDivMacro GPR32Opnd:$rt, GPR32Opnd:$rt,
+ GPR32Opnd:$rs), 0>,
+ ISA_MIPS1_NOT_32R6_64R6;
+def : MipsInstAlias<"divu $rt, $rs", (UDivMacro GPR32Opnd:$rt, GPR32Opnd:$rt,
+ GPR32Opnd:$rs), 0>,
+ ISA_MIPS1_NOT_32R6_64R6;
+def DSDivMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd),
+ (ins GPR32Opnd:$rs, GPR32Opnd:$rt),
+ "ddiv\t$rd, $rs, $rt">,
+ ISA_MIPS64_NOT_64R6;
+def DUDivMacro : MipsAsmPseudoInst<(outs GPR32Opnd:$rd),
+ (ins GPR32Opnd:$rs, GPR32Opnd:$rt),
+ "ddivu\t$rd, $rs, $rt">,
+ ISA_MIPS64_NOT_64R6;
+def : MipsInstAlias<"ddiv $rt, $rs", (DSDivMacro GPR32Opnd:$rt, GPR32Opnd:$rt,
+ GPR32Opnd:$rs), 0>,
+ ISA_MIPS64_NOT_64R6;
+def : MipsInstAlias<"ddivu $rt, $rs", (DUDivMacro GPR32Opnd:$rt, GPR32Opnd:$rt,
+ GPR32Opnd:$rs), 0>,
+ ISA_MIPS64_NOT_64R6;
def Ulh : MipsAsmPseudoInst<(outs GPR32Opnd:$rt), (ins mem:$addr),
"ulh\t$rt, $addr">; //, ISA_MIPS1_NOT_32R6_64R6;
@@ -2055,14 +2467,14 @@ def : MipsPat<(i32 imm:$imm),
(ORi (LUi (HI16 imm:$imm)), (LO16 imm:$imm))>;
// Carry MipsPatterns
-def : MipsPat<(subc GPR32:$lhs, GPR32:$rhs),
- (SUBu GPR32:$lhs, GPR32:$rhs)>;
-let AdditionalPredicates = [NotDSP] in {
- def : MipsPat<(addc GPR32:$lhs, GPR32:$rhs),
- (ADDu GPR32:$lhs, GPR32:$rhs)>;
- def : MipsPat<(addc GPR32:$src, immSExt16:$imm),
- (ADDiu GPR32:$src, imm:$imm)>;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def : MipsPat<(subc GPR32:$lhs, GPR32:$rhs),
+ (SUBu GPR32:$lhs, GPR32:$rhs)>;
}
+def : MipsPat<(addc GPR32:$lhs, GPR32:$rhs),
+ (ADDu GPR32:$lhs, GPR32:$rhs)>, ASE_NOT_DSP;
+def : MipsPat<(addc GPR32:$src, immSExt16:$imm),
+ (ADDiu GPR32:$src, imm:$imm)>, ASE_NOT_DSP;
// Support multiplication for pre-Mips32 targets that don't have
// the MUL instruction.
@@ -2138,7 +2550,9 @@ def : MipsPat<(not GPR32:$in),
// extended loads
def : MipsPat<(i32 (extloadi1 addr:$src)), (LBu addr:$src)>;
def : MipsPat<(i32 (extloadi8 addr:$src)), (LBu addr:$src)>;
-def : MipsPat<(i32 (extloadi16 addr:$src)), (LHu addr:$src)>;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def : MipsPat<(i32 (extloadi16 addr:$src)), (LHu addr:$src)>;
+}
// peepholes
def : MipsPat<(store (i32 0), addr:$dst), (SW ZERO, addr:$dst)>;
@@ -2235,15 +2649,17 @@ def : MipsPat<(bswap GPR32:$rt), (ROTR (WSBH GPR32:$rt), 16)>;
// Load halfword/word patterns.
let AddedComplexity = 40 in {
def : LoadRegImmPat<LBu, i32, zextloadi8>;
- def : LoadRegImmPat<LH, i32, sextloadi16>;
let AdditionalPredicates = [NotInMicroMips] in {
- def : LoadRegImmPat<LW, i32, load>;
+ def : LoadRegImmPat<LH, i32, sextloadi16>;
+ def : LoadRegImmPat<LW, i32, load>;
}
}
// Atomic load patterns.
def : MipsPat<(atomic_load_8 addr:$a), (LB addr:$a)>;
-def : MipsPat<(atomic_load_16 addr:$a), (LH addr:$a)>;
+let AdditionalPredicates = [NotInMicroMips] in {
+ def : MipsPat<(atomic_load_16 addr:$a), (LH addr:$a)>;
+}
def : MipsPat<(atomic_load_32 addr:$a), (LW addr:$a)>;
// Atomic store patterns.
diff --git a/lib/Target/Mips/MipsLongBranch.cpp b/lib/Target/Mips/MipsLongBranch.cpp
index 49fb99a8ec432..e721312390d2c 100644
--- a/lib/Target/Mips/MipsLongBranch.cpp
+++ b/lib/Target/Mips/MipsLongBranch.cpp
@@ -63,8 +63,7 @@ namespace {
public:
static char ID;
MipsLongBranch(TargetMachine &tm)
- : MachineFunctionPass(ID), TM(tm),
- IsPIC(TM.getRelocationModel() == Reloc::PIC_),
+ : MachineFunctionPass(ID), TM(tm), IsPIC(TM.isPositionIndependent()),
ABI(static_cast<const MipsTargetMachine &>(TM).getABI()) {}
const char *getPassName() const override {
@@ -73,11 +72,16 @@ namespace {
bool runOnMachineFunction(MachineFunction &F) override;
+ MachineFunctionProperties getRequiredProperties() const override {
+ return MachineFunctionProperties().set(
+ MachineFunctionProperties::Property::AllVRegsAllocated);
+ }
+
private:
void splitMBB(MachineBasicBlock *MBB);
void initMBBInfo();
int64_t computeOffset(const MachineInstr *Br);
- void replaceBranch(MachineBasicBlock &MBB, Iter Br, DebugLoc DL,
+ void replaceBranch(MachineBasicBlock &MBB, Iter Br, const DebugLoc &DL,
MachineBasicBlock *MBBOpnd);
void expandToLongBranch(MBBInfo &Info);
@@ -113,7 +117,7 @@ static MachineBasicBlock *getTargetMBB(const MachineInstr &Br) {
// Traverse the list of instructions backwards until a non-debug instruction is
// found or it reaches E.
-static ReverseIter getNonDebugInstr(ReverseIter B, ReverseIter E) {
+static ReverseIter getNonDebugInstr(ReverseIter B, const ReverseIter &E) {
for (; B != E; ++B)
if (!B->isDebugValue())
return B;
@@ -160,8 +164,8 @@ void MipsLongBranch::splitMBB(MachineBasicBlock *MBB) {
void MipsLongBranch::initMBBInfo() {
// Split the MBBs if they have two branches. Each basic block should have at
// most one branch after this loop is executed.
- for (MachineFunction::iterator I = MF->begin(), E = MF->end(); I != E;)
- splitMBB(&*I++);
+ for (auto &MBB : *MF)
+ splitMBB(&MBB);
MF->RenumberBlocks();
MBBInfos.clear();
@@ -175,17 +179,15 @@ void MipsLongBranch::initMBBInfo() {
// Compute size of MBB.
for (MachineBasicBlock::instr_iterator MI = MBB->instr_begin();
MI != MBB->instr_end(); ++MI)
- MBBInfos[I].Size += TII->GetInstSizeInBytes(&*MI);
+ MBBInfos[I].Size += TII->GetInstSizeInBytes(*MI);
// Search for MBB's branch instruction.
ReverseIter End = MBB->rend();
ReverseIter Br = getNonDebugInstr(MBB->rbegin(), End);
if ((Br != End) && !Br->isIndirectBranch() &&
- (Br->isConditionalBranch() ||
- (Br->isUnconditionalBranch() &&
- TM.getRelocationModel() == Reloc::PIC_)))
- MBBInfos[I].Br = (++Br).base();
+ (Br->isConditionalBranch() || (Br->isUnconditionalBranch() && IsPIC)))
+ MBBInfos[I].Br = &*(++Br).base();
}
}
@@ -213,7 +215,8 @@ int64_t MipsLongBranch::computeOffset(const MachineInstr *Br) {
// Replace Br with a branch which has the opposite condition code and a
// MachineBasicBlock operand MBBOpnd.
void MipsLongBranch::replaceBranch(MachineBasicBlock &MBB, Iter Br,
- DebugLoc DL, MachineBasicBlock *MBBOpnd) {
+ const DebugLoc &DL,
+ MachineBasicBlock *MBBOpnd) {
const MipsInstrInfo *TII = static_cast<const MipsInstrInfo *>(
MBB.getParent()->getSubtarget().getInstrInfo());
unsigned NewOpc = TII->getOppositeBranchOpc(Br->getOpcode());
@@ -238,7 +241,7 @@ void MipsLongBranch::replaceBranch(MachineBasicBlock &MBB, Iter Br,
// Bundle the instruction in the delay slot to the newly created branch
// and erase the original branch.
assert(Br->isBundledWithSucc());
- MachineBasicBlock::instr_iterator II(Br);
+ MachineBasicBlock::instr_iterator II = Br.getInstrIterator();
MIBundleBuilder(&*MIB).append((++II)->removeFromBundle());
}
Br->eraseFromParent();
@@ -329,23 +332,26 @@ void MipsLongBranch::expandToLongBranch(MBBInfo &I) {
BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::LW), Mips::RA)
.addReg(Mips::SP).addImm(0);
- if (!Subtarget.isTargetNaCl()) {
- MIBundleBuilder(*BalTgtMBB, Pos)
- .append(BuildMI(*MF, DL, TII->get(Mips::JR)).addReg(Mips::AT))
- .append(BuildMI(*MF, DL, TII->get(Mips::ADDiu), Mips::SP)
- .addReg(Mips::SP).addImm(8));
- } else {
- // In NaCl, modifying the sp is not allowed in branch delay slot.
+ // In NaCl, modifying the sp is not allowed in branch delay slot.
+ if (Subtarget.isTargetNaCl())
BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::ADDiu), Mips::SP)
.addReg(Mips::SP).addImm(8);
- MIBundleBuilder(*BalTgtMBB, Pos)
- .append(BuildMI(*MF, DL, TII->get(Mips::JR)).addReg(Mips::AT))
- .append(BuildMI(*MF, DL, TII->get(Mips::NOP)));
+ if (Subtarget.hasMips32r6())
+ BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::JALR))
+ .addReg(Mips::ZERO).addReg(Mips::AT);
+ else
+ BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::JR)).addReg(Mips::AT);
+ if (Subtarget.isTargetNaCl()) {
+ BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::NOP));
// Bundle-align the target of indirect branch JR.
TgtMBB->setAlignment(MIPS_NACL_BUNDLE_ALIGN);
- }
+ } else
+ BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::ADDiu), Mips::SP)
+ .addReg(Mips::SP).addImm(8);
+
+ BalTgtMBB->rbegin()->bundleWithPred();
} else {
// $longbr:
// daddiu $sp, $sp, -16
@@ -404,10 +410,15 @@ void MipsLongBranch::expandToLongBranch(MBBInfo &I) {
BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::LD), Mips::RA_64)
.addReg(Mips::SP_64).addImm(0);
- MIBundleBuilder(*BalTgtMBB, Pos)
- .append(BuildMI(*MF, DL, TII->get(Mips::JR64)).addReg(Mips::AT_64))
- .append(BuildMI(*MF, DL, TII->get(Mips::DADDiu), Mips::SP_64)
- .addReg(Mips::SP_64).addImm(16));
+ if (Subtarget.hasMips64r6())
+ BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::JALR64))
+ .addReg(Mips::ZERO_64).addReg(Mips::AT_64);
+ else
+ BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::JR64)).addReg(Mips::AT_64);
+
+ BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::DADDiu), Mips::SP_64)
+ .addReg(Mips::SP_64).addImm(16);
+ BalTgtMBB->rbegin()->bundleWithPred();
}
assert(LongBrMBB->size() + BalTgtMBB->size() == LongBranchSeqSize);
@@ -457,8 +468,7 @@ bool MipsLongBranch::runOnMachineFunction(MachineFunction &F) {
if (STI.inMips16Mode() || !STI.enableLongBranchPass())
return false;
- if ((TM.getRelocationModel() == Reloc::PIC_) &&
- static_cast<const MipsTargetMachine &>(TM).getABI().IsO32() &&
+ if (IsPIC && static_cast<const MipsTargetMachine &>(TM).getABI().IsO32() &&
F.getInfo<MipsFunctionInfo>()->globalBaseRegSet())
emitGPDisp(F, TII);
@@ -506,7 +516,7 @@ bool MipsLongBranch::runOnMachineFunction(MachineFunction &F) {
return true;
// Compute basic block addresses.
- if (TM.getRelocationModel() == Reloc::PIC_) {
+ if (IsPIC) {
uint64_t Address = 0;
for (I = MBBInfos.begin(); I != E; Address += I->Size, ++I)
diff --git a/lib/Target/Mips/MipsMCInstLower.cpp b/lib/Target/Mips/MipsMCInstLower.cpp
index 80d9b75b85b7d..d5bc4e537c37c 100644
--- a/lib/Target/Mips/MipsMCInstLower.cpp
+++ b/lib/Target/Mips/MipsMCInstLower.cpp
@@ -36,36 +36,87 @@ void MipsMCInstLower::Initialize(MCContext *C) {
MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
MachineOperandType MOTy,
unsigned Offset) const {
- MCSymbolRefExpr::VariantKind Kind;
+ MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None;
+ MipsMCExpr::MipsExprKind TargetKind = MipsMCExpr::MEK_None;
+ bool IsGpOff = false;
const MCSymbol *Symbol;
switch(MO.getTargetFlags()) {
- default: llvm_unreachable("Invalid target flag!");
- case MipsII::MO_NO_FLAG: Kind = MCSymbolRefExpr::VK_None; break;
- case MipsII::MO_GPREL: Kind = MCSymbolRefExpr::VK_Mips_GPREL; break;
- case MipsII::MO_GOT_CALL: Kind = MCSymbolRefExpr::VK_Mips_GOT_CALL; break;
- case MipsII::MO_GOT16: Kind = MCSymbolRefExpr::VK_Mips_GOT16; break;
- case MipsII::MO_GOT: Kind = MCSymbolRefExpr::VK_Mips_GOT; break;
- case MipsII::MO_ABS_HI: Kind = MCSymbolRefExpr::VK_Mips_ABS_HI; break;
- case MipsII::MO_ABS_LO: Kind = MCSymbolRefExpr::VK_Mips_ABS_LO; break;
- case MipsII::MO_TLSGD: Kind = MCSymbolRefExpr::VK_Mips_TLSGD; break;
- case MipsII::MO_TLSLDM: Kind = MCSymbolRefExpr::VK_Mips_TLSLDM; break;
- case MipsII::MO_DTPREL_HI: Kind = MCSymbolRefExpr::VK_Mips_DTPREL_HI; break;
- case MipsII::MO_DTPREL_LO: Kind = MCSymbolRefExpr::VK_Mips_DTPREL_LO; break;
- case MipsII::MO_GOTTPREL: Kind = MCSymbolRefExpr::VK_Mips_GOTTPREL; break;
- case MipsII::MO_TPREL_HI: Kind = MCSymbolRefExpr::VK_Mips_TPREL_HI; break;
- case MipsII::MO_TPREL_LO: Kind = MCSymbolRefExpr::VK_Mips_TPREL_LO; break;
- case MipsII::MO_GPOFF_HI: Kind = MCSymbolRefExpr::VK_Mips_GPOFF_HI; break;
- case MipsII::MO_GPOFF_LO: Kind = MCSymbolRefExpr::VK_Mips_GPOFF_LO; break;
- case MipsII::MO_GOT_DISP: Kind = MCSymbolRefExpr::VK_Mips_GOT_DISP; break;
- case MipsII::MO_GOT_PAGE: Kind = MCSymbolRefExpr::VK_Mips_GOT_PAGE; break;
- case MipsII::MO_GOT_OFST: Kind = MCSymbolRefExpr::VK_Mips_GOT_OFST; break;
- case MipsII::MO_HIGHER: Kind = MCSymbolRefExpr::VK_Mips_HIGHER; break;
- case MipsII::MO_HIGHEST: Kind = MCSymbolRefExpr::VK_Mips_HIGHEST; break;
- case MipsII::MO_GOT_HI16: Kind = MCSymbolRefExpr::VK_Mips_GOT_HI16; break;
- case MipsII::MO_GOT_LO16: Kind = MCSymbolRefExpr::VK_Mips_GOT_LO16; break;
- case MipsII::MO_CALL_HI16: Kind = MCSymbolRefExpr::VK_Mips_CALL_HI16; break;
- case MipsII::MO_CALL_LO16: Kind = MCSymbolRefExpr::VK_Mips_CALL_LO16; break;
+ default:
+ llvm_unreachable("Invalid target flag!");
+ case MipsII::MO_NO_FLAG:
+ break;
+ case MipsII::MO_GPREL:
+ TargetKind = MipsMCExpr::MEK_GPREL;
+ break;
+ case MipsII::MO_GOT_CALL:
+ TargetKind = MipsMCExpr::MEK_GOT_CALL;
+ break;
+ case MipsII::MO_GOT:
+ TargetKind = MipsMCExpr::MEK_GOT;
+ break;
+ case MipsII::MO_ABS_HI:
+ TargetKind = MipsMCExpr::MEK_HI;
+ break;
+ case MipsII::MO_ABS_LO:
+ TargetKind = MipsMCExpr::MEK_LO;
+ break;
+ case MipsII::MO_TLSGD:
+ TargetKind = MipsMCExpr::MEK_TLSGD;
+ break;
+ case MipsII::MO_TLSLDM:
+ TargetKind = MipsMCExpr::MEK_TLSLDM;
+ break;
+ case MipsII::MO_DTPREL_HI:
+ TargetKind = MipsMCExpr::MEK_DTPREL_HI;
+ break;
+ case MipsII::MO_DTPREL_LO:
+ TargetKind = MipsMCExpr::MEK_DTPREL_LO;
+ break;
+ case MipsII::MO_GOTTPREL:
+ TargetKind = MipsMCExpr::MEK_GOTTPREL;
+ break;
+ case MipsII::MO_TPREL_HI:
+ TargetKind = MipsMCExpr::MEK_TPREL_HI;
+ break;
+ case MipsII::MO_TPREL_LO:
+ TargetKind = MipsMCExpr::MEK_TPREL_LO;
+ break;
+ case MipsII::MO_GPOFF_HI:
+ TargetKind = MipsMCExpr::MEK_HI;
+ IsGpOff = true;
+ break;
+ case MipsII::MO_GPOFF_LO:
+ TargetKind = MipsMCExpr::MEK_LO;
+ IsGpOff = true;
+ break;
+ case MipsII::MO_GOT_DISP:
+ TargetKind = MipsMCExpr::MEK_GOT_DISP;
+ break;
+ case MipsII::MO_GOT_HI16:
+ TargetKind = MipsMCExpr::MEK_GOT_HI16;
+ break;
+ case MipsII::MO_GOT_LO16:
+ TargetKind = MipsMCExpr::MEK_GOT_LO16;
+ break;
+ case MipsII::MO_GOT_PAGE:
+ TargetKind = MipsMCExpr::MEK_GOT_PAGE;
+ break;
+ case MipsII::MO_GOT_OFST:
+ TargetKind = MipsMCExpr::MEK_GOT_OFST;
+ break;
+ case MipsII::MO_HIGHER:
+ TargetKind = MipsMCExpr::MEK_HIGHER;
+ break;
+ case MipsII::MO_HIGHEST:
+ TargetKind = MipsMCExpr::MEK_HIGHEST;
+ break;
+ case MipsII::MO_CALL_HI16:
+ TargetKind = MipsMCExpr::MEK_CALL_HI16;
+ break;
+ case MipsII::MO_CALL_LO16:
+ TargetKind = MipsMCExpr::MEK_CALL_LO16;
+ break;
}
switch (MOTy) {
@@ -106,30 +157,23 @@ MCOperand MipsMCInstLower::LowerSymbolOperand(const MachineOperand &MO,
llvm_unreachable("<unknown operand type>");
}
- const MCSymbolRefExpr *MCSym = MCSymbolRefExpr::create(Symbol, Kind, *Ctx);
+ const MCExpr *Expr = MCSymbolRefExpr::create(Symbol, Kind, *Ctx);
- if (!Offset)
- return MCOperand::createExpr(MCSym);
+ if (Offset) {
+ // Assume offset is never negative.
+ assert(Offset > 0);
- // Assume offset is never negative.
- assert(Offset > 0);
+ Expr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(Offset, *Ctx),
+ *Ctx);
+ }
- const MCConstantExpr *OffsetExpr = MCConstantExpr::create(Offset, *Ctx);
- const MCBinaryExpr *Add = MCBinaryExpr::createAdd(MCSym, OffsetExpr, *Ctx);
- return MCOperand::createExpr(Add);
-}
+ if (IsGpOff)
+ Expr = MipsMCExpr::createGpOff(TargetKind, Expr, *Ctx);
+ else if (TargetKind != MipsMCExpr::MEK_None)
+ Expr = MipsMCExpr::create(TargetKind, Expr, *Ctx);
-/*
-static void CreateMCInst(MCInst& Inst, unsigned Opc, const MCOperand &Opnd0,
- const MCOperand &Opnd1,
- const MCOperand &Opnd2 = MCOperand()) {
- Inst.setOpcode(Opc);
- Inst.addOperand(Opnd0);
- Inst.addOperand(Opnd1);
- if (Opnd2.isValid())
- Inst.addOperand(Opnd2);
+ return MCOperand::createExpr(Expr);
}
-*/
MCOperand MipsMCInstLower::LowerOperand(const MachineOperand &MO,
unsigned offset) const {
@@ -160,7 +204,7 @@ MCOperand MipsMCInstLower::LowerOperand(const MachineOperand &MO,
MCOperand MipsMCInstLower::createSub(MachineBasicBlock *BB1,
MachineBasicBlock *BB2,
- MCSymbolRefExpr::VariantKind Kind) const {
+ MipsMCExpr::MipsExprKind Kind) const {
const MCSymbolRefExpr *Sym1 = MCSymbolRefExpr::create(BB1->getSymbol(), *Ctx);
const MCSymbolRefExpr *Sym2 = MCSymbolRefExpr::create(BB2->getSymbol(), *Ctx);
const MCBinaryExpr *Sub = MCBinaryExpr::createSub(Sym1, Sym2, *Ctx);
@@ -178,12 +222,12 @@ lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const {
// Create %hi($tgt-$baltgt).
OutMI.addOperand(createSub(MI->getOperand(1).getMBB(),
MI->getOperand(2).getMBB(),
- MCSymbolRefExpr::VK_Mips_ABS_HI));
+ MipsMCExpr::MEK_HI));
}
-void MipsMCInstLower::
-lowerLongBranchADDiu(const MachineInstr *MI, MCInst &OutMI, int Opcode,
- MCSymbolRefExpr::VariantKind Kind) const {
+void MipsMCInstLower::lowerLongBranchADDiu(
+ const MachineInstr *MI, MCInst &OutMI, int Opcode,
+ MipsMCExpr::MipsExprKind Kind) const {
OutMI.setOpcode(Opcode);
// Lower two register operands.
@@ -206,17 +250,14 @@ bool MipsMCInstLower::lowerLongBranch(const MachineInstr *MI,
lowerLongBranchLUi(MI, OutMI);
return true;
case Mips::LONG_BRANCH_ADDiu:
- lowerLongBranchADDiu(MI, OutMI, Mips::ADDiu,
- MCSymbolRefExpr::VK_Mips_ABS_LO);
+ lowerLongBranchADDiu(MI, OutMI, Mips::ADDiu, MipsMCExpr::MEK_LO);
return true;
case Mips::LONG_BRANCH_DADDiu:
unsigned TargetFlags = MI->getOperand(2).getTargetFlags();
if (TargetFlags == MipsII::MO_ABS_HI)
- lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu,
- MCSymbolRefExpr::VK_Mips_ABS_HI);
+ lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu, MipsMCExpr::MEK_HI);
else if (TargetFlags == MipsII::MO_ABS_LO)
- lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu,
- MCSymbolRefExpr::VK_Mips_ABS_LO);
+ lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu, MipsMCExpr::MEK_LO);
else
report_fatal_error("Unexpected flags for LONG_BRANCH_DADDiu");
return true;
diff --git a/lib/Target/Mips/MipsMCInstLower.h b/lib/Target/Mips/MipsMCInstLower.h
index 1ce27e4018503..c25f900054809 100644
--- a/lib/Target/Mips/MipsMCInstLower.h
+++ b/lib/Target/Mips/MipsMCInstLower.h
@@ -10,7 +10,6 @@
#ifndef LLVM_LIB_TARGET_MIPS_MIPSMCINSTLOWER_H
#define LLVM_LIB_TARGET_MIPS_MIPSMCINSTLOWER_H
#include "MCTargetDesc/MipsMCExpr.h"
-#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/Support/Compiler.h"
@@ -38,11 +37,10 @@ private:
MCOperand LowerSymbolOperand(const MachineOperand &MO,
MachineOperandType MOTy, unsigned Offset) const;
MCOperand createSub(MachineBasicBlock *BB1, MachineBasicBlock *BB2,
- MCSymbolRefExpr::VariantKind Kind) const;
+ MipsMCExpr::MipsExprKind Kind) const;
void lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const;
- void lowerLongBranchADDiu(const MachineInstr *MI, MCInst &OutMI,
- int Opcode,
- MCSymbolRefExpr::VariantKind Kind) const;
+ void lowerLongBranchADDiu(const MachineInstr *MI, MCInst &OutMI, int Opcode,
+ MipsMCExpr::MipsExprKind Kind) const;
bool lowerLongBranch(const MachineInstr *MI, MCInst &OutMI) const;
};
}
diff --git a/lib/Target/Mips/MipsMSAInstrInfo.td b/lib/Target/Mips/MipsMSAInstrInfo.td
index eacfcec78bc7d..deb4345e26628 100644
--- a/lib/Target/Mips/MipsMSAInstrInfo.td
+++ b/lib/Target/Mips/MipsMSAInstrInfo.td
@@ -65,53 +65,11 @@ def MipsVExtractZExt : SDNode<"MipsISD::VEXTRACT_ZEXT_ELT",
def immZExt1Ptr : ImmLeaf<iPTR, [{return isUInt<1>(Imm);}]>;
def immZExt2Ptr : ImmLeaf<iPTR, [{return isUInt<2>(Imm);}]>;
+def immZExt3Ptr : ImmLeaf<iPTR, [{return isUInt<3>(Imm);}]>;
def immZExt4Ptr : ImmLeaf<iPTR, [{return isUInt<4>(Imm);}]>;
-def immZExt6Ptr : ImmLeaf<iPTR, [{return isUInt<6>(Imm);}]>;
// Operands
-def uimm4_ptr : Operand<iPTR> {
- let PrintMethod = "printUnsignedImm8";
-}
-
-def uimm6_ptr : Operand<iPTR> {
- let PrintMethod = "printUnsignedImm8";
-}
-
-def simm5 : Operand<i32>;
-
-def vsplat_uimm1 : Operand<vAny> {
- let PrintMethod = "printUnsignedImm8";
-}
-
-def vsplat_uimm2 : Operand<vAny> {
- let PrintMethod = "printUnsignedImm8";
-}
-
-def vsplat_uimm3 : Operand<vAny> {
- let PrintMethod = "printUnsignedImm8";
-}
-
-def vsplat_uimm4 : Operand<vAny> {
- let PrintMethod = "printUnsignedImm8";
-}
-
-def vsplat_uimm5 : Operand<vAny> {
- let PrintMethod = "printUnsignedImm8";
-}
-
-def vsplat_uimm6 : Operand<vAny> {
- let PrintMethod = "printUnsignedImm8";
-}
-
-def vsplat_uimm8 : Operand<vAny> {
- let PrintMethod = "printUnsignedImm8";
-}
-
-def vsplat_simm5 : Operand<vAny>;
-
-def vsplat_simm10 : Operand<vAny>;
-
def immZExt2Lsa : ImmLeaf<i32, [{return isUInt<2>(Imm - 1);}]>;
// Pattern fragments
@@ -336,15 +294,33 @@ def vsplat_uimm_inv_pow2 : ComplexPattern<vAny, 1, "selectVSplatUimmInvPow2",
// Any build_vector that is a constant splat with only a consecutive sequence
// of left-most bits set.
-def vsplat_maskl_bits : SplatComplexPattern<vsplat_uimm8, vAny, 1,
- "selectVSplatMaskL",
- [build_vector, bitconvert]>;
+def vsplat_maskl_bits_uimm3
+ : SplatComplexPattern<vsplat_uimm3, vAny, 1, "selectVSplatMaskL",
+ [build_vector, bitconvert]>;
+def vsplat_maskl_bits_uimm4
+ : SplatComplexPattern<vsplat_uimm4, vAny, 1, "selectVSplatMaskL",
+ [build_vector, bitconvert]>;
+def vsplat_maskl_bits_uimm5
+ : SplatComplexPattern<vsplat_uimm5, vAny, 1, "selectVSplatMaskL",
+ [build_vector, bitconvert]>;
+def vsplat_maskl_bits_uimm6
+ : SplatComplexPattern<vsplat_uimm6, vAny, 1, "selectVSplatMaskL",
+ [build_vector, bitconvert]>;
// Any build_vector that is a constant splat with only a consecutive sequence
// of right-most bits set.
-def vsplat_maskr_bits : SplatComplexPattern<vsplat_uimm8, vAny, 1,
- "selectVSplatMaskR",
- [build_vector, bitconvert]>;
+def vsplat_maskr_bits_uimm3
+ : SplatComplexPattern<vsplat_uimm3, vAny, 1, "selectVSplatMaskR",
+ [build_vector, bitconvert]>;
+def vsplat_maskr_bits_uimm4
+ : SplatComplexPattern<vsplat_uimm4, vAny, 1, "selectVSplatMaskR",
+ [build_vector, bitconvert]>;
+def vsplat_maskr_bits_uimm5
+ : SplatComplexPattern<vsplat_uimm5, vAny, 1, "selectVSplatMaskR",
+ [build_vector, bitconvert]>;
+def vsplat_maskr_bits_uimm6
+ : SplatComplexPattern<vsplat_uimm6, vAny, 1, "selectVSplatMaskR",
+ [build_vector, bitconvert]>;
// Any build_vector that is a constant splat with a value that equals 1
// FIXME: These should be a ComplexPattern but we can't use them because the
@@ -1185,11 +1161,11 @@ class MSA_BIT_X_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
}
class MSA_BIT_BINSXI_DESC_BASE<string instr_asm, ValueType Ty,
- ComplexPattern Mask, RegisterOperand ROWD,
+ SplatComplexPattern Mask, RegisterOperand ROWD,
RegisterOperand ROWS = ROWD,
InstrItinClass itin = NoItinerary> {
dag OutOperandList = (outs ROWD:$wd);
- dag InOperandList = (ins ROWD:$wd_in, ROWS:$ws, vsplat_uimm8:$m);
+ dag InOperandList = (ins ROWD:$wd_in, ROWS:$ws, Mask.OpClass:$m);
string AsmString = !strconcat(instr_asm, "\t$wd, $ws, $m");
// Note that binsxi and vselect treat the condition operand the opposite
// way to each other.
@@ -1202,16 +1178,16 @@ class MSA_BIT_BINSXI_DESC_BASE<string instr_asm, ValueType Ty,
}
class MSA_BIT_BINSLI_DESC_BASE<string instr_asm, ValueType Ty,
- RegisterOperand ROWD,
+ SplatComplexPattern ImmOp, RegisterOperand ROWD,
RegisterOperand ROWS = ROWD,
InstrItinClass itin = NoItinerary> :
- MSA_BIT_BINSXI_DESC_BASE<instr_asm, Ty, vsplat_maskl_bits, ROWD, ROWS, itin>;
+ MSA_BIT_BINSXI_DESC_BASE<instr_asm, Ty, ImmOp, ROWD, ROWS, itin>;
class MSA_BIT_BINSRI_DESC_BASE<string instr_asm, ValueType Ty,
- RegisterOperand ROWD,
+ SplatComplexPattern ImmOp, RegisterOperand ROWD,
RegisterOperand ROWS = ROWD,
InstrItinClass itin = NoItinerary> :
- MSA_BIT_BINSXI_DESC_BASE<instr_asm, Ty, vsplat_maskr_bits, ROWD, ROWS, itin>;
+ MSA_BIT_BINSXI_DESC_BASE<instr_asm, Ty, ImmOp, ROWD, ROWS, itin>;
class MSA_BIT_SPLAT_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
SplatComplexPattern SplatImm,
@@ -1225,13 +1201,13 @@ class MSA_BIT_SPLAT_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
}
class MSA_COPY_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
- ValueType VecTy, RegisterOperand ROD,
- RegisterOperand ROWS,
+ ValueType VecTy, Operand ImmOp, ImmLeaf Imm,
+ RegisterOperand ROD, RegisterOperand ROWS,
InstrItinClass itin = NoItinerary> {
dag OutOperandList = (outs ROD:$rd);
- dag InOperandList = (ins ROWS:$ws, uimm4_ptr:$n);
+ dag InOperandList = (ins ROWS:$ws, ImmOp:$n);
string AsmString = !strconcat(instr_asm, "\t$rd, $ws[$n]");
- list<dag> Pattern = [(set ROD:$rd, (OpNode (VecTy ROWS:$ws), immZExt4Ptr:$n))];
+ list<dag> Pattern = [(set ROD:$rd, (OpNode (VecTy ROWS:$ws), Imm:$n))];
InstrItinClass Itinerary = itin;
}
@@ -1249,9 +1225,10 @@ class MSA_ELM_SLD_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
}
class MSA_COPY_PSEUDO_BASE<SDPatternOperator OpNode, ValueType VecTy,
- RegisterClass RCD, RegisterClass RCWS> :
- MSAPseudo<(outs RCD:$wd), (ins RCWS:$ws, uimm4_ptr:$n),
- [(set RCD:$wd, (OpNode (VecTy RCWS:$ws), immZExt4Ptr:$n))]> {
+ Operand ImmOp, ImmLeaf Imm, RegisterClass RCD,
+ RegisterClass RCWS> :
+ MSAPseudo<(outs RCD:$wd), (ins RCWS:$ws, ImmOp:$n),
+ [(set RCD:$wd, (OpNode (VecTy RCWS:$ws), Imm:$n))]> {
bit usesCustomInserter = 1;
}
@@ -1433,23 +1410,22 @@ class MSA_CBRANCH_DESC_BASE<string instr_asm, RegisterOperand ROWD> {
}
class MSA_INSERT_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
- RegisterOperand ROWD, RegisterOperand ROS,
+ Operand ImmOp, ImmLeaf Imm, RegisterOperand ROWD,
+ RegisterOperand ROS,
InstrItinClass itin = NoItinerary> {
dag OutOperandList = (outs ROWD:$wd);
- dag InOperandList = (ins ROWD:$wd_in, ROS:$rs, uimm6_ptr:$n);
+ dag InOperandList = (ins ROWD:$wd_in, ROS:$rs, ImmOp:$n);
string AsmString = !strconcat(instr_asm, "\t$wd[$n], $rs");
- list<dag> Pattern = [(set ROWD:$wd, (OpNode ROWD:$wd_in,
- ROS:$rs,
- immZExt6Ptr:$n))];
+ list<dag> Pattern = [(set ROWD:$wd, (OpNode ROWD:$wd_in, ROS:$rs, Imm:$n))];
InstrItinClass Itinerary = itin;
string Constraints = "$wd = $wd_in";
}
class MSA_INSERT_PSEUDO_BASE<SDPatternOperator OpNode, ValueType Ty,
- RegisterOperand ROWD, RegisterOperand ROFS> :
- MSAPseudo<(outs ROWD:$wd), (ins ROWD:$wd_in, uimm6_ptr:$n, ROFS:$fs),
- [(set ROWD:$wd, (OpNode (Ty ROWD:$wd_in), ROFS:$fs,
- immZExt6Ptr:$n))]> {
+ Operand ImmOp, ImmLeaf Imm, RegisterOperand ROWD,
+ RegisterOperand ROFS> :
+ MSAPseudo<(outs ROWD:$wd), (ins ROWD:$wd_in, ImmOp:$n, ROFS:$fs),
+ [(set ROWD:$wd, (OpNode (Ty ROWD:$wd_in), ROFS:$fs, Imm:$n))]> {
bit usesCustomInserter = 1;
string Constraints = "$wd = $wd_in";
}
@@ -1643,10 +1619,10 @@ class BINSL_W_DESC : MSA_3R_BINSX_DESC_BASE<"binsl.w", int_mips_binsl_w,
class BINSL_D_DESC : MSA_3R_BINSX_DESC_BASE<"binsl.d", int_mips_binsl_d,
MSA128DOpnd>;
-class BINSLI_B_DESC : MSA_BIT_BINSLI_DESC_BASE<"binsli.b", v16i8, MSA128BOpnd>;
-class BINSLI_H_DESC : MSA_BIT_BINSLI_DESC_BASE<"binsli.h", v8i16, MSA128HOpnd>;
-class BINSLI_W_DESC : MSA_BIT_BINSLI_DESC_BASE<"binsli.w", v4i32, MSA128WOpnd>;
-class BINSLI_D_DESC : MSA_BIT_BINSLI_DESC_BASE<"binsli.d", v2i64, MSA128DOpnd>;
+class BINSLI_B_DESC : MSA_BIT_BINSLI_DESC_BASE<"binsli.b", v16i8, vsplat_maskl_bits_uimm3, MSA128BOpnd>;
+class BINSLI_H_DESC : MSA_BIT_BINSLI_DESC_BASE<"binsli.h", v8i16, vsplat_maskl_bits_uimm4, MSA128HOpnd>;
+class BINSLI_W_DESC : MSA_BIT_BINSLI_DESC_BASE<"binsli.w", v4i32, vsplat_maskl_bits_uimm5, MSA128WOpnd>;
+class BINSLI_D_DESC : MSA_BIT_BINSLI_DESC_BASE<"binsli.d", v2i64, vsplat_maskl_bits_uimm6, MSA128DOpnd>;
class BINSR_B_DESC : MSA_3R_BINSX_DESC_BASE<"binsr.b", int_mips_binsr_b,
MSA128BOpnd>;
@@ -1657,10 +1633,18 @@ class BINSR_W_DESC : MSA_3R_BINSX_DESC_BASE<"binsr.w", int_mips_binsr_w,
class BINSR_D_DESC : MSA_3R_BINSX_DESC_BASE<"binsr.d", int_mips_binsr_d,
MSA128DOpnd>;
-class BINSRI_B_DESC : MSA_BIT_BINSRI_DESC_BASE<"binsri.b", v16i8, MSA128BOpnd>;
-class BINSRI_H_DESC : MSA_BIT_BINSRI_DESC_BASE<"binsri.h", v8i16, MSA128HOpnd>;
-class BINSRI_W_DESC : MSA_BIT_BINSRI_DESC_BASE<"binsri.w", v4i32, MSA128WOpnd>;
-class BINSRI_D_DESC : MSA_BIT_BINSRI_DESC_BASE<"binsri.d", v2i64, MSA128DOpnd>;
+class BINSRI_B_DESC
+ : MSA_BIT_BINSRI_DESC_BASE<"binsri.b", v16i8, vsplat_maskr_bits_uimm3,
+ MSA128BOpnd>;
+class BINSRI_H_DESC
+ : MSA_BIT_BINSRI_DESC_BASE<"binsri.h", v8i16, vsplat_maskr_bits_uimm4,
+ MSA128HOpnd>;
+class BINSRI_W_DESC
+ : MSA_BIT_BINSRI_DESC_BASE<"binsri.w", v4i32, vsplat_maskr_bits_uimm5,
+ MSA128WOpnd>;
+class BINSRI_D_DESC
+ : MSA_BIT_BINSRI_DESC_BASE<"binsri.d", v2i64, vsplat_maskr_bits_uimm6,
+ MSA128DOpnd>;
class BMNZ_V_DESC {
dag OutOperandList = (outs MSA128BOpnd:$wd);
@@ -1867,24 +1851,33 @@ class CLTI_U_D_DESC : MSA_I5_DESC_BASE<"clti_u.d", vsetult_v2i64,
vsplati64_uimm5, MSA128DOpnd>;
class COPY_S_B_DESC : MSA_COPY_DESC_BASE<"copy_s.b", vextract_sext_i8, v16i8,
- GPR32Opnd, MSA128BOpnd>;
+ uimm4_ptr, immZExt4Ptr, GPR32Opnd,
+ MSA128BOpnd>;
class COPY_S_H_DESC : MSA_COPY_DESC_BASE<"copy_s.h", vextract_sext_i16, v8i16,
- GPR32Opnd, MSA128HOpnd>;
+ uimm3_ptr, immZExt3Ptr, GPR32Opnd,
+ MSA128HOpnd>;
class COPY_S_W_DESC : MSA_COPY_DESC_BASE<"copy_s.w", vextract_sext_i32, v4i32,
- GPR32Opnd, MSA128WOpnd>;
+ uimm2_ptr, immZExt2Ptr, GPR32Opnd,
+ MSA128WOpnd>;
class COPY_S_D_DESC : MSA_COPY_DESC_BASE<"copy_s.d", vextract_sext_i64, v2i64,
- GPR64Opnd, MSA128DOpnd>;
+ uimm1_ptr, immZExt1Ptr, GPR64Opnd,
+ MSA128DOpnd>;
class COPY_U_B_DESC : MSA_COPY_DESC_BASE<"copy_u.b", vextract_zext_i8, v16i8,
- GPR32Opnd, MSA128BOpnd>;
+ uimm4_ptr, immZExt4Ptr, GPR32Opnd,
+ MSA128BOpnd>;
class COPY_U_H_DESC : MSA_COPY_DESC_BASE<"copy_u.h", vextract_zext_i16, v8i16,
- GPR32Opnd, MSA128HOpnd>;
+ uimm3_ptr, immZExt3Ptr, GPR32Opnd,
+ MSA128HOpnd>;
class COPY_U_W_DESC : MSA_COPY_DESC_BASE<"copy_u.w", vextract_zext_i32, v4i32,
- GPR32Opnd, MSA128WOpnd>;
+ uimm2_ptr, immZExt2Ptr, GPR32Opnd,
+ MSA128WOpnd>;
-class COPY_FW_PSEUDO_DESC : MSA_COPY_PSEUDO_BASE<vector_extract, v4f32, FGR32,
+class COPY_FW_PSEUDO_DESC : MSA_COPY_PSEUDO_BASE<vector_extract, v4f32,
+ uimm2_ptr, immZExt2Ptr, FGR32,
MSA128W>;
-class COPY_FD_PSEUDO_DESC : MSA_COPY_PSEUDO_BASE<vector_extract, v2f64, FGR64,
+class COPY_FD_PSEUDO_DESC : MSA_COPY_PSEUDO_BASE<vector_extract, v2f64,
+ uimm1_ptr, immZExt1Ptr, FGR64,
MSA128D>;
class CTCMSA_DESC {
@@ -2249,14 +2242,14 @@ class ILVR_H_DESC : MSA_3R_DESC_BASE<"ilvr.h", MipsILVR, MSA128HOpnd>;
class ILVR_W_DESC : MSA_3R_DESC_BASE<"ilvr.w", MipsILVR, MSA128WOpnd>;
class ILVR_D_DESC : MSA_3R_DESC_BASE<"ilvr.d", MipsILVR, MSA128DOpnd>;
-class INSERT_B_DESC : MSA_INSERT_DESC_BASE<"insert.b", vinsert_v16i8,
- MSA128BOpnd, GPR32Opnd>;
-class INSERT_H_DESC : MSA_INSERT_DESC_BASE<"insert.h", vinsert_v8i16,
- MSA128HOpnd, GPR32Opnd>;
-class INSERT_W_DESC : MSA_INSERT_DESC_BASE<"insert.w", vinsert_v4i32,
- MSA128WOpnd, GPR32Opnd>;
-class INSERT_D_DESC : MSA_INSERT_DESC_BASE<"insert.d", vinsert_v2i64,
- MSA128DOpnd, GPR64Opnd>;
+class INSERT_B_DESC : MSA_INSERT_DESC_BASE<"insert.b", vinsert_v16i8, uimm4,
+ immZExt4Ptr, MSA128BOpnd, GPR32Opnd>;
+class INSERT_H_DESC : MSA_INSERT_DESC_BASE<"insert.h", vinsert_v8i16, uimm3,
+ immZExt3Ptr, MSA128HOpnd, GPR32Opnd>;
+class INSERT_W_DESC : MSA_INSERT_DESC_BASE<"insert.w", vinsert_v4i32, uimm2,
+ immZExt2Ptr, MSA128WOpnd, GPR32Opnd>;
+class INSERT_D_DESC : MSA_INSERT_DESC_BASE<"insert.d", vinsert_v2i64, uimm1,
+ immZExt1Ptr, MSA128DOpnd, GPR64Opnd>;
class INSERT_B_VIDX_PSEUDO_DESC :
MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v16i8, MSA128BOpnd, GPR32Opnd, GPR32Opnd>;
@@ -2268,8 +2261,10 @@ class INSERT_D_VIDX_PSEUDO_DESC :
MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v2i64, MSA128DOpnd, GPR64Opnd, GPR32Opnd>;
class INSERT_FW_PSEUDO_DESC : MSA_INSERT_PSEUDO_BASE<vector_insert, v4f32,
+ uimm2, immZExt2Ptr,
MSA128WOpnd, FGR32Opnd>;
class INSERT_FD_PSEUDO_DESC : MSA_INSERT_PSEUDO_BASE<vector_insert, v2f64,
+ uimm1, immZExt1Ptr,
MSA128DOpnd, FGR64Opnd>;
class INSERT_FW_VIDX_PSEUDO_DESC :
@@ -2302,7 +2297,7 @@ class INSVE_D_DESC : MSA_INSVE_DESC_BASE<"insve.d", insve_v2i64, uimm1, immZExt1
class LD_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
ValueType TyNode, RegisterOperand ROWD,
- Operand MemOpnd = mem_msa, ComplexPattern Addr = addrimm10,
+ Operand MemOpnd, ComplexPattern Addr = addrimm10,
InstrItinClass itin = NoItinerary> {
dag OutOperandList = (outs ROWD:$wd);
dag InOperandList = (ins MemOpnd:$addr);
@@ -2312,10 +2307,10 @@ class LD_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
string DecoderMethod = "DecodeMSA128Mem";
}
-class LD_B_DESC : LD_DESC_BASE<"ld.b", load, v16i8, MSA128BOpnd>;
-class LD_H_DESC : LD_DESC_BASE<"ld.h", load, v8i16, MSA128HOpnd>;
-class LD_W_DESC : LD_DESC_BASE<"ld.w", load, v4i32, MSA128WOpnd>;
-class LD_D_DESC : LD_DESC_BASE<"ld.d", load, v2i64, MSA128DOpnd>;
+class LD_B_DESC : LD_DESC_BASE<"ld.b", load, v16i8, MSA128BOpnd, mem_simm10>;
+class LD_H_DESC : LD_DESC_BASE<"ld.h", load, v8i16, MSA128HOpnd, mem_simm10_lsl1>;
+class LD_W_DESC : LD_DESC_BASE<"ld.w", load, v4i32, MSA128WOpnd, mem_simm10_lsl2>;
+class LD_D_DESC : LD_DESC_BASE<"ld.d", load, v2i64, MSA128DOpnd, mem_simm10_lsl3>;
class LDI_B_DESC : MSA_I10_LDI_DESC_BASE<"ldi.b", MSA128BOpnd>;
class LDI_H_DESC : MSA_I10_LDI_DESC_BASE<"ldi.h", MSA128HOpnd>;
@@ -2323,19 +2318,18 @@ class LDI_W_DESC : MSA_I10_LDI_DESC_BASE<"ldi.w", MSA128WOpnd>;
class LDI_D_DESC : MSA_I10_LDI_DESC_BASE<"ldi.d", MSA128DOpnd>;
class LSA_DESC_BASE<string instr_asm, RegisterOperand RORD,
- RegisterOperand RORS = RORD, RegisterOperand RORT = RORD,
- InstrItinClass itin = NoItinerary > {
+ InstrItinClass itin = NoItinerary> {
dag OutOperandList = (outs RORD:$rd);
- dag InOperandList = (ins RORS:$rs, RORT:$rt, uimm2_plus1:$sa);
+ dag InOperandList = (ins RORD:$rs, RORD:$rt, uimm2_plus1:$sa);
string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt, $sa");
- list<dag> Pattern = [(set RORD:$rd, (add RORT:$rt,
- (shl RORS:$rs,
+ list<dag> Pattern = [(set RORD:$rd, (add RORD:$rt,
+ (shl RORD:$rs,
immZExt2Lsa:$sa)))];
InstrItinClass Itinerary = itin;
}
-class LSA_DESC : LSA_DESC_BASE<"lsa", GPR32Opnd>;
-class DLSA_DESC : LSA_DESC_BASE<"dlsa", GPR64Opnd>;
+class LSA_DESC : LSA_DESC_BASE<"lsa", GPR32Opnd, II_LSA>;
+class DLSA_DESC : LSA_DESC_BASE<"dlsa", GPR64Opnd, II_DLSA>;
class MADD_Q_H_DESC : MSA_3RF_4RF_DESC_BASE<"madd_q.h", int_mips_madd_q_h,
MSA128HOpnd>;
@@ -2636,7 +2630,7 @@ class SRLRI_D_DESC : MSA_BIT_X_DESC_BASE<"srlri.d", int_mips_srlri_d, uimm6,
class ST_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
ValueType TyNode, RegisterOperand ROWD,
- Operand MemOpnd = mem_msa, ComplexPattern Addr = addrimm10,
+ Operand MemOpnd, ComplexPattern Addr = addrimm10,
InstrItinClass itin = NoItinerary> {
dag OutOperandList = (outs);
dag InOperandList = (ins ROWD:$wd, MemOpnd:$addr);
@@ -2646,10 +2640,10 @@ class ST_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
string DecoderMethod = "DecodeMSA128Mem";
}
-class ST_B_DESC : ST_DESC_BASE<"st.b", store, v16i8, MSA128BOpnd>;
-class ST_H_DESC : ST_DESC_BASE<"st.h", store, v8i16, MSA128HOpnd>;
-class ST_W_DESC : ST_DESC_BASE<"st.w", store, v4i32, MSA128WOpnd>;
-class ST_D_DESC : ST_DESC_BASE<"st.d", store, v2i64, MSA128DOpnd>;
+class ST_B_DESC : ST_DESC_BASE<"st.b", store, v16i8, MSA128BOpnd, mem_simm10>;
+class ST_H_DESC : ST_DESC_BASE<"st.h", store, v8i16, MSA128HOpnd, mem_simm10_lsl1>;
+class ST_W_DESC : ST_DESC_BASE<"st.w", store, v4i32, MSA128WOpnd, mem_simm10_lsl2>;
+class ST_D_DESC : ST_DESC_BASE<"st.d", store, v2i64, MSA128DOpnd, mem_simm10_lsl3>;
class SUBS_S_B_DESC : MSA_3R_DESC_BASE<"subs_s.b", int_mips_subs_s_b,
MSA128BOpnd>;
diff --git a/lib/Target/Mips/MipsMachineFunction.cpp b/lib/Target/Mips/MipsMachineFunction.cpp
index c7d2738af1d4a..f81e64e06f433 100644
--- a/lib/Target/Mips/MipsMachineFunction.cpp
+++ b/lib/Target/Mips/MipsMachineFunction.cpp
@@ -42,7 +42,9 @@ unsigned MipsFunctionInfo::getGlobalBaseReg() {
STI.inMips16Mode()
? &Mips::CPU16RegsRegClass
: STI.inMicroMipsMode()
- ? &Mips::GPRMM16RegClass
+ ? STI.hasMips64()
+ ? &Mips::GPRMM16_64RegClass
+ : &Mips::GPRMM16RegClass
: static_cast<const MipsTargetMachine &>(MF.getTarget())
.getABI()
.IsN64()
@@ -51,18 +53,6 @@ unsigned MipsFunctionInfo::getGlobalBaseReg() {
return GlobalBaseReg = MF.getRegInfo().createVirtualRegister(RC);
}
-bool MipsFunctionInfo::mips16SPAliasRegSet() const {
- return Mips16SPAliasReg;
-}
-unsigned MipsFunctionInfo::getMips16SPAliasReg() {
- // Return if it has already been initialized.
- if (Mips16SPAliasReg)
- return Mips16SPAliasReg;
-
- const TargetRegisterClass *RC = &Mips::CPU16RegsRegClass;
- return Mips16SPAliasReg = MF.getRegInfo().createVirtualRegister(RC);
-}
-
void MipsFunctionInfo::createEhDataRegsFI() {
for (int I = 0; I < 4; ++I) {
const TargetRegisterClass *RC =
diff --git a/lib/Target/Mips/MipsMachineFunction.h b/lib/Target/Mips/MipsMachineFunction.h
index a2f6ee03604fc..c9e5fddc19325 100644
--- a/lib/Target/Mips/MipsMachineFunction.h
+++ b/lib/Target/Mips/MipsMachineFunction.h
@@ -19,12 +19,9 @@
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineMemOperand.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
-#include "llvm/IR/ValueMap.h"
#include "llvm/Target/TargetFrameLowering.h"
#include "llvm/Target/TargetMachine.h"
#include <map>
-#include <string>
-#include <utility>
namespace llvm {
@@ -33,8 +30,8 @@ namespace llvm {
class MipsFunctionInfo : public MachineFunctionInfo {
public:
MipsFunctionInfo(MachineFunction &MF)
- : MF(MF), SRetReturnReg(0), GlobalBaseReg(0), Mips16SPAliasReg(0),
- VarArgsFrameIndex(0), CallsEhReturn(false), IsISR(false), SaveS2(false),
+ : MF(MF), SRetReturnReg(0), GlobalBaseReg(0), VarArgsFrameIndex(0),
+ CallsEhReturn(false), IsISR(false), SaveS2(false),
MoveF64ViaSpillFI(-1) {}
~MipsFunctionInfo();
@@ -45,9 +42,6 @@ public:
bool globalBaseRegSet() const;
unsigned getGlobalBaseReg();
- bool mips16SPAliasRegSet() const;
- unsigned getMips16SPAliasReg();
-
int getVarArgsFrameIndex() const { return VarArgsFrameIndex; }
void setVarArgsFrameIndex(int Index) { VarArgsFrameIndex = Index; }
@@ -104,11 +98,6 @@ private:
/// relocation models.
unsigned GlobalBaseReg;
- /// Mips16SPAliasReg - keeps track of the virtual register initialized for
- /// use as an alias for SP for use in load/store of halfword/byte from/to
- /// the stack
- unsigned Mips16SPAliasReg;
-
/// VarArgsFrameIndex - FrameIndex for start of varargs area.
int VarArgsFrameIndex;
diff --git a/lib/Target/Mips/MipsOs16.cpp b/lib/Target/Mips/MipsOs16.cpp
index b6cd79193cfcd..8136907de4d7e 100644
--- a/lib/Target/Mips/MipsOs16.cpp
+++ b/lib/Target/Mips/MipsOs16.cpp
@@ -111,22 +111,27 @@ static bool needsFP(Function &F) {
bool MipsOs16::runOnModule(Module &M) {
bool usingMask = Mips32FunctionMask.length() > 0;
bool doneUsingMask = false; // this will make it stop repeating
+
DEBUG(dbgs() << "Run on Module MipsOs16 \n" << Mips32FunctionMask << "\n");
if (usingMask)
DEBUG(dbgs() << "using mask \n" << Mips32FunctionMask << "\n");
+
unsigned int functionIndex = 0;
bool modified = false;
- for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
- if (F->isDeclaration()) continue;
- DEBUG(dbgs() << "Working on " << F->getName() << "\n");
+
+ for (auto &F : M) {
+ if (F.isDeclaration())
+ continue;
+
+ DEBUG(dbgs() << "Working on " << F.getName() << "\n");
if (usingMask) {
if (!doneUsingMask) {
if (functionIndex == Mips32FunctionMask.length())
functionIndex = 0;
switch (Mips32FunctionMask[functionIndex]) {
case '1':
- DEBUG(dbgs() << "mask forced mips32: " << F->getName() << "\n");
- F->addFnAttr("nomips16");
+ DEBUG(dbgs() << "mask forced mips32: " << F.getName() << "\n");
+ F.addFnAttr("nomips16");
break;
case '.':
doneUsingMask = true;
@@ -138,16 +143,17 @@ bool MipsOs16::runOnModule(Module &M) {
}
}
else {
- if (needsFP(*F)) {
- DEBUG(dbgs() << "os16 forced mips32: " << F->getName() << "\n");
- F->addFnAttr("nomips16");
+ if (needsFP(F)) {
+ DEBUG(dbgs() << "os16 forced mips32: " << F.getName() << "\n");
+ F.addFnAttr("nomips16");
}
else {
- DEBUG(dbgs() << "os16 forced mips16: " << F->getName() << "\n");
- F->addFnAttr("mips16");
+ DEBUG(dbgs() << "os16 forced mips16: " << F.getName() << "\n");
+ F.addFnAttr("mips16");
}
}
}
+
return modified;
}
diff --git a/lib/Target/Mips/MipsRegisterInfo.cpp b/lib/Target/Mips/MipsRegisterInfo.cpp
index 28e5a425849fa..860cf9cfd138c 100644
--- a/lib/Target/Mips/MipsRegisterInfo.cpp
+++ b/lib/Target/Mips/MipsRegisterInfo.cpp
@@ -13,7 +13,6 @@
#include "MipsRegisterInfo.h"
#include "Mips.h"
-#include "MipsAnalyzeImmediate.h"
#include "MipsInstrInfo.h"
#include "MipsMachineFunction.h"
#include "MipsSubtarget.h"
@@ -21,14 +20,13 @@
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
-#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Type.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
@@ -52,7 +50,21 @@ const TargetRegisterClass *
MipsRegisterInfo::getPointerRegClass(const MachineFunction &MF,
unsigned Kind) const {
MipsABIInfo ABI = MF.getSubtarget<MipsSubtarget>().getABI();
- return ABI.ArePtrs64bit() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass;
+ MipsPtrClass PtrClassKind = static_cast<MipsPtrClass>(Kind);
+
+ switch (PtrClassKind) {
+ case MipsPtrClass::Default:
+ return ABI.ArePtrs64bit() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass;
+ case MipsPtrClass::GPR16MM:
+ return ABI.ArePtrs64bit() ? &Mips::GPRMM16_64RegClass
+ : &Mips::GPRMM16RegClass;
+ case MipsPtrClass::StackPointer:
+ return ABI.ArePtrs64bit() ? &Mips::SP64RegClass : &Mips::SP32RegClass;
+ case MipsPtrClass::GlobalPointer:
+ return ABI.ArePtrs64bit() ? &Mips::GP64RegClass : &Mips::GP32RegClass;
+ }
+
+ llvm_unreachable("Unknown pointer kind");
}
unsigned
diff --git a/lib/Target/Mips/MipsRegisterInfo.h b/lib/Target/Mips/MipsRegisterInfo.h
index 5de68a21b73ea..32f835e83108a 100644
--- a/lib/Target/Mips/MipsRegisterInfo.h
+++ b/lib/Target/Mips/MipsRegisterInfo.h
@@ -23,18 +23,23 @@
namespace llvm {
class MipsRegisterInfo : public MipsGenRegisterInfo {
public:
- MipsRegisterInfo();
+ enum class MipsPtrClass {
+ /// The default register class for integer values.
+ Default = 0,
+ /// The subset of registers permitted in certain microMIPS instructions
+ /// such as lw16.
+ GPR16MM = 1,
+ /// The stack pointer only.
+ StackPointer = 2,
+ /// The global pointer only.
+ GlobalPointer = 3,
+ };
- /// getRegisterNumbering - Given the enum value for some register, e.g.
- /// Mips::RA, return the number that it corresponds to (e.g. 31).
- static unsigned getRegisterNumbering(unsigned RegEnum);
+ MipsRegisterInfo();
/// Get PIC indirect call register
static unsigned getPICCallReg();
- /// Adjust the Mips stack frame.
- void adjustMipsStackFrame(MachineFunction &MF) const;
-
/// Code Generation virtual methods...
const TargetRegisterClass *getPointerRegClass(const MachineFunction &MF,
unsigned Kind) const override;
@@ -57,9 +62,6 @@ public:
int SPAdj, unsigned FIOperandNum,
RegScavenger *RS = nullptr) const override;
- void processFunctionBeforeFrameFinalized(MachineFunction &MF,
- RegScavenger *RS = nullptr) const;
-
// Stack realignment queries.
bool canRealignStack(const MachineFunction &MF) const override;
diff --git a/lib/Target/Mips/MipsRegisterInfo.td b/lib/Target/Mips/MipsRegisterInfo.td
index 02bcac5a3ddb3..cfce7c8e65337 100644
--- a/lib/Target/Mips/MipsRegisterInfo.td
+++ b/lib/Target/Mips/MipsRegisterInfo.td
@@ -330,6 +330,12 @@ def GPR64 : RegisterClass<"Mips", [i64], 64, (add
// Reserved
K0_64, K1_64, GP_64, SP_64, FP_64, RA_64)>;
+def GPRMM16_64 : RegisterClass<"Mips", [i64], 64, (add
+ // Callee save
+ S0_64, S1_64,
+ // Return Values and Arguments
+ V0_64, V1_64, A0_64, A1_64, A2_64, A3_64)>;
+
def CPU16Regs : RegisterClass<"Mips", [i32], 32, (add
// Return Values and Arguments
V0, V1, A0, A1, A2, A3,
@@ -447,6 +453,13 @@ def COP2 : RegisterClass<"Mips", [i32], 32, (sequence "COP2%u", 0, 31)>,
def COP3 : RegisterClass<"Mips", [i32], 32, (sequence "COP3%u", 0, 31)>,
Unallocatable;
+// Stack pointer and global pointer classes for instructions that are limited
+// to a single register such as lwgp/lwsp in microMIPS.
+def SP32 : RegisterClass<"Mips", [i32], 32, (add SP)>, Unallocatable;
+def SP64 : RegisterClass<"Mips", [i64], 64, (add SP_64)>, Unallocatable;
+def GP32 : RegisterClass<"Mips", [i32], 32, (add GP)>, Unallocatable;
+def GP64 : RegisterClass<"Mips", [i64], 64, (add GP_64)>, Unallocatable;
+
// Octeon multiplier and product registers
def OCTEON_MPL : RegisterClass<"Mips", [i64], 64, (add MPL0, MPL1, MPL2)>,
Unallocatable;
diff --git a/lib/Target/Mips/MipsSEFrameLowering.cpp b/lib/Target/Mips/MipsSEFrameLowering.cpp
index a4abd62ee607f..a7ddd7752736b 100644
--- a/lib/Target/Mips/MipsSEFrameLowering.cpp
+++ b/lib/Target/Mips/MipsSEFrameLowering.cpp
@@ -13,7 +13,6 @@
#include "MipsSEFrameLowering.h"
#include "MCTargetDesc/MipsBaseInfo.h"
-#include "MipsAnalyzeImmediate.h"
#include "MipsMachineFunction.h"
#include "MipsSEInstrInfo.h"
#include "MipsSubtarget.h"
@@ -26,7 +25,6 @@
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetOptions.h"
using namespace llvm;
@@ -87,10 +85,10 @@ ExpandPseudo::ExpandPseudo(MachineFunction &MF_)
bool ExpandPseudo::expand() {
bool Expanded = false;
- for (MachineFunction::iterator BB = MF.begin(), BBEnd = MF.end();
- BB != BBEnd; ++BB)
- for (Iter I = BB->begin(), End = BB->end(); I != End;)
- Expanded |= expandInstr(*BB, I++);
+ for (auto &MBB : MF) {
+ for (Iter I = MBB.begin(), End = MBB.end(); I != End;)
+ Expanded |= expandInstr(MBB, I++);
+ }
return Expanded;
}
@@ -518,7 +516,7 @@ void MipsSEFrameLowering::emitPrologue(MachineFunction &MF,
unsigned VR = MF.getRegInfo().createVirtualRegister(RC);
assert(isInt<16>(MFI->getMaxAlignment()) &&
"Function's alignment size requirement is not supported.");
- int MaxAlign = - (signed) MFI->getMaxAlignment();
+ int MaxAlign = -(int)MFI->getMaxAlignment();
BuildMI(MBB, MBBI, dl, TII.get(ADDiu), VR).addReg(ZERO) .addImm(MaxAlign);
BuildMI(MBB, MBBI, dl, TII.get(AND), SP).addReg(SP).addReg(VR);
diff --git a/lib/Target/Mips/MipsSEISelDAGToDAG.cpp b/lib/Target/Mips/MipsSEISelDAGToDAG.cpp
index 6f001ea74b304..d9528da5a96de 100644
--- a/lib/Target/Mips/MipsSEISelDAGToDAG.cpp
+++ b/lib/Target/Mips/MipsSEISelDAGToDAG.cpp
@@ -47,7 +47,8 @@ void MipsSEDAGToDAGISel::addDSPCtrlRegOperands(bool IsDef, MachineInstr &MI,
MachineFunction &MF) {
MachineInstrBuilder MIB(MF, &MI);
unsigned Mask = MI.getOperand(1).getImm();
- unsigned Flag = IsDef ? RegState::ImplicitDefine : RegState::Implicit;
+ unsigned Flag =
+ IsDef ? RegState::ImplicitDefine : RegState::Implicit | RegState::Undef;
if (Mask & 1)
MIB.addReg(Mips::DSPPos, Flag);
@@ -162,7 +163,7 @@ void MipsSEDAGToDAGISel::initGlobalBaseReg(MachineFunction &MF) {
return;
}
- if (MF.getTarget().getRelocationModel() == Reloc::Static) {
+ if (!MF.getTarget().isPositionIndependent()) {
// Set global register to __gnu_local_gp.
//
// lui $v0, %hi(__gnu_local_gp)
@@ -220,21 +221,25 @@ void MipsSEDAGToDAGISel::processFunctionAfterISel(MachineFunction &MF) {
MachineRegisterInfo *MRI = &MF.getRegInfo();
- for (MachineFunction::iterator MFI = MF.begin(), MFE = MF.end(); MFI != MFE;
- ++MFI)
- for (MachineBasicBlock::iterator I = MFI->begin(); I != MFI->end(); ++I) {
- if (I->getOpcode() == Mips::RDDSP)
- addDSPCtrlRegOperands(false, *I, MF);
- else if (I->getOpcode() == Mips::WRDSP)
- addDSPCtrlRegOperands(true, *I, MF);
- else
- replaceUsesWithZeroReg(MRI, *I);
+ for (auto &MBB: MF) {
+ for (auto &MI: MBB) {
+ switch (MI.getOpcode()) {
+ case Mips::RDDSP:
+ addDSPCtrlRegOperands(false, MI, MF);
+ break;
+ case Mips::WRDSP:
+ addDSPCtrlRegOperands(true, MI, MF);
+ break;
+ default:
+ replaceUsesWithZeroReg(MRI, MI);
+ }
}
+ }
}
-SDNode *MipsSEDAGToDAGISel::selectAddESubE(unsigned MOp, SDValue InFlag,
- SDValue CmpLHS, SDLoc DL,
- SDNode *Node) const {
+void MipsSEDAGToDAGISel::selectAddESubE(unsigned MOp, SDValue InFlag,
+ SDValue CmpLHS, const SDLoc &DL,
+ SDNode *Node) const {
unsigned Opc = InFlag.getOpcode(); (void)Opc;
assert(((Opc == ISD::ADDC || Opc == ISD::ADDE) ||
@@ -271,8 +276,7 @@ SDNode *MipsSEDAGToDAGISel::selectAddESubE(unsigned MOp, SDValue InFlag,
if (!C || C->getZExtValue())
AddCarry = CurDAG->getMachineNode(ADDuOp, DL, VT, SDValue(Carry, 0), RHS);
- return CurDAG->SelectNodeTo(Node, MOp, VT, MVT::Glue, LHS,
- SDValue(AddCarry, 0));
+ CurDAG->SelectNodeTo(Node, MOp, VT, MVT::Glue, LHS, SDValue(AddCarry, 0));
}
/// Match frameindex
@@ -327,7 +331,7 @@ bool MipsSEDAGToDAGISel::selectAddrRegImm(SDValue Addr, SDValue &Base,
return true;
}
- if (TM.getRelocationModel() != Reloc::PIC_) {
+ if (!TM.isPositionIndependent()) {
if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
Addr.getOpcode() == ISD::TargetGlobalAddress))
return false;
@@ -364,18 +368,6 @@ bool MipsSEDAGToDAGISel::selectAddrRegImm(SDValue Addr, SDValue &Base,
/// ComplexPattern used on MipsInstrInfo
/// Used on Mips Load/Store instructions
-bool MipsSEDAGToDAGISel::selectAddrRegReg(SDValue Addr, SDValue &Base,
- SDValue &Offset) const {
- // Operand is a result from an ADD.
- if (Addr.getOpcode() == ISD::ADD) {
- Base = Addr.getOperand(0);
- Offset = Addr.getOperand(1);
- return true;
- }
-
- return false;
-}
-
bool MipsSEDAGToDAGISel::selectAddrDefault(SDValue Addr, SDValue &Base,
SDValue &Offset) const {
Base = Addr;
@@ -411,6 +403,18 @@ bool MipsSEDAGToDAGISel::selectAddrRegImm10(SDValue Addr, SDValue &Base,
return false;
}
+/// Used on microMIPS LWC2, LDC2, SWC2 and SDC2 instructions (11-bit offset)
+bool MipsSEDAGToDAGISel::selectAddrRegImm11(SDValue Addr, SDValue &Base,
+ SDValue &Offset) const {
+ if (selectAddrFrameIndex(Addr, Base, Offset))
+ return true;
+
+ if (selectAddrFrameIndexOffset(Addr, Base, Offset, 11))
+ return true;
+
+ return false;
+}
+
/// Used on microMIPS Load/Store unaligned instructions (12-bit offset)
bool MipsSEDAGToDAGISel::selectAddrRegImm12(SDValue Addr, SDValue &Base,
SDValue &Offset) const {
@@ -434,12 +438,24 @@ bool MipsSEDAGToDAGISel::selectAddrRegImm16(SDValue Addr, SDValue &Base,
return false;
}
-bool MipsSEDAGToDAGISel::selectIntAddrMM(SDValue Addr, SDValue &Base,
+bool MipsSEDAGToDAGISel::selectIntAddr11MM(SDValue Addr, SDValue &Base,
+ SDValue &Offset) const {
+ return selectAddrRegImm11(Addr, Base, Offset) ||
+ selectAddrDefault(Addr, Base, Offset);
+}
+
+bool MipsSEDAGToDAGISel::selectIntAddr12MM(SDValue Addr, SDValue &Base,
SDValue &Offset) const {
return selectAddrRegImm12(Addr, Base, Offset) ||
selectAddrDefault(Addr, Base, Offset);
}
+bool MipsSEDAGToDAGISel::selectIntAddr16MM(SDValue Addr, SDValue &Base,
+ SDValue &Offset) const {
+ return selectAddrRegImm16(Addr, Base, Offset) ||
+ selectAddrDefault(Addr, Base, Offset);
+}
+
bool MipsSEDAGToDAGISel::selectIntAddrLSL2MM(SDValue Addr, SDValue &Base,
SDValue &Offset) const {
if (selectAddrFrameIndexOffset(Addr, Base, Offset, 7)) {
@@ -702,7 +718,7 @@ bool MipsSEDAGToDAGISel::selectVSplatUimmInvPow2(SDValue N,
return false;
}
-std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) {
+bool MipsSEDAGToDAGISel::trySelect(SDNode *Node) {
unsigned Opcode = Node->getOpcode();
SDLoc DL(Node);
@@ -710,16 +726,14 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) {
// Instruction Selection not handled by the auto-generated
// tablegen selection should be handled here.
///
- SDNode *Result;
-
switch(Opcode) {
default: break;
case ISD::SUBE: {
SDValue InFlag = Node->getOperand(2);
unsigned Opc = Subtarget->isGP64bit() ? Mips::DSUBu : Mips::SUBu;
- Result = selectAddESubE(Opc, InFlag, InFlag.getOperand(0), DL, Node);
- return std::make_pair(true, Result);
+ selectAddESubE(Opc, InFlag, InFlag.getOperand(0), DL, Node);
+ return true;
}
case ISD::ADDE: {
@@ -727,8 +741,8 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) {
break;
SDValue InFlag = Node->getOperand(2);
unsigned Opc = Subtarget->isGP64bit() ? Mips::DADDu : Mips::ADDu;
- Result = selectAddESubE(Opc, InFlag, InFlag.getValue(0), DL, Node);
- return std::make_pair(true, Result);
+ selectAddESubE(Opc, InFlag, InFlag.getValue(0), DL, Node);
+ return true;
}
case ISD::ConstantFP: {
@@ -737,20 +751,20 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) {
if (Subtarget->isGP64bit()) {
SDValue Zero = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL,
Mips::ZERO_64, MVT::i64);
- Result = CurDAG->getMachineNode(Mips::DMTC1, DL, MVT::f64, Zero);
+ ReplaceNode(Node,
+ CurDAG->getMachineNode(Mips::DMTC1, DL, MVT::f64, Zero));
} else if (Subtarget->isFP64bit()) {
SDValue Zero = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL,
Mips::ZERO, MVT::i32);
- Result = CurDAG->getMachineNode(Mips::BuildPairF64_64, DL, MVT::f64,
- Zero, Zero);
+ ReplaceNode(Node, CurDAG->getMachineNode(Mips::BuildPairF64_64, DL,
+ MVT::f64, Zero, Zero));
} else {
SDValue Zero = CurDAG->getCopyFromReg(CurDAG->getEntryNode(), DL,
Mips::ZERO, MVT::i32);
- Result = CurDAG->getMachineNode(Mips::BuildPairF64, DL, MVT::f64, Zero,
- Zero);
+ ReplaceNode(Node, CurDAG->getMachineNode(Mips::BuildPairF64, DL,
+ MVT::f64, Zero, Zero));
}
-
- return std::make_pair(true, Result);
+ return true;
}
break;
}
@@ -793,7 +807,8 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) {
SDValue(RegOpnd, 0), ImmOpnd);
}
- return std::make_pair(true, RegOpnd);
+ ReplaceNode(Node, RegOpnd);
+ return true;
}
case ISD::INTRINSIC_W_CHAIN: {
@@ -806,7 +821,8 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) {
SDValue RegIdx = Node->getOperand(2);
SDValue Reg = CurDAG->getCopyFromReg(ChainIn, DL,
getMSACtrlReg(RegIdx), MVT::i32);
- return std::make_pair(true, Reg.getNode());
+ ReplaceNode(Node, Reg.getNode());
+ return true;
}
}
break;
@@ -820,10 +836,10 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) {
case Intrinsic::mips_move_v:
// Like an assignment but will always produce a move.v even if
// unnecessary.
- return std::make_pair(true,
- CurDAG->getMachineNode(Mips::MOVE_V, DL,
- Node->getValueType(0),
- Node->getOperand(1)));
+ ReplaceNode(Node, CurDAG->getMachineNode(Mips::MOVE_V, DL,
+ Node->getValueType(0),
+ Node->getOperand(1)));
+ return true;
}
break;
}
@@ -839,7 +855,8 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) {
SDValue Value = Node->getOperand(3);
SDValue ChainOut = CurDAG->getCopyToReg(ChainIn, DL,
getMSACtrlReg(RegIdx), Value);
- return std::make_pair(true, ChainOut.getNode());
+ ReplaceNode(Node, ChainOut.getNode());
+ return true;
}
}
break;
@@ -864,8 +881,8 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) {
SDValue Chain = CurDAG->getCopyToReg(CurDAG->getEntryNode(), DL, DestReg,
SDValue(Rdhwr, 0));
SDValue ResNode = CurDAG->getCopyFromReg(Chain, DL, DestReg, PtrVT);
- ReplaceUses(SDValue(Node, 0), ResNode);
- return std::make_pair(true, ResNode.getNode());
+ ReplaceNode(Node, ResNode.getNode());
+ return true;
}
case ISD::BUILD_VECTOR: {
@@ -890,16 +907,16 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) {
EVT ViaVecTy;
if (!Subtarget->hasMSA() || !BVN->getValueType(0).is128BitVector())
- return std::make_pair(false, nullptr);
+ return false;
if (!BVN->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
HasAnyUndefs, 8,
!Subtarget->isLittle()))
- return std::make_pair(false, nullptr);
+ return false;
switch (SplatBitSize) {
default:
- return std::make_pair(false, nullptr);
+ return false;
case 8:
LdiOp = Mips::LDI_B;
ViaVecTy = MVT::v16i8;
@@ -919,7 +936,7 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) {
}
if (!SplatValue.isSignedIntN(10))
- return std::make_pair(false, nullptr);
+ return false;
SDValue Imm = CurDAG->getTargetConstant(SplatValue, DL,
ViaVecTy.getVectorElementType());
@@ -940,12 +957,13 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) {
MVT::i32));
}
- return std::make_pair(true, Res);
+ ReplaceNode(Node, Res);
+ return true;
}
}
- return std::make_pair(false, nullptr);
+ return false;
}
bool MipsSEDAGToDAGISel::
@@ -1015,6 +1033,7 @@ SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID,
return true;
}
-FunctionPass *llvm::createMipsSEISelDag(MipsTargetMachine &TM) {
- return new MipsSEDAGToDAGISel(TM);
+FunctionPass *llvm::createMipsSEISelDag(MipsTargetMachine &TM,
+ CodeGenOpt::Level OptLevel) {
+ return new MipsSEDAGToDAGISel(TM, OptLevel);
}
diff --git a/lib/Target/Mips/MipsSEISelDAGToDAG.h b/lib/Target/Mips/MipsSEISelDAGToDAG.h
index a894034020e99..0f08b72a334e3 100644
--- a/lib/Target/Mips/MipsSEISelDAGToDAG.h
+++ b/lib/Target/Mips/MipsSEISelDAGToDAG.h
@@ -21,7 +21,8 @@ namespace llvm {
class MipsSEDAGToDAGISel : public MipsDAGToDAGISel {
public:
- explicit MipsSEDAGToDAGISel(MipsTargetMachine &TM) : MipsDAGToDAGISel(TM) {}
+ explicit MipsSEDAGToDAGISel(MipsTargetMachine &TM, CodeGenOpt::Level OL)
+ : MipsDAGToDAGISel(TM, OL) {}
private:
@@ -34,11 +35,12 @@ private:
bool replaceUsesWithZeroReg(MachineRegisterInfo *MRI, const MachineInstr&);
- std::pair<SDNode*, SDNode*> selectMULT(SDNode *N, unsigned Opc, SDLoc dl,
- EVT Ty, bool HasLo, bool HasHi);
+ std::pair<SDNode *, SDNode *> selectMULT(SDNode *N, unsigned Opc,
+ const SDLoc &dl, EVT Ty, bool HasLo,
+ bool HasHi);
- SDNode *selectAddESubE(unsigned MOp, SDValue InFlag, SDValue CmpLHS,
- SDLoc DL, SDNode *Node) const;
+ void selectAddESubE(unsigned MOp, SDValue InFlag, SDValue CmpLHS,
+ const SDLoc &DL, SDNode *Node) const;
bool selectAddrFrameIndex(SDValue Addr, SDValue &Base, SDValue &Offset) const;
bool selectAddrFrameIndexOffset(SDValue Addr, SDValue &Base, SDValue &Offset,
@@ -47,9 +49,6 @@ private:
bool selectAddrRegImm(SDValue Addr, SDValue &Base,
SDValue &Offset) const override;
- bool selectAddrRegReg(SDValue Addr, SDValue &Base,
- SDValue &Offset) const override;
-
bool selectAddrDefault(SDValue Addr, SDValue &Base,
SDValue &Offset) const override;
@@ -62,14 +61,23 @@ private:
bool selectAddrRegImm10(SDValue Addr, SDValue &Base,
SDValue &Offset) const;
+ bool selectAddrRegImm11(SDValue Addr, SDValue &Base,
+ SDValue &Offset) const;
+
bool selectAddrRegImm12(SDValue Addr, SDValue &Base,
SDValue &Offset) const;
bool selectAddrRegImm16(SDValue Addr, SDValue &Base,
SDValue &Offset) const;
- bool selectIntAddrMM(SDValue Addr, SDValue &Base,
- SDValue &Offset) const override;
+ bool selectIntAddr11MM(SDValue Addr, SDValue &Base,
+ SDValue &Offset) const override;
+
+ bool selectIntAddr12MM(SDValue Addr, SDValue &Base,
+ SDValue &Offset) const override;
+
+ bool selectIntAddr16MM(SDValue Addr, SDValue &Base,
+ SDValue &Offset) const override;
bool selectIntAddrLSL2MM(SDValue Addr, SDValue &Base,
SDValue &Offset) const override;
@@ -111,7 +119,7 @@ private:
/// starting at bit zero.
bool selectVSplatMaskR(SDValue N, SDValue &Imm) const override;
- std::pair<bool, SDNode*> selectNode(SDNode *Node) override;
+ bool trySelect(SDNode *Node) override;
void processFunctionAfterISel(MachineFunction &MF) override;
@@ -124,8 +132,8 @@ private:
std::vector<SDValue> &OutOps) override;
};
-FunctionPass *createMipsSEISelDag(MipsTargetMachine &TM);
-
+FunctionPass *createMipsSEISelDag(MipsTargetMachine &TM,
+ CodeGenOpt::Level OptLevel);
}
#endif
diff --git a/lib/Target/Mips/MipsSEISelLowering.cpp b/lib/Target/Mips/MipsSEISelLowering.cpp
index efe22fba98cee..80c000d5746d7 100644
--- a/lib/Target/Mips/MipsSEISelLowering.cpp
+++ b/lib/Target/Mips/MipsSEISelLowering.cpp
@@ -793,7 +793,7 @@ static SDValue performSUBECombine(SDNode *N, SelectionDAG &DAG,
return SDValue();
}
-static SDValue genConstMult(SDValue X, uint64_t C, SDLoc DL, EVT VT,
+static SDValue genConstMult(SDValue X, uint64_t C, const SDLoc &DL, EVT VT,
EVT ShiftTy, SelectionDAG &DAG) {
// Clear the upper (64 - VT.sizeInBits) bits.
C &= ((uint64_t)-1) >> (64 - VT.getSizeInBits());
@@ -1111,9 +1111,9 @@ MipsSETargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const {
}
MachineBasicBlock *
-MipsSETargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
+MipsSETargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI,
MachineBasicBlock *BB) const {
- switch (MI->getOpcode()) {
+ switch (MI.getOpcode()) {
default:
return MipsTargetLowering::EmitInstrWithCustomInserter(MI, BB);
case Mips::BPOSGE32_PSEUDO:
@@ -1218,17 +1218,14 @@ SDValue MipsSETargetLowering::lowerLOAD(SDValue Op, SelectionDAG &DAG) const {
EVT PtrVT = Ptr.getValueType();
// i32 load from lower address.
- SDValue Lo = DAG.getLoad(MVT::i32, DL, Chain, Ptr,
- MachinePointerInfo(), Nd.isVolatile(),
- Nd.isNonTemporal(), Nd.isInvariant(),
- Nd.getAlignment());
+ SDValue Lo = DAG.getLoad(MVT::i32, DL, Chain, Ptr, MachinePointerInfo(),
+ Nd.getAlignment(), Nd.getMemOperand()->getFlags());
// i32 load from higher address.
Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, Ptr, DAG.getConstant(4, DL, PtrVT));
- SDValue Hi = DAG.getLoad(MVT::i32, DL, Lo.getValue(1), Ptr,
- MachinePointerInfo(), Nd.isVolatile(),
- Nd.isNonTemporal(), Nd.isInvariant(),
- std::min(Nd.getAlignment(), 4U));
+ SDValue Hi = DAG.getLoad(
+ MVT::i32, DL, Lo.getValue(1), Ptr, MachinePointerInfo(),
+ std::min(Nd.getAlignment(), 4U), Nd.getMemOperand()->getFlags());
if (!Subtarget.isLittle())
std::swap(Lo, Hi);
@@ -1257,15 +1254,15 @@ SDValue MipsSETargetLowering::lowerSTORE(SDValue Op, SelectionDAG &DAG) const {
std::swap(Lo, Hi);
// i32 store to lower address.
- Chain = DAG.getStore(Chain, DL, Lo, Ptr, MachinePointerInfo(),
- Nd.isVolatile(), Nd.isNonTemporal(), Nd.getAlignment(),
- Nd.getAAInfo());
+ Chain =
+ DAG.getStore(Chain, DL, Lo, Ptr, MachinePointerInfo(), Nd.getAlignment(),
+ Nd.getMemOperand()->getFlags(), Nd.getAAInfo());
// i32 store to higher address.
Ptr = DAG.getNode(ISD::ADD, DL, PtrVT, Ptr, DAG.getConstant(4, DL, PtrVT));
return DAG.getStore(Chain, DL, Hi, Ptr, MachinePointerInfo(),
- Nd.isVolatile(), Nd.isNonTemporal(),
- std::min(Nd.getAlignment(), 4U), Nd.getAAInfo());
+ std::min(Nd.getAlignment(), 4U),
+ Nd.getMemOperand()->getFlags(), Nd.getAAInfo());
}
SDValue MipsSETargetLowering::lowerMulDiv(SDValue Op, unsigned NewOpc,
@@ -1292,8 +1289,7 @@ SDValue MipsSETargetLowering::lowerMulDiv(SDValue Op, unsigned NewOpc,
return DAG.getMergeValues(Vals, DL);
}
-
-static SDValue initAccumulator(SDValue In, SDLoc DL, SelectionDAG &DAG) {
+static SDValue initAccumulator(SDValue In, const SDLoc &DL, SelectionDAG &DAG) {
SDValue InLo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, In,
DAG.getConstant(0, DL, MVT::i32));
SDValue InHi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, In,
@@ -1301,7 +1297,7 @@ static SDValue initAccumulator(SDValue In, SDLoc DL, SelectionDAG &DAG) {
return DAG.getNode(MipsISD::MTLOHI, DL, MVT::Untyped, InLo, InHi);
}
-static SDValue extractLOHI(SDValue Op, SDLoc DL, SelectionDAG &DAG) {
+static SDValue extractLOHI(SDValue Op, const SDLoc &DL, SelectionDAG &DAG) {
SDValue Lo = DAG.getNode(MipsISD::MFLO, DL, MVT::i32, Op);
SDValue Hi = DAG.getNode(MipsISD::MFHI, DL, MVT::i32, Op);
return DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, Lo, Hi);
@@ -1401,8 +1397,8 @@ static SDValue lowerMSASplatZExt(SDValue Op, unsigned OpNr, SelectionDAG &DAG) {
SDValue Ops[16] = { LaneA, LaneB, LaneA, LaneB, LaneA, LaneB, LaneA, LaneB,
LaneA, LaneB, LaneA, LaneB, LaneA, LaneB, LaneA, LaneB };
- SDValue Result = DAG.getNode(ISD::BUILD_VECTOR, DL, ViaVecTy,
- makeArrayRef(Ops, ViaVecTy.getVectorNumElements()));
+ SDValue Result = DAG.getBuildVector(
+ ViaVecTy, DL, makeArrayRef(Ops, ViaVecTy.getVectorNumElements()));
if (ViaVecTy != ResVecTy)
Result = DAG.getNode(ISD::BITCAST, DL, ResVecTy, Result);
@@ -1442,8 +1438,8 @@ static SDValue getBuildVectorSplat(EVT VecTy, SDValue SplatValue,
SplatValueA, SplatValueB, SplatValueA, SplatValueB,
SplatValueA, SplatValueB, SplatValueA, SplatValueB };
- SDValue Result = DAG.getNode(ISD::BUILD_VECTOR, DL, ViaVecTy,
- makeArrayRef(Ops, ViaVecTy.getVectorNumElements()));
+ SDValue Result = DAG.getBuildVector(
+ ViaVecTy, DL, makeArrayRef(Ops, ViaVecTy.getVectorNumElements()));
if (VecTy != ViaVecTy)
Result = DAG.getNode(ISD::BITCAST, DL, VecTy, Result);
@@ -1471,10 +1467,10 @@ static SDValue lowerMSABinaryBitImmIntr(SDValue Op, SelectionDAG &DAG,
if (BigEndian)
std::swap(BitImmLoOp, BitImmHiOp);
- Exp2Imm =
- DAG.getNode(ISD::BITCAST, DL, MVT::v2i64,
- DAG.getNode(ISD::BUILD_VECTOR, DL, MVT::v4i32, BitImmLoOp,
- BitImmHiOp, BitImmLoOp, BitImmHiOp));
+ Exp2Imm = DAG.getNode(
+ ISD::BITCAST, DL, MVT::v2i64,
+ DAG.getBuildVector(MVT::v4i32, DL,
+ {BitImmLoOp, BitImmHiOp, BitImmLoOp, BitImmHiOp}));
}
}
@@ -1860,7 +1856,7 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op,
// If ResTy is v2i64 then the type legalizer will break this node down into
// an equivalent v4i32.
- return DAG.getNode(ISD::BUILD_VECTOR, DL, ResTy, Ops);
+ return DAG.getBuildVector(ResTy, DL, Ops);
}
case Intrinsic::mips_fexp2_w:
case Intrinsic::mips_fexp2_d: {
@@ -2166,6 +2162,10 @@ SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op,
case Intrinsic::mips_xori_b:
return DAG.getNode(ISD::XOR, DL, Op->getValueType(0),
Op->getOperand(1), lowerMSASplatImm(Op, 2, DAG));
+ case Intrinsic::thread_pointer: {
+ EVT PtrVT = getPointerTy(DAG.getDataLayout());
+ return DAG.getNode(MipsISD::ThreadPointer, DL, PtrVT);
+ }
}
}
@@ -2178,9 +2178,8 @@ static SDValue lowerMSALoadIntr(SDValue Op, SelectionDAG &DAG, unsigned Intr) {
EVT PtrTy = Address->getValueType(0);
Address = DAG.getNode(ISD::ADD, DL, PtrTy, Address, Offset);
-
- return DAG.getLoad(ResTy, DL, ChainIn, Address, MachinePointerInfo(), false,
- false, false, 16);
+ return DAG.getLoad(ResTy, DL, ChainIn, Address, MachinePointerInfo(),
+ /* Alignment = */ 16);
}
SDValue MipsSETargetLowering::lowerINTRINSIC_W_CHAIN(SDValue Op,
@@ -2247,8 +2246,8 @@ static SDValue lowerMSAStoreIntr(SDValue Op, SelectionDAG &DAG, unsigned Intr) {
Address = DAG.getNode(ISD::ADD, DL, PtrTy, Address, Offset);
- return DAG.getStore(ChainIn, DL, Value, Address, MachinePointerInfo(), false,
- false, 16);
+ return DAG.getStore(ChainIn, DL, Value, Address, MachinePointerInfo(),
+ /* Alignment = */ 16);
}
SDValue MipsSETargetLowering::lowerINTRINSIC_VOID(SDValue Op,
@@ -2311,7 +2310,7 @@ lowerEXTRACT_VECTOR_ELT(SDValue Op, SelectionDAG &DAG) const {
}
static bool isConstantOrUndef(const SDValue Op) {
- if (Op->getOpcode() == ISD::UNDEF)
+ if (Op->isUndef())
return true;
if (isa<ConstantSDNode>(Op))
return true;
@@ -2841,7 +2840,7 @@ static SDValue lowerVECTOR_SHUFFLE_VSHF(SDValue Op, EVT ResTy,
++I)
Ops.push_back(DAG.getTargetConstant(*I, DL, MaskEltTy));
- SDValue MaskVec = DAG.getNode(ISD::BUILD_VECTOR, DL, MaskVecTy, Ops);
+ SDValue MaskVec = DAG.getBuildVector(MaskVecTy, DL, Ops);
if (Using1stVec && Using2ndVec) {
Op0 = Op->getOperand(0);
@@ -2883,32 +2882,27 @@ SDValue MipsSETargetLowering::lowerVECTOR_SHUFFLE(SDValue Op,
// MipsISD::VSHF.
if (isVECTOR_SHUFFLE_SPLATI(Op, ResTy, Indices, DAG))
return lowerVECTOR_SHUFFLE_VSHF(Op, ResTy, Indices, DAG);
- SDValue Result = lowerVECTOR_SHUFFLE_ILVEV(Op, ResTy, Indices, DAG);
- if (Result.getNode())
+ SDValue Result;
+ if ((Result = lowerVECTOR_SHUFFLE_ILVEV(Op, ResTy, Indices, DAG)))
return Result;
- Result = lowerVECTOR_SHUFFLE_ILVOD(Op, ResTy, Indices, DAG);
- if (Result.getNode())
+ if ((Result = lowerVECTOR_SHUFFLE_ILVOD(Op, ResTy, Indices, DAG)))
return Result;
- Result = lowerVECTOR_SHUFFLE_ILVL(Op, ResTy, Indices, DAG);
- if (Result.getNode())
+ if ((Result = lowerVECTOR_SHUFFLE_ILVL(Op, ResTy, Indices, DAG)))
return Result;
- Result = lowerVECTOR_SHUFFLE_ILVR(Op, ResTy, Indices, DAG);
- if (Result.getNode())
+ if ((Result = lowerVECTOR_SHUFFLE_ILVR(Op, ResTy, Indices, DAG)))
return Result;
- Result = lowerVECTOR_SHUFFLE_PCKEV(Op, ResTy, Indices, DAG);
- if (Result.getNode())
+ if ((Result = lowerVECTOR_SHUFFLE_PCKEV(Op, ResTy, Indices, DAG)))
return Result;
- Result = lowerVECTOR_SHUFFLE_PCKOD(Op, ResTy, Indices, DAG);
- if (Result.getNode())
+ if ((Result = lowerVECTOR_SHUFFLE_PCKOD(Op, ResTy, Indices, DAG)))
return Result;
- Result = lowerVECTOR_SHUFFLE_SHF(Op, ResTy, Indices, DAG);
- if (Result.getNode())
+ if ((Result = lowerVECTOR_SHUFFLE_SHF(Op, ResTy, Indices, DAG)))
return Result;
return lowerVECTOR_SHUFFLE_VSHF(Op, ResTy, Indices, DAG);
}
-MachineBasicBlock * MipsSETargetLowering::
-emitBPOSGE32(MachineInstr *MI, MachineBasicBlock *BB) const{
+MachineBasicBlock *
+MipsSETargetLowering::emitBPOSGE32(MachineInstr &MI,
+ MachineBasicBlock *BB) const {
// $bb:
// bposge32_pseudo $vr0
// =>
@@ -2925,7 +2919,7 @@ emitBPOSGE32(MachineInstr *MI, MachineBasicBlock *BB) const{
MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
const TargetInstrInfo *TII = Subtarget.getInstrInfo();
const TargetRegisterClass *RC = &Mips::GPR32RegClass;
- DebugLoc DL = MI->getDebugLoc();
+ DebugLoc DL = MI.getDebugLoc();
const BasicBlock *LLVM_BB = BB->getBasicBlock();
MachineFunction::iterator It = std::next(MachineFunction::iterator(BB));
MachineFunction *F = BB->getParent();
@@ -2949,6 +2943,8 @@ emitBPOSGE32(MachineInstr *MI, MachineBasicBlock *BB) const{
// Insert the real bposge32 instruction to $BB.
BuildMI(BB, DL, TII->get(Mips::BPOSGE32)).addMBB(TBB);
+ // Insert the real bposge32c instruction to $BB.
+ BuildMI(BB, DL, TII->get(Mips::BPOSGE32C_MMR3)).addMBB(TBB);
// Fill $FBB.
unsigned VR2 = RegInfo.createVirtualRegister(RC);
@@ -2963,16 +2959,18 @@ emitBPOSGE32(MachineInstr *MI, MachineBasicBlock *BB) const{
// Insert phi function to $Sink.
BuildMI(*Sink, Sink->begin(), DL, TII->get(Mips::PHI),
- MI->getOperand(0).getReg())
- .addReg(VR2).addMBB(FBB).addReg(VR1).addMBB(TBB);
+ MI.getOperand(0).getReg())
+ .addReg(VR2)
+ .addMBB(FBB)
+ .addReg(VR1)
+ .addMBB(TBB);
- MI->eraseFromParent(); // The pseudo instruction is gone now.
+ MI.eraseFromParent(); // The pseudo instruction is gone now.
return Sink;
}
-MachineBasicBlock * MipsSETargetLowering::
-emitMSACBranchPseudo(MachineInstr *MI, MachineBasicBlock *BB,
- unsigned BranchOp) const{
+MachineBasicBlock *MipsSETargetLowering::emitMSACBranchPseudo(
+ MachineInstr &MI, MachineBasicBlock *BB, unsigned BranchOp) const {
// $bb:
// vany_nonzero $rd, $ws
// =>
@@ -2990,7 +2988,7 @@ emitMSACBranchPseudo(MachineInstr *MI, MachineBasicBlock *BB,
MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
const TargetInstrInfo *TII = Subtarget.getInstrInfo();
const TargetRegisterClass *RC = &Mips::GPR32RegClass;
- DebugLoc DL = MI->getDebugLoc();
+ DebugLoc DL = MI.getDebugLoc();
const BasicBlock *LLVM_BB = BB->getBasicBlock();
MachineFunction::iterator It = std::next(MachineFunction::iterator(BB));
MachineFunction *F = BB->getParent();
@@ -3014,8 +3012,8 @@ emitMSACBranchPseudo(MachineInstr *MI, MachineBasicBlock *BB,
// Insert the real bnz.b instruction to $BB.
BuildMI(BB, DL, TII->get(BranchOp))
- .addReg(MI->getOperand(1).getReg())
- .addMBB(TBB);
+ .addReg(MI.getOperand(1).getReg())
+ .addMBB(TBB);
// Fill $FBB.
unsigned RD1 = RegInfo.createVirtualRegister(RC);
@@ -3030,10 +3028,13 @@ emitMSACBranchPseudo(MachineInstr *MI, MachineBasicBlock *BB,
// Insert phi function to $Sink.
BuildMI(*Sink, Sink->begin(), DL, TII->get(Mips::PHI),
- MI->getOperand(0).getReg())
- .addReg(RD1).addMBB(FBB).addReg(RD2).addMBB(TBB);
+ MI.getOperand(0).getReg())
+ .addReg(RD1)
+ .addMBB(FBB)
+ .addReg(RD2)
+ .addMBB(TBB);
- MI->eraseFromParent(); // The pseudo instruction is gone now.
+ MI.eraseFromParent(); // The pseudo instruction is gone now.
return Sink;
}
@@ -3047,14 +3048,15 @@ emitMSACBranchPseudo(MachineInstr *MI, MachineBasicBlock *BB,
// When n is zero, the equivalent operation can be performed with (potentially)
// zero instructions due to register overlaps. This optimization is never valid
// for lane 1 because it would require FR=0 mode which isn't supported by MSA.
-MachineBasicBlock * MipsSETargetLowering::
-emitCOPY_FW(MachineInstr *MI, MachineBasicBlock *BB) const{
+MachineBasicBlock *
+MipsSETargetLowering::emitCOPY_FW(MachineInstr &MI,
+ MachineBasicBlock *BB) const {
const TargetInstrInfo *TII = Subtarget.getInstrInfo();
MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
- DebugLoc DL = MI->getDebugLoc();
- unsigned Fd = MI->getOperand(0).getReg();
- unsigned Ws = MI->getOperand(1).getReg();
- unsigned Lane = MI->getOperand(2).getImm();
+ DebugLoc DL = MI.getDebugLoc();
+ unsigned Fd = MI.getOperand(0).getReg();
+ unsigned Ws = MI.getOperand(1).getReg();
+ unsigned Lane = MI.getOperand(2).getImm();
if (Lane == 0) {
unsigned Wt = Ws;
@@ -3076,7 +3078,7 @@ emitCOPY_FW(MachineInstr *MI, MachineBasicBlock *BB) const{
BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Fd).addReg(Wt, 0, Mips::sub_lo);
}
- MI->eraseFromParent(); // The pseudo instruction is gone now.
+ MI.eraseFromParent(); // The pseudo instruction is gone now.
return BB;
}
@@ -3090,16 +3092,17 @@ emitCOPY_FW(MachineInstr *MI, MachineBasicBlock *BB) const{
// When n is zero, the equivalent operation can be performed with (potentially)
// zero instructions due to register overlaps. This optimization is always
// valid because FR=1 mode which is the only supported mode in MSA.
-MachineBasicBlock * MipsSETargetLowering::
-emitCOPY_FD(MachineInstr *MI, MachineBasicBlock *BB) const{
+MachineBasicBlock *
+MipsSETargetLowering::emitCOPY_FD(MachineInstr &MI,
+ MachineBasicBlock *BB) const {
assert(Subtarget.isFP64bit());
const TargetInstrInfo *TII = Subtarget.getInstrInfo();
MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
- unsigned Fd = MI->getOperand(0).getReg();
- unsigned Ws = MI->getOperand(1).getReg();
- unsigned Lane = MI->getOperand(2).getImm() * 2;
- DebugLoc DL = MI->getDebugLoc();
+ unsigned Fd = MI.getOperand(0).getReg();
+ unsigned Ws = MI.getOperand(1).getReg();
+ unsigned Lane = MI.getOperand(2).getImm() * 2;
+ DebugLoc DL = MI.getDebugLoc();
if (Lane == 0)
BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Fd).addReg(Ws, 0, Mips::sub_64);
@@ -3110,7 +3113,7 @@ emitCOPY_FD(MachineInstr *MI, MachineBasicBlock *BB) const{
BuildMI(*BB, MI, DL, TII->get(Mips::COPY), Fd).addReg(Wt, 0, Mips::sub_64);
}
- MI->eraseFromParent(); // The pseudo instruction is gone now.
+ MI.eraseFromParent(); // The pseudo instruction is gone now.
return BB;
}
@@ -3121,15 +3124,15 @@ emitCOPY_FD(MachineInstr *MI, MachineBasicBlock *BB) const{
// subreg_to_reg $wt:sub_lo, $fs
// insve_w $wd[$n], $wd_in, $wt[0]
MachineBasicBlock *
-MipsSETargetLowering::emitINSERT_FW(MachineInstr *MI,
+MipsSETargetLowering::emitINSERT_FW(MachineInstr &MI,
MachineBasicBlock *BB) const {
const TargetInstrInfo *TII = Subtarget.getInstrInfo();
MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
- DebugLoc DL = MI->getDebugLoc();
- unsigned Wd = MI->getOperand(0).getReg();
- unsigned Wd_in = MI->getOperand(1).getReg();
- unsigned Lane = MI->getOperand(2).getImm();
- unsigned Fs = MI->getOperand(3).getReg();
+ DebugLoc DL = MI.getDebugLoc();
+ unsigned Wd = MI.getOperand(0).getReg();
+ unsigned Wd_in = MI.getOperand(1).getReg();
+ unsigned Lane = MI.getOperand(2).getImm();
+ unsigned Fs = MI.getOperand(3).getReg();
unsigned Wt = RegInfo.createVirtualRegister(
Subtarget.useOddSPReg() ? &Mips::MSA128WRegClass :
&Mips::MSA128WEvensRegClass);
@@ -3144,7 +3147,7 @@ MipsSETargetLowering::emitINSERT_FW(MachineInstr *MI,
.addReg(Wt)
.addImm(0);
- MI->eraseFromParent(); // The pseudo instruction is gone now.
+ MI.eraseFromParent(); // The pseudo instruction is gone now.
return BB;
}
@@ -3155,17 +3158,17 @@ MipsSETargetLowering::emitINSERT_FW(MachineInstr *MI,
// subreg_to_reg $wt:sub_64, $fs
// insve_d $wd[$n], $wd_in, $wt[0]
MachineBasicBlock *
-MipsSETargetLowering::emitINSERT_FD(MachineInstr *MI,
+MipsSETargetLowering::emitINSERT_FD(MachineInstr &MI,
MachineBasicBlock *BB) const {
assert(Subtarget.isFP64bit());
const TargetInstrInfo *TII = Subtarget.getInstrInfo();
MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
- DebugLoc DL = MI->getDebugLoc();
- unsigned Wd = MI->getOperand(0).getReg();
- unsigned Wd_in = MI->getOperand(1).getReg();
- unsigned Lane = MI->getOperand(2).getImm();
- unsigned Fs = MI->getOperand(3).getReg();
+ DebugLoc DL = MI.getDebugLoc();
+ unsigned Wd = MI.getOperand(0).getReg();
+ unsigned Wd_in = MI.getOperand(1).getReg();
+ unsigned Lane = MI.getOperand(2).getImm();
+ unsigned Fs = MI.getOperand(3).getReg();
unsigned Wt = RegInfo.createVirtualRegister(&Mips::MSA128DRegClass);
BuildMI(*BB, MI, DL, TII->get(Mips::SUBREG_TO_REG), Wt)
@@ -3178,7 +3181,7 @@ MipsSETargetLowering::emitINSERT_FD(MachineInstr *MI,
.addReg(Wt)
.addImm(0);
- MI->eraseFromParent(); // The pseudo instruction is gone now.
+ MI.eraseFromParent(); // The pseudo instruction is gone now.
return BB;
}
@@ -3202,22 +3205,23 @@ MipsSETargetLowering::emitINSERT_FD(MachineInstr *MI,
// (INSVE_[WD], $wdtmp2, 0, $wdtmp1, 0)
// (NEG $lanetmp2, $lanetmp1)
// (SLD_B $wd, $wdtmp2, $wdtmp2, $lanetmp2)
-MachineBasicBlock *
-MipsSETargetLowering::emitINSERT_DF_VIDX(MachineInstr *MI,
- MachineBasicBlock *BB,
- unsigned EltSizeInBytes,
- bool IsFP) const {
+MachineBasicBlock *MipsSETargetLowering::emitINSERT_DF_VIDX(
+ MachineInstr &MI, MachineBasicBlock *BB, unsigned EltSizeInBytes,
+ bool IsFP) const {
const TargetInstrInfo *TII = Subtarget.getInstrInfo();
MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
- DebugLoc DL = MI->getDebugLoc();
- unsigned Wd = MI->getOperand(0).getReg();
- unsigned SrcVecReg = MI->getOperand(1).getReg();
- unsigned LaneReg = MI->getOperand(2).getReg();
- unsigned SrcValReg = MI->getOperand(3).getReg();
+ DebugLoc DL = MI.getDebugLoc();
+ unsigned Wd = MI.getOperand(0).getReg();
+ unsigned SrcVecReg = MI.getOperand(1).getReg();
+ unsigned LaneReg = MI.getOperand(2).getReg();
+ unsigned SrcValReg = MI.getOperand(3).getReg();
const TargetRegisterClass *VecRC = nullptr;
+ // FIXME: This should be true for N32 too.
const TargetRegisterClass *GPRRC =
Subtarget.isABI_N64() ? &Mips::GPR64RegClass : &Mips::GPR32RegClass;
+ unsigned SubRegIdx = Subtarget.isABI_N64() ? Mips::sub_32 : 0;
+ unsigned ShiftOp = Subtarget.isABI_N64() ? Mips::DSLL : Mips::SLL;
unsigned EltLog2Size;
unsigned InsertOp = 0;
unsigned InsveOp = 0;
@@ -3262,7 +3266,7 @@ MipsSETargetLowering::emitINSERT_DF_VIDX(MachineInstr *MI,
// Convert the lane index into a byte index
if (EltSizeInBytes != 1) {
unsigned LaneTmp1 = RegInfo.createVirtualRegister(GPRRC);
- BuildMI(*BB, MI, DL, TII->get(Mips::SLL), LaneTmp1)
+ BuildMI(*BB, MI, DL, TII->get(ShiftOp), LaneTmp1)
.addReg(LaneReg)
.addImm(EltLog2Size);
LaneReg = LaneTmp1;
@@ -3273,7 +3277,7 @@ MipsSETargetLowering::emitINSERT_DF_VIDX(MachineInstr *MI,
BuildMI(*BB, MI, DL, TII->get(Mips::SLD_B), WdTmp1)
.addReg(SrcVecReg)
.addReg(SrcVecReg)
- .addReg(LaneReg);
+ .addReg(LaneReg, 0, SubRegIdx);
unsigned WdTmp2 = RegInfo.createVirtualRegister(VecRC);
if (IsFP) {
@@ -3302,9 +3306,9 @@ MipsSETargetLowering::emitINSERT_DF_VIDX(MachineInstr *MI,
BuildMI(*BB, MI, DL, TII->get(Mips::SLD_B), Wd)
.addReg(WdTmp2)
.addReg(WdTmp2)
- .addReg(LaneTmp2);
+ .addReg(LaneTmp2, 0, SubRegIdx);
- MI->eraseFromParent(); // The pseudo instruction is gone now.
+ MI.eraseFromParent(); // The pseudo instruction is gone now.
return BB;
}
@@ -3316,13 +3320,13 @@ MipsSETargetLowering::emitINSERT_DF_VIDX(MachineInstr *MI,
// insert_subreg $wt2:subreg_lo, $wt1, $fs
// splati.w $wd, $wt2[0]
MachineBasicBlock *
-MipsSETargetLowering::emitFILL_FW(MachineInstr *MI,
+MipsSETargetLowering::emitFILL_FW(MachineInstr &MI,
MachineBasicBlock *BB) const {
const TargetInstrInfo *TII = Subtarget.getInstrInfo();
MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
- DebugLoc DL = MI->getDebugLoc();
- unsigned Wd = MI->getOperand(0).getReg();
- unsigned Fs = MI->getOperand(1).getReg();
+ DebugLoc DL = MI.getDebugLoc();
+ unsigned Wd = MI.getOperand(0).getReg();
+ unsigned Fs = MI.getOperand(1).getReg();
unsigned Wt1 = RegInfo.createVirtualRegister(&Mips::MSA128WRegClass);
unsigned Wt2 = RegInfo.createVirtualRegister(&Mips::MSA128WRegClass);
@@ -3333,7 +3337,7 @@ MipsSETargetLowering::emitFILL_FW(MachineInstr *MI,
.addImm(Mips::sub_lo);
BuildMI(*BB, MI, DL, TII->get(Mips::SPLATI_W), Wd).addReg(Wt2).addImm(0);
- MI->eraseFromParent(); // The pseudo instruction is gone now.
+ MI.eraseFromParent(); // The pseudo instruction is gone now.
return BB;
}
@@ -3345,15 +3349,15 @@ MipsSETargetLowering::emitFILL_FW(MachineInstr *MI,
// insert_subreg $wt2:subreg_64, $wt1, $fs
// splati.d $wd, $wt2[0]
MachineBasicBlock *
-MipsSETargetLowering::emitFILL_FD(MachineInstr *MI,
+MipsSETargetLowering::emitFILL_FD(MachineInstr &MI,
MachineBasicBlock *BB) const {
assert(Subtarget.isFP64bit());
const TargetInstrInfo *TII = Subtarget.getInstrInfo();
MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
- DebugLoc DL = MI->getDebugLoc();
- unsigned Wd = MI->getOperand(0).getReg();
- unsigned Fs = MI->getOperand(1).getReg();
+ DebugLoc DL = MI.getDebugLoc();
+ unsigned Wd = MI.getOperand(0).getReg();
+ unsigned Fs = MI.getOperand(1).getReg();
unsigned Wt1 = RegInfo.createVirtualRegister(&Mips::MSA128DRegClass);
unsigned Wt2 = RegInfo.createVirtualRegister(&Mips::MSA128DRegClass);
@@ -3364,7 +3368,7 @@ MipsSETargetLowering::emitFILL_FD(MachineInstr *MI,
.addImm(Mips::sub_64);
BuildMI(*BB, MI, DL, TII->get(Mips::SPLATI_D), Wd).addReg(Wt2).addImm(0);
- MI->eraseFromParent(); // The pseudo instruction is gone now.
+ MI.eraseFromParent(); // The pseudo instruction is gone now.
return BB;
}
@@ -3375,25 +3379,25 @@ MipsSETargetLowering::emitFILL_FD(MachineInstr *MI,
// ldi.w $ws, 1
// fexp2.w $wd, $ws, $wt
MachineBasicBlock *
-MipsSETargetLowering::emitFEXP2_W_1(MachineInstr *MI,
+MipsSETargetLowering::emitFEXP2_W_1(MachineInstr &MI,
MachineBasicBlock *BB) const {
const TargetInstrInfo *TII = Subtarget.getInstrInfo();
MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
const TargetRegisterClass *RC = &Mips::MSA128WRegClass;
unsigned Ws1 = RegInfo.createVirtualRegister(RC);
unsigned Ws2 = RegInfo.createVirtualRegister(RC);
- DebugLoc DL = MI->getDebugLoc();
+ DebugLoc DL = MI.getDebugLoc();
// Splat 1.0 into a vector
BuildMI(*BB, MI, DL, TII->get(Mips::LDI_W), Ws1).addImm(1);
BuildMI(*BB, MI, DL, TII->get(Mips::FFINT_U_W), Ws2).addReg(Ws1);
// Emit 1.0 * fexp2(Wt)
- BuildMI(*BB, MI, DL, TII->get(Mips::FEXP2_W), MI->getOperand(0).getReg())
+ BuildMI(*BB, MI, DL, TII->get(Mips::FEXP2_W), MI.getOperand(0).getReg())
.addReg(Ws2)
- .addReg(MI->getOperand(1).getReg());
+ .addReg(MI.getOperand(1).getReg());
- MI->eraseFromParent(); // The pseudo instruction is gone now.
+ MI.eraseFromParent(); // The pseudo instruction is gone now.
return BB;
}
@@ -3404,24 +3408,24 @@ MipsSETargetLowering::emitFEXP2_W_1(MachineInstr *MI,
// ldi.d $ws, 1
// fexp2.d $wd, $ws, $wt
MachineBasicBlock *
-MipsSETargetLowering::emitFEXP2_D_1(MachineInstr *MI,
+MipsSETargetLowering::emitFEXP2_D_1(MachineInstr &MI,
MachineBasicBlock *BB) const {
const TargetInstrInfo *TII = Subtarget.getInstrInfo();
MachineRegisterInfo &RegInfo = BB->getParent()->getRegInfo();
const TargetRegisterClass *RC = &Mips::MSA128DRegClass;
unsigned Ws1 = RegInfo.createVirtualRegister(RC);
unsigned Ws2 = RegInfo.createVirtualRegister(RC);
- DebugLoc DL = MI->getDebugLoc();
+ DebugLoc DL = MI.getDebugLoc();
// Splat 1.0 into a vector
BuildMI(*BB, MI, DL, TII->get(Mips::LDI_D), Ws1).addImm(1);
BuildMI(*BB, MI, DL, TII->get(Mips::FFINT_U_D), Ws2).addReg(Ws1);
// Emit 1.0 * fexp2(Wt)
- BuildMI(*BB, MI, DL, TII->get(Mips::FEXP2_D), MI->getOperand(0).getReg())
+ BuildMI(*BB, MI, DL, TII->get(Mips::FEXP2_D), MI.getOperand(0).getReg())
.addReg(Ws2)
- .addReg(MI->getOperand(1).getReg());
+ .addReg(MI.getOperand(1).getReg());
- MI->eraseFromParent(); // The pseudo instruction is gone now.
+ MI.eraseFromParent(); // The pseudo instruction is gone now.
return BB;
}
diff --git a/lib/Target/Mips/MipsSEISelLowering.h b/lib/Target/Mips/MipsSEISelLowering.h
index d44f8d82ec3ea..54154662f2614 100644
--- a/lib/Target/Mips/MipsSEISelLowering.h
+++ b/lib/Target/Mips/MipsSEISelLowering.h
@@ -40,7 +40,7 @@ namespace llvm {
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override;
MachineBasicBlock *
- EmitInstrWithCustomInserter(MachineInstr *MI,
+ EmitInstrWithCustomInserter(MachineInstr &MI,
MachineBasicBlock *MBB) const override;
bool isShuffleMaskLegal(const SmallVectorImpl<int> &Mask,
@@ -77,39 +77,39 @@ namespace llvm {
/// depending on the indices in the shuffle.
SDValue lowerVECTOR_SHUFFLE(SDValue Op, SelectionDAG &DAG) const;
- MachineBasicBlock *emitBPOSGE32(MachineInstr *MI,
+ MachineBasicBlock *emitBPOSGE32(MachineInstr &MI,
MachineBasicBlock *BB) const;
- MachineBasicBlock *emitMSACBranchPseudo(MachineInstr *MI,
+ MachineBasicBlock *emitMSACBranchPseudo(MachineInstr &MI,
MachineBasicBlock *BB,
unsigned BranchOp) const;
/// \brief Emit the COPY_FW pseudo instruction
- MachineBasicBlock *emitCOPY_FW(MachineInstr *MI,
+ MachineBasicBlock *emitCOPY_FW(MachineInstr &MI,
MachineBasicBlock *BB) const;
/// \brief Emit the COPY_FD pseudo instruction
- MachineBasicBlock *emitCOPY_FD(MachineInstr *MI,
+ MachineBasicBlock *emitCOPY_FD(MachineInstr &MI,
MachineBasicBlock *BB) const;
/// \brief Emit the INSERT_FW pseudo instruction
- MachineBasicBlock *emitINSERT_FW(MachineInstr *MI,
+ MachineBasicBlock *emitINSERT_FW(MachineInstr &MI,
MachineBasicBlock *BB) const;
/// \brief Emit the INSERT_FD pseudo instruction
- MachineBasicBlock *emitINSERT_FD(MachineInstr *MI,
+ MachineBasicBlock *emitINSERT_FD(MachineInstr &MI,
MachineBasicBlock *BB) const;
/// \brief Emit the INSERT_([BHWD]|F[WD])_VIDX pseudo instruction
- MachineBasicBlock *emitINSERT_DF_VIDX(MachineInstr *MI,
+ MachineBasicBlock *emitINSERT_DF_VIDX(MachineInstr &MI,
MachineBasicBlock *BB,
unsigned EltSizeInBytes,
bool IsFP) const;
/// \brief Emit the FILL_FW pseudo instruction
- MachineBasicBlock *emitFILL_FW(MachineInstr *MI,
+ MachineBasicBlock *emitFILL_FW(MachineInstr &MI,
MachineBasicBlock *BB) const;
/// \brief Emit the FILL_FD pseudo instruction
- MachineBasicBlock *emitFILL_FD(MachineInstr *MI,
+ MachineBasicBlock *emitFILL_FD(MachineInstr &MI,
MachineBasicBlock *BB) const;
/// \brief Emit the FEXP2_W_1 pseudo instructions.
- MachineBasicBlock *emitFEXP2_W_1(MachineInstr *MI,
+ MachineBasicBlock *emitFEXP2_W_1(MachineInstr &MI,
MachineBasicBlock *BB) const;
/// \brief Emit the FEXP2_D_1 pseudo instructions.
- MachineBasicBlock *emitFEXP2_D_1(MachineInstr *MI,
+ MachineBasicBlock *emitFEXP2_D_1(MachineInstr &MI,
MachineBasicBlock *BB) const;
};
}
diff --git a/lib/Target/Mips/MipsSEInstrInfo.cpp b/lib/Target/Mips/MipsSEInstrInfo.cpp
index d4aeaf9286552..29107b2c1aa5e 100644
--- a/lib/Target/Mips/MipsSEInstrInfo.cpp
+++ b/lib/Target/Mips/MipsSEInstrInfo.cpp
@@ -13,20 +13,20 @@
#include "MipsSEInstrInfo.h"
#include "InstPrinter/MipsInstPrinter.h"
+#include "MipsAnalyzeImmediate.h"
#include "MipsMachineFunction.h"
#include "MipsTargetMachine.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MathExtras.h"
#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
MipsSEInstrInfo::MipsSEInstrInfo(const MipsSubtarget &STI)
- : MipsInstrInfo(STI, STI.getRelocationModel() == Reloc::PIC_ ? Mips::B
- : Mips::J),
+ : MipsInstrInfo(STI, STI.isPositionIndependent() ? Mips::B : Mips::J),
RI() {}
const MipsRegisterInfo &MipsSEInstrInfo::getRegisterInfo() const {
@@ -38,17 +38,17 @@ const MipsRegisterInfo &MipsSEInstrInfo::getRegisterInfo() const {
/// the destination along with the FrameIndex of the loaded stack slot. If
/// not, return 0. This predicate must return 0 if the instruction has
/// any side effects other than loading from the stack slot.
-unsigned MipsSEInstrInfo::isLoadFromStackSlot(const MachineInstr *MI,
+unsigned MipsSEInstrInfo::isLoadFromStackSlot(const MachineInstr &MI,
int &FrameIndex) const {
- unsigned Opc = MI->getOpcode();
+ unsigned Opc = MI.getOpcode();
if ((Opc == Mips::LW) || (Opc == Mips::LD) ||
(Opc == Mips::LWC1) || (Opc == Mips::LDC1) || (Opc == Mips::LDC164)) {
- if ((MI->getOperand(1).isFI()) && // is a stack slot
- (MI->getOperand(2).isImm()) && // the imm is zero
- (isZeroImm(MI->getOperand(2)))) {
- FrameIndex = MI->getOperand(1).getIndex();
- return MI->getOperand(0).getReg();
+ if ((MI.getOperand(1).isFI()) && // is a stack slot
+ (MI.getOperand(2).isImm()) && // the imm is zero
+ (isZeroImm(MI.getOperand(2)))) {
+ FrameIndex = MI.getOperand(1).getIndex();
+ return MI.getOperand(0).getReg();
}
}
@@ -60,26 +60,26 @@ unsigned MipsSEInstrInfo::isLoadFromStackSlot(const MachineInstr *MI,
/// the source reg along with the FrameIndex of the loaded stack slot. If
/// not, return 0. This predicate must return 0 if the instruction has
/// any side effects other than storing to the stack slot.
-unsigned MipsSEInstrInfo::isStoreToStackSlot(const MachineInstr *MI,
+unsigned MipsSEInstrInfo::isStoreToStackSlot(const MachineInstr &MI,
int &FrameIndex) const {
- unsigned Opc = MI->getOpcode();
+ unsigned Opc = MI.getOpcode();
if ((Opc == Mips::SW) || (Opc == Mips::SD) ||
(Opc == Mips::SWC1) || (Opc == Mips::SDC1) || (Opc == Mips::SDC164)) {
- if ((MI->getOperand(1).isFI()) && // is a stack slot
- (MI->getOperand(2).isImm()) && // the imm is zero
- (isZeroImm(MI->getOperand(2)))) {
- FrameIndex = MI->getOperand(1).getIndex();
- return MI->getOperand(0).getReg();
+ if ((MI.getOperand(1).isFI()) && // is a stack slot
+ (MI.getOperand(2).isImm()) && // the imm is zero
+ (isZeroImm(MI.getOperand(2)))) {
+ FrameIndex = MI.getOperand(1).getIndex();
+ return MI.getOperand(0).getReg();
}
}
return 0;
}
void MipsSEInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator I, DebugLoc DL,
- unsigned DestReg, unsigned SrcReg,
- bool KillSrc) const {
+ MachineBasicBlock::iterator I,
+ const DebugLoc &DL, unsigned DestReg,
+ unsigned SrcReg, bool KillSrc) const {
unsigned Opc = 0, ZeroReg = 0;
bool isMicroMips = Subtarget.inMicroMipsMode();
@@ -129,9 +129,12 @@ void MipsSEInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
.addReg(SrcReg, getKillRegState(KillSrc)).addImm(1 << 4)
.addReg(DestReg, RegState::ImplicitDefine);
return;
+ } else if (Mips::MSACtrlRegClass.contains(DestReg)) {
+ BuildMI(MBB, I, DL, get(Mips::CTCMSA))
+ .addReg(DestReg)
+ .addReg(SrcReg, getKillRegState(KillSrc));
+ return;
}
- else if (Mips::MSACtrlRegClass.contains(DestReg))
- Opc = Mips::CTCMSA;
}
else if (Mips::FGR32RegClass.contains(DestReg, SrcReg))
Opc = Mips::FMOV_S;
@@ -325,12 +328,12 @@ loadRegFromStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
}
}
-bool MipsSEInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const {
- MachineBasicBlock &MBB = *MI->getParent();
+bool MipsSEInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
+ MachineBasicBlock &MBB = *MI.getParent();
bool isMicroMips = Subtarget.inMicroMipsMode();
unsigned Opc;
- switch(MI->getDesc().getOpcode()) {
+ switch (MI.getDesc().getOpcode()) {
default:
return false;
case Mips::RetRA:
@@ -420,6 +423,14 @@ unsigned MipsSEInstrInfo::getOppositeBranchOpc(unsigned Opc) const {
case Mips::BC1F: return Mips::BC1T;
case Mips::BEQZC_MM: return Mips::BNEZC_MM;
case Mips::BNEZC_MM: return Mips::BEQZC_MM;
+ case Mips::BEQZC: return Mips::BNEZC;
+ case Mips::BNEZC: return Mips::BEQZC;
+ case Mips::BEQC: return Mips::BNEC;
+ case Mips::BNEC: return Mips::BEQC;
+ case Mips::BGTZC: return Mips::BLEZC;
+ case Mips::BGEZC: return Mips::BLTZC;
+ case Mips::BLTZC: return Mips::BGEZC;
+ case Mips::BLEZC: return Mips::BGTZC;
}
}
@@ -429,26 +440,33 @@ void MipsSEInstrInfo::adjustStackPtr(unsigned SP, int64_t Amount,
MachineBasicBlock::iterator I) const {
MipsABIInfo ABI = Subtarget.getABI();
DebugLoc DL;
- unsigned ADDu = ABI.GetPtrAdduOp();
unsigned ADDiu = ABI.GetPtrAddiuOp();
if (Amount == 0)
return;
- if (isInt<16>(Amount))// addi sp, sp, amount
+ if (isInt<16>(Amount)) {
+ // addi sp, sp, amount
BuildMI(MBB, I, DL, get(ADDiu), SP).addReg(SP).addImm(Amount);
- else { // Expand immediate that doesn't fit in 16-bit.
+ } else {
+ // For numbers which are not 16bit integers we synthesize Amount inline
+ // then add or subtract it from sp.
+ unsigned Opc = ABI.GetPtrAdduOp();
+ if (Amount < 0) {
+ Opc = ABI.GetPtrSubuOp();
+ Amount = -Amount;
+ }
unsigned Reg = loadImmediate(Amount, MBB, I, DL, nullptr);
- BuildMI(MBB, I, DL, get(ADDu), SP).addReg(SP).addReg(Reg, RegState::Kill);
+ BuildMI(MBB, I, DL, get(Opc), SP).addReg(SP).addReg(Reg, RegState::Kill);
}
}
/// This function generates the sequence of instructions needed to get the
/// result of adding register REG and immediate IMM.
-unsigned
-MipsSEInstrInfo::loadImmediate(int64_t Imm, MachineBasicBlock &MBB,
- MachineBasicBlock::iterator II, DebugLoc DL,
- unsigned *NewImm) const {
+unsigned MipsSEInstrInfo::loadImmediate(int64_t Imm, MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator II,
+ const DebugLoc &DL,
+ unsigned *NewImm) const {
MipsAnalyzeImmediate AnalyzeImm;
const MipsSubtarget &STI = Subtarget;
MachineRegisterInfo &RegInfo = MBB.getParent()->getRegInfo();
@@ -493,8 +511,12 @@ unsigned MipsSEInstrInfo::getAnalyzableBrOpc(unsigned Opc) const {
Opc == Mips::BEQ64 || Opc == Mips::BNE64 || Opc == Mips::BGTZ64 ||
Opc == Mips::BGEZ64 || Opc == Mips::BLTZ64 || Opc == Mips::BLEZ64 ||
Opc == Mips::BC1T || Opc == Mips::BC1F || Opc == Mips::B ||
- Opc == Mips::J || Opc == Mips::BEQZC_MM || Opc == Mips::BNEZC_MM) ?
- Opc : 0;
+ Opc == Mips::J || Opc == Mips::BEQZC_MM || Opc == Mips::BNEZC_MM ||
+ Opc == Mips::BEQC || Opc == Mips::BNEC || Opc == Mips::BLTC ||
+ Opc == Mips::BGEC || Opc == Mips::BLTUC || Opc == Mips::BGEUC ||
+ Opc == Mips::BGTZC || Opc == Mips::BLEZC || Opc == Mips::BGEZC ||
+ Opc == Mips::BLTZC || Opc == Mips::BEQZC || Opc == Mips::BNEZC ||
+ Opc == Mips::BC) ? Opc : 0;
}
void MipsSEInstrInfo::expandRetRA(MachineBasicBlock &MBB,
@@ -697,7 +719,7 @@ void MipsSEInstrInfo::expandEhReturn(MachineBasicBlock &MBB,
// addu $sp, $sp, $v1
// jr $ra (via RetRA)
const TargetMachine &TM = MBB.getParent()->getTarget();
- if (TM.getRelocationModel() == Reloc::PIC_)
+ if (TM.isPositionIndependent())
BuildMI(MBB, I, I->getDebugLoc(), get(ADDU), T9)
.addReg(TargetReg)
.addReg(ZERO);
diff --git a/lib/Target/Mips/MipsSEInstrInfo.h b/lib/Target/Mips/MipsSEInstrInfo.h
index 5d73545ef6b9b..b356909bf1cf9 100644
--- a/lib/Target/Mips/MipsSEInstrInfo.h
+++ b/lib/Target/Mips/MipsSEInstrInfo.h
@@ -32,7 +32,7 @@ public:
/// the destination along with the FrameIndex of the loaded stack slot. If
/// not, return 0. This predicate must return 0 if the instruction has
/// any side effects other than loading from the stack slot.
- unsigned isLoadFromStackSlot(const MachineInstr *MI,
+ unsigned isLoadFromStackSlot(const MachineInstr &MI,
int &FrameIndex) const override;
/// isStoreToStackSlot - If the specified machine instruction is a direct
@@ -40,12 +40,11 @@ public:
/// the source reg along with the FrameIndex of the loaded stack slot. If
/// not, return 0. This predicate must return 0 if the instruction has
/// any side effects other than storing to the stack slot.
- unsigned isStoreToStackSlot(const MachineInstr *MI,
+ unsigned isStoreToStackSlot(const MachineInstr &MI,
int &FrameIndex) const override;
- void copyPhysReg(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI, DebugLoc DL,
- unsigned DestReg, unsigned SrcReg,
+ void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,
+ const DebugLoc &DL, unsigned DestReg, unsigned SrcReg,
bool KillSrc) const override;
void storeRegToStack(MachineBasicBlock &MBB,
@@ -62,7 +61,7 @@ public:
const TargetRegisterInfo *TRI,
int64_t Offset) const override;
- bool expandPostRAPseudo(MachineBasicBlock::iterator MI) const override;
+ bool expandPostRAPseudo(MachineInstr &MI) const override;
unsigned getOppositeBranchOpc(unsigned Opc) const override;
@@ -74,7 +73,7 @@ public:
/// non-NULL parameter, the last instruction is not emitted, but instead
/// its immediate operand is returned in NewImm.
unsigned loadImmediate(int64_t Imm, MachineBasicBlock &MBB,
- MachineBasicBlock::iterator II, DebugLoc DL,
+ MachineBasicBlock::iterator II, const DebugLoc &DL,
unsigned *NewImm) const;
private:
diff --git a/lib/Target/Mips/MipsSERegisterInfo.cpp b/lib/Target/Mips/MipsSERegisterInfo.cpp
index b1e2885f5ba31..e3431cd118ab1 100644
--- a/lib/Target/Mips/MipsSERegisterInfo.cpp
+++ b/lib/Target/Mips/MipsSERegisterInfo.cpp
@@ -14,12 +14,10 @@
#include "MipsSERegisterInfo.h"
#include "Mips.h"
-#include "MipsAnalyzeImmediate.h"
#include "MipsMachineFunction.h"
#include "MipsSEInstrInfo.h"
#include "MipsSubtarget.h"
#include "MipsTargetMachine.h"
-#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineFunction.h"
@@ -29,7 +27,6 @@
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Type.h"
-#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
@@ -63,10 +60,11 @@ MipsSERegisterInfo::intRegClass(unsigned Size) const {
return &Mips::GPR64RegClass;
}
-/// Get the size of the offset supported by the given load/store.
+/// Get the size of the offset supported by the given load/store/inline asm.
/// The result includes the effects of any scale factors applied to the
/// instruction immediate.
-static inline unsigned getLoadStoreOffsetSizeInBits(const unsigned Opcode) {
+static inline unsigned getLoadStoreOffsetSizeInBits(const unsigned Opcode,
+ MachineOperand MO) {
switch (Opcode) {
case Mips::LD_B:
case Mips::ST_B:
@@ -80,6 +78,49 @@ static inline unsigned getLoadStoreOffsetSizeInBits(const unsigned Opcode) {
case Mips::LD_D:
case Mips::ST_D:
return 10 + 3 /* scale factor */;
+ case Mips::LL:
+ case Mips::LL64:
+ case Mips::LLD:
+ case Mips::LLE:
+ case Mips::SC:
+ case Mips::SC64:
+ case Mips::SCD:
+ case Mips::SCE:
+ return 16;
+ case Mips::LLE_MM:
+ case Mips::LLE_MMR6:
+ case Mips::LL_MM:
+ case Mips::SCE_MM:
+ case Mips::SCE_MMR6:
+ case Mips::SC_MM:
+ return 12;
+ case Mips::LL64_R6:
+ case Mips::LL_R6:
+ case Mips::LLD_R6:
+ case Mips::SC64_R6:
+ case Mips::SCD_R6:
+ case Mips::SC_R6:
+ return 9;
+ case Mips::INLINEASM: {
+ unsigned ConstraintID = InlineAsm::getMemoryConstraintID(MO.getImm());
+ switch (ConstraintID) {
+ case InlineAsm::Constraint_ZC: {
+ const MipsSubtarget &Subtarget = MO.getParent()
+ ->getParent()
+ ->getParent()
+ ->getSubtarget<MipsSubtarget>();
+ if (Subtarget.inMicroMipsMode())
+ return 12;
+
+ if (Subtarget.hasMips32r6())
+ return 9;
+
+ return 16;
+ }
+ default:
+ return 16;
+ }
+ }
default:
return 16;
}
@@ -169,7 +210,8 @@ void MipsSERegisterInfo::eliminateFI(MachineBasicBlock::iterator II,
// Make sure Offset fits within the field available.
// For MSA instructions, this is a 10-bit signed immediate (scaled by
// element size), otherwise it is a 16-bit signed immediate.
- unsigned OffsetBitSize = getLoadStoreOffsetSizeInBits(MI.getOpcode());
+ unsigned OffsetBitSize =
+ getLoadStoreOffsetSizeInBits(MI.getOpcode(), MI.getOperand(OpNo - 1));
unsigned OffsetAlign = getLoadStoreOffsetAlign(MI.getOpcode());
if (OffsetBitSize < 16 && isInt<16>(Offset) &&
diff --git a/lib/Target/Mips/MipsSchedule.td b/lib/Target/Mips/MipsSchedule.td
index 37f9e491d546e..738b6c46407a7 100644
--- a/lib/Target/Mips/MipsSchedule.td
+++ b/lib/Target/Mips/MipsSchedule.td
@@ -23,24 +23,34 @@ def IIPseudo : InstrItinClass;
def II_ABS : InstrItinClass;
def II_ADDI : InstrItinClass;
def II_ADDIU : InstrItinClass;
+def II_ADDIUPC : InstrItinClass;
+def II_ADD : InstrItinClass;
def II_ADDU : InstrItinClass;
def II_ADD_D : InstrItinClass;
def II_ADD_S : InstrItinClass;
+def II_ALIGN : InstrItinClass;
def II_AND : InstrItinClass;
def II_ANDI : InstrItinClass;
+def II_ALUIPC : InstrItinClass;
+def II_AUI : InstrItinClass;
+def II_AUIPC : InstrItinClass;
def II_B : InstrItinClass;
def II_BADDU : InstrItinClass;
def II_BBIT : InstrItinClass; // bbit[01], bbit[01]32
+def II_BALC : InstrItinClass;
def II_BC : InstrItinClass;
def II_BC1F : InstrItinClass;
def II_BC1FL : InstrItinClass;
def II_BC1T : InstrItinClass;
def II_BC1TL : InstrItinClass;
+def II_BC1CCZ : InstrItinClass;
def II_BCC : InstrItinClass; // beq and bne
def II_BCCZ : InstrItinClass; // b[gl][et]z
+def II_BCCC : InstrItinClass; // b<cc>c
def II_BCCZAL : InstrItinClass; // bgezal and bltzal
def II_BCCZALS : InstrItinClass; // bgezals and bltzals
def II_BCCZC : InstrItinClass; // beqzc, bnezc
+def II_BITSWAP : InstrItinClass;
def II_CEIL : InstrItinClass;
def II_CFC1 : InstrItinClass;
def II_CLO : InstrItinClass;
@@ -51,16 +61,33 @@ def II_C_CC_D : InstrItinClass; // Any c.<cc>.d instruction
def II_C_CC_S : InstrItinClass; // Any c.<cc>.s instruction
def II_DADDIU : InstrItinClass;
def II_DADDU : InstrItinClass;
+def II_DADDI : InstrItinClass;
def II_DADD : InstrItinClass;
+def II_DAHI : InstrItinClass;
+def II_DATI : InstrItinClass;
+def II_DAUI : InstrItinClass;
+def II_DALIGN : InstrItinClass;
+def II_DBITSWAP : InstrItinClass;
+def II_DCLO : InstrItinClass;
+def II_DCLZ : InstrItinClass;
def II_DDIV : InstrItinClass;
def II_DDIVU : InstrItinClass;
def II_DIV : InstrItinClass;
def II_DIVU : InstrItinClass;
def II_DIV_D : InstrItinClass;
def II_DIV_S : InstrItinClass;
+def II_DMFC0 : InstrItinClass;
+def II_DMTC0 : InstrItinClass;
def II_DMFC1 : InstrItinClass;
def II_DMTC1 : InstrItinClass;
+def II_DMOD : InstrItinClass;
+def II_DMODU : InstrItinClass;
+def II_DMUH : InstrItinClass;
+def II_DMUHU : InstrItinClass;
+def II_DMFC2 : InstrItinClass;
+def II_DMTC2 : InstrItinClass;
def II_DMUL : InstrItinClass;
+def II_DMULU : InstrItinClass;
def II_DMULT : InstrItinClass;
def II_DMULTU : InstrItinClass;
def II_DROTR : InstrItinClass;
@@ -75,6 +102,8 @@ def II_DSRAV : InstrItinClass;
def II_DSRL : InstrItinClass;
def II_DSRL32 : InstrItinClass;
def II_DSRLV : InstrItinClass;
+def II_DSBH : InstrItinClass;
+def II_DSHD : InstrItinClass;
def II_DSUBU : InstrItinClass;
def II_DSUB : InstrItinClass;
def II_EXT : InstrItinClass; // Any EXT instruction
@@ -84,44 +113,96 @@ def II_IndirectBranchPseudo : InstrItinClass; // Indirect branch pseudo.
def II_J : InstrItinClass;
def II_JAL : InstrItinClass;
def II_JALR : InstrItinClass;
+def II_JALR_HB : InstrItinClass;
def II_JALRC : InstrItinClass;
def II_JALRS : InstrItinClass;
def II_JALS : InstrItinClass;
+def II_JIC : InstrItinClass;
+def II_JIALC : InstrItinClass;
def II_JR : InstrItinClass;
+def II_JR_HB : InstrItinClass;
def II_JRADDIUSP : InstrItinClass;
def II_JRC : InstrItinClass;
def II_ReturnPseudo : InstrItinClass; // Return pseudo.
+def II_ERET : InstrItinClass;
+def II_DERET : InstrItinClass;
+def II_ERETNC : InstrItinClass;
+def II_EHB : InstrItinClass;
+def II_SDBBP : InstrItinClass;
+def II_SSNOP : InstrItinClass;
+def II_SYSCALL : InstrItinClass;
+def II_PAUSE : InstrItinClass;
+def II_WAIT : InstrItinClass;
+def II_EI : InstrItinClass;
+def II_DI : InstrItinClass;
+def II_TEQ : InstrItinClass;
+def II_TEQI : InstrItinClass;
+def II_TGE : InstrItinClass;
+def II_TGEI : InstrItinClass;
+def II_TGEIU : InstrItinClass;
+def II_TGEU : InstrItinClass;
+def II_TNE : InstrItinClass;
+def II_TNEI : InstrItinClass;
+def II_TLT : InstrItinClass;
+def II_TLTI : InstrItinClass;
+def II_TLTU : InstrItinClass;
+def II_TTLTIU : InstrItinClass;
+def II_TLBP : InstrItinClass;
+def II_TLBR : InstrItinClass;
+def II_TLBWI : InstrItinClass;
+def II_TLBWR : InstrItinClass;
+def II_TRAP : InstrItinClass;
+def II_BREAK : InstrItinClass;
+def II_SYNC : InstrItinClass;
+def II_SYNCI : InstrItinClass;
def II_LB : InstrItinClass;
def II_LBE : InstrItinClass;
def II_LBU : InstrItinClass;
def II_LBUE : InstrItinClass;
def II_LD : InstrItinClass;
def II_LDC1 : InstrItinClass;
+def II_LDC2 : InstrItinClass;
+def II_LDC3 : InstrItinClass;
def II_LDL : InstrItinClass;
def II_LDR : InstrItinClass;
+def II_LDPC : InstrItinClass;
def II_LDXC1 : InstrItinClass;
def II_LH : InstrItinClass;
def II_LHE : InstrItinClass;
def II_LHU : InstrItinClass;
def II_LHUE : InstrItinClass;
+def II_LL : InstrItinClass;
+def II_LLD : InstrItinClass;
def II_LUI : InstrItinClass;
def II_LUXC1 : InstrItinClass;
def II_LW : InstrItinClass;
def II_LWE : InstrItinClass;
def II_LWC1 : InstrItinClass;
+def II_LWC2 : InstrItinClass;
+def II_LWC3 : InstrItinClass;
def II_LWL : InstrItinClass;
def II_LWLE : InstrItinClass;
+def II_LWPC : InstrItinClass;
def II_LWR : InstrItinClass;
def II_LWRE : InstrItinClass;
def II_LWU : InstrItinClass;
+def II_LWUPC : InstrItinClass;
def II_LWXC1 : InstrItinClass;
+def II_LSA : InstrItinClass;
+def II_DLSA : InstrItinClass;
def II_MADD : InstrItinClass;
def II_MADDU : InstrItinClass;
def II_MADD_D : InstrItinClass;
def II_MADD_S : InstrItinClass;
+def II_MADDF_D : InstrItinClass;
+def II_MADDF_S : InstrItinClass;
+def II_MFC0 : InstrItinClass;
def II_MFC1 : InstrItinClass;
def II_MFHC1 : InstrItinClass;
+def II_MFC2 : InstrItinClass;
def II_MFHI_MFLO : InstrItinClass; // mfhi and mflo
+def II_MOD : InstrItinClass;
+def II_MODU : InstrItinClass;
def II_MOVF : InstrItinClass;
def II_MOVF_D : InstrItinClass;
def II_MOVF_S : InstrItinClass;
@@ -140,10 +221,17 @@ def II_MSUB : InstrItinClass;
def II_MSUBU : InstrItinClass;
def II_MSUB_D : InstrItinClass;
def II_MSUB_S : InstrItinClass;
+def II_MSUBF_D : InstrItinClass;
+def II_MSUBF_S : InstrItinClass;
+def II_MTC0 : InstrItinClass;
def II_MTC1 : InstrItinClass;
def II_MTHC1 : InstrItinClass;
+def II_MTC2 : InstrItinClass;
def II_MTHI_MTLO : InstrItinClass; // mthi and mtlo
def II_MUL : InstrItinClass;
+def II_MUH : InstrItinClass;
+def II_MUHU : InstrItinClass;
+def II_MULU : InstrItinClass;
def II_MULT : InstrItinClass;
def II_MULTU : InstrItinClass;
def II_MUL_D : InstrItinClass;
@@ -163,15 +251,20 @@ def II_ROTR : InstrItinClass;
def II_ROTRV : InstrItinClass;
def II_ROUND : InstrItinClass;
def II_SAVE : InstrItinClass;
+def II_SC : InstrItinClass;
+def II_SCD : InstrItinClass;
def II_SB : InstrItinClass;
def II_SBE : InstrItinClass;
def II_SD : InstrItinClass;
def II_SDC1 : InstrItinClass;
+def II_SDC2 : InstrItinClass;
+def II_SDC3 : InstrItinClass;
def II_SDL : InstrItinClass;
def II_SDR : InstrItinClass;
def II_SDXC1 : InstrItinClass;
def II_SEB : InstrItinClass;
def II_SEH : InstrItinClass;
+def II_SELCCZ : InstrItinClass;
def II_SEQ_SNE : InstrItinClass; // seq and sne
def II_SEQI_SNEI : InstrItinClass; // seqi and snei
def II_SH : InstrItinClass;
@@ -186,6 +279,7 @@ def II_SRA : InstrItinClass;
def II_SRAV : InstrItinClass;
def II_SRL : InstrItinClass;
def II_SRLV : InstrItinClass;
+def II_SUB : InstrItinClass;
def II_SUBU : InstrItinClass;
def II_SUB_D : InstrItinClass;
def II_SUB_S : InstrItinClass;
@@ -193,6 +287,8 @@ def II_SUXC1 : InstrItinClass;
def II_SW : InstrItinClass;
def II_SWE : InstrItinClass;
def II_SWC1 : InstrItinClass;
+def II_SWC2 : InstrItinClass;
+def II_SWC3 : InstrItinClass;
def II_SWL : InstrItinClass;
def II_SWLE : InstrItinClass;
def II_SWR : InstrItinClass;
@@ -202,6 +298,14 @@ def II_TRUNC : InstrItinClass;
def II_WSBH : InstrItinClass;
def II_XOR : InstrItinClass;
def II_XORI : InstrItinClass;
+def II_CACHE : InstrItinClass;
+def II_PREF : InstrItinClass;
+def II_CACHEE : InstrItinClass;
+def II_PREFE : InstrItinClass;
+def II_LLE : InstrItinClass;
+def II_SCE : InstrItinClass;
+def II_TLBINV : InstrItinClass;
+def II_TLBINVF : InstrItinClass;
//===----------------------------------------------------------------------===//
// Mips Generic instruction itineraries.
@@ -210,9 +314,16 @@ def MipsGenericItineraries : ProcessorItineraries<[ALU, IMULDIV], [], [
InstrItinData<IIM16Alu , [InstrStage<1, [ALU]>]>,
InstrItinData<II_ADDI , [InstrStage<1, [ALU]>]>,
InstrItinData<II_ADDIU , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_ADDIUPC , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_ADD , [InstrStage<1, [ALU]>]>,
InstrItinData<II_ADDU , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_AUI , [InstrStage<1, [ALU]>]>,
InstrItinData<II_AND , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_ALUIPC , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_AUIPC , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_ALIGN , [InstrStage<1, [ALU]>]>,
InstrItinData<II_BADDU , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_BITSWAP , [InstrStage<1, [ALU]>]>,
InstrItinData<II_SLL , [InstrStage<1, [ALU]>]>,
InstrItinData<II_SRA , [InstrStage<1, [ALU]>]>,
InstrItinData<II_SRL , [InstrStage<1, [ALU]>]>,
@@ -225,17 +336,35 @@ def MipsGenericItineraries : ProcessorItineraries<[ALU, IMULDIV], [], [
InstrItinData<II_CLZ , [InstrStage<1, [ALU]>]>,
InstrItinData<II_DADDIU , [InstrStage<1, [ALU]>]>,
InstrItinData<II_DADDU , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_DADDI , [InstrStage<1, [ALU]>]>,
InstrItinData<II_DADD , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_DALIGN , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_DAHI , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_DATI , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_DAUI , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_DBITSWAP , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_DCLO , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_DCLZ , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_DMOD , [InstrStage<17, [IMULDIV]>]>,
+ InstrItinData<II_DMODU , [InstrStage<17, [IMULDIV]>]>,
InstrItinData<II_DSLL , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_DSLL32 , [InstrStage<1, [ALU]>]>,
InstrItinData<II_DSRL , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_DSRL32 , [InstrStage<1, [ALU]>]>,
InstrItinData<II_DSRA , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_DSRA32 , [InstrStage<1, [ALU]>]>,
InstrItinData<II_DSLLV , [InstrStage<1, [ALU]>]>,
InstrItinData<II_DSRLV , [InstrStage<1, [ALU]>]>,
InstrItinData<II_DSRAV , [InstrStage<1, [ALU]>]>,
InstrItinData<II_DSUBU , [InstrStage<1, [ALU]>]>,
InstrItinData<II_DSUB , [InstrStage<1, [ALU]>]>,
InstrItinData<II_DROTR , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_DROTR32 , [InstrStage<1, [ALU]>]>,
InstrItinData<II_DROTRV , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_DSBH , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_DSHD , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_DCLO , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_DCLZ , [InstrStage<1, [ALU]>]>,
InstrItinData<II_EXT , [InstrStage<1, [ALU]>]>,
InstrItinData<II_INS , [InstrStage<1, [ALU]>]>,
InstrItinData<II_LUI , [InstrStage<1, [ALU]>]>,
@@ -249,41 +378,61 @@ def MipsGenericItineraries : ProcessorItineraries<[ALU, IMULDIV], [], [
InstrItinData<II_OR , [InstrStage<1, [ALU]>]>,
InstrItinData<II_POP , [InstrStage<1, [ALU]>]>,
InstrItinData<II_RDHWR , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_SUB , [InstrStage<1, [ALU]>]>,
InstrItinData<II_SUBU , [InstrStage<1, [ALU]>]>,
InstrItinData<II_XOR , [InstrStage<1, [ALU]>]>,
InstrItinData<II_ANDI , [InstrStage<1, [ALU]>]>,
InstrItinData<II_ORI , [InstrStage<1, [ALU]>]>,
InstrItinData<II_XORI , [InstrStage<1, [ALU]>]>,
InstrItinData<II_LB , [InstrStage<3, [ALU]>]>,
+ InstrItinData<II_LBE , [InstrStage<3, [ALU]>]>,
InstrItinData<II_LBU , [InstrStage<3, [ALU]>]>,
+ InstrItinData<II_LBUE , [InstrStage<3, [ALU]>]>,
InstrItinData<II_LH , [InstrStage<3, [ALU]>]>,
InstrItinData<II_LHU , [InstrStage<3, [ALU]>]>,
+ InstrItinData<II_LHUE , [InstrStage<3, [ALU]>]>,
InstrItinData<II_LW , [InstrStage<3, [ALU]>]>,
+ InstrItinData<II_LWPC , [InstrStage<3, [ALU]>]>,
InstrItinData<II_LWL , [InstrStage<3, [ALU]>]>,
+ InstrItinData<II_LWLE , [InstrStage<3, [ALU]>]>,
InstrItinData<II_LWR , [InstrStage<3, [ALU]>]>,
+ InstrItinData<II_LWRE , [InstrStage<3, [ALU]>]>,
+ InstrItinData<II_LWUPC , [InstrStage<3, [ALU]>]>,
InstrItinData<II_LD , [InstrStage<3, [ALU]>]>,
InstrItinData<II_LDL , [InstrStage<3, [ALU]>]>,
InstrItinData<II_LDR , [InstrStage<3, [ALU]>]>,
+ InstrItinData<II_LDPC , [InstrStage<3, [ALU]>]>,
+ InstrItinData<II_LL , [InstrStage<3, [ALU]>]>,
+ InstrItinData<II_LLD , [InstrStage<3, [ALU]>]>,
InstrItinData<II_RESTORE , [InstrStage<3, [ALU]>]>,
InstrItinData<II_SB , [InstrStage<1, [ALU]>]>,
InstrItinData<II_SH , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_SHE , [InstrStage<1, [ALU]>]>,
InstrItinData<II_SW , [InstrStage<1, [ALU]>]>,
InstrItinData<II_SWL , [InstrStage<1, [ALU]>]>,
InstrItinData<II_SWR , [InstrStage<1, [ALU]>]>,
InstrItinData<II_SDL , [InstrStage<1, [ALU]>]>,
InstrItinData<II_SDR , [InstrStage<1, [ALU]>]>,
InstrItinData<II_SD , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_SC , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_SCD , [InstrStage<1, [ALU]>]>,
InstrItinData<II_SAVE , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_SELCCZ , [InstrStage<1, [ALU]>]>,
InstrItinData<II_SEQ_SNE , [InstrStage<1, [ALU]>]>,
InstrItinData<II_SEQI_SNEI , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_SLTI_SLTIU , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_SLT_SLTU , [InstrStage<1, [ALU]>]>,
InstrItinData<II_B , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_BALC , [InstrStage<1, [ALU]>]>,
InstrItinData<II_BBIT , [InstrStage<1, [ALU]>]>,
InstrItinData<II_BC , [InstrStage<1, [ALU]>]>,
InstrItinData<II_BC1F , [InstrStage<1, [ALU]>]>,
InstrItinData<II_BC1FL , [InstrStage<1, [ALU]>]>,
InstrItinData<II_BC1T , [InstrStage<1, [ALU]>]>,
InstrItinData<II_BC1TL , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_BC1CCZ , [InstrStage<1, [ALU]>]>,
InstrItinData<II_BCC , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_BCCC , [InstrStage<1, [ALU]>]>,
InstrItinData<II_BCCZ , [InstrStage<1, [ALU]>]>,
InstrItinData<II_BCCZAL , [InstrStage<1, [ALU]>]>,
InstrItinData<II_BCCZALS , [InstrStage<1, [ALU]>]>,
@@ -292,25 +441,69 @@ def MipsGenericItineraries : ProcessorItineraries<[ALU, IMULDIV], [], [
InstrItinData<II_J , [InstrStage<1, [ALU]>]>,
InstrItinData<II_JAL , [InstrStage<1, [ALU]>]>,
InstrItinData<II_JALR , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_JALR_HB , [InstrStage<1, [ALU]>]>,
InstrItinData<II_JALRC , [InstrStage<1, [ALU]>]>,
InstrItinData<II_JALRS , [InstrStage<1, [ALU]>]>,
InstrItinData<II_JALS , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_JIC , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_JIALC , [InstrStage<1, [ALU]>]>,
InstrItinData<II_JR , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_JR_HB , [InstrStage<1, [ALU]>]>,
InstrItinData<II_JRADDIUSP , [InstrStage<1, [ALU]>]>,
InstrItinData<II_JRC , [InstrStage<1, [ALU]>]>,
InstrItinData<II_ReturnPseudo , [InstrStage<1, [ALU]>]>,
+ InstrItinData<IIPseudo , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_DMUH , [InstrStage<17, [IMULDIV]>]>,
+ InstrItinData<II_DMUHU , [InstrStage<17, [IMULDIV]>]>,
+ InstrItinData<II_ERET , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_DERET , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_ERETNC , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_EHB , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_SDBBP , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_SSNOP , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_SYSCALL , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_PAUSE , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_WAIT , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_EI , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_DI , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_TEQ , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_TEQI , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_TGE , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_TGEI , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_TGEIU , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_TGEU , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_TNE , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_TNEI , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_TLT , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_TLTI , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_TLTU , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_TTLTIU , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_TLBP , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_TLBR , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_TLBWI , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_TLBWR , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_TRAP , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_BREAK , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_SYNC , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_SYNCI , [InstrStage<1, [ALU]>]>,
InstrItinData<II_DMUL , [InstrStage<17, [IMULDIV]>]>,
InstrItinData<II_DMULT , [InstrStage<17, [IMULDIV]>]>,
InstrItinData<II_DMULTU , [InstrStage<17, [IMULDIV]>]>,
+ InstrItinData<II_DMULU , [InstrStage<17, [IMULDIV]>]>,
InstrItinData<II_MADD , [InstrStage<17, [IMULDIV]>]>,
InstrItinData<II_MADDU , [InstrStage<17, [IMULDIV]>]>,
InstrItinData<II_MFHI_MFLO , [InstrStage<1, [IMULDIV]>]>,
+ InstrItinData<II_MOD , [InstrStage<38, [IMULDIV]>]>,
+ InstrItinData<II_MODU , [InstrStage<38, [IMULDIV]>]>,
InstrItinData<II_MSUB , [InstrStage<17, [IMULDIV]>]>,
InstrItinData<II_MSUBU , [InstrStage<17, [IMULDIV]>]>,
InstrItinData<II_MTHI_MTLO , [InstrStage<1, [IMULDIV]>]>,
+ InstrItinData<II_MUH , [InstrStage<17, [IMULDIV]>]>,
+ InstrItinData<II_MUHU , [InstrStage<17, [IMULDIV]>]>,
InstrItinData<II_MUL , [InstrStage<17, [IMULDIV]>]>,
InstrItinData<II_MULT , [InstrStage<17, [IMULDIV]>]>,
InstrItinData<II_MULTU , [InstrStage<17, [IMULDIV]>]>,
+ InstrItinData<II_MULU , [InstrStage<17, [IMULDIV]>]>,
InstrItinData<II_MSUB , [InstrStage<17, [IMULDIV]>]>,
InstrItinData<II_MSUBU , [InstrStage<17, [IMULDIV]>]>,
InstrItinData<II_DIV , [InstrStage<38, [IMULDIV]>]>,
@@ -342,34 +535,65 @@ def MipsGenericItineraries : ProcessorItineraries<[ALU, IMULDIV], [], [
InstrItinData<II_SUB_S , [InstrStage<4, [ALU]>]>,
InstrItinData<II_MUL_S , [InstrStage<7, [ALU]>]>,
InstrItinData<II_MADD_S , [InstrStage<7, [ALU]>]>,
+ InstrItinData<II_MADDF_S , [InstrStage<7, [ALU]>]>,
InstrItinData<II_MSUB_S , [InstrStage<7, [ALU]>]>,
+ InstrItinData<II_MSUBF_S , [InstrStage<7, [ALU]>]>,
InstrItinData<II_NMADD_S , [InstrStage<7, [ALU]>]>,
InstrItinData<II_NMSUB_S , [InstrStage<7, [ALU]>]>,
InstrItinData<II_MUL_D , [InstrStage<8, [ALU]>]>,
InstrItinData<II_MADD_D , [InstrStage<8, [ALU]>]>,
+ InstrItinData<II_MADDF_D , [InstrStage<8, [ALU]>]>,
InstrItinData<II_MSUB_D , [InstrStage<8, [ALU]>]>,
+ InstrItinData<II_MSUBF_D , [InstrStage<8, [ALU]>]>,
InstrItinData<II_NMADD_D , [InstrStage<8, [ALU]>]>,
InstrItinData<II_NMSUB_D , [InstrStage<8, [ALU]>]>,
InstrItinData<II_DIV_S , [InstrStage<23, [ALU]>]>,
InstrItinData<II_DIV_D , [InstrStage<36, [ALU]>]>,
InstrItinData<II_SQRT_S , [InstrStage<54, [ALU]>]>,
InstrItinData<II_SQRT_D , [InstrStage<12, [ALU]>]>,
+ InstrItinData<II_WSBH , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_LSA , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_DLSA , [InstrStage<1, [ALU]>]>,
InstrItinData<II_LDC1 , [InstrStage<3, [ALU]>]>,
+ InstrItinData<II_LDC2 , [InstrStage<3, [ALU]>]>,
+ InstrItinData<II_LDC3 , [InstrStage<3, [ALU]>]>,
InstrItinData<II_LWC1 , [InstrStage<3, [ALU]>]>,
+ InstrItinData<II_LWC2 , [InstrStage<3, [ALU]>]>,
+ InstrItinData<II_LWC3 , [InstrStage<3, [ALU]>]>,
InstrItinData<II_LDXC1 , [InstrStage<3, [ALU]>]>,
InstrItinData<II_LWXC1 , [InstrStage<3, [ALU]>]>,
InstrItinData<II_LUXC1 , [InstrStage<3, [ALU]>]>,
InstrItinData<II_SDC1 , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_SDC2 , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_SDC3 , [InstrStage<1, [ALU]>]>,
InstrItinData<II_SWC1 , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_SWC2 , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_SWC3 , [InstrStage<1, [ALU]>]>,
InstrItinData<II_SDXC1 , [InstrStage<1, [ALU]>]>,
InstrItinData<II_SWXC1 , [InstrStage<1, [ALU]>]>,
InstrItinData<II_SUXC1 , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_DMFC0 , [InstrStage<2, [ALU]>]>,
InstrItinData<II_DMFC1 , [InstrStage<2, [ALU]>]>,
+ InstrItinData<II_DMFC2 , [InstrStage<2, [ALU]>]>,
+ InstrItinData<II_DMTC0 , [InstrStage<2, [ALU]>]>,
InstrItinData<II_DMTC1 , [InstrStage<2, [ALU]>]>,
+ InstrItinData<II_DMTC2 , [InstrStage<2, [ALU]>]>,
+ InstrItinData<II_MFC0 , [InstrStage<2, [ALU]>]>,
InstrItinData<II_MFC1 , [InstrStage<2, [ALU]>]>,
+ InstrItinData<II_MFC2 , [InstrStage<2, [ALU]>]>,
+ InstrItinData<II_MTC0 , [InstrStage<2, [ALU]>]>,
InstrItinData<II_MTC1 , [InstrStage<2, [ALU]>]>,
+ InstrItinData<II_MTC2 , [InstrStage<2, [ALU]>]>,
InstrItinData<II_MFHC1 , [InstrStage<2, [ALU]>]>,
- InstrItinData<II_MTHC1 , [InstrStage<2, [ALU]>]>
+ InstrItinData<II_MTHC1 , [InstrStage<2, [ALU]>]>,
+ InstrItinData<II_CACHE , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_PREF , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_CACHEE , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_PREFE , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_TLBINV , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_TLBINVF , [InstrStage<1, [ALU]>]>,
+ InstrItinData<II_LLE , [InstrStage<3, [ALU]>]>,
+ InstrItinData<II_SCE , [InstrStage<1, [ALU]>]>
]>;
include "MipsScheduleP5600.td"
diff --git a/lib/Target/Mips/MipsScheduleP5600.td b/lib/Target/Mips/MipsScheduleP5600.td
index d32ae4f55eaf1..cee42873c6e8c 100644
--- a/lib/Target/Mips/MipsScheduleP5600.td
+++ b/lib/Target/Mips/MipsScheduleP5600.td
@@ -13,7 +13,7 @@ def MipsP5600Model : SchedMachineModel {
int LoadLatency = 4;
int MispredictPenalty = 8; // TODO: Estimated
- let CompleteModel = 1;
+ let CompleteModel = 0;
}
let SchedModel = MipsP5600Model in {
diff --git a/lib/Target/Mips/MipsSubtarget.cpp b/lib/Target/Mips/MipsSubtarget.cpp
index 8a18b517d16be..3e7570ff46ed3 100644
--- a/lib/Target/Mips/MipsSubtarget.cpp
+++ b/lib/Target/Mips/MipsSubtarget.cpp
@@ -90,7 +90,7 @@ MipsSubtarget::MipsSubtarget(const Triple &TT, const std::string &CPU,
report_fatal_error("Code generation for MIPS-V is not implemented", false);
// Check if Architecture and ABI are compatible.
- assert(((!isGP64bit() && (isABI_O32() || isABI_EABI())) ||
+ assert(((!isGP64bit() && isABI_O32()) ||
(isGP64bit() && (isABI_N32() || isABI_N64()))) &&
"Invalid Arch & ABI pair.");
@@ -114,7 +114,7 @@ MipsSubtarget::MipsSubtarget(const Triple &TT, const std::string &CPU,
report_fatal_error(ISA + " is not compatible with the DSP ASE", false);
}
- if (NoABICalls && TM.getRelocationModel() == Reloc::PIC_)
+ if (NoABICalls && TM.isPositionIndependent())
report_fatal_error("position-independent code requires '-mabicalls'");
// Set UseSmallSection.
@@ -126,6 +126,10 @@ MipsSubtarget::MipsSubtarget(const Triple &TT, const std::string &CPU,
}
}
+bool MipsSubtarget::isPositionIndependent() const {
+ return TM.isPositionIndependent();
+}
+
/// This overrides the PostRAScheduler bit in the SchedModel for any CPU.
bool MipsSubtarget::enablePostRAScheduler() const { return true; }
@@ -164,7 +168,6 @@ Reloc::Model MipsSubtarget::getRelocationModel() const {
return TM.getRelocationModel();
}
-bool MipsSubtarget::isABI_EABI() const { return getABI().IsEABI(); }
bool MipsSubtarget::isABI_N64() const { return getABI().IsN64(); }
bool MipsSubtarget::isABI_N32() const { return getABI().IsN32(); }
bool MipsSubtarget::isABI_O32() const { return getABI().IsO32(); }
diff --git a/lib/Target/Mips/MipsSubtarget.h b/lib/Target/Mips/MipsSubtarget.h
index fbb01fe770294..38d3cee704777 100644
--- a/lib/Target/Mips/MipsSubtarget.h
+++ b/lib/Target/Mips/MipsSubtarget.h
@@ -18,10 +18,10 @@
#include "MipsFrameLowering.h"
#include "MipsISelLowering.h"
#include "MipsInstrInfo.h"
+#include "llvm/CodeGen/SelectionDAGTargetInfo.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/MC/MCInstrItineraries.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Target/TargetSelectionDAGInfo.h"
#include "llvm/Target/TargetSubtargetInfo.h"
#include <string>
@@ -81,6 +81,9 @@ class MipsSubtarget : public MipsGenSubtargetInfo {
// IsFP64bit - General-purpose registers are 64 bits wide
bool IsGP64bit;
+ // IsPTR64bit - Pointers are 64 bit wide
+ bool IsPTR64bit;
+
// HasVFPU - Processor has a vector floating point unit.
bool HasVFPU;
@@ -152,19 +155,18 @@ class MipsSubtarget : public MipsGenSubtargetInfo {
Triple TargetTriple;
- const TargetSelectionDAGInfo TSInfo;
+ const SelectionDAGTargetInfo TSInfo;
std::unique_ptr<const MipsInstrInfo> InstrInfo;
std::unique_ptr<const MipsFrameLowering> FrameLowering;
std::unique_ptr<const MipsTargetLowering> TLInfo;
public:
+ bool isPositionIndependent() const;
/// This overrides the PostRAScheduler bit in the SchedModel for each CPU.
bool enablePostRAScheduler() const override;
void getCriticalPathRCs(RegClassVector &CriticalPathRCs) const override;
CodeGenOpt::Level getOptLevelToEnablePostRAScheduler() const override;
- /// Only O32 and EABI supported right now.
- bool isABI_EABI() const;
bool isABI_N64() const;
bool isABI_N32() const;
bool isABI_O32() const;
@@ -225,6 +227,8 @@ public:
bool isGP64bit() const { return IsGP64bit; }
bool isGP32bit() const { return !IsGP64bit; }
unsigned getGPRSizeInBytes() const { return isGP64bit() ? 8 : 4; }
+ bool isPTR64bit() const { return IsPTR64bit; }
+ bool isPTR32bit() const { return !IsPTR64bit; }
bool isSingleFloat() const { return IsSingleFloat; }
bool hasVFPU() const { return HasVFPU; }
bool inMips16Mode() const { return InMips16Mode; }
@@ -290,7 +294,7 @@ public:
void setHelperClassesMips16();
void setHelperClassesMipsSE();
- const TargetSelectionDAGInfo *getSelectionDAGInfo() const override {
+ const SelectionDAGTargetInfo *getSelectionDAGInfo() const override {
return &TSInfo;
}
const MipsInstrInfo *getInstrInfo() const override { return InstrInfo.get(); }
diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp
index 3e638720e8392..c248c3a50ac8d 100644
--- a/lib/Target/Mips/MipsTargetMachine.cpp
+++ b/lib/Target/Mips/MipsTargetMachine.cpp
@@ -26,6 +26,7 @@
#include "MipsTargetObjectFile.h"
#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/CodeGen/Passes.h"
+#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/LegacyPassManager.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/TargetRegistry.h"
@@ -77,6 +78,13 @@ static std::string computeDataLayout(const Triple &TT, StringRef CPU,
return Ret;
}
+static Reloc::Model getEffectiveRelocModel(CodeModel::Model CM,
+ Optional<Reloc::Model> RM) {
+ if (!RM.hasValue() || CM == CodeModel::JITDefault)
+ return Reloc::Static;
+ return *RM;
+}
+
// On function prologue, the stack is created by decrementing
// its pointer. Once decremented, all references are done with positive
// offset from the stack/frame pointer, using StackGrowsUp enables
@@ -85,10 +93,12 @@ static std::string computeDataLayout(const Triple &TT, StringRef CPU,
MipsTargetMachine::MipsTargetMachine(const Target &T, const Triple &TT,
StringRef CPU, StringRef FS,
const TargetOptions &Options,
- Reloc::Model RM, CodeModel::Model CM,
- CodeGenOpt::Level OL, bool isLittle)
+ Optional<Reloc::Model> RM,
+ CodeModel::Model CM, CodeGenOpt::Level OL,
+ bool isLittle)
: LLVMTargetMachine(T, computeDataLayout(TT, CPU, Options, isLittle), TT,
- CPU, FS, Options, RM, CM, OL),
+ CPU, FS, Options, getEffectiveRelocModel(CM, RM), CM,
+ OL),
isLittle(isLittle), TLOF(make_unique<MipsTargetObjectFile>()),
ABI(MipsABIInfo::computeTargetABI(TT, CPU, Options.MCOptions)),
Subtarget(nullptr), DefaultSubtarget(TT, CPU, FS, isLittle, *this),
@@ -107,7 +117,8 @@ void MipsebTargetMachine::anchor() { }
MipsebTargetMachine::MipsebTargetMachine(const Target &T, const Triple &TT,
StringRef CPU, StringRef FS,
const TargetOptions &Options,
- Reloc::Model RM, CodeModel::Model CM,
+ Optional<Reloc::Model> RM,
+ CodeModel::Model CM,
CodeGenOpt::Level OL)
: MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, false) {}
@@ -116,7 +127,8 @@ void MipselTargetMachine::anchor() { }
MipselTargetMachine::MipselTargetMachine(const Target &T, const Triple &TT,
StringRef CPU, StringRef FS,
const TargetOptions &Options,
- Reloc::Model RM, CodeModel::Model CM,
+ Optional<Reloc::Model> RM,
+ CodeModel::Model CM,
CodeGenOpt::Level OL)
: MipsTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL, true) {}
@@ -217,8 +229,8 @@ void MipsPassConfig::addIRPasses() {
// the ISelDag to gen Mips code.
bool MipsPassConfig::addInstSelector() {
addPass(createMipsModuleISelDagPass(getMipsTargetMachine()));
- addPass(createMips16ISelDag(getMipsTargetMachine()));
- addPass(createMipsSEISelDag(getMipsTargetMachine()));
+ addPass(createMips16ISelDag(getMipsTargetMachine(), getOptLevel()));
+ addPass(createMipsSEISelDag(getMipsTargetMachine(), getOptLevel()));
return false;
}
@@ -250,7 +262,13 @@ TargetIRAnalysis MipsTargetMachine::getTargetIRAnalysis() {
// print out the code after the passes.
void MipsPassConfig::addPreEmitPass() {
MipsTargetMachine &TM = getMipsTargetMachine();
+
+ // The delay slot filler pass can potientially create forbidden slot (FS)
+ // hazards for MIPSR6 which the hazard schedule pass (HSP) will fix. Any
+ // (new) pass that creates compact branches after the HSP must handle FS
+ // hazards itself or be pipelined before the HSP.
addPass(createMipsDelaySlotFillerPass(TM));
+ addPass(createMipsHazardSchedule());
addPass(createMipsLongBranchPass(TM));
- addPass(createMipsConstantIslandPass(TM));
+ addPass(createMipsConstantIslandPass());
}
diff --git a/lib/Target/Mips/MipsTargetMachine.h b/lib/Target/Mips/MipsTargetMachine.h
index 38b2ecff7d7f1..e4cf17e2abd85 100644
--- a/lib/Target/Mips/MipsTargetMachine.h
+++ b/lib/Target/Mips/MipsTargetMachine.h
@@ -40,8 +40,9 @@ class MipsTargetMachine : public LLVMTargetMachine {
public:
MipsTargetMachine(const Target &T, const Triple &TT, StringRef CPU,
- StringRef FS, const TargetOptions &Options, Reloc::Model RM,
- CodeModel::Model CM, CodeGenOpt::Level OL, bool isLittle);
+ StringRef FS, const TargetOptions &Options,
+ Optional<Reloc::Model> RM, CodeModel::Model CM,
+ CodeGenOpt::Level OL, bool isLittle);
~MipsTargetMachine() override;
TargetIRAnalysis getTargetIRAnalysis() override;
@@ -68,25 +69,25 @@ public:
const MipsABIInfo &getABI() const { return ABI; }
};
-/// MipsebTargetMachine - Mips32/64 big endian target machine.
+/// Mips32/64 big endian target machine.
///
class MipsebTargetMachine : public MipsTargetMachine {
virtual void anchor();
public:
MipsebTargetMachine(const Target &T, const Triple &TT, StringRef CPU,
StringRef FS, const TargetOptions &Options,
- Reloc::Model RM, CodeModel::Model CM,
+ Optional<Reloc::Model> RM, CodeModel::Model CM,
CodeGenOpt::Level OL);
};
-/// MipselTargetMachine - Mips32/64 little endian target machine.
+/// Mips32/64 little endian target machine.
///
class MipselTargetMachine : public MipsTargetMachine {
virtual void anchor();
public:
MipselTargetMachine(const Target &T, const Triple &TT, StringRef CPU,
StringRef FS, const TargetOptions &Options,
- Reloc::Model RM, CodeModel::Model CM,
+ Optional<Reloc::Model> RM, CodeModel::Model CM,
CodeGenOpt::Level OL);
};
diff --git a/lib/Target/Mips/MipsTargetObjectFile.cpp b/lib/Target/Mips/MipsTargetObjectFile.cpp
index 146f33bda249f..3bd4567e37922 100644
--- a/lib/Target/Mips/MipsTargetObjectFile.cpp
+++ b/lib/Target/Mips/MipsTargetObjectFile.cpp
@@ -41,10 +41,12 @@ void MipsTargetObjectFile::Initialize(MCContext &Ctx, const TargetMachine &TM){
InitializeELF(TM.Options.UseInitArray);
SmallDataSection = getContext().getELFSection(
- ".sdata", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC);
+ ".sdata", ELF::SHT_PROGBITS,
+ ELF::SHF_WRITE | ELF::SHF_ALLOC | ELF::SHF_MIPS_GPREL);
SmallBSSSection = getContext().getELFSection(".sbss", ELF::SHT_NOBITS,
- ELF::SHF_WRITE | ELF::SHF_ALLOC);
+ ELF::SHF_WRITE | ELF::SHF_ALLOC |
+ ELF::SHF_MIPS_GPREL);
this->TM = &static_cast<const MipsTargetMachine &>(TM);
}
@@ -106,7 +108,7 @@ IsGlobalInSmallSectionImpl(const GlobalValue *GV,
GV->hasCommonLinkage()))
return false;
- Type *Ty = GV->getType()->getElementType();
+ Type *Ty = GV->getValueType();
return IsInSmallSection(
GV->getParent()->getDataLayout().getTypeAllocSize(Ty));
}
@@ -138,11 +140,13 @@ bool MipsTargetObjectFile::IsConstantInSmallSection(
}
/// Return true if this constant should be placed into small data section.
-MCSection *MipsTargetObjectFile::getSectionForConstant(
- const DataLayout &DL, SectionKind Kind, const Constant *C) const {
+MCSection *MipsTargetObjectFile::getSectionForConstant(const DataLayout &DL,
+ SectionKind Kind,
+ const Constant *C,
+ unsigned &Align) const {
if (IsConstantInSmallSection(DL, C, *TM))
return SmallDataSection;
// Otherwise, we work the same as ELF.
- return TargetLoweringObjectFileELF::getSectionForConstant(DL, Kind, C);
+ return TargetLoweringObjectFileELF::getSectionForConstant(DL, Kind, C, Align);
}
diff --git a/lib/Target/Mips/MipsTargetObjectFile.h b/lib/Target/Mips/MipsTargetObjectFile.h
index ba04343bad87a..9840769aff695 100644
--- a/lib/Target/Mips/MipsTargetObjectFile.h
+++ b/lib/Target/Mips/MipsTargetObjectFile.h
@@ -40,7 +40,8 @@ class MipsTargetMachine;
const TargetMachine &TM) const;
MCSection *getSectionForConstant(const DataLayout &DL, SectionKind Kind,
- const Constant *C) const override;
+ const Constant *C,
+ unsigned &Align) const override;
};
} // end namespace llvm
diff --git a/lib/Target/Mips/MipsTargetStreamer.h b/lib/Target/Mips/MipsTargetStreamer.h
index b3222f5d89ef0..41ebe411b98d9 100644
--- a/lib/Target/Mips/MipsTargetStreamer.h
+++ b/lib/Target/Mips/MipsTargetStreamer.h
@@ -13,6 +13,7 @@
#include "MCTargetDesc/MipsABIFlagsSection.h"
#include "MCTargetDesc/MipsABIInfo.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/MC/MCELFStreamer.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCStreamer.h"
@@ -24,8 +25,12 @@ struct MipsABIFlagsSection;
class MipsTargetStreamer : public MCTargetStreamer {
public:
MipsTargetStreamer(MCStreamer &S);
+
+ virtual void setPic(bool Value) {}
+
virtual void emitDirectiveSetMicroMips();
virtual void emitDirectiveSetNoMicroMips();
+ virtual void setUsesMicroMips();
virtual void emitDirectiveSetMips16();
virtual void emitDirectiveSetNoMips16();
@@ -78,8 +83,9 @@ public:
// PIC support
virtual void emitDirectiveCpLoad(unsigned RegNo);
- virtual void emitDirectiveCpRestore(SmallVector<MCInst, 3> &StoreInsts,
- int Offset);
+ virtual bool emitDirectiveCpRestore(int Offset,
+ function_ref<unsigned()> GetATReg,
+ SMLoc IDLoc, const MCSubtargetInfo *STI);
virtual void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
const MCSymbol &Sym, bool IsReg);
virtual void emitDirectiveCpreturn(unsigned SaveLocation,
@@ -94,6 +100,54 @@ public:
virtual void emitDirectiveSetOddSPReg();
virtual void emitDirectiveSetNoOddSPReg();
+ void emitR(unsigned Opcode, unsigned Reg0, SMLoc IDLoc,
+ const MCSubtargetInfo *STI);
+ void emitII(unsigned Opcode, int16_t Imm1, int16_t Imm2, SMLoc IDLoc,
+ const MCSubtargetInfo *STI);
+ void emitRX(unsigned Opcode, unsigned Reg0, MCOperand Op1, SMLoc IDLoc,
+ const MCSubtargetInfo *STI);
+ void emitRI(unsigned Opcode, unsigned Reg0, int32_t Imm, SMLoc IDLoc,
+ const MCSubtargetInfo *STI);
+ void emitRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, SMLoc IDLoc,
+ const MCSubtargetInfo *STI);
+ void emitRRX(unsigned Opcode, unsigned Reg0, unsigned Reg1, MCOperand Op2,
+ SMLoc IDLoc, const MCSubtargetInfo *STI);
+ void emitRRR(unsigned Opcode, unsigned Reg0, unsigned Reg1, unsigned Reg2,
+ SMLoc IDLoc, const MCSubtargetInfo *STI);
+ void emitRRI(unsigned Opcode, unsigned Reg0, unsigned Reg1, int16_t Imm,
+ SMLoc IDLoc, const MCSubtargetInfo *STI);
+ void emitAddu(unsigned DstReg, unsigned SrcReg, unsigned TrgReg, bool Is64Bit,
+ const MCSubtargetInfo *STI);
+ void emitDSLL(unsigned DstReg, unsigned SrcReg, int16_t ShiftAmount,
+ SMLoc IDLoc, const MCSubtargetInfo *STI);
+ void emitEmptyDelaySlot(bool hasShortDelaySlot, SMLoc IDLoc,
+ const MCSubtargetInfo *STI);
+ void emitNop(SMLoc IDLoc, const MCSubtargetInfo *STI);
+
+ /// Emit a store instruction with an offset. If the offset is out of range
+ /// then it will be synthesized using the assembler temporary.
+ ///
+ /// GetATReg() is a callback that can be used to obtain the current assembler
+ /// temporary and is only called when the assembler temporary is required. It
+ /// must handle the case where no assembler temporary is available (typically
+ /// by reporting an error).
+ void emitStoreWithImmOffset(unsigned Opcode, unsigned SrcReg,
+ unsigned BaseReg, int64_t Offset,
+ function_ref<unsigned()> GetATReg, SMLoc IDLoc,
+ const MCSubtargetInfo *STI);
+ void emitStoreWithSymOffset(unsigned Opcode, unsigned SrcReg,
+ unsigned BaseReg, MCOperand &HiOperand,
+ MCOperand &LoOperand, unsigned ATReg, SMLoc IDLoc,
+ const MCSubtargetInfo *STI);
+ void emitLoadWithImmOffset(unsigned Opcode, unsigned DstReg, unsigned BaseReg,
+ int64_t Offset, unsigned TmpReg, SMLoc IDLoc,
+ const MCSubtargetInfo *STI);
+ void emitLoadWithSymOffset(unsigned Opcode, unsigned DstReg, unsigned BaseReg,
+ MCOperand &HiOperand, MCOperand &LoOperand,
+ unsigned ATReg, SMLoc IDLoc,
+ const MCSubtargetInfo *STI);
+ void emitGPRestore(int Offset, SMLoc IDLoc, const MCSubtargetInfo *STI);
+
void forbidModuleDirective() { ModuleDirectiveAllowed = false; }
void reallowModuleDirective() { ModuleDirectiveAllowed = true; }
bool isModuleDirectiveAllowed() { return ModuleDirectiveAllowed; }
@@ -193,8 +247,16 @@ public:
// PIC support
void emitDirectiveCpLoad(unsigned RegNo) override;
- void emitDirectiveCpRestore(SmallVector<MCInst, 3> &StoreInsts,
- int Offset) override;
+
+ /// Emit a .cprestore directive. If the offset is out of range then it will
+ /// be synthesized using the assembler temporary.
+ ///
+ /// GetATReg() is a callback that can be used to obtain the current assembler
+ /// temporary and is only called when the assembler temporary is required. It
+ /// must handle the case where no assembler temporary is available (typically
+ /// by reporting an error).
+ bool emitDirectiveCpRestore(int Offset, function_ref<unsigned()> GetATReg,
+ SMLoc IDLoc, const MCSubtargetInfo *STI) override;
void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
const MCSymbol &Sym, bool IsReg) override;
void emitDirectiveCpreturn(unsigned SaveLocation,
@@ -221,12 +283,15 @@ public:
MCELFStreamer &getStreamer();
MipsTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI);
+ void setPic(bool Value) override { Pic = Value; }
+
void emitLabel(MCSymbol *Symbol) override;
void emitAssignment(MCSymbol *Symbol, const MCExpr *Value) override;
void finish() override;
void emitDirectiveSetMicroMips() override;
void emitDirectiveSetNoMicroMips() override;
+ void setUsesMicroMips() override;
void emitDirectiveSetMips16() override;
void emitDirectiveSetNoReorder() override;
@@ -246,8 +311,8 @@ public:
// PIC support
void emitDirectiveCpLoad(unsigned RegNo) override;
- void emitDirectiveCpRestore(SmallVector<MCInst, 3> &StoreInsts,
- int Offset) override;
+ bool emitDirectiveCpRestore(int Offset, function_ref<unsigned()> GetATReg,
+ SMLoc IDLoc, const MCSubtargetInfo *STI) override;
void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
const MCSymbol &Sym, bool IsReg) override;
void emitDirectiveCpreturn(unsigned SaveLocation,
diff --git a/lib/Target/Mips/TargetInfo/Makefile b/lib/Target/Mips/TargetInfo/Makefile
deleted file mode 100644
index 32f4e1695b1d7..0000000000000
--- a/lib/Target/Mips/TargetInfo/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-##===- lib/Target/Mips/TargetInfo/Makefile -----------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-LEVEL = ../../../..
-LIBRARYNAME = LLVMMipsInfo
-
-# Hack: we need to include 'main' target directory to grab private headers
-CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
-
-include $(LEVEL)/Makefile.common