aboutsummaryrefslogtreecommitdiff
path: root/ChocolArm64/Instructions/SoftFallback.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/SoftFallback.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/SoftFallback.cs')
-rw-r--r--ChocolArm64/Instructions/SoftFallback.cs279
1 files changed, 278 insertions, 1 deletions
diff --git a/ChocolArm64/Instructions/SoftFallback.cs b/ChocolArm64/Instructions/SoftFallback.cs
index 8315395a..def95343 100644
--- a/ChocolArm64/Instructions/SoftFallback.cs
+++ b/ChocolArm64/Instructions/SoftFallback.cs
@@ -16,6 +16,283 @@ namespace ChocolArm64.Instructions
context.EmitCall(typeof(SoftFallback), mthdName);
}
+#region "ShlReg"
+ public static long SignedShlReg(long value, long shift, bool round, int size)
+ {
+ int eSize = 8 << size;
+
+ int shiftLsB = (sbyte)shift;
+
+ if (shiftLsB < 0)
+ {
+ return SignedShrReg(value, -shiftLsB, round, eSize);
+ }
+ else if (shiftLsB > 0)
+ {
+ if (shiftLsB >= eSize)
+ {
+ return 0L;
+ }
+
+ return value << shiftLsB;
+ }
+ else /* if (shiftLsB == 0) */
+ {
+ return value;
+ }
+ }
+
+ public static ulong UnsignedShlReg(ulong value, ulong shift, bool round, int size)
+ {
+ int eSize = 8 << size;
+
+ int shiftLsB = (sbyte)shift;
+
+ if (shiftLsB < 0)
+ {
+ return UnsignedShrReg(value, -shiftLsB, round, eSize);
+ }
+ else if (shiftLsB > 0)
+ {
+ if (shiftLsB >= eSize)
+ {
+ return 0UL;
+ }
+
+ return value << shiftLsB;
+ }
+ else /* if (shiftLsB == 0) */
+ {
+ return value;
+ }
+ }
+
+ public static long SignedShlRegSatQ(long value, long shift, bool round, int size, CpuThreadState state)
+ {
+ int eSize = 8 << size;
+
+ int shiftLsB = (sbyte)shift;
+
+ if (shiftLsB < 0)
+ {
+ return SignedShrReg(value, -shiftLsB, round, eSize);
+ }
+ else if (shiftLsB > 0)
+ {
+ if (shiftLsB >= eSize)
+ {
+ return SignedSignSatQ(value, eSize, state);
+ }
+
+ if (eSize == 64)
+ {
+ long shl = value << shiftLsB;
+ long shr = shl >> shiftLsB;
+
+ if (shr != value)
+ {
+ return SignedSignSatQ(value, eSize, state);
+ }
+ else /* if (shr == value) */
+ {
+ return shl;
+ }
+ }
+ else /* if (eSize != 64) */
+ {
+ return SignedSrcSignedDstSatQ(value << shiftLsB, size, state);
+ }
+ }
+ else /* if (shiftLsB == 0) */
+ {
+ return value;
+ }
+ }
+
+ public static ulong UnsignedShlRegSatQ(ulong value, ulong shift, bool round, int size, CpuThreadState state)
+ {
+ int eSize = 8 << size;
+
+ int shiftLsB = (sbyte)shift;
+
+ if (shiftLsB < 0)
+ {
+ return UnsignedShrReg(value, -shiftLsB, round, eSize);
+ }
+ else if (shiftLsB > 0)
+ {
+ if (shiftLsB >= eSize)
+ {
+ return UnsignedSignSatQ(value, eSize, state);
+ }
+
+ if (eSize == 64)
+ {
+ ulong shl = value << shiftLsB;
+ ulong shr = shl >> shiftLsB;
+
+ if (shr != value)
+ {
+ return UnsignedSignSatQ(value, eSize, state);
+ }
+ else /* if (shr == value) */
+ {
+ return shl;
+ }
+ }
+ else /* if (eSize != 64) */
+ {
+ return UnsignedSrcUnsignedDstSatQ(value << shiftLsB, size, state);
+ }
+ }
+ else /* if (shiftLsB == 0) */
+ {
+ return value;
+ }
+ }
+
+ private static long SignedShrReg(long value, int shift, bool round, int eSize) // shift := [1, 128]; eSize := {8, 16, 32, 64}.
+ {
+ if (round)
+ {
+ if (shift >= eSize)
+ {
+ return 0L;
+ }
+
+ long roundConst = 1L << (shift - 1);
+
+ long add = value + roundConst;
+
+ if (eSize == 64)
+ {
+ if ((~value & (value ^ add)) < 0L)
+ {
+ return (long)((ulong)add >> shift);
+ }
+ else
+ {
+ return add >> shift;
+ }
+ }
+ else /* if (eSize != 64) */
+ {
+ return add >> shift;
+ }
+ }
+ else /* if (!round) */
+ {
+ if (shift >= eSize)
+ {
+ if (value < 0L)
+ {
+ return -1L;
+ }
+ else /* if (value >= 0L) */
+ {
+ return 0L;
+ }
+ }
+
+ return value >> shift;
+ }
+ }
+
+ private static ulong UnsignedShrReg(ulong value, int shift, bool round, int eSize) // shift := [1, 128]; eSize := {8, 16, 32, 64}.
+ {
+ if (round)
+ {
+ if (shift > 64)
+ {
+ return 0UL;
+ }
+
+ ulong roundConst = 1UL << (shift - 1);
+
+ ulong add = value + roundConst;
+
+ if (eSize == 64)
+ {
+ if ((add < value) && (add < roundConst))
+ {
+ if (shift == 64)
+ {
+ return 1UL;
+ }
+
+ return (add >> shift) | (0x8000000000000000UL >> (shift - 1));
+ }
+ else
+ {
+ if (shift == 64)
+ {
+ return 0UL;
+ }
+
+ return add >> shift;
+ }
+ }
+ else /* if (eSize != 64) */
+ {
+ if (shift == 64)
+ {
+ return 0UL;
+ }
+
+ return add >> shift;
+ }
+ }
+ else /* if (!round) */
+ {
+ if (shift >= eSize)
+ {
+ return 0UL;
+ }
+
+ return value >> shift;
+ }
+ }
+
+ private static long SignedSignSatQ(long op, int eSize, CpuThreadState state) // eSize := {8, 16, 32, 64}.
+ {
+ long tMaxValue = (1L << (eSize - 1)) - 1L;
+ long tMinValue = -(1L << (eSize - 1));
+
+ if (op > 0L)
+ {
+ state.SetFpsrFlag(Fpsr.Qc);
+
+ return tMaxValue;
+ }
+ else if (op < 0L)
+ {
+ state.SetFpsrFlag(Fpsr.Qc);
+
+ return tMinValue;
+ }
+ else
+ {
+ return 0L;
+ }
+ }
+
+ private static ulong UnsignedSignSatQ(ulong op, int eSize, CpuThreadState state) // eSize := {8, 16, 32, 64}.
+ {
+ ulong tMaxValue = ulong.MaxValue >> (64 - eSize);
+
+ if (op > 0UL)
+ {
+ state.SetFpsrFlag(Fpsr.Qc);
+
+ return tMaxValue;
+ }
+ else
+ {
+ return 0UL;
+ }
+ }
+#endregion
+
#region "ShrImm64"
public static long SignedShrImm64(long value, long roundConst, int shift)
{
@@ -31,7 +308,7 @@ namespace ChocolArm64.Instructions
{
return -1L;
}
- else
+ else /* if (value >= 0L) */
{
return 0L;
}