diff options
| author | LDj3SNuD <35856442+LDj3SNuD@users.noreply.github.com> | 2018-08-04 21:58:54 +0200 |
|---|---|---|
| committer | gdkchan <gab.dark.100@gmail.com> | 2018-08-04 16:58:54 -0300 |
| commit | 5f34353dce716bca2e3fc1c7e82be6276b95d61a (patch) | |
| tree | ebd21bf7aa8a67b3b60321789e404c224c66c8f4 /ChocolArm64/Instruction/ASoftFallback.cs | |
| parent | fa70629fabbab5074640f55cb70f9d7d82cf91cb (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.cs | 268 |
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; |
