1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 19:52:54 +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:
Bruno Cardoso Lopes 2007-11-05 03:02:32 +00:00
parent 314e68f58f
commit 569b5512b0
9 changed files with 214 additions and 103 deletions

View File

@ -250,7 +250,7 @@ emitFunctionStart(MachineFunction &MF)
emitMaskDirective(MF); emitMaskDirective(MF);
emitFMaskDirective(MF); emitFMaskDirective(MF);
if (MF.getTarget().getRelocationModel() == Reloc::Static) { if (TM.getRelocationModel() == Reloc::Static) {
emitSetDirective(NOREORDER); emitSetDirective(NOREORDER);
emitSetDirective(NOMACRO); emitSetDirective(NOMACRO);
} }
@ -262,7 +262,7 @@ emitFunctionStart(MachineFunction &MF)
void MipsAsmPrinter:: void MipsAsmPrinter::
emitFunctionEnd(MachineFunction &MF) emitFunctionEnd(MachineFunction &MF)
{ {
if (MF.getTarget().getRelocationModel() == Reloc::Static) { if (TM.getRelocationModel() == Reloc::Static) {
emitSetDirective(MACRO); emitSetDirective(MACRO);
emitSetDirective(REORDER); emitSetDirective(REORDER);
} }
@ -305,6 +305,9 @@ runOnMachineFunction(MachineFunction &MF)
printInstruction(II); printInstruction(II);
++EmittedInsts; ++EmittedInsts;
} }
// Each Basic Block is separated by a newline
O << '\n';
} }
// Emit function end directives // Emit function end directives
@ -319,17 +322,41 @@ printOperand(const MachineInstr *MI, int opNum)
{ {
const MachineOperand &MO = MI->getOperand(opNum); const MachineOperand &MO = MI->getOperand(opNum);
const MRegisterInfo &RI = *TM.getRegisterInfo(); 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() if (MI->getOpcode() == Mips::LUi && !MO.isRegister()
&& !MO.isImmediate()) { && !MO.isImmediate()) {
if ((isPIC) && (isCodeLarge))
O << "%call_hi(";
else
O << "%hi("; O << "%hi(";
closeP = true; closeP = true;
} else if ((MI->getOpcode() == Mips::ADDiu) && !MO.isRegister() } else if ((MI->getOpcode() == Mips::ADDiu) && !MO.isRegister()
&& !MO.isImmediate()) { && !MO.isImmediate()) {
O << "%lo("; O << "%lo(";
closeP = true; 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()) switch (MO.getType())
@ -361,6 +388,7 @@ printOperand(const MachineInstr *MI, int opNum)
O << MO.getSymbolName(); O << MO.getSymbolName();
break; break;
// FIXME: Verify correct
case MachineOperand::MO_ConstantPoolIndex: case MachineOperand::MO_ConstantPoolIndex:
O << TAI->getPrivateGlobalPrefix() << "CPI" O << TAI->getPrivateGlobalPrefix() << "CPI"
<< getFunctionNumber() << "_" << MO.getConstantPoolIndex(); << getFunctionNumber() << "_" << MO.getConstantPoolIndex();
@ -386,6 +414,8 @@ printMemOperand(const MachineInstr *MI, int opNum, const char *Modifier)
} }
// 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); printOperand(MI, opNum);
O << "("; O << "(";
printOperand(MI, opNum+1); printOperand(MI, opNum+1);

View File

@ -15,6 +15,7 @@
#include "Mips.h" #include "Mips.h"
#include "MipsISelLowering.h" #include "MipsISelLowering.h"
#include "MipsMachineFunction.h"
#include "MipsRegisterInfo.h" #include "MipsRegisterInfo.h"
#include "MipsSubtarget.h" #include "MipsSubtarget.h"
#include "MipsTargetMachine.h" #include "MipsTargetMachine.h"
@ -135,20 +136,24 @@ SelectAddr(SDOperand Op, SDOperand Addr, SDOperand &Offset, SDOperand &Base)
return true; return true;
} }
// TargetExternalSymbol and TargetGlobalAddress are // on PIC code Load GA
// lowered and their addresses go into registers, so if (TM.getRelocationModel() == Reloc::PIC_) {
// they should not be touched here. if (Addr.getOpcode() == ISD::TargetGlobalAddress) {
Base = CurDAG->getRegister(Mips::GP, MVT::i32);
Offset = Addr;
return true;
}
} else {
if ((Addr.getOpcode() == ISD::TargetExternalSymbol || if ((Addr.getOpcode() == ISD::TargetExternalSymbol ||
Addr.getOpcode() == ISD::TargetGlobalAddress)) Addr.getOpcode() == ISD::TargetGlobalAddress))
return false; return false;
}
// Operand is a result from an ADD. // Operand is a result from an ADD.
if (Addr.getOpcode() == ISD::ADD) if (Addr.getOpcode() == ISD::ADD) {
{ if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) {
if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(Addr.getOperand(1))) if (Predicate_immSExt16(CN)) {
{
if (Predicate_immSExt16(CN))
{
// If the first operand is a FI, get the TargetFI Node // If the first operand is a FI, get the TargetFI Node
if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode> if (FrameIndexSDNode *FIN = dyn_cast<FrameIndexSDNode>
(Addr.getOperand(0))) { (Addr.getOperand(0))) {
@ -247,6 +252,51 @@ Select(SDOperand N)
SDOperand MFInFlag = SDOperand(RemNode, 0); SDOperand MFInFlag = SDOperand(RemNode, 0);
return CurDAG->getTargetNode(Mips::MFHI, MVT::i32, MFInFlag); 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 // Select the default instruction

View File

@ -43,8 +43,6 @@ getTargetNodeName(unsigned Opcode) const
case MipsISD::Hi : return "MipsISD::Hi"; case MipsISD::Hi : return "MipsISD::Hi";
case MipsISD::Lo : return "MipsISD::Lo"; case MipsISD::Lo : return "MipsISD::Lo";
case MipsISD::Ret : return "MipsISD::Ret"; case MipsISD::Ret : return "MipsISD::Ret";
case MipsISD::Add : return "MipsISD::Add";
case MipsISD::LoadAddr : return "MipsISD::LoadAddr";
default : return NULL; default : return NULL;
} }
} }
@ -149,21 +147,24 @@ LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG)
{ {
SDOperand ResNode; SDOperand ResNode;
GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal(); GlobalValue *GV = cast<GlobalAddressSDNode>(Op)->getGlobal();
SDOperand GA = DAG.getTargetGlobalAddress(GV, MVT::i32); SDOperand GA = DAG.getTargetGlobalAddress(GV, MVT::i32);
bool isPIC = (getTargetMachine().getRelocationModel() == Reloc::PIC_);
// On PIC code global addresses are loaded with "la" instruction SDOperand HiPart;
if (!(getTargetMachine().getRelocationModel() == Reloc::PIC_)) { if (!isPIC) {
const MVT::ValueType *VTs = DAG.getNodeValueTypes(MVT::i32, MVT::Flag); const MVT::ValueType *VTs = DAG.getNodeValueTypes(MVT::i32);
SDOperand Ops[] = { GA }; 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);
// 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 Hi = DAG.getNode(MipsISD::Hi, VTs, 2, Ops, 1);
SDOperand Lo = DAG.getNode(MipsISD::Lo, MVT::i32, GA); SDOperand Lo = DAG.getNode(MipsISD::Lo, MVT::i32, GA);
ResNode = DAG.getNode(ISD::ADD, MVT::i32, HiPart, Lo);
SDOperand InFlag = Hi.getValue(1);
ResNode = DAG.getNode(MipsISD::Add, MVT::i32, Lo, Hi, InFlag);
} else
ResNode = DAG.getNode(MipsISD::LoadAddr, MVT::i32, GA);
return ResNode; return ResNode;
} }
@ -211,7 +212,7 @@ LowerCALL(SDOperand Op, SelectionDAG &DAG)
/// LowerCCCCallTo - functions arguments are copied from virtual /// LowerCCCCallTo - functions arguments are copied from virtual
/// regs to (physical regs)/(stack frame), CALLSEQ_START and /// regs to (physical regs)/(stack frame), CALLSEQ_START and
/// CALLSEQ_END are emitted. /// CALLSEQ_END are emitted.
/// TODO: isVarArg, isTailCall, sret, GOT, linkage types. /// TODO: isVarArg, isTailCall, sret.
SDOperand MipsTargetLowering:: SDOperand MipsTargetLowering::
LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC) LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC)
{ {
@ -244,7 +245,7 @@ LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC)
SmallVector<SDOperand, 8> MemOpChains; SmallVector<SDOperand, 8> MemOpChains;
SDOperand StackPtr; SDOperand StackPtr;
unsigned LastStackLoc=0; int LastStackLoc=0;
// Walk the register/memloc assignments, inserting copies/loads. // Walk the register/memloc assignments, inserting copies/loads.
for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) { for (unsigned i = 0, e = ArgLocs.size(); i != e; ++i) {
@ -268,8 +269,8 @@ LowerCCCCallTo(SDOperand Op, SelectionDAG &DAG, unsigned CC)
break; break;
} }
// Arguments that can be passed on register, // Arguments that can be passed on register must be kept at
// must be kept at RegsToPass vector // RegsToPass vector
if (VA.isRegLoc()) { if (VA.isRegLoc()) {
RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg));
} else { } 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 // Transform all store nodes into one single node because
// all store nodes are independent of each other. // all store nodes are independent of each other.
if (!MemOpChains.empty()) 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 // If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
// direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol // direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
// node so that legalize doesn't hack it. Otherwise we have an indirect call, // node so that legalize doesn't hack it.
// if PIC is used, the call must use register GP
if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
Callee = DAG.getTargetGlobalAddress(G->getGlobal(), getPointerTy()); Callee = DAG.getTargetGlobalAddress(G->getGlobal(), getPointerTy());
else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee)) else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy()); Callee = DAG.getTargetExternalSymbol(S->getSymbol(), getPointerTy());
// MipsJmpLink = #chain, #target_address, #opt_in_flags... // MipsJmpLink = #chain, #target_address, #opt_in_flags...
// = Chain, Callee, Reg#1, Reg#2, ... // = 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()); Chain = DAG.getNode(MipsISD::JmpLink, NodeTys, &Ops[0], Ops.size());
InFlag = Chain.getValue(1); 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. // Create the CALLSEQ_END node.
NodeTys = DAG.getVTList(MVT::Other, MVT::Flag); NodeTys = DAG.getVTList(MVT::Other, MVT::Flag);
Ops.clear(); Ops.clear();
@ -389,8 +413,9 @@ LowerCallResult(SDOperand Chain, SDOperand InFlag, SDNode *TheCall,
ResultVals.push_back(Chain.getValue(0)); ResultVals.push_back(Chain.getValue(0));
} }
// Merge everything together with a MERGE_VALUES node.
ResultVals.push_back(Chain); ResultVals.push_back(Chain);
// Merge everything together with a MERGE_VALUES node.
return DAG.getNode(ISD::MERGE_VALUES, TheCall->getVTList(), return DAG.getNode(ISD::MERGE_VALUES, TheCall->getVTList(),
&ResultVals[0], ResultVals.size()).Val; &ResultVals[0], ResultVals.size()).Val;
} }

View File

@ -38,13 +38,7 @@ namespace llvm {
Lo, Lo,
// Return // Return
Ret, Ret
// Need to support addition with a input flag
Add,
// Used on PIC Code to load global addresses
LoadAddr
}; };
} }

View File

@ -22,21 +22,12 @@ def SDT_MipsJmpLink : SDTypeProfile<0, 1, [SDTCisVT<0, iPTR>]>;
def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, [SDNPHasChain, def MipsJmpLink : SDNode<"MipsISD::JmpLink",SDT_MipsJmpLink, [SDNPHasChain,
SDNPOutFlag]>; SDNPOutFlag]>;
// Hi and Lo nodes are created to let easy manipulation of 16-bit when // Hi and Lo nodes are used to handle global addresses. Used on
// handling 32-bit immediates. They are used on MipsISelLowering to // MipsISelLowering to lower stuff like GlobalAddress, ExternalSymbol
// lower stuff like GlobalAddress, ExternalSymbol, ... on static model // static model. (nothing to do with Mips Registers Hi and Lo)
// This two nodes have nothing to do with Mips Registers Hi and Lo.
def MipsHi : SDNode<"MipsISD::Hi", SDTIntUnaryOp, [SDNPOutFlag]>; def MipsHi : SDNode<"MipsISD::Hi", SDTIntUnaryOp, [SDNPOutFlag]>;
def MipsLo : SDNode<"MipsISD::Lo", SDTIntUnaryOp>; 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>;
// Return // Return
def SDT_MipsRet : SDTypeProfile<0, 1, [SDTCisInt<0>]>; def SDT_MipsRet : SDTypeProfile<0, 1, [SDTCisInt<0>]>;
def MipsRet : SDNode<"MipsISD::Ret", SDT_MipsRet, [SDNPHasChain, def MipsRet : SDNode<"MipsISD::Ret", SDT_MipsRet, [SDNPHasChain,
@ -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 // are used, we have the same behavior, but get also a bunch of warnings
// from the assembler. // from the assembler.
def CPLOAD: PseudoInstMips<(outs), (ins CPURegs:$reg), 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), def CPRESTORE: PseudoInstMips<(outs), (ins uimm16:$loc),
".cprestore $loc", []>; ".cprestore $loc\n", []>;
// 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", []>;
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// Instruction definition // 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. // ADDiu just accept 16-bit immediates but we handle this on Pat's.
// immZExt32 is used here so it can match GlobalAddress immediates. // 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 ADDi : ArithI<0x08, "addi", add, simm16, immSExt16>;
def MUL : ArithR<0x1c, 0x02, "mul", mul, IIImul>; def MUL : ArithR<0x1c, 0x02, "mul", mul, IIImul>;
def ADDu : ArithR<0x00, 0x21, "addu", add, IIAlu>; def ADDu : ArithR<0x00, 0x21, "addu", add, IIAlu>;
def SUBu : ArithR<0x00, 0x23, "subu", sub, IIAlu>; def SUBu : ArithR<0x00, 0x23, "subu", sub, IIAlu>;
def ADD : ArithOverflowR<0x00, 0x20, "add">; def ADD : ArithOverflowR<0x00, 0x20, "add">;
def SUB : ArithOverflowR<0x00, 0x22, "sub">; 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 // Logical
def AND : LogicR<0x24, "and", and>; def AND : LogicR<0x24, "and", and>;
@ -485,6 +466,12 @@ def MTLO : MoveFromTo<0x13, "mtlo">;
//def CLO : CountLeading<0x21, "clo">; //def CLO : CountLeading<0x21, "clo">;
//def CLZ : CountLeading<0x20, "clz">; //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 // No operation
let addr=0 in let addr=0 in
def NOP : FJ<0, (outs), (ins), "nop", [], IIAlu>; def NOP : FJ<0, (outs), (ins), "nop", [], IIAlu>;
@ -529,9 +516,8 @@ def : Pat<(MipsJmpLink CPURegs:$dst),
// GlobalAddress, Constant Pool, ExternalSymbol, and JumpTable // GlobalAddress, Constant Pool, ExternalSymbol, and JumpTable
def : Pat<(MipsHi tglobaladdr:$in), (LUi tglobaladdr:$in)>; def : Pat<(MipsHi tglobaladdr:$in), (LUi tglobaladdr:$in)>;
def : Pat<(MipsLo tglobaladdr:$in), (ADDiu ZERO, 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)>; (ADDiu CPURegs:$hi, tglobaladdr:$lo)>;
def : Pat<(MipsLoadAddr tglobaladdr:$in), (LA tglobaladdr:$in)>;
// Mips does not have not, so we increase the operation // Mips does not have not, so we increase the operation
def : Pat<(not CPURegs:$in), 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), def : Pat<(truncstorei1 CPURegs:$src, addr:$addr),
(SB CPURegs:$src, addr:$addr)>; (SB CPURegs:$src, addr:$addr)>;
// some peepholes
def : Pat<(store (i32 0), addr:$dst), (SW ZERO, addr:$dst)>;
/// ///
/// brcond patterns /// brcond patterns
/// ///

View File

@ -33,11 +33,6 @@ private:
/// the Return Address must be saved /// the Return Address must be saved
int RAStackOffset; 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 /// MipsFIHolder - Holds a FrameIndex and it's Stack Pointer Offset
struct MipsFIHolder { struct MipsFIHolder {
@ -48,6 +43,13 @@ private:
: FI(FrameIndex), SPOffset(StackPointerOffset) {} : 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, // On LowerFORMAL_ARGUMENTS the stack size is unknown,
// so the Stack Pointer Offset calculation of "not in // so the Stack Pointer Offset calculation of "not in
// register arguments" must be postponed to emitPrologue. // register arguments" must be postponed to emitPrologue.
@ -64,7 +66,7 @@ private:
public: public:
MipsFunctionInfo(MachineFunction& MF) MipsFunctionInfo(MachineFunction& MF)
: FPStackOffset(0), RAStackOffset(0), : FPStackOffset(0), RAStackOffset(0), GPHolder(-1,-1),
HasLoadArgs(false), HasStoreVarArgs(false) HasLoadArgs(false), HasStoreVarArgs(false)
{} {}
@ -74,8 +76,10 @@ public:
int getRAStackOffset() const { return RAStackOffset; } int getRAStackOffset() const { return RAStackOffset; }
void setRAStackOffset(int Off) { RAStackOffset = Off; } void setRAStackOffset(int Off) { RAStackOffset = Off; }
int getGPStackOffset() const { return GPStackOffset; } int getGPStackOffset() const { return GPHolder.SPOffset; }
void setGPStackOffset(int Off) { GPStackOffset = Off; } int getGPFI() const { return GPHolder.FI; }
void setGPStackOffset(int Off) { GPHolder.SPOffset = Off; }
void setGPFI(int FI) { GPHolder.FI = FI; }
int getTopSavedRegOffset() const { int getTopSavedRegOffset() const {
return (RAStackOffset > FPStackOffset) ? return (RAStackOffset > FPStackOffset) ?

View File

@ -203,6 +203,12 @@ foldMemoryOperand(MachineInstr* MI, unsigned OpNum, int FI) const
return NewMI; return NewMI;
} }
MachineInstr *MipsRegisterInfo::
foldMemoryOperand(MachineInstr* MI, unsigned OpNum,
MachineInstr* LoadMI) const {
return NULL;
}
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// //
// Callee Saved Registers methods // Callee Saved Registers methods
@ -359,7 +365,7 @@ eliminateFrameIndex(MachineBasicBlock::iterator II, int SPAdj,
#endif #endif
MI.getOperand(i-1).ChangeToImmediate(Offset); MI.getOperand(i-1).ChangeToImmediate(Offset);
MI.getOperand(i).ChangeToRegister(getFrameRegister(MF),false); MI.getOperand(i).ChangeToRegister(getFrameRegister(MF), false);
} }
void MipsRegisterInfo:: void MipsRegisterInfo::
@ -453,7 +459,6 @@ emitPrologue(MachineFunction &MF) const
if ((isPIC) && (MFI->hasCalls())) if ((isPIC) && (MFI->hasCalls()))
BuildMI(MBB, MBBI, TII.get(Mips::CPRESTORE)) BuildMI(MBB, MBBI, TII.get(Mips::CPRESTORE))
.addImm(MipsFI->getGPStackOffset()); .addImm(MipsFI->getGPStackOffset());
} }
void MipsRegisterInfo:: void MipsRegisterInfo::
@ -498,6 +503,17 @@ emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const
void MipsRegisterInfo:: void MipsRegisterInfo::
processFunctionBeforeFrameFinalized(MachineFunction &MF) const { 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:: unsigned MipsRegisterInfo::

View File

@ -59,9 +59,7 @@ struct MipsRegisterInfo : public MipsGenRegisterInfo {
int FrameIndex) const; int FrameIndex) const;
MachineInstr* foldMemoryOperand(MachineInstr* MI, unsigned OpNum, MachineInstr* foldMemoryOperand(MachineInstr* MI, unsigned OpNum,
MachineInstr* LoadMI) const { MachineInstr* LoadMI) const;
return 0;
}
void copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, void copyRegToReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
unsigned DestReg, unsigned SrcReg, unsigned DestReg, unsigned SrcReg,

View File

@ -35,6 +35,9 @@ createTargetAsmInfo() const
// On function prologue, the stack is created by decrementing // On function prologue, the stack is created by decrementing
// its pointer. Once decremented, all references are done with positive // its pointer. Once decremented, all references are done with positive
// offset from the stack/frame pointer, so StackGrowsUp is used. // offset from the stack/frame pointer, so StackGrowsUp is used.
// When using CodeModel::Large the behaviour
//
//
MipsTargetMachine:: MipsTargetMachine::
MipsTargetMachine(const Module &M, const std::string &FS): MipsTargetMachine(const Module &M, const std::string &FS):
Subtarget(*this, M, FS), DataLayout("E-p:32:32:32"), 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) if (getRelocationModel() != Reloc::Static)
setRelocationModel(Reloc::PIC_); setRelocationModel(Reloc::PIC_);
if (getCodeModel() == CodeModel::Default)
setCodeModel(CodeModel::Small);
} }
// return 0 and must specify -march to gen MIPS code. // return 0 and must specify -march to gen MIPS code.