aboutsummaryrefslogtreecommitdiff
path: root/ChocolArm64/Instruction/ASoftFallback.cs
diff options
context:
space:
mode:
authorLDj3SNuD <35856442+LDj3SNuD@users.noreply.github.com>2018-08-04 21:58:54 +0200
committergdkchan <gab.dark.100@gmail.com>2018-08-04 16:58:54 -0300
commit5f34353dce716bca2e3fc1c7e82be6276b95d61a (patch)
treeebd21bf7aa8a67b3b60321789e404c224c66c8f4 /ChocolArm64/Instruction/ASoftFallback.cs
parentfa70629fabbab5074640f55cb70f9d7d82cf91cb (diff)
Add SQADD, UQADD, SQSUB, UQSUB, SUQADD, USQADD, SQABS, SQNEG (Scalar, Vector) instructions; add 24 Tests. Most saturation instructions now on ASoftFallback. (#314)
* Update AOpCodeTable.cs * Update AInstEmitSimdHelper.cs * Update AInstEmitSimdArithmetic.cs * Update Pseudocode.cs * Update Instructions.cs * Update CpuTestSimd.cs * Update CpuTestSimdReg.cs * Update AInstEmitSimdHelper.cs * Update AInstEmitSimdHelper.cs * Update AInstEmitSimdHelper.cs * Update AInstEmitSimdHelper.cs * Update ASoftFallback.cs * Update AInstEmitSimdHelper.cs * Update ASoftFallback.cs * Update AInstEmitSimdHelper.cs * Update CpuTestSimd.cs * Update CpuTestSimdReg.cs * Update ASoftFallback.cs * Update AInstEmitSimdHelper.cs * Opt. (retest).
Diffstat (limited to 'ChocolArm64/Instruction/ASoftFallback.cs')
-rw-r--r--ChocolArm64/Instruction/ASoftFallback.cs268
1 files changed, 268 insertions, 0 deletions
diff --git a/ChocolArm64/Instruction/ASoftFallback.cs b/ChocolArm64/Instruction/ASoftFallback.cs
index ae3994b0..a4d12dd6 100644
--- a/ChocolArm64/Instruction/ASoftFallback.cs
+++ b/ChocolArm64/Instruction/ASoftFallback.cs
@@ -1,3 +1,4 @@
+using ChocolArm64.State;
using ChocolArm64.Translation;
using System;
@@ -10,6 +11,273 @@ namespace ChocolArm64.Instruction
Context.EmitCall(typeof(ASoftFallback), MthdName);
}
+ public static long BinarySignedSatQAdd(long op1, long op2, AThreadState State)
+ {
+ long Add = op1 + op2;
+
+ if ((~(op1 ^ op2) & (op1 ^ Add)) < 0L)
+ {
+ SetFpsrQCFlag(State);
+
+ if (op1 < 0L)
+ {
+ return long.MinValue;
+ }
+ else
+ {
+ return long.MaxValue;
+ }
+ }
+ else
+ {
+ return Add;
+ }
+ }
+
+ public static ulong BinaryUnsignedSatQAdd(ulong op1, ulong op2, AThreadState State)
+ {
+ ulong Add = op1 + op2;
+
+ if ((Add < op1) && (Add < op2))
+ {
+ SetFpsrQCFlag(State);
+
+ return ulong.MaxValue;
+ }
+ else
+ {
+ return Add;
+ }
+ }
+
+ public static long BinarySignedSatQSub(long op1, long op2, AThreadState State)
+ {
+ long Sub = op1 - op2;
+
+ if (((op1 ^ op2) & (op1 ^ Sub)) < 0L)
+ {
+ SetFpsrQCFlag(State);
+
+ if (op1 < 0L)
+ {
+ return long.MinValue;
+ }
+ else
+ {
+ return long.MaxValue;
+ }
+ }
+ else
+ {
+ return Sub;
+ }
+ }
+
+ public static ulong BinaryUnsignedSatQSub(ulong op1, ulong op2, AThreadState State)
+ {
+ ulong Sub = op1 - op2;
+
+ if (op1 < op2)
+ {
+ SetFpsrQCFlag(State);
+
+ return ulong.MinValue;
+ }
+ else
+ {
+ return Sub;
+ }
+ }
+
+ public static long BinarySignedSatQAcc(ulong op1, long op2, AThreadState State)
+ {
+ if (op1 <= (ulong)long.MaxValue)
+ {
+ // op1 from ulong.MinValue to (ulong)long.MaxValue
+ // op2 from long.MinValue to long.MaxValue
+
+ long Add = (long)op1 + op2;
+
+ if ((~op2 & Add) < 0L)
+ {
+ SetFpsrQCFlag(State);
+
+ return long.MaxValue;
+ }
+ else
+ {
+ return Add;
+ }
+ }
+ else if (op2 >= 0L)
+ {
+ // op1 from (ulong)long.MaxValue + 1UL to ulong.MaxValue
+ // op2 from (long)ulong.MinValue to long.MaxValue
+
+ SetFpsrQCFlag(State);
+
+ return long.MaxValue;
+ }
+ else
+ {
+ // op1 from (ulong)long.MaxValue + 1UL to ulong.MaxValue
+ // op2 from long.MinValue to (long)ulong.MinValue - 1L
+
+ ulong Add = op1 + (ulong)op2;
+
+ if (Add > (ulong)long.MaxValue)
+ {
+ SetFpsrQCFlag(State);
+
+ return long.MaxValue;
+ }
+ else
+ {
+ return (long)Add;
+ }
+ }
+ }
+
+ public static ulong BinaryUnsignedSatQAcc(long op1, ulong op2, AThreadState State)
+ {
+ if (op1 >= 0L)
+ {
+ // op1 from (long)ulong.MinValue to long.MaxValue
+ // op2 from ulong.MinValue to ulong.MaxValue
+
+ ulong Add = (ulong)op1 + op2;
+
+ if ((Add < (ulong)op1) && (Add < op2))
+ {
+ SetFpsrQCFlag(State);
+
+ return ulong.MaxValue;
+ }
+ else
+ {
+ return Add;
+ }
+ }
+ else if (op2 > (ulong)long.MaxValue)
+ {
+ // op1 from long.MinValue to (long)ulong.MinValue - 1L
+ // op2 from (ulong)long.MaxValue + 1UL to ulong.MaxValue
+
+ return (ulong)op1 + op2;
+ }
+ else
+ {
+ // op1 from long.MinValue to (long)ulong.MinValue - 1L
+ // op2 from ulong.MinValue to (ulong)long.MaxValue
+
+ long Add = op1 + (long)op2;
+
+ if (Add < (long)ulong.MinValue)
+ {
+ SetFpsrQCFlag(State);
+
+ return ulong.MinValue;
+ }
+ else
+ {
+ return (ulong)Add;
+ }
+ }
+ }
+
+ public static long SignedSrcSignedDstSatQ(long op, int Size, AThreadState State)
+ {
+ int ESize = 8 << Size;
+
+ long TMaxValue = (1L << (ESize - 1)) - 1L;
+ long TMinValue = -(1L << (ESize - 1));
+
+ if (op > TMaxValue)
+ {
+ SetFpsrQCFlag(State);
+
+ return TMaxValue;
+ }
+ else if (op < TMinValue)
+ {
+ SetFpsrQCFlag(State);
+
+ return TMinValue;
+ }
+ else
+ {
+ return op;
+ }
+ }
+
+ public static ulong SignedSrcUnsignedDstSatQ(long op, int Size, AThreadState State)
+ {
+ int ESize = 8 << Size;
+
+ ulong TMaxValue = (1UL << ESize) - 1UL;
+ ulong TMinValue = 0UL;
+
+ if (op > (long)TMaxValue)
+ {
+ SetFpsrQCFlag(State);
+
+ return TMaxValue;
+ }
+ else if (op < (long)TMinValue)
+ {
+ SetFpsrQCFlag(State);
+
+ return TMinValue;
+ }
+ else
+ {
+ return (ulong)op;
+ }
+ }
+
+ public static long UnsignedSrcSignedDstSatQ(ulong op, int Size, AThreadState State)
+ {
+ int ESize = 8 << Size;
+
+ long TMaxValue = (1L << (ESize - 1)) - 1L;
+
+ if (op > (ulong)TMaxValue)
+ {
+ SetFpsrQCFlag(State);
+
+ return TMaxValue;
+ }
+ else
+ {
+ return (long)op;
+ }
+ }
+
+ public static ulong UnsignedSrcUnsignedDstSatQ(ulong op, int Size, AThreadState State)
+ {
+ int ESize = 8 << Size;
+
+ ulong TMaxValue = (1UL << ESize) - 1UL;
+
+ if (op > TMaxValue)
+ {
+ SetFpsrQCFlag(State);
+
+ return TMaxValue;
+ }
+ else
+ {
+ return op;
+ }
+ }
+
+ private static void SetFpsrQCFlag(AThreadState State)
+ {
+ const int QCFlagBit = 27;
+
+ State.Fpsr |= 1 << QCFlagBit;
+ }
+
public static ulong CountLeadingSigns(ulong Value, int Size)
{
Value ^= Value >> 1;