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).
This commit is contained in:
LDj3SNuD 2018-08-04 21:58:54 +02:00 committed by gdkchan
parent fa70629fab
commit 5f34353dce
8 changed files with 2330 additions and 85 deletions

View file

@ -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;