+SDOperand PPC32DAGToDAGISel::SelectDYNAMIC_STACKALLOC(SDOperand Op) {
+ SDNode *N = Op.Val;
+
+ // FIXME: We are currently ignoring the requested alignment for handling
+ // greater than the stack alignment. This will need to be revisited at some
+ // point. Align = N.getOperand(2);
+ if (!isa<ConstantSDNode>(N->getOperand(2)) ||
+ cast<ConstantSDNode>(N->getOperand(2))->getValue() != 0) {
+ std::cerr << "Cannot allocate stack object with greater alignment than"
+ << " the stack alignment yet!";
+ abort();
+ }
+ SDOperand Chain = Select(N->getOperand(0));
+ SDOperand Amt = Select(N->getOperand(1));
+
+ SDOperand R1Reg = CurDAG->getRegister(PPC::R1, MVT::i32);
+
+ SDOperand R1Val = CurDAG->getCopyFromReg(Chain, PPC::R1, MVT::i32);
+ Chain = R1Val.getValue(1);
+
+ // Subtract the amount (guaranteed to be a multiple of the stack alignment)
+ // from the stack pointer, giving us the result pointer.
+ SDOperand Result = CurDAG->getTargetNode(PPC::SUBF, MVT::i32, Amt, R1Val);
+
+ // Copy this result back into R1.
+ Chain = CurDAG->getNode(ISD::CopyToReg, MVT::Other, Chain, R1Reg, Result);
+
+ // Copy this result back out of R1 to make sure we're not using the stack
+ // space without decrementing the stack pointer.
+ Result = CurDAG->getCopyFromReg(Chain, PPC::R1, MVT::i32);
+
+ // Finally, replace the DYNAMIC_STACKALLOC with the copyfromreg.
+ CodeGenMap[Op.getValue(0)] = Result;
+ CodeGenMap[Op.getValue(1)] = Result.getValue(1);
+ return SDOperand(Result.Val, Op.ResNo);
+}
+
+SDOperand PPC32DAGToDAGISel::SelectADD_PARTS(SDOperand Op) {
+ SDNode *N = Op.Val;
+ SDOperand LHSL = Select(N->getOperand(0));
+ SDOperand LHSH = Select(N->getOperand(1));
+
+ unsigned Imm;
+ bool ME = false, ZE = false;
+ if (isIntImmediate(N->getOperand(3), Imm)) {
+ ME = (signed)Imm == -1;
+ ZE = Imm == 0;
+ }
+
+ std::vector<SDOperand> Result;
+ SDOperand CarryFromLo;
+ if (isIntImmediate(N->getOperand(2), Imm) &&
+ ((signed)Imm >= -32768 || (signed)Imm < 32768)) {
+ // Codegen the low 32 bits of the add. Interestingly, there is no
+ // shifted form of add immediate carrying.
+ CarryFromLo = CurDAG->getTargetNode(PPC::ADDIC, MVT::i32, MVT::Flag,
+ LHSL, getI32Imm(Imm));
+ } else {
+ CarryFromLo = CurDAG->getTargetNode(PPC::ADDC, MVT::i32, MVT::Flag,
+ LHSL, Select(N->getOperand(2)));
+ }
+ CarryFromLo = CarryFromLo.getValue(1);
+
+ // Codegen the high 32 bits, adding zero, minus one, or the full value
+ // along with the carry flag produced by addc/addic.
+ SDOperand ResultHi;
+ if (ZE)
+ ResultHi = CurDAG->getTargetNode(PPC::ADDZE, MVT::i32, LHSH, CarryFromLo);
+ else if (ME)
+ ResultHi = CurDAG->getTargetNode(PPC::ADDME, MVT::i32, LHSH, CarryFromLo);
+ else
+ ResultHi = CurDAG->getTargetNode(PPC::ADDE, MVT::i32, LHSH,
+ Select(N->getOperand(3)), CarryFromLo);
+ Result.push_back(CarryFromLo.getValue(0));
+ Result.push_back(ResultHi);
+
+ CodeGenMap[Op.getValue(0)] = Result[0];
+ CodeGenMap[Op.getValue(1)] = Result[1];
+ return Result[Op.ResNo];
+}
+SDOperand PPC32DAGToDAGISel::SelectSUB_PARTS(SDOperand Op) {
+ SDNode *N = Op.Val;
+ SDOperand LHSL = Select(N->getOperand(0));
+ SDOperand LHSH = Select(N->getOperand(1));
+ SDOperand RHSL = Select(N->getOperand(2));
+ SDOperand RHSH = Select(N->getOperand(3));
+
+ std::vector<SDOperand> Result;
+ Result.push_back(CurDAG->getTargetNode(PPC::SUBFC, MVT::i32, MVT::Flag,
+ RHSL, LHSL));
+ Result.push_back(CurDAG->getTargetNode(PPC::SUBFE, MVT::i32, RHSH, LHSH,
+ Result[0].getValue(1)));
+ CodeGenMap[Op.getValue(0)] = Result[0];
+ CodeGenMap[Op.getValue(1)] = Result[1];
+ return Result[Op.ResNo];
+}
+
+SDOperand PPC32DAGToDAGISel::SelectSETCC(SDOperand Op) {
+ SDNode *N = Op.Val;
+ unsigned Imm;
+ ISD::CondCode CC = cast<CondCodeSDNode>(N->getOperand(2))->get();
+ if (isIntImmediate(N->getOperand(1), Imm)) {
+ // We can codegen setcc op, imm very efficiently compared to a brcond.
+ // Check for those cases here.
+ // setcc op, 0
+ if (Imm == 0) {
+ SDOperand Op = Select(N->getOperand(0));
+ switch (CC) {
+ default: assert(0 && "Unhandled SetCC condition"); abort();
+ case ISD::SETEQ:
+ Op = CurDAG->getTargetNode(PPC::CNTLZW, MVT::i32, Op);
+ CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Op, getI32Imm(27),
+ getI32Imm(5), getI32Imm(31));
+ break;
+ case ISD::SETNE: {
+ SDOperand AD = CurDAG->getTargetNode(PPC::ADDIC, MVT::i32, MVT::Flag,
+ Op, getI32Imm(~0U));
+ CurDAG->SelectNodeTo(N, PPC::SUBFE, MVT::i32, AD, Op, AD.getValue(1));
+ break;
+ }
+ case ISD::SETLT:
+ CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, Op, getI32Imm(1),
+ getI32Imm(31), getI32Imm(31));
+ break;
+ case ISD::SETGT: {
+ SDOperand T = CurDAG->getTargetNode(PPC::NEG, MVT::i32, Op);
+ T = CurDAG->getTargetNode(PPC::ANDC, MVT::i32, T, Op);;
+ CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, T, getI32Imm(1),
+ getI32Imm(31), getI32Imm(31));
+ break;
+ }
+ }
+ return SDOperand(N, 0);
+ } else if (Imm == ~0U) { // setcc op, -1
+ SDOperand Op = Select(N->getOperand(0));
+ switch (CC) {
+ default: assert(0 && "Unhandled SetCC condition"); abort();
+ case ISD::SETEQ:
+ Op = CurDAG->getTargetNode(PPC::ADDIC, MVT::i32, MVT::Flag,
+ Op, getI32Imm(1));
+ CurDAG->SelectNodeTo(N, PPC::ADDZE, MVT::i32,
+ CurDAG->getTargetNode(PPC::LI, MVT::i32,
+ getI32Imm(0)),
+ Op.getValue(1));
+ break;
+ case ISD::SETNE: {
+ Op = CurDAG->getTargetNode(PPC::NOR, MVT::i32, Op, Op);
+ SDOperand AD = CurDAG->getTargetNode(PPC::ADDIC, MVT::i32, MVT::Flag,
+ Op, getI32Imm(~0U));
+ CurDAG->SelectNodeTo(N, PPC::SUBFE, MVT::i32, AD, Op, AD.getValue(1));
+ break;
+ }
+ case ISD::SETLT: {
+ SDOperand AD = CurDAG->getTargetNode(PPC::ADDI, MVT::i32, Op,
+ getI32Imm(1));
+ SDOperand AN = CurDAG->getTargetNode(PPC::AND, MVT::i32, AD, Op);
+ CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, AN, getI32Imm(1),
+ getI32Imm(31), getI32Imm(31));
+ break;
+ }
+ case ISD::SETGT:
+ Op = CurDAG->getTargetNode(PPC::RLWINM, MVT::i32, Op, getI32Imm(1),
+ getI32Imm(31), getI32Imm(31));
+ CurDAG->SelectNodeTo(N, PPC::XORI, MVT::i32, Op, getI32Imm(1));
+ break;
+ }
+ return SDOperand(N, 0);
+ }
+ }
+
+ bool Inv;
+ unsigned Idx = getCRIdxForSetCC(CC, Inv);
+ SDOperand CCReg = SelectCC(N->getOperand(0), N->getOperand(1), CC);
+ SDOperand IntCR;
+
+ // Force the ccreg into CR7.
+ SDOperand CR7Reg = CurDAG->getRegister(PPC::CR7, MVT::i32);
+
+ std::vector<MVT::ValueType> VTs;
+ VTs.push_back(MVT::Other);
+ VTs.push_back(MVT::Flag); // NONSTANDARD CopyToReg node: defines a flag
+ std::vector<SDOperand> Ops;
+ Ops.push_back(CurDAG->getEntryNode());
+ Ops.push_back(CR7Reg);
+ Ops.push_back(CCReg);
+ CCReg = CurDAG->getNode(ISD::CopyToReg, VTs, Ops).getValue(1);
+
+ if (TLI.getTargetMachine().getSubtarget<PPCSubtarget>().isGigaProcessor())
+ IntCR = CurDAG->getTargetNode(PPC::MFOCRF, MVT::i32, CR7Reg, CCReg);
+ else
+ IntCR = CurDAG->getTargetNode(PPC::MFCR, MVT::i32, CCReg);
+
+ if (!Inv) {
+ CurDAG->SelectNodeTo(N, PPC::RLWINM, MVT::i32, IntCR,
+ getI32Imm(32-(3-Idx)), getI32Imm(31), getI32Imm(31));
+ } else {
+ SDOperand Tmp =
+ CurDAG->getTargetNode(PPC::RLWINM, MVT::i32, IntCR,
+ getI32Imm(32-(3-Idx)), getI32Imm(31),getI32Imm(31));
+ CurDAG->SelectNodeTo(N, PPC::XORI, MVT::i32, Tmp, getI32Imm(1));
+ }
+
+ return SDOperand(N, 0);
+}
+