@@ -842,6 +842,9 @@ AArch64TargetLowering::AArch64TargetLowering(const TargetMachine &TM,
842
842
843
843
setOperationAction(ISD::GET_ROUNDING, MVT::i32, Custom);
844
844
setOperationAction(ISD::SET_ROUNDING, MVT::Other, Custom);
845
+ setOperationAction(ISD::GET_FPMODE, MVT::i32, Custom);
846
+ setOperationAction(ISD::SET_FPMODE, MVT::i32, Custom);
847
+ setOperationAction(ISD::RESET_FPMODE, MVT::Other, Custom);
845
848
846
849
setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i128, Custom);
847
850
if (!Subtarget->hasLSE() && !Subtarget->outlineAtomics()) {
@@ -4870,6 +4873,65 @@ SDValue AArch64TargetLowering::LowerSET_ROUNDING(SDValue Op,
4870
4873
return DAG.getNode(ISD::INTRINSIC_VOID, DL, MVT::Other, Ops2);
4871
4874
}
4872
4875
4876
+ SDValue AArch64TargetLowering::LowerGET_FPMODE(SDValue Op,
4877
+ SelectionDAG &DAG) const {
4878
+ SDLoc DL(Op);
4879
+ SDValue Chain = Op->getOperand(0);
4880
+
4881
+ // Get current value of FPCR.
4882
+ SDValue Ops[] = {
4883
+ Chain, DAG.getTargetConstant(Intrinsic::aarch64_get_fpcr, DL, MVT::i64)};
4884
+ SDValue FPCR =
4885
+ DAG.getNode(ISD::INTRINSIC_W_CHAIN, DL, {MVT::i64, MVT::Other}, Ops);
4886
+ Chain = FPCR.getValue(1);
4887
+ FPCR = FPCR.getValue(0);
4888
+
4889
+ // Truncate FPCR to 32 bits.
4890
+ SDValue Result = DAG.getNode(ISD::TRUNCATE, DL, MVT::i32, FPCR);
4891
+
4892
+ return DAG.getMergeValues({Result, Chain}, DL);
4893
+ }
4894
+
4895
+ SDValue AArch64TargetLowering::LowerSET_FPMODE(SDValue Op,
4896
+ SelectionDAG &DAG) const {
4897
+ SDLoc DL(Op);
4898
+ SDValue Chain = Op->getOperand(0);
4899
+ SDValue Mode = Op->getOperand(1);
4900
+
4901
+ // Extend the specified value to 64 bits.
4902
+ SDValue FPCR = DAG.getZExtOrTrunc(Mode, DL, MVT::i64);
4903
+
4904
+ // Set new value of FPCR.
4905
+ SDValue Ops2[] = {
4906
+ Chain, DAG.getConstant(Intrinsic::aarch64_set_fpcr, DL, MVT::i64), FPCR};
4907
+ return DAG.getNode(ISD::INTRINSIC_VOID, DL, MVT::Other, Ops2);
4908
+ }
4909
+
4910
+ SDValue AArch64TargetLowering::LowerRESET_FPMODE(SDValue Op,
4911
+ SelectionDAG &DAG) const {
4912
+ SDLoc DL(Op);
4913
+ SDValue Chain = Op->getOperand(0);
4914
+
4915
+ // Get current value of FPCR.
4916
+ SDValue Ops[] = {
4917
+ Chain, DAG.getTargetConstant(Intrinsic::aarch64_get_fpcr, DL, MVT::i64)};
4918
+ SDValue FPCR =
4919
+ DAG.getNode(ISD::INTRINSIC_W_CHAIN, DL, {MVT::i64, MVT::Other}, Ops);
4920
+ Chain = FPCR.getValue(1);
4921
+ FPCR = FPCR.getValue(0);
4922
+
4923
+ // Clear bits that are not reserved.
4924
+ SDValue FPSCRMasked = DAG.getNode(
4925
+ ISD::AND, DL, MVT::i64, FPCR,
4926
+ DAG.getConstant(AArch64::ReservedFPControlBits, DL, MVT::i64));
4927
+
4928
+ // Set new value of FPCR.
4929
+ SDValue Ops2[] = {Chain,
4930
+ DAG.getConstant(Intrinsic::aarch64_set_fpcr, DL, MVT::i64),
4931
+ FPSCRMasked};
4932
+ return DAG.getNode(ISD::INTRINSIC_VOID, DL, MVT::Other, Ops2);
4933
+ }
4934
+
4873
4935
static unsigned selectUmullSmull(SDValue &N0, SDValue &N1, SelectionDAG &DAG,
4874
4936
SDLoc DL, bool &IsMLA) {
4875
4937
bool IsN0SExt = isSignExtended(N0, DAG);
@@ -6484,6 +6546,12 @@ SDValue AArch64TargetLowering::LowerOperation(SDValue Op,
6484
6546
return LowerGET_ROUNDING(Op, DAG);
6485
6547
case ISD::SET_ROUNDING:
6486
6548
return LowerSET_ROUNDING(Op, DAG);
6549
+ case ISD::GET_FPMODE:
6550
+ return LowerGET_FPMODE(Op, DAG);
6551
+ case ISD::SET_FPMODE:
6552
+ return LowerSET_FPMODE(Op, DAG);
6553
+ case ISD::RESET_FPMODE:
6554
+ return LowerRESET_FPMODE(Op, DAG);
6487
6555
case ISD::MUL:
6488
6556
return LowerMUL(Op, DAG);
6489
6557
case ISD::MULHS:
0 commit comments