SDNode *MipsDAGToDAGISel::SelectLoadFp64(SDNode *N) { MVT::SimpleValueType NVT = N->getValueType(0).getSimpleVT().SimpleTy; if (!Subtarget.isMips1() || NVT != MVT::f64) return NULL; LoadSDNode *LN = cast<LoadSDNode>(N); if (LN->getExtensionType() != ISD::NON_EXTLOAD || LN->getAddressingMode() != ISD::UNINDEXED) return NULL; SDValue Chain = N->getOperand(0); SDValue N1 = N->getOperand(1); SDValue Offset0, Offset1, Base; if (!SelectAddr(N1, Base, Offset0) || N1.getValueType() != MVT::i32) return NULL; MachineSDNode::mmo_iterator MemRefs0 = MF->allocateMemRefsArray(1); MemRefs0[0] = cast<MemSDNode>(N)->getMemOperand(); DebugLoc dl = N->getDebugLoc(); // The second load should start after for 4 bytes. if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Offset0)) Offset1 = CurDAG->getTargetConstant(C->getSExtValue()+4, MVT::i32); else if (ConstantPoolSDNode *CP = dyn_cast<ConstantPoolSDNode>(Offset0)) Offset1 = CurDAG->getTargetConstantPool(CP->getConstVal(), MVT::i32, CP->getAlignment(), CP->getOffset()+4, CP->getTargetFlags()); else return NULL; // Choose the offsets depending on the endianess if (TM.getTargetData()->isBigEndian()) std::swap(Offset0, Offset1); // Instead of: // ldc $f0, X($3) // Generate: // lwc $f0, X($3) // lwc $f1, X+4($3) SDNode *LD0 = CurDAG->getMachineNode(Mips::LWC1, dl, MVT::f32, MVT::Other, Base, Offset0, Chain); SDValue Undef = SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, dl, NVT), 0); SDValue I0 = CurDAG->getTargetInsertSubreg(Mips::sub_fpeven, dl, MVT::f64, Undef, SDValue(LD0, 0)); SDNode *LD1 = CurDAG->getMachineNode(Mips::LWC1, dl, MVT::f32, MVT::Other, Base, Offset1, SDValue(LD0, 1)); SDValue I1 = CurDAG->getTargetInsertSubreg(Mips::sub_fpodd, dl, MVT::f64, I0, SDValue(LD1, 0)); ReplaceUses(SDValue(N, 0), I1); ReplaceUses(SDValue(N, 1), Chain); cast<MachineSDNode>(LD0)->setMemRefs(MemRefs0, MemRefs0 + 1); cast<MachineSDNode>(LD1)->setMemRefs(MemRefs0, MemRefs0 + 1); return I1.getNode(); }