aboutsummaryrefslogtreecommitdiff
path: root/ChocolArm64/Instructions/InstEmitSimdShift.cs
diff options
context:
space:
mode:
authorLDj3SNuD <35856442+LDj3SNuD@users.noreply.github.com>2018-12-02 01:34:43 +0100
committergdkchan <gab.dark.100@gmail.com>2018-12-01 22:34:43 -0200
commitad00fd02442cf9c0f00c4562635738042b521efa (patch)
treecf1e9607e41f616d2c0ad171406fc1d271d45456 /ChocolArm64/Instructions/InstEmitSimdShift.cs
parent9b22e8af5ee3e0896fc5f464022579ef0713e504 (diff)
Fix Sshl_V; Add S/Uqrshl_V, S/Uqshl_V, S/Urshl_V; Add Tests. (#516)
* Update OpCodeTable.cs * Update InstEmitSimdShift.cs * Update SoftFallback.cs * Update CpuTestSimdReg.cs * Nit. * Update SoftFallback.cs * Update Optimizations.cs * Update InstEmitSimdLogical.cs * Update InstEmitSimdArithmetic.cs
Diffstat (limited to 'ChocolArm64/Instructions/InstEmitSimdShift.cs')
-rw-r--r--ChocolArm64/Instructions/InstEmitSimdShift.cs273
1 files changed, 208 insertions, 65 deletions
diff --git a/ChocolArm64/Instructions/InstEmitSimdShift.cs b/ChocolArm64/Instructions/InstEmitSimdShift.cs
index b183e8aa..5b606167 100644
--- a/ChocolArm64/Instructions/InstEmitSimdShift.cs
+++ b/ChocolArm64/Instructions/InstEmitSimdShift.cs
@@ -110,6 +110,34 @@ namespace ChocolArm64.Instructions
}
}
+ public static void Sqrshl_V(ILEmitterCtx context)
+ {
+ OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;
+
+ int bytes = op.GetBitsCount() >> 3;
+ int elems = bytes >> op.Size;
+
+ for (int index = 0; index < elems; index++)
+ {
+ EmitVectorExtractSx(context, op.Rn, index, op.Size);
+ EmitVectorExtractSx(context, op.Rm, index, op.Size);
+
+ context.Emit(OpCodes.Ldc_I4_1);
+ context.EmitLdc_I4(op.Size);
+
+ context.EmitLdarg(TranslatedSub.StateArgIdx);
+
+ SoftFallback.EmitCall(context, nameof(SoftFallback.SignedShlRegSatQ));
+
+ EmitVectorInsert(context, op.Rd, index, op.Size);
+ }
+
+ if (op.RegisterSize == RegisterSize.Simd64)
+ {
+ EmitVectorZeroUpper(context, op.Rd);
+ }
+ }
+
public static void Sqrshrn_S(ILEmitterCtx context)
{
EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarSxSx);
@@ -130,6 +158,34 @@ namespace ChocolArm64.Instructions
EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorSxZx);
}
+ public static void Sqshl_V(ILEmitterCtx context)
+ {
+ OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;
+
+ int bytes = op.GetBitsCount() >> 3;
+ int elems = bytes >> op.Size;
+
+ for (int index = 0; index < elems; index++)
+ {
+ EmitVectorExtractSx(context, op.Rn, index, op.Size);
+ EmitVectorExtractSx(context, op.Rm, index, op.Size);
+
+ context.Emit(OpCodes.Ldc_I4_0);
+ context.EmitLdc_I4(op.Size);
+
+ context.EmitLdarg(TranslatedSub.StateArgIdx);
+
+ SoftFallback.EmitCall(context, nameof(SoftFallback.SignedShlRegSatQ));
+
+ EmitVectorInsert(context, op.Rd, index, op.Size);
+ }
+
+ if (op.RegisterSize == RegisterSize.Simd64)
+ {
+ EmitVectorZeroUpper(context, op.Rd);
+ }
+ }
+
public static void Sqshrn_S(ILEmitterCtx context)
{
EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarSxSx);
@@ -150,6 +206,32 @@ namespace ChocolArm64.Instructions
EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorSxZx);
}
+ public static void Srshl_V(ILEmitterCtx context)
+ {
+ OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;
+
+ int bytes = op.GetBitsCount() >> 3;
+ int elems = bytes >> op.Size;
+
+ for (int index = 0; index < elems; index++)
+ {
+ EmitVectorExtractSx(context, op.Rn, index, op.Size);
+ EmitVectorExtractSx(context, op.Rm, index, op.Size);
+
+ context.Emit(OpCodes.Ldc_I4_1);
+ context.EmitLdc_I4(op.Size);
+
+ SoftFallback.EmitCall(context, nameof(SoftFallback.SignedShlReg));
+
+ EmitVectorInsert(context, op.Rd, index, op.Size);
+ }
+
+ if (op.RegisterSize == RegisterSize.Simd64)
+ {
+ EmitVectorZeroUpper(context, op.Rd);
+ }
+ }
+
public static void Srshr_S(ILEmitterCtx context)
{
EmitScalarShrImmOpSx(context, ShrImmFlags.Round);
@@ -252,7 +334,28 @@ namespace ChocolArm64.Instructions
public static void Sshl_V(ILEmitterCtx context)
{
- EmitVectorShl(context, signed: true);
+ OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;
+
+ int bytes = op.GetBitsCount() >> 3;
+ int elems = bytes >> op.Size;
+
+ for (int index = 0; index < elems; index++)
+ {
+ EmitVectorExtractSx(context, op.Rn, index, op.Size);
+ EmitVectorExtractSx(context, op.Rm, index, op.Size);
+
+ context.Emit(OpCodes.Ldc_I4_0);
+ context.EmitLdc_I4(op.Size);
+
+ SoftFallback.EmitCall(context, nameof(SoftFallback.SignedShlReg));
+
+ EmitVectorInsert(context, op.Rd, index, op.Size);
+ }
+
+ if (op.RegisterSize == RegisterSize.Simd64)
+ {
+ EmitVectorZeroUpper(context, op.Rd);
+ }
}
public static void Sshll_V(ILEmitterCtx context)
@@ -330,6 +433,34 @@ namespace ChocolArm64.Instructions
}
}
+ public static void Uqrshl_V(ILEmitterCtx context)
+ {
+ OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;
+
+ int bytes = op.GetBitsCount() >> 3;
+ int elems = bytes >> op.Size;
+
+ for (int index = 0; index < elems; index++)
+ {
+ EmitVectorExtractZx(context, op.Rn, index, op.Size);
+ EmitVectorExtractZx(context, op.Rm, index, op.Size);
+
+ context.Emit(OpCodes.Ldc_I4_1);
+ context.EmitLdc_I4(op.Size);
+
+ context.EmitLdarg(TranslatedSub.StateArgIdx);
+
+ SoftFallback.EmitCall(context, nameof(SoftFallback.UnsignedShlRegSatQ));
+
+ EmitVectorInsert(context, op.Rd, index, op.Size);
+ }
+
+ if (op.RegisterSize == RegisterSize.Simd64)
+ {
+ EmitVectorZeroUpper(context, op.Rd);
+ }
+ }
+
public static void Uqrshrn_S(ILEmitterCtx context)
{
EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarZxZx);
@@ -340,6 +471,34 @@ namespace ChocolArm64.Instructions
EmitRoundShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorZxZx);
}
+ public static void Uqshl_V(ILEmitterCtx context)
+ {
+ OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;
+
+ int bytes = op.GetBitsCount() >> 3;
+ int elems = bytes >> op.Size;
+
+ for (int index = 0; index < elems; index++)
+ {
+ EmitVectorExtractZx(context, op.Rn, index, op.Size);
+ EmitVectorExtractZx(context, op.Rm, index, op.Size);
+
+ context.Emit(OpCodes.Ldc_I4_0);
+ context.EmitLdc_I4(op.Size);
+
+ context.EmitLdarg(TranslatedSub.StateArgIdx);
+
+ SoftFallback.EmitCall(context, nameof(SoftFallback.UnsignedShlRegSatQ));
+
+ EmitVectorInsert(context, op.Rd, index, op.Size);
+ }
+
+ if (op.RegisterSize == RegisterSize.Simd64)
+ {
+ EmitVectorZeroUpper(context, op.Rd);
+ }
+ }
+
public static void Uqshrn_S(ILEmitterCtx context)
{
EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.ScalarZxZx);
@@ -350,6 +509,32 @@ namespace ChocolArm64.Instructions
EmitShrImmSaturatingNarrowOp(context, ShrImmSaturatingNarrowFlags.VectorZxZx);
}
+ public static void Urshl_V(ILEmitterCtx context)
+ {
+ OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;
+
+ int bytes = op.GetBitsCount() >> 3;
+ int elems = bytes >> op.Size;
+
+ for (int index = 0; index < elems; index++)
+ {
+ EmitVectorExtractZx(context, op.Rn, index, op.Size);
+ EmitVectorExtractZx(context, op.Rm, index, op.Size);
+
+ context.Emit(OpCodes.Ldc_I4_1);
+ context.EmitLdc_I4(op.Size);
+
+ SoftFallback.EmitCall(context, nameof(SoftFallback.UnsignedShlReg));
+
+ EmitVectorInsert(context, op.Rd, index, op.Size);
+ }
+
+ if (op.RegisterSize == RegisterSize.Simd64)
+ {
+ EmitVectorZeroUpper(context, op.Rd);
+ }
+ }
+
public static void Urshr_S(ILEmitterCtx context)
{
EmitScalarShrImmOpZx(context, ShrImmFlags.Round);
@@ -450,7 +635,28 @@ namespace ChocolArm64.Instructions
public static void Ushl_V(ILEmitterCtx context)
{
- EmitVectorShl(context, signed: false);
+ OpCodeSimdReg64 op = (OpCodeSimdReg64)context.CurrOp;
+
+ int bytes = op.GetBitsCount() >> 3;
+ int elems = bytes >> op.Size;
+
+ for (int index = 0; index < elems; index++)
+ {
+ EmitVectorExtractZx(context, op.Rn, index, op.Size);
+ EmitVectorExtractZx(context, op.Rm, index, op.Size);
+
+ context.Emit(OpCodes.Ldc_I4_0);
+ context.EmitLdc_I4(op.Size);
+
+ SoftFallback.EmitCall(context, nameof(SoftFallback.UnsignedShlReg));
+
+ EmitVectorInsert(context, op.Rd, index, op.Size);
+ }
+
+ if (op.RegisterSize == RegisterSize.Simd64)
+ {
+ EmitVectorZeroUpper(context, op.Rd);
+ }
}
public static void Ushll_V(ILEmitterCtx context)
@@ -526,69 +732,6 @@ namespace ChocolArm64.Instructions
}
}
- private static void EmitVectorShl(ILEmitterCtx context, bool signed)
- {
- //This instruction shifts the value on vector A by the number of bits
- //specified on the signed, lower 8 bits of vector B. If the shift value
- //is greater or equal to the data size of each lane, then the result is zero.
- //Additionally, negative shifts produces right shifts by the negated shift value.
- OpCodeSimd64 op = (OpCodeSimd64)context.CurrOp;
-
- int maxShift = 8 << op.Size;
-
- Action emit = () =>
- {
- ILLabel lblShl = new ILLabel();
- ILLabel lblZero = new ILLabel();
- ILLabel lblEnd = new ILLabel();
-
- void EmitShift(OpCode ilOp)
- {
- context.Emit(OpCodes.Dup);
-
- context.EmitLdc_I4(maxShift);
-
- context.Emit(OpCodes.Bge_S, lblZero);
- context.Emit(ilOp);
- context.Emit(OpCodes.Br_S, lblEnd);
- }
-
- context.Emit(OpCodes.Conv_I1);
- context.Emit(OpCodes.Dup);
-
- context.EmitLdc_I4(0);
-
- context.Emit(OpCodes.Bge_S, lblShl);
- context.Emit(OpCodes.Neg);
-
- EmitShift(signed
- ? OpCodes.Shr
- : OpCodes.Shr_Un);
-
- context.MarkLabel(lblShl);
-
- EmitShift(OpCodes.Shl);
-
- context.MarkLabel(lblZero);
-
- context.Emit(OpCodes.Pop);
- context.Emit(OpCodes.Pop);
-
- context.EmitLdc_I8(0);
-
- context.MarkLabel(lblEnd);
- };
-
- if (signed)
- {
- EmitVectorBinaryOpSx(context, emit);
- }
- else
- {
- EmitVectorBinaryOpZx(context, emit);
- }
- }
-
[Flags]
private enum ShrImmFlags
{