diff options
| author | LDj3SNuD <35856442+LDj3SNuD@users.noreply.github.com> | 2018-11-18 03:41:16 +0100 |
|---|---|---|
| committer | gdkchan <gab.dark.100@gmail.com> | 2018-11-18 00:41:16 -0200 |
| commit | e603b7afbcdff0fc732304872f5a65d410c601f9 (patch) | |
| tree | d1949402bc6c6edd5a3d6e2ea40d9033a3d2f654 /ChocolArm64/Instructions/InstEmitSimdCmp.cs | |
| parent | b7613dd4b8a535d028ae180ee3a4b574abe4e3e0 (diff) | |
Add Sse Opt. for S/Umax_V, S/Umin_V, S/Uaddw_V, S/Usubw_V, Fabs_S/V, Fneg_S/V Inst.; for Fcvtl_V, Fcvtn_V Inst.; and for Fcmp_S Inst.. Add/Improve other Sse Opt.. Add Tests. (#496)
* Update CpuTest.cs
* Update CpuTestSimd.cs
* Update CpuTestSimdReg.cs
* Update InstEmitSimdCmp.cs
* Update SoftFloat.cs
* Update InstEmitAluHelper.cs
* Update InstEmitSimdArithmetic.cs
* Update InstEmitSimdHelper.cs
* Update VectorHelper.cs
* Update InstEmitSimdCvt.cs
* Update InstEmitSimdArithmetic.cs
* Update CpuTestSimd.cs
* Update InstEmitSimdArithmetic.cs
* Update OpCodeTable.cs
* Update InstEmitSimdArithmetic.cs
* Update InstEmitSimdCmp.cs
* Update InstEmitSimdCvt.cs
* Update CpuTestSimd.cs
* Update CpuTestSimdReg.cs
* Create CpuTestSimdFcond.cs
* Update OpCodeTable.cs
* Update InstEmitSimdMove.cs
* Update CpuTestSimdIns.cs
* Create CpuTestSimdExt.cs
* Nit.
* Update PackageReference.
Diffstat (limited to 'ChocolArm64/Instructions/InstEmitSimdCmp.cs')
| -rw-r--r-- | ChocolArm64/Instructions/InstEmitSimdCmp.cs | 243 |
1 files changed, 166 insertions, 77 deletions
diff --git a/ChocolArm64/Instructions/InstEmitSimdCmp.cs b/ChocolArm64/Instructions/InstEmitSimdCmp.cs index c473c0ae..3ee25482 100644 --- a/ChocolArm64/Instructions/InstEmitSimdCmp.cs +++ b/ChocolArm64/Instructions/InstEmitSimdCmp.cs @@ -3,6 +3,7 @@ using ChocolArm64.State; using ChocolArm64.Translation; using System; using System.Reflection.Emit; +using System.Runtime.Intrinsics; using System.Runtime.Intrinsics.X86; using static ChocolArm64.Instructions.InstEmitAluHelper; @@ -137,26 +138,43 @@ namespace ChocolArm64.Instructions context.EmitCondBranch(lblTrue, op.Cond); - EmitSetNzcv(context, op.Nzcv); + context.EmitLdc_I4(op.Nzcv); + EmitSetNzcv(context); context.Emit(OpCodes.Br, lblEnd); context.MarkLabel(lblTrue); - Fcmp_S(context); + EmitFcmpE(context, signalNaNs: false); context.MarkLabel(lblEnd); } public static void Fccmpe_S(ILEmitterCtx context) { - Fccmp_S(context); + OpCodeSimdFcond64 op = (OpCodeSimdFcond64)context.CurrOp; + + ILLabel lblTrue = new ILLabel(); + ILLabel lblEnd = new ILLabel(); + + context.EmitCondBranch(lblTrue, op.Cond); + + context.EmitLdc_I4(op.Nzcv); + EmitSetNzcv(context); + + context.Emit(OpCodes.Br, lblEnd); + + context.MarkLabel(lblTrue); + + EmitFcmpE(context, signalNaNs: true); + + context.MarkLabel(lblEnd); } public static void Fcmeq_S(ILEmitterCtx context) { if (context.CurrOp is OpCodeSimdReg64 && Optimizations.UseSse - && Optimizations.UseSse2) + && Optimizations.UseSse2) { EmitScalarSseOrSse2OpF(context, nameof(Sse.CompareEqualScalar)); } @@ -169,7 +187,7 @@ namespace ChocolArm64.Instructions public static void Fcmeq_V(ILEmitterCtx context) { if (context.CurrOp is OpCodeSimdReg64 && Optimizations.UseSse - && Optimizations.UseSse2) + && Optimizations.UseSse2) { EmitVectorSseOrSse2OpF(context, nameof(Sse.CompareEqual)); } @@ -182,7 +200,7 @@ namespace ChocolArm64.Instructions public static void Fcmge_S(ILEmitterCtx context) { if (context.CurrOp is OpCodeSimdReg64 && Optimizations.UseSse - && Optimizations.UseSse2) + && Optimizations.UseSse2) { EmitScalarSseOrSse2OpF(context, nameof(Sse.CompareGreaterThanOrEqualScalar)); } @@ -195,7 +213,7 @@ namespace ChocolArm64.Instructions public static void Fcmge_V(ILEmitterCtx context) { if (context.CurrOp is OpCodeSimdReg64 && Optimizations.UseSse - && Optimizations.UseSse2) + && Optimizations.UseSse2) { EmitVectorSseOrSse2OpF(context, nameof(Sse.CompareGreaterThanOrEqual)); } @@ -208,7 +226,7 @@ namespace ChocolArm64.Instructions public static void Fcmgt_S(ILEmitterCtx context) { if (context.CurrOp is OpCodeSimdReg64 && Optimizations.UseSse - && Optimizations.UseSse2) + && Optimizations.UseSse2) { EmitScalarSseOrSse2OpF(context, nameof(Sse.CompareGreaterThanScalar)); } @@ -221,7 +239,7 @@ namespace ChocolArm64.Instructions public static void Fcmgt_V(ILEmitterCtx context) { if (context.CurrOp is OpCodeSimdReg64 && Optimizations.UseSse - && Optimizations.UseSse2) + && Optimizations.UseSse2) { EmitVectorSseOrSse2OpF(context, nameof(Sse.CompareGreaterThan)); } @@ -253,109 +271,180 @@ namespace ChocolArm64.Instructions public static void Fcmp_S(ILEmitterCtx context) { + EmitFcmpE(context, signalNaNs: false); + } + + public static void Fcmpe_S(ILEmitterCtx context) + { + EmitFcmpE(context, signalNaNs: true); + } + + private static void EmitFcmpE(ILEmitterCtx context, bool signalNaNs) + { OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp; bool cmpWithZero = !(op is OpCodeSimdFcond64) ? op.Bit3 : false; - //Handle NaN case. - //If any number is NaN, then NZCV = 0011. - if (cmpWithZero) - { - EmitNaNCheck(context, op.Rn); - } - else + if (Optimizations.FastFP && Optimizations.UseSse2) { - EmitNaNCheck(context, op.Rn); - EmitNaNCheck(context, op.Rm); + if (op.Size == 0) + { + Type[] typesCmp = new Type[] { typeof(Vector128<float>), typeof(Vector128<float>) }; - context.Emit(OpCodes.Or); - } + ILLabel lblNaN = new ILLabel(); + ILLabel lblEnd = new ILLabel(); - ILLabel lblNaN = new ILLabel(); - ILLabel lblEnd = new ILLabel(); + context.EmitLdvec(op.Rn); - context.Emit(OpCodes.Brtrue_S, lblNaN); + context.Emit(OpCodes.Dup); + context.EmitStvectmp(); - void EmitLoadOpers() - { - EmitVectorExtractF(context, op.Rn, 0, op.Size); - - if (cmpWithZero) - { - if (op.Size == 0) + if (cmpWithZero) { - context.EmitLdc_R4(0f); + VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); } - else /* if (Op.Size == 1) */ + else { - context.EmitLdc_R8(0d); + context.EmitLdvec(op.Rm); } + + context.Emit(OpCodes.Dup); + context.EmitStvectmp2(); + + context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.CompareOrderedScalar), typesCmp)); + VectorHelper.EmitCall(context, nameof(VectorHelper.VectorSingleZero)); + + context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.CompareEqualOrderedScalar), typesCmp)); + + context.Emit(OpCodes.Brtrue_S, lblNaN); + + context.EmitLdc_I4(0); + + context.EmitLdvectmp(); + context.EmitLdvectmp2(); + context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.CompareGreaterThanOrEqualOrderedScalar), typesCmp)); + + context.EmitLdvectmp(); + context.EmitLdvectmp2(); + context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.CompareEqualOrderedScalar), typesCmp)); + + context.EmitLdvectmp(); + context.EmitLdvectmp2(); + context.EmitCall(typeof(Sse).GetMethod(nameof(Sse.CompareLessThanOrderedScalar), typesCmp)); + + context.EmitStflg((int)PState.NBit); + context.EmitStflg((int)PState.ZBit); + context.EmitStflg((int)PState.CBit); + context.EmitStflg((int)PState.VBit); + + context.Emit(OpCodes.Br_S, lblEnd); + + context.MarkLabel(lblNaN); + + context.EmitLdc_I4(1); + context.Emit(OpCodes.Dup); + context.EmitLdc_I4(0); + context.Emit(OpCodes.Dup); + + context.EmitStflg((int)PState.NBit); + context.EmitStflg((int)PState.ZBit); + context.EmitStflg((int)PState.CBit); + context.EmitStflg((int)PState.VBit); + + context.MarkLabel(lblEnd); } - else + else /* if (op.Size == 1) */ { - EmitVectorExtractF(context, op.Rm, 0, op.Size); - } - } - - //Z = Rn == Rm - EmitLoadOpers(); + Type[] typesCmp = new Type[] { typeof(Vector128<double>), typeof(Vector128<double>) }; - context.Emit(OpCodes.Ceq); - context.Emit(OpCodes.Dup); + ILLabel lblNaN = new ILLabel(); + ILLabel lblEnd = new ILLabel(); - context.EmitStflg((int)PState.ZBit); + EmitLdvecWithCastToDouble(context, op.Rn); - //C = Rn >= Rm - EmitLoadOpers(); + context.Emit(OpCodes.Dup); + context.EmitStvectmp(); - context.Emit(OpCodes.Cgt); - context.Emit(OpCodes.Or); + if (cmpWithZero) + { + VectorHelper.EmitCall(context, nameof(VectorHelper.VectorDoubleZero)); + } + else + { + EmitLdvecWithCastToDouble(context, op.Rm); + } - context.EmitStflg((int)PState.CBit); + context.Emit(OpCodes.Dup); + context.EmitStvectmp2(); - //N = Rn < Rm - EmitLoadOpers(); + context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareOrderedScalar), typesCmp)); + VectorHelper.EmitCall(context, nameof(VectorHelper.VectorDoubleZero)); - context.Emit(OpCodes.Clt); + context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareEqualOrderedScalar), typesCmp)); - context.EmitStflg((int)PState.NBit); + context.Emit(OpCodes.Brtrue_S, lblNaN); - //V = 0 - context.EmitLdc_I4(0); + context.EmitLdc_I4(0); - context.EmitStflg((int)PState.VBit); + context.EmitLdvectmp(); + context.EmitLdvectmp2(); + context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareGreaterThanOrEqualOrderedScalar), typesCmp)); - context.Emit(OpCodes.Br_S, lblEnd); + context.EmitLdvectmp(); + context.EmitLdvectmp2(); + context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareEqualOrderedScalar), typesCmp)); - context.MarkLabel(lblNaN); + context.EmitLdvectmp(); + context.EmitLdvectmp2(); + context.EmitCall(typeof(Sse2).GetMethod(nameof(Sse2.CompareLessThanOrderedScalar), typesCmp)); - EmitSetNzcv(context, 0b0011); + context.EmitStflg((int)PState.NBit); + context.EmitStflg((int)PState.ZBit); + context.EmitStflg((int)PState.CBit); + context.EmitStflg((int)PState.VBit); - context.MarkLabel(lblEnd); - } + context.Emit(OpCodes.Br_S, lblEnd); - public static void Fcmpe_S(ILEmitterCtx context) - { - Fcmp_S(context); - } + context.MarkLabel(lblNaN); - private static void EmitNaNCheck(ILEmitterCtx context, int reg) - { - IOpCodeSimd64 op = (IOpCodeSimd64)context.CurrOp; + context.EmitLdc_I4(1); + context.Emit(OpCodes.Dup); + context.EmitLdc_I4(0); + context.Emit(OpCodes.Dup); - EmitVectorExtractF(context, reg, 0, op.Size); + context.EmitStflg((int)PState.NBit); + context.EmitStflg((int)PState.ZBit); + context.EmitStflg((int)PState.CBit); + context.EmitStflg((int)PState.VBit); - if (op.Size == 0) - { - context.EmitCall(typeof(float), nameof(float.IsNaN)); - } - else if (op.Size == 1) - { - context.EmitCall(typeof(double), nameof(double.IsNaN)); + context.MarkLabel(lblEnd); + } } else { - throw new InvalidOperationException(); + EmitVectorExtractF(context, op.Rn, 0, op.Size); + + if (cmpWithZero) + { + if (op.Size == 0) + { + context.EmitLdc_R4(0f); + } + else // if (op.Size == 1) + { + context.EmitLdc_R8(0d); + } + } + else + { + EmitVectorExtractF(context, op.Rm, 0, op.Size); + } + + context.EmitLdc_I4(!signalNaNs ? 0 : 1); + + EmitSoftFloatCall(context, nameof(SoftFloat32.FPCompare)); + + EmitSetNzcv(context); } } @@ -486,7 +575,7 @@ namespace ChocolArm64.Instructions { context.EmitLdc_R4(0f); } - else /* if (SizeF == 1) */ + else /* if (sizeF == 1) */ { context.EmitLdc_R8(0d); } |
