summaryrefslogtreecommitdiff
path: root/lib/Target/Mips
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/Mips')
-rw-r--r--lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp8
-rw-r--r--lib/Target/Mips/Mips16HardFloat.cpp277
-rw-r--r--lib/Target/Mips/Mips16InstrInfo.cpp4
-rw-r--r--lib/Target/Mips/Mips16InstrInfo.h4
-rw-r--r--lib/Target/Mips/MipsInstrFPU.td14
-rw-r--r--lib/Target/Mips/MipsInstrInfo.cpp23
-rw-r--r--lib/Target/Mips/MipsInstrInfo.h10
-rw-r--r--lib/Target/Mips/MipsInstrInfo.td3
-rw-r--r--lib/Target/Mips/MipsLongBranch.cpp2
-rw-r--r--lib/Target/Mips/MipsSEInstrInfo.cpp84
-rw-r--r--lib/Target/Mips/MipsSEInstrInfo.h15
-rw-r--r--lib/Target/Mips/MipsTargetMachine.cpp1
12 files changed, 407 insertions, 38 deletions
diff --git a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
index 26694ffdac..837fabee76 100644
--- a/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
+++ b/lib/Target/Mips/MCTargetDesc/MipsMCTargetDesc.cpp
@@ -93,12 +93,12 @@ static MCSubtargetInfo *createMipsMCSubtargetInfo(StringRef TT, StringRef CPU,
return X;
}
-static MCAsmInfo *createMipsMCAsmInfo(StringRef TT) {
+static MCAsmInfo *createMipsMCAsmInfo(const MCRegisterInfo &MRI, StringRef TT) {
MCAsmInfo *MAI = new MipsMCAsmInfo(TT);
- MachineLocation Dst(MachineLocation::VirtualFP);
- MachineLocation Src(Mips::SP, 0);
- MAI->addInitialFrameState(0, Dst, Src);
+ unsigned SP = MRI.getDwarfRegNum(Mips::SP, true);
+ MCCFIInstruction Inst = MCCFIInstruction::createDefCfa(0, SP, 0);
+ MAI->addInitialFrameState(Inst);
return MAI;
}
diff --git a/lib/Target/Mips/Mips16HardFloat.cpp b/lib/Target/Mips/Mips16HardFloat.cpp
index 4d1e61bb99..cc7324f26e 100644
--- a/lib/Target/Mips/Mips16HardFloat.cpp
+++ b/lib/Target/Mips/Mips16HardFloat.cpp
@@ -18,6 +18,36 @@
#include "llvm/Support/raw_ostream.h"
#include <string>
+static void inlineAsmOut
+ (LLVMContext &C, StringRef AsmString, BasicBlock *BB ) {
+ std::vector<llvm::Type *> AsmArgTypes;
+ std::vector<llvm::Value*> AsmArgs;
+ llvm::FunctionType *AsmFTy =
+ llvm::FunctionType::get(Type::getVoidTy(C),
+ AsmArgTypes, false);
+ llvm::InlineAsm *IA =
+ llvm::InlineAsm::get(AsmFTy, AsmString, "", true,
+ /* IsAlignStack */ false,
+ llvm::InlineAsm::AD_ATT);
+ CallInst::Create(IA, AsmArgs, "", BB);
+}
+
+namespace {
+
+class InlineAsmHelper {
+ LLVMContext &C;
+ BasicBlock *BB;
+public:
+ InlineAsmHelper(LLVMContext &C_, BasicBlock *BB_) :
+ C(C_), BB(BB_) {
+ }
+
+ void Out(StringRef AsmString) {
+ inlineAsmOut(C, AsmString, BB);
+ }
+
+};
+}
//
// Return types that matter for hard float are:
// float, double, complex float, and complex double
@@ -52,6 +82,243 @@ static FPReturnVariant whichFPReturnVariant(Type *T) {
}
//
+// Parameter type that matter are float, (float, float), (float, double),
+// double, (double, double), (double, float)
+//
+enum FPParamVariant {
+ FSig, FFSig, FDSig,
+ DSig, DDSig, DFSig, NoSig
+};
+
+// which floating point parameter signature variant we are dealing with
+//
+typedef Type::TypeID TypeID;
+const Type::TypeID FloatTyID = Type::FloatTyID;
+const Type::TypeID DoubleTyID = Type::DoubleTyID;
+
+static FPParamVariant whichFPParamVariantNeeded(Function &F) {
+ switch (F.arg_size()) {
+ case 0:
+ return NoSig;
+ case 1:{
+ TypeID ArgTypeID = F.getFunctionType()->getParamType(0)->getTypeID();
+ switch (ArgTypeID) {
+ case FloatTyID:
+ return FSig;
+ case DoubleTyID:
+ return DSig;
+ default:
+ return NoSig;
+ }
+ }
+ default: {
+ TypeID ArgTypeID0 = F.getFunctionType()->getParamType(0)->getTypeID();
+ TypeID ArgTypeID1 = F.getFunctionType()->getParamType(1)->getTypeID();
+ switch(ArgTypeID0) {
+ case FloatTyID: {
+ switch (ArgTypeID1) {
+ case FloatTyID:
+ return FFSig;
+ case DoubleTyID:
+ return FDSig;
+ default:
+ return FSig;
+ }
+ }
+ case DoubleTyID: {
+ switch (ArgTypeID1) {
+ case FloatTyID:
+ return DFSig;
+ case DoubleTyID:
+ return DDSig;
+ default:
+ return DSig;
+ }
+ }
+ default:
+ return NoSig;
+ }
+ }
+ }
+ llvm_unreachable("can't get here");
+}
+
+// Figure out if we need float point based on the function parameters.
+// We need to move variables in and/or out of floating point
+// registers because of the ABI
+//
+static bool needsFPStubFromParams(Function &F) {
+ if (F.arg_size() >=1) {
+ Type *ArgType = F.getFunctionType()->getParamType(0);
+ switch (ArgType->getTypeID()) {
+ case Type::FloatTyID:
+ case Type::DoubleTyID:
+ return true;
+ default:
+ break;
+ }
+ }
+ return false;
+}
+
+static bool needsFPReturnHelper(Function &F) {
+ Type* RetType = F.getReturnType();
+ return whichFPReturnVariant(RetType) != NoFPRet;
+}
+
+static bool needsFPHelperFromSig(Function &F) {
+ return needsFPStubFromParams(F) || needsFPReturnHelper(F);
+}
+
+//
+// We swap between FP and Integer registers to allow Mips16 and Mips32 to
+// interoperate
+//
+
+static void swapFPIntParams
+ (FPParamVariant PV, Module *M, InlineAsmHelper &IAH,
+ bool LE, bool ToFP) {
+ //LLVMContext &Context = M->getContext();
+ std::string MI = ToFP? "mtc1 ": "mfc1 ";
+ switch (PV) {
+ case FSig:
+ IAH.Out(MI + "$$4,$$f12");
+ break;
+ case FFSig:
+ IAH.Out(MI +"$$4,$$f12");
+ IAH.Out(MI + "$$5,$$f14");
+ break;
+ case FDSig:
+ IAH.Out(MI + "$$4,$$f12");
+ if (LE) {
+ IAH.Out(MI + "$$6,$$f14");
+ IAH.Out(MI + "$$7,$$f15");
+ } else {
+ IAH.Out(MI + "$$7,$$f14");
+ IAH.Out(MI + "$$6,$$f15");
+ }
+ break;
+ case DSig:
+ if (LE) {
+ IAH.Out(MI + "$$4,$$f12");
+ IAH.Out(MI + "$$5,$$f13");
+ } else {
+ IAH.Out(MI + "$$5,$$f12");
+ IAH.Out(MI + "$$4,$$f13");
+ }
+ break;
+ case DDSig:
+ if (LE) {
+ IAH.Out(MI + "$$4,$$f12");
+ IAH.Out(MI + "$$5,$$f13");
+ IAH.Out(MI + "$$6,$$f14");
+ IAH.Out(MI + "$$7,$$f15");
+ } else {
+ IAH.Out(MI + "$$5,$$f12");
+ IAH.Out(MI + "$$4,$$f13");
+ IAH.Out(MI + "$$7,$$f14");
+ IAH.Out(MI + "$$6,$$f15");
+ }
+ break;
+ case DFSig:
+ if (LE) {
+ IAH.Out(MI + "$$4,$$f12");
+ IAH.Out(MI + "$$5,$$f13");
+ } else {
+ IAH.Out(MI + "$$5,$$f12");
+ IAH.Out(MI + "$$4,$$f13");
+ }
+ IAH.Out(MI + "$$6,$$f14");
+ break;
+ case NoSig:
+ return;
+ }
+}
+//
+// Make sure that we know we already need a stub for this function.
+// Having called needsFPHelperFromSig
+//
+static void assureFPCallStub(Function &F, Module *M,
+ const MipsSubtarget &Subtarget){
+ // for now we only need them for static relocation
+ if (Subtarget.getRelocationModel() == Reloc::PIC_)
+ return;
+ LLVMContext &Context = M->getContext();
+ bool LE = Subtarget.isLittle();
+ std::string Name = F.getName();
+ std::string SectionName = ".mips16.call.fp." + Name;
+ std::string StubName = "__call_stub_" + Name;
+ //
+ // see if we already have the stub
+ //
+ Function *FStub = M->getFunction(StubName);
+ if (FStub && !FStub->isDeclaration()) return;
+ FStub = Function::Create(F.getFunctionType(),
+ Function::InternalLinkage, StubName, M);
+ FStub->addFnAttr("mips16_fp_stub");
+ FStub->addFnAttr(llvm::Attribute::Naked);
+ FStub->addFnAttr(llvm::Attribute::NoUnwind);
+ FStub->addFnAttr("nomips16");
+ FStub->setSection(SectionName);
+ BasicBlock *BB = BasicBlock::Create(Context, "entry", FStub);
+ InlineAsmHelper IAH(Context, BB);
+ FPReturnVariant RV = whichFPReturnVariant(FStub->getReturnType());
+ FPParamVariant PV = whichFPParamVariantNeeded(F);
+ swapFPIntParams(PV, M, IAH, LE, true);
+ if (RV != NoFPRet) {
+ IAH.Out("move $$18, $$31");
+ IAH.Out("jal " + Name);
+ } else {
+ IAH.Out("lui $$25,%hi(" + Name + ")");
+ IAH.Out("addiu $$25,$$25,%lo(" + Name + ")" );
+ }
+ switch (RV) {
+ case FRet:
+ IAH.Out("mfc1 $$2,$$f0");
+ break;
+ case DRet:
+ if (LE) {
+ IAH.Out("mfc1 $$2,$$f0");
+ IAH.Out("mfc1 $$3,$$f1");
+ } else {
+ IAH.Out("mfc1 $$3,$$f0");
+ IAH.Out("mfc1 $$2,$$f1");
+ }
+ break;
+ case CFRet:
+ if (LE) {
+ IAH.Out("mfc1 $$2,$$f0");
+ IAH.Out("mfc1 $$3,$$f2");
+ } else {
+ IAH.Out("mfc1 $$3,$$f0");
+ IAH.Out("mfc1 $$3,$$f2");
+ }
+ break;
+ case CDRet:
+ if (LE) {
+ IAH.Out("mfc1 $$4,$$f2");
+ IAH.Out("mfc1 $$5,$$f3");
+ IAH.Out("mfc1 $$2,$$f0");
+ IAH.Out("mfc1 $$3,$$f1");
+
+ } else {
+ IAH.Out("mfc1 $$5,$$f2");
+ IAH.Out("mfc1 $$4,$$f3");
+ IAH.Out("mfc1 $$3,$$f0");
+ IAH.Out("mfc1 $$2,$$f1");
+ }
+ break;
+ case NoFPRet:
+ break;
+ }
+ if (RV != NoFPRet)
+ IAH.Out("jr $$18");
+ else
+ IAH.Out("jr $$25");
+ new UnreachableInst(Context, BB);
+}
+
+//
// Returns of float, double and complex need to be handled with a helper
// function. The "AndCal" part is coming in a later patch.
//
@@ -96,6 +363,16 @@ static bool fixupFPReturnAndCall
Attribute::ReadNone);
Value *F = (M->getOrInsertFunction(Name, A, MyVoid, T, NULL));
CallInst::Create(F, Params, "", &Inst );
+ } else if (const CallInst *CI = dyn_cast<CallInst>(I)) {
+ // pic mode calls are handled by already defined
+ // helper functions
+ if (Subtarget.getRelocationModel() != Reloc::PIC_ ) {
+ Function *F_ = CI->getCalledFunction();
+ if (F_ && needsFPHelperFromSig(*F_)) {
+ assureFPCallStub(*F_, M, Subtarget);
+ Modified=true;
+ }
+ }
}
}
return Modified;
diff --git a/lib/Target/Mips/Mips16InstrInfo.cpp b/lib/Target/Mips/Mips16InstrInfo.cpp
index 17dd2c0796..ab9e62703b 100644
--- a/lib/Target/Mips/Mips16InstrInfo.cpp
+++ b/lib/Target/Mips/Mips16InstrInfo.cpp
@@ -145,7 +145,7 @@ bool Mips16InstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const {
/// GetOppositeBranchOpc - Return the inverse of the specified
/// opcode, e.g. turning BEQ to BNE.
-unsigned Mips16InstrInfo::GetOppositeBranchOpc(unsigned Opc) const {
+unsigned Mips16InstrInfo::getOppositeBranchOpc(unsigned Opc) const {
switch (Opc) {
default: llvm_unreachable("Illegal opcode!");
case Mips::BeqzRxImmX16: return Mips::BnezRxImmX16;
@@ -380,7 +380,7 @@ Mips16InstrInfo::loadImmediate(unsigned FrameReg,
return Reg;
}
-unsigned Mips16InstrInfo::GetAnalyzableBrOpc(unsigned Opc) const {
+unsigned Mips16InstrInfo::getAnalyzableBrOpc(unsigned Opc) const {
return (Opc == Mips::BeqzRxImmX16 || Opc == Mips::BimmX16 ||
Opc == Mips::BnezRxImmX16 || Opc == Mips::BteqzX16 ||
Opc == Mips::BteqzT8CmpX16 || Opc == Mips::BteqzT8CmpiX16 ||
diff --git a/lib/Target/Mips/Mips16InstrInfo.h b/lib/Target/Mips/Mips16InstrInfo.h
index a77a9043bb..a3bd31e94f 100644
--- a/lib/Target/Mips/Mips16InstrInfo.h
+++ b/lib/Target/Mips/Mips16InstrInfo.h
@@ -64,7 +64,7 @@ public:
virtual bool expandPostRAPseudo(MachineBasicBlock::iterator MI) const;
- virtual unsigned GetOppositeBranchOpc(unsigned Opc) const;
+ virtual unsigned getOppositeBranchOpc(unsigned Opc) const;
// Adjust SP by FrameSize bytes. Save RA, S0, S1
void makeFrame(unsigned SP, int64_t FrameSize, MachineBasicBlock &MBB,
@@ -102,7 +102,7 @@ public:
(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, int64_t Imm) const;
private:
- virtual unsigned GetAnalyzableBrOpc(unsigned Opc) const;
+ virtual unsigned getAnalyzableBrOpc(unsigned Opc) const;
void ExpandRetRA16(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
unsigned Opc) const;
diff --git a/lib/Target/Mips/MipsInstrFPU.td b/lib/Target/Mips/MipsInstrFPU.td
index 6b23057c9c..5fa79cb159 100644
--- a/lib/Target/Mips/MipsInstrFPU.td
+++ b/lib/Target/Mips/MipsInstrFPU.td
@@ -154,6 +154,7 @@ class LW_FT<string opstr, RegisterClass RC, InstrItinClass Itin,
InstSE<(outs RC:$rt), (ins MemOpnd:$addr), !strconcat(opstr, "\t$rt, $addr"),
[(set RC:$rt, (OpNode addrDefault:$addr))], Itin, FrmFI> {
let DecoderMethod = "DecodeFMem";
+ let mayLoad = 1;
}
class SW_FT<string opstr, RegisterClass RC, InstrItinClass Itin,
@@ -161,6 +162,7 @@ class SW_FT<string opstr, RegisterClass RC, InstrItinClass Itin,
InstSE<(outs), (ins RC:$rt, MemOpnd:$addr), !strconcat(opstr, "\t$rt, $addr"),
[(OpNode RC:$rt, addrDefault:$addr)], Itin, FrmFI> {
let DecoderMethod = "DecodeFMem";
+ let mayStore = 1;
}
class MADDS_FT<string opstr, RegisterClass RC, InstrItinClass Itin,
@@ -314,8 +316,12 @@ let Predicates = [NotN64, HasMips64, HasStdEnc],
}
let Predicates = [NotN64, NotMips64, HasStdEnc] in {
- def LDC1 : LW_FT<"ldc1", AFGR64, IILoad, mem, load>, LW_FM<0x35>;
- def SDC1 : SW_FT<"sdc1", AFGR64, IIStore, mem, store>, LW_FM<0x3d>;
+ let isPseudo = 1, isCodeGenOnly = 1 in {
+ def PseudoLDC1 : LW_FT<"", AFGR64, IILoad, mem, load>;
+ def PseudoSDC1 : SW_FT<"", AFGR64, IIStore, mem, store>;
+ }
+ def LDC1 : LW_FT<"ldc1", AFGR64, IILoad, mem>, LW_FM<0x35>;
+ def SDC1 : SW_FT<"sdc1", AFGR64, IIStore, mem>, LW_FM<0x3d>;
}
// Indexed loads and stores.
@@ -523,7 +529,7 @@ let AddedComplexity = 40 in {
}
let Predicates = [NotN64, NotMips64, HasStdEnc] in {
- def : LoadRegImmPat<LDC1, f64, load>;
- def : StoreRegImmPat<SDC1, f64>;
+ def : LoadRegImmPat<PseudoLDC1, f64, load>;
+ def : StoreRegImmPat<PseudoSDC1, f64>;
}
}
diff --git a/lib/Target/Mips/MipsInstrInfo.cpp b/lib/Target/Mips/MipsInstrInfo.cpp
index ad92d41209..3144daebd7 100644
--- a/lib/Target/Mips/MipsInstrInfo.cpp
+++ b/lib/Target/Mips/MipsInstrInfo.cpp
@@ -77,7 +77,7 @@ MipsInstrInfo::emitFrameIndexDebugValue(MachineFunction &MF, int FrameIx,
void MipsInstrInfo::AnalyzeCondBr(const MachineInstr *Inst, unsigned Opc,
MachineBasicBlock *&BB,
SmallVectorImpl<MachineOperand> &Cond) const {
- assert(GetAnalyzableBrOpc(Opc) && "Not an analyzable branch");
+ assert(getAnalyzableBrOpc(Opc) && "Not an analyzable branch");
int NumOp = Inst->getNumExplicitOperands();
// for both int and fp branches, the last explicit operand is the
@@ -167,7 +167,7 @@ RemoveBranch(MachineBasicBlock &MBB) const
// Up to 2 branches are removed.
// Note that indirect branches are not removed.
for(removed = 0; I != REnd && removed < 2; ++I, ++removed)
- if (!GetAnalyzableBrOpc(I->getOpcode()))
+ if (!getAnalyzableBrOpc(I->getOpcode()))
break;
MBB.erase(I.base(), FirstBr.base());
@@ -182,7 +182,7 @@ ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const
{
assert( (Cond.size() && Cond.size() <= 3) &&
"Invalid Mips branch condition!");
- Cond[0].setImm(GetOppositeBranchOpc(Cond[0].getImm()));
+ Cond[0].setImm(getOppositeBranchOpc(Cond[0].getImm()));
return false;
}
@@ -210,7 +210,7 @@ AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
BranchInstrs.push_back(LastInst);
// Not an analyzable branch (e.g., indirect jump).
- if (!GetAnalyzableBrOpc(LastOpc))
+ if (!getAnalyzableBrOpc(LastOpc))
return LastInst->isIndirectBranch() ? BT_Indirect : BT_None;
// Get the second to last instruction in the block.
@@ -219,7 +219,7 @@ AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB,
if (++I != REnd) {
SecondLastInst = &*I;
- SecondLastOpc = GetAnalyzableBrOpc(SecondLastInst->getOpcode());
+ SecondLastOpc = getAnalyzableBrOpc(SecondLastInst->getOpcode());
// Not an analyzable branch (must be an indirect jump).
if (isUnpredicatedTerminator(SecondLastInst) && !SecondLastOpc)
@@ -282,3 +282,16 @@ unsigned MipsInstrInfo::GetInstSizeInBytes(const MachineInstr *MI) const {
}
}
}
+
+MachineInstrBuilder
+MipsInstrInfo::genInstrWithNewOpc(unsigned NewOpc,
+ MachineBasicBlock::iterator I) const {
+ MachineInstrBuilder MIB;
+ MIB = BuildMI(*I->getParent(), I, I->getDebugLoc(), get(NewOpc));
+
+ for (unsigned J = 0, E = I->getDesc().getNumOperands(); J < E; ++J)
+ MIB.addOperand(I->getOperand(J));
+
+ MIB.setMemRefs(I->memoperands_begin(), I->memoperands_end());
+ return MIB;
+}
diff --git a/lib/Target/Mips/MipsInstrInfo.h b/lib/Target/Mips/MipsInstrInfo.h
index 8c05d97bea..0f075ec6d0 100644
--- a/lib/Target/Mips/MipsInstrInfo.h
+++ b/lib/Target/Mips/MipsInstrInfo.h
@@ -17,6 +17,7 @@
#include "Mips.h"
#include "MipsAnalyzeImmediate.h"
#include "MipsRegisterInfo.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Target/TargetInstrInfo.h"
@@ -81,7 +82,7 @@ public:
///
virtual const MipsRegisterInfo &getRegisterInfo() const = 0;
- virtual unsigned GetOppositeBranchOpc(unsigned Opc) const = 0;
+ virtual unsigned getOppositeBranchOpc(unsigned Opc) const = 0;
/// Return the number of bytes of code the specified instruction may be.
unsigned GetInstSizeInBytes(const MachineInstr *MI) const;
@@ -116,6 +117,11 @@ public:
const TargetRegisterInfo *TRI,
int64_t Offset) const = 0;
+ /// Create an instruction which has the same operands and memory operands
+ /// as MI but has a new opcode.
+ MachineInstrBuilder genInstrWithNewOpc(unsigned NewOpc,
+ MachineBasicBlock::iterator I) const;
+
protected:
bool isZeroImm(const MachineOperand &op) const;
@@ -123,7 +129,7 @@ protected:
unsigned Flag) const;
private:
- virtual unsigned GetAnalyzableBrOpc(unsigned Opc) const = 0;
+ virtual unsigned getAnalyzableBrOpc(unsigned Opc) const = 0;
void AnalyzeCondBr(const MachineInstr *Inst, unsigned Opc,
MachineBasicBlock *&BB,
diff --git a/lib/Target/Mips/MipsInstrInfo.td b/lib/Target/Mips/MipsInstrInfo.td
index 3d319373fe..5ada1df267 100644
--- a/lib/Target/Mips/MipsInstrInfo.td
+++ b/lib/Target/Mips/MipsInstrInfo.td
@@ -1095,7 +1095,8 @@ def : InstAlias<"mfc2 $rt, $rd",
(MFC2_3OP CPURegsOpnd:$rt, CPURegsOpnd:$rd, 0), 0>;
def : InstAlias<"mtc2 $rt, $rd",
(MTC2_3OP CPURegsOpnd:$rd, 0, CPURegsOpnd:$rt), 0>;
-
+def : InstAlias<"addiu $rs, $imm",
+ (ADDiu CPURegsOpnd:$rs, CPURegsOpnd:$rs, simm16:$imm), 0>;
//===----------------------------------------------------------------------===//
// Assembler Pseudo Instructions
//===----------------------------------------------------------------------===//
diff --git a/lib/Target/Mips/MipsLongBranch.cpp b/lib/Target/Mips/MipsLongBranch.cpp
index bf5ad37031..daabf3d25a 100644
--- a/lib/Target/Mips/MipsLongBranch.cpp
+++ b/lib/Target/Mips/MipsLongBranch.cpp
@@ -217,7 +217,7 @@ int64_t MipsLongBranch::computeOffset(const MachineInstr *Br) {
// MachineBasicBlock operand MBBOpnd.
void MipsLongBranch::replaceBranch(MachineBasicBlock &MBB, Iter Br,
DebugLoc DL, MachineBasicBlock *MBBOpnd) {
- unsigned NewOpc = TII->GetOppositeBranchOpc(Br->getOpcode());
+ unsigned NewOpc = TII->getOppositeBranchOpc(Br->getOpcode());
const MCInstrDesc &NewDesc = TII->get(NewOpc);
MachineInstrBuilder MIB = BuildMI(MBB, Br, DL, NewDesc);
diff --git a/lib/Target/Mips/MipsSEInstrInfo.cpp b/lib/Target/Mips/MipsSEInstrInfo.cpp
index a0768e51c0..12ed1bc186 100644
--- a/lib/Target/Mips/MipsSEInstrInfo.cpp
+++ b/lib/Target/Mips/MipsSEInstrInfo.cpp
@@ -18,11 +18,17 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
+static cl::opt<bool> NoDPLoadStore("mno-ldc1-sdc1", cl::init(false),
+ cl::desc("Expand double precision loads and "
+ "stores to their single precision "
+ "counterparts."));
+
MipsSEInstrInfo::MipsSEInstrInfo(MipsTargetMachine &tm)
: MipsInstrInfo(tm,
tm.getRelocationModel() == Reloc::PIC_ ? Mips::B : Mips::J),
@@ -245,17 +251,23 @@ bool MipsSEInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const {
default:
return false;
case Mips::RetRA:
- ExpandRetRA(MBB, MI, Mips::RET);
+ expandRetRA(MBB, MI, Mips::RET);
break;
case Mips::BuildPairF64:
- ExpandBuildPairF64(MBB, MI);
+ expandBuildPairF64(MBB, MI);
break;
case Mips::ExtractElementF64:
- ExpandExtractElementF64(MBB, MI);
+ expandExtractElementF64(MBB, MI);
+ break;
+ case Mips::PseudoLDC1:
+ expandDPLoadStore(MBB, MI, Mips::LDC1, Mips::LWC1);
+ break;
+ case Mips::PseudoSDC1:
+ expandDPLoadStore(MBB, MI, Mips::SDC1, Mips::SWC1);
break;
case Mips::MIPSeh_return32:
case Mips::MIPSeh_return64:
- ExpandEhReturn(MBB, MI);
+ expandEhReturn(MBB, MI);
break;
}
@@ -263,9 +275,9 @@ bool MipsSEInstrInfo::expandPostRAPseudo(MachineBasicBlock::iterator MI) const {
return true;
}
-/// GetOppositeBranchOpc - Return the inverse of the specified
+/// getOppositeBranchOpc - Return the inverse of the specified
/// opcode, e.g. turning BEQ to BNE.
-unsigned MipsSEInstrInfo::GetOppositeBranchOpc(unsigned Opc) const {
+unsigned MipsSEInstrInfo::getOppositeBranchOpc(unsigned Opc) const {
switch (Opc) {
default: llvm_unreachable("Illegal opcode!");
case Mips::BEQ: return Mips::BNE;
@@ -346,7 +358,7 @@ MipsSEInstrInfo::loadImmediate(int64_t Imm, MachineBasicBlock &MBB,
return Reg;
}
-unsigned MipsSEInstrInfo::GetAnalyzableBrOpc(unsigned Opc) const {
+unsigned MipsSEInstrInfo::getAnalyzableBrOpc(unsigned Opc) const {
return (Opc == Mips::BEQ || Opc == Mips::BNE || Opc == Mips::BGTZ ||
Opc == Mips::BGEZ || Opc == Mips::BLTZ || Opc == Mips::BLEZ ||
Opc == Mips::BEQ64 || Opc == Mips::BNE64 || Opc == Mips::BGTZ64 ||
@@ -356,13 +368,13 @@ unsigned MipsSEInstrInfo::GetAnalyzableBrOpc(unsigned Opc) const {
Opc : 0;
}
-void MipsSEInstrInfo::ExpandRetRA(MachineBasicBlock &MBB,
+void MipsSEInstrInfo::expandRetRA(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I,
unsigned Opc) const {
BuildMI(MBB, I, I->getDebugLoc(), get(Opc)).addReg(Mips::RA);
}
-void MipsSEInstrInfo::ExpandExtractElementF64(MachineBasicBlock &MBB,
+void MipsSEInstrInfo::expandExtractElementF64(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const {
unsigned DstReg = I->getOperand(0).getReg();
unsigned SrcReg = I->getOperand(1).getReg();
@@ -377,7 +389,7 @@ void MipsSEInstrInfo::ExpandExtractElementF64(MachineBasicBlock &MBB,
BuildMI(MBB, I, dl, Mfc1Tdd, DstReg).addReg(SubReg);
}
-void MipsSEInstrInfo::ExpandBuildPairF64(MachineBasicBlock &MBB,
+void MipsSEInstrInfo::expandBuildPairF64(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const {
unsigned DstReg = I->getOperand(0).getReg();
unsigned LoReg = I->getOperand(1).getReg(), HiReg = I->getOperand(2).getReg();
@@ -393,7 +405,57 @@ void MipsSEInstrInfo::ExpandBuildPairF64(MachineBasicBlock &MBB,
.addReg(HiReg);
}
-void MipsSEInstrInfo::ExpandEhReturn(MachineBasicBlock &MBB,
+/// Add 4 to the displacement of operand MO.
+static void fixDisp(MachineOperand &MO) {
+ switch (MO.getType()) {
+ default:
+ llvm_unreachable("Unhandled operand type.");
+ case MachineOperand::MO_Immediate:
+ MO.setImm(MO.getImm() + 4);
+ break;
+ case MachineOperand::MO_GlobalAddress:
+ case MachineOperand::MO_ConstantPoolIndex:
+ case MachineOperand::MO_BlockAddress:
+ case MachineOperand::MO_TargetIndex:
+ case MachineOperand::MO_ExternalSymbol:
+ MO.setOffset(MO.getOffset() + 4);
+ break;
+ }
+}
+
+void MipsSEInstrInfo::expandDPLoadStore(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator I,
+ unsigned OpcD, unsigned OpcS) const {
+ // If NoDPLoadStore is false, just change the opcode.
+ if (!NoDPLoadStore) {
+ genInstrWithNewOpc(OpcD, I);
+ return;
+ }
+
+ // Expand a double precision FP load or store to two single precision
+ // instructions.
+
+ const TargetRegisterInfo &TRI = getRegisterInfo();
+ const MachineOperand &ValReg = I->getOperand(0);
+ unsigned LoReg = TRI.getSubReg(ValReg.getReg(), Mips::sub_fpeven);
+ unsigned HiReg = TRI.getSubReg(ValReg.getReg(), Mips::sub_fpodd);
+
+ if (!TM.getSubtarget<MipsSubtarget>().isLittle())
+ std::swap(LoReg, HiReg);
+
+ // Create an instruction which loads from or stores to the lower memory
+ // address.
+ MachineInstrBuilder MIB = genInstrWithNewOpc(OpcS, I);
+ MIB->getOperand(0).setReg(LoReg);
+
+ // Create an instruction which loads from or stores to the higher memory
+ // address.
+ MIB = genInstrWithNewOpc(OpcS, I);
+ MIB->getOperand(0).setReg(HiReg);
+ fixDisp(MIB->getOperand(2));
+}
+
+void MipsSEInstrInfo::expandEhReturn(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const {
// This pseudo instruction is generated as part of the lowering of
// ISD::EH_RETURN. We convert it to a stack increment by OffsetReg, and
diff --git a/lib/Target/Mips/MipsSEInstrInfo.h b/lib/Target/Mips/MipsSEInstrInfo.h
index 0bf7876f0f..416fff8a60 100644
--- a/lib/Target/Mips/MipsSEInstrInfo.h
+++ b/lib/Target/Mips/MipsSEInstrInfo.h
@@ -65,7 +65,7 @@ public:
virtual bool expandPostRAPseudo(MachineBasicBlock::iterator MI) const;
- virtual unsigned GetOppositeBranchOpc(unsigned Opc) const;
+ virtual unsigned getOppositeBranchOpc(unsigned Opc) const;
/// Adjust SP by Amount bytes.
void adjustStackPtr(unsigned SP, int64_t Amount, MachineBasicBlock &MBB,
@@ -79,15 +79,18 @@ public:
unsigned *NewImm) const;
private:
- virtual unsigned GetAnalyzableBrOpc(unsigned Opc) const;
+ virtual unsigned getAnalyzableBrOpc(unsigned Opc) const;
- void ExpandRetRA(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
+ void expandRetRA(MachineBasicBlock &MBB, MachineBasicBlock::iterator I,
unsigned Opc) const;
- void ExpandExtractElementF64(MachineBasicBlock &MBB,
+ void expandExtractElementF64(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const;
- void ExpandBuildPairF64(MachineBasicBlock &MBB,
+ void expandBuildPairF64(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const;
- void ExpandEhReturn(MachineBasicBlock &MBB,
+ void expandDPLoadStore(MachineBasicBlock &MBB,
+ MachineBasicBlock::iterator I, unsigned OpcD,
+ unsigned OpcS) const;
+ void expandEhReturn(MachineBasicBlock &MBB,
MachineBasicBlock::iterator I) const;
};
diff --git a/lib/Target/Mips/MipsTargetMachine.cpp b/lib/Target/Mips/MipsTargetMachine.cpp
index a876f1c7f0..89407351a0 100644
--- a/lib/Target/Mips/MipsTargetMachine.cpp
+++ b/lib/Target/Mips/MipsTargetMachine.cpp
@@ -72,6 +72,7 @@ MipsTargetMachine(const Target &T, StringRef TT,
FrameLowering(MipsFrameLowering::create(*this, Subtarget)),
TLInfo(MipsTargetLowering::create(*this)),
TSInfo(*this), JITInfo() {
+ initAsmInfo();
}