-// This function expands mips intrinsic nodes which have 64-bit input operands
-// or output values.
-//
-// out64 = intrinsic-node in64
-// =>
-// lo = copy (extract-element (in64, 0))
-// hi = copy (extract-element (in64, 1))
-// mips-specific-node
-// v0 = copy lo
-// v1 = copy hi
-// out64 = merge-values (v0, v1)
-//
-static SDValue LowerDSPIntr(SDValue Op, SelectionDAG &DAG,
- unsigned Opc, bool HasI64In, bool HasI64Out) {
- DebugLoc DL = Op.getDebugLoc();
- bool HasChainIn = Op->getOperand(0).getValueType() == MVT::Other;
- SDValue Chain = HasChainIn ? Op->getOperand(0) : DAG.getEntryNode();
- SmallVector<SDValue, 3> Ops;
-
- if (HasI64In) {
- SDValue InLo = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32,
- Op->getOperand(1 + HasChainIn),
- DAG.getConstant(0, MVT::i32));
- SDValue InHi = DAG.getNode(ISD::EXTRACT_ELEMENT, DL, MVT::i32,
- Op->getOperand(1 + HasChainIn),
- DAG.getConstant(1, MVT::i32));
-
- Chain = DAG.getCopyToReg(Chain, DL, Mips::LO, InLo, SDValue());
- Chain = DAG.getCopyToReg(Chain, DL, Mips::HI, InHi, Chain.getValue(1));
-
- Ops.push_back(Chain);
- Ops.append(Op->op_begin() + HasChainIn + 2, Op->op_end());
- Ops.push_back(Chain.getValue(1));
- } else {
- Ops.push_back(Chain);
- Ops.append(Op->op_begin() + HasChainIn + 1, Op->op_end());
- }
-
- if (!HasI64Out)
- return DAG.getNode(Opc, DL, Op->value_begin(), Op->getNumValues(),
- Ops.begin(), Ops.size());
-
- SDValue Intr = DAG.getNode(Opc, DL, DAG.getVTList(MVT::Other, MVT::Glue),
- Ops.begin(), Ops.size());
- SDValue OutLo = DAG.getCopyFromReg(Intr.getValue(0), DL, Mips::LO, MVT::i32,
- Intr.getValue(1));
- SDValue OutHi = DAG.getCopyFromReg(OutLo.getValue(1), DL, Mips::HI, MVT::i32,
- OutLo.getValue(2));
- SDValue Out = DAG.getNode(ISD::BUILD_PAIR, DL, MVT::i64, OutLo, OutHi);
-
- if (!HasChainIn)
- return Out;
-
- SDValue Vals[] = { Out, OutHi.getValue(1) };
- return DAG.getMergeValues(Vals, 2, DL);
-}
-
-SDValue MipsTargetLowering::LowerINTRINSIC_WO_CHAIN(SDValue Op,
- SelectionDAG &DAG) const {
- switch (cast<ConstantSDNode>(Op->getOperand(0))->getZExtValue()) {
- default:
- return SDValue();
- case Intrinsic::mips_shilo:
- return LowerDSPIntr(Op, DAG, MipsISD::SHILO, true, true);
- case Intrinsic::mips_dpau_h_qbl:
- return LowerDSPIntr(Op, DAG, MipsISD::DPAU_H_QBL, true, true);
- case Intrinsic::mips_dpau_h_qbr:
- return LowerDSPIntr(Op, DAG, MipsISD::DPAU_H_QBR, true, true);
- case Intrinsic::mips_dpsu_h_qbl:
- return LowerDSPIntr(Op, DAG, MipsISD::DPSU_H_QBL, true, true);
- case Intrinsic::mips_dpsu_h_qbr:
- return LowerDSPIntr(Op, DAG, MipsISD::DPSU_H_QBR, true, true);
- case Intrinsic::mips_dpa_w_ph:
- return LowerDSPIntr(Op, DAG, MipsISD::DPA_W_PH, true, true);
- case Intrinsic::mips_dps_w_ph:
- return LowerDSPIntr(Op, DAG, MipsISD::DPS_W_PH, true, true);
- case Intrinsic::mips_dpax_w_ph:
- return LowerDSPIntr(Op, DAG, MipsISD::DPAX_W_PH, true, true);
- case Intrinsic::mips_dpsx_w_ph:
- return LowerDSPIntr(Op, DAG, MipsISD::DPSX_W_PH, true, true);
- case Intrinsic::mips_mulsa_w_ph:
- return LowerDSPIntr(Op, DAG, MipsISD::MULSA_W_PH, true, true);
- case Intrinsic::mips_mult:
- return LowerDSPIntr(Op, DAG, MipsISD::MULT, false, true);
- case Intrinsic::mips_multu:
- return LowerDSPIntr(Op, DAG, MipsISD::MULTU, false, true);
- case Intrinsic::mips_madd:
- return LowerDSPIntr(Op, DAG, MipsISD::MADD_DSP, true, true);
- case Intrinsic::mips_maddu:
- return LowerDSPIntr(Op, DAG, MipsISD::MADDU_DSP, true, true);
- case Intrinsic::mips_msub:
- return LowerDSPIntr(Op, DAG, MipsISD::MSUB_DSP, true, true);
- case Intrinsic::mips_msubu:
- return LowerDSPIntr(Op, DAG, MipsISD::MSUBU_DSP, true, true);
- }
-}
-
-SDValue MipsTargetLowering::LowerINTRINSIC_W_CHAIN(SDValue Op,
- SelectionDAG &DAG) const {
- switch (cast<ConstantSDNode>(Op->getOperand(1))->getZExtValue()) {
- default:
- return SDValue();
- case Intrinsic::mips_extp:
- return LowerDSPIntr(Op, DAG, MipsISD::EXTP, true, false);
- case Intrinsic::mips_extpdp:
- return LowerDSPIntr(Op, DAG, MipsISD::EXTPDP, true, false);
- case Intrinsic::mips_extr_w:
- return LowerDSPIntr(Op, DAG, MipsISD::EXTR_W, true, false);
- case Intrinsic::mips_extr_r_w:
- return LowerDSPIntr(Op, DAG, MipsISD::EXTR_R_W, true, false);
- case Intrinsic::mips_extr_rs_w:
- return LowerDSPIntr(Op, DAG, MipsISD::EXTR_RS_W, true, false);
- case Intrinsic::mips_extr_s_h:
- return LowerDSPIntr(Op, DAG, MipsISD::EXTR_S_H, true, false);
- case Intrinsic::mips_mthlip:
- return LowerDSPIntr(Op, DAG, MipsISD::MTHLIP, true, true);
- case Intrinsic::mips_mulsaq_s_w_ph:
- return LowerDSPIntr(Op, DAG, MipsISD::MULSAQ_S_W_PH, true, true);
- case Intrinsic::mips_maq_s_w_phl:
- return LowerDSPIntr(Op, DAG, MipsISD::MAQ_S_W_PHL, true, true);
- case Intrinsic::mips_maq_s_w_phr:
- return LowerDSPIntr(Op, DAG, MipsISD::MAQ_S_W_PHR, true, true);
- case Intrinsic::mips_maq_sa_w_phl:
- return LowerDSPIntr(Op, DAG, MipsISD::MAQ_SA_W_PHL, true, true);
- case Intrinsic::mips_maq_sa_w_phr:
- return LowerDSPIntr(Op, DAG, MipsISD::MAQ_SA_W_PHR, true, true);
- case Intrinsic::mips_dpaq_s_w_ph:
- return LowerDSPIntr(Op, DAG, MipsISD::DPAQ_S_W_PH, true, true);
- case Intrinsic::mips_dpsq_s_w_ph:
- return LowerDSPIntr(Op, DAG, MipsISD::DPSQ_S_W_PH, true, true);
- case Intrinsic::mips_dpaq_sa_l_w:
- return LowerDSPIntr(Op, DAG, MipsISD::DPAQ_SA_L_W, true, true);
- case Intrinsic::mips_dpsq_sa_l_w:
- return LowerDSPIntr(Op, DAG, MipsISD::DPSQ_SA_L_W, true, true);
- case Intrinsic::mips_dpaqx_s_w_ph:
- return LowerDSPIntr(Op, DAG, MipsISD::DPAQX_S_W_PH, true, true);
- case Intrinsic::mips_dpaqx_sa_w_ph:
- return LowerDSPIntr(Op, DAG, MipsISD::DPAQX_SA_W_PH, true, true);
- case Intrinsic::mips_dpsqx_s_w_ph:
- return LowerDSPIntr(Op, DAG, MipsISD::DPSQX_S_W_PH, true, true);
- case Intrinsic::mips_dpsqx_sa_w_ph:
- return LowerDSPIntr(Op, DAG, MipsISD::DPSQX_SA_W_PH, true, true);
- }
-}
-
-SDValue MipsTargetLowering::LowerADD(SDValue Op, SelectionDAG &DAG) const {