aboutsummaryrefslogtreecommitdiff
path: root/ChocolArm64/Instructions/InstEmitSimdCmp.cs
diff options
context:
space:
mode:
authorLDj3SNuD <35856442+LDj3SNuD@users.noreply.github.com>2018-11-18 03:41:16 +0100
committergdkchan <gab.dark.100@gmail.com>2018-11-18 00:41:16 -0200
commite603b7afbcdff0fc732304872f5a65d410c601f9 (patch)
treed1949402bc6c6edd5a3d6e2ea40d9033a3d2f654 /ChocolArm64/Instructions/InstEmitSimdCmp.cs
parentb7613dd4b8a535d028ae180ee3a4b574abe4e3e0 (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.cs243
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);
}