diff options
Diffstat (limited to 'ARMeilleure/Instructions/InstEmitSimdCvt32.cs')
-rw-r--r-- | ARMeilleure/Instructions/InstEmitSimdCvt32.cs | 49 |
1 files changed, 41 insertions, 8 deletions
diff --git a/ARMeilleure/Instructions/InstEmitSimdCvt32.cs b/ARMeilleure/Instructions/InstEmitSimdCvt32.cs index 69ba4274..c76634eb 100644 --- a/ARMeilleure/Instructions/InstEmitSimdCvt32.cs +++ b/ARMeilleure/Instructions/InstEmitSimdCvt32.cs @@ -203,6 +203,9 @@ namespace ARMeilleure.Instructions FPRoundingMode roundMode; switch (rm) { + case 0b00: + roundMode = FPRoundingMode.ToNearestAway; + break; case 0b01: roundMode = FPRoundingMode.ToNearest; break; @@ -228,7 +231,7 @@ namespace ARMeilleure.Instructions bool unsigned = op.Opc == 0; int rm = op.Opc2 & 3; - if (Optimizations.UseSse41 && rm != 0b00) + if (Optimizations.UseSse41) { EmitSse41ConvertInt32(context, RMToRoundMode(rm), !unsigned); } @@ -267,15 +270,21 @@ namespace ARMeilleure.Instructions int rm = op.Opc2 & 3; - if (Optimizations.UseSse2 && rm != 0b00) + if (Optimizations.UseSse41) { EmitScalarUnaryOpSimd32(context, (m) => { - Intrinsic inst = (op.Size & 1) == 0 ? Intrinsic.X86Roundss : Intrinsic.X86Roundsd; - FPRoundingMode roundMode = RMToRoundMode(rm); - return context.AddIntrinsic(inst, m, Const(X86GetRoundControl(roundMode))); + if (roundMode != FPRoundingMode.ToNearestAway) + { + Intrinsic inst = (op.Size & 1) == 0 ? Intrinsic.X86Roundss : Intrinsic.X86Roundsd; + return context.AddIntrinsic(inst, m, Const(X86GetRoundControl(roundMode))); + } + else + { + return EmitSse41RoundToNearestWithTiesToAwayOpF(context, m, scalar: true); + } }); } else @@ -305,7 +314,17 @@ namespace ARMeilleure.Instructions // VRINTA (vector). public static void Vrinta_V(ArmEmitterContext context) { - EmitVectorUnaryOpF32(context, (m) => EmitRoundMathCall(context, MidpointRounding.AwayFromZero, m)); + if (Optimizations.UseSse41) + { + EmitVectorUnaryOpSimd32(context, (m) => + { + return EmitSse41RoundToNearestWithTiesToAwayOpF(context, m, scalar: false); + }); + } + else + { + EmitVectorUnaryOpF32(context, (m) => EmitRoundMathCall(context, MidpointRounding.AwayFromZero, m)); + } } // VRINTM (vector). @@ -413,7 +432,14 @@ namespace ARMeilleure.Instructions Operand nRes = context.AddIntrinsic(Intrinsic.X86Cmpss, n, n, Const((int)CmpCondition.OrderedQ)); nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, n); - nRes = context.AddIntrinsic(Intrinsic.X86Roundss, nRes, Const(X86GetRoundControl(roundMode))); + if (roundMode != FPRoundingMode.ToNearestAway) + { + nRes = context.AddIntrinsic(Intrinsic.X86Roundss, nRes, Const(X86GetRoundControl(roundMode))); + } + else + { + nRes = EmitSse41RoundToNearestWithTiesToAwayOpF(context, nRes, scalar: true); + } Operand zero = context.VectorZero(); @@ -464,7 +490,14 @@ namespace ARMeilleure.Instructions Operand nRes = context.AddIntrinsic(Intrinsic.X86Cmpsd, n, n, Const((int)CmpCondition.OrderedQ)); nRes = context.AddIntrinsic(Intrinsic.X86Pand, nRes, n); - nRes = context.AddIntrinsic(Intrinsic.X86Roundsd, nRes, Const(X86GetRoundControl(roundMode))); + if (roundMode != FPRoundingMode.ToNearestAway) + { + nRes = context.AddIntrinsic(Intrinsic.X86Roundsd, nRes, Const(X86GetRoundControl(roundMode))); + } + else + { + nRes = EmitSse41RoundToNearestWithTiesToAwayOpF(context, nRes, scalar: true); + } Operand zero = context.VectorZero(); |