mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-07-21 02:29:22 +00:00
Patch to clean up function call pseudos and support the BLA instruction,
which branches to an absolute address. This is required to support objc direct dispatch. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@24370 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
427189ad51
commit
422b0cee7a
@ -152,6 +152,10 @@ namespace {
|
|||||||
TM.getInstrInfo()->isCall(MI->getOpcode()));
|
TM.getInstrInfo()->isCall(MI->getOpcode()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
void printAbsAddrOperand(const MachineInstr *MI, unsigned OpNo,
|
||||||
|
MVT::ValueType VT) {
|
||||||
|
O << (int)MI->getOperand(OpNo).getImmedValue()*4;
|
||||||
|
}
|
||||||
void printPICLabel(const MachineInstr *MI, unsigned OpNo,
|
void printPICLabel(const MachineInstr *MI, unsigned OpNo,
|
||||||
MVT::ValueType VT) {
|
MVT::ValueType VT) {
|
||||||
// FIXME: should probably be converted to cout.width and cout.fill
|
// FIXME: should probably be converted to cout.width and cout.fill
|
||||||
|
@ -196,7 +196,7 @@ int PPCCodeEmitter::getMachineOpValue(MachineInstr &MI, MachineOperand &MO) {
|
|||||||
MO.getGlobal()->hasWeakLinkage() ||
|
MO.getGlobal()->hasWeakLinkage() ||
|
||||||
MO.getGlobal()->isExternal();
|
MO.getGlobal()->isExternal();
|
||||||
unsigned Reloc = 0;
|
unsigned Reloc = 0;
|
||||||
if (MI.getOpcode() == PPC::CALLpcrel)
|
if (MI.getOpcode() == PPC::BL)
|
||||||
Reloc = PPC::reloc_pcrel_bx;
|
Reloc = PPC::reloc_pcrel_bx;
|
||||||
else {
|
else {
|
||||||
switch (MI.getOpcode()) {
|
switch (MI.getOpcode()) {
|
||||||
|
@ -735,6 +735,14 @@ SDOperand PPCDAGToDAGISel::SelectSETCC(SDOperand Op) {
|
|||||||
return SDOperand(N, 0);
|
return SDOperand(N, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// isCallCompatibleAddress - Return true if the specified 32-bit value is
|
||||||
|
/// representable in the immediate field of a Bx instruction.
|
||||||
|
static bool isCallCompatibleAddress(ConstantSDNode *C) {
|
||||||
|
int Addr = C->getValue();
|
||||||
|
if (Addr & 3) return false; // Low 2 bits are implicitly zero.
|
||||||
|
return (Addr << 6 >> 6) == Addr; // Top 6 bits have to be sext of immediate.
|
||||||
|
}
|
||||||
|
|
||||||
SDOperand PPCDAGToDAGISel::SelectCALL(SDOperand Op) {
|
SDOperand PPCDAGToDAGISel::SelectCALL(SDOperand Op) {
|
||||||
SDNode *N = Op.Val;
|
SDNode *N = Op.Val;
|
||||||
SDOperand Chain = Select(N->getOperand(0));
|
SDOperand Chain = Select(N->getOperand(0));
|
||||||
@ -744,13 +752,18 @@ SDOperand PPCDAGToDAGISel::SelectCALL(SDOperand Op) {
|
|||||||
|
|
||||||
if (GlobalAddressSDNode *GASD =
|
if (GlobalAddressSDNode *GASD =
|
||||||
dyn_cast<GlobalAddressSDNode>(N->getOperand(1))) {
|
dyn_cast<GlobalAddressSDNode>(N->getOperand(1))) {
|
||||||
CallOpcode = PPC::CALLpcrel;
|
CallOpcode = PPC::BL;
|
||||||
CallOperands.push_back(CurDAG->getTargetGlobalAddress(GASD->getGlobal(),
|
CallOperands.push_back(CurDAG->getTargetGlobalAddress(GASD->getGlobal(),
|
||||||
MVT::i32));
|
MVT::i32));
|
||||||
} else if (ExternalSymbolSDNode *ESSDN =
|
} else if (ExternalSymbolSDNode *ESSDN =
|
||||||
dyn_cast<ExternalSymbolSDNode>(N->getOperand(1))) {
|
dyn_cast<ExternalSymbolSDNode>(N->getOperand(1))) {
|
||||||
CallOpcode = PPC::CALLpcrel;
|
CallOpcode = PPC::BL;
|
||||||
CallOperands.push_back(N->getOperand(1));
|
CallOperands.push_back(N->getOperand(1));
|
||||||
|
} else if (isa<ConstantSDNode>(N->getOperand(1)) &&
|
||||||
|
isCallCompatibleAddress(cast<ConstantSDNode>(N->getOperand(1)))) {
|
||||||
|
ConstantSDNode *C = cast<ConstantSDNode>(N->getOperand(1));
|
||||||
|
CallOpcode = PPC::BLA;
|
||||||
|
CallOperands.push_back(getI32Imm((int)C->getValue() >> 2));
|
||||||
} else {
|
} else {
|
||||||
// Copy the callee address into the CTR register.
|
// Copy the callee address into the CTR register.
|
||||||
SDOperand Callee = Select(N->getOperand(1));
|
SDOperand Callee = Select(N->getOperand(1));
|
||||||
@ -759,11 +772,9 @@ SDOperand PPCDAGToDAGISel::SelectCALL(SDOperand Op) {
|
|||||||
// Copy the callee address into R12 on darwin.
|
// Copy the callee address into R12 on darwin.
|
||||||
SDOperand R12 = CurDAG->getRegister(PPC::R12, MVT::i32);
|
SDOperand R12 = CurDAG->getRegister(PPC::R12, MVT::i32);
|
||||||
Chain = CurDAG->getNode(ISD::CopyToReg, MVT::Other, Chain, R12, Callee);
|
Chain = CurDAG->getNode(ISD::CopyToReg, MVT::Other, Chain, R12, Callee);
|
||||||
|
|
||||||
CallOperands.push_back(getI32Imm(20)); // Information to encode indcall
|
|
||||||
CallOperands.push_back(getI32Imm(0)); // Information to encode indcall
|
|
||||||
CallOperands.push_back(R12);
|
CallOperands.push_back(R12);
|
||||||
CallOpcode = PPC::CALLindirect;
|
CallOpcode = PPC::BCTRL;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned GPR_idx = 0, FPR_idx = 0;
|
unsigned GPR_idx = 0, FPR_idx = 0;
|
||||||
|
@ -842,18 +842,15 @@ unsigned ISel::SelectExpr(SDOperand N, bool Recording) {
|
|||||||
// Emit the correct call instruction based on the type of symbol called.
|
// Emit the correct call instruction based on the type of symbol called.
|
||||||
if (GlobalAddressSDNode *GASD =
|
if (GlobalAddressSDNode *GASD =
|
||||||
dyn_cast<GlobalAddressSDNode>(N.getOperand(1))) {
|
dyn_cast<GlobalAddressSDNode>(N.getOperand(1))) {
|
||||||
CallMI = BuildMI(PPC::CALLpcrel, 1).addGlobalAddress(GASD->getGlobal(),
|
CallMI = BuildMI(PPC::BL, 1).addGlobalAddress(GASD->getGlobal(), true);
|
||||||
true);
|
|
||||||
} else if (ExternalSymbolSDNode *ESSDN =
|
} else if (ExternalSymbolSDNode *ESSDN =
|
||||||
dyn_cast<ExternalSymbolSDNode>(N.getOperand(1))) {
|
dyn_cast<ExternalSymbolSDNode>(N.getOperand(1))) {
|
||||||
CallMI = BuildMI(PPC::CALLpcrel, 1).addExternalSymbol(ESSDN->getSymbol(),
|
CallMI = BuildMI(PPC::BL, 1).addExternalSymbol(ESSDN->getSymbol(), true);
|
||||||
true);
|
|
||||||
} else {
|
} else {
|
||||||
Tmp1 = SelectExpr(N.getOperand(1));
|
Tmp1 = SelectExpr(N.getOperand(1));
|
||||||
BuildMI(BB, PPC::MTCTR, 1).addReg(Tmp1);
|
BuildMI(BB, PPC::MTCTR, 1).addReg(Tmp1);
|
||||||
BuildMI(BB, PPC::OR4, 2, PPC::R12).addReg(Tmp1).addReg(Tmp1);
|
BuildMI(BB, PPC::OR4, 2, PPC::R12).addReg(Tmp1).addReg(Tmp1);
|
||||||
CallMI = BuildMI(PPC::CALLindirect, 3).addImm(20).addImm(0)
|
CallMI = BuildMI(PPC::BCTRL, 1).addReg(PPC::R12);
|
||||||
.addReg(PPC::R12);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load the register args to virtual regs
|
// Load the register args to virtual regs
|
||||||
|
@ -128,6 +128,9 @@ def s16immX4 : Operand<i32> { // Multiply imm by 4 before printing.
|
|||||||
def target : Operand<i32> {
|
def target : Operand<i32> {
|
||||||
let PrintMethod = "printBranchOperand";
|
let PrintMethod = "printBranchOperand";
|
||||||
}
|
}
|
||||||
|
def aaddr : Operand<i32> {
|
||||||
|
let PrintMethod = "printAbsAddrOperand";
|
||||||
|
}
|
||||||
def piclabel: Operand<i32> {
|
def piclabel: Operand<i32> {
|
||||||
let PrintMethod = "printPICLabel";
|
let PrintMethod = "printPICLabel";
|
||||||
}
|
}
|
||||||
@ -186,9 +189,6 @@ let isBranch = 1, isTerminator = 1 in {
|
|||||||
target:$true, target:$false),
|
target:$true, target:$false),
|
||||||
"; COND_BRANCH", []>;
|
"; COND_BRANCH", []>;
|
||||||
def B : IForm<18, 0, 0, (ops target:$func), "b $func", BrB>;
|
def B : IForm<18, 0, 0, (ops target:$func), "b $func", BrB>;
|
||||||
//def BA : IForm<18, 1, 0, (ops target:$func), "ba $func", BrB>;
|
|
||||||
def BL : IForm<18, 0, 1, (ops target:$func), "bl $func", BrB>;
|
|
||||||
//def BLA : IForm<18, 1, 1, (ops target:$func), "bla $func", BrB>;
|
|
||||||
|
|
||||||
// FIXME: 4*CR# needs to be added to the BI field!
|
// FIXME: 4*CR# needs to be added to the BI field!
|
||||||
// This will only work for CR0 as it stands now
|
// This will only work for CR0 as it stands now
|
||||||
@ -217,10 +217,9 @@ let isCall = 1,
|
|||||||
LR,CTR,
|
LR,CTR,
|
||||||
CR0,CR1,CR5,CR6,CR7] in {
|
CR0,CR1,CR5,CR6,CR7] in {
|
||||||
// Convenient aliases for call instructions
|
// Convenient aliases for call instructions
|
||||||
def CALLpcrel : IForm<18, 0, 1, (ops target:$func, variable_ops),
|
def BL : IForm<18, 0, 1, (ops target:$func, variable_ops), "bl $func", BrB>;
|
||||||
"bl $func", BrB>;
|
def BLA : IForm<18, 1, 1, (ops aaddr:$func, variable_ops), "bla $func", BrB>;
|
||||||
def CALLindirect : XLForm_2_ext<19, 528, 20, 0, 1,
|
def BCTRL : XLForm_2_ext<19, 528, 20, 0, 1, (ops variable_ops), "bctrl", BrB>;
|
||||||
(ops variable_ops), "bctrl", BrB>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// D-Form instructions. Most instructions that perform an operation on a
|
// D-Form instructions. Most instructions that perform an operation on a
|
||||||
|
Loading…
Reference in New Issue
Block a user