// on SparcV8 and later.
setOperationAction(ISD::ATOMIC_FENCE, MVT::Other, Expand);
+ if (!Subtarget->isV9()) {
+ // SparcV8 does not have FNEGD and FABSD.
+ setOperationAction(ISD::FNEG, MVT::f64, Custom);
+ setOperationAction(ISD::FABS, MVT::f64, Custom);
+ }
+
setOperationAction(ISD::FSIN , MVT::f64, Expand);
setOperationAction(ISD::FCOS , MVT::f64, Expand);
setOperationAction(ISD::FSINCOS, MVT::f64, Expand);
setStackPointerRegisterToSaveRestore(SP::O6);
- if (TM.getSubtarget<SparcSubtarget>().isV9())
+ if (Subtarget->isV9())
setOperationAction(ISD::CTPOP, MVT::i32, Legal);
setMinFunctionAlignment(2);
return RetAddr;
}
+static SDValue LowerF64Op(SDValue Op, SelectionDAG &DAG)
+{
+ SDLoc dl(Op);
+
+ assert(Op.getValueType() == MVT::f64 && "LowerF64Op called on non-double!");
+ assert(Op.getOpcode() == ISD::FNEG || Op.getOpcode() == ISD::FABS);
+
+ // Lower fneg/fabs on f64 to fneg/fabs on f32.
+ // fneg f64 => fneg f32:sub_even, fmov f32:sub_odd.
+ // fabs f64 => fabs f32:sub_even, fmov f32:sub_odd.
+
+ SDValue SrcReg64 = Op.getOperand(0);
+ SDValue Hi32 = DAG.getTargetExtractSubreg(SP::sub_even, dl, MVT::f32,
+ SrcReg64);
+ SDValue Lo32 = DAG.getTargetExtractSubreg(SP::sub_odd, dl, MVT::f32,
+ SrcReg64);
+
+ Hi32 = DAG.getNode(Op.getOpcode(), dl, MVT::f32, Hi32);
+
+ SDValue DstReg64 = SDValue(DAG.getMachineNode(TargetOpcode::IMPLICIT_DEF,
+ dl, MVT::f64), 0);
+ DstReg64 = DAG.getTargetInsertSubreg(SP::sub_even, dl, MVT::f64,
+ DstReg64, Hi32);
+ DstReg64 = DAG.getTargetInsertSubreg(SP::sub_odd, dl, MVT::f64,
+ DstReg64, Lo32);
+ return DstReg64;
+}
+
SDValue SparcTargetLowering::
LowerOperation(SDValue Op, SelectionDAG &DAG) const {
switch (Op.getOpcode()) {
default: llvm_unreachable("Should not custom lower this!");
+
+ case ISD::FNEG:
+ case ISD::FABS: return LowerF64Op(Op, DAG);
+
case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG);
case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG);
case ISD::GlobalTLSAddress: