aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target/Mips
diff options
context:
space:
mode:
authorStephen Hines <srhines@google.com>2014-05-29 02:49:00 -0700
committerStephen Hines <srhines@google.com>2014-05-29 02:49:00 -0700
commitdce4a407a24b04eebc6a376f8e62b41aaa7b071f (patch)
treedcebc53f2b182f145a2e659393bf9a0472cedf23 /lib/Target/Mips
parent220b921aed042f9e520c26cffd8282a94c66c3d5 (diff)
downloadexternal_llvm-dce4a407a24b04eebc6a376f8e62b41aaa7b071f.zip
external_llvm-dce4a407a24b04eebc6a376f8e62b41aaa7b071f.tar.gz
external_llvm-dce4a407a24b04eebc6a376f8e62b41aaa7b071f.tar.bz2
Update LLVM for 3.5 rebase (r209712).
Change-Id: I149556c940fb7dc92d075273c87ff584f400941f
Diffstat (limited to 'lib/Target/Mips')
-rw-r--r--lib/Target/Mips/Android.mk1
-rw-r--r--lib/Target/Mips/AsmParser/LLVMBuild.txt2
-rw-r--r--lib/Target/Mips/AsmParser/MipsAsmParser.cpp273
-rw-r--r--lib/Target/Mips/CMakeLists.txt2
-rw-r--r--lib/Target/Mips/Disassembler/LLVMBuild.txt2
-rw-r--r--lib/Target/Mips/Disassembler/MipsDisassembler.cpp370
-rw-r--r--lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp5
-rw-r--r--lib/Target/Mips/InstPrinter/MipsInstPrinter.h6
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp92
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h18
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp12
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h12
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h2
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp85
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h27
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp3
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsMCExpr.h10
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h2
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp13
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp7
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp153
-rw-r--r--lib/Target/Mips/Makefile2
-rw-r--r--lib/Target/Mips/MicroMipsInstrFPU.td14
-rw-r--r--lib/Target/Mips/MicroMipsInstrInfo.td23
-rw-r--r--lib/Target/Mips/Mips.td101
-rw-r--r--lib/Target/Mips/Mips16FrameLowering.cpp2
-rw-r--r--lib/Target/Mips/Mips16FrameLowering.h20
-rw-r--r--lib/Target/Mips/Mips16HardFloat.cpp14
-rw-r--r--lib/Target/Mips/Mips16HardFloat.h4
-rw-r--r--lib/Target/Mips/Mips16HardFloatInfo.cpp4
-rw-r--r--lib/Target/Mips/Mips16ISelDAGToDAG.cpp19
-rw-r--r--lib/Target/Mips/Mips16ISelDAGToDAG.h10
-rw-r--r--lib/Target/Mips/Mips16ISelLowering.cpp34
-rw-r--r--lib/Target/Mips/Mips16ISelLowering.h21
-rw-r--r--lib/Target/Mips/Mips16InstrInfo.cpp1
-rw-r--r--lib/Target/Mips/Mips16InstrInfo.h50
-rw-r--r--lib/Target/Mips/Mips16RegisterInfo.cpp2
-rw-r--r--lib/Target/Mips/Mips16RegisterInfo.h16
-rw-r--r--lib/Target/Mips/Mips32r6InstrFormats.td386
-rw-r--r--lib/Target/Mips/Mips32r6InstrInfo.td583
-rw-r--r--lib/Target/Mips/Mips64InstrInfo.td257
-rw-r--r--lib/Target/Mips/Mips64r6InstrInfo.td88
-rw-r--r--lib/Target/Mips/MipsAsmPrinter.cpp40
-rw-r--r--lib/Target/Mips/MipsAsmPrinter.h32
-rw-r--r--lib/Target/Mips/MipsCallingConv.td4
-rw-r--r--lib/Target/Mips/MipsCodeEmitter.cpp46
-rw-r--r--lib/Target/Mips/MipsCondMov.td138
-rw-r--r--lib/Target/Mips/MipsConstantIslandPass.cpp20
-rw-r--r--lib/Target/Mips/MipsDelaySlotFiller.cpp78
-rw-r--r--lib/Target/Mips/MipsFastISel.cpp283
-rw-r--r--lib/Target/Mips/MipsFrameLowering.cpp2
-rw-r--r--lib/Target/Mips/MipsFrameLowering.h2
-rw-r--r--lib/Target/Mips/MipsISelDAGToDAG.cpp12
-rw-r--r--lib/Target/Mips/MipsISelDAGToDAG.h12
-rw-r--r--lib/Target/Mips/MipsISelLowering.cpp296
-rw-r--r--lib/Target/Mips/MipsISelLowering.h103
-rw-r--r--lib/Target/Mips/MipsInstrFPU.td356
-rw-r--r--lib/Target/Mips/MipsInstrFormats.td33
-rw-r--r--lib/Target/Mips/MipsInstrInfo.cpp8
-rw-r--r--lib/Target/Mips/MipsInstrInfo.h50
-rw-r--r--lib/Target/Mips/MipsInstrInfo.td412
-rw-r--r--lib/Target/Mips/MipsJITInfo.cpp3
-rw-r--r--lib/Target/Mips/MipsJITInfo.h14
-rw-r--r--lib/Target/Mips/MipsLongBranch.cpp96
-rw-r--r--lib/Target/Mips/MipsMCInstLower.cpp68
-rw-r--r--lib/Target/Mips/MipsMCInstLower.h8
-rw-r--r--lib/Target/Mips/MipsMSAInstrInfo.td90
-rw-r--r--lib/Target/Mips/MipsMachineFunction.cpp7
-rw-r--r--lib/Target/Mips/MipsMachineFunction.h8
-rw-r--r--lib/Target/Mips/MipsModuleISelDAGToDAG.cpp2
-rw-r--r--lib/Target/Mips/MipsModuleISelDAGToDAG.h8
-rw-r--r--lib/Target/Mips/MipsOptimizePICCall.cpp46
-rw-r--r--lib/Target/Mips/MipsOs16.cpp3
-rw-r--r--lib/Target/Mips/MipsOs16.h4
-rw-r--r--lib/Target/Mips/MipsRegisterInfo.cpp16
-rw-r--r--lib/Target/Mips/MipsRegisterInfo.h21
-rw-r--r--lib/Target/Mips/MipsRegisterInfo.td16
-rw-r--r--lib/Target/Mips/MipsSEFrameLowering.cpp3
-rw-r--r--lib/Target/Mips/MipsSEFrameLowering.h14
-rw-r--r--lib/Target/Mips/MipsSEISelDAGToDAG.cpp15
-rw-r--r--lib/Target/Mips/MipsSEISelDAGToDAG.h66
-rw-r--r--lib/Target/Mips/MipsSEISelLowering.cpp185
-rw-r--r--lib/Target/Mips/MipsSEISelLowering.h36
-rw-r--r--lib/Target/Mips/MipsSEInstrInfo.cpp2
-rw-r--r--lib/Target/Mips/MipsSEInstrInfo.h48
-rw-r--r--lib/Target/Mips/MipsSERegisterInfo.cpp4
-rw-r--r--lib/Target/Mips/MipsSERegisterInfo.h12
-rw-r--r--lib/Target/Mips/MipsSelectionDAGInfo.cpp3
-rw-r--r--lib/Target/Mips/MipsSubtarget.cpp57
-rw-r--r--lib/Target/Mips/MipsSubtarget.h61
-rw-r--r--lib/Target/Mips/MipsTargetMachine.cpp12
-rw-r--r--lib/Target/Mips/MipsTargetMachine.h46
-rw-r--r--lib/Target/Mips/MipsTargetStreamer.h134
93 files changed, 4260 insertions, 1523 deletions
diff --git a/lib/Target/Mips/Android.mk b/lib/Target/Mips/Android.mk
index 74b8a3b..4e8831c 100644
--- a/lib/Target/Mips/Android.mk
+++ b/lib/Target/Mips/Android.mk
@@ -24,6 +24,7 @@ mips_codegen_SRC_FILES := \
MipsCodeEmitter.cpp \
MipsConstantIslandPass.cpp \
MipsDelaySlotFiller.cpp \
+ MipsFastISel.cpp \
MipsFrameLowering.cpp \
MipsInstrInfo.cpp \
MipsISelDAGToDAG.cpp \
diff --git a/lib/Target/Mips/AsmParser/LLVMBuild.txt b/lib/Target/Mips/AsmParser/LLVMBuild.txt
index e7ca243..dd8e3cf 100644
--- a/lib/Target/Mips/AsmParser/LLVMBuild.txt
+++ b/lib/Target/Mips/AsmParser/LLVMBuild.txt
@@ -19,5 +19,5 @@
type = Library
name = MipsAsmParser
parent = Mips
-required_libraries = MC MCParser Support MipsDesc MipsInfo
+required_libraries = MC MCParser MipsDesc MipsInfo Support
add_to_library_groups = Mips
diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
index 911a119..86fd386 100644
--- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -29,6 +29,8 @@
using namespace llvm;
+#define DEBUG_TYPE "mips-asm-parser"
+
namespace llvm {
class MCInstrInfo;
}
@@ -73,10 +75,10 @@ class MipsAsmParser : public MCTargetAsmParser {
bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
SmallVectorImpl<MCParsedAsmOperand *> &Operands,
MCStreamer &Out, unsigned &ErrorInfo,
- bool MatchingInlineAsm);
+ bool MatchingInlineAsm) override;
/// Parse a register as used in CFI directives
- bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
+ bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
bool ParseParenSuffix(StringRef Name,
SmallVectorImpl<MCParsedAsmOperand *> &Operands);
@@ -84,11 +86,11 @@ class MipsAsmParser : public MCTargetAsmParser {
bool ParseBracketSuffix(StringRef Name,
SmallVectorImpl<MCParsedAsmOperand *> &Operands);
- bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
- SMLoc NameLoc,
- SmallVectorImpl<MCParsedAsmOperand *> &Operands);
+ bool
+ ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
+ SmallVectorImpl<MCParsedAsmOperand *> &Operands) override;
- bool ParseDirective(AsmToken DirectiveID);
+ bool ParseDirective(AsmToken DirectiveID) override;
MipsAsmParser::OperandMatchResultTy
parseMemOperand(SmallVectorImpl<MCParsedAsmOperand *> &Operands);
@@ -135,6 +137,7 @@ class MipsAsmParser : public MCTargetAsmParser {
SmallVectorImpl<MCInst> &Instructions, bool isLoad,
bool isImmOpnd);
bool reportParseError(StringRef ErrorMsg);
+ bool reportParseError(SMLoc Loc, StringRef ErrorMsg);
bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
bool parseRelocOperand(const MCExpr *&Res);
@@ -143,7 +146,9 @@ class MipsAsmParser : public MCTargetAsmParser {
bool isEvaluated(const MCExpr *Expr);
bool parseSetFeature(uint64_t Feature);
+ bool parseDirectiveCPLoad(SMLoc Loc);
bool parseDirectiveCPSetup();
+ bool parseDirectiveNaN();
bool parseDirectiveSet();
bool parseDirectiveOption();
@@ -212,21 +217,22 @@ class MipsAsmParser : public MCTargetAsmParser {
void setFeatureBits(unsigned Feature, StringRef FeatureString) {
if (!(STI.getFeatureBits() & Feature)) {
- setAvailableFeatures(ComputeAvailableFeatures(
- STI.ToggleFeature(FeatureString)));
+ setAvailableFeatures(
+ ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
}
}
void clearFeatureBits(unsigned Feature, StringRef FeatureString) {
if (STI.getFeatureBits() & Feature) {
- setAvailableFeatures(ComputeAvailableFeatures(
- STI.ToggleFeature(FeatureString)));
+ setAvailableFeatures(
+ ComputeAvailableFeatures(STI.ToggleFeature(FeatureString)));
}
}
public:
MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser,
- const MCInstrInfo &MII)
+ const MCInstrInfo &MII,
+ const MCTargetOptions &Options)
: MCTargetAsmParser(), STI(sti), Parser(parser) {
// Initialize the set of available features.
setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
@@ -266,11 +272,12 @@ public:
/// context).
RegKind_CCR = 128, /// CCR
RegKind_HWRegs = 256, /// HWRegs
+ RegKind_COP3 = 512, /// COP3
/// Potentially any (e.g. $1)
RegKind_Numeric = RegKind_GPR | RegKind_FGR | RegKind_FCC | RegKind_MSA128 |
RegKind_MSACtrl | RegKind_COP2 | RegKind_ACC |
- RegKind_CCR | RegKind_HWRegs
+ RegKind_CCR | RegKind_HWRegs | RegKind_COP3
};
private:
@@ -422,6 +429,14 @@ private:
return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
}
+ /// Coerce the register to COP3 and return the real register for the
+ /// current target.
+ unsigned getCOP3Reg() const {
+ assert(isRegIdx() && (RegIdx.Kind & RegKind_COP3) && "Invalid access!");
+ unsigned ClassID = Mips::COP3RegClassID;
+ return RegIdx.RegInfo->getRegClass(ClassID).getRegister(RegIdx.Index);
+ }
+
/// Coerce the register to ACC64DSP and return the real register for the
/// current target.
unsigned getACC64DSPReg() const {
@@ -465,7 +480,7 @@ private:
public:
void addExpr(MCInst &Inst, const MCExpr *Expr) const {
// Add as immediate when possible. Null MCExpr = 0.
- if (Expr == 0)
+ if (!Expr)
Inst.addOperand(MCOperand::CreateImm(0));
else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
@@ -533,6 +548,11 @@ public:
Inst.addOperand(MCOperand::CreateReg(getCOP2Reg()));
}
+ void addCOP3AsmRegOperands(MCInst &Inst, unsigned N) const {
+ assert(N == 1 && "Invalid number of operands!");
+ Inst.addOperand(MCOperand::CreateReg(getCOP3Reg()));
+ }
+
void addACC64DSPAsmRegOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
Inst.addOperand(MCOperand::CreateReg(getACC64DSPReg()));
@@ -573,7 +593,7 @@ public:
addExpr(Inst, Expr);
}
- bool isReg() const {
+ 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)
@@ -582,16 +602,16 @@ public:
return Kind == k_PhysRegister;
}
bool isRegIdx() const { return Kind == k_RegisterIndex; }
- bool isImm() const { return Kind == k_Immediate; }
+ bool isImm() const override { return Kind == k_Immediate; }
bool isConstantImm() const {
return isImm() && dyn_cast<MCConstantExpr>(getImm());
}
- bool isToken() const {
+ bool isToken() const override {
// Note: It's not possible to pretend that other operand kinds are tokens.
// The matcher emitter checks tokens first.
return Kind == k_Token;
}
- bool isMem() const { return Kind == k_Memory; }
+ bool isMem() const override { return Kind == k_Memory; }
bool isInvNum() const { return Kind == k_Immediate; }
bool isLSAImm() const {
if (!isConstantImm())
@@ -605,7 +625,7 @@ public:
return StringRef(Tok.Data, Tok.Length);
}
- unsigned getReg() const {
+ 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.
if (Kind == k_RegisterIndex && RegIdx.Index == 0 &&
@@ -744,6 +764,9 @@ public:
bool isCOP2AsmReg() const {
return isRegIdx() && RegIdx.Kind & RegKind_COP2 && RegIdx.Index <= 31;
}
+ bool isCOP3AsmReg() const {
+ return isRegIdx() && RegIdx.Kind & RegKind_COP3 && RegIdx.Index <= 31;
+ }
bool isMSA128AsmReg() const {
return isRegIdx() && RegIdx.Kind & RegKind_MSA128 && RegIdx.Index <= 31;
}
@@ -752,11 +775,25 @@ public:
}
/// getStartLoc - Get the location of the first token of this operand.
- SMLoc getStartLoc() const { return StartLoc; }
+ SMLoc getStartLoc() const override { return StartLoc; }
/// getEndLoc - Get the location of the last token of this operand.
- SMLoc getEndLoc() const { return EndLoc; }
+ SMLoc getEndLoc() const override { return EndLoc; }
- virtual void print(raw_ostream &OS) const {
+ virtual ~MipsOperand() {
+ switch (Kind) {
+ case k_Immediate:
+ break;
+ case k_Memory:
+ delete Mem.Base;
+ break;
+ case k_PhysRegister:
+ case k_RegisterIndex:
+ case k_Token:
+ break;
+ }
+ }
+
+ void print(raw_ostream &OS) const override {
switch (Kind) {
case k_Immediate:
OS << "Imm<";
@@ -906,10 +943,6 @@ bool MipsAsmParser::needsExpansion(MCInst &Inst) {
case Mips::LoadImm32Reg:
case Mips::LoadAddr32Imm:
case Mips::LoadAddr32Reg:
- case Mips::SUBi:
- case Mips::SUBiu:
- case Mips::DSUBi:
- case Mips::DSUBiu:
return true;
default:
return false;
@@ -925,30 +958,6 @@ void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
return expandLoadAddressImm(Inst, IDLoc, Instructions);
case Mips::LoadAddr32Reg:
return expandLoadAddressReg(Inst, IDLoc, Instructions);
- case Mips::SUBi:
- Instructions.push_back(MCInstBuilder(Mips::ADDi)
- .addReg(Inst.getOperand(0).getReg())
- .addReg(Inst.getOperand(1).getReg())
- .addImm(-Inst.getOperand(2).getImm()));
- return;
- case Mips::SUBiu:
- Instructions.push_back(MCInstBuilder(Mips::ADDiu)
- .addReg(Inst.getOperand(0).getReg())
- .addReg(Inst.getOperand(1).getReg())
- .addImm(-Inst.getOperand(2).getImm()));
- return;
- case Mips::DSUBi:
- Instructions.push_back(MCInstBuilder(Mips::DADDi)
- .addReg(Inst.getOperand(0).getReg())
- .addReg(Inst.getOperand(1).getReg())
- .addImm(-Inst.getOperand(2).getImm()));
- return;
- case Mips::DSUBiu:
- Instructions.push_back(MCInstBuilder(Mips::DADDiu)
- .addReg(Inst.getOperand(0).getReg())
- .addReg(Inst.getOperand(1).getReg())
- .addImm(-Inst.getOperand(2).getImm()));
- return;
}
}
@@ -1586,6 +1595,8 @@ bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
RegNo = isGP64() ? Operand.getGPR64Reg() : Operand.getGPR32Reg();
}
+ delete &Operand;
+
return (RegNo == (unsigned)-1);
}
@@ -1624,7 +1635,7 @@ bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
SmallVectorImpl<MCParsedAsmOperand *> &Operands) {
DEBUG(dbgs() << "parseMemOperand\n");
- const MCExpr *IdVal = 0;
+ const MCExpr *IdVal = nullptr;
SMLoc S;
bool isParenExpr = false;
MipsAsmParser::OperandMatchResultTy Res = MatchOperand_NoMatch;
@@ -1654,6 +1665,7 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
// Zero register assumed, add a memory operand with ZERO as its base.
+ // "Base" will be managed by k_Memory.
MipsOperand *Base = MipsOperand::CreateGPRReg(
0, getContext().getRegisterInfo(), S, E, *this);
Operands.push_back(MipsOperand::CreateMem(Base, IdVal, S, E, *this));
@@ -1679,12 +1691,13 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
Parser.Lex(); // Eat the ')' token.
- if (IdVal == 0)
+ if (!IdVal)
IdVal = MCConstantExpr::Create(0, getContext());
// Replace the register operand with the memory operand.
MipsOperand *op = static_cast<MipsOperand *>(Operands.back());
// Remove the register from the operands.
+ // "op" will be managed by k_Memory.
Operands.pop_back();
// Add the memory operand.
if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
@@ -1969,9 +1982,11 @@ MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
.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);
+ assert(VK != MCSymbolRefExpr::VK_None);
return VK;
}
@@ -2089,6 +2104,10 @@ bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
return Error(Loc, ErrorMsg);
}
+bool MipsAsmParser::reportParseError(SMLoc Loc, StringRef ErrorMsg) {
+ return Error(Loc, ErrorMsg);
+}
+
bool MipsAsmParser::parseSetNoAtDirective() {
// Line should look like: ".set noat".
// set at reg to 0.
@@ -2248,29 +2267,30 @@ bool MipsAsmParser::parseSetFeature(uint64_t Feature) {
if (getLexer().isNot(AsmToken::EndOfStatement))
return reportParseError("unexpected token in .set directive");
- switch(Feature) {
- default: llvm_unreachable("Unimplemented feature");
- case Mips::FeatureDSP:
- setFeatureBits(Mips::FeatureDSP, "dsp");
- getTargetStreamer().emitDirectiveSetDsp();
+ switch (Feature) {
+ default:
+ llvm_unreachable("Unimplemented feature");
+ case Mips::FeatureDSP:
+ setFeatureBits(Mips::FeatureDSP, "dsp");
+ getTargetStreamer().emitDirectiveSetDsp();
break;
- case Mips::FeatureMicroMips:
- getTargetStreamer().emitDirectiveSetMicroMips();
+ case Mips::FeatureMicroMips:
+ getTargetStreamer().emitDirectiveSetMicroMips();
break;
- case Mips::FeatureMips16:
- getTargetStreamer().emitDirectiveSetMips16();
+ case Mips::FeatureMips16:
+ getTargetStreamer().emitDirectiveSetMips16();
break;
- case Mips::FeatureMips32r2:
- setFeatureBits(Mips::FeatureMips32r2, "mips32r2");
- getTargetStreamer().emitDirectiveSetMips32R2();
+ case Mips::FeatureMips32r2:
+ setFeatureBits(Mips::FeatureMips32r2, "mips32r2");
+ getTargetStreamer().emitDirectiveSetMips32R2();
break;
- case Mips::FeatureMips64:
- setFeatureBits(Mips::FeatureMips64, "mips64");
- getTargetStreamer().emitDirectiveSetMips64();
+ case Mips::FeatureMips64:
+ setFeatureBits(Mips::FeatureMips64, "mips64");
+ getTargetStreamer().emitDirectiveSetMips64();
break;
- case Mips::FeatureMips64r2:
- setFeatureBits(Mips::FeatureMips64r2, "mips64r2");
- getTargetStreamer().emitDirectiveSetMips64R2();
+ case Mips::FeatureMips64r2:
+ setFeatureBits(Mips::FeatureMips64r2, "mips64r2");
+ getTargetStreamer().emitDirectiveSetMips64R2();
break;
}
return false;
@@ -2302,10 +2322,34 @@ bool MipsAsmParser::eatComma(StringRef ErrorStr) {
return Error(Loc, ErrorStr);
}
- Parser.Lex(); // Eat the comma.
+ Parser.Lex(); // Eat the comma.
return true;
}
+bool MipsAsmParser::parseDirectiveCPLoad(SMLoc Loc) {
+ if (Options.isReorder())
+ Warning(Loc, ".cpload in reorder section");
+
+ // FIXME: Warn if cpload is used in Mips16 mode.
+
+ SmallVector<MCParsedAsmOperand *, 1> Reg;
+ OperandMatchResultTy ResTy = ParseAnyRegister(Reg);
+ if (ResTy == MatchOperand_NoMatch || ResTy == MatchOperand_ParseFail) {
+ reportParseError("expected register containing function address");
+ return false;
+ }
+
+ MipsOperand *RegOpnd = static_cast<MipsOperand *>(Reg[0]);
+ if (!RegOpnd->isGPRAsmReg()) {
+ reportParseError(RegOpnd->getStartLoc(), "invalid register");
+ return false;
+ }
+
+ getTargetStreamer().emitDirectiveCpload(RegOpnd->getGPR32Reg());
+ delete RegOpnd;
+ return false;
+}
+
bool MipsAsmParser::parseDirectiveCPSetup() {
unsigned FuncReg;
unsigned Save;
@@ -2336,60 +2380,28 @@ bool MipsAsmParser::parseDirectiveCPSetup() {
if (Parser.parseIdentifier(Name))
reportParseError("expected identifier");
MCSymbol *Sym = getContext().GetOrCreateSymbol(Name);
- unsigned GPReg = getGPR(matchCPURegisterName("gp"));
- // FIXME: The code below this point should be in the TargetStreamers.
- // Only N32 and N64 emit anything for .cpsetup
- // FIXME: We should only emit something for PIC mode too.
- if (!isN32() && !isN64())
- return false;
+ getTargetStreamer().emitDirectiveCpsetup(FuncReg, Save, *Sym, SaveIsReg);
+ return false;
+}
- MCStreamer &TS = getStreamer();
- MCInst Inst;
- // Either store the old $gp in a register or on the stack
- if (SaveIsReg) {
- // move $save, $gpreg
- Inst.setOpcode(Mips::DADDu);
- Inst.addOperand(MCOperand::CreateReg(Save));
- Inst.addOperand(MCOperand::CreateReg(GPReg));
- Inst.addOperand(MCOperand::CreateReg(getGPR(0)));
- } else {
- // sd $gpreg, offset($sp)
- Inst.setOpcode(Mips::SD);
- Inst.addOperand(MCOperand::CreateReg(GPReg));
- Inst.addOperand(MCOperand::CreateReg(getGPR(matchCPURegisterName("sp"))));
- Inst.addOperand(MCOperand::CreateImm(Save));
- }
- TS.EmitInstruction(Inst, STI);
- Inst.clear();
-
- const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
- Sym->getName(), MCSymbolRefExpr::VK_Mips_GPOFF_HI,
- getContext());
- const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
- Sym->getName(), MCSymbolRefExpr::VK_Mips_GPOFF_LO,
- getContext());
- // lui $gp, %hi(%neg(%gp_rel(funcSym)))
- Inst.setOpcode(Mips::LUi);
- Inst.addOperand(MCOperand::CreateReg(GPReg));
- Inst.addOperand(MCOperand::CreateExpr(HiExpr));
- TS.EmitInstruction(Inst, STI);
- Inst.clear();
-
- // addiu $gp, $gp, %lo(%neg(%gp_rel(funcSym)))
- Inst.setOpcode(Mips::ADDiu);
- Inst.addOperand(MCOperand::CreateReg(GPReg));
- Inst.addOperand(MCOperand::CreateReg(GPReg));
- Inst.addOperand(MCOperand::CreateExpr(LoExpr));
- TS.EmitInstruction(Inst, STI);
- Inst.clear();
-
- // daddu $gp, $gp, $funcreg
- Inst.setOpcode(Mips::DADDu);
- Inst.addOperand(MCOperand::CreateReg(GPReg));
- Inst.addOperand(MCOperand::CreateReg(GPReg));
- Inst.addOperand(MCOperand::CreateReg(FuncReg));
- TS.EmitInstruction(Inst, STI);
+bool MipsAsmParser::parseDirectiveNaN() {
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ const AsmToken &Tok = Parser.getTok();
+
+ if (Tok.getString() == "2008") {
+ Parser.Lex();
+ getTargetStreamer().emitDirectiveNaN2008();
+ return false;
+ } else if (Tok.getString() == "legacy") {
+ Parser.Lex();
+ getTargetStreamer().emitDirectiveNaNLegacy();
+ return false;
+ }
+ }
+ // If we don't recognize the option passed to the .nan
+ // directive (e.g. no option or unknown option), emit an error.
+ reportParseError("invalid option in .nan directive");
return false;
}
@@ -2419,15 +2431,15 @@ bool MipsAsmParser::parseDirectiveSet() {
Parser.eatToEndOfStatement();
return false;
} else if (Tok.getString() == "micromips") {
- return parseSetFeature(Mips::FeatureMicroMips);
+ return parseSetFeature(Mips::FeatureMicroMips);
} else if (Tok.getString() == "mips32r2") {
- return parseSetFeature(Mips::FeatureMips32r2);
+ return parseSetFeature(Mips::FeatureMips32r2);
} else if (Tok.getString() == "mips64") {
- return parseSetFeature(Mips::FeatureMips64);
+ return parseSetFeature(Mips::FeatureMips64);
} else if (Tok.getString() == "mips64r2") {
- return parseSetFeature(Mips::FeatureMips64r2);
+ return parseSetFeature(Mips::FeatureMips64r2);
} else if (Tok.getString() == "dsp") {
- return parseSetFeature(Mips::FeatureDSP);
+ return parseSetFeature(Mips::FeatureDSP);
} else {
// It is just an identifier, look for an assignment.
parseSetAssignment();
@@ -2537,6 +2549,8 @@ bool MipsAsmParser::parseDirectiveOption() {
bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
StringRef IDVal = DirectiveID.getString();
+ if (IDVal == ".cpload")
+ return parseDirectiveCPLoad(DirectiveID.getLoc());
if (IDVal == ".dword") {
parseDataDirective(8, DirectiveID.getLoc());
return false;
@@ -2576,6 +2590,9 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
return false;
}
+ if (IDVal == ".nan")
+ return parseDirectiveNaN();
+
if (IDVal == ".gpword") {
parseDirectiveGpWord();
return false;
diff --git a/lib/Target/Mips/CMakeLists.txt b/lib/Target/Mips/CMakeLists.txt
index c304ee3..bf67d71 100644
--- a/lib/Target/Mips/CMakeLists.txt
+++ b/lib/Target/Mips/CMakeLists.txt
@@ -7,6 +7,7 @@ tablegen(LLVM MipsGenCodeEmitter.inc -gen-emitter)
tablegen(LLVM MipsGenMCCodeEmitter.inc -gen-emitter -mc-emitter)
tablegen(LLVM MipsGenAsmWriter.inc -gen-asm-writer)
tablegen(LLVM MipsGenDAGISel.inc -gen-dag-isel)
+tablegen(LLVM MipsGenFastISel.inc -gen-fast-isel)
tablegen(LLVM MipsGenCallingConv.inc -gen-callingconv)
tablegen(LLVM MipsGenSubtargetInfo.inc -gen-subtarget)
tablegen(LLVM MipsGenAsmMatcher.inc -gen-asm-matcher)
@@ -26,6 +27,7 @@ add_llvm_target(MipsCodeGen
MipsCodeEmitter.cpp
MipsConstantIslandPass.cpp
MipsDelaySlotFiller.cpp
+ MipsFastISel.cpp
MipsJITInfo.cpp
MipsInstrInfo.cpp
MipsISelDAGToDAG.cpp
diff --git a/lib/Target/Mips/Disassembler/LLVMBuild.txt b/lib/Target/Mips/Disassembler/LLVMBuild.txt
index 7101c06..bb70fd3 100644
--- a/lib/Target/Mips/Disassembler/LLVMBuild.txt
+++ b/lib/Target/Mips/Disassembler/LLVMBuild.txt
@@ -19,5 +19,5 @@
type = Library
name = MipsDisassembler
parent = Mips
-required_libraries = MC Support MipsInfo
+required_libraries = MC MipsInfo Support
add_to_library_groups = Mips
diff --git a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
index fc3b922..95670aa 100644
--- a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
+++ b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
@@ -14,6 +14,7 @@
#include "Mips.h"
#include "MipsRegisterInfo.h"
#include "MipsSubtarget.h"
+#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDisassembler.h"
#include "llvm/MC/MCFixedLenDisassembler.h"
#include "llvm/MC/MCInst.h"
@@ -24,6 +25,8 @@
using namespace llvm;
+#define DEBUG_TYPE "mips-disassembler"
+
typedef MCDisassembler::DecodeStatus DecodeStatus;
namespace {
@@ -33,19 +36,16 @@ class MipsDisassemblerBase : public MCDisassembler {
public:
/// Constructor - Initializes the disassembler.
///
- MipsDisassemblerBase(const MCSubtargetInfo &STI, const MCRegisterInfo *Info,
+ MipsDisassemblerBase(const MCSubtargetInfo &STI, MCContext &Ctx,
bool bigEndian) :
- MCDisassembler(STI), RegInfo(Info),
+ MCDisassembler(STI, Ctx),
IsN64(STI.getFeatureBits() & Mips::FeatureN64), isBigEndian(bigEndian) {}
virtual ~MipsDisassemblerBase() {}
- const MCRegisterInfo *getRegInfo() const { return RegInfo.get(); }
-
bool isN64() const { return IsN64; }
private:
- OwningPtr<const MCRegisterInfo> RegInfo;
bool IsN64;
protected:
bool isBigEndian;
@@ -57,19 +57,23 @@ class MipsDisassembler : public MipsDisassemblerBase {
public:
/// Constructor - Initializes the disassembler.
///
- MipsDisassembler(const MCSubtargetInfo &STI, const MCRegisterInfo *Info,
+ MipsDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
bool bigEndian) :
- MipsDisassemblerBase(STI, Info, bigEndian) {
+ MipsDisassemblerBase(STI, Ctx, bigEndian) {
IsMicroMips = STI.getFeatureBits() & Mips::FeatureMicroMips;
}
+ bool isMips32r6() const {
+ return STI.getFeatureBits() & Mips::FeatureMips32r6;
+ }
+
/// getInstruction - See MCDisassembler.
- virtual DecodeStatus getInstruction(MCInst &instr,
- uint64_t &size,
- const MemoryObject &region,
- uint64_t address,
- raw_ostream &vStream,
- raw_ostream &cStream) const;
+ DecodeStatus getInstruction(MCInst &instr,
+ uint64_t &size,
+ const MemoryObject &region,
+ uint64_t address,
+ raw_ostream &vStream,
+ raw_ostream &cStream) const override;
};
@@ -78,17 +82,17 @@ class Mips64Disassembler : public MipsDisassemblerBase {
public:
/// Constructor - Initializes the disassembler.
///
- Mips64Disassembler(const MCSubtargetInfo &STI, const MCRegisterInfo *Info,
+ Mips64Disassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
bool bigEndian) :
- MipsDisassemblerBase(STI, Info, bigEndian) {}
+ MipsDisassemblerBase(STI, Ctx, bigEndian) {}
/// getInstruction - See MCDisassembler.
- virtual DecodeStatus getInstruction(MCInst &instr,
- uint64_t &size,
- const MemoryObject &region,
- uint64_t address,
- raw_ostream &vStream,
- raw_ostream &cStream) const;
+ DecodeStatus getInstruction(MCInst &instr,
+ uint64_t &size,
+ const MemoryObject &region,
+ uint64_t address,
+ raw_ostream &vStream,
+ raw_ostream &cStream) const override;
};
} // end anonymous namespace
@@ -195,6 +199,11 @@ static DecodeStatus DecodeMSACtrlRegisterClass(MCInst &Inst,
uint64_t Address,
const void *Decoder);
+static DecodeStatus DecodeCOP2RegisterClass(MCInst &Inst,
+ unsigned RegNo,
+ uint64_t Address,
+ const void *Decoder);
+
static DecodeStatus DecodeBranchTarget(MCInst &Inst,
unsigned Offset,
uint64_t Address,
@@ -205,6 +214,16 @@ static DecodeStatus DecodeJumpTarget(MCInst &Inst,
uint64_t Address,
const void *Decoder);
+static DecodeStatus DecodeBranchTarget21(MCInst &Inst,
+ unsigned Offset,
+ uint64_t Address,
+ const void *Decoder);
+
+static DecodeStatus DecodeBranchTarget26(MCInst &Inst,
+ unsigned Offset,
+ uint64_t Address,
+ const void *Decoder);
+
// DecodeBranchTargetMM - Decode microMIPS branch offset, which is
// shifted left by 1 bit.
static DecodeStatus DecodeBranchTargetMM(MCInst &Inst,
@@ -263,11 +282,40 @@ static DecodeStatus DecodeExtSize(MCInst &Inst,
uint64_t Address,
const void *Decoder);
+static DecodeStatus DecodeSimm19Lsl2(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder);
+
/// INSVE_[BHWD] have an implicit operand that the generated decoder doesn't
/// handle.
template <typename InsnType>
static DecodeStatus DecodeINSVE_DF(MCInst &MI, InsnType insn, uint64_t Address,
const void *Decoder);
+
+template <typename InsnType>
+static DecodeStatus
+DecodeAddiGroupBranch(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
+DecodeBlezlGroupBranch(MCInst &MI, InsnType insn, uint64_t Address,
+ const void *Decoder);
+
+template <typename InsnType>
+static DecodeStatus
+DecodeBgtzlGroupBranch(MCInst &MI, InsnType insn, uint64_t Address,
+ const void *Decoder);
+
+template <typename InsnType>
+static DecodeStatus
+DecodeBgtzGroupBranch(MCInst &MI, InsnType insn, uint64_t Address,
+ const void *Decoder);
+
namespace llvm {
extern Target TheMipselTarget, TheMipsTarget, TheMips64Target,
TheMips64elTarget;
@@ -275,26 +323,30 @@ extern Target TheMipselTarget, TheMipsTarget, TheMips64Target,
static MCDisassembler *createMipsDisassembler(
const Target &T,
- const MCSubtargetInfo &STI) {
- return new MipsDisassembler(STI, T.createMCRegInfo(""), true);
+ const MCSubtargetInfo &STI,
+ MCContext &Ctx) {
+ return new MipsDisassembler(STI, Ctx, true);
}
static MCDisassembler *createMipselDisassembler(
const Target &T,
- const MCSubtargetInfo &STI) {
- return new MipsDisassembler(STI, T.createMCRegInfo(""), false);
+ const MCSubtargetInfo &STI,
+ MCContext &Ctx) {
+ return new MipsDisassembler(STI, Ctx, false);
}
static MCDisassembler *createMips64Disassembler(
const Target &T,
- const MCSubtargetInfo &STI) {
- return new Mips64Disassembler(STI, T.createMCRegInfo(""), true);
+ const MCSubtargetInfo &STI,
+ MCContext &Ctx) {
+ return new Mips64Disassembler(STI, Ctx, true);
}
static MCDisassembler *createMips64elDisassembler(
const Target &T,
- const MCSubtargetInfo &STI) {
- return new Mips64Disassembler(STI, T.createMCRegInfo(""), false);
+ const MCSubtargetInfo &STI,
+ MCContext &Ctx) {
+ return new Mips64Disassembler(STI, Ctx, false);
}
extern "C" void LLVMInitializeMipsDisassembler() {
@@ -311,6 +363,12 @@ extern "C" void LLVMInitializeMipsDisassembler() {
#include "MipsGenDisassemblerTables.inc"
+static unsigned getReg(const void *D, unsigned RC, unsigned RegNo) {
+ const MipsDisassemblerBase *Dis = static_cast<const MipsDisassemblerBase*>(D);
+ const MCRegisterInfo *RegInfo = Dis->getContext().getRegisterInfo();
+ return *(RegInfo->getRegClass(RC).begin() + RegNo);
+}
+
template <typename InsnType>
static DecodeStatus DecodeINSVE_DF(MCInst &MI, InsnType insn, uint64_t Address,
const void *Decoder) {
@@ -357,6 +415,202 @@ static DecodeStatus DecodeINSVE_DF(MCInst &MI, InsnType insn, uint64_t Address,
return MCDisassembler::Success;
}
+template <typename InsnType>
+static DecodeStatus DecodeAddiGroupBranch(MCInst &MI, InsnType insn,
+ uint64_t Address,
+ const void *Decoder) {
+ // If we are called then we can assume that MIPS32r6/MIPS64r6 is enabled
+ // (otherwise we would have matched the ADDI instruction from the earlier
+ // ISA's instead).
+ //
+ // We have:
+ // 0b001000 sssss ttttt iiiiiiiiiiiiiiii
+ // BOVC if rs >= rt
+ // BEQZALC if rs == 0 && rt != 0
+ // BEQC if rs < rt && rs != 0
+
+ InsnType Rs = fieldFromInstruction(insn, 21, 5);
+ InsnType Rt = fieldFromInstruction(insn, 16, 5);
+ InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) << 2;
+ bool HasRs = false;
+
+ if (Rs >= Rt) {
+ MI.setOpcode(Mips::BOVC);
+ HasRs = true;
+ } else if (Rs != 0 && Rs < Rt) {
+ MI.setOpcode(Mips::BEQC);
+ HasRs = true;
+ } else
+ MI.setOpcode(Mips::BEQZALC);
+
+ 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;
+}
+
+template <typename InsnType>
+static DecodeStatus DecodeDaddiGroupBranch(MCInst &MI, InsnType insn,
+ uint64_t Address,
+ const void *Decoder) {
+ // If we are called then we can assume that MIPS32r6/MIPS64r6 is enabled
+ // (otherwise we would have matched the ADDI instruction from the earlier
+ // ISA's instead).
+ //
+ // We have:
+ // 0b011000 sssss ttttt iiiiiiiiiiiiiiii
+ // BNVC if rs >= rt
+ // BNEZALC if rs == 0 && rt != 0
+ // BNEC if rs < rt && rs != 0
+
+ InsnType Rs = fieldFromInstruction(insn, 21, 5);
+ InsnType Rt = fieldFromInstruction(insn, 16, 5);
+ InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) << 2;
+ bool HasRs = false;
+
+ if (Rs >= Rt) {
+ MI.setOpcode(Mips::BNVC);
+ HasRs = true;
+ } else if (Rs != 0 && Rs < Rt) {
+ MI.setOpcode(Mips::BNEC);
+ HasRs = true;
+ } else
+ MI.setOpcode(Mips::BNEZALC);
+
+ 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;
+}
+
+template <typename InsnType>
+static DecodeStatus DecodeBlezlGroupBranch(MCInst &MI, InsnType insn,
+ uint64_t Address,
+ const void *Decoder) {
+ // If we are called then we can assume that MIPS32r6/MIPS64r6 is enabled
+ // (otherwise we would have matched the BLEZL instruction from the earlier
+ // ISA's instead).
+ //
+ // We have:
+ // 0b010110 sssss ttttt iiiiiiiiiiiiiiii
+ // Invalid if rs == 0
+ // BLEZC if rs == 0 && rt != 0
+ // BGEZC if rs == rt && rt != 0
+ // BGEC if rs != rt && rs != 0 && rt != 0
+
+ InsnType Rs = fieldFromInstruction(insn, 21, 5);
+ InsnType Rt = fieldFromInstruction(insn, 16, 5);
+ InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) << 2;
+
+ if (Rt == 0)
+ return MCDisassembler::Fail;
+ else if (Rs == 0)
+ MI.setOpcode(Mips::BLEZC);
+ else if (Rs == Rt)
+ MI.setOpcode(Mips::BGEZC);
+ else
+ return MCDisassembler::Fail; // FIXME: BGEC is not implemented yet.
+
+ MI.addOperand(MCOperand::CreateReg(getReg(Decoder, Mips::GPR32RegClassID,
+ Rt)));
+
+ MI.addOperand(MCOperand::CreateImm(Imm));
+
+ return MCDisassembler::Success;
+}
+
+template <typename InsnType>
+static DecodeStatus DecodeBgtzlGroupBranch(MCInst &MI, InsnType insn,
+ uint64_t Address,
+ const void *Decoder) {
+ // If we are called then we can assume that MIPS32r6/MIPS64r6 is enabled
+ // (otherwise we would have matched the BGTZL instruction from the earlier
+ // ISA's instead).
+ //
+ // We have:
+ // 0b010111 sssss ttttt iiiiiiiiiiiiiiii
+ // Invalid if rs == 0
+ // BGTZC if rs == 0 && rt != 0
+ // BLTZC if rs == rt && rt != 0
+ // BLTC if rs != rt && rs != 0 && rt != 0
+
+ InsnType Rs = fieldFromInstruction(insn, 21, 5);
+ InsnType Rt = fieldFromInstruction(insn, 16, 5);
+ InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) << 2;
+
+ if (Rt == 0)
+ return MCDisassembler::Fail;
+ else if (Rs == 0)
+ MI.setOpcode(Mips::BGTZC);
+ else if (Rs == Rt)
+ MI.setOpcode(Mips::BLTZC);
+ else
+ return MCDisassembler::Fail; // FIXME: BLTC is not implemented yet.
+
+ MI.addOperand(MCOperand::CreateReg(getReg(Decoder, Mips::GPR32RegClassID,
+ Rt)));
+
+ MI.addOperand(MCOperand::CreateImm(Imm));
+
+ return MCDisassembler::Success;
+}
+
+template <typename InsnType>
+static DecodeStatus DecodeBgtzGroupBranch(MCInst &MI, InsnType insn,
+ uint64_t Address,
+ const void *Decoder) {
+ // If we are called then we can assume that MIPS32r6/MIPS64r6 is enabled
+ // (otherwise we would have matched the BGTZ instruction from the earlier
+ // ISA's instead).
+ //
+ // We have:
+ // 0b000111 sssss ttttt iiiiiiiiiiiiiiii
+ // BGTZ if rt == 0
+ // BGTZALC if rs == 0 && rt != 0
+ // BLTZALC if rs != 0 && rs == rt
+ // BLTUC if rs != 0 && rs != rt
+
+ InsnType Rs = fieldFromInstruction(insn, 21, 5);
+ InsnType Rt = fieldFromInstruction(insn, 16, 5);
+ InsnType Imm = SignExtend64(fieldFromInstruction(insn, 0, 16), 16) << 2;
+ bool HasRs = false;
+ bool HasRt = false;
+
+ if (Rt == 0) {
+ MI.setOpcode(Mips::BGTZ);
+ HasRs = true;
+ } else if (Rs == 0) {
+ MI.setOpcode(Mips::BGTZALC);
+ HasRt = true;
+ } else if (Rs == Rt) {
+ MI.setOpcode(Mips::BLTZALC);
+ HasRs = true;
+ } else
+ return MCDisassembler::Fail; // BLTUC not implemented yet
+
+ 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;
+}
+
/// readInstruction - read four bytes from the MemoryObject
/// and return 32 bit word sorted according to the given endianess
static DecodeStatus readInstruction32(const MemoryObject &region,
@@ -426,6 +680,15 @@ MipsDisassembler::getInstruction(MCInst &instr,
return MCDisassembler::Fail;
}
+ if (isMips32r6()) {
+ Result = decodeInstruction(DecoderTableMips32r6_64r632, instr, Insn,
+ Address, this, STI);
+ if (Result != MCDisassembler::Fail) {
+ Size = 4;
+ return Result;
+ }
+ }
+
// Calling the auto-generated decoder function.
Result = decodeInstruction(DecoderTableMips32, instr, Insn, Address,
this, STI);
@@ -469,11 +732,6 @@ Mips64Disassembler::getInstruction(MCInst &instr,
return MCDisassembler::Fail;
}
-static unsigned getReg(const void *D, unsigned RC, unsigned RegNo) {
- const MipsDisassemblerBase *Dis = static_cast<const MipsDisassemblerBase*>(D);
- return *(Dis->getRegInfo()->getRegClass(RC).begin() + RegNo);
-}
-
static DecodeStatus DecodeCPU16RegsRegisterClass(MCInst &Inst,
unsigned RegNo,
uint64_t Address,
@@ -828,12 +1086,23 @@ static DecodeStatus DecodeMSACtrlRegisterClass(MCInst &Inst,
return MCDisassembler::Success;
}
+static DecodeStatus DecodeCOP2RegisterClass(MCInst &Inst,
+ unsigned RegNo,
+ uint64_t Address,
+ const void *Decoder) {
+ if (RegNo > 31)
+ return MCDisassembler::Fail;
+
+ unsigned Reg = getReg(Decoder, Mips::COP2RegClassID, RegNo);
+ Inst.addOperand(MCOperand::CreateReg(Reg));
+ return MCDisassembler::Success;
+}
+
static DecodeStatus DecodeBranchTarget(MCInst &Inst,
unsigned Offset,
uint64_t Address,
const void *Decoder) {
- unsigned BranchOffset = Offset & 0xffff;
- BranchOffset = SignExtend32<18>(BranchOffset << 2) + 4;
+ int32_t BranchOffset = (SignExtend32<16>(Offset) << 2) + 4;
Inst.addOperand(MCOperand::CreateImm(BranchOffset));
return MCDisassembler::Success;
}
@@ -848,12 +1117,31 @@ static DecodeStatus DecodeJumpTarget(MCInst &Inst,
return MCDisassembler::Success;
}
+static DecodeStatus DecodeBranchTarget21(MCInst &Inst,
+ unsigned Offset,
+ uint64_t Address,
+ const void *Decoder) {
+ int32_t BranchOffset = SignExtend32<21>(Offset) << 2;
+
+ Inst.addOperand(MCOperand::CreateImm(BranchOffset));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeBranchTarget26(MCInst &Inst,
+ unsigned Offset,
+ uint64_t Address,
+ const void *Decoder) {
+ int32_t BranchOffset = SignExtend32<26>(Offset) << 2;
+
+ Inst.addOperand(MCOperand::CreateImm(BranchOffset));
+ return MCDisassembler::Success;
+}
+
static DecodeStatus DecodeBranchTargetMM(MCInst &Inst,
unsigned Offset,
uint64_t Address,
const void *Decoder) {
- unsigned BranchOffset = Offset & 0xffff;
- BranchOffset = SignExtend32<18>(BranchOffset << 1);
+ int32_t BranchOffset = SignExtend32<16>(Offset) << 1;
Inst.addOperand(MCOperand::CreateImm(BranchOffset));
return MCDisassembler::Success;
}
@@ -903,3 +1191,9 @@ static DecodeStatus DecodeExtSize(MCInst &Inst,
Inst.addOperand(MCOperand::CreateImm(SignExtend32<16>(Size)));
return MCDisassembler::Success;
}
+
+static DecodeStatus DecodeSimm19Lsl2(MCInst &Inst, unsigned Insn,
+ uint64_t Address, const void *Decoder) {
+ Inst.addOperand(MCOperand::CreateImm(SignExtend32<19>(Insn) << 2));
+ return MCDisassembler::Success;
+}
diff --git a/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp b/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp
index c8f08f1..8c79751 100644
--- a/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp
+++ b/lib/Target/Mips/InstPrinter/MipsInstPrinter.cpp
@@ -11,7 +11,6 @@
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "asm-printer"
#include "MipsInstPrinter.h"
#include "MCTargetDesc/MipsMCExpr.h"
#include "MipsInstrInfo.h"
@@ -24,6 +23,8 @@
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
+#define DEBUG_TYPE "asm-printer"
+
#define PRINT_ALIAS_INSTR
#include "MipsGenAsmWriter.inc"
@@ -165,6 +166,8 @@ static void printExpr(const MCExpr *Expr, raw_ostream &OS) {
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;
}
OS << SRE->getSymbol();
diff --git a/lib/Target/Mips/InstPrinter/MipsInstPrinter.h b/lib/Target/Mips/InstPrinter/MipsInstPrinter.h
index 2b745f0..550a0f1 100644
--- a/lib/Target/Mips/InstPrinter/MipsInstPrinter.h
+++ b/lib/Target/Mips/InstPrinter/MipsInstPrinter.h
@@ -85,10 +85,12 @@ public:
void printInstruction(const MCInst *MI, raw_ostream &O);
static const char *getRegisterName(unsigned RegNo);
- virtual void printRegName(raw_ostream &OS, unsigned RegNo) const;
- virtual void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot);
+ void printRegName(raw_ostream &OS, unsigned RegNo) const override;
+ void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot) override;
bool printAliasInstr(const MCInst *MI, raw_ostream &OS);
+ void printCustomAliasOperand(const MCInst *MI, unsigned OpIdx,
+ unsigned PrintMethodIdx, raw_ostream &O);
private:
void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O);
diff --git a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
index 0f99ecc..5375a00 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
+++ b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.cpp
@@ -31,7 +31,7 @@ using namespace llvm;
// Prepare value for the target space for it
static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
- MCContext *Ctx = NULL) {
+ MCContext *Ctx = nullptr) {
unsigned Kind = Fixup.getKind();
@@ -56,6 +56,7 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
case Mips::fixup_MICROMIPS_GOT_PAGE:
case Mips::fixup_MICROMIPS_GOT_OFST:
case Mips::fixup_MICROMIPS_GOT_DISP:
+ case Mips::fixup_MIPS_PCLO16:
break;
case Mips::fixup_Mips_PC16:
// So far we are only using this type for branches.
@@ -80,6 +81,7 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
case Mips::fixup_Mips_GOT_HI16:
case Mips::fixup_Mips_CALL_HI16:
case Mips::fixup_MICROMIPS_HI16:
+ case Mips::fixup_MIPS_PCHI16:
// Get the 2nd 16-bits. Also add 1 if bit 15 is 1.
Value = ((Value + 0x8000) >> 16) & 0xffff;
break;
@@ -102,6 +104,22 @@ static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
if (!isIntN(16, Value) && Ctx)
Ctx->FatalError(Fixup.getLoc(), "out of range PC16 fixup");
break;
+ case Mips::fixup_MIPS_PC21_S2:
+ Value -= 4;
+ // Forcing a signed division because Value can be negative.
+ Value = (int64_t) Value / 4;
+ // We now check if Value can be encoded as a 21-bit signed immediate.
+ if (!isIntN(21, Value) && Ctx)
+ Ctx->FatalError(Fixup.getLoc(), "out of range PC21 fixup");
+ break;
+ case Mips::fixup_MIPS_PC26_S2:
+ Value -= 4;
+ // Forcing a signed division because Value can be negative.
+ Value = (int64_t) Value / 4;
+ // We now check if Value can be encoded as a 26-bit signed immediate.
+ if (!isIntN(26, Value) && Ctx)
+ Ctx->FatalError(Fixup.getLoc(), "out of range PC26 fixup");
+ break;
}
return Value;
@@ -189,7 +207,7 @@ void MipsAsmBackend::applyFixup(const MCFixup &Fixup, char *Data,
const MCFixupKindInfo &MipsAsmBackend::
getFixupKindInfo(MCFixupKind Kind) const {
- const static MCFixupKindInfo Infos[Mips::NumTargetFixupKinds] = {
+ const static MCFixupKindInfo LittleEndianInfos[Mips::NumTargetFixupKinds] = {
// This table *must* be in same the order of fixup_* kinds in
// MipsFixupKinds.h.
//
@@ -229,6 +247,10 @@ getFixupKindInfo(MCFixupKind Kind) const {
{ "fixup_Mips_GOT_LO16", 0, 16, 0 },
{ "fixup_Mips_CALL_HI16", 0, 16, 0 },
{ "fixup_Mips_CALL_LO16", 0, 16, 0 },
+ { "fixup_MIPS_PC21_S2", 0, 21, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_MIPS_PC26_S2", 0, 26, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_MIPS_PCHI16", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_MIPS_PCLO16", 0, 16, MCFixupKindInfo::FKF_IsPCRel },
{ "fixup_MICROMIPS_26_S1", 0, 26, 0 },
{ "fixup_MICROMIPS_HI16", 0, 16, 0 },
{ "fixup_MICROMIPS_LO16", 0, 16, 0 },
@@ -246,12 +268,76 @@ getFixupKindInfo(MCFixupKind Kind) const {
{ "fixup_MICROMIPS_TLS_TPREL_LO16", 0, 16, 0 }
};
+ const static MCFixupKindInfo BigEndianInfos[Mips::NumTargetFixupKinds] = {
+ // This table *must* be in same the order of fixup_* kinds in
+ // MipsFixupKinds.h.
+ //
+ // name offset bits flags
+ { "fixup_Mips_16", 16, 16, 0 },
+ { "fixup_Mips_32", 0, 32, 0 },
+ { "fixup_Mips_REL32", 0, 32, 0 },
+ { "fixup_Mips_26", 6, 26, 0 },
+ { "fixup_Mips_HI16", 16, 16, 0 },
+ { "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_PC16", 16, 16, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_Mips_CALL16", 16, 16, 0 },
+ { "fixup_Mips_GPREL32", 0, 32, 0 },
+ { "fixup_Mips_SHIFT5", 21, 5, 0 },
+ { "fixup_Mips_SHIFT6", 21, 5, 0 },
+ { "fixup_Mips_64", 0, 64, 0 },
+ { "fixup_Mips_TLSGD", 16, 16, 0 },
+ { "fixup_Mips_GOTTPREL", 16, 16, 0 },
+ { "fixup_Mips_TPREL_HI", 16, 16, 0 },
+ { "fixup_Mips_TPREL_LO", 16, 16, 0 },
+ { "fixup_Mips_TLSLDM", 16, 16, 0 },
+ { "fixup_Mips_DTPREL_HI", 16, 16, 0 },
+ { "fixup_Mips_DTPREL_LO", 16, 16, 0 },
+ { "fixup_Mips_Branch_PCRel",16, 16, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_Mips_GPOFF_HI", 16, 16, 0 },
+ { "fixup_Mips_GPOFF_LO", 16, 16, 0 },
+ { "fixup_Mips_GOT_PAGE", 16, 16, 0 },
+ { "fixup_Mips_GOT_OFST", 16, 16, 0 },
+ { "fixup_Mips_GOT_DISP", 16, 16, 0 },
+ { "fixup_Mips_HIGHER", 16, 16, 0 },
+ { "fixup_Mips_HIGHEST", 16, 16, 0 },
+ { "fixup_Mips_GOT_HI16", 16, 16, 0 },
+ { "fixup_Mips_GOT_LO16", 16, 16, 0 },
+ { "fixup_Mips_CALL_HI16", 16, 16, 0 },
+ { "fixup_Mips_CALL_LO16", 16, 16, 0 },
+ { "fixup_MIPS_PC21_S2", 11, 21, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_MIPS_PC26_S2", 6, 26, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_MIPS_PCHI16", 16, 16, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_MIPS_PCLO16", 16, 16, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_MICROMIPS_26_S1", 6, 26, 0 },
+ { "fixup_MICROMIPS_HI16", 16, 16, 0 },
+ { "fixup_MICROMIPS_LO16", 16, 16, 0 },
+ { "fixup_MICROMIPS_GOT16", 16, 16, 0 },
+ { "fixup_MICROMIPS_PC16_S1",16, 16, MCFixupKindInfo::FKF_IsPCRel },
+ { "fixup_MICROMIPS_CALL16", 16, 16, 0 },
+ { "fixup_MICROMIPS_GOT_DISP", 16, 16, 0 },
+ { "fixup_MICROMIPS_GOT_PAGE", 16, 16, 0 },
+ { "fixup_MICROMIPS_GOT_OFST", 16, 16, 0 },
+ { "fixup_MICROMIPS_TLS_GD", 16, 16, 0 },
+ { "fixup_MICROMIPS_TLS_LDM", 16, 16, 0 },
+ { "fixup_MICROMIPS_TLS_DTPREL_HI16", 16, 16, 0 },
+ { "fixup_MICROMIPS_TLS_DTPREL_LO16", 16, 16, 0 },
+ { "fixup_MICROMIPS_TLS_TPREL_HI16", 16, 16, 0 },
+ { "fixup_MICROMIPS_TLS_TPREL_LO16", 16, 16, 0 }
+ };
+
if (Kind < FirstTargetFixupKind)
return MCAsmBackend::getFixupKindInfo(Kind);
assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
"Invalid kind!");
- return Infos[Kind - FirstTargetFixupKind];
+
+ if (IsLittle)
+ return LittleEndianInfos[Kind - FirstTargetFixupKind];
+ return BigEndianInfos[Kind - FirstTargetFixupKind];
}
/// WriteNopData - Write an (optimal) nop sequence of Count bytes
diff --git a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h
index cc5207a..bc695e6 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h
+++ b/lib/Target/Mips/MCTargetDesc/MipsAsmBackend.h
@@ -37,14 +37,14 @@ public:
: MCAsmBackend(), OSType(_OSType), IsLittle(_isLittle),
Is64Bit(_is64Bit) {}
- MCObjectWriter *createObjectWriter(raw_ostream &OS) const;
+ MCObjectWriter *createObjectWriter(raw_ostream &OS) const override;
void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
- uint64_t Value, bool IsPCRel) const;
+ uint64_t Value, bool IsPCRel) const override;
- const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const;
+ const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override;
- unsigned getNumFixupKinds() const {
+ unsigned getNumFixupKinds() const override {
return Mips::NumTargetFixupKinds;
}
@@ -55,7 +55,7 @@ public:
/// relaxation.
///
/// \param Inst - The instruction to test.
- bool mayNeedRelaxation(const MCInst &Inst) const {
+ bool mayNeedRelaxation(const MCInst &Inst) const override {
return false;
}
@@ -63,7 +63,7 @@ public:
/// fixup requires the associated instruction to be relaxed.
bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
const MCRelaxableFragment *DF,
- const MCAsmLayout &Layout) const {
+ const MCAsmLayout &Layout) const override {
// FIXME.
assert(0 && "RelaxInstruction() unimplemented");
return false;
@@ -75,16 +75,16 @@ 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 {}
+ void relaxInstruction(const MCInst &Inst, MCInst &Res) const override {}
/// @}
- bool writeNopData(uint64_t Count, MCObjectWriter *OW) const;
+ bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
void processFixupValue(const MCAssembler &Asm, const MCAsmLayout &Layout,
const MCFixup &Fixup, const MCFragment *DF,
const MCValue &Target, uint64_t &Value,
- bool &IsResolved);
+ bool &IsResolved) override;
}; // class MipsAsmBackend
diff --git a/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp b/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp
index 794978b..74c12ff 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp
+++ b/lib/Target/Mips/MCTargetDesc/MipsELFObjectWriter.cpp
@@ -193,6 +193,18 @@ unsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target,
case Mips::fixup_MICROMIPS_TLS_TPREL_LO16:
Type = ELF::R_MICROMIPS_TLS_TPREL_LO16;
break;
+ case Mips::fixup_MIPS_PC21_S2:
+ Type = ELF::R_MIPS_PC21_S2;
+ break;
+ case Mips::fixup_MIPS_PC26_S2:
+ Type = ELF::R_MIPS_PC26_S2;
+ break;
+ case Mips::fixup_MIPS_PCHI16:
+ Type = ELF::R_MIPS_PCHI16;
+ break;
+ case Mips::fixup_MIPS_PCLO16:
+ Type = ELF::R_MIPS_PCLO16;
+ break;
}
return Type;
}
diff --git a/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h b/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h
index dc6192c..3079004 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h
+++ b/lib/Target/Mips/MCTargetDesc/MipsFixupKinds.h
@@ -128,6 +128,18 @@ namespace Mips {
// resulting in - R_MIPS_CALL_LO16
fixup_Mips_CALL_LO16,
+ // resulting in - R_MIPS_PC21_S2
+ fixup_MIPS_PC21_S2,
+
+ // resulting in - R_MIPS_PC26_S2
+ fixup_MIPS_PC26_S2,
+
+ // resulting in - R_MIPS_PCHI16
+ fixup_MIPS_PCHI16,
+
+ // resulting in - R_MIPS_PCLO16
+ fixup_MIPS_PCLO16,
+
// resulting in - R_MICROMIPS_26_S1
fixup_MICROMIPS_26_S1,
diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h
index 1000113..37ba0c4 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h
+++ b/lib/Target/Mips/MCTargetDesc/MipsMCAsmInfo.h
@@ -20,7 +20,7 @@ namespace llvm {
class StringRef;
class MipsMCAsmInfo : public MCAsmInfoELF {
- virtual void anchor();
+ void anchor() override;
public:
explicit MipsMCAsmInfo(StringRef TT);
};
diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
index edd2146..85e0bf1 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
+++ b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
@@ -12,8 +12,6 @@
//===----------------------------------------------------------------------===//
//
-#define DEBUG_TYPE "mccodeemitter"
-
#include "MipsMCCodeEmitter.h"
#include "MCTargetDesc/MipsFixupKinds.h"
#include "MCTargetDesc/MipsMCExpr.h"
@@ -28,6 +26,8 @@
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/raw_ostream.h"
+#define DEBUG_TYPE "mccodeemitter"
+
#define GET_INSTRMAP_INFO
#include "MipsGenInstrInfo.inc"
#undef GET_INSTRMAP_INFO
@@ -242,6 +242,69 @@ getBranchTargetOpValueMM(const MCInst &MI, unsigned OpNo,
return 0;
}
+/// getBranchTarget21OpValue - Return binary encoding of the branch
+/// target operand. If the machine operand requires relocation,
+/// record the relocation and return zero.
+unsigned MipsMCCodeEmitter::
+getBranchTarget21OpValue(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 4.
+ if (MO.isImm()) return MO.getImm() >> 2;
+
+ assert(MO.isExpr() &&
+ "getBranchTarget21OpValue expects only expressions or immediates");
+
+ const MCExpr *Expr = MO.getExpr();
+ Fixups.push_back(MCFixup::Create(0, Expr,
+ MCFixupKind(Mips::fixup_MIPS_PC21_S2)));
+ return 0;
+}
+
+/// getBranchTarget26OpValue - Return binary encoding of the branch
+/// target operand. If the machine operand requires relocation,
+/// record the relocation and return zero.
+unsigned MipsMCCodeEmitter::
+getBranchTarget26OpValue(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 4.
+ if (MO.isImm()) return MO.getImm() >> 2;
+
+ assert(MO.isExpr() &&
+ "getBranchTarget26OpValue expects only expressions or immediates");
+
+ const MCExpr *Expr = MO.getExpr();
+ Fixups.push_back(MCFixup::Create(0, Expr,
+ MCFixupKind(Mips::fixup_MIPS_PC26_S2)));
+ return 0;
+}
+
+/// getJumpOffset16OpValue - Return binary encoding of the jump
+/// target operand. If the machine operand requires relocation,
+/// record the relocation and return zero.
+unsigned MipsMCCodeEmitter::
+getJumpOffset16OpValue(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+
+ const MCOperand &MO = MI.getOperand(OpNo);
+
+ if (MO.isImm()) return MO.getImm();
+
+ assert(MO.isExpr() &&
+ "getJumpOffset16OpValue expects only expressions or an immediate");
+
+ // TODO: Push fixup.
+ return 0;
+}
+
/// getJumpTargetOpValue - Return binary encoding of the jump
/// target operand. If the machine operand requires relocation,
/// record the relocation and return zero.
@@ -417,6 +480,12 @@ getExprOpValue(const MCExpr *Expr,SmallVectorImpl<MCFixup> &Fixups,
case MCSymbolRefExpr::VK_Mips_CALL_LO16:
FixupKind = Mips::fixup_Mips_CALL_LO16;
break;
+ case MCSymbolRefExpr::VK_Mips_PCREL_HI16:
+ FixupKind = Mips::fixup_MIPS_PCHI16;
+ break;
+ case MCSymbolRefExpr::VK_Mips_PCREL_LO16:
+ FixupKind = Mips::fixup_MIPS_PCLO16;
+ break;
} // switch
Fixups.push_back(MCFixup::Create(0, Expr, MCFixupKind(FixupKind)));
@@ -548,5 +617,15 @@ MipsMCCodeEmitter::getLSAImmEncoding(const MCInst &MI, unsigned OpNo,
return getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI) - 1;
}
-#include "MipsGenMCCodeEmitter.inc"
+unsigned
+MipsMCCodeEmitter::getSimm19Lsl2Encoding(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const {
+ assert(MI.getOperand(OpNo).isImm());
+ // The immediate is encoded as 'immediate << 2'.
+ unsigned Res = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
+ assert((Res & 3) == 0);
+ return Res >> 2;
+}
+#include "MipsGenMCCodeEmitter.inc"
diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h
index 49a2490..3f7daab 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h
+++ b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.h
@@ -52,7 +52,7 @@ public:
void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
SmallVectorImpl<MCFixup> &Fixups,
- const MCSubtargetInfo &STI) const;
+ const MCSubtargetInfo &STI) const override;
// getBinaryCodeForInstr - TableGen'erated function for getting the
// binary encoding for an instruction.
@@ -88,6 +88,27 @@ public:
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
+ // getBranchTarget21OpValue - Return binary encoding of the branch
+ // offset operand. If the machine operand requires relocation,
+ // record the relocation and return zero.
+ unsigned getBranchTarget21OpValue(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.
+ unsigned getBranchTarget26OpValue(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
+ // getJumpOffset16OpValue - Return binary encoding of the jump
+ // offset operand. If the machine operand requires relocation,
+ // record the relocation and return zero.
+ unsigned getJumpOffset16OpValue(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
// getMachineOpValue - Return binary encoding of operand. If the machin
// operand requires relocation, record the relocation and return zero.
unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
@@ -116,6 +137,10 @@ public:
SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
+ unsigned getSimm19Lsl2Encoding(const MCInst &MI, unsigned OpNo,
+ SmallVectorImpl<MCFixup> &Fixups,
+ const MCSubtargetInfo &STI) const;
+
unsigned getExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups,
const MCSubtargetInfo &STI) const;
diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp
index c7ba12d..21ccc3c 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp
+++ b/lib/Target/Mips/MCTargetDesc/MipsMCExpr.cpp
@@ -7,7 +7,6 @@
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "mipsmcexpr"
#include "MipsMCExpr.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCAssembler.h"
@@ -15,6 +14,8 @@
using namespace llvm;
+#define DEBUG_TYPE "mipsmcexpr"
+
bool MipsMCExpr::isSupportedBinaryExpr(MCSymbolRefExpr::VariantKind VK,
const MCBinaryExpr *BE) {
switch (VK) {
diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h b/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h
index 722bba7..8d7aacd 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h
+++ b/lib/Target/Mips/MCTargetDesc/MipsMCExpr.h
@@ -46,16 +46,16 @@ public:
/// getSubExpr - Get the child of this expression.
const MCExpr *getSubExpr() const { return Expr; }
- void PrintImpl(raw_ostream &OS) const;
+ void PrintImpl(raw_ostream &OS) const override;
bool EvaluateAsRelocatableImpl(MCValue &Res,
- const MCAsmLayout *Layout) const;
- void AddValueSymbols(MCAssembler *) const;
- const MCSection *FindAssociatedSection() const {
+ const MCAsmLayout *Layout) const override;
+ void AddValueSymbols(MCAssembler *) const override;
+ const MCSection *FindAssociatedSection() const override {
return getSubExpr()->FindAssociatedSection();
}
// There are no TLS MipsMCExprs at the moment.
- void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const {}
+ void fixELFSymbolsInTLSFixups(MCAssembler &Asm) const override {}
static bool classof(const MCExpr *E) {
return E->getKind() == MCExpr::Target;
diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h b/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h
index 6992d06..01d5363 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h
+++ b/lib/Target/Mips/MCTargetDesc/MipsMCNaCl.h
@@ -18,7 +18,7 @@ namespace llvm {
static const unsigned MIPS_NACL_BUNDLE_ALIGN = 4u;
bool isBasePlusOffsetMemoryAccess(unsigned Opcode, unsigned *AddrIdx,
- bool *IsStore = NULL);
+ bool *IsStore = nullptr);
bool baseRegNeedsLoadStoreMask(unsigned Reg);
// This function creates an MCELFStreamer for Mips NaCl.
diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
index eecca68..660e5a7 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
+++ b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
@@ -30,6 +30,8 @@
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/TargetRegistry.h"
+using namespace llvm;
+
#define GET_INSTRINFO_MC_DESC
#include "MipsGenInstrInfo.inc"
@@ -39,8 +41,6 @@
#define GET_REGINFO_MC_DESC
#include "MipsGenRegisterInfo.inc"
-using namespace llvm;
-
/// Select the Mips CPU for the given triple and cpu name.
/// FIXME: Merge with the copy in MipsSubtarget.cpp
static inline StringRef selectMipsCPU(StringRef TT, StringRef CPU) {
@@ -79,7 +79,7 @@ static MCAsmInfo *createMipsMCAsmInfo(const MCRegisterInfo &MRI, StringRef TT) {
MCAsmInfo *MAI = new MipsMCAsmInfo(TT);
unsigned SP = MRI.getDwarfRegNum(Mips::SP, true);
- MCCFIInstruction Inst = MCCFIInstruction::createDefCfa(0, SP, 0);
+ MCCFIInstruction Inst = MCCFIInstruction::createDefCfa(nullptr, SP, 0);
MAI->addInitialFrameState(Inst);
return MAI;
@@ -124,12 +124,11 @@ static MCStreamer *createMCStreamer(const Target &T, StringRef TT,
static MCStreamer *
createMCAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS,
- bool isVerboseAsm, bool useCFI, bool useDwarfDirectory,
+ bool isVerboseAsm, bool useDwarfDirectory,
MCInstPrinter *InstPrint, MCCodeEmitter *CE,
MCAsmBackend *TAB, bool ShowInst) {
- MCStreamer *S =
- llvm::createAsmStreamer(Ctx, OS, isVerboseAsm, useCFI, useDwarfDirectory,
- InstPrint, CE, TAB, ShowInst);
+ MCStreamer *S = llvm::createAsmStreamer(
+ Ctx, OS, isVerboseAsm, useDwarfDirectory, InstPrint, CE, TAB, ShowInst);
new MipsTargetAsmStreamer(*S, OS);
return S;
}
diff --git a/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp b/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp
index 639a058..cd6be73 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp
+++ b/lib/Target/Mips/MCTargetDesc/MipsNaClELFStreamer.cpp
@@ -17,8 +17,6 @@
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "mips-mc-nacl"
-
#include "Mips.h"
#include "MipsELFStreamer.h"
#include "MipsMCNaCl.h"
@@ -26,6 +24,8 @@
using namespace llvm;
+#define DEBUG_TYPE "mips-mc-nacl"
+
namespace {
const unsigned IndirectBranchMaskReg = Mips::T6;
@@ -120,7 +120,8 @@ private:
public:
/// This function is the one used to emit instruction data into the ELF
/// streamer. We override it to mask dangerous instructions.
- virtual void EmitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) {
+ void EmitInstruction(const MCInst &Inst,
+ const MCSubtargetInfo &STI) override {
// Sandbox indirect jumps.
if (isIndirectJump(Inst)) {
if (PendingCall)
diff --git a/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp b/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
index fb6aff2..a8fa272 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
+++ b/lib/Target/Mips/MCTargetDesc/MipsTargetStreamer.cpp
@@ -85,6 +85,13 @@ void MipsTargetAsmStreamer::emitDirectiveEnt(const MCSymbol &Symbol) {
}
void MipsTargetAsmStreamer::emitDirectiveAbiCalls() { OS << "\t.abicalls\n"; }
+
+void MipsTargetAsmStreamer::emitDirectiveNaN2008() { OS << "\t.nan\t2008\n"; }
+
+void MipsTargetAsmStreamer::emitDirectiveNaNLegacy() {
+ OS << "\t.nan\tlegacy\n";
+}
+
void MipsTargetAsmStreamer::emitDirectiveOptionPic0() {
OS << "\t.option\tpic0\n";
}
@@ -137,6 +144,29 @@ void MipsTargetAsmStreamer::emitFMask(unsigned FPUBitmask,
OS << "," << FPUTopSavedRegOff << '\n';
}
+void MipsTargetAsmStreamer::emitDirectiveCpload(unsigned RegNo) {
+ OS << "\t.cpload\t$"
+ << StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << "\n";
+}
+
+void MipsTargetAsmStreamer::emitDirectiveCpsetup(unsigned RegNo,
+ int RegOrOffset,
+ const MCSymbol &Sym,
+ bool IsReg) {
+ OS << "\t.cpsetup\t$"
+ << StringRef(MipsInstPrinter::getRegisterName(RegNo)).lower() << ", ";
+
+ if (IsReg)
+ OS << "$"
+ << StringRef(MipsInstPrinter::getRegisterName(RegOrOffset)).lower();
+ else
+ OS << RegOrOffset;
+
+ OS << ", ";
+
+ OS << Sym.getName() << "\n";
+}
+
// This part is for ELF object output.
MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S,
const MCSubtargetInfo &STI)
@@ -180,6 +210,10 @@ MipsTargetELFStreamer::MipsTargetELFStreamer(MCStreamer &S,
EFlags |= ELF::EF_MIPS_ABI_O32;
}
+ // Other options.
+ if (Features & Mips::FeatureNaN2008)
+ EFlags |= ELF::EF_MIPS_NAN2008;
+
MCA.setELFHeaderEFlags(EFlags);
}
@@ -325,6 +359,21 @@ void MipsTargetELFStreamer::emitDirectiveAbiCalls() {
Flags |= ELF::EF_MIPS_CPIC | ELF::EF_MIPS_PIC;
MCA.setELFHeaderEFlags(Flags);
}
+
+void MipsTargetELFStreamer::emitDirectiveNaN2008() {
+ MCAssembler &MCA = getStreamer().getAssembler();
+ unsigned Flags = MCA.getELFHeaderEFlags();
+ Flags |= ELF::EF_MIPS_NAN2008;
+ MCA.setELFHeaderEFlags(Flags);
+}
+
+void MipsTargetELFStreamer::emitDirectiveNaNLegacy() {
+ MCAssembler &MCA = getStreamer().getAssembler();
+ unsigned Flags = MCA.getELFHeaderEFlags();
+ Flags &= ~ELF::EF_MIPS_NAN2008;
+ MCA.setELFHeaderEFlags(Flags);
+}
+
void MipsTargetELFStreamer::emitDirectiveOptionPic0() {
MCAssembler &MCA = getStreamer().getAssembler();
unsigned Flags = MCA.getELFHeaderEFlags();
@@ -376,3 +425,107 @@ void MipsTargetELFStreamer::emitDirectiveSetMips64R2() {
void MipsTargetELFStreamer::emitDirectiveSetDsp() {
// No action required for ELF output.
}
+
+void MipsTargetELFStreamer::emitDirectiveCpload(unsigned RegNo) {
+ // .cpload $reg
+ // This directive expands to:
+ // lui $gp, %hi(_gp_disp)
+ // addui $gp, $gp, %lo(_gp_disp)
+ // addu $gp, $gp, $reg
+ // when support for position independent code is enabled.
+ if (!Pic || (isN32() || isN64()))
+ return;
+
+ // There's a GNU extension controlled by -mno-shared that allows
+ // locally-binding symbols to be accessed using absolute addresses.
+ // This is currently not supported. When supported -mno-shared makes
+ // .cpload expand to:
+ // lui $gp, %hi(__gnu_local_gp)
+ // addiu $gp, $gp, %lo(__gnu_local_gp)
+
+ StringRef SymName("_gp_disp");
+ MCAssembler &MCA = getStreamer().getAssembler();
+ MCSymbol *GP_Disp = MCA.getContext().GetOrCreateSymbol(SymName);
+ MCA.getOrCreateSymbolData(*GP_Disp);
+
+ 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());
+ TmpInst.addOperand(MCOperand::CreateExpr(HiSym));
+ getStreamer().EmitInstruction(TmpInst, STI);
+
+ TmpInst.clear();
+
+ TmpInst.setOpcode(Mips::ADDiu);
+ TmpInst.addOperand(MCOperand::CreateReg(Mips::GP));
+ TmpInst.addOperand(MCOperand::CreateReg(Mips::GP));
+ const MCSymbolRefExpr *LoSym = MCSymbolRefExpr::Create(
+ "_gp_disp", MCSymbolRefExpr::VK_Mips_ABS_LO, MCA.getContext());
+ TmpInst.addOperand(MCOperand::CreateExpr(LoSym));
+ getStreamer().EmitInstruction(TmpInst, STI);
+
+ TmpInst.clear();
+
+ TmpInst.setOpcode(Mips::ADDu);
+ TmpInst.addOperand(MCOperand::CreateReg(Mips::GP));
+ TmpInst.addOperand(MCOperand::CreateReg(Mips::GP));
+ TmpInst.addOperand(MCOperand::CreateReg(RegNo));
+ getStreamer().EmitInstruction(TmpInst, STI);
+}
+
+void MipsTargetELFStreamer::emitDirectiveCpsetup(unsigned RegNo,
+ int RegOrOffset,
+ const MCSymbol &Sym,
+ bool IsReg) {
+ // Only N32 and N64 emit anything for .cpsetup iff PIC is set.
+ if (!Pic || !(isN32() || isN64()))
+ return;
+
+ 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::DADDu);
+ Inst.addOperand(MCOperand::CreateReg(RegOrOffset));
+ Inst.addOperand(MCOperand::CreateReg(Mips::GP));
+ Inst.addOperand(MCOperand::CreateReg(Mips::ZERO));
+ } else {
+ // sd $gpreg, offset($sp)
+ Inst.setOpcode(Mips::SD);
+ Inst.addOperand(MCOperand::CreateReg(Mips::GP));
+ Inst.addOperand(MCOperand::CreateReg(Mips::SP));
+ Inst.addOperand(MCOperand::CreateImm(RegOrOffset));
+ }
+ getStreamer().EmitInstruction(Inst, STI);
+ Inst.clear();
+
+ const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
+ Sym.getName(), MCSymbolRefExpr::VK_Mips_GPOFF_HI, MCA.getContext());
+ const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
+ Sym.getName(), MCSymbolRefExpr::VK_Mips_GPOFF_LO, MCA.getContext());
+ // 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();
+
+ // 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();
+
+ // 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);
+}
diff --git a/lib/Target/Mips/Makefile b/lib/Target/Mips/Makefile
index bcf951e..41efa47 100644
--- a/lib/Target/Mips/Makefile
+++ b/lib/Target/Mips/Makefile
@@ -13,7 +13,7 @@ TARGET = Mips
# Make sure that tblgen is run, first thing.
BUILT_SOURCES = MipsGenRegisterInfo.inc MipsGenInstrInfo.inc \
- MipsGenAsmWriter.inc MipsGenCodeEmitter.inc \
+ MipsGenAsmWriter.inc MipsGenFastISel.inc MipsGenCodeEmitter.inc \
MipsGenDAGISel.inc MipsGenCallingConv.inc \
MipsGenSubtargetInfo.inc MipsGenMCCodeEmitter.inc \
MipsGenDisassemblerTables.inc \
diff --git a/lib/Target/Mips/MicroMipsInstrFPU.td b/lib/Target/Mips/MicroMipsInstrFPU.td
index 91d447a..d95f9b0 100644
--- a/lib/Target/Mips/MicroMipsInstrFPU.td
+++ b/lib/Target/Mips/MicroMipsInstrFPU.td
@@ -28,9 +28,9 @@ def LWXC1_MM : MMRel, LWXC1_FT<"lwxc1", FGR32Opnd, II_LWXC1, load>,
def SWXC1_MM : MMRel, SWXC1_FT<"swxc1", FGR32Opnd, II_SWXC1, store>,
SWXC1_FM_MM<0x88>;
def LUXC1_MM : MMRel, LWXC1_FT<"luxc1", AFGR64Opnd, II_LUXC1>,
- LWXC1_FM_MM<0x148>;
+ LWXC1_FM_MM<0x148>, INSN_MIPS5_32R2;
def SUXC1_MM : MMRel, SWXC1_FT<"suxc1", AFGR64Opnd, II_SUXC1>,
- SWXC1_FM_MM<0x188>;
+ SWXC1_FM_MM<0x188>, INSN_MIPS5_32R2;
def FCMP_S32_MM : MMRel, CEQS_FT<"s", FGR32, II_C_CC_S, MipsFPCmp>,
CEQS_FM_MM<0>;
@@ -70,9 +70,9 @@ def FSQRT_MM : MMRel, ABSS_FT<"sqrt.d", AFGR64Opnd, AFGR64Opnd, II_SQRT_D,
fsqrt>, ROUND_W_FM_MM<1, 0x28>;
def CVT_L_S_MM : MMRel, ABSS_FT<"cvt.l.s", FGR64Opnd, FGR32Opnd, II_CVT>,
- ROUND_W_FM_MM<0, 0x4>;
+ ROUND_W_FM_MM<0, 0x4>, INSN_MIPS3_32R2;
def CVT_L_D64_MM : MMRel, ABSS_FT<"cvt.l.d", FGR64Opnd, FGR64Opnd, II_CVT>,
- ROUND_W_FM_MM<1, 0x4>;
+ ROUND_W_FM_MM<1, 0x4>, INSN_MIPS3_32R2;
def FABS_S_MM : MMRel, ABSS_FT<"abs.s", FGR32Opnd, FGR32Opnd, II_ABS, fabs>,
ABS_FM_MM<0, 0xd>;
@@ -95,7 +95,7 @@ def FNEG_MM : MMRel, ABSS_FT<"neg.d", AFGR64Opnd, AFGR64Opnd, II_NEG, fneg>,
ABS_FM_MM<1, 0x2d>;
def FMOV_D32_MM : MMRel, ABSS_FT<"mov.d", AFGR64Opnd, AFGR64Opnd, II_MOV_D>,
- ABS_FM_MM<1, 0x1>, Requires<[NotFP64bit, HasStdEnc]>;
+ ABS_FM_MM<1, 0x1>, AdditionalRequires<[NotFP64bit]>;
def MOVZ_I_S_MM : MMRel, CMov_I_F_FT<"movz.s", GPR32Opnd, FGR32Opnd,
II_MOVZ_S>, CMov_I_F_FM_MM<0x78, 0>;
@@ -124,9 +124,9 @@ def MFC1_MM : MMRel, MFC1_FT<"mfc1", GPR32Opnd, FGR32Opnd,
def MTC1_MM : MMRel, MTC1_FT<"mtc1", FGR32Opnd, GPR32Opnd,
II_MTC1, bitconvert>, MFC1_FM_MM<0xa0>;
def MFHC1_MM : MMRel, MFC1_FT<"mfhc1", GPR32Opnd, FGRH32Opnd, II_MFHC1>,
- MFC1_FM_MM<3>;
+ MFC1_FM_MM<3>, ISA_MIPS32R2;
def MTHC1_MM : MMRel, MTC1_FT<"mthc1", FGRH32Opnd, GPR32Opnd, II_MTHC1>,
- MFC1_FM_MM<7>;
+ MFC1_FM_MM<7>, ISA_MIPS32R2;
def MADD_S_MM : MMRel, MADDS_FT<"madd.s", FGR32Opnd, II_MADD_S, fadd>,
MADDS_FM_MM<0x1>;
diff --git a/lib/Target/Mips/MicroMipsInstrInfo.td b/lib/Target/Mips/MicroMipsInstrInfo.td
index 3f13e83..9904bc6 100644
--- a/lib/Target/Mips/MicroMipsInstrInfo.td
+++ b/lib/Target/Mips/MicroMipsInstrInfo.td
@@ -218,15 +218,20 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in {
def MSUBU_MM : MMRel, MArithR<"msubu", II_MSUBU>, MULT_FM_MM<0x3ec>;
/// Count Leading
- def CLZ_MM : MMRel, CountLeading0<"clz", GPR32Opnd>, CLO_FM_MM<0x16c>;
- def CLO_MM : MMRel, CountLeading1<"clo", GPR32Opnd>, CLO_FM_MM<0x12c>;
+ def CLZ_MM : MMRel, CountLeading0<"clz", GPR32Opnd>, CLO_FM_MM<0x16c>,
+ ISA_MIPS32;
+ def CLO_MM : MMRel, CountLeading1<"clo", GPR32Opnd>, CLO_FM_MM<0x12c>,
+ ISA_MIPS32;
/// Sign Ext In Register Instructions.
- def SEB_MM : MMRel, SignExtInReg<"seb", i8, GPR32Opnd, II_SEB>, SEB_FM_MM<0x0ac>;
- def SEH_MM : MMRel, SignExtInReg<"seh", i16, GPR32Opnd, II_SEH>, SEB_FM_MM<0x0ec>;
+ def SEB_MM : MMRel, SignExtInReg<"seb", i8, GPR32Opnd, II_SEB>,
+ SEB_FM_MM<0x0ac>, ISA_MIPS32R2;
+ def SEH_MM : MMRel, SignExtInReg<"seh", i16, GPR32Opnd, II_SEH>,
+ SEB_FM_MM<0x0ec>, ISA_MIPS32R2;
/// Word Swap Bytes Within Halfwords
- def WSBH_MM : MMRel, SubwordSwap<"wsbh", GPR32Opnd>, SEB_FM_MM<0x1ec>;
+ def WSBH_MM : MMRel, SubwordSwap<"wsbh", GPR32Opnd>, SEB_FM_MM<0x1ec>,
+ ISA_MIPS32R2;
def EXT_MM : MMRel, ExtBase<"ext", GPR32Opnd, uimm5, MipsExt>,
EXT_FM_MM<0x2c>;
@@ -268,8 +273,10 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in {
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>;
- def EI_MM : MMRel, DEI_FT<"ei", GPR32Opnd>, EI_FM_MM<0x15d>;
- def DI_MM : MMRel, DEI_FT<"di", GPR32Opnd>, EI_FM_MM<0x11d>;
+ def EI_MM : MMRel, DEI_FT<"ei", GPR32Opnd>, EI_FM_MM<0x15d>,
+ ISA_MIPS32R2;
+ def DI_MM : MMRel, DEI_FT<"di", GPR32Opnd>, EI_FM_MM<0x11d>,
+ ISA_MIPS32R2;
/// Trap Instructions
def TEQ_MM : MMRel, TEQ_FT<"teq", GPR32Opnd>, TEQ_FM_MM<0x0>;
@@ -296,5 +303,5 @@ let DecoderNamespace = "MicroMips", Predicates = [InMicroMips] in {
//===----------------------------------------------------------------------===//
let Predicates = [InMicroMips] in {
- def : InstAlias<"wait", (WAIT_MM 0x0), 1>;
+ def : MipsInstAlias<"wait", (WAIT_MM 0x0), 1>;
}
diff --git a/lib/Target/Mips/Mips.td b/lib/Target/Mips/Mips.td
index 10a4699..ea16331 100644
--- a/lib/Target/Mips/Mips.td
+++ b/lib/Target/Mips/Mips.td
@@ -15,6 +15,33 @@
include "llvm/Target/Target.td"
+// The overall idea of the PredicateControl class is to chop the Predicates list
+// into subsets that are usually overridden independently. This allows
+// subclasses to partially override the predicates of their superclasses without
+// having to re-add all the existing predicates.
+class PredicateControl {
+ // Predicates for the encoding scheme in use such as HasStdEnc
+ list<Predicate> EncodingPredicates = [];
+ // Predicates for the GPR size such as IsGP64bit
+ list<Predicate> GPRPredicates = [];
+ // 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
+ list<Predicate> InsnPredicates = [];
+ // Predicates for anything else
+ list<Predicate> AdditionalPredicates = [];
+ list<Predicate> Predicates = !listconcat(EncodingPredicates,
+ GPRPredicates,
+ FGRPredicates,
+ InsnPredicates,
+ AdditionalPredicates);
+}
+
+// Like Requires<> but for the AdditionalPredicates list
+class AdditionalRequires<list<Predicate> preds> {
+ list<Predicate> AdditionalPredicates = preds;
+}
+
//===----------------------------------------------------------------------===//
// Register File, Calling Conv, Instruction Descriptions
//===----------------------------------------------------------------------===//
@@ -34,6 +61,8 @@ def FeatureGP64Bit : SubtargetFeature<"gp64", "IsGP64bit", "true",
"General Purpose Registers are 64-bit wide.">;
def FeatureFP64Bit : SubtargetFeature<"fp64", "IsFP64bit", "true",
"Support 64-bit FP registers.">;
+def FeatureNaN2008 : SubtargetFeature<"nan2008", "IsNaN2008bit", "true",
+ "IEEE 754-2008 NaN encoding.">;
def FeatureSingleFloat : SubtargetFeature<"single-float", "IsSingleFloat",
"true", "Only supports single precision float">;
def FeatureO32 : SubtargetFeature<"o32", "MipsABI", "O32",
@@ -46,33 +75,62 @@ def FeatureEABI : SubtargetFeature<"eabi", "MipsABI", "EABI",
"Enable eabi ABI">;
def FeatureVFPU : SubtargetFeature<"vfpu", "HasVFPU",
"true", "Enable vector FPU instructions.">;
-def FeatureSEInReg : SubtargetFeature<"seinreg", "HasSEInReg", "true",
- "Enable 'signext in register' instructions.">;
-def FeatureCondMov : SubtargetFeature<"condmov", "HasCondMov", "true",
- "Enable 'conditional move' instructions.">;
-def FeatureSwap : SubtargetFeature<"swap", "HasSwap", "true",
- "Enable 'byte/half swap' instructions.">;
-def FeatureBitCount : SubtargetFeature<"bitcount", "HasBitCount", "true",
- "Enable 'count leading bits' instructions.">;
-def FeatureFPIdx : SubtargetFeature<"FPIdx", "HasFPIdx", "true",
- "Enable 'FP indexed load/store' instructions.">;
+def FeatureMips1 : SubtargetFeature<"mips1", "MipsArchVersion", "Mips1",
+ "Mips I ISA Support [highly experimental]">;
+def FeatureMips2 : SubtargetFeature<"mips2", "MipsArchVersion", "Mips2",
+ "Mips II ISA Support [highly experimental]",
+ [FeatureMips1]>;
+def FeatureMips3_32 : SubtargetFeature<"mips3_32", "HasMips3_32", "true",
+ "Subset of MIPS-III that is also in MIPS32 "
+ "[highly experimental]">;
+def FeatureMips3_32r2 : SubtargetFeature<"mips3_32r2", "HasMips3_32r2", "true",
+ "Subset of MIPS-III that is also in MIPS32r2 "
+ "[highly experimental]">;
+def FeatureMips3 : SubtargetFeature<"mips3", "MipsArchVersion", "Mips3",
+ "MIPS III ISA Support [highly experimental]",
+ [FeatureMips2, FeatureMips3_32,
+ FeatureMips3_32r2, FeatureGP64Bit,
+ FeatureFP64Bit]>;
+def FeatureMips4_32 : SubtargetFeature<"mips4_32", "HasMips4_32", "true",
+ "Subset of MIPS-IV that is also in MIPS32 "
+ "[highly experimental]">;
+def FeatureMips4_32r2 : SubtargetFeature<"mips4_32r2", "HasMips4_32r2", "true",
+ "Subset of MIPS-IV that is also in MIPS32r2 "
+ "[highly experimental]">;
+def FeatureMips4 : SubtargetFeature<"mips4", "MipsArchVersion",
+ "Mips4", "MIPS IV ISA Support",
+ [FeatureMips3, FeatureMips4_32,
+ FeatureMips4_32r2]>;
+def FeatureMips5_32r2 : SubtargetFeature<"mips5_32r2", "HasMips5_32r2", "true",
+ "Subset of MIPS-V that is also in MIPS32r2 "
+ "[highly experimental]">;
+def FeatureMips5 : SubtargetFeature<"mips5", "MipsArchVersion", "Mips5",
+ "MIPS V ISA Support [highly experimental]",
+ [FeatureMips4, FeatureMips5_32r2]>;
def FeatureMips32 : SubtargetFeature<"mips32", "MipsArchVersion", "Mips32",
"Mips32 ISA Support",
- [FeatureCondMov, FeatureBitCount]>;
+ [FeatureMips2, FeatureMips3_32,
+ FeatureMips4_32]>;
def FeatureMips32r2 : SubtargetFeature<"mips32r2", "MipsArchVersion",
"Mips32r2", "Mips32r2 ISA Support",
- [FeatureMips32, FeatureSEInReg, FeatureSwap,
- FeatureFPIdx]>;
-def FeatureMips4 : SubtargetFeature<"mips4", "MipsArchVersion",
- "Mips4", "MIPS IV ISA Support",
- [FeatureGP64Bit, FeatureFP64Bit,
- FeatureCondMov]>;
+ [FeatureMips3_32r2, FeatureMips4_32r2,
+ FeatureMips5_32r2, FeatureMips32]>;
+def FeatureMips32r6 : SubtargetFeature<"mips32r6", "MipsArchVersion",
+ "Mips32r6",
+ "Mips32r6 ISA Support [experimental]",
+ [FeatureMips32r2, FeatureFP64Bit,
+ FeatureNaN2008]>;
def FeatureMips64 : SubtargetFeature<"mips64", "MipsArchVersion",
"Mips64", "Mips64 ISA Support",
- [FeatureMips4, FeatureMips32, FeatureFPIdx]>;
+ [FeatureMips5, FeatureMips32]>;
def FeatureMips64r2 : SubtargetFeature<"mips64r2", "MipsArchVersion",
"Mips64r2", "Mips64r2 ISA Support",
[FeatureMips64, FeatureMips32r2]>;
+def FeatureMips64r6 : SubtargetFeature<"mips64r6", "MipsArchVersion",
+ "Mips64r6",
+ "Mips64r6 ISA Support [experimental]",
+ [FeatureMips32r6, FeatureMips64r2,
+ FeatureNaN2008]>;
def FeatureMips16 : SubtargetFeature<"mips16", "InMips16Mode", "true",
"Mips16 mode">;
@@ -97,11 +155,18 @@ def FeatureCnMips : SubtargetFeature<"cnmips", "HasCnMips",
class Proc<string Name, list<SubtargetFeature> Features>
: Processor<Name, MipsGenericItineraries, Features>;
+def : Proc<"mips1", [FeatureMips1, FeatureO32]>;
+def : Proc<"mips2", [FeatureMips2, FeatureO32]>;
def : Proc<"mips32", [FeatureMips32, FeatureO32]>;
def : Proc<"mips32r2", [FeatureMips32r2, FeatureO32]>;
+def : Proc<"mips32r6", [FeatureMips32r6, FeatureO32]>;
+
+def : Proc<"mips3", [FeatureMips3, FeatureN64]>;
def : Proc<"mips4", [FeatureMips4, FeatureN64]>;
+def : Proc<"mips5", [FeatureMips5, FeatureN64]>;
def : Proc<"mips64", [FeatureMips64, FeatureN64]>;
def : Proc<"mips64r2", [FeatureMips64r2, FeatureN64]>;
+def : Proc<"mips64r6", [FeatureMips64r6, FeatureN64]>;
def : Proc<"mips16", [FeatureMips16, FeatureO32]>;
def : Proc<"octeon", [FeatureMips64r2, FeatureN64, FeatureCnMips]>;
diff --git a/lib/Target/Mips/Mips16FrameLowering.cpp b/lib/Target/Mips/Mips16FrameLowering.cpp
index 028b049..c01d03a 100644
--- a/lib/Target/Mips/Mips16FrameLowering.cpp
+++ b/lib/Target/Mips/Mips16FrameLowering.cpp
@@ -71,7 +71,7 @@ void Mips16FrameLowering::emitPrologue(MachineFunction &MF) const {
}
if (hasFP(MF))
BuildMI(MBB, MBBI, dl, TII.get(Mips::MoveR3216), Mips::S0)
- .addReg(Mips::SP);
+ .addReg(Mips::SP).setMIFlag(MachineInstr::FrameSetup);
}
diff --git a/lib/Target/Mips/Mips16FrameLowering.h b/lib/Target/Mips/Mips16FrameLowering.h
index 8ce2ced..3f7829d 100644
--- a/lib/Target/Mips/Mips16FrameLowering.h
+++ b/lib/Target/Mips/Mips16FrameLowering.h
@@ -24,27 +24,27 @@ public:
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
/// the function.
- void emitPrologue(MachineFunction &MF) const;
- void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
+ void emitPrologue(MachineFunction &MF) const override;
+ void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
void eliminateCallFramePseudoInstr(MachineFunction &MF,
- MachineBasicBlock &MBB,
- MachineBasicBlock::iterator I) const;
+ MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator I) const override;
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &CSI,
- const TargetRegisterInfo *TRI) const;
+ const TargetRegisterInfo *TRI) const override;
bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI,
- const std::vector<CalleeSavedInfo> &CSI,
- const TargetRegisterInfo *TRI) const;
+ MachineBasicBlock::iterator MI,
+ const std::vector<CalleeSavedInfo> &CSI,
+ const TargetRegisterInfo *TRI) const override;
- bool hasReservedCallFrame(const MachineFunction &MF) const;
+ bool hasReservedCallFrame(const MachineFunction &MF) const override;
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
- RegScavenger *RS) const;
+ RegScavenger *RS) const override;
};
} // End llvm namespace
diff --git a/lib/Target/Mips/Mips16HardFloat.cpp b/lib/Target/Mips/Mips16HardFloat.cpp
index d321e21..14055d6 100644
--- a/lib/Target/Mips/Mips16HardFloat.cpp
+++ b/lib/Target/Mips/Mips16HardFloat.cpp
@@ -11,7 +11,6 @@
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "mips16-hard-float"
#include "Mips16HardFloat.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Value.h"
@@ -20,6 +19,8 @@
#include <algorithm>
#include <string>
+#define DEBUG_TYPE "mips16-hard-float"
+
static void inlineAsmOut
(LLVMContext &C, StringRef AsmString, BasicBlock *BB ) {
std::vector<llvm::Type *> AsmArgTypes;
@@ -354,9 +355,8 @@ static const char *IntrinsicInline[] =
};
static bool isIntrinsicInline(Function *F) {
- return std::binary_search(
- IntrinsicInline, array_endof(IntrinsicInline),
- F->getName());
+ return std::binary_search(std::begin(IntrinsicInline),
+ std::end(IntrinsicInline), F->getName());
}
//
// Returns of float, double and complex need to be handled with a helper
@@ -407,11 +407,11 @@ static bool fixupFPReturnAndCall
CallInst::Create(F, Params, "", &Inst );
} else if (const CallInst *CI = dyn_cast<CallInst>(I)) {
const Value* V = CI->getCalledValue();
- const Type* T = 0;
+ const Type* T = nullptr;
if (V) T = V->getType();
- const PointerType *PFT=0;
+ const PointerType *PFT=nullptr;
if (T) PFT = dyn_cast<PointerType>(T);
- const FunctionType *FT=0;
+ const FunctionType *FT=nullptr;
if (PFT) FT = dyn_cast<FunctionType>(PFT->getElementType());
Function *F_ = CI->getCalledFunction();
if (FT && needsFPReturnHelper(*FT) &&
diff --git a/lib/Target/Mips/Mips16HardFloat.h b/lib/Target/Mips/Mips16HardFloat.h
index b7f712a..826887e 100644
--- a/lib/Target/Mips/Mips16HardFloat.h
+++ b/lib/Target/Mips/Mips16HardFloat.h
@@ -34,11 +34,11 @@ public:
TM(TM_), Subtarget(TM.getSubtarget<MipsSubtarget>()) {
}
- virtual const char *getPassName() const {
+ const char *getPassName() const override {
return "MIPS16 Hard Float Pass";
}
- virtual bool runOnModule(Module &M);
+ bool runOnModule(Module &M) override;
protected:
/// Keep a pointer to the MipsSubtarget around so that we can make the right
diff --git a/lib/Target/Mips/Mips16HardFloatInfo.cpp b/lib/Target/Mips/Mips16HardFloatInfo.cpp
index d8b685e..2eb6e5d 100644
--- a/lib/Target/Mips/Mips16HardFloatInfo.cpp
+++ b/lib/Target/Mips/Mips16HardFloatInfo.cpp
@@ -30,7 +30,7 @@ const FuncNameSignature PredefinedFuncs[] = {
{ "__fixunssfsi", { FSig, NoFPRet } },
{ "__fixunssfdi", { FSig, NoFPRet } },
{ "__floatundisf", { NoSig, FRet } },
- { 0, { NoSig, NoFPRet } }
+ { nullptr, { NoSig, NoFPRet } }
};
// just do a search for now. there are very few of these special cases.
@@ -44,7 +44,7 @@ extern FuncSignature const *findFuncSignature(const char *name) {
return &PredefinedFuncs[i].Signature;
i++;
}
- return 0;
+ return nullptr;
}
}
}
diff --git a/lib/Target/Mips/Mips16ISelDAGToDAG.cpp b/lib/Target/Mips/Mips16ISelDAGToDAG.cpp
index 9e36546..4e86a27 100644
--- a/lib/Target/Mips/Mips16ISelDAGToDAG.cpp
+++ b/lib/Target/Mips/Mips16ISelDAGToDAG.cpp
@@ -11,7 +11,6 @@
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "mips-isel"
#include "Mips16ISelDAGToDAG.h"
#include "MCTargetDesc/MipsBaseInfo.h"
#include "Mips.h"
@@ -35,6 +34,8 @@
#include "llvm/Target/TargetMachine.h"
using namespace llvm;
+#define DEBUG_TYPE "mips-isel"
+
bool Mips16DAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
if (!Subtarget.inMips16Mode())
return false;
@@ -44,7 +45,7 @@ bool Mips16DAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
std::pair<SDNode*, SDNode*>
Mips16DAGToDAGISel::selectMULT(SDNode *N, unsigned Opc, SDLoc DL, EVT Ty,
bool HasLo, bool HasHi) {
- SDNode *Lo = 0, *Hi = 0;
+ SDNode *Lo = nullptr, *Hi = nullptr;
SDNode *Mul = CurDAG->getMachineNode(Opc, DL, MVT::Glue, N->getOperand(0),
N->getOperand(1));
SDValue InFlag = SDValue(Mul, 0);
@@ -224,10 +225,12 @@ bool Mips16DAGToDAGISel::selectAddr16(
// If an indexed floating point load/store can be emitted, return false.
const LSBaseSDNode *LS = dyn_cast<LSBaseSDNode>(Parent);
- if (LS &&
- (LS->getMemoryVT() == MVT::f32 || LS->getMemoryVT() == MVT::f64) &&
- Subtarget.hasFPIdx())
- return false;
+ if (LS) {
+ if (LS->getMemoryVT() == MVT::f32 && Subtarget.hasMips4_32r2())
+ return false;
+ if (LS->getMemoryVT() == MVT::f64 && Subtarget.hasMips4_32r2())
+ return false;
+ }
}
Base = Addr;
Offset = CurDAG->getTargetConstant(0, ValTy);
@@ -297,7 +300,7 @@ std::pair<bool, SDNode*> Mips16DAGToDAGISel::selectNode(SDNode *Node) {
if (!SDValue(Node, 1).use_empty())
ReplaceUses(SDValue(Node, 1), SDValue(LoHi.second, 0));
- return std::make_pair(true, (SDNode*)NULL);
+ return std::make_pair(true, nullptr);
}
case ISD::MULHS:
@@ -308,7 +311,7 @@ std::pair<bool, SDNode*> Mips16DAGToDAGISel::selectNode(SDNode *Node) {
}
}
- return std::make_pair(false, (SDNode*)NULL);
+ return std::make_pair(false, nullptr);
}
FunctionPass *llvm::createMips16ISelDag(MipsTargetMachine &TM) {
diff --git a/lib/Target/Mips/Mips16ISelDAGToDAG.h b/lib/Target/Mips/Mips16ISelDAGToDAG.h
index 49dc6e5..e653b39 100644
--- a/lib/Target/Mips/Mips16ISelDAGToDAG.h
+++ b/lib/Target/Mips/Mips16ISelDAGToDAG.h
@@ -28,16 +28,16 @@ private:
SDValue getMips16SPAliasReg();
- virtual bool runOnMachineFunction(MachineFunction &MF);
+ bool runOnMachineFunction(MachineFunction &MF) override;
void getMips16SPRefReg(SDNode *Parent, SDValue &AliasReg);
- virtual bool selectAddr16(SDNode *Parent, SDValue N, SDValue &Base,
- SDValue &Offset, SDValue &Alias);
+ bool selectAddr16(SDNode *Parent, SDValue N, SDValue &Base,
+ SDValue &Offset, SDValue &Alias) override;
- virtual std::pair<bool, SDNode*> selectNode(SDNode *Node);
+ std::pair<bool, SDNode*> selectNode(SDNode *Node) override;
- virtual void processFunctionAfterISel(MachineFunction &MF);
+ void processFunctionAfterISel(MachineFunction &MF) override;
// Insert instructions to initialize the global base register in the
// first MBB of the function.
diff --git a/lib/Target/Mips/Mips16ISelLowering.cpp b/lib/Target/Mips/Mips16ISelLowering.cpp
index 5c6f302..9102450 100644
--- a/lib/Target/Mips/Mips16ISelLowering.cpp
+++ b/lib/Target/Mips/Mips16ISelLowering.cpp
@@ -10,7 +10,6 @@
// Subclass of MipsTargetLowering specialized for mips16.
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "mips-lower"
#include "Mips16ISelLowering.h"
#include "MCTargetDesc/MipsBaseInfo.h"
#include "MipsRegisterInfo.h"
@@ -23,6 +22,8 @@
using namespace llvm;
+#define DEBUG_TYPE "mips-lower"
+
static cl::opt<bool> DontExpandCondPseudos16(
"mips16-dont-expand-cond-pseudo",
cl::init(false),
@@ -353,7 +354,7 @@ unsigned int Mips16TargetLowering::getMips16HelperFunctionStubNumber
#define T P "0" , T1
#define P P_
static char const * vMips16Helper[MAX_STUB_NUMBER+1] =
- {0, T1 };
+ {nullptr, T1 };
#undef P
#define P P_ "sf_"
static char const * sfMips16Helper[MAX_STUB_NUMBER+1] =
@@ -430,7 +431,7 @@ getOpndList(SmallVectorImpl<SDValue> &Ops,
SelectionDAG &DAG = CLI.DAG;
MachineFunction &MF = DAG.getMachineFunction();
MipsFunctionInfo *FuncInfo = MF.getInfo<MipsFunctionInfo>();
- const char* Mips16HelperFunction = 0;
+ const char* Mips16HelperFunction = nullptr;
bool NeedMips16Helper = false;
if (Subtarget->inMips16HardFloat()) {
@@ -443,8 +444,8 @@ getOpndList(SmallVectorImpl<SDValue> &Ops,
if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(CLI.Callee)) {
Mips16Libcall Find = { RTLIB::UNKNOWN_LIBCALL, S->getSymbol() };
- if (std::binary_search(HardFloatLibCalls, array_endof(HardFloatLibCalls),
- Find))
+ if (std::binary_search(std::begin(HardFloatLibCalls),
+ std::end(HardFloatLibCalls), Find))
LookupHelper = false;
else {
const char *Symbol = S->getSymbol();
@@ -471,13 +472,12 @@ getOpndList(SmallVectorImpl<SDValue> &Ops,
FuncInfo->setSaveS2();
}
// one more look at list of intrinsics
- if (std::binary_search(Mips16IntrinsicHelper,
- array_endof(Mips16IntrinsicHelper),
- IntrinsicFind)) {
- const Mips16IntrinsicHelperType *h =(std::find(Mips16IntrinsicHelper,
- array_endof(Mips16IntrinsicHelper),
- IntrinsicFind));
- Mips16HelperFunction = h->Helper;
+ const Mips16IntrinsicHelperType *Helper =
+ std::lower_bound(std::begin(Mips16IntrinsicHelper),
+ std::end(Mips16IntrinsicHelper), IntrinsicFind);
+ if (Helper != std::end(Mips16IntrinsicHelper) &&
+ *Helper == IntrinsicFind) {
+ Mips16HelperFunction = Helper->Helper;
NeedMips16Helper = true;
LookupHelper = false;
}
@@ -488,13 +488,13 @@ getOpndList(SmallVectorImpl<SDValue> &Ops,
Mips16Libcall Find = { RTLIB::UNKNOWN_LIBCALL,
G->getGlobal()->getName().data() };
- if (std::binary_search(HardFloatLibCalls, array_endof(HardFloatLibCalls),
- Find))
+ if (std::binary_search(std::begin(HardFloatLibCalls),
+ std::end(HardFloatLibCalls), Find))
LookupHelper = false;
}
- if (LookupHelper) Mips16HelperFunction =
- getMips16HelperFunction(CLI.RetTy, CLI.Args, NeedMips16Helper);
-
+ if (LookupHelper)
+ Mips16HelperFunction =
+ getMips16HelperFunction(CLI.RetTy, CLI.getArgs(), NeedMips16Helper);
}
SDValue JumpTarget = Callee;
diff --git a/lib/Target/Mips/Mips16ISelLowering.h b/lib/Target/Mips/Mips16ISelLowering.h
index 618ec90..df88333 100644
--- a/lib/Target/Mips/Mips16ISelLowering.h
+++ b/lib/Target/Mips/Mips16ISelLowering.h
@@ -21,17 +21,17 @@ namespace llvm {
public:
explicit Mips16TargetLowering(MipsTargetMachine &TM);
- virtual bool allowsUnalignedMemoryAccesses(EVT VT, unsigned AddrSpace,
- bool *Fast) const;
+ bool allowsUnalignedMemoryAccesses(EVT VT, unsigned AddrSpace,
+ bool *Fast) const override;
- virtual MachineBasicBlock *
- EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB) const;
+ MachineBasicBlock *
+ EmitInstrWithCustomInserter(MachineInstr *MI,
+ MachineBasicBlock *MBB) const override;
private:
- virtual bool
- isEligibleForTailCallOptimization(const MipsCC &MipsCCInfo,
- unsigned NextStackOffset,
- const MipsFunctionInfo& FI) const;
+ bool isEligibleForTailCallOptimization(const MipsCC &MipsCCInfo,
+ unsigned NextStackOffset,
+ const MipsFunctionInfo& FI) const override;
void setMips16HardFloatLibCalls();
@@ -41,11 +41,12 @@ namespace llvm {
const char *getMips16HelperFunction
(Type* RetTy, ArgListTy &Args, bool &needHelper) const;
- virtual void
+ void
getOpndList(SmallVectorImpl<SDValue> &Ops,
std::deque< std::pair<unsigned, SDValue> > &RegsToPass,
bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage,
- CallLoweringInfo &CLI, SDValue Callee, SDValue Chain) const;
+ CallLoweringInfo &CLI, SDValue Callee,
+ SDValue Chain) const override;
MachineBasicBlock *emitSel16(unsigned Opc, MachineInstr *MI,
MachineBasicBlock *BB) const;
diff --git a/lib/Target/Mips/Mips16InstrInfo.cpp b/lib/Target/Mips/Mips16InstrInfo.cpp
index 43c2fbd..79607de 100644
--- a/lib/Target/Mips/Mips16InstrInfo.cpp
+++ b/lib/Target/Mips/Mips16InstrInfo.cpp
@@ -29,6 +29,7 @@
using namespace llvm;
+#define DEBUG_TYPE "mips16-instrinfo"
Mips16InstrInfo::Mips16InstrInfo(MipsTargetMachine &tm)
: MipsInstrInfo(tm, Mips::Bimm16),
diff --git a/lib/Target/Mips/Mips16InstrInfo.h b/lib/Target/Mips/Mips16InstrInfo.h
index e93925c..0dc0046 100644
--- a/lib/Target/Mips/Mips16InstrInfo.h
+++ b/lib/Target/Mips/Mips16InstrInfo.h
@@ -25,46 +25,46 @@ class Mips16InstrInfo : public MipsInstrInfo {
public:
explicit Mips16InstrInfo(MipsTargetMachine &TM);
- virtual const MipsRegisterInfo &getRegisterInfo() const;
+ const MipsRegisterInfo &getRegisterInfo() const override;
/// isLoadFromStackSlot - If the specified machine instruction is a direct
/// load from a stack slot, return the virtual or physical register number of
/// 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.
- virtual unsigned isLoadFromStackSlot(const MachineInstr *MI,
- int &FrameIndex) const;
+ unsigned isLoadFromStackSlot(const MachineInstr *MI,
+ int &FrameIndex) const override;
/// isStoreToStackSlot - If the specified machine instruction is a direct
/// store to a stack slot, return the virtual or physical register number of
/// 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.
- virtual unsigned isStoreToStackSlot(const MachineInstr *MI,
- int &FrameIndex) const;
+ unsigned isStoreToStackSlot(const MachineInstr *MI,
+ int &FrameIndex) const override;
- virtual void copyPhysReg(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI, DebugLoc DL,
- unsigned DestReg, unsigned SrcReg,
- bool KillSrc) const;
+ void copyPhysReg(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI, DebugLoc DL,
+ unsigned DestReg, unsigned SrcReg,
+ bool KillSrc) const override;
- virtual void storeRegToStack(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MBBI,
- unsigned SrcReg, bool isKill, int FrameIndex,
- const TargetRegisterClass *RC,
- const TargetRegisterInfo *TRI,
- int64_t Offset) const;
+ void storeRegToStack(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MBBI,
+ unsigned SrcReg, bool isKill, int FrameIndex,
+ const TargetRegisterClass *RC,
+ const TargetRegisterInfo *TRI,
+ int64_t Offset) const override;
- virtual void loadRegFromStack(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MBBI,
- unsigned DestReg, int FrameIndex,
- const TargetRegisterClass *RC,
- const TargetRegisterInfo *TRI,
- int64_t Offset) const;
+ void loadRegFromStack(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MBBI,
+ unsigned DestReg, int FrameIndex,
+ const TargetRegisterClass *RC,
+ const TargetRegisterInfo *TRI,
+ int64_t Offset) const override;
- virtual bool expandPostRAPseudo(MachineBasicBlock::iterator MI) const;
+ bool expandPostRAPseudo(MachineBasicBlock::iterator MI) const override;
- virtual unsigned getOppositeBranchOpc(unsigned Opc) const;
+ unsigned getOppositeBranchOpc(unsigned Opc) const override;
// Adjust SP by FrameSize bytes. Save RA, S0, S1
void makeFrame(unsigned SP, int64_t FrameSize, MachineBasicBlock &MBB,
@@ -104,9 +104,9 @@ public:
(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, int64_t Imm) const;
unsigned getInlineAsmLength(const char *Str,
- const MCAsmInfo &MAI) const;
+ const MCAsmInfo &MAI) const override;
private:
- virtual unsigned getAnalyzableBrOpc(unsigned Opc) const;
+ unsigned getAnalyzableBrOpc(unsigned Opc) const override;
void ExpandRetRA16(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
unsigned Opc) const;
diff --git a/lib/Target/Mips/Mips16RegisterInfo.cpp b/lib/Target/Mips/Mips16RegisterInfo.cpp
index 3a50ed9..dbee774 100644
--- a/lib/Target/Mips/Mips16RegisterInfo.cpp
+++ b/lib/Target/Mips/Mips16RegisterInfo.cpp
@@ -39,6 +39,8 @@
using namespace llvm;
+#define DEBUG_TYPE "mips16-registerinfo"
+
Mips16RegisterInfo::Mips16RegisterInfo(const MipsSubtarget &ST)
: MipsRegisterInfo(ST) {}
diff --git a/lib/Target/Mips/Mips16RegisterInfo.h b/lib/Target/Mips/Mips16RegisterInfo.h
index 13e82a3..f59f1a7 100644
--- a/lib/Target/Mips/Mips16RegisterInfo.h
+++ b/lib/Target/Mips/Mips16RegisterInfo.h
@@ -23,24 +23,24 @@ class Mips16RegisterInfo : public MipsRegisterInfo {
public:
Mips16RegisterInfo(const MipsSubtarget &Subtarget);
- bool requiresRegisterScavenging(const MachineFunction &MF) const;
+ bool requiresRegisterScavenging(const MachineFunction &MF) const override;
- bool requiresFrameIndexScavenging(const MachineFunction &MF) const;
+ bool requiresFrameIndexScavenging(const MachineFunction &MF) const override;
- bool useFPForScavengingIndex(const MachineFunction &MF) const;
+ bool useFPForScavengingIndex(const MachineFunction &MF) const override;
bool saveScavengerRegister(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
MachineBasicBlock::iterator &UseMI,
const TargetRegisterClass *RC,
- unsigned Reg) const;
+ unsigned Reg) const override;
- virtual const TargetRegisterClass *intRegClass(unsigned Size) const;
+ const TargetRegisterClass *intRegClass(unsigned Size) const override;
private:
- virtual void eliminateFI(MachineBasicBlock::iterator II, unsigned OpNo,
- int FrameIndex, uint64_t StackSize,
- int64_t SPOffset) const;
+ void eliminateFI(MachineBasicBlock::iterator II, unsigned OpNo,
+ int FrameIndex, uint64_t StackSize,
+ int64_t SPOffset) const override;
};
} // end namespace llvm
diff --git a/lib/Target/Mips/Mips32r6InstrFormats.td b/lib/Target/Mips/Mips32r6InstrFormats.td
new file mode 100644
index 0000000..a3f9df5
--- /dev/null
+++ b/lib/Target/Mips/Mips32r6InstrFormats.td
@@ -0,0 +1,386 @@
+//=- Mips32r6InstrFormats.td - Mips32r6 Instruction Formats -*- tablegen -*-==//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file describes Mips32r6 instruction formats.
+//
+//===----------------------------------------------------------------------===//
+
+class MipsR6Inst : MipsInst<(outs), (ins), "", [], NoItinerary, FrmOther>,
+ PredicateControl {
+ let DecoderNamespace = "Mips32r6_64r6";
+ let EncodingPredicates = [HasStdEnc];
+}
+
+//===----------------------------------------------------------------------===//
+//
+// Field Values
+//
+//===----------------------------------------------------------------------===//
+
+class OPGROUP<bits<6> Val> {
+ bits<6> Value = Val;
+}
+def OPGROUP_COP1 : OPGROUP<0b010001>;
+def OPGROUP_COP2 : OPGROUP<0b010010>;
+def OPGROUP_ADDI : OPGROUP<0b001000>;
+def OPGROUP_AUI : OPGROUP<0b001111>;
+def OPGROUP_BLEZ : OPGROUP<0b000110>;
+def OPGROUP_BGTZ : OPGROUP<0b000111>;
+def OPGROUP_BLEZL : OPGROUP<0b010110>;
+def OPGROUP_BGTZL : OPGROUP<0b010111>;
+def OPGROUP_DADDI : OPGROUP<0b011000>;
+def OPGROUP_DAUI : OPGROUP<0b011101>;
+def OPGROUP_PCREL : OPGROUP<0b111011>;
+def OPGROUP_REGIMM : OPGROUP<0b000001>;
+def OPGROUP_SPECIAL : OPGROUP<0b000000>;
+def OPGROUP_SPECIAL3 : OPGROUP<0b011111>;
+
+class OPCODE2<bits<2> Val> {
+ bits<2> Value = Val;
+}
+def OPCODE2_ADDIUPC : OPCODE2<0b00>;
+def OPCODE2_LWPC : OPCODE2<0b01>;
+def OPCODE2_LWUPC : OPCODE2<0b10>;
+
+class OPCODE5<bits<5> Val> {
+ bits<5> Value = Val;
+}
+def OPCODE5_ALUIPC : OPCODE5<0b11111>;
+def OPCODE5_AUIPC : OPCODE5<0b11110>;
+def OPCODE5_DAHI : OPCODE5<0b00110>;
+def OPCODE5_DATI : OPCODE5<0b11110>;
+def OPCODE5_BC1EQZ : OPCODE5<0b01001>;
+def OPCODE5_BC1NEZ : OPCODE5<0b01101>;
+def OPCODE5_BC2EQZ : OPCODE5<0b01001>;
+def OPCODE5_BC2NEZ : OPCODE5<0b01101>;
+
+class OPCODE6<bits<6> Val> {
+ bits<6> Value = Val;
+}
+def OPCODE6_ALIGN : OPCODE6<0b100000>;
+def OPCODE6_DALIGN : OPCODE6<0b100100>;
+def OPCODE6_BITSWAP : OPCODE6<0b100000>;
+def OPCODE6_DBITSWAP : OPCODE6<0b100100>;
+
+class FIELD_FMT<bits<5> Val> {
+ bits<5> Value = Val;
+}
+def FIELD_FMT_S : FIELD_FMT<0b10000>;
+def FIELD_FMT_D : FIELD_FMT<0b10001>;
+
+class FIELD_CMP_COND<bits<5> Val> {
+ bits<5> Value = Val;
+}
+def FIELD_CMP_COND_F : FIELD_CMP_COND<0b00000>;
+def FIELD_CMP_COND_UN : FIELD_CMP_COND<0b00001>;
+def FIELD_CMP_COND_EQ : FIELD_CMP_COND<0b00010>;
+def FIELD_CMP_COND_UEQ : FIELD_CMP_COND<0b00011>;
+def FIELD_CMP_COND_OLT : FIELD_CMP_COND<0b00100>;
+def FIELD_CMP_COND_ULT : FIELD_CMP_COND<0b00101>;
+def FIELD_CMP_COND_OLE : FIELD_CMP_COND<0b00110>;
+def FIELD_CMP_COND_ULE : FIELD_CMP_COND<0b00111>;
+def FIELD_CMP_COND_SF : FIELD_CMP_COND<0b01000>;
+def FIELD_CMP_COND_NGLE : FIELD_CMP_COND<0b01001>;
+def FIELD_CMP_COND_SEQ : FIELD_CMP_COND<0b01010>;
+def FIELD_CMP_COND_NGL : FIELD_CMP_COND<0b01011>;
+def FIELD_CMP_COND_LT : FIELD_CMP_COND<0b01100>;
+def FIELD_CMP_COND_NGE : FIELD_CMP_COND<0b01101>;
+def FIELD_CMP_COND_LE : FIELD_CMP_COND<0b01110>;
+def FIELD_CMP_COND_NGT : FIELD_CMP_COND<0b01111>;
+
+class FIELD_CMP_FORMAT<bits<5> Val> {
+ bits<5> Value = Val;
+}
+def FIELD_CMP_FORMAT_S : FIELD_CMP_FORMAT<0b10100>;
+def FIELD_CMP_FORMAT_D : FIELD_CMP_FORMAT<0b10101>;
+
+//===----------------------------------------------------------------------===//
+//
+// Disambiguators
+//
+//===----------------------------------------------------------------------===//
+//
+// Some encodings are ambiguous except by comparing field values.
+
+class DecodeDisambiguates<string Name> {
+ string DecoderMethod = !strconcat("Decode", Name);
+}
+
+class DecodeDisambiguatedBy<string Name> : DecodeDisambiguates<Name> {
+ string DecoderNamespace = "Mips32r6_64r6_Ambiguous";
+}
+
+//===----------------------------------------------------------------------===//
+//
+// Encoding Formats
+//
+//===----------------------------------------------------------------------===//
+
+class AUI_FM : MipsR6Inst {
+ bits<5> rs;
+ bits<5> rt;
+ bits<16> imm;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = OPGROUP_AUI.Value;
+ let Inst{25-21} = rs;
+ let Inst{20-16} = rt;
+ let Inst{15-0} = imm;
+}
+
+class DAUI_FM : AUI_FM {
+ let Inst{31-26} = OPGROUP_DAUI.Value;
+}
+
+class COP1_2R_FM<bits<6> funct, FIELD_FMT Format> : MipsR6Inst {
+ bits<5> fs;
+ bits<5> fd;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = OPGROUP_COP1.Value;
+ let Inst{25-21} = Format.Value;
+ let Inst{20-16} = 0b00000;
+ let Inst{15-11} = fs;
+ let Inst{10-6} = fd;
+ let Inst{5-0} = funct;
+}
+
+class COP1_3R_FM<bits<6> funct, FIELD_FMT Format> : MipsR6Inst {
+ bits<5> ft;
+ bits<5> fs;
+ bits<5> fd;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = OPGROUP_COP1.Value;
+ let Inst{25-21} = Format.Value;
+ let Inst{20-16} = ft;
+ let Inst{15-11} = fs;
+ let Inst{10-6} = fd;
+ let Inst{5-0} = funct;
+}
+
+class COP1_BCCZ_FM<OPCODE5 Operation> : MipsR6Inst {
+ bits<5> ft;
+ bits<16> offset;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = OPGROUP_COP1.Value;
+ let Inst{25-21} = Operation.Value;
+ let Inst{20-16} = ft;
+ let Inst{15-0} = offset;
+}
+
+class COP2_BCCZ_FM<OPCODE5 Operation> : MipsR6Inst {
+ bits<5> ct;
+ bits<16> offset;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = OPGROUP_COP2.Value;
+ let Inst{25-21} = Operation.Value;
+ let Inst{20-16} = ct;
+ let Inst{15-0} = offset;
+}
+
+class PCREL16_FM<OPCODE5 Operation> : MipsR6Inst {
+ bits<5> rs;
+ bits<16> imm;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = OPGROUP_PCREL.Value;
+ let Inst{25-21} = rs;
+ let Inst{20-16} = Operation.Value;
+ let Inst{15-0} = imm;
+}
+
+class PCREL19_FM<OPCODE2 Operation> : MipsR6Inst {
+ bits<5> rs;
+ bits<19> imm;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = OPGROUP_PCREL.Value;
+ let Inst{25-21} = rs;
+ let Inst{20-19} = Operation.Value;
+ let Inst{18-0} = imm;
+}
+
+class SPECIAL3_2R_FM<OPCODE6 Operation> : MipsR6Inst {
+ bits<5> rd;
+ bits<5> rt;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = OPGROUP_SPECIAL3.Value;
+ let Inst{25-21} = 0b00000;
+ let Inst{20-16} = rt;
+ let Inst{15-11} = rd;
+ let Inst{10-6} = 0b00000;
+ let Inst{5-0} = Operation.Value;
+}
+
+class SPECIAL_3R_FM<bits<5> mulop, bits<6> funct> : MipsR6Inst {
+ bits<5> rd;
+ bits<5> rs;
+ bits<5> rt;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = OPGROUP_SPECIAL.Value;
+ let Inst{25-21} = rs;
+ let Inst{20-16} = rt;
+ let Inst{15-11} = rd;
+ let Inst{10-6} = mulop;
+ let Inst{5-0} = funct;
+}
+
+// This class is ambiguous with other branches:
+// BEQC/BNEC require that rs > rt
+class CMP_BRANCH_2R_OFF16_FM<OPGROUP funct> : MipsR6Inst {
+ bits<5> rs;
+ bits<5> rt;
+ bits<16> offset;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = funct.Value;
+ let Inst{25-21} = rs;
+ let Inst{20-16} = rt;
+ let Inst{15-0} = offset;
+}
+
+// This class is ambiguous with other branches:
+// BLEZC/BGEZC/BEQZALC/BNEZALC/BGTZALC require that rs == 0 && rt != 0
+// The '1R_RT' in the name means 1 register in the rt field.
+class CMP_BRANCH_1R_RT_OFF16_FM<OPGROUP funct> : MipsR6Inst {
+ bits<5> rt;
+ bits<16> offset;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = funct.Value;
+ let Inst{25-21} = 0b00000;
+ let Inst{20-16} = rt;
+ let Inst{15-0} = offset;
+}
+
+// This class is ambiguous with other branches:
+// BLTZC/BGTZC/BLTZALC/BGEZALC require that rs == rt && rt != 0
+// The '1R_BOTH' in the name means 1 register in both the rs and rt fields.
+class CMP_BRANCH_1R_BOTH_OFF16_FM<OPGROUP funct> : MipsR6Inst {
+ bits<5> rt;
+ bits<16> offset;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = funct.Value;
+ let Inst{25-21} = rt;
+ let Inst{20-16} = rt;
+ let Inst{15-0} = offset;
+}
+
+class CMP_BRANCH_OFF21_FM<bits<6> funct> : MipsR6Inst {
+ bits<5> rs; // rs != 0
+ bits<21> offset;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = funct;
+ let Inst{25-21} = rs;
+ let Inst{20-0} = offset;
+}
+
+class JMP_IDX_COMPACT_FM<bits<6> funct> : MipsR6Inst {
+ bits<5> rt;
+ bits<16> offset;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = funct;
+ let Inst{25-21} = 0b000000;
+ let Inst{20-16} = rt;
+ let Inst{15-0} = offset;
+}
+
+class BRANCH_OFF26_FM<bits<6> funct> : MipsR6Inst {
+ bits<32> Inst;
+ bits<26> offset;
+
+ let Inst{31-26} = funct;
+ let Inst{25-0} = offset;
+}
+
+class SPECIAL3_ALIGN_FM<OPCODE6 Operation> : MipsR6Inst {
+ bits<5> rd;
+ bits<5> rs;
+ bits<5> rt;
+ bits<2> bp;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = OPGROUP_SPECIAL3.Value;
+ let Inst{25-21} = rs;
+ let Inst{20-16} = rt;
+ let Inst{15-11} = rd;
+ let Inst{10-8} = 0b010;
+ let Inst{7-6} = bp;
+ let Inst{5-0} = Operation.Value;
+}
+
+class SPECIAL3_DALIGN_FM<OPCODE6 Operation> : MipsR6Inst {
+ bits<5> rd;
+ bits<5> rs;
+ bits<5> rt;
+ bits<3> bp;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = OPGROUP_SPECIAL3.Value;
+ let Inst{25-21} = rs;
+ let Inst{20-16} = rt;
+ let Inst{15-11} = rd;
+ let Inst{10-9} = 0b01;
+ let Inst{8-6} = bp;
+ let Inst{5-0} = Operation.Value;
+}
+
+class REGIMM_FM<OPCODE5 Operation> : MipsR6Inst {
+ bits<5> rs;
+ bits<16> imm;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = OPGROUP_REGIMM.Value;
+ let Inst{25-21} = rs;
+ let Inst{20-16} = Operation.Value;
+ let Inst{15-0} = imm;
+}
+
+class COP1_CMP_CONDN_FM<FIELD_CMP_FORMAT Format,
+ FIELD_CMP_COND Cond> : MipsR6Inst {
+ bits<5> fd;
+ bits<5> fs;
+ bits<5> ft;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = OPGROUP_COP1.Value;
+ let Inst{25-21} = Format.Value;
+ let Inst{20-16} = ft;
+ let Inst{15-11} = fs;
+ let Inst{10-6} = fd;
+ let Inst{5} = 0;
+ let Inst{4-0} = Cond.Value;
+}
+
diff --git a/lib/Target/Mips/Mips32r6InstrInfo.td b/lib/Target/Mips/Mips32r6InstrInfo.td
new file mode 100644
index 0000000..ffaf965
--- /dev/null
+++ b/lib/Target/Mips/Mips32r6InstrInfo.td
@@ -0,0 +1,583 @@
+//=- Mips32r6InstrInfo.td - Mips32r6 Instruction Information -*- tablegen -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file describes Mips32r6 instructions.
+//
+//===----------------------------------------------------------------------===//
+
+include "Mips32r6InstrFormats.td"
+
+// Notes about removals/changes from MIPS32r6:
+// Unclear: ssnop
+// Reencoded: cache, pref
+// Reencoded: clo, clz
+// Reencoded: jr -> jalr
+// Reencoded: jr.hb -> jalr.hb
+// Reencoded: ldc2
+// Reencoded: ll, sc
+// Reencoded: lwc2
+// Reencoded: sdbbp
+// Reencoded: sdc2
+// Reencoded: swc2
+// Removed: bc1any2, bc1any4
+// Removed: bc2[ft]
+// Removed: bc2f, bc2t
+// Removed: bgezal
+// Removed: bltzal
+// Removed: c.cond.fmt, bc1[ft]
+// Removed: div, divu
+// Removed: jalx
+// Removed: ldxc1
+// Removed: luxc1
+// Removed: lwxc1
+// Removed: madd.[ds], nmadd.[ds], nmsub.[ds], sub.[ds]
+// Removed: mfhi, mflo, mthi, mtlo, madd, maddu, msub, msubu, mul
+// Removed: movf, movt
+// Removed: movf.fmt, movt.fmt, movn.fmt, movz.fmt
+// Removed: movn, movz
+// Removed: mult, multu
+// Removed: prefx
+// Removed: sdxc1
+// Removed: suxc1
+// Removed: swxc1
+// Rencoded: [ls][wd]c2
+
+def brtarget21 : Operand<OtherVT> {
+ let EncoderMethod = "getBranchTarget21OpValue";
+ let OperandType = "OPERAND_PCREL";
+ let DecoderMethod = "DecodeBranchTarget21";
+ let ParserMatchClass = MipsJumpTargetAsmOperand;
+}
+
+def brtarget26 : Operand<OtherVT> {
+ let EncoderMethod = "getBranchTarget26OpValue";
+ let OperandType = "OPERAND_PCREL";
+ let DecoderMethod = "DecodeBranchTarget26";
+ let ParserMatchClass = MipsJumpTargetAsmOperand;
+}
+
+def jmpoffset16 : Operand<OtherVT> {
+ let EncoderMethod = "getJumpOffset16OpValue";
+ let ParserMatchClass = MipsJumpTargetAsmOperand;
+}
+
+def calloffset16 : Operand<iPTR> {
+ let EncoderMethod = "getJumpOffset16OpValue";
+ let ParserMatchClass = MipsJumpTargetAsmOperand;
+}
+
+//===----------------------------------------------------------------------===//
+//
+// Instruction Encodings
+//
+//===----------------------------------------------------------------------===//
+
+class ADDIUPC_ENC : PCREL19_FM<OPCODE2_ADDIUPC>;
+class ALIGN_ENC : SPECIAL3_ALIGN_FM<OPCODE6_ALIGN>;
+class ALUIPC_ENC : PCREL16_FM<OPCODE5_ALUIPC>;
+class AUI_ENC : AUI_FM;
+class AUIPC_ENC : PCREL16_FM<OPCODE5_AUIPC>;
+
+class BALC_ENC : BRANCH_OFF26_FM<0b111010>;
+class BC_ENC : BRANCH_OFF26_FM<0b110010>;
+class BEQC_ENC : CMP_BRANCH_2R_OFF16_FM<OPGROUP_ADDI>,
+ DecodeDisambiguates<"AddiGroupBranch">;
+class BEQZALC_ENC : CMP_BRANCH_1R_RT_OFF16_FM<OPGROUP_ADDI>,
+ DecodeDisambiguatedBy<"DaddiGroupBranch">;
+class BNEC_ENC : CMP_BRANCH_2R_OFF16_FM<OPGROUP_DADDI>,
+ DecodeDisambiguates<"DaddiGroupBranch">;
+class BNEZALC_ENC : CMP_BRANCH_1R_RT_OFF16_FM<OPGROUP_DADDI>,
+ DecodeDisambiguatedBy<"DaddiGroupBranch">;
+
+class BLTZC_ENC : CMP_BRANCH_1R_BOTH_OFF16_FM<OPGROUP_BGTZL>,
+ DecodeDisambiguates<"BgtzlGroupBranch">;
+class BGEZC_ENC : CMP_BRANCH_1R_BOTH_OFF16_FM<OPGROUP_BLEZL>,
+ DecodeDisambiguates<"BlezlGroupBranch">;
+class BGTZALC_ENC : CMP_BRANCH_1R_RT_OFF16_FM<OPGROUP_BGTZ>,
+ DecodeDisambiguatedBy<"BgtzGroupBranch">;
+
+class BLEZC_ENC : CMP_BRANCH_1R_RT_OFF16_FM<OPGROUP_BLEZL>,
+ DecodeDisambiguatedBy<"BlezlGroupBranch">;
+class BLTZALC_ENC : CMP_BRANCH_1R_BOTH_OFF16_FM<OPGROUP_BGTZ>,
+ DecodeDisambiguates<"BgtzGroupBranch">;
+class BGTZC_ENC : CMP_BRANCH_1R_RT_OFF16_FM<OPGROUP_BGTZL>,
+ DecodeDisambiguatedBy<"BgtzlGroupBranch">;
+
+class BEQZC_ENC : CMP_BRANCH_OFF21_FM<0b110110>;
+class BGEZALC_ENC : CMP_BRANCH_1R_BOTH_OFF16_FM<OPGROUP_BLEZ>;
+class BNEZC_ENC : CMP_BRANCH_OFF21_FM<0b111110>;
+
+class BC1EQZ_ENC : COP1_BCCZ_FM<OPCODE5_BC1EQZ>;
+class BC1NEZ_ENC : COP1_BCCZ_FM<OPCODE5_BC1NEZ>;
+class BC2EQZ_ENC : COP2_BCCZ_FM<OPCODE5_BC2EQZ>;
+class BC2NEZ_ENC : COP2_BCCZ_FM<OPCODE5_BC2NEZ>;
+
+class JIALC_ENC : JMP_IDX_COMPACT_FM<0b111110>;
+class JIC_ENC : JMP_IDX_COMPACT_FM<0b110110>;
+
+class BITSWAP_ENC : SPECIAL3_2R_FM<OPCODE6_BITSWAP>;
+class BLEZALC_ENC : CMP_BRANCH_1R_RT_OFF16_FM<OPGROUP_BLEZ>;
+class BNVC_ENC : CMP_BRANCH_2R_OFF16_FM<OPGROUP_DADDI>,
+ DecodeDisambiguatedBy<"DaddiGroupBranch">;
+class BOVC_ENC : CMP_BRANCH_2R_OFF16_FM<OPGROUP_ADDI>,
+ DecodeDisambiguatedBy<"AddiGroupBranch">;
+class DIV_ENC : SPECIAL_3R_FM<0b00010, 0b011010>;
+class DIVU_ENC : SPECIAL_3R_FM<0b00010, 0b011011>;
+class MOD_ENC : SPECIAL_3R_FM<0b00011, 0b011010>;
+class MODU_ENC : SPECIAL_3R_FM<0b00011, 0b011011>;
+class MUH_ENC : SPECIAL_3R_FM<0b00011, 0b011000>;
+class MUHU_ENC : SPECIAL_3R_FM<0b00011, 0b011001>;
+class MUL_R6_ENC : SPECIAL_3R_FM<0b00010, 0b011000>;
+class MULU_ENC : SPECIAL_3R_FM<0b00010, 0b011001>;
+
+class MADDF_S_ENC : COP1_3R_FM<0b011000, FIELD_FMT_S>;
+class MADDF_D_ENC : COP1_3R_FM<0b011000, FIELD_FMT_D>;
+class MSUBF_S_ENC : COP1_3R_FM<0b011001, FIELD_FMT_S>;
+class MSUBF_D_ENC : COP1_3R_FM<0b011001, FIELD_FMT_D>;
+
+class SEL_D_ENC : COP1_3R_FM<0b010000, FIELD_FMT_D>;
+class SEL_S_ENC : COP1_3R_FM<0b010000, FIELD_FMT_S>;
+
+class SELEQZ_ENC : SPECIAL_3R_FM<0b00000, 0b110101>;
+class SELNEZ_ENC : SPECIAL_3R_FM<0b00000, 0b110111>;
+
+class LWPC_ENC : PCREL19_FM<OPCODE2_LWPC>;
+class LWUPC_ENC : PCREL19_FM<OPCODE2_LWUPC>;
+
+class MAX_S_ENC : COP1_3R_FM<0b011101, FIELD_FMT_S>;
+class MAX_D_ENC : COP1_3R_FM<0b011101, FIELD_FMT_D>;
+class MIN_S_ENC : COP1_3R_FM<0b011100, FIELD_FMT_S>;
+class MIN_D_ENC : COP1_3R_FM<0b011100, FIELD_FMT_D>;
+
+class MAXA_S_ENC : COP1_3R_FM<0b011111, FIELD_FMT_S>;
+class MAXA_D_ENC : COP1_3R_FM<0b011111, FIELD_FMT_D>;
+class MINA_S_ENC : COP1_3R_FM<0b011110, FIELD_FMT_S>;
+class MINA_D_ENC : COP1_3R_FM<0b011110, FIELD_FMT_D>;
+
+class SELEQZ_S_ENC : COP1_3R_FM<0b010100, FIELD_FMT_S>;
+class SELEQZ_D_ENC : COP1_3R_FM<0b010100, FIELD_FMT_D>;
+class SELNEZ_S_ENC : COP1_3R_FM<0b010111, FIELD_FMT_S>;
+class SELNEZ_D_ENC : COP1_3R_FM<0b010111, FIELD_FMT_D>;
+
+class RINT_S_ENC : COP1_2R_FM<0b011010, FIELD_FMT_S>;
+class RINT_D_ENC : COP1_2R_FM<0b011010, FIELD_FMT_D>;
+class CLASS_S_ENC : COP1_2R_FM<0b011011, FIELD_FMT_S>;
+class CLASS_D_ENC : COP1_2R_FM<0b011011, FIELD_FMT_D>;
+
+class CMP_CONDN_DESC_BASE<string CondStr, string Typestr, RegisterOperand FGROpnd> {
+ dag OutOperandList = (outs FGROpnd:$fd);
+ dag InOperandList = (ins FGROpnd:$fs, FGROpnd:$ft);
+ string AsmString = !strconcat("cmp.", CondStr, ".", Typestr, "\t$fd, $fs, $ft");
+ list<dag> Pattern = [];
+}
+
+//===----------------------------------------------------------------------===//
+//
+// Instruction Multiclasses
+//
+//===----------------------------------------------------------------------===//
+
+multiclass CMP_CC_M <FIELD_CMP_FORMAT Format, string Typestr,
+ RegisterOperand FGROpnd>{
+ def CMP_F_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_F>,
+ CMP_CONDN_DESC_BASE<"f", Typestr, FGROpnd>,
+ ISA_MIPS32R6;
+ def CMP_UN_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_UN>,
+ CMP_CONDN_DESC_BASE<"un", Typestr, FGROpnd>,
+ ISA_MIPS32R6;
+ def CMP_EQ_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_EQ>,
+ CMP_CONDN_DESC_BASE<"eq", Typestr, FGROpnd>,
+ ISA_MIPS32R6;
+ def CMP_UEQ_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_UEQ>,
+ CMP_CONDN_DESC_BASE<"ueq", Typestr, FGROpnd>,
+ ISA_MIPS32R6;
+ def CMP_OLT_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_OLT>,
+ CMP_CONDN_DESC_BASE<"olt", Typestr, FGROpnd>,
+ ISA_MIPS32R6;
+ def CMP_ULT_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_ULT>,
+ CMP_CONDN_DESC_BASE<"ult", Typestr, FGROpnd>,
+ ISA_MIPS32R6;
+ def CMP_OLE_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_OLE>,
+ CMP_CONDN_DESC_BASE<"ole", Typestr, FGROpnd>,
+ ISA_MIPS32R6;
+ def CMP_ULE_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_ULE>,
+ CMP_CONDN_DESC_BASE<"ule", Typestr, FGROpnd>,
+ ISA_MIPS32R6;
+ def CMP_SF_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_SF>,
+ CMP_CONDN_DESC_BASE<"sf", Typestr, FGROpnd>,
+ ISA_MIPS32R6;
+ def CMP_NGLE_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_NGLE>,
+ CMP_CONDN_DESC_BASE<"ngle", Typestr, FGROpnd>,
+ ISA_MIPS32R6;
+ def CMP_SEQ_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_SEQ>,
+ CMP_CONDN_DESC_BASE<"seq", Typestr, FGROpnd>,
+ ISA_MIPS32R6;
+ def CMP_NGL_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_NGL>,
+ CMP_CONDN_DESC_BASE<"ngl", Typestr, FGROpnd>,
+ ISA_MIPS32R6;
+ def CMP_LT_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_LT>,
+ CMP_CONDN_DESC_BASE<"lt", Typestr, FGROpnd>,
+ ISA_MIPS32R6;
+ def CMP_NGE_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_NGE>,
+ CMP_CONDN_DESC_BASE<"nge", Typestr, FGROpnd>,
+ ISA_MIPS32R6;
+ def CMP_LE_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_LE>,
+ CMP_CONDN_DESC_BASE<"le", Typestr, FGROpnd>,
+ ISA_MIPS32R6;
+ def CMP_NGT_#NAME : COP1_CMP_CONDN_FM<Format, FIELD_CMP_COND_NGT>,
+ CMP_CONDN_DESC_BASE<"ngt", Typestr, FGROpnd>,
+ ISA_MIPS32R6;
+}
+
+//===----------------------------------------------------------------------===//
+//
+// Instruction Descriptions
+//
+//===----------------------------------------------------------------------===//
+
+class PCREL19_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> {
+ dag OutOperandList = (outs GPROpnd:$rs);
+ dag InOperandList = (ins simm19_lsl2:$imm);
+ string AsmString = !strconcat(instr_asm, "\t$rs, $imm");
+ list<dag> Pattern = [];
+}
+
+class ADDIUPC_DESC : PCREL19_DESC_BASE<"addiupc", GPR32Opnd>;
+class LWPC_DESC: PCREL19_DESC_BASE<"lwpc", GPR32Opnd>;
+class LWUPC_DESC: PCREL19_DESC_BASE<"lwupc", GPR32Opnd>;
+
+class ALIGN_DESC_BASE<string instr_asm, RegisterOperand GPROpnd,
+ Operand ImmOpnd> {
+ dag OutOperandList = (outs GPROpnd:$rd);
+ dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt, ImmOpnd:$bp);
+ string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt, $bp");
+ list<dag> Pattern = [];
+}
+
+class ALIGN_DESC : ALIGN_DESC_BASE<"align", GPR32Opnd, uimm2>;
+
+class ALUIPC_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> {
+ dag OutOperandList = (outs GPROpnd:$rs);
+ dag InOperandList = (ins simm16:$imm);
+ string AsmString = !strconcat(instr_asm, "\t$rs, $imm");
+ list<dag> Pattern = [];
+}
+
+class ALUIPC_DESC : ALUIPC_DESC_BASE<"aluipc", GPR32Opnd>;
+class AUIPC_DESC : ALUIPC_DESC_BASE<"auipc", GPR32Opnd>;
+
+class AUI_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> {
+ dag OutOperandList = (outs GPROpnd:$rs);
+ dag InOperandList = (ins GPROpnd:$rt, simm16:$imm);
+ string AsmString = !strconcat(instr_asm, "\t$rs, $rt, $imm");
+ list<dag> Pattern = [];
+}
+
+class AUI_DESC : AUI_DESC_BASE<"aui", GPR32Opnd>;
+
+class BRANCH_DESC_BASE {
+ bit isBranch = 1;
+ bit isTerminator = 1;
+ bit hasDelaySlot = 0;
+}
+
+class BC_DESC_BASE<string instr_asm, DAGOperand opnd> : BRANCH_DESC_BASE {
+ dag InOperandList = (ins opnd:$offset);
+ dag OutOperandList = (outs);
+ string AsmString = !strconcat(instr_asm, "\t$offset");
+ bit isBarrier = 1;
+}
+
+class CMP_BC_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 CMP_CBR_EQNE_Z_DESC_BASE<string instr_asm, DAGOperand opnd,
+ RegisterOperand GPROpnd> : BRANCH_DESC_BASE {
+ dag InOperandList = (ins GPROpnd:$rs, opnd:$offset);
+ dag OutOperandList = (outs);
+ string AsmString = !strconcat(instr_asm, "\t$rs, $offset");
+ list<Register> Defs = [AT];
+}
+
+class CMP_CBR_RT_Z_DESC_BASE<string instr_asm, DAGOperand opnd,
+ RegisterOperand GPROpnd> : BRANCH_DESC_BASE {
+ dag InOperandList = (ins GPROpnd:$rt, opnd:$offset);
+ dag OutOperandList = (outs);
+ string AsmString = !strconcat(instr_asm, "\t$rt, $offset");
+ list<Register> Defs = [AT];
+}
+
+class BALC_DESC : BC_DESC_BASE<"balc", brtarget26> {
+ bit isCall = 1;
+ list<Register> Defs = [RA];
+}
+
+class BC_DESC : BC_DESC_BASE<"bc", brtarget26>;
+class BEQC_DESC : CMP_BC_DESC_BASE<"beqc", brtarget, GPR32Opnd>;
+class BNEC_DESC : CMP_BC_DESC_BASE<"bnec", brtarget, GPR32Opnd>;
+
+class BLTZC_DESC : CMP_CBR_RT_Z_DESC_BASE<"bltzc", brtarget, GPR32Opnd>;
+class BGEZC_DESC : CMP_CBR_RT_Z_DESC_BASE<"bgezc", brtarget, GPR32Opnd>;
+
+class BLEZC_DESC : CMP_CBR_RT_Z_DESC_BASE<"blezc", brtarget, GPR32Opnd>;
+class BGTZC_DESC : CMP_CBR_RT_Z_DESC_BASE<"bgtzc", brtarget, GPR32Opnd>;
+
+class BEQZC_DESC : CMP_CBR_EQNE_Z_DESC_BASE<"beqzc", brtarget21, GPR32Opnd>;
+class BNEZC_DESC : CMP_CBR_EQNE_Z_DESC_BASE<"bnezc", brtarget21, GPR32Opnd>;
+
+class COP1_BCCZ_DESC_BASE<string instr_asm> : BRANCH_DESC_BASE {
+ dag InOperandList = (ins FGR64Opnd:$ft, brtarget:$offset);
+ dag OutOperandList = (outs);
+ string AsmString = instr_asm;
+ bit hasDelaySlot = 1;
+}
+
+class BC1EQZ_DESC : COP1_BCCZ_DESC_BASE<"bc1eqz $ft, $offset">;
+class BC1NEZ_DESC : COP1_BCCZ_DESC_BASE<"bc1nez $ft, $offset">;
+
+class COP2_BCCZ_DESC_BASE<string instr_asm> : BRANCH_DESC_BASE {
+ dag InOperandList = (ins COP2Opnd:$ct, brtarget:$offset);
+ dag OutOperandList = (outs);
+ string AsmString = instr_asm;
+ bit hasDelaySlot = 1;
+}
+
+class BC2EQZ_DESC : COP2_BCCZ_DESC_BASE<"bc2eqz $ct, $offset">;
+class BC2NEZ_DESC : COP2_BCCZ_DESC_BASE<"bc2nez $ct, $offset">;
+
+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> {
+ dag InOperandList = (ins GPROpnd:$rt, opnd:$offset);
+ string AsmString = !strconcat(opstr, "\t$rt, $offset");
+ list<dag> Pattern = [];
+ bit isTerminator = 1;
+ bit hasDelaySlot = 0;
+ string DecoderMethod = "DecodeSimm16";
+}
+
+class JIALC_DESC : JMP_IDX_COMPACT_DESC_BASE<"jialc", calloffset16,
+ GPR32Opnd> {
+ bit isCall = 1;
+ list<Register> Defs = [RA];
+}
+
+class JIC_DESC : JMP_IDX_COMPACT_DESC_BASE<"jic", jmpoffset16, GPR32Opnd> {
+ bit isBarrier = 1;
+ list<Register> Defs = [AT];
+}
+
+class BITSWAP_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> {
+ dag OutOperandList = (outs GPROpnd:$rd);
+ dag InOperandList = (ins GPROpnd:$rt);
+ string AsmString = !strconcat(instr_asm, "\t$rd, $rt");
+ list<dag> Pattern = [];
+}
+
+class BITSWAP_DESC : BITSWAP_DESC_BASE<"bitswap", GPR32Opnd>;
+
+class DIVMOD_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> {
+ dag OutOperandList = (outs GPROpnd:$rd);
+ dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt);
+ string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt");
+ list<dag> Pattern = [];
+}
+
+class DIV_DESC : DIVMOD_DESC_BASE<"div", GPR32Opnd>;
+class DIVU_DESC : DIVMOD_DESC_BASE<"divu", GPR32Opnd>;
+class MOD_DESC : DIVMOD_DESC_BASE<"mod", GPR32Opnd>;
+class MODU_DESC : DIVMOD_DESC_BASE<"modu", GPR32Opnd>;
+
+class BEQZALC_DESC : CMP_CBR_RT_Z_DESC_BASE<"beqzalc", brtarget, GPR32Opnd> {
+ list<Register> Defs = [RA];
+}
+
+class BGEZALC_DESC : CMP_CBR_RT_Z_DESC_BASE<"bgezalc", brtarget, GPR32Opnd> {
+ list<Register> Defs = [RA];
+}
+
+class BGTZALC_DESC : CMP_CBR_RT_Z_DESC_BASE<"bgtzalc", brtarget, GPR32Opnd> {
+ list<Register> Defs = [RA];
+}
+
+class BLEZALC_DESC : CMP_CBR_RT_Z_DESC_BASE<"blezalc", brtarget, GPR32Opnd> {
+ list<Register> Defs = [RA];
+}
+
+class BLTZALC_DESC : CMP_CBR_RT_Z_DESC_BASE<"bltzalc", brtarget, GPR32Opnd> {
+ list<Register> Defs = [RA];
+}
+
+class BNEZALC_DESC : CMP_CBR_RT_Z_DESC_BASE<"bnezalc", brtarget, GPR32Opnd> {
+ list<Register> Defs = [RA];
+}
+class MUL_R6_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> {
+ dag OutOperandList = (outs GPROpnd:$rd);
+ dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt);
+ string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt");
+ list<dag> Pattern = [];
+}
+
+class MUH_DESC : MUL_R6_DESC_BASE<"muh", GPR32Opnd>;
+class MUHU_DESC : MUL_R6_DESC_BASE<"muhu", GPR32Opnd>;
+class MUL_R6_DESC : MUL_R6_DESC_BASE<"mul", GPR32Opnd>;
+class MULU_DESC : MUL_R6_DESC_BASE<"mulu", GPR32Opnd>;
+
+class COP1_4R_DESC_BASE<string instr_asm, RegisterOperand FGROpnd> {
+ 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";
+}
+
+class SEL_D_DESC : COP1_4R_DESC_BASE<"sel.d", FGR64Opnd>;
+class SEL_S_DESC : COP1_4R_DESC_BASE<"sel.s", FGR32Opnd>;
+
+class SELEQNE_Z_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> {
+ dag OutOperandList = (outs GPROpnd:$rd);
+ dag InOperandList = (ins GPROpnd:$rs, GPROpnd:$rt);
+ string AsmString = !strconcat(instr_asm, "\t$rd, $rs, $rt");
+ list<dag> Pattern = [];
+}
+
+class SELEQZ_DESC : SELEQNE_Z_DESC_BASE<"seleqz", GPR32Opnd>;
+class SELNEZ_DESC : SELEQNE_Z_DESC_BASE<"selnez", GPR32Opnd>;
+
+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 MAX_MIN_DESC_BASE<string instr_asm, RegisterOperand FGROpnd> {
+ dag OutOperandList = (outs FGROpnd:$fd);
+ dag InOperandList = (ins FGROpnd:$fs, FGROpnd:$ft);
+ string AsmString = !strconcat(instr_asm, "\t$fd, $fs, $ft");
+ list<dag> Pattern = [];
+}
+
+class MAX_S_DESC : MAX_MIN_DESC_BASE<"max.s", FGR32Opnd>;
+class MAX_D_DESC : MAX_MIN_DESC_BASE<"max.d", FGR64Opnd>;
+class MIN_S_DESC : MAX_MIN_DESC_BASE<"min.s", FGR32Opnd>;
+class MIN_D_DESC : MAX_MIN_DESC_BASE<"min.d", FGR64Opnd>;
+
+class MAXA_S_DESC : MAX_MIN_DESC_BASE<"maxa.s", FGR32Opnd>;
+class MAXA_D_DESC : MAX_MIN_DESC_BASE<"maxa.d", FGR64Opnd>;
+class MINA_S_DESC : MAX_MIN_DESC_BASE<"mina.s", FGR32Opnd>;
+class MINA_D_DESC : MAX_MIN_DESC_BASE<"mina.d", FGR64Opnd>;
+
+class SELEQNEZ_DESC_BASE<string instr_asm, RegisterOperand FGROpnd> {
+ dag OutOperandList = (outs FGROpnd:$fd);
+ dag InOperandList = (ins FGROpnd:$fs, FGROpnd:$ft);
+ string AsmString = !strconcat(instr_asm, "\t$fd, $fs, $ft");
+ 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 CLASS_RINT_DESC_BASE<string instr_asm, RegisterOperand FGROpnd> {
+ dag OutOperandList = (outs FGROpnd:$fd);
+ dag InOperandList = (ins FGROpnd:$fs);
+ string AsmString = !strconcat(instr_asm, "\t$fd, $fs");
+ list<dag> Pattern = [];
+}
+
+class RINT_S_DESC : CLASS_RINT_DESC_BASE<"rint.s", FGR32Opnd>;
+class RINT_D_DESC : CLASS_RINT_DESC_BASE<"rint.d", FGR64Opnd>;
+class CLASS_S_DESC : CLASS_RINT_DESC_BASE<"class.s", FGR32Opnd>;
+class CLASS_D_DESC : CLASS_RINT_DESC_BASE<"class.d", FGR64Opnd>;
+
+//===----------------------------------------------------------------------===//
+//
+// Instruction Definitions
+//
+//===----------------------------------------------------------------------===//
+
+def ADDIUPC : ADDIUPC_ENC, ADDIUPC_DESC, ISA_MIPS32R6;
+def ALIGN : ALIGN_ENC, ALIGN_DESC, ISA_MIPS32R6;
+def ALUIPC : ALUIPC_ENC, ALUIPC_DESC, ISA_MIPS32R6;
+def AUI : AUI_ENC, AUI_DESC, ISA_MIPS32R6;
+def AUIPC : AUIPC_ENC, AUIPC_DESC, ISA_MIPS32R6;
+def BALC : BALC_ENC, BALC_DESC, ISA_MIPS32R6;
+def BC1EQZ : BC1EQZ_ENC, BC1EQZ_DESC, ISA_MIPS32R6;
+def BC1NEZ : BC1NEZ_ENC, BC1NEZ_DESC, ISA_MIPS32R6;
+def BC2EQZ : BC2EQZ_ENC, BC2EQZ_DESC, ISA_MIPS32R6;
+def BC2NEZ : BC2NEZ_ENC, BC2NEZ_DESC, ISA_MIPS32R6;
+def BC : BC_ENC, BC_DESC, ISA_MIPS32R6;
+def BEQC : BEQC_ENC, BEQC_DESC, ISA_MIPS32R6;
+def BEQZALC : BEQZALC_ENC, BEQZALC_DESC, ISA_MIPS32R6;
+def BEQZC : BEQZC_ENC, BEQZC_DESC, ISA_MIPS32R6;
+def BGEC; // Also aliased to blec with operands swapped
+def BGEUC; // Also aliased to bleuc with operands swapped
+def BGEZALC : BGEZALC_ENC, BGEZALC_DESC, ISA_MIPS32R6;
+def BGEZC : BGEZC_ENC, BGEZC_DESC, ISA_MIPS32R6;
+def BGTZALC : BGTZALC_ENC, BGTZALC_DESC, ISA_MIPS32R6;
+def BGTZC : BGTZC_ENC, BGTZC_DESC, ISA_MIPS32R6;
+def BITSWAP : BITSWAP_ENC, BITSWAP_DESC, ISA_MIPS32R6;
+def BLEZALC : BLEZALC_ENC, BLEZALC_DESC, ISA_MIPS32R6;
+def BLEZC : BLEZC_ENC, BLEZC_DESC, ISA_MIPS32R6;
+def BLTC; // Also aliased to bgtc with operands swapped
+def BLTUC; // Also aliased to bgtuc with operands swapped
+def BLTZALC : BLTZALC_ENC, BLTZALC_DESC, ISA_MIPS32R6;
+def BLTZC : BLTZC_ENC, BLTZC_DESC, ISA_MIPS32R6;
+def BNEC : BNEC_ENC, BNEC_DESC, ISA_MIPS32R6;
+def BNEZALC : BNEZALC_ENC, BNEZALC_DESC, ISA_MIPS32R6;
+def BNEZC : BNEZC_ENC, BNEZC_DESC, ISA_MIPS32R6;
+def BNVC : BNVC_ENC, BNVC_DESC, ISA_MIPS32R6;
+def BOVC : BOVC_ENC, BOVC_DESC, ISA_MIPS32R6;
+def CLASS_D : CLASS_D_ENC, CLASS_D_DESC, ISA_MIPS32R6;
+def CLASS_S : CLASS_S_ENC, CLASS_S_DESC, ISA_MIPS32R6;
+defm S : CMP_CC_M<FIELD_CMP_FORMAT_S, "s", FGR32Opnd>;
+defm D : CMP_CC_M<FIELD_CMP_FORMAT_D, "d", FGR64Opnd>;
+def DIV : DIV_ENC, DIV_DESC, ISA_MIPS32R6;
+def DIVU : DIVU_ENC, DIVU_DESC, ISA_MIPS32R6;
+def JIALC : JIALC_ENC, JIALC_DESC, ISA_MIPS32R6;
+def JIC : JIC_ENC, JIC_DESC, ISA_MIPS32R6;
+// def LSA; // See MSA
+def LWPC : LWPC_ENC, LWPC_DESC, ISA_MIPS32R6;
+def LWUPC : LWUPC_ENC, LWUPC_DESC, ISA_MIPS32R6;
+def MADDF_S : MADDF_S_ENC, MADDF_S_DESC, ISA_MIPS32R6;
+def MADDF_D : MADDF_D_ENC, MADDF_D_DESC, ISA_MIPS32R6;
+def MAXA_D : MAXA_D_ENC, MAXA_D_DESC, ISA_MIPS32R6;
+def MAXA_S : MAXA_S_ENC, MAXA_S_DESC, ISA_MIPS32R6;
+def MAX_D : MAX_D_ENC, MAX_D_DESC, ISA_MIPS32R6;
+def MAX_S : MAX_S_ENC, MAX_S_DESC, ISA_MIPS32R6;
+def MINA_D : MINA_D_ENC, MINA_D_DESC, ISA_MIPS32R6;
+def MINA_S : MINA_S_ENC, MINA_S_DESC, ISA_MIPS32R6;
+def MIN_D : MIN_D_ENC, MIN_D_DESC, ISA_MIPS32R6;
+def MIN_S : MIN_S_ENC, MIN_S_DESC, ISA_MIPS32R6;
+def MOD : MOD_ENC, MOD_DESC, ISA_MIPS32R6;
+def MODU : MODU_ENC, MODU_DESC, ISA_MIPS32R6;
+def MSUBF_S : MSUBF_S_ENC, MSUBF_S_DESC, ISA_MIPS32R6;
+def MSUBF_D : MSUBF_D_ENC, MSUBF_D_DESC, ISA_MIPS32R6;
+def MUH : MUH_ENC, MUH_DESC, ISA_MIPS32R6;
+def MUHU : MUHU_ENC, MUHU_DESC, ISA_MIPS32R6;
+def MUL_R6 : MUL_R6_ENC, MUL_R6_DESC, ISA_MIPS32R6;
+def MULU : MULU_ENC, MULU_DESC, ISA_MIPS32R6;
+def NAL; // BAL with rd=0
+def RINT_D : RINT_D_ENC, RINT_D_DESC, ISA_MIPS32R6;
+def RINT_S : RINT_S_ENC, RINT_S_DESC, ISA_MIPS32R6;
+def SELEQZ : SELEQZ_ENC, SELEQZ_DESC, ISA_MIPS32R6;
+def SELEQZ_D : SELEQZ_D_ENC, SELEQZ_D_DESC, ISA_MIPS32R6;
+def SELEQZ_S : SELEQZ_S_ENC, SELEQZ_S_DESC, ISA_MIPS32R6;
+def SELNEZ : SELNEZ_ENC, SELNEZ_DESC, ISA_MIPS32R6;
+def SELNEZ_D : SELNEZ_D_ENC, SELNEZ_D_DESC, ISA_MIPS32R6;
+def SELNEZ_S : SELNEZ_S_ENC, SELNEZ_S_DESC, ISA_MIPS32R6;
+def SEL_D : SEL_D_ENC, SEL_D_DESC, ISA_MIPS32R6;
+def SEL_S : SEL_S_ENC, SEL_S_DESC, ISA_MIPS32R6;
diff --git a/lib/Target/Mips/Mips64InstrInfo.td b/lib/Target/Mips/Mips64InstrInfo.td
index 7115d11..924b325 100644
--- a/lib/Target/Mips/Mips64InstrInfo.td
+++ b/lib/Target/Mips/Mips64InstrInfo.td
@@ -20,6 +20,9 @@ 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);
@@ -28,6 +31,11 @@ def Subtract32 : SDNodeXForm<imm, [{
// shamt must fit in 6 bits.
def immZExt6 : ImmLeaf<i32, [{return Imm == (Imm & 0x3f);}]>;
+// Node immediate fits as 10-bit sign extended on target immediate.
+// e.g. seqi, snei
+def immSExt10_64 : PatLeaf<(i64 imm),
+ [{ return isInt<10>(N->getSExtValue()); }]>;
+
//===----------------------------------------------------------------------===//
// Instructions specific format
//===----------------------------------------------------------------------===//
@@ -53,10 +61,11 @@ let isPseudo = 1, isCodeGenOnly = 1 in {
//===----------------------------------------------------------------------===//
let DecoderNamespace = "Mips64" in {
/// Arithmetic Instructions (ALU Immediate)
-def DADDi : ArithLogicI<"daddi", simm16_64, GPR64Opnd>, ADDI_FM<0x18>;
+def DADDi : ArithLogicI<"daddi", simm16_64, GPR64Opnd>, ADDI_FM<0x18>,
+ ISA_MIPS3;
def DADDiu : ArithLogicI<"daddiu", simm16_64, GPR64Opnd, II_DADDIU,
immSExt16, add>,
- ADDI_FM<0x19>, IsAsCheapAsAMove;
+ ADDI_FM<0x19>, IsAsCheapAsAMove, ISA_MIPS3;
let isCodeGenOnly = 1 in {
def SLTi64 : SetCC_I<"slti", setlt, simm16_64, immSExt16, GPR64Opnd>,
@@ -73,12 +82,14 @@ def LUi64 : LoadUpper<"lui", GPR64Opnd, uimm16_64>, LUI_FM;
}
/// Arithmetic Instructions (3-Operand, R-Type)
-def DADD : ArithLogicR<"dadd", GPR64Opnd, 1, II_DADD>, ADD_FM<0, 0x2c>;
-def DADDu : ArithLogicR<"daddu", GPR64Opnd, 1, II_DADDU, add>,
- ADD_FM<0, 0x2d>;
-def DSUBu : ArithLogicR<"dsubu", GPR64Opnd, 0, II_DSUBU, sub>,
- ADD_FM<0, 0x2f>;
-def DSUB : ArithLogicR<"dsub", GPR64Opnd, 0, II_DSUB, sub>, ADD_FM<0, 0x2e>;
+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 isCodeGenOnly = 1 in {
def SLT64 : SetCC_R<"slt", setlt, GPR64Opnd>, ADD_FM<0, 0x2a>;
@@ -91,33 +102,32 @@ def NOR64 : LogicNOR<"nor", GPR64Opnd>, ADD_FM<0, 0x27>;
/// Shift Instructions
def DSLL : shift_rotate_imm<"dsll", uimm6, GPR64Opnd, II_DSLL, shl, immZExt6>,
- SRA_FM<0x38, 0>;
+ SRA_FM<0x38, 0>, ISA_MIPS3;
def DSRL : shift_rotate_imm<"dsrl", uimm6, GPR64Opnd, II_DSRL, srl, immZExt6>,
- SRA_FM<0x3a, 0>;
+ SRA_FM<0x3a, 0>, ISA_MIPS3;
def DSRA : shift_rotate_imm<"dsra", uimm6, GPR64Opnd, II_DSRA, sra, immZExt6>,
- SRA_FM<0x3b, 0>;
+ SRA_FM<0x3b, 0>, ISA_MIPS3;
def DSLLV : shift_rotate_reg<"dsllv", GPR64Opnd, II_DSLLV, shl>,
- SRLV_FM<0x14, 0>;
+ SRLV_FM<0x14, 0>, ISA_MIPS3;
def DSRLV : shift_rotate_reg<"dsrlv", GPR64Opnd, II_DSRLV, srl>,
- SRLV_FM<0x16, 0>;
+ SRLV_FM<0x16, 0>, ISA_MIPS3;
def DSRAV : shift_rotate_reg<"dsrav", GPR64Opnd, II_DSRAV, sra>,
- SRLV_FM<0x17, 0>;
+ SRLV_FM<0x17, 0>, ISA_MIPS3;
def DSLL32 : shift_rotate_imm<"dsll32", uimm5, GPR64Opnd, II_DSLL32>,
- SRA_FM<0x3c, 0>;
+ SRA_FM<0x3c, 0>, ISA_MIPS3;
def DSRL32 : shift_rotate_imm<"dsrl32", uimm5, GPR64Opnd, II_DSRL32>,
- SRA_FM<0x3e, 0>;
+ SRA_FM<0x3e, 0>, ISA_MIPS3;
def DSRA32 : shift_rotate_imm<"dsra32", uimm5, GPR64Opnd, II_DSRA32>,
- SRA_FM<0x3f, 0>;
+ SRA_FM<0x3f, 0>, ISA_MIPS3;
// Rotate Instructions
-let Predicates = [HasMips64r2, HasStdEnc] in {
- def DROTR : shift_rotate_imm<"drotr", uimm6, GPR64Opnd, II_DROTR, rotr,
- immZExt6>, SRA_FM<0x3a, 1>;
- def DROTRV : shift_rotate_reg<"drotrv", GPR64Opnd, II_DROTRV, rotr>,
- SRLV_FM<0x16, 1>;
- def DROTR32 : shift_rotate_imm<"drotr32", uimm5, GPR64Opnd, II_DROTR32>,
- SRA_FM<0x3e, 1>;
-}
+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;
/// Load and Store Instructions
/// aligned
@@ -132,9 +142,9 @@ 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>;
-def LD : Load<"ld", GPR64Opnd, load, II_LD>, LW_FM<0x37>;
-def SD : Store<"sd", GPR64Opnd, store, II_SD>, LW_FM<0x3f>;
+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;
/// load/store left/right
let isCodeGenOnly = 1 in {
@@ -144,14 +154,18 @@ def SWL64 : StoreLeftRight<"swl", MipsSWL, GPR64Opnd, II_SWL>, LW_FM<0x2a>;
def SWR64 : StoreLeftRight<"swr", MipsSWR, GPR64Opnd, II_SWR>, LW_FM<0x2e>;
}
-def LDL : LoadLeftRight<"ldl", MipsLDL, GPR64Opnd, II_LDL>, LW_FM<0x1a>;
-def LDR : LoadLeftRight<"ldr", MipsLDR, GPR64Opnd, II_LDR>, LW_FM<0x1b>;
-def SDL : StoreLeftRight<"sdl", MipsSDL, GPR64Opnd, II_SDL>, LW_FM<0x2c>;
-def SDR : StoreLeftRight<"sdr", MipsSDR, GPR64Opnd, II_SDR>, LW_FM<0x2d>;
+def LDL : LoadLeftRight<"ldl", MipsLDL, GPR64Opnd, II_LDL>, LW_FM<0x1a>,
+ ISA_MIPS3_NOT_32R6_64R6;
+def LDR : LoadLeftRight<"ldr", MipsLDR, GPR64Opnd, II_LDR>, LW_FM<0x1b>,
+ ISA_MIPS3_NOT_32R6_64R6;
+def SDL : StoreLeftRight<"sdl", MipsSDL, GPR64Opnd, II_SDL>, LW_FM<0x2c>,
+ ISA_MIPS3_NOT_32R6_64R6;
+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>;
-def SCD : SCBase<"scd", GPR64Opnd>, LW_FM<0x3c>;
+def LLD : LLBase<"lld", GPR64Opnd>, LW_FM<0x34>, ISA_MIPS3;
+def SCD : SCBase<"scd", GPR64Opnd>, LW_FM<0x3c>, ISA_MIPS3;
/// Jump and Branch Instructions
let isCodeGenOnly = 1 in {
@@ -169,17 +183,17 @@ def TAILCALL64_R : TailCallReg<GPR64Opnd, JR, GPR32Opnd>;
/// Multiply and Divide Instructions.
def DMULT : Mult<"dmult", II_DMULT, GPR64Opnd, [HI0_64, LO0_64]>,
- MULT_FM<0, 0x1c>;
+ MULT_FM<0, 0x1c>, ISA_MIPS3;
def DMULTu : Mult<"dmultu", II_DMULTU, GPR64Opnd, [HI0_64, LO0_64]>,
- MULT_FM<0, 0x1d>;
+ MULT_FM<0, 0x1d>, ISA_MIPS3;
def PseudoDMULT : MultDivPseudo<DMULT, ACC128, GPR64Opnd, MipsMult,
II_DMULT>;
def PseudoDMULTu : MultDivPseudo<DMULTu, ACC128, GPR64Opnd, MipsMultu,
II_DMULTU>;
def DSDIV : Div<"ddiv", II_DDIV, GPR64Opnd, [HI0_64, LO0_64]>,
- MULT_FM<0, 0x1e>;
+ MULT_FM<0, 0x1e>, ISA_MIPS3;
def DUDIV : Div<"ddivu", II_DDIVU, GPR64Opnd, [HI0_64, LO0_64]>,
- MULT_FM<0, 0x1f>;
+ MULT_FM<0, 0x1f>, ISA_MIPS3;
def PseudoDSDIV : MultDivPseudo<DSDIV, ACC128, GPR64Opnd, MipsDivRem,
II_DDIV, 0, 1, 1>;
def PseudoDUDIV : MultDivPseudo<DUDIV, ACC128, GPR64Opnd, MipsDivRemU,
@@ -195,17 +209,19 @@ def PseudoMFLO64 : PseudoMFLOHI<GPR64, ACC128, MipsMFLO>;
def PseudoMTLOHI64 : PseudoMTLOHI<ACC128, GPR64>;
/// Sign Ext In Register Instructions.
-def SEB64 : SignExtInReg<"seb", i8, GPR64Opnd, II_SEB>, SEB_FM<0x10, 0x20>;
-def SEH64 : SignExtInReg<"seh", i16, GPR64Opnd, II_SEH>, SEB_FM<0x18, 0x20>;
+def SEB64 : SignExtInReg<"seb", i8, GPR64Opnd, II_SEB>, SEB_FM<0x10, 0x20>,
+ ISA_MIPS32R2;
+def SEH64 : SignExtInReg<"seh", i16, GPR64Opnd, II_SEH>, SEB_FM<0x18, 0x20>,
+ ISA_MIPS32R2;
}
/// Count Leading
-def DCLZ : CountLeading0<"dclz", GPR64Opnd>, CLO_FM<0x24>;
-def DCLO : CountLeading1<"dclo", GPR64Opnd>, CLO_FM<0x25>;
+def DCLZ : CountLeading0<"dclz", GPR64Opnd>, CLO_FM<0x24>, ISA_MIPS64;
+def DCLO : CountLeading1<"dclo", GPR64Opnd>, CLO_FM<0x25>, ISA_MIPS64;
/// Double Word Swap Bytes/HalfWords
-def DSBH : SubwordSwap<"dsbh", GPR64Opnd>, SEB_FM<2, 0x24>;
-def DSHD : SubwordSwap<"dshd", GPR64Opnd>, SEB_FM<5, 0x24>;
+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>;
@@ -229,8 +245,19 @@ let isCodeGenOnly = 1, rs = 0, shamt = 0 in {
"sll\t$rd, $rt, 0", [], II_SLL>;
}
+// We need the following pseudo instruction to avoid offset calculation for
+// long branches. See the comment in file MipsLongBranch.cpp for detailed
+// explanation.
+
+// Expands to: daddiu $dst, $src, %PART($tgt - $baltgt)
+// where %PART may be %hi or %lo, depending on the relocation kind
+// that $tgt is annotated with.
+def LONG_BRANCH_DADDiu : PseudoSE<(outs GPR64Opnd:$dst),
+ (ins GPR64Opnd:$src, brtarget:$tgt, brtarget:$baltgt), []>;
+
// Cavium Octeon cmMIPS instructions
-let Predicates = [HasCnMips] in {
+let EncodingPredicates = []<Predicate>, // FIXME: The lack of HasStdEnc is probably a bug
+ AdditionalPredicates = [HasCnMips] in {
class Count1s<string opstr, RegisterOperand RO>:
InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"),
@@ -254,6 +281,14 @@ class SetCC64_R<string opstr, PatFrag cond_op> :
let TwoOperandAliasConstraint = "$rd = $rs";
}
+class SetCC64_I<string opstr, PatFrag cond_op>:
+ InstSE<(outs GPR64Opnd:$rt), (ins GPR64Opnd:$rs, simm10_64:$imm10),
+ !strconcat(opstr, "\t$rt, $rs, $imm10"),
+ [(set GPR64Opnd:$rt, (cond_op GPR64Opnd:$rs, immSExt10_64:$imm10))],
+ II_SEQI_SNEI, FrmI, opstr> {
+ let TwoOperandAliasConstraint = "$rt = $rs";
+}
+
// Unsigned Byte Add
let Pattern = [(set GPR64Opnd:$rd,
(and (add GPR64Opnd:$rs, GPR64Opnd:$rt), 255))] in
@@ -287,7 +322,25 @@ def DPOP : Count1s<"dpop", GPR64Opnd>, POP_FM<0x2d>;
// 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>;
+
+// 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>;
+
+// 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>;
+
+// 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>;
+
}
}
@@ -297,12 +350,10 @@ def SNE : SetCC64_R<"sne", setne>, SEQ_FM<0x2b>;
//===----------------------------------------------------------------------===//
// extended loads
-let Predicates = [HasStdEnc] in {
- def : MipsPat<(i64 (extloadi1 addr:$src)), (LB64 addr:$src)>;
- def : MipsPat<(i64 (extloadi8 addr:$src)), (LB64 addr:$src)>;
- def : MipsPat<(i64 (extloadi16 addr:$src)), (LH64 addr:$src)>;
- def : MipsPat<(i64 (extloadi32 addr:$src)), (LW64 addr:$src)>;
-}
+def : MipsPat<(i64 (extloadi1 addr:$src)), (LB64 addr:$src)>;
+def : MipsPat<(i64 (extloadi8 addr:$src)), (LB64 addr:$src)>;
+def : MipsPat<(i64 (extloadi16 addr:$src)), (LH64 addr:$src)>;
+def : MipsPat<(i64 (extloadi32 addr:$src)), (LW64 addr:$src)>;
// hi/lo relocs
def : MipsPat<(MipsHi tglobaladdr:$in), (LUi64 tglobaladdr:$in)>;
@@ -355,8 +406,7 @@ defm : SetgeImmPats<GPR64, SLTi64, SLTiu64>;
// truncate
def : MipsPat<(i32 (trunc GPR64:$src)),
- (SLL (EXTRACT_SUBREG GPR64:$src, sub_32), 0)>,
- Requires<[HasStdEnc]>;
+ (SLL (EXTRACT_SUBREG GPR64:$src, sub_32), 0)>;
// 32-to-64-bit extension
def : MipsPat<(i64 (anyext GPR32:$src)), (SLL64_32 GPR32:$src)>;
@@ -373,64 +423,59 @@ def : MipsPat<(bswap GPR64:$rt), (DSHD (DSBH GPR64:$rt))>;
//===----------------------------------------------------------------------===//
// Instruction aliases
//===----------------------------------------------------------------------===//
-def : InstAlias<"move $dst, $src",
- (DADDu GPR64Opnd:$dst, GPR64Opnd:$src, ZERO_64), 1>,
- Requires<[HasMips64]>;
-def : InstAlias<"daddu $rs, $rt, $imm",
- (DADDiu GPR64Opnd:$rs, GPR64Opnd:$rt, simm16_64:$imm),
- 0>;
-def : InstAlias<"dadd $rs, $rt, $imm",
- (DADDi GPR64Opnd:$rs, GPR64Opnd:$rt, simm16_64:$imm),
- 0>;
-def : InstAlias<"daddu $rs, $imm",
- (DADDiu GPR64Opnd:$rs, GPR64Opnd:$rs, simm16_64:$imm),
- 0>;
-def : InstAlias<"dadd $rs, $imm",
- (DADDi GPR64Opnd:$rs, GPR64Opnd:$rs, simm16_64:$imm),
- 0>;
-def : InstAlias<"add $rs, $imm",
- (ADDi GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm),
- 0>;
-def : InstAlias<"addu $rs, $imm",
- (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm),
- 0>;
-let isPseudo=1, usesCustomInserter=1, isCodeGenOnly=1 in {
-def SUBi : MipsInst<(outs GPR32Opnd: $rt), (ins GPR32Opnd: $rs, simm16: $imm),
- "sub\t$rt, $rs, $imm", [], II_DSUB, Pseudo>;
-def SUBiu : MipsInst<(outs GPR32Opnd: $rt), (ins GPR32Opnd: $rs, simm16: $imm),
- "subu\t$rt, $rs, $imm", [], II_DSUB, Pseudo>;
-def DSUBi : MipsInst<(outs GPR64Opnd: $rt), (ins GPR64Opnd: $rs, simm16_64: $imm),
- "ssub\t$rt, $rs, $imm", [], II_DSUB, Pseudo>;
-def DSUBiu : MipsInst<(outs GPR64Opnd: $rt), (ins GPR64Opnd: $rs, simm16_64: $imm),
- "ssubu\t$rt, $rs, $imm", [], II_DSUB, Pseudo>;
-}
-def : InstAlias<"dsubu $rt, $rs, $imm",
- (DSUBiu GPR64Opnd:$rt, GPR64Opnd:$rs, simm16_64: $imm),
- 0>;
-def : InstAlias<"sub $rs, $imm",
- (SUBi GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm),
- 0>;
-def : InstAlias<"subu $rs, $imm",
- (SUBiu GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm),
- 0>;
-def : InstAlias<"dsub $rs, $imm",
- (DSUBi GPR64Opnd:$rs, GPR64Opnd:$rs, simm16_64:$imm),
- 0>;
-def : InstAlias<"dsubu $rs, $imm",
- (DSUBiu GPR64Opnd:$rs, GPR64Opnd:$rs, simm16_64:$imm),
- 0>;
+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>;
+def : MipsInstAlias<"dadd $rs, $rt, $imm",
+ (DADDi GPR64Opnd:$rs, GPR64Opnd:$rt, simm16_64:$imm),
+ 0>;
+def : MipsInstAlias<"daddu $rs, $imm",
+ (DADDiu GPR64Opnd:$rs, GPR64Opnd:$rs, simm16_64:$imm),
+ 0>;
+def : MipsInstAlias<"dadd $rs, $imm",
+ (DADDi GPR64Opnd:$rs, GPR64Opnd:$rs, simm16_64:$imm),
+ 0>;
+def : MipsInstAlias<"add $rs, $imm",
+ (ADDi GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm),
+ 0>;
+def : MipsInstAlias<"addu $rs, $imm",
+ (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rs, simm16:$imm),
+ 0>;
+def : MipsInstAlias<"dsll $rd, $rt, $rs",
+ (DSLLV GPR64Opnd:$rd, GPR64Opnd:$rt, GPR32Opnd:$rs), 0>,
+ ISA_MIPS3;
+def : MipsInstAlias<"dsubu $rt, $rs, $imm",
+ (DADDiu GPR64Opnd:$rt, GPR64Opnd:$rs,
+ InvertedImOperand64:$imm), 0>;
+def : MipsInstAlias<"dsub $rs, $imm",
+ (DADDi GPR64Opnd:$rs, GPR64Opnd:$rs,
+ InvertedImOperand64:$imm),
+ 0>;
+def : MipsInstAlias<"dsubu $rs, $imm",
+ (DADDiu GPR64Opnd:$rs, GPR64Opnd:$rs,
+ InvertedImOperand64:$imm),
+ 0>;
+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;
/// Move between CPU and coprocessor registers
let DecoderNamespace = "Mips64", Predicates = [HasMips64] in {
def DMFC0 : MFC3OP<"dmfc0", GPR64Opnd>, MFC3OP_FM<0x10, 1>;
-def DMTC0 : MFC3OP<"dmtc0", GPR64Opnd>, MFC3OP_FM<0x10, 5>;
-def DMFC2 : MFC3OP<"dmfc2", GPR64Opnd>, MFC3OP_FM<0x12, 1>;
-def DMTC2 : MFC3OP<"dmtc2", GPR64Opnd>, MFC3OP_FM<0x12, 5>;
+def DMTC0 : MFC3OP<"dmtc0", GPR64Opnd>, MFC3OP_FM<0x10, 5>, ISA_MIPS3;
+def DMFC2 : MFC3OP<"dmfc2", GPR64Opnd>, MFC3OP_FM<0x12, 1>, ISA_MIPS3;
+def DMTC2 : MFC3OP<"dmtc2", GPR64Opnd>, MFC3OP_FM<0x12, 5>, ISA_MIPS3;
}
// Two operand (implicit 0 selector) versions:
-def : InstAlias<"dmfc0 $rt, $rd", (DMFC0 GPR64Opnd:$rt, GPR64Opnd:$rd, 0), 0>;
-def : InstAlias<"dmtc0 $rt, $rd", (DMTC0 GPR64Opnd:$rt, GPR64Opnd:$rd, 0), 0>;
-def : InstAlias<"dmfc2 $rt, $rd", (DMFC2 GPR64Opnd:$rt, GPR64Opnd:$rd, 0), 0>;
-def : InstAlias<"dmtc2 $rt, $rd", (DMTC2 GPR64Opnd:$rt, GPR64Opnd:$rd, 0), 0>;
+def : MipsInstAlias<"dmfc0 $rt, $rd", (DMFC0 GPR64Opnd:$rt, GPR64Opnd:$rd, 0), 0>;
+def : MipsInstAlias<"dmtc0 $rt, $rd", (DMTC0 GPR64Opnd:$rt, GPR64Opnd:$rd, 0), 0>;
+def : MipsInstAlias<"dmfc2 $rt, $rd", (DMFC2 GPR64Opnd:$rt, GPR64Opnd:$rd, 0), 0>;
+def : MipsInstAlias<"dmtc2 $rt, $rd", (DMTC2 GPR64Opnd:$rt, GPR64Opnd:$rd, 0), 0>;
diff --git a/lib/Target/Mips/Mips64r6InstrInfo.td b/lib/Target/Mips/Mips64r6InstrInfo.td
new file mode 100644
index 0000000..f971218
--- /dev/null
+++ b/lib/Target/Mips/Mips64r6InstrInfo.td
@@ -0,0 +1,88 @@
+//=- Mips64r6InstrInfo.td - Mips64r6 Instruction Information -*- tablegen -*-=//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file describes Mips64r6 instructions.
+//
+//===----------------------------------------------------------------------===//
+
+// Notes about removals/changes from MIPS32r6:
+// Reencoded: dclo, dclz
+// Reencoded: lld, scd
+// Removed: daddi
+// Removed: ddiv, ddivu, dmult, dmultu
+// Removed: div, divu
+
+//===----------------------------------------------------------------------===//
+//
+// Instruction Encodings
+//
+//===----------------------------------------------------------------------===//
+
+class DALIGN_ENC : SPECIAL3_DALIGN_FM<OPCODE6_DALIGN>;
+class DAUI_ENC : DAUI_FM;
+class DAHI_ENC : REGIMM_FM<OPCODE5_DAHI>;
+class DATI_ENC : REGIMM_FM<OPCODE5_DATI>;
+class DBITSWAP_ENC : SPECIAL3_2R_FM<OPCODE6_DBITSWAP>;
+class DDIV_ENC : SPECIAL_3R_FM<0b00010, 0b011110>;
+class DDIVU_ENC : SPECIAL_3R_FM<0b00010, 0b011111>;
+class DMOD_ENC : SPECIAL_3R_FM<0b00011, 0b011110>;
+class DMODU_ENC : SPECIAL_3R_FM<0b00011, 0b011111>;
+class DMUH_ENC : SPECIAL_3R_FM<0b00011, 0b111000>;
+class DMUHU_ENC : SPECIAL_3R_FM<0b00011, 0b111001>;
+class DMUL_R6_ENC : SPECIAL_3R_FM<0b00010, 0b111000>;
+class DMULU_ENC : SPECIAL_3R_FM<0b00010, 0b111001>;
+
+//===----------------------------------------------------------------------===//
+//
+// Instruction Descriptions
+//
+//===----------------------------------------------------------------------===//
+
+class AHI_ATI_DESC_BASE<string instr_asm, RegisterOperand GPROpnd> {
+ dag OutOperandList = (outs GPROpnd:$rs);
+ dag InOperandList = (ins GPROpnd:$rt, simm16:$imm);
+ string AsmString = !strconcat(instr_asm, "\t$rt, $imm");
+ string Constraints = "$rs = $rt";
+}
+
+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 DDIV_DESC : DIVMOD_DESC_BASE<"ddiv", GPR64Opnd>;
+class DDIVU_DESC : DIVMOD_DESC_BASE<"ddivu", GPR64Opnd>;
+class DMOD_DESC : DIVMOD_DESC_BASE<"dmod", GPR64Opnd>;
+class DMODU_DESC : DIVMOD_DESC_BASE<"dmodu", GPR64Opnd>;
+class DMUH_DESC : MUL_R6_DESC_BASE<"dmuh", GPR64Opnd>;
+class DMUHU_DESC : MUL_R6_DESC_BASE<"dmuhu", GPR64Opnd>;
+class DMUL_R6_DESC : MUL_R6_DESC_BASE<"dmul", GPR64Opnd>;
+class DMULU_DESC : MUL_R6_DESC_BASE<"dmulu", GPR64Opnd>;
+
+//===----------------------------------------------------------------------===//
+//
+// Instruction Definitions
+//
+//===----------------------------------------------------------------------===//
+
+def DAHI : DAHI_ENC, DAHI_DESC, ISA_MIPS64R6;
+def DALIGN : DALIGN_ENC, DALIGN_DESC, ISA_MIPS64R6;
+def DATI : DATI_ENC, DATI_DESC, ISA_MIPS64R6;
+def DAUI : DAUI_ENC, DAUI_DESC, ISA_MIPS64R6;
+def DBITSWAP : DBITSWAP_ENC, DBITSWAP_DESC, ISA_MIPS64R6;
+def DDIV : DDIV_ENC, DDIV_DESC, ISA_MIPS64R6;
+def DDIVU : DDIVU_ENC, DDIVU_DESC, ISA_MIPS64R6;
+// def DLSA; // See MSA
+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;
diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp
index d5df855..6df90aa 100644
--- a/lib/Target/Mips/MipsAsmPrinter.cpp
+++ b/lib/Target/Mips/MipsAsmPrinter.cpp
@@ -12,7 +12,6 @@
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "mips-asm-printer"
#include "InstPrinter/MipsInstPrinter.h"
#include "MCTargetDesc/MipsBaseInfo.h"
#include "MCTargetDesc/MipsMCNaCl.h"
@@ -52,6 +51,8 @@
using namespace llvm;
+#define DEBUG_TYPE "mips-asm-printer"
+
MipsTargetStreamer &MipsAsmPrinter::getTargetStreamer() {
return static_cast<MipsTargetStreamer &>(*OutStreamer.getTargetStreamer());
}
@@ -147,7 +148,8 @@ void MipsAsmPrinter::EmitInstruction(const MachineInstr *MI) {
// removing another test for this situation downstream in the
// callchain.
//
- if (I->isPseudo() && !Subtarget->inMips16Mode())
+ if (I->isPseudo() && !Subtarget->inMips16Mode()
+ && !isLongBranchPseudo(I->getOpcode()))
llvm_unreachable("Pseudo opcode found in EmitInstruction()");
MCInst TmpInst0;
@@ -285,9 +287,8 @@ void MipsAsmPrinter::EmitFunctionEntryLabel() {
if (Subtarget->inMicroMipsMode())
TS.emitDirectiveSetMicroMips();
- // leave out until FSF available gas has micromips changes
- // else
- // TS.emitDirectiveSetNoMicroMips();
+ else
+ TS.emitDirectiveSetNoMicroMips();
if (Subtarget->inMips16Mode())
TS.emitDirectiveSetMips16();
@@ -621,16 +622,29 @@ printFCCOperand(const MachineInstr *MI, int opNum, raw_ostream &O,
void MipsAsmPrinter::EmitStartOfAsmFile(Module &M) {
// TODO: Need to add -mabicalls and -mno-abicalls flags.
// Currently we assume that -mabicalls is the default.
- getTargetStreamer().emitDirectiveAbiCalls();
- Reloc::Model RM = Subtarget->getRelocationModel();
- if (RM == Reloc::Static && !Subtarget->hasMips64())
- getTargetStreamer().emitDirectiveOptionPic0();
+ bool IsABICalls = true;
+ if (IsABICalls) {
+ getTargetStreamer().emitDirectiveAbiCalls();
+ Reloc::Model RM = Subtarget->getRelocationModel();
+ // 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 && !Subtarget->isABI_N64())
+ getTargetStreamer().emitDirectiveOptionPic0();
+ }
// Tell the assembler which ABI we are using
std::string SectionName = std::string(".mdebug.") + getCurrentABIString();
OutStreamer.SwitchSection(OutContext.getELFSection(
SectionName, ELF::SHT_PROGBITS, 0, SectionKind::getDataRel()));
+ // NaN: At the moment we only support:
+ // 1. .nan legacy (default)
+ // 2. .nan 2008
+ Subtarget->isNaN2008() ? getTargetStreamer().emitDirectiveNaN2008()
+ : getTargetStreamer().emitDirectiveNaNLegacy();
+
// TODO: handle O64 ABI
if (Subtarget->isABI_EABI()) {
@@ -824,7 +838,7 @@ void MipsAsmPrinter::EmitFPCallStub(
const MCSectionELF *M = OutContext.getELFSection(
".mips16.call.fp." + std::string(Symbol), ELF::SHT_PROGBITS,
ELF::SHF_ALLOC | ELF::SHF_EXECINSTR, SectionKind::getText());
- OutStreamer.SwitchSection(M, 0);
+ OutStreamer.SwitchSection(M, nullptr);
//
// .align 2
//
@@ -941,6 +955,12 @@ void MipsAsmPrinter::NaClAlignIndirectJumpTargets(MachineFunction &MF) {
}
}
+bool MipsAsmPrinter::isLongBranchPseudo(int Opcode) const {
+ return (Opcode == Mips::LONG_BRANCH_LUi
+ || Opcode == Mips::LONG_BRANCH_ADDiu
+ || Opcode == Mips::LONG_BRANCH_DADDiu);
+}
+
// Force static initialization.
extern "C" void LLVMInitializeMipsAsmPrinter() {
RegisterAsmPrinter<MipsAsmPrinter> X(TheMipsTarget);
diff --git a/lib/Target/Mips/MipsAsmPrinter.h b/lib/Target/Mips/MipsAsmPrinter.h
index 3e9093e..e82b145 100644
--- a/lib/Target/Mips/MipsAsmPrinter.h
+++ b/lib/Target/Mips/MipsAsmPrinter.h
@@ -75,6 +75,8 @@ private:
void NaClAlignIndirectJumpTargets(MachineFunction &MF);
+ bool isLongBranchPseudo(int Opcode) const;
+
public:
const MipsSubtarget *Subtarget;
@@ -82,18 +84,18 @@ public:
MipsMCInstLower MCInstLowering;
explicit MipsAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
- : AsmPrinter(TM, Streamer), MCP(0), InConstantPool(false),
+ : AsmPrinter(TM, Streamer), MCP(nullptr), InConstantPool(false),
MCInstLowering(*this) {
Subtarget = &TM.getSubtarget<MipsSubtarget>();
}
- virtual const char *getPassName() const {
+ const char *getPassName() const override {
return "Mips Assembly Printer";
}
- virtual bool runOnMachineFunction(MachineFunction &MF);
+ bool runOnMachineFunction(MachineFunction &MF) override;
- virtual void EmitConstantPool() override {
+ void EmitConstantPool() override {
bool UsingConstantPools =
(Subtarget->inMips16Mode() && Subtarget->useConstantIslands());
if (!UsingConstantPools)
@@ -101,30 +103,30 @@ public:
// we emit constant pools customly!
}
- void EmitInstruction(const MachineInstr *MI);
+ void EmitInstruction(const MachineInstr *MI) override;
void printSavedRegsBitmask();
void emitFrameDirective();
const char *getCurrentABIString() const;
- virtual void EmitFunctionEntryLabel();
- virtual void EmitFunctionBodyStart();
- virtual void EmitFunctionBodyEnd();
- virtual bool isBlockOnlyReachableByFallthrough(const MachineBasicBlock*
- MBB) const;
+ void EmitFunctionEntryLabel() override;
+ void EmitFunctionBodyStart() override;
+ void EmitFunctionBodyEnd() override;
+ bool isBlockOnlyReachableByFallthrough(
+ const MachineBasicBlock* MBB) const override;
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
unsigned AsmVariant, const char *ExtraCode,
- raw_ostream &O);
+ raw_ostream &O) override;
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
unsigned AsmVariant, const char *ExtraCode,
- raw_ostream &O);
+ 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,
- const char *Modifier = 0);
- void EmitStartOfAsmFile(Module &M);
- void EmitEndOfAsmFile(Module &M);
+ const char *Modifier = nullptr);
+ void EmitStartOfAsmFile(Module &M) override;
+ void EmitEndOfAsmFile(Module &M) override;
void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS);
};
}
diff --git a/lib/Target/Mips/MipsCallingConv.td b/lib/Target/Mips/MipsCallingConv.td
index 615310f..c83d880 100644
--- a/lib/Target/Mips/MipsCallingConv.td
+++ b/lib/Target/Mips/MipsCallingConv.td
@@ -245,8 +245,8 @@ def CSR_O32 : CalleeSavedRegs<(add (sequence "D%u", 15, 10), RA, FP,
def CSR_O32_FP64 : CalleeSavedRegs<(add (sequence "D%u_64", 31, 20), RA, FP,
(sequence "S%u", 7, 0))>;
-def CSR_N32 : CalleeSavedRegs<(add D31_64, D29_64, D27_64, D25_64, D24_64,
- D23_64, D22_64, D21_64, RA_64, FP_64, GP_64,
+def CSR_N32 : CalleeSavedRegs<(add D20_64, D22_64, D24_64, D26_64, D28_64,
+ D30_64, RA_64, FP_64, GP_64,
(sequence "S%u_64", 7, 0))>;
def CSR_N64 : CalleeSavedRegs<(add (sequence "D%u_64", 31, 24), RA_64, FP_64,
diff --git a/lib/Target/Mips/MipsCodeEmitter.cpp b/lib/Target/Mips/MipsCodeEmitter.cpp
index ea49086..13fa546 100644
--- a/lib/Target/Mips/MipsCodeEmitter.cpp
+++ b/lib/Target/Mips/MipsCodeEmitter.cpp
@@ -12,7 +12,6 @@
//
//===---------------------------------------------------------------------===//
-#define DEBUG_TYPE "jit"
#include "Mips.h"
#include "MCTargetDesc/MipsBaseInfo.h"
#include "MipsInstrInfo.h"
@@ -41,6 +40,8 @@
using namespace llvm;
+#define DEBUG_TYPE "jit"
+
STATISTIC(NumEmitted, "Number of machine instructions emitted");
namespace {
@@ -56,7 +57,7 @@ class MipsCodeEmitter : public MachineFunctionPass {
const std::vector<MachineJumpTableEntry> *MJTEs;
bool IsPIC;
- void getAnalysisUsage(AnalysisUsage &AU) const {
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addRequired<MachineModuleInfo> ();
MachineFunctionPass::getAnalysisUsage(AU);
}
@@ -65,13 +66,13 @@ class MipsCodeEmitter : public MachineFunctionPass {
public:
MipsCodeEmitter(TargetMachine &tm, JITCodeEmitter &mce)
- : MachineFunctionPass(ID), JTI(0), II(0), TD(0),
- TM(tm), MCE(mce), MCPEs(0), MJTEs(0),
+ : MachineFunctionPass(ID), JTI(nullptr), II(nullptr), TD(nullptr),
+ TM(tm), MCE(mce), MCPEs(nullptr), MJTEs(nullptr),
IsPIC(TM.getRelocationModel() == Reloc::PIC_) {}
- bool runOnMachineFunction(MachineFunction &MF);
+ bool runOnMachineFunction(MachineFunction &MF) override;
- virtual const char *getPassName() const {
+ const char *getPassName() const override {
return "Mips Machine Code Emitter";
}
@@ -109,6 +110,12 @@ private:
unsigned getBranchTargetOpValueMM(const MachineInstr &MI,
unsigned OpNo) const;
+ unsigned getBranchTarget21OpValue(const MachineInstr &MI,
+ unsigned OpNo) const;
+ unsigned getBranchTarget26OpValue(const MachineInstr &MI,
+ unsigned OpNo) const;
+ unsigned getJumpOffset16OpValue(const MachineInstr &MI, unsigned OpNo) const;
+
unsigned getBranchTargetOpValue(const MachineInstr &MI, unsigned OpNo) const;
unsigned getMemEncoding(const MachineInstr &MI, unsigned OpNo) const;
unsigned getMemEncodingMMImm12(const MachineInstr &MI, unsigned OpNo) const;
@@ -116,6 +123,7 @@ private:
unsigned getSizeExtEncoding(const MachineInstr &MI, unsigned OpNo) const;
unsigned getSizeInsEncoding(const MachineInstr &MI, unsigned OpNo) const;
unsigned getLSAImmEncoding(const MachineInstr &MI, unsigned OpNo) const;
+ unsigned getSimm19Lsl2Encoding(const MachineInstr &MI, unsigned OpNo) const;
/// Expand pseudo instructions with accumulator register operands.
void expandACCInstr(MachineBasicBlock::instr_iterator MI,
@@ -138,7 +146,7 @@ bool MipsCodeEmitter::runOnMachineFunction(MachineFunction &MF) {
TD = Target.getDataLayout();
Subtarget = &TM.getSubtarget<MipsSubtarget> ();
MCPEs = &MF.getConstantPool()->getConstants();
- MJTEs = 0;
+ MJTEs = nullptr;
if (MF.getJumpTableInfo()) MJTEs = &MF.getJumpTableInfo()->getJumpTables();
JTI->Initialize(MF, IsPIC, Subtarget->isLittle());
MCE.setModuleInfo(&getAnalysis<MachineModuleInfo> ());
@@ -201,6 +209,24 @@ unsigned MipsCodeEmitter::getBranchTargetOpValueMM(const MachineInstr &MI,
return 0;
}
+unsigned MipsCodeEmitter::getBranchTarget21OpValue(const MachineInstr &MI,
+ unsigned OpNo) const {
+ llvm_unreachable("Unimplemented function.");
+ return 0;
+}
+
+unsigned MipsCodeEmitter::getBranchTarget26OpValue(const MachineInstr &MI,
+ unsigned OpNo) const {
+ llvm_unreachable("Unimplemented function.");
+ return 0;
+}
+
+unsigned MipsCodeEmitter::getJumpOffset16OpValue(const MachineInstr &MI,
+ unsigned OpNo) const {
+ llvm_unreachable("Unimplemented function.");
+ return 0;
+}
+
unsigned MipsCodeEmitter::getBranchTargetOpValue(const MachineInstr &MI,
unsigned OpNo) const {
MachineOperand MO = MI.getOperand(OpNo);
@@ -247,6 +273,12 @@ unsigned MipsCodeEmitter::getLSAImmEncoding(const MachineInstr &MI,
return 0;
}
+unsigned MipsCodeEmitter::getSimm19Lsl2Encoding(const MachineInstr &MI,
+ unsigned OpNo) const {
+ llvm_unreachable("Unimplemented function.");
+ return 0;
+}
+
/// getMachineOpValue - Return binary encoding of operand. If the machine
/// operand requires relocation, record the relocation and return zero.
unsigned MipsCodeEmitter::getMachineOpValue(const MachineInstr &MI,
diff --git a/lib/Target/Mips/MipsCondMov.td b/lib/Target/Mips/MipsCondMov.td
index 567eef9..7177f65 100644
--- a/lib/Target/Mips/MipsCondMov.td
+++ b/lib/Target/Mips/MipsCondMov.td
@@ -104,9 +104,9 @@ multiclass MovnPats<RegisterClass CRC, RegisterClass DRC, Instruction MOVNInst,
// Instantiation of instructions.
def MOVZ_I_I : MMRel, CMov_I_I_FT<"movz", GPR32Opnd, GPR32Opnd, II_MOVZ>,
- ADD_FM<0, 0xa>;
+ ADD_FM<0, 0xa>, INSN_MIPS4_32;
-let Predicates = [HasStdEnc], isCodeGenOnly = 1 in {
+let isCodeGenOnly = 1 in {
def MOVZ_I_I64 : CMov_I_I_FT<"movz", GPR32Opnd, GPR64Opnd, II_MOVZ>,
ADD_FM<0, 0xa>;
def MOVZ_I64_I : CMov_I_I_FT<"movz", GPR64Opnd, GPR32Opnd, II_MOVZ>,
@@ -116,9 +116,9 @@ let Predicates = [HasStdEnc], isCodeGenOnly = 1 in {
}
def MOVN_I_I : MMRel, CMov_I_I_FT<"movn", GPR32Opnd, GPR32Opnd, II_MOVN>,
- ADD_FM<0, 0xb>;
+ ADD_FM<0, 0xb>, INSN_MIPS4_32;
-let Predicates = [HasStdEnc], isCodeGenOnly = 1 in {
+let isCodeGenOnly = 1 in {
def MOVN_I_I64 : CMov_I_I_FT<"movn", GPR32Opnd, GPR64Opnd, II_MOVN>,
ADD_FM<0, 0xb>;
def MOVN_I64_I : CMov_I_I_FT<"movn", GPR64Opnd, GPR32Opnd, II_MOVN>,
@@ -128,118 +128,112 @@ let Predicates = [HasStdEnc], isCodeGenOnly = 1 in {
}
def MOVZ_I_S : MMRel, CMov_I_F_FT<"movz.s", GPR32Opnd, FGR32Opnd, II_MOVZ_S>,
- CMov_I_F_FM<18, 16>;
+ CMov_I_F_FM<18, 16>, INSN_MIPS4_32;
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>, Requires<[HasMips64, HasStdEnc]>;
+ CMov_I_F_FM<18, 16>, AdditionalRequires<[HasMips64]>;
def MOVN_I_S : MMRel, CMov_I_F_FT<"movn.s", GPR32Opnd, FGR32Opnd, II_MOVN_S>,
- CMov_I_F_FM<19, 16>;
+ CMov_I_F_FM<19, 16>, INSN_MIPS4_32;
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>, Requires<[HasMips64, HasStdEnc]>;
+ CMov_I_F_FM<19, 16>, AdditionalRequires<[IsGP64bit]>;
-let Predicates = [NotFP64bit, HasStdEnc] in {
- def MOVZ_I_D32 : MMRel, CMov_I_F_FT<"movz.d", GPR32Opnd, AFGR64Opnd,
- II_MOVZ_D>, CMov_I_F_FM<18, 17>;
- def MOVN_I_D32 : MMRel, CMov_I_F_FT<"movn.d", GPR32Opnd, AFGR64Opnd,
- II_MOVN_D>, CMov_I_F_FM<19, 17>;
-}
+def MOVZ_I_D32 : MMRel, CMov_I_F_FT<"movz.d", GPR32Opnd, AFGR64Opnd,
+ II_MOVZ_D>, CMov_I_F_FM<18, 17>,
+ INSN_MIPS4_32, FGR_32;
+def MOVN_I_D32 : MMRel, CMov_I_F_FT<"movn.d", GPR32Opnd, AFGR64Opnd,
+ II_MOVN_D>, CMov_I_F_FM<19, 17>,
+ INSN_MIPS4_32, FGR_32;
-let Predicates = [IsFP64bit, HasStdEnc], DecoderNamespace = "Mips64" in {
+let DecoderNamespace = "Mips64" in {
def MOVZ_I_D64 : CMov_I_F_FT<"movz.d", GPR32Opnd, FGR64Opnd, II_MOVZ_D>,
- CMov_I_F_FM<18, 17>;
+ CMov_I_F_FM<18, 17>, INSN_MIPS4_32, FGR_64;
def MOVN_I_D64 : CMov_I_F_FT<"movn.d", GPR32Opnd, FGR64Opnd, II_MOVN_D>,
- CMov_I_F_FM<19, 17>;
+ CMov_I_F_FM<19, 17>, INSN_MIPS4_32, FGR_64;
let isCodeGenOnly = 1 in {
def MOVZ_I64_D64 : CMov_I_F_FT<"movz.d", GPR64Opnd, FGR64Opnd,
- II_MOVZ_D>, CMov_I_F_FM<18, 17>;
+ II_MOVZ_D>, CMov_I_F_FM<18, 17>, FGR_64;
def MOVN_I64_D64 : CMov_I_F_FT<"movn.d", GPR64Opnd, FGR64Opnd,
- II_MOVN_D>, CMov_I_F_FM<19, 17>;
+ II_MOVN_D>, CMov_I_F_FM<19, 17>, FGR_64;
}
}
def MOVT_I : MMRel, CMov_F_I_FT<"movt", GPR32Opnd, II_MOVT, MipsCMovFP_T>,
- CMov_F_I_FM<1>;
+ CMov_F_I_FM<1>, INSN_MIPS4_32;
let isCodeGenOnly = 1 in
def MOVT_I64 : CMov_F_I_FT<"movt", GPR64Opnd, II_MOVT, MipsCMovFP_T>,
- CMov_F_I_FM<1>, Requires<[HasMips64, HasStdEnc]>;
+ CMov_F_I_FM<1>, AdditionalRequires<[IsGP64bit]>;
def MOVF_I : MMRel, CMov_F_I_FT<"movf", GPR32Opnd, II_MOVF, MipsCMovFP_F>,
- CMov_F_I_FM<0>;
+ CMov_F_I_FM<0>, INSN_MIPS4_32;
let isCodeGenOnly = 1 in
def MOVF_I64 : CMov_F_I_FT<"movf", GPR64Opnd, II_MOVF, MipsCMovFP_F>,
- CMov_F_I_FM<0>, Requires<[HasMips64, HasStdEnc]>;
+ CMov_F_I_FM<0>, AdditionalRequires<[IsGP64bit]>;
def MOVT_S : MMRel, CMov_F_F_FT<"movt.s", FGR32Opnd, II_MOVT_S, MipsCMovFP_T>,
- CMov_F_F_FM<16, 1>;
+ CMov_F_F_FM<16, 1>, INSN_MIPS4_32;
def MOVF_S : MMRel, CMov_F_F_FT<"movf.s", FGR32Opnd, II_MOVF_S, MipsCMovFP_F>,
- CMov_F_F_FM<16, 0>;
+ CMov_F_F_FM<16, 0>, INSN_MIPS4_32;
-let Predicates = [NotFP64bit, HasStdEnc] in {
- def MOVT_D32 : MMRel, CMov_F_F_FT<"movt.d", AFGR64Opnd, II_MOVT_D,
- MipsCMovFP_T>, CMov_F_F_FM<17, 1>;
- def MOVF_D32 : MMRel, CMov_F_F_FT<"movf.d", AFGR64Opnd, II_MOVF_D,
- MipsCMovFP_F>, CMov_F_F_FM<17, 0>;
-}
+def MOVT_D32 : MMRel, CMov_F_F_FT<"movt.d", AFGR64Opnd, II_MOVT_D,
+ MipsCMovFP_T>, CMov_F_F_FM<17, 1>,
+ INSN_MIPS4_32, FGR_32;
+def MOVF_D32 : MMRel, CMov_F_F_FT<"movf.d", AFGR64Opnd, II_MOVF_D,
+ MipsCMovFP_F>, CMov_F_F_FM<17, 0>,
+ INSN_MIPS4_32, FGR_32;
-let Predicates = [IsFP64bit, HasStdEnc], DecoderNamespace = "Mips64" in {
+let DecoderNamespace = "Mips64" in {
def MOVT_D64 : CMov_F_F_FT<"movt.d", FGR64Opnd, II_MOVT_D, MipsCMovFP_T>,
- CMov_F_F_FM<17, 1>;
+ CMov_F_F_FM<17, 1>, INSN_MIPS4_32, FGR_64;
def MOVF_D64 : CMov_F_F_FT<"movf.d", FGR64Opnd, II_MOVF_D, MipsCMovFP_F>,
- CMov_F_F_FM<17, 0>;
+ CMov_F_F_FM<17, 0>, INSN_MIPS4_32, FGR_64;
}
// Instantiation of conditional move patterns.
defm : MovzPats0<GPR32, GPR32, MOVZ_I_I, SLT, SLTu, SLTi, SLTiu>;
defm : MovzPats1<GPR32, GPR32, MOVZ_I_I, XOR>;
defm : MovzPats2<GPR32, GPR32, MOVZ_I_I, XORi>;
-let Predicates = [HasMips64, HasStdEnc] in {
- defm : MovzPats0<GPR32, GPR64, MOVZ_I_I64, SLT, SLTu, SLTi, SLTiu>;
- defm : MovzPats0<GPR64, GPR32, MOVZ_I_I, SLT64, SLTu64, SLTi64,
- SLTiu64>;
- defm : MovzPats0<GPR64, GPR64, MOVZ_I_I64, SLT64, SLTu64, SLTi64,
- SLTiu64>;
- defm : MovzPats1<GPR32, GPR64, MOVZ_I_I64, XOR>;
- defm : MovzPats1<GPR64, GPR32, MOVZ_I64_I, XOR64>;
- defm : MovzPats1<GPR64, GPR64, MOVZ_I64_I64, XOR64>;
- defm : MovzPats2<GPR32, GPR64, MOVZ_I_I64, XORi>;
- defm : MovzPats2<GPR64, GPR32, MOVZ_I64_I, XORi64>;
- defm : MovzPats2<GPR64, GPR64, MOVZ_I64_I64, XORi64>;
-}
+
+defm : MovzPats0<GPR32, GPR64, MOVZ_I_I64, SLT, SLTu, SLTi, SLTiu>, GPR_64;
+defm : MovzPats0<GPR64, GPR32, MOVZ_I_I, SLT64, SLTu64, SLTi64, SLTiu64>,
+ GPR_64;
+defm : MovzPats0<GPR64, GPR64, MOVZ_I_I64, SLT64, SLTu64, SLTi64, SLTiu64>,
+ GPR_64;
+defm : MovzPats1<GPR32, GPR64, MOVZ_I_I64, XOR>, GPR_64;
+defm : MovzPats1<GPR64, GPR32, MOVZ_I64_I, XOR64>, GPR_64;
+defm : MovzPats1<GPR64, GPR64, MOVZ_I64_I64, XOR64>, GPR_64;
+defm : MovzPats2<GPR32, GPR64, MOVZ_I_I64, XORi>, GPR_64;
+defm : MovzPats2<GPR64, GPR32, MOVZ_I64_I, XORi64>, GPR_64;
+defm : MovzPats2<GPR64, GPR64, MOVZ_I64_I64, XORi64>, GPR_64;
defm : MovnPats<GPR32, GPR32, MOVN_I_I, XOR>;
-let Predicates = [HasMips64, HasStdEnc] in {
- defm : MovnPats<GPR32, GPR64, MOVN_I_I64, XOR>;
- defm : MovnPats<GPR64, GPR32, MOVN_I64_I, XOR64>;
- defm : MovnPats<GPR64, GPR64, MOVN_I64_I64, XOR64>;
-}
+
+defm : MovnPats<GPR32, GPR64, MOVN_I_I64, XOR>, GPR_64;
+defm : MovnPats<GPR64, GPR32, MOVN_I64_I, XOR64>, GPR_64;
+defm : MovnPats<GPR64, GPR64, MOVN_I64_I64, XOR64>, GPR_64;
defm : MovzPats0<GPR32, FGR32, MOVZ_I_S, SLT, SLTu, SLTi, SLTiu>;
defm : MovzPats1<GPR32, FGR32, MOVZ_I_S, XOR>;
defm : MovnPats<GPR32, FGR32, MOVN_I_S, XOR>;
-let Predicates = [HasMips64, HasStdEnc] in {
- defm : MovzPats0<GPR64, FGR32, MOVZ_I_S, SLT64, SLTu64, SLTi64,
- SLTiu64>;
- defm : MovzPats1<GPR64, FGR32, MOVZ_I64_S, XOR64>;
- defm : MovnPats<GPR64, FGR32, MOVN_I64_S, XOR64>;
-}
-let Predicates = [NotFP64bit, HasStdEnc] in {
- defm : MovzPats0<GPR32, AFGR64, MOVZ_I_D32, SLT, SLTu, SLTi, SLTiu>;
- defm : MovzPats1<GPR32, AFGR64, MOVZ_I_D32, XOR>;
- defm : MovnPats<GPR32, AFGR64, MOVN_I_D32, XOR>;
-}
-let Predicates = [IsFP64bit, HasStdEnc] in {
- defm : MovzPats0<GPR32, FGR64, MOVZ_I_D64, SLT, SLTu, SLTi, SLTiu>;
- defm : MovzPats0<GPR64, FGR64, MOVZ_I_D64, SLT64, SLTu64, SLTi64,
- SLTiu64>;
- defm : MovzPats1<GPR32, FGR64, MOVZ_I_D64, XOR>;
- defm : MovzPats1<GPR64, FGR64, MOVZ_I64_D64, XOR64>;
- defm : MovnPats<GPR32, FGR64, MOVN_I_D64, XOR>;
- defm : MovnPats<GPR64, FGR64, MOVN_I64_D64, XOR64>;
-}
+defm : MovzPats0<GPR64, FGR32, MOVZ_I_S, SLT64, SLTu64, SLTi64, SLTiu64>,
+ GPR_64;
+defm : MovzPats1<GPR64, FGR32, MOVZ_I64_S, XOR64>, GPR_64;
+defm : MovnPats<GPR64, FGR32, MOVN_I64_S, XOR64>, GPR_64;
+
+defm : MovzPats0<GPR32, AFGR64, MOVZ_I_D32, SLT, SLTu, SLTi, SLTiu>, FGR_32;
+defm : MovzPats1<GPR32, AFGR64, MOVZ_I_D32, XOR>, FGR_32;
+defm : MovnPats<GPR32, AFGR64, MOVN_I_D32, XOR>, FGR_32;
+
+defm : MovzPats0<GPR32, FGR64, MOVZ_I_D64, SLT, SLTu, SLTi, SLTiu>, FGR_64;
+defm : MovzPats0<GPR64, FGR64, MOVZ_I_D64, SLT64, SLTu64, SLTi64, SLTiu64>,
+ FGR_64;
+defm : MovzPats1<GPR32, FGR64, MOVZ_I_D64, XOR>, FGR_64;
+defm : MovzPats1<GPR64, FGR64, MOVZ_I64_D64, XOR64>, FGR_64;
+defm : MovnPats<GPR32, FGR64, MOVN_I_D64, XOR>, FGR_64;
+defm : MovnPats<GPR64, FGR64, MOVN_I64_D64, XOR64>, FGR_64;
diff --git a/lib/Target/Mips/MipsConstantIslandPass.cpp b/lib/Target/Mips/MipsConstantIslandPass.cpp
index e5642ba..a37062f 100644
--- a/lib/Target/Mips/MipsConstantIslandPass.cpp
+++ b/lib/Target/Mips/MipsConstantIslandPass.cpp
@@ -21,8 +21,6 @@
//
//
-#define DEBUG_TYPE "mips-constant-islands"
-
#include "Mips.h"
#include "MCTargetDesc/MipsBaseInfo.h"
#include "Mips16InstrInfo.h"
@@ -47,6 +45,8 @@
using namespace llvm;
+#define DEBUG_TYPE "mips-constant-islands"
+
STATISTIC(NumCPEs, "Number of constpool entries");
STATISTIC(NumSplit, "Number of uncond branches inserted");
STATISTIC(NumCBrFixed, "Number of cond branches fixed");
@@ -368,14 +368,14 @@ namespace {
: MachineFunctionPass(ID), TM(tm),
IsPIC(TM.getRelocationModel() == Reloc::PIC_),
ABI(TM.getSubtarget<MipsSubtarget>().getTargetABI()),
- STI(&TM.getSubtarget<MipsSubtarget>()), MF(0), MCP(0),
+ STI(&TM.getSubtarget<MipsSubtarget>()), MF(nullptr), MCP(nullptr),
PrescannedForConstants(false){}
- virtual const char *getPassName() const {
+ const char *getPassName() const override {
return "Mips Constant Islands";
}
- bool runOnMachineFunction(MachineFunction &F);
+ bool runOnMachineFunction(MachineFunction &F) override;
void doInitialPlacement(std::vector<MachineInstr*> &CPEMIs);
CPEntry *findConstPoolEntry(unsigned CPI, const MachineInstr *CPEMI);
@@ -628,7 +628,7 @@ MipsConstantIslands::CPEntry
if (CPEs[i].CPEMI == CPEMI)
return &CPEs[i];
}
- return NULL;
+ return nullptr;
}
/// getCPELogAlign - Returns the required alignment of the constant pool entry
@@ -1065,7 +1065,7 @@ bool MipsConstantIslands::decrementCPEReferenceCount(unsigned CPI,
assert(CPE && "Unexpected!");
if (--CPE->RefCount == 0) {
removeDeadCPEMI(CPEMI);
- CPE->CPEMI = NULL;
+ CPE->CPEMI = nullptr;
--NumCPEs;
return true;
}
@@ -1098,7 +1098,7 @@ int MipsConstantIslands::findInRangeCPEntry(CPUser& U, unsigned UserOffset)
if (CPEs[i].CPEMI == CPEMI)
continue;
// Removing CPEs can leave empty entries, skip
- if (CPEs[i].CPEMI == NULL)
+ if (CPEs[i].CPEMI == nullptr)
continue;
if (isCPEntryInRange(UserMI, UserOffset, CPEs[i].CPEMI, U.getMaxDisp(),
U.NegOk)) {
@@ -1154,7 +1154,7 @@ int MipsConstantIslands::findLongFormInRangeCPEntry
if (CPEs[i].CPEMI == CPEMI)
continue;
// Removing CPEs can leave empty entries, skip
- if (CPEs[i].CPEMI == NULL)
+ if (CPEs[i].CPEMI == nullptr)
continue;
if (isCPEntryInRange(UserMI, UserOffset, CPEs[i].CPEMI,
U.getLongFormMaxDisp(), U.NegOk)) {
@@ -1486,7 +1486,7 @@ bool MipsConstantIslands::removeUnusedCPEntries() {
for (unsigned j = 0, ee = CPEs.size(); j != ee; ++j) {
if (CPEs[j].RefCount == 0 && CPEs[j].CPEMI) {
removeDeadCPEMI(CPEs[j].CPEMI);
- CPEs[j].CPEMI = NULL;
+ CPEs[j].CPEMI = nullptr;
MadeChange = true;
}
}
diff --git a/lib/Target/Mips/MipsDelaySlotFiller.cpp b/lib/Target/Mips/MipsDelaySlotFiller.cpp
index eef9f38..d6c7cac 100644
--- a/lib/Target/Mips/MipsDelaySlotFiller.cpp
+++ b/lib/Target/Mips/MipsDelaySlotFiller.cpp
@@ -11,8 +11,6 @@
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "delay-slot-filler"
-
#include "MCTargetDesc/MipsMCNaCl.h"
#include "Mips.h"
#include "MipsInstrInfo.h"
@@ -33,6 +31,8 @@
using namespace llvm;
+#define DEBUG_TYPE "delay-slot-filler"
+
STATISTIC(FilledSlots, "Number of delay slots filled");
STATISTIC(UsefulSlots, "Number of delay slots filled with instructions that"
" are not NOP.");
@@ -124,7 +124,7 @@ namespace {
public:
NoMemInstr() : InspectMemInstr(true) {}
private:
- virtual bool hasHazard_(const MachineInstr &MI) { return true; }
+ bool hasHazard_(const MachineInstr &MI) override { return true; }
};
/// This subclass accepts loads from stacks and constant loads.
@@ -132,7 +132,7 @@ namespace {
public:
LoadFromStackOrConst() : InspectMemInstr(false) {}
private:
- virtual bool hasHazard_(const MachineInstr &MI);
+ bool hasHazard_(const MachineInstr &MI) override;
};
/// This subclass uses memory dependence information to determine whether a
@@ -142,19 +142,21 @@ namespace {
MemDefsUses(const MachineFrameInfo *MFI);
private:
- virtual bool hasHazard_(const MachineInstr &MI);
+ typedef PointerUnion<const Value *, const PseudoSourceValue *> ValueType;
+
+ bool hasHazard_(const MachineInstr &MI) override;
/// Update Defs and Uses. Return true if there exist dependences that
/// disqualify the delay slot candidate between V and values in Uses and
/// Defs.
- bool updateDefsUses(const Value *V, bool MayStore);
+ bool updateDefsUses(ValueType V, bool MayStore);
/// Get the list of underlying objects of MI's memory operand.
bool getUnderlyingObjects(const MachineInstr &MI,
- SmallVectorImpl<const Value *> &Objects) const;
+ SmallVectorImpl<ValueType> &Objects) const;
const MachineFrameInfo *MFI;
- SmallPtrSet<const Value*, 4> Uses, Defs;
+ SmallPtrSet<ValueType, 4> Uses, Defs;
/// Flags indicating whether loads or stores with no underlying objects have
/// been seen.
@@ -166,11 +168,11 @@ namespace {
Filler(TargetMachine &tm)
: MachineFunctionPass(ID), TM(tm) { }
- virtual const char *getPassName() const {
+ const char *getPassName() const override {
return "Mips Delay Slot Filler";
}
- bool runOnMachineFunction(MachineFunction &F) {
+ bool runOnMachineFunction(MachineFunction &F) override {
bool Changed = false;
for (MachineFunction::iterator FI = F.begin(), FE = F.end();
FI != FE; ++FI)
@@ -178,7 +180,7 @@ namespace {
return Changed;
}
- void getAnalysisUsage(AnalysisUsage &AU) const {
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addRequired<MachineBranchProbabilityInfo>();
MachineFunctionPass::getAnalysisUsage(AU);
}
@@ -399,16 +401,15 @@ bool LoadFromStackOrConst::hasHazard_(const MachineInstr &MI) {
if (MI.mayStore())
return true;
- if (!MI.hasOneMemOperand() || !(*MI.memoperands_begin())->getValue())
+ if (!MI.hasOneMemOperand() || !(*MI.memoperands_begin())->getPseudoValue())
return true;
- const Value *V = (*MI.memoperands_begin())->getValue();
-
- if (isa<FixedStackPseudoSourceValue>(V))
- return false;
-
- if (const PseudoSourceValue *PSV = dyn_cast<const PseudoSourceValue>(V))
- return !PSV->isConstant(0) && V != PseudoSourceValue::getStack();
+ if (const PseudoSourceValue *PSV =
+ (*MI.memoperands_begin())->getPseudoValue()) {
+ if (isa<FixedStackPseudoSourceValue>(PSV))
+ return false;
+ return !PSV->isConstant(nullptr) && PSV != PseudoSourceValue::getStack();
+ }
return true;
}
@@ -419,11 +420,11 @@ MemDefsUses::MemDefsUses(const MachineFrameInfo *MFI_)
bool MemDefsUses::hasHazard_(const MachineInstr &MI) {
bool HasHazard = false;
- SmallVector<const Value *, 4> Objs;
+ SmallVector<ValueType, 4> Objs;
// Check underlying object list.
if (getUnderlyingObjects(MI, Objs)) {
- for (SmallVectorImpl<const Value *>::const_iterator I = Objs.begin();
+ for (SmallVectorImpl<ValueType>::const_iterator I = Objs.begin();
I != Objs.end(); ++I)
HasHazard |= updateDefsUses(*I, MI.mayStore());
@@ -440,7 +441,7 @@ bool MemDefsUses::hasHazard_(const MachineInstr &MI) {
return HasHazard;
}
-bool MemDefsUses::updateDefsUses(const Value *V, bool MayStore) {
+bool MemDefsUses::updateDefsUses(ValueType V, bool MayStore) {
if (MayStore)
return !Defs.insert(V) || Uses.count(V) || SeenNoObjStore || SeenNoObjLoad;
@@ -450,10 +451,20 @@ bool MemDefsUses::updateDefsUses(const Value *V, bool MayStore) {
bool MemDefsUses::
getUnderlyingObjects(const MachineInstr &MI,
- SmallVectorImpl<const Value *> &Objects) const {
- if (!MI.hasOneMemOperand() || !(*MI.memoperands_begin())->getValue())
+ SmallVectorImpl<ValueType> &Objects) const {
+ if (!MI.hasOneMemOperand() ||
+ (!(*MI.memoperands_begin())->getValue() &&
+ !(*MI.memoperands_begin())->getPseudoValue()))
return false;
+ if (const PseudoSourceValue *PSV =
+ (*MI.memoperands_begin())->getPseudoValue()) {
+ if (!PSV->isAliased(MFI))
+ return false;
+ Objects.push_back(PSV);
+ return true;
+ }
+
const Value *V = (*MI.memoperands_begin())->getValue();
SmallVector<Value *, 4> Objs;
@@ -461,10 +472,7 @@ getUnderlyingObjects(const MachineInstr &MI,
for (SmallVectorImpl<Value *>::iterator I = Objs.begin(), E = Objs.end();
I != E; ++I) {
- if (const PseudoSourceValue *PSV = dyn_cast<PseudoSourceValue>(*I)) {
- if (PSV->isAliased(MFI))
- return false;
- } else if (!isIdentifiedObject(V))
+ if (!isIdentifiedObject(V))
return false;
Objects.push_back(*I);
@@ -602,7 +610,7 @@ bool Filler::searchSuccBBs(MachineBasicBlock &MBB, Iter Slot) const {
RegDefsUses RegDU(TM);
bool HasMultipleSuccs = false;
BB2BrMap BrMap;
- OwningPtr<InspectMemInstr> IM;
+ std::unique_ptr<InspectMemInstr> IM;
Iter Filler;
// Iterate over SuccBB's predecessor list.
@@ -636,7 +644,7 @@ bool Filler::searchSuccBBs(MachineBasicBlock &MBB, Iter Slot) const {
MachineBasicBlock *Filler::selectSuccBB(MachineBasicBlock &B) const {
if (B.succ_empty())
- return NULL;
+ return nullptr;
// Select the successor with the larget edge weight.
auto &Prob = getAnalysis<MachineBranchProbabilityInfo>();
@@ -645,14 +653,14 @@ MachineBasicBlock *Filler::selectSuccBB(MachineBasicBlock &B) const {
const MachineBasicBlock *Dst1) {
return Prob.getEdgeWeight(&B, Dst0) < Prob.getEdgeWeight(&B, Dst1);
});
- return S->isLandingPad() ? NULL : S;
+ return S->isLandingPad() ? nullptr : S;
}
std::pair<MipsInstrInfo::BranchType, MachineInstr *>
Filler::getBranch(MachineBasicBlock &MBB, const MachineBasicBlock &Dst) const {
const MipsInstrInfo *TII =
static_cast<const MipsInstrInfo*>(TM.getInstrInfo());
- MachineBasicBlock *TrueBB = 0, *FalseBB = 0;
+ MachineBasicBlock *TrueBB = nullptr, *FalseBB = nullptr;
SmallVector<MachineInstr*, 2> BranchInstrs;
SmallVector<MachineOperand, 2> Cond;
@@ -660,11 +668,11 @@ Filler::getBranch(MachineBasicBlock &MBB, const MachineBasicBlock &Dst) const {
TII->AnalyzeBranch(MBB, TrueBB, FalseBB, Cond, false, BranchInstrs);
if ((R == MipsInstrInfo::BT_None) || (R == MipsInstrInfo::BT_NoBranch))
- return std::make_pair(R, (MachineInstr*)NULL);
+ return std::make_pair(R, nullptr);
if (R != MipsInstrInfo::BT_CondUncond) {
if (!hasUnoccupiedSlot(BranchInstrs[0]))
- return std::make_pair(MipsInstrInfo::BT_None, (MachineInstr*)NULL);
+ return std::make_pair(MipsInstrInfo::BT_None, nullptr);
assert(((R != MipsInstrInfo::BT_Uncond) || (TrueBB == &Dst)));
@@ -681,7 +689,7 @@ Filler::getBranch(MachineBasicBlock &MBB, const MachineBasicBlock &Dst) const {
if (hasUnoccupiedSlot(BranchInstrs[1]) && (FalseBB == &Dst))
return std::make_pair(MipsInstrInfo::BT_Uncond, BranchInstrs[1]);
- return std::make_pair(MipsInstrInfo::BT_None, (MachineInstr*)NULL);
+ return std::make_pair(MipsInstrInfo::BT_None, nullptr);
}
bool Filler::examinePred(MachineBasicBlock &Pred, const MachineBasicBlock &Succ,
diff --git a/lib/Target/Mips/MipsFastISel.cpp b/lib/Target/Mips/MipsFastISel.cpp
new file mode 100644
index 0000000..268a0ed
--- /dev/null
+++ b/lib/Target/Mips/MipsFastISel.cpp
@@ -0,0 +1,283 @@
+//===-- MipsastISel.cpp - Mips FastISel implementation
+//---------------------===//
+
+#include "llvm/CodeGen/FunctionLoweringInfo.h"
+#include "llvm/CodeGen/FastISel.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/IR/GlobalAlias.h"
+#include "llvm/IR/GlobalVariable.h"
+#include "llvm/Target/TargetInstrInfo.h"
+#include "llvm/Target/TargetLibraryInfo.h"
+#include "MipsRegisterInfo.h"
+#include "MipsISelLowering.h"
+#include "MipsMachineFunction.h"
+#include "MipsSubtarget.h"
+
+using namespace llvm;
+
+namespace {
+
+// All possible address modes.
+typedef struct Address {
+ enum { RegBase, FrameIndexBase } BaseType;
+
+ union {
+ unsigned Reg;
+ int FI;
+ } Base;
+
+ int64_t Offset;
+
+ // Innocuous defaults for our address.
+ Address() : BaseType(RegBase), Offset(0) { Base.Reg = 0; }
+} Address;
+
+class MipsFastISel final : public FastISel {
+
+ /// Subtarget - Keep a pointer to the MipsSubtarget around so that we can
+ /// make the right decision when generating code for different targets.
+ const MipsSubtarget *Subtarget;
+ Module &M;
+ const TargetMachine &TM;
+ const TargetInstrInfo &TII;
+ const TargetLowering &TLI;
+ MipsFunctionInfo *MFI;
+
+ // Convenience variables to avoid some queries.
+ LLVMContext *Context;
+
+ bool TargetSupported;
+
+public:
+ explicit MipsFastISel(FunctionLoweringInfo &funcInfo,
+ const TargetLibraryInfo *libInfo)
+ : FastISel(funcInfo, libInfo),
+ M(const_cast<Module &>(*funcInfo.Fn->getParent())),
+ TM(funcInfo.MF->getTarget()), TII(*TM.getInstrInfo()),
+ TLI(*TM.getTargetLowering()) {
+ Subtarget = &TM.getSubtarget<MipsSubtarget>();
+ MFI = funcInfo.MF->getInfo<MipsFunctionInfo>();
+ Context = &funcInfo.Fn->getContext();
+ TargetSupported = ((Subtarget->getRelocationModel() == Reloc::PIC_) &&
+ (Subtarget->hasMips32r2() && (Subtarget->isABI_O32())));
+ }
+
+ bool TargetSelectInstruction(const Instruction *I) override;
+ unsigned TargetMaterializeConstant(const Constant *C) override;
+
+ bool ComputeAddress(const Value *Obj, Address &Addr);
+
+private:
+ bool EmitStore(MVT VT, unsigned SrcReg, Address &Addr,
+ unsigned Alignment = 0);
+ bool SelectRet(const Instruction *I);
+ bool SelectStore(const Instruction *I);
+
+ bool isTypeLegal(Type *Ty, MVT &VT);
+ bool isLoadTypeLegal(Type *Ty, MVT &VT);
+
+ unsigned MaterializeFP(const ConstantFP *CFP, MVT VT);
+ unsigned MaterializeGV(const GlobalValue *GV, MVT VT);
+ unsigned MaterializeInt(const Constant *C, MVT VT);
+ unsigned Materialize32BitInt(int64_t Imm, const TargetRegisterClass *RC);
+};
+
+bool MipsFastISel::isTypeLegal(Type *Ty, MVT &VT) {
+ EVT evt = TLI.getValueType(Ty, true);
+ // Only handle simple types.
+ if (evt == MVT::Other || !evt.isSimple())
+ return false;
+ VT = evt.getSimpleVT();
+
+ // Handle all legal types, i.e. a register that will directly hold this
+ // value.
+ return TLI.isTypeLegal(VT);
+}
+
+bool MipsFastISel::isLoadTypeLegal(Type *Ty, MVT &VT) {
+ if (isTypeLegal(Ty, VT))
+ return true;
+ // We will extend this in a later patch:
+ // If this is a type than can be sign or zero-extended to a basic operation
+ // go ahead and accept it now.
+ return false;
+}
+
+bool MipsFastISel::ComputeAddress(const Value *Obj, Address &Addr) {
+ // This construct looks a big awkward but it is how other ports handle this
+ // and as this function is more fully completed, these cases which
+ // return false will have additional code in them.
+ //
+ if (isa<Instruction>(Obj))
+ return false;
+ else if (isa<ConstantExpr>(Obj))
+ return false;
+ Addr.Base.Reg = getRegForValue(Obj);
+ return Addr.Base.Reg != 0;
+}
+
+// Materialize a constant into a register, and return the register
+// number (or zero if we failed to handle it).
+unsigned MipsFastISel::TargetMaterializeConstant(const Constant *C) {
+ EVT CEVT = TLI.getValueType(C->getType(), true);
+
+ // Only handle simple types.
+ if (!CEVT.isSimple())
+ return 0;
+ MVT VT = CEVT.getSimpleVT();
+
+ if (const ConstantFP *CFP = dyn_cast<ConstantFP>(C))
+ return MaterializeFP(CFP, VT);
+ else if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
+ return MaterializeGV(GV, VT);
+ else if (isa<ConstantInt>(C))
+ return MaterializeInt(C, VT);
+
+ return 0;
+}
+
+bool MipsFastISel::EmitStore(MVT VT, unsigned SrcReg, Address &Addr,
+ unsigned Alignment) {
+ //
+ // more cases will be handled here in following patches.
+ //
+ if (VT != MVT::i32)
+ return false;
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::SW))
+ .addReg(SrcReg)
+ .addReg(Addr.Base.Reg)
+ .addImm(Addr.Offset);
+ return true;
+}
+
+bool MipsFastISel::SelectStore(const Instruction *I) {
+ Value *Op0 = I->getOperand(0);
+ unsigned SrcReg = 0;
+
+ // Atomic stores need special handling.
+ if (cast<StoreInst>(I)->isAtomic())
+ return false;
+
+ // Verify we have a legal type before going any further.
+ MVT VT;
+ if (!isLoadTypeLegal(I->getOperand(0)->getType(), VT))
+ return false;
+
+ // Get the value to be stored into a register.
+ SrcReg = getRegForValue(Op0);
+ if (SrcReg == 0)
+ return false;
+
+ // See if we can handle this address.
+ Address Addr;
+ if (!ComputeAddress(I->getOperand(1), Addr))
+ return false;
+
+ if (!EmitStore(VT, SrcReg, Addr, cast<StoreInst>(I)->getAlignment()))
+ return false;
+ return true;
+}
+
+bool MipsFastISel::SelectRet(const Instruction *I) {
+ const ReturnInst *Ret = cast<ReturnInst>(I);
+
+ if (!FuncInfo.CanLowerReturn)
+ return false;
+ if (Ret->getNumOperands() > 0) {
+ return false;
+ }
+ unsigned RetOpc = Mips::RetRA;
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(RetOpc));
+ return true;
+}
+
+bool MipsFastISel::TargetSelectInstruction(const Instruction *I) {
+ if (!TargetSupported)
+ return false;
+ switch (I->getOpcode()) {
+ default:
+ break;
+ case Instruction::Store:
+ return SelectStore(I);
+ case Instruction::Ret:
+ return SelectRet(I);
+ }
+ return false;
+}
+}
+
+unsigned MipsFastISel::MaterializeFP(const ConstantFP *CFP, MVT VT) {
+ return 0;
+}
+
+unsigned MipsFastISel::MaterializeGV(const GlobalValue *GV, MVT VT) {
+ // For now 32-bit only.
+ if (VT != MVT::i32)
+ return 0;
+ const TargetRegisterClass *RC = &Mips::GPR32RegClass;
+ unsigned DestReg = createResultReg(RC);
+ const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);
+ bool IsThreadLocal = GVar && GVar->isThreadLocal();
+ // TLS not supported at this time.
+ if (IsThreadLocal)
+ return 0;
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::LW), DestReg)
+ .addReg(MFI->getGlobalBaseReg())
+ .addGlobalAddress(GV, 0, MipsII::MO_GOT);
+ return DestReg;
+}
+unsigned MipsFastISel::MaterializeInt(const Constant *C, MVT VT) {
+ if (VT != MVT::i32 && VT != MVT::i16 && VT != MVT::i8 && VT != MVT::i1)
+ return 0;
+ const TargetRegisterClass *RC = &Mips::GPR32RegClass;
+ const ConstantInt *CI = cast<ConstantInt>(C);
+ int64_t Imm;
+ if (CI->isNegative())
+ Imm = CI->getSExtValue();
+ else
+ Imm = CI->getZExtValue();
+ return Materialize32BitInt(Imm, RC);
+}
+
+unsigned MipsFastISel::Materialize32BitInt(int64_t Imm,
+ const TargetRegisterClass *RC) {
+ unsigned ResultReg = createResultReg(RC);
+
+ if (isInt<16>(Imm)) {
+ unsigned Opc = Mips::ADDiu;
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Opc), ResultReg)
+ .addReg(Mips::ZERO)
+ .addImm(Imm);
+ return ResultReg;
+ } else if (isUInt<16>(Imm)) {
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::ORi),
+ ResultReg)
+ .addReg(Mips::ZERO)
+ .addImm(Imm);
+ return ResultReg;
+ }
+ unsigned Lo = Imm & 0xFFFF;
+ unsigned Hi = (Imm >> 16) & 0xFFFF;
+ if (Lo) {
+ // Both Lo and Hi have nonzero bits.
+ unsigned TmpReg = createResultReg(RC);
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::LUi),
+ TmpReg).addImm(Hi);
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::ORi),
+ ResultReg)
+ .addReg(TmpReg)
+ .addImm(Lo);
+
+ } else {
+ BuildMI(*FuncInfo.MBB, FuncInfo.InsertPt, DbgLoc, TII.get(Mips::LUi),
+ ResultReg).addImm(Hi);
+ }
+ return ResultReg;
+}
+
+namespace llvm {
+FastISel *Mips::createFastISel(FunctionLoweringInfo &funcInfo,
+ const TargetLibraryInfo *libInfo) {
+ return new MipsFastISel(funcInfo, libInfo);
+}
+}
diff --git a/lib/Target/Mips/MipsFrameLowering.cpp b/lib/Target/Mips/MipsFrameLowering.cpp
index eb9d49f..8ba35fa 100644
--- a/lib/Target/Mips/MipsFrameLowering.cpp
+++ b/lib/Target/Mips/MipsFrameLowering.cpp
@@ -110,7 +110,7 @@ uint64_t MipsFrameLowering::estimateStackSize(const MachineFunction &MF) const {
Offset = std::max(Offset, -MFI->getObjectOffset(I));
// Conservatively assume all callee-saved registers will be saved.
- for (const uint16_t *R = TRI.getCalleeSavedRegs(&MF); *R; ++R) {
+ for (const MCPhysReg *R = TRI.getCalleeSavedRegs(&MF); *R; ++R) {
unsigned Size = TRI.getMinimalPhysRegClass(*R)->getSize();
Offset = RoundUpToAlignment(Offset + Size, Size);
}
diff --git a/lib/Target/Mips/MipsFrameLowering.h b/lib/Target/Mips/MipsFrameLowering.h
index 6a5f79d..e10a3a5 100644
--- a/lib/Target/Mips/MipsFrameLowering.h
+++ b/lib/Target/Mips/MipsFrameLowering.h
@@ -32,7 +32,7 @@ public:
static const MipsFrameLowering *create(MipsTargetMachine &TM,
const MipsSubtarget &ST);
- bool hasFP(const MachineFunction &MF) const;
+ bool hasFP(const MachineFunction &MF) const override;
protected:
uint64_t estimateStackSize(const MachineFunction &MF) const;
diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp
index 941aeac..90cff63 100644
--- a/lib/Target/Mips/MipsISelDAGToDAG.cpp
+++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp
@@ -11,7 +11,6 @@
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "mips-isel"
#include "MipsISelDAGToDAG.h"
#include "MCTargetDesc/MipsBaseInfo.h"
#include "Mips.h"
@@ -36,6 +35,8 @@
#include "llvm/Target/TargetMachine.h"
using namespace llvm;
+#define DEBUG_TYPE "mips-isel"
+
//===----------------------------------------------------------------------===//
// Instruction Selector Implementation
//===----------------------------------------------------------------------===//
@@ -182,7 +183,7 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) {
if (Node->isMachineOpcode()) {
DEBUG(errs() << "== "; Node->dump(CurDAG); errs() << "\n");
Node->setNodeId(-1);
- return NULL;
+ return nullptr;
}
// See if subclasses can handle this node.
@@ -201,8 +202,9 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) {
#ifndef NDEBUG
case ISD::LOAD:
case ISD::STORE:
- assert(cast<MemSDNode>(Node)->getMemoryVT().getSizeInBits() / 8 <=
- cast<MemSDNode>(Node)->getAlignment() &&
+ assert((Subtarget.systemSupportsUnalignedAccess() ||
+ cast<MemSDNode>(Node)->getMemoryVT().getSizeInBits() / 8 <=
+ cast<MemSDNode>(Node)->getAlignment()) &&
"Unexpected unaligned loads/stores.");
break;
#endif
@@ -212,7 +214,7 @@ SDNode* MipsDAGToDAGISel::Select(SDNode *Node) {
SDNode *ResNode = SelectCode(Node);
DEBUG(errs() << "=> ");
- if (ResNode == NULL || ResNode == Node)
+ if (ResNode == nullptr || ResNode == Node)
DEBUG(Node->dump(CurDAG));
else
DEBUG(ResNode->dump(CurDAG));
diff --git a/lib/Target/Mips/MipsISelDAGToDAG.h b/lib/Target/Mips/MipsISelDAGToDAG.h
index 4546182..13becb6 100644
--- a/lib/Target/Mips/MipsISelDAGToDAG.h
+++ b/lib/Target/Mips/MipsISelDAGToDAG.h
@@ -35,11 +35,11 @@ public:
: SelectionDAGISel(TM), Subtarget(TM.getSubtarget<MipsSubtarget>()) {}
// Pass Name
- virtual const char *getPassName() const {
+ const char *getPassName() const override {
return "MIPS DAG->DAG Pattern Instruction Selection";
}
- virtual bool runOnMachineFunction(MachineFunction &MF);
+ bool runOnMachineFunction(MachineFunction &MF) override;
protected:
SDNode *getGlobalBaseReg();
@@ -110,7 +110,7 @@ private:
/// starting at bit zero.
virtual bool selectVSplatMaskR(SDValue N, SDValue &Imm) const;
- virtual SDNode *Select(SDNode *N);
+ SDNode *Select(SDNode *N) override;
virtual std::pair<bool, SDNode*> selectNode(SDNode *Node) = 0;
@@ -121,9 +121,9 @@ private:
virtual void processFunctionAfterISel(MachineFunction &MF) = 0;
- virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op,
- char ConstraintCode,
- std::vector<SDValue> &OutOps);
+ bool SelectInlineAsmMemoryOperand(const SDValue &Op,
+ char ConstraintCode,
+ std::vector<SDValue> &OutOps) override;
};
/// createMipsISelDag - This pass converts a legalized DAG into a
diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp
index abf36da..bfe5ea1 100644
--- a/lib/Target/Mips/MipsISelLowering.cpp
+++ b/lib/Target/Mips/MipsISelLowering.cpp
@@ -11,7 +11,6 @@
// selection DAG.
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "mips-lower"
#include "MipsISelLowering.h"
#include "InstPrinter/MipsInstPrinter.h"
#include "MCTargetDesc/MipsBaseInfo.h"
@@ -39,6 +38,8 @@
using namespace llvm;
+#define DEBUG_TYPE "mips-lower"
+
STATISTIC(NumTailCalls, "Number of tail calls");
static cl::opt<bool>
@@ -50,16 +51,21 @@ NoZeroDivCheck("mno-check-zero-division", cl::Hidden,
cl::desc("MIPS: Don't trap on integer division by zero."),
cl::init(false));
-static const uint16_t O32IntRegs[4] = {
+cl::opt<bool>
+EnableMipsFastISel("mips-fast-isel", cl::Hidden,
+ cl::desc("Allow mips-fast-isel to be used"),
+ cl::init(false));
+
+static const MCPhysReg O32IntRegs[4] = {
Mips::A0, Mips::A1, Mips::A2, Mips::A3
};
-static const uint16_t Mips64IntRegs[8] = {
+static const MCPhysReg Mips64IntRegs[8] = {
Mips::A0_64, Mips::A1_64, Mips::A2_64, Mips::A3_64,
Mips::T0_64, Mips::T1_64, Mips::T2_64, Mips::T3_64
};
-static const uint16_t Mips64DPRegs[8] = {
+static const MCPhysReg Mips64DPRegs[8] = {
Mips::D12_64, Mips::D13_64, Mips::D14_64, Mips::D15_64,
Mips::D16_64, Mips::D17_64, Mips::D18_64, Mips::D19_64
};
@@ -198,7 +204,7 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const {
case MipsISD::PCKEV: return "MipsISD::PCKEV";
case MipsISD::PCKOD: return "MipsISD::PCKOD";
case MipsISD::INSVE: return "MipsISD::INSVE";
- default: return NULL;
+ default: return nullptr;
}
}
@@ -245,12 +251,7 @@ MipsTargetLowering::MipsTargetLowering(MipsTargetMachine &TM)
setOperationAction(ISD::FCOPYSIGN, MVT::f64, Custom);
setOperationAction(ISD::FP_TO_SINT, MVT::i32, Custom);
- if (!TM.Options.NoNaNsFPMath) {
- setOperationAction(ISD::FABS, MVT::f32, Custom);
- setOperationAction(ISD::FABS, MVT::f64, Custom);
- }
-
- if (hasMips64()) {
+ if (isGP64bit()) {
setOperationAction(ISD::GlobalAddress, MVT::i64, Custom);
setOperationAction(ISD::BlockAddress, MVT::i64, Custom);
setOperationAction(ISD::GlobalTLSAddress, MVT::i64, Custom);
@@ -262,14 +263,14 @@ MipsTargetLowering::MipsTargetLowering(MipsTargetMachine &TM)
setOperationAction(ISD::FP_TO_SINT, MVT::i64, Custom);
}
- if (!hasMips64()) {
+ if (!isGP64bit()) {
setOperationAction(ISD::SHL_PARTS, MVT::i32, Custom);
setOperationAction(ISD::SRA_PARTS, MVT::i32, Custom);
setOperationAction(ISD::SRL_PARTS, MVT::i32, Custom);
}
setOperationAction(ISD::ADD, MVT::i32, Custom);
- if (hasMips64())
+ if (isGP64bit())
setOperationAction(ISD::ADD, MVT::i64, Custom);
setOperationAction(ISD::SDIV, MVT::i32, Expand);
@@ -334,11 +335,6 @@ MipsTargetLowering::MipsTargetLowering(MipsTargetMachine &TM)
setOperationAction(ISD::FREM, MVT::f32, Expand);
setOperationAction(ISD::FREM, MVT::f64, Expand);
- if (!TM.Options.NoNaNsFPMath) {
- setOperationAction(ISD::FNEG, MVT::f32, Expand);
- setOperationAction(ISD::FNEG, MVT::f64, Expand);
- }
-
setOperationAction(ISD::EH_RETURN, MVT::Other, Custom);
setOperationAction(ISD::VAARG, MVT::Other, Expand);
@@ -356,22 +352,23 @@ MipsTargetLowering::MipsTargetLowering(MipsTargetMachine &TM)
setInsertFencesForAtomic(true);
- if (!Subtarget->hasSEInReg()) {
+ if (!Subtarget->hasMips32r2()) {
setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i8, Expand);
setOperationAction(ISD::SIGN_EXTEND_INREG, MVT::i16, Expand);
}
- if (!Subtarget->hasBitCount()) {
+ // MIPS16 lacks MIPS32's clz and clo instructions.
+ if (!Subtarget->hasMips32() || Subtarget->inMips16Mode())
setOperationAction(ISD::CTLZ, MVT::i32, Expand);
+ if (!Subtarget->hasMips64())
setOperationAction(ISD::CTLZ, MVT::i64, Expand);
- }
- if (!Subtarget->hasSwap()) {
+ if (!Subtarget->hasMips32r2())
setOperationAction(ISD::BSWAP, MVT::i32, Expand);
+ if (!Subtarget->hasMips64r2())
setOperationAction(ISD::BSWAP, MVT::i64, Expand);
- }
- if (hasMips64()) {
+ if (isGP64bit()) {
setLoadExtAction(ISD::SEXTLOAD, MVT::i32, Custom);
setLoadExtAction(ISD::ZEXTLOAD, MVT::i32, Custom);
setLoadExtAction(ISD::EXTLOAD, MVT::i32, Custom);
@@ -387,7 +384,7 @@ MipsTargetLowering::MipsTargetLowering(MipsTargetMachine &TM)
setTargetDAGCombine(ISD::OR);
setTargetDAGCombine(ISD::ADD);
- setMinFunctionAlignment(hasMips64() ? 3 : 2);
+ setMinFunctionAlignment(isGP64bit() ? 3 : 2);
setStackPointerRegisterToSaveRestore(isN64() ? Mips::SP_64 : Mips::SP);
@@ -406,6 +403,15 @@ const MipsTargetLowering *MipsTargetLowering::create(MipsTargetMachine &TM) {
return llvm::createMipsSETargetLowering(TM);
}
+// Create a fast isel object.
+FastISel *
+MipsTargetLowering::createFastISel(FunctionLoweringInfo &funcInfo,
+ const TargetLibraryInfo *libInfo) const {
+ if (!EnableMipsFastISel)
+ return TargetLowering::createFastISel(funcInfo, libInfo);
+ return Mips::createFastISel(funcInfo, libInfo);
+}
+
EVT MipsTargetLowering::getSetCCResultType(LLVMContext &, EVT VT) const {
if (!VT.isVector())
return MVT::i32;
@@ -779,7 +785,6 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const
case ISD::SETCC: return lowerSETCC(Op, DAG);
case ISD::VASTART: return lowerVASTART(Op, DAG);
case ISD::FCOPYSIGN: return lowerFCOPYSIGN(Op, DAG);
- case ISD::FABS: return lowerFABS(Op, DAG);
case ISD::FRAMEADDR: return lowerFRAMEADDR(Op, DAG);
case ISD::RETURNADDR: return lowerRETURNADDR(Op, DAG);
case ISD::EH_RETURN: return lowerEH_RETURN(Op, DAG);
@@ -1506,7 +1511,7 @@ SDValue MipsTargetLowering::lowerGlobalAddress(SDValue Op,
SDValue GA = DAG.getTargetGlobalAddress(GV, DL, MVT::i32, 0,
MipsII::MO_GPREL);
SDValue GPRelNode = DAG.getNode(MipsISD::GPRel, DL,
- DAG.getVTList(MVT::i32), &GA, 1);
+ DAG.getVTList(MVT::i32), GA);
SDValue GPReg = DAG.getRegister(Mips::GP, MVT::i32);
return DAG.getNode(ISD::ADD, DL, MVT::i32, GPReg, GPRelNode);
}
@@ -1572,11 +1577,9 @@ lowerGlobalTLSAddress(SDValue Op, SelectionDAG &DAG) const
Entry.Ty = PtrTy;
Args.push_back(Entry);
- TargetLowering::CallLoweringInfo CLI(DAG.getEntryNode(), PtrTy,
- false, false, false, false, 0, CallingConv::C,
- /*IsTailCall=*/false, /*doesNotRet=*/false,
- /*isReturnValueUsed=*/true,
- TlsGetAddr, Args, DAG, DL);
+ TargetLowering::CallLoweringInfo CLI(DAG);
+ CLI.setDebugLoc(DL).setChain(DAG.getEntryNode())
+ .setCallee(CallingConv::C, PtrTy, TlsGetAddr, &Args, 0);
std::pair<SDValue, SDValue> CallResult = LowerCallTo(CLI);
SDValue Ret = CallResult.first;
@@ -1765,71 +1768,12 @@ static SDValue lowerFCOPYSIGN64(SDValue Op, SelectionDAG &DAG,
SDValue
MipsTargetLowering::lowerFCOPYSIGN(SDValue Op, SelectionDAG &DAG) const {
- if (Subtarget->hasMips64())
+ if (Subtarget->isGP64bit())
return lowerFCOPYSIGN64(Op, DAG, Subtarget->hasExtractInsert());
return lowerFCOPYSIGN32(Op, DAG, Subtarget->hasExtractInsert());
}
-static SDValue lowerFABS32(SDValue Op, SelectionDAG &DAG,
- bool HasExtractInsert) {
- SDValue Res, Const1 = DAG.getConstant(1, MVT::i32);
- SDLoc DL(Op);
-
- // If operand is of type f64, extract the upper 32-bit. Otherwise, bitcast it
- // to i32.
- SDValue X = (Op.getValueType() == MVT::f32) ?
- DAG.getNode(ISD::BITCAST, DL, MVT::i32, Op.getOperand(0)) :
- DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32, Op.getOperand(0),
- Const1);
-
- // Clear MSB.
- if (HasExtractInsert)
- Res = DAG.getNode(MipsISD::Ins, DL, MVT::i32,
- DAG.getRegister(Mips::ZERO, MVT::i32),
- DAG.getConstant(31, MVT::i32), Const1, X);
- else {
- SDValue SllX = DAG.getNode(ISD::SHL, DL, MVT::i32, X, Const1);
- Res = DAG.getNode(ISD::SRL, DL, MVT::i32, SllX, Const1);
- }
-
- if (Op.getValueType() == MVT::f32)
- return DAG.getNode(ISD::BITCAST, DL, MVT::f32, Res);
-
- SDValue LowX = DAG.getNode(MipsISD::ExtractElementF64, DL, MVT::i32,
- Op.getOperand(0), DAG.getConstant(0, MVT::i32));
- return DAG.getNode(MipsISD::BuildPairF64, DL, MVT::f64, LowX, Res);
-}
-
-static SDValue lowerFABS64(SDValue Op, SelectionDAG &DAG,
- bool HasExtractInsert) {
- SDValue Res, Const1 = DAG.getConstant(1, MVT::i32);
- SDLoc DL(Op);
-
- // Bitcast to integer node.
- SDValue X = DAG.getNode(ISD::BITCAST, DL, MVT::i64, Op.getOperand(0));
-
- // Clear MSB.
- if (HasExtractInsert)
- Res = DAG.getNode(MipsISD::Ins, DL, MVT::i64,
- DAG.getRegister(Mips::ZERO_64, MVT::i64),
- DAG.getConstant(63, MVT::i32), Const1, X);
- else {
- SDValue SllX = DAG.getNode(ISD::SHL, DL, MVT::i64, X, Const1);
- Res = DAG.getNode(ISD::SRL, DL, MVT::i64, SllX, Const1);
- }
-
- return DAG.getNode(ISD::BITCAST, DL, MVT::f64, Res);
-}
-
-SDValue
-MipsTargetLowering::lowerFABS(SDValue Op, SelectionDAG &DAG) const {
- if (Subtarget->hasMips64() && (Op.getValueType() == MVT::f64))
- return lowerFABS64(Op, DAG, Subtarget->hasExtractInsert());
-
- return lowerFABS32(Op, DAG, Subtarget->hasExtractInsert());
-}
-
SDValue MipsTargetLowering::
lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const {
// check the depth
@@ -1931,7 +1875,7 @@ SDValue MipsTargetLowering::lowerShiftLeftParts(SDValue Op,
Hi = DAG.getNode(ISD::SELECT, DL, MVT::i32, Cond, ShiftLeftLo, Or);
SDValue Ops[2] = {Lo, Hi};
- return DAG.getMergeValues(Ops, 2, DL);
+ return DAG.getMergeValues(Ops, DL);
}
SDValue MipsTargetLowering::lowerShiftRightParts(SDValue Op, SelectionDAG &DAG,
@@ -1972,7 +1916,7 @@ SDValue MipsTargetLowering::lowerShiftRightParts(SDValue Op, SelectionDAG &DAG,
ShiftRightHi);
SDValue Ops[2] = {Lo, Hi};
- return DAG.getMergeValues(Ops, 2, DL);
+ return DAG.getMergeValues(Ops, DL);
}
static SDValue createLoadLR(unsigned Opc, SelectionDAG &DAG, LoadSDNode *LD,
@@ -1988,7 +1932,7 @@ static SDValue createLoadLR(unsigned Opc, SelectionDAG &DAG, LoadSDNode *LD,
DAG.getConstant(Offset, BasePtrVT));
SDValue Ops[] = { Chain, Ptr, Src };
- return DAG.getMemIntrinsicNode(Opc, DL, VTList, Ops, 3, MemVT,
+ return DAG.getMemIntrinsicNode(Opc, DL, VTList, Ops, MemVT,
LD->getMemOperand());
}
@@ -1997,6 +1941,9 @@ SDValue MipsTargetLowering::lowerLOAD(SDValue Op, SelectionDAG &DAG) const {
LoadSDNode *LD = cast<LoadSDNode>(Op);
EVT MemVT = LD->getMemoryVT();
+ if (Subtarget->systemSupportsUnalignedAccess())
+ return Op;
+
// Return if load is aligned or if MemVT is neither i32 nor i64.
if ((LD->getAlignment() >= MemVT.getSizeInBits() / 8) ||
((MemVT != MVT::i32) && (MemVT != MVT::i64)))
@@ -2051,7 +1998,7 @@ SDValue MipsTargetLowering::lowerLOAD(SDValue Op, SelectionDAG &DAG) const {
SDValue SLL = DAG.getNode(ISD::SHL, DL, MVT::i64, LWR, Const32);
SDValue SRL = DAG.getNode(ISD::SRL, DL, MVT::i64, SLL, Const32);
SDValue Ops[] = { SRL, LWR.getValue(1) };
- return DAG.getMergeValues(Ops, 2, DL);
+ return DAG.getMergeValues(Ops, DL);
}
static SDValue createStoreLR(unsigned Opc, SelectionDAG &DAG, StoreSDNode *SD,
@@ -2066,7 +2013,7 @@ static SDValue createStoreLR(unsigned Opc, SelectionDAG &DAG, StoreSDNode *SD,
DAG.getConstant(Offset, BasePtrVT));
SDValue Ops[] = { Chain, Value, Ptr };
- return DAG.getMemIntrinsicNode(Opc, DL, VTList, Ops, 3, MemVT,
+ return DAG.getMemIntrinsicNode(Opc, DL, VTList, Ops, MemVT,
SD->getMemOperand());
}
@@ -2120,7 +2067,8 @@ SDValue MipsTargetLowering::lowerSTORE(SDValue Op, SelectionDAG &DAG) const {
EVT MemVT = SD->getMemoryVT();
// Lower unaligned integer stores.
- if ((SD->getAlignment() < MemVT.getSizeInBits() / 8) &&
+ if (!Subtarget->systemSupportsUnalignedAccess() &&
+ (SD->getAlignment() < MemVT.getSizeInBits() / 8) &&
((MemVT == MVT::i32) || (MemVT == MVT::i64)))
return lowerUnalignedIntStore(SD, DAG, Subtarget->isLittle());
@@ -2177,12 +2125,12 @@ SDValue MipsTargetLowering::lowerFP_TO_SINT(SDValue Op,
static bool CC_MipsO32(unsigned ValNo, MVT ValVT, MVT LocVT,
CCValAssign::LocInfo LocInfo, ISD::ArgFlagsTy ArgFlags,
- CCState &State, const uint16_t *F64Regs) {
+ CCState &State, const MCPhysReg *F64Regs) {
static const unsigned IntRegsSize = 4, FloatRegsSize = 2;
- static const uint16_t IntRegs[] = { Mips::A0, Mips::A1, Mips::A2, Mips::A3 };
- static const uint16_t F32Regs[] = { Mips::F12, Mips::F14 };
+ static const MCPhysReg IntRegs[] = { Mips::A0, Mips::A1, Mips::A2, Mips::A3 };
+ static const MCPhysReg F32Regs[] = { Mips::F12, Mips::F14 };
// Do not process byval args here.
if (ArgFlags.isByVal())
@@ -2254,7 +2202,7 @@ static bool CC_MipsO32(unsigned ValNo, MVT ValVT, MVT LocVT,
static bool CC_MipsO32_FP32(unsigned ValNo, MVT ValVT,
MVT LocVT, CCValAssign::LocInfo LocInfo,
ISD::ArgFlagsTy ArgFlags, CCState &State) {
- static const uint16_t F64Regs[] = { Mips::D6, Mips::D7 };
+ static const MCPhysReg F64Regs[] = { Mips::D6, Mips::D7 };
return CC_MipsO32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State, F64Regs);
}
@@ -2262,7 +2210,7 @@ static bool CC_MipsO32_FP32(unsigned ValNo, MVT ValVT,
static bool CC_MipsO32_FP64(unsigned ValNo, MVT ValVT,
MVT LocVT, CCValAssign::LocInfo LocInfo,
ISD::ArgFlagsTy ArgFlags, CCState &State) {
- static const uint16_t F64Regs[] = { Mips::D12_64, Mips::D14_64 };
+ static const MCPhysReg F64Regs[] = { Mips::D12_64, Mips::D14_64 };
return CC_MipsO32(ValNo, ValVT, LocVT, LocInfo, ArgFlags, State, F64Regs);
}
@@ -2383,7 +2331,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
MipsCCInfo.analyzeCallOperands(Outs, IsVarArg,
Subtarget->mipsSEUsesSoftFloat(),
- Callee.getNode(), CLI.Args);
+ Callee.getNode(), CLI.getArgs());
// Get a count of how many bytes are to be pushed on the stack.
unsigned NextStackOffset = CCInfo.getNextStackOffset();
@@ -2394,6 +2342,10 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
isEligibleForTailCallOptimization(MipsCCInfo, NextStackOffset,
*MF.getInfo<MipsFunctionInfo>());
+ if (!IsTailCall && CLI.CS && CLI.CS->isMustTailCall())
+ report_fatal_error("failed to perform tail call elimination on a call "
+ "site marked musttail");
+
if (IsTailCall)
++NumTailCalls;
@@ -2489,8 +2441,7 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
// Transform all store nodes into one single node because all store
// nodes are independent of each other.
if (!MemOpChains.empty())
- Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other,
- &MemOpChains[0], MemOpChains.size());
+ Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, MemOpChains);
// If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
// direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
@@ -2544,9 +2495,9 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
CLI, Callee, Chain);
if (IsTailCall)
- return DAG.getNode(MipsISD::TailCall, DL, MVT::Other, &Ops[0], Ops.size());
+ return DAG.getNode(MipsISD::TailCall, DL, MVT::Other, Ops);
- Chain = DAG.getNode(MipsISD::JmpLink, DL, NodeTys, &Ops[0], Ops.size());
+ Chain = DAG.getNode(MipsISD::JmpLink, DL, NodeTys, Ops);
SDValue InFlag = Chain.getValue(1);
// Create the CALLSEQ_END node.
@@ -2713,18 +2664,21 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain,
}
}
- // The mips ABIs for returning structs by value requires that we copy
- // the sret argument into $v0 for the return. Save the argument into
- // a virtual register so that we can access it from the return points.
- if (DAG.getMachineFunction().getFunction()->hasStructRetAttr()) {
- unsigned Reg = MipsFI->getSRetReturnReg();
- if (!Reg) {
- Reg = MF.getRegInfo().createVirtualRegister(
- getRegClassFor(isN64() ? MVT::i64 : MVT::i32));
- MipsFI->setSRetReturnReg(Reg);
+ for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
+ // The mips ABIs for returning structs by value requires that we copy
+ // the sret argument into $v0 for the return. Save the argument into
+ // a virtual register so that we can access it from the return points.
+ if (Ins[i].Flags.isSRet()) {
+ unsigned Reg = MipsFI->getSRetReturnReg();
+ if (!Reg) {
+ Reg = MF.getRegInfo().createVirtualRegister(
+ getRegClassFor(isN64() ? MVT::i64 : MVT::i32));
+ MipsFI->setSRetReturnReg(Reg);
+ }
+ SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), DL, Reg, InVals[i]);
+ Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Copy, Chain);
+ break;
}
- SDValue Copy = DAG.getCopyToReg(DAG.getEntryNode(), DL, Reg, InVals[0]);
- Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Copy, Chain);
}
if (IsVarArg)
@@ -2734,8 +2688,7 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain,
// the size of Ins and InVals. This only happens when on varg functions
if (!OutChains.empty()) {
OutChains.push_back(Chain);
- Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other,
- &OutChains[0], OutChains.size());
+ Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains);
}
return Chain;
@@ -2820,7 +2773,7 @@ MipsTargetLowering::LowerReturn(SDValue Chain,
RetOps.push_back(Flag);
// Return on Mips is always a "jr $ra"
- return DAG.getNode(MipsISD::Ret, DL, MVT::Other, &RetOps[0], RetOps.size());
+ return DAG.getNode(MipsISD::Ret, DL, MVT::Other, RetOps);
}
//===----------------------------------------------------------------------===//
@@ -2870,7 +2823,7 @@ MipsTargetLowering::getSingleConstraintMatchWeight(
Value *CallOperandVal = info.CallOperandVal;
// If we don't have a value, we can't do a match,
// but allow it at the lowest weight.
- if (CallOperandVal == NULL)
+ if (!CallOperandVal)
return CW_Default;
Type *type = CallOperandVal->getType();
// Look at the constraint type.
@@ -2948,12 +2901,12 @@ parseRegForInlineAsmConstraint(const StringRef &C, MVT VT) const {
std::pair<bool, bool> R = parsePhysicalReg(C, Prefix, Reg);
if (!R.first)
- return std::make_pair((unsigned)0, (const TargetRegisterClass*)0);
+ return std::make_pair(0U, nullptr);
if ((Prefix == "hi" || Prefix == "lo")) { // Parse hi/lo.
// No numeric characters follow "hi" or "lo".
if (R.second)
- return std::make_pair((unsigned)0, (const TargetRegisterClass*)0);
+ return std::make_pair(0U, nullptr);
RC = TRI->getRegClass(Prefix == "hi" ?
Mips::HI32RegClassID : Mips::LO32RegClassID);
@@ -2963,7 +2916,7 @@ parseRegForInlineAsmConstraint(const StringRef &C, MVT VT) const {
// No numeric characters follow the name.
if (R.second)
- return std::make_pair((unsigned)0, (const TargetRegisterClass *)0);
+ return std::make_pair(0U, nullptr);
Reg = StringSwitch<unsigned long long>(Prefix)
.Case("$msair", Mips::MSAIR)
@@ -2977,14 +2930,14 @@ parseRegForInlineAsmConstraint(const StringRef &C, MVT VT) const {
.Default(0);
if (!Reg)
- return std::make_pair((unsigned)0, (const TargetRegisterClass *)0);
+ return std::make_pair(0U, nullptr);
RC = TRI->getRegClass(Mips::MSACtrlRegClassID);
return std::make_pair(Reg, RC);
}
if (!R.second)
- return std::make_pair((unsigned)0, (const TargetRegisterClass*)0);
+ return std::make_pair(0U, nullptr);
if (Prefix == "$f") { // Parse $f0-$f31.
// If the size of FP registers is 64-bit or Reg is an even number, select
@@ -3032,7 +2985,7 @@ getRegForInlineAsmConstraint(const std::string &Constraint, MVT VT) const
if (VT == MVT::i64 && isGP64bit())
return std::make_pair(0U, &Mips::GPR64RegClass);
// This will generate an error message
- return std::make_pair(0u, static_cast<const TargetRegisterClass*>(0));
+ return std::make_pair(0U, nullptr);
case 'f': // FPU or MSA register
if (VT == MVT::v16i8)
return std::make_pair(0U, &Mips::MSA128BRegClass);
@@ -3062,7 +3015,7 @@ getRegForInlineAsmConstraint(const std::string &Constraint, MVT VT) const
case 'x': // register suitable for indirect jump
// Fixme: Not triggering the use of both hi and low
// This will generate an error message
- return std::make_pair(0u, static_cast<const TargetRegisterClass*>(0));
+ return std::make_pair(0U, nullptr);
}
}
@@ -3081,7 +3034,7 @@ void MipsTargetLowering::LowerAsmOperandForConstraint(SDValue Op,
std::string &Constraint,
std::vector<SDValue>&Ops,
SelectionDAG &DAG) const {
- SDValue Result(0, 0);
+ SDValue Result;
// Only support length 1 constraints for now.
if (Constraint.length() > 1) return;
@@ -3265,7 +3218,7 @@ static bool originalTypeIsF128(const Type *Ty, const SDNode *CallNode) {
MipsTargetLowering::MipsCC::SpecialCallingConvType
MipsTargetLowering::getSpecialCallingConv(SDValue Callee) const {
MipsCC::SpecialCallingConvType SpecialCallingConv =
- MipsCC::NoSpecialCallingConv;;
+ MipsCC::NoSpecialCallingConv;
if (Subtarget->inMips16HardFloat()) {
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) {
llvm::StringRef Sym = G->getGlobal()->getName();
@@ -3321,7 +3274,7 @@ analyzeCallOperands(const SmallVectorImpl<ISD::OutputArg> &Args,
dbgs() << "Call operand #" << I << " has unhandled type "
<< EVT(ArgVT).getEVTString();
#endif
- llvm_unreachable(0);
+ llvm_unreachable(nullptr);
}
}
}
@@ -3344,7 +3297,7 @@ analyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Args,
continue;
}
- MVT RegVT = getRegVT(ArgVT, FuncArg->getType(), 0, IsSoftFloat);
+ MVT RegVT = getRegVT(ArgVT, FuncArg->getType(), nullptr, IsSoftFloat);
if (!FixedFn(I, ArgVT, RegVT, CCValAssign::Full, ArgFlags, CCInfo))
continue;
@@ -3353,7 +3306,7 @@ analyzeFormalArguments(const SmallVectorImpl<ISD::InputArg> &Args,
dbgs() << "Formal Arg #" << I << " has unhandled type "
<< EVT(ArgVT).getEVTString();
#endif
- llvm_unreachable(0);
+ llvm_unreachable(nullptr);
}
}
@@ -3378,7 +3331,7 @@ analyzeReturn(const SmallVectorImpl<Ty> &RetVals, bool IsSoftFloat,
dbgs() << "Call result #" << I << " has unhandled type "
<< EVT(VT).getEVTString() << '\n';
#endif
- llvm_unreachable(0);
+ llvm_unreachable(nullptr);
}
}
}
@@ -3392,7 +3345,7 @@ analyzeCallResult(const SmallVectorImpl<ISD::InputArg> &Ins, bool IsSoftFloat,
void MipsTargetLowering::MipsCC::
analyzeReturn(const SmallVectorImpl<ISD::OutputArg> &Outs, bool IsSoftFloat,
const Type *RetTy) const {
- analyzeReturn(Outs, IsSoftFloat, 0, RetTy);
+ analyzeReturn(Outs, IsSoftFloat, nullptr, RetTy);
}
void MipsTargetLowering::MipsCC::handleByValArg(unsigned ValNo, MVT ValVT,
@@ -3426,7 +3379,7 @@ unsigned MipsTargetLowering::MipsCC::reservedArgArea() const {
return (IsO32 && (CallConv != CallingConv::Fast)) ? 16 : 0;
}
-const uint16_t *MipsTargetLowering::MipsCC::intArgRegs() const {
+const MCPhysReg *MipsTargetLowering::MipsCC::intArgRegs() const {
return IsO32 ? O32IntRegs : Mips64IntRegs;
}
@@ -3443,7 +3396,7 @@ llvm::CCAssignFn *MipsTargetLowering::MipsCC::varArgFn() const {
return IsO32 ? (IsFP64 ? CC_MipsO32_FP64 : CC_MipsO32_FP32) : CC_MipsN_VarArg;
}
-const uint16_t *MipsTargetLowering::MipsCC::shadowRegs() const {
+const MCPhysReg *MipsTargetLowering::MipsCC::shadowRegs() const {
return IsO32 ? O32IntRegs : Mips64DPRegs;
}
@@ -3451,7 +3404,7 @@ void MipsTargetLowering::MipsCC::allocateRegs(ByValArgInfo &ByVal,
unsigned ByValSize,
unsigned Align) {
unsigned RegSize = regSize(), NumIntArgRegs = numIntArgRegs();
- const uint16_t *IntArgRegs = intArgRegs(), *ShadowRegs = shadowRegs();
+ const MCPhysReg *IntArgRegs = intArgRegs(), *ShadowRegs = shadowRegs();
assert(!(ByValSize % RegSize) && !(Align % RegSize) &&
"Byval argument's size and alignment should be a multiple of"
"RegSize.");
@@ -3536,21 +3489,22 @@ passByValArg(SDValue Chain, SDLoc DL,
MachineFrameInfo *MFI, SelectionDAG &DAG, SDValue Arg,
const MipsCC &CC, const ByValArgInfo &ByVal,
const ISD::ArgFlagsTy &Flags, bool isLittle) const {
- unsigned ByValSize = Flags.getByValSize();
- unsigned Offset = 0; // Offset in # of bytes from the beginning of struct.
- unsigned RegSize = CC.regSize();
- unsigned Alignment = std::min(Flags.getByValAlign(), RegSize);
- EVT PtrTy = getPointerTy(), RegTy = MVT::getIntegerVT(RegSize * 8);
+ unsigned ByValSizeInBytes = Flags.getByValSize();
+ unsigned OffsetInBytes = 0; // From beginning of struct
+ unsigned RegSizeInBytes = CC.regSize();
+ unsigned Alignment = std::min(Flags.getByValAlign(), RegSizeInBytes);
+ EVT PtrTy = getPointerTy(), RegTy = MVT::getIntegerVT(RegSizeInBytes * 8);
if (ByVal.NumRegs) {
- const uint16_t *ArgRegs = CC.intArgRegs();
- bool LeftoverBytes = (ByVal.NumRegs * RegSize > ByValSize);
+ const MCPhysReg *ArgRegs = CC.intArgRegs();
+ bool LeftoverBytes = (ByVal.NumRegs * RegSizeInBytes > ByValSizeInBytes);
unsigned I = 0;
// Copy words to registers.
- for (; I < ByVal.NumRegs - LeftoverBytes; ++I, Offset += RegSize) {
+ for (; I < ByVal.NumRegs - LeftoverBytes;
+ ++I, OffsetInBytes += RegSizeInBytes) {
SDValue LoadPtr = DAG.getNode(ISD::ADD, DL, PtrTy, Arg,
- DAG.getConstant(Offset, PtrTy));
+ DAG.getConstant(OffsetInBytes, PtrTy));
SDValue LoadVal = DAG.getLoad(RegTy, DL, Chain, LoadPtr,
MachinePointerInfo(), false, false, false,
Alignment);
@@ -3560,38 +3514,38 @@ passByValArg(SDValue Chain, SDLoc DL,
}
// Return if the struct has been fully copied.
- if (ByValSize == Offset)
+ if (ByValSizeInBytes == OffsetInBytes)
return;
// Copy the remainder of the byval argument with sub-word loads and shifts.
if (LeftoverBytes) {
- assert((ByValSize > Offset) && (ByValSize < Offset + RegSize) &&
- "Size of the remainder should be smaller than RegSize.");
+ assert((ByValSizeInBytes > OffsetInBytes) &&
+ (ByValSizeInBytes < OffsetInBytes + RegSizeInBytes) &&
+ "Size of the remainder should be smaller than RegSizeInBytes.");
SDValue Val;
- for (unsigned LoadSize = RegSize / 2, TotalSizeLoaded = 0;
- Offset < ByValSize; LoadSize /= 2) {
- unsigned RemSize = ByValSize - Offset;
+ for (unsigned LoadSizeInBytes = RegSizeInBytes / 2, TotalBytesLoaded = 0;
+ OffsetInBytes < ByValSizeInBytes; LoadSizeInBytes /= 2) {
+ unsigned RemainingSizeInBytes = ByValSizeInBytes - OffsetInBytes;
- if (RemSize < LoadSize)
+ if (RemainingSizeInBytes < LoadSizeInBytes)
continue;
// Load subword.
SDValue LoadPtr = DAG.getNode(ISD::ADD, DL, PtrTy, Arg,
- DAG.getConstant(Offset, PtrTy));
- SDValue LoadVal =
- DAG.getExtLoad(ISD::ZEXTLOAD, DL, RegTy, Chain, LoadPtr,
- MachinePointerInfo(), MVT::getIntegerVT(LoadSize * 8),
- false, false, Alignment);
+ DAG.getConstant(OffsetInBytes, PtrTy));
+ SDValue LoadVal = DAG.getExtLoad(
+ ISD::ZEXTLOAD, DL, RegTy, Chain, LoadPtr, MachinePointerInfo(),
+ MVT::getIntegerVT(LoadSizeInBytes * 8), false, false, Alignment);
MemOpChains.push_back(LoadVal.getValue(1));
// Shift the loaded value.
unsigned Shamt;
if (isLittle)
- Shamt = TotalSizeLoaded;
+ Shamt = TotalBytesLoaded * 8;
else
- Shamt = (RegSize - (TotalSizeLoaded + LoadSize)) * 8;
+ Shamt = (RegSizeInBytes - (TotalBytesLoaded + LoadSizeInBytes)) * 8;
SDValue Shift = DAG.getNode(ISD::SHL, DL, RegTy, LoadVal,
DAG.getConstant(Shamt, MVT::i32));
@@ -3601,9 +3555,9 @@ passByValArg(SDValue Chain, SDLoc DL,
else
Val = Shift;
- Offset += LoadSize;
- TotalSizeLoaded += LoadSize;
- Alignment = std::min(Alignment, LoadSize);
+ OffsetInBytes += LoadSizeInBytes;
+ TotalBytesLoaded += LoadSizeInBytes;
+ Alignment = std::min(Alignment, LoadSizeInBytes);
}
unsigned ArgReg = ArgRegs[ByVal.FirstIdx + I];
@@ -3613,14 +3567,14 @@ passByValArg(SDValue Chain, SDLoc DL,
}
// Copy remainder of byval arg to it with memcpy.
- unsigned MemCpySize = ByValSize - Offset;
+ unsigned MemCpySize = ByValSizeInBytes - OffsetInBytes;
SDValue Src = DAG.getNode(ISD::ADD, DL, PtrTy, Arg,
- DAG.getConstant(Offset, PtrTy));
+ DAG.getConstant(OffsetInBytes, PtrTy));
SDValue Dst = DAG.getNode(ISD::ADD, DL, PtrTy, StackPtr,
DAG.getIntPtrConstant(ByVal.Address));
Chain = DAG.getMemcpy(Chain, DL, Dst, Src, DAG.getConstant(MemCpySize, PtrTy),
Alignment, /*isVolatile=*/false, /*AlwaysInline=*/false,
- MachinePointerInfo(0), MachinePointerInfo(0));
+ MachinePointerInfo(), MachinePointerInfo());
MemOpChains.push_back(Chain);
}
@@ -3628,7 +3582,7 @@ void MipsTargetLowering::writeVarArgRegs(std::vector<SDValue> &OutChains,
const MipsCC &CC, SDValue Chain,
SDLoc DL, SelectionDAG &DAG) const {
unsigned NumRegs = CC.numIntArgRegs();
- const uint16_t *ArgRegs = CC.intArgRegs();
+ const MCPhysReg *ArgRegs = CC.intArgRegs();
const CCState &CCInfo = CC.getCCInfo();
unsigned Idx = CCInfo.getFirstUnallocated(ArgRegs, NumRegs);
unsigned RegSize = CC.regSize();
@@ -3662,7 +3616,7 @@ void MipsTargetLowering::writeVarArgRegs(std::vector<SDValue> &OutChains,
SDValue PtrOff = DAG.getFrameIndex(FI, getPointerTy());
SDValue Store = DAG.getStore(Chain, DL, ArgValue, PtrOff,
MachinePointerInfo(), false, false, 0);
- cast<StoreSDNode>(Store.getNode())->getMemOperand()->setValue(0);
+ cast<StoreSDNode>(Store.getNode())->getMemOperand()->setValue((Value*)nullptr);
OutChains.push_back(Store);
}
}
diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h
index 35dd396..4ac33bf 100644
--- a/lib/Target/Mips/MipsISelLowering.h
+++ b/lib/Target/Mips/MipsISelLowering.h
@@ -218,32 +218,38 @@ namespace llvm {
static const MipsTargetLowering *create(MipsTargetMachine &TM);
- virtual MVT getScalarShiftAmountTy(EVT LHSTy) const { return MVT::i32; }
+ /// createFastISel - This method returns a target specific FastISel object,
+ /// or null if the target does not support "fast" ISel.
+ FastISel *createFastISel(FunctionLoweringInfo &funcInfo,
+ const TargetLibraryInfo *libInfo) const override;
- virtual void LowerOperationWrapper(SDNode *N,
- SmallVectorImpl<SDValue> &Results,
- SelectionDAG &DAG) const;
+ MVT getScalarShiftAmountTy(EVT LHSTy) const override { return MVT::i32; }
+
+ void LowerOperationWrapper(SDNode *N,
+ SmallVectorImpl<SDValue> &Results,
+ SelectionDAG &DAG) const override;
/// LowerOperation - Provide custom lowering hooks for some operations.
- virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;
/// ReplaceNodeResults - Replace the results of node with an illegal result
/// type with new values built out of custom code.
///
- virtual void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue>&Results,
- SelectionDAG &DAG) const;
+ void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue>&Results,
+ SelectionDAG &DAG) const override;
/// getTargetNodeName - This method returns the name of a target specific
// DAG node.
- virtual const char *getTargetNodeName(unsigned Opcode) const;
+ const char *getTargetNodeName(unsigned Opcode) const override;
/// getSetCCResultType - get the ISD::SETCC result ValueType
- EVT getSetCCResultType(LLVMContext &Context, EVT VT) const;
+ EVT getSetCCResultType(LLVMContext &Context, EVT VT) const override;
- virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
+ SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override;
- virtual MachineBasicBlock *
- EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB) const;
+ MachineBasicBlock *
+ EmitInstrWithCustomInserter(MachineInstr *MI,
+ MachineBasicBlock *MBB) const override;
struct LTStr {
bool operator()(const char *S1, const char *S2) const {
@@ -382,7 +388,7 @@ namespace llvm {
unsigned reservedArgArea() const;
/// Return pointer to array of integer argument registers.
- const uint16_t *intArgRegs() const;
+ const MCPhysReg *intArgRegs() const;
typedef SmallVectorImpl<ByValArgInfo>::const_iterator byval_iterator;
byval_iterator byval_begin() const { return ByValArgs.begin(); }
@@ -403,7 +409,7 @@ namespace llvm {
/// Return the function that analyzes variable argument list functions.
llvm::CCAssignFn *varArgFn() const;
- const uint16_t *shadowRegs() const;
+ const MCPhysReg *shadowRegs() const;
void allocateRegs(ByValArgInfo &ByVal, unsigned ByValSize,
unsigned Align);
@@ -523,41 +529,39 @@ namespace llvm {
void writeVarArgRegs(std::vector<SDValue> &OutChains, const MipsCC &CC,
SDValue Chain, SDLoc DL, SelectionDAG &DAG) const;
- virtual SDValue
+ SDValue
LowerFormalArguments(SDValue Chain,
CallingConv::ID CallConv, bool isVarArg,
const SmallVectorImpl<ISD::InputArg> &Ins,
SDLoc dl, SelectionDAG &DAG,
- SmallVectorImpl<SDValue> &InVals) const;
+ SmallVectorImpl<SDValue> &InVals) const override;
SDValue passArgOnStack(SDValue StackPtr, unsigned Offset, SDValue Chain,
SDValue Arg, SDLoc DL, bool IsTailCall,
SelectionDAG &DAG) const;
- virtual SDValue
- LowerCall(TargetLowering::CallLoweringInfo &CLI,
- SmallVectorImpl<SDValue> &InVals) const;
+ SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI,
+ SmallVectorImpl<SDValue> &InVals) const override;
- virtual bool
- CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
- bool isVarArg,
- const SmallVectorImpl<ISD::OutputArg> &Outs,
- LLVMContext &Context) const;
-
- virtual SDValue
- LowerReturn(SDValue Chain,
- CallingConv::ID CallConv, bool isVarArg,
- const SmallVectorImpl<ISD::OutputArg> &Outs,
- const SmallVectorImpl<SDValue> &OutVals,
- SDLoc dl, SelectionDAG &DAG) const;
+ bool CanLowerReturn(CallingConv::ID CallConv, MachineFunction &MF,
+ bool isVarArg,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ LLVMContext &Context) const override;
+
+ SDValue LowerReturn(SDValue Chain,
+ CallingConv::ID CallConv, bool isVarArg,
+ const SmallVectorImpl<ISD::OutputArg> &Outs,
+ const SmallVectorImpl<SDValue> &OutVals,
+ SDLoc dl, SelectionDAG &DAG) const override;
// Inline asm support
- ConstraintType getConstraintType(const std::string &Constraint) const;
+ ConstraintType
+ getConstraintType(const std::string &Constraint) const override;
/// Examine constraint string and operand type and determine a weight value.
/// The operand object must already have been set up with the operand type.
ConstraintWeight getSingleConstraintMatchWeight(
- AsmOperandInfo &info, const char *constraint) const;
+ AsmOperandInfo &info, const char *constraint) const override;
/// This function parses registers that appear in inline-asm constraints.
/// It returns pair (0, 0) on failure.
@@ -566,33 +570,33 @@ namespace llvm {
std::pair<unsigned, const TargetRegisterClass*>
getRegForInlineAsmConstraint(const std::string &Constraint,
- MVT VT) const;
+ MVT VT) const override;
/// LowerAsmOperandForConstraint - Lower the specified operand into the Ops
/// vector. If it is invalid, don't add anything to Ops. If hasMemory is
/// true it means one of the asm constraint of the inline asm instruction
/// being processed is 'm'.
- virtual void LowerAsmOperandForConstraint(SDValue Op,
- std::string &Constraint,
- std::vector<SDValue> &Ops,
- SelectionDAG &DAG) const;
+ void LowerAsmOperandForConstraint(SDValue Op,
+ std::string &Constraint,
+ std::vector<SDValue> &Ops,
+ SelectionDAG &DAG) const override;
- virtual bool isLegalAddressingMode(const AddrMode &AM, Type *Ty) const;
+ bool isLegalAddressingMode(const AddrMode &AM, Type *Ty) const override;
- virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const;
+ bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override;
- virtual EVT getOptimalMemOpType(uint64_t Size, unsigned DstAlign,
- unsigned SrcAlign,
- bool IsMemset, bool ZeroMemset,
- bool MemcpyStrSrc,
- MachineFunction &MF) const;
+ EVT getOptimalMemOpType(uint64_t Size, unsigned DstAlign,
+ unsigned SrcAlign,
+ bool IsMemset, bool ZeroMemset,
+ bool MemcpyStrSrc,
+ MachineFunction &MF) const override;
/// isFPImmLegal - Returns true if the target can instruction select the
/// specified FP immediate natively. If false, the legalizer will
/// materialize the FP immediate as a load from a constant pool.
- virtual bool isFPImmLegal(const APFloat &Imm, EVT VT) const;
+ bool isFPImmLegal(const APFloat &Imm, EVT VT) const override;
- virtual unsigned getJumpTableEncoding() const;
+ unsigned getJumpTableEncoding() const override;
MachineBasicBlock *emitAtomicBinary(MachineInstr *MI, MachineBasicBlock *BB,
unsigned Size, unsigned BinOpcode, bool Nand = false) const;
@@ -608,6 +612,11 @@ namespace llvm {
/// Create MipsTargetLowering objects.
const MipsTargetLowering *createMips16TargetLowering(MipsTargetMachine &TM);
const MipsTargetLowering *createMipsSETargetLowering(MipsTargetMachine &TM);
+
+ namespace Mips {
+ FastISel *createFastISel(FunctionLoweringInfo &funcInfo,
+ const TargetLibraryInfo *libInfo);
+ }
}
#endif // MipsISELLOWERING_H
diff --git a/lib/Target/Mips/MipsInstrFPU.td b/lib/Target/Mips/MipsInstrFPU.td
index 4b5a73e..32cda3b 100644
--- a/lib/Target/Mips/MipsInstrFPU.td
+++ b/lib/Target/Mips/MipsInstrFPU.td
@@ -66,6 +66,16 @@ def IsSingleFloat : Predicate<"Subtarget.isSingleFloat()">,
def IsNotSingleFloat : Predicate<"!Subtarget.isSingleFloat()">,
AssemblerPredicate<"!FeatureSingleFloat">;
+//===----------------------------------------------------------------------===//
+// Mips FGR size adjectives.
+// They are mutually exclusive.
+//===----------------------------------------------------------------------===//
+
+class FGR_32 { list<Predicate> FGRPredicates = [NotFP64bit]; }
+class FGR_64 { list<Predicate> FGRPredicates = [IsFP64bit]; }
+
+//===----------------------------------------------------------------------===//
+
// FP immediate patterns.
def fpimm0 : PatLeaf<(fpimm), [{
return N->isExactlyValue(+0.0);
@@ -100,10 +110,10 @@ class ADDS_FT<string opstr, RegisterOperand RC, InstrItinClass Itin, bit IsComm,
multiclass ADDS_M<string opstr, InstrItinClass Itin, bit IsComm,
SDPatternOperator OpNode = null_frag> {
def _D32 : MMRel, ADDS_FT<opstr, AFGR64Opnd, Itin, IsComm, OpNode>,
- Requires<[NotFP64bit, HasStdEnc]>;
+ AdditionalRequires<[NotFP64bit]>;
def _D64 : ADDS_FT<opstr, FGR64Opnd, Itin,
IsComm, OpNode>,
- Requires<[IsFP64bit, HasStdEnc]> {
+ AdditionalRequires<[IsFP64bit]> {
string DecoderNamespace = "Mips64";
}
}
@@ -117,18 +127,18 @@ class ABSS_FT<string opstr, RegisterOperand DstRC, RegisterOperand SrcRC,
multiclass ABSS_M<string opstr, InstrItinClass Itin,
SDPatternOperator OpNode= null_frag> {
def _D32 : MMRel, ABSS_FT<opstr, AFGR64Opnd, AFGR64Opnd, Itin, OpNode>,
- Requires<[NotFP64bit, HasStdEnc]>;
+ AdditionalRequires<[NotFP64bit]>;
def _D64 : ABSS_FT<opstr, FGR64Opnd, FGR64Opnd, Itin, OpNode>,
- Requires<[IsFP64bit, HasStdEnc]> {
+ AdditionalRequires<[IsFP64bit]> {
string DecoderNamespace = "Mips64";
}
}
multiclass ROUND_M<string opstr, InstrItinClass Itin> {
def _D32 : MMRel, ABSS_FT<opstr, FGR32Opnd, AFGR64Opnd, Itin>,
- Requires<[NotFP64bit, HasStdEnc]>;
+ AdditionalRequires<[NotFP64bit]>;
def _D64 : ABSS_FT<opstr, FGR32Opnd, FGR64Opnd, Itin>,
- Requires<[IsFP64bit, HasStdEnc]> {
+ AdditionalRequires<[IsFP64bit]> {
let DecoderNamespace = "Mips64";
}
}
@@ -241,77 +251,75 @@ multiclass C_COND_M<string TypeStr, RegisterOperand RC, bits<5> fmt,
defm S : C_COND_M<"s", FGR32Opnd, 16, II_C_CC_S>;
defm D32 : C_COND_M<"d", AFGR64Opnd, 17, II_C_CC_D>,
- Requires<[NotFP64bit, HasStdEnc]>;
+ AdditionalRequires<[NotFP64bit]>;
let DecoderNamespace = "Mips64" in
defm D64 : C_COND_M<"d", FGR64Opnd, 17, II_C_CC_D>,
- Requires<[IsFP64bit, HasStdEnc]>;
+ AdditionalRequires<[IsFP64bit]>;
//===----------------------------------------------------------------------===//
// Floating Point Instructions
//===----------------------------------------------------------------------===//
def ROUND_W_S : MMRel, ABSS_FT<"round.w.s", FGR32Opnd, FGR32Opnd, II_ROUND>,
- ABSS_FM<0xc, 16>;
+ ABSS_FM<0xc, 16>, ISA_MIPS2;
def TRUNC_W_S : MMRel, ABSS_FT<"trunc.w.s", FGR32Opnd, FGR32Opnd, II_TRUNC>,
- ABSS_FM<0xd, 16>;
+ ABSS_FM<0xd, 16>, ISA_MIPS2;
def CEIL_W_S : MMRel, ABSS_FT<"ceil.w.s", FGR32Opnd, FGR32Opnd, II_CEIL>,
- ABSS_FM<0xe, 16>;
+ ABSS_FM<0xe, 16>, ISA_MIPS2;
def FLOOR_W_S : MMRel, ABSS_FT<"floor.w.s", FGR32Opnd, FGR32Opnd, II_FLOOR>,
- ABSS_FM<0xf, 16>;
+ ABSS_FM<0xf, 16>, ISA_MIPS2;
def CVT_W_S : MMRel, ABSS_FT<"cvt.w.s", FGR32Opnd, FGR32Opnd, II_CVT>,
ABSS_FM<0x24, 16>;
-defm ROUND_W : ROUND_M<"round.w.d", II_ROUND>, ABSS_FM<0xc, 17>;
-defm TRUNC_W : ROUND_M<"trunc.w.d", II_TRUNC>, ABSS_FM<0xd, 17>;
-defm CEIL_W : ROUND_M<"ceil.w.d", II_CEIL>, ABSS_FM<0xe, 17>;
-defm FLOOR_W : ROUND_M<"floor.w.d", II_FLOOR>, ABSS_FM<0xf, 17>;
+defm ROUND_W : ROUND_M<"round.w.d", II_ROUND>, ABSS_FM<0xc, 17>, ISA_MIPS2;
+defm TRUNC_W : ROUND_M<"trunc.w.d", II_TRUNC>, ABSS_FM<0xd, 17>, ISA_MIPS2;
+defm CEIL_W : ROUND_M<"ceil.w.d", II_CEIL>, ABSS_FM<0xe, 17>, ISA_MIPS2;
+defm FLOOR_W : ROUND_M<"floor.w.d", II_FLOOR>, ABSS_FM<0xf, 17>, ISA_MIPS2;
defm CVT_W : ROUND_M<"cvt.w.d", II_CVT>, ABSS_FM<0x24, 17>;
-let Predicates = [IsFP64bit, HasStdEnc], DecoderNamespace = "Mips64" in {
+let DecoderNamespace = "Mips64" in {
def ROUND_L_S : ABSS_FT<"round.l.s", FGR64Opnd, FGR32Opnd, II_ROUND>,
- ABSS_FM<0x8, 16>;
+ ABSS_FM<0x8, 16>, FGR_64;
def ROUND_L_D64 : ABSS_FT<"round.l.d", FGR64Opnd, FGR64Opnd, II_ROUND>,
- ABSS_FM<0x8, 17>;
+ ABSS_FM<0x8, 17>, FGR_64;
def TRUNC_L_S : ABSS_FT<"trunc.l.s", FGR64Opnd, FGR32Opnd, II_TRUNC>,
- ABSS_FM<0x9, 16>;
+ ABSS_FM<0x9, 16>, FGR_64;
def TRUNC_L_D64 : ABSS_FT<"trunc.l.d", FGR64Opnd, FGR64Opnd, II_TRUNC>,
- ABSS_FM<0x9, 17>;
+ ABSS_FM<0x9, 17>, FGR_64;
def CEIL_L_S : ABSS_FT<"ceil.l.s", FGR64Opnd, FGR32Opnd, II_CEIL>,
- ABSS_FM<0xa, 16>;
+ ABSS_FM<0xa, 16>, FGR_64;
def CEIL_L_D64 : ABSS_FT<"ceil.l.d", FGR64Opnd, FGR64Opnd, II_CEIL>,
- ABSS_FM<0xa, 17>;
+ ABSS_FM<0xa, 17>, FGR_64;
def FLOOR_L_S : ABSS_FT<"floor.l.s", FGR64Opnd, FGR32Opnd, II_FLOOR>,
- ABSS_FM<0xb, 16>;
+ ABSS_FM<0xb, 16>, FGR_64;
def FLOOR_L_D64 : ABSS_FT<"floor.l.d", FGR64Opnd, FGR64Opnd, II_FLOOR>,
- ABSS_FM<0xb, 17>;
+ ABSS_FM<0xb, 17>, FGR_64;
}
def CVT_S_W : MMRel, ABSS_FT<"cvt.s.w", FGR32Opnd, FGR32Opnd, II_CVT>,
ABSS_FM<0x20, 20>;
def CVT_L_S : MMRel, ABSS_FT<"cvt.l.s", FGR64Opnd, FGR32Opnd, II_CVT>,
- ABSS_FM<0x25, 16>;
+ ABSS_FM<0x25, 16>, INSN_MIPS3_32R2;
def CVT_L_D64: MMRel, ABSS_FT<"cvt.l.d", FGR64Opnd, FGR64Opnd, II_CVT>,
- ABSS_FM<0x25, 17>;
-
-let Predicates = [NotFP64bit, HasStdEnc] in {
- def CVT_S_D32 : MMRel, ABSS_FT<"cvt.s.d", FGR32Opnd, AFGR64Opnd, II_CVT>,
- ABSS_FM<0x20, 17>;
- def CVT_D32_W : MMRel, ABSS_FT<"cvt.d.w", AFGR64Opnd, FGR32Opnd, II_CVT>,
- ABSS_FM<0x21, 20>;
- def CVT_D32_S : MMRel, ABSS_FT<"cvt.d.s", AFGR64Opnd, FGR32Opnd, II_CVT>,
- ABSS_FM<0x21, 16>;
-}
+ ABSS_FM<0x25, 17>, INSN_MIPS3_32R2;
+
+def CVT_S_D32 : MMRel, ABSS_FT<"cvt.s.d", FGR32Opnd, AFGR64Opnd, II_CVT>,
+ ABSS_FM<0x20, 17>, FGR_32;
+def CVT_D32_W : MMRel, ABSS_FT<"cvt.d.w", AFGR64Opnd, FGR32Opnd, II_CVT>,
+ ABSS_FM<0x21, 20>, FGR_32;
+def CVT_D32_S : MMRel, ABSS_FT<"cvt.d.s", AFGR64Opnd, FGR32Opnd, II_CVT>,
+ ABSS_FM<0x21, 16>, FGR_32;
-let Predicates = [IsFP64bit, HasStdEnc], DecoderNamespace = "Mips64" in {
+let DecoderNamespace = "Mips64" in {
def CVT_S_D64 : ABSS_FT<"cvt.s.d", FGR32Opnd, FGR64Opnd, II_CVT>,
- ABSS_FM<0x20, 17>;
+ ABSS_FM<0x20, 17>, FGR_64;
def CVT_S_L : ABSS_FT<"cvt.s.l", FGR32Opnd, FGR64Opnd, II_CVT>,
- ABSS_FM<0x20, 21>;
+ ABSS_FM<0x20, 21>, FGR_64;
def CVT_D64_W : ABSS_FT<"cvt.d.w", FGR64Opnd, FGR32Opnd, II_CVT>,
- ABSS_FM<0x21, 20>;
+ ABSS_FM<0x21, 20>, FGR_64;
def CVT_D64_S : ABSS_FT<"cvt.d.s", FGR64Opnd, FGR32Opnd, II_CVT>,
- ABSS_FM<0x21, 16>;
+ ABSS_FM<0x21, 16>, FGR_64;
def CVT_D64_L : ABSS_FT<"cvt.d.l", FGR64Opnd, FGR64Opnd, II_CVT>,
- ABSS_FM<0x21, 21>;
+ ABSS_FM<0x21, 21>, FGR_64;
}
let isPseudo = 1, isCodeGenOnly = 1 in {
@@ -322,18 +330,16 @@ let isPseudo = 1, isCodeGenOnly = 1 in {
def PseudoCVT_D64_L : ABSS_FT<"", FGR64Opnd, GPR64Opnd, II_CVT>;
}
-let Predicates = [NoNaNsFPMath, HasStdEnc] in {
- def FABS_S : MMRel, ABSS_FT<"abs.s", FGR32Opnd, FGR32Opnd, II_ABS, fabs>,
- ABSS_FM<0x5, 16>;
- def FNEG_S : MMRel, ABSS_FT<"neg.s", FGR32Opnd, FGR32Opnd, II_NEG, fneg>,
- ABSS_FM<0x7, 16>;
- defm FABS : ABSS_M<"abs.d", II_ABS, fabs>, ABSS_FM<0x5, 17>;
- defm FNEG : ABSS_M<"neg.d", II_NEG, fneg>, ABSS_FM<0x7, 17>;
-}
+def FABS_S : MMRel, ABSS_FT<"abs.s", FGR32Opnd, FGR32Opnd, II_ABS, fabs>,
+ ABSS_FM<0x5, 16>;
+def FNEG_S : MMRel, ABSS_FT<"neg.s", FGR32Opnd, FGR32Opnd, II_NEG, fneg>,
+ ABSS_FM<0x7, 16>;
+defm FABS : ABSS_M<"abs.d", II_ABS, fabs>, ABSS_FM<0x5, 17>;
+defm FNEG : ABSS_M<"neg.d", II_NEG, fneg>, ABSS_FM<0x7, 17>;
def FSQRT_S : MMRel, ABSS_FT<"sqrt.s", FGR32Opnd, FGR32Opnd, II_SQRT_S, fsqrt>,
- ABSS_FM<0x4, 16>;
-defm FSQRT : ABSS_M<"sqrt.d", II_SQRT_D, fsqrt>, ABSS_FM<0x4, 17>;
+ ABSS_FM<0x4, 16>, ISA_MIPS2;
+defm FSQRT : ABSS_M<"sqrt.d", II_SQRT_D, fsqrt>, ABSS_FM<0x4, 17>, ISA_MIPS2;
// The odd-numbered registers are only referenced when doing loads,
// stores, and moves between floating-point and integer registers.
@@ -348,76 +354,92 @@ def MFC1 : MMRel, MFC1_FT<"mfc1", GPR32Opnd, FGR32Opnd, II_MFC1,
def MTC1 : MMRel, MTC1_FT<"mtc1", FGR32Opnd, GPR32Opnd, II_MTC1,
bitconvert>, MFC1_FM<4>;
def MFHC1 : MMRel, MFC1_FT<"mfhc1", GPR32Opnd, FGRH32Opnd, II_MFHC1>,
- MFC1_FM<3>;
+ MFC1_FM<3>, ISA_MIPS32R2;
def MTHC1 : MMRel, MTC1_FT<"mthc1", FGRH32Opnd, GPR32Opnd, II_MTHC1>,
- MFC1_FM<7>;
+ MFC1_FM<7>, ISA_MIPS32R2;
def DMFC1 : MFC1_FT<"dmfc1", GPR64Opnd, FGR64Opnd, II_DMFC1,
- bitconvert>, MFC1_FM<1>;
+ bitconvert>, MFC1_FM<1>, ISA_MIPS3;
def DMTC1 : MTC1_FT<"dmtc1", FGR64Opnd, GPR64Opnd, II_DMTC1,
- bitconvert>, MFC1_FM<5>;
+ bitconvert>, MFC1_FM<5>, ISA_MIPS3;
def FMOV_S : MMRel, ABSS_FT<"mov.s", FGR32Opnd, FGR32Opnd, II_MOV_S>,
ABSS_FM<0x6, 16>;
def FMOV_D32 : MMRel, ABSS_FT<"mov.d", AFGR64Opnd, AFGR64Opnd, II_MOV_D>,
- ABSS_FM<0x6, 17>, Requires<[NotFP64bit, HasStdEnc]>;
+ ABSS_FM<0x6, 17>, AdditionalRequires<[NotFP64bit]>;
def FMOV_D64 : ABSS_FT<"mov.d", FGR64Opnd, FGR64Opnd, II_MOV_D>,
- ABSS_FM<0x6, 17>, Requires<[IsFP64bit, HasStdEnc]> {
+ ABSS_FM<0x6, 17>, AdditionalRequires<[IsFP64bit]> {
let DecoderNamespace = "Mips64";
}
/// Floating Point Memory Instructions
-let Predicates = [HasStdEnc] in {
- 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 Predicates = [IsFP64bit, HasStdEnc], DecoderNamespace = "Mips64" in {
- def LDC164 : LW_FT<"ldc1", FGR64Opnd, II_LDC1, load>, LW_FM<0x35>;
- def SDC164 : SW_FT<"sdc1", FGR64Opnd, II_SDC1, store>, LW_FM<0x3d>;
-}
-
-let Predicates = [NotFP64bit, HasStdEnc] in {
- def LDC1 : MMRel, LW_FT<"ldc1", AFGR64Opnd, II_LDC1, load>, LW_FM<0x35>;
- def SDC1 : MMRel, SW_FT<"sdc1", AFGR64Opnd, II_SDC1, store>, LW_FM<0x3d>;
-}
-
-/// Cop2 Memory Instructions
-let Predicates = [HasStdEnc] in {
- def LWC2 : LW_FT<"lwc2", COP2Opnd, NoItinerary, load>, LW_FM<0x32>;
- def SWC2 : SW_FT<"swc2", COP2Opnd, NoItinerary, store>, LW_FM<0x3a>;
- def LDC2 : LW_FT<"ldc2", COP2Opnd, NoItinerary, load>, LW_FM<0x36>;
- def SDC2 : SW_FT<"sdc2", COP2Opnd, NoItinerary, store>, LW_FM<0x3e>;
-}
+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 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;
+}
+
+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;
+
+// Cop2 Memory Instructions
+// FIXME: These aren't really FPU instructions and as such don't belong in this
+// file
+def LWC2 : LW_FT<"lwc2", COP2Opnd, NoItinerary, load>, LW_FM<0x32>;
+def SWC2 : SW_FT<"swc2", COP2Opnd, NoItinerary, store>, LW_FM<0x3a>;
+def LDC2 : LW_FT<"ldc2", COP2Opnd, NoItinerary, load>, LW_FM<0x36>, ISA_MIPS2;
+def SDC2 : SW_FT<"sdc2", COP2Opnd, NoItinerary, store>, LW_FM<0x3e>, ISA_MIPS2;
+
+// Cop3 Memory Instructions
+// FIXME: These aren't really FPU instructions and as such don't belong in this
+// file
+def LWC3 : LW_FT<"lwc3", COP3Opnd, NoItinerary, load>, LW_FM<0x33>;
+def SWC3 : SW_FT<"swc3", COP3Opnd, NoItinerary, store>, LW_FM<0x3b>;
+def LDC3 : LW_FT<"ldc3", COP3Opnd, NoItinerary, load>, LW_FM<0x37>, ISA_MIPS2;
+def SDC3 : SW_FT<"sdc3", COP3Opnd, NoItinerary, store>, LW_FM<0x3f>, ISA_MIPS2;
// Indexed loads and stores.
// Base register + offset register addressing mode (indicated by "x" in the
// instruction mnemonic) is disallowed under NaCl.
-let Predicates = [HasFPIdx, HasStdEnc, IsNotNaCl] in {
- def LWXC1 : MMRel, LWXC1_FT<"lwxc1", FGR32Opnd, II_LWXC1, load>, LWXC1_FM<0>;
- def SWXC1 : MMRel, SWXC1_FT<"swxc1", FGR32Opnd, II_SWXC1, store>, SWXC1_FM<8>;
+let AdditionalPredicates = [IsNotNaCl] in {
+ def LWXC1 : MMRel, LWXC1_FT<"lwxc1", FGR32Opnd, II_LWXC1, load>, LWXC1_FM<0>,
+ INSN_MIPS4_32R2;
+ def SWXC1 : MMRel, SWXC1_FT<"swxc1", FGR32Opnd, II_SWXC1, store>, SWXC1_FM<8>,
+ INSN_MIPS4_32R2;
}
-let Predicates = [HasFPIdx, NotFP64bit, HasStdEnc, NotInMicroMips,
- IsNotNaCl] in {
- def LDXC1 : LWXC1_FT<"ldxc1", AFGR64Opnd, II_LDXC1, load>, LWXC1_FM<1>;
- def SDXC1 : SWXC1_FT<"sdxc1", AFGR64Opnd, II_SDXC1, store>, SWXC1_FM<9>;
+let AdditionalPredicates = [NotInMicroMips, IsNotNaCl] in {
+ def LDXC1 : LWXC1_FT<"ldxc1", AFGR64Opnd, II_LDXC1, load>, LWXC1_FM<1>,
+ INSN_MIPS4_32R2, FGR_32;
+ def SDXC1 : SWXC1_FT<"sdxc1", AFGR64Opnd, II_SDXC1, store>, SWXC1_FM<9>,
+ INSN_MIPS4_32R2, FGR_32;
}
-let Predicates = [HasFPIdx, IsFP64bit, HasStdEnc],
- DecoderNamespace="Mips64" in {
- def LDXC164 : LWXC1_FT<"ldxc1", FGR64Opnd, II_LDXC1, load>, LWXC1_FM<1>;
- def SDXC164 : SWXC1_FT<"sdxc1", FGR64Opnd, II_SDXC1, store>, SWXC1_FM<9>;
+let DecoderNamespace="Mips64" in {
+ def LDXC164 : LWXC1_FT<"ldxc1", FGR64Opnd, II_LDXC1, load>, LWXC1_FM<1>,
+ INSN_MIPS4_32R2, FGR_64;
+ def SDXC164 : SWXC1_FT<"sdxc1", FGR64Opnd, II_SDXC1, store>, SWXC1_FM<9>,
+ INSN_MIPS4_32R2, FGR_64;
}
// Load/store doubleword indexed unaligned.
-let Predicates = [NotFP64bit, HasStdEnc, IsNotNaCl] in {
- def LUXC1 : MMRel, LWXC1_FT<"luxc1", AFGR64Opnd, II_LUXC1>, LWXC1_FM<0x5>;
- def SUXC1 : MMRel, SWXC1_FT<"suxc1", AFGR64Opnd, II_SUXC1>, SWXC1_FM<0xd>;
+let AdditionalPredicates = [IsNotNaCl] in {
+ def LUXC1 : MMRel, LWXC1_FT<"luxc1", AFGR64Opnd, II_LUXC1>, LWXC1_FM<0x5>,
+ INSN_MIPS5_32R2, FGR_32;
+ def SUXC1 : MMRel, SWXC1_FT<"suxc1", AFGR64Opnd, II_SUXC1>, SWXC1_FM<0xd>,
+ INSN_MIPS5_32R2, FGR_32;
}
-let Predicates = [IsFP64bit, HasStdEnc], DecoderNamespace="Mips64" in {
- def LUXC164 : LWXC1_FT<"luxc1", FGR64Opnd, II_LUXC1>, LWXC1_FM<0x5>;
- def SUXC164 : SWXC1_FT<"suxc1", FGR64Opnd, II_SUXC1>, SWXC1_FM<0xd>;
+let DecoderNamespace="Mips64" in {
+ def LUXC164 : LWXC1_FT<"luxc1", FGR64Opnd, II_LUXC1>, LWXC1_FM<0x5>,
+ INSN_MIPS5_32R2, FGR_64;
+ def SUXC164 : SWXC1_FT<"suxc1", FGR64Opnd, II_SUXC1>, SWXC1_FM<0xd>,
+ INSN_MIPS5_32R2, FGR_64;
}
/// Floating-point Aritmetic
@@ -434,47 +456,43 @@ def FSUB_S : MMRel, ADDS_FT<"sub.s", FGR32Opnd, II_SUB_S, 0, fsub>,
ADDS_FM<0x01, 16>;
defm FSUB : ADDS_M<"sub.d", II_SUB_D, 0, fsub>, ADDS_FM<0x01, 17>;
-let Predicates = [HasMips32r2, HasStdEnc] in {
- def MADD_S : MMRel, MADDS_FT<"madd.s", FGR32Opnd, II_MADD_S, fadd>,
- MADDS_FM<4, 0>;
- def MSUB_S : MMRel, MADDS_FT<"msub.s", FGR32Opnd, II_MSUB_S, fsub>,
- MADDS_FM<5, 0>;
-}
+def MADD_S : MMRel, MADDS_FT<"madd.s", FGR32Opnd, II_MADD_S, fadd>,
+ MADDS_FM<4, 0>, ISA_MIPS32R2;
+def MSUB_S : MMRel, MADDS_FT<"msub.s", FGR32Opnd, II_MSUB_S, fsub>,
+ MADDS_FM<5, 0>, ISA_MIPS32R2;
-let Predicates = [HasMips32r2, NoNaNsFPMath, HasStdEnc] in {
+let AdditionalPredicates = [NoNaNsFPMath] in {
def NMADD_S : MMRel, NMADDS_FT<"nmadd.s", FGR32Opnd, II_NMADD_S, fadd>,
- MADDS_FM<6, 0>;
+ MADDS_FM<6, 0>, ISA_MIPS32R2;
def NMSUB_S : MMRel, NMADDS_FT<"nmsub.s", FGR32Opnd, II_NMSUB_S, fsub>,
- MADDS_FM<7, 0>;
+ MADDS_FM<7, 0>, ISA_MIPS32R2;
}
-let Predicates = [HasMips32r2, NotFP64bit, HasStdEnc] in {
- def MADD_D32 : MMRel, MADDS_FT<"madd.d", AFGR64Opnd, II_MADD_D, fadd>,
- MADDS_FM<4, 1>;
- def MSUB_D32 : MMRel, MADDS_FT<"msub.d", AFGR64Opnd, II_MSUB_D, fsub>,
- MADDS_FM<5, 1>;
-}
+def MADD_D32 : MMRel, MADDS_FT<"madd.d", AFGR64Opnd, II_MADD_D, fadd>,
+ MADDS_FM<4, 1>, ISA_MIPS32R2, FGR_32;
+def MSUB_D32 : MMRel, MADDS_FT<"msub.d", AFGR64Opnd, II_MSUB_D, fsub>,
+ MADDS_FM<5, 1>, ISA_MIPS32R2, FGR_32;
-let Predicates = [HasMips32r2, NotFP64bit, NoNaNsFPMath, HasStdEnc] in {
+let AdditionalPredicates = [NoNaNsFPMath] in {
def NMADD_D32 : MMRel, NMADDS_FT<"nmadd.d", AFGR64Opnd, II_NMADD_D, fadd>,
- MADDS_FM<6, 1>;
+ MADDS_FM<6, 1>, ISA_MIPS32R2, FGR_32;
def NMSUB_D32 : MMRel, NMADDS_FT<"nmsub.d", AFGR64Opnd, II_NMSUB_D, fsub>,
- MADDS_FM<7, 1>;
+ MADDS_FM<7, 1>, ISA_MIPS32R2, FGR_32;
}
-let Predicates = [HasMips32r2, IsFP64bit, HasStdEnc], isCodeGenOnly=1 in {
+let isCodeGenOnly=1 in {
def MADD_D64 : MADDS_FT<"madd.d", FGR64Opnd, II_MADD_D, fadd>,
- MADDS_FM<4, 1>;
+ MADDS_FM<4, 1>, ISA_MIPS32R2, FGR_64;
def MSUB_D64 : MADDS_FT<"msub.d", FGR64Opnd, II_MSUB_D, fsub>,
- MADDS_FM<5, 1>;
+ MADDS_FM<5, 1>, ISA_MIPS32R2, FGR_64;
}
-let Predicates = [HasMips32r2, IsFP64bit, NoNaNsFPMath, HasStdEnc],
+let AdditionalPredicates = [NoNaNsFPMath],
isCodeGenOnly=1 in {
def NMADD_D64 : NMADDS_FT<"nmadd.d", FGR64Opnd, II_NMADD_D, fadd>,
- MADDS_FM<6, 1>;
+ MADDS_FM<6, 1>, ISA_MIPS32R2, FGR_64;
def NMSUB_D64 : NMADDS_FT<"nmsub.d", FGR64Opnd, II_NMSUB_D, fsub>,
- MADDS_FM<7, 1>;
+ MADDS_FM<7, 1>, ISA_MIPS32R2, FGR_64;
}
//===----------------------------------------------------------------------===//
@@ -515,10 +533,10 @@ def MIPS_FCOND_NGT : PatLeaf<(i32 15)>;
/// Floating Point Compare
def FCMP_S32 : MMRel, CEQS_FT<"s", FGR32, II_C_CC_S, MipsFPCmp>, CEQS_FM<16>;
def FCMP_D32 : MMRel, CEQS_FT<"d", AFGR64, II_C_CC_D, MipsFPCmp>, CEQS_FM<17>,
- Requires<[NotFP64bit, HasStdEnc]>;
+ AdditionalRequires<[NotFP64bit]>;
let DecoderNamespace = "Mips64" in
def FCMP_D64 : CEQS_FT<"d", FGR64, II_C_CC_D, MipsFPCmp>, CEQS_FM<17>,
- Requires<[IsFP64bit, HasStdEnc]>;
+ AdditionalRequires<[IsFP64bit]>;
//===----------------------------------------------------------------------===//
// Floating Point Pseudo-Instructions
@@ -531,9 +549,9 @@ class BuildPairF64Base<RegisterOperand RO> :
[(set RO:$dst, (MipsBuildPairF64 GPR32Opnd:$lo, GPR32Opnd:$hi))]>;
def BuildPairF64 : BuildPairF64Base<AFGR64Opnd>,
- Requires<[NotFP64bit, HasStdEnc]>;
+ AdditionalRequires<[NotFP64bit]>;
def BuildPairF64_64 : BuildPairF64Base<FGR64Opnd>,
- Requires<[IsFP64bit, HasStdEnc]>;
+ AdditionalRequires<[IsFP64bit]>;
// This pseudo instr gets expanded into 2 mfc1 instrs after register
// allocation.
@@ -544,15 +562,15 @@ class ExtractElementF64Base<RegisterOperand RO> :
[(set GPR32Opnd:$dst, (MipsExtractElementF64 RO:$src, imm:$n))]>;
def ExtractElementF64 : ExtractElementF64Base<AFGR64Opnd>,
- Requires<[NotFP64bit, HasStdEnc]>;
+ AdditionalRequires<[NotFP64bit]>;
def ExtractElementF64_64 : ExtractElementF64Base<FGR64Opnd>,
- Requires<[IsFP64bit, HasStdEnc]>;
+ AdditionalRequires<[IsFP64bit]>;
//===----------------------------------------------------------------------===//
// InstAliases.
//===----------------------------------------------------------------------===//
-def : InstAlias<"bc1t $offset", (BC1T FCC0, brtarget:$offset)>;
-def : InstAlias<"bc1f $offset", (BC1F FCC0, brtarget:$offset)>;
+def : MipsInstAlias<"bc1t $offset", (BC1T FCC0, brtarget:$offset)>;
+def : MipsInstAlias<"bc1f $offset", (BC1F FCC0, brtarget:$offset)>;
//===----------------------------------------------------------------------===//
// Floating Point Patterns
@@ -565,55 +583,45 @@ def : MipsPat<(f32 (sint_to_fp GPR32Opnd:$src)),
def : MipsPat<(MipsTruncIntFP FGR32Opnd:$src),
(TRUNC_W_S FGR32Opnd:$src)>;
-let Predicates = [NotFP64bit, HasStdEnc] in {
- def : MipsPat<(f64 (sint_to_fp GPR32Opnd:$src)),
- (PseudoCVT_D32_W GPR32Opnd:$src)>;
- def : MipsPat<(MipsTruncIntFP AFGR64Opnd:$src),
- (TRUNC_W_D32 AFGR64Opnd:$src)>;
- def : MipsPat<(f32 (fround AFGR64Opnd:$src)),
- (CVT_S_D32 AFGR64Opnd:$src)>;
- def : MipsPat<(f64 (fextend FGR32Opnd:$src)),
- (CVT_D32_S FGR32Opnd:$src)>;
-}
+def : MipsPat<(f64 (sint_to_fp GPR32Opnd:$src)),
+ (PseudoCVT_D32_W GPR32Opnd:$src)>, FGR_32;
+def : MipsPat<(MipsTruncIntFP AFGR64Opnd:$src),
+ (TRUNC_W_D32 AFGR64Opnd:$src)>, FGR_32;
+def : MipsPat<(f32 (fround AFGR64Opnd:$src)),
+ (CVT_S_D32 AFGR64Opnd:$src)>, FGR_32;
+def : MipsPat<(f64 (fextend FGR32Opnd:$src)),
+ (CVT_D32_S FGR32Opnd:$src)>, FGR_32;
+
+def : MipsPat<(f64 fpimm0), (DMTC1 ZERO_64)>, FGR_64;
+def : MipsPat<(f64 fpimm0neg), (FNEG_D64 (DMTC1 ZERO_64))>, FGR_64;
+
+def : MipsPat<(f64 (sint_to_fp GPR32Opnd:$src)),
+ (PseudoCVT_D64_W GPR32Opnd:$src)>, FGR_64;
+def : MipsPat<(f32 (sint_to_fp GPR64Opnd:$src)),
+ (EXTRACT_SUBREG (PseudoCVT_S_L GPR64Opnd:$src), sub_lo)>, FGR_64;
+def : MipsPat<(f64 (sint_to_fp GPR64Opnd:$src)),
+ (PseudoCVT_D64_L GPR64Opnd:$src)>, FGR_64;
+
+def : MipsPat<(MipsTruncIntFP FGR64Opnd:$src),
+ (TRUNC_W_D64 FGR64Opnd:$src)>, FGR_64;
+def : MipsPat<(MipsTruncIntFP FGR32Opnd:$src),
+ (TRUNC_L_S FGR32Opnd:$src)>, FGR_64;
+def : MipsPat<(MipsTruncIntFP FGR64Opnd:$src),
+ (TRUNC_L_D64 FGR64Opnd:$src)>, FGR_64;
-let Predicates = [IsFP64bit, HasStdEnc] in {
- def : MipsPat<(f64 fpimm0), (DMTC1 ZERO_64)>;
- def : MipsPat<(f64 fpimm0neg), (FNEG_D64 (DMTC1 ZERO_64))>;
-
- def : MipsPat<(f64 (sint_to_fp GPR32Opnd:$src)),
- (PseudoCVT_D64_W GPR32Opnd:$src)>;
- def : MipsPat<(f32 (sint_to_fp GPR64Opnd:$src)),
- (EXTRACT_SUBREG (PseudoCVT_S_L GPR64Opnd:$src), sub_lo)>;
- def : MipsPat<(f64 (sint_to_fp GPR64Opnd:$src)),
- (PseudoCVT_D64_L GPR64Opnd:$src)>;
-
- def : MipsPat<(MipsTruncIntFP FGR64Opnd:$src),
- (TRUNC_W_D64 FGR64Opnd:$src)>;
- def : MipsPat<(MipsTruncIntFP FGR32Opnd:$src),
- (TRUNC_L_S FGR32Opnd:$src)>;
- def : MipsPat<(MipsTruncIntFP FGR64Opnd:$src),
- (TRUNC_L_D64 FGR64Opnd:$src)>;
-
- def : MipsPat<(f32 (fround FGR64Opnd:$src)),
- (CVT_S_D64 FGR64Opnd:$src)>;
- def : MipsPat<(f64 (fextend FGR32Opnd:$src)),
- (CVT_D64_S FGR32Opnd:$src)>;
-}
+def : MipsPat<(f32 (fround FGR64Opnd:$src)),
+ (CVT_S_D64 FGR64Opnd:$src)>, FGR_64;
+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 {
- let Predicates = [HasStdEnc] in {
- def : LoadRegImmPat<LWC1, f32, load>;
- def : StoreRegImmPat<SWC1, f32>;
- }
+ def : LoadRegImmPat<LWC1, f32, load>;
+ def : StoreRegImmPat<SWC1, f32>;
- let Predicates = [IsFP64bit, HasStdEnc] in {
- def : LoadRegImmPat<LDC164, f64, load>;
- def : StoreRegImmPat<SDC164, f64>;
- }
+ def : LoadRegImmPat<LDC164, f64, load>, FGR_64;
+ def : StoreRegImmPat<SDC164, f64>, FGR_64;
- let Predicates = [NotFP64bit, HasStdEnc] in {
- def : LoadRegImmPat<LDC1, f64, load>;
- def : StoreRegImmPat<SDC1, f64>;
- }
+ 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 e4405ab..0377eab 100644
--- a/lib/Target/Mips/MipsInstrFormats.td
+++ b/lib/Target/Mips/MipsInstrFormats.td
@@ -93,8 +93,8 @@ class MipsInst<dag outs, dag ins, string asmstr, list<dag> pattern,
// Mips32/64 Instruction Format
class InstSE<dag outs, dag ins, string asmstr, list<dag> pattern,
InstrItinClass itin, Format f, string opstr = ""> :
- MipsInst<outs, ins, asmstr, pattern, itin, f> {
- let Predicates = [HasStdEnc];
+ MipsInst<outs, ins, asmstr, pattern, itin, f>, PredicateControl {
+ let EncodingPredicates = [HasStdEnc];
string BaseOpcode = opstr;
string Arch;
}
@@ -109,9 +109,9 @@ class MipsPseudo<dag outs, dag ins, list<dag> pattern,
// Mips32/64 Pseudo Instruction Format
class PseudoSE<dag outs, dag ins, list<dag> pattern,
- InstrItinClass itin = IIPseudo>:
- MipsPseudo<outs, ins, pattern, itin> {
- let Predicates = [HasStdEnc];
+ InstrItinClass itin = IIPseudo> :
+ MipsPseudo<outs, ins, pattern, itin>, PredicateControl {
+ let EncodingPredicates = [HasStdEnc];
}
// Pseudo-instructions for alternate assembly syntax (never used by codegen).
@@ -545,6 +545,20 @@ class SEQ_FM<bits<6> funct> : StdArch {
let Inst{5-0} = funct;
}
+class SEQI_FM<bits<6> funct> : StdArch {
+ bits<5> rs;
+ bits<5> rt;
+ bits<10> imm10;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = 0x1c;
+ let Inst{25-21} = rs;
+ let Inst{20-16} = rt;
+ let Inst{15-6} = imm10;
+ let Inst{5-0} = funct;
+}
+
//===----------------------------------------------------------------------===//
// System calls format <op|code_|funct>
//===----------------------------------------------------------------------===//
@@ -829,3 +843,12 @@ class BARRIER_FM<bits<5> op> : StdArch {
let Inst{10-6} = op; // Operation
let Inst{5-0} = 0; // SLL
}
+
+class COP0_TLB_FM<bits<6> op> : StdArch {
+ bits<32> Inst;
+
+ let Inst{31-26} = 0x10; // COP0
+ let Inst{25} = 1; // CO
+ let Inst{24-6} = 0;
+ let Inst{5-0} = op; // Operation
+}
diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp
index 0ebad05..d6da6c6 100644
--- a/lib/Target/Mips/MipsInstrInfo.cpp
+++ b/lib/Target/Mips/MipsInstrInfo.cpp
@@ -22,11 +22,11 @@
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TargetRegistry.h"
+using namespace llvm;
+
#define GET_INSTRINFO_CTOR_DTOR
#include "MipsGenInstrInfo.inc"
-using namespace llvm;
-
// Pin the vtable to this file.
void MipsInstrInfo::anchor() {}
@@ -195,7 +195,7 @@ AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
if (I == REnd || !isUnpredicatedTerminator(&*I)) {
// This block ends with no branches (it just falls through to its succ).
// Leave TBB/FBB null.
- TBB = FBB = NULL;
+ TBB = FBB = nullptr;
return BT_NoBranch;
}
@@ -209,7 +209,7 @@ AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
// Get the second to last instruction in the block.
unsigned SecondLastOpc = 0;
- MachineInstr *SecondLastInst = NULL;
+ MachineInstr *SecondLastInst = nullptr;
if (++I != REnd) {
SecondLastInst = &*I;
diff --git a/lib/Target/Mips/MipsInstrInfo.h b/lib/Target/Mips/MipsInstrInfo.h
index d9ac961..742193f 100644
--- a/lib/Target/Mips/MipsInstrInfo.h
+++ b/lib/Target/Mips/MipsInstrInfo.h
@@ -9,6 +9,10 @@
//
// This file contains the Mips implementation of the TargetInstrInfo class.
//
+// FIXME: We need to override TargetInstrInfo::getInlineAsmLength method in
+// order for MipsLongBranch pass to work correctly when the code has inline
+// assembly. The returned value doesn't have to be the asm instruction's exact
+// size in bytes; MipsLongBranch only expects it to be the correct upper bound.
//===----------------------------------------------------------------------===//
#ifndef MIPSINSTRUCTIONINFO_H
@@ -47,20 +51,20 @@ public:
static const MipsInstrInfo *create(MipsTargetMachine &TM);
/// Branch Analysis
- virtual bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
- MachineBasicBlock *&FBB,
- SmallVectorImpl<MachineOperand> &Cond,
- bool AllowModify) const;
+ bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
+ MachineBasicBlock *&FBB,
+ SmallVectorImpl<MachineOperand> &Cond,
+ bool AllowModify) const override;
- virtual unsigned RemoveBranch(MachineBasicBlock &MBB) const;
+ unsigned RemoveBranch(MachineBasicBlock &MBB) const override;
- virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
- MachineBasicBlock *FBB,
- const SmallVectorImpl<MachineOperand> &Cond,
- DebugLoc DL) const;
+ unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB,
+ MachineBasicBlock *FBB,
+ const SmallVectorImpl<MachineOperand> &Cond,
+ DebugLoc DL) const override;
- virtual
- bool ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const;
+ bool
+ ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const override;
BranchType AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
MachineBasicBlock *&FBB,
@@ -69,8 +73,8 @@ public:
SmallVectorImpl<MachineInstr*> &BranchInstrs) const;
/// Insert nop instruction when hazard condition is found
- virtual void insertNoop(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI) const;
+ void insertNoop(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI) const override;
/// getRegisterInfo - TargetInstrInfo is a superset of MRegister info. As
/// such, whenever a client has an instance of instruction info, it should
@@ -83,19 +87,19 @@ public:
/// Return the number of bytes of code the specified instruction may be.
unsigned GetInstSizeInBytes(const MachineInstr *MI) const;
- virtual void storeRegToStackSlot(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MBBI,
- unsigned SrcReg, bool isKill, int FrameIndex,
- const TargetRegisterClass *RC,
- const TargetRegisterInfo *TRI) const {
+ void storeRegToStackSlot(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MBBI,
+ unsigned SrcReg, bool isKill, int FrameIndex,
+ const TargetRegisterClass *RC,
+ const TargetRegisterInfo *TRI) const override {
storeRegToStack(MBB, MBBI, SrcReg, isKill, FrameIndex, RC, TRI, 0);
}
- virtual void loadRegFromStackSlot(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MBBI,
- unsigned DestReg, int FrameIndex,
- const TargetRegisterClass *RC,
- const TargetRegisterInfo *TRI) const {
+ void loadRegFromStackSlot(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MBBI,
+ unsigned DestReg, int FrameIndex,
+ const TargetRegisterClass *RC,
+ const TargetRegisterInfo *TRI) const override {
loadRegFromStack(MBB, MBBI, DestReg, FrameIndex, RC, TRI, 0);
}
diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td
index 07c37d8..0d3cb75 100644
--- a/lib/Target/Mips/MipsInstrInfo.td
+++ b/lib/Target/Mips/MipsInstrInfo.td
@@ -146,26 +146,40 @@ def MipsSDR : SDNode<"MipsISD::SDR", SDTStore,
//===----------------------------------------------------------------------===//
// Mips Instruction Predicate Definitions.
//===----------------------------------------------------------------------===//
-def HasSEInReg : Predicate<"Subtarget.hasSEInReg()">,
- AssemblerPredicate<"FeatureSEInReg">;
-def HasBitCount : Predicate<"Subtarget.hasBitCount()">,
- AssemblerPredicate<"FeatureBitCount">;
-def HasSwap : Predicate<"Subtarget.hasSwap()">,
- AssemblerPredicate<"FeatureSwap">;
-def HasCondMov : Predicate<"Subtarget.hasCondMov()">,
- AssemblerPredicate<"FeatureCondMov">;
-def HasFPIdx : Predicate<"Subtarget.hasFPIdx()">,
- AssemblerPredicate<"FeatureFPIdx">;
+def HasMips2 : Predicate<"Subtarget.hasMips2()">,
+ AssemblerPredicate<"FeatureMips2">;
+def HasMips3_32 : Predicate<"Subtarget.hasMips3_32()">,
+ AssemblerPredicate<"FeatureMips3_32">;
+def HasMips3_32r2 : Predicate<"Subtarget.hasMips3_32r2()">,
+ AssemblerPredicate<"FeatureMips3_32r2">;
+def HasMips3 : Predicate<"Subtarget.hasMips3()">,
+ AssemblerPredicate<"FeatureMips3">;
+def HasMips4_32 : Predicate<"Subtarget.hasMips4_32()">,
+ AssemblerPredicate<"FeatureMips4_32">;
+def HasMips4_32r2 : Predicate<"Subtarget.hasMips4_32r2()">,
+ AssemblerPredicate<"FeatureMips4_32r2">;
+def HasMips5_32r2 : Predicate<"Subtarget.hasMips5_32r2()">,
+ AssemblerPredicate<"FeatureMips5_32r2">;
def HasMips32 : Predicate<"Subtarget.hasMips32()">,
AssemblerPredicate<"FeatureMips32">;
def HasMips32r2 : Predicate<"Subtarget.hasMips32r2()">,
AssemblerPredicate<"FeatureMips32r2">;
+def HasMips32r6 : Predicate<"Subtarget.hasMips32r6()">,
+ AssemblerPredicate<"FeatureMips32r6">;
+def NotMips32r6 : Predicate<"!Subtarget.hasMips32r6()">,
+ AssemblerPredicate<"!FeatureMips32r6">;
+def IsGP64bit : Predicate<"Subtarget.isGP64bit()">,
+ AssemblerPredicate<"FeatureGP64Bit">;
+def IsGP32bit : Predicate<"!Subtarget.isGP64bit()">,
+ AssemblerPredicate<"!FeatureGP64Bit">;
def HasMips64 : Predicate<"Subtarget.hasMips64()">,
AssemblerPredicate<"FeatureMips64">;
-def NotMips64 : Predicate<"!Subtarget.hasMips64()">,
- AssemblerPredicate<"!FeatureMips64">;
def HasMips64r2 : Predicate<"Subtarget.hasMips64r2()">,
AssemblerPredicate<"FeatureMips64r2">;
+def HasMips64r6 : Predicate<"Subtarget.hasMips64r6()">,
+ AssemblerPredicate<"FeatureMips64r6">;
+def NotMips64r6 : Predicate<"!Subtarget.hasMips64r6()">,
+ AssemblerPredicate<"!FeatureMips64r6">;
def IsN64 : Predicate<"Subtarget.isABI_N64()">,
AssemblerPredicate<"FeatureN64">;
def InMips16Mode : Predicate<"Subtarget.inMips16Mode()">,
@@ -176,8 +190,7 @@ def RelocStatic : Predicate<"TM.getRelocationModel() == Reloc::Static">,
AssemblerPredicate<"FeatureMips32">;
def RelocPIC : Predicate<"TM.getRelocationModel() == Reloc::PIC_">,
AssemblerPredicate<"FeatureMips32">;
-def NoNaNsFPMath : Predicate<"TM.Options.NoNaNsFPMath">,
- AssemblerPredicate<"FeatureMips32">;
+def NoNaNsFPMath : Predicate<"TM.Options.NoNaNsFPMath">;
def HasStdEnc : Predicate<"Subtarget.hasStandardEncoding()">,
AssemblerPredicate<"!FeatureMips16">;
def NotDSP : Predicate<"!Subtarget.hasDSP()">;
@@ -189,9 +202,65 @@ def IsLE : Predicate<"Subtarget.isLittle()">;
def IsBE : Predicate<"!Subtarget.isLittle()">;
def IsNotNaCl : Predicate<"!Subtarget.isTargetNaCl()">;
-class MipsPat<dag pattern, dag result> : Pat<pattern, result> {
- let Predicates = [HasStdEnc];
+//===----------------------------------------------------------------------===//
+// Mips GPR size adjectives.
+// They are mutually exclusive.
+//===----------------------------------------------------------------------===//
+
+class GPR_32 { list<Predicate> GPRPredicates = [IsGP32bit]; }
+class GPR_64 { list<Predicate> GPRPredicates = [IsGP64bit]; }
+
+//===----------------------------------------------------------------------===//
+// Mips ISA/ASE membership and instruction group membership adjectives.
+// They are mutually exclusive.
+//===----------------------------------------------------------------------===//
+
+// FIXME: I'd prefer to use additive predicates to build the instruction sets
+// but we are short on assembler feature bits at the moment. Using a
+// subtractive predicate will hopefully keep us under the 32 predicate
+// limit long enough to develop an alternative way to handle P1||P2
+// predicates.
+class ISA_MIPS1_NOT_32R6_64R6 {
+ list<Predicate> InsnPredicates = [NotMips32r6, NotMips64r6];
+}
+class ISA_MIPS2 { list<Predicate> InsnPredicates = [HasMips2]; }
+class ISA_MIPS2_NOT_32R6_64R6 {
+ list<Predicate> InsnPredicates = [HasMips2, NotMips32r6, NotMips64r6];
+}
+class ISA_MIPS3 { list<Predicate> InsnPredicates = [HasMips3]; }
+class ISA_MIPS3_NOT_32R6_64R6 {
+ list<Predicate> InsnPredicates = [HasMips3, NotMips32r6, NotMips64r6];
}
+class ISA_MIPS32 { list<Predicate> InsnPredicates = [HasMips32]; }
+class ISA_MIPS32R2 { list<Predicate> InsnPredicates = [HasMips32r2]; }
+class ISA_MIPS64 { list<Predicate> InsnPredicates = [HasMips64]; }
+class ISA_MIPS64R2 { list<Predicate> InsnPredicates = [HasMips64r2]; }
+class ISA_MIPS32R6 { list<Predicate> InsnPredicates = [HasMips32r6]; }
+class ISA_MIPS64R6 { list<Predicate> InsnPredicates = [HasMips64r6]; }
+
+// The portions of MIPS-III that were also added to MIPS32
+class INSN_MIPS3_32 { list<Predicate> InsnPredicates = [HasMips3_32]; }
+
+// The portions of MIPS-III that were also added to MIPS32
+class INSN_MIPS3_32R2 { list<Predicate> InsnPredicates = [HasMips3_32r2]; }
+
+// The portions of MIPS-IV that were also added to MIPS32
+class INSN_MIPS4_32 { list<Predicate> InsnPredicates = [HasMips4_32]; }
+
+// The portions of MIPS-IV that were also added to MIPS32R2
+class INSN_MIPS4_32R2 { list<Predicate> InsnPredicates = [HasMips4_32r2]; }
+
+// The portions of MIPS-V that were also added to MIPS32R2
+class INSN_MIPS5_32R2 { list<Predicate> InsnPredicates = [HasMips5_32r2]; }
+
+//===----------------------------------------------------------------------===//
+
+class MipsPat<dag pattern, dag result> : Pat<pattern, result>, PredicateControl {
+ let EncodingPredicates = [HasStdEnc];
+}
+
+class MipsInstAlias<string Asm, dag Result, bit Emit = 0b1> :
+ InstAlias<Asm, Result, Emit>, PredicateControl;
class IsCommutable {
bit isCommutable = 1;
@@ -265,6 +334,11 @@ def simm16 : Operand<i32> {
let DecoderMethod= "DecodeSimm16";
}
+def simm19_lsl2 : Operand<i32> {
+ let EncoderMethod = "getSimm19Lsl2Encoding";
+ let DecoderMethod = "DecodeSimm19Lsl2";
+}
+
def simm20 : Operand<i32> {
}
@@ -284,6 +358,14 @@ def uimmz : Operand<i32> {
}
// Unsigned Operand
+def uimm2 : Operand<i32> {
+ let PrintMethod = "printUnsignedImm";
+}
+
+def uimm3 : Operand<i32> {
+ let PrintMethod = "printUnsignedImm";
+}
+
def uimm5 : Operand<i32> {
let PrintMethod = "printUnsignedImm";
}
@@ -314,6 +396,10 @@ def InvertedImOperand : Operand<i32> {
let ParserMatchClass = MipsInvertedImmoperand;
}
+def InvertedImOperand64 : Operand<i64> {
+ let ParserMatchClass = MipsInvertedImmoperand;
+}
+
class mem_generic : Operand<iPTR> {
let PrintMethod = "printMemOperand";
let MIOperandInfo = (ops ptr_rc, simm16);
@@ -478,7 +564,9 @@ class shift_rotate_imm<string opstr, Operand ImmOpnd,
SDPatternOperator PF = null_frag> :
InstSE<(outs RO:$rd), (ins RO:$rt, ImmOpnd:$shamt),
!strconcat(opstr, "\t$rd, $rt, $shamt"),
- [(set RO:$rd, (OpNode RO:$rt, PF:$shamt))], itin, FrmR, opstr>;
+ [(set RO:$rd, (OpNode RO:$rt, PF:$shamt))], itin, FrmR, opstr> {
+ let TwoOperandAliasConstraint = "$rt = $rd";
+}
class shift_rotate_reg<string opstr, RegisterOperand RO, InstrItinClass itin,
SDPatternOperator OpNode = null_frag>:
@@ -590,7 +678,7 @@ class UncondBranch<Instruction BEQInst> :
let isTerminator = 1;
let isBarrier = 1;
let hasDelaySlot = 1;
- let Predicates = [RelocPIC, HasStdEnc];
+ let AdditionalPredicates = [RelocPIC];
let Defs = [AT];
}
@@ -779,27 +867,22 @@ class EffectiveAddress<string opstr, RegisterOperand RO> :
// Count Leading Ones/Zeros in Word
class CountLeading0<string opstr, RegisterOperand RO>:
InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"),
- [(set RO:$rd, (ctlz RO:$rs))], II_CLZ, FrmR, opstr>,
- Requires<[HasBitCount, HasStdEnc]>;
+ [(set RO:$rd, (ctlz RO:$rs))], II_CLZ, FrmR, opstr>;
class CountLeading1<string opstr, RegisterOperand RO>:
InstSE<(outs RO:$rd), (ins RO:$rs), !strconcat(opstr, "\t$rd, $rs"),
- [(set RO:$rd, (ctlz (not RO:$rs)))], II_CLO, FrmR, opstr>,
- Requires<[HasBitCount, HasStdEnc]>;
+ [(set RO:$rd, (ctlz (not RO:$rs)))], II_CLO, FrmR, opstr>;
// Sign Extend in Register.
class SignExtInReg<string opstr, ValueType vt, RegisterOperand RO,
InstrItinClass itin> :
InstSE<(outs RO:$rd), (ins RO:$rt), !strconcat(opstr, "\t$rd, $rt"),
- [(set RO:$rd, (sext_inreg RO:$rt, vt))], itin, FrmR, opstr> {
- let Predicates = [HasSEInReg, HasStdEnc];
-}
+ [(set RO:$rd, (sext_inreg RO:$rt, vt))], itin, FrmR, opstr>;
// Subword Swap
class SubwordSwap<string opstr, RegisterOperand RO>:
InstSE<(outs RO:$rd), (ins RO:$rt), !strconcat(opstr, "\t$rd, $rt"), [],
NoItinerary, FrmR, opstr> {
- let Predicates = [HasSwap, HasStdEnc];
let neverHasSideEffects = 1;
}
@@ -814,17 +897,14 @@ class ExtBase<string opstr, RegisterOperand RO, Operand PosOpnd,
InstSE<(outs RO:$rt), (ins RO:$rs, PosOpnd:$pos, size_ext:$size),
!strconcat(opstr, " $rt, $rs, $pos, $size"),
[(set RO:$rt, (Op RO:$rs, imm:$pos, imm:$size))], NoItinerary,
- FrmR, opstr> {
- let Predicates = [HasMips32r2, HasStdEnc];
-}
+ 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),
!strconcat(opstr, " $rt, $rs, $pos, $size"),
[(set RO:$rt, (Op RO:$rs, imm:$pos, imm:$size, RO:$src))],
- NoItinerary, FrmR, opstr> {
- let Predicates = [HasMips32r2, HasStdEnc];
+ NoItinerary, FrmR, opstr>, ISA_MIPS32R2 {
let Constraints = "$src = $rt";
}
@@ -915,6 +995,18 @@ let isPseudo = 1, isCodeGenOnly = 1 in {
def STORE_ACC64 : Store<"", ACC64>;
}
+// We need these two pseudo instructions to avoid offset calculation for long
+// branches. See the comment in file MipsLongBranch.cpp for detailed
+// explanation.
+
+// Expands to: lui $dst, %hi($tgt - $baltgt)
+def LONG_BRANCH_LUi : PseudoSE<(outs GPR32Opnd:$dst),
+ (ins brtarget:$tgt, brtarget:$baltgt), []>;
+
+// Expands to: addiu $dst, $src, %lo($tgt - $baltgt)
+def LONG_BRANCH_ADDiu : PseudoSE<(outs GPR32Opnd:$dst),
+ (ins GPR32Opnd:$src, brtarget:$tgt, brtarget:$baltgt), []>;
+
//===----------------------------------------------------------------------===//
// Instruction definition
//===----------------------------------------------------------------------===//
@@ -926,7 +1018,8 @@ let isPseudo = 1, isCodeGenOnly = 1 in {
def ADDiu : MMRel, ArithLogicI<"addiu", simm16, GPR32Opnd, II_ADDIU, immSExt16,
add>,
ADDI_FM<0x9>, IsAsCheapAsAMove;
-def ADDi : MMRel, ArithLogicI<"addi", simm16, GPR32Opnd>, ADDI_FM<0x8>;
+def ADDi : MMRel, ArithLogicI<"addi", simm16, GPR32Opnd>, 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>,
@@ -949,7 +1042,7 @@ def SUBu : MMRel, ArithLogicR<"subu", GPR32Opnd, 0, II_SUBU, sub>,
ADD_FM<0, 0x23>;
let Defs = [HI0, LO0] in
def MUL : MMRel, ArithLogicR<"mul", GPR32Opnd, 1, II_MUL, mul>,
- ADD_FM<0x1c, 2>;
+ ADD_FM<0x1c, 2>, ISA_MIPS32;
def ADD : MMRel, ArithLogicR<"add", GPR32Opnd>, ADD_FM<0, 0x20>;
def SUB : MMRel, ArithLogicR<"sub", GPR32Opnd>, ADD_FM<0, 0x22>;
def SLT : MMRel, SetCC_R<"slt", setlt, GPR32Opnd>, ADD_FM<0, 0x2a>;
@@ -977,12 +1070,11 @@ def SRAV : MMRel, shift_rotate_reg<"srav", GPR32Opnd, II_SRAV, sra>,
SRLV_FM<7, 0>;
// Rotate Instructions
-let Predicates = [HasMips32r2, HasStdEnc] in {
- def ROTR : MMRel, shift_rotate_imm<"rotr", uimm5, GPR32Opnd, II_ROTR, rotr,
- immZExt5>, SRA_FM<2, 1>;
- def ROTRV : MMRel, shift_rotate_reg<"rotrv", GPR32Opnd, II_ROTRV, rotr>,
- SRLV_FM<6, 1>;
-}
+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
@@ -999,11 +1091,16 @@ def SH : Store<"sh", GPR32Opnd, truncstorei16, II_SH>, MMRel, LW_FM<0x29>;
def SW : Store<"sw", GPR32Opnd, store, II_SW>, MMRel, LW_FM<0x2b>;
/// load/store left/right
-let Predicates = [NotInMicroMips] in {
-def LWL : LoadLeftRight<"lwl", MipsLWL, GPR32Opnd, II_LWL>, LW_FM<0x22>;
-def LWR : LoadLeftRight<"lwr", MipsLWR, GPR32Opnd, II_LWR>, LW_FM<0x26>;
-def SWL : StoreLeftRight<"swl", MipsSWL, GPR32Opnd, II_SWL>, LW_FM<0x2a>;
-def SWR : StoreLeftRight<"swr", MipsSWR, GPR32Opnd, II_SWR>, LW_FM<0x2e>;
+let EncodingPredicates = []<Predicate>, // FIXME: Lack of HasStdEnc is probably a bug
+ AdditionalPredicates = [NotInMicroMips] in {
+def LWL : LoadLeftRight<"lwl", MipsLWL, GPR32Opnd, II_LWL>, LW_FM<0x22>,
+ ISA_MIPS1_NOT_32R6_64R6;
+def LWR : LoadLeftRight<"lwr", MipsLWR, GPR32Opnd, II_LWR>, LW_FM<0x26>,
+ ISA_MIPS1_NOT_32R6_64R6;
+def SWL : StoreLeftRight<"swl", MipsSWL, GPR32Opnd, II_SWL>, LW_FM<0x2a>,
+ ISA_MIPS1_NOT_32R6_64R6;
+def SWR : StoreLeftRight<"swr", MipsSWR, GPR32Opnd, II_SWR>, LW_FM<0x2e>,
+ ISA_MIPS1_NOT_32R6_64R6;
}
def SYNC : MMRel, SYNC_FT<"sync">, SYNC_FM;
@@ -1014,34 +1111,41 @@ def TLT : MMRel, TEQ_FT<"tlt", GPR32Opnd>, TEQ_FM<0x32>;
def TLTU : MMRel, TEQ_FT<"tltu", GPR32Opnd>, TEQ_FM<0x33>;
def TNE : MMRel, TEQ_FT<"tne", GPR32Opnd>, TEQ_FM<0x36>;
-def TEQI : MMRel, TEQI_FT<"teqi", GPR32Opnd>, TEQI_FM<0xc>;
-def TGEI : MMRel, TEQI_FT<"tgei", GPR32Opnd>, TEQI_FM<0x8>;
-def TGEIU : MMRel, TEQI_FT<"tgeiu", GPR32Opnd>, TEQI_FM<0x9>;
-def TLTI : MMRel, TEQI_FT<"tlti", GPR32Opnd>, TEQI_FM<0xa>;
-def TTLTIU : MMRel, TEQI_FT<"tltiu", GPR32Opnd>, TEQI_FM<0xb>;
-def TNEI : MMRel, TEQI_FT<"tnei", GPR32Opnd>, TEQI_FM<0xe>;
+def TEQI : MMRel, TEQI_FT<"teqi", GPR32Opnd>, TEQI_FM<0xc>,
+ ISA_MIPS2_NOT_32R6_64R6;
+def TGEI : MMRel, TEQI_FT<"tgei", GPR32Opnd>, TEQI_FM<0x8>,
+ ISA_MIPS2_NOT_32R6_64R6;
+def TGEIU : MMRel, TEQI_FT<"tgeiu", GPR32Opnd>, TEQI_FM<0x9>,
+ ISA_MIPS2_NOT_32R6_64R6;
+def TLTI : MMRel, TEQI_FT<"tlti", GPR32Opnd>, TEQI_FM<0xa>,
+ ISA_MIPS2_NOT_32R6_64R6;
+def TTLTIU : MMRel, TEQI_FT<"tltiu", GPR32Opnd>, TEQI_FM<0xb>,
+ ISA_MIPS2_NOT_32R6_64R6;
+def TNEI : MMRel, TEQI_FT<"tnei", GPR32Opnd>, TEQI_FM<0xe>,
+ ISA_MIPS2_NOT_32R6_64R6;
def BREAK : MMRel, BRK_FT<"break">, BRK_FM<0xd>;
def SYSCALL : MMRel, SYS_FT<"syscall">, SYS_FM<0xc>;
def TRAP : TrapBase<BREAK>;
-def ERET : MMRel, ER_FT<"eret">, ER_FM<0x18>;
-def DERET : MMRel, ER_FT<"deret">, ER_FM<0x1f>;
+def ERET : MMRel, ER_FT<"eret">, ER_FM<0x18>, INSN_MIPS3_32;
+def DERET : MMRel, ER_FT<"deret">, ER_FM<0x1f>, ISA_MIPS32;
-def EI : MMRel, DEI_FT<"ei", GPR32Opnd>, EI_FM<1>;
-def DI : MMRel, DEI_FT<"di", GPR32Opnd>, EI_FM<0>;
+def EI : MMRel, DEI_FT<"ei", GPR32Opnd>, EI_FM<1>, ISA_MIPS32R2;
+def DI : MMRel, DEI_FT<"di", GPR32Opnd>, EI_FM<0>, ISA_MIPS32R2;
-let Predicates = [NotInMicroMips] in {
+let EncodingPredicates = []<Predicate>, // FIXME: Lack of HasStdEnc is probably a bug
+ AdditionalPredicates = [NotInMicroMips] in {
def WAIT : WAIT_FT<"wait">, WAIT_FM;
/// Load-linked, Store-conditional
-def LL : LLBase<"ll", GPR32Opnd>, LW_FM<0x30>;
-def SC : SCBase<"sc", GPR32Opnd>, LW_FM<0x38>;
+def LL : LLBase<"ll", GPR32Opnd>, LW_FM<0x30>, ISA_MIPS2;
+def SC : SCBase<"sc", GPR32Opnd>, LW_FM<0x38>, ISA_MIPS2;
}
/// Jump and Branch Instructions
def J : MMRel, JumpFJ<jmptarget, "j", br, bb, "j">, FJ<2>,
- Requires<[RelocStatic, HasStdEnc]>, IsBranch;
+ AdditionalRequires<[RelocStatic]>, IsBranch;
def JR : MMRel, IndirectBranch<"jr", GPR32Opnd>, MTLO_FM<8>;
def BEQ : MMRel, CBranch<"beq", brtarget, seteq, GPR32Opnd>, BEQ_FM<4>;
def BNE : MMRel, CBranch<"bne", brtarget, setne, GPR32Opnd>, BEQ_FM<5>;
@@ -1056,7 +1160,7 @@ def BLTZ : MMRel, CBranchZero<"bltz", brtarget, setlt, GPR32Opnd>,
def B : UncondBranch<BEQ>;
def JAL : MMRel, JumpLink<"jal", calltarget>, FJ<3>;
-let Predicates = [NotInMicroMips, HasStdEnc] in {
+let AdditionalPredicates = [NotInMicroMips] in {
def JALR : JumpLinkReg<"jalr", GPR32Opnd>, JALR_FM;
def JALRPseudo : JumpLinkRegPseudo<GPR32Opnd, JALR, RA>;
}
@@ -1102,21 +1206,24 @@ def UDIV : MMRel, Div<"divu", II_DIVU, GPR32Opnd, [HI0, LO0]>,
def MTHI : MMRel, MoveToLOHI<"mthi", GPR32Opnd, [HI0]>, MTLO_FM<0x11>;
def MTLO : MMRel, MoveToLOHI<"mtlo", GPR32Opnd, [LO0]>, MTLO_FM<0x13>;
-let Predicates = [NotInMicroMips] in {
+let EncodingPredicates = []<Predicate>, // FIXME: Lack of HasStdEnc is probably a bug
+ AdditionalPredicates = [NotInMicroMips] in {
def MFHI : MMRel, MoveFromLOHI<"mfhi", GPR32Opnd, AC0>, MFLO_FM<0x10>;
def MFLO : MMRel, MoveFromLOHI<"mflo", GPR32Opnd, AC0>, MFLO_FM<0x12>;
}
/// Sign Ext In Register Instructions.
-def SEB : MMRel, SignExtInReg<"seb", i8, GPR32Opnd, II_SEB>, SEB_FM<0x10, 0x20>;
-def SEH : MMRel, SignExtInReg<"seh", i16, GPR32Opnd, II_SEH>, SEB_FM<0x18, 0x20>;
+def SEB : MMRel, SignExtInReg<"seb", i8, GPR32Opnd, II_SEB>,
+ SEB_FM<0x10, 0x20>, ISA_MIPS32R2;
+def SEH : MMRel, SignExtInReg<"seh", i16, GPR32Opnd, II_SEH>,
+ SEB_FM<0x18, 0x20>, ISA_MIPS32R2;
/// Count Leading
-def CLZ : MMRel, CountLeading0<"clz", GPR32Opnd>, CLO_FM<0x20>;
-def CLO : MMRel, CountLeading1<"clo", GPR32Opnd>, CLO_FM<0x21>;
+def CLZ : MMRel, CountLeading0<"clz", GPR32Opnd>, CLO_FM<0x20>, ISA_MIPS32;
+def CLO : MMRel, CountLeading1<"clo", GPR32Opnd>, CLO_FM<0x21>, ISA_MIPS32;
/// Word Swap Bytes Within Halfwords
-def WSBH : MMRel, SubwordSwap<"wsbh", GPR32Opnd>, SEB_FM<2, 0x20>;
+def WSBH : MMRel, SubwordSwap<"wsbh", GPR32Opnd>, SEB_FM<2, 0x20>, ISA_MIPS32R2;
/// No operation.
def NOP : PseudoSE<(outs), (ins), []>, PseudoInstExpansion<(SLL ZERO, ZERO, 0)>;
@@ -1128,12 +1235,12 @@ def NOP : PseudoSE<(outs), (ins), []>, PseudoInstExpansion<(SLL ZERO, ZERO, 0)>;
def LEA_ADDiu : MMRel, EffectiveAddress<"addiu", GPR32Opnd>, LW_FM<9>;
// MADD*/MSUB*
-def MADD : MMRel, MArithR<"madd", II_MADD, 1>, MULT_FM<0x1c, 0>;
-def MADDU : MMRel, MArithR<"maddu", II_MADDU, 1>, MULT_FM<0x1c, 1>;
-def MSUB : MMRel, MArithR<"msub", II_MSUB>, MULT_FM<0x1c, 4>;
-def MSUBU : MMRel, MArithR<"msubu", II_MSUBU>, MULT_FM<0x1c, 5>;
+def MADD : MMRel, MArithR<"madd", II_MADD, 1>, MULT_FM<0x1c, 0>, ISA_MIPS32;
+def MADDU : MMRel, MArithR<"maddu", II_MADDU, 1>, MULT_FM<0x1c, 1>, ISA_MIPS32;
+def MSUB : MMRel, MArithR<"msub", II_MSUB>, MULT_FM<0x1c, 4>, ISA_MIPS32;
+def MSUBU : MMRel, MArithR<"msubu", II_MSUBU>, MULT_FM<0x1c, 5>, ISA_MIPS32;
-let Predicates = [HasStdEnc, NotDSP] in {
+let AdditionalPredicates = [NotDSP] in {
def PseudoMULT : MultDivPseudo<MULT, ACC64, GPR32Opnd, MipsMult, II_MULT>;
def PseudoMULTu : MultDivPseudo<MULTu, ACC64, GPR32Opnd, MipsMultu, II_MULTU>;
def PseudoMFHI : PseudoMFLOHI<GPR32, ACC64, MipsMFHI>;
@@ -1156,8 +1263,8 @@ def EXT : MMRel, ExtBase<"ext", GPR32Opnd, uimm5, 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>, MFC3OP_FM<0x10, 0>;
-def MTC0 : MFC3OP<"mtc0", GPR32Opnd>, MFC3OP_FM<0x10, 4>;
+def MFC0 : MFC3OP<"mfc0", GPR32Opnd>, MFC3OP_FM<0x10, 0>, ISA_MIPS32;
+def MTC0 : MFC3OP<"mtc0", GPR32Opnd>, MFC3OP_FM<0x10, 4>, ISA_MIPS32;
def MFC2 : MFC3OP<"mfc2", GPR32Opnd>, MFC3OP_FM<0x12, 0>;
def MTC2 : MFC3OP<"mtc2", GPR32Opnd>, MFC3OP_FM<0x12, 4>;
@@ -1165,67 +1272,94 @@ class Barrier<string asmstr> : InstSE<(outs), (ins), asmstr, [], NoItinerary,
FrmOther>;
def SSNOP : Barrier<"ssnop">, BARRIER_FM<1>;
def EHB : Barrier<"ehb">, BARRIER_FM<3>;
-def PAUSE : Barrier<"pause">, BARRIER_FM<5>, Requires<[HasMips32r2]>;
+def PAUSE : Barrier<"pause">, BARRIER_FM<5>, ISA_MIPS32R2;
+
+class TLB<string asmstr> : InstSE<(outs), (ins), asmstr, [], NoItinerary,
+ FrmOther>;
+def TLBP : TLB<"tlbp">, COP0_TLB_FM<0x08>;
+def TLBR : TLB<"tlbr">, COP0_TLB_FM<0x01>;
+def TLBWI : TLB<"tlbwi">, COP0_TLB_FM<0x02>;
+def TLBWR : TLB<"tlbwr">, COP0_TLB_FM<0x06>;
//===----------------------------------------------------------------------===//
// Instruction aliases
//===----------------------------------------------------------------------===//
-def : InstAlias<"move $dst, $src",
- (ADDu GPR32Opnd:$dst, GPR32Opnd:$src,ZERO), 1>,
- Requires<[NotMips64, NotInMicroMips]>;
-def : InstAlias<"bal $offset", (BGEZAL ZERO, brtarget:$offset), 0>;
-def : InstAlias<"addu $rs, $rt, $imm",
- (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>;
-def : InstAlias<"add $rs, $rt, $imm",
- (ADDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>;
-def : InstAlias<"and $rs, $rt, $imm",
- (ANDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>;
-def : InstAlias<"j $rs", (JR GPR32Opnd:$rs), 0>;
+def : MipsInstAlias<"move $dst, $src",
+ (ADDu GPR32Opnd:$dst, GPR32Opnd:$src,ZERO), 1>,
+ GPR_32 {
+ let AdditionalPredicates = [NotInMicroMips];
+}
+def : MipsInstAlias<"bal $offset", (BGEZAL ZERO, brtarget:$offset), 0>;
+def : MipsInstAlias<"addu $rs, $rt, $imm",
+ (ADDiu GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>;
+def : MipsInstAlias<"add $rs, $rt, $imm",
+ (ADDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>;
+def : MipsInstAlias<"and $rs, $rt, $imm",
+ (ANDi GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>;
+def : MipsInstAlias<"j $rs", (JR GPR32Opnd:$rs), 0>;
let Predicates = [NotInMicroMips] in {
-def : InstAlias<"jalr $rs", (JALR RA, GPR32Opnd:$rs), 0>;
-}
-def : InstAlias<"jal $rs", (JALR RA, GPR32Opnd:$rs), 0>;
-def : InstAlias<"jal $rd,$rs", (JALR GPR32Opnd:$rd, GPR32Opnd:$rs), 0>;
-def : InstAlias<"not $rt, $rs",
- (NOR GPR32Opnd:$rt, GPR32Opnd:$rs, ZERO), 0>;
-def : InstAlias<"neg $rt, $rs",
- (SUB GPR32Opnd:$rt, ZERO, GPR32Opnd:$rs), 1>;
-def : InstAlias<"negu $rt, $rs",
- (SUBu GPR32Opnd:$rt, ZERO, GPR32Opnd:$rs), 1>;
-def : InstAlias<"slt $rs, $rt, $imm",
- (SLTi GPR32Opnd:$rs, GPR32Opnd:$rt, simm16:$imm), 0>;
-def : InstAlias<"xor $rs, $rt, $imm",
- (XORi GPR32Opnd:$rs, GPR32Opnd:$rt, uimm16:$imm), 0>;
-def : InstAlias<"or $rs, $rt, $imm",
- (ORi GPR32Opnd:$rs, GPR32Opnd:$rt, uimm16:$imm), 0>;
-def : InstAlias<"nop", (SLL ZERO, ZERO, 0), 1>;
-def : InstAlias<"mfc0 $rt, $rd", (MFC0 GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>;
-def : InstAlias<"mtc0 $rt, $rd", (MTC0 GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>;
-def : InstAlias<"mfc2 $rt, $rd", (MFC2 GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>;
-def : InstAlias<"mtc2 $rt, $rd", (MTC2 GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>;
-def : InstAlias<"b $offset", (BEQ ZERO, ZERO, brtarget:$offset), 0>;
-def : InstAlias<"bnez $rs,$offset",
- (BNE GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>;
-def : InstAlias<"beqz $rs,$offset",
- (BEQ GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>;
-def : InstAlias<"syscall", (SYSCALL 0), 1>;
-
-def : InstAlias<"break $imm", (BREAK uimm10:$imm, 0), 1>;
-def : InstAlias<"break", (BREAK 0, 0), 1>;
-def : InstAlias<"ei", (EI ZERO), 1>;
-def : InstAlias<"di", (DI ZERO), 1>;
-
-def : InstAlias<"teq $rs, $rt", (TEQ GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>;
-def : InstAlias<"tge $rs, $rt", (TGE GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>;
-def : InstAlias<"tgeu $rs, $rt", (TGEU GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>;
-def : InstAlias<"tlt $rs, $rt", (TLT GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>;
-def : InstAlias<"tltu $rs, $rt", (TLTU GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>;
-def : InstAlias<"tne $rs, $rt", (TNE GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>;
-def : InstAlias<"sub, $rd, $rs, $imm",
- (ADDi GPR32Opnd:$rd, GPR32Opnd:$rs, InvertedImOperand:$imm)>;
-def : InstAlias<"subu, $rd, $rs, $imm",
- (ADDiu GPR32Opnd:$rd, GPR32Opnd:$rs, InvertedImOperand:$imm)>;
-
+def : MipsInstAlias<"jalr $rs", (JALR RA, GPR32Opnd:$rs), 0>;
+}
+def : MipsInstAlias<"jal $rs", (JALR RA, GPR32Opnd:$rs), 0>;
+def : MipsInstAlias<"jal $rd,$rs", (JALR GPR32Opnd:$rd, GPR32Opnd:$rs), 0>;
+def : MipsInstAlias<"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<"or $rs, $rt, $imm",
+ (ORi GPR32Opnd:$rs, GPR32Opnd:$rt, uimm16:$imm), 0>;
+def : MipsInstAlias<"nop", (SLL ZERO, ZERO, 0), 1>;
+def : MipsInstAlias<"mfc0 $rt, $rd", (MFC0 GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>;
+def : MipsInstAlias<"mtc0 $rt, $rd", (MTC0 GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>;
+def : MipsInstAlias<"mfc2 $rt, $rd", (MFC2 GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>;
+def : MipsInstAlias<"mtc2 $rt, $rd", (MTC2 GPR32Opnd:$rt, GPR32Opnd:$rd, 0), 0>;
+def : MipsInstAlias<"b $offset", (BEQ ZERO, ZERO, brtarget:$offset), 0>;
+def : MipsInstAlias<"bnez $rs,$offset",
+ (BNE GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>;
+def : MipsInstAlias<"beqz $rs,$offset",
+ (BEQ GPR32Opnd:$rs, ZERO, brtarget:$offset), 0>;
+def : MipsInstAlias<"syscall", (SYSCALL 0), 1>;
+
+def : MipsInstAlias<"break", (BREAK 0, 0), 1>;
+def : MipsInstAlias<"break $imm", (BREAK uimm10:$imm, 0), 1>;
+def : MipsInstAlias<"ei", (EI ZERO), 1>;
+def : MipsInstAlias<"di", (DI ZERO), 1>;
+
+def : MipsInstAlias<"teq $rs, $rt", (TEQ GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>;
+def : MipsInstAlias<"tge $rs, $rt", (TGE GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>;
+def : MipsInstAlias<"tgeu $rs, $rt", (TGEU GPR32Opnd:$rs, GPR32Opnd:$rt, 0),
+ 1>;
+def : MipsInstAlias<"tlt $rs, $rt", (TLT GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>;
+def : MipsInstAlias<"tltu $rs, $rt", (TLTU GPR32Opnd:$rs, GPR32Opnd:$rt, 0),
+ 1>;
+def : MipsInstAlias<"tne $rs, $rt", (TNE GPR32Opnd:$rs, GPR32Opnd:$rt, 0), 1>;
+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>;
+def : MipsInstAlias<"sub $rs, $imm",
+ (ADDi GPR32Opnd:$rs, GPR32Opnd:$rs, InvertedImOperand:$imm),
+ 0>;
+def : MipsInstAlias<"subu, $rd, $rs, $imm",
+ (ADDiu GPR32Opnd:$rd, GPR32Opnd:$rs,
+ 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>;
//===----------------------------------------------------------------------===//
// Assembler Pseudo Instructions
//===----------------------------------------------------------------------===//
@@ -1271,7 +1405,7 @@ def : MipsPat<(i32 imm:$imm),
// Carry MipsPatterns
def : MipsPat<(subc GPR32:$lhs, GPR32:$rhs),
(SUBu GPR32:$lhs, GPR32:$rhs)>;
-let Predicates = [HasStdEnc, NotDSP] in {
+let AdditionalPredicates = [NotDSP] in {
def : MipsPat<(addc GPR32:$lhs, GPR32:$rhs),
(ADDu GPR32:$lhs, GPR32:$rhs)>;
def : MipsPat<(addc GPR32:$src, immSExt16:$imm),
@@ -1340,14 +1474,11 @@ def : MipsPat<(not GPR32:$in),
(NOR GPR32Opnd:$in, ZERO)>;
// extended loads
-let Predicates = [HasStdEnc] in {
- 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)>;
-}
+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)>;
// peepholes
-let Predicates = [HasStdEnc] in
def : MipsPat<(store (i32 0), addr:$dst), (SW ZERO, addr:$dst)>;
// brcond patterns
@@ -1441,11 +1572,9 @@ def : MipsPat<(bswap GPR32:$rt), (ROTR (WSBH GPR32:$rt), 16)>;
// Load halfword/word patterns.
let AddedComplexity = 40 in {
- let Predicates = [HasStdEnc] in {
- def : LoadRegImmPat<LBu, i32, zextloadi8>;
- def : LoadRegImmPat<LH, i32, sextloadi16>;
- def : LoadRegImmPat<LW, i32, load>;
- }
+ def : LoadRegImmPat<LBu, i32, zextloadi8>;
+ def : LoadRegImmPat<LH, i32, sextloadi16>;
+ def : LoadRegImmPat<LW, i32, load>;
}
//===----------------------------------------------------------------------===//
@@ -1456,6 +1585,9 @@ include "MipsInstrFPU.td"
include "Mips64InstrInfo.td"
include "MipsCondMov.td"
+include "Mips32r6InstrInfo.td"
+include "Mips64r6InstrInfo.td"
+
//
// Mips16
diff --git a/lib/Target/Mips/MipsJITInfo.cpp b/lib/Target/Mips/MipsJITInfo.cpp
index d76cb1d..2072488 100644
--- a/lib/Target/Mips/MipsJITInfo.cpp
+++ b/lib/Target/Mips/MipsJITInfo.cpp
@@ -11,7 +11,6 @@
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "jit"
#include "MipsJITInfo.h"
#include "MipsInstrInfo.h"
#include "MipsRelocations.h"
@@ -25,6 +24,8 @@
#include <cstdlib>
using namespace llvm;
+#define DEBUG_TYPE "jit"
+
void MipsJITInfo::replaceMachineCodeForFunction(void *Old, void *New) {
unsigned NewAddr = (intptr_t)New;
diff --git a/lib/Target/Mips/MipsJITInfo.h b/lib/Target/Mips/MipsJITInfo.h
index ecda310..c9dfd83 100644
--- a/lib/Target/Mips/MipsJITInfo.h
+++ b/lib/Target/Mips/MipsJITInfo.h
@@ -37,26 +37,26 @@ class MipsJITInfo : public TargetJITInfo {
/// overwriting OLD with a branch to NEW. This is used for self-modifying
/// code.
///
- virtual void replaceMachineCodeForFunction(void *Old, void *New);
+ void replaceMachineCodeForFunction(void *Old, void *New) override;
// getStubLayout - Returns the size and alignment of the largest call stub
// on Mips.
- virtual StubLayout getStubLayout();
+ StubLayout getStubLayout() override;
/// emitFunctionStub - Use the specified JITCodeEmitter object to emit a
/// small native function that simply calls the function at the specified
/// address.
- virtual void *emitFunctionStub(const Function *F, void *Fn,
- JITCodeEmitter &JCE);
+ void *emitFunctionStub(const Function *F, void *Fn,
+ JITCodeEmitter &JCE) override;
/// getLazyResolverFunction - Expose the lazy resolver to the JIT.
- virtual LazyResolverFn getLazyResolverFunction(JITCompilerFn);
+ LazyResolverFn getLazyResolverFunction(JITCompilerFn) override;
/// relocate - Before the JIT can run a block of code that has been emitted,
/// it must rewrite the code to contain the actual addresses of any
/// referenced global symbols.
- virtual void relocate(void *Function, MachineRelocation *MR,
- unsigned NumRelocs, unsigned char *GOTBase);
+ void relocate(void *Function, MachineRelocation *MR,
+ unsigned NumRelocs, unsigned char *GOTBase) override;
/// Initialize - Initialize internal stage for the function being JITted.
void Initialize(const MachineFunction &MF, bool isPIC,
diff --git a/lib/Target/Mips/MipsLongBranch.cpp b/lib/Target/Mips/MipsLongBranch.cpp
index 2b6a874..acfe76e 100644
--- a/lib/Target/Mips/MipsLongBranch.cpp
+++ b/lib/Target/Mips/MipsLongBranch.cpp
@@ -10,14 +10,9 @@
// This pass expands a branch or jump instruction into a long branch if its
// offset is too large to fit into its immediate field.
//
-// FIXME:
-// 1. Fix pc-region jump instructions which cross 256MB segment boundaries.
-// 2. If program has inline assembly statements whose size cannot be
-// determined accurately, load branch target addresses from the GOT.
+// FIXME: Fix pc-region jump instructions which cross 256MB segment boundaries.
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "mips-long-branch"
-
#include "Mips.h"
#include "MCTargetDesc/MipsBaseInfo.h"
#include "MipsTargetMachine.h"
@@ -33,6 +28,8 @@
using namespace llvm;
+#define DEBUG_TYPE "mips-long-branch"
+
STATISTIC(LongBranches, "Number of long branches.");
static cl::opt<bool> SkipLongBranch(
@@ -56,7 +53,7 @@ namespace {
bool HasLongBranch;
MachineInstr *Br;
- MBBInfo() : Size(0), HasLongBranch(false), Br(0) {}
+ MBBInfo() : Size(0), HasLongBranch(false), Br(nullptr) {}
};
class MipsLongBranch : public MachineFunctionPass {
@@ -67,13 +64,13 @@ namespace {
: MachineFunctionPass(ID), TM(tm),
IsPIC(TM.getRelocationModel() == Reloc::PIC_),
ABI(TM.getSubtarget<MipsSubtarget>().getTargetABI()),
- LongBranchSeqSize(!IsPIC ? 2 : (ABI == MipsSubtarget::N64 ? 13 : 9)) {}
+ LongBranchSeqSize(!IsPIC ? 2 : (ABI == MipsSubtarget::N64 ? 10 : 9)) {}
- virtual const char *getPassName() const {
+ const char *getPassName() const override {
return "Mips Long Branch";
}
- bool runOnMachineFunction(MachineFunction &F);
+ bool runOnMachineFunction(MachineFunction &F) override;
private:
void splitMBB(MachineBasicBlock *MBB);
@@ -111,7 +108,7 @@ static MachineBasicBlock *getTargetMBB(const MachineInstr &Br) {
}
assert(false && "This instruction does not have an MBB operand.");
- return 0;
+ return nullptr;
}
// Traverse the list of instructions backwards until a non-debug instruction is
@@ -267,20 +264,14 @@ void MipsLongBranch::expandToLongBranch(MBBInfo &I) {
LongBrMBB->addSuccessor(BalTgtMBB);
BalTgtMBB->addSuccessor(TgtMBB);
- int64_t TgtAddress = MBBInfos[TgtMBB->getNumber()].Address;
- unsigned BalTgtMBBSize = 5;
- int64_t Offset = TgtAddress - (I.Address + I.Size - BalTgtMBBSize * 4);
- int64_t Lo = SignExtend64<16>(Offset & 0xffff);
- int64_t Hi = SignExtend64<16>(((Offset + 0x8000) >> 16) & 0xffff);
-
if (ABI != MipsSubtarget::N64) {
// $longbr:
// addiu $sp, $sp, -8
// sw $ra, 0($sp)
- // bal $baltgt
// lui $at, %hi($tgt - $baltgt)
- // $baltgt:
+ // bal $baltgt
// addiu $at, $at, %lo($tgt - $baltgt)
+ // $baltgt:
// addu $at, $ra, $at
// lw $ra, 0($sp)
// jr $at
@@ -295,14 +286,31 @@ void MipsLongBranch::expandToLongBranch(MBBInfo &I) {
BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::SW)).addReg(Mips::RA)
.addReg(Mips::SP).addImm(0);
+ // LUi and ADDiu instructions create 32-bit offset of the target basic
+ // block from the target of BAL instruction. We cannot use immediate
+ // value for this offset because it cannot be determined accurately when
+ // the program has inline assembly statements. We therefore use the
+ // relocation expressions %hi($tgt-$baltgt) and %lo($tgt-$baltgt) which
+ // are resolved during the fixup, so the values will always be correct.
+ //
+ // Since we cannot create %hi($tgt-$baltgt) and %lo($tgt-$baltgt)
+ // expressions at this point (it is possible only at the MC layer),
+ // we replace LUi and ADDiu with pseudo instructions
+ // LONG_BRANCH_LUi and LONG_BRANCH_ADDiu, and add both basic
+ // blocks as operands to these instructions. When lowering these pseudo
+ // instructions to LUi and ADDiu in the MC layer, we will create
+ // %hi($tgt-$baltgt) and %lo($tgt-$baltgt) expressions and add them as
+ // operands to lowered instructions.
+
+ BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::LONG_BRANCH_LUi), Mips::AT)
+ .addMBB(TgtMBB).addMBB(BalTgtMBB);
MIBundleBuilder(*LongBrMBB, Pos)
.append(BuildMI(*MF, DL, TII->get(Mips::BAL_BR)).addMBB(BalTgtMBB))
- .append(BuildMI(*MF, DL, TII->get(Mips::LUi), Mips::AT).addImm(Hi));
+ .append(BuildMI(*MF, DL, TII->get(Mips::LONG_BRANCH_ADDiu), Mips::AT)
+ .addReg(Mips::AT).addMBB(TgtMBB).addMBB(BalTgtMBB));
Pos = BalTgtMBB->begin();
- BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::ADDiu), Mips::AT)
- .addReg(Mips::AT).addImm(Lo);
BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::ADDu), Mips::AT)
.addReg(Mips::RA).addReg(Mips::AT);
BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::LW), Mips::RA)
@@ -316,14 +324,11 @@ void MipsLongBranch::expandToLongBranch(MBBInfo &I) {
// $longbr:
// daddiu $sp, $sp, -16
// sd $ra, 0($sp)
- // lui64 $at, %highest($tgt - $baltgt)
- // daddiu $at, $at, %higher($tgt - $baltgt)
+ // daddiu $at, $zero, %hi($tgt - $baltgt)
// dsll $at, $at, 16
- // daddiu $at, $at, %hi($tgt - $baltgt)
// bal $baltgt
- // dsll $at, $at, 16
- // $baltgt:
// daddiu $at, $at, %lo($tgt - $baltgt)
+ // $baltgt:
// daddu $at, $ra, $at
// ld $ra, 0($sp)
// jr64 $at
@@ -331,9 +336,20 @@ void MipsLongBranch::expandToLongBranch(MBBInfo &I) {
// $fallthrough:
//
- int64_t Higher = SignExtend64<16>(((Offset + 0x80008000) >> 32) & 0xffff);
- int64_t Highest =
- SignExtend64<16>(((Offset + 0x800080008000LL) >> 48) & 0xffff);
+ // We assume the branch is within-function, and that offset is within
+ // +/- 2GB. High 32 bits will therefore always be zero.
+
+ // Note that this will work even if the offset is negative, because
+ // of the +1 modification that's added in that case. For example, if the
+ // offset is -1MB (0xFFFFFFFFFFF00000), the computation for %higher is
+ //
+ // 0xFFFFFFFFFFF00000 + 0x80008000 = 0x000000007FF08000
+ //
+ // and the bits [47:32] are zero. For %highest
+ //
+ // 0xFFFFFFFFFFF00000 + 0x800080008000 = 0x000080007FF08000
+ //
+ // and the bits [63:48] are zero.
Pos = LongBrMBB->begin();
@@ -341,24 +357,21 @@ void MipsLongBranch::expandToLongBranch(MBBInfo &I) {
.addReg(Mips::SP_64).addImm(-16);
BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::SD)).addReg(Mips::RA_64)
.addReg(Mips::SP_64).addImm(0);
- BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::LUi64), Mips::AT_64)
- .addImm(Highest);
- BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::DADDiu), Mips::AT_64)
- .addReg(Mips::AT_64).addImm(Higher);
+ BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::LONG_BRANCH_DADDiu),
+ Mips::AT_64).addReg(Mips::ZERO_64)
+ .addMBB(TgtMBB, MipsII::MO_ABS_HI).addMBB(BalTgtMBB);
BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::DSLL), Mips::AT_64)
.addReg(Mips::AT_64).addImm(16);
- BuildMI(*LongBrMBB, Pos, DL, TII->get(Mips::DADDiu), Mips::AT_64)
- .addReg(Mips::AT_64).addImm(Hi);
MIBundleBuilder(*LongBrMBB, Pos)
.append(BuildMI(*MF, DL, TII->get(Mips::BAL_BR)).addMBB(BalTgtMBB))
- .append(BuildMI(*MF, DL, TII->get(Mips::DSLL), Mips::AT_64)
- .addReg(Mips::AT_64).addImm(16));
+ .append(BuildMI(*MF, DL, TII->get(Mips::LONG_BRANCH_DADDiu),
+ Mips::AT_64).addReg(Mips::AT_64)
+ .addMBB(TgtMBB, MipsII::MO_ABS_LO)
+ .addMBB(BalTgtMBB));
Pos = BalTgtMBB->begin();
- BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::DADDiu), Mips::AT_64)
- .addReg(Mips::AT_64).addImm(Lo);
BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::DADDu), Mips::AT_64)
.addReg(Mips::RA_64).addReg(Mips::AT_64);
BuildMI(*BalTgtMBB, Pos, DL, TII->get(Mips::LD), Mips::RA_64)
@@ -370,8 +383,7 @@ void MipsLongBranch::expandToLongBranch(MBBInfo &I) {
.addReg(Mips::SP_64).addImm(16));
}
- assert(BalTgtMBBSize == BalTgtMBB->size());
- assert(LongBrMBB->size() + BalTgtMBBSize == LongBranchSeqSize);
+ assert(LongBrMBB->size() + BalTgtMBB->size() == LongBranchSeqSize);
} else {
// $longbr:
// j $tgt
diff --git a/lib/Target/Mips/MipsMCInstLower.cpp b/lib/Target/Mips/MipsMCInstLower.cpp
index 7c9a9ed..821392e 100644
--- a/lib/Target/Mips/MipsMCInstLower.cpp
+++ b/lib/Target/Mips/MipsMCInstLower.cpp
@@ -151,7 +151,75 @@ MCOperand MipsMCInstLower::LowerOperand(const MachineOperand &MO,
return MCOperand();
}
+MCOperand MipsMCInstLower::createSub(MachineBasicBlock *BB1,
+ MachineBasicBlock *BB2,
+ MCSymbolRefExpr::VariantKind Kind) const {
+ const MCSymbolRefExpr *Sym1 = MCSymbolRefExpr::Create(BB1->getSymbol(), *Ctx);
+ const MCSymbolRefExpr *Sym2 = MCSymbolRefExpr::Create(BB2->getSymbol(), *Ctx);
+ const MCBinaryExpr *Sub = MCBinaryExpr::CreateSub(Sym1, Sym2, *Ctx);
+
+ return MCOperand::CreateExpr(MipsMCExpr::Create(Kind, Sub, *Ctx));
+}
+
+void MipsMCInstLower::
+lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const {
+ OutMI.setOpcode(Mips::LUi);
+
+ // Lower register operand.
+ OutMI.addOperand(LowerOperand(MI->getOperand(0)));
+
+ // Create %hi($tgt-$baltgt).
+ OutMI.addOperand(createSub(MI->getOperand(1).getMBB(),
+ MI->getOperand(2).getMBB(),
+ MCSymbolRefExpr::VK_Mips_ABS_HI));
+}
+
+void MipsMCInstLower::
+lowerLongBranchADDiu(const MachineInstr *MI, MCInst &OutMI, int Opcode,
+ MCSymbolRefExpr::VariantKind Kind) const {
+ OutMI.setOpcode(Opcode);
+
+ // Lower two register operands.
+ for (unsigned I = 0, E = 2; I != E; ++I) {
+ const MachineOperand &MO = MI->getOperand(I);
+ OutMI.addOperand(LowerOperand(MO));
+ }
+
+ // Create %lo($tgt-$baltgt) or %hi($tgt-$baltgt).
+ OutMI.addOperand(createSub(MI->getOperand(2).getMBB(),
+ MI->getOperand(3).getMBB(), Kind));
+}
+
+bool MipsMCInstLower::lowerLongBranch(const MachineInstr *MI,
+ MCInst &OutMI) const {
+ switch (MI->getOpcode()) {
+ default:
+ return false;
+ case Mips::LONG_BRANCH_LUi:
+ lowerLongBranchLUi(MI, OutMI);
+ return true;
+ case Mips::LONG_BRANCH_ADDiu:
+ lowerLongBranchADDiu(MI, OutMI, Mips::ADDiu,
+ MCSymbolRefExpr::VK_Mips_ABS_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);
+ else if (TargetFlags == MipsII::MO_ABS_LO)
+ lowerLongBranchADDiu(MI, OutMI, Mips::DADDiu,
+ MCSymbolRefExpr::VK_Mips_ABS_LO);
+ else
+ report_fatal_error("Unexpected flags for LONG_BRANCH_DADDiu");
+ return true;
+ }
+}
+
void MipsMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
+ if (lowerLongBranch(MI, OutMI))
+ return;
+
OutMI.setOpcode(MI->getOpcode());
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
diff --git a/lib/Target/Mips/MipsMCInstLower.h b/lib/Target/Mips/MipsMCInstLower.h
index 4570bd9..269190f 100644
--- a/lib/Target/Mips/MipsMCInstLower.h
+++ b/lib/Target/Mips/MipsMCInstLower.h
@@ -9,6 +9,7 @@
#ifndef MIPSMCINSTLOWER_H
#define MIPSMCINSTLOWER_H
+#include "MCTargetDesc/MipsMCExpr.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/Support/Compiler.h"
@@ -36,6 +37,13 @@ public:
private:
MCOperand LowerSymbolOperand(const MachineOperand &MO,
MachineOperandType MOTy, unsigned Offset) const;
+ MCOperand createSub(MachineBasicBlock *BB1, MachineBasicBlock *BB2,
+ MCSymbolRefExpr::VariantKind Kind) const;
+ void lowerLongBranchLUi(const MachineInstr *MI, MCInst &OutMI) const;
+ void lowerLongBranchADDiu(const MachineInstr *MI, MCInst &OutMI,
+ int Opcode,
+ MCSymbolRefExpr::VariantKind 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 5722c6c..285bb14 100644
--- a/lib/Target/Mips/MipsMSAInstrInfo.td
+++ b/lib/Target/Mips/MipsMSAInstrInfo.td
@@ -65,10 +65,6 @@ def MipsVExtractZExt : SDNode<"MipsISD::VEXTRACT_ZEXT_ELT",
// Operands
-def uimm2 : Operand<i32> {
- let PrintMethod = "printUnsignedImm";
-}
-
// The immediate of an LSA instruction needs special handling
// as the encoded value should be subtracted by one.
def uimm2LSAAsmOperand : AsmOperandClass {
@@ -84,10 +80,6 @@ def LSAImm : Operand<i32> {
let ParserMatchClass = uimm2LSAAsmOperand;
}
-def uimm3 : Operand<i32> {
- let PrintMethod = "printUnsignedImm8";
-}
-
def uimm4 : Operand<i32> {
let PrintMethod = "printUnsignedImm8";
}
@@ -1505,6 +1497,15 @@ class MSA_INSERT_PSEUDO_BASE<SDPatternOperator OpNode, ValueType Ty,
string Constraints = "$wd = $wd_in";
}
+class MSA_INSERT_VIDX_PSEUDO_BASE<SDPatternOperator OpNode, ValueType Ty,
+ RegisterOperand ROWD, RegisterOperand ROFS> :
+ MSAPseudo<(outs ROWD:$wd), (ins ROWD:$wd_in, GPR32Opnd:$n, ROFS:$fs),
+ [(set ROWD:$wd, (OpNode (Ty ROWD:$wd_in), ROFS:$fs,
+ GPR32Opnd:$n))]> {
+ bit usesCustomInserter = 1;
+ string Constraints = "$wd = $wd_in";
+}
+
class MSA_INSVE_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
RegisterOperand ROWD, RegisterOperand ROWS = ROWD,
InstrItinClass itin = NoItinerary> {
@@ -2300,11 +2301,25 @@ class INSERT_W_DESC : MSA_INSERT_DESC_BASE<"insert.w", vinsert_v4i32,
class INSERT_D_DESC : MSA_INSERT_DESC_BASE<"insert.d", vinsert_v2i64,
MSA128DOpnd, GPR64Opnd>;
+class INSERT_B_VIDX_PSEUDO_DESC :
+ MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v16i8, MSA128BOpnd, GPR32Opnd>;
+class INSERT_H_VIDX_PSEUDO_DESC :
+ MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v8i16, MSA128HOpnd, GPR32Opnd>;
+class INSERT_W_VIDX_PSEUDO_DESC :
+ MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v4i32, MSA128WOpnd, GPR32Opnd>;
+class INSERT_D_VIDX_PSEUDO_DESC :
+ MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v2i64, MSA128DOpnd, GPR64Opnd>;
+
class INSERT_FW_PSEUDO_DESC : MSA_INSERT_PSEUDO_BASE<vector_insert, v4f32,
MSA128WOpnd, FGR32Opnd>;
class INSERT_FD_PSEUDO_DESC : MSA_INSERT_PSEUDO_BASE<vector_insert, v2f64,
MSA128DOpnd, FGR64Opnd>;
+class INSERT_FW_VIDX_PSEUDO_DESC :
+ MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v4f32, MSA128WOpnd, FGR32Opnd>;
+class INSERT_FD_VIDX_PSEUDO_DESC :
+ MSA_INSERT_VIDX_PSEUDO_BASE<vector_insert, v2f64, MSA128DOpnd, FGR64Opnd>;
+
class INSVE_B_DESC : MSA_INSVE_DESC_BASE<"insve.b", insve_v16i8,
MSA128BOpnd>;
class INSVE_H_DESC : MSA_INSVE_DESC_BASE<"insve.h", insve_v8i16,
@@ -3214,6 +3229,13 @@ let DecoderMethod = "DecodeINSVE_DF" in {
def INSERT_FW_PSEUDO : INSERT_FW_PSEUDO_DESC;
def INSERT_FD_PSEUDO : INSERT_FD_PSEUDO_DESC;
+def INSERT_B_VIDX_PSEUDO : INSERT_B_VIDX_PSEUDO_DESC;
+def INSERT_H_VIDX_PSEUDO : INSERT_H_VIDX_PSEUDO_DESC;
+def INSERT_W_VIDX_PSEUDO : INSERT_W_VIDX_PSEUDO_DESC;
+def INSERT_D_VIDX_PSEUDO : INSERT_D_VIDX_PSEUDO_DESC;
+def INSERT_FW_VIDX_PSEUDO : INSERT_FW_VIDX_PSEUDO_DESC;
+def INSERT_FD_VIDX_PSEUDO : INSERT_FD_VIDX_PSEUDO_DESC;
+
def LD_B: LD_B_ENC, LD_B_DESC;
def LD_H: LD_H_ENC, LD_H_DESC;
def LD_W: LD_W_ENC, LD_W_DESC;
@@ -3731,3 +3753,55 @@ def SZ_D_PSEUDO : MSA_CBRANCH_PSEUDO_DESC_BASE<MipsVAllZero, v2i64,
MSA128D, NoItinerary>;
def SZ_V_PSEUDO : MSA_CBRANCH_PSEUDO_DESC_BASE<MipsVAnyZero, v16i8,
MSA128B, NoItinerary>;
+
+// Vector extraction with variable index
+def : MSAPat<(i32 (vextract_sext_i8 v16i8:$ws, i32:$idx)),
+ (SRA (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG (SPLAT_B v16i8:$ws,
+ i32:$idx),
+ sub_lo)),
+ GPR32), (i32 24))>;
+def : MSAPat<(i32 (vextract_sext_i16 v8i16:$ws, i32:$idx)),
+ (SRA (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG (SPLAT_H v8i16:$ws,
+ i32:$idx),
+ sub_lo)),
+ GPR32), (i32 16))>;
+def : MSAPat<(i32 (vextract_sext_i32 v4i32:$ws, i32:$idx)),
+ (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG (SPLAT_W v4i32:$ws,
+ i32:$idx),
+ sub_lo)),
+ GPR32)>;
+def : MSAPat<(i64 (vextract_sext_i64 v2i64:$ws, i32:$idx)),
+ (COPY_TO_REGCLASS (i64 (EXTRACT_SUBREG (SPLAT_D v2i64:$ws,
+ i32:$idx),
+ sub_64)),
+ GPR64), [HasMSA, IsGP64bit]>;
+
+def : MSAPat<(i32 (vextract_zext_i8 v16i8:$ws, i32:$idx)),
+ (SRL (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG (SPLAT_B v16i8:$ws,
+ i32:$idx),
+ sub_lo)),
+ GPR32), (i32 24))>;
+def : MSAPat<(i32 (vextract_zext_i16 v8i16:$ws, i32:$idx)),
+ (SRL (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG (SPLAT_H v8i16:$ws,
+ i32:$idx),
+ sub_lo)),
+ GPR32), (i32 16))>;
+def : MSAPat<(i32 (vextract_zext_i32 v4i32:$ws, i32:$idx)),
+ (COPY_TO_REGCLASS (i32 (EXTRACT_SUBREG (SPLAT_W v4i32:$ws,
+ i32:$idx),
+ sub_lo)),
+ GPR32)>;
+def : MSAPat<(i64 (vextract_zext_i64 v2i64:$ws, i32:$idx)),
+ (COPY_TO_REGCLASS (i64 (EXTRACT_SUBREG (SPLAT_D v2i64:$ws,
+ i32:$idx),
+ sub_64)),
+ GPR64), [HasMSA, IsGP64bit]>;
+
+def : MSAPat<(f32 (vector_extract v4f32:$ws, i32:$idx)),
+ (f32 (EXTRACT_SUBREG (SPLAT_W v4f32:$ws,
+ i32:$idx),
+ sub_lo))>;
+def : MSAPat<(f64 (vector_extract v2f64:$ws, i32:$idx)),
+ (f64 (EXTRACT_SUBREG (SPLAT_D v2f64:$ws,
+ i32:$idx),
+ sub_64))>;
diff --git a/lib/Target/Mips/MipsMachineFunction.cpp b/lib/Target/Mips/MipsMachineFunction.cpp
index dedf802..e30302e 100644
--- a/lib/Target/Mips/MipsMachineFunction.cpp
+++ b/lib/Target/Mips/MipsMachineFunction.cpp
@@ -27,7 +27,7 @@ FixGlobalBaseReg("mips-fix-global-base-reg", cl::Hidden, cl::init(true),
MipsCallEntry::MipsCallEntry(const StringRef &N) {
#ifndef NDEBUG
Name = N;
- Val = 0;
+ Val = nullptr;
#endif
}
@@ -65,9 +65,8 @@ MipsFunctionInfo::~MipsFunctionInfo() {
++I)
delete I->getValue();
- for (ValueMap<const GlobalValue *, const MipsCallEntry *>::iterator
- I = GlobalCallEntries.begin(), E = GlobalCallEntries.end(); I != E; ++I)
- delete I->second;
+ for (const auto &Entry : GlobalCallEntries)
+ delete Entry.second;
}
bool MipsFunctionInfo::globalBaseRegSet() const {
diff --git a/lib/Target/Mips/MipsMachineFunction.h b/lib/Target/Mips/MipsMachineFunction.h
index 3e14c8c..e9101cc 100644
--- a/lib/Target/Mips/MipsMachineFunction.h
+++ b/lib/Target/Mips/MipsMachineFunction.h
@@ -37,12 +37,12 @@ class MipsCallEntry : public PseudoSourceValue {
public:
explicit MipsCallEntry(const StringRef &N);
explicit MipsCallEntry(const GlobalValue *V);
- virtual bool isConstant(const MachineFrameInfo *) const;
- virtual bool isAliased(const MachineFrameInfo *) const;
- virtual bool mayAlias(const MachineFrameInfo *) const;
+ bool isConstant(const MachineFrameInfo *) const override;
+ bool isAliased(const MachineFrameInfo *) const override;
+ bool mayAlias(const MachineFrameInfo *) const override;
private:
- virtual void printCustom(raw_ostream &O) const;
+ void printCustom(raw_ostream &O) const override;
#ifndef NDEBUG
std::string Name;
const GlobalValue *Val;
diff --git a/lib/Target/Mips/MipsModuleISelDAGToDAG.cpp b/lib/Target/Mips/MipsModuleISelDAGToDAG.cpp
index c6abf17..03c76ea 100644
--- a/lib/Target/Mips/MipsModuleISelDAGToDAG.cpp
+++ b/lib/Target/Mips/MipsModuleISelDAGToDAG.cpp
@@ -14,6 +14,8 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
+#define DEBUG_TYPE "mips-isel"
+
namespace llvm {
bool MipsModuleDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
diff --git a/lib/Target/Mips/MipsModuleISelDAGToDAG.h b/lib/Target/Mips/MipsModuleISelDAGToDAG.h
index fda35ae..a96862a 100644
--- a/lib/Target/Mips/MipsModuleISelDAGToDAG.h
+++ b/lib/Target/Mips/MipsModuleISelDAGToDAG.h
@@ -41,15 +41,11 @@ public:
TM(TM_), Subtarget(TM.getSubtarget<MipsSubtarget>()) {}
// Pass Name
- virtual const char *getPassName() const {
+ const char *getPassName() const override {
return "MIPS DAG->DAG Pattern Instruction Selection";
}
- virtual bool runOnMachineFunction(MachineFunction &MF);
-
- virtual SDNode *Select(SDNode *N) {
- llvm_unreachable("unexpected");
- }
+ bool runOnMachineFunction(MachineFunction &MF) override;
protected:
/// Keep a pointer to the MipsSubtarget around so that we can make the right
diff --git a/lib/Target/Mips/MipsOptimizePICCall.cpp b/lib/Target/Mips/MipsOptimizePICCall.cpp
index db270f3..c234049 100644
--- a/lib/Target/Mips/MipsOptimizePICCall.cpp
+++ b/lib/Target/Mips/MipsOptimizePICCall.cpp
@@ -12,8 +12,6 @@
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "optimize-mips-pic-call"
-
#include "Mips.h"
#include "MCTargetDesc/MipsBaseInfo.h"
#include "MipsMachineFunction.h"
@@ -25,6 +23,8 @@
using namespace llvm;
+#define DEBUG_TYPE "optimize-mips-pic-call"
+
static cl::opt<bool> LoadTargetFromGOT("mips-load-target-from-got",
cl::init(true),
cl::desc("Load target address from GOT"),
@@ -35,11 +35,13 @@ static cl::opt<bool> EraseGPOpnd("mips-erase-gp-opnd",
cl::Hidden);
namespace {
+typedef PointerUnion<const Value *, const PseudoSourceValue *> ValueType;
+
typedef std::pair<unsigned, unsigned> CntRegP;
typedef RecyclingAllocator<BumpPtrAllocator,
- ScopedHashTableVal<const Value *, CntRegP> >
+ ScopedHashTableVal<ValueType, CntRegP> >
AllocatorTy;
-typedef ScopedHashTable<const Value *, CntRegP, DenseMapInfo<const Value *>,
+typedef ScopedHashTable<ValueType, CntRegP, DenseMapInfo<ValueType>,
AllocatorTy> ScopedHTType;
class MBBInfo {
@@ -59,11 +61,11 @@ class OptimizePICCall : public MachineFunctionPass {
public:
OptimizePICCall(TargetMachine &tm) : MachineFunctionPass(ID) {}
- virtual const char *getPassName() const { return "Mips OptimizePICCall"; }
+ const char *getPassName() const override { return "Mips OptimizePICCall"; }
- bool runOnMachineFunction(MachineFunction &F);
+ bool runOnMachineFunction(MachineFunction &F) override;
- void getAnalysisUsage(AnalysisUsage &AU) const {
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.addRequired<MachineDominatorTree>();
MachineFunctionPass::getAnalysisUsage(AU);
}
@@ -78,18 +80,18 @@ private:
/// and the underlying object in Reg and Val respectively, if the function's
/// address can be resolved lazily.
bool isCallViaRegister(MachineInstr &MI, unsigned &Reg,
- const Value *&Val) const;
+ ValueType &Val) const;
/// \brief Return the number of instructions that dominate the current
/// instruction and load the function address from object Entry.
- unsigned getCount(const Value *Entry);
+ unsigned getCount(ValueType Entry);
/// \brief Return the destination virtual register of the last instruction
/// that loads from object Entry.
- unsigned getReg(const Value *Entry);
+ unsigned getReg(ValueType Entry);
/// \brief Update ScopedHT.
- void incCntAndSetReg(const Value *Entry, unsigned Reg);
+ void incCntAndSetReg(ValueType Entry, unsigned Reg);
ScopedHTType ScopedHT;
static char ID;
@@ -101,13 +103,13 @@ char OptimizePICCall::ID = 0;
/// Return the first MachineOperand of MI if it is a used virtual register.
static MachineOperand *getCallTargetRegOpnd(MachineInstr &MI) {
if (MI.getNumOperands() == 0)
- return 0;
+ return nullptr;
MachineOperand &MO = MI.getOperand(0);
if (!MO.isReg() || !MO.isUse() ||
!TargetRegisterInfo::isVirtualRegister(MO.getReg()))
- return 0;
+ return nullptr;
return &MO;
}
@@ -153,10 +155,10 @@ static void eraseGPOpnd(MachineInstr &MI) {
}
}
- llvm_unreachable(0);
+ llvm_unreachable(nullptr);
}
-MBBInfo::MBBInfo(MachineDomTreeNode *N) : Node(N), HTScope(0) {}
+MBBInfo::MBBInfo(MachineDomTreeNode *N) : Node(N), HTScope(nullptr) {}
const MachineDomTreeNode *MBBInfo::getNode() const { return Node; }
@@ -210,7 +212,7 @@ bool OptimizePICCall::visitNode(MBBInfo &MBBI) {
for (MachineBasicBlock::iterator I = MBB->begin(), E = MBB->end(); I != E;
++I) {
unsigned Reg;
- const Value *Entry;
+ ValueType Entry;
// Skip instructions that are not call instructions via registers.
if (!isCallViaRegister(*I, Reg, Entry))
@@ -242,7 +244,7 @@ bool OptimizePICCall::visitNode(MBBInfo &MBBI) {
}
bool OptimizePICCall::isCallViaRegister(MachineInstr &MI, unsigned &Reg,
- const Value *&Val) const {
+ ValueType &Val) const {
if (!MI.isCall())
return false;
@@ -254,7 +256,7 @@ bool OptimizePICCall::isCallViaRegister(MachineInstr &MI, unsigned &Reg,
// Get the instruction that loads the function address from the GOT.
Reg = MO->getReg();
- Val = 0;
+ Val = (Value*)nullptr;
MachineRegisterInfo &MRI = MI.getParent()->getParent()->getRegInfo();
MachineInstr *DefMI = MRI.getVRegDef(Reg);
@@ -273,20 +275,22 @@ bool OptimizePICCall::isCallViaRegister(MachineInstr &MI, unsigned &Reg,
// Return the underlying object for the GOT entry in Val.
assert(DefMI->hasOneMemOperand());
Val = (*DefMI->memoperands_begin())->getValue();
+ if (!Val)
+ Val = (*DefMI->memoperands_begin())->getPseudoValue();
return true;
}
-unsigned OptimizePICCall::getCount(const Value *Entry) {
+unsigned OptimizePICCall::getCount(ValueType Entry) {
return ScopedHT.lookup(Entry).first;
}
-unsigned OptimizePICCall::getReg(const Value *Entry) {
+unsigned OptimizePICCall::getReg(ValueType Entry) {
unsigned Reg = ScopedHT.lookup(Entry).second;
assert(Reg);
return Reg;
}
-void OptimizePICCall::incCntAndSetReg(const Value *Entry, unsigned Reg) {
+void OptimizePICCall::incCntAndSetReg(ValueType Entry, unsigned Reg) {
CntRegP P = ScopedHT.lookup(Entry);
ScopedHT.insert(Entry, std::make_pair(P.first + 1, Reg));
}
diff --git a/lib/Target/Mips/MipsOs16.cpp b/lib/Target/Mips/MipsOs16.cpp
index fe60841..7aae964 100644
--- a/lib/Target/Mips/MipsOs16.cpp
+++ b/lib/Target/Mips/MipsOs16.cpp
@@ -11,13 +11,14 @@
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "mips-os16"
#include "MipsOs16.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
+#define DEBUG_TYPE "mips-os16"
+
static cl::opt<std::string> Mips32FunctionMask(
"mips32-function-mask",
diff --git a/lib/Target/Mips/MipsOs16.h b/lib/Target/Mips/MipsOs16.h
index 21beef8..55e5a81 100644
--- a/lib/Target/Mips/MipsOs16.h
+++ b/lib/Target/Mips/MipsOs16.h
@@ -34,11 +34,11 @@ public:
}
- virtual const char *getPassName() const {
+ const char *getPassName() const override {
return "MIPS Os16 Optimization";
}
- virtual bool runOnModule(Module &M);
+ bool runOnModule(Module &M) override;
};
diff --git a/lib/Target/Mips/MipsRegisterInfo.cpp b/lib/Target/Mips/MipsRegisterInfo.cpp
index d7fc93b..83d25ab 100644
--- a/lib/Target/Mips/MipsRegisterInfo.cpp
+++ b/lib/Target/Mips/MipsRegisterInfo.cpp
@@ -11,8 +11,6 @@
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "mips-reg-info"
-
#include "MipsRegisterInfo.h"
#include "Mips.h"
#include "MipsAnalyzeImmediate.h"
@@ -37,11 +35,13 @@
#include "llvm/Target/TargetMachine.h"
#include "llvm/Target/TargetOptions.h"
+using namespace llvm;
+
+#define DEBUG_TYPE "mips-reg-info"
+
#define GET_REGINFO_TARGET_DESC
#include "MipsGenRegisterInfo.inc"
-using namespace llvm;
-
MipsRegisterInfo::MipsRegisterInfo(const MipsSubtarget &ST)
: MipsGenRegisterInfo(Mips::RA), Subtarget(ST) {}
@@ -79,8 +79,8 @@ MipsRegisterInfo::getRegPressureLimit(const TargetRegisterClass *RC,
//===----------------------------------------------------------------------===//
/// Mips Callee Saved Registers
-const uint16_t* MipsRegisterInfo::
-getCalleeSavedRegs(const MachineFunction *MF) const {
+const MCPhysReg *
+MipsRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
if (Subtarget.isSingleFloat())
return CSR_SingleFloatOnly_SaveList;
@@ -119,11 +119,11 @@ const uint32_t *MipsRegisterInfo::getMips16RetHelperMask() {
BitVector MipsRegisterInfo::
getReservedRegs(const MachineFunction &MF) const {
- static const uint16_t ReservedGPR32[] = {
+ static const MCPhysReg ReservedGPR32[] = {
Mips::ZERO, Mips::K0, Mips::K1, Mips::SP
};
- static const uint16_t ReservedGPR64[] = {
+ static const MCPhysReg ReservedGPR64[] = {
Mips::ZERO_64, Mips::K0_64, Mips::K1_64, Mips::SP_64
};
diff --git a/lib/Target/Mips/MipsRegisterInfo.h b/lib/Target/Mips/MipsRegisterInfo.h
index 0450c6f..b34496f 100644
--- a/lib/Target/Mips/MipsRegisterInfo.h
+++ b/lib/Target/Mips/MipsRegisterInfo.h
@@ -43,30 +43,31 @@ public:
/// Code Generation virtual methods...
const TargetRegisterClass *getPointerRegClass(const MachineFunction &MF,
- unsigned Kind) const;
+ unsigned Kind) const override;
unsigned getRegPressureLimit(const TargetRegisterClass *RC,
- MachineFunction &MF) const;
- const uint16_t *getCalleeSavedRegs(const MachineFunction *MF = 0) const;
- const uint32_t *getCallPreservedMask(CallingConv::ID) const;
+ MachineFunction &MF) const override;
+ const MCPhysReg *
+ getCalleeSavedRegs(const MachineFunction *MF = nullptr) const override;
+ const uint32_t *getCallPreservedMask(CallingConv::ID) const override;
static const uint32_t *getMips16RetHelperMask();
- BitVector getReservedRegs(const MachineFunction &MF) const;
+ BitVector getReservedRegs(const MachineFunction &MF) const override;
- virtual bool requiresRegisterScavenging(const MachineFunction &MF) const;
+ bool requiresRegisterScavenging(const MachineFunction &MF) const override;
- virtual bool trackLivenessAfterRegAlloc(const MachineFunction &MF) const;
+ bool trackLivenessAfterRegAlloc(const MachineFunction &MF) const override;
/// Stack Frame Processing Methods
void eliminateFrameIndex(MachineBasicBlock::iterator II,
int SPAdj, unsigned FIOperandNum,
- RegScavenger *RS = NULL) const;
+ RegScavenger *RS = nullptr) const override;
void processFunctionBeforeFrameFinalized(MachineFunction &MF,
- RegScavenger *RS = NULL) const;
+ RegScavenger *RS = nullptr) const;
/// Debug information queries.
- unsigned getFrameRegister(const MachineFunction &MF) const;
+ unsigned getFrameRegister(const MachineFunction &MF) const override;
/// \brief Return GPR register class.
virtual const TargetRegisterClass *intRegClass(unsigned Size) const = 0;
diff --git a/lib/Target/Mips/MipsRegisterInfo.td b/lib/Target/Mips/MipsRegisterInfo.td
index 834e6c5..875a596 100644
--- a/lib/Target/Mips/MipsRegisterInfo.td
+++ b/lib/Target/Mips/MipsRegisterInfo.td
@@ -205,6 +205,10 @@ let Namespace = "Mips" in {
foreach I = 0-31 in
def COP2#I : MipsReg<#I, ""#I>;
+ // COP3 registers.
+ foreach I = 0-31 in
+ def COP3#I : MipsReg<#I, ""#I>;
+
// PC register
def PC : Register<"pc">;
@@ -387,6 +391,10 @@ def DSPCC : RegisterClass<"Mips", [v4i8, v2i16], 32, (add DSPCCond)>;
def COP2 : RegisterClass<"Mips", [i32], 32, (sequence "COP2%u", 0, 31)>,
Unallocatable;
+// Coprocessor 3 registers.
+def COP3 : RegisterClass<"Mips", [i32], 32, (sequence "COP3%u", 0, 31)>,
+ Unallocatable;
+
// Octeon multiplier and product registers
def OCTEON_MPL : RegisterClass<"Mips", [i64], 64, (add MPL0, MPL1, MPL2)>,
Unallocatable;
@@ -484,6 +492,10 @@ def COP2AsmOperand : MipsAsmRegOperand {
let Name = "COP2AsmReg";
}
+def COP3AsmOperand : MipsAsmRegOperand {
+ let Name = "COP3AsmReg";
+}
+
def HWRegsOpnd : RegisterOperand<HWRegs> {
let ParserMatchClass = HWRegsAsmOperand;
}
@@ -524,6 +536,10 @@ def COP2Opnd : RegisterOperand<COP2> {
let ParserMatchClass = COP2AsmOperand;
}
+def COP3Opnd : RegisterOperand<COP3> {
+ let ParserMatchClass = COP3AsmOperand;
+}
+
def MSA128BOpnd : RegisterOperand<MSA128B> {
let ParserMatchClass = MSA128AsmOperand;
}
diff --git a/lib/Target/Mips/MipsSEFrameLowering.cpp b/lib/Target/Mips/MipsSEFrameLowering.cpp
index 0343a47..6ad5821 100644
--- a/lib/Target/Mips/MipsSEFrameLowering.cpp
+++ b/lib/Target/Mips/MipsSEFrameLowering.cpp
@@ -375,7 +375,8 @@ void MipsSEFrameLowering::emitPrologue(MachineFunction &MF) const {
// if framepointer enabled, set it to point to the stack pointer.
if (hasFP(MF)) {
// Insert instruction "move $fp, $sp" at this location.
- BuildMI(MBB, MBBI, dl, TII.get(ADDu), FP).addReg(SP).addReg(ZERO);
+ BuildMI(MBB, MBBI, dl, TII.get(ADDu), FP).addReg(SP).addReg(ZERO)
+ .setMIFlag(MachineInstr::FrameSetup);
// emit ".cfi_def_cfa_register $fp"
unsigned CFIIndex = MMI.addFrameInst(MCCFIInstruction::createDefCfaRegister(
diff --git a/lib/Target/Mips/MipsSEFrameLowering.h b/lib/Target/Mips/MipsSEFrameLowering.h
index 8fa9e46..5d2801f 100644
--- a/lib/Target/Mips/MipsSEFrameLowering.h
+++ b/lib/Target/Mips/MipsSEFrameLowering.h
@@ -25,22 +25,22 @@ public:
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
/// the function.
- void emitPrologue(MachineFunction &MF) const;
- void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
+ void emitPrologue(MachineFunction &MF) const override;
+ void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override;
void eliminateCallFramePseudoInstr(MachineFunction &MF,
- MachineBasicBlock &MBB,
- MachineBasicBlock::iterator I) const;
+ MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator I) const override;
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB,
MachineBasicBlock::iterator MI,
const std::vector<CalleeSavedInfo> &CSI,
- const TargetRegisterInfo *TRI) const;
+ const TargetRegisterInfo *TRI) const override;
- bool hasReservedCallFrame(const MachineFunction &MF) const;
+ bool hasReservedCallFrame(const MachineFunction &MF) const override;
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
- RegScavenger *RS) const;
+ RegScavenger *RS) const override;
unsigned ehDataReg(unsigned I) const;
};
diff --git a/lib/Target/Mips/MipsSEISelDAGToDAG.cpp b/lib/Target/Mips/MipsSEISelDAGToDAG.cpp
index 5b20a6c..d5385be 100644
--- a/lib/Target/Mips/MipsSEISelDAGToDAG.cpp
+++ b/lib/Target/Mips/MipsSEISelDAGToDAG.cpp
@@ -11,7 +11,6 @@
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "mips-isel"
#include "MipsSEISelDAGToDAG.h"
#include "MCTargetDesc/MipsBaseInfo.h"
#include "Mips.h"
@@ -35,6 +34,8 @@
#include "llvm/Target/TargetMachine.h"
using namespace llvm;
+#define DEBUG_TYPE "mips-isel"
+
bool MipsSEDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
if (Subtarget.inMips16Mode())
return false;
@@ -412,7 +413,7 @@ bool MipsSEDAGToDAGISel::selectVSplat(SDNode *N, APInt &Imm) const {
BuildVectorSDNode *Node = dyn_cast<BuildVectorSDNode>(N);
- if (Node == NULL)
+ if (!Node)
return false;
APInt SplatValue, SplatUndef;
@@ -813,16 +814,16 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) {
EVT ViaVecTy;
if (!Subtarget.hasMSA() || !BVN->getValueType(0).is128BitVector())
- return std::make_pair(false, (SDNode*)NULL);
+ return std::make_pair(false, nullptr);
if (!BVN->isConstantSplat(SplatValue, SplatUndef, SplatBitSize,
HasAnyUndefs, 8,
!Subtarget.isLittle()))
- return std::make_pair(false, (SDNode*)NULL);
+ return std::make_pair(false, nullptr);
switch (SplatBitSize) {
default:
- return std::make_pair(false, (SDNode*)NULL);
+ return std::make_pair(false, nullptr);
case 8:
LdiOp = Mips::LDI_B;
ViaVecTy = MVT::v16i8;
@@ -842,7 +843,7 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) {
}
if (!SplatValue.isSignedIntN(10))
- return std::make_pair(false, (SDNode*)NULL);
+ return std::make_pair(false, nullptr);
SDValue Imm = CurDAG->getTargetConstant(SplatValue,
ViaVecTy.getVectorElementType());
@@ -868,7 +869,7 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) {
}
- return std::make_pair(false, (SDNode*)NULL);
+ return std::make_pair(false, nullptr);
}
FunctionPass *llvm::createMipsSEISelDag(MipsTargetMachine &TM) {
diff --git a/lib/Target/Mips/MipsSEISelDAGToDAG.h b/lib/Target/Mips/MipsSEISelDAGToDAG.h
index ba84a6d..57328d2 100644
--- a/lib/Target/Mips/MipsSEISelDAGToDAG.h
+++ b/lib/Target/Mips/MipsSEISelDAGToDAG.h
@@ -25,7 +25,7 @@ public:
private:
- virtual bool runOnMachineFunction(MachineFunction &MF);
+ bool runOnMachineFunction(MachineFunction &MF) override;
void addDSPCtrlRegOperands(bool IsDef, MachineInstr &MI,
MachineFunction &MF);
@@ -44,66 +44,66 @@ private:
bool selectAddrFrameIndexOffset(SDValue Addr, SDValue &Base, SDValue &Offset,
unsigned OffsetBits) const;
- virtual bool selectAddrRegImm(SDValue Addr, SDValue &Base,
- SDValue &Offset) const;
+ bool selectAddrRegImm(SDValue Addr, SDValue &Base,
+ SDValue &Offset) const override;
- virtual bool selectAddrRegReg(SDValue Addr, SDValue &Base,
- SDValue &Offset) const;
+ bool selectAddrRegReg(SDValue Addr, SDValue &Base,
+ SDValue &Offset) const override;
- virtual bool selectAddrDefault(SDValue Addr, SDValue &Base,
- SDValue &Offset) const;
+ bool selectAddrDefault(SDValue Addr, SDValue &Base,
+ SDValue &Offset) const override;
- virtual bool selectIntAddr(SDValue Addr, SDValue &Base,
- SDValue &Offset) const;
+ bool selectIntAddr(SDValue Addr, SDValue &Base,
+ SDValue &Offset) const override;
- virtual bool selectAddrRegImm10(SDValue Addr, SDValue &Base,
- SDValue &Offset) const;
+ bool selectAddrRegImm10(SDValue Addr, SDValue &Base,
+ SDValue &Offset) const;
- virtual bool selectAddrRegImm12(SDValue Addr, SDValue &Base,
- SDValue &Offset) const;
+ bool selectAddrRegImm12(SDValue Addr, SDValue &Base,
+ SDValue &Offset) const;
- virtual bool selectIntAddrMM(SDValue Addr, SDValue &Base,
- SDValue &Offset) const;
+ bool selectIntAddrMM(SDValue Addr, SDValue &Base,
+ SDValue &Offset) const override;
- virtual bool selectIntAddrMSA(SDValue Addr, SDValue &Base,
- SDValue &Offset) const;
+ bool selectIntAddrMSA(SDValue Addr, SDValue &Base,
+ SDValue &Offset) const override;
/// \brief Select constant vector splats.
- virtual bool selectVSplat(SDNode *N, APInt &Imm) const;
+ bool selectVSplat(SDNode *N, APInt &Imm) const override;
/// \brief Select constant vector splats whose value fits in a given integer.
- virtual bool selectVSplatCommon(SDValue N, SDValue &Imm, bool Signed,
+ bool selectVSplatCommon(SDValue N, SDValue &Imm, bool Signed,
unsigned ImmBitSize) const;
/// \brief Select constant vector splats whose value fits in a uimm1.
- virtual bool selectVSplatUimm1(SDValue N, SDValue &Imm) const;
+ bool selectVSplatUimm1(SDValue N, SDValue &Imm) const override;
/// \brief Select constant vector splats whose value fits in a uimm2.
- virtual bool selectVSplatUimm2(SDValue N, SDValue &Imm) const;
+ bool selectVSplatUimm2(SDValue N, SDValue &Imm) const override;
/// \brief Select constant vector splats whose value fits in a uimm3.
- virtual bool selectVSplatUimm3(SDValue N, SDValue &Imm) const;
+ bool selectVSplatUimm3(SDValue N, SDValue &Imm) const override;
/// \brief Select constant vector splats whose value fits in a uimm4.
- virtual bool selectVSplatUimm4(SDValue N, SDValue &Imm) const;
+ bool selectVSplatUimm4(SDValue N, SDValue &Imm) const override;
/// \brief Select constant vector splats whose value fits in a uimm5.
- virtual bool selectVSplatUimm5(SDValue N, SDValue &Imm) const;
+ bool selectVSplatUimm5(SDValue N, SDValue &Imm) const override;
/// \brief Select constant vector splats whose value fits in a uimm6.
- virtual bool selectVSplatUimm6(SDValue N, SDValue &Imm) const;
+ bool selectVSplatUimm6(SDValue N, SDValue &Imm) const override;
/// \brief Select constant vector splats whose value fits in a uimm8.
- virtual bool selectVSplatUimm8(SDValue N, SDValue &Imm) const;
+ bool selectVSplatUimm8(SDValue N, SDValue &Imm) const override;
/// \brief Select constant vector splats whose value fits in a simm5.
- virtual bool selectVSplatSimm5(SDValue N, SDValue &Imm) const;
+ bool selectVSplatSimm5(SDValue N, SDValue &Imm) const override;
/// \brief Select constant vector splats whose value is a power of 2.
- virtual bool selectVSplatUimmPow2(SDValue N, SDValue &Imm) const;
+ bool selectVSplatUimmPow2(SDValue N, SDValue &Imm) const override;
/// \brief Select constant vector splats whose value is the inverse of a
/// power of 2.
- virtual bool selectVSplatUimmInvPow2(SDValue N, SDValue &Imm) const;
+ bool selectVSplatUimmInvPow2(SDValue N, SDValue &Imm) const override;
/// \brief Select constant vector splats whose value is a run of set bits
/// ending at the most significant bit
- virtual bool selectVSplatMaskL(SDValue N, SDValue &Imm) const;
+ bool selectVSplatMaskL(SDValue N, SDValue &Imm) const override;
/// \brief Select constant vector splats whose value is a run of set bits
/// starting at bit zero.
- virtual bool selectVSplatMaskR(SDValue N, SDValue &Imm) const;
+ bool selectVSplatMaskR(SDValue N, SDValue &Imm) const override;
- virtual std::pair<bool, SDNode*> selectNode(SDNode *Node);
+ std::pair<bool, SDNode*> selectNode(SDNode *Node) override;
- virtual void processFunctionAfterISel(MachineFunction &MF);
+ void processFunctionAfterISel(MachineFunction &MF) override;
// Insert instructions to initialize the global base register in the
// first MBB of the function.
diff --git a/lib/Target/Mips/MipsSEISelLowering.cpp b/lib/Target/Mips/MipsSEISelLowering.cpp
index 0dac0b7..969d730 100644
--- a/lib/Target/Mips/MipsSEISelLowering.cpp
+++ b/lib/Target/Mips/MipsSEISelLowering.cpp
@@ -10,7 +10,6 @@
// Subclass of MipsTargetLowering specialized for mips32/64.
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "mips-isel"
#include "MipsSEISelLowering.h"
#include "MipsRegisterInfo.h"
#include "MipsTargetMachine.h"
@@ -24,6 +23,8 @@
using namespace llvm;
+#define DEBUG_TYPE "mips-isel"
+
static cl::opt<bool>
EnableMipsTailCalls("enable-mips-tail-calls", cl::Hidden,
cl::desc("MIPS: Enable tail calls."), cl::init(false));
@@ -119,10 +120,10 @@ MipsSETargetLowering::MipsSETargetLowering(MipsTargetMachine &TM)
if (Subtarget->hasCnMips())
setOperationAction(ISD::MUL, MVT::i64, Legal);
- else if (hasMips64())
+ else if (isGP64bit())
setOperationAction(ISD::MUL, MVT::i64, Custom);
- if (hasMips64()) {
+ if (isGP64bit()) {
setOperationAction(ISD::MULHS, MVT::i64, Custom);
setOperationAction(ISD::MULHU, MVT::i64, Custom);
}
@@ -253,6 +254,16 @@ MipsSETargetLowering::allowsUnalignedMemoryAccesses(EVT VT,
bool *Fast) const {
MVT::SimpleValueType SVT = VT.getSimpleVT().SimpleTy;
+ if (Subtarget->systemSupportsUnalignedAccess()) {
+ // MIPS32r6/MIPS64r6 is required to support unaligned access. It's
+ // implementation defined whether this is handled by hardware, software, or
+ // a hybrid of the two but it's expected that most implementations will
+ // handle the majority of cases in hardware.
+ if (Fast)
+ *Fast = true;
+ return true;
+ }
+
switch (SVT) {
case MVT::i64:
case MVT::i32:
@@ -487,7 +498,8 @@ static SDValue performANDCombine(SDNode *N, SelectionDAG &DAG,
Log2 == ExtendTySize) {
SDValue Ops[] = { Op0->getOperand(0), Op0->getOperand(1), Op0Op2 };
DAG.MorphNodeTo(Op0.getNode(), MipsISD::VEXTRACT_ZEXT_ELT,
- Op0->getVTList(), Ops, Op0->getNumOperands());
+ Op0->getVTList(),
+ makeArrayRef(Ops, Op0->getNumOperands()));
return Op0;
}
}
@@ -507,7 +519,7 @@ static SDValue performANDCombine(SDNode *N, SelectionDAG &DAG,
static bool isVSplat(SDValue N, APInt &Imm, bool IsLittleEndian) {
BuildVectorSDNode *Node = dyn_cast<BuildVectorSDNode>(N.getNode());
- if (Node == NULL)
+ if (!Node)
return false;
APInt SplatValue, SplatUndef;
@@ -831,7 +843,8 @@ static SDValue performSRACombine(SDNode *N, SelectionDAG &DAG,
SDValue Ops[] = { Op0Op0->getOperand(0), Op0Op0->getOperand(1),
Op0Op0->getOperand(2) };
DAG.MorphNodeTo(Op0Op0.getNode(), MipsISD::VEXTRACT_SEXT_ELT,
- Op0Op0->getVTList(), Ops, Op0Op0->getNumOperands());
+ Op0Op0->getVTList(),
+ makeArrayRef(Ops, Op0Op0->getNumOperands()));
return Op0Op0;
}
}
@@ -1051,6 +1064,18 @@ MipsSETargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
return emitINSERT_FW(MI, BB);
case Mips::INSERT_FD_PSEUDO:
return emitINSERT_FD(MI, BB);
+ case Mips::INSERT_B_VIDX_PSEUDO:
+ return emitINSERT_DF_VIDX(MI, BB, 1, false);
+ case Mips::INSERT_H_VIDX_PSEUDO:
+ return emitINSERT_DF_VIDX(MI, BB, 2, false);
+ case Mips::INSERT_W_VIDX_PSEUDO:
+ return emitINSERT_DF_VIDX(MI, BB, 4, false);
+ case Mips::INSERT_D_VIDX_PSEUDO:
+ return emitINSERT_DF_VIDX(MI, BB, 8, false);
+ case Mips::INSERT_FW_VIDX_PSEUDO:
+ return emitINSERT_DF_VIDX(MI, BB, 4, true);
+ case Mips::INSERT_FD_VIDX_PSEUDO:
+ return emitINSERT_DF_VIDX(MI, BB, 8, true);
case Mips::FILL_FW_PSEUDO:
return emitFILL_FW(MI, BB);
case Mips::FILL_FD_PSEUDO:
@@ -1117,7 +1142,7 @@ SDValue MipsSETargetLowering::lowerLOAD(SDValue Op, SelectionDAG &DAG) const {
SDValue BP = DAG.getNode(MipsISD::BuildPairF64, DL, MVT::f64, Lo, Hi);
SDValue Ops[2] = {BP, Hi.getValue(1)};
- return DAG.getMergeValues(Ops, 2, DL);
+ return DAG.getMergeValues(Ops, DL);
}
SDValue MipsSETargetLowering::lowerSTORE(SDValue Op, SelectionDAG &DAG) const {
@@ -1168,7 +1193,7 @@ SDValue MipsSETargetLowering::lowerMulDiv(SDValue Op, unsigned NewOpc,
return HasLo ? Lo : Hi;
SDValue Vals[] = { Lo, Hi };
- return DAG.getMergeValues(Vals, 2, DL);
+ return DAG.getMergeValues(Vals, DL);
}
@@ -1235,7 +1260,7 @@ static SDValue lowerDSPIntr(SDValue Op, SelectionDAG &DAG, unsigned Opc) {
ResTys.push_back((*I == MVT::i64) ? MVT::Untyped : *I);
// Create node.
- SDValue Val = DAG.getNode(Opc, DL, ResTys, &Ops[0], Ops.size());
+ SDValue Val = DAG.getNode(Opc, DL, ResTys, Ops);
SDValue Out = (ResTys[0] == MVT::Untyped) ? extractLOHI(Val, DL, DAG) : Val;
if (!HasChainIn)
@@ -1243,7 +1268,7 @@ static SDValue lowerDSPIntr(SDValue Op, SelectionDAG &DAG, unsigned Opc) {
assert(Val->getValueType(1) == MVT::Other);
SDValue Vals[] = { Out, SDValue(Val.getNode(), 1) };
- return DAG.getMergeValues(Vals, 2, DL);
+ return DAG.getMergeValues(Vals, DL);
}
// Lower an MSA copy intrinsic into the specified SelectionDAG node
@@ -1280,8 +1305,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, Ops,
- ViaVecTy.getVectorNumElements());
+ SDValue Result = DAG.getNode(ISD::BUILD_VECTOR, DL, ViaVecTy,
+ makeArrayRef(Ops, ViaVecTy.getVectorNumElements()));
if (ViaVecTy != ResVecTy)
Result = DAG.getNode(ISD::BITCAST, DL, ResVecTy, Result);
@@ -1320,8 +1345,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, Ops,
- ViaVecTy.getVectorNumElements());
+ SDValue Result = DAG.getNode(ISD::BUILD_VECTOR, DL, ViaVecTy,
+ makeArrayRef(Ops, ViaVecTy.getVectorNumElements()));
if (VecTy != ViaVecTy)
Result = DAG.getNode(ISD::BITCAST, DL, VecTy, Result);
@@ -1355,7 +1380,7 @@ static SDValue lowerMSABinaryBitImmIntr(SDValue Op, SelectionDAG &DAG,
}
}
- if (Exp2Imm.getNode() == NULL) {
+ if (!Exp2Imm.getNode()) {
// We couldnt constant fold, do a vector shift instead
// Extend i32 to i64 if necessary. Sign or zero extend doesn't matter since
@@ -1735,7 +1760,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[0], Ops.size());
+ return DAG.getNode(ISD::BUILD_VECTOR, DL, ResTy, Ops);
}
case Intrinsic::mips_fexp2_w:
case Intrinsic::mips_fexp2_d: {
@@ -2560,8 +2585,7 @@ static SDValue lowerVECTOR_SHUFFLE_VSHF(SDValue Op, EVT ResTy,
++I)
Ops.push_back(DAG.getTargetConstant(*I, MaskEltTy));
- SDValue MaskVec = DAG.getNode(ISD::BUILD_VECTOR, DL, MaskVecTy, &Ops[0],
- Ops.size());
+ SDValue MaskVec = DAG.getNode(ISD::BUILD_VECTOR, DL, MaskVecTy, Ops);
if (Using1stVec && Using2ndVec) {
Op0 = Op->getOperand(0);
@@ -2885,6 +2909,131 @@ MipsSETargetLowering::emitINSERT_FD(MachineInstr *MI,
return BB;
}
+// Emit the INSERT_([BHWD]|F[WD])_VIDX pseudo instruction.
+//
+// For integer:
+// (INSERT_([BHWD]|F[WD])_PSEUDO $wd, $wd_in, $n, $rs)
+// =>
+// (SLL $lanetmp1, $lane, <log2size)
+// (SLD_B $wdtmp1, $wd_in, $wd_in, $lanetmp1)
+// (INSERT_[BHWD], $wdtmp2, $wdtmp1, 0, $rs)
+// (NEG $lanetmp2, $lanetmp1)
+// (SLD_B $wd, $wdtmp2, $wdtmp2, $lanetmp2)
+//
+// For floating point:
+// (INSERT_([BHWD]|F[WD])_PSEUDO $wd, $wd_in, $n, $fs)
+// =>
+// (SUBREG_TO_REG $wt, $fs, <subreg>)
+// (SLL $lanetmp1, $lane, <log2size)
+// (SLD_B $wdtmp1, $wd_in, $wd_in, $lanetmp1)
+// (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 {
+ const TargetInstrInfo *TII = getTargetMachine().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();
+
+ const TargetRegisterClass *VecRC = nullptr;
+ const TargetRegisterClass *GPRRC = isGP64bit() ? &Mips::GPR64RegClass
+ : &Mips::GPR32RegClass;
+ unsigned EltLog2Size;
+ unsigned InsertOp = 0;
+ unsigned InsveOp = 0;
+ switch (EltSizeInBytes) {
+ default:
+ llvm_unreachable("Unexpected size");
+ case 1:
+ EltLog2Size = 0;
+ InsertOp = Mips::INSERT_B;
+ InsveOp = Mips::INSVE_B;
+ VecRC = &Mips::MSA128BRegClass;
+ break;
+ case 2:
+ EltLog2Size = 1;
+ InsertOp = Mips::INSERT_H;
+ InsveOp = Mips::INSVE_H;
+ VecRC = &Mips::MSA128HRegClass;
+ break;
+ case 4:
+ EltLog2Size = 2;
+ InsertOp = Mips::INSERT_W;
+ InsveOp = Mips::INSVE_W;
+ VecRC = &Mips::MSA128WRegClass;
+ break;
+ case 8:
+ EltLog2Size = 3;
+ InsertOp = Mips::INSERT_D;
+ InsveOp = Mips::INSVE_D;
+ VecRC = &Mips::MSA128DRegClass;
+ break;
+ }
+
+ if (IsFP) {
+ unsigned Wt = RegInfo.createVirtualRegister(VecRC);
+ BuildMI(*BB, MI, DL, TII->get(Mips::SUBREG_TO_REG), Wt)
+ .addImm(0)
+ .addReg(SrcValReg)
+ .addImm(EltSizeInBytes == 8 ? Mips::sub_64 : Mips::sub_lo);
+ SrcValReg = Wt;
+ }
+
+ // 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)
+ .addReg(LaneReg)
+ .addImm(EltLog2Size);
+ LaneReg = LaneTmp1;
+ }
+
+ // Rotate bytes around so that the desired lane is element zero
+ unsigned WdTmp1 = RegInfo.createVirtualRegister(VecRC);
+ BuildMI(*BB, MI, DL, TII->get(Mips::SLD_B), WdTmp1)
+ .addReg(SrcVecReg)
+ .addReg(SrcVecReg)
+ .addReg(LaneReg);
+
+ unsigned WdTmp2 = RegInfo.createVirtualRegister(VecRC);
+ if (IsFP) {
+ // Use insve.df to insert to element zero
+ BuildMI(*BB, MI, DL, TII->get(InsveOp), WdTmp2)
+ .addReg(WdTmp1)
+ .addImm(0)
+ .addReg(SrcValReg)
+ .addImm(0);
+ } else {
+ // Use insert.df to insert to element zero
+ BuildMI(*BB, MI, DL, TII->get(InsertOp), WdTmp2)
+ .addReg(WdTmp1)
+ .addReg(SrcValReg)
+ .addImm(0);
+ }
+
+ // Rotate elements the rest of the way for a full rotation.
+ // sld.df inteprets $rt modulo the number of columns so we only need to negate
+ // the lane index to do this.
+ unsigned LaneTmp2 = RegInfo.createVirtualRegister(GPRRC);
+ BuildMI(*BB, MI, DL, TII->get(Mips::SUB), LaneTmp2)
+ .addReg(Mips::ZERO)
+ .addReg(LaneReg);
+ BuildMI(*BB, MI, DL, TII->get(Mips::SLD_B), Wd)
+ .addReg(WdTmp2)
+ .addReg(WdTmp2)
+ .addReg(LaneTmp2);
+
+ MI->eraseFromParent(); // The pseudo instruction is gone now.
+ return BB;
+}
+
// Emit the FILL_FW pseudo instruction.
//
// fill_fw_pseudo $wd, $fs
diff --git a/lib/Target/Mips/MipsSEISelLowering.h b/lib/Target/Mips/MipsSEISelLowering.h
index 079fbf6..03a20ef 100644
--- a/lib/Target/Mips/MipsSEISelLowering.h
+++ b/lib/Target/Mips/MipsSEISelLowering.h
@@ -30,22 +30,23 @@ namespace llvm {
void addMSAFloatType(MVT::SimpleValueType Ty,
const TargetRegisterClass *RC);
- virtual bool allowsUnalignedMemoryAccesses(EVT VT, unsigned AS = 0,
- bool *Fast = 0) const override;
+ bool allowsUnalignedMemoryAccesses(EVT VT, unsigned AS = 0,
+ bool *Fast = nullptr) const override;
- virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const;
+ SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override;
- virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
+ SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override;
- virtual MachineBasicBlock *
- EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB) const;
+ MachineBasicBlock *
+ EmitInstrWithCustomInserter(MachineInstr *MI,
+ MachineBasicBlock *MBB) const override;
- virtual bool isShuffleMaskLegal(const SmallVectorImpl<int> &Mask,
- EVT VT) const {
+ bool isShuffleMaskLegal(const SmallVectorImpl<int> &Mask,
+ EVT VT) const override {
return false;
}
- virtual const TargetRegisterClass *getRepRegClassFor(MVT VT) const {
+ const TargetRegisterClass *getRepRegClassFor(MVT VT) const override {
if (VT == MVT::Untyped)
return Subtarget->hasDSP() ? &Mips::ACC64DSPRegClass :
&Mips::ACC64RegClass;
@@ -54,16 +55,16 @@ namespace llvm {
}
private:
- virtual bool
- isEligibleForTailCallOptimization(const MipsCC &MipsCCInfo,
- unsigned NextStackOffset,
- const MipsFunctionInfo& FI) const;
+ bool isEligibleForTailCallOptimization(const MipsCC &MipsCCInfo,
+ unsigned NextStackOffset,
+ const MipsFunctionInfo& FI) const override;
- virtual void
+ void
getOpndList(SmallVectorImpl<SDValue> &Ops,
std::deque< std::pair<unsigned, SDValue> > &RegsToPass,
bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage,
- CallLoweringInfo &CLI, SDValue Callee, SDValue Chain) const;
+ CallLoweringInfo &CLI, SDValue Callee,
+ SDValue Chain) const override;
SDValue lowerLOAD(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerSTORE(SDValue Op, SelectionDAG &DAG) const;
@@ -97,6 +98,11 @@ namespace llvm {
/// \brief Emit the INSERT_FD pseudo instruction
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 *BB,
+ unsigned EltSizeInBytes,
+ bool IsFP) const;
/// \brief Emit the FILL_FW pseudo instruction
MachineBasicBlock *emitFILL_FW(MachineInstr *MI,
MachineBasicBlock *BB) const;
diff --git a/lib/Target/Mips/MipsSEInstrInfo.cpp b/lib/Target/Mips/MipsSEInstrInfo.cpp
index 094ee29..f6f364f 100644
--- a/lib/Target/Mips/MipsSEInstrInfo.cpp
+++ b/lib/Target/Mips/MipsSEInstrInfo.cpp
@@ -368,7 +368,7 @@ void MipsSEInstrInfo::adjustStackPtr(unsigned SP, int64_t 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.
- unsigned Reg = loadImmediate(Amount, MBB, I, DL, 0);
+ unsigned Reg = loadImmediate(Amount, MBB, I, DL, nullptr);
BuildMI(MBB, I, DL, get(ADDu), SP).addReg(SP).addReg(Reg, RegState::Kill);
}
}
diff --git a/lib/Target/Mips/MipsSEInstrInfo.h b/lib/Target/Mips/MipsSEInstrInfo.h
index 6d2dd90..aa68552 100644
--- a/lib/Target/Mips/MipsSEInstrInfo.h
+++ b/lib/Target/Mips/MipsSEInstrInfo.h
@@ -26,46 +26,46 @@ class MipsSEInstrInfo : public MipsInstrInfo {
public:
explicit MipsSEInstrInfo(MipsTargetMachine &TM);
- virtual const MipsRegisterInfo &getRegisterInfo() const;
+ const MipsRegisterInfo &getRegisterInfo() const override;
/// isLoadFromStackSlot - If the specified machine instruction is a direct
/// load from a stack slot, return the virtual or physical register number of
/// 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.
- virtual unsigned isLoadFromStackSlot(const MachineInstr *MI,
- int &FrameIndex) const;
+ unsigned isLoadFromStackSlot(const MachineInstr *MI,
+ int &FrameIndex) const override;
/// isStoreToStackSlot - If the specified machine instruction is a direct
/// store to a stack slot, return the virtual or physical register number of
/// 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.
- virtual unsigned isStoreToStackSlot(const MachineInstr *MI,
- int &FrameIndex) const;
+ unsigned isStoreToStackSlot(const MachineInstr *MI,
+ int &FrameIndex) const override;
- virtual void copyPhysReg(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI, DebugLoc DL,
- unsigned DestReg, unsigned SrcReg,
- bool KillSrc) const;
+ void copyPhysReg(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI, DebugLoc DL,
+ unsigned DestReg, unsigned SrcReg,
+ bool KillSrc) const override;
- virtual void storeRegToStack(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI,
- unsigned SrcReg, bool isKill, int FrameIndex,
- const TargetRegisterClass *RC,
- const TargetRegisterInfo *TRI,
- int64_t Offset) const;
+ void storeRegToStack(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI,
+ unsigned SrcReg, bool isKill, int FrameIndex,
+ const TargetRegisterClass *RC,
+ const TargetRegisterInfo *TRI,
+ int64_t Offset) const override;
- virtual void loadRegFromStack(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MI,
- unsigned DestReg, int FrameIndex,
- const TargetRegisterClass *RC,
- const TargetRegisterInfo *TRI,
- int64_t Offset) const;
+ void loadRegFromStack(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI,
+ unsigned DestReg, int FrameIndex,
+ const TargetRegisterClass *RC,
+ const TargetRegisterInfo *TRI,
+ int64_t Offset) const override;
- virtual bool expandPostRAPseudo(MachineBasicBlock::iterator MI) const;
+ bool expandPostRAPseudo(MachineBasicBlock::iterator MI) const override;
- virtual unsigned getOppositeBranchOpc(unsigned Opc) const;
+ unsigned getOppositeBranchOpc(unsigned Opc) const override;
/// Adjust SP by Amount bytes.
void adjustStackPtr(unsigned SP, int64_t Amount, MachineBasicBlock &MBB,
@@ -79,7 +79,7 @@ public:
unsigned *NewImm) const;
private:
- virtual unsigned getAnalyzableBrOpc(unsigned Opc) const;
+ unsigned getAnalyzableBrOpc(unsigned Opc) const override;
void expandRetRA(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
unsigned Opc) const;
diff --git a/lib/Target/Mips/MipsSERegisterInfo.cpp b/lib/Target/Mips/MipsSERegisterInfo.cpp
index 2ac082f..0af1a6b 100644
--- a/lib/Target/Mips/MipsSERegisterInfo.cpp
+++ b/lib/Target/Mips/MipsSERegisterInfo.cpp
@@ -39,6 +39,8 @@
using namespace llvm;
+#define DEBUG_TYPE "mips-reg-info"
+
MipsSERegisterInfo::MipsSERegisterInfo(const MipsSubtarget &ST)
: MipsRegisterInfo(ST) {}
@@ -187,7 +189,7 @@ void MipsSERegisterInfo::eliminateFI(MachineBasicBlock::iterator II,
*static_cast<const MipsSEInstrInfo *>(
MBB.getParent()->getTarget().getInstrInfo());
unsigned Reg = TII.loadImmediate(Offset, MBB, II, DL,
- OffsetBitSize == 16 ? &NewImm : NULL);
+ OffsetBitSize == 16 ? &NewImm : nullptr);
BuildMI(MBB, II, DL, TII.get(ADDu), Reg).addReg(FrameReg)
.addReg(Reg, RegState::Kill);
diff --git a/lib/Target/Mips/MipsSERegisterInfo.h b/lib/Target/Mips/MipsSERegisterInfo.h
index 76cdd9d..f2f3a7e 100644
--- a/lib/Target/Mips/MipsSERegisterInfo.h
+++ b/lib/Target/Mips/MipsSERegisterInfo.h
@@ -24,16 +24,16 @@ class MipsSERegisterInfo : public MipsRegisterInfo {
public:
MipsSERegisterInfo(const MipsSubtarget &Subtarget);
- bool requiresRegisterScavenging(const MachineFunction &MF) const;
+ bool requiresRegisterScavenging(const MachineFunction &MF) const override;
- bool requiresFrameIndexScavenging(const MachineFunction &MF) const;
+ bool requiresFrameIndexScavenging(const MachineFunction &MF) const override;
- virtual const TargetRegisterClass *intRegClass(unsigned Size) const;
+ const TargetRegisterClass *intRegClass(unsigned Size) const override;
private:
- virtual void eliminateFI(MachineBasicBlock::iterator II, unsigned OpNo,
- int FrameIndex, uint64_t StackSize,
- int64_t SPOffset) const;
+ void eliminateFI(MachineBasicBlock::iterator II, unsigned OpNo,
+ int FrameIndex, uint64_t StackSize,
+ int64_t SPOffset) const override;
};
} // end namespace llvm
diff --git a/lib/Target/Mips/MipsSelectionDAGInfo.cpp b/lib/Target/Mips/MipsSelectionDAGInfo.cpp
index e4d70fc..0d4398e 100644
--- a/lib/Target/Mips/MipsSelectionDAGInfo.cpp
+++ b/lib/Target/Mips/MipsSelectionDAGInfo.cpp
@@ -11,10 +11,11 @@
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "mips-selectiondag-info"
#include "MipsTargetMachine.h"
using namespace llvm;
+#define DEBUG_TYPE "mips-selectiondag-info"
+
MipsSelectionDAGInfo::MipsSelectionDAGInfo(const MipsTargetMachine &TM)
: TargetSelectionDAGInfo(TM) {
}
diff --git a/lib/Target/Mips/MipsSubtarget.cpp b/lib/Target/Mips/MipsSubtarget.cpp
index 143b945..74ec064 100644
--- a/lib/Target/Mips/MipsSubtarget.cpp
+++ b/lib/Target/Mips/MipsSubtarget.cpp
@@ -11,8 +11,6 @@
//
//===----------------------------------------------------------------------===//
-#define DEBUG_TYPE "mips-subtarget"
-
#include "MipsMachineFunction.h"
#include "Mips.h"
#include "MipsRegisterInfo.h"
@@ -25,13 +23,14 @@
#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+#define DEBUG_TYPE "mips-subtarget"
+
#define GET_SUBTARGETINFO_TARGET_DESC
#define GET_SUBTARGETINFO_CTOR
#include "MipsGenSubtargetInfo.inc"
-
-using namespace llvm;
-
// FIXME: Maybe this should be on by default when Mips16 is specified
//
static cl::opt<bool> Mixed16_32(
@@ -77,17 +76,16 @@ void MipsSubtarget::anchor() { }
MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU,
const std::string &FS, bool little,
- Reloc::Model _RM, MipsTargetMachine *_TM) :
- MipsGenSubtargetInfo(TT, CPU, FS),
- MipsArchVersion(Mips32), MipsABI(UnknownABI), IsLittle(little),
- IsSingleFloat(false), IsFP64bit(false), IsGP64bit(false), HasVFPU(false),
- HasCnMips(false), IsLinux(true), HasSEInReg(false), HasCondMov(false),
- HasSwap(false), HasBitCount(false), HasFPIdx(false),
- InMips16Mode(false), InMips16HardFloat(Mips16HardFloat),
- InMicroMipsMode(false), HasDSP(false), HasDSPR2(false),
- AllowMixed16_32(Mixed16_32 | Mips_Os16), Os16(Mips_Os16), HasMSA(false),
- RM(_RM), OverrideMode(NoOverride), TM(_TM), TargetTriple(TT)
-{
+ Reloc::Model _RM, MipsTargetMachine *_TM)
+ : MipsGenSubtargetInfo(TT, CPU, FS), MipsArchVersion(Mips32),
+ MipsABI(UnknownABI), IsLittle(little), IsSingleFloat(false),
+ IsFP64bit(false), IsNaN2008bit(false), IsGP64bit(false), HasVFPU(false),
+ HasCnMips(false), IsLinux(true), HasMips3_32(false), HasMips3_32r2(false),
+ HasMips4_32(false), HasMips4_32r2(false), HasMips5_32r2(false),
+ InMips16Mode(false), InMips16HardFloat(Mips16HardFloat),
+ InMicroMipsMode(false), HasDSP(false), HasDSPR2(false),
+ AllowMixed16_32(Mixed16_32 | Mips_Os16), Os16(Mips_Os16), HasMSA(false),
+ RM(_RM), OverrideMode(NoOverride), TM(_TM), TargetTriple(TT) {
std::string CPUName = CPU;
CPUName = selectMipsCPU(TT, CPUName);
@@ -109,6 +107,19 @@ MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU,
// Initialize scheduling itinerary for the specified CPU.
InstrItins = getInstrItineraryForCPU(CPUName);
+ // Don't even attempt to generate code for MIPS-I, MIPS-II, MIPS-III, and
+ // MIPS-V. They have not been tested and currently exist for the integrated
+ // assembler only.
+ if (MipsArchVersion == Mips1)
+ report_fatal_error("Code generation for MIPS-I is not implemented", false);
+ if (MipsArchVersion == Mips2)
+ report_fatal_error("Code generation for MIPS-II is not implemented", false);
+ if (MipsArchVersion == Mips3)
+ report_fatal_error("Code generation for MIPS-III is not implemented",
+ false);
+ if (MipsArchVersion == Mips5)
+ report_fatal_error("Code generation for MIPS-V is not implemented", false);
+
// Assert exactly one ABI was chosen.
assert(MipsABI != UnknownABI);
assert((((getFeatureBits() & Mips::FeatureO32) != 0) +
@@ -126,15 +137,23 @@ MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU,
"See -mattr=+fp64.",
false);
+ if (hasMips32r6()) {
+ StringRef ISA = hasMips64r6() ? "MIPS64r6" : "MIPS32r6";
+
+ assert(isFP64bit());
+ assert(isNaN2008());
+ if (hasDSP())
+ report_fatal_error(ISA + " is not compatible with the DSP ASE", false);
+ }
+
// Is the target system Linux ?
if (TT.find("linux") == std::string::npos)
IsLinux = false;
// Set UseSmallSection.
+ // TODO: Investigate the IsLinux check. I suspect it's really checking for
+ // bare-metal.
UseSmallSection = !IsLinux && (RM == Reloc::Static);
- // set some subtarget specific features
- if (inMips16Mode())
- HasBitCount=false;
}
bool
diff --git a/lib/Target/Mips/MipsSubtarget.h b/lib/Target/Mips/MipsSubtarget.h
index 2166b93..373f481 100644
--- a/lib/Target/Mips/MipsSubtarget.h
+++ b/lib/Target/Mips/MipsSubtarget.h
@@ -37,7 +37,10 @@ public:
};
protected:
- enum MipsArchEnum { Mips32, Mips32r2, Mips4, Mips64, Mips64r2 };
+ enum MipsArchEnum {
+ Mips1, Mips2, Mips32, Mips32r2, Mips32r6, Mips3, Mips4, Mips5, Mips64,
+ Mips64r2, Mips64r6
+ };
// Mips architecture version
MipsArchEnum MipsArchVersion;
@@ -56,6 +59,9 @@ protected:
// IsFP64bit - The target processor has 64-bit floating point registers.
bool IsFP64bit;
+ // IsNan2008 - IEEE 754-2008 NaN encoding.
+ bool IsNaN2008bit;
+
// IsFP64bit - General-purpose registers are 64 bits wide
bool IsGP64bit;
@@ -73,20 +79,20 @@ protected:
/// Features related to the presence of specific instructions.
- // HasSEInReg - SEB and SEH (signext in register) instructions.
- bool HasSEInReg;
+ // HasMips3_32 - The subset of MIPS-III instructions added to MIPS32
+ bool HasMips3_32;
- // HasCondMov - Conditional mov (MOVZ, MOVN) instructions.
- bool HasCondMov;
+ // HasMips3_32r2 - The subset of MIPS-III instructions added to MIPS32r2
+ bool HasMips3_32r2;
- // HasSwap - Byte and half swap instructions.
- bool HasSwap;
+ // HasMips4_32 - Has the subset of MIPS-IV present in MIPS32
+ bool HasMips4_32;
- // HasBitCount - Count leading '1' and '0' bits.
- bool HasBitCount;
+ // HasMips4_32r2 - Has the subset of MIPS-IV present in MIPS32r2
+ bool HasMips4_32r2;
- // HasFPIdx -- Floating point indexed load/store instructions.
- bool HasFPIdx;
+ // HasMips5_32r2 - Has the subset of MIPS-V present in MIPS32r2
+ bool HasMips5_32r2;
// InMips16 -- can process Mips16 instructions
bool InMips16Mode;
@@ -127,9 +133,9 @@ protected:
Triple TargetTriple;
public:
- virtual bool enablePostRAScheduler(CodeGenOpt::Level OptLevel,
- AntiDepBreakMode& Mode,
- RegClassVector& CriticalPathRCs) const;
+ bool enablePostRAScheduler(CodeGenOpt::Level OptLevel,
+ AntiDepBreakMode& Mode,
+ RegClassVector& CriticalPathRCs) const override;
/// Only O32 and EABI supported right now.
bool isABI_EABI() const { return MipsABI == EABI; }
@@ -148,16 +154,24 @@ public:
/// subtarget options. Definition of function is auto generated by tblgen.
void ParseSubtargetFeatures(StringRef CPU, StringRef FS);
+ bool hasMips2() const { return MipsArchVersion >= Mips2; }
+ bool hasMips3() const { return MipsArchVersion >= Mips3; }
+ bool hasMips4_32() const { return HasMips4_32; }
+ bool hasMips4_32r2() const { return HasMips4_32r2; }
bool hasMips32() const { return MipsArchVersion >= Mips32; }
bool hasMips32r2() const { return MipsArchVersion == Mips32r2 ||
MipsArchVersion == Mips64r2; }
+ bool hasMips32r6() const { return MipsArchVersion == Mips32r6 ||
+ MipsArchVersion == Mips64r6; }
bool hasMips64() const { return MipsArchVersion >= Mips64; }
bool hasMips64r2() const { return MipsArchVersion == Mips64r2; }
+ bool hasMips64r6() const { return MipsArchVersion == Mips64r6; }
bool hasCnMips() const { return HasCnMips; }
bool isLittle() const { return IsLittle; }
bool isFP64bit() const { return IsFP64bit; }
+ bool isNaN2008() const { return IsNaN2008bit; }
bool isNotFP64bit() const { return !IsFP64bit; }
bool isGP64bit() const { return IsGP64bit; }
bool isGP32bit() const { return !IsGP64bit; }
@@ -197,11 +211,6 @@ public:
}
/// Features related to the presence of specific instructions.
- bool hasSEInReg() const { return HasSEInReg; }
- bool hasCondMov() const { return HasCondMov; }
- bool hasSwap() const { return HasSwap; }
- bool hasBitCount() const { return HasBitCount; }
- bool hasFPIdx() const { return HasFPIdx; }
bool hasExtractInsert() const { return !inMips16Mode() && hasMips32r2(); }
const InstrItineraryData &getInstrItineraryData() const { return InstrItins; }
@@ -213,10 +222,9 @@ public:
bool isTargetNaCl() const { return TargetTriple.isOSNaCl(); }
bool isNotTargetNaCl() const { return !TargetTriple.isOSNaCl(); }
-// for now constant islands are on for the whole compilation unit but we only
-// really use them if in addition we are in mips16 mode
-//
-static bool useConstantIslands();
+ // for now constant islands are on for the whole compilation unit but we only
+ // really use them if in addition we are in mips16 mode
+ static bool useConstantIslands();
unsigned stackAlignment() const { return hasMips64() ? 16 : 8; }
@@ -226,7 +234,12 @@ static bool useConstantIslands();
/// \brief Reset the subtarget for the Mips target.
void resetSubtarget(MachineFunction *MF);
-
+ /// Does the system support unaligned memory access.
+ ///
+ /// MIPS32r6/MIPS64r6 require full unaligned access support but does not
+ /// specify which component of the system provides it. Hardware, software, and
+ /// hybrid implementations are all valid.
+ bool systemSupportsUnalignedAccess() const { return hasMips32r6(); }
};
} // End llvm namespace
diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp
index e9053c8..984c58e 100644
--- a/lib/Target/Mips/MipsTargetMachine.cpp
+++ b/lib/Target/Mips/MipsTargetMachine.cpp
@@ -35,7 +35,7 @@
#include "llvm/Transforms/Scalar.h"
using namespace llvm;
-
+#define DEBUG_TYPE "mips"
extern "C" void LLVMInitializeMipsTarget() {
// Register the target.
@@ -171,12 +171,12 @@ public:
return *getMipsTargetMachine().getSubtargetImpl();
}
- virtual void addIRPasses();
- virtual bool addInstSelector();
- virtual void addMachineSSAOptimization();
- virtual bool addPreEmitPass();
+ void addIRPasses() override;
+ bool addInstSelector() override;
+ void addMachineSSAOptimization() override;
+ bool addPreEmitPass() override;
- virtual bool addPreRegAlloc();
+ bool addPreRegAlloc() override;
};
} // namespace
diff --git a/lib/Target/Mips/MipsTargetMachine.h b/lib/Target/Mips/MipsTargetMachine.h
index 5a9a11d..a5aa39b 100644
--- a/lib/Target/Mips/MipsTargetMachine.h
+++ b/lib/Target/Mips/MipsTargetMachine.h
@@ -20,7 +20,6 @@
#include "MipsJITInfo.h"
#include "MipsSelectionDAGInfo.h"
#include "MipsSubtarget.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/CodeGen/SelectionDAGISel.h"
#include "llvm/IR/DataLayout.h"
@@ -34,15 +33,15 @@ class MipsRegisterInfo;
class MipsTargetMachine : public LLVMTargetMachine {
MipsSubtarget Subtarget;
const DataLayout DL; // Calculates type size & alignment
- OwningPtr<const MipsInstrInfo> InstrInfo;
- OwningPtr<const MipsFrameLowering> FrameLowering;
- OwningPtr<const MipsTargetLowering> TLInfo;
- OwningPtr<const MipsInstrInfo> InstrInfo16;
- OwningPtr<const MipsFrameLowering> FrameLowering16;
- OwningPtr<const MipsTargetLowering> TLInfo16;
- OwningPtr<const MipsInstrInfo> InstrInfoSE;
- OwningPtr<const MipsFrameLowering> FrameLoweringSE;
- OwningPtr<const MipsTargetLowering> TLInfoSE;
+ std::unique_ptr<const MipsInstrInfo> InstrInfo;
+ std::unique_ptr<const MipsFrameLowering> FrameLowering;
+ std::unique_ptr<const MipsTargetLowering> TLInfo;
+ std::unique_ptr<const MipsInstrInfo> InstrInfo16;
+ std::unique_ptr<const MipsFrameLowering> FrameLowering16;
+ std::unique_ptr<const MipsTargetLowering> TLInfo16;
+ std::unique_ptr<const MipsInstrInfo> InstrInfoSE;
+ std::unique_ptr<const MipsFrameLowering> FrameLoweringSE;
+ std::unique_ptr<const MipsTargetLowering> TLInfoSE;
MipsSelectionDAGInfo TSInfo;
const InstrItineraryData &InstrItins;
MipsJITInfo JITInfo;
@@ -56,39 +55,38 @@ public:
virtual ~MipsTargetMachine() {}
- virtual void addAnalysisPasses(PassManagerBase &PM);
+ void addAnalysisPasses(PassManagerBase &PM) override;
- virtual const MipsInstrInfo *getInstrInfo() const
+ const MipsInstrInfo *getInstrInfo() const override
{ return InstrInfo.get(); }
- virtual const TargetFrameLowering *getFrameLowering() const
+ const TargetFrameLowering *getFrameLowering() const override
{ return FrameLowering.get(); }
- virtual const MipsSubtarget *getSubtargetImpl() const
+ const MipsSubtarget *getSubtargetImpl() const override
{ return &Subtarget; }
- virtual const DataLayout *getDataLayout() const
+ const DataLayout *getDataLayout() const override
{ return &DL;}
- virtual const InstrItineraryData *getInstrItineraryData() const {
- return Subtarget.inMips16Mode() ? 0 : &InstrItins;
+ const InstrItineraryData *getInstrItineraryData() const override {
+ return Subtarget.inMips16Mode() ? nullptr : &InstrItins;
}
- virtual MipsJITInfo *getJITInfo()
- { return &JITInfo; }
+ MipsJITInfo *getJITInfo() override { return &JITInfo; }
- virtual const MipsRegisterInfo *getRegisterInfo() const {
+ const MipsRegisterInfo *getRegisterInfo() const override {
return &InstrInfo->getRegisterInfo();
}
- virtual const MipsTargetLowering *getTargetLowering() const {
+ const MipsTargetLowering *getTargetLowering() const override {
return TLInfo.get();
}
- virtual const MipsSelectionDAGInfo* getSelectionDAGInfo() const {
+ const MipsSelectionDAGInfo* getSelectionDAGInfo() const override {
return &TSInfo;
}
// Pass Pipeline Configuration
- virtual TargetPassConfig *createPassConfig(PassManagerBase &PM);
- virtual bool addCodeEmitter(PassManagerBase &PM, JITCodeEmitter &JCE);
+ TargetPassConfig *createPassConfig(PassManagerBase &PM) override;
+ bool addCodeEmitter(PassManagerBase &PM, JITCodeEmitter &JCE) override;
// Set helper classes
void setHelperClassesMips16();
diff --git a/lib/Target/Mips/MipsTargetStreamer.h b/lib/Target/Mips/MipsTargetStreamer.h
index 5f4b74b..4ad37ac 100644
--- a/lib/Target/Mips/MipsTargetStreamer.h
+++ b/lib/Target/Mips/MipsTargetStreamer.h
@@ -34,6 +34,8 @@ public:
virtual void emitDirectiveEnt(const MCSymbol &Symbol) = 0;
virtual void emitDirectiveAbiCalls() = 0;
+ virtual void emitDirectiveNaN2008() = 0;
+ virtual void emitDirectiveNaNLegacy() = 0;
virtual void emitDirectiveOptionPic0() = 0;
virtual void emitDirectiveOptionPic2() = 0;
virtual void emitFrame(unsigned StackReg, unsigned StackSize,
@@ -45,6 +47,11 @@ public:
virtual void emitDirectiveSetMips64() = 0;
virtual void emitDirectiveSetMips64R2() = 0;
virtual void emitDirectiveSetDsp() = 0;
+
+ // PIC support
+ virtual void emitDirectiveCpload(unsigned RegNo) = 0;
+ virtual void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
+ const MCSymbol &Sym, bool IsReg) = 0;
};
// This part is for ascii assembly output
@@ -53,32 +60,39 @@ class MipsTargetAsmStreamer : public MipsTargetStreamer {
public:
MipsTargetAsmStreamer(MCStreamer &S, formatted_raw_ostream &OS);
- virtual void emitDirectiveSetMicroMips();
- virtual void emitDirectiveSetNoMicroMips();
- virtual void emitDirectiveSetMips16();
- virtual void emitDirectiveSetNoMips16();
-
- virtual void emitDirectiveSetReorder();
- virtual void emitDirectiveSetNoReorder();
- virtual void emitDirectiveSetMacro();
- virtual void emitDirectiveSetNoMacro();
- virtual void emitDirectiveSetAt();
- virtual void emitDirectiveSetNoAt();
- virtual void emitDirectiveEnd(StringRef Name);
-
- virtual void emitDirectiveEnt(const MCSymbol &Symbol);
- virtual void emitDirectiveAbiCalls();
- virtual void emitDirectiveOptionPic0();
- virtual void emitDirectiveOptionPic2();
- virtual void emitFrame(unsigned StackReg, unsigned StackSize,
- unsigned ReturnReg);
- virtual void emitMask(unsigned CPUBitmask, int CPUTopSavedRegOff);
- virtual void emitFMask(unsigned FPUBitmask, int FPUTopSavedRegOff);
-
- virtual void emitDirectiveSetMips32R2();
- virtual void emitDirectiveSetMips64();
- virtual void emitDirectiveSetMips64R2();
- virtual void emitDirectiveSetDsp();
+ void emitDirectiveSetMicroMips() override;
+ void emitDirectiveSetNoMicroMips() override;
+ void emitDirectiveSetMips16() override;
+ void emitDirectiveSetNoMips16() override;
+
+ void emitDirectiveSetReorder() override;
+ void emitDirectiveSetNoReorder() override;
+ void emitDirectiveSetMacro() override;
+ void emitDirectiveSetNoMacro() override;
+ void emitDirectiveSetAt() override;
+ void emitDirectiveSetNoAt() override;
+ void emitDirectiveEnd(StringRef Name) override;
+
+ void emitDirectiveEnt(const MCSymbol &Symbol) override;
+ void emitDirectiveAbiCalls() override;
+ void emitDirectiveNaN2008() override;
+ void emitDirectiveNaNLegacy() override;
+ void emitDirectiveOptionPic0() override;
+ void emitDirectiveOptionPic2() override;
+ void emitFrame(unsigned StackReg, unsigned StackSize,
+ unsigned ReturnReg) override;
+ void emitMask(unsigned CPUBitmask, int CPUTopSavedRegOff) override;
+ void emitFMask(unsigned FPUBitmask, int FPUTopSavedRegOff) override;
+
+ void emitDirectiveSetMips32R2() override;
+ void emitDirectiveSetMips64() override;
+ void emitDirectiveSetMips64R2() override;
+ void emitDirectiveSetDsp() override;
+
+ // PIC support
+ virtual void emitDirectiveCpload(unsigned RegNo);
+ void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
+ const MCSymbol &Sym, bool IsReg) override;
};
// This part is for ELF object output
@@ -92,36 +106,48 @@ public:
MCELFStreamer &getStreamer();
MipsTargetELFStreamer(MCStreamer &S, const MCSubtargetInfo &STI);
- virtual void emitLabel(MCSymbol *Symbol) override;
- virtual void emitAssignment(MCSymbol *Symbol, const MCExpr *Value) override;
+ void emitLabel(MCSymbol *Symbol) override;
+ void emitAssignment(MCSymbol *Symbol, const MCExpr *Value) override;
void finish() override;
- virtual void emitDirectiveSetMicroMips();
- virtual void emitDirectiveSetNoMicroMips();
- virtual void emitDirectiveSetMips16();
- virtual void emitDirectiveSetNoMips16();
-
- virtual void emitDirectiveSetReorder();
- virtual void emitDirectiveSetNoReorder();
- virtual void emitDirectiveSetMacro();
- virtual void emitDirectiveSetNoMacro();
- virtual void emitDirectiveSetAt();
- virtual void emitDirectiveSetNoAt();
- virtual void emitDirectiveEnd(StringRef Name);
-
- virtual void emitDirectiveEnt(const MCSymbol &Symbol);
- virtual void emitDirectiveAbiCalls();
- virtual void emitDirectiveOptionPic0();
- virtual void emitDirectiveOptionPic2();
- virtual void emitFrame(unsigned StackReg, unsigned StackSize,
- unsigned ReturnReg);
- virtual void emitMask(unsigned CPUBitmask, int CPUTopSavedRegOff);
- virtual void emitFMask(unsigned FPUBitmask, int FPUTopSavedRegOff);
-
- virtual void emitDirectiveSetMips32R2();
- virtual void emitDirectiveSetMips64();
- virtual void emitDirectiveSetMips64R2();
- virtual void emitDirectiveSetDsp();
+ void emitDirectiveSetMicroMips() override;
+ void emitDirectiveSetNoMicroMips() override;
+ void emitDirectiveSetMips16() override;
+ void emitDirectiveSetNoMips16() override;
+
+ void emitDirectiveSetReorder() override;
+ void emitDirectiveSetNoReorder() override;
+ void emitDirectiveSetMacro() override;
+ void emitDirectiveSetNoMacro() override;
+ void emitDirectiveSetAt() override;
+ void emitDirectiveSetNoAt() override;
+ void emitDirectiveEnd(StringRef Name) override;
+
+ void emitDirectiveEnt(const MCSymbol &Symbol) override;
+ void emitDirectiveAbiCalls() override;
+ void emitDirectiveNaN2008() override;
+ void emitDirectiveNaNLegacy() override;
+ void emitDirectiveOptionPic0() override;
+ void emitDirectiveOptionPic2() override;
+ void emitFrame(unsigned StackReg, unsigned StackSize,
+ unsigned ReturnReg) override;
+ void emitMask(unsigned CPUBitmask, int CPUTopSavedRegOff) override;
+ void emitFMask(unsigned FPUBitmask, int FPUTopSavedRegOff) override;
+
+ void emitDirectiveSetMips32R2() override;
+ void emitDirectiveSetMips64() override;
+ void emitDirectiveSetMips64R2() override;
+ void emitDirectiveSetDsp() override;
+
+ // PIC support
+ virtual void emitDirectiveCpload(unsigned RegNo);
+ void emitDirectiveCpsetup(unsigned RegNo, int RegOrOffset,
+ const MCSymbol &Sym, bool IsReg) override;
+
+protected:
+ bool isO32() const { return STI.getFeatureBits() & Mips::FeatureO32; }
+ bool isN32() const { return STI.getFeatureBits() & Mips::FeatureN32; }
+ bool isN64() const { return STI.getFeatureBits() & Mips::FeatureN64; }
};
}
#endif