mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 11:42:57 +01:00
Added support for PIC code with "explicit relocations" *only*.
Removed all macro code for PIC (goodbye "la"). Support tested with shootout bench. llvm-svn: 43697
This commit is contained in:
parent
314e68f58f
commit
569b5512b0
@ -250,7 +250,7 @@ emitFunctionStart(MachineFunction &MF)
|
||||
emitMaskDirective(MF);
|
||||
emitFMaskDirective(MF);
|
||||
|
||||
if (MF.getTarget().getRelocationModel() == Reloc::Static) {
|
||||
if (TM.getRelocationModel() == Reloc::Static) {
|
||||
emitSetDirective(NOREORDER);
|
||||
emitSetDirective(NOMACRO);
|
||||
}
|
||||
@ -262,7 +262,7 @@ emitFunctionStart(MachineFunction &MF)
|
||||
void MipsAsmPrinter::
|
||||
emitFunctionEnd(MachineFunction &MF)
|
||||
{
|
||||
if (MF.getTarget().getRelocationModel() == Reloc::Static) {
|
||||
if (TM.getRelocationModel() == Reloc::Static) {
|
||||
emitSetDirective(MACRO);
|
||||
emitSetDirective(REORDER);
|
||||
}
|
||||
@ -305,6 +305,9 @@ runOnMachineFunction(MachineFunction &MF)
|
||||
printInstruction(II);
|
||||
++EmittedInsts;
|
||||
}
|
||||
|
||||
// Each Basic Block is separated by a newline
|
||||
O << '\n';
|
||||
}
|
||||
|
||||
// Emit function end directives
|
||||
@ -319,17 +322,41 @@ printOperand(const MachineInstr *MI, int opNum)
|
||||
{
|
||||
const MachineOperand &MO = MI->getOperand(opNum);
|
||||
const MRegisterInfo &RI = *TM.getRegisterInfo();
|
||||
bool closeP=false;
|
||||
bool closeP = false;
|
||||
bool isPIC = (TM.getRelocationModel() == Reloc::PIC_);
|
||||
bool isCodeLarge = (TM.getCodeModel() == CodeModel::Large);
|
||||
|
||||
// %hi and %lo used on mips gas to break large constants
|
||||
// %hi and %lo used on mips gas to load global addresses on
|
||||
// static code. %got is used to load global addresses when
|
||||
// using PIC_. %call16 is used to load direct call targets
|
||||
// on PIC_ and small code size. %call_lo and %call_hi load
|
||||
// direct call targets on PIC_ and large code size.
|
||||
if (MI->getOpcode() == Mips::LUi && !MO.isRegister()
|
||||
&& !MO.isImmediate()) {
|
||||
O << "%hi(";
|
||||
if ((isPIC) && (isCodeLarge))
|
||||
O << "%call_hi(";
|
||||
else
|
||||
O << "%hi(";
|
||||
closeP = true;
|
||||
} else if ((MI->getOpcode() == Mips::ADDiu) && !MO.isRegister()
|
||||
&& !MO.isImmediate()) {
|
||||
O << "%lo(";
|
||||
closeP = true;
|
||||
} else if ((isPIC) && (MI->getOpcode() == Mips::LW)
|
||||
&& (!MO.isRegister()) && (!MO.isImmediate())) {
|
||||
const MachineOperand &firstMO = MI->getOperand(opNum-1);
|
||||
const MachineOperand &lastMO = MI->getOperand(opNum+1);
|
||||
if ((firstMO.isRegister()) && (lastMO.isRegister())) {
|
||||
if ((firstMO.getReg() == Mips::T9) && (lastMO.getReg() == Mips::GP)
|
||||
&& (!isCodeLarge))
|
||||
O << "%call16(";
|
||||
else if ((firstMO.getReg() != Mips::T9) && (lastMO.getReg() == Mips::GP))
|
||||
O << "%got(";
|
||||
else if ((firstMO.getReg() == Mips::T9) && (lastMO.getReg() != Mips::GP)
|
||||
&& (isCodeLarge))
|
||||
O << "%call_lo(";
|
||||
closeP = true;
|
||||
}
|
||||
}
|
||||
|
||||
switch (MO.getType())
|
||||
@ -361,6 +388,7 @@ printOperand(const MachineInstr *MI, int opNum)
|
||||
O << MO.getSymbolName();
|
||||
break;
|
||||
|
||||
// FIXME: Verify correct
|
||||
case MachineOperand::MO_ConstantPoolIndex:
|
||||
O << TAI->getPrivateGlobalPrefix() << "CPI"
|
||||
<< getFunctionNumber() << "_" << MO.getConstantPoolIndex();
|
||||
@ -385,7 +413,9 @@ printMemOperand(const MachineInstr *MI, int opNum, const char *Modifier)
|
||||
return;
|
||||
}
|
||||
|
||||
// Load/Store memory operands -- imm($reg)
|
||||
// Load/Store memory operands -- imm($reg)
|
||||
// If PIC target the target is loaded as the
|
||||
// pattern lw $25,%call16($28)
|
||||
printOperand(MI, opNum);
|
||||
O << "(";
|
||||
printOperand(MI, opNum+1);
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "Mips.h"
|
||||
#include "MipsISelLowering.h"
|
||||
#include "MipsMachineFunction.h"
|
||||
#include "MipsRegisterInfo.h"
|
||||
#include "MipsSubtarget.h"
|
||||
#include "MipsTargetMachine.h"
|
||||
@ -135,20 +136,24 @@ SelectAddr(SDOperand Op, SDOperand Addr, SDOperand &Offset, SDOperand &Base)
|
||||
return true;
|
||||
}
|
||||
|
||||
// TargetExternalSymbol and TargetGlobalAddress are
|
||||
// lowered and their addresses go into registers, so
|
||||
// they should not be touched here.
|
||||
if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
|
||||
Addr.getOpcode() == ISD::TargetGlobalAddress))
|
||||
return false;
|
||||
// on PIC code Load GA
|
||||
if (TM.getRelocationModel() == Reloc::PIC_) {
|
||||
if (Addr.getOpcode() == ISD::TargetGlobalAddress) {
|
||||
Base = CurDAG->getRegister(Mips::GP, MVT::i32);
|
||||
Offset = Addr;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
|
||||
Addr.getOpcode() == ISD::TargetGlobalAddress))
|
||||
return false;
|
||||
}
|
||||
|
||||
// Operand is a result from an ADD.
|
||||
if (Addr.getOpcode() == ISD::ADD)
|
||||
{
|
||||
if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1)))
|
||||
{
|
||||
if (Predicate_immSExt16(CN))
|
||||
{
|
||||
if (Addr.getOpcode() == ISD::ADD) {
|
||||
if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {
|
||||
if (Predicate_immSExt16(CN)) {
|
||||
|
||||
// If the first operand is a FI, get the TargetFI Node
|
||||
if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>
|
||||
(Addr.getOperand(0))) {
|
||||
@ -247,6 +252,51 @@ Select(SDOperand N)
|
||||
SDOperand MFInFlag = SDOperand(RemNode, 0);
|
||||
return CurDAG->getTargetNode(Mips::MFHI, MVT::i32, MFInFlag);
|
||||
}
|
||||
|
||||
/// Handle direct and indirect calls when using PIC. On PIC, when
|
||||
/// GOT is smaller than about 64k (small code) the GA target is
|
||||
/// loaded with only one instruction. Otherwise GA's target must
|
||||
/// be loaded with 3 instructions.
|
||||
case MipsISD::JmpLink: {
|
||||
if (TM.getRelocationModel() == Reloc::PIC_) {
|
||||
//bool isCodeLarge = (TM.getCodeModel() == CodeModel::Large);
|
||||
SDOperand Chain = Node->getOperand(0);
|
||||
SDOperand Callee = Node->getOperand(1);
|
||||
AddToISelQueue(Chain);
|
||||
SDOperand T9Reg = CurDAG->getRegister(Mips::T9, MVT::i32);
|
||||
SDOperand InFlag(0, 0);
|
||||
|
||||
if ( (isa<GlobalAddressSDNode>(Callee)) ||
|
||||
(isa<ExternalSymbolSDNode>(Callee)) )
|
||||
{
|
||||
/// Direct call for global addresses and external symbols
|
||||
SDOperand GPReg = CurDAG->getRegister(Mips::GP, MVT::i32);
|
||||
|
||||
// Use load to get GOT target
|
||||
SDOperand Ops[] = { Callee, GPReg, Chain };
|
||||
SDOperand Load = SDOperand(CurDAG->getTargetNode(Mips::LW, MVT::i32,
|
||||
MVT::Other, Ops, 3), 0);
|
||||
Chain = Load.getValue(1);
|
||||
AddToISelQueue(Chain);
|
||||
|
||||
// Call target must be on T9
|
||||
Chain = CurDAG->getCopyToReg(Chain, T9Reg, Load, InFlag);
|
||||
} else
|
||||
/// Indirect call
|
||||
Chain = CurDAG->getCopyToReg(Chain, T9Reg, Callee, InFlag);
|
||||
|
||||
AddToISelQueue(Chain);
|
||||
|
||||
// Emit Jump and Link Register
|
||||
SDNode *ResNode = CurDAG->getTargetNode(Mips::JALR, MVT::Other,
|
||||
MVT::Flag, T9Reg, Chain);
|
||||
Chain = SDOperand(ResNode, 0);
|
||||
InFlag = SDOperand(ResNode, 1);
|
||||
ReplaceUses(SDOperand(Node, 0), Chain);
|
||||
ReplaceUses(SDOperand(Node, 1), InFlag);
|
||||
return ResNode;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Select the default instruction
|
||||
|
@ -39,13 +39,11 @@ getTargetNodeName(unsigned Opcode) const
|
||||
{
|
||||
switch (Opcode)
|
||||
{
|
||||
case MipsISD::JmpLink : return "MipsISD::JmpLink";
|
||||
case MipsISD::Hi : return "MipsISD::Hi";
|
||||
case MipsISD::Lo : return "MipsISD::Lo";
|
||||
case MipsISD::Ret : return "MipsISD::Ret";
|
||||
case MipsISD::Add : return "MipsISD::Add";
|
||||
case MipsISD::LoadAddr : return "MipsISD::LoadAddr";
|
||||
default : return NULL;
|
||||
case MipsISD::JmpLink : return "MipsISD::JmpLink";
|
||||
case MipsISD::Hi : return "MipsISD::Hi";
|
||||
case MipsISD::Lo : return "MipsISD::Lo";
|
||||
case MipsISD::Ret : return "MipsISD::Ret";
|
||||
default : return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@ -149,21 +147,24 @@ LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG)
|
||||
{
|
||||
SDOperand ResNode;
|
||||
GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
|
||||
|
||||
SDOperand GA = DAG.getTargetGlobalAddress(GV, MVT::i32);
|
||||
bool isPIC = (getTargetMachine().getRelocationModel() == Reloc::PIC_);
|
||||
|
||||
// On PIC code global addresses are loaded with "la" instruction
|
||||
if (!(getTargetMachine().getRelocationModel() == Reloc::PIC_)) {
|
||||
const MVT::ValueType *VTs = DAG.getNodeValueTypes(MVT::i32, MVT::Flag);
|
||||
SDOperand HiPart;
|
||||
if (!isPIC) {
|
||||
const MVT::ValueType *VTs = DAG.getNodeValueTypes(MVT::i32);
|
||||
SDOperand Ops[] = { GA };
|
||||
HiPart = DAG.getNode(MipsISD::Hi, VTs, 1, Ops, 1);
|
||||
} else // Emit Load from Global Pointer
|
||||
HiPart = DAG.getLoad(MVT::i32, DAG.getEntryNode(), GA, NULL, 0);
|
||||
|
||||
SDOperand Hi = DAG.getNode(MipsISD::Hi, VTs, 2, Ops, 1);
|
||||
SDOperand Lo = DAG.getNode(MipsISD::Lo, MVT::i32, GA);
|
||||
// On functions and global targets not internal linked only
|
||||
// a load from got/GP is necessary for PIC to work.
|
||||
if ((isPIC) && ((!GV->hasInternalLinkage()) || (isa<Function>(GV))))
|
||||
return HiPart;
|
||||
|
||||
SDOperand InFlag = Hi.getValue(1);
|
||||
ResNode = DAG.getNode(MipsISD::Add, MVT::i32, Lo, Hi, InFlag);
|
||||
} else
|
||||
ResNode = DAG.getNode(MipsISD::LoadAddr, MVT::i32, GA);
|
||||
SDOperand Lo = DAG.getNode(MipsISD::Lo, MVT::i32, GA);
|
||||
ResNode = DAG.getNode(ISD::ADD, MVT::i32, HiPart, Lo);
|
||||
|
||||
return ResNode;
|
||||
}
|
||||
@ -211,7 +212,7 @@ LowerCALL(SDOperand Op, SelectionDAG &DAG)
|
||||
/// LowerCCCCallTo - functions arguments are copied from virtual
|
||||
/// regs to (physical regs)/(stack frame), CALLSEQ_START and
|
||||
/// CALLSEQ_END are emitted.
|
||||
/// TODO: isVarArg, isTailCall, sret, GOT, linkage types.
|
||||
/// TODO: isVarArg, isTailCall, sret.
|
||||
SDOperand MipsTargetLowering::
|
||||
LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC)
|
||||
{
|
||||
@ -244,7 +245,7 @@ LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC)
|
||||
SmallVector<SDOperand, 8> MemOpChains;
|
||||
|
||||
SDOperand StackPtr;
|
||||
unsigned LastStackLoc=0;
|
||||
int LastStackLoc=0;
|
||||
|
||||
// Walk the register/memloc assignments, inserting copies/loads.
|
||||
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
|
||||
@ -268,8 +269,8 @@ LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC)
|
||||
break;
|
||||
}
|
||||
|
||||
// Arguments that can be passed on register,
|
||||
// must be kept at RegsToPass vector
|
||||
// Arguments that can be passed on register must be kept at
|
||||
// RegsToPass vector
|
||||
if (VA.isRegLoc()) {
|
||||
RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
|
||||
} else {
|
||||
@ -294,14 +295,6 @@ LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC)
|
||||
}
|
||||
}
|
||||
|
||||
// Create a stack location to hold GP when PIC is used
|
||||
if (getTargetMachine().getRelocationModel() == Reloc::PIC_) {
|
||||
LastStackLoc = (!LastStackLoc) ? (16) : (LastStackLoc+4);
|
||||
MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
|
||||
MFI->CreateFixedObject(4, LastStackLoc);
|
||||
MipsFI->setGPStackOffset(LastStackLoc);
|
||||
}
|
||||
|
||||
// Transform all store nodes into one single node because
|
||||
// all store nodes are independent of each other.
|
||||
if (!MemOpChains.empty())
|
||||
@ -321,13 +314,13 @@ LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC)
|
||||
|
||||
// If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
|
||||
// direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
|
||||
// node so that legalize doesn't hack it. Otherwise we have an indirect call,
|
||||
// if PIC is used, the call must use register GP
|
||||
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
|
||||
// node so that legalize doesn't hack it.
|
||||
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
|
||||
Callee = DAG.getTargetGlobalAddress(G->getGlobal(), getPointerTy());
|
||||
else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
|
||||
Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy());
|
||||
|
||||
|
||||
// MipsJmpLink = #chain, #target_address, #opt_in_flags...
|
||||
// = Chain, Callee, Reg#1, Reg#2, ...
|
||||
//
|
||||
@ -349,6 +342,37 @@ LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC)
|
||||
Chain = DAG.getNode(MipsISD::JmpLink, NodeTys, &Ops[0], Ops.size());
|
||||
InFlag = Chain.getValue(1);
|
||||
|
||||
// Create a stack location to hold GP when PIC is used. This stack
|
||||
// location is used on function prologue to save GP and also after all
|
||||
// emited CALL's to restore GP.
|
||||
if (getTargetMachine().getRelocationModel() == Reloc::PIC_) {
|
||||
|
||||
// Function can have an arbitrary number of calls, so
|
||||
// hold the LastStackLoc with the biggest offset.
|
||||
int FI;
|
||||
MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
|
||||
if (LastStackLoc >= MipsFI->getGPStackOffset()) {
|
||||
|
||||
LastStackLoc = (!LastStackLoc) ? (16) : (LastStackLoc+4);
|
||||
// Create the frame index only once. SPOffset here can be anything
|
||||
// (this will be fixed on processFunctionBeforeFrameFinalized)
|
||||
if (MipsFI->getGPStackOffset() == -1) {
|
||||
FI = MFI->CreateFixedObject(4, 0);
|
||||
MipsFI->setGPFI(FI);
|
||||
}
|
||||
MipsFI->setGPStackOffset(LastStackLoc);
|
||||
}
|
||||
|
||||
|
||||
// Reload GP value.
|
||||
FI = MipsFI->getGPFI();
|
||||
SDOperand FIN = DAG.getFrameIndex(FI,getPointerTy());
|
||||
SDOperand GPLoad = DAG.getLoad(MVT::i32, Chain, FIN, NULL, 0);
|
||||
Chain = GPLoad.getValue(1);
|
||||
Chain = DAG.getCopyToReg(Chain, DAG.getRegister(Mips::GP, MVT::i32),
|
||||
GPLoad, SDOperand(0,0));
|
||||
}
|
||||
|
||||
// Create the CALLSEQ_END node.
|
||||
NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
|
||||
Ops.clear();
|
||||
@ -389,10 +413,11 @@ LowerCallResult(SDOperand Chain, SDOperand InFlag, SDNode *TheCall,
|
||||
ResultVals.push_back(Chain.getValue(0));
|
||||
}
|
||||
|
||||
// Merge everything together with a MERGE_VALUES node.
|
||||
ResultVals.push_back(Chain);
|
||||
|
||||
// Merge everything together with a MERGE_VALUES node.
|
||||
return DAG.getNode(ISD::MERGE_VALUES, TheCall->getVTList(),
|
||||
&ResultVals[0], ResultVals.size()).Val;
|
||||
&ResultVals[0], ResultVals.size()).Val;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -38,13 +38,7 @@ namespace llvm {
|
||||
Lo,
|
||||
|
||||
// Return
|
||||
Ret,
|
||||
|
||||
// Need to support addition with a input flag
|
||||
Add,
|
||||
|
||||
// Used on PIC Code to load global addresses
|
||||
LoadAddr
|
||||
Ret
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -22,20 +22,11 @@ def SDT_MipsJmpLink : SDTypeProfile<0, 1, [SDTCisVT<0, iPTR>]>;
|
||||
def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, [SDNPHasChain,
|
||||
SDNPOutFlag]>;
|
||||
|
||||
// Hi and Lo nodes are created to let easy manipulation of 16-bit when
|
||||
// handling 32-bit immediates. They are used on MipsISelLowering to
|
||||
// lower stuff like GlobalAddress, ExternalSymbol, ... on static model
|
||||
// This two nodes have nothing to do with Mips Registers Hi and Lo.
|
||||
def MipsHi : SDNode<"MipsISD::Hi", SDTIntUnaryOp, [SDNPOutFlag]>;
|
||||
def MipsLo : SDNode<"MipsISD::Lo", SDTIntUnaryOp>;
|
||||
|
||||
// Necessary to generate glued instructions when loading GlobalAddress
|
||||
// into registers.
|
||||
def MipsAdd : SDNode<"MipsISD::Add", SDTIntBinOp, [SDNPCommutative,
|
||||
SDNPAssociative, SDNPOptInFlag]>;
|
||||
|
||||
// Used to Load Addresses on PIC code.
|
||||
def MipsLoadAddr: SDNode<"MipsISD::LoadAddr", SDTIntUnaryOp>;
|
||||
// Hi and Lo nodes are used to handle global addresses. Used on
|
||||
// MipsISelLowering to lower stuff like GlobalAddress, ExternalSymbol
|
||||
// static model. (nothing to do with Mips Registers Hi and Lo)
|
||||
def MipsHi : SDNode<"MipsISD::Hi", SDTIntUnaryOp, [SDNPOutFlag]>;
|
||||
def MipsLo : SDNode<"MipsISD::Lo", SDTIntUnaryOp>;
|
||||
|
||||
// Return
|
||||
def SDT_MipsRet : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
|
||||
@ -371,15 +362,9 @@ def IMPLICIT_DEF_CPURegs : PseudoInstMips<(outs CPURegs:$dst), (ins),
|
||||
// are used, we have the same behavior, but get also a bunch of warnings
|
||||
// from the assembler.
|
||||
def CPLOAD: PseudoInstMips<(outs), (ins CPURegs:$reg),
|
||||
".set noreorder\n\t.cpload $reg\n\t.set reorder", []>;
|
||||
".set noreorder\n\t.cpload $reg\n\t.set reorder\n", []>;
|
||||
def CPRESTORE: PseudoInstMips<(outs), (ins uimm16:$loc),
|
||||
".cprestore $loc", []>;
|
||||
|
||||
// Used on PIC code only, it loads the address of label into register reg. The
|
||||
// address is calculated from the global pointer ($gp) and is expanded by the
|
||||
// assembler into two instructions "lw" and "addiu".
|
||||
def LA: PseudoInstMips<(outs CPURegs:$dst), (ins addrlabel:$label),
|
||||
"la $dst, $label", []>;
|
||||
".cprestore $loc\n", []>;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Instruction definition
|
||||
@ -393,17 +378,13 @@ def LA: PseudoInstMips<(outs CPURegs:$dst), (ins addrlabel:$label),
|
||||
|
||||
// ADDiu just accept 16-bit immediates but we handle this on Pat's.
|
||||
// immZExt32 is used here so it can match GlobalAddress immediates.
|
||||
def ADDiu : ArithI<0x09, "addiu", MipsAdd, uimm16, immZExt16>;
|
||||
def ADDiu : ArithI<0x09, "addiu", add, uimm16, immZExt16>;
|
||||
def ADDi : ArithI<0x08, "addi", add, simm16, immSExt16>;
|
||||
def MUL : ArithR<0x1c, 0x02, "mul", mul, IIImul>;
|
||||
def ADDu : ArithR<0x00, 0x21, "addu", add, IIAlu>;
|
||||
def SUBu : ArithR<0x00, 0x23, "subu", sub, IIAlu>;
|
||||
def ADD : ArithOverflowR<0x00, 0x20, "add">;
|
||||
def SUB : ArithOverflowR<0x00, 0x22, "sub">;
|
||||
def MADD : MArithR<0x00, "madd">;
|
||||
def MADDU : MArithR<0x01, "maddu">;
|
||||
def MSUB : MArithR<0x04, "msub">;
|
||||
def MSUBU : MArithR<0x05, "msubu">;
|
||||
|
||||
// Logical
|
||||
def AND : LogicR<0x24, "and", and>;
|
||||
@ -481,10 +462,16 @@ def MTLO : MoveFromTo<0x13, "mtlo">;
|
||||
// Count Leading
|
||||
// CLO/CLZ are part of the newer MIPS32(tm) instruction
|
||||
// set and not older Mips I keep this for future use
|
||||
// though.
|
||||
// though.
|
||||
//def CLO : CountLeading<0x21, "clo">;
|
||||
//def CLZ : CountLeading<0x20, "clz">;
|
||||
|
||||
// MADD*/MSUB* are not part of MipsI either.
|
||||
//def MADD : MArithR<0x00, "madd">;
|
||||
//def MADDU : MArithR<0x01, "maddu">;
|
||||
//def MSUB : MArithR<0x04, "msub">;
|
||||
//def MSUBU : MArithR<0x05, "msubu">;
|
||||
|
||||
// No operation
|
||||
let addr=0 in
|
||||
def NOP : FJ<0, (outs), (ins), "nop", [], IIAlu>;
|
||||
@ -529,9 +516,8 @@ def : Pat<(MipsJmpLink CPURegs:$dst),
|
||||
// GlobalAddress, Constant Pool, ExternalSymbol, and JumpTable
|
||||
def : Pat<(MipsHi tglobaladdr:$in), (LUi tglobaladdr:$in)>;
|
||||
def : Pat<(MipsLo tglobaladdr:$in), (ADDiu ZERO, tglobaladdr:$in)>;
|
||||
def : Pat<(MipsAdd CPURegs:$hi, (MipsLo tglobaladdr:$lo)),
|
||||
def : Pat<(add CPURegs:$hi, (MipsLo tglobaladdr:$lo)),
|
||||
(ADDiu CPURegs:$hi, tglobaladdr:$lo)>;
|
||||
def : Pat<(MipsLoadAddr tglobaladdr:$in), (LA tglobaladdr:$in)>;
|
||||
|
||||
// Mips does not have not, so we increase the operation
|
||||
def : Pat<(not CPURegs:$in),
|
||||
@ -544,6 +530,9 @@ def : Pat<(i32 (extloadi16 addr:$src)), (LHu addr:$src)>;
|
||||
def : Pat<(truncstorei1 CPURegs:$src, addr:$addr),
|
||||
(SB CPURegs:$src, addr:$addr)>;
|
||||
|
||||
// some peepholes
|
||||
def : Pat<(store (i32 0), addr:$dst), (SW ZERO, addr:$dst)>;
|
||||
|
||||
///
|
||||
/// brcond patterns
|
||||
///
|
||||
|
@ -33,11 +33,6 @@ private:
|
||||
/// the Return Address must be saved
|
||||
int RAStackOffset;
|
||||
|
||||
/// When PIC is used the GP must be saved on the stack
|
||||
/// on the function prologue, so a reference to its stack
|
||||
/// location must be kept.
|
||||
int GPStackOffset;
|
||||
|
||||
/// MipsFIHolder - Holds a FrameIndex and it's Stack Pointer Offset
|
||||
struct MipsFIHolder {
|
||||
|
||||
@ -48,6 +43,13 @@ private:
|
||||
: FI(FrameIndex), SPOffset(StackPointerOffset) {}
|
||||
};
|
||||
|
||||
/// When PIC is used the GP must be saved on the stack
|
||||
/// on the function prologue and must be reloaded from this
|
||||
/// stack location after every call. A reference to its stack
|
||||
/// location and frame index must be kept to be used on
|
||||
/// emitPrologue and processFunctionBeforeFrameFinalized.
|
||||
MipsFIHolder GPHolder;
|
||||
|
||||
// On LowerFORMAL_ARGUMENTS the stack size is unknown,
|
||||
// so the Stack Pointer Offset calculation of "not in
|
||||
// register arguments" must be postponed to emitPrologue.
|
||||
@ -64,7 +66,7 @@ private:
|
||||
|
||||
public:
|
||||
MipsFunctionInfo(MachineFunction& MF)
|
||||
: FPStackOffset(0), RAStackOffset(0),
|
||||
: FPStackOffset(0), RAStackOffset(0), GPHolder(-1,-1),
|
||||
HasLoadArgs(false), HasStoreVarArgs(false)
|
||||
{}
|
||||
|
||||
@ -74,8 +76,10 @@ public:
|
||||
int getRAStackOffset() const { return RAStackOffset; }
|
||||
void setRAStackOffset(int Off) { RAStackOffset = Off; }
|
||||
|
||||
int getGPStackOffset() const { return GPStackOffset; }
|
||||
void setGPStackOffset(int Off) { GPStackOffset = Off; }
|
||||
int getGPStackOffset() const { return GPHolder.SPOffset; }
|
||||
int getGPFI() const { return GPHolder.FI; }
|
||||
void setGPStackOffset(int Off) { GPHolder.SPOffset = Off; }
|
||||
void setGPFI(int FI) { GPHolder.FI = FI; }
|
||||
|
||||
int getTopSavedRegOffset() const {
|
||||
return (RAStackOffset > FPStackOffset) ?
|
||||
|
@ -203,6 +203,12 @@ foldMemoryOperand(MachineInstr* MI, unsigned OpNum, int FI) const
|
||||
return NewMI;
|
||||
}
|
||||
|
||||
MachineInstr *MipsRegisterInfo::
|
||||
foldMemoryOperand(MachineInstr* MI, unsigned OpNum,
|
||||
MachineInstr* LoadMI) const {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Callee Saved Registers methods
|
||||
@ -325,7 +331,7 @@ void MipsRegisterInfo::
|
||||
eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
|
||||
RegScavenger *RS) const
|
||||
{
|
||||
MachineInstr &MI = *II;
|
||||
MachineInstr &MI = *II;
|
||||
MachineFunction &MF = *MI.getParent()->getParent();
|
||||
|
||||
unsigned i = 0;
|
||||
@ -359,7 +365,7 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
|
||||
#endif
|
||||
|
||||
MI.getOperand(i-1).ChangeToImmediate(Offset);
|
||||
MI.getOperand(i).ChangeToRegister(getFrameRegister(MF),false);
|
||||
MI.getOperand(i).ChangeToRegister(getFrameRegister(MF), false);
|
||||
}
|
||||
|
||||
void MipsRegisterInfo::
|
||||
@ -453,7 +459,6 @@ emitPrologue(MachineFunction &MF) const
|
||||
if ((isPIC) && (MFI->hasCalls()))
|
||||
BuildMI(MBB, MBBI, TII.get(Mips::CPRESTORE))
|
||||
.addImm(MipsFI->getGPStackOffset());
|
||||
|
||||
}
|
||||
|
||||
void MipsRegisterInfo::
|
||||
@ -498,6 +503,17 @@ emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const
|
||||
|
||||
void MipsRegisterInfo::
|
||||
processFunctionBeforeFrameFinalized(MachineFunction &MF) const {
|
||||
// Set the SPOffset on the FI where GP must be saved/loaded.
|
||||
MachineFrameInfo *MFI = MF.getFrameInfo();
|
||||
if (MFI->hasCalls()) {
|
||||
MipsFunctionInfo *MipsFI = MF.getInfo<MipsFunctionInfo>();
|
||||
#ifndef NDEBUG
|
||||
DOUT << "processFunctionBeforeFrameFinalized\n";
|
||||
DOUT << "GPOffset :" << MipsFI->getGPStackOffset() << "\n";
|
||||
DOUT << "FI :" << MipsFI->getGPFI() << "\n";
|
||||
#endif
|
||||
MFI->setObjectOffset(MipsFI->getGPFI(), MipsFI->getGPStackOffset());
|
||||
}
|
||||
}
|
||||
|
||||
unsigned MipsRegisterInfo::
|
||||
|
@ -59,9 +59,7 @@ struct MipsRegisterInfo : public MipsGenRegisterInfo {
|
||||
int FrameIndex) const;
|
||||
|
||||
MachineInstr* foldMemoryOperand(MachineInstr* MI, unsigned OpNum,
|
||||
MachineInstr* LoadMI) const {
|
||||
return 0;
|
||||
}
|
||||
MachineInstr* LoadMI) const;
|
||||
|
||||
void copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
|
||||
unsigned DestReg, unsigned SrcReg,
|
||||
|
@ -35,6 +35,9 @@ createTargetAsmInfo() const
|
||||
// On function prologue, the stack is created by decrementing
|
||||
// its pointer. Once decremented, all references are done with positive
|
||||
// offset from the stack/frame pointer, so StackGrowsUp is used.
|
||||
// When using CodeModel::Large the behaviour
|
||||
//
|
||||
//
|
||||
MipsTargetMachine::
|
||||
MipsTargetMachine(const Module &M, const std::string &FS):
|
||||
Subtarget(*this, M, FS), DataLayout("E-p:32:32:32"),
|
||||
@ -43,6 +46,8 @@ MipsTargetMachine(const Module &M, const std::string &FS):
|
||||
{
|
||||
if (getRelocationModel() != Reloc::Static)
|
||||
setRelocationModel(Reloc::PIC_);
|
||||
if (getCodeModel() == CodeModel::Default)
|
||||
setCodeModel(CodeModel::Small);
|
||||
}
|
||||
|
||||
// return 0 and must specify -march to gen MIPS code.
|
||||
|
Loading…
Reference in New Issue
Block a user