aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target/Mips
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/Mips')
-rw-r--r--lib/Target/Mips/AsmParser/MipsAsmParser.cpp860
-rw-r--r--lib/Target/Mips/CMakeLists.txt2
-rw-r--r--lib/Target/Mips/Disassembler/MipsDisassembler.cpp52
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp87
-rw-r--r--lib/Target/Mips/MicroMipsInstrFormats.td112
-rw-r--r--lib/Target/Mips/MicroMipsInstrInfo.td67
-rw-r--r--lib/Target/Mips/Mips16FrameLowering.h2
-rw-r--r--lib/Target/Mips/Mips16ISelDAGToDAG.cpp7
-rw-r--r--lib/Target/Mips/Mips16ISelDAGToDAG.h2
-rw-r--r--lib/Target/Mips/Mips16ISelLowering.cpp7
-rw-r--r--lib/Target/Mips/Mips16InstrInfo.cpp19
-rw-r--r--lib/Target/Mips/Mips16InstrInfo.h24
-rw-r--r--lib/Target/Mips/Mips16InstrInfo.td4
-rw-r--r--lib/Target/Mips/Mips16RegisterInfo.cpp9
-rw-r--r--lib/Target/Mips/Mips16RegisterInfo.h2
-rw-r--r--lib/Target/Mips/Mips64InstrInfo.td32
-rw-r--r--lib/Target/Mips/MipsAsmPrinter.cpp16
-rw-r--r--lib/Target/Mips/MipsCodeEmitter.cpp36
-rw-r--r--lib/Target/Mips/MipsConstantIslandPass.cpp6
-rw-r--r--lib/Target/Mips/MipsDSPInstrFormats.td27
-rw-r--r--lib/Target/Mips/MipsDSPInstrInfo.td459
-rw-r--r--lib/Target/Mips/MipsDelaySlotFiller.cpp6
-rw-r--r--lib/Target/Mips/MipsFrameLowering.h5
-rw-r--r--lib/Target/Mips/MipsISelDAGToDAG.cpp1
-rw-r--r--lib/Target/Mips/MipsISelLowering.cpp460
-rw-r--r--lib/Target/Mips/MipsISelLowering.h24
-rw-r--r--lib/Target/Mips/MipsInstrFPU.td27
-rw-r--r--lib/Target/Mips/MipsInstrFormats.td36
-rw-r--r--lib/Target/Mips/MipsInstrInfo.h30
-rw-r--r--lib/Target/Mips/MipsInstrInfo.td298
-rw-r--r--lib/Target/Mips/MipsLongBranch.cpp2
-rw-r--r--lib/Target/Mips/MipsModuleISelDAGToDAG.cpp34
-rw-r--r--lib/Target/Mips/MipsModuleISelDAGToDAG.h66
-rw-r--r--lib/Target/Mips/MipsOs16.cpp113
-rw-r--r--lib/Target/Mips/MipsOs16.h49
-rw-r--r--lib/Target/Mips/MipsRegisterInfo.h3
-rw-r--r--lib/Target/Mips/MipsRegisterInfo.td53
-rw-r--r--lib/Target/Mips/MipsSEFrameLowering.cpp179
-rw-r--r--lib/Target/Mips/MipsSEFrameLowering.h2
-rw-r--r--lib/Target/Mips/MipsSEISelDAGToDAG.cpp85
-rw-r--r--lib/Target/Mips/MipsSEISelDAGToDAG.h3
-rw-r--r--lib/Target/Mips/MipsSEISelLowering.cpp553
-rw-r--r--lib/Target/Mips/MipsSEISelLowering.h24
-rw-r--r--lib/Target/Mips/MipsSEInstrInfo.cpp60
-rw-r--r--lib/Target/Mips/MipsSEInstrInfo.h24
-rw-r--r--lib/Target/Mips/MipsSERegisterInfo.cpp9
-rw-r--r--lib/Target/Mips/MipsSERegisterInfo.h2
-rw-r--r--lib/Target/Mips/MipsSubtarget.cpp78
-rw-r--r--lib/Target/Mips/MipsSubtarget.h48
-rw-r--r--lib/Target/Mips/MipsTargetMachine.cpp91
-rw-r--r--lib/Target/Mips/MipsTargetMachine.h17
51 files changed, 3035 insertions, 1179 deletions
diff --git a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
index ebe12c9..0795cb9 100644
--- a/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -63,7 +63,6 @@ class MipsAsmParser : public MCTargetAsmParser {
MCAsmParser &Parser;
MipsAssemblerOptions Options;
-
#define GET_ASSEMBLER_HEADER
#include "MipsGenAsmMatcher.inc"
@@ -101,6 +100,9 @@ class MipsAsmParser : public MCTargetAsmParser {
MipsAsmParser::OperandMatchResultTy
parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands);
+ bool searchSymbolAlias(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
+ unsigned RegisterClass);
+
bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &,
StringRef Mnemonic);
@@ -119,11 +121,17 @@ class MipsAsmParser : public MCTargetAsmParser {
SmallVectorImpl<MCInst> &Instructions);
void expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
SmallVectorImpl<MCInst> &Instructions);
+ void expandMemInst(MCInst &Inst, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions,
+ bool isLoad,bool isImmOpnd);
bool reportParseError(StringRef ErrorMsg);
- bool parseMemOffset(const MCExpr *&Res);
+ bool parseMemOffset(const MCExpr *&Res, bool isParenExpr);
bool parseRelocOperand(const MCExpr *&Res);
+ const MCExpr* evaluateRelocExpr(const MCExpr *Expr, StringRef RelocStr);
+
+ bool isEvaluated(const MCExpr *Expr);
bool parseDirectiveSet();
bool parseSetAtDirective();
@@ -133,6 +141,8 @@ class MipsAsmParser : public MCTargetAsmParser {
bool parseSetReorderDirective();
bool parseSetNoReorderDirective();
+ bool parseSetAssignment();
+
bool parseDirectiveWord(unsigned Size, SMLoc L);
MCSymbolRefExpr::VariantKind getVariantKind(StringRef Symbol);
@@ -163,9 +173,12 @@ class MipsAsmParser : public MCTargetAsmParser {
bool requestsDoubleOperand(StringRef Mnemonic);
- unsigned getReg(int RC,int RegNo);
+ unsigned getReg(int RC, int RegNo);
int getATReg();
+
+ bool processInstruction(MCInst &Inst, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions);
public:
MipsAsmParser(MCSubtargetInfo &sti, MCAsmParser &parser)
: MCTargetAsmParser(), STI(sti), Parser(parser) {
@@ -258,7 +271,7 @@ public:
void addImmOperands(MCInst &Inst, unsigned N) const {
assert(N == 1 && "Invalid number of operands!");
const MCExpr *Expr = getImm();
- addExpr(Inst,Expr);
+ addExpr(Inst, Expr);
}
void addMemOperands(MCInst &Inst, unsigned N) const {
@@ -267,7 +280,7 @@ public:
Inst.addOperand(MCOperand::CreateReg(getMemBase()));
const MCExpr *Expr = getMemOff();
- addExpr(Inst,Expr);
+ addExpr(Inst, Expr);
}
bool isReg() const { return Kind == k_Register; }
@@ -380,42 +393,112 @@ public:
}
/// getStartLoc - Get the location of the first token of this operand.
- SMLoc getStartLoc() const { return StartLoc; }
+ SMLoc getStartLoc() const {
+ return StartLoc;
+ }
/// getEndLoc - Get the location of the last token of this operand.
- SMLoc getEndLoc() const { return EndLoc; }
+ SMLoc getEndLoc() const {
+ return EndLoc;
+ }
virtual void print(raw_ostream &OS) const {
llvm_unreachable("unimplemented!");
}
-};
+}; // class MipsOperand
+} // namespace
+
+namespace llvm {
+extern const MCInstrDesc MipsInsts[];
+}
+static const MCInstrDesc &getInstDesc(unsigned Opcode) {
+ return MipsInsts[Opcode];
+}
+
+bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions) {
+ const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
+ Inst.setLoc(IDLoc);
+ if (MCID.hasDelaySlot() && Options.isReorder()) {
+ // If this instruction has a delay slot and .set reorder is active,
+ // emit a NOP after it.
+ Instructions.push_back(Inst);
+ MCInst NopInst;
+ NopInst.setOpcode(Mips::SLL);
+ NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
+ NopInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
+ NopInst.addOperand(MCOperand::CreateImm(0));
+ Instructions.push_back(NopInst);
+ return false;
+ }
+
+ if (MCID.mayLoad() || MCID.mayStore()) {
+ // Check the offset of memory operand, if it is a symbol
+ // reference or immediate we may have to expand instructions.
+ for (unsigned i = 0; i < MCID.getNumOperands(); i++) {
+ const MCOperandInfo &OpInfo = MCID.OpInfo[i];
+ if ((OpInfo.OperandType == MCOI::OPERAND_MEMORY)
+ || (OpInfo.OperandType == MCOI::OPERAND_UNKNOWN)) {
+ MCOperand &Op = Inst.getOperand(i);
+ if (Op.isImm()) {
+ int MemOffset = Op.getImm();
+ if (MemOffset < -32768 || MemOffset > 32767) {
+ // Offset can't exceed 16bit value.
+ expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), true);
+ return false;
+ }
+ } else if (Op.isExpr()) {
+ const MCExpr *Expr = Op.getExpr();
+ if (Expr->getKind() == MCExpr::SymbolRef) {
+ const MCSymbolRefExpr *SR =
+ static_cast<const MCSymbolRefExpr*>(Expr);
+ if (SR->getKind() == MCSymbolRefExpr::VK_None) {
+ // Expand symbol.
+ expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
+ return false;
+ }
+ } else if (!isEvaluated(Expr)) {
+ expandMemInst(Inst, IDLoc, Instructions, MCID.mayLoad(), false);
+ return false;
+ }
+ }
+ }
+ } // for
+ } // if load/store
+
+ if (needsExpansion(Inst))
+ expandInstruction(Inst, IDLoc, Instructions);
+ else
+ Instructions.push_back(Inst);
+
+ return false;
}
bool MipsAsmParser::needsExpansion(MCInst &Inst) {
- switch(Inst.getOpcode()) {
- case Mips::LoadImm32Reg:
- case Mips::LoadAddr32Imm:
- case Mips::LoadAddr32Reg:
- return true;
- default:
- return false;
+ switch (Inst.getOpcode()) {
+ case Mips::LoadImm32Reg:
+ case Mips::LoadAddr32Imm:
+ case Mips::LoadAddr32Reg:
+ return true;
+ default:
+ return false;
}
}
void MipsAsmParser::expandInstruction(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions){
- switch(Inst.getOpcode()) {
- case Mips::LoadImm32Reg:
- return expandLoadImm(Inst, IDLoc, Instructions);
- case Mips::LoadAddr32Imm:
- return expandLoadAddressImm(Inst,IDLoc,Instructions);
- case Mips::LoadAddr32Reg:
- return expandLoadAddressReg(Inst,IDLoc,Instructions);
- }
+ SmallVectorImpl<MCInst> &Instructions) {
+ switch (Inst.getOpcode()) {
+ case Mips::LoadImm32Reg:
+ return expandLoadImm(Inst, IDLoc, Instructions);
+ case Mips::LoadAddr32Imm:
+ return expandLoadAddressImm(Inst, IDLoc, Instructions);
+ case Mips::LoadAddr32Reg:
+ return expandLoadAddressReg(Inst, IDLoc, Instructions);
+ }
}
void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions){
+ SmallVectorImpl<MCInst> &Instructions) {
MCInst tmpInst;
const MCOperand &ImmOp = Inst.getOperand(1);
assert(ImmOp.isImm() && "expected immediate operand kind");
@@ -424,26 +507,24 @@ void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
int ImmValue = ImmOp.getImm();
tmpInst.setLoc(IDLoc);
- if ( 0 <= ImmValue && ImmValue <= 65535) {
- // for 0 <= j <= 65535.
+ if (0 <= ImmValue && ImmValue <= 65535) {
+ // For 0 <= j <= 65535.
// li d,j => ori d,$zero,j
tmpInst.setOpcode(Mips::ORi);
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
- tmpInst.addOperand(
- MCOperand::CreateReg(Mips::ZERO));
+ tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Instructions.push_back(tmpInst);
- } else if ( ImmValue < 0 && ImmValue >= -32768) {
- // for -32768 <= j < 0.
+ } else if (ImmValue < 0 && ImmValue >= -32768) {
+ // For -32768 <= j < 0.
// li d,j => addiu d,$zero,j
tmpInst.setOpcode(Mips::ADDiu);
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
- tmpInst.addOperand(
- MCOperand::CreateReg(Mips::ZERO));
+ tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Instructions.push_back(tmpInst);
} else {
- // for any other value of j that is representable as a 32-bit integer.
+ // For any other value of j that is representable as a 32-bit integer.
// li d,j => lui d,hi16(j)
// ori d,d,lo16(j)
tmpInst.setOpcode(Mips::LUi);
@@ -461,7 +542,7 @@ void MipsAsmParser::expandLoadImm(MCInst &Inst, SMLoc IDLoc,
}
void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions){
+ SmallVectorImpl<MCInst> &Instructions) {
MCInst tmpInst;
const MCOperand &ImmOp = Inst.getOperand(2);
assert(ImmOp.isImm() && "expected immediate operand kind");
@@ -470,19 +551,19 @@ void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
const MCOperand &DstRegOp = Inst.getOperand(0);
assert(DstRegOp.isReg() && "expected register operand kind");
int ImmValue = ImmOp.getImm();
- if ( -32768 <= ImmValue && ImmValue <= 65535) {
- //for -32768 <= j <= 65535.
- //la d,j(s) => addiu d,s,j
+ if (-32768 <= ImmValue && ImmValue <= 65535) {
+ // For -32768 <= j <= 65535.
+ // la d,j(s) => addiu d,s,j
tmpInst.setOpcode(Mips::ADDiu);
tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
tmpInst.addOperand(MCOperand::CreateReg(SrcRegOp.getReg()));
tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Instructions.push_back(tmpInst);
} else {
- //for any other value of j that is representable as a 32-bit integer.
- //la d,j(s) => lui d,hi16(j)
- // ori d,d,lo16(j)
- // addu d,d,s
+ // For any other value of j that is representable as a 32-bit integer.
+ // la d,j(s) => lui d,hi16(j)
+ // ori d,d,lo16(j)
+ // addu d,d,s
tmpInst.setOpcode(Mips::LUi);
tmpInst.addOperand(MCOperand::CreateReg(DstRegOp.getReg()));
tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
@@ -503,26 +584,25 @@ void MipsAsmParser::expandLoadAddressReg(MCInst &Inst, SMLoc IDLoc,
}
void MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
- SmallVectorImpl<MCInst> &Instructions){
+ SmallVectorImpl<MCInst> &Instructions) {
MCInst tmpInst;
const MCOperand &ImmOp = Inst.getOperand(1);
assert(ImmOp.isImm() && "expected immediate operand kind");
const MCOperand &RegOp = Inst.getOperand(0);
assert(RegOp.isReg() && "expected register operand kind");
int ImmValue = ImmOp.getImm();
- if ( -32768 <= ImmValue && ImmValue <= 65535) {
- //for -32768 <= j <= 65535.
- //la d,j => addiu d,$zero,j
+ if (-32768 <= ImmValue && ImmValue <= 65535) {
+ // For -32768 <= j <= 65535.
+ // la d,j => addiu d,$zero,j
tmpInst.setOpcode(Mips::ADDiu);
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
- tmpInst.addOperand(
- MCOperand::CreateReg(Mips::ZERO));
+ tmpInst.addOperand(MCOperand::CreateReg(Mips::ZERO));
tmpInst.addOperand(MCOperand::CreateImm(ImmValue));
Instructions.push_back(tmpInst);
} else {
- //for any other value of j that is representable as a 32-bit integer.
- //la d,j => lui d,hi16(j)
- // ori d,d,lo16(j)
+ // For any other value of j that is representable as a 32-bit integer.
+ // la d,j => lui d,hi16(j)
+ // ori d,d,lo16(j)
tmpInst.setOpcode(Mips::LUi);
tmpInst.addOperand(MCOperand::CreateReg(RegOp.getReg()));
tmpInst.addOperand(MCOperand::CreateImm((ImmValue & 0xffff0000) >> 16));
@@ -536,28 +616,105 @@ void MipsAsmParser::expandLoadAddressImm(MCInst &Inst, SMLoc IDLoc,
}
}
+void MipsAsmParser::expandMemInst(MCInst &Inst, SMLoc IDLoc,
+ SmallVectorImpl<MCInst> &Instructions, bool isLoad, bool isImmOpnd) {
+ const MCSymbolRefExpr *SR;
+ MCInst TempInst;
+ unsigned ImmOffset, HiOffset, LoOffset;
+ const MCExpr *ExprOffset;
+ unsigned TmpRegNum;
+ unsigned AtRegNum = getReg((isMips64()) ? Mips::CPU64RegsRegClassID
+ : Mips::CPURegsRegClassID, getATReg());
+ // 1st operand is either the source or destination register.
+ assert(Inst.getOperand(0).isReg() && "expected register operand kind");
+ unsigned RegOpNum = Inst.getOperand(0).getReg();
+ // 2nd operand is the base register.
+ assert(Inst.getOperand(1).isReg() && "expected register operand kind");
+ unsigned BaseRegNum = Inst.getOperand(1).getReg();
+ // 3rd operand is either an immediate or expression.
+ if (isImmOpnd) {
+ assert(Inst.getOperand(2).isImm() && "expected immediate operand kind");
+ ImmOffset = Inst.getOperand(2).getImm();
+ LoOffset = ImmOffset & 0x0000ffff;
+ HiOffset = (ImmOffset & 0xffff0000) >> 16;
+ // If msb of LoOffset is 1(negative number) we must increment HiOffset.
+ if (LoOffset & 0x8000)
+ HiOffset++;
+ } else
+ ExprOffset = Inst.getOperand(2).getExpr();
+ // All instructions will have the same location.
+ TempInst.setLoc(IDLoc);
+ // 1st instruction in expansion is LUi. For load instruction we can use
+ // the dst register as a temporary if base and dst are different,
+ // but for stores we must use $at.
+ TmpRegNum = (isLoad && (BaseRegNum != RegOpNum)) ? RegOpNum : AtRegNum;
+ TempInst.setOpcode(Mips::LUi);
+ TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
+ if (isImmOpnd)
+ TempInst.addOperand(MCOperand::CreateImm(HiOffset));
+ else {
+ if (ExprOffset->getKind() == MCExpr::SymbolRef) {
+ SR = static_cast<const MCSymbolRefExpr*>(ExprOffset);
+ const MCSymbolRefExpr *HiExpr = MCSymbolRefExpr::Create(
+ SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_HI,
+ getContext());
+ TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
+ } else {
+ const MCExpr *HiExpr = evaluateRelocExpr(ExprOffset, "hi");
+ TempInst.addOperand(MCOperand::CreateExpr(HiExpr));
+ }
+ }
+ // Add the instruction to the list.
+ Instructions.push_back(TempInst);
+ // Prepare TempInst for next instruction.
+ TempInst.clear();
+ // Add temp register to base.
+ TempInst.setOpcode(Mips::ADDu);
+ TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
+ TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
+ TempInst.addOperand(MCOperand::CreateReg(BaseRegNum));
+ Instructions.push_back(TempInst);
+ TempInst.clear();
+ // And finaly, create original instruction with low part
+ // of offset and new base.
+ TempInst.setOpcode(Inst.getOpcode());
+ TempInst.addOperand(MCOperand::CreateReg(RegOpNum));
+ TempInst.addOperand(MCOperand::CreateReg(TmpRegNum));
+ if (isImmOpnd)
+ TempInst.addOperand(MCOperand::CreateImm(LoOffset));
+ else {
+ if (ExprOffset->getKind() == MCExpr::SymbolRef) {
+ const MCSymbolRefExpr *LoExpr = MCSymbolRefExpr::Create(
+ SR->getSymbol().getName(), MCSymbolRefExpr::VK_Mips_ABS_LO,
+ getContext());
+ TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
+ } else {
+ const MCExpr *LoExpr = evaluateRelocExpr(ExprOffset, "lo");
+ TempInst.addOperand(MCOperand::CreateExpr(LoExpr));
+ }
+ }
+ Instructions.push_back(TempInst);
+ TempInst.clear();
+}
+
bool MipsAsmParser::
MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
SmallVectorImpl<MCParsedAsmOperand*> &Operands,
MCStreamer &Out, unsigned &ErrorInfo,
bool MatchingInlineAsm) {
MCInst Inst;
+ SmallVector<MCInst, 8> Instructions;
unsigned MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
MatchingInlineAsm);
switch (MatchResult) {
- default: break;
+ default:
+ break;
case Match_Success: {
- if (needsExpansion(Inst)) {
- SmallVector<MCInst, 4> Instructions;
- expandInstruction(Inst, IDLoc, Instructions);
- for(unsigned i =0; i < Instructions.size(); i++){
- Out.EmitInstruction(Instructions[i]);
- }
- } else {
- Inst.setLoc(IDLoc);
- Out.EmitInstruction(Inst);
- }
+ if (processInstruction(Inst, IDLoc, Instructions))
+ return true;
+ for (unsigned i = 0; i < Instructions.size(); i++)
+ Out.EmitInstruction(Instructions[i]);
return false;
}
case Match_MissingFeature:
@@ -569,8 +726,9 @@ MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
if (ErrorInfo >= Operands.size())
return Error(IDLoc, "too few operands for instruction");
- ErrorLoc = ((MipsOperand*)Operands[ErrorInfo])->getStartLoc();
- if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
+ ErrorLoc = ((MipsOperand*) Operands[ErrorInfo])->getStartLoc();
+ if (ErrorLoc == SMLoc())
+ ErrorLoc = IDLoc;
}
return Error(ErrorLoc, "invalid operand for instruction");
@@ -621,10 +779,10 @@ int MipsAsmParser::matchCPURegisterName(StringRef Name) {
.Case("t9", 25)
.Default(-1);
- // Although SGI documentation just cut out t0-t3 for n32/n64,
+ // Although SGI documentation just cuts out t0-t3 for n32/n64,
// GNU pushes the values of t0-t3 to override the o32/o64 values for t4-t7
// We are supporting both cases, so for t0-t3 we'll just push them to t4-t7.
- if (isMips64() && 8 <= CC && CC <= 11)
+ if (isMips64() && 8 <= CC && CC <= 11)
CC += 4;
if (CC == -1 && isMips64())
@@ -640,19 +798,23 @@ int MipsAsmParser::matchCPURegisterName(StringRef Name) {
return CC;
}
+
int MipsAsmParser::matchRegisterName(StringRef Name, bool is64BitReg) {
+ if (Name.equals("fcc0"))
+ return Mips::FCC0;
+
int CC;
CC = matchCPURegisterName(Name);
if (CC != -1)
- return matchRegisterByNumber(CC,is64BitReg?Mips::CPU64RegsRegClassID:
- Mips::CPURegsRegClassID);
+ return matchRegisterByNumber(CC, is64BitReg ? Mips::CPU64RegsRegClassID
+ : Mips::CPURegsRegClassID);
if (Name[0] == 'f') {
StringRef NumString = Name.substr(1);
unsigned IntVal;
- if( NumString.getAsInteger(10, IntVal))
- return -1; // not integer
+ if (NumString.getAsInteger(10, IntVal))
+ return -1; // This is not an integer.
if (IntVal > 31)
return -1;
@@ -661,18 +823,19 @@ int MipsAsmParser::matchRegisterName(StringRef Name, bool is64BitReg) {
if (Format == FP_FORMAT_S || Format == FP_FORMAT_W)
return getReg(Mips::FGR32RegClassID, IntVal);
if (Format == FP_FORMAT_D) {
- if(isFP64()) {
+ if (isFP64()) {
return getReg(Mips::FGR64RegClassID, IntVal);
}
- // only even numbers available as register pairs
- if (( IntVal > 31) || (IntVal%2 != 0))
+ // Only even numbers available as register pairs.
+ if ((IntVal > 31) || (IntVal % 2 != 0))
return -1;
- return getReg(Mips::AFGR64RegClassID, IntVal/2);
+ return getReg(Mips::AFGR64RegClassID, IntVal / 2);
}
}
return -1;
}
+
void MipsAsmParser::setDefaultFpFormat() {
if (isMips64() || isFP64())
@@ -692,6 +855,7 @@ bool MipsAsmParser::requestsDoubleOperand(StringRef Mnemonic){
return IsDouble;
}
+
void MipsAsmParser::setFpFormat(StringRef Format) {
FpFormat = StringSwitch<FpFormatTy>(Format.lower())
@@ -714,7 +878,7 @@ int MipsAsmParser::getATReg() {
return Options.getATRegNum();
}
-unsigned MipsAsmParser::getReg(int RC,int RegNo) {
+unsigned MipsAsmParser::getReg(int RC, int RegNo) {
return *(getContext().getRegisterInfo().getRegClass(RC).begin() + RegNo);
}
@@ -735,14 +899,12 @@ int MipsAsmParser::tryParseRegister(bool is64BitReg) {
RegNum = matchRegisterName(lowerCase, is64BitReg);
} else if (Tok.is(AsmToken::Integer))
RegNum = matchRegisterByNumber(static_cast<unsigned>(Tok.getIntVal()),
- is64BitReg ? Mips::CPU64RegsRegClassID
- : Mips::CPURegsRegClassID);
+ is64BitReg ? Mips::CPU64RegsRegClassID : Mips::CPURegsRegClassID);
return RegNum;
}
-bool MipsAsmParser::
- tryParseRegisterOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
- bool is64BitReg){
+bool MipsAsmParser::tryParseRegisterOperand(
+ SmallVectorImpl<MCParsedAsmOperand*> &Operands, bool is64BitReg) {
SMLoc S = Parser.getTok().getLoc();
int RegNo = -1;
@@ -752,7 +914,7 @@ bool MipsAsmParser::
return true;
Operands.push_back(MipsOperand::CreateReg(RegNo, S,
- Parser.getTok().getLoc()));
+ Parser.getTok().getLoc()));
Parser.Lex(); // Eat register token.
return false;
}
@@ -775,19 +937,19 @@ bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
Error(Parser.getTok().getLoc(), "unexpected token in operand");
return true;
case AsmToken::Dollar: {
- // parse register
+ // Parse the register.
SMLoc S = Parser.getTok().getLoc();
Parser.Lex(); // Eat dollar token.
- // parse register operand
+ // Parse the register operand.
if (!tryParseRegisterOperand(Operands, isMips64())) {
if (getLexer().is(AsmToken::LParen)) {
- // check if it is indexed addressing operand
+ // Check if it is indexed addressing operand.
Operands.push_back(MipsOperand::CreateToken("(", S));
- Parser.Lex(); // eat parenthesis
+ Parser.Lex(); // Eat the parenthesis.
if (getLexer().isNot(AsmToken::Dollar))
return true;
- Parser.Lex(); // eat dollar
+ Parser.Lex(); // Eat the dollar
if (tryParseRegisterOperand(Operands, isMips64()))
return true;
@@ -800,7 +962,7 @@ bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
}
return false;
}
- // maybe it is a symbol reference
+ // Maybe it is a symbol reference.
StringRef Identifier;
if (Parser.parseIdentifier(Identifier))
return true;
@@ -809,7 +971,7 @@ bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
MCSymbol *Sym = getContext().GetOrCreateSymbol("$" + Identifier);
- // Otherwise create a symbol ref.
+ // Otherwise create a symbol reference.
const MCExpr *Res = MCSymbolRefExpr::Create(Sym, MCSymbolRefExpr::VK_None,
getContext());
@@ -817,12 +979,17 @@ bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
return false;
}
case AsmToken::Identifier:
+ // Look for the existing symbol, we should check if
+ // we need to assigne the propper RegisterKind.
+ if (searchSymbolAlias(Operands, MipsOperand::Kind_None))
+ return false;
+ // Else drop to expression parsing.
case AsmToken::LParen:
case AsmToken::Minus:
case AsmToken::Plus:
case AsmToken::Integer:
case AsmToken::String: {
- // quoted label names
+ // Quoted label names.
const MCExpr *IdVal;
SMLoc S = Parser.getTok().getLoc();
if (getParser().parseExpression(IdVal))
@@ -832,9 +999,9 @@ bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
return false;
}
case AsmToken::Percent: {
- // it is a symbol reference or constant expression
+ // It is a symbol reference or constant expression.
const MCExpr *IdVal;
- SMLoc S = Parser.getTok().getLoc(); // start location of the operand
+ SMLoc S = Parser.getTok().getLoc(); // Start location of the operand.
if (parseRelocOperand(IdVal))
return true;
@@ -847,129 +1014,200 @@ bool MipsAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*>&Operands,
return true;
}
-bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
+const MCExpr* MipsAsmParser::evaluateRelocExpr(const MCExpr *Expr,
+ StringRef RelocStr) {
+ const MCExpr *Res;
+ // Check the type of the expression.
+ if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Expr)) {
+ // It's a constant, evaluate lo or hi value.
+ if (RelocStr == "lo") {
+ short Val = MCE->getValue();
+ Res = MCConstantExpr::Create(Val, getContext());
+ } else if (RelocStr == "hi") {
+ int Val = MCE->getValue();
+ int LoSign = Val & 0x8000;
+ Val = (Val & 0xffff0000) >> 16;
+ // Lower part is treated as a signed int, so if it is negative
+ // we must add 1 to the hi part to compensate.
+ if (LoSign)
+ Val++;
+ Res = MCConstantExpr::Create(Val, getContext());
+ } else {
+ llvm_unreachable("Invalid RelocStr value");
+ }
+ return Res;
+ }
+
+ if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(Expr)) {
+ // It's a symbol, create a symbolic expression from the symbol.
+ StringRef Symbol = MSRE->getSymbol().getName();
+ MCSymbolRefExpr::VariantKind VK = getVariantKind(RelocStr);
+ Res = MCSymbolRefExpr::Create(Symbol, VK, getContext());
+ return Res;
+ }
- Parser.Lex(); // eat % token
- const AsmToken &Tok = Parser.getTok(); // get next token, operation
+ if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
+ const MCExpr *LExp = evaluateRelocExpr(BE->getLHS(), RelocStr);
+ const MCExpr *RExp = evaluateRelocExpr(BE->getRHS(), RelocStr);
+ Res = MCBinaryExpr::Create(BE->getOpcode(), LExp, RExp, getContext());
+ return Res;
+ }
+
+ if (const MCUnaryExpr *UN = dyn_cast<MCUnaryExpr>(Expr)) {
+ const MCExpr *UnExp = evaluateRelocExpr(UN->getSubExpr(), RelocStr);
+ Res = MCUnaryExpr::Create(UN->getOpcode(), UnExp, getContext());
+ return Res;
+ }
+ // Just return the original expression.
+ return Expr;
+}
+
+bool MipsAsmParser::isEvaluated(const MCExpr *Expr) {
+
+ switch (Expr->getKind()) {
+ case MCExpr::Constant:
+ return true;
+ case MCExpr::SymbolRef:
+ return (cast<MCSymbolRefExpr>(Expr)->getKind() != MCSymbolRefExpr::VK_None);
+ case MCExpr::Binary:
+ if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr)) {
+ if (!isEvaluated(BE->getLHS()))
+ return false;
+ return isEvaluated(BE->getRHS());
+ }
+ case MCExpr::Unary:
+ return isEvaluated(cast<MCUnaryExpr>(Expr)->getSubExpr());
+ default:
+ return false;
+ }
+ return false;
+}
+
+bool MipsAsmParser::parseRelocOperand(const MCExpr *&Res) {
+ Parser.Lex(); // Eat the % token.
+ const AsmToken &Tok = Parser.getTok(); // Get next token, operation.
if (Tok.isNot(AsmToken::Identifier))
return true;
std::string Str = Tok.getIdentifier().str();
- Parser.Lex(); // eat identifier
- // now make expression from the rest of the operand
+ Parser.Lex(); // Eat the identifier.
+ // Now make an expression from the rest of the operand.
const MCExpr *IdVal;
SMLoc EndLoc;
if (getLexer().getKind() == AsmToken::LParen) {
while (1) {
- Parser.Lex(); // eat '(' token
+ Parser.Lex(); // Eat the '(' token.
if (getLexer().getKind() == AsmToken::Percent) {
- Parser.Lex(); // eat % token
+ Parser.Lex(); // Eat the % token.
const AsmToken &nextTok = Parser.getTok();
if (nextTok.isNot(AsmToken::Identifier))
return true;
Str += "(%";
Str += nextTok.getIdentifier();
- Parser.Lex(); // eat identifier
+ Parser.Lex(); // Eat the identifier.
if (getLexer().getKind() != AsmToken::LParen)
return true;
} else
break;
}
- if (getParser().parseParenExpression(IdVal,EndLoc))
+ if (getParser().parseParenExpression(IdVal, EndLoc))
return true;
while (getLexer().getKind() == AsmToken::RParen)
- Parser.Lex(); // eat ')' token
+ Parser.Lex(); // Eat the ')' token.
} else
- return true; // parenthesis must follow reloc operand
-
- // Check the type of the expression
- if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(IdVal)) {
- // it's a constant, evaluate lo or hi value
- int Val = MCE->getValue();
- if (Str == "lo") {
- Val = Val & 0xffff;
- } else if (Str == "hi") {
- int LoSign = Val & 0x8000;
- Val = (Val & 0xffff0000) >> 16;
- //lower part is treated as signed int, so if it is negative
- //we must add 1 to hi part to compensate
- if (LoSign)
- Val++;
- }
- Res = MCConstantExpr::Create(Val, getContext());
- return false;
- }
+ return true; // Parenthesis must follow the relocation operand.
- if (const MCSymbolRefExpr *MSRE = dyn_cast<MCSymbolRefExpr>(IdVal)) {
- // it's a symbol, create symbolic expression from symbol
- StringRef Symbol = MSRE->getSymbol().getName();
- MCSymbolRefExpr::VariantKind VK = getVariantKind(Str);
- Res = MCSymbolRefExpr::Create(Symbol,VK,getContext());
- return false;
- }
- return true;
+ Res = evaluateRelocExpr(IdVal, Str);
+ return false;
}
bool MipsAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
SMLoc &EndLoc) {
-
StartLoc = Parser.getTok().getLoc();
RegNo = tryParseRegister(isMips64());
EndLoc = Parser.getTok().getLoc();
- return (RegNo == (unsigned)-1);
+ return (RegNo == (unsigned) -1);
}
-bool MipsAsmParser::parseMemOffset(const MCExpr *&Res) {
-
+bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
SMLoc S;
+ bool Result = true;
- switch(getLexer().getKind()) {
+ while (getLexer().getKind() == AsmToken::LParen)
+ Parser.Lex();
+
+ switch (getLexer().getKind()) {
default:
return true;
+ case AsmToken::Identifier:
+ case AsmToken::LParen:
case AsmToken::Integer:
case AsmToken::Minus:
case AsmToken::Plus:
- return (getParser().parseExpression(Res));
+ if (isParenExpr)
+ Result = getParser().parseParenExpression(Res, S);
+ else
+ Result = (getParser().parseExpression(Res));
+ while (getLexer().getKind() == AsmToken::RParen)
+ Parser.Lex();
+ break;
case AsmToken::Percent:
- return parseRelocOperand(Res);
- case AsmToken::LParen:
- return false; // it's probably assuming 0
+ Result = parseRelocOperand(Res);
}
- return true;
+ return Result;
}
MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
- SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
+ SmallVectorImpl<MCParsedAsmOperand*>&Operands) {
const MCExpr *IdVal = 0;
SMLoc S;
- // first operand is the offset
+ bool isParenExpr = false;
+ // First operand is the offset.
S = Parser.getTok().getLoc();
- if (parseMemOffset(IdVal))
- return MatchOperand_ParseFail;
+ if (getLexer().getKind() == AsmToken::LParen) {
+ Parser.Lex();
+ isParenExpr = true;
+ }
- const AsmToken &Tok = Parser.getTok(); // get next token
- if (Tok.isNot(AsmToken::LParen)) {
- MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
- if (Mnemonic->getToken() == "la") {
- SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() -1);
- Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
- return MatchOperand_Success;
+ if (getLexer().getKind() != AsmToken::Dollar) {
+ if (parseMemOffset(IdVal, isParenExpr))
+ return MatchOperand_ParseFail;
+
+ const AsmToken &Tok = Parser.getTok(); // Get the next token.
+ if (Tok.isNot(AsmToken::LParen)) {
+ MipsOperand *Mnemonic = static_cast<MipsOperand*>(Operands[0]);
+ if (Mnemonic->getToken() == "la") {
+ SMLoc E = SMLoc::getFromPointer(
+ Parser.getTok().getLoc().getPointer() - 1);
+ Operands.push_back(MipsOperand::CreateImm(IdVal, S, E));
+ return MatchOperand_Success;
+ }
+ if (Tok.is(AsmToken::EndOfStatement)) {
+ SMLoc E = SMLoc::getFromPointer(
+ Parser.getTok().getLoc().getPointer() - 1);
+
+ // Zero register assumed, add a memory operand with ZERO as its base.
+ Operands.push_back(MipsOperand::CreateMem(isMips64() ? Mips::ZERO_64
+ : Mips::ZERO,
+ IdVal, S, E));
+ return MatchOperand_Success;
+ }
+ Error(Parser.getTok().getLoc(), "'(' expected");
+ return MatchOperand_ParseFail;
}
- Error(Parser.getTok().getLoc(), "'(' expected");
- return MatchOperand_ParseFail;
- }
- Parser.Lex(); // Eat '(' token.
+ Parser.Lex(); // Eat the '(' token.
+ }
- const AsmToken &Tok1 = Parser.getTok(); // get next token
+ const AsmToken &Tok1 = Parser.getTok(); // Get next token
if (Tok1.is(AsmToken::Dollar)) {
- Parser.Lex(); // Eat '$' token.
+ Parser.Lex(); // Eat the '$' token.
if (tryParseRegisterOperand(Operands, isMips64())) {
Error(Parser.getTok().getLoc(), "unexpected token in operand");
return MatchOperand_ParseFail;
@@ -980,7 +1218,7 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
return MatchOperand_ParseFail;
}
- const AsmToken &Tok2 = Parser.getTok(); // get next token
+ const AsmToken &Tok2 = Parser.getTok(); // Get next token.
if (Tok2.isNot(AsmToken::RParen)) {
Error(Parser.getTok().getLoc(), "')' expected");
return MatchOperand_ParseFail;
@@ -988,17 +1226,26 @@ MipsAsmParser::OperandMatchResultTy MipsAsmParser::parseMemOperand(
SMLoc E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
- Parser.Lex(); // Eat ')' token.
+ Parser.Lex(); // Eat the ')' token.
if (IdVal == 0)
IdVal = MCConstantExpr::Create(0, getContext());
- // now replace register operand with the mem operand
+ // Replace the register operand with the memory operand.
MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
int RegNo = op->getReg();
- // remove register from operands
+ // Remove the register from the operands.
Operands.pop_back();
- // and add memory operand
+ // Add the memory operand.
+ if (const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(IdVal)) {
+ int64_t Imm;
+ if (IdVal->EvaluateAsAbsolute(Imm))
+ IdVal = MCConstantExpr::Create(Imm, getContext());
+ else if (BE->getLHS()->getKind() != MCExpr::SymbolRef)
+ IdVal = MCBinaryExpr::Create(BE->getOpcode(), BE->getRHS(), BE->getLHS(),
+ getContext());
+ }
+
Operands.push_back(MipsOperand::CreateMem(RegNo, IdVal, S, E));
delete op;
return MatchOperand_Success;
@@ -1009,13 +1256,18 @@ MipsAsmParser::parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
if (!isMips64())
return MatchOperand_NoMatch;
- // if the first token is not '$' we have an error
+ if (getLexer().getKind() == AsmToken::Identifier) {
+ if (searchSymbolAlias(Operands, MipsOperand::Kind_CPU64Regs))
+ return MatchOperand_Success;
+ return MatchOperand_NoMatch;
+ }
+ // If the first token is not '$', we have an error.
if (Parser.getTok().isNot(AsmToken::Dollar))
return MatchOperand_NoMatch;
Parser.Lex(); // Eat $
- if(!tryParseRegisterOperand(Operands, true)) {
- // set the proper register kind
+ if (!tryParseRegisterOperand(Operands, true)) {
+ // Set the proper register kind.
MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
op->setRegKind(MipsOperand::Kind_CPU64Regs);
return MatchOperand_Success;
@@ -1023,16 +1275,59 @@ MipsAsmParser::parseCPU64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
return MatchOperand_NoMatch;
}
+bool MipsAsmParser::searchSymbolAlias(
+ SmallVectorImpl<MCParsedAsmOperand*> &Operands, unsigned RegisterKind) {
+
+ MCSymbol *Sym = getContext().LookupSymbol(Parser.getTok().getIdentifier());
+ if (Sym) {
+ SMLoc S = Parser.getTok().getLoc();
+ const MCExpr *Expr;
+ if (Sym->isVariable())
+ Expr = Sym->getVariableValue();
+ else
+ return false;
+ if (Expr->getKind() == MCExpr::SymbolRef) {
+ const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr*>(Expr);
+ const StringRef DefSymbol = Ref->getSymbol().getName();
+ if (DefSymbol.startswith("$")) {
+ // Lookup for the register with the corresponding name.
+ int RegNum = matchRegisterName(DefSymbol.substr(1), isMips64());
+ if (RegNum > -1) {
+ Parser.Lex();
+ MipsOperand *op = MipsOperand::CreateReg(RegNum, S,
+ Parser.getTok().getLoc());
+ op->setRegKind((MipsOperand::RegisterKind) RegisterKind);
+ Operands.push_back(op);
+ return true;
+ }
+ }
+ } else if (Expr->getKind() == MCExpr::Constant) {
+ Parser.Lex();
+ const MCConstantExpr *Const = static_cast<const MCConstantExpr*>(Expr);
+ MipsOperand *op = MipsOperand::CreateImm(Const, S,
+ Parser.getTok().getLoc());
+ Operands.push_back(op);
+ return true;
+ }
+ }
+ return false;
+}
+
MipsAsmParser::OperandMatchResultTy
MipsAsmParser::parseCPURegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
- // if the first token is not '$' we have an error
+ if (getLexer().getKind() == AsmToken::Identifier) {
+ if (searchSymbolAlias(Operands, MipsOperand::Kind_CPURegs))
+ return MatchOperand_Success;
+ return MatchOperand_NoMatch;
+ }
+ // If the first token is not '$' we have an error.
if (Parser.getTok().isNot(AsmToken::Dollar))
return MatchOperand_NoMatch;
Parser.Lex(); // Eat $
- if(!tryParseRegisterOperand(Operands, false)) {
- // set the propper register kind
+ if (!tryParseRegisterOperand(Operands, false)) {
+ // Set the proper register kind.
MipsOperand* op = static_cast<MipsOperand*>(Operands.back());
op->setRegKind(MipsOperand::Kind_CPURegs);
return MatchOperand_Success;
@@ -1046,87 +1341,88 @@ MipsAsmParser::parseHWRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
if (isMips64())
return MatchOperand_NoMatch;
- // if the first token is not '$' we have error
+ // If the first token is not '$' we have error.
if (Parser.getTok().isNot(AsmToken::Dollar))
return MatchOperand_NoMatch;
SMLoc S = Parser.getTok().getLoc();
- Parser.Lex(); // Eat $
+ Parser.Lex(); // Eat the '$'.
- const AsmToken &Tok = Parser.getTok(); // get next token
+ const AsmToken &Tok = Parser.getTok(); // Get the next token.
if (Tok.isNot(AsmToken::Integer))
return MatchOperand_NoMatch;
unsigned RegNum = Tok.getIntVal();
- // at the moment only hwreg29 is supported
+ // At the moment only hwreg29 is supported.
if (RegNum != 29)
return MatchOperand_ParseFail;
MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29, S,
- Parser.getTok().getLoc());
+ Parser.getTok().getLoc());
op->setRegKind(MipsOperand::Kind_HWRegs);
Operands.push_back(op);
- Parser.Lex(); // Eat reg number
+ Parser.Lex(); // Eat the register number.
return MatchOperand_Success;
}
MipsAsmParser::OperandMatchResultTy
-MipsAsmParser::parseHW64Regs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+MipsAsmParser::parseHW64Regs(
+ SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
if (!isMips64())
return MatchOperand_NoMatch;
- //if the first token is not '$' we have error
+ // If the first token is not '$' we have an error.
if (Parser.getTok().isNot(AsmToken::Dollar))
return MatchOperand_NoMatch;
SMLoc S = Parser.getTok().getLoc();
Parser.Lex(); // Eat $
- const AsmToken &Tok = Parser.getTok(); // get next token
+ const AsmToken &Tok = Parser.getTok(); // Get the next token.
if (Tok.isNot(AsmToken::Integer))
return MatchOperand_NoMatch;
unsigned RegNum = Tok.getIntVal();
- // at the moment only hwreg29 is supported
+ // At the moment only hwreg29 is supported.
if (RegNum != 29)
return MatchOperand_ParseFail;
MipsOperand *op = MipsOperand::CreateReg(Mips::HWR29_64, S,
- Parser.getTok().getLoc());
+ Parser.getTok().getLoc());
op->setRegKind(MipsOperand::Kind_HW64Regs);
Operands.push_back(op);
- Parser.Lex(); // Eat reg number
+ Parser.Lex(); // Eat the register number.
return MatchOperand_Success;
}
MipsAsmParser::OperandMatchResultTy
MipsAsmParser::parseCCRRegs(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
unsigned RegNum;
- //if the first token is not '$' we have error
+ // If the first token is not '$' we have an error.
if (Parser.getTok().isNot(AsmToken::Dollar))
return MatchOperand_NoMatch;
SMLoc S = Parser.getTok().getLoc();
- Parser.Lex(); // Eat $
+ Parser.Lex(); // Eat the '$'
- const AsmToken &Tok = Parser.getTok(); // get next token
+ const AsmToken &Tok = Parser.getTok(); // Get next token.
if (Tok.is(AsmToken::Integer)) {
RegNum = Tok.getIntVal();
- // at the moment only fcc0 is supported
+ // At the moment only fcc0 is supported.
if (RegNum != 0)
return MatchOperand_ParseFail;
} else if (Tok.is(AsmToken::Identifier)) {
- // at the moment only fcc0 is supported
+ // At the moment only fcc0 is supported.
if (Tok.getIdentifier() != "fcc0")
return MatchOperand_ParseFail;
} else
return MatchOperand_NoMatch;
MipsOperand *op = MipsOperand::CreateReg(Mips::FCC0, S,
- Parser.getTok().getLoc());
+ Parser.getTok().getLoc());
op->setRegKind(MipsOperand::Kind_CCRRegs);
Operands.push_back(op);
- Parser.Lex(); // Eat reg number
+ Parser.Lex(); // Eat the register number.
return MatchOperand_Success;
}
@@ -1158,23 +1454,23 @@ MCSymbolRefExpr::VariantKind MipsAsmParser::getVariantKind(StringRef Symbol) {
static int ConvertCcString(StringRef CondString) {
int CC = StringSwitch<unsigned>(CondString)
- .Case(".f", 0)
- .Case(".un", 1)
- .Case(".eq", 2)
- .Case(".ueq", 3)
- .Case(".olt", 4)
- .Case(".ult", 5)
- .Case(".ole", 6)
- .Case(".ule", 7)
- .Case(".sf", 8)
- .Case(".ngle", 9)
- .Case(".seq", 10)
- .Case(".ngl", 11)
- .Case(".lt", 12)
- .Case(".nge", 13)
- .Case(".le", 14)
- .Case(".ngt", 15)
- .Default(-1);
+ .Case(".f", 0)
+ .Case(".un", 1)
+ .Case(".eq", 2)
+ .Case(".ueq", 3)
+ .Case(".olt", 4)
+ .Case(".ult", 5)
+ .Case(".ole", 6)
+ .Case(".ule", 7)
+ .Case(".sf", 8)
+ .Case(".ngle", 9)
+ .Case(".seq", 10)
+ .Case(".ngl", 11)
+ .Case(".lt", 12)
+ .Case(".nge", 13)
+ .Case(".le", 14)
+ .Case(".ngt", 15)
+ .Default(-1);
return CC;
}
@@ -1182,16 +1478,16 @@ static int ConvertCcString(StringRef CondString) {
bool MipsAsmParser::
parseMathOperation(StringRef Name, SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
- // split the format
+ // Split the format.
size_t Start = Name.find('.'), Next = Name.rfind('.');
StringRef Format1 = Name.slice(Start, Next);
- // and add the first format to the operands
+ // Add the first format to the operands.
Operands.push_back(MipsOperand::CreateToken(Format1, NameLoc));
- // now for the second format
+ // Now for the second format.
StringRef Format2 = Name.slice(Next, StringRef::npos);
Operands.push_back(MipsOperand::CreateToken(Format2, NameLoc));
- // set the format for the first register
+ // Set the format for the first register.
setFpFormat(Format1);
// Read the remaining operands.
@@ -1207,11 +1503,10 @@ parseMathOperation(StringRef Name, SMLoc NameLoc,
SMLoc Loc = getLexer().getLoc();
Parser.eatToEndOfStatement();
return Error(Loc, "unexpected token in argument list");
-
}
- Parser.Lex(); // Eat the comma.
+ Parser.Lex(); // Eat the comma.
- //set the format for the first register
+ // Set the format for the first register
setFpFormat(Format2);
// Parse and remember the operand.
@@ -1228,7 +1523,7 @@ parseMathOperation(StringRef Name, SMLoc NameLoc,
return Error(Loc, "unexpected token in argument list");
}
- Parser.Lex(); // Consume the EndOfStatement
+ Parser.Lex(); // Consume the EndOfStatement.
return false;
}
@@ -1236,13 +1531,12 @@ bool MipsAsmParser::
ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
StringRef Mnemonic;
- // floating point instructions: should register be treated as double?
+ // Floating point instructions: Should the register be treated as a double?
if (requestsDoubleOperand(Name)) {
setFpFormat(FP_FORMAT_D);
- Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
- Mnemonic = Name;
- }
- else {
+ Operands.push_back(MipsOperand::CreateToken(Name, NameLoc));
+ Mnemonic = Name;
+ } else {
setDefaultFpFormat();
// Create the leading tokens for the mnemonic, split by '.' characters.
size_t Start = 0, Next = Name.find('.');
@@ -1251,30 +1545,30 @@ ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
Operands.push_back(MipsOperand::CreateToken(Mnemonic, NameLoc));
if (Next != StringRef::npos) {
- // there is a format token in mnemonic
- // StringRef Rest = Name.slice(Next, StringRef::npos);
- size_t Dot = Name.find('.', Next+1);
+ // There is a format token in mnemonic.
+ size_t Dot = Name.find('.', Next + 1);
StringRef Format = Name.slice(Next, Dot);
- if (Dot == StringRef::npos) //only one '.' in a string, it's a format
+ if (Dot == StringRef::npos) // Only one '.' in a string, it's a format.
Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
else {
- if (Name.startswith("c.")){
- // floating point compare, add '.' and immediate represent for cc
+ if (Name.startswith("c.")) {
+ // Floating point compare, add '.' and immediate represent for cc.
Operands.push_back(MipsOperand::CreateToken(".", NameLoc));
int Cc = ConvertCcString(Format);
if (Cc == -1) {
return Error(NameLoc, "Invalid conditional code");
}
SMLoc E = SMLoc::getFromPointer(
- Parser.getTok().getLoc().getPointer() -1 );
- Operands.push_back(MipsOperand::CreateImm(
- MCConstantExpr::Create(Cc, getContext()), NameLoc, E));
+ Parser.getTok().getLoc().getPointer() - 1);
+ Operands.push_back(
+ MipsOperand::CreateImm(MCConstantExpr::Create(Cc, getContext()),
+ NameLoc, E));
} else {
// trunc, ceil, floor ...
return parseMathOperation(Name, NameLoc, Operands);
}
- // the rest is a format
+ // The rest is a format.
Format = Name.slice(Dot, StringRef::npos);
Operands.push_back(MipsOperand::CreateToken(Format, NameLoc));
}
@@ -1292,8 +1586,8 @@ ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
return Error(Loc, "unexpected token in argument list");
}
- while (getLexer().is(AsmToken::Comma) ) {
- Parser.Lex(); // Eat the comma.
+ while (getLexer().is(AsmToken::Comma)) {
+ Parser.Lex(); // Eat the comma.
// Parse and remember the operand.
if (ParseOperand(Operands, Name)) {
@@ -1310,48 +1604,47 @@ ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
return Error(Loc, "unexpected token in argument list");
}
- Parser.Lex(); // Consume the EndOfStatement
+ Parser.Lex(); // Consume the EndOfStatement.
return false;
}
bool MipsAsmParser::reportParseError(StringRef ErrorMsg) {
- SMLoc Loc = getLexer().getLoc();
- Parser.eatToEndOfStatement();
- return Error(Loc, ErrorMsg);
+ SMLoc Loc = getLexer().getLoc();
+ Parser.eatToEndOfStatement();
+ return Error(Loc, ErrorMsg);
}
bool MipsAsmParser::parseSetNoAtDirective() {
- // line should look like:
- // .set noat
- // set at reg to 0
+ // Line should look like: ".set noat".
+ // set at reg to 0.
Options.setATReg(0);
// eat noat
Parser.Lex();
- // if this is not the end of the statement, report error
+ // If this is not the end of the statement, report an error.
if (getLexer().isNot(AsmToken::EndOfStatement)) {
reportParseError("unexpected token in statement");
return false;
}
- Parser.Lex(); // Consume the EndOfStatement
+ Parser.Lex(); // Consume the EndOfStatement.
return false;
}
+
bool MipsAsmParser::parseSetAtDirective() {
- // line can be
- // .set at - defaults to $1
+ // Line can be .set at - defaults to $1
// or .set at=$reg
int AtRegNo;
getParser().Lex();
if (getLexer().is(AsmToken::EndOfStatement)) {
Options.setATReg(1);
- Parser.Lex(); // Consume the EndOfStatement
+ Parser.Lex(); // Consume the EndOfStatement.
return false;
} else if (getLexer().is(AsmToken::Equal)) {
- getParser().Lex(); //eat '='
+ getParser().Lex(); // Eat the '='.
if (getLexer().isNot(AsmToken::Dollar)) {
reportParseError("unexpected token in statement");
return false;
}
- Parser.Lex(); // eat '$'
+ Parser.Lex(); // Eat the '$'.
const AsmToken &Reg = Parser.getTok();
if (Reg.is(AsmToken::Identifier)) {
AtRegNo = matchCPURegisterName(Reg.getIdentifier());
@@ -1362,7 +1655,7 @@ bool MipsAsmParser::parseSetAtDirective() {
return false;
}
- if ( AtRegNo < 1 || AtRegNo > 31) {
+ if (AtRegNo < 1 || AtRegNo > 31) {
reportParseError("unexpected token in statement");
return false;
}
@@ -1371,13 +1664,13 @@ bool MipsAsmParser::parseSetAtDirective() {
reportParseError("unexpected token in statement");
return false;
}
- getParser().Lex(); //eat reg
+ getParser().Lex(); // Eat the register.
if (getLexer().isNot(AsmToken::EndOfStatement)) {
reportParseError("unexpected token in statement");
return false;
- }
- Parser.Lex(); // Consume the EndOfStatement
+ }
+ Parser.Lex(); // Consume the EndOfStatement.
return false;
} else {
reportParseError("unexpected token in statement");
@@ -1387,43 +1680,43 @@ bool MipsAsmParser::parseSetAtDirective() {
bool MipsAsmParser::parseSetReorderDirective() {
Parser.Lex();
- // if this is not the end of the statement, report error
+ // If this is not the end of the statement, report an error.
if (getLexer().isNot(AsmToken::EndOfStatement)) {
reportParseError("unexpected token in statement");
return false;
}
Options.setReorder();
- Parser.Lex(); // Consume the EndOfStatement
+ Parser.Lex(); // Consume the EndOfStatement.
return false;
}
bool MipsAsmParser::parseSetNoReorderDirective() {
- Parser.Lex();
- // if this is not the end of the statement, report error
- if (getLexer().isNot(AsmToken::EndOfStatement)) {
- reportParseError("unexpected token in statement");
- return false;
- }
- Options.setNoreorder();
- Parser.Lex(); // Consume the EndOfStatement
+ Parser.Lex();
+ // If this is not the end of the statement, report an error.
+ if (getLexer().isNot(AsmToken::EndOfStatement)) {
+ reportParseError("unexpected token in statement");
return false;
+ }
+ Options.setNoreorder();
+ Parser.Lex(); // Consume the EndOfStatement.
+ return false;
}
bool MipsAsmParser::parseSetMacroDirective() {
Parser.Lex();
- // if this is not the end of the statement, report error
+ // If this is not the end of the statement, report an error.
if (getLexer().isNot(AsmToken::EndOfStatement)) {
reportParseError("unexpected token in statement");
return false;
}
Options.setMacro();
- Parser.Lex(); // Consume the EndOfStatement
+ Parser.Lex(); // Consume the EndOfStatement.
return false;
}
bool MipsAsmParser::parseSetNoMacroDirective() {
Parser.Lex();
- // if this is not the end of the statement, report error
+ // If this is not the end of the statement, report an error.
if (getLexer().isNot(AsmToken::EndOfStatement)) {
reportParseError("`noreorder' must be set before `nomacro'");
return false;
@@ -1433,12 +1726,37 @@ bool MipsAsmParser::parseSetNoMacroDirective() {
return false;
}
Options.setNomacro();
- Parser.Lex(); // Consume the EndOfStatement
+ Parser.Lex(); // Consume the EndOfStatement.
return false;
}
+
+bool MipsAsmParser::parseSetAssignment() {
+ StringRef Name;
+ const MCExpr *Value;
+
+ if (Parser.parseIdentifier(Name))
+ reportParseError("expected identifier after .set");
+
+ if (getLexer().isNot(AsmToken::Comma))
+ return reportParseError("unexpected token in .set directive");
+ Lex(); // Eat comma
+
+ if (Parser.parseExpression(Value))
+ reportParseError("expected valid expression after comma");
+
+ // Check if the Name already exists as a symbol.
+ MCSymbol *Sym = getContext().LookupSymbol(Name);
+ if (Sym)
+ return reportParseError("symbol already defined");
+ Sym = getContext().GetOrCreateSymbol(Name);
+ Sym->setVariableValue(Value);
+
+ return false;
+}
+
bool MipsAsmParser::parseDirectiveSet() {
- // get next token
+ // Get the next token.
const AsmToken &Tok = Parser.getTok();
if (Tok.getString() == "noat") {
@@ -1454,13 +1772,17 @@ bool MipsAsmParser::parseDirectiveSet() {
} else if (Tok.getString() == "nomacro") {
return parseSetNoMacroDirective();
} else if (Tok.getString() == "nomips16") {
- // ignore this directive for now
+ // Ignore this directive for now.
Parser.eatToEndOfStatement();
return false;
} else if (Tok.getString() == "nomicromips") {
- // ignore this directive for now
+ // Ignore this directive for now.
Parser.eatToEndOfStatement();
return false;
+ } else {
+ // It is just an identifier, look for an assignment.
+ parseSetAssignment();
+ return false;
}
return true;
@@ -1495,20 +1817,20 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
StringRef IDVal = DirectiveID.getString();
- if ( IDVal == ".ent") {
- // ignore this directive for now
+ if (IDVal == ".ent") {
+ // Ignore this directive for now.
Parser.Lex();
return false;
}
if (IDVal == ".end") {
- // ignore this directive for now
+ // Ignore this directive for now.
Parser.Lex();
return false;
}
if (IDVal == ".frame") {
- // ignore this directive for now
+ // Ignore this directive for now.
Parser.eatToEndOfStatement();
return false;
}
@@ -1518,19 +1840,19 @@ bool MipsAsmParser::ParseDirective(AsmToken DirectiveID) {
}
if (IDVal == ".fmask") {
- // ignore this directive for now
+ // Ignore this directive for now.
Parser.eatToEndOfStatement();
return false;
}
if (IDVal == ".mask") {
- // ignore this directive for now
+ // Ignore this directive for now.
Parser.eatToEndOfStatement();
return false;
}
if (IDVal == ".gpword") {
- // ignore this directive for now
+ // Ignore this directive for now.
Parser.eatToEndOfStatement();
return false;
}
diff --git a/lib/Target/Mips/CMakeLists.txt b/lib/Target/Mips/CMakeLists.txt
index cf8bb18..78a9f70 100644
--- a/lib/Target/Mips/CMakeLists.txt
+++ b/lib/Target/Mips/CMakeLists.txt
@@ -32,6 +32,8 @@ add_llvm_target(MipsCodeGen
MipsLongBranch.cpp
MipsMCInstLower.cpp
MipsMachineFunction.cpp
+ MipsModuleISelDAGToDAG.cpp
+ MipsOs16.cpp
MipsRegisterInfo.cpp
MipsSEFrameLowering.cpp
MipsSEInstrInfo.cpp
diff --git a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
index 025a783..0dba33a 100644
--- a/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
+++ b/lib/Target/Mips/Disassembler/MipsDisassembler.cpp
@@ -138,10 +138,20 @@ static DecodeStatus DecodeHWRegs64RegisterClass(MCInst &Inst,
uint64_t Address,
const void *Decoder);
-static DecodeStatus DecodeACRegsRegisterClass(MCInst &Inst,
- unsigned RegNo,
- uint64_t Address,
- const void *Decoder);
+static DecodeStatus DecodeACRegsDSPRegisterClass(MCInst &Inst,
+ unsigned RegNo,
+ uint64_t Address,
+ const void *Decoder);
+
+static DecodeStatus DecodeHIRegsDSPRegisterClass(MCInst &Inst,
+ unsigned RegNo,
+ uint64_t Address,
+ const void *Decoder);
+
+static DecodeStatus DecodeLORegsDSPRegisterClass(MCInst &Inst,
+ unsigned RegNo,
+ uint64_t Address,
+ const void *Decoder);
static DecodeStatus DecodeBranchTarget(MCInst &Inst,
unsigned Offset,
@@ -484,14 +494,38 @@ static DecodeStatus DecodeHWRegs64RegisterClass(MCInst &Inst,
return MCDisassembler::Success;
}
-static DecodeStatus DecodeACRegsRegisterClass(MCInst &Inst,
- unsigned RegNo,
- uint64_t Address,
- const void *Decoder) {
+static DecodeStatus DecodeACRegsDSPRegisterClass(MCInst &Inst,
+ unsigned RegNo,
+ uint64_t Address,
+ const void *Decoder) {
+ if (RegNo >= 4)
+ return MCDisassembler::Fail;
+
+ unsigned Reg = getReg(Decoder, Mips::ACRegsDSPRegClassID, RegNo);
+ Inst.addOperand(MCOperand::CreateReg(Reg));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeHIRegsDSPRegisterClass(MCInst &Inst,
+ unsigned RegNo,
+ uint64_t Address,
+ const void *Decoder) {
+ if (RegNo >= 4)
+ return MCDisassembler::Fail;
+
+ unsigned Reg = getReg(Decoder, Mips::HIRegsDSPRegClassID, RegNo);
+ Inst.addOperand(MCOperand::CreateReg(Reg));
+ return MCDisassembler::Success;
+}
+
+static DecodeStatus DecodeLORegsDSPRegisterClass(MCInst &Inst,
+ unsigned RegNo,
+ uint64_t Address,
+ const void *Decoder) {
if (RegNo >= 4)
return MCDisassembler::Fail;
- unsigned Reg = getReg(Decoder, Mips::ACRegsRegClassID, RegNo);
+ unsigned Reg = getReg(Decoder, Mips::LORegsDSPRegClassID, RegNo);
Inst.addOperand(MCOperand::CreateReg(Reg));
return MCDisassembler::Success;
}
diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
index 96f93a0..9460731 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
+++ b/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp
@@ -27,6 +27,9 @@
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/Support/raw_ostream.h"
+#define GET_INSTRMAP_INFO
+#include "MipsGenInstrInfo.inc"
+
using namespace llvm;
namespace {
@@ -35,12 +38,13 @@ class MipsMCCodeEmitter : public MCCodeEmitter {
void operator=(const MipsMCCodeEmitter &) LLVM_DELETED_FUNCTION;
const MCInstrInfo &MCII;
MCContext &Ctx;
+ const MCSubtargetInfo &STI;
bool IsLittleEndian;
public:
MipsMCCodeEmitter(const MCInstrInfo &mcii, MCContext &Ctx_,
const MCSubtargetInfo &sti, bool IsLittle) :
- MCII(mcii), Ctx(Ctx_), IsLittleEndian(IsLittle) {}
+ MCII(mcii), Ctx(Ctx_), STI (sti), IsLittleEndian(IsLittle) {}
~MipsMCCodeEmitter() {}
@@ -88,6 +92,9 @@ public:
unsigned getSizeInsEncoding(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups) const;
+ unsigned
+ getExprOpValue(const MCExpr *Expr,SmallVectorImpl<MCFixup> &Fixups) const;
+
}; // class MipsMCCodeEmitter
} // namespace
@@ -141,6 +148,15 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS,
if ((Opcode != Mips::NOP) && (Opcode != Mips::SLL) && !Binary)
llvm_unreachable("unimplemented opcode in EncodeInstruction()");
+ if (STI.getFeatureBits() & Mips::FeatureMicroMips) {
+ int NewOpcode = Mips::Std2MicroMips (Opcode, Mips::Arch_micromips);
+ if (NewOpcode != -1) {
+ Opcode = NewOpcode;
+ TmpInst.setOpcode (NewOpcode);
+ Binary = getBinaryCodeForInstr(TmpInst, Fixups);
+ }
+ }
+
const MCInstrDesc &Desc = MCII.get(TmpInst.getOpcode());
// Get byte count of instruction
@@ -160,8 +176,9 @@ getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
const MCOperand &MO = MI.getOperand(OpNo);
- // If the destination is an immediate, we have nothing to do.
- if (MO.isImm()) return MO.getImm();
+ // If the destination is an immediate, divide by 4.
+ if (MO.isImm()) return MO.getImm() >> 2;
+
assert(MO.isExpr() &&
"getBranchTargetOpValue expects only expressions or immediates");
@@ -179,8 +196,9 @@ getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,
SmallVectorImpl<MCFixup> &Fixups) const {
const MCOperand &MO = MI.getOperand(OpNo);
- // If the destination is an immediate, we have nothing to do.
- if (MO.isImm()) return MO.getImm();
+ // If the destination is an immediate, divide by 4.
+ if (MO.isImm()) return MO.getImm()>>2;
+
assert(MO.isExpr() &&
"getJumpTargetOpValue expects only expressions or an immediate");
@@ -190,35 +208,24 @@ getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,
return 0;
}
-/// getMachineOpValue - Return binary encoding of operand. If the machine
-/// operand requires relocation, record the relocation and return zero.
unsigned MipsMCCodeEmitter::
-getMachineOpValue(const MCInst &MI, const MCOperand &MO,
- SmallVectorImpl<MCFixup> &Fixups) const {
- if (MO.isReg()) {
- unsigned Reg = MO.getReg();
- unsigned RegNo = Ctx.getRegisterInfo().getEncodingValue(Reg);
- return RegNo;
- } else if (MO.isImm()) {
- return static_cast<unsigned>(MO.getImm());
- } else if (MO.isFPImm()) {
- return static_cast<unsigned>(APFloat(MO.getFPImm())
- .bitcastToAPInt().getHiBits(32).getLimitedValue());
- }
+getExprOpValue(const MCExpr *Expr,SmallVectorImpl<MCFixup> &Fixups) const {
+ int64_t Res;
- // MO must be an Expr.
- assert(MO.isExpr());
+ if (Expr->EvaluateAsAbsolute(Res))
+ return Res;
- const MCExpr *Expr = MO.getExpr();
MCExpr::ExprKind Kind = Expr->getKind();
+ if (Kind == MCExpr::Constant) {
+ return cast<MCConstantExpr>(Expr)->getValue();
+ }
if (Kind == MCExpr::Binary) {
- Expr = static_cast<const MCBinaryExpr*>(Expr)->getLHS();
- Kind = Expr->getKind();
+ unsigned Res = getExprOpValue(cast<MCBinaryExpr>(Expr)->getLHS(), Fixups);
+ Res += getExprOpValue(cast<MCBinaryExpr>(Expr)->getRHS(), Fixups);
+ return Res;
}
-
- assert (Kind == MCExpr::SymbolRef);
-
+ if (Kind == MCExpr::SymbolRef) {
Mips::Fixups FixupKind = Mips::Fixups(0);
switch(cast<MCSymbolRefExpr>(Expr)->getKind()) {
@@ -298,12 +305,32 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO,
break;
} // switch
- Fixups.push_back(MCFixup::Create(0, MO.getExpr(), MCFixupKind(FixupKind)));
-
- // All of the information is in the fixup.
+ Fixups.push_back(MCFixup::Create(0, Expr, MCFixupKind(FixupKind)));
+ return 0;
+ }
return 0;
}
+/// getMachineOpValue - Return binary encoding of operand. If the machine
+/// operand requires relocation, record the relocation and return zero.
+unsigned MipsMCCodeEmitter::
+getMachineOpValue(const MCInst &MI, const MCOperand &MO,
+ SmallVectorImpl<MCFixup> &Fixups) const {
+ if (MO.isReg()) {
+ unsigned Reg = MO.getReg();
+ unsigned RegNo = Ctx.getRegisterInfo().getEncodingValue(Reg);
+ return RegNo;
+ } else if (MO.isImm()) {
+ return static_cast<unsigned>(MO.getImm());
+ } else if (MO.isFPImm()) {
+ return static_cast<unsigned>(APFloat(MO.getFPImm())
+ .bitcastToAPInt().getHiBits(32).getLimitedValue());
+ }
+ // MO must be an Expr.
+ assert(MO.isExpr());
+ return getExprOpValue(MO.getExpr(),Fixups);
+}
+
/// getMemEncoding - Return binary encoding of memory related operand.
/// If the offset operand requires relocation, record the relocation.
unsigned
diff --git a/lib/Target/Mips/MicroMipsInstrFormats.td b/lib/Target/Mips/MicroMipsInstrFormats.td
new file mode 100644
index 0000000..665b4d2
--- /dev/null
+++ b/lib/Target/Mips/MicroMipsInstrFormats.td
@@ -0,0 +1,112 @@
+class MMArch {
+ string Arch = "micromips";
+ list<dag> Pattern = [];
+}
+
+class ADD_FM_MM<bits<6> op, bits<10> funct> : MMArch {
+ bits<5> rt;
+ bits<5> rs;
+ bits<5> rd;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = op;
+ let Inst{25-21} = rt;
+ let Inst{20-16} = rs;
+ let Inst{15-11} = rd;
+ let Inst{10} = 0;
+ let Inst{9-0} = funct;
+}
+
+class ADDI_FM_MM<bits<6> op> : MMArch {
+ bits<5> rs;
+ bits<5> rt;
+ bits<16> imm16;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = op;
+ let Inst{25-21} = rt;
+ let Inst{20-16} = rs;
+ let Inst{15-0} = imm16;
+}
+
+class SLTI_FM_MM<bits<6> op> : MMArch {
+ bits<5> rt;
+ bits<5> rs;
+ bits<16> imm16;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = op;
+ let Inst{25-21} = rs;
+ let Inst{20-16} = rt;
+ let Inst{15-0} = imm16;
+}
+
+class LUI_FM_MM : MMArch {
+ bits<5> rt;
+ bits<16> imm16;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = 0x10;
+ let Inst{25-21} = 0xd;
+ let Inst{20-16} = rt;
+ let Inst{15-0} = imm16;
+}
+
+class MULT_FM_MM<bits<10> funct> : MMArch {
+ bits<5> rs;
+ bits<5> rt;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = 0x00;
+ let Inst{25-21} = rt;
+ let Inst{20-16} = rs;
+ let Inst{15-6} = funct;
+ let Inst{5-0} = 0x3c;
+}
+
+class SRA_FM_MM<bits<10> funct, bit rotate> : MMArch {
+ bits<5> rd;
+ bits<5> rt;
+ bits<5> shamt;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = 0;
+ let Inst{25-21} = rd;
+ let Inst{20-16} = rt;
+ let Inst{15-11} = shamt;
+ let Inst{10} = rotate;
+ let Inst{9-0} = funct;
+}
+
+class SRLV_FM_MM<bits<10> funct, bit rotate> : MMArch {
+ bits<5> rd;
+ bits<5> rt;
+ bits<5> rs;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = 0;
+ let Inst{25-21} = rt;
+ let Inst{20-16} = rs;
+ let Inst{15-11} = rd;
+ let Inst{10} = rotate;
+ let Inst{9-0} = funct;
+}
+
+class LW_FM_MM<bits<6> op> : MMArch {
+ bits<5> rt;
+ bits<21> addr;
+
+ bits<32> Inst;
+
+ let Inst{31-26} = op;
+ let Inst{25-21} = rt;
+ let Inst{20-16} = addr{20-16};
+ let Inst{15-0} = addr{15-0};
+}
diff --git a/lib/Target/Mips/MicroMipsInstrInfo.td b/lib/Target/Mips/MicroMipsInstrInfo.td
new file mode 100644
index 0000000..74cdccd
--- /dev/null
+++ b/lib/Target/Mips/MicroMipsInstrInfo.td
@@ -0,0 +1,67 @@
+let isCodeGenOnly = 1 in {
+ /// Arithmetic Instructions (ALU Immediate)
+ def ADDiu_MM : MMRel, ArithLogicI<"addiu", simm16, CPURegsOpnd>,
+ ADDI_FM_MM<0xc>;
+ def ADDi_MM : MMRel, ArithLogicI<"addi", simm16, CPURegsOpnd>,
+ ADDI_FM_MM<0x4>;
+ def SLTi_MM : MMRel, SetCC_I<"slti", setlt, simm16, immSExt16, CPURegs>,
+ SLTI_FM_MM<0x24>;
+ def SLTiu_MM : MMRel, SetCC_I<"sltiu", setult, simm16, immSExt16, CPURegs>,
+ SLTI_FM_MM<0x2c>;
+ def ANDi_MM : MMRel, ArithLogicI<"andi", uimm16, CPURegsOpnd, immZExt16, and>,
+ ADDI_FM_MM<0x34>;
+ def ORi_MM : MMRel, ArithLogicI<"ori", uimm16, CPURegsOpnd, immZExt16, or>,
+ ADDI_FM_MM<0x14>;
+ def XORi_MM : MMRel, ArithLogicI<"xori", uimm16, CPURegsOpnd, immZExt16, xor>,
+ ADDI_FM_MM<0x1c>;
+ def LUi_MM : MMRel, LoadUpper<"lui", CPURegs, uimm16>, LUI_FM_MM;
+
+ /// Arithmetic Instructions (3-Operand, R-Type)
+ def ADDu_MM : MMRel, ArithLogicR<"addu", CPURegsOpnd>, ADD_FM_MM<0, 0x150>;
+ def SUBu_MM : MMRel, ArithLogicR<"subu", CPURegsOpnd>, ADD_FM_MM<0, 0x1d0>;
+ def MUL_MM : MMRel, ArithLogicR<"mul", CPURegsOpnd>, ADD_FM_MM<0, 0x210>;
+ def ADD_MM : MMRel, ArithLogicR<"add", CPURegsOpnd>, ADD_FM_MM<0, 0x110>;
+ def SUB_MM : MMRel, ArithLogicR<"sub", CPURegsOpnd>, ADD_FM_MM<0, 0x190>;
+ def SLT_MM : MMRel, SetCC_R<"slt", setlt, CPURegs>, ADD_FM_MM<0, 0x350>;
+ def SLTu_MM : MMRel, SetCC_R<"sltu", setult, CPURegs>,
+ ADD_FM_MM<0, 0x390>;
+ def AND_MM : MMRel, ArithLogicR<"and", CPURegsOpnd, 1, IIAlu, and>,
+ ADD_FM_MM<0, 0x250>;
+ def OR_MM : MMRel, ArithLogicR<"or", CPURegsOpnd, 1, IIAlu, or>,
+ ADD_FM_MM<0, 0x290>;
+ def XOR_MM : MMRel, ArithLogicR<"xor", CPURegsOpnd, 1, IIAlu, xor>,
+ ADD_FM_MM<0, 0x310>;
+ def NOR_MM : MMRel, LogicNOR<"nor", CPURegsOpnd>, ADD_FM_MM<0, 0x2d0>;
+ def MULT_MM : MMRel, Mult<"mult", IIImul, CPURegsOpnd, [HI, LO]>,
+ MULT_FM_MM<0x22c>;
+ def MULTu_MM : MMRel, Mult<"multu", IIImul, CPURegsOpnd, [HI, LO]>,
+ MULT_FM_MM<0x26c>;
+
+ /// Shift Instructions
+ def SLL_MM : MMRel, shift_rotate_imm<"sll", shamt, CPURegsOpnd>,
+ SRA_FM_MM<0, 0>;
+ def SRL_MM : MMRel, shift_rotate_imm<"srl", shamt, CPURegsOpnd>,
+ SRA_FM_MM<0x40, 0>;
+ def SRA_MM : MMRel, shift_rotate_imm<"sra", shamt, CPURegsOpnd>,
+ SRA_FM_MM<0x80, 0>;
+ def SLLV_MM : MMRel, shift_rotate_reg<"sllv", CPURegsOpnd>,
+ SRLV_FM_MM<0x10, 0>;
+ def SRLV_MM : MMRel, shift_rotate_reg<"srlv", CPURegsOpnd>,
+ SRLV_FM_MM<0x50, 0>;
+ def SRAV_MM : MMRel, shift_rotate_reg<"srav", CPURegsOpnd>,
+ SRLV_FM_MM<0x90, 0>;
+ def ROTR_MM : MMRel, shift_rotate_imm<"rotr", shamt, CPURegsOpnd>,
+ SRA_FM_MM<0xc0, 0>;
+ def ROTRV_MM : MMRel, shift_rotate_reg<"rotrv", CPURegsOpnd>,
+ SRLV_FM_MM<0xd0, 0>;
+
+ /// Load and Store Instructions - aligned
+ defm LB_MM : LoadM<"lb", CPURegs, sextloadi8>, MMRel, LW_FM_MM<0x7>;
+ defm LBu_MM : LoadM<"lbu", CPURegs, zextloadi8>, MMRel, LW_FM_MM<0x5>;
+ defm LH_MM : LoadM<"lh", CPURegs, sextloadi16>, MMRel, LW_FM_MM<0xf>;
+ defm LHu_MM : LoadM<"lhu", CPURegs, zextloadi16>, MMRel, LW_FM_MM<0xd>;
+ defm LW_MM : LoadM<"lw", CPURegs>, MMRel, LW_FM_MM<0x3f>;
+ defm SB_MM : StoreM<"sb", CPURegs, truncstorei8>, MMRel, LW_FM_MM<0x6>;
+ defm SH_MM : StoreM<"sh", CPURegs, truncstorei16>, MMRel, LW_FM_MM<0xe>;
+ defm SW_MM : StoreM<"sw", CPURegs>, MMRel, LW_FM_MM<0x3e>;
+}
diff --git a/lib/Target/Mips/Mips16FrameLowering.h b/lib/Target/Mips/Mips16FrameLowering.h
index 25f4ffb..54fdb78 100644
--- a/lib/Target/Mips/Mips16FrameLowering.h
+++ b/lib/Target/Mips/Mips16FrameLowering.h
@@ -20,7 +20,7 @@ namespace llvm {
class Mips16FrameLowering : public MipsFrameLowering {
public:
explicit Mips16FrameLowering(const MipsSubtarget &STI)
- : MipsFrameLowering(STI) {}
+ : MipsFrameLowering(STI, 8) {}
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
/// the function.
diff --git a/lib/Target/Mips/Mips16ISelDAGToDAG.cpp b/lib/Target/Mips/Mips16ISelDAGToDAG.cpp
index 00b3449..c1c635c 100644
--- a/lib/Target/Mips/Mips16ISelDAGToDAG.cpp
+++ b/lib/Target/Mips/Mips16ISelDAGToDAG.cpp
@@ -35,6 +35,11 @@
#include "llvm/Target/TargetMachine.h"
using namespace llvm;
+bool Mips16DAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
+ if (!Subtarget.inMips16Mode())
+ return false;
+ return MipsDAGToDAGISel::runOnMachineFunction(MF);
+}
/// Select multiply instructions.
std::pair<SDNode*, SDNode*>
Mips16DAGToDAGISel::selectMULT(SDNode *N, unsigned Opc, DebugLoc DL, EVT Ty,
@@ -267,7 +272,7 @@ std::pair<bool, SDNode*> Mips16DAGToDAGISel::selectNode(SDNode *Node) {
EVT VT = LHS.getValueType();
unsigned Sltu_op = Mips::SltuRxRyRz16;
- SDNode *Carry = CurDAG->getMachineNode(Sltu_op, DL, VT, Ops, 2);
+ SDNode *Carry = CurDAG->getMachineNode(Sltu_op, DL, VT, Ops);
unsigned Addu_op = Mips::AdduRxRyRz16;
SDNode *AddCarry = CurDAG->getMachineNode(Addu_op, DL, VT,
SDValue(Carry,0), RHS);
diff --git a/lib/Target/Mips/Mips16ISelDAGToDAG.h b/lib/Target/Mips/Mips16ISelDAGToDAG.h
index baa8587..f05f9b7 100644
--- a/lib/Target/Mips/Mips16ISelDAGToDAG.h
+++ b/lib/Target/Mips/Mips16ISelDAGToDAG.h
@@ -28,6 +28,8 @@ private:
SDValue getMips16SPAliasReg();
+ virtual bool runOnMachineFunction(MachineFunction &MF);
+
void getMips16SPRefReg(SDNode *Parent, SDValue &AliasReg);
virtual bool selectAddr16(SDNode *Parent, SDValue N, SDValue &Base,
diff --git a/lib/Target/Mips/Mips16ISelLowering.cpp b/lib/Target/Mips/Mips16ISelLowering.cpp
index 23eb537..f63318f 100644
--- a/lib/Target/Mips/Mips16ISelLowering.cpp
+++ b/lib/Target/Mips/Mips16ISelLowering.cpp
@@ -53,7 +53,6 @@ Mips16TargetLowering::Mips16TargetLowering(MipsTargetMachine &TM)
if (Mips16HardFloat)
setMips16HardFloatLibCalls();
- setOperationAction(ISD::MEMBARRIER, MVT::Other, Expand);
setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Expand);
setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i32, Expand);
setOperationAction(ISD::ATOMIC_SWAP, MVT::i32, Expand);
@@ -614,7 +613,8 @@ MachineBasicBlock
unsigned regX = MI->getOperand(0).getReg();
unsigned regY = MI->getOperand(1).getReg();
MachineBasicBlock *target = MI->getOperand(2).getMBB();
- BuildMI(*BB, MI, MI->getDebugLoc(), TII->get(CmpOpc)).addReg(regX).addReg(regY);
+ BuildMI(*BB, MI, MI->getDebugLoc(), TII->get(CmpOpc)).addReg(regX)
+ .addReg(regY);
BuildMI(*BB, MI, MI->getDebugLoc(), TII->get(BtOpc)).addMBB(target);
MI->eraseFromParent(); // The pseudo instruction is gone now.
return BB;
@@ -636,7 +636,8 @@ MachineBasicBlock *Mips16TargetLowering::emitFEXT_T8I8I16_ins(
CmpOpc = CmpiXOpc;
else
llvm_unreachable("immediate field not usable");
- BuildMI(*BB, MI, MI->getDebugLoc(), TII->get(CmpOpc)).addReg(regX).addImm(imm);
+ BuildMI(*BB, MI, MI->getDebugLoc(), TII->get(CmpOpc)).addReg(regX)
+ .addImm(imm);
BuildMI(*BB, MI, MI->getDebugLoc(), TII->get(BtOpc)).addMBB(target);
MI->eraseFromParent(); // The pseudo instruction is gone now.
return BB;
diff --git a/lib/Target/Mips/Mips16InstrInfo.cpp b/lib/Target/Mips/Mips16InstrInfo.cpp
index fd3cc8f..17dd2c0 100644
--- a/lib/Target/Mips/Mips16InstrInfo.cpp
+++ b/lib/Target/Mips/Mips16InstrInfo.cpp
@@ -98,10 +98,10 @@ void Mips16InstrInfo::copyPhysReg(MachineBasicBlock &MBB,
}
void Mips16InstrInfo::
-storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
- unsigned SrcReg, bool isKill, int FI,
- const TargetRegisterClass *RC,
- const TargetRegisterInfo *TRI) const {
+storeRegToStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
+ unsigned SrcReg, bool isKill, int FI,
+ const TargetRegisterClass *RC, const TargetRegisterInfo *TRI,
+ int64_t Offset) const {
DebugLoc DL;
if (I != MBB.end()) DL = I->getDebugLoc();
MachineMemOperand *MMO = GetMemOperand(MBB, FI, MachineMemOperand::MOStore);
@@ -110,14 +110,13 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
Opc = Mips::SwRxSpImmX16;
assert(Opc && "Register class not handled!");
BuildMI(MBB, I, DL, get(Opc)).addReg(SrcReg, getKillRegState(isKill))
- .addFrameIndex(FI).addImm(0).addMemOperand(MMO);
+ .addFrameIndex(FI).addImm(Offset).addMemOperand(MMO);
}
void Mips16InstrInfo::
-loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
- unsigned DestReg, int FI,
- const TargetRegisterClass *RC,
- const TargetRegisterInfo *TRI) const {
+loadRegFromStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
+ unsigned DestReg, int FI, const TargetRegisterClass *RC,
+ const TargetRegisterInfo *TRI, int64_t Offset) const {
DebugLoc DL;
if (I != MBB.end()) DL = I->getDebugLoc();
MachineMemOperand *MMO = GetMemOperand(MBB, FI, MachineMemOperand::MOLoad);
@@ -126,7 +125,7 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
if (Mips::CPU16RegsRegClass.hasSubClassEq(RC))
Opc = Mips::LwRxSpImmX16;
assert(Opc && "Register class not handled!");
- BuildMI(MBB, I, DL, get(Opc), DestReg).addFrameIndex(FI).addImm(0)
+ BuildMI(MBB, I, DL, get(Opc), DestReg).addFrameIndex(FI).addImm(Offset)
.addMemOperand(MMO);
}
diff --git a/lib/Target/Mips/Mips16InstrInfo.h b/lib/Target/Mips/Mips16InstrInfo.h
index 1cb1dfe..a77a904 100644
--- a/lib/Target/Mips/Mips16InstrInfo.h
+++ b/lib/Target/Mips/Mips16InstrInfo.h
@@ -48,17 +48,19 @@ public:
unsigned DestReg, unsigned SrcReg,
bool KillSrc) const;
- virtual void storeRegToStackSlot(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MBBI,
- unsigned SrcReg, bool isKill, int FrameIndex,
- const TargetRegisterClass *RC,
- const TargetRegisterInfo *TRI) const;
-
- virtual void loadRegFromStackSlot(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MBBI,
- unsigned DestReg, int FrameIndex,
- const TargetRegisterClass *RC,
- const TargetRegisterInfo *TRI) const;
+ virtual void storeRegToStack(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MBBI,
+ unsigned SrcReg, bool isKill, int FrameIndex,
+ const TargetRegisterClass *RC,
+ const TargetRegisterInfo *TRI,
+ int64_t Offset) const;
+
+ virtual void loadRegFromStack(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MBBI,
+ unsigned DestReg, int FrameIndex,
+ const TargetRegisterClass *RC,
+ const TargetRegisterInfo *TRI,
+ int64_t Offset) const;
virtual bool expandPostRAPseudo(MachineBasicBlock::iterator MI) const;
diff --git a/lib/Target/Mips/Mips16InstrInfo.td b/lib/Target/Mips/Mips16InstrInfo.td
index 6293829..aa51aaf 100644
--- a/lib/Target/Mips/Mips16InstrInfo.td
+++ b/lib/Target/Mips/Mips16InstrInfo.td
@@ -1466,14 +1466,14 @@ def: Mips16Pat<(i32 immZExt16:$in), (LiRxImmX16 immZExt16:$in)>;
// MipsDivRem
//
def: Mips16Pat
- <(MipsDivRem CPU16Regs:$rx, CPU16Regs:$ry),
+ <(MipsDivRem16 CPU16Regs:$rx, CPU16Regs:$ry),
(DivRxRy16 CPU16Regs:$rx, CPU16Regs:$ry)>;
//
// MipsDivRemU
//
def: Mips16Pat
- <(MipsDivRemU CPU16Regs:$rx, CPU16Regs:$ry),
+ <(MipsDivRemU16 CPU16Regs:$rx, CPU16Regs:$ry),
(DivuRxRy16 CPU16Regs:$rx, CPU16Regs:$ry)>;
// signed a,b
diff --git a/lib/Target/Mips/Mips16RegisterInfo.cpp b/lib/Target/Mips/Mips16RegisterInfo.cpp
index 0ea9368..7ad18f2 100644
--- a/lib/Target/Mips/Mips16RegisterInfo.cpp
+++ b/lib/Target/Mips/Mips16RegisterInfo.cpp
@@ -1,5 +1,4 @@
-
-//===-- Mips16RegisterInfo.cpp - MIPS16 Register Information -== ----------===//
+//===-- Mips16RegisterInfo.cpp - MIPS16 Register Information --------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -72,6 +71,12 @@ bool Mips16RegisterInfo::saveScavengerRegister
return true;
}
+const TargetRegisterClass *
+Mips16RegisterInfo::intRegClass(unsigned Size) const {
+ assert(Size == 4);
+ return &Mips::CPU16RegsRegClass;
+}
+
void Mips16RegisterInfo::eliminateFI(MachineBasicBlock::iterator II,
unsigned OpNo, int FrameIndex,
uint64_t StackSize,
diff --git a/lib/Target/Mips/Mips16RegisterInfo.h b/lib/Target/Mips/Mips16RegisterInfo.h
index b8f818a..2b3d2b1 100644
--- a/lib/Target/Mips/Mips16RegisterInfo.h
+++ b/lib/Target/Mips/Mips16RegisterInfo.h
@@ -37,6 +37,8 @@ public:
const TargetRegisterClass *RC,
unsigned Reg) const;
+ virtual const TargetRegisterClass *intRegClass(unsigned Size) const;
+
private:
virtual void eliminateFI(MachineBasicBlock::iterator II, unsigned OpNo,
int FrameIndex, uint64_t StackSize,
diff --git a/lib/Target/Mips/Mips64InstrInfo.td b/lib/Target/Mips/Mips64InstrInfo.td
index 5903b9e..fc533fb 100644
--- a/lib/Target/Mips/Mips64InstrInfo.td
+++ b/lib/Target/Mips/Mips64InstrInfo.td
@@ -66,6 +66,12 @@ let usesCustomInserter = 1, Predicates = [HasStdEnc],
defm ATOMIC_CMP_SWAP_I64 : AtomicCmpSwap64<atomic_cmp_swap_64>;
}
+/// Pseudo instructions for loading and storing accumulator registers.
+let isPseudo = 1 in {
+ defm LOAD_AC128 : LoadM<"load_ac128", ACRegs128>;
+ defm STORE_AC128 : StoreM<"store_ac128", ACRegs128>;
+}
+
//===----------------------------------------------------------------------===//
// Instruction definition
//===----------------------------------------------------------------------===//
@@ -179,10 +185,16 @@ def DMULT : Mult<"dmult", IIImul, CPU64RegsOpnd, [HI64, LO64]>,
MULT_FM<0, 0x1c>;
def DMULTu : Mult<"dmultu", IIImul, CPU64RegsOpnd, [HI64, LO64]>,
MULT_FM<0, 0x1d>;
-def DSDIV : Div<MipsDivRem, "ddiv", IIIdiv, CPU64RegsOpnd, [HI64, LO64]>,
- MULT_FM<0, 0x1e>;
-def DUDIV : Div<MipsDivRemU, "ddivu", IIIdiv, CPU64RegsOpnd, [HI64, LO64]>,
- MULT_FM<0, 0x1f>;
+def PseudoDMULT : MultDivPseudo<DMULT, ACRegs128, CPU64RegsOpnd, MipsMult,
+ IIImul>;
+def PseudoDMULTu : MultDivPseudo<DMULTu, ACRegs128, CPU64RegsOpnd, MipsMultu,
+ IIImul>;
+def DSDIV : Div<"ddiv", IIIdiv, CPU64RegsOpnd, [HI64, LO64]>, MULT_FM<0, 0x1e>;
+def DUDIV : Div<"ddivu", IIIdiv, CPU64RegsOpnd, [HI64, LO64]>, MULT_FM<0, 0x1f>;
+def PseudoDSDIV : MultDivPseudo<DSDIV, ACRegs128, CPU64RegsOpnd, MipsDivRem,
+ IIIdiv, 0>;
+def PseudoDUDIV : MultDivPseudo<DUDIV, ACRegs128, CPU64RegsOpnd, MipsDivRemU,
+ IIIdiv, 0>;
def MTHI64 : MoveToLOHI<"mthi", CPU64Regs, [HI64]>, MTLO_FM<0x11>;
def MTLO64 : MoveToLOHI<"mtlo", CPU64Regs, [LO64]>, MTLO_FM<0x13>;
@@ -306,6 +318,10 @@ def : MipsPat<(i64 (sext_inreg CPU64Regs:$src, i32)),
// bswap MipsPattern
def : MipsPat<(bswap CPU64Regs:$rt), (DSHD (DSBH CPU64Regs:$rt))>;
+// mflo/hi patterns.
+def : MipsPat<(i64 (ExtractLOHI ACRegs128:$ac, imm:$lohi_idx)),
+ (EXTRACT_SUBREG ACRegs128:$ac, imm:$lohi_idx)>;
+
//===----------------------------------------------------------------------===//
// Instruction aliases
//===----------------------------------------------------------------------===//
@@ -332,13 +348,19 @@ def : InstAlias<"not $rt, $rs",
def : InstAlias<"j $rs", (JR64 CPU64Regs:$rs), 0>, Requires<[HasMips64]>;
def : InstAlias<"jalr $rs", (JALR64 RA_64, CPU64Regs:$rs)>,
Requires<[HasMips64]>;
+def : InstAlias<"jal $rs", (JALR64 RA_64, CPU64Regs:$rs), 0>,
+ Requires<[HasMips64]>;
+def : InstAlias<"jal $rd,$rs", (JALR64 CPU64Regs:$rd, CPU64Regs:$rs), 0>,
+ Requires<[HasMips64]>;
def : InstAlias<"daddu $rs, $rt, $imm",
(DADDiu CPU64RegsOpnd:$rs, CPU64RegsOpnd:$rt, simm16_64:$imm),
1>;
def : InstAlias<"dadd $rs, $rt, $imm",
(DADDi CPU64RegsOpnd:$rs, CPU64RegsOpnd:$rt, simm16_64:$imm),
1>;
-
+def : InstAlias<"or $rs, $rt, $imm",
+ (ORi64 CPU64RegsOpnd:$rs, CPU64RegsOpnd:$rt, uimm16_64:$imm),
+ 1>, Requires<[HasMips64]>;
/// Move between CPU and coprocessor registers
let DecoderNamespace = "Mips64" in {
diff --git a/lib/Target/Mips/MipsAsmPrinter.cpp b/lib/Target/Mips/MipsAsmPrinter.cpp
index 1876cb6..f4f71cb 100644
--- a/lib/Target/Mips/MipsAsmPrinter.cpp
+++ b/lib/Target/Mips/MipsAsmPrinter.cpp
@@ -46,6 +46,10 @@
using namespace llvm;
bool MipsAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
+ // Initialize TargetLoweringObjectFile.
+ if (Subtarget->allowMixed16_32())
+ const_cast<TargetLoweringObjectFile&>(getObjFileLowering())
+ .Initialize(OutContext, TM);
MipsFI = MF.getInfo<MipsFunctionInfo>();
AsmPrinter::runOnMachineFunction(MF);
return true;
@@ -419,12 +423,18 @@ bool MipsAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
unsigned OpNum, unsigned AsmVariant,
const char *ExtraCode,
raw_ostream &O) {
- if (ExtraCode && ExtraCode[0])
- return true; // Unknown modifier.
+ int Offset = 0;
+ // Currently we are expecting either no ExtraCode or 'D'
+ if (ExtraCode) {
+ if (ExtraCode[0] == 'D')
+ Offset = 4;
+ else
+ return true; // Unknown modifier.
+ }
const MachineOperand &MO = MI->getOperand(OpNum);
assert(MO.isReg() && "unexpected inline asm memory operand");
- O << "0($" << MipsInstPrinter::getRegisterName(MO.getReg()) << ")";
+ O << Offset << "($" << MipsInstPrinter::getRegisterName(MO.getReg()) << ")";
return false;
}
diff --git a/lib/Target/Mips/MipsCodeEmitter.cpp b/lib/Target/Mips/MipsCodeEmitter.cpp
index df877b6..3fc402b 100644
--- a/lib/Target/Mips/MipsCodeEmitter.cpp
+++ b/lib/Target/Mips/MipsCodeEmitter.cpp
@@ -115,6 +115,10 @@ private:
void emitGlobalAddressUnaligned(const GlobalValue *GV, unsigned Reloc,
int Offset) const;
+ /// Expand pseudo instructions with accumulator register operands.
+ void expandACCInstr(MachineBasicBlock::instr_iterator MI,
+ MachineBasicBlock &MBB, unsigned Opc) const;
+
/// \brief Expand pseudo instruction. Return true if MI was expanded.
bool expandPseudos(MachineBasicBlock::instr_iterator &MI,
MachineBasicBlock &MBB) const;
@@ -298,6 +302,14 @@ void MipsCodeEmitter::emitWord(unsigned Word) {
MCE.emitWordBE(Word);
}
+void MipsCodeEmitter::expandACCInstr(MachineBasicBlock::instr_iterator MI,
+ MachineBasicBlock &MBB,
+ unsigned Opc) const {
+ // Expand "pseudomult $ac0, $t0, $t1" to "mult $t0, $t1".
+ BuildMI(MBB, &*MI, MI->getDebugLoc(), II->get(Opc))
+ .addReg(MI->getOperand(1).getReg()).addReg(MI->getOperand(2).getReg());
+}
+
bool MipsCodeEmitter::expandPseudos(MachineBasicBlock::instr_iterator &MI,
MachineBasicBlock &MBB) const {
switch (MI->getOpcode()) {
@@ -309,6 +321,30 @@ bool MipsCodeEmitter::expandPseudos(MachineBasicBlock::instr_iterator &MI,
BuildMI(MBB, &*MI, MI->getDebugLoc(), II->get(Mips::JALR), Mips::RA)
.addReg(MI->getOperand(0).getReg());
break;
+ case Mips::PseudoMULT:
+ expandACCInstr(MI, MBB, Mips::MULT);
+ break;
+ case Mips::PseudoMULTu:
+ expandACCInstr(MI, MBB, Mips::MULTu);
+ break;
+ case Mips::PseudoSDIV:
+ expandACCInstr(MI, MBB, Mips::SDIV);
+ break;
+ case Mips::PseudoUDIV:
+ expandACCInstr(MI, MBB, Mips::UDIV);
+ break;
+ case Mips::PseudoMADD:
+ expandACCInstr(MI, MBB, Mips::MADD);
+ break;
+ case Mips::PseudoMADDU:
+ expandACCInstr(MI, MBB, Mips::MADDU);
+ break;
+ case Mips::PseudoMSUB:
+ expandACCInstr(MI, MBB, Mips::MSUB);
+ break;
+ case Mips::PseudoMSUBU:
+ expandACCInstr(MI, MBB, Mips::MSUBU);
+ break;
default:
return false;
}
diff --git a/lib/Target/Mips/MipsConstantIslandPass.cpp b/lib/Target/Mips/MipsConstantIslandPass.cpp
index b5de1eb..1951324 100644
--- a/lib/Target/Mips/MipsConstantIslandPass.cpp
+++ b/lib/Target/Mips/MipsConstantIslandPass.cpp
@@ -80,6 +80,10 @@ FunctionPass *llvm::createMipsConstantIslandPass(MipsTargetMachine &tm) {
}
bool MipsConstantIslands::runOnMachineFunction(MachineFunction &F) {
- return true;
+ // The intention is for this to be a mips16 only pass for now
+ // FIXME:
+ // if (!TM.getSubtarget<MipsSubtarget>().inMips16Mode())
+ // return false;
+ return false;
}
diff --git a/lib/Target/Mips/MipsDSPInstrFormats.td b/lib/Target/Mips/MipsDSPInstrFormats.td
index a72a763..cf09113 100644
--- a/lib/Target/Mips/MipsDSPInstrFormats.td
+++ b/lib/Target/Mips/MipsDSPInstrFormats.td
@@ -219,6 +219,33 @@ class MULT_FMT<bits<6> opcode, bits<6> funct> : DSPInst {
let Inst{5-0} = funct;
}
+// MFHI sub-class format.
+class MFHI_FMT<bits<6> funct> : DSPInst {
+ bits<5> rd;
+ bits<2> ac;
+
+ let Inst{31-26} = 0;
+ let Inst{25-23} = 0;
+ let Inst{22-21} = ac;
+ let Inst{20-16} = 0;
+ let Inst{15-11} = rd;
+ let Inst{10-6} = 0;
+ let Inst{5-0} = funct;
+}
+
+// MTHI sub-class format.
+class MTHI_FMT<bits<6> funct> : DSPInst {
+ bits<5> rs;
+ bits<2> ac;
+
+ let Inst{31-26} = 0;
+ let Inst{25-21} = rs;
+ let Inst{20-13} = 0;
+ let Inst{12-11} = ac;
+ let Inst{10-6} = 0;
+ let Inst{5-0} = funct;
+}
+
// EXTR.W sub-class format (type 1).
class EXTR_W_TY1_FMT<bits<5> op> : DSPInst {
bits<5> rt;
diff --git a/lib/Target/Mips/MipsDSPInstrInfo.td b/lib/Target/Mips/MipsDSPInstrInfo.td
index 9531b91..710b40d 100644
--- a/lib/Target/Mips/MipsDSPInstrInfo.td
+++ b/lib/Target/Mips/MipsDSPInstrInfo.td
@@ -20,17 +20,20 @@ def immZExt10 : ImmLeaf<i32, [{return isUInt<10>(Imm);}]>;
def immSExt6 : ImmLeaf<i32, [{return isInt<6>(Imm);}]>;
// Mips-specific dsp nodes
-def SDT_MipsExtr : SDTypeProfile<1, 1, [SDTCisVT<0, i32>, SDTCisSameAs<0, 1>]>;
-def SDT_MipsShilo : SDTypeProfile<0, 1, [SDTCisVT<0, i32>]>;
-def SDT_MipsDPA : SDTypeProfile<0, 2, [SDTCisVT<0, i32>, SDTCisSameAs<0, 1>]>;
+def SDT_MipsExtr : SDTypeProfile<1, 2, [SDTCisVT<0, i32>, SDTCisSameAs<0, 1>,
+ SDTCisVT<2, untyped>]>;
+def SDT_MipsShilo : SDTypeProfile<1, 2, [SDTCisVT<0, untyped>,
+ SDTCisSameAs<0, 2>, SDTCisVT<1, i32>]>;
+def SDT_MipsDPA : SDTypeProfile<1, 3, [SDTCisVT<0, untyped>, SDTCisSameAs<0, 3>,
+ SDTCisVT<1, i32>, SDTCisSameAs<1, 2>]>;
+def SDT_MipsSHIFT_DSP : SDTypeProfile<1, 2, [SDTCisVec<0>, SDTCisSameAs<0, 1>,
+ SDTCisVT<2, i32>]>;
class MipsDSPBase<string Opc, SDTypeProfile Prof> :
- SDNode<!strconcat("MipsISD::", Opc), Prof,
- [SDNPHasChain, SDNPInGlue, SDNPOutGlue]>;
+ SDNode<!strconcat("MipsISD::", Opc), Prof>;
class MipsDSPSideEffectBase<string Opc, SDTypeProfile Prof> :
- SDNode<!strconcat("MipsISD::", Opc), Prof,
- [SDNPHasChain, SDNPInGlue, SDNPOutGlue, SDNPSideEffect]>;
+ SDNode<!strconcat("MipsISD::", Opc), Prof, [SDNPHasChain, SDNPSideEffect]>;
def MipsEXTP : MipsDSPSideEffectBase<"EXTP", SDT_MipsExtr>;
def MipsEXTPDP : MipsDSPSideEffectBase<"EXTPDP", SDT_MipsExtr>;
@@ -40,7 +43,7 @@ def MipsEXTR_R_W : MipsDSPSideEffectBase<"EXTR_R_W", SDT_MipsExtr>;
def MipsEXTR_RS_W : MipsDSPSideEffectBase<"EXTR_RS_W", SDT_MipsExtr>;
def MipsSHILO : MipsDSPBase<"SHILO", SDT_MipsShilo>;
-def MipsMTHLIP : MipsDSPBase<"MTHLIP", SDT_MipsShilo>;
+def MipsMTHLIP : MipsDSPSideEffectBase<"MTHLIP", SDT_MipsShilo>;
def MipsMULSAQ_S_W_PH : MipsDSPSideEffectBase<"MULSAQ_S_W_PH", SDT_MipsDPA>;
def MipsMAQ_S_W_PHL : MipsDSPSideEffectBase<"MAQ_S_W_PHL", SDT_MipsDPA>;
@@ -73,6 +76,11 @@ def MipsMADD_DSP : MipsDSPBase<"MADD_DSP", SDT_MipsDPA>;
def MipsMADDU_DSP : MipsDSPBase<"MADDU_DSP", SDT_MipsDPA>;
def MipsMSUB_DSP : MipsDSPBase<"MSUB_DSP", SDT_MipsDPA>;
def MipsMSUBU_DSP : MipsDSPBase<"MSUBU_DSP", SDT_MipsDPA>;
+def MipsSHLL_DSP : MipsDSPBase<"SHLL_DSP", SDT_MipsSHIFT_DSP>;
+def MipsSHRA_DSP : MipsDSPBase<"SHRA_DSP", SDT_MipsSHIFT_DSP>;
+def MipsSHRL_DSP : MipsDSPBase<"SHRL_DSP", SDT_MipsSHIFT_DSP>;
+def MipsSETCC_DSP : MipsDSPBase<"SETCC_DSP", SDTSetCC>;
+def MipsSELECT_CC_DSP : MipsDSPBase<"SELECT_CC_DSP", SDTSelectCC>;
// Flags.
class UseAC {
@@ -144,6 +152,10 @@ class MAQ_S_W_PHL_ENC : DPA_W_PH_FMT<0b10100>;
class MAQ_S_W_PHR_ENC : DPA_W_PH_FMT<0b10110>;
class MAQ_SA_W_PHL_ENC : DPA_W_PH_FMT<0b10000>;
class MAQ_SA_W_PHR_ENC : DPA_W_PH_FMT<0b10010>;
+class MFHI_ENC : MFHI_FMT<0b010000>;
+class MFLO_ENC : MFHI_FMT<0b010010>;
+class MTHI_ENC : MTHI_FMT<0b010001>;
+class MTLO_ENC : MTHI_FMT<0b010011>;
class DPAU_H_QBL_ENC : DPA_W_PH_FMT<0b00011>;
class DPAU_H_QBR_ENC : DPA_W_PH_FMT<0b00111>;
class DPSU_H_QBL_ENC : DPA_W_PH_FMT<0b01011>;
@@ -343,6 +355,7 @@ class SHLL_QB_R2_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
list<dag> Pattern = [(set RC:$rd, (OpNode RC:$rt, ImmPat:$rs_sa))];
InstrItinClass Itinerary = itin;
list<Register> Defs = [DSPCtrl];
+ bit hasSideEffects = 1;
}
class LX_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
@@ -383,7 +396,7 @@ class APPEND_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
class EXTR_W_TY1_R2_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
InstrItinClass itin> {
dag OutOperandList = (outs CPURegs:$rt);
- dag InOperandList = (ins ACRegs:$ac, CPURegs:$shift_rs);
+ dag InOperandList = (ins ACRegsDSP:$ac, CPURegs:$shift_rs);
string AsmString = !strconcat(instr_asm, "\t$rt, $ac, $shift_rs");
InstrItinClass Itinerary = itin;
list<Register> Defs = [DSPCtrl];
@@ -392,46 +405,40 @@ class EXTR_W_TY1_R2_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
class EXTR_W_TY1_R1_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
InstrItinClass itin> {
dag OutOperandList = (outs CPURegs:$rt);
- dag InOperandList = (ins ACRegs:$ac, uimm16:$shift_rs);
+ dag InOperandList = (ins ACRegsDSP:$ac, uimm16:$shift_rs);
string AsmString = !strconcat(instr_asm, "\t$rt, $ac, $shift_rs");
InstrItinClass Itinerary = itin;
list<Register> Defs = [DSPCtrl];
}
-class SHILO_R1_PSEUDO_BASE<SDPatternOperator OpNode, InstrItinClass itin,
- Instruction realinst> :
- PseudoDSP<(outs), (ins simm16:$shift), [(OpNode immSExt6:$shift)]>,
- PseudoInstExpansion<(realinst AC0, simm16:$shift)> {
- list<Register> Defs = [DSPCtrl, AC0];
- list<Register> Uses = [AC0];
- InstrItinClass Itinerary = itin;
-}
-
-class SHILO_R1_DESC_BASE<string instr_asm> {
- dag OutOperandList = (outs ACRegs:$ac);
- dag InOperandList = (ins simm16:$shift);
+class SHILO_R1_DESC_BASE<string instr_asm, SDPatternOperator OpNode> {
+ dag OutOperandList = (outs ACRegsDSP:$ac);
+ dag InOperandList = (ins simm16:$shift, ACRegsDSP:$acin);
string AsmString = !strconcat(instr_asm, "\t$ac, $shift");
+ list<dag> Pattern = [(set ACRegsDSP:$ac,
+ (OpNode immSExt6:$shift, ACRegsDSP:$acin))];
+ list<Register> Defs = [DSPCtrl];
+ string Constraints = "$acin = $ac";
}
-class SHILO_R2_PSEUDO_BASE<SDPatternOperator OpNode, InstrItinClass itin,
- Instruction realinst> :
- PseudoDSP<(outs), (ins CPURegs:$rs), [(OpNode CPURegs:$rs)]>,
- PseudoInstExpansion<(realinst AC0, CPURegs:$rs)> {
- list<Register> Defs = [DSPCtrl, AC0];
- list<Register> Uses = [AC0];
- InstrItinClass Itinerary = itin;
-}
-
-class SHILO_R2_DESC_BASE<string instr_asm> {
- dag OutOperandList = (outs ACRegs:$ac);
- dag InOperandList = (ins CPURegs:$rs);
+class SHILO_R2_DESC_BASE<string instr_asm, SDPatternOperator OpNode> {
+ dag OutOperandList = (outs ACRegsDSP:$ac);
+ dag InOperandList = (ins CPURegs:$rs, ACRegsDSP:$acin);
string AsmString = !strconcat(instr_asm, "\t$ac, $rs");
+ list<dag> Pattern = [(set ACRegsDSP:$ac,
+ (OpNode CPURegs:$rs, ACRegsDSP:$acin))];
+ list<Register> Defs = [DSPCtrl];
+ string Constraints = "$acin = $ac";
}
-class MTHLIP_DESC_BASE<string instr_asm> {
- dag OutOperandList = (outs ACRegs:$ac);
- dag InOperandList = (ins CPURegs:$rs);
+class MTHLIP_DESC_BASE<string instr_asm, SDPatternOperator OpNode> {
+ dag OutOperandList = (outs ACRegsDSP:$ac);
+ dag InOperandList = (ins CPURegs:$rs, ACRegsDSP:$acin);
string AsmString = !strconcat(instr_asm, "\t$rs, $ac");
+ list<dag> Pattern = [(set ACRegsDSP:$ac,
+ (OpNode CPURegs:$rs, ACRegsDSP:$acin))];
+ list<Register> Uses = [DSPCtrl];
+ string Constraints = "$acin = $ac";
}
class RDDSP_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
@@ -454,35 +461,51 @@ class WRDSP_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
list<Register> Defs = [DSPCtrl];
}
-class DPA_W_PH_PSEUDO_BASE<SDPatternOperator OpNode, InstrItinClass itin,
- Instruction realinst> :
- PseudoDSP<(outs), (ins CPURegs:$rs, CPURegs:$rt),
- [(OpNode CPURegs:$rs, CPURegs:$rt)]>,
- PseudoInstExpansion<(realinst AC0, CPURegs:$rs, CPURegs:$rt)> {
- list<Register> Defs = [DSPCtrl, AC0];
- list<Register> Uses = [AC0];
- InstrItinClass Itinerary = itin;
+class DPA_W_PH_DESC_BASE<string instr_asm, SDPatternOperator OpNode> {
+ dag OutOperandList = (outs ACRegsDSP:$ac);
+ dag InOperandList = (ins CPURegs:$rs, CPURegs:$rt, ACRegsDSP:$acin);
+ string AsmString = !strconcat(instr_asm, "\t$ac, $rs, $rt");
+ list<dag> Pattern = [(set ACRegsDSP:$ac,
+ (OpNode CPURegs:$rs, CPURegs:$rt, ACRegsDSP:$acin))];
+ list<Register> Defs = [DSPCtrl];
+ string Constraints = "$acin = $ac";
}
-class DPA_W_PH_DESC_BASE<string instr_asm> {
- dag OutOperandList = (outs ACRegs:$ac);
+class MULT_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
+ InstrItinClass itin> {
+ dag OutOperandList = (outs ACRegsDSP:$ac);
dag InOperandList = (ins CPURegs:$rs, CPURegs:$rt);
string AsmString = !strconcat(instr_asm, "\t$ac, $rs, $rt");
+ list<dag> Pattern = [(set ACRegsDSP:$ac, (OpNode CPURegs:$rs, CPURegs:$rt))];
+ InstrItinClass Itinerary = itin;
+ int AddedComplexity = 20;
+ bit isCommutable = 1;
}
-class MULT_PSEUDO_BASE<SDPatternOperator OpNode, InstrItinClass itin,
- Instruction realinst> :
- PseudoDSP<(outs), (ins CPURegs:$rs, CPURegs:$rt),
- [(OpNode CPURegs:$rs, CPURegs:$rt)]>,
- PseudoInstExpansion<(realinst AC0, CPURegs:$rs, CPURegs:$rt)> {
- list<Register> Defs = [DSPCtrl, AC0];
+class MADD_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
+ InstrItinClass itin> {
+ dag OutOperandList = (outs ACRegsDSP:$ac);
+ dag InOperandList = (ins CPURegs:$rs, CPURegs:$rt, ACRegsDSP:$acin);
+ string AsmString = !strconcat(instr_asm, "\t$ac, $rs, $rt");
+ list<dag> Pattern = [(set ACRegsDSP:$ac,
+ (OpNode CPURegs:$rs, CPURegs:$rt, ACRegsDSP:$acin))];
InstrItinClass Itinerary = itin;
+ int AddedComplexity = 20;
+ string Constraints = "$acin = $ac";
}
-class MULT_DESC_BASE<string instr_asm> {
- dag OutOperandList = (outs ACRegs:$ac);
- dag InOperandList = (ins CPURegs:$rs, CPURegs:$rt);
- string AsmString = !strconcat(instr_asm, "\t$ac, $rs, $rt");
+class MFHI_DESC_BASE<string instr_asm, RegisterClass RC, InstrItinClass itin> {
+ dag OutOperandList = (outs CPURegs:$rd);
+ dag InOperandList = (ins RC:$ac);
+ string AsmString = !strconcat(instr_asm, "\t$rd, $ac");
+ InstrItinClass Itinerary = itin;
+}
+
+class MTHI_DESC_BASE<string instr_asm, RegisterClass RC, InstrItinClass itin> {
+ dag OutOperandList = (outs RC:$ac);
+ dag InOperandList = (ins CPURegs:$rs);
+ string AsmString = !strconcat(instr_asm, "\t$rs, $ac");
+ InstrItinClass Itinerary = itin;
}
class BPOSGE32_PSEUDO_DESC_BASE<SDPatternOperator OpNode, InstrItinClass itin> :
@@ -518,27 +541,27 @@ class INSV_DESC_BASE<string instr_asm, SDPatternOperator OpNode,
//===----------------------------------------------------------------------===//
// Addition/subtraction
-class ADDU_QB_DESC : ADDU_QB_DESC_BASE<"addu.qb", int_mips_addu_qb, NoItinerary,
+class ADDU_QB_DESC : ADDU_QB_DESC_BASE<"addu.qb", null_frag, NoItinerary,
DSPRegs, DSPRegs>, IsCommutable;
class ADDU_S_QB_DESC : ADDU_QB_DESC_BASE<"addu_s.qb", int_mips_addu_s_qb,
NoItinerary, DSPRegs, DSPRegs>,
IsCommutable;
-class SUBU_QB_DESC : ADDU_QB_DESC_BASE<"subu.qb", int_mips_subu_qb, NoItinerary,
+class SUBU_QB_DESC : ADDU_QB_DESC_BASE<"subu.qb", null_frag, NoItinerary,
DSPRegs, DSPRegs>;
class SUBU_S_QB_DESC : ADDU_QB_DESC_BASE<"subu_s.qb", int_mips_subu_s_qb,
NoItinerary, DSPRegs, DSPRegs>;
-class ADDQ_PH_DESC : ADDU_QB_DESC_BASE<"addq.ph", int_mips_addq_ph, NoItinerary,
+class ADDQ_PH_DESC : ADDU_QB_DESC_BASE<"addq.ph", null_frag, NoItinerary,
DSPRegs, DSPRegs>, IsCommutable;
class ADDQ_S_PH_DESC : ADDU_QB_DESC_BASE<"addq_s.ph", int_mips_addq_s_ph,
NoItinerary, DSPRegs, DSPRegs>,
IsCommutable;
-class SUBQ_PH_DESC : ADDU_QB_DESC_BASE<"subq.ph", int_mips_subq_ph, NoItinerary,
+class SUBQ_PH_DESC : ADDU_QB_DESC_BASE<"subq.ph", null_frag, NoItinerary,
DSPRegs, DSPRegs>;
class SUBQ_S_PH_DESC : ADDU_QB_DESC_BASE<"subq_s.ph", int_mips_subq_s_ph,
@@ -551,10 +574,10 @@ class ADDQ_S_W_DESC : ADDU_QB_DESC_BASE<"addq_s.w", int_mips_addq_s_w,
class SUBQ_S_W_DESC : ADDU_QB_DESC_BASE<"subq_s.w", int_mips_subq_s_w,
NoItinerary, CPURegs, CPURegs>;
-class ADDSC_DESC : ADDU_QB_DESC_BASE<"addsc", int_mips_addsc, NoItinerary,
+class ADDSC_DESC : ADDU_QB_DESC_BASE<"addsc", null_frag, NoItinerary,
CPURegs, CPURegs>, IsCommutable;
-class ADDWC_DESC : ADDU_QB_DESC_BASE<"addwc", int_mips_addwc, NoItinerary,
+class ADDWC_DESC : ADDU_QB_DESC_BASE<"addwc", null_frag, NoItinerary,
CPURegs, CPURegs>,
IsCommutable, UseDSPCtrl;
@@ -644,19 +667,19 @@ class PRECEU_PH_QBRA_DESC : ABSQ_S_PH_R2_DESC_BASE<"preceu.ph.qbra",
ClearDefs;
// Shift
-class SHLL_QB_DESC : SHLL_QB_R2_DESC_BASE<"shll.qb", int_mips_shll_qb, immZExt3,
+class SHLL_QB_DESC : SHLL_QB_R2_DESC_BASE<"shll.qb", null_frag, immZExt3,
NoItinerary, DSPRegs>;
class SHLLV_QB_DESC : SHLL_QB_R3_DESC_BASE<"shllv.qb", int_mips_shll_qb,
NoItinerary, DSPRegs>;
-class SHRL_QB_DESC : SHLL_QB_R2_DESC_BASE<"shrl.qb", int_mips_shrl_qb, immZExt3,
+class SHRL_QB_DESC : SHLL_QB_R2_DESC_BASE<"shrl.qb", null_frag, immZExt3,
NoItinerary, DSPRegs>, ClearDefs;
class SHRLV_QB_DESC : SHLL_QB_R3_DESC_BASE<"shrlv.qb", int_mips_shrl_qb,
NoItinerary, DSPRegs>, ClearDefs;
-class SHLL_PH_DESC : SHLL_QB_R2_DESC_BASE<"shll.ph", int_mips_shll_ph, immZExt4,
+class SHLL_PH_DESC : SHLL_QB_R2_DESC_BASE<"shll.ph", null_frag, immZExt4,
NoItinerary, DSPRegs>;
class SHLLV_PH_DESC : SHLL_QB_R3_DESC_BASE<"shllv.ph", int_mips_shll_ph,
@@ -668,7 +691,7 @@ class SHLL_S_PH_DESC : SHLL_QB_R2_DESC_BASE<"shll_s.ph", int_mips_shll_s_ph,
class SHLLV_S_PH_DESC : SHLL_QB_R3_DESC_BASE<"shllv_s.ph", int_mips_shll_s_ph,
NoItinerary, DSPRegs>;
-class SHRA_PH_DESC : SHLL_QB_R2_DESC_BASE<"shra.ph", int_mips_shra_ph, immZExt4,
+class SHRA_PH_DESC : SHLL_QB_R2_DESC_BASE<"shra.ph", null_frag, immZExt4,
NoItinerary, DSPRegs>, ClearDefs;
class SHRAV_PH_DESC : SHLL_QB_R3_DESC_BASE<"shrav.ph", int_mips_shra_ph,
@@ -717,44 +740,46 @@ class MULQ_RS_PH_DESC : ADDU_QB_DESC_BASE<"mulq_rs.ph", int_mips_mulq_rs_ph,
NoItinerary, DSPRegs, DSPRegs>,
IsCommutable;
-class MULSAQ_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"mulsaq_s.w.ph">;
+class MULSAQ_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"mulsaq_s.w.ph",
+ MipsMULSAQ_S_W_PH>;
-class MAQ_S_W_PHL_DESC : DPA_W_PH_DESC_BASE<"maq_s.w.phl">;
+class MAQ_S_W_PHL_DESC : DPA_W_PH_DESC_BASE<"maq_s.w.phl", MipsMAQ_S_W_PHL>;
-class MAQ_S_W_PHR_DESC : DPA_W_PH_DESC_BASE<"maq_s.w.phr">;
+class MAQ_S_W_PHR_DESC : DPA_W_PH_DESC_BASE<"maq_s.w.phr", MipsMAQ_S_W_PHR>;
-class MAQ_SA_W_PHL_DESC : DPA_W_PH_DESC_BASE<"maq_sa.w.phl">;
+class MAQ_SA_W_PHL_DESC : DPA_W_PH_DESC_BASE<"maq_sa.w.phl", MipsMAQ_SA_W_PHL>;
-class MAQ_SA_W_PHR_DESC : DPA_W_PH_DESC_BASE<"maq_sa.w.phr">;
-
-// Dot product with accumulate/subtract
-class DPAU_H_QBL_DESC : DPA_W_PH_DESC_BASE<"dpau.h.qbl">;
+class MAQ_SA_W_PHR_DESC : DPA_W_PH_DESC_BASE<"maq_sa.w.phr", MipsMAQ_SA_W_PHR>;
-class DPAU_H_QBR_DESC : DPA_W_PH_DESC_BASE<"dpau.h.qbr">;
+// Move from/to hi/lo.
+class MFHI_DESC : MFHI_DESC_BASE<"mfhi", HIRegsDSP, NoItinerary>;
+class MFLO_DESC : MFHI_DESC_BASE<"mflo", LORegsDSP, NoItinerary>;
+class MTHI_DESC : MTHI_DESC_BASE<"mthi", HIRegsDSP, NoItinerary>;
+class MTLO_DESC : MTHI_DESC_BASE<"mtlo", LORegsDSP, NoItinerary>;
-class DPSU_H_QBL_DESC : DPA_W_PH_DESC_BASE<"dpsu.h.qbl">;
-
-class DPSU_H_QBR_DESC : DPA_W_PH_DESC_BASE<"dpsu.h.qbr">;
-
-class DPAQ_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpaq_s.w.ph">;
-
-class DPSQ_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpsq_s.w.ph">;
+// Dot product with accumulate/subtract
+class DPAU_H_QBL_DESC : DPA_W_PH_DESC_BASE<"dpau.h.qbl", MipsDPAU_H_QBL>;
-class DPAQ_SA_L_W_DESC : DPA_W_PH_DESC_BASE<"dpaq_sa.l.w">;
+class DPAU_H_QBR_DESC : DPA_W_PH_DESC_BASE<"dpau.h.qbr", MipsDPAU_H_QBR>;
-class DPSQ_SA_L_W_DESC : DPA_W_PH_DESC_BASE<"dpsq_sa.l.w">;
+class DPSU_H_QBL_DESC : DPA_W_PH_DESC_BASE<"dpsu.h.qbl", MipsDPSU_H_QBL>;
-class MULT_DSP_DESC : MULT_DESC_BASE<"mult">;
+class DPSU_H_QBR_DESC : DPA_W_PH_DESC_BASE<"dpsu.h.qbr", MipsDPSU_H_QBR>;
-class MULTU_DSP_DESC : MULT_DESC_BASE<"multu">;
+class DPAQ_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpaq_s.w.ph", MipsDPAQ_S_W_PH>;
-class MADD_DSP_DESC : MULT_DESC_BASE<"madd">;
+class DPSQ_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpsq_s.w.ph", MipsDPSQ_S_W_PH>;
-class MADDU_DSP_DESC : MULT_DESC_BASE<"maddu">;
+class DPAQ_SA_L_W_DESC : DPA_W_PH_DESC_BASE<"dpaq_sa.l.w", MipsDPAQ_SA_L_W>;
-class MSUB_DSP_DESC : MULT_DESC_BASE<"msub">;
+class DPSQ_SA_L_W_DESC : DPA_W_PH_DESC_BASE<"dpsq_sa.l.w", MipsDPSQ_SA_L_W>;
-class MSUBU_DSP_DESC : MULT_DESC_BASE<"msubu">;
+class MULT_DSP_DESC : MULT_DESC_BASE<"mult", MipsMult, NoItinerary>;
+class MULTU_DSP_DESC : MULT_DESC_BASE<"multu", MipsMultu, NoItinerary>;
+class MADD_DSP_DESC : MADD_DESC_BASE<"madd", MipsMAdd, NoItinerary>;
+class MADDU_DSP_DESC : MADD_DESC_BASE<"maddu", MipsMAddu, NoItinerary>;
+class MSUB_DSP_DESC : MADD_DESC_BASE<"msub", MipsMSub, NoItinerary>;
+class MSUBU_DSP_DESC : MADD_DESC_BASE<"msubu", MipsMSubu, NoItinerary>;
// Comparison
class CMPU_EQ_QB_DESC : CMP_EQ_QB_R2_DESC_BASE<"cmpu.eq.qb",
@@ -763,11 +788,11 @@ class CMPU_EQ_QB_DESC : CMP_EQ_QB_R2_DESC_BASE<"cmpu.eq.qb",
class CMPU_LT_QB_DESC : CMP_EQ_QB_R2_DESC_BASE<"cmpu.lt.qb",
int_mips_cmpu_lt_qb, NoItinerary,
- DSPRegs>, IsCommutable;
+ DSPRegs>;
class CMPU_LE_QB_DESC : CMP_EQ_QB_R2_DESC_BASE<"cmpu.le.qb",
int_mips_cmpu_le_qb, NoItinerary,
- DSPRegs>, IsCommutable;
+ DSPRegs>;
class CMPGU_EQ_QB_DESC : CMP_EQ_QB_R3_DESC_BASE<"cmpgu.eq.qb",
int_mips_cmpgu_eq_qb,
@@ -776,25 +801,21 @@ class CMPGU_EQ_QB_DESC : CMP_EQ_QB_R3_DESC_BASE<"cmpgu.eq.qb",
class CMPGU_LT_QB_DESC : CMP_EQ_QB_R3_DESC_BASE<"cmpgu.lt.qb",
int_mips_cmpgu_lt_qb,
- NoItinerary, CPURegs, DSPRegs>,
- IsCommutable;
+ NoItinerary, CPURegs, DSPRegs>;
class CMPGU_LE_QB_DESC : CMP_EQ_QB_R3_DESC_BASE<"cmpgu.le.qb",
int_mips_cmpgu_le_qb,
- NoItinerary, CPURegs, DSPRegs>,
- IsCommutable;
+ NoItinerary, CPURegs, DSPRegs>;
class CMP_EQ_PH_DESC : CMP_EQ_QB_R2_DESC_BASE<"cmp.eq.ph", int_mips_cmp_eq_ph,
NoItinerary, DSPRegs>,
IsCommutable;
class CMP_LT_PH_DESC : CMP_EQ_QB_R2_DESC_BASE<"cmp.lt.ph", int_mips_cmp_lt_ph,
- NoItinerary, DSPRegs>,
- IsCommutable;
+ NoItinerary, DSPRegs>;
class CMP_LE_PH_DESC : CMP_EQ_QB_R2_DESC_BASE<"cmp.le.ph", int_mips_cmp_le_ph,
- NoItinerary, DSPRegs>,
- IsCommutable;
+ NoItinerary, DSPRegs>;
// Misc
class BITREV_DESC : ABSQ_S_PH_R2_DESC_BASE<"bitrev", int_mips_bitrev,
@@ -867,11 +888,11 @@ class EXTR_S_H_DESC : EXTR_W_TY1_R1_DESC_BASE<"extr_s.h", MipsEXTR_S_H,
class EXTRV_S_H_DESC : EXTR_W_TY1_R2_DESC_BASE<"extrv_s.h", MipsEXTR_S_H,
NoItinerary>;
-class SHILO_DESC : SHILO_R1_DESC_BASE<"shilo">;
+class SHILO_DESC : SHILO_R1_DESC_BASE<"shilo", MipsSHILO>;
-class SHILOV_DESC : SHILO_R2_DESC_BASE<"shilov">;
+class SHILOV_DESC : SHILO_R2_DESC_BASE<"shilov", MipsSHILO>;
-class MTHLIP_DESC : MTHLIP_DESC_BASE<"mthlip">;
+class MTHLIP_DESC : MTHLIP_DESC_BASE<"mthlip", MipsMTHLIP>;
class RDDSP_DESC : RDDSP_DESC_BASE<"rddsp", int_mips_rddsp, NoItinerary>;
@@ -945,20 +966,18 @@ class CMPGDU_EQ_QB_DESC : CMP_EQ_QB_R3_DESC_BASE<"cmpgdu.eq.qb",
class CMPGDU_LT_QB_DESC : CMP_EQ_QB_R3_DESC_BASE<"cmpgdu.lt.qb",
int_mips_cmpgdu_lt_qb,
- NoItinerary, CPURegs, DSPRegs>,
- IsCommutable;
+ NoItinerary, CPURegs, DSPRegs>;
class CMPGDU_LE_QB_DESC : CMP_EQ_QB_R3_DESC_BASE<"cmpgdu.le.qb",
int_mips_cmpgdu_le_qb,
- NoItinerary, CPURegs, DSPRegs>,
- IsCommutable;
+ NoItinerary, CPURegs, DSPRegs>;
// Absolute
class ABSQ_S_QB_DESC : ABSQ_S_PH_R2_DESC_BASE<"absq_s.qb", int_mips_absq_s_qb,
NoItinerary, DSPRegs>;
// Multiplication
-class MUL_PH_DESC : ADDUH_QB_DESC_BASE<"mul.ph", int_mips_mul_ph, NoItinerary,
+class MUL_PH_DESC : ADDUH_QB_DESC_BASE<"mul.ph", null_frag, NoItinerary,
DSPRegs>, IsCommutable;
class MUL_S_PH_DESC : ADDUH_QB_DESC_BASE<"mul_s.ph", int_mips_mul_s_ph,
@@ -975,23 +994,25 @@ class MULQ_S_PH_DESC : ADDU_QB_DESC_BASE<"mulq_s.ph", int_mips_mulq_s_ph,
IsCommutable;
// Dot product with accumulate/subtract
-class DPA_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpa.w.ph">;
+class DPA_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpa.w.ph", MipsDPA_W_PH>;
-class DPS_W_PH_DESC : DPA_W_PH_DESC_BASE<"dps.w.ph">;
+class DPS_W_PH_DESC : DPA_W_PH_DESC_BASE<"dps.w.ph", MipsDPS_W_PH>;
-class DPAQX_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpaqx_s.w.ph">;
+class DPAQX_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpaqx_s.w.ph", MipsDPAQX_S_W_PH>;
-class DPAQX_SA_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpaqx_sa.w.ph">;
+class DPAQX_SA_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpaqx_sa.w.ph",
+ MipsDPAQX_SA_W_PH>;
-class DPAX_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpax.w.ph">;
+class DPAX_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpax.w.ph", MipsDPAX_W_PH>;
-class DPSX_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpsx.w.ph">;
+class DPSX_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpsx.w.ph", MipsDPSX_W_PH>;
-class DPSQX_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpsqx_s.w.ph">;
+class DPSQX_S_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpsqx_s.w.ph", MipsDPSQX_S_W_PH>;
-class DPSQX_SA_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpsqx_sa.w.ph">;
+class DPSQX_SA_W_PH_DESC : DPA_W_PH_DESC_BASE<"dpsqx_sa.w.ph",
+ MipsDPSQX_SA_W_PH>;
-class MULSA_W_PH_DESC : DPA_W_PH_DESC_BASE<"mulsa.w.ph">;
+class MULSA_W_PH_DESC : DPA_W_PH_DESC_BASE<"mulsa.w.ph", MipsMULSA_W_PH>;
// Precision reduce/expand
class PRECR_QB_PH_DESC : CMP_EQ_QB_R3_DESC_BASE<"precr.qb.ph",
@@ -1009,7 +1030,7 @@ class PRECR_SRA_R_PH_W_DESC : PRECR_SRA_PH_W_DESC_BASE<"precr_sra_r.ph.w",
CPURegs>, ClearDefs;
// Shift
-class SHRA_QB_DESC : SHLL_QB_R2_DESC_BASE<"shra.qb", int_mips_shra_qb, immZExt3,
+class SHRA_QB_DESC : SHLL_QB_R2_DESC_BASE<"shra.qb", null_frag, immZExt3,
NoItinerary, DSPRegs>, ClearDefs;
class SHRAV_QB_DESC : SHLL_QB_R3_DESC_BASE<"shrav.qb", int_mips_shra_qb,
@@ -1022,7 +1043,7 @@ class SHRA_R_QB_DESC : SHLL_QB_R2_DESC_BASE<"shra_r.qb", int_mips_shra_r_qb,
class SHRAV_R_QB_DESC : SHLL_QB_R3_DESC_BASE<"shrav_r.qb", int_mips_shra_r_qb,
NoItinerary, DSPRegs>, ClearDefs;
-class SHRL_PH_DESC : SHLL_QB_R2_DESC_BASE<"shrl.ph", int_mips_shrl_ph, immZExt4,
+class SHRL_PH_DESC : SHLL_QB_R2_DESC_BASE<"shrl.ph", null_frag, immZExt4,
NoItinerary, DSPRegs>, ClearDefs;
class SHRLV_PH_DESC : SHLL_QB_R3_DESC_BASE<"shrlv.ph", int_mips_shrl_ph,
@@ -1099,6 +1120,10 @@ def MAQ_S_W_PHL : MAQ_S_W_PHL_ENC, MAQ_S_W_PHL_DESC;
def MAQ_S_W_PHR : MAQ_S_W_PHR_ENC, MAQ_S_W_PHR_DESC;
def MAQ_SA_W_PHL : MAQ_SA_W_PHL_ENC, MAQ_SA_W_PHL_DESC;
def MAQ_SA_W_PHR : MAQ_SA_W_PHR_ENC, MAQ_SA_W_PHR_DESC;
+def MFHI_DSP : MFHI_ENC, MFHI_DESC;
+def MFLO_DSP : MFLO_ENC, MFLO_DESC;
+def MTHI_DSP : MTHI_ENC, MTHI_DESC;
+def MTLO_DSP : MTLO_ENC, MTLO_DESC;
def DPAU_H_QBL : DPAU_H_QBL_ENC, DPAU_H_QBL_DESC;
def DPAU_H_QBR : DPAU_H_QBR_ENC, DPAU_H_QBR_DESC;
def DPSU_H_QBL : DPSU_H_QBL_ENC, DPSU_H_QBL_DESC;
@@ -1206,70 +1231,31 @@ def PREPEND : PREPEND_ENC, PREPEND_DESC;
}
// Pseudos.
-def MULSAQ_S_W_PH_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsMULSAQ_S_W_PH, NoItinerary,
- MULSAQ_S_W_PH>;
-def MAQ_S_W_PHL_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsMAQ_S_W_PHL, NoItinerary,
- MAQ_S_W_PHL>;
-def MAQ_S_W_PHR_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsMAQ_S_W_PHR, NoItinerary,
- MAQ_S_W_PHR>;
-def MAQ_SA_W_PHL_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsMAQ_SA_W_PHL, NoItinerary,
- MAQ_SA_W_PHL>;
-def MAQ_SA_W_PHR_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsMAQ_SA_W_PHR, NoItinerary,
- MAQ_SA_W_PHR>;
-def DPAU_H_QBL_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsDPAU_H_QBL, NoItinerary,
- DPAU_H_QBL>;
-def DPAU_H_QBR_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsDPAU_H_QBR, NoItinerary,
- DPAU_H_QBR>;
-def DPSU_H_QBL_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsDPSU_H_QBL, NoItinerary,
- DPSU_H_QBL>;
-def DPSU_H_QBR_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsDPSU_H_QBR, NoItinerary,
- DPSU_H_QBR>;
-def DPAQ_S_W_PH_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsDPAQ_S_W_PH, NoItinerary,
- DPAQ_S_W_PH>;
-def DPSQ_S_W_PH_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsDPSQ_S_W_PH, NoItinerary,
- DPSQ_S_W_PH>;
-def DPAQ_SA_L_W_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsDPAQ_SA_L_W, NoItinerary,
- DPAQ_SA_L_W>;
-def DPSQ_SA_L_W_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsDPSQ_SA_L_W, NoItinerary,
- DPSQ_SA_L_W>;
-
-def MULT_DSP_PSEUDO : MULT_PSEUDO_BASE<MipsMULT, NoItinerary, MULT_DSP>,
- IsCommutable;
-def MULTU_DSP_PSEUDO : MULT_PSEUDO_BASE<MipsMULTU, NoItinerary, MULTU_DSP>,
- IsCommutable;
-def MADD_DSP_PSEUDO : MULT_PSEUDO_BASE<MipsMADD_DSP, NoItinerary, MADD_DSP>,
- IsCommutable, UseAC;
-def MADDU_DSP_PSEUDO : MULT_PSEUDO_BASE<MipsMADDU_DSP, NoItinerary, MADDU_DSP>,
- IsCommutable, UseAC;
-def MSUB_DSP_PSEUDO : MULT_PSEUDO_BASE<MipsMSUB_DSP, NoItinerary, MSUB_DSP>,
- UseAC;
-def MSUBU_DSP_PSEUDO : MULT_PSEUDO_BASE<MipsMSUBU_DSP, NoItinerary, MSUBU_DSP>,
- UseAC;
-
-def SHILO_PSEUDO : SHILO_R1_PSEUDO_BASE<MipsSHILO, NoItinerary, SHILO>;
-def SHILOV_PSEUDO : SHILO_R2_PSEUDO_BASE<MipsSHILO, NoItinerary, SHILOV>;
-def MTHLIP_PSEUDO : SHILO_R2_PSEUDO_BASE<MipsMTHLIP, NoItinerary, MTHLIP>;
+/// Pseudo instructions for loading and storing accumulator registers.
+let isPseudo = 1 in {
+ defm LOAD_AC_DSP : LoadM<"load_ac_dsp", ACRegsDSP>;
+ defm STORE_AC_DSP : StoreM<"store_ac_dsp", ACRegsDSP>;
+}
-let Predicates = [HasDSPR2] in {
+// Pseudo CMP and PICK instructions.
+class PseudoCMP<Instruction RealInst> :
+ PseudoDSP<(outs DSPCC:$cmp), (ins DSPRegs:$rs, DSPRegs:$rt), []>,
+ PseudoInstExpansion<(RealInst DSPRegs:$rs, DSPRegs:$rt)>, NeverHasSideEffects;
-def DPA_W_PH_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsDPA_W_PH, NoItinerary, DPA_W_PH>;
-def DPS_W_PH_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsDPS_W_PH, NoItinerary, DPS_W_PH>;
-def DPAQX_S_W_PH_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsDPAQX_S_W_PH, NoItinerary,
- DPAQX_S_W_PH>;
-def DPAQX_SA_W_PH_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsDPAQX_SA_W_PH, NoItinerary,
- DPAQX_SA_W_PH>;
-def DPAX_W_PH_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsDPAX_W_PH, NoItinerary,
- DPAX_W_PH>;
-def DPSX_W_PH_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsDPSX_W_PH, NoItinerary,
- DPSX_W_PH>;
-def DPSQX_S_W_PH_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsDPSQX_S_W_PH, NoItinerary,
- DPSQX_S_W_PH>;
-def DPSQX_SA_W_PH_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsDPSQX_SA_W_PH, NoItinerary,
- DPSQX_SA_W_PH>;
-def MULSA_W_PH_PSEUDO : DPA_W_PH_PSEUDO_BASE<MipsMULSA_W_PH, NoItinerary,
- MULSA_W_PH>;
+class PseudoPICK<Instruction RealInst> :
+ PseudoDSP<(outs DSPRegs:$rd), (ins DSPCC:$cmp, DSPRegs:$rs, DSPRegs:$rt), []>,
+ PseudoInstExpansion<(RealInst DSPRegs:$rd, DSPRegs:$rs, DSPRegs:$rt)>,
+ NeverHasSideEffects;
-}
+def PseudoCMP_EQ_PH : PseudoCMP<CMP_EQ_PH>;
+def PseudoCMP_LT_PH : PseudoCMP<CMP_LT_PH>;
+def PseudoCMP_LE_PH : PseudoCMP<CMP_LE_PH>;
+def PseudoCMPU_EQ_QB : PseudoCMP<CMPU_EQ_QB>;
+def PseudoCMPU_LT_QB : PseudoCMP<CMPU_LT_QB>;
+def PseudoCMPU_LE_QB : PseudoCMP<CMPU_LE_QB>;
+
+def PseudoPICK_PH : PseudoPICK<PICK_PH>;
+def PseudoPICK_QB : PseudoPICK<PICK_QB>;
// Patterns.
class DSPPat<dag pattern, dag result, Predicate pred = HasDSP> :
@@ -1294,12 +1280,103 @@ def : DSPPat<(store (v2i16 DSPRegs:$val), addr:$a),
def : DSPPat<(store (v4i8 DSPRegs:$val), addr:$a),
(SW (COPY_TO_REGCLASS DSPRegs:$val, CPURegs), addr:$a)>;
+// Binary operations.
+class DSPBinPat<Instruction Inst, ValueType ValTy, SDPatternOperator Node,
+ Predicate Pred = HasDSP> :
+ DSPPat<(Node ValTy:$a, ValTy:$b), (Inst ValTy:$a, ValTy:$b), Pred>;
+
+def : DSPBinPat<ADDQ_PH, v2i16, int_mips_addq_ph>;
+def : DSPBinPat<ADDQ_PH, v2i16, add>;
+def : DSPBinPat<SUBQ_PH, v2i16, int_mips_subq_ph>;
+def : DSPBinPat<SUBQ_PH, v2i16, sub>;
+def : DSPBinPat<MUL_PH, v2i16, int_mips_mul_ph, HasDSPR2>;
+def : DSPBinPat<MUL_PH, v2i16, mul, HasDSPR2>;
+def : DSPBinPat<ADDU_QB, v4i8, int_mips_addu_qb>;
+def : DSPBinPat<ADDU_QB, v4i8, add>;
+def : DSPBinPat<SUBU_QB, v4i8, int_mips_subu_qb>;
+def : DSPBinPat<SUBU_QB, v4i8, sub>;
+def : DSPBinPat<ADDSC, i32, int_mips_addsc>;
+def : DSPBinPat<ADDSC, i32, addc>;
+def : DSPBinPat<ADDWC, i32, int_mips_addwc>;
+def : DSPBinPat<ADDWC, i32, adde>;
+
+// Shift immediate patterns.
+class DSPShiftPat<Instruction Inst, ValueType ValTy, SDPatternOperator Node,
+ SDPatternOperator Imm, Predicate Pred = HasDSP> :
+ DSPPat<(Node ValTy:$a, Imm:$shamt), (Inst ValTy:$a, Imm:$shamt), Pred>;
+
+def : DSPShiftPat<SHLL_PH, v2i16, MipsSHLL_DSP, imm>;
+def : DSPShiftPat<SHRA_PH, v2i16, MipsSHRA_DSP, imm>;
+def : DSPShiftPat<SHRL_PH, v2i16, MipsSHRL_DSP, imm, HasDSPR2>;
+def : DSPShiftPat<SHLL_PH, v2i16, int_mips_shll_ph, immZExt4>;
+def : DSPShiftPat<SHRA_PH, v2i16, int_mips_shra_ph, immZExt4>;
+def : DSPShiftPat<SHRL_PH, v2i16, int_mips_shrl_ph, immZExt4, HasDSPR2>;
+def : DSPShiftPat<SHLL_QB, v4i8, MipsSHLL_DSP, imm>;
+def : DSPShiftPat<SHRA_QB, v4i8, MipsSHRA_DSP, imm, HasDSPR2>;
+def : DSPShiftPat<SHRL_QB, v4i8, MipsSHRL_DSP, imm>;
+def : DSPShiftPat<SHLL_QB, v4i8, int_mips_shll_qb, immZExt3>;
+def : DSPShiftPat<SHRA_QB, v4i8, int_mips_shra_qb, immZExt3, HasDSPR2>;
+def : DSPShiftPat<SHRL_QB, v4i8, int_mips_shrl_qb, immZExt3>;
+
+// SETCC/SELECT_CC patterns.
+class DSPSetCCPat<Instruction Cmp, Instruction Pick, ValueType ValTy,
+ CondCode CC> :
+ DSPPat<(ValTy (MipsSETCC_DSP ValTy:$a, ValTy:$b, CC)),
+ (ValTy (Pick (ValTy (Cmp ValTy:$a, ValTy:$b)),
+ (ValTy (COPY_TO_REGCLASS (ADDiu ZERO, -1), DSPRegs)),
+ (ValTy ZERO)))>;
+
+class DSPSetCCPatInv<Instruction Cmp, Instruction Pick, ValueType ValTy,
+ CondCode CC> :
+ DSPPat<(ValTy (MipsSETCC_DSP ValTy:$a, ValTy:$b, CC)),
+ (ValTy (Pick (ValTy (Cmp ValTy:$a, ValTy:$b)),
+ (ValTy ZERO),
+ (ValTy (COPY_TO_REGCLASS (ADDiu ZERO, -1), DSPRegs))))>;
+
+class DSPSelectCCPat<Instruction Cmp, Instruction Pick, ValueType ValTy,
+ CondCode CC> :
+ DSPPat<(ValTy (MipsSELECT_CC_DSP ValTy:$a, ValTy:$b, ValTy:$c, ValTy:$d, CC)),
+ (ValTy (Pick (ValTy (Cmp ValTy:$a, ValTy:$b)), $c, $d))>;
+
+class DSPSelectCCPatInv<Instruction Cmp, Instruction Pick, ValueType ValTy,
+ CondCode CC> :
+ DSPPat<(ValTy (MipsSELECT_CC_DSP ValTy:$a, ValTy:$b, ValTy:$c, ValTy:$d, CC)),
+ (ValTy (Pick (ValTy (Cmp ValTy:$a, ValTy:$b)), $d, $c))>;
+
+def : DSPSetCCPat<PseudoCMP_EQ_PH, PseudoPICK_PH, v2i16, SETEQ>;
+def : DSPSetCCPat<PseudoCMP_LT_PH, PseudoPICK_PH, v2i16, SETLT>;
+def : DSPSetCCPat<PseudoCMP_LE_PH, PseudoPICK_PH, v2i16, SETLE>;
+def : DSPSetCCPatInv<PseudoCMP_EQ_PH, PseudoPICK_PH, v2i16, SETNE>;
+def : DSPSetCCPatInv<PseudoCMP_LT_PH, PseudoPICK_PH, v2i16, SETGE>;
+def : DSPSetCCPatInv<PseudoCMP_LE_PH, PseudoPICK_PH, v2i16, SETGT>;
+def : DSPSetCCPat<PseudoCMPU_EQ_QB, PseudoPICK_QB, v4i8, SETEQ>;
+def : DSPSetCCPat<PseudoCMPU_LT_QB, PseudoPICK_QB, v4i8, SETULT>;
+def : DSPSetCCPat<PseudoCMPU_LE_QB, PseudoPICK_QB, v4i8, SETULE>;
+def : DSPSetCCPatInv<PseudoCMPU_EQ_QB, PseudoPICK_QB, v4i8, SETNE>;
+def : DSPSetCCPatInv<PseudoCMPU_LT_QB, PseudoPICK_QB, v4i8, SETUGE>;
+def : DSPSetCCPatInv<PseudoCMPU_LE_QB, PseudoPICK_QB, v4i8, SETUGT>;
+
+def : DSPSelectCCPat<PseudoCMP_EQ_PH, PseudoPICK_PH, v2i16, SETEQ>;
+def : DSPSelectCCPat<PseudoCMP_LT_PH, PseudoPICK_PH, v2i16, SETLT>;
+def : DSPSelectCCPat<PseudoCMP_LE_PH, PseudoPICK_PH, v2i16, SETLE>;
+def : DSPSelectCCPatInv<PseudoCMP_EQ_PH, PseudoPICK_PH, v2i16, SETNE>;
+def : DSPSelectCCPatInv<PseudoCMP_LT_PH, PseudoPICK_PH, v2i16, SETGE>;
+def : DSPSelectCCPatInv<PseudoCMP_LE_PH, PseudoPICK_PH, v2i16, SETGT>;
+def : DSPSelectCCPat<PseudoCMPU_EQ_QB, PseudoPICK_QB, v4i8, SETEQ>;
+def : DSPSelectCCPat<PseudoCMPU_LT_QB, PseudoPICK_QB, v4i8, SETULT>;
+def : DSPSelectCCPat<PseudoCMPU_LE_QB, PseudoPICK_QB, v4i8, SETULE>;
+def : DSPSelectCCPatInv<PseudoCMPU_EQ_QB, PseudoPICK_QB, v4i8, SETNE>;
+def : DSPSelectCCPatInv<PseudoCMPU_LT_QB, PseudoPICK_QB, v4i8, SETUGE>;
+def : DSPSelectCCPatInv<PseudoCMPU_LE_QB, PseudoPICK_QB, v4i8, SETUGT>;
+
// Extr patterns.
class EXTR_W_TY1_R2_Pat<SDPatternOperator OpNode, Instruction Instr> :
- DSPPat<(i32 (OpNode CPURegs:$rs)), (Instr AC0, CPURegs:$rs)>;
+ DSPPat<(i32 (OpNode CPURegs:$rs, ACRegsDSP:$ac)),
+ (Instr ACRegsDSP:$ac, CPURegs:$rs)>;
class EXTR_W_TY1_R1_Pat<SDPatternOperator OpNode, Instruction Instr> :
- DSPPat<(i32 (OpNode immZExt5:$shift)), (Instr AC0, immZExt5:$shift)>;
+ DSPPat<(i32 (OpNode immZExt5:$shift, ACRegsDSP:$ac)),
+ (Instr ACRegsDSP:$ac, immZExt5:$shift)>;
def : EXTR_W_TY1_R1_Pat<MipsEXTP, EXTP>;
def : EXTR_W_TY1_R2_Pat<MipsEXTP, EXTPV>;
@@ -1313,3 +1390,19 @@ def : EXTR_W_TY1_R1_Pat<MipsEXTR_RS_W, EXTR_RS_W>;
def : EXTR_W_TY1_R2_Pat<MipsEXTR_RS_W, EXTRV_RS_W>;
def : EXTR_W_TY1_R1_Pat<MipsEXTR_S_H, EXTR_S_H>;
def : EXTR_W_TY1_R2_Pat<MipsEXTR_S_H, EXTRV_S_H>;
+
+// mflo/hi patterns.
+let AddedComplexity = 20 in
+def : DSPPat<(i32 (ExtractLOHI ACRegsDSP:$ac, imm:$lohi_idx)),
+ (EXTRACT_SUBREG ACRegsDSP:$ac, imm:$lohi_idx)>;
+
+// Indexed load patterns.
+class IndexedLoadPat<SDPatternOperator LoadNode, Instruction Instr> :
+ DSPPat<(i32 (LoadNode (add i32:$base, i32:$index))),
+ (Instr i32:$base, i32:$index)>;
+
+let AddedComplexity = 20 in {
+ def : IndexedLoadPat<zextloadi8, LBUX>;
+ def : IndexedLoadPat<sextloadi16, LHX>;
+ def : IndexedLoadPat<load, LWX>;
+}
diff --git a/lib/Target/Mips/MipsDelaySlotFiller.cpp b/lib/Target/Mips/MipsDelaySlotFiller.cpp
index e265590..d07a595 100644
--- a/lib/Target/Mips/MipsDelaySlotFiller.cpp
+++ b/lib/Target/Mips/MipsDelaySlotFiller.cpp
@@ -220,9 +220,9 @@ namespace {
/// that can be moved to the delay slot. Returns true on success.
bool searchForward(MachineBasicBlock &MBB, Iter Slot) const;
- /// This function searches MBB's successor blocks for an instruction that
- /// can be moved to the delay slot and inserts clones of the instruction
- /// into the successor blocks.
+ /// This function searches one of MBB's successor blocks for an instruction
+ /// that can be moved to the delay slot and inserts clones of the
+ /// instruction into the successor's predecessor blocks.
bool searchSuccBBs(MachineBasicBlock &MBB, Iter Slot) const;
/// Pick a successor block of MBB. Return NULL if MBB doesn't have a
diff --git a/lib/Target/Mips/MipsFrameLowering.h b/lib/Target/Mips/MipsFrameLowering.h
index 14268d2..6a5f79d 100644
--- a/lib/Target/Mips/MipsFrameLowering.h
+++ b/lib/Target/Mips/MipsFrameLowering.h
@@ -26,9 +26,8 @@ protected:
const MipsSubtarget &STI;
public:
- explicit MipsFrameLowering(const MipsSubtarget &sti)
- : TargetFrameLowering(StackGrowsDown, sti.hasMips64() ? 16 : 8, 0,
- sti.hasMips64() ? 16 : 8), STI(sti) {}
+ explicit MipsFrameLowering(const MipsSubtarget &sti, unsigned Alignment)
+ : TargetFrameLowering(StackGrowsDown, Alignment, 0, Alignment), STI(sti) {}
static const MipsFrameLowering *create(MipsTargetMachine &TM,
const MipsSubtarget &ST);
diff --git a/lib/Target/Mips/MipsISelDAGToDAG.cpp b/lib/Target/Mips/MipsISelDAGToDAG.cpp
index 77b08cb..968e536 100644
--- a/lib/Target/Mips/MipsISelDAGToDAG.cpp
+++ b/lib/Target/Mips/MipsISelDAGToDAG.cpp
@@ -17,7 +17,6 @@
#include "MipsSEISelDAGToDAG.h"
#include "Mips.h"
#include "MCTargetDesc/MipsBaseInfo.h"
-#include "MipsAnalyzeImmediate.h"
#include "MipsMachineFunction.h"
#include "MipsRegisterInfo.h"
#include "llvm/CodeGen/MachineConstantPool.h"
diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp
index 4bf43f4..4d76181 100644
--- a/lib/Target/Mips/MipsISelLowering.cpp
+++ b/lib/Target/Mips/MipsISelLowering.cpp
@@ -30,7 +30,6 @@
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/GlobalVariable.h"
-#include "llvm/IR/Intrinsics.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
@@ -158,12 +157,18 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const {
case MipsISD::CMovFP_T: return "MipsISD::CMovFP_T";
case MipsISD::CMovFP_F: return "MipsISD::CMovFP_F";
case MipsISD::FPRound: return "MipsISD::FPRound";
+ case MipsISD::ExtractLOHI: return "MipsISD::ExtractLOHI";
+ case MipsISD::InsertLOHI: return "MipsISD::InsertLOHI";
+ case MipsISD::Mult: return "MipsISD::Mult";
+ case MipsISD::Multu: return "MipsISD::Multu";
case MipsISD::MAdd: return "MipsISD::MAdd";
case MipsISD::MAddu: return "MipsISD::MAddu";
case MipsISD::MSub: return "MipsISD::MSub";
case MipsISD::MSubu: return "MipsISD::MSubu";
case MipsISD::DivRem: return "MipsISD::DivRem";
case MipsISD::DivRemU: return "MipsISD::DivRemU";
+ case MipsISD::DivRem16: return "MipsISD::DivRem16";
+ case MipsISD::DivRemU16: return "MipsISD::DivRemU16";
case MipsISD::BuildPairF64: return "MipsISD::BuildPairF64";
case MipsISD::ExtractElementF64: return "MipsISD::ExtractElementF64";
case MipsISD::Wrapper: return "MipsISD::Wrapper";
@@ -192,6 +197,11 @@ const char *MipsTargetLowering::getTargetNodeName(unsigned Opcode) const {
case MipsISD::MADDU_DSP: return "MipsISD::MADDU_DSP";
case MipsISD::MSUB_DSP: return "MipsISD::MSUB_DSP";
case MipsISD::MSUBU_DSP: return "MipsISD::MSUBU_DSP";
+ case MipsISD::SHLL_DSP: return "MipsISD::SHLL_DSP";
+ case MipsISD::SHRA_DSP: return "MipsISD::SHRA_DSP";
+ case MipsISD::SHRL_DSP: return "MipsISD::SHRL_DSP";
+ case MipsISD::SETCC_DSP: return "MipsISD::SETCC_DSP";
+ case MipsISD::SELECT_CC_DSP: return "MipsISD::SELECT_CC_DSP";
default: return NULL;
}
}
@@ -205,7 +215,7 @@ MipsTargetLowering(MipsTargetMachine &TM)
// Mips does not have i1 type, so use i32 for
// setcc operations results (slt, sgt, ...).
setBooleanContents(ZeroOrOneBooleanContent);
- setBooleanVectorContents(ZeroOrOneBooleanContent); // FIXME: Is this correct?
+ setBooleanVectorContents(ZeroOrNegativeOneBooleanContent);
// Load extented operations for i1 types must be promoted
setLoadExtAction(ISD::EXTLOAD, MVT::i1, Promote);
@@ -340,9 +350,6 @@ MipsTargetLowering(MipsTargetMachine &TM)
setOperationAction(ISD::VACOPY, MVT::Other, Expand);
setOperationAction(ISD::VAEND, MVT::Other, Expand);
- setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::i64, Custom);
- setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::i64, Custom);
-
// Use the default for now
setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
@@ -376,8 +383,6 @@ MipsTargetLowering(MipsTargetMachine &TM)
setTruncStoreAction(MVT::i64, MVT::i32, Custom);
}
- setTargetDAGCombine(ISD::ADDE);
- setTargetDAGCombine(ISD::SUBE);
setTargetDAGCombine(ISD::SDIVREM);
setTargetDAGCombine(ISD::UDIVREM);
setTargetDAGCombine(ISD::SELECT);
@@ -408,178 +413,6 @@ EVT MipsTargetLowering::getSetCCResultType(EVT VT) const {
return VT.changeVectorElementTypeToInteger();
}
-// selectMADD -
-// Transforms a subgraph in CurDAG if the following pattern is found:
-// (addc multLo, Lo0), (adde multHi, Hi0),
-// where,
-// multHi/Lo: product of multiplication
-// Lo0: initial value of Lo register
-// Hi0: initial value of Hi register
-// Return true if pattern matching was successful.
-static bool selectMADD(SDNode *ADDENode, SelectionDAG *CurDAG) {
- // ADDENode's second operand must be a flag output of an ADDC node in order
- // for the matching to be successful.
- SDNode *ADDCNode = ADDENode->getOperand(2).getNode();
-
- if (ADDCNode->getOpcode() != ISD::ADDC)
- return false;
-
- SDValue MultHi = ADDENode->getOperand(0);
- SDValue MultLo = ADDCNode->getOperand(0);
- SDNode *MultNode = MultHi.getNode();
- unsigned MultOpc = MultHi.getOpcode();
-
- // MultHi and MultLo must be generated by the same node,
- if (MultLo.getNode() != MultNode)
- return false;
-
- // and it must be a multiplication.
- if (MultOpc != ISD::SMUL_LOHI && MultOpc != ISD::UMUL_LOHI)
- return false;
-
- // MultLo amd MultHi must be the first and second output of MultNode
- // respectively.
- if (MultHi.getResNo() != 1 || MultLo.getResNo() != 0)
- return false;
-
- // Transform this to a MADD only if ADDENode and ADDCNode are the only users
- // of the values of MultNode, in which case MultNode will be removed in later
- // phases.
- // If there exist users other than ADDENode or ADDCNode, this function returns
- // here, which will result in MultNode being mapped to a single MULT
- // instruction node rather than a pair of MULT and MADD instructions being
- // produced.
- if (!MultHi.hasOneUse() || !MultLo.hasOneUse())
- return false;
-
- SDValue Chain = CurDAG->getEntryNode();
- DebugLoc DL = ADDENode->getDebugLoc();
-
- // create MipsMAdd(u) node
- MultOpc = MultOpc == ISD::UMUL_LOHI ? MipsISD::MAddu : MipsISD::MAdd;
-
- SDValue MAdd = CurDAG->getNode(MultOpc, DL, MVT::Glue,
- MultNode->getOperand(0),// Factor 0
- MultNode->getOperand(1),// Factor 1
- ADDCNode->getOperand(1),// Lo0
- ADDENode->getOperand(1));// Hi0
-
- // create CopyFromReg nodes
- SDValue CopyFromLo = CurDAG->getCopyFromReg(Chain, DL, Mips::LO, MVT::i32,
- MAdd);
- SDValue CopyFromHi = CurDAG->getCopyFromReg(CopyFromLo.getValue(1), DL,
- Mips::HI, MVT::i32,
- CopyFromLo.getValue(2));
-
- // replace uses of adde and addc here
- if (!SDValue(ADDCNode, 0).use_empty())
- CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDCNode, 0), CopyFromLo);
-
- if (!SDValue(ADDENode, 0).use_empty())
- CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDENode, 0), CopyFromHi);
-
- return true;
-}
-
-// selectMSUB -
-// Transforms a subgraph in CurDAG if the following pattern is found:
-// (addc Lo0, multLo), (sube Hi0, multHi),
-// where,
-// multHi/Lo: product of multiplication
-// Lo0: initial value of Lo register
-// Hi0: initial value of Hi register
-// Return true if pattern matching was successful.
-static bool selectMSUB(SDNode *SUBENode, SelectionDAG *CurDAG) {
- // SUBENode's second operand must be a flag output of an SUBC node in order
- // for the matching to be successful.
- SDNode *SUBCNode = SUBENode->getOperand(2).getNode();
-
- if (SUBCNode->getOpcode() != ISD::SUBC)
- return false;
-
- SDValue MultHi = SUBENode->getOperand(1);
- SDValue MultLo = SUBCNode->getOperand(1);
- SDNode *MultNode = MultHi.getNode();
- unsigned MultOpc = MultHi.getOpcode();
-
- // MultHi and MultLo must be generated by the same node,
- if (MultLo.getNode() != MultNode)
- return false;
-
- // and it must be a multiplication.
- if (MultOpc != ISD::SMUL_LOHI && MultOpc != ISD::UMUL_LOHI)
- return false;
-
- // MultLo amd MultHi must be the first and second output of MultNode
- // respectively.
- if (MultHi.getResNo() != 1 || MultLo.getResNo() != 0)
- return false;
-
- // Transform this to a MSUB only if SUBENode and SUBCNode are the only users
- // of the values of MultNode, in which case MultNode will be removed in later
- // phases.
- // If there exist users other than SUBENode or SUBCNode, this function returns
- // here, which will result in MultNode being mapped to a single MULT
- // instruction node rather than a pair of MULT and MSUB instructions being
- // produced.
- if (!MultHi.hasOneUse() || !MultLo.hasOneUse())
- return false;
-
- SDValue Chain = CurDAG->getEntryNode();
- DebugLoc DL = SUBENode->getDebugLoc();
-
- // create MipsSub(u) node
- MultOpc = MultOpc == ISD::UMUL_LOHI ? MipsISD::MSubu : MipsISD::MSub;
-
- SDValue MSub = CurDAG->getNode(MultOpc, DL, MVT::Glue,
- MultNode->getOperand(0),// Factor 0
- MultNode->getOperand(1),// Factor 1
- SUBCNode->getOperand(0),// Lo0
- SUBENode->getOperand(0));// Hi0
-
- // create CopyFromReg nodes
- SDValue CopyFromLo = CurDAG->getCopyFromReg(Chain, DL, Mips::LO, MVT::i32,
- MSub);
- SDValue CopyFromHi = CurDAG->getCopyFromReg(CopyFromLo.getValue(1), DL,
- Mips::HI, MVT::i32,
- CopyFromLo.getValue(2));
-
- // replace uses of sube and subc here
- if (!SDValue(SUBCNode, 0).use_empty())
- CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBCNode, 0), CopyFromLo);
-
- if (!SDValue(SUBENode, 0).use_empty())
- CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBENode, 0), CopyFromHi);
-
- return true;
-}
-
-static SDValue performADDECombine(SDNode *N, SelectionDAG &DAG,
- TargetLowering::DAGCombinerInfo &DCI,
- const MipsSubtarget *Subtarget) {
- if (DCI.isBeforeLegalize())
- return SDValue();
-
- if (Subtarget->hasMips32() && N->getValueType(0) == MVT::i32 &&
- selectMADD(N, &DAG))
- return SDValue(N, 0);
-
- return SDValue();
-}
-
-static SDValue performSUBECombine(SDNode *N, SelectionDAG &DAG,
- TargetLowering::DAGCombinerInfo &DCI,
- const MipsSubtarget *Subtarget) {
- if (DCI.isBeforeLegalize())
- return SDValue();
-
- if (Subtarget->hasMips32() && N->getValueType(0) == MVT::i32 &&
- selectMSUB(N, &DAG))
- return SDValue(N, 0);
-
- return SDValue();
-}
-
static SDValue performDivRemCombine(SDNode *N, SelectionDAG &DAG,
TargetLowering::DAGCombinerInfo &DCI,
const MipsSubtarget *Subtarget) {
@@ -589,8 +422,8 @@ static SDValue performDivRemCombine(SDNode *N, SelectionDAG &DAG,
EVT Ty = N->getValueType(0);
unsigned LO = (Ty == MVT::i32) ? Mips::LO : Mips::LO64;
unsigned HI = (Ty == MVT::i32) ? Mips::HI : Mips::HI64;
- unsigned Opc = N->getOpcode() == ISD::SDIVREM ? MipsISD::DivRem :
- MipsISD::DivRemU;
+ unsigned Opc = N->getOpcode() == ISD::SDIVREM ? MipsISD::DivRem16 :
+ MipsISD::DivRemU16;
DebugLoc DL = N->getDebugLoc();
SDValue DivRem = DAG.getNode(Opc, DL, MVT::Glue,
@@ -617,7 +450,7 @@ static SDValue performDivRemCombine(SDNode *N, SelectionDAG &DAG,
return SDValue();
}
-static Mips::CondCode FPCondCCodeToFCC(ISD::CondCode CC) {
+static Mips::CondCode condCodeToFCC(ISD::CondCode CC) {
switch (CC) {
default: llvm_unreachable("Unknown fp condition code!");
case ISD::SETEQ:
@@ -644,8 +477,9 @@ static Mips::CondCode FPCondCCodeToFCC(ISD::CondCode CC) {
}
-// Returns true if condition code has to be inverted.
-static bool invertFPCondCode(Mips::CondCode CC) {
+/// This function returns true if the floating point conditional branches and
+/// conditional moves which use condition code CC should be inverted.
+static bool invertFPCondCodeUser(Mips::CondCode CC) {
if (CC >= Mips::FCOND_F && CC <= Mips::FCOND_NGT)
return false;
@@ -675,15 +509,14 @@ static SDValue createFPCmp(SelectionDAG &DAG, const SDValue &Op) {
ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get();
return DAG.getNode(MipsISD::FPCmp, DL, MVT::Glue, LHS, RHS,
- DAG.getConstant(FPCondCCodeToFCC(CC), MVT::i32));
+ DAG.getConstant(condCodeToFCC(CC), MVT::i32));
}
// Creates and returns a CMovFPT/F node.
static SDValue createCMovFP(SelectionDAG &DAG, SDValue Cond, SDValue True,
SDValue False, DebugLoc DL) {
- bool invert = invertFPCondCode((Mips::CondCode)
- cast<ConstantSDNode>(Cond.getOperand(2))
- ->getSExtValue());
+ ConstantSDNode *CC = cast<ConstantSDNode>(Cond.getOperand(2));
+ bool invert = invertFPCondCodeUser((Mips::CondCode)CC->getSExtValue());
return DAG.getNode((invert ? MipsISD::CMovFP_F : MipsISD::CMovFP_T), DL,
True.getValueType(), True, False, Cond);
@@ -850,10 +683,6 @@ SDValue MipsTargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI)
switch (Opc) {
default: break;
- case ISD::ADDE:
- return performADDECombine(N, DAG, DCI, Subtarget);
- case ISD::SUBE:
- return performSUBECombine(N, DAG, DCI, Subtarget);
case ISD::SDIVREM:
case ISD::UDIVREM:
return performDivRemCombine(N, DAG, DCI, Subtarget);
@@ -884,10 +713,7 @@ void
MipsTargetLowering::ReplaceNodeResults(SDNode *N,
SmallVectorImpl<SDValue> &Results,
SelectionDAG &DAG) const {
- SDValue Res = LowerOperation(SDValue(N, 0), DAG);
-
- for (unsigned I = 0, E = Res->getNumValues(); I != E; ++I)
- Results.push_back(Res.getValue(I));
+ return LowerOperationWrapper(N, Results, DAG);
}
SDValue MipsTargetLowering::
@@ -895,32 +721,29 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) const
{
switch (Op.getOpcode())
{
- case ISD::BR_JT: return lowerBR_JT(Op, DAG);
- case ISD::BRCOND: return lowerBRCOND(Op, DAG);
- case ISD::ConstantPool: return lowerConstantPool(Op, DAG);
- case ISD::GlobalAddress: return lowerGlobalAddress(Op, DAG);
- case ISD::BlockAddress: return lowerBlockAddress(Op, DAG);
- case ISD::GlobalTLSAddress: return lowerGlobalTLSAddress(Op, DAG);
- case ISD::JumpTable: return lowerJumpTable(Op, DAG);
- case ISD::SELECT: return lowerSELECT(Op, DAG);
- case ISD::SELECT_CC: return lowerSELECT_CC(Op, DAG);
- 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);
- case ISD::MEMBARRIER: return lowerMEMBARRIER(Op, DAG);
- case ISD::ATOMIC_FENCE: return lowerATOMIC_FENCE(Op, DAG);
- case ISD::SHL_PARTS: return lowerShiftLeftParts(Op, DAG);
- case ISD::SRA_PARTS: return lowerShiftRightParts(Op, DAG, true);
- case ISD::SRL_PARTS: return lowerShiftRightParts(Op, DAG, false);
- case ISD::LOAD: return lowerLOAD(Op, DAG);
- case ISD::STORE: return lowerSTORE(Op, DAG);
- case ISD::INTRINSIC_WO_CHAIN: return lowerINTRINSIC_WO_CHAIN(Op, DAG);
- case ISD::INTRINSIC_W_CHAIN: return lowerINTRINSIC_W_CHAIN(Op, DAG);
- case ISD::ADD: return lowerADD(Op, DAG);
+ case ISD::BR_JT: return lowerBR_JT(Op, DAG);
+ case ISD::BRCOND: return lowerBRCOND(Op, DAG);
+ case ISD::ConstantPool: return lowerConstantPool(Op, DAG);
+ case ISD::GlobalAddress: return lowerGlobalAddress(Op, DAG);
+ case ISD::BlockAddress: return lowerBlockAddress(Op, DAG);
+ case ISD::GlobalTLSAddress: return lowerGlobalTLSAddress(Op, DAG);
+ case ISD::JumpTable: return lowerJumpTable(Op, DAG);
+ case ISD::SELECT: return lowerSELECT(Op, DAG);
+ case ISD::SELECT_CC: return lowerSELECT_CC(Op, DAG);
+ 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);
+ case ISD::ATOMIC_FENCE: return lowerATOMIC_FENCE(Op, DAG);
+ case ISD::SHL_PARTS: return lowerShiftLeftParts(Op, DAG);
+ case ISD::SRA_PARTS: return lowerShiftRightParts(Op, DAG, true);
+ case ISD::SRL_PARTS: return lowerShiftRightParts(Op, DAG, false);
+ case ISD::LOAD: return lowerLOAD(Op, DAG);
+ case ISD::STORE: return lowerSTORE(Op, DAG);
+ case ISD::ADD: return lowerADD(Op, DAG);
}
return SDValue();
}
@@ -940,17 +763,6 @@ addLiveIn(MachineFunction &MF, unsigned PReg, const TargetRegisterClass *RC)
return VReg;
}
-// Get fp branch code (not opcode) from condition code.
-static Mips::FPBranchCode getFPBranchCodeFromCond(Mips::CondCode CC) {
- if (CC >= Mips::FCOND_F && CC <= Mips::FCOND_NGT)
- return Mips::BRANCH_T;
-
- assert((CC >= Mips::FCOND_T && CC <= Mips::FCOND_GT) &&
- "Invalid CondCode.");
-
- return Mips::BRANCH_F;
-}
-
MachineBasicBlock *
MipsTargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
MachineBasicBlock *BB) const {
@@ -1581,8 +1393,8 @@ lowerBRCOND(SDValue Op, SelectionDAG &DAG) const
SDValue CCNode = CondRes.getOperand(2);
Mips::CondCode CC =
(Mips::CondCode)cast<ConstantSDNode>(CCNode)->getZExtValue();
- SDValue BrCode = DAG.getConstant(getFPBranchCodeFromCond(CC), MVT::i32);
-
+ unsigned Opc = invertFPCondCodeUser(CC) ? Mips::BRANCH_F : Mips::BRANCH_T;
+ SDValue BrCode = DAG.getConstant(Opc, MVT::i32);
return DAG.getNode(MipsISD::FPBrcond, DL, Op.getValueType(), Chain, BrCode,
Dest, CondRes);
}
@@ -2010,15 +1822,6 @@ SDValue MipsTargetLowering::lowerEH_RETURN(SDValue Op, SelectionDAG &DAG)
Chain.getValue(1));
}
-// TODO: set SType according to the desired memory barrier behavior.
-SDValue
-MipsTargetLowering::lowerMEMBARRIER(SDValue Op, SelectionDAG &DAG) const {
- unsigned SType = 0;
- DebugLoc DL = Op.getDebugLoc();
- return DAG.getNode(MipsISD::Sync, DL, MVT::Other, Op.getOperand(0),
- DAG.getConstant(SType, MVT::i32));
-}
-
SDValue MipsTargetLowering::lowerATOMIC_FENCE(SDValue Op,
SelectionDAG &DAG) const {
// FIXME: Need pseudo-fence for 'singlethread' fences
@@ -2101,7 +1904,7 @@ SDValue MipsTargetLowering::lowerShiftRightParts(SDValue Op, SelectionDAG &DAG,
return DAG.getMergeValues(Ops, 2, DL);
}
-static SDValue CreateLoadLR(unsigned Opc, SelectionDAG &DAG, LoadSDNode *LD,
+static SDValue createLoadLR(unsigned Opc, SelectionDAG &DAG, LoadSDNode *LD,
SDValue Chain, SDValue Src, unsigned Offset) {
SDValue Ptr = LD->getBasePtr();
EVT VT = LD->getValueType(0), MemVT = LD->getMemoryVT();
@@ -2141,15 +1944,15 @@ SDValue MipsTargetLowering::lowerLOAD(SDValue Op, SelectionDAG &DAG) const {
// (set tmp, (ldl (add baseptr, 7), undef))
// (set dst, (ldr baseptr, tmp))
if ((VT == MVT::i64) && (ExtType == ISD::NON_EXTLOAD)) {
- SDValue LDL = CreateLoadLR(MipsISD::LDL, DAG, LD, Chain, Undef,
+ SDValue LDL = createLoadLR(MipsISD::LDL, DAG, LD, Chain, Undef,
IsLittle ? 7 : 0);
- return CreateLoadLR(MipsISD::LDR, DAG, LD, LDL.getValue(1), LDL,
+ return createLoadLR(MipsISD::LDR, DAG, LD, LDL.getValue(1), LDL,
IsLittle ? 0 : 7);
}
- SDValue LWL = CreateLoadLR(MipsISD::LWL, DAG, LD, Chain, Undef,
+ SDValue LWL = createLoadLR(MipsISD::LWL, DAG, LD, Chain, Undef,
IsLittle ? 3 : 0);
- SDValue LWR = CreateLoadLR(MipsISD::LWR, DAG, LD, LWL.getValue(1), LWL,
+ SDValue LWR = createLoadLR(MipsISD::LWR, DAG, LD, LWL.getValue(1), LWL,
IsLittle ? 0 : 3);
// Expand
@@ -2180,7 +1983,7 @@ SDValue MipsTargetLowering::lowerLOAD(SDValue Op, SelectionDAG &DAG) const {
return DAG.getMergeValues(Ops, 2, DL);
}
-static SDValue CreateStoreLR(unsigned Opc, SelectionDAG &DAG, StoreSDNode *SD,
+static SDValue createStoreLR(unsigned Opc, SelectionDAG &DAG, StoreSDNode *SD,
SDValue Chain, unsigned Offset) {
SDValue Ptr = SD->getBasePtr(), Value = SD->getValue();
EVT MemVT = SD->getMemoryVT(), BasePtrVT = Ptr.getValueType();
@@ -2217,9 +2020,9 @@ SDValue MipsTargetLowering::lowerSTORE(SDValue Op, SelectionDAG &DAG) const {
// (swl val, (add baseptr, 3))
// (swr val, baseptr)
if ((VT == MVT::i32) || SD->isTruncatingStore()) {
- SDValue SWL = CreateStoreLR(MipsISD::SWL, DAG, SD, Chain,
+ SDValue SWL = createStoreLR(MipsISD::SWL, DAG, SD, Chain,
IsLittle ? 3 : 0);
- return CreateStoreLR(MipsISD::SWR, DAG, SD, SWL, IsLittle ? 0 : 3);
+ return createStoreLR(MipsISD::SWR, DAG, SD, SWL, IsLittle ? 0 : 3);
}
assert(VT == MVT::i64);
@@ -2229,153 +2032,8 @@ SDValue MipsTargetLowering::lowerSTORE(SDValue Op, SelectionDAG &DAG) const {
// to
// (sdl val, (add baseptr, 7))
// (sdr val, baseptr)
- SDValue SDL = CreateStoreLR(MipsISD::SDL, DAG, SD, Chain, IsLittle ? 7 : 0);
- return CreateStoreLR(MipsISD::SDR, DAG, SD, SDL, IsLittle ? 0 : 7);
-}
-
-// This function expands mips intrinsic nodes which have 64-bit input operands
-// or output values.
-//
-// out64 = intrinsic-node in64
-// =>
-// lo = copy (extract-element (in64, 0))
-// hi = copy (extract-element (in64, 1))
-// mips-specific-node
-// v0 = copy lo
-// v1 = copy hi
-// out64 = merge-values (v0, v1)
-//
-static SDValue lowerDSPIntr(SDValue Op, SelectionDAG &DAG,
- unsigned Opc, bool HasI64In, bool HasI64Out) {
- DebugLoc DL = Op.getDebugLoc();
- bool HasChainIn = Op->getOperand(0).getValueType() == MVT::Other;
- SDValue Chain = HasChainIn ? Op->getOperand(0) : DAG.getEntryNode();
- SmallVector<SDValue, 3> Ops;
-
- if (HasI64In) {
- SDValue InLo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32,
- Op->getOperand(1 + HasChainIn),
- DAG.getConstant(0, MVT::i32));
- SDValue InHi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32,
- Op->getOperand(1 + HasChainIn),
- DAG.getConstant(1, MVT::i32));
-
- Chain = DAG.getCopyToReg(Chain, DL, Mips::LO, InLo, SDValue());
- Chain = DAG.getCopyToReg(Chain, DL, Mips::HI, InHi, Chain.getValue(1));
-
- Ops.push_back(Chain);
- Ops.append(Op->op_begin() + HasChainIn + 2, Op->op_end());
- Ops.push_back(Chain.getValue(1));
- } else {
- Ops.push_back(Chain);
- Ops.append(Op->op_begin() + HasChainIn + 1, Op->op_end());
- }
-
- if (!HasI64Out)
- return DAG.getNode(Opc, DL, Op->value_begin(), Op->getNumValues(),
- Ops.begin(), Ops.size());
-
- SDValue Intr = DAG.getNode(Opc, DL, DAG.getVTList(MVT::Other, MVT::Glue),
- Ops.begin(), Ops.size());
- SDValue OutLo = DAG.getCopyFromReg(Intr.getValue(0), DL, Mips::LO, MVT::i32,
- Intr.getValue(1));
- SDValue OutHi = DAG.getCopyFromReg(OutLo.getValue(1), DL, Mips::HI, MVT::i32,
- OutLo.getValue(2));
- SDValue Out = DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, OutLo, OutHi);
-
- if (!HasChainIn)
- return Out;
-
- SDValue Vals[] = { Out, OutHi.getValue(1) };
- return DAG.getMergeValues(Vals, 2, DL);
-}
-
-SDValue MipsTargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op,
- SelectionDAG &DAG) const {
- switch (cast<ConstantSDNode>(Op->getOperand(0))->getZExtValue()) {
- default:
- return SDValue();
- case Intrinsic::mips_shilo:
- return lowerDSPIntr(Op, DAG, MipsISD::SHILO, true, true);
- case Intrinsic::mips_dpau_h_qbl:
- return lowerDSPIntr(Op, DAG, MipsISD::DPAU_H_QBL, true, true);
- case Intrinsic::mips_dpau_h_qbr:
- return lowerDSPIntr(Op, DAG, MipsISD::DPAU_H_QBR, true, true);
- case Intrinsic::mips_dpsu_h_qbl:
- return lowerDSPIntr(Op, DAG, MipsISD::DPSU_H_QBL, true, true);
- case Intrinsic::mips_dpsu_h_qbr:
- return lowerDSPIntr(Op, DAG, MipsISD::DPSU_H_QBR, true, true);
- case Intrinsic::mips_dpa_w_ph:
- return lowerDSPIntr(Op, DAG, MipsISD::DPA_W_PH, true, true);
- case Intrinsic::mips_dps_w_ph:
- return lowerDSPIntr(Op, DAG, MipsISD::DPS_W_PH, true, true);
- case Intrinsic::mips_dpax_w_ph:
- return lowerDSPIntr(Op, DAG, MipsISD::DPAX_W_PH, true, true);
- case Intrinsic::mips_dpsx_w_ph:
- return lowerDSPIntr(Op, DAG, MipsISD::DPSX_W_PH, true, true);
- case Intrinsic::mips_mulsa_w_ph:
- return lowerDSPIntr(Op, DAG, MipsISD::MULSA_W_PH, true, true);
- case Intrinsic::mips_mult:
- return lowerDSPIntr(Op, DAG, MipsISD::MULT, false, true);
- case Intrinsic::mips_multu:
- return lowerDSPIntr(Op, DAG, MipsISD::MULTU, false, true);
- case Intrinsic::mips_madd:
- return lowerDSPIntr(Op, DAG, MipsISD::MADD_DSP, true, true);
- case Intrinsic::mips_maddu:
- return lowerDSPIntr(Op, DAG, MipsISD::MADDU_DSP, true, true);
- case Intrinsic::mips_msub:
- return lowerDSPIntr(Op, DAG, MipsISD::MSUB_DSP, true, true);
- case Intrinsic::mips_msubu:
- return lowerDSPIntr(Op, DAG, MipsISD::MSUBU_DSP, true, true);
- }
-}
-
-SDValue MipsTargetLowering::lowerINTRINSIC_W_CHAIN(SDValue Op,
- SelectionDAG &DAG) const {
- switch (cast<ConstantSDNode>(Op->getOperand(1))->getZExtValue()) {
- default:
- return SDValue();
- case Intrinsic::mips_extp:
- return lowerDSPIntr(Op, DAG, MipsISD::EXTP, true, false);
- case Intrinsic::mips_extpdp:
- return lowerDSPIntr(Op, DAG, MipsISD::EXTPDP, true, false);
- case Intrinsic::mips_extr_w:
- return lowerDSPIntr(Op, DAG, MipsISD::EXTR_W, true, false);
- case Intrinsic::mips_extr_r_w:
- return lowerDSPIntr(Op, DAG, MipsISD::EXTR_R_W, true, false);
- case Intrinsic::mips_extr_rs_w:
- return lowerDSPIntr(Op, DAG, MipsISD::EXTR_RS_W, true, false);
- case Intrinsic::mips_extr_s_h:
- return lowerDSPIntr(Op, DAG, MipsISD::EXTR_S_H, true, false);
- case Intrinsic::mips_mthlip:
- return lowerDSPIntr(Op, DAG, MipsISD::MTHLIP, true, true);
- case Intrinsic::mips_mulsaq_s_w_ph:
- return lowerDSPIntr(Op, DAG, MipsISD::MULSAQ_S_W_PH, true, true);
- case Intrinsic::mips_maq_s_w_phl:
- return lowerDSPIntr(Op, DAG, MipsISD::MAQ_S_W_PHL, true, true);
- case Intrinsic::mips_maq_s_w_phr:
- return lowerDSPIntr(Op, DAG, MipsISD::MAQ_S_W_PHR, true, true);
- case Intrinsic::mips_maq_sa_w_phl:
- return lowerDSPIntr(Op, DAG, MipsISD::MAQ_SA_W_PHL, true, true);
- case Intrinsic::mips_maq_sa_w_phr:
- return lowerDSPIntr(Op, DAG, MipsISD::MAQ_SA_W_PHR, true, true);
- case Intrinsic::mips_dpaq_s_w_ph:
- return lowerDSPIntr(Op, DAG, MipsISD::DPAQ_S_W_PH, true, true);
- case Intrinsic::mips_dpsq_s_w_ph:
- return lowerDSPIntr(Op, DAG, MipsISD::DPSQ_S_W_PH, true, true);
- case Intrinsic::mips_dpaq_sa_l_w:
- return lowerDSPIntr(Op, DAG, MipsISD::DPAQ_SA_L_W, true, true);
- case Intrinsic::mips_dpsq_sa_l_w:
- return lowerDSPIntr(Op, DAG, MipsISD::DPSQ_SA_L_W, true, true);
- case Intrinsic::mips_dpaqx_s_w_ph:
- return lowerDSPIntr(Op, DAG, MipsISD::DPAQX_S_W_PH, true, true);
- case Intrinsic::mips_dpaqx_sa_w_ph:
- return lowerDSPIntr(Op, DAG, MipsISD::DPAQX_SA_W_PH, true, true);
- case Intrinsic::mips_dpsqx_s_w_ph:
- return lowerDSPIntr(Op, DAG, MipsISD::DPSQX_S_W_PH, true, true);
- case Intrinsic::mips_dpsqx_sa_w_ph:
- return lowerDSPIntr(Op, DAG, MipsISD::DPSQX_SA_W_PH, true, true);
- }
+ SDValue SDL = createStoreLR(MipsISD::SDL, DAG, SD, Chain, IsLittle ? 7 : 0);
+ return createStoreLR(MipsISD::SDR, DAG, SD, SDL, IsLittle ? 0 : 7);
}
SDValue MipsTargetLowering::lowerADD(SDValue Op, SelectionDAG &DAG) const {
@@ -3173,8 +2831,8 @@ getRegForInlineAsmConstraint(const std::string &Constraint, EVT VT) const
return std::make_pair((unsigned)Mips::T9_64, &Mips::CPU64RegsRegClass);
case 'l': // register suitable for indirect jump
if (VT == MVT::i32)
- return std::make_pair((unsigned)Mips::LO, &Mips::HILORegClass);
- return std::make_pair((unsigned)Mips::LO64, &Mips::HILO64RegClass);
+ return std::make_pair((unsigned)Mips::LO, &Mips::LORegsRegClass);
+ return std::make_pair((unsigned)Mips::LO64, &Mips::LORegs64RegClass);
case 'x': // register suitable for indirect jump
// Fixme: Not triggering the use of both hi and low
// This will generate an error message
diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h
index 71977d7..5587e8f 100644
--- a/lib/Target/Mips/MipsISelLowering.h
+++ b/lib/Target/Mips/MipsISelLowering.h
@@ -68,6 +68,16 @@ namespace llvm {
EH_RETURN,
+ // Node used to extract integer from accumulator.
+ ExtractLOHI,
+
+ // Node used to insert integers to accumulator.
+ InsertLOHI,
+
+ // Mult nodes.
+ Mult,
+ Multu,
+
// MAdd/Sub nodes
MAdd,
MAddu,
@@ -77,6 +87,8 @@ namespace llvm {
// DivRem(u)
DivRem,
DivRemU,
+ DivRem16,
+ DivRemU16,
BuildPairF64,
ExtractElementF64,
@@ -131,6 +143,15 @@ namespace llvm {
MSUB_DSP,
MSUBU_DSP,
+ // DSP shift nodes.
+ SHLL_DSP,
+ SHRA_DSP,
+ SHRL_DSP,
+
+ // DSP setcc and select_cc nodes.
+ SETCC_DSP,
+ SELECT_CC_DSP,
+
// Load/Store Left/Right nodes.
LWL = ISD::FIRST_TARGET_MEMORY_OPCODE,
LWR,
@@ -326,15 +347,12 @@ namespace llvm {
SDValue lowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerRETURNADDR(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const;
- SDValue lowerMEMBARRIER(SDValue Op, SelectionDAG& DAG) const;
SDValue lowerATOMIC_FENCE(SDValue Op, SelectionDAG& DAG) const;
SDValue lowerShiftLeftParts(SDValue Op, SelectionDAG& DAG) const;
SDValue lowerShiftRightParts(SDValue Op, SelectionDAG& DAG,
bool IsSRA) const;
SDValue lowerLOAD(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerSTORE(SDValue Op, SelectionDAG &DAG) const;
- SDValue lowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const;
- SDValue lowerINTRINSIC_W_CHAIN(SDValue Op, SelectionDAG &DAG) const;
SDValue lowerADD(SDValue Op, SelectionDAG &DAG) const;
/// isEligibleForTailCallOptimization - Check whether the call is eligible
diff --git a/lib/Target/Mips/MipsInstrFPU.td b/lib/Target/Mips/MipsInstrFPU.td
index 891bdc1..6b23057 100644
--- a/lib/Target/Mips/MipsInstrFPU.td
+++ b/lib/Target/Mips/MipsInstrFPU.td
@@ -503,32 +503,27 @@ let Predicates = [IsFP64bit, HasStdEnc] in {
def : MipsPat<(f64 (fextend FGR32:$src)), (CVT_D64_S FGR32:$src)>;
}
-// Load/Store patterns.
+// Patterns for loads/stores with a reg+imm operand.
let AddedComplexity = 40 in {
let Predicates = [IsN64, HasStdEnc] in {
- def : MipsPat<(f32 (load addrRegImm:$a)), (LWC1_P8 addrRegImm:$a)>;
- def : MipsPat<(store FGR32:$v, addrRegImm:$a),
- (SWC1_P8 FGR32:$v, addrRegImm:$a)>;
- def : MipsPat<(f64 (load addrRegImm:$a)), (LDC164_P8 addrRegImm:$a)>;
- def : MipsPat<(store FGR64:$v, addrRegImm:$a),
- (SDC164_P8 FGR64:$v, addrRegImm:$a)>;
+ def : LoadRegImmPat<LWC1_P8, f32, load>;
+ def : StoreRegImmPat<SWC1_P8, f32>;
+ def : LoadRegImmPat<LDC164_P8, f64, load>;
+ def : StoreRegImmPat<SDC164_P8, f64>;
}
let Predicates = [NotN64, HasStdEnc] in {
- def : MipsPat<(f32 (load addrRegImm:$a)), (LWC1 addrRegImm:$a)>;
- def : MipsPat<(store FGR32:$v, addrRegImm:$a),
- (SWC1 FGR32:$v, addrRegImm:$a)>;
+ def : LoadRegImmPat<LWC1, f32, load>;
+ def : StoreRegImmPat<SWC1, f32>;
}
let Predicates = [NotN64, HasMips64, HasStdEnc] in {
- def : MipsPat<(f64 (load addrRegImm:$a)), (LDC164 addrRegImm:$a)>;
- def : MipsPat<(store FGR64:$v, addrRegImm:$a),
- (SDC164 FGR64:$v, addrRegImm:$a)>;
+ def : LoadRegImmPat<LDC164, f64, load>;
+ def : StoreRegImmPat<SDC164, f64>;
}
let Predicates = [NotN64, NotMips64, HasStdEnc] in {
- def : MipsPat<(f64 (load addrRegImm:$a)), (LDC1 addrRegImm:$a)>;
- def : MipsPat<(store AFGR64:$v, addrRegImm:$a),
- (SDC1 AFGR64:$v, addrRegImm:$a)>;
+ def : LoadRegImmPat<LDC1, f64, load>;
+ def : StoreRegImmPat<SDC1, f64>;
}
}
diff --git a/lib/Target/Mips/MipsInstrFormats.td b/lib/Target/Mips/MipsInstrFormats.td
index ee432c8..ea07372 100644
--- a/lib/Target/Mips/MipsInstrFormats.td
+++ b/lib/Target/Mips/MipsInstrFormats.td
@@ -36,6 +36,24 @@ def FrmFR : Format<4>;
def FrmFI : Format<5>;
def FrmOther : Format<6>; // Instruction w/ a custom format
+class MMRel;
+
+def Std2MicroMips : InstrMapping {
+ let FilterClass = "MMRel";
+ // Instructions with the same BaseOpcode and isNVStore values form a row.
+ let RowFields = ["BaseOpcode"];
+ // Instructions with the same predicate sense form a column.
+ let ColFields = ["Arch"];
+ // The key column is the unpredicated instructions.
+ let KeyCol = ["se"];
+ // Value columns are PredSense=true and PredSense=false
+ let ValueCols = [["se"], ["micromips"]];
+}
+
+class StdArch {
+ string Arch = "se";
+}
+
// Generic Mips Format
class MipsInst<dag outs, dag ins, string asmstr, list<dag> pattern,
InstrItinClass itin, Format f>: Instruction
@@ -74,9 +92,11 @@ 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>:
+ InstrItinClass itin, Format f, string opstr = ""> :
MipsInst<outs, ins, asmstr, pattern, itin, f> {
let Predicates = [HasStdEnc];
+ string BaseOpcode = opstr;
+ string Arch;
}
// Mips Pseudo Instructions Format
@@ -192,7 +212,7 @@ class MFC3OP_FM<bits<6> op, bits<5> mfmt>
let Inst{2-0} = sel;
}
-class ADD_FM<bits<6> op, bits<6> funct> {
+class ADD_FM<bits<6> op, bits<6> funct> : StdArch {
bits<5> rd;
bits<5> rs;
bits<5> rt;
@@ -207,7 +227,7 @@ class ADD_FM<bits<6> op, bits<6> funct> {
let Inst{5-0} = funct;
}
-class ADDI_FM<bits<6> op> {
+class ADDI_FM<bits<6> op> : StdArch {
bits<5> rs;
bits<5> rt;
bits<16> imm16;
@@ -220,7 +240,7 @@ class ADDI_FM<bits<6> op> {
let Inst{15-0} = imm16;
}
-class SRA_FM<bits<6> funct, bit rotate> {
+class SRA_FM<bits<6> funct, bit rotate> : StdArch {
bits<5> rd;
bits<5> rt;
bits<5> shamt;
@@ -236,7 +256,7 @@ class SRA_FM<bits<6> funct, bit rotate> {
let Inst{5-0} = funct;
}
-class SRLV_FM<bits<6> funct, bit rotate> {
+class SRLV_FM<bits<6> funct, bit rotate> : StdArch {
bits<5> rd;
bits<5> rt;
bits<5> rs;
@@ -288,7 +308,7 @@ class B_FM {
let Inst{15-0} = offset;
}
-class SLTI_FM<bits<6> op> {
+class SLTI_FM<bits<6> op> : StdArch {
bits<5> rt;
bits<5> rs;
bits<16> imm16;
@@ -413,7 +433,7 @@ class SYNC_FM {
let Inst{5-0} = 0xf;
}
-class MULT_FM<bits<6> op, bits<6> funct> {
+class MULT_FM<bits<6> op, bits<6> funct> : StdArch {
bits<5> rs;
bits<5> rt;
@@ -529,7 +549,7 @@ class MFC1_FM<bits<5> funct> {
let Inst{10-0} = 0;
}
-class LW_FM<bits<6> op> {
+class LW_FM<bits<6> op> : StdArch {
bits<5> rt;
bits<21> addr;
diff --git a/lib/Target/Mips/MipsInstrInfo.h b/lib/Target/Mips/MipsInstrInfo.h
index 3cd9088..8c05d97 100644
--- a/lib/Target/Mips/MipsInstrInfo.h
+++ b/lib/Target/Mips/MipsInstrInfo.h
@@ -86,6 +86,36 @@ 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 {
+ 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 {
+ loadRegFromStack(MBB, MBBI, DestReg, FrameIndex, RC, TRI, 0);
+ }
+
+ virtual void storeRegToStack(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI,
+ unsigned SrcReg, bool isKill, int FrameIndex,
+ const TargetRegisterClass *RC,
+ const TargetRegisterInfo *TRI,
+ int64_t Offset) const = 0;
+
+ virtual void loadRegFromStack(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI,
+ unsigned DestReg, int FrameIndex,
+ const TargetRegisterClass *RC,
+ const TargetRegisterInfo *TRI,
+ int64_t Offset) const = 0;
+
protected:
bool isZeroImm(const MachineOperand &op) const;
diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td
index 25b5d24..86ec729 100644
--- a/lib/Target/Mips/MipsInstrInfo.td
+++ b/lib/Target/Mips/MipsInstrInfo.td
@@ -23,13 +23,16 @@ def SDT_MipsCMov : SDTypeProfile<1, 4, [SDTCisSameAs<0, 1>,
SDTCisInt<4>]>;
def SDT_MipsCallSeqStart : SDCallSeqStart<[SDTCisVT<0, i32>]>;
def SDT_MipsCallSeqEnd : SDCallSeqEnd<[SDTCisVT<0, i32>, SDTCisVT<1, i32>]>;
-def SDT_MipsMAddMSub : SDTypeProfile<0, 4,
- [SDTCisVT<0, i32>, SDTCisSameAs<0, 1>,
- SDTCisSameAs<1, 2>,
- SDTCisSameAs<2, 3>]>;
-def SDT_MipsDivRem : SDTypeProfile<0, 2,
- [SDTCisInt<0>,
- SDTCisSameAs<0, 1>]>;
+def SDT_ExtractLOHI : SDTypeProfile<1, 2, [SDTCisInt<0>, SDTCisVT<1, untyped>,
+ SDTCisVT<2, i32>]>;
+def SDT_InsertLOHI : SDTypeProfile<1, 2, [SDTCisVT<0, untyped>,
+ SDTCisVT<1, i32>, SDTCisSameAs<1, 2>]>;
+def SDT_MipsMultDiv : SDTypeProfile<1, 2, [SDTCisVT<0, untyped>, SDTCisInt<1>,
+ SDTCisSameAs<1, 2>]>;
+def SDT_MipsMAddMSub : SDTypeProfile<1, 3,
+ [SDTCisVT<0, untyped>, SDTCisSameAs<0, 3>,
+ SDTCisVT<1, i32>, SDTCisSameAs<1, 2>]>;
+def SDT_MipsDivRem16 : SDTypeProfile<0, 2, [SDTCisInt<0>, SDTCisSameAs<0, 1>]>;
def SDT_MipsThreadPointer : SDTypeProfile<1, 0, [SDTCisPtrTy<0>]>;
@@ -82,20 +85,27 @@ def callseq_end : SDNode<"ISD::CALLSEQ_END", SDT_MipsCallSeqEnd,
[SDNPHasChain, SDNPSideEffect,
SDNPOptInGlue, SDNPOutGlue]>;
+// Node used to extract integer from LO/HI register.
+def ExtractLOHI : SDNode<"MipsISD::ExtractLOHI", SDT_ExtractLOHI>;
+
+// Node used to insert 32-bit integers to LOHI register pair.
+def InsertLOHI : SDNode<"MipsISD::InsertLOHI", SDT_InsertLOHI>;
+
+// Mult nodes.
+def MipsMult : SDNode<"MipsISD::Mult", SDT_MipsMultDiv>;
+def MipsMultu : SDNode<"MipsISD::Multu", SDT_MipsMultDiv>;
+
// MAdd*/MSub* nodes
-def MipsMAdd : SDNode<"MipsISD::MAdd", SDT_MipsMAddMSub,
- [SDNPOptInGlue, SDNPOutGlue]>;
-def MipsMAddu : SDNode<"MipsISD::MAddu", SDT_MipsMAddMSub,
- [SDNPOptInGlue, SDNPOutGlue]>;
-def MipsMSub : SDNode<"MipsISD::MSub", SDT_MipsMAddMSub,
- [SDNPOptInGlue, SDNPOutGlue]>;
-def MipsMSubu : SDNode<"MipsISD::MSubu", SDT_MipsMAddMSub,
- [SDNPOptInGlue, SDNPOutGlue]>;
+def MipsMAdd : SDNode<"MipsISD::MAdd", SDT_MipsMAddMSub>;
+def MipsMAddu : SDNode<"MipsISD::MAddu", SDT_MipsMAddMSub>;
+def MipsMSub : SDNode<"MipsISD::MSub", SDT_MipsMAddMSub>;
+def MipsMSubu : SDNode<"MipsISD::MSubu", SDT_MipsMAddMSub>;
// DivRem(u) nodes
-def MipsDivRem : SDNode<"MipsISD::DivRem", SDT_MipsDivRem,
- [SDNPOutGlue]>;
-def MipsDivRemU : SDNode<"MipsISD::DivRemU", SDT_MipsDivRem,
+def MipsDivRem : SDNode<"MipsISD::DivRem", SDT_MipsMultDiv>;
+def MipsDivRemU : SDNode<"MipsISD::DivRemU", SDT_MipsMultDiv>;
+def MipsDivRem16 : SDNode<"MipsISD::DivRem16", SDT_MipsDivRem16, [SDNPOutGlue]>;
+def MipsDivRemU16 : SDNode<"MipsISD::DivRemU16", SDT_MipsDivRem16,
[SDNPOutGlue]>;
// Target constant nodes that are not part of any isel patterns and remain
@@ -169,6 +179,7 @@ def NoNaNsFPMath : Predicate<"TM.Options.NoNaNsFPMath">,
AssemblerPredicate<"FeatureMips32">;
def HasStdEnc : Predicate<"Subtarget.hasStandardEncoding()">,
AssemblerPredicate<"!FeatureMips16">;
+def NotDSP : Predicate<"!Subtarget.hasDSP()">;
class MipsPat<dag pattern, dag result> : Pat<pattern, result> {
let Predicates = [HasStdEnc];
@@ -256,6 +267,7 @@ def mem : Operand<i32> {
let MIOperandInfo = (ops CPURegs, simm16);
let EncoderMethod = "getMemEncoding";
let ParserMatchClass = MipsMemAsmOperand;
+ let OperandType = "OPERAND_MEMORY";
}
def mem64 : Operand<i64> {
@@ -263,18 +275,21 @@ def mem64 : Operand<i64> {
let MIOperandInfo = (ops CPU64Regs, simm16_64);
let EncoderMethod = "getMemEncoding";
let ParserMatchClass = MipsMemAsmOperand;
+ let OperandType = "OPERAND_MEMORY";
}
def mem_ea : Operand<i32> {
let PrintMethod = "printMemOperandEA";
let MIOperandInfo = (ops CPURegs, simm16);
let EncoderMethod = "getMemEncoding";
+ let OperandType = "OPERAND_MEMORY";
}
def mem_ea_64 : Operand<i64> {
let PrintMethod = "printMemOperandEA";
let MIOperandInfo = (ops CPU64Regs, simm16_64);
let EncoderMethod = "getMemEncoding";
+ let OperandType = "OPERAND_MEMORY";
}
// size operand of ext instruction
@@ -360,11 +375,9 @@ class ArithLogicR<string opstr, RegisterOperand RO, bit isComm = 0,
SDPatternOperator OpNode = null_frag>:
InstSE<(outs RO:$rd), (ins RO:$rs, RO:$rt),
!strconcat(opstr, "\t$rd, $rs, $rt"),
- [(set RO:$rd, (OpNode RO:$rs, RO:$rt))], Itin, FrmR> {
+ [(set RO:$rd, (OpNode RO:$rs, RO:$rt))], Itin, FrmR, opstr> {
let isCommutable = isComm;
let isReMaterializable = 1;
- string BaseOpcode;
- string Arch;
}
// Arithmetic and logical instructions with 2 register operands.
@@ -373,15 +386,15 @@ class ArithLogicI<string opstr, Operand Od, RegisterOperand RO,
SDPatternOperator OpNode = null_frag> :
InstSE<(outs RO:$rt), (ins RO:$rs, Od:$imm16),
!strconcat(opstr, "\t$rt, $rs, $imm16"),
- [(set RO:$rt, (OpNode RO:$rs, imm_type:$imm16))], IIAlu, FrmI> {
+ [(set RO:$rt, (OpNode RO:$rs, imm_type:$imm16))],
+ IIAlu, FrmI, opstr> {
let isReMaterializable = 1;
}
// Arithmetic Multiply ADD/SUB
-class MArithR<string opstr, SDPatternOperator op = null_frag, bit isComm = 0> :
+class MArithR<string opstr, bit isComm = 0> :
InstSE<(outs), (ins CPURegsOpnd:$rs, CPURegsOpnd:$rt),
- !strconcat(opstr, "\t$rs, $rt"),
- [(op CPURegsOpnd:$rs, CPURegsOpnd:$rt, LO, HI)], IIImul, FrmR> {
+ !strconcat(opstr, "\t$rs, $rt"), [], IIImul, FrmR> {
let Defs = [HI, LO];
let Uses = [HI, LO];
let isCommutable = isComm;
@@ -391,7 +404,7 @@ class MArithR<string opstr, SDPatternOperator op = null_frag, bit isComm = 0> :
class LogicNOR<string opstr, RegisterOperand RC>:
InstSE<(outs RC:$rd), (ins RC:$rs, RC:$rt),
!strconcat(opstr, "\t$rd, $rs, $rt"),
- [(set RC:$rd, (not (or RC:$rs, RC:$rt)))], IIAlu, FrmR> {
+ [(set RC:$rd, (not (or RC:$rs, RC:$rt)))], IIAlu, FrmR, opstr> {
let isCommutable = 1;
}
@@ -401,13 +414,13 @@ class shift_rotate_imm<string opstr, Operand ImmOpnd,
SDPatternOperator PF = null_frag> :
InstSE<(outs RC:$rd), (ins RC:$rt, ImmOpnd:$shamt),
!strconcat(opstr, "\t$rd, $rt, $shamt"),
- [(set RC:$rd, (OpNode RC:$rt, PF:$shamt))], IIAlu, FrmR>;
+ [(set RC:$rd, (OpNode RC:$rt, PF:$shamt))], IIAlu, FrmR, opstr>;
class shift_rotate_reg<string opstr, RegisterOperand RC,
SDPatternOperator OpNode = null_frag>:
InstSE<(outs RC:$rd), (ins CPURegsOpnd:$rs, RC:$rt),
!strconcat(opstr, "\t$rd, $rt, $rs"),
- [(set RC:$rd, (OpNode RC:$rt, CPURegsOpnd:$rs))], IIAlu, FrmR>;
+ [(set RC:$rd, (OpNode RC:$rt, CPURegsOpnd:$rs))], IIAlu, FrmR, opstr>;
// Load Upper Imediate
class LoadUpper<string opstr, RegisterClass RC, Operand Imm>:
@@ -427,33 +440,43 @@ class FMem<bits<6> op, dag outs, dag ins, string asmstr, list<dag> pattern,
// Memory Load/Store
class Load<string opstr, SDPatternOperator OpNode, RegisterClass RC,
- Operand MemOpnd> :
+ Operand MemOpnd, ComplexPattern Addr, string ofsuffix> :
InstSE<(outs RC:$rt), (ins MemOpnd:$addr), !strconcat(opstr, "\t$rt, $addr"),
- [(set RC:$rt, (OpNode addr:$addr))], NoItinerary, FrmI> {
+ [(set RC:$rt, (OpNode Addr:$addr))], NoItinerary, FrmI,
+ !strconcat(opstr, ofsuffix)> {
let DecoderMethod = "DecodeMem";
let canFoldAsLoad = 1;
+ let mayLoad = 1;
}
class Store<string opstr, SDPatternOperator OpNode, RegisterClass RC,
- Operand MemOpnd> :
+ Operand MemOpnd, ComplexPattern Addr, string ofsuffix> :
InstSE<(outs), (ins RC:$rt, MemOpnd:$addr), !strconcat(opstr, "\t$rt, $addr"),
- [(OpNode RC:$rt, addr:$addr)], NoItinerary, FrmI> {
+ [(OpNode RC:$rt, Addr:$addr)], NoItinerary, FrmI,
+ !strconcat(opstr, ofsuffix)> {
let DecoderMethod = "DecodeMem";
+ let mayStore = 1;
}
multiclass LoadM<string opstr, RegisterClass RC,
- SDPatternOperator OpNode = null_frag> {
- def NAME : Load<opstr, OpNode, RC, mem>, Requires<[NotN64, HasStdEnc]>;
- def _P8 : Load<opstr, OpNode, RC, mem64>, Requires<[IsN64, HasStdEnc]> {
+ SDPatternOperator OpNode = null_frag,
+ ComplexPattern Addr = addr> {
+ def NAME : Load<opstr, OpNode, RC, mem, Addr, "">,
+ Requires<[NotN64, HasStdEnc]>;
+ def _P8 : Load<opstr, OpNode, RC, mem64, Addr, "_p8">,
+ Requires<[IsN64, HasStdEnc]> {
let DecoderNamespace = "Mips64";
let isCodeGenOnly = 1;
}
}
multiclass StoreM<string opstr, RegisterClass RC,
- SDPatternOperator OpNode = null_frag> {
- def NAME : Store<opstr, OpNode, RC, mem>, Requires<[NotN64, HasStdEnc]>;
- def _P8 : Store<opstr, OpNode, RC, mem64>, Requires<[IsN64, HasStdEnc]> {
+ SDPatternOperator OpNode = null_frag,
+ ComplexPattern Addr = addr> {
+ def NAME : Store<opstr, OpNode, RC, mem, Addr, "">,
+ Requires<[NotN64, HasStdEnc]>;
+ def _P8 : Store<opstr, OpNode, RC, mem64, Addr, "_p8">,
+ Requires<[IsN64, HasStdEnc]> {
let DecoderNamespace = "Mips64";
let isCodeGenOnly = 1;
}
@@ -523,14 +546,15 @@ class CBranchZero<string opstr, PatFrag cond_op, RegisterClass RC> :
class SetCC_R<string opstr, PatFrag cond_op, RegisterClass RC> :
InstSE<(outs CPURegsOpnd:$rd), (ins RC:$rs, RC:$rt),
!strconcat(opstr, "\t$rd, $rs, $rt"),
- [(set CPURegsOpnd:$rd, (cond_op RC:$rs, RC:$rt))], IIAlu, FrmR>;
+ [(set CPURegsOpnd:$rd, (cond_op RC:$rs, RC:$rt))],
+ IIAlu, FrmR, opstr>;
class SetCC_I<string opstr, PatFrag cond_op, Operand Od, PatLeaf imm_type,
RegisterClass RC>:
InstSE<(outs CPURegsOpnd:$rt), (ins RC:$rs, Od:$imm16),
!strconcat(opstr, "\t$rt, $rs, $imm16"),
[(set CPURegsOpnd:$rt, (cond_op RC:$rs, imm_type:$imm16))],
- IIAlu, FrmI>;
+ IIAlu, FrmI, opstr>;
// Jump
class JumpFJ<DAGOperand opnd, string opstr, SDPatternOperator operator,
@@ -617,17 +641,40 @@ class SYNC_FT :
class Mult<string opstr, InstrItinClass itin, RegisterOperand RO,
list<Register> DefRegs> :
InstSE<(outs), (ins RO:$rs, RO:$rt), !strconcat(opstr, "\t$rs, $rt"), [],
- itin, FrmR> {
+ itin, FrmR, opstr> {
let isCommutable = 1;
let Defs = DefRegs;
let neverHasSideEffects = 1;
}
-class Div<SDNode op, string opstr, InstrItinClass itin, RegisterOperand RO,
+// Pseudo multiply/divide instruction with explicit accumulator register
+// operands.
+class MultDivPseudo<Instruction RealInst, RegisterClass R0, RegisterOperand R1,
+ SDPatternOperator OpNode, InstrItinClass Itin,
+ bit IsComm = 1, bit HasSideEffects = 0> :
+ PseudoSE<(outs R0:$ac), (ins R1:$rs, R1:$rt),
+ [(set R0:$ac, (OpNode R1:$rs, R1:$rt))], Itin>,
+ PseudoInstExpansion<(RealInst R1:$rs, R1:$rt)> {
+ let isCommutable = IsComm;
+ let hasSideEffects = HasSideEffects;
+}
+
+// Pseudo multiply add/sub instruction with explicit accumulator register
+// operands.
+class MAddSubPseudo<Instruction RealInst, SDPatternOperator OpNode>
+ : PseudoSE<(outs ACRegs:$ac),
+ (ins CPURegsOpnd:$rs, CPURegsOpnd:$rt, ACRegs:$acin),
+ [(set ACRegs:$ac,
+ (OpNode CPURegsOpnd:$rs, CPURegsOpnd:$rt, ACRegs:$acin))],
+ IIImul>,
+ PseudoInstExpansion<(RealInst CPURegsOpnd:$rs, CPURegsOpnd:$rt)> {
+ string Constraints = "$acin = $ac";
+}
+
+class Div<string opstr, InstrItinClass itin, RegisterOperand RO,
list<Register> DefRegs> :
- InstSE<(outs), (ins RO:$rs, RO:$rt),
- !strconcat(opstr, "\t$$zero, $rs, $rt"), [(op RO:$rs, RO:$rt)], itin,
- FrmR> {
+ InstSE<(outs), (ins RO:$rs, RO:$rt), !strconcat(opstr, "\t$$zero, $rs, $rt"),
+ [], itin, FrmR> {
let Defs = DefRegs;
}
@@ -790,6 +837,12 @@ let usesCustomInserter = 1 in {
defm ATOMIC_CMP_SWAP_I32 : AtomicCmpSwap32<atomic_cmp_swap_32>;
}
+/// Pseudo instructions for loading and storing accumulator registers.
+let isPseudo = 1 in {
+ defm LOAD_AC64 : LoadM<"load_ac64", ACRegs>;
+ defm STORE_AC64 : StoreM<"store_ac64", ACRegs>;
+}
+
//===----------------------------------------------------------------------===//
// Instruction definition
//===----------------------------------------------------------------------===//
@@ -798,60 +851,70 @@ let usesCustomInserter = 1 in {
//===----------------------------------------------------------------------===//
/// Arithmetic Instructions (ALU Immediate)
-def ADDiu : ArithLogicI<"addiu", simm16, CPURegsOpnd, immSExt16, add>,
+def ADDiu : MMRel, ArithLogicI<"addiu", simm16, CPURegsOpnd, immSExt16, add>,
ADDI_FM<0x9>, IsAsCheapAsAMove;
-def ADDi : ArithLogicI<"addi", simm16, CPURegsOpnd>, ADDI_FM<0x8>;
-def SLTi : SetCC_I<"slti", setlt, simm16, immSExt16, CPURegs>, SLTI_FM<0xa>;
-def SLTiu : SetCC_I<"sltiu", setult, simm16, immSExt16, CPURegs>, SLTI_FM<0xb>;
-def ANDi : ArithLogicI<"andi", uimm16, CPURegsOpnd, immZExt16, and>,
+def ADDi : MMRel, ArithLogicI<"addi", simm16, CPURegsOpnd>, ADDI_FM<0x8>;
+def SLTi : MMRel, SetCC_I<"slti", setlt, simm16, immSExt16, CPURegs>,
+ SLTI_FM<0xa>;
+def SLTiu : MMRel, SetCC_I<"sltiu", setult, simm16, immSExt16, CPURegs>,
+ SLTI_FM<0xb>;
+def ANDi : MMRel, ArithLogicI<"andi", uimm16, CPURegsOpnd, immZExt16, and>,
ADDI_FM<0xc>;
-def ORi : ArithLogicI<"ori", uimm16, CPURegsOpnd, immZExt16, or>,
+def ORi : MMRel, ArithLogicI<"ori", uimm16, CPURegsOpnd, immZExt16, or>,
ADDI_FM<0xd>;
-def XORi : ArithLogicI<"xori", uimm16, CPURegsOpnd, immZExt16, xor>,
+def XORi : MMRel, ArithLogicI<"xori", uimm16, CPURegsOpnd, immZExt16, xor>,
ADDI_FM<0xe>;
-def LUi : LoadUpper<"lui", CPURegs, uimm16>, LUI_FM;
+def LUi : MMRel, LoadUpper<"lui", CPURegs, uimm16>, LUI_FM;
/// Arithmetic Instructions (3-Operand, R-Type)
-def ADDu : ArithLogicR<"addu", CPURegsOpnd, 1, IIAlu, add>, ADD_FM<0, 0x21>;
-def SUBu : ArithLogicR<"subu", CPURegsOpnd, 0, IIAlu, sub>, ADD_FM<0, 0x23>;
-def MUL : ArithLogicR<"mul", CPURegsOpnd, 1, IIImul, mul>, ADD_FM<0x1c, 2>;
-def ADD : ArithLogicR<"add", CPURegsOpnd>, ADD_FM<0, 0x20>;
-def SUB : ArithLogicR<"sub", CPURegsOpnd>, ADD_FM<0, 0x22>;
-def SLT : SetCC_R<"slt", setlt, CPURegs>, ADD_FM<0, 0x2a>;
-def SLTu : SetCC_R<"sltu", setult, CPURegs>, ADD_FM<0, 0x2b>;
-def AND : ArithLogicR<"and", CPURegsOpnd, 1, IIAlu, and>, ADD_FM<0, 0x24>;
-def OR : ArithLogicR<"or", CPURegsOpnd, 1, IIAlu, or>, ADD_FM<0, 0x25>;
-def XOR : ArithLogicR<"xor", CPURegsOpnd, 1, IIAlu, xor>, ADD_FM<0, 0x26>;
-def NOR : LogicNOR<"nor", CPURegsOpnd>, ADD_FM<0, 0x27>;
+def ADDu : MMRel, ArithLogicR<"addu", CPURegsOpnd, 1, IIAlu, add>,
+ ADD_FM<0, 0x21>;
+def SUBu : MMRel, ArithLogicR<"subu", CPURegsOpnd, 0, IIAlu, sub>,
+ ADD_FM<0, 0x23>;
+def MUL : MMRel, ArithLogicR<"mul", CPURegsOpnd, 1, IIImul, mul>,
+ ADD_FM<0x1c, 2>;
+def ADD : MMRel, ArithLogicR<"add", CPURegsOpnd>, ADD_FM<0, 0x20>;
+def SUB : MMRel, ArithLogicR<"sub", CPURegsOpnd>, ADD_FM<0, 0x22>;
+def SLT : MMRel, SetCC_R<"slt", setlt, CPURegs>, ADD_FM<0, 0x2a>;
+def SLTu : MMRel, SetCC_R<"sltu", setult, CPURegs>, ADD_FM<0, 0x2b>;
+def AND : MMRel, ArithLogicR<"and", CPURegsOpnd, 1, IIAlu, and>,
+ ADD_FM<0, 0x24>;
+def OR : MMRel, ArithLogicR<"or", CPURegsOpnd, 1, IIAlu, or>,
+ ADD_FM<0, 0x25>;
+def XOR : MMRel, ArithLogicR<"xor", CPURegsOpnd, 1, IIAlu, xor>,
+ ADD_FM<0, 0x26>;
+def NOR : MMRel, LogicNOR<"nor", CPURegsOpnd>, ADD_FM<0, 0x27>;
/// Shift Instructions
-def SLL : shift_rotate_imm<"sll", shamt, CPURegsOpnd, shl, immZExt5>,
+def SLL : MMRel, shift_rotate_imm<"sll", shamt, CPURegsOpnd, shl, immZExt5>,
SRA_FM<0, 0>;
-def SRL : shift_rotate_imm<"srl", shamt, CPURegsOpnd, srl, immZExt5>,
+def SRL : MMRel, shift_rotate_imm<"srl", shamt, CPURegsOpnd, srl, immZExt5>,
SRA_FM<2, 0>;
-def SRA : shift_rotate_imm<"sra", shamt, CPURegsOpnd, sra, immZExt5>,
+def SRA : MMRel, shift_rotate_imm<"sra", shamt, CPURegsOpnd, sra, immZExt5>,
SRA_FM<3, 0>;
-def SLLV : shift_rotate_reg<"sllv", CPURegsOpnd, shl>, SRLV_FM<4, 0>;
-def SRLV : shift_rotate_reg<"srlv", CPURegsOpnd, srl>, SRLV_FM<6, 0>;
-def SRAV : shift_rotate_reg<"srav", CPURegsOpnd, sra>, SRLV_FM<7, 0>;
+def SLLV : MMRel, shift_rotate_reg<"sllv", CPURegsOpnd, shl>, SRLV_FM<4, 0>;
+def SRLV : MMRel, shift_rotate_reg<"srlv", CPURegsOpnd, srl>, SRLV_FM<6, 0>;
+def SRAV : MMRel, shift_rotate_reg<"srav", CPURegsOpnd, sra>, SRLV_FM<7, 0>;
// Rotate Instructions
let Predicates = [HasMips32r2, HasStdEnc] in {
- def ROTR : shift_rotate_imm<"rotr", shamt, CPURegsOpnd, rotr, immZExt5>,
+ def ROTR : MMRel, shift_rotate_imm<"rotr", shamt, CPURegsOpnd, rotr,
+ immZExt5>,
SRA_FM<2, 1>;
- def ROTRV : shift_rotate_reg<"rotrv", CPURegsOpnd, rotr>, SRLV_FM<6, 1>;
+ def ROTRV : MMRel, shift_rotate_reg<"rotrv", CPURegsOpnd, rotr>,
+ SRLV_FM<6, 1>;
}
/// Load and Store Instructions
/// aligned
-defm LB : LoadM<"lb", CPURegs, sextloadi8>, LW_FM<0x20>;
-defm LBu : LoadM<"lbu", CPURegs, zextloadi8>, LW_FM<0x24>;
-defm LH : LoadM<"lh", CPURegs, sextloadi16>, LW_FM<0x21>;
-defm LHu : LoadM<"lhu", CPURegs, zextloadi16>, LW_FM<0x25>;
-defm LW : LoadM<"lw", CPURegs, load>, LW_FM<0x23>;
-defm SB : StoreM<"sb", CPURegs, truncstorei8>, LW_FM<0x28>;
-defm SH : StoreM<"sh", CPURegs, truncstorei16>, LW_FM<0x29>;
-defm SW : StoreM<"sw", CPURegs, store>, LW_FM<0x2b>;
+defm LB : LoadM<"lb", CPURegs, sextloadi8>, MMRel, LW_FM<0x20>;
+defm LBu : LoadM<"lbu", CPURegs, zextloadi8, addrDefault>, MMRel, LW_FM<0x24>;
+defm LH : LoadM<"lh", CPURegs, sextloadi16, addrDefault>, MMRel, LW_FM<0x21>;
+defm LHu : LoadM<"lhu", CPURegs, zextloadi16>, MMRel, LW_FM<0x25>;
+defm LW : LoadM<"lw", CPURegs, load, addrDefault>, MMRel, LW_FM<0x23>;
+defm SB : StoreM<"sb", CPURegs, truncstorei8>, MMRel, LW_FM<0x28>;
+defm SH : StoreM<"sh", CPURegs, truncstorei16>, MMRel, LW_FM<0x29>;
+defm SW : StoreM<"sw", CPURegs, store>, MMRel, LW_FM<0x2b>;
/// load/store left/right
defm LWL : LoadLeftRightM<"lwl", MipsLWL, CPURegs>, LW_FM<0x22>;
@@ -918,12 +981,17 @@ let Uses = [V0, V1], isTerminator = 1, isReturn = 1, isBarrier = 1 in {
}
/// Multiply and Divide Instructions.
-def MULT : Mult<"mult", IIImul, CPURegsOpnd, [HI, LO]>, MULT_FM<0, 0x18>;
-def MULTu : Mult<"multu", IIImul, CPURegsOpnd, [HI, LO]>, MULT_FM<0, 0x19>;
-def SDIV : Div<MipsDivRem, "div", IIIdiv, CPURegsOpnd, [HI, LO]>,
- MULT_FM<0, 0x1a>;
-def UDIV : Div<MipsDivRemU, "divu", IIIdiv, CPURegsOpnd, [HI, LO]>,
- MULT_FM<0, 0x1b>;
+def MULT : MMRel, Mult<"mult", IIImul, CPURegsOpnd, [HI, LO]>,
+ MULT_FM<0, 0x18>;
+def MULTu : MMRel, Mult<"multu", IIImul, CPURegsOpnd, [HI, LO]>,
+ MULT_FM<0, 0x19>;
+def PseudoMULT : MultDivPseudo<MULT, ACRegs, CPURegsOpnd, MipsMult, IIImul>;
+def PseudoMULTu : MultDivPseudo<MULTu, ACRegs, CPURegsOpnd, MipsMultu, IIImul>;
+def SDIV : Div<"div", IIIdiv, CPURegsOpnd, [HI, LO]>, MULT_FM<0, 0x1a>;
+def UDIV : Div<"divu", IIIdiv, CPURegsOpnd, [HI, LO]>, MULT_FM<0, 0x1b>;
+def PseudoSDIV : MultDivPseudo<SDIV, ACRegs, CPURegsOpnd, MipsDivRem, IIIdiv, 0>;
+def PseudoUDIV : MultDivPseudo<UDIV, ACRegs, CPURegsOpnd, MipsDivRemU, IIIdiv,
+ 0>;
def MTHI : MoveToLOHI<"mthi", CPURegs, [HI]>, MTLO_FM<0x11>;
def MTLO : MoveToLOHI<"mtlo", CPURegs, [LO]>, MTLO_FM<0x13>;
@@ -951,10 +1019,14 @@ def NOP : PseudoSE<(outs), (ins), []>, PseudoInstExpansion<(SLL ZERO, ZERO, 0)>;
def LEA_ADDiu : EffectiveAddress<"addiu", CPURegs, mem_ea>, LW_FM<9>;
// MADD*/MSUB*
-def MADD : MArithR<"madd", MipsMAdd, 1>, MULT_FM<0x1c, 0>;
-def MADDU : MArithR<"maddu", MipsMAddu, 1>, MULT_FM<0x1c, 1>;
-def MSUB : MArithR<"msub", MipsMSub>, MULT_FM<0x1c, 4>;
-def MSUBU : MArithR<"msubu", MipsMSubu>, MULT_FM<0x1c, 5>;
+def MADD : MArithR<"madd", 1>, MULT_FM<0x1c, 0>;
+def MADDU : MArithR<"maddu", 1>, MULT_FM<0x1c, 1>;
+def MSUB : MArithR<"msub">, MULT_FM<0x1c, 4>;
+def MSUBU : MArithR<"msubu">, MULT_FM<0x1c, 5>;
+def PseudoMADD : MAddSubPseudo<MADD, MipsMAdd>;
+def PseudoMADDU : MAddSubPseudo<MADDU, MipsMAddu>;
+def PseudoMSUB : MAddSubPseudo<MSUB, MipsMSub>;
+def PseudoMSUBU : MAddSubPseudo<MSUBU, MipsMSubu>;
def RDHWR : ReadHardware<CPURegs, HWRegsOpnd>, RDHWR_FM;
@@ -997,6 +1069,9 @@ def : InstAlias<"and $rs, $rt, $imm",
def : InstAlias<"j $rs", (JR CPURegs:$rs), 0>,
Requires<[NotMips64]>;
def : InstAlias<"jalr $rs", (JALR RA, CPURegs:$rs)>, Requires<[NotMips64]>;
+def : InstAlias<"jal $rs", (JALR RA, CPURegs:$rs), 0>, Requires<[NotMips64]>;
+def : InstAlias<"jal $rd,$rs", (JALR CPURegs:$rd, CPURegs:$rs), 0>,
+ Requires<[NotMips64]>;
def : InstAlias<"not $rt, $rs",
(NOR CPURegsOpnd:$rt, CPURegsOpnd:$rs, ZERO), 1>;
def : InstAlias<"neg $rt, $rs",
@@ -1006,8 +1081,11 @@ def : InstAlias<"negu $rt, $rs",
def : InstAlias<"slt $rs, $rt, $imm",
(SLTi CPURegsOpnd:$rs, CPURegs:$rt, simm16:$imm), 0>;
def : InstAlias<"xor $rs, $rt, $imm",
- (XORi CPURegsOpnd:$rs, CPURegsOpnd:$rt, simm16:$imm), 0>,
+ (XORi CPURegsOpnd:$rs, CPURegsOpnd:$rt, uimm16:$imm), 1>,
Requires<[NotMips64]>;
+def : InstAlias<"or $rs, $rt, $imm",
+ (ORi CPURegsOpnd:$rs, CPURegsOpnd:$rt, uimm16:$imm), 1>,
+ Requires<[NotMips64]>;
def : InstAlias<"nop", (SLL ZERO, ZERO, 0), 1>;
def : InstAlias<"mfc0 $rt, $rd",
(MFC0_3OP CPURegsOpnd:$rt, CPURegsOpnd:$rd, 0), 0>;
@@ -1043,6 +1121,13 @@ def LoadAddr32Imm : LoadAddressImm<"la", shamt,CPURegsOpnd>;
// Arbitrary patterns that map to one or more instructions
//===----------------------------------------------------------------------===//
+// Load/store pattern templates.
+class LoadRegImmPat<Instruction LoadInst, ValueType ValTy, PatFrag Node> :
+ MipsPat<(ValTy (Node addrRegImm:$a)), (LoadInst addrRegImm:$a)>;
+
+class StoreRegImmPat<Instruction StoreInst, ValueType ValTy> :
+ MipsPat<(store ValTy:$v, addrRegImm:$a), (StoreInst ValTy:$v, addrRegImm:$a)>;
+
// Small immediates
def : MipsPat<(i32 immSExt16:$in),
(ADDiu ZERO, imm:$in)>;
@@ -1058,10 +1143,12 @@ def : MipsPat<(i32 imm:$imm),
// Carry MipsPatterns
def : MipsPat<(subc CPURegs:$lhs, CPURegs:$rhs),
(SUBu CPURegs:$lhs, CPURegs:$rhs)>;
-def : MipsPat<(addc CPURegs:$lhs, CPURegs:$rhs),
- (ADDu CPURegs:$lhs, CPURegs:$rhs)>;
-def : MipsPat<(addc CPURegs:$src, immSExt16:$imm),
- (ADDiu CPURegs:$src, imm:$imm)>;
+let Predicates = [HasStdEnc, NotDSP] in {
+ def : MipsPat<(addc CPURegs:$lhs, CPURegs:$rhs),
+ (ADDu CPURegs:$lhs, CPURegs:$rhs)>;
+ def : MipsPat<(addc CPURegs:$src, immSExt16:$imm),
+ (ADDiu CPURegs:$src, imm:$imm)>;
+}
// Call
def : MipsPat<(MipsJmpLink (i32 tglobaladdr:$dst)),
@@ -1220,6 +1307,24 @@ defm : SetgeImmPats<CPURegs, SLTi, SLTiu>;
// bswap pattern
def : MipsPat<(bswap CPURegs:$rt), (ROTR (WSBH CPURegs:$rt), 16)>;
+// mflo/hi patterns.
+def : MipsPat<(i32 (ExtractLOHI ACRegs:$ac, imm:$lohi_idx)),
+ (EXTRACT_SUBREG ACRegs:$ac, imm:$lohi_idx)>;
+
+// Load halfword/word patterns.
+let AddedComplexity = 40 in {
+ let Predicates = [NotN64, HasStdEnc] in {
+ def : LoadRegImmPat<LBu, i32, zextloadi8>;
+ def : LoadRegImmPat<LH, i32, sextloadi16>;
+ def : LoadRegImmPat<LW, i32, load>;
+ }
+ let Predicates = [IsN64, HasStdEnc] in {
+ def : LoadRegImmPat<LBu_P8, i32, zextloadi8>;
+ def : LoadRegImmPat<LH_P8, i32, sextloadi16>;
+ def : LoadRegImmPat<LW_P8, i32, load>;
+ }
+}
+
//===----------------------------------------------------------------------===//
// Floating Point Support
//===----------------------------------------------------------------------===//
@@ -1238,3 +1343,6 @@ include "Mips16InstrInfo.td"
include "MipsDSPInstrFormats.td"
include "MipsDSPInstrInfo.td"
+// Micromips
+include "MicroMipsInstrFormats.td"
+include "MicroMipsInstrInfo.td"
diff --git a/lib/Target/Mips/MipsLongBranch.cpp b/lib/Target/Mips/MipsLongBranch.cpp
index 2efe534..bf5ad37 100644
--- a/lib/Target/Mips/MipsLongBranch.cpp
+++ b/lib/Target/Mips/MipsLongBranch.cpp
@@ -399,6 +399,8 @@ static void emitGPDisp(MachineFunction &F, const MipsInstrInfo *TII) {
}
bool MipsLongBranch::runOnMachineFunction(MachineFunction &F) {
+ if (TM.getSubtarget<MipsSubtarget>().inMips16Mode())
+ return false;
if ((TM.getRelocationModel() == Reloc::PIC_) &&
TM.getSubtarget<MipsSubtarget>().isABI_O32() &&
F.getInfo<MipsFunctionInfo>()->globalBaseRegSet())
diff --git a/lib/Target/Mips/MipsModuleISelDAGToDAG.cpp b/lib/Target/Mips/MipsModuleISelDAGToDAG.cpp
new file mode 100644
index 0000000..c6abf17
--- /dev/null
+++ b/lib/Target/Mips/MipsModuleISelDAGToDAG.cpp
@@ -0,0 +1,34 @@
+//===----------------------------------------------------------------------===//
+// Instruction Selector Subtarget Control
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// This file defines a pass used to change the subtarget for the
+// Mips Instruction selector.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MipsISelDAGToDAG.h"
+#include "MipsModuleISelDAGToDAG.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace llvm {
+
+bool MipsModuleDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
+ DEBUG(errs() << "In MipsModuleDAGToDAGISel::runMachineFunction\n");
+ const_cast<MipsSubtarget&>(Subtarget).resetSubtarget(&MF);
+ return false;
+}
+
+char MipsModuleDAGToDAGISel::ID = 0;
+
+}
+
+
+llvm::FunctionPass *llvm::createMipsModuleISelDag(MipsTargetMachine &TM) {
+ return new MipsModuleDAGToDAGISel(TM);
+}
+
+
diff --git a/lib/Target/Mips/MipsModuleISelDAGToDAG.h b/lib/Target/Mips/MipsModuleISelDAGToDAG.h
new file mode 100644
index 0000000..fda35ae
--- /dev/null
+++ b/lib/Target/Mips/MipsModuleISelDAGToDAG.h
@@ -0,0 +1,66 @@
+//===---- MipsModuleISelDAGToDAG.h - Change Subtarget --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a pass used to change the subtarget for the
+// Mips Instruction selector.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MIPSMODULEISELDAGTODAG_H
+#define MIPSMODULEISELDAGTODAG_H
+
+#include "Mips.h"
+#include "MipsSubtarget.h"
+#include "MipsTargetMachine.h"
+#include "llvm/CodeGen/SelectionDAGISel.h"
+
+
+//===----------------------------------------------------------------------===//
+// Instruction Selector Implementation
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// MipsModuleDAGToDAGISel - MIPS specific code to select MIPS machine
+// instructions for SelectionDAG operations.
+//===----------------------------------------------------------------------===//
+namespace llvm {
+
+class MipsModuleDAGToDAGISel : public MachineFunctionPass {
+public:
+
+ static char ID;
+
+ explicit MipsModuleDAGToDAGISel(MipsTargetMachine &TM_)
+ : MachineFunctionPass(ID),
+ TM(TM_), Subtarget(TM.getSubtarget<MipsSubtarget>()) {}
+
+ // Pass Name
+ virtual const char *getPassName() const {
+ return "MIPS DAG->DAG Pattern Instruction Selection";
+ }
+
+ virtual bool runOnMachineFunction(MachineFunction &MF);
+
+ virtual SDNode *Select(SDNode *N) {
+ llvm_unreachable("unexpected");
+ }
+
+protected:
+ /// Keep a pointer to the MipsSubtarget around so that we can make the right
+ /// decision when generating code for different targets.
+ const TargetMachine &TM;
+ const MipsSubtarget &Subtarget;
+};
+
+/// createMipsISelDag - This pass converts a legalized DAG into a
+/// MIPS-specific DAG, ready for instruction scheduling.
+FunctionPass *createMipsModuleISelDag(MipsTargetMachine &TM);
+}
+
+#endif
diff --git a/lib/Target/Mips/MipsOs16.cpp b/lib/Target/Mips/MipsOs16.cpp
new file mode 100644
index 0000000..1919077
--- /dev/null
+++ b/lib/Target/Mips/MipsOs16.cpp
@@ -0,0 +1,113 @@
+//===---- MipsOs16.cpp for Mips Option -Os16 --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines an optimization phase for the MIPS target.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "mips-os16"
+#include "MipsOs16.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace {
+
+ // Figure out if we need float point based on the function signature.
+ // We need to move variables in and/or out of floating point
+ // registers because of the ABI
+ //
+ bool needsFPFromSig(Function &F) {
+ Type* RetType = F.getReturnType();
+ switch (RetType->getTypeID()) {
+ case Type::FloatTyID:
+ case Type::DoubleTyID:
+ return true;
+ default:
+ ;
+ }
+ if (F.arg_size() >=1) {
+ Argument &Arg = F.getArgumentList().front();
+ switch (Arg.getType()->getTypeID()) {
+ case Type::FloatTyID:
+ case Type::DoubleTyID:
+ return true;
+ default:
+ ;
+ }
+ }
+ return false;
+ }
+
+ // Figure out if the function will need floating point operations
+ //
+ bool needsFP(Function &F) {
+ if (needsFPFromSig(F))
+ return true;
+ for (Function::const_iterator BB = F.begin(), E = F.end(); BB != E; ++BB)
+ for (BasicBlock::const_iterator I = BB->begin(), E = BB->end();
+ I != E; ++I) {
+ const Instruction &Inst = *I;
+ switch (Inst.getOpcode()) {
+ case Instruction::FAdd:
+ case Instruction::FSub:
+ case Instruction::FMul:
+ case Instruction::FDiv:
+ case Instruction::FRem:
+ case Instruction::FPToUI:
+ case Instruction::FPToSI:
+ case Instruction::UIToFP:
+ case Instruction::SIToFP:
+ case Instruction::FPTrunc:
+ case Instruction::FPExt:
+ case Instruction::FCmp:
+ return true;
+ default:
+ ;
+ }
+ if (const CallInst *CI = dyn_cast<CallInst>(I)) {
+ DEBUG(dbgs() << "Working on call" << "\n");
+ Function &F_ = *CI->getCalledFunction();
+ if (needsFPFromSig(F_))
+ return true;
+ }
+ }
+ return false;
+ }
+}
+namespace llvm {
+
+
+bool MipsOs16::runOnModule(Module &M) {
+ DEBUG(errs() << "Run on Module MipsOs16\n");
+ bool modified = false;
+ for (Module::iterator F = M.begin(), E = M.end(); F != E; ++F) {
+ if (F->isDeclaration()) continue;
+ DEBUG(dbgs() << "Working on " << F->getName() << "\n");
+ if (needsFP(*F)) {
+ DEBUG(dbgs() << " need to compile as nomips16 \n");
+ F->addFnAttr("nomips16");
+ }
+ else {
+ F->addFnAttr("mips16");
+ DEBUG(dbgs() << " no need to compile as nomips16 \n");
+ }
+ }
+ return modified;
+}
+
+char MipsOs16::ID = 0;
+
+}
+
+ModulePass *llvm::createMipsOs16(MipsTargetMachine &TM) {
+ return new MipsOs16;
+}
+
+
diff --git a/lib/Target/Mips/MipsOs16.h b/lib/Target/Mips/MipsOs16.h
new file mode 100644
index 0000000..21beef8
--- /dev/null
+++ b/lib/Target/Mips/MipsOs16.h
@@ -0,0 +1,49 @@
+//===---- MipsOs16.h for Mips Option -Os16 --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines an optimization phase for the MIPS target.
+//
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/MipsMCTargetDesc.h"
+#include "MipsTargetMachine.h"
+#include "llvm/Pass.h"
+#include "llvm/Target/TargetMachine.h"
+
+
+
+#ifndef MIPSOS16_H
+#define MIPSOS16_H
+
+using namespace llvm;
+
+namespace llvm {
+
+class MipsOs16 : public ModulePass {
+
+public:
+ static char ID;
+
+ MipsOs16() : ModulePass(ID) {
+
+ }
+
+ virtual const char *getPassName() const {
+ return "MIPS Os16 Optimization";
+ }
+
+ virtual bool runOnModule(Module &M);
+
+};
+
+ModulePass *createMipsOs16(MipsTargetMachine &TM);
+
+}
+
+#endif
diff --git a/lib/Target/Mips/MipsRegisterInfo.h b/lib/Target/Mips/MipsRegisterInfo.h
index 3c210e7..5ed5124 100644
--- a/lib/Target/Mips/MipsRegisterInfo.h
+++ b/lib/Target/Mips/MipsRegisterInfo.h
@@ -68,6 +68,9 @@ public:
unsigned getEHExceptionRegister() const;
unsigned getEHHandlerRegister() const;
+ /// \brief Return GPR register class.
+ virtual const TargetRegisterClass *intRegClass(unsigned Size) const = 0;
+
private:
virtual void eliminateFI(MachineBasicBlock::iterator II, unsigned OpNo,
int FrameIndex, uint64_t StackSize,
diff --git a/lib/Target/Mips/MipsRegisterInfo.td b/lib/Target/Mips/MipsRegisterInfo.td
index 6d76e8a..865d4d7 100644
--- a/lib/Target/Mips/MipsRegisterInfo.td
+++ b/lib/Target/Mips/MipsRegisterInfo.td
@@ -58,6 +58,13 @@ class AFPR64<bits<16> Enc, string n, list<Register> subregs>
let SubRegIndices = [sub_32];
}
+// Accumulator Registers
+class ACC<bits<16> Enc, string n, list<Register> subregs>
+ : MipsRegWithSubRegs<Enc, n, subregs> {
+ let SubRegIndices = [sub_lo, sub_hi];
+ let CoveredBySubRegs = 1;
+}
+
// Mips Hardware Registers
class HWR<bits<16> Enc, string n> : MipsReg<Enc, n>;
@@ -222,8 +229,14 @@ let Namespace = "Mips" in {
def D31_64 : AFPR64<31, "f31", [F31]>, DwarfRegNum<[63]>;
// Hi/Lo registers
- def HI : Register<"hi">, DwarfRegNum<[64]>;
- def LO : Register<"lo">, DwarfRegNum<[65]>;
+ def HI : Register<"ac0">, DwarfRegNum<[64]>;
+ def HI1 : Register<"ac1">, DwarfRegNum<[176]>;
+ def HI2 : Register<"ac2">, DwarfRegNum<[178]>;
+ def HI3 : Register<"ac3">, DwarfRegNum<[180]>;
+ def LO : Register<"ac0">, DwarfRegNum<[65]>;
+ def LO1 : Register<"ac1">, DwarfRegNum<[177]>;
+ def LO2 : Register<"ac2">, DwarfRegNum<[179]>;
+ def LO3 : Register<"ac3">, DwarfRegNum<[181]>;
let SubRegIndices = [sub_32] in {
def HI64 : RegisterWithSubRegs<"hi", [HI]>;
@@ -244,13 +257,15 @@ let Namespace = "Mips" in {
def HWR29_64 : MipsReg<29, "29">;
// Accum registers
- let SubRegIndices = [sub_lo, sub_hi] in
- def AC0 : MipsRegWithSubRegs<0, "ac0", [LO, HI]>;
- def AC1 : MipsReg<1, "ac1">;
- def AC2 : MipsReg<2, "ac2">;
- def AC3 : MipsReg<3, "ac3">;
+ def AC0 : ACC<0, "ac0", [LO, HI]>;
+ def AC1 : ACC<1, "ac1", [LO1, HI1]>;
+ def AC2 : ACC<2, "ac2", [LO2, HI2]>;
+ def AC3 : ACC<3, "ac3", [LO3, HI3]>;
+
+ def AC0_64 : ACC<0, "ac0", [LO64, HI64]>;
def DSPCtrl : Register<"dspctrl">;
+ def DSPCCond : Register<"">;
}
//===----------------------------------------------------------------------===//
@@ -326,17 +341,33 @@ def FGR64 : RegisterClass<"Mips", [f64], 64, (sequence "D%u_64", 0, 31)>;
def CCR : RegisterClass<"Mips", [i32], 32, (add FCR31,FCC0)>, Unallocatable;
// Hi/Lo Registers
-def HILO : RegisterClass<"Mips", [i32], 32, (add HI, LO)>, Unallocatable;
-def HILO64 : RegisterClass<"Mips", [i64], 64, (add HI64, LO64)>, Unallocatable;
+def LORegs : RegisterClass<"Mips", [i32], 32, (add LO)>;
+def HIRegs : RegisterClass<"Mips", [i32], 32, (add HI)>;
+def LORegsDSP : RegisterClass<"Mips", [i32], 32, (add LO, LO1, LO2, LO3)>;
+def HIRegsDSP : RegisterClass<"Mips", [i32], 32, (add HI, HI1, HI2, HI3)>;
+def LORegs64 : RegisterClass<"Mips", [i64], 64, (add LO64)>;
+def HIRegs64 : RegisterClass<"Mips", [i64], 64, (add HI64)>;
// Hardware registers
def HWRegs : RegisterClass<"Mips", [i32], 32, (add HWR29)>, Unallocatable;
def HWRegs64 : RegisterClass<"Mips", [i64], 64, (add HWR29_64)>, Unallocatable;
// Accumulator Registers
-def ACRegs : RegisterClass<"Mips", [i64], 64, (sequence "AC%u", 0, 3)>,
- Unallocatable;
+def ACRegs : RegisterClass<"Mips", [untyped], 64, (add AC0)> {
+ let Size = 64;
+}
+
+def ACRegs128 : RegisterClass<"Mips", [untyped], 128, (add AC0_64)> {
+ let Size = 128;
+}
+
+def ACRegsDSP : RegisterClass<"Mips", [untyped], 64, (sequence "AC%u", 0, 3)> {
+ let Size = 64;
+}
+
+def DSPCC : RegisterClass<"Mips", [v4i8, v2i16], 32, (add DSPCCond)>;
+// Register Operands.
def CPURegsAsmOperand : AsmOperandClass {
let Name = "CPURegsAsm";
let ParserMethod = "parseCPURegs";
diff --git a/lib/Target/Mips/MipsSEFrameLowering.cpp b/lib/Target/Mips/MipsSEFrameLowering.cpp
index 0dd6713..2b76704 100644
--- a/lib/Target/Mips/MipsSEFrameLowering.cpp
+++ b/lib/Target/Mips/MipsSEFrameLowering.cpp
@@ -29,6 +29,166 @@
using namespace llvm;
+namespace {
+typedef MachineBasicBlock::iterator Iter;
+
+/// Helper class to expand pseudos.
+class ExpandPseudo {
+public:
+ ExpandPseudo(MachineFunction &MF);
+ bool expand();
+
+private:
+ bool expandInstr(MachineBasicBlock &MBB, Iter I);
+ void expandLoadACC(MachineBasicBlock &MBB, Iter I, unsigned RegSize);
+ void expandStoreACC(MachineBasicBlock &MBB, Iter I, unsigned RegSize);
+ bool expandCopy(MachineBasicBlock &MBB, Iter I);
+ bool expandCopyACC(MachineBasicBlock &MBB, Iter I, unsigned Dst,
+ unsigned Src, unsigned RegSize);
+
+ MachineFunction &MF;
+ const MipsSEInstrInfo &TII;
+ const MipsRegisterInfo &RegInfo;
+ MachineRegisterInfo &MRI;
+};
+}
+
+ExpandPseudo::ExpandPseudo(MachineFunction &MF_)
+ : MF(MF_),
+ TII(*static_cast<const MipsSEInstrInfo*>(MF.getTarget().getInstrInfo())),
+ RegInfo(TII.getRegisterInfo()), MRI(MF.getRegInfo()) {}
+
+bool ExpandPseudo::expand() {
+ bool Expanded = false;
+
+ for (MachineFunction::iterator BB = MF.begin(), BBEnd = MF.end();
+ BB != BBEnd; ++BB)
+ for (Iter I = BB->begin(), End = BB->end(); I != End;)
+ Expanded |= expandInstr(*BB, I++);
+
+ return Expanded;
+}
+
+bool ExpandPseudo::expandInstr(MachineBasicBlock &MBB, Iter I) {
+ switch(I->getOpcode()) {
+ case Mips::LOAD_AC64:
+ case Mips::LOAD_AC64_P8:
+ case Mips::LOAD_AC_DSP:
+ case Mips::LOAD_AC_DSP_P8:
+ expandLoadACC(MBB, I, 4);
+ break;
+ case Mips::LOAD_AC128:
+ case Mips::LOAD_AC128_P8:
+ expandLoadACC(MBB, I, 8);
+ break;
+ case Mips::STORE_AC64:
+ case Mips::STORE_AC64_P8:
+ case Mips::STORE_AC_DSP:
+ case Mips::STORE_AC_DSP_P8:
+ expandStoreACC(MBB, I, 4);
+ break;
+ case Mips::STORE_AC128:
+ case Mips::STORE_AC128_P8:
+ expandStoreACC(MBB, I, 8);
+ break;
+ case TargetOpcode::COPY:
+ if (!expandCopy(MBB, I))
+ return false;
+ break;
+ default:
+ return false;
+ }
+
+ MBB.erase(I);
+ return true;
+}
+
+void ExpandPseudo::expandLoadACC(MachineBasicBlock &MBB, Iter I,
+ unsigned RegSize) {
+ // load $vr0, FI
+ // copy lo, $vr0
+ // load $vr1, FI + 4
+ // copy hi, $vr1
+
+ assert(I->getOperand(0).isReg() && I->getOperand(1).isFI());
+
+ const TargetRegisterClass *RC = RegInfo.intRegClass(RegSize);
+ unsigned VR0 = MRI.createVirtualRegister(RC);
+ unsigned VR1 = MRI.createVirtualRegister(RC);
+ unsigned Dst = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex();
+ unsigned Lo = RegInfo.getSubReg(Dst, Mips::sub_lo);
+ unsigned Hi = RegInfo.getSubReg(Dst, Mips::sub_hi);
+ DebugLoc DL = I->getDebugLoc();
+ const MCInstrDesc &Desc = TII.get(TargetOpcode::COPY);
+
+ TII.loadRegFromStack(MBB, I, VR0, FI, RC, &RegInfo, 0);
+ BuildMI(MBB, I, DL, Desc, Lo).addReg(VR0, RegState::Kill);
+ TII.loadRegFromStack(MBB, I, VR1, FI, RC, &RegInfo, RegSize);
+ BuildMI(MBB, I, DL, Desc, Hi).addReg(VR1, RegState::Kill);
+}
+
+void ExpandPseudo::expandStoreACC(MachineBasicBlock &MBB, Iter I,
+ unsigned RegSize) {
+ // copy $vr0, lo
+ // store $vr0, FI
+ // copy $vr1, hi
+ // store $vr1, FI + 4
+
+ assert(I->getOperand(0).isReg() && I->getOperand(1).isFI());
+
+ const TargetRegisterClass *RC = RegInfo.intRegClass(RegSize);
+ unsigned VR0 = MRI.createVirtualRegister(RC);
+ unsigned VR1 = MRI.createVirtualRegister(RC);
+ unsigned Src = I->getOperand(0).getReg(), FI = I->getOperand(1).getIndex();
+ unsigned SrcKill = getKillRegState(I->getOperand(0).isKill());
+ unsigned Lo = RegInfo.getSubReg(Src, Mips::sub_lo);
+ unsigned Hi = RegInfo.getSubReg(Src, Mips::sub_hi);
+ DebugLoc DL = I->getDebugLoc();
+
+ BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), VR0).addReg(Lo, SrcKill);
+ TII.storeRegToStack(MBB, I, VR0, true, FI, RC, &RegInfo, 0);
+ BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), VR1).addReg(Hi, SrcKill);
+ TII.storeRegToStack(MBB, I, VR1, true, FI, RC, &RegInfo, RegSize);
+}
+
+bool ExpandPseudo::expandCopy(MachineBasicBlock &MBB, Iter I) {
+ unsigned Dst = I->getOperand(0).getReg(), Src = I->getOperand(1).getReg();
+
+ if (Mips::ACRegsDSPRegClass.contains(Dst, Src))
+ return expandCopyACC(MBB, I, Dst, Src, 4);
+
+ if (Mips::ACRegs128RegClass.contains(Dst, Src))
+ return expandCopyACC(MBB, I, Dst, Src, 8);
+
+ return false;
+}
+
+bool ExpandPseudo::expandCopyACC(MachineBasicBlock &MBB, Iter I, unsigned Dst,
+ unsigned Src, unsigned RegSize) {
+ // copy $vr0, src_lo
+ // copy dst_lo, $vr0
+ // copy $vr1, src_hi
+ // copy dst_hi, $vr1
+
+ const TargetRegisterClass *RC = RegInfo.intRegClass(RegSize);
+ unsigned VR0 = MRI.createVirtualRegister(RC);
+ unsigned VR1 = MRI.createVirtualRegister(RC);
+ unsigned SrcKill = getKillRegState(I->getOperand(1).isKill());
+ unsigned DstLo = RegInfo.getSubReg(Dst, Mips::sub_lo);
+ unsigned DstHi = RegInfo.getSubReg(Dst, Mips::sub_hi);
+ unsigned SrcLo = RegInfo.getSubReg(Src, Mips::sub_lo);
+ unsigned SrcHi = RegInfo.getSubReg(Src, Mips::sub_hi);
+ DebugLoc DL = I->getDebugLoc();
+
+ BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), VR0).addReg(SrcLo, SrcKill);
+ BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), DstLo)
+ .addReg(VR0, RegState::Kill);
+ BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), VR1).addReg(SrcHi, SrcKill);
+ BuildMI(MBB, I, DL, TII.get(TargetOpcode::COPY), DstHi)
+ .addReg(VR1, RegState::Kill);
+ return true;
+}
+
unsigned MipsSEFrameLowering::ehDataReg(unsigned I) const {
static const unsigned EhDataReg[] = {
Mips::A0, Mips::A1, Mips::A2, Mips::A3
@@ -246,7 +406,10 @@ MipsSEFrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {
// Reserve call frame if the size of the maximum call frame fits into 16-bit
// immediate field and there are no variable sized objects on the stack.
- return isInt<16>(MFI->getMaxCallFrameSize()) && !MFI->hasVarSizedObjects();
+ // Make sure the second register scavenger spill slot can be accessed with one
+ // instruction.
+ return isInt<16>(MFI->getMaxCallFrameSize() + getStackAlignment()) &&
+ !MFI->hasVarSizedObjects();
}
// Eliminate ADJCALLSTACKDOWN, ADJCALLSTACKUP pseudo instructions
@@ -284,6 +447,18 @@ processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
if (MipsFI->callsEhReturn())
MipsFI->createEhDataRegsFI();
+ // Expand pseudo instructions which load, store or copy accumulators.
+ // Add an emergency spill slot if a pseudo was expanded.
+ if (ExpandPseudo(MF).expand()) {
+ // The spill slot should be half the size of the accumulator. If target is
+ // mips64, it should be 64-bit, otherwise it should be 32-bt.
+ const TargetRegisterClass *RC = STI.hasMips64() ?
+ &Mips::CPU64RegsRegClass : &Mips::CPURegsRegClass;
+ int FI = MF.getFrameInfo()->CreateStackObject(RC->getSize(),
+ RC->getAlignment(), false);
+ RS->addScavengingFrameIndex(FI);
+ }
+
// Set scavenging frame index if necessary.
uint64_t MaxSPOffset = MF.getInfo<MipsFunctionInfo>()->getIncomingArgSize() +
estimateStackSize(MF);
@@ -295,7 +470,7 @@ processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
&Mips::CPU64RegsRegClass : &Mips::CPURegsRegClass;
int FI = MF.getFrameInfo()->CreateStackObject(RC->getSize(),
RC->getAlignment(), false);
- RS->setScavengingFrameIndex(FI);
+ RS->addScavengingFrameIndex(FI);
}
const MipsFrameLowering *
diff --git a/lib/Target/Mips/MipsSEFrameLowering.h b/lib/Target/Mips/MipsSEFrameLowering.h
index 7becd25..193a66c 100644
--- a/lib/Target/Mips/MipsSEFrameLowering.h
+++ b/lib/Target/Mips/MipsSEFrameLowering.h
@@ -21,7 +21,7 @@ namespace llvm {
class MipsSEFrameLowering : public MipsFrameLowering {
public:
explicit MipsSEFrameLowering(const MipsSubtarget &STI)
- : MipsFrameLowering(STI) {}
+ : MipsFrameLowering(STI, STI.hasMips64() ? 16 : 8) {}
/// emitProlog/emitEpilog - These methods insert prolog and epilog code into
/// the function.
diff --git a/lib/Target/Mips/MipsSEISelDAGToDAG.cpp b/lib/Target/Mips/MipsSEISelDAGToDAG.cpp
index e22c3c8..b54f1f4 100644
--- a/lib/Target/Mips/MipsSEISelDAGToDAG.cpp
+++ b/lib/Target/Mips/MipsSEISelDAGToDAG.cpp
@@ -35,6 +35,11 @@
#include "llvm/Target/TargetMachine.h"
using namespace llvm;
+bool MipsSEDAGToDAGISel::runOnMachineFunction(MachineFunction &MF) {
+ if (Subtarget.inMips16Mode())
+ return false;
+ return MipsDAGToDAGISel::runOnMachineFunction(MF);
+}
bool MipsSEDAGToDAGISel::replaceUsesWithZeroReg(MachineRegisterInfo *MRI,
const MachineInstr& MI) {
@@ -177,27 +182,6 @@ void MipsSEDAGToDAGISel::processFunctionAfterISel(MachineFunction &MF) {
replaceUsesWithZeroReg(MRI, *I);
}
-/// Select multiply instructions.
-std::pair<SDNode*, SDNode*>
-MipsSEDAGToDAGISel::selectMULT(SDNode *N, unsigned Opc, DebugLoc DL, EVT Ty,
- bool HasLo, bool HasHi) {
- SDNode *Lo = 0, *Hi = 0;
- SDNode *Mul = CurDAG->getMachineNode(Opc, DL, MVT::Glue, N->getOperand(0),
- N->getOperand(1));
- SDValue InFlag = SDValue(Mul, 0);
-
- if (HasLo) {
- unsigned Opcode = (Ty == MVT::i32 ? Mips::MFLO : Mips::MFLO64);
- Lo = CurDAG->getMachineNode(Opcode, DL, Ty, MVT::Glue, InFlag);
- InFlag = SDValue(Lo, 1);
- }
- if (HasHi) {
- unsigned Opcode = (Ty == MVT::i32 ? Mips::MFHI : Mips::MFHI64);
- Hi = CurDAG->getMachineNode(Opcode, DL, Ty, InFlag);
- }
- return std::make_pair(Lo, Hi);
-}
-
SDNode *MipsSEDAGToDAGISel::selectAddESubE(unsigned MOp, SDValue InFlag,
SDValue CmpLHS, DebugLoc DL,
SDNode *Node) const {
@@ -211,7 +195,7 @@ SDNode *MipsSEDAGToDAGISel::selectAddESubE(unsigned MOp, SDValue InFlag,
SDValue LHS = Node->getOperand(0), RHS = Node->getOperand(1);
EVT VT = LHS.getValueType();
- SDNode *Carry = CurDAG->getMachineNode(Mips::SLTu, DL, VT, Ops, 2);
+ SDNode *Carry = CurDAG->getMachineNode(Mips::SLTu, DL, VT, Ops);
SDNode *AddCarry = CurDAG->getMachineNode(Mips::ADDu, DL, VT,
SDValue(Carry, 0), RHS);
return CurDAG->SelectNodeTo(Node, MOp, VT, MVT::Glue, LHS,
@@ -307,9 +291,7 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) {
// Instruction Selection not handled by the auto-generated
// tablegen selection should be handled here.
///
- EVT NodeTy = Node->getValueType(0);
SDNode *Result;
- unsigned MultOpc;
switch(Opcode) {
default: break;
@@ -321,51 +303,13 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) {
}
case ISD::ADDE: {
+ if (Subtarget.hasDSP()) // Select DSP instructions, ADDSC and ADDWC.
+ break;
SDValue InFlag = Node->getOperand(2);
Result = selectAddESubE(Mips::ADDu, InFlag, InFlag.getValue(0), DL, Node);
return std::make_pair(true, Result);
}
- /// Mul with two results
- case ISD::SMUL_LOHI:
- case ISD::UMUL_LOHI: {
- if (NodeTy == MVT::i32)
- MultOpc = (Opcode == ISD::UMUL_LOHI ? Mips::MULTu : Mips::MULT);
- else
- MultOpc = (Opcode == ISD::UMUL_LOHI ? Mips::DMULTu : Mips::DMULT);
-
- std::pair<SDNode*, SDNode*> LoHi = selectMULT(Node, MultOpc, DL, NodeTy,
- true, true);
-
- if (!SDValue(Node, 0).use_empty())
- ReplaceUses(SDValue(Node, 0), SDValue(LoHi.first, 0));
-
- if (!SDValue(Node, 1).use_empty())
- ReplaceUses(SDValue(Node, 1), SDValue(LoHi.second, 0));
-
- return std::make_pair(true, (SDNode*)NULL);
- }
-
- /// Special Muls
- case ISD::MUL: {
- // Mips32 has a 32-bit three operand mul instruction.
- if (Subtarget.hasMips32() && NodeTy == MVT::i32)
- break;
- MultOpc = NodeTy == MVT::i32 ? Mips::MULT : Mips::DMULT;
- Result = selectMULT(Node, MultOpc, DL, NodeTy, true, false).first;
- return std::make_pair(true, Result);
- }
- case ISD::MULHS:
- case ISD::MULHU: {
- if (NodeTy == MVT::i32)
- MultOpc = (Opcode == ISD::MULHU ? Mips::MULTu : Mips::MULT);
- else
- MultOpc = (Opcode == ISD::MULHU ? Mips::DMULTu : Mips::DMULT);
-
- Result = selectMULT(Node, MultOpc, DL, NodeTy, false, true).second;
- return std::make_pair(true, Result);
- }
-
case ISD::ConstantFP: {
ConstantFPSDNode *CN = dyn_cast<ConstantFPSDNode>(Node);
if (Node->getValueType(0) == MVT::f64 && CN->isExactlyValue(+0.0)) {
@@ -450,6 +394,19 @@ std::pair<bool, SDNode*> MipsSEDAGToDAGISel::selectNode(SDNode *Node) {
ReplaceUses(SDValue(Node, 0), ResNode);
return std::make_pair(true, ResNode.getNode());
}
+
+ case MipsISD::InsertLOHI: {
+ unsigned RCID = Subtarget.hasDSP() ? Mips::ACRegsDSPRegClassID :
+ Mips::ACRegsRegClassID;
+ SDValue RegClass = CurDAG->getTargetConstant(RCID, MVT::i32);
+ SDValue LoIdx = CurDAG->getTargetConstant(Mips::sub_lo, MVT::i32);
+ SDValue HiIdx = CurDAG->getTargetConstant(Mips::sub_hi, MVT::i32);
+ const SDValue Ops[] = { RegClass, Node->getOperand(0), LoIdx,
+ Node->getOperand(1), HiIdx };
+ SDNode *Res = CurDAG->getMachineNode(TargetOpcode::REG_SEQUENCE, DL,
+ MVT::Untyped, Ops);
+ return std::make_pair(true, Res);
+ }
}
return std::make_pair(false, (SDNode*)NULL);
diff --git a/lib/Target/Mips/MipsSEISelDAGToDAG.h b/lib/Target/Mips/MipsSEISelDAGToDAG.h
index 6137ab0..0dae73d 100644
--- a/lib/Target/Mips/MipsSEISelDAGToDAG.h
+++ b/lib/Target/Mips/MipsSEISelDAGToDAG.h
@@ -24,6 +24,9 @@ public:
explicit MipsSEDAGToDAGISel(MipsTargetMachine &TM) : MipsDAGToDAGISel(TM) {}
private:
+
+ virtual bool runOnMachineFunction(MachineFunction &MF);
+
bool replaceUsesWithZeroReg(MachineRegisterInfo *MRI, const MachineInstr&);
std::pair<SDNode*, SDNode*> selectMULT(SDNode *N, unsigned Opc, DebugLoc dl,
diff --git a/lib/Target/Mips/MipsSEISelLowering.cpp b/lib/Target/Mips/MipsSEISelLowering.cpp
index 287e2ed..8544bb8 100644
--- a/lib/Target/Mips/MipsSEISelLowering.cpp
+++ b/lib/Target/Mips/MipsSEISelLowering.cpp
@@ -15,6 +15,7 @@
#include "MipsTargetMachine.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/IR/Intrinsics.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Target/TargetInstrInfo.h"
@@ -27,6 +28,9 @@ EnableMipsTailCalls("enable-mips-tail-calls", cl::Hidden,
MipsSETargetLowering::MipsSETargetLowering(MipsTargetMachine &TM)
: MipsTargetLowering(TM) {
// Set up the register classes
+
+ clearRegisterClasses();
+
addRegisterClass(MVT::i32, &Mips::CPURegsRegClass);
if (HasMips64)
@@ -42,12 +46,23 @@ MipsSETargetLowering::MipsSETargetLowering(MipsTargetMachine &TM)
for (unsigned Opc = 0; Opc < ISD::BUILTIN_OP_END; ++Opc)
setOperationAction(Opc, VecTys[i], Expand);
+ setOperationAction(ISD::ADD, VecTys[i], Legal);
+ setOperationAction(ISD::SUB, VecTys[i], Legal);
setOperationAction(ISD::LOAD, VecTys[i], Legal);
setOperationAction(ISD::STORE, VecTys[i], Legal);
setOperationAction(ISD::BITCAST, VecTys[i], Legal);
}
+
+ setTargetDAGCombine(ISD::SHL);
+ setTargetDAGCombine(ISD::SRA);
+ setTargetDAGCombine(ISD::SRL);
+ setTargetDAGCombine(ISD::SETCC);
+ setTargetDAGCombine(ISD::VSELECT);
}
+ if (Subtarget->hasDSPR2())
+ setOperationAction(ISD::MUL, MVT::v2i16, Legal);
+
if (!TM.Options.UseSoftFloat) {
addRegisterClass(MVT::f32, &Mips::FGR32RegClass);
@@ -60,11 +75,31 @@ MipsSETargetLowering::MipsSETargetLowering(MipsTargetMachine &TM)
}
}
- setOperationAction(ISD::MEMBARRIER, MVT::Other, Custom);
+ setOperationAction(ISD::SMUL_LOHI, MVT::i32, Custom);
+ setOperationAction(ISD::UMUL_LOHI, MVT::i32, Custom);
+ setOperationAction(ISD::MULHS, MVT::i32, Custom);
+ setOperationAction(ISD::MULHU, MVT::i32, Custom);
+
+ if (HasMips64) {
+ setOperationAction(ISD::MULHS, MVT::i64, Custom);
+ setOperationAction(ISD::MULHU, MVT::i64, Custom);
+ setOperationAction(ISD::MUL, MVT::i64, Custom);
+ }
+
+ setOperationAction(ISD::INTRINSIC_WO_CHAIN, MVT::i64, Custom);
+ setOperationAction(ISD::INTRINSIC_W_CHAIN, MVT::i64, Custom);
+
+ setOperationAction(ISD::SDIVREM, MVT::i32, Custom);
+ setOperationAction(ISD::UDIVREM, MVT::i32, Custom);
+ setOperationAction(ISD::SDIVREM, MVT::i64, Custom);
+ setOperationAction(ISD::UDIVREM, MVT::i64, Custom);
setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Custom);
setOperationAction(ISD::LOAD, MVT::i32, Custom);
setOperationAction(ISD::STORE, MVT::i32, Custom);
+ setTargetDAGCombine(ISD::ADDE);
+ setTargetDAGCombine(ISD::SUBE);
+
computeRegisterProperties();
}
@@ -89,6 +124,334 @@ MipsSETargetLowering::allowsUnalignedMemoryAccesses(EVT VT, bool *Fast) const {
}
}
+SDValue MipsSETargetLowering::LowerOperation(SDValue Op,
+ SelectionDAG &DAG) const {
+ switch(Op.getOpcode()) {
+ case ISD::SMUL_LOHI: return lowerMulDiv(Op, MipsISD::Mult, true, true, DAG);
+ case ISD::UMUL_LOHI: return lowerMulDiv(Op, MipsISD::Multu, true, true, DAG);
+ case ISD::MULHS: return lowerMulDiv(Op, MipsISD::Mult, false, true, DAG);
+ case ISD::MULHU: return lowerMulDiv(Op, MipsISD::Multu, false, true, DAG);
+ case ISD::MUL: return lowerMulDiv(Op, MipsISD::Mult, true, false, DAG);
+ case ISD::SDIVREM: return lowerMulDiv(Op, MipsISD::DivRem, true, true, DAG);
+ case ISD::UDIVREM: return lowerMulDiv(Op, MipsISD::DivRemU, true, true,
+ DAG);
+ case ISD::INTRINSIC_WO_CHAIN: return lowerINTRINSIC_WO_CHAIN(Op, DAG);
+ case ISD::INTRINSIC_W_CHAIN: return lowerINTRINSIC_W_CHAIN(Op, DAG);
+ }
+
+ return MipsTargetLowering::LowerOperation(Op, DAG);
+}
+
+// selectMADD -
+// Transforms a subgraph in CurDAG if the following pattern is found:
+// (addc multLo, Lo0), (adde multHi, Hi0),
+// where,
+// multHi/Lo: product of multiplication
+// Lo0: initial value of Lo register
+// Hi0: initial value of Hi register
+// Return true if pattern matching was successful.
+static bool selectMADD(SDNode *ADDENode, SelectionDAG *CurDAG) {
+ // ADDENode's second operand must be a flag output of an ADDC node in order
+ // for the matching to be successful.
+ SDNode *ADDCNode = ADDENode->getOperand(2).getNode();
+
+ if (ADDCNode->getOpcode() != ISD::ADDC)
+ return false;
+
+ SDValue MultHi = ADDENode->getOperand(0);
+ SDValue MultLo = ADDCNode->getOperand(0);
+ SDNode *MultNode = MultHi.getNode();
+ unsigned MultOpc = MultHi.getOpcode();
+
+ // MultHi and MultLo must be generated by the same node,
+ if (MultLo.getNode() != MultNode)
+ return false;
+
+ // and it must be a multiplication.
+ if (MultOpc != ISD::SMUL_LOHI && MultOpc != ISD::UMUL_LOHI)
+ return false;
+
+ // MultLo amd MultHi must be the first and second output of MultNode
+ // respectively.
+ if (MultHi.getResNo() != 1 || MultLo.getResNo() != 0)
+ return false;
+
+ // Transform this to a MADD only if ADDENode and ADDCNode are the only users
+ // of the values of MultNode, in which case MultNode will be removed in later
+ // phases.
+ // If there exist users other than ADDENode or ADDCNode, this function returns
+ // here, which will result in MultNode being mapped to a single MULT
+ // instruction node rather than a pair of MULT and MADD instructions being
+ // produced.
+ if (!MultHi.hasOneUse() || !MultLo.hasOneUse())
+ return false;
+
+ DebugLoc DL = ADDENode->getDebugLoc();
+
+ // Initialize accumulator.
+ SDValue ACCIn = CurDAG->getNode(MipsISD::InsertLOHI, DL, MVT::Untyped,
+ ADDCNode->getOperand(1),
+ ADDENode->getOperand(1));
+
+ // create MipsMAdd(u) node
+ MultOpc = MultOpc == ISD::UMUL_LOHI ? MipsISD::MAddu : MipsISD::MAdd;
+
+ SDValue MAdd = CurDAG->getNode(MultOpc, DL, MVT::Untyped,
+ MultNode->getOperand(0),// Factor 0
+ MultNode->getOperand(1),// Factor 1
+ ACCIn);
+
+ // replace uses of adde and addc here
+ if (!SDValue(ADDCNode, 0).use_empty()) {
+ SDValue LoIdx = CurDAG->getConstant(Mips::sub_lo, MVT::i32);
+ SDValue LoOut = CurDAG->getNode(MipsISD::ExtractLOHI, DL, MVT::i32, MAdd,
+ LoIdx);
+ CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDCNode, 0), LoOut);
+ }
+ if (!SDValue(ADDENode, 0).use_empty()) {
+ SDValue HiIdx = CurDAG->getConstant(Mips::sub_hi, MVT::i32);
+ SDValue HiOut = CurDAG->getNode(MipsISD::ExtractLOHI, DL, MVT::i32, MAdd,
+ HiIdx);
+ CurDAG->ReplaceAllUsesOfValueWith(SDValue(ADDENode, 0), HiOut);
+ }
+
+ return true;
+}
+
+// selectMSUB -
+// Transforms a subgraph in CurDAG if the following pattern is found:
+// (addc Lo0, multLo), (sube Hi0, multHi),
+// where,
+// multHi/Lo: product of multiplication
+// Lo0: initial value of Lo register
+// Hi0: initial value of Hi register
+// Return true if pattern matching was successful.
+static bool selectMSUB(SDNode *SUBENode, SelectionDAG *CurDAG) {
+ // SUBENode's second operand must be a flag output of an SUBC node in order
+ // for the matching to be successful.
+ SDNode *SUBCNode = SUBENode->getOperand(2).getNode();
+
+ if (SUBCNode->getOpcode() != ISD::SUBC)
+ return false;
+
+ SDValue MultHi = SUBENode->getOperand(1);
+ SDValue MultLo = SUBCNode->getOperand(1);
+ SDNode *MultNode = MultHi.getNode();
+ unsigned MultOpc = MultHi.getOpcode();
+
+ // MultHi and MultLo must be generated by the same node,
+ if (MultLo.getNode() != MultNode)
+ return false;
+
+ // and it must be a multiplication.
+ if (MultOpc != ISD::SMUL_LOHI && MultOpc != ISD::UMUL_LOHI)
+ return false;
+
+ // MultLo amd MultHi must be the first and second output of MultNode
+ // respectively.
+ if (MultHi.getResNo() != 1 || MultLo.getResNo() != 0)
+ return false;
+
+ // Transform this to a MSUB only if SUBENode and SUBCNode are the only users
+ // of the values of MultNode, in which case MultNode will be removed in later
+ // phases.
+ // If there exist users other than SUBENode or SUBCNode, this function returns
+ // here, which will result in MultNode being mapped to a single MULT
+ // instruction node rather than a pair of MULT and MSUB instructions being
+ // produced.
+ if (!MultHi.hasOneUse() || !MultLo.hasOneUse())
+ return false;
+
+ DebugLoc DL = SUBENode->getDebugLoc();
+
+ // Initialize accumulator.
+ SDValue ACCIn = CurDAG->getNode(MipsISD::InsertLOHI, DL, MVT::Untyped,
+ SUBCNode->getOperand(0),
+ SUBENode->getOperand(0));
+
+ // create MipsSub(u) node
+ MultOpc = MultOpc == ISD::UMUL_LOHI ? MipsISD::MSubu : MipsISD::MSub;
+
+ SDValue MSub = CurDAG->getNode(MultOpc, DL, MVT::Glue,
+ MultNode->getOperand(0),// Factor 0
+ MultNode->getOperand(1),// Factor 1
+ ACCIn);
+
+ // replace uses of sube and subc here
+ if (!SDValue(SUBCNode, 0).use_empty()) {
+ SDValue LoIdx = CurDAG->getConstant(Mips::sub_lo, MVT::i32);
+ SDValue LoOut = CurDAG->getNode(MipsISD::ExtractLOHI, DL, MVT::i32, MSub,
+ LoIdx);
+ CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBCNode, 0), LoOut);
+ }
+ if (!SDValue(SUBENode, 0).use_empty()) {
+ SDValue HiIdx = CurDAG->getConstant(Mips::sub_hi, MVT::i32);
+ SDValue HiOut = CurDAG->getNode(MipsISD::ExtractLOHI, DL, MVT::i32, MSub,
+ HiIdx);
+ CurDAG->ReplaceAllUsesOfValueWith(SDValue(SUBENode, 0), HiOut);
+ }
+
+ return true;
+}
+
+static SDValue performADDECombine(SDNode *N, SelectionDAG &DAG,
+ TargetLowering::DAGCombinerInfo &DCI,
+ const MipsSubtarget *Subtarget) {
+ if (DCI.isBeforeLegalize())
+ return SDValue();
+
+ if (Subtarget->hasMips32() && N->getValueType(0) == MVT::i32 &&
+ selectMADD(N, &DAG))
+ return SDValue(N, 0);
+
+ return SDValue();
+}
+
+static SDValue performSUBECombine(SDNode *N, SelectionDAG &DAG,
+ TargetLowering::DAGCombinerInfo &DCI,
+ const MipsSubtarget *Subtarget) {
+ if (DCI.isBeforeLegalize())
+ return SDValue();
+
+ if (Subtarget->hasMips32() && N->getValueType(0) == MVT::i32 &&
+ selectMSUB(N, &DAG))
+ return SDValue(N, 0);
+
+ return SDValue();
+}
+
+static SDValue performDSPShiftCombine(unsigned Opc, SDNode *N, EVT Ty,
+ SelectionDAG &DAG,
+ const MipsSubtarget *Subtarget) {
+ // See if this is a vector splat immediate node.
+ APInt SplatValue, SplatUndef;
+ unsigned SplatBitSize;
+ bool HasAnyUndefs;
+ unsigned EltSize = Ty.getVectorElementType().getSizeInBits();
+ BuildVectorSDNode *BV = dyn_cast<BuildVectorSDNode>(N->getOperand(1));
+
+ if (!BV ||
+ !BV->isConstantSplat(SplatValue, SplatUndef, SplatBitSize, HasAnyUndefs,
+ EltSize, !Subtarget->isLittle()) ||
+ (SplatBitSize != EltSize) ||
+ (SplatValue.getZExtValue() >= EltSize))
+ return SDValue();
+
+ return DAG.getNode(Opc, N->getDebugLoc(), Ty, N->getOperand(0),
+ DAG.getConstant(SplatValue.getZExtValue(), MVT::i32));
+}
+
+static SDValue performSHLCombine(SDNode *N, SelectionDAG &DAG,
+ TargetLowering::DAGCombinerInfo &DCI,
+ const MipsSubtarget *Subtarget) {
+ EVT Ty = N->getValueType(0);
+
+ if ((Ty != MVT::v2i16) && (Ty != MVT::v4i8))
+ return SDValue();
+
+ return performDSPShiftCombine(MipsISD::SHLL_DSP, N, Ty, DAG, Subtarget);
+}
+
+static SDValue performSRACombine(SDNode *N, SelectionDAG &DAG,
+ TargetLowering::DAGCombinerInfo &DCI,
+ const MipsSubtarget *Subtarget) {
+ EVT Ty = N->getValueType(0);
+
+ if ((Ty != MVT::v2i16) && ((Ty != MVT::v4i8) || !Subtarget->hasDSPR2()))
+ return SDValue();
+
+ return performDSPShiftCombine(MipsISD::SHRA_DSP, N, Ty, DAG, Subtarget);
+}
+
+
+static SDValue performSRLCombine(SDNode *N, SelectionDAG &DAG,
+ TargetLowering::DAGCombinerInfo &DCI,
+ const MipsSubtarget *Subtarget) {
+ EVT Ty = N->getValueType(0);
+
+ if (((Ty != MVT::v2i16) || !Subtarget->hasDSPR2()) && (Ty != MVT::v4i8))
+ return SDValue();
+
+ return performDSPShiftCombine(MipsISD::SHRL_DSP, N, Ty, DAG, Subtarget);
+}
+
+static bool isLegalDSPCondCode(EVT Ty, ISD::CondCode CC) {
+ bool IsV216 = (Ty == MVT::v2i16);
+
+ switch (CC) {
+ case ISD::SETEQ:
+ case ISD::SETNE: return true;
+ case ISD::SETLT:
+ case ISD::SETLE:
+ case ISD::SETGT:
+ case ISD::SETGE: return IsV216;
+ case ISD::SETULT:
+ case ISD::SETULE:
+ case ISD::SETUGT:
+ case ISD::SETUGE: return !IsV216;
+ default: return false;
+ }
+}
+
+static SDValue performSETCCCombine(SDNode *N, SelectionDAG &DAG) {
+ EVT Ty = N->getValueType(0);
+
+ if ((Ty != MVT::v2i16) && (Ty != MVT::v4i8))
+ return SDValue();
+
+ if (!isLegalDSPCondCode(Ty, cast<CondCodeSDNode>(N->getOperand(2))->get()))
+ return SDValue();
+
+ return DAG.getNode(MipsISD::SETCC_DSP, N->getDebugLoc(), Ty, N->getOperand(0),
+ N->getOperand(1), N->getOperand(2));
+}
+
+static SDValue performVSELECTCombine(SDNode *N, SelectionDAG &DAG) {
+ EVT Ty = N->getValueType(0);
+
+ if ((Ty != MVT::v2i16) && (Ty != MVT::v4i8))
+ return SDValue();
+
+ SDValue SetCC = N->getOperand(0);
+
+ if (SetCC.getOpcode() != MipsISD::SETCC_DSP)
+ return SDValue();
+
+ return DAG.getNode(MipsISD::SELECT_CC_DSP, N->getDebugLoc(), Ty,
+ SetCC.getOperand(0), SetCC.getOperand(1), N->getOperand(1),
+ N->getOperand(2), SetCC.getOperand(2));
+}
+
+SDValue
+MipsSETargetLowering::PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const {
+ SelectionDAG &DAG = DCI.DAG;
+ SDValue Val;
+
+ switch (N->getOpcode()) {
+ case ISD::ADDE:
+ return performADDECombine(N, DAG, DCI, Subtarget);
+ case ISD::SUBE:
+ return performSUBECombine(N, DAG, DCI, Subtarget);
+ case ISD::SHL:
+ return performSHLCombine(N, DAG, DCI, Subtarget);
+ case ISD::SRA:
+ return performSRACombine(N, DAG, DCI, Subtarget);
+ case ISD::SRL:
+ return performSRLCombine(N, DAG, DCI, Subtarget);
+ case ISD::VSELECT:
+ return performVSELECTCombine(N, DAG);
+ case ISD::SETCC: {
+ Val = performSETCCCombine(N, DAG);
+ break;
+ }
+ }
+
+ if (Val.getNode())
+ return Val;
+
+ return MipsTargetLowering::PerformDAGCombine(N, DCI);
+}
+
MachineBasicBlock *
MipsSETargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI,
MachineBasicBlock *BB) const {
@@ -133,6 +496,194 @@ getOpndList(SmallVectorImpl<SDValue> &Ops,
InternalLinkage, CLI, Callee, Chain);
}
+SDValue MipsSETargetLowering::lowerMulDiv(SDValue Op, unsigned NewOpc,
+ bool HasLo, bool HasHi,
+ SelectionDAG &DAG) const {
+ EVT Ty = Op.getOperand(0).getValueType();
+ DebugLoc DL = Op.getDebugLoc();
+ SDValue Mult = DAG.getNode(NewOpc, DL, MVT::Untyped,
+ Op.getOperand(0), Op.getOperand(1));
+ SDValue Lo, Hi;
+
+ if (HasLo)
+ Lo = DAG.getNode(MipsISD::ExtractLOHI, DL, Ty, Mult,
+ DAG.getConstant(Mips::sub_lo, MVT::i32));
+ if (HasHi)
+ Hi = DAG.getNode(MipsISD::ExtractLOHI, DL, Ty, Mult,
+ DAG.getConstant(Mips::sub_hi, MVT::i32));
+
+ if (!HasLo || !HasHi)
+ return HasLo ? Lo : Hi;
+
+ SDValue Vals[] = { Lo, Hi };
+ return DAG.getMergeValues(Vals, 2, DL);
+}
+
+
+static SDValue initAccumulator(SDValue In, DebugLoc DL, SelectionDAG &DAG) {
+ SDValue InLo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, In,
+ DAG.getConstant(0, MVT::i32));
+ SDValue InHi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32, In,
+ DAG.getConstant(1, MVT::i32));
+ return DAG.getNode(MipsISD::InsertLOHI, DL, MVT::Untyped, InLo, InHi);
+}
+
+static SDValue extractLOHI(SDValue Op, DebugLoc DL, SelectionDAG &DAG) {
+ SDValue Lo = DAG.getNode(MipsISD::ExtractLOHI, DL, MVT::i32, Op,
+ DAG.getConstant(Mips::sub_lo, MVT::i32));
+ SDValue Hi = DAG.getNode(MipsISD::ExtractLOHI, DL, MVT::i32, Op,
+ DAG.getConstant(Mips::sub_hi, MVT::i32));
+ return DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, Lo, Hi);
+}
+
+// This function expands mips intrinsic nodes which have 64-bit input operands
+// or output values.
+//
+// out64 = intrinsic-node in64
+// =>
+// lo = copy (extract-element (in64, 0))
+// hi = copy (extract-element (in64, 1))
+// mips-specific-node
+// v0 = copy lo
+// v1 = copy hi
+// out64 = merge-values (v0, v1)
+//
+static SDValue lowerDSPIntr(SDValue Op, SelectionDAG &DAG, unsigned Opc) {
+ DebugLoc DL = Op.getDebugLoc();
+ bool HasChainIn = Op->getOperand(0).getValueType() == MVT::Other;
+ SmallVector<SDValue, 3> Ops;
+ unsigned OpNo = 0;
+
+ // See if Op has a chain input.
+ if (HasChainIn)
+ Ops.push_back(Op->getOperand(OpNo++));
+
+ // The next operand is the intrinsic opcode.
+ assert(Op->getOperand(OpNo).getOpcode() == ISD::TargetConstant);
+
+ // See if the next operand has type i64.
+ SDValue Opnd = Op->getOperand(++OpNo), In64;
+
+ if (Opnd.getValueType() == MVT::i64)
+ In64 = initAccumulator(Opnd, DL, DAG);
+ else
+ Ops.push_back(Opnd);
+
+ // Push the remaining operands.
+ for (++OpNo ; OpNo < Op->getNumOperands(); ++OpNo)
+ Ops.push_back(Op->getOperand(OpNo));
+
+ // Add In64 to the end of the list.
+ if (In64.getNode())
+ Ops.push_back(In64);
+
+ // Scan output.
+ SmallVector<EVT, 2> ResTys;
+
+ for (SDNode::value_iterator I = Op->value_begin(), E = Op->value_end();
+ I != E; ++I)
+ ResTys.push_back((*I == MVT::i64) ? MVT::Untyped : *I);
+
+ // Create node.
+ SDValue Val = DAG.getNode(Opc, DL, ResTys, &Ops[0], Ops.size());
+ SDValue Out = (ResTys[0] == MVT::Untyped) ? extractLOHI(Val, DL, DAG) : Val;
+
+ if (!HasChainIn)
+ return Out;
+
+ assert(Val->getValueType(1) == MVT::Other);
+ SDValue Vals[] = { Out, SDValue(Val.getNode(), 1) };
+ return DAG.getMergeValues(Vals, 2, DL);
+}
+
+SDValue MipsSETargetLowering::lowerINTRINSIC_WO_CHAIN(SDValue Op,
+ SelectionDAG &DAG) const {
+ switch (cast<ConstantSDNode>(Op->getOperand(0))->getZExtValue()) {
+ default:
+ return SDValue();
+ case Intrinsic::mips_shilo:
+ return lowerDSPIntr(Op, DAG, MipsISD::SHILO);
+ case Intrinsic::mips_dpau_h_qbl:
+ return lowerDSPIntr(Op, DAG, MipsISD::DPAU_H_QBL);
+ case Intrinsic::mips_dpau_h_qbr:
+ return lowerDSPIntr(Op, DAG, MipsISD::DPAU_H_QBR);
+ case Intrinsic::mips_dpsu_h_qbl:
+ return lowerDSPIntr(Op, DAG, MipsISD::DPSU_H_QBL);
+ case Intrinsic::mips_dpsu_h_qbr:
+ return lowerDSPIntr(Op, DAG, MipsISD::DPSU_H_QBR);
+ case Intrinsic::mips_dpa_w_ph:
+ return lowerDSPIntr(Op, DAG, MipsISD::DPA_W_PH);
+ case Intrinsic::mips_dps_w_ph:
+ return lowerDSPIntr(Op, DAG, MipsISD::DPS_W_PH);
+ case Intrinsic::mips_dpax_w_ph:
+ return lowerDSPIntr(Op, DAG, MipsISD::DPAX_W_PH);
+ case Intrinsic::mips_dpsx_w_ph:
+ return lowerDSPIntr(Op, DAG, MipsISD::DPSX_W_PH);
+ case Intrinsic::mips_mulsa_w_ph:
+ return lowerDSPIntr(Op, DAG, MipsISD::MULSA_W_PH);
+ case Intrinsic::mips_mult:
+ return lowerDSPIntr(Op, DAG, MipsISD::Mult);
+ case Intrinsic::mips_multu:
+ return lowerDSPIntr(Op, DAG, MipsISD::Multu);
+ case Intrinsic::mips_madd:
+ return lowerDSPIntr(Op, DAG, MipsISD::MAdd);
+ case Intrinsic::mips_maddu:
+ return lowerDSPIntr(Op, DAG, MipsISD::MAddu);
+ case Intrinsic::mips_msub:
+ return lowerDSPIntr(Op, DAG, MipsISD::MSub);
+ case Intrinsic::mips_msubu:
+ return lowerDSPIntr(Op, DAG, MipsISD::MSubu);
+ }
+}
+
+SDValue MipsSETargetLowering::lowerINTRINSIC_W_CHAIN(SDValue Op,
+ SelectionDAG &DAG) const {
+ switch (cast<ConstantSDNode>(Op->getOperand(1))->getZExtValue()) {
+ default:
+ return SDValue();
+ case Intrinsic::mips_extp:
+ return lowerDSPIntr(Op, DAG, MipsISD::EXTP);
+ case Intrinsic::mips_extpdp:
+ return lowerDSPIntr(Op, DAG, MipsISD::EXTPDP);
+ case Intrinsic::mips_extr_w:
+ return lowerDSPIntr(Op, DAG, MipsISD::EXTR_W);
+ case Intrinsic::mips_extr_r_w:
+ return lowerDSPIntr(Op, DAG, MipsISD::EXTR_R_W);
+ case Intrinsic::mips_extr_rs_w:
+ return lowerDSPIntr(Op, DAG, MipsISD::EXTR_RS_W);
+ case Intrinsic::mips_extr_s_h:
+ return lowerDSPIntr(Op, DAG, MipsISD::EXTR_S_H);
+ case Intrinsic::mips_mthlip:
+ return lowerDSPIntr(Op, DAG, MipsISD::MTHLIP);
+ case Intrinsic::mips_mulsaq_s_w_ph:
+ return lowerDSPIntr(Op, DAG, MipsISD::MULSAQ_S_W_PH);
+ case Intrinsic::mips_maq_s_w_phl:
+ return lowerDSPIntr(Op, DAG, MipsISD::MAQ_S_W_PHL);
+ case Intrinsic::mips_maq_s_w_phr:
+ return lowerDSPIntr(Op, DAG, MipsISD::MAQ_S_W_PHR);
+ case Intrinsic::mips_maq_sa_w_phl:
+ return lowerDSPIntr(Op, DAG, MipsISD::MAQ_SA_W_PHL);
+ case Intrinsic::mips_maq_sa_w_phr:
+ return lowerDSPIntr(Op, DAG, MipsISD::MAQ_SA_W_PHR);
+ case Intrinsic::mips_dpaq_s_w_ph:
+ return lowerDSPIntr(Op, DAG, MipsISD::DPAQ_S_W_PH);
+ case Intrinsic::mips_dpsq_s_w_ph:
+ return lowerDSPIntr(Op, DAG, MipsISD::DPSQ_S_W_PH);
+ case Intrinsic::mips_dpaq_sa_l_w:
+ return lowerDSPIntr(Op, DAG, MipsISD::DPAQ_SA_L_W);
+ case Intrinsic::mips_dpsq_sa_l_w:
+ return lowerDSPIntr(Op, DAG, MipsISD::DPSQ_SA_L_W);
+ case Intrinsic::mips_dpaqx_s_w_ph:
+ return lowerDSPIntr(Op, DAG, MipsISD::DPAQX_S_W_PH);
+ case Intrinsic::mips_dpaqx_sa_w_ph:
+ return lowerDSPIntr(Op, DAG, MipsISD::DPAQX_SA_W_PH);
+ case Intrinsic::mips_dpsqx_s_w_ph:
+ return lowerDSPIntr(Op, DAG, MipsISD::DPSQX_S_W_PH);
+ case Intrinsic::mips_dpsqx_sa_w_ph:
+ return lowerDSPIntr(Op, DAG, MipsISD::DPSQX_SA_W_PH);
+ }
+}
+
MachineBasicBlock * MipsSETargetLowering::
emitBPOSGE32(MachineInstr *MI, MachineBasicBlock *BB) const{
// $bb:
diff --git a/lib/Target/Mips/MipsSEISelLowering.h b/lib/Target/Mips/MipsSEISelLowering.h
index 04a28ce..ec8a5c7 100644
--- a/lib/Target/Mips/MipsSEISelLowering.h
+++ b/lib/Target/Mips/MipsSEISelLowering.h
@@ -15,6 +15,7 @@
#define MipsSEISELLOWERING_H
#include "MipsISelLowering.h"
+#include "MipsRegisterInfo.h"
namespace llvm {
class MipsSETargetLowering : public MipsTargetLowering {
@@ -23,9 +24,26 @@ namespace llvm {
virtual bool allowsUnalignedMemoryAccesses(EVT VT, bool *Fast) const;
+ virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const;
+
+ virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
+
virtual MachineBasicBlock *
EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB) const;
+ virtual bool isShuffleMaskLegal(const SmallVectorImpl<int> &Mask,
+ EVT VT) const {
+ return false;
+ }
+
+ virtual const TargetRegisterClass *getRepRegClassFor(MVT VT) const {
+ if (VT == MVT::Untyped)
+ return Subtarget->hasDSP() ? &Mips::ACRegsDSPRegClass :
+ &Mips::ACRegsRegClass;
+
+ return TargetLowering::getRepRegClassFor(VT);
+ }
+
private:
virtual bool
isEligibleForTailCallOptimization(const MipsCC &MipsCCInfo,
@@ -38,6 +56,12 @@ namespace llvm {
bool IsPICCall, bool GlobalOrExternal, bool InternalLinkage,
CallLoweringInfo &CLI, SDValue Callee, SDValue Chain) const;
+ SDValue lowerMulDiv(SDValue Op, unsigned NewOpc, bool HasLo, bool HasHi,
+ SelectionDAG &DAG) const;
+
+ SDValue lowerINTRINSIC_WO_CHAIN(SDValue Op, SelectionDAG &DAG) const;
+ SDValue lowerINTRINSIC_W_CHAIN(SDValue Op, SelectionDAG &DAG) const;
+
MachineBasicBlock *emitBPOSGE32(MachineInstr *MI,
MachineBasicBlock *BB) const;
};
diff --git a/lib/Target/Mips/MipsSEInstrInfo.cpp b/lib/Target/Mips/MipsSEInstrInfo.cpp
index a9809ef..2e7048d 100644
--- a/lib/Target/Mips/MipsSEInstrInfo.cpp
+++ b/lib/Target/Mips/MipsSEInstrInfo.cpp
@@ -95,20 +95,28 @@ void MipsSEInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
Opc = Mips::CFC1;
else if (Mips::FGR32RegClass.contains(SrcReg))
Opc = Mips::MFC1;
- else if (SrcReg == Mips::HI)
+ else if (Mips::HIRegsRegClass.contains(SrcReg))
Opc = Mips::MFHI, SrcReg = 0;
- else if (SrcReg == Mips::LO)
+ else if (Mips::LORegsRegClass.contains(SrcReg))
Opc = Mips::MFLO, SrcReg = 0;
+ else if (Mips::HIRegsDSPRegClass.contains(SrcReg))
+ Opc = Mips::MFHI_DSP;
+ else if (Mips::LORegsDSPRegClass.contains(SrcReg))
+ Opc = Mips::MFLO_DSP;
}
else if (Mips::CPURegsRegClass.contains(SrcReg)) { // Copy from CPU Reg.
if (Mips::CCRRegClass.contains(DestReg))
Opc = Mips::CTC1;
else if (Mips::FGR32RegClass.contains(DestReg))
Opc = Mips::MTC1;
- else if (DestReg == Mips::HI)
+ else if (Mips::HIRegsRegClass.contains(DestReg))
Opc = Mips::MTHI, DestReg = 0;
- else if (DestReg == Mips::LO)
+ else if (Mips::LORegsRegClass.contains(DestReg))
Opc = Mips::MTLO, DestReg = 0;
+ else if (Mips::HIRegsDSPRegClass.contains(DestReg))
+ Opc = Mips::MTHI_DSP;
+ else if (Mips::LORegsDSPRegClass.contains(DestReg))
+ Opc = Mips::MTLO_DSP;
}
else if (Mips::FGR32RegClass.contains(DestReg, SrcReg))
Opc = Mips::FMOV_S;
@@ -121,17 +129,17 @@ void MipsSEInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
else if (Mips::CPU64RegsRegClass.contains(DestReg)) { // Copy to CPU64 Reg.
if (Mips::CPU64RegsRegClass.contains(SrcReg))
Opc = Mips::OR64, ZeroReg = Mips::ZERO_64;
- else if (SrcReg == Mips::HI64)
+ else if (Mips::HIRegs64RegClass.contains(SrcReg))
Opc = Mips::MFHI64, SrcReg = 0;
- else if (SrcReg == Mips::LO64)
+ else if (Mips::LORegs64RegClass.contains(SrcReg))
Opc = Mips::MFLO64, SrcReg = 0;
else if (Mips::FGR64RegClass.contains(SrcReg))
Opc = Mips::DMFC1;
}
else if (Mips::CPU64RegsRegClass.contains(SrcReg)) { // Copy from CPU64 Reg.
- if (DestReg == Mips::HI64)
+ if (Mips::HIRegs64RegClass.contains(DestReg))
Opc = Mips::MTHI64, DestReg = 0;
- else if (DestReg == Mips::LO64)
+ else if (Mips::LORegs64RegClass.contains(DestReg))
Opc = Mips::MTLO64, DestReg = 0;
else if (Mips::FGR64RegClass.contains(DestReg))
Opc = Mips::DMTC1;
@@ -152,10 +160,10 @@ void MipsSEInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
}
void MipsSEInstrInfo::
-storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
- unsigned SrcReg, bool isKill, int FI,
- const TargetRegisterClass *RC,
- const TargetRegisterInfo *TRI) const {
+storeRegToStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
+ unsigned SrcReg, bool isKill, int FI,
+ const TargetRegisterClass *RC, const TargetRegisterInfo *TRI,
+ int64_t Offset) const {
DebugLoc DL;
if (I != MBB.end()) DL = I->getDebugLoc();
MachineMemOperand *MMO = GetMemOperand(MBB, FI, MachineMemOperand::MOStore);
@@ -166,6 +174,12 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
Opc = IsN64 ? Mips::SW_P8 : Mips::SW;
else if (Mips::CPU64RegsRegClass.hasSubClassEq(RC))
Opc = IsN64 ? Mips::SD_P8 : Mips::SD;
+ else if (Mips::ACRegsRegClass.hasSubClassEq(RC))
+ Opc = IsN64 ? Mips::STORE_AC64_P8 : Mips::STORE_AC64;
+ else if (Mips::ACRegsDSPRegClass.hasSubClassEq(RC))
+ Opc = IsN64 ? Mips::STORE_AC_DSP_P8 : Mips::STORE_AC_DSP;
+ else if (Mips::ACRegs128RegClass.hasSubClassEq(RC))
+ Opc = IsN64 ? Mips::STORE_AC128_P8 : Mips::STORE_AC128;
else if (Mips::FGR32RegClass.hasSubClassEq(RC))
Opc = IsN64 ? Mips::SWC1_P8 : Mips::SWC1;
else if (Mips::AFGR64RegClass.hasSubClassEq(RC))
@@ -175,15 +189,13 @@ storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
assert(Opc && "Register class not handled!");
BuildMI(MBB, I, DL, get(Opc)).addReg(SrcReg, getKillRegState(isKill))
- .addFrameIndex(FI).addImm(0).addMemOperand(MMO);
+ .addFrameIndex(FI).addImm(Offset).addMemOperand(MMO);
}
void MipsSEInstrInfo::
-loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
- unsigned DestReg, int FI,
- const TargetRegisterClass *RC,
- const TargetRegisterInfo *TRI) const
-{
+loadRegFromStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
+ unsigned DestReg, int FI, const TargetRegisterClass *RC,
+ const TargetRegisterInfo *TRI, int64_t Offset) const {
DebugLoc DL;
if (I != MBB.end()) DL = I->getDebugLoc();
MachineMemOperand *MMO = GetMemOperand(MBB, FI, MachineMemOperand::MOLoad);
@@ -193,6 +205,12 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
Opc = IsN64 ? Mips::LW_P8 : Mips::LW;
else if (Mips::CPU64RegsRegClass.hasSubClassEq(RC))
Opc = IsN64 ? Mips::LD_P8 : Mips::LD;
+ else if (Mips::ACRegsRegClass.hasSubClassEq(RC))
+ Opc = IsN64 ? Mips::LOAD_AC64_P8 : Mips::LOAD_AC64;
+ else if (Mips::ACRegsDSPRegClass.hasSubClassEq(RC))
+ Opc = IsN64 ? Mips::LOAD_AC_DSP_P8 : Mips::LOAD_AC_DSP;
+ else if (Mips::ACRegs128RegClass.hasSubClassEq(RC))
+ Opc = IsN64 ? Mips::LOAD_AC128_P8 : Mips::LOAD_AC128;
else if (Mips::FGR32RegClass.hasSubClassEq(RC))
Opc = IsN64 ? Mips::LWC1_P8 : Mips::LWC1;
else if (Mips::AFGR64RegClass.hasSubClassEq(RC))
@@ -201,7 +219,7 @@ loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
Opc = IsN64 ? Mips::LDC164_P8 : Mips::LDC164;
assert(Opc && "Register class not handled!");
- BuildMI(MBB, I, DL, get(Opc), DestReg).addFrameIndex(FI).addImm(0)
+ BuildMI(MBB, I, DL, get(Opc), DestReg).addFrameIndex(FI).addImm(Offset)
.addMemOperand(MMO);
}
@@ -371,6 +389,7 @@ void MipsSEInstrInfo::ExpandEhReturn(MachineBasicBlock &MBB,
unsigned JR = STI.isABI_N64() ? Mips::JR64 : Mips::JR;
unsigned SP = STI.isABI_N64() ? Mips::SP_64 : Mips::SP;
unsigned RA = STI.isABI_N64() ? Mips::RA_64 : Mips::RA;
+ unsigned T9 = STI.isABI_N64() ? Mips::T9_64 : Mips::T9;
unsigned ZERO = STI.isABI_N64() ? Mips::ZERO_64 : Mips::ZERO;
unsigned OffsetReg = I->getOperand(0).getReg();
unsigned TargetReg = I->getOperand(1).getReg();
@@ -378,6 +397,9 @@ void MipsSEInstrInfo::ExpandEhReturn(MachineBasicBlock &MBB,
// or $ra, $v0, $zero
// addu $sp, $sp, $v1
// jr $ra
+ if (TM.getRelocationModel() == Reloc::PIC_)
+ BuildMI(MBB, I, I->getDebugLoc(), TM.getInstrInfo()->get(OR), T9)
+ .addReg(TargetReg).addReg(ZERO);
BuildMI(MBB, I, I->getDebugLoc(), TM.getInstrInfo()->get(OR), RA)
.addReg(TargetReg).addReg(ZERO);
BuildMI(MBB, I, I->getDebugLoc(), TM.getInstrInfo()->get(ADDU), SP)
diff --git a/lib/Target/Mips/MipsSEInstrInfo.h b/lib/Target/Mips/MipsSEInstrInfo.h
index 3e22b33..0bf7876 100644
--- a/lib/Target/Mips/MipsSEInstrInfo.h
+++ b/lib/Target/Mips/MipsSEInstrInfo.h
@@ -49,17 +49,19 @@ public:
unsigned DestReg, unsigned SrcReg,
bool KillSrc) const;
- virtual void storeRegToStackSlot(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MBBI,
- unsigned SrcReg, bool isKill, int FrameIndex,
- const TargetRegisterClass *RC,
- const TargetRegisterInfo *TRI) const;
-
- virtual void loadRegFromStackSlot(MachineBasicBlock &MBB,
- MachineBasicBlock::iterator MBBI,
- unsigned DestReg, int FrameIndex,
- const TargetRegisterClass *RC,
- const TargetRegisterInfo *TRI) const;
+ virtual void storeRegToStack(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI,
+ unsigned SrcReg, bool isKill, int FrameIndex,
+ const TargetRegisterClass *RC,
+ const TargetRegisterInfo *TRI,
+ int64_t Offset) const;
+
+ virtual void loadRegFromStack(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator MI,
+ unsigned DestReg, int FrameIndex,
+ const TargetRegisterClass *RC,
+ const TargetRegisterInfo *TRI,
+ int64_t Offset) const;
virtual bool expandPostRAPseudo(MachineBasicBlock::iterator MI) const;
diff --git a/lib/Target/Mips/MipsSERegisterInfo.cpp b/lib/Target/Mips/MipsSERegisterInfo.cpp
index a39b393..9696738 100644
--- a/lib/Target/Mips/MipsSERegisterInfo.cpp
+++ b/lib/Target/Mips/MipsSERegisterInfo.cpp
@@ -54,6 +54,15 @@ requiresFrameIndexScavenging(const MachineFunction &MF) const {
return true;
}
+const TargetRegisterClass *
+MipsSERegisterInfo::intRegClass(unsigned Size) const {
+ if (Size == 4)
+ return &Mips::CPURegsRegClass;
+
+ assert(Size == 8);
+ return &Mips::CPU64RegsRegClass;
+}
+
void MipsSERegisterInfo::eliminateFI(MachineBasicBlock::iterator II,
unsigned OpNo, int FrameIndex,
uint64_t StackSize,
diff --git a/lib/Target/Mips/MipsSERegisterInfo.h b/lib/Target/Mips/MipsSERegisterInfo.h
index f6827e9..2f7c37b 100644
--- a/lib/Target/Mips/MipsSERegisterInfo.h
+++ b/lib/Target/Mips/MipsSERegisterInfo.h
@@ -31,6 +31,8 @@ public:
bool requiresFrameIndexScavenging(const MachineFunction &MF) const;
+ virtual const TargetRegisterClass *intRegClass(unsigned Size) const;
+
private:
virtual void eliminateFI(MachineBasicBlock::iterator II, unsigned OpNo,
int FrameIndex, uint64_t StackSize,
diff --git a/lib/Target/Mips/MipsSubtarget.cpp b/lib/Target/Mips/MipsSubtarget.cpp
index e11e5d1..14a2b27 100644
--- a/lib/Target/Mips/MipsSubtarget.cpp
+++ b/lib/Target/Mips/MipsSubtarget.cpp
@@ -11,29 +11,56 @@
//
//===----------------------------------------------------------------------===//
+#define DEBUG_TYPE "mips-subtarget"
+
+#include "MipsMachineFunction.h"
#include "MipsSubtarget.h"
+#include "MipsTargetMachine.h"
#include "Mips.h"
#include "MipsRegisterInfo.h"
+#include "llvm/IR/Attributes.h"
+#include "llvm/IR/Function.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/TargetRegistry.h"
+#include "llvm/Support/raw_ostream.h"
#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(
+ "mips-mixed-16-32",
+ cl::init(false),
+ cl::desc("Allow for a mixture of Mips16 "
+ "and Mips32 code in a single source file"),
+ cl::Hidden);
+
+static cl::opt<bool> Mips_Os16(
+ "mips-os16",
+ cl::init(false),
+ cl::desc("Compile all functions that don' use "
+ "floating point as Mips 16"),
+ cl::Hidden);
+
void MipsSubtarget::anchor() { }
MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU,
const std::string &FS, bool little,
- Reloc::Model _RM) :
+ Reloc::Model _RM, MipsTargetMachine *_TM) :
MipsGenSubtargetInfo(TT, CPU, FS),
MipsArchVersion(Mips32), MipsABI(UnknownABI), IsLittle(little),
IsSingleFloat(false), IsFP64bit(false), IsGP64bit(false), HasVFPU(false),
IsLinux(true), HasSEInReg(false), HasCondMov(false), HasSwap(false),
HasBitCount(false), HasFPIdx(false),
InMips16Mode(false), InMicroMipsMode(false), HasDSP(false), HasDSPR2(false),
- RM(_RM)
+ AllowMixed16_32(Mixed16_32 | Mips_Os16), Os16(Mips_Os16),
+ RM(_RM), OverrideMode(NoOverride), TM(_TM)
{
std::string CPUName = CPU;
if (CPUName.empty())
@@ -42,6 +69,8 @@ MipsSubtarget::MipsSubtarget(const std::string &TT, const std::string &CPU,
// Parse features string.
ParseSubtargetFeatures(CPUName, FS);
+ PreviousInMips16Mode = InMips16Mode;
+
// Initialize scheduling itinerary for the specified CPU.
InstrItins = getInstrItineraryForCPU(CPUName);
@@ -72,3 +101,48 @@ MipsSubtarget::enablePostRAScheduler(CodeGenOpt::Level OptLevel,
&Mips::CPU64RegsRegClass : &Mips::CPURegsRegClass);
return OptLevel >= CodeGenOpt::Aggressive;
}
+
+//FIXME: This logic for reseting the subtarget along with
+// the helper classes can probably be simplified but there are a lot of
+// cases so we will defer rewriting this to later.
+//
+void MipsSubtarget::resetSubtarget(MachineFunction *MF) {
+ bool ChangeToMips16 = false, ChangeToNoMips16 = false;
+ DEBUG(dbgs() << "resetSubtargetFeatures" << "\n");
+ AttributeSet FnAttrs = MF->getFunction()->getAttributes();
+ ChangeToMips16 = FnAttrs.hasAttribute(AttributeSet::FunctionIndex,
+ "mips16");
+ ChangeToNoMips16 = FnAttrs.hasAttribute(AttributeSet::FunctionIndex,
+ "nomips16");
+ assert (!(ChangeToMips16 & ChangeToNoMips16) &&
+ "mips16 and nomips16 specified on the same function");
+ if (ChangeToMips16) {
+ if (PreviousInMips16Mode)
+ return;
+ OverrideMode = Mips16Override;
+ PreviousInMips16Mode = true;
+ TM->setHelperClassesMips16();
+ return;
+ } else if (ChangeToNoMips16) {
+ if (!PreviousInMips16Mode)
+ return;
+ OverrideMode = NoMips16Override;
+ PreviousInMips16Mode = false;
+ TM->setHelperClassesMipsSE();
+ return;
+ } else {
+ if (OverrideMode == NoOverride)
+ return;
+ OverrideMode = NoOverride;
+ DEBUG(dbgs() << "back to default" << "\n");
+ if (inMips16Mode() && !PreviousInMips16Mode) {
+ TM->setHelperClassesMips16();
+ PreviousInMips16Mode = true;
+ } else if (!inMips16Mode() && PreviousInMips16Mode) {
+ TM->setHelperClassesMipsSE();
+ PreviousInMips16Mode = false;
+ }
+ return;
+ }
+}
+
diff --git a/lib/Target/Mips/MipsSubtarget.h b/lib/Target/Mips/MipsSubtarget.h
index 7a2e47c..f2f0e15 100644
--- a/lib/Target/Mips/MipsSubtarget.h
+++ b/lib/Target/Mips/MipsSubtarget.h
@@ -16,7 +16,9 @@
#include "MCTargetDesc/MipsReginfo.h"
#include "llvm/MC/MCInstrItineraries.h"
+#include "llvm/Support/ErrorHandling.h"
#include "llvm/Target/TargetSubtargetInfo.h"
+
#include <string>
#define GET_SUBTARGETINFO_HEADER
@@ -25,6 +27,8 @@
namespace llvm {
class StringRef;
+class MipsTargetMachine;
+
class MipsSubtarget : public MipsGenSubtargetInfo {
virtual void anchor();
@@ -89,12 +93,23 @@ protected:
// InMips16 -- can process Mips16 instructions
bool InMips16Mode;
+ // PreviousInMips16 -- the function we just processed was in Mips 16 Mode
+ bool PreviousInMips16Mode;
+
// InMicroMips -- can process MicroMips instructions
bool InMicroMipsMode;
// HasDSP, HasDSPR2 -- supports DSP ASE.
bool HasDSP, HasDSPR2;
+ // Allow mixed Mips16 and Mips32 in one source file
+ bool AllowMixed16_32;
+
+ // Optimize for space by compiling all functions as Mips 16 unless
+ // it needs floating point. Functions needing floating point are
+ // compiled as Mips32
+ bool Os16;
+
InstrItineraryData InstrItins;
// The instance to the register info section object
@@ -103,6 +118,12 @@ protected:
// Relocation Model
Reloc::Model RM;
+ // We can override the determination of whether we are in mips16 mode
+ // as from the command line
+ enum {NoOverride, Mips16Override, NoMips16Override} OverrideMode;
+
+ MipsTargetMachine *TM;
+
public:
virtual bool enablePostRAScheduler(CodeGenOpt::Level OptLevel,
AntiDepBreakMode& Mode,
@@ -118,7 +139,8 @@ public:
/// This constructor initializes the data members to match that
/// of the specified triple.
MipsSubtarget(const std::string &TT, const std::string &CPU,
- const std::string &FS, bool little, Reloc::Model RM);
+ const std::string &FS, bool little, Reloc::Model RM,
+ MipsTargetMachine *TM);
/// ParseSubtargetFeatures - Parses features string setting specified
/// subtarget options. Definition of function is auto generated by tblgen.
@@ -137,7 +159,20 @@ public:
bool isSingleFloat() const { return IsSingleFloat; }
bool isNotSingleFloat() const { return !IsSingleFloat; }
bool hasVFPU() const { return HasVFPU; }
- bool inMips16Mode() const { return InMips16Mode; }
+ bool inMips16Mode() const {
+ switch (OverrideMode) {
+ case NoOverride:
+ return InMips16Mode;
+ case Mips16Override:
+ return true;
+ case NoMips16Override:
+ return false;
+ }
+ llvm_unreachable("Unexpected mode");
+ }
+ bool inMips16ModeDefault() {
+ return InMips16Mode;
+ }
bool inMicroMipsMode() const { return InMicroMipsMode; }
bool hasDSP() const { return HasDSP; }
bool hasDSPR2() const { return HasDSPR2; }
@@ -153,11 +188,20 @@ public:
bool hasBitCount() const { return HasBitCount; }
bool hasFPIdx() const { return HasFPIdx; }
+ bool allowMixed16_32() const { return AllowMixed16_32;};
+
+ bool os16() const { return Os16;};
+
// Grab MipsRegInfo object
const MipsReginfo &getMReginfo() const { return MRI; }
// Grab relocation model
Reloc::Model getRelocationModel() const {return RM;}
+
+ /// \brief Reset the subtarget for the Mips target.
+ void resetSubtarget(MachineFunction *MF);
+
+
};
} // End llvm namespace
diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp
index 3336358..ee28e2a 100644
--- a/lib/Target/Mips/MipsTargetMachine.cpp
+++ b/lib/Target/Mips/MipsTargetMachine.cpp
@@ -15,11 +15,26 @@
#include "Mips.h"
#include "MipsFrameLowering.h"
#include "MipsInstrInfo.h"
+#include "MipsModuleISelDAGToDAG.h"
+#include "MipsOs16.h"
+#include "MipsSEFrameLowering.h"
+#include "MipsSEInstrInfo.h"
+#include "MipsSEISelLowering.h"
+#include "MipsSEISelDAGToDAG.h"
+#include "Mips16FrameLowering.h"
+#include "Mips16InstrInfo.h"
+#include "Mips16ISelDAGToDAG.h"
+#include "Mips16ISelLowering.h"
+#include "llvm/Analysis/TargetTransformInfo.h"
#include "llvm/CodeGen/Passes.h"
#include "llvm/PassManager.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
+
+
extern "C" void LLVMInitializeMipsTarget() {
// Register the target.
RegisterTargetMachine<MipsebTargetMachine> X(TheMipsTarget);
@@ -42,7 +57,7 @@ MipsTargetMachine(const Target &T, StringRef TT,
CodeGenOpt::Level OL,
bool isLittle)
: LLVMTargetMachine(T, TT, CPU, FS, Options, RM, CM, OL),
- Subtarget(TT, CPU, FS, isLittle, RM),
+ Subtarget(TT, CPU, FS, isLittle, RM, this),
DL(isLittle ?
(Subtarget.isABI_N64() ?
"e-p:64:64:64-i8:8:32-i16:16:32-i64:64:64-f128:128:128-"
@@ -54,9 +69,46 @@ MipsTargetMachine(const Target &T, StringRef TT,
"E-p:32:32:32-i8:8:32-i16:16:32-i64:64:64-n32-S64")),
InstrInfo(MipsInstrInfo::create(*this)),
FrameLowering(MipsFrameLowering::create(*this, Subtarget)),
- TLInfo(MipsTargetLowering::create(*this)), TSInfo(*this), JITInfo() {
+ TLInfo(MipsTargetLowering::create(*this)),
+ TSInfo(*this), JITInfo() {
+}
+
+
+void MipsTargetMachine::setHelperClassesMips16() {
+ InstrInfoSE.swap(InstrInfo);
+ FrameLoweringSE.swap(FrameLowering);
+ TLInfoSE.swap(TLInfo);
+ if (!InstrInfo16) {
+ InstrInfo.reset(MipsInstrInfo::create(*this));
+ FrameLowering.reset(MipsFrameLowering::create(*this, Subtarget));
+ TLInfo.reset(MipsTargetLowering::create(*this));
+ } else {
+ InstrInfo16.swap(InstrInfo);
+ FrameLowering16.swap(FrameLowering);
+ TLInfo16.swap(TLInfo);
+ }
+ assert(TLInfo && "null target lowering 16");
+ assert(InstrInfo && "null instr info 16");
+ assert(FrameLowering && "null frame lowering 16");
}
+void MipsTargetMachine::setHelperClassesMipsSE() {
+ InstrInfo16.swap(InstrInfo);
+ FrameLowering16.swap(FrameLowering);
+ TLInfo16.swap(TLInfo);
+ if (!InstrInfoSE) {
+ InstrInfo.reset(MipsInstrInfo::create(*this));
+ FrameLowering.reset(MipsFrameLowering::create(*this, Subtarget));
+ TLInfo.reset(MipsTargetLowering::create(*this));
+ } else {
+ InstrInfoSE.swap(InstrInfo);
+ FrameLoweringSE.swap(FrameLowering);
+ TLInfoSE.swap(TLInfo);
+ }
+ assert(TLInfo && "null target lowering in SE");
+ assert(InstrInfo && "null instr info SE");
+ assert(FrameLowering && "null frame lowering SE");
+}
void MipsebTargetMachine::anchor() { }
MipsebTargetMachine::
@@ -90,6 +142,7 @@ public:
return *getMipsTargetMachine().getSubtargetImpl();
}
+ virtual void addIRPasses();
virtual bool addInstSelector();
virtual bool addPreEmitPass();
};
@@ -99,24 +152,50 @@ TargetPassConfig *MipsTargetMachine::createPassConfig(PassManagerBase &PM) {
return new MipsPassConfig(this, PM);
}
+void MipsPassConfig::addIRPasses() {
+ TargetPassConfig::addIRPasses();
+ if (getMipsSubtarget().os16())
+ addPass(createMipsOs16(getMipsTargetMachine()));
+}
// Install an instruction selector pass using
// the ISelDag to gen Mips code.
bool MipsPassConfig::addInstSelector() {
- addPass(createMipsISelDag(getMipsTargetMachine()));
+ if (getMipsSubtarget().allowMixed16_32()) {
+ addPass(createMipsModuleISelDag(getMipsTargetMachine()));
+ addPass(createMips16ISelDag(getMipsTargetMachine()));
+ addPass(createMipsSEISelDag(getMipsTargetMachine()));
+ } else {
+ addPass(createMipsISelDag(getMipsTargetMachine()));
+ }
return false;
}
+void MipsTargetMachine::addAnalysisPasses(PassManagerBase &PM) {
+ if (Subtarget.allowMixed16_32()) {
+ DEBUG(errs() << "No ");
+ //FIXME: The Basic Target Transform Info
+ // pass needs to become a function pass instead of
+ // being an immutable pass and then this method as it exists now
+ // would be unnecessary.
+ PM.add(createNoTargetTransformInfoPass());
+ } else
+ LLVMTargetMachine::addAnalysisPasses(PM);
+ DEBUG(errs() << "Target Transform Info Pass Added\n");
+}
+
// Implemented by targets that want to run passes immediately before
// machine code is emitted. return true if -print-machineinstrs should
// print out the code after the passes.
bool MipsPassConfig::addPreEmitPass() {
MipsTargetMachine &TM = getMipsTargetMachine();
+ const MipsSubtarget &Subtarget = TM.getSubtarget<MipsSubtarget>();
addPass(createMipsDelaySlotFillerPass(TM));
- // NOTE: long branch has not been implemented for mips16.
- if (TM.getSubtarget<MipsSubtarget>().hasStandardEncoding())
+ if (Subtarget.hasStandardEncoding() ||
+ Subtarget.allowMixed16_32())
addPass(createMipsLongBranchPass(TM));
- if (TM.getSubtarget<MipsSubtarget>().inMips16Mode())
+ if (Subtarget.inMips16Mode() ||
+ Subtarget.allowMixed16_32())
addPass(createMipsConstantIslandPass(TM));
return true;
diff --git a/lib/Target/Mips/MipsTargetMachine.h b/lib/Target/Mips/MipsTargetMachine.h
index 7e5f192..ee55708 100644
--- a/lib/Target/Mips/MipsTargetMachine.h
+++ b/lib/Target/Mips/MipsTargetMachine.h
@@ -21,6 +21,8 @@
#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"
#include "llvm/Target/TargetFrameLowering.h"
#include "llvm/Target/TargetMachine.h"
@@ -35,6 +37,12 @@ class MipsTargetMachine : public LLVMTargetMachine {
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;
MipsSelectionDAGInfo TSInfo;
MipsJITInfo JITInfo;
@@ -47,6 +55,8 @@ public:
virtual ~MipsTargetMachine() {}
+ virtual void addAnalysisPasses(PassManagerBase &PM);
+
virtual const MipsInstrInfo *getInstrInfo() const
{ return InstrInfo.get(); }
virtual const TargetFrameLowering *getFrameLowering() const
@@ -73,6 +83,13 @@ public:
// Pass Pipeline Configuration
virtual TargetPassConfig *createPassConfig(PassManagerBase &PM);
virtual bool addCodeEmitter(PassManagerBase &PM, JITCodeEmitter &JCE);
+
+ // Set helper classes
+ void setHelperClassesMips16();
+
+ void setHelperClassesMipsSE();
+
+
};
/// MipsebTargetMachine - Mips32/64 big endian target machine.