aboutsummaryrefslogtreecommitdiffstats
path: root/lib/Target/PowerPC/PPCISelLowering.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Target/PowerPC/PPCISelLowering.cpp')
-rw-r--r--lib/Target/PowerPC/PPCISelLowering.cpp32
1 files changed, 32 insertions, 0 deletions
diff --git a/lib/Target/PowerPC/PPCISelLowering.cpp b/lib/Target/PowerPC/PPCISelLowering.cpp
index 18404fcfef..fac2806c12 100644
--- a/lib/Target/PowerPC/PPCISelLowering.cpp
+++ b/lib/Target/PowerPC/PPCISelLowering.cpp
@@ -123,6 +123,7 @@ PPCTargetLowering::PPCTargetLowering(TargetMachine &TM)
// appropriate instructions to materialize the address.
setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
+ setOperationAction(ISD::JumpTable, MVT::i32, Custom);
// RET must be custom lowered, to meet ABI requirements
setOperationAction(ISD::RET , MVT::Other, Custom);
@@ -605,6 +606,36 @@ static SDOperand LowerConstantPool(SDOperand Op, SelectionDAG &DAG) {
return Lo;
}
+static SDOperand LowerJumpTable(SDOperand Op, SelectionDAG &DAG) {
+ JumpTableSDNode *JT = cast<JumpTableSDNode>(Op);
+ SDOperand JTI = DAG.getTargetJumpTable(JT->getIndex(), MVT::i32);
+ SDOperand Zero = DAG.getConstant(0, MVT::i32);
+
+ const TargetMachine &TM = DAG.getTarget();
+
+ // If this is a non-darwin platform, we don't support non-static relo models
+ // yet.
+ if (TM.getRelocationModel() == Reloc::Static ||
+ !TM.getSubtarget<PPCSubtarget>().isDarwin()) {
+ // Generate non-pic code that has direct accesses to the constant pool.
+ // The address of the global is just (hi(&g)+lo(&g)).
+ SDOperand Hi = DAG.getNode(PPCISD::Hi, MVT::i32, JTI, Zero);
+ SDOperand Lo = DAG.getNode(PPCISD::Lo, MVT::i32, JTI, Zero);
+ return DAG.getNode(ISD::ADD, MVT::i32, Hi, Lo);
+ }
+
+ SDOperand Hi = DAG.getNode(PPCISD::Hi, MVT::i32, JTI, Zero);
+ if (TM.getRelocationModel() == Reloc::PIC) {
+ // With PIC, the first instruction is actually "GR+hi(&G)".
+ Hi = DAG.getNode(ISD::ADD, MVT::i32,
+ DAG.getNode(PPCISD::GlobalBaseReg, MVT::i32), Hi);
+ }
+
+ SDOperand Lo = DAG.getNode(PPCISD::Lo, MVT::i32, JTI, Zero);
+ Lo = DAG.getNode(ISD::ADD, MVT::i32, Hi, Lo);
+ return Lo;
+}
+
static SDOperand LowerGlobalAddress(SDOperand Op, SelectionDAG &DAG) {
GlobalAddressSDNode *GSDN = cast<GlobalAddressSDNode>(Op);
GlobalValue *GV = GSDN->getGlobal();
@@ -1652,6 +1683,7 @@ SDOperand PPCTargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) {
default: assert(0 && "Wasn't expecting to be able to lower this!");
case ISD::ConstantPool: return LowerConstantPool(Op, DAG);
case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG);
+ case ISD::JumpTable: return LowerJumpTable(Op, DAG);
case ISD::SETCC: return LowerSETCC(Op, DAG);
case ISD::VASTART: return LowerVASTART(Op, DAG, VarArgsFrameIndex);
case ISD::RET: return LowerRET(Op, DAG);